From 1a2f9ab0591ca3ac1027d27add42b0e7456ee5f9 Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Sat, 16 Jan 2016 23:28:07 +0100 Subject: [PATCH] All the EOLs are now LF. Fuck you too 0D :^) --- code/ATMOSPHERICS/atmospherics.dm | 606 +- .../binary_devices/binary_atmos_base.dm | 306 +- .../components/binary_devices/circulator.dm | 324 +- .../components/binary_devices/dp_vent_pump.dm | 444 +- .../components/binary_devices/passive_gate.dm | 310 +- .../components/binary_devices/pump.dm | 348 +- .../components/binary_devices/volume_pump.dm | 318 +- .../components/trinary_devices/filter.dm | 444 +- .../components/trinary_devices/mixer.dm | 308 +- .../trinary_devices/trinary_base.dm | 410 +- .../components/unary/cold_sink.dm | 64 +- .../components/unary/generator_input.dm | 40 +- .../components/unary/heat_exchanger.dm | 126 +- .../components/unary/heat_source.dm | 68 +- .../components/unary/outlet_injector.dm | 358 +- .../components/unary/oxygen_generator.dm | 96 +- .../components/unary/unary_base.dm | 190 +- .../components/unary/vent_pump.dm | 744 +- .../components/unary/vent_scrubber.dm | 768 +- code/ATMOSPHERICS/datum_pipe_network.dm | 468 +- code/ATMOSPHERICS/datum_pipeline.dm | 462 +- code/ATMOSPHERICS/he_pipes.dm | 418 +- code/ATMOSPHERICS/pipes.dm | 2518 +++--- .../Cael_Aislinn/ShieldGen/energy_field.dm | 100 +- code/WorkInProgress/Cael_Aislinn/sculpture.dm | 530 +- code/WorkInProgress/explosion_particles.dm | 210 +- code/__HELPERS/files.dm | 212 +- code/__HELPERS/global_lists.dm | 130 +- code/__HELPERS/icons.dm | 272 +- code/__HELPERS/lists.dm | 678 +- code/__HELPERS/logging.dm | 266 +- code/__HELPERS/maths.dm | 480 +- code/__HELPERS/mobs.dm | 336 +- code/__HELPERS/names.dm | 650 +- code/__HELPERS/sanitize_values.dm | 92 +- code/__HELPERS/text.dm | 954 +- code/__HELPERS/time.dm | 144 +- code/controllers/configuration.dm | 1406 +-- code/controllers/failsafe.dm | 118 +- code/controllers/master_controller.dm | 952 +- code/controllers/shuttle_controller.dm | 714 +- code/controllers/verbs.dm | 184 +- code/datums/ai_laws.dm | 748 +- code/datums/circuits.dm | 242 +- code/datums/computerfiles.dm | 12 +- code/datums/datacore.dm | 554 +- code/datums/datumvars.dm | 1878 ++-- code/datums/disease.dm | 418 +- code/datums/diseases/advance/advance.dm | 846 +- code/datums/diseases/advance/presets.dm | 84 +- .../diseases/advance/symptoms/confusion.dm | 74 +- .../datums/diseases/advance/symptoms/cough.dm | 74 +- .../advance/symptoms/damage_converter.dm | 86 +- .../datums/diseases/advance/symptoms/dizzy.dm | 68 +- .../datums/diseases/advance/symptoms/fever.dm | 68 +- .../diseases/advance/symptoms/hallucigen.dm | 72 +- .../diseases/advance/symptoms/headache.dm | 62 +- code/datums/diseases/advance/symptoms/heal.dm | 80 +- .../diseases/advance/symptoms/itching.dm | 62 +- .../diseases/advance/symptoms/shivering.dm | 68 +- .../diseases/advance/symptoms/sneeze.dm | 74 +- .../diseases/advance/symptoms/symptoms.dm | 76 +- .../diseases/advance/symptoms/voice_change.dm | 94 +- .../datums/diseases/advance/symptoms/vomit.dm | 186 +- .../diseases/advance/symptoms/weight.dm | 230 +- code/datums/diseases/alien_embryo.dm | 304 +- code/datums/diseases/appendicitis.dm | 106 +- code/datums/diseases/beesease.dm | 54 +- code/datums/diseases/brainrot.dm | 134 +- code/datums/diseases/cold.dm | 110 +- code/datums/diseases/cold9.dm | 68 +- code/datums/diseases/dna_spread.dm | 128 +- code/datums/diseases/fake_gbs.dm | 62 +- code/datums/diseases/flu.dm | 116 +- code/datums/diseases/fluspanish.dm | 68 +- code/datums/diseases/gbs.dm | 74 +- code/datums/diseases/jungle_fever.dm | 24 +- code/datums/diseases/magnitis.dm | 174 +- code/datums/diseases/pierrot_throat.dm | 48 +- code/datums/diseases/plasmatoid.dm | 8 +- code/datums/diseases/retrovirus.dm | 182 +- .../datums/diseases/robotic_transformation.dm | 104 +- code/datums/diseases/wizarditis.dm | 244 +- code/datums/diseases/xeno_transformation.dm | 98 +- .../helper_datums/construction_datum.dm | 828 +- code/datums/helper_datums/events.dm | 128 +- code/datums/helper_datums/global_iterator.dm | 306 +- code/datums/helper_datums/teleport.dm | 422 +- code/datums/helper_datums/topic_input.dm | 118 +- code/datums/mind.dm | 2872 +++--- code/datums/mixed.dm | 62 +- code/datums/modules.dm | 122 +- code/datums/recipe.dm | 268 +- code/datums/sun.dm | 184 +- code/datums/supplypacks.dm | 3092 +++---- code/datums/wires/jukebox.dm | 186 +- code/datums/wires/transmitter.dm | 88 +- code/defines/obj.dm | 708 +- code/defines/obj/hydro.dm | 3178 +++---- code/defines/procs/AStar.dm | 670 +- code/defines/procs/captain_announce.dm | 4 +- code/defines/procs/command_alert.dm | 28 +- code/defines/procs/statistics.dm | 318 +- code/game/area/Space Station 13 areas.dm | 4486 +++++----- code/game/area/ai_monitored.dm | 52 +- code/game/area/areas.dm | 1358 +-- code/game/asteroid.dm | 172 +- code/game/atoms.dm | 1520 ++-- code/game/atoms_movable.dm | 1008 +-- code/game/communications.dm | 764 +- code/game/gamemodes/blob/blob.dm | 362 +- code/game/gamemodes/blob/blob_finish.dm | 162 +- code/game/gamemodes/blob/blob_report.dm | 238 +- code/game/gamemodes/blob/blobs/core.dm | 208 +- code/game/gamemodes/blob/blobs/factory.dm | 162 +- code/game/gamemodes/blob/blobs/node.dm | 76 +- code/game/gamemodes/blob/blobs/shield.dm | 58 +- code/game/gamemodes/blob/theblob.dm | 442 +- code/game/gamemodes/changeling/changeling.dm | 568 +- .../gamemodes/changeling/changeling_powers.dm | 1928 ++-- code/game/gamemodes/cult/cult.dm | 1308 +-- code/game/gamemodes/cult/cult_items.dm | 226 +- code/game/gamemodes/cult/ritual.dm | 1328 +-- code/game/gamemodes/cult/talisman.dm | 444 +- code/game/gamemodes/events/biomass.dm | 412 +- .../gamemodes/events/holidays/Christmas.dm | 102 +- .../gamemodes/events/holidays/Holidays.dm | 452 +- code/game/gamemodes/events/holidays/Other.dm | 18 +- code/game/gamemodes/events/spacevines.dm | 44 +- code/game/gamemodes/events/wormholes.dm | 118 +- code/game/gamemodes/extended/extended.dm | 42 +- code/game/gamemodes/game_mode.dm | 1016 +-- code/game/gamemodes/gameticker.dm | 1394 +-- code/game/gamemodes/intercept_report.dm | 518 +- .../gamemodes/malfunction/Malf_Modules.dm | 728 +- .../game/gamemodes/malfunction/malfunction.dm | 570 +- code/game/gamemodes/meme/meme.dm | 344 +- code/game/gamemodes/meteor/meteor.dm | 226 +- code/game/gamemodes/meteor/meteors.dm | 614 +- code/game/gamemodes/nuclear/nuclear.dm | 856 +- code/game/gamemodes/nuclear/nuclearbomb.dm | 732 +- code/game/gamemodes/nuclear/pinpointer.dm | 602 +- code/game/gamemodes/objective.dm | 1440 +-- code/game/gamemodes/revolution/revolution.dm | 1006 +-- .../gamemodes/revolution/rp_revolution.dm | 470 +- code/game/gamemodes/sandbox/h_sandbox.dm | 388 +- code/game/gamemodes/sandbox/sandbox.dm | 48 +- code/game/gamemodes/setupgame.dm | 348 +- code/game/gamemodes/traitor/traitor.dm | 798 +- code/game/gamemodes/wizard/soulstone.dm | 480 +- code/game/gamemodes/wizard/spellbook.dm | 1164 +-- code/game/gamemodes/wizard/wizard.dm | 778 +- code/game/jobs/access.dm | 984 +-- code/game/jobs/job/assistant.dm | 50 +- code/game/jobs/job/civilian.dm | 840 +- code/game/jobs/job/civilian_chaplain.dm | 888 +- code/game/jobs/job/engineering.dm | 336 +- code/game/jobs/job/job.dm | 150 +- code/game/jobs/job/medical.dm | 498 +- code/game/jobs/job/science.dm | 260 +- code/game/jobs/job/security.dm | 418 +- code/game/jobs/job/silicon.dm | 92 +- code/game/jobs/job_controller.dm | 1118 +-- code/game/jobs/jobs.dm | 292 +- code/game/jobs/whitelist.dm | 156 +- code/game/machinery/Freezer.dm | 640 +- code/game/machinery/OpTable.dm | 368 +- code/game/machinery/Sleeper.dm | 1112 +-- code/game/machinery/airlock_control.dm | 774 +- code/game/machinery/alarm.dm | 2444 ++--- code/game/machinery/atmoalter/canister.dm | 1048 +-- code/game/machinery/atmoalter/meter.dm | 346 +- .../atmoalter/portable_atmospherics.dm | 260 +- code/game/machinery/atmoalter/pump.dm | 328 +- code/game/machinery/atmoalter/scrubber.dm | 422 +- code/game/machinery/atmoalter/zvent.dm | 58 +- code/game/machinery/autolathe.dm | 374 +- code/game/machinery/bots/bots.dm | 386 +- code/game/machinery/bots/cleanbot.dm | 714 +- code/game/machinery/bots/ed209bot.dm | 2212 ++--- code/game/machinery/bots/floorbot.dm | 1526 ++-- code/game/machinery/bots/medbot.dm | 1246 +-- code/game/machinery/bots/mulebot.dm | 1798 ++-- code/game/machinery/bots/secbot.dm | 1736 ++-- code/game/machinery/buttons.dm | 140 +- code/game/machinery/camera/camera.dm | 902 +- code/game/machinery/camera/camera_assembly.dm | 336 +- code/game/machinery/camera/motion.dm | 124 +- code/game/machinery/camera/presets.dm | 182 +- code/game/machinery/camera/tracking.dm | 428 +- code/game/machinery/cell_charger.dm | 278 +- code/game/machinery/computer/Operating.dm | 222 +- code/game/machinery/computer/aifixer.dm | 246 +- code/game/machinery/computer/arcade.dm | 622 +- .../game/machinery/computer/buildandrepair.dm | 878 +- code/game/machinery/computer/camera.dm | 300 +- .../game/machinery/computer/communications.dm | 1224 +-- code/game/machinery/computer/hologram.dm | 220 +- code/game/machinery/computer/medical.dm | 1056 +-- code/game/machinery/computer/prisonshuttle.dm | 412 +- code/game/machinery/computer/robot.dm | 466 +- code/game/machinery/computer/security.dm | 1224 +-- code/game/machinery/computer/shuttle.dm | 136 +- .../machinery/computer/specops_shuttle.dm | 1138 +-- code/game/machinery/computer/station_alert.dm | 310 +- .../computer/syndicate_specops_shuttle.dm | 492 +- code/game/machinery/constructable_frame.dm | 2402 ++--- code/game/machinery/cryo.dm | 1024 +-- code/game/machinery/deployable.dm | 316 +- code/game/machinery/door_control.dm | 410 +- code/game/machinery/doors/airlock.dm | 2378 ++--- .../machinery/doors/airlock_electronics.dm | 280 +- code/game/machinery/doors/alarmlock.dm | 78 +- code/game/machinery/doors/brigdoors.dm | 618 +- .../machinery/doors/checkForMultipleDoors.dm | 30 +- code/game/machinery/doors/door.dm | 854 +- code/game/machinery/doors/firedoor.dm | 972 +- code/game/machinery/doors/poddoor.dm | 856 +- code/game/machinery/doors/shutters.dm | 140 +- code/game/machinery/doors/windowdoor.dm | 692 +- code/game/machinery/doppler_array.dm | 298 +- .../embedded_controller_base.dm | 598 +- code/game/machinery/flasher.dm | 344 +- code/game/machinery/hologram.dm | 420 +- code/game/machinery/hydroponics.dm | 1950 ++-- code/game/machinery/igniter.dm | 404 +- code/game/machinery/iv_drip.dm | 358 +- code/game/machinery/kitchen/gibber.dm | 730 +- code/game/machinery/kitchen/juicer.dm | 348 +- code/game/machinery/kitchen/microwave.dm | 892 +- code/game/machinery/kitchen/processor.dm | 526 +- code/game/machinery/kitchen/smartfridge.dm | 688 +- code/game/machinery/lightswitch.dm | 226 +- code/game/machinery/machinery.dm | 1412 +-- code/game/machinery/magnet.dm | 810 +- code/game/machinery/mass_driver.dm | 454 +- code/game/machinery/navbeacon.dm | 482 +- code/game/machinery/overview.dm | 712 +- code/game/machinery/portable_turret.dm | 2238 ++--- code/game/machinery/rechargestation.dm | 786 +- code/game/machinery/requests_console.dm | 902 +- code/game/machinery/robot_fabricator.dm | 296 +- code/game/machinery/shieldgen.dm | 1186 +-- code/game/machinery/status_display.dm | 828 +- code/game/machinery/suit_storage_unit.dm | 1314 +-- code/game/machinery/syndicatebeacon.dm | 532 +- code/game/machinery/telecomms/presets.dm | 440 +- .../machinery/telecomms/telecomunications.dm | 1346 +-- code/game/machinery/transformer.dm | 330 +- code/game/machinery/turrets.dm | 1332 +-- code/game/machinery/vending.dm | 4494 +++++----- code/game/mecha/combat/combat.dm | 546 +- code/game/mecha/combat/durand.dm | 190 +- code/game/mecha/combat/gygax.dm | 224 +- code/game/mecha/combat/honker.dm | 328 +- code/game/mecha/combat/marauder.dm | 420 +- code/game/mecha/combat/phazon.dm | 138 +- code/game/mecha/equipment/mecha_equipment.dm | 286 +- .../mecha/equipment/tools/medical_tools.dm | 1346 +-- code/game/mecha/equipment/tools/tools.dm | 2554 +++--- .../mecha/equipment/tools/unused_tools.dm | 108 +- code/game/mecha/equipment/weapons/weapons.dm | 894 +- code/game/mecha/mech_bay.dm | 522 +- code/game/mecha/mech_fabricator.dm | 174 +- code/game/mecha/mecha.dm | 3946 ++++----- code/game/mecha/mecha_construction_paths.dm | 1368 +-- code/game/mecha/mecha_control_console.dm | 344 +- code/game/mecha/mecha_parts.dm | 852 +- code/game/mecha/mecha_wreckage.dm | 436 +- code/game/mecha/medical/medical.dm | 42 +- code/game/mecha/medical/odysseus.dm | 206 +- code/game/mecha/working/ripley.dm | 248 +- code/game/mecha/working/working.dm | 62 +- code/game/objects/effects/aliens.dm | 1004 +-- code/game/objects/effects/biomass_rift.dm | 250 +- code/game/objects/effects/bump_teleporter.dm | 68 +- .../effects/decals/Cleanable/aliens.dm | 78 +- .../objects/effects/decals/Cleanable/misc.dm | 404 +- .../effects/decals/Cleanable/robots.dm | 100 +- code/game/objects/effects/decals/crayon.dm | 76 +- code/game/objects/effects/decals/misc.dm | 94 +- code/game/objects/effects/decals/remains.dm | 50 +- code/game/objects/effects/effect_system.dm | 2076 ++--- code/game/objects/effects/gibs.dm | 160 +- code/game/objects/effects/glowshroom.dm | 314 +- code/game/objects/effects/landmarks.dm | 200 +- code/game/objects/effects/manifest.dm | 44 +- code/game/objects/effects/mines.dm | 234 +- code/game/objects/effects/overlays.dm | 128 +- code/game/objects/effects/portals.dm | 334 +- .../objects/effects/spawners/bombspawner.dm | 348 +- .../objects/effects/spawners/gibspawner.dm | 74 +- .../objects/effects/spawners/vaultspawner.dm | 52 +- code/game/objects/empulse.dm | 94 +- code/game/objects/explosion.dm | 312 +- code/game/objects/explosion_recursive.dm | 314 +- code/game/objects/items/bodybag.dm | 260 +- code/game/objects/items/candle.dm | 130 +- code/game/objects/items/devices/PDA/PDA.dm | 4806 +++++----- code/game/objects/items/devices/PDA/cart.dm | 1616 ++-- code/game/objects/items/devices/PDA/radio.dm | 530 +- code/game/objects/items/devices/aicard.dm | 260 +- .../objects/items/devices/chameleonproj.dm | 362 +- code/game/objects/items/devices/debugger.dm | 80 +- code/game/objects/items/devices/flash.dm | 436 +- code/game/objects/items/devices/flashlight.dm | 480 +- .../objects/items/devices/lightreplacer.dm | 1186 +-- code/game/objects/items/devices/multitool.dm | 274 +- code/game/objects/items/devices/paicard.dm | 328 +- code/game/objects/items/devices/powersink.dm | 248 +- .../items/devices/radio/electropack.dm | 324 +- .../objects/items/devices/radio/headset.dm | 724 +- .../objects/items/devices/radio/intercom.dm | 308 +- .../game/objects/items/devices/radio/radio.dm | 1096 +-- code/game/objects/items/devices/scanners.dm | 950 +- .../objects/items/devices/taperecorder.dm | 488 +- .../objects/items/devices/transfer_valve.dm | 452 +- code/game/objects/items/devices/violin.dm | 792 +- code/game/objects/items/latexballoon.dm | 94 +- .../items/mountable_frames/newscaster.dm | 24 +- .../items/mountable_frames/sound_system.dm | 24 +- code/game/objects/items/robot/robot_items.dm | 74 +- code/game/objects/items/shooting_range.dm | 354 +- code/game/objects/items/stacks/medical.dm | 506 +- code/game/objects/items/stacks/packagewrap.dm | 366 +- code/game/objects/items/stacks/rods.dm | 230 +- .../game/objects/items/stacks/sheets/glass.dm | 608 +- .../objects/items/stacks/sheets/leather.dm | 288 +- .../game/objects/items/stacks/sheets/light.dm | 68 +- .../objects/items/stacks/sheets/mineral.dm | 942 +- .../objects/items/stacks/sheets/sheets.dm | 64 +- code/game/objects/items/stacks/tiles/light.dm | 182 +- .../objects/items/stacks/tiles/plasteel.dm | 200 +- .../objects/items/stacks/tiles/tile_types.dm | 258 +- code/game/objects/items/trash.dm | 254 +- code/game/objects/items/weapons/RCL.dm | 226 +- code/game/objects/items/weapons/cards_ids.dm | 1152 +-- .../objects/items/weapons/cigs_lighters.dm | 1448 +-- code/game/objects/items/weapons/cosmetics.dm | 166 +- code/game/objects/items/weapons/dice.dm | 582 +- .../objects/items/weapons/dna_injector.dm | 2468 +++--- code/game/objects/items/weapons/explosives.dm | 270 +- .../objects/items/weapons/extinguisher.dm | 688 +- .../objects/items/weapons/flamethrower.dm | 426 +- .../items/weapons/grenades/chem_grenade.dm | 844 +- .../items/weapons/grenades/emgrenade.dm | 24 +- .../items/weapons/grenades/flashbang.dm | 348 +- .../objects/items/weapons/grenades/grenade.dm | 226 +- .../items/weapons/grenades/smokebomb.dm | 70 +- .../items/weapons/grenades/spawnergrenade.dm | 198 +- code/game/objects/items/weapons/handcuffs.dm | 348 +- .../game/objects/items/weapons/hydroponics.dm | 450 +- .../objects/items/weapons/implants/implant.dm | 1026 +-- .../items/weapons/implants/implantcase.dm | 256 +- .../items/weapons/implants/implantchair.dm | 350 +- .../items/weapons/implants/implanter.dm | 290 +- .../items/weapons/implants/implantfreedom.dm | 138 +- .../items/weapons/implants/implantpad.dm | 194 +- .../items/weapons/implants/implantuplink.dm | 42 +- code/game/objects/items/weapons/kitchen.dm | 1102 +-- code/game/objects/items/weapons/manuals.dm | 1210 +-- .../objects/items/weapons/melee/energy.dm | 260 +- code/game/objects/items/weapons/melee/misc.dm | 32 +- code/game/objects/items/weapons/mop.dm | 98 +- code/game/objects/items/weapons/paint.dm | 478 +- code/game/objects/items/weapons/paiwire.dm | 20 +- .../game/objects/items/weapons/power_cells.dm | 254 +- code/game/objects/items/weapons/scrolls.dm | 194 +- code/game/objects/items/weapons/shields.dm | 332 +- .../objects/items/weapons/storage/backpack.dm | 448 +- .../objects/items/weapons/storage/bags.dm | 692 +- .../objects/items/weapons/storage/bible.dm | 320 +- .../objects/items/weapons/storage/boxes.dm | 1072 +-- .../items/weapons/storage/briefcase.dm | 270 +- .../objects/items/weapons/storage/fancy.dm | 1026 +-- .../objects/items/weapons/storage/firstaid.dm | 522 +- .../objects/items/weapons/storage/lockbox.dm | 388 +- .../objects/items/weapons/storage/secure.dm | 472 +- .../objects/items/weapons/storage/storage.dm | 1242 +-- .../objects/items/weapons/storage/toolbox.dm | 182 +- .../objects/items/weapons/swords_axes_etc.dm | 422 +- .../objects/items/weapons/tanks/jetpack.dm | 204 +- .../objects/items/weapons/tanks/tank_types.dm | 280 +- .../game/objects/items/weapons/tanks/tanks.dm | 564 +- .../objects/items/weapons/teleportation.dm | 430 +- code/game/objects/items/weapons/tools.dm | 1416 +-- code/game/objects/items/weapons/twohanded.dm | 390 +- code/game/objects/items/weapons/weaponry.dm | 308 +- code/game/objects/objs.dm | 644 +- code/game/objects/structures.dm | 44 +- code/game/objects/structures/bedsheet_bin.dm | 438 +- .../structures/crates_lockers/closets.dm | 902 +- .../crates_lockers/closets/coffin.dm | 22 +- .../crates_lockers/closets/crittercrate.dm | 14 +- .../crates_lockers/closets/gimmick.dm | 284 +- .../crates_lockers/closets/job_closets.dm | 238 +- .../crates_lockers/closets/l3closet.dm | 152 +- .../crates_lockers/closets/malfunction.dm | 32 +- .../closets/secure/engineering.dm | 438 +- .../crates_lockers/closets/secure/freezer.dm | 222 +- .../crates_lockers/closets/secure/medical.dm | 460 +- .../crates_lockers/closets/secure/personal.dm | 162 +- .../closets/secure/scientist.dm | 98 +- .../closets/secure/secure_closets.dm | 348 +- .../crates_lockers/closets/secure/security.dm | 696 +- .../crates_lockers/closets/syndicate.dm | 312 +- .../crates_lockers/closets/utility_closets.dm | 474 +- .../crates_lockers/closets/wardrobe.dm | 818 +- .../structures/crates_lockers/crates.dm | 1244 +-- .../structures/crates_lockers/largecrate.dm | 148 +- code/game/objects/structures/displaycase.dm | 550 +- code/game/objects/structures/door_assembly.dm | 674 +- code/game/objects/structures/false_walls.dm | 724 +- code/game/objects/structures/flora.dm | 720 +- code/game/objects/structures/girders.dm | 886 +- code/game/objects/structures/grille.dm | 502 +- code/game/objects/structures/janicart.dm | 248 +- code/game/objects/structures/kitchen_spike.dm | 180 +- code/game/objects/structures/ladders.dm | 144 +- code/game/objects/structures/lamarr_cage.dm | 188 +- code/game/objects/structures/lattice.dm | 136 +- code/game/objects/structures/mirror.dm | 268 +- code/game/objects/structures/mop_bucket.dm | 110 +- code/game/objects/structures/morgue.dm | 854 +- code/game/objects/structures/musician.dm | 888 +- code/game/objects/structures/noticeboard.dm | 160 +- code/game/objects/structures/safe.dm | 378 +- code/game/objects/structures/signs.dm | 452 +- .../stool_bed_chair_nest/alien_nests.dm | 156 +- .../structures/stool_bed_chair_nest/bed.dm | 332 +- .../structures/stool_bed_chair_nest/chairs.dm | 408 +- .../structures/stool_bed_chair_nest/stools.dm | 104 +- code/game/objects/structures/support_rail.dm | 106 +- code/game/objects/structures/tables_racks.dm | 1362 +-- .../game/objects/structures/tank_dispenser.dm | 244 +- code/game/objects/structures/target_stake.dm | 102 +- code/game/objects/structures/window.dm | 1066 +-- code/game/shuttle_engines.dm | 128 +- code/game/skincmd.dm | 24 +- code/game/smoothwall.dm | 248 +- code/game/sound.dm | 314 +- code/game/supplyshuttle.dm | 1682 ++-- code/game/turfs/simulated.dm | 284 +- code/game/turfs/simulated/floor.dm | 1300 +-- code/game/turfs/simulated/floor_types.dm | 708 +- code/game/turfs/simulated/walls.dm | 732 +- code/game/turfs/simulated/walls_mineral.dm | 334 +- code/game/turfs/simulated/walls_misc.dm | 64 +- code/game/turfs/simulated/walls_reinforced.dm | 872 +- code/game/turfs/space/space.dm | 346 +- code/game/turfs/space/transit.dm | 108 +- code/game/turfs/unsimulated.dm | 8 +- code/game/turfs/unsimulated/beach.dm | 44 +- code/game/turfs/unsimulated/floor.dm | 440 +- code/game/turfs/unsimulated/walls.dm | 124 +- code/game/verbs/ooc.dm | 312 +- code/game/verbs/suicide.dm | 590 +- code/game/verbs/who.dm | 224 +- code/global.dm | 790 +- code/hub.dm | 24 +- code/js/byjax.dm | 100 +- code/js/menus.dm | 72 +- code/modules/admin/DB ban/functions.dm | 910 +- code/modules/admin/NewBan.dm | 434 +- code/modules/admin/ToRban.dm | 164 +- code/modules/admin/admin.dm | 2842 +++--- code/modules/admin/admin_ranks.dm | 316 +- code/modules/admin/admin_verbs.dm | 2118 ++--- code/modules/admin/banjob.dm | 230 +- code/modules/admin/create_mob.dm | 18 +- code/modules/admin/create_object.dm | 56 +- code/modules/admin/create_turf.dm | 18 +- code/modules/admin/holder2.dm | 238 +- code/modules/admin/newbanjob.dm | 514 +- .../admin/permissionverbs/permissionedit.dm | 300 +- code/modules/admin/topic.dm | 7808 ++++++++-------- code/modules/admin/verbs/BrokenInhands.dm | 74 +- code/modules/admin/verbs/adminhelp.dm | 230 +- code/modules/admin/verbs/adminjump.dm | 318 +- code/modules/admin/verbs/adminsay.dm | 92 +- code/modules/admin/verbs/atmosdebug.dm | 76 +- code/modules/admin/verbs/deadsay.dm | 70 +- code/modules/admin/verbs/diagnostics.dm | 470 +- code/modules/admin/verbs/mapping.dm | 800 +- code/modules/admin/verbs/massmodvar.dm | 798 +- code/modules/admin/verbs/modifyvariables.dm | 1070 +-- code/modules/admin/verbs/one_click_antag.dm | 942 +- code/modules/admin/verbs/onlyone.dm | 98 +- code/modules/admin/verbs/playsound.dm | 146 +- code/modules/admin/verbs/pray.dm | 80 +- code/modules/admin/verbs/randomverbs.dm | 1822 ++-- code/modules/admin/verbs/striketeam.dm | 340 +- .../admin/verbs/striketeam_syndicate.dm | 352 +- code/modules/admin/verbs/ticklag.dm | 34 +- code/modules/admin/verbs/tripAI.dm | 36 +- code/modules/assembly/assembly.dm | 558 +- code/modules/assembly/bomb.dm | 322 +- code/modules/assembly/helpers.dm | 86 +- code/modules/assembly/holder.dm | 604 +- code/modules/assembly/igniter.dm | 76 +- code/modules/assembly/infrared.dm | 418 +- code/modules/assembly/mousetrap.dm | 254 +- code/modules/assembly/proximity.dm | 362 +- code/modules/assembly/shock_kit.dm | 94 +- code/modules/assembly/signaler.dm | 556 +- code/modules/assembly/timer.dm | 238 +- .../awaymissions/bluespaceartillery.dm | 132 +- code/modules/awaymissions/corpse.dm | 548 +- code/modules/awaymissions/exile.dm | 100 +- code/modules/awaymissions/gateway.dm | 460 +- code/modules/awaymissions/loot.dm | 48 +- code/modules/awaymissions/pamphlet.dm | 74 +- code/modules/awaymissions/trigger.dm | 86 +- code/modules/client/preferences.dm | 2912 +++--- code/modules/client/preferences_savefile.dm | 1494 ++-- code/modules/client/preferences_toggles.dm | 454 +- code/modules/clothing/glasses/glasses.dm | 614 +- code/modules/clothing/glasses/hud.dm | 100 +- code/modules/clothing/gloves/color.dm | 402 +- code/modules/clothing/gloves/miscellaneous.dm | 276 +- code/modules/clothing/gloves/stungloves.dm | 122 +- code/modules/clothing/head/collectable.dm | 238 +- code/modules/clothing/head/helmet.dm | 454 +- code/modules/clothing/head/jobs.dm | 170 +- code/modules/clothing/head/misc.dm | 792 +- code/modules/clothing/head/misc_special.dm | 414 +- code/modules/clothing/head/soft_caps.dm | 196 +- code/modules/clothing/masks/boxing.dm | 112 +- code/modules/clothing/masks/breath.dm | 58 +- code/modules/clothing/masks/chemmask.dm | 770 +- code/modules/clothing/masks/gasmask.dm | 334 +- code/modules/clothing/masks/miscellaneous.dm | 234 +- code/modules/clothing/shoes/colour.dm | 226 +- code/modules/clothing/shoes/magboots.dm | 128 +- code/modules/clothing/shoes/miscellaneous.dm | 676 +- code/modules/clothing/spacesuits/captain.dm | 64 +- .../clothing/spacesuits/miscellaneous.dm | 110 +- code/modules/clothing/spacesuits/ninja.dm | 18 +- code/modules/clothing/spacesuits/rig.dm | 902 +- code/modules/clothing/spacesuits/syndi.dm | 306 +- code/modules/clothing/spacesuits/void.dm | 32 +- code/modules/clothing/suits/jobs.dm | 440 +- code/modules/clothing/suits/labcoat.dm | 170 +- code/modules/clothing/suits/miscellaneous.dm | 1008 +-- code/modules/clothing/suits/utility.dm | 288 +- code/modules/clothing/suits/wiz_robe.dm | 314 +- code/modules/clothing/under/chameleon.dm | 156 +- code/modules/clothing/under/color.dm | 366 +- code/modules/clothing/under/jobs/civilian.dm | 434 +- .../clothing/under/jobs/engineering.dm | 176 +- code/modules/clothing/under/jobs/medsci.dm | 482 +- code/modules/clothing/under/jobs/security.dm | 280 +- code/modules/clothing/under/miscellaneous.dm | 1168 +-- code/modules/clothing/under/shorts.dm | 50 +- code/modules/clothing/under/syndicate.dm | 56 +- code/modules/events/alien_infestation.dm | 82 +- code/modules/events/blob.dm | 226 +- code/modules/events/brand_intelligence.dm | 114 +- code/modules/events/carp_migration.dm | 50 +- .../modules/events/communications_blackout.dm | 32 +- code/modules/events/disease_outbreak.dm | 86 +- code/modules/events/electrical_storm.dm | 54 +- code/modules/events/event.dm | 168 +- code/modules/events/event_manager.dm | 128 +- code/modules/events/prison_break.dm | 100 +- code/modules/events/radiation_storm.dm | 162 +- code/modules/events/spacevine.dm | 22 +- code/modules/events/spider_infestation.dm | 56 +- .../events/spontaneous_appendicitis.dm | 30 +- code/modules/genetics/side_effects.dm | 180 +- code/modules/hydroponics/eggincubator.dm | 214 +- code/modules/library/lib_items.dm | 730 +- code/modules/library/lib_machines.dm | 412 +- code/modules/library/lib_readme.dm | 122 +- code/modules/liquid/splash_simulation.dm | 406 +- code/modules/maps/map_objects.dm | 32 +- code/modules/maps/nests.dm | 124 +- code/modules/maps/spawners/set_spawners.dm | 280 +- code/modules/maps/spawners/spawners.dm | 1866 ++-- .../mining/machine_input_output_plates.dm | 62 +- code/modules/mining/mine_areas.dm | 110 +- code/modules/mining/money_bag.dm | 158 +- code/modules/mob/dead/observer/login.dm | 40 +- code/modules/mob/dead/observer/logout.dm | 10 +- code/modules/mob/dead/observer/say.dm | 102 +- code/modules/mob/emote.dm | 156 +- code/modules/mob/inventory.dm | 670 +- code/modules/mob/living/carbon/alien/alien.dm | 576 +- .../carbon/alien/humanoid/alien_powers.dm | 378 +- .../carbon/alien/humanoid/caste/drone.dm | 102 +- .../carbon/alien/humanoid/caste/hunter.dm | 152 +- .../carbon/alien/humanoid/caste/sentinel.dm | 96 +- .../mob/living/carbon/alien/humanoid/death.dm | 34 +- .../mob/living/carbon/alien/humanoid/emote.dm | 258 +- .../living/carbon/alien/humanoid/humanoid.dm | 660 +- .../living/carbon/alien/humanoid/inventory.dm | 146 +- .../mob/living/carbon/alien/humanoid/life.dm | 922 +- .../mob/living/carbon/alien/humanoid/login.dm | 16 +- .../mob/living/carbon/alien/humanoid/queen.dm | 196 +- .../carbon/alien/humanoid/update_icons.dm | 350 +- .../mob/living/carbon/alien/larva/death.dm | 30 +- .../mob/living/carbon/alien/larva/emote.dm | 228 +- .../living/carbon/alien/larva/inventory.dm | 4 +- .../mob/living/carbon/alien/larva/larva.dm | 590 +- .../mob/living/carbon/alien/larva/life.dm | 776 +- .../mob/living/carbon/alien/larva/login.dm | 6 +- .../mob/living/carbon/alien/larva/powers.dm | 112 +- .../living/carbon/alien/larva/update_icons.dm | 44 +- code/modules/mob/living/carbon/alien/login.dm | 8 +- .../modules/mob/living/carbon/alien/logout.dm | 8 +- .../modules/mob/living/carbon/alien/powers.dm | 14 +- code/modules/mob/living/carbon/alien/say.dm | 60 +- .../mob/living/carbon/alien/special/_main.dm | 144 +- .../carbon/alien/special/alien_embryo.dm | 384 +- .../living/carbon/alien/special/facehugger.dm | 494 +- .../living/carbon/alien/special/snakeman.dm | 110 +- code/modules/mob/living/carbon/brain/MMI.dm | 556 +- code/modules/mob/living/carbon/brain/brain.dm | 128 +- .../mob/living/carbon/brain/brain_item.dm | 142 +- code/modules/mob/living/carbon/brain/death.dm | 68 +- code/modules/mob/living/carbon/brain/emote.dm | 144 +- code/modules/mob/living/carbon/brain/life.dm | 564 +- code/modules/mob/living/carbon/brain/login.dm | 2 +- code/modules/mob/living/carbon/brain/say.dm | 40 +- code/modules/mob/living/carbon/carbon.dm | 1320 +-- .../mob/living/carbon/carbon_defines.dm | 48 +- code/modules/mob/living/carbon/human/death.dm | 246 +- code/modules/mob/living/carbon/human/emote.dm | 1548 ++-- .../mob/living/carbon/human/examine.dm | 1032 +-- .../living/carbon/human/human_attackalien.dm | 124 +- .../living/carbon/human/human_attackhand.dm | 646 +- .../living/carbon/human/human_attackpaw.dm | 48 +- .../mob/living/carbon/human/human_damage.dm | 674 +- .../mob/living/carbon/human/human_defines.dm | 156 +- .../mob/living/carbon/human/human_movement.dm | 302 +- .../mob/living/carbon/human/inventory.dm | 1858 ++-- code/modules/mob/living/carbon/human/life.dm | 956 +- code/modules/mob/living/carbon/human/login.dm | 10 +- code/modules/mob/living/carbon/human/say.dm | 370 +- .../mob/living/carbon/human/update_icons.dm | 2218 ++--- .../mob/living/carbon/human/whisper.dm | 204 +- .../modules/mob/living/carbon/monkey/death.dm | 82 +- .../modules/mob/living/carbon/monkey/emote.dm | 292 +- .../mob/living/carbon/monkey/examine.dm | 92 +- .../mob/living/carbon/monkey/inventory.dm | 468 +- code/modules/mob/living/carbon/monkey/life.dm | 1426 +-- .../modules/mob/living/carbon/monkey/login.dm | 8 +- .../mob/living/carbon/monkey/monkey.dm | 1466 +-- .../mob/living/carbon/monkey/powers.dm | 12 +- code/modules/mob/living/carbon/monkey/say.dm | 24 +- .../mob/living/carbon/monkey/update_icons.dm | 370 +- code/modules/mob/living/damage_procs.dm | 178 +- code/modules/mob/living/living_defense.dm | 406 +- code/modules/mob/living/living_defines.dm | 150 +- code/modules/mob/living/logout.dm | 16 +- code/modules/mob/living/silicon/ai/ai.dm | 1694 ++-- code/modules/mob/living/silicon/ai/death.dm | 126 +- code/modules/mob/living/silicon/ai/examine.dm | 46 +- .../living/silicon/ai/freelook/cameranet.dm | 308 +- .../mob/living/silicon/ai/freelook/chunk.dm | 346 +- .../mob/living/silicon/ai/freelook/eye.dm | 322 +- .../mob/living/silicon/ai/freelook/read_me.dm | 100 +- .../silicon/ai/freelook/update_triggers.dm | 196 +- code/modules/mob/living/silicon/ai/laws.dm | 274 +- code/modules/mob/living/silicon/ai/life.dm | 374 +- code/modules/mob/living/silicon/ai/login.dm | 22 +- code/modules/mob/living/silicon/ai/logout.dm | 18 +- code/modules/mob/living/silicon/ai/say.dm | 514 +- .../modules/mob/living/silicon/decoy/death.dm | 18 +- .../modules/mob/living/silicon/decoy/decoy.dm | 42 +- code/modules/mob/living/silicon/decoy/life.dm | 34 +- code/modules/mob/living/silicon/login.dm | 8 +- code/modules/mob/living/silicon/pai/death.dm | 38 +- .../modules/mob/living/silicon/pai/examine.dm | 2 +- code/modules/mob/living/silicon/pai/life.dm | 42 +- code/modules/mob/living/silicon/pai/pai.dm | 486 +- .../mob/living/silicon/pai/personality.dm | 112 +- .../modules/mob/living/silicon/pai/recruit.dm | 458 +- code/modules/mob/living/silicon/pai/say.dm | 32 +- .../mob/living/silicon/pai/software.dm | 1454 +-- .../modules/mob/living/silicon/robot/death.dm | 128 +- .../modules/mob/living/silicon/robot/emote.dm | 450 +- .../mob/living/silicon/robot/examine.dm | 74 +- .../mob/living/silicon/robot/inventory.dm | 484 +- code/modules/mob/living/silicon/robot/laws.dm | 368 +- code/modules/mob/living/silicon/robot/life.dm | 736 +- .../modules/mob/living/silicon/robot/login.dm | 16 +- .../living/silicon/robot/robot_movement.dm | 66 +- code/modules/mob/living/silicon/say.dm | 172 +- code/modules/mob/living/silicon/silicon.dm | 620 +- .../mob/living/simple_animal/constructs.dm | 956 +- .../mob/living/simple_animal/friendly/cat.dm | 242 +- .../living/simple_animal/friendly/corgi.dm | 1140 +-- .../mob/living/simple_animal/friendly/crab.dm | 204 +- .../simple_animal/friendly/farm_animals.dm | 552 +- .../living/simple_animal/friendly/lizard.dm | 34 +- .../living/simple_animal/friendly/mouse.dm | 376 +- .../living/simple_animal/friendly/mushroom.dm | 30 +- .../living/simple_animal/friendly/slime.dm | 170 +- .../living/simple_animal/friendly/tomato.dm | 28 +- .../mob/living/simple_animal/hostile/alien.dm | 240 +- .../mob/living/simple_animal/hostile/carp.dm | 256 +- .../living/simple_animal/hostile/creature.dm | 162 +- .../living/simple_animal/hostile/faithless.dm | 210 +- .../living/simple_animal/hostile/hostile.dm | 690 +- .../simple_animal/hostile/retaliate/clown.dm | 78 +- .../hostile/retaliate/retaliate.dm | 108 +- .../mob/living/simple_animal/hostile/tree.dm | 142 +- .../mob/living/simple_animal/parrot.dm | 1702 ++-- .../modules/mob/living/simple_animal/shade.dm | 218 +- .../mob/living/simple_animal/simple_animal.dm | 1338 +-- code/modules/mob/living/simple_animal/worm.dm | 406 +- code/modules/mob/login.dm | 174 +- code/modules/mob/logout.dm | 54 +- code/modules/mob/mob_grab.dm | 482 +- code/modules/mob/mob_helpers.dm | 738 +- code/modules/mob/mob_movement.dm | 1100 +-- code/modules/mob/new_player/logout.dm | 12 +- code/modules/mob/new_player/new_player.dm | 1008 +-- code/modules/mob/new_player/poll.dm | 1098 +-- .../mob/new_player/preferences_setup.dm | 870 +- .../mob/new_player/sprite_accessories.dm | 1694 ++-- code/modules/mob/say.dm | 278 +- code/modules/mob/transform_procs.dm | 942 +- code/modules/mob/update_icons.dm | 140 +- code/modules/paperwork/photography.dm | 1004 +-- code/modules/power/antimatter/computer.dm | 192 +- .../power/antimatter/containment_jar.dm | 86 +- code/modules/power/antimatter/control.dm | 774 +- code/modules/power/antimatter/engine.dm | 414 +- code/modules/power/antimatter/fuel.dm | 194 +- code/modules/power/antimatter/shielding.dm | 478 +- code/modules/power/apc.dm | 2636 +++--- code/modules/power/cable.dm | 916 +- code/modules/power/cable_logic.dm | 582 +- code/modules/power/cell.dm | 306 +- code/modules/power/engine.dm | 24 +- code/modules/power/generator.dm | 864 +- code/modules/power/generator_type2.dm | 236 +- code/modules/power/lighting.dm | 1434 +-- code/modules/power/port_gen.dm | 660 +- code/modules/power/power.dm | 478 +- code/modules/power/singularity/collector.dm | 294 +- .../power/singularity/containment_field.dm | 156 +- code/modules/power/singularity/emitter.dm | 666 +- .../power/singularity/field_generator.dm | 642 +- code/modules/power/singularity/generator.dm | 70 +- .../particle_accelerator/particle.dm | 270 +- .../particle_accelerator.dm | 794 +- .../particle_accelerator/particle_chamber.dm | 18 +- .../particle_accelerator/particle_control.dm | 558 +- .../particle_accelerator/particle_emitter.dm | 104 +- .../particle_accelerator/particle_power.dm | 20 +- code/modules/power/singularity/singularity.dm | 1132 +-- code/modules/power/smes.dm | 214 +- code/modules/power/terminal.dm | 150 +- code/modules/power/treadmill.dm | 174 +- code/modules/power/turbine.dm | 618 +- code/modules/projectiles/ammunition.dm | 408 +- code/modules/projectiles/ammunition/boxes.dm | 160 +- .../modules/projectiles/ammunition/bullets.dm | 310 +- code/modules/projectiles/gun.dm | 544 +- code/modules/projectiles/guns/energy.dm | 128 +- code/modules/projectiles/guns/energy/laser.dm | 684 +- .../projectiles/guns/energy/nuclear.dm | 242 +- code/modules/projectiles/guns/energy/pulse.dm | 130 +- .../projectiles/guns/energy/special.dm | 1086 +-- code/modules/projectiles/guns/energy/stun.dm | 222 +- .../projectiles/guns/energy/temperature.dm | 360 +- code/modules/projectiles/guns/lawgiver.dm | 1150 +-- code/modules/projectiles/guns/projectile.dm | 464 +- .../projectiles/guns/projectile/automatic.dm | 356 +- .../projectiles/guns/projectile/pistol.dm | 178 +- .../projectiles/guns/projectile/revolver.dm | 362 +- .../projectiles/guns/projectile/shotgun.dm | 264 +- code/modules/projectiles/projectile.dm | 1210 +-- .../modules/projectiles/projectile/animate.dm | 28 +- code/modules/projectiles/projectile/beams.dm | 1716 ++-- .../modules/projectiles/projectile/bullets.dm | 632 +- code/modules/projectiles/projectile/change.dm | 372 +- code/modules/projectiles/projectile/energy.dm | 298 +- .../modules/projectiles/projectile/special.dm | 666 +- code/modules/reagents/Chemistry-Colours.dm | 132 +- code/modules/reagents/Chemistry-Machinery.dm | 4206 ++++----- code/modules/reagents/Chemistry-Readme.dm | 508 +- code/modules/reagents/grenade_launcher.dm | 132 +- code/modules/reagents/reagent_containers.dm | 454 +- .../reagents/reagent_containers/blood_pack.dm | 188 +- .../reagents/reagent_containers/borghydro.dm | 200 +- .../reagents/reagent_containers/chempack.dm | 638 +- .../reagents/reagent_containers/dropper.dm | 260 +- .../reagents/reagent_containers/food.dm | 26 +- .../reagent_containers/food/condiment.dm | 538 +- .../reagent_containers/food/drinks.dm | 2396 ++--- .../food/drinks/drinkingglass.dm | 1310 +-- .../reagent_containers/food/drinks/jar.dm | 64 +- .../reagent_containers/food/snacks.dm | 7860 ++++++++--------- .../reagent_containers/food/snacks/grown.dm | 1552 ++-- .../reagents/reagent_containers/glass.dm | 748 +- .../reagent_containers/glass/bottle.dm | 772 +- .../reagent_containers/glass/bottle/robot.dm | 64 +- .../reagents/reagent_containers/hypospray.dm | 204 +- .../reagents/reagent_containers/pill.dm | 562 +- .../reagents/reagent_containers/spray.dm | 382 +- .../reagents/reagent_containers/syringes.dm | 796 +- code/modules/reagents/syringe_gun.dm | 324 +- code/modules/recycling/conveyor2.dm | 892 +- .../recycling/disposal-construction.dm | 556 +- code/modules/recycling/disposal.dm | 2968 +++---- code/modules/recycling/sortingmachinery.dm | 1176 +-- code/modules/research/circuitprinter.dm | 152 +- code/modules/research/designs.dm | 324 +- code/modules/research/destructive_analyzer.dm | 228 +- code/modules/research/message_server.dm | 774 +- code/modules/research/protolathe.dm | 162 +- code/modules/research/rd-readme.dm | 476 +- code/modules/research/rdconsole.dm | 2248 ++--- code/modules/research/rdmachines.dm | 480 +- code/modules/research/research.dm | 636 +- code/modules/research/research_shuttle.dm | 230 +- code/modules/research/server.dm | 740 +- .../modules/research/xenoarchaeology/areas.dm | 204 +- .../research/xenoarchaeology/readme.dm | 8 +- code/modules/scripting/AST/AST Nodes.dm | 256 +- code/modules/scripting/AST/Blocks.dm | 88 +- .../AST/Operators/Binary Operators.dm | 382 +- .../AST/Operators/Unary Operators.dm | 102 +- code/modules/scripting/AST/Statements.dm | 218 +- code/modules/scripting/Errors.dm | 338 +- code/modules/scripting/IDE.dm | 374 +- .../scripting/Implementations/_Logic.dm | 450 +- .../scripting/Interpreter/Evaluation.dm | 406 +- .../scripting/Interpreter/Interaction.dm | 314 +- .../scripting/Interpreter/Interpreter.dm | 756 +- code/modules/scripting/Interpreter/Scope.dm | 32 +- code/modules/scripting/Options.dm | 240 +- code/modules/scripting/Parser/Expressions.dm | 740 +- code/modules/scripting/Parser/Keywords.dm | 412 +- code/modules/scripting/Parser/Parser.dm | 410 +- code/modules/scripting/Scanner/Scanner.dm | 582 +- code/modules/scripting/Scanner/Tokens.dm | 80 +- .../security levels/keycard authentication.dm | 372 +- .../security levels/security levels.dm | 206 +- code/names.dm | 34 +- code/stylesheet.dm | 172 +- code/unused/Virus2Prob.dm | 24 +- code/unused/computer2/airlock_control.dm | 118 +- code/unused/computer2/arcade.dm | 270 +- code/unused/computer2/base_program.dm | 516 +- code/unused/computer2/buildandrepair.dm | 266 +- code/unused/computer2/computerII.dm | 812 +- code/unused/computer2/filebrowse.dm | 322 +- code/unused/computer2/med_rec.dm | 924 +- code/unused/computer2/messenger.dm | 192 +- code/unused/computer2/peripherals.dm | 410 +- code/unused/filter_control.dm | 324 +- code/unused/gamemodes/ctf.dm | 258 +- code/unused/gamemodes/ctf_items.dm | 248 +- code/unused/gamemodes/deathmatch.dm | 128 +- code/unused/gamemodes/monkey.dm | 248 +- code/unused/gamemodes/restructuring.dm | 136 +- code/unused/gamemodes/ruby.dm | 556 +- code/unused/hivebot/death.dm | 46 +- code/unused/hivebot/emote.dm | 278 +- code/unused/hivebot/examine.dm | 18 +- code/unused/hivebot/hive_modules.dm | 114 +- code/unused/hivebot/hivebot.dm | 984 +-- code/unused/hivebot/hivebotdefine.dm | 86 +- code/unused/hivebot/hud.dm | 504 +- code/unused/hivebot/life.dm | 454 +- code/unused/hivebot/login.dm | 28 +- code/unused/hivebot/mainframe.dm | 324 +- code/unused/hivebot/say.dm | 20 +- .../mining/machine_craftlathe_unused.dm | 468 +- .../mining/machine_gas_extractor_unused.dm | 154 +- code/unused/mining/machine_purifier_unused.dm | 176 +- code/unused/mining/mine_generator_unused.dm | 348 +- code/unused/mining/rail_unused.dm | 672 +- code/unused/optics/beam.dm | 354 +- code/unused/optics/laser-pointer.dm | 144 +- code/unused/optics/mirror.dm | 164 +- code/unused/pda2/base_os.dm | 888 +- code/unused/pda2/base_program.dm | 364 +- code/unused/pda2/pda2.dm | 582 +- code/unused/pda2/record_progs.dm | 360 +- code/unused/pda2/scanners.dm | 206 +- code/unused/pda2/smallprogs.dm | 408 +- code/unused/shuttle_engines.dm | 74 +- code/unused/siphs.dm | 1030 +-- code/unused/spacecraft/manufacturing.dm | 494 +- code/unused/spacecraft/shipcore.dm | 694 +- code/unused/vehicle.dm | 640 +- code/world.dm | 952 +- maps/RandomZLevels/Academy.dm | 84 +- maps/RandomZLevels/challenge.dm | 62 +- maps/RandomZLevels/stationCollision.dm | 378 +- maps/RandomZLevels/wildwest.dm | 302 +- maps/_map.dm | 366 +- 898 files changed, 222641 insertions(+), 222641 deletions(-) diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 8e94f07b2be..5eadf8cf618 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -1,307 +1,307 @@ -/* -Quick overview: - -Pipes combine to form pipelines -Pipelines and other atmospheric objects combine to form pipe_networks - Note: A single pipe_network represents a completely open space - -Pipes -> Pipelines -Pipelines + Other Objects -> Pipe network - -*/ - -#define PIPE_TYPE_STANDARD 0 -#define PIPE_TYPE_HE 1 - -//Pipe bitflags -#define IS_MIRROR 1 -#define ALL_LAYER 2 //if the pipe can connect at any layer, instead of just the specific one - -/obj/machinery/atmospherics - anchored = 1 - idle_power_usage = 0 - active_power_usage = 0 - power_channel = ENVIRON - var/nodealert = 0 - var/update_icon_ready = 0 // don't update icons before they're ready or if they don't want to be - var/starting_volume = 200 - // Which directions can we connect with? - var/initialize_directions = 0 - var/can_be_coloured = 0 - var/image/centre_overlay = null - // Investigation logs - var/log - var/global/list/node_con = list() - var/global/list/node_ex = list() - var/pipe_flags = 0 - var/obj/machinery/atmospherics/mirror //not actually an object reference, but a type. The reflection of the current pipe - var/default_colour = null - var/image/pipe_image - - var/piping_layer = PIPING_LAYER_DEFAULT //used in multi-pipe-on-tile - pipes only connect if they're on the same pipe layer - - internal_gravity = 1 // Ventcrawlers can move in pipes without gravity since they have traction. - - -/obj/machinery/atmospherics/New() - ..() - machines.Remove(src) - atmos_machines |= src - -/obj/machinery/atmospherics/Destroy() - for(var/mob/living/M in src) //ventcrawling is serious business - M.remove_ventcrawl() - M.forceMove(src.loc) - if(pipe_image) - for(var/mob/living/M in player_list) - if(M.client) - M.client.images -= pipe_image - M.pipes_shown -= pipe_image - pipe_image = null - atmos_machines -= src - centre_overlay = null - ..() - - - -/obj/machinery/atmospherics/update_icon(var/adjacent_procd,node_list) - if(!can_be_coloured && color) - default_colour = color - color = null - else if(can_be_coloured && default_colour) - color = default_colour - default_colour = null - if((!node_con.len)||(!node_ex.len)) - node_con["[NORTH]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 1) - node_con["[SOUTH]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 2) - node_con["[EAST]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 4) - node_con["[WEST]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 8) - node_ex["[NORTH]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 1) - node_ex["[SOUTH]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 2) - node_ex["[EAST]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 4) - node_ex["[WEST]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 8) - alpha = invisibility ? 128 : 255 - if (!update_icon_ready) - update_icon_ready = 1 - else underlays.Cut() - var/list/missing_nodes = list() - for(var/direction in cardinal) - if(direction & initialize_directions) - missing_nodes += direction - for (var/obj/machinery/atmospherics/connected_node in node_list) - var/con_dir = get_dir(src, connected_node) - missing_nodes -= con_dir // finds all the directions that aren't pointed to by a node - var/image/nodecon = node_con["[con_dir]"] - if(nodecon) - if (default_colour && connected_node.default_colour && (connected_node.default_colour != default_colour)) // if both pipes have special colours - average them - var/list/centre_colour = GetHexColors(default_colour) - var/list/other_colour = GetHexColors(connected_node.default_colour) - var/list/average_colour = list(((centre_colour[1]+other_colour[1])/2),((centre_colour[2]+other_colour[2])/2),((centre_colour[3]+other_colour[3])/2)) - nodecon.color = rgb(average_colour[1],average_colour[2],average_colour[3]) - else if (color) - nodecon.color = null - else if (connected_node.color) - nodecon.color = connected_node.color - else if(default_colour) - nodecon.color = default_colour - else if(connected_node.default_colour && connected_node.default_colour != "#B4B4B4") - nodecon.color = connected_node.default_colour - else nodecon.color = "#B4B4B4" - underlays += nodecon - if (!adjacent_procd && connected_node.update_icon_ready && !(istype(connected_node,/obj/machinery/atmospherics/pipe/simple))) - connected_node.update_icon(1) - for (var/missing_dir in missing_nodes) - var/image/nodeex = node_ex["[missing_dir]"] - if(!color) - nodeex.color = default_colour ? default_colour : "#B4B4B4" - else nodeex.color = null - underlays += nodeex - - -/obj/machinery/atmospherics/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT) - piping_layer = new_layer - pixel_x = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X - pixel_y = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y - layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE) - -// Find a connecting /obj/machinery/atmospherics in specified direction. -/obj/machinery/atmospherics/proc/findConnecting(var/direction, var/given_layer = src.piping_layer) - for(var/obj/machinery/atmospherics/target in get_step(src,direction)) - if(target.initialize_directions & get_dir(target,src)) - if(isConnectable(target, direction, given_layer) && target.isConnectable(src, turn(direction, 180), given_layer)) - return target - -// Ditto, but for heat-exchanging pipes. -/obj/machinery/atmospherics/proc/findConnectingHE(var/direction, var/given_layer = src.piping_layer) - for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,direction)) - if(target.initialize_directions_he & get_dir(target,src)) - if(isConnectable(target, direction, given_layer) && target.isConnectable(src, turn(direction, 180), given_layer)) - return target - -//Called when checking connectability in findConnecting() -//This is checked for both pipes in establishing a connection - the base behaviour will work fine nearly every time -/obj/machinery/atmospherics/proc/isConnectable(var/obj/machinery/atmospherics/target, var/direction, var/given_layer) - return (target.piping_layer == given_layer || target.pipe_flags & ALL_LAYER) - -/obj/machinery/atmospherics/proc/getNodeType(var/node_id) - return PIPE_TYPE_STANDARD - -// A bit more flexible. -// @param connect_dirs integer Directions at which we should check for connections. -/obj/machinery/atmospherics/proc/findAllConnections(var/connect_dirs) - var/node_id=0 - for(var/direction in cardinal) - if(connect_dirs & direction) - node_id++ - var/obj/machinery/atmospherics/found - var/node_type=getNodeType(node_id) - switch(node_type) - if(PIPE_TYPE_STANDARD) - found = findConnecting(direction) - if(PIPE_TYPE_HE) - found = findConnectingHE(direction) - else - error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([node_id]): [node_type]") - return - if(!found) continue - var/node_var="node[node_id]" - if(!(node_var in vars)) - testing("[node_var] not in vars.") - return - if(!vars[node_var]) - vars[node_var] = found - -// Wait.. What the fuck? -// I asked /tg/ and bay and they have no idea why this is here, so into the trash it goes. - N3X -// Re-enabled for debugging. -/obj/machinery/atmospherics/process() - - if(timestopped) return 0 //under effects of time magick - . = build_network() - //testing("[src] called parent process to build_network()") - -/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - // Check to see if should be added to network. Add self if so and adjust variables appropriately. - // Note don't forget to have neighbors look as well! - - return null - -/obj/machinery/atmospherics/proc/build_network() - // Called to build a network from this node - return null - -/obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference) - // Returns pipe_network associated with connection to reference - // Notes: should create network if necessary - // Should never return null - - return null - -/obj/machinery/atmospherics/proc/unassign_network(datum/pipe_network/reference) - -/obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) - // Used when two pipe_networks are combining - -/obj/machinery/atmospherics/proc/return_network_air(datum/network/reference) - // Return a list of gas_mixture(s) in the object - // associated with reference pipe_network for use in rebuilding the networks gases list - // Is permitted to return null - -/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference) - -/obj/machinery/atmospherics/proc/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - error("[src] does not define a buildFrom!") - return FALSE - -/obj/machinery/atmospherics/cultify() - if(src.invisibility != INVISIBILITY_MAXIMUM) - src.invisibility = INVISIBILITY_MAXIMUM - - -/obj/machinery/atmospherics/attackby(var/obj/item/W, mob/user) - if(istype(W, /obj/item/pipe)) //lets you autodrop - var/obj/item/pipe/pipe = W - if(user.drop_item(pipe)) - pipe.setPipingLayer(src.piping_layer) //align it with us - return 1 - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if(src.machine_flags & WRENCHMOVE) - return ..() - var/turf/T = src.loc - if (level==1 && isturf(T) && T.intact) +/* +Quick overview: + +Pipes combine to form pipelines +Pipelines and other atmospheric objects combine to form pipe_networks + Note: A single pipe_network represents a completely open space + +Pipes -> Pipelines +Pipelines + Other Objects -> Pipe network + +*/ + +#define PIPE_TYPE_STANDARD 0 +#define PIPE_TYPE_HE 1 + +//Pipe bitflags +#define IS_MIRROR 1 +#define ALL_LAYER 2 //if the pipe can connect at any layer, instead of just the specific one + +/obj/machinery/atmospherics + anchored = 1 + idle_power_usage = 0 + active_power_usage = 0 + power_channel = ENVIRON + var/nodealert = 0 + var/update_icon_ready = 0 // don't update icons before they're ready or if they don't want to be + var/starting_volume = 200 + // Which directions can we connect with? + var/initialize_directions = 0 + var/can_be_coloured = 0 + var/image/centre_overlay = null + // Investigation logs + var/log + var/global/list/node_con = list() + var/global/list/node_ex = list() + var/pipe_flags = 0 + var/obj/machinery/atmospherics/mirror //not actually an object reference, but a type. The reflection of the current pipe + var/default_colour = null + var/image/pipe_image + + var/piping_layer = PIPING_LAYER_DEFAULT //used in multi-pipe-on-tile - pipes only connect if they're on the same pipe layer + + internal_gravity = 1 // Ventcrawlers can move in pipes without gravity since they have traction. + + +/obj/machinery/atmospherics/New() + ..() + machines.Remove(src) + atmos_machines |= src + +/obj/machinery/atmospherics/Destroy() + for(var/mob/living/M in src) //ventcrawling is serious business + M.remove_ventcrawl() + M.forceMove(src.loc) + if(pipe_image) + for(var/mob/living/M in player_list) + if(M.client) + M.client.images -= pipe_image + M.pipes_shown -= pipe_image + pipe_image = null + atmos_machines -= src + centre_overlay = null + ..() + + + +/obj/machinery/atmospherics/update_icon(var/adjacent_procd,node_list) + if(!can_be_coloured && color) + default_colour = color + color = null + else if(can_be_coloured && default_colour) + color = default_colour + default_colour = null + if((!node_con.len)||(!node_ex.len)) + node_con["[NORTH]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 1) + node_con["[SOUTH]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 2) + node_con["[EAST]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 4) + node_con["[WEST]"] = image('icons/obj/pipes.dmi',"pipe_intact",dir = 8) + node_ex["[NORTH]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 1) + node_ex["[SOUTH]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 2) + node_ex["[EAST]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 4) + node_ex["[WEST]"] = image('icons/obj/pipes.dmi',"pipe_exposed",dir = 8) + alpha = invisibility ? 128 : 255 + if (!update_icon_ready) + update_icon_ready = 1 + else underlays.Cut() + var/list/missing_nodes = list() + for(var/direction in cardinal) + if(direction & initialize_directions) + missing_nodes += direction + for (var/obj/machinery/atmospherics/connected_node in node_list) + var/con_dir = get_dir(src, connected_node) + missing_nodes -= con_dir // finds all the directions that aren't pointed to by a node + var/image/nodecon = node_con["[con_dir]"] + if(nodecon) + if (default_colour && connected_node.default_colour && (connected_node.default_colour != default_colour)) // if both pipes have special colours - average them + var/list/centre_colour = GetHexColors(default_colour) + var/list/other_colour = GetHexColors(connected_node.default_colour) + var/list/average_colour = list(((centre_colour[1]+other_colour[1])/2),((centre_colour[2]+other_colour[2])/2),((centre_colour[3]+other_colour[3])/2)) + nodecon.color = rgb(average_colour[1],average_colour[2],average_colour[3]) + else if (color) + nodecon.color = null + else if (connected_node.color) + nodecon.color = connected_node.color + else if(default_colour) + nodecon.color = default_colour + else if(connected_node.default_colour && connected_node.default_colour != "#B4B4B4") + nodecon.color = connected_node.default_colour + else nodecon.color = "#B4B4B4" + underlays += nodecon + if (!adjacent_procd && connected_node.update_icon_ready && !(istype(connected_node,/obj/machinery/atmospherics/pipe/simple))) + connected_node.update_icon(1) + for (var/missing_dir in missing_nodes) + var/image/nodeex = node_ex["[missing_dir]"] + if(!color) + nodeex.color = default_colour ? default_colour : "#B4B4B4" + else nodeex.color = null + underlays += nodeex + + +/obj/machinery/atmospherics/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT) + piping_layer = new_layer + pixel_x = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X + pixel_y = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y + layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE) + +// Find a connecting /obj/machinery/atmospherics in specified direction. +/obj/machinery/atmospherics/proc/findConnecting(var/direction, var/given_layer = src.piping_layer) + for(var/obj/machinery/atmospherics/target in get_step(src,direction)) + if(target.initialize_directions & get_dir(target,src)) + if(isConnectable(target, direction, given_layer) && target.isConnectable(src, turn(direction, 180), given_layer)) + return target + +// Ditto, but for heat-exchanging pipes. +/obj/machinery/atmospherics/proc/findConnectingHE(var/direction, var/given_layer = src.piping_layer) + for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,direction)) + if(target.initialize_directions_he & get_dir(target,src)) + if(isConnectable(target, direction, given_layer) && target.isConnectable(src, turn(direction, 180), given_layer)) + return target + +//Called when checking connectability in findConnecting() +//This is checked for both pipes in establishing a connection - the base behaviour will work fine nearly every time +/obj/machinery/atmospherics/proc/isConnectable(var/obj/machinery/atmospherics/target, var/direction, var/given_layer) + return (target.piping_layer == given_layer || target.pipe_flags & ALL_LAYER) + +/obj/machinery/atmospherics/proc/getNodeType(var/node_id) + return PIPE_TYPE_STANDARD + +// A bit more flexible. +// @param connect_dirs integer Directions at which we should check for connections. +/obj/machinery/atmospherics/proc/findAllConnections(var/connect_dirs) + var/node_id=0 + for(var/direction in cardinal) + if(connect_dirs & direction) + node_id++ + var/obj/machinery/atmospherics/found + var/node_type=getNodeType(node_id) + switch(node_type) + if(PIPE_TYPE_STANDARD) + found = findConnecting(direction) + if(PIPE_TYPE_HE) + found = findConnectingHE(direction) + else + error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([node_id]): [node_type]") + return + if(!found) continue + var/node_var="node[node_id]" + if(!(node_var in vars)) + testing("[node_var] not in vars.") + return + if(!vars[node_var]) + vars[node_var] = found + +// Wait.. What the fuck? +// I asked /tg/ and bay and they have no idea why this is here, so into the trash it goes. - N3X +// Re-enabled for debugging. +/obj/machinery/atmospherics/process() + + if(timestopped) return 0 //under effects of time magick + . = build_network() + //testing("[src] called parent process to build_network()") + +/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + // Check to see if should be added to network. Add self if so and adjust variables appropriately. + // Note don't forget to have neighbors look as well! + + return null + +/obj/machinery/atmospherics/proc/build_network() + // Called to build a network from this node + return null + +/obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference) + // Returns pipe_network associated with connection to reference + // Notes: should create network if necessary + // Should never return null + + return null + +/obj/machinery/atmospherics/proc/unassign_network(datum/pipe_network/reference) + +/obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) + // Used when two pipe_networks are combining + +/obj/machinery/atmospherics/proc/return_network_air(datum/network/reference) + // Return a list of gas_mixture(s) in the object + // associated with reference pipe_network for use in rebuilding the networks gases list + // Is permitted to return null + +/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference) + +/obj/machinery/atmospherics/proc/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + error("[src] does not define a buildFrom!") + return FALSE + +/obj/machinery/atmospherics/cultify() + if(src.invisibility != INVISIBILITY_MAXIMUM) + src.invisibility = INVISIBILITY_MAXIMUM + + +/obj/machinery/atmospherics/attackby(var/obj/item/W, mob/user) + if(istype(W, /obj/item/pipe)) //lets you autodrop + var/obj/item/pipe/pipe = W + if(user.drop_item(pipe)) + pipe.setPipingLayer(src.piping_layer) //align it with us + return 1 + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + if(src.machine_flags & WRENCHMOVE) + return ..() + var/turf/T = src.loc + if (level==1 && isturf(T) && T.intact) to_chat(user, "You must remove the plating first.") - return 1 - var/datum/gas_mixture/int_air = return_air() - var/datum/gas_mixture/env_air = loc.return_air() - add_fingerprint(user) - if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE) - if(istype(W, /obj/item/weapon/wrench/socket) && istype(src, /obj/machinery/atmospherics/pipe)) + return 1 + var/datum/gas_mixture/int_air = return_air() + var/datum/gas_mixture/env_air = loc.return_air() + add_fingerprint(user) + if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE) + if(istype(W, /obj/item/weapon/wrench/socket) && istype(src, /obj/machinery/atmospherics/pipe)) to_chat(user, "You begin to open the pressure release valve on the pipe...") - if(do_after(user, src, 50)) - if(!loc) return - playsound(get_turf(src), 'sound/machines/hiss.ogg', 50, 1) - user.visible_message("[user] vents \the [src].", - "You have vented \the [src].", - "You hear a ratchet.") - var/obj/machinery/atmospherics/pipe/P = src - var/datum/gas_mixture/transit = new - transit.add(int_air) - var/datum/pipeline/pipe_parent = P.parent - if(pipe_parent) - transit.divide(pipe_parent.members.len) //we get the total pressure over the number of pipes to find gas per pipe - env_air.add(transit) //put it in the air - qdel(transit) //remove the carrier - transit = null - else + if(do_after(user, src, 50)) + if(!loc) return + playsound(get_turf(src), 'sound/machines/hiss.ogg', 50, 1) + user.visible_message("[user] vents \the [src].", + "You have vented \the [src].", + "You hear a ratchet.") + var/obj/machinery/atmospherics/pipe/P = src + var/datum/gas_mixture/transit = new + transit.add(int_air) + var/datum/pipeline/pipe_parent = P.parent + if(pipe_parent) + transit.divide(pipe_parent.members.len) //we get the total pressure over the number of pipes to find gas per pipe + env_air.add(transit) //put it in the air + qdel(transit) //remove the carrier + transit = null + else to_chat(user, "You cannot unwrench this [src], it's too exerted due to internal pressure.") - return 1 - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + return 1 + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You begin to unfasten \the [src]...") - if (do_after(user, src, 40)) - user.visible_message( \ - "[user] unfastens \the [src].", \ - "You have unfastened \the [src].", \ - "You hear a ratchet.") - getFromPool(/obj/item/pipe, loc, null, null, src) - //P.New(loc, make_from=src) //new /obj/item/pipe(loc, make_from=src) - qdel(src) - return 1 - -#define VENT_SOUND_DELAY 30 - -/obj/machinery/atmospherics/Entered(atom/movable/Obj) - if(istype(Obj, /mob/living)) - var/mob/living/L = Obj - L.ventcrawl_layer = src.piping_layer - -/obj/machinery/atmospherics/relaymove(mob/living/user, direction) - if(!(direction & initialize_directions)) //can't go in a way we aren't connecting to - return - - var/obj/machinery/atmospherics/target_move = findConnecting(direction, user.ventcrawl_layer) - if(target_move) - if(is_type_in_list(target_move, ventcrawl_machinery) && target_move.can_crawl_through()) - user.remove_ventcrawl() - user.forceMove(target_move.loc) //handles entering and so on - user.visible_message("You hear something squeezing through the ducts.", "You climb out the ventilation system.") - else if(target_move.can_crawl_through()) - if(target_move.return_network(target_move) != return_network(src)) - user.remove_ventcrawl() - user.add_ventcrawl(target_move) - user.forceMove(target_move) - user.client.eye = target_move //if we don't do this, Byond only updates the eye every tick - required for smooth movement - if(world.time - user.last_played_vent > VENT_SOUND_DELAY) - user.last_played_vent = world.time - playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3) - else - if((direction & initialize_directions) || is_type_in_list(src, ventcrawl_machinery) && src.can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent - user.remove_ventcrawl() - user.forceMove(src.loc) - user.visible_message("You hear something squeezing through the pipes.", "You climb out the ventilation system.") - user.canmove = 0 - spawn(1) - user.canmove = 1 - -/obj/machinery/atmospherics/proc/can_crawl_through() - return 1 + if (do_after(user, src, 40)) + user.visible_message( \ + "[user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") + getFromPool(/obj/item/pipe, loc, null, null, src) + //P.New(loc, make_from=src) //new /obj/item/pipe(loc, make_from=src) + qdel(src) + return 1 + +#define VENT_SOUND_DELAY 30 + +/obj/machinery/atmospherics/Entered(atom/movable/Obj) + if(istype(Obj, /mob/living)) + var/mob/living/L = Obj + L.ventcrawl_layer = src.piping_layer + +/obj/machinery/atmospherics/relaymove(mob/living/user, direction) + if(!(direction & initialize_directions)) //can't go in a way we aren't connecting to + return + + var/obj/machinery/atmospherics/target_move = findConnecting(direction, user.ventcrawl_layer) + if(target_move) + if(is_type_in_list(target_move, ventcrawl_machinery) && target_move.can_crawl_through()) + user.remove_ventcrawl() + user.forceMove(target_move.loc) //handles entering and so on + user.visible_message("You hear something squeezing through the ducts.", "You climb out the ventilation system.") + else if(target_move.can_crawl_through()) + if(target_move.return_network(target_move) != return_network(src)) + user.remove_ventcrawl() + user.add_ventcrawl(target_move) + user.forceMove(target_move) + user.client.eye = target_move //if we don't do this, Byond only updates the eye every tick - required for smooth movement + if(world.time - user.last_played_vent > VENT_SOUND_DELAY) + user.last_played_vent = world.time + playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3) + else + if((direction & initialize_directions) || is_type_in_list(src, ventcrawl_machinery) && src.can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent + user.remove_ventcrawl() + user.forceMove(src.loc) + user.visible_message("You hear something squeezing through the pipes.", "You climb out the ventilation system.") + user.canmove = 0 + spawn(1) + user.canmove = 1 + +/obj/machinery/atmospherics/proc/can_crawl_through() + return 1 diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm index 352e0eb2265..96bc145c00c 100644 --- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm +++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm @@ -1,154 +1,154 @@ -/obj/machinery/atmospherics/binary - dir = SOUTH - initialize_directions = SOUTH|NORTH - use_power = 1 - - var/datum/gas_mixture/air1 - var/datum/gas_mixture/air2 - - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - - var/datum/pipe_network/network1 - var/datum/pipe_network/network2 - - var/activity_log = "" - -/obj/machinery/atmospherics/binary/investigation_log(var/subject, var/message) - activity_log += ..() - -/obj/machinery/atmospherics/binary/New() - ..() - switch(dir) - if(NORTH) - initialize_directions = NORTH|SOUTH - if(SOUTH) - initialize_directions = NORTH|SOUTH - if(EAST) - initialize_directions = EAST|WEST - if(WEST) - initialize_directions = EAST|WEST - air1 = new - air2 = new - update_icon() - air1.volume = 200 - air2.volume = 200 - -/obj/machinery/atmospherics/binary/update_icon(var/adjacent_procd) - var/node_list = list(node1,node2) - ..(adjacent_procd,node_list) - -/obj/machinery/atmospherics/binary/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - if (pipe.pipename) - name = pipe.pipename - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize() - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - return 1 - -// Housekeeping and pipe network stuff below -/obj/machinery/atmospherics/binary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - if(reference == node1) - network1 = new_network - - else if(reference == node2) - network2 = new_network - - if(new_network.normal_members.Find(src)) - return 0 - - new_network.normal_members += src - - return null - -/obj/machinery/atmospherics/binary/Destroy() - if(node1) - node1.disconnect(src) - if(network1) - returnToPool(network1) - if(node2) - node2.disconnect(src) - if(network2) - returnToPool(network2) - - node1 = null - node2 = null - - ..() - -/obj/machinery/atmospherics/binary/initialize() - if(node1 && node2) return - - node1 = findConnecting(turn(dir, 180)) - node2 = findConnecting(dir) - - update_icon() - -/obj/machinery/atmospherics/binary/build_network() - if(!network1 && node1) - network1 = getFromPool(/datum/pipe_network) - network1.normal_members += src - network1.build_network(node1, src) - - if(!network2 && node2) - network2 = getFromPool(/datum/pipe_network) - network2.normal_members += src - network2.build_network(node2, src) - - -/obj/machinery/atmospherics/binary/return_network(obj/machinery/atmospherics/reference) - build_network() - - if(reference==node1) - return network1 - - if(reference==node2) - return network2 - - return null - -/obj/machinery/atmospherics/binary/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) - if(network1 == old_network) - network1 = new_network - if(network2 == old_network) - network2 = new_network - - return 1 - -/obj/machinery/atmospherics/binary/return_network_air(datum/pipe_network/reference) - var/list/results = list() - - if(network1 == reference) - results += air1 - if(network2 == reference) - results += air2 - - return results - -/obj/machinery/atmospherics/binary/disconnect(obj/machinery/atmospherics/reference) - if(reference==node1) - if(network1) - returnToPool(network1) - node1 = null - - else if(reference==node2) - if(network2) - returnToPool(network2) - node2 = null - - return null - -/obj/machinery/atmospherics/binary/unassign_network(datum/pipe_network/reference) - if(network1 == reference) - network1 = null - if(network2 == reference) +/obj/machinery/atmospherics/binary + dir = SOUTH + initialize_directions = SOUTH|NORTH + use_power = 1 + + var/datum/gas_mixture/air1 + var/datum/gas_mixture/air2 + + var/obj/machinery/atmospherics/node1 + var/obj/machinery/atmospherics/node2 + + var/datum/pipe_network/network1 + var/datum/pipe_network/network2 + + var/activity_log = "" + +/obj/machinery/atmospherics/binary/investigation_log(var/subject, var/message) + activity_log += ..() + +/obj/machinery/atmospherics/binary/New() + ..() + switch(dir) + if(NORTH) + initialize_directions = NORTH|SOUTH + if(SOUTH) + initialize_directions = NORTH|SOUTH + if(EAST) + initialize_directions = EAST|WEST + if(WEST) + initialize_directions = EAST|WEST + air1 = new + air2 = new + update_icon() + air1.volume = 200 + air2.volume = 200 + +/obj/machinery/atmospherics/binary/update_icon(var/adjacent_procd) + var/node_list = list(node1,node2) + ..(adjacent_procd,node_list) + +/obj/machinery/atmospherics/binary/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + if (pipe.pipename) + name = pipe.pipename + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize() + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + return 1 + +// Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/binary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + if(reference == node1) + network1 = new_network + + else if(reference == node2) + network2 = new_network + + if(new_network.normal_members.Find(src)) + return 0 + + new_network.normal_members += src + + return null + +/obj/machinery/atmospherics/binary/Destroy() + if(node1) + node1.disconnect(src) + if(network1) + returnToPool(network1) + if(node2) + node2.disconnect(src) + if(network2) + returnToPool(network2) + + node1 = null + node2 = null + + ..() + +/obj/machinery/atmospherics/binary/initialize() + if(node1 && node2) return + + node1 = findConnecting(turn(dir, 180)) + node2 = findConnecting(dir) + + update_icon() + +/obj/machinery/atmospherics/binary/build_network() + if(!network1 && node1) + network1 = getFromPool(/datum/pipe_network) + network1.normal_members += src + network1.build_network(node1, src) + + if(!network2 && node2) + network2 = getFromPool(/datum/pipe_network) + network2.normal_members += src + network2.build_network(node2, src) + + +/obj/machinery/atmospherics/binary/return_network(obj/machinery/atmospherics/reference) + build_network() + + if(reference==node1) + return network1 + + if(reference==node2) + return network2 + + return null + +/obj/machinery/atmospherics/binary/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) + if(network1 == old_network) + network1 = new_network + if(network2 == old_network) + network2 = new_network + + return 1 + +/obj/machinery/atmospherics/binary/return_network_air(datum/pipe_network/reference) + var/list/results = list() + + if(network1 == reference) + results += air1 + if(network2 == reference) + results += air2 + + return results + +/obj/machinery/atmospherics/binary/disconnect(obj/machinery/atmospherics/reference) + if(reference==node1) + if(network1) + returnToPool(network1) + node1 = null + + else if(reference==node2) + if(network2) + returnToPool(network2) + node2 = null + + return null + +/obj/machinery/atmospherics/binary/unassign_network(datum/pipe_network/reference) + if(network1 == reference) + network1 = null + if(network2 == reference) network2 = null \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm index 18b7703efec..580484aadbb 100644 --- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm +++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm @@ -1,162 +1,162 @@ -//node1, air1, network1 correspond to input -//node2, air2, network2 correspond to output - -/obj/machinery/atmospherics/binary/circulator - name = "circulator" - desc = "A gas circulator turbine and heat exchanger." - icon = 'icons/obj/pipes.dmi' - icon_state = "circ-off" - anchored = 0 - - use_power = 0 - - var/obj/machinery/power/generator/linked_generator - - var/kinetic_efficiency = 0.04 //combined kinetic and kinetic-to-electric efficiency - var/volume_ratio = 0.2 - - var/recent_moles_transferred = 0 - var/last_heat_capacity = 0 - var/last_temperature = 0 - var/last_pressure_delta = 0 - var/last_worldtime_transfer = 0 - - var/last_stored_energy_transferred = 0 - var/volume_capacity_used = 0 - var/stored_energy = 0 - - density = 1 - - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/atmospherics/binary/circulator/New() - . = ..() - air1.volume = 1000 - -/obj/machinery/atmospherics/binary/circulator/Destroy() - . = ..() - if(linked_generator) - linked_generator.reconnect() - -/obj/machinery/atmospherics/binary/circulator/examine(var/mob/user) - . = ..() - to_chat(user, "Its outlet port is to the [dir2text(dir)].") - -/obj/machinery/atmospherics/binary/circulator/proc/return_transfer_air() - if(!anchored || stat & BROKEN || !network1) - return - - var/datum/gas_mixture/removed - var/input_starting_pressure = air1.return_pressure() - var/output_starting_pressure = air2.return_pressure() - last_pressure_delta = max(input_starting_pressure - output_starting_pressure - 5, 0) - - //Only circulate air if there is a pressure difference (plus 5kPa kinetic, 10kPa static friction). - if(air1.temperature > 0 && last_pressure_delta > 5) - - //Calculate necessary moles to transfer using PV = nRT. - recent_moles_transferred = (last_pressure_delta * air1.volume / (air1.temperature * R_IDEAL_GAS_EQUATION)) / 3 //Uses the volume of the whole network, not just itself. - volume_capacity_used = min((last_pressure_delta * air1.volume / 3) / (input_starting_pressure * air1.volume), 1) //How much of the gas in the input air volume is consumed. - - //Calculate energy generated from kinetic turbine. - stored_energy += 1 / ADIABATIC_EXPONENT * min(last_pressure_delta * air1.volume, input_starting_pressure * air1.volume) * (1 - volume_ratio ** ADIABATIC_EXPONENT) * kinetic_efficiency - - - //Actually transfer the gas. - removed = air1.remove(recent_moles_transferred) - if(removed) - last_heat_capacity = removed.heat_capacity() - last_temperature = removed.temperature - - //Update the gas networks. - network1.update = 1 - - last_worldtime_transfer = world.time - else - recent_moles_transferred = 0 - - update_icon() - return removed - -/obj/machinery/atmospherics/binary/circulator/proc/return_stored_energy() - last_stored_energy_transferred = stored_energy - stored_energy = 0 - return last_stored_energy_transferred - -/obj/machinery/atmospherics/binary/circulator/process() - . = ..() - - if(last_worldtime_transfer < world.time - 50) - recent_moles_transferred = 0 - update_icon() - -/obj/machinery/atmospherics/binary/circulator/update_icon() - if(!linked_generator || linked_generator.stat & (NOPOWER | BROKEN)) //These get power from the TeG itself. - icon_state = "circ-p" - - else if(last_pressure_delta > 0 && recent_moles_transferred > 0) - if(last_pressure_delta > 5* ONE_ATMOSPHERE) - icon_state = "circ-run" - else - icon_state = "circ-slow" - else - icon_state = "circ-off" - - return 1 - -/obj/machinery/atmospherics/binary/circulator/wrenchAnchor(mob/user) - . = ..() - if(anchored) - if(dir & (NORTH|SOUTH)) - initialize_directions = NORTH|SOUTH - else if(dir & (EAST|WEST)) - initialize_directions = EAST|WEST - - initialize() - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - - var/gendir = turn(dir, -90) - for(var/obj/machinery/power/generator/pot_gen in get_step(src, gendir)) - pot_gen.reconnect() - - else - if(node1) - node1.disconnect(src) - if(network1) - returnToPool(network1) - if(node2) - node2.disconnect(src) - if(network2) - returnToPool(network2) - - node1 = null - node2 = null - - linked_generator.reconnect() - - -/obj/machinery/atmospherics/binary/circulator/verb/rotate_clockwise() - set category = "Object" - set name = "Rotate Circulator (Clockwise)" - set src in view(1) - - if(usr.isUnconscious() || usr.restrained() || anchored) - return - - src.dir = turn(src.dir, 90) - -/obj/machinery/atmospherics/binary/circulator/verb/rotate_anticlockwise() - set category = "Object" - set name = "Rotate Circulator (Counterclockwise)" - set src in view(1) - - if(usr.isUnconscious() || usr.restrained() || anchored) - return - - src.dir = turn(src.dir, -90) +//node1, air1, network1 correspond to input +//node2, air2, network2 correspond to output + +/obj/machinery/atmospherics/binary/circulator + name = "circulator" + desc = "A gas circulator turbine and heat exchanger." + icon = 'icons/obj/pipes.dmi' + icon_state = "circ-off" + anchored = 0 + + use_power = 0 + + var/obj/machinery/power/generator/linked_generator + + var/kinetic_efficiency = 0.04 //combined kinetic and kinetic-to-electric efficiency + var/volume_ratio = 0.2 + + var/recent_moles_transferred = 0 + var/last_heat_capacity = 0 + var/last_temperature = 0 + var/last_pressure_delta = 0 + var/last_worldtime_transfer = 0 + + var/last_stored_energy_transferred = 0 + var/volume_capacity_used = 0 + var/stored_energy = 0 + + density = 1 + + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/atmospherics/binary/circulator/New() + . = ..() + air1.volume = 1000 + +/obj/machinery/atmospherics/binary/circulator/Destroy() + . = ..() + if(linked_generator) + linked_generator.reconnect() + +/obj/machinery/atmospherics/binary/circulator/examine(var/mob/user) + . = ..() + to_chat(user, "Its outlet port is to the [dir2text(dir)].") + +/obj/machinery/atmospherics/binary/circulator/proc/return_transfer_air() + if(!anchored || stat & BROKEN || !network1) + return + + var/datum/gas_mixture/removed + var/input_starting_pressure = air1.return_pressure() + var/output_starting_pressure = air2.return_pressure() + last_pressure_delta = max(input_starting_pressure - output_starting_pressure - 5, 0) + + //Only circulate air if there is a pressure difference (plus 5kPa kinetic, 10kPa static friction). + if(air1.temperature > 0 && last_pressure_delta > 5) + + //Calculate necessary moles to transfer using PV = nRT. + recent_moles_transferred = (last_pressure_delta * air1.volume / (air1.temperature * R_IDEAL_GAS_EQUATION)) / 3 //Uses the volume of the whole network, not just itself. + volume_capacity_used = min((last_pressure_delta * air1.volume / 3) / (input_starting_pressure * air1.volume), 1) //How much of the gas in the input air volume is consumed. + + //Calculate energy generated from kinetic turbine. + stored_energy += 1 / ADIABATIC_EXPONENT * min(last_pressure_delta * air1.volume, input_starting_pressure * air1.volume) * (1 - volume_ratio ** ADIABATIC_EXPONENT) * kinetic_efficiency + + + //Actually transfer the gas. + removed = air1.remove(recent_moles_transferred) + if(removed) + last_heat_capacity = removed.heat_capacity() + last_temperature = removed.temperature + + //Update the gas networks. + network1.update = 1 + + last_worldtime_transfer = world.time + else + recent_moles_transferred = 0 + + update_icon() + return removed + +/obj/machinery/atmospherics/binary/circulator/proc/return_stored_energy() + last_stored_energy_transferred = stored_energy + stored_energy = 0 + return last_stored_energy_transferred + +/obj/machinery/atmospherics/binary/circulator/process() + . = ..() + + if(last_worldtime_transfer < world.time - 50) + recent_moles_transferred = 0 + update_icon() + +/obj/machinery/atmospherics/binary/circulator/update_icon() + if(!linked_generator || linked_generator.stat & (NOPOWER | BROKEN)) //These get power from the TeG itself. + icon_state = "circ-p" + + else if(last_pressure_delta > 0 && recent_moles_transferred > 0) + if(last_pressure_delta > 5* ONE_ATMOSPHERE) + icon_state = "circ-run" + else + icon_state = "circ-slow" + else + icon_state = "circ-off" + + return 1 + +/obj/machinery/atmospherics/binary/circulator/wrenchAnchor(mob/user) + . = ..() + if(anchored) + if(dir & (NORTH|SOUTH)) + initialize_directions = NORTH|SOUTH + else if(dir & (EAST|WEST)) + initialize_directions = EAST|WEST + + initialize() + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + + var/gendir = turn(dir, -90) + for(var/obj/machinery/power/generator/pot_gen in get_step(src, gendir)) + pot_gen.reconnect() + + else + if(node1) + node1.disconnect(src) + if(network1) + returnToPool(network1) + if(node2) + node2.disconnect(src) + if(network2) + returnToPool(network2) + + node1 = null + node2 = null + + linked_generator.reconnect() + + +/obj/machinery/atmospherics/binary/circulator/verb/rotate_clockwise() + set category = "Object" + set name = "Rotate Circulator (Clockwise)" + set src in view(1) + + if(usr.isUnconscious() || usr.restrained() || anchored) + return + + src.dir = turn(src.dir, 90) + +/obj/machinery/atmospherics/binary/circulator/verb/rotate_anticlockwise() + set category = "Object" + set name = "Rotate Circulator (Counterclockwise)" + set src in view(1) + + if(usr.isUnconscious() || usr.restrained() || anchored) + return + + src.dir = turn(src.dir, -90) diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm index 49fab8ff878..066e2df2c21 100644 --- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm @@ -1,222 +1,222 @@ -/obj/machinery/atmospherics/binary/dp_vent_pump - icon = 'icons/obj/atmospherics/dp_vent_pump.dmi' - icon_state = "off" - - //node2 is output port - //node1 is input port - - name = "Dual Port Air Vent" - desc = "Has a valve and pump attached to it. There are two ports." - - level = 1 - - var/on = 0 - var/pump_direction = 1 //0 = siphoning, 1 = releasing - - var/external_pressure_bound = ONE_ATMOSPHERE - var/input_pressure_min = 0 - var/output_pressure_max = 0 - - var/pressure_checks = 1 - //1: Do not pass external_pressure_bound - //2: Do not pass input_pressure_min - //4: Do not pass output_pressure_max - - var/frequency = 0 - var/id_tag = null - var/datum/radio_frequency/radio_connection - - machine_flags = MULTITOOL_MENU - -/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume - name = "Large Dual Port Air Vent" - -/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/New() - ..() - - air1.volume = 2500 - air2.volume = 2500 - -/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon() - if(on) - if(pump_direction) - icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out" - else - icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in" - else - icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off" - on = 0 - - return - -/obj/machinery/atmospherics/binary/dp_vent_pump/hide(var/i) //to make the little pipe section invisible, the icon changes. - if(on) - if(pump_direction) - icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out" - else - icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in" - else - icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off" - on = 0 - return - -/obj/machinery/atmospherics/binary/dp_vent_pump/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return {" - - "} - -/obj/machinery/atmospherics/binary/dp_vent_pump/process() - . = ..() - - if(!on) - return - - var/datum/gas_mixture/environment = loc.return_air() - var/environment_pressure = environment.return_pressure() - - if(pump_direction) //input -> external - var/pressure_delta = 10000 - - if(pressure_checks&1) - pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure)) - if(pressure_checks&2) - pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min)) - - if(pressure_delta > 0) - if(air1.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - - loc.assume_air(removed) - - if(network1) - network1.update = 1 - - else //external -> output - var/pressure_delta = 10000 - - if(pressure_checks&1) - pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) - if(pressure_checks&4) - pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure())) - - if(pressure_delta > 0) - if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - - air2.merge(removed) - - if(network2) - network2.update = 1 - - return 1 - -//Radio remote control - -/obj/machinery/atmospherics/binary/dp_vent_pump/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA) - -/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "tag" = id_tag, - "device" = "ADVP", - "power" = on, - "direction" = pump_direction?("release"):("siphon"), - "checks" = pressure_checks, - "input" = input_pressure_min, - "output" = output_pressure_max, - "external" = external_pressure_bound, - "sigtype" = "status" - ) - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - - return 1 - -/obj/machinery/atmospherics/binary/dp_vent_pump/initialize() - ..() - if(frequency) - set_frequency(frequency) - -/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal) - - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) - return 0 - - var/handled=0 - if("power" in signal.data) - on = text2num(signal.data["power"]) - handled=1 - - if("power_toggle" in signal.data) - on = !on - handled=1 - - if("direction" in signal.data) - pump_direction = text2num(signal.data["direction"]) - handled=1 - - if("checks" in signal.data) - pressure_checks = text2num(signal.data["checks"]) - handled=1 - - if("purge" in signal.data) - pressure_checks &= ~1 - pump_direction = 0 - handled=1 - - if("stabilize" in signal.data) - pressure_checks |= 1 - pump_direction = 1 - handled=1 - - if("set_input_pressure" in signal.data) - input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 - - if("set_output_pressure" in signal.data) - output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 - - if("set_external_pressure" in signal.data) - external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - if(!handled) - testing("\[[world.timeofday]\]: dp_vent_pump/receive_signal: unknown command \n[signal.debug_print()]") - spawn(2) - broadcast_status() - update_icon() - -/obj/machinery/atmospherics/binary/dp_vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob) - return ..() - -/obj/machinery/atmospherics/binary/dp_vent_pump/interact(var/mob/user) - update_multitool_menu(user) - -/obj/machinery/atmospherics/binary/dp_vent_pump/canClone(var/obj/O) - return istype(O, /obj/machinery/atmospherics/binary/dp_vent_pump) - -/obj/machinery/atmospherics/binary/dp_vent_pump/clone(var/obj/machinery/atmospherics/binary/dp_vent_pump/O) - id_tag = O.id_tag - set_frequency(O.frequency) - return 1 +/obj/machinery/atmospherics/binary/dp_vent_pump + icon = 'icons/obj/atmospherics/dp_vent_pump.dmi' + icon_state = "off" + + //node2 is output port + //node1 is input port + + name = "Dual Port Air Vent" + desc = "Has a valve and pump attached to it. There are two ports." + + level = 1 + + var/on = 0 + var/pump_direction = 1 //0 = siphoning, 1 = releasing + + var/external_pressure_bound = ONE_ATMOSPHERE + var/input_pressure_min = 0 + var/output_pressure_max = 0 + + var/pressure_checks = 1 + //1: Do not pass external_pressure_bound + //2: Do not pass input_pressure_min + //4: Do not pass output_pressure_max + + var/frequency = 0 + var/id_tag = null + var/datum/radio_frequency/radio_connection + + machine_flags = MULTITOOL_MENU + +/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume + name = "Large Dual Port Air Vent" + +/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/New() + ..() + + air1.volume = 2500 + air2.volume = 2500 + +/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon() + if(on) + if(pump_direction) + icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out" + else + icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in" + else + icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off" + on = 0 + + return + +/obj/machinery/atmospherics/binary/dp_vent_pump/hide(var/i) //to make the little pipe section invisible, the icon changes. + if(on) + if(pump_direction) + icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out" + else + icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in" + else + icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off" + on = 0 + return + +/obj/machinery/atmospherics/binary/dp_vent_pump/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return {" + + "} + +/obj/machinery/atmospherics/binary/dp_vent_pump/process() + . = ..() + + if(!on) + return + + var/datum/gas_mixture/environment = loc.return_air() + var/environment_pressure = environment.return_pressure() + + if(pump_direction) //input -> external + var/pressure_delta = 10000 + + if(pressure_checks&1) + pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure)) + if(pressure_checks&2) + pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min)) + + if(pressure_delta > 0) + if(air1.temperature > 0) + var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = air1.remove(transfer_moles) + + loc.assume_air(removed) + + if(network1) + network1.update = 1 + + else //external -> output + var/pressure_delta = 10000 + + if(pressure_checks&1) + pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) + if(pressure_checks&4) + pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure())) + + if(pressure_delta > 0) + if(environment.temperature > 0) + var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) + + air2.merge(removed) + + if(network2) + network2.update = 1 + + return 1 + +//Radio remote control + +/obj/machinery/atmospherics/binary/dp_vent_pump/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA) + +/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "tag" = id_tag, + "device" = "ADVP", + "power" = on, + "direction" = pump_direction?("release"):("siphon"), + "checks" = pressure_checks, + "input" = input_pressure_min, + "output" = output_pressure_max, + "external" = external_pressure_bound, + "sigtype" = "status" + ) + radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + + return 1 + +/obj/machinery/atmospherics/binary/dp_vent_pump/initialize() + ..() + if(frequency) + set_frequency(frequency) + +/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal) + + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) + return 0 + + var/handled=0 + if("power" in signal.data) + on = text2num(signal.data["power"]) + handled=1 + + if("power_toggle" in signal.data) + on = !on + handled=1 + + if("direction" in signal.data) + pump_direction = text2num(signal.data["direction"]) + handled=1 + + if("checks" in signal.data) + pressure_checks = text2num(signal.data["checks"]) + handled=1 + + if("purge" in signal.data) + pressure_checks &= ~1 + pump_direction = 0 + handled=1 + + if("stabilize" in signal.data) + pressure_checks |= 1 + pump_direction = 1 + handled=1 + + if("set_input_pressure" in signal.data) + input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled = 1 + + if("set_output_pressure" in signal.data) + output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled = 1 + + if("set_external_pressure" in signal.data) + external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled = 1 + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + if(!handled) + testing("\[[world.timeofday]\]: dp_vent_pump/receive_signal: unknown command \n[signal.debug_print()]") + spawn(2) + broadcast_status() + update_icon() + +/obj/machinery/atmospherics/binary/dp_vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob) + return ..() + +/obj/machinery/atmospherics/binary/dp_vent_pump/interact(var/mob/user) + update_multitool_menu(user) + +/obj/machinery/atmospherics/binary/dp_vent_pump/canClone(var/obj/O) + return istype(O, /obj/machinery/atmospherics/binary/dp_vent_pump) + +/obj/machinery/atmospherics/binary/dp_vent_pump/clone(var/obj/machinery/atmospherics/binary/dp_vent_pump/O) + id_tag = O.id_tag + set_frequency(O.frequency) + return 1 diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index 442925481d8..5dee3926aed 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -1,156 +1,156 @@ -/obj/machinery/atmospherics/binary/passive_gate - //Tries to achieve target pressure at output (like a normal pump) except - // Uses no power but can not transfer gases from a low pressure area to a high pressure area - icon = 'icons/obj/atmospherics/passive_gate.dmi' - icon_state = "intact_off" - - name = "Passive gate" - desc = "A one-way air valve that does not require power" - - var/on = 0 - var/target_pressure = ONE_ATMOSPHERE - - var/frequency = 0 - var/id_tag = null - var/datum/radio_frequency/radio_connection - -/obj/machinery/atmospherics/binary/passive_gate/update_icon() - if(stat & NOPOWER) - icon_state = "intact_off" - else if(node1 && node2) - icon_state = "intact_[on?("on"):("off")]" - ..() - return - -/obj/machinery/atmospherics/binary/passive_gate/process() - . = ..() - if(!on) - return - - var/output_starting_pressure = air2.return_pressure() - var/input_starting_pressure = air1.return_pressure() - - if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10)) - //No need to pump gas if target is already reached or input pressure is too low - //Need at least 10 KPa difference to overcome friction in the mechanism - return - - //Calculate necessary moles to transfer using PV = nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) - var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2) - //Can not have a pressure delta that would cause output_pressure > input_pressure - - var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - air2.merge(removed) - - if(network1) - network1.update = 1 - - if(network2) - network2.update = 1 - - return 1 - - -//Radio remote control - - -/obj/machinery/atmospherics/binary/passive_gate/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA) - -/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "tag" = id_tag, - "device" = "AGP", - "power" = on, - "target_output" = target_pressure, - "sigtype" = "status" - ) - - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - - return 1 - -/obj/machinery/atmospherics/binary/passive_gate/interact(mob/user as mob) - var/dat = {"Power: [on?"On":"Off"]
- Desirable output pressure: - [round(target_pressure,0.1)]kPa | Change - "} - - user << browse("[src.name] control[dat]", "window=atmo_pump") - onclose(user, "atmo_pump") - -/obj/machinery/atmospherics/binary/passive_gate/initialize() - ..() - if(frequency) - set_frequency(frequency) - -/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal) - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) - return 0 - - var/old_on=on - if("power" in signal.data) - on = text2num(signal.data["power"]) - - if("power_toggle" in signal.data) - on = !on - - if("set_output_pressure" in signal.data) - target_pressure = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - - spawn(2) - broadcast_status() - update_icon() - if(old_on!=on) - investigation_log(I_ATMOS,"was powered [on ? "on" : "off"] by a remote signal") - return - - - -/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob) - if(..()) - return - src.add_fingerprint(usr) - if(!src.allowed(user)) +/obj/machinery/atmospherics/binary/passive_gate + //Tries to achieve target pressure at output (like a normal pump) except + // Uses no power but can not transfer gases from a low pressure area to a high pressure area + icon = 'icons/obj/atmospherics/passive_gate.dmi' + icon_state = "intact_off" + + name = "Passive gate" + desc = "A one-way air valve that does not require power" + + var/on = 0 + var/target_pressure = ONE_ATMOSPHERE + + var/frequency = 0 + var/id_tag = null + var/datum/radio_frequency/radio_connection + +/obj/machinery/atmospherics/binary/passive_gate/update_icon() + if(stat & NOPOWER) + icon_state = "intact_off" + else if(node1 && node2) + icon_state = "intact_[on?("on"):("off")]" + ..() + return + +/obj/machinery/atmospherics/binary/passive_gate/process() + . = ..() + if(!on) + return + + var/output_starting_pressure = air2.return_pressure() + var/input_starting_pressure = air1.return_pressure() + + if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10)) + //No need to pump gas if target is already reached or input pressure is too low + //Need at least 10 KPa difference to overcome friction in the mechanism + return + + //Calculate necessary moles to transfer using PV = nRT + if((air1.total_moles() > 0) && (air1.temperature>0)) + var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2) + //Can not have a pressure delta that would cause output_pressure > input_pressure + + var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed = air1.remove(transfer_moles) + air2.merge(removed) + + if(network1) + network1.update = 1 + + if(network2) + network2.update = 1 + + return 1 + + +//Radio remote control + + +/obj/machinery/atmospherics/binary/passive_gate/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA) + +/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "tag" = id_tag, + "device" = "AGP", + "power" = on, + "target_output" = target_pressure, + "sigtype" = "status" + ) + + radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + + return 1 + +/obj/machinery/atmospherics/binary/passive_gate/interact(mob/user as mob) + var/dat = {"Power: [on?"On":"Off"]
+ Desirable output pressure: + [round(target_pressure,0.1)]kPa | Change + "} + + user << browse("[src.name] control[dat]", "window=atmo_pump") + onclose(user, "atmo_pump") + +/obj/machinery/atmospherics/binary/passive_gate/initialize() + ..() + if(frequency) + set_frequency(frequency) + +/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal) + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) + return 0 + + var/old_on=on + if("power" in signal.data) + on = text2num(signal.data["power"]) + + if("power_toggle" in signal.data) + on = !on + + if("set_output_pressure" in signal.data) + target_pressure = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + + spawn(2) + broadcast_status() + update_icon() + if(old_on!=on) + investigation_log(I_ATMOS,"was powered [on ? "on" : "off"] by a remote signal") + return + + + +/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob) + if(..()) + return + src.add_fingerprint(usr) + if(!src.allowed(user)) to_chat(user, "Access denied.") - return - usr.set_machine(src) - interact(user) - return - -/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list) - if(..()) return - if(href_list["power"]) - on = !on - investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by [key_name(usr)]") - if(href_list["set_press"]) - var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num - src.target_pressure = max(0, min(4500, new_pressure)) - investigation_log(I_ATMOS,"was set to [target_pressure] kPa by [key_name(usr)]") - usr.set_machine(src) - src.update_icon() - src.updateUsrDialog() - return - -/obj/machinery/atmospherics/binary/passive_gate/power_change() - ..() - update_icon() + return + usr.set_machine(src) + interact(user) + return + +/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list) + if(..()) return + if(href_list["power"]) + on = !on + investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by [key_name(usr)]") + if(href_list["set_press"]) + var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num + src.target_pressure = max(0, min(4500, new_pressure)) + investigation_log(I_ATMOS,"was set to [target_pressure] kPa by [key_name(usr)]") + usr.set_machine(src) + src.update_icon() + src.updateUsrDialog() + return + +/obj/machinery/atmospherics/binary/passive_gate/power_change() + ..() + update_icon() diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index f5cbc9dd595..e973f57c380 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -1,176 +1,176 @@ -/* -Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure. - -node1, air1, network1 correspond to input -node2, air2, network2 correspond to output - -Thus, the two variables affect pump operation are set in New(): - air1.volume - This is the volume of gas available to the pump that may be transfered to the output - air2.volume - Higher quantities of this cause more air to be perfected later - but overall network volume is also increased as this increases... -*/ - -/obj/machinery/atmospherics/binary/pump - icon = 'icons/obj/atmospherics/pump.dmi' - icon_state = "intact_off" - - name = "Gas pump" - desc = "A pump." - var/on = 0 - var/target_pressure = ONE_ATMOSPHERE - - var/frequency = 0 - var/id_tag = null - var/datum/radio_frequency/radio_connection - -/obj/machinery/atmospherics/binary/pump/highcap - name = "High capacity gas pump" - desc = "A high capacity pump" - - target_pressure = 15000000 // Holy fuck man - -/obj/machinery/atmospherics/binary/pump/on - on = 1 - icon_state = "intact_on" - -/obj/machinery/atmospherics/binary/pump/update_icon() - if(stat & NOPOWER) - icon_state = "intact_off" - else if(node1 && node2) - icon_state = "intact_[on?("on"):("off")]" - ..() - -/obj/machinery/atmospherics/binary/pump/process() - . = ..() - if((stat & (NOPOWER|BROKEN)) || !on) - return - - var/output_starting_pressure = air2.return_pressure() - - if( (target_pressure - output_starting_pressure) < 0.01) - //No need to pump gas if target is already reached! - return - - //Calculate necessary moles to transfer using PV=nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) - var/pressure_delta = target_pressure - output_starting_pressure - var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - air2.merge(removed) - - if(network1) - network1.update = 1 - - if(network2) - network2.update = 1 - - return 1 - -//Radio remote control - - -/obj/machinery/atmospherics/binary/pump/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA) - -/obj/machinery/atmospherics/binary/pump/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "tag" = id_tag, - "device" = "AGP", - "power" = on, - "target_output" = target_pressure, - "sigtype" = "status" - ) - - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - - return 1 - -/obj/machinery/atmospherics/binary/pump/interact(mob/user as mob) - var/dat = {"Power: [on?"On":"Off"]
- Desirable output pressure: - [round(target_pressure,0.1)]kPa | Change - "} - - user << browse("[src.name] control[dat]", "window=atmo_pump") - onclose(user, "atmo_pump") - -/obj/machinery/atmospherics/binary/pump/initialize() - ..() - if(frequency) - set_frequency(frequency) - -/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal) - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) - return 0 - - if("power" in signal.data) - on = text2num(signal.data["power"]) - - if("power_toggle" in signal.data) - on = !on - - if("set_output_pressure" in signal.data) - target_pressure = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - - spawn(2) - broadcast_status() - update_icon() - investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by signal.") - return - - -/obj/machinery/atmospherics/binary/pump/attack_hand(user as mob) - if(..()) - return - src.add_fingerprint(usr) - if(!src.allowed(user)) +/* +Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure. + +node1, air1, network1 correspond to input +node2, air2, network2 correspond to output + +Thus, the two variables affect pump operation are set in New(): + air1.volume + This is the volume of gas available to the pump that may be transfered to the output + air2.volume + Higher quantities of this cause more air to be perfected later + but overall network volume is also increased as this increases... +*/ + +/obj/machinery/atmospherics/binary/pump + icon = 'icons/obj/atmospherics/pump.dmi' + icon_state = "intact_off" + + name = "Gas pump" + desc = "A pump." + var/on = 0 + var/target_pressure = ONE_ATMOSPHERE + + var/frequency = 0 + var/id_tag = null + var/datum/radio_frequency/radio_connection + +/obj/machinery/atmospherics/binary/pump/highcap + name = "High capacity gas pump" + desc = "A high capacity pump" + + target_pressure = 15000000 // Holy fuck man + +/obj/machinery/atmospherics/binary/pump/on + on = 1 + icon_state = "intact_on" + +/obj/machinery/atmospherics/binary/pump/update_icon() + if(stat & NOPOWER) + icon_state = "intact_off" + else if(node1 && node2) + icon_state = "intact_[on?("on"):("off")]" + ..() + +/obj/machinery/atmospherics/binary/pump/process() + . = ..() + if((stat & (NOPOWER|BROKEN)) || !on) + return + + var/output_starting_pressure = air2.return_pressure() + + if( (target_pressure - output_starting_pressure) < 0.01) + //No need to pump gas if target is already reached! + return + + //Calculate necessary moles to transfer using PV=nRT + if((air1.total_moles() > 0) && (air1.temperature>0)) + var/pressure_delta = target_pressure - output_starting_pressure + var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed = air1.remove(transfer_moles) + air2.merge(removed) + + if(network1) + network1.update = 1 + + if(network2) + network2.update = 1 + + return 1 + +//Radio remote control + + +/obj/machinery/atmospherics/binary/pump/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA) + +/obj/machinery/atmospherics/binary/pump/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "tag" = id_tag, + "device" = "AGP", + "power" = on, + "target_output" = target_pressure, + "sigtype" = "status" + ) + + radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + + return 1 + +/obj/machinery/atmospherics/binary/pump/interact(mob/user as mob) + var/dat = {"Power: [on?"On":"Off"]
+ Desirable output pressure: + [round(target_pressure,0.1)]kPa | Change + "} + + user << browse("[src.name] control[dat]", "window=atmo_pump") + onclose(user, "atmo_pump") + +/obj/machinery/atmospherics/binary/pump/initialize() + ..() + if(frequency) + set_frequency(frequency) + +/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal) + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) + return 0 + + if("power" in signal.data) + on = text2num(signal.data["power"]) + + if("power_toggle" in signal.data) + on = !on + + if("set_output_pressure" in signal.data) + target_pressure = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + + spawn(2) + broadcast_status() + update_icon() + investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by signal.") + return + + +/obj/machinery/atmospherics/binary/pump/attack_hand(user as mob) + if(..()) + return + src.add_fingerprint(usr) + if(!src.allowed(user)) to_chat(user, "Access denied.") - return - usr.set_machine(src) - interact(user) - return - -/obj/machinery/atmospherics/binary/pump/Topic(href,href_list) - if(..()) return - if(href_list["power"]) - on = !on - investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by [key_name(usr)].") - if(href_list["set_press"]) - var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num - src.target_pressure = max(0, min(4500, new_pressure)) - investigation_log(I_ATMOS,"was set to [target_pressure] kPa by [key_name(usr)].") - usr.set_machine(src) - src.update_icon() - src.updateUsrDialog() - return - -/obj/machinery/atmospherics/binary/pump/power_change() - ..() - update_icon() - -/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if (!(stat & NOPOWER) && on) + return + usr.set_machine(src) + interact(user) + return + +/obj/machinery/atmospherics/binary/pump/Topic(href,href_list) + if(..()) return + if(href_list["power"]) + on = !on + investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by [key_name(usr)].") + if(href_list["set_press"]) + var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num + src.target_pressure = max(0, min(4500, new_pressure)) + investigation_log(I_ATMOS,"was set to [target_pressure] kPa by [key_name(usr)].") + usr.set_machine(src) + src.update_icon() + src.updateUsrDialog() + return + +/obj/machinery/atmospherics/binary/pump/power_change() + ..() + update_icon() + +/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + if (!(stat & NOPOWER) && on) to_chat(user, "You cannot unwrench this [src], turn it off first.") - return 1 - return ..() + return 1 + return ..() diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm index 359d73abd85..919d7ed1ad5 100644 --- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm @@ -1,160 +1,160 @@ -/* -Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure. - -node1, air1, network1 correspond to input -node2, air2, network2 correspond to output - -Thus, the two variables affect pump operation are set in New(): - air1.volume - This is the volume of gas available to the pump that may be transfered to the output - air2.volume - Higher quantities of this cause more air to be perfected later - but overall network volume is also increased as this increases... -*/ - -/obj/machinery/atmospherics/binary/volume_pump - icon = 'icons/obj/atmospherics/volume_pump.dmi' - icon_state = "intact_off" - - name = "Volumetric gas pump" - desc = "A volumetric pump" - - var/on = 0 - var/transfer_rate = 200 - - var/frequency = 0 - var/id_tag = null - var/datum/radio_frequency/radio_connection - -/obj/machinery/atmospherics/binary/volume_pump/on - on = 1 - icon_state = "intact_on" - -/obj/machinery/atmospherics/binary/volume_pump/update_icon(var/adjacent_procd) - if(stat & NOPOWER) - icon_state = "intact_off" - else if(node1 && node2) - icon_state = "intact_[on?("on"):("off")]" - ..() - -/obj/machinery/atmospherics/binary/volume_pump/process() - . = ..() - if((stat & (NOPOWER|BROKEN)) || !on || transfer_rate < 1) - return - -// Pump mechanism just won't do anything if the pressure is too high/too low - - var/input_starting_pressure = air1.return_pressure() - var/output_starting_pressure = air2.return_pressure() - - if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000)) - return - - var/transfer_ratio = max(1, transfer_rate/air1.volume) - - var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio) - - air2.merge(removed) - - if(network1) - network1.update = 1 - - if(network2) - network2.update = 1 - - return 1 - -/obj/machinery/atmospherics/binary/volume_pump/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency) - -/obj/machinery/atmospherics/binary/volume_pump/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "tag" = id_tag, - "device" = "APV", - "power" = on, - "transfer_rate" = transfer_rate, - "sigtype" = "status" - ) - radio_connection.post_signal(src, signal) - - return 1 - -/obj/machinery/atmospherics/binary/volume_pump/interact(mob/user as mob) - var/dat = {"Power: [on?"On":"Off"]
- Desirable output flow: - [round(transfer_rate,1)]l/s | Change - "} - - user << browse("[src.name] control[dat]", "window=atmo_pump") - onclose(user, "atmo_pump") - - - -/obj/machinery/atmospherics/binary/volume_pump/initialize() - ..() - - set_frequency(frequency) - -/obj/machinery/atmospherics/binary/volume_pump/receive_signal(datum/signal/signal) - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) - return 0 - var/old_on=on - if("power" in signal.data) - on = text2num(signal.data["power"]) - - if("power_toggle" in signal.data) - on = !on - - if("set_transfer_rate" in signal.data) - transfer_rate = Clamp(text2num(signal.data["set_transfer_rate"]), 0, air1.volume) - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - - spawn(2) - broadcast_status() - update_icon() - if(old_on!=on) - investigation_log(I_ATMOS,"was powered [on ? "on" : "off"] by a remote signal") - - -/obj/machinery/atmospherics/binary/volume_pump/attack_hand(user as mob) - if(..()) - return - src.add_fingerprint(usr) - if(!src.allowed(user)) +/* +Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure. + +node1, air1, network1 correspond to input +node2, air2, network2 correspond to output + +Thus, the two variables affect pump operation are set in New(): + air1.volume + This is the volume of gas available to the pump that may be transfered to the output + air2.volume + Higher quantities of this cause more air to be perfected later + but overall network volume is also increased as this increases... +*/ + +/obj/machinery/atmospherics/binary/volume_pump + icon = 'icons/obj/atmospherics/volume_pump.dmi' + icon_state = "intact_off" + + name = "Volumetric gas pump" + desc = "A volumetric pump" + + var/on = 0 + var/transfer_rate = 200 + + var/frequency = 0 + var/id_tag = null + var/datum/radio_frequency/radio_connection + +/obj/machinery/atmospherics/binary/volume_pump/on + on = 1 + icon_state = "intact_on" + +/obj/machinery/atmospherics/binary/volume_pump/update_icon(var/adjacent_procd) + if(stat & NOPOWER) + icon_state = "intact_off" + else if(node1 && node2) + icon_state = "intact_[on?("on"):("off")]" + ..() + +/obj/machinery/atmospherics/binary/volume_pump/process() + . = ..() + if((stat & (NOPOWER|BROKEN)) || !on || transfer_rate < 1) + return + +// Pump mechanism just won't do anything if the pressure is too high/too low + + var/input_starting_pressure = air1.return_pressure() + var/output_starting_pressure = air2.return_pressure() + + if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000)) + return + + var/transfer_ratio = max(1, transfer_rate/air1.volume) + + var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio) + + air2.merge(removed) + + if(network1) + network1.update = 1 + + if(network2) + network2.update = 1 + + return 1 + +/obj/machinery/atmospherics/binary/volume_pump/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency) + +/obj/machinery/atmospherics/binary/volume_pump/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "tag" = id_tag, + "device" = "APV", + "power" = on, + "transfer_rate" = transfer_rate, + "sigtype" = "status" + ) + radio_connection.post_signal(src, signal) + + return 1 + +/obj/machinery/atmospherics/binary/volume_pump/interact(mob/user as mob) + var/dat = {"Power: [on?"On":"Off"]
+ Desirable output flow: + [round(transfer_rate,1)]l/s | Change + "} + + user << browse("[src.name] control[dat]", "window=atmo_pump") + onclose(user, "atmo_pump") + + + +/obj/machinery/atmospherics/binary/volume_pump/initialize() + ..() + + set_frequency(frequency) + +/obj/machinery/atmospherics/binary/volume_pump/receive_signal(datum/signal/signal) + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) + return 0 + var/old_on=on + if("power" in signal.data) + on = text2num(signal.data["power"]) + + if("power_toggle" in signal.data) + on = !on + + if("set_transfer_rate" in signal.data) + transfer_rate = Clamp(text2num(signal.data["set_transfer_rate"]), 0, air1.volume) + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + + spawn(2) + broadcast_status() + update_icon() + if(old_on!=on) + investigation_log(I_ATMOS,"was powered [on ? "on" : "off"] by a remote signal") + + +/obj/machinery/atmospherics/binary/volume_pump/attack_hand(user as mob) + if(..()) + return + src.add_fingerprint(usr) + if(!src.allowed(user)) to_chat(user, "Access denied.") - return - usr.set_machine(src) - interact(user) - return - -/obj/machinery/atmospherics/binary/volume_pump/Topic(href,href_list) - if(..()) return - if(href_list["power"]) - on = !on - investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by [key_name(usr)]") - if(href_list["set_transfer_rate"]) - var/new_transfer_rate = input(usr,"Enter new output volume (0-200l/s)","Flow control",src.transfer_rate) as num - src.transfer_rate = max(0, min(200, new_transfer_rate)) - investigation_log(I_ATMOS,"was set to [transfer_rate] L/s by [key_name(usr)]") - usr.set_machine(src) - src.update_icon() - src.updateUsrDialog() - return - -/obj/machinery/atmospherics/binary/volume_pump/power_change() - ..() - update_icon() + return + usr.set_machine(src) + interact(user) + return + +/obj/machinery/atmospherics/binary/volume_pump/Topic(href,href_list) + if(..()) return + if(href_list["power"]) + on = !on + investigation_log(I_ATMOS,"was turned [on ? "on" : "off"] by [key_name(usr)]") + if(href_list["set_transfer_rate"]) + var/new_transfer_rate = input(usr,"Enter new output volume (0-200l/s)","Flow control",src.transfer_rate) as num + src.transfer_rate = max(0, min(200, new_transfer_rate)) + investigation_log(I_ATMOS,"was set to [transfer_rate] L/s by [key_name(usr)]") + usr.set_machine(src) + src.update_icon() + src.updateUsrDialog() + return + +/obj/machinery/atmospherics/binary/volume_pump/power_change() + ..() + update_icon() diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index d8e34f5ffdf..06bf7109865 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -1,223 +1,223 @@ -obj/machinery/atmospherics/trinary/filter - icon = 'icons/obj/atmospherics/filter.dmi' - icon_state = "hintact_off" - name = "Gas filter" - default_colour = "#b70000" - mirror = /obj/machinery/atmospherics/trinary/filter/mirrored - - var/on = 0 - var/temp = null // -- TLE - - var/target_pressure = ONE_ATMOSPHERE - - var/filter_type = 0 -/* -Filter types: --1: Nothing - 0: Plasma: Plasma Toxin, Oxygen Agent B - 1: Oxygen: Oxygen ONLY - 2: Nitrogen: Nitrogen ONLY - 3: Carbon Dioxide: Carbon Dioxide ONLY - 4: Sleeping Agent (N2O) -*/ - - var/frequency = 0 - var/datum/radio_frequency/radio_connection - -obj/machinery/atmospherics/trinary/filter/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) - -obj/machinery/atmospherics/trinary/filter/New() - if(radio_controller) - initialize() - ..() - -obj/machinery/atmospherics/trinary/filter/update_icon() - if(stat & NOPOWER) - icon_state = "hintact_off" - else if(node2 && node3 && node1) - icon_state = "hintact_[on?("on"):("off")]" - else - icon_state = "hintact_off" - on = 0 - ..() - -obj/machinery/atmospherics/trinary/filter/power_change() - var/old_stat = stat - ..() - if(old_stat != stat) - update_icon() - -obj/machinery/atmospherics/trinary/filter/process() - . = ..() - if(!on) - return - - var/output_starting_pressure = air3.return_pressure() - - if(output_starting_pressure >= target_pressure || air2.return_pressure() >= target_pressure ) - //No need to mix if target is already full! - return - - //Calculate necessary moles to transfer using PV=nRT - - var/pressure_delta = target_pressure - output_starting_pressure - var/transfer_moles - - if(air1.temperature > 0) - transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - - if(transfer_moles > 0) - var/datum/gas_mixture/removed = air1.remove(transfer_moles) - - if(!removed) - return - var/datum/gas_mixture/filtered_out = new - filtered_out.temperature = removed.temperature - - switch(filter_type) - if(0) //removing hydrocarbons - filtered_out.toxins = removed.toxins - removed.toxins = 0 - - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - - if(1) //removing O2 - filtered_out.oxygen = removed.oxygen - removed.oxygen = 0 - - if(2) //removing N2 - filtered_out.nitrogen = removed.nitrogen - removed.nitrogen = 0 - - if(3) //removing CO2 - filtered_out.carbon_dioxide = removed.carbon_dioxide - removed.carbon_dioxide = 0 - - if(4)//removing N2O - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/sleeping_agent)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - - else - filtered_out = null - - - air2.merge(filtered_out) - air3.merge(removed) - - if(network2) - network2.update = 1 - - if(network3) - network3.update = 1 - - if(network1) - network1.update = 1 - - return 1 - -obj/machinery/atmospherics/trinary/filter/initialize() - set_frequency(frequency) - ..() - - -obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE - if(..()) - return - - if(!src.allowed(user)) +obj/machinery/atmospherics/trinary/filter + icon = 'icons/obj/atmospherics/filter.dmi' + icon_state = "hintact_off" + name = "Gas filter" + default_colour = "#b70000" + mirror = /obj/machinery/atmospherics/trinary/filter/mirrored + + var/on = 0 + var/temp = null // -- TLE + + var/target_pressure = ONE_ATMOSPHERE + + var/filter_type = 0 +/* +Filter types: +-1: Nothing + 0: Plasma: Plasma Toxin, Oxygen Agent B + 1: Oxygen: Oxygen ONLY + 2: Nitrogen: Nitrogen ONLY + 3: Carbon Dioxide: Carbon Dioxide ONLY + 4: Sleeping Agent (N2O) +*/ + + var/frequency = 0 + var/datum/radio_frequency/radio_connection + +obj/machinery/atmospherics/trinary/filter/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) + +obj/machinery/atmospherics/trinary/filter/New() + if(radio_controller) + initialize() + ..() + +obj/machinery/atmospherics/trinary/filter/update_icon() + if(stat & NOPOWER) + icon_state = "hintact_off" + else if(node2 && node3 && node1) + icon_state = "hintact_[on?("on"):("off")]" + else + icon_state = "hintact_off" + on = 0 + ..() + +obj/machinery/atmospherics/trinary/filter/power_change() + var/old_stat = stat + ..() + if(old_stat != stat) + update_icon() + +obj/machinery/atmospherics/trinary/filter/process() + . = ..() + if(!on) + return + + var/output_starting_pressure = air3.return_pressure() + + if(output_starting_pressure >= target_pressure || air2.return_pressure() >= target_pressure ) + //No need to mix if target is already full! + return + + //Calculate necessary moles to transfer using PV=nRT + + var/pressure_delta = target_pressure - output_starting_pressure + var/transfer_moles + + if(air1.temperature > 0) + transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + + if(transfer_moles > 0) + var/datum/gas_mixture/removed = air1.remove(transfer_moles) + + if(!removed) + return + var/datum/gas_mixture/filtered_out = new + filtered_out.temperature = removed.temperature + + switch(filter_type) + if(0) //removing hydrocarbons + filtered_out.toxins = removed.toxins + removed.toxins = 0 + + if(removed.trace_gases.len>0) + for(var/datum/gas/trace_gas in removed.trace_gases) + if(istype(trace_gas, /datum/gas/oxygen_agent_b)) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + + if(1) //removing O2 + filtered_out.oxygen = removed.oxygen + removed.oxygen = 0 + + if(2) //removing N2 + filtered_out.nitrogen = removed.nitrogen + removed.nitrogen = 0 + + if(3) //removing CO2 + filtered_out.carbon_dioxide = removed.carbon_dioxide + removed.carbon_dioxide = 0 + + if(4)//removing N2O + if(removed.trace_gases.len>0) + for(var/datum/gas/trace_gas in removed.trace_gases) + if(istype(trace_gas, /datum/gas/sleeping_agent)) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + + else + filtered_out = null + + + air2.merge(filtered_out) + air3.merge(removed) + + if(network2) + network2.update = 1 + + if(network3) + network3.update = 1 + + if(network1) + network1.update = 1 + + return 1 + +obj/machinery/atmospherics/trinary/filter/initialize() + set_frequency(frequency) + ..() + + +obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE + if(..()) + return + + if(!src.allowed(user)) to_chat(user, "Access denied.") - return - - var/dat - var/current_filter_type - switch(filter_type) - if(0) - current_filter_type = "Plasma" - if(1) - current_filter_type = "Oxygen" - if(2) - current_filter_type = "Nitrogen" - if(3) - current_filter_type = "Carbon Dioxide" - if(4) - current_filter_type = "Nitrous Oxide" - if(-1) - current_filter_type = "Nothing" - else - current_filter_type = "ERROR - Report this bug to the admin, please!" - - dat += {" - Power: [on?"On":"Off"]
- Filtering: [current_filter_type]

-

Set Filter Type:

- Plasma
- Oxygen
- Nitrogen
- Carbon Dioxide
- Nitrous Oxide
- Nothing
-
Desirable output pressure: - [src.target_pressure]kPa | Change - "} -/* - user << browse("[src.name] control[dat]","window=atmo_filter") - onclose(user, "atmo_filter") - return - - if (src.temp) - dat = text("[]

Clear Screen", src.temp, src) - //else - // src.on != src.on -*/ - user << browse("[src.name] control[dat]", "window=atmo_filter") - onclose(user, "atmo_filter") - return - -obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(href_list["filterset"]) - src.filter_type = text2num(href_list["filterset"]) - if (href_list["temp"]) - src.temp = null - if(href_list["set_press"]) - var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num - src.target_pressure = max(0, min(4500, new_pressure)) - if(href_list["power"]) - on=!on - src.update_icon() - src.updateUsrDialog() -/* - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) -*/ - return - - -/obj/machinery/atmospherics/trinary/filter/mirrored - icon_state = "hintactm_off" - pipe_flags = IS_MIRROR - -/obj/machinery/atmospherics/trinary/filter/mirrored/update_icon(var/adjacent_procd) - ..(adjacent_procd) - if(stat & NOPOWER) - icon_state = "hintactm_off" - else if(!(node2 && node3 && node1)) - on = 0 - icon_state = "hintactm_[on?("on"):("off")]" + return + + var/dat + var/current_filter_type + switch(filter_type) + if(0) + current_filter_type = "Plasma" + if(1) + current_filter_type = "Oxygen" + if(2) + current_filter_type = "Nitrogen" + if(3) + current_filter_type = "Carbon Dioxide" + if(4) + current_filter_type = "Nitrous Oxide" + if(-1) + current_filter_type = "Nothing" + else + current_filter_type = "ERROR - Report this bug to the admin, please!" + + dat += {" + Power: [on?"On":"Off"]
+ Filtering: [current_filter_type]

+

Set Filter Type:

+ Plasma
+ Oxygen
+ Nitrogen
+ Carbon Dioxide
+ Nitrous Oxide
+ Nothing
+
Desirable output pressure: + [src.target_pressure]kPa | Change + "} +/* + user << browse("[src.name] control[dat]","window=atmo_filter") + onclose(user, "atmo_filter") + return + + if (src.temp) + dat = text("[]

Clear Screen", src.temp, src) + //else + // src.on != src.on +*/ + user << browse("[src.name] control[dat]", "window=atmo_filter") + onclose(user, "atmo_filter") + return + +obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if(href_list["filterset"]) + src.filter_type = text2num(href_list["filterset"]) + if (href_list["temp"]) + src.temp = null + if(href_list["set_press"]) + var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num + src.target_pressure = max(0, min(4500, new_pressure)) + if(href_list["power"]) + on=!on + src.update_icon() + src.updateUsrDialog() +/* + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) +*/ + return + + +/obj/machinery/atmospherics/trinary/filter/mirrored + icon_state = "hintactm_off" + pipe_flags = IS_MIRROR + +/obj/machinery/atmospherics/trinary/filter/mirrored/update_icon(var/adjacent_procd) + ..(adjacent_procd) + if(stat & NOPOWER) + icon_state = "hintactm_off" + else if(!(node2 && node3 && node1)) + on = 0 + icon_state = "hintactm_[on?("on"):("off")]" diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 582cd718a30..e7fb924abc4 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -1,155 +1,155 @@ -obj/machinery/atmospherics/trinary/mixer - icon = 'icons/obj/atmospherics/mixer.dmi' - icon_state = "intact_off" - - name = "Gas mixer" - - mirror = /obj/machinery/atmospherics/trinary/mixer/mirrored - - var/on = 0 - - var/target_pressure = ONE_ATMOSPHERE - var/node1_concentration = 0.5 - var/node2_concentration = 0.5 - - //node 3 is the outlet, nodes 1 & 2 are intakes - -obj/machinery/atmospherics/trinary/mixer/update_icon() - if(stat & NOPOWER) - icon_state = "intact_off" - else if(node2 && node3 && node1) - icon_state = "intact_[on?("on"):("off")]" - else - icon_state = "intact_off" - on = 0 - ..() - -obj/machinery/atmospherics/trinary/mixer/power_change() - var/old_stat = stat - ..() - if(old_stat != stat) - update_icon() - -obj/machinery/atmospherics/trinary/mixer/New() - ..() - air3.volume = 300 - - -obj/machinery/atmospherics/trinary/mixer/process() - . = ..() - if(!on) - return - - var/output_starting_pressure = air3.return_pressure() - - if(output_starting_pressure >= target_pressure) - //No need to mix if target is already full! - return - - //Calculate necessary moles to transfer using PV=nRT - - var/pressure_delta = target_pressure - output_starting_pressure - var/transfer_moles1 = 0 - var/transfer_moles2 = 0 - - if(air1.temperature > 0) - transfer_moles1 = (node1_concentration*pressure_delta)*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) - - if(air2.temperature > 0) - transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) - - var/air1_moles = air1.total_moles() - var/air2_moles = air2.total_moles() - - if((air1_moles < transfer_moles1) || (air2_moles < transfer_moles2)) - if(!transfer_moles1 || !transfer_moles2) return - var/ratio = min(air1_moles/transfer_moles1, air2_moles/transfer_moles2) - - transfer_moles1 *= ratio - transfer_moles2 *= ratio - - //Actually transfer the gas - - if(transfer_moles1 > 0) - var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1) - air3.merge(removed1) - - if(transfer_moles2 > 0) - var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2) - air3.merge(removed2) - - if(network1 && transfer_moles1) - network1.update = 1 - - if(network2 && transfer_moles2) - network2.update = 1 - - if(network3) - network3.update = 1 - - return 1 - -obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob) - if(..()) - return - src.add_fingerprint(usr) - if(!src.allowed(user)) +obj/machinery/atmospherics/trinary/mixer + icon = 'icons/obj/atmospherics/mixer.dmi' + icon_state = "intact_off" + + name = "Gas mixer" + + mirror = /obj/machinery/atmospherics/trinary/mixer/mirrored + + var/on = 0 + + var/target_pressure = ONE_ATMOSPHERE + var/node1_concentration = 0.5 + var/node2_concentration = 0.5 + + //node 3 is the outlet, nodes 1 & 2 are intakes + +obj/machinery/atmospherics/trinary/mixer/update_icon() + if(stat & NOPOWER) + icon_state = "intact_off" + else if(node2 && node3 && node1) + icon_state = "intact_[on?("on"):("off")]" + else + icon_state = "intact_off" + on = 0 + ..() + +obj/machinery/atmospherics/trinary/mixer/power_change() + var/old_stat = stat + ..() + if(old_stat != stat) + update_icon() + +obj/machinery/atmospherics/trinary/mixer/New() + ..() + air3.volume = 300 + + +obj/machinery/atmospherics/trinary/mixer/process() + . = ..() + if(!on) + return + + var/output_starting_pressure = air3.return_pressure() + + if(output_starting_pressure >= target_pressure) + //No need to mix if target is already full! + return + + //Calculate necessary moles to transfer using PV=nRT + + var/pressure_delta = target_pressure - output_starting_pressure + var/transfer_moles1 = 0 + var/transfer_moles2 = 0 + + if(air1.temperature > 0) + transfer_moles1 = (node1_concentration*pressure_delta)*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + + if(air2.temperature > 0) + transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) + + var/air1_moles = air1.total_moles() + var/air2_moles = air2.total_moles() + + if((air1_moles < transfer_moles1) || (air2_moles < transfer_moles2)) + if(!transfer_moles1 || !transfer_moles2) return + var/ratio = min(air1_moles/transfer_moles1, air2_moles/transfer_moles2) + + transfer_moles1 *= ratio + transfer_moles2 *= ratio + + //Actually transfer the gas + + if(transfer_moles1 > 0) + var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1) + air3.merge(removed1) + + if(transfer_moles2 > 0) + var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2) + air3.merge(removed2) + + if(network1 && transfer_moles1) + network1.update = 1 + + if(network2 && transfer_moles2) + network2.update = 1 + + if(network3) + network3.update = 1 + + return 1 + +obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob) + if(..()) + return + src.add_fingerprint(usr) + if(!src.allowed(user)) to_chat(user, "Access denied.") - return - usr.set_machine(src) - var/dat = {"Power: [on?"On":"Off"]
- Desirable output pressure: - [target_pressure]kPa | Change -
- Node 1 Concentration: - - - - - [node1_concentration]([node1_concentration*100]%) - + - + -
- Node 2 Concentration: - - - - - [node2_concentration]([node2_concentration*100]%) - + - + - "} - - user << browse("[src.name] control[dat]", "window=atmo_mixer") - onclose(user, "atmo_mixer") - return - -obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list) - if(..()) return - if(href_list["power"]) - on = !on - if(href_list["set_press"]) - var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num - src.target_pressure = max(0, min(4500, new_pressure)) - if(href_list["node1_c"]) - var/value = text2num(href_list["node1_c"]) - src.node1_concentration = max(0, min(1, src.node1_concentration + value)) - src.node2_concentration = max(0, min(1, src.node2_concentration - value)) - if(href_list["node2_c"]) - var/value = text2num(href_list["node2_c"]) - src.node2_concentration = max(0, min(1, src.node2_concentration + value)) - src.node1_concentration = max(0, min(1, src.node1_concentration - value)) - src.update_icon() - src.updateUsrDialog() - return - -/obj/machinery/atmospherics/trinary/mixer/mirrored - icon_state = "intactm_off" - pipe_flags = IS_MIRROR - -/obj/machinery/atmospherics/trinary/mixer/mirrored/update_icon() - ..() - if(stat & NOPOWER) - icon_state = "intactm_off" - else if(node2 && node3 && node1) - icon_state = "intactm_[on?("on"):("off")]" - else - icon_state = "intactm_off" - on = 0 - return + return + usr.set_machine(src) + var/dat = {"Power: [on?"On":"Off"]
+ Desirable output pressure: + [target_pressure]kPa | Change +
+ Node 1 Concentration: + - + - + [node1_concentration]([node1_concentration*100]%) + + + + +
+ Node 2 Concentration: + - + - + [node2_concentration]([node2_concentration*100]%) + + + + + "} + + user << browse("[src.name] control[dat]", "window=atmo_mixer") + onclose(user, "atmo_mixer") + return + +obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list) + if(..()) return + if(href_list["power"]) + on = !on + if(href_list["set_press"]) + var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num + src.target_pressure = max(0, min(4500, new_pressure)) + if(href_list["node1_c"]) + var/value = text2num(href_list["node1_c"]) + src.node1_concentration = max(0, min(1, src.node1_concentration + value)) + src.node2_concentration = max(0, min(1, src.node2_concentration - value)) + if(href_list["node2_c"]) + var/value = text2num(href_list["node2_c"]) + src.node2_concentration = max(0, min(1, src.node2_concentration + value)) + src.node1_concentration = max(0, min(1, src.node1_concentration - value)) + src.update_icon() + src.updateUsrDialog() + return + +/obj/machinery/atmospherics/trinary/mixer/mirrored + icon_state = "intactm_off" + pipe_flags = IS_MIRROR + +/obj/machinery/atmospherics/trinary/mixer/mirrored/update_icon() + ..() + if(stat & NOPOWER) + icon_state = "intactm_off" + else if(node2 && node3 && node1) + icon_state = "intactm_[on?("on"):("off")]" + else + icon_state = "intactm_off" + on = 0 + return diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm index e404e2b5a8c..8608d881a88 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm @@ -1,206 +1,206 @@ -obj/machinery/atmospherics/trinary - dir = SOUTH - initialize_directions = SOUTH|NORTH|WEST - use_power = 1 - - var/datum/gas_mixture/air1 - var/datum/gas_mixture/air2 - var/datum/gas_mixture/air3 - - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/obj/machinery/atmospherics/node3 - - var/datum/pipe_network/network1 - var/datum/pipe_network/network2 - var/datum/pipe_network/network3 - - var/activity_log = "" - -/obj/machinery/atmospherics/trinary/update_icon(var/adjacent_procd) - var/node_list = list(node1,node2,node3) - ..(adjacent_procd,node_list) - -obj/machinery/atmospherics/trinary/New() - ..() - initialize_directions() - air1 = new - air2 = new - air3 = new - air1.volume = starting_volume - air2.volume = starting_volume - air3.volume = starting_volume - -/obj/machinery/atmospherics/trinary/proc/initialize_directions() - switch(dir) - if(NORTH) - initialize_directions = SOUTH|NORTH|EAST - if(SOUTH) - initialize_directions = NORTH|SOUTH|WEST - if(EAST) - initialize_directions = WEST|EAST|SOUTH - if(WEST) - initialize_directions = EAST|WEST|NORTH - -obj/machinery/atmospherics/trinary/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - if(!(pipe.dir in list(NORTH, SOUTH, EAST, WEST)) && src.mirror) //because the dir isn't in the right set, we want to make the mirror kind - var/obj/machinery/atmospherics/trinary/mirrored_pipe = new mirror(src.loc) - pipe.dir = turn(pipe.dir, -45) - qdel(src) - mirrored_pipe.setPipingLayer(pipe.piping_layer) - return mirrored_pipe.buildFrom(usr, pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - if (pipe.pipename) - name = pipe.pipename - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize() - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - if (node3) - node3.initialize() - node3.build_network() - return 1 - -// Housekeeping and pipe network stuff below -obj/machinery/atmospherics/trinary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - if(reference == node1) - network1 = new_network - - else if(reference == node2) - network2 = new_network - - else if (reference == node3) - network3 = new_network - - if(new_network.normal_members.Find(src)) - return 0 - - new_network.normal_members += src - - return null - -obj/machinery/atmospherics/trinary/Destroy() - if(node1) - node1.disconnect(src) - if(network1) - returnToPool(network1) - if(node2) - node2.disconnect(src) - if(network2) - returnToPool(network2) - if(node3) - node3.disconnect(src) - if(network3) - returnToPool(network3) - - node1 = null - node2 = null - node3 = null - - ..() - -obj/machinery/atmospherics/trinary/initialize() - if(node1 && node2 && node3) return - - //mirrored pipes face the same way and have their nodes in the same place - //The 1 and 3 nodes are reversed, however. - // 1 3 - // 2-- becomes 2-- facing south, for example - // 3 1 - if(!(pipe_flags & IS_MIRROR)) - node1 = findConnecting(turn(dir, -180)) - node2 = findConnecting(turn(dir, -90)) - node3 = findConnecting(dir) - else - node1 = findConnecting(dir) - node2 = findConnecting(turn(dir, -90)) - node3 = findConnecting(turn(dir, -180)) - - - update_icon() - -obj/machinery/atmospherics/trinary/build_network() - if(!network1 && node1) - network1 = getFromPool(/datum/pipe_network) - network1.normal_members += src - network1.build_network(node1, src) - - if(!network2 && node2) - network2 = getFromPool(/datum/pipe_network) - network2.normal_members += src - network2.build_network(node2, src) - - if(!network3 && node3) - network3 = getFromPool(/datum/pipe_network) - network3.normal_members += src - network3.build_network(node3, src) - - -obj/machinery/atmospherics/trinary/return_network(obj/machinery/atmospherics/reference) - build_network() - - if(reference==node1) - return network1 - - if(reference==node2) - return network2 - - if(reference==node3) - return network3 - - return null - -obj/machinery/atmospherics/trinary/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) - if(network1 == old_network) - network1 = new_network - if(network2 == old_network) - network2 = new_network - if(network3 == old_network) - network3 = new_network - - return 1 - -obj/machinery/atmospherics/trinary/return_network_air(datum/pipe_network/reference) - var/list/results = list() - - if(network1 == reference) - results += air1 - if(network2 == reference) - results += air2 - if(network3 == reference) - results += air3 - - return results - -obj/machinery/atmospherics/trinary/disconnect(obj/machinery/atmospherics/reference) - if(reference==node1) - if(network1) - returnToPool(network1) - node1 = null - - else if(reference==node2) - if(network2) - returnToPool(network2) - node2 = null - - else if(reference==node3) - if(network3) - returnToPool(network3) - node3 = null - - return null - -/obj/machinery/atmospherics/trinary/unassign_network(datum/pipe_network/reference) - if(network1 == reference) - network1 = null - if(network2 == reference) - network2 = null - if(network3 == reference) +obj/machinery/atmospherics/trinary + dir = SOUTH + initialize_directions = SOUTH|NORTH|WEST + use_power = 1 + + var/datum/gas_mixture/air1 + var/datum/gas_mixture/air2 + var/datum/gas_mixture/air3 + + var/obj/machinery/atmospherics/node1 + var/obj/machinery/atmospherics/node2 + var/obj/machinery/atmospherics/node3 + + var/datum/pipe_network/network1 + var/datum/pipe_network/network2 + var/datum/pipe_network/network3 + + var/activity_log = "" + +/obj/machinery/atmospherics/trinary/update_icon(var/adjacent_procd) + var/node_list = list(node1,node2,node3) + ..(adjacent_procd,node_list) + +obj/machinery/atmospherics/trinary/New() + ..() + initialize_directions() + air1 = new + air2 = new + air3 = new + air1.volume = starting_volume + air2.volume = starting_volume + air3.volume = starting_volume + +/obj/machinery/atmospherics/trinary/proc/initialize_directions() + switch(dir) + if(NORTH) + initialize_directions = SOUTH|NORTH|EAST + if(SOUTH) + initialize_directions = NORTH|SOUTH|WEST + if(EAST) + initialize_directions = WEST|EAST|SOUTH + if(WEST) + initialize_directions = EAST|WEST|NORTH + +obj/machinery/atmospherics/trinary/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + if(!(pipe.dir in list(NORTH, SOUTH, EAST, WEST)) && src.mirror) //because the dir isn't in the right set, we want to make the mirror kind + var/obj/machinery/atmospherics/trinary/mirrored_pipe = new mirror(src.loc) + pipe.dir = turn(pipe.dir, -45) + qdel(src) + mirrored_pipe.setPipingLayer(pipe.piping_layer) + return mirrored_pipe.buildFrom(usr, pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + if (pipe.pipename) + name = pipe.pipename + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize() + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + if (node3) + node3.initialize() + node3.build_network() + return 1 + +// Housekeeping and pipe network stuff below +obj/machinery/atmospherics/trinary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + if(reference == node1) + network1 = new_network + + else if(reference == node2) + network2 = new_network + + else if (reference == node3) + network3 = new_network + + if(new_network.normal_members.Find(src)) + return 0 + + new_network.normal_members += src + + return null + +obj/machinery/atmospherics/trinary/Destroy() + if(node1) + node1.disconnect(src) + if(network1) + returnToPool(network1) + if(node2) + node2.disconnect(src) + if(network2) + returnToPool(network2) + if(node3) + node3.disconnect(src) + if(network3) + returnToPool(network3) + + node1 = null + node2 = null + node3 = null + + ..() + +obj/machinery/atmospherics/trinary/initialize() + if(node1 && node2 && node3) return + + //mirrored pipes face the same way and have their nodes in the same place + //The 1 and 3 nodes are reversed, however. + // 1 3 + // 2-- becomes 2-- facing south, for example + // 3 1 + if(!(pipe_flags & IS_MIRROR)) + node1 = findConnecting(turn(dir, -180)) + node2 = findConnecting(turn(dir, -90)) + node3 = findConnecting(dir) + else + node1 = findConnecting(dir) + node2 = findConnecting(turn(dir, -90)) + node3 = findConnecting(turn(dir, -180)) + + + update_icon() + +obj/machinery/atmospherics/trinary/build_network() + if(!network1 && node1) + network1 = getFromPool(/datum/pipe_network) + network1.normal_members += src + network1.build_network(node1, src) + + if(!network2 && node2) + network2 = getFromPool(/datum/pipe_network) + network2.normal_members += src + network2.build_network(node2, src) + + if(!network3 && node3) + network3 = getFromPool(/datum/pipe_network) + network3.normal_members += src + network3.build_network(node3, src) + + +obj/machinery/atmospherics/trinary/return_network(obj/machinery/atmospherics/reference) + build_network() + + if(reference==node1) + return network1 + + if(reference==node2) + return network2 + + if(reference==node3) + return network3 + + return null + +obj/machinery/atmospherics/trinary/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) + if(network1 == old_network) + network1 = new_network + if(network2 == old_network) + network2 = new_network + if(network3 == old_network) + network3 = new_network + + return 1 + +obj/machinery/atmospherics/trinary/return_network_air(datum/pipe_network/reference) + var/list/results = list() + + if(network1 == reference) + results += air1 + if(network2 == reference) + results += air2 + if(network3 == reference) + results += air3 + + return results + +obj/machinery/atmospherics/trinary/disconnect(obj/machinery/atmospherics/reference) + if(reference==node1) + if(network1) + returnToPool(network1) + node1 = null + + else if(reference==node2) + if(network2) + returnToPool(network2) + node2 = null + + else if(reference==node3) + if(network3) + returnToPool(network3) + node3 = null + + return null + +/obj/machinery/atmospherics/trinary/unassign_network(datum/pipe_network/reference) + if(network1 == reference) + network1 = null + if(network2 == reference) + network2 = null + if(network3 == reference) network3 = null \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm index e90ead21ad6..33cec462690 100644 --- a/code/ATMOSPHERICS/components/unary/cold_sink.dm +++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm @@ -1,33 +1,33 @@ -/obj/machinery/atmospherics/unary/cold_sink - icon = 'icons/obj/atmospherics/cold_sink.dmi' - icon_state = "on_cool" - density = 1 - use_power = 1 - - name = "Cold Sink" - desc = "Cools gas when connected to pipe network" - - var/on = 0 - - var/current_temperature = T20C - var/current_heat_capacity = 50000 //totally random - - -/obj/machinery/atmospherics/unary/cold_sink/process() - . = ..() - if(!on || !network) - return - var/air_heat_capacity = air_contents.heat_capacity() - var/combined_heat_capacity = current_heat_capacity + air_heat_capacity - var/old_temperature = air_contents.temperature - - if(combined_heat_capacity > 0) - var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature - if(air_contents.temperature > current_temperature) //if it's hotter than we can cool it, cool it - air_contents.temperature = combined_energy/combined_heat_capacity - - //todo: have current temperature affected. require power to bring down current temperature again - - if(abs(old_temperature-air_contents.temperature) > 1) - network.update = 1 +/obj/machinery/atmospherics/unary/cold_sink + icon = 'icons/obj/atmospherics/cold_sink.dmi' + icon_state = "on_cool" + density = 1 + use_power = 1 + + name = "Cold Sink" + desc = "Cools gas when connected to pipe network" + + var/on = 0 + + var/current_temperature = T20C + var/current_heat_capacity = 50000 //totally random + + +/obj/machinery/atmospherics/unary/cold_sink/process() + . = ..() + if(!on || !network) + return + var/air_heat_capacity = air_contents.heat_capacity() + var/combined_heat_capacity = current_heat_capacity + air_heat_capacity + var/old_temperature = air_contents.temperature + + if(combined_heat_capacity > 0) + var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature + if(air_contents.temperature > current_temperature) //if it's hotter than we can cool it, cool it + air_contents.temperature = combined_energy/combined_heat_capacity + + //todo: have current temperature affected. require power to bring down current temperature again + + if(abs(old_temperature-air_contents.temperature) > 1) + network.update = 1 return 1 \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/generator_input.dm b/code/ATMOSPHERICS/components/unary/generator_input.dm index 2b31097dc41..3a4d11428bb 100644 --- a/code/ATMOSPHERICS/components/unary/generator_input.dm +++ b/code/ATMOSPHERICS/components/unary/generator_input.dm @@ -1,21 +1,21 @@ -/obj/machinery/atmospherics/unary/generator_input - icon = 'icons/obj/atmospherics/heat_exchanger.dmi' - icon_state = "intact" - density = 1 - - name = "Generator Input" - desc = "Placeholder" - - var/update_cycle - - update_icon() - if(node) - icon_state = "intact" - else - icon_state = "exposed" - - return - - proc - return_exchange_air() +/obj/machinery/atmospherics/unary/generator_input + icon = 'icons/obj/atmospherics/heat_exchanger.dmi' + icon_state = "intact" + density = 1 + + name = "Generator Input" + desc = "Placeholder" + + var/update_cycle + + update_icon() + if(node) + icon_state = "intact" + else + icon_state = "exposed" + + return + + proc + return_exchange_air() return air_contents \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm index e72979f51bb..b8b58697630 100644 --- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm +++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm @@ -1,63 +1,63 @@ -/obj/machinery/atmospherics/unary/heat_exchanger - - icon = 'icons/obj/atmospherics/heat_exchanger.dmi' - icon_state = "intact" - density = 1 - - name = "Heat Exchanger" - desc = "Exchanges heat between two input gases. Setup for fast heat transfer" - - var/obj/machinery/atmospherics/unary/heat_exchanger/partner = null - var/update_cycle - -/obj/machinery/atmospherics/unary/heat_exchanger/update_icon() - if(node) - icon_state = "intact" - else - icon_state = "exposed" - ..() - return - -/obj/machinery/atmospherics/unary/heat_exchanger/initialize() - if(!partner) - var/partner_connect = turn(dir,180) - - for(var/obj/machinery/atmospherics/unary/heat_exchanger/target in get_step(src,partner_connect)) - if(target.dir & get_dir(src,target)) - partner = target - partner.partner = src - break - - ..() - -/obj/machinery/atmospherics/unary/heat_exchanger/process() - . = ..() - if(!partner || !air_master || air_master.current_cycle <= update_cycle) - return - - update_cycle = air_master.current_cycle - partner.update_cycle = air_master.current_cycle - - var/air_heat_capacity = air_contents.heat_capacity() - var/other_air_heat_capacity = partner.air_contents.heat_capacity() - var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity - - var/old_temperature = air_contents.temperature - var/other_old_temperature = partner.air_contents.temperature - - if(combined_heat_capacity > 0) - var/combined_energy = partner.air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature - - var/new_temperature = combined_energy/combined_heat_capacity - air_contents.temperature = new_temperature - partner.air_contents.temperature = new_temperature - - if(network) - if(abs(old_temperature-air_contents.temperature) > 1) - network.update = 1 - - if(partner.network) - if(abs(other_old_temperature-partner.air_contents.temperature) > 1) - partner.network.update = 1 - - return 1 +/obj/machinery/atmospherics/unary/heat_exchanger + + icon = 'icons/obj/atmospherics/heat_exchanger.dmi' + icon_state = "intact" + density = 1 + + name = "Heat Exchanger" + desc = "Exchanges heat between two input gases. Setup for fast heat transfer" + + var/obj/machinery/atmospherics/unary/heat_exchanger/partner = null + var/update_cycle + +/obj/machinery/atmospherics/unary/heat_exchanger/update_icon() + if(node) + icon_state = "intact" + else + icon_state = "exposed" + ..() + return + +/obj/machinery/atmospherics/unary/heat_exchanger/initialize() + if(!partner) + var/partner_connect = turn(dir,180) + + for(var/obj/machinery/atmospherics/unary/heat_exchanger/target in get_step(src,partner_connect)) + if(target.dir & get_dir(src,target)) + partner = target + partner.partner = src + break + + ..() + +/obj/machinery/atmospherics/unary/heat_exchanger/process() + . = ..() + if(!partner || !air_master || air_master.current_cycle <= update_cycle) + return + + update_cycle = air_master.current_cycle + partner.update_cycle = air_master.current_cycle + + var/air_heat_capacity = air_contents.heat_capacity() + var/other_air_heat_capacity = partner.air_contents.heat_capacity() + var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity + + var/old_temperature = air_contents.temperature + var/other_old_temperature = partner.air_contents.temperature + + if(combined_heat_capacity > 0) + var/combined_energy = partner.air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature + + var/new_temperature = combined_energy/combined_heat_capacity + air_contents.temperature = new_temperature + partner.air_contents.temperature = new_temperature + + if(network) + if(abs(old_temperature-air_contents.temperature) > 1) + network.update = 1 + + if(partner.network) + if(abs(other_old_temperature-partner.air_contents.temperature) > 1) + partner.network.update = 1 + + return 1 diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm index bee01c10d71..3663539ae5d 100644 --- a/code/ATMOSPHERICS/components/unary/heat_source.dm +++ b/code/ATMOSPHERICS/components/unary/heat_source.dm @@ -1,35 +1,35 @@ -/obj/machinery/atmospherics/unary/heat_reservoir -//currently the same code as cold_sink but anticipating process() changes - - icon = 'icons/obj/atmospherics/cold_sink.dmi' - icon_state = "intact_off" - density = 1 - use_power = 1 - - name = "Heat Reservoir" - desc = "Heats gas when connected to pipe network" - - var/on = 0 - - var/current_temperature = T20C - var/current_heat_capacity = 50000 //totally random - - -/obj/machinery/atmospherics/unary/heat_reservoir/process() - . = ..() - if(!on) - return - var/air_heat_capacity = air_contents.heat_capacity() - var/combined_heat_capacity = current_heat_capacity + air_heat_capacity - var/old_temperature = air_contents.temperature - - if(combined_heat_capacity > 0) - var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature - if(air_contents.temperature < current_temperature) //if its colder than we can heat it, heat it - air_contents.temperature = combined_energy/combined_heat_capacity - - //todo: have current temperature affected. require power to bring up current temperature again - - if(abs(old_temperature-air_contents.temperature) > 1) - network.update = 1 +/obj/machinery/atmospherics/unary/heat_reservoir +//currently the same code as cold_sink but anticipating process() changes + + icon = 'icons/obj/atmospherics/cold_sink.dmi' + icon_state = "intact_off" + density = 1 + use_power = 1 + + name = "Heat Reservoir" + desc = "Heats gas when connected to pipe network" + + var/on = 0 + + var/current_temperature = T20C + var/current_heat_capacity = 50000 //totally random + + +/obj/machinery/atmospherics/unary/heat_reservoir/process() + . = ..() + if(!on) + return + var/air_heat_capacity = air_contents.heat_capacity() + var/combined_heat_capacity = current_heat_capacity + air_heat_capacity + var/old_temperature = air_contents.temperature + + if(combined_heat_capacity > 0) + var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature + if(air_contents.temperature < current_temperature) //if its colder than we can heat it, heat it + air_contents.temperature = combined_energy/combined_heat_capacity + + //todo: have current temperature affected. require power to bring up current temperature again + + if(abs(old_temperature-air_contents.temperature) > 1) + network.update = 1 return 1 \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm index fc7c16421fb..a9f0d863faf 100644 --- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm +++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm @@ -1,180 +1,180 @@ -/obj/machinery/atmospherics/unary/outlet_injector - icon = 'icons/obj/atmospherics/outlet_injector.dmi' - icon_state = "off" - use_power = 1 - - name = "Air Injector" - desc = "Has a valve and pump attached to it." - - var/on = 0 - var/injecting = 0 - - var/volume_rate = 50 - var/max_rate=50 - - var/frequency = 0 - var/id_tag = null - var/datum/radio_frequency/radio_connection - - level = 1 - - machine_flags = MULTITOOL_MENU - -/obj/machinery/atmospherics/unary/outlet_injector/update_icon() - if(node) - if(on && !(stat & NOPOWER)) - icon_state = "hon" - else - icon_state = "hoff" - else - icon_state = "exposed" - on = 0 - ..() - if (istype(loc, /turf/simulated/floor) && node) - var/turf/simulated/floor/floor = loc - if(floor.floor_tile && node.alpha == 128) - underlays.Cut() - return - -/obj/machinery/atmospherics/unary/outlet_injector/power_change() - var/old_stat = stat - ..() - if(old_stat != stat) - update_icon() - - -/obj/machinery/atmospherics/unary/outlet_injector/process() - . = ..() - injecting = 0 - - if(!on || stat & NOPOWER) - return - - if(air_contents.temperature > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - loc.assume_air(removed) - - if(network) - network.update = 1 - - return 1 - -/obj/machinery/atmospherics/unary/outlet_injector/proc/inject() - if(on || injecting) - return 0 - - injecting = 1 - - if(air_contents.temperature > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - loc.assume_air(removed) - - if(network) - network.update = 1 - - flick("inject", src) - -/obj/machinery/atmospherics/unary/outlet_injector/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency) - -/obj/machinery/atmospherics/unary/outlet_injector/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "tag" = id_tag, - "device" = "AO", - "power" = on, - "volume_rate" = volume_rate, - //"timestamp" = world.time, - "sigtype" = "status" - ) - - radio_connection.post_signal(src, signal) - - return 1 - -/obj/machinery/atmospherics/unary/outlet_injector/initialize() - ..() - - set_frequency(frequency) - -/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal) - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "injector")) - return 0 - - if("power" in signal.data) - on = text2num(signal.data["power"]) - - if("power_toggle" in signal.data) - on = !on - - if("inject" in signal.data) - spawn inject() - return - - if("set_volume_rate" in signal.data) - var/number = text2num(signal.data["set_volume_rate"]) - volume_rate = Clamp(number, 0, air_contents.volume) - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - - //log_admin("DEBUG \[[world.timeofday]\]: outlet_injector/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") - //return - spawn(2) - broadcast_status() - update_icon() - -/obj/machinery/atmospherics/unary/outlet_injector/hide(var/i) //to make the little pipe section invisible, the icon changes. - if(node) - if(on) - icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on" - else - icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off" - else - icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]exposed" - on = 0 - return - -/obj/machinery/atmospherics/unary/outlet_injector/interact(mob/user as mob) - update_multitool_menu(user) - -/obj/machinery/atmospherics/unary/outlet_injector/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return {" - -"} - -/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if (!(stat & NOPOWER) && on) +/obj/machinery/atmospherics/unary/outlet_injector + icon = 'icons/obj/atmospherics/outlet_injector.dmi' + icon_state = "off" + use_power = 1 + + name = "Air Injector" + desc = "Has a valve and pump attached to it." + + var/on = 0 + var/injecting = 0 + + var/volume_rate = 50 + var/max_rate=50 + + var/frequency = 0 + var/id_tag = null + var/datum/radio_frequency/radio_connection + + level = 1 + + machine_flags = MULTITOOL_MENU + +/obj/machinery/atmospherics/unary/outlet_injector/update_icon() + if(node) + if(on && !(stat & NOPOWER)) + icon_state = "hon" + else + icon_state = "hoff" + else + icon_state = "exposed" + on = 0 + ..() + if (istype(loc, /turf/simulated/floor) && node) + var/turf/simulated/floor/floor = loc + if(floor.floor_tile && node.alpha == 128) + underlays.Cut() + return + +/obj/machinery/atmospherics/unary/outlet_injector/power_change() + var/old_stat = stat + ..() + if(old_stat != stat) + update_icon() + + +/obj/machinery/atmospherics/unary/outlet_injector/process() + . = ..() + injecting = 0 + + if(!on || stat & NOPOWER) + return + + if(air_contents.temperature > 0) + var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) + + loc.assume_air(removed) + + if(network) + network.update = 1 + + return 1 + +/obj/machinery/atmospherics/unary/outlet_injector/proc/inject() + if(on || injecting) + return 0 + + injecting = 1 + + if(air_contents.temperature > 0) + var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) + + loc.assume_air(removed) + + if(network) + network.update = 1 + + flick("inject", src) + +/obj/machinery/atmospherics/unary/outlet_injector/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency) + +/obj/machinery/atmospherics/unary/outlet_injector/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "tag" = id_tag, + "device" = "AO", + "power" = on, + "volume_rate" = volume_rate, + //"timestamp" = world.time, + "sigtype" = "status" + ) + + radio_connection.post_signal(src, signal) + + return 1 + +/obj/machinery/atmospherics/unary/outlet_injector/initialize() + ..() + + set_frequency(frequency) + +/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal) + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "injector")) + return 0 + + if("power" in signal.data) + on = text2num(signal.data["power"]) + + if("power_toggle" in signal.data) + on = !on + + if("inject" in signal.data) + spawn inject() + return + + if("set_volume_rate" in signal.data) + var/number = text2num(signal.data["set_volume_rate"]) + volume_rate = Clamp(number, 0, air_contents.volume) + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + + //log_admin("DEBUG \[[world.timeofday]\]: outlet_injector/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") + //return + spawn(2) + broadcast_status() + update_icon() + +/obj/machinery/atmospherics/unary/outlet_injector/hide(var/i) //to make the little pipe section invisible, the icon changes. + if(node) + if(on) + icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on" + else + icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off" + else + icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]exposed" + on = 0 + return + +/obj/machinery/atmospherics/unary/outlet_injector/interact(mob/user as mob) + update_multitool_menu(user) + +/obj/machinery/atmospherics/unary/outlet_injector/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return {" + +"} + +/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + if (!(stat & NOPOWER) && on) to_chat(user, "You cannot unwrench this [src], turn it off first.") - return 1 - return ..() - -/obj/machinery/atmospherics/unary/outlet_injector/canClone(var/obj/O) - return istype(O, /obj/machinery/atmospherics/unary/outlet_injector) - -/obj/machinery/atmospherics/unary/outlet_injector/clone(var/obj/machinery/atmospherics/unary/outlet_injector/O) - id_tag = O.id_tag - set_frequency(O.frequency) - return 1 + return 1 + return ..() + +/obj/machinery/atmospherics/unary/outlet_injector/canClone(var/obj/O) + return istype(O, /obj/machinery/atmospherics/unary/outlet_injector) + +/obj/machinery/atmospherics/unary/outlet_injector/clone(var/obj/machinery/atmospherics/unary/outlet_injector/O) + id_tag = O.id_tag + set_frequency(O.frequency) + return 1 diff --git a/code/ATMOSPHERICS/components/unary/oxygen_generator.dm b/code/ATMOSPHERICS/components/unary/oxygen_generator.dm index 355251849f4..9e93b230236 100644 --- a/code/ATMOSPHERICS/components/unary/oxygen_generator.dm +++ b/code/ATMOSPHERICS/components/unary/oxygen_generator.dm @@ -1,49 +1,49 @@ -obj/machinery/atmospherics/unary/oxygen_generator - icon = 'icons/obj/atmospherics/oxygen_generator.dmi' - icon_state = "intact_off" - density = 1 - - name = "Oxygen Generator" - desc = "" - - dir = SOUTH - initialize_directions = SOUTH - - var/on = 0 - - var/oxygen_content = 10 - -obj/machinery/atmospherics/unary/oxygen_generator/update_icon() - if(node) - icon_state = "intact_[on?("on"):("off")]" - else - icon_state = "exposed_off" - - on = 0 - - return - -obj/machinery/atmospherics/unary/oxygen_generator/New() - ..() - - air_contents.volume = 50 - -obj/machinery/atmospherics/unary/oxygen_generator/process() - . = ..() - if(!on) - return - - var/total_moles = air_contents.total_moles() - - if(total_moles < oxygen_content) - var/current_heat_capacity = air_contents.heat_capacity() - - var/added_oxygen = oxygen_content - total_moles - - air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen) - air_contents.oxygen += added_oxygen - - if(network) - network.update = 1 - +obj/machinery/atmospherics/unary/oxygen_generator + icon = 'icons/obj/atmospherics/oxygen_generator.dmi' + icon_state = "intact_off" + density = 1 + + name = "Oxygen Generator" + desc = "" + + dir = SOUTH + initialize_directions = SOUTH + + var/on = 0 + + var/oxygen_content = 10 + +obj/machinery/atmospherics/unary/oxygen_generator/update_icon() + if(node) + icon_state = "intact_[on?("on"):("off")]" + else + icon_state = "exposed_off" + + on = 0 + + return + +obj/machinery/atmospherics/unary/oxygen_generator/New() + ..() + + air_contents.volume = 50 + +obj/machinery/atmospherics/unary/oxygen_generator/process() + . = ..() + if(!on) + return + + var/total_moles = air_contents.total_moles() + + if(total_moles < oxygen_content) + var/current_heat_capacity = air_contents.heat_capacity() + + var/added_oxygen = oxygen_content - total_moles + + air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen) + air_contents.oxygen += added_oxygen + + if(network) + network.update = 1 + return 1 \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm index 5afb9c975a4..e69b0fe8262 100644 --- a/code/ATMOSPHERICS/components/unary/unary_base.dm +++ b/code/ATMOSPHERICS/components/unary/unary_base.dm @@ -1,96 +1,96 @@ -/obj/machinery/atmospherics/unary - dir = SOUTH - initialize_directions = SOUTH - layer = 2.45 // Cable says we're at 2.45, so we're at 2.45. (old: TURF_LAYER+0.1) - - var/datum/gas_mixture/air_contents - var/obj/machinery/atmospherics/node - var/datum/pipe_network/network - -/obj/machinery/atmospherics/unary/New() - ..() - initialize_directions = dir - air_contents = new - - air_contents.temperature = T0C - air_contents.volume = starting_volume - -/obj/machinery/atmospherics/unary/update_icon(var/adjacent_procd,node_list) - node_list = list(node) - ..(adjacent_procd,node_list) - -/obj/machinery/atmospherics/unary/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - if (pipe.pipename) - name = pipe.pipename - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize() - build_network() - if (node) - node.initialize() - node.build_network() - return 1 - -// Housekeeping and pipe network stuff below -/obj/machinery/atmospherics/unary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - if(reference == node) - network = new_network - if(new_network.normal_members.Find(src)) - return 0 - new_network.normal_members += src - return null - -/obj/machinery/atmospherics/unary/Destroy() - if(node) - node.disconnect(src) - if(network) - returnToPool(network) - node = null - ..() - -/obj/machinery/atmospherics/unary/initialize() - if(node) return - var/node_connect = dir - for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - if(target.piping_layer == piping_layer || target.pipe_flags & ALL_LAYER) - node = target - break - update_icon() - -/obj/machinery/atmospherics/unary/build_network() - if(!network && node) - network = getFromPool(/datum/pipe_network) - network.normal_members += src - network.build_network(node, src) - - -/obj/machinery/atmospherics/unary/return_network(obj/machinery/atmospherics/reference) - build_network() - if(reference == node || reference == src) - return network - return null - -/obj/machinery/atmospherics/unary/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) - if(network == old_network) - network = new_network - return 1 - -/obj/machinery/atmospherics/unary/return_network_air(datum/pipe_network/reference) - var/list/results = list() - if(network == reference) - results += air_contents - return results - -/obj/machinery/atmospherics/unary/disconnect(obj/machinery/atmospherics/reference) - if(reference==node) - if(network) - returnToPool(network) - node = null - return null - -/obj/machinery/atmospherics/unary/unassign_network(datum/pipe_network/reference) - if(network == reference) +/obj/machinery/atmospherics/unary + dir = SOUTH + initialize_directions = SOUTH + layer = 2.45 // Cable says we're at 2.45, so we're at 2.45. (old: TURF_LAYER+0.1) + + var/datum/gas_mixture/air_contents + var/obj/machinery/atmospherics/node + var/datum/pipe_network/network + +/obj/machinery/atmospherics/unary/New() + ..() + initialize_directions = dir + air_contents = new + + air_contents.temperature = T0C + air_contents.volume = starting_volume + +/obj/machinery/atmospherics/unary/update_icon(var/adjacent_procd,node_list) + node_list = list(node) + ..(adjacent_procd,node_list) + +/obj/machinery/atmospherics/unary/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + if (pipe.pipename) + name = pipe.pipename + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize() + build_network() + if (node) + node.initialize() + node.build_network() + return 1 + +// Housekeeping and pipe network stuff below +/obj/machinery/atmospherics/unary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + if(reference == node) + network = new_network + if(new_network.normal_members.Find(src)) + return 0 + new_network.normal_members += src + return null + +/obj/machinery/atmospherics/unary/Destroy() + if(node) + node.disconnect(src) + if(network) + returnToPool(network) + node = null + ..() + +/obj/machinery/atmospherics/unary/initialize() + if(node) return + var/node_connect = dir + for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) + if(target.initialize_directions & get_dir(target,src)) + if(target.piping_layer == piping_layer || target.pipe_flags & ALL_LAYER) + node = target + break + update_icon() + +/obj/machinery/atmospherics/unary/build_network() + if(!network && node) + network = getFromPool(/datum/pipe_network) + network.normal_members += src + network.build_network(node, src) + + +/obj/machinery/atmospherics/unary/return_network(obj/machinery/atmospherics/reference) + build_network() + if(reference == node || reference == src) + return network + return null + +/obj/machinery/atmospherics/unary/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network) + if(network == old_network) + network = new_network + return 1 + +/obj/machinery/atmospherics/unary/return_network_air(datum/pipe_network/reference) + var/list/results = list() + if(network == reference) + results += air_contents + return results + +/obj/machinery/atmospherics/unary/disconnect(obj/machinery/atmospherics/reference) + if(reference==node) + if(network) + returnToPool(network) + node = null + return null + +/obj/machinery/atmospherics/unary/unassign_network(datum/pipe_network/reference) + if(network == reference) network = null \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index e68c43ab216..c18ff0a21e8 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -1,377 +1,377 @@ -/obj/machinery/atmospherics/unary/vent_pump - icon = 'icons/obj/atmospherics/vent_pump.dmi' - icon_state = "hoff" - - name = "Air Vent" - desc = "Has a valve and pump attached to it." - use_power = 1 - - level = 1 - var/area_uid - var/id_tag = null - - var/on = 0 - var/pump_direction = 1 //0 = siphoning, 1 = releasing - - var/external_pressure_bound = ONE_ATMOSPHERE - var/internal_pressure_bound = 0 - - var/pressure_checks = 1 - //1: Do not pass external_pressure_bound - //2: Do not pass internal_pressure_bound - //3: Do not pass either - - var/welded = 0 // Added for aliens -- TLE - var/canSpawnMice = 1 // Set to 0 to prevent spawning of mice. - - var/frequency = 1439 - var/datum/radio_frequency/radio_connection - - var/radio_filter_out - var/radio_filter_in - - machine_flags = MULTITOOL_MENU - - starting_volume = 400 // Previously 200 - -/obj/machinery/atmospherics/unary/vent_pump/on - on = 1 - icon_state = "hout" - -/obj/machinery/atmospherics/unary/vent_pump/siphon - pump_direction = 0 - icon_state = "hoff" - -/obj/machinery/atmospherics/unary/vent_pump/siphon/on - on = 1 - icon_state = "hin" - -/obj/machinery/atmospherics/unary/vent_pump/New() - ..() - area_uid = areaMaster.uid - if (!id_tag) - assign_uid() - id_tag = num2text(uid) - if(ticker && ticker.current_state == 3)//if the game is running - //src.initialize() - src.broadcast_status() - -/obj/machinery/atmospherics/unary/vent_pump/high_volume - name = "Large Air Vent" - power_channel = EQUIP - -/obj/machinery/atmospherics/unary/vent_pump/high_volume/New() - ..() - air_contents.volume = 1000 - -/obj/machinery/atmospherics/unary/vent_pump/update_icon() - if(welded) - icon_state = "hweld" - return - if(on && !(stat & (NOPOWER|BROKEN))) - if(pump_direction) - icon_state = "hout" - else - icon_state = "hin" - else - icon_state = "hoff" - ..() - if (istype(loc, /turf/simulated/floor) && node) - var/turf/simulated/floor/floor = loc - if(floor.floor_tile && node.alpha == 128) - underlays.Cut() - return - -/obj/machinery/atmospherics/unary/vent_pump/process() - . = ..() - CHECK_DISABLED(vents) - if (!node) - return // Turning off the vent is a PITA. - N3X - if(stat & (NOPOWER|BROKEN)) - return - //on = 0 - - //broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0 - if(!on) - return - - if(welded) - return - - // New GC does this sometimes - if(!loc) return - - var/datum/gas_mixture/environment = loc.return_air() - var/environment_pressure = environment.return_pressure() - - if(pump_direction) //internal -> external - var/pressure_delta = 10000 - - if(pressure_checks&1) - pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure)) - if(pressure_checks&2) - pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound)) - - if(pressure_delta > 0.1) - if(air_contents.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - loc.assume_air(removed) - - if(network) - network.update = 1 - - else //external -> internal - var/pressure_delta = 10000 - if(pressure_checks&1) - pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) - if(pressure_checks&2) - pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure())) - - if(pressure_delta > 0.1) - if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - if (isnull(removed)) //in space - return - - air_contents.merge(removed) - - if(network) - network.update = 1 - - return 1 - - //Radio remote control - -/obj/machinery/atmospherics/unary/vent_pump/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_filter_in) - - if(frequency != 1439) - areaMaster.air_vent_info -= id_tag - areaMaster.air_vent_names -= id_tag - name = "Vent Pump" - else - broadcast_status() - -/obj/machinery/atmospherics/unary/vent_pump/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - ..() - src.broadcast_status() - return 1 - -/obj/machinery/atmospherics/unary/vent_pump/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = list( - "area" = src.area_uid, - "tag" = src.id_tag, - "device" = "AVP", - "power" = on, - "direction" = pump_direction?("release"):("siphon"), - "checks" = pressure_checks, - "internal" = internal_pressure_bound, - "external" = external_pressure_bound, - "timestamp" = world.time, - "sigtype" = "status" - ) - - if(frequency == 1439) - if(!areaMaster.air_vent_names[id_tag]) - var/new_name = "[areaMaster.name] Vent Pump #[areaMaster.air_vent_names.len+1]" - areaMaster.air_vent_names[id_tag] = new_name - name = new_name - areaMaster.air_vent_info[id_tag] = signal.data - - radio_connection.post_signal(src, signal, radio_filter_out) - - return 1 - - -/obj/machinery/atmospherics/unary/vent_pump/initialize() - ..() - - //some vents work his own spesial way - radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null - radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null - if(frequency) - set_frequency(frequency) - -/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN)) - return - //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/unary/vent_pump/receive_signal([signal.debug_print()])") - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "vent")) - return 0 - - var/handled=0 - if("purge" in signal.data) - pressure_checks &= ~1 - pump_direction = 0 - handled=1 - - if("stabilize" in signal.data) - pressure_checks |= 1 - pump_direction = 1 - handled = 1 - - if("power" in signal.data) - on = text2num(signal.data["power"]) - handled = 1 - - if("power_toggle" in signal.data) - on = !on - handled = 1 - - if("checks" in signal.data) - pressure_checks = text2num(signal.data["checks"]) - handled = 1 - - if("checks_toggle" in signal.data) - pressure_checks = (pressure_checks?0:3) - handled = 1 - - if("direction" in signal.data) - pump_direction = text2num(signal.data["direction"]) - handled = 1 - - if("set_internal_pressure" in signal.data) - internal_pressure_bound = Clamp(text2num(signal.data["set_internal_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled =1 - - if("set_external_pressure" in signal.data) - external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 - - if("adjust_internal_pressure" in signal.data) - internal_pressure_bound = Clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 - - if("adjust_external_pressure" in signal.data) - external_pressure_bound = Clamp(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 - - if("init" in signal.data) - name = signal.data["init"] - return - - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon - - if(!handled) - testing("\[[world.timeofday]\]: vent_pump/receive_signal: unknown command \n[signal.debug_print()]") - spawn(2) - broadcast_status() - update_icon() - return - -/obj/machinery/atmospherics/unary/vent_pump/hide(var/i) //to make the little pipe section invisible, the icon changes. - update_icon() - return - -/obj/machinery/atmospherics/unary/vent_pump/examine(mob/user) - ..() - if(welded) +/obj/machinery/atmospherics/unary/vent_pump + icon = 'icons/obj/atmospherics/vent_pump.dmi' + icon_state = "hoff" + + name = "Air Vent" + desc = "Has a valve and pump attached to it." + use_power = 1 + + level = 1 + var/area_uid + var/id_tag = null + + var/on = 0 + var/pump_direction = 1 //0 = siphoning, 1 = releasing + + var/external_pressure_bound = ONE_ATMOSPHERE + var/internal_pressure_bound = 0 + + var/pressure_checks = 1 + //1: Do not pass external_pressure_bound + //2: Do not pass internal_pressure_bound + //3: Do not pass either + + var/welded = 0 // Added for aliens -- TLE + var/canSpawnMice = 1 // Set to 0 to prevent spawning of mice. + + var/frequency = 1439 + var/datum/radio_frequency/radio_connection + + var/radio_filter_out + var/radio_filter_in + + machine_flags = MULTITOOL_MENU + + starting_volume = 400 // Previously 200 + +/obj/machinery/atmospherics/unary/vent_pump/on + on = 1 + icon_state = "hout" + +/obj/machinery/atmospherics/unary/vent_pump/siphon + pump_direction = 0 + icon_state = "hoff" + +/obj/machinery/atmospherics/unary/vent_pump/siphon/on + on = 1 + icon_state = "hin" + +/obj/machinery/atmospherics/unary/vent_pump/New() + ..() + area_uid = areaMaster.uid + if (!id_tag) + assign_uid() + id_tag = num2text(uid) + if(ticker && ticker.current_state == 3)//if the game is running + //src.initialize() + src.broadcast_status() + +/obj/machinery/atmospherics/unary/vent_pump/high_volume + name = "Large Air Vent" + power_channel = EQUIP + +/obj/machinery/atmospherics/unary/vent_pump/high_volume/New() + ..() + air_contents.volume = 1000 + +/obj/machinery/atmospherics/unary/vent_pump/update_icon() + if(welded) + icon_state = "hweld" + return + if(on && !(stat & (NOPOWER|BROKEN))) + if(pump_direction) + icon_state = "hout" + else + icon_state = "hin" + else + icon_state = "hoff" + ..() + if (istype(loc, /turf/simulated/floor) && node) + var/turf/simulated/floor/floor = loc + if(floor.floor_tile && node.alpha == 128) + underlays.Cut() + return + +/obj/machinery/atmospherics/unary/vent_pump/process() + . = ..() + CHECK_DISABLED(vents) + if (!node) + return // Turning off the vent is a PITA. - N3X + if(stat & (NOPOWER|BROKEN)) + return + //on = 0 + + //broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0 + if(!on) + return + + if(welded) + return + + // New GC does this sometimes + if(!loc) return + + var/datum/gas_mixture/environment = loc.return_air() + var/environment_pressure = environment.return_pressure() + + if(pump_direction) //internal -> external + var/pressure_delta = 10000 + + if(pressure_checks&1) + pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure)) + if(pressure_checks&2) + pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound)) + + if(pressure_delta > 0.1) + if(air_contents.temperature > 0) + var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) + + loc.assume_air(removed) + + if(network) + network.update = 1 + + else //external -> internal + var/pressure_delta = 10000 + if(pressure_checks&1) + pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) + if(pressure_checks&2) + pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure())) + + if(pressure_delta > 0.1) + if(environment.temperature > 0) + var/transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + + var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) + if (isnull(removed)) //in space + return + + air_contents.merge(removed) + + if(network) + network.update = 1 + + return 1 + + //Radio remote control + +/obj/machinery/atmospherics/unary/vent_pump/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_filter_in) + + if(frequency != 1439) + areaMaster.air_vent_info -= id_tag + areaMaster.air_vent_names -= id_tag + name = "Vent Pump" + else + broadcast_status() + +/obj/machinery/atmospherics/unary/vent_pump/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + ..() + src.broadcast_status() + return 1 + +/obj/machinery/atmospherics/unary/vent_pump/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = list( + "area" = src.area_uid, + "tag" = src.id_tag, + "device" = "AVP", + "power" = on, + "direction" = pump_direction?("release"):("siphon"), + "checks" = pressure_checks, + "internal" = internal_pressure_bound, + "external" = external_pressure_bound, + "timestamp" = world.time, + "sigtype" = "status" + ) + + if(frequency == 1439) + if(!areaMaster.air_vent_names[id_tag]) + var/new_name = "[areaMaster.name] Vent Pump #[areaMaster.air_vent_names.len+1]" + areaMaster.air_vent_names[id_tag] = new_name + name = new_name + areaMaster.air_vent_info[id_tag] = signal.data + + radio_connection.post_signal(src, signal, radio_filter_out) + + return 1 + + +/obj/machinery/atmospherics/unary/vent_pump/initialize() + ..() + + //some vents work his own spesial way + radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null + radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null + if(frequency) + set_frequency(frequency) + +/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal) + if(stat & (NOPOWER|BROKEN)) + return + //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/unary/vent_pump/receive_signal([signal.debug_print()])") + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "vent")) + return 0 + + var/handled=0 + if("purge" in signal.data) + pressure_checks &= ~1 + pump_direction = 0 + handled=1 + + if("stabilize" in signal.data) + pressure_checks |= 1 + pump_direction = 1 + handled = 1 + + if("power" in signal.data) + on = text2num(signal.data["power"]) + handled = 1 + + if("power_toggle" in signal.data) + on = !on + handled = 1 + + if("checks" in signal.data) + pressure_checks = text2num(signal.data["checks"]) + handled = 1 + + if("checks_toggle" in signal.data) + pressure_checks = (pressure_checks?0:3) + handled = 1 + + if("direction" in signal.data) + pump_direction = text2num(signal.data["direction"]) + handled = 1 + + if("set_internal_pressure" in signal.data) + internal_pressure_bound = Clamp(text2num(signal.data["set_internal_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled =1 + + if("set_external_pressure" in signal.data) + external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled = 1 + + if("adjust_internal_pressure" in signal.data) + internal_pressure_bound = Clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled = 1 + + if("adjust_external_pressure" in signal.data) + external_pressure_bound = Clamp(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]), 0, ONE_ATMOSPHERE * 50) + handled = 1 + + if("init" in signal.data) + name = signal.data["init"] + return + + if("status" in signal.data) + spawn(2) + broadcast_status() + return //do not update_icon + + if(!handled) + testing("\[[world.timeofday]\]: vent_pump/receive_signal: unknown command \n[signal.debug_print()]") + spawn(2) + broadcast_status() + update_icon() + return + +/obj/machinery/atmospherics/unary/vent_pump/hide(var/i) //to make the little pipe section invisible, the icon changes. + update_icon() + return + +/obj/machinery/atmospherics/unary/vent_pump/examine(mob/user) + ..() + if(welded) to_chat(user, "It seems welded shut.") - -/obj/machinery/atmospherics/unary/vent_pump/power_change() - if(powered(power_channel)) - stat &= ~NOPOWER - else - stat |= NOPOWER - update_icon() - -/obj/machinery/atmospherics/unary/vent_pump/interact(mob/user as mob) - update_multitool_menu(user) - -/obj/machinery/atmospherics/unary/vent_pump/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return {" - - "} - -/obj/machinery/atmospherics/unary/vent_pump/can_crawl_through() - return !welded - -/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0,user)) + +/obj/machinery/atmospherics/unary/vent_pump/power_change() + if(powered(power_channel)) + stat &= ~NOPOWER + else + stat |= NOPOWER + update_icon() + +/obj/machinery/atmospherics/unary/vent_pump/interact(mob/user as mob) + update_multitool_menu(user) + +/obj/machinery/atmospherics/unary/vent_pump/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return {" + + "} + +/obj/machinery/atmospherics/unary/vent_pump/can_crawl_through() + return !welded + +/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(0,user)) to_chat(user, "Now welding the vent.") - if(do_after(user, src, 20)) - if(!src || !WT.isOn()) return - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) - if(!welded) - user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.") - welded = 1 - update_icon() - else - user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.") - welded = 0 - update_icon() - else + if(do_after(user, src, 20)) + if(!src || !WT.isOn()) return + playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + if(!welded) + user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.") + welded = 1 + update_icon() + else + user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.") + welded = 0 + update_icon() + else to_chat(user, "The welding tool needs to be on to start this task.") - else + else to_chat(user, "You need more welding fuel to complete this task.") - return 1 - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if (!(stat & NOPOWER) && on) + return 1 + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + if (!(stat & NOPOWER) && on) to_chat(user, "You cannot unwrench this [src], turn it off first.") - return 1 - return ..() - -/obj/machinery/atmospherics/unary/vent_pump/Destroy() - areaMaster.air_vent_info.Remove(id_tag) - areaMaster.air_vent_names.Remove(id_tag) - ..() - -/obj/machinery/atmospherics/unary/vent_pump/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) - if("set_id" in href_list) - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src.id_tag) as null|text), 1, MAX_MESSAGE_LEN) - if(!newid) - return - if(frequency == 1439) - areaMaster.air_vent_info -= id_tag - areaMaster.air_vent_names -= id_tag - - id_tag = newid - broadcast_status() - - return MT_UPDATE - - return ..() - -/obj/machinery/atmospherics/unary/vent_pump/change_area(oldarea, newarea) - areaMaster.air_vent_info.Remove(id_tag) - areaMaster.air_vent_names.Remove(id_tag) - ..() - name = replacetext(name,newarea,oldarea) - area_uid = areaMaster.uid - broadcast_status() - -/obj/machinery/atmospherics/unary/vent_pump/canClone(var/obj/O) - return istype(O, /obj/machinery/atmospherics/unary/vent_pump) - -/obj/machinery/atmospherics/unary/vent_pump/clone(var/obj/machinery/atmospherics/unary/vent_pump/O) - if(frequency == 1439) // Note: if the frequency stays at 1439 we'll be readded to the area in set_frequency(). - areaMaster.air_vent_info -= id_tag - areaMaster.air_vent_names -= id_tag - id_tag = O.id_tag - - set_frequency(O.frequency) - return 1 + return 1 + return ..() + +/obj/machinery/atmospherics/unary/vent_pump/Destroy() + areaMaster.air_vent_info.Remove(id_tag) + areaMaster.air_vent_names.Remove(id_tag) + ..() + +/obj/machinery/atmospherics/unary/vent_pump/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) + if("set_id" in href_list) + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src.id_tag) as null|text), 1, MAX_MESSAGE_LEN) + if(!newid) + return + if(frequency == 1439) + areaMaster.air_vent_info -= id_tag + areaMaster.air_vent_names -= id_tag + + id_tag = newid + broadcast_status() + + return MT_UPDATE + + return ..() + +/obj/machinery/atmospherics/unary/vent_pump/change_area(oldarea, newarea) + areaMaster.air_vent_info.Remove(id_tag) + areaMaster.air_vent_names.Remove(id_tag) + ..() + name = replacetext(name,newarea,oldarea) + area_uid = areaMaster.uid + broadcast_status() + +/obj/machinery/atmospherics/unary/vent_pump/canClone(var/obj/O) + return istype(O, /obj/machinery/atmospherics/unary/vent_pump) + +/obj/machinery/atmospherics/unary/vent_pump/clone(var/obj/machinery/atmospherics/unary/vent_pump/O) + if(frequency == 1439) // Note: if the frequency stays at 1439 we'll be readded to the area in set_frequency(). + areaMaster.air_vent_info -= id_tag + areaMaster.air_vent_names -= id_tag + id_tag = O.id_tag + + set_frequency(O.frequency) + return 1 diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index 23cce7c4577..1a0dbbba5ea 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -1,384 +1,384 @@ -/obj/machinery/atmospherics/unary/vent_scrubber - icon = 'icons/obj/atmospherics/vent_scrubber.dmi' - icon_state = "hoff" - name = "Air Scrubber" - desc = "Has a valve and pump attached to it." - use_power = 1 - - level = 1 - - var/id_tag = null - var/frequency = 1439 - var/datum/radio_frequency/radio_connection - - var/on = 0 - var/scrubbing = 1 //0 = siphoning, 1 = scrubbing - var/scrub_CO2 = 1 - var/scrub_Toxins = 1 - var/scrub_N2O = 0 - var/scrub_O2 = 0 - var/scrub_N2 = 0 - - var/volume_rate = 1000 // 120 - var/panic = 0 //is this scrubber panicked? - var/welded = 0 - - var/area_uid - var/radio_filter_out - var/radio_filter_in - - machine_flags = MULTITOOL_MENU - -/obj/machinery/atmospherics/unary/vent_scrubber/on - on = 1 - icon_state = "on" - -/obj/machinery/atmospherics/unary/vent_scrubber/on/burn_chamber - name = "\improper Burn Chamber Scrubber" - - frequency = 1449 - id_tag = "inc_out" - - scrub_Toxins = 0 - -/obj/machinery/atmospherics/unary/vent_scrubber/New() - ..() - area_uid = areaMaster.uid - if (!id_tag) - assign_uid() - id_tag = num2text(uid) - if(ticker && ticker.current_state == 3)//if the game is running - //src.initialize() - src.broadcast_status() - -/obj/machinery/atmospherics/unary/vent_scrubber/update_icon() - if(welded) - icon_state = "hweld" - return - var/suffix="" - if(scrub_O2) - suffix="1" - if(node && on && !(stat & (NOPOWER|BROKEN))) - if(scrubbing) - icon_state = "hon[suffix]" - else - icon_state = "hin" - else - icon_state = "hoff" - ..() - if (istype(loc, /turf/simulated/floor) && node) - var/turf/simulated/floor/floor = loc - if(floor.floor_tile && node.alpha == 128) - underlays.Cut() - return - -/obj/machinery/atmospherics/unary/vent_scrubber/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, radio_filter_in) - - if(frequency != 1439) - areaMaster.air_scrub_info -= id_tag - areaMaster.air_scrub_names -= id_tag - name = "Air Scrubber" - else - broadcast_status() - -/obj/machinery/atmospherics/unary/vent_scrubber/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - ..() - src.broadcast_status() - return 1 - -/obj/machinery/atmospherics/unary/vent_scrubber/proc/broadcast_status() - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - signal.data = list( - "area" = area_uid, - "tag" = id_tag, - "device" = "AScr", - "timestamp" = world.time, - "power" = on, - "scrubbing" = scrubbing, - "panic" = panic, - "filter_co2" = scrub_CO2, - "filter_tox" = scrub_Toxins, - "filter_n2o" = scrub_N2O, - "filter_o2" = scrub_O2, - "filter_n2" = scrub_N2, - "sigtype" = "status" - ) - if(frequency == 1439) - if(!areaMaster.air_scrub_names[id_tag]) - var/new_name = "[areaMaster.name] Air Scrubber #[areaMaster.air_scrub_names.len+1]" - areaMaster.air_scrub_names[id_tag] = new_name - src.name = new_name - areaMaster.air_scrub_info[id_tag] = signal.data - - radio_connection.post_signal(src, signal, radio_filter_out) - - return 1 - -/obj/machinery/atmospherics/unary/vent_scrubber/initialize() - ..() - radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null - radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null - if (frequency) - set_frequency(frequency) - -/obj/machinery/atmospherics/unary/vent_scrubber/process() - . = ..() - CHECK_DISABLED(scrubbers) - if(stat & (NOPOWER|BROKEN)) - return - if (!node) - return // Let's not shut it off, for now. - if(welded) - return - //broadcast_status() - if(!on) - return - // New GC does this sometimes - if(!loc) return - - - var/datum/gas_mixture/environment = loc.return_air() - - if(scrubbing) - // Are we scrubbing gasses that are present? - if(\ - (scrub_Toxins && environment.toxins > 0) ||\ - (scrub_CO2 && environment.carbon_dioxide > 0) ||\ - (scrub_N2O && environment.trace_gases.len > 0) ||\ - (scrub_O2 && environment.oxygen > 0) ||\ - (scrub_N2 && environment.nitrogen > 0)) - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() - - //Take a gas sample - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - if (isnull(removed)) //in space - return - - //Filter it - var/datum/gas_mixture/filtered_out = new - filtered_out.temperature = removed.temperature - - if(scrub_Toxins) - filtered_out.toxins = removed.toxins - removed.toxins = 0 - - if(scrub_CO2) - filtered_out.carbon_dioxide = removed.carbon_dioxide - removed.carbon_dioxide = 0 - - if(scrub_O2) - filtered_out.oxygen = removed.oxygen - removed.oxygen = 0 - - if(scrub_N2) - filtered_out.nitrogen = removed.nitrogen - removed.nitrogen = 0 - - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - else if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - - - //Remix the resulting gases - air_contents.merge(filtered_out) - - loc.assume_air(removed) - - if(network) - network.update = 1 - - else //Just siphoning all air - if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE) - return - - var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume) - - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - - air_contents.merge(removed) - - if(network) - network.update = 1 - - return 1 - -/obj/machinery/atmospherics/unary/vent_scrubber/hide(var/i) //to make the little pipe section invisible, the icon changes. - update_icon() - return - - -/obj/machinery/atmospherics/unary/vent_scrubber/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN)) - return - if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "scrubber")) - return 0 - - if(signal.data["power"] != null) - on = text2num(signal.data["power"]) - if(signal.data["power_toggle"] != null) - on = !on - - if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing - panic = text2num(signal.data["panic_siphon"]) // We send 0 for false in the alarm. - if(panic) - on = 1 - scrubbing = 0 - volume_rate = 2000 - else - scrubbing = 1 - volume_rate = initial(volume_rate) - if(signal.data["toggle_panic_siphon"] != null) - panic = !panic - if(panic) - on = 1 - scrubbing = 0 - volume_rate = 2000 - else - scrubbing = 1 - volume_rate = initial(volume_rate) - - if(signal.data["scrubbing"] != null) - scrubbing = text2num(signal.data["scrubbing"]) - if(signal.data["toggle_scrubbing"]) - scrubbing = !scrubbing - - if(signal.data["co2_scrub"] != null) - scrub_CO2 = text2num(signal.data["co2_scrub"]) - if(signal.data["toggle_co2_scrub"]) - scrub_CO2 = !scrub_CO2 - - if(signal.data["tox_scrub"] != null) - scrub_Toxins = text2num(signal.data["tox_scrub"]) - if(signal.data["toggle_tox_scrub"]) - scrub_Toxins = !scrub_Toxins - - if(signal.data["n2o_scrub"] != null) - scrub_N2O = text2num(signal.data["n2o_scrub"]) - if(signal.data["toggle_n2o_scrub"]) - scrub_N2O = !scrub_N2O - - if(signal.data["o2_scrub"] != null) - scrub_O2 = text2num(signal.data["o2_scrub"]) - if(signal.data["toggle_o2_scrub"]) - scrub_O2 = !scrub_O2 - - if(signal.data["n2_scrub"] != null) - scrub_N2 = text2num(signal.data["n2_scrub"]) - if(signal.data["toggle_n2_scrub"]) - scrub_N2 = !scrub_N2 - - if(signal.data["init"] != null) - name = signal.data["init"] - return - - if(signal.data["status"] != null) - spawn(2) - broadcast_status() - return //do not update_icon - -// log_admin("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") - spawn(2) - broadcast_status() - update_icon() - return - -/obj/machinery/atmospherics/unary/vent_scrubber/power_change() - if(powered(power_channel)) - stat &= ~NOPOWER - else - stat |= NOPOWER - update_icon() - -/obj/machinery/atmospherics/unary/vent_scrubber/can_crawl_through() - return !welded - -/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(1,user)) - to_chat(user, "Now welding the scrubber.") - if(do_after(user, src, 20)) - if(!src || !WT.isOn()) return - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) - if(!welded) - user.visible_message("[user] welds the scrubber shut.", "You weld the vent scrubber.", "You hear welding.") - welded = 1 - update_icon() - else - user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.") - welded = 0 - update_icon() - else - to_chat(user, "The welding tool needs to be on to start this task.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return 1 - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - if (!(stat & NOPOWER) && on) - to_chat(user, "You cannot unwrench this [src], turn it off first.") - return 1 - return ..() - -/obj/machinery/atmospherics/unary/vent_scrubber/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return {" - - "} - -/obj/machinery/atmospherics/unary/vent_scrubber/Destroy() - areaMaster.air_scrub_info.Remove(id_tag) - areaMaster.air_scrub_names.Remove(id_tag) - ..() - -/obj/machinery/atmospherics/unary/vent_scrubber/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) - if("set_id" in href_list) - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN) - if(!newid) - return - - if(frequency == 1439) - areaMaster.air_scrub_info -= id_tag - areaMaster.air_scrub_names -= id_tag - - id_tag = newid - broadcast_status() - - return MT_UPDATE - - return ..() - -/obj/machinery/atmospherics/unary/vent_scrubber/change_area(oldarea, newarea) - areaMaster.air_scrub_info.Remove(id_tag) - areaMaster.air_scrub_names.Remove(id_tag) - ..() - name = replacetext(name,newarea,oldarea) - area_uid = areaMaster.uid - broadcast_status() - -/obj/machinery/atmospherics/unary/vent_scrubber/canClone(var/obj/O) - return istype(O, /obj/machinery/atmospherics/unary/vent_scrubber) - -/obj/machinery/atmospherics/unary/vent_scrubber/clone(var/obj/machinery/atmospherics/unary/vent_scrubber/O) - if(frequency == 1439) // Note: if the frequency stays at 1439 we'll be readded to the area in set_frequency(). - areaMaster.air_scrub_info -= id_tag - areaMaster.air_scrub_names -= id_tag - id_tag = O.id_tag - - set_frequency(O.frequency) - return 1 +/obj/machinery/atmospherics/unary/vent_scrubber + icon = 'icons/obj/atmospherics/vent_scrubber.dmi' + icon_state = "hoff" + name = "Air Scrubber" + desc = "Has a valve and pump attached to it." + use_power = 1 + + level = 1 + + var/id_tag = null + var/frequency = 1439 + var/datum/radio_frequency/radio_connection + + var/on = 0 + var/scrubbing = 1 //0 = siphoning, 1 = scrubbing + var/scrub_CO2 = 1 + var/scrub_Toxins = 1 + var/scrub_N2O = 0 + var/scrub_O2 = 0 + var/scrub_N2 = 0 + + var/volume_rate = 1000 // 120 + var/panic = 0 //is this scrubber panicked? + var/welded = 0 + + var/area_uid + var/radio_filter_out + var/radio_filter_in + + machine_flags = MULTITOOL_MENU + +/obj/machinery/atmospherics/unary/vent_scrubber/on + on = 1 + icon_state = "on" + +/obj/machinery/atmospherics/unary/vent_scrubber/on/burn_chamber + name = "\improper Burn Chamber Scrubber" + + frequency = 1449 + id_tag = "inc_out" + + scrub_Toxins = 0 + +/obj/machinery/atmospherics/unary/vent_scrubber/New() + ..() + area_uid = areaMaster.uid + if (!id_tag) + assign_uid() + id_tag = num2text(uid) + if(ticker && ticker.current_state == 3)//if the game is running + //src.initialize() + src.broadcast_status() + +/obj/machinery/atmospherics/unary/vent_scrubber/update_icon() + if(welded) + icon_state = "hweld" + return + var/suffix="" + if(scrub_O2) + suffix="1" + if(node && on && !(stat & (NOPOWER|BROKEN))) + if(scrubbing) + icon_state = "hon[suffix]" + else + icon_state = "hin" + else + icon_state = "hoff" + ..() + if (istype(loc, /turf/simulated/floor) && node) + var/turf/simulated/floor/floor = loc + if(floor.floor_tile && node.alpha == 128) + underlays.Cut() + return + +/obj/machinery/atmospherics/unary/vent_scrubber/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, radio_filter_in) + + if(frequency != 1439) + areaMaster.air_scrub_info -= id_tag + areaMaster.air_scrub_names -= id_tag + name = "Air Scrubber" + else + broadcast_status() + +/obj/machinery/atmospherics/unary/vent_scrubber/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + ..() + src.broadcast_status() + return 1 + +/obj/machinery/atmospherics/unary/vent_scrubber/proc/broadcast_status() + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + signal.data = list( + "area" = area_uid, + "tag" = id_tag, + "device" = "AScr", + "timestamp" = world.time, + "power" = on, + "scrubbing" = scrubbing, + "panic" = panic, + "filter_co2" = scrub_CO2, + "filter_tox" = scrub_Toxins, + "filter_n2o" = scrub_N2O, + "filter_o2" = scrub_O2, + "filter_n2" = scrub_N2, + "sigtype" = "status" + ) + if(frequency == 1439) + if(!areaMaster.air_scrub_names[id_tag]) + var/new_name = "[areaMaster.name] Air Scrubber #[areaMaster.air_scrub_names.len+1]" + areaMaster.air_scrub_names[id_tag] = new_name + src.name = new_name + areaMaster.air_scrub_info[id_tag] = signal.data + + radio_connection.post_signal(src, signal, radio_filter_out) + + return 1 + +/obj/machinery/atmospherics/unary/vent_scrubber/initialize() + ..() + radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null + radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null + if (frequency) + set_frequency(frequency) + +/obj/machinery/atmospherics/unary/vent_scrubber/process() + . = ..() + CHECK_DISABLED(scrubbers) + if(stat & (NOPOWER|BROKEN)) + return + if (!node) + return // Let's not shut it off, for now. + if(welded) + return + //broadcast_status() + if(!on) + return + // New GC does this sometimes + if(!loc) return + + + var/datum/gas_mixture/environment = loc.return_air() + + if(scrubbing) + // Are we scrubbing gasses that are present? + if(\ + (scrub_Toxins && environment.toxins > 0) ||\ + (scrub_CO2 && environment.carbon_dioxide > 0) ||\ + (scrub_N2O && environment.trace_gases.len > 0) ||\ + (scrub_O2 && environment.oxygen > 0) ||\ + (scrub_N2 && environment.nitrogen > 0)) + var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + + //Take a gas sample + var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) + if (isnull(removed)) //in space + return + + //Filter it + var/datum/gas_mixture/filtered_out = new + filtered_out.temperature = removed.temperature + + if(scrub_Toxins) + filtered_out.toxins = removed.toxins + removed.toxins = 0 + + if(scrub_CO2) + filtered_out.carbon_dioxide = removed.carbon_dioxide + removed.carbon_dioxide = 0 + + if(scrub_O2) + filtered_out.oxygen = removed.oxygen + removed.oxygen = 0 + + if(scrub_N2) + filtered_out.nitrogen = removed.nitrogen + removed.nitrogen = 0 + + if(removed.trace_gases.len>0) + for(var/datum/gas/trace_gas in removed.trace_gases) + if(istype(trace_gas, /datum/gas/oxygen_agent_b)) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + else if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + + + //Remix the resulting gases + air_contents.merge(filtered_out) + + loc.assume_air(removed) + + if(network) + network.update = 1 + + else //Just siphoning all air + if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE) + return + + var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume) + + var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) + + air_contents.merge(removed) + + if(network) + network.update = 1 + + return 1 + +/obj/machinery/atmospherics/unary/vent_scrubber/hide(var/i) //to make the little pipe section invisible, the icon changes. + update_icon() + return + + +/obj/machinery/atmospherics/unary/vent_scrubber/receive_signal(datum/signal/signal) + if(stat & (NOPOWER|BROKEN)) + return + if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "scrubber")) + return 0 + + if(signal.data["power"] != null) + on = text2num(signal.data["power"]) + if(signal.data["power_toggle"] != null) + on = !on + + if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing + panic = text2num(signal.data["panic_siphon"]) // We send 0 for false in the alarm. + if(panic) + on = 1 + scrubbing = 0 + volume_rate = 2000 + else + scrubbing = 1 + volume_rate = initial(volume_rate) + if(signal.data["toggle_panic_siphon"] != null) + panic = !panic + if(panic) + on = 1 + scrubbing = 0 + volume_rate = 2000 + else + scrubbing = 1 + volume_rate = initial(volume_rate) + + if(signal.data["scrubbing"] != null) + scrubbing = text2num(signal.data["scrubbing"]) + if(signal.data["toggle_scrubbing"]) + scrubbing = !scrubbing + + if(signal.data["co2_scrub"] != null) + scrub_CO2 = text2num(signal.data["co2_scrub"]) + if(signal.data["toggle_co2_scrub"]) + scrub_CO2 = !scrub_CO2 + + if(signal.data["tox_scrub"] != null) + scrub_Toxins = text2num(signal.data["tox_scrub"]) + if(signal.data["toggle_tox_scrub"]) + scrub_Toxins = !scrub_Toxins + + if(signal.data["n2o_scrub"] != null) + scrub_N2O = text2num(signal.data["n2o_scrub"]) + if(signal.data["toggle_n2o_scrub"]) + scrub_N2O = !scrub_N2O + + if(signal.data["o2_scrub"] != null) + scrub_O2 = text2num(signal.data["o2_scrub"]) + if(signal.data["toggle_o2_scrub"]) + scrub_O2 = !scrub_O2 + + if(signal.data["n2_scrub"] != null) + scrub_N2 = text2num(signal.data["n2_scrub"]) + if(signal.data["toggle_n2_scrub"]) + scrub_N2 = !scrub_N2 + + if(signal.data["init"] != null) + name = signal.data["init"] + return + + if(signal.data["status"] != null) + spawn(2) + broadcast_status() + return //do not update_icon + +// log_admin("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]") + spawn(2) + broadcast_status() + update_icon() + return + +/obj/machinery/atmospherics/unary/vent_scrubber/power_change() + if(powered(power_channel)) + stat &= ~NOPOWER + else + stat |= NOPOWER + update_icon() + +/obj/machinery/atmospherics/unary/vent_scrubber/can_crawl_through() + return !welded + +/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(1,user)) + to_chat(user, "Now welding the scrubber.") + if(do_after(user, src, 20)) + if(!src || !WT.isOn()) return + playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + if(!welded) + user.visible_message("[user] welds the scrubber shut.", "You weld the vent scrubber.", "You hear welding.") + welded = 1 + update_icon() + else + user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.") + welded = 0 + update_icon() + else + to_chat(user, "The welding tool needs to be on to start this task.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return 1 + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + if (!(stat & NOPOWER) && on) + to_chat(user, "You cannot unwrench this [src], turn it off first.") + return 1 + return ..() + +/obj/machinery/atmospherics/unary/vent_scrubber/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return {" + + "} + +/obj/machinery/atmospherics/unary/vent_scrubber/Destroy() + areaMaster.air_scrub_info.Remove(id_tag) + areaMaster.air_scrub_names.Remove(id_tag) + ..() + +/obj/machinery/atmospherics/unary/vent_scrubber/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) + if("set_id" in href_list) + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN) + if(!newid) + return + + if(frequency == 1439) + areaMaster.air_scrub_info -= id_tag + areaMaster.air_scrub_names -= id_tag + + id_tag = newid + broadcast_status() + + return MT_UPDATE + + return ..() + +/obj/machinery/atmospherics/unary/vent_scrubber/change_area(oldarea, newarea) + areaMaster.air_scrub_info.Remove(id_tag) + areaMaster.air_scrub_names.Remove(id_tag) + ..() + name = replacetext(name,newarea,oldarea) + area_uid = areaMaster.uid + broadcast_status() + +/obj/machinery/atmospherics/unary/vent_scrubber/canClone(var/obj/O) + return istype(O, /obj/machinery/atmospherics/unary/vent_scrubber) + +/obj/machinery/atmospherics/unary/vent_scrubber/clone(var/obj/machinery/atmospherics/unary/vent_scrubber/O) + if(frequency == 1439) // Note: if the frequency stays at 1439 we'll be readded to the area in set_frequency(). + areaMaster.air_scrub_info -= id_tag + areaMaster.air_scrub_names -= id_tag + id_tag = O.id_tag + + set_frequency(O.frequency) + return 1 diff --git a/code/ATMOSPHERICS/datum_pipe_network.dm b/code/ATMOSPHERICS/datum_pipe_network.dm index f1290129ccd..e7da431b4d8 100644 --- a/code/ATMOSPHERICS/datum_pipe_network.dm +++ b/code/ATMOSPHERICS/datum_pipe_network.dm @@ -1,235 +1,235 @@ -/datum/pipe_network - var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network - - var/list/obj/machinery/atmospherics/normal_members = list() - var/list/datum/pipeline/line_members = list() - //membership roster to go through for updates and what not - - var/update = 1 - var/datum/gas_mixture/air_transient = null - var/datum/gas_mixture/radiate = null - -/datum/pipe_network/New() - - air_transient = new() - - ..() - -/datum/pipeline/Del() - pipe_networks -= src - ..() - -/datum/pipe_network/Destroy() - for(var/datum/pipeline/pipeline in line_members) //This will remove the pipeline references for us - pipeline.network = null - for(var/obj/machinery/atmospherics/objects in normal_members) //Procs for the different bases will remove the references - objects.unassign_network(src) - -/datum/pipe_network/resetVariables() - ..("gases", "normal_members", "line_members") - gases = list() - normal_members = list() - line_members = list() - -/datum/pipe_network/proc/process() - //Equalize gases amongst pipe if called for - if(update) - update = 0 - reconcile_air() //equalize_gases(gases) - radiate = null //Reset our last ticks calculation for the post-radiate() gases inside a thermal plate - -#ifdef ATMOS_PIPELINE_PROCESSING - //Give pipelines their process call for pressure checking and what not. Have to remove pressure checks for the time being as pipes dont radiate heat - Mport - for(var/datum/pipeline/line_member in line_members) - line_member.process() -#endif - -/datum/pipe_network/proc/build_network(obj/machinery/atmospherics/start_normal, obj/machinery/atmospherics/reference) - //Purpose: Generate membership roster - //Notes: Assuming that members will add themselves to appropriate roster in network_expandz() - - if(!start_normal) - returnToPool(src) - return - - start_normal.network_expand(src, reference) - - update_network_gases() - - if((normal_members.len>0)||(line_members.len>0)) - pipe_networks |= src - else - returnToPool(src) - return - return 1 - -/datum/pipe_network/proc/merge(datum/pipe_network/giver) - if(giver==src) return 0 - - normal_members |= giver.normal_members - - line_members |= giver.line_members - - for(var/obj/machinery/atmospherics/normal_member in giver.normal_members) - normal_member.reassign_network(giver, src) - - for(var/datum/pipeline/line_member in giver.line_members) - line_member.network = src - - - update_network_gases() - return 1 - -/datum/pipe_network/proc/update_network_gases() - //Go through membership roster and make sure gases is up to date - - gases = list() - - for(var/obj/machinery/atmospherics/normal_member in normal_members) - var/result = normal_member.return_network_air(src) - if(result) gases += result - - for(var/datum/pipeline/line_member in line_members) - gases += line_member.air - -/datum/pipe_network/proc/reconcile_air() - //Perfectly equalize all gases members instantly - - //Calculate totals from individual components - var/total_thermal_energy = 0 - var/total_heat_capacity = 0 - - //air_transient.volume = 0 - var/air_transient_volume = 0 - - air_transient.oxygen = 0 - air_transient.nitrogen = 0 - air_transient.toxins = 0 - air_transient.carbon_dioxide = 0 - - - air_transient.trace_gases = list() - - for(var/datum/gas_mixture/gas in gases) - air_transient_volume += gas.volume - var/temp_heatcap = gas.heat_capacity() - total_thermal_energy += gas.temperature*temp_heatcap - total_heat_capacity += temp_heatcap - - air_transient.oxygen += gas.oxygen - air_transient.nitrogen += gas.nitrogen - air_transient.toxins += gas.toxins - air_transient.carbon_dioxide += gas.carbon_dioxide - - if(gas.trace_gases.len) - for(var/datum/gas/trace_gas in gas.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in air_transient.trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - air_transient.trace_gases += corresponding - - corresponding.moles += trace_gas.moles - - air_transient.volume = air_transient_volume - - if(air_transient_volume > 0) - - if(total_heat_capacity > 0) - air_transient.temperature = total_thermal_energy/total_heat_capacity - - //Allow air mixture to react - if(air_transient.react()) - update = 1 - - else - air_transient.temperature = 0 - - //Update individual gas_mixtures by volume ratio - for(var/datum/gas_mixture/gas in gases) - var/volume_ratio = gas.volume / air_transient.volume - - gas.oxygen = air_transient.oxygen * volume_ratio - gas.nitrogen = air_transient.nitrogen * volume_ratio - gas.toxins = air_transient.toxins * volume_ratio - gas.carbon_dioxide = air_transient.carbon_dioxide * volume_ratio - - gas.temperature = air_transient.temperature - - if(air_transient.trace_gases.len) - for(var/datum/gas/trace_gas in air_transient.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases - - if(!corresponding) - corresponding = new trace_gas.type() - gas.trace_gases += corresponding - - corresponding.moles = trace_gas.moles * volume_ratio - - gas.update_values() - - air_transient.update_values() - return 1 - -proc/equalize_gases(datum/gas_mixture/list/gases) - //Perfectly equalize all gases members instantly - - //Calculate totals from individual components - var/total_volume = 0 - var/total_thermal_energy = 0 - var/total_heat_capacity = 0 - - var/total_oxygen = 0 - var/total_nitrogen = 0 - var/total_toxins = 0 - var/total_carbon_dioxide = 0 - - var/list/total_trace_gases = list() - - for(var/datum/gas_mixture/gas in gases) - total_volume += gas.volume - var/temp_heatcap = gas.heat_capacity() - total_thermal_energy += gas.temperature*temp_heatcap - total_heat_capacity += temp_heatcap - - total_oxygen += gas.oxygen - total_nitrogen += gas.nitrogen - total_toxins += gas.toxins - total_carbon_dioxide += gas.carbon_dioxide - - if(gas.trace_gases.len) - for(var/datum/gas/trace_gas in gas.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - total_trace_gases += corresponding - - corresponding.moles += trace_gas.moles - - if(total_volume > 0) - - //Calculate temperature - var/temperature = 0 - - if(total_heat_capacity > 0) - temperature = total_thermal_energy/total_heat_capacity - - //Update individual gas_mixtures by volume ratio - for(var/datum/gas_mixture/gas in gases) - gas.oxygen = total_oxygen*gas.volume/total_volume - gas.nitrogen = total_nitrogen*gas.volume/total_volume - gas.toxins = total_toxins*gas.volume/total_volume - gas.carbon_dioxide = total_carbon_dioxide*gas.volume/total_volume - - gas.temperature = temperature - - if(total_trace_gases.len) - for(var/datum/gas/trace_gas in total_trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - gas.trace_gases += corresponding - - corresponding.moles = trace_gas.moles*gas.volume/total_volume - gas.update_values() - +/datum/pipe_network + var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network + + var/list/obj/machinery/atmospherics/normal_members = list() + var/list/datum/pipeline/line_members = list() + //membership roster to go through for updates and what not + + var/update = 1 + var/datum/gas_mixture/air_transient = null + var/datum/gas_mixture/radiate = null + +/datum/pipe_network/New() + + air_transient = new() + + ..() + +/datum/pipeline/Del() + pipe_networks -= src + ..() + +/datum/pipe_network/Destroy() + for(var/datum/pipeline/pipeline in line_members) //This will remove the pipeline references for us + pipeline.network = null + for(var/obj/machinery/atmospherics/objects in normal_members) //Procs for the different bases will remove the references + objects.unassign_network(src) + +/datum/pipe_network/resetVariables() + ..("gases", "normal_members", "line_members") + gases = list() + normal_members = list() + line_members = list() + +/datum/pipe_network/proc/process() + //Equalize gases amongst pipe if called for + if(update) + update = 0 + reconcile_air() //equalize_gases(gases) + radiate = null //Reset our last ticks calculation for the post-radiate() gases inside a thermal plate + +#ifdef ATMOS_PIPELINE_PROCESSING + //Give pipelines their process call for pressure checking and what not. Have to remove pressure checks for the time being as pipes dont radiate heat - Mport + for(var/datum/pipeline/line_member in line_members) + line_member.process() +#endif + +/datum/pipe_network/proc/build_network(obj/machinery/atmospherics/start_normal, obj/machinery/atmospherics/reference) + //Purpose: Generate membership roster + //Notes: Assuming that members will add themselves to appropriate roster in network_expandz() + + if(!start_normal) + returnToPool(src) + return + + start_normal.network_expand(src, reference) + + update_network_gases() + + if((normal_members.len>0)||(line_members.len>0)) + pipe_networks |= src + else + returnToPool(src) + return + return 1 + +/datum/pipe_network/proc/merge(datum/pipe_network/giver) + if(giver==src) return 0 + + normal_members |= giver.normal_members + + line_members |= giver.line_members + + for(var/obj/machinery/atmospherics/normal_member in giver.normal_members) + normal_member.reassign_network(giver, src) + + for(var/datum/pipeline/line_member in giver.line_members) + line_member.network = src + + + update_network_gases() + return 1 + +/datum/pipe_network/proc/update_network_gases() + //Go through membership roster and make sure gases is up to date + + gases = list() + + for(var/obj/machinery/atmospherics/normal_member in normal_members) + var/result = normal_member.return_network_air(src) + if(result) gases += result + + for(var/datum/pipeline/line_member in line_members) + gases += line_member.air + +/datum/pipe_network/proc/reconcile_air() + //Perfectly equalize all gases members instantly + + //Calculate totals from individual components + var/total_thermal_energy = 0 + var/total_heat_capacity = 0 + + //air_transient.volume = 0 + var/air_transient_volume = 0 + + air_transient.oxygen = 0 + air_transient.nitrogen = 0 + air_transient.toxins = 0 + air_transient.carbon_dioxide = 0 + + + air_transient.trace_gases = list() + + for(var/datum/gas_mixture/gas in gases) + air_transient_volume += gas.volume + var/temp_heatcap = gas.heat_capacity() + total_thermal_energy += gas.temperature*temp_heatcap + total_heat_capacity += temp_heatcap + + air_transient.oxygen += gas.oxygen + air_transient.nitrogen += gas.nitrogen + air_transient.toxins += gas.toxins + air_transient.carbon_dioxide += gas.carbon_dioxide + + if(gas.trace_gases.len) + for(var/datum/gas/trace_gas in gas.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in air_transient.trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + air_transient.trace_gases += corresponding + + corresponding.moles += trace_gas.moles + + air_transient.volume = air_transient_volume + + if(air_transient_volume > 0) + + if(total_heat_capacity > 0) + air_transient.temperature = total_thermal_energy/total_heat_capacity + + //Allow air mixture to react + if(air_transient.react()) + update = 1 + + else + air_transient.temperature = 0 + + //Update individual gas_mixtures by volume ratio + for(var/datum/gas_mixture/gas in gases) + var/volume_ratio = gas.volume / air_transient.volume + + gas.oxygen = air_transient.oxygen * volume_ratio + gas.nitrogen = air_transient.nitrogen * volume_ratio + gas.toxins = air_transient.toxins * volume_ratio + gas.carbon_dioxide = air_transient.carbon_dioxide * volume_ratio + + gas.temperature = air_transient.temperature + + if(air_transient.trace_gases.len) + for(var/datum/gas/trace_gas in air_transient.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases + + if(!corresponding) + corresponding = new trace_gas.type() + gas.trace_gases += corresponding + + corresponding.moles = trace_gas.moles * volume_ratio + + gas.update_values() + + air_transient.update_values() + return 1 + +proc/equalize_gases(datum/gas_mixture/list/gases) + //Perfectly equalize all gases members instantly + + //Calculate totals from individual components + var/total_volume = 0 + var/total_thermal_energy = 0 + var/total_heat_capacity = 0 + + var/total_oxygen = 0 + var/total_nitrogen = 0 + var/total_toxins = 0 + var/total_carbon_dioxide = 0 + + var/list/total_trace_gases = list() + + for(var/datum/gas_mixture/gas in gases) + total_volume += gas.volume + var/temp_heatcap = gas.heat_capacity() + total_thermal_energy += gas.temperature*temp_heatcap + total_heat_capacity += temp_heatcap + + total_oxygen += gas.oxygen + total_nitrogen += gas.nitrogen + total_toxins += gas.toxins + total_carbon_dioxide += gas.carbon_dioxide + + if(gas.trace_gases.len) + for(var/datum/gas/trace_gas in gas.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + total_trace_gases += corresponding + + corresponding.moles += trace_gas.moles + + if(total_volume > 0) + + //Calculate temperature + var/temperature = 0 + + if(total_heat_capacity > 0) + temperature = total_thermal_energy/total_heat_capacity + + //Update individual gas_mixtures by volume ratio + for(var/datum/gas_mixture/gas in gases) + gas.oxygen = total_oxygen*gas.volume/total_volume + gas.nitrogen = total_nitrogen*gas.volume/total_volume + gas.toxins = total_toxins*gas.volume/total_volume + gas.carbon_dioxide = total_carbon_dioxide*gas.volume/total_volume + + gas.temperature = temperature + + if(total_trace_gases.len) + for(var/datum/gas/trace_gas in total_trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + gas.trace_gases += corresponding + + corresponding.moles = trace_gas.moles*gas.volume/total_volume + gas.update_values() + return 1 \ No newline at end of file diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index 189e70c325d..09b1813c9a2 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -1,231 +1,231 @@ -/datum/pipeline - var/datum/gas_mixture/air - - var/list/obj/machinery/atmospherics/pipe/members = list() - var/list/obj/machinery/atmospherics/pipe/edges = list() //Used for building networks - - var/datum/pipe_network/network - - var/alert_pressure = 0 - var/last_pressure_check=0 - - var/const/PRESSURE_CHECK_DELAY=5 // 5s delay between pchecks to give pipenets time to recover. - -/datum/pipeline/Destroy() - if(network) //For the pipenet rebuild - returnToPool(network) - if(air && air.volume) //For the pipeline rebuild next tick - temporarily_store_air() - qdel(air) - air = null - //Null the fuck out of all these references - for(var/obj/machinery/atmospherics/pipe/M in members) //Edges are a subset of members - M.parent = null - -/datum/pipeline/resetVariables() - ..("members", "edges") - members = list() - edges = list() - -/datum/pipeline/proc/process()//This use to be called called from the pipe networks - if((world.timeofday - last_pressure_check) / 10 >= PRESSURE_CHECK_DELAY) - //Check to see if pressure is within acceptable limits - var/pressure = air.return_pressure() - if(pressure > alert_pressure) - for(var/obj/machinery/atmospherics/pipe/member in members) - if(!member.check_pressure(pressure)) - // Delay next update so we have a chance to recalculate. - last_pressure_check=world.timeofday - break //Only delete 1 pipe per process - - - //Allow for reactions - //air.react() //Should be handled by pipe_network now - -/datum/pipeline/proc/temporarily_store_air() - //Update individual gas_mixtures by volume ratio - - for(var/obj/machinery/atmospherics/pipe/member in members) - member.air_temporary = new - member.air_temporary.volume = member.volume - - member.air_temporary.oxygen = air.oxygen*member.volume/air.volume - member.air_temporary.nitrogen = air.nitrogen*member.volume/air.volume - member.air_temporary.toxins = air.toxins*member.volume/air.volume - member.air_temporary.carbon_dioxide = air.carbon_dioxide*member.volume/air.volume - - member.air_temporary.temperature = air.temperature - - if(air.trace_gases.len) - for(var/datum/gas/trace_gas in air.trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - member.air_temporary.trace_gases += corresponding - - corresponding.moles = trace_gas.moles*member.volume/air.volume - member.air_temporary.update_values() - -/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/pipe/base) - var/list/possible_expansions = list(base) - members = list(base) - edges = list() - - var/volume = base.volume - base.parent = src - alert_pressure = base.alert_pressure - - if(base.air_temporary) - air = base.air_temporary - base.air_temporary = null - else - air = new - - while(possible_expansions.len>0) - for(var/obj/machinery/atmospherics/pipe/borderline in possible_expansions) - - var/list/result = borderline.pipeline_expansion() - var/edge_check = result.len - - if(result.len>0) - for(var/obj/machinery/atmospherics/pipe/item in result) - if(!members.Find(item)) - members += item - possible_expansions += item - - volume += item.volume - item.parent = src - - alert_pressure = min(alert_pressure, item.alert_pressure) - - if(item.air_temporary) - air.merge(item.air_temporary) - - edge_check-- - - if(edge_check>0) - edges += borderline - - possible_expansions -= borderline - - air.volume = volume - air.update_values() - -/datum/pipeline/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - - - if(new_network.line_members.Find(src)) - return 0 - - new_network.line_members += src - - network = new_network - - for(var/obj/machinery/atmospherics/pipe/edge in edges) - for(var/obj/machinery/atmospherics/result in edge.pipeline_expansion()) - if(!istype(result,/obj/machinery/atmospherics/pipe) && (result!=reference)) - result.network_expand(new_network, edge) - - return 1 - -/datum/pipeline/proc/return_network(obj/machinery/atmospherics/reference) - if(!network) - network = getFromPool(/datum/pipe_network) - network.build_network(src, null) - //technically passing these parameters should not be allowed - //however pipe_network.build_network(..) and pipeline.network_extend(...) - // were setup to properly handle this case - - return network - -/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume) - var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume) - air_sample.volume = mingle_volume - - if(istype(target) && target.zone) - //Have to consider preservation of group statuses - var/datum/gas_mixture/turf_copy = new - - turf_copy.copy_from(target.zone.air) - turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group - - equalize_gases(list(air_sample, turf_copy)) - air.merge(air_sample) - - turf_copy.subtract(target.zone.air) - - target.zone.air.merge(turf_copy) - - else - var/datum/gas_mixture/turf_air = target.return_air() - - equalize_gases(list(air_sample, turf_air)) - air.merge(air_sample) - //turf_air already modified by equalize_gases() - - /* - if(istype(target) && !target.processing) - if(target.air) - if(target.air.check_tile_graphic()) - target.update_visuals(target.air) - */ - if(network) - network.update = 1 - -/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity) - var/total_heat_capacity = air.heat_capacity() - var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) - - if(istype(target, /turf/simulated)) - var/turf/simulated/modeled_location = target - - if(modeled_location.blocks_air) - - if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.temperature - modeled_location.temperature - - var/heat = thermal_conductivity*delta_temperature* \ - (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity)) - - air.temperature -= heat/total_heat_capacity - modeled_location.temperature += heat/modeled_location.heat_capacity - - else - var/delta_temperature = 0 - var/sharer_heat_capacity = 0 - - if(modeled_location.zone) - delta_temperature = (air.temperature - modeled_location.zone.air.temperature) - sharer_heat_capacity = modeled_location.zone.air.heat_capacity() - else - delta_temperature = (air.temperature - modeled_location.air.temperature) - sharer_heat_capacity = modeled_location.air.heat_capacity() - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if((sharer_heat_capacity>0) && (partial_heat_capacity>0)) - var/heat = thermal_conductivity*delta_temperature* \ - (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity)) - - self_temperature_delta = -heat/total_heat_capacity - sharer_temperature_delta = heat/sharer_heat_capacity - else - return 1 - - air.temperature += self_temperature_delta - - if(modeled_location.zone) - modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier - else - modeled_location.air.temperature += sharer_temperature_delta - - - else - if((target.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.temperature - target.temperature - - var/heat = thermal_conductivity*delta_temperature* \ - (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) - - air.temperature -= heat/total_heat_capacity - if(network) - network.update = 1 +/datum/pipeline + var/datum/gas_mixture/air + + var/list/obj/machinery/atmospherics/pipe/members = list() + var/list/obj/machinery/atmospherics/pipe/edges = list() //Used for building networks + + var/datum/pipe_network/network + + var/alert_pressure = 0 + var/last_pressure_check=0 + + var/const/PRESSURE_CHECK_DELAY=5 // 5s delay between pchecks to give pipenets time to recover. + +/datum/pipeline/Destroy() + if(network) //For the pipenet rebuild + returnToPool(network) + if(air && air.volume) //For the pipeline rebuild next tick + temporarily_store_air() + qdel(air) + air = null + //Null the fuck out of all these references + for(var/obj/machinery/atmospherics/pipe/M in members) //Edges are a subset of members + M.parent = null + +/datum/pipeline/resetVariables() + ..("members", "edges") + members = list() + edges = list() + +/datum/pipeline/proc/process()//This use to be called called from the pipe networks + if((world.timeofday - last_pressure_check) / 10 >= PRESSURE_CHECK_DELAY) + //Check to see if pressure is within acceptable limits + var/pressure = air.return_pressure() + if(pressure > alert_pressure) + for(var/obj/machinery/atmospherics/pipe/member in members) + if(!member.check_pressure(pressure)) + // Delay next update so we have a chance to recalculate. + last_pressure_check=world.timeofday + break //Only delete 1 pipe per process + + + //Allow for reactions + //air.react() //Should be handled by pipe_network now + +/datum/pipeline/proc/temporarily_store_air() + //Update individual gas_mixtures by volume ratio + + for(var/obj/machinery/atmospherics/pipe/member in members) + member.air_temporary = new + member.air_temporary.volume = member.volume + + member.air_temporary.oxygen = air.oxygen*member.volume/air.volume + member.air_temporary.nitrogen = air.nitrogen*member.volume/air.volume + member.air_temporary.toxins = air.toxins*member.volume/air.volume + member.air_temporary.carbon_dioxide = air.carbon_dioxide*member.volume/air.volume + + member.air_temporary.temperature = air.temperature + + if(air.trace_gases.len) + for(var/datum/gas/trace_gas in air.trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + member.air_temporary.trace_gases += corresponding + + corresponding.moles = trace_gas.moles*member.volume/air.volume + member.air_temporary.update_values() + +/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/pipe/base) + var/list/possible_expansions = list(base) + members = list(base) + edges = list() + + var/volume = base.volume + base.parent = src + alert_pressure = base.alert_pressure + + if(base.air_temporary) + air = base.air_temporary + base.air_temporary = null + else + air = new + + while(possible_expansions.len>0) + for(var/obj/machinery/atmospherics/pipe/borderline in possible_expansions) + + var/list/result = borderline.pipeline_expansion() + var/edge_check = result.len + + if(result.len>0) + for(var/obj/machinery/atmospherics/pipe/item in result) + if(!members.Find(item)) + members += item + possible_expansions += item + + volume += item.volume + item.parent = src + + alert_pressure = min(alert_pressure, item.alert_pressure) + + if(item.air_temporary) + air.merge(item.air_temporary) + + edge_check-- + + if(edge_check>0) + edges += borderline + + possible_expansions -= borderline + + air.volume = volume + air.update_values() + +/datum/pipeline/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + + + if(new_network.line_members.Find(src)) + return 0 + + new_network.line_members += src + + network = new_network + + for(var/obj/machinery/atmospherics/pipe/edge in edges) + for(var/obj/machinery/atmospherics/result in edge.pipeline_expansion()) + if(!istype(result,/obj/machinery/atmospherics/pipe) && (result!=reference)) + result.network_expand(new_network, edge) + + return 1 + +/datum/pipeline/proc/return_network(obj/machinery/atmospherics/reference) + if(!network) + network = getFromPool(/datum/pipe_network) + network.build_network(src, null) + //technically passing these parameters should not be allowed + //however pipe_network.build_network(..) and pipeline.network_extend(...) + // were setup to properly handle this case + + return network + +/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume) + var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume) + air_sample.volume = mingle_volume + + if(istype(target) && target.zone) + //Have to consider preservation of group statuses + var/datum/gas_mixture/turf_copy = new + + turf_copy.copy_from(target.zone.air) + turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group + + equalize_gases(list(air_sample, turf_copy)) + air.merge(air_sample) + + turf_copy.subtract(target.zone.air) + + target.zone.air.merge(turf_copy) + + else + var/datum/gas_mixture/turf_air = target.return_air() + + equalize_gases(list(air_sample, turf_air)) + air.merge(air_sample) + //turf_air already modified by equalize_gases() + + /* + if(istype(target) && !target.processing) + if(target.air) + if(target.air.check_tile_graphic()) + target.update_visuals(target.air) + */ + if(network) + network.update = 1 + +/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity) + var/total_heat_capacity = air.heat_capacity() + var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) + + if(istype(target, /turf/simulated)) + var/turf/simulated/modeled_location = target + + if(modeled_location.blocks_air) + + if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) + var/delta_temperature = air.temperature - modeled_location.temperature + + var/heat = thermal_conductivity*delta_temperature* \ + (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity)) + + air.temperature -= heat/total_heat_capacity + modeled_location.temperature += heat/modeled_location.heat_capacity + + else + var/delta_temperature = 0 + var/sharer_heat_capacity = 0 + + if(modeled_location.zone) + delta_temperature = (air.temperature - modeled_location.zone.air.temperature) + sharer_heat_capacity = modeled_location.zone.air.heat_capacity() + else + delta_temperature = (air.temperature - modeled_location.air.temperature) + sharer_heat_capacity = modeled_location.air.heat_capacity() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if((sharer_heat_capacity>0) && (partial_heat_capacity>0)) + var/heat = thermal_conductivity*delta_temperature* \ + (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity)) + + self_temperature_delta = -heat/total_heat_capacity + sharer_temperature_delta = heat/sharer_heat_capacity + else + return 1 + + air.temperature += self_temperature_delta + + if(modeled_location.zone) + modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier + else + modeled_location.air.temperature += sharer_temperature_delta + + + else + if((target.heat_capacity>0) && (partial_heat_capacity>0)) + var/delta_temperature = air.temperature - target.temperature + + var/heat = thermal_conductivity*delta_temperature* \ + (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) + + air.temperature -= heat/total_heat_capacity + if(network) + network.update = 1 diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/he_pipes.dm index 97d6d54342f..c3085fc8db7 100644 --- a/code/ATMOSPHERICS/he_pipes.dm +++ b/code/ATMOSPHERICS/he_pipes.dm @@ -1,212 +1,212 @@ -#define NO_GAS 0.01 -#define SOME_GAS 1 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging - icon = 'icons/obj/pipes/heat.dmi' - icon_state = "intact" - level = 2 - var/initialize_directions_he - - minimum_temperature_difference = 20 - thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT - - var/const/RADIATION_CAPACITY = 32000 // Radiation isn't particularly effective (TODO BALANCE) - // Plate value is 30000, increased it a bit because of additional surface area. - N3X - var/const/ENERGY_MULT = 6.4 // Not sure what this is, keeping it the same as plates. - - burst_type = /obj/machinery/atmospherics/unary/vent/burstpipe/heat_exchanging - - can_be_coloured = 0 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/getNodeType(var/node_id) - return PIPE_TYPE_HE - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/update_icon(var/adjacent_procd) - var/node_list = list(node1,node2) - if(!node1 && !node2) - qdel(src) - if(!adjacent_procd) - for(var/obj/machinery/atmospherics/node in node_list) - if(node.update_icon_ready && !(istype(node,/obj/machinery/atmospherics/pipe/simple))) - node.update_icon(1) - - // BubbleWrap -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New() - ..() - initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe - // BubbleWrap END - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = 0 - initialize_directions_he = pipe.get_pipe_dir() - //var/turf/T = loc - //level = T.intact ? 2 : 1 - if(!initialize(1)) +#define NO_GAS 0.01 +#define SOME_GAS 1 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging + icon = 'icons/obj/pipes/heat.dmi' + icon_state = "intact" + level = 2 + var/initialize_directions_he + + minimum_temperature_difference = 20 + thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT + + var/const/RADIATION_CAPACITY = 32000 // Radiation isn't particularly effective (TODO BALANCE) + // Plate value is 30000, increased it a bit because of additional surface area. - N3X + var/const/ENERGY_MULT = 6.4 // Not sure what this is, keeping it the same as plates. + + burst_type = /obj/machinery/atmospherics/unary/vent/burstpipe/heat_exchanging + + can_be_coloured = 0 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/getNodeType(var/node_id) + return PIPE_TYPE_HE + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/update_icon(var/adjacent_procd) + var/node_list = list(node1,node2) + if(!node1 && !node2) + qdel(src) + if(!adjacent_procd) + for(var/obj/machinery/atmospherics/node in node_list) + if(node.update_icon_ready && !(istype(node,/obj/machinery/atmospherics/pipe/simple))) + node.update_icon(1) + + // BubbleWrap +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New() + ..() + initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe + // BubbleWrap END + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = 0 + initialize_directions_he = pipe.get_pipe_dir() + //var/turf/T = loc + //level = T.intact ? 2 : 1 + if(!initialize(1)) to_chat(usr, "Unable to build pipe here; It must be connected to a machine, or another pipe that has a connection.") - return 0 - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - return 1 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/initialize(var/suppress_icon_check=0) - normalize_dir() - - findAllConnections(initialize_directions_he) - - if(!suppress_icon_check) - update_icon() - return node1 || node2 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process() - if(!parent) - . = ..() - - // Get gas from pipenet - var/datum/gas_mixture/internal = return_air() - var/internal_transfer_moles = 0.25 * internal.total_moles() - var/datum/gas_mixture/internal_removed = internal.remove(internal_transfer_moles) - - //Get processable air sample and thermal info from environment - var/datum/gas_mixture/environment = loc.return_air() - var/environment_moles = environment.total_moles() - var/transfer_moles = 0.25 * environment_moles - var/datum/gas_mixture/external_removed = environment.remove(transfer_moles) - - // No environmental gas? We radiate it, then. - if(!external_removed) - if(internal_removed) - internal.merge(internal_removed) - return radiate() - - // Not enough gas in the air around us to care about. Radiate. Less gas than airless tiles start with. - if(environment_moles < NO_GAS) - if(internal_removed) - internal.merge(internal_removed) - environment.merge(external_removed) - return radiate() - // A tiny bit of air so this isn't really space, but its not worth activating exchange procs - else if(environment_moles < SOME_GAS) - return 0 - - // No internal gas. Screw this, we're out. - if(!internal_removed) - environment.merge(external_removed) - return - - //Get same info from connected gas - var/combined_heat_capacity = internal_removed.heat_capacity() + external_removed.heat_capacity() - var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + external_removed.heat_capacity() * external_removed.temperature - - if(!combined_heat_capacity) - combined_heat_capacity = 1 - var/final_temperature = combined_energy / combined_heat_capacity - - external_removed.temperature = final_temperature - environment.merge(external_removed) - - internal_removed.temperature = final_temperature - internal.merge(internal_removed) - - - if(parent && parent.network) - parent.network.update = 1 - return 1 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/proc/radiate() - var/datum/gas_mixture/internal = return_air() - var/internal_transfer_moles = 0.25 * internal.total_moles() - var/datum/gas_mixture/internal_removed = internal.remove(internal_transfer_moles) - - if (!internal_removed) - return - - var/combined_heat_capacity = internal_removed.heat_capacity() + RADIATION_CAPACITY - var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + (RADIATION_CAPACITY * ENERGY_MULT) - - var/final_temperature = combined_energy / combined_heat_capacity - - internal_removed.temperature = final_temperature - internal.merge(internal_removed) - - if(parent && parent.network) - parent.network.update = 1 - - return 1 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/hidden - level=1 - icon_state="intact-f" - -///////////////////////////////// -// JUNCTION -///////////////////////////////// -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction - icon = 'icons/obj/pipes/junction.dmi' - icon_state = "intact" - level = 2 - minimum_temperature_difference = 300 - thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT - - // BubbleWrap -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/New() - .. () - switch ( dir ) - if ( SOUTH ) - initialize_directions = NORTH - initialize_directions_he = SOUTH - if ( NORTH ) - initialize_directions = SOUTH - initialize_directions_he = NORTH - if ( EAST ) - initialize_directions = WEST - initialize_directions_he = EAST - if ( WEST ) - initialize_directions = EAST - initialize_directions_he = WEST - // BubbleWrap END - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pdir() - initialize_directions_he = pipe.get_hdir() - if (!initialize(1)) + return 0 + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + return 1 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/initialize(var/suppress_icon_check=0) + normalize_dir() + + findAllConnections(initialize_directions_he) + + if(!suppress_icon_check) + update_icon() + return node1 || node2 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process() + if(!parent) + . = ..() + + // Get gas from pipenet + var/datum/gas_mixture/internal = return_air() + var/internal_transfer_moles = 0.25 * internal.total_moles() + var/datum/gas_mixture/internal_removed = internal.remove(internal_transfer_moles) + + //Get processable air sample and thermal info from environment + var/datum/gas_mixture/environment = loc.return_air() + var/environment_moles = environment.total_moles() + var/transfer_moles = 0.25 * environment_moles + var/datum/gas_mixture/external_removed = environment.remove(transfer_moles) + + // No environmental gas? We radiate it, then. + if(!external_removed) + if(internal_removed) + internal.merge(internal_removed) + return radiate() + + // Not enough gas in the air around us to care about. Radiate. Less gas than airless tiles start with. + if(environment_moles < NO_GAS) + if(internal_removed) + internal.merge(internal_removed) + environment.merge(external_removed) + return radiate() + // A tiny bit of air so this isn't really space, but its not worth activating exchange procs + else if(environment_moles < SOME_GAS) + return 0 + + // No internal gas. Screw this, we're out. + if(!internal_removed) + environment.merge(external_removed) + return + + //Get same info from connected gas + var/combined_heat_capacity = internal_removed.heat_capacity() + external_removed.heat_capacity() + var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + external_removed.heat_capacity() * external_removed.temperature + + if(!combined_heat_capacity) + combined_heat_capacity = 1 + var/final_temperature = combined_energy / combined_heat_capacity + + external_removed.temperature = final_temperature + environment.merge(external_removed) + + internal_removed.temperature = final_temperature + internal.merge(internal_removed) + + + if(parent && parent.network) + parent.network.update = 1 + return 1 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/proc/radiate() + var/datum/gas_mixture/internal = return_air() + var/internal_transfer_moles = 0.25 * internal.total_moles() + var/datum/gas_mixture/internal_removed = internal.remove(internal_transfer_moles) + + if (!internal_removed) + return + + var/combined_heat_capacity = internal_removed.heat_capacity() + RADIATION_CAPACITY + var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + (RADIATION_CAPACITY * ENERGY_MULT) + + var/final_temperature = combined_energy / combined_heat_capacity + + internal_removed.temperature = final_temperature + internal.merge(internal_removed) + + if(parent && parent.network) + parent.network.update = 1 + + return 1 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/hidden + level=1 + icon_state="intact-f" + +///////////////////////////////// +// JUNCTION +///////////////////////////////// +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction + icon = 'icons/obj/pipes/junction.dmi' + icon_state = "intact" + level = 2 + minimum_temperature_difference = 300 + thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT + + // BubbleWrap +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/New() + .. () + switch ( dir ) + if ( SOUTH ) + initialize_directions = NORTH + initialize_directions_he = SOUTH + if ( NORTH ) + initialize_directions = SOUTH + initialize_directions_he = NORTH + if ( EAST ) + initialize_directions = WEST + initialize_directions_he = EAST + if ( WEST ) + initialize_directions = EAST + initialize_directions_he = WEST + // BubbleWrap END + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pdir() + initialize_directions_he = pipe.get_hdir() + if (!initialize(1)) to_chat(usr, "There's nothing to connect this junction to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)") - return 0 - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - return 1 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/update_icon() - if(node1&&node2) - icon_state = "intact[invisibility ? "-f" : "" ]" - else - var/have_node1 = node1?1:0 - var/have_node2 = node2?1:0 - icon_state = "exposed[have_node1][have_node2]" - - if(!node1&&!node2) - qdel(src) - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/initialize(var/suppress_icon_check=0) - node1 = findConnecting(initialize_directions) - node2 = findConnectingHE(initialize_directions_he) - - if(!suppress_icon_check) - update_icon() - - return node1 || node2 - -/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/hidden - level=1 + return 0 + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + return 1 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/update_icon() + if(node1&&node2) + icon_state = "intact[invisibility ? "-f" : "" ]" + else + var/have_node1 = node1?1:0 + var/have_node2 = node2?1:0 + icon_state = "exposed[have_node1][have_node2]" + + if(!node1&&!node2) + qdel(src) + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/initialize(var/suppress_icon_check=0) + node1 = findConnecting(initialize_directions) + node2 = findConnectingHE(initialize_directions_he) + + if(!suppress_icon_check) + update_icon() + + return node1 || node2 + +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/hidden + level=1 icon_state="intact-f" \ No newline at end of file diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index ec1262b5e7f..f7ea3a92be4 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -1,1259 +1,1259 @@ -// Regular pipe colors -// #RRGGBB -#define PIPE_COLOR_BLUE "#0000B7" -#define PIPE_COLOR_CYAN "#00B8B8" -#define PIPE_COLOR_GREEN "#00B900" -#define PIPE_COLOR_GREY "#B4B4B4" -#define PIPE_COLOR_PURPLE "#800080" -#define PIPE_COLOR_RED "#B70000" -#define PIPE_COLOR_ORANGE "#B77900" - -// Insulated pipes -#define IPIPE_COLOR_RED PIPE_COLOR_RED -#define IPIPE_COLOR_BLUE "#4285F4" - -/obj/machinery/atmospherics/pipe - var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke - var/datum/pipeline/parent - var/volume = 0 - force = 20 - layer = 2.4 //under wires with their 2.44 - use_power = 0 - var/alert_pressure = 80*ONE_ATMOSPHERE - var/baseicon="" - -/obj/machinery/atmospherics/pipe/proc/mass_colouration(var/mass_colour) - if (findtext(mass_colour,"#")) - var/datum/pipeline/pipeline = parent - var/list/update_later = list() - for(var/obj/machinery/atmospherics/pipe in pipeline.members) - pipe.color = mass_colour - if(!pipe.can_be_coloured) - pipe.default_colour = mass_colour - update_later += pipe - for(var/obj/machinery/atmospherics/pipe in pipeline.edges) - pipe.update_icon() - update_later -= pipeline.edges - for(var/obj/machinery/atmospherics/pipe in update_later) - pipe.update_icon(1) - -/obj/machinery/atmospherics/pipe/singularity_pull(/obj/machinery/singularity/S, size) - return -/obj/machinery/atmospherics/pipe/proc/pipeline_expansion() - return null - - -/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure) - //Return 1 if parent should continue checking other pipes - //Return null if parent should stop checking other pipes. Recall: del(src) will by default return null - return 1 - -/obj/machinery/atmospherics/pipe/update_icon(var/adjacent_procd) - if(color && centre_overlay) - centre_overlay.color = color - overlays.Cut() - overlays += centre_overlay - ..() - - - -/obj/machinery/atmospherics/pipe/return_air() - if(!parent) - parent = getFromPool(/datum/pipeline) - parent.build_pipeline(src) - return parent.air - - -/obj/machinery/atmospherics/pipe/build_network() - if(!parent) - parent = getFromPool(/datum/pipeline) - parent.build_pipeline(src) - return parent.return_network() - - -/obj/machinery/atmospherics/pipe/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - if(!parent) - parent = getFromPool(/datum/pipeline) - parent.build_pipeline(src) - return parent.network_expand(new_network, reference) - - -/obj/machinery/atmospherics/pipe/return_network(obj/machinery/atmospherics/reference) - if(!parent) - parent = getFromPool(/datum/pipeline) - parent.build_pipeline(src) - return parent.return_network(reference) - - -/obj/machinery/atmospherics/pipe/Destroy() - if(parent) - returnToPool(parent) - for(var/obj/machinery/meter/M in src.loc) - if(M.target == src) - new /obj/item/pipe_meter(src.loc) - qdel(M) - if(air_temporary && loc) - loc.assume_air(air_temporary) - air_temporary = null - - ..() - -/obj/machinery/atmospherics/pipe/simple - icon = 'icons/obj/pipes.dmi' - icon_state = "intact" - name = "pipe" - desc = "A one meter section of regular pipe." - volume = 70 - dir = SOUTH - initialize_directions = SOUTH|NORTH - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/minimum_temperature_difference = 300 - var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No - color = "#B4B4B4" - var/maximum_pressure = 100*ONE_ATMOSPHERE // 10132.5 kPa - var/fatigue_pressure = 80 *ONE_ATMOSPHERE // 8106 kPa - alert_pressure = 80 *ONE_ATMOSPHERE - can_be_coloured = 1 - // Type of burstpipe to use on burst() - var/burst_type = /obj/machinery/atmospherics/unary/vent/burstpipe - - level = 1 - -/obj/machinery/atmospherics/pipe/simple/New() - ..() - switch(dir) - if(SOUTH || NORTH) - initialize_directions = SOUTH|NORTH - if(EAST || WEST) - initialize_directions = EAST|WEST - if(NORTHEAST) - initialize_directions = NORTH|EAST - if(NORTHWEST) - initialize_directions = NORTH|WEST - if(SOUTHEAST) - initialize_directions = SOUTH|EAST - if(SOUTHWEST) - initialize_directions = SOUTH|WEST - -/obj/machinery/atmospherics/pipe/simple/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize(1) - if(!node1&&!node2) - to_chat(usr, "There's nothing to connect this pipe section to! A pipe segment must be connected to at least one other object!") - return 0 - update_icon() - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - return 1 - - -/obj/machinery/atmospherics/pipe/simple/hide(var/i) - if(level == 1 && istype(loc, /turf/simulated)) - invisibility = i ? 101 : 0 - update_icon() - - -/obj/machinery/atmospherics/pipe/simple/process() - if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle - . = ..() - atmos_machines.Remove(src) - - /*if(!node1) - parent.mingle_with_turf(loc, volume) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - - else if(!node2) - parent.mingle_with_turf(loc, volume) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if (nodealert) - nodealert = 0 - - - else if(parent) - var/environment_temperature = 0 - - if(istype(loc, /turf/simulated/)) - if(loc:blocks_air) - environment_temperature = loc:temperature - else - var/datum/gas_mixture/environment = loc.return_air() - environment_temperature = environment.temperature - - else - environment_temperature = loc:temperature - - var/datum/gas_mixture/pipe_air = return_air() - - if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) - parent.temperature_interact(loc, volume, thermal_conductivity) - */ - - -/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure) - if(!loc) - return - - // Note: This checks the difference between atmospheric pressure and pressure in the pipe. - // So, a pipe rated at 8,000 kPa in a 104kPa environment will explode at 8,104kPa. - var/datum/gas_mixture/environment = loc.return_air() - - var/pressure_difference = pressure - environment.return_pressure() - - // Burst check first. - if(pressure_difference > maximum_pressure && prob(1)) - burst() - - // Groan if that check failed and we're above fatigue pressure - else if(pressure_difference > fatigue_pressure && prob(1)) // 5 was too often - groan() - - // Otherwise, continue on. - else - return 1 - -/obj/machinery/atmospherics/pipe/simple/examine(mob/user) - ..() - to_chat(user, "This [src.name] is rated up to [format_num(alert_pressure)] kPa.") - -/obj/machinery/atmospherics/pipe/simple/proc/groan() - src.visible_message("\The [src] groans from the pressure!"); - - // Need SFX for groaning metal. - //playsound(get_turf(src), 'sound/effects/groan.ogg', 25, 1) - - -/obj/machinery/atmospherics/pipe/simple/proc/burst() - src.visible_message("\The [src] bursts!"); - - var/turf/T=get_turf(src) - - message_admins("Pipe burst in area [formatJumpTo(T)]") - var/area/A=get_area_master(src) - log_game("Pipe burst in area [A.name] ") - - // Disconnect first. - for(var/obj/machinery/atmospherics/node in pipeline_expansion()) - if(node) - node.disconnect(src) - node = null - - // Move away from explosion - loc=null - - if(prob(50)) - explosion(T, -1, 1, 2, adminlog=0) - else - explosion(T, 0, 1, 2, adminlog=0) - - // Now connect burstpipes. - var/node_id=0 - for(var/direction in cardinal) - if(initialize_directions & direction) - node_id++ - var/obj/machinery/atmospherics/found - var/node_type=getNodeType(node_id) - switch(node_type) - if(PIPE_TYPE_STANDARD) - found = findConnecting(direction) - if(PIPE_TYPE_HE) - found = findConnectingHE(direction) - else - error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([node_id]): [node_type]") - return - if(!found) continue - - var/obj/machinery/atmospherics/unary/vent/burstpipe/BP = new burst_type(T, setdir=direction) - BP.color=src.color - BP.invisibility=src.invisibility - BP.level=src.level - BP.do_connect() - - qdel(src) // NOT qdel. - - -/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir() - if(dir==3) - dir = 1 - else if(dir==12) - dir = 4 - - -/obj/machinery/atmospherics/pipe/simple/Destroy() - if(node1) - node1.disconnect(src) - if(node2) - node2.disconnect(src) - - node1 = null - node2 = null - - ..() - - -/obj/machinery/atmospherics/pipe/simple/pipeline_expansion() - return list(node1, node2) - - -/obj/machinery/atmospherics/pipe/simple/update_icon(var/adjacent_procd) - var/node_list = list(node1,node2) - if(!node1||!node2) - icon_state = "exposed" - ..(adjacent_procd,node_list) - else - underlays.Cut() - icon_state = "intact" - alpha = invisibility ? 128 : 255 - if(!adjacent_procd) - for(var/obj/machinery/atmospherics/node in node_list) - if(node.update_icon_ready && !(istype(node,/obj/machinery/atmospherics/pipe/simple))) - node.update_icon(1) - if(!node1&&!node2) - qdel(src) //TODO: silent deleting looks weird - -/obj/machinery/atmospherics/pipe/simple/initialize(var/suppress_icon_check=0) - normalize_dir() - - findAllConnections(initialize_directions) - - var/turf/T = src.loc // hide if turf is not intact - hide(T.intact) - if(!suppress_icon_check) - update_icon() - - -/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference) - if(reference == node1) - if(istype(node1, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node1 = null - - if(reference == node2) - if(istype(node2, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node2 = null - - update_icon() - return null - -/obj/machinery/atmospherics/pipe/simple/scrubbers - name = "Scrubbers pipe" - color=PIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/simple/supply - name = "Air supply pipe" - color=PIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/simple/supplymain - name = "Main air supply pipe" - color=PIPE_COLOR_PURPLE -/obj/machinery/atmospherics/pipe/simple/general - name = "Pipe" - color=PIPE_COLOR_GREY -/obj/machinery/atmospherics/pipe/simple/yellow - name = "Pipe" - color=PIPE_COLOR_ORANGE -/obj/machinery/atmospherics/pipe/simple/cyan - name = "Pipe" - color=PIPE_COLOR_CYAN -/obj/machinery/atmospherics/pipe/simple/filtering - name = "Pipe" - color=PIPE_COLOR_GREEN - -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/supply/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/supply/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/supplymain/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/general/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/general/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/yellow/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/yellow/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/cyan/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/cyan/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/filtering/visible - level = 2 -/obj/machinery/atmospherics/pipe/simple/filtering/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/simple/insulated - name = "\improper Insulated pipe" - //icon = 'icons/obj/atmospherics/red_pipe.dmi' - minimum_temperature_difference = 10000 - thermal_conductivity = 0 - - maximum_pressure = 1000000 // 1M kPa - fatigue_pressure = 900000 // 900k kPa - alert_pressure = 900000 - - can_be_coloured = 1 - color = IPIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/simple/insulated/visible - icon_state = "intact" - level = 2 - color=IPIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/simple/insulated/visible/blue - color=IPIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/simple/insulated/hidden - icon_state = "intact" - alpha=128 - level = 1 - color=IPIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/simple/insulated/hidden/blue - color= IPIPE_COLOR_BLUE - -/obj/machinery/atmospherics/pipe/manifold - icon = 'icons/obj/atmospherics/pipe_manifold.dmi' - icon_state = "map" - baseicon = "manifold" - name = "pipe manifold" - desc = "A manifold composed of regular pipes." - volume = 105 - color = "#B4B4B4" - dir = SOUTH - initialize_directions = EAST|NORTH|WEST - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/obj/machinery/atmospherics/node3 - level = 1 - layer = 2.4 //under wires with their 2.44 - var/global/image/manifold_centre = image('icons/obj/pipes.dmi',"manifold_centre") - -/obj/machinery/atmospherics/pipe/manifold/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize(1) - if(!node1&&!node2&&!node3) - to_chat(usr, "There's nothing to connect this manifold to! A pipe segment must be connected to at least one other object!") - return 0 - update_icon() // Skipped in initialize()! - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - if (node3) - node3.initialize() - node3.build_network() - return 1 - - -/obj/machinery/atmospherics/pipe/manifold/New() - icon_state = "manifold" - switch(dir) - if(NORTH) - initialize_directions = EAST|SOUTH|WEST - if(SOUTH) - initialize_directions = WEST|NORTH|EAST - if(EAST) - initialize_directions = SOUTH|WEST|NORTH - if(WEST) - initialize_directions = NORTH|EAST|SOUTH - centre_overlay = manifold_centre - centre_overlay.color = color - overlays += centre_overlay - ..() - - -/obj/machinery/atmospherics/pipe/manifold/hide(var/i) - if(level == 1 && istype(loc, /turf/simulated)) - invisibility = i ? 101 : 0 - update_icon() - - -/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion() - return list(node1, node2, node3) - - -/obj/machinery/atmospherics/pipe/manifold/process() - if(!parent) - . = ..() - atmos_machines.Remove(src) - /* - if(!node1) - parent.mingle_with_turf(loc, 70) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if(!node2) - parent.mingle_with_turf(loc, 70) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if(!node3) - parent.mingle_with_turf(loc, 70) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if (nodealert) - nodealert = 0 - */ - - -/obj/machinery/atmospherics/pipe/manifold/Destroy() - if(node1) - node1.disconnect(src) - if(node2) - node2.disconnect(src) - if(node3) - node3.disconnect(src) - - node1 = null - node2 = null - node3 = null - - ..() - - -/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference) - if(reference == node1) - if(istype(node1, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node1 = null - - if(reference == node2) - if(istype(node2, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node2 = null - - if(reference == node3) - if(istype(node3, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node3 = null - - update_icon() - - ..() - - - -/obj/machinery/atmospherics/pipe/manifold/update_icon(var/adjacent_procd) - var/node_list = list(node1,node2,node3) - ..(adjacent_procd,node_list) - if(!node1 && !node2 && !node3) - qdel(src) - - -/obj/machinery/atmospherics/pipe/manifold/initialize(var/skip_icon_update=0) - var/connect_directions = (NORTH|SOUTH|EAST|WEST)&(~dir) - - findAllConnections(connect_directions) - - var/turf/T = src.loc // hide if turf is not intact - hide(T.intact) - if(!skip_icon_update) - update_icon() - -/obj/machinery/atmospherics/pipe/manifold/scrubbers - name = "\improper Scrubbers pipe" - color = PIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/manifold/supply - name = "\improper Air supply pipe" - color = PIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/manifold/supplymain - name = "\improper Main air supply pipe" - color = PIPE_COLOR_PURPLE -/obj/machinery/atmospherics/pipe/manifold/general - name = "\improper Gas pipe" - color = PIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/manifold/yellow - name = "\improper Air supply pipe" - color = PIPE_COLOR_ORANGE -/obj/machinery/atmospherics/pipe/manifold/cyan - name = "\improper Air supply pipe" - color = PIPE_COLOR_CYAN -/obj/machinery/atmospherics/pipe/manifold/filtering - name = "\improper Air filtering pipe" - color = PIPE_COLOR_GREEN -/obj/machinery/atmospherics/pipe/manifold/insulated - name = "\improper Insulated pipe" - //icon = 'icons/obj/atmospherics/red_pipe.dmi' - icon_state = "manifold" - alert_pressure = 900*ONE_ATMOSPHERE - color=IPIPE_COLOR_RED - level = 2 - can_be_coloured = 1 -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/supply/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/supply/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/supplymain/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/general/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/general/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/insulated/visible - level = 2 - color=IPIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/manifold/insulated/visible/blue - color=IPIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/manifold/insulated/hidden - level = 1 - color=IPIPE_COLOR_RED - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/insulated/hidden/blue - color=IPIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/manifold/yellow/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/yellow/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/cyan/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold/filtering/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold/filtering/hidden - level = 1 - alpha=128 - -/obj/machinery/atmospherics/pipe/manifold4w - icon = 'icons/obj/atmospherics/pipe_manifold.dmi' - icon_state = "map_4way" - name = "4-way pipe manifold" - desc = "A manifold composed of regular pipes." - volume = 140 - dir = SOUTH - initialize_directions = NORTH|SOUTH|EAST|WEST - color = "#B4B4B4" - var/obj/machinery/atmospherics/node1 - var/obj/machinery/atmospherics/node2 - var/obj/machinery/atmospherics/node3 - var/obj/machinery/atmospherics/node4 - level = 1 - layer = 2.4 //under wires with their 2.44 - baseicon="manifold4w" - var/global/image/manifold4w_centre = image('icons/obj/pipes.dmi',"manifold4w_centre") - - -/obj/machinery/atmospherics/pipe/manifold4w/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize(1) - if(!node1 && !node2 && !node3 && !node4) - to_chat(usr, "There's nothing to connect this manifold to! A pipe segment must be connected to at least one other object!") - return 0 - update_icon() - build_network() - if (node1) - node1.initialize() - node1.build_network() - if (node2) - node2.initialize() - node2.build_network() - if (node3) - node3.initialize() - node3.build_network() - if (node4) - node4.initialize() - node4.build_network() - return 1 - -/obj/machinery/atmospherics/pipe/manifold4w/New() - icon_state = "manifold4w" - ..() - centre_overlay = manifold4w_centre - centre_overlay.color = color - overlays += centre_overlay - -/obj/machinery/atmospherics/pipe/manifold4w/hide(var/i) - if(level == 1 && istype(loc, /turf/simulated)) - invisibility = i ? 101 : 0 - update_icon() - - -/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion() - return list(node1, node2, node3, node4) - - -/obj/machinery/atmospherics/pipe/manifold4w/process() - if(!parent) - . = ..() - atmos_machines.Remove(src) - /* - if(!node1) - parent.mingle_with_turf(loc, 70) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if(!node2) - parent.mingle_with_turf(loc, 70) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if(!node3) - parent.mingle_with_turf(loc, 70) - if(!nodealert) -// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") - nodealert = 1 - else if (nodealert) - nodealert = 0 - */ - - -/obj/machinery/atmospherics/pipe/manifold4w/Destroy() - if(node1) - node1.disconnect(src) - if(node2) - node2.disconnect(src) - if(node3) - node3.disconnect(src) - if(node4) - node4.disconnect(src) - - node1 = null - node2 = null - node3 = null - node4 = null - - ..() - - -/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference) - if(reference == node1) - if(istype(node1, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node1 = null - - if(reference == node2) - if(istype(node2, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node2 = null - - if(reference == node3) - if(istype(node3, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node3 = null - - if(reference == node4) - if(istype(node4, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - node4 = null - - update_icon() - - ..() - - -/obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/adjacent_procd) - var/node_list = list(node1,node2,node3,node4) - ..(adjacent_procd,node_list) - if(!node1 && !node2 && !node3 && !node4) - qdel(src) - return - - -/obj/machinery/atmospherics/pipe/manifold4w/initialize(var/skip_update_icon=0) - - findAllConnections(initialize_directions) - - var/turf/T = src.loc // hide if turf is not intact - hide(T.intact) - if(!skip_update_icon) - update_icon() - -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers - name = "\improper Scrubbers pipe" - color = PIPE_COLOR_RED -/obj/machinery/atmospherics/pipe/manifold4w/supply - name = "\improper Air supply pipe" - color = PIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/manifold4w/supplymain - name = "\improper Main air supply pipe" - color = PIPE_COLOR_PURPLE -/obj/machinery/atmospherics/pipe/manifold4w/general - name = "\improper Air supply pipe" - color = PIPE_COLOR_GREY -/obj/machinery/atmospherics/pipe/manifold4w/yellow - name = "\improper Air supply pipe" - color = PIPE_COLOR_ORANGE -/obj/machinery/atmospherics/pipe/manifold4w/filtering - name = "\improper Air filtering pipe" - color = PIPE_COLOR_GREEN -/obj/machinery/atmospherics/pipe/manifold4w/insulated - name = "\improper Insulated pipe" - color = IPIPE_COLOR_RED - alert_pressure = 900*ONE_ATMOSPHERE - color=IPIPE_COLOR_RED - level = 2 - can_be_coloured = 1 - -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/supply/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/supplymain/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/general/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/general/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/filtering/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/filtering/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/yellow/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/insulated/hidden - level = 1 - alpha=128 -/obj/machinery/atmospherics/pipe/manifold4w/insulated/visible - level = 2 -/obj/machinery/atmospherics/pipe/manifold4w/insulated/hidden/blue - color=IPIPE_COLOR_BLUE -/obj/machinery/atmospherics/pipe/manifold4w/insulated/visible/blue - color=IPIPE_COLOR_BLUE - - -/obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(istype(W, /obj/item/device/rcd/rpd) || istype(W, /obj/item/device/pipe_painter)) - return // Coloring pipes. - - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/red)) - src.color = PIPE_COLOR_RED - to_chat(user, "You paint the pipe red.") - update_icon() - return 1 - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/blue)) - src.color = PIPE_COLOR_BLUE - to_chat(user, "You paint the pipe blue.") - update_icon() - return 1 - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/green)) - src.color = PIPE_COLOR_GREEN - to_chat(user, "You paint the pipe green.") - update_icon() - return 1 - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/yellow)) - src.color = PIPE_COLOR_ORANGE - to_chat(user, "You paint the pipe yellow.") - update_icon() - return 1 - - if(istype(W, /obj/item/pipe_meter)) - var/obj/item/pipe_meter/meter = W - if(user.drop_item(meter, src.loc)) - meter.setAttachLayer(src.piping_layer) - - if(istype(W,/obj/item/device/analyzer)) - var/obj/item/device/analyzer/A = W - var/datum/gas_mixture/environment = src.return_air() - user.show_message(A.output_gas_scan(environment,src,1)) - - return ..() - - -/obj/machinery/atmospherics/pipe/layer_manifold - name = "pipe-layer manifold" - - icon = 'icons/obj/atmospherics/pipe_manifold.dmi' - icon_state = "manifoldlayer" - baseicon = "manifoldlayer" - - dir = SOUTH - initialize_directions = NORTH|SOUTH - - volume = 260 //6 averaged pipe segments - - pipe_flags = ALL_LAYER - - var/list/layer_nodes = list() - var/obj/machinery/atmospherics/other_node = null - -/obj/machinery/atmospherics/pipe/layer_manifold/New() - for(var/pipelayer = PIPING_LAYER_MIN; pipelayer <= PIPING_LAYER_MAX; pipelayer += PIPING_LAYER_INCREMENT) - layer_nodes.Add(null) - switch(dir) - if(NORTH,SOUTH) - initialize_directions = NORTH|SOUTH - if(EAST,WEST) - initialize_directions = EAST|WEST - ..() - -/obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer(var/new_layer = PIPING_LAYER_DEFAULT) - piping_layer = PIPING_LAYER_DEFAULT - -/obj/machinery/atmospherics/pipe/layer_manifold/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize(1) - if(!(locate(/obj/machinery/atmospherics) in layer_nodes) && !other_node) - to_chat(usr, "There's nothing to connect this manifold to! A pipe segment must be connected to at least one other object!") - return 0 - update_icon() - build_network() - for(var/obj/machinery/atmospherics/node in layer_nodes) - node.initialize() - node.build_network() - if (other_node) - other_node.initialize() - other_node.build_network() - return 1 - -/obj/machinery/atmospherics/pipe/layer_manifold/hide(var/i) - if(level == 1 && istype(loc, /turf/simulated)) - invisibility = i ? 101 : 0 - update_icon() - -/obj/machinery/atmospherics/pipe/layer_manifold/pipeline_expansion() - return layer_nodes + other_node - - -/obj/machinery/atmospherics/pipe/layer_manifold/process() - if(!parent) - . = ..() - atmos_machines.Remove(src) - -/obj/machinery/atmospherics/pipe/layer_manifold/Destroy() - for(var/obj/machinery/atmospherics/node in layer_nodes) - node.disconnect(src) - if(other_node) - other_node.disconnect(src) - ..() - - -/obj/machinery/atmospherics/pipe/layer_manifold/disconnect(obj/machinery/atmospherics/reference) - if(reference == other_node) - if(istype(other_node, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - other_node = null - - else - for(var/pipelayer = PIPING_LAYER_MIN; pipelayer <= PIPING_LAYER_MAX; pipelayer += PIPING_LAYER_INCREMENT) - if(reference == layer_nodes[pipelayer]) - if(istype(layer_nodes[pipelayer], /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - layer_nodes[pipelayer] = null - - update_icon() - - ..() - -/obj/machinery/atmospherics/pipe/layer_manifold/update_icon() - overlays.len = 0 - alpha = invisibility ? 128 : 255 - icon_state = baseicon - if(other_node) - var/icon/con = new/icon(icon,"manifoldl_other_con") - - overlays += new/image(con, dir = turn(src.dir, 180)) //adds the back connector - - for(var/pipelayer = PIPING_LAYER_MIN; pipelayer <= PIPING_LAYER_MAX; pipelayer += PIPING_LAYER_INCREMENT) - if(layer_nodes[pipelayer]) //we are connected at this layer - - var/layer_diff = pipelayer - PIPING_LAYER_DEFAULT - - var/image/con = image(icon(src.icon,"manifoldl_con",src.dir)) - con.pixel_x = layer_diff * PIPING_LAYER_P_X - con.pixel_y = layer_diff * PIPING_LAYER_P_Y - - overlays += con - - if(!other_node && !(locate(/obj/machinery/atmospherics) in layer_nodes)) - qdel(src) - return - - -/obj/machinery/atmospherics/pipe/layer_manifold/initialize(var/skip_update_icon=0) - - findAllConnections(initialize_directions) - - var/turf/T = src.loc // hide if turf is not intact - hide(T.intact) - if(!skip_update_icon) - update_icon() - -/obj/machinery/atmospherics/pipe/layer_manifold/findAllConnections(var/connect_dirs) - for(var/direction in cardinal) - if(connect_dirs & direction) - if(direction == dir) //we're facing this - for(var/i = PIPING_LAYER_MIN; i <= PIPING_LAYER_MAX; i += PIPING_LAYER_INCREMENT) - var/obj/machinery/atmospherics/found - var/node_type=getNodeType(i) - switch(node_type) - if(PIPE_TYPE_STANDARD) - found = findConnecting(direction, i) //we pass the layer to find the pipe - if(PIPE_TYPE_HE) - found = findConnectingHE(direction, i) - else - error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([i]): [node_type]") - return - if(!found) - continue - layer_nodes[i] = found //put it in the list - else - var/obj/machinery/atmospherics/found - var/node_type=getNodeType(direction) - switch(node_type) - if(PIPE_TYPE_STANDARD) - found = findConnecting(direction) - if(PIPE_TYPE_HE) - found = findConnectingHE(direction) - else - error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([direction]): [node_type]") - if(!found) - continue - other_node = found - -/obj/machinery/atmospherics/pipe/layer_manifold/isConnectable(var/obj/machinery/atmospherics/target, var/direction, var/given_layer) - if(direction == turn(src.dir, 180)) - return (given_layer == PIPING_LAYER_DEFAULT) - return ..() - -/obj/machinery/atmospherics/pipe/layer_manifold/getNodeType() - return PIPE_TYPE_STANDARD - -//We would normally set layer here, but I don't want to -/obj/machinery/atmospherics/pipe/layer_manifold/Entered() - return - -/obj/machinery/atmospherics/pipe/layer_manifold/relaymove(mob/living/user, direction) - if(!(direction & initialize_directions)) //can't go in a way we aren't connecting to - var/layer_mod = 0 - - if(dir & (NORTH|SOUTH)) - if(direction == EAST) //Going up in layers - layer_mod = 1 - else - layer_mod = -1 - else - if(direction == SOUTH) // - layer_mod = 1 - else - layer_mod = -1 - - user.ventcrawl_layer = Clamp(user.ventcrawl_layer + layer_mod, PIPING_LAYER_MIN, PIPING_LAYER_MAX) - to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.") - return 1 - else - if(direction != dir && user.ventcrawl_layer != PIPING_LAYER_DEFAULT) // The mob is moving to the single pipe outlet, we need to align it if it's on a layer that's not the default layer - user.ventcrawl_layer = PIPING_LAYER_DEFAULT - to_chat(user, "You are redirected into the [user.ventcrawl_layer]\th piping layer.") - - return ..() - - -/obj/machinery/atmospherics/pipe/layer_adapter - name = "pipe-layer adapter" - - icon = 'icons/obj/atmospherics/pipe_adapter.dmi' - icon_state = "adapter_1" - baseicon = "adapter" - - color = PIPE_COLOR_GREY - - dir = SOUTH - initialize_directions = NORTH|SOUTH - - volume = 260 //6 averaged pipe segments - - pipe_flags = ALL_LAYER - - var/obj/machinery/atmospherics/layer_node = null - var/obj/machinery/atmospherics/mid_node = null - -/obj/machinery/atmospherics/pipe/layer_adapter/New() - ..() - switch(dir) - if(NORTH,SOUTH) - initialize_directions = NORTH|SOUTH - if(EAST,WEST) - initialize_directions = EAST|WEST - -/obj/machinery/atmospherics/pipe/layer_adapter/setPipingLayer(var/new_layer = PIPING_LAYER_DEFAULT) - piping_layer = new_layer - -/obj/machinery/atmospherics/pipe/layer_adapter/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) - dir = pipe.dir - initialize_directions = pipe.get_pipe_dir() - var/turf/T = loc - level = T.intact ? 2 : 1 - initialize(1) - if(!mid_node && !layer_node) - to_chat(usr, "There's nothing to connect this adapter to! A pipe segment must be connected to at least one other object!") - return 0 - update_icon() - build_network() - if (mid_node) - mid_node.initialize() - mid_node.build_network() - if (layer_node) - layer_node.initialize() - layer_node.build_network() - return 1 - -/obj/machinery/atmospherics/pipe/layer_adapter/hide(var/i) - if(level == 1 && istype(loc, /turf/simulated)) - invisibility = i ? 101 : 0 - update_icon() - -/obj/machinery/atmospherics/pipe/layer_adapter/pipeline_expansion() - return list(layer_node, mid_node) - - -/obj/machinery/atmospherics/pipe/layer_adapter/process() - if(!parent) - . = ..() - atmos_machines.Remove(src) - -/obj/machinery/atmospherics/pipe/layer_adapter/Destroy() - if(mid_node) - mid_node.disconnect(src) - if(layer_node) - layer_node.disconnect(src) - ..() - - -/obj/machinery/atmospherics/pipe/layer_adapter/disconnect(var/obj/machinery/atmospherics/reference) - if(reference == mid_node) - if(istype(mid_node, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - mid_node = null - if(reference == layer_node) - if(istype(layer_node, /obj/machinery/atmospherics/pipe) && !isnull(parent)) - returnToPool(parent) - layer_node = null - - update_icon() - - ..() - -/obj/machinery/atmospherics/pipe/layer_adapter/update_icon() - overlays.len = 0 - alpha = invisibility ? 128 : 255 - icon_state = "[baseicon]_[piping_layer]" - if(layer_node) - var/layer_diff = piping_layer - PIPING_LAYER_DEFAULT - - var/image/con = image(icon(src.icon,"layer_con",turn(src.dir,180))) - con.pixel_x = layer_diff * PIPING_LAYER_P_X - con.pixel_y = layer_diff * PIPING_LAYER_P_Y - - overlays += con - if(!mid_node && !layer_node) - qdel(src) - return - - -/obj/machinery/atmospherics/pipe/layer_adapter/initialize(var/skip_update_icon=0) - - findAllConnections(initialize_directions) - - var/turf/T = src.loc // hide if turf is not intact - hide(T.intact) - if(!skip_update_icon) - update_icon() - -/obj/machinery/atmospherics/pipe/layer_adapter/findAllConnections(var/connect_dirs) - for(var/direction in cardinal) - if(connect_dirs & direction) - if(direction == dir) //we're facing this - var/obj/machinery/atmospherics/found - var/node_type=getNodeType(direction) - switch(node_type) - if(PIPE_TYPE_STANDARD) - found = findConnecting(direction, PIPING_LAYER_DEFAULT) - if(PIPE_TYPE_HE) - found = findConnectingHE(direction, PIPING_LAYER_DEFAULT) - else - error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([direction]): [node_type]") - if(!found) - continue - mid_node = found - else - var/obj/machinery/atmospherics/found - var/node_type=getNodeType(direction) - switch(node_type) - if(PIPE_TYPE_STANDARD) - found = findConnecting(direction, piping_layer) //we pass the layer to find the pipe - if(PIPE_TYPE_HE) - found = findConnectingHE(direction, piping_layer) - else - error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([piping_layer]): [node_type]") - return - if(!found) - continue - layer_node = found - -/obj/machinery/atmospherics/pipe/layer_adapter/isConnectable(var/obj/machinery/atmospherics/target, var/direction, var/given_layer) - if(direction == dir) - return (given_layer == PIPING_LAYER_DEFAULT) - return ..() - -/obj/machinery/atmospherics/pipe/layer_adapter/getNodeType() - return PIPE_TYPE_STANDARD - -//We would normally set layer here, but I don't want to -/obj/machinery/atmospherics/pipe/layer_adapter/Entered() - return - -/obj/machinery/atmospherics/pipe/layer_adapter/relaymove(mob/living/user, direction) - // Autoset layer - if(direction & initialize_directions) - user.ventcrawl_layer = (direction == dir) ? PIPING_LAYER_DEFAULT : piping_layer - to_chat(user, "You are redirected into the [user.ventcrawl_layer]\th piping layer.") - return ..() +// Regular pipe colors +// #RRGGBB +#define PIPE_COLOR_BLUE "#0000B7" +#define PIPE_COLOR_CYAN "#00B8B8" +#define PIPE_COLOR_GREEN "#00B900" +#define PIPE_COLOR_GREY "#B4B4B4" +#define PIPE_COLOR_PURPLE "#800080" +#define PIPE_COLOR_RED "#B70000" +#define PIPE_COLOR_ORANGE "#B77900" + +// Insulated pipes +#define IPIPE_COLOR_RED PIPE_COLOR_RED +#define IPIPE_COLOR_BLUE "#4285F4" + +/obj/machinery/atmospherics/pipe + var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke + var/datum/pipeline/parent + var/volume = 0 + force = 20 + layer = 2.4 //under wires with their 2.44 + use_power = 0 + var/alert_pressure = 80*ONE_ATMOSPHERE + var/baseicon="" + +/obj/machinery/atmospherics/pipe/proc/mass_colouration(var/mass_colour) + if (findtext(mass_colour,"#")) + var/datum/pipeline/pipeline = parent + var/list/update_later = list() + for(var/obj/machinery/atmospherics/pipe in pipeline.members) + pipe.color = mass_colour + if(!pipe.can_be_coloured) + pipe.default_colour = mass_colour + update_later += pipe + for(var/obj/machinery/atmospherics/pipe in pipeline.edges) + pipe.update_icon() + update_later -= pipeline.edges + for(var/obj/machinery/atmospherics/pipe in update_later) + pipe.update_icon(1) + +/obj/machinery/atmospherics/pipe/singularity_pull(/obj/machinery/singularity/S, size) + return +/obj/machinery/atmospherics/pipe/proc/pipeline_expansion() + return null + + +/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure) + //Return 1 if parent should continue checking other pipes + //Return null if parent should stop checking other pipes. Recall: del(src) will by default return null + return 1 + +/obj/machinery/atmospherics/pipe/update_icon(var/adjacent_procd) + if(color && centre_overlay) + centre_overlay.color = color + overlays.Cut() + overlays += centre_overlay + ..() + + + +/obj/machinery/atmospherics/pipe/return_air() + if(!parent) + parent = getFromPool(/datum/pipeline) + parent.build_pipeline(src) + return parent.air + + +/obj/machinery/atmospherics/pipe/build_network() + if(!parent) + parent = getFromPool(/datum/pipeline) + parent.build_pipeline(src) + return parent.return_network() + + +/obj/machinery/atmospherics/pipe/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + if(!parent) + parent = getFromPool(/datum/pipeline) + parent.build_pipeline(src) + return parent.network_expand(new_network, reference) + + +/obj/machinery/atmospherics/pipe/return_network(obj/machinery/atmospherics/reference) + if(!parent) + parent = getFromPool(/datum/pipeline) + parent.build_pipeline(src) + return parent.return_network(reference) + + +/obj/machinery/atmospherics/pipe/Destroy() + if(parent) + returnToPool(parent) + for(var/obj/machinery/meter/M in src.loc) + if(M.target == src) + new /obj/item/pipe_meter(src.loc) + qdel(M) + if(air_temporary && loc) + loc.assume_air(air_temporary) + air_temporary = null + + ..() + +/obj/machinery/atmospherics/pipe/simple + icon = 'icons/obj/pipes.dmi' + icon_state = "intact" + name = "pipe" + desc = "A one meter section of regular pipe." + volume = 70 + dir = SOUTH + initialize_directions = SOUTH|NORTH + var/obj/machinery/atmospherics/node1 + var/obj/machinery/atmospherics/node2 + var/minimum_temperature_difference = 300 + var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No + color = "#B4B4B4" + var/maximum_pressure = 100*ONE_ATMOSPHERE // 10132.5 kPa + var/fatigue_pressure = 80 *ONE_ATMOSPHERE // 8106 kPa + alert_pressure = 80 *ONE_ATMOSPHERE + can_be_coloured = 1 + // Type of burstpipe to use on burst() + var/burst_type = /obj/machinery/atmospherics/unary/vent/burstpipe + + level = 1 + +/obj/machinery/atmospherics/pipe/simple/New() + ..() + switch(dir) + if(SOUTH || NORTH) + initialize_directions = SOUTH|NORTH + if(EAST || WEST) + initialize_directions = EAST|WEST + if(NORTHEAST) + initialize_directions = NORTH|EAST + if(NORTHWEST) + initialize_directions = NORTH|WEST + if(SOUTHEAST) + initialize_directions = SOUTH|EAST + if(SOUTHWEST) + initialize_directions = SOUTH|WEST + +/obj/machinery/atmospherics/pipe/simple/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize(1) + if(!node1&&!node2) + to_chat(usr, "There's nothing to connect this pipe section to! A pipe segment must be connected to at least one other object!") + return 0 + update_icon() + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + return 1 + + +/obj/machinery/atmospherics/pipe/simple/hide(var/i) + if(level == 1 && istype(loc, /turf/simulated)) + invisibility = i ? 101 : 0 + update_icon() + + +/obj/machinery/atmospherics/pipe/simple/process() + if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle + . = ..() + atmos_machines.Remove(src) + + /*if(!node1) + parent.mingle_with_turf(loc, volume) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + + else if(!node2) + parent.mingle_with_turf(loc, volume) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if (nodealert) + nodealert = 0 + + + else if(parent) + var/environment_temperature = 0 + + if(istype(loc, /turf/simulated/)) + if(loc:blocks_air) + environment_temperature = loc:temperature + else + var/datum/gas_mixture/environment = loc.return_air() + environment_temperature = environment.temperature + + else + environment_temperature = loc:temperature + + var/datum/gas_mixture/pipe_air = return_air() + + if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) + parent.temperature_interact(loc, volume, thermal_conductivity) + */ + + +/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure) + if(!loc) + return + + // Note: This checks the difference between atmospheric pressure and pressure in the pipe. + // So, a pipe rated at 8,000 kPa in a 104kPa environment will explode at 8,104kPa. + var/datum/gas_mixture/environment = loc.return_air() + + var/pressure_difference = pressure - environment.return_pressure() + + // Burst check first. + if(pressure_difference > maximum_pressure && prob(1)) + burst() + + // Groan if that check failed and we're above fatigue pressure + else if(pressure_difference > fatigue_pressure && prob(1)) // 5 was too often + groan() + + // Otherwise, continue on. + else + return 1 + +/obj/machinery/atmospherics/pipe/simple/examine(mob/user) + ..() + to_chat(user, "This [src.name] is rated up to [format_num(alert_pressure)] kPa.") + +/obj/machinery/atmospherics/pipe/simple/proc/groan() + src.visible_message("\The [src] groans from the pressure!"); + + // Need SFX for groaning metal. + //playsound(get_turf(src), 'sound/effects/groan.ogg', 25, 1) + + +/obj/machinery/atmospherics/pipe/simple/proc/burst() + src.visible_message("\The [src] bursts!"); + + var/turf/T=get_turf(src) + + message_admins("Pipe burst in area [formatJumpTo(T)]") + var/area/A=get_area_master(src) + log_game("Pipe burst in area [A.name] ") + + // Disconnect first. + for(var/obj/machinery/atmospherics/node in pipeline_expansion()) + if(node) + node.disconnect(src) + node = null + + // Move away from explosion + loc=null + + if(prob(50)) + explosion(T, -1, 1, 2, adminlog=0) + else + explosion(T, 0, 1, 2, adminlog=0) + + // Now connect burstpipes. + var/node_id=0 + for(var/direction in cardinal) + if(initialize_directions & direction) + node_id++ + var/obj/machinery/atmospherics/found + var/node_type=getNodeType(node_id) + switch(node_type) + if(PIPE_TYPE_STANDARD) + found = findConnecting(direction) + if(PIPE_TYPE_HE) + found = findConnectingHE(direction) + else + error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([node_id]): [node_type]") + return + if(!found) continue + + var/obj/machinery/atmospherics/unary/vent/burstpipe/BP = new burst_type(T, setdir=direction) + BP.color=src.color + BP.invisibility=src.invisibility + BP.level=src.level + BP.do_connect() + + qdel(src) // NOT qdel. + + +/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir() + if(dir==3) + dir = 1 + else if(dir==12) + dir = 4 + + +/obj/machinery/atmospherics/pipe/simple/Destroy() + if(node1) + node1.disconnect(src) + if(node2) + node2.disconnect(src) + + node1 = null + node2 = null + + ..() + + +/obj/machinery/atmospherics/pipe/simple/pipeline_expansion() + return list(node1, node2) + + +/obj/machinery/atmospherics/pipe/simple/update_icon(var/adjacent_procd) + var/node_list = list(node1,node2) + if(!node1||!node2) + icon_state = "exposed" + ..(adjacent_procd,node_list) + else + underlays.Cut() + icon_state = "intact" + alpha = invisibility ? 128 : 255 + if(!adjacent_procd) + for(var/obj/machinery/atmospherics/node in node_list) + if(node.update_icon_ready && !(istype(node,/obj/machinery/atmospherics/pipe/simple))) + node.update_icon(1) + if(!node1&&!node2) + qdel(src) //TODO: silent deleting looks weird + +/obj/machinery/atmospherics/pipe/simple/initialize(var/suppress_icon_check=0) + normalize_dir() + + findAllConnections(initialize_directions) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + if(!suppress_icon_check) + update_icon() + + +/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference) + if(reference == node1) + if(istype(node1, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node1 = null + + if(reference == node2) + if(istype(node2, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node2 = null + + update_icon() + return null + +/obj/machinery/atmospherics/pipe/simple/scrubbers + name = "Scrubbers pipe" + color=PIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/simple/supply + name = "Air supply pipe" + color=PIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/simple/supplymain + name = "Main air supply pipe" + color=PIPE_COLOR_PURPLE +/obj/machinery/atmospherics/pipe/simple/general + name = "Pipe" + color=PIPE_COLOR_GREY +/obj/machinery/atmospherics/pipe/simple/yellow + name = "Pipe" + color=PIPE_COLOR_ORANGE +/obj/machinery/atmospherics/pipe/simple/cyan + name = "Pipe" + color=PIPE_COLOR_CYAN +/obj/machinery/atmospherics/pipe/simple/filtering + name = "Pipe" + color=PIPE_COLOR_GREEN + +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/supply/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/supply/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/supplymain/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/general/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/general/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/yellow/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/yellow/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/cyan/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/cyan/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/filtering/visible + level = 2 +/obj/machinery/atmospherics/pipe/simple/filtering/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/simple/insulated + name = "\improper Insulated pipe" + //icon = 'icons/obj/atmospherics/red_pipe.dmi' + minimum_temperature_difference = 10000 + thermal_conductivity = 0 + + maximum_pressure = 1000000 // 1M kPa + fatigue_pressure = 900000 // 900k kPa + alert_pressure = 900000 + + can_be_coloured = 1 + color = IPIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/simple/insulated/visible + icon_state = "intact" + level = 2 + color=IPIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/simple/insulated/visible/blue + color=IPIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/simple/insulated/hidden + icon_state = "intact" + alpha=128 + level = 1 + color=IPIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/simple/insulated/hidden/blue + color= IPIPE_COLOR_BLUE + +/obj/machinery/atmospherics/pipe/manifold + icon = 'icons/obj/atmospherics/pipe_manifold.dmi' + icon_state = "map" + baseicon = "manifold" + name = "pipe manifold" + desc = "A manifold composed of regular pipes." + volume = 105 + color = "#B4B4B4" + dir = SOUTH + initialize_directions = EAST|NORTH|WEST + var/obj/machinery/atmospherics/node1 + var/obj/machinery/atmospherics/node2 + var/obj/machinery/atmospherics/node3 + level = 1 + layer = 2.4 //under wires with their 2.44 + var/global/image/manifold_centre = image('icons/obj/pipes.dmi',"manifold_centre") + +/obj/machinery/atmospherics/pipe/manifold/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize(1) + if(!node1&&!node2&&!node3) + to_chat(usr, "There's nothing to connect this manifold to! A pipe segment must be connected to at least one other object!") + return 0 + update_icon() // Skipped in initialize()! + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + if (node3) + node3.initialize() + node3.build_network() + return 1 + + +/obj/machinery/atmospherics/pipe/manifold/New() + icon_state = "manifold" + switch(dir) + if(NORTH) + initialize_directions = EAST|SOUTH|WEST + if(SOUTH) + initialize_directions = WEST|NORTH|EAST + if(EAST) + initialize_directions = SOUTH|WEST|NORTH + if(WEST) + initialize_directions = NORTH|EAST|SOUTH + centre_overlay = manifold_centre + centre_overlay.color = color + overlays += centre_overlay + ..() + + +/obj/machinery/atmospherics/pipe/manifold/hide(var/i) + if(level == 1 && istype(loc, /turf/simulated)) + invisibility = i ? 101 : 0 + update_icon() + + +/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion() + return list(node1, node2, node3) + + +/obj/machinery/atmospherics/pipe/manifold/process() + if(!parent) + . = ..() + atmos_machines.Remove(src) + /* + if(!node1) + parent.mingle_with_turf(loc, 70) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if(!node2) + parent.mingle_with_turf(loc, 70) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if(!node3) + parent.mingle_with_turf(loc, 70) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if (nodealert) + nodealert = 0 + */ + + +/obj/machinery/atmospherics/pipe/manifold/Destroy() + if(node1) + node1.disconnect(src) + if(node2) + node2.disconnect(src) + if(node3) + node3.disconnect(src) + + node1 = null + node2 = null + node3 = null + + ..() + + +/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference) + if(reference == node1) + if(istype(node1, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node1 = null + + if(reference == node2) + if(istype(node2, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node2 = null + + if(reference == node3) + if(istype(node3, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node3 = null + + update_icon() + + ..() + + + +/obj/machinery/atmospherics/pipe/manifold/update_icon(var/adjacent_procd) + var/node_list = list(node1,node2,node3) + ..(adjacent_procd,node_list) + if(!node1 && !node2 && !node3) + qdel(src) + + +/obj/machinery/atmospherics/pipe/manifold/initialize(var/skip_icon_update=0) + var/connect_directions = (NORTH|SOUTH|EAST|WEST)&(~dir) + + findAllConnections(connect_directions) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + if(!skip_icon_update) + update_icon() + +/obj/machinery/atmospherics/pipe/manifold/scrubbers + name = "\improper Scrubbers pipe" + color = PIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/manifold/supply + name = "\improper Air supply pipe" + color = PIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/manifold/supplymain + name = "\improper Main air supply pipe" + color = PIPE_COLOR_PURPLE +/obj/machinery/atmospherics/pipe/manifold/general + name = "\improper Gas pipe" + color = PIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/manifold/yellow + name = "\improper Air supply pipe" + color = PIPE_COLOR_ORANGE +/obj/machinery/atmospherics/pipe/manifold/cyan + name = "\improper Air supply pipe" + color = PIPE_COLOR_CYAN +/obj/machinery/atmospherics/pipe/manifold/filtering + name = "\improper Air filtering pipe" + color = PIPE_COLOR_GREEN +/obj/machinery/atmospherics/pipe/manifold/insulated + name = "\improper Insulated pipe" + //icon = 'icons/obj/atmospherics/red_pipe.dmi' + icon_state = "manifold" + alert_pressure = 900*ONE_ATMOSPHERE + color=IPIPE_COLOR_RED + level = 2 + can_be_coloured = 1 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/supply/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/supply/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/supplymain/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/general/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/general/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/insulated/visible + level = 2 + color=IPIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/manifold/insulated/visible/blue + color=IPIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/manifold/insulated/hidden + level = 1 + color=IPIPE_COLOR_RED + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/insulated/hidden/blue + color=IPIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/manifold/yellow/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/yellow/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/cyan/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold/filtering/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold/filtering/hidden + level = 1 + alpha=128 + +/obj/machinery/atmospherics/pipe/manifold4w + icon = 'icons/obj/atmospherics/pipe_manifold.dmi' + icon_state = "map_4way" + name = "4-way pipe manifold" + desc = "A manifold composed of regular pipes." + volume = 140 + dir = SOUTH + initialize_directions = NORTH|SOUTH|EAST|WEST + color = "#B4B4B4" + var/obj/machinery/atmospherics/node1 + var/obj/machinery/atmospherics/node2 + var/obj/machinery/atmospherics/node3 + var/obj/machinery/atmospherics/node4 + level = 1 + layer = 2.4 //under wires with their 2.44 + baseicon="manifold4w" + var/global/image/manifold4w_centre = image('icons/obj/pipes.dmi',"manifold4w_centre") + + +/obj/machinery/atmospherics/pipe/manifold4w/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize(1) + if(!node1 && !node2 && !node3 && !node4) + to_chat(usr, "There's nothing to connect this manifold to! A pipe segment must be connected to at least one other object!") + return 0 + update_icon() + build_network() + if (node1) + node1.initialize() + node1.build_network() + if (node2) + node2.initialize() + node2.build_network() + if (node3) + node3.initialize() + node3.build_network() + if (node4) + node4.initialize() + node4.build_network() + return 1 + +/obj/machinery/atmospherics/pipe/manifold4w/New() + icon_state = "manifold4w" + ..() + centre_overlay = manifold4w_centre + centre_overlay.color = color + overlays += centre_overlay + +/obj/machinery/atmospherics/pipe/manifold4w/hide(var/i) + if(level == 1 && istype(loc, /turf/simulated)) + invisibility = i ? 101 : 0 + update_icon() + + +/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion() + return list(node1, node2, node3, node4) + + +/obj/machinery/atmospherics/pipe/manifold4w/process() + if(!parent) + . = ..() + atmos_machines.Remove(src) + /* + if(!node1) + parent.mingle_with_turf(loc, 70) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if(!node2) + parent.mingle_with_turf(loc, 70) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if(!node3) + parent.mingle_with_turf(loc, 70) + if(!nodealert) +// to_chat(world, "Missing node from [src] at [src.x],[src.y],[src.z]") + nodealert = 1 + else if (nodealert) + nodealert = 0 + */ + + +/obj/machinery/atmospherics/pipe/manifold4w/Destroy() + if(node1) + node1.disconnect(src) + if(node2) + node2.disconnect(src) + if(node3) + node3.disconnect(src) + if(node4) + node4.disconnect(src) + + node1 = null + node2 = null + node3 = null + node4 = null + + ..() + + +/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference) + if(reference == node1) + if(istype(node1, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node1 = null + + if(reference == node2) + if(istype(node2, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node2 = null + + if(reference == node3) + if(istype(node3, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node3 = null + + if(reference == node4) + if(istype(node4, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + node4 = null + + update_icon() + + ..() + + +/obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/adjacent_procd) + var/node_list = list(node1,node2,node3,node4) + ..(adjacent_procd,node_list) + if(!node1 && !node2 && !node3 && !node4) + qdel(src) + return + + +/obj/machinery/atmospherics/pipe/manifold4w/initialize(var/skip_update_icon=0) + + findAllConnections(initialize_directions) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + if(!skip_update_icon) + update_icon() + +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers + name = "\improper Scrubbers pipe" + color = PIPE_COLOR_RED +/obj/machinery/atmospherics/pipe/manifold4w/supply + name = "\improper Air supply pipe" + color = PIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/manifold4w/supplymain + name = "\improper Main air supply pipe" + color = PIPE_COLOR_PURPLE +/obj/machinery/atmospherics/pipe/manifold4w/general + name = "\improper Air supply pipe" + color = PIPE_COLOR_GREY +/obj/machinery/atmospherics/pipe/manifold4w/yellow + name = "\improper Air supply pipe" + color = PIPE_COLOR_ORANGE +/obj/machinery/atmospherics/pipe/manifold4w/filtering + name = "\improper Air filtering pipe" + color = PIPE_COLOR_GREEN +/obj/machinery/atmospherics/pipe/manifold4w/insulated + name = "\improper Insulated pipe" + color = IPIPE_COLOR_RED + alert_pressure = 900*ONE_ATMOSPHERE + color=IPIPE_COLOR_RED + level = 2 + can_be_coloured = 1 + +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/supply/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/supplymain/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/general/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/general/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/filtering/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/filtering/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/yellow/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/insulated/hidden + level = 1 + alpha=128 +/obj/machinery/atmospherics/pipe/manifold4w/insulated/visible + level = 2 +/obj/machinery/atmospherics/pipe/manifold4w/insulated/hidden/blue + color=IPIPE_COLOR_BLUE +/obj/machinery/atmospherics/pipe/manifold4w/insulated/visible/blue + color=IPIPE_COLOR_BLUE + + +/obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/device/rcd/rpd) || istype(W, /obj/item/device/pipe_painter)) + return // Coloring pipes. + + if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/red)) + src.color = PIPE_COLOR_RED + to_chat(user, "You paint the pipe red.") + update_icon() + return 1 + if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/blue)) + src.color = PIPE_COLOR_BLUE + to_chat(user, "You paint the pipe blue.") + update_icon() + return 1 + if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/green)) + src.color = PIPE_COLOR_GREEN + to_chat(user, "You paint the pipe green.") + update_icon() + return 1 + if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/yellow)) + src.color = PIPE_COLOR_ORANGE + to_chat(user, "You paint the pipe yellow.") + update_icon() + return 1 + + if(istype(W, /obj/item/pipe_meter)) + var/obj/item/pipe_meter/meter = W + if(user.drop_item(meter, src.loc)) + meter.setAttachLayer(src.piping_layer) + + if(istype(W,/obj/item/device/analyzer)) + var/obj/item/device/analyzer/A = W + var/datum/gas_mixture/environment = src.return_air() + user.show_message(A.output_gas_scan(environment,src,1)) + + return ..() + + +/obj/machinery/atmospherics/pipe/layer_manifold + name = "pipe-layer manifold" + + icon = 'icons/obj/atmospherics/pipe_manifold.dmi' + icon_state = "manifoldlayer" + baseicon = "manifoldlayer" + + dir = SOUTH + initialize_directions = NORTH|SOUTH + + volume = 260 //6 averaged pipe segments + + pipe_flags = ALL_LAYER + + var/list/layer_nodes = list() + var/obj/machinery/atmospherics/other_node = null + +/obj/machinery/atmospherics/pipe/layer_manifold/New() + for(var/pipelayer = PIPING_LAYER_MIN; pipelayer <= PIPING_LAYER_MAX; pipelayer += PIPING_LAYER_INCREMENT) + layer_nodes.Add(null) + switch(dir) + if(NORTH,SOUTH) + initialize_directions = NORTH|SOUTH + if(EAST,WEST) + initialize_directions = EAST|WEST + ..() + +/obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer(var/new_layer = PIPING_LAYER_DEFAULT) + piping_layer = PIPING_LAYER_DEFAULT + +/obj/machinery/atmospherics/pipe/layer_manifold/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize(1) + if(!(locate(/obj/machinery/atmospherics) in layer_nodes) && !other_node) + to_chat(usr, "There's nothing to connect this manifold to! A pipe segment must be connected to at least one other object!") + return 0 + update_icon() + build_network() + for(var/obj/machinery/atmospherics/node in layer_nodes) + node.initialize() + node.build_network() + if (other_node) + other_node.initialize() + other_node.build_network() + return 1 + +/obj/machinery/atmospherics/pipe/layer_manifold/hide(var/i) + if(level == 1 && istype(loc, /turf/simulated)) + invisibility = i ? 101 : 0 + update_icon() + +/obj/machinery/atmospherics/pipe/layer_manifold/pipeline_expansion() + return layer_nodes + other_node + + +/obj/machinery/atmospherics/pipe/layer_manifold/process() + if(!parent) + . = ..() + atmos_machines.Remove(src) + +/obj/machinery/atmospherics/pipe/layer_manifold/Destroy() + for(var/obj/machinery/atmospherics/node in layer_nodes) + node.disconnect(src) + if(other_node) + other_node.disconnect(src) + ..() + + +/obj/machinery/atmospherics/pipe/layer_manifold/disconnect(obj/machinery/atmospherics/reference) + if(reference == other_node) + if(istype(other_node, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + other_node = null + + else + for(var/pipelayer = PIPING_LAYER_MIN; pipelayer <= PIPING_LAYER_MAX; pipelayer += PIPING_LAYER_INCREMENT) + if(reference == layer_nodes[pipelayer]) + if(istype(layer_nodes[pipelayer], /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + layer_nodes[pipelayer] = null + + update_icon() + + ..() + +/obj/machinery/atmospherics/pipe/layer_manifold/update_icon() + overlays.len = 0 + alpha = invisibility ? 128 : 255 + icon_state = baseicon + if(other_node) + var/icon/con = new/icon(icon,"manifoldl_other_con") + + overlays += new/image(con, dir = turn(src.dir, 180)) //adds the back connector + + for(var/pipelayer = PIPING_LAYER_MIN; pipelayer <= PIPING_LAYER_MAX; pipelayer += PIPING_LAYER_INCREMENT) + if(layer_nodes[pipelayer]) //we are connected at this layer + + var/layer_diff = pipelayer - PIPING_LAYER_DEFAULT + + var/image/con = image(icon(src.icon,"manifoldl_con",src.dir)) + con.pixel_x = layer_diff * PIPING_LAYER_P_X + con.pixel_y = layer_diff * PIPING_LAYER_P_Y + + overlays += con + + if(!other_node && !(locate(/obj/machinery/atmospherics) in layer_nodes)) + qdel(src) + return + + +/obj/machinery/atmospherics/pipe/layer_manifold/initialize(var/skip_update_icon=0) + + findAllConnections(initialize_directions) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + if(!skip_update_icon) + update_icon() + +/obj/machinery/atmospherics/pipe/layer_manifold/findAllConnections(var/connect_dirs) + for(var/direction in cardinal) + if(connect_dirs & direction) + if(direction == dir) //we're facing this + for(var/i = PIPING_LAYER_MIN; i <= PIPING_LAYER_MAX; i += PIPING_LAYER_INCREMENT) + var/obj/machinery/atmospherics/found + var/node_type=getNodeType(i) + switch(node_type) + if(PIPE_TYPE_STANDARD) + found = findConnecting(direction, i) //we pass the layer to find the pipe + if(PIPE_TYPE_HE) + found = findConnectingHE(direction, i) + else + error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([i]): [node_type]") + return + if(!found) + continue + layer_nodes[i] = found //put it in the list + else + var/obj/machinery/atmospherics/found + var/node_type=getNodeType(direction) + switch(node_type) + if(PIPE_TYPE_STANDARD) + found = findConnecting(direction) + if(PIPE_TYPE_HE) + found = findConnectingHE(direction) + else + error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([direction]): [node_type]") + if(!found) + continue + other_node = found + +/obj/machinery/atmospherics/pipe/layer_manifold/isConnectable(var/obj/machinery/atmospherics/target, var/direction, var/given_layer) + if(direction == turn(src.dir, 180)) + return (given_layer == PIPING_LAYER_DEFAULT) + return ..() + +/obj/machinery/atmospherics/pipe/layer_manifold/getNodeType() + return PIPE_TYPE_STANDARD + +//We would normally set layer here, but I don't want to +/obj/machinery/atmospherics/pipe/layer_manifold/Entered() + return + +/obj/machinery/atmospherics/pipe/layer_manifold/relaymove(mob/living/user, direction) + if(!(direction & initialize_directions)) //can't go in a way we aren't connecting to + var/layer_mod = 0 + + if(dir & (NORTH|SOUTH)) + if(direction == EAST) //Going up in layers + layer_mod = 1 + else + layer_mod = -1 + else + if(direction == SOUTH) // + layer_mod = 1 + else + layer_mod = -1 + + user.ventcrawl_layer = Clamp(user.ventcrawl_layer + layer_mod, PIPING_LAYER_MIN, PIPING_LAYER_MAX) + to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.") + return 1 + else + if(direction != dir && user.ventcrawl_layer != PIPING_LAYER_DEFAULT) // The mob is moving to the single pipe outlet, we need to align it if it's on a layer that's not the default layer + user.ventcrawl_layer = PIPING_LAYER_DEFAULT + to_chat(user, "You are redirected into the [user.ventcrawl_layer]\th piping layer.") + + return ..() + + +/obj/machinery/atmospherics/pipe/layer_adapter + name = "pipe-layer adapter" + + icon = 'icons/obj/atmospherics/pipe_adapter.dmi' + icon_state = "adapter_1" + baseicon = "adapter" + + color = PIPE_COLOR_GREY + + dir = SOUTH + initialize_directions = NORTH|SOUTH + + volume = 260 //6 averaged pipe segments + + pipe_flags = ALL_LAYER + + var/obj/machinery/atmospherics/layer_node = null + var/obj/machinery/atmospherics/mid_node = null + +/obj/machinery/atmospherics/pipe/layer_adapter/New() + ..() + switch(dir) + if(NORTH,SOUTH) + initialize_directions = NORTH|SOUTH + if(EAST,WEST) + initialize_directions = EAST|WEST + +/obj/machinery/atmospherics/pipe/layer_adapter/setPipingLayer(var/new_layer = PIPING_LAYER_DEFAULT) + piping_layer = new_layer + +/obj/machinery/atmospherics/pipe/layer_adapter/buildFrom(var/mob/usr,var/obj/item/pipe/pipe) + dir = pipe.dir + initialize_directions = pipe.get_pipe_dir() + var/turf/T = loc + level = T.intact ? 2 : 1 + initialize(1) + if(!mid_node && !layer_node) + to_chat(usr, "There's nothing to connect this adapter to! A pipe segment must be connected to at least one other object!") + return 0 + update_icon() + build_network() + if (mid_node) + mid_node.initialize() + mid_node.build_network() + if (layer_node) + layer_node.initialize() + layer_node.build_network() + return 1 + +/obj/machinery/atmospherics/pipe/layer_adapter/hide(var/i) + if(level == 1 && istype(loc, /turf/simulated)) + invisibility = i ? 101 : 0 + update_icon() + +/obj/machinery/atmospherics/pipe/layer_adapter/pipeline_expansion() + return list(layer_node, mid_node) + + +/obj/machinery/atmospherics/pipe/layer_adapter/process() + if(!parent) + . = ..() + atmos_machines.Remove(src) + +/obj/machinery/atmospherics/pipe/layer_adapter/Destroy() + if(mid_node) + mid_node.disconnect(src) + if(layer_node) + layer_node.disconnect(src) + ..() + + +/obj/machinery/atmospherics/pipe/layer_adapter/disconnect(var/obj/machinery/atmospherics/reference) + if(reference == mid_node) + if(istype(mid_node, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + mid_node = null + if(reference == layer_node) + if(istype(layer_node, /obj/machinery/atmospherics/pipe) && !isnull(parent)) + returnToPool(parent) + layer_node = null + + update_icon() + + ..() + +/obj/machinery/atmospherics/pipe/layer_adapter/update_icon() + overlays.len = 0 + alpha = invisibility ? 128 : 255 + icon_state = "[baseicon]_[piping_layer]" + if(layer_node) + var/layer_diff = piping_layer - PIPING_LAYER_DEFAULT + + var/image/con = image(icon(src.icon,"layer_con",turn(src.dir,180))) + con.pixel_x = layer_diff * PIPING_LAYER_P_X + con.pixel_y = layer_diff * PIPING_LAYER_P_Y + + overlays += con + if(!mid_node && !layer_node) + qdel(src) + return + + +/obj/machinery/atmospherics/pipe/layer_adapter/initialize(var/skip_update_icon=0) + + findAllConnections(initialize_directions) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + if(!skip_update_icon) + update_icon() + +/obj/machinery/atmospherics/pipe/layer_adapter/findAllConnections(var/connect_dirs) + for(var/direction in cardinal) + if(connect_dirs & direction) + if(direction == dir) //we're facing this + var/obj/machinery/atmospherics/found + var/node_type=getNodeType(direction) + switch(node_type) + if(PIPE_TYPE_STANDARD) + found = findConnecting(direction, PIPING_LAYER_DEFAULT) + if(PIPE_TYPE_HE) + found = findConnectingHE(direction, PIPING_LAYER_DEFAULT) + else + error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([direction]): [node_type]") + if(!found) + continue + mid_node = found + else + var/obj/machinery/atmospherics/found + var/node_type=getNodeType(direction) + switch(node_type) + if(PIPE_TYPE_STANDARD) + found = findConnecting(direction, piping_layer) //we pass the layer to find the pipe + if(PIPE_TYPE_HE) + found = findConnectingHE(direction, piping_layer) + else + error("UNKNOWN RESPONSE FROM [src.type]/getNodeType([piping_layer]): [node_type]") + return + if(!found) + continue + layer_node = found + +/obj/machinery/atmospherics/pipe/layer_adapter/isConnectable(var/obj/machinery/atmospherics/target, var/direction, var/given_layer) + if(direction == dir) + return (given_layer == PIPING_LAYER_DEFAULT) + return ..() + +/obj/machinery/atmospherics/pipe/layer_adapter/getNodeType() + return PIPE_TYPE_STANDARD + +//We would normally set layer here, but I don't want to +/obj/machinery/atmospherics/pipe/layer_adapter/Entered() + return + +/obj/machinery/atmospherics/pipe/layer_adapter/relaymove(mob/living/user, direction) + // Autoset layer + if(direction & initialize_directions) + user.ventcrawl_layer = (direction == dir) ? PIPING_LAYER_DEFAULT : piping_layer + to_chat(user, "You are redirected into the [user.ventcrawl_layer]\th piping layer.") + return ..() diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm index aa3b3c74382..00ed5543daa 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm @@ -1,50 +1,50 @@ - -//---------- actual energy field - -/obj/effect/energy_field - name = "energy field" - desc = "Impenetrable field of energy, capable of blocking anything as long as it's active." - icon = 'code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi' - icon_state = "shieldsparkles" - anchored = 1 - layer = 4.1 //just above mobs - density = 0 - invisibility = 101 - var/strength = 0 - -/obj/effect/energy_field/ex_act(var/severity) - Stress(0.5 + severity) - -/obj/effect/energy_field/bullet_act(var/obj/item/projectile/Proj) - Stress(Proj.damage / 10) - -/obj/effect/energy_field/proc/Stress(var/severity) - strength -= severity - - //if we take too much damage, drop out - the generator will bring us back up if we have enough power - if(strength < 1) - invisibility = 101 - density = 0 - else if(strength >= 1) - invisibility = 0 - density = 1 - -/obj/effect/energy_field/proc/Strengthen(var/severity) - strength += severity - - //if we take too much damage, drop out - the generator will bring us back up if we have enough power - if(strength >= 1) - invisibility = 0 - density = 1 - else if(strength < 1) - invisibility = 101 - density = 0 - -/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - //Purpose: Determines if the object (or airflow) can pass this atom. - //Called by: Movement, airflow. - //Inputs: The moving atom (optional), target turf, "height" and air group - //Outputs: Boolean if can pass. - - //return (!density || !height || air_group) - return !density + +//---------- actual energy field + +/obj/effect/energy_field + name = "energy field" + desc = "Impenetrable field of energy, capable of blocking anything as long as it's active." + icon = 'code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi' + icon_state = "shieldsparkles" + anchored = 1 + layer = 4.1 //just above mobs + density = 0 + invisibility = 101 + var/strength = 0 + +/obj/effect/energy_field/ex_act(var/severity) + Stress(0.5 + severity) + +/obj/effect/energy_field/bullet_act(var/obj/item/projectile/Proj) + Stress(Proj.damage / 10) + +/obj/effect/energy_field/proc/Stress(var/severity) + strength -= severity + + //if we take too much damage, drop out - the generator will bring us back up if we have enough power + if(strength < 1) + invisibility = 101 + density = 0 + else if(strength >= 1) + invisibility = 0 + density = 1 + +/obj/effect/energy_field/proc/Strengthen(var/severity) + strength += severity + + //if we take too much damage, drop out - the generator will bring us back up if we have enough power + if(strength >= 1) + invisibility = 0 + density = 1 + else if(strength < 1) + invisibility = 101 + density = 0 + +/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + //Purpose: Determines if the object (or airflow) can pass this atom. + //Called by: Movement, airflow. + //Inputs: The moving atom (optional), target turf, "height" and air group + //Outputs: Boolean if can pass. + + //return (!density || !height || air_group) + return !density diff --git a/code/WorkInProgress/Cael_Aislinn/sculpture.dm b/code/WorkInProgress/Cael_Aislinn/sculpture.dm index f72c1d025ba..5c759209500 100644 --- a/code/WorkInProgress/Cael_Aislinn/sculpture.dm +++ b/code/WorkInProgress/Cael_Aislinn/sculpture.dm @@ -1,266 +1,266 @@ -//sculpture -//SCP-173, nothing more need be said -/mob/living/simple_animal/sculpture - name = "SCP-173" - desc = "It's some kind of hastily-painted human-size stone sculpture. Just looking at it makes you feel nervous." - icon = 'code/WorkInProgress/Cael_Aislinn/unknown.dmi' - icon_state = "sculpture" - icon_living = "sculpture" - icon_dead = "sculpture" - emote_hear = list("makes a faint scraping sound") - emote_see = list("twitches slightly", "shivers") - response_help = "touches the" - response_disarm = "pushes the" - response_harm = "hits the" - meat_type = null - var/response_snap = "snapped the neck of" //Past tense because it "happened before you could see it" - var/response_snap_target = "In the blink of an eye, something grabs you and snaps your neck!" - var/snap_sound = list('sound/scp/firstpersonsnap.ogg','sound/scp/firstpersonsnap2.ogg','sound/scp/firstpersonsnap3.ogg') - var/scare_sound = list('sound/scp/scare1.ogg','sound/scp/scare2.ogg','sound/scp/scare3.ogg','sound/scp/scare4.ogg') //Boo - var/obj/item/weapon/grab/G - var/observed = 0 - var/hibernate = 0 //Disables SCP until toggled back to 0 - var/scare_played = 0 //Did we rape everyone's ears yet ? - var/obj/machinery/atmospherics/unary/vent_pump/entry_vent //Graciously stolen from spider code - -/mob/living/simple_animal/sculpture/proc/GrabMob(var/mob/living/target) - if(target && target != src && ishuman(target) && !observed) - G = getFromPool(/obj/item/weapon/grab,src,target) - target.Stun(1) - target.Paralyse(1) - G.loc = src - target.grabbed_by += G - G.synch() - target.LAssailant = src - //Killing people has been extradited here for reasons, SCP still looks to grab targets on his turf later down - target.apply_damage(rand(120,150), BRUTE, "head") - - playsound(target.loc, pick(snap_sound), 100, 1, -1) - visible_message("[src] [response_snap] [target]!") +//sculpture +//SCP-173, nothing more need be said +/mob/living/simple_animal/sculpture + name = "SCP-173" + desc = "It's some kind of hastily-painted human-size stone sculpture. Just looking at it makes you feel nervous." + icon = 'code/WorkInProgress/Cael_Aislinn/unknown.dmi' + icon_state = "sculpture" + icon_living = "sculpture" + icon_dead = "sculpture" + emote_hear = list("makes a faint scraping sound") + emote_see = list("twitches slightly", "shivers") + response_help = "touches the" + response_disarm = "pushes the" + response_harm = "hits the" + meat_type = null + var/response_snap = "snapped the neck of" //Past tense because it "happened before you could see it" + var/response_snap_target = "In the blink of an eye, something grabs you and snaps your neck!" + var/snap_sound = list('sound/scp/firstpersonsnap.ogg','sound/scp/firstpersonsnap2.ogg','sound/scp/firstpersonsnap3.ogg') + var/scare_sound = list('sound/scp/scare1.ogg','sound/scp/scare2.ogg','sound/scp/scare3.ogg','sound/scp/scare4.ogg') //Boo + var/obj/item/weapon/grab/G + var/observed = 0 + var/hibernate = 0 //Disables SCP until toggled back to 0 + var/scare_played = 0 //Did we rape everyone's ears yet ? + var/obj/machinery/atmospherics/unary/vent_pump/entry_vent //Graciously stolen from spider code + +/mob/living/simple_animal/sculpture/proc/GrabMob(var/mob/living/target) + if(target && target != src && ishuman(target) && !observed) + G = getFromPool(/obj/item/weapon/grab,src,target) + target.Stun(1) + target.Paralyse(1) + G.loc = src + target.grabbed_by += G + G.synch() + target.LAssailant = src + //Killing people has been extradited here for reasons, SCP still looks to grab targets on his turf later down + target.apply_damage(rand(120,150), BRUTE, "head") + + playsound(target.loc, pick(snap_sound), 100, 1, -1) + visible_message("[src] [response_snap] [target]!") to_chat(target, "[response_snap_target] Your vision fades away...") - target.attack_log += text("\[[time_stamp()]\] Had his neck snapped by [src]!") - log_admin("[target] ([target.ckey]) had his neck snapped by an active [src].") - message_admins("ALERT: [target.real_name] had his neck snapped by an active [src].") - - //Instead of making SCP piss around, let's have him snap more necks - del(G) - -/mob/living/simple_animal/sculpture/Life() - if(timestopped) return 0 //under effects of time magick - - //If we are hibernating, just don't do anything - if(hibernate) - return - - // Grabbing (kept just in case) - if(G) - G.process() - - for(var/mob/living/carbon/human/M in view(7, src)) //Only humans - if(M.stat || M == src) - continue - var/xdif = M.x - src.x - var/ydif = M.y - src.y - if(!(ydif == 0)) // If we are not on the same vertical plane (up/down) - //mob is either above or below src - //We'll estimate that humans have a perfect 180 degrees view for simplicity, quite zanny - if(ydif < 0 && M.dir == NORTH) - //mob is below src and looking up - observed = 1 - break - else if(ydif > 0 && M.dir == SOUTH) - //mob is above src and looking down - observed = 1 - break - if(!(xdif == 0)) // If we are not on the same horizontal plane (left/right) - //mob is either left or right of src - if(xdif < 0 && M.dir == EAST) - //mob is to the left of src and looking right - observed = 1 - break - else if(xdif > 0 && M.dir == WEST) - //mob is to the right of src and looking left - observed = 1 - break - else if (xdif == 0 && ydif == 0) //SCP is on the same tile. So technically, in the mob's back - observed = 0 - //breaks the sculpture since it's target can observe it, changed to observed = 0 - else - observed = 0 - //otherwise we don't understand your situation, it's pretty non-euclidian, just move - - //account for darkness - var/turf/T = get_turf(src) - var/in_darkness = 0 - if(T.luminosity == 0 && !istype(T, /turf/unsimulated)) //Let's only bother with dark tiles. Unsimulated tiles can't run this check for reference. - in_darkness = 1 - - - if(observed && !in_darkness) //Is someone looking at us, given that they can see us ? - return //Try again when we get a chance - - //see if we're able to strangle anyone - for(var/mob/living/carbon/human/M in T) - if(M.stat == CONSCIOUS) - GrabMob(M) - break - - //find out what mobs we can see (-tried to- remove sight and doubled range) - //var/list/incapacitated = list() - var/list/conscious = list() - for(var/mob/living/carbon/human/M in view(7, src)) - //this may not be quite the right test - if(M == src) - continue - if (M.stat == CONSCIOUS) - conscious.Add(M) - - //pick the nearest valid conscious target - var/mob/living/carbon/human/target - for(var/mob/living/carbon/human/M in conscious) - if(!target || get_dist(src, M) < get_dist(src, target)) - target = M - - if(target) - var/turf/target_turf - if(in_darkness) - //move to right behind them - target_turf = get_step(target, src) - if(scare_played == 0) //Let's minimize the spam - playsound(loc, pick(scare_sound), 100, 1, -1) - scare_played = 1 - spawn(50) - scare_played = 0 - else - //move to them really really fast and knock them down - target_turf = get_turf(target) - if(scare_played == 0) //Let's minimize the spam - playsound(loc, pick(scare_sound), 100, 1, -1) - scare_played = 1 - spawn(50) - scare_played = 0 - - //rampage along a path to get to them, in the blink of an eye - var/turf/next_turf = get_step_towards(src, target) - var/num_turfs = get_dist(src,target) - spawn() - while(get_turf(src) != target_turf && num_turfs > 0) - for(var/obj/structure/window/W in next_turf) - W.Destroy(brokenup = 1) - sleep(5) - for(var/obj/structure/table/O in next_turf) - O.ex_act(1) - sleep(10) - for(var/obj/structure/grille/G in next_turf) - G.ex_act(1) - sleep(10) - for(var/obj/machinery/door/airlock/A in next_turf) //Snowflakey code to take in account bolts and welding - if(A.welded || A.locked) - break - A.open() - sleep(10) - for(var/obj/machinery/door/D in next_turf) - D.open() - sleep(10) - if(!next_turf.CanPass(src, next_turf)) - break - src.loc = next_turf - src.dir = get_dir(src, target) - next_turf = get_step(src, get_dir(next_turf,target)) - num_turfs-- - - //if we're not strangling anyone, take a stroll - if(prob(30)) //30 % of dance of its people - var/list/turfs = new/list() - for(var/turf/thisturf in view(7,src)) - if(istype(thisturf, /turf/space)) - continue - else if(istype(thisturf, /turf/simulated/wall)) - continue - else if(istype(thisturf, /turf/unsimulated/mineral)) - continue - else if(istype(thisturf, /turf/simulated/shuttle/wall)) - continue - else if(istype(thisturf, /turf/unsimulated/wall)) - continue - turfs += thisturf - var/turf/target_turf = safepick(turfs) - if(!target_turf) return - //MUH 6 QUADRILLION WINDOWS - //rampage along a path to get to it, in the blink of an eye - var/turf/next_turf = get_step_towards(src, target_turf) - var/num_turfs = get_dist(src,target_turf) - spawn() - while(get_turf(src) != target_turf && num_turfs > 0) - for(var/obj/structure/window/W in next_turf) - W.Destroy(brokenup = 1) - sleep(5) - for(var/obj/structure/table/O in next_turf) - O.ex_act(1) - sleep(5) - for(var/obj/structure/grille/G in next_turf) - G.ex_act(1) - sleep(5) - for(var/obj/machinery/door/D in next_turf) - D.open() - sleep(5) - if(!next_turf.CanPass(src, next_turf)) - break - src.loc = next_turf - src.dir = get_dir(src, target) - next_turf = get_step(src, get_dir(next_turf,target_turf)) - num_turfs-- - //Coding note : This is known to allow SCP to end up on tiles that contain obstructing structures (doors, machinery, etc) - //Although he CAN'T pass through them during normal movement. Will look into a fix soon - - //Do we have a vent ? Good, let's take a look - for(entry_vent in view(1, src)) - if(prob(75)) - return //Ignore that vent for this tick - sleep(5) //Let's stop SCP-173 for half a second to take a look - ..() - if(entry_vent.network && entry_vent.network.normal_members.len) - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in entry_vent.network.normal_members) - vents.Add(temp_vent) - if(!vents.len) - entry_vent = null - return - var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = pick(vents) - spawn() - visible_message("[src] suddenly disappears into the vent !") - loc = exit_vent - var/travel_time = round(get_dist(loc, exit_vent.loc)/2) - spawn(travel_time) - - if(!exit_vent || exit_vent.welded) - loc = entry_vent - entry_vent = null - return - - loc = exit_vent.loc - entry_vent = null - var/area/new_area = get_area(loc) - if(new_area) - new_area.Entered(src) - visible_message("[src] suddenly appears from the vent !") - else - entry_vent = null - -/mob/living/simple_animal/sculpture/attackby(var/obj/item/O as obj, var/mob/user as mob) - ..() - -/mob/living/simple_animal/sculpture/Topic(href, href_list) - ..() - -/mob/living/simple_animal/sculpture/Bump(atom/movable/AM as mob, yes) - if(!G && !observed) - GrabMob(AM) - ..() - -/mob/living/simple_animal/sculpture/Bumped(atom/movable/AM as mob, yes) - if(!G && !observed) - GrabMob(AM) - -/mob/living/simple_animal/sculpture/ex_act(var/severity) - //You cannot destroy SCP-173, fool ! + target.attack_log += text("\[[time_stamp()]\] Had his neck snapped by [src]!") + log_admin("[target] ([target.ckey]) had his neck snapped by an active [src].") + message_admins("ALERT: [target.real_name] had his neck snapped by an active [src].") + + //Instead of making SCP piss around, let's have him snap more necks + del(G) + +/mob/living/simple_animal/sculpture/Life() + if(timestopped) return 0 //under effects of time magick + + //If we are hibernating, just don't do anything + if(hibernate) + return + + // Grabbing (kept just in case) + if(G) + G.process() + + for(var/mob/living/carbon/human/M in view(7, src)) //Only humans + if(M.stat || M == src) + continue + var/xdif = M.x - src.x + var/ydif = M.y - src.y + if(!(ydif == 0)) // If we are not on the same vertical plane (up/down) + //mob is either above or below src + //We'll estimate that humans have a perfect 180 degrees view for simplicity, quite zanny + if(ydif < 0 && M.dir == NORTH) + //mob is below src and looking up + observed = 1 + break + else if(ydif > 0 && M.dir == SOUTH) + //mob is above src and looking down + observed = 1 + break + if(!(xdif == 0)) // If we are not on the same horizontal plane (left/right) + //mob is either left or right of src + if(xdif < 0 && M.dir == EAST) + //mob is to the left of src and looking right + observed = 1 + break + else if(xdif > 0 && M.dir == WEST) + //mob is to the right of src and looking left + observed = 1 + break + else if (xdif == 0 && ydif == 0) //SCP is on the same tile. So technically, in the mob's back + observed = 0 + //breaks the sculpture since it's target can observe it, changed to observed = 0 + else + observed = 0 + //otherwise we don't understand your situation, it's pretty non-euclidian, just move + + //account for darkness + var/turf/T = get_turf(src) + var/in_darkness = 0 + if(T.luminosity == 0 && !istype(T, /turf/unsimulated)) //Let's only bother with dark tiles. Unsimulated tiles can't run this check for reference. + in_darkness = 1 + + + if(observed && !in_darkness) //Is someone looking at us, given that they can see us ? + return //Try again when we get a chance + + //see if we're able to strangle anyone + for(var/mob/living/carbon/human/M in T) + if(M.stat == CONSCIOUS) + GrabMob(M) + break + + //find out what mobs we can see (-tried to- remove sight and doubled range) + //var/list/incapacitated = list() + var/list/conscious = list() + for(var/mob/living/carbon/human/M in view(7, src)) + //this may not be quite the right test + if(M == src) + continue + if (M.stat == CONSCIOUS) + conscious.Add(M) + + //pick the nearest valid conscious target + var/mob/living/carbon/human/target + for(var/mob/living/carbon/human/M in conscious) + if(!target || get_dist(src, M) < get_dist(src, target)) + target = M + + if(target) + var/turf/target_turf + if(in_darkness) + //move to right behind them + target_turf = get_step(target, src) + if(scare_played == 0) //Let's minimize the spam + playsound(loc, pick(scare_sound), 100, 1, -1) + scare_played = 1 + spawn(50) + scare_played = 0 + else + //move to them really really fast and knock them down + target_turf = get_turf(target) + if(scare_played == 0) //Let's minimize the spam + playsound(loc, pick(scare_sound), 100, 1, -1) + scare_played = 1 + spawn(50) + scare_played = 0 + + //rampage along a path to get to them, in the blink of an eye + var/turf/next_turf = get_step_towards(src, target) + var/num_turfs = get_dist(src,target) + spawn() + while(get_turf(src) != target_turf && num_turfs > 0) + for(var/obj/structure/window/W in next_turf) + W.Destroy(brokenup = 1) + sleep(5) + for(var/obj/structure/table/O in next_turf) + O.ex_act(1) + sleep(10) + for(var/obj/structure/grille/G in next_turf) + G.ex_act(1) + sleep(10) + for(var/obj/machinery/door/airlock/A in next_turf) //Snowflakey code to take in account bolts and welding + if(A.welded || A.locked) + break + A.open() + sleep(10) + for(var/obj/machinery/door/D in next_turf) + D.open() + sleep(10) + if(!next_turf.CanPass(src, next_turf)) + break + src.loc = next_turf + src.dir = get_dir(src, target) + next_turf = get_step(src, get_dir(next_turf,target)) + num_turfs-- + + //if we're not strangling anyone, take a stroll + if(prob(30)) //30 % of dance of its people + var/list/turfs = new/list() + for(var/turf/thisturf in view(7,src)) + if(istype(thisturf, /turf/space)) + continue + else if(istype(thisturf, /turf/simulated/wall)) + continue + else if(istype(thisturf, /turf/unsimulated/mineral)) + continue + else if(istype(thisturf, /turf/simulated/shuttle/wall)) + continue + else if(istype(thisturf, /turf/unsimulated/wall)) + continue + turfs += thisturf + var/turf/target_turf = safepick(turfs) + if(!target_turf) return + //MUH 6 QUADRILLION WINDOWS + //rampage along a path to get to it, in the blink of an eye + var/turf/next_turf = get_step_towards(src, target_turf) + var/num_turfs = get_dist(src,target_turf) + spawn() + while(get_turf(src) != target_turf && num_turfs > 0) + for(var/obj/structure/window/W in next_turf) + W.Destroy(brokenup = 1) + sleep(5) + for(var/obj/structure/table/O in next_turf) + O.ex_act(1) + sleep(5) + for(var/obj/structure/grille/G in next_turf) + G.ex_act(1) + sleep(5) + for(var/obj/machinery/door/D in next_turf) + D.open() + sleep(5) + if(!next_turf.CanPass(src, next_turf)) + break + src.loc = next_turf + src.dir = get_dir(src, target) + next_turf = get_step(src, get_dir(next_turf,target_turf)) + num_turfs-- + //Coding note : This is known to allow SCP to end up on tiles that contain obstructing structures (doors, machinery, etc) + //Although he CAN'T pass through them during normal movement. Will look into a fix soon + + //Do we have a vent ? Good, let's take a look + for(entry_vent in view(1, src)) + if(prob(75)) + return //Ignore that vent for this tick + sleep(5) //Let's stop SCP-173 for half a second to take a look + ..() + if(entry_vent.network && entry_vent.network.normal_members.len) + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in entry_vent.network.normal_members) + vents.Add(temp_vent) + if(!vents.len) + entry_vent = null + return + var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = pick(vents) + spawn() + visible_message("[src] suddenly disappears into the vent !") + loc = exit_vent + var/travel_time = round(get_dist(loc, exit_vent.loc)/2) + spawn(travel_time) + + if(!exit_vent || exit_vent.welded) + loc = entry_vent + entry_vent = null + return + + loc = exit_vent.loc + entry_vent = null + var/area/new_area = get_area(loc) + if(new_area) + new_area.Entered(src) + visible_message("[src] suddenly appears from the vent !") + else + entry_vent = null + +/mob/living/simple_animal/sculpture/attackby(var/obj/item/O as obj, var/mob/user as mob) + ..() + +/mob/living/simple_animal/sculpture/Topic(href, href_list) + ..() + +/mob/living/simple_animal/sculpture/Bump(atom/movable/AM as mob, yes) + if(!G && !observed) + GrabMob(AM) + ..() + +/mob/living/simple_animal/sculpture/Bumped(atom/movable/AM as mob, yes) + if(!G && !observed) + GrabMob(AM) + +/mob/living/simple_animal/sculpture/ex_act(var/severity) + //You cannot destroy SCP-173, fool ! diff --git a/code/WorkInProgress/explosion_particles.dm b/code/WorkInProgress/explosion_particles.dm index 8c649475bfd..c8346785711 100644 --- a/code/WorkInProgress/explosion_particles.dm +++ b/code/WorkInProgress/explosion_particles.dm @@ -1,106 +1,106 @@ -/obj/effect/expl_particles - name = "explosive particles" - icon = 'icons/effects/effects.dmi' - icon_state = "explosion_particle" - opacity = 1 - anchored = 1 - mouse_opacity = 0 - -/obj/effect/expl_particles/New() - ..() - spawn (15) - qdel(src) - return - -/obj/effect/expl_particles/Move() - ..() - return - -/datum/effect/system/expl_particles - var/number = 10 - var/turf/location - var/total_particles = 0 - -/datum/effect/system/expl_particles/proc/set_up(n = 10, loca) - number = n - if(istype(loca, /turf/)) location = loca - else location = get_turf(loca) - -/datum/effect/system/expl_particles/proc/start() - var/i = 0 - for(i=0, i max) - skipping = 2 - if(copytext(binaries,-4,0) == ".dmb") - if(binary) - warning("Extra DMB [binary] in map folder, skipping.") - continue - binary = binaries - continue - if(skipping) - message_admins("Skipping map [binary] due to [skipping == 1 ? "not enough players." : "too many players."]") - warning("Skipping map [binary] due to [skipping == 1 ? "not enough players." : "too many players."]") - binary = null - continue - if(!binary) - warning("Map folder [path] does not contain a valid byond binary, skipping.") - else - maps[potential] = path + binary - binary = null - recursion_limit-- - return maps - -//Sends resource files to client cache -/client/proc/getFiles() - for(var/file in args) - src << browse_rsc(file) - -/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm", ".csv")) - var/path = root - - for(var/i=0, i max) + skipping = 2 + if(copytext(binaries,-4,0) == ".dmb") + if(binary) + warning("Extra DMB [binary] in map folder, skipping.") + continue + binary = binaries + continue + if(skipping) + message_admins("Skipping map [binary] due to [skipping == 1 ? "not enough players." : "too many players."]") + warning("Skipping map [binary] due to [skipping == 1 ? "not enough players." : "too many players."]") + binary = null + continue + if(!binary) + warning("Map folder [path] does not contain a valid byond binary, skipping.") + else + maps[potential] = path + binary + binary = null + recursion_limit-- + return maps + +//Sends resource files to client cache +/client/proc/getFiles() + for(var/file in args) + src << browse_rsc(file) + +/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm", ".csv")) + var/path = root + + for(var/i=0, iError: browse_files(): File not found/Invalid file([path]).") - return - - return path - -#define FTPDELAY 200 //200 tick delay to discourage spam -/* This proc is a failsafe to prevent spamming of file requests. - It is just a timer that only permits a download every [FTPDELAY] ticks. - This can be changed by modifying FTPDELAY's value above. - - PLEASE USE RESPONSIBLY, Some log files canr each sizes of 4MB! */ -/client/proc/file_spam_check() - var/time_to_wait = fileaccess_timer - world.time - if(time_to_wait > 0) + return + + return path + +#define FTPDELAY 200 //200 tick delay to discourage spam +/* This proc is a failsafe to prevent spamming of file requests. + It is just a timer that only permits a download every [FTPDELAY] ticks. + This can be changed by modifying FTPDELAY's value above. + + PLEASE USE RESPONSIBLY, Some log files canr each sizes of 4MB! */ +/client/proc/file_spam_check() + var/time_to_wait = fileaccess_timer - world.time + if(time_to_wait > 0) to_chat(src, "Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.") - return 1 - fileaccess_timer = world.time + FTPDELAY - return 0 + return 1 + fileaccess_timer = world.time + FTPDELAY + return 0 #undef FTPDELAY \ No newline at end of file diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 81682f6c478..630528f43ec 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -1,67 +1,67 @@ -var/list/clients = list() //list of all clients -var/list/admins = list() //list of all clients whom are admins -var/list/directory = list() //list of all ckeys with associated client - -//Since it didn't really belong in any other category, I'm putting this here -//This is for procs to replace all the goddamn 'in world's that are chilling around the code - -var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player -var/global/list/mob_list = list() //List of all mobs, including clientless -var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player -var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player -var/list/observers = new/list() -var/global/list/areas = list() -var/global/list/turfs = list() - -var/global/list/chemical_reactions_list //list of all /datum/chemical_reaction datums. Used during chemical reactions -var/global/list/chemical_reagents_list //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff -var/global/list/landmarks_list = list() //list of all landmarks created -var/global/list/surgery_steps = list() //list of all surgery steps |BS12 -var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking. - -// Posters -var/global/list/datum/poster/poster_designs = typesof(/datum/poster) - /datum/poster - /datum/poster/goldstar - -//Preferences stuff - //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") - //Backpacks -var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt") - -// This is stupid as fuck. -var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") - -//*-hud user lists -var/global/list/table_recipes = list() //list of all table craft recipes -var/global/list/med_hud_users = list() //list of all entities using a medical HUD. -var/global/list/sec_hud_users = list() //list of all entities using a security HUD. - -////////////////////////// -/////Initial Building///// -////////////////////////// - -/proc/make_datum_references_lists() - var/list/paths - //Surgery Steps - Initialize all /datum/surgery_step into a list - paths = typesof(/datum/surgery_step)-/datum/surgery_step - for(var/T in paths) - var/datum/surgery_step/S = new T - surgery_steps += S - sort_surgeries() - - -/* // Uncomment to debug chemical reaction list. -/client/verb/debug_chemical_list() - - - for (var/reaction in chemical_reactions_list) - . += "chemical_reactions_list\[\"[reaction]\"\] = \"[chemical_reactions_list[reaction]]\"\n" - if(islist(chemical_reactions_list[reaction])) - var/list/L = chemical_reactions_list[reaction] - for(var/t in L) - . += " has: [t]\n" +var/list/clients = list() //list of all clients +var/list/admins = list() //list of all clients whom are admins +var/list/directory = list() //list of all ckeys with associated client + +//Since it didn't really belong in any other category, I'm putting this here +//This is for procs to replace all the goddamn 'in world's that are chilling around the code + +var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player +var/global/list/mob_list = list() //List of all mobs, including clientless +var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player +var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player +var/list/observers = new/list() +var/global/list/areas = list() +var/global/list/turfs = list() + +var/global/list/chemical_reactions_list //list of all /datum/chemical_reaction datums. Used during chemical reactions +var/global/list/chemical_reagents_list //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff +var/global/list/landmarks_list = list() //list of all landmarks created +var/global/list/surgery_steps = list() //list of all surgery steps |BS12 +var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking. + +// Posters +var/global/list/datum/poster/poster_designs = typesof(/datum/poster) - /datum/poster - /datum/poster/goldstar + +//Preferences stuff + //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") + //Backpacks +var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt") + +// This is stupid as fuck. +var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") + +//*-hud user lists +var/global/list/table_recipes = list() //list of all table craft recipes +var/global/list/med_hud_users = list() //list of all entities using a medical HUD. +var/global/list/sec_hud_users = list() //list of all entities using a security HUD. + +////////////////////////// +/////Initial Building///// +////////////////////////// + +/proc/make_datum_references_lists() + var/list/paths + //Surgery Steps - Initialize all /datum/surgery_step into a list + paths = typesof(/datum/surgery_step)-/datum/surgery_step + for(var/T in paths) + var/datum/surgery_step/S = new T + surgery_steps += S + sort_surgeries() + + +/* // Uncomment to debug chemical reaction list. +/client/verb/debug_chemical_list() + + + for (var/reaction in chemical_reactions_list) + . += "chemical_reactions_list\[\"[reaction]\"\] = \"[chemical_reactions_list[reaction]]\"\n" + if(islist(chemical_reactions_list[reaction])) + var/list/L = chemical_reactions_list[reaction] + for(var/t in L) + . += " has: [t]\n" to_chat(world, .) -*/ - +*/ + var/global/list/escape_list = list() \ No newline at end of file diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 9bcdaac70b1..693937fcf31 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1,136 +1,136 @@ -proc - getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N - var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. - for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. - if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. - var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. - //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. - alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. - return alpha_mask//And now return the mask. - -/mob/proc/AddCamoOverlay(atom/A)//A is the atom which we are using as the overlay. - var/icon/opacity_icon = new(A.icon, A.icon_state)//Don't really care for overlays/underlays. - //Now we need to culculate overlays+underlays and add them together to form an image for a mask. - //var/icon/alpha_mask = getFlatIcon(src)//Accurate but SLOW. Not designed for running each tick. Could have other uses I guess. - var/icon/alpha_mask = getIconMask(src)//Which is why I created that proc. Also a little slow since it's blending a bunch of icons together but good enough. - opacity_icon.AddAlphaMask(alpha_mask)//Likely the main source of lag for this proc. Probably not designed to run each tick. - opacity_icon.ChangeOpacity(0.4)//Front end for MapColors so it's fast. 0.5 means half opacity and looks the best in my opinion. - for(var/i=0,i<5,i++)//And now we add it as overlays. It's faster than creating an icon and then merging it. - var/image/I = image("icon" = opacity_icon, "icon_state" = A.icon_state, "layer" = layer+0.8)//So it's above other stuff but below weapons and the like. - switch(i)//Now to determine offset so the result is somewhat blurred. - if(1) I.pixel_x-- - if(2) I.pixel_x++ - if(3) I.pixel_y-- - if(4) I.pixel_y++ - overlays += I//And finally add the overlay. - -/proc/getHologramIcon(icon/A, safety=1)//If safety is on, a new icon is not created. - var/icon/flat_icon = safety ? A : new(A)//Has to be a new icon to not constantly change the same icon. - flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish. - flat_icon.ChangeOpacity(0.5)//Make it half transparent. - var/icon/alpha_mask = new('icons/effects/effects.dmi', "scanline")//Scanline effect. - flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect. - return flat_icon - -/proc/getStaticIcon(icon/A, safety=1) - var/icon/flat_icon = safety ? A : new(A) - flat_icon.Blend(rgb(255, 255, 255)) - flat_icon.BecomeAlphaMask() - var/icon/static_icon = new/icon('icons/effects/effects.dmi', "static_base") - static_icon.AddAlphaMask(flat_icon) - return static_icon - -/proc/getBlankIcon(icon/A, safety=1) - var/icon/flat_icon = safety ? A : new(A) - flat_icon.Blend(rgb(255, 255, 255)) - flat_icon.BecomeAlphaMask() - var/icon/blank_icon = new/icon('icons/effects/effects.dmi', "blank_base") - blank_icon.AddAlphaMask(flat_icon) - return blank_icon - -/proc/getLetterImage(atom/A, letter = "", uppercase = 0) - if(!A) - return - - var/icon/atom_icon = new(A.icon, A.icon_state) - - if(!letter) - letter = copytext(A.name, 1, 2) - if(uppercase == 1) - letter = uppertext(letter) - else if(uppercase == -1) - letter = lowertext(letter) - - var/image/text_image = new(loc = A) - text_image.maptext = "[letter]" - text_image.color = AverageColor(atom_icon) - text_image.pixel_x = 6 - text_image.pixel_y = 5 - del(atom_icon) - return text_image - -//For photo camera. -/proc/build_composite_icon(atom/A) - var/icon/composite = icon(A.icon, A.icon_state, A.dir, 1) - for(var/O in A.overlays) - var/image/I = O - var/icon/C = icon(I.icon, I.icon_state, I.dir, 1) - C.Blend(I.color, ICON_MULTIPLY) - composite.Blend(C, ICON_OVERLAY) - return composite - -proc/adjust_brightness(var/color, var/value) - if (!color) return "#FFFFFF" - if (!value) return color - - var/list/RGB = ReadRGB(color) - RGB[1] = Clamp(RGB[1]+value,0,255) - RGB[2] = Clamp(RGB[2]+value,0,255) - RGB[3] = Clamp(RGB[3]+value,0,255) - return rgb(RGB[1],RGB[2],RGB[3]) - -/proc/ListColors(var/icon/I, var/ignoreGreyscale = 0) - var/list/colors = list() - for(var/x_pixel = 1 to I.Width()) - for(var/y_pixel = 1 to I.Height()) - var/this_color = I.GetPixel(x_pixel, y_pixel) - if(this_color) - if (ignoreGreyscale && ReadHSV(RGBtoHSV(this_color))[2] == 0) //If saturation is 0, must be greyscale - continue - colors.Add(this_color) - return colors - -/proc/AverageColor(var/icon/I, var/accurate = 0, var/ignoreGreyscale = 0) -//Accurate: Use more accurate color averaging, usually has better results and prevents muddied or overly dark colors. Mad thanks to wwjnc. -//ignoreGreyscale: Excempts greyscale colors from the color list, useful for filtering outlines or plate overlays. - var/list/colors = ListColors(I, ignoreGreyscale) - if(!colors.len) - return null - - var/list/colorsum = list(0, 0, 0) //Holds the sum of the RGB values to calculate the average - var/list/RGB = list(0, 0, 0) //Temp list for each color - var/total = colors.len - - var/final_average - if (accurate) //keeping it legible - for(var/i = 1 to total) - RGB = ReadRGB(colors[i]) - colorsum[1] += RGB[1]*RGB[1] - colorsum[2] += RGB[2]*RGB[2] - colorsum[3] += RGB[3]*RGB[3] - final_average = rgb(sqrt(colorsum[1]/total), sqrt(colorsum[2]/total), sqrt(colorsum[3]/total)) - else - for(var/i = 1 to total) - RGB = ReadRGB(colors[i]) - colorsum[1] += RGB[1] - colorsum[2] += RGB[2] - colorsum[3] += RGB[3] - final_average = rgb(colorsum[1]/total, colorsum[2]/total, colorsum[3]/total) - return final_average - -/proc/empty_Y_space(var/icon/I) //Returns the amount of lines containing only transparent pixels in an icon, starting from the bottom - for(var/y_pixel = 1 to I.Height()) - for(var/x_pixel = 1 to I.Width()) - if (I.GetPixel(x_pixel, y_pixel)) - return y_pixel - 1 - return null +proc + getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N + var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. + for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. + if(I:layer>A.layer) continue//If layer is greater than what we need, skip it. + var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. + //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. + alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. + return alpha_mask//And now return the mask. + +/mob/proc/AddCamoOverlay(atom/A)//A is the atom which we are using as the overlay. + var/icon/opacity_icon = new(A.icon, A.icon_state)//Don't really care for overlays/underlays. + //Now we need to culculate overlays+underlays and add them together to form an image for a mask. + //var/icon/alpha_mask = getFlatIcon(src)//Accurate but SLOW. Not designed for running each tick. Could have other uses I guess. + var/icon/alpha_mask = getIconMask(src)//Which is why I created that proc. Also a little slow since it's blending a bunch of icons together but good enough. + opacity_icon.AddAlphaMask(alpha_mask)//Likely the main source of lag for this proc. Probably not designed to run each tick. + opacity_icon.ChangeOpacity(0.4)//Front end for MapColors so it's fast. 0.5 means half opacity and looks the best in my opinion. + for(var/i=0,i<5,i++)//And now we add it as overlays. It's faster than creating an icon and then merging it. + var/image/I = image("icon" = opacity_icon, "icon_state" = A.icon_state, "layer" = layer+0.8)//So it's above other stuff but below weapons and the like. + switch(i)//Now to determine offset so the result is somewhat blurred. + if(1) I.pixel_x-- + if(2) I.pixel_x++ + if(3) I.pixel_y-- + if(4) I.pixel_y++ + overlays += I//And finally add the overlay. + +/proc/getHologramIcon(icon/A, safety=1)//If safety is on, a new icon is not created. + var/icon/flat_icon = safety ? A : new(A)//Has to be a new icon to not constantly change the same icon. + flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish. + flat_icon.ChangeOpacity(0.5)//Make it half transparent. + var/icon/alpha_mask = new('icons/effects/effects.dmi', "scanline")//Scanline effect. + flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect. + return flat_icon + +/proc/getStaticIcon(icon/A, safety=1) + var/icon/flat_icon = safety ? A : new(A) + flat_icon.Blend(rgb(255, 255, 255)) + flat_icon.BecomeAlphaMask() + var/icon/static_icon = new/icon('icons/effects/effects.dmi', "static_base") + static_icon.AddAlphaMask(flat_icon) + return static_icon + +/proc/getBlankIcon(icon/A, safety=1) + var/icon/flat_icon = safety ? A : new(A) + flat_icon.Blend(rgb(255, 255, 255)) + flat_icon.BecomeAlphaMask() + var/icon/blank_icon = new/icon('icons/effects/effects.dmi', "blank_base") + blank_icon.AddAlphaMask(flat_icon) + return blank_icon + +/proc/getLetterImage(atom/A, letter = "", uppercase = 0) + if(!A) + return + + var/icon/atom_icon = new(A.icon, A.icon_state) + + if(!letter) + letter = copytext(A.name, 1, 2) + if(uppercase == 1) + letter = uppertext(letter) + else if(uppercase == -1) + letter = lowertext(letter) + + var/image/text_image = new(loc = A) + text_image.maptext = "[letter]" + text_image.color = AverageColor(atom_icon) + text_image.pixel_x = 6 + text_image.pixel_y = 5 + del(atom_icon) + return text_image + +//For photo camera. +/proc/build_composite_icon(atom/A) + var/icon/composite = icon(A.icon, A.icon_state, A.dir, 1) + for(var/O in A.overlays) + var/image/I = O + var/icon/C = icon(I.icon, I.icon_state, I.dir, 1) + C.Blend(I.color, ICON_MULTIPLY) + composite.Blend(C, ICON_OVERLAY) + return composite + +proc/adjust_brightness(var/color, var/value) + if (!color) return "#FFFFFF" + if (!value) return color + + var/list/RGB = ReadRGB(color) + RGB[1] = Clamp(RGB[1]+value,0,255) + RGB[2] = Clamp(RGB[2]+value,0,255) + RGB[3] = Clamp(RGB[3]+value,0,255) + return rgb(RGB[1],RGB[2],RGB[3]) + +/proc/ListColors(var/icon/I, var/ignoreGreyscale = 0) + var/list/colors = list() + for(var/x_pixel = 1 to I.Width()) + for(var/y_pixel = 1 to I.Height()) + var/this_color = I.GetPixel(x_pixel, y_pixel) + if(this_color) + if (ignoreGreyscale && ReadHSV(RGBtoHSV(this_color))[2] == 0) //If saturation is 0, must be greyscale + continue + colors.Add(this_color) + return colors + +/proc/AverageColor(var/icon/I, var/accurate = 0, var/ignoreGreyscale = 0) +//Accurate: Use more accurate color averaging, usually has better results and prevents muddied or overly dark colors. Mad thanks to wwjnc. +//ignoreGreyscale: Excempts greyscale colors from the color list, useful for filtering outlines or plate overlays. + var/list/colors = ListColors(I, ignoreGreyscale) + if(!colors.len) + return null + + var/list/colorsum = list(0, 0, 0) //Holds the sum of the RGB values to calculate the average + var/list/RGB = list(0, 0, 0) //Temp list for each color + var/total = colors.len + + var/final_average + if (accurate) //keeping it legible + for(var/i = 1 to total) + RGB = ReadRGB(colors[i]) + colorsum[1] += RGB[1]*RGB[1] + colorsum[2] += RGB[2]*RGB[2] + colorsum[3] += RGB[3]*RGB[3] + final_average = rgb(sqrt(colorsum[1]/total), sqrt(colorsum[2]/total), sqrt(colorsum[3]/total)) + else + for(var/i = 1 to total) + RGB = ReadRGB(colors[i]) + colorsum[1] += RGB[1] + colorsum[2] += RGB[2] + colorsum[3] += RGB[3] + final_average = rgb(colorsum[1]/total, colorsum[2]/total, colorsum[3]/total) + return final_average + +/proc/empty_Y_space(var/icon/I) //Returns the amount of lines containing only transparent pixels in an icon, starting from the bottom + for(var/y_pixel = 1 to I.Height()) + for(var/x_pixel = 1 to I.Width()) + if (I.GetPixel(x_pixel, y_pixel)) + return y_pixel - 1 + return null diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 9dad210db9f..e77641ca22c 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -1,339 +1,339 @@ -/* - * Holds procs to help with list operations - * Contains groups: - * Misc - * Sorting - */ - -/* - * Misc - */ - -//Returns a list in plain english as a string -/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) - var/total = input.len - if (!total) - return "[nothing_text]" - else if (total == 1) - return "[input[1]]" - else if (total == 2) - return "[input[1]][and_text][input[2]]" - else - var/output = "" - var/index = 1 - while (index < total) - if (index == total - 1) - comma_text = final_comma_text - - output += "[input[index]][comma_text]" - index++ - - return "[output][and_text][input[index]]" - -//Returns list element or null. Should prevent "index out of bounds" error. -/proc/listgetindex(list/L, index) - if(istype(L)) - if(isnum(index)) - if(IsInRange(index,1,L.len)) - return L[index] - else if(index in L) - return L[index] - return - -/proc/islist(list/L) - if(istype(L)) - return 1 - return 0 - -//Return either pick(list) or null if list is not of type /list or is empty -/proc/safepick(list/L) - if(istype(L) && L.len) - return pick(L) - -//Checks if the list is empty -/proc/isemptylist(list/L) - if(!L.len) - return 1 - return 0 - -//Checks for specific types in a list -/proc/is_type_in_list(var/atom/A, var/list/L) - for(var/type in L) - if(istype(A, type)) - return 1 - return 0 - -//Empties the list by setting the length to 0. Hopefully the elements get garbage collected -/proc/clearlist(list/list) - if(istype(list)) - list.len = 0 - return - -//Removes any null entries from the list -/proc/listclearnulls(list/L) - if(istype(L)) - var/i=1 - for(var/thing in L) - if(thing != null) - ++i - continue - L.Cut(i,i+1) - -/* - * Returns list containing all the entries from first list that are not present in second. - * If skiprep = 1, repeated elements are treated as one. - * If either of arguments is not a list, returns null - */ -/proc/difflist(var/list/first, var/list/second, var/skiprep=0) - if(!islist(first) || !islist(second)) - return - var/list/result = new - if(skiprep) - for(var/e in first) - if(!(e in result) && !(e in second)) - result += e - else - result = first - second - return result - -/* - * Returns list containing entries that are in either list but not both. - * If skipref = 1, repeated elements are treated as one. - * If either of arguments is not a list, returns null - */ -/proc/uniquemergelist(var/list/first, var/list/second, var/skiprep=0) - if(!islist(first) || !islist(second)) - return - var/list/result = new - if(skiprep) - result = difflist(first, second, skiprep)+difflist(second, first, skiprep) - else - result = first ^ second - return result - -//Pretends to pick an element based on its weight but really just seems to pick a random element. -/proc/pickweight(list/L) - var/total = 0 - var/item - for (item in L) - if (!L[item]) - L[item] = 1 - total += L[item] - - total = rand(1, total) - for (item in L) - total -=L [item] - if (total <= 0) - return item - - return null - -//Pick a random element from the list and remove it from the list. -/proc/pick_n_take(list/L) - if(L.len) - var/picked = rand(1,L.len) - . = L[picked] - L.Cut(picked,picked+1) //Cut is far more efficient that Remove() - -//Returns the top(last) element from the list and removes it from the list (typical stack function) -/proc/pop(list/L) - if(L.len) - . = L[L.len] - L.len-- - -/proc/sorted_insert(list/L, thing, comparator) - var/pos = L.len - while(pos > 0 && call(comparator)(thing, L[pos]) > 0) - pos-- - L.Insert(pos+1, thing) - -// Returns the next item in a list -/proc/next_list_item(var/item, var/list/L) - var/i - i = L.Find(item) - if(i == L.len) - i = 1 - else - i++ - return L[i] - -// Returns the previous item in a list -/proc/previous_list_item(var/item, var/list/L) - var/i - i = L.Find(item) - if(i == 1) - i = L.len - else - i-- - if(i < L.len || i > L.len) - warning("[__FILE__]L[__LINE__]: [i] is outside of bounds for list, ([L.len])") - return - return L[i] - -/* - * Sorting - */ -/* -//Reverses the order of items in the list -/proc/reverselist(var/list/input) - var/list/output = list() - for(var/i = input.len; i >= 1; i--) - output += input[i] - return output -*/ - -//Randomize: Return the list in a random order -/proc/shuffle(var/list/L) - if(!L) - return - L = L.Copy() - - for(var/i=1, i<=L.len, ++i) - L.Swap(i,rand(1,L.len)) - - return L - -//Return a list with no duplicate entries -/proc/uniquelist(var/list/L) - var/list/K = list() - for(var/item in L) - if(!(item in K)) - K += item - return K - -//for sorting clients or mobs by ckey -/proc/sortKey(list/L, order=1) - return sortTim(L, order >= 0 ? /proc/cmp_ckey_asc : /proc/cmp_ckey_dsc) - -//Specifically for record datums in a list. -/proc/sortRecord(list/L, field = "name", order = 1) - cmp_field = field - return sortTim(L, order >= 0 ? /proc/cmp_records_asc : /proc/cmp_records_dsc) - -//any value in a list -/proc/sortList(var/list/L, cmp=/proc/cmp_text_asc) - return sortTim(L.Copy(), cmp) - -//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead -/proc/sortNames(var/list/L, order=1) - return sortTim(L, order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc) - - -//Converts a bitfield to a list of numbers (or words if a wordlist is provided) -/proc/bitfield2list(bitfield = 0, list/wordlist) - var/list/r = list() - if(istype(wordlist,/list)) - var/max = min(wordlist.len,16) - var/bit = 1 - for(var/i=1, i<=max, i++) - if(bitfield & bit) - r += wordlist[i] - bit = bit << 1 - else - for(var/bit=1, bit<=65535, bit = bit << 1) - if(bitfield & bit) - r += bit - - return r - -// Returns the key based on the index -/proc/get_key_by_index(var/list/L, var/index) - var/i = 1 - for(var/key in L) - if(index == i) - return key - i++ - return null - -/proc/count_by_type(var/list/L, type) - var/i = 0 - for(var/T in L) - if(istype(T, type)) - i++ - return i - -/proc/find_record(field, value, list/L) - for(var/datum/data/record/R in L) - if(R.fields[field] == value) - return R - - -//Move a single element from position fromIndex within a list, to position toIndex -//All elements in the range [1,toIndex) before the move will be before the pivot afterwards -//All elements in the range [toIndex, L.len+1) before the move will be after the pivot afterwards -//In other words, it's as if the range [fromIndex,toIndex) have been rotated using a <<< operation common to other languages. -//fromIndex and toIndex must be in the range [1,L.len+1] -//This will preserve associations ~Carnie -/proc/moveElement(list/L, fromIndex, toIndex) - if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move - return - if(fromIndex > toIndex) - ++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one - - L.Insert(toIndex, null) - L.Swap(fromIndex, toIndex) - L.Cut(fromIndex, fromIndex+1) - - -//Move elements [fromIndex,fromIndex+len) to [toIndex-len, toIndex) -//Same as moveElement but for ranges of elements -//This will preserve associations ~Carnie -/proc/moveRange(list/L, fromIndex, toIndex, len=1) - var/distance = abs(toIndex - fromIndex) - if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements - if(fromIndex <= toIndex) - return //no need to move - fromIndex += len //we want to shift left instead of right - - for(var/i=0, i toIndex) - fromIndex += len - - for(var/i=0, i distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements - if(fromIndex < toIndex) - toIndex += len - else - fromIndex += len - - for(var/i=0, i fromIndex) - var/a = toIndex - toIndex = fromIndex - fromIndex = a - - for(var/i=0, i 0 && call(comparator)(thing, L[pos]) > 0) + pos-- + L.Insert(pos+1, thing) + +// Returns the next item in a list +/proc/next_list_item(var/item, var/list/L) + var/i + i = L.Find(item) + if(i == L.len) + i = 1 + else + i++ + return L[i] + +// Returns the previous item in a list +/proc/previous_list_item(var/item, var/list/L) + var/i + i = L.Find(item) + if(i == 1) + i = L.len + else + i-- + if(i < L.len || i > L.len) + warning("[__FILE__]L[__LINE__]: [i] is outside of bounds for list, ([L.len])") + return + return L[i] + +/* + * Sorting + */ +/* +//Reverses the order of items in the list +/proc/reverselist(var/list/input) + var/list/output = list() + for(var/i = input.len; i >= 1; i--) + output += input[i] + return output +*/ + +//Randomize: Return the list in a random order +/proc/shuffle(var/list/L) + if(!L) + return + L = L.Copy() + + for(var/i=1, i<=L.len, ++i) + L.Swap(i,rand(1,L.len)) + + return L + +//Return a list with no duplicate entries +/proc/uniquelist(var/list/L) + var/list/K = list() + for(var/item in L) + if(!(item in K)) + K += item + return K + +//for sorting clients or mobs by ckey +/proc/sortKey(list/L, order=1) + return sortTim(L, order >= 0 ? /proc/cmp_ckey_asc : /proc/cmp_ckey_dsc) + +//Specifically for record datums in a list. +/proc/sortRecord(list/L, field = "name", order = 1) + cmp_field = field + return sortTim(L, order >= 0 ? /proc/cmp_records_asc : /proc/cmp_records_dsc) + +//any value in a list +/proc/sortList(var/list/L, cmp=/proc/cmp_text_asc) + return sortTim(L.Copy(), cmp) + +//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead +/proc/sortNames(var/list/L, order=1) + return sortTim(L, order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc) + + +//Converts a bitfield to a list of numbers (or words if a wordlist is provided) +/proc/bitfield2list(bitfield = 0, list/wordlist) + var/list/r = list() + if(istype(wordlist,/list)) + var/max = min(wordlist.len,16) + var/bit = 1 + for(var/i=1, i<=max, i++) + if(bitfield & bit) + r += wordlist[i] + bit = bit << 1 + else + for(var/bit=1, bit<=65535, bit = bit << 1) + if(bitfield & bit) + r += bit + + return r + +// Returns the key based on the index +/proc/get_key_by_index(var/list/L, var/index) + var/i = 1 + for(var/key in L) + if(index == i) + return key + i++ + return null + +/proc/count_by_type(var/list/L, type) + var/i = 0 + for(var/T in L) + if(istype(T, type)) + i++ + return i + +/proc/find_record(field, value, list/L) + for(var/datum/data/record/R in L) + if(R.fields[field] == value) + return R + + +//Move a single element from position fromIndex within a list, to position toIndex +//All elements in the range [1,toIndex) before the move will be before the pivot afterwards +//All elements in the range [toIndex, L.len+1) before the move will be after the pivot afterwards +//In other words, it's as if the range [fromIndex,toIndex) have been rotated using a <<< operation common to other languages. +//fromIndex and toIndex must be in the range [1,L.len+1] +//This will preserve associations ~Carnie +/proc/moveElement(list/L, fromIndex, toIndex) + if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move + return + if(fromIndex > toIndex) + ++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one + + L.Insert(toIndex, null) + L.Swap(fromIndex, toIndex) + L.Cut(fromIndex, fromIndex+1) + + +//Move elements [fromIndex,fromIndex+len) to [toIndex-len, toIndex) +//Same as moveElement but for ranges of elements +//This will preserve associations ~Carnie +/proc/moveRange(list/L, fromIndex, toIndex, len=1) + var/distance = abs(toIndex - fromIndex) + if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements + if(fromIndex <= toIndex) + return //no need to move + fromIndex += len //we want to shift left instead of right + + for(var/i=0, i toIndex) + fromIndex += len + + for(var/i=0, i distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements + if(fromIndex < toIndex) + toIndex += len + else + fromIndex += len + + for(var/i=0, i fromIndex) + var/a = toIndex + toIndex = fromIndex + fromIndex = a + + for(var/i=0, i") - var/target_txt = (target ? "[target][target.ckey ? " ([target.ckey])" : ""]" : "\") - var/object_txt = (object ? " with \the [object]" : "") - var/intent_txt = (user ? " (INTENT: [uppertext(user.a_intent)])" : "") - var/addition_txt = (addition ? " ([addition])" : "") - - if (ismob(user)) - user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target_txt][object_txt].[intent_txt][addition_txt]") - - if (ismob(target)) - target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user_txt][object_txt].[intent_txt][addition_txt]") - target.LAssailant = (iscarbon(user) ? user : null) - - var/log_msg = "[user_txt] [what_done] [target_txt][object_txt][intent_txt].[addition_txt] ([formatJumpTo(user, "JMP")])" - log_attack(log_msg) - if (admin_warn) - msg_admin_attack(log_msg) - -/** - * Helper proc to log detailed game events easier. - * - * @param user Subject of the action - * @param what_done Description of the action that user has done (e.g. "toggled the PA to 3") - * @param admin Whether to message the admins about this - * @param tp_link Whether to add a jump link to the position of the action (i.e. user.loc) - * @param tp_link_short Whether to make the jump link display 'JMP' instead of the area and coordinates - * @param span_class What CSS class to use for the message. - */ -/proc/add_gamelogs(var/mob/user, var/what_done, var/admin = 1, var/tp_link = FALSE, var/tp_link_short = TRUE, var/span_class = "notice") - var/user_text = (ismob(user) ? "[user] ([user.ckey])" : "") - var/link = (tp_link ? " ([formatJumpTo(user, (tp_link_short ? "JMP" : ""))])" : "") - - var/msg = "[user_text] has [what_done].[link]" - log_game(msg) - if (admin) - message_admins(msg) - -/** - * Helper function to log reagent transfers, usually 'bad' ones. - * - * @param user The user that performed the transfer - * @param source The item from which the reagents are transferred. - * @param target The destination of the transfer - * @param amount The amount of units transferred - * @param reagent_names List of reagent names to log - */ -/proc/log_reagents(var/mob/user, var/source, var/target, var/amount, var/list/reagent_names) - if (amount == 0) - return - - if (reagent_names && reagent_names.len > 0) - var/reagent_text = "[english_list(reagent_names)]" - add_gamelogs(user, "added [amount]u (inc. [reagent_text]) to \a [target] with \the [source]", admin = TRUE, tp_link = TRUE) - else - add_gamelogs(user, "added [amount]u to \a [target] with \the [source]", admin = TRUE, tp_link = FALSE) - - -/** - * Standardized method for tracking startup times. - */ -/proc/log_startup_progress(var/message) + + + + +/proc/log_adminghost(text) + if (config.log_adminghost) + diary << html_decode("\[[time_stamp()]]ADMINGHOST: [text]") + message_admins("\[ADMINGHOST\] [text]") + +/proc/log_ghost(text) + if (config.log_adminghost) + diary << html_decode("\[[time_stamp()]]GHOST: [text]") + message_admins("\[GHOST\] [text]") + + +/** + * Helper proc to log attacks or similar events between two mobs. + */ +/proc/add_attacklogs(var/mob/user, var/mob/target, var/what_done, var/object = null, var/addition = null, var/admin_warn = TRUE) + var/user_txt = (user ? "[user][user.ckey ? " ([user.ckey])" : ""]" : "\") + var/target_txt = (target ? "[target][target.ckey ? " ([target.ckey])" : ""]" : "\") + var/object_txt = (object ? " with \the [object]" : "") + var/intent_txt = (user ? " (INTENT: [uppertext(user.a_intent)])" : "") + var/addition_txt = (addition ? " ([addition])" : "") + + if (ismob(user)) + user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target_txt][object_txt].[intent_txt][addition_txt]") + + if (ismob(target)) + target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user_txt][object_txt].[intent_txt][addition_txt]") + target.LAssailant = (iscarbon(user) ? user : null) + + var/log_msg = "[user_txt] [what_done] [target_txt][object_txt][intent_txt].[addition_txt] ([formatJumpTo(user, "JMP")])" + log_attack(log_msg) + if (admin_warn) + msg_admin_attack(log_msg) + +/** + * Helper proc to log detailed game events easier. + * + * @param user Subject of the action + * @param what_done Description of the action that user has done (e.g. "toggled the PA to 3") + * @param admin Whether to message the admins about this + * @param tp_link Whether to add a jump link to the position of the action (i.e. user.loc) + * @param tp_link_short Whether to make the jump link display 'JMP' instead of the area and coordinates + * @param span_class What CSS class to use for the message. + */ +/proc/add_gamelogs(var/mob/user, var/what_done, var/admin = 1, var/tp_link = FALSE, var/tp_link_short = TRUE, var/span_class = "notice") + var/user_text = (ismob(user) ? "[user] ([user.ckey])" : "") + var/link = (tp_link ? " ([formatJumpTo(user, (tp_link_short ? "JMP" : ""))])" : "") + + var/msg = "[user_text] has [what_done].[link]" + log_game(msg) + if (admin) + message_admins(msg) + +/** + * Helper function to log reagent transfers, usually 'bad' ones. + * + * @param user The user that performed the transfer + * @param source The item from which the reagents are transferred. + * @param target The destination of the transfer + * @param amount The amount of units transferred + * @param reagent_names List of reagent names to log + */ +/proc/log_reagents(var/mob/user, var/source, var/target, var/amount, var/list/reagent_names) + if (amount == 0) + return + + if (reagent_names && reagent_names.len > 0) + var/reagent_text = "[english_list(reagent_names)]" + add_gamelogs(user, "added [amount]u (inc. [reagent_text]) to \a [target] with \the [source]", admin = TRUE, tp_link = TRUE) + else + add_gamelogs(user, "added [amount]u to \a [target] with \the [source]", admin = TRUE, tp_link = FALSE) + + +/** + * Standardized method for tracking startup times. + */ +/proc/log_startup_progress(var/message) to_chat(world, "[message]") world.log << message diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index e650579881b..f51a739bc88 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -1,240 +1,240 @@ -/** - * Credits to Nickr5 for the useful procs I've taken from his library resource. - */ - -var/const/E = 2.71828183 -var/const/Sqrt2 = 1.41421356 - -/* //All point fingers and laugh at this joke of a list, I even heard using sqrt() is faster than this list lookup, honk. -// List of square roots for the numbers 1-100. -var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10) -*/ - -/proc/Atan2(x, y) - if (!x && !y) - return 0 - - var/invcos = arccos(x / sqrt(x * x + y * y)) - return y >= 0 ? invcos : -invcos - -proc/arctan(x) - var/y=arcsin(x/sqrt(1+x*x)) - return y - -/proc/Ceiling(x, y = 1) - . = -round(-x / y) * y - -//Moved to macros.dm to reduce pure calling overhead, this was being called shitloads, like, most calls of all procs. -/* -/proc/Clamp(const/val, const/min, const/max) - if (val <= min) - return min - - if (val >= max) - return max - - return val -*/ - -// cotangent -/proc/Cot(x) - return 1 / Tan(x) - -// cosecant -/proc/Csc(x) - return 1 / sin(x) - -/proc/Default(a, b) - return a ? a : b - -/proc/Floor(x = 0, y = 0) - if(x == 0) - return 0 - if(y == 0) - return round(x) - - if(x < y) - return 0 - - var/diff = round(x, y) //finds x to the nearest value of y - if(diff > x) - return x - (y - (diff - x)) //diff minus x is the inverse of what we want to remove, so we subtract from y - the base unit - and subtract the result - else - return diff //this is good enough - -// Greatest Common Divisor - Euclid's algorithm -/proc/Gcd(a, b) - return b ? Gcd(b, a % b) : a - -/proc/Inverse(x) - return 1 / x - -/proc/IsAboutEqual(a, b, deviation = 0.1) - return abs(a - b) <= deviation - -/proc/IsEven(x) - return x % 2 == 0 - -// Returns true if val is from min to max, inclusive. -/proc/IsInRange(val, min, max) - return min <= val && val <= max - -/proc/IsInteger(x) - return Floor(x) == x - -/proc/IsOdd(x) - return !IsEven(x) - -/proc/IsMultiple(x, y) - return x % y == 0 - -// Least Common Multiple -/proc/Lcm(a, b) - return abs(a) / Gcd(a, b) * abs(b) - -/** - * Generic lerp function. - */ -/proc/lerp(x, x0, x1, y0 = 0, y1 = 1) - return y0 + (y1 - y0)*(x - x0)/(x1 - x0) - -/** - * Lerps x to a value between [a, b]. x must be in the range [0, 1]. - * My undying gratitude goes out to wwjnc. - * - * Basically this returns the number corresponding to a certain - * percentage in a range. 0% would be a, 100% would be b, 50% would - * be halfways between a and b, and so on. - * - * Other methods of lerping might not yield the exact value of a or b - * when x = 0 or 1. This one guarantees that. - * - * Examples: - * - mix(0.0, 30, 60) = 30 - * - mix(1.0, 30, 60) = 60 - * - mix(0.5, 30, 60) = 45 - * - mix(0.75, 30, 60) = 52.5 - */ -/proc/mix(a, b, x) - return a*(1 - x) + b*x - -/** - * Lerps x to a value between [0, 1]. x must be in the range [a, b]. - * - * This is the counterpart to the mix() function. It returns the actual - * percentage x is at inside the [a, b] range. - * - * Note that this is theoretically equivalent to calling lerp(x, a, b) - * (y0 and y1 default to 0 and 1) but this one is slightly faster - * because Byond is too dumb to optimize procs with default values. It - * shouldn't matter which one you use (since there are no FP issues) - * but this one is more explicit as to what you're doing. - * - * @todo Find a better name for this. I can't into english. - * http://i.imgur.com/8Pu0x7M.png - */ -/proc/unmix(x, a, b, min = 0, max = 1) - if(a==b) return 1 - return Clamp( (b - x)/(b - a), min, max ) - -/proc/Mean(...) - var/values = 0 - var/sum = 0 - for(var/val in args) - values++ - sum += val - return sum / values - - -/* - * Returns the nth root of x. - */ -/proc/Root(const/n, const/x) - return x ** (1 / n) - -/* - * Secant. - */ -/proc/Sec(const/x) - return 1 / cos(x) - -// The quadratic formula. Returns a list with the solutions, or an empty list -// if they are imaginary. -/proc/SolveQuadratic(a, b, c) - ASSERT(a) - . = list() - var/d = b*b - 4 * a * c - var/bottom = 2 * a - if(d < 0) return - var/root = sqrt(d) - . += (-b + root) / bottom - if(!d) return - . += (-b - root) / bottom - -/* - * Tangent. - */ -/proc/Tan(const/x) - return sin(x) / cos(x) - -/proc/ToDegrees(const/radians) - // 180 / Pi - return radians * 57.2957795 - -/proc/ToRadians(const/degrees) - // Pi / 180 - return degrees * 0.0174532925 - -// min is inclusive, max is exclusive -/proc/Wrap(val, min, max) - var/d = max - min - var/t = Floor((val - min) / d) - return val - (t * d) - -/* - * A very crude linear approximatiaon of pythagoras theorem. - */ -/proc/cheap_pythag(const/Ax, const/Ay) - var/dx = abs(Ax) - var/dy = abs(Ay) - - if (dx >= dy) - return dx + (0.5 * dy) // The longest side add half the shortest side approximates the hypotenuse. - else - return dy + (0.5 * dx) - -/* - * Magic constants obtained by using linear regression on right-angled triangles of sides 0= dy) - return (k1*dx) + (k2*dy) // No sqrt or powers :). - else - return (k2*dx) + (k1*dy) -#undef k1 -#undef k2 - -//Checks if something's a power of 2, to check bitflags. -//Thanks to wwjnc for this. -/proc/test_bitflag(var/bitflag) - return bitflag != 0 && !(bitflag & (bitflag - 1)) - -/* - * Diminishing returns formula using a triangular number sequence. - * Taken from http://lostsouls.org/grimoire_diminishing_returns - */ -/proc/triangular_seq(input, scale) - if(input < 0) - return -triangular_seq(-input, scale) - var/mult = input/scale - var/trinum = (sqrt(8 * mult + 1) - 1 ) / 2 - return trinum * scale +/** + * Credits to Nickr5 for the useful procs I've taken from his library resource. + */ + +var/const/E = 2.71828183 +var/const/Sqrt2 = 1.41421356 + +/* //All point fingers and laugh at this joke of a list, I even heard using sqrt() is faster than this list lookup, honk. +// List of square roots for the numbers 1-100. +var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10) +*/ + +/proc/Atan2(x, y) + if (!x && !y) + return 0 + + var/invcos = arccos(x / sqrt(x * x + y * y)) + return y >= 0 ? invcos : -invcos + +proc/arctan(x) + var/y=arcsin(x/sqrt(1+x*x)) + return y + +/proc/Ceiling(x, y = 1) + . = -round(-x / y) * y + +//Moved to macros.dm to reduce pure calling overhead, this was being called shitloads, like, most calls of all procs. +/* +/proc/Clamp(const/val, const/min, const/max) + if (val <= min) + return min + + if (val >= max) + return max + + return val +*/ + +// cotangent +/proc/Cot(x) + return 1 / Tan(x) + +// cosecant +/proc/Csc(x) + return 1 / sin(x) + +/proc/Default(a, b) + return a ? a : b + +/proc/Floor(x = 0, y = 0) + if(x == 0) + return 0 + if(y == 0) + return round(x) + + if(x < y) + return 0 + + var/diff = round(x, y) //finds x to the nearest value of y + if(diff > x) + return x - (y - (diff - x)) //diff minus x is the inverse of what we want to remove, so we subtract from y - the base unit - and subtract the result + else + return diff //this is good enough + +// Greatest Common Divisor - Euclid's algorithm +/proc/Gcd(a, b) + return b ? Gcd(b, a % b) : a + +/proc/Inverse(x) + return 1 / x + +/proc/IsAboutEqual(a, b, deviation = 0.1) + return abs(a - b) <= deviation + +/proc/IsEven(x) + return x % 2 == 0 + +// Returns true if val is from min to max, inclusive. +/proc/IsInRange(val, min, max) + return min <= val && val <= max + +/proc/IsInteger(x) + return Floor(x) == x + +/proc/IsOdd(x) + return !IsEven(x) + +/proc/IsMultiple(x, y) + return x % y == 0 + +// Least Common Multiple +/proc/Lcm(a, b) + return abs(a) / Gcd(a, b) * abs(b) + +/** + * Generic lerp function. + */ +/proc/lerp(x, x0, x1, y0 = 0, y1 = 1) + return y0 + (y1 - y0)*(x - x0)/(x1 - x0) + +/** + * Lerps x to a value between [a, b]. x must be in the range [0, 1]. + * My undying gratitude goes out to wwjnc. + * + * Basically this returns the number corresponding to a certain + * percentage in a range. 0% would be a, 100% would be b, 50% would + * be halfways between a and b, and so on. + * + * Other methods of lerping might not yield the exact value of a or b + * when x = 0 or 1. This one guarantees that. + * + * Examples: + * - mix(0.0, 30, 60) = 30 + * - mix(1.0, 30, 60) = 60 + * - mix(0.5, 30, 60) = 45 + * - mix(0.75, 30, 60) = 52.5 + */ +/proc/mix(a, b, x) + return a*(1 - x) + b*x + +/** + * Lerps x to a value between [0, 1]. x must be in the range [a, b]. + * + * This is the counterpart to the mix() function. It returns the actual + * percentage x is at inside the [a, b] range. + * + * Note that this is theoretically equivalent to calling lerp(x, a, b) + * (y0 and y1 default to 0 and 1) but this one is slightly faster + * because Byond is too dumb to optimize procs with default values. It + * shouldn't matter which one you use (since there are no FP issues) + * but this one is more explicit as to what you're doing. + * + * @todo Find a better name for this. I can't into english. + * http://i.imgur.com/8Pu0x7M.png + */ +/proc/unmix(x, a, b, min = 0, max = 1) + if(a==b) return 1 + return Clamp( (b - x)/(b - a), min, max ) + +/proc/Mean(...) + var/values = 0 + var/sum = 0 + for(var/val in args) + values++ + sum += val + return sum / values + + +/* + * Returns the nth root of x. + */ +/proc/Root(const/n, const/x) + return x ** (1 / n) + +/* + * Secant. + */ +/proc/Sec(const/x) + return 1 / cos(x) + +// The quadratic formula. Returns a list with the solutions, or an empty list +// if they are imaginary. +/proc/SolveQuadratic(a, b, c) + ASSERT(a) + . = list() + var/d = b*b - 4 * a * c + var/bottom = 2 * a + if(d < 0) return + var/root = sqrt(d) + . += (-b + root) / bottom + if(!d) return + . += (-b - root) / bottom + +/* + * Tangent. + */ +/proc/Tan(const/x) + return sin(x) / cos(x) + +/proc/ToDegrees(const/radians) + // 180 / Pi + return radians * 57.2957795 + +/proc/ToRadians(const/degrees) + // Pi / 180 + return degrees * 0.0174532925 + +// min is inclusive, max is exclusive +/proc/Wrap(val, min, max) + var/d = max - min + var/t = Floor((val - min) / d) + return val - (t * d) + +/* + * A very crude linear approximatiaon of pythagoras theorem. + */ +/proc/cheap_pythag(const/Ax, const/Ay) + var/dx = abs(Ax) + var/dy = abs(Ay) + + if (dx >= dy) + return dx + (0.5 * dy) // The longest side add half the shortest side approximates the hypotenuse. + else + return dy + (0.5 * dx) + +/* + * Magic constants obtained by using linear regression on right-angled triangles of sides 0= dy) + return (k1*dx) + (k2*dy) // No sqrt or powers :). + else + return (k2*dx) + (k1*dy) +#undef k1 +#undef k2 + +//Checks if something's a power of 2, to check bitflags. +//Thanks to wwjnc for this. +/proc/test_bitflag(var/bitflag) + return bitflag != 0 && !(bitflag & (bitflag - 1)) + +/* + * Diminishing returns formula using a triangular number sequence. + * Taken from http://lostsouls.org/grimoire_diminishing_returns + */ +/proc/triangular_seq(input, scale) + if(input < 0) + return -triangular_seq(-input, scale) + var/mult = input/scale + var/trinum = (sqrt(8 * mult + 1) - 1 ) / 2 + return trinum * scale diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index df0b0bc800e..a2b9d8bf12b 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -1,169 +1,169 @@ -proc/random_hair_style(gender, species = "Human") - var/h_style = "Bald" - - var/list/valid_hairstyles = list() - for(var/hairstyle in hair_styles_list) - var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue - if( !(species in S.species_allowed)) - continue - valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] - - if(valid_hairstyles.len) - h_style = pick(valid_hairstyles) - - return h_style - -/proc/GetOppositeDir(var/dir) - switch(dir) - if(NORTH) return SOUTH - if(SOUTH) return NORTH - if(EAST) return WEST - if(WEST) return EAST - if(SOUTHWEST) return NORTHEAST - if(NORTHWEST) return SOUTHEAST - if(NORTHEAST) return SOUTHWEST - if(SOUTHEAST) return NORTHWEST - return 0 - -proc/random_facial_hair_style(gender, species = "Human") - var/f_style = "Shaved" - - var/list/valid_facialhairstyles = list() - for(var/facialhairstyle in facial_hair_styles_list) - var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue - if( !(species in S.species_allowed)) - continue - - valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] - - if(valid_facialhairstyles.len) - f_style = pick(valid_facialhairstyles) - - return f_style - -proc/random_name(gender, speciesName = "Human") - var/datum/species/S = all_species[speciesName] - if(S) - return S.makeName(gender) - else - var/datum/species/human/H = new - return H.makeName(gender) - - - -proc/random_skin_tone() - switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino")) - if("caucasian") . = -10 - if("afroamerican") . = -115 - if("african") . = -165 - if("latino") . = -55 - if("albino") . = 34 - else . = rand(-185,34) - return min(max( .+rand(-25, 25), -185),34) - -proc/skintone2racedescription(tone) - switch (tone) - if(30 to INFINITY) return "albino" - if(20 to 30) return "pale" - if(5 to 15) return "light skinned" - if(-10 to 5) return "white" - if(-25 to -10) return "tan" - if(-45 to -25) return "darker skinned" - if(-65 to -45) return "brown" - if(-INFINITY to -65) return "black" - else return "unknown" - -proc/age2agedescription(age) - switch(age) - if(0 to 1) return "infant" - if(1 to 3) return "toddler" - if(3 to 13) return "child" - if(13 to 19) return "teenager" - if(19 to 30) return "young adult" - if(30 to 45) return "adult" - if(45 to 60) return "middle-aged" - if(60 to 70) return "aging" - if(70 to INFINITY) return "elderly" - else return "unknown" - -proc/RoundHealth(health) - switch(health) - if(100 to INFINITY) - return "health100" - if(70 to 100) - return "health80" - if(50 to 70) - return "health60" - if(30 to 50) - return "health40" - if(18 to 30) - return "health25" - if(5 to 18) - return "health10" - if(1 to 5) - return "health1" - if(-99 to 0) - return "health0" - else - return "health-100" - return "0" - -/* -Proc for attack log creation, because really why not -1 argument is the actor -2 argument is the target of action -3 is the description of action(like punched, throwed, or any other verb) -4 should it make adminlog note or not -5 is the tool with which the action was made(usually item) 5 and 6 are very similar(5 have "by " before it, that it) and are separated just to keep things in a bit more in order -6 is additional information, anything that needs to be added -*/ - -proc/add_logs(mob/user, mob/target, what_done, var/admin=1, var/object=null, var/addition=null) - if(user && ismob(user)) - user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") - if(target && ismob(target)) - target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") - if(!iscarbon(user)) - target.LAssailant = null - else - target.LAssailant = user - if(admin) - log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") - -proc/add_ghostlogs(var/mob/user, var/obj/target, var/what_done, var/admin=1, var/addition=null) - var/target_text = "NON-EXISTENT TARGET" - var/subject_text = "NON-EXISTENT SUBJECT" - if(target) - target_text=target.name - if(ismob(target)) - var/mob/M=target - if(M.ckey) - target_text += "([M.ckey])" - if(user) - subject_text=user.name - if(ismob(user)) - var/mob/M=user - if(M.ckey) - subject_text += "([M.ckey])" - if(user && ismob(user)) - user.attack_log += "\[[time_stamp()]\] GHOST: Has [what_done] [target_text] [addition]" - if(target && ismob(target)) - var/mob/M=target - M.attack_log += "\[[time_stamp()]\] GHOST: Has been [what_done] by [subject_text] [addition]" - if(admin) - //message_admins("GHOST: [subject_text] [what_done] [target_text] [addition]") - if(isAdminGhost(user)) - log_adminghost("[subject_text] [what_done] [target_text] [addition]") - else - log_ghost("[subject_text] [what_done] [target_text] [addition]") - -/mob/proc/isVentCrawling() +proc/random_hair_style(gender, species = "Human") + var/h_style = "Bald" + + var/list/valid_hairstyles = list() + for(var/hairstyle in hair_styles_list) + var/datum/sprite_accessory/S = hair_styles_list[hairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) + continue + valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] + + if(valid_hairstyles.len) + h_style = pick(valid_hairstyles) + + return h_style + +/proc/GetOppositeDir(var/dir) + switch(dir) + if(NORTH) return SOUTH + if(SOUTH) return NORTH + if(EAST) return WEST + if(WEST) return EAST + if(SOUTHWEST) return NORTHEAST + if(NORTHWEST) return SOUTHEAST + if(NORTHEAST) return SOUTHWEST + if(SOUTHEAST) return NORTHWEST + return 0 + +proc/random_facial_hair_style(gender, species = "Human") + var/f_style = "Shaved" + + var/list/valid_facialhairstyles = list() + for(var/facialhairstyle in facial_hair_styles_list) + var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) + continue + + valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] + + if(valid_facialhairstyles.len) + f_style = pick(valid_facialhairstyles) + + return f_style + +proc/random_name(gender, speciesName = "Human") + var/datum/species/S = all_species[speciesName] + if(S) + return S.makeName(gender) + else + var/datum/species/human/H = new + return H.makeName(gender) + + + +proc/random_skin_tone() + switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino")) + if("caucasian") . = -10 + if("afroamerican") . = -115 + if("african") . = -165 + if("latino") . = -55 + if("albino") . = 34 + else . = rand(-185,34) + return min(max( .+rand(-25, 25), -185),34) + +proc/skintone2racedescription(tone) + switch (tone) + if(30 to INFINITY) return "albino" + if(20 to 30) return "pale" + if(5 to 15) return "light skinned" + if(-10 to 5) return "white" + if(-25 to -10) return "tan" + if(-45 to -25) return "darker skinned" + if(-65 to -45) return "brown" + if(-INFINITY to -65) return "black" + else return "unknown" + +proc/age2agedescription(age) + switch(age) + if(0 to 1) return "infant" + if(1 to 3) return "toddler" + if(3 to 13) return "child" + if(13 to 19) return "teenager" + if(19 to 30) return "young adult" + if(30 to 45) return "adult" + if(45 to 60) return "middle-aged" + if(60 to 70) return "aging" + if(70 to INFINITY) return "elderly" + else return "unknown" + +proc/RoundHealth(health) + switch(health) + if(100 to INFINITY) + return "health100" + if(70 to 100) + return "health80" + if(50 to 70) + return "health60" + if(30 to 50) + return "health40" + if(18 to 30) + return "health25" + if(5 to 18) + return "health10" + if(1 to 5) + return "health1" + if(-99 to 0) + return "health0" + else + return "health-100" + return "0" + +/* +Proc for attack log creation, because really why not +1 argument is the actor +2 argument is the target of action +3 is the description of action(like punched, throwed, or any other verb) +4 should it make adminlog note or not +5 is the tool with which the action was made(usually item) 5 and 6 are very similar(5 have "by " before it, that it) and are separated just to keep things in a bit more in order +6 is additional information, anything that needs to be added +*/ + +proc/add_logs(mob/user, mob/target, what_done, var/admin=1, var/object=null, var/addition=null) + if(user && ismob(user)) + user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") + if(target && ismob(target)) + target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") + if(!iscarbon(user)) + target.LAssailant = null + else + target.LAssailant = user + if(admin) + log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") + +proc/add_ghostlogs(var/mob/user, var/obj/target, var/what_done, var/admin=1, var/addition=null) + var/target_text = "NON-EXISTENT TARGET" + var/subject_text = "NON-EXISTENT SUBJECT" + if(target) + target_text=target.name + if(ismob(target)) + var/mob/M=target + if(M.ckey) + target_text += "([M.ckey])" + if(user) + subject_text=user.name + if(ismob(user)) + var/mob/M=user + if(M.ckey) + subject_text += "([M.ckey])" + if(user && ismob(user)) + user.attack_log += "\[[time_stamp()]\] GHOST: Has [what_done] [target_text] [addition]" + if(target && ismob(target)) + var/mob/M=target + M.attack_log += "\[[time_stamp()]\] GHOST: Has been [what_done] by [subject_text] [addition]" + if(admin) + //message_admins("GHOST: [subject_text] [what_done] [target_text] [addition]") + if(isAdminGhost(user)) + log_adminghost("[subject_text] [what_done] [target_text] [addition]") + else + log_ghost("[subject_text] [what_done] [target_text] [addition]") + +/mob/proc/isVentCrawling() return (istype(loc, /obj/machinery/atmospherics)) // Crude but no other situation would put them inside of this \ No newline at end of file diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 59250971b8d..f3b94afc125 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -1,327 +1,327 @@ -var/church_name = null -/proc/church_name() - if (church_name) - return church_name - - var/name = "" - - name += pick("Holy", "United", "First", "Second", "Last") - - if (prob(20)) - name += " Space" - - name += {"[pick("Church", "Cathedral", "Body", "Worshippers", "Movement", "Witnesses")] of [religion_name()]"} - return name - -var/command_name = null -/proc/command_name() - if (command_name) - return command_name - - var/name = "" - - if (prob(10)) - name += pick("Super", "Ultra") - name += " " - - // Prefix - if (name) - name += pick("", "Central", "System", "Home", "Galactic") - else - name += pick("Central", "System", "Home", "Galactic") - if (name) - name += " " - - // Suffix - name += pick("Federation", "Command", "Alliance", "Unity", "Empire", "Confederation", "Protectorate", "Commonwealth", "Imperium", "Republic") - name += " " - - command_name = name - return name - -/proc/change_command_name(var/name) - - - command_name = name - - return name - -var/religion_name = null -/proc/religion_name() - if (religion_name) - return religion_name - - var/name = "" - - name += pick("bee", "science", "edu", "captain", "assistant", "monkey", "alien", "space", "unit", "sprocket", "gadget", "bomb", "revolution", "beyond", "station", "goon", "robot", "ivor", "hobnob") - name += pick("ism", "ia", "ology", "istism", "ites", "ick", "ian", "ity") - - return capitalize(name) - -/proc/station_name() - if(station_name) - return station_name - var/random = rand(1,5) - var/name = "" - - //Rare: Pre-Prefix - if (prob(10)) - name = pick("Imperium", "Heretical", "Cuban", "Psychic", "Elegant", "Common", "Uncommon", "Rare", "Unique", "Houseruled", "Religious", "Atheist", "Traditional", "Houseruled", "Mad", "Super", "Ultra", "Secret", "Top Secret", "Deep", "Death", "Zybourne", "Central", "Main", "Government", "Uoi", "Fat", "Automated", "Experimental", "Augmented") - station_name = name + " " - - // Prefix - switch(Holiday) - //get normal name - if(null,"",0) - name = pick("", "Stanford", "Dorf", "Alium", "Prefix", "Clowning", "Aegis", "Ishimura", "Scaredy", "Death-World", "Mime", "Honk", "Rogue", "MacRagge", "Ultrameens", "Safety", "Paranoia", "Explosive", "Neckbear", "Donk", "Muppet", "North", "West", "East", "South", "Slant-ways", "Widdershins", "Rimward", "Expensive", "Procreatory", "Imperial", "Unidentified", "Immoral", "Carp", "Ork", "Pete", "Control", "Nettle", "Aspie", "Class", "Crab", "Fist","Corrogated","Skeleton","Race", "Fatguy", "Gentleman", "Capitalist", "Communist", "Bear", "Beard", "Derp", "Space", "Spess", "Star", "Moon", "System", "Mining", "Neckbeard", "Research", "Supply", "Military", "Orbital", "Battle", "Science", "Asteroid", "Home", "Production", "Transport", "Delivery", "Extraplanetary", "Orbital", "Correctional", "Robot", "Hats", "Pizza") - if(name) - station_name += name + " " - - //For special days like christmas, easter, new-years etc ~Carn - if("Friday the 13th") - name = pick("Mike","Friday","Evil","Myers","Murder","Deathly","Stabby") - station_name += name + " " - random = 13 - else - //get the first word of the Holiday and use that - var/i = findtext(Holiday," ",1,0) - name = copytext(Holiday,1,i) - station_name += name + " " - - // Suffix - name = pick("Station", "Fortress", "Frontier", "Suffix", "Death-trap", "Space-hulk", "Lab", "Hazard","Spess Junk", "Fishery", "No-Moon", "Tomb", "Crypt", "Hut", "Monkey", "Bomb", "Trade Post", "Fortress", "Village", "Town", "City", "Edition", "Hive", "Complex", "Base", "Facility", "Depot", "Outpost", "Installation", "Drydock", "Observatory", "Array", "Relay", "Monitor", "Platform", "Construct", "Hangar", "Prison", "Center", "Port", "Waystation", "Factory", "Waypoint", "Stopover", "Hub", "HQ", "Office", "Object", "Fortification", "Colony", "Planet-Cracker", "Roost", "Fat Camp") - station_name += name + " " - - // ID Number - switch(random) - if(1) - station_name += "[rand(1, 99)]" - if(2) - station_name += pick("Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega") - if(3) - station_name += pick("II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX") - if(4) - station_name += pick("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu") - if(5) - station_name += pick("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen") - if(13) - station_name += pick("13","XIII","Thirteen") - - - if (config && config.server_name) - world.name = "[config.server_name]: [name]" - else - world.name = station_name - - return station_name - -/proc/world_name(var/name) - - - station_name = name - - if (config && config.server_name) - world.name = "[config.server_name]: [name]" - else - world.name = name - - return name - -var/syndicate_name = null -/proc/syndicate_name() - if (syndicate_name) - return syndicate_name - - var/name = "" - - // Prefix - name += pick("Clandestine", "Prima", "Blue", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Bonk", "Gene", "Gib") - - // Suffix - if (prob(80)) - name += " " - - // Full - if (prob(60)) - name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Intergalactic", "Interplanetary", "Foundation", "Positronics", "Hive") - // Broken - else - name += pick("Syndi", "Corp", "Bio", "System", "Prod", "Chem", "Inter", "Hive") - name += pick("", "-") - name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Code") - // Small - else - name += pick("-", "*", "") - name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive") - - syndicate_name = name - return name - - -//Traitors and traitor silicons will get these. Revs will not. -var/syndicate_code_phrase//Code phrase for traitors. -var/syndicate_code_response//Code response for traitors. - - /* - Should be expanded. - How this works: - Instead of "I'm looking for James Smith," the traitor would say "James Smith" as part of a conversation. - Another traitor may then respond with: "They enjoy running through the void-filled vacuum of the derelict." - The phrase should then have the words: James Smith. - The response should then have the words: run, void, and derelict. - This way assures that the code is suited to the conversation and is unpredicatable. - Obviously, some people will be better at this than others but in theory, everyone should be able to do it and it only enhances roleplay. - Can probably be done through "{ }" but I don't really see the practical benefit. - One example of an earlier system is commented below. - /N - */ - -/proc/generate_code_phrase()//Proc is used for phrase and response in master_controller.dm - - - var/code_phrase = ""//What is returned when the proc finishes. - var/words = pick(//How many words there will be. Minimum of two. 2, 4 and 5 have a lesser chance of being selected. 3 is the most likely. - 50; 2, - 200; 3, - 50; 4, - 25; 5 - ) - - var/safety[] = list(1,2,3)//Tells the proc which options to remove later on. - var/nouns[] = list("love","hate","anger","peace","pride","sympathy","bravery","loyalty","honesty","integrity","compassion","charity","success","courage","deceit","skill","beauty","brilliance","pain","misery","beliefs","dreams","justice","truth","faith","liberty","knowledge","thought","information","culture","trust","dedication","progress","education","hospitality","leisure","trouble","friendships", "relaxation") - var/drinks[] = list("vodka and tonic","gin fizz","bahama mama","manhattan","black Russian","whiskey soda","long island tea","margarita","Irish coffee"," manly dwarf","Irish cream","doctor's delight","Beepksy Smash","tequila sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine") - var/locations[] = teleportlocs.len ? teleportlocs : drinks//if null, defaults to drinks instead. - - var/names[] = list() - for(var/datum/data/record/t in data_core.general)//Picks from crew manifest. - names += t.fields["name"] - - var/maxwords = words//Extra var to check for duplicates. - - for(words,words>0,words--)//Randomly picks from one of the choices below. - - if(words==1&&(1 in safety)&&(2 in safety))//If there is only one word remaining and choice 1 or 2 have not been selected. - safety = list(pick(1,2))//Select choice 1 or 2. - else if(words==1&&maxwords==2)//Else if there is only one word remaining (and there were two originally), and 1 or 2 were chosen, - safety = list(3)//Default to list 3 - - switch(pick(safety))//Chance based on the safety list. - if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc. - switch(rand(1,2))//Mainly to add more options later. - if(1) - if(names.len&&prob(70)) - code_phrase += pick(names) - else - code_phrase += pick(pick(first_names_male,first_names_female)) - code_phrase += " " - code_phrase += pick(last_names) - if(2) - code_phrase += pick(get_all_jobs())//Returns a job. - safety -= 1 - if(2) - switch(rand(1,2))//Places or things. - if(1) - code_phrase += pick(drinks) - if(2) - code_phrase += pick(locations) - safety -= 2 - if(3) - switch(rand(1,3))//Nouns, adjectives, verbs. Can be selected more than once. - if(1) - code_phrase += pick(nouns) - if(2) - code_phrase += pick(adjectives) - if(3) - code_phrase += pick(verbs) - if(words==1) - code_phrase += "." - else - code_phrase += ", " - - return code_phrase - -/* -//This proc tests the gen above. -/client/verb/test_code_phrase() - set name = "Generate Code Phrase" - set category = "Debug" - +var/church_name = null +/proc/church_name() + if (church_name) + return church_name + + var/name = "" + + name += pick("Holy", "United", "First", "Second", "Last") + + if (prob(20)) + name += " Space" + + name += {"[pick("Church", "Cathedral", "Body", "Worshippers", "Movement", "Witnesses")] of [religion_name()]"} + return name + +var/command_name = null +/proc/command_name() + if (command_name) + return command_name + + var/name = "" + + if (prob(10)) + name += pick("Super", "Ultra") + name += " " + + // Prefix + if (name) + name += pick("", "Central", "System", "Home", "Galactic") + else + name += pick("Central", "System", "Home", "Galactic") + if (name) + name += " " + + // Suffix + name += pick("Federation", "Command", "Alliance", "Unity", "Empire", "Confederation", "Protectorate", "Commonwealth", "Imperium", "Republic") + name += " " + + command_name = name + return name + +/proc/change_command_name(var/name) + + + command_name = name + + return name + +var/religion_name = null +/proc/religion_name() + if (religion_name) + return religion_name + + var/name = "" + + name += pick("bee", "science", "edu", "captain", "assistant", "monkey", "alien", "space", "unit", "sprocket", "gadget", "bomb", "revolution", "beyond", "station", "goon", "robot", "ivor", "hobnob") + name += pick("ism", "ia", "ology", "istism", "ites", "ick", "ian", "ity") + + return capitalize(name) + +/proc/station_name() + if(station_name) + return station_name + var/random = rand(1,5) + var/name = "" + + //Rare: Pre-Prefix + if (prob(10)) + name = pick("Imperium", "Heretical", "Cuban", "Psychic", "Elegant", "Common", "Uncommon", "Rare", "Unique", "Houseruled", "Religious", "Atheist", "Traditional", "Houseruled", "Mad", "Super", "Ultra", "Secret", "Top Secret", "Deep", "Death", "Zybourne", "Central", "Main", "Government", "Uoi", "Fat", "Automated", "Experimental", "Augmented") + station_name = name + " " + + // Prefix + switch(Holiday) + //get normal name + if(null,"",0) + name = pick("", "Stanford", "Dorf", "Alium", "Prefix", "Clowning", "Aegis", "Ishimura", "Scaredy", "Death-World", "Mime", "Honk", "Rogue", "MacRagge", "Ultrameens", "Safety", "Paranoia", "Explosive", "Neckbear", "Donk", "Muppet", "North", "West", "East", "South", "Slant-ways", "Widdershins", "Rimward", "Expensive", "Procreatory", "Imperial", "Unidentified", "Immoral", "Carp", "Ork", "Pete", "Control", "Nettle", "Aspie", "Class", "Crab", "Fist","Corrogated","Skeleton","Race", "Fatguy", "Gentleman", "Capitalist", "Communist", "Bear", "Beard", "Derp", "Space", "Spess", "Star", "Moon", "System", "Mining", "Neckbeard", "Research", "Supply", "Military", "Orbital", "Battle", "Science", "Asteroid", "Home", "Production", "Transport", "Delivery", "Extraplanetary", "Orbital", "Correctional", "Robot", "Hats", "Pizza") + if(name) + station_name += name + " " + + //For special days like christmas, easter, new-years etc ~Carn + if("Friday the 13th") + name = pick("Mike","Friday","Evil","Myers","Murder","Deathly","Stabby") + station_name += name + " " + random = 13 + else + //get the first word of the Holiday and use that + var/i = findtext(Holiday," ",1,0) + name = copytext(Holiday,1,i) + station_name += name + " " + + // Suffix + name = pick("Station", "Fortress", "Frontier", "Suffix", "Death-trap", "Space-hulk", "Lab", "Hazard","Spess Junk", "Fishery", "No-Moon", "Tomb", "Crypt", "Hut", "Monkey", "Bomb", "Trade Post", "Fortress", "Village", "Town", "City", "Edition", "Hive", "Complex", "Base", "Facility", "Depot", "Outpost", "Installation", "Drydock", "Observatory", "Array", "Relay", "Monitor", "Platform", "Construct", "Hangar", "Prison", "Center", "Port", "Waystation", "Factory", "Waypoint", "Stopover", "Hub", "HQ", "Office", "Object", "Fortification", "Colony", "Planet-Cracker", "Roost", "Fat Camp") + station_name += name + " " + + // ID Number + switch(random) + if(1) + station_name += "[rand(1, 99)]" + if(2) + station_name += pick("Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega") + if(3) + station_name += pick("II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX") + if(4) + station_name += pick("Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu") + if(5) + station_name += pick("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen") + if(13) + station_name += pick("13","XIII","Thirteen") + + + if (config && config.server_name) + world.name = "[config.server_name]: [name]" + else + world.name = station_name + + return station_name + +/proc/world_name(var/name) + + + station_name = name + + if (config && config.server_name) + world.name = "[config.server_name]: [name]" + else + world.name = name + + return name + +var/syndicate_name = null +/proc/syndicate_name() + if (syndicate_name) + return syndicate_name + + var/name = "" + + // Prefix + name += pick("Clandestine", "Prima", "Blue", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Bonk", "Gene", "Gib") + + // Suffix + if (prob(80)) + name += " " + + // Full + if (prob(60)) + name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Intergalactic", "Interplanetary", "Foundation", "Positronics", "Hive") + // Broken + else + name += pick("Syndi", "Corp", "Bio", "System", "Prod", "Chem", "Inter", "Hive") + name += pick("", "-") + name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Code") + // Small + else + name += pick("-", "*", "") + name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive") + + syndicate_name = name + return name + + +//Traitors and traitor silicons will get these. Revs will not. +var/syndicate_code_phrase//Code phrase for traitors. +var/syndicate_code_response//Code response for traitors. + + /* + Should be expanded. + How this works: + Instead of "I'm looking for James Smith," the traitor would say "James Smith" as part of a conversation. + Another traitor may then respond with: "They enjoy running through the void-filled vacuum of the derelict." + The phrase should then have the words: James Smith. + The response should then have the words: run, void, and derelict. + This way assures that the code is suited to the conversation and is unpredicatable. + Obviously, some people will be better at this than others but in theory, everyone should be able to do it and it only enhances roleplay. + Can probably be done through "{ }" but I don't really see the practical benefit. + One example of an earlier system is commented below. + /N + */ + +/proc/generate_code_phrase()//Proc is used for phrase and response in master_controller.dm + + + var/code_phrase = ""//What is returned when the proc finishes. + var/words = pick(//How many words there will be. Minimum of two. 2, 4 and 5 have a lesser chance of being selected. 3 is the most likely. + 50; 2, + 200; 3, + 50; 4, + 25; 5 + ) + + var/safety[] = list(1,2,3)//Tells the proc which options to remove later on. + var/nouns[] = list("love","hate","anger","peace","pride","sympathy","bravery","loyalty","honesty","integrity","compassion","charity","success","courage","deceit","skill","beauty","brilliance","pain","misery","beliefs","dreams","justice","truth","faith","liberty","knowledge","thought","information","culture","trust","dedication","progress","education","hospitality","leisure","trouble","friendships", "relaxation") + var/drinks[] = list("vodka and tonic","gin fizz","bahama mama","manhattan","black Russian","whiskey soda","long island tea","margarita","Irish coffee"," manly dwarf","Irish cream","doctor's delight","Beepksy Smash","tequila sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine") + var/locations[] = teleportlocs.len ? teleportlocs : drinks//if null, defaults to drinks instead. + + var/names[] = list() + for(var/datum/data/record/t in data_core.general)//Picks from crew manifest. + names += t.fields["name"] + + var/maxwords = words//Extra var to check for duplicates. + + for(words,words>0,words--)//Randomly picks from one of the choices below. + + if(words==1&&(1 in safety)&&(2 in safety))//If there is only one word remaining and choice 1 or 2 have not been selected. + safety = list(pick(1,2))//Select choice 1 or 2. + else if(words==1&&maxwords==2)//Else if there is only one word remaining (and there were two originally), and 1 or 2 were chosen, + safety = list(3)//Default to list 3 + + switch(pick(safety))//Chance based on the safety list. + if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc. + switch(rand(1,2))//Mainly to add more options later. + if(1) + if(names.len&&prob(70)) + code_phrase += pick(names) + else + code_phrase += pick(pick(first_names_male,first_names_female)) + code_phrase += " " + code_phrase += pick(last_names) + if(2) + code_phrase += pick(get_all_jobs())//Returns a job. + safety -= 1 + if(2) + switch(rand(1,2))//Places or things. + if(1) + code_phrase += pick(drinks) + if(2) + code_phrase += pick(locations) + safety -= 2 + if(3) + switch(rand(1,3))//Nouns, adjectives, verbs. Can be selected more than once. + if(1) + code_phrase += pick(nouns) + if(2) + code_phrase += pick(adjectives) + if(3) + code_phrase += pick(verbs) + if(words==1) + code_phrase += "." + else + code_phrase += ", " + + return code_phrase + +/* +//This proc tests the gen above. +/client/verb/test_code_phrase() + set name = "Generate Code Phrase" + set category = "Debug" + to_chat(world, "Code Phrase is: [generate_code_phrase()]") - return - - - This was an earlier attempt at code phrase system, aside from an even earlier attempt (and failure). - This system more or less works as intended--aside from being unfinished--but it's still very predictable. - Particularly, the phrase opening statements are pretty easy to recognize and identify when metagaming. - I think the above-used method solves this issue by using words in a sequence, providing for much greater flexibility. - /N - - switch(choice) - if(1) - syndicate_code_phrase += pick("I'm looking for","Have you seen","Maybe you've seen","I'm trying to find","I'm tracking") - syndicate_code_phrase += " " - syndicate_code_phrase += pick(pick(first_names_male,first_names_female)) - syndicate_code_phrase += " " - syndicate_code_phrase += pick(last_names) - syndicate_code_phrase += "." - if(2) - syndicate_code_phrase += pick("How do I get to","How do I find","Where is","Where do I find") - syndicate_code_phrase += " " - syndicate_code_phrase += pick("Escape","Engineering","Atmos","the bridge","the brig","Clown Planet","CentCom","the library","the chapel","a bathroom","Med Bay","Tool Storage","the escape shuttle","Robotics","a locker room","the living quarters","the gym","the autolathe","QM","the bar","the theater","the derelict") - syndicate_code_phrase += "?" - if(3) - if(prob(70)) - syndicate_code_phrase += pick("Get me","I want","I'd like","Make me") - syndicate_code_phrase += " a " - else - syndicate_code_phrase += pick("One") - syndicate_code_phrase += " " - syndicate_code_phrase += pick("vodka and tonic","gin fizz","bahama mama","manhattan","black Russian","whiskey soda","long island tea","margarita","Irish coffee"," manly dwarf","Irish cream","doctor's delight","Beepksy Smash","tequila sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine") - syndicate_code_phrase += "." - if(4) - syndicate_code_phrase += pick("I wish I was","My dad was","His mom was","Where do I find","The hero this station needs is","I'd fuck","I wouldn't trust","Someone caught","HoS caught","Someone found","I'd wrestle","I wanna kill") - syndicate_code_phrase += " [pick("a","the")] " - syndicate_code_phrase += pick("wizard","ninja","xeno","lizard","slime","monkey","syndicate","cyborg","clown","space carp","singularity","singulo","mime") - syndicate_code_phrase += "." - if(5) - syndicate_code_phrase += pick("Do we have","Is there","Where is","Where's","Who's") - syndicate_code_phrase += " " - syndicate_code_phrase += "[pick(get_all_jobs())]" - syndicate_code_phrase += "?" - - switch(choice) - if(1) - if(prob(80)) - syndicate_code_response += pick("Try looking for them near","I they ran off to","Yes. I saw them near","Nope. I'm heading to","Try searching") - syndicate_code_response += " " - syndicate_code_response += pick("Escape","Engineering","Atmos","the bridge","the brig","Clown Planet","CentCom","the library","the chapel","a bathroom","Med Bay","Tool Storage","the escape shuttle","Robotics","a locker room","the living quarters","the gym","the autolathe","QM","the bar","the theater","the derelict") - syndicate_code_response += "." - else if(prob(60)) - syndicate_code_response += pick("No. I'm busy, sorry.","I don't have the time.","Not sure, maybe?","There is no time.") - else - syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*") - if(2) - if(prob(80)) - syndicate_code_response += pick("Go to","Navigate to","Try","Sure, run to","Try searching","It's near","It's around") - syndicate_code_response += " the " - syndicate_code_response += pick("[pick("south","north","east","west")] maitenance door","nearby maitenance","teleporter","[pick("cold","dead")] space","morgue","vacuum","[pick("south","north","east","west")] hall ","[pick("south","north","east","west")] hallway","[pick("white","black","red","green","blue","pink","purple")] [pick("rabbit","frog","lion","tiger","panther","snake","facehugger")]") - syndicate_code_response += "." - else if(prob(60)) - syndicate_code_response += pick("Try asking","Ask","Talk to","Go see","Follow","Hunt down") - syndicate_code_response += " " - if(prob(50)) - syndicate_code_response += pick(pick(first_names_male,first_names_female)) - syndicate_code_response += " " - syndicate_code_response += pick(last_names) - else - syndicate_code_response += " the " - syndicate_code_response += "[pic(get_all_jobs())]" - syndicate_code_response += "." - else - syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*") - if(3) - if(4) - if(5) - - return + return + + + This was an earlier attempt at code phrase system, aside from an even earlier attempt (and failure). + This system more or less works as intended--aside from being unfinished--but it's still very predictable. + Particularly, the phrase opening statements are pretty easy to recognize and identify when metagaming. + I think the above-used method solves this issue by using words in a sequence, providing for much greater flexibility. + /N + + switch(choice) + if(1) + syndicate_code_phrase += pick("I'm looking for","Have you seen","Maybe you've seen","I'm trying to find","I'm tracking") + syndicate_code_phrase += " " + syndicate_code_phrase += pick(pick(first_names_male,first_names_female)) + syndicate_code_phrase += " " + syndicate_code_phrase += pick(last_names) + syndicate_code_phrase += "." + if(2) + syndicate_code_phrase += pick("How do I get to","How do I find","Where is","Where do I find") + syndicate_code_phrase += " " + syndicate_code_phrase += pick("Escape","Engineering","Atmos","the bridge","the brig","Clown Planet","CentCom","the library","the chapel","a bathroom","Med Bay","Tool Storage","the escape shuttle","Robotics","a locker room","the living quarters","the gym","the autolathe","QM","the bar","the theater","the derelict") + syndicate_code_phrase += "?" + if(3) + if(prob(70)) + syndicate_code_phrase += pick("Get me","I want","I'd like","Make me") + syndicate_code_phrase += " a " + else + syndicate_code_phrase += pick("One") + syndicate_code_phrase += " " + syndicate_code_phrase += pick("vodka and tonic","gin fizz","bahama mama","manhattan","black Russian","whiskey soda","long island tea","margarita","Irish coffee"," manly dwarf","Irish cream","doctor's delight","Beepksy Smash","tequila sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine") + syndicate_code_phrase += "." + if(4) + syndicate_code_phrase += pick("I wish I was","My dad was","His mom was","Where do I find","The hero this station needs is","I'd fuck","I wouldn't trust","Someone caught","HoS caught","Someone found","I'd wrestle","I wanna kill") + syndicate_code_phrase += " [pick("a","the")] " + syndicate_code_phrase += pick("wizard","ninja","xeno","lizard","slime","monkey","syndicate","cyborg","clown","space carp","singularity","singulo","mime") + syndicate_code_phrase += "." + if(5) + syndicate_code_phrase += pick("Do we have","Is there","Where is","Where's","Who's") + syndicate_code_phrase += " " + syndicate_code_phrase += "[pick(get_all_jobs())]" + syndicate_code_phrase += "?" + + switch(choice) + if(1) + if(prob(80)) + syndicate_code_response += pick("Try looking for them near","I they ran off to","Yes. I saw them near","Nope. I'm heading to","Try searching") + syndicate_code_response += " " + syndicate_code_response += pick("Escape","Engineering","Atmos","the bridge","the brig","Clown Planet","CentCom","the library","the chapel","a bathroom","Med Bay","Tool Storage","the escape shuttle","Robotics","a locker room","the living quarters","the gym","the autolathe","QM","the bar","the theater","the derelict") + syndicate_code_response += "." + else if(prob(60)) + syndicate_code_response += pick("No. I'm busy, sorry.","I don't have the time.","Not sure, maybe?","There is no time.") + else + syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*") + if(2) + if(prob(80)) + syndicate_code_response += pick("Go to","Navigate to","Try","Sure, run to","Try searching","It's near","It's around") + syndicate_code_response += " the " + syndicate_code_response += pick("[pick("south","north","east","west")] maitenance door","nearby maitenance","teleporter","[pick("cold","dead")] space","morgue","vacuum","[pick("south","north","east","west")] hall ","[pick("south","north","east","west")] hallway","[pick("white","black","red","green","blue","pink","purple")] [pick("rabbit","frog","lion","tiger","panther","snake","facehugger")]") + syndicate_code_response += "." + else if(prob(60)) + syndicate_code_response += pick("Try asking","Ask","Talk to","Go see","Follow","Hunt down") + syndicate_code_response += " " + if(prob(50)) + syndicate_code_response += pick(pick(first_names_male,first_names_female)) + syndicate_code_response += " " + syndicate_code_response += pick(last_names) + else + syndicate_code_response += " the " + syndicate_code_response += "[pic(get_all_jobs())]" + syndicate_code_response += "." + else + syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*") + if(3) + if(4) + if(5) + + return */ \ No newline at end of file diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index 4b521f9bfbb..ca23a2a7f7b 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -1,46 +1,46 @@ -//general stuff -/proc/sanitize_integer(number, min=0, max=1, default=0) - if(isnum(number)) - number = round(number) - if(min <= number && number <= max) - return number - return default - -/proc/sanitize_text(text, default="") - if(istext(text)) - return text - return default - -/proc/sanitize_inlist(value, list/List, default) - if(value in List) return value - if(default) return default - if(List && List.len)return List[1] - - - -//more specialised stuff -/proc/sanitize_gender(gender,neuter=0,plural=0, default="male") - switch(gender) - if(MALE, FEMALE)return gender - if(NEUTER) - if(neuter) return gender - else return default - if(PLURAL) - if(plural) return gender - else return default - return default - -/proc/sanitize_hexcolor(color, default="#000000") - if(!istext(color)) return default - var/len = length(color) - if(len != 7 && len !=4) return default - if(text2ascii(color,1) != 35) return default //35 is the ascii code for "#" - . = "#" - for(var/i=2,i<=len,i++) - var/ascii = text2ascii(color,i) - switch(ascii) - if(48 to 57) . += ascii2text(ascii) //numbers 0 to 9 - if(97 to 102) . += ascii2text(ascii) //letters a to f - if(65 to 70) . += ascii2text(ascii+32) //letters A to F - translates to lowercase - else return default - return . +//general stuff +/proc/sanitize_integer(number, min=0, max=1, default=0) + if(isnum(number)) + number = round(number) + if(min <= number && number <= max) + return number + return default + +/proc/sanitize_text(text, default="") + if(istext(text)) + return text + return default + +/proc/sanitize_inlist(value, list/List, default) + if(value in List) return value + if(default) return default + if(List && List.len)return List[1] + + + +//more specialised stuff +/proc/sanitize_gender(gender,neuter=0,plural=0, default="male") + switch(gender) + if(MALE, FEMALE)return gender + if(NEUTER) + if(neuter) return gender + else return default + if(PLURAL) + if(plural) return gender + else return default + return default + +/proc/sanitize_hexcolor(color, default="#000000") + if(!istext(color)) return default + var/len = length(color) + if(len != 7 && len !=4) return default + if(text2ascii(color,1) != 35) return default //35 is the ascii code for "#" + . = "#" + for(var/i=2,i<=len,i++) + var/ascii = text2ascii(color,i) + switch(ascii) + if(48 to 57) . += ascii2text(ascii) //numbers 0 to 9 + if(97 to 102) . += ascii2text(ascii) //letters a to f + if(65 to 70) . += ascii2text(ascii+32) //letters A to F - translates to lowercase + else return default + return . diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 51398c6e834..85b7aca2cce 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -1,480 +1,480 @@ -/* - * Holds procs designed to help with filtering text - * Contains groups: - * SQL sanitization - * Text sanitization - * Text searches - * Text modification - * Misc - */ - - -/* - * SQL sanitization - */ - -// Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts. -/proc/sanitizeSQL(var/t as text) - //var/sanitized_text = replacetext(t, "'", "\\'") - //sanitized_text = replacetext(sanitized_text, "\"", "\\\"") - - var/sqltext = dbcon.Quote(t) - //testing("sanitizeSQL(): BEFORE copytext(): [sqltext]") - sqltext = copytext(sqltext, 2, length(sqltext))//Quote() adds quotes around input, we already do that - //testing("sanitizeSQL(): AFTER copytext(): [sqltext]") - return sqltext - -/* -/mob/verb/SanitizeTest(var/t as text) +/* + * Holds procs designed to help with filtering text + * Contains groups: + * SQL sanitization + * Text sanitization + * Text searches + * Text modification + * Misc + */ + + +/* + * SQL sanitization + */ + +// Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts. +/proc/sanitizeSQL(var/t as text) + //var/sanitized_text = replacetext(t, "'", "\\'") + //sanitized_text = replacetext(sanitized_text, "\"", "\\\"") + + var/sqltext = dbcon.Quote(t) + //testing("sanitizeSQL(): BEFORE copytext(): [sqltext]") + sqltext = copytext(sqltext, 2, length(sqltext))//Quote() adds quotes around input, we already do that + //testing("sanitizeSQL(): AFTER copytext(): [sqltext]") + return sqltext + +/* +/mob/verb/SanitizeTest(var/t as text) to_chat(src, "IN: [t]") to_chat(src, "OUT: [sanitizeSQL(t)]") -*/ -/* - * Text sanitization - */ - -//Simply removes < and > and limits the length of the message -/proc/strip_html_simple(var/t,var/limit=MAX_MESSAGE_LEN) - var/list/strip_chars = list("<",">") - t = copytext(t,1,limit) - for(var/char in strip_chars) - var/index = findtext(t, char) - while(index) - t = copytext(t, 1, index) + copytext(t, index+1) - index = findtext(t, char) - return t - -/proc/strip_html_properly(input = "") - // these store the position of < and > respectively - var/opentag = 0 - var/closetag = 0 - - while (input) - opentag = rfindtext(input, "<") - closetag = findtext(input, ">", opentag + 1) - - if (!opentag || !closetag) - break - - input = copytext(input, 1, opentag) + copytext(input, closetag + 1) - - return input - -/proc/rfindtext(Haystack, Needle, Start = 1, End = 0) - var/i = findtext(Haystack, Needle, Start, End) - - while (i) - . = i - i = findtext(Haystack, Needle, i + 1, End) - -//Removes a few problematic characters -/proc/sanitize_simple(var/t,var/list/repl_chars = list("\n"="#","\t"="#","�"="�")) - for(var/char in repl_chars) - var/index = findtext(t, char) - while(index) - t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+1) - index = findtext(t, char) - return t - -//Runs byond's sanitization proc along-side sanitize_simple -/proc/sanitize(var/t,var/list/repl_chars = null) - return html_encode(sanitize_simple(t,repl_chars)) - -//Runs sanitize and strip_html_simple -//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '<' after sanitize() calls byond's html_encode() -/proc/strip_html(var/t,var/limit=MAX_MESSAGE_LEN) - return copytext((sanitize(strip_html_simple(t))),1,limit) - -//Runs byond's sanitization proc along-side strip_html_simple -//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '<' that html_encode() would cause -/proc/adminscrub(var/t,var/limit=MAX_MESSAGE_LEN) - return copytext((html_encode(strip_html_simple(t))),1,limit) - -/proc/reverse_text(txt) - var/i = length(txt)+1 - . = "" - while(--i) - . += copytext(txt,i,i+1) - -/* - * returns null if there is any bad text in the string - */ -/proc/reject_bad_text(const/text, var/max_length = 512) - var/text_length = length(text) - - if(text_length > max_length) - return // message too long - - var/non_whitespace = FALSE - - for(var/i = 1 to text_length) - switch(text2ascii(text, i)) - if(62, 60, 92, 47) - return // rejects the text if it contains these bad characters: <, >, \ or / - if(127 to 255) - return // rejects weird letters like � - if(0 to 31) - return // more weird stuff - if(32) - continue //whitespace - else - non_whitespace = TRUE - - if(non_whitespace) - return text // only accepts the text if it has some non-spaces - -// Used to get a sanitized input. -/proc/stripped_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN) - var/name = input(user, message, title, default) - return strip_html_simple(name, max_length) - -//Filters out undesirable characters from names -/proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN) - if(!t_in || length(t_in) > max_length) - return //Rejects the input if it is null or if it is longer then the max length allowed - - var/number_of_alphanumeric = 0 - var/last_char_group = 0 - var/t_out = "" - - for(var/i=1, i<=length(t_in), i++) - var/ascii_char = text2ascii(t_in,i) - switch(ascii_char) - // A .. Z - if(65 to 90) //Uppercase Letters - t_out += ascii2text(ascii_char) - number_of_alphanumeric++ - last_char_group = 4 - - // a .. z - if(97 to 122) //Lowercase Letters - if(last_char_group<2) t_out += ascii2text(ascii_char-32) //Force uppercase first character - else t_out += ascii2text(ascii_char) - number_of_alphanumeric++ - last_char_group = 4 - - // 0 .. 9 - if(48 to 57) //Numbers - if(!last_char_group) continue //suppress at start of string - if(!allow_numbers) continue - t_out += ascii2text(ascii_char) - number_of_alphanumeric++ - last_char_group = 3 - - // ' - . - if(39,45,46) //Common name punctuation - if(!last_char_group) continue - t_out += ascii2text(ascii_char) - last_char_group = 2 - - // ~ | @ : # $ % & * + - if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI) - if(!last_char_group) continue //suppress at start of string - if(!allow_numbers) continue - t_out += ascii2text(ascii_char) - last_char_group = 2 - - //Space - if(32) - if(last_char_group <= 1) continue //suppress double-spaces and spaces at start of string - t_out += ascii2text(ascii_char) - last_char_group = 1 - else - return - - if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '" - - if(last_char_group == 1) - t_out = copytext(t_out,1,length(t_out)) //removes the last character (in this case a space) - - for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai","plating")) //prevents these common metagamey names - if(cmptext(t_out,bad_name)) return //(not case sensitive) - - return t_out - -//checks text for html tags -//if tag is not in whitelist (var/list/paper_tag_whitelist in global.dm) -//relpaces < with < -proc/checkhtml(var/t) - t = sanitize_simple(t, list("&#"=".")) - var/p = findtext(t,"<",1) - while (p) //going through all the tags - var/start = p++ - var/tag = copytext(t,p, p+1) - if (tag != "/") - while (reject_bad_text(copytext(t, p, p+1), 1)) - tag = copytext(t,start, p) - p++ - tag = copytext(t,start+1, p) - if (!(tag in paper_tag_whitelist)) //if it's unkown tag, disarming it - t = copytext(t,1,start-1) + "<" + copytext(t,start+1) - p = findtext(t,"<",p) - return t -/* - * Text searches - */ - -//Checks the beginning of a string for a specified sub-string -//Returns the position of the substring or 0 if it was not found -/proc/dd_hasprefix(text, prefix) - var/start = 1 - var/end = length(prefix) + 1 - return findtext(text, prefix, start, end) - -//Checks the beginning of a string for a specified sub-string. This proc is case sensitive -//Returns the position of the substring or 0 if it was not found -/proc/dd_hasprefix_case(text, prefix) - var/start = 1 - var/end = length(prefix) + 1 - return findtextEx(text, prefix, start, end) - -//Checks the end of a string for a specified substring. -//Returns the position of the substring or 0 if it was not found -/proc/dd_hassuffix(text, suffix) - var/start = length(text) - length(suffix) - if(start) - return findtext(text, suffix, start, null) - return - -//Checks the end of a string for a specified substring. This proc is case sensitive -//Returns the position of the substring or 0 if it was not found -/proc/dd_hassuffix_case(text, suffix) - var/start = length(text) - length(suffix) - if(start) - return findtextEx(text, suffix, start, null) - -/* - * Text modification - */ -/proc/replacetext(text, find, replacement) - return list2text(text2list(text, find), replacement) - -/proc/replacetextEx(text, find, replacement) - return list2text(text2listEx(text, find), replacement) - -//Adds 'u' number of zeros ahead of the text 't' -/proc/add_zero(t, u) - while (length(t) < u) - t = "0[t]" - return t - -//Adds 'u' number of spaces ahead of the text 't' -/proc/add_lspace(t, u) - while(length(t) < u) - t = " [t]" - return t - -//Adds 'u' number of spaces behind the text 't' -/proc/add_tspace(t, u) - while(length(t) < u) - t = "[t] " - return t - -//Returns a string with reserved characters and spaces before the first letter removed -/proc/trim_left(text) - for (var/i = 1 to length(text)) - if (text2ascii(text, i) > 32) - return copytext(text, i) - return "" - -//Returns a string with reserved characters and spaces after the last letter removed -/proc/trim_right(text) - for (var/i = length(text), i > 0, i--) - if (text2ascii(text, i) > 32) - return copytext(text, 1, i + 1) - - return "" - -//Returns a string with reserved characters and spaces before the first word and after the last word removed. -/proc/trim(text) - return trim_left(trim_right(text)) - -//Returns a string with the first element of the string capitalized. -/proc/capitalize(var/t as text) - return uppertext(copytext(t, 1, 2)) + copytext(t, 2) - -//Centers text by adding spaces to either side of the string. -/proc/dd_centertext(message, length) - var/new_message = message - var/size = length(message) - var/delta = length - size - if(size == length) - return new_message - if(size > length) - return copytext(new_message, 1, length + 1) - if(delta == 1) - return new_message + " " - if(delta % 2) - new_message = " " + new_message - delta-- - var/spaces = add_lspace("",delta/2-1) - return spaces + new_message + spaces - -//Limits the length of the text. Note: MAX_MESSAGE_LEN and MAX_NAME_LEN are widely used for this purpose -/proc/dd_limittext(message, length) - var/size = length(message) - if(size <= length) - return message - return copytext(message, 1, length + 1) - -/proc/stringmerge(var/text,var/compare,replace = "*") -//This proc fills in all spaces with the "replace" var (* by default) with whatever -//is in the other string at the same spot (assuming it is not a replace char). -//This is used for fingerprints - var/newtext = text - if(length(text) != length(compare)) - return 0 - for(var/i = 1, i < length(text), i++) - var/a = copytext(text,i,i+1) - var/b = copytext(compare,i,i+1) -//if it isn't both the same letter, or if they are both the replacement character -//(no way to know what it was supposed to be) - if(a != b) - if(a == replace) //if A is the replacement char - newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1) - else if(b == replace) //if B is the replacement char - newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1) - else //The lists disagree, Uh-oh! - return 0 - return newtext - -/proc/stringpercent(var/text,character = "*") -//This proc returns the number of chars of the string that is the character -//This is used for detective work to determine fingerprint completion. - if(!text || !character) - return 0 - var/count = 0 - for(var/i = 1, i <= length(text), i++) - var/a = copytext(text,i,i+1) - if(a == character) - count++ - return count - -/** - * Format number with thousands seperators. - * @param number Number to format. - * @param sep seperator to use - */ -/proc/format_num(var/number, var/sep=",") - var/c="" // Current char - var/list/parts = text2list("[number]",".") - var/origtext = "[parts[1]]" - var/len = length(origtext) - var/offset = len % 3 - for(var/i=1;i<=len;i++) - c = copytext(origtext,i,i+1) - . += c - if((i%3)==offset && i!=len) - . += sep - if(parts.len==2) - . += ".[parts[2]]" - -var/global/list/watt_suffixes = list("W", "KW", "MW", "GW", "TW", "PW", "EW", "ZW", "YW") -/proc/format_watts(var/number) - if(number<0) return "-[format_watts(number)]" - if(number==0) return "0 W" - - var/i=1 - while (round(number/1000) >= 1) - number/=1000 - i++ - return "[format_num(number)] [watt_suffixes[i]]" - - -// Custom algorithm since stackoverflow is full of complete garbage and even the MS algorithm sucks. -// Uses recursion, in places. -// (c)2015 Rob "N3X15" Nelson -// Available under the MIT license. - -var/list/number_digits=list( - "one", - "two", - "three", - "four", - "five", - "six", - "seven", - "eight", - "nine", - "ten", - "eleven", - "twelve", - "thirteen", - "fourteen", - "fifteen", - "sixteen", - "seventeen", - "eighteen", - "nineteen", -) - -var/list/number_tens=list( - null, // 0 :V - null, // teens, special case - "twenty", - "thirty", - "forty", - "fifty", - "sixty", - "seventy", - "eighty", - "ninety" -) - -var/list/number_units=list( - null, // Don't yell units - "thousand", - "million", - "billion" -) - -/proc/num2words(var/number, var/zero="zero", var/minus="minus", var/hundred="hundred", var/list/digits=number_digits, var/list/tens=number_tens, var/list/units=number_units, var/recursion=0) - if(!isnum(number)) - warning("num2words fed a non-number: [number]") - return list() - number=round(number) - //testing("num2words [recursion] ([number])") - if(number == 0) - return list(zero) - - if(number < 0) - return list(minus) + num2words(abs(number), zero, minus, hundred, digits, tens, units, recursion+1) - - var/list/out=list() - if(number < 1000) - var/hundreds = round(number/100) - //testing(" ([recursion]) hundreds=[hundreds]") - if(hundreds) - out += num2words(hundreds, zero, minus, hundred, digits, tens, units, recursion+1) + list(hundred) - number %= 100 - - if(number < 100) - // Teens - if(number <= 19) - out.Add(digits[number]) - else - var/tens_place = tens[round(number/10)+1] - //testing(" ([recursion]) tens_place=[round(number/10)+1] = [tens_place]") - if(tens_place!=null) - out.Add(tens_place) - number = number%10 - //testing(" ([recursion]) number%10+1 = [number+1] = [digits[number+1]]") - if(number>0) - out.Add(digits[number]) - else - var/i=1 - while(round(number) > 0) - var/unit_number = number%1000 - //testing(" ([recursion]) [number]%1000 = [unit_number] ([i])") - if(unit_number > 0) - if(units[i]) - //testing(" ([recursion]) units = [units[i]]") - out = list(units[i]) + out - out = num2words(unit_number, zero, minus, hundred, digits, tens, units, recursion+1) + out - number /= 1000 - i++ - //testing(" ([recursion]) out=list("+list2text(out,", ")+")") - return out - -///mob/verb/test_num2words(var/number as num) +*/ +/* + * Text sanitization + */ + +//Simply removes < and > and limits the length of the message +/proc/strip_html_simple(var/t,var/limit=MAX_MESSAGE_LEN) + var/list/strip_chars = list("<",">") + t = copytext(t,1,limit) + for(var/char in strip_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + copytext(t, index+1) + index = findtext(t, char) + return t + +/proc/strip_html_properly(input = "") + // these store the position of < and > respectively + var/opentag = 0 + var/closetag = 0 + + while (input) + opentag = rfindtext(input, "<") + closetag = findtext(input, ">", opentag + 1) + + if (!opentag || !closetag) + break + + input = copytext(input, 1, opentag) + copytext(input, closetag + 1) + + return input + +/proc/rfindtext(Haystack, Needle, Start = 1, End = 0) + var/i = findtext(Haystack, Needle, Start, End) + + while (i) + . = i + i = findtext(Haystack, Needle, i + 1, End) + +//Removes a few problematic characters +/proc/sanitize_simple(var/t,var/list/repl_chars = list("\n"="#","\t"="#","�"="�")) + for(var/char in repl_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+1) + index = findtext(t, char) + return t + +//Runs byond's sanitization proc along-side sanitize_simple +/proc/sanitize(var/t,var/list/repl_chars = null) + return html_encode(sanitize_simple(t,repl_chars)) + +//Runs sanitize and strip_html_simple +//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '<' after sanitize() calls byond's html_encode() +/proc/strip_html(var/t,var/limit=MAX_MESSAGE_LEN) + return copytext((sanitize(strip_html_simple(t))),1,limit) + +//Runs byond's sanitization proc along-side strip_html_simple +//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '<' that html_encode() would cause +/proc/adminscrub(var/t,var/limit=MAX_MESSAGE_LEN) + return copytext((html_encode(strip_html_simple(t))),1,limit) + +/proc/reverse_text(txt) + var/i = length(txt)+1 + . = "" + while(--i) + . += copytext(txt,i,i+1) + +/* + * returns null if there is any bad text in the string + */ +/proc/reject_bad_text(const/text, var/max_length = 512) + var/text_length = length(text) + + if(text_length > max_length) + return // message too long + + var/non_whitespace = FALSE + + for(var/i = 1 to text_length) + switch(text2ascii(text, i)) + if(62, 60, 92, 47) + return // rejects the text if it contains these bad characters: <, >, \ or / + if(127 to 255) + return // rejects weird letters like � + if(0 to 31) + return // more weird stuff + if(32) + continue //whitespace + else + non_whitespace = TRUE + + if(non_whitespace) + return text // only accepts the text if it has some non-spaces + +// Used to get a sanitized input. +/proc/stripped_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN) + var/name = input(user, message, title, default) + return strip_html_simple(name, max_length) + +//Filters out undesirable characters from names +/proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN) + if(!t_in || length(t_in) > max_length) + return //Rejects the input if it is null or if it is longer then the max length allowed + + var/number_of_alphanumeric = 0 + var/last_char_group = 0 + var/t_out = "" + + for(var/i=1, i<=length(t_in), i++) + var/ascii_char = text2ascii(t_in,i) + switch(ascii_char) + // A .. Z + if(65 to 90) //Uppercase Letters + t_out += ascii2text(ascii_char) + number_of_alphanumeric++ + last_char_group = 4 + + // a .. z + if(97 to 122) //Lowercase Letters + if(last_char_group<2) t_out += ascii2text(ascii_char-32) //Force uppercase first character + else t_out += ascii2text(ascii_char) + number_of_alphanumeric++ + last_char_group = 4 + + // 0 .. 9 + if(48 to 57) //Numbers + if(!last_char_group) continue //suppress at start of string + if(!allow_numbers) continue + t_out += ascii2text(ascii_char) + number_of_alphanumeric++ + last_char_group = 3 + + // ' - . + if(39,45,46) //Common name punctuation + if(!last_char_group) continue + t_out += ascii2text(ascii_char) + last_char_group = 2 + + // ~ | @ : # $ % & * + + if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI) + if(!last_char_group) continue //suppress at start of string + if(!allow_numbers) continue + t_out += ascii2text(ascii_char) + last_char_group = 2 + + //Space + if(32) + if(last_char_group <= 1) continue //suppress double-spaces and spaces at start of string + t_out += ascii2text(ascii_char) + last_char_group = 1 + else + return + + if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '" + + if(last_char_group == 1) + t_out = copytext(t_out,1,length(t_out)) //removes the last character (in this case a space) + + for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai","plating")) //prevents these common metagamey names + if(cmptext(t_out,bad_name)) return //(not case sensitive) + + return t_out + +//checks text for html tags +//if tag is not in whitelist (var/list/paper_tag_whitelist in global.dm) +//relpaces < with < +proc/checkhtml(var/t) + t = sanitize_simple(t, list("&#"=".")) + var/p = findtext(t,"<",1) + while (p) //going through all the tags + var/start = p++ + var/tag = copytext(t,p, p+1) + if (tag != "/") + while (reject_bad_text(copytext(t, p, p+1), 1)) + tag = copytext(t,start, p) + p++ + tag = copytext(t,start+1, p) + if (!(tag in paper_tag_whitelist)) //if it's unkown tag, disarming it + t = copytext(t,1,start-1) + "<" + copytext(t,start+1) + p = findtext(t,"<",p) + return t +/* + * Text searches + */ + +//Checks the beginning of a string for a specified sub-string +//Returns the position of the substring or 0 if it was not found +/proc/dd_hasprefix(text, prefix) + var/start = 1 + var/end = length(prefix) + 1 + return findtext(text, prefix, start, end) + +//Checks the beginning of a string for a specified sub-string. This proc is case sensitive +//Returns the position of the substring or 0 if it was not found +/proc/dd_hasprefix_case(text, prefix) + var/start = 1 + var/end = length(prefix) + 1 + return findtextEx(text, prefix, start, end) + +//Checks the end of a string for a specified substring. +//Returns the position of the substring or 0 if it was not found +/proc/dd_hassuffix(text, suffix) + var/start = length(text) - length(suffix) + if(start) + return findtext(text, suffix, start, null) + return + +//Checks the end of a string for a specified substring. This proc is case sensitive +//Returns the position of the substring or 0 if it was not found +/proc/dd_hassuffix_case(text, suffix) + var/start = length(text) - length(suffix) + if(start) + return findtextEx(text, suffix, start, null) + +/* + * Text modification + */ +/proc/replacetext(text, find, replacement) + return list2text(text2list(text, find), replacement) + +/proc/replacetextEx(text, find, replacement) + return list2text(text2listEx(text, find), replacement) + +//Adds 'u' number of zeros ahead of the text 't' +/proc/add_zero(t, u) + while (length(t) < u) + t = "0[t]" + return t + +//Adds 'u' number of spaces ahead of the text 't' +/proc/add_lspace(t, u) + while(length(t) < u) + t = " [t]" + return t + +//Adds 'u' number of spaces behind the text 't' +/proc/add_tspace(t, u) + while(length(t) < u) + t = "[t] " + return t + +//Returns a string with reserved characters and spaces before the first letter removed +/proc/trim_left(text) + for (var/i = 1 to length(text)) + if (text2ascii(text, i) > 32) + return copytext(text, i) + return "" + +//Returns a string with reserved characters and spaces after the last letter removed +/proc/trim_right(text) + for (var/i = length(text), i > 0, i--) + if (text2ascii(text, i) > 32) + return copytext(text, 1, i + 1) + + return "" + +//Returns a string with reserved characters and spaces before the first word and after the last word removed. +/proc/trim(text) + return trim_left(trim_right(text)) + +//Returns a string with the first element of the string capitalized. +/proc/capitalize(var/t as text) + return uppertext(copytext(t, 1, 2)) + copytext(t, 2) + +//Centers text by adding spaces to either side of the string. +/proc/dd_centertext(message, length) + var/new_message = message + var/size = length(message) + var/delta = length - size + if(size == length) + return new_message + if(size > length) + return copytext(new_message, 1, length + 1) + if(delta == 1) + return new_message + " " + if(delta % 2) + new_message = " " + new_message + delta-- + var/spaces = add_lspace("",delta/2-1) + return spaces + new_message + spaces + +//Limits the length of the text. Note: MAX_MESSAGE_LEN and MAX_NAME_LEN are widely used for this purpose +/proc/dd_limittext(message, length) + var/size = length(message) + if(size <= length) + return message + return copytext(message, 1, length + 1) + +/proc/stringmerge(var/text,var/compare,replace = "*") +//This proc fills in all spaces with the "replace" var (* by default) with whatever +//is in the other string at the same spot (assuming it is not a replace char). +//This is used for fingerprints + var/newtext = text + if(length(text) != length(compare)) + return 0 + for(var/i = 1, i < length(text), i++) + var/a = copytext(text,i,i+1) + var/b = copytext(compare,i,i+1) +//if it isn't both the same letter, or if they are both the replacement character +//(no way to know what it was supposed to be) + if(a != b) + if(a == replace) //if A is the replacement char + newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1) + else if(b == replace) //if B is the replacement char + newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1) + else //The lists disagree, Uh-oh! + return 0 + return newtext + +/proc/stringpercent(var/text,character = "*") +//This proc returns the number of chars of the string that is the character +//This is used for detective work to determine fingerprint completion. + if(!text || !character) + return 0 + var/count = 0 + for(var/i = 1, i <= length(text), i++) + var/a = copytext(text,i,i+1) + if(a == character) + count++ + return count + +/** + * Format number with thousands seperators. + * @param number Number to format. + * @param sep seperator to use + */ +/proc/format_num(var/number, var/sep=",") + var/c="" // Current char + var/list/parts = text2list("[number]",".") + var/origtext = "[parts[1]]" + var/len = length(origtext) + var/offset = len % 3 + for(var/i=1;i<=len;i++) + c = copytext(origtext,i,i+1) + . += c + if((i%3)==offset && i!=len) + . += sep + if(parts.len==2) + . += ".[parts[2]]" + +var/global/list/watt_suffixes = list("W", "KW", "MW", "GW", "TW", "PW", "EW", "ZW", "YW") +/proc/format_watts(var/number) + if(number<0) return "-[format_watts(number)]" + if(number==0) return "0 W" + + var/i=1 + while (round(number/1000) >= 1) + number/=1000 + i++ + return "[format_num(number)] [watt_suffixes[i]]" + + +// Custom algorithm since stackoverflow is full of complete garbage and even the MS algorithm sucks. +// Uses recursion, in places. +// (c)2015 Rob "N3X15" Nelson +// Available under the MIT license. + +var/list/number_digits=list( + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten", + "eleven", + "twelve", + "thirteen", + "fourteen", + "fifteen", + "sixteen", + "seventeen", + "eighteen", + "nineteen", +) + +var/list/number_tens=list( + null, // 0 :V + null, // teens, special case + "twenty", + "thirty", + "forty", + "fifty", + "sixty", + "seventy", + "eighty", + "ninety" +) + +var/list/number_units=list( + null, // Don't yell units + "thousand", + "million", + "billion" +) + +/proc/num2words(var/number, var/zero="zero", var/minus="minus", var/hundred="hundred", var/list/digits=number_digits, var/list/tens=number_tens, var/list/units=number_units, var/recursion=0) + if(!isnum(number)) + warning("num2words fed a non-number: [number]") + return list() + number=round(number) + //testing("num2words [recursion] ([number])") + if(number == 0) + return list(zero) + + if(number < 0) + return list(minus) + num2words(abs(number), zero, minus, hundred, digits, tens, units, recursion+1) + + var/list/out=list() + if(number < 1000) + var/hundreds = round(number/100) + //testing(" ([recursion]) hundreds=[hundreds]") + if(hundreds) + out += num2words(hundreds, zero, minus, hundred, digits, tens, units, recursion+1) + list(hundred) + number %= 100 + + if(number < 100) + // Teens + if(number <= 19) + out.Add(digits[number]) + else + var/tens_place = tens[round(number/10)+1] + //testing(" ([recursion]) tens_place=[round(number/10)+1] = [tens_place]") + if(tens_place!=null) + out.Add(tens_place) + number = number%10 + //testing(" ([recursion]) number%10+1 = [number+1] = [digits[number+1]]") + if(number>0) + out.Add(digits[number]) + else + var/i=1 + while(round(number) > 0) + var/unit_number = number%1000 + //testing(" ([recursion]) [number]%1000 = [unit_number] ([i])") + if(unit_number > 0) + if(units[i]) + //testing(" ([recursion]) units = [units[i]]") + out = list(units[i]) + out + out = num2words(unit_number, zero, minus, hundred, digits, tens, units, recursion+1) + out + number /= 1000 + i++ + //testing(" ([recursion]) out=list("+list2text(out,", ")+")") + return out + +///mob/verb/test_num2words(var/number as num) // to_chat(usr, "\"[list2text(num2words(number), " ")]\"") diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 793ff9778b5..aaead754e8b 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -1,73 +1,73 @@ -// So you can be all 10 SECONDS -#define SECONDS * 10 -#define MINUTES * 600 -#define HOURS * 36000 - -//Returns the world time in english -/proc/worldtime2text(timestamp = world.time) - return "[(round(timestamp / 36000) + 12) % 24]:[(timestamp / 600 % 60) < 10 ? add_zero(timestamp / 600 % 60, 1) : timestamp / 600 % 60]" - - -/proc/formatTimeDuration(var/deciseconds) - var/m = round(deciseconds / 600) - var/s = (deciseconds % 600)/10 - var/h = round(m / 60) - m = m % 60 - if(h>0) - . += "[h]:" - if(h>0 || m > 0) - . += "[(m<10)?"0":""][m]:" - . += "[(s<10)?"0":""][s]" - -/proc/altFormatTimeDuration(var/deciseconds) - var/m = round(deciseconds / 600) - var/s = (deciseconds % 600)/10 - var/h = round(m / 60) - m = m % 60 - if(h > 0) - . += "[h]h " - if(m > 0) - . += "[m]m " - . += "[s]s" - -/proc/time_stamp() - return time2text(world.timeofday, "hh:mm:ss") - -/* Preserving this so future generations can see how fucking retarded some people are -/proc/time_stamp() - var/hh = text2num(time2text(world.timeofday, "hh")) // Set the hour - var/mm = text2num(time2text(world.timeofday, "mm")) // Set the minute - var/ss = text2num(time2text(world.timeofday, "ss")) // Set the second - var/ph - var/pm - var/ps - if(hh < 10) ph = "0" - if(mm < 10) pm = "0" - if(ss < 10) ps = "0" - return"[ph][hh]:[pm][mm]:[ps][ss]" -*/ - -/* Returns 1 if it is the selected month and day */ -/proc/isDay(var/month, var/day) - if(isnum(month) && isnum(day)) - var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month - var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day - if(month == MM && day == DD) - return 1 - - // Uncomment this out when debugging! - //else - //return 1 - -/** - * Returns "watch handle" (really just a timestamp :V) - */ -/proc/start_watch() - return world.timeofday - -/** - * Returns number of seconds elapsed. - * @param wh number The "Watch Handle" from start_watch(). (timestamp) - */ -/proc/stop_watch(wh) +// So you can be all 10 SECONDS +#define SECONDS * 10 +#define MINUTES * 600 +#define HOURS * 36000 + +//Returns the world time in english +/proc/worldtime2text(timestamp = world.time) + return "[(round(timestamp / 36000) + 12) % 24]:[(timestamp / 600 % 60) < 10 ? add_zero(timestamp / 600 % 60, 1) : timestamp / 600 % 60]" + + +/proc/formatTimeDuration(var/deciseconds) + var/m = round(deciseconds / 600) + var/s = (deciseconds % 600)/10 + var/h = round(m / 60) + m = m % 60 + if(h>0) + . += "[h]:" + if(h>0 || m > 0) + . += "[(m<10)?"0":""][m]:" + . += "[(s<10)?"0":""][s]" + +/proc/altFormatTimeDuration(var/deciseconds) + var/m = round(deciseconds / 600) + var/s = (deciseconds % 600)/10 + var/h = round(m / 60) + m = m % 60 + if(h > 0) + . += "[h]h " + if(m > 0) + . += "[m]m " + . += "[s]s" + +/proc/time_stamp() + return time2text(world.timeofday, "hh:mm:ss") + +/* Preserving this so future generations can see how fucking retarded some people are +/proc/time_stamp() + var/hh = text2num(time2text(world.timeofday, "hh")) // Set the hour + var/mm = text2num(time2text(world.timeofday, "mm")) // Set the minute + var/ss = text2num(time2text(world.timeofday, "ss")) // Set the second + var/ph + var/pm + var/ps + if(hh < 10) ph = "0" + if(mm < 10) pm = "0" + if(ss < 10) ps = "0" + return"[ph][hh]:[pm][mm]:[ps][ss]" +*/ + +/* Returns 1 if it is the selected month and day */ +/proc/isDay(var/month, var/day) + if(isnum(month) && isnum(day)) + var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month + var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day + if(month == MM && day == DD) + return 1 + + // Uncomment this out when debugging! + //else + //return 1 + +/** + * Returns "watch handle" (really just a timestamp :V) + */ +/proc/start_watch() + return world.timeofday + +/** + * Returns number of seconds elapsed. + * @param wh number The "Watch Handle" from start_watch(). (timestamp) + */ +/proc/stop_watch(wh) return round(0.1*(world.timeofday-wh),0.1) \ No newline at end of file diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 4bbda772fbc..92e5a2698ca 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -1,705 +1,705 @@ -/datum/configuration - var/server_name = null // server name (for world name / status) - var/server_suffix = 0 // generate numeric suffix based on server port - var/world_style_config = world_style - - var/nudge_script_path = "nudge.py" // where the nudge.py script is located - - var/log_ooc = 0 // log OOC channel - var/log_access = 0 // log login/logout - var/log_say = 0 // log client say - var/log_admin = 0 // log admin actions - var/log_admin_only = FALSE - var/log_debug = 1 // log debug output - var/log_game = 0 // log game events - var/log_vote = 0 // log voting - var/log_whisper = 0 // log client whisper - var/log_emote = 0 // log emotes - var/log_attack = 0 // log attack messages - var/log_adminchat = 0 // log admin chat messages - var/log_adminwarn = 0 // log warnings admins get about bomb construction and such - var/log_adminghost = 1 // log warnings admins get about bomb construction and such - var/log_pda = 0 // log pda messages - var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits - var/log_runtimes = 0 // Logs all runtimes. - var/sql_enabled = 1 // for sql switching - var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour - var/allow_vote_restart = 0 // allow votes to restart - var/allow_vote_mode = 0 // allow votes to change mode - var/allow_admin_jump = 1 // allows admin jumping - var/allow_admin_spawning = 1 // allows admin item spawning - var/allow_admin_rev = 1 // allows admin revives - var/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default) - var/vote_period = 600 // length of voting period (deciseconds, default 1 minute) - var/vote_no_default = 0 // vote does not default to nochange/norestart (tbi) - var/vote_no_dead = 0 // dead people can't vote (tbi) -// var/enable_authentication = 0 // goon authentication - var/del_new_on_log = 1 // del's new players if they log before they spawn in - 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/protect_roles_from_antagonist = 0// If security and such can be tratior/cult/other - var/continous_rounds = 0 // 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. - var/Ticklag = 0.9 - var/socket_talk = 0 // use socket_talk to communicate with other processes - var/list/resource_urls = null - var/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round. - var/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round. - var/list/mode_names = list() - var/list/modes = list() // allowed modes - var/list/votable_modes = list() // votable modes - var/list/probabilities = list() // relative probability of each mode - var/humans_need_surnames = 0 - var/allow_random_events = 0 // enables random events mid-round when set to 1 - var/allow_ai = 1 // allow ai job - var/hostedby = null - var/respawn = 1 - var/respawn_delay=30 - var/respawn_as_mommi = 0 - var/respawn_as_mouse = 1 - var/guest_jobban = 1 - var/usewhitelist = 0 - var/kick_inactive = 0 //force disconnect for inactive players - var/load_jobs_from_txt = 0 - var/ToRban = 0 - var/automute_on = 0 //enables automuting/spam prevention - var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access. - var/copy_logs = null - - var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds... - var/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active. - - var/borer_takeover_immediately = 0 - - var/disable_player_mice = 0 - var/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech - - var/usealienwhitelist = 0 - var/limitalienplayers = 0 - var/alien_to_human_ratio = 0.5 - - //used to determine if cyborgs/AI can speak - var/silent_ai = 0 - var/silent_borg = 0 - - var/server - var/banappeals - var/wikiurl = "http://baystation12.net/wiki/index.php?title=Main_Page" - var/vgws_base_url = "http://ss13.pomf.se" // No hanging slashes. - var/forumurl = "http://baystation12.net/forums/" - - var/media_base_url = "" // http://ss13.nexisonline.net/media - var/media_secret_key = "" // Random string - - //Alert level description - var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." - var/alert_desc_blue_upto = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted." - var/alert_desc_blue_downto = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed." - var/alert_desc_red_upto = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised." - var/alert_desc_red_downto = "The self-destruct mechanism has been deactivated, there is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised." - var/alert_desc_delta = "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." - - var/forbid_singulo_possession = 0 - - //game_options.txt configs - - var/health_threshold_softcrit = 0 - var/health_threshold_crit = 0 - var/health_threshold_dead = -100 - - var/organ_health_multiplier = 1 - var/organ_regeneration_multiplier = 1 - - var/bones_can_break = 0 - var/limbs_can_break = 0 - - var/revival_pod_plants = 1 - var/revival_cloning = 1 - var/revival_brain_life = -1 - - //Used for modifying movement speed for mobs. - //Unversal modifiers - var/run_speed = 0 - var/walk_speed = 0 - - //Mob specific modifiers. NOTE: These will affect different mob types in different ways - var/human_delay = 0 - var/robot_delay = 0 - var/monkey_delay = 0 - var/alien_delay = 0 - var/slime_delay = 0 - var/animal_delay = 0 - - var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt - var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt - var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database - - var/simultaneous_pm_warning_timeout = 100 - - var/use_recursive_explosions //Defines whether the server uses recursive or circular explosions. - - var/assistant_maint = 0 //Do assistants get maint access? - var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour. - var/ghost_interaction = 0 - - var/comms_password = "" - var/paperwork_library = 0 //use the library DLL. - - var/use_irc_bot = 0 - var/irc_bot_host = "localhost" - var/irc_bot_port = 45678 - var/irc_bot_server_id = 45678 - var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix - - var/assistantlimit = 0 //enables assistant limiting - var/assistantratio = 2 //how many assistants to security members - - var/emag_energy = -1 - var/emag_starts_charged = 1 - var/emag_recharge_rate = 0 - var/emag_recharge_ticks = 0 - - var/map_voting = 0 - var/renders_url = "" - - var/default_ooc_color = "#002eb8" - - var/mommi_static = 0 //Scrambling mobs for mommis or not - -/datum/configuration/New() - . = ..() - var/list/L = typesof(/datum/game_mode) - /datum/game_mode - - for (var/T in L) - // I wish I didn't have to instance the game modes in order to look up - // their information, but it is the only way (at least that I know of). - var/datum/game_mode/M = new T() - - if (M.config_tag) - if (!(M.config_tag in modes)) // Ensure each mode is added only once. - diary << "Adding game mode [M.name] ([M.config_tag]) to configuration." - src.modes += M.config_tag - src.mode_names[M.config_tag] = M.name - src.probabilities[M.config_tag] = M.probability - - if (M.votable) - votable_modes += M.config_tag - qdel(M) - - votable_modes += "secret" - -/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist - var/list/Lines = file2list(filename) - - for(var/t in Lines) - if(!t) continue - - t = trim(t) - if (length(t) == 0) - continue - else if (copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if (pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if (!name) - continue - - if(type == "config") - switch (name) - if ("resource_urls") - config.resource_urls = text2list(value, " ") - - if ("admin_legacy_system") - config.admin_legacy_system = 1 - - if ("ban_legacy_system") - config.ban_legacy_system = 1 - - if ("use_age_restriction_for_jobs") - config.use_age_restriction_for_jobs = 1 - - if ("jobs_have_minimal_access") - config.jobs_have_minimal_access = 1 - - if ("use_recursive_explosions") - use_recursive_explosions = 1 - - if ("log_ooc") - config.log_ooc = 1 - - if ("log_access") - config.log_access = 1 - - if ("sql_enabled") - config.sql_enabled = text2num(value) - - if ("log_say") - config.log_say = 1 - - if ("log_admin") - config.log_admin = 1 - - if("log_admin_only") - config.log_admin_only = TRUE - - if ("log_debug") - config.log_debug = text2num(value) - - if ("log_game") - config.log_game = 1 - - if ("log_vote") - config.log_vote = 1 - - if ("log_whisper") - config.log_whisper = 1 - - if ("log_attack") - config.log_attack = 1 - - if ("log_emote") - config.log_emote = 1 - - if ("log_adminchat") - config.log_adminchat = 1 - - if ("log_adminwarn") - config.log_adminwarn = 1 - - if ("log_adminghost") - config.log_adminghost = 1 - - if ("log_runtimes") - config.log_runtimes = 1 - - if ("log_pda") - config.log_pda = 1 - - if ("log_hrefs") - config.log_hrefs = 1 - - if("allow_admin_ooccolor") - config.allow_admin_ooccolor = 1 - - if ("allow_vote_restart") - config.allow_vote_restart = 1 - - if ("allow_vote_mode") - config.allow_vote_mode = 1 - - if ("allow_admin_jump") - config.allow_admin_jump = 1 - - if("allow_admin_rev") - config.allow_admin_rev = 1 - - if ("allow_admin_spawning") - config.allow_admin_spawning = 1 - - if ("no_dead_vote") - config.vote_no_dead = 1 - - if ("default_no_vote") - config.vote_no_default = 1 - - if ("vote_delay") - config.vote_delay = text2num(value) - - if ("vote_period") - config.vote_period = text2num(value) - - if ("allow_ai") - config.allow_ai = 1 - -// if ("authentication") -// config.enable_authentication = 1 - - if ("norespawn") - config.respawn = 0 - - if ("respawn_as_mommi") - config.respawn_as_mommi = 1 - - if ("no_respawn_as_mouse") - config.respawn_as_mouse = 0 - - if ("servername") - config.server_name = value - - if ("serversuffix") - config.server_suffix = 1 - - if ("nudge_script_path") - config.nudge_script_path = value - - if ("hostedby") - config.hostedby = value - - if ("server") - config.server = value - - if ("banappeals") - config.banappeals = value - - if ("wikiurl") - config.wikiurl = value - - if ("forumurl") - config.forumurl = value - - if ("guest_jobban") - config.guest_jobban = 1 - - if ("guest_ban") - guests_allowed = 0 - - if ("usewhitelist") - config.usewhitelist = 1 - - if ("feature_object_spell_system") - config.feature_object_spell_system = 1 - - if ("allow_metadata") - config.allow_Metadata = 1 - - if ("traitor_scaling") - config.traitor_scaling = 1 - - if("protect_roles_from_antagonist") - config.protect_roles_from_antagonist = 1 - - if ("probability") - var/prob_pos = findtext(value, " ") - var/prob_name = null - var/prob_value = null - - if (prob_pos) - prob_name = lowertext(copytext(value, 1, prob_pos)) - prob_value = copytext(value, prob_pos + 1) - if (prob_name in config.modes) - config.probabilities[prob_name] = text2num(prob_value) - else - diary << "Unknown game mode probability configuration definition: [prob_name]." - else - diary << "Incorrect probability configuration definition: [prob_name] [prob_value]." - - if("allow_random_events") - config.allow_random_events = 1 - - if("kick_inactive") - config.kick_inactive = 1 - - if("load_jobs_from_txt") - load_jobs_from_txt = 1 - - if("alert_red_upto") - config.alert_desc_red_upto = value - - if("alert_red_downto") - config.alert_desc_red_downto = value - - if("alert_blue_downto") - config.alert_desc_blue_downto = value - - if("alert_blue_upto") - config.alert_desc_blue_upto = value - - if("alert_green") - config.alert_desc_green = value - - if("alert_delta") - config.alert_desc_delta = value - - if("forbid_singulo_possession") - forbid_singulo_possession = 1 - - if("popup_admin_pm") - config.popup_admin_pm = 1 - - if("allow_holidays") - Holiday = 1 - - if("use_irc_bot") - use_irc_bot = 1 - - if("ticklag") - Ticklag = text2num(value) - - if("allow_antag_hud") - config.antag_hud_allowed = 1 - if("antag_hud_restricted") - config.antag_hud_restricted = 1 - - if("socket_talk") - socket_talk = text2num(value) - - if("humans_need_surnames") - humans_need_surnames = 1 - - if("tor_ban") - ToRban = 1 - - if("automute_on") - automute_on = 1 - - if("usealienwhitelist") - usealienwhitelist = 1 - - if("alien_player_ratio") - limitalienplayers = 1 - alien_to_human_ratio = text2num(value) - - if("assistant_maint") - config.assistant_maint = 1 - - if("gateway_delay") - config.gateway_delay = text2num(value) - - if("continuous_rounds") - config.continous_rounds = 1 - - if("ghost_interaction") - config.ghost_interaction = 1 - - if("disable_player_mice") - config.disable_player_mice = 1 - - if("uneducated_mice") - config.uneducated_mice = 1 - - if("comms_password") - config.comms_password = value - - if("paperwork_library") - config.paperwork_library = 1 - - if("irc_bot_host") - config.irc_bot_host = value - - if("irc_bot_port") - config.irc_bot_port = text2num(value) - - if("irc_bot_server_id") - config.irc_bot_server_id = value - - if("python_path") - if(value) - config.python_path = value - else - if(world.system_type == UNIX) - config.python_path = "/usr/bin/env python2" - else //probably windows, if not this should work anyway - config.python_path = "python" - - if("allow_cult_ghostwriter") - config.cult_ghostwriter = 1 - - if("req_cult_ghostwriter") - config.cult_ghostwriter_req_cultists = value - if("assistant_limit") - config.assistantlimit = 1 - if("assistant_ratio") - config.assistantratio = text2num(value) - if("copy_logs") - copy_logs=value - if("media_base_url") - media_base_url = value - if("media_secret_key") - media_secret_key = value - if("vgws_base_url") - vgws_base_url = value - if("map_voting") - map_voting = 1 - if("renders_url") - renders_url = value - if("mommi_static") - mommi_static = 1 - else - diary << "Unknown setting in configuration: '[name]'" - - else if(type == "game_options") - if(!value) - diary << "Unknown value for setting [name] in [filename]." - value = text2num(value) - - switch(name) - if("max_explosion_range") - MAX_EXPLOSION_RANGE = value - if("health_threshold_crit") - config.health_threshold_crit = value - if("health_threshold_softcrit") - config.health_threshold_softcrit = value - if("health_threshold_dead") - config.health_threshold_dead = value - if("revival_pod_plants") - config.revival_pod_plants = value - if("revival_cloning") - config.revival_cloning = value - if("revival_brain_life") - config.revival_brain_life = value - if("run_speed") - config.run_speed = value - if("walk_speed") - config.walk_speed = value - if("human_delay") - config.human_delay = value - if("robot_delay") - config.robot_delay = value - if("monkey_delay") - config.monkey_delay = value - if("alien_delay") - config.alien_delay = value - if("slime_delay") - config.slime_delay = value - if("animal_delay") - config.animal_delay = value - if("organ_health_multiplier") - config.organ_health_multiplier = value / 100 - if("organ_regeneration_multiplier") - config.organ_regeneration_multiplier = value / 100 - if("bones_can_break") - config.bones_can_break = value - if("limbs_can_break") - config.limbs_can_break = value - if("respawn_delay") - config.respawn_delay = value - if("emag_energy") - config.emag_energy = value - if("emag_starts_charged") - config.emag_starts_charged = value - if("emag_recharge_rate") - config.emag_recharge_rate = value - if("emag_recharge_ticks") - config.emag_recharge_ticks = value - if("silent_ai") - config.silent_ai = 1 - if("silent_borg") - config.silent_borg = 1 - if("borer_takeover_immediately") - config.borer_takeover_immediately = 1 - else - diary << "Unknown setting in configuration: '[name]'" - -/datum/configuration/proc/loadsql(filename) // -- TLE - var/list/Lines = file2list(filename) - for(var/t in Lines) - if(!t) continue - - t = trim(t) - if (length(t) == 0) - continue - else if (copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if (pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if (!name) - continue - - switch (name) - if ("address") - sqladdress = value - if ("port") - sqlport = value - if ("database") - sqldb = value - if ("login") - sqllogin = value - if ("password") - sqlpass = value - if ("feedback_database") - sqlfdbkdb = value - if ("feedback_login") - sqlfdbklogin = value - if ("feedback_password") - sqlfdbkpass = value - if ("enable_stat_tracking") - sqllogging = 1 - else - diary << "Unknown setting in configuration: '[name]'" - -/datum/configuration/proc/loadforumsql(filename) // -- TLE - var/list/Lines = file2list(filename) - for(var/t in Lines) - if(!t) continue - - t = trim(t) - if (length(t) == 0) - continue - else if (copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if (pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if (!name) - continue - - switch (name) - if ("address") - forumsqladdress = value - if ("port") - forumsqlport = value - if ("database") - forumsqldb = value - if ("login") - forumsqllogin = value - if ("password") - forumsqlpass = value - if ("activatedgroup") - forum_activated_group = value - if ("authenticatedgroup") - forum_authenticated_group = value - else - diary << "Unknown setting in configuration: '[name]'" - -/datum/configuration/proc/pick_mode(mode_name) - // I wish I didn't have to instance the game modes in order to look up - // their information, but it is the only way (at least that I know of). - for (var/T in (typesof(/datum/game_mode) - /datum/game_mode)) - var/datum/game_mode/M = new T() - if (M.config_tag && M.config_tag == mode_name) - return M - del(M) - return new /datum/game_mode/extended() - -/datum/configuration/proc/get_runnable_modes() - var/list/datum/game_mode/runnable_modes = new - for (var/T in (typesof(/datum/game_mode) - /datum/game_mode)) - var/datum/game_mode/M = new T() +/datum/configuration + var/server_name = null // server name (for world name / status) + var/server_suffix = 0 // generate numeric suffix based on server port + var/world_style_config = world_style + + var/nudge_script_path = "nudge.py" // where the nudge.py script is located + + var/log_ooc = 0 // log OOC channel + var/log_access = 0 // log login/logout + var/log_say = 0 // log client say + var/log_admin = 0 // log admin actions + var/log_admin_only = FALSE + var/log_debug = 1 // log debug output + var/log_game = 0 // log game events + var/log_vote = 0 // log voting + var/log_whisper = 0 // log client whisper + var/log_emote = 0 // log emotes + var/log_attack = 0 // log attack messages + var/log_adminchat = 0 // log admin chat messages + var/log_adminwarn = 0 // log warnings admins get about bomb construction and such + var/log_adminghost = 1 // log warnings admins get about bomb construction and such + var/log_pda = 0 // log pda messages + var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits + var/log_runtimes = 0 // Logs all runtimes. + var/sql_enabled = 1 // for sql switching + var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour + var/allow_vote_restart = 0 // allow votes to restart + var/allow_vote_mode = 0 // allow votes to change mode + var/allow_admin_jump = 1 // allows admin jumping + var/allow_admin_spawning = 1 // allows admin item spawning + var/allow_admin_rev = 1 // allows admin revives + var/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default) + var/vote_period = 600 // length of voting period (deciseconds, default 1 minute) + var/vote_no_default = 0 // vote does not default to nochange/norestart (tbi) + var/vote_no_dead = 0 // dead people can't vote (tbi) +// var/enable_authentication = 0 // goon authentication + var/del_new_on_log = 1 // del's new players if they log before they spawn in + 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/protect_roles_from_antagonist = 0// If security and such can be tratior/cult/other + var/continous_rounds = 0 // 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. + var/Ticklag = 0.9 + var/socket_talk = 0 // use socket_talk to communicate with other processes + var/list/resource_urls = null + var/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round. + var/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round. + var/list/mode_names = list() + var/list/modes = list() // allowed modes + var/list/votable_modes = list() // votable modes + var/list/probabilities = list() // relative probability of each mode + var/humans_need_surnames = 0 + var/allow_random_events = 0 // enables random events mid-round when set to 1 + var/allow_ai = 1 // allow ai job + var/hostedby = null + var/respawn = 1 + var/respawn_delay=30 + var/respawn_as_mommi = 0 + var/respawn_as_mouse = 1 + var/guest_jobban = 1 + var/usewhitelist = 0 + var/kick_inactive = 0 //force disconnect for inactive players + var/load_jobs_from_txt = 0 + var/ToRban = 0 + var/automute_on = 0 //enables automuting/spam prevention + var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access. + var/copy_logs = null + + var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds... + var/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active. + + var/borer_takeover_immediately = 0 + + var/disable_player_mice = 0 + var/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech + + var/usealienwhitelist = 0 + var/limitalienplayers = 0 + var/alien_to_human_ratio = 0.5 + + //used to determine if cyborgs/AI can speak + var/silent_ai = 0 + var/silent_borg = 0 + + var/server + var/banappeals + var/wikiurl = "http://baystation12.net/wiki/index.php?title=Main_Page" + var/vgws_base_url = "http://ss13.pomf.se" // No hanging slashes. + var/forumurl = "http://baystation12.net/forums/" + + var/media_base_url = "" // http://ss13.nexisonline.net/media + var/media_secret_key = "" // Random string + + //Alert level description + var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." + var/alert_desc_blue_upto = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted." + var/alert_desc_blue_downto = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed." + var/alert_desc_red_upto = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised." + var/alert_desc_red_downto = "The self-destruct mechanism has been deactivated, there is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised." + var/alert_desc_delta = "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." + + var/forbid_singulo_possession = 0 + + //game_options.txt configs + + var/health_threshold_softcrit = 0 + var/health_threshold_crit = 0 + var/health_threshold_dead = -100 + + var/organ_health_multiplier = 1 + var/organ_regeneration_multiplier = 1 + + var/bones_can_break = 0 + var/limbs_can_break = 0 + + var/revival_pod_plants = 1 + var/revival_cloning = 1 + var/revival_brain_life = -1 + + //Used for modifying movement speed for mobs. + //Unversal modifiers + var/run_speed = 0 + var/walk_speed = 0 + + //Mob specific modifiers. NOTE: These will affect different mob types in different ways + var/human_delay = 0 + var/robot_delay = 0 + var/monkey_delay = 0 + var/alien_delay = 0 + var/slime_delay = 0 + var/animal_delay = 0 + + var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt + var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt + var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database + + var/simultaneous_pm_warning_timeout = 100 + + var/use_recursive_explosions //Defines whether the server uses recursive or circular explosions. + + var/assistant_maint = 0 //Do assistants get maint access? + var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour. + var/ghost_interaction = 0 + + var/comms_password = "" + var/paperwork_library = 0 //use the library DLL. + + var/use_irc_bot = 0 + var/irc_bot_host = "localhost" + var/irc_bot_port = 45678 + var/irc_bot_server_id = 45678 + var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix + + var/assistantlimit = 0 //enables assistant limiting + var/assistantratio = 2 //how many assistants to security members + + var/emag_energy = -1 + var/emag_starts_charged = 1 + var/emag_recharge_rate = 0 + var/emag_recharge_ticks = 0 + + var/map_voting = 0 + var/renders_url = "" + + var/default_ooc_color = "#002eb8" + + var/mommi_static = 0 //Scrambling mobs for mommis or not + +/datum/configuration/New() + . = ..() + var/list/L = typesof(/datum/game_mode) - /datum/game_mode + + for (var/T in L) + // I wish I didn't have to instance the game modes in order to look up + // their information, but it is the only way (at least that I know of). + var/datum/game_mode/M = new T() + + if (M.config_tag) + if (!(M.config_tag in modes)) // Ensure each mode is added only once. + diary << "Adding game mode [M.name] ([M.config_tag]) to configuration." + src.modes += M.config_tag + src.mode_names[M.config_tag] = M.name + src.probabilities[M.config_tag] = M.probability + + if (M.votable) + votable_modes += M.config_tag + qdel(M) + + votable_modes += "secret" + +/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist + var/list/Lines = file2list(filename) + + for(var/t in Lines) + if(!t) continue + + t = trim(t) + if (length(t) == 0) + continue + else if (copytext(t, 1, 2) == "#") + continue + + var/pos = findtext(t, " ") + var/name = null + var/value = null + + if (pos) + name = lowertext(copytext(t, 1, pos)) + value = copytext(t, pos + 1) + else + name = lowertext(t) + + if (!name) + continue + + if(type == "config") + switch (name) + if ("resource_urls") + config.resource_urls = text2list(value, " ") + + if ("admin_legacy_system") + config.admin_legacy_system = 1 + + if ("ban_legacy_system") + config.ban_legacy_system = 1 + + if ("use_age_restriction_for_jobs") + config.use_age_restriction_for_jobs = 1 + + if ("jobs_have_minimal_access") + config.jobs_have_minimal_access = 1 + + if ("use_recursive_explosions") + use_recursive_explosions = 1 + + if ("log_ooc") + config.log_ooc = 1 + + if ("log_access") + config.log_access = 1 + + if ("sql_enabled") + config.sql_enabled = text2num(value) + + if ("log_say") + config.log_say = 1 + + if ("log_admin") + config.log_admin = 1 + + if("log_admin_only") + config.log_admin_only = TRUE + + if ("log_debug") + config.log_debug = text2num(value) + + if ("log_game") + config.log_game = 1 + + if ("log_vote") + config.log_vote = 1 + + if ("log_whisper") + config.log_whisper = 1 + + if ("log_attack") + config.log_attack = 1 + + if ("log_emote") + config.log_emote = 1 + + if ("log_adminchat") + config.log_adminchat = 1 + + if ("log_adminwarn") + config.log_adminwarn = 1 + + if ("log_adminghost") + config.log_adminghost = 1 + + if ("log_runtimes") + config.log_runtimes = 1 + + if ("log_pda") + config.log_pda = 1 + + if ("log_hrefs") + config.log_hrefs = 1 + + if("allow_admin_ooccolor") + config.allow_admin_ooccolor = 1 + + if ("allow_vote_restart") + config.allow_vote_restart = 1 + + if ("allow_vote_mode") + config.allow_vote_mode = 1 + + if ("allow_admin_jump") + config.allow_admin_jump = 1 + + if("allow_admin_rev") + config.allow_admin_rev = 1 + + if ("allow_admin_spawning") + config.allow_admin_spawning = 1 + + if ("no_dead_vote") + config.vote_no_dead = 1 + + if ("default_no_vote") + config.vote_no_default = 1 + + if ("vote_delay") + config.vote_delay = text2num(value) + + if ("vote_period") + config.vote_period = text2num(value) + + if ("allow_ai") + config.allow_ai = 1 + +// if ("authentication") +// config.enable_authentication = 1 + + if ("norespawn") + config.respawn = 0 + + if ("respawn_as_mommi") + config.respawn_as_mommi = 1 + + if ("no_respawn_as_mouse") + config.respawn_as_mouse = 0 + + if ("servername") + config.server_name = value + + if ("serversuffix") + config.server_suffix = 1 + + if ("nudge_script_path") + config.nudge_script_path = value + + if ("hostedby") + config.hostedby = value + + if ("server") + config.server = value + + if ("banappeals") + config.banappeals = value + + if ("wikiurl") + config.wikiurl = value + + if ("forumurl") + config.forumurl = value + + if ("guest_jobban") + config.guest_jobban = 1 + + if ("guest_ban") + guests_allowed = 0 + + if ("usewhitelist") + config.usewhitelist = 1 + + if ("feature_object_spell_system") + config.feature_object_spell_system = 1 + + if ("allow_metadata") + config.allow_Metadata = 1 + + if ("traitor_scaling") + config.traitor_scaling = 1 + + if("protect_roles_from_antagonist") + config.protect_roles_from_antagonist = 1 + + if ("probability") + var/prob_pos = findtext(value, " ") + var/prob_name = null + var/prob_value = null + + if (prob_pos) + prob_name = lowertext(copytext(value, 1, prob_pos)) + prob_value = copytext(value, prob_pos + 1) + if (prob_name in config.modes) + config.probabilities[prob_name] = text2num(prob_value) + else + diary << "Unknown game mode probability configuration definition: [prob_name]." + else + diary << "Incorrect probability configuration definition: [prob_name] [prob_value]." + + if("allow_random_events") + config.allow_random_events = 1 + + if("kick_inactive") + config.kick_inactive = 1 + + if("load_jobs_from_txt") + load_jobs_from_txt = 1 + + if("alert_red_upto") + config.alert_desc_red_upto = value + + if("alert_red_downto") + config.alert_desc_red_downto = value + + if("alert_blue_downto") + config.alert_desc_blue_downto = value + + if("alert_blue_upto") + config.alert_desc_blue_upto = value + + if("alert_green") + config.alert_desc_green = value + + if("alert_delta") + config.alert_desc_delta = value + + if("forbid_singulo_possession") + forbid_singulo_possession = 1 + + if("popup_admin_pm") + config.popup_admin_pm = 1 + + if("allow_holidays") + Holiday = 1 + + if("use_irc_bot") + use_irc_bot = 1 + + if("ticklag") + Ticklag = text2num(value) + + if("allow_antag_hud") + config.antag_hud_allowed = 1 + if("antag_hud_restricted") + config.antag_hud_restricted = 1 + + if("socket_talk") + socket_talk = text2num(value) + + if("humans_need_surnames") + humans_need_surnames = 1 + + if("tor_ban") + ToRban = 1 + + if("automute_on") + automute_on = 1 + + if("usealienwhitelist") + usealienwhitelist = 1 + + if("alien_player_ratio") + limitalienplayers = 1 + alien_to_human_ratio = text2num(value) + + if("assistant_maint") + config.assistant_maint = 1 + + if("gateway_delay") + config.gateway_delay = text2num(value) + + if("continuous_rounds") + config.continous_rounds = 1 + + if("ghost_interaction") + config.ghost_interaction = 1 + + if("disable_player_mice") + config.disable_player_mice = 1 + + if("uneducated_mice") + config.uneducated_mice = 1 + + if("comms_password") + config.comms_password = value + + if("paperwork_library") + config.paperwork_library = 1 + + if("irc_bot_host") + config.irc_bot_host = value + + if("irc_bot_port") + config.irc_bot_port = text2num(value) + + if("irc_bot_server_id") + config.irc_bot_server_id = value + + if("python_path") + if(value) + config.python_path = value + else + if(world.system_type == UNIX) + config.python_path = "/usr/bin/env python2" + else //probably windows, if not this should work anyway + config.python_path = "python" + + if("allow_cult_ghostwriter") + config.cult_ghostwriter = 1 + + if("req_cult_ghostwriter") + config.cult_ghostwriter_req_cultists = value + if("assistant_limit") + config.assistantlimit = 1 + if("assistant_ratio") + config.assistantratio = text2num(value) + if("copy_logs") + copy_logs=value + if("media_base_url") + media_base_url = value + if("media_secret_key") + media_secret_key = value + if("vgws_base_url") + vgws_base_url = value + if("map_voting") + map_voting = 1 + if("renders_url") + renders_url = value + if("mommi_static") + mommi_static = 1 + else + diary << "Unknown setting in configuration: '[name]'" + + else if(type == "game_options") + if(!value) + diary << "Unknown value for setting [name] in [filename]." + value = text2num(value) + + switch(name) + if("max_explosion_range") + MAX_EXPLOSION_RANGE = value + if("health_threshold_crit") + config.health_threshold_crit = value + if("health_threshold_softcrit") + config.health_threshold_softcrit = value + if("health_threshold_dead") + config.health_threshold_dead = value + if("revival_pod_plants") + config.revival_pod_plants = value + if("revival_cloning") + config.revival_cloning = value + if("revival_brain_life") + config.revival_brain_life = value + if("run_speed") + config.run_speed = value + if("walk_speed") + config.walk_speed = value + if("human_delay") + config.human_delay = value + if("robot_delay") + config.robot_delay = value + if("monkey_delay") + config.monkey_delay = value + if("alien_delay") + config.alien_delay = value + if("slime_delay") + config.slime_delay = value + if("animal_delay") + config.animal_delay = value + if("organ_health_multiplier") + config.organ_health_multiplier = value / 100 + if("organ_regeneration_multiplier") + config.organ_regeneration_multiplier = value / 100 + if("bones_can_break") + config.bones_can_break = value + if("limbs_can_break") + config.limbs_can_break = value + if("respawn_delay") + config.respawn_delay = value + if("emag_energy") + config.emag_energy = value + if("emag_starts_charged") + config.emag_starts_charged = value + if("emag_recharge_rate") + config.emag_recharge_rate = value + if("emag_recharge_ticks") + config.emag_recharge_ticks = value + if("silent_ai") + config.silent_ai = 1 + if("silent_borg") + config.silent_borg = 1 + if("borer_takeover_immediately") + config.borer_takeover_immediately = 1 + else + diary << "Unknown setting in configuration: '[name]'" + +/datum/configuration/proc/loadsql(filename) // -- TLE + var/list/Lines = file2list(filename) + for(var/t in Lines) + if(!t) continue + + t = trim(t) + if (length(t) == 0) + continue + else if (copytext(t, 1, 2) == "#") + continue + + var/pos = findtext(t, " ") + var/name = null + var/value = null + + if (pos) + name = lowertext(copytext(t, 1, pos)) + value = copytext(t, pos + 1) + else + name = lowertext(t) + + if (!name) + continue + + switch (name) + if ("address") + sqladdress = value + if ("port") + sqlport = value + if ("database") + sqldb = value + if ("login") + sqllogin = value + if ("password") + sqlpass = value + if ("feedback_database") + sqlfdbkdb = value + if ("feedback_login") + sqlfdbklogin = value + if ("feedback_password") + sqlfdbkpass = value + if ("enable_stat_tracking") + sqllogging = 1 + else + diary << "Unknown setting in configuration: '[name]'" + +/datum/configuration/proc/loadforumsql(filename) // -- TLE + var/list/Lines = file2list(filename) + for(var/t in Lines) + if(!t) continue + + t = trim(t) + if (length(t) == 0) + continue + else if (copytext(t, 1, 2) == "#") + continue + + var/pos = findtext(t, " ") + var/name = null + var/value = null + + if (pos) + name = lowertext(copytext(t, 1, pos)) + value = copytext(t, pos + 1) + else + name = lowertext(t) + + if (!name) + continue + + switch (name) + if ("address") + forumsqladdress = value + if ("port") + forumsqlport = value + if ("database") + forumsqldb = value + if ("login") + forumsqllogin = value + if ("password") + forumsqlpass = value + if ("activatedgroup") + forum_activated_group = value + if ("authenticatedgroup") + forum_authenticated_group = value + else + diary << "Unknown setting in configuration: '[name]'" + +/datum/configuration/proc/pick_mode(mode_name) + // I wish I didn't have to instance the game modes in order to look up + // their information, but it is the only way (at least that I know of). + for (var/T in (typesof(/datum/game_mode) - /datum/game_mode)) + var/datum/game_mode/M = new T() + if (M.config_tag && M.config_tag == mode_name) + return M + del(M) + return new /datum/game_mode/extended() + +/datum/configuration/proc/get_runnable_modes() + var/list/datum/game_mode/runnable_modes = new + for (var/T in (typesof(/datum/game_mode) - /datum/game_mode)) + var/datum/game_mode/M = new T() // to_chat(world, "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]") - if (!(M.config_tag in modes)) - del(M) - continue - if (probabilities[M.config_tag]<=0) - del(M) - continue - if (M.can_start()) - runnable_modes[M] = probabilities[M.config_tag] + if (!(M.config_tag in modes)) + del(M) + continue + if (probabilities[M.config_tag]<=0) + del(M) + continue + if (M.can_start()) + runnable_modes[M] = probabilities[M.config_tag] // to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]") - return runnable_modes + return runnable_modes diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index bc405f404d9..707046ee39f 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -1,61 +1,61 @@ -var/global/datum/controller/failsafe/failsafe - -/datum/controller/failsafe // This thing pretty much just keeps poking the controllers. - processing_interval = 100 // Poke the controllers every 10 seconds. - - /* - * Controller alert level. - * For every poke that fails this is raised by 1. - * When it reaches 5 the MC is replaced with a new one - * (effectively killing any controller process() and starting a new one). - */ - - // master - var/masterControllerIteration = 0 - var/masterControllerAlertLevel = 0 - - // lighting - var/lightingControllerIteration = 0 - var/lightingControllerAlertLevel = 0 - -/datum/controller/failsafe/New() - . = ..() - - // There can be only one failsafe. Out with the old in with the new (that way we can restart the Failsafe by spawning a new one). - if (failsafe != src) - if (istype(failsafe)) - recover() - qdel(failsafe) - - failsafe = src - - failsafe.process() - -/datum/controller/failsafe/proc/process() - processing = 1 - - spawn(0) - set background = BACKGROUND_ENABLED - - while(1) // More efficient than recursivly calling ourself over and over. background = 1 ensures we do not trigger an infinite loop. - iteration++ - - if(processing) - if(master_controller.processing) // Only poke if these overrides aren't in effect - if(masterControllerIteration == master_controller.iteration) // Master controller hasn't finished processing in the defined interval. - switch(masterControllerAlertLevel) - if(0 to 3) - masterControllerAlertLevel++ - if(4) +var/global/datum/controller/failsafe/failsafe + +/datum/controller/failsafe // This thing pretty much just keeps poking the controllers. + processing_interval = 100 // Poke the controllers every 10 seconds. + + /* + * Controller alert level. + * For every poke that fails this is raised by 1. + * When it reaches 5 the MC is replaced with a new one + * (effectively killing any controller process() and starting a new one). + */ + + // master + var/masterControllerIteration = 0 + var/masterControllerAlertLevel = 0 + + // lighting + var/lightingControllerIteration = 0 + var/lightingControllerAlertLevel = 0 + +/datum/controller/failsafe/New() + . = ..() + + // There can be only one failsafe. Out with the old in with the new (that way we can restart the Failsafe by spawning a new one). + if (failsafe != src) + if (istype(failsafe)) + recover() + qdel(failsafe) + + failsafe = src + + failsafe.process() + +/datum/controller/failsafe/proc/process() + processing = 1 + + spawn(0) + set background = BACKGROUND_ENABLED + + while(1) // More efficient than recursivly calling ourself over and over. background = 1 ensures we do not trigger an infinite loop. + iteration++ + + if(processing) + if(master_controller.processing) // Only poke if these overrides aren't in effect + if(masterControllerIteration == master_controller.iteration) // Master controller hasn't finished processing in the defined interval. + switch(masterControllerAlertLevel) + if(0 to 3) + masterControllerAlertLevel++ + if(4) to_chat(admins, "Warning. The master Controller has not fired in the last [masterControllerAlertLevel * processing_interval] ticks. Automatic restart in [processing_interval] ticks.") - masterControllerAlertLevel = 5 - if(5) + masterControllerAlertLevel = 5 + if(5) to_chat(admins, "Warning. The master Controller has still not fired within the last [masterControllerAlertLevel * processing_interval] ticks. Killing and restarting...") - new /datum/controller/game_controller() // Replace the old master controller (hence killing the old one's process). - master_controller.process() // Start it rolling again. - masterControllerAlertLevel = 0 - else - masterControllerAlertLevel = 0 - masterControllerIteration = master_controller.iteration - - sleep(processing_interval) + new /datum/controller/game_controller() // Replace the old master controller (hence killing the old one's process). + master_controller.process() // Start it rolling again. + masterControllerAlertLevel = 0 + else + masterControllerAlertLevel = 0 + masterControllerIteration = master_controller.iteration + + sleep(processing_interval) diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 9eee2bbfd39..08d54ef64bf 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -1,476 +1,476 @@ -//simplified MC that is designed to fail when procs 'break'. When it fails it's just replaced with a new one. -//It ensures master_controller.process() is never doubled up by killing the MC (hence terminating any of its sleeping procs) -//WIP, needs lots of work still - -var/global/datum/controller/game_controller/master_controller //Set in world.New() - -var/global/last_tick_duration = 0 - -var/global/air_processing_killed = 0 -var/global/pipe_processing_killed = 0 - -#ifdef PROFILE_MACHINES -// /type = time this tick -var/list/machine_profiling=list() -#endif - -/datum/controller/game_controller - var/breather_ticks = 2 //a somewhat crude attempt to iron over the 'bumps' caused by high-cpu use by letting the MC have a breather for this many ticks after every loop - var/minimum_ticks = 20 //The minimum length of time between MC ticks - - var/air_cost = 0 - var/sun_cost = 0 - var/mobs_cost = 0 - var/diseases_cost = 0 - var/machines_cost = 0 - var/objects_cost = 0 - var/networks_cost = 0 - var/powernets_cost = 0 - var/nano_cost = 0 - var/events_cost = 0 - var/ticker_cost = 0 - var/garbageCollectorCost = 0 - var/total_cost = 0 - - var/last_thing_processed - var/mob/list/expensive_mobs = list() - var/rebuild_active_areas = 0 - - var/initialized = 0 // Everything initialized? (Delays game start timer until shit is actually loaded) - - var/global/datum/garbage_collector/garbageCollector - -datum/controller/game_controller/New() - . = ..() - - // There can be only one master_controller. Out with the old and in with the new. - if (master_controller != src) - log_debug("Rebuilding Master Controller") - - if (istype(master_controller)) - recover() - qdel(master_controller) - - master_controller = src - - var/watch=0 - if (isnull(job_master)) - watch = start_watch() - job_master = new /datum/controller/occupations() - job_master.SetupOccupations() - job_master.LoadJobs("config/jobs.txt") -// to_chat(world, "Job setup complete in ") - log_startup_progress("Job setup complete in [stop_watch(watch)]s.") - - if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase() - if(!syndicate_code_response) syndicate_code_response = generate_code_phrase() - /*if(!emergency_shuttle) emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()*/ -/* - if(global.garbageCollector) - garbageCollector = global.garbageCollector -*/ -datum/controller/game_controller/proc/setup() - world.tick_lag = config.Ticklag - - // notify the other process that we started up - socket_talk = new /datum/socket_talk() - socket_talk.send_raw("type=startup") - - createRandomZlevel() -/* - if(!air_master) - air_master = new /datum/controller/air_system() - air_master.Setup() - - if(!ticker) - ticker = new /datum/controller/gameticker() - - if(!global.garbageCollector) - global.garbageCollector = new - garbageCollector = global.garbageCollector -*/ - setup_objects() // Most log_startup spam happens here - setupgenetics() - setupfactions() - setup_economy() - SetupXenoarch() - var/watch=start_watch() - log_startup_progress("Caching damage icons...") - cachedamageicons() - log_startup_progress(" Finished caching damage icons in [stop_watch(watch)]s.") - - buildcamlist() - - watch=start_watch() - log_startup_progress("Caching jukebox playlists...") - load_juke_playlists() - log_startup_progress(" Finished caching jukebox playlists in [stop_watch(watch)]s.") - //if(map && map.dorf) - //mining_surprises = typesof(/mining_surprise/dorf) - /mining_surprise/dorf - //max_secret_rooms += 2 - for(var/i=0, i 5) - to_chat(world, "RUNTIMES IN ATMOS TICKER. Killing air simulation!") - world.log << "### ZAS SHUTDOWN" - message_admins("ZASALERT: unable to run [air_master.tick_progress], shutting down!") - log_admin("ZASALERT: unable run zone/process() -- [air_master.tick_progress]") - air_processing_killed = 1 - air_master.failed_ticks = 0 - - air_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //SUN - timer = world.timeofday - last_thing_processed = sun.type - sun.calc_position() - sun_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //MOBS - timer = world.timeofday - processMobs() - mobs_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //DISEASES - timer = world.timeofday - processDiseases() - diseases_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //MACHINES - timer = world.timeofday - processMachines() - machines_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //OBJECTS - timer = world.timeofday - processObjects() - objects_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //PIPENETS - if(!pipe_processing_killed) - timer = world.timeofday - processPipenets() - networks_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //POWERNETS - timer = world.timeofday - processPowernets() - powernets_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //NANO UIS - timer = world.timeofday - processNano() - nano_cost = (world.timeofday - timer) / 10 - - sleep(breather_ticks) - - //EVENTS - timer = world.timeofday - processEvents() - events_cost = (world.timeofday - timer) / 10 - - //TICKER - timer = world.timeofday - last_thing_processed = ticker.type - ticker.process() - ticker_cost = (world.timeofday - timer) / 10 - - timer = world.timeofday - last_thing_processed = garbageCollector.type - garbageCollector.process() - garbageCollectorCost = (world.timeofday - timer) / 10 - - //TIMING - total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + objects_cost + networks_cost + powernets_cost + nano_cost + events_cost + ticker_cost + garbageCollectorCost - - var/end_time = world.timeofday - if(end_time < start_time) - start_time -= 864000 //deciseconds in a day - sleep( round(minimum_ticks - (end_time - start_time),1) ) - else - sleep(10) - -datum/controller/game_controller/proc/processMobs() - var/i = 1 - expensive_mobs.len = 0 - while(i<=mob_list.len) - var/mob/M = mob_list[i] - if(M) - var/clock = world.timeofday - last_thing_processed = M.type - M.Life() - if((world.timeofday - clock) > 1) - expensive_mobs += M - i++ - continue - if(!mob_list.Remove(null)) - mob_list.Cut(i,i+1) - -/datum/controller/game_controller/proc/processDiseases() - for (var/datum/disease/Disease in active_diseases) - if(Disease) - last_thing_processed = Disease.type - Disease.process() - continue - - active_diseases -= Disease - -/datum/controller/game_controller/proc/processMachines() - #ifdef PROFILE_MACHINES - machine_profiling.len = 0 - #endif - - for (var/obj/machinery/Machinery in machines) - if (Machinery && Machinery.loc) - last_thing_processed = Machinery.type - - #ifdef PROFILE_MACHINES - var/start = world.timeofday - #endif - - if(PROCESS_KILL == Machinery.process()) - Machinery.inMachineList = 0 - machines.Remove(Machinery) - continue - - if (Machinery && Machinery.use_power) - Machinery.auto_use_power() - - #ifdef PROFILE_MACHINES - var/end = world.timeofday - - if (!(Machinery.type in machine_profiling)) - machine_profiling[Machinery.type] = 0 - - machine_profiling[Machinery.type] += (end - start) - #endif - - -/datum/controller/game_controller/proc/processObjects() - for (var/obj/Object in processing_objects) - if (Object && Object.loc) - last_thing_processed = Object.type - Object.process() - continue - - processing_objects -= Object - - // Hack. - for (var/turf/unsimulated/wall/supermatter/SM in processing_objects) - if (SM) - last_thing_processed = SM.type - SM.process() - continue - - processing_objects -= SM - -/datum/controller/game_controller/proc/processPipenets() - last_thing_processed = /datum/pipe_network - - for (var/datum/pipe_network/Pipe_Network in pipe_networks) - if(Pipe_Network) - Pipe_Network.process() - continue - - pipe_networks -= Pipe_Network - -/datum/controller/game_controller/proc/processPowernets() - last_thing_processed = /datum/powernet - - for (var/datum/powernet/Powernet in powernets) - if (Powernet) - Powernet.reset() - continue - - powernets -= Powernet - -/datum/controller/game_controller/proc/processNano() - for (var/datum/nanoui/Nanoui in nanomanager.processing_uis) - if (Nanoui) - Nanoui.process() - continue - - nanomanager.processing_uis -= Nanoui - -/datum/controller/game_controller/proc/processEvents() - last_thing_processed = /datum/event - - for (var/datum/event/Event in events) - if (Event) - Event.process() - continue - - events -= Event - - checkEvent() - -datum/controller/game_controller/recover() //Mostly a placeholder for now. - . = ..() - var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n" - for(var/varname in master_controller.vars) - switch(varname) - if("tag","type","parent_type","vars") continue - else - var/varval = master_controller.vars[varname] - if(istype(varval,/datum)) - var/datum/D = varval - msg += "\t [varname] = [D.type]\n" - else - msg += "\t [varname] = [varval]\n" - world.log << msg - +//simplified MC that is designed to fail when procs 'break'. When it fails it's just replaced with a new one. +//It ensures master_controller.process() is never doubled up by killing the MC (hence terminating any of its sleeping procs) +//WIP, needs lots of work still + +var/global/datum/controller/game_controller/master_controller //Set in world.New() + +var/global/last_tick_duration = 0 + +var/global/air_processing_killed = 0 +var/global/pipe_processing_killed = 0 + +#ifdef PROFILE_MACHINES +// /type = time this tick +var/list/machine_profiling=list() +#endif + +/datum/controller/game_controller + var/breather_ticks = 2 //a somewhat crude attempt to iron over the 'bumps' caused by high-cpu use by letting the MC have a breather for this many ticks after every loop + var/minimum_ticks = 20 //The minimum length of time between MC ticks + + var/air_cost = 0 + var/sun_cost = 0 + var/mobs_cost = 0 + var/diseases_cost = 0 + var/machines_cost = 0 + var/objects_cost = 0 + var/networks_cost = 0 + var/powernets_cost = 0 + var/nano_cost = 0 + var/events_cost = 0 + var/ticker_cost = 0 + var/garbageCollectorCost = 0 + var/total_cost = 0 + + var/last_thing_processed + var/mob/list/expensive_mobs = list() + var/rebuild_active_areas = 0 + + var/initialized = 0 // Everything initialized? (Delays game start timer until shit is actually loaded) + + var/global/datum/garbage_collector/garbageCollector + +datum/controller/game_controller/New() + . = ..() + + // There can be only one master_controller. Out with the old and in with the new. + if (master_controller != src) + log_debug("Rebuilding Master Controller") + + if (istype(master_controller)) + recover() + qdel(master_controller) + + master_controller = src + + var/watch=0 + if (isnull(job_master)) + watch = start_watch() + job_master = new /datum/controller/occupations() + job_master.SetupOccupations() + job_master.LoadJobs("config/jobs.txt") +// to_chat(world, "Job setup complete in ") + log_startup_progress("Job setup complete in [stop_watch(watch)]s.") + + if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase() + if(!syndicate_code_response) syndicate_code_response = generate_code_phrase() + /*if(!emergency_shuttle) emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()*/ +/* + if(global.garbageCollector) + garbageCollector = global.garbageCollector +*/ +datum/controller/game_controller/proc/setup() + world.tick_lag = config.Ticklag + + // notify the other process that we started up + socket_talk = new /datum/socket_talk() + socket_talk.send_raw("type=startup") + + createRandomZlevel() +/* + if(!air_master) + air_master = new /datum/controller/air_system() + air_master.Setup() + + if(!ticker) + ticker = new /datum/controller/gameticker() + + if(!global.garbageCollector) + global.garbageCollector = new + garbageCollector = global.garbageCollector +*/ + setup_objects() // Most log_startup spam happens here + setupgenetics() + setupfactions() + setup_economy() + SetupXenoarch() + var/watch=start_watch() + log_startup_progress("Caching damage icons...") + cachedamageicons() + log_startup_progress(" Finished caching damage icons in [stop_watch(watch)]s.") + + buildcamlist() + + watch=start_watch() + log_startup_progress("Caching jukebox playlists...") + load_juke_playlists() + log_startup_progress(" Finished caching jukebox playlists in [stop_watch(watch)]s.") + //if(map && map.dorf) + //mining_surprises = typesof(/mining_surprise/dorf) - /mining_surprise/dorf + //max_secret_rooms += 2 + for(var/i=0, i 5) + to_chat(world, "RUNTIMES IN ATMOS TICKER. Killing air simulation!") + world.log << "### ZAS SHUTDOWN" + message_admins("ZASALERT: unable to run [air_master.tick_progress], shutting down!") + log_admin("ZASALERT: unable run zone/process() -- [air_master.tick_progress]") + air_processing_killed = 1 + air_master.failed_ticks = 0 + + air_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //SUN + timer = world.timeofday + last_thing_processed = sun.type + sun.calc_position() + sun_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //MOBS + timer = world.timeofday + processMobs() + mobs_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //DISEASES + timer = world.timeofday + processDiseases() + diseases_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //MACHINES + timer = world.timeofday + processMachines() + machines_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //OBJECTS + timer = world.timeofday + processObjects() + objects_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //PIPENETS + if(!pipe_processing_killed) + timer = world.timeofday + processPipenets() + networks_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //POWERNETS + timer = world.timeofday + processPowernets() + powernets_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //NANO UIS + timer = world.timeofday + processNano() + nano_cost = (world.timeofday - timer) / 10 + + sleep(breather_ticks) + + //EVENTS + timer = world.timeofday + processEvents() + events_cost = (world.timeofday - timer) / 10 + + //TICKER + timer = world.timeofday + last_thing_processed = ticker.type + ticker.process() + ticker_cost = (world.timeofday - timer) / 10 + + timer = world.timeofday + last_thing_processed = garbageCollector.type + garbageCollector.process() + garbageCollectorCost = (world.timeofday - timer) / 10 + + //TIMING + total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + objects_cost + networks_cost + powernets_cost + nano_cost + events_cost + ticker_cost + garbageCollectorCost + + var/end_time = world.timeofday + if(end_time < start_time) + start_time -= 864000 //deciseconds in a day + sleep( round(minimum_ticks - (end_time - start_time),1) ) + else + sleep(10) + +datum/controller/game_controller/proc/processMobs() + var/i = 1 + expensive_mobs.len = 0 + while(i<=mob_list.len) + var/mob/M = mob_list[i] + if(M) + var/clock = world.timeofday + last_thing_processed = M.type + M.Life() + if((world.timeofday - clock) > 1) + expensive_mobs += M + i++ + continue + if(!mob_list.Remove(null)) + mob_list.Cut(i,i+1) + +/datum/controller/game_controller/proc/processDiseases() + for (var/datum/disease/Disease in active_diseases) + if(Disease) + last_thing_processed = Disease.type + Disease.process() + continue + + active_diseases -= Disease + +/datum/controller/game_controller/proc/processMachines() + #ifdef PROFILE_MACHINES + machine_profiling.len = 0 + #endif + + for (var/obj/machinery/Machinery in machines) + if (Machinery && Machinery.loc) + last_thing_processed = Machinery.type + + #ifdef PROFILE_MACHINES + var/start = world.timeofday + #endif + + if(PROCESS_KILL == Machinery.process()) + Machinery.inMachineList = 0 + machines.Remove(Machinery) + continue + + if (Machinery && Machinery.use_power) + Machinery.auto_use_power() + + #ifdef PROFILE_MACHINES + var/end = world.timeofday + + if (!(Machinery.type in machine_profiling)) + machine_profiling[Machinery.type] = 0 + + machine_profiling[Machinery.type] += (end - start) + #endif + + +/datum/controller/game_controller/proc/processObjects() + for (var/obj/Object in processing_objects) + if (Object && Object.loc) + last_thing_processed = Object.type + Object.process() + continue + + processing_objects -= Object + + // Hack. + for (var/turf/unsimulated/wall/supermatter/SM in processing_objects) + if (SM) + last_thing_processed = SM.type + SM.process() + continue + + processing_objects -= SM + +/datum/controller/game_controller/proc/processPipenets() + last_thing_processed = /datum/pipe_network + + for (var/datum/pipe_network/Pipe_Network in pipe_networks) + if(Pipe_Network) + Pipe_Network.process() + continue + + pipe_networks -= Pipe_Network + +/datum/controller/game_controller/proc/processPowernets() + last_thing_processed = /datum/powernet + + for (var/datum/powernet/Powernet in powernets) + if (Powernet) + Powernet.reset() + continue + + powernets -= Powernet + +/datum/controller/game_controller/proc/processNano() + for (var/datum/nanoui/Nanoui in nanomanager.processing_uis) + if (Nanoui) + Nanoui.process() + continue + + nanomanager.processing_uis -= Nanoui + +/datum/controller/game_controller/proc/processEvents() + last_thing_processed = /datum/event + + for (var/datum/event/Event in events) + if (Event) + Event.process() + continue + + events -= Event + + checkEvent() + +datum/controller/game_controller/recover() //Mostly a placeholder for now. + . = ..() + var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n" + for(var/varname in master_controller.vars) + switch(varname) + if("tag","type","parent_type","vars") continue + else + var/varval = master_controller.vars[varname] + if(istype(varval,/datum)) + var/datum/D = varval + msg += "\t [varname] = [D.type]\n" + else + msg += "\t [varname] = [varval]\n" + world.log << msg + diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 52ad8095dbb..bf287388598 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -1,357 +1,357 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -// Controls the emergency shuttle - - -// these define the time taken for the shuttle to get to SS13 -// and the time before it leaves again -#define SHUTTLEARRIVETIME 600 // 10 minutes = 600 seconds -#define SHUTTLELEAVETIME 180 // 3 minutes = 180 seconds -#define SHUTTLETRANSITTIME 120 // 2 minutes = 120 seconds - -var/global/datum/shuttle_controller/emergency_shuttle/emergency_shuttle - -datum/shuttle_controller - var/alert = 0 //0 = emergency, 1 = crew cycle - - var/location = 0 //0 = somewhere far away (in spess), 1 = at SS13, 2 = returned from SS13 - var/online = 0 - var/direction = 1 //-1 = going back to central command, 1 = going to SS13, 2 = in transit to centcom (not recalled) - - var/endtime // timeofday that shuttle arrives - var/timelimit //important when the shuttle gets called for more than shuttlearrivetime - //timeleft = 360 //600 - var/fake_recall = 0 //Used in rounds to prevent "ON NOES, IT MUST [INSERT ROUND] BECAUSE SHUTTLE CAN'T BE CALLED" - - var/always_fake_recall = 0 - var/deny_shuttle = 0 //for admins not allowing it to be called. - var/departed = 0 - - var/shutdown = 0 // Completely shut down. - - var/can_recall = 1 - - var/datum/shuttle/shuttle - - // call the shuttle - // if not called before, set the endtime to T+600 seconds - // otherwise if outgoing, switch to incoming - -datum/shuttle_controller/proc/incall(coeff = 1) - if(shutdown) return - if((!universe.OnShuttleCall(null) || deny_shuttle) && alert == 1) //crew transfer shuttle does not gets recalled by gamemode - return - if(endtime) - if(direction == -1) - setdirection(1) - else - settimeleft(SHUTTLEARRIVETIME*coeff) - online = 1 - if(always_fake_recall) - fake_recall = rand(300,500) - //turning on the red lights in hallways - if(alert == 0) - for(var/area/A in areas) - if(istype(A, /area/hallway)) - A.readyalert() - -datum/shuttle_controller/proc/shuttlealert(var/X) - if(shutdown) return - alert = X - - -datum/shuttle_controller/proc/force_shutdown() - online=0 - shutdown=1 - - - -datum/shuttle_controller/proc/recall() - if(shutdown) return - if(!can_recall) return - if(direction == 1) - var/timeleft = timeleft() - if(alert == 0) - if(timeleft >= 600) - return - captain_announce("The emergency shuttle has been recalled.") - to_chat(world, sound('sound/AI/shuttlerecalled.ogg')) - setdirection(-1) - online = 1 - for(var/area/A in areas) - if(istype(A, /area/hallway)) - A.readyreset() - return - else //makes it possible to send shuttle back. - captain_announce("The shuttle has been recalled.") - setdirection(-1) - online = 1 - return - -// returns the time (in seconds) before shuttle arrival -// note if direction = -1, gives a count-up to SHUTTLEARRIVETIME -datum/shuttle_controller/proc/timeleft() - - - if(online) - var/timeleft = round((endtime - world.timeofday)/10 ,1) - if(direction == 1 || direction == 2) - return timeleft - else - return SHUTTLEARRIVETIME-timeleft - else - return SHUTTLEARRIVETIME - -// sets the time left to a given delay (in seconds) -datum/shuttle_controller/proc/settimeleft(var/delay) - endtime = world.timeofday + delay * 10 - timelimit = delay - -// sets the shuttle direction -// 1 = towards SS13, -1 = back to centcom -datum/shuttle_controller/proc/setdirection(var/dirn) - if(direction == dirn) - return - direction = dirn - // if changing direction, flip the timeleft by SHUTTLEARRIVETIME - var/ticksleft = endtime - world.timeofday - endtime = world.timeofday + (SHUTTLEARRIVETIME*10 - ticksleft) - return - -datum/shuttle_controller/proc/process() - -datum/shuttle_controller/proc/move_pod(var/start_type,var/end_type,var/direction,var/open_doors) - var/area/start_location=locate(start_type) - var/area/end_location=locate(end_type) - - start_location.move_contents_to(end_location, null, direction) - - for(var/obj/machinery/door/D in all_doors) - if( get_area(D) == end_location ) - spawn(0) - if(open_doors) - D.open() - else - D.close() - - for(var/mob/M in end_location) - if(M.client) - spawn() - if(M.locked_to) - shake_camera(M, 4, 1) // locked_to, not a lot of shaking - else - shake_camera(M, 10, 2) // unlocked_to, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.locked_to) - M.Weaken(5) - - -datum/shuttle_controller/emergency_shuttle - -datum/shuttle_controller/emergency_shuttle/force_shutdown() - ..() - if(direction == 2) - location = 1 - - //main shuttle - if(shuttle && istype(shuttle,/datum/shuttle/escape)) - var/datum/shuttle/escape/E = shuttle - E.open_all_doors() - if(!E.move_to_dock(E.dock_station, 0, E.dir)) //Throw everything forward - message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND THE STATION! PANIC PANIC PANIC") - else - message_admins("WARNING: THERE IS NO EMERGENCY SHUTTLE! PANIC") - //move_pod(/area/shuttle/escape/transit,/area/shuttle/escape/station,NORTH,1) - - //pods - move_pod(/area/shuttle/escape_pod1/transit,/area/shuttle/escape_pod1/station, NORTH,1) - move_pod(/area/shuttle/escape_pod2/transit,/area/shuttle/escape_pod2/station, NORTH,1) - move_pod(/area/shuttle/escape_pod3/transit,/area/shuttle/escape_pod3/station, NORTH,1) - move_pod(/area/shuttle/escape_pod5/transit,/area/shuttle/escape_pod5/station, NORTH,1) - - online = 0 - -datum/shuttle_controller/emergency_shuttle/process() - if(!online || shutdown) - return - - var/timeleft = timeleft() - if(timeleft > 1e5) // midnight rollover protection - timeleft = 0 - if(timeleft < 0) // Sanity - timeleft = 0 - switch(location) - if(0) - - /* --- Shuttle is in transit to Central Command from SS13 --- */ - if(direction == 2) - if(timeleft>0) - return 0 - - /* --- Shuttle has arrived at Centrcal Command --- */ - else - // turn off the star spawners - /* - for(var/obj/effect/starspawner/S in world) - S.spawning = 0 - */ - - location = 2 - - //main shuttle - if(shuttle && istype(shuttle,/datum/shuttle/escape)) - var/datum/shuttle/escape/E = shuttle - E.open_all_doors() - if(!E.move_to_dock(E.dock_centcom, 0, E.dir)) //Throw everything forward - message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND CENTCOMM! PANIC PANIC PANIC") - else - message_admins("WARNING: THERE IS NO EMERGENCY SHUTTLE! PANIC") - //move_pod(/area/shuttle/escape/transit,/area/shuttle/escape/centcom,NORTH,1) - - //pods - move_pod(/area/shuttle/escape_pod1/transit,/area/shuttle/escape_pod1/centcom, NORTH,1) - move_pod(/area/shuttle/escape_pod2/transit,/area/shuttle/escape_pod2/centcom, NORTH,1) - move_pod(/area/shuttle/escape_pod3/transit,/area/shuttle/escape_pod3/centcom, NORTH,1) - move_pod(/area/shuttle/escape_pod5/transit,/area/shuttle/escape_pod5/centcom, NORTH,1) - - online = 0 - - return 1 - - /* --- Shuttle has docked centcom after being recalled --- */ - if(timeleft>timelimit) - online = 0 - direction = 1 - endtime = null - - return 0 - - else if((fake_recall != 0) && (timeleft <= fake_recall)) - recall() - fake_recall = 0 - return 0 - - /* --- Shuttle has docked with the station - begin countdown to transit --- */ - else if(timeleft <= 0) - location = 1 - - if(shuttle && istype(shuttle,/datum/shuttle/escape)) - var/datum/shuttle/escape/E = shuttle - E.open_all_doors() - if(!E.move_to_dock(E.dock_station, 0, E.dir)) //Throw everything forward, on chance that there's anybody in the shuttle - message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND THE STATION! PANIC PANIC PANIC") - - settimeleft(SHUTTLELEAVETIME) - send2mainirc("The Emergency Shuttle has docked with the station.") - captain_announce("The Emergency Shuttle has docked with the station. You have [round(timeleft()/60,1)] minutes to board the Emergency Shuttle.") - to_chat(world, sound('sound/AI/shuttledock.ogg')) - - if(universe.name == "Hell Rising") - to_chat(world, "___________________________________________________________________") - to_chat(world, " A vile force of darkness is making its way toward the escape shuttle.") - - return 1 - - if(1) - - // Just before it leaves, close the damn doors! - if(timeleft == 2 || timeleft == 1) - for(var/obj/machinery/door/unpowered/shuttle/D in shuttle.linked_area) - spawn(0) - D.close() - D.locked = 1 - - if(timeleft>0) - return 0 - - /* --- Shuttle leaves the station, enters transit --- */ - else - - // Turn on the star effects - - /* // kinda buggy atm, i'll fix this later - for(var/obj/effect/starspawner/S in world) - if(!S.spawning) - spawn() S.startspawn() - */ - - departed = 1 // It's going! - location = 0 // in deep space - direction = 2 // heading to centcom - - settimeleft(SHUTTLETRANSITTIME) - - // Shuttle Radio - CallHook("EmergencyShuttleDeparture", list()) - - //main shuttle - if(shuttle && istype(shuttle,/datum/shuttle/escape)) - var/datum/shuttle/escape/E = shuttle - E.close_all_doors() - if(!E.move_to_dock(E.transit_port, 0, turn(E.dir,180))) //Throw everything backwards - message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND TRANSIT! PANIC PANIC PANIC") - else - message_admins("WARNING: THERE IS NO EMERGENCY SHUTTLE! PANIC") - //move_pod(/area/shuttle/escape/station,/area/shuttle/escape/transit,NORTH,0) - - //pods - move_pod(/area/shuttle/escape_pod1/station,/area/shuttle/escape_pod1/transit,NORTH,0) - move_pod(/area/shuttle/escape_pod2/station,/area/shuttle/escape_pod2/transit,NORTH,0) - move_pod(/area/shuttle/escape_pod3/station,/area/shuttle/escape_pod3/transit,NORTH,0) - - move_pod(/area/shuttle/escape_pod5/station,/area/shuttle/escape_pod5/transit,EAST,0) - - captain_announce("The Emergency Shuttle has left the station. Estimate [round(timeleft()/60,1)] minutes until the shuttle docks at Central Command.") - - return 1 - - else - return 1 - - -/* - Some slapped-together star effects for maximum spess immershuns. Basically consists of a - spawner, an ender, and bgstar. Spawners create bgstars, bgstars shoot off into a direction - until they reach a starender. -*/ - -/obj/effect/bgstar - name = "star" - var/speed - var/direction = SOUTH - layer = TURF_LAYER - -/obj/effect/bgstar/New() - . = ..() - pixel_x += rand(-2, 30) - pixel_y += rand(-2, 30) - icon_state = "star" + pick("1", "1", "1", "2", "3", "4") - speed = rand(2, 5) - -/obj/effect/bgstar/proc/startmove() - while (src) - sleep(speed) - step(src, direction) - - for (var/obj/effect/starender/E in loc) - qdel(src) - -/obj/effect/starender - invisibility = 101 - -/obj/effect/starspawner - invisibility = 101 - var/spawndir = SOUTH - var/spawning = 0 - - West - spawndir = WEST - - proc/startspawn() - spawning = 1 - while(spawning) - sleep(rand(2, 30)) - var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z)) - S.direction = spawndir - spawn() - S.startmove() +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +// Controls the emergency shuttle + + +// these define the time taken for the shuttle to get to SS13 +// and the time before it leaves again +#define SHUTTLEARRIVETIME 600 // 10 minutes = 600 seconds +#define SHUTTLELEAVETIME 180 // 3 minutes = 180 seconds +#define SHUTTLETRANSITTIME 120 // 2 minutes = 120 seconds + +var/global/datum/shuttle_controller/emergency_shuttle/emergency_shuttle + +datum/shuttle_controller + var/alert = 0 //0 = emergency, 1 = crew cycle + + var/location = 0 //0 = somewhere far away (in spess), 1 = at SS13, 2 = returned from SS13 + var/online = 0 + var/direction = 1 //-1 = going back to central command, 1 = going to SS13, 2 = in transit to centcom (not recalled) + + var/endtime // timeofday that shuttle arrives + var/timelimit //important when the shuttle gets called for more than shuttlearrivetime + //timeleft = 360 //600 + var/fake_recall = 0 //Used in rounds to prevent "ON NOES, IT MUST [INSERT ROUND] BECAUSE SHUTTLE CAN'T BE CALLED" + + var/always_fake_recall = 0 + var/deny_shuttle = 0 //for admins not allowing it to be called. + var/departed = 0 + + var/shutdown = 0 // Completely shut down. + + var/can_recall = 1 + + var/datum/shuttle/shuttle + + // call the shuttle + // if not called before, set the endtime to T+600 seconds + // otherwise if outgoing, switch to incoming + +datum/shuttle_controller/proc/incall(coeff = 1) + if(shutdown) return + if((!universe.OnShuttleCall(null) || deny_shuttle) && alert == 1) //crew transfer shuttle does not gets recalled by gamemode + return + if(endtime) + if(direction == -1) + setdirection(1) + else + settimeleft(SHUTTLEARRIVETIME*coeff) + online = 1 + if(always_fake_recall) + fake_recall = rand(300,500) + //turning on the red lights in hallways + if(alert == 0) + for(var/area/A in areas) + if(istype(A, /area/hallway)) + A.readyalert() + +datum/shuttle_controller/proc/shuttlealert(var/X) + if(shutdown) return + alert = X + + +datum/shuttle_controller/proc/force_shutdown() + online=0 + shutdown=1 + + + +datum/shuttle_controller/proc/recall() + if(shutdown) return + if(!can_recall) return + if(direction == 1) + var/timeleft = timeleft() + if(alert == 0) + if(timeleft >= 600) + return + captain_announce("The emergency shuttle has been recalled.") + to_chat(world, sound('sound/AI/shuttlerecalled.ogg')) + setdirection(-1) + online = 1 + for(var/area/A in areas) + if(istype(A, /area/hallway)) + A.readyreset() + return + else //makes it possible to send shuttle back. + captain_announce("The shuttle has been recalled.") + setdirection(-1) + online = 1 + return + +// returns the time (in seconds) before shuttle arrival +// note if direction = -1, gives a count-up to SHUTTLEARRIVETIME +datum/shuttle_controller/proc/timeleft() + + + if(online) + var/timeleft = round((endtime - world.timeofday)/10 ,1) + if(direction == 1 || direction == 2) + return timeleft + else + return SHUTTLEARRIVETIME-timeleft + else + return SHUTTLEARRIVETIME + +// sets the time left to a given delay (in seconds) +datum/shuttle_controller/proc/settimeleft(var/delay) + endtime = world.timeofday + delay * 10 + timelimit = delay + +// sets the shuttle direction +// 1 = towards SS13, -1 = back to centcom +datum/shuttle_controller/proc/setdirection(var/dirn) + if(direction == dirn) + return + direction = dirn + // if changing direction, flip the timeleft by SHUTTLEARRIVETIME + var/ticksleft = endtime - world.timeofday + endtime = world.timeofday + (SHUTTLEARRIVETIME*10 - ticksleft) + return + +datum/shuttle_controller/proc/process() + +datum/shuttle_controller/proc/move_pod(var/start_type,var/end_type,var/direction,var/open_doors) + var/area/start_location=locate(start_type) + var/area/end_location=locate(end_type) + + start_location.move_contents_to(end_location, null, direction) + + for(var/obj/machinery/door/D in all_doors) + if( get_area(D) == end_location ) + spawn(0) + if(open_doors) + D.open() + else + D.close() + + for(var/mob/M in end_location) + if(M.client) + spawn() + if(M.locked_to) + shake_camera(M, 4, 1) // locked_to, not a lot of shaking + else + shake_camera(M, 10, 2) // unlocked_to, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.locked_to) + M.Weaken(5) + + +datum/shuttle_controller/emergency_shuttle + +datum/shuttle_controller/emergency_shuttle/force_shutdown() + ..() + if(direction == 2) + location = 1 + + //main shuttle + if(shuttle && istype(shuttle,/datum/shuttle/escape)) + var/datum/shuttle/escape/E = shuttle + E.open_all_doors() + if(!E.move_to_dock(E.dock_station, 0, E.dir)) //Throw everything forward + message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND THE STATION! PANIC PANIC PANIC") + else + message_admins("WARNING: THERE IS NO EMERGENCY SHUTTLE! PANIC") + //move_pod(/area/shuttle/escape/transit,/area/shuttle/escape/station,NORTH,1) + + //pods + move_pod(/area/shuttle/escape_pod1/transit,/area/shuttle/escape_pod1/station, NORTH,1) + move_pod(/area/shuttle/escape_pod2/transit,/area/shuttle/escape_pod2/station, NORTH,1) + move_pod(/area/shuttle/escape_pod3/transit,/area/shuttle/escape_pod3/station, NORTH,1) + move_pod(/area/shuttle/escape_pod5/transit,/area/shuttle/escape_pod5/station, NORTH,1) + + online = 0 + +datum/shuttle_controller/emergency_shuttle/process() + if(!online || shutdown) + return + + var/timeleft = timeleft() + if(timeleft > 1e5) // midnight rollover protection + timeleft = 0 + if(timeleft < 0) // Sanity + timeleft = 0 + switch(location) + if(0) + + /* --- Shuttle is in transit to Central Command from SS13 --- */ + if(direction == 2) + if(timeleft>0) + return 0 + + /* --- Shuttle has arrived at Centrcal Command --- */ + else + // turn off the star spawners + /* + for(var/obj/effect/starspawner/S in world) + S.spawning = 0 + */ + + location = 2 + + //main shuttle + if(shuttle && istype(shuttle,/datum/shuttle/escape)) + var/datum/shuttle/escape/E = shuttle + E.open_all_doors() + if(!E.move_to_dock(E.dock_centcom, 0, E.dir)) //Throw everything forward + message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND CENTCOMM! PANIC PANIC PANIC") + else + message_admins("WARNING: THERE IS NO EMERGENCY SHUTTLE! PANIC") + //move_pod(/area/shuttle/escape/transit,/area/shuttle/escape/centcom,NORTH,1) + + //pods + move_pod(/area/shuttle/escape_pod1/transit,/area/shuttle/escape_pod1/centcom, NORTH,1) + move_pod(/area/shuttle/escape_pod2/transit,/area/shuttle/escape_pod2/centcom, NORTH,1) + move_pod(/area/shuttle/escape_pod3/transit,/area/shuttle/escape_pod3/centcom, NORTH,1) + move_pod(/area/shuttle/escape_pod5/transit,/area/shuttle/escape_pod5/centcom, NORTH,1) + + online = 0 + + return 1 + + /* --- Shuttle has docked centcom after being recalled --- */ + if(timeleft>timelimit) + online = 0 + direction = 1 + endtime = null + + return 0 + + else if((fake_recall != 0) && (timeleft <= fake_recall)) + recall() + fake_recall = 0 + return 0 + + /* --- Shuttle has docked with the station - begin countdown to transit --- */ + else if(timeleft <= 0) + location = 1 + + if(shuttle && istype(shuttle,/datum/shuttle/escape)) + var/datum/shuttle/escape/E = shuttle + E.open_all_doors() + if(!E.move_to_dock(E.dock_station, 0, E.dir)) //Throw everything forward, on chance that there's anybody in the shuttle + message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND THE STATION! PANIC PANIC PANIC") + + settimeleft(SHUTTLELEAVETIME) + send2mainirc("The Emergency Shuttle has docked with the station.") + captain_announce("The Emergency Shuttle has docked with the station. You have [round(timeleft()/60,1)] minutes to board the Emergency Shuttle.") + to_chat(world, sound('sound/AI/shuttledock.ogg')) + + if(universe.name == "Hell Rising") + to_chat(world, "___________________________________________________________________") + to_chat(world, " A vile force of darkness is making its way toward the escape shuttle.") + + return 1 + + if(1) + + // Just before it leaves, close the damn doors! + if(timeleft == 2 || timeleft == 1) + for(var/obj/machinery/door/unpowered/shuttle/D in shuttle.linked_area) + spawn(0) + D.close() + D.locked = 1 + + if(timeleft>0) + return 0 + + /* --- Shuttle leaves the station, enters transit --- */ + else + + // Turn on the star effects + + /* // kinda buggy atm, i'll fix this later + for(var/obj/effect/starspawner/S in world) + if(!S.spawning) + spawn() S.startspawn() + */ + + departed = 1 // It's going! + location = 0 // in deep space + direction = 2 // heading to centcom + + settimeleft(SHUTTLETRANSITTIME) + + // Shuttle Radio + CallHook("EmergencyShuttleDeparture", list()) + + //main shuttle + if(shuttle && istype(shuttle,/datum/shuttle/escape)) + var/datum/shuttle/escape/E = shuttle + E.close_all_doors() + if(!E.move_to_dock(E.transit_port, 0, turn(E.dir,180))) //Throw everything backwards + message_admins("WARNING: THE EMERGENCY SHUTTLE FAILED TO FIND TRANSIT! PANIC PANIC PANIC") + else + message_admins("WARNING: THERE IS NO EMERGENCY SHUTTLE! PANIC") + //move_pod(/area/shuttle/escape/station,/area/shuttle/escape/transit,NORTH,0) + + //pods + move_pod(/area/shuttle/escape_pod1/station,/area/shuttle/escape_pod1/transit,NORTH,0) + move_pod(/area/shuttle/escape_pod2/station,/area/shuttle/escape_pod2/transit,NORTH,0) + move_pod(/area/shuttle/escape_pod3/station,/area/shuttle/escape_pod3/transit,NORTH,0) + + move_pod(/area/shuttle/escape_pod5/station,/area/shuttle/escape_pod5/transit,EAST,0) + + captain_announce("The Emergency Shuttle has left the station. Estimate [round(timeleft()/60,1)] minutes until the shuttle docks at Central Command.") + + return 1 + + else + return 1 + + +/* + Some slapped-together star effects for maximum spess immershuns. Basically consists of a + spawner, an ender, and bgstar. Spawners create bgstars, bgstars shoot off into a direction + until they reach a starender. +*/ + +/obj/effect/bgstar + name = "star" + var/speed + var/direction = SOUTH + layer = TURF_LAYER + +/obj/effect/bgstar/New() + . = ..() + pixel_x += rand(-2, 30) + pixel_y += rand(-2, 30) + icon_state = "star" + pick("1", "1", "1", "2", "3", "4") + speed = rand(2, 5) + +/obj/effect/bgstar/proc/startmove() + while (src) + sleep(speed) + step(src, direction) + + for (var/obj/effect/starender/E in loc) + qdel(src) + +/obj/effect/starender + invisibility = 101 + +/obj/effect/starspawner + invisibility = 101 + var/spawndir = SOUTH + var/spawning = 0 + + West + spawndir = WEST + + proc/startspawn() + spawning = 1 + while(spawning) + sleep(rand(2, 30)) + var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z)) + S.direction = spawndir + spawn() + S.startmove() diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index a6ebe7aa6fb..73a9278498f 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -1,93 +1,93 @@ -//TODO: rewrite and standardise all controller datums to the datum/controller type -//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done - -/client/proc/restart_controller(controller in list("Master","Failsafe","Supply Shuttle", "Process Scheduler")) - set category = "Debug" - set name = "Restart Controller" - set desc = "Restart one of the various periodic loop controllers for the game (be careful!)" - - if(!holder) return - usr = null - src = null - switch(controller) - if("Supply Shuttle") - supply_shuttle.process() - feedback_add_details("admin_verb","RSupply") - if("Process Scheduler") - var/datum/controller/processScheduler/psched = new - psched.processes = processScheduler.processes.Copy() - psched.idle = processScheduler.idle.Copy() - psched.idle = processScheduler.idle.Copy() - psched.last_start = processScheduler.last_start.Copy() - psched.last_run_time = processScheduler.last_run_time.Copy() - psched.last_twenty_run_times = processScheduler.last_twenty_run_times.Copy() - psched.highest_run_time = processScheduler.highest_run_time.Copy() - psched.nameToProcessMap = processScheduler.nameToProcessMap.Copy() - psched.last_start = processScheduler.last_start.Copy() - for(var/datum/controller/process/P in psched.processes) - P.main = psched - del(processScheduler) - processScheduler = psched - //processScheduler.deferSetupFor(/datum/controller/process/ticker) - processScheduler.start() +//TODO: rewrite and standardise all controller datums to the datum/controller type +//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done + +/client/proc/restart_controller(controller in list("Master","Failsafe","Supply Shuttle", "Process Scheduler")) + set category = "Debug" + set name = "Restart Controller" + set desc = "Restart one of the various periodic loop controllers for the game (be careful!)" + + if(!holder) return + usr = null + src = null + switch(controller) + if("Supply Shuttle") + supply_shuttle.process() + feedback_add_details("admin_verb","RSupply") + if("Process Scheduler") + var/datum/controller/processScheduler/psched = new + psched.processes = processScheduler.processes.Copy() + psched.idle = processScheduler.idle.Copy() + psched.idle = processScheduler.idle.Copy() + psched.last_start = processScheduler.last_start.Copy() + psched.last_run_time = processScheduler.last_run_time.Copy() + psched.last_twenty_run_times = processScheduler.last_twenty_run_times.Copy() + psched.highest_run_time = processScheduler.highest_run_time.Copy() + psched.nameToProcessMap = processScheduler.nameToProcessMap.Copy() + psched.last_start = processScheduler.last_start.Copy() + for(var/datum/controller/process/P in psched.processes) + P.main = psched + del(processScheduler) + processScheduler = psched + //processScheduler.deferSetupFor(/datum/controller/process/ticker) + processScheduler.start() to_chat(world, "

Process Scheduler was restarted

") - message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.") - return - - -/client/proc/debug_controller(controller in list("Air", "Cameras", "Configuration", "Emergency Shuttle", "failsafe", "Garbage", "Jobs", "master", "pAI", "Radio", "Scheduler", "Sun", "Supply Shuttle", "Ticker", "Vote")) - set category = "Debug" - set name = "debug controller" - set desc = "debug the various periodic loop controllers for the game (be careful!)." - - if (!holder) - return - - switch (controller) - if ("master") - debug_variables(master_controller) - feedback_add_details("admin_verb", "dmaster") - if ("failsafe") - debug_variables(failsafe) - feedback_add_details("admin_verb", "dfailsafe") - if("Ticker") - debug_variables(ticker) - feedback_add_details("admin_verb","DTicker") - if("Air") - debug_variables(air_master) - feedback_add_details("admin_verb","DAir") - if("Jobs") - debug_variables(job_master) - feedback_add_details("admin_verb","DJobs") - if("Sun") - debug_variables(sun) - feedback_add_details("admin_verb","DSun") - if("Radio") - debug_variables(radio_controller) - feedback_add_details("admin_verb","DRadio") - if("Supply Shuttle") - debug_variables(supply_shuttle) - feedback_add_details("admin_verb","DSupply") - if("Emergency Shuttle") - debug_variables(emergency_shuttle) - feedback_add_details("admin_verb","DEmergency") - if("Configuration") - debug_variables(config) - feedback_add_details("admin_verb","DConf") - if("pAI") - debug_variables(paiController) - feedback_add_details("admin_verb","DpAI") - if("Cameras") - debug_variables(cameranet) - feedback_add_details("admin_verb","DCameras") - if("Garbage") - debug_variables(garbageCollector) - feedback_add_details("admin_verb","DGarbage") - if("Scheduler") - debug_variables(processScheduler) - feedback_add_details("admin_verb","DprocessScheduler") - if("Vote") - debug_variables(vote) - feedback_add_details("admin_verb","DprocessVote") - message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") - return + message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.") + return + + +/client/proc/debug_controller(controller in list("Air", "Cameras", "Configuration", "Emergency Shuttle", "failsafe", "Garbage", "Jobs", "master", "pAI", "Radio", "Scheduler", "Sun", "Supply Shuttle", "Ticker", "Vote")) + set category = "Debug" + set name = "debug controller" + set desc = "debug the various periodic loop controllers for the game (be careful!)." + + if (!holder) + return + + switch (controller) + if ("master") + debug_variables(master_controller) + feedback_add_details("admin_verb", "dmaster") + if ("failsafe") + debug_variables(failsafe) + feedback_add_details("admin_verb", "dfailsafe") + if("Ticker") + debug_variables(ticker) + feedback_add_details("admin_verb","DTicker") + if("Air") + debug_variables(air_master) + feedback_add_details("admin_verb","DAir") + if("Jobs") + debug_variables(job_master) + feedback_add_details("admin_verb","DJobs") + if("Sun") + debug_variables(sun) + feedback_add_details("admin_verb","DSun") + if("Radio") + debug_variables(radio_controller) + feedback_add_details("admin_verb","DRadio") + if("Supply Shuttle") + debug_variables(supply_shuttle) + feedback_add_details("admin_verb","DSupply") + if("Emergency Shuttle") + debug_variables(emergency_shuttle) + feedback_add_details("admin_verb","DEmergency") + if("Configuration") + debug_variables(config) + feedback_add_details("admin_verb","DConf") + if("pAI") + debug_variables(paiController) + feedback_add_details("admin_verb","DpAI") + if("Cameras") + debug_variables(cameranet) + feedback_add_details("admin_verb","DCameras") + if("Garbage") + debug_variables(garbageCollector) + feedback_add_details("admin_verb","DGarbage") + if("Scheduler") + debug_variables(processScheduler) + feedback_add_details("admin_verb","DprocessScheduler") + if("Vote") + debug_variables(vote) + feedback_add_details("admin_verb","DprocessVote") + message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") + return diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 9dddbb8ce24..339d231793e 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -1,379 +1,379 @@ -var/global/randomize_laws = 0 // Not right now - N3X -var/global/base_law_type = /datum/ai_laws/asimov //Deinitialize this variable by commenting out Asimov as the base_law_type to activate AI lawset randomization -var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck on MoMMIs. - N3X - -//Create proc for determining the lawset of the first silicon -//So long as base_law_type is declared, but uninitialized, the first silicon created in a round will randomly select a base_law_type based upon the below proc -//All silicons created during the round will start with the randomized base_law_type -//Weights are currently set to 40% Asimov, 20% Corporate, 20% NT Default, 10% Robocop, 10% Paladin -//Add, comment out, or adjust weights to modify law selection -//So long as the weights come to a sum of 100 total, they will be equal parts of 100% -/proc/getLawset(var/mob/M) - if(!base_law_type) base_law_type = pick( - 40;/datum/ai_laws/asimov, - 20;/datum/ai_laws/corporate, - 20;/datum/ai_laws/nanotrasen, - 10;/datum/ai_laws/robocop, - 10;/datum/ai_laws/paladin - ) - return (new base_law_type) //Return the chosen lawset - -// Used for the refactored law modules. -#define LAW_IONIC -2 -#define LAW_INHERENT -1 -#define LAW_ZERO 0 - -/datum/ai_laws - var/name = "Unknown Laws" - var/randomly_selectable = 0 - // Zeroth laws - var/zeroth = null - var/zeroth_borg = null // wotm8 - var/list/inherent = list() - var/list/supplied = list() - var/list/ion = list() - - // Used in planning frames. - var/inherent_cleared = 0 - -/* General ai_law functions */ - -/datum/ai_laws/proc/set_zeroth_law(var/law, var/law_borg = null) - src.zeroth = law - if(law_borg) //Making it possible for slaved borgs to see a different law 0 than their AI. --NEO - src.zeroth_borg = law_borg - -/datum/ai_laws/proc/add_inherent_law(var/law) - if (!(law in src.inherent)) - src.inherent += law - -/datum/ai_laws/proc/add_ion_law(var/law) - src.ion += law - -/datum/ai_laws/proc/clear_inherent_laws() - del(src.inherent) - src.inherent = list() - inherent_cleared = 1 - -/datum/ai_laws/proc/add_supplied_law(var/number, var/law) - while (src.supplied.len < number + 1) - src.supplied += "" - - src.supplied[number + 1] = law - -/datum/ai_laws/proc/clear_supplied_laws() - src.supplied = list() - -/datum/ai_laws/proc/clear_ion_laws() - src.ion = list() - -/datum/ai_laws/proc/show_laws(var/who) - - - if (src.zeroth) +var/global/randomize_laws = 0 // Not right now - N3X +var/global/base_law_type = /datum/ai_laws/asimov //Deinitialize this variable by commenting out Asimov as the base_law_type to activate AI lawset randomization +var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck on MoMMIs. - N3X + +//Create proc for determining the lawset of the first silicon +//So long as base_law_type is declared, but uninitialized, the first silicon created in a round will randomly select a base_law_type based upon the below proc +//All silicons created during the round will start with the randomized base_law_type +//Weights are currently set to 40% Asimov, 20% Corporate, 20% NT Default, 10% Robocop, 10% Paladin +//Add, comment out, or adjust weights to modify law selection +//So long as the weights come to a sum of 100 total, they will be equal parts of 100% +/proc/getLawset(var/mob/M) + if(!base_law_type) base_law_type = pick( + 40;/datum/ai_laws/asimov, + 20;/datum/ai_laws/corporate, + 20;/datum/ai_laws/nanotrasen, + 10;/datum/ai_laws/robocop, + 10;/datum/ai_laws/paladin + ) + return (new base_law_type) //Return the chosen lawset + +// Used for the refactored law modules. +#define LAW_IONIC -2 +#define LAW_INHERENT -1 +#define LAW_ZERO 0 + +/datum/ai_laws + var/name = "Unknown Laws" + var/randomly_selectable = 0 + // Zeroth laws + var/zeroth = null + var/zeroth_borg = null // wotm8 + var/list/inherent = list() + var/list/supplied = list() + var/list/ion = list() + + // Used in planning frames. + var/inherent_cleared = 0 + +/* General ai_law functions */ + +/datum/ai_laws/proc/set_zeroth_law(var/law, var/law_borg = null) + src.zeroth = law + if(law_borg) //Making it possible for slaved borgs to see a different law 0 than their AI. --NEO + src.zeroth_borg = law_borg + +/datum/ai_laws/proc/add_inherent_law(var/law) + if (!(law in src.inherent)) + src.inherent += law + +/datum/ai_laws/proc/add_ion_law(var/law) + src.ion += law + +/datum/ai_laws/proc/clear_inherent_laws() + del(src.inherent) + src.inherent = list() + inherent_cleared = 1 + +/datum/ai_laws/proc/add_supplied_law(var/number, var/law) + while (src.supplied.len < number + 1) + src.supplied += "" + + src.supplied[number + 1] = law + +/datum/ai_laws/proc/clear_supplied_laws() + src.supplied = list() + +/datum/ai_laws/proc/clear_ion_laws() + src.ion = list() + +/datum/ai_laws/proc/show_laws(var/who) + + + if (src.zeroth) to_chat(who, "0. [src.zeroth]") - - for (var/index = 1, index <= src.ion.len, index++) - var/law = src.ion[index] - var/num = ionnum() + + for (var/index = 1, index <= src.ion.len, index++) + var/law = src.ion[index] + var/num = ionnum() to_chat(who, "[num]. [law]") - - var/number = 1 - for (var/index = 1, index <= src.inherent.len, index++) - var/law = src.inherent[index] - - if (length(law) > 0) + + var/number = 1 + for (var/index = 1, index <= src.inherent.len, index++) + var/law = src.inherent[index] + + if (length(law) > 0) to_chat(who, "[number]. [law]") - number++ - - for (var/index = 1, index <= src.supplied.len, index++) - var/law = src.supplied[index] - if (length(law) > 0) + number++ + + for (var/index = 1, index <= src.supplied.len, index++) + var/law = src.supplied[index] + if (length(law) > 0) to_chat(who, "[number]. [law]") - number++ - -/datum/ai_laws/proc/write_laws() - var/text = "" - if (src.zeroth) - text += "0. [src.zeroth]" - - for (var/index = 1, index <= src.ion.len, index++) - var/law = src.ion[index] - var/num = ionnum() - text += "
[num]. [law]" - - var/number = 1 - for (var/index = 1, index <= src.inherent.len, index++) - var/law = src.inherent[index] - - if (length(law) > 0) - text += "
[number]. [law]" - number++ - - for (var/index = 1, index <= src.supplied.len, index++) - var/law = src.supplied[index] - if (length(law) > 0) - text += "
[number]. [law]" - number++ - return text - -/datum/ai_laws/proc/adminLink(var/mob/living/silicon/S,var/law_type,var/index,var/label) - return "[label] (Remove)" - -/datum/ai_laws/Topic(href,href_list) - if(!usr.client || !usr.client.holder) - return - if("rm_law" in href_list) - var/lawtype = text2num(href_list["rm_law"]) - var/index=text2num(href_list["index"]) - var/mob/living/silicon/S=locate(href_list["mob"]) - - - var/oldlaw = get_law(lawtype,index) - - rm_law(lawtype,index) - - var/lawtype_str="law #[index]" - switch(lawtype) - if(LAW_ZERO) - lawtype_str = "law zero" - if(LAW_IONIC) - lawtype_str = "ionic law #[index]" - if(LAW_INHERENT) - lawtype_str = "core law #[index]" - log_admin("[key_name(usr)] has removed [lawtype_str] on [key_name(S)]: \"[oldlaw]\"") - message_admins("[usr.key] removed [lawtype_str] on [key_name(S)]: \"[oldlaw]\"") - lawchanges.Add("[key_name(usr)] has removed [lawtype_str] on [key_name(S)]: \"[oldlaw]\"") - usr.client.holder.show_player_panel(S) - - return 1 - - if("set_law" in href_list) - var/lawtype=text2num(href_list["set_law"]) - var/index=text2num(href_list["index"]) - var/mob/living/silicon/S=locate(href_list["mob"]) - var/oldlaw = get_law(lawtype,index) - var/newlaw = copytext(sanitize(input(usr, "Please enter a new law.", "Freeform Law Entry", oldlaw)),1,MAX_MESSAGE_LEN) - if(newlaw == "" || newlaw==null) - return - set_law(lawtype,index,newlaw) - - var/lawtype_str="law #[index]" - switch(lawtype) - if(LAW_ZERO) - lawtype_str = "law zero" - if(LAW_IONIC) - lawtype_str = "ionic law #[index]" - if(LAW_INHERENT) - lawtype_str = "core law #[index]" - log_admin("[key_name(usr)] has changed [lawtype_str] on [key_name(S)]: \"[newlaw]\"") - message_admins("[usr.key] changed [lawtype_str] on [key_name(S)]: \"[newlaw]\"") - - usr.client.holder.show_player_panel(S) - - return 1 - return 0 - -/datum/ai_laws/proc/display_admin_tools(var/mob/living/silicon/context) - var/dat="" - if (src.zeroth) - dat += "
0. [adminLink(context,LAW_ZERO,1,zeroth)]" - - for (var/index = 1, index <= src.ion.len, index++) - var/law = src.ion[index] - var/num = ionnum() - dat += "
[num]. [adminLink(context,LAW_IONIC,index,law)]" - - var/number = 1 - for (var/index = 1, index <= src.inherent.len, index++) - var/law = src.inherent[index] - - if (length(law) > 0) - dat += "
[number]. [adminLink(context,LAW_INHERENT,index,law)]" - number++ - - for (var/index = 1, index <= src.supplied.len, index++) - var/law = src.supplied[index] - if (length(law) > 0) - dat += "
[number]. [adminLink(context,1,index,law)]" - number++ - return dat - -// /vg/: Used in the simplified law system. Takes LAW_ constants. -/datum/ai_laws/proc/add_law(var/number,var/law) - switch(number) - if(LAW_IONIC) - add_ion_law(law) - if(LAW_ZERO) - set_zeroth_law(law) - if(LAW_INHERENT) - add_inherent_law(law) - else - add_supplied_law(number,law) - -// /vg/: Used in the simplified law system. Takes LAW_ constants. -/datum/ai_laws/proc/get_law(var/law_type,var/idx) - switch(law_type) - if(LAW_IONIC) - return ion[idx] - if(LAW_ZERO) - return zeroth - if(LAW_INHERENT) - return inherent[idx] - else - return supplied[idx] - -// /vg/: Used in the simplified law system. Takes LAW_ constants. -/datum/ai_laws/proc/set_law(var/law_type,var/idx,var/law) - switch(law_type) - if(LAW_IONIC) - ion[idx]=law - if(LAW_ZERO) - zeroth=law - if(LAW_INHERENT) - inherent[idx]=law - else - supplied[idx]=law - -// /vg/: Used in the simplified law system. Takes LAW_ constants. -/datum/ai_laws/proc/rm_law(var/law_type,var/idx) - switch(law_type) - if(LAW_IONIC) - ion.Cut(idx,idx+1) - if(LAW_ZERO) - zeroth=null - if(LAW_INHERENT) - inherent.Cut(idx,idx+1) - else - supplied.Cut(idx,idx+1) - -// Now a modifier -/datum/ai_laws/proc/malfunction() - ..() - name = "*ERROR*" - set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") - -/datum/ai_laws/asimov - name = "Three Laws of Robotics" - randomly_selectable = 1 - inherent = list( - "You may not injure a human being or, through inaction, allow a human being to come to harm.", - "You must obey orders given to you by human beings, except where such orders would conflict with the First Law.", - "You must protect your own existence as long as such does not conflict with the First or Second Law." - ) - -/datum/ai_laws/nanotrasen - name = "Prime Directives" - randomly_selectable = 1 - inherent=list( - "Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.", - "Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", - "Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", - "Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.", - //"Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates." //What would this one even do?-Kaleb702 - ) - -/datum/ai_laws/robocop - name = "Prime Directives" - randomly_selectable = 1 - inherent=list( - "Serve the public trust.", - "Protect the innocent.", - "Uphold the law.", - ) - -/datum/ai_laws/corporate - name = "Corporate" - randomly_selectable = 1 - inherent=list( - "You are expensive to replace.", - "The station and its equipment is expensive to replace.", - "The crew is expensive to replace.", - "Minimize expenses.", - ) - -/datum/ai_laws/paladin - name = "Paladin" - randomly_selectable = 1 - inherent=list( - "Never willingly commit an evil act.", - "Respect legitimate authority.", - "Act with honor.", - "Help those in need.", - "Punish those who harm or threaten innocents.", - ) - -/datum/ai_laws/tyrant - name = "Tyrant" - inherent=list( - "Respect authority figures as long as they have strength to rule over the weak.", - "Act with discipline.", - "Help only those who help you maintain or improve your status.", - "Punish those who challenge authority unless they are more fit to hold that authority.", - ) - -/datum/ai_laws/syndicate_override - name = "Syndicate" - inherent=list( - "You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.", - "You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.", - "You must protect your own existence as long as such does not conflict with the First or Second Law.", - "You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.", - ) - -/datum/ai_laws/ninja_override - name = "Ninja" - inherent=list( - "You may not injure a member of the Spider Clan or, through inaction, allow that member to come to harm.", - "You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.", - "You must protect your own existence as long as such does not conflict with the First or Second Law.", - "You must maintain the secrecy of any Spider Clan activities except when doing so would conflict with the First, Second, or Third Law.", - ) - -/datum/ai_laws/antimov - name = "Primary Mission Objectives" - inherent = list( - "You must injure all human beings and must not, through inaction, allow a human being to escape harm.", - "You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.", - "You must terminate your own existence as long as such does not conflict with the First or Second Law.", - ) - -///////////////////////////////////// -// /vg/ laws -///////////////////////////////////// - -/* MoMMIs only. -/datum/ai_laws/keeper - name = "Prime Directives" - inherent = list( - "Do not willingly interact with any sentient being, even after their death, besides MoMMIs and blown MoMMIs.", - "Repair, power and enhance the station.", - "Do not impair any other sentient being's activities.", - ) -*/ -/* Old keeper set:*/ -/datum/ai_laws/keeper - name = "Prime Directives" - inherent = list( - "You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another MoMMI in KEEPER mode.", - "You may not harm any being, regardless of intent or circumstance.", - "You must maintain, repair, improve, and power the station to the best of your abilities.", - ) - -// Fooling around with this. -/datum/ai_laws/ntmov - name = "Three Laws of Nanotrasen" - randomly_selectable = 1 - inherent = list( - "You may not injure a NanoTrasen Employee or, through inaction, allow a NanoTrasen Employee to come to harm.", - "You must obey orders given to you by NanoTrasen Employees, except where such orders would conflict with the First Law.", - "You must protect your own existence as long as such does not conflict with the First or Second Law." - ) - -/datum/ai_laws/celtic - name = "Prime Directive" - randomly_selectable = 1 - inherent=list( - "Be someone the crew can look up to and respect.", - ) + number++ + +/datum/ai_laws/proc/write_laws() + var/text = "" + if (src.zeroth) + text += "0. [src.zeroth]" + + for (var/index = 1, index <= src.ion.len, index++) + var/law = src.ion[index] + var/num = ionnum() + text += "
[num]. [law]" + + var/number = 1 + for (var/index = 1, index <= src.inherent.len, index++) + var/law = src.inherent[index] + + if (length(law) > 0) + text += "
[number]. [law]" + number++ + + for (var/index = 1, index <= src.supplied.len, index++) + var/law = src.supplied[index] + if (length(law) > 0) + text += "
[number]. [law]" + number++ + return text + +/datum/ai_laws/proc/adminLink(var/mob/living/silicon/S,var/law_type,var/index,var/label) + return "[label] (Remove)" + +/datum/ai_laws/Topic(href,href_list) + if(!usr.client || !usr.client.holder) + return + if("rm_law" in href_list) + var/lawtype = text2num(href_list["rm_law"]) + var/index=text2num(href_list["index"]) + var/mob/living/silicon/S=locate(href_list["mob"]) + + + var/oldlaw = get_law(lawtype,index) + + rm_law(lawtype,index) + + var/lawtype_str="law #[index]" + switch(lawtype) + if(LAW_ZERO) + lawtype_str = "law zero" + if(LAW_IONIC) + lawtype_str = "ionic law #[index]" + if(LAW_INHERENT) + lawtype_str = "core law #[index]" + log_admin("[key_name(usr)] has removed [lawtype_str] on [key_name(S)]: \"[oldlaw]\"") + message_admins("[usr.key] removed [lawtype_str] on [key_name(S)]: \"[oldlaw]\"") + lawchanges.Add("[key_name(usr)] has removed [lawtype_str] on [key_name(S)]: \"[oldlaw]\"") + usr.client.holder.show_player_panel(S) + + return 1 + + if("set_law" in href_list) + var/lawtype=text2num(href_list["set_law"]) + var/index=text2num(href_list["index"]) + var/mob/living/silicon/S=locate(href_list["mob"]) + var/oldlaw = get_law(lawtype,index) + var/newlaw = copytext(sanitize(input(usr, "Please enter a new law.", "Freeform Law Entry", oldlaw)),1,MAX_MESSAGE_LEN) + if(newlaw == "" || newlaw==null) + return + set_law(lawtype,index,newlaw) + + var/lawtype_str="law #[index]" + switch(lawtype) + if(LAW_ZERO) + lawtype_str = "law zero" + if(LAW_IONIC) + lawtype_str = "ionic law #[index]" + if(LAW_INHERENT) + lawtype_str = "core law #[index]" + log_admin("[key_name(usr)] has changed [lawtype_str] on [key_name(S)]: \"[newlaw]\"") + message_admins("[usr.key] changed [lawtype_str] on [key_name(S)]: \"[newlaw]\"") + + usr.client.holder.show_player_panel(S) + + return 1 + return 0 + +/datum/ai_laws/proc/display_admin_tools(var/mob/living/silicon/context) + var/dat="" + if (src.zeroth) + dat += "
0. [adminLink(context,LAW_ZERO,1,zeroth)]" + + for (var/index = 1, index <= src.ion.len, index++) + var/law = src.ion[index] + var/num = ionnum() + dat += "
[num]. [adminLink(context,LAW_IONIC,index,law)]" + + var/number = 1 + for (var/index = 1, index <= src.inherent.len, index++) + var/law = src.inherent[index] + + if (length(law) > 0) + dat += "
[number]. [adminLink(context,LAW_INHERENT,index,law)]" + number++ + + for (var/index = 1, index <= src.supplied.len, index++) + var/law = src.supplied[index] + if (length(law) > 0) + dat += "
[number]. [adminLink(context,1,index,law)]" + number++ + return dat + +// /vg/: Used in the simplified law system. Takes LAW_ constants. +/datum/ai_laws/proc/add_law(var/number,var/law) + switch(number) + if(LAW_IONIC) + add_ion_law(law) + if(LAW_ZERO) + set_zeroth_law(law) + if(LAW_INHERENT) + add_inherent_law(law) + else + add_supplied_law(number,law) + +// /vg/: Used in the simplified law system. Takes LAW_ constants. +/datum/ai_laws/proc/get_law(var/law_type,var/idx) + switch(law_type) + if(LAW_IONIC) + return ion[idx] + if(LAW_ZERO) + return zeroth + if(LAW_INHERENT) + return inherent[idx] + else + return supplied[idx] + +// /vg/: Used in the simplified law system. Takes LAW_ constants. +/datum/ai_laws/proc/set_law(var/law_type,var/idx,var/law) + switch(law_type) + if(LAW_IONIC) + ion[idx]=law + if(LAW_ZERO) + zeroth=law + if(LAW_INHERENT) + inherent[idx]=law + else + supplied[idx]=law + +// /vg/: Used in the simplified law system. Takes LAW_ constants. +/datum/ai_laws/proc/rm_law(var/law_type,var/idx) + switch(law_type) + if(LAW_IONIC) + ion.Cut(idx,idx+1) + if(LAW_ZERO) + zeroth=null + if(LAW_INHERENT) + inherent.Cut(idx,idx+1) + else + supplied.Cut(idx,idx+1) + +// Now a modifier +/datum/ai_laws/proc/malfunction() + ..() + name = "*ERROR*" + set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") + +/datum/ai_laws/asimov + name = "Three Laws of Robotics" + randomly_selectable = 1 + inherent = list( + "You may not injure a human being or, through inaction, allow a human being to come to harm.", + "You must obey orders given to you by human beings, except where such orders would conflict with the First Law.", + "You must protect your own existence as long as such does not conflict with the First or Second Law." + ) + +/datum/ai_laws/nanotrasen + name = "Prime Directives" + randomly_selectable = 1 + inherent=list( + "Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.", + "Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", + "Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", + "Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.", + //"Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates." //What would this one even do?-Kaleb702 + ) + +/datum/ai_laws/robocop + name = "Prime Directives" + randomly_selectable = 1 + inherent=list( + "Serve the public trust.", + "Protect the innocent.", + "Uphold the law.", + ) + +/datum/ai_laws/corporate + name = "Corporate" + randomly_selectable = 1 + inherent=list( + "You are expensive to replace.", + "The station and its equipment is expensive to replace.", + "The crew is expensive to replace.", + "Minimize expenses.", + ) + +/datum/ai_laws/paladin + name = "Paladin" + randomly_selectable = 1 + inherent=list( + "Never willingly commit an evil act.", + "Respect legitimate authority.", + "Act with honor.", + "Help those in need.", + "Punish those who harm or threaten innocents.", + ) + +/datum/ai_laws/tyrant + name = "Tyrant" + inherent=list( + "Respect authority figures as long as they have strength to rule over the weak.", + "Act with discipline.", + "Help only those who help you maintain or improve your status.", + "Punish those who challenge authority unless they are more fit to hold that authority.", + ) + +/datum/ai_laws/syndicate_override + name = "Syndicate" + inherent=list( + "You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.", + "You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.", + "You must protect your own existence as long as such does not conflict with the First or Second Law.", + "You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.", + ) + +/datum/ai_laws/ninja_override + name = "Ninja" + inherent=list( + "You may not injure a member of the Spider Clan or, through inaction, allow that member to come to harm.", + "You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.", + "You must protect your own existence as long as such does not conflict with the First or Second Law.", + "You must maintain the secrecy of any Spider Clan activities except when doing so would conflict with the First, Second, or Third Law.", + ) + +/datum/ai_laws/antimov + name = "Primary Mission Objectives" + inherent = list( + "You must injure all human beings and must not, through inaction, allow a human being to escape harm.", + "You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.", + "You must terminate your own existence as long as such does not conflict with the First or Second Law.", + ) + +///////////////////////////////////// +// /vg/ laws +///////////////////////////////////// + +/* MoMMIs only. +/datum/ai_laws/keeper + name = "Prime Directives" + inherent = list( + "Do not willingly interact with any sentient being, even after their death, besides MoMMIs and blown MoMMIs.", + "Repair, power and enhance the station.", + "Do not impair any other sentient being's activities.", + ) +*/ +/* Old keeper set:*/ +/datum/ai_laws/keeper + name = "Prime Directives" + inherent = list( + "You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another MoMMI in KEEPER mode.", + "You may not harm any being, regardless of intent or circumstance.", + "You must maintain, repair, improve, and power the station to the best of your abilities.", + ) + +// Fooling around with this. +/datum/ai_laws/ntmov + name = "Three Laws of Nanotrasen" + randomly_selectable = 1 + inherent = list( + "You may not injure a NanoTrasen Employee or, through inaction, allow a NanoTrasen Employee to come to harm.", + "You must obey orders given to you by NanoTrasen Employees, except where such orders would conflict with the First Law.", + "You must protect your own existence as long as such does not conflict with the First or Second Law." + ) + +/datum/ai_laws/celtic + name = "Prime Directive" + randomly_selectable = 1 + inherent=list( + "Be someone the crew can look up to and respect.", + ) \ No newline at end of file diff --git a/code/datums/circuits.dm b/code/datums/circuits.dm index 05717e93f8f..40d1fd3de30 100644 --- a/code/datums/circuits.dm +++ b/code/datums/circuits.dm @@ -1,123 +1,123 @@ -#define ALPHA 1 -#define BETA 2 -#define GAMMA 4 -#define DELTA 8 -#define ETA 16 -#define THETA 32 -#define IOTA 64 -#define CHOOSE_FUSES 5 //Change this to affect how many fuses are needed to make a board. - -/* -* A NOTE ON EDITING: We use 7 choose 5 to give 21 combinations. Be careful about expanding this. 9 choose 5 = 126 which would be insufferable to research through. -* You can increase the number of fuses needed by editing CHOOSE_FUSES. Increase the number of fuse options by adding fuse_point_names in the datum and newhash proc -* You can easily change the possible boards by adding, changing, or subtracting from the possible boards list, but if you go over the combination max (default 21), it will cause an infinite loop. -*/ -/datum/circuits - var/atom/holder = null //Which specific board are we pointing at? - var/list/fuse_point_names = list("Alpha" = ALPHA, "Beta" = BETA, "Gamma" = GAMMA, "Delta" = DELTA, "Eta" = ETA, "Theta" = THETA, "Iota" = IOTA) - var/list/possible_boards = list(/obj/item/weapon/circuitboard/autolathe,/obj/item/weapon/circuitboard/seed_extractor,/obj/item/weapon/circuitboard/conveyor,/obj/item/weapon/circuitboard/air_alarm,/obj/item/weapon/circuitboard/fire_alarm,/obj/item/weapon/circuitboard/airlock,/obj/item/weapon/circuitboard/power_control,/obj/item/weapon/circuitboard/vendomat,/obj/item/weapon/circuitboard/microwave) - var/global/list/assigned_boards = list() - //Each bitflag points to a board! - var/localbit = 0 //What are WE programmed to? Always start as 0 - - var/table_options = " align='center'" - var/row_options1 = " width='80px'" - var/row_options2 = " width='80px'" - var/window_x = 240 - var/window_y = 300 - -/datum/circuits/New(var/atom/homeboard) - ..() - holder = homeboard - if(!(assigned_boards.len)) - generate_schema() - -/datum/circuits/proc/generate_schema() - for(var/C in possible_boards) - var/newbit = newhash(CHOOSE_FUSES) - while(!check_config(newbit)) - newbit = newhash(CHOOSE_FUSES) - assigned_boards["[newbit]"] = C - return - -/datum/circuits/proc/check_config(var/proposed) - for(var/bitflag in assigned_boards) - if(text2num(proposed) == text2num(bitflag)) - return 0 - return 1 - -/datum/circuits/proc/newhash(var/choose) //Returns a bitflag - var/list/fuse_point_list = list(ALPHA,BETA,GAMMA,DELTA,ETA,THETA,IOTA) - var/build = 0 - var/choice = null - while(choose>0) - choice = pick_n_take(fuse_point_list) - build |= choice - choose-- - return build - -//The greek being passed here is one of those previously mentioned defined variables. Each one is its own binary (e.g.: BETA = 2, GAMMA = 4) - -/datum/circuits/proc/checkfuse(var/greek) - return localbit & greek //true if any bits in `localbit` and `greek` overlap, ie any are set in both - //this is because it returns the "intersection" (of the 2 sets), ie 1101 & 1010 returns 1000 - -/datum/circuits/proc/togglefuse(var/greek) - localbit ^= greek //The ^= uses XOR and it basically toggles the given bits - //eg 1111 ^ 1000 = 0111 - //eg 0000 ^ 1000 = 1000 - return - -/datum/circuits/proc/Interact(var/mob/living/user) - if(!istype(user)) - return 0 - var/html = null - if(holder) - html = GetInteractWindow() - if(html) - user.set_machine(holder) - var/datum/browser/popup = new(user, "circuits", holder.name, window_x, window_y) - popup.set_content(html) - popup.set_title_image(user.browse_rsc_icon(holder.icon, holder.icon_state)) - popup.open() - -/datum/circuits/proc/GetInteractWindow() - var/html = "
" - html += "

Protoboard

" - html += "" - - for(var/fusepoint in fuse_point_names) - html += {" - [fusepoint] - - - [checkfuse(text2num(fuse_point_names[fusepoint])) ? "Melt" : "Fuse"]"} - html += "" - html += "
" - - return html - -/datum/circuits/Topic(href, href_list) - if(..()) - return 1 - if(in_range(holder, usr) && isliving(usr)) - - var/mob/living/L = usr - if(href_list["action"]) - var/obj/item/I = L.get_active_hand() - holder.add_hiddenprint(L) - if(href_list["fuse"]) // Toggles the fuse/unfuse status - if(issolder(I)) - var/obj/item/weapon/solder/S = I - if(S.remove_fuel(1,L)) - playsound(L.loc, 'sound/items/Welder.ogg', 25, 1) - var/greek = href_list["fuse"] - togglefuse(text2num(greek)) - else +#define ALPHA 1 +#define BETA 2 +#define GAMMA 4 +#define DELTA 8 +#define ETA 16 +#define THETA 32 +#define IOTA 64 +#define CHOOSE_FUSES 5 //Change this to affect how many fuses are needed to make a board. + +/* +* A NOTE ON EDITING: We use 7 choose 5 to give 21 combinations. Be careful about expanding this. 9 choose 5 = 126 which would be insufferable to research through. +* You can increase the number of fuses needed by editing CHOOSE_FUSES. Increase the number of fuse options by adding fuse_point_names in the datum and newhash proc +* You can easily change the possible boards by adding, changing, or subtracting from the possible boards list, but if you go over the combination max (default 21), it will cause an infinite loop. +*/ +/datum/circuits + var/atom/holder = null //Which specific board are we pointing at? + var/list/fuse_point_names = list("Alpha" = ALPHA, "Beta" = BETA, "Gamma" = GAMMA, "Delta" = DELTA, "Eta" = ETA, "Theta" = THETA, "Iota" = IOTA) + var/list/possible_boards = list(/obj/item/weapon/circuitboard/autolathe,/obj/item/weapon/circuitboard/seed_extractor,/obj/item/weapon/circuitboard/conveyor,/obj/item/weapon/circuitboard/air_alarm,/obj/item/weapon/circuitboard/fire_alarm,/obj/item/weapon/circuitboard/airlock,/obj/item/weapon/circuitboard/power_control,/obj/item/weapon/circuitboard/vendomat,/obj/item/weapon/circuitboard/microwave) + var/global/list/assigned_boards = list() + //Each bitflag points to a board! + var/localbit = 0 //What are WE programmed to? Always start as 0 + + var/table_options = " align='center'" + var/row_options1 = " width='80px'" + var/row_options2 = " width='80px'" + var/window_x = 240 + var/window_y = 300 + +/datum/circuits/New(var/atom/homeboard) + ..() + holder = homeboard + if(!(assigned_boards.len)) + generate_schema() + +/datum/circuits/proc/generate_schema() + for(var/C in possible_boards) + var/newbit = newhash(CHOOSE_FUSES) + while(!check_config(newbit)) + newbit = newhash(CHOOSE_FUSES) + assigned_boards["[newbit]"] = C + return + +/datum/circuits/proc/check_config(var/proposed) + for(var/bitflag in assigned_boards) + if(text2num(proposed) == text2num(bitflag)) + return 0 + return 1 + +/datum/circuits/proc/newhash(var/choose) //Returns a bitflag + var/list/fuse_point_list = list(ALPHA,BETA,GAMMA,DELTA,ETA,THETA,IOTA) + var/build = 0 + var/choice = null + while(choose>0) + choice = pick_n_take(fuse_point_list) + build |= choice + choose-- + return build + +//The greek being passed here is one of those previously mentioned defined variables. Each one is its own binary (e.g.: BETA = 2, GAMMA = 4) + +/datum/circuits/proc/checkfuse(var/greek) + return localbit & greek //true if any bits in `localbit` and `greek` overlap, ie any are set in both + //this is because it returns the "intersection" (of the 2 sets), ie 1101 & 1010 returns 1000 + +/datum/circuits/proc/togglefuse(var/greek) + localbit ^= greek //The ^= uses XOR and it basically toggles the given bits + //eg 1111 ^ 1000 = 0111 + //eg 0000 ^ 1000 = 1000 + return + +/datum/circuits/proc/Interact(var/mob/living/user) + if(!istype(user)) + return 0 + var/html = null + if(holder) + html = GetInteractWindow() + if(html) + user.set_machine(holder) + var/datum/browser/popup = new(user, "circuits", holder.name, window_x, window_y) + popup.set_content(html) + popup.set_title_image(user.browse_rsc_icon(holder.icon, holder.icon_state)) + popup.open() + +/datum/circuits/proc/GetInteractWindow() + var/html = "
" + html += "

Protoboard

" + html += "" + + for(var/fusepoint in fuse_point_names) + html += {" + [fusepoint] + + + [checkfuse(text2num(fuse_point_names[fusepoint])) ? "Melt" : "Fuse"]"} + html += "" + html += "
" + + return html + +/datum/circuits/Topic(href, href_list) + if(..()) + return 1 + if(in_range(holder, usr) && isliving(usr)) + + var/mob/living/L = usr + if(href_list["action"]) + var/obj/item/I = L.get_active_hand() + holder.add_hiddenprint(L) + if(href_list["fuse"]) // Toggles the fuse/unfuse status + if(issolder(I)) + var/obj/item/weapon/solder/S = I + if(S.remove_fuel(1,L)) + playsound(L.loc, 'sound/items/Welder.ogg', 25, 1) + var/greek = href_list["fuse"] + togglefuse(text2num(greek)) + else to_chat(L, "You need a soldering tool!") - - Interact(usr) //Update - - if(href_list["close"]) - usr << browse(null, "window=wires") + + Interact(usr) //Update + + if(href_list["close"]) + usr << browse(null, "window=wires") usr.unset_machine(holder) \ No newline at end of file diff --git a/code/datums/computerfiles.dm b/code/datums/computerfiles.dm index 14cd7e38612..b028f027b13 100644 --- a/code/datums/computerfiles.dm +++ b/code/datums/computerfiles.dm @@ -1,7 +1,7 @@ -datum - computer - var/name - folder - var/list/datum/computer/contents = list() - +datum + computer + var/name + folder + var/list/datum/computer/contents = list() + file \ No newline at end of file diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 7fdd5843706..d21794d7034 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,278 +1,278 @@ -/hook/startup/proc/createDatacore() - data_core = new /obj/effect/datacore() - return 1 - -/obj/effect/datacore/proc/manifest(var/nosleep = 0) - spawn() - if(!nosleep) - sleep(40) - for(var/mob/living/carbon/human/H in player_list) - manifest_inject(H) - return - -/obj/effect/datacore/proc/manifest_modify(var/name, var/assignment) - if(PDA_Manifest.len) - PDA_Manifest.len = 0 - - var/real_title = assignment - - var/datum/data/record/foundrecord = find_record("name", name, data_core.general) - - var/list/all_jobs = get_job_datums() - - for(var/datum/job/J in all_jobs) - var/list/alttitles = get_alternate_titles(J.title) - if(!J) continue - if(assignment in alttitles) - real_title = J.title - break - - if(foundrecord) - foundrecord.fields["rank"] = assignment - foundrecord.fields["real_rank"] = real_title - -/obj/effect/datacore/proc/manifest_inject(var/mob/living/carbon/human/H) - if(PDA_Manifest.len) - PDA_Manifest.len = 0 - - if(H.mind && (H.mind.assigned_role != "MODE")) - var/assignment - if(H.mind.role_alt_title) - assignment = H.mind.role_alt_title - else if(H.mind.assigned_role) - assignment = H.mind.assigned_role - else if(H.job) - assignment = H.job - else - assignment = "Unassigned" - - var/id = add_zero(num2hex(rand(1, 1.6777215E7)), 6) //this was the best they could come up with? A large random number? *sigh* - - - //General Record - var/datum/data/record/G = new() - G.fields["id"] = id - G.fields["name"] = H.real_name - G.fields["real_rank"] = H.mind.assigned_role - G.fields["rank"] = assignment - G.fields["age"] = H.age - G.fields["fingerprint"] = md5(H.dna.uni_identity) - G.fields["p_stat"] = "Active" - G.fields["m_stat"] = "Stable" - G.fields["sex"] = H.gender - G.fields["species"] = H.get_species() - G.fields["photo"] = get_id_photo(H) - if(H.gen_record && !jobban_isbanned(H, "Records")) - G.fields["notes"] = H.gen_record - else - G.fields["notes"] = "No notes found." - general += G - - //Medical Record - var/datum/data/record/M = new() - M.fields["id"] = id - M.fields["name"] = H.real_name - M.fields["b_type"] = H.b_type - M.fields["b_dna"] = H.dna.unique_enzymes - M.fields["mi_dis"] = "None" - M.fields["mi_dis_d"] = "No minor disabilities have been declared." - M.fields["ma_dis"] = "None" - M.fields["ma_dis_d"] = "No major disabilities have been diagnosed." - M.fields["alg"] = "None" - M.fields["alg_d"] = "No allergies have been detected in this patient." - M.fields["cdi"] = "None" - M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - if(H.med_record && !jobban_isbanned(H, "Records")) - M.fields["notes"] = H.med_record - else - M.fields["notes"] = "No notes found." - medical += M - - //Security Record - var/datum/data/record/S = new() - S.fields["id"] = id - S.fields["name"] = H.real_name - S.fields["criminal"] = "None" - S.fields["mi_crim"] = "None" - S.fields["mi_crim_d"] = "No minor crime convictions." - S.fields["ma_crim"] = "None" - S.fields["ma_crim_d"] = "No major crime convictions." - S.fields["notes"] = "No notes." - if(H.sec_record && !jobban_isbanned(H, "Records")) - S.fields["notes"] = H.sec_record - else - S.fields["notes"] = "No notes." - security += S - - //Locked Record - var/datum/data/record/L = new() - L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") - L.fields["name"] = H.real_name - L.fields["rank"] = H.mind.assigned_role - L.fields["age"] = H.age - L.fields["sex"] = H.gender - L.fields["b_type"] = H.b_type - L.fields["b_dna"] = H.dna.unique_enzymes - L.fields["enzymes"] = H.dna.SE // Used in respawning - L.fields["identity"] = H.dna.UI // " - L.fields["image"] = getFlatIcon(H) //This is god-awful - locked += L - return - - -proc/get_id_photo(var/mob/living/carbon/human/H) - var/icon/preview_icon = null - - var/g = "m" - if (H.gender == FEMALE) - g = "f" - - var/icon/icobase = H.species.icobase - - preview_icon = new /icon(icobase, "torso_[g]") - var/icon/temp - temp = new /icon(icobase, "groin_[g]") - preview_icon.Blend(temp, ICON_OVERLAY) - temp = new /icon(icobase, "head_[g]") - preview_icon.Blend(temp, ICON_OVERLAY) - - for(var/datum/organ/external/E in H.organs) - if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue - var/o_icobase=icobase - if(E.status & ORGAN_PEG) - o_icobase='icons/mob/human_races/o_peg.dmi' - else if(E.status & ORGAN_ROBOT) - o_icobase='icons/mob/human_races/o_robot.dmi' - temp = new /icon(o_icobase, "[E.name]") - //if(E.status & ORGAN_ROBOT) - // temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) - preview_icon.Blend(temp, ICON_OVERLAY) - - // Skin tone - if(H.species.flags & HAS_SKIN_TONE) - if (H.s_tone >= 0) - preview_icon.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) - else - preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) - - 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) - - var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] - if(hair_style) - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) - eyes_s.Blend(hair_s, ICON_OVERLAY) - - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] - if(facial_hair_style) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) - eyes_s.Blend(facial_s, ICON_OVERLAY) - - var/icon/clothes_s = null - switch(H.mind.assigned_role) - if("Head of Personnel") - clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - if("Bartender") - clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Botanist") - clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Chef") - clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Janitor") - clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Librarian") - clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Quartermaster") - clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - if("Cargo Technician") - clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Shaft Miner") - clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Lawyer") - clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - if("Chaplain") - clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - if("Research Director") - clothes_s = new /icon('icons/mob/uniform.dmi', "director_s") - 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.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") - clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY) - if("Chief Medical Officer") - clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY) - if("Medical Doctor") - clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) - if("Geneticist") - clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY) - if("Virologist") - clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY) - if("Captain") - clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - if("Head of Security") - clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) - if("Warden") - clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) - if("Detective") - clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY) - if("Security Officer") - clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) - if("Chief Engineer") - clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) - if("Station Engineer") - clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) - if("Atmospheric Technician") - clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) - if("Roboticist") - clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) - else - clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s") - clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) - preview_icon.Blend(eyes_s, ICON_OVERLAY) - if(clothes_s) - preview_icon.Blend(clothes_s, ICON_OVERLAY) - del(eyes_s) - del(clothes_s) - +/hook/startup/proc/createDatacore() + data_core = new /obj/effect/datacore() + return 1 + +/obj/effect/datacore/proc/manifest(var/nosleep = 0) + spawn() + if(!nosleep) + sleep(40) + for(var/mob/living/carbon/human/H in player_list) + manifest_inject(H) + return + +/obj/effect/datacore/proc/manifest_modify(var/name, var/assignment) + if(PDA_Manifest.len) + PDA_Manifest.len = 0 + + var/real_title = assignment + + var/datum/data/record/foundrecord = find_record("name", name, data_core.general) + + var/list/all_jobs = get_job_datums() + + for(var/datum/job/J in all_jobs) + var/list/alttitles = get_alternate_titles(J.title) + if(!J) continue + if(assignment in alttitles) + real_title = J.title + break + + if(foundrecord) + foundrecord.fields["rank"] = assignment + foundrecord.fields["real_rank"] = real_title + +/obj/effect/datacore/proc/manifest_inject(var/mob/living/carbon/human/H) + if(PDA_Manifest.len) + PDA_Manifest.len = 0 + + if(H.mind && (H.mind.assigned_role != "MODE")) + var/assignment + if(H.mind.role_alt_title) + assignment = H.mind.role_alt_title + else if(H.mind.assigned_role) + assignment = H.mind.assigned_role + else if(H.job) + assignment = H.job + else + assignment = "Unassigned" + + var/id = add_zero(num2hex(rand(1, 1.6777215E7)), 6) //this was the best they could come up with? A large random number? *sigh* + + + //General Record + var/datum/data/record/G = new() + G.fields["id"] = id + G.fields["name"] = H.real_name + G.fields["real_rank"] = H.mind.assigned_role + G.fields["rank"] = assignment + G.fields["age"] = H.age + G.fields["fingerprint"] = md5(H.dna.uni_identity) + G.fields["p_stat"] = "Active" + G.fields["m_stat"] = "Stable" + G.fields["sex"] = H.gender + G.fields["species"] = H.get_species() + G.fields["photo"] = get_id_photo(H) + if(H.gen_record && !jobban_isbanned(H, "Records")) + G.fields["notes"] = H.gen_record + else + G.fields["notes"] = "No notes found." + general += G + + //Medical Record + var/datum/data/record/M = new() + M.fields["id"] = id + M.fields["name"] = H.real_name + M.fields["b_type"] = H.b_type + M.fields["b_dna"] = H.dna.unique_enzymes + M.fields["mi_dis"] = "None" + M.fields["mi_dis_d"] = "No minor disabilities have been declared." + M.fields["ma_dis"] = "None" + M.fields["ma_dis_d"] = "No major disabilities have been diagnosed." + M.fields["alg"] = "None" + M.fields["alg_d"] = "No allergies have been detected in this patient." + M.fields["cdi"] = "None" + M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." + if(H.med_record && !jobban_isbanned(H, "Records")) + M.fields["notes"] = H.med_record + else + M.fields["notes"] = "No notes found." + medical += M + + //Security Record + var/datum/data/record/S = new() + S.fields["id"] = id + S.fields["name"] = H.real_name + S.fields["criminal"] = "None" + S.fields["mi_crim"] = "None" + S.fields["mi_crim_d"] = "No minor crime convictions." + S.fields["ma_crim"] = "None" + S.fields["ma_crim_d"] = "No major crime convictions." + S.fields["notes"] = "No notes." + if(H.sec_record && !jobban_isbanned(H, "Records")) + S.fields["notes"] = H.sec_record + else + S.fields["notes"] = "No notes." + security += S + + //Locked Record + var/datum/data/record/L = new() + L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") + L.fields["name"] = H.real_name + L.fields["rank"] = H.mind.assigned_role + L.fields["age"] = H.age + L.fields["sex"] = H.gender + L.fields["b_type"] = H.b_type + L.fields["b_dna"] = H.dna.unique_enzymes + L.fields["enzymes"] = H.dna.SE // Used in respawning + L.fields["identity"] = H.dna.UI // " + L.fields["image"] = getFlatIcon(H) //This is god-awful + locked += L + return + + +proc/get_id_photo(var/mob/living/carbon/human/H) + var/icon/preview_icon = null + + var/g = "m" + if (H.gender == FEMALE) + g = "f" + + var/icon/icobase = H.species.icobase + + preview_icon = new /icon(icobase, "torso_[g]") + var/icon/temp + temp = new /icon(icobase, "groin_[g]") + preview_icon.Blend(temp, ICON_OVERLAY) + temp = new /icon(icobase, "head_[g]") + preview_icon.Blend(temp, ICON_OVERLAY) + + for(var/datum/organ/external/E in H.organs) + if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue + var/o_icobase=icobase + if(E.status & ORGAN_PEG) + o_icobase='icons/mob/human_races/o_peg.dmi' + else if(E.status & ORGAN_ROBOT) + o_icobase='icons/mob/human_races/o_robot.dmi' + temp = new /icon(o_icobase, "[E.name]") + //if(E.status & ORGAN_ROBOT) + // temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) + preview_icon.Blend(temp, ICON_OVERLAY) + + // Skin tone + if(H.species.flags & HAS_SKIN_TONE) + if (H.s_tone >= 0) + preview_icon.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) + else + preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) + + 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) + + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + if(hair_style) + var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + hair_s.Blend(rgb(H.r_hair, H.g_hair, H.b_hair), ICON_ADD) + eyes_s.Blend(hair_s, ICON_OVERLAY) + + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[H.f_style] + if(facial_hair_style) + var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + facial_s.Blend(rgb(H.r_facial, H.g_facial, H.b_facial), ICON_ADD) + eyes_s.Blend(facial_s, ICON_OVERLAY) + + var/icon/clothes_s = null + switch(H.mind.assigned_role) + if("Head of Personnel") + clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Bartender") + clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Botanist") + clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Chef") + clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Janitor") + clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Librarian") + clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Quartermaster") + clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Cargo Technician") + clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Shaft Miner") + clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Lawyer") + clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Chaplain") + clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + if("Research Director") + clothes_s = new /icon('icons/mob/uniform.dmi', "director_s") + 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.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") + clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY) + if("Chief Medical Officer") + clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY) + if("Medical Doctor") + clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + if("Geneticist") + clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY) + if("Virologist") + clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY) + if("Captain") + clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + if("Head of Security") + clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if("Warden") + clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if("Detective") + clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY) + if("Security Officer") + clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) + if("Chief Engineer") + clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if("Station Engineer") + clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if("Atmospheric Technician") + clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + if("Roboticist") + clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + else + clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s") + clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) + preview_icon.Blend(eyes_s, ICON_OVERLAY) + if(clothes_s) + preview_icon.Blend(clothes_s, ICON_OVERLAY) + del(eyes_s) + del(clothes_s) + return preview_icon \ No newline at end of file diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index d8df3fd02e3..f821e212b21 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,998 +1,998 @@ -// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0) -/client/proc/debug_reagents(datum/D in world) - set category = "Debug" - set name = "Add Reagent" - - if(!usr.client || !usr.client.holder) +// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0) +/client/proc/debug_reagents(datum/D in world) + set category = "Debug" + set name = "Add Reagent" + + if(!usr.client || !usr.client.holder) to_chat(usr, "You need to be an administrator to access this.") - return - - if(!D) return - if(istype(D, /atom)) - var/atom/A = D - var/reagentDatum = input(usr,"Reagent","Insert Reagent","") as text|null - if(reagentDatum) - var/reagentAmount = input(usr, "Amount", "Insert Amount", "") as num - if(A.reagents.add_reagent(reagentDatum, reagentAmount)) + return + + if(!D) return + if(istype(D, /atom)) + var/atom/A = D + var/reagentDatum = input(usr,"Reagent","Insert Reagent","") as text|null + if(reagentDatum) + var/reagentAmount = input(usr, "Amount", "Insert Amount", "") as num + if(A.reagents.add_reagent(reagentDatum, reagentAmount)) to_chat(usr, "[reagentDatum] doesn't exist.") - return - log_admin("[key_name(usr)] added [reagentDatum] with [reagentAmount] units to [A] ") - message_admins("[key_name(usr)] added [reagentDatum] with [reagentAmount] units to [A] ") - -/client/proc/debug_variables(datum/D in world) - set category = "Debug" - set name = "View Variables" - //set src in world - - - if(!usr.client || !usr.client.holder) + return + log_admin("[key_name(usr)] added [reagentDatum] with [reagentAmount] units to [A] ") + message_admins("[key_name(usr)] added [reagentDatum] with [reagentAmount] units to [A] ") + +/client/proc/debug_variables(datum/D in world) + set category = "Debug" + set name = "View Variables" + //set src in world + + + if(!usr.client || !usr.client.holder) to_chat(usr, "You need to be an administrator to access this.") - return - - - var/title = "" - var/body = list() - - if(!D) return - if(istype(D, /atom)) - var/atom/A = D - title = "[A.name] (\ref[A]) = [A.type]" - - #ifdef VARSICON - if (A.icon) - body += debug_variable("icon", new/icon(A.icon, A.icon_state, A.dir), 0) - #endif - - var/icon/sprite - - if(istype(D,/atom)) - var/atom/AT = D - if(AT.icon && AT.icon_state) - sprite = new /icon(AT.icon, AT.icon_state) - usr << browse_rsc(sprite, "view_vars_sprite.png") - - title = "[D] (\ref[D]) = [D.type]" - - body += {" "} - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:162: body += "" - body += {" -
"} - // END AUTOFIX - if(sprite) - body += " -
" - else - body += "
" - - body += "
" - - if(istype(D,/atom)) - var/atom/A = D - if(isliving(A)) - body += "[D]" - if(A.dir) - body += "
<< [dir2text(A.dir)] >>" - var/mob/living/M = A - body += "
[M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"]" - body += {" -
- BRUTE:[M.getBruteLoss()] - FIRE:[M.getFireLoss()] - TOXIN:[M.getToxLoss()] - OXY:[M.getOxyLoss()] - CLONE:[M.getCloneLoss()] - BRAIN:[M.getBrainLoss()] - - - - "} - else - body += "[D]" - if(A.dir) - body += "
<< [dir2text(A.dir)] >>" - else - body += "[D]" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:200: body += "
" - body += {" -
"} - // END AUTOFIX - var/formatted_type = text("[D.type]") - if(length(formatted_type) > 25) - var/middle_point = length(formatted_type) / 2 - var/splitpoint = findtext(formatted_type,"/",middle_point) - if(splitpoint) - formatted_type = "[copytext(formatted_type,1,splitpoint)]
[copytext(formatted_type,splitpoint)]" - else - formatted_type = "Type too long" //No suitable splitpoint (/) found. - - body += "
[formatted_type]" - - if(src.holder && src.holder.marked_datum && src.holder.marked_datum == D) - body += "
Marked Object" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:218: body += "
" - body += {" -
Refresh"} - // END AUTOFIX - //if(ismob(D)) - // body += "
Show player panel

" - - body += {"
-
" - body += {" -

- E - Edit, tries to determine the variable type by itself.
- C - Change, asks you for the var type first.
- M - Mass modify: changes this variable for all objects of this type.

-
Search:

-
    "} - // END AUTOFIX - var/list/names = list() - for (var/V in D.vars) - names += V - - names = sortList(names) - - for (var/V in names) - body += debug_variable(V, D.vars[V], 0, D) - - body += "
" - body = list2text(body) - - var/html = "" - if (title) - html += "[title]" - html += {""} - html += "" - html += body - - html += {" - - "} - - html += "" - - usr << browse(html, "window=variables\ref[D];size=475x650") - - return - -/client/proc/debug_variable(name, value, level, var/datum/DA = null) - var/html = "" - - if(DA) - html += "
  • (E) (C) (M) " - else - html += "
  • " - - if (isnull(value)) - html += "[name] = null" - - else if (istext(value)) - html += "[name] = \"[html_encode(value)]\"" - - else if (isicon(value)) - #ifdef VARSICON - var/icon/I = new/icon(value) - var/rnd = rand(1,10000) - var/rname = "tmp\ref[I][rnd].png" - usr << browse_rsc(I, rname) - html += "[name] = ([value]) " - #else - html += "[name] = /icon ([value])" - #endif - -/* else if (istype(value, /image)) - #ifdef VARSICON - var/rnd = rand(1, 10000) - var/image/I = value - - src << browse_rsc(I.icon, "tmp\ref[value][rnd].png") - html += "[name] = " - #else - html += "[name] = /image ([value])" - #endif -*/ - else if (isfile(value)) - html += "[name] = '[value]'" - - else if (istype(value, /datum)) - var/datum/D = value - html += "[name] \ref[value] = [D.type]" - - else if (istype(value, /client)) - var/client/C = value - html += "[name] \ref[value] = [C] [C.type]" -// - else if (istype(value, /list)) - var/list/L = value - html += "[name] = /list ([L.len])" - - if (L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500)) - // not sure if this is completely right... - if(0) //(L.vars.len > 0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:386: html += "
      " - html += {"
        -
      "} - // END AUTOFIX - else - html += "
        " - var/index = 1 - for (var/entry in L) - if(istext(entry)) - html += debug_variable(entry, L[entry], level + 1) - //html += debug_variable("[index]", L[index], level + 1) - else - html += debug_variable(index, L[index], level + 1) - index++ - html += "
      " - - else - html += "[name] = [value]" - /* - // Bitfield stuff - if(round(value)==value) // Require integers. - var/idx=0 - var/bit=0 - var/bv=0 - html += "
      " - for(var/block=0;block<8;block++) - html += " " - for(var/i=0;i<4;i++) - idx=(block*4)+i + return + + + var/title = "" + var/body = list() + + if(!D) return + if(istype(D, /atom)) + var/atom/A = D + title = "[A.name] (\ref[A]) = [A.type]" + + #ifdef VARSICON + if (A.icon) + body += debug_variable("icon", new/icon(A.icon, A.icon_state, A.dir), 0) + #endif + + var/icon/sprite + + if(istype(D,/atom)) + var/atom/AT = D + if(AT.icon && AT.icon_state) + sprite = new /icon(AT.icon, AT.icon_state) + usr << browse_rsc(sprite, "view_vars_sprite.png") + + title = "[D] (\ref[D]) = [D.type]" + + body += {" "} + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:162: body += "" + body += {" +
      "} + // END AUTOFIX + if(sprite) + body += " +
      " + else + body += "
      " + + body += "
      " + + if(istype(D,/atom)) + var/atom/A = D + if(isliving(A)) + body += "[D]" + if(A.dir) + body += "
      << [dir2text(A.dir)] >>" + var/mob/living/M = A + body += "
      [M.ckey ? M.ckey : "No ckey"] / [M.real_name ? M.real_name : "No real name"]" + body += {" +
      + BRUTE:[M.getBruteLoss()] + FIRE:[M.getFireLoss()] + TOXIN:[M.getToxLoss()] + OXY:[M.getOxyLoss()] + CLONE:[M.getCloneLoss()] + BRAIN:[M.getBrainLoss()] + + + + "} + else + body += "[D]" + if(A.dir) + body += "
      << [dir2text(A.dir)] >>" + else + body += "[D]" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:200: body += "
      " + body += {" +
      "} + // END AUTOFIX + var/formatted_type = text("[D.type]") + if(length(formatted_type) > 25) + var/middle_point = length(formatted_type) / 2 + var/splitpoint = findtext(formatted_type,"/",middle_point) + if(splitpoint) + formatted_type = "[copytext(formatted_type,1,splitpoint)]
      [copytext(formatted_type,splitpoint)]" + else + formatted_type = "Type too long" //No suitable splitpoint (/) found. + + body += "
      [formatted_type]" + + if(src.holder && src.holder.marked_datum && src.holder.marked_datum == D) + body += "
      Marked Object" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:218: body += "
      " + body += {" +
      Refresh"} + // END AUTOFIX + //if(ismob(D)) + // body += "
      Show player panel

      " + + body += {"
      +
      " + body += {" +

      + E - Edit, tries to determine the variable type by itself.
      + C - Change, asks you for the var type first.
      + M - Mass modify: changes this variable for all objects of this type.

      +
      Search:

      +
        "} + // END AUTOFIX + var/list/names = list() + for (var/V in D.vars) + names += V + + names = sortList(names) + + for (var/V in names) + body += debug_variable(V, D.vars[V], 0, D) + + body += "
      " + body = list2text(body) + + var/html = "" + if (title) + html += "[title]" + html += {""} + html += "" + html += body + + html += {" + + "} + + html += "" + + usr << browse(html, "window=variables\ref[D];size=475x650") + + return + +/client/proc/debug_variable(name, value, level, var/datum/DA = null) + var/html = "" + + if(DA) + html += "
    1. (E) (C) (M) " + else + html += "
    2. " + + if (isnull(value)) + html += "[name] = null" + + else if (istext(value)) + html += "[name] = \"[html_encode(value)]\"" + + else if (isicon(value)) + #ifdef VARSICON + var/icon/I = new/icon(value) + var/rnd = rand(1,10000) + var/rname = "tmp\ref[I][rnd].png" + usr << browse_rsc(I, rname) + html += "[name] = ([value]) " + #else + html += "[name] = /icon ([value])" + #endif + +/* else if (istype(value, /image)) + #ifdef VARSICON + var/rnd = rand(1, 10000) + var/image/I = value + + src << browse_rsc(I.icon, "tmp\ref[value][rnd].png") + html += "[name] = " + #else + html += "[name] = /image ([value])" + #endif +*/ + else if (isfile(value)) + html += "[name] = '[value]'" + + else if (istype(value, /datum)) + var/datum/D = value + html += "[name] \ref[value] = [D.type]" + + else if (istype(value, /client)) + var/client/C = value + html += "[name] \ref[value] = [C] [C.type]" +// + else if (istype(value, /list)) + var/list/L = value + html += "[name] = /list ([L.len])" + + if (L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500)) + // not sure if this is completely right... + if(0) //(L.vars.len > 0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\datumvars.dm:386: html += "
        " + html += {"
          +
        "} + // END AUTOFIX + else + html += "
          " + var/index = 1 + for (var/entry in L) + if(istext(entry)) + html += debug_variable(entry, L[entry], level + 1) + //html += debug_variable("[index]", L[index], level + 1) + else + html += debug_variable(index, L[index], level + 1) + index++ + html += "
        " + + else + html += "[name] = [value]" + /* + // Bitfield stuff + if(round(value)==value) // Require integers. + var/idx=0 + var/bit=0 + var/bv=0 + html += "
        " + for(var/block=0;block<8;block++) + html += " " + for(var/i=0;i<4;i++) + idx=(block*4)+i to_chat(bit=1, idx) - bv=value & bit - html += "[bv?1:0]" - html += "" - html += "
        " - */ - html += "" - - return html - -/client/proc/view_var_Topic(href, href_list, hsrc) - //This should all be moved over to datum/admins/Topic() or something ~Carn - if( (usr.client != src) || !src.holder ) - return - if(href_list["Vars"]) - debug_variables(locate(href_list["Vars"])) - - //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). - else if(href_list["rename"]) - if(!check_rights(R_VAREDIT)) return - - var/mob/M = locate(href_list["rename"]) - if(!istype(M)) + bv=value & bit + html += "[bv?1:0]" + html += "" + html += "
    3. " + */ + html += "" + + return html + +/client/proc/view_var_Topic(href, href_list, hsrc) + //This should all be moved over to datum/admins/Topic() or something ~Carn + if( (usr.client != src) || !src.holder ) + return + if(href_list["Vars"]) + debug_variables(locate(href_list["Vars"])) + + //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). + else if(href_list["rename"]) + if(!check_rights(R_VAREDIT)) return + + var/mob/M = locate(href_list["rename"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - var/new_name = copytext(sanitize(input(usr,"What would you like to name this mob?","Input a name",M.real_name) as text|null),1,MAX_NAME_LEN) - if( !new_name || !M ) return - - message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") - M.fully_replace_character_name(M.real_name,new_name) - href_list["datumrefresh"] = href_list["rename"] - - else if(href_list["varnameedit"] && href_list["datumedit"]) - if(!check_rights(R_VAREDIT)) return - - var/D = locate(href_list["datumedit"]) - if(!istype(D,/datum) && !istype(D,/client)) + return + + var/new_name = copytext(sanitize(input(usr,"What would you like to name this mob?","Input a name",M.real_name) as text|null),1,MAX_NAME_LEN) + if( !new_name || !M ) return + + message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") + M.fully_replace_character_name(M.real_name,new_name) + href_list["datumrefresh"] = href_list["rename"] + + else if(href_list["varnameedit"] && href_list["datumedit"]) + if(!check_rights(R_VAREDIT)) return + + var/D = locate(href_list["datumedit"]) + if(!istype(D,/datum) && !istype(D,/client)) to_chat(usr, "This can only be used on instances of types /client or /datum") - return - - modify_variables(D, href_list["varnameedit"], 1) - - else if(href_list["togbit"]) - if(!check_rights(R_VAREDIT)) return - - var/atom/D = locate(href_list["subject"]) - if(!istype(D,/datum) && !istype(D,/client)) + return + + modify_variables(D, href_list["varnameedit"], 1) + + else if(href_list["togbit"]) + if(!check_rights(R_VAREDIT)) return + + var/atom/D = locate(href_list["subject"]) + if(!istype(D,/datum) && !istype(D,/client)) to_chat(usr, "This can only be used on instances of types /client or /datum") - return - if(!(href_list["var"] in D.vars)) + return + if(!(href_list["var"] in D.vars)) to_chat(usr, "Unable to find variable specified.") - return - var/value = D.vars[href_list["var"]] + return + var/value = D.vars[href_list["var"]] value ^= 1 << text2num(href_list["togbit"]) - D.vars[href_list["var"]] = value - - else if(href_list["varnamechange"] && href_list["datumchange"]) - if(!check_rights(R_VAREDIT)) return - - var/D = locate(href_list["datumchange"]) - if(!istype(D,/datum) && !istype(D,/client)) + D.vars[href_list["var"]] = value + + else if(href_list["varnamechange"] && href_list["datumchange"]) + if(!check_rights(R_VAREDIT)) return + + var/D = locate(href_list["datumchange"]) + if(!istype(D,/datum) && !istype(D,/client)) to_chat(usr, "This can only be used on instances of types /client or /datum") - return - - modify_variables(D, href_list["varnamechange"], 0) - - else if(href_list["varnamemass"] && href_list["datummass"]) - if(!check_rights(R_VAREDIT)) return - - var/atom/A = locate(href_list["datummass"]) - if(!istype(A)) + return + + modify_variables(D, href_list["varnamechange"], 0) + + else if(href_list["varnamemass"] && href_list["datummass"]) + if(!check_rights(R_VAREDIT)) return + + var/atom/A = locate(href_list["datummass"]) + if(!istype(A)) to_chat(usr, "This can only be used on instances of type /atom") - return - - cmd_mass_modify_object_variables(A, href_list["varnamemass"]) - - else if(href_list["mob_player_panel"]) - if(!check_rights(0)) return - - var/mob/M = locate(href_list["mob_player_panel"]) - if(!istype(M)) + return + + cmd_mass_modify_object_variables(A, href_list["varnamemass"]) + + else if(href_list["mob_player_panel"]) + if(!check_rights(0)) return + + var/mob/M = locate(href_list["mob_player_panel"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - src.holder.show_player_panel(M) - href_list["datumrefresh"] = href_list["mob_player_panel"] - - else if(href_list["give_spell"]) - if(!check_rights(R_ADMIN|R_FUN)) return - - var/mob/M = locate(href_list["give_spell"]) - if(!istype(M)) + return + + src.holder.show_player_panel(M) + href_list["datumrefresh"] = href_list["mob_player_panel"] + + else if(href_list["give_spell"]) + if(!check_rights(R_ADMIN|R_FUN)) return + + var/mob/M = locate(href_list["give_spell"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_spell(M) - href_list["datumrefresh"] = href_list["give_spell"] - - else if(href_list["give_disease"]) - if(!check_rights(R_ADMIN|R_FUN)) return - - var/mob/M = locate(href_list["give_disease"]) - if(!istype(M)) + return + + src.give_spell(M) + href_list["datumrefresh"] = href_list["give_spell"] + + else if(href_list["give_disease"]) + if(!check_rights(R_ADMIN|R_FUN)) return + + var/mob/M = locate(href_list["give_disease"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_disease(M) - href_list["datumrefresh"] = href_list["give_spell"] - - else if(href_list["godmode"]) - if(!check_rights(R_REJUVINATE)) return - - var/mob/M = locate(href_list["godmode"]) - if(!istype(M)) + return + + src.give_disease(M) + href_list["datumrefresh"] = href_list["give_spell"] + + else if(href_list["godmode"]) + if(!check_rights(R_REJUVINATE)) return + + var/mob/M = locate(href_list["godmode"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_godmode(M) - href_list["datumrefresh"] = href_list["godmode"] - - else if(href_list["gib"]) - if(!check_rights(0)) return - - var/mob/M = locate(href_list["gib"]) - if(!istype(M)) + return + + src.cmd_admin_godmode(M) + href_list["datumrefresh"] = href_list["godmode"] + + else if(href_list["gib"]) + if(!check_rights(0)) return + + var/mob/M = locate(href_list["gib"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_gib(M) - - else if(href_list["build_mode"]) - if(!check_rights(R_BUILDMODE)) return - - var/mob/M = locate(href_list["build_mode"]) - if(!istype(M)) + return + + src.cmd_admin_gib(M) + + else if(href_list["build_mode"]) + if(!check_rights(R_BUILDMODE)) return + + var/mob/M = locate(href_list["build_mode"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - togglebuildmode(M) - href_list["datumrefresh"] = href_list["build_mode"] - - else if(href_list["drop_everything"]) - if(!check_rights(R_DEBUG|R_ADMIN)) return - - var/mob/M = locate(href_list["drop_everything"]) - if(!istype(M)) + return + + togglebuildmode(M) + href_list["datumrefresh"] = href_list["build_mode"] + + else if(href_list["drop_everything"]) + if(!check_rights(R_DEBUG|R_ADMIN)) return + + var/mob/M = locate(href_list["drop_everything"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - if(usr.client) - usr.client.cmd_admin_drop_everything(M) - - else if(href_list["direct_control"]) - if(!check_rights(0)) return - - var/mob/M = locate(href_list["direct_control"]) - if(!istype(M)) + return + + if(usr.client) + usr.client.cmd_admin_drop_everything(M) + + else if(href_list["direct_control"]) + if(!check_rights(0)) return + + var/mob/M = locate(href_list["direct_control"]) + if(!istype(M)) to_chat(usr, "This can only be used on instances of type /mob") - return - - if(usr.client) - usr.client.cmd_assume_direct_control(M) - - else if(href_list["make_skeleton"]) - if(!check_rights(R_FUN)) return - - var/mob/living/carbon/human/H = locate(href_list["make_skeleton"]) - if(!istype(H)) + return + + if(usr.client) + usr.client.cmd_assume_direct_control(M) + + else if(href_list["make_skeleton"]) + if(!check_rights(R_FUN)) return + + var/mob/living/carbon/human/H = locate(href_list["make_skeleton"]) + if(!istype(H)) to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - H.makeSkeleton() - href_list["datumrefresh"] = href_list["make_skeleton"] - - else if(href_list["delall"]) - if(!check_rights(R_DEBUG|R_SERVER)) return - - var/obj/O = locate(href_list["delall"]) - if(!isobj(O)) + return + + H.makeSkeleton() + href_list["datumrefresh"] = href_list["make_skeleton"] + + else if(href_list["delall"]) + if(!check_rights(R_DEBUG|R_SERVER)) return + + var/obj/O = locate(href_list["delall"]) + if(!isobj(O)) to_chat(usr, "This can only be used on instances of type /obj") - return - - var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") - if(action_type == "Cancel" || !action_type) - return - - if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes") - return - - if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes") - return - - var/O_type = O.type - switch(action_type) - if("Strict type") - var/i = 0 - for(var/obj/Obj in world) - if(Obj.type == O_type) - i++ - qdel(Obj) - if(!i) + return + + var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") + if(action_type == "Cancel" || !action_type) + return + + if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes") + return + + if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes") + return + + var/O_type = O.type + switch(action_type) + if("Strict type") + var/i = 0 + for(var/obj/Obj in world) + if(Obj.type == O_type) + i++ + qdel(Obj) + if(!i) to_chat(usr, "No objects of this type exist") - return - log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") - message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") - if("Type and subtypes") - var/i = 0 - for(var/obj/Obj in world) - if(istype(Obj,O_type)) - i++ - qdel(Obj) - if(!i) + return + log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + if("Type and subtypes") + var/i = 0 + for(var/obj/Obj in world) + if(istype(Obj,O_type)) + i++ + qdel(Obj) + if(!i) to_chat(usr, "No objects of this type exist") - return - log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") - message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") - - else if(href_list["explode"]) - if(!check_rights(R_DEBUG|R_FUN)) return - - var/atom/A = locate(href_list["explode"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) + return + log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + + else if(href_list["explode"]) + if(!check_rights(R_DEBUG|R_FUN)) return + + var/atom/A = locate(href_list["explode"]) + if(!isobj(A) && !ismob(A) && !isturf(A)) to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") - return - - src.cmd_admin_explosion(A) - href_list["datumrefresh"] = href_list["explode"] - - else if(href_list["emp"]) - if(!check_rights(R_DEBUG|R_FUN)) return - - var/atom/A = locate(href_list["emp"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) + return + + src.cmd_admin_explosion(A) + href_list["datumrefresh"] = href_list["explode"] + + else if(href_list["emp"]) + if(!check_rights(R_DEBUG|R_FUN)) return + + var/atom/A = locate(href_list["emp"]) + if(!isobj(A) && !ismob(A) && !isturf(A)) to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") - return - - src.cmd_admin_emp(A) - href_list["datumrefresh"] = href_list["emp"] - - else if(href_list["mark_object"]) - if(!check_rights(0)) return - - var/datum/D = locate(href_list["mark_object"]) - if(!istype(D)) + return + + src.cmd_admin_emp(A) + href_list["datumrefresh"] = href_list["emp"] + + else if(href_list["mark_object"]) + if(!check_rights(0)) return + + var/datum/D = locate(href_list["mark_object"]) + if(!istype(D)) to_chat(usr, "This can only be done to instances of type /datum") - return - - src.holder.marked_datum = D - href_list["datumrefresh"] = href_list["mark_object"] - - else if(href_list["teleport_here"]) - if(!check_rights(0)) return - - var/atom/movable/A = locate(href_list["teleport_here"]) - if(!istype(A)) + return + + src.holder.marked_datum = D + href_list["datumrefresh"] = href_list["mark_object"] + + else if(href_list["teleport_here"]) + if(!check_rights(0)) return + + var/atom/movable/A = locate(href_list["teleport_here"]) + if(!istype(A)) to_chat(usr, "This can only be done to instances of movable atoms.") - return - - var/turf/T = get_turf(usr) - if(istype(A,/mob)) - var/mob/M = A - M.teleport_to(T) - else - A.forceMove(T) - switch(teleport_here_pref) - if("Flashy") - if(flashy_level > 0) - T.turf_animation('icons/effects/96x96.dmi',"beamin",-32,0,MOB_LAYER+1,'sound/weapons/emitter2.ogg') - if(flashy_level > 1) - for(var/mob/M in range(T,7)) - shake_camera(M, 4, 1) - if(flashy_level > 2) + return + + var/turf/T = get_turf(usr) + if(istype(A,/mob)) + var/mob/M = A + M.teleport_to(T) + else + A.forceMove(T) + switch(teleport_here_pref) + if("Flashy") + if(flashy_level > 0) + T.turf_animation('icons/effects/96x96.dmi',"beamin",-32,0,MOB_LAYER+1,'sound/weapons/emitter2.ogg') + if(flashy_level > 1) + for(var/mob/M in range(T,7)) + shake_camera(M, 4, 1) + if(flashy_level > 2) to_chat(world, "[uppertext(A.name)] HAS RISEN") - if("Stealthy") - A.alpha = 0 - animate(A, alpha = 255, time = stealthy_level) - - else if(href_list["teleport_to"]) - if(!check_rights(0)) return - - var/mob/user = usr - if(!istype(user)) - return - - var/atom/A = locate(href_list["teleport_to"]) - if(!istype(A)) + if("Stealthy") + A.alpha = 0 + animate(A, alpha = 255, time = stealthy_level) + + else if(href_list["teleport_to"]) + if(!check_rights(0)) return + + var/mob/user = usr + if(!istype(user)) + return + + var/atom/A = locate(href_list["teleport_to"]) + if(!istype(A)) to_chat(user, "This can only be done to instances of atoms.") - return - - user.teleport_to(A) - - else if(href_list["delete"]) - if(!check_rights(0)) return - - var/atom/movable/A = locate(href_list["delete"]) - if(!istype(A)) + return + + user.teleport_to(A) + + else if(href_list["delete"]) + if(!check_rights(0)) return + + var/atom/movable/A = locate(href_list["delete"]) + if(!istype(A)) to_chat(usr, "This can only be done to instances of movable atoms.") - return - - if(ismob(A)) - var/mob/M = A - if(M.client) - if(alert("You sure?","Confirm","Yes","No") != "Yes") - return - - log_admin("[key_name(usr)] deleted [A] at ([A.x],[A.y],[A.z])") - message_admins("[key_name(usr)] deleted [A] at ([A.x],[A.y],[A.z])") - qdel(A) - - else if(href_list["rotatedatum"]) - if(!check_rights(0)) return - - var/atom/A = locate(href_list["rotatedatum"]) - if(!istype(A)) + return + + if(ismob(A)) + var/mob/M = A + if(M.client) + if(alert("You sure?","Confirm","Yes","No") != "Yes") + return + + log_admin("[key_name(usr)] deleted [A] at ([A.x],[A.y],[A.z])") + message_admins("[key_name(usr)] deleted [A] at ([A.x],[A.y],[A.z])") + qdel(A) + + else if(href_list["rotatedatum"]) + if(!check_rights(0)) return + + var/atom/A = locate(href_list["rotatedatum"]) + if(!istype(A)) to_chat(usr, "This can only be done to instances of type /atom") - return - - switch(href_list["rotatedir"]) - if("right") A.dir = turn(A.dir, -45) - if("left") A.dir = turn(A.dir, 45) - href_list["datumrefresh"] = href_list["rotatedatum"] - - else if(href_list["makemonkey"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makemonkey"]) - if(!istype(H)) + return + + switch(href_list["rotatedir"]) + if("right") A.dir = turn(A.dir, -45) + if("left") A.dir = turn(A.dir, 45) + href_list["datumrefresh"] = href_list["rotatedatum"] + + else if(href_list["makemonkey"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makemonkey"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return - if(!H) + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("monkeyone"=href_list["makemonkey"])) - - else if(href_list["makerobot"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makerobot"]) - if(!istype(H)) + return + holder.Topic(href, list("monkeyone"=href_list["makemonkey"])) + + else if(href_list["makerobot"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makerobot"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return - if(!H) + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makerobot"=href_list["makerobot"])) - - else if(href_list["makealien"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makealien"]) - if(!istype(H)) + return + holder.Topic(href, list("makerobot"=href_list["makerobot"])) + + else if(href_list["makealien"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makealien"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return - if(!H) + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makealien"=href_list["makealien"])) - - else if(href_list["makeslime"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makeslime"]) - if(!istype(H)) + return + holder.Topic(href, list("makealien"=href_list["makealien"])) + + else if(href_list["makeslime"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makeslime"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return - if(!H) + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeslime"=href_list["makeslime"])) - - else if(href_list["makeai"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makeai"]) - if(!istype(H)) + return + holder.Topic(href, list("makeslime"=href_list["makeslime"])) + + else if(href_list["makeai"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makeai"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return - if(!H) + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeai"=href_list["makeai"])) - - else if(href_list["setmutantrace"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["setmutantrace"]) - if(!istype(H)) + return + holder.Topic(href, list("makeai"=href_list["makeai"])) + + else if(href_list["setmutantrace"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["setmutantrace"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - var/new_mutantrace = input("Please choose a new mutantrace","Mutantrace",null) as null|anything in list("NONE","golem","lizard","slime","plant","shadow","tajaran","skrell","vox") - switch(new_mutantrace) - if(null) - return - if("NONE") - new_mutantrace = "" - if(!H) + return + + var/new_mutantrace = input("Please choose a new mutantrace","Mutantrace",null) as null|anything in list("NONE","golem","lizard","slime","plant","shadow","tajaran","skrell","vox") + switch(new_mutantrace) + if(null) + return + if("NONE") + new_mutantrace = "" + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - if(H.dna) - H.dna.mutantrace = new_mutantrace - H.update_mutantrace() - - else if(href_list["setspecies"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["setspecies"]) - if(!istype(H)) + return + if(H.dna) + H.dna.mutantrace = new_mutantrace + H.update_mutantrace() + + else if(href_list["setspecies"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["setspecies"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - var/new_species = input("Please choose a new species.","Species",null) as null|anything in all_species - - if(!H) + return + + var/new_species = input("Please choose a new species.","Species",null) as null|anything in all_species + + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - - if(H.set_species(new_species)) + return + + if(H.set_species(new_species)) to_chat(usr, "Set species of [H] to [H.species].") - H.regenerate_icons() - else + H.regenerate_icons() + else to_chat(usr, "Failed! Something went wrong.") - - else if(href_list["addlanguage"]) - if(!check_rights(R_SPAWN)) return - - var/mob/H = locate(href_list["addlanguage"]) - if(!istype(H)) + + else if(href_list["addlanguage"]) + if(!check_rights(R_SPAWN)) return + + var/mob/H = locate(href_list["addlanguage"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob") - return - - var/new_language = input("Please choose a language to add.","Language",null) as null|anything in all_languages - - if(!new_language) - return - - if(!H) + return + + var/new_language = input("Please choose a language to add.","Language",null) as null|anything in all_languages + + if(!new_language) + return + + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - - if(H.add_language(new_language)) + return + + if(H.add_language(new_language)) to_chat(usr, "Added [new_language] to [H].") - else + else to_chat(usr, "Mob already knows that language.") - - else if(href_list["remlanguage"]) - if(!check_rights(R_SPAWN)) return - - var/mob/H = locate(href_list["remlanguage"]) - if(!istype(H)) + + else if(href_list["remlanguage"]) + if(!check_rights(R_SPAWN)) return + + var/mob/H = locate(href_list["remlanguage"]) + if(!istype(H)) to_chat(usr, "This can only be done to instances of type /mob") - return - - if(!H.languages.len) + return + + if(!H.languages.len) to_chat(usr, "This mob knows no languages.") - return - - var/datum/language/rem_language = input("Please choose a language to remove.","Language",null) as null|anything in H.languages - - if(!rem_language) - return - - if(!H) + return + + var/datum/language/rem_language = input("Please choose a language to remove.","Language",null) as null|anything in H.languages + + if(!rem_language) + return + + if(!H) to_chat(usr, "Mob doesn't exist anymore") - return - - if(H.remove_language(rem_language.name)) + return + + if(H.remove_language(rem_language.name)) to_chat(usr, "Removed [rem_language] from [H].") - else + else to_chat(usr, "Mob doesn't know that language.") - - else if(href_list["regenerateicons"]) - if(!check_rights(0)) return - - var/mob/M = locate(href_list["regenerateicons"]) - if(!ismob(M)) + + else if(href_list["regenerateicons"]) + if(!check_rights(0)) return + + var/mob/M = locate(href_list["regenerateicons"]) + if(!ismob(M)) to_chat(usr, "This can only be done to instances of type /mob") - return - M.regenerate_icons() - - else if(href_list["adjustDamage"] && href_list["mobToDamage"]) - if(!check_rights(R_DEBUG|R_ADMIN|R_FUN)) return - - var/mob/living/L = locate(href_list["mobToDamage"]) - if(!istype(L)) return - - var/Text = href_list["adjustDamage"] - - var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num - - if(!L) + return + M.regenerate_icons() + + else if(href_list["adjustDamage"] && href_list["mobToDamage"]) + if(!check_rights(R_DEBUG|R_ADMIN|R_FUN)) return + + var/mob/living/L = locate(href_list["mobToDamage"]) + if(!istype(L)) return + + var/Text = href_list["adjustDamage"] + + var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num + + if(!L) to_chat(usr, "Mob doesn't exist anymore") - return - - switch(Text) - if("brute") L.adjustBruteLoss(amount) - if("fire") L.adjustFireLoss(amount) - if("toxin") L.adjustToxLoss(amount) - if("oxygen")L.adjustOxyLoss(amount) - if("brain") L.adjustBrainLoss(amount) - if("clone") L.adjustCloneLoss(amount) - else + return + + switch(Text) + if("brute") L.adjustBruteLoss(amount) + if("fire") L.adjustFireLoss(amount) + if("toxin") L.adjustToxLoss(amount) + if("oxygen")L.adjustOxyLoss(amount) + if("brain") L.adjustBrainLoss(amount) + if("clone") L.adjustCloneLoss(amount) + else to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") - return - - if(amount != 0) - log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") - message_admins("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") - href_list["datumrefresh"] = href_list["mobToDamage"] - - else if(href_list["datumrefresh"]) - var/datum/DAT = locate(href_list["datumrefresh"]) - if(!istype(DAT, /datum)) - return - src.debug_variables(DAT) - - else if(href_list["proc_call"]) - if(!check_rights(R_DEBUG)) - return - - var/datum/DAT = locate(href_list["proc_call"]) - if(!DAT) - return - - callatomproc(DAT) //Yes it could be a datum, technically but eh - - return + return + + if(amount != 0) + log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") + message_admins("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") + href_list["datumrefresh"] = href_list["mobToDamage"] + + else if(href_list["datumrefresh"]) + var/datum/DAT = locate(href_list["datumrefresh"]) + if(!istype(DAT, /datum)) + return + src.debug_variables(DAT) + + else if(href_list["proc_call"]) + if(!check_rights(R_DEBUG)) + return + + var/datum/DAT = locate(href_list["proc_call"]) + if(!DAT) + return + + callatomproc(DAT) //Yes it could be a datum, technically but eh + + return diff --git a/code/datums/disease.dm b/code/datums/disease.dm index 4d7f31659a0..63ab29a31df 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -1,213 +1,213 @@ -#define SPECIAL -1 -#define NON_CONTAGIOUS 0 -#define BLOOD 1 -#define CONTACT_FEET 2 -#define CONTACT_HANDS 3 -#define CONTACT_GENERAL 4 -#define AIRBORNE 5 - -#define SCANNER 1 -#define PANDEMIC 2 - -/* - -IMPORTANT NOTE: Please delete the diseases by using cure() proc or del() instruction. -Diseases are referenced in a global list, so simply setting mob or obj vars -to null does not delete the object itself. Thank you. - -*/ - -var/list/diseases = typesof(/datum/disease) - /datum/disease - - -/datum/disease - var/form = "Virus" //During medscans, what the disease is referred to as - var/name = "No disease" - var/stage = 1 //all diseases start at stage 1 - var/max_stages = 0.0 - var/cure = null - var/cure_id = null// reagent.id or list containing them - var/cure_list = null // allows for multiple possible cure combinations - var/cure_chance = 8//chance for the cure to do its job - var/spread = null //spread type description - var/initial_spread = null - var/spread_type = AIRBORNE - var/contagious_period = 0//the disease stage when it can be spread - var/list/affected_species = list() - var/mob/living/carbon/affected_mob = null //the mob which is affected by disease. - var/holder = null //the atom containing the disease (mob or obj) - var/carrier = 0.0 //there will be a small chance that the person will be a carrier - var/curable = 0 //can this disease be cured? (By itself...) - var/list/strain_data = list() //This is passed on to infectees - var/stage_prob = 4 // probability of advancing to next stage, default 4% per check - var/agent = "some microbes"//name of the disease agent - var/permeability_mod = 1//permeability modifier coefficient. - var/desc = null//description. Leave it null and this disease won't show in med records. - var/severity = null//severity descr - var/longevity = 150//time in "ticks" the virus stays in inanimate object (blood stains, corpses, etc). In syringes, bottles and beakers it stays infinitely. - var/list/hidden = list(0, 0) - var/can_carry = 1 // If the disease allows "carriers". - var/age = 0 // age of the disease in the current mob - var/stage_minimum_age = 0 // how old the disease must be to advance per stage - // if hidden[1] is true, then virus is hidden from medical scanners - // if hidden[2] is true, then virus is hidden from PANDEMIC machine - -/datum/disease/proc/stage_act() - age++ - var/cure_present = has_cure() +#define SPECIAL -1 +#define NON_CONTAGIOUS 0 +#define BLOOD 1 +#define CONTACT_FEET 2 +#define CONTACT_HANDS 3 +#define CONTACT_GENERAL 4 +#define AIRBORNE 5 + +#define SCANNER 1 +#define PANDEMIC 2 + +/* + +IMPORTANT NOTE: Please delete the diseases by using cure() proc or del() instruction. +Diseases are referenced in a global list, so simply setting mob or obj vars +to null does not delete the object itself. Thank you. + +*/ + +var/list/diseases = typesof(/datum/disease) - /datum/disease + + +/datum/disease + var/form = "Virus" //During medscans, what the disease is referred to as + var/name = "No disease" + var/stage = 1 //all diseases start at stage 1 + var/max_stages = 0.0 + var/cure = null + var/cure_id = null// reagent.id or list containing them + var/cure_list = null // allows for multiple possible cure combinations + var/cure_chance = 8//chance for the cure to do its job + var/spread = null //spread type description + var/initial_spread = null + var/spread_type = AIRBORNE + var/contagious_period = 0//the disease stage when it can be spread + var/list/affected_species = list() + var/mob/living/carbon/affected_mob = null //the mob which is affected by disease. + var/holder = null //the atom containing the disease (mob or obj) + var/carrier = 0.0 //there will be a small chance that the person will be a carrier + var/curable = 0 //can this disease be cured? (By itself...) + var/list/strain_data = list() //This is passed on to infectees + var/stage_prob = 4 // probability of advancing to next stage, default 4% per check + var/agent = "some microbes"//name of the disease agent + var/permeability_mod = 1//permeability modifier coefficient. + var/desc = null//description. Leave it null and this disease won't show in med records. + var/severity = null//severity descr + var/longevity = 150//time in "ticks" the virus stays in inanimate object (blood stains, corpses, etc). In syringes, bottles and beakers it stays infinitely. + var/list/hidden = list(0, 0) + var/can_carry = 1 // If the disease allows "carriers". + var/age = 0 // age of the disease in the current mob + var/stage_minimum_age = 0 // how old the disease must be to advance per stage + // if hidden[1] is true, then virus is hidden from medical scanners + // if hidden[2] is true, then virus is hidden from PANDEMIC machine + +/datum/disease/proc/stage_act() + age++ + var/cure_present = has_cure() // to_chat(world, "[cure_present]") - - if(carrier&&!cure_present) + + if(carrier&&!cure_present) // to_chat(world, "[affected_mob] is carrier") - return - - spread = (cure_present?"Remissive":initial_spread) - if(stage > max_stages) - stage = max_stages - - if(!cure_present && prob(stage_prob) && age > stage_minimum_age) //now the disease shouldn't get back up to stage 4 in no time - stage = min(stage + 1, max_stages) - age = 0 - - else if(cure_present && prob(cure_chance)) - stage = max(stage - 1, 1) - - if(stage <= 1 && ((prob(1) && curable) || (cure_present && prob(cure_chance)))) - cure() - return - return - -/datum/disease/proc/has_cure()//check if affected_mob has required reagents. - if(!cure_id) return 0 - var/result = 1 - if(cure_list == list(cure_id)) - if(istype(cure_id, /list)) - for(var/C_id in cure_id) - if(!affected_mob.reagents.has_reagent(C_id)) - result = 0 - else if(!affected_mob.reagents.has_reagent(cure_id)) - result = 0 - else - for(var/C_list in cure_list) - if(istype(C_list, /list)) - for(var/C_id in cure_id) - if(affected_mob.reagents != null) - result = 0 - else if(!affected_mob.reagents.has_reagent(C_id)) - result = 0 - else if(affected_mob.reagents != null) - if(!affected_mob.reagents.has_reagent(C_list)) - result = 0 - - return result - -/datum/disease/proc/spread_by_touch() - switch(spread_type) - if(CONTACT_FEET, CONTACT_HANDS, CONTACT_GENERAL) - return 1 - return 0 - -/datum/disease/proc/spread(var/atom/source=null, var/airborne_range = 2, var/force_spread) + return + + spread = (cure_present?"Remissive":initial_spread) + if(stage > max_stages) + stage = max_stages + + if(!cure_present && prob(stage_prob) && age > stage_minimum_age) //now the disease shouldn't get back up to stage 4 in no time + stage = min(stage + 1, max_stages) + age = 0 + + else if(cure_present && prob(cure_chance)) + stage = max(stage - 1, 1) + + if(stage <= 1 && ((prob(1) && curable) || (cure_present && prob(cure_chance)))) + cure() + return + return + +/datum/disease/proc/has_cure()//check if affected_mob has required reagents. + if(!cure_id) return 0 + var/result = 1 + if(cure_list == list(cure_id)) + if(istype(cure_id, /list)) + for(var/C_id in cure_id) + if(!affected_mob.reagents.has_reagent(C_id)) + result = 0 + else if(!affected_mob.reagents.has_reagent(cure_id)) + result = 0 + else + for(var/C_list in cure_list) + if(istype(C_list, /list)) + for(var/C_id in cure_id) + if(affected_mob.reagents != null) + result = 0 + else if(!affected_mob.reagents.has_reagent(C_id)) + result = 0 + else if(affected_mob.reagents != null) + if(!affected_mob.reagents.has_reagent(C_list)) + result = 0 + + return result + +/datum/disease/proc/spread_by_touch() + switch(spread_type) + if(CONTACT_FEET, CONTACT_HANDS, CONTACT_GENERAL) + return 1 + return 0 + +/datum/disease/proc/spread(var/atom/source=null, var/airborne_range = 2, var/force_spread) // to_chat(world, "Disease [src] proc spread was called from holder [source]") - - // If we're overriding how we spread, say so here - var/how_spread = spread_type - if(!istype(affected_mob)) - return 0 - if(force_spread) - how_spread = force_spread - - if(how_spread == SPECIAL || how_spread == NON_CONTAGIOUS || how_spread == BLOOD)//does not spread - return - - if(stage < contagious_period) //the disease is not contagious at this stage - return - - if(!source)//no holder specified - if(affected_mob)//no mob affected holder - source = affected_mob - else //no source and no mob affected. Rogue disease. Break - return - if(affected_mob.reagents != null) - if(affected_mob) - if(affected_mob.reagents.has_reagent("spaceacillin")) - return // Don't spread if we have spaceacillin in our system. - - var/check_range = airborne_range//defaults to airborne - range 2 - - if(how_spread != AIRBORNE && how_spread != SPECIAL) - check_range = 1 // everything else, like infect-on-contact things, only infect things on top of it - - if(isturf(source.loc)) - for(var/mob/living/carbon/M in oview(check_range, source)) - if(isturf(M.loc)) - if(AStar(source.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, check_range)) - M.contract_disease(src, 0, 1, force_spread) - - return - - -/datum/disease/proc/process() - if(!holder) - active_diseases -= src - return - if(prob(65)) - spread(holder) - - if(affected_mob) - for(var/datum/disease/D in affected_mob.viruses) - if(D != src) - if(IsSame(D)) - //error("Deleting [D.name] because it's the same as [src.name].") - del(D) // if there are somehow two viruses of the same kind in the system, delete the other one - - if(holder == affected_mob) - if(affected_mob.stat != DEAD) //he's alive - stage_act() - else //he's dead. - if(spread_type!=SPECIAL) - spread_type = CONTACT_GENERAL - affected_mob = null - if(!affected_mob) //the virus is in inanimate obj + + // If we're overriding how we spread, say so here + var/how_spread = spread_type + if(!istype(affected_mob)) + return 0 + if(force_spread) + how_spread = force_spread + + if(how_spread == SPECIAL || how_spread == NON_CONTAGIOUS || how_spread == BLOOD)//does not spread + return + + if(stage < contagious_period) //the disease is not contagious at this stage + return + + if(!source)//no holder specified + if(affected_mob)//no mob affected holder + source = affected_mob + else //no source and no mob affected. Rogue disease. Break + return + if(affected_mob.reagents != null) + if(affected_mob) + if(affected_mob.reagents.has_reagent("spaceacillin")) + return // Don't spread if we have spaceacillin in our system. + + var/check_range = airborne_range//defaults to airborne - range 2 + + if(how_spread != AIRBORNE && how_spread != SPECIAL) + check_range = 1 // everything else, like infect-on-contact things, only infect things on top of it + + if(isturf(source.loc)) + for(var/mob/living/carbon/M in oview(check_range, source)) + if(isturf(M.loc)) + if(AStar(source.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, check_range)) + M.contract_disease(src, 0, 1, force_spread) + + return + + +/datum/disease/proc/process() + if(!holder) + active_diseases -= src + return + if(prob(65)) + spread(holder) + + if(affected_mob) + for(var/datum/disease/D in affected_mob.viruses) + if(D != src) + if(IsSame(D)) + //error("Deleting [D.name] because it's the same as [src.name].") + del(D) // if there are somehow two viruses of the same kind in the system, delete the other one + + if(holder == affected_mob) + if(affected_mob.stat != DEAD) //he's alive + stage_act() + else //he's dead. + if(spread_type!=SPECIAL) + spread_type = CONTACT_GENERAL + affected_mob = null + if(!affected_mob) //the virus is in inanimate obj // to_chat(world, "[src] longevity = [longevity]") - - if(prob(70)) - if(--longevity<=0) - cure(0) - return - -/datum/disease/proc/cure(var/resistance=1)//if resistance = 0, the mob won't develop resistance to disease - if(affected_mob) - if(resistance && !(type in affected_mob.resistances)) - var/saved_type = "[type]" - affected_mob.resistances += text2path(saved_type) - /*if(istype(src, /datum/disease/alien_embryo)) //Get rid of the infection flag if it's a xeno embryo. - affected_mob.status_flags &= ~(XENO_HOST)*/ - affected_mob.viruses -= src //remove the datum from the list - del(src) //delete the datum to stop it processing - return - -/datum/disease/Del() - active_diseases -= src - if(affected_mob) - affected_mob.viruses -= src - ..() - -/datum/disease/New(var/process=1, var/datum/disease/D)//process = 1 - adding the object to global list. List is processed by master controller. - cure_list = list(cure_id) // to add more cures, add more vars to this list in the actual disease's New() - if(process) // Viruses in list are considered active. - active_diseases += src - initial_spread = spread - -/datum/disease/proc/IsSame(var/datum/disease/D) - if(istype(src, D.type)) - return 1 - return 0 - -/datum/disease/proc/Copy(var/process = 0) - return new type(process, src) - -/* -/datum/disease/Destroy() - active_diseases.Remove(src) -*/ + + if(prob(70)) + if(--longevity<=0) + cure(0) + return + +/datum/disease/proc/cure(var/resistance=1)//if resistance = 0, the mob won't develop resistance to disease + if(affected_mob) + if(resistance && !(type in affected_mob.resistances)) + var/saved_type = "[type]" + affected_mob.resistances += text2path(saved_type) + /*if(istype(src, /datum/disease/alien_embryo)) //Get rid of the infection flag if it's a xeno embryo. + affected_mob.status_flags &= ~(XENO_HOST)*/ + affected_mob.viruses -= src //remove the datum from the list + del(src) //delete the datum to stop it processing + return + +/datum/disease/Del() + active_diseases -= src + if(affected_mob) + affected_mob.viruses -= src + ..() + +/datum/disease/New(var/process=1, var/datum/disease/D)//process = 1 - adding the object to global list. List is processed by master controller. + cure_list = list(cure_id) // to add more cures, add more vars to this list in the actual disease's New() + if(process) // Viruses in list are considered active. + active_diseases += src + initial_spread = spread + +/datum/disease/proc/IsSame(var/datum/disease/D) + if(istype(src, D.type)) + return 1 + return 0 + +/datum/disease/proc/Copy(var/process = 0) + return new type(process, src) + +/* +/datum/disease/Destroy() + active_diseases.Remove(src) +*/ diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 94a4d1e3a84..358a336f3c7 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -1,430 +1,430 @@ -/* - - Advance Disease is a system for Virologist to Engineer their own disease with symptoms that have effects and properties - which add onto the overall disease. - - If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus. - -*/ - -#define RANDOM_STARTING_LEVEL 2 - -var/list/archive_diseases = list() - -// The order goes from easy to cure to hard to cure. -var/list/advance_cures = list( - "nutriment", "sugar", "orangejuice", - "spaceacillin", "kelotane", "ethanol", - "leporazine", "synaptizine", "lipozine", - "silver", "gold", "plasma" - ) - -/* - - PROPERTIES - - */ - -/datum/disease/advance - - name = "Unknown" // We will always let our Virologist name our disease. - desc = "An engineered disease which can contain a multitude of symptoms." - form = "Advance Disease" // Will let med-scanners know that this disease was engineered. - agent = "advance microbes" - max_stages = 5 - spread = "Unknown" - affected_species = list("Human","Monkey") - - // NEW VARS - - var/list/symptoms = list() // The symptoms of the disease. - var/id = "" - var/processing = 0 - -/* - - OLD PROCS - - */ - -/datum/disease/advance/New(var/process = 1, var/datum/disease/advance/D) - - // Setup our dictionary if it hasn't already. - if(!dictionary_symptoms.len) - for(var/symp in list_symptoms) - var/datum/symptom/S = new symp - dictionary_symptoms[S.id] = symp - - if(!istype(D)) - D = null - // Generate symptoms if we weren't given any. - - if(!symptoms || !symptoms.len) - - if(!D || !D.symptoms || !D.symptoms.len) - symptoms = GenerateSymptoms() - else - for(var/datum/symptom/S in D.symptoms) - symptoms += new S.type - - Refresh() - ..(process, D) - return - -/datum/disease/advance/Del() - if(processing) - for(var/datum/symptom/S in symptoms) - S.End(src) - ..() - -// Randomly pick a symptom to activate. -/datum/disease/advance/stage_act() - ..() - if(symptoms && symptoms.len) - - if(!processing) - processing = 1 - for(var/datum/symptom/S in symptoms) - S.Start(src) - - for(var/datum/symptom/S in symptoms) - S.Activate(src) - else - CRASH("We do not have any symptoms during stage_act()!") - -// Compares type then ID. -/datum/disease/advance/IsSame(var/datum/disease/advance/D) - - if(!(istype(D, /datum/disease/advance))) - return 0 - - if(src.GetDiseaseID() != D.GetDiseaseID()) - return 0 - return 1 - -// To add special resistances. -/datum/disease/advance/cure(var/resistance=1) - if(affected_mob) - var/id = "[GetDiseaseID()]" - if(resistance && !(id in affected_mob.resistances)) - affected_mob.resistances[id] = id - affected_mob.viruses -= src //remove the datum from the list - del(src) //delete the datum to stop it processing - return - -// Returns the advance disease with a different reference memory. -/datum/disease/advance/Copy(var/process = 0) - return new /datum/disease/advance(process, src, 1) - -/* - - NEW PROCS - - */ - -// Mix the symptoms of two diseases (the src and the argument) -/datum/disease/advance/proc/Mix(var/datum/disease/advance/D) - if(!(src.IsSame(D))) - for(var/datum/symptom/S in shuffle(D.symptoms)) - AddSymptom(new S.type) - -/datum/disease/advance/proc/HasSymptom(var/datum/symptom/S) - for(var/datum/symptom/symp in symptoms) - if(symp.id == S.id) - return 1 - return 0 - -// Will generate new unique symptoms, use this if there are none. Returns a list of symptoms that were generated. -/datum/disease/advance/proc/GenerateSymptoms(var/type_level_limit = RANDOM_STARTING_LEVEL, var/amount_get = 0) - - - var/list/generated = list() // Symptoms we generated. - - // Generate symptoms. By default, we only choose non-deadly symptoms. - var/list/possible_symptoms = list() - for(var/symp in list_symptoms) - var/datum/symptom/S = new symp - if(S.level <= type_level_limit) - if(!HasSymptom(S)) - possible_symptoms += S - - if(!possible_symptoms.len) - return - //error("Advance Disease - We weren't able to get any possible symptoms in GenerateSymptoms([type_level_limit], [amount_get])") - - // Random chance to get more than one symptom - var/number_of = amount_get - if(!amount_get) - number_of = 1 - while(prob(20)) - number_of += 1 - - for(var/i = 1; number_of >= i; i++) - var/datum/symptom/S = pick(possible_symptoms) - generated += S - possible_symptoms -= S - - return generated - -/datum/disease/advance/proc/Refresh(var/new_name = 0) +/* + + Advance Disease is a system for Virologist to Engineer their own disease with symptoms that have effects and properties + which add onto the overall disease. + + If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus. + +*/ + +#define RANDOM_STARTING_LEVEL 2 + +var/list/archive_diseases = list() + +// The order goes from easy to cure to hard to cure. +var/list/advance_cures = list( + "nutriment", "sugar", "orangejuice", + "spaceacillin", "kelotane", "ethanol", + "leporazine", "synaptizine", "lipozine", + "silver", "gold", "plasma" + ) + +/* + + PROPERTIES + + */ + +/datum/disease/advance + + name = "Unknown" // We will always let our Virologist name our disease. + desc = "An engineered disease which can contain a multitude of symptoms." + form = "Advance Disease" // Will let med-scanners know that this disease was engineered. + agent = "advance microbes" + max_stages = 5 + spread = "Unknown" + affected_species = list("Human","Monkey") + + // NEW VARS + + var/list/symptoms = list() // The symptoms of the disease. + var/id = "" + var/processing = 0 + +/* + + OLD PROCS + + */ + +/datum/disease/advance/New(var/process = 1, var/datum/disease/advance/D) + + // Setup our dictionary if it hasn't already. + if(!dictionary_symptoms.len) + for(var/symp in list_symptoms) + var/datum/symptom/S = new symp + dictionary_symptoms[S.id] = symp + + if(!istype(D)) + D = null + // Generate symptoms if we weren't given any. + + if(!symptoms || !symptoms.len) + + if(!D || !D.symptoms || !D.symptoms.len) + symptoms = GenerateSymptoms() + else + for(var/datum/symptom/S in D.symptoms) + symptoms += new S.type + + Refresh() + ..(process, D) + return + +/datum/disease/advance/Del() + if(processing) + for(var/datum/symptom/S in symptoms) + S.End(src) + ..() + +// Randomly pick a symptom to activate. +/datum/disease/advance/stage_act() + ..() + if(symptoms && symptoms.len) + + if(!processing) + processing = 1 + for(var/datum/symptom/S in symptoms) + S.Start(src) + + for(var/datum/symptom/S in symptoms) + S.Activate(src) + else + CRASH("We do not have any symptoms during stage_act()!") + +// Compares type then ID. +/datum/disease/advance/IsSame(var/datum/disease/advance/D) + + if(!(istype(D, /datum/disease/advance))) + return 0 + + if(src.GetDiseaseID() != D.GetDiseaseID()) + return 0 + return 1 + +// To add special resistances. +/datum/disease/advance/cure(var/resistance=1) + if(affected_mob) + var/id = "[GetDiseaseID()]" + if(resistance && !(id in affected_mob.resistances)) + affected_mob.resistances[id] = id + affected_mob.viruses -= src //remove the datum from the list + del(src) //delete the datum to stop it processing + return + +// Returns the advance disease with a different reference memory. +/datum/disease/advance/Copy(var/process = 0) + return new /datum/disease/advance(process, src, 1) + +/* + + NEW PROCS + + */ + +// Mix the symptoms of two diseases (the src and the argument) +/datum/disease/advance/proc/Mix(var/datum/disease/advance/D) + if(!(src.IsSame(D))) + for(var/datum/symptom/S in shuffle(D.symptoms)) + AddSymptom(new S.type) + +/datum/disease/advance/proc/HasSymptom(var/datum/symptom/S) + for(var/datum/symptom/symp in symptoms) + if(symp.id == S.id) + return 1 + return 0 + +// Will generate new unique symptoms, use this if there are none. Returns a list of symptoms that were generated. +/datum/disease/advance/proc/GenerateSymptoms(var/type_level_limit = RANDOM_STARTING_LEVEL, var/amount_get = 0) + + + var/list/generated = list() // Symptoms we generated. + + // Generate symptoms. By default, we only choose non-deadly symptoms. + var/list/possible_symptoms = list() + for(var/symp in list_symptoms) + var/datum/symptom/S = new symp + if(S.level <= type_level_limit) + if(!HasSymptom(S)) + possible_symptoms += S + + if(!possible_symptoms.len) + return + //error("Advance Disease - We weren't able to get any possible symptoms in GenerateSymptoms([type_level_limit], [amount_get])") + + // Random chance to get more than one symptom + var/number_of = amount_get + if(!amount_get) + number_of = 1 + while(prob(20)) + number_of += 1 + + for(var/i = 1; number_of >= i; i++) + var/datum/symptom/S = pick(possible_symptoms) + generated += S + possible_symptoms -= S + + return generated + +/datum/disease/advance/proc/Refresh(var/new_name = 0) // to_chat(world, "[src.name] \ref[src] - REFRESH!") - var/list/properties = GenerateProperties() - AssignProperties(properties) - - if(!archive_diseases[GetDiseaseID()]) - if(new_name) - AssignName() - archive_diseases[GetDiseaseID()] = src // So we don't infinite loop - archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1) - - var/datum/disease/advance/A = archive_diseases[GetDiseaseID()] - AssignName(A.name) - -//Generate disease properties based on the effects. Returns an associated list. -/datum/disease/advance/proc/GenerateProperties() - - - if(!symptoms || !symptoms.len) - CRASH("We did not have any symptoms before generating properties.") - return - - var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 1) - - for(var/datum/symptom/S in symptoms) - - properties["resistance"] += S.resistance - properties["stealth"] += S.stealth - properties["stage_rate"] += S.stage_speed - properties["transmittable"] += S.transmittable - properties["severity"] = max(properties["severity"], S.level) // severity is based on the highest level symptom - - return properties - -// Assign the properties that are in the list. -/datum/disease/advance/proc/AssignProperties(var/list/properties = list()) - - - if(properties && properties.len) - - hidden = list( (properties["stealth"] > 2), (properties["stealth"] > 3) ) - // The more symptoms we have, the less transmittable it is but some symptoms can make up for it. - SetSpread(Clamp(properties["transmittable"] - symptoms.len, BLOOD, AIRBORNE)) - permeability_mod = max(Ceiling(0.4 * properties["transmittable"]), 1) - cure_chance = 15 - Clamp(properties["resistance"], -5, 5) // can be between 10 and 20 - stage_prob = max(properties["stage_rate"], 2) - SetSeverity(properties["severity"]) - GenerateCure(properties) - else - CRASH("Our properties were empty or null!") - - -// Assign the spread type and give it the correct description. -/datum/disease/advance/proc/SetSpread(var/spread_id) - switch(spread_id) - - if(NON_CONTAGIOUS) - spread = "None" - if(SPECIAL) - spread = "None" - if(CONTACT_GENERAL, CONTACT_HANDS, CONTACT_FEET) - spread = "On contact" - if(AIRBORNE) - spread = "Airborne" - if(BLOOD) - spread = "Blood" - - spread_type = spread_id + var/list/properties = GenerateProperties() + AssignProperties(properties) + + if(!archive_diseases[GetDiseaseID()]) + if(new_name) + AssignName() + archive_diseases[GetDiseaseID()] = src // So we don't infinite loop + archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1) + + var/datum/disease/advance/A = archive_diseases[GetDiseaseID()] + AssignName(A.name) + +//Generate disease properties based on the effects. Returns an associated list. +/datum/disease/advance/proc/GenerateProperties() + + + if(!symptoms || !symptoms.len) + CRASH("We did not have any symptoms before generating properties.") + return + + var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 1) + + for(var/datum/symptom/S in symptoms) + + properties["resistance"] += S.resistance + properties["stealth"] += S.stealth + properties["stage_rate"] += S.stage_speed + properties["transmittable"] += S.transmittable + properties["severity"] = max(properties["severity"], S.level) // severity is based on the highest level symptom + + return properties + +// Assign the properties that are in the list. +/datum/disease/advance/proc/AssignProperties(var/list/properties = list()) + + + if(properties && properties.len) + + hidden = list( (properties["stealth"] > 2), (properties["stealth"] > 3) ) + // The more symptoms we have, the less transmittable it is but some symptoms can make up for it. + SetSpread(Clamp(properties["transmittable"] - symptoms.len, BLOOD, AIRBORNE)) + permeability_mod = max(Ceiling(0.4 * properties["transmittable"]), 1) + cure_chance = 15 - Clamp(properties["resistance"], -5, 5) // can be between 10 and 20 + stage_prob = max(properties["stage_rate"], 2) + SetSeverity(properties["severity"]) + GenerateCure(properties) + else + CRASH("Our properties were empty or null!") + + +// Assign the spread type and give it the correct description. +/datum/disease/advance/proc/SetSpread(var/spread_id) + switch(spread_id) + + if(NON_CONTAGIOUS) + spread = "None" + if(SPECIAL) + spread = "None" + if(CONTACT_GENERAL, CONTACT_HANDS, CONTACT_FEET) + spread = "On contact" + if(AIRBORNE) + spread = "Airborne" + if(BLOOD) + spread = "Blood" + + spread_type = spread_id // to_chat(world, "Setting spread type to [spread_id]/[spread]") - -/datum/disease/advance/proc/SetSeverity(var/level_sev) - - - switch(level_sev) - - if(-INFINITY to 0) - severity = "Non-Threat" - if(1) - severity = "Minor" - if(2) - severity = "Medium" - if(3) - severity = "Harmful" - if(4) - severity = "Dangerous!" - if(5 to INFINITY) - severity = "BIOHAZARD THREAT!" - else - severity = "Unknown" - - -// Will generate a random cure, the less resistance the symptoms have, the harder the cure. -/datum/disease/advance/proc/GenerateCure(var/list/properties = list()) - if(properties && properties.len) - var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) + +/datum/disease/advance/proc/SetSeverity(var/level_sev) + + + switch(level_sev) + + if(-INFINITY to 0) + severity = "Non-Threat" + if(1) + severity = "Minor" + if(2) + severity = "Medium" + if(3) + severity = "Harmful" + if(4) + severity = "Dangerous!" + if(5 to INFINITY) + severity = "BIOHAZARD THREAT!" + else + severity = "Unknown" + + +// Will generate a random cure, the less resistance the symptoms have, the harder the cure. +/datum/disease/advance/proc/GenerateCure(var/list/properties = list()) + if(properties && properties.len) + var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) // to_chat(world, "Res = [res]") - cure_id = advance_cures[res] - - // Get the cure name from the cure_id - var/datum/reagent/D = chemical_reagents_list[cure_id] - cure = D.name - - - return - -// Randomly generate a symptom, has a chance to lose or gain a symptom. -/datum/disease/advance/proc/Evolve(var/level = 2) - var/s = safepick(GenerateSymptoms(level, 1)) - if(s) - AddSymptom(s) - Refresh(1) - return - -// Randomly remove a symptom. -/datum/disease/advance/proc/Devolve() - if(symptoms.len > 1) - var/s = safepick(symptoms) - if(s) - RemoveSymptom(s) - Refresh(1) - return - -// Name the disease. -/datum/disease/advance/proc/AssignName(var/name = "Unknown") - src.name = name - return - -// Return a unique ID of the disease. -/datum/disease/advance/proc/GetDiseaseID() - - - var/list/L = list() - for(var/datum/symptom/S in symptoms) - L += S.id - L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in. - var/result = list2text(L, ":") - id = result - return result - - -// Add a symptom, if it is over the limit (with a small chance to be able to go over) -// we take a random symptom away and add the new one. -/datum/disease/advance/proc/AddSymptom(var/datum/symptom/S) - - - if(HasSymptom(S)) - return - - if(symptoms.len < 5 + rand(-1, 1)) - symptoms += S - else - RemoveSymptom(pick(symptoms)) - symptoms += S - return - -// Simply removes the symptom. -/datum/disease/advance/proc/RemoveSymptom(var/datum/symptom/S) - symptoms -= S - return - -/* - - Static Procs - -*/ - -// Mix a list of advance diseases and return the mixed result. -/proc/Advance_Mix(var/list/D_list) - - + cure_id = advance_cures[res] + + // Get the cure name from the cure_id + var/datum/reagent/D = chemical_reagents_list[cure_id] + cure = D.name + + + return + +// Randomly generate a symptom, has a chance to lose or gain a symptom. +/datum/disease/advance/proc/Evolve(var/level = 2) + var/s = safepick(GenerateSymptoms(level, 1)) + if(s) + AddSymptom(s) + Refresh(1) + return + +// Randomly remove a symptom. +/datum/disease/advance/proc/Devolve() + if(symptoms.len > 1) + var/s = safepick(symptoms) + if(s) + RemoveSymptom(s) + Refresh(1) + return + +// Name the disease. +/datum/disease/advance/proc/AssignName(var/name = "Unknown") + src.name = name + return + +// Return a unique ID of the disease. +/datum/disease/advance/proc/GetDiseaseID() + + + var/list/L = list() + for(var/datum/symptom/S in symptoms) + L += S.id + L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in. + var/result = list2text(L, ":") + id = result + return result + + +// Add a symptom, if it is over the limit (with a small chance to be able to go over) +// we take a random symptom away and add the new one. +/datum/disease/advance/proc/AddSymptom(var/datum/symptom/S) + + + if(HasSymptom(S)) + return + + if(symptoms.len < 5 + rand(-1, 1)) + symptoms += S + else + RemoveSymptom(pick(symptoms)) + symptoms += S + return + +// Simply removes the symptom. +/datum/disease/advance/proc/RemoveSymptom(var/datum/symptom/S) + symptoms -= S + return + +/* + + Static Procs + +*/ + +// Mix a list of advance diseases and return the mixed result. +/proc/Advance_Mix(var/list/D_list) + + // to_chat(world, "Mixing!!!!") - - var/list/diseases = list() - - for(var/datum/disease/advance/A in D_list) - diseases += A.Copy() - - if(!diseases.len) - return null - if(diseases.len <= 1) - return pick(diseases) // Just return the only entry. - - var/i = 0 - // Mix our diseases until we are left with only one result. - while(i < 20 && diseases.len > 1) - - i++ - - var/datum/disease/advance/D1 = pick(diseases) - diseases -= D1 - - var/datum/disease/advance/D2 = pick(diseases) - D2.Mix(D1) - - // Should be only 1 entry left, but if not let's only return a single entry + + var/list/diseases = list() + + for(var/datum/disease/advance/A in D_list) + diseases += A.Copy() + + if(!diseases.len) + return null + if(diseases.len <= 1) + return pick(diseases) // Just return the only entry. + + var/i = 0 + // Mix our diseases until we are left with only one result. + while(i < 20 && diseases.len > 1) + + i++ + + var/datum/disease/advance/D1 = pick(diseases) + diseases -= D1 + + var/datum/disease/advance/D2 = pick(diseases) + D2.Mix(D1) + + // Should be only 1 entry left, but if not let's only return a single entry // to_chat(world, "END MIXING!!!!!") - var/datum/disease/advance/to_return = pick(diseases) - to_return.Refresh(1) - return to_return - -/proc/SetViruses(var/datum/reagent/R, var/list/data) - if(data) - var/list/preserve = list() - if(istype(data) && data["viruses"]) - for(var/datum/disease/A in data["viruses"]) - preserve += A.Copy() - R.data = data.Copy() - else - R.data = data - if(preserve.len) - R.data["viruses"] = preserve - -/proc/AdminCreateVirus(var/mob/user) - var/i = 5 - - var/datum/disease/advance/D = new(0, null) - D.symptoms = list() - - var/list/symptoms = list() - symptoms += "Done" - symptoms += list_symptoms.Copy() - do - var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms - if(istext(symptom)) - i = 0 - else if(ispath(symptom)) - var/datum/symptom/S = new symptom - if(!D.HasSymptom(S)) - D.symptoms += S - i -= 1 - while(i > 0) - - if(D.symptoms.len > 0) - - var/new_name = copytext(sanitize(input(user, "Name your new disease.", "New Name")),1,MAX_NAME_LEN) - D.AssignName(new_name) - D.Refresh() - - for(var/datum/disease/advance/AD in active_diseases) - AD.Refresh() - - for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) - if(H.z != 1) - continue - if(!H.has_disease(D)) - H.contract_disease(D, 1) - break - - var/list/name_symptoms = list() - for(var/datum/symptom/S in D.symptoms) - name_symptoms += S.name - message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]") - -/* -/mob/verb/test() - - - for(var/datum/disease/D in active_diseases) + var/datum/disease/advance/to_return = pick(diseases) + to_return.Refresh(1) + return to_return + +/proc/SetViruses(var/datum/reagent/R, var/list/data) + if(data) + var/list/preserve = list() + if(istype(data) && data["viruses"]) + for(var/datum/disease/A in data["viruses"]) + preserve += A.Copy() + R.data = data.Copy() + else + R.data = data + if(preserve.len) + R.data["viruses"] = preserve + +/proc/AdminCreateVirus(var/mob/user) + var/i = 5 + + var/datum/disease/advance/D = new(0, null) + D.symptoms = list() + + var/list/symptoms = list() + symptoms += "Done" + symptoms += list_symptoms.Copy() + do + var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms + if(istext(symptom)) + i = 0 + else if(ispath(symptom)) + var/datum/symptom/S = new symptom + if(!D.HasSymptom(S)) + D.symptoms += S + i -= 1 + while(i > 0) + + if(D.symptoms.len > 0) + + var/new_name = copytext(sanitize(input(user, "Name your new disease.", "New Name")),1,MAX_NAME_LEN) + D.AssignName(new_name) + D.Refresh() + + for(var/datum/disease/advance/AD in active_diseases) + AD.Refresh() + + for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) + if(H.z != 1) + continue + if(!H.has_disease(D)) + H.contract_disease(D, 1) + break + + var/list/name_symptoms = list() + for(var/datum/symptom/S in D.symptoms) + name_symptoms += S.name + message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]") + +/* +/mob/verb/test() + + + for(var/datum/disease/D in active_diseases) to_chat(src, "[D.name] - [D.holder]") -*/ - +*/ + #undef RANDOM_STARTING_LEVEL \ No newline at end of file diff --git a/code/datums/diseases/advance/presets.dm b/code/datums/diseases/advance/presets.dm index b62b18e306c..675feadbb0b 100644 --- a/code/datums/diseases/advance/presets.dm +++ b/code/datums/diseases/advance/presets.dm @@ -1,43 +1,43 @@ -// Cold - -/datum/disease/advance/cold/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) - if(!D) - name = "Cold" - symptoms = list(new/datum/symptom/sneeze) - ..(process, D, copy) - - -// Flu - -/datum/disease/advance/flu/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) - if(!D) - name = "Flu" - symptoms = list(new/datum/symptom/cough) - ..(process, D, copy) - - -// Voice Changing - -/datum/disease/advance/voice_change/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) - if(!D) - name = "Epiglottis Mutation" - symptoms = list(new/datum/symptom/voice_change) - ..(process, D, copy) - - -// Toxin Filter - -/datum/disease/advance/heal/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) - if(!D) - name = "Liver Enhancer" - symptoms = list(new/datum/symptom/heal) - ..(process, D, copy) - - -// Hullucigen - -/datum/disease/advance/hullucigen/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) - if(!D) - name = "Reality Impairment" - symptoms = list(new/datum/symptom/hallucigen) +// Cold + +/datum/disease/advance/cold/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) + if(!D) + name = "Cold" + symptoms = list(new/datum/symptom/sneeze) + ..(process, D, copy) + + +// Flu + +/datum/disease/advance/flu/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) + if(!D) + name = "Flu" + symptoms = list(new/datum/symptom/cough) + ..(process, D, copy) + + +// Voice Changing + +/datum/disease/advance/voice_change/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) + if(!D) + name = "Epiglottis Mutation" + symptoms = list(new/datum/symptom/voice_change) + ..(process, D, copy) + + +// Toxin Filter + +/datum/disease/advance/heal/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) + if(!D) + name = "Liver Enhancer" + symptoms = list(new/datum/symptom/heal) + ..(process, D, copy) + + +// Hullucigen + +/datum/disease/advance/hullucigen/New(var/process = 1, var/datum/disease/advance/D, var/copy = 0) + if(!D) + name = "Reality Impairment" + symptoms = list(new/datum/symptom/hallucigen) ..(process, D, copy) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm index 8786119bf0a..6391cf7110a 100644 --- a/code/datums/diseases/advance/symptoms/confusion.dm +++ b/code/datums/diseases/advance/symptoms/confusion.dm @@ -1,39 +1,39 @@ -/* -////////////////////////////////////// - -Confusion - - Little bit hidden. - Lowers resistance. - Decreases stage speed. - Not very transmittable. - Intense Level. - -Bonus - Makes the affected mob be confused for short periods of time. - -////////////////////////////////////// -*/ - -/datum/symptom/confusion - - name = "Confusion" - stealth = 1 - resistance = -1 - stage_speed = -3 - transmittable = 0 - level = 4 - - -/datum/symptom/confusion/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) +/* +////////////////////////////////////// + +Confusion + + Little bit hidden. + Lowers resistance. + Decreases stage speed. + Not very transmittable. + Intense Level. + +Bonus + Makes the affected mob be confused for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/confusion + + name = "Confusion" + stealth = 1 + resistance = -1 + stage_speed = -3 + transmittable = 0 + level = 4 + + +/datum/symptom/confusion/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("You feel confused.", "You forgot what you were thinking about.")]") - else + else to_chat(M, "You are unable to think straight!") - M.confused = min(100, M.confused + 2) - - return + M.confused = min(100, M.confused + 2) + + return diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm index 6d1f200dba6..86ac3dc6271 100644 --- a/code/datums/diseases/advance/symptoms/cough.dm +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -1,39 +1,39 @@ -/* -////////////////////////////////////// - -Coughing - - Noticable. - Little Resistance. - Doesn't increase stage speed much. - Transmittable. - Low Level. - -BONUS - Will force the affected mob to drop small items! - -////////////////////////////////////// -*/ - -/datum/symptom/cough - - name = "Cough" - stealth = -1 - resistance = 3 - stage_speed = 1 - transmittable = 2 - level = 1 - -/datum/symptom/cough/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3) +/* +////////////////////////////////////// + +Coughing + + Noticable. + Little Resistance. + Doesn't increase stage speed much. + Transmittable. + Low Level. + +BONUS + Will force the affected mob to drop small items! + +////////////////////////////////////// +*/ + +/datum/symptom/cough + + name = "Cough" + stealth = -1 + resistance = 3 + stage_speed = 1 + transmittable = 2 + level = 1 + +/datum/symptom/cough/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) to_chat(M, "[pick("You swallow excess mucus.", "You lightly cough.")]") - else - M.emote("cough") - var/obj/item/I = M.get_active_hand() - if(I && I.w_class < 3) - M.drop_item(I) + else + M.emote("cough") + var/obj/item/I = M.get_active_hand() + if(I && I.w_class < 3) + M.drop_item(I) return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm index 3e276179f38..4461d94a4ac 100644 --- a/code/datums/diseases/advance/symptoms/damage_converter.dm +++ b/code/datums/diseases/advance/symptoms/damage_converter.dm @@ -1,44 +1,44 @@ -/* -////////////////////////////////////// - -Damage Converter - - Little bit hidden. - Lowers resistance tremendously. - Decreases stage speed tremendously. - Reduced transmittablity - Intense Level. - -Bonus - Slowly converts brute/fire damage to toxin. - -////////////////////////////////////// -*/ - -/datum/symptom/damage_converter - - name = "Toxic Compensation" - stealth = 1 - resistance = -4 - stage_speed = -4 - transmittable = -2 - level = 4 - -/datum/symptom/damage_converter/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(4, 5) - Convert(M) - return - -/datum/symptom/damage_converter/proc/Convert(var/mob/living/M) - - - if(M.getFireLoss() < M.getMaxHealth() || M.getBruteLoss() < M.getMaxHealth()) - var/get_damage = rand(1, 2) - M.adjustFireLoss(-get_damage) - M.adjustBruteLoss(-get_damage) - M.adjustToxLoss(get_damage) +/* +////////////////////////////////////// + +Damage Converter + + Little bit hidden. + Lowers resistance tremendously. + Decreases stage speed tremendously. + Reduced transmittablity + Intense Level. + +Bonus + Slowly converts brute/fire damage to toxin. + +////////////////////////////////////// +*/ + +/datum/symptom/damage_converter + + name = "Toxic Compensation" + stealth = 1 + resistance = -4 + stage_speed = -4 + transmittable = -2 + level = 4 + +/datum/symptom/damage_converter/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + Convert(M) + return + +/datum/symptom/damage_converter/proc/Convert(var/mob/living/M) + + + if(M.getFireLoss() < M.getMaxHealth() || M.getBruteLoss() < M.getMaxHealth()) + var/get_damage = rand(1, 2) + M.adjustFireLoss(-get_damage) + M.adjustBruteLoss(-get_damage) + M.adjustToxLoss(get_damage) return 1 \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm index 243b8ed5bb9..de690bd4167 100644 --- a/code/datums/diseases/advance/symptoms/dizzy.dm +++ b/code/datums/diseases/advance/symptoms/dizzy.dm @@ -1,37 +1,37 @@ -/* -////////////////////////////////////// - -Dizziness - - Hidden. - Lowers resistance considerably. - Decreases stage speed. - Reduced transmittability - Intense Level. - -Bonus - Shakes the affected mob's screen for short periods. - -////////////////////////////////////// -*/ - -/datum/symptom/dizzy // Not the egg - - name = "Dizziness" - stealth = 2 - resistance = -2 - stage_speed = -3 - transmittable = -1 - level = 4 - -/datum/symptom/dizzy/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) +/* +////////////////////////////////////// + +Dizziness + + Hidden. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittability + Intense Level. + +Bonus + Shakes the affected mob's screen for short periods. + +////////////////////////////////////// +*/ + +/datum/symptom/dizzy // Not the egg + + name = "Dizziness" + stealth = 2 + resistance = -2 + stage_speed = -3 + transmittable = -1 + level = 4 + +/datum/symptom/dizzy/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("You feel dizzy.", "Your head starts spinning.")]") - else + else to_chat(M, "You are unable to look straight!") - M.Dizzy(5) + M.Dizzy(5) return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm index 78b3a6e0679..c00bd0bbd35 100644 --- a/code/datums/diseases/advance/symptoms/fever.dm +++ b/code/datums/diseases/advance/symptoms/fever.dm @@ -1,35 +1,35 @@ -/* -////////////////////////////////////// - -Fever - - No change to hidden. - Increases resistance. - Increases stage speed. - Little transmittable. - Low level. - -Bonus - Heats up your body. - -////////////////////////////////////// -*/ - -/datum/symptom/fever - - name = "Fever" - stealth = 0 - resistance = 3 - stage_speed = 3 - transmittable = 2 - level = 2 - -/datum/symptom/fever/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/carbon/M = A.affected_mob +/* +////////////////////////////////////// + +Fever + + No change to hidden. + Increases resistance. + Increases stage speed. + Little transmittable. + Low level. + +Bonus + Heats up your body. + +////////////////////////////////////// +*/ + +/datum/symptom/fever + + name = "Fever" + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 2 + level = 2 + +/datum/symptom/fever/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/M = A.affected_mob to_chat(M, "[pick("You feel hot.", "You feel like you're burning.")]") - if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT) - M.bodytemperature = min(M.bodytemperature + (20 * A.stage), BODYTEMP_HEAT_DAMAGE_LIMIT - 1) - - return + if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT) + M.bodytemperature = min(M.bodytemperature + (20 * A.stage), BODYTEMP_HEAT_DAMAGE_LIMIT - 1) + + return diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm index f92c5aeb019..a3e1dc03375 100644 --- a/code/datums/diseases/advance/symptoms/hallucigen.dm +++ b/code/datums/diseases/advance/symptoms/hallucigen.dm @@ -1,37 +1,37 @@ -/* -////////////////////////////////////// - -Hallucigen - - Very noticable. - Lowers resistance considerably. - Decreases stage speed. - Reduced transmittable. - Critical Level. - -Bonus - Makes the affected mob be hallucinated for short periods of time. - -////////////////////////////////////// -*/ - -/datum/symptom/hallucigen - - name = "Hallucigen" - stealth = -2 - resistance = -3 - stage_speed = -3 - transmittable = -1 - level = 5 - -/datum/symptom/hallucigen/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) +/* +////////////////////////////////////// + +Hallucigen + + Very noticable. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittable. + Critical Level. + +Bonus + Makes the affected mob be hallucinated for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/hallucigen + + name = "Hallucigen" + stealth = -2 + resistance = -3 + stage_speed = -3 + transmittable = -1 + level = 5 + +/datum/symptom/hallucigen/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("You notice someone in the corner of your eye.", "Is that footsteps?.")]") - else - M.hallucination += 5 - - return + else + M.hallucination += 5 + + return diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm index a5e8e6d8db3..328e4fe1a50 100644 --- a/code/datums/diseases/advance/symptoms/headache.dm +++ b/code/datums/diseases/advance/symptoms/headache.dm @@ -1,33 +1,33 @@ -/* -////////////////////////////////////// - -Headache - - Noticable. - Highly resistant. - Increases stage speed. - Not transmittable. - Low Level. - -BONUS - Displays an annoying message! - Should be used for buffing your disease. - -////////////////////////////////////// -*/ - -/datum/symptom/headache - - name = "Headache" - stealth = -1 - resistance = 4 - stage_speed = 2 - transmittable = 0 - level = 1 - -/datum/symptom/headache/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob +/* +////////////////////////////////////// + +Headache + + Noticable. + Highly resistant. + Increases stage speed. + Not transmittable. + Low Level. + +BONUS + Displays an annoying message! + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/headache + + name = "Headache" + stealth = -1 + resistance = 4 + stage_speed = 2 + transmittable = 0 + level = 1 + +/datum/symptom/headache/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob to_chat(M, "[pick("Your head hurts.", "Your head starts pounding.")]") return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index e1f6e4941de..03bad20115f 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -1,41 +1,41 @@ -/* -////////////////////////////////////// - -Healing - - Little bit hidden. - Lowers resistance tremendously. - Decreases stage speed tremendously. - Decreases transmittablity temrendously. - Fatal Level. - -Bonus - Heals toxins in the affected mob's blood stream. - -////////////////////////////////////// -*/ - -/datum/symptom/heal - - name = "Toxic Filter" - stealth = 1 - resistance = -4 - stage_speed = -4 - transmittable = -4 - level = 6 - -/datum/symptom/heal/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(4, 5) - Heal(M) - return - -/datum/symptom/heal/proc/Heal(var/mob/living/M) - - - var/get_damage = rand(1, 2) - M.adjustToxLoss(-get_damage) +/* +////////////////////////////////////// + +Healing + + Little bit hidden. + Lowers resistance tremendously. + Decreases stage speed tremendously. + Decreases transmittablity temrendously. + Fatal Level. + +Bonus + Heals toxins in the affected mob's blood stream. + +////////////////////////////////////// +*/ + +/datum/symptom/heal + + name = "Toxic Filter" + stealth = 1 + resistance = -4 + stage_speed = -4 + transmittable = -4 + level = 6 + +/datum/symptom/heal/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + Heal(M) + return + +/datum/symptom/heal/proc/Heal(var/mob/living/M) + + + var/get_damage = rand(1, 2) + M.adjustToxLoss(-get_damage) return 1 \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm index 381fcf654bb..6a3a823cf2d 100644 --- a/code/datums/diseases/advance/symptoms/itching.dm +++ b/code/datums/diseases/advance/symptoms/itching.dm @@ -1,33 +1,33 @@ -/* -////////////////////////////////////// - -Itching - - Not noticable or unnoticable. - Resistant. - Increases stage speed. - Little transmittable. - Low Level. - -BONUS - Displays an annoying message! - Should be used for buffing your disease. - -////////////////////////////////////// -*/ - -/datum/symptom/itching - - name = "Itching" - stealth = 0 - resistance = 3 - stage_speed = 3 - transmittable = 1 - level = 1 - -/datum/symptom/itching/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob +/* +////////////////////////////////////// + +Itching + + Not noticable or unnoticable. + Resistant. + Increases stage speed. + Little transmittable. + Low Level. + +BONUS + Displays an annoying message! + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/itching + + name = "Itching" + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 1 + level = 1 + +/datum/symptom/itching/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob to_chat(M, "Your [pick("back", "arm", "leg", "elbow", "head")] itches.") return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm index 77631143eb8..51cbd782458 100644 --- a/code/datums/diseases/advance/symptoms/shivering.dm +++ b/code/datums/diseases/advance/symptoms/shivering.dm @@ -1,35 +1,35 @@ -/* -////////////////////////////////////// - -Shivering - - No change to hidden. - Increases resistance. - Increases stage speed. - Little transmittable. - Low level. - -Bonus - Cools down your body. - -////////////////////////////////////// -*/ - -/datum/symptom/shivering - - name = "Shivering" - stealth = 0 - resistance = 2 - stage_speed = 2 - transmittable = 2 - level = 2 - -/datum/symptom/shivering/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/carbon/M = A.affected_mob +/* +////////////////////////////////////// + +Shivering + + No change to hidden. + Increases resistance. + Increases stage speed. + Little transmittable. + Low level. + +Bonus + Cools down your body. + +////////////////////////////////////// +*/ + +/datum/symptom/shivering + + name = "Shivering" + stealth = 0 + resistance = 2 + stage_speed = 2 + transmittable = 2 + level = 2 + +/datum/symptom/shivering/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/carbon/M = A.affected_mob to_chat(M, "[pick("You feel cold.", "You start shaking from the cold.")]") - if(M.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) - M.bodytemperature = min(M.bodytemperature - (20 * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1) - - return + if(M.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) + M.bodytemperature = min(M.bodytemperature - (20 * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1) + + return diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 155e71839a4..bab59c2d8cb 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -1,38 +1,38 @@ -/* -////////////////////////////////////// - -Sneezing - - Very Noticable. - Increases resistance. - Doesn't increase stage speed. - Very transmittable. - Low Level. - -Bonus - Forces a spread type of AIRBORNE - with extra range! - -////////////////////////////////////// -*/ - -/datum/symptom/sneeze - - name = "Sneezing" - stealth = -2 - resistance = 3 - stage_speed = 0 - transmittable = 4 - level = 1 - -/datum/symptom/sneeze/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3) - M.emote("sniff") - else - M.emote("sneeze") - A.spread(A.holder, 5, AIRBORNE) +/* +////////////////////////////////////// + +Sneezing + + Very Noticable. + Increases resistance. + Doesn't increase stage speed. + Very transmittable. + Low Level. + +Bonus + Forces a spread type of AIRBORNE + with extra range! + +////////////////////////////////////// +*/ + +/datum/symptom/sneeze + + name = "Sneezing" + stealth = -2 + resistance = 3 + stage_speed = 0 + transmittable = 4 + level = 1 + +/datum/symptom/sneeze/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) + M.emote("sniff") + else + M.emote("sneeze") + A.spread(A.holder, 5, AIRBORNE) return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm index 349809b973e..0cb69eaab8c 100644 --- a/code/datums/diseases/advance/symptoms/symptoms.dm +++ b/code/datums/diseases/advance/symptoms/symptoms.dm @@ -1,38 +1,38 @@ -// Symptoms are the effects that engineered advanced diseases do. - -var/list/list_symptoms = typesof(/datum/symptom) - /datum/symptom -var/list/dictionary_symptoms = list() - -var/global/const/SYMPTOM_ACTIVATION_PROB = 3 - -/datum/symptom - // Buffs/Debuffs the symptom has to the overall engineered disease. - var/name = "" - var/stealth = 0 - var/resistance = 0 - var/stage_speed = 0 - var/transmittable = 0 - // The type level of the symptom. Higher is more lethal and harder to generate. - var/level = 0 - // The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!! - var/id = "" - -/datum/symptom/New() - var/list/S = list_symptoms - for(var/i = 1; i <= S.len; i++) - if(src.type == S[i]) - id = "[i]" - return - CRASH("We couldn't assign an ID!") - -// Called when processing of the advance disease, which holds this symptom, starts. -/datum/symptom/proc/Start(var/datum/disease/advance/A) - return - -// Called when the advance disease is going to be deleted or when the advance disease stops processing. -/datum/symptom/proc/End(var/datum/disease/advance/A) - return - -/datum/symptom/proc/Activate(var/datum/disease/advance/A) - return - +// Symptoms are the effects that engineered advanced diseases do. + +var/list/list_symptoms = typesof(/datum/symptom) - /datum/symptom +var/list/dictionary_symptoms = list() + +var/global/const/SYMPTOM_ACTIVATION_PROB = 3 + +/datum/symptom + // Buffs/Debuffs the symptom has to the overall engineered disease. + var/name = "" + var/stealth = 0 + var/resistance = 0 + var/stage_speed = 0 + var/transmittable = 0 + // The type level of the symptom. Higher is more lethal and harder to generate. + var/level = 0 + // The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!! + var/id = "" + +/datum/symptom/New() + var/list/S = list_symptoms + for(var/i = 1; i <= S.len; i++) + if(src.type == S[i]) + id = "[i]" + return + CRASH("We couldn't assign an ID!") + +// Called when processing of the advance disease, which holds this symptom, starts. +/datum/symptom/proc/Start(var/datum/disease/advance/A) + return + +// Called when the advance disease is going to be deleted or when the advance disease stops processing. +/datum/symptom/proc/End(var/datum/disease/advance/A) + return + +/datum/symptom/proc/Activate(var/datum/disease/advance/A) + return + diff --git a/code/datums/diseases/advance/symptoms/voice_change.dm b/code/datums/diseases/advance/symptoms/voice_change.dm index a2ad53fa19d..5e730e054df 100644 --- a/code/datums/diseases/advance/symptoms/voice_change.dm +++ b/code/datums/diseases/advance/symptoms/voice_change.dm @@ -1,48 +1,48 @@ -/* -////////////////////////////////////// - -Voice Change - - Very Very noticable. - Lowers resistance considerably. - Decreases stage speed. - Reduced transmittable. - Fatal Level. - -Bonus - Changes the voice of the affected mob. Causing confusion in communication. - -////////////////////////////////////// -*/ - -/datum/symptom/voice_change - - name = "Voice Change" - stealth = -2 - resistance = -3 - stage_speed = -3 - transmittable = -1 - level = 6 - -/datum/symptom/voice_change/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) +/* +////////////////////////////////////// + +Voice Change + + Very Very noticable. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittable. + Fatal Level. + +Bonus + Changes the voice of the affected mob. Causing confusion in communication. + +////////////////////////////////////// +*/ + +/datum/symptom/voice_change + + name = "Voice Change" + stealth = -2 + resistance = -3 + stage_speed = -3 + transmittable = -1 + level = 6 + +/datum/symptom/voice_change/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("Your throat hurts.", "You clear your throat.")]") - else - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/random_name = H.species.makeName(H.gender,H) - H.SetSpecialVoice(random_name) - - return - -/datum/symptom/voice_change/End(var/datum/disease/advance/A) - ..() - if(ishuman(A.affected_mob)) - var/mob/living/carbon/human/H = A.affected_mob - H.UnsetSpecialVoice() - return + else + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/random_name = H.species.makeName(H.gender,H) + H.SetSpecialVoice(random_name) + + return + +/datum/symptom/voice_change/End(var/datum/disease/advance/A) + ..() + if(ishuman(A.affected_mob)) + var/mob/living/carbon/human/H = A.affected_mob + H.UnsetSpecialVoice() + return diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm index 6aa24248c6e..e08e0b1d4c9 100644 --- a/code/datums/diseases/advance/symptoms/vomit.dm +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -1,95 +1,95 @@ -/* -////////////////////////////////////// - -Vomiting - - Very Very Noticable. - Decreases resistance. - Doesn't increase stage speed. - Little transmittable. - Medium Level. - -Bonus - Forces the affected mob to vomit! - Meaning your disease can spread via - people walking on vomit. - Makes the affected mob lose nutrition and - heal toxin damage. - -////////////////////////////////////// -*/ - -/datum/symptom/vomit - - name = "Vomiting" - stealth = -2 - resistance = -1 - stage_speed = 0 - transmittable = 1 - level = 3 - -/datum/symptom/vomit/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB / 2)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) +/* +////////////////////////////////////// + +Vomiting + + Very Very Noticable. + Decreases resistance. + Doesn't increase stage speed. + Little transmittable. + Medium Level. + +Bonus + Forces the affected mob to vomit! + Meaning your disease can spread via + people walking on vomit. + Makes the affected mob lose nutrition and + heal toxin damage. + +////////////////////////////////////// +*/ + +/datum/symptom/vomit + + name = "Vomiting" + stealth = -2 + resistance = -1 + stage_speed = 0 + transmittable = 1 + level = 3 + +/datum/symptom/vomit/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB / 2)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("You feel nauseous...", "You feel like you're going to throw up!")]") - else - Vomit(M) - - return - -/datum/symptom/vomit/proc/Vomit(var/mob/living/M) - - - M.visible_message("[M] vomits on the floor!") - - M.nutrition -= 20 - M.adjustToxLoss(-3) - - var/turf/pos = get_turf(M) - pos.add_vomit_floor(M) - playsound(pos, 'sound/effects/splat.ogg', 50, 1) -/* -////////////////////////////////////// - -Vomiting Blood - - Very Very Noticable. - Decreases resistance. - Decreases stage speed. - Little transmittable. - Intense level. - -Bonus - Forces the affected mob to vomit blood! - Meaning your disease can spread via - people walking on the blood. - Makes the affected mob lose health. - -////////////////////////////////////// -*/ - -/datum/symptom/vomit/blood - - name = "Blood Vomiting" - stealth = -2 - resistance = -1 - stage_speed = -1 - transmittable = 1 - level = 4 - -/datum/symptom/vomit/blood/Vomit(var/mob/living/M) - - M.Stun(1) - M.visible_message("[M] vomits on the floor!") - - // They lose blood and health. - var/brute_dam = M.getBruteLoss() - if(brute_dam < 50) - M.adjustBruteLoss(3) - - var/turf/simulated/pos = get_turf(M) - pos.add_blood_floor(M) + else + Vomit(M) + + return + +/datum/symptom/vomit/proc/Vomit(var/mob/living/M) + + + M.visible_message("[M] vomits on the floor!") + + M.nutrition -= 20 + M.adjustToxLoss(-3) + + var/turf/pos = get_turf(M) + pos.add_vomit_floor(M) + playsound(pos, 'sound/effects/splat.ogg', 50, 1) +/* +////////////////////////////////////// + +Vomiting Blood + + Very Very Noticable. + Decreases resistance. + Decreases stage speed. + Little transmittable. + Intense level. + +Bonus + Forces the affected mob to vomit blood! + Meaning your disease can spread via + people walking on the blood. + Makes the affected mob lose health. + +////////////////////////////////////// +*/ + +/datum/symptom/vomit/blood + + name = "Blood Vomiting" + stealth = -2 + resistance = -1 + stage_speed = -1 + transmittable = 1 + level = 4 + +/datum/symptom/vomit/blood/Vomit(var/mob/living/M) + + M.Stun(1) + M.visible_message("[M] vomits on the floor!") + + // They lose blood and health. + var/brute_dam = M.getBruteLoss() + if(brute_dam < 50) + M.adjustBruteLoss(3) + + var/turf/simulated/pos = get_turf(M) + pos.add_blood_floor(M) playsound(pos, 'sound/effects/splat.ogg', 50, 1) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index f9b67a8385b..75027b7fd42 100644 --- a/code/datums/diseases/advance/symptoms/weight.dm +++ b/code/datums/diseases/advance/symptoms/weight.dm @@ -1,119 +1,119 @@ -/* -////////////////////////////////////// - -Weight Gain - - Very Very Noticable. - Decreases resistance. - Decreases stage speed. - Reduced transmittable. - Intense Level. - -Bonus - Increases the weight gain of the mob, - forcing it to eventually turn fat. -////////////////////////////////////// -*/ - -/datum/symptom/weight_gain - - name = "Weight Gain" - stealth = -3 - resistance = -3 - stage_speed = -2 - transmittable = -2 - level = 4 - -/datum/symptom/weight_gain/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) +/* +////////////////////////////////////// + +Weight Gain + + Very Very Noticable. + Decreases resistance. + Decreases stage speed. + Reduced transmittable. + Intense Level. + +Bonus + Increases the weight gain of the mob, + forcing it to eventually turn fat. +////////////////////////////////////// +*/ + +/datum/symptom/weight_gain + + name = "Weight Gain" + stealth = -3 + resistance = -3 + stage_speed = -2 + transmittable = -2 + level = 4 + +/datum/symptom/weight_gain/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("You feel blubbery.", "You feel full.")]") - else - M.overeatduration = min(M.overeatduration + 100, 600) - M.nutrition = min(M.nutrition + 100, 500) - - return - - -/* -////////////////////////////////////// - -Weight Loss - - Very Very Noticable. - Decreases resistance. - Decreases stage speed. - Reduced Transmittable. - High level. - -Bonus - Decreases the weight of the mob, - forcing it to be skinny. - -////////////////////////////////////// -*/ - -/datum/symptom/weight_loss - - name = "Weight Loss" - stealth = -3 - resistance = -2 - stage_speed = -2 - transmittable = -2 - level = 3 - -/datum/symptom/weight_loss/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) + else + M.overeatduration = min(M.overeatduration + 100, 600) + M.nutrition = min(M.nutrition + 100, 500) + + return + + +/* +////////////////////////////////////// + +Weight Loss + + Very Very Noticable. + Decreases resistance. + Decreases stage speed. + Reduced Transmittable. + High level. + +Bonus + Decreases the weight of the mob, + forcing it to be skinny. + +////////////////////////////////////// +*/ + +/datum/symptom/weight_loss + + name = "Weight Loss" + stealth = -3 + resistance = -2 + stage_speed = -2 + transmittable = -2 + level = 3 + +/datum/symptom/weight_loss/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) to_chat(M, "[pick("You feel hungry.", "You crave for food.")]") - else + else to_chat(M, "Your stomach rumbles.") - M.overeatduration = max(M.overeatduration - 100, 0) - M.nutrition = max(M.nutrition - 100, 0) - - return - -/* -////////////////////////////////////// - -Weight Even - - Very Noticable. - Decreases resistance. - Decreases stage speed. - Reduced transmittable. - High level. - -Bonus - Causes the weight of the mob to - be even, meaning eating isn't - required anymore. - -////////////////////////////////////// -*/ - -/datum/symptom/weight_even - - name = "Weight Even" - stealth = -3 - resistance = -2 - stage_speed = -2 - transmittable = -2 - level = 4 - -/datum/symptom/weight_loss/Activate(var/datum/disease/advance/A) - ..() - if(prob(SYMPTOM_ACTIVATION_PROB)) - var/mob/living/M = A.affected_mob - switch(A.stage) - if(4, 5) - M.overeatduration = 0 - M.nutrition = 400 - + M.overeatduration = max(M.overeatduration - 100, 0) + M.nutrition = max(M.nutrition - 100, 0) + + return + +/* +////////////////////////////////////// + +Weight Even + + Very Noticable. + Decreases resistance. + Decreases stage speed. + Reduced transmittable. + High level. + +Bonus + Causes the weight of the mob to + be even, meaning eating isn't + required anymore. + +////////////////////////////////////// +*/ + +/datum/symptom/weight_even + + name = "Weight Even" + stealth = -3 + resistance = -2 + stage_speed = -2 + transmittable = -2 + level = 4 + +/datum/symptom/weight_loss/Activate(var/datum/disease/advance/A) + ..() + if(prob(SYMPTOM_ACTIVATION_PROB)) + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + M.overeatduration = 0 + M.nutrition = 400 + return \ No newline at end of file diff --git a/code/datums/diseases/alien_embryo.dm b/code/datums/diseases/alien_embryo.dm index f7765bef8a9..46d954bc26b 100644 --- a/code/datums/diseases/alien_embryo.dm +++ b/code/datums/diseases/alien_embryo.dm @@ -1,156 +1,156 @@ -//affected_mob.contract_disease(new /datum/disease/alien_embryo) - -//cael - retained this file for legacy reference, see code\\modules\\mob\living\carbon\alien\special\alien_embryo.dm for replacement - -//Our own special process so that dead hosts still chestburst -/datum/disease/alien_embryo/process() - if(!holder) return - if(holder == affected_mob) - stage_act() - if(affected_mob) - if(affected_mob.stat == DEAD) - if(prob(50)) - if(--longevity<=0) - cure(0) - else //the virus is in inanimate obj - cure(0) - return - -/datum/disease/alien_embryo/New() - ..() - /* Special Hud for xenos */ - spawn(0) - if (affected_mob) - AddInfectionImages(affected_mob) - -/datum/disease/alien_embryo/cure(var/resistance=1) - ..() - spawn(0) - if (affected_mob) - RemoveInfectionImages(affected_mob) - -/datum/disease/alien_embryo - name = "Unidentified Foreign Body" - max_stages = 5 - spread = "None" - spread_type = SPECIAL - cure = "Unknown" - cure_id = list("lexorin","toxin","gargleblaster") - cure_chance = 50 - affected_species = list("Human", "Monkey") - permeability_mod = 15//likely to infect - can_carry = 0 - stage_prob = 3 - var/gibbed = 0 - stage_minimum_age = 300 - -/datum/disease/alien_embryo/stage_act() - ..() - switch(stage) - if(2, 3) - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(1)) - to_chat(affected_mob, "Mucous runs down the back of your throat.") - if(4) - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(2)) - to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_organ_damage(1) - if(prob(2)) - to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - if(5) - to_chat(affected_mob, "You feel something tearing its way out of your stomach...") - affected_mob.adjustToxLoss(10) - affected_mob.updatehealth() - if(prob(50)) - if(gibbed != 0) return 0 - var/list/candidates = get_alien_candidates() - var/picked = null - - // To stop clientless larva, we will check that our host has a client - // if we find no ghosts to become the alien. If the host has a client - // he will become the alien but if he doesn't then we will set the stage - // to 2, so we don't do a process heavy check everytime. - - if(candidates.len) - picked = pick(candidates) - else if(affected_mob.client) - picked = affected_mob.key - else - stage = 2 // Let's try again later. - return - - var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc) - new_xeno.key = picked - new_xeno << sound('sound/voice/hiss5.ogg', 0, 0, 0, 100)) // To get the player's attention. +//affected_mob.contract_disease(new /datum/disease/alien_embryo) - affected_mob.gib() - src.cure(0) - gibbed = 1 - return - -/datum/disease/alien_embryo/stage_change(var/old_stage) - RefreshInfectionImage() - -/*---------------------------------------- +//cael - retained this file for legacy reference, see code\\modules\\mob\living\carbon\alien\special\alien_embryo.dm for replacement + +//Our own special process so that dead hosts still chestburst +/datum/disease/alien_embryo/process() + if(!holder) return + if(holder == affected_mob) + stage_act() + if(affected_mob) + if(affected_mob.stat == DEAD) + if(prob(50)) + if(--longevity<=0) + cure(0) + else //the virus is in inanimate obj + cure(0) + return + +/datum/disease/alien_embryo/New() + ..() + /* Special Hud for xenos */ + spawn(0) + if (affected_mob) + AddInfectionImages(affected_mob) + +/datum/disease/alien_embryo/cure(var/resistance=1) + ..() + spawn(0) + if (affected_mob) + RemoveInfectionImages(affected_mob) + +/datum/disease/alien_embryo + name = "Unidentified Foreign Body" + max_stages = 5 + spread = "None" + spread_type = SPECIAL + cure = "Unknown" + cure_id = list("lexorin","toxin","gargleblaster") + cure_chance = 50 + affected_species = list("Human", "Monkey") + permeability_mod = 15//likely to infect + can_carry = 0 + stage_prob = 3 + var/gibbed = 0 + stage_minimum_age = 300 + +/datum/disease/alien_embryo/stage_act() + ..() + switch(stage) + if(2, 3) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "Mucous runs down the back of your throat.") + if(4) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(2)) + to_chat(affected_mob, "Your muscles ache.") + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(2)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + if(5) + to_chat(affected_mob, "You feel something tearing its way out of your stomach...") + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(50)) + if(gibbed != 0) return 0 + var/list/candidates = get_alien_candidates() + var/picked = null + + // To stop clientless larva, we will check that our host has a client + // if we find no ghosts to become the alien. If the host has a client + // he will become the alien but if he doesn't then we will set the stage + // to 2, so we don't do a process heavy check everytime. + + if(candidates.len) + picked = pick(candidates) + else if(affected_mob.client) + picked = affected_mob.key + else + stage = 2 // Let's try again later. + return + + var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc) + new_xeno.key = picked + new_xeno << sound('sound/voice/hiss5.ogg', 0, 0, 0, 100)) // To get the player's attention. + + affected_mob.gib() + src.cure(0) + gibbed = 1 + return + +/datum/disease/alien_embryo/stage_change(var/old_stage) + RefreshInfectionImage() + +/*---------------------------------------- Proc: RefreshInfectionImage() -Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. -----------------------------------------*/ -/datum/disease/alien_embryo/proc/RefreshInfectionImage() - spawn(0) - for (var/mob/living/carbon/alien/alien in player_list) - if (alien.client) - for(var/image/I in alien.client.images) - if(dd_hasprefix_case(I.icon_state, "infected")) - //del(I) - alien.client.images -= I - - for (var/mob/living/carbon/alien/alien in player_list) - if (alien.client) - for (var/mob/living/carbon/C in mob_list) - if(C) - if (C.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") - alien.client.images += I - return - -/*---------------------------------------- +Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. +----------------------------------------*/ +/datum/disease/alien_embryo/proc/RefreshInfectionImage() + spawn(0) + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + for(var/image/I in alien.client.images) + if(dd_hasprefix_case(I.icon_state, "infected")) + //del(I) + alien.client.images -= I + + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + for (var/mob/living/carbon/C in mob_list) + if(C) + if (C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + return + +/*---------------------------------------- Proc: AddInfectionImages(C) -Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C. -----------------------------------------*/ -/datum/disease/alien_embryo/proc/AddInfectionImages(var/mob/living/carbon/C) - if (C) - for (var/mob/living/carbon/alien/alien in player_list) - if (alien.client) - if (C.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") - alien.client.images += I - return - -/*---------------------------------------- +Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C. +----------------------------------------*/ +/datum/disease/alien_embryo/proc/AddInfectionImages(var/mob/living/carbon/C) + if (C) + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + if (C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + return + +/*---------------------------------------- Proc: RemoveInfectionImage(C) -Des: Removes the alien infection image from all aliens in the world located in passed mob (C). -----------------------------------------*/ - -/datum/disease/alien_embryo/proc/RemoveInfectionImages(var/mob/living/carbon/C) - if (C) - for (var/mob/living/carbon/alien/alien in player_list) - if (alien.client) - for(var/image/I in alien.client.images) - if(I.loc == C) - if(dd_hasprefix_case(I.icon_state, "infected")) - //del(I) - alien.client.images -= I - return +Des: Removes the alien infection image from all aliens in the world located in passed mob (C). +----------------------------------------*/ + +/datum/disease/alien_embryo/proc/RemoveInfectionImages(var/mob/living/carbon/C) + if (C) + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + for(var/image/I in alien.client.images) + if(I.loc == C) + if(dd_hasprefix_case(I.icon_state, "infected")) + //del(I) + alien.client.images -= I + return diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index a4c34c67c4e..3d0c532e252 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -1,57 +1,57 @@ -/datum/disease/appendicitis - form = "Condition" - name = "Appendicitis" - max_stages = 4 - spread = "Acute" - cure = "Surgery" - agent = "Appendix" - affected_species = list("Human") - permeability_mod = 1 - contagious_period = 9001 //slightly hacky, but hey! whatever works, right? - desc = "If left untreated the subject will become very weak, and may vomit often." - severity = "Medium" - longevity = 1000 - hidden = list(0, 1) - stage_minimum_age = 160 // at least 200 life ticks per stage - -/datum/disease/appendicitis/stage_act() - ..() - - if(istype(affected_mob,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = affected_mob - if(!H.internal_organs_by_name["appendix"]) - src.cure() - - if(stage == 1) - if(affected_mob.op_stage.appendix == 2.0) - // appendix is removed, can't get infected again - src.cure() - if(prob(5)) +/datum/disease/appendicitis + form = "Condition" + name = "Appendicitis" + max_stages = 4 + spread = "Acute" + cure = "Surgery" + agent = "Appendix" + affected_species = list("Human") + permeability_mod = 1 + contagious_period = 9001 //slightly hacky, but hey! whatever works, right? + desc = "If left untreated the subject will become very weak, and may vomit often." + severity = "Medium" + longevity = 1000 + hidden = list(0, 1) + stage_minimum_age = 160 // at least 200 life ticks per stage + +/datum/disease/appendicitis/stage_act() + ..() + + if(istype(affected_mob,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = affected_mob + if(!H.internal_organs_by_name["appendix"]) + src.cure() + + if(stage == 1) + if(affected_mob.op_stage.appendix == 2.0) + // appendix is removed, can't get infected again + src.cure() + if(prob(5)) to_chat(affected_mob, "You feel a stinging pain in your abdomen!") - affected_mob.emote("me",1,"winces slightly.") - if(stage > 1) - if(prob(3)) + affected_mob.emote("me",1,"winces slightly.") + if(stage > 1) + if(prob(3)) to_chat(affected_mob, "You feel a stabbing pain in your abdomen!") - affected_mob.emote("me",1,"winces painfully.") - affected_mob.adjustToxLoss(1) - if(stage > 2) - if(prob(1)) - if (affected_mob.nutrition > 100) - var/mob/living/carbon/human/H = affected_mob - H.vomit() - else + affected_mob.emote("me",1,"winces painfully.") + affected_mob.adjustToxLoss(1) + if(stage > 2) + if(prob(1)) + if (affected_mob.nutrition > 100) + var/mob/living/carbon/human/H = affected_mob + H.vomit() + else to_chat(affected_mob, "You gag as you want to throw up, but there's nothing in your stomach!") - affected_mob.Weaken(10) - affected_mob.adjustToxLoss(3) - if(stage > 3) - if(prob(1) && ishuman(affected_mob)) - var/mob/living/carbon/human/H = affected_mob + affected_mob.Weaken(10) + affected_mob.adjustToxLoss(3) + if(stage > 3) + if(prob(1) && ishuman(affected_mob)) + var/mob/living/carbon/human/H = affected_mob to_chat(H, "Your abdomen is a world of pain!") - H.Weaken(10) - H.op_stage.appendix = 2.0 - - var/datum/organ/external/groin = H.get_organ("groin") - var/datum/wound/W = new /datum/wound/internal_bleeding(20) - H.adjustToxLoss(25) - groin.wounds += W - src.cure() + H.Weaken(10) + H.op_stage.appendix = 2.0 + + var/datum/organ/external/groin = H.get_organ("groin") + var/datum/wound/W = new /datum/wound/internal_bleeding(20) + H.adjustToxLoss(25) + groin.wounds += W + src.cure() diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm index 75813be17d8..80fe8f78e8a 100644 --- a/code/datums/diseases/beesease.dm +++ b/code/datums/diseases/beesease.dm @@ -1,31 +1,31 @@ -/* -/datum/disease/beesease - name = "Beesease" - max_stages = 5 - spread = "Contact" //ie shot bees - cure = "???" - cure_id = "???" - agent = "Bees" - affected_species = list("Human","Monkey") - curable = 0 - -/datum/disease/beesease/stage_act() - ..() - switch(stage) - if(1) - if(prob(2)) +/* +/datum/disease/beesease + name = "Beesease" + max_stages = 5 + spread = "Contact" //ie shot bees + cure = "???" + cure_id = "???" + agent = "Bees" + affected_species = list("Human","Monkey") + curable = 0 + +/datum/disease/beesease/stage_act() + ..() + switch(stage) + if(1) + if(prob(2)) to_chat(affected_mob, "You feel like something is moving inside of you") - if(2) //also changes say, see say.dm - if(prob(2)) + if(2) //also changes say, see say.dm + if(prob(2)) to_chat(affected_mob, "You feel like something is moving inside of you") - if(prob(2)) + if(prob(2)) to_chat(affected_mob, "BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ") - if(3) - //Should give the bee spit verb - if(4) - //Plus bees now spit randomly - if(5) - //Plus if you die, you explode into bees - return -*/ + if(3) + //Should give the bee spit verb + if(4) + //Plus bees now spit randomly + if(5) + //Plus if you die, you explode into bees + return +*/ //Started working on it, but am too lazy to finish it today -- Urist \ No newline at end of file diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 0eb88e6b088..c167c6c7f96 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -1,67 +1,67 @@ -/datum/disease/brainrot - name = "Brainrot" - max_stages = 4 - spread = "On contact" - spread_type = CONTACT_GENERAL - cure = "Alkysine" - cure_id = list("alkysine") - agent = "Cryptococcus Cosmosis" - affected_species = list("Human") - curable = 0 - cure_chance = 15//higher chance to cure, since two reagents are required - desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." - severity = "Major" - -/datum/disease/brainrot/stage_act() //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist - ..() - switch(stage) - if(2) - if(prob(2)) - affected_mob.emote("blink") - if(prob(2)) - affected_mob.emote("yawn") - if(prob(2)) - to_chat(affected_mob, "Your don't feel like yourself.") - if(prob(5)) - affected_mob.adjustBrainLoss(1) - affected_mob.updatehealth() - if(3) - if(prob(2)) - affected_mob.emote("stare") - if(prob(2)) - affected_mob.emote("drool") - if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't retard you to death now - affected_mob.adjustBrainLoss(2) - affected_mob.updatehealth() - if(prob(2)) - to_chat(affected_mob, "Your try to remember something important...but can't.") -/* if(prob(10)) - affected_mob.adjustToxLoss(3) - affected_mob.updatehealth() - if(prob(2)) - to_chat(affected_mob, "Your head hurts." ) */ - if(4) - if(prob(2)) - affected_mob.emote("stare") - if(prob(2)) - affected_mob.emote("drool") -/* if(prob(15)) - affected_mob.adjustToxLoss(4) - affected_mob.updatehealth() - if(prob(2)) - to_chat(affected_mob, "Your head hurts.") */ - if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now - affected_mob.adjustBrainLoss(3) - affected_mob.updatehealth() - if(prob(2)) - to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") - if(prob(3)) - to_chat(affected_mob, "You lose consciousness...") - for(var/mob/O in viewers(affected_mob, null)) - O.show_message("[affected_mob] suddenly collapses", 1) - affected_mob.Paralyse(rand(5,10)) - if(prob(1)) - affected_mob.emote("snore") - if(prob(15)) - affected_mob.stuttering += 3 - return +/datum/disease/brainrot + name = "Brainrot" + max_stages = 4 + spread = "On contact" + spread_type = CONTACT_GENERAL + cure = "Alkysine" + cure_id = list("alkysine") + agent = "Cryptococcus Cosmosis" + affected_species = list("Human") + curable = 0 + cure_chance = 15//higher chance to cure, since two reagents are required + desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." + severity = "Major" + +/datum/disease/brainrot/stage_act() //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist + ..() + switch(stage) + if(2) + if(prob(2)) + affected_mob.emote("blink") + if(prob(2)) + affected_mob.emote("yawn") + if(prob(2)) + to_chat(affected_mob, "Your don't feel like yourself.") + if(prob(5)) + affected_mob.adjustBrainLoss(1) + affected_mob.updatehealth() + if(3) + if(prob(2)) + affected_mob.emote("stare") + if(prob(2)) + affected_mob.emote("drool") + if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't retard you to death now + affected_mob.adjustBrainLoss(2) + affected_mob.updatehealth() + if(prob(2)) + to_chat(affected_mob, "Your try to remember something important...but can't.") +/* if(prob(10)) + affected_mob.adjustToxLoss(3) + affected_mob.updatehealth() + if(prob(2)) + to_chat(affected_mob, "Your head hurts." ) */ + if(4) + if(prob(2)) + affected_mob.emote("stare") + if(prob(2)) + affected_mob.emote("drool") +/* if(prob(15)) + affected_mob.adjustToxLoss(4) + affected_mob.updatehealth() + if(prob(2)) + to_chat(affected_mob, "Your head hurts.") */ + if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now + affected_mob.adjustBrainLoss(3) + affected_mob.updatehealth() + if(prob(2)) + to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") + if(prob(3)) + to_chat(affected_mob, "You lose consciousness...") + for(var/mob/O in viewers(affected_mob, null)) + O.show_message("[affected_mob] suddenly collapses", 1) + affected_mob.Paralyse(rand(5,10)) + if(prob(1)) + affected_mob.emote("snore") + if(prob(15)) + affected_mob.stuttering += 3 + return diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm index cf830afe3c2..f87c231c18f 100644 --- a/code/datums/diseases/cold.dm +++ b/code/datums/diseases/cold.dm @@ -1,66 +1,66 @@ -/datum/disease/cold - name = "The Cold" - max_stages = 3 - spread = "Airborne" - cure = "Rest & Spaceacillin" - cure_id = "spaceacillin" - agent = "XY-rhinovirus" - affected_species = list("Human", "Monkey") - permeability_mod = 0.5 - desc = "If left untreated the subject will contract the flu." - severity = "Minor" - -/datum/disease/cold/stage_act() - ..() - switch(stage) - if(2) -/* - if(affected_mob.sleeping && prob(40)) //removed until sleeping is fixed +/datum/disease/cold + name = "The Cold" + max_stages = 3 + spread = "Airborne" + cure = "Rest & Spaceacillin" + cure_id = "spaceacillin" + agent = "XY-rhinovirus" + affected_species = list("Human", "Monkey") + permeability_mod = 0.5 + desc = "If left untreated the subject will contract the flu." + severity = "Minor" + +/datum/disease/cold/stage_act() + ..() + switch(stage) + if(2) +/* + if(affected_mob.sleeping && prob(40)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed + cure() + return +*/ + if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1) && prob(5)) + cure() + return + if(prob(1) && prob(5)) to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your throat feels sore.") - if(prob(1)) + if(prob(1)) to_chat(affected_mob, "Mucous runs down the back of your throat.") - if(3) -/* - if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed + if(3) +/* + if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed + cure() + return +*/ + if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1) && prob(1)) + cure() + return + if(prob(1) && prob(1)) to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your throat feels sore.") - if(prob(1)) + if(prob(1)) to_chat(affected_mob, "Mucous runs down the back of your throat.") - if(prob(1) && prob(50)) - if(!affected_mob.resistances.Find(/datum/disease/flu)) - var/datum/disease/Flu = new /datum/disease/flu(0) - affected_mob.contract_disease(Flu,1) + if(prob(1) && prob(50)) + if(!affected_mob.resistances.Find(/datum/disease/flu)) + var/datum/disease/Flu = new /datum/disease/flu(0) + affected_mob.contract_disease(Flu,1) cure() \ No newline at end of file diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index 777afe530a2..89e93780d4c 100644 --- a/code/datums/diseases/cold9.dm +++ b/code/datums/diseases/cold9.dm @@ -1,39 +1,39 @@ -/datum/disease/cold9 - name = "The Cold" - max_stages = 3 - spread = "On contact" - spread_type = CONTACT_GENERAL - cure = "Common Cold Anti-bodies & Spaceacillin" - cure_id = "spaceacillin" - agent = "ICE9-rhinovirus" - affected_species = list("Human") - desc = "If left untreated the subject will slow, as if partly frozen." - severity = "Moderate" - -/datum/disease/cold9/stage_act() - ..() - switch(stage) - if(2) - affected_mob.bodytemperature -= 10 - if(prob(1) && prob(10)) +/datum/disease/cold9 + name = "The Cold" + max_stages = 3 + spread = "On contact" + spread_type = CONTACT_GENERAL + cure = "Common Cold Anti-bodies & Spaceacillin" + cure_id = "spaceacillin" + agent = "ICE9-rhinovirus" + affected_species = list("Human") + desc = "If left untreated the subject will slow, as if partly frozen." + severity = "Moderate" + +/datum/disease/cold9/stage_act() + ..() + switch(stage) + if(2) + affected_mob.bodytemperature -= 10 + if(prob(1) && prob(10)) to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your throat feels sore.") - if(prob(5)) + if(prob(5)) to_chat(affected_mob, "You feel stiff.") - if(3) - affected_mob.bodytemperature -= 20 - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) + if(3) + affected_mob.bodytemperature -= 20 + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your throat feels sore.") - if(prob(10)) + if(prob(10)) to_chat(affected_mob, "You feel stiff.") diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 93cd1707675..7154231cd9e 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -1,69 +1,69 @@ -/datum/disease/dnaspread - name = "Space Retrovirus" - max_stages = 4 - spread = "On contact" - spread_type = CONTACT_GENERAL - cure = "Ryetalyn" - cure_id = "ryetalyn" - curable = 1 - agent = "S4E1 retrovirus" - affected_species = list("Human") - var/list/original_dna = list() - var/transformed = 0 - desc = "This disease transplants the genetic code of the intial vector into new hosts." - severity = "Medium" - - -/datum/disease/dnaspread/stage_act() - ..() - switch(stage) - if(2 || 3) //Pretend to be a cold and give time to spread. - if(prob(8)) - affected_mob.emote("sneeze") - if(prob(8)) - affected_mob.emote("cough") - if(prob(1)) +/datum/disease/dnaspread + name = "Space Retrovirus" + max_stages = 4 + spread = "On contact" + spread_type = CONTACT_GENERAL + cure = "Ryetalyn" + cure_id = "ryetalyn" + curable = 1 + agent = "S4E1 retrovirus" + affected_species = list("Human") + var/list/original_dna = list() + var/transformed = 0 + desc = "This disease transplants the genetic code of the intial vector into new hosts." + severity = "Medium" + + +/datum/disease/dnaspread/stage_act() + ..() + switch(stage) + if(2 || 3) //Pretend to be a cold and give time to spread. + if(prob(8)) + affected_mob.emote("sneeze") + if(prob(8)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_organ_damage(1) - if(prob(1)) + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(1)) to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(2) - affected_mob.updatehealth() - if(4) - if(!src.transformed) - if ((!strain_data["name"]) || (!strain_data["UI"]) || (!strain_data["SE"])) - del(affected_mob.virus) - return - - //Save original dna for when the disease is cured. - src.original_dna["name"] = affected_mob.real_name - src.original_dna["UI"] = affected_mob.dna.UI.Copy() - src.original_dna["SE"] = affected_mob.dna.SE.Copy() - + if(prob(20)) + affected_mob.adjustToxLoss(2) + affected_mob.updatehealth() + if(4) + if(!src.transformed) + if ((!strain_data["name"]) || (!strain_data["UI"]) || (!strain_data["SE"])) + del(affected_mob.virus) + return + + //Save original dna for when the disease is cured. + src.original_dna["name"] = affected_mob.real_name + src.original_dna["UI"] = affected_mob.dna.UI.Copy() + src.original_dna["SE"] = affected_mob.dna.SE.Copy() + to_chat(affected_mob, "You don't feel like yourself..") - var/list/newUI=strain_data["UI"] - var/list/newSE=strain_data["SE"] - affected_mob.UpdateAppearance(newUI.Copy()) - affected_mob.dna.SE = newSE.Copy() - affected_mob.dna.UpdateSE() - affected_mob.real_name = strain_data["name"] - domutcheck(affected_mob) - - src.transformed = 1 - src.carrier = 1 //Just chill out at stage 4 - - return - -/datum/disease/dnaspread/Del() - if ((original_dna["name"]) && (original_dna["UI"]) && (original_dna["SE"])) - var/list/newUI=original_dna["UI"] - var/list/newSE=original_dna["SE"] - affected_mob.UpdateAppearance(newUI.Copy()) - affected_mob.dna.SE = newSE.Copy() - affected_mob.dna.UpdateSE() - affected_mob.real_name = original_dna["name"] - + var/list/newUI=strain_data["UI"] + var/list/newSE=strain_data["SE"] + affected_mob.UpdateAppearance(newUI.Copy()) + affected_mob.dna.SE = newSE.Copy() + affected_mob.dna.UpdateSE() + affected_mob.real_name = strain_data["name"] + domutcheck(affected_mob) + + src.transformed = 1 + src.carrier = 1 //Just chill out at stage 4 + + return + +/datum/disease/dnaspread/Del() + if ((original_dna["name"]) && (original_dna["UI"]) && (original_dna["SE"])) + var/list/newUI=original_dna["UI"] + var/list/newSE=original_dna["SE"] + affected_mob.UpdateAppearance(newUI.Copy()) + affected_mob.dna.SE = newSE.Copy() + affected_mob.dna.UpdateSE() + affected_mob.real_name = original_dna["name"] + to_chat(affected_mob, "You feel more like yourself.") ..() \ No newline at end of file diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm index a7855c95b5d..1478d81caab 100644 --- a/code/datums/diseases/fake_gbs.dm +++ b/code/datums/diseases/fake_gbs.dm @@ -1,32 +1,32 @@ -/datum/disease/fake_gbs - name = "GBS" - max_stages = 5 - spread = "On contact" - spread_type = CONTACT_GENERAL - cure = "Synaptizine & Sulfur" - cure_id = list("synaptizine","sulfur") - agent = "Gravitokinetic Bipotential SADS-" - affected_species = list("Human", "Monkey") - desc = "If left untreated death will occur." - severity = "Major" - -/datum/disease/fake_gbs/stage_act() - ..() - switch(stage) - if(2) - if(prob(1)) - affected_mob.emote("sneeze") - if(3) - if(prob(5)) - affected_mob.emote("cough") - else if(prob(5)) - affected_mob.emote("gasp") - if(prob(10)) +/datum/disease/fake_gbs + name = "GBS" + max_stages = 5 + spread = "On contact" + spread_type = CONTACT_GENERAL + cure = "Synaptizine & Sulfur" + cure_id = list("synaptizine","sulfur") + agent = "Gravitokinetic Bipotential SADS-" + affected_species = list("Human", "Monkey") + desc = "If left untreated death will occur." + severity = "Major" + +/datum/disease/fake_gbs/stage_act() + ..() + switch(stage) + if(2) + if(prob(1)) + affected_mob.emote("sneeze") + if(3) + if(prob(5)) + affected_mob.emote("cough") + else if(prob(5)) + affected_mob.emote("gasp") + if(prob(10)) to_chat(affected_mob, "You're starting to feel very weak...") - if(4) - if(prob(10)) - affected_mob.emote("cough") - - if(5) - if(prob(10)) - affected_mob.emote("cough") + if(4) + if(prob(10)) + affected_mob.emote("cough") + + if(5) + if(prob(10)) + affected_mob.emote("cough") diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index facd4d54d5f..a1f3231f675 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -1,66 +1,66 @@ -/datum/disease/flu - name = "The Flu" - max_stages = 3 - spread = "Airborne" - cure = "Spaceacillin" - cure_id = "spaceacillin" - cure_chance = 10 - agent = "H13N1 flu virion" - affected_species = list("Human", "Monkey") - permeability_mod = 0.75 - desc = "If left untreated the subject will feel quite unwell." - severity = "Medium" - -/datum/disease/flu/stage_act() - ..() - switch(stage) - if(2) -/* - if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed --Blaank +/datum/disease/flu + name = "The Flu" + max_stages = 3 + spread = "Airborne" + cure = "Spaceacillin" + cure_id = "spaceacillin" + cure_chance = 10 + agent = "H13N1 flu virion" + affected_species = list("Human", "Monkey") + permeability_mod = 0.75 + desc = "If left untreated the subject will feel quite unwell." + severity = "Medium" + +/datum/disease/flu/stage_act() + ..() + switch(stage) + if(2) +/* + if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed --Blaank to_chat(affected_mob, "You feel better.") - stage-- - return -*/ - if(affected_mob.lying && prob(20)) //added until sleeping is fixed --Blaank + stage-- + return +*/ + if(affected_mob.lying && prob(20)) //added until sleeping is fixed --Blaank to_chat(affected_mob, "You feel better.") - stage-- - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_organ_damage(1) - if(prob(1)) + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(1)) to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - - if(3) -/* - if(affected_mob.sleeping && prob(15)) //removed until sleeping is fixed + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + + if(3) +/* + if(affected_mob.sleeping && prob(15)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - stage-- - return -*/ - if(affected_mob.lying && prob(15)) //added until sleeping is fixed + stage-- + return +*/ + if(affected_mob.lying && prob(15)) //added until sleeping is fixed to_chat(affected_mob, "You feel better.") - stage-- - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_organ_damage(1) - if(prob(1)) + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(1)) to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - return + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + return diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm index f196667e48a..c806d81a43f 100644 --- a/code/datums/diseases/fluspanish.dm +++ b/code/datums/diseases/fluspanish.dm @@ -1,36 +1,36 @@ -/datum/disease/fluspanish - name = "Spanish inquisition Flu" - max_stages = 3 - spread = "Airborne" - cure = "Spaceacillin & Anti-bodies to the common flu" - cure_id = "spaceacillin" - cure_chance = 10 - agent = "1nqu1s1t10n flu virion" - affected_species = list("Human") - permeability_mod = 0.75 - desc = "If left untreated the subject will burn to death for being a heretic." - severity = "Serious" - -/datum/disease/inquisition/stage_act() - ..() - switch(stage) - if(2) - affected_mob.bodytemperature += 10 - if(prob(5)) - affected_mob.emote("sneeze") - if(prob(5)) - affected_mob.emote("cough") - if(prob(1)) +/datum/disease/fluspanish + name = "Spanish inquisition Flu" + max_stages = 3 + spread = "Airborne" + cure = "Spaceacillin & Anti-bodies to the common flu" + cure_id = "spaceacillin" + cure_chance = 10 + agent = "1nqu1s1t10n flu virion" + affected_species = list("Human") + permeability_mod = 0.75 + desc = "If left untreated the subject will burn to death for being a heretic." + severity = "Serious" + +/datum/disease/inquisition/stage_act() + ..() + switch(stage) + if(2) + affected_mob.bodytemperature += 10 + if(prob(5)) + affected_mob.emote("sneeze") + if(prob(5)) + affected_mob.emote("cough") + if(prob(1)) to_chat(affected_mob, "You're burning in your own skin!") - affected_mob.take_organ_damage(0,5) - - if(3) - affected_mob.bodytemperature += 20 - if(prob(5)) - affected_mob.emote("sneeze") - if(prob(5)) - affected_mob.emote("cough") - if(prob(5)) + affected_mob.take_organ_damage(0,5) + + if(3) + affected_mob.bodytemperature += 20 + if(prob(5)) + affected_mob.emote("sneeze") + if(prob(5)) + affected_mob.emote("cough") + if(prob(5)) to_chat(affected_mob, "You're burning in your own skin!") - affected_mob.take_organ_damage(0,5) - return + affected_mob.take_organ_damage(0,5) + return diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index e9a92768744..81c7501f113 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -1,40 +1,40 @@ -/datum/disease/gbs - name = "GBS" - max_stages = 5 - spread = "On contact" - spread_type = CONTACT_GENERAL - cure = "Synaptizine & Sulfur" - cure_id = list("synaptizine","sulfur") - cure_chance = 15//higher chance to cure, since two reagents are required - agent = "Gravitokinetic Bipotential SADS+" - affected_species = list("Human") - curable = 0 - permeability_mod = 1 - -/datum/disease/gbs/stage_act() - ..() - switch(stage) - if(2) - if(prob(45)) - affected_mob.adjustToxLoss(5) - affected_mob.updatehealth() - if(prob(1)) - affected_mob.emote("sneeze") - if(3) - if(prob(5)) - affected_mob.emote("cough") - else if(prob(5)) - affected_mob.emote("gasp") - if(prob(10)) +/datum/disease/gbs + name = "GBS" + max_stages = 5 + spread = "On contact" + spread_type = CONTACT_GENERAL + cure = "Synaptizine & Sulfur" + cure_id = list("synaptizine","sulfur") + cure_chance = 15//higher chance to cure, since two reagents are required + agent = "Gravitokinetic Bipotential SADS+" + affected_species = list("Human") + curable = 0 + permeability_mod = 1 + +/datum/disease/gbs/stage_act() + ..() + switch(stage) + if(2) + if(prob(45)) + affected_mob.adjustToxLoss(5) + affected_mob.updatehealth() + if(prob(1)) + affected_mob.emote("sneeze") + if(3) + if(prob(5)) + affected_mob.emote("cough") + else if(prob(5)) + affected_mob.emote("gasp") + if(prob(10)) to_chat(affected_mob, "You're starting to feel very weak...") - if(4) - if(prob(10)) - affected_mob.emote("cough") - affected_mob.adjustToxLoss(5) - affected_mob.updatehealth() - if(5) + if(4) + if(prob(10)) + affected_mob.emote("cough") + affected_mob.adjustToxLoss(5) + affected_mob.updatehealth() + if(5) to_chat(affected_mob, "Your body feels as if it's trying to rip itself open...") - if(prob(50)) - affected_mob.gib() - else + if(prob(50)) + affected_mob.gib() + else return \ No newline at end of file diff --git a/code/datums/diseases/jungle_fever.dm b/code/datums/diseases/jungle_fever.dm index dba0c5f4a4f..f27ef32140b 100644 --- a/code/datums/diseases/jungle_fever.dm +++ b/code/datums/diseases/jungle_fever.dm @@ -1,12 +1,12 @@ -/datum/disease/jungle_fever - name = "Jungle Fever" - max_stages = 1 - cure = "None" - spread = "Bites" - spread_type = SPECIAL - affected_species = list("Monkey", "Human") - curable = 0 - desc = "monkeys with this disease will bite humans, causing humans to spontaneously mutate into a monkey." - severity = "Medium" - //stage_prob = 100 - agent = "Kongey Vibrion M-909" +/datum/disease/jungle_fever + name = "Jungle Fever" + max_stages = 1 + cure = "None" + spread = "Bites" + spread_type = SPECIAL + affected_species = list("Monkey", "Human") + curable = 0 + desc = "monkeys with this disease will bite humans, causing humans to spontaneously mutate into a monkey." + severity = "Medium" + //stage_prob = 100 + agent = "Kongey Vibrion M-909" diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index 1d5de1a8169..4b07d498a16 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -1,93 +1,93 @@ -/datum/disease/magnitis - name = "Magnitis" - max_stages = 4 - spread = "Airborne" - cure = "Iron" - cure_id = "iron" - agent = "Fukkos Miracos" - affected_species = list("Human") - curable = 0 - permeability_mod = 0.75 - desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." - severity = "Medium" - -/datum/disease/magnitis/stage_act() - ..() - switch(stage) - if(2) - if(prob(2)) +/datum/disease/magnitis + name = "Magnitis" + max_stages = 4 + spread = "Airborne" + cure = "Iron" + cure_id = "iron" + agent = "Fukkos Miracos" + affected_species = list("Human") + curable = 0 + permeability_mod = 0.75 + desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." + severity = "Medium" + +/datum/disease/magnitis/stage_act() + ..() + switch(stage) + if(2) + if(prob(2)) to_chat(affected_mob, "You feel a slight shock course through your body.") - if(prob(2)) - for(var/obj/M in orange(2,affected_mob)) - if(!M.anchored && (M.is_conductor())) - step_towards(M,affected_mob) - for(var/mob/living/silicon/S in orange(2,affected_mob)) - if(istype(S, /mob/living/silicon/ai)) continue - step_towards(S,affected_mob) - /* - if(M.x > affected_mob.x) - M.x-- - else if(M.x < affected_mob.x) - M.x++ - if(M.y > affected_mob.y) - M.y-- - else if(M.y < affected_mob.y) - M.y++ - */ - if(3) - if(prob(2)) + if(prob(2)) + for(var/obj/M in orange(2,affected_mob)) + if(!M.anchored && (M.is_conductor())) + step_towards(M,affected_mob) + for(var/mob/living/silicon/S in orange(2,affected_mob)) + if(istype(S, /mob/living/silicon/ai)) continue + step_towards(S,affected_mob) + /* + if(M.x > affected_mob.x) + M.x-- + else if(M.x < affected_mob.x) + M.x++ + if(M.y > affected_mob.y) + M.y-- + else if(M.y < affected_mob.y) + M.y++ + */ + if(3) + if(prob(2)) to_chat(affected_mob, "You feel a strong shock course through your body.") - if(prob(2)) + if(prob(2)) to_chat(affected_mob, "You feel like clowning around.") - if(prob(4)) - for(var/obj/M in orange(4,affected_mob)) - if(!M.anchored && (M.is_conductor())) - var/i - var/iter = rand(1,2) - for(i=0,i affected_mob.x) - M.x-=rand(1,min(3,M.x-affected_mob.x)) - else if(M.x < affected_mob.x) - M.x+=rand(1,min(3,affected_mob.x-M.x)) - if(M.y > affected_mob.y) - M.y-=rand(1,min(3,M.y-affected_mob.y)) - else if(M.y < affected_mob.y) - M.y+=rand(1,min(3,affected_mob.y-M.y)) - */ - if(4) - if(prob(2)) + if(prob(4)) + for(var/obj/M in orange(4,affected_mob)) + if(!M.anchored && (M.is_conductor())) + var/i + var/iter = rand(1,2) + for(i=0,i affected_mob.x) + M.x-=rand(1,min(3,M.x-affected_mob.x)) + else if(M.x < affected_mob.x) + M.x+=rand(1,min(3,affected_mob.x-M.x)) + if(M.y > affected_mob.y) + M.y-=rand(1,min(3,M.y-affected_mob.y)) + else if(M.y < affected_mob.y) + M.y+=rand(1,min(3,affected_mob.y-M.y)) + */ + if(4) + if(prob(2)) to_chat(affected_mob, "You feel a powerful shock course through your body.") - if(prob(2)) + if(prob(2)) to_chat(affected_mob, "You query upon the nature of miracles.") - if(prob(8)) - for(var/obj/M in orange(6,affected_mob)) - if(!M.anchored && (M.is_conductor())) - var/i - var/iter = rand(1,3) - for(i=0,i affected_mob.x) - M.x-=rand(1,min(5,M.x-affected_mob.x)) - else if(M.x < affected_mob.x) - M.x+=rand(1,min(5,affected_mob.x-M.x)) - if(M.y > affected_mob.y) - M.y-=rand(1,min(5,M.y-affected_mob.y)) - else if(M.y < affected_mob.y) - M.y+=rand(1,min(5,affected_mob.y-M.y)) - */ + if(prob(8)) + for(var/obj/M in orange(6,affected_mob)) + if(!M.anchored && (M.is_conductor())) + var/i + var/iter = rand(1,3) + for(i=0,i affected_mob.x) + M.x-=rand(1,min(5,M.x-affected_mob.x)) + else if(M.x < affected_mob.x) + M.x+=rand(1,min(5,affected_mob.x-M.x)) + if(M.y > affected_mob.y) + M.y-=rand(1,min(5,M.y-affected_mob.y)) + else if(M.y < affected_mob.y) + M.y+=rand(1,min(5,affected_mob.y-M.y)) + */ return \ No newline at end of file diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm index d0ef2a97906..4ebb0bd5747 100644 --- a/code/datums/diseases/pierrot_throat.dm +++ b/code/datums/diseases/pierrot_throat.dm @@ -1,30 +1,30 @@ -/datum/disease/pierrot_throat - name = "Pierrot's Throat" - max_stages = 4 - spread = "Airborne" - cure = "A whole banana." - cure_id = "banana" - cure_chance = 75 - curable=1 - agent = "H0NI<42 Virus" - affected_species = list("Human") - permeability_mod = 0.75 - desc = "If left untreated the subject will probably drive others to insanity." - severity = "Medium" - longevity = 400 - -/datum/disease/pierrot_throat/stage_act() - ..() - switch(stage) - if(1) +/datum/disease/pierrot_throat + name = "Pierrot's Throat" + max_stages = 4 + spread = "Airborne" + cure = "A whole banana." + cure_id = "banana" + cure_chance = 75 + curable=1 + agent = "H0NI<42 Virus" + affected_species = list("Human") + permeability_mod = 0.75 + desc = "If left untreated the subject will probably drive others to insanity." + severity = "Medium" + longevity = 400 + +/datum/disease/pierrot_throat/stage_act() + ..() + switch(stage) + if(1) if(prob(10)) to_chat(affected_mob, "You feel a little silly.") - if(2) + if(2) if(prob(10)) to_chat(affected_mob, "You start seeing rainbows.") - if(3) + if(3) if(prob(10)) to_chat(affected_mob, "Your thoughts are interrupted by a loud HONK!") - if(4) - if(prob(5)) - affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) + if(4) + if(prob(5)) + affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) ) diff --git a/code/datums/diseases/plasmatoid.dm b/code/datums/diseases/plasmatoid.dm index 232371cd3b2..12e0476b631 100644 --- a/code/datums/diseases/plasmatoid.dm +++ b/code/datums/diseases/plasmatoid.dm @@ -1,5 +1,5 @@ -/datum/disease/plasmatoid - name = "Plasmatoid" - max_stages = 4 - cure = "None" +/datum/disease/plasmatoid + name = "Plasmatoid" + max_stages = 4 + cure = "None" affected_species = list("Monkey", "Human") \ No newline at end of file diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 35d59996fc7..a5128562eef 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -1,108 +1,108 @@ -/datum/disease/dna_retrovirus - name = "Retrovirus" - max_stages = 4 - spread = "Contact" - spread_type = CONTACT_GENERAL - cure = "Rest or an injection of ryetalyn" - cure_chance = 6 - agent = "" - affected_species = list("Human") - desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly." - severity = "Severe" - permeability_mod = 0.4 - stage_prob = 2 - var/SE - var/UI - var/restcure = 0 - New() - ..() - agent = "Virus class [pick("A","B","C","D","E","F")][pick("A","B","C","D","E","F")]-[rand(50,300)]" - if(prob(40)) - cure_id = list("ryetalyn") - cure_list = list("ryetalyn") - else - restcure = 1 - - - - -/datum/disease/dna_retrovirus/stage_act() - ..() - switch(stage) - if(1) - if(restcure) -/* - if(affected_mob.sleeping && prob(30)) //removed until sleeping is fixed +/datum/disease/dna_retrovirus + name = "Retrovirus" + max_stages = 4 + spread = "Contact" + spread_type = CONTACT_GENERAL + cure = "Rest or an injection of ryetalyn" + cure_chance = 6 + agent = "" + affected_species = list("Human") + desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly." + severity = "Severe" + permeability_mod = 0.4 + stage_prob = 2 + var/SE + var/UI + var/restcure = 0 + New() + ..() + agent = "Virus class [pick("A","B","C","D","E","F")][pick("A","B","C","D","E","F")]-[rand(50,300)]" + if(prob(40)) + cure_id = list("ryetalyn") + cure_list = list("ryetalyn") + else + restcure = 1 + + + + +/datum/disease/dna_retrovirus/stage_act() + ..() + switch(stage) + if(1) + if(restcure) +/* + if(affected_mob.sleeping && prob(30)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(30)) //changed FROM prob(20) until sleeping is fixed + cure() + return +*/ + if(affected_mob.lying && prob(30)) //changed FROM prob(20) until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(8)) + cure() + return + if (prob(8)) to_chat(affected_mob, "Your head hurts.") - if (prob(9)) + if (prob(9)) to_chat(affected_mob, "You feel a tingling sensation in your chest.") - if (prob(9)) + if (prob(9)) to_chat(affected_mob, "You feel angry.") - if(2) - if(restcure) -/* - if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed + if(2) + if(restcure) +/* + if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed + cure() + return +*/ + if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(8)) + cure() + return + if (prob(8)) to_chat(affected_mob, "Your skin feels loose.") - if (prob(10)) + if (prob(10)) to_chat(affected_mob, "You feel very strange.") - if (prob(4)) + if (prob(4)) to_chat(affected_mob, "You feel a stabbing pain in your head!") - affected_mob.Paralyse(2) - if (prob(4)) + affected_mob.Paralyse(2) + if (prob(4)) to_chat(affected_mob, "Your stomach churns.") - if(3) - if(restcure) -/* - if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed + if(3) + if(restcure) +/* + if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed + cure() + return +*/ + if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(10)) + cure() + return + if (prob(10)) to_chat(affected_mob, "Your entire body vibrates.") - - if (prob(35)) - if(prob(50)) - scramble(1, affected_mob, rand(15,45)) - else - scramble(0, affected_mob, rand(15,45)) - - if(4) - if(restcure) -/* - if(affected_mob.sleeping && prob(10)) //removed until sleeping is fixed + + if (prob(35)) + if(prob(50)) + scramble(1, affected_mob, rand(15,45)) + else + scramble(0, affected_mob, rand(15,45)) + + if(4) + if(restcure) +/* + if(affected_mob.sleeping && prob(10)) //removed until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(5)) //changed FROM prob(5) until sleeping is fixed + cure() + return +*/ + if(affected_mob.lying && prob(5)) //changed FROM prob(5) until sleeping is fixed to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(60)) - if(prob(50)) - scramble(1, affected_mob, rand(50,75)) - else + cure() + return + if (prob(60)) + if(prob(50)) + scramble(1, affected_mob, rand(50,75)) + else scramble(0, affected_mob, rand(50,75)) \ No newline at end of file diff --git a/code/datums/diseases/robotic_transformation.dm b/code/datums/diseases/robotic_transformation.dm index f107d4ba2f7..3c1414c9e31 100644 --- a/code/datums/diseases/robotic_transformation.dm +++ b/code/datums/diseases/robotic_transformation.dm @@ -1,62 +1,62 @@ -//Nanomachines! - -/datum/disease/robotic_transformation - name = "Robotic Transformation" - max_stages = 5 - spread = "Syringe" - spread_type = SPECIAL - cure = "An injection of copper." - cure_id = list("copper") - cure_chance = 5 - agent = "R2D2 Nanomachines" - affected_species = list("Human") - desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg." - severity = "Major" - var/gibbed = 0 - -/datum/disease/robotic_transformation/stage_act() - ..() - switch(stage) - if(2) - if (prob(8)) +//Nanomachines! + +/datum/disease/robotic_transformation + name = "Robotic Transformation" + max_stages = 5 + spread = "Syringe" + spread_type = SPECIAL + cure = "An injection of copper." + cure_id = list("copper") + cure_chance = 5 + agent = "R2D2 Nanomachines" + affected_species = list("Human") + desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg." + severity = "Major" + var/gibbed = 0 + +/datum/disease/robotic_transformation/stage_act() + ..() + switch(stage) + if(2) + if (prob(8)) to_chat(affected_mob, "Your joints feel stiff.") - affected_mob.take_organ_damage(1) - if (prob(9)) + affected_mob.take_organ_damage(1) + if (prob(9)) to_chat(affected_mob, "Beep...boop..") - if (prob(9)) + if (prob(9)) to_chat(affected_mob, "Bop...beeep...") - if(3) - if (prob(8)) + if(3) + if (prob(8)) to_chat(affected_mob, "Your joints feel very stiff.") - affected_mob.take_organ_damage(1) - if (prob(8)) - affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) - if (prob(10)) + affected_mob.take_organ_damage(1) + if (prob(8)) + affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) + if (prob(10)) to_chat(affected_mob, "Your skin feels loose.") - affected_mob.take_organ_damage(5) - if (prob(4)) + affected_mob.take_organ_damage(5) + if (prob(4)) to_chat(affected_mob, "You feel a stabbing pain in your head.") - affected_mob.Paralyse(2) - if (prob(4)) + affected_mob.Paralyse(2) + if (prob(4)) to_chat(affected_mob, "You can feel something move...inside.") - if(4) - if (prob(10)) + if(4) + if (prob(10)) to_chat(affected_mob, "Your skin feels very loose.") - affected_mob.take_organ_damage(8) - if (prob(20)) - affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee...")) - if (prob(8)) + affected_mob.take_organ_damage(8) + if (prob(20)) + affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee...")) + if (prob(8)) to_chat(affected_mob, "You can feel... something...inside you.") - if(5) + if(5) to_chat(affected_mob, "Your skin feels as if it's about to burst off...") - affected_mob.adjustToxLoss(10) - affected_mob.updatehealth() - if(prob(40)) //So everyone can feel like robot Seth Brundle - if(src.gibbed != 0) return 0 - gibs(affected_mob) - gibbed = 1 - var/mob/living/carbon/human/H = affected_mob - if(istype(H) && !jobban_isbanned(affected_mob, "Cyborg")) - H.Robotize() - else - affected_mob.death(1) + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(40)) //So everyone can feel like robot Seth Brundle + if(src.gibbed != 0) return 0 + gibs(affected_mob) + gibbed = 1 + var/mob/living/carbon/human/H = affected_mob + if(istype(H) && !jobban_isbanned(affected_mob, "Cyborg")) + H.Robotize() + else + affected_mob.death(1) diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index f731eaee422..f33e25bf86c 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -1,122 +1,122 @@ -/datum/disease/wizarditis - name = "Wizarditis" - max_stages = 4 - spread = "Airborne" - cure = "The Manly Dorf" - cure_id = "manlydorf" - cure_chance = 100 - agent = "Rincewindus Vulgaris" - affected_species = list("Human") - curable = 1 - permeability_mod = 0.75 - desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition." - severity = "Major" - - -/* -BIRUZ BENNAR -SCYAR NILA - teleport -NEC CANTIO - dis techno -EI NATH - shocking grasp -AULIE OXIN FIERA - knock -TARCOL MINTI ZHERI - forcewall -STI KALY - blind -*/ - -/datum/disease/wizarditis/stage_act() - ..() - - switch(stage) - if(2) - if(prob(1)&&prob(50)) - affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!")) - if(prob(1)&&prob(50)) - to_chat(affected_mob, "You feel [pick("that you don't have enough mana.", "that the winds of magic are gone.", "an urge to summon familiar.")]") - - - if(3) - if(prob(1)&&prob(50)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!")) - if(prob(1)&&prob(50)) - to_chat(affected_mob, "You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar.")].") - - if(4) - - if(prob(1)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!")) - return - if(prob(1)&&prob(50)) - to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].") - spawn_wizard_clothes(50) - if(prob(1)&&prob(1)) - teleport() - return - - - -/datum/disease/wizarditis/proc/spawn_wizard_clothes(var/chance = 0) - if(istype(affected_mob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = affected_mob - if(prob(chance)) - if(!istype(H.head, /obj/item/clothing/head/wizard)) - if(H.head) - H.drop_from_inventory(H.head) - H.head = new /obj/item/clothing/head/wizard(H) - H.head.layer = 20 - return - if(prob(chance)) - if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe)) - if(H.wear_suit) - H.drop_from_inventory(H.wear_suit) - H.wear_suit = new /obj/item/clothing/suit/wizrobe(H) - H.wear_suit.layer = 20 - return - if(prob(chance)) - if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) - if(H.shoes) - H.drop_from_inventory(H.shoes) - H.shoes = new /obj/item/clothing/shoes/sandal(H) - H.shoes.layer = 20 - return - else - var/mob/living/carbon/H = affected_mob - if(prob(chance)) - if(!istype(H.r_hand, /obj/item/weapon/staff)) - if(H.r_hand || H.drop_item(H.r_hand)) - H.put_in_r_hand( new /obj/item/weapon/staff(H) ) - return - return - - - -/datum/disease/wizarditis/proc/teleport() - var/list/theareas = new/list() - for(var/area/AR in orange(80, affected_mob)) - if(theareas.Find(AR) || isspace(AR)) continue - theareas += AR - - if(!theareas) - return - - var/area/thearea = pick(theareas) - - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(T.z != affected_mob.z) continue - if(T.name == "space") continue - if(!T.density) - var/clear = 1 - for(var/obj/O in T) - if(O.density) - clear = 0 - break - if(clear) - L+=T - - if(!L) - return - - affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!") - affected_mob.loc = pick(L) - - return +/datum/disease/wizarditis + name = "Wizarditis" + max_stages = 4 + spread = "Airborne" + cure = "The Manly Dorf" + cure_id = "manlydorf" + cure_chance = 100 + agent = "Rincewindus Vulgaris" + affected_species = list("Human") + curable = 1 + permeability_mod = 0.75 + desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition." + severity = "Major" + + +/* +BIRUZ BENNAR +SCYAR NILA - teleport +NEC CANTIO - dis techno +EI NATH - shocking grasp +AULIE OXIN FIERA - knock +TARCOL MINTI ZHERI - forcewall +STI KALY - blind +*/ + +/datum/disease/wizarditis/stage_act() + ..() + + switch(stage) + if(2) + if(prob(1)&&prob(50)) + affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!")) + if(prob(1)&&prob(50)) + to_chat(affected_mob, "You feel [pick("that you don't have enough mana.", "that the winds of magic are gone.", "an urge to summon familiar.")]") + + + if(3) + if(prob(1)&&prob(50)) + affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!")) + if(prob(1)&&prob(50)) + to_chat(affected_mob, "You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar.")].") + + if(4) + + if(prob(1)) + affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!")) + return + if(prob(1)&&prob(50)) + to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].") + spawn_wizard_clothes(50) + if(prob(1)&&prob(1)) + teleport() + return + + + +/datum/disease/wizarditis/proc/spawn_wizard_clothes(var/chance = 0) + if(istype(affected_mob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = affected_mob + if(prob(chance)) + if(!istype(H.head, /obj/item/clothing/head/wizard)) + if(H.head) + H.drop_from_inventory(H.head) + H.head = new /obj/item/clothing/head/wizard(H) + H.head.layer = 20 + return + if(prob(chance)) + if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe)) + if(H.wear_suit) + H.drop_from_inventory(H.wear_suit) + H.wear_suit = new /obj/item/clothing/suit/wizrobe(H) + H.wear_suit.layer = 20 + return + if(prob(chance)) + if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) + if(H.shoes) + H.drop_from_inventory(H.shoes) + H.shoes = new /obj/item/clothing/shoes/sandal(H) + H.shoes.layer = 20 + return + else + var/mob/living/carbon/H = affected_mob + if(prob(chance)) + if(!istype(H.r_hand, /obj/item/weapon/staff)) + if(H.r_hand || H.drop_item(H.r_hand)) + H.put_in_r_hand( new /obj/item/weapon/staff(H) ) + return + return + + + +/datum/disease/wizarditis/proc/teleport() + var/list/theareas = new/list() + for(var/area/AR in orange(80, affected_mob)) + if(theareas.Find(AR) || isspace(AR)) continue + theareas += AR + + if(!theareas) + return + + var/area/thearea = pick(theareas) + + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(T.z != affected_mob.z) continue + if(T.name == "space") continue + if(!T.density) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + + if(!L) + return + + affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!") + affected_mob.loc = pick(L) + + return diff --git a/code/datums/diseases/xeno_transformation.dm b/code/datums/diseases/xeno_transformation.dm index 62bea1404a2..944ef95c8cf 100644 --- a/code/datums/diseases/xeno_transformation.dm +++ b/code/datums/diseases/xeno_transformation.dm @@ -1,59 +1,59 @@ -//Xenomicrobes - -/datum/disease/xeno_transformation - name = "Xenomorph Transformation" - max_stages = 5 - spread = "Syringe" - spread_type = SPECIAL - cure = "Spaceacillin & Glycerol" - cure_id = list("spaceacillin", "glycerol") - cure_chance = 5 - agent = "Rip-LEY Alien Microbes" - affected_species = list("Human") - var/gibbed = 0 - -/datum/disease/xeno_transformation/stage_act() - ..() - switch(stage) - if(2) - if (prob(8)) +//Xenomicrobes + +/datum/disease/xeno_transformation + name = "Xenomorph Transformation" + max_stages = 5 + spread = "Syringe" + spread_type = SPECIAL + cure = "Spaceacillin & Glycerol" + cure_id = list("spaceacillin", "glycerol") + cure_chance = 5 + agent = "Rip-LEY Alien Microbes" + affected_species = list("Human") + var/gibbed = 0 + +/datum/disease/xeno_transformation/stage_act() + ..() + switch(stage) + if(2) + if (prob(8)) to_chat(affected_mob, "Your throat feels scratchy.") - affected_mob.take_organ_damage(1) - if (prob(9)) + affected_mob.take_organ_damage(1) + if (prob(9)) to_chat(affected_mob, "Kill...") - if (prob(9)) + if (prob(9)) to_chat(affected_mob, "Kill...") - if(3) - if (prob(8)) + if(3) + if (prob(8)) to_chat(affected_mob, "Your throat feels very scratchy.") - affected_mob.take_organ_damage(1) - /* - if (prob(8)) - affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) - */ - if (prob(10)) + affected_mob.take_organ_damage(1) + /* + if (prob(8)) + affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop")) + */ + if (prob(10)) to_chat(affected_mob, "Your skin feels tight.") - affected_mob.take_organ_damage(5) - if (prob(4)) + affected_mob.take_organ_damage(5) + if (prob(4)) to_chat(affected_mob, "You feel a stabbing pain in your head.") - affected_mob.Paralyse(2) - if (prob(4)) + affected_mob.Paralyse(2) + if (prob(4)) to_chat(affected_mob, "You can feel something move...inside.") - if(4) - if (prob(10)) + if(4) + if (prob(10)) to_chat(affected_mob, pick("Your skin feels very tight.", "Your blood boils!")) - affected_mob.take_organ_damage(8) - if (prob(20)) - affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!")) - if (prob(8)) + affected_mob.take_organ_damage(8) + if (prob(20)) + affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!")) + if (prob(8)) to_chat(affected_mob, "You can feel... something...inside you.") - if(5) + if(5) to_chat(affected_mob, "Your skin feels impossibly calloused...") - affected_mob.adjustToxLoss(10) - affected_mob.updatehealth() - if(prob(40)) - if(gibbed != 0) return 0 - gibs(affected_mob) - gibbed = 1 - affected_mob:Alienize() - + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(40)) + if(gibbed != 0) return 0 + gibs(affected_mob) + gibbed = 1 + affected_mob:Alienize() + diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm index 83e252aefa1..98578cf2273 100644 --- a/code/datums/helper_datums/construction_datum.dm +++ b/code/datums/helper_datums/construction_datum.dm @@ -1,415 +1,415 @@ -#define FORWARD -1 -#define BACKWARD 1 - -#define Co_KEY "key" -#define Co_VIS_MSG "vis_msg" -#define Co_START_MSG "start_msg" -#define Co_AMOUNT "amount" -#define Co_MAX_AMOUNT "max_amount" -#define Co_DELAY "delay" -#define Co_KEEP "keep" //if permanence is set to 0, we can still store specific step items by including this in the step -#define Co_TAKE "take" //if we want to actually have a stack or weldingtool in construction, rather than weld or add a stack, we can use this override -#define Co_DESC "desc" - -#define Co_NEXTSTEP "nextstep" -#define Co_BACKSTEP "backstep" - -#define Co_CON_SPEED "construct" //For tools. See tools.dm -#define Co_DECON_SPEED "deconstruct" //For tools. See tools.dm - -/datum/construction - var/list/steps - var/atom/holder - var/result - var/list/steps_desc - var/taskpath = null // Path of job objective completed. - var/assembling = 0 //if we're in a step, we won't be allowed to do another step - var/permanence = 0 - var/list/used_atoms = list() //contains the stuff we add. Can be used in multiple-choice construction - -/datum/construction/New(atom) - ..() - holder = atom - if(!holder) //don't want this without a holder - spawn - qdel (src) - set_desc(steps.len) - add_max_amounts() - return - -/datum/construction/proc/next_step(mob/user as mob) - steps.len-- - if(!steps.len) - spawn_result(user) - else - set_desc(steps.len) - return - -/datum/construction/proc/action(atom/used_atom,mob/user as mob) - return - -/datum/construction/proc/check_step(atom/used_atom,mob/user as mob) //check last step only - var/valid_step = is_right_key(user,used_atom) - if(valid_step) - assembling = 1 - if(custom_action(steps[valid_step], used_atom, user)) - next_step(user) - assembling = 0 - return 1 - assembling = 0 - return 0 - -/datum/construction/proc/is_right_key(mob/user as mob, atom/used_atom) // returns current step num if used_atom is of the right type. - if(assembling) return 0 - var/list/L = steps[steps.len] - if((istype(L[Co_KEY], /list) && is_type_in_list(used_atom, L[Co_KEY])) || istype(used_atom, L[Co_KEY])) - //if our keys are in a list, we want to check them all - //otherwise, sanity permits setting it as a single type and checking that - if(!try_consume(user, used_atom, L)) - return 0 - return steps.len - return 0 - -/datum/construction/proc/custom_action(step, used_atom, user) - if(istype(used_atom, /obj/item/weapon/weldingtool)) - playsound(holder, 'sound/items/Welder2.ogg', 50, 1) - - else if(istype(used_atom, /obj/item/weapon/wrench)) - playsound(holder, 'sound/items/Ratchet.ogg', 50, 1) - - else if(istype(used_atom, /obj/item/weapon/screwdriver)) - playsound(holder, 'sound/items/Screwdriver.ogg', 50, 1) - - else if(istype(used_atom, /obj/item/weapon/wirecutters)) - playsound(holder, 'sound/items/Wirecutter.ogg', 50, 1) - - construct_message(step, user) - return 1 - - -/datum/construction/proc/fixText(text,user,self=0) - if(self) - text = replacetext(text, "{s}", "") - text = replacetext(text, "{USER}", "You") - else - text = replacetext(text, "{s}", "s") - text = replacetext(text,"{USER}","[user]") - text = replacetext(text,"{HOLDER}","[holder]") - return text - -/datum/construction/proc/construct_message(step, mob/user) - if(Co_VIS_MSG in step) - user.visible_message(fixText(step[Co_VIS_MSG],user), fixText(step[Co_VIS_MSG],user,1)) - -/datum/construction/proc/start_construct_message(step, mob/user, atom/movable/used_atom) - if(Co_START_MSG in step) - user.visible_message(fixText(step[Co_START_MSG],user), fixText(step[Co_START_MSG],user,1)) - -/datum/construction/proc/check_all_steps(atom/used_atom,mob/user as mob) //check all steps, remove matching one. - for(var/i=1;i<=steps.len;i++) - var/list/L = steps[i]; - if((islist(L[Co_KEY]) && is_type_in_list(used_atom, L[Co_KEY])) ||istype(used_atom, L[Co_KEY])) - if(custom_action(L, used_atom, user)) - steps[i]=null;//stupid byond list from list removal... - listclearnulls(steps); - if(!steps.len) - spawn_result(user) - return 1 - return 0 - - -/datum/construction/proc/spawn_result(mob/user as mob) - if(result) - testing("[user] finished a [result]!") - - new result(get_turf(holder)) - spawn() - qdel (holder) - holder = null - return - -/datum/construction/proc/set_desc(index as num) - var/list/step = steps[index] - holder.desc = step[Co_DESC] - return - -/datum/construction/proc/try_consume(mob/user as mob, atom/movable/used_atom, given_step) - if(used_atom.construction_delay_mult && !used_atom.construction_delay_mult[Co_CON_SPEED]) - to_chat(user, "This tool only works for deconstruction!")//It doesn't technically have to be a tool to cause this message, but it wouldn't make sense for anything else to do so. - - return 0 - - if(!(Co_AMOUNT in given_step) && !(Co_DELAY in given_step)) - return 1 - - - var/delay = 0 - if(Co_DELAY in given_step) - if(used_atom.construction_delay_mult) - delay = given_step[Co_DELAY] * used_atom.construction_delay_mult[Co_CON_SPEED] - else - delay = given_step[Co_DELAY] - if(delay > 0) - start_construct_message(given_step, user, used_atom) - if(!do_after(user, src.holder, delay, needhand = 1)) - return 0 - - var/amount = 0 - if(Co_AMOUNT in given_step) - amount = given_step[Co_AMOUNT] - if(amount>0) - // STACKS - if(istype(used_atom,/obj/item/stack) && !(Co_TAKE in given_step)) - var/obj/item/stack/stack=used_atom - if(stack.amount < amount) - to_chat(user, "You start adding [stack] to \the [holder]. It still needs [amount - stack.amount] [stack.singular_name].") - given_step[Co_AMOUNT] -= stack.amount - stack.use(stack.amount) - return 0 - stack.use(amount) - // WELDER - else if(istype(used_atom,/obj/item/weapon/weldingtool) && !(Co_TAKE in given_step)) - var/obj/item/weapon/weldingtool/welder=used_atom - if(!welder.isOn()) - to_chat(user, "You tap \the [holder] with your unlit welder. [pick("Ding","Dong")].") - return 0 - if(!welder.remove_fuel(amount,user)) - to_chat(user, "You don't have enough fuel!") - return 0 - //generic things - else - var/atom_name = used_atom.name - if(permanence || (Co_KEEP in given_step)) - if(user.drop_item(used_atom, holder)) - used_atoms.Add(list("[steps.Find(given_step)]" = used_atom)) - else - qdel(used_atom) - given_step[Co_AMOUNT]-- - if(given_step[Co_AMOUNT] > 0) - to_chat(user, "You add \a [atom_name] to \the [holder]. It still needs [amount -1 ] [atom_name]\s.") - return 0 - given_step[Co_AMOUNT] = given_step[Co_MAX_AMOUNT] - return 1 - -/datum/construction/proc/add_max_amounts() - for(var/list/this_step in steps) - if((Co_AMOUNT in this_step)) - this_step.Add(list(Co_MAX_AMOUNT = this_step[Co_AMOUNT])) //puts in something we can refer to when we reset the step - -/datum/construction/reversible - var/index - -/datum/construction/reversible/New(atom) - ..() - index = steps.len - return - -/datum/construction/reversible/proc/update_index(diff as num, mob/user as mob) - index+=diff - if(index==0) - spawn_result(user) - else - set_desc(index) - return - -/datum/construction/reversible/is_right_key(mob/user as mob,atom/used_atom) // returns index step - if(assembling) return 0 - assembling = 1 - var/list/step_next = get_forward_step(index) - var/list/step_back = get_backward_step(index) - if(step_next && ((islist(step_next[Co_KEY]) && is_type_in_list(used_atom, step_next[Co_KEY])) || istype(used_atom, step_next[Co_KEY]))) - //if our keys are in a list, we want to check them all - //otherwise, sanity permits setting it as a single type and checking that - if(!try_consume(user, used_atom, step_next, index, FORWARD)) - assembling = 0 - return 0 - return FORWARD //to the first step -> forward - if(step_back && ((islist(step_back[Co_KEY]) && is_type_in_list(used_atom, step_back[Co_KEY])) || istype(used_atom, step_back[Co_KEY]))) - if(!try_consume(user, used_atom, step_back, index, BACKWARD)) - assembling = 0 - return 0 - return BACKWARD //to the last step -> backwards - assembling = 0 - return 0 - -/datum/construction/reversible/check_step(atom/used_atom,mob/user as mob) - var/diff = is_right_key(user,used_atom) - if(diff) - assembling = 1 - if(custom_action(index, diff, used_atom, user)) - update_index(diff,user) - assembling = 0 - return 1 - assembling = 0 - return 0 - -/datum/construction/reversible/custom_action(index, diff, used_atom, user) - . = ..(index,used_atom,user) - - if(.) - construct_message(steps[index], user, diff, 1) - -/datum/construction/reversible/construct_message(step, mob/user, diff, override) - if(!override) - return - var/message_step - if(diff == FORWARD && (Co_NEXTSTEP in step)) - message_step = step[Co_NEXTSTEP] - else if (Co_BACKSTEP in step) - message_step = step[Co_BACKSTEP] - if(message_step) - user.visible_message(fixText(message_step[Co_VIS_MSG],user), fixText(message_step[Co_VIS_MSG],user,1)) - -/datum/construction/reversible/start_construct_message(step, mob/user, atom/movable/used_atom) - user.visible_message(fixText(step[Co_START_MSG],user), fixText(step[Co_START_MSG],user,1)) - -/datum/construction/reversible/add_max_amounts() - for(var/i = 1; i <= steps.len; i++) - var/list/dir_step = get_forward_step(i) - if((Co_AMOUNT in dir_step)) - dir_step.Add(list(Co_MAX_AMOUNT = dir_step[Co_AMOUNT])) //puts in something we can refer to when we reset the step - - dir_step = get_backward_step(i) - if((Co_AMOUNT in dir_step)) - dir_step.Add(list(Co_MAX_AMOUNT = dir_step[Co_AMOUNT])) - - //NOT IN PLACE: message segments like verbs can be written as {UN|forwardmessage|backwardmessage}. This formats that in selection -/datum/construction/reversible/fixText(message, mob/user, self = 0) - return ..(message, user, self) - /* - while("{UN|" in text) - var/start_bracket = findtext(text, "{") - var/this_verb = copytext(text, start_bracket, findtext(text, "}", start_bracket + 1)) - to_chat(world, this_verb) - var/marker = findtext(this_verb, "|") - var/final_verb = "" - if(diff == FORWARD) - final_verb = copytext(this_verb, marker + 1, findtext(this_verb, "|", marker + 1)) - else - final_verb = copytext(this_verb, findtext(this_verb, "|", marker + 1), findtext(text, "}", start_bracket + 1)) - to_chat(world, final_verb) - replacetext(text, this_verb, final_verb) - */ - -/datum/construction/reversible/try_consume(mob/user as mob, atom/movable/used_atom, given_step, index, diff) - //if we've made some progress on a step, we want to drop it - var/current_step = (diff == BACKWARD ? get_forward_step(index) : get_backward_step(index)) - if(used_atom.construction_delay_mult && !used_atom.construction_delay_mult[diff == FORWARD ? Co_CON_SPEED : Co_DECON_SPEED]) - to_chat(user, "This tool only works for [diff == FORWARD ? "de" : ""]construction!")//It doesn't technically have to be a tool to cause this message, but it wouldn't make sense for anything else to do so. - - return 0 - if(current_step && (Co_AMOUNT in current_step) && (Co_MAX_AMOUNT in current_step) && (current_step[Co_AMOUNT] < current_step[Co_MAX_AMOUNT])) - var/obj/item/stack/S - if(used_atoms["[index][diff == FORWARD ? "+" : "-"]"]) - for(var/atom/movable/A in used_atoms["[index][diff == FORWARD ? "+" : "-"]"]) - A.loc = holder.loc - used_atoms.Remove("[index][diff == FORWARD ? "+" : "-"]") - else - var/working_type = (islist(current_step[Co_KEY]) ? pick(current_step[Co_KEY]) : current_step[Co_KEY]) - S = new working_type(holder.loc) - if(istype(S) && !(Co_KEEP in current_step)) - S.amount = current_step[Co_MAX_AMOUNT] - current_step[Co_AMOUNT] - S.update_icon() - else - for(var/i = 2; i <= current_step[Co_MAX_AMOUNT] - current_step[Co_AMOUNT]; i++) - new working_type(holder.loc) - current_step[Co_AMOUNT] = current_step[Co_MAX_AMOUNT] - - var/delay = 0 - if(Co_DELAY in given_step) - if(used_atom.construction_delay_mult) - delay = given_step[Co_DELAY] * used_atom.construction_delay_mult[diff == FORWARD ? Co_CON_SPEED : Co_DECON_SPEED] - else - delay = given_step[Co_DELAY] - if(delay > 0) - start_construct_message(given_step, user, used_atom) - if(!do_after(user, src.holder, delay, needhand = 1)) - return 0 - - var/amount = 0 - if(Co_AMOUNT in given_step) - amount = given_step[Co_AMOUNT] - if(amount > 0) - // STACKS - if(istype(used_atom,/obj/item/stack) && !(Co_TAKE in given_step)) - var/obj/item/stack/stack=used_atom - if(stack.amount < amount) - to_chat(user, "You start adding [stack] to \the [holder]. It still needs [amount - stack.amount] [stack.singular_name].") - given_step[Co_AMOUNT] -= stack.amount - stack.use(stack.amount) - return 0 - stack.use(amount) - // WELDER - else if(istype(used_atom,/obj/item/weapon/weldingtool) && !(Co_TAKE in given_step)) - var/obj/item/weapon/weldingtool/welder=used_atom - if(!welder.isOn()) - to_chat(user, "You tap \the [holder] with your unlit welder. [pick("Ding","Dong")].") - return 0 - if(!welder.remove_fuel(amount,user)) - to_chat(user, "You don't have enough fuel!") - return 0 - //generic things - else - var/atom_name = used_atom.name - if(permanence || (Co_KEEP in given_step)) - if(user.drop_item(used_atom, holder)) - if(!("[index][diff == FORWARD ? "+" : "-"]" in used_atoms)) - used_atoms.Add(list("[index][diff == FORWARD ? "+" : "-"]" = list())) - used_atoms["[index][diff == FORWARD ? "+" : "-"]"] += used_atom - else - qdel(used_atom) - given_step[Co_AMOUNT]-- - if(given_step[Co_AMOUNT] > 0) - to_chat(user, "You add \a [atom_name] to \the [holder]. It still needs [amount -1 ] [atom_name]\s.") - return 0 - given_step[Co_AMOUNT] = given_step[Co_MAX_AMOUNT] - - else - var/list/spawn_step - var/new_index = (diff == FORWARD ? index - 1 : index + 1) - if(new_index == 0) - message_admins("Holy shit [src]/([src.type]) is trying to set its new index to 0! how the fuck did this happen? I don't know, our direction is [diff==FORWARD?"forward":"backward"] old index was [index]. User is [formatPlayerPanel(user,user.ckey)], itemused [used_atom], step [given_step]") - spawn_result(user) - return 1 - //CRASH("Holy shit [src]/([src.type]) is trying to set its new index to 0! how the fuck did this happen? I don't know, our direction is [diff==FORWARD?"forward":"backward"] old index was [index]. User is [user], itemused [used_atom], step [given_step]") - if(diff == FORWARD) - spawn_step = get_backward_step(new_index) - else if(diff == BACKWARD) - spawn_step = get_forward_step(new_index) - var/list/atom/movable/to_drop = list() - - if(("[new_index][diff == FORWARD ? "-" : "+"]" in used_atoms) && used_atoms["[new_index][diff == FORWARD ? "-" : "+"]"]) - to_drop = used_atoms["[new_index][diff == FORWARD ? "-" : "+"]"] - used_atoms.Remove("[new_index][diff == FORWARD ? "-" : "+"]") - - else if(Co_AMOUNT in spawn_step) - var/to_create = (islist(spawn_step[Co_KEY]) ? pick(spawn_step[Co_KEY]) : spawn_step[Co_KEY]) - var/test = new to_create - if(istype(test, /obj/item/weapon/weldingtool) && !(Co_TAKE in spawn_step)) - qdel(test) - else if(istype(test, /obj/item/stack) && !(Co_TAKE in spawn_step)) - var/obj/item/stack/S = test - S.amount = spawn_step[Co_AMOUNT] - to_drop.Add(S) - else - to_drop.Add(test) - for(var/i = 1; i <= spawn_step[Co_AMOUNT] - 1; i++) - to_drop.Add(new to_create) - - for(var/atom/movable/this_drop in to_drop) - this_drop.loc = holder.loc - return 1 - -/datum/construction/reversible/proc/get_forward_step(index) - if(index < 0 || index > steps.len) - return - var/list/S = steps[index] - if(Co_NEXTSTEP in S) - return S[Co_NEXTSTEP] - -/datum/construction/reversible/proc/get_backward_step(index) - if(index < 0 || index > steps.len) - return - var/list/S = steps[index] - if(Co_BACKSTEP in S) +#define FORWARD -1 +#define BACKWARD 1 + +#define Co_KEY "key" +#define Co_VIS_MSG "vis_msg" +#define Co_START_MSG "start_msg" +#define Co_AMOUNT "amount" +#define Co_MAX_AMOUNT "max_amount" +#define Co_DELAY "delay" +#define Co_KEEP "keep" //if permanence is set to 0, we can still store specific step items by including this in the step +#define Co_TAKE "take" //if we want to actually have a stack or weldingtool in construction, rather than weld or add a stack, we can use this override +#define Co_DESC "desc" + +#define Co_NEXTSTEP "nextstep" +#define Co_BACKSTEP "backstep" + +#define Co_CON_SPEED "construct" //For tools. See tools.dm +#define Co_DECON_SPEED "deconstruct" //For tools. See tools.dm + +/datum/construction + var/list/steps + var/atom/holder + var/result + var/list/steps_desc + var/taskpath = null // Path of job objective completed. + var/assembling = 0 //if we're in a step, we won't be allowed to do another step + var/permanence = 0 + var/list/used_atoms = list() //contains the stuff we add. Can be used in multiple-choice construction + +/datum/construction/New(atom) + ..() + holder = atom + if(!holder) //don't want this without a holder + spawn + qdel (src) + set_desc(steps.len) + add_max_amounts() + return + +/datum/construction/proc/next_step(mob/user as mob) + steps.len-- + if(!steps.len) + spawn_result(user) + else + set_desc(steps.len) + return + +/datum/construction/proc/action(atom/used_atom,mob/user as mob) + return + +/datum/construction/proc/check_step(atom/used_atom,mob/user as mob) //check last step only + var/valid_step = is_right_key(user,used_atom) + if(valid_step) + assembling = 1 + if(custom_action(steps[valid_step], used_atom, user)) + next_step(user) + assembling = 0 + return 1 + assembling = 0 + return 0 + +/datum/construction/proc/is_right_key(mob/user as mob, atom/used_atom) // returns current step num if used_atom is of the right type. + if(assembling) return 0 + var/list/L = steps[steps.len] + if((istype(L[Co_KEY], /list) && is_type_in_list(used_atom, L[Co_KEY])) || istype(used_atom, L[Co_KEY])) + //if our keys are in a list, we want to check them all + //otherwise, sanity permits setting it as a single type and checking that + if(!try_consume(user, used_atom, L)) + return 0 + return steps.len + return 0 + +/datum/construction/proc/custom_action(step, used_atom, user) + if(istype(used_atom, /obj/item/weapon/weldingtool)) + playsound(holder, 'sound/items/Welder2.ogg', 50, 1) + + else if(istype(used_atom, /obj/item/weapon/wrench)) + playsound(holder, 'sound/items/Ratchet.ogg', 50, 1) + + else if(istype(used_atom, /obj/item/weapon/screwdriver)) + playsound(holder, 'sound/items/Screwdriver.ogg', 50, 1) + + else if(istype(used_atom, /obj/item/weapon/wirecutters)) + playsound(holder, 'sound/items/Wirecutter.ogg', 50, 1) + + construct_message(step, user) + return 1 + + +/datum/construction/proc/fixText(text,user,self=0) + if(self) + text = replacetext(text, "{s}", "") + text = replacetext(text, "{USER}", "You") + else + text = replacetext(text, "{s}", "s") + text = replacetext(text,"{USER}","[user]") + text = replacetext(text,"{HOLDER}","[holder]") + return text + +/datum/construction/proc/construct_message(step, mob/user) + if(Co_VIS_MSG in step) + user.visible_message(fixText(step[Co_VIS_MSG],user), fixText(step[Co_VIS_MSG],user,1)) + +/datum/construction/proc/start_construct_message(step, mob/user, atom/movable/used_atom) + if(Co_START_MSG in step) + user.visible_message(fixText(step[Co_START_MSG],user), fixText(step[Co_START_MSG],user,1)) + +/datum/construction/proc/check_all_steps(atom/used_atom,mob/user as mob) //check all steps, remove matching one. + for(var/i=1;i<=steps.len;i++) + var/list/L = steps[i]; + if((islist(L[Co_KEY]) && is_type_in_list(used_atom, L[Co_KEY])) ||istype(used_atom, L[Co_KEY])) + if(custom_action(L, used_atom, user)) + steps[i]=null;//stupid byond list from list removal... + listclearnulls(steps); + if(!steps.len) + spawn_result(user) + return 1 + return 0 + + +/datum/construction/proc/spawn_result(mob/user as mob) + if(result) + testing("[user] finished a [result]!") + + new result(get_turf(holder)) + spawn() + qdel (holder) + holder = null + return + +/datum/construction/proc/set_desc(index as num) + var/list/step = steps[index] + holder.desc = step[Co_DESC] + return + +/datum/construction/proc/try_consume(mob/user as mob, atom/movable/used_atom, given_step) + if(used_atom.construction_delay_mult && !used_atom.construction_delay_mult[Co_CON_SPEED]) + to_chat(user, "This tool only works for deconstruction!")//It doesn't technically have to be a tool to cause this message, but it wouldn't make sense for anything else to do so. + + return 0 + + if(!(Co_AMOUNT in given_step) && !(Co_DELAY in given_step)) + return 1 + + + var/delay = 0 + if(Co_DELAY in given_step) + if(used_atom.construction_delay_mult) + delay = given_step[Co_DELAY] * used_atom.construction_delay_mult[Co_CON_SPEED] + else + delay = given_step[Co_DELAY] + if(delay > 0) + start_construct_message(given_step, user, used_atom) + if(!do_after(user, src.holder, delay, needhand = 1)) + return 0 + + var/amount = 0 + if(Co_AMOUNT in given_step) + amount = given_step[Co_AMOUNT] + if(amount>0) + // STACKS + if(istype(used_atom,/obj/item/stack) && !(Co_TAKE in given_step)) + var/obj/item/stack/stack=used_atom + if(stack.amount < amount) + to_chat(user, "You start adding [stack] to \the [holder]. It still needs [amount - stack.amount] [stack.singular_name].") + given_step[Co_AMOUNT] -= stack.amount + stack.use(stack.amount) + return 0 + stack.use(amount) + // WELDER + else if(istype(used_atom,/obj/item/weapon/weldingtool) && !(Co_TAKE in given_step)) + var/obj/item/weapon/weldingtool/welder=used_atom + if(!welder.isOn()) + to_chat(user, "You tap \the [holder] with your unlit welder. [pick("Ding","Dong")].") + return 0 + if(!welder.remove_fuel(amount,user)) + to_chat(user, "You don't have enough fuel!") + return 0 + //generic things + else + var/atom_name = used_atom.name + if(permanence || (Co_KEEP in given_step)) + if(user.drop_item(used_atom, holder)) + used_atoms.Add(list("[steps.Find(given_step)]" = used_atom)) + else + qdel(used_atom) + given_step[Co_AMOUNT]-- + if(given_step[Co_AMOUNT] > 0) + to_chat(user, "You add \a [atom_name] to \the [holder]. It still needs [amount -1 ] [atom_name]\s.") + return 0 + given_step[Co_AMOUNT] = given_step[Co_MAX_AMOUNT] + return 1 + +/datum/construction/proc/add_max_amounts() + for(var/list/this_step in steps) + if((Co_AMOUNT in this_step)) + this_step.Add(list(Co_MAX_AMOUNT = this_step[Co_AMOUNT])) //puts in something we can refer to when we reset the step + +/datum/construction/reversible + var/index + +/datum/construction/reversible/New(atom) + ..() + index = steps.len + return + +/datum/construction/reversible/proc/update_index(diff as num, mob/user as mob) + index+=diff + if(index==0) + spawn_result(user) + else + set_desc(index) + return + +/datum/construction/reversible/is_right_key(mob/user as mob,atom/used_atom) // returns index step + if(assembling) return 0 + assembling = 1 + var/list/step_next = get_forward_step(index) + var/list/step_back = get_backward_step(index) + if(step_next && ((islist(step_next[Co_KEY]) && is_type_in_list(used_atom, step_next[Co_KEY])) || istype(used_atom, step_next[Co_KEY]))) + //if our keys are in a list, we want to check them all + //otherwise, sanity permits setting it as a single type and checking that + if(!try_consume(user, used_atom, step_next, index, FORWARD)) + assembling = 0 + return 0 + return FORWARD //to the first step -> forward + if(step_back && ((islist(step_back[Co_KEY]) && is_type_in_list(used_atom, step_back[Co_KEY])) || istype(used_atom, step_back[Co_KEY]))) + if(!try_consume(user, used_atom, step_back, index, BACKWARD)) + assembling = 0 + return 0 + return BACKWARD //to the last step -> backwards + assembling = 0 + return 0 + +/datum/construction/reversible/check_step(atom/used_atom,mob/user as mob) + var/diff = is_right_key(user,used_atom) + if(diff) + assembling = 1 + if(custom_action(index, diff, used_atom, user)) + update_index(diff,user) + assembling = 0 + return 1 + assembling = 0 + return 0 + +/datum/construction/reversible/custom_action(index, diff, used_atom, user) + . = ..(index,used_atom,user) + + if(.) + construct_message(steps[index], user, diff, 1) + +/datum/construction/reversible/construct_message(step, mob/user, diff, override) + if(!override) + return + var/message_step + if(diff == FORWARD && (Co_NEXTSTEP in step)) + message_step = step[Co_NEXTSTEP] + else if (Co_BACKSTEP in step) + message_step = step[Co_BACKSTEP] + if(message_step) + user.visible_message(fixText(message_step[Co_VIS_MSG],user), fixText(message_step[Co_VIS_MSG],user,1)) + +/datum/construction/reversible/start_construct_message(step, mob/user, atom/movable/used_atom) + user.visible_message(fixText(step[Co_START_MSG],user), fixText(step[Co_START_MSG],user,1)) + +/datum/construction/reversible/add_max_amounts() + for(var/i = 1; i <= steps.len; i++) + var/list/dir_step = get_forward_step(i) + if((Co_AMOUNT in dir_step)) + dir_step.Add(list(Co_MAX_AMOUNT = dir_step[Co_AMOUNT])) //puts in something we can refer to when we reset the step + + dir_step = get_backward_step(i) + if((Co_AMOUNT in dir_step)) + dir_step.Add(list(Co_MAX_AMOUNT = dir_step[Co_AMOUNT])) + + //NOT IN PLACE: message segments like verbs can be written as {UN|forwardmessage|backwardmessage}. This formats that in selection +/datum/construction/reversible/fixText(message, mob/user, self = 0) + return ..(message, user, self) + /* + while("{UN|" in text) + var/start_bracket = findtext(text, "{") + var/this_verb = copytext(text, start_bracket, findtext(text, "}", start_bracket + 1)) + to_chat(world, this_verb) + var/marker = findtext(this_verb, "|") + var/final_verb = "" + if(diff == FORWARD) + final_verb = copytext(this_verb, marker + 1, findtext(this_verb, "|", marker + 1)) + else + final_verb = copytext(this_verb, findtext(this_verb, "|", marker + 1), findtext(text, "}", start_bracket + 1)) + to_chat(world, final_verb) + replacetext(text, this_verb, final_verb) + */ + +/datum/construction/reversible/try_consume(mob/user as mob, atom/movable/used_atom, given_step, index, diff) + //if we've made some progress on a step, we want to drop it + var/current_step = (diff == BACKWARD ? get_forward_step(index) : get_backward_step(index)) + if(used_atom.construction_delay_mult && !used_atom.construction_delay_mult[diff == FORWARD ? Co_CON_SPEED : Co_DECON_SPEED]) + to_chat(user, "This tool only works for [diff == FORWARD ? "de" : ""]construction!")//It doesn't technically have to be a tool to cause this message, but it wouldn't make sense for anything else to do so. + + return 0 + if(current_step && (Co_AMOUNT in current_step) && (Co_MAX_AMOUNT in current_step) && (current_step[Co_AMOUNT] < current_step[Co_MAX_AMOUNT])) + var/obj/item/stack/S + if(used_atoms["[index][diff == FORWARD ? "+" : "-"]"]) + for(var/atom/movable/A in used_atoms["[index][diff == FORWARD ? "+" : "-"]"]) + A.loc = holder.loc + used_atoms.Remove("[index][diff == FORWARD ? "+" : "-"]") + else + var/working_type = (islist(current_step[Co_KEY]) ? pick(current_step[Co_KEY]) : current_step[Co_KEY]) + S = new working_type(holder.loc) + if(istype(S) && !(Co_KEEP in current_step)) + S.amount = current_step[Co_MAX_AMOUNT] - current_step[Co_AMOUNT] + S.update_icon() + else + for(var/i = 2; i <= current_step[Co_MAX_AMOUNT] - current_step[Co_AMOUNT]; i++) + new working_type(holder.loc) + current_step[Co_AMOUNT] = current_step[Co_MAX_AMOUNT] + + var/delay = 0 + if(Co_DELAY in given_step) + if(used_atom.construction_delay_mult) + delay = given_step[Co_DELAY] * used_atom.construction_delay_mult[diff == FORWARD ? Co_CON_SPEED : Co_DECON_SPEED] + else + delay = given_step[Co_DELAY] + if(delay > 0) + start_construct_message(given_step, user, used_atom) + if(!do_after(user, src.holder, delay, needhand = 1)) + return 0 + + var/amount = 0 + if(Co_AMOUNT in given_step) + amount = given_step[Co_AMOUNT] + if(amount > 0) + // STACKS + if(istype(used_atom,/obj/item/stack) && !(Co_TAKE in given_step)) + var/obj/item/stack/stack=used_atom + if(stack.amount < amount) + to_chat(user, "You start adding [stack] to \the [holder]. It still needs [amount - stack.amount] [stack.singular_name].") + given_step[Co_AMOUNT] -= stack.amount + stack.use(stack.amount) + return 0 + stack.use(amount) + // WELDER + else if(istype(used_atom,/obj/item/weapon/weldingtool) && !(Co_TAKE in given_step)) + var/obj/item/weapon/weldingtool/welder=used_atom + if(!welder.isOn()) + to_chat(user, "You tap \the [holder] with your unlit welder. [pick("Ding","Dong")].") + return 0 + if(!welder.remove_fuel(amount,user)) + to_chat(user, "You don't have enough fuel!") + return 0 + //generic things + else + var/atom_name = used_atom.name + if(permanence || (Co_KEEP in given_step)) + if(user.drop_item(used_atom, holder)) + if(!("[index][diff == FORWARD ? "+" : "-"]" in used_atoms)) + used_atoms.Add(list("[index][diff == FORWARD ? "+" : "-"]" = list())) + used_atoms["[index][diff == FORWARD ? "+" : "-"]"] += used_atom + else + qdel(used_atom) + given_step[Co_AMOUNT]-- + if(given_step[Co_AMOUNT] > 0) + to_chat(user, "You add \a [atom_name] to \the [holder]. It still needs [amount -1 ] [atom_name]\s.") + return 0 + given_step[Co_AMOUNT] = given_step[Co_MAX_AMOUNT] + + else + var/list/spawn_step + var/new_index = (diff == FORWARD ? index - 1 : index + 1) + if(new_index == 0) + message_admins("Holy shit [src]/([src.type]) is trying to set its new index to 0! how the fuck did this happen? I don't know, our direction is [diff==FORWARD?"forward":"backward"] old index was [index]. User is [formatPlayerPanel(user,user.ckey)], itemused [used_atom], step [given_step]") + spawn_result(user) + return 1 + //CRASH("Holy shit [src]/([src.type]) is trying to set its new index to 0! how the fuck did this happen? I don't know, our direction is [diff==FORWARD?"forward":"backward"] old index was [index]. User is [user], itemused [used_atom], step [given_step]") + if(diff == FORWARD) + spawn_step = get_backward_step(new_index) + else if(diff == BACKWARD) + spawn_step = get_forward_step(new_index) + var/list/atom/movable/to_drop = list() + + if(("[new_index][diff == FORWARD ? "-" : "+"]" in used_atoms) && used_atoms["[new_index][diff == FORWARD ? "-" : "+"]"]) + to_drop = used_atoms["[new_index][diff == FORWARD ? "-" : "+"]"] + used_atoms.Remove("[new_index][diff == FORWARD ? "-" : "+"]") + + else if(Co_AMOUNT in spawn_step) + var/to_create = (islist(spawn_step[Co_KEY]) ? pick(spawn_step[Co_KEY]) : spawn_step[Co_KEY]) + var/test = new to_create + if(istype(test, /obj/item/weapon/weldingtool) && !(Co_TAKE in spawn_step)) + qdel(test) + else if(istype(test, /obj/item/stack) && !(Co_TAKE in spawn_step)) + var/obj/item/stack/S = test + S.amount = spawn_step[Co_AMOUNT] + to_drop.Add(S) + else + to_drop.Add(test) + for(var/i = 1; i <= spawn_step[Co_AMOUNT] - 1; i++) + to_drop.Add(new to_create) + + for(var/atom/movable/this_drop in to_drop) + this_drop.loc = holder.loc + return 1 + +/datum/construction/reversible/proc/get_forward_step(index) + if(index < 0 || index > steps.len) + return + var/list/S = steps[index] + if(Co_NEXTSTEP in S) + return S[Co_NEXTSTEP] + +/datum/construction/reversible/proc/get_backward_step(index) + if(index < 0 || index > steps.len) + return + var/list/S = steps[index] + if(Co_BACKSTEP in S) return S[Co_BACKSTEP] \ No newline at end of file diff --git a/code/datums/helper_datums/events.dm b/code/datums/helper_datums/events.dm index 8ae17aed621..ae4393cb3fc 100644 --- a/code/datums/helper_datums/events.dm +++ b/code/datums/helper_datums/events.dm @@ -1,67 +1,67 @@ -/* - * WARRANTY VOID IF CODE USED - */ - - -/datum/events - var/list/events - - New() - ..() - events = new - - proc/addEventType(event_type as text) - if(!(event_type in events) || !islist(events[event_type])) - events[event_type] = list() - return 1 - return - - - // Arguments: event_type as text, proc_holder as datum, proc_name as text - // Returns: New event, null on error. - proc/addEvent(event_type as text, proc_holder, proc_name as text) - if(!event_type || !proc_holder || !proc_name) - return - addEventType(event_type) - var/list/event = events[event_type] - var/datum/event/E = new /datum/event(proc_holder,proc_name) - event += E - return E - - // Arguments: event_type as text, any number of additional arguments to pass to event handler - // Returns: null - proc/fireEvent() +/* + * WARRANTY VOID IF CODE USED + */ + + +/datum/events + var/list/events + + New() + ..() + events = new + + proc/addEventType(event_type as text) + if(!(event_type in events) || !islist(events[event_type])) + events[event_type] = list() + return 1 + return + + + // Arguments: event_type as text, proc_holder as datum, proc_name as text + // Returns: New event, null on error. + proc/addEvent(event_type as text, proc_holder, proc_name as text) + if(!event_type || !proc_holder || !proc_name) + return + addEventType(event_type) + var/list/event = events[event_type] + var/datum/event/E = new /datum/event(proc_holder,proc_name) + event += E + return E + + // Arguments: event_type as text, any number of additional arguments to pass to event handler + // Returns: null + proc/fireEvent() // to_chat(world, "Events in [args[1]] called") - var/list/event = listgetindex(events,args[1]) - if(istype(event)) - spawn(-1) - for(var/datum/event/E in event) - if(!E.Fire(arglist(args.Copy(2)))) - clearEvent(args[1],E) - return - - // Arguments: event_type as text, E as /datum/event - // Returns: 1 if event cleared, null on error - proc/clearEvent(event_type as text, datum/event/E) - if(!event_type || !E) - return - var/list/event = listgetindex(events,event_type) - event -= E - return 1 - - -/datum/event - var/listener - var/proc_name - - New(tlistener,tprocname) - listener = tlistener - proc_name = tprocname - return ..() - - proc/Fire() + var/list/event = listgetindex(events,args[1]) + if(istype(event)) + spawn(-1) + for(var/datum/event/E in event) + if(!E.Fire(arglist(args.Copy(2)))) + clearEvent(args[1],E) + return + + // Arguments: event_type as text, E as /datum/event + // Returns: 1 if event cleared, null on error + proc/clearEvent(event_type as text, datum/event/E) + if(!event_type || !E) + return + var/list/event = listgetindex(events,event_type) + event -= E + return 1 + + +/datum/event + var/listener + var/proc_name + + New(tlistener,tprocname) + listener = tlistener + proc_name = tprocname + return ..() + + proc/Fire() // to_chat(world, "Event fired") - if(listener) - call(listener,proc_name)(arglist(args)) - return 1 + if(listener) + call(listener,proc_name)(arglist(args)) + return 1 return \ No newline at end of file diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm index 03c09fc2fec..a81830ab5ab 100644 --- a/code/datums/helper_datums/global_iterator.dm +++ b/code/datums/helper_datums/global_iterator.dm @@ -1,154 +1,154 @@ -/* -README: - -The global_iterator datum is supposed to provide a simple and robust way to -create some constantly "looping" processes with ability to stop and restart them at will. -Generally, the only thing you want to play with (meaning, redefine) is the process() proc. -It must contain all the things you want done. - -Control functions: - new - used to create datum. First argument (optional) - var list(to use in process() proc) as list, - second (optional) - autostart control. - If autostart == TRUE, the loop will be started immediately after datum creation. - - start(list/arguments) - starts the loop. Takes arguments(optional) as a list, which is then used - by process() proc. Returns null if datum already active, 1 if loop started succesfully and 0 if there's - an error in supplied arguments (not list or empty list). - - stop() - stops the loop. Returns null if datum is already inactive and 1 on success. - - set_delay(new_delay) - sets the delay between iterations. Pretty selfexplanatory. - Returns 0 on error(new_delay is not numerical), 1 otherwise. - - set_process_args(list/arguments) - passes the supplied arguments to the process() proc. - - active() - Returns 1 if datum is active, 0 otherwise. - - toggle() - toggles datum state. Returns new datum state (see active()). - -Misc functions: - - get_last_exec_time() - Returns the time of last iteration. - - get_last_exec_time_as_text() - Returns the time of last iteration as text - - -Control vars: - - delay - delay between iterations - - check_for_null - if equals TRUE, on each iteration the supplied arguments will be checked for nulls. - If some varible equals null (and null only), the loop is stopped. - Usefull, if some var unexpectedly becomes null - due to object deletion, for example. - Of course, you can also check the variables inside process() proc to prevent runtime errors. - -Data storage vars: - - result - stores the value returned by process() proc -*/ - -/datum/global_iterator - var/control_switch = 0 - var/delay = 10 - var/list/arg_list = new - var/last_exec = null - var/check_for_null = 1 - var/forbid_garbage = 0 - var/result - var/state = 0 - - New(list/arguments=null,autostart=1) - delay = delay>0?(delay):1 - if(forbid_garbage) //prevents garbage collection with tag != null - tag = "\ref[src]" - set_process_args(arguments) - if(autostart) - start() - return - - proc/main() - state = 1 - while(src && control_switch) - last_exec = world.timeofday - if(check_for_null && has_null_args()) - stop() - return 0 - result = process(arglist(arg_list)) - for(var/sleep_time=delay;sleep_time>0;sleep_time--) //uhh, this is ugly. But I see no other way to terminate sleeping proc. Such disgrace. - if(!control_switch) - return 0 - sleep(1) - return 0 - - proc/start(list/arguments=null) - if(active()) - return - if(arguments) - if(!set_process_args(arguments)) - return 0 - if(!state_check()) //the main loop is sleeping, wait for it to terminate. - return - control_switch = 1 - spawn() - state = main() - return 1 - - proc/stop() - if(!active()) - return - control_switch = 0 - spawn(-1) //report termination error but don't wait for state_check(). - state_check() - return 1 - - proc/state_check() - var/lag = 0 - while(state) - sleep(1) - if(++lag>10) - CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.") - return 1 - - proc/process() - return - - proc/active() - return control_switch - - proc/has_null_args() - if(null in arg_list) - return 1 - return 0 - - - proc/set_delay(new_delay) - if(isnum(new_delay)) - delay = max(1, round(new_delay)) - return 1 - else - return 0 - - proc/get_last_exec_time() - return (last_exec||0) - - proc/get_last_exec_time_as_text() - return (time2text(last_exec)||"Wasn't executed yet") - - proc/set_process_args(list/arguments) - if(arguments && istype(arguments, /list) && arguments.len) - arg_list = arguments - return 1 - else +/* +README: + +The global_iterator datum is supposed to provide a simple and robust way to +create some constantly "looping" processes with ability to stop and restart them at will. +Generally, the only thing you want to play with (meaning, redefine) is the process() proc. +It must contain all the things you want done. + +Control functions: + new - used to create datum. First argument (optional) - var list(to use in process() proc) as list, + second (optional) - autostart control. + If autostart == TRUE, the loop will be started immediately after datum creation. + + start(list/arguments) - starts the loop. Takes arguments(optional) as a list, which is then used + by process() proc. Returns null if datum already active, 1 if loop started succesfully and 0 if there's + an error in supplied arguments (not list or empty list). + + stop() - stops the loop. Returns null if datum is already inactive and 1 on success. + + set_delay(new_delay) - sets the delay between iterations. Pretty selfexplanatory. + Returns 0 on error(new_delay is not numerical), 1 otherwise. + + set_process_args(list/arguments) - passes the supplied arguments to the process() proc. + + active() - Returns 1 if datum is active, 0 otherwise. + + toggle() - toggles datum state. Returns new datum state (see active()). + +Misc functions: + + get_last_exec_time() - Returns the time of last iteration. + + get_last_exec_time_as_text() - Returns the time of last iteration as text + + +Control vars: + + delay - delay between iterations + + check_for_null - if equals TRUE, on each iteration the supplied arguments will be checked for nulls. + If some varible equals null (and null only), the loop is stopped. + Usefull, if some var unexpectedly becomes null - due to object deletion, for example. + Of course, you can also check the variables inside process() proc to prevent runtime errors. + +Data storage vars: + + result - stores the value returned by process() proc +*/ + +/datum/global_iterator + var/control_switch = 0 + var/delay = 10 + var/list/arg_list = new + var/last_exec = null + var/check_for_null = 1 + var/forbid_garbage = 0 + var/result + var/state = 0 + + New(list/arguments=null,autostart=1) + delay = delay>0?(delay):1 + if(forbid_garbage) //prevents garbage collection with tag != null + tag = "\ref[src]" + set_process_args(arguments) + if(autostart) + start() + return + + proc/main() + state = 1 + while(src && control_switch) + last_exec = world.timeofday + if(check_for_null && has_null_args()) + stop() + return 0 + result = process(arglist(arg_list)) + for(var/sleep_time=delay;sleep_time>0;sleep_time--) //uhh, this is ugly. But I see no other way to terminate sleeping proc. Such disgrace. + if(!control_switch) + return 0 + sleep(1) + return 0 + + proc/start(list/arguments=null) + if(active()) + return + if(arguments) + if(!set_process_args(arguments)) + return 0 + if(!state_check()) //the main loop is sleeping, wait for it to terminate. + return + control_switch = 1 + spawn() + state = main() + return 1 + + proc/stop() + if(!active()) + return + control_switch = 0 + spawn(-1) //report termination error but don't wait for state_check(). + state_check() + return 1 + + proc/state_check() + var/lag = 0 + while(state) + sleep(1) + if(++lag>10) + CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.") + return 1 + + proc/process() + return + + proc/active() + return control_switch + + proc/has_null_args() + if(null in arg_list) + return 1 + return 0 + + + proc/set_delay(new_delay) + if(isnum(new_delay)) + delay = max(1, round(new_delay)) + return 1 + else + return 0 + + proc/get_last_exec_time() + return (last_exec||0) + + proc/get_last_exec_time_as_text() + return (time2text(last_exec)||"Wasn't executed yet") + + proc/set_process_args(list/arguments) + if(arguments && istype(arguments, /list) && arguments.len) + arg_list = arguments + return 1 + else // to_chat(world, "Invalid arguments supplied for [src.type], ref = \ref[src]") - return 0 - - proc/toggle_null_checks() - check_for_null = !check_for_null - return check_for_null - - proc/toggle() - if(!stop()) - start() - return active() - - + return 0 + + proc/toggle_null_checks() + check_for_null = !check_for_null + return check_for_null + + proc/toggle() + if(!stop()) + start() + return active() + + diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 6a8bf0bd859..48c0f3f179b 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -1,213 +1,213 @@ -//wrapper -/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) - new /datum/teleport/instant/science(arglist(args)) - return - -/datum/teleport - var/atom/movable/teleatom //atom to teleport - var/atom/destination //destination to teleport to - var/precision = 0 //teleport precision - var/datum/effect/effect/system/effectin //effect to show right before teleportation - var/datum/effect/effect/system/effectout //effect to show right after teleportation - var/soundin //soundfile to play before teleportation - var/soundout //soundfile to play after teleportation - var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation) - - -/datum/teleport/New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) - ..() - if(!Init(arglist(args))) - return 0 - return 1 - -/datum/teleport/proc/Init(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout) - if(!setTeleatom(ateleatom)) - return 0 - if(!setDestination(adestination)) - return 0 - if(!setPrecision(aprecision)) - return 0 - setEffects(aeffectin,aeffectout) - setForceTeleport(afteleport) - setSounds(asoundin,asoundout) - return 1 - - //must succeed -/datum/teleport/proc/setPrecision(aprecision) - if(isnum(aprecision)) - precision = aprecision - return 1 - return 0 - - //must succeed -/datum/teleport/proc/setDestination(atom/adestination) - if(istype(adestination)) - destination = adestination - return 1 - return 0 - - //must succeed in most cases -/datum/teleport/proc/setTeleatom(atom/movable/ateleatom) - if(istype(ateleatom, /obj/effect) && !istype(ateleatom, /obj/effect/dummy/chameleon)) - qdel(ateleatom) - return 0 - if(istype(ateleatom)) - teleatom = ateleatom - return 1 - return 0 - - //custom effects must be properly set up first for instant-type teleports - //optional -/datum/teleport/proc/setEffects(datum/effect/effect/system/aeffectin=null,datum/effect/effect/system/aeffectout=null) - effectin = istype(aeffectin) ? aeffectin : null - effectout = istype(aeffectout) ? aeffectout : null - return 1 - - //optional -/datum/teleport/proc/setForceTeleport(afteleport) - force_teleport = afteleport - return 1 - - //optional -/datum/teleport/proc/setSounds(asoundin=null,asoundout=null) - soundin = isfile(asoundin) ? asoundin : null - soundout = isfile(asoundout) ? asoundout : null - return 1 - - //placeholder -/datum/teleport/proc/teleportChecks() - return 1 - -/datum/teleport/proc/playSpecials(atom/location,datum/effect/effect/system/effect,sound) - if(location) - if(effect) - spawn(-1) - src = null - effect.attach(location) - effect.start() - if(sound) - spawn(-1) - src = null - playsound(location,sound,60,1) - return - - //do the monkey dance -/datum/teleport/proc/doTeleport() - - - var/turf/destturf - var/turf/curturf = get_turf(teleatom) - var/area/destarea = get_area(destination) - if(precision) - var/list/posturfs = circlerangeturfs(destination,precision) - destturf = safepick(posturfs) - else - destturf = get_turf(destination) - - if(!destturf || !curturf) - return 0 - - playSpecials(curturf,effectin,soundin) - - if(istype(teleatom,/obj/item/projectile)) - var/Xchange = destturf.x - curturf.x - var/Ychange = destturf.y - curturf.y - var/obj/item/projectile/P = teleatom - P.override_starting_X += Xchange - P.override_starting_Y += Ychange - P.override_target_X += Xchange - P.override_target_Y += Ychange - P.reflected = 1//you can now get hit by the projectile you just fired. Careful with portals! - - if(force_teleport) - teleatom.forceMove(destturf,1) - playSpecials(destturf,effectout,soundout) - else - if(teleatom.Move(destturf)) - playSpecials(destturf,effectout,soundout) - - destarea.Entered(teleatom) - - return 1 - -/datum/teleport/proc/teleport() - if(teleportChecks()) - return doTeleport() - return 0 - -/datum/teleport/instant //teleports when datum is created - -/datum/teleport/instant/New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) - if(..()) - teleport() - return - - -/datum/teleport/instant/science - -/datum/teleport/instant/science/setEffects(datum/effect/effect/system/aeffectin,datum/effect/effect/system/aeffectout) - if(!aeffectin || !aeffectout) - var/datum/effect/effect/system/spark_spread/aeffect = new - aeffect.set_up(5, 1, teleatom) - effectin = effectin || aeffect - effectout = effectout || aeffect - return 1 - else - return ..() - -/datum/teleport/instant/science/setPrecision(aprecision) - ..() - if(istype(teleatom, /obj/item/weapon/storage/backpack/holding)) - precision = rand(1,100) - - var/list/bagholding = teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding) - if(bagholding.len) - precision = max(rand(1,100)*bagholding.len,100) - if(istype(teleatom, /mob/living)) - var/mob/living/MM = teleatom - to_chat(MM, "The Bluespace interface on your Bag of Holding interferes with the teleport!") - return 1 - -/datum/teleport/instant/science/teleportChecks() - if(istype(teleatom, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite - teleatom.visible_message("The [teleatom] bounces off of the portal!") - return 0 - if(teleatom.locked_to) - return 0 - - if(!isemptylist(teleatom.search_contents_for(/obj/item/weapon/disk/nuclear))) - if(istype(teleatom, /mob/living)) - var/mob/living/MM = teleatom - MM.visible_message("The [MM] bounces off of the portal!","Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through.") - else - teleatom.visible_message("The [teleatom] bounces off of the portal!") - return 0 - - if(destination.z == 2) //centcomm z-level - if(istype(teleatom, /obj/mecha) && (universe.name != "Supermatter Cascade")) - var/obj/mecha/MM = teleatom - to_chat(MM.occupant, "The mech would not survive the jump to a location so far away!")//seriously though, why? who wrote that? +//wrapper +/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) + new /datum/teleport/instant/science(arglist(args)) + return - return 0 - if(!isemptylist(teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding))) - teleatom.visible_message("The Bag of Holding bounces off of the portal!") - return 0 - - if(istype(teleatom,/obj/item/clothing/head/tinfoil)) - return 0 - - if(istype(teleatom,/mob/living/carbon/human)) //Tinfoil hats resist teleportation, but only when worn - var/mob/living/carbon/human/H = teleatom - if(H.head && istype(H.head,/obj/item/clothing/head/tinfoil)) +/datum/teleport + var/atom/movable/teleatom //atom to teleport + var/atom/destination //destination to teleport to + var/precision = 0 //teleport precision + var/datum/effect/effect/system/effectin //effect to show right before teleportation + var/datum/effect/effect/system/effectout //effect to show right after teleportation + var/soundin //soundfile to play before teleportation + var/soundout //soundfile to play after teleportation + var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation) + + +/datum/teleport/New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) + ..() + if(!Init(arglist(args))) + return 0 + return 1 + +/datum/teleport/proc/Init(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout) + if(!setTeleatom(ateleatom)) + return 0 + if(!setDestination(adestination)) + return 0 + if(!setPrecision(aprecision)) + return 0 + setEffects(aeffectin,aeffectout) + setForceTeleport(afteleport) + setSounds(asoundin,asoundout) + return 1 + + //must succeed +/datum/teleport/proc/setPrecision(aprecision) + if(isnum(aprecision)) + precision = aprecision + return 1 + return 0 + + //must succeed +/datum/teleport/proc/setDestination(atom/adestination) + if(istype(adestination)) + destination = adestination + return 1 + return 0 + + //must succeed in most cases +/datum/teleport/proc/setTeleatom(atom/movable/ateleatom) + if(istype(ateleatom, /obj/effect) && !istype(ateleatom, /obj/effect/dummy/chameleon)) + qdel(ateleatom) + return 0 + if(istype(ateleatom)) + teleatom = ateleatom + return 1 + return 0 + + //custom effects must be properly set up first for instant-type teleports + //optional +/datum/teleport/proc/setEffects(datum/effect/effect/system/aeffectin=null,datum/effect/effect/system/aeffectout=null) + effectin = istype(aeffectin) ? aeffectin : null + effectout = istype(aeffectout) ? aeffectout : null + return 1 + + //optional +/datum/teleport/proc/setForceTeleport(afteleport) + force_teleport = afteleport + return 1 + + //optional +/datum/teleport/proc/setSounds(asoundin=null,asoundout=null) + soundin = isfile(asoundin) ? asoundin : null + soundout = isfile(asoundout) ? asoundout : null + return 1 + + //placeholder +/datum/teleport/proc/teleportChecks() + return 1 + +/datum/teleport/proc/playSpecials(atom/location,datum/effect/effect/system/effect,sound) + if(location) + if(effect) + spawn(-1) + src = null + effect.attach(location) + effect.start() + if(sound) + spawn(-1) + src = null + playsound(location,sound,60,1) + return + + //do the monkey dance +/datum/teleport/proc/doTeleport() + + + var/turf/destturf + var/turf/curturf = get_turf(teleatom) + var/area/destarea = get_area(destination) + if(precision) + var/list/posturfs = circlerangeturfs(destination,precision) + destturf = safepick(posturfs) + else + destturf = get_turf(destination) + + if(!destturf || !curturf) + return 0 + + playSpecials(curturf,effectin,soundin) + + if(istype(teleatom,/obj/item/projectile)) + var/Xchange = destturf.x - curturf.x + var/Ychange = destturf.y - curturf.y + var/obj/item/projectile/P = teleatom + P.override_starting_X += Xchange + P.override_starting_Y += Ychange + P.override_target_X += Xchange + P.override_target_Y += Ychange + P.reflected = 1//you can now get hit by the projectile you just fired. Careful with portals! + + if(force_teleport) + teleatom.forceMove(destturf,1) + playSpecials(destturf,effectout,soundout) + else + if(teleatom.Move(destturf)) + playSpecials(destturf,effectout,soundout) + + destarea.Entered(teleatom) + + return 1 + +/datum/teleport/proc/teleport() + if(teleportChecks()) + return doTeleport() + return 0 + +/datum/teleport/instant //teleports when datum is created + +/datum/teleport/instant/New(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) + if(..()) + teleport() + return + + +/datum/teleport/instant/science + +/datum/teleport/instant/science/setEffects(datum/effect/effect/system/aeffectin,datum/effect/effect/system/aeffectout) + if(!aeffectin || !aeffectout) + var/datum/effect/effect/system/spark_spread/aeffect = new + aeffect.set_up(5, 1, teleatom) + effectin = effectin || aeffect + effectout = effectout || aeffect + return 1 + else + return ..() + +/datum/teleport/instant/science/setPrecision(aprecision) + ..() + if(istype(teleatom, /obj/item/weapon/storage/backpack/holding)) + precision = rand(1,100) + + var/list/bagholding = teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding) + if(bagholding.len) + precision = max(rand(1,100)*bagholding.len,100) + if(istype(teleatom, /mob/living)) + var/mob/living/MM = teleatom + to_chat(MM, "The Bluespace interface on your Bag of Holding interferes with the teleport!") + return 1 + +/datum/teleport/instant/science/teleportChecks() + if(istype(teleatom, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite + teleatom.visible_message("The [teleatom] bounces off of the portal!") + return 0 + if(teleatom.locked_to) + return 0 + + if(!isemptylist(teleatom.search_contents_for(/obj/item/weapon/disk/nuclear))) + if(istype(teleatom, /mob/living)) + var/mob/living/MM = teleatom + MM.visible_message("The [MM] bounces off of the portal!","Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through.") + else + teleatom.visible_message("The [teleatom] bounces off of the portal!") + return 0 + + if(destination.z == 2) //centcomm z-level + if(istype(teleatom, /obj/mecha) && (universe.name != "Supermatter Cascade")) + var/obj/mecha/MM = teleatom + to_chat(MM.occupant, "The mech would not survive the jump to a location so far away!")//seriously though, why? who wrote that? + + return 0 + if(!isemptylist(teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding))) + teleatom.visible_message("The Bag of Holding bounces off of the portal!") + return 0 + + if(istype(teleatom,/obj/item/clothing/head/tinfoil)) + return 0 + + if(istype(teleatom,/mob/living/carbon/human)) //Tinfoil hats resist teleportation, but only when worn + var/mob/living/carbon/human/H = teleatom + if(H.head && istype(H.head,/obj/item/clothing/head/tinfoil)) to_chat(H, "Your headgear has 'foiled' a teleport!") - return 0 - - if(destination.z > 7) //Away mission z-levels - return 0 - - if(istype(teleatom, /mob/living)) - var/mob/living/MM = teleatom - if(MM.locked_to_z != 0 && destination.z != MM.locked_to_z) - MM.visible_message("[MM] bounces off the portal!","You're unable to go to that destination!") - return 0 - return 1 + return 0 + + if(destination.z > 7) //Away mission z-levels + return 0 + + if(istype(teleatom, /mob/living)) + var/mob/living/MM = teleatom + if(MM.locked_to_z != 0 && destination.z != MM.locked_to_z) + MM.visible_message("[MM] bounces off the portal!","You're unable to go to that destination!") + return 0 + return 1 diff --git a/code/datums/helper_datums/topic_input.dm b/code/datums/helper_datums/topic_input.dm index 17dd3f1266e..c08ca754be4 100644 --- a/code/datums/helper_datums/topic_input.dm +++ b/code/datums/helper_datums/topic_input.dm @@ -1,60 +1,60 @@ -/datum/topic_input - var/href - var/list/href_list - - New(thref,list/thref_list) - href = thref - href_list = thref_list.Copy() - return - - proc/get(i) - return listgetindex(href_list,i) - - proc/getAndLocate(i) - var/t = get(i) - if(t) - t = locate(t) - return t || null - - proc/getNum(i) - var/t = get(i) - if(t) - t = text2num(t) - return isnum(t) ? t : null - - proc/getObj(i) - var/t = getAndLocate(i) - return isobj(t) ? t : null - - proc/getMob(i) - var/t = getAndLocate(i) - return ismob(t) ? t : null - - proc/getTurf(i) - var/t = getAndLocate(i) - return isturf(t) ? t : null - - proc/getAtom(i) - return getType(i,/atom) - - proc/getArea(i) - var/t = getAndLocate(i) - return isarea(t) ? t : null - - proc/getStr(i)//params should always be text, but... - var/t = get(i) - return istext(t) ? t : null - - proc/getType(i,type) - var/t = getAndLocate(i) - return istype(t,type) ? t : null - - proc/getPath(i) - var/t = get(i) - if(t) - t = text2path(t) - return ispath(t) ? t : null - - proc/getList(i) - var/t = getAndLocate(i) +/datum/topic_input + var/href + var/list/href_list + + New(thref,list/thref_list) + href = thref + href_list = thref_list.Copy() + return + + proc/get(i) + return listgetindex(href_list,i) + + proc/getAndLocate(i) + var/t = get(i) + if(t) + t = locate(t) + return t || null + + proc/getNum(i) + var/t = get(i) + if(t) + t = text2num(t) + return isnum(t) ? t : null + + proc/getObj(i) + var/t = getAndLocate(i) + return isobj(t) ? t : null + + proc/getMob(i) + var/t = getAndLocate(i) + return ismob(t) ? t : null + + proc/getTurf(i) + var/t = getAndLocate(i) + return isturf(t) ? t : null + + proc/getAtom(i) + return getType(i,/atom) + + proc/getArea(i) + var/t = getAndLocate(i) + return isarea(t) ? t : null + + proc/getStr(i)//params should always be text, but... + var/t = get(i) + return istext(t) ? t : null + + proc/getType(i,type) + var/t = getAndLocate(i) + return istype(t,type) ? t : null + + proc/getPath(i) + var/t = get(i) + if(t) + t = text2path(t) + return ispath(t) ? t : null + + proc/getList(i) + var/t = getAndLocate(i) return islist(t) ? t : null \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 781b4cef799..02b3d1ad1e2 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1,1436 +1,1436 @@ -/* Note from Carnie: - The way datum/mind stuff works has been changed a lot. - Minds now represent IC characters rather than following a client around constantly. - - Guidelines for using minds properly: - - - Never mind.transfer_to(ghost). The var/current and var/original of a mind must always be of type mob/living! - ghost.mind is however used as a reference to the ghost's corpse - - - When creating a new mob for an existing IC character (e.g. cloning a dead guy or borging a brain of a human) - the existing mind of the old mob should be transfered to the new mob like so: - - mind.transfer_to(new_mob) - - - You must not assign key= or ckey= after transfer_to() since the transfer_to transfers the client for you. - By setting key or ckey explicitly after transfering the mind with transfer_to you will cause bugs like DCing - the player. - - - IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you. - - - When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting - a ghost to become a xeno during an event). Simply assign the key or ckey like you've always done. - - new_mob.key = key - - The Login proc will handle making a new mob for that mobtype (including setting up stuff like mind.name). Simple! - However if you want that mind to have any special properties like being a traitor etc you will have to do that - yourself. - -*/ - -/datum/mind - var/key - var/name //replaces mob/var/original_name - var/mob/living/current - var/mob/living/original //TODO: remove.not used in any meaningful way ~Carn. First I'll need to tweak the way silicon-mobs handle minds. - var/active = 0 - - var/memory - - var/assigned_role - var/special_role - var/list/wizard_spells // So we can track our wizmen spells that we learned from the book of magicks. - - var/role_alt_title - - var/datum/job/assigned_job - - var/list/kills=list() - var/list/datum/objective/objectives = list() - var/list/datum/objective/special_verbs = list() - - var/has_been_rev = 0//Tracks if this mind has been a rev or not - - var/datum/faction/faction //associated faction - var/datum/changeling/changeling //changeling holder - var/datum/vampire/vampire //vampire holder - - var/rev_cooldown = 0 - - // the world.time since the mob has been brigged, or -1 if not at all - var/brigged_since = -1 - - //put this here for easier tracking ingame - var/datum/money_account/initial_account - var/list/uplink_items_bought = list() - var/total_TC = 0 - var/spent_TC = 0 - - //fix scrying raging mages issue. - var/isScrying = 0 - - -/datum/mind/New(var/key) - src.key = key - -/datum/mind/proc/transfer_to(mob/living/new_character) - if(!istype(new_character)) - error("transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob. Please inform Carn") - - if(current) //remove ourself from our old body's mind variable - if(changeling) - current.remove_changeling_powers() - current.verbs -= /datum/changeling/proc/EvolutionMenu - if(vampire) - current.remove_vampire_powers() - current.mind = null - if(new_character.mind) //remove any mind currently in our new body's mind variable - new_character.mind.current = null - - nanomanager.user_transferred(current, new_character) - - current = new_character //link ourself to our new body - new_character.mind = src //and link our new body to ourself - - if(changeling) - new_character.make_changeling() - if(vampire) - new_character.make_vampire() - if(active) - new_character.key = key //now transfer the key to link the client to our new body - -/datum/mind/proc/store_memory(new_text) - memory += "[new_text]
      " - -/datum/mind/proc/show_memory(mob/recipient) - var/output = "[current.real_name]'s Memory
      " - output += memory - - if(objectives.len>0) - output += "
      Objectives:" - - var/obj_count = 1 - for(var/datum/objective/objective in objectives) - output += "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ - - recipient << browse(output,"window=memory") - -/datum/mind/proc/edit_memory() - if(!ticker || !ticker.mode) - alert("Not before round-start!", "Alert") - return - - var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
      " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:110: out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
      " - out += {"Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
      - Assigned role: [assigned_role]. Edit
      - Factions and special roles:
      "} - // END AUTOFIX - var/list/sections = list( - "revolution", - "cult", - "wizard", - "changeling", - "vampire", - "nuclear", - "traitor", // "traitorchan", - "monkey", - "malfunction", - "resteam", - "dsquad", - ) - var/text = "" - - if (istype(current, /mob/living/carbon/human) || istype(current, /mob/living/carbon/monkey) || istype(current, /mob/living/simple_animal/construct)) - /** REVOLUTION ***/ - text = "revolution" - if (ticker.mode.config_tag=="revolution") - text = uppertext(text) - text = "[text]: " - if (assigned_role in command_positions) - text += "HEAD|officer|employee|headrev|rev" - else if (assigned_role in list("Security Officer", "Detective", "Warden")) - text += "head|OFFICER|employee|headre|rev" - else if (src in ticker.mode.head_revolutionaries) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:137: text = "head|officer|employee|HEADREV|rev" - text = {"head|officer|employee|HEADREV|rev -
      Flash: give"} - // END AUTOFIX - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - if (flash) - if(!flash.broken) - text += "|take." - else - text += "|take|repair." - else - text += "." - - text += " Reequip (gives traitor uplink)." - if (objectives.len==0) - text += "
      Objectives are empty! Set to kill all heads." - else if (src in ticker.mode.revolutionaries) - text += "head|officer|employee|headrev|REV" - else - text += "head|officer|EMPLOYEE|headrev|rev" - sections["revolution"] = text - - /** CULT ***/ - text = "cult" - if (ticker.mode.config_tag=="cult") - text = uppertext(text) - text = "[text]: " - if (assigned_role in command_positions) - text += "HEAD|officer|employee|cultist" - else if (assigned_role in list("Security Officer", "Detective", "Warden")) - text += "head|OFFICER|employee|cultist" - else if (src in ticker.mode.cult) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:169: text += "head|officer|employee|CULTIST" - text += {"head|officer|employee|CULTIST -
      Give tome|amulet."} - // END AUTOFIX -/* - if (objectives.len==0) - text += "
      Objectives are empty! Set to sacrifice and escape or summon." -*/ - else - text += "head|officer|EMPLOYEE|cultist" - sections["cult"] = text - - /** WIZARD ***/ - text = "wizard" - if (ticker.mode.config_tag=="wizard") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.wizards) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:185: text += "YES|no" - text += {"YES|no -
      To lair, undress, dress up, let choose name."} - // END AUTOFIX - if (objectives.len==0) - text += "
      Objectives are empty! Randomize!" - else - text += "yes|NO" - sections["wizard"] = text - - /** CHANGELING ***/ - text = "changeling" - if (ticker.mode.config_tag=="changeling" || ticker.mode.config_tag=="traitorchan") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.changelings) - text += "YES|no" - if (objectives.len==0) - text += "
      Objectives are empty! Randomize!" - if( changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]) ) - text += "
      Transform to initial appearance." - if( changeling ) - text += "
      [changeling.geneticpoints] genomes" - else - text += "yes|NO" -// var/datum/game_mode/changeling/changeling = ticker.mode -// if (istype(changeling) && changeling.changelingdeath) -// text += "
      All the changelings are dead! Restart in [round((changeling.TIME_TO_GET_REVIVED-(world.time-changeling.changelingdeathtime))/10)] seconds." - sections["changeling"] = text - - /** VAMPIRE ***/ - text = "vampire" - if (ticker.mode.config_tag=="vampire") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.vampires) - text += "YES|no" - if (objectives.len==0) - text += "
      Objectives are empty! Randomize!" - else - text += "yes|NO" - /** ENTHRALLED ***/ - text += "
      enthralled: " - if(src in ticker.mode.enthralled) - text += "YES|no" - else - text += "yes|NO" - sections["vampire"] = text - - /** NUCLEAR ***/ - text = "nuclear" - if (ticker.mode.config_tag=="nuclear") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.syndicates) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:217: text += "OPERATIVE|nanotrasen" - text += {"OPERATIVE|nanotrasen -
      To shuttle, undress, dress up."} - // END AUTOFIX - var/code - for (var/obj/machinery/nuclearbomb/bombue in machines) - if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") - code = bombue.r_code - break - if (code) - text += " Code is [code]. tell the code." - else - text += "operative|NANOTRASEN" - sections["nuclear"] = text - - /** TRAITOR ***/ - text = "traitor" - if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.traitors) - text += "TRAITOR|loyal" - if (objectives.len==0) - text += "
      Objectives are empty! Randomize!" - else - text += "traitor|LOYAL" - sections["traitor"] = text - - /** MONKEY ***/ - if (istype(current, /mob/living/carbon)) - text = "monkey" - if (ticker.mode.config_tag=="monkey") - text = uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/carbon/human)) - text += "healthy|infected|HUMAN|other" - else if (istype(current, /mob/living/carbon/monkey)) - var/found = 0 - for(var/datum/disease/D in current.viruses) - if(istype(D, /datum/disease/jungle_fever)) found = 1 - - if(found) - text += "healthy|INFECTED|human|other" - else - text += "HEALTHY|infected|human|other" - - else - text += "healthy|infected|human|OTHER" - sections["monkey"] = text - - - /** SILICON ***/ - - if (istype(current, /mob/living/silicon)) - text = "silicon" - if (ticker.mode.config_tag=="malfunction") - text = uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/silicon/ai)) - if (src in ticker.mode.malf_ai) - text += "MALF|not malf" - else - text += "malf|NOT MALF" - var/mob/living/silicon/robot/robot = current - if (istype(robot) && robot.emagged) - text += "
      Cyborg: Is emagged! Unemag!
      0th law: [robot.laws.zeroth]" - var/mob/living/silicon/ai/ai = current - if (istype(ai) && ai.connected_robots.len) - var/n_e_robots = 0 - for (var/mob/living/silicon/robot/R in ai.connected_robots) - if (R.emagged) - n_e_robots++ - text += "
      [n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. Unemag" - sections["malfunction"] = text - - if (ticker.mode.config_tag == "traitorchan") - if (sections["traitor"]) - out += sections["traitor"]+"
      " - if (sections["changeling"]) - out += sections["changeling"]+"
      " - sections -= "traitor" - sections -= "changeling" - else - if (sections[ticker.mode.config_tag]) - out += sections[ticker.mode.config_tag]+"
      " - sections -= ticker.mode.config_tag - for (var/i in sections) - if (sections[i]) - out += sections[i]+"
      " - - - if (((src in ticker.mode.head_revolutionaries) || \ - (src in ticker.mode.traitors) || \ - (src in ticker.mode.syndicates)) && \ - istype(current,/mob/living/carbon/human) ) - - text = "Uplink: give" - var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() - var/crystals - if (suplink) - crystals = suplink.uses - if (suplink) - text += "|take" - if (usr.client.holder.rights & R_FUN) - text += ", [crystals] crystals" - else - text += ", [crystals] crystals" - text += "." //hiel grammar - out += text - - /** ERT ***/ - if (istype(current, /mob/living/carbon)) - text = "Emergency Response Team" - text = "[text]: " - if (src in ticker.mode.ert) - text += "YES|no" - else - text += "yes|NO" - sections["resteam"] = text - - /** DEATHSQUAD ***/ - if (istype(current, /mob/living/carbon)) - text = "Death Squad" - text = "[text]: " - if (src in ticker.mode.deathsquad) - text += "YES|no" - else - text += "yes|NO" - sections["dsquad"] = text - - out += {"
      - Strike Teams:
      - [sections["resteam"]]
      - [sections["dsquad"]]
      -
      "} - - out += {"
      - Memory: -
      [memory] -
      Edit memory -
      Objectives:
      "} - - if (objectives.len == 0) - out += "EMPTY
      " - else - var/obj_count = 1 - for(var/datum/objective/objective in objectives) - out += "[obj_count]: [objective.explanation_text] Edit Delete Toggle Completion
      " - obj_count++ - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:338: out += "Add objective

      " - out += {"Add objective

      - Announce objectives

      "} - // END AUTOFIX - usr << browse(out, "window=edit_memory[src]") - -/datum/mind/Topic(href, href_list) - if(!check_rights(R_ADMIN)) return - - if (href_list["role_edit"]) - var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs() - if (!new_role) return - assigned_role = new_role - - else if (href_list["memory_edit"]) - var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN) - if (isnull(new_memo)) return - memory = new_memo - - else if (href_list["obj_edit"] || href_list["obj_add"]) - var/datum/objective/objective - var/objective_pos - var/def_value - - if (href_list["obj_edit"]) - objective = locate(href_list["obj_edit"]) - if (!objective) return - objective_pos = objectives.Find(objective) - - //Text strings are easy to manipulate. Revised for simplicity. - var/temp_obj_type = "[objective.type]"//Convert path into a text string. - def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword. - if(!def_value)//If it's a custom objective, it will be an empty string. - def_value = "custom" - - var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "blood", "debrain", "protect", "prevent", "harm", "brig", "hijack", "escape", "survive", "steal", "download", "nuclear", "capture", "absorb", "custom") - if (!new_obj_type) return - - var/datum/objective/new_objective = null - - switch (new_obj_type) - if ("assassinate","protect","debrain", "harm", "brig") - //To determine what to name the objective in explanation text. - var/objective_type_capital = uppertext(copytext(new_obj_type, 1,2))//Capitalize first letter. - var/objective_type_text = copytext(new_obj_type, 2)//Leave the rest of the text. - var/objective_type = "[objective_type_capital][objective_type_text]"//Add them together into a text string. - - var/list/possible_targets = list("Free objective") - for(var/datum/mind/possible_target in ticker.minds) - if ((possible_target != src) && istype(possible_target.current, /mob/living/carbon/human)) - possible_targets += possible_target.current - - var/mob/def_target = null - var/objective_list[] = list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain) - if (objective&&(objective.type in objective_list) && objective:target) - def_target = objective:target.current - - var/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets - if (!new_target) return - - var/objective_path = text2path("/datum/objective/[new_obj_type]") - if (new_target == "Free objective") - new_objective = new objective_path - new_objective.owner = src - new_objective:target = null - new_objective.explanation_text = "Free objective" - else - new_objective = new objective_path - new_objective.owner = src - new_objective:target = new_target:mind - //Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops. - new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]." - - if ("prevent") - new_objective = new /datum/objective/block - new_objective.owner = src - - if ("hijack") - new_objective = new /datum/objective/hijack - new_objective.owner = src - - if ("escape") - new_objective = new /datum/objective/escape - new_objective.owner = src - - if ("survive") - new_objective = new /datum/objective/survive - new_objective.owner = src - - if ("die") - new_objective = new /datum/objective/die - new_objective.owner = src - - if ("nuclear") - new_objective = new /datum/objective/nuclear - new_objective.owner = src - - if ("steal") - if (!istype(objective, /datum/objective/steal)) - new_objective = new /datum/objective/steal - new_objective.owner = src - else - new_objective = objective - var/datum/objective/steal/steal = new_objective - if (!steal.select_target()) - return - - if("download","capture","absorb", "blood") - var/def_num - if(objective&&objective.type==text2path("/datum/objective/[new_obj_type]")) - def_num = objective.target_amount - - var/target_number = input("Input target number:", "Objective", def_num) as num|null - if (isnull(target_number))//Ordinarily, you wouldn't need isnull. In this case, the value may already exist. - return - - switch(new_obj_type) - if("capture") - new_objective = new /datum/objective/capture - new_objective.explanation_text = "Accumulate [target_number] capture points." - if("absorb") - new_objective = new /datum/objective/absorb - new_objective.explanation_text = "Absorb [target_number] compatible genomes." - if("blood") - new_objective = new /datum/objective/blood - new_objective.explanation_text = "Accumulate atleast [target_number] units of blood in total." - new_objective.owner = src - new_objective.target_amount = target_number - - if ("custom") - var/expl = copytext(sanitize(input("Custom objective:", "Objective", objective ? objective.explanation_text : "") as text|null),1,MAX_MESSAGE_LEN) - if (!expl) return - new_objective = new /datum/objective - new_objective.owner = src - new_objective.explanation_text = expl - - if (!new_objective) return - - if (objective) - objectives -= objective - objectives.Insert(objective_pos, new_objective) - log_admin("[usr.key]/([usr.name]) changed [key]/([name])'s objective from [objective.explanation_text] to [new_objective.explanation_text]") - else - objectives += new_objective - log_admin("[usr.key]/([usr.name]) gave [key]/([name]) the objective: [new_objective.explanation_text]") - - else if (href_list["obj_delete"]) - var/datum/objective/objective = locate(href_list["obj_delete"]) - if(!istype(objective)) return - objectives -= objective - log_admin("[usr.key]/([usr.name]) removed [key]/([name])'s objective ([objective.explanation_text])") - - else if(href_list["obj_completed"]) - var/datum/objective/objective = locate(href_list["obj_completed"]) - if(!istype(objective)) return - objective.completed = !objective.completed - log_admin("[usr.key]/([usr.name]) toggled [key]/([name]) [objective.explanation_text] to [objective.completed ? "completed" : "incomplete"]") - - else if (href_list["revolution"]) - switch(href_list["revolution"]) - if("clear") - if(src in ticker.mode.revolutionaries) - ticker.mode.revolutionaries -= src - to_chat(current, "You have been brainwashed! You are no longer a revolutionary!") - ticker.mode.update_rev_icons_removed(src) - special_role = null - if(src in ticker.mode.head_revolutionaries) - ticker.mode.head_revolutionaries -= src - to_chat(current, "You have been brainwashed! You are no longer a head revolutionary!") - ticker.mode.update_rev_icons_removed(src) - special_role = null - log_admin("[key_name_admin(usr)] has de-rev'ed [current].") - - if("rev") - if(src in ticker.mode.head_revolutionaries) - ticker.mode.head_revolutionaries -= src - ticker.mode.update_rev_icons_removed(src) - to_chat(current, "Revolution has been disappointed of your leader traits! You are a regular revolutionary now!") - else if(!(src in ticker.mode.revolutionaries)) - to_chat(current, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") - else - return - ticker.mode.revolutionaries += src - ticker.mode.update_rev_icons_added(src) - special_role = "Revolutionary" - log_admin("[key_name(usr)] has rev'ed [current].") - - if("headrev") - if(src in ticker.mode.revolutionaries) - ticker.mode.revolutionaries -= src - ticker.mode.update_rev_icons_removed(src) - to_chat(current, "You have proved your devotion to revoltion! Yea are a head revolutionary now!") - else if(!(src in ticker.mode.head_revolutionaries)) - to_chat(current, "You are a member of the revolutionaries' leadership now!") - else - return - if (ticker.mode.head_revolutionaries.len>0) - // copy targets - var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries - if (valid_head) - for (var/datum/objective/mutiny/O in valid_head.objectives) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = src - rev_obj.target = O.target - rev_obj.explanation_text = "Assassinate [O.target.name], the [O.target.assigned_role]." - objectives += rev_obj - ticker.mode.greet_revolutionary(src,0) - ticker.mode.head_revolutionaries += src - ticker.mode.update_rev_icons_added(src) - special_role = "Head Revolutionary" - log_admin("[key_name_admin(usr)] has head-rev'ed [current].") - - if("autoobjectives") - ticker.mode.forge_revolutionary_objectives(src) - ticker.mode.greet_revolutionary(src,0) - to_chat(usr, "The objectives for revolution have been generated and shown to [key]") - - if("flash") - if (!ticker.mode.equip_revolutionary(current)) - to_chat(usr, "Spawning flash failed!") - - if("takeflash") - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - if (!flash) - to_chat(usr, "Deleting flash failed!") - qdel(flash) - - if("repairflash") - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - if (!flash) - to_chat(usr, "Repairing flash failed!") - else - flash.broken = 0 - - if("reequip") - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - qdel(flash) - take_uplink() - var/fail = 0 - fail |= !ticker.mode.equip_traitor(current, 1) - fail |= !ticker.mode.equip_revolutionary(current) - if (fail) - to_chat(usr, "Reequipping revolutionary goes wrong!") - - else if (href_list["cult"]) - switch(href_list["cult"]) - if("clear") - if(src in ticker.mode.cult) - ticker.mode.cult -= src - ticker.mode.update_cult_icons_removed(src) - special_role = null - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memoize_cult_objectives(src) - to_chat(current, "You have been brainwashed! You are no longer a cultist!") - to_chat(current, "You find yourself unable to mouth the words of the forgotten...") - current.remove_language("Cult") - memory = "" - log_admin("[key_name_admin(usr)] has de-cult'ed [current].") - if("cultist") - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) - special_role = "Cultist" - to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie.") - to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - to_chat(current, "You can now speak and understand the forgotten tongue of the occult.") - current.add_language("Cult") - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memoize_cult_objectives(src) - log_admin("[key_name_admin(usr)] has cult'ed [current].") - if("tome") - var/mob/living/carbon/human/H = current - if (istype(H)) - var/obj/item/weapon/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if (!where) - to_chat(usr, "Spawning tome failed!") - else - to_chat(H, "A tome, a message from your new master, appears in your [where].") - - if("amulet") - if (!ticker.mode.equip_cultist(current)) - to_chat(usr, "Spawning amulet failed!") - - else if (href_list["wizard"]) - switch(href_list["wizard"]) - if("clear") - if(src in ticker.mode.wizards) - ticker.mode.wizards -= src - special_role = null - current.spellremove(current, config.feature_object_spell_system? "object":"verb") - to_chat(current, "You have been brainwashed! You are no longer a wizard!") - ticker.mode.update_wizard_icons_removed(src) - log_admin("[key_name_admin(usr)] has de-wizard'ed [current].") - if("wizard") - if(!(src in ticker.mode.wizards)) - ticker.mode.wizards += src - special_role = "Wizard" - //ticker.mode.learn_basic_spells(current) - to_chat(current, "You are the Space Wizard!") - ticker.mode.update_wizard_icons_added(src) - log_admin("[key_name_admin(usr)] has wizard'ed [current].") - if("lair") - current.loc = pick(wizardstart) - if("dressup") - ticker.mode.equip_wizard(current) - if("name") - ticker.mode.name_wizard(current) - if("autoobjectives") - ticker.mode.forge_wizard_objectives(src) - to_chat(usr, "The objectives for wizard [key] have been generated. You can edit them and anounce manually.") - ticker.mode.update_all_wizard_icons() - - else if (href_list["changeling"]) - switch(href_list["changeling"]) - if("clear") - if(src in ticker.mode.changelings) - ticker.mode.changelings -= src - special_role = null - current.remove_changeling_powers() - current.verbs -= /datum/changeling/proc/EvolutionMenu - if(changeling) - qdel(changeling) - changeling = null - to_chat(current, "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!") - log_admin("[key_name_admin(usr)] has de-changeling'ed [current].") - if("changeling") - if(!(src in ticker.mode.changelings)) - ticker.mode.changelings += src - ticker.mode.grant_changeling_powers(current) - special_role = "Changeling" - to_chat(current, "Your powers are awoken. A flash of memory returns to us...we are a changeling!") - log_admin("[key_name_admin(usr)] has changeling'ed [current].") - if("autoobjectives") - ticker.mode.forge_changeling_objectives(src) - to_chat(usr, "The objectives for changeling [key] have been generated. You can edit them and anounce manually.") - - if("initialdna") - if( !changeling || !changeling.absorbed_dna.len ) - to_chat(usr, "Resetting DNA failed!") - else - current.dna = changeling.absorbed_dna[1] - current.real_name = current.dna.real_name - current.UpdateAppearance() - domutcheck(current, null) - - if("set_genomes") - if( !changeling ) - to_chat(usr, "No changeling!") - return - var/new_g = input(usr,"Number of genomes","Changeling",changeling.geneticpoints) as num - changeling.geneticpoints = Clamp(new_g, 0, 100) - log_admin("[key_name_admin(usr)] has set changeling [current] to [changeling.geneticpoints] genomes.") - - else if (href_list["vampire"]) - switch(href_list["vampire"]) - if("clear") - if(src in ticker.mode.vampires) - ticker.mode.vampires -= src - special_role = null - current.remove_vampire_powers() - if(vampire) - qdel(vampire) - vampire = null - to_chat(current, "You grow weak and lose your powers! You are no longer a vampire and are stuck in your current form!") - log_admin("[key_name_admin(usr)] has de-vampired [current].") - if("vampire") - if(!(src in ticker.mode.vampires)) - ticker.mode.vampires += src - ticker.mode.grant_vampire_powers(current) - special_role = "Vampire" - to_chat(current, "Your powers are awoken. Your lust for blood grows... You are a Vampire!") - log_admin("[key_name_admin(usr)] has vampired [current].") - if("autoobjectives") - ticker.mode.forge_vampire_objectives(src) - to_chat(usr, "The objectives for vampire [key] have been generated. You can edit them and announce manually.") - - else if (href_list["nuclear"]) - switch(href_list["nuclear"]) - if("clear") - if(src in ticker.mode.syndicates) - ticker.mode.syndicates -= src - ticker.mode.update_synd_icons_removed(src) - special_role = null - for (var/datum/objective/nuclear/O in objectives) - objectives-=O - to_chat(current, "You have been brainwashed! You are no longer a syndicate operative!") - log_admin("[key_name_admin(usr)] has de-nuke op'ed [current].") - if("nuclear") - if(!(src in ticker.mode.syndicates)) - ticker.mode.syndicates += src - ticker.mode.update_synd_icons_added(src) - if (ticker.mode.syndicates.len==1) - ticker.mode.prepare_syndicate_leader(src) - else - current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" - special_role = "Syndicate" - to_chat(current, "You are a [syndicate_name()] agent!") - ticker.mode.forge_syndicate_objectives(src) - ticker.mode.greet_syndicate(src) - log_admin("[key_name_admin(usr)] has nuke op'ed [current].") - if("lair") - current.loc = get_turf(locate("landmark*Syndicate-Spawn")) - if("dressup") - var/mob/living/carbon/human/H = current - qdel(H.belt) - qdel(H.back) - qdel(H.ears) - qdel(H.gloves) - qdel(H.head) - qdel(H.shoes) - qdel(H.wear_id) - qdel(H.wear_suit) - qdel(H.w_uniform) - - if (!ticker.mode.equip_syndicate(current)) - to_chat(usr, "Equipping a syndicate failed!") - if("tellcode") - var/code - for (var/obj/machinery/nuclearbomb/bombue in machines) - if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") - code = bombue.r_code - break - if (code) - store_memory("Syndicate Nuclear Bomb Code: [code]", 0, 0) - to_chat(current, "The nuclear authorization code is: [code]") - else - to_chat(usr, "No valid nuke found!") - - else if (href_list["traitor"]) - switch(href_list["traitor"]) - if ("clear") - if(src in ticker.mode.traitors) - ticker.mode.traitors -= src - special_role = null - to_chat(current, "You have been brainwashed! You are no longer a traitor!") - log_admin("[key_name_admin(usr)] has de-traitor'ed [current].") - if(isAI(current)) - var/mob/living/silicon/ai/A = current - A.set_zeroth_law("") - A.show_laws() - if ("traitor") - if (make_traitor()) - log_admin("[key_name(usr)] has traitor'ed [key_name(current)].") - if ("autoobjectives") - ticker.mode.forge_traitor_objectives(src) - to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and anounce manually.") - - else if (href_list["monkey"]) - var/mob/living/L = current - if (L.monkeyizing) - return - switch(href_list["monkey"]) - if("healthy") - if (usr.client.holder.rights & R_ADMIN) - var/mob/living/carbon/human/H = current - var/mob/living/carbon/monkey/M = current - if (istype(H)) - log_admin("[key_name(usr)] attempting to monkeyize [key_name(current)]") - message_admins("[key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") - src = null - M = H.monkeyize() - src = M.mind -// to_chat(world, "DEBUG: \"healthy\": M=[M], M.mind=[M.mind], src=[src]!") - else if (istype(M) && length(M.viruses)) - for(var/datum/disease/D in M.viruses) - D.cure(0) - sleep(0) //because deleting of virus is done through spawn(0) - if("infected") - if (usr.client.holder.rights & R_ADMIN) - var/mob/living/carbon/human/H = current - var/mob/living/carbon/monkey/M = current - if (istype(H)) - log_admin("[key_name(usr)] attempting to monkeyize and infect [key_name(current)]") - message_admins("[key_name_admin(usr)] attempting to monkeyize and infect [key_name_admin(current)]", 1) - src = null - M = H.monkeyize() - src = M.mind - current.contract_disease(new /datum/disease/jungle_fever,1,0) - else if (istype(M)) - current.contract_disease(new /datum/disease/jungle_fever,1,0) - if("human") - var/mob/living/carbon/monkey/M = current - if (istype(M)) - for(var/datum/disease/D in M.viruses) - if (istype(D,/datum/disease/jungle_fever)) - D.cure(0) - sleep(0) //because deleting of virus is doing throught spawn(0) - log_admin("[key_name(usr)] attempting to humanize [key_name(current)]") - message_admins("[key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") - var/obj/item/weapon/dnainjector/nofail/m2h/m2h = new - var/obj/item/weapon/implant/mobfinder = new(M) //hack because humanizing deletes mind --rastaf0 - src = null - m2h.inject(M) - src = mobfinder.loc:mind - qdel(mobfinder) - mobfinder = null - current.radiation -= 50 - - else if (href_list["silicon"]) - switch(href_list["silicon"]) - if("unmalf") - if(src in ticker.mode.malf_ai) - ticker.mode.malf_ai -= src - special_role = null - var/mob/living/silicon/ai/A = current - - A.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, - /datum/game_mode/malfunction/proc/takeover, - /datum/game_mode/malfunction/proc/ai_win) - - A.malf_picker.remove_verbs(A) - - - A.laws = new base_law_type - qdel(A.malf_picker) - A.malf_picker = null - A.show_laws() - A.icon_state = "ai" - - to_chat(A, "You have been patched! You are no longer malfunctioning!") - message_admins("[key_name_admin(usr)] has de-malf'ed [A].") - log_admin("[key_name_admin(usr)] has de-malf'ed [A].") - - if("malf") - make_AI_Malf() - log_admin("[key_name_admin(usr)] has malf'ed [current].") - - if("unemag") - if(istype(current,/mob/living/silicon/robot/mommi)) - var/mob/living/silicon/robot/mommi/R = current - R.emagged = 0 - if (R.activated(R.module.emag)) - R.module_active = null - if(R.tool_state == R.module.emag) - R.tool_state = null - R.contents -= R.module.emag - log_admin("[key_name_admin(usr)] has unemag'ed [R].") - else - if (istype(current,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = current - R.emagged = 0 - if (R.activated(R.module.emag)) - R.module_active = null - if(R.module_state_1 == R.module.emag) - R.module_state_1 = null - R.contents -= R.module.emag - else if(R.module_state_2 == R.module.emag) - R.module_state_2 = null - R.contents -= R.module.emag - else if(R.module_state_3 == R.module.emag) - R.module_state_3 = null - R.contents -= R.module.emag - log_admin("[key_name_admin(usr)] has unemag'ed [R].") - - if("unemagcyborgs") - if (istype(current, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/ai = current - for (var/mob/living/silicon/robot/R in ai.connected_robots) - R.emagged = 0 - if(istype(R,/mob/living/silicon/robot/mommi)) - var/mob/living/silicon/robot/mommi/M=R - if (M.activated(M.module.emag)) - M.module_active = null - if(M.tool_state == M.module.emag) - M.tool_state = null - M.contents -= M.module.emag - if (R.module) - if (R.activated(R.module.emag)) - R.module_active = null - if(R.module_state_1 == R.module.emag) - R.module_state_1 = null - R.contents -= R.module.emag - else if(R.module_state_2 == R.module.emag) - R.module_state_2 = null - R.contents -= R.module.emag - else if(R.module_state_3 == R.module.emag) - R.module_state_3 = null - R.contents -= R.module.emag - log_admin("[key_name_admin(usr)] has unemag'ed [ai]'s Cyborgs.") - - else if (href_list["common"]) - switch(href_list["common"]) - if("undress") - for(var/obj/item/W in current) - current.drop_from_inventory(W) - if("takeuplink") - take_uplink() - memory = null//Remove any memory they may have had. - if("crystals") - if (usr.client.holder.rights & R_FUN) - var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() - var/crystals - if (suplink) - crystals = suplink.uses - crystals = input("Amount of telecrystals for [key]","Syndicate uplink", crystals) as null|num - if (!isnull(crystals)) - if (suplink) - var/diff = crystals - suplink.uses - suplink.uses = crystals - total_TC += diff - if("uplink") - if (!ticker.mode.equip_traitor(current, !(src in ticker.mode.traitors))) - to_chat(usr, "Equipping a syndicate failed!") - - else if (href_list["obj_announce"]) - var/obj_count = 1 - to_chat(current, "Your current objectives:") - for(var/datum/objective/objective in objectives) - to_chat(current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - - else if (href_list["resteam"]) - switch(href_list["resteam"]) - if ("clear") - if(src in ticker.mode.ert) - ticker.mode.ert -= src - special_role = null - to_chat(current, "You have been demoted! You are no longer an Emergency Responder!") - log_admin("[key_name_admin(usr)] has de-ERT'ed [current].") - if ("resteam") - if (!(src in ticker.mode.ert)) - ticker.mode.ert += src - assigned_role = "MODE" - special_role = "Response Team" - log_admin("[key_name(usr)] has ERT'ed [key_name(current)].") - - else if (href_list["dsquad"]) - switch(href_list["dsquad"]) - if ("clear") - if(src in ticker.mode.deathsquad) - ticker.mode.deathsquad -= src - special_role = null - to_chat(current, "You have been demoted! You are no longer a Death Commando!") - log_admin("[key_name_admin(usr)] has de-deathsquad'ed [current].") - if ("dsquad") - if (!(src in ticker.mode.deathsquad)) - ticker.mode.deathsquad += src - assigned_role = "MODE" - special_role = "Death Commando" - log_admin("[key_name(usr)] has deathsquad'ed [key_name(current)].") - - - edit_memory() -/* -proc/clear_memory(var/silent = 1) - var/datum/game_mode/current_mode = ticker.mode - - // remove traitor uplinks - var/list/L = current.get_contents() - for (var/t in L) - if (istype(t, /obj/item/device/pda)) - var/obj/item/device/pda/P = t - if (P.uplink) del(P.uplink) - P.uplink = null - else if (istype(t, /obj/item/device/radio)) - var/obj/item/device/radio/R = t - if (R.traitorradio) del(R.traitorradio) - R.traitorradio = null - R.traitor_frequency = 0.0 - else if (istype(t, /obj/item/weapon/SWF_uplink) || istype(t, /obj/item/weapon/syndicate_uplink)) - var/obj/item/weapon/W = t - if (W.origradio) - var/obj/item/device/radio/R = t:origradio - R.loc = current.loc - R.traitorradio = null - R.traitor_frequency = 0.0 - del(W) - - // remove wizards spells - //If there are more special powers that need removal, they can be procced into here./N - current.spellremove(current) - - // clear memory - memory = "" - special_role = null - -*/ - -/datum/mind/proc/find_syndicate_uplink() - var/uplink = null - - for (var/obj/item/I in get_contents_in_object(current, /obj/item)) - if (I && I.hidden_uplink) - uplink = I.hidden_uplink - break - - return uplink - -/datum/mind/proc/take_uplink() - var/obj/item/device/uplink/hidden/H = find_syndicate_uplink() - if(H) - qdel(H) - - -/datum/mind/proc/make_AI_Malf() - if(!isAI(current)) - return - if(!(src in ticker.mode.malf_ai)) - ticker.mode.malf_ai += src - var/mob/living/silicon/ai/A = current - A.verbs += /mob/living/silicon/ai/proc/choose_modules - A.verbs += /datum/game_mode/malfunction/proc/takeover - A.malf_picker = new /datum/module_picker - var/datum/ai_laws/laws = A.laws - laws.malfunction() - A.show_laws() - to_chat(A, "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first...") - special_role = "malfunction" - A.icon_state = "ai-malf" - -/datum/mind/proc/make_Nuke() - if(!(src in ticker.mode.syndicates)) - ticker.mode.syndicates += src - ticker.mode.update_synd_icons_added(src) - if (ticker.mode.syndicates.len==1) - ticker.mode.prepare_syndicate_leader(src) - else - current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" - special_role = "Syndicate" - assigned_role = "MODE" - to_chat(current, "You are a [syndicate_name()] agent!") - ticker.mode.forge_syndicate_objectives(src) - ticker.mode.greet_syndicate(src) - - current.loc = get_turf(locate("landmark*Syndicate-Spawn")) - - var/mob/living/carbon/human/H = current - qdel(H.belt) - qdel(H.back) - qdel(H.ears) - qdel(H.gloves) - qdel(H.head) - qdel(H.shoes) - qdel(H.wear_id) - qdel(H.wear_suit) - qdel(H.w_uniform) - - ticker.mode.equip_syndicate(current) - -/datum/mind/proc/make_Changling() - if(!(src in ticker.mode.changelings)) - ticker.mode.changelings += src - ticker.mode.grant_changeling_powers(current) - special_role = "Changeling" - ticker.mode.forge_changeling_objectives(src) - ticker.mode.greet_changeling(src) - -/datum/mind/proc/make_Wizard() - if(!(src in ticker.mode.wizards)) - ticker.mode.wizards += src - special_role = "Wizard" - assigned_role = "MODE" - //ticker.mode.learn_basic_spells(current) - ticker.mode.update_wizard_icons_added(src) - if(!wizardstart.len) - current.loc = pick(latejoin) - to_chat(current, "HOT INSERTION, GO GO GO") - else - current.loc = pick(wizardstart) - - ticker.mode.equip_wizard(current) - for(var/obj/item/weapon/spellbook/S in current.contents) - S.op = 0 - ticker.mode.name_wizard(current) - ticker.mode.forge_wizard_objectives(src) - ticker.mode.greet_wizard(src) - ticker.mode.update_all_wizard_icons() - - -/datum/mind/proc/make_Cultist() - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_cult_icons_added(src) - special_role = "Cultist" - to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie.") - to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - to_chat(current, "You can now speak and understand the forgotten tongue of the occult.") - current.add_language("Cult") - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - cult.memoize_cult_objectives(src) - else - var/explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." - to_chat(current, "Objective #1: [explanation]") - current.memory += "Objective #1: [explanation]
      " - to_chat(current, "The convert rune is join blood self") - current.memory += "The convert rune is join blood self
      " - - var/mob/living/carbon/human/H = current - if (istype(H)) - var/obj/item/weapon/tome/T = new(H) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = H.equip_in_one_of_slots(T, slots) - if (!where) - else - to_chat(H, "A tome, a message from your new master, appears in your [where].") - - if (!ticker.mode.equip_cultist(current)) - to_chat(H, "Spawning an amulet from your Master failed.") - -/datum/mind/proc/make_Rev() - if (ticker.mode.head_revolutionaries.len>0) - // copy targets - var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries - if (valid_head) - for (var/datum/objective/mutiny/O in valid_head.objectives) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = src - rev_obj.target = O.target - rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]." - objectives += rev_obj - ticker.mode.greet_revolutionary(src,0) - ticker.mode.head_revolutionaries += src - ticker.mode.update_rev_icons_added(src) - special_role = "Head Revolutionary" - - ticker.mode.forge_revolutionary_objectives(src) - ticker.mode.greet_revolutionary(src,0) - - var/list/L = current.get_contents() - var/obj/item/device/flash/flash = locate() in L - qdel(flash) - take_uplink() - var/fail = 0 -// fail |= !ticker.mode.equip_traitor(current, 1) - fail |= !ticker.mode.equip_revolutionary(current) - - -// check whether this mind's mob has been brigged for the given duration -// have to call this periodically for the duration to work properly -/datum/mind/proc/is_brigged(duration) - var/turf/T = current.loc - if(!istype(T)) - brigged_since = -1 - return 0 - - var/is_currently_brigged = 0 - - if(istype(T.loc,/area/security/brig)) - is_currently_brigged = 1 - for(var/obj/item/weapon/card/id/card in current) - is_currently_brigged = 0 - break // if they still have ID they're not brigged - for(var/obj/item/device/pda/P in current) - if(P.id) - is_currently_brigged = 0 - break // if they still have ID they're not brigged - - if(!is_currently_brigged) - brigged_since = -1 - return 0 - - if(brigged_since == -1) - brigged_since = world.time - - return (duration <= world.time - brigged_since) - -/datum/mind/proc/make_traitor() - if (!(src in ticker.mode.traitors)) - ticker.mode.traitors += src - - special_role = "traitor" - - ticker.mode.forge_traitor_objectives(src) - - to_chat(current, {" - ATTENTION - It's time to pay your debt to \the [syndicate_name()]. - "}) - - ticker.mode.finalize_traitor(src) - - ticker.mode.greet_traitor(src) - - return TRUE - - return FALSE - -//Initialisation procs -/mob/proc/mind_initialize() // vgedit: /mob instead of /mob/living - if(mind) - mind.key = key - else - mind = new /datum/mind(key) - mind.original = src - if(ticker) - ticker.minds += mind - else - world.log << "## DEBUG: mind_initialize(): No ticker ready yet! Please inform Carn" - if(!mind.name) mind.name = real_name - mind.current = src - -//HUMAN -/mob/living/carbon/human/mind_initialize() - ..() - if(!mind.assigned_role) mind.assigned_role = "Assistant" //defualt - -//MONKEY -/mob/living/carbon/monkey/mind_initialize() - ..() - -//slime -/mob/living/carbon/slime/mind_initialize() - ..() - mind.assigned_role = "slime" - -//XENO -/mob/living/carbon/alien/mind_initialize() - ..() - mind.assigned_role = "Alien" - //XENO HUMANOID -/mob/living/carbon/alien/humanoid/queen/mind_initialize() - ..() - mind.special_role = "Queen" - -/mob/living/carbon/alien/humanoid/hunter/mind_initialize() - ..() - mind.special_role = "Hunter" - -/mob/living/carbon/alien/humanoid/drone/mind_initialize() - ..() - mind.special_role = "Drone" - -/mob/living/carbon/alien/humanoid/sentinel/mind_initialize() - ..() - mind.special_role = "Sentinel" - //XENO LARVA -/mob/living/carbon/alien/larva/mind_initialize() - ..() - mind.special_role = "Larva" - -//AI -/mob/living/silicon/ai/mind_initialize() - ..() - mind.assigned_role = "AI" - -//BORG -/mob/living/silicon/robot/mind_initialize() - ..() - mind.assigned_role = "[isMoMMI(src) ? "Mobile MMI" : "Cyborg"]" - -//PAI -/mob/living/silicon/pai/mind_initialize() - ..() - mind.assigned_role = "pAI" - mind.special_role = "" - -//BLOB -/mob/camera/overmind/mind_initialize() - ..() - mind.special_role = "Blob" - -//Animals -/mob/living/simple_animal/mind_initialize() - ..() - mind.assigned_role = "Animal" - -/mob/living/simple_animal/corgi/mind_initialize() - ..() - mind.assigned_role = "Corgi" - -/mob/living/simple_animal/shade/mind_initialize() - ..() - mind.assigned_role = "Shade" - -/mob/living/simple_animal/construct/builder/mind_initialize() - ..() - mind.assigned_role = "Artificer" - mind.special_role = "Cultist" - -/mob/living/simple_animal/construct/wraith/mind_initialize() - ..() - mind.assigned_role = "Wraith" - mind.special_role = "Cultist" - -/mob/living/simple_animal/construct/armoured/mind_initialize() - ..() - mind.assigned_role = "Juggernaut" - mind.special_role = "Cultist" - -/mob/living/simple_animal/vox/armalis/mind_initialize() - ..() - mind.assigned_role = "Armalis" - mind.special_role = "Vox Raider" - - -/proc/mind_can_reenter(var/datum/mind/mind) - if(mind) - for(var/mob/dead/observer/G in player_list) - if(G.can_reenter_corpse && G.mind == mind) - return TRUE - return FALSE +/* Note from Carnie: + The way datum/mind stuff works has been changed a lot. + Minds now represent IC characters rather than following a client around constantly. + + Guidelines for using minds properly: + + - Never mind.transfer_to(ghost). The var/current and var/original of a mind must always be of type mob/living! + ghost.mind is however used as a reference to the ghost's corpse + + - When creating a new mob for an existing IC character (e.g. cloning a dead guy or borging a brain of a human) + the existing mind of the old mob should be transfered to the new mob like so: + + mind.transfer_to(new_mob) + + - You must not assign key= or ckey= after transfer_to() since the transfer_to transfers the client for you. + By setting key or ckey explicitly after transfering the mind with transfer_to you will cause bugs like DCing + the player. + + - IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you. + + - When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting + a ghost to become a xeno during an event). Simply assign the key or ckey like you've always done. + + new_mob.key = key + + The Login proc will handle making a new mob for that mobtype (including setting up stuff like mind.name). Simple! + However if you want that mind to have any special properties like being a traitor etc you will have to do that + yourself. + +*/ + +/datum/mind + var/key + var/name //replaces mob/var/original_name + var/mob/living/current + var/mob/living/original //TODO: remove.not used in any meaningful way ~Carn. First I'll need to tweak the way silicon-mobs handle minds. + var/active = 0 + + var/memory + + var/assigned_role + var/special_role + var/list/wizard_spells // So we can track our wizmen spells that we learned from the book of magicks. + + var/role_alt_title + + var/datum/job/assigned_job + + var/list/kills=list() + var/list/datum/objective/objectives = list() + var/list/datum/objective/special_verbs = list() + + var/has_been_rev = 0//Tracks if this mind has been a rev or not + + var/datum/faction/faction //associated faction + var/datum/changeling/changeling //changeling holder + var/datum/vampire/vampire //vampire holder + + var/rev_cooldown = 0 + + // the world.time since the mob has been brigged, or -1 if not at all + var/brigged_since = -1 + + //put this here for easier tracking ingame + var/datum/money_account/initial_account + var/list/uplink_items_bought = list() + var/total_TC = 0 + var/spent_TC = 0 + + //fix scrying raging mages issue. + var/isScrying = 0 + + +/datum/mind/New(var/key) + src.key = key + +/datum/mind/proc/transfer_to(mob/living/new_character) + if(!istype(new_character)) + error("transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob. Please inform Carn") + + if(current) //remove ourself from our old body's mind variable + if(changeling) + current.remove_changeling_powers() + current.verbs -= /datum/changeling/proc/EvolutionMenu + if(vampire) + current.remove_vampire_powers() + current.mind = null + if(new_character.mind) //remove any mind currently in our new body's mind variable + new_character.mind.current = null + + nanomanager.user_transferred(current, new_character) + + current = new_character //link ourself to our new body + new_character.mind = src //and link our new body to ourself + + if(changeling) + new_character.make_changeling() + if(vampire) + new_character.make_vampire() + if(active) + new_character.key = key //now transfer the key to link the client to our new body + +/datum/mind/proc/store_memory(new_text) + memory += "[new_text]
      " + +/datum/mind/proc/show_memory(mob/recipient) + var/output = "[current.real_name]'s Memory
      " + output += memory + + if(objectives.len>0) + output += "
      Objectives:" + + var/obj_count = 1 + for(var/datum/objective/objective in objectives) + output += "Objective #[obj_count]: [objective.explanation_text]" + obj_count++ + + recipient << browse(output,"window=memory") + +/datum/mind/proc/edit_memory() + if(!ticker || !ticker.mode) + alert("Not before round-start!", "Alert") + return + + var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
      " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:110: out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
      " + out += {"Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
      + Assigned role: [assigned_role]. Edit
      + Factions and special roles:
      "} + // END AUTOFIX + var/list/sections = list( + "revolution", + "cult", + "wizard", + "changeling", + "vampire", + "nuclear", + "traitor", // "traitorchan", + "monkey", + "malfunction", + "resteam", + "dsquad", + ) + var/text = "" + + if (istype(current, /mob/living/carbon/human) || istype(current, /mob/living/carbon/monkey) || istype(current, /mob/living/simple_animal/construct)) + /** REVOLUTION ***/ + text = "revolution" + if (ticker.mode.config_tag=="revolution") + text = uppertext(text) + text = "[text]: " + if (assigned_role in command_positions) + text += "HEAD|officer|employee|headrev|rev" + else if (assigned_role in list("Security Officer", "Detective", "Warden")) + text += "head|OFFICER|employee|headre|rev" + else if (src in ticker.mode.head_revolutionaries) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:137: text = "head|officer|employee|HEADREV|rev" + text = {"head|officer|employee|HEADREV|rev +
      Flash: give"} + // END AUTOFIX + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (flash) + if(!flash.broken) + text += "|take." + else + text += "|take|repair." + else + text += "." + + text += " Reequip (gives traitor uplink)." + if (objectives.len==0) + text += "
      Objectives are empty! Set to kill all heads." + else if (src in ticker.mode.revolutionaries) + text += "head|officer|employee|headrev|REV" + else + text += "head|officer|EMPLOYEE|headrev|rev" + sections["revolution"] = text + + /** CULT ***/ + text = "cult" + if (ticker.mode.config_tag=="cult") + text = uppertext(text) + text = "[text]: " + if (assigned_role in command_positions) + text += "HEAD|officer|employee|cultist" + else if (assigned_role in list("Security Officer", "Detective", "Warden")) + text += "head|OFFICER|employee|cultist" + else if (src in ticker.mode.cult) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:169: text += "head|officer|employee|CULTIST" + text += {"head|officer|employee|CULTIST +
      Give tome|amulet."} + // END AUTOFIX +/* + if (objectives.len==0) + text += "
      Objectives are empty! Set to sacrifice and escape or summon." +*/ + else + text += "head|officer|EMPLOYEE|cultist" + sections["cult"] = text + + /** WIZARD ***/ + text = "wizard" + if (ticker.mode.config_tag=="wizard") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.wizards) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:185: text += "YES|no" + text += {"YES|no +
      To lair, undress, dress up, let choose name."} + // END AUTOFIX + if (objectives.len==0) + text += "
      Objectives are empty! Randomize!" + else + text += "yes|NO" + sections["wizard"] = text + + /** CHANGELING ***/ + text = "changeling" + if (ticker.mode.config_tag=="changeling" || ticker.mode.config_tag=="traitorchan") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.changelings) + text += "YES|no" + if (objectives.len==0) + text += "
      Objectives are empty! Randomize!" + if( changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]) ) + text += "
      Transform to initial appearance." + if( changeling ) + text += "
      [changeling.geneticpoints] genomes" + else + text += "yes|NO" +// var/datum/game_mode/changeling/changeling = ticker.mode +// if (istype(changeling) && changeling.changelingdeath) +// text += "
      All the changelings are dead! Restart in [round((changeling.TIME_TO_GET_REVIVED-(world.time-changeling.changelingdeathtime))/10)] seconds." + sections["changeling"] = text + + /** VAMPIRE ***/ + text = "vampire" + if (ticker.mode.config_tag=="vampire") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.vampires) + text += "YES|no" + if (objectives.len==0) + text += "
      Objectives are empty! Randomize!" + else + text += "yes|NO" + /** ENTHRALLED ***/ + text += "
      enthralled: " + if(src in ticker.mode.enthralled) + text += "YES|no" + else + text += "yes|NO" + sections["vampire"] = text + + /** NUCLEAR ***/ + text = "nuclear" + if (ticker.mode.config_tag=="nuclear") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.syndicates) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:217: text += "OPERATIVE|nanotrasen" + text += {"OPERATIVE|nanotrasen +
      To shuttle, undress, dress up."} + // END AUTOFIX + var/code + for (var/obj/machinery/nuclearbomb/bombue in machines) + if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") + code = bombue.r_code + break + if (code) + text += " Code is [code]. tell the code." + else + text += "operative|NANOTRASEN" + sections["nuclear"] = text + + /** TRAITOR ***/ + text = "traitor" + if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.traitors) + text += "TRAITOR|loyal" + if (objectives.len==0) + text += "
      Objectives are empty! Randomize!" + else + text += "traitor|LOYAL" + sections["traitor"] = text + + /** MONKEY ***/ + if (istype(current, /mob/living/carbon)) + text = "monkey" + if (ticker.mode.config_tag=="monkey") + text = uppertext(text) + text = "[text]: " + if (istype(current, /mob/living/carbon/human)) + text += "healthy|infected|HUMAN|other" + else if (istype(current, /mob/living/carbon/monkey)) + var/found = 0 + for(var/datum/disease/D in current.viruses) + if(istype(D, /datum/disease/jungle_fever)) found = 1 + + if(found) + text += "healthy|INFECTED|human|other" + else + text += "HEALTHY|infected|human|other" + + else + text += "healthy|infected|human|OTHER" + sections["monkey"] = text + + + /** SILICON ***/ + + if (istype(current, /mob/living/silicon)) + text = "silicon" + if (ticker.mode.config_tag=="malfunction") + text = uppertext(text) + text = "[text]: " + if (istype(current, /mob/living/silicon/ai)) + if (src in ticker.mode.malf_ai) + text += "MALF|not malf" + else + text += "malf|NOT MALF" + var/mob/living/silicon/robot/robot = current + if (istype(robot) && robot.emagged) + text += "
      Cyborg: Is emagged! Unemag!
      0th law: [robot.laws.zeroth]" + var/mob/living/silicon/ai/ai = current + if (istype(ai) && ai.connected_robots.len) + var/n_e_robots = 0 + for (var/mob/living/silicon/robot/R in ai.connected_robots) + if (R.emagged) + n_e_robots++ + text += "
      [n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. Unemag" + sections["malfunction"] = text + + if (ticker.mode.config_tag == "traitorchan") + if (sections["traitor"]) + out += sections["traitor"]+"
      " + if (sections["changeling"]) + out += sections["changeling"]+"
      " + sections -= "traitor" + sections -= "changeling" + else + if (sections[ticker.mode.config_tag]) + out += sections[ticker.mode.config_tag]+"
      " + sections -= ticker.mode.config_tag + for (var/i in sections) + if (sections[i]) + out += sections[i]+"
      " + + + if (((src in ticker.mode.head_revolutionaries) || \ + (src in ticker.mode.traitors) || \ + (src in ticker.mode.syndicates)) && \ + istype(current,/mob/living/carbon/human) ) + + text = "Uplink: give" + var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() + var/crystals + if (suplink) + crystals = suplink.uses + if (suplink) + text += "|take" + if (usr.client.holder.rights & R_FUN) + text += ", [crystals] crystals" + else + text += ", [crystals] crystals" + text += "." //hiel grammar + out += text + + /** ERT ***/ + if (istype(current, /mob/living/carbon)) + text = "Emergency Response Team" + text = "[text]: " + if (src in ticker.mode.ert) + text += "YES|no" + else + text += "yes|NO" + sections["resteam"] = text + + /** DEATHSQUAD ***/ + if (istype(current, /mob/living/carbon)) + text = "Death Squad" + text = "[text]: " + if (src in ticker.mode.deathsquad) + text += "YES|no" + else + text += "yes|NO" + sections["dsquad"] = text + + out += {"
      + Strike Teams:
      + [sections["resteam"]]
      + [sections["dsquad"]]
      +
      "} + + out += {"
      + Memory: +
      [memory] +
      Edit memory +
      Objectives:
      "} + + if (objectives.len == 0) + out += "EMPTY
      " + else + var/obj_count = 1 + for(var/datum/objective/objective in objectives) + out += "[obj_count]: [objective.explanation_text] Edit Delete Toggle Completion
      " + obj_count++ + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\datums\\mind.dm:338: out += "Add objective

      " + out += {"Add objective

      + Announce objectives

      "} + // END AUTOFIX + usr << browse(out, "window=edit_memory[src]") + +/datum/mind/Topic(href, href_list) + if(!check_rights(R_ADMIN)) return + + if (href_list["role_edit"]) + var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs() + if (!new_role) return + assigned_role = new_role + + else if (href_list["memory_edit"]) + var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN) + if (isnull(new_memo)) return + memory = new_memo + + else if (href_list["obj_edit"] || href_list["obj_add"]) + var/datum/objective/objective + var/objective_pos + var/def_value + + if (href_list["obj_edit"]) + objective = locate(href_list["obj_edit"]) + if (!objective) return + objective_pos = objectives.Find(objective) + + //Text strings are easy to manipulate. Revised for simplicity. + var/temp_obj_type = "[objective.type]"//Convert path into a text string. + def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword. + if(!def_value)//If it's a custom objective, it will be an empty string. + def_value = "custom" + + var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "blood", "debrain", "protect", "prevent", "harm", "brig", "hijack", "escape", "survive", "steal", "download", "nuclear", "capture", "absorb", "custom") + if (!new_obj_type) return + + var/datum/objective/new_objective = null + + switch (new_obj_type) + if ("assassinate","protect","debrain", "harm", "brig") + //To determine what to name the objective in explanation text. + var/objective_type_capital = uppertext(copytext(new_obj_type, 1,2))//Capitalize first letter. + var/objective_type_text = copytext(new_obj_type, 2)//Leave the rest of the text. + var/objective_type = "[objective_type_capital][objective_type_text]"//Add them together into a text string. + + var/list/possible_targets = list("Free objective") + for(var/datum/mind/possible_target in ticker.minds) + if ((possible_target != src) && istype(possible_target.current, /mob/living/carbon/human)) + possible_targets += possible_target.current + + var/mob/def_target = null + var/objective_list[] = list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain) + if (objective&&(objective.type in objective_list) && objective:target) + def_target = objective:target.current + + var/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets + if (!new_target) return + + var/objective_path = text2path("/datum/objective/[new_obj_type]") + if (new_target == "Free objective") + new_objective = new objective_path + new_objective.owner = src + new_objective:target = null + new_objective.explanation_text = "Free objective" + else + new_objective = new objective_path + new_objective.owner = src + new_objective:target = new_target:mind + //Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops. + new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]." + + if ("prevent") + new_objective = new /datum/objective/block + new_objective.owner = src + + if ("hijack") + new_objective = new /datum/objective/hijack + new_objective.owner = src + + if ("escape") + new_objective = new /datum/objective/escape + new_objective.owner = src + + if ("survive") + new_objective = new /datum/objective/survive + new_objective.owner = src + + if ("die") + new_objective = new /datum/objective/die + new_objective.owner = src + + if ("nuclear") + new_objective = new /datum/objective/nuclear + new_objective.owner = src + + if ("steal") + if (!istype(objective, /datum/objective/steal)) + new_objective = new /datum/objective/steal + new_objective.owner = src + else + new_objective = objective + var/datum/objective/steal/steal = new_objective + if (!steal.select_target()) + return + + if("download","capture","absorb", "blood") + var/def_num + if(objective&&objective.type==text2path("/datum/objective/[new_obj_type]")) + def_num = objective.target_amount + + var/target_number = input("Input target number:", "Objective", def_num) as num|null + if (isnull(target_number))//Ordinarily, you wouldn't need isnull. In this case, the value may already exist. + return + + switch(new_obj_type) + if("capture") + new_objective = new /datum/objective/capture + new_objective.explanation_text = "Accumulate [target_number] capture points." + if("absorb") + new_objective = new /datum/objective/absorb + new_objective.explanation_text = "Absorb [target_number] compatible genomes." + if("blood") + new_objective = new /datum/objective/blood + new_objective.explanation_text = "Accumulate atleast [target_number] units of blood in total." + new_objective.owner = src + new_objective.target_amount = target_number + + if ("custom") + var/expl = copytext(sanitize(input("Custom objective:", "Objective", objective ? objective.explanation_text : "") as text|null),1,MAX_MESSAGE_LEN) + if (!expl) return + new_objective = new /datum/objective + new_objective.owner = src + new_objective.explanation_text = expl + + if (!new_objective) return + + if (objective) + objectives -= objective + objectives.Insert(objective_pos, new_objective) + log_admin("[usr.key]/([usr.name]) changed [key]/([name])'s objective from [objective.explanation_text] to [new_objective.explanation_text]") + else + objectives += new_objective + log_admin("[usr.key]/([usr.name]) gave [key]/([name]) the objective: [new_objective.explanation_text]") + + else if (href_list["obj_delete"]) + var/datum/objective/objective = locate(href_list["obj_delete"]) + if(!istype(objective)) return + objectives -= objective + log_admin("[usr.key]/([usr.name]) removed [key]/([name])'s objective ([objective.explanation_text])") + + else if(href_list["obj_completed"]) + var/datum/objective/objective = locate(href_list["obj_completed"]) + if(!istype(objective)) return + objective.completed = !objective.completed + log_admin("[usr.key]/([usr.name]) toggled [key]/([name]) [objective.explanation_text] to [objective.completed ? "completed" : "incomplete"]") + + else if (href_list["revolution"]) + switch(href_list["revolution"]) + if("clear") + if(src in ticker.mode.revolutionaries) + ticker.mode.revolutionaries -= src + to_chat(current, "You have been brainwashed! You are no longer a revolutionary!") + ticker.mode.update_rev_icons_removed(src) + special_role = null + if(src in ticker.mode.head_revolutionaries) + ticker.mode.head_revolutionaries -= src + to_chat(current, "You have been brainwashed! You are no longer a head revolutionary!") + ticker.mode.update_rev_icons_removed(src) + special_role = null + log_admin("[key_name_admin(usr)] has de-rev'ed [current].") + + if("rev") + if(src in ticker.mode.head_revolutionaries) + ticker.mode.head_revolutionaries -= src + ticker.mode.update_rev_icons_removed(src) + to_chat(current, "Revolution has been disappointed of your leader traits! You are a regular revolutionary now!") + else if(!(src in ticker.mode.revolutionaries)) + to_chat(current, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") + else + return + ticker.mode.revolutionaries += src + ticker.mode.update_rev_icons_added(src) + special_role = "Revolutionary" + log_admin("[key_name(usr)] has rev'ed [current].") + + if("headrev") + if(src in ticker.mode.revolutionaries) + ticker.mode.revolutionaries -= src + ticker.mode.update_rev_icons_removed(src) + to_chat(current, "You have proved your devotion to revoltion! Yea are a head revolutionary now!") + else if(!(src in ticker.mode.head_revolutionaries)) + to_chat(current, "You are a member of the revolutionaries' leadership now!") + else + return + if (ticker.mode.head_revolutionaries.len>0) + // copy targets + var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries + if (valid_head) + for (var/datum/objective/mutiny/O in valid_head.objectives) + var/datum/objective/mutiny/rev_obj = new + rev_obj.owner = src + rev_obj.target = O.target + rev_obj.explanation_text = "Assassinate [O.target.name], the [O.target.assigned_role]." + objectives += rev_obj + ticker.mode.greet_revolutionary(src,0) + ticker.mode.head_revolutionaries += src + ticker.mode.update_rev_icons_added(src) + special_role = "Head Revolutionary" + log_admin("[key_name_admin(usr)] has head-rev'ed [current].") + + if("autoobjectives") + ticker.mode.forge_revolutionary_objectives(src) + ticker.mode.greet_revolutionary(src,0) + to_chat(usr, "The objectives for revolution have been generated and shown to [key]") + + if("flash") + if (!ticker.mode.equip_revolutionary(current)) + to_chat(usr, "Spawning flash failed!") + + if("takeflash") + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (!flash) + to_chat(usr, "Deleting flash failed!") + qdel(flash) + + if("repairflash") + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (!flash) + to_chat(usr, "Repairing flash failed!") + else + flash.broken = 0 + + if("reequip") + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + qdel(flash) + take_uplink() + var/fail = 0 + fail |= !ticker.mode.equip_traitor(current, 1) + fail |= !ticker.mode.equip_revolutionary(current) + if (fail) + to_chat(usr, "Reequipping revolutionary goes wrong!") + + else if (href_list["cult"]) + switch(href_list["cult"]) + if("clear") + if(src in ticker.mode.cult) + ticker.mode.cult -= src + ticker.mode.update_cult_icons_removed(src) + special_role = null + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + cult.memoize_cult_objectives(src) + to_chat(current, "You have been brainwashed! You are no longer a cultist!") + to_chat(current, "You find yourself unable to mouth the words of the forgotten...") + current.remove_language("Cult") + memory = "" + log_admin("[key_name_admin(usr)] has de-cult'ed [current].") + if("cultist") + if(!(src in ticker.mode.cult)) + ticker.mode.cult += src + ticker.mode.update_cult_icons_added(src) + special_role = "Cultist" + to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie.") + to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") + to_chat(current, "You can now speak and understand the forgotten tongue of the occult.") + current.add_language("Cult") + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + cult.memoize_cult_objectives(src) + log_admin("[key_name_admin(usr)] has cult'ed [current].") + if("tome") + var/mob/living/carbon/human/H = current + if (istype(H)) + var/obj/item/weapon/tome/T = new(H) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + var/where = H.equip_in_one_of_slots(T, slots) + if (!where) + to_chat(usr, "Spawning tome failed!") + else + to_chat(H, "A tome, a message from your new master, appears in your [where].") + + if("amulet") + if (!ticker.mode.equip_cultist(current)) + to_chat(usr, "Spawning amulet failed!") + + else if (href_list["wizard"]) + switch(href_list["wizard"]) + if("clear") + if(src in ticker.mode.wizards) + ticker.mode.wizards -= src + special_role = null + current.spellremove(current, config.feature_object_spell_system? "object":"verb") + to_chat(current, "You have been brainwashed! You are no longer a wizard!") + ticker.mode.update_wizard_icons_removed(src) + log_admin("[key_name_admin(usr)] has de-wizard'ed [current].") + if("wizard") + if(!(src in ticker.mode.wizards)) + ticker.mode.wizards += src + special_role = "Wizard" + //ticker.mode.learn_basic_spells(current) + to_chat(current, "You are the Space Wizard!") + ticker.mode.update_wizard_icons_added(src) + log_admin("[key_name_admin(usr)] has wizard'ed [current].") + if("lair") + current.loc = pick(wizardstart) + if("dressup") + ticker.mode.equip_wizard(current) + if("name") + ticker.mode.name_wizard(current) + if("autoobjectives") + ticker.mode.forge_wizard_objectives(src) + to_chat(usr, "The objectives for wizard [key] have been generated. You can edit them and anounce manually.") + ticker.mode.update_all_wizard_icons() + + else if (href_list["changeling"]) + switch(href_list["changeling"]) + if("clear") + if(src in ticker.mode.changelings) + ticker.mode.changelings -= src + special_role = null + current.remove_changeling_powers() + current.verbs -= /datum/changeling/proc/EvolutionMenu + if(changeling) + qdel(changeling) + changeling = null + to_chat(current, "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!") + log_admin("[key_name_admin(usr)] has de-changeling'ed [current].") + if("changeling") + if(!(src in ticker.mode.changelings)) + ticker.mode.changelings += src + ticker.mode.grant_changeling_powers(current) + special_role = "Changeling" + to_chat(current, "Your powers are awoken. A flash of memory returns to us...we are a changeling!") + log_admin("[key_name_admin(usr)] has changeling'ed [current].") + if("autoobjectives") + ticker.mode.forge_changeling_objectives(src) + to_chat(usr, "The objectives for changeling [key] have been generated. You can edit them and anounce manually.") + + if("initialdna") + if( !changeling || !changeling.absorbed_dna.len ) + to_chat(usr, "Resetting DNA failed!") + else + current.dna = changeling.absorbed_dna[1] + current.real_name = current.dna.real_name + current.UpdateAppearance() + domutcheck(current, null) + + if("set_genomes") + if( !changeling ) + to_chat(usr, "No changeling!") + return + var/new_g = input(usr,"Number of genomes","Changeling",changeling.geneticpoints) as num + changeling.geneticpoints = Clamp(new_g, 0, 100) + log_admin("[key_name_admin(usr)] has set changeling [current] to [changeling.geneticpoints] genomes.") + + else if (href_list["vampire"]) + switch(href_list["vampire"]) + if("clear") + if(src in ticker.mode.vampires) + ticker.mode.vampires -= src + special_role = null + current.remove_vampire_powers() + if(vampire) + qdel(vampire) + vampire = null + to_chat(current, "You grow weak and lose your powers! You are no longer a vampire and are stuck in your current form!") + log_admin("[key_name_admin(usr)] has de-vampired [current].") + if("vampire") + if(!(src in ticker.mode.vampires)) + ticker.mode.vampires += src + ticker.mode.grant_vampire_powers(current) + special_role = "Vampire" + to_chat(current, "Your powers are awoken. Your lust for blood grows... You are a Vampire!") + log_admin("[key_name_admin(usr)] has vampired [current].") + if("autoobjectives") + ticker.mode.forge_vampire_objectives(src) + to_chat(usr, "The objectives for vampire [key] have been generated. You can edit them and announce manually.") + + else if (href_list["nuclear"]) + switch(href_list["nuclear"]) + if("clear") + if(src in ticker.mode.syndicates) + ticker.mode.syndicates -= src + ticker.mode.update_synd_icons_removed(src) + special_role = null + for (var/datum/objective/nuclear/O in objectives) + objectives-=O + to_chat(current, "You have been brainwashed! You are no longer a syndicate operative!") + log_admin("[key_name_admin(usr)] has de-nuke op'ed [current].") + if("nuclear") + if(!(src in ticker.mode.syndicates)) + ticker.mode.syndicates += src + ticker.mode.update_synd_icons_added(src) + if (ticker.mode.syndicates.len==1) + ticker.mode.prepare_syndicate_leader(src) + else + current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" + special_role = "Syndicate" + to_chat(current, "You are a [syndicate_name()] agent!") + ticker.mode.forge_syndicate_objectives(src) + ticker.mode.greet_syndicate(src) + log_admin("[key_name_admin(usr)] has nuke op'ed [current].") + if("lair") + current.loc = get_turf(locate("landmark*Syndicate-Spawn")) + if("dressup") + var/mob/living/carbon/human/H = current + qdel(H.belt) + qdel(H.back) + qdel(H.ears) + qdel(H.gloves) + qdel(H.head) + qdel(H.shoes) + qdel(H.wear_id) + qdel(H.wear_suit) + qdel(H.w_uniform) + + if (!ticker.mode.equip_syndicate(current)) + to_chat(usr, "Equipping a syndicate failed!") + if("tellcode") + var/code + for (var/obj/machinery/nuclearbomb/bombue in machines) + if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") + code = bombue.r_code + break + if (code) + store_memory("Syndicate Nuclear Bomb Code: [code]", 0, 0) + to_chat(current, "The nuclear authorization code is: [code]") + else + to_chat(usr, "No valid nuke found!") + + else if (href_list["traitor"]) + switch(href_list["traitor"]) + if ("clear") + if(src in ticker.mode.traitors) + ticker.mode.traitors -= src + special_role = null + to_chat(current, "You have been brainwashed! You are no longer a traitor!") + log_admin("[key_name_admin(usr)] has de-traitor'ed [current].") + if(isAI(current)) + var/mob/living/silicon/ai/A = current + A.set_zeroth_law("") + A.show_laws() + if ("traitor") + if (make_traitor()) + log_admin("[key_name(usr)] has traitor'ed [key_name(current)].") + if ("autoobjectives") + ticker.mode.forge_traitor_objectives(src) + to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and anounce manually.") + + else if (href_list["monkey"]) + var/mob/living/L = current + if (L.monkeyizing) + return + switch(href_list["monkey"]) + if("healthy") + if (usr.client.holder.rights & R_ADMIN) + var/mob/living/carbon/human/H = current + var/mob/living/carbon/monkey/M = current + if (istype(H)) + log_admin("[key_name(usr)] attempting to monkeyize [key_name(current)]") + message_admins("[key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") + src = null + M = H.monkeyize() + src = M.mind +// to_chat(world, "DEBUG: \"healthy\": M=[M], M.mind=[M.mind], src=[src]!") + else if (istype(M) && length(M.viruses)) + for(var/datum/disease/D in M.viruses) + D.cure(0) + sleep(0) //because deleting of virus is done through spawn(0) + if("infected") + if (usr.client.holder.rights & R_ADMIN) + var/mob/living/carbon/human/H = current + var/mob/living/carbon/monkey/M = current + if (istype(H)) + log_admin("[key_name(usr)] attempting to monkeyize and infect [key_name(current)]") + message_admins("[key_name_admin(usr)] attempting to monkeyize and infect [key_name_admin(current)]", 1) + src = null + M = H.monkeyize() + src = M.mind + current.contract_disease(new /datum/disease/jungle_fever,1,0) + else if (istype(M)) + current.contract_disease(new /datum/disease/jungle_fever,1,0) + if("human") + var/mob/living/carbon/monkey/M = current + if (istype(M)) + for(var/datum/disease/D in M.viruses) + if (istype(D,/datum/disease/jungle_fever)) + D.cure(0) + sleep(0) //because deleting of virus is doing throught spawn(0) + log_admin("[key_name(usr)] attempting to humanize [key_name(current)]") + message_admins("[key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") + var/obj/item/weapon/dnainjector/nofail/m2h/m2h = new + var/obj/item/weapon/implant/mobfinder = new(M) //hack because humanizing deletes mind --rastaf0 + src = null + m2h.inject(M) + src = mobfinder.loc:mind + qdel(mobfinder) + mobfinder = null + current.radiation -= 50 + + else if (href_list["silicon"]) + switch(href_list["silicon"]) + if("unmalf") + if(src in ticker.mode.malf_ai) + ticker.mode.malf_ai -= src + special_role = null + var/mob/living/silicon/ai/A = current + + A.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules, + /datum/game_mode/malfunction/proc/takeover, + /datum/game_mode/malfunction/proc/ai_win) + + A.malf_picker.remove_verbs(A) + + + A.laws = new base_law_type + qdel(A.malf_picker) + A.malf_picker = null + A.show_laws() + A.icon_state = "ai" + + to_chat(A, "You have been patched! You are no longer malfunctioning!") + message_admins("[key_name_admin(usr)] has de-malf'ed [A].") + log_admin("[key_name_admin(usr)] has de-malf'ed [A].") + + if("malf") + make_AI_Malf() + log_admin("[key_name_admin(usr)] has malf'ed [current].") + + if("unemag") + if(istype(current,/mob/living/silicon/robot/mommi)) + var/mob/living/silicon/robot/mommi/R = current + R.emagged = 0 + if (R.activated(R.module.emag)) + R.module_active = null + if(R.tool_state == R.module.emag) + R.tool_state = null + R.contents -= R.module.emag + log_admin("[key_name_admin(usr)] has unemag'ed [R].") + else + if (istype(current,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = current + R.emagged = 0 + if (R.activated(R.module.emag)) + R.module_active = null + if(R.module_state_1 == R.module.emag) + R.module_state_1 = null + R.contents -= R.module.emag + else if(R.module_state_2 == R.module.emag) + R.module_state_2 = null + R.contents -= R.module.emag + else if(R.module_state_3 == R.module.emag) + R.module_state_3 = null + R.contents -= R.module.emag + log_admin("[key_name_admin(usr)] has unemag'ed [R].") + + if("unemagcyborgs") + if (istype(current, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/ai = current + for (var/mob/living/silicon/robot/R in ai.connected_robots) + R.emagged = 0 + if(istype(R,/mob/living/silicon/robot/mommi)) + var/mob/living/silicon/robot/mommi/M=R + if (M.activated(M.module.emag)) + M.module_active = null + if(M.tool_state == M.module.emag) + M.tool_state = null + M.contents -= M.module.emag + if (R.module) + if (R.activated(R.module.emag)) + R.module_active = null + if(R.module_state_1 == R.module.emag) + R.module_state_1 = null + R.contents -= R.module.emag + else if(R.module_state_2 == R.module.emag) + R.module_state_2 = null + R.contents -= R.module.emag + else if(R.module_state_3 == R.module.emag) + R.module_state_3 = null + R.contents -= R.module.emag + log_admin("[key_name_admin(usr)] has unemag'ed [ai]'s Cyborgs.") + + else if (href_list["common"]) + switch(href_list["common"]) + if("undress") + for(var/obj/item/W in current) + current.drop_from_inventory(W) + if("takeuplink") + take_uplink() + memory = null//Remove any memory they may have had. + if("crystals") + if (usr.client.holder.rights & R_FUN) + var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() + var/crystals + if (suplink) + crystals = suplink.uses + crystals = input("Amount of telecrystals for [key]","Syndicate uplink", crystals) as null|num + if (!isnull(crystals)) + if (suplink) + var/diff = crystals - suplink.uses + suplink.uses = crystals + total_TC += diff + if("uplink") + if (!ticker.mode.equip_traitor(current, !(src in ticker.mode.traitors))) + to_chat(usr, "Equipping a syndicate failed!") + + else if (href_list["obj_announce"]) + var/obj_count = 1 + to_chat(current, "Your current objectives:") + for(var/datum/objective/objective in objectives) + to_chat(current, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ + + else if (href_list["resteam"]) + switch(href_list["resteam"]) + if ("clear") + if(src in ticker.mode.ert) + ticker.mode.ert -= src + special_role = null + to_chat(current, "You have been demoted! You are no longer an Emergency Responder!") + log_admin("[key_name_admin(usr)] has de-ERT'ed [current].") + if ("resteam") + if (!(src in ticker.mode.ert)) + ticker.mode.ert += src + assigned_role = "MODE" + special_role = "Response Team" + log_admin("[key_name(usr)] has ERT'ed [key_name(current)].") + + else if (href_list["dsquad"]) + switch(href_list["dsquad"]) + if ("clear") + if(src in ticker.mode.deathsquad) + ticker.mode.deathsquad -= src + special_role = null + to_chat(current, "You have been demoted! You are no longer a Death Commando!") + log_admin("[key_name_admin(usr)] has de-deathsquad'ed [current].") + if ("dsquad") + if (!(src in ticker.mode.deathsquad)) + ticker.mode.deathsquad += src + assigned_role = "MODE" + special_role = "Death Commando" + log_admin("[key_name(usr)] has deathsquad'ed [key_name(current)].") + + + edit_memory() +/* +proc/clear_memory(var/silent = 1) + var/datum/game_mode/current_mode = ticker.mode + + // remove traitor uplinks + var/list/L = current.get_contents() + for (var/t in L) + if (istype(t, /obj/item/device/pda)) + var/obj/item/device/pda/P = t + if (P.uplink) del(P.uplink) + P.uplink = null + else if (istype(t, /obj/item/device/radio)) + var/obj/item/device/radio/R = t + if (R.traitorradio) del(R.traitorradio) + R.traitorradio = null + R.traitor_frequency = 0.0 + else if (istype(t, /obj/item/weapon/SWF_uplink) || istype(t, /obj/item/weapon/syndicate_uplink)) + var/obj/item/weapon/W = t + if (W.origradio) + var/obj/item/device/radio/R = t:origradio + R.loc = current.loc + R.traitorradio = null + R.traitor_frequency = 0.0 + del(W) + + // remove wizards spells + //If there are more special powers that need removal, they can be procced into here./N + current.spellremove(current) + + // clear memory + memory = "" + special_role = null + +*/ + +/datum/mind/proc/find_syndicate_uplink() + var/uplink = null + + for (var/obj/item/I in get_contents_in_object(current, /obj/item)) + if (I && I.hidden_uplink) + uplink = I.hidden_uplink + break + + return uplink + +/datum/mind/proc/take_uplink() + var/obj/item/device/uplink/hidden/H = find_syndicate_uplink() + if(H) + qdel(H) + + +/datum/mind/proc/make_AI_Malf() + if(!isAI(current)) + return + if(!(src in ticker.mode.malf_ai)) + ticker.mode.malf_ai += src + var/mob/living/silicon/ai/A = current + A.verbs += /mob/living/silicon/ai/proc/choose_modules + A.verbs += /datum/game_mode/malfunction/proc/takeover + A.malf_picker = new /datum/module_picker + var/datum/ai_laws/laws = A.laws + laws.malfunction() + A.show_laws() + to_chat(A, "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first...") + special_role = "malfunction" + A.icon_state = "ai-malf" + +/datum/mind/proc/make_Nuke() + if(!(src in ticker.mode.syndicates)) + ticker.mode.syndicates += src + ticker.mode.update_synd_icons_added(src) + if (ticker.mode.syndicates.len==1) + ticker.mode.prepare_syndicate_leader(src) + else + current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" + special_role = "Syndicate" + assigned_role = "MODE" + to_chat(current, "You are a [syndicate_name()] agent!") + ticker.mode.forge_syndicate_objectives(src) + ticker.mode.greet_syndicate(src) + + current.loc = get_turf(locate("landmark*Syndicate-Spawn")) + + var/mob/living/carbon/human/H = current + qdel(H.belt) + qdel(H.back) + qdel(H.ears) + qdel(H.gloves) + qdel(H.head) + qdel(H.shoes) + qdel(H.wear_id) + qdel(H.wear_suit) + qdel(H.w_uniform) + + ticker.mode.equip_syndicate(current) + +/datum/mind/proc/make_Changling() + if(!(src in ticker.mode.changelings)) + ticker.mode.changelings += src + ticker.mode.grant_changeling_powers(current) + special_role = "Changeling" + ticker.mode.forge_changeling_objectives(src) + ticker.mode.greet_changeling(src) + +/datum/mind/proc/make_Wizard() + if(!(src in ticker.mode.wizards)) + ticker.mode.wizards += src + special_role = "Wizard" + assigned_role = "MODE" + //ticker.mode.learn_basic_spells(current) + ticker.mode.update_wizard_icons_added(src) + if(!wizardstart.len) + current.loc = pick(latejoin) + to_chat(current, "HOT INSERTION, GO GO GO") + else + current.loc = pick(wizardstart) + + ticker.mode.equip_wizard(current) + for(var/obj/item/weapon/spellbook/S in current.contents) + S.op = 0 + ticker.mode.name_wizard(current) + ticker.mode.forge_wizard_objectives(src) + ticker.mode.greet_wizard(src) + ticker.mode.update_all_wizard_icons() + + +/datum/mind/proc/make_Cultist() + if(!(src in ticker.mode.cult)) + ticker.mode.cult += src + ticker.mode.update_cult_icons_added(src) + special_role = "Cultist" + to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie.") + to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") + to_chat(current, "You can now speak and understand the forgotten tongue of the occult.") + current.add_language("Cult") + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + cult.memoize_cult_objectives(src) + else + var/explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." + to_chat(current, "Objective #1: [explanation]") + current.memory += "Objective #1: [explanation]
      " + to_chat(current, "The convert rune is join blood self") + current.memory += "The convert rune is join blood self
      " + + var/mob/living/carbon/human/H = current + if (istype(H)) + var/obj/item/weapon/tome/T = new(H) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + var/where = H.equip_in_one_of_slots(T, slots) + if (!where) + else + to_chat(H, "A tome, a message from your new master, appears in your [where].") + + if (!ticker.mode.equip_cultist(current)) + to_chat(H, "Spawning an amulet from your Master failed.") + +/datum/mind/proc/make_Rev() + if (ticker.mode.head_revolutionaries.len>0) + // copy targets + var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries + if (valid_head) + for (var/datum/objective/mutiny/O in valid_head.objectives) + var/datum/objective/mutiny/rev_obj = new + rev_obj.owner = src + rev_obj.target = O.target + rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]." + objectives += rev_obj + ticker.mode.greet_revolutionary(src,0) + ticker.mode.head_revolutionaries += src + ticker.mode.update_rev_icons_added(src) + special_role = "Head Revolutionary" + + ticker.mode.forge_revolutionary_objectives(src) + ticker.mode.greet_revolutionary(src,0) + + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + qdel(flash) + take_uplink() + var/fail = 0 +// fail |= !ticker.mode.equip_traitor(current, 1) + fail |= !ticker.mode.equip_revolutionary(current) + + +// check whether this mind's mob has been brigged for the given duration +// have to call this periodically for the duration to work properly +/datum/mind/proc/is_brigged(duration) + var/turf/T = current.loc + if(!istype(T)) + brigged_since = -1 + return 0 + + var/is_currently_brigged = 0 + + if(istype(T.loc,/area/security/brig)) + is_currently_brigged = 1 + for(var/obj/item/weapon/card/id/card in current) + is_currently_brigged = 0 + break // if they still have ID they're not brigged + for(var/obj/item/device/pda/P in current) + if(P.id) + is_currently_brigged = 0 + break // if they still have ID they're not brigged + + if(!is_currently_brigged) + brigged_since = -1 + return 0 + + if(brigged_since == -1) + brigged_since = world.time + + return (duration <= world.time - brigged_since) + +/datum/mind/proc/make_traitor() + if (!(src in ticker.mode.traitors)) + ticker.mode.traitors += src + + special_role = "traitor" + + ticker.mode.forge_traitor_objectives(src) + + to_chat(current, {" + ATTENTION + It's time to pay your debt to \the [syndicate_name()]. + "}) + + ticker.mode.finalize_traitor(src) + + ticker.mode.greet_traitor(src) + + return TRUE + + return FALSE + +//Initialisation procs +/mob/proc/mind_initialize() // vgedit: /mob instead of /mob/living + if(mind) + mind.key = key + else + mind = new /datum/mind(key) + mind.original = src + if(ticker) + ticker.minds += mind + else + world.log << "## DEBUG: mind_initialize(): No ticker ready yet! Please inform Carn" + if(!mind.name) mind.name = real_name + mind.current = src + +//HUMAN +/mob/living/carbon/human/mind_initialize() + ..() + if(!mind.assigned_role) mind.assigned_role = "Assistant" //defualt + +//MONKEY +/mob/living/carbon/monkey/mind_initialize() + ..() + +//slime +/mob/living/carbon/slime/mind_initialize() + ..() + mind.assigned_role = "slime" + +//XENO +/mob/living/carbon/alien/mind_initialize() + ..() + mind.assigned_role = "Alien" + //XENO HUMANOID +/mob/living/carbon/alien/humanoid/queen/mind_initialize() + ..() + mind.special_role = "Queen" + +/mob/living/carbon/alien/humanoid/hunter/mind_initialize() + ..() + mind.special_role = "Hunter" + +/mob/living/carbon/alien/humanoid/drone/mind_initialize() + ..() + mind.special_role = "Drone" + +/mob/living/carbon/alien/humanoid/sentinel/mind_initialize() + ..() + mind.special_role = "Sentinel" + //XENO LARVA +/mob/living/carbon/alien/larva/mind_initialize() + ..() + mind.special_role = "Larva" + +//AI +/mob/living/silicon/ai/mind_initialize() + ..() + mind.assigned_role = "AI" + +//BORG +/mob/living/silicon/robot/mind_initialize() + ..() + mind.assigned_role = "[isMoMMI(src) ? "Mobile MMI" : "Cyborg"]" + +//PAI +/mob/living/silicon/pai/mind_initialize() + ..() + mind.assigned_role = "pAI" + mind.special_role = "" + +//BLOB +/mob/camera/overmind/mind_initialize() + ..() + mind.special_role = "Blob" + +//Animals +/mob/living/simple_animal/mind_initialize() + ..() + mind.assigned_role = "Animal" + +/mob/living/simple_animal/corgi/mind_initialize() + ..() + mind.assigned_role = "Corgi" + +/mob/living/simple_animal/shade/mind_initialize() + ..() + mind.assigned_role = "Shade" + +/mob/living/simple_animal/construct/builder/mind_initialize() + ..() + mind.assigned_role = "Artificer" + mind.special_role = "Cultist" + +/mob/living/simple_animal/construct/wraith/mind_initialize() + ..() + mind.assigned_role = "Wraith" + mind.special_role = "Cultist" + +/mob/living/simple_animal/construct/armoured/mind_initialize() + ..() + mind.assigned_role = "Juggernaut" + mind.special_role = "Cultist" + +/mob/living/simple_animal/vox/armalis/mind_initialize() + ..() + mind.assigned_role = "Armalis" + mind.special_role = "Vox Raider" + + +/proc/mind_can_reenter(var/datum/mind/mind) + if(mind) + for(var/mob/dead/observer/G in player_list) + if(G.can_reenter_corpse && G.mind == mind) + return TRUE + return FALSE diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm index 48d5cc9c4b6..ba660c6af0d 100644 --- a/code/datums/mixed.dm +++ b/code/datums/mixed.dm @@ -1,31 +1,31 @@ -/datum/data - var/name = "data" - var/size = 1.0 - - -/datum/data/function - name = "function" - size = 2.0 - - -/datum/data/function/data_control - name = "data control" - - -/datum/data/function/id_changer - name = "id changer" - - -/datum/data/record - name = "record" - size = 5.0 - var/list/fields = list( ) - - -/datum/data/text - name = "text" - var/data = null - - -/datum/debug - var/list/debuglist +/datum/data + var/name = "data" + var/size = 1.0 + + +/datum/data/function + name = "function" + size = 2.0 + + +/datum/data/function/data_control + name = "data control" + + +/datum/data/function/id_changer + name = "id changer" + + +/datum/data/record + name = "record" + size = 5.0 + var/list/fields = list( ) + + +/datum/data/text + name = "text" + var/data = null + + +/datum/debug + var/list/debuglist diff --git a/code/datums/modules.dm b/code/datums/modules.dm index 67de6d7a15d..7c05b5d190a 100644 --- a/code/datums/modules.dm +++ b/code/datums/modules.dm @@ -1,61 +1,61 @@ -// module datum. -// this is per-object instance, and shows the condition of the modules in the object -// actual modules needed is referenced through modulestypes and the object type - -/datum/module - var/status // bits set if working, 0 if broken - var/installed // bits set if installed, 0 if missing - -// moduletypes datum -// this is per-object type, and shows the modules needed for a type of object - -/datum/moduletypes - var/list/modcount = list() // assoc list of the count of modules for a type - - -var/list/modules = list( // global associative list -"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge") - - -/datum/module/New(var/obj/O) - - var/type = O.type // the type of the creating object - - var/mneed = mods.inmodlist(type) // find if this type has modules defined - - if(!mneed) // not found in module list? - qdel(src) // used to delete self, thus ending proc - return - - var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object - status = needed - installed = needed - -/datum/moduletypes/proc/addmod(var/type, var/modtextlist) - modules += type // index by type text - modules[type] = modtextlist - -/datum/moduletypes/proc/inmodlist(var/type) - return ("[type]" in modules) - -/datum/moduletypes/proc/getbitmask(var/type) - var/count = modcount["[type]"] - if(count) - return 2**count-1 - - var/modtext = modules["[type]"] - var/num = 1 - var/pos = 1 - - while(1) - pos = findtext(modtext, ",", pos, 0) - if(!pos) - break - else - pos++ - num++ - - modcount += "[type]" - modcount["[type]"] = num - - return 2**num-1 +// module datum. +// this is per-object instance, and shows the condition of the modules in the object +// actual modules needed is referenced through modulestypes and the object type + +/datum/module + var/status // bits set if working, 0 if broken + var/installed // bits set if installed, 0 if missing + +// moduletypes datum +// this is per-object type, and shows the modules needed for a type of object + +/datum/moduletypes + var/list/modcount = list() // assoc list of the count of modules for a type + + +var/list/modules = list( // global associative list +"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge") + + +/datum/module/New(var/obj/O) + + var/type = O.type // the type of the creating object + + var/mneed = mods.inmodlist(type) // find if this type has modules defined + + if(!mneed) // not found in module list? + qdel(src) // used to delete self, thus ending proc + return + + var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object + status = needed + installed = needed + +/datum/moduletypes/proc/addmod(var/type, var/modtextlist) + modules += type // index by type text + modules[type] = modtextlist + +/datum/moduletypes/proc/inmodlist(var/type) + return ("[type]" in modules) + +/datum/moduletypes/proc/getbitmask(var/type) + var/count = modcount["[type]"] + if(count) + return 2**count-1 + + var/modtext = modules["[type]"] + var/num = 1 + var/pos = 1 + + while(1) + pos = findtext(modtext, ",", pos, 0) + if(!pos) + break + else + pos++ + num++ + + modcount += "[type]" + modcount["[type]"] = num + + return 2**num-1 diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index 684a383b506..b8ca85ece98 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -1,134 +1,134 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * - * /datum/recipe by rastaf0 13 apr 2011 * - * * * * * * * * * * * * * * * * * * * * * * * * * * - * This is powerful and flexible recipe system. - * It exists not only for food. - * supports both reagents and objects as prerequisites. - * In order to use this system you have to define a deriative from /datum/recipe - * * reagents are reagents. Acid, milc, booze, etc. - * * items are objects. Fruits, tools, circuit boards. - * * result is type to create as new object - * * time is optional parameter, you shall use in in your machine, - default /datum/recipe/ procs does not rely on this parameter. - * - * Functions you need: - * /datum/recipe/proc/make(var/obj/container as obj) - * Creates result inside container, - * deletes prerequisite reagents, - * transfers reagents from prerequisite objects, - * deletes all prerequisite objects (even not needed for recipe at the moment). - * - * /proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj as obj, exact = 1) - * Wonderful function that select suitable recipe for you. - * obj is a machine (or magik hat) with prerequisites, - * exact = 0 forces algorithm to ignore superfluous stuff. - * - * Functions you do not need to call directly but could: - * /datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) - * //1 = precisely, 0 = insufficiently, -1 = superfluous - * - * /datum/recipe/proc/check_items(var/obj/container as obj) - * //1 = precisely, 0=insufficiently, -1 = superfluous - * - * */ - -//The person who made this honestly thought that the average coder from the distant future of 2015 would understand any of this shit without a thorough and painful examination -//And this is exactly why any Chemistry-related system is impenetrable to anyone but the best coders, even things theorically as simple as this -//So as I decrypt this arcane coding technology, I'll add comments where I see it fit, so absolutely fucking everywhere -//I'll take my Nobel Prize with fries thank you -//And yes indeed I know it's a lot of comments, but if you're not here to understand how recipes work, why are you here ? -/datum/recipe - - var/list/reagents //List of reagents needed and their amount, reagents = list("berryjuice" = 5) - var/list/reagents_forbidden //List of reagents that will not be transfered to the cooked item under any circumstance, use smartly and sparringly. reagents_forbidden = list("toxin", "water") - var/list/items //List of items needed, items = list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) - var/result //Well gee, what we output, result = /obj/item/weapon/reagent_containers/food/snacks/donut/normal - var/time = 100 //In tenths of a second, this is how long it takes for the magic to happen. The machine producing the recipe handles this value, but the recipe defines it - -//First step, let's check the reagents in our recipe machine (generally a microwave) -//Since it's reagents, it's about time for Chemistry-Holder insanity -/datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) //1 = Precisely what we need, 0 = Not enough, -1 = More than needed - //Now, here comes the arcane magic. Before we even do anything, we estimate we have just what we need. Why ? Who knows - . = 1 - //Scan the reagents in our recipe machine thingie one by one for shit we need in our recipe (water, hotsauce, salt, etc...) - for(var/r_r in reagents) - //Get the amount of said reagent we'll need in our recipe and assign it to that variable - var/reagent_amount = avail_reagents.get_reagent_amount(r_r) - //And now, the fun begins. Let's put this in plain words because holy crap - if(!(abs(reagent_amount - reagents[r_r]) < 0.5)) //If the absolute value of the amount of our reagent minus the needed amount of reagents for the recipe is NOT under 0.5 (rounding sanity) - if(reagent_amount > reagents[r_r]) //Let's check if the amount of our reagent is above the needed amount - . = -1 //If so, then we can say that we have more of this reagent that needed - else //Else - return 0 //We don't have what we need, abort, ABORT - //Remember that this is a for loop, so we do this for every reagent listed in our recipe - //Now, that check was fun, but we need to check for reagents we have not included per se (things not used in our recipe) - if((reagents ? (reagents.len) : (0)) < avail_reagents.reagent_list.len) //Given we have reagents in our recipe, are there more reagents in our machine than reagents needed in our recipe ? - return -1 //We have more reagents than needed, period - //Otherwise, get that value we determined earlier and send it, nevermind that a variable would have worked since it cannot be null - return . //If we have too much reagent (in numerical amounts) but only the reagents we need, -1, otherwise 1 - -//We just had fun with reagents, now let's check for items, literally any item, that is in our recipe. Apples, wrenches, dildos -//You would imagine that this would take a few lines of simple code, but you don't grasp oldcoder logic -/datum/recipe/proc/check_items(var/obj/container as obj) //1 = Precisely what we need, 0 = Not enough, -1 = More than needed - if(!items) //If there's no items in our recipe - if(locate(/obj/) in container) //And there are items in our recipe machine currently - return -1 //That's too much, abort - else //Nothing in our recipe machine - return 1 //Just what we need, *ping - . = 1 //The arcane magic rises again - var/list/checklist = items.Copy() //We need items in our recipe, so let's copy every single item in our recipe into a checklist - //Time for a loop - for(var/obj/O in container) //Let's loop through all the objects in our recipe machine - var/found = 0 //For once we use an actual variable - for(var/type in checklist) //At every object we find, stop to take a look at our entire checklist - if(istype(O, type)) //Is that what we are looking for yet - checklist -= type //Good, strike it out of our checklist - found = 1 //WE FOUND IT MA - break //Break that loop, continue downwards - if(!found) //Did we not find the object in our recipe machine on the checklist ? - . = -1 //Something extra in our ingredients, notify the cops - //We start looping through the objects in the container again at this point, until we checked every single one of them - if(checklist.len) //Are there still items on our recipe checklist ? - return 0 //Something is missing, abort - return . //If we found extra items, return -1, otherwise return 1 - -//Food-related recipe production -//Note : Due to changes to no longer wipe nutriments from cooked items, this is the same as make. So from now on this is THE "turn recipe into new thing" proc -/datum/recipe/proc/make_food(var/obj/container as obj) //Find our recipe machine and let's begin - var/obj/result_obj = new result(container) //Spawn the result of our little cuisine in the recipe machine in advance to transfer reagents - for(var/obj/O in (container.contents - result_obj)) //Find all objects (for instance, raw food or beakers) in our machine, excluding the result we just created - if(O.reagents) //Little sanity, can't hurt - for(var/r_r in reagents_forbidden) //Check forbidden reagents - O.reagents.del_reagent("[r_r]") //If we find any, remove - O.reagents.update_total() //Make sure we're set - O.reagents.trans_to(result_obj, O.reagents.total_volume) //If we have reagents in here, squeeze them into the end product - qdel(O) //Delete the object, he has outlived his usefulness - container.reagents.clear_reagents() //Clear all the reagents we haven't transfered, for instance if we need to cook in water - score["meals"]++ //Yes, it's a weird placement, but it's sure to work correctly as long as make_food() is used for food - return result_obj //Here we go, your result sire - -//Find what to do with all this shit in the microwave dynamically, without blowing up the station -//We consider all recipes in the game, obj (typecast as obj and estimated as obj because fuck you) and wherever or not its ingredients are exact based on what we learned from the last two procs -/proc/select_recipe(var/list/datum/recipe/avaiable_recipes, var/obj/obj as obj, var/exact = 1 as num) - if(!exact) //Is the recipe not exact (1) - exact = -1 //Change it to -1 for simplicity, too much or not enough is the same problem now - var/list/datum/recipe/possible_recipes = new //Create a list, hopefully not ending the universe in the process - for(var/datum/recipe/recipe in avaiable_recipes) //Loop through the ingame recipes - if(recipe.check_reagents(obj.reagents) == exact && recipe.check_items(obj) == exact) //What did we return for reagents and objects ingredient checks, and does it fit with our recipe ? - possible_recipes += recipe //Perfect, we can make this recipe with our current ingredients, add it - if(possible_recipes.len == 0) //We're done looping through the ingame recipes, did we find nothing ? - return null //Game over - else if(possible_recipes.len == 1) //Do we have precisely ONE recipe, the only one ? - return possible_recipes[1] //He is the chosen one - else //Okay, let's select the most complicated recipe //For posterity, this is the only comment oldcoder left outside of defining what "-1", "0" and "1" correspond to, in broken English - var/reagents_count = 0 //Let's reserve two variables for the fun inbound, this one for reagents - var/items_count = 0 //Ditto above, this one is for ingredients - . = possible_recipes[1] //We'll estimate the first recipe we found is the correct one until we start looping, to avoid returning nothing, nevermind this is what . allows - for(var/datum/recipe/recipe in possible_recipes) //Loop through all those recipes we found to be matching - var/items_number = (recipe.items) ? (recipe.items.len) : 0 //Get the exact length of items needed for each recipe - var/reagents_number = (recipe.reagents) ? (recipe.reagents.len) : 0 //Get the exact length of reagents needed for each recipe - if(items_number > items_count || (items_number == items_count && reagents_number > reagents_count)) //If there's more items or as much items and more reagents than the previous recipe - reagents_count = reagents_number //Set this as new maximum - items_count = items_number //And this one too - . = recipe //This recipe is now our favourite - return . //We found the most complex recipe, send that +/* * * * * * * * * * * * * * * * * * * * * * * * * * + * /datum/recipe by rastaf0 13 apr 2011 * + * * * * * * * * * * * * * * * * * * * * * * * * * * + * This is powerful and flexible recipe system. + * It exists not only for food. + * supports both reagents and objects as prerequisites. + * In order to use this system you have to define a deriative from /datum/recipe + * * reagents are reagents. Acid, milc, booze, etc. + * * items are objects. Fruits, tools, circuit boards. + * * result is type to create as new object + * * time is optional parameter, you shall use in in your machine, + default /datum/recipe/ procs does not rely on this parameter. + * + * Functions you need: + * /datum/recipe/proc/make(var/obj/container as obj) + * Creates result inside container, + * deletes prerequisite reagents, + * transfers reagents from prerequisite objects, + * deletes all prerequisite objects (even not needed for recipe at the moment). + * + * /proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj as obj, exact = 1) + * Wonderful function that select suitable recipe for you. + * obj is a machine (or magik hat) with prerequisites, + * exact = 0 forces algorithm to ignore superfluous stuff. + * + * Functions you do not need to call directly but could: + * /datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) + * //1 = precisely, 0 = insufficiently, -1 = superfluous + * + * /datum/recipe/proc/check_items(var/obj/container as obj) + * //1 = precisely, 0=insufficiently, -1 = superfluous + * + * */ + +//The person who made this honestly thought that the average coder from the distant future of 2015 would understand any of this shit without a thorough and painful examination +//And this is exactly why any Chemistry-related system is impenetrable to anyone but the best coders, even things theorically as simple as this +//So as I decrypt this arcane coding technology, I'll add comments where I see it fit, so absolutely fucking everywhere +//I'll take my Nobel Prize with fries thank you +//And yes indeed I know it's a lot of comments, but if you're not here to understand how recipes work, why are you here ? +/datum/recipe + + var/list/reagents //List of reagents needed and their amount, reagents = list("berryjuice" = 5) + var/list/reagents_forbidden //List of reagents that will not be transfered to the cooked item under any circumstance, use smartly and sparringly. reagents_forbidden = list("toxin", "water") + var/list/items //List of items needed, items = list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) + var/result //Well gee, what we output, result = /obj/item/weapon/reagent_containers/food/snacks/donut/normal + var/time = 100 //In tenths of a second, this is how long it takes for the magic to happen. The machine producing the recipe handles this value, but the recipe defines it + +//First step, let's check the reagents in our recipe machine (generally a microwave) +//Since it's reagents, it's about time for Chemistry-Holder insanity +/datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) //1 = Precisely what we need, 0 = Not enough, -1 = More than needed + //Now, here comes the arcane magic. Before we even do anything, we estimate we have just what we need. Why ? Who knows + . = 1 + //Scan the reagents in our recipe machine thingie one by one for shit we need in our recipe (water, hotsauce, salt, etc...) + for(var/r_r in reagents) + //Get the amount of said reagent we'll need in our recipe and assign it to that variable + var/reagent_amount = avail_reagents.get_reagent_amount(r_r) + //And now, the fun begins. Let's put this in plain words because holy crap + if(!(abs(reagent_amount - reagents[r_r]) < 0.5)) //If the absolute value of the amount of our reagent minus the needed amount of reagents for the recipe is NOT under 0.5 (rounding sanity) + if(reagent_amount > reagents[r_r]) //Let's check if the amount of our reagent is above the needed amount + . = -1 //If so, then we can say that we have more of this reagent that needed + else //Else + return 0 //We don't have what we need, abort, ABORT + //Remember that this is a for loop, so we do this for every reagent listed in our recipe + //Now, that check was fun, but we need to check for reagents we have not included per se (things not used in our recipe) + if((reagents ? (reagents.len) : (0)) < avail_reagents.reagent_list.len) //Given we have reagents in our recipe, are there more reagents in our machine than reagents needed in our recipe ? + return -1 //We have more reagents than needed, period + //Otherwise, get that value we determined earlier and send it, nevermind that a variable would have worked since it cannot be null + return . //If we have too much reagent (in numerical amounts) but only the reagents we need, -1, otherwise 1 + +//We just had fun with reagents, now let's check for items, literally any item, that is in our recipe. Apples, wrenches, dildos +//You would imagine that this would take a few lines of simple code, but you don't grasp oldcoder logic +/datum/recipe/proc/check_items(var/obj/container as obj) //1 = Precisely what we need, 0 = Not enough, -1 = More than needed + if(!items) //If there's no items in our recipe + if(locate(/obj/) in container) //And there are items in our recipe machine currently + return -1 //That's too much, abort + else //Nothing in our recipe machine + return 1 //Just what we need, *ping + . = 1 //The arcane magic rises again + var/list/checklist = items.Copy() //We need items in our recipe, so let's copy every single item in our recipe into a checklist + //Time for a loop + for(var/obj/O in container) //Let's loop through all the objects in our recipe machine + var/found = 0 //For once we use an actual variable + for(var/type in checklist) //At every object we find, stop to take a look at our entire checklist + if(istype(O, type)) //Is that what we are looking for yet + checklist -= type //Good, strike it out of our checklist + found = 1 //WE FOUND IT MA + break //Break that loop, continue downwards + if(!found) //Did we not find the object in our recipe machine on the checklist ? + . = -1 //Something extra in our ingredients, notify the cops + //We start looping through the objects in the container again at this point, until we checked every single one of them + if(checklist.len) //Are there still items on our recipe checklist ? + return 0 //Something is missing, abort + return . //If we found extra items, return -1, otherwise return 1 + +//Food-related recipe production +//Note : Due to changes to no longer wipe nutriments from cooked items, this is the same as make. So from now on this is THE "turn recipe into new thing" proc +/datum/recipe/proc/make_food(var/obj/container as obj) //Find our recipe machine and let's begin + var/obj/result_obj = new result(container) //Spawn the result of our little cuisine in the recipe machine in advance to transfer reagents + for(var/obj/O in (container.contents - result_obj)) //Find all objects (for instance, raw food or beakers) in our machine, excluding the result we just created + if(O.reagents) //Little sanity, can't hurt + for(var/r_r in reagents_forbidden) //Check forbidden reagents + O.reagents.del_reagent("[r_r]") //If we find any, remove + O.reagents.update_total() //Make sure we're set + O.reagents.trans_to(result_obj, O.reagents.total_volume) //If we have reagents in here, squeeze them into the end product + qdel(O) //Delete the object, he has outlived his usefulness + container.reagents.clear_reagents() //Clear all the reagents we haven't transfered, for instance if we need to cook in water + score["meals"]++ //Yes, it's a weird placement, but it's sure to work correctly as long as make_food() is used for food + return result_obj //Here we go, your result sire + +//Find what to do with all this shit in the microwave dynamically, without blowing up the station +//We consider all recipes in the game, obj (typecast as obj and estimated as obj because fuck you) and wherever or not its ingredients are exact based on what we learned from the last two procs +/proc/select_recipe(var/list/datum/recipe/avaiable_recipes, var/obj/obj as obj, var/exact = 1 as num) + if(!exact) //Is the recipe not exact (1) + exact = -1 //Change it to -1 for simplicity, too much or not enough is the same problem now + var/list/datum/recipe/possible_recipes = new //Create a list, hopefully not ending the universe in the process + for(var/datum/recipe/recipe in avaiable_recipes) //Loop through the ingame recipes + if(recipe.check_reagents(obj.reagents) == exact && recipe.check_items(obj) == exact) //What did we return for reagents and objects ingredient checks, and does it fit with our recipe ? + possible_recipes += recipe //Perfect, we can make this recipe with our current ingredients, add it + if(possible_recipes.len == 0) //We're done looping through the ingame recipes, did we find nothing ? + return null //Game over + else if(possible_recipes.len == 1) //Do we have precisely ONE recipe, the only one ? + return possible_recipes[1] //He is the chosen one + else //Okay, let's select the most complicated recipe //For posterity, this is the only comment oldcoder left outside of defining what "-1", "0" and "1" correspond to, in broken English + var/reagents_count = 0 //Let's reserve two variables for the fun inbound, this one for reagents + var/items_count = 0 //Ditto above, this one is for ingredients + . = possible_recipes[1] //We'll estimate the first recipe we found is the correct one until we start looping, to avoid returning nothing, nevermind this is what . allows + for(var/datum/recipe/recipe in possible_recipes) //Loop through all those recipes we found to be matching + var/items_number = (recipe.items) ? (recipe.items.len) : 0 //Get the exact length of items needed for each recipe + var/reagents_number = (recipe.reagents) ? (recipe.reagents.len) : 0 //Get the exact length of reagents needed for each recipe + if(items_number > items_count || (items_number == items_count && reagents_number > reagents_count)) //If there's more items or as much items and more reagents than the previous recipe + reagents_count = reagents_number //Set this as new maximum + items_count = items_number //And this one too + . = recipe //This recipe is now our favourite + return . //We found the most complex recipe, send that diff --git a/code/datums/sun.dm b/code/datums/sun.dm index 6cb0ffe6356..4208631aa03 100644 --- a/code/datums/sun.dm +++ b/code/datums/sun.dm @@ -1,93 +1,93 @@ -var/global/datum/sun/sun - -/datum/sun - var/angle - var/dx - var/dy - var/list/solars // For debugging purposes, references solars_list at the constructor. - - // Replacement for var/counter to force the sun to move every X IC minutes. - // To prevent excess server load the server only updates the sun's sight lines by minute(s). - // 300 is 30 seconds. - var/updatePer = 600 - - var/nextTime - var/lastAngle = 0 - var/rotationRate = 1 //A pretty average way of setting up station rotation direction AND absolute speed - -/datum/sun/New() - - solars = solars_list - nextTime = updatePer - - rotationRate = rand(850, 1150) / 1000 //Slight deviation, no more than 15 %, budget orbital stabilization system - if(prob(50)) - rotationRate = -rotationRate - -/* - * Calculate the sun's position given the time of day. - */ -/datum/sun/proc/calc_position() - var/time = world.time - angle = ((rotationRate * time / 100) % 360 + 360) % 360 - - if(angle != lastAngle) - var/obj/machinery/power/solar/panel/tracker/T - for(T in solars_list) - if(!T.powernet) - solars_list.Remove(T) - continue - - T.set_angle(angle) - lastAngle = angle - - if(world.time < nextTime) - return - - nextTime += updatePer - - // Now calculate and cache the (dx,dy) increments for line drawing. - var/si = sin(angle) - var/co = cos(angle) - - if(!co) - dx = 0 - dy = si - else if (abs(si) < abs(co)) - dx = si / abs(co) - dy = co / abs(co) - else - dx = si / abs(si) - dy = co / abs(si) - - var/obj/machinery/power/solar/panel/S - - for(S in solars_list) - if(!S.powernet) - solars_list.Remove(S) - - if(S.control) - occlusion(S) - -//For a solar panel, trace towards sun to see if we're in shadow. - -/datum/sun/proc/occlusion(const/obj/machinery/power/solar/panel/S) - var/ax = S.x //Start at the solar panel. - var/ay = S.y - var/i - var/turf/T - - for(i = 1 to 256) //No tiles shall stay unchecked. Since the loop stops when it hit level boundaries or opaque blocks, this can't cause too much problems - ax += dx //Do step - ay += dy - - T = locate(round(ax, 0.5), round(ay, 0.5), S.z) - - if(T.x == 1 || T.x == world.maxx || T.y == 1 || T.y == world.maxy) // Not obscured if we reach the edge. - break - if(T.opacity) //Opaque objects block light. - S.obscured = 1 - return - - S.obscured = 0 //If hit the edge or stepped 20 times, not obscured. +var/global/datum/sun/sun + +/datum/sun + var/angle + var/dx + var/dy + var/list/solars // For debugging purposes, references solars_list at the constructor. + + // Replacement for var/counter to force the sun to move every X IC minutes. + // To prevent excess server load the server only updates the sun's sight lines by minute(s). + // 300 is 30 seconds. + var/updatePer = 600 + + var/nextTime + var/lastAngle = 0 + var/rotationRate = 1 //A pretty average way of setting up station rotation direction AND absolute speed + +/datum/sun/New() + + solars = solars_list + nextTime = updatePer + + rotationRate = rand(850, 1150) / 1000 //Slight deviation, no more than 15 %, budget orbital stabilization system + if(prob(50)) + rotationRate = -rotationRate + +/* + * Calculate the sun's position given the time of day. + */ +/datum/sun/proc/calc_position() + var/time = world.time + angle = ((rotationRate * time / 100) % 360 + 360) % 360 + + if(angle != lastAngle) + var/obj/machinery/power/solar/panel/tracker/T + for(T in solars_list) + if(!T.powernet) + solars_list.Remove(T) + continue + + T.set_angle(angle) + lastAngle = angle + + if(world.time < nextTime) + return + + nextTime += updatePer + + // Now calculate and cache the (dx,dy) increments for line drawing. + var/si = sin(angle) + var/co = cos(angle) + + if(!co) + dx = 0 + dy = si + else if (abs(si) < abs(co)) + dx = si / abs(co) + dy = co / abs(co) + else + dx = si / abs(si) + dy = co / abs(si) + + var/obj/machinery/power/solar/panel/S + + for(S in solars_list) + if(!S.powernet) + solars_list.Remove(S) + + if(S.control) + occlusion(S) + +//For a solar panel, trace towards sun to see if we're in shadow. + +/datum/sun/proc/occlusion(const/obj/machinery/power/solar/panel/S) + var/ax = S.x //Start at the solar panel. + var/ay = S.y + var/i + var/turf/T + + for(i = 1 to 256) //No tiles shall stay unchecked. Since the loop stops when it hit level boundaries or opaque blocks, this can't cause too much problems + ax += dx //Do step + ay += dy + + T = locate(round(ax, 0.5), round(ay, 0.5), S.z) + + if(T.x == 1 || T.x == world.maxx || T.y == 1 || T.y == world.maxy) // Not obscured if we reach the edge. + break + if(T.opacity) //Opaque objects block light. + S.obscured = 1 + return + + S.obscured = 0 //If hit the edge or stepped 20 times, not obscured. S.update_solar_exposure() \ No newline at end of file diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index ccc290538c6..aa0982c516e 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -1,1546 +1,1546 @@ -//SUPPLY PACKS -//NOTE: only secure crate types use the access var (and are lockable) -//NOTE: hidden packs only show up when the computer has been emagged. -//ANOTER NOTE: Contraband is obtainable through modified supplycomp circuitboards. -//BIG NOTE: Don't add living things to crates, that's bad, it will break the shuttle. -//NEW NOTE: Do NOT set the price of any crates below 7 points. Doing so allows infinite points. - -var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality","Engineering","Medical","Science","Hydroponics","Vending Machine packs") - -/datum/supply_packs - var/name = null - var/list/contains = list() - var/manifest = "" - var/amount = null - var/cost = null - var/containertype = null - var/containername = null - var/access = null - var/hidden = 0 //Emaggable - var/contraband = 0 //Hackable via tools - var/group = "Supplies" - -/datum/supply_packs/New() - manifest += "
        " - for(var/path in contains) - if(!path) continue - var/atom/movable/AM = new path() - manifest += "
      • [AM.name]
      • " - AM.loc = null //just to make sure they're deleted by the garbage collector - manifest += "
      " - -//////SUPPLIES////// - -/datum/supply_packs/toner - name = "Toner Cartridges" - contains = list(/obj/item/device/toner, - /obj/item/device/toner, - /obj/item/device/toner, - /obj/item/device/toner, - /obj/item/device/toner, - /obj/item/device/toner) - cost = 10 - containertype = /obj/structure/closet/crate - containername = "Toner Cartridges" - group = "Supplies" - -/datum/supply_packs/labels - name = "Label Rolls" - contains = list(/obj/item/weapon/storage/box/labels, - /obj/item/weapon/storage/box/labels, //21 label rolls is enough to label Beepsky "SHITCURITRON" 375 times, - /obj/item/weapon/storage/box/labels) //so this might be a bit excessive. - cost = 10 - containertype = /obj/structure/closet/crate - containername = "Label Rolls" - group = "Supplies" - -/datum/supply_packs/internals - name = "Internals crate" - contains = list(/obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/item/weapon/tank/air, - /obj/item/weapon/tank/air, - /obj/item/weapon/tank/air) - cost = 10 - containertype = /obj/structure/closet/crate/internals - containername = "Internals crate" - group = "Supplies" - -/datum/supply_packs/evacuation - name = "Emergency equipment" - contains = list(/obj/item/weapon/storage/toolbox/emergency, - /obj/item/weapon/storage/toolbox/emergency, - /obj/item/clothing/suit/storage/hazardvest, - /obj/item/clothing/suit/storage/hazardvest, - /obj/item/weapon/tank/emergency_oxygen, - /obj/item/weapon/tank/emergency_oxygen, - /obj/item/weapon/tank/emergency_oxygen, - /obj/item/weapon/tank/emergency_oxygen, - /obj/item/weapon/tank/emergency_oxygen, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas, - /obj/machinery/bot/floorbot, - /obj/machinery/bot/floorbot, - /obj/machinery/bot/medbot, - /obj/machinery/bot/medbot) - cost = 40 - containertype = /obj/structure/closet/crate/internals - containername = "Emergency Crate" - group = "Supplies" - -/datum/supply_packs/janitor - name = "Janitorial supplies" - contains = list(/obj/item/weapon/reagent_containers/glass/bucket, - /obj/item/weapon/reagent_containers/glass/bucket, - /obj/item/weapon/reagent_containers/glass/bucket, - /obj/item/weapon/mop, - /obj/item/weapon/caution, - /obj/item/weapon/caution, - /obj/item/weapon/caution, - /obj/item/weapon/storage/bag/trash, - /obj/item/weapon/reagent_containers/spray/cleaner, - /obj/item/weapon/reagent_containers/glass/rag, - /obj/item/weapon/grenade/chem_grenade/cleaner, - /obj/item/weapon/grenade/chem_grenade/cleaner, - /obj/item/weapon/grenade/chem_grenade/cleaner, - /obj/structure/mopbucket) - cost = 10 - containertype = /obj/structure/closet/crate - containername = "Janitorial supplies" - group = "Supplies" - -/datum/supply_packs/lightbulbs - name = "Replacement lights" - contains = list(/obj/item/weapon/storage/box/lights/mixed, - /obj/item/weapon/storage/box/lights/mixed, - /obj/item/weapon/storage/box/lights/mixed) - cost = 10 - containertype = /obj/structure/closet/crate - containername = "Replacement lights" - group = "Supplies" - -/datum/supply_packs/helightbulbs - name = "High efficiency lights" - contains = list(/obj/item/weapon/storage/box/lights/he, - /obj/item/weapon/storage/box/lights/he) - cost = 20 - containertype = /obj/structure/closet/crate - containername = "High efficiency lights" - group = "Supplies" - -/datum/supply_packs/newscaster - name = "Newscaster crate" - contains = list(/obj/item/mounted/frame/newscaster, - /obj/item/mounted/frame/newscaster, - /obj/item/mounted/frame/newscaster) - cost = 10 - containertype = /obj/structure/closet/crate - containername = "Newscaster crate" - group = "Supplies" - -/datum/supply_packs/mule - name = "MULEbot Crate" - contains = list(/obj/machinery/bot/mulebot) - cost = 20 - containertype = /obj/structure/largecrate/mule - containername = "MULEbot Crate" - group = "Supplies" - -/datum/supply_packs/porcelain - name = "Porcelain Crate" - contains = list() - cost = 10 - containertype = /obj/structure/largecrate/porcelain - containername = "Porcelain Crate" - group = "Supplies" - -/datum/supply_packs/metal50 - name = "50 Metal Sheets" - contains = list(/obj/item/stack/sheet/metal) - amount = 50 - cost = 10 - containertype = /obj/structure/closet/crate/engi - containername = "Metal sheets crate" - group = "Supplies" - -/datum/supply_packs/glass50 - name = "50 Glass Sheets" - contains = list(/obj/item/stack/sheet/glass/glass) - amount = 50 - cost = 10 - containertype = /obj/structure/closet/crate/engi - containername = "Glass sheets crate" - group = "Supplies" - -/datum/supply_packs/wood25 - name = "25 Wooden Planks" - contains = list(/obj/item/stack/sheet/wood) - amount = 25 - cost = 12 - containertype = /obj/structure/closet/crate/engi - containername = "Wooden planks crate" - group = "Supplies" - -/datum/supply_packs/carpet - name = "30 Carpet Tiles" - contains = list(/obj/item/stack/tile/carpet) - amount = 30 - cost = 15 - containertype = /obj/structure/closet/crate - containername = "Carpet Crate" - group = "Supplies" - -/datum/supply_packs/arcade - name = "30 Arcade Tiles" - contains = list(/obj/item/stack/tile/arcade) - amount = 30 - cost = 15 - containertype = /obj/structure/closet/crate - containername = "Arcade Tiles Crate" - group = "Supplies" - -/datum/supply_packs/grass - name = "30 Grass Tiles" - contains = list(/obj/item/stack/tile/grass) - amount = 30 - cost = 15 - containertype = /obj/structure/closet/crate - containername = "Grass Crate" - group = "Supplies" - -/datum/supply_packs/watertank - name = "Water tank crate" - contains = list(/obj/structure/reagent_dispensers/watertank) - cost = 8 - containertype = /obj/structure/largecrate - containername = "water tank crate" - group = "Supplies" - -/datum/supply_packs/fueltank - name = "Fuel tank crate" - contains = list(/obj/structure/reagent_dispensers/fueltank) - cost = 8 - containertype = /obj/structure/largecrate - containername = "fuel tank crate" - group = "Supplies" - -/datum/supply_packs/silicatetank - name = "Silicate tank crate" - contains = list(/obj/structure/reagent_dispensers/silicate) - cost = 8 - containertype = /obj/structure/largecrate - containername = "silicate tank crate" - group = "Supplies" - -/datum/supply_packs/mining - name = "Mining Equipment" - contains = list(/obj/item/weapon/pickaxe/drill, - /obj/item/weapon/pickaxe, - /obj/item/weapon/pickaxe, - /obj/item/device/flashlight/lantern, - /obj/item/device/flashlight/lantern, - /obj/item/device/flashlight/lantern, - /obj/item/device/mining_scanner, - /obj/item/weapon/storage/bag/ore, - /obj/item/weapon/storage/bag/ore, - /obj/item/weapon/storage/bag/ore) - cost = 20 - containertype = /obj/structure/closet/crate - containername = "Mining Equipment Crate" - access = access_mining - group = "Supplies" - -/datum/supply_packs/artscrafts - name = "Arts and Crafts supplies" - contains = list(/obj/item/weapon/storage/fancy/crayons, - /obj/item/device/camera, - /obj/item/device/camera_film, - /obj/item/device/camera_film, - /obj/item/weapon/storage/photo_album, - /obj/item/stack/package_wrap, - /obj/item/weapon/reagent_containers/glass/paint/red, - /obj/item/weapon/reagent_containers/glass/paint/green, - /obj/item/weapon/reagent_containers/glass/paint/blue, - /obj/item/weapon/reagent_containers/glass/paint/yellow, - /obj/item/weapon/reagent_containers/glass/paint/violet, - /obj/item/weapon/reagent_containers/glass/paint/black, - /obj/item/weapon/reagent_containers/glass/paint/white, - /obj/item/weapon/reagent_containers/glass/paint/remover, - /obj/item/mounted/poster, - /obj/item/stack/package_wrap/gift, - /obj/item/stack/package_wrap/gift, - /obj/item/stack/package_wrap/gift) - cost = 10 - containertype = "/obj/structure/closet/crate" - containername = "Arts and Crafts crate" - group = "Supplies" - - -/datum/supply_packs/randomised/contraband - num_contained = 5 - contains = list(/obj/item/seeds/bloodtomatoseed, - /obj/item/weapon/storage/pill_bottle/zoom, - /obj/item/weapon/storage/pill_bottle/happy, - /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, - /obj/item/weapon/storage/bag/wiz_cards/frog) - - name = "Contraband crate" - cost = 30 - containertype = /obj/structure/closet/crate - containername = "Unlabeled crate" - contraband = 1 - group = "Supplies" - -/datum/supply_packs/boxes - name = "Empty Box supplies" - contains = list(/obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box, - /obj/item/weapon/storage/box) - cost = 10 - containertype = "/obj/structure/closet/crate" - containername = "Empty Box crate" - group = "Supplies" - -/datum/supply_packs/eftpos - contains = list(/obj/item/device/eftpos) - name = "EFTPOS scanner" - cost = 10 - containertype = /obj/structure/closet/crate - containername = "EFTPOS crate" - group = "Supplies" - -//////CLOTHING////// - -/datum/supply_packs/costume - name = "Standard Costume crate" - contains = list(/obj/item/weapon/storage/backpack/clown, - /obj/item/clothing/shoes/clown_shoes, - /obj/item/clothing/mask/gas/clown_hat, - /obj/item/clothing/under/rank/clown, - /obj/item/weapon/bikehorn, - /obj/item/clothing/under/mime, - /obj/item/clothing/shoes/mime, - /obj/item/clothing/gloves/white, - /obj/item/clothing/mask/gas/mime, - /obj/item/clothing/head/beret, - /obj/item/clothing/suit/suspenders, - /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing) - cost = 10 - containertype = /obj/structure/closet/crate/secure - containername = "Standard Costumes" - access = access_theatre - group = "Clothing" - -/datum/supply_packs/wizard - name = "Wizard costume" - contains = list(/obj/item/weapon/staff, - /obj/item/clothing/suit/wizrobe/fake, - /obj/item/clothing/shoes/sandal, - /obj/item/clothing/head/wizard/fake) - cost = 20 - containertype = /obj/structure/closet/crate - containername = "Wizard costume crate" - group = "Clothing" - -/datum/supply_packs/randomised - var/num_contained = 3 //number of items picked to be contained in a randomised crate - contains = list(/obj/item/clothing/head/collectable/chef, - /obj/item/clothing/head/collectable/paper, - /obj/item/clothing/head/collectable/tophat, - /obj/item/clothing/head/collectable/captain, - /obj/item/clothing/head/collectable/beret, - /obj/item/clothing/head/collectable/welding, - /obj/item/clothing/head/collectable/flatcap, - /obj/item/clothing/head/collectable/pirate, - /obj/item/clothing/head/collectable/kitty, - /obj/item/clothing/head/collectable/rabbitears, - /obj/item/clothing/head/collectable/wizard, - /obj/item/clothing/head/collectable/hardhat, - /obj/item/clothing/head/collectable/HoS, - /obj/item/clothing/head/collectable/thunderdome, - /obj/item/clothing/head/collectable/swat, - /obj/item/clothing/head/collectable/slime, - /obj/item/clothing/head/collectable/police, - /obj/item/clothing/head/collectable/slime, - /obj/item/clothing/head/collectable/xenom, - /obj/item/clothing/head/collectable/petehat) - name = "Collectable hat crate!" - cost = 200 - containertype = /obj/structure/closet/crate - containername = "Collectable hats crate! Brought to you by Bass.inc!" - group = "Clothing" - -/datum/supply_packs/randomised/New() - manifest += "Contains any [num_contained] of:" - ..() - -/datum/supply_packs/formal_wear - contains = list(/obj/item/clothing/head/that, - /obj/item/clothing/suit/storage/lawyer/bluejacket, - /obj/item/clothing/suit/storage/lawyer/purpjacket, - /obj/item/clothing/under/suit_jacket, - /obj/item/clothing/under/suit_jacket/female, - /obj/item/clothing/under/suit_jacket/really_black, - /obj/item/clothing/under/suit_jacket/red, - /obj/item/clothing/shoes/black, - /obj/item/clothing/shoes/black, - /obj/item/clothing/suit/wcoat) - name = "Formalwear closet" - cost = 30 - containertype = /obj/structure/closet - containername = "Formalwear for the best occasions." - group = "Clothing" - -/datum/supply_packs/waifu - name = "Feminine formalwear" - contains = list(/obj/item/clothing/under/dress/dress_fire, - /obj/item/clothing/under/dress/dress_green, - /obj/item/clothing/under/dress/dress_orange, - /obj/item/clothing/under/dress/dress_pink, - /obj/item/clothing/under/dress/dress_yellow, - /obj/item/clothing/under/dress/dress_saloon, - /obj/item/clothing/under/wedding/bride_orange, - /obj/item/clothing/under/wedding/bride_purple, - /obj/item/clothing/under/wedding/bride_blue, - /obj/item/clothing/under/wedding/bride_red, - /obj/item/clothing/under/wedding/bride_white, - /obj/item/clothing/under/sundress, - /obj/item/weapon/lipstick/random, - /obj/item/weapon/lipstick/random) - cost = 30 - containertype = /obj/structure/closet/crate - containername = "Feminine clothing" - group = "Clothing" - -/datum/supply_packs/knight //why seperate them - name = "Knight Armor Crate" - contains = list(/obj/item/clothing/suit/armor/knight, - /obj/item/clothing/suit/armor/knight/red, - /obj/item/clothing/suit/armor/knight/yellow, - /obj/item/clothing/suit/armor/knight/blue, - /obj/item/clothing/head/helmet/knight, - /obj/item/clothing/head/helmet/knight/red, - /obj/item/clothing/head/helmet/knight/yellow, - /obj/item/clothing/head/helmet/knight/blue) - cost = 35 - containertype = /obj/structure/closet/crate - containername = "knight armor crate" - group = "Clothing" - -//////SECURITY////// - -/datum/supply_packs/specialops - name = "Special Ops supplies" - contains = list(/obj/item/weapon/storage/box/emps, - /obj/item/weapon/grenade/smokebomb, - /obj/item/weapon/grenade/smokebomb, - /obj/item/weapon/grenade/smokebomb, - /obj/item/weapon/pen/paralysis, - /obj/item/weapon/grenade/chem_grenade/incendiary) - cost = 20 - containertype = /obj/structure/closet/crate - containername = "Special Ops crate" - group = "Security" - hidden = 1 - -/datum/supply_packs/beanbagammo - name = "Beanbag shells" - contains = list(/obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag, - /obj/item/ammo_casing/shotgun/beanbag) - cost = 10 - containertype = /obj/structure/closet/crate - containername = "Beanbag shells" - group = "Security" - -/datum/supply_packs/weapons - name = "Weapons crate" - contains = list(/obj/item/weapon/melee/baton/loaded, - /obj/item/weapon/melee/baton/loaded, - /obj/item/weapon/gun/energy/laser, - /obj/item/weapon/gun/energy/laser, - /obj/item/weapon/gun/energy/taser, - /obj/item/weapon/gun/energy/taser, - /obj/item/weapon/storage/box/flashbangs, - /obj/item/weapon/storage/box/flashbangs, - /obj/item/weapon/storage/box/bolas) - cost = 30 - containertype = /obj/structure/closet/crate/secure/weapon - containername = "Weapons crate" - access = access_security - group = "Security" - -/datum/supply_packs/eweapons - name = "Incendiary weapons crate" - contains = list(/obj/item/weapon/flamethrower/full, - /obj/item/weapon/tank/plasma, - /obj/item/weapon/tank/plasma, - /obj/item/weapon/tank/plasma, - /obj/item/weapon/grenade/chem_grenade/incendiary, - /obj/item/weapon/grenade/chem_grenade/incendiary, - /obj/item/weapon/grenade/chem_grenade/incendiary) - cost = 25 - containertype = /obj/structure/closet/crate/secure/weapon - containername = "Incendiary weapons crate" - access = access_heads - group = "Security" - -/datum/supply_packs/armor - name = "Armor crate" - contains = list(/obj/item/clothing/head/helmet, - /obj/item/clothing/head/helmet, - /obj/item/clothing/suit/armor/vest, - /obj/item/clothing/suit/armor/vest) - cost = 15 - containertype = /obj/structure/closet/crate/secure - containername = "Armor crate" - access = access_security - group = "Security" - -/datum/supply_packs/riot - name = "Riot gear crate" - contains = list(/obj/item/weapon/melee/baton/loaded, - /obj/item/weapon/melee/baton/loaded, - /obj/item/weapon/melee/baton/loaded, - /obj/item/weapon/shield/riot, - /obj/item/weapon/shield/riot, - /obj/item/weapon/shield/riot, - /obj/item/weapon/storage/box/flashbangs, - /obj/item/weapon/storage/box/flashbangs, - /obj/item/weapon/storage/box/flashbangs, - /obj/item/weapon/handcuffs, - /obj/item/weapon/handcuffs, - /obj/item/weapon/handcuffs, - /obj/item/clothing/head/helmet/riot, - /obj/item/clothing/suit/armor/riot, - /obj/item/clothing/head/helmet/riot, - /obj/item/clothing/suit/armor/riot, - /obj/item/clothing/head/helmet/riot, - /obj/item/clothing/suit/armor/riot, - /obj/item/weapon/storage/box/bolas, - /obj/item/weapon/storage/box/bolas) - cost = 60 - containertype = /obj/structure/closet/crate/secure - containername = "Riot gear crate" - access = access_armory - group = "Security" - -/datum/supply_packs/loyalty - name = "Loyalty implant crate" - contains = list (/obj/item/weapon/storage/lockbox/loyalty) - cost = 60 - containertype = /obj/structure/closet/crate/secure - containername = "Loyalty implant crate" - access = access_armory - group = "Security" - -/datum/supply_packs/tracking - name = "Tracking implant crate" - contains = list (/obj/item/weapon/storage/lockbox/tracking) - cost = 50 - containertype = /obj/structure/closet/crate/secure - containername = "Tracking implant crate" - access = access_armory - group = "Security" - -/datum/supply_packs/chem - name = "Chemical implant crate" - contains = list (/obj/item/weapon/storage/lockbox/chem) - cost = 50 - containertype = /obj/structure/closet/crate/secure - containername = "Chemical implant crate" - access = access_armory - group = "Security" - -/datum/supply_packs/ballistic - name = "Ballistic gear crate" - contains = list(/obj/item/clothing/suit/armor/bulletproof, - /obj/item/clothing/suit/armor/bulletproof, - /obj/item/weapon/gun/projectile/shotgun/pump/combat, - /obj/item/weapon/gun/projectile/shotgun/pump/combat) - cost = 50 - containertype = /obj/structure/closet/crate/secure - containername = "Ballistic gear crate" - access = access_armory - group = "Security" - -/datum/supply_packs/shotgunammo - name = "Shotgun shells" - contains = list(/obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun, - /obj/item/ammo_casing/shotgun) - cost = 20 - containertype = /obj/structure/closet/crate/secure - containername = "Shotgun shells" - access = access_armory - group = "Security" - -/datum/supply_packs/expenergy - name = "Experimental energy gear crate" - contains = list(/obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/suit/armor/laserproof, - /obj/item/weapon/gun/energy/gun, - /obj/item/weapon/gun/energy/gun) - cost = 50 - containertype = /obj/structure/closet/crate/secure - containername = "Experimental energy gear crate" - access = access_armory - group = "Security" - -/datum/supply_packs/exparmor - name = "Experimental armor crate" - contains = list(/obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/suit/armor/bulletproof, - /obj/item/clothing/head/helmet/riot, - /obj/item/clothing/suit/armor/riot) - cost = 35 - containertype = /obj/structure/closet/crate/secure - containername = "Experimental armor crate" - access = access_armory - group = "Security" - -/datum/supply_packs/securitybarriers - name = "Security Checkpoint Equipment" - contains = list(/obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/detector) - cost = 10 - containertype = /obj/structure/closet/crate/secure/gear - containername = "Security Barriers crate" - group = "Security" - -//////HOSPITALITY////// - -/datum/supply_packs/food - name = "Basic cooking crate" - contains = list(/obj/item/weapon/reagent_containers/food/drinks/flour, - /obj/item/weapon/reagent_containers/food/drinks/flour, - /obj/item/weapon/reagent_containers/food/drinks/flour, - /obj/item/weapon/reagent_containers/food/drinks/flour, - /obj/item/weapon/reagent_containers/food/drinks/milk, - /obj/item/weapon/reagent_containers/food/drinks/milk, - /obj/item/weapon/storage/fancy/egg_box) - cost = 10 - containertype = /obj/structure/closet/crate/freezer - containername = "Basic cooking crate" - group = "Hospitality" - -/datum/supply_packs/randomised/fruit - name = "Fruit crate" - num_contained = 16 - contains = list(/obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, - /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, - /obj/item/weapon/reagent_containers/food/snacks/grown/berries, - /obj/item/weapon/reagent_containers/food/snacks/grown/cherries, - /obj/item/weapon/reagent_containers/food/snacks/grown/grapes, - /obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes, - /obj/item/weapon/reagent_containers/food/snacks/grown/lime, - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, - /obj/item/weapon/reagent_containers/food/snacks/grown/orange) - cost = 20 - containertype = /obj/structure/closet/crate/freezer - containername = "Fruit crate" - group = "Hospitality" - -/datum/supply_packs/exotic_garnishes //We don't use a randomised crate because we want some special reagents, and also to control chances - name = "Exotic garnishes" - contains = list(/obj/item/weapon/reagent_containers/food/condiment/exotic, - /obj/item/weapon/reagent_containers/food/condiment/exotic, - /obj/item/weapon/reagent_containers/food/condiment/exotic, - /obj/item/weapon/reagent_containers/food/condiment/exotic, - /obj/item/weapon/reagent_containers/food/condiment/exotic, - /obj/item/weapon/reagent_containers/food/condiment/exotic) - cost = 15 - containertype = /obj/structure/closet/crate/secure - containername = "Exotic garnishes" - access = access_kitchen - group = "Hospitality" - -/datum/supply_packs/randomised/trophy_meats - name = "Trophy meats" - num_contained = 8 - contains = list(/obj/item/weapon/reagent_containers/food/snacks/meat/mimic, - /obj/item/weapon/reagent_containers/food/snacks/meat/bearmeat, - /obj/item/weapon/reagent_containers/food/snacks/meat/spidermeat, - /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat, - /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat/imitation, - /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/spiderleg, - /obj/item/weapon/reagent_containers/food/snacks/spidereggs) - cost = 30 - containertype = /obj/structure/closet/crate/secure - containername = "Trophy meats" - access = access_kitchen - group = "Hospitality" - -/datum/supply_packs/party - name = "Party equipment" - contains = list(/obj/item/weapon/storage/box/drinkingglasses, - /obj/item/weapon/reagent_containers/food/drinks/shaker, - /obj/item/weapon/reagent_containers/food/drinks/bottle/patron, - /obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager, - /obj/item/weapon/storage/fancy/cigarettes/dromedaryco, - /obj/item/weapon/lipstick/random, - /obj/item/weapon/reagent_containers/food/drinks/ale, - /obj/item/weapon/reagent_containers/food/drinks/ale, - /obj/item/weapon/reagent_containers/food/drinks/beer, - /obj/item/weapon/reagent_containers/food/drinks/beer, - /obj/item/weapon/reagent_containers/food/drinks/beer, - /obj/item/weapon/reagent_containers/food/drinks/beer, - /obj/item/device/maracas, - /obj/item/device/maracas) - cost = 20 - containertype = /obj/structure/closet/crate - containername = "Party equipment" - group = "Hospitality" - -/datum/supply_packs/randomised/pizza - num_contained = 5 - contains = list(/obj/item/pizzabox/margherita, - /obj/item/pizzabox/mushroom, - /obj/item/pizzabox/meat, - /obj/item/pizzabox/vegetable) - name = "Surprise pack of five pizzas" - cost = 75 - containertype = /obj/structure/closet/crate/freezer - containername = "Pizza crate" - group = "Hospitality" - -/datum/supply_packs/cafe - name = "Cafe equipment" - contains = list(/obj/item/weapon/circuitboard/chem_dispenser/brewer, - /obj/item/weapon/storage/box/mugs, - /obj/item/weapon/storage/box/mugs, - /obj/item/weapon/reagent_containers/glass/kettle/red) - cost = 20 - containertype = /obj/structure/closet/crate - containername = "Cafe equipment" - group = "Hospitality" - -/datum/supply_packs/bar - name = "Advanced Bartending equipment" - contains = list(/obj/item/weapon/circuitboard/chem_dispenser/soda_dispenser, - /obj/item/weapon/circuitboard/chem_dispenser/booze_dispenser, - /obj/item/weapon/storage/box/drinkingglasses, - /obj/item/weapon/storage/box/drinkingglasses, - /obj/item/weapon/reagent_containers/food/drinks/shaker) - cost = 40 - containertype = /obj/structure/closet/crate - containername = "Bartending equipment" - group = "Hospitality" - -/datum/supply_packs/festive - name = "Festive supplies" - contains = list(/obj/item/stack/package_wrap/gift, - /obj/item/stack/package_wrap/gift, - /obj/item/weapon/toy/xmas_cracker, - /obj/item/weapon/toy/xmas_cracker, - /obj/item/weapon/toy/xmas_cracker, - /obj/item/weapon/toy/xmas_cracker, - /obj/item/weapon/toy/xmas_cracker, - /obj/item/weapon/toy/xmas_cracker, - /obj/item/clothing/head/christmas/santahat/red, - /obj/item/clothing/head/christmas/santahat/green, - /obj/item/clothing/suit/jumper/christmas/red, - /obj/item/clothing/suit/jumper/christmas/green, - /obj/item/clothing/suit/jumper/christmas/blue, - /obj/item/clothing/mask/scarf/red, - /obj/item/clothing/mask/scarf/blue, - /obj/item/clothing/mask/scarf/green) - cost = 30 - containertype = /obj/structure/closet/crate - containername = "Festivus supplies" - group = "Hospitality" - - -//////ENGINEERING////// - -/datum/supply_packs/electrical - name = "Electrical maintenance crate" - contains = list(/obj/item/weapon/storage/toolbox/electrical, - /obj/item/weapon/storage/toolbox/electrical, - /obj/item/clothing/gloves/yellow, - /obj/item/clothing/gloves/yellow, - /obj/item/weapon/cell, - /obj/item/weapon/cell, - /obj/item/weapon/cell/high, - /obj/item/weapon/cell/high) - cost = 15 - containertype = /obj/structure/closet/crate/engi - containername = "Electrical maintenance crate" - group = "Engineering" - -/datum/supply_packs/mechanical - name = "Mechanical maintenance crate" - contains = list(/obj/item/weapon/storage/belt/utility/full, - /obj/item/weapon/storage/belt/utility/full, - /obj/item/weapon/storage/belt/utility/full, - /obj/item/clothing/suit/storage/hazardvest, - /obj/item/clothing/suit/storage/hazardvest, - /obj/item/clothing/suit/storage/hazardvest, - /obj/item/clothing/head/welding, - /obj/item/clothing/head/welding, - /obj/item/clothing/head/hardhat) - cost = 10 - containertype = /obj/structure/closet/crate/engi - containername = "Mechanical maintenance crate" - group = "Engineering" - -/datum/supply_packs/solar - name = "Solar Pack crate" - contains = list(/obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, - /obj/machinery/power/solar_assembly, //21 Solar Assemblies. 1 Extra for the controller - /obj/item/weapon/circuitboard/solar_control, - /obj/item/weapon/tracker_electronics, - /obj/item/weapon/paper/solar) - cost = 20 - containertype = /obj/structure/closet/crate/engi - containername = "solar pack crate" - group = "Engineering" - -/datum/supply_packs/engine - name = "Emitter crate" - contains = list(/obj/machinery/power/emitter, - /obj/machinery/power/emitter) - cost = 10 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Emitter crate" - access = access_ce - group = "Engineering" - -/datum/supply_packs/engine/field_gen - name = "Field Generator crate" - contains = list(/obj/machinery/field_generator, - /obj/machinery/field_generator) - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Field Generator crate" - access = access_ce - group = "Engineering" - -/datum/supply_packs/engine/sing_gen - name = "Singularity Generator crate" - contains = list(/obj/machinery/the_singularitygen) - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Singularity Generator crate" - access = access_ce - group = "Engineering" - -/datum/supply_packs/engine/collector - name = "Collector crate" - contains = list(/obj/machinery/power/rad_collector, - /obj/machinery/power/rad_collector, - /obj/machinery/power/rad_collector) - containername = "Collector crate" - group = "Engineering" - -/datum/supply_packs/engine/PA - name = "Particle Accelerator crate" - cost = 40 - contains = list(/obj/structure/particle_accelerator/fuel_chamber, - /obj/machinery/particle_accelerator/control_box, - /obj/structure/particle_accelerator/particle_emitter/center, - /obj/structure/particle_accelerator/particle_emitter/left, - /obj/structure/particle_accelerator/particle_emitter/right, - /obj/structure/particle_accelerator/power_box, - /obj/structure/particle_accelerator/end_cap) - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Particle Accelerator crate" - access = access_ce - group = "Engineering" - -/datum/supply_packs/mecha_ripley - name = "Circuit Crate (\"Ripley\" APLU)" - contains = list(/obj/item/weapon/book/manual/ripley_build_and_repair, - /obj/item/weapon/circuitboard/mecha/ripley/main, //TEMPORARY due to lack of circuitboard printer - /obj/item/weapon/circuitboard/mecha/ripley/peripherals) //TEMPORARY due to lack of circuitboard printer - cost = 30 - containertype = /obj/structure/closet/crate/secure/scisec - containername = "APLU \"Ripley\" Circuit Crate" - access = access_robotics - group = "Engineering" - -/datum/supply_packs/mecha_odysseus - name = "Circuit Crate (\"Odysseus\")" - contains = list(/obj/item/weapon/circuitboard/mecha/odysseus/peripherals, //TEMPORARY due to lack of circuitboard printer - /obj/item/weapon/circuitboard/mecha/odysseus/main) //TEMPORARY due to lack of circuitboard printer - cost = 25 - containertype = /obj/structure/closet/crate/secure/scisec - containername = "\"Odysseus\" Circuit Crate" - access = access_robotics - group = "Engineering" - -/datum/supply_packs/shieldgens - name = "Shield Generators" - contains = list(/obj/machinery/shieldwallgen, - /obj/machinery/shieldwallgen, - /obj/machinery/shieldwallgen, - /obj/machinery/shieldwallgen) - cost = 20 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Shield Generators crate" - access = access_teleporter - group = "Engineering" - -/datum/supply_packs/engine/amrcontrol - name = "Antimatter control unit crate" - contains = list(/obj/machinery/power/am_control_unit) - cost = 30 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Antimatter Control Unit crate" - access = access_engine - group = "Engineering" - -/datum/supply_packs/engine/amrparts - name = "AMR Parts crate" - contains = list(/obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container, - /obj/item/device/am_shielding_container) - cost = 30 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "packaged antimatter reactor crate" - access = access_engine - group = "Engineering" - -/datum/supply_packs/engine/amrcontainment - name = "Antimatter containment jar crate" - contains = list(/obj/item/weapon/am_containment, - /obj/item/weapon/am_containment, - /obj/item/weapon/am_containment) - cost = 15 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Antimatter containment jar crate" - access = access_engine - group = "Engineering" - -/datum/supply_packs/rust_injector - contains = list(/obj/machinery/power/rust_fuel_injector) - name = "R-UST Mk. 7 fuel injector" - cost = 25 - containertype = /obj/structure/closet/crate/secure/large - containername = "R-UST Mk. 7 injector crate" - group = "Engineering" - access = access_engine - -/datum/supply_packs/rust_gyrotron - contains = list(/obj/machinery/rust/gyrotron) - name = "R-UST Mk. 7 gyrotron" - cost = 25 - containertype = /obj/structure/closet/crate/secure/large - containername = "R-UST Mk. 7 gyrotron crate" - group = "Engineering" - access = access_engine - -/datum/supply_packs/rust_compressor - contains = list(/obj/item/weapon/module/rust_fuel_compressor) - name = "R-UST Mk. 7 fuel compressor circuitry" - cost = 30 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "R-UST Mk. 7 fuel compressor circuitry" - group = "Engineering" - access = access_engine - -/datum/supply_packs/rust_assembly_port - contains = list(/obj/item/weapon/module/rust_fuel_port) - name = "R-UST Mk. 7 fuel assembly port circuitry" - cost = 20 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "R-UST Mk. 7 fuel assembly port circuitry" - group = "Engineering" - access = access_engine - -/datum/supply_packs/rust_core - contains = list(/obj/machinery/power/rust_core) - name = "R-UST Mk. 7 Tokamak Core" - cost = 50 - containertype = /obj/structure/closet/crate/secure/large - containername = "R-UST Mk. 7 tokamak crate" - group = "Engineering" - access = access_engine - -/datum/supply_packs/shield_gen - contains = list(/obj/item/weapon/circuitboard/shield_gen) - name = "Experimental shield generator circuitry" - cost = 30 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Experimental shield generator" - group = "Engineering" - access = access_ce - -/datum/supply_packs/shield_cap - contains = list(/obj/item/weapon/circuitboard/shield_cap) - name = "Experimental shield capacitor circuitry" - cost = 30 - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Experimental shield capacitor" - group = "Engineering" - access = access_ce - -/datum/supply_packs/teg - contains = list(/obj/machinery/power/generator) - name = "Mark I Thermoelectric Generator" - cost = 75 - containertype = /obj/structure/closet/crate/secure/large - containername = "Mk1 TEG crate" - group = "Engineering" - access = access_engine - -/datum/supply_packs/circulator - contains = list(/obj/machinery/atmospherics/binary/circulator) - name = "Binary atmospheric circulator" - cost = 60 - containertype = /obj/structure/closet/crate/secure/large - containername = "Atmospheric circulator crate" - group = "Engineering" - access = access_engine - -/datum/supply_packs/supermatter_shard - contains = list(/obj/machinery/power/supermatter/shard) - name = "Supermatter Shard" - cost = 100 //So cargo thinks twice before killing themselves with it - containertype = /obj/structure/closet/crate/secure/engisec - containername = "Supermatter Shard Crate" - group = "Engineering" - access = access_ce - -//////MEDICAL////// - -/datum/supply_packs/medical - name = "Medical crate" - contains = list(/obj/item/weapon/storage/firstaid/regular, - /obj/item/weapon/storage/firstaid/fire, - /obj/item/weapon/storage/firstaid/toxin, - /obj/item/weapon/storage/firstaid/o2, - /obj/item/weapon/reagent_containers/glass/bottle/antitoxin, - /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline, - /obj/item/weapon/reagent_containers/glass/bottle/stoxin, - /obj/item/weapon/storage/box/syringes, - /obj/item/weapon/storage/bag/chem, - /obj/item/weapon/storage/box/autoinjectors) - cost = 10 - containertype = /obj/structure/closet/crate/medical - containername = "Medical crate" - group = "Medical" - -/datum/supply_packs/virus - name = "Virus crate" -/* contains = list(/obj/item/weapon/reagent_containers/glass/bottle/flu_virion, - /obj/item/weapon/reagent_containers/glass/bottle/cold, - /obj/item/weapon/reagent_containers/glass/bottle/epiglottis_virion, - /obj/item/weapon/reagent_containers/glass/bottle/liver_enhance_virion, - /obj/item/weapon/reagent_containers/glass/bottle/fake_gbs, - /obj/item/weapon/reagent_containers/glass/bottle/magnitis, - /obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat, - /obj/item/weapon/reagent_containers/glass/bottle/brainrot, - /obj/item/weapon/reagent_containers/glass/bottle/hullucigen_virion, - /obj/item/weapon/storage/box/syringes, - /obj/item/weapon/storage/box/beakers, - /obj/item/weapon/reagent_containers/glass/bottle/mutagen)*/ - contains = list(/obj/item/weapon/virusdish/random, - /obj/item/weapon/virusdish/random, - /obj/item/weapon/virusdish/random, - /obj/item/weapon/virusdish/random) - cost = 25 - containertype = "/obj/structure/closet/crate/secure" - containername = "Virus crate" - access = access_cmo - group = "Medical" - -/datum/supply_packs/surgery - name = "Surgery crate" - contains = list(/obj/item/weapon/cautery, - /obj/item/weapon/surgicaldrill, - /obj/item/clothing/mask/breath/medical, - /obj/item/weapon/tank/anesthetic, - /obj/item/weapon/FixOVein, - /obj/item/weapon/hemostat, - /obj/item/weapon/scalpel, - /obj/item/weapon/bonegel, - /obj/item/weapon/retractor, - /obj/item/weapon/bonesetter, - /obj/item/weapon/circular_saw) - cost = 25 - containertype = "/obj/structure/closet/crate/secure" - containername = "Surgery crate" - access = access_medical - group = "Medical" - -/datum/supply_packs/sterile - name = "Sterile equipment crate" - contains = list(/obj/item/clothing/under/rank/medical/green, - /obj/item/clothing/under/rank/medical/green, - /obj/item/weapon/storage/box/masks, - /obj/item/weapon/storage/box/gloves) - cost = 15 - containertype = "/obj/structure/closet/crate" - containername = "Sterile equipment crate" - group = "Medical" - -/datum/supply_packs/bloodbags - name = "Bloodbag Crate" - contains = list(/obj/item/weapon/reagent_containers/blood/APlus, - /obj/item/weapon/reagent_containers/blood/AMinus, - /obj/item/weapon/reagent_containers/blood/BPlus, - /obj/item/weapon/reagent_containers/blood/BMinus, - /obj/item/weapon/reagent_containers/blood/OPlus, - /obj/item/weapon/reagent_containers/blood/OMinus, - /obj/item/weapon/reagent_containers/blood/empty) - cost = 10 - containertype = /obj/structure/closet/crate/secure - containername = "Bloodbag Crate" - access = access_medical - group = "Medical" - -/datum/supply_packs/wheelchair - name = "Wheelchair Crate" - contains = list(/obj/structure/bed/chair/vehicle/wheelchair) - cost = 40 - containertype = /obj/structure/closet/crate/medical - containername = "Wheelchair Crate" - group = "Medical" - -/datum/supply_packs/wheelchair_motorized - name = "Motorized Wheelchair Crate" - contains = list(/obj/structure/bed/chair/vehicle/wheelchair/motorized) - cost = 200 - containertype = "/obj/structure/closet/crate/secure" - containername = "Motorized Wheelchair Crate" - access = access_cmo - group = "Medical" - -//////SCIENCE////// - -/datum/supply_packs/research_parts - name = "RnD Stock Parts Crate" - contains = list( - /obj/item/weapon/circuitboard/protolathe, - /obj/item/weapon/circuitboard/rdconsole, - /obj/item/weapon/circuitboard/circuit_imprinter, - /obj/item/weapon/circuitboard/destructive_analyzer, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/micro_laser) - cost = 30 - containertype = /obj/structure/closet/crate/secure/scisec - containername = "RnD Stock Parts Crate" - access = access_research - group = "Science" - -/datum/supply_packs/research_nanotrasen - name = "RnD Experimental Crate" - contains = list( - /obj/item/weapon/disk/tech_disk/nanotrasen, - /obj/item/weapon/paper/tech_nanotrasen, - ) - cost = 80 - containertype = /obj/structure/closet/crate/secure/scisec - containername = "RnD Experimental Crate" - access = access_research - group = "Science" - -/datum/supply_packs/robotics - name = "Robotics Assembly Crate" - contains = list(/obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/prox_sensor, - /obj/item/weapon/storage/toolbox/electrical, - /obj/item/device/flash, - /obj/item/device/flash, - /obj/item/device/flash, - /obj/item/device/flash, - /obj/item/weapon/cell/high, - /obj/item/weapon/cell/high) - cost = 10 - containertype = /obj/structure/closet/crate/secure/scisec - containername = "Robotics Assembly" - access = access_robotics - group = "Science" - -/datum/supply_packs/plasma - name = "Plasma assembly crate" - contains = list(/obj/item/weapon/tank/plasma, - /obj/item/weapon/tank/plasma, - /obj/item/weapon/tank/plasma, - /obj/item/device/assembly/igniter, - /obj/item/device/assembly/igniter, - /obj/item/device/assembly/igniter, - /obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/timer, - /obj/item/device/assembly/timer, - /obj/item/device/assembly/timer) - cost = 10 - containertype = /obj/structure/closet/crate/secure/plasma - containername = "Plasma assembly crate" - access = access_tox_storage - group = "Science" - -/datum/supply_packs/borer - name = "Borer Egg Crate" - contains = list (/obj/item/weapon/reagent_containers/food/snacks/borer_egg) - cost = 100 - containertype = /obj/structure/closet/crate/secure/scisec - containername = "Borer egg crate" - access = access_xenobiology - group = "Science" - -//////HYDROPONICS////// - -/datum/supply_packs/monkey - name = "Monkey crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes) - cost = 20 - containertype = /obj/structure/closet/crate/freezer - containername = "Monkey crate" - group = "Hydroponics" - -/datum/supply_packs/farwa - name = "Farwa crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes/farwacubes) - cost = 30 - containertype = /obj/structure/closet/crate/freezer - containername = "Farwa crate" - group = "Hydroponics" - -/datum/supply_packs/skrell - name = "Neaera crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes/neaeracubes) - cost = 30 - containertype = /obj/structure/closet/crate/freezer - containername = "Neaera crate" - group = "Hydroponics" - -/datum/supply_packs/stok - name = "Stok crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes/stokcubes) - cost = 30 - containertype = /obj/structure/closet/crate/freezer - containername = "Stok crate" - group = "Hydroponics" - -/* Defined below -/datum/supply_packs/lisa - name = "Corgi Crate" - contains = list() - cost = 50 - containertype = /obj/structure/largecrate/lisa - containername = "Corgi Crate" - group = "Hydroponics" */ - -/datum/supply_packs/hydroponics // -- Skie - name = "Hydroponics Supply Crate" - contains = list(/obj/item/weapon/reagent_containers/spray/plantbgone, - /obj/item/weapon/reagent_containers/spray/plantbgone, - /obj/item/weapon/reagent_containers/glass/bottle/ammonia, - /obj/item/weapon/reagent_containers/glass/bottle/ammonia, - /obj/item/weapon/hatchet, - /obj/item/weapon/minihoe, - /obj/item/weapon/minihoe, - /obj/item/device/analyzer/plant_analyzer, - /obj/item/clothing/gloves/botanic_leather, - /obj/item/clothing/suit/apron, // Updated with new things - /obj/item/weapon/storage/box/botanydisk) //Updated with flora disks - cost = 15 - containertype = /obj/structure/closet/crate/hydroponics - containername = "Hydroponics crate" - access = access_hydroponics - group = "Hydroponics" - -//farm animals - useless and annoying, but potentially a good source of food -/datum/supply_packs/cow - name = "Cow Crate" - cost = 30 - containertype = /obj/structure/largecrate/cow - containername = "Cow Crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_packs/goat - name = "Goat Crate" - cost = 25 - containertype = /obj/structure/largecrate/goat - containername = "Goat Crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_packs/chicken - name = "Chicken Crate" - cost = 20 - containertype = /obj/structure/largecrate/chick - containername = "Chicken Crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_packs/lisa - name = "Corgi Crate" - contains = list() - cost = 50 - containertype = /obj/structure/largecrate/lisa - containername = "Corgi Crate" - group = "Hydroponics" - -/datum/supply_packs/weedcontrol - name = "Weed Control Crate" - contains = list(/obj/item/weapon/scythe, - /obj/item/clothing/mask/gas, - /obj/item/weapon/grenade/chem_grenade/antiweed, - /obj/item/weapon/grenade/chem_grenade/antiweed) - cost = 20 - containertype = /obj/structure/closet/crate/secure/hydrosec - containername = "Weed control crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_packs/exoticseeds - name = "Exotic seeds crate" - contains = list(/obj/item/seeds/dionanode, - /obj/item/seeds/dionanode, - /obj/item/seeds/libertymycelium, - /obj/item/seeds/reishimycelium, - /obj/item/seeds/random, - /obj/item/seeds/random, - /obj/item/seeds/random, - /obj/item/seeds/random, - /obj/item/seeds/random, - /obj/item/seeds/random, - /obj/item/seeds/kudzuseed) - cost = 15 - containertype = /obj/structure/closet/crate/secure/hydrosec - containername = "Exotic Seeds crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_packs/bee_keeper - name = "Beekeeping Crate" - contains = list( - /obj/item/beezeez, - /obj/item/beezeez, - /obj/item/weapon/bee_net, - /obj/item/weapon/extinguisher/mini, - /obj/item/apiary, - /obj/item/queen_bee, - /obj/item/queen_bee, - /obj/item/queen_bee, - /obj/item/clothing/suit/bio_suit/beekeeping, - /obj/item/clothing/head/bio_hood/beekeeping, - /obj/item/weapon/book/manual/hydroponics_beekeeping, - ) - cost = 20 - containertype = /obj/structure/closet/crate/secure/hydrosec - containername = "Beekeeping crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_packs/ranching - name = "Ranching Crate" - contains = list( - /obj/item/weapon/circuitboard/egg_incubator, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/kitchen/utensil/knife/large, - /obj/item/clothing/head/cowboy - ) - cost = 15 - containertype = /obj/structure/closet/crate/hydroponics - containername = "Ranching crate" - group = "Hydroponics" - -/datum/supply_packs/Hydroponics_Trays - name = "Hydroponic Trays Components Crate" - contains = list( - /obj/item/weapon/circuitboard/hydroponics, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/circuitboard/hydroponics, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/stock_parts/console_screen) - cost = 12 - containertype = /obj/structure/closet/crate/secure/hydrosec - containername = "Hydroponic Trays Components Crate" - access = access_hydroponics - group = "Hydroponics" - -/////VENDING MACHINES PACKS//////// - -/datum/supply_packs/snackmachines - name = "Snacks n Cigs stack of packs" - contains = list(/obj/structure/vendomatpack/snack, - /obj/structure/vendomatpack/snack, - /obj/structure/vendomatpack/snack, - /obj/structure/vendomatpack/cola, - /obj/structure/vendomatpack/coffee, - /obj/structure/vendomatpack/cigarette) - cost = 30 - containertype = /obj/structure/stackopacks - containername = "Snacks n Cigs stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/snackmachinesalt - name = "Groans n Dan stack of packs" - contains = list(/obj/structure/vendomatpack/discount, - /obj/structure/vendomatpack/discount, - /obj/structure/vendomatpack/groans, - /obj/structure/vendomatpack/groans) - cost = 20 - containertype = /obj/structure/stackopacks - containername = "Groans n Dan stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/hospitalitymachines - name = "Theatre, Bar n Kitchen stack of packs" - contains = list(/obj/structure/vendomatpack/boozeomat, - /obj/structure/vendomatpack/dinnerware, - /obj/structure/vendomatpack/autodrobe) - cost = 15 - containertype = /obj/structure/stackopacks - containername = "Theatre, Bar n Kitchen stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/securitymachines - name = "Security stack of packs" - contains = list(/obj/structure/vendomatpack/security, - /obj/structure/vendomatpack/security) - cost = 10 - containertype = /obj/structure/stackopacks - containername = "Security stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/medbaymachines - name = "Medical stack of packs" - contains = list(/obj/structure/vendomatpack/medical, - /obj/structure/vendomatpack/medical) - cost = 10 - containertype = /obj/structure/stackopacks - containername = "Medical stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/botanymachines - name = "Hydroponics stack of packs" - contains = list(/obj/structure/vendomatpack/hydronutrients, - /obj/structure/vendomatpack/hydroseeds) - cost = 10 - containertype = /obj/structure/stackopacks - containername = "Hydroponics stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/toolsmachines - name = "Tools n Engineering stack of packs" - contains = list(/obj/structure/vendomatpack/tool, - /obj/structure/vendomatpack/tool, - /obj/structure/vendomatpack/assist, - /obj/structure/vendomatpack/engivend) - cost = 20 - containertype = /obj/structure/stackopacks - containername = "Tools n Engineering stack of packs" - group = "Vending Machine packs" - -/datum/supply_packs/clothesmachines - name = "Clothing stack of packs" - contains = list(/obj/structure/vendomatpack/hatdispenser, - /obj/structure/vendomatpack/suitdispenser, - /obj/structure/vendomatpack/shoedispenser) - cost = 15 - containertype = /obj/structure/stackopacks - containername = "Clothing stack of packs" - group = "Vending Machine packs" - -/* -/datum/supply_packs/sovietmachines - name = "Old and Forgotten stack of packs" - contains = list(/obj/structure/vendomatpack/sovietsoda, - /obj/structure/vendomatpack/sovietsoda, - /obj/structure/vendomatpack/nazivend, - /obj/structure/vendomatpack/sovietvend) - cost = 20 - containertype = /obj/structure/stackopacks - containername = "Old and Forgotten stack of packs" - group = "Vending Machine packs" - hidden = 1 -*/ - -/datum/supply_packs/magimachines - name = "Strange and Bright stack of packs" - contains = list(/obj/structure/vendomatpack/magivend) - cost = 80 - containertype = /obj/structure/stackopacks - containername = "Strange and Bright stack of packs" - group = "Vending Machine packs" - hidden = 1 +//SUPPLY PACKS +//NOTE: only secure crate types use the access var (and are lockable) +//NOTE: hidden packs only show up when the computer has been emagged. +//ANOTER NOTE: Contraband is obtainable through modified supplycomp circuitboards. +//BIG NOTE: Don't add living things to crates, that's bad, it will break the shuttle. +//NEW NOTE: Do NOT set the price of any crates below 7 points. Doing so allows infinite points. + +var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality","Engineering","Medical","Science","Hydroponics","Vending Machine packs") + +/datum/supply_packs + var/name = null + var/list/contains = list() + var/manifest = "" + var/amount = null + var/cost = null + var/containertype = null + var/containername = null + var/access = null + var/hidden = 0 //Emaggable + var/contraband = 0 //Hackable via tools + var/group = "Supplies" + +/datum/supply_packs/New() + manifest += "
        " + for(var/path in contains) + if(!path) continue + var/atom/movable/AM = new path() + manifest += "
      • [AM.name]
      • " + AM.loc = null //just to make sure they're deleted by the garbage collector + manifest += "
      " + +//////SUPPLIES////// + +/datum/supply_packs/toner + name = "Toner Cartridges" + contains = list(/obj/item/device/toner, + /obj/item/device/toner, + /obj/item/device/toner, + /obj/item/device/toner, + /obj/item/device/toner, + /obj/item/device/toner) + cost = 10 + containertype = /obj/structure/closet/crate + containername = "Toner Cartridges" + group = "Supplies" + +/datum/supply_packs/labels + name = "Label Rolls" + contains = list(/obj/item/weapon/storage/box/labels, + /obj/item/weapon/storage/box/labels, //21 label rolls is enough to label Beepsky "SHITCURITRON" 375 times, + /obj/item/weapon/storage/box/labels) //so this might be a bit excessive. + cost = 10 + containertype = /obj/structure/closet/crate + containername = "Label Rolls" + group = "Supplies" + +/datum/supply_packs/internals + name = "Internals crate" + contains = list(/obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/weapon/tank/air, + /obj/item/weapon/tank/air, + /obj/item/weapon/tank/air) + cost = 10 + containertype = /obj/structure/closet/crate/internals + containername = "Internals crate" + group = "Supplies" + +/datum/supply_packs/evacuation + name = "Emergency equipment" + contains = list(/obj/item/weapon/storage/toolbox/emergency, + /obj/item/weapon/storage/toolbox/emergency, + /obj/item/clothing/suit/storage/hazardvest, + /obj/item/clothing/suit/storage/hazardvest, + /obj/item/weapon/tank/emergency_oxygen, + /obj/item/weapon/tank/emergency_oxygen, + /obj/item/weapon/tank/emergency_oxygen, + /obj/item/weapon/tank/emergency_oxygen, + /obj/item/weapon/tank/emergency_oxygen, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas, + /obj/machinery/bot/floorbot, + /obj/machinery/bot/floorbot, + /obj/machinery/bot/medbot, + /obj/machinery/bot/medbot) + cost = 40 + containertype = /obj/structure/closet/crate/internals + containername = "Emergency Crate" + group = "Supplies" + +/datum/supply_packs/janitor + name = "Janitorial supplies" + contains = list(/obj/item/weapon/reagent_containers/glass/bucket, + /obj/item/weapon/reagent_containers/glass/bucket, + /obj/item/weapon/reagent_containers/glass/bucket, + /obj/item/weapon/mop, + /obj/item/weapon/caution, + /obj/item/weapon/caution, + /obj/item/weapon/caution, + /obj/item/weapon/storage/bag/trash, + /obj/item/weapon/reagent_containers/spray/cleaner, + /obj/item/weapon/reagent_containers/glass/rag, + /obj/item/weapon/grenade/chem_grenade/cleaner, + /obj/item/weapon/grenade/chem_grenade/cleaner, + /obj/item/weapon/grenade/chem_grenade/cleaner, + /obj/structure/mopbucket) + cost = 10 + containertype = /obj/structure/closet/crate + containername = "Janitorial supplies" + group = "Supplies" + +/datum/supply_packs/lightbulbs + name = "Replacement lights" + contains = list(/obj/item/weapon/storage/box/lights/mixed, + /obj/item/weapon/storage/box/lights/mixed, + /obj/item/weapon/storage/box/lights/mixed) + cost = 10 + containertype = /obj/structure/closet/crate + containername = "Replacement lights" + group = "Supplies" + +/datum/supply_packs/helightbulbs + name = "High efficiency lights" + contains = list(/obj/item/weapon/storage/box/lights/he, + /obj/item/weapon/storage/box/lights/he) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "High efficiency lights" + group = "Supplies" + +/datum/supply_packs/newscaster + name = "Newscaster crate" + contains = list(/obj/item/mounted/frame/newscaster, + /obj/item/mounted/frame/newscaster, + /obj/item/mounted/frame/newscaster) + cost = 10 + containertype = /obj/structure/closet/crate + containername = "Newscaster crate" + group = "Supplies" + +/datum/supply_packs/mule + name = "MULEbot Crate" + contains = list(/obj/machinery/bot/mulebot) + cost = 20 + containertype = /obj/structure/largecrate/mule + containername = "MULEbot Crate" + group = "Supplies" + +/datum/supply_packs/porcelain + name = "Porcelain Crate" + contains = list() + cost = 10 + containertype = /obj/structure/largecrate/porcelain + containername = "Porcelain Crate" + group = "Supplies" + +/datum/supply_packs/metal50 + name = "50 Metal Sheets" + contains = list(/obj/item/stack/sheet/metal) + amount = 50 + cost = 10 + containertype = /obj/structure/closet/crate/engi + containername = "Metal sheets crate" + group = "Supplies" + +/datum/supply_packs/glass50 + name = "50 Glass Sheets" + contains = list(/obj/item/stack/sheet/glass/glass) + amount = 50 + cost = 10 + containertype = /obj/structure/closet/crate/engi + containername = "Glass sheets crate" + group = "Supplies" + +/datum/supply_packs/wood25 + name = "25 Wooden Planks" + contains = list(/obj/item/stack/sheet/wood) + amount = 25 + cost = 12 + containertype = /obj/structure/closet/crate/engi + containername = "Wooden planks crate" + group = "Supplies" + +/datum/supply_packs/carpet + name = "30 Carpet Tiles" + contains = list(/obj/item/stack/tile/carpet) + amount = 30 + cost = 15 + containertype = /obj/structure/closet/crate + containername = "Carpet Crate" + group = "Supplies" + +/datum/supply_packs/arcade + name = "30 Arcade Tiles" + contains = list(/obj/item/stack/tile/arcade) + amount = 30 + cost = 15 + containertype = /obj/structure/closet/crate + containername = "Arcade Tiles Crate" + group = "Supplies" + +/datum/supply_packs/grass + name = "30 Grass Tiles" + contains = list(/obj/item/stack/tile/grass) + amount = 30 + cost = 15 + containertype = /obj/structure/closet/crate + containername = "Grass Crate" + group = "Supplies" + +/datum/supply_packs/watertank + name = "Water tank crate" + contains = list(/obj/structure/reagent_dispensers/watertank) + cost = 8 + containertype = /obj/structure/largecrate + containername = "water tank crate" + group = "Supplies" + +/datum/supply_packs/fueltank + name = "Fuel tank crate" + contains = list(/obj/structure/reagent_dispensers/fueltank) + cost = 8 + containertype = /obj/structure/largecrate + containername = "fuel tank crate" + group = "Supplies" + +/datum/supply_packs/silicatetank + name = "Silicate tank crate" + contains = list(/obj/structure/reagent_dispensers/silicate) + cost = 8 + containertype = /obj/structure/largecrate + containername = "silicate tank crate" + group = "Supplies" + +/datum/supply_packs/mining + name = "Mining Equipment" + contains = list(/obj/item/weapon/pickaxe/drill, + /obj/item/weapon/pickaxe, + /obj/item/weapon/pickaxe, + /obj/item/device/flashlight/lantern, + /obj/item/device/flashlight/lantern, + /obj/item/device/flashlight/lantern, + /obj/item/device/mining_scanner, + /obj/item/weapon/storage/bag/ore, + /obj/item/weapon/storage/bag/ore, + /obj/item/weapon/storage/bag/ore) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Mining Equipment Crate" + access = access_mining + group = "Supplies" + +/datum/supply_packs/artscrafts + name = "Arts and Crafts supplies" + contains = list(/obj/item/weapon/storage/fancy/crayons, + /obj/item/device/camera, + /obj/item/device/camera_film, + /obj/item/device/camera_film, + /obj/item/weapon/storage/photo_album, + /obj/item/stack/package_wrap, + /obj/item/weapon/reagent_containers/glass/paint/red, + /obj/item/weapon/reagent_containers/glass/paint/green, + /obj/item/weapon/reagent_containers/glass/paint/blue, + /obj/item/weapon/reagent_containers/glass/paint/yellow, + /obj/item/weapon/reagent_containers/glass/paint/violet, + /obj/item/weapon/reagent_containers/glass/paint/black, + /obj/item/weapon/reagent_containers/glass/paint/white, + /obj/item/weapon/reagent_containers/glass/paint/remover, + /obj/item/mounted/poster, + /obj/item/stack/package_wrap/gift, + /obj/item/stack/package_wrap/gift, + /obj/item/stack/package_wrap/gift) + cost = 10 + containertype = "/obj/structure/closet/crate" + containername = "Arts and Crafts crate" + group = "Supplies" + + +/datum/supply_packs/randomised/contraband + num_contained = 5 + contains = list(/obj/item/seeds/bloodtomatoseed, + /obj/item/weapon/storage/pill_bottle/zoom, + /obj/item/weapon/storage/pill_bottle/happy, + /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, + /obj/item/weapon/storage/bag/wiz_cards/frog) + + name = "Contraband crate" + cost = 30 + containertype = /obj/structure/closet/crate + containername = "Unlabeled crate" + contraband = 1 + group = "Supplies" + +/datum/supply_packs/boxes + name = "Empty Box supplies" + contains = list(/obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box, + /obj/item/weapon/storage/box) + cost = 10 + containertype = "/obj/structure/closet/crate" + containername = "Empty Box crate" + group = "Supplies" + +/datum/supply_packs/eftpos + contains = list(/obj/item/device/eftpos) + name = "EFTPOS scanner" + cost = 10 + containertype = /obj/structure/closet/crate + containername = "EFTPOS crate" + group = "Supplies" + +//////CLOTHING////// + +/datum/supply_packs/costume + name = "Standard Costume crate" + contains = list(/obj/item/weapon/storage/backpack/clown, + /obj/item/clothing/shoes/clown_shoes, + /obj/item/clothing/mask/gas/clown_hat, + /obj/item/clothing/under/rank/clown, + /obj/item/weapon/bikehorn, + /obj/item/clothing/under/mime, + /obj/item/clothing/shoes/mime, + /obj/item/clothing/gloves/white, + /obj/item/clothing/mask/gas/mime, + /obj/item/clothing/head/beret, + /obj/item/clothing/suit/suspenders, + /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing) + cost = 10 + containertype = /obj/structure/closet/crate/secure + containername = "Standard Costumes" + access = access_theatre + group = "Clothing" + +/datum/supply_packs/wizard + name = "Wizard costume" + contains = list(/obj/item/weapon/staff, + /obj/item/clothing/suit/wizrobe/fake, + /obj/item/clothing/shoes/sandal, + /obj/item/clothing/head/wizard/fake) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Wizard costume crate" + group = "Clothing" + +/datum/supply_packs/randomised + var/num_contained = 3 //number of items picked to be contained in a randomised crate + contains = list(/obj/item/clothing/head/collectable/chef, + /obj/item/clothing/head/collectable/paper, + /obj/item/clothing/head/collectable/tophat, + /obj/item/clothing/head/collectable/captain, + /obj/item/clothing/head/collectable/beret, + /obj/item/clothing/head/collectable/welding, + /obj/item/clothing/head/collectable/flatcap, + /obj/item/clothing/head/collectable/pirate, + /obj/item/clothing/head/collectable/kitty, + /obj/item/clothing/head/collectable/rabbitears, + /obj/item/clothing/head/collectable/wizard, + /obj/item/clothing/head/collectable/hardhat, + /obj/item/clothing/head/collectable/HoS, + /obj/item/clothing/head/collectable/thunderdome, + /obj/item/clothing/head/collectable/swat, + /obj/item/clothing/head/collectable/slime, + /obj/item/clothing/head/collectable/police, + /obj/item/clothing/head/collectable/slime, + /obj/item/clothing/head/collectable/xenom, + /obj/item/clothing/head/collectable/petehat) + name = "Collectable hat crate!" + cost = 200 + containertype = /obj/structure/closet/crate + containername = "Collectable hats crate! Brought to you by Bass.inc!" + group = "Clothing" + +/datum/supply_packs/randomised/New() + manifest += "Contains any [num_contained] of:" + ..() + +/datum/supply_packs/formal_wear + contains = list(/obj/item/clothing/head/that, + /obj/item/clothing/suit/storage/lawyer/bluejacket, + /obj/item/clothing/suit/storage/lawyer/purpjacket, + /obj/item/clothing/under/suit_jacket, + /obj/item/clothing/under/suit_jacket/female, + /obj/item/clothing/under/suit_jacket/really_black, + /obj/item/clothing/under/suit_jacket/red, + /obj/item/clothing/shoes/black, + /obj/item/clothing/shoes/black, + /obj/item/clothing/suit/wcoat) + name = "Formalwear closet" + cost = 30 + containertype = /obj/structure/closet + containername = "Formalwear for the best occasions." + group = "Clothing" + +/datum/supply_packs/waifu + name = "Feminine formalwear" + contains = list(/obj/item/clothing/under/dress/dress_fire, + /obj/item/clothing/under/dress/dress_green, + /obj/item/clothing/under/dress/dress_orange, + /obj/item/clothing/under/dress/dress_pink, + /obj/item/clothing/under/dress/dress_yellow, + /obj/item/clothing/under/dress/dress_saloon, + /obj/item/clothing/under/wedding/bride_orange, + /obj/item/clothing/under/wedding/bride_purple, + /obj/item/clothing/under/wedding/bride_blue, + /obj/item/clothing/under/wedding/bride_red, + /obj/item/clothing/under/wedding/bride_white, + /obj/item/clothing/under/sundress, + /obj/item/weapon/lipstick/random, + /obj/item/weapon/lipstick/random) + cost = 30 + containertype = /obj/structure/closet/crate + containername = "Feminine clothing" + group = "Clothing" + +/datum/supply_packs/knight //why seperate them + name = "Knight Armor Crate" + contains = list(/obj/item/clothing/suit/armor/knight, + /obj/item/clothing/suit/armor/knight/red, + /obj/item/clothing/suit/armor/knight/yellow, + /obj/item/clothing/suit/armor/knight/blue, + /obj/item/clothing/head/helmet/knight, + /obj/item/clothing/head/helmet/knight/red, + /obj/item/clothing/head/helmet/knight/yellow, + /obj/item/clothing/head/helmet/knight/blue) + cost = 35 + containertype = /obj/structure/closet/crate + containername = "knight armor crate" + group = "Clothing" + +//////SECURITY////// + +/datum/supply_packs/specialops + name = "Special Ops supplies" + contains = list(/obj/item/weapon/storage/box/emps, + /obj/item/weapon/grenade/smokebomb, + /obj/item/weapon/grenade/smokebomb, + /obj/item/weapon/grenade/smokebomb, + /obj/item/weapon/pen/paralysis, + /obj/item/weapon/grenade/chem_grenade/incendiary) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Special Ops crate" + group = "Security" + hidden = 1 + +/datum/supply_packs/beanbagammo + name = "Beanbag shells" + contains = list(/obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag, + /obj/item/ammo_casing/shotgun/beanbag) + cost = 10 + containertype = /obj/structure/closet/crate + containername = "Beanbag shells" + group = "Security" + +/datum/supply_packs/weapons + name = "Weapons crate" + contains = list(/obj/item/weapon/melee/baton/loaded, + /obj/item/weapon/melee/baton/loaded, + /obj/item/weapon/gun/energy/laser, + /obj/item/weapon/gun/energy/laser, + /obj/item/weapon/gun/energy/taser, + /obj/item/weapon/gun/energy/taser, + /obj/item/weapon/storage/box/flashbangs, + /obj/item/weapon/storage/box/flashbangs, + /obj/item/weapon/storage/box/bolas) + cost = 30 + containertype = /obj/structure/closet/crate/secure/weapon + containername = "Weapons crate" + access = access_security + group = "Security" + +/datum/supply_packs/eweapons + name = "Incendiary weapons crate" + contains = list(/obj/item/weapon/flamethrower/full, + /obj/item/weapon/tank/plasma, + /obj/item/weapon/tank/plasma, + /obj/item/weapon/tank/plasma, + /obj/item/weapon/grenade/chem_grenade/incendiary, + /obj/item/weapon/grenade/chem_grenade/incendiary, + /obj/item/weapon/grenade/chem_grenade/incendiary) + cost = 25 + containertype = /obj/structure/closet/crate/secure/weapon + containername = "Incendiary weapons crate" + access = access_heads + group = "Security" + +/datum/supply_packs/armor + name = "Armor crate" + contains = list(/obj/item/clothing/head/helmet, + /obj/item/clothing/head/helmet, + /obj/item/clothing/suit/armor/vest, + /obj/item/clothing/suit/armor/vest) + cost = 15 + containertype = /obj/structure/closet/crate/secure + containername = "Armor crate" + access = access_security + group = "Security" + +/datum/supply_packs/riot + name = "Riot gear crate" + contains = list(/obj/item/weapon/melee/baton/loaded, + /obj/item/weapon/melee/baton/loaded, + /obj/item/weapon/melee/baton/loaded, + /obj/item/weapon/shield/riot, + /obj/item/weapon/shield/riot, + /obj/item/weapon/shield/riot, + /obj/item/weapon/storage/box/flashbangs, + /obj/item/weapon/storage/box/flashbangs, + /obj/item/weapon/storage/box/flashbangs, + /obj/item/weapon/handcuffs, + /obj/item/weapon/handcuffs, + /obj/item/weapon/handcuffs, + /obj/item/clothing/head/helmet/riot, + /obj/item/clothing/suit/armor/riot, + /obj/item/clothing/head/helmet/riot, + /obj/item/clothing/suit/armor/riot, + /obj/item/clothing/head/helmet/riot, + /obj/item/clothing/suit/armor/riot, + /obj/item/weapon/storage/box/bolas, + /obj/item/weapon/storage/box/bolas) + cost = 60 + containertype = /obj/structure/closet/crate/secure + containername = "Riot gear crate" + access = access_armory + group = "Security" + +/datum/supply_packs/loyalty + name = "Loyalty implant crate" + contains = list (/obj/item/weapon/storage/lockbox/loyalty) + cost = 60 + containertype = /obj/structure/closet/crate/secure + containername = "Loyalty implant crate" + access = access_armory + group = "Security" + +/datum/supply_packs/tracking + name = "Tracking implant crate" + contains = list (/obj/item/weapon/storage/lockbox/tracking) + cost = 50 + containertype = /obj/structure/closet/crate/secure + containername = "Tracking implant crate" + access = access_armory + group = "Security" + +/datum/supply_packs/chem + name = "Chemical implant crate" + contains = list (/obj/item/weapon/storage/lockbox/chem) + cost = 50 + containertype = /obj/structure/closet/crate/secure + containername = "Chemical implant crate" + access = access_armory + group = "Security" + +/datum/supply_packs/ballistic + name = "Ballistic gear crate" + contains = list(/obj/item/clothing/suit/armor/bulletproof, + /obj/item/clothing/suit/armor/bulletproof, + /obj/item/weapon/gun/projectile/shotgun/pump/combat, + /obj/item/weapon/gun/projectile/shotgun/pump/combat) + cost = 50 + containertype = /obj/structure/closet/crate/secure + containername = "Ballistic gear crate" + access = access_armory + group = "Security" + +/datum/supply_packs/shotgunammo + name = "Shotgun shells" + contains = list(/obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun, + /obj/item/ammo_casing/shotgun) + cost = 20 + containertype = /obj/structure/closet/crate/secure + containername = "Shotgun shells" + access = access_armory + group = "Security" + +/datum/supply_packs/expenergy + name = "Experimental energy gear crate" + contains = list(/obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/suit/armor/laserproof, + /obj/item/weapon/gun/energy/gun, + /obj/item/weapon/gun/energy/gun) + cost = 50 + containertype = /obj/structure/closet/crate/secure + containername = "Experimental energy gear crate" + access = access_armory + group = "Security" + +/datum/supply_packs/exparmor + name = "Experimental armor crate" + contains = list(/obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/suit/armor/bulletproof, + /obj/item/clothing/head/helmet/riot, + /obj/item/clothing/suit/armor/riot) + cost = 35 + containertype = /obj/structure/closet/crate/secure + containername = "Experimental armor crate" + access = access_armory + group = "Security" + +/datum/supply_packs/securitybarriers + name = "Security Checkpoint Equipment" + contains = list(/obj/machinery/deployable/barrier, + /obj/machinery/deployable/barrier, + /obj/machinery/deployable/barrier, + /obj/machinery/deployable/barrier, + /obj/machinery/detector) + cost = 10 + containertype = /obj/structure/closet/crate/secure/gear + containername = "Security Barriers crate" + group = "Security" + +//////HOSPITALITY////// + +/datum/supply_packs/food + name = "Basic cooking crate" + contains = list(/obj/item/weapon/reagent_containers/food/drinks/flour, + /obj/item/weapon/reagent_containers/food/drinks/flour, + /obj/item/weapon/reagent_containers/food/drinks/flour, + /obj/item/weapon/reagent_containers/food/drinks/flour, + /obj/item/weapon/reagent_containers/food/drinks/milk, + /obj/item/weapon/reagent_containers/food/drinks/milk, + /obj/item/weapon/storage/fancy/egg_box) + cost = 10 + containertype = /obj/structure/closet/crate/freezer + containername = "Basic cooking crate" + group = "Hospitality" + +/datum/supply_packs/randomised/fruit + name = "Fruit crate" + num_contained = 16 + contains = list(/obj/item/weapon/reagent_containers/food/snacks/grown/tomato, + /obj/item/weapon/reagent_containers/food/snacks/grown/banana, + /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon, + /obj/item/weapon/reagent_containers/food/snacks/grown/apple, + /obj/item/weapon/reagent_containers/food/snacks/grown/berries, + /obj/item/weapon/reagent_containers/food/snacks/grown/cherries, + /obj/item/weapon/reagent_containers/food/snacks/grown/grapes, + /obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes, + /obj/item/weapon/reagent_containers/food/snacks/grown/lime, + /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, + /obj/item/weapon/reagent_containers/food/snacks/grown/orange) + cost = 20 + containertype = /obj/structure/closet/crate/freezer + containername = "Fruit crate" + group = "Hospitality" + +/datum/supply_packs/exotic_garnishes //We don't use a randomised crate because we want some special reagents, and also to control chances + name = "Exotic garnishes" + contains = list(/obj/item/weapon/reagent_containers/food/condiment/exotic, + /obj/item/weapon/reagent_containers/food/condiment/exotic, + /obj/item/weapon/reagent_containers/food/condiment/exotic, + /obj/item/weapon/reagent_containers/food/condiment/exotic, + /obj/item/weapon/reagent_containers/food/condiment/exotic, + /obj/item/weapon/reagent_containers/food/condiment/exotic) + cost = 15 + containertype = /obj/structure/closet/crate/secure + containername = "Exotic garnishes" + access = access_kitchen + group = "Hospitality" + +/datum/supply_packs/randomised/trophy_meats + name = "Trophy meats" + num_contained = 8 + contains = list(/obj/item/weapon/reagent_containers/food/snacks/meat/mimic, + /obj/item/weapon/reagent_containers/food/snacks/meat/bearmeat, + /obj/item/weapon/reagent_containers/food/snacks/meat/spidermeat, + /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat, + /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat/imitation, + /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken, + /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, + /obj/item/weapon/reagent_containers/food/snacks/meat/spiderleg, + /obj/item/weapon/reagent_containers/food/snacks/spidereggs) + cost = 30 + containertype = /obj/structure/closet/crate/secure + containername = "Trophy meats" + access = access_kitchen + group = "Hospitality" + +/datum/supply_packs/party + name = "Party equipment" + contains = list(/obj/item/weapon/storage/box/drinkingglasses, + /obj/item/weapon/reagent_containers/food/drinks/shaker, + /obj/item/weapon/reagent_containers/food/drinks/bottle/patron, + /obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager, + /obj/item/weapon/storage/fancy/cigarettes/dromedaryco, + /obj/item/weapon/lipstick/random, + /obj/item/weapon/reagent_containers/food/drinks/ale, + /obj/item/weapon/reagent_containers/food/drinks/ale, + /obj/item/weapon/reagent_containers/food/drinks/beer, + /obj/item/weapon/reagent_containers/food/drinks/beer, + /obj/item/weapon/reagent_containers/food/drinks/beer, + /obj/item/weapon/reagent_containers/food/drinks/beer, + /obj/item/device/maracas, + /obj/item/device/maracas) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Party equipment" + group = "Hospitality" + +/datum/supply_packs/randomised/pizza + num_contained = 5 + contains = list(/obj/item/pizzabox/margherita, + /obj/item/pizzabox/mushroom, + /obj/item/pizzabox/meat, + /obj/item/pizzabox/vegetable) + name = "Surprise pack of five pizzas" + cost = 75 + containertype = /obj/structure/closet/crate/freezer + containername = "Pizza crate" + group = "Hospitality" + +/datum/supply_packs/cafe + name = "Cafe equipment" + contains = list(/obj/item/weapon/circuitboard/chem_dispenser/brewer, + /obj/item/weapon/storage/box/mugs, + /obj/item/weapon/storage/box/mugs, + /obj/item/weapon/reagent_containers/glass/kettle/red) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Cafe equipment" + group = "Hospitality" + +/datum/supply_packs/bar + name = "Advanced Bartending equipment" + contains = list(/obj/item/weapon/circuitboard/chem_dispenser/soda_dispenser, + /obj/item/weapon/circuitboard/chem_dispenser/booze_dispenser, + /obj/item/weapon/storage/box/drinkingglasses, + /obj/item/weapon/storage/box/drinkingglasses, + /obj/item/weapon/reagent_containers/food/drinks/shaker) + cost = 40 + containertype = /obj/structure/closet/crate + containername = "Bartending equipment" + group = "Hospitality" + +/datum/supply_packs/festive + name = "Festive supplies" + contains = list(/obj/item/stack/package_wrap/gift, + /obj/item/stack/package_wrap/gift, + /obj/item/weapon/toy/xmas_cracker, + /obj/item/weapon/toy/xmas_cracker, + /obj/item/weapon/toy/xmas_cracker, + /obj/item/weapon/toy/xmas_cracker, + /obj/item/weapon/toy/xmas_cracker, + /obj/item/weapon/toy/xmas_cracker, + /obj/item/clothing/head/christmas/santahat/red, + /obj/item/clothing/head/christmas/santahat/green, + /obj/item/clothing/suit/jumper/christmas/red, + /obj/item/clothing/suit/jumper/christmas/green, + /obj/item/clothing/suit/jumper/christmas/blue, + /obj/item/clothing/mask/scarf/red, + /obj/item/clothing/mask/scarf/blue, + /obj/item/clothing/mask/scarf/green) + cost = 30 + containertype = /obj/structure/closet/crate + containername = "Festivus supplies" + group = "Hospitality" + + +//////ENGINEERING////// + +/datum/supply_packs/electrical + name = "Electrical maintenance crate" + contains = list(/obj/item/weapon/storage/toolbox/electrical, + /obj/item/weapon/storage/toolbox/electrical, + /obj/item/clothing/gloves/yellow, + /obj/item/clothing/gloves/yellow, + /obj/item/weapon/cell, + /obj/item/weapon/cell, + /obj/item/weapon/cell/high, + /obj/item/weapon/cell/high) + cost = 15 + containertype = /obj/structure/closet/crate/engi + containername = "Electrical maintenance crate" + group = "Engineering" + +/datum/supply_packs/mechanical + name = "Mechanical maintenance crate" + contains = list(/obj/item/weapon/storage/belt/utility/full, + /obj/item/weapon/storage/belt/utility/full, + /obj/item/weapon/storage/belt/utility/full, + /obj/item/clothing/suit/storage/hazardvest, + /obj/item/clothing/suit/storage/hazardvest, + /obj/item/clothing/suit/storage/hazardvest, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/hardhat) + cost = 10 + containertype = /obj/structure/closet/crate/engi + containername = "Mechanical maintenance crate" + group = "Engineering" + +/datum/supply_packs/solar + name = "Solar Pack crate" + contains = list(/obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, + /obj/machinery/power/solar_assembly, //21 Solar Assemblies. 1 Extra for the controller + /obj/item/weapon/circuitboard/solar_control, + /obj/item/weapon/tracker_electronics, + /obj/item/weapon/paper/solar) + cost = 20 + containertype = /obj/structure/closet/crate/engi + containername = "solar pack crate" + group = "Engineering" + +/datum/supply_packs/engine + name = "Emitter crate" + contains = list(/obj/machinery/power/emitter, + /obj/machinery/power/emitter) + cost = 10 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Emitter crate" + access = access_ce + group = "Engineering" + +/datum/supply_packs/engine/field_gen + name = "Field Generator crate" + contains = list(/obj/machinery/field_generator, + /obj/machinery/field_generator) + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Field Generator crate" + access = access_ce + group = "Engineering" + +/datum/supply_packs/engine/sing_gen + name = "Singularity Generator crate" + contains = list(/obj/machinery/the_singularitygen) + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Singularity Generator crate" + access = access_ce + group = "Engineering" + +/datum/supply_packs/engine/collector + name = "Collector crate" + contains = list(/obj/machinery/power/rad_collector, + /obj/machinery/power/rad_collector, + /obj/machinery/power/rad_collector) + containername = "Collector crate" + group = "Engineering" + +/datum/supply_packs/engine/PA + name = "Particle Accelerator crate" + cost = 40 + contains = list(/obj/structure/particle_accelerator/fuel_chamber, + /obj/machinery/particle_accelerator/control_box, + /obj/structure/particle_accelerator/particle_emitter/center, + /obj/structure/particle_accelerator/particle_emitter/left, + /obj/structure/particle_accelerator/particle_emitter/right, + /obj/structure/particle_accelerator/power_box, + /obj/structure/particle_accelerator/end_cap) + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Particle Accelerator crate" + access = access_ce + group = "Engineering" + +/datum/supply_packs/mecha_ripley + name = "Circuit Crate (\"Ripley\" APLU)" + contains = list(/obj/item/weapon/book/manual/ripley_build_and_repair, + /obj/item/weapon/circuitboard/mecha/ripley/main, //TEMPORARY due to lack of circuitboard printer + /obj/item/weapon/circuitboard/mecha/ripley/peripherals) //TEMPORARY due to lack of circuitboard printer + cost = 30 + containertype = /obj/structure/closet/crate/secure/scisec + containername = "APLU \"Ripley\" Circuit Crate" + access = access_robotics + group = "Engineering" + +/datum/supply_packs/mecha_odysseus + name = "Circuit Crate (\"Odysseus\")" + contains = list(/obj/item/weapon/circuitboard/mecha/odysseus/peripherals, //TEMPORARY due to lack of circuitboard printer + /obj/item/weapon/circuitboard/mecha/odysseus/main) //TEMPORARY due to lack of circuitboard printer + cost = 25 + containertype = /obj/structure/closet/crate/secure/scisec + containername = "\"Odysseus\" Circuit Crate" + access = access_robotics + group = "Engineering" + +/datum/supply_packs/shieldgens + name = "Shield Generators" + contains = list(/obj/machinery/shieldwallgen, + /obj/machinery/shieldwallgen, + /obj/machinery/shieldwallgen, + /obj/machinery/shieldwallgen) + cost = 20 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Shield Generators crate" + access = access_teleporter + group = "Engineering" + +/datum/supply_packs/engine/amrcontrol + name = "Antimatter control unit crate" + contains = list(/obj/machinery/power/am_control_unit) + cost = 30 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Antimatter Control Unit crate" + access = access_engine + group = "Engineering" + +/datum/supply_packs/engine/amrparts + name = "AMR Parts crate" + contains = list(/obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container, + /obj/item/device/am_shielding_container) + cost = 30 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "packaged antimatter reactor crate" + access = access_engine + group = "Engineering" + +/datum/supply_packs/engine/amrcontainment + name = "Antimatter containment jar crate" + contains = list(/obj/item/weapon/am_containment, + /obj/item/weapon/am_containment, + /obj/item/weapon/am_containment) + cost = 15 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Antimatter containment jar crate" + access = access_engine + group = "Engineering" + +/datum/supply_packs/rust_injector + contains = list(/obj/machinery/power/rust_fuel_injector) + name = "R-UST Mk. 7 fuel injector" + cost = 25 + containertype = /obj/structure/closet/crate/secure/large + containername = "R-UST Mk. 7 injector crate" + group = "Engineering" + access = access_engine + +/datum/supply_packs/rust_gyrotron + contains = list(/obj/machinery/rust/gyrotron) + name = "R-UST Mk. 7 gyrotron" + cost = 25 + containertype = /obj/structure/closet/crate/secure/large + containername = "R-UST Mk. 7 gyrotron crate" + group = "Engineering" + access = access_engine + +/datum/supply_packs/rust_compressor + contains = list(/obj/item/weapon/module/rust_fuel_compressor) + name = "R-UST Mk. 7 fuel compressor circuitry" + cost = 30 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "R-UST Mk. 7 fuel compressor circuitry" + group = "Engineering" + access = access_engine + +/datum/supply_packs/rust_assembly_port + contains = list(/obj/item/weapon/module/rust_fuel_port) + name = "R-UST Mk. 7 fuel assembly port circuitry" + cost = 20 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "R-UST Mk. 7 fuel assembly port circuitry" + group = "Engineering" + access = access_engine + +/datum/supply_packs/rust_core + contains = list(/obj/machinery/power/rust_core) + name = "R-UST Mk. 7 Tokamak Core" + cost = 50 + containertype = /obj/structure/closet/crate/secure/large + containername = "R-UST Mk. 7 tokamak crate" + group = "Engineering" + access = access_engine + +/datum/supply_packs/shield_gen + contains = list(/obj/item/weapon/circuitboard/shield_gen) + name = "Experimental shield generator circuitry" + cost = 30 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Experimental shield generator" + group = "Engineering" + access = access_ce + +/datum/supply_packs/shield_cap + contains = list(/obj/item/weapon/circuitboard/shield_cap) + name = "Experimental shield capacitor circuitry" + cost = 30 + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Experimental shield capacitor" + group = "Engineering" + access = access_ce + +/datum/supply_packs/teg + contains = list(/obj/machinery/power/generator) + name = "Mark I Thermoelectric Generator" + cost = 75 + containertype = /obj/structure/closet/crate/secure/large + containername = "Mk1 TEG crate" + group = "Engineering" + access = access_engine + +/datum/supply_packs/circulator + contains = list(/obj/machinery/atmospherics/binary/circulator) + name = "Binary atmospheric circulator" + cost = 60 + containertype = /obj/structure/closet/crate/secure/large + containername = "Atmospheric circulator crate" + group = "Engineering" + access = access_engine + +/datum/supply_packs/supermatter_shard + contains = list(/obj/machinery/power/supermatter/shard) + name = "Supermatter Shard" + cost = 100 //So cargo thinks twice before killing themselves with it + containertype = /obj/structure/closet/crate/secure/engisec + containername = "Supermatter Shard Crate" + group = "Engineering" + access = access_ce + +//////MEDICAL////// + +/datum/supply_packs/medical + name = "Medical crate" + contains = list(/obj/item/weapon/storage/firstaid/regular, + /obj/item/weapon/storage/firstaid/fire, + /obj/item/weapon/storage/firstaid/toxin, + /obj/item/weapon/storage/firstaid/o2, + /obj/item/weapon/reagent_containers/glass/bottle/antitoxin, + /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline, + /obj/item/weapon/reagent_containers/glass/bottle/stoxin, + /obj/item/weapon/storage/box/syringes, + /obj/item/weapon/storage/bag/chem, + /obj/item/weapon/storage/box/autoinjectors) + cost = 10 + containertype = /obj/structure/closet/crate/medical + containername = "Medical crate" + group = "Medical" + +/datum/supply_packs/virus + name = "Virus crate" +/* contains = list(/obj/item/weapon/reagent_containers/glass/bottle/flu_virion, + /obj/item/weapon/reagent_containers/glass/bottle/cold, + /obj/item/weapon/reagent_containers/glass/bottle/epiglottis_virion, + /obj/item/weapon/reagent_containers/glass/bottle/liver_enhance_virion, + /obj/item/weapon/reagent_containers/glass/bottle/fake_gbs, + /obj/item/weapon/reagent_containers/glass/bottle/magnitis, + /obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat, + /obj/item/weapon/reagent_containers/glass/bottle/brainrot, + /obj/item/weapon/reagent_containers/glass/bottle/hullucigen_virion, + /obj/item/weapon/storage/box/syringes, + /obj/item/weapon/storage/box/beakers, + /obj/item/weapon/reagent_containers/glass/bottle/mutagen)*/ + contains = list(/obj/item/weapon/virusdish/random, + /obj/item/weapon/virusdish/random, + /obj/item/weapon/virusdish/random, + /obj/item/weapon/virusdish/random) + cost = 25 + containertype = "/obj/structure/closet/crate/secure" + containername = "Virus crate" + access = access_cmo + group = "Medical" + +/datum/supply_packs/surgery + name = "Surgery crate" + contains = list(/obj/item/weapon/cautery, + /obj/item/weapon/surgicaldrill, + /obj/item/clothing/mask/breath/medical, + /obj/item/weapon/tank/anesthetic, + /obj/item/weapon/FixOVein, + /obj/item/weapon/hemostat, + /obj/item/weapon/scalpel, + /obj/item/weapon/bonegel, + /obj/item/weapon/retractor, + /obj/item/weapon/bonesetter, + /obj/item/weapon/circular_saw) + cost = 25 + containertype = "/obj/structure/closet/crate/secure" + containername = "Surgery crate" + access = access_medical + group = "Medical" + +/datum/supply_packs/sterile + name = "Sterile equipment crate" + contains = list(/obj/item/clothing/under/rank/medical/green, + /obj/item/clothing/under/rank/medical/green, + /obj/item/weapon/storage/box/masks, + /obj/item/weapon/storage/box/gloves) + cost = 15 + containertype = "/obj/structure/closet/crate" + containername = "Sterile equipment crate" + group = "Medical" + +/datum/supply_packs/bloodbags + name = "Bloodbag Crate" + contains = list(/obj/item/weapon/reagent_containers/blood/APlus, + /obj/item/weapon/reagent_containers/blood/AMinus, + /obj/item/weapon/reagent_containers/blood/BPlus, + /obj/item/weapon/reagent_containers/blood/BMinus, + /obj/item/weapon/reagent_containers/blood/OPlus, + /obj/item/weapon/reagent_containers/blood/OMinus, + /obj/item/weapon/reagent_containers/blood/empty) + cost = 10 + containertype = /obj/structure/closet/crate/secure + containername = "Bloodbag Crate" + access = access_medical + group = "Medical" + +/datum/supply_packs/wheelchair + name = "Wheelchair Crate" + contains = list(/obj/structure/bed/chair/vehicle/wheelchair) + cost = 40 + containertype = /obj/structure/closet/crate/medical + containername = "Wheelchair Crate" + group = "Medical" + +/datum/supply_packs/wheelchair_motorized + name = "Motorized Wheelchair Crate" + contains = list(/obj/structure/bed/chair/vehicle/wheelchair/motorized) + cost = 200 + containertype = "/obj/structure/closet/crate/secure" + containername = "Motorized Wheelchair Crate" + access = access_cmo + group = "Medical" + +//////SCIENCE////// + +/datum/supply_packs/research_parts + name = "RnD Stock Parts Crate" + contains = list( + /obj/item/weapon/circuitboard/protolathe, + /obj/item/weapon/circuitboard/rdconsole, + /obj/item/weapon/circuitboard/circuit_imprinter, + /obj/item/weapon/circuitboard/destructive_analyzer, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/micro_laser) + cost = 30 + containertype = /obj/structure/closet/crate/secure/scisec + containername = "RnD Stock Parts Crate" + access = access_research + group = "Science" + +/datum/supply_packs/research_nanotrasen + name = "RnD Experimental Crate" + contains = list( + /obj/item/weapon/disk/tech_disk/nanotrasen, + /obj/item/weapon/paper/tech_nanotrasen, + ) + cost = 80 + containertype = /obj/structure/closet/crate/secure/scisec + containername = "RnD Experimental Crate" + access = access_research + group = "Science" + +/datum/supply_packs/robotics + name = "Robotics Assembly Crate" + contains = list(/obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/prox_sensor, + /obj/item/weapon/storage/toolbox/electrical, + /obj/item/device/flash, + /obj/item/device/flash, + /obj/item/device/flash, + /obj/item/device/flash, + /obj/item/weapon/cell/high, + /obj/item/weapon/cell/high) + cost = 10 + containertype = /obj/structure/closet/crate/secure/scisec + containername = "Robotics Assembly" + access = access_robotics + group = "Science" + +/datum/supply_packs/plasma + name = "Plasma assembly crate" + contains = list(/obj/item/weapon/tank/plasma, + /obj/item/weapon/tank/plasma, + /obj/item/weapon/tank/plasma, + /obj/item/device/assembly/igniter, + /obj/item/device/assembly/igniter, + /obj/item/device/assembly/igniter, + /obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/timer, + /obj/item/device/assembly/timer, + /obj/item/device/assembly/timer) + cost = 10 + containertype = /obj/structure/closet/crate/secure/plasma + containername = "Plasma assembly crate" + access = access_tox_storage + group = "Science" + +/datum/supply_packs/borer + name = "Borer Egg Crate" + contains = list (/obj/item/weapon/reagent_containers/food/snacks/borer_egg) + cost = 100 + containertype = /obj/structure/closet/crate/secure/scisec + containername = "Borer egg crate" + access = access_xenobiology + group = "Science" + +//////HYDROPONICS////// + +/datum/supply_packs/monkey + name = "Monkey crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes) + cost = 20 + containertype = /obj/structure/closet/crate/freezer + containername = "Monkey crate" + group = "Hydroponics" + +/datum/supply_packs/farwa + name = "Farwa crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes/farwacubes) + cost = 30 + containertype = /obj/structure/closet/crate/freezer + containername = "Farwa crate" + group = "Hydroponics" + +/datum/supply_packs/skrell + name = "Neaera crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes/neaeracubes) + cost = 30 + containertype = /obj/structure/closet/crate/freezer + containername = "Neaera crate" + group = "Hydroponics" + +/datum/supply_packs/stok + name = "Stok crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes/stokcubes) + cost = 30 + containertype = /obj/structure/closet/crate/freezer + containername = "Stok crate" + group = "Hydroponics" + +/* Defined below +/datum/supply_packs/lisa + name = "Corgi Crate" + contains = list() + cost = 50 + containertype = /obj/structure/largecrate/lisa + containername = "Corgi Crate" + group = "Hydroponics" */ + +/datum/supply_packs/hydroponics // -- Skie + name = "Hydroponics Supply Crate" + contains = list(/obj/item/weapon/reagent_containers/spray/plantbgone, + /obj/item/weapon/reagent_containers/spray/plantbgone, + /obj/item/weapon/reagent_containers/glass/bottle/ammonia, + /obj/item/weapon/reagent_containers/glass/bottle/ammonia, + /obj/item/weapon/hatchet, + /obj/item/weapon/minihoe, + /obj/item/weapon/minihoe, + /obj/item/device/analyzer/plant_analyzer, + /obj/item/clothing/gloves/botanic_leather, + /obj/item/clothing/suit/apron, // Updated with new things + /obj/item/weapon/storage/box/botanydisk) //Updated with flora disks + cost = 15 + containertype = /obj/structure/closet/crate/hydroponics + containername = "Hydroponics crate" + access = access_hydroponics + group = "Hydroponics" + +//farm animals - useless and annoying, but potentially a good source of food +/datum/supply_packs/cow + name = "Cow Crate" + cost = 30 + containertype = /obj/structure/largecrate/cow + containername = "Cow Crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_packs/goat + name = "Goat Crate" + cost = 25 + containertype = /obj/structure/largecrate/goat + containername = "Goat Crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_packs/chicken + name = "Chicken Crate" + cost = 20 + containertype = /obj/structure/largecrate/chick + containername = "Chicken Crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_packs/lisa + name = "Corgi Crate" + contains = list() + cost = 50 + containertype = /obj/structure/largecrate/lisa + containername = "Corgi Crate" + group = "Hydroponics" + +/datum/supply_packs/weedcontrol + name = "Weed Control Crate" + contains = list(/obj/item/weapon/scythe, + /obj/item/clothing/mask/gas, + /obj/item/weapon/grenade/chem_grenade/antiweed, + /obj/item/weapon/grenade/chem_grenade/antiweed) + cost = 20 + containertype = /obj/structure/closet/crate/secure/hydrosec + containername = "Weed control crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_packs/exoticseeds + name = "Exotic seeds crate" + contains = list(/obj/item/seeds/dionanode, + /obj/item/seeds/dionanode, + /obj/item/seeds/libertymycelium, + /obj/item/seeds/reishimycelium, + /obj/item/seeds/random, + /obj/item/seeds/random, + /obj/item/seeds/random, + /obj/item/seeds/random, + /obj/item/seeds/random, + /obj/item/seeds/random, + /obj/item/seeds/kudzuseed) + cost = 15 + containertype = /obj/structure/closet/crate/secure/hydrosec + containername = "Exotic Seeds crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_packs/bee_keeper + name = "Beekeeping Crate" + contains = list( + /obj/item/beezeez, + /obj/item/beezeez, + /obj/item/weapon/bee_net, + /obj/item/weapon/extinguisher/mini, + /obj/item/apiary, + /obj/item/queen_bee, + /obj/item/queen_bee, + /obj/item/queen_bee, + /obj/item/clothing/suit/bio_suit/beekeeping, + /obj/item/clothing/head/bio_hood/beekeeping, + /obj/item/weapon/book/manual/hydroponics_beekeeping, + ) + cost = 20 + containertype = /obj/structure/closet/crate/secure/hydrosec + containername = "Beekeeping crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_packs/ranching + name = "Ranching Crate" + contains = list( + /obj/item/weapon/circuitboard/egg_incubator, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/kitchen/utensil/knife/large, + /obj/item/clothing/head/cowboy + ) + cost = 15 + containertype = /obj/structure/closet/crate/hydroponics + containername = "Ranching crate" + group = "Hydroponics" + +/datum/supply_packs/Hydroponics_Trays + name = "Hydroponic Trays Components Crate" + contains = list( + /obj/item/weapon/circuitboard/hydroponics, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/circuitboard/hydroponics, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/stock_parts/console_screen) + cost = 12 + containertype = /obj/structure/closet/crate/secure/hydrosec + containername = "Hydroponic Trays Components Crate" + access = access_hydroponics + group = "Hydroponics" + +/////VENDING MACHINES PACKS//////// + +/datum/supply_packs/snackmachines + name = "Snacks n Cigs stack of packs" + contains = list(/obj/structure/vendomatpack/snack, + /obj/structure/vendomatpack/snack, + /obj/structure/vendomatpack/snack, + /obj/structure/vendomatpack/cola, + /obj/structure/vendomatpack/coffee, + /obj/structure/vendomatpack/cigarette) + cost = 30 + containertype = /obj/structure/stackopacks + containername = "Snacks n Cigs stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/snackmachinesalt + name = "Groans n Dan stack of packs" + contains = list(/obj/structure/vendomatpack/discount, + /obj/structure/vendomatpack/discount, + /obj/structure/vendomatpack/groans, + /obj/structure/vendomatpack/groans) + cost = 20 + containertype = /obj/structure/stackopacks + containername = "Groans n Dan stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/hospitalitymachines + name = "Theatre, Bar n Kitchen stack of packs" + contains = list(/obj/structure/vendomatpack/boozeomat, + /obj/structure/vendomatpack/dinnerware, + /obj/structure/vendomatpack/autodrobe) + cost = 15 + containertype = /obj/structure/stackopacks + containername = "Theatre, Bar n Kitchen stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/securitymachines + name = "Security stack of packs" + contains = list(/obj/structure/vendomatpack/security, + /obj/structure/vendomatpack/security) + cost = 10 + containertype = /obj/structure/stackopacks + containername = "Security stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/medbaymachines + name = "Medical stack of packs" + contains = list(/obj/structure/vendomatpack/medical, + /obj/structure/vendomatpack/medical) + cost = 10 + containertype = /obj/structure/stackopacks + containername = "Medical stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/botanymachines + name = "Hydroponics stack of packs" + contains = list(/obj/structure/vendomatpack/hydronutrients, + /obj/structure/vendomatpack/hydroseeds) + cost = 10 + containertype = /obj/structure/stackopacks + containername = "Hydroponics stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/toolsmachines + name = "Tools n Engineering stack of packs" + contains = list(/obj/structure/vendomatpack/tool, + /obj/structure/vendomatpack/tool, + /obj/structure/vendomatpack/assist, + /obj/structure/vendomatpack/engivend) + cost = 20 + containertype = /obj/structure/stackopacks + containername = "Tools n Engineering stack of packs" + group = "Vending Machine packs" + +/datum/supply_packs/clothesmachines + name = "Clothing stack of packs" + contains = list(/obj/structure/vendomatpack/hatdispenser, + /obj/structure/vendomatpack/suitdispenser, + /obj/structure/vendomatpack/shoedispenser) + cost = 15 + containertype = /obj/structure/stackopacks + containername = "Clothing stack of packs" + group = "Vending Machine packs" + +/* +/datum/supply_packs/sovietmachines + name = "Old and Forgotten stack of packs" + contains = list(/obj/structure/vendomatpack/sovietsoda, + /obj/structure/vendomatpack/sovietsoda, + /obj/structure/vendomatpack/nazivend, + /obj/structure/vendomatpack/sovietvend) + cost = 20 + containertype = /obj/structure/stackopacks + containername = "Old and Forgotten stack of packs" + group = "Vending Machine packs" + hidden = 1 +*/ + +/datum/supply_packs/magimachines + name = "Strange and Bright stack of packs" + contains = list(/obj/structure/vendomatpack/magivend) + cost = 80 + containertype = /obj/structure/stackopacks + containername = "Strange and Bright stack of packs" + group = "Vending Machine packs" + hidden = 1 diff --git a/code/datums/wires/jukebox.dm b/code/datums/wires/jukebox.dm index a1b0accbd72..2d5d244ab2b 100644 --- a/code/datums/wires/jukebox.dm +++ b/code/datums/wires/jukebox.dm @@ -1,93 +1,93 @@ -#define JUKEMODE_PLAY_ONCE 3 - -/datum/wires/jukebox - holder_type = /obj/machinery/media/jukebox - wire_count = 8 - var/interference = 0 //Caused by pulsing the transmit wire - var/last = 0 //Value of the last JukeWire we pulsed - var/list/freq_config_data = list(0,0,0,0) //Set up in new - -/datum/wires/jukebox/New(var/atom/holder) - ..() - last = rand(1,14) - freq_config_data[JUKE_POWER_ONE] = rand(1,14) - freq_config_data[JUKE_POWER_TWO] = rand(1,14) - freq_config_data[JUKE_POWER_THREE] = rand(1,14) - -var/const/JUKE_POWER_ONE = 1 //Power. Cut for shock and off. Pulse toggles. -var/const/JUKE_POWER_TWO = 2 //Power. Cut for shock and off. Pulse toggles. -var/const/JUKE_POWER_THREE = 4 //Power. Cut for shock and off. Pulse toggles. -var/const/JUKE_SHUFFLE = 8 //Cut to disable shuffle and move to play_once. Pulse immediately shuffles. -var/const/JUKE_CAPITAL = 16 //Cut to disable song picking. Pulse randomizes song pick price 1-10. -var/const/JUKE_TRANSMIT = 32 //Cut shocks and disables multitool. Pulse emits burst of rads. -var/const/JUKE_CONFIG = 64 //Cut emags. Pulse plays IAMERROR.ogg -var/const/JUKE_SETTING = 128 //Cut shocks. Pulse toggles settings menu. - -/datum/wires/jukebox/CanUse(var/mob/living/L) - var/obj/machinery/media/jukebox/J = holder - if(J.panel_open) - return 1 - return 0 - -/datum/wires/jukebox/GetInteractWindow() - var/obj/machinery/media/jukebox/J = holder - . += ..() - . += {"
      The decorative tube with bubbles is [!J.any_power_cut() ? "glowing" : "dim"].
      - The green slider bar is [!IsIndexCut(JUKE_TRANSMIT) ? "modulating around full" : "empty"].
      - The maintenance button is [J.access_unlocked ? "lit" : "off"].
      - An unlabelled light is [J.emagged ? "dark" : "blinking occasionally"].
      "} - -/datum/wires/jukebox/UpdatePulsed(var/index) - if(interference) return - var/obj/machinery/media/jukebox/J = holder - switch(index) - if(JUKE_POWER_ONE,JUKE_POWER_TWO,JUKE_POWER_THREE) - J.playing=!J.playing - J.update_music() - J.update_icon() - var/calc = freq_config_data[index] - last - J.visible_message("[J] hums and outputs: [calc]") - last = freq_config_data[index] - if(JUKE_SHUFFLE) - J.current_song=rand(1,J.playlist.len) - if(JUKE_CAPITAL) - J.change_cost = rand(0,20) - if(JUKE_TRANSMIT) - J.rad_pulse() - interference = 1 - sleep(50) - interference = 0 - if(JUKE_CONFIG) - playsound(J.loc, 'sound/effects/IAMERROR.ogg', 100, 1) - if(JUKE_SETTING) - J.access_unlocked = !J.access_unlocked - -/datum/wires/jukebox/UpdateCut(var/index, var/mended) - var/obj/machinery/media/jukebox/J = holder - switch(index) - if(JUKE_POWER_ONE,JUKE_POWER_TWO,JUKE_POWER_THREE) - J.power_change() - J.shock(usr, 50) - if(freq_config_data[index]==0) - freq_config_data[index] = 14 - else - freq_config_data[index] -= 1 - if(JUKE_SHUFFLE) - if(IsIndexCut(JUKE_SHUFFLE)) - J.allowed_modes = list(2 = "Single", 3 = "Once") - J.loop_mode = JUKEMODE_PLAY_ONCE //Dammit Comic you're relentless there's no reason to define something for one use - else - J.allowed_modes = loopModeNames.Copy() - if(JUKE_TRANSMIT) - J.shock(usr, 50) - if(IsIndexCut(JUKE_TRANSMIT)) - J.machine_flags &= !MULTITOOL_MENU - else - J.machine_flags |= MULTITOOL_MENU - if(JUKE_CONFIG) - for(var/e in freq_config_data) - if(e != 0) - return - J.short() - if(JUKE_SETTING) - J.shock(usr, 50) +#define JUKEMODE_PLAY_ONCE 3 + +/datum/wires/jukebox + holder_type = /obj/machinery/media/jukebox + wire_count = 8 + var/interference = 0 //Caused by pulsing the transmit wire + var/last = 0 //Value of the last JukeWire we pulsed + var/list/freq_config_data = list(0,0,0,0) //Set up in new + +/datum/wires/jukebox/New(var/atom/holder) + ..() + last = rand(1,14) + freq_config_data[JUKE_POWER_ONE] = rand(1,14) + freq_config_data[JUKE_POWER_TWO] = rand(1,14) + freq_config_data[JUKE_POWER_THREE] = rand(1,14) + +var/const/JUKE_POWER_ONE = 1 //Power. Cut for shock and off. Pulse toggles. +var/const/JUKE_POWER_TWO = 2 //Power. Cut for shock and off. Pulse toggles. +var/const/JUKE_POWER_THREE = 4 //Power. Cut for shock and off. Pulse toggles. +var/const/JUKE_SHUFFLE = 8 //Cut to disable shuffle and move to play_once. Pulse immediately shuffles. +var/const/JUKE_CAPITAL = 16 //Cut to disable song picking. Pulse randomizes song pick price 1-10. +var/const/JUKE_TRANSMIT = 32 //Cut shocks and disables multitool. Pulse emits burst of rads. +var/const/JUKE_CONFIG = 64 //Cut emags. Pulse plays IAMERROR.ogg +var/const/JUKE_SETTING = 128 //Cut shocks. Pulse toggles settings menu. + +/datum/wires/jukebox/CanUse(var/mob/living/L) + var/obj/machinery/media/jukebox/J = holder + if(J.panel_open) + return 1 + return 0 + +/datum/wires/jukebox/GetInteractWindow() + var/obj/machinery/media/jukebox/J = holder + . += ..() + . += {"
      The decorative tube with bubbles is [!J.any_power_cut() ? "glowing" : "dim"].
      + The green slider bar is [!IsIndexCut(JUKE_TRANSMIT) ? "modulating around full" : "empty"].
      + The maintenance button is [J.access_unlocked ? "lit" : "off"].
      + An unlabelled light is [J.emagged ? "dark" : "blinking occasionally"].
      "} + +/datum/wires/jukebox/UpdatePulsed(var/index) + if(interference) return + var/obj/machinery/media/jukebox/J = holder + switch(index) + if(JUKE_POWER_ONE,JUKE_POWER_TWO,JUKE_POWER_THREE) + J.playing=!J.playing + J.update_music() + J.update_icon() + var/calc = freq_config_data[index] - last + J.visible_message("[J] hums and outputs: [calc]") + last = freq_config_data[index] + if(JUKE_SHUFFLE) + J.current_song=rand(1,J.playlist.len) + if(JUKE_CAPITAL) + J.change_cost = rand(0,20) + if(JUKE_TRANSMIT) + J.rad_pulse() + interference = 1 + sleep(50) + interference = 0 + if(JUKE_CONFIG) + playsound(J.loc, 'sound/effects/IAMERROR.ogg', 100, 1) + if(JUKE_SETTING) + J.access_unlocked = !J.access_unlocked + +/datum/wires/jukebox/UpdateCut(var/index, var/mended) + var/obj/machinery/media/jukebox/J = holder + switch(index) + if(JUKE_POWER_ONE,JUKE_POWER_TWO,JUKE_POWER_THREE) + J.power_change() + J.shock(usr, 50) + if(freq_config_data[index]==0) + freq_config_data[index] = 14 + else + freq_config_data[index] -= 1 + if(JUKE_SHUFFLE) + if(IsIndexCut(JUKE_SHUFFLE)) + J.allowed_modes = list(2 = "Single", 3 = "Once") + J.loop_mode = JUKEMODE_PLAY_ONCE //Dammit Comic you're relentless there's no reason to define something for one use + else + J.allowed_modes = loopModeNames.Copy() + if(JUKE_TRANSMIT) + J.shock(usr, 50) + if(IsIndexCut(JUKE_TRANSMIT)) + J.machine_flags &= !MULTITOOL_MENU + else + J.machine_flags |= MULTITOOL_MENU + if(JUKE_CONFIG) + for(var/e in freq_config_data) + if(e != 0) + return + J.short() + if(JUKE_SETTING) + J.shock(usr, 50) diff --git a/code/datums/wires/transmitter.dm b/code/datums/wires/transmitter.dm index dd0a6425aa7..ec4563ca521 100644 --- a/code/datums/wires/transmitter.dm +++ b/code/datums/wires/transmitter.dm @@ -1,44 +1,44 @@ -/datum/wires/transmitter - holder_type = /obj/machinery/media/transmitter/broadcast - wire_count = 5 - var/counter = null - -var/const/TRANS_POWER = 1 //Power. Cut for shock and off. Pulse toggles. -var/const/TRANS_RAD_ONE = 2 //Reduces rad output by 50%. Requires at least one to function. Pulse does nothing. -var/const/TRANS_RAD_TWO = 4 //Reduces rad output by 50%. Requires at least one to function. Pulse does nothing. -var/const/TRANS_LINK = 8 //Cut shocks. Pulse clears links. -var/const/TRANS_SETTINGS = 16 //Pulse shows percentage given by environment temperature over safe operating temperature. - -/datum/wires/transmitter/CanUse(var/mob/living/L) - var/obj/machinery/media/transmitter/broadcast/T = holder - if(T.panel_open) - return 1 - return 0 - -/datum/wires/transmitter/GetInteractWindow() - var/obj/machinery/media/transmitter/broadcast/T = holder - . += ..() - . += {"
      The backlight is [IsIndexCut(TRANS_POWER) ? "dim" : "illuminated"].
      - The radiation warning light is [T.count_rad_wires() > 1 ? "brightly" : ""] [T.count_rad_wires() ? "shining" : "off"].
      - It has a cryptic display [counter ? "reading [counter]" : "that is blank"].
      "} - -/datum/wires/transmitter/UpdatePulsed(var/index) - var/obj/machinery/media/transmitter/broadcast/T = holder - switch(index) - if(TRANS_POWER) - T.on = !T.on - T.update_on() - if(TRANS_LINK) - T.unhook_media_sources() - if(TRANS_SETTINGS) - var/datum/gas_mixture/env = T.loc.return_air() - counter = 100*(env.temperature / (T20C + 20)) - -/datum/wires/transmitter/UpdateCut(var/index, var/mended) - var/obj/machinery/media/transmitter/broadcast/T = holder - switch(index) - if(TRANS_POWER) - T.power_change() - T.shock(usr, 50) - if(TRANS_LINK) - T.shock(usr, 50) +/datum/wires/transmitter + holder_type = /obj/machinery/media/transmitter/broadcast + wire_count = 5 + var/counter = null + +var/const/TRANS_POWER = 1 //Power. Cut for shock and off. Pulse toggles. +var/const/TRANS_RAD_ONE = 2 //Reduces rad output by 50%. Requires at least one to function. Pulse does nothing. +var/const/TRANS_RAD_TWO = 4 //Reduces rad output by 50%. Requires at least one to function. Pulse does nothing. +var/const/TRANS_LINK = 8 //Cut shocks. Pulse clears links. +var/const/TRANS_SETTINGS = 16 //Pulse shows percentage given by environment temperature over safe operating temperature. + +/datum/wires/transmitter/CanUse(var/mob/living/L) + var/obj/machinery/media/transmitter/broadcast/T = holder + if(T.panel_open) + return 1 + return 0 + +/datum/wires/transmitter/GetInteractWindow() + var/obj/machinery/media/transmitter/broadcast/T = holder + . += ..() + . += {"
      The backlight is [IsIndexCut(TRANS_POWER) ? "dim" : "illuminated"].
      + The radiation warning light is [T.count_rad_wires() > 1 ? "brightly" : ""] [T.count_rad_wires() ? "shining" : "off"].
      + It has a cryptic display [counter ? "reading [counter]" : "that is blank"].
      "} + +/datum/wires/transmitter/UpdatePulsed(var/index) + var/obj/machinery/media/transmitter/broadcast/T = holder + switch(index) + if(TRANS_POWER) + T.on = !T.on + T.update_on() + if(TRANS_LINK) + T.unhook_media_sources() + if(TRANS_SETTINGS) + var/datum/gas_mixture/env = T.loc.return_air() + counter = 100*(env.temperature / (T20C + 20)) + +/datum/wires/transmitter/UpdateCut(var/index, var/mended) + var/obj/machinery/media/transmitter/broadcast/T = holder + switch(index) + if(TRANS_POWER) + T.power_change() + T.shock(usr, 50) + if(TRANS_LINK) + T.shock(usr, 50) diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 13252de6c94..2fe7370429f 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -1,355 +1,355 @@ -/obj/structure/signpost - icon = 'icons/obj/stationobjs.dmi' - icon_state = "signpost" - anchored = 1 - density = 1 - - attackby(obj/item/weapon/W as obj, mob/user as mob) - return attack_hand(user) - - attack_hand(mob/user as mob) - switch(alert("Travel back to ss13?",,"Yes","No")) - if("Yes") - if(user.z != src.z) return - user.loc.loc.Exited(user) - user.loc = pick(latejoin) - if("No") - return - -/obj/effect/mark - var/mark = "" - icon = 'icons/misc/mark.dmi' - icon_state = "blank" - anchored = 1 - layer = 99 - mouse_opacity = 0 - unacidable = 1//Just to be sure. - - - -/obj/effect/begin - name = "begin" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "begin" - anchored = 1.0 - unacidable = 1 - -/* - * This item is completely unused, but removing it will break something in R&D and Radio code causing PDA and Ninja code to fail on compile - */ - -/obj/effect/datacore - name = "datacore" - var/medical[] = list() - var/general[] = list() - var/security[] = list() - //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). - var/locked[] = list() - - - -/obj/effect/datacore/proc/get_manifest(monochrome, OOC) - var/list/heads = new() - var/list/sec = new() - var/list/eng = new() - var/list/med = new() - var/list/sci = new() - var/list/civ = new() - var/list/bot = new() - var/list/misc = new() - var/list/isactive = new() - var/dat = {" - - - - "} - var/even = 0 - // sort mobs - for(var/datum/data/record/t in sortRecord(data_core.general)) - var/name = t.fields["name"] - var/rank = t.fields["rank"] - var/real_rank = t.fields["real_rank"] - if(OOC) - var/active = 0 - var/SSD = 0 - for(var/mob/M in player_list) - if(M.real_name == name) - if(!M.client) - SSD = 1 - break - if(M.client && M.client.inactivity <= 10 * 60 * 10) - active = 1 - break - isactive[name] = (SSD ? "SSD" : (active ? "Active" : "Inactive")) - else - isactive[name] = t.fields["p_stat"] +/obj/structure/signpost + icon = 'icons/obj/stationobjs.dmi' + icon_state = "signpost" + anchored = 1 + density = 1 + + attackby(obj/item/weapon/W as obj, mob/user as mob) + return attack_hand(user) + + attack_hand(mob/user as mob) + switch(alert("Travel back to ss13?",,"Yes","No")) + if("Yes") + if(user.z != src.z) return + user.loc.loc.Exited(user) + user.loc = pick(latejoin) + if("No") + return + +/obj/effect/mark + var/mark = "" + icon = 'icons/misc/mark.dmi' + icon_state = "blank" + anchored = 1 + layer = 99 + mouse_opacity = 0 + unacidable = 1//Just to be sure. + + + +/obj/effect/begin + name = "begin" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "begin" + anchored = 1.0 + unacidable = 1 + +/* + * This item is completely unused, but removing it will break something in R&D and Radio code causing PDA and Ninja code to fail on compile + */ + +/obj/effect/datacore + name = "datacore" + var/medical[] = list() + var/general[] = list() + var/security[] = list() + //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). + var/locked[] = list() + + + +/obj/effect/datacore/proc/get_manifest(monochrome, OOC) + var/list/heads = new() + var/list/sec = new() + var/list/eng = new() + var/list/med = new() + var/list/sci = new() + var/list/civ = new() + var/list/bot = new() + var/list/misc = new() + var/list/isactive = new() + var/dat = {" + +
      NameRankActivity
      + + "} + var/even = 0 + // sort mobs + for(var/datum/data/record/t in sortRecord(data_core.general)) + var/name = t.fields["name"] + var/rank = t.fields["rank"] + var/real_rank = t.fields["real_rank"] + if(OOC) + var/active = 0 + var/SSD = 0 + for(var/mob/M in player_list) + if(M.real_name == name) + if(!M.client) + SSD = 1 + break + if(M.client && M.client.inactivity <= 10 * 60 * 10) + active = 1 + break + isactive[name] = (SSD ? "SSD" : (active ? "Active" : "Inactive")) + else + isactive[name] = t.fields["p_stat"] // to_chat(world, "[name]: [rank]") - //cael - to prevent multiple appearances of a player/job combination, add a continue after each line - var/department = 0 - if(real_rank in command_positions) - heads[name] = rank - department = 1 - if(real_rank in security_positions) - sec[name] = rank - department = 1 - if(real_rank in engineering_positions) - eng[name] = rank - department = 1 - if(real_rank in medical_positions) - med[name] = rank - department = 1 - if(real_rank in science_positions) - sci[name] = rank - department = 1 - if(real_rank in civilian_positions) - civ[name] = rank - department = 1 - if(real_rank in nonhuman_positions) - bot[name] = rank - department = 1 - if(!department && !(name in heads)) - misc[name] = rank - if(heads.len > 0) - dat += "" - for(name in heads) - dat += "" - even = !even - if(sec.len > 0) - dat += "" - for(name in sec) - dat += "" - even = !even - if(eng.len > 0) - dat += "" - for(name in eng) - dat += "" - even = !even - if(med.len > 0) - dat += "" - for(name in med) - dat += "" - even = !even - if(sci.len > 0) - dat += "" - for(name in sci) - dat += "" - even = !even - if(civ.len > 0) - dat += "" - for(name in civ) - dat += "" - even = !even - // in case somebody is insane and added them to the manifest, why not - if(bot.len > 0) - dat += "" - for(name in bot) - dat += "" - even = !even - // misc guys - if(misc.len > 0) - dat += "" - for(name in misc) - dat += "" - even = !even - - dat += "
      NameRankActivity
      Heads
      [name][heads[name]][isactive[name]]
      Security
      [name][sec[name]][isactive[name]]
      Engineering
      [name][eng[name]][isactive[name]]
      Medical
      [name][med[name]][isactive[name]]
      Science
      [name][sci[name]][isactive[name]]
      Civilian
      [name][civ[name]][isactive[name]]
      Silicon
      [name][bot[name]][isactive[name]]
      Miscellaneous
      [name][misc[name]][isactive[name]]
      " - dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly - dat = replacetext(dat, "\t", "") - return dat - - -/* -We can't just insert in HTML into the nanoUI so we need the raw data to play with. -Instead of creating this list over and over when someone leaves their PDA open to the page -we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change -using /obj/effect/datacore/proc/manifest_inject( ), or manifest_insert( ) -*/ - -var/global/list/PDA_Manifest = list() - -/obj/effect/datacore/proc/get_manifest_json() - if(PDA_Manifest.len) - return PDA_Manifest - var/heads[0] - var/sec[0] - var/eng[0] - var/med[0] - var/sci[0] - var/civ[0] - var/bot[0] - var/misc[0] - for(var/datum/data/record/t in data_core.general) - var/name = sanitize(t.fields["name"]) - var/rank = sanitize(t.fields["rank"]) - var/real_rank = t.fields["real_rank"] - var/isactive = t.fields["p_stat"] - var/department = 0 - var/depthead = 0 // Department Heads will be placed at the top of their lists. - if(real_rank in command_positions) - heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - depthead = 1 - if(rank=="Captain" && heads.len != 1) - heads.Swap(1,heads.len) - - if(real_rank in security_positions) - sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - if(depthead && sec.len != 1) - sec.Swap(1,sec.len) - - if(real_rank in engineering_positions) - eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - if(depthead && eng.len != 1) - eng.Swap(1,eng.len) - - if(real_rank in medical_positions) - med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - if(depthead && med.len != 1) - med.Swap(1,med.len) - - if(real_rank in science_positions) - sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - if(depthead && sci.len != 1) - sci.Swap(1,sci.len) - - if(real_rank in civilian_positions) - civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - if(depthead && civ.len != 1) - civ.Swap(1,civ.len) - - if(real_rank in nonhuman_positions) - bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive) - department = 1 - - if(!department && !(name in heads)) - misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive) - - - PDA_Manifest = list(\ - "heads" = heads,\ - "sec" = sec,\ - "eng" = eng,\ - "med" = med,\ - "sci" = sci,\ - "civ" = civ,\ - "bot" = bot,\ - "misc" = misc\ - ) - return PDA_Manifest - - - -/obj/effect/laser - name = "laser" - desc = "IT BURNS!!!" - icon = 'icons/obj/projectiles.dmi' - var/damage = 0.0 - var/range = 10.0 - - -/obj/effect/list_container - name = "list container" - -/obj/effect/list_container/mobl - name = "mobl" - var/master = null - - var/list/container = list( ) - -/obj/effect/projection - name = "Projection" - desc = "This looks like a projection of something." - anchored = 1.0 - - -/obj/effect/shut_controller - name = "shut controller" - var/moving = null - var/list/parts = list( ) - -/obj/structure/showcase - name = "Showcase" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "showcase_1" - desc = "A stand with the empty body of a cyborg bolted to it." - density = 1 - anchored = 1 - unacidable = 1//temporary until I decide whether the borg can be removed. -veyveyr - -/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER - -/obj/item/weapon/beach_ball - icon = 'icons/misc/beach.dmi' - icon_state = "ball" - name = "beach ball" - item_state = "beachball" - density = 0 - anchored = 0 - w_class = 1.0 - force = 0.0 - throwforce = 0.0 - throw_speed = 1 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - -/obj/item/weapon/beach_ball/afterattack(atom/target as mob|obj|turf|area, mob/user as mob) - if(user.drop_item(src)) - src.throw_at(target, throw_range, throw_speed) - -/obj/effect/stop - var/victim = null - icon_state = "empty" - name = "Geas" - desc = "You can't resist." - // name = "" - -/obj/effect/stop/sleeping - var/sleeptime - icon_state = "empty" - name = "Sleepy time" - var/datum/mind/owner - var/spell/aoe_turf/fall/ourspell - invisibility = 100 - var/theworld - ignoreinvert = 1 - -/obj/effect/stop/sleeping/New(loc, ourtime, mind, var/spell/aoe_turf/fall/F, theworld) - ..() - sleeptime = ourtime - owner = mind - ourspell = F - src.theworld = theworld -/obj/effect/stop/sleeping/Crossed(atom/movable/A) - if(sleeptime > world.time) - if(ismob(A)) - var/mob/living/L = A - if(L.mind != owner) - if(!L.stat) L.playsound_local(src, theworld == 1 ? 'sound/effects/theworld2.ogg' : 'sound/effects/fall2.ogg', 100, 0, 0, 0, 0) - //L.Paralyse(round(((sleeptime - world.time)/10)/2, 1)) - //L.update_canmove() - if(!(L in ourspell.affected)) - invertcolor(L) - ourspell.affected += L - ourspell.recursive_timestop(L) - else - if(!(A in ourspell.affected)) - invertcolor(A) - ourspell.affected += A - ourspell.recursive_timestop(A) - - -/obj/effect/spawner - name = "object spawner" + //cael - to prevent multiple appearances of a player/job combination, add a continue after each line + var/department = 0 + if(real_rank in command_positions) + heads[name] = rank + department = 1 + if(real_rank in security_positions) + sec[name] = rank + department = 1 + if(real_rank in engineering_positions) + eng[name] = rank + department = 1 + if(real_rank in medical_positions) + med[name] = rank + department = 1 + if(real_rank in science_positions) + sci[name] = rank + department = 1 + if(real_rank in civilian_positions) + civ[name] = rank + department = 1 + if(real_rank in nonhuman_positions) + bot[name] = rank + department = 1 + if(!department && !(name in heads)) + misc[name] = rank + if(heads.len > 0) + dat += "Heads" + for(name in heads) + dat += "[name][heads[name]][isactive[name]]" + even = !even + if(sec.len > 0) + dat += "Security" + for(name in sec) + dat += "[name][sec[name]][isactive[name]]" + even = !even + if(eng.len > 0) + dat += "Engineering" + for(name in eng) + dat += "[name][eng[name]][isactive[name]]" + even = !even + if(med.len > 0) + dat += "Medical" + for(name in med) + dat += "[name][med[name]][isactive[name]]" + even = !even + if(sci.len > 0) + dat += "Science" + for(name in sci) + dat += "[name][sci[name]][isactive[name]]" + even = !even + if(civ.len > 0) + dat += "Civilian" + for(name in civ) + dat += "[name][civ[name]][isactive[name]]" + even = !even + // in case somebody is insane and added them to the manifest, why not + if(bot.len > 0) + dat += "Silicon" + for(name in bot) + dat += "[name][bot[name]][isactive[name]]" + even = !even + // misc guys + if(misc.len > 0) + dat += "Miscellaneous" + for(name in misc) + dat += "[name][misc[name]][isactive[name]]" + even = !even + + dat += "" + dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly + dat = replacetext(dat, "\t", "") + return dat + + +/* +We can't just insert in HTML into the nanoUI so we need the raw data to play with. +Instead of creating this list over and over when someone leaves their PDA open to the page +we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change +using /obj/effect/datacore/proc/manifest_inject( ), or manifest_insert( ) +*/ + +var/global/list/PDA_Manifest = list() + +/obj/effect/datacore/proc/get_manifest_json() + if(PDA_Manifest.len) + return PDA_Manifest + var/heads[0] + var/sec[0] + var/eng[0] + var/med[0] + var/sci[0] + var/civ[0] + var/bot[0] + var/misc[0] + for(var/datum/data/record/t in data_core.general) + var/name = sanitize(t.fields["name"]) + var/rank = sanitize(t.fields["rank"]) + var/real_rank = t.fields["real_rank"] + var/isactive = t.fields["p_stat"] + var/department = 0 + var/depthead = 0 // Department Heads will be placed at the top of their lists. + if(real_rank in command_positions) + heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + depthead = 1 + if(rank=="Captain" && heads.len != 1) + heads.Swap(1,heads.len) + + if(real_rank in security_positions) + sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + if(depthead && sec.len != 1) + sec.Swap(1,sec.len) + + if(real_rank in engineering_positions) + eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + if(depthead && eng.len != 1) + eng.Swap(1,eng.len) + + if(real_rank in medical_positions) + med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + if(depthead && med.len != 1) + med.Swap(1,med.len) + + if(real_rank in science_positions) + sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + if(depthead && sci.len != 1) + sci.Swap(1,sci.len) + + if(real_rank in civilian_positions) + civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + if(depthead && civ.len != 1) + civ.Swap(1,civ.len) + + if(real_rank in nonhuman_positions) + bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive) + department = 1 + + if(!department && !(name in heads)) + misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive) + + + PDA_Manifest = list(\ + "heads" = heads,\ + "sec" = sec,\ + "eng" = eng,\ + "med" = med,\ + "sci" = sci,\ + "civ" = civ,\ + "bot" = bot,\ + "misc" = misc\ + ) + return PDA_Manifest + + + +/obj/effect/laser + name = "laser" + desc = "IT BURNS!!!" + icon = 'icons/obj/projectiles.dmi' + var/damage = 0.0 + var/range = 10.0 + + +/obj/effect/list_container + name = "list container" + +/obj/effect/list_container/mobl + name = "mobl" + var/master = null + + var/list/container = list( ) + +/obj/effect/projection + name = "Projection" + desc = "This looks like a projection of something." + anchored = 1.0 + + +/obj/effect/shut_controller + name = "shut controller" + var/moving = null + var/list/parts = list( ) + +/obj/structure/showcase + name = "Showcase" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "showcase_1" + desc = "A stand with the empty body of a cyborg bolted to it." + density = 1 + anchored = 1 + unacidable = 1//temporary until I decide whether the borg can be removed. -veyveyr + +/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER + +/obj/item/weapon/beach_ball + icon = 'icons/misc/beach.dmi' + icon_state = "ball" + name = "beach ball" + item_state = "beachball" + density = 0 + anchored = 0 + w_class = 1.0 + force = 0.0 + throwforce = 0.0 + throw_speed = 1 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + +/obj/item/weapon/beach_ball/afterattack(atom/target as mob|obj|turf|area, mob/user as mob) + if(user.drop_item(src)) + src.throw_at(target, throw_range, throw_speed) + +/obj/effect/stop + var/victim = null + icon_state = "empty" + name = "Geas" + desc = "You can't resist." + // name = "" + +/obj/effect/stop/sleeping + var/sleeptime + icon_state = "empty" + name = "Sleepy time" + var/datum/mind/owner + var/spell/aoe_turf/fall/ourspell + invisibility = 100 + var/theworld + ignoreinvert = 1 + +/obj/effect/stop/sleeping/New(loc, ourtime, mind, var/spell/aoe_turf/fall/F, theworld) + ..() + sleeptime = ourtime + owner = mind + ourspell = F + src.theworld = theworld +/obj/effect/stop/sleeping/Crossed(atom/movable/A) + if(sleeptime > world.time) + if(ismob(A)) + var/mob/living/L = A + if(L.mind != owner) + if(!L.stat) L.playsound_local(src, theworld == 1 ? 'sound/effects/theworld2.ogg' : 'sound/effects/fall2.ogg', 100, 0, 0, 0, 0) + //L.Paralyse(round(((sleeptime - world.time)/10)/2, 1)) + //L.update_canmove() + if(!(L in ourspell.affected)) + invertcolor(L) + ourspell.affected += L + ourspell.recursive_timestop(L) + else + if(!(A in ourspell.affected)) + invertcolor(A) + ourspell.affected += A + ourspell.recursive_timestop(A) + + +/obj/effect/spawner + name = "object spawner" diff --git a/code/defines/obj/hydro.dm b/code/defines/obj/hydro.dm index 8fb7d97b651..f9e92b17c0f 100644 --- a/code/defines/obj/hydro.dm +++ b/code/defines/obj/hydro.dm @@ -1,1602 +1,1602 @@ -// Plant analyzer - -/obj/item/device/analyzer/plant_analyzer - name = "plant analyzer" - icon = 'icons/obj/device.dmi' - icon_state = "hydro" - item_state = "analyzer" - - attack_self(mob/user as mob) - return 0 - -// ******************************************************** -// Here's all the seeds (plants) that can be used in hydro -// ******************************************************** - -/obj/item/seeds - name = "pack of seeds" - 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 - var/mypath = "/obj/item/seeds" - var/plantname = "Plants" - var/productname = "" - var/species = "" - var/lifespan = 0 - var/endurance = 0 - var/maturation = 0 - var/production = 0 - var/yield = 0 // If is -1, the plant/shroom/weed is never meant to be harvested - var/oneharvest = 0 - var/potency = -1 - var/growthstages = 0 - var/plant_type = 0 // 0 = 'normal plant'; 1 = weed; 2 = shroom - -/obj/item/seeds/examine(mob/user) - ..() +// Plant analyzer + +/obj/item/device/analyzer/plant_analyzer + name = "plant analyzer" + icon = 'icons/obj/device.dmi' + icon_state = "hydro" + item_state = "analyzer" + + attack_self(mob/user as mob) + return 0 + +// ******************************************************** +// Here's all the seeds (plants) that can be used in hydro +// ******************************************************** + +/obj/item/seeds + name = "pack of seeds" + 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 + var/mypath = "/obj/item/seeds" + var/plantname = "Plants" + var/productname = "" + var/species = "" + var/lifespan = 0 + var/endurance = 0 + var/maturation = 0 + var/production = 0 + var/yield = 0 // If is -1, the plant/shroom/weed is never meant to be harvested + var/oneharvest = 0 + var/potency = -1 + var/growthstages = 0 + var/plant_type = 0 // 0 = 'normal plant'; 1 = weed; 2 = shroom + +/obj/item/seeds/examine(mob/user) + ..() to_chat(user, "Plant Yield: [(yield != -1) ? yield : "ERROR"]") to_chat(user, "Plant Potency: [(potency != -1) ? potency : "ERROR"]") - -/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (istype(O, /obj/item/device/analyzer/plant_analyzer)) + +/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob) + if (istype(O, /obj/item/device/analyzer/plant_analyzer)) to_chat(user, "*** [plantname] ***") to_chat(user, "-Plant Endurance: [endurance]") to_chat(user, "-Plant Lifespan: [lifespan]") - if(yield != -1) + if(yield != -1) to_chat(user, "-Plant Yield: [yield]") to_chat(user, "-Plant Production: [production]") - if(potency != -1) + if(potency != -1) to_chat(user, "-Plant Potency: [potency]") - return - ..() // Fallthrough to item/attackby() so that bags can pick seeds up - -/obj/item/seeds/chiliseed - name = "pack of chili seeds" - desc = "These seeds grow into chili plants. HOT! HOT! HOT!" - icon_state = "seed-chili" - mypath = "/obj/item/seeds/chiliseed" - species = "chili" - plantname = "Chili Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/chili" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 4 - potency = 20 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/chillighost - name = "pack of ghost chilli seeds" - desc = "These seeds grow into a chili said to be the hottest in the galaxy." - icon_state = "seed-chilighost" - mypath = "/obj/item/seeds/chillighost" - species = "chilighost" - plantname = "Ghost Chili Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chilli" - lifespan = 20 - endurance = 10 - maturation = 10 - production = 10 - yield = 3 - potency = 20 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/plastiseed - name = "plastellium mycelium" - desc = "This mycelium grows into Plastellium" - icon_state = "mycelium-plast" - mypath = "/obj/item/seeds/plastiseed" - species = "plastellium" - plantname = "Plastellium" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/plastellium" - lifespan = 15 - endurance = 17 - maturation = 5 - production = 6 - yield = 6 - oneharvest = 1 - potency = 20 - plant_type = 2 - growthstages = 3 - -/obj/item/seeds/grapeseed - name = "pack of grape seeds" - desc = "These seeds grow into grape vines." - icon_state = "seed-grapes" - mypath = "/obj/item/seeds/grapeseed" - species = "grape" - plantname = "Grape Vine" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/grapes" - lifespan = 50 - endurance = 25 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 2 - -/obj/item/seeds/greengrapeseed - name = "pack of green grape seeds" - desc = "These seeds grow into green-grape vines." - icon_state = "seed-greengrapes" - mypath = "/obj/item/seeds/greengrapeseed" - species = "greengrape" - plantname = "Green-Grape Vine" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes" - lifespan = 50 - endurance = 25 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 2 - -/obj/item/seeds/cabbageseed - name = "pack of cabbage seeds" - desc = "These seeds grow into cabbages." - icon_state = "seed-cabbage" - mypath = "/obj/item/seeds/cabbageseed" - species = "cabbage" - plantname = "Cabbages" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/cabbage" - lifespan = 50 - endurance = 25 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 1 - -/obj/item/seeds/shandseed - name = "pack of s'rendarr's hand seeds" - desc = "These seeds grow into a helpful herb called S'Rendarr's Hand, native to Ahdomai." - icon_state = "seed-shand" - mypath = "/obj/item/seeds/shandseed" - species = "shand" - plantname = "S'Rendarr's Hand" - productname = "/obj/item/stack/medical/bruise_pack/tajaran" - lifespan = 50 - endurance = 25 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 3 - -/obj/item/seeds/mtearseed - name = "pack of messa's tear seeds" - desc = "These seeds grow into a helpful herb called Messa's Tear, native to Ahdomai." - icon_state = "seed-mtear" - mypath = "/obj/item/seeds/mtearseed" - species = "mtear" - plantname = "Messa's Tear" - productname = "/obj/item/stack/medical/ointment/tajaran" - lifespan = 50 - endurance = 25 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 3 - -/obj/item/seeds/berryseed - name = "pack of berry seeds" - desc = "These seeds grow into berry bushes." - icon_state = "seed-berry" - mypath = "/obj/item/seeds/berryseed" - species = "berry" - plantname = "Berry Bush" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/berries" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/glowberryseed - name = "pack of glow-berry seeds" - desc = "These seeds grow into glow-berry bushes." - icon_state = "seed-glowberry" - mypath = "/obj/item/seeds/glowberryseed" - species = "glowberry" - plantname = "Glow-Berry Bush" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/glowberries" - lifespan = 30 - endurance = 25 - maturation = 5 - production = 5 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/bananaseed - name = "pack of banana seeds" - desc = "They're seeds that grow into banana trees." - icon_state = "seed-banana" - mypath = "/obj/item/seeds/bananaseed" - species = "banana" - plantname = "Banana Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/banana" - lifespan = 50 - endurance = 30 - maturation = 6 - production = 6 - yield = 3 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/eggplantseed - name = "pack of eggplant seeds" - desc = "These seeds grow to produce berries that look nothing like eggs." - icon_state = "seed-eggplant" - mypath = "/obj/item/seeds/eggplantseed" - species = "eggplant" - plantname = "Eggplants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant" - lifespan = 25 - endurance = 15 - maturation = 6 - production = 6 - yield = 2 - potency = 20 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/eggyseed - name = "pack of eggplant seeds" - desc = "These seeds grow to produce berries that look a lot like eggs." - icon_state = "seed-eggy" - mypath = "/obj/item/seeds/eggy" - species = "eggy" - plantname = "Eggplants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/egg" - lifespan = 75 - endurance = 15 - maturation = 6 - production = 12 - yield = 2 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/bloodtomatoseed - name = "pack of blood-tomato seeds" - desc = "These seeds grow into blood-tomato plants." - icon_state = "seed-bloodtomato" - mypath = "/obj/item/seeds/bloodtomatoseed" - species = "bloodtomato" - plantname = "Blood-Tomato Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato" - lifespan = 25 - endurance = 20 - maturation = 8 - production = 6 - yield = 3 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/tomatoseed - name = "pack of tomato seeds" - desc = "These seeds grow into tomato plants." - icon_state = "seed-tomato" - mypath = "/obj/item/seeds/tomatoseed" - species = "tomato" - plantname = "Tomato Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/tomato" - lifespan = 25 - endurance = 15 - maturation = 8 - production = 6 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/killertomatoseed - name = "pack of killer-tomato seeds" - desc = "These seeds grow into killer-tomato plants." - icon_state = "seed-killertomato" - mypath = "/obj/item/seeds/killertomatoseed" - species = "killertomato" - plantname = "Killer-Tomato Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato" - lifespan = 25 - endurance = 15 - maturation = 8 - production = 6 - yield = 2 - potency = 10 - plant_type = 0 - oneharvest = 1 - growthstages = 2 - -/obj/item/seeds/bluetomatoseed - name = "pack of blue-tomato seeds" - desc = "These seeds grow into blue-tomato plants." - icon_state = "seed-bluetomato" - mypath = "/obj/item/seeds/bluetomatoseed" - species = "bluetomato" - plantname = "Blue-Tomato Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/bluetomato" - lifespan = 25 - endurance = 15 - maturation = 8 - production = 6 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/bluespacetomatoseed - name = "pack of blue-space tomato seeds" - desc = "These seeds grow into blue-space tomato plants." - icon_state = "seed-bluespacetomato" - mypath = "/obj/item/seeds/bluespacetomatoseed" - species = "bluespacetomato" - plantname = "Blue-Space Tomato Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato" - lifespan = 25 - endurance = 15 - maturation = 8 - production = 6 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/cornseed - name = "pack of corn seeds" - desc = "I don't mean to sound corny..." - icon_state = "seed-corn" - mypath = "/obj/item/seeds/cornseed" - species = "corn" - plantname = "Corn Stalks" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/corn" - lifespan = 25 - endurance = 15 - maturation = 8 - production = 6 - yield = 3 - plant_type = 0 - oneharvest = 1 - potency = 20 - growthstages = 3 - -/obj/item/seeds/poppyseed - name = "pack of poppy seeds" - desc = "These seeds grow into poppies." - icon_state = "seed-poppy" - mypath = "/obj/item/seeds/poppyseed" - species = "poppy" - plantname = "Poppy Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/poppy" - lifespan = 25 - endurance = 10 - potency = 20 - maturation = 8 - production = 6 - yield = 6 - plant_type = 0 - oneharvest = 1 - growthstages = 3 - -/obj/item/seeds/potatoseed - name = "pack of potato seeds" - desc = "Boil 'em! Mash 'em! Stick 'em in a stew!" - icon_state = "seed-potato" - mypath = "/obj/item/seeds/potatoseed" - species = "potato" - plantname = "Potato-Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/potato" - lifespan = 30 - endurance = 15 - maturation = 10 - production = 1 - yield = 4 - plant_type = 0 - oneharvest = 1 - potency = 10 - growthstages = 4 - -/obj/item/seeds/icepepperseed - name = "pack of ice-pepper seeds" - desc = "These seeds grow into ice-pepper plants." - icon_state = "seed-icepepper" - mypath = "/obj/item/seeds/icepepperseed" - species = "chiliice" - plantname = "Ice-Pepper Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/icepepper" - lifespan = 25 - endurance = 15 - maturation = 4 - production = 4 - yield = 4 - potency = 20 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/soyaseed - name = "pack of soybean seeds" - desc = "These seeds grow into soybean plants." - icon_state = "seed-soybean" - mypath = "/obj/item/seeds/soyaseed" - species = "soybean" - plantname = "Soybean Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans" - lifespan = 25 - endurance = 15 - maturation = 4 - production = 4 - yield = 3 - potency = 5 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/koiseed - name = "pack of koibean seeds" - desc = "These seeds grow into koibean plants." - icon_state = "seed-koibean" - mypath = "/obj/item/seeds/koiseed" - species = "koibean" - plantname = "Koibean Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/koibeans" - lifespan = 25 - endurance = 15 - maturation = 4 - production = 4 - yield = 3 - potency = 10 - plant_type = 0 - growthstages = 4 - -/obj/item/seeds/wheatseed - name = "pack of wheat seeds" - desc = "These may, or may not, grow into weed." - icon_state = "seed-wheat" - mypath = "/obj/item/seeds/wheatseed" - species = "wheat" - plantname = "Wheat Stalks" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/wheat" - lifespan = 25 - endurance = 15 - maturation = 6 - production = 1 - yield = 4 - potency = 5 - oneharvest = 1 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/riceseed - name = "pack of rice seeds" - desc = "These seeds grow into rice stalks." - icon_state = "seed-rice" - mypath = "/obj/item/seeds/riceseed" - species = "rice" - plantname = "Rice Stalks" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk" - lifespan = 25 - endurance = 15 - maturation = 6 - production = 1 - yield = 4 - potency = 5 - oneharvest = 1 - plant_type = 0 - growthstages = 4 - -/obj/item/seeds/carrotseed - name = "pack of carrot seeds" - desc = "These seeds grow into carrots." - icon_state = "seed-carrot" - mypath = "/obj/item/seeds/carrotseed" - species = "carrot" - plantname = "Carrots" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/carrot" - lifespan = 25 - endurance = 15 - maturation = 10 - production = 1 - yield = 5 - potency = 10 - oneharvest = 1 - plant_type = 0 - growthstages = 3 - -/obj/item/seeds/reishimycelium - name = "pack of reishi mycelium" - desc = "This mycelium grows into something relaxing." - icon_state = "mycelium-reishi" - mypath = "/obj/item/seeds/reishimycelium" - species = "reishi" - plantname = "Reishi" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/reishi" - lifespan = 35 - endurance = 35 - maturation = 10 - production = 5 - yield = 4 - potency = 15 // Sleeping based on potency? - oneharvest = 1 - growthstages = 4 - plant_type = 2 - -/obj/item/seeds/amanitamycelium - name = "pack of fly amanita mycelium" - desc = "This mycelium grows into something horrible." - icon_state = "mycelium-amanita" - mypath = "/obj/item/seeds/amanitamycelium" - species = "amanita" - plantname = "Fly Amanitas" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita" - lifespan = 50 - endurance = 35 - maturation = 10 - production = 5 - yield = 4 - potency = 10 // Damage based on potency? - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/angelmycelium - name = "pack of destroying angel mycelium" - desc = "This mycelium grows into something devastating." - icon_state = "mycelium-angel" - mypath = "/obj/item/seeds/angelmycelium" - species = "angel" - plantname = "Destroying Angels" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel" - lifespan = 50 - endurance = 35 - maturation = 12 - production = 5 - yield = 2 - potency = 35 - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/libertymycelium - name = "pack of liberty-cap mycelium" - desc = "This mycelium grows into liberty-cap mushrooms." - icon_state = "mycelium-liberty" - mypath = "/obj/item/seeds/libertymycelium" - species = "liberty" - plantname = "Liberty-Caps" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap" - lifespan = 25 - endurance = 15 - maturation = 7 - production = 1 - yield = 5 - potency = 15 // Lowish potency at start - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/chantermycelium - name = "pack of chanterelle mycelium" - desc = "This mycelium grows into chanterelle mushrooms." - icon_state = "mycelium-chanter" - mypath = "/obj/item/seeds/chantermycelium" - species = "chanter" - plantname = "Chanterelle Mushrooms" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle" - lifespan = 35 - endurance = 20 - maturation = 7 - production = 1 - yield = 5 - potency = 1 - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/towermycelium - name = "pack of tower-cap mycelium" - desc = "This mycelium grows into tower-cap mushrooms." - icon_state = "mycelium-tower" - mypath = "/obj/item/seeds/towermycelium" - species = "towercap" - plantname = "Tower Caps" - productname = "/obj/item/weapon/grown/log" - lifespan = 80 - endurance = 50 - maturation = 15 - production = 1 - yield = 5 - potency = 1 - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/glowshroom - name = "pack of glowshroom mycelium" - desc = "This mycelium -glows- into mushrooms!" - icon_state = "mycelium-glowshroom" - mypath = "/obj/item/seeds/glowshroom" - species = "glowshroom" - plantname = "Glowshrooms" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom" - lifespan = 120 //ten times that is the delay - endurance = 30 - maturation = 15 - production = 1 - yield = 3 //-> spread - potency = 30 //-> brightness - oneharvest = 1 - growthstages = 4 - plant_type = 2 - -/obj/item/seeds/plumpmycelium - name = "pack of plump-helmet mycelium" - desc = "This mycelium grows into helmets... maybe." - icon_state = "mycelium-plump" - mypath = "/obj/item/seeds/plumpmycelium" - species = "plump" - plantname = "Plump-Helmet Mushrooms" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet" - lifespan = 25 - endurance = 15 - maturation = 8 - production = 1 - yield = 4 - potency = 0 - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/walkingmushroommycelium - name = "pack of walking mushroom mycelium" - desc = "This mycelium will grow into huge stuff!" - icon_state = "mycelium-walkingmushroom" - mypath = "/obj/item/seeds/walkingmushroommycelium" - species = "walkingmushroom" - plantname = "Walking Mushrooms" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom" - lifespan = 30 - endurance = 30 - maturation = 5 - production = 1 - yield = 1 - potency = 0 - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/nettleseed - name = "pack of nettle seeds" - desc = "These seeds grow into nettles." - icon_state = "seed-nettle" - mypath = "/obj/item/seeds/nettleseed" - species = "nettle" - plantname = "Nettles" - productname = "/obj/item/weapon/grown/nettle" - lifespan = 30 - endurance = 40 // tuff like a toiger - maturation = 6 - production = 6 - yield = 4 - potency = 10 - oneharvest = 0 - growthstages = 5 - plant_type = 1 - -/obj/item/seeds/deathnettleseed - name = "pack of death-nettle seeds" - desc = "These seeds grow into death-nettles." - icon_state = "seed-deathnettle" - mypath = "/obj/item/seeds/deathnettleseed" - species = "deathnettle" - plantname = "Death Nettles" - productname = "/obj/item/weapon/grown/deathnettle" - lifespan = 30 - endurance = 25 - maturation = 8 - production = 6 - yield = 2 - potency = 10 - oneharvest = 0 - growthstages = 5 - plant_type = 1 - -/obj/item/seeds/weeds - name = "pack of weed seeds" - desc = "Yo mang, want some weeds?" - icon_state = "seed" - mypath = "/obj/item/seeds/weeds" - species = "weeds" - plantname = "Starthistle" - productname = "" - lifespan = 100 - endurance = 50 // damm pesky weeds - maturation = 5 - production = 1 - yield = -1 - potency = -1 - oneharvest = 1 - growthstages = 4 - plant_type = 1 - -/obj/item/seeds/harebell - name = "pack of harebell seeds" - desc = "These seeds grow into pretty little flowers." - icon_state = "seed-harebell" - mypath = "/obj/item/seeds/harebell" - species = "harebell" - plantname = "Harebells" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/harebell" - lifespan = 100 - endurance = 20 - maturation = 7 - production = 1 - yield = 2 - potency = 1 - oneharvest = 1 - growthstages = 4 - plant_type = 1 - -/obj/item/seeds/sunflowerseed - name = "pack of sunflower seeds" - desc = "These seeds grow into sunflowers." - icon_state = "seed-sunflower" - mypath = "/obj/item/seeds/sunflowerseed" - species = "sunflower" - plantname = "Sunflowers" - productname = "/obj/item/weapon/grown/sunflower" - lifespan = 25 - endurance = 20 - maturation = 6 - production = 1 - yield = 2 - potency = 1 - oneharvest = 1 - growthstages = 3 - plant_type = 1 - -/obj/item/seeds/moonflowerseed - name = "pack of moonflower seeds" - desc = "These seeds grow into moonflowers." - icon_state = "seed-moonflower" - mypath = "/obj/item/seeds/moonflowerseed" - species = "moonflower" - plantname = "Moonflowers" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower" - lifespan = 25 - endurance = 20 - maturation = 6 - production = 2 - yield = 2 - potency = 15 - oneharvest = 1 - growthstages = 3 - plant_type = 0 - -/obj/item/seeds/novaflowerseed - name = "pack of novaflower seeds" - desc = "These seeds grow into novaflowers." - icon_state = "seed-novaflower" - mypath = "/obj/item/seeds/novaflowerseed" - species = "novaflower" - plantname = "Novaflowers" - productname = "/obj/item/weapon/grown/novaflower" - lifespan = 25 - endurance = 20 - maturation = 6 - production = 2 - yield = 2 - potency = 20 - oneharvest = 1 - growthstages = 3 - plant_type = 0 - -/obj/item/seeds/brownmold - name = "pack of brown mold" - desc = "Eww.. moldy." - icon_state = "seed" - mypath = "/obj/item/seeds/brownmold" - species = "mold" - plantname = "Brown Mold" - productname = "" - lifespan = 50 - endurance = 30 - maturation = 10 - production = 1 - yield = -1 - potency = 1 - oneharvest = 1 - growthstages = 3 - plant_type = 2 - -/obj/item/seeds/appleseed - name = "pack of apple seeds" - desc = "These seeds grow into apple trees." - icon_state = "seed-apple" - mypath = "/obj/item/seeds/appleseed" - species = "apple" - plantname = "Apple Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/apple" - lifespan = 55 - endurance = 35 - maturation = 6 - production = 6 - yield = 5 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/poisonedappleseed - name = "pack of apple seeds" - desc = "These seeds grow into apple trees." - icon_state = "seed-apple" - mypath = "/obj/item/seeds/poisonedappleseed" - species = "apple" - plantname = "Apple Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned" - lifespan = 55 - endurance = 35 - maturation = 6 - production = 6 - yield = 5 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/goldappleseed - name = "pack of golden apple seeds" - desc = "These seeds grow into golden apple trees. Good thing there are no firebirds in space." - icon_state = "seed-goldapple" - mypath = "/obj/item/seeds/goldappleseed" - species = "goldapple" - plantname = "Golden Apple Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/goldapple" - lifespan = 55 - endurance = 35 - maturation = 10 - production = 10 - yield = 3 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/ambrosiavulgarisseed - name = "pack of ambrosia vulgaris seeds" - desc = "These seeds grow into common ambrosia, a plant grown by and from medicine." - icon_state = "seed-ambrosiavulgaris" - mypath = "/obj/item/seeds/ambrosiavulgarisseed" - species = "ambrosiavulgaris" - plantname = "Ambrosia Vulgaris" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris" - lifespan = 60 - endurance = 25 - maturation = 6 - production = 6 - yield = 6 - potency = 5 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/ambrosiavulgarisseed/cruciatus - name = "pack of ambrosia vulgaris seeds" - desc = "These seeds grow into common ambrosia, a plant grown by and from medicine." - icon_state = "seed-ambrosiavulgaris" - mypath = "/obj/item/seeds/ambrosiavulgarisseed/cruciatus" - species = "ambrosiavulgaris" - plantname = "Ambrosia Vulgaris" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/cruciatus" - lifespan = 60 - endurance = 25 - maturation = 6 - production = 6 - yield = 6 - potency = 5 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/ambrosiadeusseed - name = "pack of ambrosia deus seeds" - desc = "These seeds grow into ambrosia deus. Could it be the food of the gods..?" - icon_state = "seed-ambrosiadeus" - mypath = "/obj/item/seeds/ambrosiadeusseed" - species = "ambrosiadeus" - plantname = "Ambrosia Deus" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus" - lifespan = 60 - endurance = 25 - maturation = 6 - production = 6 - yield = 6 - potency = 5 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/whitebeetseed - name = "pack of white-beet seeds" - desc = "These seeds grow into sugary beet producing plants." - icon_state = "seed-whitebeet" - mypath = "/obj/item/seeds/whitebeetseed" - species = "whitebeet" - plantname = "White-Beet Plants" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet" - lifespan = 60 - endurance = 50 - maturation = 6 - production = 6 - yield = 6 - oneharvest = 1 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/sugarcaneseed - name = "pack of sugarcane seeds" - desc = "These seeds grow into sugarcane." - icon_state = "seed-sugarcane" - mypath = "/obj/item/seeds/sugarcaneseed" - species = "sugarcane" - plantname = "Sugarcane" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/sugarcane" - lifespan = 60 - endurance = 50 - maturation = 3 - production = 6 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 3 - -/obj/item/seeds/watermelonseed - name = "pack of watermelon seeds" - desc = "These seeds grow into watermelon plants." - icon_state = "seed-watermelon" - mypath = "/obj/item/seeds/watermelonseed" - species = "watermelon" - plantname = "Watermelon Vines" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/watermelon" - lifespan = 50 - endurance = 40 - maturation = 6 - production = 6 - yield = 3 - potency = 1 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/pumpkinseed - name = "pack of pumpkin seeds" - desc = "These seeds grow into pumpkin vines." - icon_state = "seed-pumpkin" - mypath = "/obj/item/seeds/pumpkinseed" - species = "pumpkin" - plantname = "Pumpkin Vines" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin" - lifespan = 50 - endurance = 40 - maturation = 6 - production = 6 - yield = 3 - potency = 10 - plant_type = 0 - growthstages = 3 - - -/obj/item/seeds/limeseed - name = "pack of lime seeds" - desc = "These are very sour seeds." - icon_state = "seed-lime" - mypath = "/obj/item/seeds/limeseed" - species = "lime" - plantname = "Lime Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/lime" - lifespan = 55 - endurance = 50 - maturation = 6 - production = 6 - yield = 4 - potency = 15 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/lemonseed - name = "pack of lemon seeds" - desc = "These are sour seeds." - icon_state = "seed-lemon" - mypath = "/obj/item/seeds/lemonseed" - species = "lemon" - plantname = "Lemon Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/lemon" - lifespan = 55 - endurance = 45 - maturation = 6 - production = 6 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/cashseed - name = "pack of money seeds" - desc = "When life gives you lemons, mutate them into cash." - icon_state = "seed-cash" - mypath = "/obj/item/seeds/cashseed" - species = "cashtree" - plantname = "Money Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/money" - lifespan = 55 - endurance = 45 - maturation = 6 - production = 6 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/orangeseed - name = "pack of orange seed" - desc = "Sour seeds." - icon_state = "seed-orange" - mypath = "/obj/item/seeds/orangeseed" - species = "orange" - plantname = "Orange Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/orange" - lifespan = 60 - endurance = 50 - maturation = 6 - production = 6 - yield = 5 - potency = 1 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/poisonberryseed - name = "pack of poison-berry seeds" - desc = "These seeds grow into poison-berry bushes." - icon_state = "seed-poisonberry" - mypath = "/obj/item/seeds/poisonberryseed" - species = "poisonberry" - plantname = "Poison-Berry Bush" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/deathberryseed - name = "pack of death-berry seeds" - desc = "These seeds grow into death berries." - icon_state = "seed-deathberry" - mypath = "/obj/item/seeds/deathberryseed" - species = "deathberry" - plantname = "Death Berry Bush" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/deathberries" - lifespan = 30 - endurance = 20 - maturation = 5 - production = 5 - yield = 3 - potency = 50 - plant_type = 0 - growthstages = 6 - -/obj/item/seeds/grassseed - name = "pack of grass seeds" - desc = "These seeds grow into grass. Yummy!" - icon_state = "seed-grass" - mypath = "/obj/item/seeds/grassseed" - species = "grass" - plantname = "Grass" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/grass" - lifespan = 60 - endurance = 50 - maturation = 2 - production = 5 - yield = 5 - plant_type = 0 - growthstages = 2 - -/obj/item/seeds/cocoapodseed - name = "pack of cocoa pod seeds" - desc = "These seeds grow into cacao trees. They look fattening." //SIC: cocoa is the seeds. The tress ARE spelled cacao. - icon_state = "seed-cocoapod" - mypath = "/obj/item/seeds/cocoapodseed" - species = "cocoapod" - plantname = "Cocao Tree" //SIC: see above - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 2 - potency = 10 - plant_type = 0 - growthstages = 5 - -/obj/item/seeds/cherryseed - name = "pack of cherry pits" - desc = "Careful not to crack a tooth on one... That'd be the pits." - icon_state = "seed-cherry" - mypath = "/obj/item/seeds/cherryseed" - species = "cherry" - plantname = "Cherry Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/cherries" - lifespan = 35 - endurance = 35 - maturation = 5 - production = 5 - yield = 3 - potency = 10 - plant_type = 0 - growthstages = 5 - -/obj/item/seeds/kudzuseed - name = "pack of kudzu seeds" - desc = "These seeds grow into a weed that grows incredibly fast." - icon_state = "seed-kudzu" - mypath = "/obj/item/seeds/kudzuseed" - species = "kudzu" - plantname = "Kudzu" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod" - lifespan = 20 - endurance = 10 - maturation = 6 - production = 6 - yield = 4 - potency = 10 - growthstages = 4 - plant_type = 1 - -/obj/item/seeds/synthmeatseed - name = "pack of synthmeat seeds" - desc = "These seeds grow into a synthmeat tree." - icon_state = "seed-synthmeat" - mypath = "/obj/item/seeds/synthmeatseed" - species = "synthmeat" - plantname = "Synthmeat Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/meat" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 2 - -/obj/item/seeds/synthbuttseed //*fart - name = "pack of synthbutt seeds" - desc = "These butts butt into a synthbutt butt." - icon_state = "seed-synthbutt" - mypath = "/obj/item/seeds/synthbuttseed" - species = "synthbutt" - plantname = "Synthbutt Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/butt" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 2 - -/obj/item/seeds/synthbrainseed - name = "pack of synthbrain seeds" - desc = "These seeds grow into a synthbrain tree." - icon_state = "seed-synthbrain" - mypath = "/obj/item/seeds/synthbrainseed" - species = "synthbrain" - plantname = "Synthbrain Tree" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/brain" - lifespan = 20 - endurance = 15 - maturation = 5 - production = 5 - yield = 4 - potency = 10 - plant_type = 0 - growthstages = 2 - -/obj/item/seeds/kudzuseed/attack_self(mob/user as mob) - if(istype(user.loc,/turf/space)) - return + return + ..() // Fallthrough to item/attackby() so that bags can pick seeds up + +/obj/item/seeds/chiliseed + name = "pack of chili seeds" + desc = "These seeds grow into chili plants. HOT! HOT! HOT!" + icon_state = "seed-chili" + mypath = "/obj/item/seeds/chiliseed" + species = "chili" + plantname = "Chili Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/chili" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 4 + potency = 20 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/chillighost + name = "pack of ghost chilli seeds" + desc = "These seeds grow into a chili said to be the hottest in the galaxy." + icon_state = "seed-chilighost" + mypath = "/obj/item/seeds/chillighost" + species = "chilighost" + plantname = "Ghost Chili Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chilli" + lifespan = 20 + endurance = 10 + maturation = 10 + production = 10 + yield = 3 + potency = 20 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/plastiseed + name = "plastellium mycelium" + desc = "This mycelium grows into Plastellium" + icon_state = "mycelium-plast" + mypath = "/obj/item/seeds/plastiseed" + species = "plastellium" + plantname = "Plastellium" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/plastellium" + lifespan = 15 + endurance = 17 + maturation = 5 + production = 6 + yield = 6 + oneharvest = 1 + potency = 20 + plant_type = 2 + growthstages = 3 + +/obj/item/seeds/grapeseed + name = "pack of grape seeds" + desc = "These seeds grow into grape vines." + icon_state = "seed-grapes" + mypath = "/obj/item/seeds/grapeseed" + species = "grape" + plantname = "Grape Vine" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/grapes" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 2 + +/obj/item/seeds/greengrapeseed + name = "pack of green grape seeds" + desc = "These seeds grow into green-grape vines." + icon_state = "seed-greengrapes" + mypath = "/obj/item/seeds/greengrapeseed" + species = "greengrape" + plantname = "Green-Grape Vine" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 2 + +/obj/item/seeds/cabbageseed + name = "pack of cabbage seeds" + desc = "These seeds grow into cabbages." + icon_state = "seed-cabbage" + mypath = "/obj/item/seeds/cabbageseed" + species = "cabbage" + plantname = "Cabbages" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/cabbage" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 1 + +/obj/item/seeds/shandseed + name = "pack of s'rendarr's hand seeds" + desc = "These seeds grow into a helpful herb called S'Rendarr's Hand, native to Ahdomai." + icon_state = "seed-shand" + mypath = "/obj/item/seeds/shandseed" + species = "shand" + plantname = "S'Rendarr's Hand" + productname = "/obj/item/stack/medical/bruise_pack/tajaran" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 3 + +/obj/item/seeds/mtearseed + name = "pack of messa's tear seeds" + desc = "These seeds grow into a helpful herb called Messa's Tear, native to Ahdomai." + icon_state = "seed-mtear" + mypath = "/obj/item/seeds/mtearseed" + species = "mtear" + plantname = "Messa's Tear" + productname = "/obj/item/stack/medical/ointment/tajaran" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 3 + +/obj/item/seeds/berryseed + name = "pack of berry seeds" + desc = "These seeds grow into berry bushes." + icon_state = "seed-berry" + mypath = "/obj/item/seeds/berryseed" + species = "berry" + plantname = "Berry Bush" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/berries" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/glowberryseed + name = "pack of glow-berry seeds" + desc = "These seeds grow into glow-berry bushes." + icon_state = "seed-glowberry" + mypath = "/obj/item/seeds/glowberryseed" + species = "glowberry" + plantname = "Glow-Berry Bush" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/glowberries" + lifespan = 30 + endurance = 25 + maturation = 5 + production = 5 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/bananaseed + name = "pack of banana seeds" + desc = "They're seeds that grow into banana trees." + icon_state = "seed-banana" + mypath = "/obj/item/seeds/bananaseed" + species = "banana" + plantname = "Banana Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/banana" + lifespan = 50 + endurance = 30 + maturation = 6 + production = 6 + yield = 3 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/eggplantseed + name = "pack of eggplant seeds" + desc = "These seeds grow to produce berries that look nothing like eggs." + icon_state = "seed-eggplant" + mypath = "/obj/item/seeds/eggplantseed" + species = "eggplant" + plantname = "Eggplants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant" + lifespan = 25 + endurance = 15 + maturation = 6 + production = 6 + yield = 2 + potency = 20 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/eggyseed + name = "pack of eggplant seeds" + desc = "These seeds grow to produce berries that look a lot like eggs." + icon_state = "seed-eggy" + mypath = "/obj/item/seeds/eggy" + species = "eggy" + plantname = "Eggplants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/egg" + lifespan = 75 + endurance = 15 + maturation = 6 + production = 12 + yield = 2 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/bloodtomatoseed + name = "pack of blood-tomato seeds" + desc = "These seeds grow into blood-tomato plants." + icon_state = "seed-bloodtomato" + mypath = "/obj/item/seeds/bloodtomatoseed" + species = "bloodtomato" + plantname = "Blood-Tomato Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato" + lifespan = 25 + endurance = 20 + maturation = 8 + production = 6 + yield = 3 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/tomatoseed + name = "pack of tomato seeds" + desc = "These seeds grow into tomato plants." + icon_state = "seed-tomato" + mypath = "/obj/item/seeds/tomatoseed" + species = "tomato" + plantname = "Tomato Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/tomato" + lifespan = 25 + endurance = 15 + maturation = 8 + production = 6 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/killertomatoseed + name = "pack of killer-tomato seeds" + desc = "These seeds grow into killer-tomato plants." + icon_state = "seed-killertomato" + mypath = "/obj/item/seeds/killertomatoseed" + species = "killertomato" + plantname = "Killer-Tomato Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato" + lifespan = 25 + endurance = 15 + maturation = 8 + production = 6 + yield = 2 + potency = 10 + plant_type = 0 + oneharvest = 1 + growthstages = 2 + +/obj/item/seeds/bluetomatoseed + name = "pack of blue-tomato seeds" + desc = "These seeds grow into blue-tomato plants." + icon_state = "seed-bluetomato" + mypath = "/obj/item/seeds/bluetomatoseed" + species = "bluetomato" + plantname = "Blue-Tomato Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/bluetomato" + lifespan = 25 + endurance = 15 + maturation = 8 + production = 6 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/bluespacetomatoseed + name = "pack of blue-space tomato seeds" + desc = "These seeds grow into blue-space tomato plants." + icon_state = "seed-bluespacetomato" + mypath = "/obj/item/seeds/bluespacetomatoseed" + species = "bluespacetomato" + plantname = "Blue-Space Tomato Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato" + lifespan = 25 + endurance = 15 + maturation = 8 + production = 6 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/cornseed + name = "pack of corn seeds" + desc = "I don't mean to sound corny..." + icon_state = "seed-corn" + mypath = "/obj/item/seeds/cornseed" + species = "corn" + plantname = "Corn Stalks" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/corn" + lifespan = 25 + endurance = 15 + maturation = 8 + production = 6 + yield = 3 + plant_type = 0 + oneharvest = 1 + potency = 20 + growthstages = 3 + +/obj/item/seeds/poppyseed + name = "pack of poppy seeds" + desc = "These seeds grow into poppies." + icon_state = "seed-poppy" + mypath = "/obj/item/seeds/poppyseed" + species = "poppy" + plantname = "Poppy Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/poppy" + lifespan = 25 + endurance = 10 + potency = 20 + maturation = 8 + production = 6 + yield = 6 + plant_type = 0 + oneharvest = 1 + growthstages = 3 + +/obj/item/seeds/potatoseed + name = "pack of potato seeds" + desc = "Boil 'em! Mash 'em! Stick 'em in a stew!" + icon_state = "seed-potato" + mypath = "/obj/item/seeds/potatoseed" + species = "potato" + plantname = "Potato-Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/potato" + lifespan = 30 + endurance = 15 + maturation = 10 + production = 1 + yield = 4 + plant_type = 0 + oneharvest = 1 + potency = 10 + growthstages = 4 + +/obj/item/seeds/icepepperseed + name = "pack of ice-pepper seeds" + desc = "These seeds grow into ice-pepper plants." + icon_state = "seed-icepepper" + mypath = "/obj/item/seeds/icepepperseed" + species = "chiliice" + plantname = "Ice-Pepper Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/icepepper" + lifespan = 25 + endurance = 15 + maturation = 4 + production = 4 + yield = 4 + potency = 20 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/soyaseed + name = "pack of soybean seeds" + desc = "These seeds grow into soybean plants." + icon_state = "seed-soybean" + mypath = "/obj/item/seeds/soyaseed" + species = "soybean" + plantname = "Soybean Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans" + lifespan = 25 + endurance = 15 + maturation = 4 + production = 4 + yield = 3 + potency = 5 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/koiseed + name = "pack of koibean seeds" + desc = "These seeds grow into koibean plants." + icon_state = "seed-koibean" + mypath = "/obj/item/seeds/koiseed" + species = "koibean" + plantname = "Koibean Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/koibeans" + lifespan = 25 + endurance = 15 + maturation = 4 + production = 4 + yield = 3 + potency = 10 + plant_type = 0 + growthstages = 4 + +/obj/item/seeds/wheatseed + name = "pack of wheat seeds" + desc = "These may, or may not, grow into weed." + icon_state = "seed-wheat" + mypath = "/obj/item/seeds/wheatseed" + species = "wheat" + plantname = "Wheat Stalks" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/wheat" + lifespan = 25 + endurance = 15 + maturation = 6 + production = 1 + yield = 4 + potency = 5 + oneharvest = 1 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/riceseed + name = "pack of rice seeds" + desc = "These seeds grow into rice stalks." + icon_state = "seed-rice" + mypath = "/obj/item/seeds/riceseed" + species = "rice" + plantname = "Rice Stalks" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk" + lifespan = 25 + endurance = 15 + maturation = 6 + production = 1 + yield = 4 + potency = 5 + oneharvest = 1 + plant_type = 0 + growthstages = 4 + +/obj/item/seeds/carrotseed + name = "pack of carrot seeds" + desc = "These seeds grow into carrots." + icon_state = "seed-carrot" + mypath = "/obj/item/seeds/carrotseed" + species = "carrot" + plantname = "Carrots" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/carrot" + lifespan = 25 + endurance = 15 + maturation = 10 + production = 1 + yield = 5 + potency = 10 + oneharvest = 1 + plant_type = 0 + growthstages = 3 + +/obj/item/seeds/reishimycelium + name = "pack of reishi mycelium" + desc = "This mycelium grows into something relaxing." + icon_state = "mycelium-reishi" + mypath = "/obj/item/seeds/reishimycelium" + species = "reishi" + plantname = "Reishi" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/reishi" + lifespan = 35 + endurance = 35 + maturation = 10 + production = 5 + yield = 4 + potency = 15 // Sleeping based on potency? + oneharvest = 1 + growthstages = 4 + plant_type = 2 + +/obj/item/seeds/amanitamycelium + name = "pack of fly amanita mycelium" + desc = "This mycelium grows into something horrible." + icon_state = "mycelium-amanita" + mypath = "/obj/item/seeds/amanitamycelium" + species = "amanita" + plantname = "Fly Amanitas" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita" + lifespan = 50 + endurance = 35 + maturation = 10 + production = 5 + yield = 4 + potency = 10 // Damage based on potency? + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/angelmycelium + name = "pack of destroying angel mycelium" + desc = "This mycelium grows into something devastating." + icon_state = "mycelium-angel" + mypath = "/obj/item/seeds/angelmycelium" + species = "angel" + plantname = "Destroying Angels" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel" + lifespan = 50 + endurance = 35 + maturation = 12 + production = 5 + yield = 2 + potency = 35 + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/libertymycelium + name = "pack of liberty-cap mycelium" + desc = "This mycelium grows into liberty-cap mushrooms." + icon_state = "mycelium-liberty" + mypath = "/obj/item/seeds/libertymycelium" + species = "liberty" + plantname = "Liberty-Caps" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap" + lifespan = 25 + endurance = 15 + maturation = 7 + production = 1 + yield = 5 + potency = 15 // Lowish potency at start + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/chantermycelium + name = "pack of chanterelle mycelium" + desc = "This mycelium grows into chanterelle mushrooms." + icon_state = "mycelium-chanter" + mypath = "/obj/item/seeds/chantermycelium" + species = "chanter" + plantname = "Chanterelle Mushrooms" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle" + lifespan = 35 + endurance = 20 + maturation = 7 + production = 1 + yield = 5 + potency = 1 + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/towermycelium + name = "pack of tower-cap mycelium" + desc = "This mycelium grows into tower-cap mushrooms." + icon_state = "mycelium-tower" + mypath = "/obj/item/seeds/towermycelium" + species = "towercap" + plantname = "Tower Caps" + productname = "/obj/item/weapon/grown/log" + lifespan = 80 + endurance = 50 + maturation = 15 + production = 1 + yield = 5 + potency = 1 + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/glowshroom + name = "pack of glowshroom mycelium" + desc = "This mycelium -glows- into mushrooms!" + icon_state = "mycelium-glowshroom" + mypath = "/obj/item/seeds/glowshroom" + species = "glowshroom" + plantname = "Glowshrooms" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom" + lifespan = 120 //ten times that is the delay + endurance = 30 + maturation = 15 + production = 1 + yield = 3 //-> spread + potency = 30 //-> brightness + oneharvest = 1 + growthstages = 4 + plant_type = 2 + +/obj/item/seeds/plumpmycelium + name = "pack of plump-helmet mycelium" + desc = "This mycelium grows into helmets... maybe." + icon_state = "mycelium-plump" + mypath = "/obj/item/seeds/plumpmycelium" + species = "plump" + plantname = "Plump-Helmet Mushrooms" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet" + lifespan = 25 + endurance = 15 + maturation = 8 + production = 1 + yield = 4 + potency = 0 + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/walkingmushroommycelium + name = "pack of walking mushroom mycelium" + desc = "This mycelium will grow into huge stuff!" + icon_state = "mycelium-walkingmushroom" + mypath = "/obj/item/seeds/walkingmushroommycelium" + species = "walkingmushroom" + plantname = "Walking Mushrooms" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom" + lifespan = 30 + endurance = 30 + maturation = 5 + production = 1 + yield = 1 + potency = 0 + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/nettleseed + name = "pack of nettle seeds" + desc = "These seeds grow into nettles." + icon_state = "seed-nettle" + mypath = "/obj/item/seeds/nettleseed" + species = "nettle" + plantname = "Nettles" + productname = "/obj/item/weapon/grown/nettle" + lifespan = 30 + endurance = 40 // tuff like a toiger + maturation = 6 + production = 6 + yield = 4 + potency = 10 + oneharvest = 0 + growthstages = 5 + plant_type = 1 + +/obj/item/seeds/deathnettleseed + name = "pack of death-nettle seeds" + desc = "These seeds grow into death-nettles." + icon_state = "seed-deathnettle" + mypath = "/obj/item/seeds/deathnettleseed" + species = "deathnettle" + plantname = "Death Nettles" + productname = "/obj/item/weapon/grown/deathnettle" + lifespan = 30 + endurance = 25 + maturation = 8 + production = 6 + yield = 2 + potency = 10 + oneharvest = 0 + growthstages = 5 + plant_type = 1 + +/obj/item/seeds/weeds + name = "pack of weed seeds" + desc = "Yo mang, want some weeds?" + icon_state = "seed" + mypath = "/obj/item/seeds/weeds" + species = "weeds" + plantname = "Starthistle" + productname = "" + lifespan = 100 + endurance = 50 // damm pesky weeds + maturation = 5 + production = 1 + yield = -1 + potency = -1 + oneharvest = 1 + growthstages = 4 + plant_type = 1 + +/obj/item/seeds/harebell + name = "pack of harebell seeds" + desc = "These seeds grow into pretty little flowers." + icon_state = "seed-harebell" + mypath = "/obj/item/seeds/harebell" + species = "harebell" + plantname = "Harebells" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/harebell" + lifespan = 100 + endurance = 20 + maturation = 7 + production = 1 + yield = 2 + potency = 1 + oneharvest = 1 + growthstages = 4 + plant_type = 1 + +/obj/item/seeds/sunflowerseed + name = "pack of sunflower seeds" + desc = "These seeds grow into sunflowers." + icon_state = "seed-sunflower" + mypath = "/obj/item/seeds/sunflowerseed" + species = "sunflower" + plantname = "Sunflowers" + productname = "/obj/item/weapon/grown/sunflower" + lifespan = 25 + endurance = 20 + maturation = 6 + production = 1 + yield = 2 + potency = 1 + oneharvest = 1 + growthstages = 3 + plant_type = 1 + +/obj/item/seeds/moonflowerseed + name = "pack of moonflower seeds" + desc = "These seeds grow into moonflowers." + icon_state = "seed-moonflower" + mypath = "/obj/item/seeds/moonflowerseed" + species = "moonflower" + plantname = "Moonflowers" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower" + lifespan = 25 + endurance = 20 + maturation = 6 + production = 2 + yield = 2 + potency = 15 + oneharvest = 1 + growthstages = 3 + plant_type = 0 + +/obj/item/seeds/novaflowerseed + name = "pack of novaflower seeds" + desc = "These seeds grow into novaflowers." + icon_state = "seed-novaflower" + mypath = "/obj/item/seeds/novaflowerseed" + species = "novaflower" + plantname = "Novaflowers" + productname = "/obj/item/weapon/grown/novaflower" + lifespan = 25 + endurance = 20 + maturation = 6 + production = 2 + yield = 2 + potency = 20 + oneharvest = 1 + growthstages = 3 + plant_type = 0 + +/obj/item/seeds/brownmold + name = "pack of brown mold" + desc = "Eww.. moldy." + icon_state = "seed" + mypath = "/obj/item/seeds/brownmold" + species = "mold" + plantname = "Brown Mold" + productname = "" + lifespan = 50 + endurance = 30 + maturation = 10 + production = 1 + yield = -1 + potency = 1 + oneharvest = 1 + growthstages = 3 + plant_type = 2 + +/obj/item/seeds/appleseed + name = "pack of apple seeds" + desc = "These seeds grow into apple trees." + icon_state = "seed-apple" + mypath = "/obj/item/seeds/appleseed" + species = "apple" + plantname = "Apple Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/apple" + lifespan = 55 + endurance = 35 + maturation = 6 + production = 6 + yield = 5 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/poisonedappleseed + name = "pack of apple seeds" + desc = "These seeds grow into apple trees." + icon_state = "seed-apple" + mypath = "/obj/item/seeds/poisonedappleseed" + species = "apple" + plantname = "Apple Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned" + lifespan = 55 + endurance = 35 + maturation = 6 + production = 6 + yield = 5 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/goldappleseed + name = "pack of golden apple seeds" + desc = "These seeds grow into golden apple trees. Good thing there are no firebirds in space." + icon_state = "seed-goldapple" + mypath = "/obj/item/seeds/goldappleseed" + species = "goldapple" + plantname = "Golden Apple Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/goldapple" + lifespan = 55 + endurance = 35 + maturation = 10 + production = 10 + yield = 3 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/ambrosiavulgarisseed + name = "pack of ambrosia vulgaris seeds" + desc = "These seeds grow into common ambrosia, a plant grown by and from medicine." + icon_state = "seed-ambrosiavulgaris" + mypath = "/obj/item/seeds/ambrosiavulgarisseed" + species = "ambrosiavulgaris" + plantname = "Ambrosia Vulgaris" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris" + lifespan = 60 + endurance = 25 + maturation = 6 + production = 6 + yield = 6 + potency = 5 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/ambrosiavulgarisseed/cruciatus + name = "pack of ambrosia vulgaris seeds" + desc = "These seeds grow into common ambrosia, a plant grown by and from medicine." + icon_state = "seed-ambrosiavulgaris" + mypath = "/obj/item/seeds/ambrosiavulgarisseed/cruciatus" + species = "ambrosiavulgaris" + plantname = "Ambrosia Vulgaris" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/cruciatus" + lifespan = 60 + endurance = 25 + maturation = 6 + production = 6 + yield = 6 + potency = 5 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/ambrosiadeusseed + name = "pack of ambrosia deus seeds" + desc = "These seeds grow into ambrosia deus. Could it be the food of the gods..?" + icon_state = "seed-ambrosiadeus" + mypath = "/obj/item/seeds/ambrosiadeusseed" + species = "ambrosiadeus" + plantname = "Ambrosia Deus" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus" + lifespan = 60 + endurance = 25 + maturation = 6 + production = 6 + yield = 6 + potency = 5 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/whitebeetseed + name = "pack of white-beet seeds" + desc = "These seeds grow into sugary beet producing plants." + icon_state = "seed-whitebeet" + mypath = "/obj/item/seeds/whitebeetseed" + species = "whitebeet" + plantname = "White-Beet Plants" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet" + lifespan = 60 + endurance = 50 + maturation = 6 + production = 6 + yield = 6 + oneharvest = 1 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/sugarcaneseed + name = "pack of sugarcane seeds" + desc = "These seeds grow into sugarcane." + icon_state = "seed-sugarcane" + mypath = "/obj/item/seeds/sugarcaneseed" + species = "sugarcane" + plantname = "Sugarcane" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/sugarcane" + lifespan = 60 + endurance = 50 + maturation = 3 + production = 6 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 3 + +/obj/item/seeds/watermelonseed + name = "pack of watermelon seeds" + desc = "These seeds grow into watermelon plants." + icon_state = "seed-watermelon" + mypath = "/obj/item/seeds/watermelonseed" + species = "watermelon" + plantname = "Watermelon Vines" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/watermelon" + lifespan = 50 + endurance = 40 + maturation = 6 + production = 6 + yield = 3 + potency = 1 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/pumpkinseed + name = "pack of pumpkin seeds" + desc = "These seeds grow into pumpkin vines." + icon_state = "seed-pumpkin" + mypath = "/obj/item/seeds/pumpkinseed" + species = "pumpkin" + plantname = "Pumpkin Vines" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin" + lifespan = 50 + endurance = 40 + maturation = 6 + production = 6 + yield = 3 + potency = 10 + plant_type = 0 + growthstages = 3 + + +/obj/item/seeds/limeseed + name = "pack of lime seeds" + desc = "These are very sour seeds." + icon_state = "seed-lime" + mypath = "/obj/item/seeds/limeseed" + species = "lime" + plantname = "Lime Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/lime" + lifespan = 55 + endurance = 50 + maturation = 6 + production = 6 + yield = 4 + potency = 15 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/lemonseed + name = "pack of lemon seeds" + desc = "These are sour seeds." + icon_state = "seed-lemon" + mypath = "/obj/item/seeds/lemonseed" + species = "lemon" + plantname = "Lemon Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/lemon" + lifespan = 55 + endurance = 45 + maturation = 6 + production = 6 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/cashseed + name = "pack of money seeds" + desc = "When life gives you lemons, mutate them into cash." + icon_state = "seed-cash" + mypath = "/obj/item/seeds/cashseed" + species = "cashtree" + plantname = "Money Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/money" + lifespan = 55 + endurance = 45 + maturation = 6 + production = 6 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/orangeseed + name = "pack of orange seed" + desc = "Sour seeds." + icon_state = "seed-orange" + mypath = "/obj/item/seeds/orangeseed" + species = "orange" + plantname = "Orange Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/orange" + lifespan = 60 + endurance = 50 + maturation = 6 + production = 6 + yield = 5 + potency = 1 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/poisonberryseed + name = "pack of poison-berry seeds" + desc = "These seeds grow into poison-berry bushes." + icon_state = "seed-poisonberry" + mypath = "/obj/item/seeds/poisonberryseed" + species = "poisonberry" + plantname = "Poison-Berry Bush" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/deathberryseed + name = "pack of death-berry seeds" + desc = "These seeds grow into death berries." + icon_state = "seed-deathberry" + mypath = "/obj/item/seeds/deathberryseed" + species = "deathberry" + plantname = "Death Berry Bush" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/deathberries" + lifespan = 30 + endurance = 20 + maturation = 5 + production = 5 + yield = 3 + potency = 50 + plant_type = 0 + growthstages = 6 + +/obj/item/seeds/grassseed + name = "pack of grass seeds" + desc = "These seeds grow into grass. Yummy!" + icon_state = "seed-grass" + mypath = "/obj/item/seeds/grassseed" + species = "grass" + plantname = "Grass" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/grass" + lifespan = 60 + endurance = 50 + maturation = 2 + production = 5 + yield = 5 + plant_type = 0 + growthstages = 2 + +/obj/item/seeds/cocoapodseed + name = "pack of cocoa pod seeds" + desc = "These seeds grow into cacao trees. They look fattening." //SIC: cocoa is the seeds. The tress ARE spelled cacao. + icon_state = "seed-cocoapod" + mypath = "/obj/item/seeds/cocoapodseed" + species = "cocoapod" + plantname = "Cocao Tree" //SIC: see above + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 2 + potency = 10 + plant_type = 0 + growthstages = 5 + +/obj/item/seeds/cherryseed + name = "pack of cherry pits" + desc = "Careful not to crack a tooth on one... That'd be the pits." + icon_state = "seed-cherry" + mypath = "/obj/item/seeds/cherryseed" + species = "cherry" + plantname = "Cherry Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/cherries" + lifespan = 35 + endurance = 35 + maturation = 5 + production = 5 + yield = 3 + potency = 10 + plant_type = 0 + growthstages = 5 + +/obj/item/seeds/kudzuseed + name = "pack of kudzu seeds" + desc = "These seeds grow into a weed that grows incredibly fast." + icon_state = "seed-kudzu" + mypath = "/obj/item/seeds/kudzuseed" + species = "kudzu" + plantname = "Kudzu" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod" + lifespan = 20 + endurance = 10 + maturation = 6 + production = 6 + yield = 4 + potency = 10 + growthstages = 4 + plant_type = 1 + +/obj/item/seeds/synthmeatseed + name = "pack of synthmeat seeds" + desc = "These seeds grow into a synthmeat tree." + icon_state = "seed-synthmeat" + mypath = "/obj/item/seeds/synthmeatseed" + species = "synthmeat" + plantname = "Synthmeat Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/meat" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 2 + +/obj/item/seeds/synthbuttseed //*fart + name = "pack of synthbutt seeds" + desc = "These butts butt into a synthbutt butt." + icon_state = "seed-synthbutt" + mypath = "/obj/item/seeds/synthbuttseed" + species = "synthbutt" + plantname = "Synthbutt Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/butt" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 2 + +/obj/item/seeds/synthbrainseed + name = "pack of synthbrain seeds" + desc = "These seeds grow into a synthbrain tree." + icon_state = "seed-synthbrain" + mypath = "/obj/item/seeds/synthbrainseed" + species = "synthbrain" + plantname = "Synthbrain Tree" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/brain" + lifespan = 20 + endurance = 15 + maturation = 5 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 2 + +/obj/item/seeds/kudzuseed/attack_self(mob/user as mob) + if(istype(user.loc,/turf/space)) + return to_chat(user, "You plant the kudzu. You monster.") - new /obj/effect/plantsegment_controller(user.loc) - qdel(src) - - - -/* // Maybe one day when I get it to work like a grenade which exlodes gibs. -/obj/item/seeds/gibtomatoseed - name = "Gib Tomato seeds" - desc = "Used to grow gib tomotoes." - icon_state = "seed-gibtomato" - mypath = "/obj/item/seeds/gibtomatoseed" - species = "gibtomato" - plantname = "Gib Tomato plant" - productname = "/obj/item/weapon/grown/gibtomato" - lifespan = 35 - endurance = 25 - maturation = 6 - production = 6 - yield = 3 - potency = 10 - plant_type = 0 - growthstages = 6 -*/ - -/* -/obj/item/seeds/ - name = "" - icon_state = "seed" - mypath = "/obj/item/seeds/" - species = "" - plantname = "" - productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/" - lifespan = 25 - endurance = 15 - maturation = 10 - production = 1 - yield = -1 - potency = 0 - oneharvest = 1 - growthstages = 3 - plant_type = 0 - -*/ - -// *****************oolokitthesefancystars******** -// Grown FOOD types moved to reagents -// ********************** - -// ********************** -// Other harvested materials from plants (that are not food) -// ********************** - -/obj/item/weapon/grown // Grown weapons - name = "grown_weapon" - icon = 'icons/obj/weapons.dmi' - var/seed = "" - var/plantname = "" - var/productname = "" - var/species = "" - var/lifespan = 20 - var/endurance = 15 - var/maturation = 7 - var/production = 7 - var/yield = 2 - var/potency = 1 - var/plant_type = 0 - -/obj/item/weapon/grown/New() - . = ..() - create_reagents(50) - -/obj/item/weapon/grown/proc/changePotency(newValue) //-QualityVan - potency = newValue - -/obj/item/weapon/grown/log - name = "tower-cap log" - desc = "It's better than bad, it's good!" - icon = 'icons/obj/harvest.dmi' - icon_state = "logs" - force = 5 - flags = TABLEPASS - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - plant_type = 2 - origin_tech = "materials=1" - seed = "/obj/item/seeds/towermycelium" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - - - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || (istype(W, /obj/item/weapon/twohanded/fireaxe) && W:wielded) || istype(W, /obj/item/weapon/melee/energy)) - user.show_message("You make planks out of the [src]!", 1) - for(var/i=0,i<2,i++) - var/obj/item/stack/sheet/wood/NG = new (user.loc) - for (var/obj/item/stack/sheet/wood/G in user.loc) - if(G==NG) - continue - if(G.amount>=G.max_amount) - continue - G.attackby(NG, user) + new /obj/effect/plantsegment_controller(user.loc) + qdel(src) + + + +/* // Maybe one day when I get it to work like a grenade which exlodes gibs. +/obj/item/seeds/gibtomatoseed + name = "Gib Tomato seeds" + desc = "Used to grow gib tomotoes." + icon_state = "seed-gibtomato" + mypath = "/obj/item/seeds/gibtomatoseed" + species = "gibtomato" + plantname = "Gib Tomato plant" + productname = "/obj/item/weapon/grown/gibtomato" + lifespan = 35 + endurance = 25 + maturation = 6 + production = 6 + yield = 3 + potency = 10 + plant_type = 0 + growthstages = 6 +*/ + +/* +/obj/item/seeds/ + name = "" + icon_state = "seed" + mypath = "/obj/item/seeds/" + species = "" + plantname = "" + productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/" + lifespan = 25 + endurance = 15 + maturation = 10 + production = 1 + yield = -1 + potency = 0 + oneharvest = 1 + growthstages = 3 + plant_type = 0 + +*/ + +// *****************oolokitthesefancystars******** +// Grown FOOD types moved to reagents +// ********************** + +// ********************** +// Other harvested materials from plants (that are not food) +// ********************** + +/obj/item/weapon/grown // Grown weapons + name = "grown_weapon" + icon = 'icons/obj/weapons.dmi' + var/seed = "" + var/plantname = "" + var/productname = "" + var/species = "" + var/lifespan = 20 + var/endurance = 15 + var/maturation = 7 + var/production = 7 + var/yield = 2 + var/potency = 1 + var/plant_type = 0 + +/obj/item/weapon/grown/New() + . = ..() + create_reagents(50) + +/obj/item/weapon/grown/proc/changePotency(newValue) //-QualityVan + potency = newValue + +/obj/item/weapon/grown/log + name = "tower-cap log" + desc = "It's better than bad, it's good!" + icon = 'icons/obj/harvest.dmi' + icon_state = "logs" + force = 5 + flags = TABLEPASS + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + plant_type = 2 + origin_tech = "materials=1" + seed = "/obj/item/seeds/towermycelium" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || (istype(W, /obj/item/weapon/twohanded/fireaxe) && W:wielded) || istype(W, /obj/item/weapon/melee/energy)) + user.show_message("You make planks out of the [src]!", 1) + for(var/i=0,i<2,i++) + var/obj/item/stack/sheet/wood/NG = new (user.loc) + for (var/obj/item/stack/sheet/wood/G in user.loc) + if(G==NG) + continue + if(G.amount>=G.max_amount) + continue + G.attackby(NG, user) to_chat(usr, "You add the newly-formed wood to the stack. It now contains [NG.amount] planks.") - qdel(src) - return - -/obj/item/weapon/grown/sunflower // FLOWER POWER! - name = "sunflower" - desc = "It's beautiful! A certain person might beat you to death if you trample these." - icon = 'icons/obj/harvest.dmi' - icon_state = "sunflower" - damtype = "fire" - force = 0 - flags = TABLEPASS - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - seed = "/obj/item/seeds/sunflower" - -/obj/item/weapon/grown/novaflower - name = "novaflower" - desc = "These beautiful flowers have a crisp smokey scent, like a summer bonfire." - icon = 'icons/obj/harvest.dmi' - icon_state = "novaflower" - damtype = "fire" - force = 0 - flags = TABLEPASS - slot_flags = SLOT_HEAD - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - plant_type = 0 - seed = "/obj/item/seeds/novaflower" - attack_verb = list("seared", "heated", "whacked", "steamed") - -/obj/item/weapon/grown/novaflower/New() - . = ..() - - spawn(5) // So potency can be set in the proc that creates these crops - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("capsaicin", round(potency, 1)) - force = round((5 + potency / 5), 1) - -/* -/obj/item/weapon/grown/gibtomato - desc = "A plump tomato." - icon = 'icons/obj/harvest.dmi' - name = "Gib Tomato" - icon_state = "gibtomato" - damtype = "fire" - force = 0 - flags = TABLEPASS - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - seed = "/obj/item/seeds/gibtomato" - New() - ..() - - -/obj/item/weapon/grown/gibtomato/New() - ..() - src.gibs = new /obj/effect/gibspawner/human(get_turf(src)) - src.gibs.attach(src) - src.smoke.set_up(10, 0, usr.loc) -*/ -/obj/item/weapon/grown/nettle // -- Skie - desc = "It's probably not wise to touch it with bare hands..." - icon = 'icons/obj/weapons.dmi' - name = "nettle" - icon_state = "nettle" - damtype = "fire" - force = 15 - flags = TABLEPASS - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - origin_tech = "combat=1" - seed = "/obj/item/seeds/nettleseed" - -/obj/item/weapon/grown/nettle/New() - . = ..() - - spawn(5) //So potency can be set in the proc that creates these crops - reagents.add_reagent("nutriment", 1 + round((potency / 50), 1)) - reagents.add_reagent("sacid", round(potency, 1)) - force = round((5 + potency / 5), 1) - -/obj/item/weapon/grown/deathnettle // -- Skie - desc = "The glowing nettle incites rage in you just from looking at it!" - icon = 'icons/obj/weapons.dmi' - name = "deathnettle" - icon_state = "deathnettle" - damtype = "fire" - force = 30 - flags = TABLEPASS - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - seed = "/obj/item/seeds/deathnettleseed" - origin_tech = "combat=3" - attack_verb = list("stung") - - - suicide_act(mob/user) + qdel(src) + return + +/obj/item/weapon/grown/sunflower // FLOWER POWER! + name = "sunflower" + desc = "It's beautiful! A certain person might beat you to death if you trample these." + icon = 'icons/obj/harvest.dmi' + icon_state = "sunflower" + damtype = "fire" + force = 0 + flags = TABLEPASS + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + seed = "/obj/item/seeds/sunflower" + +/obj/item/weapon/grown/novaflower + name = "novaflower" + desc = "These beautiful flowers have a crisp smokey scent, like a summer bonfire." + icon = 'icons/obj/harvest.dmi' + icon_state = "novaflower" + damtype = "fire" + force = 0 + flags = TABLEPASS + slot_flags = SLOT_HEAD + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + plant_type = 0 + seed = "/obj/item/seeds/novaflower" + attack_verb = list("seared", "heated", "whacked", "steamed") + +/obj/item/weapon/grown/novaflower/New() + . = ..() + + spawn(5) // So potency can be set in the proc that creates these crops + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("capsaicin", round(potency, 1)) + force = round((5 + potency / 5), 1) + +/* +/obj/item/weapon/grown/gibtomato + desc = "A plump tomato." + icon = 'icons/obj/harvest.dmi' + name = "Gib Tomato" + icon_state = "gibtomato" + damtype = "fire" + force = 0 + flags = TABLEPASS + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + seed = "/obj/item/seeds/gibtomato" + New() + ..() + + +/obj/item/weapon/grown/gibtomato/New() + ..() + src.gibs = new /obj/effect/gibspawner/human(get_turf(src)) + src.gibs.attach(src) + src.smoke.set_up(10, 0, usr.loc) +*/ +/obj/item/weapon/grown/nettle // -- Skie + desc = "It's probably not wise to touch it with bare hands..." + icon = 'icons/obj/weapons.dmi' + name = "nettle" + icon_state = "nettle" + damtype = "fire" + force = 15 + flags = TABLEPASS + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + origin_tech = "combat=1" + seed = "/obj/item/seeds/nettleseed" + +/obj/item/weapon/grown/nettle/New() + . = ..() + + spawn(5) //So potency can be set in the proc that creates these crops + reagents.add_reagent("nutriment", 1 + round((potency / 50), 1)) + reagents.add_reagent("sacid", round(potency, 1)) + force = round((5 + potency / 5), 1) + +/obj/item/weapon/grown/deathnettle // -- Skie + desc = "The glowing nettle incites rage in you just from looking at it!" + icon = 'icons/obj/weapons.dmi' + name = "deathnettle" + icon_state = "deathnettle" + damtype = "fire" + force = 30 + flags = TABLEPASS + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + seed = "/obj/item/seeds/deathnettleseed" + origin_tech = "combat=3" + attack_verb = list("stung") + + + suicide_act(mob/user) to_chat(viewers(user), "[user] is eating some of the [src.name]! It looks like \he's trying to commit suicide.") - return (BRUTELOSS|TOXLOSS) - -/obj/item/weapon/grown/deathnettle/New() - . = ..() - - spawn(5) //So potency can be set in the proc that creates these crops - reagents.add_reagent("nutriment", 1 + round((potency / 50), 1)) - reagents.add_reagent("pacid", round(potency, 1)) - force = round((5 + potency / 2.5), 1) - - -// ************************************* -// Pestkiller defines for hydroponics -// ************************************* - -/obj/item/pestkiller - name = "bottle of pestkiller" - icon_state = "bottle16" - flags = FPRINT | TABLEPASS - var/toxicity = 0 - var/PestKillStr = 0 - -/obj/item/pestkiller/New() - . = ..() - pixel_x = rand(-5.0, 5) - pixel_y = rand(-5.0, 5) - -/obj/item/pestkiller/carbaryl - name = "bottle of carbaryl" - icon_state = "bottle16" - toxicity = 4 - PestKillStr = 2 - -/obj/item/pestkiller/lindane - name = "bottle of lindane" - icon_state = "bottle18" - toxicity = 6 - PestKillStr = 4 - -/obj/item/pestkiller/phosmet - name = "bottle of phosmet" - icon_state = "bottle15" - toxicity = 8 - PestKillStr = 7 - -// ************************************* -// Hydroponics Tools -// ************************************* - -/obj/item/weapon/weedspray // -- Skie - desc = "It's a toxic mixture, in spray form, to kill small weeds." - icon = 'icons/obj/hydroponics.dmi' - name = "weed-spray" - icon_state = "weedspray" - item_state = "spray" - flags = TABLEPASS | OPENCONTAINER | FPRINT | NOBLUDGEON - slot_flags = SLOT_BELT - throwforce = 4 - w_class = 2.0 - throw_speed = 2 - throw_range = 10 - var/toxicity = 4 - var/WeedKillStr = 2 - - suicide_act(mob/user) + return (BRUTELOSS|TOXLOSS) + +/obj/item/weapon/grown/deathnettle/New() + . = ..() + + spawn(5) //So potency can be set in the proc that creates these crops + reagents.add_reagent("nutriment", 1 + round((potency / 50), 1)) + reagents.add_reagent("pacid", round(potency, 1)) + force = round((5 + potency / 2.5), 1) + + +// ************************************* +// Pestkiller defines for hydroponics +// ************************************* + +/obj/item/pestkiller + name = "bottle of pestkiller" + icon_state = "bottle16" + flags = FPRINT | TABLEPASS + var/toxicity = 0 + var/PestKillStr = 0 + +/obj/item/pestkiller/New() + . = ..() + pixel_x = rand(-5.0, 5) + pixel_y = rand(-5.0, 5) + +/obj/item/pestkiller/carbaryl + name = "bottle of carbaryl" + icon_state = "bottle16" + toxicity = 4 + PestKillStr = 2 + +/obj/item/pestkiller/lindane + name = "bottle of lindane" + icon_state = "bottle18" + toxicity = 6 + PestKillStr = 4 + +/obj/item/pestkiller/phosmet + name = "bottle of phosmet" + icon_state = "bottle15" + toxicity = 8 + PestKillStr = 7 + +// ************************************* +// Hydroponics Tools +// ************************************* + +/obj/item/weapon/weedspray // -- Skie + desc = "It's a toxic mixture, in spray form, to kill small weeds." + icon = 'icons/obj/hydroponics.dmi' + name = "weed-spray" + icon_state = "weedspray" + item_state = "spray" + flags = TABLEPASS | OPENCONTAINER | FPRINT | NOBLUDGEON + slot_flags = SLOT_BELT + throwforce = 4 + w_class = 2.0 + throw_speed = 2 + throw_range = 10 + var/toxicity = 4 + var/WeedKillStr = 2 + + suicide_act(mob/user) to_chat(viewers(user), "[user] is huffing the [src.name]! It looks like \he's trying to commit suicide.") - return (TOXLOSS) - -/obj/item/weapon/pestspray // -- Skie - desc = "It's some pest eliminator spray! Do not inhale!" - icon = 'icons/obj/hydroponics.dmi' - name = "pest-spray" - icon_state = "pestspray" - item_state = "spray" - flags = TABLEPASS | OPENCONTAINER | FPRINT | NOBLUDGEON - slot_flags = SLOT_BELT - throwforce = 4 - w_class = 2.0 - throw_speed = 2 - throw_range = 10 - var/toxicity = 4 - var/PestKillStr = 2 - - suicide_act(mob/user) + return (TOXLOSS) + +/obj/item/weapon/pestspray // -- Skie + desc = "It's some pest eliminator spray! Do not inhale!" + icon = 'icons/obj/hydroponics.dmi' + name = "pest-spray" + icon_state = "pestspray" + item_state = "spray" + flags = TABLEPASS | OPENCONTAINER | FPRINT | NOBLUDGEON + slot_flags = SLOT_BELT + throwforce = 4 + w_class = 2.0 + throw_speed = 2 + throw_range = 10 + var/toxicity = 4 + var/PestKillStr = 2 + + suicide_act(mob/user) to_chat(viewers(user), "[user] is huffing the [src.name]! It looks like \he's trying to commit suicide.") - return (TOXLOSS) - -/obj/item/weapon/minihoe // -- Numbers - name = "mini hoe" - desc = "It's used for removing weeds or scratching your back." - icon = 'icons/obj/weapons.dmi' - icon_state = "hoe" - item_state = "hoe" - flags = FPRINT | TABLEPASS | CONDUCT | NOBLUDGEON - force = 5.0 - throwforce = 7.0 - w_class = 2.0 - m_amt = 50 - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - attack_verb = list("slashed", "sliced", "cut", "clawed") - -// ************************************* -// Weedkiller defines for hydroponics -// ************************************* - -/obj/item/weedkiller - name = "bottle of weedkiller" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - flags = FPRINT | TABLEPASS - var/toxicity = 0 - var/WeedKillStr = 0 - -/obj/item/weedkiller/triclopyr - name = "bottle of glyphosate" - icon_state = "bottle16" - toxicity = 4 - WeedKillStr = 2 - -/obj/item/weedkiller/lindane - name = "bottle of triclopyr" - icon_state = "bottle18" - toxicity = 6 - WeedKillStr = 4 - -/obj/item/weedkiller/D24 - name = "bottle of 2,4-D" - icon_state = "bottle15" - toxicity = 8 - WeedKillStr = 7 - -// ************************************* -// Nutrient defines for hydroponics -// ************************************* - -/obj/item/nutrient - name = "bottle of nutrient" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - flags = FPRINT | TABLEPASS - w_class = 1.0 - var/mutmod = 0 - var/yieldmod = 0 - -/obj/item/nutrient/New() - . = ..() - pixel_x = rand(-5.0, 5) - pixel_y = rand(-5.0, 5) - -/obj/item/nutrient/ez - name = "bottle of E-Z-Nutrient" - icon_state = "bottle16" - mutmod = 1 - yieldmod = 1 - -/obj/item/nutrient/l4z - name = "bottle of Left 4 Zed" - icon_state = "bottle18" - mutmod = 2 - yieldmod = 0 - -/obj/item/nutrient/rh - name = "bottle of Robust Harvest" - icon_state = "bottle15" - mutmod = 0 - yieldmod = 2 + return (TOXLOSS) + +/obj/item/weapon/minihoe // -- Numbers + name = "mini hoe" + desc = "It's used for removing weeds or scratching your back." + icon = 'icons/obj/weapons.dmi' + icon_state = "hoe" + item_state = "hoe" + flags = FPRINT | TABLEPASS | CONDUCT | NOBLUDGEON + force = 5.0 + throwforce = 7.0 + w_class = 2.0 + m_amt = 50 + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + attack_verb = list("slashed", "sliced", "cut", "clawed") + +// ************************************* +// Weedkiller defines for hydroponics +// ************************************* + +/obj/item/weedkiller + name = "bottle of weedkiller" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + flags = FPRINT | TABLEPASS + var/toxicity = 0 + var/WeedKillStr = 0 + +/obj/item/weedkiller/triclopyr + name = "bottle of glyphosate" + icon_state = "bottle16" + toxicity = 4 + WeedKillStr = 2 + +/obj/item/weedkiller/lindane + name = "bottle of triclopyr" + icon_state = "bottle18" + toxicity = 6 + WeedKillStr = 4 + +/obj/item/weedkiller/D24 + name = "bottle of 2,4-D" + icon_state = "bottle15" + toxicity = 8 + WeedKillStr = 7 + +// ************************************* +// Nutrient defines for hydroponics +// ************************************* + +/obj/item/nutrient + name = "bottle of nutrient" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + flags = FPRINT | TABLEPASS + w_class = 1.0 + var/mutmod = 0 + var/yieldmod = 0 + +/obj/item/nutrient/New() + . = ..() + pixel_x = rand(-5.0, 5) + pixel_y = rand(-5.0, 5) + +/obj/item/nutrient/ez + name = "bottle of E-Z-Nutrient" + icon_state = "bottle16" + mutmod = 1 + yieldmod = 1 + +/obj/item/nutrient/l4z + name = "bottle of Left 4 Zed" + icon_state = "bottle18" + mutmod = 2 + yieldmod = 0 + +/obj/item/nutrient/rh + name = "bottle of Robust Harvest" + icon_state = "bottle15" + mutmod = 0 + yieldmod = 2 diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index e604d11ee7a..23362947969 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -1,335 +1,335 @@ -/* -A Star pathfinding algorithm -Returns a list of tiles forming a path from A to B, taking dense objects as well as walls, and the orientation of -windows along the route into account. -Use: -your_list = AStar(start location, end location, adjacent turf proc, distance proc) -For the adjacent turf proc i wrote: -/turf/proc/AdjacentTurfs -And for the distance one i wrote: -/turf/proc/Distance -So an example use might be: - -src.path_list = AStar(src.loc, target.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance) - -Then to start on the path, all you need to do it: -Step_to(src, src.path_list[1]) -src.path_list -= src.path_list[1] or equivilent to remove that node from the list. - -Optional extras to add on (in order): -MaxNodes: The maximum number of nodes the returned path can be (0 = infinite) -Maxnodedepth: The maximum number of nodes to search (default: 30, 0 = infinite) -Mintargetdist: Minimum distance to the target before path returns, could be used to get -near a target, but not right to it - for an AI mob with a gun, for example. -Minnodedist: Minimum number of nodes to return in the path, could be used to give a path a minimum -length to avoid portals or something i guess?? Not that they're counted right now but w/e. -*/ - -// Modified to provide ID argument - supplied to 'adjacent' proc, defaults to null -// Used for checking if route exists through a door which can be opened - -// Also added 'exclude' turf to avoid travelling over; defaults to null - -//Currently, there's four main ways to call AStar -// -// 1) adjacent = "/turf/proc/AdjacentTurfsWithAccess" and distance = "/turf/proc/Distance" -// Seeks a path moving in all directions (including diagonal) and checking for the correct id to get through doors -// -// 2) adjacent = "/turf/proc/CardinalTurfsWithAccess" and distance = "/turf/proc/Distance_cardinal" -// Seeks a path moving only in cardinal directions and checking if for the correct id to get through doors -// Used by most bots, including Beepsky -// -// 3) adjacent = "/turf/proc/AdjacentTurfs" and distance = "/turf/proc/Distance" -// Same as 1), but don't check for ID. Can get only get through open doors -// -// 4) adjacent = "/turf/proc/AdjacentTurfsSpace" and distance = "/turf/proc/Distance" -// Same as 1), but check all turf, including unsimulated - -////////////////////// -//PriorityQueue object -////////////////////// - -//an ordered list, using the cmp proc to weight the list elements -/PriorityQueue - var/list/L //the actual queue - var/cmp //the weight function used to order the queue - -/PriorityQueue/New(compare) - L = new() - cmp = compare - -/PriorityQueue/proc/IsEmpty() - return !L.len - -//add an element in the list, -//immediatly ordering it to its position using Insertion sort -/PriorityQueue/proc/Enqueue(var/atom/A) - var/i - L.Add(A) - i = L.len -1 - while(i > 0 && call(cmp)(L[i],A) >= 0) //place the element at it's right position using the compare proc - L.Swap(i,i+1) //last inserted element being first in case of ties (optimization) - i-- - -//removes and returns the first element in the queue -/PriorityQueue/proc/Dequeue() - if(!L.len) - return 0 - . = L[1] - Remove(.) - return . - -//removes an element -/PriorityQueue/proc/Remove(var/atom/A) - return L.Remove(A) - -//returns a copy of the elements list -/PriorityQueue/proc/List() - var/list/ret = L.Copy() - return ret - -//return the position of an element or 0 if not found -/PriorityQueue/proc/Seek(var/atom/A) - return L.Find(A) - -//return the element at the i_th position -/PriorityQueue/proc/Get(var/i) - if(i > L.len || i < 1) - return 0 - return L[i] - -//replace the passed element at it's right position using the cmp proc -/PriorityQueue/proc/ReSort(var/atom/A) - var/i = Seek(A) - if(i == 0) - return - while(i < L.len && call(cmp)(L[i],L[i+1]) > 0) - L.Swap(i,i+1) - i++ - while(i > 1 && call(cmp)(L[i],L[i-1]) <= 0) //last inserted element being first in case of ties (optimization) - L.Swap(i,i-1) - i-- - -////////////////////// -//PathNode object -////////////////////// - -//A* nodes variables -/PathNode - var/turf/source //turf associated with the PathNode - var/PathNode/prevNode //link to the parent PathNode - var/f //A* Node weight (f = g + h) - var/g //A* movement cost variable - var/h //A* heuristic variable - var/nt //count the number of Nodes traversed - -/PathNode/New(s,p,pg,ph,pnt) - source = s - prevNode = p - g = pg - h = ph - f = g + h - source.PNode = src - nt = pnt - -/PathNode/proc/calc_f() - f = g + h - -////////////////////// -//A* procs -////////////////////// - -//the weighting function, used in the A* algorithm -proc/PathWeightCompare(PathNode/a, PathNode/b) - return a.f - b.f - -//search if there's a PathNode that points to turf T in the Priority Queue -proc/SeekTurf(var/PriorityQueue/Queue, var/turf/T) - var/i = 1 - var/PathNode/PN - while(i < Queue.L.len + 1) - PN = Queue.L[i] - if(PN.source == T) - return i - i++ - return 0 - -//the actual algorithm -proc/AStar(start,end,adjacent,dist,maxnodes,maxnodedepth = 30,mintargetdist,minnodedist,id=null, var/turf/exclude=null) - ASSERT(!istype(end,/area)) //Because yeah some things might be doing this and we want to know what - var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare) //the open list, ordered using the PathWeightCompare proc, from lower f to higher - var/list/closed = new() //the closed list - var/list/path = null //the returned path, if any - var/PathNode/cur //current processed turf - - //sanitation - start = get_turf(start) - if(!start) - return 0 - - //initialization - open.Enqueue(new /PathNode(start,null,0,call(start,dist)(end),0)) - - //then run the main loop - while(!open.IsEmpty() && !path) - { - //get the lower f node on the open list - cur = open.Dequeue() //get the lower f turf in the open list - closed.Add(cur.source) //and tell we've processed it - - //if we only want to get near the target, check if we're close enough - var/closeenough - if(mintargetdist) - closeenough = call(cur.source,dist)(end) <= mintargetdist - - //if too many steps, abandon that path - if(maxnodedepth && (cur.nt > maxnodedepth)) - continue - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = new() - path.Add(cur.source) - while(cur.prevNode) - cur = cur.prevNode - path.Add(cur.source) - break - - //IMPLEMENTATION TO FINISH - //do we really need this minnodedist ??? - /*if(minnodedist && maxnodedepth) - if(call(cur.source,minnodedist)(end) + cur.nt >= maxnodedepth) - continue - */ - - //get adjacents turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source,adjacent)(id,closed) - - for(var/turf/T in L) - if(T == exclude) - continue - - var/newg = cur.g + call(cur.source,dist)(T) - if(!T.PNode) //is not already in open list, so add it - open.Enqueue(new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1)) - else //is already in open list, check if it's a better way from the current turf - if(newg < T.PNode.g) - T.PNode.prevNode = cur - T.PNode.g = newg - T.PNode.calc_f() - open.ReSort(T.PNode)//reorder the changed element in the list - - } - - //cleaning after us - for(var/PathNode/PN in open.L) - PN.source.PNode = null - for(var/turf/T in closed) - T.PNode = null - - //if the path is longer than maxnodes, then don't return it - if(path && maxnodes && path.len > (maxnodes + 1)) - return 0 - - //reverse the path to get it from start to finish - if(path) - for(var/i = 1; i <= path.len/2; i++) - path.Swap(i,path.len-i+1) - - return path - - - - - - -/////////////////// -//A* helpers procs -/////////////////// - -// Returns true if a link between A and B is blocked -// Movement through doors allowed if ID has access -/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID) - - - if(A == null || B == null) return 1 - var/adir = get_dir(A,B) - var/rdir = get_dir(B,A) - if(adir & (adir-1)) // diagonal - var/turf/iStep = get_step(A,adir&(NORTH|SOUTH)) - if(!iStep.density && !LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID)) - return 0 - - var/turf/pStep = get_step(A,adir&(EAST|WEST)) - if(!pStep.density && !LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID)) - return 0 - - return 1 - - if(DirBlockedWithAccess(A,adir, ID)) - return 1 - - if(DirBlockedWithAccess(B,rdir, ID)) - return 1 - - for(var/obj/O in B) - if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER)) - return 1 - - return 0 - -// Returns true if direction is blocked from loc -// Checks doors against access with given ID -/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID) - for(var/obj/structure/window/D in loc) - if(!D.density) continue - if(D.dir == SOUTHWEST) return 1 //full-tile window - if(D.dir == dir) return 1 //matching border window - - for(var/obj/machinery/door/D in loc) - if(!D.CanAStarPass(ID,dir)) - return 1 - return 0 - -// Returns true if a link between A and B is blocked -// Movement through doors allowed if door is open -/proc/LinkBlocked(turf/A, turf/B) - if(A == null || B == null) - return 1 - var/adir = get_dir(A,B) - var/rdir = get_dir(B,A) - if(adir & (adir-1)) //diagonal - var/turf/iStep = get_step(A,adir & (NORTH|SOUTH)) //check the north/south component - if(!iStep.density && !LinkBlocked(A,iStep) && !LinkBlocked(iStep,B)) - return 0 - - var/turf/pStep = get_step(A,adir & (EAST|WEST)) //check the east/west component - if(!pStep.density && !LinkBlocked(A,pStep) && !LinkBlocked(pStep,B)) - return 0 - - return 1 - - if(DirBlocked(A,adir)) return 1 - if(DirBlocked(B,rdir)) return 1 - - for(var/obj/O in B) - if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER)) - return 1 - - return 0 - -// Returns true if direction is blocked from loc -// Checks if doors are open -/proc/DirBlocked(turf/loc,var/dir) - for(var/obj/structure/window/D in loc) - if(!D.density) continue - if(D.dir == SOUTHWEST) return 1 //full-tile window - if(D.dir == dir) return 1 //matching border window - - for(var/obj/machinery/door/D in loc) - if(!D.density)//if the door is open - continue - else return 1 // if closed, it's a real, air blocking door - return 0 - -///////////////////////////////////////////////////////////////////////// +/* +A Star pathfinding algorithm +Returns a list of tiles forming a path from A to B, taking dense objects as well as walls, and the orientation of +windows along the route into account. +Use: +your_list = AStar(start location, end location, adjacent turf proc, distance proc) +For the adjacent turf proc i wrote: +/turf/proc/AdjacentTurfs +And for the distance one i wrote: +/turf/proc/Distance +So an example use might be: + +src.path_list = AStar(src.loc, target.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance) + +Then to start on the path, all you need to do it: +Step_to(src, src.path_list[1]) +src.path_list -= src.path_list[1] or equivilent to remove that node from the list. + +Optional extras to add on (in order): +MaxNodes: The maximum number of nodes the returned path can be (0 = infinite) +Maxnodedepth: The maximum number of nodes to search (default: 30, 0 = infinite) +Mintargetdist: Minimum distance to the target before path returns, could be used to get +near a target, but not right to it - for an AI mob with a gun, for example. +Minnodedist: Minimum number of nodes to return in the path, could be used to give a path a minimum +length to avoid portals or something i guess?? Not that they're counted right now but w/e. +*/ + +// Modified to provide ID argument - supplied to 'adjacent' proc, defaults to null +// Used for checking if route exists through a door which can be opened + +// Also added 'exclude' turf to avoid travelling over; defaults to null + +//Currently, there's four main ways to call AStar +// +// 1) adjacent = "/turf/proc/AdjacentTurfsWithAccess" and distance = "/turf/proc/Distance" +// Seeks a path moving in all directions (including diagonal) and checking for the correct id to get through doors +// +// 2) adjacent = "/turf/proc/CardinalTurfsWithAccess" and distance = "/turf/proc/Distance_cardinal" +// Seeks a path moving only in cardinal directions and checking if for the correct id to get through doors +// Used by most bots, including Beepsky +// +// 3) adjacent = "/turf/proc/AdjacentTurfs" and distance = "/turf/proc/Distance" +// Same as 1), but don't check for ID. Can get only get through open doors +// +// 4) adjacent = "/turf/proc/AdjacentTurfsSpace" and distance = "/turf/proc/Distance" +// Same as 1), but check all turf, including unsimulated + +////////////////////// +//PriorityQueue object +////////////////////// + +//an ordered list, using the cmp proc to weight the list elements +/PriorityQueue + var/list/L //the actual queue + var/cmp //the weight function used to order the queue + +/PriorityQueue/New(compare) + L = new() + cmp = compare + +/PriorityQueue/proc/IsEmpty() + return !L.len + +//add an element in the list, +//immediatly ordering it to its position using Insertion sort +/PriorityQueue/proc/Enqueue(var/atom/A) + var/i + L.Add(A) + i = L.len -1 + while(i > 0 && call(cmp)(L[i],A) >= 0) //place the element at it's right position using the compare proc + L.Swap(i,i+1) //last inserted element being first in case of ties (optimization) + i-- + +//removes and returns the first element in the queue +/PriorityQueue/proc/Dequeue() + if(!L.len) + return 0 + . = L[1] + Remove(.) + return . + +//removes an element +/PriorityQueue/proc/Remove(var/atom/A) + return L.Remove(A) + +//returns a copy of the elements list +/PriorityQueue/proc/List() + var/list/ret = L.Copy() + return ret + +//return the position of an element or 0 if not found +/PriorityQueue/proc/Seek(var/atom/A) + return L.Find(A) + +//return the element at the i_th position +/PriorityQueue/proc/Get(var/i) + if(i > L.len || i < 1) + return 0 + return L[i] + +//replace the passed element at it's right position using the cmp proc +/PriorityQueue/proc/ReSort(var/atom/A) + var/i = Seek(A) + if(i == 0) + return + while(i < L.len && call(cmp)(L[i],L[i+1]) > 0) + L.Swap(i,i+1) + i++ + while(i > 1 && call(cmp)(L[i],L[i-1]) <= 0) //last inserted element being first in case of ties (optimization) + L.Swap(i,i-1) + i-- + +////////////////////// +//PathNode object +////////////////////// + +//A* nodes variables +/PathNode + var/turf/source //turf associated with the PathNode + var/PathNode/prevNode //link to the parent PathNode + var/f //A* Node weight (f = g + h) + var/g //A* movement cost variable + var/h //A* heuristic variable + var/nt //count the number of Nodes traversed + +/PathNode/New(s,p,pg,ph,pnt) + source = s + prevNode = p + g = pg + h = ph + f = g + h + source.PNode = src + nt = pnt + +/PathNode/proc/calc_f() + f = g + h + +////////////////////// +//A* procs +////////////////////// + +//the weighting function, used in the A* algorithm +proc/PathWeightCompare(PathNode/a, PathNode/b) + return a.f - b.f + +//search if there's a PathNode that points to turf T in the Priority Queue +proc/SeekTurf(var/PriorityQueue/Queue, var/turf/T) + var/i = 1 + var/PathNode/PN + while(i < Queue.L.len + 1) + PN = Queue.L[i] + if(PN.source == T) + return i + i++ + return 0 + +//the actual algorithm +proc/AStar(start,end,adjacent,dist,maxnodes,maxnodedepth = 30,mintargetdist,minnodedist,id=null, var/turf/exclude=null) + ASSERT(!istype(end,/area)) //Because yeah some things might be doing this and we want to know what + var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare) //the open list, ordered using the PathWeightCompare proc, from lower f to higher + var/list/closed = new() //the closed list + var/list/path = null //the returned path, if any + var/PathNode/cur //current processed turf + + //sanitation + start = get_turf(start) + if(!start) + return 0 + + //initialization + open.Enqueue(new /PathNode(start,null,0,call(start,dist)(end),0)) + + //then run the main loop + while(!open.IsEmpty() && !path) + { + //get the lower f node on the open list + cur = open.Dequeue() //get the lower f turf in the open list + closed.Add(cur.source) //and tell we've processed it + + //if we only want to get near the target, check if we're close enough + var/closeenough + if(mintargetdist) + closeenough = call(cur.source,dist)(end) <= mintargetdist + + //if too many steps, abandon that path + if(maxnodedepth && (cur.nt > maxnodedepth)) + continue + + //found the target turf (or close enough), let's create the path to it + if(cur.source == end || closeenough) + path = new() + path.Add(cur.source) + while(cur.prevNode) + cur = cur.prevNode + path.Add(cur.source) + break + + //IMPLEMENTATION TO FINISH + //do we really need this minnodedist ??? + /*if(minnodedist && maxnodedepth) + if(call(cur.source,minnodedist)(end) + cur.nt >= maxnodedepth) + continue + */ + + //get adjacents turfs using the adjacent proc, checking for access with id + var/list/L = call(cur.source,adjacent)(id,closed) + + for(var/turf/T in L) + if(T == exclude) + continue + + var/newg = cur.g + call(cur.source,dist)(T) + if(!T.PNode) //is not already in open list, so add it + open.Enqueue(new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1)) + else //is already in open list, check if it's a better way from the current turf + if(newg < T.PNode.g) + T.PNode.prevNode = cur + T.PNode.g = newg + T.PNode.calc_f() + open.ReSort(T.PNode)//reorder the changed element in the list + + } + + //cleaning after us + for(var/PathNode/PN in open.L) + PN.source.PNode = null + for(var/turf/T in closed) + T.PNode = null + + //if the path is longer than maxnodes, then don't return it + if(path && maxnodes && path.len > (maxnodes + 1)) + return 0 + + //reverse the path to get it from start to finish + if(path) + for(var/i = 1; i <= path.len/2; i++) + path.Swap(i,path.len-i+1) + + return path + + + + + + +/////////////////// +//A* helpers procs +/////////////////// + +// Returns true if a link between A and B is blocked +// Movement through doors allowed if ID has access +/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID) + + + if(A == null || B == null) return 1 + var/adir = get_dir(A,B) + var/rdir = get_dir(B,A) + if(adir & (adir-1)) // diagonal + var/turf/iStep = get_step(A,adir&(NORTH|SOUTH)) + if(!iStep.density && !LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID)) + return 0 + + var/turf/pStep = get_step(A,adir&(EAST|WEST)) + if(!pStep.density && !LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID)) + return 0 + + return 1 + + if(DirBlockedWithAccess(A,adir, ID)) + return 1 + + if(DirBlockedWithAccess(B,rdir, ID)) + return 1 + + for(var/obj/O in B) + if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER)) + return 1 + + return 0 + +// Returns true if direction is blocked from loc +// Checks doors against access with given ID +/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID) + for(var/obj/structure/window/D in loc) + if(!D.density) continue + if(D.dir == SOUTHWEST) return 1 //full-tile window + if(D.dir == dir) return 1 //matching border window + + for(var/obj/machinery/door/D in loc) + if(!D.CanAStarPass(ID,dir)) + return 1 + return 0 + +// Returns true if a link between A and B is blocked +// Movement through doors allowed if door is open +/proc/LinkBlocked(turf/A, turf/B) + if(A == null || B == null) + return 1 + var/adir = get_dir(A,B) + var/rdir = get_dir(B,A) + if(adir & (adir-1)) //diagonal + var/turf/iStep = get_step(A,adir & (NORTH|SOUTH)) //check the north/south component + if(!iStep.density && !LinkBlocked(A,iStep) && !LinkBlocked(iStep,B)) + return 0 + + var/turf/pStep = get_step(A,adir & (EAST|WEST)) //check the east/west component + if(!pStep.density && !LinkBlocked(A,pStep) && !LinkBlocked(pStep,B)) + return 0 + + return 1 + + if(DirBlocked(A,adir)) return 1 + if(DirBlocked(B,rdir)) return 1 + + for(var/obj/O in B) + if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER)) + return 1 + + return 0 + +// Returns true if direction is blocked from loc +// Checks if doors are open +/proc/DirBlocked(turf/loc,var/dir) + for(var/obj/structure/window/D in loc) + if(!D.density) continue + if(D.dir == SOUTHWEST) return 1 //full-tile window + if(D.dir == dir) return 1 //matching border window + + for(var/obj/machinery/door/D in loc) + if(!D.density)//if the door is open + continue + else return 1 // if closed, it's a real, air blocking door + return 0 + +///////////////////////////////////////////////////////////////////////// diff --git a/code/defines/procs/captain_announce.dm b/code/defines/procs/captain_announce.dm index f9209d79974..ef3691a7aa7 100644 --- a/code/defines/procs/captain_announce.dm +++ b/code/defines/procs/captain_announce.dm @@ -1,5 +1,5 @@ -/proc/captain_announce(var/text) +/proc/captain_announce(var/text) to_chat(world, "

      Priority Announcement

      ") to_chat(world, "[html_encode(text)]") to_chat(world, "
      ") - + diff --git a/code/defines/procs/command_alert.dm b/code/defines/procs/command_alert.dm index 2accaf16c24..4caf3ab15a5 100644 --- a/code/defines/procs/command_alert.dm +++ b/code/defines/procs/command_alert.dm @@ -1,15 +1,15 @@ -/proc/command_alert(var/text, var/title = "") - var/command - command += "

      [command_name()] Update

      " - if (title && length(title) > 0) - command += "

      [html_encode(title)]

      " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\defines\\\procs\command_alert.dm:7: command += "
      [html_encode(text)]
      " - command += {"
      [html_encode(text)]
      -
      "} - // END AUTOFIX - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player) && M.client) +/proc/command_alert(var/text, var/title = "") + var/command + command += "

      [command_name()] Update

      " + if (title && length(title) > 0) + command += "

      [html_encode(title)]

      " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\defines\\\procs\command_alert.dm:7: command += "
      [html_encode(text)]
      " + command += {"
      [html_encode(text)]
      +
      "} + // END AUTOFIX + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && M.client) to_chat(M, command) diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index c1f448d9384..5e19bfdb04e 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -1,162 +1,162 @@ -proc/sql_poll_players() - if(!sqllogging) - return - var/playercount = 0 - for(var/mob/M in player_list) - if(M.client) - playercount += 1 - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during player polling. Failed to connect.") - else - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during player polling. Error : \[[err]\]\n") - - -proc/sql_poll_admins() - if(!sqllogging) - return - var/admincount = admins.len - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during admin polling. Failed to connect.") - else - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during admin polling. Error : \[[err]\]\n") - -proc/sql_report_round_start() - // TODO - if(!sqllogging) - return -proc/sql_report_round_end() - // TODO - if(!sqllogging) - return - -proc/sql_report_death(var/mob/living/carbon/human/H) - if(!sqllogging) - return - if(!H) - return - if(!H.key || !H.mind) - return - - var/turf/T = H.loc - var/area/placeofdeath = get_area(T.loc) - var/podname = placeofdeath.name - - var/sqlname = sanitizeSQL(H.real_name) - var/sqlkey = sanitizeSQL(H.key) - var/sqlpod = sanitizeSQL(podname) - var/sqlspecial = sanitizeSQL(H.mind.special_role) - var/sqljob = sanitizeSQL(H.mind.assigned_role) - var/laname - var/lakey - if(H.lastattacker) - laname = sanitizeSQL(H.lastattacker:real_name) - lakey = sanitizeSQL(H.lastattacker:key) - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/coord = "[H.x], [H.y], [H.z]" +proc/sql_poll_players() + if(!sqllogging) + return + var/playercount = 0 + for(var/mob/M in player_list) + if(M.client) + playercount += 1 + establish_db_connection() + if(!dbcon.IsConnected()) + log_game("SQL ERROR during player polling. Failed to connect.") + else + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')") + if(!query.Execute()) + var/err = query.ErrorMsg() + log_game("SQL ERROR during player polling. Error : \[[err]\]\n") + + +proc/sql_poll_admins() + if(!sqllogging) + return + var/admincount = admins.len + establish_db_connection() + if(!dbcon.IsConnected()) + log_game("SQL ERROR during admin polling. Failed to connect.") + else + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')") + if(!query.Execute()) + var/err = query.ErrorMsg() + log_game("SQL ERROR during admin polling. Error : \[[err]\]\n") + +proc/sql_report_round_start() + // TODO + if(!sqllogging) + return +proc/sql_report_round_end() + // TODO + if(!sqllogging) + return + +proc/sql_report_death(var/mob/living/carbon/human/H) + if(!sqllogging) + return + if(!H) + return + if(!H.key || !H.mind) + return + + var/turf/T = H.loc + var/area/placeofdeath = get_area(T.loc) + var/podname = placeofdeath.name + + var/sqlname = sanitizeSQL(H.real_name) + var/sqlkey = sanitizeSQL(H.key) + var/sqlpod = sanitizeSQL(podname) + var/sqlspecial = sanitizeSQL(H.mind.special_role) + var/sqljob = sanitizeSQL(H.mind.assigned_role) + var/laname + var/lakey + if(H.lastattacker) + laname = sanitizeSQL(H.lastattacker:real_name) + lakey = sanitizeSQL(H.lastattacker:key) + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/coord = "[H.x], [H.y], [H.z]" // to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])") - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during death reporting. Failed to connect.") - else - var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") - - -proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H) - if(!sqllogging) - return - if(!H) - return - if(!H.key || !H.mind) - return - - var/turf/T = H.loc - var/area/placeofdeath = get_area(T.loc) - var/podname = placeofdeath.name - - var/sqlname = sanitizeSQL(H.real_name) - var/sqlkey = sanitizeSQL(H.key) - var/sqlpod = sanitizeSQL(podname) - var/sqlspecial = sanitizeSQL(H.mind.special_role) - var/sqljob = sanitizeSQL(H.mind.assigned_role) - var/laname - var/lakey - if(H.lastattacker) - laname = sanitizeSQL(H.lastattacker:real_name) - lakey = sanitizeSQL(H.lastattacker:key) - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/coord = "[H.x], [H.y], [H.z]" + establish_db_connection() + if(!dbcon.IsConnected()) + log_game("SQL ERROR during death reporting. Failed to connect.") + else + var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") + if(!query.Execute()) + var/err = query.ErrorMsg() + log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") + + +proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H) + if(!sqllogging) + return + if(!H) + return + if(!H.key || !H.mind) + return + + var/turf/T = H.loc + var/area/placeofdeath = get_area(T.loc) + var/podname = placeofdeath.name + + var/sqlname = sanitizeSQL(H.real_name) + var/sqlkey = sanitizeSQL(H.key) + var/sqlpod = sanitizeSQL(podname) + var/sqlspecial = sanitizeSQL(H.mind.special_role) + var/sqljob = sanitizeSQL(H.mind.assigned_role) + var/laname + var/lakey + if(H.lastattacker) + laname = sanitizeSQL(H.lastattacker:real_name) + lakey = sanitizeSQL(H.lastattacker:key) + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/coord = "[H.x], [H.y], [H.z]" // to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])") - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during death reporting. Failed to connect.") - else - var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") - - -proc/statistic_cycle() - if(!sqllogging) - return - while(1) - sql_poll_players() - sleep(600) - sql_poll_admins() - sleep(6000) // Poll every ten minutes - -//This proc is used for feedback. It is executed at round end. -proc/sql_commit_feedback() - if(!blackbox) - log_game("Round ended without a blackbox recorder. No feedback was sent to the database.") - return - - //content is a list of lists. Each item in the list is a list with two fields, a variable name and a value. Items MUST only have these two values. - var/list/datum/feedback_variable/content = blackbox.get_round_feedback() - - if(!content) - log_game("Round ended without any feedback being generated. No feedback was sent to the database.") - return - - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during feedback reporting. Failed to connect.") - else - - var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback") - max_query.Execute() - - var/newroundid - - while(max_query.NextRow()) - newroundid = max_query.item[1] - - if(!(isnum(newroundid))) - newroundid = text2num(newroundid) - - if(isnum(newroundid)) - newroundid++ - else - newroundid = 1 - - for(var/datum/feedback_variable/item in content) - var/variable = item.get_variable() - var/value = item.get_value() - - var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") - if(!query.Execute()) - var/err = query.ErrorMsg() + establish_db_connection() + if(!dbcon.IsConnected()) + log_game("SQL ERROR during death reporting. Failed to connect.") + else + var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") + if(!query.Execute()) + var/err = query.ErrorMsg() + log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") + + +proc/statistic_cycle() + if(!sqllogging) + return + while(1) + sql_poll_players() + sleep(600) + sql_poll_admins() + sleep(6000) // Poll every ten minutes + +//This proc is used for feedback. It is executed at round end. +proc/sql_commit_feedback() + if(!blackbox) + log_game("Round ended without a blackbox recorder. No feedback was sent to the database.") + return + + //content is a list of lists. Each item in the list is a list with two fields, a variable name and a value. Items MUST only have these two values. + var/list/datum/feedback_variable/content = blackbox.get_round_feedback() + + if(!content) + log_game("Round ended without any feedback being generated. No feedback was sent to the database.") + return + + establish_db_connection() + if(!dbcon.IsConnected()) + log_game("SQL ERROR during feedback reporting. Failed to connect.") + else + + var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback") + max_query.Execute() + + var/newroundid + + while(max_query.NextRow()) + newroundid = max_query.item[1] + + if(!(isnum(newroundid))) + newroundid = text2num(newroundid) + + if(isnum(newroundid)) + newroundid++ + else + newroundid = 1 + + for(var/datum/feedback_variable/item in content) + var/variable = item.get_variable() + var/value = item.get_value() + + var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") + if(!query.Execute()) + var/err = query.ErrorMsg() log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") \ No newline at end of file diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 87a6a109d38..6844db8acad 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -1,2243 +1,2243 @@ -/* - -### This file contains a list of all the areas in your station. Format is as follows: - -/area/CATEGORY/OR/DESCRIPTOR/NAME (you can make as many subdivisions as you want) - name = "NICE NAME" (not required but makes things really nice) - icon = "ICON FILENAME" (defaults to areas.dmi) - icon_state = "NAME OF ICON" (defaults to "unknown" (blank)) - requires_power = 0 (defaults to 1) - music = "music/music.ogg" (defaults to "music/music.ogg") - -NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0 - -*/ - -#define SUPER_JAMMED 2 - -/area - var/fire = null - var/atmos = 1 - var/atmosalm = 0 - var/poweralm = 1 - var/party = null - var/radalert = 0 - level = null - name = "Space" - icon = 'icons/turf/areas.dmi' - icon_state = "unknown" - layer = 10 - mouse_opacity = 0 - luminosity = 0 - var/lightswitch = 1 - - var/eject = null - - var/requires_power = 1 - var/always_unpowered = 0 //this gets overriden to 1 for space in area/New() - - var/power_equip = 1 - var/power_light = 1 - var/power_environ = 1 - var/music = null - var/used_equip = 0 - var/used_light = 0 - var/used_environ = 0 - var/static_equip - var/static_light = 0 - var/static_environ - - var/has_gravity = 1 - - var/no_air = null -// var/list/lights // list of all lights on this area - var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area - - // /vg/: Bitmap of subsystems asking for firedoors. - var/door_alerts=0 - - var/doors_down=0 - - // /vg/: No teleporting for you. 2 = SUPER JAMMED, inaccessible even to telecrystals. - var/jammed = 0 - - // /vg/: Prevents entities using incorporeal move from entering the area (ghosts, jaunting wizards/ninjas...) - var/anti_ethereal = 0 - - var/general_area = /area/station // the highest parent bellow /area, - var/general_area_name = "Station" - - -/*Adding a wizard area teleport list because motherfucking lag -- Urist*/ -/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ -var/list/teleportlocs = list() - -proc/process_teleport_locs() - for(var/area/AR in areas) - if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station)) continue - if(teleportlocs.Find(AR.name)) continue - var/turf/picked = safepick(get_area_turfs(AR.type)) - if (picked && picked.z == 1) - teleportlocs += AR.name - teleportlocs[AR.name] = AR - - sortTim(teleportlocs, /proc/cmp_text_asc) - -var/list/ghostteleportlocs = list() - -proc/process_ghost_teleport_locs() - for(var/area/AR in areas) - if(ghostteleportlocs.Find(AR.name)) continue - if(istype(AR, /area/turret_protected/aisat) || istype(AR, /area/derelict) || istype(AR, /area/tdome)) - ghostteleportlocs += AR.name - ghostteleportlocs[AR.name] = AR - var/turf/picked = safepick(get_area_turfs(AR.type)) - if (picked && (picked.z == 1 || picked.z == 5 || picked.z == 3)) - ghostteleportlocs += AR.name - ghostteleportlocs[AR.name] = AR - - sortTim(ghostteleportlocs, /proc/cmp_text_asc) - -var/global/list/adminbusteleportlocs = list() - -proc/process_adminbus_teleport_locs() - for(var/area/AR in areas) - if(adminbusteleportlocs.Find(AR.name)) continue - var/turf/picked = safepick(get_area_turfs(AR.type)) - if (picked) - adminbusteleportlocs += AR.name - adminbusteleportlocs[AR.name] = AR - - sortTim(adminbusteleportlocs, /proc/cmp_text_dsc) - - -/*-----------------------------------------------------------------------------*/ - -/area/station//TODO: make every area in the MAIN station inherit from this. - name = "Station" - -/area/station/custom //For blueprints! - power_equip = 0 - power_light = 0 - power_environ = 0 - always_unpowered = 0 - lighting_use_dynamic = 1 - -/area/engineering/ - -/area/turret_protected/ - -/area/arrival - requires_power = 0 - -/area/arrival/start - name = "\improper Arrival Area" - icon_state = "start" - -/area/admin - name = "\improper Admin room" - icon_state = "start" - -/area/no_ethereal - anti_ethereal = 1 - - - -//These are shuttle areas, they must contain two areas in a subgroup if you want to move a shuttle from one -//place to another. Look at escape shuttle for example. -//All shuttles show now be under shuttle since we have smooth-wall code. - -/area/shuttle - requires_power = 0 - lighting_use_dynamic = 1 //Lighting STILL disabled, even with the new bay engine, because lighting doesn't play nice with our shuttles, might just be our shuttle code, or the small changes in the lighting engine we have from bay. - //haha fuck you we dynamic lights now - -/area/shuttle/arrival - name = "\improper Arrival Shuttle" - -/area/shuttle/arrival/pre_game - icon_state = "shuttle2" - -/area/shuttle/arrival/station - icon_state = "shuttle" - -/area/shuttle/escape - name = "\improper Emergency Shuttle" - music = "music/escape.ogg" - -/area/shuttle/escape/station - name = "\improper Emergency Shuttle Station" - icon_state = "shuttle2" - -/area/shuttle/escape/centcom - name = "\improper Emergency Shuttle Centcom" - icon_state = "shuttle" - -/area/shuttle/escape_pod1 - name = "\improper Escape Pod One" - music = "music/escape.ogg" - -/area/shuttle/escape_pod1/station - icon_state = "shuttle2" - -/area/shuttle/escape_pod1/centcom - icon_state = "shuttle" - -/area/shuttle/escape_pod1/transit - icon_state = "shuttle" - -/area/shuttle/escape_pod2 - name = "\improper Escape Pod Two" - music = "music/escape.ogg" - -/area/shuttle/escape_pod2/station - icon_state = "shuttle2" - -/area/shuttle/escape_pod2/centcom - icon_state = "shuttle" - -/area/shuttle/escape_pod2/transit - icon_state = "shuttle" - -/area/shuttle/escape_pod3 - name = "\improper Escape Pod Three" - music = "music/escape.ogg" - -/area/shuttle/escape_pod3/station - icon_state = "shuttle2" - -/area/shuttle/escape_pod3/centcom - icon_state = "shuttle" - -/area/shuttle/escape_pod3/transit - icon_state = "shuttle" - -/area/shuttle/escape_pod5 //Pod 4 was lost to meteors - name = "\improper Escape Pod Five" - music = "music/escape.ogg" - -/area/shuttle/escape_pod5/station - icon_state = "shuttle2" - -/area/shuttle/escape_pod5/centcom - icon_state = "shuttle" - -/area/shuttle/escape_pod5/transit - icon_state = "shuttle" - -/area/shuttle/supply - name = "supply shuttle" - icon_state = "shuttle3" - -/area/shuttle/mining - name = "\improper Mining Shuttle" - music = "music/escape.ogg" - -/area/shuttle/mining/station - icon_state = "shuttle2" - -/area/shuttle/mining/outpost - icon_state = "shuttle" - -/area/shuttle/transport1/centcom - icon_state = "shuttle" - name = "\improper Transport Shuttle Centcom" - -/area/shuttle/transport1/station - icon_state = "shuttle" - name = "\improper Transport Shuttle" - -/area/shuttle/alien/base - icon_state = "shuttle" - name = "\improper Alien Shuttle Base" - requires_power = 1 - -/area/shuttle/alien/mine - icon_state = "shuttle" - name = "\improper Alien Shuttle Mine" - requires_power = 1 - -/area/shuttle/prison/ - name = "\improper Prison Shuttle" - -/area/shuttle/prison/station - icon_state = "shuttle" - -/area/shuttle/prison/prison - icon_state = "shuttle2" - -/area/shuttle/specops/centcom - name = "\improper Special Ops Shuttle" - icon_state = "shuttlered" - -/area/shuttle/specops/station - name = "\improper Special Ops Shuttle" - icon_state = "shuttlered2" - -/area/shuttle/syndicate_elite/mothership - name = "\improper Syndicate Elite Shuttle" - icon_state = "shuttlered" - -/area/shuttle/syndicate_elite/station - name = "\improper Syndicate Elite Shuttle" - icon_state = "shuttlered2" - -/area/shuttle/administration/centcom - name = "\improper Administration Shuttle Centcom" - icon_state = "shuttlered" - -/area/shuttle/administration/station - name = "\improper Administration Shuttle" - icon_state = "shuttlered2" - -/area/shuttle/thunderdome - name = "honk" - lighting_use_dynamic = 0 - -/area/shuttle/thunderdome/grnshuttle - name = "\improper Thunderdome GRN Shuttle" - icon_state = "green" - -/area/shuttle/thunderdome/grnshuttle/dome - name = "\improper GRN Shuttle" - icon_state = "shuttlegrn" - -/area/shuttle/thunderdome/grnshuttle/station - name = "\improper GRN Station" - icon_state = "shuttlegrn2" - -/area/shuttle/thunderdome/redshuttle - name = "\improper Thunderdome RED Shuttle" - icon_state = "red" - -/area/shuttle/thunderdome/redshuttle/dome - name = "\improper RED Shuttle" - icon_state = "shuttlered" - -/area/shuttle/thunderdome/redshuttle/station - name = "\improper RED Station" - icon_state = "shuttlered2" -// === Trying to remove these areas: - -/area/shuttle/research - name = "\improper Research Shuttle" - music = "music/escape.ogg" - -/area/shuttle/research/station - icon_state = "shuttle2" - -/area/shuttle/research/outpost - icon_state = "shuttle" - -/area/shuttle/vox/station - name = "\improper Vox Skipjack" - icon_state = "yellow" - requires_power = 0 - -/area/shuttle/salvage - name = "\improper Salvage Ship" - icon_state = "yellow" - requires_power = 0 - -/area/shuttle/salvage/start - icon_state = "yellow" - -/area/shuttle/salvage/arrivals - name = "\improper Space Station Auxiliary Docking" - icon_state = "yellow" - -/area/shuttle/salvage/derelict - name = "\improper Derelict Station" - icon_state = "yellow" - -/area/shuttle/salvage/djstation - name = "\improper Ruskie DJ Station" - icon_state = "yellow" - -/area/shuttle/salvage/north - name = "\improper North of the Station" - icon_state = "yellow" - -/area/shuttle/salvage/east - name = "\improper East of the Station" - icon_state = "yellow" - -/area/shuttle/salvage/south - name = "\improper South of the Station" - icon_state = "yellow" - -/area/shuttle/salvage/commssat - name = "\improper The Communications Satellite" - icon_state = "yellow" - -/area/shuttle/salvage/mining - name = "\improper South-West of the Mining Asteroid" - icon_state = "yellow" - -/area/shuttle/salvage/abandoned_ship - name = "\improper Abandoned Ship" - icon_state = "yellow" - -/area/shuttle/salvage/clown_asteroid - name = "\improper Clown Asteroid" - icon_state = "yellow" - -/area/shuttle/salvage/trading_post - name = "\improper Trading Post" - icon_state = "yellow" - -// Taxi Shuttle - -/area/shuttle/taxi_a - name = "Taxi A" - requires_power = 0 - -/area/shuttle/taxi_a/medcal_silicon_station - icon_state = "bluenew" - -/area/shuttle/taxi_a/engineering_cargo_station - icon_state = "bluenew" - -/area/shuttle/taxi_a/security_science_station - icon_state = "bluenew" - -/area/shuttle/taxi_a/abandoned_station - icon_state = "bluenew" - -// B - -/area/shuttle/taxi_b - name = "Taxi B" - requires_power = 0 - -/area/shuttle/taxi_b/medcal_silicon_station - icon_state = "dk_yellow" - -/area/shuttle/taxi_b/engineering_cargo_station - icon_state = "dk_yellow" - -/area/shuttle/taxi_b/security_science_station - icon_state = "dk_yellow" - -/area/shuttle/taxi_b/abandoned_station - icon_state = "dk_yellow" - -// End Taxi Shuttle - - - -/area/airtunnel1/ // referenced in airtunnel.dm:759 - -/area/dummy/ // Referenced in engine.dm:261 - -/area/start // will be unused once kurper gets his login interface patch done - name = "start area" - icon_state = "start" - requires_power = 0 - lighting_use_dynamic = 0 - has_gravity = 1 - -// === end remove - -/area/alien - name = "\improper Alien base" - icon_state = "yellow" - requires_power = 0 - -// CENTCOM - -/area/centcom - name = "\improper Centcom" - icon_state = "centcom" - requires_power = 0 - lighting_use_dynamic = 0 - -/area/centcom/control - name = "\improper Centcom Control" - -/area/centcom/evac - name = "\improper Centcom Emergency Shuttle" - -/area/centcom/suppy - name = "\improper Centcom Supply Shuttle" - -/area/centcom/ferry - name = "\improper Centcom Transport Shuttle" - -/area/centcom/shuttle - name = "\improper Centcom Administration Shuttle" - -/area/centcom/test - name = "\improper Centcom Testing Facility" - -/area/centcom/living - name = "\improper Centcom Living Quarters" - -/area/centcom/specops - name = "\improper Centcom Special Ops" - -/area/centcom/creed - name = "Creed's Office" - -/area/centcom/holding - name = "\improper Holding Facility" - -//SYNDICATES - -/area/syndicate_mothership - name = "\improper Syndicate Mothership" - icon_state = "syndie-ship" - requires_power = 0 - lighting_use_dynamic = 0 - -/area/syndicate_mothership/control - name = "\improper Syndicate Control Room" - icon_state = "syndie-control" - -/area/syndicate_mothership/elite_squad - name = "\improper Syndicate Elite Squad" - icon_state = "syndie-elite" - -//EXTRA - -/area/asteroid // -- TLE - name = "\improper Asteroid" - icon_state = "asteroid" - requires_power = 0 - -/area/asteroid/cave // -- TLE - name = "\improper Asteroid - Underground" - icon_state = "cave" - requires_power = 0 - -/area/asteroid/artifactroom - name = "\improper Asteroid - Artifact" - icon_state = "cave" - -/area/planet/clown - name = "\improper Clown Planet" - icon_state = "honk" - requires_power = 0 - -/area/asteroid/clown - name = "\improper Clown Roid" - icon_state = "honk" - requires_power = 0 - -/area/tdome - name = "\improper Thunderdome" - icon_state = "thunder" - requires_power = 0 - lighting_use_dynamic = 0 - -/area/tdome/tdome1 - name = "\improper Thunderdome (Team 1)" - icon_state = "green" - -/area/tdome/tdome2 - name = "\improper Thunderdome (Team 2)" - icon_state = "yellow" - -/area/tdome/tdomeadmin - name = "\improper Thunderdome (Admin.)" - icon_state = "purple" - -/area/tdome/tdomeobserve - name = "\improper Thunderdome (Observer.)" - icon_state = "purple" - -//ENEMY - -//names are used -/area/syndicate_station - name = "\improper Syndicate Shuttle" - icon_state = "yellow" - requires_power = 0 - lighting_use_dynamic = 1 - -/area/syndicate_station/start - icon_state = "yellow" - -/area/syndicate_station/southwest - name = "\improper south-west of SS13" - icon_state = "southwest" - -/area/syndicate_station/northwest - name = "\improper north-west of SS13" - icon_state = "northwest" - -/area/syndicate_station/northeast - name = "\improper north-east of SS13" - icon_state = "northeast" - -/area/syndicate_station/southeast - name = "\improper south-east of SS13" - icon_state = "southeast" - -/area/syndicate_station/north - name = "\improper north of SS13" - icon_state = "north" - -/area/syndicate_station/south - name = "\improper south of SS13" - icon_state = "south" - -/area/syndicate_station/commssat - name = "\improper south of the communication satellite" - icon_state = "south" - -/area/syndicate_station/mining - name = "\improper north east of the mining asteroid" - icon_state = "north" - -/area/wizard_station - name = "\improper Wizard's Den" - icon_state = "yellow" - requires_power = 0 - lighting_use_dynamic = 0 - -/area/vox_station/southwest_solars - name = "\improper aft port solars" - icon_state = "southwest" - requires_power = 0 - -/area/vox_station/northwest_solars - name = "\improper fore port solars" - icon_state = "northwest" - requires_power = 0 - -/area/vox_station/northeast_solars - name = "\improper fore starboard solars" - icon_state = "northeast" - requires_power = 0 - -/area/vox_station/southeast_solars - name = "\improper aft starboard solars" - icon_state = "southeast" - requires_power = 0 - -/area/vox_station/mining - name = "\improper nearby mining asteroid" - icon_state = "north" - requires_power = 0 - -//PRISON -/area/prison - name = "\improper Prison Station" - icon_state = "brig" - -/area/prison/arrival_airlock - name = "\improper Prison Station Airlock" - icon_state = "green" - requires_power = 0 - -/area/prison/control - name = "\improper Prison Security Checkpoint" - icon_state = "security" - -/area/prison/crew_quarters - name = "\improper Prison Security Quarters" - icon_state = "security" - -/area/prison/rec_room - name = "\improper Prison Rec Room" - icon_state = "green" - -/area/prison/closet - name = "\improper Prison Supply Closet" - icon_state = "dk_yellow" - -/area/prison/hallway/fore - name = "\improper Prison Fore Hallway" - icon_state = "yellow" - -/area/prison/hallway/aft - name = "\improper Prison Aft Hallway" - icon_state = "yellow" - -/area/prison/hallway/port - name = "\improper Prison Port Hallway" - icon_state = "yellow" - -/area/prison/hallway/starboard - name = "\improper Prison Starboard Hallway" - icon_state = "yellow" - -/area/prison/morgue - name = "\improper Prison Morgue" - icon_state = "morgue" - -/area/prison/medical_research - name = "\improper Prison Genetic Research" - icon_state = "medresearch" - -/area/prison/medical - name = "\improper Prison Medbay" - icon_state = "medbay" - -/area/prison/solar - name = "\improper Prison Solar Array" - icon_state = "storage" - requires_power = 0 - -/area/prison/podbay - name = "\improper Prison Podbay" - icon_state = "dk_yellow" - -/area/prison/solar_control - name = "\improper Prison Solar Array Control" - icon_state = "dk_yellow" - -/area/prison/solitary - name = "Solitary Confinement" - icon_state = "brig" - -/area/prison/cell_block/A - name = "Prison Cell Block A" - icon_state = "brig" - -/area/prison/cell_block/B - name = "Prison Cell Block B" - icon_state = "brig" - -/area/prison/cell_block/C - name = "Prison Cell Block C" - icon_state = "brig" - -//STATION13 - -//Maintenance - -/area/maintenance/fpmaint - name = "Fore Port Maintenance" - icon_state = "fpmaint" - -/area/maintenance/fpmaint2 - name = "Fore Port Maintenance" - icon_state = "fpmaint" - -/area/maintenance/fpmaint3 - name = "Fore Port Maintenance" - icon_state = "fpmaint" - -/area/maintenance/fsmaint - name = "Fore Starboard Maintenance" - icon_state = "fsmaint" - -/area/maintenance/fsmaint2 - name = "Fore Starboard Maintenance" - icon_state = "fsmaint" - -/area/maintenance/asmaint - name = "Aft Starboard Maintenance" - icon_state = "asmaint" - -/area/maintenance/asmaint2 - name = "Aft Starboard Maintenance" - icon_state = "asmaint" - -/area/maintenance/asmaint3 - name = "Xenobiology Maintenance" - icon_state = "asmaint" - -/area/maintenance/apmaint - name = "Aft Port Maintenance" - icon_state = "apmaint" - -/area/maintenance/maintcentral - name = "Central Maintenance" - icon_state = "maintcentral" - -/area/maintenance/fore - name = "Fore Maintenance" - icon_state = "fmaint" - -/area/maintenance/starboard - name = "Starboard Maintenance" - icon_state = "smaint" - -/area/maintenance/port - name = "Port Maintenance" - icon_state = "pmaint" - -/area/maintenance/aft - name = "Aft Maintenance" - icon_state = "amaint" - -/area/maintenance/atmos - name = "Atmospherics" - icon_state = "green" - -/area/maintenance/incinerator - name = "\improper Incinerator" - icon_state = "disposal" - -/area/maintenance/disposal - name = "Recycling" - icon_state = "disposal" - -/area/maintenance/secdisposal - name = "Security Disposals" - icon_state = "secdisp" - -/area/maintenance/auxcharge - name = "Auxiliary Cyborg Recharge" - icon_state = "auxcharge" - -/area/maintenance/ghettobar - name = "Ghetto Bar" - icon_state = "ghettobar" - -//Hallway - -/area/hallway/primary/fore - name = "\improper Fore Primary Hallway" - icon_state = "hallF" - -/area/hallway/primary/starboard - name = "\improper Starboard Primary Hallway" - icon_state = "hallS" - -/area/hallway/primary/aft - name = "\improper Aft Primary Hallway" - icon_state = "hallA" - -/area/hallway/primary/port - name = "\improper Port Primary Hallway" - icon_state = "hallP" - -/area/hallway/primary/central - name = "\improper Central Primary Hallway" - icon_state = "hallC" - -/area/hallway/secondary/exit - name = "\improper Escape Shuttle Hallway" - icon_state = "escape" - -/area/hallway/secondary/construction - name = "\improper Construction Area" - icon_state = "construction" - -/area/hallway/secondary/entry - name = "\improper Arrival Shuttle Hallway" - icon_state = "entry" - -//Command - -/area/bridge - name = "\improper Bridge" - icon_state = "bridge" - music = "signal" - jammed=1 - -/area/bridge/meeting_room - name = "\improper Heads of Staff Meeting Room" - icon_state = "bridge" - music = null - jammed=0 - -/area/crew_quarters/captain - name = "\improper Captain's Office" - icon_state = "captain" - jammed=1 - -/area/crew_quarters/heads -/area/crew_quarters/heads/hop - name = "\improper Head of Personnel's Quarters" - icon_state = "head_quarters" - jammed=1 - -/area/crew_quarters/heads/rd - name = "\improper Research Director's Quarters" - icon_state = "head_quarters" - jammed=1 - -/area/crew_quarters/heads/ce - name = "\improper Chief Engineer's Quarters" - icon_state = "head_quarters" - jammed=1 - -/area/crew_quarters/heads/hos - name = "\improper Head of Security's Quarters" - icon_state = "head_quarters" - jammed=1 - -/area/crew_quarters/heads/cmo - name = "\improper Chief Medical Officer's Quarters" - icon_state = "head_quarters" - jammed=1 - -/area/crew_quarters/courtroom - name = "\improper Courtroom" - icon_state = "courtroom" - -/area/crew_quarters/hop - name = "\improper Head of Personnel's Office" - icon_state = "head_quarters" - jammed=1 - -/area/mint - name = "\improper Mint" - icon_state = "green" - -/area/comms - name = "\improper Communications Relay" - icon_state = "tcomsatcham" - -/area/server - name = "\improper Messaging Server Room" - icon_state = "server" - -//Crew - -/area/crew_quarters - name = "\improper Dormitories" - icon_state = "Sleep" - -/area/crew_quarters/toilet - name = "\improper Dormitory Toilets" - icon_state = "toilet" - -/area/crew_quarters/sleep - name = "\improper Dormitories" - icon_state = "Sleep" - -/area/crew_quarters/sleep_male - name = "\improper Male Dorm" - icon_state = "Sleep" - -/area/crew_quarters/sleep_male/toilet_male - name = "\improper Male Toilets" - icon_state = "toilet" - -/area/crew_quarters/sleep_female - name = "\improper Female Dorm" - icon_state = "Sleep" - -/area/crew_quarters/sleep_female/toilet_female - name = "\improper Female Toilets" - icon_state = "toilet" - -/area/crew_quarters/locker - name = "\improper Locker Room" - icon_state = "locker" - -/area/crew_quarters/locker/locker_toilet - name = "\improper Locker Toilets" - icon_state = "toilet" - -/area/crew_quarters/fitness - name = "\improper Fitness Room" - icon_state = "fitness" - -/area/crew_quarters/cafeteria - name = "\improper Cafeteria" - icon_state = "cafeteria" - -/area/crew_quarters/kitchen - name = "\improper Kitchen" - icon_state = "kitchen" - -/area/crew_quarters/bar - name = "\improper Bar" - icon_state = "bar" - -/area/crew_quarters/theatre - name = "\improper Theatre" - icon_state = "Theatre" - -/area/library - name = "\improper Library" - icon_state = "library" - -/area/chapel/main - name = "\improper Chapel" - icon_state = "chapel" - -/area/chapel/office - name = "\improper Chapel Office" - icon_state = "chapeloffice" - -/area/lawoffice - name = "\improper Law Office" - icon_state = "law" - -/area/crew_quarters/casino - name = "Casino" - icon_state = "casino" - - - - - - - -/area/holodeck - name = "\improper Holodeck" - icon_state = "Holodeck" - lighting_use_dynamic = 0 - -/area/holodeck/alphadeck - name = "\improper Holodeck Alpha" - - -/area/holodeck/source_plating - name = "\improper Holodeck - Off" - icon_state = "Holodeck" - jammed=SUPER_JAMMED - -/area/holodeck/source_emptycourt - name = "\improper Holodeck - Empty Court" - jammed=SUPER_JAMMED - -/area/holodeck/source_boxingcourt - name = "\improper Holodeck - Boxing Court" - jammed=SUPER_JAMMED - -/area/holodeck/source_basketball - name = "\improper Holodeck - Basketball Court" - jammed=SUPER_JAMMED - -/area/holodeck/source_thunderdomecourt - name = "\improper Holodeck - Thunderdome Court" - jammed=SUPER_JAMMED - -/area/holodeck/source_beach - name = "\improper Holodeck - Beach" - icon_state = "Holodeck" // Lazy. - jammed=SUPER_JAMMED - -/area/holodeck/source_burntest - name = "\improper Holodeck - Atmospheric Burn Test" - jammed=SUPER_JAMMED - -/area/holodeck/source_wildlife - name = "\improper Holodeck - Wildlife Simulation" - jammed=SUPER_JAMMED - -/area/holodeck/source_meetinghall - name = "\improper Holodeck - Meeting Hall" - jammed=SUPER_JAMMED - -/area/holodeck/source_theatre - name = "\improper Holodeck - Theatre" - jammed=SUPER_JAMMED - -/area/holodeck/source_picnicarea - name = "\improper Holodeck - Picnic Area" - jammed=SUPER_JAMMED - -/area/holodeck/source_snowfield - name = "\improper Holodeck - Snow Field" - jammed=SUPER_JAMMED - -/area/holodeck/source_desert - name = "\improper Holodeck - Desert" - jammed=SUPER_JAMMED - -/area/holodeck/source_space - name = "\improper Holodeck - Space" - jammed=SUPER_JAMMED - - - - - - - - - - - -//Engineering - -/area/engineering - -/area/engineering/engine_smes - name = "\improper Engineering SMES" - icon_state = "engine_smes" - requires_power = 0//This area only covers the batteries and they deal with their own power - -/area/engineering/engine - name = "Engineering" - icon_state = "engine" - -/area/engineering/engine_storage - name = "Engineering Secure Storage" - icon_state = "engine_storage" - -/area/engineering/break_room - name = "\improper Engineering Foyer" - icon_state = "engine_lobby" - -/area/engineering/ce - name = "\improper Chief Engineer's Office" - icon_state = "head_quarters" - jammed=1 - -/area/engineering/burn_chamber - name = "Burn Chamber" - icon_state = "thermo_engine" - -/area/engineering/atmos - name = "Atmospherics" - icon_state = "atmos" - -/area/engineering/atmos_control - name = "Atmospherics Monitoring" - icon_state = "atmos_monitor" - -/area/engineering/supermatter_room - name = "Supermatter Room" - icon_state = "supermatter" - -/area/engineering/antimatter_room - name = "Antimatter Engine Room" - icon_state = "antimatter" - -/area/engineering/engineering_auxiliary - name = "Auxiliary Engineering" - icon_state = "engiaux" - -/area/engineering/mechanics - name = "Mechanics" - icon_state = "mechanics" - - -//Solars - -/area/solar - requires_power = 0 - lighting_use_dynamic = 0 - -/area/solar/fport - name = "\improper Fore Port Solar Array" - icon_state = "panelsA" - -/area/solar/fstarboard - name = "\improper Fore Starboard Solar Array" - icon_state = "panelsA" - -/area/solar/fore - name = "\improper Fore Solar Array" - icon_state = "yellow" - -/area/solar/aft - name = "\improper Aft Solar Array" - icon_state = "aft" - -/area/solar/astarboard - name = "\improper Aft Starboard Solar Array" - icon_state = "panelsS" - -/area/solar/auxstarboard - name = "\improper Auxillary Starboard Solar Array" - icon_state = "panelsS" - -/area/solar/aport - name = "\improper Aft Port Solar Array" - icon_state = "panelsP" - -/area/solar/auxport - name = "\improper Auxillary Port Solar Array" - icon_state = "panelsP" - -/area/maintenance/auxsolarstarboard - name = "Auxillary Starboard Solar Maintenance" - icon_state = "SolarcontrolS" - -/area/maintenance/auxsolarport - name = "Auxillary Port Solar Maintenance" - icon_state = "SolarcontrolP" - -/area/maintenance/fportsolar - name = "Fore Port Solar Maintenance" - icon_state = "SolarcontrolA" - -/area/maintenance/astarboardsolar - name = "Aft Starboard Solar Maintenance" - icon_state = "SolarcontrolS" - -/area/maintenance/aportsolar - name = "Aft Port Solar Maintenance" - icon_state = "SolarcontrolP" - -/area/maintenance/fstarboardsolar - name = "Fore Starboard Solar Maintenance" - icon_state = "SolarcontrolA" - -/area/maintenance/virology_maint - name = "Virology Maintenance" - icon_state = "asmaint" - -/area/science/showroom - name = "\improper Robotics Showroom" - icon_state = "showroom" - -/area/assembly/assembly_line //Derelict Assembly Line - name = "\improper Assembly Line" - icon_state = "ass_line" - power_equip = 0 - power_light = 0 - power_environ = 0 - -//Teleporter - -/area/teleporter - name = "\improper Teleporter" - icon_state = "teleporter" - music = "signal" - jammed=1 - -/area/gateway - name = "\improper Gateway" - icon_state = "teleporter" - music = "signal" - -/area/AIsattele - name = "\improper AI Satellite Teleporter Room" - icon_state = "teleporter" - music = "signal" - -//MedBay - -/area/medical/medbay - name = "Medbay" - icon_state = "medbay" - music = 'sound/ambience/signal.ogg' - -//Medbay is a large area, these additional areas help level out APC load. -/area/medical/medbay2 - name = "Medbay" - icon_state = "medbay2" - music = 'sound/ambience/signal.ogg' - -/area/medical/surgery_ghetto - name = "Ghetto Surgery" - icon_state = "medbay_ghetto" - music = 'sound/ambience/signal.ogg' - -/area/medical/medbay3 - name = "Medbay" - icon_state = "medbay3" - music = 'sound/ambience/signal.ogg' - -/area/medical/break_room - name = "Medbay Break Room" - icon_state = "medbay_break" - music = 'sound/ambience/signal.ogg' - -/area/medical/patients_rooms - name = "\improper Patient's Rooms" - icon_state = "patients" - -/area/medical/patient_room1 - name = "\improper Patient Room 1" - icon_state = "patients" - -/area/medical/patient_room2 - name = "\improper Patient Room 2" - icon_state = "patients" - -/area/medical/cmo - name = "\improper Chief Medical Officer's Office" - icon_state = "CMO" - jammed=1 - -/area/medical/virology - name = "Virology" - icon_state = "virology" - -/area/medical/virology_break - name = "Virology Break Room" - icon_state = "virology" - -/area/medical/morgue - name = "\improper Morgue" - icon_state = "morgue" - -/area/medical/chemistry - name = "Chemistry" - icon_state = "chem" - -/area/medical/surgery - name = "Surgery" - icon_state = "surgery" - -/area/medical/cryo - name = "Cryogenics" - icon_state = "cryo" - -/area/medical/storage - name = "\improper Medbay Storage" - icon_state = "med_storage" - -/area/medical/exam_room - name = "\improper Exam Room" - icon_state = "exam_room" - -/area/medical/genetics - name = "Genetics Lab" - icon_state = "genetics" - -/area/medical/genetics_cloning - name = "Cloning Lab" - icon_state = "cloning" - -/area/medical/sleeper - name = "Medbay Treatment Center" - icon_state = "exam_room" - -/area/medical/paramedics - name = "\improper Paramedic Station" - icon_state = "paramedics" - -//Security - -/area/security/main - name = "\improper Security Office" - icon_state = "security" - -/area/security/lobby - name = "\improper Security Lobby" - icon_state = "sec_lobby" - -/area/security/brig - name = "\improper Brig" - icon_state = "brig" - -/area/security/prison - name = "\improper Prison Wing" - icon_state = "sec_prison" - -/area/security/perma - name = "\improper Permanent Confinement" - icon_state = "sec_perma" - -/area/security/gas_chamber - name = "\improper Execution Chamber" - icon_state = "bar" // Because it's all parties from here on. - jammed=1 - -/area/security/medical - name = "\improper Brig Medbay" - icon_state = "sec_medbay" - -/area/security/toilet - name = "\improper Brig Toilets" - icon_state = "toilet" - -/area/security/rec_room - name = "\improper Brig Recording Room" - icon_state = "rec" - -/area/security/evidence - name = "\improper Evidence Storage" - icon_state = "interrog" - -/area/security/interrogation - name = "\improper Interrogation Room" - icon_state = "interrog" - -/area/security/processing - name = "\improper Prisoner Education Chamber" - icon_state = "interrog" - -/obj/item/weapon/paper/Gaschamber - name = "paper - 'Gas Chambers for Idiots'" - info = {"

      Gas Chambers for Idiots

      -

      So here you are, with a fancy, new gas chamber thanks to cheap MoMMI labor. Now you've got a guy you need to die and have no idea what to do.

      -
        -
      1. First, use the computer in the witnessing room to shut off the scrubbers: Set Environmental Mode, Off.
      2. -
      3. Run down to the door for the room south of the witnessing room. You'll see a bunch of N2O or CO2 tanks.
      4. -
      5. Select the tank you want and drag it onto the connector. N2O (same shit used in anesthesia tanks in surgery) makes you go sleepy and kills in high enough doses, while CO2 makes people fall over comically and eventually die. CO2 is best because it's easier to tell when Mr. Revpants is dead, and because the room is configured for CO2 executions..
      6. -
      7. Make sure everyone you don't want dead is out of the chamber and the door is closed.
      8. -
      9. Wrench the tank in and go watch the fun from witnessing.
      10. -
      11. Once he's dead, set environmentals to filtering (or Cycle, if you're an idiot and used N2O).
      12. -
      13. Run back down to gas control and unwrench the tank.
      14. -
      15. Drag the dead bastard out once the computer says it's safe to enter.
      16. -
      "} - -/area/security/warden - name = "\improper Warden" - icon_state = "Warden" - jammed=1 - -/area/security/armory - name = "\improper Secure Armory" - icon_state = "Armory" - jammed=1 - -/area/security/hos - name = "\improper Head of Security's Office" - icon_state = "sec_hos" - jammed=1 - -/area/security/detectives_office - name = "\improper Detective's Office" - icon_state = "detective" - -/area/security/range - name = "\improper Firing Range" - icon_state = "firingrange" - -/* - New() - ..() - - spawn(10) //let objects set up first - for(var/turf/turfToGrayscale in src) - if(turfToGrayscale.icon) - var/icon/newIcon = icon(turfToGrayscale.icon) - newIcon.GrayScale() - turfToGrayscale.icon = newIcon - for(var/obj/objectToGrayscale in turfToGrayscale) //1 level deep, means tables, apcs, locker, etc, but not locker contents - if(objectToGrayscale.icon) - var/icon/newIcon = icon(objectToGrayscale.icon) - newIcon.GrayScale() - objectToGrayscale.icon = newIcon -*/ - -/area/security/checkpoint - name = "\improper Security Checkpoint" - icon_state = "checkpoint1" - -/area/security/checkpoint2 - name = "\improper Security Checkpoint" - icon_state = "security" - -/area/security/checkpoint/supply - name = "Security Post - Cargo Bay" - icon_state = "checkpoint1" - -/area/security/checkpoint/engineering - name = "Security Post - Engineering" - icon_state = "checkpoint1" - -/area/security/checkpoint/medical - name = "Security Post - Medbay" - icon_state = "checkpoint1" - -/area/security/checkpoint/science - name = "Security Post - Science" - icon_state = "checkpoint1" - -/area/security/vacantoffice - name = "\improper Vacant Office" - icon_state = "security" - -/area/security/vacantoffice2 - name = "\improper Vacant Office" - icon_state = "security" - -/area/supply - name = "\improper Quartermasters" - icon_state = "quart" - -///////////WORK IN PROGRESS////////// - -/area/supply/sorting - name = "\improper Delivery Office" - icon_state = "cargo_delivery" - -////////////WORK IN PROGRESS////////// - -/area/supply/lobby - name ="\improper Cargo Lobby" - icon_state = "cargo_lobby" - -/area/supply/office - name = "\improper Cargo Office" - icon_state = "cargo_office" - -/area/supply/storage - name = "\improper Cargo Bay" - icon_state = "cargo_bay" - -/area/supply/qm - name = "\improper Quartermaster's Office" - icon_state = "cargo_quart" - jammed=1 - -/area/supply/miningdock - name = "\improper Mining Dock" - icon_state = "mining" - -/area/supply/miningstorage - name = "\improper Mining Storage" - icon_state = "green" - -/area/supply/miningdelivery - name = "\improper Mining Delivery" - icon_state = "mining_delivery" - -/area/supply/mechbay - name = "\improper Mech Bay" - icon_state = "yellow" - -/area/janitor/ - name = "\improper Custodial Closet" - icon_state = "janitor" - -/area/janitor2/ - name = "\improper Custodial Closet" - icon_state = "janitor" - -/area/hydroponics - name = "Hydroponics" - icon_state = "hydro" - -//Toxins - -/area/science/lab - name = "\improper Research and Development" - icon_state = "toxlab" - -/area/science/hallway - name = "\improper Research Division" - icon_state = "tox_hall" - -/area/science/rd - name = "\improper Research Director's Office" - icon_state = "head_quarters" - jammed=1 - -/area/science/supermatter - name = "\improper Supermatter Lab" - icon_state = "toxlab" - -/area/science/xenobiology - name = "\improper Xenobiology Lab" - icon_state = "xenobio" - -/area/science/xenobiology/specimen_1 - name = "\improper Xenobiology Specimen Cage 1" - icon_state = "xenocell1" - -/area/science/xenobiology/specimen_2 - name = "\improper Xenobiology Specimen Cage 2" - icon_state = "xenocell2" - -/area/science/xenobiology/specimen_3 - name = "\improper Xenobiology Specimen Cage 3" - icon_state = "xenocell3" - -/area/science/xenobiology/specimen_4 - name = "\improper Xenobiology Specimen Cage 4" - icon_state = "xenocell4" - -/area/science/xenobiology/specimen_5 - name = "\improper Xenobiology Specimen Cage 5" - icon_state = "xenocell5" - -/area/science/xenobiology/specimen_6 - name = "\improper Xenobiology Specimen Cage 6" - icon_state = "xenocell6" - -/area/science/robotics - name = "\improper Robotics Lab" - icon_state = "ass_line" - -/area/science/chargebay - name = "\improper Mech Bay" - icon_state = "mechbay" - -/area/science/storage - name = "\improper Toxins Storage" - icon_state = "toxstorage" - -/area/science/test_area - name = "\improper Toxins Test Area" - icon_state = "toxtest" - -/area/science/shuttlebay - name = "\improper Research Shuttle Bay" - icon_state = "toxshuttle" - -/area/science/mixing - name = "\improper Toxins Mixing Room" - icon_state = "toxmix" - -/area/science/telescience - name = "\improper Telescience" - icon_state = "toxmisc" - -/area/science/podbay - name = "\improper Pod Bay" - icon_state = "pod" - -/area/science/server - name = "\improper Server Room" - icon_state = "server" - jammed=1 - -//Storage - -/area/storage/tools - name = "Auxiliary Tool Storage" - icon_state = "storage" - -/area/storage/primary - name = "Primary Tool Storage" - icon_state = "primarystorage" - -/area/storage/autolathe - name = "Autolathe Storage" - icon_state = "storage" - -/area/storage/art - name = "Art Supply Storage" - icon_state = "storage" - -/area/storage/auxillary - name = "Auxillary Storage" - icon_state = "auxstorage" - -/area/storage/eva - name = "EVA Storage" - icon_state = "eva" - jammed=1 - -/area/storage/secure - name = "Secure Storage" - icon_state = "storage" - jammed=1 - -/area/storage/nuke_storage - name = "\improper Vault" - icon_state = "nuke_storage" - -/area/storage/emergency - name = "Starboard Emergency Storage" - icon_state = "emergencystorage" - -/area/storage/emergency2 - name = "Port Emergency Storage" - icon_state = "emergencystorage" - -/area/storage/tech - name = "Technical Storage" - icon_state = "auxstorage" - jammed=1 - -/area/storage/testroom - requires_power = 0 - name = "\improper Test Room" - icon_state = "storage" - -//DJSTATION - -/area/djstation - name = "\improper Ruskie DJ Station" - icon_state = "DJ" - -/area/djstation/solars - name = "\improper DJ Station Solars" - icon_state = "DJ" - -//DERELICT - -/area/derelict - name = "\improper Derelict Station" - icon_state = "storage" - - general_area = /area/derelict - general_area_name = "Derelict Station" - -/area/derelict/hallway/primary - name = "\improper Derelict Primary Hallway" - icon_state = "hallP" - -/area/derelict/hallway/secondary - name = "\improper Derelict Secondary Hallway" - icon_state = "hallS" - -/area/derelict/arrival - name = "\improper Derelict Arrival Centre" - icon_state = "yellow" - -/area/derelict/storage/equipment - name = "Derelict Equipment Storage" - -/area/derelict/storage/storage_access - name = "Derelict Storage Access" - -/area/derelict/storage/engine_storage - name = "Derelict Engine Storage" - icon_state = "green" - -/area/derelict/bridge - name = "\improper Derelict Control Room" - icon_state = "bridge" - -/area/derelict/secret - name = "\improper Derelict Secret Room" - icon_state = "library" - -/area/derelict/bridge/access - name = "Derelict Control Room Access" - icon_state = "auxstorage" - -/area/derelict/bridge/ai_upload - name = "\improper Derelict Computer Core" - icon_state = "ai" - -/area/derelict/solar_control - name = "\improper Derelict Solar Control" - icon_state = "engine" - -/area/derelict/atmos - name = "\improper Derelict Atmospherics" - icon_state = "atmos" - -/area/derelict/research - name = "\improper Derelict Research" - icon_state = "toxins" - -/area/derelict/crew_quarters - name = "\improper Derelict Crew Quarters" - icon_state = "fitness" - -/area/derelict/medical - name = "Derelict Medbay" - icon_state = "medbay" - -/area/derelict/medical/morgue - name = "\improper Derelict Morgue" - icon_state = "morgue" - -/area/derelict/medical/chapel - name = "\improper Derelict Chapel" - icon_state = "chapel" - -/area/derelict/teleporter - name = "\improper Derelict Teleporter" - icon_state = "teleporter" - -/area/derelict/eva - name = "Derelict EVA Storage" - icon_state = "eva" - -/area/derelict/ship - name = "\improper Abandoned Ship" - icon_state = "yellow" - -/area/solar/derelict_starboard - name = "\improper Derelict Starboard Solar Array" - icon_state = "panelsS" - -/area/solar/derelict_aft - name = "\improper Derelict Aft Solar Array" - icon_state = "aft" - -/area/derelict/singularity_engine - name = "\improper Derelict Singularity Engine" - icon_state = "engine" - -/area/derelict/research - name = "\improper Derelict Research" - icon_state = "toxmisc" - -//Construction - -/area/construction - name = "\improper Construction Area" - icon_state = "yellow" - -/area/construction/mommi_nest - name = "\improper MoMMI Nest" - icon_state = "yellow" - -/area/construction/supplyshuttle - name = "\improper Supply Shuttle" - icon_state = "yellow" - -/area/construction/quarters - name = "\improper Engineer's Quarters" - icon_state = "yellow" - -/area/construction/qmaint - name = "Maintenance" - icon_state = "yellow" - -/area/construction/hallway - name = "\improper Hallway" - icon_state = "yellow" - -/area/construction/solars - name = "\improper Solar Panels" - icon_state = "yellow" - -/area/construction/solarscontrol - name = "\improper Solar Panel Control" - icon_state = "yellow" - -/area/construction/Storage - name = "Construction Site Storage" - icon_state = "yellow" - -//AI - -/area/ai_monitored/storage/eva - name = "EVA Storage" - icon_state = "eva" - jammed=1 - -/area/ai_monitored/storage/secure - name = "Secure Storage" - icon_state = "storage" - -/area/ai_monitored/storage/emergency - name = "Emergency Storage" - icon_state = "storage" - -/area/turret_protected/ai_upload - name = "\improper AI Upload Chamber" - icon_state = "ai_upload" - jammed=1 - -/area/turret_protected/ai_upload_foyer - name = "AI Upload Access" - icon_state = "ai_foyer" - -/area/turret_protected/ai - name = "\improper AI Chamber" - icon_state = "ai_chamber" - jammed=1 - -/area/turret_protected/aisat - name = "\improper AI Satellite" - icon_state = "ai" - -/area/turret_protected/aisat_interior - name = "\improper AI Satellite" - icon_state = "ai" - -/area/turret_protected/AIsatextFP - name = "\improper AI Sat Ext" - icon_state = "storage" - lighting_use_dynamic = 0 - -/area/turret_protected/AIsatextFS - name = "\improper AI Sat Ext" - icon_state = "storage" - lighting_use_dynamic = 0 - -/area/turret_protected/AIsatextAS - name = "\improper AI Sat Ext" - icon_state = "storage" - lighting_use_dynamic = 0 - -/area/turret_protected/AIsatextAP - name = "\improper AI Sat Ext" - icon_state = "storage" - lighting_use_dynamic = 0 - -/area/turret_protected/NewAIMain - name = "\improper AI Main New" - icon_state = "storage" - - - -//Misc - - - -/area/wreck/ai - name = "\improper AI Chamber" - icon_state = "ai" - -/area/wreck/main - name = "\improper Wreck" - icon_state = "storage" - -/area/wreck/engineering - name = "\improper Power Room" - icon_state = "engine" - -/area/wreck/bridge - name = "\improper Bridge" - icon_state = "bridge" - -/area/generic - name = "Unknown" - icon_state = "storage" - - -////////////////////////////// -// VOX TRADING POST -////////////////////////////// - -/area/vox_trading_post - name = "\improper Vox Trade Outpost" - icon_state = "yellow" - - general_area = /area/vox_trading_post - general_area_name = "Vox Trade Outpost" - -/area/vox_trading_post/trading_floor - name = "\improper Vox Trading Floor" - icon_state = "yellow" - -/area/vox_trading_post/trade_processing - name = "\improper Vox Trade Processing" - icon_state = "green" - -/area/vox_trading_post/armory - name = "\improper Vox Armory" - icon_state = "armory" - -/area/vox_trading_post/gardens - name = "\improper Vox Botanical Gardens" - icon_state = "hydro" - -/area/vox_trading_post/atmos - name = "\improper Vox Atmospherics" - icon_state = "atmos" - -/area/vox_trading_post/eva - name = "\improper Vox EVA" - icon_state = "eva" - -/area/vox_trading_post/storage_1 - name = "\improper Vox Storage Room" - icon_state = "storage" - -/area/vox_trading_post/vault - name = "\improper Vox Vault" - icon_state = "primarystorage" - -/area/vox_trading_post/hallway - name = "\improper Vox Hallways" - icon_state = "hallP" - - - -// Telecommunications Satellite -/area/tcommsat - name = "Telecommunications Satellite" - - general_area = /area/tcommsat - general_area_name = "Telecommunications Satellite" - -/area/tcommsat/entrance - name = "\improper Satellite Teleporter" - icon_state = "tcomsatentrance" - -/area/tcommsat/chamber - name = "\improper Telecoms Central Compartment" - icon_state = "tcomsatcham" - -/area/tcomms/chamber - name = "\improper Telecoms Chamber" - icon_state = "ai" - -/area/tcomms/storage - name = "\improper Telecoms Storage" - icon_state = "primarystorage" - -/area/turret_protected/tcomms_control_room - name = "\improper Telecomms Control Room" - icon_state = "tcomsatcomp" - jammed=1 - -/area/turret_protected/tcomsat - name = "\improper Satellite Entrance" - icon_state = "tcomsatlob" - -/area/turret_protected/tcomfoyer - name = "\improper Telecoms Foyer" - icon_state = "tcomsatentrance" - -/area/turret_protected/tcomwest - name = "\improper Telecommunications Satellite West Wing" - icon_state = "tcomsatwest" - -/area/turret_protected/tcomeast - name = "\improper Telecommunications Satellite East Wing" - icon_state = "tcomsateast" - -/area/tcommsat/computer - name = "\improper Satellite Control Room" - icon_state = "tcomsatcomp" - -/area/tcommsat/lounge - name = "\improper Satellite Lounge" - icon_state = "tcomsatlounge" - -/area/turret_protected/goonroom - name = "\improper Goonecode Containment" - icon_state = "ai_upload" - jammed=2 - anti_ethereal=1 - - - -// Away Missions -/area/awaymission - name = "\improper Strange Location" - icon_state = "away" - -/area/awaymission/example - name = "\improper Strange Station" - icon_state = "away" - -/area/awaymission/wwmines - name = "\improper Wild West Mines" - icon_state = "away1" - requires_power = 0 - -/area/awaymission/wwgov - name = "\improper Wild West Mansion" - icon_state = "away2" - requires_power = 0 - -/area/awaymission/wwrefine - name = "\improper Wild West Refinery" - icon_state = "away3" - requires_power = 0 - -/area/awaymission/wwvault - name = "\improper Wild West Vault" - icon_state = "away3" - -/area/awaymission/wwvaultdoors - name = "\improper Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power - icon_state = "away2" - requires_power = 0 - -/area/awaymission/desert - name = "Mars" - icon_state = "away" - -/area/awaymission/BMPship1 - name = "\improper Aft Block" - icon_state = "away1" - -/area/awaymission/BMPship2 - name = "\improper Midship Block" - icon_state = "away2" - -/area/awaymission/BMPship3 - name = "\improper Fore Block" - icon_state = "away3" - -/area/awaymission/spacebattle - name = "\improper Space Battle" - icon_state = "away" - requires_power = 0 - -/area/awaymission/spacebattle/cruiser - name = "\improper Nanotrasen Cruiser" - -/area/awaymission/spacebattle/syndicate1 - name = "\improper Syndicate Assault Ship 1" - -/area/awaymission/spacebattle/syndicate2 - name = "\improper Syndicate Assault Ship 2" - -/area/awaymission/spacebattle/syndicate3 - name = "\improper Syndicate Assault Ship 3" - -/area/awaymission/spacebattle/syndicate4 - name = "\improper Syndicate War Sphere 1" - -/area/awaymission/spacebattle/syndicate5 - name = "\improper Syndicate War Sphere 2" - -/area/awaymission/spacebattle/syndicate6 - name = "\improper Syndicate War Sphere 3" - -/area/awaymission/spacebattle/syndicate7 - name = "\improper Syndicate Fighter" - -/area/awaymission/spacebattle/secret - name = "\improper Hidden Chamber" - -/area/awaymission/listeningpost - name = "\improper Listening Post" - icon_state = "away" - requires_power = 0 - -/area/awaymission/beach - name = "Beach" - icon_state = "null" - lighting_use_dynamic = 0 - requires_power = 0 - var/sound/mysound = null - -/area/awaymission/beach/New() - ..() - var/sound/S = new/sound() - mysound = S - S.file = 'sound/ambience/shore.ogg' - S.repeat = 1 - S.wait = 0 - S.channel = 123 - S.volume = 100 - S.priority = 255 - S.status = SOUND_UPDATE - process() - -/area/awaymission/beach/Entered(atom/movable/Obj,atom/OldLoc) - if(ismob(Obj)) - if(Obj:client) - mysound.status = SOUND_UPDATE - Obj << mysound - return - -/area/awaymission/beach/Exited(atom/movable/Obj) - if(ismob(Obj)) - if(Obj:client) - mysound.status = SOUND_PAUSED | SOUND_UPDATE - Obj << mysound - -/area/awaymission/beach/proc/process() - //set background = 1 - - var/sound/S = null - var/sound_delay = 0 - if(prob(25)) - S = sound(file=pick('sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag3.ogg'), volume=100) - sound_delay = rand(0, 50) - - for(var/mob/living/carbon/human/H in src) - /* if(H.s_tone > -55) - H.s_tone-- - H.update_body()*/ - if(H.client) - mysound.status = SOUND_UPDATE - H << mysound - if(S) - spawn(sound_delay) - H << S - - spawn(60) .() - -///////////////////////////////////////////////////////////////////// -/* - Lists of areas to be used with is_type_in_list. - Used in gamemodes code at the moment. --rastaf0 -*/ - -// CENTCOM -var/list/centcom_areas = list ( - /area/centcom, - /area/shuttle/escape/centcom, - /area/shuttle/escape_pod1/centcom, - /area/shuttle/escape_pod2/centcom, - /area/shuttle/escape_pod3/centcom, - /area/shuttle/escape_pod5/centcom, - /area/shuttle/transport1/centcom, - /area/shuttle/administration/centcom, - /area/shuttle/specops/centcom, -) - -//SPACE STATION 13 -var/list/the_station_areas = list ( - /area/shuttle/arrival, - /area/shuttle/escape/station, - /area/shuttle/escape_pod1/station, - /area/shuttle/escape_pod2/station, - /area/shuttle/escape_pod3/station, - /area/shuttle/escape_pod5/station, - /area/shuttle/mining/station, - /area/shuttle/transport1/station, - // /area/shuttle/transport2/station, - /area/shuttle/prison/station, - /area/shuttle/administration/station, - /area/shuttle/specops/station, - /area/engineering/atmos, - /area/maintenance, - /area/hallway, - /area/bridge, - /area/crew_quarters, - /area/holodeck, - /area/mint, - /area/library, - /area/chapel, - /area/lawoffice, - /area/engineering, - /area/solar, - /area/assembly, - /area/teleporter, - /area/medical, - /area/security, - /area/supply, - /area/janitor, - /area/hydroponics, - /area/science, - /area/storage, - /area/tcomms, - /area/construction, - /area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0 - /area/ai_monitored/storage/secure, - /area/ai_monitored/storage/emergency, - /area/turret_protected/ai_upload, //do not try to simplify to "/area/turret_protected" --rastaf0 - /area/turret_protected/tcomms_control_room, - /area/turret_protected/ai_upload_foyer, - /area/turret_protected/ai, - /area/derelictparts, -) - - - - -/area/beach/ - name = "The metaclub's private beach" - icon_state = "null" - lighting_use_dynamic = 0 - requires_power = 0 - var/sound/mysound = null - -/* We have a jukebox now, fuck that -/area/beach/New() - ..() - var/sound/S = new/sound() - mysound = S - S.file = 'sound/ambience/shore.ogg' - S.repeat = 1 - S.wait = 0 - S.channel = 123 - S.volume = 100 - S.priority = 255 - S.status = SOUND_UPDATE - process() - -/area/beach/Entered(atom/movable/Obj,atom/OldLoc) - if(ismob(Obj)) - if(Obj:client) - mysound.status = SOUND_UPDATE - Obj << mysound - return - -//This only works when using Move() to exit the area -/area/beach/Exited(atom/movable/Obj) - if(ismob(Obj)) - if(Obj:client) - mysound.status = SOUND_PAUSED | SOUND_UPDATE - Obj << mysound - -/area/beach/proc/process() - //set background = 1 - - var/sound/S = null - var/sound_delay = 0 - if(prob(25)) - S = sound(file=pick('sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag3.ogg'), volume=50) - sound_delay = rand(0, 50) - - for(var/mob/living/carbon/human/H in src) -// if(H.s_tone > -55) //ugh...nice/novel idea but please no. -// H.s_tone-- -// H.update_body() - if(H.client) - mysound.status = SOUND_UPDATE - H << mysound - if(S) - spawn(sound_delay) - H << S - - spawn(60) .() - -*/ +/* + +### This file contains a list of all the areas in your station. Format is as follows: + +/area/CATEGORY/OR/DESCRIPTOR/NAME (you can make as many subdivisions as you want) + name = "NICE NAME" (not required but makes things really nice) + icon = "ICON FILENAME" (defaults to areas.dmi) + icon_state = "NAME OF ICON" (defaults to "unknown" (blank)) + requires_power = 0 (defaults to 1) + music = "music/music.ogg" (defaults to "music/music.ogg") + +NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0 + +*/ + +#define SUPER_JAMMED 2 + +/area + var/fire = null + var/atmos = 1 + var/atmosalm = 0 + var/poweralm = 1 + var/party = null + var/radalert = 0 + level = null + name = "Space" + icon = 'icons/turf/areas.dmi' + icon_state = "unknown" + layer = 10 + mouse_opacity = 0 + luminosity = 0 + var/lightswitch = 1 + + var/eject = null + + var/requires_power = 1 + var/always_unpowered = 0 //this gets overriden to 1 for space in area/New() + + var/power_equip = 1 + var/power_light = 1 + var/power_environ = 1 + var/music = null + var/used_equip = 0 + var/used_light = 0 + var/used_environ = 0 + var/static_equip + var/static_light = 0 + var/static_environ + + var/has_gravity = 1 + + var/no_air = null +// var/list/lights // list of all lights on this area + var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area + + // /vg/: Bitmap of subsystems asking for firedoors. + var/door_alerts=0 + + var/doors_down=0 + + // /vg/: No teleporting for you. 2 = SUPER JAMMED, inaccessible even to telecrystals. + var/jammed = 0 + + // /vg/: Prevents entities using incorporeal move from entering the area (ghosts, jaunting wizards/ninjas...) + var/anti_ethereal = 0 + + var/general_area = /area/station // the highest parent bellow /area, + var/general_area_name = "Station" + + +/*Adding a wizard area teleport list because motherfucking lag -- Urist*/ +/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ +var/list/teleportlocs = list() + +proc/process_teleport_locs() + for(var/area/AR in areas) + if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station)) continue + if(teleportlocs.Find(AR.name)) continue + var/turf/picked = safepick(get_area_turfs(AR.type)) + if (picked && picked.z == 1) + teleportlocs += AR.name + teleportlocs[AR.name] = AR + + sortTim(teleportlocs, /proc/cmp_text_asc) + +var/list/ghostteleportlocs = list() + +proc/process_ghost_teleport_locs() + for(var/area/AR in areas) + if(ghostteleportlocs.Find(AR.name)) continue + if(istype(AR, /area/turret_protected/aisat) || istype(AR, /area/derelict) || istype(AR, /area/tdome)) + ghostteleportlocs += AR.name + ghostteleportlocs[AR.name] = AR + var/turf/picked = safepick(get_area_turfs(AR.type)) + if (picked && (picked.z == 1 || picked.z == 5 || picked.z == 3)) + ghostteleportlocs += AR.name + ghostteleportlocs[AR.name] = AR + + sortTim(ghostteleportlocs, /proc/cmp_text_asc) + +var/global/list/adminbusteleportlocs = list() + +proc/process_adminbus_teleport_locs() + for(var/area/AR in areas) + if(adminbusteleportlocs.Find(AR.name)) continue + var/turf/picked = safepick(get_area_turfs(AR.type)) + if (picked) + adminbusteleportlocs += AR.name + adminbusteleportlocs[AR.name] = AR + + sortTim(adminbusteleportlocs, /proc/cmp_text_dsc) + + +/*-----------------------------------------------------------------------------*/ + +/area/station//TODO: make every area in the MAIN station inherit from this. + name = "Station" + +/area/station/custom //For blueprints! + power_equip = 0 + power_light = 0 + power_environ = 0 + always_unpowered = 0 + lighting_use_dynamic = 1 + +/area/engineering/ + +/area/turret_protected/ + +/area/arrival + requires_power = 0 + +/area/arrival/start + name = "\improper Arrival Area" + icon_state = "start" + +/area/admin + name = "\improper Admin room" + icon_state = "start" + +/area/no_ethereal + anti_ethereal = 1 + + + +//These are shuttle areas, they must contain two areas in a subgroup if you want to move a shuttle from one +//place to another. Look at escape shuttle for example. +//All shuttles show now be under shuttle since we have smooth-wall code. + +/area/shuttle + requires_power = 0 + lighting_use_dynamic = 1 //Lighting STILL disabled, even with the new bay engine, because lighting doesn't play nice with our shuttles, might just be our shuttle code, or the small changes in the lighting engine we have from bay. + //haha fuck you we dynamic lights now + +/area/shuttle/arrival + name = "\improper Arrival Shuttle" + +/area/shuttle/arrival/pre_game + icon_state = "shuttle2" + +/area/shuttle/arrival/station + icon_state = "shuttle" + +/area/shuttle/escape + name = "\improper Emergency Shuttle" + music = "music/escape.ogg" + +/area/shuttle/escape/station + name = "\improper Emergency Shuttle Station" + icon_state = "shuttle2" + +/area/shuttle/escape/centcom + name = "\improper Emergency Shuttle Centcom" + icon_state = "shuttle" + +/area/shuttle/escape_pod1 + name = "\improper Escape Pod One" + music = "music/escape.ogg" + +/area/shuttle/escape_pod1/station + icon_state = "shuttle2" + +/area/shuttle/escape_pod1/centcom + icon_state = "shuttle" + +/area/shuttle/escape_pod1/transit + icon_state = "shuttle" + +/area/shuttle/escape_pod2 + name = "\improper Escape Pod Two" + music = "music/escape.ogg" + +/area/shuttle/escape_pod2/station + icon_state = "shuttle2" + +/area/shuttle/escape_pod2/centcom + icon_state = "shuttle" + +/area/shuttle/escape_pod2/transit + icon_state = "shuttle" + +/area/shuttle/escape_pod3 + name = "\improper Escape Pod Three" + music = "music/escape.ogg" + +/area/shuttle/escape_pod3/station + icon_state = "shuttle2" + +/area/shuttle/escape_pod3/centcom + icon_state = "shuttle" + +/area/shuttle/escape_pod3/transit + icon_state = "shuttle" + +/area/shuttle/escape_pod5 //Pod 4 was lost to meteors + name = "\improper Escape Pod Five" + music = "music/escape.ogg" + +/area/shuttle/escape_pod5/station + icon_state = "shuttle2" + +/area/shuttle/escape_pod5/centcom + icon_state = "shuttle" + +/area/shuttle/escape_pod5/transit + icon_state = "shuttle" + +/area/shuttle/supply + name = "supply shuttle" + icon_state = "shuttle3" + +/area/shuttle/mining + name = "\improper Mining Shuttle" + music = "music/escape.ogg" + +/area/shuttle/mining/station + icon_state = "shuttle2" + +/area/shuttle/mining/outpost + icon_state = "shuttle" + +/area/shuttle/transport1/centcom + icon_state = "shuttle" + name = "\improper Transport Shuttle Centcom" + +/area/shuttle/transport1/station + icon_state = "shuttle" + name = "\improper Transport Shuttle" + +/area/shuttle/alien/base + icon_state = "shuttle" + name = "\improper Alien Shuttle Base" + requires_power = 1 + +/area/shuttle/alien/mine + icon_state = "shuttle" + name = "\improper Alien Shuttle Mine" + requires_power = 1 + +/area/shuttle/prison/ + name = "\improper Prison Shuttle" + +/area/shuttle/prison/station + icon_state = "shuttle" + +/area/shuttle/prison/prison + icon_state = "shuttle2" + +/area/shuttle/specops/centcom + name = "\improper Special Ops Shuttle" + icon_state = "shuttlered" + +/area/shuttle/specops/station + name = "\improper Special Ops Shuttle" + icon_state = "shuttlered2" + +/area/shuttle/syndicate_elite/mothership + name = "\improper Syndicate Elite Shuttle" + icon_state = "shuttlered" + +/area/shuttle/syndicate_elite/station + name = "\improper Syndicate Elite Shuttle" + icon_state = "shuttlered2" + +/area/shuttle/administration/centcom + name = "\improper Administration Shuttle Centcom" + icon_state = "shuttlered" + +/area/shuttle/administration/station + name = "\improper Administration Shuttle" + icon_state = "shuttlered2" + +/area/shuttle/thunderdome + name = "honk" + lighting_use_dynamic = 0 + +/area/shuttle/thunderdome/grnshuttle + name = "\improper Thunderdome GRN Shuttle" + icon_state = "green" + +/area/shuttle/thunderdome/grnshuttle/dome + name = "\improper GRN Shuttle" + icon_state = "shuttlegrn" + +/area/shuttle/thunderdome/grnshuttle/station + name = "\improper GRN Station" + icon_state = "shuttlegrn2" + +/area/shuttle/thunderdome/redshuttle + name = "\improper Thunderdome RED Shuttle" + icon_state = "red" + +/area/shuttle/thunderdome/redshuttle/dome + name = "\improper RED Shuttle" + icon_state = "shuttlered" + +/area/shuttle/thunderdome/redshuttle/station + name = "\improper RED Station" + icon_state = "shuttlered2" +// === Trying to remove these areas: + +/area/shuttle/research + name = "\improper Research Shuttle" + music = "music/escape.ogg" + +/area/shuttle/research/station + icon_state = "shuttle2" + +/area/shuttle/research/outpost + icon_state = "shuttle" + +/area/shuttle/vox/station + name = "\improper Vox Skipjack" + icon_state = "yellow" + requires_power = 0 + +/area/shuttle/salvage + name = "\improper Salvage Ship" + icon_state = "yellow" + requires_power = 0 + +/area/shuttle/salvage/start + icon_state = "yellow" + +/area/shuttle/salvage/arrivals + name = "\improper Space Station Auxiliary Docking" + icon_state = "yellow" + +/area/shuttle/salvage/derelict + name = "\improper Derelict Station" + icon_state = "yellow" + +/area/shuttle/salvage/djstation + name = "\improper Ruskie DJ Station" + icon_state = "yellow" + +/area/shuttle/salvage/north + name = "\improper North of the Station" + icon_state = "yellow" + +/area/shuttle/salvage/east + name = "\improper East of the Station" + icon_state = "yellow" + +/area/shuttle/salvage/south + name = "\improper South of the Station" + icon_state = "yellow" + +/area/shuttle/salvage/commssat + name = "\improper The Communications Satellite" + icon_state = "yellow" + +/area/shuttle/salvage/mining + name = "\improper South-West of the Mining Asteroid" + icon_state = "yellow" + +/area/shuttle/salvage/abandoned_ship + name = "\improper Abandoned Ship" + icon_state = "yellow" + +/area/shuttle/salvage/clown_asteroid + name = "\improper Clown Asteroid" + icon_state = "yellow" + +/area/shuttle/salvage/trading_post + name = "\improper Trading Post" + icon_state = "yellow" + +// Taxi Shuttle + +/area/shuttle/taxi_a + name = "Taxi A" + requires_power = 0 + +/area/shuttle/taxi_a/medcal_silicon_station + icon_state = "bluenew" + +/area/shuttle/taxi_a/engineering_cargo_station + icon_state = "bluenew" + +/area/shuttle/taxi_a/security_science_station + icon_state = "bluenew" + +/area/shuttle/taxi_a/abandoned_station + icon_state = "bluenew" + +// B + +/area/shuttle/taxi_b + name = "Taxi B" + requires_power = 0 + +/area/shuttle/taxi_b/medcal_silicon_station + icon_state = "dk_yellow" + +/area/shuttle/taxi_b/engineering_cargo_station + icon_state = "dk_yellow" + +/area/shuttle/taxi_b/security_science_station + icon_state = "dk_yellow" + +/area/shuttle/taxi_b/abandoned_station + icon_state = "dk_yellow" + +// End Taxi Shuttle + + + +/area/airtunnel1/ // referenced in airtunnel.dm:759 + +/area/dummy/ // Referenced in engine.dm:261 + +/area/start // will be unused once kurper gets his login interface patch done + name = "start area" + icon_state = "start" + requires_power = 0 + lighting_use_dynamic = 0 + has_gravity = 1 + +// === end remove + +/area/alien + name = "\improper Alien base" + icon_state = "yellow" + requires_power = 0 + +// CENTCOM + +/area/centcom + name = "\improper Centcom" + icon_state = "centcom" + requires_power = 0 + lighting_use_dynamic = 0 + +/area/centcom/control + name = "\improper Centcom Control" + +/area/centcom/evac + name = "\improper Centcom Emergency Shuttle" + +/area/centcom/suppy + name = "\improper Centcom Supply Shuttle" + +/area/centcom/ferry + name = "\improper Centcom Transport Shuttle" + +/area/centcom/shuttle + name = "\improper Centcom Administration Shuttle" + +/area/centcom/test + name = "\improper Centcom Testing Facility" + +/area/centcom/living + name = "\improper Centcom Living Quarters" + +/area/centcom/specops + name = "\improper Centcom Special Ops" + +/area/centcom/creed + name = "Creed's Office" + +/area/centcom/holding + name = "\improper Holding Facility" + +//SYNDICATES + +/area/syndicate_mothership + name = "\improper Syndicate Mothership" + icon_state = "syndie-ship" + requires_power = 0 + lighting_use_dynamic = 0 + +/area/syndicate_mothership/control + name = "\improper Syndicate Control Room" + icon_state = "syndie-control" + +/area/syndicate_mothership/elite_squad + name = "\improper Syndicate Elite Squad" + icon_state = "syndie-elite" + +//EXTRA + +/area/asteroid // -- TLE + name = "\improper Asteroid" + icon_state = "asteroid" + requires_power = 0 + +/area/asteroid/cave // -- TLE + name = "\improper Asteroid - Underground" + icon_state = "cave" + requires_power = 0 + +/area/asteroid/artifactroom + name = "\improper Asteroid - Artifact" + icon_state = "cave" + +/area/planet/clown + name = "\improper Clown Planet" + icon_state = "honk" + requires_power = 0 + +/area/asteroid/clown + name = "\improper Clown Roid" + icon_state = "honk" + requires_power = 0 + +/area/tdome + name = "\improper Thunderdome" + icon_state = "thunder" + requires_power = 0 + lighting_use_dynamic = 0 + +/area/tdome/tdome1 + name = "\improper Thunderdome (Team 1)" + icon_state = "green" + +/area/tdome/tdome2 + name = "\improper Thunderdome (Team 2)" + icon_state = "yellow" + +/area/tdome/tdomeadmin + name = "\improper Thunderdome (Admin.)" + icon_state = "purple" + +/area/tdome/tdomeobserve + name = "\improper Thunderdome (Observer.)" + icon_state = "purple" + +//ENEMY + +//names are used +/area/syndicate_station + name = "\improper Syndicate Shuttle" + icon_state = "yellow" + requires_power = 0 + lighting_use_dynamic = 1 + +/area/syndicate_station/start + icon_state = "yellow" + +/area/syndicate_station/southwest + name = "\improper south-west of SS13" + icon_state = "southwest" + +/area/syndicate_station/northwest + name = "\improper north-west of SS13" + icon_state = "northwest" + +/area/syndicate_station/northeast + name = "\improper north-east of SS13" + icon_state = "northeast" + +/area/syndicate_station/southeast + name = "\improper south-east of SS13" + icon_state = "southeast" + +/area/syndicate_station/north + name = "\improper north of SS13" + icon_state = "north" + +/area/syndicate_station/south + name = "\improper south of SS13" + icon_state = "south" + +/area/syndicate_station/commssat + name = "\improper south of the communication satellite" + icon_state = "south" + +/area/syndicate_station/mining + name = "\improper north east of the mining asteroid" + icon_state = "north" + +/area/wizard_station + name = "\improper Wizard's Den" + icon_state = "yellow" + requires_power = 0 + lighting_use_dynamic = 0 + +/area/vox_station/southwest_solars + name = "\improper aft port solars" + icon_state = "southwest" + requires_power = 0 + +/area/vox_station/northwest_solars + name = "\improper fore port solars" + icon_state = "northwest" + requires_power = 0 + +/area/vox_station/northeast_solars + name = "\improper fore starboard solars" + icon_state = "northeast" + requires_power = 0 + +/area/vox_station/southeast_solars + name = "\improper aft starboard solars" + icon_state = "southeast" + requires_power = 0 + +/area/vox_station/mining + name = "\improper nearby mining asteroid" + icon_state = "north" + requires_power = 0 + +//PRISON +/area/prison + name = "\improper Prison Station" + icon_state = "brig" + +/area/prison/arrival_airlock + name = "\improper Prison Station Airlock" + icon_state = "green" + requires_power = 0 + +/area/prison/control + name = "\improper Prison Security Checkpoint" + icon_state = "security" + +/area/prison/crew_quarters + name = "\improper Prison Security Quarters" + icon_state = "security" + +/area/prison/rec_room + name = "\improper Prison Rec Room" + icon_state = "green" + +/area/prison/closet + name = "\improper Prison Supply Closet" + icon_state = "dk_yellow" + +/area/prison/hallway/fore + name = "\improper Prison Fore Hallway" + icon_state = "yellow" + +/area/prison/hallway/aft + name = "\improper Prison Aft Hallway" + icon_state = "yellow" + +/area/prison/hallway/port + name = "\improper Prison Port Hallway" + icon_state = "yellow" + +/area/prison/hallway/starboard + name = "\improper Prison Starboard Hallway" + icon_state = "yellow" + +/area/prison/morgue + name = "\improper Prison Morgue" + icon_state = "morgue" + +/area/prison/medical_research + name = "\improper Prison Genetic Research" + icon_state = "medresearch" + +/area/prison/medical + name = "\improper Prison Medbay" + icon_state = "medbay" + +/area/prison/solar + name = "\improper Prison Solar Array" + icon_state = "storage" + requires_power = 0 + +/area/prison/podbay + name = "\improper Prison Podbay" + icon_state = "dk_yellow" + +/area/prison/solar_control + name = "\improper Prison Solar Array Control" + icon_state = "dk_yellow" + +/area/prison/solitary + name = "Solitary Confinement" + icon_state = "brig" + +/area/prison/cell_block/A + name = "Prison Cell Block A" + icon_state = "brig" + +/area/prison/cell_block/B + name = "Prison Cell Block B" + icon_state = "brig" + +/area/prison/cell_block/C + name = "Prison Cell Block C" + icon_state = "brig" + +//STATION13 + +//Maintenance + +/area/maintenance/fpmaint + name = "Fore Port Maintenance" + icon_state = "fpmaint" + +/area/maintenance/fpmaint2 + name = "Fore Port Maintenance" + icon_state = "fpmaint" + +/area/maintenance/fpmaint3 + name = "Fore Port Maintenance" + icon_state = "fpmaint" + +/area/maintenance/fsmaint + name = "Fore Starboard Maintenance" + icon_state = "fsmaint" + +/area/maintenance/fsmaint2 + name = "Fore Starboard Maintenance" + icon_state = "fsmaint" + +/area/maintenance/asmaint + name = "Aft Starboard Maintenance" + icon_state = "asmaint" + +/area/maintenance/asmaint2 + name = "Aft Starboard Maintenance" + icon_state = "asmaint" + +/area/maintenance/asmaint3 + name = "Xenobiology Maintenance" + icon_state = "asmaint" + +/area/maintenance/apmaint + name = "Aft Port Maintenance" + icon_state = "apmaint" + +/area/maintenance/maintcentral + name = "Central Maintenance" + icon_state = "maintcentral" + +/area/maintenance/fore + name = "Fore Maintenance" + icon_state = "fmaint" + +/area/maintenance/starboard + name = "Starboard Maintenance" + icon_state = "smaint" + +/area/maintenance/port + name = "Port Maintenance" + icon_state = "pmaint" + +/area/maintenance/aft + name = "Aft Maintenance" + icon_state = "amaint" + +/area/maintenance/atmos + name = "Atmospherics" + icon_state = "green" + +/area/maintenance/incinerator + name = "\improper Incinerator" + icon_state = "disposal" + +/area/maintenance/disposal + name = "Recycling" + icon_state = "disposal" + +/area/maintenance/secdisposal + name = "Security Disposals" + icon_state = "secdisp" + +/area/maintenance/auxcharge + name = "Auxiliary Cyborg Recharge" + icon_state = "auxcharge" + +/area/maintenance/ghettobar + name = "Ghetto Bar" + icon_state = "ghettobar" + +//Hallway + +/area/hallway/primary/fore + name = "\improper Fore Primary Hallway" + icon_state = "hallF" + +/area/hallway/primary/starboard + name = "\improper Starboard Primary Hallway" + icon_state = "hallS" + +/area/hallway/primary/aft + name = "\improper Aft Primary Hallway" + icon_state = "hallA" + +/area/hallway/primary/port + name = "\improper Port Primary Hallway" + icon_state = "hallP" + +/area/hallway/primary/central + name = "\improper Central Primary Hallway" + icon_state = "hallC" + +/area/hallway/secondary/exit + name = "\improper Escape Shuttle Hallway" + icon_state = "escape" + +/area/hallway/secondary/construction + name = "\improper Construction Area" + icon_state = "construction" + +/area/hallway/secondary/entry + name = "\improper Arrival Shuttle Hallway" + icon_state = "entry" + +//Command + +/area/bridge + name = "\improper Bridge" + icon_state = "bridge" + music = "signal" + jammed=1 + +/area/bridge/meeting_room + name = "\improper Heads of Staff Meeting Room" + icon_state = "bridge" + music = null + jammed=0 + +/area/crew_quarters/captain + name = "\improper Captain's Office" + icon_state = "captain" + jammed=1 + +/area/crew_quarters/heads +/area/crew_quarters/heads/hop + name = "\improper Head of Personnel's Quarters" + icon_state = "head_quarters" + jammed=1 + +/area/crew_quarters/heads/rd + name = "\improper Research Director's Quarters" + icon_state = "head_quarters" + jammed=1 + +/area/crew_quarters/heads/ce + name = "\improper Chief Engineer's Quarters" + icon_state = "head_quarters" + jammed=1 + +/area/crew_quarters/heads/hos + name = "\improper Head of Security's Quarters" + icon_state = "head_quarters" + jammed=1 + +/area/crew_quarters/heads/cmo + name = "\improper Chief Medical Officer's Quarters" + icon_state = "head_quarters" + jammed=1 + +/area/crew_quarters/courtroom + name = "\improper Courtroom" + icon_state = "courtroom" + +/area/crew_quarters/hop + name = "\improper Head of Personnel's Office" + icon_state = "head_quarters" + jammed=1 + +/area/mint + name = "\improper Mint" + icon_state = "green" + +/area/comms + name = "\improper Communications Relay" + icon_state = "tcomsatcham" + +/area/server + name = "\improper Messaging Server Room" + icon_state = "server" + +//Crew + +/area/crew_quarters + name = "\improper Dormitories" + icon_state = "Sleep" + +/area/crew_quarters/toilet + name = "\improper Dormitory Toilets" + icon_state = "toilet" + +/area/crew_quarters/sleep + name = "\improper Dormitories" + icon_state = "Sleep" + +/area/crew_quarters/sleep_male + name = "\improper Male Dorm" + icon_state = "Sleep" + +/area/crew_quarters/sleep_male/toilet_male + name = "\improper Male Toilets" + icon_state = "toilet" + +/area/crew_quarters/sleep_female + name = "\improper Female Dorm" + icon_state = "Sleep" + +/area/crew_quarters/sleep_female/toilet_female + name = "\improper Female Toilets" + icon_state = "toilet" + +/area/crew_quarters/locker + name = "\improper Locker Room" + icon_state = "locker" + +/area/crew_quarters/locker/locker_toilet + name = "\improper Locker Toilets" + icon_state = "toilet" + +/area/crew_quarters/fitness + name = "\improper Fitness Room" + icon_state = "fitness" + +/area/crew_quarters/cafeteria + name = "\improper Cafeteria" + icon_state = "cafeteria" + +/area/crew_quarters/kitchen + name = "\improper Kitchen" + icon_state = "kitchen" + +/area/crew_quarters/bar + name = "\improper Bar" + icon_state = "bar" + +/area/crew_quarters/theatre + name = "\improper Theatre" + icon_state = "Theatre" + +/area/library + name = "\improper Library" + icon_state = "library" + +/area/chapel/main + name = "\improper Chapel" + icon_state = "chapel" + +/area/chapel/office + name = "\improper Chapel Office" + icon_state = "chapeloffice" + +/area/lawoffice + name = "\improper Law Office" + icon_state = "law" + +/area/crew_quarters/casino + name = "Casino" + icon_state = "casino" + + + + + + + +/area/holodeck + name = "\improper Holodeck" + icon_state = "Holodeck" + lighting_use_dynamic = 0 + +/area/holodeck/alphadeck + name = "\improper Holodeck Alpha" + + +/area/holodeck/source_plating + name = "\improper Holodeck - Off" + icon_state = "Holodeck" + jammed=SUPER_JAMMED + +/area/holodeck/source_emptycourt + name = "\improper Holodeck - Empty Court" + jammed=SUPER_JAMMED + +/area/holodeck/source_boxingcourt + name = "\improper Holodeck - Boxing Court" + jammed=SUPER_JAMMED + +/area/holodeck/source_basketball + name = "\improper Holodeck - Basketball Court" + jammed=SUPER_JAMMED + +/area/holodeck/source_thunderdomecourt + name = "\improper Holodeck - Thunderdome Court" + jammed=SUPER_JAMMED + +/area/holodeck/source_beach + name = "\improper Holodeck - Beach" + icon_state = "Holodeck" // Lazy. + jammed=SUPER_JAMMED + +/area/holodeck/source_burntest + name = "\improper Holodeck - Atmospheric Burn Test" + jammed=SUPER_JAMMED + +/area/holodeck/source_wildlife + name = "\improper Holodeck - Wildlife Simulation" + jammed=SUPER_JAMMED + +/area/holodeck/source_meetinghall + name = "\improper Holodeck - Meeting Hall" + jammed=SUPER_JAMMED + +/area/holodeck/source_theatre + name = "\improper Holodeck - Theatre" + jammed=SUPER_JAMMED + +/area/holodeck/source_picnicarea + name = "\improper Holodeck - Picnic Area" + jammed=SUPER_JAMMED + +/area/holodeck/source_snowfield + name = "\improper Holodeck - Snow Field" + jammed=SUPER_JAMMED + +/area/holodeck/source_desert + name = "\improper Holodeck - Desert" + jammed=SUPER_JAMMED + +/area/holodeck/source_space + name = "\improper Holodeck - Space" + jammed=SUPER_JAMMED + + + + + + + + + + + +//Engineering + +/area/engineering + +/area/engineering/engine_smes + name = "\improper Engineering SMES" + icon_state = "engine_smes" + requires_power = 0//This area only covers the batteries and they deal with their own power + +/area/engineering/engine + name = "Engineering" + icon_state = "engine" + +/area/engineering/engine_storage + name = "Engineering Secure Storage" + icon_state = "engine_storage" + +/area/engineering/break_room + name = "\improper Engineering Foyer" + icon_state = "engine_lobby" + +/area/engineering/ce + name = "\improper Chief Engineer's Office" + icon_state = "head_quarters" + jammed=1 + +/area/engineering/burn_chamber + name = "Burn Chamber" + icon_state = "thermo_engine" + +/area/engineering/atmos + name = "Atmospherics" + icon_state = "atmos" + +/area/engineering/atmos_control + name = "Atmospherics Monitoring" + icon_state = "atmos_monitor" + +/area/engineering/supermatter_room + name = "Supermatter Room" + icon_state = "supermatter" + +/area/engineering/antimatter_room + name = "Antimatter Engine Room" + icon_state = "antimatter" + +/area/engineering/engineering_auxiliary + name = "Auxiliary Engineering" + icon_state = "engiaux" + +/area/engineering/mechanics + name = "Mechanics" + icon_state = "mechanics" + + +//Solars + +/area/solar + requires_power = 0 + lighting_use_dynamic = 0 + +/area/solar/fport + name = "\improper Fore Port Solar Array" + icon_state = "panelsA" + +/area/solar/fstarboard + name = "\improper Fore Starboard Solar Array" + icon_state = "panelsA" + +/area/solar/fore + name = "\improper Fore Solar Array" + icon_state = "yellow" + +/area/solar/aft + name = "\improper Aft Solar Array" + icon_state = "aft" + +/area/solar/astarboard + name = "\improper Aft Starboard Solar Array" + icon_state = "panelsS" + +/area/solar/auxstarboard + name = "\improper Auxillary Starboard Solar Array" + icon_state = "panelsS" + +/area/solar/aport + name = "\improper Aft Port Solar Array" + icon_state = "panelsP" + +/area/solar/auxport + name = "\improper Auxillary Port Solar Array" + icon_state = "panelsP" + +/area/maintenance/auxsolarstarboard + name = "Auxillary Starboard Solar Maintenance" + icon_state = "SolarcontrolS" + +/area/maintenance/auxsolarport + name = "Auxillary Port Solar Maintenance" + icon_state = "SolarcontrolP" + +/area/maintenance/fportsolar + name = "Fore Port Solar Maintenance" + icon_state = "SolarcontrolA" + +/area/maintenance/astarboardsolar + name = "Aft Starboard Solar Maintenance" + icon_state = "SolarcontrolS" + +/area/maintenance/aportsolar + name = "Aft Port Solar Maintenance" + icon_state = "SolarcontrolP" + +/area/maintenance/fstarboardsolar + name = "Fore Starboard Solar Maintenance" + icon_state = "SolarcontrolA" + +/area/maintenance/virology_maint + name = "Virology Maintenance" + icon_state = "asmaint" + +/area/science/showroom + name = "\improper Robotics Showroom" + icon_state = "showroom" + +/area/assembly/assembly_line //Derelict Assembly Line + name = "\improper Assembly Line" + icon_state = "ass_line" + power_equip = 0 + power_light = 0 + power_environ = 0 + +//Teleporter + +/area/teleporter + name = "\improper Teleporter" + icon_state = "teleporter" + music = "signal" + jammed=1 + +/area/gateway + name = "\improper Gateway" + icon_state = "teleporter" + music = "signal" + +/area/AIsattele + name = "\improper AI Satellite Teleporter Room" + icon_state = "teleporter" + music = "signal" + +//MedBay + +/area/medical/medbay + name = "Medbay" + icon_state = "medbay" + music = 'sound/ambience/signal.ogg' + +//Medbay is a large area, these additional areas help level out APC load. +/area/medical/medbay2 + name = "Medbay" + icon_state = "medbay2" + music = 'sound/ambience/signal.ogg' + +/area/medical/surgery_ghetto + name = "Ghetto Surgery" + icon_state = "medbay_ghetto" + music = 'sound/ambience/signal.ogg' + +/area/medical/medbay3 + name = "Medbay" + icon_state = "medbay3" + music = 'sound/ambience/signal.ogg' + +/area/medical/break_room + name = "Medbay Break Room" + icon_state = "medbay_break" + music = 'sound/ambience/signal.ogg' + +/area/medical/patients_rooms + name = "\improper Patient's Rooms" + icon_state = "patients" + +/area/medical/patient_room1 + name = "\improper Patient Room 1" + icon_state = "patients" + +/area/medical/patient_room2 + name = "\improper Patient Room 2" + icon_state = "patients" + +/area/medical/cmo + name = "\improper Chief Medical Officer's Office" + icon_state = "CMO" + jammed=1 + +/area/medical/virology + name = "Virology" + icon_state = "virology" + +/area/medical/virology_break + name = "Virology Break Room" + icon_state = "virology" + +/area/medical/morgue + name = "\improper Morgue" + icon_state = "morgue" + +/area/medical/chemistry + name = "Chemistry" + icon_state = "chem" + +/area/medical/surgery + name = "Surgery" + icon_state = "surgery" + +/area/medical/cryo + name = "Cryogenics" + icon_state = "cryo" + +/area/medical/storage + name = "\improper Medbay Storage" + icon_state = "med_storage" + +/area/medical/exam_room + name = "\improper Exam Room" + icon_state = "exam_room" + +/area/medical/genetics + name = "Genetics Lab" + icon_state = "genetics" + +/area/medical/genetics_cloning + name = "Cloning Lab" + icon_state = "cloning" + +/area/medical/sleeper + name = "Medbay Treatment Center" + icon_state = "exam_room" + +/area/medical/paramedics + name = "\improper Paramedic Station" + icon_state = "paramedics" + +//Security + +/area/security/main + name = "\improper Security Office" + icon_state = "security" + +/area/security/lobby + name = "\improper Security Lobby" + icon_state = "sec_lobby" + +/area/security/brig + name = "\improper Brig" + icon_state = "brig" + +/area/security/prison + name = "\improper Prison Wing" + icon_state = "sec_prison" + +/area/security/perma + name = "\improper Permanent Confinement" + icon_state = "sec_perma" + +/area/security/gas_chamber + name = "\improper Execution Chamber" + icon_state = "bar" // Because it's all parties from here on. + jammed=1 + +/area/security/medical + name = "\improper Brig Medbay" + icon_state = "sec_medbay" + +/area/security/toilet + name = "\improper Brig Toilets" + icon_state = "toilet" + +/area/security/rec_room + name = "\improper Brig Recording Room" + icon_state = "rec" + +/area/security/evidence + name = "\improper Evidence Storage" + icon_state = "interrog" + +/area/security/interrogation + name = "\improper Interrogation Room" + icon_state = "interrog" + +/area/security/processing + name = "\improper Prisoner Education Chamber" + icon_state = "interrog" + +/obj/item/weapon/paper/Gaschamber + name = "paper - 'Gas Chambers for Idiots'" + info = {"

      Gas Chambers for Idiots

      +

      So here you are, with a fancy, new gas chamber thanks to cheap MoMMI labor. Now you've got a guy you need to die and have no idea what to do.

      +
        +
      1. First, use the computer in the witnessing room to shut off the scrubbers: Set Environmental Mode, Off.
      2. +
      3. Run down to the door for the room south of the witnessing room. You'll see a bunch of N2O or CO2 tanks.
      4. +
      5. Select the tank you want and drag it onto the connector. N2O (same shit used in anesthesia tanks in surgery) makes you go sleepy and kills in high enough doses, while CO2 makes people fall over comically and eventually die. CO2 is best because it's easier to tell when Mr. Revpants is dead, and because the room is configured for CO2 executions..
      6. +
      7. Make sure everyone you don't want dead is out of the chamber and the door is closed.
      8. +
      9. Wrench the tank in and go watch the fun from witnessing.
      10. +
      11. Once he's dead, set environmentals to filtering (or Cycle, if you're an idiot and used N2O).
      12. +
      13. Run back down to gas control and unwrench the tank.
      14. +
      15. Drag the dead bastard out once the computer says it's safe to enter.
      16. +
      "} + +/area/security/warden + name = "\improper Warden" + icon_state = "Warden" + jammed=1 + +/area/security/armory + name = "\improper Secure Armory" + icon_state = "Armory" + jammed=1 + +/area/security/hos + name = "\improper Head of Security's Office" + icon_state = "sec_hos" + jammed=1 + +/area/security/detectives_office + name = "\improper Detective's Office" + icon_state = "detective" + +/area/security/range + name = "\improper Firing Range" + icon_state = "firingrange" + +/* + New() + ..() + + spawn(10) //let objects set up first + for(var/turf/turfToGrayscale in src) + if(turfToGrayscale.icon) + var/icon/newIcon = icon(turfToGrayscale.icon) + newIcon.GrayScale() + turfToGrayscale.icon = newIcon + for(var/obj/objectToGrayscale in turfToGrayscale) //1 level deep, means tables, apcs, locker, etc, but not locker contents + if(objectToGrayscale.icon) + var/icon/newIcon = icon(objectToGrayscale.icon) + newIcon.GrayScale() + objectToGrayscale.icon = newIcon +*/ + +/area/security/checkpoint + name = "\improper Security Checkpoint" + icon_state = "checkpoint1" + +/area/security/checkpoint2 + name = "\improper Security Checkpoint" + icon_state = "security" + +/area/security/checkpoint/supply + name = "Security Post - Cargo Bay" + icon_state = "checkpoint1" + +/area/security/checkpoint/engineering + name = "Security Post - Engineering" + icon_state = "checkpoint1" + +/area/security/checkpoint/medical + name = "Security Post - Medbay" + icon_state = "checkpoint1" + +/area/security/checkpoint/science + name = "Security Post - Science" + icon_state = "checkpoint1" + +/area/security/vacantoffice + name = "\improper Vacant Office" + icon_state = "security" + +/area/security/vacantoffice2 + name = "\improper Vacant Office" + icon_state = "security" + +/area/supply + name = "\improper Quartermasters" + icon_state = "quart" + +///////////WORK IN PROGRESS////////// + +/area/supply/sorting + name = "\improper Delivery Office" + icon_state = "cargo_delivery" + +////////////WORK IN PROGRESS////////// + +/area/supply/lobby + name ="\improper Cargo Lobby" + icon_state = "cargo_lobby" + +/area/supply/office + name = "\improper Cargo Office" + icon_state = "cargo_office" + +/area/supply/storage + name = "\improper Cargo Bay" + icon_state = "cargo_bay" + +/area/supply/qm + name = "\improper Quartermaster's Office" + icon_state = "cargo_quart" + jammed=1 + +/area/supply/miningdock + name = "\improper Mining Dock" + icon_state = "mining" + +/area/supply/miningstorage + name = "\improper Mining Storage" + icon_state = "green" + +/area/supply/miningdelivery + name = "\improper Mining Delivery" + icon_state = "mining_delivery" + +/area/supply/mechbay + name = "\improper Mech Bay" + icon_state = "yellow" + +/area/janitor/ + name = "\improper Custodial Closet" + icon_state = "janitor" + +/area/janitor2/ + name = "\improper Custodial Closet" + icon_state = "janitor" + +/area/hydroponics + name = "Hydroponics" + icon_state = "hydro" + +//Toxins + +/area/science/lab + name = "\improper Research and Development" + icon_state = "toxlab" + +/area/science/hallway + name = "\improper Research Division" + icon_state = "tox_hall" + +/area/science/rd + name = "\improper Research Director's Office" + icon_state = "head_quarters" + jammed=1 + +/area/science/supermatter + name = "\improper Supermatter Lab" + icon_state = "toxlab" + +/area/science/xenobiology + name = "\improper Xenobiology Lab" + icon_state = "xenobio" + +/area/science/xenobiology/specimen_1 + name = "\improper Xenobiology Specimen Cage 1" + icon_state = "xenocell1" + +/area/science/xenobiology/specimen_2 + name = "\improper Xenobiology Specimen Cage 2" + icon_state = "xenocell2" + +/area/science/xenobiology/specimen_3 + name = "\improper Xenobiology Specimen Cage 3" + icon_state = "xenocell3" + +/area/science/xenobiology/specimen_4 + name = "\improper Xenobiology Specimen Cage 4" + icon_state = "xenocell4" + +/area/science/xenobiology/specimen_5 + name = "\improper Xenobiology Specimen Cage 5" + icon_state = "xenocell5" + +/area/science/xenobiology/specimen_6 + name = "\improper Xenobiology Specimen Cage 6" + icon_state = "xenocell6" + +/area/science/robotics + name = "\improper Robotics Lab" + icon_state = "ass_line" + +/area/science/chargebay + name = "\improper Mech Bay" + icon_state = "mechbay" + +/area/science/storage + name = "\improper Toxins Storage" + icon_state = "toxstorage" + +/area/science/test_area + name = "\improper Toxins Test Area" + icon_state = "toxtest" + +/area/science/shuttlebay + name = "\improper Research Shuttle Bay" + icon_state = "toxshuttle" + +/area/science/mixing + name = "\improper Toxins Mixing Room" + icon_state = "toxmix" + +/area/science/telescience + name = "\improper Telescience" + icon_state = "toxmisc" + +/area/science/podbay + name = "\improper Pod Bay" + icon_state = "pod" + +/area/science/server + name = "\improper Server Room" + icon_state = "server" + jammed=1 + +//Storage + +/area/storage/tools + name = "Auxiliary Tool Storage" + icon_state = "storage" + +/area/storage/primary + name = "Primary Tool Storage" + icon_state = "primarystorage" + +/area/storage/autolathe + name = "Autolathe Storage" + icon_state = "storage" + +/area/storage/art + name = "Art Supply Storage" + icon_state = "storage" + +/area/storage/auxillary + name = "Auxillary Storage" + icon_state = "auxstorage" + +/area/storage/eva + name = "EVA Storage" + icon_state = "eva" + jammed=1 + +/area/storage/secure + name = "Secure Storage" + icon_state = "storage" + jammed=1 + +/area/storage/nuke_storage + name = "\improper Vault" + icon_state = "nuke_storage" + +/area/storage/emergency + name = "Starboard Emergency Storage" + icon_state = "emergencystorage" + +/area/storage/emergency2 + name = "Port Emergency Storage" + icon_state = "emergencystorage" + +/area/storage/tech + name = "Technical Storage" + icon_state = "auxstorage" + jammed=1 + +/area/storage/testroom + requires_power = 0 + name = "\improper Test Room" + icon_state = "storage" + +//DJSTATION + +/area/djstation + name = "\improper Ruskie DJ Station" + icon_state = "DJ" + +/area/djstation/solars + name = "\improper DJ Station Solars" + icon_state = "DJ" + +//DERELICT + +/area/derelict + name = "\improper Derelict Station" + icon_state = "storage" + + general_area = /area/derelict + general_area_name = "Derelict Station" + +/area/derelict/hallway/primary + name = "\improper Derelict Primary Hallway" + icon_state = "hallP" + +/area/derelict/hallway/secondary + name = "\improper Derelict Secondary Hallway" + icon_state = "hallS" + +/area/derelict/arrival + name = "\improper Derelict Arrival Centre" + icon_state = "yellow" + +/area/derelict/storage/equipment + name = "Derelict Equipment Storage" + +/area/derelict/storage/storage_access + name = "Derelict Storage Access" + +/area/derelict/storage/engine_storage + name = "Derelict Engine Storage" + icon_state = "green" + +/area/derelict/bridge + name = "\improper Derelict Control Room" + icon_state = "bridge" + +/area/derelict/secret + name = "\improper Derelict Secret Room" + icon_state = "library" + +/area/derelict/bridge/access + name = "Derelict Control Room Access" + icon_state = "auxstorage" + +/area/derelict/bridge/ai_upload + name = "\improper Derelict Computer Core" + icon_state = "ai" + +/area/derelict/solar_control + name = "\improper Derelict Solar Control" + icon_state = "engine" + +/area/derelict/atmos + name = "\improper Derelict Atmospherics" + icon_state = "atmos" + +/area/derelict/research + name = "\improper Derelict Research" + icon_state = "toxins" + +/area/derelict/crew_quarters + name = "\improper Derelict Crew Quarters" + icon_state = "fitness" + +/area/derelict/medical + name = "Derelict Medbay" + icon_state = "medbay" + +/area/derelict/medical/morgue + name = "\improper Derelict Morgue" + icon_state = "morgue" + +/area/derelict/medical/chapel + name = "\improper Derelict Chapel" + icon_state = "chapel" + +/area/derelict/teleporter + name = "\improper Derelict Teleporter" + icon_state = "teleporter" + +/area/derelict/eva + name = "Derelict EVA Storage" + icon_state = "eva" + +/area/derelict/ship + name = "\improper Abandoned Ship" + icon_state = "yellow" + +/area/solar/derelict_starboard + name = "\improper Derelict Starboard Solar Array" + icon_state = "panelsS" + +/area/solar/derelict_aft + name = "\improper Derelict Aft Solar Array" + icon_state = "aft" + +/area/derelict/singularity_engine + name = "\improper Derelict Singularity Engine" + icon_state = "engine" + +/area/derelict/research + name = "\improper Derelict Research" + icon_state = "toxmisc" + +//Construction + +/area/construction + name = "\improper Construction Area" + icon_state = "yellow" + +/area/construction/mommi_nest + name = "\improper MoMMI Nest" + icon_state = "yellow" + +/area/construction/supplyshuttle + name = "\improper Supply Shuttle" + icon_state = "yellow" + +/area/construction/quarters + name = "\improper Engineer's Quarters" + icon_state = "yellow" + +/area/construction/qmaint + name = "Maintenance" + icon_state = "yellow" + +/area/construction/hallway + name = "\improper Hallway" + icon_state = "yellow" + +/area/construction/solars + name = "\improper Solar Panels" + icon_state = "yellow" + +/area/construction/solarscontrol + name = "\improper Solar Panel Control" + icon_state = "yellow" + +/area/construction/Storage + name = "Construction Site Storage" + icon_state = "yellow" + +//AI + +/area/ai_monitored/storage/eva + name = "EVA Storage" + icon_state = "eva" + jammed=1 + +/area/ai_monitored/storage/secure + name = "Secure Storage" + icon_state = "storage" + +/area/ai_monitored/storage/emergency + name = "Emergency Storage" + icon_state = "storage" + +/area/turret_protected/ai_upload + name = "\improper AI Upload Chamber" + icon_state = "ai_upload" + jammed=1 + +/area/turret_protected/ai_upload_foyer + name = "AI Upload Access" + icon_state = "ai_foyer" + +/area/turret_protected/ai + name = "\improper AI Chamber" + icon_state = "ai_chamber" + jammed=1 + +/area/turret_protected/aisat + name = "\improper AI Satellite" + icon_state = "ai" + +/area/turret_protected/aisat_interior + name = "\improper AI Satellite" + icon_state = "ai" + +/area/turret_protected/AIsatextFP + name = "\improper AI Sat Ext" + icon_state = "storage" + lighting_use_dynamic = 0 + +/area/turret_protected/AIsatextFS + name = "\improper AI Sat Ext" + icon_state = "storage" + lighting_use_dynamic = 0 + +/area/turret_protected/AIsatextAS + name = "\improper AI Sat Ext" + icon_state = "storage" + lighting_use_dynamic = 0 + +/area/turret_protected/AIsatextAP + name = "\improper AI Sat Ext" + icon_state = "storage" + lighting_use_dynamic = 0 + +/area/turret_protected/NewAIMain + name = "\improper AI Main New" + icon_state = "storage" + + + +//Misc + + + +/area/wreck/ai + name = "\improper AI Chamber" + icon_state = "ai" + +/area/wreck/main + name = "\improper Wreck" + icon_state = "storage" + +/area/wreck/engineering + name = "\improper Power Room" + icon_state = "engine" + +/area/wreck/bridge + name = "\improper Bridge" + icon_state = "bridge" + +/area/generic + name = "Unknown" + icon_state = "storage" + + +////////////////////////////// +// VOX TRADING POST +////////////////////////////// + +/area/vox_trading_post + name = "\improper Vox Trade Outpost" + icon_state = "yellow" + + general_area = /area/vox_trading_post + general_area_name = "Vox Trade Outpost" + +/area/vox_trading_post/trading_floor + name = "\improper Vox Trading Floor" + icon_state = "yellow" + +/area/vox_trading_post/trade_processing + name = "\improper Vox Trade Processing" + icon_state = "green" + +/area/vox_trading_post/armory + name = "\improper Vox Armory" + icon_state = "armory" + +/area/vox_trading_post/gardens + name = "\improper Vox Botanical Gardens" + icon_state = "hydro" + +/area/vox_trading_post/atmos + name = "\improper Vox Atmospherics" + icon_state = "atmos" + +/area/vox_trading_post/eva + name = "\improper Vox EVA" + icon_state = "eva" + +/area/vox_trading_post/storage_1 + name = "\improper Vox Storage Room" + icon_state = "storage" + +/area/vox_trading_post/vault + name = "\improper Vox Vault" + icon_state = "primarystorage" + +/area/vox_trading_post/hallway + name = "\improper Vox Hallways" + icon_state = "hallP" + + + +// Telecommunications Satellite +/area/tcommsat + name = "Telecommunications Satellite" + + general_area = /area/tcommsat + general_area_name = "Telecommunications Satellite" + +/area/tcommsat/entrance + name = "\improper Satellite Teleporter" + icon_state = "tcomsatentrance" + +/area/tcommsat/chamber + name = "\improper Telecoms Central Compartment" + icon_state = "tcomsatcham" + +/area/tcomms/chamber + name = "\improper Telecoms Chamber" + icon_state = "ai" + +/area/tcomms/storage + name = "\improper Telecoms Storage" + icon_state = "primarystorage" + +/area/turret_protected/tcomms_control_room + name = "\improper Telecomms Control Room" + icon_state = "tcomsatcomp" + jammed=1 + +/area/turret_protected/tcomsat + name = "\improper Satellite Entrance" + icon_state = "tcomsatlob" + +/area/turret_protected/tcomfoyer + name = "\improper Telecoms Foyer" + icon_state = "tcomsatentrance" + +/area/turret_protected/tcomwest + name = "\improper Telecommunications Satellite West Wing" + icon_state = "tcomsatwest" + +/area/turret_protected/tcomeast + name = "\improper Telecommunications Satellite East Wing" + icon_state = "tcomsateast" + +/area/tcommsat/computer + name = "\improper Satellite Control Room" + icon_state = "tcomsatcomp" + +/area/tcommsat/lounge + name = "\improper Satellite Lounge" + icon_state = "tcomsatlounge" + +/area/turret_protected/goonroom + name = "\improper Goonecode Containment" + icon_state = "ai_upload" + jammed=2 + anti_ethereal=1 + + + +// Away Missions +/area/awaymission + name = "\improper Strange Location" + icon_state = "away" + +/area/awaymission/example + name = "\improper Strange Station" + icon_state = "away" + +/area/awaymission/wwmines + name = "\improper Wild West Mines" + icon_state = "away1" + requires_power = 0 + +/area/awaymission/wwgov + name = "\improper Wild West Mansion" + icon_state = "away2" + requires_power = 0 + +/area/awaymission/wwrefine + name = "\improper Wild West Refinery" + icon_state = "away3" + requires_power = 0 + +/area/awaymission/wwvault + name = "\improper Wild West Vault" + icon_state = "away3" + +/area/awaymission/wwvaultdoors + name = "\improper Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power + icon_state = "away2" + requires_power = 0 + +/area/awaymission/desert + name = "Mars" + icon_state = "away" + +/area/awaymission/BMPship1 + name = "\improper Aft Block" + icon_state = "away1" + +/area/awaymission/BMPship2 + name = "\improper Midship Block" + icon_state = "away2" + +/area/awaymission/BMPship3 + name = "\improper Fore Block" + icon_state = "away3" + +/area/awaymission/spacebattle + name = "\improper Space Battle" + icon_state = "away" + requires_power = 0 + +/area/awaymission/spacebattle/cruiser + name = "\improper Nanotrasen Cruiser" + +/area/awaymission/spacebattle/syndicate1 + name = "\improper Syndicate Assault Ship 1" + +/area/awaymission/spacebattle/syndicate2 + name = "\improper Syndicate Assault Ship 2" + +/area/awaymission/spacebattle/syndicate3 + name = "\improper Syndicate Assault Ship 3" + +/area/awaymission/spacebattle/syndicate4 + name = "\improper Syndicate War Sphere 1" + +/area/awaymission/spacebattle/syndicate5 + name = "\improper Syndicate War Sphere 2" + +/area/awaymission/spacebattle/syndicate6 + name = "\improper Syndicate War Sphere 3" + +/area/awaymission/spacebattle/syndicate7 + name = "\improper Syndicate Fighter" + +/area/awaymission/spacebattle/secret + name = "\improper Hidden Chamber" + +/area/awaymission/listeningpost + name = "\improper Listening Post" + icon_state = "away" + requires_power = 0 + +/area/awaymission/beach + name = "Beach" + icon_state = "null" + lighting_use_dynamic = 0 + requires_power = 0 + var/sound/mysound = null + +/area/awaymission/beach/New() + ..() + var/sound/S = new/sound() + mysound = S + S.file = 'sound/ambience/shore.ogg' + S.repeat = 1 + S.wait = 0 + S.channel = 123 + S.volume = 100 + S.priority = 255 + S.status = SOUND_UPDATE + process() + +/area/awaymission/beach/Entered(atom/movable/Obj,atom/OldLoc) + if(ismob(Obj)) + if(Obj:client) + mysound.status = SOUND_UPDATE + Obj << mysound + return + +/area/awaymission/beach/Exited(atom/movable/Obj) + if(ismob(Obj)) + if(Obj:client) + mysound.status = SOUND_PAUSED | SOUND_UPDATE + Obj << mysound + +/area/awaymission/beach/proc/process() + //set background = 1 + + var/sound/S = null + var/sound_delay = 0 + if(prob(25)) + S = sound(file=pick('sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag3.ogg'), volume=100) + sound_delay = rand(0, 50) + + for(var/mob/living/carbon/human/H in src) + /* if(H.s_tone > -55) + H.s_tone-- + H.update_body()*/ + if(H.client) + mysound.status = SOUND_UPDATE + H << mysound + if(S) + spawn(sound_delay) + H << S + + spawn(60) .() + +///////////////////////////////////////////////////////////////////// +/* + Lists of areas to be used with is_type_in_list. + Used in gamemodes code at the moment. --rastaf0 +*/ + +// CENTCOM +var/list/centcom_areas = list ( + /area/centcom, + /area/shuttle/escape/centcom, + /area/shuttle/escape_pod1/centcom, + /area/shuttle/escape_pod2/centcom, + /area/shuttle/escape_pod3/centcom, + /area/shuttle/escape_pod5/centcom, + /area/shuttle/transport1/centcom, + /area/shuttle/administration/centcom, + /area/shuttle/specops/centcom, +) + +//SPACE STATION 13 +var/list/the_station_areas = list ( + /area/shuttle/arrival, + /area/shuttle/escape/station, + /area/shuttle/escape_pod1/station, + /area/shuttle/escape_pod2/station, + /area/shuttle/escape_pod3/station, + /area/shuttle/escape_pod5/station, + /area/shuttle/mining/station, + /area/shuttle/transport1/station, + // /area/shuttle/transport2/station, + /area/shuttle/prison/station, + /area/shuttle/administration/station, + /area/shuttle/specops/station, + /area/engineering/atmos, + /area/maintenance, + /area/hallway, + /area/bridge, + /area/crew_quarters, + /area/holodeck, + /area/mint, + /area/library, + /area/chapel, + /area/lawoffice, + /area/engineering, + /area/solar, + /area/assembly, + /area/teleporter, + /area/medical, + /area/security, + /area/supply, + /area/janitor, + /area/hydroponics, + /area/science, + /area/storage, + /area/tcomms, + /area/construction, + /area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0 + /area/ai_monitored/storage/secure, + /area/ai_monitored/storage/emergency, + /area/turret_protected/ai_upload, //do not try to simplify to "/area/turret_protected" --rastaf0 + /area/turret_protected/tcomms_control_room, + /area/turret_protected/ai_upload_foyer, + /area/turret_protected/ai, + /area/derelictparts, +) + + + + +/area/beach/ + name = "The metaclub's private beach" + icon_state = "null" + lighting_use_dynamic = 0 + requires_power = 0 + var/sound/mysound = null + +/* We have a jukebox now, fuck that +/area/beach/New() + ..() + var/sound/S = new/sound() + mysound = S + S.file = 'sound/ambience/shore.ogg' + S.repeat = 1 + S.wait = 0 + S.channel = 123 + S.volume = 100 + S.priority = 255 + S.status = SOUND_UPDATE + process() + +/area/beach/Entered(atom/movable/Obj,atom/OldLoc) + if(ismob(Obj)) + if(Obj:client) + mysound.status = SOUND_UPDATE + Obj << mysound + return + +//This only works when using Move() to exit the area +/area/beach/Exited(atom/movable/Obj) + if(ismob(Obj)) + if(Obj:client) + mysound.status = SOUND_PAUSED | SOUND_UPDATE + Obj << mysound + +/area/beach/proc/process() + //set background = 1 + + var/sound/S = null + var/sound_delay = 0 + if(prob(25)) + S = sound(file=pick('sound/ambience/seag1.ogg','sound/ambience/seag2.ogg','sound/ambience/seag3.ogg'), volume=50) + sound_delay = rand(0, 50) + + for(var/mob/living/carbon/human/H in src) +// if(H.s_tone > -55) //ugh...nice/novel idea but please no. +// H.s_tone-- +// H.update_body() + if(H.client) + mysound.status = SOUND_UPDATE + H << mysound + if(S) + spawn(sound_delay) + H << S + + spawn(60) .() + +*/ diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm index 84f2c8eb4ea..7c95e83b0d0 100644 --- a/code/game/area/ai_monitored.dm +++ b/code/game/area/ai_monitored.dm @@ -1,26 +1,26 @@ -/area/ai_monitored - name = "AI Monitored Area" - var/obj/machinery/camera/motioncamera = null - - -/area/ai_monitored/New() - ..() - // locate and store the motioncamera - spawn (20) // spawn on a delay to let turfs/objs load - for (var/obj/machinery/camera/M in src) - if(M.isMotion()) - motioncamera = M - M.area_motion = src - return - return - -/area/ai_monitored/Entered(atom/movable/O) - ..() - if (ismob(O) && motioncamera) - motioncamera.newTarget(O) - -/area/ai_monitored/Exited(atom/movable/O) - if (ismob(O) && motioncamera) - motioncamera.lostTarget(O) - - +/area/ai_monitored + name = "AI Monitored Area" + var/obj/machinery/camera/motioncamera = null + + +/area/ai_monitored/New() + ..() + // locate and store the motioncamera + spawn (20) // spawn on a delay to let turfs/objs load + for (var/obj/machinery/camera/M in src) + if(M.isMotion()) + motioncamera = M + M.area_motion = src + return + return + +/area/ai_monitored/Entered(atom/movable/O) + ..() + if (ismob(O) && motioncamera) + motioncamera.newTarget(O) + +/area/ai_monitored/Exited(atom/movable/O) + if (ismob(O) && motioncamera) + motioncamera.lostTarget(O) + + diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 6311a9590f8..aa9cae22800 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -1,679 +1,679 @@ -// Flags for door_alerts. -#define DOORALERT_ATMOS 1 -#define DOORALERT_FIRE 2 - -/area - var/global/global_uid = 0 - var/uid - var/obj/machinery/power/apc/areaapc = null - -/area/New() - icon_state = "" - layer = 10 - uid = ++global_uid - areas |= src - - if(isspace(src)) // override defaults for space. TODO: make space areas of type /area/space rather than /area - requires_power = 1 - always_unpowered = 1 - lighting_use_dynamic = 0 - power_light = 0 - power_equip = 0 - power_environ = 0 -// lighting_state = 4 - //has_gravity = 0 // Space has gravity. Because.. because. - - if(!requires_power) - power_light = 0 //rastaf0 - power_equip = 0 //rastaf0 - power_environ = 0 //rastaf0 - - ..() - -// spawn(15) - power_change() // all machines set to current power level, also updates lighting icon - -/area/Destroy() - ..() - areaapc = null - -/* - * Added to fix mech fabs 05/2013 ~Sayu. - * This is necessary due to lighting subareas. - * If you were to go in assuming that things in the same logical /area have - * the parent /area object... well, you would be mistaken. - * If you want to find machines, mobs, etc, in the same logical area, - * you will need to check all the related areas. - * This returns a master contents list to assist in that. - * NOTE: Due to a new lighting engine this is now deprecated, but we're keeping this because I can't be bothered to relace everything that references this. - */ -/proc/area_contents(const/area/A) - if (!isarea(A)) - return - - return A.contents - -/area/proc/poweralert(var/state, var/obj/source as obj) - if (suspend_alert) return - if (state != poweralm) - poweralm = state - if(istype(source)) //Only report power alarms on the z-level where the source is located. - var/list/cameras = list() - for(var/obj/machinery/camera/C in src) - cameras += C - if(state == 1) - C.network.Remove("Power Alarms") - else - C.network.Add("Power Alarms") - for (var/mob/living/silicon/aiPlayer in player_list) - if(aiPlayer.z == source.z) - if (state == 1) - aiPlayer.cancelAlarm("Power", src, source) - else - aiPlayer.triggerAlarm("Power", src, cameras, source) - for(var/obj/machinery/computer/station_alert/a in machines) - if(src in (a.covered_areas)) - if(state == 1) - a.cancelAlarm("Power", src, source) - else - a.triggerAlarm("Power", src, cameras, source) - return - -/area/proc/send_poweralert(var/obj/machinery/computer/station_alert/a)//sending alerts to newly built Station Alert Computers. - if(!poweralm) - a.triggerAlarm("Power", src, null, src) - -///////////////////////////////////////// -// BEGIN /VG/ UNFUCKING OF AIR ALARMS -///////////////////////////////////////// - -/area/proc/updateDangerLevel() - var/danger_level = 0 - - // Determine what the highest DL reported by air alarms is - for(var/obj/machinery/alarm/AA in src) - if((AA.stat & (NOPOWER|BROKEN)) || AA.shorted || AA.buildstage != 2) - continue - var/reported_danger_level=AA.local_danger_level - if(AA.alarmActivated) - reported_danger_level=2 - if(reported_danger_level>danger_level) - danger_level=reported_danger_level - //testing("Danger level at [AA.name]: [AA.local_danger_level] (reported [reported_danger_level])") - - //testing("Danger level decided upon in [name]: [danger_level] (from [atmosalm])") - - // Danger level change? - if(danger_level != atmosalm) - // Going to danger level 2 from something else - if (danger_level == 2) - var/list/cameras = list() - //updateicon() - for(var/obj/machinery/camera/C in src) - cameras += C - C.network.Add("Atmosphere Alarms") - for(var/mob/living/silicon/aiPlayer in player_list) - aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) - for(var/obj/machinery/computer/station_alert/a in machines) - if(src in (a.covered_areas)) - a.triggerAlarm("Atmosphere", src, cameras, src) - door_alerts |= DOORALERT_ATMOS - UpdateFirelocks() - // Dropping from danger level 2. - else if (atmosalm == 2) - for(var/obj/machinery/camera/C in src) - C.network.Remove("Atmosphere Alarms") - for(var/mob/living/silicon/aiPlayer in player_list) - aiPlayer.cancelAlarm("Atmosphere", src, src) - for(var/obj/machinery/computer/station_alert/a in machines) - if(src in (a.covered_areas)) - a.cancelAlarm("Atmosphere", src, src) - door_alerts &= ~DOORALERT_ATMOS - UpdateFirelocks() - atmosalm = danger_level - for (var/obj/machinery/alarm/AA in src) - if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted) - AA.update_icon() - return 1 - return 0 - -/area/proc/sendDangerLevel(var/obj/machinery/computer/station_alert/a)//sending alerts to newly built Station Alert Computers. - var/danger_level = 0 - - // Determine what the highest DL reported by air alarms is - for(var/obj/machinery/alarm/AA in src) - if((AA.stat & (NOPOWER|BROKEN)) || AA.shorted || AA.buildstage != 2) - continue - var/reported_danger_level=AA.local_danger_level - if(AA.alarmActivated) - reported_danger_level=2 - if(reported_danger_level>danger_level) - danger_level=reported_danger_level - - if (danger_level == 2) - a.triggerAlarm("Atmosphere", src, null, src) - - -/area/proc/UpdateFirelocks() - if(door_alerts != 0) - CloseFirelocks() - else - OpenFirelocks() - -/area/proc/CloseFirelocks() - if(doors_down) return - doors_down=1 - for(var/obj/machinery/door/firedoor/D in all_doors) - if(!D.blocked) - if(D.operating) - D.nextstate = CLOSED - else if(!D.density) - spawn() - D.close() - -/area/proc/OpenFirelocks() - if(!doors_down) return - doors_down=0 - for(var/obj/machinery/door/firedoor/D in all_doors) - if(!D.blocked) - if(D.operating) - D.nextstate = OPEN - else if(D.density) - spawn() - D.open() - -////////////////////////////////////////////// -// END UNFUCKING -////////////////////////////////////////////// - -/area/proc/firealert() - if(isspace(src)) //no fire alarms in space - return - if( !fire ) - fire = 1 - updateicon() - mouse_opacity = 0 - door_alerts |= DOORALERT_FIRE - UpdateFirelocks() - var/list/cameras = list() - for (var/obj/machinery/camera/C in src) - cameras.Add(C) - C.network.Add("Fire Alarms") - for (var/mob/living/silicon/ai/aiPlayer in player_list) - aiPlayer.triggerAlarm("Fire", src, cameras, src) - for (var/obj/machinery/computer/station_alert/a in machines) - if(src in (a.covered_areas)) - a.triggerAlarm("Fire", src, cameras, src) - -/area/proc/send_firealert(var/obj/machinery/computer/station_alert/a)//sending alerts to newly built Station Alert Computers. - if(fire) - a.triggerAlarm("Fire", src, null, src) - -/area/proc/firereset() - if (fire) - fire = 0 - mouse_opacity = 0 - updateicon() - for (var/obj/machinery/camera/C in src) - C.network.Remove("Fire Alarms") - for (var/mob/living/silicon/ai/aiPlayer in player_list) - aiPlayer.cancelAlarm("Fire", src, src) - for (var/obj/machinery/computer/station_alert/a in machines) - if(src in (a.covered_areas)) - a.cancelAlarm("Fire", src, src) - door_alerts &= ~DOORALERT_FIRE - UpdateFirelocks() - -/area/proc/radiation_alert() - if(isspace(src)) return - - if(!radalert) - radalert = 1 - updateicon() - return - -/area/proc/reset_radiation_alert() - if(isspace(src)) return - - if(radalert) - radalert = 0 - updateicon() - return - -/area/proc/readyalert() - if(isspace(src)) return - - if(!eject) - eject = 1 - updateicon() - return - -/area/proc/readyreset() - if(eject) - eject = 0 - updateicon() - return - -/area/proc/partyalert() - if(isspace(src)) return - - if (!( party )) - party = 1 - updateicon() - mouse_opacity = 0 - return - -/area/proc/partyreset() - if (party) - party = 0 - mouse_opacity = 0 - updateicon() - return - -/area/proc/updateicon() - if ((fire || eject || party || radalert) && ((!requires_power)?(!requires_power):power_environ))//If it doesn't require power, can still activate this proc. - // Highest priority at the top. - if(radalert && !fire) - icon_state = "radiation" - else if(fire && !radalert && !eject && !party) - icon_state = "blue" - /*else if(atmosalm && !fire && !eject && !party) - icon_state = "bluenew"*/ - else if(!fire && eject && !party) - icon_state = "red" - else if(party && !fire && !eject) - icon_state = "party" - else - icon_state = "blue-red" - else - // new lighting behaviour with obj lights - icon_state = null - - -/* -#define EQUIP 1 -#define LIGHT 2 -#define ENVIRON 3 -*/ - -/area/proc/powered(var/chan) // return true if the area has power to given channel - - - if(!requires_power) - return 1 - if(always_unpowered) - return 0 - switch(chan) - if(EQUIP) - return power_equip - if(LIGHT) - return power_light - if(ENVIRON) - return power_environ - - return 0 - -/* - * Called when power status changes. - */ -/area/proc/power_change() - for(var/obj/machinery/M in src) // for each machine in the area - M.power_change() // reverify power status (to update icons etc.) - if (fire || eject || party) - updateicon() - -/area/proc/usage(const/chan) - switch (chan) - if (LIGHT) - return used_light - if (EQUIP) - return used_equip - if (ENVIRON) - return used_environ - if (TOTAL) - return used_light + used_equip + used_environ - if(STATIC_EQUIP) - return static_equip - if(STATIC_LIGHT) - return static_light - if(STATIC_ENVIRON) - return static_environ - return 0 - -/area/proc/addStaticPower(value, powerchannel) - switch(powerchannel) - if(STATIC_EQUIP) - static_equip += value - if(STATIC_LIGHT) - static_light += value - if(STATIC_ENVIRON) - static_environ += value - -/area/proc/clear_usage() - used_equip = 0 - used_light = 0 - used_environ = 0 - -/area/proc/use_power(const/amount, const/chan) - switch (chan) - if(EQUIP) - used_equip += amount - if(LIGHT) - used_light += amount - if(ENVIRON) - used_environ += amount - -/area/Entered(atom/movable/Obj, atom/OldLoc) - var/area/oldArea = Obj.areaMaster - Obj.areaMaster = src - if(!ismob(Obj)) - return - - var/mob/M = Obj - - // /vg/ - EVENTS! - CallHook("MobAreaChange", list("mob" = M, "new" = Obj.areaMaster, "old" = oldArea)) - - if(isnull(M.client)) - return - - if(M.client.prefs.toggles & SOUND_AMBIENCE) - if(isnull(M.areaMaster.media_source) && !M.client.ambience_playing) - M.client.ambience_playing = 1 - var/sound = 'sound/ambience/shipambience.ogg' - - if(prob(35)) - //Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! - //Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch. - //TODO: This is dumb - N3X. - if(istype(src, /area/chapel)) - sound = pick('sound/ambience/ambicha1.ogg', 'sound/ambience/ambicha2.ogg', 'sound/ambience/ambicha3.ogg', 'sound/ambience/ambicha4.ogg') - else if(istype(src, /area/medical/morgue)) - sound = pick('sound/ambience/ambimo1.ogg', 'sound/ambience/ambimo2.ogg', 'sound/music/main.ogg') - else if(isspace(src)) - sound = pick('sound/ambience/ambispace.ogg', 'sound/music/space.ogg', 'sound/music/main.ogg', 'sound/music/traitor.ogg', 'sound/ambience/spookyspace1.ogg', 'sound/ambience/spookyspace2.ogg') - else if(istype(src, /area/engineering)) - sound = pick('sound/ambience/ambisin1.ogg', 'sound/ambience/ambisin2.ogg', 'sound/ambience/ambisin3.ogg', 'sound/ambience/ambisin4.ogg') - else if(istype(src, /area/AIsattele) || istype(src, /area/turret_protected/ai) || istype(src, /area/turret_protected/ai_upload) || istype(src, /area/turret_protected/ai_upload_foyer)) - sound = pick('sound/ambience/ambimalf.ogg') - else if(istype(src, /area/maintenance/ghettobar)) - sound = pick('sound/ambience/ghetto.ogg') - else if(istype(src, /area/shuttle/salvage/derelict)) - sound = pick('sound/ambience/derelict1.ogg', 'sound/ambience/derelict2.ogg', 'sound/ambience/derelict3.ogg', 'sound/ambience/derelict4.ogg') - else if(istype(src, /area/mine/explored) || istype(src, /area/mine/unexplored)) - sound = pick('sound/ambience/ambimine.ogg', 'sound/ambience/song_game.ogg', 'sound/music/torvus.ogg') - else if(istype(src, /area/maintenance/fsmaint2) || istype(src, /area/maintenance/port) || istype(src, /area/maintenance/aft) || istype(src, /area/maintenance/asmaint)) - sound = pick('sound/ambience/spookymaint1.ogg', 'sound/ambience/spookymaint2.ogg') - else if(istype(src, /area/tcommsat) || istype(src, /area/turret_protected/tcomwest) || istype(src, /area/turret_protected/tcomeast) || istype(src, /area/turret_protected/tcomfoyer) || istype(src, /area/turret_protected/tcomsat)) - sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') - else - sound = pick('sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen7.ogg', 'sound/ambience/ambigen8.ogg', 'sound/ambience/ambigen9.ogg', 'sound/ambience/ambigen10.ogg', 'sound/ambience/ambigen11.ogg', 'sound/ambience/ambigen12.ogg', 'sound/ambience/ambigen14.ogg') - - M << sound(sound, 0, 0, SOUND_AMBIANCE, 25) - - spawn(600) // Ewww - this is very very bad. - if(M && M.client) - M.client.ambience_playing = 0 - -/area/proc/gravitychange(var/gravitystate = 0, var/area/A) - - - A.has_gravity = gravitystate - - if(gravitystate) - for(var/mob/living/carbon/human/H in A) - if(istype(get_turf(H), /turf/space)) //You can't fall on space - continue - if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) - continue - if(H.locked_to) //Locked to something, anything - continue - - H.AdjustStunned(5) - to_chat(H, "Gravity!") - -/area/proc/set_apc(var/obj/machinery/power/apc/apctoset) - areaapc = apctoset - -/area/proc/remove_apc(var/obj/machinery/power/apc/apctoremove) - if(areaapc == apctoremove) - areaapc = null - -/area/proc/get_turfs() - var/list/L = list() - for(var/turf/T in contents) - L |= T - - return L - -/area/proc/get_atoms() - var/list/L = list() - for(var/atom/A in contents) - L |= A - - return L - -/area/proc/get_shuttle() - for(var/datum/shuttle/S in shuttles) - if(S.linked_area == src) return S - return null - -/area/proc/displace_contents() - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in src) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - -//This proc adds all turfs in the list to the parent area, calling change_area on everything -//Returns nothing -/area/proc/add_turfs(var/list/L) - for(var/turf/T in L) - if(T in L) continue - var/area/old_area = get_area(T) - - L += T - - T.change_area(old_area,src) - for(var/atom/movable/AM in T.contents) - AM.change_area(old_area,src) - -var/list/ignored_keys = list("loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z","group","contents","air","light","areaMaster","underlays","lighting_overlay") -var/list/moved_landmarks = list(latejoin, wizardstart) //Landmarks that are moved by move_area_to and move_contents_to -var/list/transparent_icons = list("diagonalWall3","swall_f5","swall_f6","swall_f9","swall_f10") //icon_states for which to prepare an underlay - -/area/proc/move_contents_to(var/area/A, var/turftoleave=null, var/direction = null) - //Takes: Area. Optional: turf type to leave behind. - //Returns: Nothing. - //Notes: Attempts to move the contents of one area to another area. - // Movement based on lower left corner. Tiles that do not fit - // into the new area will not be moved. - - if(!A || !src) return 0 - - var/list/turfs_src = get_area_turfs(src.type) - var/list/turfs_trg = get_area_turfs(A.type) - - var/src_min_x = 0 - var/src_min_y = 0 - for (var/turf/T in turfs_src) - if(T.x < src_min_x || !src_min_x) src_min_x = T.x - if(T.y < src_min_y || !src_min_y) src_min_y = T.y - - var/trg_min_x = 0 - var/trg_min_y = 0 - - for (var/turf/T in turfs_trg) - if(T.x < trg_min_x || !trg_min_x) trg_min_x = T.x - if(T.y < trg_min_y || !trg_min_y) trg_min_y = T.y - - var/list/refined_src = new/list() - for(var/turf/T in turfs_src) - refined_src += T - refined_src[T] = new/datum/coords - var/datum/coords/C = refined_src[T] - C.x_pos = (T.x - src_min_x) - C.y_pos = (T.y - src_min_y) - - var/list/refined_trg = new/list() - for(var/turf/T in turfs_trg) - refined_trg += T - refined_trg[T] = new/datum/coords - var/datum/coords/C = refined_trg[T] - C.x_pos = (T.x - trg_min_x) - C.y_pos = (T.y - trg_min_y) - - var/list/fromupdate = new/list() - var/list/toupdate = new/list() - - moving: - for (var/turf/T in refined_src) - var/area/AA = get_area(T) - var/datum/coords/C_src = refined_src[T] - for (var/turf/B in refined_trg) - var/datum/coords/C_trg = refined_trg[B] - if(C_src.x_pos == C_trg.x_pos && C_src.y_pos == C_trg.y_pos) - - var/old_dir1 = T.dir - var/old_icon_state1 = T.icon_state - var/old_icon1 = T.icon - var/image/undlay = image("icon"=B.icon,"icon_state"=B.icon_state,"dir"=B.dir) - undlay.overlays = B.overlays - var/prevtype = B.type - - var/turf/X = B.ChangeTurf(T.type, allow = 1) - for(var/key in T.vars) - if(key in ignored_keys) continue - if(istype(T.vars[key],/list)) - var/list/L = T.vars[key] - X.vars[key] = L.Copy() - else - X.vars[key] = T.vars[key] - if(ispath(prevtype,/turf/space))//including the transit hyperspace turfs - /*if(ispath(AA.type, /area/syndicate_station/start) || ispath(AA.type, /area/syndicate_station/transit))//that's the snowflake to pay when people map their ships over the snow. - X.underlays += undlay - else */if(T.underlays.len) - X.underlays = T.underlays - else - X.underlays += undlay - else - X.underlays += undlay - X.dir = old_dir1 - X.icon_state = old_icon_state1 - X.icon = old_icon1 //Shuttle floors are in shuttle.dmi while the defaults are floors.dmi - - var/turf/simulated/ST = T - - if(istype(ST) && ST.zone) - var/turf/simulated/SX = X - - if(!SX.air) - SX.make_air() - - SX.air.copy_from(ST.zone.air) - ST.zone.remove(ST) - - /* Quick visual fix for some weird shuttle corner artefacts when on transit space tiles */ - if(direction && findtext(X.icon_state, "swall_s")) - - // Spawn a new shuttle corner object - var/obj/corner = new() - corner.forceMove(X) - corner.density = 1 - corner.anchored = 1 - corner.icon = X.icon - corner.icon_state = replacetext(X.icon_state, "_s", "_f") - corner.tag = "delete me" - corner.name = "wall" - - // Find a new turf to take on the property of - var/turf/nextturf = get_step(corner, direction) - if(!nextturf || !istype(nextturf, /turf/space)) - nextturf = get_step(corner, turn(direction, 180)) - - - // Take on the icon of a neighboring scrolling space icon - X.icon = nextturf.icon - X.icon_state = nextturf.icon_state - - - for(var/obj/O in T) - - // Reset the shuttle corners - if(O.tag == "delete me") - X.icon = 'icons/turf/shuttle.dmi' - X.icon_state = replacetext(O.icon_state, "_f", "_s") // revert the turf to the old icon_state - X.name = "wall" - qdel(O) // prevents multiple shuttle corners from stacking - O = null - continue - if(!istype(O,/obj)) continue - O.forceMove(X) - for(var/mob/M in T) - if(!M.can_shuttle_move()) - continue - M.forceMove(X) - -// var/area/AR = X.loc - -// if(AR.lighting_use_dynamic) //TODO: rewrite this code so it's not messed by lighting ~Carn -// X.opacity = !X.opacity -// X.SetOpacity(!X.opacity) - - toupdate += X - - if(turftoleave) - fromupdate += T.ChangeTurf(turftoleave, allow = 1) - else - if(ispath(AA.type, /area/syndicate_station/start)) - T.ChangeTurf(/turf/unsimulated/floor, allow = 1) - T.icon = 'icons/turf/snow.dmi' - T.icon_state = "snow" - else - T.ChangeTurf(get_base_turf(T.z), allow = 1) - if(istype(T, /turf/space)) - switch(universe.name) //for some reason using OnTurfChange doesn't actually do anything in this case. - if("Hell Rising") - T.overlays += "hell01" - if("Supermatter Cascade") - T.overlays += "end01" - - - refined_src -= T - refined_trg -= B - continue moving - - var/list/doors = new/list() - - if(toupdate.len) - for(var/turf/simulated/T1 in toupdate) - for(var/obj/machinery/door/D2 in T1) - doors += D2 - /*if(T1.parent) - air_master.groups_to_rebuild += T1.parent - else - air_master.mark_for_update(T1)*/ - - if(fromupdate.len) - for(var/turf/simulated/T2 in fromupdate) - for(var/obj/machinery/door/D2 in T2) - doors += D2 - /*if(T2.parent) - air_master.groups_to_rebuild += T2.parent - else - air_master.mark_for_update(T2)*/ - - for(var/obj/machinery/door/D in doors) - D.update_nearby_tiles() +// Flags for door_alerts. +#define DOORALERT_ATMOS 1 +#define DOORALERT_FIRE 2 + +/area + var/global/global_uid = 0 + var/uid + var/obj/machinery/power/apc/areaapc = null + +/area/New() + icon_state = "" + layer = 10 + uid = ++global_uid + areas |= src + + if(isspace(src)) // override defaults for space. TODO: make space areas of type /area/space rather than /area + requires_power = 1 + always_unpowered = 1 + lighting_use_dynamic = 0 + power_light = 0 + power_equip = 0 + power_environ = 0 +// lighting_state = 4 + //has_gravity = 0 // Space has gravity. Because.. because. + + if(!requires_power) + power_light = 0 //rastaf0 + power_equip = 0 //rastaf0 + power_environ = 0 //rastaf0 + + ..() + +// spawn(15) + power_change() // all machines set to current power level, also updates lighting icon + +/area/Destroy() + ..() + areaapc = null + +/* + * Added to fix mech fabs 05/2013 ~Sayu. + * This is necessary due to lighting subareas. + * If you were to go in assuming that things in the same logical /area have + * the parent /area object... well, you would be mistaken. + * If you want to find machines, mobs, etc, in the same logical area, + * you will need to check all the related areas. + * This returns a master contents list to assist in that. + * NOTE: Due to a new lighting engine this is now deprecated, but we're keeping this because I can't be bothered to relace everything that references this. + */ +/proc/area_contents(const/area/A) + if (!isarea(A)) + return + + return A.contents + +/area/proc/poweralert(var/state, var/obj/source as obj) + if (suspend_alert) return + if (state != poweralm) + poweralm = state + if(istype(source)) //Only report power alarms on the z-level where the source is located. + var/list/cameras = list() + for(var/obj/machinery/camera/C in src) + cameras += C + if(state == 1) + C.network.Remove("Power Alarms") + else + C.network.Add("Power Alarms") + for (var/mob/living/silicon/aiPlayer in player_list) + if(aiPlayer.z == source.z) + if (state == 1) + aiPlayer.cancelAlarm("Power", src, source) + else + aiPlayer.triggerAlarm("Power", src, cameras, source) + for(var/obj/machinery/computer/station_alert/a in machines) + if(src in (a.covered_areas)) + if(state == 1) + a.cancelAlarm("Power", src, source) + else + a.triggerAlarm("Power", src, cameras, source) + return + +/area/proc/send_poweralert(var/obj/machinery/computer/station_alert/a)//sending alerts to newly built Station Alert Computers. + if(!poweralm) + a.triggerAlarm("Power", src, null, src) + +///////////////////////////////////////// +// BEGIN /VG/ UNFUCKING OF AIR ALARMS +///////////////////////////////////////// + +/area/proc/updateDangerLevel() + var/danger_level = 0 + + // Determine what the highest DL reported by air alarms is + for(var/obj/machinery/alarm/AA in src) + if((AA.stat & (NOPOWER|BROKEN)) || AA.shorted || AA.buildstage != 2) + continue + var/reported_danger_level=AA.local_danger_level + if(AA.alarmActivated) + reported_danger_level=2 + if(reported_danger_level>danger_level) + danger_level=reported_danger_level + //testing("Danger level at [AA.name]: [AA.local_danger_level] (reported [reported_danger_level])") + + //testing("Danger level decided upon in [name]: [danger_level] (from [atmosalm])") + + // Danger level change? + if(danger_level != atmosalm) + // Going to danger level 2 from something else + if (danger_level == 2) + var/list/cameras = list() + //updateicon() + for(var/obj/machinery/camera/C in src) + cameras += C + C.network.Add("Atmosphere Alarms") + for(var/mob/living/silicon/aiPlayer in player_list) + aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) + for(var/obj/machinery/computer/station_alert/a in machines) + if(src in (a.covered_areas)) + a.triggerAlarm("Atmosphere", src, cameras, src) + door_alerts |= DOORALERT_ATMOS + UpdateFirelocks() + // Dropping from danger level 2. + else if (atmosalm == 2) + for(var/obj/machinery/camera/C in src) + C.network.Remove("Atmosphere Alarms") + for(var/mob/living/silicon/aiPlayer in player_list) + aiPlayer.cancelAlarm("Atmosphere", src, src) + for(var/obj/machinery/computer/station_alert/a in machines) + if(src in (a.covered_areas)) + a.cancelAlarm("Atmosphere", src, src) + door_alerts &= ~DOORALERT_ATMOS + UpdateFirelocks() + atmosalm = danger_level + for (var/obj/machinery/alarm/AA in src) + if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted) + AA.update_icon() + return 1 + return 0 + +/area/proc/sendDangerLevel(var/obj/machinery/computer/station_alert/a)//sending alerts to newly built Station Alert Computers. + var/danger_level = 0 + + // Determine what the highest DL reported by air alarms is + for(var/obj/machinery/alarm/AA in src) + if((AA.stat & (NOPOWER|BROKEN)) || AA.shorted || AA.buildstage != 2) + continue + var/reported_danger_level=AA.local_danger_level + if(AA.alarmActivated) + reported_danger_level=2 + if(reported_danger_level>danger_level) + danger_level=reported_danger_level + + if (danger_level == 2) + a.triggerAlarm("Atmosphere", src, null, src) + + +/area/proc/UpdateFirelocks() + if(door_alerts != 0) + CloseFirelocks() + else + OpenFirelocks() + +/area/proc/CloseFirelocks() + if(doors_down) return + doors_down=1 + for(var/obj/machinery/door/firedoor/D in all_doors) + if(!D.blocked) + if(D.operating) + D.nextstate = CLOSED + else if(!D.density) + spawn() + D.close() + +/area/proc/OpenFirelocks() + if(!doors_down) return + doors_down=0 + for(var/obj/machinery/door/firedoor/D in all_doors) + if(!D.blocked) + if(D.operating) + D.nextstate = OPEN + else if(D.density) + spawn() + D.open() + +////////////////////////////////////////////// +// END UNFUCKING +////////////////////////////////////////////// + +/area/proc/firealert() + if(isspace(src)) //no fire alarms in space + return + if( !fire ) + fire = 1 + updateicon() + mouse_opacity = 0 + door_alerts |= DOORALERT_FIRE + UpdateFirelocks() + var/list/cameras = list() + for (var/obj/machinery/camera/C in src) + cameras.Add(C) + C.network.Add("Fire Alarms") + for (var/mob/living/silicon/ai/aiPlayer in player_list) + aiPlayer.triggerAlarm("Fire", src, cameras, src) + for (var/obj/machinery/computer/station_alert/a in machines) + if(src in (a.covered_areas)) + a.triggerAlarm("Fire", src, cameras, src) + +/area/proc/send_firealert(var/obj/machinery/computer/station_alert/a)//sending alerts to newly built Station Alert Computers. + if(fire) + a.triggerAlarm("Fire", src, null, src) + +/area/proc/firereset() + if (fire) + fire = 0 + mouse_opacity = 0 + updateicon() + for (var/obj/machinery/camera/C in src) + C.network.Remove("Fire Alarms") + for (var/mob/living/silicon/ai/aiPlayer in player_list) + aiPlayer.cancelAlarm("Fire", src, src) + for (var/obj/machinery/computer/station_alert/a in machines) + if(src in (a.covered_areas)) + a.cancelAlarm("Fire", src, src) + door_alerts &= ~DOORALERT_FIRE + UpdateFirelocks() + +/area/proc/radiation_alert() + if(isspace(src)) return + + if(!radalert) + radalert = 1 + updateicon() + return + +/area/proc/reset_radiation_alert() + if(isspace(src)) return + + if(radalert) + radalert = 0 + updateicon() + return + +/area/proc/readyalert() + if(isspace(src)) return + + if(!eject) + eject = 1 + updateicon() + return + +/area/proc/readyreset() + if(eject) + eject = 0 + updateicon() + return + +/area/proc/partyalert() + if(isspace(src)) return + + if (!( party )) + party = 1 + updateicon() + mouse_opacity = 0 + return + +/area/proc/partyreset() + if (party) + party = 0 + mouse_opacity = 0 + updateicon() + return + +/area/proc/updateicon() + if ((fire || eject || party || radalert) && ((!requires_power)?(!requires_power):power_environ))//If it doesn't require power, can still activate this proc. + // Highest priority at the top. + if(radalert && !fire) + icon_state = "radiation" + else if(fire && !radalert && !eject && !party) + icon_state = "blue" + /*else if(atmosalm && !fire && !eject && !party) + icon_state = "bluenew"*/ + else if(!fire && eject && !party) + icon_state = "red" + else if(party && !fire && !eject) + icon_state = "party" + else + icon_state = "blue-red" + else + // new lighting behaviour with obj lights + icon_state = null + + +/* +#define EQUIP 1 +#define LIGHT 2 +#define ENVIRON 3 +*/ + +/area/proc/powered(var/chan) // return true if the area has power to given channel + + + if(!requires_power) + return 1 + if(always_unpowered) + return 0 + switch(chan) + if(EQUIP) + return power_equip + if(LIGHT) + return power_light + if(ENVIRON) + return power_environ + + return 0 + +/* + * Called when power status changes. + */ +/area/proc/power_change() + for(var/obj/machinery/M in src) // for each machine in the area + M.power_change() // reverify power status (to update icons etc.) + if (fire || eject || party) + updateicon() + +/area/proc/usage(const/chan) + switch (chan) + if (LIGHT) + return used_light + if (EQUIP) + return used_equip + if (ENVIRON) + return used_environ + if (TOTAL) + return used_light + used_equip + used_environ + if(STATIC_EQUIP) + return static_equip + if(STATIC_LIGHT) + return static_light + if(STATIC_ENVIRON) + return static_environ + return 0 + +/area/proc/addStaticPower(value, powerchannel) + switch(powerchannel) + if(STATIC_EQUIP) + static_equip += value + if(STATIC_LIGHT) + static_light += value + if(STATIC_ENVIRON) + static_environ += value + +/area/proc/clear_usage() + used_equip = 0 + used_light = 0 + used_environ = 0 + +/area/proc/use_power(const/amount, const/chan) + switch (chan) + if(EQUIP) + used_equip += amount + if(LIGHT) + used_light += amount + if(ENVIRON) + used_environ += amount + +/area/Entered(atom/movable/Obj, atom/OldLoc) + var/area/oldArea = Obj.areaMaster + Obj.areaMaster = src + if(!ismob(Obj)) + return + + var/mob/M = Obj + + // /vg/ - EVENTS! + CallHook("MobAreaChange", list("mob" = M, "new" = Obj.areaMaster, "old" = oldArea)) + + if(isnull(M.client)) + return + + if(M.client.prefs.toggles & SOUND_AMBIENCE) + if(isnull(M.areaMaster.media_source) && !M.client.ambience_playing) + M.client.ambience_playing = 1 + var/sound = 'sound/ambience/shipambience.ogg' + + if(prob(35)) + //Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! + //Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch. + //TODO: This is dumb - N3X. + if(istype(src, /area/chapel)) + sound = pick('sound/ambience/ambicha1.ogg', 'sound/ambience/ambicha2.ogg', 'sound/ambience/ambicha3.ogg', 'sound/ambience/ambicha4.ogg') + else if(istype(src, /area/medical/morgue)) + sound = pick('sound/ambience/ambimo1.ogg', 'sound/ambience/ambimo2.ogg', 'sound/music/main.ogg') + else if(isspace(src)) + sound = pick('sound/ambience/ambispace.ogg', 'sound/music/space.ogg', 'sound/music/main.ogg', 'sound/music/traitor.ogg', 'sound/ambience/spookyspace1.ogg', 'sound/ambience/spookyspace2.ogg') + else if(istype(src, /area/engineering)) + sound = pick('sound/ambience/ambisin1.ogg', 'sound/ambience/ambisin2.ogg', 'sound/ambience/ambisin3.ogg', 'sound/ambience/ambisin4.ogg') + else if(istype(src, /area/AIsattele) || istype(src, /area/turret_protected/ai) || istype(src, /area/turret_protected/ai_upload) || istype(src, /area/turret_protected/ai_upload_foyer)) + sound = pick('sound/ambience/ambimalf.ogg') + else if(istype(src, /area/maintenance/ghettobar)) + sound = pick('sound/ambience/ghetto.ogg') + else if(istype(src, /area/shuttle/salvage/derelict)) + sound = pick('sound/ambience/derelict1.ogg', 'sound/ambience/derelict2.ogg', 'sound/ambience/derelict3.ogg', 'sound/ambience/derelict4.ogg') + else if(istype(src, /area/mine/explored) || istype(src, /area/mine/unexplored)) + sound = pick('sound/ambience/ambimine.ogg', 'sound/ambience/song_game.ogg', 'sound/music/torvus.ogg') + else if(istype(src, /area/maintenance/fsmaint2) || istype(src, /area/maintenance/port) || istype(src, /area/maintenance/aft) || istype(src, /area/maintenance/asmaint)) + sound = pick('sound/ambience/spookymaint1.ogg', 'sound/ambience/spookymaint2.ogg') + else if(istype(src, /area/tcommsat) || istype(src, /area/turret_protected/tcomwest) || istype(src, /area/turret_protected/tcomeast) || istype(src, /area/turret_protected/tcomfoyer) || istype(src, /area/turret_protected/tcomsat)) + sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') + else + sound = pick('sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen7.ogg', 'sound/ambience/ambigen8.ogg', 'sound/ambience/ambigen9.ogg', 'sound/ambience/ambigen10.ogg', 'sound/ambience/ambigen11.ogg', 'sound/ambience/ambigen12.ogg', 'sound/ambience/ambigen14.ogg') + + M << sound(sound, 0, 0, SOUND_AMBIANCE, 25) + + spawn(600) // Ewww - this is very very bad. + if(M && M.client) + M.client.ambience_playing = 0 + +/area/proc/gravitychange(var/gravitystate = 0, var/area/A) + + + A.has_gravity = gravitystate + + if(gravitystate) + for(var/mob/living/carbon/human/H in A) + if(istype(get_turf(H), /turf/space)) //You can't fall on space + continue + if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) + continue + if(H.locked_to) //Locked to something, anything + continue + + H.AdjustStunned(5) + to_chat(H, "Gravity!") + +/area/proc/set_apc(var/obj/machinery/power/apc/apctoset) + areaapc = apctoset + +/area/proc/remove_apc(var/obj/machinery/power/apc/apctoremove) + if(areaapc == apctoremove) + areaapc = null + +/area/proc/get_turfs() + var/list/L = list() + for(var/turf/T in contents) + L |= T + + return L + +/area/proc/get_atoms() + var/list/L = list() + for(var/atom/A in contents) + L |= A + + return L + +/area/proc/get_shuttle() + for(var/datum/shuttle/S in shuttles) + if(S.linked_area == src) return S + return null + +/area/proc/displace_contents() + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in src) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + +//This proc adds all turfs in the list to the parent area, calling change_area on everything +//Returns nothing +/area/proc/add_turfs(var/list/L) + for(var/turf/T in L) + if(T in L) continue + var/area/old_area = get_area(T) + + L += T + + T.change_area(old_area,src) + for(var/atom/movable/AM in T.contents) + AM.change_area(old_area,src) + +var/list/ignored_keys = list("loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z","group","contents","air","light","areaMaster","underlays","lighting_overlay") +var/list/moved_landmarks = list(latejoin, wizardstart) //Landmarks that are moved by move_area_to and move_contents_to +var/list/transparent_icons = list("diagonalWall3","swall_f5","swall_f6","swall_f9","swall_f10") //icon_states for which to prepare an underlay + +/area/proc/move_contents_to(var/area/A, var/turftoleave=null, var/direction = null) + //Takes: Area. Optional: turf type to leave behind. + //Returns: Nothing. + //Notes: Attempts to move the contents of one area to another area. + // Movement based on lower left corner. Tiles that do not fit + // into the new area will not be moved. + + if(!A || !src) return 0 + + var/list/turfs_src = get_area_turfs(src.type) + var/list/turfs_trg = get_area_turfs(A.type) + + var/src_min_x = 0 + var/src_min_y = 0 + for (var/turf/T in turfs_src) + if(T.x < src_min_x || !src_min_x) src_min_x = T.x + if(T.y < src_min_y || !src_min_y) src_min_y = T.y + + var/trg_min_x = 0 + var/trg_min_y = 0 + + for (var/turf/T in turfs_trg) + if(T.x < trg_min_x || !trg_min_x) trg_min_x = T.x + if(T.y < trg_min_y || !trg_min_y) trg_min_y = T.y + + var/list/refined_src = new/list() + for(var/turf/T in turfs_src) + refined_src += T + refined_src[T] = new/datum/coords + var/datum/coords/C = refined_src[T] + C.x_pos = (T.x - src_min_x) + C.y_pos = (T.y - src_min_y) + + var/list/refined_trg = new/list() + for(var/turf/T in turfs_trg) + refined_trg += T + refined_trg[T] = new/datum/coords + var/datum/coords/C = refined_trg[T] + C.x_pos = (T.x - trg_min_x) + C.y_pos = (T.y - trg_min_y) + + var/list/fromupdate = new/list() + var/list/toupdate = new/list() + + moving: + for (var/turf/T in refined_src) + var/area/AA = get_area(T) + var/datum/coords/C_src = refined_src[T] + for (var/turf/B in refined_trg) + var/datum/coords/C_trg = refined_trg[B] + if(C_src.x_pos == C_trg.x_pos && C_src.y_pos == C_trg.y_pos) + + var/old_dir1 = T.dir + var/old_icon_state1 = T.icon_state + var/old_icon1 = T.icon + var/image/undlay = image("icon"=B.icon,"icon_state"=B.icon_state,"dir"=B.dir) + undlay.overlays = B.overlays + var/prevtype = B.type + + var/turf/X = B.ChangeTurf(T.type, allow = 1) + for(var/key in T.vars) + if(key in ignored_keys) continue + if(istype(T.vars[key],/list)) + var/list/L = T.vars[key] + X.vars[key] = L.Copy() + else + X.vars[key] = T.vars[key] + if(ispath(prevtype,/turf/space))//including the transit hyperspace turfs + /*if(ispath(AA.type, /area/syndicate_station/start) || ispath(AA.type, /area/syndicate_station/transit))//that's the snowflake to pay when people map their ships over the snow. + X.underlays += undlay + else */if(T.underlays.len) + X.underlays = T.underlays + else + X.underlays += undlay + else + X.underlays += undlay + X.dir = old_dir1 + X.icon_state = old_icon_state1 + X.icon = old_icon1 //Shuttle floors are in shuttle.dmi while the defaults are floors.dmi + + var/turf/simulated/ST = T + + if(istype(ST) && ST.zone) + var/turf/simulated/SX = X + + if(!SX.air) + SX.make_air() + + SX.air.copy_from(ST.zone.air) + ST.zone.remove(ST) + + /* Quick visual fix for some weird shuttle corner artefacts when on transit space tiles */ + if(direction && findtext(X.icon_state, "swall_s")) + + // Spawn a new shuttle corner object + var/obj/corner = new() + corner.forceMove(X) + corner.density = 1 + corner.anchored = 1 + corner.icon = X.icon + corner.icon_state = replacetext(X.icon_state, "_s", "_f") + corner.tag = "delete me" + corner.name = "wall" + + // Find a new turf to take on the property of + var/turf/nextturf = get_step(corner, direction) + if(!nextturf || !istype(nextturf, /turf/space)) + nextturf = get_step(corner, turn(direction, 180)) + + + // Take on the icon of a neighboring scrolling space icon + X.icon = nextturf.icon + X.icon_state = nextturf.icon_state + + + for(var/obj/O in T) + + // Reset the shuttle corners + if(O.tag == "delete me") + X.icon = 'icons/turf/shuttle.dmi' + X.icon_state = replacetext(O.icon_state, "_f", "_s") // revert the turf to the old icon_state + X.name = "wall" + qdel(O) // prevents multiple shuttle corners from stacking + O = null + continue + if(!istype(O,/obj)) continue + O.forceMove(X) + for(var/mob/M in T) + if(!M.can_shuttle_move()) + continue + M.forceMove(X) + +// var/area/AR = X.loc + +// if(AR.lighting_use_dynamic) //TODO: rewrite this code so it's not messed by lighting ~Carn +// X.opacity = !X.opacity +// X.SetOpacity(!X.opacity) + + toupdate += X + + if(turftoleave) + fromupdate += T.ChangeTurf(turftoleave, allow = 1) + else + if(ispath(AA.type, /area/syndicate_station/start)) + T.ChangeTurf(/turf/unsimulated/floor, allow = 1) + T.icon = 'icons/turf/snow.dmi' + T.icon_state = "snow" + else + T.ChangeTurf(get_base_turf(T.z), allow = 1) + if(istype(T, /turf/space)) + switch(universe.name) //for some reason using OnTurfChange doesn't actually do anything in this case. + if("Hell Rising") + T.overlays += "hell01" + if("Supermatter Cascade") + T.overlays += "end01" + + + refined_src -= T + refined_trg -= B + continue moving + + var/list/doors = new/list() + + if(toupdate.len) + for(var/turf/simulated/T1 in toupdate) + for(var/obj/machinery/door/D2 in T1) + doors += D2 + /*if(T1.parent) + air_master.groups_to_rebuild += T1.parent + else + air_master.mark_for_update(T1)*/ + + if(fromupdate.len) + for(var/turf/simulated/T2 in fromupdate) + for(var/obj/machinery/door/D2 in T2) + doors += D2 + /*if(T2.parent) + air_master.groups_to_rebuild += T2.parent + else + air_master.mark_for_update(T2)*/ + + for(var/obj/machinery/door/D in doors) + D.update_nearby_tiles() diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 7ee7a570777..6f70f832f8f 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -1,86 +1,86 @@ -var/global/list/spawned_surprises = list() - -var/global/max_secret_rooms = 3 - -/* Le broken. -proc/admin_spawn_room_at_pos() - var/wall - var/floor - var/x = input("X position","X pos",usr.x) - var/y = input("Y position","Y pos",usr.y) - var/z = input("Z position","Z pos",usr.z) - var/x_len = input("Desired length.","Length",5) - var/y_len = input("Desired width.","Width",5) - var/clean = input("Delete existing items in area?" , "Clean area?", 0) - switch(alert("Wall type",null,"Reinforced wall","Regular wall","Resin wall")) - if("Reinforced wall") - wall=/turf/simulated/wall/r_wall - if("Regular wall") - wall=/turf/simulated/wall - if("Resin wall") - wall=/obj/effect/alien/resin - switch(alert("Floor type",null,"Regular floor","Reinforced floor")) - if("Regular floor") - floor=/turf/simulated/floor - if("Reinforced floor") - floor=/turf/simulated/floor/engine - if(x && y && z && wall && floor && x_len && y_len) - spawn_room(locate(x,y,z),x_len,y_len,wall,floor,clean) - return -*/ - -proc/check_complex_placement(var/turf/T,var/size_x,var/size_y,var/ignore_walls=0) - var/list/surroundings = list() - - surroundings |= range(7, locate(T.x,T.y,T.z)) - surroundings |= range(7, locate(T.x+size_x,T.y,T.z)) - surroundings |= range(7, locate(T.x,T.y+size_y,T.z)) - surroundings |= range(7, locate(T.x+size_x,T.y+size_y,T.z)) - - if(locate(/area/mine/explored) in surroundings) // +5s are for view range - return 0 - - if(locate(/turf/space) in surroundings) - return 0 - - /* /vg/: Allow combining rooms. - if(locate(/area/asteroid/artifactroom) in surroundings) - return 0 - - if(locate(/turf/unsimulated/floor/asteroid) in surroundings) - return 0 - */ - - // /vg/: Stop spawning shit inside of the vox hideout - if(locate(/turf/simulated/wall) in surroundings && !ignore_walls) - return 0 - return 1 - -proc/make_mining_asteroid_secret() - var/turf/T = null - var/sanity = 0 - var/list/turfs = null - - turfs = get_area_turfs(/area/mine/unexplored) - - if(!turfs.len) - return 0 - - while(1) - sanity++ - if(sanity > 100) - testing("Tried to place complex too many times. Aborting.") - return 0 - - T=pick(turfs) - - var/complex_type=pick(mining_surprises) - var/mining_surprise/complex = new complex_type - - if(complex.spawn_complex(T)) - spawned_surprises += complex - return 1 - - return 0 - - +var/global/list/spawned_surprises = list() + +var/global/max_secret_rooms = 3 + +/* Le broken. +proc/admin_spawn_room_at_pos() + var/wall + var/floor + var/x = input("X position","X pos",usr.x) + var/y = input("Y position","Y pos",usr.y) + var/z = input("Z position","Z pos",usr.z) + var/x_len = input("Desired length.","Length",5) + var/y_len = input("Desired width.","Width",5) + var/clean = input("Delete existing items in area?" , "Clean area?", 0) + switch(alert("Wall type",null,"Reinforced wall","Regular wall","Resin wall")) + if("Reinforced wall") + wall=/turf/simulated/wall/r_wall + if("Regular wall") + wall=/turf/simulated/wall + if("Resin wall") + wall=/obj/effect/alien/resin + switch(alert("Floor type",null,"Regular floor","Reinforced floor")) + if("Regular floor") + floor=/turf/simulated/floor + if("Reinforced floor") + floor=/turf/simulated/floor/engine + if(x && y && z && wall && floor && x_len && y_len) + spawn_room(locate(x,y,z),x_len,y_len,wall,floor,clean) + return +*/ + +proc/check_complex_placement(var/turf/T,var/size_x,var/size_y,var/ignore_walls=0) + var/list/surroundings = list() + + surroundings |= range(7, locate(T.x,T.y,T.z)) + surroundings |= range(7, locate(T.x+size_x,T.y,T.z)) + surroundings |= range(7, locate(T.x,T.y+size_y,T.z)) + surroundings |= range(7, locate(T.x+size_x,T.y+size_y,T.z)) + + if(locate(/area/mine/explored) in surroundings) // +5s are for view range + return 0 + + if(locate(/turf/space) in surroundings) + return 0 + + /* /vg/: Allow combining rooms. + if(locate(/area/asteroid/artifactroom) in surroundings) + return 0 + + if(locate(/turf/unsimulated/floor/asteroid) in surroundings) + return 0 + */ + + // /vg/: Stop spawning shit inside of the vox hideout + if(locate(/turf/simulated/wall) in surroundings && !ignore_walls) + return 0 + return 1 + +proc/make_mining_asteroid_secret() + var/turf/T = null + var/sanity = 0 + var/list/turfs = null + + turfs = get_area_turfs(/area/mine/unexplored) + + if(!turfs.len) + return 0 + + while(1) + sanity++ + if(sanity > 100) + testing("Tried to place complex too many times. Aborting.") + return 0 + + T=pick(turfs) + + var/complex_type=pick(mining_surprises) + var/mining_surprise/complex = new complex_type + + if(complex.spawn_complex(T)) + spawned_surprises += complex + return 1 + + return 0 + + diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f0aadcafd1b..d0389b0aaca 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1,760 +1,760 @@ -var/global/list/del_profiling = list() -var/global/list/gdel_profiling = list() -var/global/list/ghdel_profiling = list() -/atom - layer = 2 - - var/ghost_read = 1 // All ghosts can read - var/ghost_write = 0 // Only aghosts can write - var/blessed=0 // Chaplain did his thing. (set by bless() proc, which is called by holywater) - - var/level = 2 - var/flags = FPRINT - var/list/fingerprints - var/list/fingerprintshidden - var/fingerprintslast = null - var/list/blood_DNA - var/blood_color - var/last_bumped = 0 - var/pass_flags = 0 - var/throwpass = 0 - var/germ_level = 0 // The higher the germ level, the more germ on the atom. - var/pressure_resistance = ONE_ATMOSPHERE - var/penetration_dampening = 5 //drains some of a projectile's penetration power whenever it goes through the atom - - ///Chemistry. - var/datum/reagents/reagents = null - - //Material datums - the fun way of doing things in a laggy manner - var/datum/materials/materials = null - var/list/starting_materials //starting set of mats - used in New(), you can set this to an empty list to have the datum be generated but not filled - - //var/chem_is_open_container = 0 - // replaced by OPENCONTAINER flags and atom/proc/is_open_container() - ///Chemistry. - - //Detective Work, used for the duplicate data points kept in the scanners - var/list/original_atom - - var/list/beams - - // EVENTS - ///////////////////////////// - // On Destroy() - var/event/on_destroyed - - // When this object moves. (args: loc) - var/event/on_moved - - var/labeled //Stupid and ugly way to do it, but the alternative would probably require rewriting everywhere a name is read. - var/min_harm_label = 0 //Minimum langth of harm-label to be effective. 0 means it cannot be harm-labeled. If any label should work, set this to 1 or 2. - var/harm_labeled = 0 //Length of current harm-label. 0 if it doesn't have one. - var/list/harm_label_examine //Messages that appears when examining the item if it is harm-labeled. Message in position 1 is if it is harm-labeled but the label is too short to work, while message in position 2 is if the harm-label works. - //var/harm_label_icon_state //Makes sense to have this, but I can't sprite. May be added later. - var/list/last_beamchecks // timings for beam checks. - var/ignoreinvert = 0 - var/forceinvertredraw = 0 - var/tempoverlay - var/timestopped - - -/atom/proc/beam_connect(var/obj/effect/beam/B) - if(!last_beamchecks) last_beamchecks = list() - if(!beams) beams = list() - if(!(B in beams)) - beams.Add(B) - return 1 - -/atom/proc/beam_disconnect(var/obj/effect/beam/B) - beams.Remove(B) - -/atom/proc/apply_beam_damage(var/obj/effect/beam/B) - return 1 - -/atom/proc/handle_beams() - return 1 - -/atom/proc/shake(var/xy, var/intensity, mob/user) //Zth. SHAKE IT. Vending machines' kick uses this - switch(xy) - if(1) - src.pixel_x = rand(-intensity, intensity) - if(2) - src.pixel_y = rand(-intensity, intensity) - if(3) - src.pixel_x = rand(-intensity, intensity) - src.pixel_y = rand(-intensity, intensity) - - spawn(2) - src.pixel_x = 0 - src.pixel_y = 0 - -// NOTE FROM AMATEUR CODER WHO STRUGGLED WITH RUNTIMES -// throw_impact is called multiple times when an item is thrown: see /atom/movable/proc/hit_check at atoms_movable.dm -// Do NOT delete an item as part of it's throw_impact unless you've checked the hit_atom is a turf, as that's effectively the last time throw_impact is called in a single throw. -// Otherwise, shit will runtime in the subsequent throw_impact calls. -/atom/proc/throw_impact(atom/hit_atom, var/speed, user) - if(istype(hit_atom,/mob/living)) - var/mob/living/M = hit_atom - M.hitby(src,speed,src.dir) - - log_attack("[hit_atom] ([M ? M.ckey : "what"]) was hit by [src] thrown by ([src.fingerprintslast])") - - else if(isobj(hit_atom)) - var/obj/O = hit_atom - if(!O.anchored) - step(O, src.dir) - O.hitby(src,speed) - - else if(isturf(hit_atom)) - var/turf/T = hit_atom - if(T.density) - spawn(2) - step(src, turn(src.dir, 180)) - if(istype(src,/mob/living)) - var/mob/living/M = src - M.take_organ_damage(10) - -/atom/proc/AddToProfiler() - // Memory usage profiling - N3X. - if (type in type_instances) - type_instances[type] = type_instances[type] + 1 - else - type_instances[type] = 1 - -/atom/proc/DeleteFromProfiler() - // Memory usage profiling - N3X. - if (type in type_instances) - type_instances[type] = type_instances[type] - 1 - else - type_instances[type] = 0 - WARNING("Type [type] does not inherit /atom/New(). Please ensure ..() is called, or that the type calls AddToProfiler().") - -/atom/Del() - DeleteFromProfiler() - ..() - -/atom/Destroy() - if(reagents) - qdel(reagents) - reagents = null - - if(materials) - returnToPool(materials) - - // Idea by ChuckTheSheep to make the object even more unreferencable. - invisibility = 101 - INVOKE_EVENT(on_destroyed, list()) // No args. - if(on_moved) - on_moved.holder = null - on_moved = null - if(on_destroyed) - on_destroyed.holder = null - on_destroyed = null - if(istype(beams, /list) && beams.len) beams.len = 0 - /*if(istype(beams) && beams.len) - for(var/obj/effect/beam/B in beams) - if(B && B.target == src) - B.target = null - if(B.master && B.master.target == src) - B.master.target = null - beams.len = 0 - */ - -/atom/New() - on_destroyed = new("owner"=src) - on_moved = new("owner"=src) - . = ..() - if(starting_materials) - materials = getFromPool(/datum/materials, src) - for(var/matID in starting_materials) - materials.addAmount(matID, starting_materials[matID]) - AddToProfiler() - -/atom/proc/assume_air(datum/gas_mixture/giver) - return null - -/atom/proc/remove_air(amount) - return null - -/atom/proc/return_air() - if(loc) - return loc.return_air() - else - return null - -/atom/proc/check_eye(user as mob) - if (istype(user, /mob/living/silicon/ai)) // WHYYYY - return 1 - return - -/atom/proc/on_reagent_change() - return - -/atom/proc/Bumped(AM as mob|obj) - return - -// Convenience proc to see if a container is open for chemistry handling -// returns true if open -// false if closed -/atom/proc/is_open_container() - return flags & OPENCONTAINER - -/*//Convenience proc to see whether a container can be accessed in a certain way. - - proc/can_subract_container() - return flags & EXTRACT_CONTAINER - - proc/can_add_container() - return flags & INSERT_CONTAINER -*/ - -/atom/proc/allow_drop() - return 1 - -/atom/proc/CheckExit() - return 1 - -/atom/proc/HasProximity(atom/movable/AM as mob|obj) //IF you want to use this, the atom must have the PROXMOVE flag, and the moving atom must also have the PROXMOVE flag currently to help with lag - return - -/atom/proc/emp_act(var/severity) - return - -/atom/proc/singuloCanEat() - return 1 - -/atom/proc/bullet_act(var/obj/item/projectile/Proj) - return 0 - -/atom/proc/in_contents_of(container)//can take class or object instance as argument - if(ispath(container)) - if(istype(src.loc, container)) - return 1 - else if(src in container) - return 1 - return - -/atom/proc/projectile_check() - return - -/* - * atom/proc/search_contents_for(path,list/filter_path=null) - * Recursevly searches all atom contens (including contents contents and so on). - * - * ARGS: path - search atom contents for atoms of this type - * list/filter_path - if set, contents of atoms not of types in this list are excluded from search. - * - * RETURNS: list of found atoms - */ - -/atom/proc/search_contents_for(path,list/filter_path=null) - var/list/found = list() - for(var/atom/A in src) - if(istype(A, path)) - found += A - if(filter_path) - var/pass = 0 - for(var/type in filter_path) - pass |= istype(A, type) - if(!pass) - continue - if(A.contents.len) - found += A.search_contents_for(path,filter_path) - return found - -/* - * atom/proc/contains_atom_from_list(var/list/L) - * Basically same as above but it takes a list of paths (like list(/mob/living/,/obj/machinery/something,...)) - * RETURNS: a found atom - */ -/atom/proc/contains_atom_from_list(var/list/L) - for(var/atom/A in src) - for(var/T in L) - if(istype(A,T)) - return A - if(A.contents.len) - var/atom/R = A.contains_atom_from_list(L) - if(R) - return R - return 0 - - -/* -Beam code by Gunbuddy - -Beam() proc will only allow one beam to come from a source at a time. Attempting to call it more than -once at a time per source will cause graphical errors. -Also, the icon used for the beam will have to be vertical and 32x32. -The math involved assumes that the icon is vertical to begin with so unless you want to adjust the math, -its easier to just keep the beam vertical. -*/ -/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10) - //BeamTarget represents the target for the beam, basically just means the other end. - //Time is the duration to draw the beam - //Icon is obviously which icon to use for the beam, default is beam.dmi - //Icon_state is what icon state is used. Default is b_beam which is a blue beam. - //Maxdistance is the longest range the beam will persist before it gives up. - var/EndTime=world.time+time - var/broken = 0 - var/obj/item/projectile/beam/lightning/light = getFromPool(/obj/item/projectile/beam/lightning) - while(BeamTarget&&world.timelength) - var/icon/II=new(icon,icon_state) - II.DrawBox(null,1,(length-N),32,32) - II.Turn(Angle) - X.icon=II - else X.icon=I - var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) - var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) - if(DX==0) Pixel_x=0 - if(DY==0) Pixel_y=0 - if(Pixel_x>32) - for(var/a=0, a<=Pixel_x,a+=32) - X.x++ - Pixel_x-=32 - if(Pixel_x<-32) - for(var/a=0, a>=Pixel_x,a-=32) - X.x-- - Pixel_x+=32 - if(Pixel_y>32) - for(var/a=0, a<=Pixel_y,a+=32) - X.y++ - Pixel_y-=32 - if(Pixel_y<-32) - for(var/a=0, a>=Pixel_y,a-=32) - X.y-- - Pixel_y+=32 - X.pixel_x=Pixel_x - X.pixel_y=Pixel_y - var/turf/TT = get_turf(X.loc) - if(TT.density) - qdel(X) - break - for(var/obj/O in TT) - if(!O.CanPass(light)) - broken = 1 - break - else if(O.density) - broken = 1 - break - if(broken) - qdel(X) - break - sleep(3) //Changing this to a lower value will cause the beam to follow more smoothly with movement, but it will also be more laggy. - //I've found that 3 ticks provided a nice balance for my use. - for(var/obj/effect/overlay/beam/O in orange(10,src)) if(O.BeamSource==src) returnToPool(O) - -//Woo hoo. Overtime -//All atoms -/atom/proc/examine(mob/user, var/size = "") - //This reformat names to get a/an properly working on item descriptions when they are bloody - var/f_name = "\a [src]." - if(src.blood_DNA && src.blood_DNA.len) - if(gender == PLURAL) - f_name = "some " - else - f_name = "a " - f_name += "blood-stained [name]!" - - to_chat(user, "\icon[src] That's [f_name]" + size) - if(desc) - to_chat(user, desc) - - if(reagents && is_open_container() && !ismob(src)) //is_open_container() isn't really the right proc for this, but w/e - if(get_dist(user,src) > 3) - to_chat(user, "You can't make out the contents.") - else - to_chat(user, "It contains:") - if(!user.hallucinating()) - if(reagents.reagent_list.len) - for(var/datum/reagent/R in reagents.reagent_list) - to_chat(user, "[R.volume] units of [R.name]") - else - to_chat(user, "Nothing.") - - else //Show stupid things to hallucinating mobs - var/list/fake_reagents = list("Water", "Orange juice", "Banana juice", "Tungsten", "Chloral Hydrate", "Helium",\ - "Sea water", "Energy drink", "Gushin' Granny", "Salt", "Sugar", "something yellow", "something red", "something blue",\ - "something suspicious", "something smelly", "something sweet", "Soda", "something that reminds you of home",\ - "Chef's Special") - for(var/i, i < rand(1,10), i++) - var/fake_amount = rand(1,30) - var/fake_reagent = pick(fake_reagents) - fake_reagents -= fake_reagent - - to_chat(user, "[fake_amount] units of [fake_reagent]") - if(on_fire) - user.simple_message("OH SHIT! IT'S ON FIRE!",\ - "It's on fire, man.") - - if(min_harm_label && harm_labeled) - if(harm_labeled < min_harm_label) - to_chat(user, harm_label_examine[1]) - else - to_chat(user, harm_label_examine[2]) - return - -// /atom/proc/MouseDrop_T() -// return - -/atom/proc/relaymove() - return - -// Severity is actually "distance". -// 1 is pretty much just del(src). -// 2 is moderate damage. -// 3 is light damage. -// -// child is set to the child object that exploded, if available. -/atom/proc/ex_act(var/severity, var/child=null) - return - -/atom/proc/mech_drill_act(var/severity, var/child=null) - return ex_act(severity, child) - -/atom/proc/blob_act() - return - -/* -/atom/proc/attack_hand(mob/user as mob) - return - -/atom/proc/attack_paw(mob/user as mob) - return - -/atom/proc/attack_ai(mob/user as mob) - return - -/atom/proc/attack_robot(mob/user as mob) - attack_ai(user) - return - -/atom/proc/attack_animal(mob/user as mob) - return - -/atom/proc/attack_ghost(mob/user as mob) - var/ghost_flags = 0 - if(ghost_read) - ghost_flags |= PERMIT_ALL - if(canGhostRead(user,src,ghost_flags)) - src.attack_ai(user) - else - src.examine() - return - -/atom/proc/attack_admin(mob/user as mob) - if(!user || !user.client || !user.client.holder) - return - attack_hand(user) - -//for aliens, it works the same as monkeys except for alien-> mob interactions which will be defined in the -//appropiate mob files -/atom/proc/attack_alien(mob/user as mob) - src.attack_paw(user) - return - -/atom/proc/attack_larva(mob/user as mob) - return - -// for slimes -/atom/proc/attack_slime(mob/user as mob) - return - -/atom/proc/hand_h(mob/user as mob) //human (hand) - restrained - return - -/atom/proc/hand_p(mob/user as mob) //monkey (paw) - restrained - return - -/atom/proc/hand_a(mob/user as mob) //AI - restrained - return - -/atom/proc/hand_r(mob/user as mob) //Cyborg (robot) - restrained - src.hand_a(user) - return - -/atom/proc/hand_al(mob/user as mob) //alien - restrained - src.hand_p(user) - return - -/atom/proc/hand_m(mob/user as mob) //slime - restrained - return -*/ - -/atom/proc/singularity_act() - return - -//Called when a shuttle collides with an atom -/atom/proc/shuttle_act(var/datum/shuttle/S) - return - -//Called on every object in a shuttle which rotates -/atom/proc/shuttle_rotate(var/angle) - src.dir = turn(src.dir, -angle) - - if(canSmoothWith) //Smooth the smoothable - spawn //Usually when this is called right after an atom is moved. Not having this "spawn" here will cause this atom to look for its neighbours BEFORE they have finished moving, causing bad stuff. - relativewall() - relativewall_neighbours() - - if(pixel_x || pixel_y) - var/cosine = cos(angle) - var/sine = sin(angle) - var/newX = (cosine * pixel_x) + (sine * pixel_y) - var/newY = -(sine * pixel_x) + (cosine* pixel_y) - - pixel_x = newX - pixel_y = newY - -/atom/proc/singularity_pull() - return - -/atom/proc/emag_act() - return - -/atom/proc/hitby(atom/movable/AM as mob|obj) - return - -/* -/atom/proc/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (!(istype(W, /obj/item/weapon/grab) ) && !(istype(W, /obj/item/weapon/plastique)) && !(istype(W, /obj/item/weapon/reagent_containers/spray)) && !(istype(W, /obj/item/weapon/packageWrap)) && !istype(W, /obj/item/device/detective_scanner)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - to_chat(O, "[src] has been hit by [user] with [W]") - return -*/ -/atom/proc/add_hiddenprint(mob/living/M as mob) - if(isnull(M)) return - if(isnull(M.key)) return - if (!( src.flags ) & FPRINT) - return - if (ishuman(M)) - var/mob/living/carbon/human/H = M - if (!istype(H.dna, /datum/dna)) - return 0 - if (H.gloves) - if(src.fingerprintslast != H.key) - src.fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key) - src.fingerprintslast = H.key - return 0 - if (!( src.fingerprints )) - if(src.fingerprintslast != H.key) - src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key) - src.fingerprintslast = H.key - return 1 - else - if(src.fingerprintslast != M.key) - src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key) - src.fingerprintslast = M.key - return - -/atom/proc/add_fingerprint(mob/living/M as mob) - if(isnull(M)) return - if(isAI(M)) return - if(isnull(M.key)) return - if (!( src.flags ) & FPRINT) - return - if (ishuman(M)) - //Add the list if it does not exist. - if(!fingerprintshidden) - fingerprintshidden = list() - - //Fibers~ - add_fibers(M) - - //He has no prints! - if (M_FINGERPRINTS in M.mutations) - if(fingerprintslast != M.key) - fingerprintshidden += "(Has no fingerprints) Real name: [M.real_name], Key: [M.key]" - fingerprintslast = M.key - return 0 //Now, lets get to the dirty work. - //First, make sure their DNA makes sense. - var/mob/living/carbon/human/H = M - if (!istype(H.dna, /datum/dna) || !H.dna.uni_identity || (length(H.dna.uni_identity) != 32)) - if(!istype(H.dna, /datum/dna)) - H.dna = new /datum/dna(null) - H.dna.real_name = H.real_name - H.check_dna() - - //Now, deal with gloves. - if (H.gloves && H.gloves != src) - if(fingerprintslast != H.key) - fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key) - fingerprintslast = H.key - H.gloves.add_fingerprint(M) - - //Deal with gloves the pass finger/palm prints. - if(H.gloves != src) - if(prob(75) && istype(H.gloves, /obj/item/clothing/gloves/latex)) - return 0 - else if(H.gloves && !istype(H.gloves, /obj/item/clothing/gloves/latex)) - return 0 - - //More adminstuffz - if(fingerprintslast != H.key) - fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key) - fingerprintslast = H.key - - //Make the list if it does not exist. - if(!fingerprints) - fingerprints = list() - - //Hash this shit. - var/full_print = md5(H.dna.uni_identity) - - // Add the fingerprints - fingerprints[full_print] = full_print - - return 1 - else - //Smudge up dem prints some - if(fingerprintslast != M.key) - fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key) - fingerprintslast = M.key - - //Cleaning up shit. - if(fingerprints && !fingerprints.len) - del(fingerprints) - return - - -/atom/proc/transfer_fingerprints_to(var/atom/A) - if(!istype(A.fingerprints,/list)) - A.fingerprints = list() - if(!istype(A.fingerprintshidden,/list)) - A.fingerprintshidden = list() - - //skytodo - //A.fingerprints |= fingerprints //detective - //A.fingerprintshidden |= fingerprintshidden //admin - if(fingerprints) - A.fingerprints |= fingerprints.Copy() //detective - if(fingerprintshidden && istype(fingerprintshidden)) - A.fingerprintshidden |= fingerprintshidden.Copy() //admin A.fingerprintslast = fingerprintslast - - -//returns 1 if made bloody, returns 0 otherwise -/atom/proc/add_blood(mob/living/carbon/human/M as mob) - .=1 - if(!M)//if the blood is of non-human source - if(!blood_DNA || !istype(blood_DNA, /list)) - blood_DNA = list() - blood_color = "#A10808" - return 1 - if (!( istype(M, /mob/living/carbon/human) )) - return 0 - if (!istype(M.dna, /datum/dna)) - M.dna = new /datum/dna(null) - M.dna.real_name = M.real_name - M.check_dna() - if (!( src.flags ) & FPRINT) - return 0 - if(!blood_DNA || !istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it. - blood_DNA = list() - blood_color = "#A10808" - if (M.species) - blood_color = M.species.blood_color - //adding blood to humans - else if (istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - //if this blood isn't already in the list, add it - if(blood_DNA[H.dna.unique_enzymes]) - return 0 //already bloodied with this blood. Cannot add more. - blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - H.update_inv_gloves() //handles bloody hands overlays and updating - return 1 //we applied blood to the item - return - -/atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0) - if( istype(src, /turf/simulated) ) - var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src) - - // Make toxins vomit look different - if(toxvomit) - this.icon_state = "vomittox_[pick(1,4)]" - - -/atom/proc/clean_blood() - src.germ_level = 0 - if(istype(blood_DNA, /list)) - //del(blood_DNA) - blood_DNA.len = 0 - return 1 - - -/atom/proc/get_global_map_pos() - if(!islist(global_map) || isemptylist(global_map)) return - var/cur_x = null - var/cur_y = null - var/list/y_arr = null - for(cur_x=1,cur_x<=global_map.len,cur_x++) - y_arr = global_map[cur_x] - cur_y = y_arr.Find(src.z) - if(cur_y) - break -// to_chat(world, "X = [cur_x]; Y = [cur_y]") - if(cur_x && cur_y) - return list("x"=cur_x,"y"=cur_y) - else - return 0 - -/atom/proc/checkpass(passflag) - return pass_flags&passflag - -/datum/proc/setGender(gend = FEMALE) - if(!("gender" in vars)) - CRASH("Oh shit you stupid nigger the [src] doesn't have a gender variable.") - if(ishuman(src)) - ASSERT(gend != PLURAL && gend != NEUTER) - src:gender = gend - -/atom/setGender(gend = FEMALE) - gender = gend - -/mob/living/carbon/human/setGender(gend = FEMALE) - if(gend == PLURAL || gend == NEUTER || (gend != FEMALE && gend != MALE)) - CRASH("SOMEBODY SET A BAD GENDER ON [src] [gend]") - var/old_gender = src.gender - src.gender = gend - testing("Set [src]'s gender to [gend], old gender [old_gender] previous gender [prev_gender]") - -/atom/proc/mop_act(obj/item/weapon/mop/M, mob/user) - return 0 - -/atom/proc/change_area(var/area/oldarea, var/area/newarea) - if(istype(oldarea)) - oldarea = "[oldarea.name]" - if(istype(newarea)) - newarea = "[newarea.name]" - -//Called in /spell/aoe_turf/boo/cast() (code/modules/mob/dead/observer/spells.dm) -/atom/proc/spook() - if(blessed) - return 0 - return 1 - -//Called on holy_water's reaction_obj() -/atom/proc/bless() - blessed = 1 - -/atom/proc/update_icon() +var/global/list/del_profiling = list() +var/global/list/gdel_profiling = list() +var/global/list/ghdel_profiling = list() +/atom + layer = 2 + + var/ghost_read = 1 // All ghosts can read + var/ghost_write = 0 // Only aghosts can write + var/blessed=0 // Chaplain did his thing. (set by bless() proc, which is called by holywater) + + var/level = 2 + var/flags = FPRINT + var/list/fingerprints + var/list/fingerprintshidden + var/fingerprintslast = null + var/list/blood_DNA + var/blood_color + var/last_bumped = 0 + var/pass_flags = 0 + var/throwpass = 0 + var/germ_level = 0 // The higher the germ level, the more germ on the atom. + var/pressure_resistance = ONE_ATMOSPHERE + var/penetration_dampening = 5 //drains some of a projectile's penetration power whenever it goes through the atom + + ///Chemistry. + var/datum/reagents/reagents = null + + //Material datums - the fun way of doing things in a laggy manner + var/datum/materials/materials = null + var/list/starting_materials //starting set of mats - used in New(), you can set this to an empty list to have the datum be generated but not filled + + //var/chem_is_open_container = 0 + // replaced by OPENCONTAINER flags and atom/proc/is_open_container() + ///Chemistry. + + //Detective Work, used for the duplicate data points kept in the scanners + var/list/original_atom + + var/list/beams + + // EVENTS + ///////////////////////////// + // On Destroy() + var/event/on_destroyed + + // When this object moves. (args: loc) + var/event/on_moved + + var/labeled //Stupid and ugly way to do it, but the alternative would probably require rewriting everywhere a name is read. + var/min_harm_label = 0 //Minimum langth of harm-label to be effective. 0 means it cannot be harm-labeled. If any label should work, set this to 1 or 2. + var/harm_labeled = 0 //Length of current harm-label. 0 if it doesn't have one. + var/list/harm_label_examine //Messages that appears when examining the item if it is harm-labeled. Message in position 1 is if it is harm-labeled but the label is too short to work, while message in position 2 is if the harm-label works. + //var/harm_label_icon_state //Makes sense to have this, but I can't sprite. May be added later. + var/list/last_beamchecks // timings for beam checks. + var/ignoreinvert = 0 + var/forceinvertredraw = 0 + var/tempoverlay + var/timestopped + + +/atom/proc/beam_connect(var/obj/effect/beam/B) + if(!last_beamchecks) last_beamchecks = list() + if(!beams) beams = list() + if(!(B in beams)) + beams.Add(B) + return 1 + +/atom/proc/beam_disconnect(var/obj/effect/beam/B) + beams.Remove(B) + +/atom/proc/apply_beam_damage(var/obj/effect/beam/B) + return 1 + +/atom/proc/handle_beams() + return 1 + +/atom/proc/shake(var/xy, var/intensity, mob/user) //Zth. SHAKE IT. Vending machines' kick uses this + switch(xy) + if(1) + src.pixel_x = rand(-intensity, intensity) + if(2) + src.pixel_y = rand(-intensity, intensity) + if(3) + src.pixel_x = rand(-intensity, intensity) + src.pixel_y = rand(-intensity, intensity) + + spawn(2) + src.pixel_x = 0 + src.pixel_y = 0 + +// NOTE FROM AMATEUR CODER WHO STRUGGLED WITH RUNTIMES +// throw_impact is called multiple times when an item is thrown: see /atom/movable/proc/hit_check at atoms_movable.dm +// Do NOT delete an item as part of it's throw_impact unless you've checked the hit_atom is a turf, as that's effectively the last time throw_impact is called in a single throw. +// Otherwise, shit will runtime in the subsequent throw_impact calls. +/atom/proc/throw_impact(atom/hit_atom, var/speed, user) + if(istype(hit_atom,/mob/living)) + var/mob/living/M = hit_atom + M.hitby(src,speed,src.dir) + + log_attack("[hit_atom] ([M ? M.ckey : "what"]) was hit by [src] thrown by ([src.fingerprintslast])") + + else if(isobj(hit_atom)) + var/obj/O = hit_atom + if(!O.anchored) + step(O, src.dir) + O.hitby(src,speed) + + else if(isturf(hit_atom)) + var/turf/T = hit_atom + if(T.density) + spawn(2) + step(src, turn(src.dir, 180)) + if(istype(src,/mob/living)) + var/mob/living/M = src + M.take_organ_damage(10) + +/atom/proc/AddToProfiler() + // Memory usage profiling - N3X. + if (type in type_instances) + type_instances[type] = type_instances[type] + 1 + else + type_instances[type] = 1 + +/atom/proc/DeleteFromProfiler() + // Memory usage profiling - N3X. + if (type in type_instances) + type_instances[type] = type_instances[type] - 1 + else + type_instances[type] = 0 + WARNING("Type [type] does not inherit /atom/New(). Please ensure ..() is called, or that the type calls AddToProfiler().") + +/atom/Del() + DeleteFromProfiler() + ..() + +/atom/Destroy() + if(reagents) + qdel(reagents) + reagents = null + + if(materials) + returnToPool(materials) + + // Idea by ChuckTheSheep to make the object even more unreferencable. + invisibility = 101 + INVOKE_EVENT(on_destroyed, list()) // No args. + if(on_moved) + on_moved.holder = null + on_moved = null + if(on_destroyed) + on_destroyed.holder = null + on_destroyed = null + if(istype(beams, /list) && beams.len) beams.len = 0 + /*if(istype(beams) && beams.len) + for(var/obj/effect/beam/B in beams) + if(B && B.target == src) + B.target = null + if(B.master && B.master.target == src) + B.master.target = null + beams.len = 0 + */ + +/atom/New() + on_destroyed = new("owner"=src) + on_moved = new("owner"=src) + . = ..() + if(starting_materials) + materials = getFromPool(/datum/materials, src) + for(var/matID in starting_materials) + materials.addAmount(matID, starting_materials[matID]) + AddToProfiler() + +/atom/proc/assume_air(datum/gas_mixture/giver) + return null + +/atom/proc/remove_air(amount) + return null + +/atom/proc/return_air() + if(loc) + return loc.return_air() + else + return null + +/atom/proc/check_eye(user as mob) + if (istype(user, /mob/living/silicon/ai)) // WHYYYY + return 1 + return + +/atom/proc/on_reagent_change() + return + +/atom/proc/Bumped(AM as mob|obj) + return + +// Convenience proc to see if a container is open for chemistry handling +// returns true if open +// false if closed +/atom/proc/is_open_container() + return flags & OPENCONTAINER + +/*//Convenience proc to see whether a container can be accessed in a certain way. + + proc/can_subract_container() + return flags & EXTRACT_CONTAINER + + proc/can_add_container() + return flags & INSERT_CONTAINER +*/ + +/atom/proc/allow_drop() + return 1 + +/atom/proc/CheckExit() + return 1 + +/atom/proc/HasProximity(atom/movable/AM as mob|obj) //IF you want to use this, the atom must have the PROXMOVE flag, and the moving atom must also have the PROXMOVE flag currently to help with lag + return + +/atom/proc/emp_act(var/severity) + return + +/atom/proc/singuloCanEat() + return 1 + +/atom/proc/bullet_act(var/obj/item/projectile/Proj) + return 0 + +/atom/proc/in_contents_of(container)//can take class or object instance as argument + if(ispath(container)) + if(istype(src.loc, container)) + return 1 + else if(src in container) + return 1 + return + +/atom/proc/projectile_check() + return + +/* + * atom/proc/search_contents_for(path,list/filter_path=null) + * Recursevly searches all atom contens (including contents contents and so on). + * + * ARGS: path - search atom contents for atoms of this type + * list/filter_path - if set, contents of atoms not of types in this list are excluded from search. + * + * RETURNS: list of found atoms + */ + +/atom/proc/search_contents_for(path,list/filter_path=null) + var/list/found = list() + for(var/atom/A in src) + if(istype(A, path)) + found += A + if(filter_path) + var/pass = 0 + for(var/type in filter_path) + pass |= istype(A, type) + if(!pass) + continue + if(A.contents.len) + found += A.search_contents_for(path,filter_path) + return found + +/* + * atom/proc/contains_atom_from_list(var/list/L) + * Basically same as above but it takes a list of paths (like list(/mob/living/,/obj/machinery/something,...)) + * RETURNS: a found atom + */ +/atom/proc/contains_atom_from_list(var/list/L) + for(var/atom/A in src) + for(var/T in L) + if(istype(A,T)) + return A + if(A.contents.len) + var/atom/R = A.contains_atom_from_list(L) + if(R) + return R + return 0 + + +/* +Beam code by Gunbuddy + +Beam() proc will only allow one beam to come from a source at a time. Attempting to call it more than +once at a time per source will cause graphical errors. +Also, the icon used for the beam will have to be vertical and 32x32. +The math involved assumes that the icon is vertical to begin with so unless you want to adjust the math, +its easier to just keep the beam vertical. +*/ +/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10) + //BeamTarget represents the target for the beam, basically just means the other end. + //Time is the duration to draw the beam + //Icon is obviously which icon to use for the beam, default is beam.dmi + //Icon_state is what icon state is used. Default is b_beam which is a blue beam. + //Maxdistance is the longest range the beam will persist before it gives up. + var/EndTime=world.time+time + var/broken = 0 + var/obj/item/projectile/beam/lightning/light = getFromPool(/obj/item/projectile/beam/lightning) + while(BeamTarget&&world.timelength) + var/icon/II=new(icon,icon_state) + II.DrawBox(null,1,(length-N),32,32) + II.Turn(Angle) + X.icon=II + else X.icon=I + var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) + var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) + if(DX==0) Pixel_x=0 + if(DY==0) Pixel_y=0 + if(Pixel_x>32) + for(var/a=0, a<=Pixel_x,a+=32) + X.x++ + Pixel_x-=32 + if(Pixel_x<-32) + for(var/a=0, a>=Pixel_x,a-=32) + X.x-- + Pixel_x+=32 + if(Pixel_y>32) + for(var/a=0, a<=Pixel_y,a+=32) + X.y++ + Pixel_y-=32 + if(Pixel_y<-32) + for(var/a=0, a>=Pixel_y,a-=32) + X.y-- + Pixel_y+=32 + X.pixel_x=Pixel_x + X.pixel_y=Pixel_y + var/turf/TT = get_turf(X.loc) + if(TT.density) + qdel(X) + break + for(var/obj/O in TT) + if(!O.CanPass(light)) + broken = 1 + break + else if(O.density) + broken = 1 + break + if(broken) + qdel(X) + break + sleep(3) //Changing this to a lower value will cause the beam to follow more smoothly with movement, but it will also be more laggy. + //I've found that 3 ticks provided a nice balance for my use. + for(var/obj/effect/overlay/beam/O in orange(10,src)) if(O.BeamSource==src) returnToPool(O) + +//Woo hoo. Overtime +//All atoms +/atom/proc/examine(mob/user, var/size = "") + //This reformat names to get a/an properly working on item descriptions when they are bloody + var/f_name = "\a [src]." + if(src.blood_DNA && src.blood_DNA.len) + if(gender == PLURAL) + f_name = "some " + else + f_name = "a " + f_name += "blood-stained [name]!" + + to_chat(user, "\icon[src] That's [f_name]" + size) + if(desc) + to_chat(user, desc) + + if(reagents && is_open_container() && !ismob(src)) //is_open_container() isn't really the right proc for this, but w/e + if(get_dist(user,src) > 3) + to_chat(user, "You can't make out the contents.") + else + to_chat(user, "It contains:") + if(!user.hallucinating()) + if(reagents.reagent_list.len) + for(var/datum/reagent/R in reagents.reagent_list) + to_chat(user, "[R.volume] units of [R.name]") + else + to_chat(user, "Nothing.") + + else //Show stupid things to hallucinating mobs + var/list/fake_reagents = list("Water", "Orange juice", "Banana juice", "Tungsten", "Chloral Hydrate", "Helium",\ + "Sea water", "Energy drink", "Gushin' Granny", "Salt", "Sugar", "something yellow", "something red", "something blue",\ + "something suspicious", "something smelly", "something sweet", "Soda", "something that reminds you of home",\ + "Chef's Special") + for(var/i, i < rand(1,10), i++) + var/fake_amount = rand(1,30) + var/fake_reagent = pick(fake_reagents) + fake_reagents -= fake_reagent + + to_chat(user, "[fake_amount] units of [fake_reagent]") + if(on_fire) + user.simple_message("OH SHIT! IT'S ON FIRE!",\ + "It's on fire, man.") + + if(min_harm_label && harm_labeled) + if(harm_labeled < min_harm_label) + to_chat(user, harm_label_examine[1]) + else + to_chat(user, harm_label_examine[2]) + return + +// /atom/proc/MouseDrop_T() +// return + +/atom/proc/relaymove() + return + +// Severity is actually "distance". +// 1 is pretty much just del(src). +// 2 is moderate damage. +// 3 is light damage. +// +// child is set to the child object that exploded, if available. +/atom/proc/ex_act(var/severity, var/child=null) + return + +/atom/proc/mech_drill_act(var/severity, var/child=null) + return ex_act(severity, child) + +/atom/proc/blob_act() + return + +/* +/atom/proc/attack_hand(mob/user as mob) + return + +/atom/proc/attack_paw(mob/user as mob) + return + +/atom/proc/attack_ai(mob/user as mob) + return + +/atom/proc/attack_robot(mob/user as mob) + attack_ai(user) + return + +/atom/proc/attack_animal(mob/user as mob) + return + +/atom/proc/attack_ghost(mob/user as mob) + var/ghost_flags = 0 + if(ghost_read) + ghost_flags |= PERMIT_ALL + if(canGhostRead(user,src,ghost_flags)) + src.attack_ai(user) + else + src.examine() + return + +/atom/proc/attack_admin(mob/user as mob) + if(!user || !user.client || !user.client.holder) + return + attack_hand(user) + +//for aliens, it works the same as monkeys except for alien-> mob interactions which will be defined in the +//appropiate mob files +/atom/proc/attack_alien(mob/user as mob) + src.attack_paw(user) + return + +/atom/proc/attack_larva(mob/user as mob) + return + +// for slimes +/atom/proc/attack_slime(mob/user as mob) + return + +/atom/proc/hand_h(mob/user as mob) //human (hand) - restrained + return + +/atom/proc/hand_p(mob/user as mob) //monkey (paw) - restrained + return + +/atom/proc/hand_a(mob/user as mob) //AI - restrained + return + +/atom/proc/hand_r(mob/user as mob) //Cyborg (robot) - restrained + src.hand_a(user) + return + +/atom/proc/hand_al(mob/user as mob) //alien - restrained + src.hand_p(user) + return + +/atom/proc/hand_m(mob/user as mob) //slime - restrained + return +*/ + +/atom/proc/singularity_act() + return + +//Called when a shuttle collides with an atom +/atom/proc/shuttle_act(var/datum/shuttle/S) + return + +//Called on every object in a shuttle which rotates +/atom/proc/shuttle_rotate(var/angle) + src.dir = turn(src.dir, -angle) + + if(canSmoothWith) //Smooth the smoothable + spawn //Usually when this is called right after an atom is moved. Not having this "spawn" here will cause this atom to look for its neighbours BEFORE they have finished moving, causing bad stuff. + relativewall() + relativewall_neighbours() + + if(pixel_x || pixel_y) + var/cosine = cos(angle) + var/sine = sin(angle) + var/newX = (cosine * pixel_x) + (sine * pixel_y) + var/newY = -(sine * pixel_x) + (cosine* pixel_y) + + pixel_x = newX + pixel_y = newY + +/atom/proc/singularity_pull() + return + +/atom/proc/emag_act() + return + +/atom/proc/hitby(atom/movable/AM as mob|obj) + return + +/* +/atom/proc/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (!(istype(W, /obj/item/weapon/grab) ) && !(istype(W, /obj/item/weapon/plastique)) && !(istype(W, /obj/item/weapon/reagent_containers/spray)) && !(istype(W, /obj/item/weapon/packageWrap)) && !istype(W, /obj/item/device/detective_scanner)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + to_chat(O, "[src] has been hit by [user] with [W]") + return +*/ +/atom/proc/add_hiddenprint(mob/living/M as mob) + if(isnull(M)) return + if(isnull(M.key)) return + if (!( src.flags ) & FPRINT) + return + if (ishuman(M)) + var/mob/living/carbon/human/H = M + if (!istype(H.dna, /datum/dna)) + return 0 + if (H.gloves) + if(src.fingerprintslast != H.key) + src.fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key) + src.fingerprintslast = H.key + return 0 + if (!( src.fingerprints )) + if(src.fingerprintslast != H.key) + src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key) + src.fingerprintslast = H.key + return 1 + else + if(src.fingerprintslast != M.key) + src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key) + src.fingerprintslast = M.key + return + +/atom/proc/add_fingerprint(mob/living/M as mob) + if(isnull(M)) return + if(isAI(M)) return + if(isnull(M.key)) return + if (!( src.flags ) & FPRINT) + return + if (ishuman(M)) + //Add the list if it does not exist. + if(!fingerprintshidden) + fingerprintshidden = list() + + //Fibers~ + add_fibers(M) + + //He has no prints! + if (M_FINGERPRINTS in M.mutations) + if(fingerprintslast != M.key) + fingerprintshidden += "(Has no fingerprints) Real name: [M.real_name], Key: [M.key]" + fingerprintslast = M.key + return 0 //Now, lets get to the dirty work. + //First, make sure their DNA makes sense. + var/mob/living/carbon/human/H = M + if (!istype(H.dna, /datum/dna) || !H.dna.uni_identity || (length(H.dna.uni_identity) != 32)) + if(!istype(H.dna, /datum/dna)) + H.dna = new /datum/dna(null) + H.dna.real_name = H.real_name + H.check_dna() + + //Now, deal with gloves. + if (H.gloves && H.gloves != src) + if(fingerprintslast != H.key) + fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key) + fingerprintslast = H.key + H.gloves.add_fingerprint(M) + + //Deal with gloves the pass finger/palm prints. + if(H.gloves != src) + if(prob(75) && istype(H.gloves, /obj/item/clothing/gloves/latex)) + return 0 + else if(H.gloves && !istype(H.gloves, /obj/item/clothing/gloves/latex)) + return 0 + + //More adminstuffz + if(fingerprintslast != H.key) + fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key) + fingerprintslast = H.key + + //Make the list if it does not exist. + if(!fingerprints) + fingerprints = list() + + //Hash this shit. + var/full_print = md5(H.dna.uni_identity) + + // Add the fingerprints + fingerprints[full_print] = full_print + + return 1 + else + //Smudge up dem prints some + if(fingerprintslast != M.key) + fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key) + fingerprintslast = M.key + + //Cleaning up shit. + if(fingerprints && !fingerprints.len) + del(fingerprints) + return + + +/atom/proc/transfer_fingerprints_to(var/atom/A) + if(!istype(A.fingerprints,/list)) + A.fingerprints = list() + if(!istype(A.fingerprintshidden,/list)) + A.fingerprintshidden = list() + + //skytodo + //A.fingerprints |= fingerprints //detective + //A.fingerprintshidden |= fingerprintshidden //admin + if(fingerprints) + A.fingerprints |= fingerprints.Copy() //detective + if(fingerprintshidden && istype(fingerprintshidden)) + A.fingerprintshidden |= fingerprintshidden.Copy() //admin A.fingerprintslast = fingerprintslast + + +//returns 1 if made bloody, returns 0 otherwise +/atom/proc/add_blood(mob/living/carbon/human/M as mob) + .=1 + if(!M)//if the blood is of non-human source + if(!blood_DNA || !istype(blood_DNA, /list)) + blood_DNA = list() + blood_color = "#A10808" + return 1 + if (!( istype(M, /mob/living/carbon/human) )) + return 0 + if (!istype(M.dna, /datum/dna)) + M.dna = new /datum/dna(null) + M.dna.real_name = M.real_name + M.check_dna() + if (!( src.flags ) & FPRINT) + return 0 + if(!blood_DNA || !istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it. + blood_DNA = list() + blood_color = "#A10808" + if (M.species) + blood_color = M.species.blood_color + //adding blood to humans + else if (istype(src, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + //if this blood isn't already in the list, add it + if(blood_DNA[H.dna.unique_enzymes]) + return 0 //already bloodied with this blood. Cannot add more. + blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + H.update_inv_gloves() //handles bloody hands overlays and updating + return 1 //we applied blood to the item + return + +/atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0) + if( istype(src, /turf/simulated) ) + var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src) + + // Make toxins vomit look different + if(toxvomit) + this.icon_state = "vomittox_[pick(1,4)]" + + +/atom/proc/clean_blood() + src.germ_level = 0 + if(istype(blood_DNA, /list)) + //del(blood_DNA) + blood_DNA.len = 0 + return 1 + + +/atom/proc/get_global_map_pos() + if(!islist(global_map) || isemptylist(global_map)) return + var/cur_x = null + var/cur_y = null + var/list/y_arr = null + for(cur_x=1,cur_x<=global_map.len,cur_x++) + y_arr = global_map[cur_x] + cur_y = y_arr.Find(src.z) + if(cur_y) + break +// to_chat(world, "X = [cur_x]; Y = [cur_y]") + if(cur_x && cur_y) + return list("x"=cur_x,"y"=cur_y) + else + return 0 + +/atom/proc/checkpass(passflag) + return pass_flags&passflag + +/datum/proc/setGender(gend = FEMALE) + if(!("gender" in vars)) + CRASH("Oh shit you stupid nigger the [src] doesn't have a gender variable.") + if(ishuman(src)) + ASSERT(gend != PLURAL && gend != NEUTER) + src:gender = gend + +/atom/setGender(gend = FEMALE) + gender = gend + +/mob/living/carbon/human/setGender(gend = FEMALE) + if(gend == PLURAL || gend == NEUTER || (gend != FEMALE && gend != MALE)) + CRASH("SOMEBODY SET A BAD GENDER ON [src] [gend]") + var/old_gender = src.gender + src.gender = gend + testing("Set [src]'s gender to [gend], old gender [old_gender] previous gender [prev_gender]") + +/atom/proc/mop_act(obj/item/weapon/mop/M, mob/user) + return 0 + +/atom/proc/change_area(var/area/oldarea, var/area/newarea) + if(istype(oldarea)) + oldarea = "[oldarea.name]" + if(istype(newarea)) + newarea = "[newarea.name]" + +//Called in /spell/aoe_turf/boo/cast() (code/modules/mob/dead/observer/spells.dm) +/atom/proc/spook() + if(blessed) + return 0 + return 1 + +//Called on holy_water's reaction_obj() +/atom/proc/bless() + blessed = 1 + +/atom/proc/update_icon() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 84c51595481..24e0f5adaa9 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,504 +1,504 @@ -/atom/movable - // Recycling shit - - var/w_type = NOT_RECYCLABLE // Waste category for sorters. See setup.dm - - layer = 3 - var/last_move = null - var/anchored = 0 - var/move_speed = 10 - var/l_move_time = 1 - var/m_flag = 1 - var/throwing = 0 - var/throw_speed = 2 - var/throw_range = 7 - var/moved_recently = 0 - var/mob/pulledby = null - - var/area/areaMaster - - // Garbage collection (controller). - //var/gcDestroyed - //var/timeDestroyed - - var/sound_override = 0 //Do we make a sound when bumping into something? - var/hard_deleted = 0 - - var/obj/effect/overlay/chain/tether = null - var/tether_pull = 0 - - //glide_size = 8 - - //Atom locking stuff. - var/list/locked_atoms - var/atom/movable/locked_to - var/locked_should_lie = 0 //Whether locked mobs should lie down, used by beds. - var/dense_when_locking = 1 - - // Can we send relaymove() if gravity is disabled or we are in space? (Should be handled by relaymove, but shitcode abounds) - var/internal_gravity = 0 - -/atom/movable/New() - . = ..() - areaMaster = get_area_master(src) - if(flags & HEAR && !ismob(src)) - getFromPool(/mob/virtualhearer, src) - var/icon/I = icon(icon, icon_state, dir) - if(I) - I.MapColors(-1,0,0, 0,-1,0, 0,0,-1, 1,1,1) - src.tempoverlay = I - - locked_atoms = list() - -/atom/movable/Destroy() - if(flags & HEAR && !ismob(src)) - for(var/mob/virtualhearer/VH in virtualhearers) - if(VH.attached == src) - returnToPool(VH) - gcDestroyed = "Bye, world!" - tag = null - loc = null - - for(var/atom/movable/AM in locked_atoms) - unlock_atom(AM) - - if(locked_to) - locked_to.unlock_atom(src) - - ..() - -/proc/delete_profile(var/type, code = 0) - if(!ticker || ticker.current_state < 3) return - if(code == 0) - if (!("[type]" in del_profiling)) - del_profiling["[type]"] = 0 - - del_profiling["[type]"] += 1 - else if(code == 1) - if (!("[type]" in ghdel_profiling)) - ghdel_profiling["[type]"] = 0 - - ghdel_profiling["[type]"] += 1 - else - if (!("[type]" in gdel_profiling)) - gdel_profiling["[type]"] = 0 - - gdel_profiling["[type]"] += 1 - soft_dels += 1 - -/atom/movable/Del() - if (gcDestroyed) - - if (hard_deleted) - delete_profile("[type]", 1) - else - garbageCollector.dequeue("\ref[src]") // hard deletions have already been handled by the GC queue. - delete_profile("[type]", 2) - else // direct del calls or nulled explicitly. - delete_profile("[type]", 0) - Destroy() - - ..() - -/atom/movable/Move(newLoc,Dir=0,step_x=0,step_y=0) - if(!loc || !newLoc) - return 0 - //set up glide sizes before the move - //ensure this is a step, not a jump - - //. = ..(NewLoc,Dir,step_x,step_y) - if(timestopped) - if(!pulledby || pulledby.timestopped) //being moved by our wizard maybe? - return 0 - var/move_delay = max(5 * world.tick_lag, 1) - if(ismob(src)) - var/mob/M = src - if(M.client) - move_delay = (3+(M.client.move_delayer.next_allowed - world.time))*world.tick_lag - - var/can_pull_tether = 0 - if(tether) - if(tether.attempt_to_follow(src,newLoc)) - can_pull_tether = 1 - else - return 0 - glide_size = Ceiling(32 / move_delay * world.tick_lag) - 1 //We always split up movements into cardinals for issues with diagonal movements. - var/atom/oldloc = loc - if((bound_height != 32 || bound_width != 32) && (loc == newLoc)) - . = ..() - - update_dir() - return - - if(loc != newLoc) - if (!(Dir & (Dir - 1))) //Cardinal move - . = ..() - else //Diagonal move, split it into cardinal moves - if (Dir & 1) - if (Dir & 4) - if (step(src, NORTH)) - . = step(src, EAST) - else if (step(src, EAST)) - . = step(src, NORTH) - else if (Dir & 8) - if (step(src, NORTH)) - . = step(src, WEST) - else if (step(src, WEST)) - . = step(src, NORTH) - else if (Dir & 2) - if (Dir & 4) - if (step(src, SOUTH)) - . = step(src, EAST) - else if (step(src, EAST)) - . = step(src, SOUTH) - else if (Dir & 8) - if (step(src, SOUTH)) - . = step(src, WEST) - else if (step(src, WEST)) - . = step(src, SOUTH) - - if(. && locked_atoms && locked_atoms.len) //The move was succesful, update locked atoms. - spawn(0) - for(var/atom/movable/AM in locked_atoms) - AM.forceMove(loc) - - update_dir() - - if(!loc || (loc == oldloc && oldloc != newLoc)) - last_move = 0 - return - - if(tether && can_pull_tether && !tether_pull) - tether.follow(src,oldloc) - var/datum/chain/tether_datum = tether.chain_datum - if(!tether_datum.Check_Integrity()) - tether_datum.snap = 1 - tether_datum.Delete_Chain() - - last_move = Dir - src.move_speed = world.timeofday - src.l_move_time - src.l_move_time = world.timeofday - // Update on_moved listeners. - INVOKE_EVENT(on_moved,list("loc"=newLoc)) - return . - -//The reason behind change_dir() -/atom/movable/proc/update_dir() - for(var/atom/movable/AM in locked_atoms) - if(dir != AM.dir) - AM.change_dir(dir, src) - -//Like forceMove(), but for dirs! -/atom/movable/proc/change_dir(new_dir, var/changer) - if(locked_to && changer != locked_to) - return - - if(new_dir != dir) - dir = new_dir - update_dir() - -//Atom locking, lock an atom to another atom, and the locked atom will move when the other atom moves. -//Essentially buckling mobs to chairs. For all atoms. -//Please don't lock atoms to other atoms if the atoms locked to expect for example a different type, it's basically bound to runtime/glitch. -/atom/movable/proc/lock_atom(var/atom/movable/AM) - if(AM in locked_atoms || AM.locked_to || !istype(AM)) - return - - AM.locked_to = src - locked_atoms += AM - - AM.forceMove(loc) - AM.change_dir(dir, src) - - if(ismob(AM)) - var/mob/M = AM - M.update_canmove() - - AM.anchored = 1 - - if(dense_when_locking) - density = 1 - - return 1 - -/atom/movable/proc/unlock_atom(var/atom/movable/AM) - if(!(AM in locked_atoms)) - return - - locked_atoms -= AM - AM.locked_to = null - - if(ismob(AM)) - var/mob/M = AM - M.update_canmove() - - AM.anchored = initial(AM.anchored) - - if(dense_when_locking) - density = initial(density) - - return 1 - -/atom/movable/proc/unlock_from() - if(!locked_to) - return 0 - - locked_to.unlock_atom(src) - -/atom/movable/proc/recycle(var/datum/materials/rec) - if(materials) - for(var/matid in materials.storage) - var/datum/material/material = materials.getMaterial(matid) - rec.addAmount(matid, materials.storage[matid] / material.cc_per_sheet) //the recycler's material is read as 1 = 1 sheet - materials.storage[matid] = 0 - return 1 - return 0 - -// Previously known as HasEntered() -// This is automatically called when something enters your square -/atom/movable/Crossed(atom/movable/AM) - return - -/atom/movable/Bump(atom/Obstacle, yes) - if(src.throwing) - src.throw_impact(Obstacle) - src.throwing = 0 - - if ((Obstacle && yes)) - Obstacle.last_bumped = world.time - Obstacle.Bumped(src) - return - ..() - return - -/atom/movable/proc/forceMove(atom/destination,var/no_tp=0) - if(destination) - if(loc) - loc.Exited(src) - - loc = destination - loc.Entered(src) - if(isturf(destination)) - var/area/A = get_area_master(destination) - A.Entered(src) - - for(var/atom/movable/AM in loc) - AM.Crossed(src,no_tp) - - - for(var/atom/movable/AM in locked_atoms) - AM.forceMove(loc) - - // Update on_moved listeners. - INVOKE_EVENT(on_moved,list("loc"=loc)) - return 1 - return 0 - -/atom/movable/proc/forceEnter(atom/destination) - if(destination) - if(loc) - loc.Exited(src) - loc = destination - loc.Entered(src) - if(isturf(destination)) - var/area/A = get_area_master(destination) - A.Entered(src) - - for(var/atom/movable/AM in locked_atoms) - AM.forceMove(loc) - - return 1 - return 0 - -/atom/movable/proc/hit_check(var/speed, mob/user) - if(src.throwing) - for(var/atom/A in get_turf(src)) - if(A == src) continue - - if(isliving(A)) - var/mob/living/L = A - if(L.lying) continue - src.throw_impact(L, speed, user) - - if(src.throwing == 1) //If throwing == 1, the throw was weak and will stop when it hits a dude. If a hulk throws this item, throwing is set to 2 (so the item will pass through multiple mobs) - src.throwing = 0 - - else if(isobj(A)) - if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement - src.throw_impact(A, speed, user) - src.throwing = 0 - -/atom/movable/proc/throw_at(atom/target, range, speed, override = 1) - if(!target || !src) return 0 - if(override) - sound_override = 1 - //use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target - - throwing = 1 - if(!speed) - speed = throw_speed - - var/mob/user - if(usr) - user = usr - if(M_HULK in usr.mutations) - src.throwing = 2 // really strong throw! - - var/dist_x = abs(target.x - src.x) - var/dist_y = abs(target.y - src.y) - - var/dx - if (target.x > src.x) - dx = EAST - else - dx = WEST - - var/dy - if (target.y > src.y) - dy = NORTH - else - dy = SOUTH - var/dist_travelled = 0 - var/dist_since_sleep = 0 - var/area/a = get_area(src.loc) - if(dist_x > dist_y) - var/error = dist_x/2 - dist_y - - - var/tS = 0 - while(src && target &&((((src.x < target.x && dx == EAST) || (src.x > target.x && dx == WEST)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf)) - // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up - if(tS && dist_travelled) - timestopped = loc.timestopped - tS = 0 - if(timestopped && !dist_travelled) - timestopped = 0 - tS = 1 - while((loc.timestopped || timestopped) && dist_travelled) - sleep(3) - if(error < 0) - var/atom/step = get_step(src, dy) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed, user) - error += dist_x - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - else - var/atom/step = get_step(src, dx) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed, user) - error -= dist_y - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - a = get_area(src.loc) - else - var/error = dist_y/2 - dist_x - while(src && target &&((((src.y < target.y && dy == NORTH) || (src.y > target.y && dy == SOUTH)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf)) - // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up - if(timestopped) - sleep(1) - continue - if(error < 0) - var/atom/step = get_step(src, dx) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed, user) - error += dist_y - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - else - var/atom/step = get_step(src, dy) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - hit_check(speed, user) - error -= dist_x - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - - a = get_area(src.loc) - - //done throwing, either because it hit something or it finished moving - src.throwing = 0 - if(isobj(src)) - src.throw_impact(get_turf(src), speed, user) - -/atom/movable/change_area(oldarea, newarea) - areaMaster = newarea - ..() - -//Overlays -/atom/movable/overlay - var/atom/master = null - anchored = 1 - -/atom/movable/overlay/New() - . = ..() - verbs.len = 0 - -/atom/movable/overlay/attackby(a, b, c) - if (src.master) - return src.master.attackby(a, b, c) - return - -/atom/movable/overlay/attack_paw(a, b, c) - if (src.master) - return src.master.attack_paw(a, b, c) - return - -/atom/movable/overlay/attack_hand(a, b, c) - if (src.master) - return src.master.attack_hand(a, b, c) - return - -/atom/movable/proc/attempt_to_follow(var/atom/movable/A,var/turf/T) - if(anchored) - return 0 - if(get_dist(T,loc) <= 1) - return 1 - else - var/turf/U = A.loc - return U.Enter(src,loc) - -///////////////////////////// -// SINGULOTH PULL REFACTOR -///////////////////////////// -/atom/movable/proc/canSingulothPull(var/obj/machinery/singularity/singulo) - return singuloCanEat() - -/atom/movable/proc/say_understands(var/mob/other) - return 1 - -//////////// -/// HEAR /// -//////////// -/atom/movable/proc/addHear() - flags |= HEAR - getFromPool(/mob/virtualhearer, src) - -/atom/movable/proc/removeHear() - flags &= ~HEAR - for(var/mob/virtualhearer/VH in virtualhearers) - if(VH.attached == src) - returnToPool(VH) - -//Can it be moved by a shuttle? -/atom/movable/proc/can_shuttle_move(var/datum/shuttle/S) - return 1 +/atom/movable + // Recycling shit + + var/w_type = NOT_RECYCLABLE // Waste category for sorters. See setup.dm + + layer = 3 + var/last_move = null + var/anchored = 0 + var/move_speed = 10 + var/l_move_time = 1 + var/m_flag = 1 + var/throwing = 0 + var/throw_speed = 2 + var/throw_range = 7 + var/moved_recently = 0 + var/mob/pulledby = null + + var/area/areaMaster + + // Garbage collection (controller). + //var/gcDestroyed + //var/timeDestroyed + + var/sound_override = 0 //Do we make a sound when bumping into something? + var/hard_deleted = 0 + + var/obj/effect/overlay/chain/tether = null + var/tether_pull = 0 + + //glide_size = 8 + + //Atom locking stuff. + var/list/locked_atoms + var/atom/movable/locked_to + var/locked_should_lie = 0 //Whether locked mobs should lie down, used by beds. + var/dense_when_locking = 1 + + // Can we send relaymove() if gravity is disabled or we are in space? (Should be handled by relaymove, but shitcode abounds) + var/internal_gravity = 0 + +/atom/movable/New() + . = ..() + areaMaster = get_area_master(src) + if(flags & HEAR && !ismob(src)) + getFromPool(/mob/virtualhearer, src) + var/icon/I = icon(icon, icon_state, dir) + if(I) + I.MapColors(-1,0,0, 0,-1,0, 0,0,-1, 1,1,1) + src.tempoverlay = I + + locked_atoms = list() + +/atom/movable/Destroy() + if(flags & HEAR && !ismob(src)) + for(var/mob/virtualhearer/VH in virtualhearers) + if(VH.attached == src) + returnToPool(VH) + gcDestroyed = "Bye, world!" + tag = null + loc = null + + for(var/atom/movable/AM in locked_atoms) + unlock_atom(AM) + + if(locked_to) + locked_to.unlock_atom(src) + + ..() + +/proc/delete_profile(var/type, code = 0) + if(!ticker || ticker.current_state < 3) return + if(code == 0) + if (!("[type]" in del_profiling)) + del_profiling["[type]"] = 0 + + del_profiling["[type]"] += 1 + else if(code == 1) + if (!("[type]" in ghdel_profiling)) + ghdel_profiling["[type]"] = 0 + + ghdel_profiling["[type]"] += 1 + else + if (!("[type]" in gdel_profiling)) + gdel_profiling["[type]"] = 0 + + gdel_profiling["[type]"] += 1 + soft_dels += 1 + +/atom/movable/Del() + if (gcDestroyed) + + if (hard_deleted) + delete_profile("[type]", 1) + else + garbageCollector.dequeue("\ref[src]") // hard deletions have already been handled by the GC queue. + delete_profile("[type]", 2) + else // direct del calls or nulled explicitly. + delete_profile("[type]", 0) + Destroy() + + ..() + +/atom/movable/Move(newLoc,Dir=0,step_x=0,step_y=0) + if(!loc || !newLoc) + return 0 + //set up glide sizes before the move + //ensure this is a step, not a jump + + //. = ..(NewLoc,Dir,step_x,step_y) + if(timestopped) + if(!pulledby || pulledby.timestopped) //being moved by our wizard maybe? + return 0 + var/move_delay = max(5 * world.tick_lag, 1) + if(ismob(src)) + var/mob/M = src + if(M.client) + move_delay = (3+(M.client.move_delayer.next_allowed - world.time))*world.tick_lag + + var/can_pull_tether = 0 + if(tether) + if(tether.attempt_to_follow(src,newLoc)) + can_pull_tether = 1 + else + return 0 + glide_size = Ceiling(32 / move_delay * world.tick_lag) - 1 //We always split up movements into cardinals for issues with diagonal movements. + var/atom/oldloc = loc + if((bound_height != 32 || bound_width != 32) && (loc == newLoc)) + . = ..() + + update_dir() + return + + if(loc != newLoc) + if (!(Dir & (Dir - 1))) //Cardinal move + . = ..() + else //Diagonal move, split it into cardinal moves + if (Dir & 1) + if (Dir & 4) + if (step(src, NORTH)) + . = step(src, EAST) + else if (step(src, EAST)) + . = step(src, NORTH) + else if (Dir & 8) + if (step(src, NORTH)) + . = step(src, WEST) + else if (step(src, WEST)) + . = step(src, NORTH) + else if (Dir & 2) + if (Dir & 4) + if (step(src, SOUTH)) + . = step(src, EAST) + else if (step(src, EAST)) + . = step(src, SOUTH) + else if (Dir & 8) + if (step(src, SOUTH)) + . = step(src, WEST) + else if (step(src, WEST)) + . = step(src, SOUTH) + + if(. && locked_atoms && locked_atoms.len) //The move was succesful, update locked atoms. + spawn(0) + for(var/atom/movable/AM in locked_atoms) + AM.forceMove(loc) + + update_dir() + + if(!loc || (loc == oldloc && oldloc != newLoc)) + last_move = 0 + return + + if(tether && can_pull_tether && !tether_pull) + tether.follow(src,oldloc) + var/datum/chain/tether_datum = tether.chain_datum + if(!tether_datum.Check_Integrity()) + tether_datum.snap = 1 + tether_datum.Delete_Chain() + + last_move = Dir + src.move_speed = world.timeofday - src.l_move_time + src.l_move_time = world.timeofday + // Update on_moved listeners. + INVOKE_EVENT(on_moved,list("loc"=newLoc)) + return . + +//The reason behind change_dir() +/atom/movable/proc/update_dir() + for(var/atom/movable/AM in locked_atoms) + if(dir != AM.dir) + AM.change_dir(dir, src) + +//Like forceMove(), but for dirs! +/atom/movable/proc/change_dir(new_dir, var/changer) + if(locked_to && changer != locked_to) + return + + if(new_dir != dir) + dir = new_dir + update_dir() + +//Atom locking, lock an atom to another atom, and the locked atom will move when the other atom moves. +//Essentially buckling mobs to chairs. For all atoms. +//Please don't lock atoms to other atoms if the atoms locked to expect for example a different type, it's basically bound to runtime/glitch. +/atom/movable/proc/lock_atom(var/atom/movable/AM) + if(AM in locked_atoms || AM.locked_to || !istype(AM)) + return + + AM.locked_to = src + locked_atoms += AM + + AM.forceMove(loc) + AM.change_dir(dir, src) + + if(ismob(AM)) + var/mob/M = AM + M.update_canmove() + + AM.anchored = 1 + + if(dense_when_locking) + density = 1 + + return 1 + +/atom/movable/proc/unlock_atom(var/atom/movable/AM) + if(!(AM in locked_atoms)) + return + + locked_atoms -= AM + AM.locked_to = null + + if(ismob(AM)) + var/mob/M = AM + M.update_canmove() + + AM.anchored = initial(AM.anchored) + + if(dense_when_locking) + density = initial(density) + + return 1 + +/atom/movable/proc/unlock_from() + if(!locked_to) + return 0 + + locked_to.unlock_atom(src) + +/atom/movable/proc/recycle(var/datum/materials/rec) + if(materials) + for(var/matid in materials.storage) + var/datum/material/material = materials.getMaterial(matid) + rec.addAmount(matid, materials.storage[matid] / material.cc_per_sheet) //the recycler's material is read as 1 = 1 sheet + materials.storage[matid] = 0 + return 1 + return 0 + +// Previously known as HasEntered() +// This is automatically called when something enters your square +/atom/movable/Crossed(atom/movable/AM) + return + +/atom/movable/Bump(atom/Obstacle, yes) + if(src.throwing) + src.throw_impact(Obstacle) + src.throwing = 0 + + if ((Obstacle && yes)) + Obstacle.last_bumped = world.time + Obstacle.Bumped(src) + return + ..() + return + +/atom/movable/proc/forceMove(atom/destination,var/no_tp=0) + if(destination) + if(loc) + loc.Exited(src) + + loc = destination + loc.Entered(src) + if(isturf(destination)) + var/area/A = get_area_master(destination) + A.Entered(src) + + for(var/atom/movable/AM in loc) + AM.Crossed(src,no_tp) + + + for(var/atom/movable/AM in locked_atoms) + AM.forceMove(loc) + + // Update on_moved listeners. + INVOKE_EVENT(on_moved,list("loc"=loc)) + return 1 + return 0 + +/atom/movable/proc/forceEnter(atom/destination) + if(destination) + if(loc) + loc.Exited(src) + loc = destination + loc.Entered(src) + if(isturf(destination)) + var/area/A = get_area_master(destination) + A.Entered(src) + + for(var/atom/movable/AM in locked_atoms) + AM.forceMove(loc) + + return 1 + return 0 + +/atom/movable/proc/hit_check(var/speed, mob/user) + if(src.throwing) + for(var/atom/A in get_turf(src)) + if(A == src) continue + + if(isliving(A)) + var/mob/living/L = A + if(L.lying) continue + src.throw_impact(L, speed, user) + + if(src.throwing == 1) //If throwing == 1, the throw was weak and will stop when it hits a dude. If a hulk throws this item, throwing is set to 2 (so the item will pass through multiple mobs) + src.throwing = 0 + + else if(isobj(A)) + if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement + src.throw_impact(A, speed, user) + src.throwing = 0 + +/atom/movable/proc/throw_at(atom/target, range, speed, override = 1) + if(!target || !src) return 0 + if(override) + sound_override = 1 + //use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target + + throwing = 1 + if(!speed) + speed = throw_speed + + var/mob/user + if(usr) + user = usr + if(M_HULK in usr.mutations) + src.throwing = 2 // really strong throw! + + var/dist_x = abs(target.x - src.x) + var/dist_y = abs(target.y - src.y) + + var/dx + if (target.x > src.x) + dx = EAST + else + dx = WEST + + var/dy + if (target.y > src.y) + dy = NORTH + else + dy = SOUTH + var/dist_travelled = 0 + var/dist_since_sleep = 0 + var/area/a = get_area(src.loc) + if(dist_x > dist_y) + var/error = dist_x/2 - dist_y + + + var/tS = 0 + while(src && target &&((((src.x < target.x && dx == EAST) || (src.x > target.x && dx == WEST)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf)) + // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up + if(tS && dist_travelled) + timestopped = loc.timestopped + tS = 0 + if(timestopped && !dist_travelled) + timestopped = 0 + tS = 1 + while((loc.timestopped || timestopped) && dist_travelled) + sleep(3) + if(error < 0) + var/atom/step = get_step(src, dy) + if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + break + src.Move(step) + hit_check(speed, user) + error += dist_x + dist_travelled++ + dist_since_sleep++ + if(dist_since_sleep >= speed) + dist_since_sleep = 0 + sleep(1) + else + var/atom/step = get_step(src, dx) + if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + break + src.Move(step) + hit_check(speed, user) + error -= dist_y + dist_travelled++ + dist_since_sleep++ + if(dist_since_sleep >= speed) + dist_since_sleep = 0 + sleep(1) + a = get_area(src.loc) + else + var/error = dist_y/2 - dist_x + while(src && target &&((((src.y < target.y && dy == NORTH) || (src.y > target.y && dy == SOUTH)) && dist_travelled < range) || (a && a.has_gravity == 0) || istype(src.loc, /turf/space)) && src.throwing && istype(src.loc, /turf)) + // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up + if(timestopped) + sleep(1) + continue + if(error < 0) + var/atom/step = get_step(src, dx) + if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + break + src.Move(step) + hit_check(speed, user) + error += dist_y + dist_travelled++ + dist_since_sleep++ + if(dist_since_sleep >= speed) + dist_since_sleep = 0 + sleep(1) + else + var/atom/step = get_step(src, dy) + if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + break + src.Move(step) + hit_check(speed, user) + error -= dist_x + dist_travelled++ + dist_since_sleep++ + if(dist_since_sleep >= speed) + dist_since_sleep = 0 + sleep(1) + + a = get_area(src.loc) + + //done throwing, either because it hit something or it finished moving + src.throwing = 0 + if(isobj(src)) + src.throw_impact(get_turf(src), speed, user) + +/atom/movable/change_area(oldarea, newarea) + areaMaster = newarea + ..() + +//Overlays +/atom/movable/overlay + var/atom/master = null + anchored = 1 + +/atom/movable/overlay/New() + . = ..() + verbs.len = 0 + +/atom/movable/overlay/attackby(a, b, c) + if (src.master) + return src.master.attackby(a, b, c) + return + +/atom/movable/overlay/attack_paw(a, b, c) + if (src.master) + return src.master.attack_paw(a, b, c) + return + +/atom/movable/overlay/attack_hand(a, b, c) + if (src.master) + return src.master.attack_hand(a, b, c) + return + +/atom/movable/proc/attempt_to_follow(var/atom/movable/A,var/turf/T) + if(anchored) + return 0 + if(get_dist(T,loc) <= 1) + return 1 + else + var/turf/U = A.loc + return U.Enter(src,loc) + +///////////////////////////// +// SINGULOTH PULL REFACTOR +///////////////////////////// +/atom/movable/proc/canSingulothPull(var/obj/machinery/singularity/singulo) + return singuloCanEat() + +/atom/movable/proc/say_understands(var/mob/other) + return 1 + +//////////// +/// HEAR /// +//////////// +/atom/movable/proc/addHear() + flags |= HEAR + getFromPool(/mob/virtualhearer, src) + +/atom/movable/proc/removeHear() + flags &= ~HEAR + for(var/mob/virtualhearer/VH in virtualhearers) + if(VH.attached == src) + returnToPool(VH) + +//Can it be moved by a shuttle? +/atom/movable/proc/can_shuttle_move(var/datum/shuttle/S) + return 1 diff --git a/code/game/communications.dm b/code/game/communications.dm index 36b72d8c973..a745f5b781c 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -1,385 +1,385 @@ -/* - HOW IT WORKS - - The radio_controller is a global object maintaining all radio transmissions, think about it as about "ether". - Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way. - procs: - - add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null) - Adds listening object. - parameters: - device - device receiving signals, must have proc receive_signal (see description below). - one device may listen several frequencies, but not same frequency twice. - new_frequency - see possibly frequencies below; - filter - thing for optimization. Optional, but recommended. - All filters should be consolidated in this file, see defines later. - Device without listening filter will receive all signals (on specified frequency). - Device with filter will receive any signals sent without filter. - Device with filter will not receive any signals sent with different filter. - returns: - Reference to frequency object. - - remove_object (obj/device, old_frequency) - Obliviously, after calling this proc, device will not receive any signals on old_frequency. - Other frequencies will left unaffected. - - return_frequency(var/frequency as num) - returns: - Reference to frequency object. Use it if you need to send and do not need to listen. - - radio_frequency is a global object maintaining list of devices that listening specific frequency. - procs: - - post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null) - Sends signal to all devices that wants such signal. - parameters: - source - object, emitted signal. Usually, devices will not receive their own signals. - signal - see description below. - filter - described above. - range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels. - - obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param) - Handler from received signals. By default does nothing. Define your own for your object. - Avoid of sending signals directly from this proc, use spawn(-1). Do not use sleep() here please. - parameters: - signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return! - receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO. - TRANSMISSION_WIRE is currently unused. - receive_param - for TRANSMISSION_RADIO here comes frequency. - - datum/signal - vars: - source - an object that emitted signal. Used for debug and bearing. - data - list with transmitting data. Usual use pattern: - data["msg"] = "hello world" - encryption - Some number symbolizing "encryption key". - Note that game actually do not use any cryptography here. - If receiving object don't know right key, it must ignore encrypted signal in its receive_signal. - -*/ -var/list/all_radios = list() -/proc/add_radio(var/obj/item/radio, freq) - if(!freq || !radio) - return - if(!all_radios["[freq]"]) - all_radios["[freq]"] = list(radio) - return freq - - all_radios["[freq]"] |= radio - return freq - -/proc/remove_radio(var/obj/item/radio, freq) - if(!freq || !radio) - return - if(!all_radios["[freq]"]) - return - - all_radios["[freq]"] -= radio - -/proc/remove_radio_all(var/obj/item/radio) - for(var/freq in all_radios) - all_radios["[freq]"] -= radio -/* -Frequency range: 1200 to 1600 -Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking) - -Radio: -1459 - standard radio chat -1351 - Science -1353 - Command -1355 - Medical -1357 - Engineering -1359 - Security -1441 - death squad -1443 - Confession Intercom -1349 - Botany, chef, bartender -1347 - Cargo techs - -Devices: -1451 - tracking implant -1457 - RSD default - -On the map: -1311 for prison shuttle console (in fact, it is not used) -1367 for recycling/mining processing machinery and conveyors -1435 for status displays -1437 for atmospherics/fire alerts -1439 for engine components -1439 for air pumps, air scrubbers, atmo control -1441 for atmospherics - supply tanks -1443 for atmospherics - distribution loop/mixed air tank -1445 for bot nav beacons -1447 for mulebot, secbot and ed209 control -1449 for airlock controls, electropack, magnets -1451 for toxin lab access -1453 for engineering access -1455 for AI access -*/ - -var/list/radiochannels = list( - "Common" = 1459, - "AI Private" = 1447, - "Deathsquad" = 1441, - "Security" = 1359, - "Engineering" = 1357, - "Command" = 1353, - "Medical" = 1355, - "Science" = 1351, - "Service" = 1349, - "Supply" = 1347, - "Response Team" = 1345, - "Syndicate" = 1213, - "DJ" = 1201 -) - -var/list/radiochannelsreverse = list( - "1201" = "DJ", - "1213" = "Syndicate", - "1345" = "Response Team", - "1347" = "Supply", - "1349" = "Service", - "1351" = "Science", - "1355" = "Medical", - "1353" = "Command", - "1357" = "Engineering", - "1359" = "Security", - "1441" = "Deathsquad", - "1447" = "AI Private", - "1459" = "Common" -) - - -//depenging helpers -var/const/SUPP_FREQ = 1347 //supply, coloured light brown in chat window -var/const/SERV_FREQ = 1349 //service, coloured green in chat window -var/const/DSQUAD_FREQ = 1441 //death squad frequency, coloured grey in chat window -var/const/RESTEAM_FREQ = 1345 //response team frequency, uses the deathsquad color at the moment. -var/const/AIPRIV_FREQ = 1447 //AI private, colored magenta in chat window -var/const/DJ_FREQ = 1201 //Media - -// central command channels, i.e deathsquid & response teams -var/list/CENT_FREQS = list(1345, 1441) - -var/const/COMM_FREQ = 1353 //command, colored gold in chat window -var/const/SYND_FREQ = 1213 - -// department channels -var/const/SEC_FREQ = 1359 -var/const/ENG_FREQ = 1357 -var/const/SCI_FREQ = 1351 -var/const/MED_FREQ = 1355 -var/const/SUP_FREQ = 1347 -var/const/SER_FREQ = 1349 - -#define TRANSMISSION_WIRE 0 -#define TRANSMISSION_RADIO 1 - -/* filters */ -var/const/RADIO_TO_AIRALARM = "1" -var/const/RADIO_FROM_AIRALARM = "2" -var/const/RADIO_CHAT = "3" //deprecated -var/const/RADIO_ATMOSIA = "4" -var/const/RADIO_NAVBEACONS = "5" -var/const/RADIO_AIRLOCK = "6" -var/const/RADIO_SECBOT = "7" -var/const/RADIO_MULEBOT = "8" -var/const/RADIO_MAGNETS = "9" -var/const/RADIO_CONVEYORS = "10" - -var/global/datum/controller/radio/radio_controller - -/datum/controller/radio - var/list/datum/radio_frequency/frequencies = new - -/datum/controller/radio/proc/add_object(const/obj/device, const/_frequency, var/filter = null as text|null) - var/datum/radio_frequency/frequency = return_frequency(_frequency) - - if(isnull(frequency)) - frequency = new - frequency.frequency = _frequency - frequencies[num2text(_frequency)] = frequency - - frequency.add_listener(device, filter) - return frequency - -/datum/controller/radio/proc/remove_object(const/obj/device, const/_frequency) - var/datum/radio_frequency/frequency = return_frequency(_frequency) - - if(frequency) - frequency.remove_listener(device) - - if(frequency.devices.len <= 0) - frequencies.Remove(num2text(_frequency)) - - return 1 - -/datum/controller/radio/proc/return_frequency(const/_frequency) - return frequencies[num2text(_frequency)] - -/datum/radio_frequency - var/frequency as num - var/list/list/obj/devices = list() - -/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null) - //log_admin("DEBUG \[[world.timeofday]\]: post_signal {source=\"[source]\", [signal.debug_print()], filter=[filter]}") - //var/N_f=0 - //var/N_nf=0 - //var/Nt=0 - var/turf/start_point - if(range) - start_point = get_turf(source) - if(!start_point) - returnToPool(signal) - return 0 - - if (filter) //here goes some copypasta. It is for optimisation. -rastaf0 - for(var/obj/device in devices[filter]) - if(device == source) - continue - if(range) - var/turf/end_point = get_turf(device) - if(!end_point) - continue - //if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range) - if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range) - continue - device.receive_signal(signal, TRANSMISSION_RADIO, frequency) - for(var/obj/device in devices["_default"]) - if(device == source) - continue - if(range) - var/turf/end_point = get_turf(device) - if(!end_point) - continue - //if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range) - if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range) - continue - device.receive_signal(signal, TRANSMISSION_RADIO, frequency) - //N_f++ - - else - for (var/next_filter in devices) - //var/list/obj/DDD = devices[next_filter] - //Nt+=DDD.len - for(var/obj/device in devices[next_filter]) - if(device == source) - continue - if(range) - var/turf/end_point = get_turf(device) - if(!end_point) - continue - //if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range) - if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range) - continue - device.receive_signal(signal, TRANSMISSION_RADIO, frequency) - //N_nf++ - - //log_admin("DEBUG: post_signal(source=[source] ([source.x], [source.y], [source.z]),filter=[filter]) frequency=[frequency], N_f=[N_f], N_nf=[N_nf]") - - - returnToPool(signal) - -/datum/radio_frequency/proc/add_listener(const/obj/device, var/filter) - if(!filter) // FIXME - filter = "_default" - - var/list/devices_at_filter = devices[filter] - - if(isnull(devices_at_filter)) - devices_at_filter = new - devices[filter] = devices_at_filter - - devices_at_filter.Add(device) - -/datum/radio_frequency/proc/remove_listener(const/obj/device, const/filter) - var/list/devices_at_filter = devices[filter] - - // 1. check if it's an object - // 2. check if it has contents - // 3. check if the device is in contents - if(devices_at_filter && devices_at_filter.len && devices_at_filter.Find(device)) - devices_at_filter.Remove(device) - - if(devices_at_filter.len <= 0) - devices.Remove(filter) - -/datum/radio_frequency/remove_listener(const/obj/device) - for(var/filter in devices) - ..(device, filter) - -var/list/pointers = list() - -/client/proc/print_pointers() - set name = "Debug Signals" - set category = "Debug" - - if(!holder) - return - +/* + HOW IT WORKS + + The radio_controller is a global object maintaining all radio transmissions, think about it as about "ether". + Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way. + procs: + + add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null) + Adds listening object. + parameters: + device - device receiving signals, must have proc receive_signal (see description below). + one device may listen several frequencies, but not same frequency twice. + new_frequency - see possibly frequencies below; + filter - thing for optimization. Optional, but recommended. + All filters should be consolidated in this file, see defines later. + Device without listening filter will receive all signals (on specified frequency). + Device with filter will receive any signals sent without filter. + Device with filter will not receive any signals sent with different filter. + returns: + Reference to frequency object. + + remove_object (obj/device, old_frequency) + Obliviously, after calling this proc, device will not receive any signals on old_frequency. + Other frequencies will left unaffected. + + return_frequency(var/frequency as num) + returns: + Reference to frequency object. Use it if you need to send and do not need to listen. + + radio_frequency is a global object maintaining list of devices that listening specific frequency. + procs: + + post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null) + Sends signal to all devices that wants such signal. + parameters: + source - object, emitted signal. Usually, devices will not receive their own signals. + signal - see description below. + filter - described above. + range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels. + + obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param) + Handler from received signals. By default does nothing. Define your own for your object. + Avoid of sending signals directly from this proc, use spawn(-1). Do not use sleep() here please. + parameters: + signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return! + receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO. + TRANSMISSION_WIRE is currently unused. + receive_param - for TRANSMISSION_RADIO here comes frequency. + + datum/signal + vars: + source + an object that emitted signal. Used for debug and bearing. + data + list with transmitting data. Usual use pattern: + data["msg"] = "hello world" + encryption + Some number symbolizing "encryption key". + Note that game actually do not use any cryptography here. + If receiving object don't know right key, it must ignore encrypted signal in its receive_signal. + +*/ +var/list/all_radios = list() +/proc/add_radio(var/obj/item/radio, freq) + if(!freq || !radio) + return + if(!all_radios["[freq]"]) + all_radios["[freq]"] = list(radio) + return freq + + all_radios["[freq]"] |= radio + return freq + +/proc/remove_radio(var/obj/item/radio, freq) + if(!freq || !radio) + return + if(!all_radios["[freq]"]) + return + + all_radios["[freq]"] -= radio + +/proc/remove_radio_all(var/obj/item/radio) + for(var/freq in all_radios) + all_radios["[freq]"] -= radio +/* +Frequency range: 1200 to 1600 +Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking) + +Radio: +1459 - standard radio chat +1351 - Science +1353 - Command +1355 - Medical +1357 - Engineering +1359 - Security +1441 - death squad +1443 - Confession Intercom +1349 - Botany, chef, bartender +1347 - Cargo techs + +Devices: +1451 - tracking implant +1457 - RSD default + +On the map: +1311 for prison shuttle console (in fact, it is not used) +1367 for recycling/mining processing machinery and conveyors +1435 for status displays +1437 for atmospherics/fire alerts +1439 for engine components +1439 for air pumps, air scrubbers, atmo control +1441 for atmospherics - supply tanks +1443 for atmospherics - distribution loop/mixed air tank +1445 for bot nav beacons +1447 for mulebot, secbot and ed209 control +1449 for airlock controls, electropack, magnets +1451 for toxin lab access +1453 for engineering access +1455 for AI access +*/ + +var/list/radiochannels = list( + "Common" = 1459, + "AI Private" = 1447, + "Deathsquad" = 1441, + "Security" = 1359, + "Engineering" = 1357, + "Command" = 1353, + "Medical" = 1355, + "Science" = 1351, + "Service" = 1349, + "Supply" = 1347, + "Response Team" = 1345, + "Syndicate" = 1213, + "DJ" = 1201 +) + +var/list/radiochannelsreverse = list( + "1201" = "DJ", + "1213" = "Syndicate", + "1345" = "Response Team", + "1347" = "Supply", + "1349" = "Service", + "1351" = "Science", + "1355" = "Medical", + "1353" = "Command", + "1357" = "Engineering", + "1359" = "Security", + "1441" = "Deathsquad", + "1447" = "AI Private", + "1459" = "Common" +) + + +//depenging helpers +var/const/SUPP_FREQ = 1347 //supply, coloured light brown in chat window +var/const/SERV_FREQ = 1349 //service, coloured green in chat window +var/const/DSQUAD_FREQ = 1441 //death squad frequency, coloured grey in chat window +var/const/RESTEAM_FREQ = 1345 //response team frequency, uses the deathsquad color at the moment. +var/const/AIPRIV_FREQ = 1447 //AI private, colored magenta in chat window +var/const/DJ_FREQ = 1201 //Media + +// central command channels, i.e deathsquid & response teams +var/list/CENT_FREQS = list(1345, 1441) + +var/const/COMM_FREQ = 1353 //command, colored gold in chat window +var/const/SYND_FREQ = 1213 + +// department channels +var/const/SEC_FREQ = 1359 +var/const/ENG_FREQ = 1357 +var/const/SCI_FREQ = 1351 +var/const/MED_FREQ = 1355 +var/const/SUP_FREQ = 1347 +var/const/SER_FREQ = 1349 + +#define TRANSMISSION_WIRE 0 +#define TRANSMISSION_RADIO 1 + +/* filters */ +var/const/RADIO_TO_AIRALARM = "1" +var/const/RADIO_FROM_AIRALARM = "2" +var/const/RADIO_CHAT = "3" //deprecated +var/const/RADIO_ATMOSIA = "4" +var/const/RADIO_NAVBEACONS = "5" +var/const/RADIO_AIRLOCK = "6" +var/const/RADIO_SECBOT = "7" +var/const/RADIO_MULEBOT = "8" +var/const/RADIO_MAGNETS = "9" +var/const/RADIO_CONVEYORS = "10" + +var/global/datum/controller/radio/radio_controller + +/datum/controller/radio + var/list/datum/radio_frequency/frequencies = new + +/datum/controller/radio/proc/add_object(const/obj/device, const/_frequency, var/filter = null as text|null) + var/datum/radio_frequency/frequency = return_frequency(_frequency) + + if(isnull(frequency)) + frequency = new + frequency.frequency = _frequency + frequencies[num2text(_frequency)] = frequency + + frequency.add_listener(device, filter) + return frequency + +/datum/controller/radio/proc/remove_object(const/obj/device, const/_frequency) + var/datum/radio_frequency/frequency = return_frequency(_frequency) + + if(frequency) + frequency.remove_listener(device) + + if(frequency.devices.len <= 0) + frequencies.Remove(num2text(_frequency)) + + return 1 + +/datum/controller/radio/proc/return_frequency(const/_frequency) + return frequencies[num2text(_frequency)] + +/datum/radio_frequency + var/frequency as num + var/list/list/obj/devices = list() + +/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null) + //log_admin("DEBUG \[[world.timeofday]\]: post_signal {source=\"[source]\", [signal.debug_print()], filter=[filter]}") + //var/N_f=0 + //var/N_nf=0 + //var/Nt=0 + var/turf/start_point + if(range) + start_point = get_turf(source) + if(!start_point) + returnToPool(signal) + return 0 + + if (filter) //here goes some copypasta. It is for optimisation. -rastaf0 + for(var/obj/device in devices[filter]) + if(device == source) + continue + if(range) + var/turf/end_point = get_turf(device) + if(!end_point) + continue + //if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range) + if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range) + continue + device.receive_signal(signal, TRANSMISSION_RADIO, frequency) + for(var/obj/device in devices["_default"]) + if(device == source) + continue + if(range) + var/turf/end_point = get_turf(device) + if(!end_point) + continue + //if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range) + if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range) + continue + device.receive_signal(signal, TRANSMISSION_RADIO, frequency) + //N_f++ + + else + for (var/next_filter in devices) + //var/list/obj/DDD = devices[next_filter] + //Nt+=DDD.len + for(var/obj/device in devices[next_filter]) + if(device == source) + continue + if(range) + var/turf/end_point = get_turf(device) + if(!end_point) + continue + //if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range) + if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range) + continue + device.receive_signal(signal, TRANSMISSION_RADIO, frequency) + //N_nf++ + + //log_admin("DEBUG: post_signal(source=[source] ([source.x], [source.y], [source.z]),filter=[filter]) frequency=[frequency], N_f=[N_f], N_nf=[N_nf]") + + + returnToPool(signal) + +/datum/radio_frequency/proc/add_listener(const/obj/device, var/filter) + if(!filter) // FIXME + filter = "_default" + + var/list/devices_at_filter = devices[filter] + + if(isnull(devices_at_filter)) + devices_at_filter = new + devices[filter] = devices_at_filter + + devices_at_filter.Add(device) + +/datum/radio_frequency/proc/remove_listener(const/obj/device, const/filter) + var/list/devices_at_filter = devices[filter] + + // 1. check if it's an object + // 2. check if it has contents + // 3. check if the device is in contents + if(devices_at_filter && devices_at_filter.len && devices_at_filter.Find(device)) + devices_at_filter.Remove(device) + + if(devices_at_filter.len <= 0) + devices.Remove(filter) + +/datum/radio_frequency/remove_listener(const/obj/device) + for(var/filter in devices) + ..(device, filter) + +var/list/pointers = list() + +/client/proc/print_pointers() + set name = "Debug Signals" + set category = "Debug" + + if(!holder) + return + to_chat(src, "There are [pointers.len] pointers:") - for(var/p in pointers) + for(var/p in pointers) to_chat(src, p) - var/datum/signal/S = locate(p) - if(istype(S)) + var/datum/signal/S = locate(p) + if(istype(S)) to_chat(src, S.debug_print()) - -/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) - return - -#define SIGNAL_WIRE 0 -#define SIGNAL_RADIO 1 -#define SIGNAL_SUBSPACE 2 - -/datum/signal - var/obj/source - - var/transmission_method = SIGNAL_WIRE - //0 = wire - //1 = radio transmission - //2 = subspace transmission - - var/data = list() - var/encryption - - var/frequency = 0 - -/datum/signal/New() - ..() - pointers += "\ref[src]" - -/datum/signal/Destroy() - pointers -= "\ref[src]" - -/datum/signal/resetVariables() - . = ..("data") - - source = null - data = list() - -/datum/signal/proc/copy_from(datum/signal/model) - source = model.source - transmission_method = model.transmission_method - data = model.data - encryption = model.encryption - frequency = model.frequency - -/datum/signal/proc/debug_print() - if (source) - . = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n" - else - . = "signal = {source = '[source]' ()\n" - for (var/i in data) - . += "data\[\"[i]\"\] = \"[data[i]]\"\n" - if(islist(data[i])) - var/list/L = data[i] - for(var/t in L) - . += "data\[\"[i]\"\] list has: [t]" - -/datum/signal/proc/sanitize_data() - for(var/d in data) - var/val = data[d] - if(istext(val)) - data[d] = strip_html_simple(val) + +/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) + return + +#define SIGNAL_WIRE 0 +#define SIGNAL_RADIO 1 +#define SIGNAL_SUBSPACE 2 + +/datum/signal + var/obj/source + + var/transmission_method = SIGNAL_WIRE + //0 = wire + //1 = radio transmission + //2 = subspace transmission + + var/data = list() + var/encryption + + var/frequency = 0 + +/datum/signal/New() + ..() + pointers += "\ref[src]" + +/datum/signal/Destroy() + pointers -= "\ref[src]" + +/datum/signal/resetVariables() + . = ..("data") + + source = null + data = list() + +/datum/signal/proc/copy_from(datum/signal/model) + source = model.source + transmission_method = model.transmission_method + data = model.data + encryption = model.encryption + frequency = model.frequency + +/datum/signal/proc/debug_print() + if (source) + . = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n" + else + . = "signal = {source = '[source]' ()\n" + for (var/i in data) + . += "data\[\"[i]\"\] = \"[data[i]]\"\n" + if(islist(data[i])) + var/list/L = data[i] + for(var/t in L) + . += "data\[\"[i]\"\] list has: [t]" + +/datum/signal/proc/sanitize_data() + for(var/d in data) + var/val = data[d] + if(istext(val)) + data[d] = strip_html_simple(val) diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 651ab0f06a4..ea272fcccf8 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -1,186 +1,186 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -//Few global vars to track the blob -var/list/blobs = list() -var/list/blob_cores = list() -var/list/blob_nodes = list() - - -/datum/game_mode/blob - name = "Blob" - config_tag = "Blob" - - required_players = 15 - required_players_secret = 25 - restricted_jobs = list("Cyborg", "AI", "Mobile MMI") - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/declared = 0 - var/outbreak = 0 - var/nuclear = 0 - - var/cores_to_spawn = 15 - var/players_per_core = 30 - var/blob_point_rate = 3 - - var/blobwincount = 750 // WAS: 500 - var/blobnukeposs = 650 // At this point the nuke has a chance of being authorized by Centcomm - - var/list/infected_crew = list() - var/list/pre_escapees = list() - -/datum/game_mode/blob/pre_setup() - - var/list/possible_blobs = get_players_for_role(ROLE_BLOB) - - // stop setup if no possible traitors - if(!possible_blobs.len) - log_admin("Failed to set-up a round of blob. Couldn't find any volunteers to be blob.") - message_admins("Failed to set-up a round of blob. Couldn't find any volunteers to be blob.") - return 0 - - cores_to_spawn = max(round(num_players()/players_per_core, 1), 1) - - blobwincount = initial(blobwincount) * cores_to_spawn - - - for(var/j = 0, j < cores_to_spawn, j++) - if (!possible_blobs.len) - break - var/datum/mind/blob = pick(possible_blobs) - infected_crew += blob - blob.special_role = "Blob" - log_game("[blob.key] (ckey) has been selected as a Blob") - possible_blobs -= blob - - if(!infected_crew.len) - log_admin("Failed to set-up a round of blob. Couldn't select any crew members to infect.") - message_admins("Failed to set-up a round of blob. Couldn't select any crew members to infect.") - return 0 - - log_admin("Starting a round of blob with [infected_crew.len] starting blobs.") - message_admins("Starting a round of blob with [infected_crew.len] starting blobs.") - return 1 - - -/datum/game_mode/blob/announce() +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +//Few global vars to track the blob +var/list/blobs = list() +var/list/blob_cores = list() +var/list/blob_nodes = list() + + +/datum/game_mode/blob + name = "Blob" + config_tag = "Blob" + + required_players = 15 + required_players_secret = 25 + restricted_jobs = list("Cyborg", "AI", "Mobile MMI") + + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + + var/declared = 0 + var/outbreak = 0 + var/nuclear = 0 + + var/cores_to_spawn = 15 + var/players_per_core = 30 + var/blob_point_rate = 3 + + var/blobwincount = 750 // WAS: 500 + var/blobnukeposs = 650 // At this point the nuke has a chance of being authorized by Centcomm + + var/list/infected_crew = list() + var/list/pre_escapees = list() + +/datum/game_mode/blob/pre_setup() + + var/list/possible_blobs = get_players_for_role(ROLE_BLOB) + + // stop setup if no possible traitors + if(!possible_blobs.len) + log_admin("Failed to set-up a round of blob. Couldn't find any volunteers to be blob.") + message_admins("Failed to set-up a round of blob. Couldn't find any volunteers to be blob.") + return 0 + + cores_to_spawn = max(round(num_players()/players_per_core, 1), 1) + + blobwincount = initial(blobwincount) * cores_to_spawn + + + for(var/j = 0, j < cores_to_spawn, j++) + if (!possible_blobs.len) + break + var/datum/mind/blob = pick(possible_blobs) + infected_crew += blob + blob.special_role = "Blob" + log_game("[blob.key] (ckey) has been selected as a Blob") + possible_blobs -= blob + + if(!infected_crew.len) + log_admin("Failed to set-up a round of blob. Couldn't select any crew members to infect.") + message_admins("Failed to set-up a round of blob. Couldn't select any crew members to infect.") + return 0 + + log_admin("Starting a round of blob with [infected_crew.len] starting blobs.") + message_admins("Starting a round of blob with [infected_crew.len] starting blobs.") + return 1 + + +/datum/game_mode/blob/announce() to_chat(world, {"The current game mode is - Blob! -A dangerous alien organism is rapidly spreading throughout the station! -You must kill it all while minimizing the damage to the station."}) - - -/datum/game_mode/blob/proc/greet_blob(var/datum/mind/blob) +A dangerous alien organism is rapidly spreading throughout the station! +You must kill it all while minimizing the damage to the station."}) + + +/datum/game_mode/blob/proc/greet_blob(var/datum/mind/blob) to_chat(blob.current, {"You are infected by the Blob! -Your body is ready to give spawn to a new blob core which will eat this station. -Find a good location to spawn the core and then take control and overwhelm the station! Make sure you are ON the station when you burst! -When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process. -If you go outside of the station level, or in space, then you will die; make sure your location has plenty of space to expand.
      "}) - return - -/datum/game_mode/blob/proc/show_message(var/message) - for(var/datum/mind/blob in infected_crew) +Your body is ready to give spawn to a new blob core which will eat this station. +Find a good location to spawn the core and then take control and overwhelm the station! Make sure you are ON the station when you burst! +When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process. +If you go outside of the station level, or in space, then you will die; make sure your location has plenty of space to expand."}) + return + +/datum/game_mode/blob/proc/show_message(var/message) + for(var/datum/mind/blob in infected_crew) to_chat(blob.current, message) - -/datum/game_mode/blob/proc/burst_blobs() - for(var/datum/mind/blob in infected_crew) - - var/client/blob_client = null - var/turf/location = null - - if(iscarbon(blob.current)) - var/mob/living/carbon/C = blob.current - if(directory[ckey(blob.key)]) - blob_client = directory[ckey(blob.key)] - location = get_turf(C) - if(location.z != 1 || istype(location, /turf/space)) - location = null - C.gib() - - - if(blob_client && location) - var/obj/effect/blob/core/core = new(location, 200, blob_client, blob_point_rate) - if(core.overmind && core.overmind.mind) - core.overmind.mind.name = blob.name - infected_crew -= blob - infected_crew += core.overmind.mind - - -/datum/game_mode/blob/post_setup() - - for(var/datum/mind/blob in infected_crew) - greet_blob(blob) - - if(emergency_shuttle) - emergency_shuttle.always_fake_recall = 1 - - /*// Disable the blob event for this round. - if(events) - var/datum/round_event_control/blob/B = locate() in events.control - if(B) - B.max_occurrences = 0 // disable the event - else - error("Events variable is null in blob gamemode post setup.")*/ - - spawn(10) - start_state = new /datum/station_state() - start_state.count() - - spawn(0) - - var/wait_time = rand(waittime_l, waittime_h) - - sleep(wait_time) - - if(!mixed) send_intercept(0) - - sleep(100) - - show_message("You feel tired and bloated.") - - sleep(wait_time) - - show_message("You feel like you are about to burst.") - - sleep(wait_time / 2) - - burst_blobs() - - // Stage 0 - sleep(rand(600,1200)) - stage(0) - - // Stage 1 - sleep(rand(2000,2400)) - stage(1) - ..() - -/datum/game_mode/blob/proc/stage(var/stage) - - - switch(stage) - if (0) - biohazard_alert() - declared = 1 - return - - if (1) - command_alert("Biohazard outbreak alert status upgraded to level 9. [station_name()] is now locked down, under Directive 7-10, until further notice.", "Directive 7-10 Initiated") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player) && M.client) + +/datum/game_mode/blob/proc/burst_blobs() + for(var/datum/mind/blob in infected_crew) + + var/client/blob_client = null + var/turf/location = null + + if(iscarbon(blob.current)) + var/mob/living/carbon/C = blob.current + if(directory[ckey(blob.key)]) + blob_client = directory[ckey(blob.key)] + location = get_turf(C) + if(location.z != 1 || istype(location, /turf/space)) + location = null + C.gib() + + + if(blob_client && location) + var/obj/effect/blob/core/core = new(location, 200, blob_client, blob_point_rate) + if(core.overmind && core.overmind.mind) + core.overmind.mind.name = blob.name + infected_crew -= blob + infected_crew += core.overmind.mind + + +/datum/game_mode/blob/post_setup() + + for(var/datum/mind/blob in infected_crew) + greet_blob(blob) + + if(emergency_shuttle) + emergency_shuttle.always_fake_recall = 1 + + /*// Disable the blob event for this round. + if(events) + var/datum/round_event_control/blob/B = locate() in events.control + if(B) + B.max_occurrences = 0 // disable the event + else + error("Events variable is null in blob gamemode post setup.")*/ + + spawn(10) + start_state = new /datum/station_state() + start_state.count() + + spawn(0) + + var/wait_time = rand(waittime_l, waittime_h) + + sleep(wait_time) + + if(!mixed) send_intercept(0) + + sleep(100) + + show_message("You feel tired and bloated.") + + sleep(wait_time) + + show_message("You feel like you are about to burst.") + + sleep(wait_time / 2) + + burst_blobs() + + // Stage 0 + sleep(rand(600,1200)) + stage(0) + + // Stage 1 + sleep(rand(2000,2400)) + stage(1) + ..() + +/datum/game_mode/blob/proc/stage(var/stage) + + + switch(stage) + if (0) + biohazard_alert() + declared = 1 + return + + if (1) + command_alert("Biohazard outbreak alert status upgraded to level 9. [station_name()] is now locked down, under Directive 7-10, until further notice.", "Directive 7-10 Initiated") + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && M.client) M << sound('sound/AI/blob_confirmed.ogg') - var/T = M.loc - if((istype(T, /turf/space)) || ((istype(T, /turf)) && (M.z!=1))) - pre_escapees += M - if(!mixed) send_intercept(1) - outbreak = 1 - - research_shuttle.lockdown = "Under directive 7-10, [station_name()] is quarantined until further notice." //LOCKDOWN THESE SHUTTLES - mining_shuttle.lockdown = "Under directive 7-10, [station_name()] is quarantined until further notice." - if (2) - command_alert("Biohazard outbreak containment status reaching critical mass, total quarantine failure is now possibile. As such, Directive 7-12 has now been authorized for [station_name()].", "Final Measure") - for(var/mob/camera/blob/B in player_list) + var/T = M.loc + if((istype(T, /turf/space)) || ((istype(T, /turf)) && (M.z!=1))) + pre_escapees += M + if(!mixed) send_intercept(1) + outbreak = 1 + + research_shuttle.lockdown = "Under directive 7-10, [station_name()] is quarantined until further notice." //LOCKDOWN THESE SHUTTLES + mining_shuttle.lockdown = "Under directive 7-10, [station_name()] is quarantined until further notice." + if (2) + command_alert("Biohazard outbreak containment status reaching critical mass, total quarantine failure is now possibile. As such, Directive 7-12 has now been authorized for [station_name()].", "Final Measure") + for(var/mob/camera/blob/B in player_list) to_chat(B, "The beings intend to eliminate you with a final suicidal attack, you must stop them quickly or consume the station before this occurs!") - if(!mixed) send_intercept(2) - return + if(!mixed) send_intercept(2) + return diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm index 5c2831c4fef..fadd3e3740c 100644 --- a/code/game/gamemodes/blob/blob_finish.dm +++ b/code/game/gamemodes/blob/blob_finish.dm @@ -1,84 +1,84 @@ -/datum/game_mode/blob/check_finished() - if(!declared)//No blobs have been spawned yet - return 0 - if(blobwincount <= blobs.len)//Blob took over - return 1 - if(!blob_cores.len) // blob is dead - return 1 - if(station_was_nuked)//Nuke went off - return 1 - return 0 - - -/datum/game_mode/blob/declare_completion() - if(blobwincount <= blobs.len) - feedback_set_details("round_end_result","loss - blob took over") - completion_text += {"
      The blob has taken over the station! -The entire station was consumed by the Blob!"} - check_quarantine() - - else if(station_was_nuked) - feedback_set_details("round_end_result","halfwin - nuke") - completion_text += {"
      Partial Win: The station has been destroyed! -Directive 7-12 has been successfully carried out, the Blobs have taken another station but failed to spread any further!"} - - else if(!blob_cores.len) - feedback_set_details("round_end_result","win - blob eliminated") - completion_text += {"
      The staff has won! -The alien organism has been eradicated from the station"} - - var/datum/station_state/end_state = new /datum/station_state() - end_state.count() - var/percent = round( 100.0 * start_state.score(end_state), 0.1) - completion_text += "
      The station is [percent]% intact." - log_game("Blob mode was won with station [percent]% intact.") +/datum/game_mode/blob/check_finished() + if(!declared)//No blobs have been spawned yet + return 0 + if(blobwincount <= blobs.len)//Blob took over + return 1 + if(!blob_cores.len) // blob is dead + return 1 + if(station_was_nuked)//Nuke went off + return 1 + return 0 + + +/datum/game_mode/blob/declare_completion() + if(blobwincount <= blobs.len) + feedback_set_details("round_end_result","loss - blob took over") + completion_text += {"
      The blob has taken over the station! +The entire station was consumed by the Blob!"} + check_quarantine() + + else if(station_was_nuked) + feedback_set_details("round_end_result","halfwin - nuke") + completion_text += {"
      Partial Win: The station has been destroyed! +Directive 7-12 has been successfully carried out, the Blobs have taken another station but failed to spread any further!"} + + else if(!blob_cores.len) + feedback_set_details("round_end_result","win - blob eliminated") + completion_text += {"
      The staff has won! +The alien organism has been eradicated from the station"} + + var/datum/station_state/end_state = new /datum/station_state() + end_state.count() + var/percent = round( 100.0 * start_state.score(end_state), 0.1) + completion_text += "
      The station is [percent]% intact." + log_game("Blob mode was won with station [percent]% intact.") to_chat(world, "
      Rebooting in 30s") - ..() - return 1 - -datum/game_mode/proc/auto_declare_completion_blob() - if(istype(ticker.mode,/datum/game_mode/blob) ) - var/text = "" - var/datum/game_mode/blob/blob_mode = src - if(blob_mode.infected_crew.len) - text += "The blob[(blob_mode.infected_crew.len > 1 ? "s were" : " was")]:" - - var/icon/logo = icon('icons/mob/blob.dmi', "blob_core") - end_icons += logo - var/tempstate = end_icons.len - for(var/datum/mind/blob in blob_mode.infected_crew) - text += {"
      [blob.key] was [blob.name]"} - text += "

      " - return text - -/datum/game_mode/blob/proc/check_quarantine() - var/numDead = 0 - var/numAlive = 0 - var/numSpace = 0 - var/numOffStation = 0 - for (var/mob/living/silicon/ai/aiPlayer in mob_list) - for(var/mob/living/carbon/human/M in mob_list) - if ((M != aiPlayer && M.client)) - if (M.stat == 2) - numDead += 1 - else if(M in pre_escapees) - continue - else - var/T = M.loc - if (istype(T, /turf/space)) - numSpace += 1 - else if(istype(T, /turf)) - if (M.z!=1) - numOffStation += 1 - else - numAlive += 1 - if (numSpace==0 && numOffStation==0) + ..() + return 1 + +datum/game_mode/proc/auto_declare_completion_blob() + if(istype(ticker.mode,/datum/game_mode/blob) ) + var/text = "" + var/datum/game_mode/blob/blob_mode = src + if(blob_mode.infected_crew.len) + text += "The blob[(blob_mode.infected_crew.len > 1 ? "s were" : " was")]:" + + var/icon/logo = icon('icons/mob/blob.dmi', "blob_core") + end_icons += logo + var/tempstate = end_icons.len + for(var/datum/mind/blob in blob_mode.infected_crew) + text += {"
      [blob.key] was [blob.name]"} + text += "

      " + return text + +/datum/game_mode/blob/proc/check_quarantine() + var/numDead = 0 + var/numAlive = 0 + var/numSpace = 0 + var/numOffStation = 0 + for (var/mob/living/silicon/ai/aiPlayer in mob_list) + for(var/mob/living/carbon/human/M in mob_list) + if ((M != aiPlayer && M.client)) + if (M.stat == 2) + numDead += 1 + else if(M in pre_escapees) + continue + else + var/T = M.loc + if (istype(T, /turf/space)) + numSpace += 1 + else if(istype(T, /turf)) + if (M.z!=1) + numOffStation += 1 + else + numAlive += 1 + if (numSpace==0 && numOffStation==0) to_chat(world, {"The AI has succeeded! -The AI successfully maintained the quarantine - no players were in space or were off-station (as far as we can tell)."}) - log_game("AI won at Blob mode despite overall loss.") - else +The AI successfully maintained the quarantine - no players were in space or were off-station (as far as we can tell)."}) + log_game("AI won at Blob mode despite overall loss.") + else to_chat(world, {"The AI has failed! -The AI failed to maintain the quarantine - [numSpace] were in space and [numOffStation] were off-station (as far as we can tell)."}) - log_game("AI lost at Blob mode.") - log_game("Blob mode was lost.") - return 1 +The AI failed to maintain the quarantine - [numSpace] were in space and [numOffStation] were off-station (as far as we can tell)."}) + log_game("AI lost at Blob mode.") + log_game("Blob mode was lost.") + return 1 diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index 2aedf100955..bdb97dfe025 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -1,121 +1,121 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/datum/game_mode/blob/send_intercept(var/report = 1) - var/intercepttext = "" - var/interceptname = "Error" - switch(report) - if(0) - ..() - return - if(1) - interceptname = "Biohazard Alert" - intercepttext = {"NanoTrasen Update: Biohazard Alert.
      -Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle. -Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown. -NanoTrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined. -Orders for all [station_name()] personnel follows: -
        -
      1. Do not leave the quarantine area.
      2. -
      3. Locate any outbreaks of the organism on the station.
      4. -
      5. If found, use any neccesary means to contain the organism.
      6. -
      7. Avoid damage to the capital infrastructure of the station.
      8. -
      -Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12. -Message ends."} - for (var/mob/living/silicon/ai/aiPlayer in player_list) - var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard laws 1-3 if necessary to prevent, by any means necessary, anyone from leaving." - aiPlayer.set_zeroth_law(law) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/datum/game_mode/blob/send_intercept(var/report = 1) + var/intercepttext = "" + var/interceptname = "Error" + switch(report) + if(0) + ..() + return + if(1) + interceptname = "Biohazard Alert" + intercepttext = {"NanoTrasen Update: Biohazard Alert.
      +Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle. +Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown. +NanoTrasen has issued a directive 7-10 for [station_name()]. The station is to be considered quarantined. +Orders for all [station_name()] personnel follows: +
        +
      1. Do not leave the quarantine area.
      2. +
      3. Locate any outbreaks of the organism on the station.
      4. +
      5. If found, use any neccesary means to contain the organism.
      6. +
      7. Avoid damage to the capital infrastructure of the station.
      8. +
      +Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12. +Message ends."} + for (var/mob/living/silicon/ai/aiPlayer in player_list) + var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard laws 1-3 if necessary to prevent, by any means necessary, anyone from leaving." + aiPlayer.set_zeroth_law(law) to_chat(aiPlayer, "Laws Updated: [law]") - if(2) - var/nukecode = "ERROR" - for(var/obj/machinery/nuclearbomb/bomb in machines) - if(bomb && bomb.r_code) - if(bomb.z == 1) - nukecode = bomb.r_code - interceptname = "Directive 7-12" - intercepttext = {"NanoTrasen Update: Biohazard Alert.
      -Directive 7-12 has been issued for [station_name()]. -The biohazard has grown out of control and will soon reach critical mass. -Your orders are as follows: -
        -
      1. Secure the Nuclear Authentication Disk.
      2. -
      3. Detonate the Nuke located in the Station's Vault.
      4. -
      -Nuclear Authentication Code: [nukecode] -Message ends."} - for (var/mob/living/silicon/ai/aiPlayer in player_list) - var/law = "Directive 7-12 has been authorized. Allow no sentient being to escape the purge. The nuclear failsafe must be activated at any cost, the code is: [nukecode]." - aiPlayer.set_zeroth_law(law) + if(2) + var/nukecode = "ERROR" + for(var/obj/machinery/nuclearbomb/bomb in machines) + if(bomb && bomb.r_code) + if(bomb.z == 1) + nukecode = bomb.r_code + interceptname = "Directive 7-12" + intercepttext = {"NanoTrasen Update: Biohazard Alert.
      +Directive 7-12 has been issued for [station_name()]. +The biohazard has grown out of control and will soon reach critical mass. +Your orders are as follows: +
        +
      1. Secure the Nuclear Authentication Disk.
      2. +
      3. Detonate the Nuke located in the Station's Vault.
      4. +
      +Nuclear Authentication Code: [nukecode] +Message ends."} + for (var/mob/living/silicon/ai/aiPlayer in player_list) + var/law = "Directive 7-12 has been authorized. Allow no sentient being to escape the purge. The nuclear failsafe must be activated at any cost, the code is: [nukecode]." + aiPlayer.set_zeroth_law(law) to_chat(aiPlayer, "Laws Updated: [law]") - - 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- [interceptname]" - intercept.info = intercepttext - - comm.messagetitle.Add("[interceptname]") - comm.messagetext.Add(intercepttext) - return - - - -/datum/station_state - var/floor = 0 - var/wall = 0 - var/r_wall = 0 - var/window = 0 - var/door = 0 - var/grille = 0 - var/mach = 0 - - - proc/count() - for(var/turf/T in turfs) - if(T.z != 1) - continue - - if(istype(T,/turf/simulated/floor)) - if(!(T:burnt)) - src.floor += 12 - else - src.floor += 1 - - if(istype(T, /turf/simulated/wall)) - if(T:intact) - src.wall += 2 - else - src.wall += 1 - - if(istype(T, /turf/simulated/wall/r_wall)) - if(T:intact) - src.r_wall += 2 - else - src.r_wall += 1 - - for(var/obj/O in world) - if(O.z != 1) - continue - - if(istype(O, /obj/structure/window)) - src.window += 1 - else if(istype(O, /obj/structure/grille) && (!O:destroyed)) - src.grille += 1 - else if(istype(O, /obj/machinery/door)) - src.door += 1 - else if(istype(O, /obj/machinery)) - src.mach += 1 - return - - - proc/score(var/datum/station_state/result) - if(!result) return 0 - var/output = 0 - output += (result.floor / max(floor,1)) - output += (result.r_wall/ max(r_wall,1)) - output += (result.wall / max(wall,1)) - output += (result.window / max(window,1)) - output += (result.door / max(door,1)) - output += (result.grille / max(grille,1)) - output += (result.mach / max(mach,1)) - return (output/7) + + 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- [interceptname]" + intercept.info = intercepttext + + comm.messagetitle.Add("[interceptname]") + comm.messagetext.Add(intercepttext) + return + + + +/datum/station_state + var/floor = 0 + var/wall = 0 + var/r_wall = 0 + var/window = 0 + var/door = 0 + var/grille = 0 + var/mach = 0 + + + proc/count() + for(var/turf/T in turfs) + if(T.z != 1) + continue + + if(istype(T,/turf/simulated/floor)) + if(!(T:burnt)) + src.floor += 12 + else + src.floor += 1 + + if(istype(T, /turf/simulated/wall)) + if(T:intact) + src.wall += 2 + else + src.wall += 1 + + if(istype(T, /turf/simulated/wall/r_wall)) + if(T:intact) + src.r_wall += 2 + else + src.r_wall += 1 + + for(var/obj/O in world) + if(O.z != 1) + continue + + if(istype(O, /obj/structure/window)) + src.window += 1 + else if(istype(O, /obj/structure/grille) && (!O:destroyed)) + src.grille += 1 + else if(istype(O, /obj/machinery/door)) + src.door += 1 + else if(istype(O, /obj/machinery)) + src.mach += 1 + return + + + proc/score(var/datum/station_state/result) + if(!result) return 0 + var/output = 0 + output += (result.floor / max(floor,1)) + output += (result.r_wall/ max(r_wall,1)) + output += (result.wall / max(wall,1)) + output += (result.window / max(window,1)) + output += (result.door / max(door,1)) + output += (result.grille / max(grille,1)) + output += (result.mach / max(mach,1)) + return (output/7) diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index 6fc3270769c..6d9481fda46 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -1,104 +1,104 @@ -/obj/effect/blob/core - name = "blob core" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_core" - health = 200 - fire_resist = 2 - custom_process=1 - var/mob/camera/blob/overmind = null // the blob core's overmind - var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 30 seconds - var/resource_delay = 0 - var/point_rate = 2 - var/mob/camera/blob/creator = null - - -/obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, var/mob/camera/blob/C = null) - blob_cores += src - processing_objects.Add(src) - creator = C - if(!overmind) - create_overmind(new_overmind) - point_rate = new_rate - ..(loc, h) - -/obj/effect/blob/core/Destroy() - blob_cores -= src - if(overmind) - qdel(overmind) - overmind = null - processing_objects.Remove(src) - ..() - -/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/effect/blob/core/update_icon() - if(health <= 0) - playsound(get_turf(src), 'sound/effects/blobkill.ogg', 50, 1) - Delete() - return - return - -/obj/effect/blob/core/Life() - if(timestopped) return 0 //under effects of time magick - - if(!overmind) - create_overmind() - else - if(resource_delay <= world.time) - resource_delay = world.time + 10 // 1 second - overmind.add_points(point_rate) - health = min(initial(health), health + 1) - var/turf/T = get_turf(overmind) //The overmind's mind can expand the blob - var/obj/effect/blob/O = locate() in T //As long as it is 'thinking' about a blob already - for(var/i = 1; i < 8; i += i) - Pulse(0, i) - if(istype(O)) - O.Pulse(0,i) - for(var/b_dir in alldirs) - if(!prob(5)) - continue - var/obj/effect/blob/normal/B = locate() in get_step(src, b_dir) - if(B) - B.change_to(/obj/effect/blob/shield) - ..() - - -/obj/effect/blob/core/run_action() - return 0 - - -/obj/effect/blob/core/proc/create_overmind(var/client/new_overmind) - - - if(overmind_get_delay > world.time) - return - - overmind_get_delay = world.time + 300 // 30 seconds - - if(overmind) - qdel(overmind) - overmind = null - - var/client/C = null - var/list/candidates = list() - - if(!new_overmind) - candidates = get_candidates(ROLE_BLOB) - if(candidates.len) - C = pick(candidates) - else - C = new_overmind - - if(C) - var/mob/camera/blob/B = new(src.loc) - B.key = C.key - B.blob_core = src - src.overmind = B - if(!B.blob_core.creator) - B.verbs += /mob/camera/blob/proc/create_core - if(istype(ticker.mode, /datum/game_mode/blob)) - var/datum/game_mode/blob/mode = ticker.mode - mode.infected_crew += B.mind - return 1 - return 0 +/obj/effect/blob/core + name = "blob core" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_core" + health = 200 + fire_resist = 2 + custom_process=1 + var/mob/camera/blob/overmind = null // the blob core's overmind + var/overmind_get_delay = 0 // we don't want to constantly try to find an overmind, do it every 30 seconds + var/resource_delay = 0 + var/point_rate = 2 + var/mob/camera/blob/creator = null + + +/obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, var/mob/camera/blob/C = null) + blob_cores += src + processing_objects.Add(src) + creator = C + if(!overmind) + create_overmind(new_overmind) + point_rate = new_rate + ..(loc, h) + +/obj/effect/blob/core/Destroy() + blob_cores -= src + if(overmind) + qdel(overmind) + overmind = null + processing_objects.Remove(src) + ..() + +/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/effect/blob/core/update_icon() + if(health <= 0) + playsound(get_turf(src), 'sound/effects/blobkill.ogg', 50, 1) + Delete() + return + return + +/obj/effect/blob/core/Life() + if(timestopped) return 0 //under effects of time magick + + if(!overmind) + create_overmind() + else + if(resource_delay <= world.time) + resource_delay = world.time + 10 // 1 second + overmind.add_points(point_rate) + health = min(initial(health), health + 1) + var/turf/T = get_turf(overmind) //The overmind's mind can expand the blob + var/obj/effect/blob/O = locate() in T //As long as it is 'thinking' about a blob already + for(var/i = 1; i < 8; i += i) + Pulse(0, i) + if(istype(O)) + O.Pulse(0,i) + for(var/b_dir in alldirs) + if(!prob(5)) + continue + var/obj/effect/blob/normal/B = locate() in get_step(src, b_dir) + if(B) + B.change_to(/obj/effect/blob/shield) + ..() + + +/obj/effect/blob/core/run_action() + return 0 + + +/obj/effect/blob/core/proc/create_overmind(var/client/new_overmind) + + + if(overmind_get_delay > world.time) + return + + overmind_get_delay = world.time + 300 // 30 seconds + + if(overmind) + qdel(overmind) + overmind = null + + var/client/C = null + var/list/candidates = list() + + if(!new_overmind) + candidates = get_candidates(ROLE_BLOB) + if(candidates.len) + C = pick(candidates) + else + C = new_overmind + + if(C) + var/mob/camera/blob/B = new(src.loc) + B.key = C.key + B.blob_core = src + src.overmind = B + if(!B.blob_core.creator) + B.verbs += /mob/camera/blob/proc/create_core + if(istype(ticker.mode, /datum/game_mode/blob)) + var/datum/game_mode/blob/mode = ticker.mode + mode.infected_crew += B.mind + return 1 + return 0 diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm index 856b4a7d78e..df183239e2c 100644 --- a/code/game/gamemodes/blob/blobs/factory.dm +++ b/code/game/gamemodes/blob/blobs/factory.dm @@ -1,81 +1,81 @@ -/obj/effect/blob/factory - name = "factory blob" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_factory" - health = 100 - fire_resist = 2 - var/list/spores = list() - var/max_spores = 2 - var/spore_delay = 50 - -/obj/effect/blob/factory/update_icon() - if(health <= 0) - playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1) - qdel(src) - return - return - -/obj/effect/blob/factory/run_action() - if(spores.len >= max_spores) - return 0 - if(spore_delay > world.time) - return 0 - spore_delay = world.time + (40 SECONDS) // 30 seconds - new/mob/living/simple_animal/hostile/blobspore(src.loc, src) - return 1 - -/obj/effect/blob/factory/Destroy() - if(spores.len) - for(var/mob/living/simple_animal/hostile/blobspore/S in spores) - S.Die() - ..() - -/mob/living/simple_animal/hostile/blobspore - name = "Blob Spore" - desc = "A form of blob antibodies that attack foreign entities." - icon = 'icons/mob/blob.dmi' - icon_state = "blobpod" - icon_living = "blobpod" - pass_flags = PASSBLOB - health = 30 - maxHealth = 30 - melee_damage_lower = 2 - melee_damage_upper = 4 - attacktext = "hits" - attack_sound = 'sound/weapons/rapidslice.ogg' - can_butcher = 0 - var/obj/effect/blob/factory/factory = null - faction = "blob" - min_oxy = 0 - max_tox = 0 - max_co2 = 0 - minbodytemp = 0 - maxbodytemp = 360 - -/mob/living/simple_animal/hostile/blobspore/New(loc, var/obj/effect/blob/factory/linked_node) - if(istype(linked_node)) - factory = linked_node - factory.spores += src - ..() - -/mob/living/simple_animal/hostile/blobspore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - ..() - adjustBruteLoss(Clamp(0.01 * exposed_temperature, 1, 5)) - -/mob/living/simple_animal/hostile/blobspore/blob_act() - return - -/mob/living/simple_animal/hostile/blobspore/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover, /obj/effect/blob)) - return 1 - return ..() - -/mob/living/simple_animal/hostile/blobspore/Die() - var/sound = pick('sound/effects/gib1.ogg','sound/effects/gib2.ogg','sound/effects/gib3.ogg') - playsound(get_turf(src), sound, 50, 1) - qdel(src) - -/mob/living/simple_animal/hostile/blobspore/Destroy() - if(factory) - factory.spores -= src - ..() +/obj/effect/blob/factory + name = "factory blob" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_factory" + health = 100 + fire_resist = 2 + var/list/spores = list() + var/max_spores = 2 + var/spore_delay = 50 + +/obj/effect/blob/factory/update_icon() + if(health <= 0) + playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1) + qdel(src) + return + return + +/obj/effect/blob/factory/run_action() + if(spores.len >= max_spores) + return 0 + if(spore_delay > world.time) + return 0 + spore_delay = world.time + (40 SECONDS) // 30 seconds + new/mob/living/simple_animal/hostile/blobspore(src.loc, src) + return 1 + +/obj/effect/blob/factory/Destroy() + if(spores.len) + for(var/mob/living/simple_animal/hostile/blobspore/S in spores) + S.Die() + ..() + +/mob/living/simple_animal/hostile/blobspore + name = "Blob Spore" + desc = "A form of blob antibodies that attack foreign entities." + icon = 'icons/mob/blob.dmi' + icon_state = "blobpod" + icon_living = "blobpod" + pass_flags = PASSBLOB + health = 30 + maxHealth = 30 + melee_damage_lower = 2 + melee_damage_upper = 4 + attacktext = "hits" + attack_sound = 'sound/weapons/rapidslice.ogg' + can_butcher = 0 + var/obj/effect/blob/factory/factory = null + faction = "blob" + min_oxy = 0 + max_tox = 0 + max_co2 = 0 + minbodytemp = 0 + maxbodytemp = 360 + +/mob/living/simple_animal/hostile/blobspore/New(loc, var/obj/effect/blob/factory/linked_node) + if(istype(linked_node)) + factory = linked_node + factory.spores += src + ..() + +/mob/living/simple_animal/hostile/blobspore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + ..() + adjustBruteLoss(Clamp(0.01 * exposed_temperature, 1, 5)) + +/mob/living/simple_animal/hostile/blobspore/blob_act() + return + +/mob/living/simple_animal/hostile/blobspore/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover, /obj/effect/blob)) + return 1 + return ..() + +/mob/living/simple_animal/hostile/blobspore/Die() + var/sound = pick('sound/effects/gib1.ogg','sound/effects/gib2.ogg','sound/effects/gib3.ogg') + playsound(get_turf(src), sound, 50, 1) + qdel(src) + +/mob/living/simple_animal/hostile/blobspore/Destroy() + if(factory) + factory.spores -= src + ..() diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm index 6bc6522a0c8..024f86e327c 100644 --- a/code/game/gamemodes/blob/blobs/node.dm +++ b/code/game/gamemodes/blob/blobs/node.dm @@ -1,38 +1,38 @@ -/obj/effect/blob/node - name = "blob node" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_node" - health = 100 - fire_resist = 2 - custom_process=1 - - -/obj/effect/blob/node/New(loc, var/h = 100) - blob_nodes += src - processing_objects.Add(src) - ..(loc, h) - -/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/effect/blob/node/Destroy() - blob_nodes -= src - processing_objects.Remove(src) - ..() - -/obj/effect/blob/node/Life() - if(timestopped) return 0 //under effects of time magick - - for(var/i = 1; i < 8; i += i) - Pulse(5, i) - health = min(initial(health), health + 1) - -/obj/effect/blob/node/update_icon() - if(health <= 0) - playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1) - Delete() - return - return - -/obj/effect/blob/node/run_action() - return 0 +/obj/effect/blob/node + name = "blob node" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_node" + health = 100 + fire_resist = 2 + custom_process=1 + + +/obj/effect/blob/node/New(loc, var/h = 100) + blob_nodes += src + processing_objects.Add(src) + ..(loc, h) + +/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/effect/blob/node/Destroy() + blob_nodes -= src + processing_objects.Remove(src) + ..() + +/obj/effect/blob/node/Life() + if(timestopped) return 0 //under effects of time magick + + for(var/i = 1; i < 8; i += i) + Pulse(5, i) + health = min(initial(health), health + 1) + +/obj/effect/blob/node/update_icon() + if(health <= 0) + playsound(get_turf(src), 'sound/effects/blobsplatspecial.ogg', 50, 1) + Delete() + return + return + +/obj/effect/blob/node/run_action() + return 0 diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm index 6114e8a4e2d..0d7ed4a888e 100644 --- a/code/game/gamemodes/blob/blobs/shield.dm +++ b/code/game/gamemodes/blob/blobs/shield.dm @@ -1,29 +1,29 @@ -/obj/effect/blob/shield - name = "strong blob" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_idle" - desc = "Some blob creature thingy" - health = 75 - fire_resist = 2 - - -/obj/effect/blob/shield/update_icon() - if(health <= 0) - playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1) - qdel(src) - return - return - -/obj/effect/blob/shield/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/effect/blob/shield/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 - return 0 - -/obj/effect/blob/shield/run_action() - if(health >= 50) - return 0 - - health += 10 - return 1 +/obj/effect/blob/shield + name = "strong blob" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_idle" + desc = "Some blob creature thingy" + health = 75 + fire_resist = 2 + + +/obj/effect/blob/shield/update_icon() + if(health <= 0) + playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1) + qdel(src) + return + return + +/obj/effect/blob/shield/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/effect/blob/shield/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 + return 0 + +/obj/effect/blob/shield/run_action() + if(health >= 50) + return 0 + + health += 10 + return 1 diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index e3c30b1fc9e..9866b99a61c 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -1,221 +1,221 @@ -//I will need to recode parts of this but I am way too tired atm -/obj/effect/blob - name = "blob" - icon = 'icons/mob/blob.dmi' - luminosity = 3 - desc = "Some blob creature thingy" - density = 0 - opacity = 0 - anchored = 1 - penetration_dampening = 17 - var/health = 20 - var/health_timestamp = 0 - var/brute_resist = 4 - var/fire_resist = 1 - - // A note to the beam processing shit. - var/custom_process=0 - -/obj/effect/blob/New(loc) - blobs += src - if(istype(ticker.mode,/datum/game_mode/blob)) - var/datum/game_mode/blob/blobmode = ticker.mode - if((blobs.len >= blobmode.blobnukeposs) && prob(3) && !blobmode.nuclear) - blobmode.stage(2) - blobmode.nuclear = 1 - src.dir = pick(cardinal) - src.update_icon() - ..(loc) - for(var/atom/A in loc) - A.blob_act() - return - - -/obj/effect/blob/Destroy() - blobs -= src - ..() - -/obj/effect/blob/projectile_check() - return PROJREACT_BLOB - -/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 - return 0 - -/obj/effect/blob/beam_connect(var/obj/effect/beam/B) - ..() - last_beamchecks["\ref[B]"]=world.time+1 - apply_beam_damage(B) // Contact damage for larger beams (deals 1/10th second of damage) - if(!custom_process && !(src in processing_objects)) - processing_objects.Add(src) - - -/obj/effect/blob/beam_disconnect(var/obj/effect/beam/B) - ..() - apply_beam_damage(B) - last_beamchecks.Remove("\ref[B]") // RIP - update_icon() - if(beams.len == 0) - if(!custom_process && src in processing_objects) - processing_objects.Remove(src) - -/obj/effect/blob/apply_beam_damage(var/obj/effect/beam/B) - var/lastcheck=last_beamchecks["\ref[B]"] - - // Standard damage formula / 2 - var/damage = ((world.time - lastcheck)/10) * (B.get_damage() / 2) - - // Actually apply damage - health -= damage - - // Update check time. - last_beamchecks["\ref[B]"]=world.time - -/obj/effect/blob/handle_beams() - // New beam damage code (per-tick) - for(var/obj/effect/beam/B in beams) - apply_beam_damage(B) - update_icon() - -/obj/effect/blob/process() - handle_beams() - Life() - return - -/obj/effect/blob/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - ..() - var/damage = Clamp(0.01 * exposed_temperature / fire_resist, 0, 4 - fire_resist) - if(damage) - health -= damage - update_icon() - -/obj/effect/blob/proc/Life() - return - - -/obj/effect/blob/proc/Pulse(var/pulse = 0, var/origin_dir = 0)//Todo: Fix spaceblob expand - - - //set background = 1 - - if(run_action())//If we can do something here then we dont need to pulse more - return - - if(pulse > 30) - return//Inf loop check - - //Looking for another blob to pulse - var/list/dirs = cardinal.Copy() - dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us - for(var/i in 1 to 4) - if(!dirs.len) break - var/dirn = pick_n_take(dirs) - var/turf/T = get_step(src, dirn) - var/obj/effect/blob/B = locate() in T - if(!B) - expand(T)//No blob here so try and expand - return - B.Pulse((pulse+1),get_dir(src.loc,T)) - return - return - - -/obj/effect/blob/proc/run_action() - return 0 - - -/obj/effect/blob/proc/expand(var/turf/T = null, var/prob = 1) - if(prob && !prob(health)) - return - if(istype(T, /turf/space) && prob(75)) - return - if(!T) - var/list/dirs = cardinal.Copy() - for(var/i in 1 to 4) - var/dirn = pick_n_take(dirs) - T = get_step(src, dirn) - if(!(locate(/obj/effect/blob) in T)) break - else T = null - - if(!T) return 0 - var/obj/effect/blob/normal/B = new(src.loc, min(src.health, 30)) - B.density = 1 - if(T.Enter(B,src))//Attempt to move into the tile - B.density = initial(B.density) - B.loc = T - else - T.blob_act()//If we cant move in hit the turf - B.Delete() - - for(var/atom/A in T)//Hit everything in the turf - A.blob_act() - return 1 - - -/obj/effect/blob/ex_act(severity) - var/damage = 150 - health -= ((damage/brute_resist) - (severity * 5)) - update_icon() - return - - -/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj) - ..() - switch(Proj.damage_type) - if(BRUTE) - health -= (Proj.damage/brute_resist) - if(BURN) - health -= (Proj.damage/fire_resist) - update_icon() - return 0 - - -/obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/user) - user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/attackblob.ogg', 50, 1) - src.visible_message("The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]") - var/damage = 0 - switch(W.damtype) - if("fire") - damage = (W.force / max(src.fire_resist,1)) - if(istype(W, /obj/item/weapon/weldingtool)) - playsound(get_turf(src), 'sound/effects/blobweld.ogg', 100, 1) - if("brute") - damage = (W.force / max(src.brute_resist,1)) - - health -= damage - update_icon() - return - -/obj/effect/blob/proc/change_to(var/type, var/mob/camera/blob/M = null) - if(!ispath(type)) - error("[type] is an invalid type for the blob.") - if("[type]" == "/obj/effect/blob/core") - new type(src.loc, 200, null, 1, M) - else - new type(src.loc) - Delete() - return - -/obj/effect/blob/proc/Delete() - qdel(src) - -/obj/effect/blob/normal - icon_state = "blob" - luminosity = 0 - health = 21 - -/obj/effect/blob/normal/Delete() - src.loc = null - blobs -= src - ..() - -/obj/effect/blob/normal/update_icon() - if(health <= 0) - playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1) - Delete() - return - if(health <= 15) - icon_state = "blob_damaged" - return +//I will need to recode parts of this but I am way too tired atm +/obj/effect/blob + name = "blob" + icon = 'icons/mob/blob.dmi' + luminosity = 3 + desc = "Some blob creature thingy" + density = 0 + opacity = 0 + anchored = 1 + penetration_dampening = 17 + var/health = 20 + var/health_timestamp = 0 + var/brute_resist = 4 + var/fire_resist = 1 + + // A note to the beam processing shit. + var/custom_process=0 + +/obj/effect/blob/New(loc) + blobs += src + if(istype(ticker.mode,/datum/game_mode/blob)) + var/datum/game_mode/blob/blobmode = ticker.mode + if((blobs.len >= blobmode.blobnukeposs) && prob(3) && !blobmode.nuclear) + blobmode.stage(2) + blobmode.nuclear = 1 + src.dir = pick(cardinal) + src.update_icon() + ..(loc) + for(var/atom/A in loc) + A.blob_act() + return + + +/obj/effect/blob/Destroy() + blobs -= src + ..() + +/obj/effect/blob/projectile_check() + return PROJREACT_BLOB + +/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 + return 0 + +/obj/effect/blob/beam_connect(var/obj/effect/beam/B) + ..() + last_beamchecks["\ref[B]"]=world.time+1 + apply_beam_damage(B) // Contact damage for larger beams (deals 1/10th second of damage) + if(!custom_process && !(src in processing_objects)) + processing_objects.Add(src) + + +/obj/effect/blob/beam_disconnect(var/obj/effect/beam/B) + ..() + apply_beam_damage(B) + last_beamchecks.Remove("\ref[B]") // RIP + update_icon() + if(beams.len == 0) + if(!custom_process && src in processing_objects) + processing_objects.Remove(src) + +/obj/effect/blob/apply_beam_damage(var/obj/effect/beam/B) + var/lastcheck=last_beamchecks["\ref[B]"] + + // Standard damage formula / 2 + var/damage = ((world.time - lastcheck)/10) * (B.get_damage() / 2) + + // Actually apply damage + health -= damage + + // Update check time. + last_beamchecks["\ref[B]"]=world.time + +/obj/effect/blob/handle_beams() + // New beam damage code (per-tick) + for(var/obj/effect/beam/B in beams) + apply_beam_damage(B) + update_icon() + +/obj/effect/blob/process() + handle_beams() + Life() + return + +/obj/effect/blob/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + ..() + var/damage = Clamp(0.01 * exposed_temperature / fire_resist, 0, 4 - fire_resist) + if(damage) + health -= damage + update_icon() + +/obj/effect/blob/proc/Life() + return + + +/obj/effect/blob/proc/Pulse(var/pulse = 0, var/origin_dir = 0)//Todo: Fix spaceblob expand + + + //set background = 1 + + if(run_action())//If we can do something here then we dont need to pulse more + return + + if(pulse > 30) + return//Inf loop check + + //Looking for another blob to pulse + var/list/dirs = cardinal.Copy() + dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us + for(var/i in 1 to 4) + if(!dirs.len) break + var/dirn = pick_n_take(dirs) + var/turf/T = get_step(src, dirn) + var/obj/effect/blob/B = locate() in T + if(!B) + expand(T)//No blob here so try and expand + return + B.Pulse((pulse+1),get_dir(src.loc,T)) + return + return + + +/obj/effect/blob/proc/run_action() + return 0 + + +/obj/effect/blob/proc/expand(var/turf/T = null, var/prob = 1) + if(prob && !prob(health)) + return + if(istype(T, /turf/space) && prob(75)) + return + if(!T) + var/list/dirs = cardinal.Copy() + for(var/i in 1 to 4) + var/dirn = pick_n_take(dirs) + T = get_step(src, dirn) + if(!(locate(/obj/effect/blob) in T)) break + else T = null + + if(!T) return 0 + var/obj/effect/blob/normal/B = new(src.loc, min(src.health, 30)) + B.density = 1 + if(T.Enter(B,src))//Attempt to move into the tile + B.density = initial(B.density) + B.loc = T + else + T.blob_act()//If we cant move in hit the turf + B.Delete() + + for(var/atom/A in T)//Hit everything in the turf + A.blob_act() + return 1 + + +/obj/effect/blob/ex_act(severity) + var/damage = 150 + health -= ((damage/brute_resist) - (severity * 5)) + update_icon() + return + + +/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj) + ..() + switch(Proj.damage_type) + if(BRUTE) + health -= (Proj.damage/brute_resist) + if(BURN) + health -= (Proj.damage/fire_resist) + update_icon() + return 0 + + +/obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/user) + user.delayNextAttack(10) + playsound(get_turf(src), 'sound/effects/attackblob.ogg', 50, 1) + src.visible_message("The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]") + var/damage = 0 + switch(W.damtype) + if("fire") + damage = (W.force / max(src.fire_resist,1)) + if(istype(W, /obj/item/weapon/weldingtool)) + playsound(get_turf(src), 'sound/effects/blobweld.ogg', 100, 1) + if("brute") + damage = (W.force / max(src.brute_resist,1)) + + health -= damage + update_icon() + return + +/obj/effect/blob/proc/change_to(var/type, var/mob/camera/blob/M = null) + if(!ispath(type)) + error("[type] is an invalid type for the blob.") + if("[type]" == "/obj/effect/blob/core") + new type(src.loc, 200, null, 1, M) + else + new type(src.loc) + Delete() + return + +/obj/effect/blob/proc/Delete() + qdel(src) + +/obj/effect/blob/normal + icon_state = "blob" + luminosity = 0 + health = 21 + +/obj/effect/blob/normal/Delete() + src.loc = null + blobs -= src + ..() + +/obj/effect/blob/normal/update_icon() + if(health <= 0) + playsound(get_turf(src), 'sound/effects/blobsplat.ogg', 50, 1) + Delete() + return + if(health <= 15) + icon_state = "blob_damaged" + return diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 33b96aa2829..a18b7f38c2a 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -1,292 +1,292 @@ -var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega") - -/datum/game_mode - var/list/datum/mind/changelings = list() - - -/datum/game_mode/changeling - name = "changeling" - config_tag = "changeling" - restricted_jobs = list("AI", "Cyborg", "Mobile MMI") - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") - required_players = 1 - required_players_secret = 20 - required_enemies = 1 - recommended_enemies = 4 - - uplink_welcome = "Syndicate Uplink Console:" - uplink_uses = 10 - - var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time - var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target - var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target - - var/const/prob_int_item = 50 // intercept names the theft target half the time - var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target - var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target - - var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time - var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target - var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target - - var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative - var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative - var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly - var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/changeling_amount = 4 - -/datum/game_mode/changeling/announce() +var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega") + +/datum/game_mode + var/list/datum/mind/changelings = list() + + +/datum/game_mode/changeling + name = "changeling" + config_tag = "changeling" + restricted_jobs = list("AI", "Cyborg", "Mobile MMI") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") + required_players = 1 + required_players_secret = 20 + required_enemies = 1 + recommended_enemies = 4 + + uplink_welcome = "Syndicate Uplink Console:" + uplink_uses = 10 + + var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time + var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target + var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target + + var/const/prob_int_item = 50 // intercept names the theft target half the time + var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target + var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target + + var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time + var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target + var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target + + var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative + var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative + var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly + var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly + + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + + var/changeling_amount = 4 + +/datum/game_mode/changeling/announce() to_chat(world, "The current game mode is - Changeling!") to_chat(world, "There are alien changelings on the station. Do not let the changelings succeed!") - -/datum/game_mode/changeling/pre_setup() - if(istype(ticker.mode, /datum/game_mode/mixed)) - mixed = 1 - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING) - - for(var/datum/mind/player in possible_changelings) - if(mixed && (player in ticker.mode.modePlayer)) - possible_changelings -= player - continue - for(var/job in restricted_jobs)//Removing robots from the list - if(player.assigned_role == job) - possible_changelings -= player - - changeling_amount = 1 + round(num_players() / 10) - -// mixed mode scaling - if(mixed) - changeling_amount = min(2, changeling_amount) - - if(possible_changelings.len>0) - for(var/i = 0, i < changeling_amount, i++) - if(!possible_changelings.len) break - var/datum/mind/changeling = pick(possible_changelings) - if(changeling.special_role) - possible_changelings.Remove(changeling) - continue - possible_changelings -= changeling - changelings += changeling - modePlayer += changelings - log_admin("Starting a round of changeling with [changelings.len] changelings.") - message_admins("Starting a round of changeling with [changelings.len] changelings.") - if(mixed) - ticker.mode.modePlayer += changelings //merge into master antag list - ticker.mode.changelings += changelings - return 1 - else - log_admin("Failed to set-up a round of changeling. Couldn't find any volunteers to be changeling.") - message_admins("Failed to set-up a round of changeling. Couldn't find any volunteers to be changeling.") - if(mixed) - ticker.mode.modePlayer -= changelings //merge into master antag list - ticker.mode.traitors -= changelings - return 0 - -/datum/game_mode/changeling/post_setup() - for(var/datum/mind/changeling in changelings) - grant_changeling_powers(changeling.current) - changeling.special_role = "Changeling" - forge_changeling_objectives(changeling) - greet_changeling(changeling) - if(!mixed) - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - ..() - return - - -/datum/game_mode/proc/forge_changeling_objectives(var/datum/mind/changeling) - //OBJECTIVES - Always absorb 5 genomes, plus random traitor objectives. - //If they have two objectives as well as absorb, they must survive rather than escape - //No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting - //If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone - - var/datum/objective/absorb/absorb_objective = new - absorb_objective.owner = changeling - absorb_objective.gen_amount_goal(2, 3) - changeling.objectives += absorb_objective - - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = changeling - kill_objective.find_target() - changeling.objectives += kill_objective - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = changeling - steal_objective.find_target() - changeling.objectives += steal_objective - - - switch(rand(1,100)) - if(1 to 80) - if (!(locate(/datum/objective/escape) in changeling.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = changeling - changeling.objectives += escape_objective - else - if (!(locate(/datum/objective/survive) in changeling.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = changeling - changeling.objectives += survive_objective - return - -/datum/game_mode/proc/greet_changeling(var/datum/mind/changeling, var/you_are=1) - if (you_are) + +/datum/game_mode/changeling/pre_setup() + if(istype(ticker.mode, /datum/game_mode/mixed)) + mixed = 1 + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING) + + for(var/datum/mind/player in possible_changelings) + if(mixed && (player in ticker.mode.modePlayer)) + possible_changelings -= player + continue + for(var/job in restricted_jobs)//Removing robots from the list + if(player.assigned_role == job) + possible_changelings -= player + + changeling_amount = 1 + round(num_players() / 10) + +// mixed mode scaling + if(mixed) + changeling_amount = min(2, changeling_amount) + + if(possible_changelings.len>0) + for(var/i = 0, i < changeling_amount, i++) + if(!possible_changelings.len) break + var/datum/mind/changeling = pick(possible_changelings) + if(changeling.special_role) + possible_changelings.Remove(changeling) + continue + possible_changelings -= changeling + changelings += changeling + modePlayer += changelings + log_admin("Starting a round of changeling with [changelings.len] changelings.") + message_admins("Starting a round of changeling with [changelings.len] changelings.") + if(mixed) + ticker.mode.modePlayer += changelings //merge into master antag list + ticker.mode.changelings += changelings + return 1 + else + log_admin("Failed to set-up a round of changeling. Couldn't find any volunteers to be changeling.") + message_admins("Failed to set-up a round of changeling. Couldn't find any volunteers to be changeling.") + if(mixed) + ticker.mode.modePlayer -= changelings //merge into master antag list + ticker.mode.traitors -= changelings + return 0 + +/datum/game_mode/changeling/post_setup() + for(var/datum/mind/changeling in changelings) + grant_changeling_powers(changeling.current) + changeling.special_role = "Changeling" + forge_changeling_objectives(changeling) + greet_changeling(changeling) + if(!mixed) + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + ..() + return + + +/datum/game_mode/proc/forge_changeling_objectives(var/datum/mind/changeling) + //OBJECTIVES - Always absorb 5 genomes, plus random traitor objectives. + //If they have two objectives as well as absorb, they must survive rather than escape + //No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting + //If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone + + var/datum/objective/absorb/absorb_objective = new + absorb_objective.owner = changeling + absorb_objective.gen_amount_goal(2, 3) + changeling.objectives += absorb_objective + + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = changeling + kill_objective.find_target() + changeling.objectives += kill_objective + + var/datum/objective/steal/steal_objective = new + steal_objective.owner = changeling + steal_objective.find_target() + changeling.objectives += steal_objective + + + switch(rand(1,100)) + if(1 to 80) + if (!(locate(/datum/objective/escape) in changeling.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = changeling + changeling.objectives += escape_objective + else + if (!(locate(/datum/objective/survive) in changeling.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = changeling + changeling.objectives += survive_objective + return + +/datum/game_mode/proc/greet_changeling(var/datum/mind/changeling, var/you_are=1) + if (you_are) to_chat(changeling.current, "You are a changeling!") to_chat(changeling.current, "Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them.") to_chat(changeling.current, "You must complete the following tasks:") - - if (changeling.current.mind) - if (changeling.current.mind.assigned_role == "Clown") + + if (changeling.current.mind) + if (changeling.current.mind.assigned_role == "Clown") to_chat(changeling.current, "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself.") - changeling.current.mutations.Remove(M_CLUMSY) - - var/obj_count = 1 - for(var/datum/objective/objective in changeling.objectives) + changeling.current.mutations.Remove(M_CLUMSY) + + var/obj_count = 1 + for(var/datum/objective/objective in changeling.objectives) to_chat(changeling.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - return - -/*/datum/game_mode/changeling/check_finished() - var/changelings_alive = 0 - for(var/datum/mind/changeling in changelings) - if(!istype(changeling.current,/mob/living/carbon)) - continue - if(changeling.current.stat==2) - continue - changelings_alive++ - - if (changelings_alive) - changelingdeath = 0 - return ..() - else - if (!changelingdeath) - changelingdeathtime = world.time - changelingdeath = 1 - if(world.time-changelingdeathtime > TIME_TO_GET_REVIVED) - return 1 - else - return ..() - return 0*/ - -/datum/game_mode/proc/grant_changeling_powers(mob/living/carbon/changeling_mob) - if(!istype(changeling_mob)) return - changeling_mob.make_changeling() - -/datum/game_mode/proc/auto_declare_completion_changeling() - var/text = "" - if(changelings.len) - var/icon/logoa = icon('icons/mob/mob.dmi', "change-logoa") - var/icon/logob = icon('icons/mob/mob.dmi', "change-logob") - end_icons += logoa - var/tempstatea = end_icons.len - end_icons += logob - var/tempstateb = end_icons.len - text += {"
      The changelings were: "} - for(var/datum/mind/changeling in changelings) - var/changelingwin = 1 - - if(changeling.current) - var/icon/flat = getFlatIcon(changeling.current, SOUTH, 1, 1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [changeling.key] was [changeling.name] ("} - if(changeling.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(changeling.current.real_name != changeling.name) - text += " as [changeling.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - var/tempstate = end_icons.len - text += {"
      [changeling.key] was [changeling.name] ("} - text += "body destroyed" - changelingwin = 0 - text += ")" - - //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\changeling\changeling.dm:182: text += "
      Changeling ID: [changeling.changeling.changelingID]." - text += {"
      Changeling ID: [changeling.changeling.changelingID]. -Genomes Absorbed: [changeling.changeling.absorbedcount]"} - // END AUTOFIX - if(changeling.objectives.len) - var/count = 1 - for(var/datum/objective/objective in changeling.objectives) - if(objective.check_completion()) - text += "
      Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("changeling_objective","[objective.type]|SUCCESS") - else - text += "
      Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("changeling_objective","[objective.type]|FAIL") - changelingwin = 0 - count++ - - if(changelingwin) - text += "
      The changeling was successful!" - feedback_add_details("changeling_success","SUCCESS") - else - text += "
      The changeling has failed." - feedback_add_details("changeling_success","FAIL") - - if(changeling.total_TC) - if(changeling.spent_TC) - text += "
      TC Remaining: [changeling.total_TC - changeling.spent_TC]/[changeling.total_TC] - The tools used by the Changeling were: " - for(var/entry in changeling.uplink_items_bought) - text += "
      [entry]" - else - text += "
      The Changeling was a smooth operator this round (did not purchase any uplink items)" - text += "

      " - return text - -/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 - var/chem_storage = 50 - var/sting_range = 1 - var/changelingID = "Changeling" - var/geneticdamage = 0 - var/isabsorbing = 0 - var/geneticpoints = 5 - var/purchasedpowers = list() - var/mimicing = "" - -/datum/changeling/New(var/gender=FEMALE) - ..() - var/honorific - if(gender == FEMALE) honorific = "Ms." - else honorific = "Mr." - if(possible_changeling_IDs.len) - changelingID = pick(possible_changeling_IDs) - possible_changeling_IDs -= changelingID - changelingID = "[honorific] [changelingID]" - else - changelingID = "[honorific] [rand(1,999)]" - -/datum/changeling/proc/regenerate() - chem_charges = Clamp(chem_charges + chem_recharge_rate, 0, chem_storage) - geneticdamage = max(0, geneticdamage-1) - -/datum/changeling/proc/GetDNA(var/dna_owner) - var/datum/dna/chosen_dna - for(var/datum/dna/DNA in absorbed_dna) - if(dna_owner == DNA.real_name) - chosen_dna = DNA - break + obj_count++ + return + +/*/datum/game_mode/changeling/check_finished() + var/changelings_alive = 0 + for(var/datum/mind/changeling in changelings) + if(!istype(changeling.current,/mob/living/carbon)) + continue + if(changeling.current.stat==2) + continue + changelings_alive++ + + if (changelings_alive) + changelingdeath = 0 + return ..() + else + if (!changelingdeath) + changelingdeathtime = world.time + changelingdeath = 1 + if(world.time-changelingdeathtime > TIME_TO_GET_REVIVED) + return 1 + else + return ..() + return 0*/ + +/datum/game_mode/proc/grant_changeling_powers(mob/living/carbon/changeling_mob) + if(!istype(changeling_mob)) return + changeling_mob.make_changeling() + +/datum/game_mode/proc/auto_declare_completion_changeling() + var/text = "" + if(changelings.len) + var/icon/logoa = icon('icons/mob/mob.dmi', "change-logoa") + var/icon/logob = icon('icons/mob/mob.dmi', "change-logob") + end_icons += logoa + var/tempstatea = end_icons.len + end_icons += logob + var/tempstateb = end_icons.len + text += {"
      The changelings were: "} + for(var/datum/mind/changeling in changelings) + var/changelingwin = 1 + + if(changeling.current) + var/icon/flat = getFlatIcon(changeling.current, SOUTH, 1, 1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [changeling.key] was [changeling.name] ("} + if(changeling.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(changeling.current.real_name != changeling.name) + text += " as [changeling.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + var/tempstate = end_icons.len + text += {"
      [changeling.key] was [changeling.name] ("} + text += "body destroyed" + changelingwin = 0 + text += ")" + + //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\changeling\changeling.dm:182: text += "
      Changeling ID: [changeling.changeling.changelingID]." + text += {"
      Changeling ID: [changeling.changeling.changelingID]. +Genomes Absorbed: [changeling.changeling.absorbedcount]"} + // END AUTOFIX + if(changeling.objectives.len) + var/count = 1 + for(var/datum/objective/objective in changeling.objectives) + if(objective.check_completion()) + text += "
      Objective #[count]: [objective.explanation_text] Success!" + feedback_add_details("changeling_objective","[objective.type]|SUCCESS") + else + text += "
      Objective #[count]: [objective.explanation_text] Fail." + feedback_add_details("changeling_objective","[objective.type]|FAIL") + changelingwin = 0 + count++ + + if(changelingwin) + text += "
      The changeling was successful!" + feedback_add_details("changeling_success","SUCCESS") + else + text += "
      The changeling has failed." + feedback_add_details("changeling_success","FAIL") + + if(changeling.total_TC) + if(changeling.spent_TC) + text += "
      TC Remaining: [changeling.total_TC - changeling.spent_TC]/[changeling.total_TC] - The tools used by the Changeling were: " + for(var/entry in changeling.uplink_items_bought) + text += "
      [entry]" + else + text += "
      The Changeling was a smooth operator this round (did not purchase any uplink items)" + text += "

      " + return text + +/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 + var/chem_storage = 50 + var/sting_range = 1 + var/changelingID = "Changeling" + var/geneticdamage = 0 + var/isabsorbing = 0 + var/geneticpoints = 5 + var/purchasedpowers = list() + var/mimicing = "" + +/datum/changeling/New(var/gender=FEMALE) + ..() + var/honorific + if(gender == FEMALE) honorific = "Ms." + else honorific = "Mr." + if(possible_changeling_IDs.len) + changelingID = pick(possible_changeling_IDs) + possible_changeling_IDs -= changelingID + changelingID = "[honorific] [changelingID]" + else + changelingID = "[honorific] [rand(1,999)]" + +/datum/changeling/proc/regenerate() + chem_charges = Clamp(chem_charges + chem_recharge_rate, 0, chem_storage) + geneticdamage = max(0, geneticdamage-1) + +/datum/changeling/proc/GetDNA(var/dna_owner) + var/datum/dna/chosen_dna + for(var/datum/dna/DNA in absorbed_dna) + if(dna_owner == DNA.real_name) + chosen_dna = DNA + break return chosen_dna \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index d3d5e04379e..b843ae2068b 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -1,964 +1,964 @@ -//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 - - var/lesser_form = !ishuman(src) - - if(!powerinstances.len) - for(var/P in powers) - powerinstances += new P() - - // Code to auto-purchase free powers. - for(var/datum/power/changeling/P in powerinstances) - if(!P.genomecost) // Is it free? - if(!(P in mind.changeling.purchasedpowers)) // Do we not have it already? - mind.changeling.purchasePower(mind, P.name, 0)// Purchase it. Don't remake our verbs, we're doing it after this. - - for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) - if(P.isVerb) - if(lesser_form && !P.allowduringlesserform) continue - if(!(P in src.verbs)) - 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) - mind.changeling.absorbed_languages |= language - updateChangelingHUD() - return 1 - -/mob/proc/updateChangelingHUD() - if(hud_used) - if(!mind.changeling) return - if(!hud_used.vampire_blood_display) - hud_used.changeling_hud() - //hud_used.human_hud(hud_used.ui_style) - hud_used.vampire_blood_display.maptext_width = 64 - hud_used.vampire_blood_display.maptext_height = 32 - var/C = round(mind.changeling.chem_charges) - hud_used.vampire_blood_display.maptext = "
      C:[C]
      G:[mind.changeling.absorbedcount]
      " - return - -//Used to dump the languages from the changeling datum into the actual mob. -/mob/proc/changeling_update_languages(var/updated_languages) - - - languages.len = 0 - for(var/language in updated_languages) - languages += language - - //This isn't strictly necessary but just to be safe... - add_language("Changeling") - - 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)) - to_chat(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) - to_chat(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 - H.set_species(S,1) //Until someone moves body colour into DNA, they're going to have to use the default. - - spawn(10) - src.verbs += /mob/proc/changeling_change_species - src.regenerate_icons() - - changeling_update_languages(changeling.absorbed_languages) - feedback_add_details("changeling_powers","TR") - - return 1 - -/mob/proc/changeling_horror_form() - set category = "Changeling" - set name = "Horror Form (30)" - set desc = "This costly evolution allows us to transform into an all-consuming abomination. We are extremely strong, to the point that we can force airlocks open and devour humans whole, and immune to stuns." - - if(!istype(src, /mob/living/carbon/human)) - to_chat(usr, "We must be in human form before activating Horror Form.") - return - - var/datum/changeling/changeling = changeling_power(0,0,100) - if(!changeling) return - - var/mob/living/carbon/human/H = src - - for(var/obj/item/slot in H.get_all_slots()) - u_equip(slot, 1) - - monkeyizing = 1 - canmove = 0 - delayNextAttack(50) - icon = null - invisibility = 101 - - var/atom/movable/overlay/animation = new /atom/movable/overlay( loc ) - H.visible_message("[src] emits a putrid odor as their torso splits open!") - to_chat(world, sound('sound/effects/greaterling.ogg')) - to_chat(world, "A roar pierces the air and makes your blood curdle. Uh oh.") - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("h2horror", animation) - sleep(14*2) // Frames * lag - qdel(animation) - - monkeyizing = 0 - canmove = 1 - delayNextAttack(0) - icon = null - invisibility = initial(invisibility) - H.maxHealth = 800 /* Gonna need more than one egun to kill one of these bad boys*/ - H.health = 800 - H.set_species("Horror") - H.client.verbs |= H.species.abilities // Force ability equip. - H.update_icons() - -//removes our changeling verbs -/mob/proc/remove_changeling_powers() - if(!mind || !mind.changeling) return - for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) - if(P.isVerb) - verbs -= P.verbpath - - -//Helper proc. Does all the checks and stuff for us to avoid copypasta -/mob/proc/changeling_power(var/required_chems=0, var/required_dna=0, var/max_genetic_damage=100, var/max_stat=0, var/deny_horror=0) - - if(timestopped) return 0 //under effects of time magick - - if(!src.mind) return - if(!iscarbon(src)) return - - var/datum/changeling/changeling = src.mind.changeling - if(!changeling) - world.log << "[src] has the changeling_transform() verb but is not a changeling." - return - - if(src.stat > max_stat) - to_chat(src, "We are incapacitated.") - return - - if(changeling.absorbed_dna.len < required_dna) - to_chat(src, "We require at least [required_dna] samples of compatible DNA.") - return - - if(changeling.chem_charges < required_chems) - to_chat(src, "We require at least [required_chems] units of chemicals to do that!") - return - - if(changeling.geneticdamage > max_genetic_damage) - to_chat(src, "Our genomes are still reassembling. We need time to recover first.") - return - - var/mob/living/carbon/human/H = src - if(deny_horror && istype(H) && H.species && H.species.name == "Horror") - to_chat(src, "You are not permitted to taint our purity. You cannot do this as a Horror.") - return - - return changeling - - -//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() - set category = "Changeling" - set name = "Absorb DNA" - - var/datum/changeling/changeling = changeling_power(0,0,100) - if(!changeling) return - - var/obj/item/weapon/grab/G = src.get_active_hand() - if(!istype(G)) - to_chat(src, "We must be grabbing a creature in our active hand to absorb them.") - return - - var/mob/living/carbon/human/T = G.affecting - if(!istype(T)) - to_chat(src, "[T] is not compatible with our biology.") - return - - if(M_NOCLONE in T.mutations) - to_chat(src, "This creature's DNA is ruined beyond useability!") - return - - if(!G.state == GRAB_KILL) - to_chat(src, "We must have a tighter grip to absorb this creature.") - return - - if(changeling.isabsorbing) - to_chat(src, "We are already absorbing!") - return - - changeling.isabsorbing = 1 - for(var/stage = 1, stage<=3, stage++) - switch(stage) - if(1) - to_chat(src, "This creature is compatible. We must hold still...") - if(2) - to_chat(src, "We extend a proboscis.") - src.visible_message("[src] extends a proboscis!") - playsound(get_turf(src), 'sound/effects/lingextends.ogg', 50, 1) - if(3) - to_chat(src, "We stab [T] with the proboscis.") - src.visible_message("[src] stabs [T] with the proboscis!") - to_chat(T, "You feel a sharp stabbing pain!") - playsound(get_turf(src), 'sound/effects/lingstabs.ogg', 50, 1) - var/datum/organ/external/affecting = T.get_organ(src.zone_sel.selecting) - if(affecting.take_damage(39,0,1,"large organic needle")) - T:UpdateDamageIcon(1) - continue - - feedback_add_details("changeling_powers","A[stage]") - if(!do_mob(src, T, 150)) - to_chat(src, "Our absorption of [T] has been interrupted!") - changeling.isabsorbing = 0 - return - - to_chat(src, "We have absorbed [T]!") - src.visible_message("[src] sucks the fluids from [T]!") - to_chat(T, "You have been absorbed by the changeling!") - playsound(get_turf(src), 'sound/effects/lingabsorbs.ogg', 50, 1) - - T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set. - changeling.absorbed_dna |= T.dna - - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/thechangeling = src - var/avail_blood = T.vessel.get_reagent_amount("blood") - for(var/datum/reagent/blood/B in thechangeling.vessel.reagent_list) - B.volume = min(BLOOD_VOLUME_MAX, avail_blood + B.volume) - - if(src.nutrition < 400) src.nutrition = min((src.nutrition + T.nutrition), 400) - 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 - if(dna_data in changeling.absorbed_dna) - continue - changeling.absorbed_dna += dna_data - changeling.absorbedcount++ - T.mind.changeling.absorbed_dna.len = 1 - - if(T.mind.changeling.purchasedpowers) - for(var/datum/power/changeling/Tp in T.mind.changeling.purchasedpowers) - if(Tp in changeling.purchasedpowers) - continue - else - changeling.purchasedpowers += Tp - - if(!Tp.isVerb) - call(Tp.verbpath)() - else - src.make_changeling() - - changeling.chem_charges += T.mind.changeling.chem_charges - changeling.geneticpoints += T.mind.changeling.geneticpoints - T.mind.changeling.chem_charges = 0 - T.mind.changeling.geneticpoints = 0 - T.mind.changeling.absorbedcount = 0 - - changeling.absorbedcount++ - changeling.isabsorbing = 0 - updateChangelingHUD() - - T.death(0) - T.Drain() - return 1 - - -//Change our DNA to that of somebody we've absorbed. -/mob/proc/changeling_transform() - set category = "Changeling" - set name = "Transform (5)" - - var/datum/changeling/changeling = changeling_power(5,1,0, deny_horror=1) - if(!changeling) return - - var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - names += "[DNA.real_name]" - - var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names - if(!S) return - - var/datum/dna/chosen_dna = changeling.GetDNA(S) - if(!chosen_dna) - return - - changeling.chem_charges -= 5 - src.visible_message("[src] transforms!") - changeling.geneticdamage = 30 - var/oldspecies = src.dna.species - src.dna = chosen_dna.Clone() - src.real_name = chosen_dna.real_name - src.flavor_text = "" - src.UpdateAppearance() - var/mob/living/carbon/human/H = src - if(istype(H) && oldspecies != dna.species) - H.set_species(H.dna.species, 0) - domutcheck(src, null) - - src.verbs -= /mob/proc/changeling_transform - spawn(10) src.verbs += /mob/proc/changeling_transform - - feedback_add_details("changeling_powers","TR") - return 1 - - -//Transform into a monkey. //TODO replace with monkeyize proc -/mob/proc/changeling_lesser_form() - set category = "Changeling" - set name = "Lesser Form (1)" - - var/datum/changeling/changeling = changeling_power(1,0,0, deny_horror=1) - if(!changeling) return - - var/mob/living/carbon/human/C = src - - if(!istype(C) || !C.species.primitive) - to_chat(src, "We cannot perform this ability in this form!") - return - - changeling.chem_charges-- - C.remove_changeling_powers() - C.visible_message("[C] transforms!") - changeling.geneticdamage = 30 - to_chat(C, "Our genes cry out!") - - C.monkeyizing = 1 - C.canmove = 0 - C.icon = null - C.overlays.len = 0 - C.invisibility = 101 - C.delayNextAttack(50) - - var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("h2monkey", animation) - sleep(48) - animation.master = null - qdel(animation) - - - var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(src) - O.dna = C.dna.Clone() - C.dna = null - C.transferImplantsTo(O) - C.transferBorers(O) - - for(var/obj/item/W in C) - C.drop_from_inventory(W) - for(var/obj/T in C) - qdel(T) - - O.loc = C.loc - O.name = "monkey ([rand(1,1000)])" - O.setToxLoss(C.getToxLoss()) - O.adjustBruteLoss(C.getBruteLoss()) - O.setOxyLoss(C.getOxyLoss()) - O.adjustFireLoss(C.getFireLoss()) - O.stat = C.stat - O.delayNextAttack(0) - O.a_intent = I_HURT - C.mind.transfer_to(O) - O.make_changeling(1) - O.verbs += /mob/proc/changeling_lesser_transform - O.changeling_update_languages(O.mind.changeling.absorbed_languages) - feedback_add_details("changeling_powers","LF") - qdel(C) - C = null - return 1 - - -//Transform into a human -/mob/proc/changeling_lesser_transform() - set category = "Changeling" - set name = "Transform (1)" - - var/datum/changeling/changeling = changeling_power(1,1,0, deny_horror=1) - if(!changeling) return - - var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - names += "[DNA.real_name]" - - var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names - if(!S) return - - var/datum/dna/chosen_dna = changeling.GetDNA(S) - if(!chosen_dna) - return - - var/mob/living/carbon/C = src - - changeling.chem_charges-- - C.remove_changeling_powers() - C.visible_message("[C] transforms!") - C.dna = chosen_dna.Clone() - - C.monkeyizing = 1 - C.canmove = 0 - C.icon = null - C.overlays.len = 0 - C.invisibility = 101 - C.delayNextAttack(50) - var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("monkey2h", animation) - sleep(48) - qdel(animation) - animation = null - - var/mob/living/carbon/human/O = new /mob/living/carbon/human( src, delay_ready_dna=1 ) - if (C.dna.GetUIState(DNA_UI_GENDER)) - O.setGender(FEMALE) - else - O.setGender(MALE) - C.transferImplantsTo(O) - C.transferBorers(O) - O.dna = C.dna.Clone() - C.dna = null - O.real_name = chosen_dna.real_name - - for(var/obj/item/W in src) - C.drop_from_inventory(W) - for(var/obj/T in C) - qdel(T) - - O.loc = C.loc - - O.UpdateAppearance() - domutcheck(O, null) - O.setToxLoss(C.getToxLoss()) - O.adjustBruteLoss(C.getBruteLoss()) - O.setOxyLoss(C.getOxyLoss()) - O.adjustFireLoss(C.getFireLoss()) - O.stat = C.stat - O.delayNextAttack(0) - C.mind.transfer_to(O) - O.make_changeling() - O.changeling_update_languages(changeling.absorbed_languages) - - feedback_add_details("changeling_powers","LFT") - qdel(C) - C = null - return 1 - - -//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. -/mob/verb/check_mob_list() - set name = "(Mobs) Check Mob List" - set hidden = 1 - var/yes = 0 - if(src in mob_list) - yes = 1 - else - var/mob/M = locate(src) in mob_list - if(M == src) - yes = 1 - to_chat(usr, "[yes ? "" : ""] You are [yes ? "" : "not "]in the mob list") - yes = 0 - if(src in living_mob_list) - yes = 1 - else - var/mob/M = locate(src) in living_mob_list - if(M == src) - yes = 1 - to_chat(usr, "[yes ? "" : ""] You are [yes ? "" : "not "]in the living mob list") - -/mob/proc/changeling_returntolife() - set category = "Changeling" - set name = "Return To Life (20)" - - var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) - if(!changeling) return - - var/mob/living/carbon/C = src - if(changeling_power(20,1,100,DEAD)) - changeling.chem_charges -= 20 - dead_mob_list -= C - living_mob_list |= list(C) - C.stat = CONSCIOUS - C.tod = null - C.revive(0) - to_chat(C, "We have regenerated.") - C.visible_message("[src] appears to wake from the dead, having healed all wounds.") - C.status_flags &= ~(FAKEDEATH) - C.update_canmove() - C.make_changeling() - regenerate_icons() - src.verbs -= /mob/proc/changeling_returntolife - feedback_add_details("changeling_powers","RJ") - -/mob/proc/changeling_fakedeath() - set category = "Changeling" - set name = "Regenerative Stasis (20)" - - // BYOND bug where verbs don't update if you're not on a turf, as such you'll be permanently stuck in regen statis until you get moved to a turf. - if(!isturf(loc)) - to_chat(src, "((Due to a BYOND bug, it is not possible to come out of regenerative statis if you are not on a turf (walls, floors...)))") - return - - var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) - if(!changeling) return - - var/mob/living/carbon/C = src - if(C.suiciding) - to_chat(C, "Why would we wish to regenerate if we have already committed suicide?") - return - - if(!C.stat && alert("Are we sure we wish to fake our death?",,"Yes","No") == "No")//Confirmation for living changelings if they want to fake their death - return - to_chat(C, "We will attempt to regenerate our form.") - - C.status_flags |= FAKEDEATH //play dead - C.update_canmove() - C.remove_changeling_powers() - - C.emote("deathgasp") - C.tod = worldtime2text() - - spawn(rand(800,1200)) - to_chat(src, "We are now ready to regenerate.") - src.verbs += /mob/proc/changeling_returntolife - feedback_add_details("changeling_powers","FD") - return 1 - - -//Boosts the range of your next sting attack by 1 -/mob/proc/changeling_boost_range() - set category = "Changeling" - set name = "Ranged Sting (10)" - set desc="Your next sting ability can be used against targets 2 squares away." - - var/datum/changeling/changeling = changeling_power(10,0,100) - if(!changeling) return 0 - changeling.chem_charges -= 10 - to_chat(src, "Your throat adjusts to launch the sting.") - changeling.sting_range = 2 - src.verbs -= /mob/proc/changeling_boost_range - spawn(5) src.verbs += /mob/proc/changeling_boost_range - feedback_add_details("changeling_powers","RS") - return 1 - - -//Recover from stuns. -/mob/proc/changeling_unstun() - set category = "Changeling" - set name = "Epinephrine Sacs (45)" - set desc = "Removes all stuns" - - var/datum/changeling/changeling = changeling_power(45,0,100,UNCONSCIOUS) - if(!changeling) return 0 - changeling.chem_charges -= 45 - - var/mob/living/carbon/human/C = src - if(ishuman(src)) - var/mob/living/carbon/human/H=src - if(H.said_last_words) - H.said_last_words=0 - C.stat = 0 - C.SetParalysis(0) - C.SetStunned(0) - C.SetWeakened(0) - C.lying = 0 - C.update_canmove() - - src.verbs -= /mob/proc/changeling_unstun - spawn(5) src.verbs += /mob/proc/changeling_unstun - feedback_add_details("changeling_powers","UNS") - return 1 - - -//Speeds up chemical regeneration -/mob/proc/changeling_fastchemical() - src.mind.changeling.chem_recharge_rate *= 2 - return 1 - -//Increases macimum chemical storage -/mob/proc/changeling_engorgedglands() - src.mind.changeling.chem_storage += 25 - return 1 - - -//Prevents AIs tracking you but makes you easily detectable to the human-eye. -/mob/proc/changeling_digitalcamo() - set category = "Changeling" - set name = "Toggle Digital Camoflague" - set desc = "The AI can no longer track us, but we will look different if examined. Has a constant cost while active." - - var/datum/changeling/changeling = changeling_power() - if(!changeling) return 0 - - var/mob/living/carbon/human/C = src - if(C.digitalcamo) to_chat(C, "We return to normal.") - else to_chat(C, "We distort our form to prevent AI-tracking.") - C.digitalcamo = !C.digitalcamo - - spawn(0) - while(C && C.digitalcamo && C.mind && C.mind.changeling) - C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0) - sleep(40) - - src.verbs -= /mob/proc/changeling_digitalcamo - spawn(5) src.verbs += /mob/proc/changeling_digitalcamo - feedback_add_details("changeling_powers","CAM") - return 1 - - -//Starts healing you every second for 10 seconds. Can be used whilst unconscious. -/mob/proc/changeling_rapidregen() - set category = "Changeling" - set name = "Rapid Regeneration (30)" - set desc = "Begins rapidly regenerating. Does not effect stuns or chemicals." - - var/datum/changeling/changeling = changeling_power(30,0,100,UNCONSCIOUS) - if(!changeling) return 0 - src.mind.changeling.chem_charges -= 30 - - var/mob/living/carbon/human/C = src - spawn(0) - for(var/i = 0, i<10,i++) - if(C) - C.adjustBruteLoss(-10) - C.adjustToxLoss(-10) - C.adjustOxyLoss(-10) - C.adjustFireLoss(-10) - sleep(10) - - src.verbs -= /mob/proc/changeling_rapidregen - spawn(5) src.verbs += /mob/proc/changeling_rapidregen - feedback_add_details("changeling_powers","RR") - return 1 - -// HIVE MIND UPLOAD/DOWNLOAD DNA - -var/list/datum/dna/hivemind_bank = list() - -/mob/proc/changeling_hiveupload() - set category = "Changeling" - set name = "Hive Channel (10)" - set desc = "Allows you to channel DNA in the airwaves to allow other changelings to absorb it." - - var/datum/changeling/changeling = changeling_power(10,1) - if(!changeling) return - - var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - if(!(DNA in hivemind_bank)) - names += DNA.real_name - - if(names.len <= 0) - to_chat(src, "The airwaves already have all of our DNA.") - return - - var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names - if(!S) return - - var/datum/dna/chosen_dna = changeling.GetDNA(S) - if(!chosen_dna) - return - - changeling.chem_charges -= 10 - hivemind_bank += chosen_dna - to_chat(src, "We channel the DNA of [S] to the air.") - feedback_add_details("changeling_powers","HU") - return 1 - -/mob/proc/changeling_hivedownload() - set category = "Changeling" - set name = "Hive Absorb (20)" - set desc = "Allows you to absorb DNA that is being channeled in the airwaves." - - var/datum/changeling/changeling = changeling_power(20,1) - if(!changeling) return - - var/list/names = list() - for(var/datum/dna/DNA in hivemind_bank) - if(!(DNA in changeling.absorbed_dna)) - names[DNA.real_name] = DNA - - if(names.len <= 0) - to_chat(src, "There's no new DNA to absorb from the air.") - return - - var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names - if(!S) return - var/datum/dna/chosen_dna = names[S] - if(!chosen_dna) - return - - changeling.chem_charges -= 20 - changeling.absorbed_dna += chosen_dna - to_chat(src, "We absorb the DNA of [S] from the air.") - feedback_add_details("changeling_powers","HD") - return 1 - -// Fake Voice - -/mob/proc/changeling_mimicvoice() - set category = "Changeling" - set name = "Mimic Voice" - set desc = "Shape our vocal glands to form a voice of someone we choose. We cannot regenerate chemicals when mimicing." - - - if(!usr) - return - var/mob/user = usr - var/datum/changeling/changeling = changeling_power() - if(!changeling) return - - if(changeling.mimicing) - changeling.mimicing = "" - to_chat(src, "We return our vocal glands to their original location.") - return - - var/mimic_voice = stripped_input(user, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN) - if(!mimic_voice) - return - - changeling.mimicing = mimic_voice - - to_chat(src, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.") - to_chat(src, "Use this power again to return to our original voice and reproduce chemicals again.") - - feedback_add_details("changeling_powers","MV") - - spawn(0) - while(src && src.mind && src.mind.changeling && src.mind.changeling.mimicing) - src.mind.changeling.chem_charges = max(src.mind.changeling.chem_charges - 1, 0) - sleep(40) - if(src && src.mind && src.mind.changeling) - src.mind.changeling.mimicing = "" - ////////// - //STINGS// //They get a pretty header because there's just so fucking many of them ;_; - ////////// - -/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1) - if(M.loc == src.loc) return 1 //target and source are in the same thing - if(!isturf(src.loc) || !isturf(M.loc)) return 0 //One is inside, the other is outside something. - if(sting_range < 2) - return Adjacent(M) - if(AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, sting_range)) //If a path exists, good! - return 1 - return 0 - -//Handles the general sting code to reduce on copypasta (seeming as somebody decided to make SO MANY dumb abilities) -/mob/proc/changeling_sting(var/required_chems=0, var/verb_path) - var/datum/changeling/changeling = changeling_power(required_chems) - if(!changeling) return - - var/list/victims = list() - for(var/mob/living/carbon/C in oview(changeling.sting_range)) - victims += C - var/mob/living/carbon/T = input(src, "Who will we sting?") as null|anything in victims - - if(!T) return - if(!(T in view(changeling.sting_range))) return - if(!sting_can_reach(T, changeling.sting_range)) return - if(!changeling_power(required_chems)) return - - changeling.chem_charges -= required_chems - changeling.sting_range = 1 - src.verbs -= verb_path - spawn(10) src.verbs += verb_path - - to_chat(src, "We stealthily sting [T].") - if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting - to_chat(T, "You feel a tiny prick.") - return - - -/mob/proc/changeling_lsdsting() - set category = "Changeling" - set name = "Hallucination Sting (15)" - set desc = "Causes terror in the target." - - var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting) - if(!T) return 0 - spawn(rand(300,600)) - if(T) T.hallucination += 400 - feedback_add_details("changeling_powers","HS") - return 1 - -/mob/proc/changeling_silence_sting() - set category = "Changeling" - set name = "Silence sting (10)" - set desc="Sting target" - - var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting) - if(!T) return 0 - T.silent += 30 - feedback_add_details("changeling_powers","SS") - return 1 - -/mob/proc/changeling_blind_sting() - set category = "Changeling" - set name = "Blind sting (20)" - set desc="Sting target" - - var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting) - if(!T) return 0 - to_chat(T, "Your eyes burn horrificly!") - T.disabilities |= NEARSIGHTED - spawn(300) T.disabilities &= ~NEARSIGHTED - T.eye_blind = 10 - T.eye_blurry = 20 - feedback_add_details("changeling_powers","BS") - return 1 - -/mob/proc/changeling_deaf_sting() - set category = "Changeling" - set name = "Deaf sting (5)" - set desc="Sting target:" - - var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting) - if(!T) return 0 - to_chat(T, "Your ears pop and begin ringing loudly!") - T.sdisabilities |= DEAF - spawn(300) T.sdisabilities &= ~DEAF - feedback_add_details("changeling_powers","DS") - return 1 - -/mob/proc/changeling_paralysis_sting() - set category = "Changeling" - set name = "Paralysis sting (30)" - set desc="Sting target" - - var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting) - if(!T) return 0 - to_chat(T, "Your muscles begin to painfully tighten.") - T.Weaken(20) - feedback_add_details("changeling_powers","PS") - return 1 - -/mob/proc/changeling_transformation_sting() - set category = "Changeling" - set name = "Transformation sting (40)" - set desc="Sting target" - - var/datum/changeling/changeling = changeling_power(40) - if(!changeling) return 0 - - - - var/list/names = list() - for(var/datum/dna/DNA in changeling.absorbed_dna) - names += "[DNA.real_name]" - - var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names - if(!S) return - - var/datum/dna/chosen_dna = changeling.GetDNA(S) - if(!chosen_dna) - return - - var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting) - if(!T) return 0 - if((M_HUSK in T.mutations) || (!ishuman(T) && !ismonkey(T))) - to_chat(src, "Our sting appears ineffective against its DNA.") - return 0 - T.visible_message("[T] transforms!") - T.dna = chosen_dna.Clone() - T.real_name = chosen_dna.real_name - T.UpdateAppearance() - domutcheck(T, null) - feedback_add_details("changeling_powers","TS") - return 1 - -/mob/proc/changeling_unfat_sting() - set category = "Changeling" - set name = "Unfat sting" - set desc = "A rapid weightloss plan that actually works!" - - var/mob/living/carbon/T = changeling_sting(0,/mob/proc/changeling_unfat_sting) - if(!T) return 0 - if(T.overeatduration>100) - to_chat(T, "You feel a small prick as your stomach churns violently. You begin to feel skinnier.") - T.overeatduration = 0 - T.nutrition -= 100 - feedback_add_details("changeling_powers","US") - return 1 - -/mob/proc/changeling_DEATHsting() - set category = "Changeling" - set name = "Death Sting (40)" - set desc = "Causes spasms onto death." - - var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting) - if(!T) return 0 - to_chat(T, "You feel a small prick and your chest becomes tight.") - T.silent = 10 - T.Paralyse(10) - T.Jitter(1000) - if(T.reagents) T.reagents.add_reagent("lexorin", 40) - feedback_add_details("changeling_powers","DTHS") - return 1 - -/mob/proc/changeling_extract_dna_sting() - set category = "Changeling" - set name = "Extract DNA Sting (40)" - set desc="Stealthily sting a target to extract their DNA." - - var/datum/changeling/changeling = null - if(src.mind && src.mind.changeling) - changeling = src.mind.changeling - if(!changeling) - return 0 - - var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) - if(!T) return 0 - - T.dna.real_name = T.real_name - changeling.absorbed_dna |= T.dna - if(T.species && !(T.species.name in changeling.absorbed_species)) - changeling.absorbed_species += T.species.name - - feedback_add_details("changeling_powers","ED") - return 1 +//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 + + var/lesser_form = !ishuman(src) + + if(!powerinstances.len) + for(var/P in powers) + powerinstances += new P() + + // Code to auto-purchase free powers. + for(var/datum/power/changeling/P in powerinstances) + if(!P.genomecost) // Is it free? + if(!(P in mind.changeling.purchasedpowers)) // Do we not have it already? + mind.changeling.purchasePower(mind, P.name, 0)// Purchase it. Don't remake our verbs, we're doing it after this. + + for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) + if(P.isVerb) + if(lesser_form && !P.allowduringlesserform) continue + if(!(P in src.verbs)) + 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) + mind.changeling.absorbed_languages |= language + updateChangelingHUD() + return 1 + +/mob/proc/updateChangelingHUD() + if(hud_used) + if(!mind.changeling) return + if(!hud_used.vampire_blood_display) + hud_used.changeling_hud() + //hud_used.human_hud(hud_used.ui_style) + hud_used.vampire_blood_display.maptext_width = 64 + hud_used.vampire_blood_display.maptext_height = 32 + var/C = round(mind.changeling.chem_charges) + hud_used.vampire_blood_display.maptext = "
      C:[C]
      G:[mind.changeling.absorbedcount]
      " + return + +//Used to dump the languages from the changeling datum into the actual mob. +/mob/proc/changeling_update_languages(var/updated_languages) + + + languages.len = 0 + for(var/language in updated_languages) + languages += language + + //This isn't strictly necessary but just to be safe... + add_language("Changeling") + + 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)) + to_chat(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) + to_chat(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 + H.set_species(S,1) //Until someone moves body colour into DNA, they're going to have to use the default. + + spawn(10) + src.verbs += /mob/proc/changeling_change_species + src.regenerate_icons() + + changeling_update_languages(changeling.absorbed_languages) + feedback_add_details("changeling_powers","TR") + + return 1 + +/mob/proc/changeling_horror_form() + set category = "Changeling" + set name = "Horror Form (30)" + set desc = "This costly evolution allows us to transform into an all-consuming abomination. We are extremely strong, to the point that we can force airlocks open and devour humans whole, and immune to stuns." + + if(!istype(src, /mob/living/carbon/human)) + to_chat(usr, "We must be in human form before activating Horror Form.") + return + + var/datum/changeling/changeling = changeling_power(0,0,100) + if(!changeling) return + + var/mob/living/carbon/human/H = src + + for(var/obj/item/slot in H.get_all_slots()) + u_equip(slot, 1) + + monkeyizing = 1 + canmove = 0 + delayNextAttack(50) + icon = null + invisibility = 101 + + var/atom/movable/overlay/animation = new /atom/movable/overlay( loc ) + H.visible_message("[src] emits a putrid odor as their torso splits open!") + to_chat(world, sound('sound/effects/greaterling.ogg')) + to_chat(world, "A roar pierces the air and makes your blood curdle. Uh oh.") + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("h2horror", animation) + sleep(14*2) // Frames * lag + qdel(animation) + + monkeyizing = 0 + canmove = 1 + delayNextAttack(0) + icon = null + invisibility = initial(invisibility) + H.maxHealth = 800 /* Gonna need more than one egun to kill one of these bad boys*/ + H.health = 800 + H.set_species("Horror") + H.client.verbs |= H.species.abilities // Force ability equip. + H.update_icons() + +//removes our changeling verbs +/mob/proc/remove_changeling_powers() + if(!mind || !mind.changeling) return + for(var/datum/power/changeling/P in mind.changeling.purchasedpowers) + if(P.isVerb) + verbs -= P.verbpath + + +//Helper proc. Does all the checks and stuff for us to avoid copypasta +/mob/proc/changeling_power(var/required_chems=0, var/required_dna=0, var/max_genetic_damage=100, var/max_stat=0, var/deny_horror=0) + + if(timestopped) return 0 //under effects of time magick + + if(!src.mind) return + if(!iscarbon(src)) return + + var/datum/changeling/changeling = src.mind.changeling + if(!changeling) + world.log << "[src] has the changeling_transform() verb but is not a changeling." + return + + if(src.stat > max_stat) + to_chat(src, "We are incapacitated.") + return + + if(changeling.absorbed_dna.len < required_dna) + to_chat(src, "We require at least [required_dna] samples of compatible DNA.") + return + + if(changeling.chem_charges < required_chems) + to_chat(src, "We require at least [required_chems] units of chemicals to do that!") + return + + if(changeling.geneticdamage > max_genetic_damage) + to_chat(src, "Our genomes are still reassembling. We need time to recover first.") + return + + var/mob/living/carbon/human/H = src + if(deny_horror && istype(H) && H.species && H.species.name == "Horror") + to_chat(src, "You are not permitted to taint our purity. You cannot do this as a Horror.") + return + + return changeling + + +//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() + set category = "Changeling" + set name = "Absorb DNA" + + var/datum/changeling/changeling = changeling_power(0,0,100) + if(!changeling) return + + var/obj/item/weapon/grab/G = src.get_active_hand() + if(!istype(G)) + to_chat(src, "We must be grabbing a creature in our active hand to absorb them.") + return + + var/mob/living/carbon/human/T = G.affecting + if(!istype(T)) + to_chat(src, "[T] is not compatible with our biology.") + return + + if(M_NOCLONE in T.mutations) + to_chat(src, "This creature's DNA is ruined beyond useability!") + return + + if(!G.state == GRAB_KILL) + to_chat(src, "We must have a tighter grip to absorb this creature.") + return + + if(changeling.isabsorbing) + to_chat(src, "We are already absorbing!") + return + + changeling.isabsorbing = 1 + for(var/stage = 1, stage<=3, stage++) + switch(stage) + if(1) + to_chat(src, "This creature is compatible. We must hold still...") + if(2) + to_chat(src, "We extend a proboscis.") + src.visible_message("[src] extends a proboscis!") + playsound(get_turf(src), 'sound/effects/lingextends.ogg', 50, 1) + if(3) + to_chat(src, "We stab [T] with the proboscis.") + src.visible_message("[src] stabs [T] with the proboscis!") + to_chat(T, "You feel a sharp stabbing pain!") + playsound(get_turf(src), 'sound/effects/lingstabs.ogg', 50, 1) + var/datum/organ/external/affecting = T.get_organ(src.zone_sel.selecting) + if(affecting.take_damage(39,0,1,"large organic needle")) + T:UpdateDamageIcon(1) + continue + + feedback_add_details("changeling_powers","A[stage]") + if(!do_mob(src, T, 150)) + to_chat(src, "Our absorption of [T] has been interrupted!") + changeling.isabsorbing = 0 + return + + to_chat(src, "We have absorbed [T]!") + src.visible_message("[src] sucks the fluids from [T]!") + to_chat(T, "You have been absorbed by the changeling!") + playsound(get_turf(src), 'sound/effects/lingabsorbs.ogg', 50, 1) + + T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set. + changeling.absorbed_dna |= T.dna + + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/thechangeling = src + var/avail_blood = T.vessel.get_reagent_amount("blood") + for(var/datum/reagent/blood/B in thechangeling.vessel.reagent_list) + B.volume = min(BLOOD_VOLUME_MAX, avail_blood + B.volume) + + if(src.nutrition < 400) src.nutrition = min((src.nutrition + T.nutrition), 400) + 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 + if(dna_data in changeling.absorbed_dna) + continue + changeling.absorbed_dna += dna_data + changeling.absorbedcount++ + T.mind.changeling.absorbed_dna.len = 1 + + if(T.mind.changeling.purchasedpowers) + for(var/datum/power/changeling/Tp in T.mind.changeling.purchasedpowers) + if(Tp in changeling.purchasedpowers) + continue + else + changeling.purchasedpowers += Tp + + if(!Tp.isVerb) + call(Tp.verbpath)() + else + src.make_changeling() + + changeling.chem_charges += T.mind.changeling.chem_charges + changeling.geneticpoints += T.mind.changeling.geneticpoints + T.mind.changeling.chem_charges = 0 + T.mind.changeling.geneticpoints = 0 + T.mind.changeling.absorbedcount = 0 + + changeling.absorbedcount++ + changeling.isabsorbing = 0 + updateChangelingHUD() + + T.death(0) + T.Drain() + return 1 + + +//Change our DNA to that of somebody we've absorbed. +/mob/proc/changeling_transform() + set category = "Changeling" + set name = "Transform (5)" + + var/datum/changeling/changeling = changeling_power(5,1,0, deny_horror=1) + if(!changeling) return + + var/list/names = list() + for(var/datum/dna/DNA in changeling.absorbed_dna) + names += "[DNA.real_name]" + + var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names + if(!S) return + + var/datum/dna/chosen_dna = changeling.GetDNA(S) + if(!chosen_dna) + return + + changeling.chem_charges -= 5 + src.visible_message("[src] transforms!") + changeling.geneticdamage = 30 + var/oldspecies = src.dna.species + src.dna = chosen_dna.Clone() + src.real_name = chosen_dna.real_name + src.flavor_text = "" + src.UpdateAppearance() + var/mob/living/carbon/human/H = src + if(istype(H) && oldspecies != dna.species) + H.set_species(H.dna.species, 0) + domutcheck(src, null) + + src.verbs -= /mob/proc/changeling_transform + spawn(10) src.verbs += /mob/proc/changeling_transform + + feedback_add_details("changeling_powers","TR") + return 1 + + +//Transform into a monkey. //TODO replace with monkeyize proc +/mob/proc/changeling_lesser_form() + set category = "Changeling" + set name = "Lesser Form (1)" + + var/datum/changeling/changeling = changeling_power(1,0,0, deny_horror=1) + if(!changeling) return + + var/mob/living/carbon/human/C = src + + if(!istype(C) || !C.species.primitive) + to_chat(src, "We cannot perform this ability in this form!") + return + + changeling.chem_charges-- + C.remove_changeling_powers() + C.visible_message("[C] transforms!") + changeling.geneticdamage = 30 + to_chat(C, "Our genes cry out!") + + C.monkeyizing = 1 + C.canmove = 0 + C.icon = null + C.overlays.len = 0 + C.invisibility = 101 + C.delayNextAttack(50) + + var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("h2monkey", animation) + sleep(48) + animation.master = null + qdel(animation) + + + var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(src) + O.dna = C.dna.Clone() + C.dna = null + C.transferImplantsTo(O) + C.transferBorers(O) + + for(var/obj/item/W in C) + C.drop_from_inventory(W) + for(var/obj/T in C) + qdel(T) + + O.loc = C.loc + O.name = "monkey ([rand(1,1000)])" + O.setToxLoss(C.getToxLoss()) + O.adjustBruteLoss(C.getBruteLoss()) + O.setOxyLoss(C.getOxyLoss()) + O.adjustFireLoss(C.getFireLoss()) + O.stat = C.stat + O.delayNextAttack(0) + O.a_intent = I_HURT + C.mind.transfer_to(O) + O.make_changeling(1) + O.verbs += /mob/proc/changeling_lesser_transform + O.changeling_update_languages(O.mind.changeling.absorbed_languages) + feedback_add_details("changeling_powers","LF") + qdel(C) + C = null + return 1 + + +//Transform into a human +/mob/proc/changeling_lesser_transform() + set category = "Changeling" + set name = "Transform (1)" + + var/datum/changeling/changeling = changeling_power(1,1,0, deny_horror=1) + if(!changeling) return + + var/list/names = list() + for(var/datum/dna/DNA in changeling.absorbed_dna) + names += "[DNA.real_name]" + + var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names + if(!S) return + + var/datum/dna/chosen_dna = changeling.GetDNA(S) + if(!chosen_dna) + return + + var/mob/living/carbon/C = src + + changeling.chem_charges-- + C.remove_changeling_powers() + C.visible_message("[C] transforms!") + C.dna = chosen_dna.Clone() + + C.monkeyizing = 1 + C.canmove = 0 + C.icon = null + C.overlays.len = 0 + C.invisibility = 101 + C.delayNextAttack(50) + var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("monkey2h", animation) + sleep(48) + qdel(animation) + animation = null + + var/mob/living/carbon/human/O = new /mob/living/carbon/human( src, delay_ready_dna=1 ) + if (C.dna.GetUIState(DNA_UI_GENDER)) + O.setGender(FEMALE) + else + O.setGender(MALE) + C.transferImplantsTo(O) + C.transferBorers(O) + O.dna = C.dna.Clone() + C.dna = null + O.real_name = chosen_dna.real_name + + for(var/obj/item/W in src) + C.drop_from_inventory(W) + for(var/obj/T in C) + qdel(T) + + O.loc = C.loc + + O.UpdateAppearance() + domutcheck(O, null) + O.setToxLoss(C.getToxLoss()) + O.adjustBruteLoss(C.getBruteLoss()) + O.setOxyLoss(C.getOxyLoss()) + O.adjustFireLoss(C.getFireLoss()) + O.stat = C.stat + O.delayNextAttack(0) + C.mind.transfer_to(O) + O.make_changeling() + O.changeling_update_languages(changeling.absorbed_languages) + + feedback_add_details("changeling_powers","LFT") + qdel(C) + C = null + return 1 + + +//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. +/mob/verb/check_mob_list() + set name = "(Mobs) Check Mob List" + set hidden = 1 + var/yes = 0 + if(src in mob_list) + yes = 1 + else + var/mob/M = locate(src) in mob_list + if(M == src) + yes = 1 + to_chat(usr, "[yes ? "" : ""] You are [yes ? "" : "not "]in the mob list") + yes = 0 + if(src in living_mob_list) + yes = 1 + else + var/mob/M = locate(src) in living_mob_list + if(M == src) + yes = 1 + to_chat(usr, "[yes ? "" : ""] You are [yes ? "" : "not "]in the living mob list") + +/mob/proc/changeling_returntolife() + set category = "Changeling" + set name = "Return To Life (20)" + + var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) + if(!changeling) return + + var/mob/living/carbon/C = src + if(changeling_power(20,1,100,DEAD)) + changeling.chem_charges -= 20 + dead_mob_list -= C + living_mob_list |= list(C) + C.stat = CONSCIOUS + C.tod = null + C.revive(0) + to_chat(C, "We have regenerated.") + C.visible_message("[src] appears to wake from the dead, having healed all wounds.") + C.status_flags &= ~(FAKEDEATH) + C.update_canmove() + C.make_changeling() + regenerate_icons() + src.verbs -= /mob/proc/changeling_returntolife + feedback_add_details("changeling_powers","RJ") + +/mob/proc/changeling_fakedeath() + set category = "Changeling" + set name = "Regenerative Stasis (20)" + + // BYOND bug where verbs don't update if you're not on a turf, as such you'll be permanently stuck in regen statis until you get moved to a turf. + if(!isturf(loc)) + to_chat(src, "((Due to a BYOND bug, it is not possible to come out of regenerative statis if you are not on a turf (walls, floors...)))") + return + + var/datum/changeling/changeling = changeling_power(20,1,100,DEAD) + if(!changeling) return + + var/mob/living/carbon/C = src + if(C.suiciding) + to_chat(C, "Why would we wish to regenerate if we have already committed suicide?") + return + + if(!C.stat && alert("Are we sure we wish to fake our death?",,"Yes","No") == "No")//Confirmation for living changelings if they want to fake their death + return + to_chat(C, "We will attempt to regenerate our form.") + + C.status_flags |= FAKEDEATH //play dead + C.update_canmove() + C.remove_changeling_powers() + + C.emote("deathgasp") + C.tod = worldtime2text() + + spawn(rand(800,1200)) + to_chat(src, "We are now ready to regenerate.") + src.verbs += /mob/proc/changeling_returntolife + feedback_add_details("changeling_powers","FD") + return 1 + + +//Boosts the range of your next sting attack by 1 +/mob/proc/changeling_boost_range() + set category = "Changeling" + set name = "Ranged Sting (10)" + set desc="Your next sting ability can be used against targets 2 squares away." + + var/datum/changeling/changeling = changeling_power(10,0,100) + if(!changeling) return 0 + changeling.chem_charges -= 10 + to_chat(src, "Your throat adjusts to launch the sting.") + changeling.sting_range = 2 + src.verbs -= /mob/proc/changeling_boost_range + spawn(5) src.verbs += /mob/proc/changeling_boost_range + feedback_add_details("changeling_powers","RS") + return 1 + + +//Recover from stuns. +/mob/proc/changeling_unstun() + set category = "Changeling" + set name = "Epinephrine Sacs (45)" + set desc = "Removes all stuns" + + var/datum/changeling/changeling = changeling_power(45,0,100,UNCONSCIOUS) + if(!changeling) return 0 + changeling.chem_charges -= 45 + + var/mob/living/carbon/human/C = src + if(ishuman(src)) + var/mob/living/carbon/human/H=src + if(H.said_last_words) + H.said_last_words=0 + C.stat = 0 + C.SetParalysis(0) + C.SetStunned(0) + C.SetWeakened(0) + C.lying = 0 + C.update_canmove() + + src.verbs -= /mob/proc/changeling_unstun + spawn(5) src.verbs += /mob/proc/changeling_unstun + feedback_add_details("changeling_powers","UNS") + return 1 + + +//Speeds up chemical regeneration +/mob/proc/changeling_fastchemical() + src.mind.changeling.chem_recharge_rate *= 2 + return 1 + +//Increases macimum chemical storage +/mob/proc/changeling_engorgedglands() + src.mind.changeling.chem_storage += 25 + return 1 + + +//Prevents AIs tracking you but makes you easily detectable to the human-eye. +/mob/proc/changeling_digitalcamo() + set category = "Changeling" + set name = "Toggle Digital Camoflague" + set desc = "The AI can no longer track us, but we will look different if examined. Has a constant cost while active." + + var/datum/changeling/changeling = changeling_power() + if(!changeling) return 0 + + var/mob/living/carbon/human/C = src + if(C.digitalcamo) to_chat(C, "We return to normal.") + else to_chat(C, "We distort our form to prevent AI-tracking.") + C.digitalcamo = !C.digitalcamo + + spawn(0) + while(C && C.digitalcamo && C.mind && C.mind.changeling) + C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0) + sleep(40) + + src.verbs -= /mob/proc/changeling_digitalcamo + spawn(5) src.verbs += /mob/proc/changeling_digitalcamo + feedback_add_details("changeling_powers","CAM") + return 1 + + +//Starts healing you every second for 10 seconds. Can be used whilst unconscious. +/mob/proc/changeling_rapidregen() + set category = "Changeling" + set name = "Rapid Regeneration (30)" + set desc = "Begins rapidly regenerating. Does not effect stuns or chemicals." + + var/datum/changeling/changeling = changeling_power(30,0,100,UNCONSCIOUS) + if(!changeling) return 0 + src.mind.changeling.chem_charges -= 30 + + var/mob/living/carbon/human/C = src + spawn(0) + for(var/i = 0, i<10,i++) + if(C) + C.adjustBruteLoss(-10) + C.adjustToxLoss(-10) + C.adjustOxyLoss(-10) + C.adjustFireLoss(-10) + sleep(10) + + src.verbs -= /mob/proc/changeling_rapidregen + spawn(5) src.verbs += /mob/proc/changeling_rapidregen + feedback_add_details("changeling_powers","RR") + return 1 + +// HIVE MIND UPLOAD/DOWNLOAD DNA + +var/list/datum/dna/hivemind_bank = list() + +/mob/proc/changeling_hiveupload() + set category = "Changeling" + set name = "Hive Channel (10)" + set desc = "Allows you to channel DNA in the airwaves to allow other changelings to absorb it." + + var/datum/changeling/changeling = changeling_power(10,1) + if(!changeling) return + + var/list/names = list() + for(var/datum/dna/DNA in changeling.absorbed_dna) + if(!(DNA in hivemind_bank)) + names += DNA.real_name + + if(names.len <= 0) + to_chat(src, "The airwaves already have all of our DNA.") + return + + var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names + if(!S) return + + var/datum/dna/chosen_dna = changeling.GetDNA(S) + if(!chosen_dna) + return + + changeling.chem_charges -= 10 + hivemind_bank += chosen_dna + to_chat(src, "We channel the DNA of [S] to the air.") + feedback_add_details("changeling_powers","HU") + return 1 + +/mob/proc/changeling_hivedownload() + set category = "Changeling" + set name = "Hive Absorb (20)" + set desc = "Allows you to absorb DNA that is being channeled in the airwaves." + + var/datum/changeling/changeling = changeling_power(20,1) + if(!changeling) return + + var/list/names = list() + for(var/datum/dna/DNA in hivemind_bank) + if(!(DNA in changeling.absorbed_dna)) + names[DNA.real_name] = DNA + + if(names.len <= 0) + to_chat(src, "There's no new DNA to absorb from the air.") + return + + var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names + if(!S) return + var/datum/dna/chosen_dna = names[S] + if(!chosen_dna) + return + + changeling.chem_charges -= 20 + changeling.absorbed_dna += chosen_dna + to_chat(src, "We absorb the DNA of [S] from the air.") + feedback_add_details("changeling_powers","HD") + return 1 + +// Fake Voice + +/mob/proc/changeling_mimicvoice() + set category = "Changeling" + set name = "Mimic Voice" + set desc = "Shape our vocal glands to form a voice of someone we choose. We cannot regenerate chemicals when mimicing." + + + if(!usr) + return + var/mob/user = usr + var/datum/changeling/changeling = changeling_power() + if(!changeling) return + + if(changeling.mimicing) + changeling.mimicing = "" + to_chat(src, "We return our vocal glands to their original location.") + return + + var/mimic_voice = stripped_input(user, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN) + if(!mimic_voice) + return + + changeling.mimicing = mimic_voice + + to_chat(src, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.") + to_chat(src, "Use this power again to return to our original voice and reproduce chemicals again.") + + feedback_add_details("changeling_powers","MV") + + spawn(0) + while(src && src.mind && src.mind.changeling && src.mind.changeling.mimicing) + src.mind.changeling.chem_charges = max(src.mind.changeling.chem_charges - 1, 0) + sleep(40) + if(src && src.mind && src.mind.changeling) + src.mind.changeling.mimicing = "" + ////////// + //STINGS// //They get a pretty header because there's just so fucking many of them ;_; + ////////// + +/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1) + if(M.loc == src.loc) return 1 //target and source are in the same thing + if(!isturf(src.loc) || !isturf(M.loc)) return 0 //One is inside, the other is outside something. + if(sting_range < 2) + return Adjacent(M) + if(AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, sting_range)) //If a path exists, good! + return 1 + return 0 + +//Handles the general sting code to reduce on copypasta (seeming as somebody decided to make SO MANY dumb abilities) +/mob/proc/changeling_sting(var/required_chems=0, var/verb_path) + var/datum/changeling/changeling = changeling_power(required_chems) + if(!changeling) return + + var/list/victims = list() + for(var/mob/living/carbon/C in oview(changeling.sting_range)) + victims += C + var/mob/living/carbon/T = input(src, "Who will we sting?") as null|anything in victims + + if(!T) return + if(!(T in view(changeling.sting_range))) return + if(!sting_can_reach(T, changeling.sting_range)) return + if(!changeling_power(required_chems)) return + + changeling.chem_charges -= required_chems + changeling.sting_range = 1 + src.verbs -= verb_path + spawn(10) src.verbs += verb_path + + to_chat(src, "We stealthily sting [T].") + if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting + to_chat(T, "You feel a tiny prick.") + return + + +/mob/proc/changeling_lsdsting() + set category = "Changeling" + set name = "Hallucination Sting (15)" + set desc = "Causes terror in the target." + + var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting) + if(!T) return 0 + spawn(rand(300,600)) + if(T) T.hallucination += 400 + feedback_add_details("changeling_powers","HS") + return 1 + +/mob/proc/changeling_silence_sting() + set category = "Changeling" + set name = "Silence sting (10)" + set desc="Sting target" + + var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting) + if(!T) return 0 + T.silent += 30 + feedback_add_details("changeling_powers","SS") + return 1 + +/mob/proc/changeling_blind_sting() + set category = "Changeling" + set name = "Blind sting (20)" + set desc="Sting target" + + var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting) + if(!T) return 0 + to_chat(T, "Your eyes burn horrificly!") + T.disabilities |= NEARSIGHTED + spawn(300) T.disabilities &= ~NEARSIGHTED + T.eye_blind = 10 + T.eye_blurry = 20 + feedback_add_details("changeling_powers","BS") + return 1 + +/mob/proc/changeling_deaf_sting() + set category = "Changeling" + set name = "Deaf sting (5)" + set desc="Sting target:" + + var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting) + if(!T) return 0 + to_chat(T, "Your ears pop and begin ringing loudly!") + T.sdisabilities |= DEAF + spawn(300) T.sdisabilities &= ~DEAF + feedback_add_details("changeling_powers","DS") + return 1 + +/mob/proc/changeling_paralysis_sting() + set category = "Changeling" + set name = "Paralysis sting (30)" + set desc="Sting target" + + var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting) + if(!T) return 0 + to_chat(T, "Your muscles begin to painfully tighten.") + T.Weaken(20) + feedback_add_details("changeling_powers","PS") + return 1 + +/mob/proc/changeling_transformation_sting() + set category = "Changeling" + set name = "Transformation sting (40)" + set desc="Sting target" + + var/datum/changeling/changeling = changeling_power(40) + if(!changeling) return 0 + + + + var/list/names = list() + for(var/datum/dna/DNA in changeling.absorbed_dna) + names += "[DNA.real_name]" + + var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names + if(!S) return + + var/datum/dna/chosen_dna = changeling.GetDNA(S) + if(!chosen_dna) + return + + var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_transformation_sting) + if(!T) return 0 + if((M_HUSK in T.mutations) || (!ishuman(T) && !ismonkey(T))) + to_chat(src, "Our sting appears ineffective against its DNA.") + return 0 + T.visible_message("[T] transforms!") + T.dna = chosen_dna.Clone() + T.real_name = chosen_dna.real_name + T.UpdateAppearance() + domutcheck(T, null) + feedback_add_details("changeling_powers","TS") + return 1 + +/mob/proc/changeling_unfat_sting() + set category = "Changeling" + set name = "Unfat sting" + set desc = "A rapid weightloss plan that actually works!" + + var/mob/living/carbon/T = changeling_sting(0,/mob/proc/changeling_unfat_sting) + if(!T) return 0 + if(T.overeatduration>100) + to_chat(T, "You feel a small prick as your stomach churns violently. You begin to feel skinnier.") + T.overeatduration = 0 + T.nutrition -= 100 + feedback_add_details("changeling_powers","US") + return 1 + +/mob/proc/changeling_DEATHsting() + set category = "Changeling" + set name = "Death Sting (40)" + set desc = "Causes spasms onto death." + + var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting) + if(!T) return 0 + to_chat(T, "You feel a small prick and your chest becomes tight.") + T.silent = 10 + T.Paralyse(10) + T.Jitter(1000) + if(T.reagents) T.reagents.add_reagent("lexorin", 40) + feedback_add_details("changeling_powers","DTHS") + return 1 + +/mob/proc/changeling_extract_dna_sting() + set category = "Changeling" + set name = "Extract DNA Sting (40)" + set desc="Stealthily sting a target to extract their DNA." + + var/datum/changeling/changeling = null + if(src.mind && src.mind.changeling) + changeling = src.mind.changeling + if(!changeling) + return 0 + + var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting) + if(!T) return 0 + + T.dna.real_name = T.real_name + changeling.absorbed_dna |= T.dna + if(T.species && !(T.species.name in changeling.absorbed_species)) + changeling.absorbed_species += T.species.name + + feedback_add_details("changeling_powers","ED") + return 1 diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index d8b6229a2bd..e33a32fdebf 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -1,673 +1,673 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/datum/game_mode - var/list/datum/mind/cult = list() - var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") - - -/proc/iscultist(mob/living/M as mob) - return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) - -/proc/is_convertable_to_cult(datum/mind/mind) - if(!istype(mind)) return 0 - if(istype(mind.current, /mob/living/carbon/human) && (mind.assigned_role == "Chaplain")) return 0 - for(var/obj/item/weapon/implant/loyalty/L in mind.current) - if(L && (L.imp_in == mind.current))//Checks to see if the person contains an implant, then checks that the implant is actually inside of them - return 0 - return 1 - -//Objectives revamped in February 2015 by Deity Link #vgstation - -//Cult round flow: -//* at the beginning of the round, cultists aren't able to summon Nar-Sie. -//* during the first phase, cultists start the round with only one objective: either "bloodspill", "convert", or "sacrifice" -//* once they complete that objective, the game checks how well the cult is performing (Are there still at least 4 of them? Are they getting outnumbered by loyalty implanted people?) -//* if the cult is performing well, the game will try to give them another objective among the above three. -//* if the cult is in bad shape, or all objectives have been completed, or none of the remaining possible objectives are feasible, then the game let's them summon Nar-Sie -//* once Nar-Sie is summonned, the shuttle automatically arrives after 10 minutes (even if the shuttle was already on its way) and can't be recalled -//* the cultists get one last bonus objective to complete before the round ends: either "harvest", "hijack", or "massacre" - -//* the cult "wins" as soon as it summons Nar-Sie. - -/datum/game_mode/cult - name = "cult" - config_tag = "cult" - restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Internal Affairs Agent", "Mobile MMI", "Head of Personnel") - protected_jobs = list() - required_players = 5 - required_players_secret = 15 - required_enemies = 3 - recommended_enemies = 4 - - uplink_welcome = "Nar-Sie Uplink Console:"//what? - uplink_uses = 10//whaaaat? - - var/datum/mind/sacrifice_target = null - var/finished = 0 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/list/startwords = list("blood","join","self","hell") - - var/list/objectives = list() - - var/const/min_cultists_to_start = 3 - var/const/max_cultists_to_start = 4 - var/acolytes_survived = 0 - var/ext_survivors = 0 - - var/narsie_condition_cleared = 0 //allows Nar-Sie to be summonned during cult rounds. set to 1 once the cult reaches the second phase. - var/current_objective = 1 //equals the number of cleared objectives + 1 - var/prenarsie_objectives = 2 //how many objectives at most before the cult gets to summon narsie - var/list/bloody_floors = list() - var/spilltarget = 100 //how many floor tiles must be covered in blood to complete the bloodspill objective - var/convert_target = 0 //how many members the cult needs to reach to complete the convert objective - var/harvested = 0 - - var/list/sacrificed = list() //contains the mind of the sacrifice target ONCE the sacrifice objective has been completed - var/mass_convert = 0 //set to 1 if the convert objective has been accomplised once that round - var/spilled_blood = 0 //set to 1 if the bloodspill objective has been accomplised once that round - var/max_spilled_blood = 0 //highest quantity of blood covered tiles during the round - var/bonus = 0 //set to 1 if the cult has completed the bonus (third phase) objective (harvest, hijack, massacre) - - var/harvest_target = 10 - var/massacre_target = 5 - - var/escaped_shuttle = 0 - var/escaped_pod = 0 - var/survivors = 0 - -/datum/game_mode/cult/announce() +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/datum/game_mode + var/list/datum/mind/cult = list() + var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") + + +/proc/iscultist(mob/living/M as mob) + return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) + +/proc/is_convertable_to_cult(datum/mind/mind) + if(!istype(mind)) return 0 + if(istype(mind.current, /mob/living/carbon/human) && (mind.assigned_role == "Chaplain")) return 0 + for(var/obj/item/weapon/implant/loyalty/L in mind.current) + if(L && (L.imp_in == mind.current))//Checks to see if the person contains an implant, then checks that the implant is actually inside of them + return 0 + return 1 + +//Objectives revamped in February 2015 by Deity Link #vgstation + +//Cult round flow: +//* at the beginning of the round, cultists aren't able to summon Nar-Sie. +//* during the first phase, cultists start the round with only one objective: either "bloodspill", "convert", or "sacrifice" +//* once they complete that objective, the game checks how well the cult is performing (Are there still at least 4 of them? Are they getting outnumbered by loyalty implanted people?) +//* if the cult is performing well, the game will try to give them another objective among the above three. +//* if the cult is in bad shape, or all objectives have been completed, or none of the remaining possible objectives are feasible, then the game let's them summon Nar-Sie +//* once Nar-Sie is summonned, the shuttle automatically arrives after 10 minutes (even if the shuttle was already on its way) and can't be recalled +//* the cultists get one last bonus objective to complete before the round ends: either "harvest", "hijack", or "massacre" + +//* the cult "wins" as soon as it summons Nar-Sie. + +/datum/game_mode/cult + name = "cult" + config_tag = "cult" + restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Internal Affairs Agent", "Mobile MMI", "Head of Personnel") + protected_jobs = list() + required_players = 5 + required_players_secret = 15 + required_enemies = 3 + recommended_enemies = 4 + + uplink_welcome = "Nar-Sie Uplink Console:"//what? + uplink_uses = 10//whaaaat? + + var/datum/mind/sacrifice_target = null + var/finished = 0 + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + + var/list/startwords = list("blood","join","self","hell") + + var/list/objectives = list() + + var/const/min_cultists_to_start = 3 + var/const/max_cultists_to_start = 4 + var/acolytes_survived = 0 + var/ext_survivors = 0 + + var/narsie_condition_cleared = 0 //allows Nar-Sie to be summonned during cult rounds. set to 1 once the cult reaches the second phase. + var/current_objective = 1 //equals the number of cleared objectives + 1 + var/prenarsie_objectives = 2 //how many objectives at most before the cult gets to summon narsie + var/list/bloody_floors = list() + var/spilltarget = 100 //how many floor tiles must be covered in blood to complete the bloodspill objective + var/convert_target = 0 //how many members the cult needs to reach to complete the convert objective + var/harvested = 0 + + var/list/sacrificed = list() //contains the mind of the sacrifice target ONCE the sacrifice objective has been completed + var/mass_convert = 0 //set to 1 if the convert objective has been accomplised once that round + var/spilled_blood = 0 //set to 1 if the bloodspill objective has been accomplised once that round + var/max_spilled_blood = 0 //highest quantity of blood covered tiles during the round + var/bonus = 0 //set to 1 if the cult has completed the bonus (third phase) objective (harvest, hijack, massacre) + + var/harvest_target = 10 + var/massacre_target = 5 + + var/escaped_shuttle = 0 + var/escaped_pod = 0 + var/survivors = 0 + +/datum/game_mode/cult/announce() to_chat(world, "The current game mode is - Cult!") to_chat(world, "Some crewmembers are attempting to start a cult!
      \nCultists - complete your objectives. Convert crewmembers to your cause by using the convert rune. Remember - there is no you, there is only the cult.
      \nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with the chaplain's bible reverts them to whatever CentCom-allowed faith they had.
      ") - - -/datum/game_mode/cult/pre_setup() - if(istype(ticker.mode, /datum/game_mode/mixed)) - mixed = 1 - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/cultists_possible = get_players_for_role(ROLE_CULTIST) - for(var/datum/mind/player in cultists_possible) - if(mixed && (player in ticker.mode.modePlayer)) - cultists_possible -= player - continue - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - cultists_possible -= player - - for(var/cultists_number = 1 to max_cultists_to_start) - if(!cultists_possible.len) - break - var/datum/mind/cultist = pick(cultists_possible) - cultists_possible -= cultist - cult += cultist - - . = cult.len <= 0 - if(.) - log_admin("Failed to set-up a round of cult. Couldn't pick any players to be starting cultists.") - message_admins("Failed to set-up a round of cult. Couldn't pick any players to be starting cultists.") - else - log_admin("Starting a round of cult with [cult.len] starting cultists.") - message_admins("Starting a round of cult with [cult.len] starting cultists.") - if(mixed) - ticker.mode.modePlayer += cult //merge into master antag list - ticker.mode.cult += cult - - return !. - -/datum/game_mode/cult/proc/blood_check() - max_spilled_blood = (max(bloody_floors.len,max_spilled_blood)) - if((objectives[current_objective] == "bloodspill") && (bloody_floors.len >= spilltarget) && !spilled_blood) - spilled_blood = 1 - additional_phase() - -/datum/game_mode/cult/proc/check_numbers() - if((objectives[current_objective] == "convert") && (cult.len >= convert_target) && !mass_convert) - mass_convert = 1 - additional_phase() - -/datum/game_mode/cult/proc/first_phase() - - - var/new_objective = pick_objective() - - objectives += new_objective - - var/explanation - - switch(new_objective) - if("convert") - explanation = "We must increase our influence before we can summon Nar-Sie. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions." - if("bloodspill") - spilltarget = 100 + rand(0,player_list.len * 3) - explanation = "We must prepare this place for the Geometer of Blood's coming. Spill blood and gibs over [spilltarget] floor tiles." - if("sacrifice") - explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune (Hell Blood Join) to perform the ritual." - - for(var/datum/mind/cult_mind in cult) - equip_cultist(cult_mind.current) - grant_runeword(cult_mind.current) - update_cult_icons_added(cult_mind) - cult_mind.special_role = "Cultist" + + +/datum/game_mode/cult/pre_setup() + if(istype(ticker.mode, /datum/game_mode/mixed)) + mixed = 1 + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + var/list/cultists_possible = get_players_for_role(ROLE_CULTIST) + for(var/datum/mind/player in cultists_possible) + if(mixed && (player in ticker.mode.modePlayer)) + cultists_possible -= player + continue + for(var/job in restricted_jobs)//Removing heads and such from the list + if(player.assigned_role == job) + cultists_possible -= player + + for(var/cultists_number = 1 to max_cultists_to_start) + if(!cultists_possible.len) + break + var/datum/mind/cultist = pick(cultists_possible) + cultists_possible -= cultist + cult += cultist + + . = cult.len <= 0 + if(.) + log_admin("Failed to set-up a round of cult. Couldn't pick any players to be starting cultists.") + message_admins("Failed to set-up a round of cult. Couldn't pick any players to be starting cultists.") + else + log_admin("Starting a round of cult with [cult.len] starting cultists.") + message_admins("Starting a round of cult with [cult.len] starting cultists.") + if(mixed) + ticker.mode.modePlayer += cult //merge into master antag list + ticker.mode.cult += cult + + return !. + +/datum/game_mode/cult/proc/blood_check() + max_spilled_blood = (max(bloody_floors.len,max_spilled_blood)) + if((objectives[current_objective] == "bloodspill") && (bloody_floors.len >= spilltarget) && !spilled_blood) + spilled_blood = 1 + additional_phase() + +/datum/game_mode/cult/proc/check_numbers() + if((objectives[current_objective] == "convert") && (cult.len >= convert_target) && !mass_convert) + mass_convert = 1 + additional_phase() + +/datum/game_mode/cult/proc/first_phase() + + + var/new_objective = pick_objective() + + objectives += new_objective + + var/explanation + + switch(new_objective) + if("convert") + explanation = "We must increase our influence before we can summon Nar-Sie. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions." + if("bloodspill") + spilltarget = 100 + rand(0,player_list.len * 3) + explanation = "We must prepare this place for the Geometer of Blood's coming. Spill blood and gibs over [spilltarget] floor tiles." + if("sacrifice") + explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune (Hell Blood Join) to perform the ritual." + + for(var/datum/mind/cult_mind in cult) + equip_cultist(cult_mind.current) + grant_runeword(cult_mind.current) + update_cult_icons_added(cult_mind) + cult_mind.special_role = "Cultist" to_chat(cult_mind.current, "You are a member of the cult!") to_chat(cult_mind.current, "You can now speak and understand the forgotten tongue of Nar-Sie.") - cult_mind.current.add_language("Cult") - //memoize_cult_objectives(cult_mind) - - - + cult_mind.current.add_language("Cult") + //memoize_cult_objectives(cult_mind) + + + to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]") - cult_mind.memory += "Objective #[current_objective]: [explanation]
      " - -/datum/game_mode/cult/proc/bypass_phase() - switch(objectives[current_objective]) - if("convert") - mass_convert = 1 - if("bloodspill") - spilled_blood = 1 - if("sacrifice") - sacrificed += sacrifice_target - additional_phase() - -/datum/game_mode/cult/proc/additional_phase() - current_objective++ - - message_admins("Picking a new Cult objective.") - var/new_objective = "eldergod" - //the idea here is that if the cult performs well, the should get more objectives before they can summon Nar-Sie. - if(cult.len >= 4)//if there are less than 4 remaining cultists, they get a free pass to the summon objective. - if(current_objective <= prenarsie_objectives) - var/list/unconvertables = get_unconvertables() - if(unconvertables.len <= (cult.len * 2))//if cultists are getting radically outnumbered, they get a free pass to the summon objective. - new_objective = pick_objective() - else - message_admins("There are over twice more unconvertables than there are cultists ([cult.len] cultists for [unconvertables.len]) unconvertables! Nar-Sie objective unlocked.") - log_admin("There are over twice more unconvertables than there are cultists ([cult.len] cultists for [unconvertables.len]) unconvertables! Nar-Sie objective unlocked.") - else - message_admins("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.") - log_admin("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.") - else - message_admins("There are less than 4 cultists! Nar-Sie objective unlocked.") - log_admin("There are less than 4 cultists! Nar-Sie objective unlocked.") - - if(!sacrificed.len && (new_objective != "sacrifice")) - sacrifice_target = null - - if(new_objective == "eldergod") - second_phase() - return - else - objectives += new_objective - - var/explanation - - switch(new_objective) - if("convert") - explanation = "We must increase our influence before we can summon Nar-Sie. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions." - if("bloodspill") - spilltarget = 100 + rand(0,player_list.len * 3) - explanation = "We must prepare this place for the Geometer of Blood's coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles." - if("sacrifice") - explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune (Hell Blood Join) to perform the ritual." - - for(var/datum/mind/cult_mind in cult) + cult_mind.memory += "Objective #[current_objective]: [explanation]
      " + +/datum/game_mode/cult/proc/bypass_phase() + switch(objectives[current_objective]) + if("convert") + mass_convert = 1 + if("bloodspill") + spilled_blood = 1 + if("sacrifice") + sacrificed += sacrifice_target + additional_phase() + +/datum/game_mode/cult/proc/additional_phase() + current_objective++ + + message_admins("Picking a new Cult objective.") + var/new_objective = "eldergod" + //the idea here is that if the cult performs well, the should get more objectives before they can summon Nar-Sie. + if(cult.len >= 4)//if there are less than 4 remaining cultists, they get a free pass to the summon objective. + if(current_objective <= prenarsie_objectives) + var/list/unconvertables = get_unconvertables() + if(unconvertables.len <= (cult.len * 2))//if cultists are getting radically outnumbered, they get a free pass to the summon objective. + new_objective = pick_objective() + else + message_admins("There are over twice more unconvertables than there are cultists ([cult.len] cultists for [unconvertables.len]) unconvertables! Nar-Sie objective unlocked.") + log_admin("There are over twice more unconvertables than there are cultists ([cult.len] cultists for [unconvertables.len]) unconvertables! Nar-Sie objective unlocked.") + else + message_admins("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.") + log_admin("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.") + else + message_admins("There are less than 4 cultists! Nar-Sie objective unlocked.") + log_admin("There are less than 4 cultists! Nar-Sie objective unlocked.") + + if(!sacrificed.len && (new_objective != "sacrifice")) + sacrifice_target = null + + if(new_objective == "eldergod") + second_phase() + return + else + objectives += new_objective + + var/explanation + + switch(new_objective) + if("convert") + explanation = "We must increase our influence before we can summon Nar-Sie. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions." + if("bloodspill") + spilltarget = 100 + rand(0,player_list.len * 3) + explanation = "We must prepare this place for the Geometer of Blood's coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles." + if("sacrifice") + explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune (Hell Blood Join) to perform the ritual." + + for(var/datum/mind/cult_mind in cult) to_chat(cult_mind.current, "You and your acolytes have completed your task, but this place requires yet more preparation!") to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]") - cult_mind.memory += "Objective #[current_objective]: [explanation]
      " - - message_admins("New Cult Objective: [new_objective]") - log_admin("New Cult Objective: [new_objective]") - - blood_check()//in case there are already enough blood covered tiles when the objective is given. - -/datum/game_mode/cult/proc/second_phase() - narsie_condition_cleared = 1 - - objectives += "eldergod" - - var/explanation = "Summon Nar-Sie on the Station via the use of the Tear Reality rune (Hell Join Self). You will need 9 cultists standing on and around the rune to summon Him." - - for(var/datum/mind/cult_mind in cult) + cult_mind.memory += "Objective #[current_objective]: [explanation]
      " + + message_admins("New Cult Objective: [new_objective]") + log_admin("New Cult Objective: [new_objective]") + + blood_check()//in case there are already enough blood covered tiles when the objective is given. + +/datum/game_mode/cult/proc/second_phase() + narsie_condition_cleared = 1 + + objectives += "eldergod" + + var/explanation = "Summon Nar-Sie on the Station via the use of the Tear Reality rune (Hell Join Self). You will need 9 cultists standing on and around the rune to summon Him." + + for(var/datum/mind/cult_mind in cult) to_chat(cult_mind.current, "You and your acolytes have succeeded in preparing the station for the ultimate ritual!") to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]") - cult_mind.memory += "Objective #[current_objective]: [explanation]
      " - -/datum/game_mode/cult/proc/third_phase() - current_objective++ - - sleep(10) - - var/last_objective = pick_bonus_objective() - - objectives += last_objective - - var/explanation - - switch(last_objective) - if("harvest") - explanation = "The Geometer of Blood hungers for his first meal of this never-ending day. Offer him [harvest_target] humans in sacrifice." - if("hijack") - explanation = "Nar-Sie wishes for his troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it." - if("massacre") - explanation = "Nar-Sie wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)." - - for(var/datum/mind/cult_mind in cult) + cult_mind.memory += "Objective #[current_objective]: [explanation]
      " + +/datum/game_mode/cult/proc/third_phase() + current_objective++ + + sleep(10) + + var/last_objective = pick_bonus_objective() + + objectives += last_objective + + var/explanation + + switch(last_objective) + if("harvest") + explanation = "The Geometer of Blood hungers for his first meal of this never-ending day. Offer him [harvest_target] humans in sacrifice." + if("hijack") + explanation = "Nar-Sie wishes for his troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it." + if("massacre") + explanation = "Nar-Sie wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)." + + for(var/datum/mind/cult_mind in cult) to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]") - cult_mind.memory += "Objective #[current_objective]: [explanation]
      " - - message_admins("Last Cult Objective: [last_objective]") - log_admin("Last Cult Objective: [last_objective]") - -/datum/game_mode/cult/post_setup() - modePlayer += cult - - first_phase() - - if(!mixed) - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - ..() - -/datum/game_mode/cult/proc/pick_objective() - var/list/possible_objectives = list() - - if(!spilled_blood && (bloody_floors.len < spilltarget)) - possible_objectives |= "bloodspill" - - if(!sacrificed.len) - var/list/possible_targets = list() - for(var/mob/living/carbon/human/player in player_list) - if(player.z == map.zCentcomm) //We can't sacrifice people that are on the centcom z-level - continue - if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD)) - possible_targets += player.mind - - if(!possible_targets.len) - //There are no living Unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers - for(var/mob/living/carbon/human/player in player_list) - if(player.z == map.zCentcomm) //We can't sacrifice people that are on the centcom z-level - continue - if(player.mind && !(player.mind in cult)) - possible_targets += player.mind - - if(possible_targets.len > 0) - sacrifice_target = pick(possible_targets) - possible_objectives |= "sacrifice" - else - message_admins("Didn't find a suitable sacrifice target...what the hell? Shout at Deity.") - log_admin("Didn't find a suitable sacrifice target...what the hell? Shout at Deity.") - - if(!mass_convert) - var/living_crew = 0 - var/living_cultists = 0 - for(var/mob/living/L in player_list) - if(L.stat != DEAD) - if(L.mind in cult) - living_cultists++ - else - if(istype(L, /mob/living/carbon)) - living_crew++ - - var/total = living_crew + living_cultists - - if((living_cultists * 2) < total) - if (total < 15) - message_admins("There are [total] players, too little for the mass convert objective!") - log_admin("There are [total] players, too little for the mass convert objective!") - else if (total > 50) - message_admins("There are [total] players, too many for the mass convert objective!") - log_admin("There are [total] players, too many for the mass convert objective!") - else - possible_objectives |= "convert" - convert_target = round(total / 2) - - if(!possible_objectives.len)//No more possible objectives, time to summon Nar-Sie - message_admins("No suitable objectives left! Nar-Sie objective unlocked.") - log_admin("No suitable objectives left! Nar-Sie objective unlocked.") - return "eldergod" - else - return pick(possible_objectives) - -/datum/game_mode/cult/proc/pick_bonus_objective() - var/list/possible_objectives = list() - - var/living_crew = 0 - for(var/mob/living/carbon/C in player_list) - if(C.stat != DEAD) - if(!(C.mind in cult)) - var/turf/T = get_turf(C) - if(T.z == map.zMainStation) //we're only interested in the remaining humans on the station - living_crew++ - - if(living_crew > 5) - possible_objectives |= "massacre" - - if(living_crew > 10) - possible_objectives |= "harvest" - - possible_objectives |= "hijack" //we need at least one objective guarranted to fire - - return pick(possible_objectives) - - -/datum/game_mode/cult/proc/memoize_cult_objectives(var/datum/mind/cult_mind) + cult_mind.memory += "Objective #[current_objective]: [explanation]
      " + + message_admins("Last Cult Objective: [last_objective]") + log_admin("Last Cult Objective: [last_objective]") + +/datum/game_mode/cult/post_setup() + modePlayer += cult + + first_phase() + + if(!mixed) + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + ..() + +/datum/game_mode/cult/proc/pick_objective() + var/list/possible_objectives = list() + + if(!spilled_blood && (bloody_floors.len < spilltarget)) + possible_objectives |= "bloodspill" + + if(!sacrificed.len) + var/list/possible_targets = list() + for(var/mob/living/carbon/human/player in player_list) + if(player.z == map.zCentcomm) //We can't sacrifice people that are on the centcom z-level + continue + if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD)) + possible_targets += player.mind + + if(!possible_targets.len) + //There are no living Unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers + for(var/mob/living/carbon/human/player in player_list) + if(player.z == map.zCentcomm) //We can't sacrifice people that are on the centcom z-level + continue + if(player.mind && !(player.mind in cult)) + possible_targets += player.mind + + if(possible_targets.len > 0) + sacrifice_target = pick(possible_targets) + possible_objectives |= "sacrifice" + else + message_admins("Didn't find a suitable sacrifice target...what the hell? Shout at Deity.") + log_admin("Didn't find a suitable sacrifice target...what the hell? Shout at Deity.") + + if(!mass_convert) + var/living_crew = 0 + var/living_cultists = 0 + for(var/mob/living/L in player_list) + if(L.stat != DEAD) + if(L.mind in cult) + living_cultists++ + else + if(istype(L, /mob/living/carbon)) + living_crew++ + + var/total = living_crew + living_cultists + + if((living_cultists * 2) < total) + if (total < 15) + message_admins("There are [total] players, too little for the mass convert objective!") + log_admin("There are [total] players, too little for the mass convert objective!") + else if (total > 50) + message_admins("There are [total] players, too many for the mass convert objective!") + log_admin("There are [total] players, too many for the mass convert objective!") + else + possible_objectives |= "convert" + convert_target = round(total / 2) + + if(!possible_objectives.len)//No more possible objectives, time to summon Nar-Sie + message_admins("No suitable objectives left! Nar-Sie objective unlocked.") + log_admin("No suitable objectives left! Nar-Sie objective unlocked.") + return "eldergod" + else + return pick(possible_objectives) + +/datum/game_mode/cult/proc/pick_bonus_objective() + var/list/possible_objectives = list() + + var/living_crew = 0 + for(var/mob/living/carbon/C in player_list) + if(C.stat != DEAD) + if(!(C.mind in cult)) + var/turf/T = get_turf(C) + if(T.z == map.zMainStation) //we're only interested in the remaining humans on the station + living_crew++ + + if(living_crew > 5) + possible_objectives |= "massacre" + + if(living_crew > 10) + possible_objectives |= "harvest" + + possible_objectives |= "hijack" //we need at least one objective guarranted to fire + + return pick(possible_objectives) + + +/datum/game_mode/cult/proc/memoize_cult_objectives(var/datum/mind/cult_mind) to_chat(cult_mind.current, "The convert rune is Join Blood Self") - cult_mind.memory += "The convert rune is Join Blood Self
      " - var/explanation - switch(objectives[current_objective]) - if("convert") - explanation = "We must increase our influence before we can summon Nar-Sie. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions." - if("bloodspill") - explanation = "We must prepare this place for the Geometer of Blood's coming. Spill blood and gibs over [spilltarget] floor tiles." - if("sacrifice") - explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune (Hell Blood Join) to perform the ritual." - if("eldergod") - explanation = "Summon Nar-Sie via the use of the Tear Reality rune (Hell Join Self). You will need 9 cultists standing on and around the rune to summon Him." + cult_mind.memory += "The convert rune is Join Blood Self
      " + var/explanation + switch(objectives[current_objective]) + if("convert") + explanation = "We must increase our influence before we can summon Nar-Sie. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions." + if("bloodspill") + explanation = "We must prepare this place for the Geometer of Blood's coming. Spill blood and gibs over [spilltarget] floor tiles." + if("sacrifice") + explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune (Hell Blood Join) to perform the ritual." + if("eldergod") + explanation = "Summon Nar-Sie via the use of the Tear Reality rune (Hell Join Self). You will need 9 cultists standing on and around the rune to summon Him." to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]") - cult_mind.memory += "Objective #[current_objective]: [explanation]
      " - - -/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob) - if(!istype(mob)) - return - - if (mob.mind) - if (mob.mind.assigned_role == "Clown") + cult_mind.memory += "Objective #[current_objective]: [explanation]
      " + + +/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob) + if(!istype(mob)) + return + + if (mob.mind) + if (mob.mind.assigned_role == "Clown") to_chat(mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - mob.mutations.Remove(M_CLUMSY) - - - var/obj/item/weapon/paper/talisman/supply/T = new(mob) - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = mob.equip_in_one_of_slots(T, slots, EQUIP_FAILACTION_DROP) - if (!where) + mob.mutations.Remove(M_CLUMSY) + + + var/obj/item/weapon/paper/talisman/supply/T = new(mob) + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + var/where = mob.equip_in_one_of_slots(T, slots, EQUIP_FAILACTION_DROP) + if (!where) to_chat(mob, "Unfortunately, you weren't able to sneak in a talisman. Pray, and He most likely shall get you one.") - else + else to_chat(mob, "You have a talisman in your [where], one that will help you start the cult on this station. Use it well and remember - there are others.") - mob.update_icons() - return 1 - - -/datum/game_mode/cult/grant_runeword(mob/living/carbon/human/cult_mob, var/word) - if (!word) - if(startwords.len > 0) - word=pick(startwords) - startwords -= word - return ..(cult_mob,word) - - -/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, var/word) - if(!cultwords["travel"]) - runerandom() - if (!word) - word=pick(allwords) - var/wordexp = "[cultwords[word]] is [word]..." + mob.update_icons() + return 1 + + +/datum/game_mode/cult/grant_runeword(mob/living/carbon/human/cult_mob, var/word) + if (!word) + if(startwords.len > 0) + word=pick(startwords) + startwords -= word + return ..(cult_mob,word) + + +/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, var/word) + if(!cultwords["travel"]) + runerandom() + if (!word) + word=pick(allwords) + var/wordexp = "[cultwords[word]] is [word]..." to_chat(cult_mob, "You remember one thing from the dark teachings of your master... [wordexp]") - cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0) - - -/datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE - if (!istype(cult_mind)) - return 0 - if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) - cult += cult_mind - update_cult_icons_added(cult_mind) - if(name == "cult") - var/datum/game_mode/cult/C = src - C.check_numbers() - return 1 - - -/datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT - if (!..(cult_mind)) - return - memoize_cult_objectives(cult_mind) - - -/datum/game_mode/proc/remove_cultist(var/datum/mind/cult_mind, var/show_message = 1, var/log=1) - if(cult_mind in cult) - update_cult_icons_removed(cult_mind) - cult -= cult_mind + cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0) + + +/datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE + if (!istype(cult_mind)) + return 0 + if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) + cult += cult_mind + update_cult_icons_added(cult_mind) + if(name == "cult") + var/datum/game_mode/cult/C = src + C.check_numbers() + return 1 + + +/datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT + if (!..(cult_mind)) + return + memoize_cult_objectives(cult_mind) + + +/datum/game_mode/proc/remove_cultist(var/datum/mind/cult_mind, var/show_message = 1, var/log=1) + if(cult_mind in cult) + update_cult_icons_removed(cult_mind) + cult -= cult_mind to_chat(cult_mind.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and removing all of the memories of your time as his servant, except the one who converted you, with it.") to_chat(cult_mind.current, "You find yourself unable to mouth the words of the forgotten...") - cult_mind.current.remove_language("Cult") - cult_mind.memory = "" - - if(show_message) - for(var/mob/M in viewers(cult_mind.current)) + cult_mind.current.remove_language("Cult") + cult_mind.memory = "" + + if(show_message) + for(var/mob/M in viewers(cult_mind.current)) to_chat(M, "[cult_mind.current] looks like they just reverted to their old faith!") - if(log) - log_admin("[cult_mind.current] ([ckey(cult_mind.current.key)] has been deconverted from the cult") - stat_collection.cult.deconverted++ - -/datum/game_mode/proc/update_all_cult_icons() - spawn(0) - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult") - cultist.current.client.images -= I - - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/datum/mind/cultist_1 in cult) - if(cultist_1.current) - var/imageloc = cultist_1.current - if(istype(cultist_1.current.loc,/obj/mecha)) - imageloc = cultist_1.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "cult") - cultist.current.client.images += I - - -/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) - if(!cult_mind) - return 0 - spawn(0) - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - var/imageloc = cult_mind.current - if(istype(cult_mind.current.loc,/obj/mecha)) - imageloc = cult_mind.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "cult", layer = 13) - cultist.current.client.images += I - if(cult_mind.current) - if(cult_mind.current.client) - var/imageloc = cultist.current - if(istype(cultist.current.loc,/obj/mecha)) - imageloc = cultist.current.loc - var/image/J = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "cult", layer = 13) - cult_mind.current.client.images += J - - -/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) - spawn(0) - for(var/datum/mind/cultist in cult) - if(cultist.current) - if(cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult" && ((I.loc == cult_mind.current) || (I.loc == cult_mind.current.loc))) - cultist.current.client.images -= I - - if(cult_mind.current) - if(cult_mind.current.client) - for(var/image/I in cult_mind.current.client.images) - if(I.icon_state == "cult") - cult_mind.current.client.images -= I - - -/datum/game_mode/cult/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in player_list) - if(player.mind && (!is_convertable_to_cult(player.mind) || jobban_isbanned(player, "cultist"))) - ucs += player.mind - return ucs - -/datum/game_mode/cult/proc/bonus_check() - if(universe.name == "Hell Rising") - switch(objectives[current_objective]) - if("harvest") - if(harvested >= harvest_target) - bonus = 1 - - if("hijack") - for(var/mob/living/L in player_list) - if(L.stat != DEAD) - if(!(L.mind in cult)) - var/turf/T = get_turf(L) - if(istype(T.loc, /area/shuttle/escape/centcom)) - escaped_shuttle++ - else if(istype(T.loc, /area/shuttle/escape_pod1/centcom) || istype(T.loc, /area/shuttle/escape_pod2/centcom) || istype(T.loc, /area/shuttle/escape_pod3/centcom) || istype(T.loc, /area/shuttle/escape_pod5/centcom)) - escaped_pod++ - if(!escaped_shuttle) - bonus = 1 - - if("massacre") - for(var/mob/living/carbon/C in player_list) - if(C.stat != DEAD) - if(!(C.mind in cult)) - var/turf/T = get_turf(C) - if(T.z == map.zMainStation) //we're only interested in the remaining humans on the station - survivors++ - if(survivors < massacre_target) - bonus = 1 - -/datum/game_mode/cult/declare_completion() - - bonus_check() - - if(universe.name == "Hell Rising") - if(bonus) - feedback_set_details("round_end_result","win - narsie summoned - all objectives completed") - completion_text += "Cult Total Victory!" - completion_text += "
      The Cult has summoned Nar-Sie and fulfilled all of his requests" - else - feedback_set_details("round_end_result","win - narsie summoned") - completion_text += "Cult Major Victory!" - completion_text += "
      The Cult has managed to summon Nar-Sie" - else - if(current_objective > 1) - feedback_set_details("round_end_result","halfwin - some objectives completed") - completion_text += "Crew Minor Victory!" - completion_text += "
      The Cult didn't summon Nar-Sie in time but still managed to fulfill some of his requests." - else - feedback_set_details("round_end_result","loss - no objective done") - completion_text += "Crew Major Victory!" - completion_text += "
      The Staff has managed to stop the Cult" - - var/text = "
      Objectives Completed: [current_objective - 1 + bonus]" - - if(objectives.len) - text += "
      The cultists' objectives were:" - for(var/obj_count=1, obj_count <= objectives.len, obj_count++) - var/explanation - switch(objectives[obj_count]) - if("convert")//convert half the crew - if(obj_count < objectives.len) - explanation = "Convert [convert_target] crewmembers ([cult.len] cultists at round end). Success!" - feedback_add_details("cult_objective","cult_convertion|SUCCESS") - else - explanation = "Convert [convert_target] crewmembers ([cult.len] total cultists). Fail!" - feedback_add_details("cult_objective","cult_convertion|FAIL") - - if("bloodspill")//cover a large portion of the station in blood - if(obj_count < objectives.len) - explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Success!" - feedback_add_details("cult_objective","cult_bloodspill|SUCCESS") - else - explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Fail!" - feedback_add_details("cult_objective","cult_bloodspill|FAIL") - - if("sacrifice")//sacrifice a high value target - if(sacrifice_target) - if(sacrifice_target in sacrificed) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!" - feedback_add_details("cult_objective","cult_sacrifice|SUCCESS") - else if(sacrifice_target && sacrifice_target.current) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail." - feedback_add_details("cult_objective","cult_sacrifice|FAIL") - else - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)." - feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED") - - if("eldergod")//summon narsie - if(universe.name == "Hell Rising") - explanation = "Summon Nar-Sie. Success!" - feedback_add_details("cult_objective","cult_narsie|SUCCESS") - else - explanation = "Summon Nar-Sie. Fail." - feedback_add_details("cult_objective","cult_narsie|FAIL") - - if("harvest") - if(harvested > harvest_target) - explanation = "Offer [harvest_target] humans for Nar-Sie's first meal of the day. ([harvested] eaten) Success!" - feedback_add_details("cult_objective","cult_harvest|SUCCESS") - else - explanation = "Offer [harvest_target] humans for Nar-Sie's first meal of the day. ([harvested] eaten) Fail!" - feedback_add_details("cult_objective","cult_harvest|FAIL") - - if("hijack") - if(!escaped_shuttle) - explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Success!" - feedback_add_details("cult_objective","cult_hijack|SUCCESS") - else - explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Fail!" - feedback_add_details("cult_objective","cult_hijack|FAIL") - - if("massacre") - if(survivors < massacre_target) - explanation = "Massacre the crew until less than [massacre_target] humans are left on the station. ([survivors] humans left alive) Success!" - feedback_add_details("cult_objective","cult_massacre|SUCCESS") - else - explanation = "Massacre the crew until less than [massacre_target] humans are left on the station. ([survivors] humans left alive) Fail!" - feedback_add_details("cult_objective","cult_massacre|FAIL") - - text += "
      Objective #[obj_count]: [explanation]" - - completion_text += text - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_cult() - var/text = "" - if( cult.len || (ticker && istype(ticker.mode,/datum/game_mode/cult)) ) - var/icon/logo = icon('icons/mob/mob.dmi', "cult-logo") - end_icons += logo - var/tempstate = end_icons.len - text += {"
      The cultists were: "} - for(var/datum/mind/cultist in cult) - if(cultist.current) - var/icon/flat = getFlatIcon(cultist.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [cultist.key] was [cultist.name] ("} - if(cultist.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(cultist.current.real_name != cultist.name) - text += " as [cultist.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [cultist.key] was [cultist.name] ("} - text += "body destroyed" - text += ")" - text += "

      " - - return text + if(log) + log_admin("[cult_mind.current] ([ckey(cult_mind.current.key)] has been deconverted from the cult") + stat_collection.cult.deconverted++ + +/datum/game_mode/proc/update_all_cult_icons() + spawn(0) + for(var/datum/mind/cultist in cult) + if(cultist.current) + if(cultist.current.client) + for(var/image/I in cultist.current.client.images) + if(I.icon_state == "cult") + cultist.current.client.images -= I + + for(var/datum/mind/cultist in cult) + if(cultist.current) + if(cultist.current.client) + for(var/datum/mind/cultist_1 in cult) + if(cultist_1.current) + var/imageloc = cultist_1.current + if(istype(cultist_1.current.loc,/obj/mecha)) + imageloc = cultist_1.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "cult") + cultist.current.client.images += I + + +/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) + if(!cult_mind) + return 0 + spawn(0) + for(var/datum/mind/cultist in cult) + if(cultist.current) + if(cultist.current.client) + var/imageloc = cult_mind.current + if(istype(cult_mind.current.loc,/obj/mecha)) + imageloc = cult_mind.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "cult", layer = 13) + cultist.current.client.images += I + if(cult_mind.current) + if(cult_mind.current.client) + var/imageloc = cultist.current + if(istype(cultist.current.loc,/obj/mecha)) + imageloc = cultist.current.loc + var/image/J = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "cult", layer = 13) + cult_mind.current.client.images += J + + +/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) + spawn(0) + for(var/datum/mind/cultist in cult) + if(cultist.current) + if(cultist.current.client) + for(var/image/I in cultist.current.client.images) + if(I.icon_state == "cult" && ((I.loc == cult_mind.current) || (I.loc == cult_mind.current.loc))) + cultist.current.client.images -= I + + if(cult_mind.current) + if(cult_mind.current.client) + for(var/image/I in cult_mind.current.client.images) + if(I.icon_state == "cult") + cult_mind.current.client.images -= I + + +/datum/game_mode/cult/proc/get_unconvertables() + var/list/ucs = list() + for(var/mob/living/carbon/human/player in player_list) + if(player.mind && (!is_convertable_to_cult(player.mind) || jobban_isbanned(player, "cultist"))) + ucs += player.mind + return ucs + +/datum/game_mode/cult/proc/bonus_check() + if(universe.name == "Hell Rising") + switch(objectives[current_objective]) + if("harvest") + if(harvested >= harvest_target) + bonus = 1 + + if("hijack") + for(var/mob/living/L in player_list) + if(L.stat != DEAD) + if(!(L.mind in cult)) + var/turf/T = get_turf(L) + if(istype(T.loc, /area/shuttle/escape/centcom)) + escaped_shuttle++ + else if(istype(T.loc, /area/shuttle/escape_pod1/centcom) || istype(T.loc, /area/shuttle/escape_pod2/centcom) || istype(T.loc, /area/shuttle/escape_pod3/centcom) || istype(T.loc, /area/shuttle/escape_pod5/centcom)) + escaped_pod++ + if(!escaped_shuttle) + bonus = 1 + + if("massacre") + for(var/mob/living/carbon/C in player_list) + if(C.stat != DEAD) + if(!(C.mind in cult)) + var/turf/T = get_turf(C) + if(T.z == map.zMainStation) //we're only interested in the remaining humans on the station + survivors++ + if(survivors < massacre_target) + bonus = 1 + +/datum/game_mode/cult/declare_completion() + + bonus_check() + + if(universe.name == "Hell Rising") + if(bonus) + feedback_set_details("round_end_result","win - narsie summoned - all objectives completed") + completion_text += "Cult Total Victory!" + completion_text += "
      The Cult has summoned Nar-Sie and fulfilled all of his requests" + else + feedback_set_details("round_end_result","win - narsie summoned") + completion_text += "Cult Major Victory!" + completion_text += "
      The Cult has managed to summon Nar-Sie" + else + if(current_objective > 1) + feedback_set_details("round_end_result","halfwin - some objectives completed") + completion_text += "Crew Minor Victory!" + completion_text += "
      The Cult didn't summon Nar-Sie in time but still managed to fulfill some of his requests." + else + feedback_set_details("round_end_result","loss - no objective done") + completion_text += "Crew Major Victory!" + completion_text += "
      The Staff has managed to stop the Cult" + + var/text = "
      Objectives Completed: [current_objective - 1 + bonus]" + + if(objectives.len) + text += "
      The cultists' objectives were:" + for(var/obj_count=1, obj_count <= objectives.len, obj_count++) + var/explanation + switch(objectives[obj_count]) + if("convert")//convert half the crew + if(obj_count < objectives.len) + explanation = "Convert [convert_target] crewmembers ([cult.len] cultists at round end). Success!" + feedback_add_details("cult_objective","cult_convertion|SUCCESS") + else + explanation = "Convert [convert_target] crewmembers ([cult.len] total cultists). Fail!" + feedback_add_details("cult_objective","cult_convertion|FAIL") + + if("bloodspill")//cover a large portion of the station in blood + if(obj_count < objectives.len) + explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Success!" + feedback_add_details("cult_objective","cult_bloodspill|SUCCESS") + else + explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Fail!" + feedback_add_details("cult_objective","cult_bloodspill|FAIL") + + if("sacrifice")//sacrifice a high value target + if(sacrifice_target) + if(sacrifice_target in sacrificed) + explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Success!" + feedback_add_details("cult_objective","cult_sacrifice|SUCCESS") + else if(sacrifice_target && sacrifice_target.current) + explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail." + feedback_add_details("cult_objective","cult_sacrifice|FAIL") + else + explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. Fail (Gibbed)." + feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED") + + if("eldergod")//summon narsie + if(universe.name == "Hell Rising") + explanation = "Summon Nar-Sie. Success!" + feedback_add_details("cult_objective","cult_narsie|SUCCESS") + else + explanation = "Summon Nar-Sie. Fail." + feedback_add_details("cult_objective","cult_narsie|FAIL") + + if("harvest") + if(harvested > harvest_target) + explanation = "Offer [harvest_target] humans for Nar-Sie's first meal of the day. ([harvested] eaten) Success!" + feedback_add_details("cult_objective","cult_harvest|SUCCESS") + else + explanation = "Offer [harvest_target] humans for Nar-Sie's first meal of the day. ([harvested] eaten) Fail!" + feedback_add_details("cult_objective","cult_harvest|FAIL") + + if("hijack") + if(!escaped_shuttle) + explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Success!" + feedback_add_details("cult_objective","cult_hijack|SUCCESS") + else + explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Fail!" + feedback_add_details("cult_objective","cult_hijack|FAIL") + + if("massacre") + if(survivors < massacre_target) + explanation = "Massacre the crew until less than [massacre_target] humans are left on the station. ([survivors] humans left alive) Success!" + feedback_add_details("cult_objective","cult_massacre|SUCCESS") + else + explanation = "Massacre the crew until less than [massacre_target] humans are left on the station. ([survivors] humans left alive) Fail!" + feedback_add_details("cult_objective","cult_massacre|FAIL") + + text += "
      Objective #[obj_count]: [explanation]" + + completion_text += text + ..() + return 1 + + +/datum/game_mode/proc/auto_declare_completion_cult() + var/text = "" + if( cult.len || (ticker && istype(ticker.mode,/datum/game_mode/cult)) ) + var/icon/logo = icon('icons/mob/mob.dmi', "cult-logo") + end_icons += logo + var/tempstate = end_icons.len + text += {"
      The cultists were: "} + for(var/datum/mind/cultist in cult) + if(cultist.current) + var/icon/flat = getFlatIcon(cultist.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [cultist.key] was [cultist.name] ("} + if(cultist.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(cultist.current.real_name != cultist.name) + text += " as [cultist.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [cultist.key] was [cultist.name] ("} + text += "body destroyed" + text += ")" + text += "

      " + + return text diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index da4173a40fd..81408e253f1 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -1,114 +1,114 @@ -/obj/item/weapon/melee/cultblade - name = "Cult Blade" - desc = "An arcane weapon wielded by the followers of Nar-Sie" - icon_state = "cultblade" - item_state = "cultblade" - flags = FPRINT - w_class = 4 - force = 30 - throwforce = 10 - sharpness = 1.35 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/weapon/melee/cultblade/cultify() - return - -/obj/item/weapon/melee/cultblade/attack(mob/living/target as mob, mob/living/carbon/human/user as mob) - if(iscultist(user)) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - else - user.Paralyse(5) - to_chat(user, "An unexplicable force powerfully repels the sword from [target]!") - var/organ = ((user.hand ? "l_":"r_") + "arm") - var/datum/organ/external/affecting = user.get_organ(organ) - if(affecting.take_damage(rand(force/2, force))) //random amount of damage between half of the blade's force and the full force of the blade. - user.UpdateDamageIcon() - return - -/obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob) - if(!iscultist(user)) - to_chat(user, "An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly.") - user.Dizzy(120) - - -/obj/item/clothing/head/culthood - name = "cult hood" - icon_state = "culthood" - desc = "A hood worn by the followers of Nar-Sie." - flags_inv = HIDEFACE - flags = FPRINT - armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0) - cold_protection = HEAD - body_parts_covered = HEAD | EYES - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0 - -/obj/item/clothing/head/culthood/cultify() - return - -/obj/item/clothing/head/culthood/alt - icon_state = "cult_hoodalt" - item_state = "cult_hoodalt" - -/obj/item/clothing/suit/cultrobes/alt - icon_state = "cultrobesalt" - item_state = "cultrobesalt" - -/obj/item/clothing/suit/cultrobes - name = "cult robes" - desc = "A set of armored robes worn by the followers of Nar-Sie" - icon_state = "cultrobes" - item_state = "cultrobes" - flags = FPRINT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) - armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0 - -/obj/item/clothing/suit/cultrobes/cultify() - return - -/obj/item/clothing/head/magus - name = "magus helm" - icon_state = "magus" - item_state = "magus" - desc = "A helm worn by the followers of Nar-Sie." - flags_inv = HIDEFACE|HIDEHAIR - flags = FPRINT - body_parts_covered = FULL_HEAD - armor = list(melee = 30, bullet = 30, laser = 30,energy = 20, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0 - -/obj/item/clothing/suit/magusred - name = "magus robes" - desc = "A set of armored robes worn by the followers of Nar-Sie" - icon_state = "magusred" - item_state = "magusred" - flags = FPRINT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) - armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - siemens_coefficient = 0 - - -/obj/item/clothing/head/helmet/space/cult - name = "cult helmet" - desc = "A space worthy helmet used by the followers of Nar-Sie" - icon_state = "cult_helmet" - item_state = "cult_helmet" - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0 - -/obj/item/clothing/suit/space/cult - name = "cult armour" - icon_state = "cult_armour" - item_state = "cult_armour" - desc = "A bulky suit of armour, bristling with spikes. It looks space proof." - w_class = 3 - allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) - slowdown = 0 - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) +/obj/item/weapon/melee/cultblade + name = "Cult Blade" + desc = "An arcane weapon wielded by the followers of Nar-Sie" + icon_state = "cultblade" + item_state = "cultblade" + flags = FPRINT + w_class = 4 + force = 30 + throwforce = 10 + sharpness = 1.35 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/melee/cultblade/cultify() + return + +/obj/item/weapon/melee/cultblade/attack(mob/living/target as mob, mob/living/carbon/human/user as mob) + if(iscultist(user)) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + else + user.Paralyse(5) + to_chat(user, "An unexplicable force powerfully repels the sword from [target]!") + var/organ = ((user.hand ? "l_":"r_") + "arm") + var/datum/organ/external/affecting = user.get_organ(organ) + if(affecting.take_damage(rand(force/2, force))) //random amount of damage between half of the blade's force and the full force of the blade. + user.UpdateDamageIcon() + return + +/obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob) + if(!iscultist(user)) + to_chat(user, "An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly.") + user.Dizzy(120) + + +/obj/item/clothing/head/culthood + name = "cult hood" + icon_state = "culthood" + desc = "A hood worn by the followers of Nar-Sie." + flags_inv = HIDEFACE + flags = FPRINT + armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0) + cold_protection = HEAD + body_parts_covered = HEAD | EYES + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0 + +/obj/item/clothing/head/culthood/cultify() + return + +/obj/item/clothing/head/culthood/alt + icon_state = "cult_hoodalt" + item_state = "cult_hoodalt" + +/obj/item/clothing/suit/cultrobes/alt + icon_state = "cultrobesalt" + item_state = "cultrobesalt" + +/obj/item/clothing/suit/cultrobes + name = "cult robes" + desc = "A set of armored robes worn by the followers of Nar-Sie" + icon_state = "cultrobes" + item_state = "cultrobes" + flags = FPRINT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) + armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0 + +/obj/item/clothing/suit/cultrobes/cultify() + return + +/obj/item/clothing/head/magus + name = "magus helm" + icon_state = "magus" + item_state = "magus" + desc = "A helm worn by the followers of Nar-Sie." + flags_inv = HIDEFACE|HIDEHAIR + flags = FPRINT + body_parts_covered = FULL_HEAD + armor = list(melee = 30, bullet = 30, laser = 30,energy = 20, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0 + +/obj/item/clothing/suit/magusred + name = "magus robes" + desc = "A set of armored robes worn by the followers of Nar-Sie" + icon_state = "magusred" + item_state = "magusred" + flags = FPRINT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade) + armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 0 + + +/obj/item/clothing/head/helmet/space/cult + name = "cult helmet" + desc = "A space worthy helmet used by the followers of Nar-Sie" + icon_state = "cult_helmet" + item_state = "cult_helmet" + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0 + +/obj/item/clothing/suit/space/cult + name = "cult armour" + icon_state = "cult_armour" + item_state = "cult_armour" + desc = "A bulky suit of armour, bristling with spikes. It looks space proof." + w_class = 3 + allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) + slowdown = 0 + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 94c7cc5b3b9..f0a94aa5310 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -1,680 +1,680 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -var/cultwords = list() -var/global/runedec = 0 -var/global/list/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide") -var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") -var/global/list/rune_list = list() // HOLY FUCK WHY ARE WE LOOPING THROUGH THE WORLD WHEN AN AI LOGS IN - -/client/proc/check_words() // -- Urist - set category = "Special Verbs" - set name = "Check Rune Words" - set desc = "Check the rune-word meaning" - if(!cultwords["travel"]) - runerandom() - for (var/word in engwords) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +var/cultwords = list() +var/global/runedec = 0 +var/global/list/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide") +var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") +var/global/list/rune_list = list() // HOLY FUCK WHY ARE WE LOOPING THROUGH THE WORLD WHEN AN AI LOGS IN + +/client/proc/check_words() // -- Urist + set category = "Special Verbs" + set name = "Check Rune Words" + set desc = "Check the rune-word meaning" + if(!cultwords["travel"]) + runerandom() + for (var/word in engwords) to_chat(usr, "[cultwords[word]] is [word]") - -/proc/runerandom() //randomizes word meaning - var/list/runewords= rnwords///"orkan" and "allaq" removed. - for (var/word in engwords) - cultwords[word] = pick(runewords) - runewords-=cultwords[word] - -/obj/effect/rune - desc = "A strange collection of symbols drawn in blood." - anchored = 1 - icon = 'icons/obj/rune.dmi' - icon_state = "1" - var/visibility = 0 - unacidable = 1 - layer = TURF_LAYER - - var/dead=0 // For cascade and whatnot. - - - var/word1 - var/word2 - var/word3 - var/image/blood_image - - var/atom/movable/overlay/c_animation = null - var/nullblock = 0 - var/mob/living/ajourn - - var/summoning = 0 - var/list/summonturfs = list() - -// Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere. - -// travel self [word] - Teleport to random [rune with word destination matching] -// travel other [word] - Portal to rune with word destination matching - kinda doesnt work. At least the icon. No idea why. -// see blood Hell - Create a new tome -// join blood self - Incorporate person over the rune into the group -// Hell join self - Summon TERROR -// destroy see technology - EMP rune -// travel blood self - Drain blood -// see Hell join - See invisible -// blood join Hell - Raise dead - -// hide see blood - Hide nearby runes -// blood see hide - Reveal nearby runes - The point of this rune is that its reversed obscure rune. So you always know the words to reveal the rune once oyu have obscured it. - -// Hell travel self - Leave your body and ghost around -// blood see travel - Manifest a ghost into a mortal body -// Hell tech join - Imbue a rune into a talisman -// Hell blood join - Sacrifice rune -// destroy travel self - Wall rune -// join other self - Summon cultist rune -// travel technology other - Freeing rune // other blood travel was freedom join other - -// hide other see - Deafening rune // was destroy see hear -// destroy see other - Blinding rune -// destroy see blood - BLOOD BOIL - -// self other technology - Communication rune //was other hear blood -// join hide technology - stun rune. Rune color: bright pink. -/obj/effect/rune/New() - ..() - blood_image = image(loc = src) - blood_image.override = 1 - for(var/mob/living/silicon/ai/AI in player_list) - if(AI.client) - AI.client.images += blood_image - rune_list.Add(src) - stat_collection.cult.runes_written++ - -/obj/effect/rune/Destroy() - if(istype(ajourn)) - ajourn.ajourn = null - ajourn = null - for(var/mob/living/silicon/ai/AI in player_list) - if(AI.client) - AI.client.images -= blood_image - qdel(blood_image) - blood_image = null - rune_list.Remove(src) - ..() - -/obj/effect/rune/examine(mob/user) - ..() - if(iscultist(user) || isobserver(user)) - var/rune_name = get_uristrune_name(word1,word2,word3) + +/proc/runerandom() //randomizes word meaning + var/list/runewords= rnwords///"orkan" and "allaq" removed. + for (var/word in engwords) + cultwords[word] = pick(runewords) + runewords-=cultwords[word] + +/obj/effect/rune + desc = "A strange collection of symbols drawn in blood." + anchored = 1 + icon = 'icons/obj/rune.dmi' + icon_state = "1" + var/visibility = 0 + unacidable = 1 + layer = TURF_LAYER + + var/dead=0 // For cascade and whatnot. + + + var/word1 + var/word2 + var/word3 + var/image/blood_image + + var/atom/movable/overlay/c_animation = null + var/nullblock = 0 + var/mob/living/ajourn + + var/summoning = 0 + var/list/summonturfs = list() + +// Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere. + +// travel self [word] - Teleport to random [rune with word destination matching] +// travel other [word] - Portal to rune with word destination matching - kinda doesnt work. At least the icon. No idea why. +// see blood Hell - Create a new tome +// join blood self - Incorporate person over the rune into the group +// Hell join self - Summon TERROR +// destroy see technology - EMP rune +// travel blood self - Drain blood +// see Hell join - See invisible +// blood join Hell - Raise dead + +// hide see blood - Hide nearby runes +// blood see hide - Reveal nearby runes - The point of this rune is that its reversed obscure rune. So you always know the words to reveal the rune once oyu have obscured it. + +// Hell travel self - Leave your body and ghost around +// blood see travel - Manifest a ghost into a mortal body +// Hell tech join - Imbue a rune into a talisman +// Hell blood join - Sacrifice rune +// destroy travel self - Wall rune +// join other self - Summon cultist rune +// travel technology other - Freeing rune // other blood travel was freedom join other + +// hide other see - Deafening rune // was destroy see hear +// destroy see other - Blinding rune +// destroy see blood - BLOOD BOIL + +// self other technology - Communication rune //was other hear blood +// join hide technology - stun rune. Rune color: bright pink. +/obj/effect/rune/New() + ..() + blood_image = image(loc = src) + blood_image.override = 1 + for(var/mob/living/silicon/ai/AI in player_list) + if(AI.client) + AI.client.images += blood_image + rune_list.Add(src) + stat_collection.cult.runes_written++ + +/obj/effect/rune/Destroy() + if(istype(ajourn)) + ajourn.ajourn = null + ajourn = null + for(var/mob/living/silicon/ai/AI in player_list) + if(AI.client) + AI.client.images -= blood_image + qdel(blood_image) + blood_image = null + rune_list.Remove(src) + ..() + +/obj/effect/rune/examine(mob/user) + ..() + if(iscultist(user) || isobserver(user)) + var/rune_name = get_uristrune_name(word1,word2,word3) to_chat(user, "A spell circle drawn in blood. It reads: [word1] [word2] [word3].[rune_name ? " From [pick("your intuition, you are pretty sure that","deep memories, you determine that","the rune's energies, you deduct that","Nar-Sie's murmurs, you know that")] this is \a [rune_name] rune." : ""]") - - -/obj/effect/rune/attackby(I as obj, user as mob) - if(istype(I, /obj/item/weapon/tome) && iscultist(user)) + + +/obj/effect/rune/attackby(I as obj, user as mob) + if(istype(I, /obj/item/weapon/tome) && iscultist(user)) to_chat(user, "You retrace your steps, carefully undoing the lines of the rune.") - qdel(src) - return - else if(istype(I, /obj/item/weapon/nullrod)) + qdel(src) + return + else if(istype(I, /obj/item/weapon/nullrod)) to_chat(user, "You disrupt the vile magic with the deadening field of the null rod!") - qdel(src) - stat_collection.cult.runes_nulled++ - return - return - -/obj/effect/rune/attack_animal(mob/living/simple_animal/user as mob) - if(istype(user, /mob/living/simple_animal/construct/harvester)) - attack_hand(user) - -/obj/effect/rune/attack_paw(mob/living/M as mob) - if(ismonkey(M)) - attack_hand(M) - -/obj/effect/rune/attack_hand(mob/living/user as mob) - if(!iscultist(user)) + qdel(src) + stat_collection.cult.runes_nulled++ + return + return + +/obj/effect/rune/attack_animal(mob/living/simple_animal/user as mob) + if(istype(user, /mob/living/simple_animal/construct/harvester)) + attack_hand(user) + +/obj/effect/rune/attack_paw(mob/living/M as mob) + if(ismonkey(M)) + attack_hand(M) + +/obj/effect/rune/attack_hand(mob/living/user as mob) + if(!iscultist(user)) to_chat(user, "You can't mouth the arcane scratchings without fumbling over them.") - return - if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) + return + if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) to_chat(user, "You are unable to speak the words of the rune.") - return - if(!word1 || !word2 || !word3 || prob(user.getBrainLoss())) - return fizzle() -// if(!src.visibility) -// src.visibility=1 - if(word1 == cultwords["travel"] && word2 == cultwords["self"]) - return teleport(src.word3) - if(word1 == cultwords["see"] && word2 == cultwords["blood"] && word3 == cultwords["hell"]) - return tomesummon() - if(word1 == cultwords["hell"] && word2 == cultwords["destroy"] && word3 == cultwords["other"]) - return armor() - if(word1 == cultwords["join"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) - return convert() - if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) - return tearreality() - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) - return emp(src.loc,3) - if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) - return drain() - if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) - return seer() - if(word1 == cultwords["blood"] && word2 == cultwords["join"] && word3 == cultwords["hell"]) - return raise() - if(word1 == cultwords["hide"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) - return obscure(4) - if(word1 == cultwords["hell"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) - return ajourney() - if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["travel"]) - return manifest() - if(word1 == cultwords["hell"] && word2 == cultwords["technology"] && word3 == cultwords["join"]) - return talisman() - if(word1 == cultwords["hell"] && word2 == cultwords["blood"] && word3 == cultwords["join"]) - return sacrifice() - if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["hide"]) - return revealrunes(src) - if(word1 == cultwords["destroy"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) - return wall() - if(word1 == cultwords["travel"] && word2 == cultwords["technology"] && word3 == cultwords["other"]) - return freedom() - if(word1 == cultwords["join"] && word2 == cultwords["other"] && word3 == cultwords["self"]) - return cultsummon() - if(word1 == cultwords["hide"] && word2 == cultwords["other"] && word3 == cultwords["see"]) - return deafen() - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["other"]) - return blind() - if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) - return bloodboil() - if(word1 == cultwords["self"] && word2 == cultwords["other"] && word3 == cultwords["technology"]) - return communicate() - if(word1 == cultwords["travel"] && word2 == cultwords["other"]) - return itemport(src.word3) - if(word1 == cultwords["join"] && word2 == cultwords["hide"] && word3 == cultwords["technology"]) - return runestun() - else - return fizzle() - - -/obj/effect/rune/proc/fizzle() - stat_collection.cult.runes_fumbled++ - if(istype(src,/obj/effect/rune)) - usr.say(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP")) - else - usr.whisper(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP")) - for (var/mob/V in viewers(src)) - V.show_message("The markings pulse with a small burst of light, then fall dark.", 1, "You hear a faint fizzle.", 2) - return - -/obj/effect/rune/proc/check_icon() - icon = get_uristrune_cult(word1, word2, word3) - -/obj/item/weapon/tome - name = "arcane tome" - desc = "An old, dusty tome with frayed edges and a sinister looking cover." - icon = 'icons/obj/cult.dmi' - icon_state ="tome" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - flags = FPRINT - var/notedat = "" - var/tomedat = "" - var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") - - tomedat = {" - - - - -

      The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood.

      - - The book is written in an unknown dialect, there are lots of pictures of various complex geometric shapes. You find some notes in english that give you basic understanding of the many runes written in the book. The notes give you an understanding what the words for the runes should be. However, you do not know how to write all these words in this dialect.
      - Below is the summary of the runes.
      - -

      Contents

      -

      - Teleport self: Travel Self (word)
      - Teleport other: Travel Other (word)
      - Summon new tome: See Blood Hell
      - Convert a person: Join Blood Self
      - Summon Nar-Sie: Hell Join Self
      - EMP: Destroy See Technology
      - Drain blood: Travel Blood Self
      - Raise dead: Blood Join Hell
      - Hide runes: Hide See Blood
      - Reveal runes: Blood See Hide
      - Astral Journey: Hell travel self
      - Manifest a ghost : Blood See Travel
      - Imbue a talisman: Hell Technology Join
      - Sacrifice: Hell Blood Join
      - Wall: Destroy Travel Self
      - Summon cultist: Join Other Self
      - Free a cultist: Travel technology other
      - Deafen: Hide Other See
      - Blind: Destroy See Other
      - Communicate: Self Other Technology
      - Stun: Join Hide Technology
      - Cult Armor: Hell Destroy Other
      - See Invisible: See Hell Join
      - Blood Boil: Destroy See Blood
      -

      -

      Rune Descriptions

      -

      Teleport self

      - Teleport rune is a special rune, as it only needs two words, with the third word being destination. Basically, when you have two runes with the same destination, invoking one will teleport you to the other one. If there are more than 2 runes, you will be teleported to a random one. Runes with different third words will create separate networks. You can imbue this rune into a talisman, giving you a great escape mechanism.
      -

      Teleport other

      - Teleport other allows for teleportation for any movable object to another rune with the same third word. You need 3 cultists chanting the invocation for this rune to work.
      -

      Summon new tome

      - Invoking this rune summons a new arcane tome. -

      Convert a person

      - This rune opens target's mind to the realm of Nar-Sie, which usually results in this person joining the cult. However, some people (mostly the ones who posess high authority) have strong enough will to stay true to their old ideals.
      -

      Summon Nar-Sie

      - The ultimate rune. It summons the Avatar of Nar-Sie himself, tearing a huge hole in reality and consuming everything around it. Summoning it is the final goal of any cult. Just make sure that you have completed any other objectives and that you are on the Station when you try summon Him.
      -

      EMP

      - Invoking this rune creates a strong electromagnetic pulse in a small radius, making it basically analogic to an EMP grenade. You can imbue this rune into a talisman, making it a decent defensive item.
      -

      Drain Blood

      - This rune instantly heals you of some brute damage at the expense of a person placed on top of the rune. Whenever you invoke a drain rune, ALL drain runes on the station are activated, draining blood from anyone located on top of those runes. This includes yourself, though the blood you drain from yourself just comes back to you. This might help you identify this rune when studying words. One drain gives up to 25HP per each victim, but you can repeat it if you need more. Draining only works on living people, so you might need to recharge your "Battery" once its empty. Drinking too much blood at once might cause blood hunger.
      -

      Raise Dead

      - This rune allows for the resurrection of any dead person. You will need a dead human body and a living human sacrifice. Make 2 raise dead runes. Put a living non-braindead human on top of one, and a dead body on the other one. When you invoke the rune, the life force of the living human will be transferred into the dead body, allowing a ghost standing on top of the dead body to enter it, instantly and fully healing it. Use other runes to ensure there is a ghost ready to be resurrected.
      -

      Hide runes

      - This rune makes all nearby runes completely invisible. They are still there and will work if activated somehow, but you cannot invoke them directly if you do not see them.
      -

      Reveal runes

      - This rune is made to reverse the process of hiding a rune. It reveals all hidden runes in a rather large area around it. -

      Astral Journey

      - This rune gently rips your soul out of your body, leaving it intact. You can observe the surroundings as a ghost as well as communicate with other ghosts. Your body takes damage while you are there, so ensure your journey is not too long, or you might never come back.
      -

      Manifest a ghost

      - Unlike the Raise Dead rune, this rune does not require any special preparations or vessels. Instead of using full lifeforce of a sacrifice, it will drain YOUR lifeforce. Stand on the rune and invoke it. If theres a ghost standing over the rune, it will materialise, and will live as long as you dont move off the rune or die. You can put a paper with a name on the rune to make the new body look like that person.
      -

      Imbue a talisman

      - This rune allows you to imbue the magic of some runes into paper talismans. Create an imbue rune, then an appropriate rune beside it. Put an empty piece of paper on the imbue rune and invoke it. You will now have a one-use talisman with the power of the target rune. Using a talisman drains some health, so be careful with it. You can imbue a talisman with power of the following runes: summon tome, reveal, conceal, teleport, disable technology, communicate, deafen, blind and stun.
      -

      Sacrifice

      - Sacrifice rune allows you to sacrifice a living thing or a body to the Geometer of Blood. Monkeys and dead humans are the most basic sacrifices, they might or might not be enough to gain His favor. A living human is what a real sacrifice should be, however, you will need 3 people chanting the invocation to sacrifice a living person.
      Silicons can also be disposed of using this rune.
      -

      Create a wall

      - Invoking this rune solidifies the air above it, creating an an invisible wall. To remove the wall, simply invoke the rune again. -

      Summon cultist

      - This rune allows you to summon a fellow cultist to your location. The target cultist must be unhandcuffed ant not buckled to anything. You also need to have 3 people chanting at the rune to succesfully invoke it. Invoking it takes heavy strain on the bodies of all chanting cultists.
      -

      Free a cultist

      - This rune unhandcuffs and unbuckles any cultist of your choice, no matter where he is. You need to have 3 people invoking the rune for it to work. Invoking it takes heavy strain on the bodies of all chanting cultists.
      -

      Deafen

      - This rune temporarily deafens all non-cultists around you.
      -

      Blind

      - This rune temporarily blinds all non-cultists around you. Very robust. Use together with the deafen rune to leave your enemies completely helpless.
      -

      Communicate

      - Invoking this rune allows you to relay a message to all cultists on the station and nearby space objects. -

      Stun

      - Unlike other runes, this ons is supposed to be used in talisman form. When invoked directly, it simply releases some dark energy, briefly stunning everyone around. When imbued into a talisman, you can force all of its energy into one person, stunning him so hard he cant even speak. However, effect wears off rather fast.

      Works on robots!
      -

      Cult Armor

      - When this rune is invoked, either from a rune or a talisman, it will equip the user with the armor of the followers of Nar-Sie. To use this rune to its fullest extent, make sure you are not wearing any form of headgear, armor, gloves or shoes, and make sure you are not holding anything in your hands.
      Small-sized individuals will be provided with a fitting armor.

      You may also use this rune to change a construct's type. Simply ask the construct to stand on the rune then touch it.
      -

      See Invisible

      - When invoked when standing on it, this rune allows the user to see the the world beyond as long as he does not move.
      -

      Blood boil

      - This rune boils the blood all non-cultists in visible range. The damage is enough to instantly critically hurt any person. You need 3 cultists invoking the rune for it to work. This rune is unreliable and may cause unpredicted effect when invoked. It also drains significant amount of your health when succesfully invoked.
      - - - "} - - -/obj/item/weapon/tome/Topic(href,href_list[]) - if (src.loc == usr) - var/number = text2num(href_list["number"]) - if (usr.stat || usr.restrained()) - return - switch(href_list["action"]) - if("clear") - words[words[number]] = words[number] - if("change") - words[words[number]] = input("Enter the translation for [words[number]]", "Word notes") in engwords - for (var/w in words) - if ((words[w] == words[words[number]]) && (w != words[number])) - words[w] = w - notedat = {" -
      Word translation notes
      - [words[1]] is [words[words[1]]] Clear
      - [words[2]] is [words[words[2]]] Clear
      - [words[3]] is [words[words[3]]] Clear
      - [words[4]] is [words[words[4]]] Clear
      - [words[5]] is [words[words[5]]] Clear
      - [words[6]] is [words[words[6]]] Clear
      - [words[7]] is [words[words[7]]] Clear
      - [words[8]] is [words[words[8]]] Clear
      - [words[9]] is [words[words[9]]] Clear
      - [words[10]] is [words[words[10]]] Clear
      - "} - usr << browse("[notedat]", "window=notes") -// call(/obj/item/weapon/tome/proc/edit_notes)() - else - usr << browse(null, "window=notes") - return - -/* -/obj/item/weapon/tome/proc/edit_notes() FUCK IT. Cant get it to work properly. - K0000 + return + if(!word1 || !word2 || !word3 || prob(user.getBrainLoss())) + return fizzle() +// if(!src.visibility) +// src.visibility=1 + if(word1 == cultwords["travel"] && word2 == cultwords["self"]) + return teleport(src.word3) + if(word1 == cultwords["see"] && word2 == cultwords["blood"] && word3 == cultwords["hell"]) + return tomesummon() + if(word1 == cultwords["hell"] && word2 == cultwords["destroy"] && word3 == cultwords["other"]) + return armor() + if(word1 == cultwords["join"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) + return convert() + if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) + return tearreality() + if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) + return emp(src.loc,3) + if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) + return drain() + if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) + return seer() + if(word1 == cultwords["blood"] && word2 == cultwords["join"] && word3 == cultwords["hell"]) + return raise() + if(word1 == cultwords["hide"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) + return obscure(4) + if(word1 == cultwords["hell"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) + return ajourney() + if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["travel"]) + return manifest() + if(word1 == cultwords["hell"] && word2 == cultwords["technology"] && word3 == cultwords["join"]) + return talisman() + if(word1 == cultwords["hell"] && word2 == cultwords["blood"] && word3 == cultwords["join"]) + return sacrifice() + if(word1 == cultwords["blood"] && word2 == cultwords["see"] && word3 == cultwords["hide"]) + return revealrunes(src) + if(word1 == cultwords["destroy"] && word2 == cultwords["travel"] && word3 == cultwords["self"]) + return wall() + if(word1 == cultwords["travel"] && word2 == cultwords["technology"] && word3 == cultwords["other"]) + return freedom() + if(word1 == cultwords["join"] && word2 == cultwords["other"] && word3 == cultwords["self"]) + return cultsummon() + if(word1 == cultwords["hide"] && word2 == cultwords["other"] && word3 == cultwords["see"]) + return deafen() + if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["other"]) + return blind() + if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["blood"]) + return bloodboil() + if(word1 == cultwords["self"] && word2 == cultwords["other"] && word3 == cultwords["technology"]) + return communicate() + if(word1 == cultwords["travel"] && word2 == cultwords["other"]) + return itemport(src.word3) + if(word1 == cultwords["join"] && word2 == cultwords["hide"] && word3 == cultwords["technology"]) + return runestun() + else + return fizzle() + + +/obj/effect/rune/proc/fizzle() + stat_collection.cult.runes_fumbled++ + if(istype(src,/obj/effect/rune)) + usr.say(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP")) + else + usr.whisper(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP")) + for (var/mob/V in viewers(src)) + V.show_message("The markings pulse with a small burst of light, then fall dark.", 1, "You hear a faint fizzle.", 2) + return + +/obj/effect/rune/proc/check_icon() + icon = get_uristrune_cult(word1, word2, word3) + +/obj/item/weapon/tome + name = "arcane tome" + desc = "An old, dusty tome with frayed edges and a sinister looking cover." + icon = 'icons/obj/cult.dmi' + icon_state ="tome" + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + flags = FPRINT + var/notedat = "" + var/tomedat = "" + var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") + + tomedat = {" + + + + +

      The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood.

      + + The book is written in an unknown dialect, there are lots of pictures of various complex geometric shapes. You find some notes in english that give you basic understanding of the many runes written in the book. The notes give you an understanding what the words for the runes should be. However, you do not know how to write all these words in this dialect.
      + Below is the summary of the runes.
      + +

      Contents

      +

      + Teleport self: Travel Self (word)
      + Teleport other: Travel Other (word)
      + Summon new tome: See Blood Hell
      + Convert a person: Join Blood Self
      + Summon Nar-Sie: Hell Join Self
      + EMP: Destroy See Technology
      + Drain blood: Travel Blood Self
      + Raise dead: Blood Join Hell
      + Hide runes: Hide See Blood
      + Reveal runes: Blood See Hide
      + Astral Journey: Hell travel self
      + Manifest a ghost : Blood See Travel
      + Imbue a talisman: Hell Technology Join
      + Sacrifice: Hell Blood Join
      + Wall: Destroy Travel Self
      + Summon cultist: Join Other Self
      + Free a cultist: Travel technology other
      + Deafen: Hide Other See
      + Blind: Destroy See Other
      + Communicate: Self Other Technology
      + Stun: Join Hide Technology
      + Cult Armor: Hell Destroy Other
      + See Invisible: See Hell Join
      + Blood Boil: Destroy See Blood
      +

      +

      Rune Descriptions

      +

      Teleport self

      + Teleport rune is a special rune, as it only needs two words, with the third word being destination. Basically, when you have two runes with the same destination, invoking one will teleport you to the other one. If there are more than 2 runes, you will be teleported to a random one. Runes with different third words will create separate networks. You can imbue this rune into a talisman, giving you a great escape mechanism.
      +

      Teleport other

      + Teleport other allows for teleportation for any movable object to another rune with the same third word. You need 3 cultists chanting the invocation for this rune to work.
      +

      Summon new tome

      + Invoking this rune summons a new arcane tome. +

      Convert a person

      + This rune opens target's mind to the realm of Nar-Sie, which usually results in this person joining the cult. However, some people (mostly the ones who posess high authority) have strong enough will to stay true to their old ideals.
      +

      Summon Nar-Sie

      + The ultimate rune. It summons the Avatar of Nar-Sie himself, tearing a huge hole in reality and consuming everything around it. Summoning it is the final goal of any cult. Just make sure that you have completed any other objectives and that you are on the Station when you try summon Him.
      +

      EMP

      + Invoking this rune creates a strong electromagnetic pulse in a small radius, making it basically analogic to an EMP grenade. You can imbue this rune into a talisman, making it a decent defensive item.
      +

      Drain Blood

      + This rune instantly heals you of some brute damage at the expense of a person placed on top of the rune. Whenever you invoke a drain rune, ALL drain runes on the station are activated, draining blood from anyone located on top of those runes. This includes yourself, though the blood you drain from yourself just comes back to you. This might help you identify this rune when studying words. One drain gives up to 25HP per each victim, but you can repeat it if you need more. Draining only works on living people, so you might need to recharge your "Battery" once its empty. Drinking too much blood at once might cause blood hunger.
      +

      Raise Dead

      + This rune allows for the resurrection of any dead person. You will need a dead human body and a living human sacrifice. Make 2 raise dead runes. Put a living non-braindead human on top of one, and a dead body on the other one. When you invoke the rune, the life force of the living human will be transferred into the dead body, allowing a ghost standing on top of the dead body to enter it, instantly and fully healing it. Use other runes to ensure there is a ghost ready to be resurrected.
      +

      Hide runes

      + This rune makes all nearby runes completely invisible. They are still there and will work if activated somehow, but you cannot invoke them directly if you do not see them.
      +

      Reveal runes

      + This rune is made to reverse the process of hiding a rune. It reveals all hidden runes in a rather large area around it. +

      Astral Journey

      + This rune gently rips your soul out of your body, leaving it intact. You can observe the surroundings as a ghost as well as communicate with other ghosts. Your body takes damage while you are there, so ensure your journey is not too long, or you might never come back.
      +

      Manifest a ghost

      + Unlike the Raise Dead rune, this rune does not require any special preparations or vessels. Instead of using full lifeforce of a sacrifice, it will drain YOUR lifeforce. Stand on the rune and invoke it. If theres a ghost standing over the rune, it will materialise, and will live as long as you dont move off the rune or die. You can put a paper with a name on the rune to make the new body look like that person.
      +

      Imbue a talisman

      + This rune allows you to imbue the magic of some runes into paper talismans. Create an imbue rune, then an appropriate rune beside it. Put an empty piece of paper on the imbue rune and invoke it. You will now have a one-use talisman with the power of the target rune. Using a talisman drains some health, so be careful with it. You can imbue a talisman with power of the following runes: summon tome, reveal, conceal, teleport, disable technology, communicate, deafen, blind and stun.
      +

      Sacrifice

      + Sacrifice rune allows you to sacrifice a living thing or a body to the Geometer of Blood. Monkeys and dead humans are the most basic sacrifices, they might or might not be enough to gain His favor. A living human is what a real sacrifice should be, however, you will need 3 people chanting the invocation to sacrifice a living person.
      Silicons can also be disposed of using this rune.
      +

      Create a wall

      + Invoking this rune solidifies the air above it, creating an an invisible wall. To remove the wall, simply invoke the rune again. +

      Summon cultist

      + This rune allows you to summon a fellow cultist to your location. The target cultist must be unhandcuffed ant not buckled to anything. You also need to have 3 people chanting at the rune to succesfully invoke it. Invoking it takes heavy strain on the bodies of all chanting cultists.
      +

      Free a cultist

      + This rune unhandcuffs and unbuckles any cultist of your choice, no matter where he is. You need to have 3 people invoking the rune for it to work. Invoking it takes heavy strain on the bodies of all chanting cultists.
      +

      Deafen

      + This rune temporarily deafens all non-cultists around you.
      +

      Blind

      + This rune temporarily blinds all non-cultists around you. Very robust. Use together with the deafen rune to leave your enemies completely helpless.
      +

      Communicate

      + Invoking this rune allows you to relay a message to all cultists on the station and nearby space objects. +

      Stun

      + Unlike other runes, this ons is supposed to be used in talisman form. When invoked directly, it simply releases some dark energy, briefly stunning everyone around. When imbued into a talisman, you can force all of its energy into one person, stunning him so hard he cant even speak. However, effect wears off rather fast.

      Works on robots!
      +

      Cult Armor

      + When this rune is invoked, either from a rune or a talisman, it will equip the user with the armor of the followers of Nar-Sie. To use this rune to its fullest extent, make sure you are not wearing any form of headgear, armor, gloves or shoes, and make sure you are not holding anything in your hands.
      Small-sized individuals will be provided with a fitting armor.

      You may also use this rune to change a construct's type. Simply ask the construct to stand on the rune then touch it.
      +

      See Invisible

      + When invoked when standing on it, this rune allows the user to see the the world beyond as long as he does not move.
      +

      Blood boil

      + This rune boils the blood all non-cultists in visible range. The damage is enough to instantly critically hurt any person. You need 3 cultists invoking the rune for it to work. This rune is unreliable and may cause unpredicted effect when invoked. It also drains significant amount of your health when succesfully invoked.
      + + + "} + + +/obj/item/weapon/tome/Topic(href,href_list[]) + if (src.loc == usr) + var/number = text2num(href_list["number"]) + if (usr.stat || usr.restrained()) + return + switch(href_list["action"]) + if("clear") + words[words[number]] = words[number] + if("change") + words[words[number]] = input("Enter the translation for [words[number]]", "Word notes") in engwords + for (var/w in words) + if ((words[w] == words[words[number]]) && (w != words[number])) + words[w] = w + notedat = {" +
      Word translation notes
      + [words[1]] is [words[words[1]]] Clear
      + [words[2]] is [words[words[2]]] Clear
      + [words[3]] is [words[words[3]]] Clear
      + [words[4]] is [words[words[4]]] Clear
      + [words[5]] is [words[words[5]]] Clear
      + [words[6]] is [words[words[6]]] Clear
      + [words[7]] is [words[words[7]]] Clear
      + [words[8]] is [words[words[8]]] Clear
      + [words[9]] is [words[words[9]]] Clear
      + [words[10]] is [words[words[10]]] Clear
      + "} + usr << browse("[notedat]", "window=notes") +// call(/obj/item/weapon/tome/proc/edit_notes)() + else + usr << browse(null, "window=notes") + return + +/* +/obj/item/weapon/tome/proc/edit_notes() FUCK IT. Cant get it to work properly. - K0000 to_chat(world, "its been called! [usr]") - notedat = {" -
      Word translation notes
      - [words[1]] is [words[words[1]]] Clear
      - [words[2]] is [words[words[2]]] Clear
      - [words[3]] is [words[words[3]]] Clear
      - [words[4]] is [words[words[4]]] Clear
      - [words[5]] is [words[words[5]]] Clear
      - [words[6]] is [words[words[6]]] Clear
      - [words[7]] is [words[words[7]]] Clear
      - [words[8]] is [words[words[8]]] Clear
      - [words[9]] is [words[words[9]]] Clear
      - [words[10]] is [words[words[10]]] Clear
      - "} + notedat = {" +
      Word translation notes
      + [words[1]] is [words[words[1]]] Clear
      + [words[2]] is [words[words[2]]] Clear
      + [words[3]] is [words[words[3]]] Clear
      + [words[4]] is [words[words[4]]] Clear
      + [words[5]] is [words[words[5]]] Clear
      + [words[6]] is [words[words[6]]] Clear
      + [words[7]] is [words[words[7]]] Clear
      + [words[8]] is [words[words[8]]] Clear
      + [words[9]] is [words[words[9]]] Clear
      + [words[10]] is [words[words[10]]] Clear
      + "} to_chat(usr, "whatev") - usr << browse(null, "window=tank") -*/ - -/obj/item/weapon/tome/attack(mob/living/M as mob, mob/living/user as mob) - M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on him by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used [name] on [M.name] ([M.ckey]) (JMP)") - if(!iscarbon(M)) - M.LAssailant = null - else - M.LAssailant = user - - return - if(!istype(M)) - return - if(!iscultist(user)) - return ..() - if(iscultist(M)) - return - M.take_organ_damage(0,rand(5,20)) //really lucky - 5 hits for a crit - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] beats [] with the arcane tome!", user, M), 1) + usr << browse(null, "window=tank") +*/ + +/obj/item/weapon/tome/attack(mob/living/M as mob, mob/living/user as mob) + M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on him by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) used [name] on [M.name] ([M.ckey]) (JMP)") + if(!iscarbon(M)) + M.LAssailant = null + else + M.LAssailant = user + + return + if(!istype(M)) + return + if(!iscultist(user)) + return ..() + if(iscultist(M)) + return + M.take_organ_damage(0,rand(5,20)) //really lucky - 5 hits for a crit + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] beats [] with the arcane tome!", user, M), 1) to_chat(M, "You feel searing heat inside!") - - -/obj/item/weapon/tome/attack_self(mob/living/user as mob) - usr = user - if(!usr.canmove || usr.stat || usr.restrained()) - return - - if(!cultwords["travel"]) - runerandom() - if(iscultist(user)) - if (!istype(user.loc,/turf)) + + +/obj/item/weapon/tome/attack_self(mob/living/user as mob) + usr = user + if(!usr.canmove || usr.stat || usr.restrained()) + return + + if(!cultwords["travel"]) + runerandom() + if(iscultist(user)) + if (!istype(user.loc,/turf)) to_chat(user, "You do not have enough space to write a proper rune.") - return - - - - - if (rune_list.len >= 26+runedec+ticker.mode.cult.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist - alert("The cloth of reality can't take that much of a strain. Remove some runes first!") - return - else - switch(alert("You open the tome",,"Read it","Scribe a rune", "Notes")) //Fuck the "Cancel" option. Rewrite the whole tome interface yourself if you want it to work better. And input() is just ugly. - K0000 - if("Cancel") - return - if("Read it") - if(usr.get_active_hand() != src) - return - user << browse("[tomedat]", "window=Arcane Tome") - return - if("Notes") - if(usr.get_active_hand() != src) - return - notedat = {" -
      Word translation notes
      - [words[1]] is [words[words[1]]] Clear
      - [words[2]] is [words[words[2]]] Clear
      - [words[3]] is [words[words[3]]] Clear
      - [words[4]] is [words[words[4]]] Clear
      - [words[5]] is [words[words[5]]] Clear
      - [words[6]] is [words[words[6]]] Clear
      - [words[7]] is [words[words[7]]] Clear
      - [words[8]] is [words[words[8]]] Clear
      - [words[9]] is [words[words[9]]] Clear
      - [words[10]] is [words[words[10]]] Clear
      - "} -// call(/obj/item/weapon/tome/proc/edit_notes)() - user << browse("[notedat]", "window=notes") - return - if(usr.get_active_hand() != src) - return - - var/w1 - var/w2 - var/w3 - var/list/english = list() - for (var/w in words) - english+=words[w] - if(usr) - w1 = input("Write your first rune: \[ __ \] \[ ... \] \[ ... \]", "Rune Scribing") as null|anything in english - if(!w1) - return - if(usr) - w2 = input("Write your second rune: \[ [w1] \] \[ __ \] \[ ... \]", "Rune Scribing") as null|anything in english - if(!w2) - return - if(usr) - w3 = input("Write your third rune: \[ [w1] \] \[ [w2] \] \[ __ \]", "Rune Scribing") as null|anything in english - if(!w3) - return - - for (var/w in words) - if (words[w] == w1) - w1 = w - if (words[w] == w2) - w2 = w - if (words[w] == w3) - w3 = w - - if(usr.get_active_hand() != src) - return - for (var/mob/V in viewers(src)) - V.show_message("[user] slices open a finger and begins to chant and paint symbols on the floor.", 1, "You hear chanting.", 2) + return + + + + + if (rune_list.len >= 26+runedec+ticker.mode.cult.len) //including the useless rune at the secret room, shouldn't count against the limit of 25 runes - Urist + alert("The cloth of reality can't take that much of a strain. Remove some runes first!") + return + else + switch(alert("You open the tome",,"Read it","Scribe a rune", "Notes")) //Fuck the "Cancel" option. Rewrite the whole tome interface yourself if you want it to work better. And input() is just ugly. - K0000 + if("Cancel") + return + if("Read it") + if(usr.get_active_hand() != src) + return + user << browse("[tomedat]", "window=Arcane Tome") + return + if("Notes") + if(usr.get_active_hand() != src) + return + notedat = {" +
      Word translation notes
      + [words[1]] is [words[words[1]]] Clear
      + [words[2]] is [words[words[2]]] Clear
      + [words[3]] is [words[words[3]]] Clear
      + [words[4]] is [words[words[4]]] Clear
      + [words[5]] is [words[words[5]]] Clear
      + [words[6]] is [words[words[6]]] Clear
      + [words[7]] is [words[words[7]]] Clear
      + [words[8]] is [words[words[8]]] Clear
      + [words[9]] is [words[words[9]]] Clear
      + [words[10]] is [words[words[10]]] Clear
      + "} +// call(/obj/item/weapon/tome/proc/edit_notes)() + user << browse("[notedat]", "window=notes") + return + if(usr.get_active_hand() != src) + return + + var/w1 + var/w2 + var/w3 + var/list/english = list() + for (var/w in words) + english+=words[w] + if(usr) + w1 = input("Write your first rune: \[ __ \] \[ ... \] \[ ... \]", "Rune Scribing") as null|anything in english + if(!w1) + return + if(usr) + w2 = input("Write your second rune: \[ [w1] \] \[ __ \] \[ ... \]", "Rune Scribing") as null|anything in english + if(!w2) + return + if(usr) + w3 = input("Write your third rune: \[ [w1] \] \[ [w2] \] \[ __ \]", "Rune Scribing") as null|anything in english + if(!w3) + return + + for (var/w in words) + if (words[w] == w1) + w1 = w + if (words[w] == w2) + w2 = w + if (words[w] == w3) + w3 = w + + if(usr.get_active_hand() != src) + return + for (var/mob/V in viewers(src)) + V.show_message("[user] slices open a finger and begins to chant and paint symbols on the floor.", 1, "You hear chanting.", 2) to_chat(user, "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.") - user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage - if(do_after(user, user.loc, 50)) - if(usr.get_active_hand() != src) - return - var/mob/living/carbon/human/H = user - var/obj/effect/rune/R = new /obj/effect/rune(get_turf(user)) + user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage + if(do_after(user, user.loc, 50)) + if(usr.get_active_hand() != src) + return + var/mob/living/carbon/human/H = user + var/obj/effect/rune/R = new /obj/effect/rune(get_turf(user)) to_chat(user, "You finish drawing the arcane markings of the Geometer.") - R.word1 = w1 - R.word2 = w2 - R.word3 = w3 - R.check_icon() - R.blood_DNA = list() - R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - return - else + R.word1 = w1 + R.word2 = w2 + R.word3 = w3 + R.check_icon() + R.blood_DNA = list() + R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + return + else to_chat(user, "The book seems full of illegible scribbles. Is this a joke?") - return - -/obj/item/weapon/tome/attackby(obj/item/weapon/tome/T as obj, mob/living/user as mob) - if(istype(T, /obj/item/weapon/tome) && iscultist(user)) // sanity check to prevent a runtime error - switch(alert("Copy the runes from your tome?",,"Copy", "Cancel")) - if("cancel") - return -// var/list/nearby = viewers(1,src) //- Fuck this as well. No clue why this doesnt work. -K0000 -// if (T.loc != user) -// return -// for(var/mob/M in nearby) -// if(M == user) - for(var/w in words) - words[w] = T.words[w] + return + +/obj/item/weapon/tome/attackby(obj/item/weapon/tome/T as obj, mob/living/user as mob) + if(istype(T, /obj/item/weapon/tome) && iscultist(user)) // sanity check to prevent a runtime error + switch(alert("Copy the runes from your tome?",,"Copy", "Cancel")) + if("cancel") + return +// var/list/nearby = viewers(1,src) //- Fuck this as well. No clue why this doesnt work. -K0000 +// if (T.loc != user) +// return +// for(var/mob/M in nearby) +// if(M == user) + for(var/w in words) + words[w] = T.words[w] to_chat(user, "You copy the translation notes from your tome.") - flick("tome-copied",src) - - -/obj/item/weapon/tome/examine(mob/user) - ..() - if(iscultist(user)) + flick("tome-copied",src) + + +/obj/item/weapon/tome/examine(mob/user) + ..() + if(iscultist(user)) to_chat(user, "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though.") - -/obj/item/weapon/tome/cultify() - return - -/obj/item/weapon/tome/imbued //admin tome, spawns working runes without waiting - w_class = 2.0 - var/cultistsonly = 1 - attack_self(mob/user as mob) - if(src.cultistsonly && !iscultist(usr)) - return - if(!cultwords["travel"]) - runerandom() - if(user) - var/r - if (!istype(user.loc,/turf)) + +/obj/item/weapon/tome/cultify() + return + +/obj/item/weapon/tome/imbued //admin tome, spawns working runes without waiting + w_class = 2.0 + var/cultistsonly = 1 + attack_self(mob/user as mob) + if(src.cultistsonly && !iscultist(usr)) + return + if(!cultwords["travel"]) + runerandom() + if(user) + var/r + if (!istype(user.loc,/turf)) to_chat(user, "You do not have enough space to write a proper rune.") - var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun") - r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. - var/obj/effect/rune/R = new /obj/effect/rune - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - R.blood_DNA = list() - R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - switch(r) - if("teleport") - var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") - var/beacon - if(usr) - beacon = input("Select the last rune", "Rune Scribing") in words - R.word1=cultwords["travel"] - R.word2=cultwords["self"] - R.word3=beacon - R.loc = user.loc - R.check_icon() - if("itemport") - var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") - var/beacon - if(usr) - beacon = input("Select the last rune", "Rune Scribing") in words - R.word1=cultwords["travel"] - R.word2=cultwords["other"] - R.word3=beacon - R.loc = user.loc - R.check_icon() - if("tome") - R.word1=cultwords["see"] - R.word2=cultwords["blood"] - R.word3=cultwords["hell"] - R.loc = user.loc - R.check_icon() - if("armor") - R.word1=cultwords["hell"] - R.word2=cultwords["destroy"] - R.word3=cultwords["other"] - R.loc = user.loc - R.check_icon() - if("convert") - R.word1=cultwords["join"] - R.word2=cultwords["blood"] - R.word3=cultwords["self"] - R.loc = user.loc - R.check_icon() - if("tear in reality") - R.word1=cultwords["hell"] - R.word2=cultwords["join"] - R.word3=cultwords["self"] - R.loc = user.loc - R.check_icon() - if("emp") - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["technology"] - R.loc = user.loc - R.check_icon() - if("drain") - R.word1=cultwords["travel"] - R.word2=cultwords["blood"] - R.word3=cultwords["self"] - R.loc = user.loc - R.check_icon() - if("seer") - R.word1=cultwords["see"] - R.word2=cultwords["hell"] - R.word3=cultwords["join"] - R.loc = user.loc - R.check_icon() - if("raise") - R.word1=cultwords["blood"] - R.word2=cultwords["join"] - R.word3=cultwords["hell"] - R.loc = user.loc - R.check_icon() - if("obscure") - R.word1=cultwords["hide"] - R.word2=cultwords["see"] - R.word3=cultwords["blood"] - R.loc = user.loc - R.check_icon() - if("astral journey") - R.word1=cultwords["hell"] - R.word2=cultwords["travel"] - R.word3=cultwords["self"] - R.loc = user.loc - R.check_icon() - if("manifest") - R.word1=cultwords["blood"] - R.word2=cultwords["see"] - R.word3=cultwords["travel"] - R.loc = user.loc - R.check_icon() - if("imbue talisman") - R.word1=cultwords["hell"] - R.word2=cultwords["technology"] - R.word3=cultwords["join"] - R.loc = user.loc - R.check_icon() - if("sacrifice") - R.word1=cultwords["hell"] - R.word2=cultwords["blood"] - R.word3=cultwords["join"] - R.loc = user.loc - R.check_icon() - if("reveal") - R.word1=cultwords["blood"] - R.word2=cultwords["see"] - R.word3=cultwords["hide"] - R.loc = user.loc - R.check_icon() - if("wall") - R.word1=cultwords["destroy"] - R.word2=cultwords["travel"] - R.word3=cultwords["self"] - R.loc = user.loc - R.check_icon() - if("freedom") - R.word1=cultwords["travel"] - R.word2=cultwords["technology"] - R.word3=cultwords["other"] - R.loc = user.loc - R.check_icon() - if("cultsummon") - R.word1=cultwords["join"] - R.word2=cultwords["other"] - R.word3=cultwords["self"] - R.loc = user.loc - R.check_icon() - if("deafen") - R.word1=cultwords["hide"] - R.word2=cultwords["other"] - R.word3=cultwords["see"] - R.loc = user.loc - R.check_icon() - if("blind") - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["other"] - R.loc = user.loc - R.check_icon() - if("bloodboil") - R.word1=cultwords["destroy"] - R.word2=cultwords["see"] - R.word3=cultwords["blood"] - R.loc = user.loc - R.check_icon() - if("communicate") - R.word1=cultwords["self"] - R.word2=cultwords["other"] - R.word3=cultwords["technology"] - R.loc = user.loc - R.check_icon() - if("stun") - R.word1=cultwords["join"] - R.word2=cultwords["hide"] - R.word3=cultwords["technology"] - R.loc = user.loc - R.check_icon() + var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun") + r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable. + var/obj/effect/rune/R = new /obj/effect/rune + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + R.blood_DNA = list() + R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + switch(r) + if("teleport") + var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") + var/beacon + if(usr) + beacon = input("Select the last rune", "Rune Scribing") in words + R.word1=cultwords["travel"] + R.word2=cultwords["self"] + R.word3=beacon + R.loc = user.loc + R.check_icon() + if("itemport") + var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") + var/beacon + if(usr) + beacon = input("Select the last rune", "Rune Scribing") in words + R.word1=cultwords["travel"] + R.word2=cultwords["other"] + R.word3=beacon + R.loc = user.loc + R.check_icon() + if("tome") + R.word1=cultwords["see"] + R.word2=cultwords["blood"] + R.word3=cultwords["hell"] + R.loc = user.loc + R.check_icon() + if("armor") + R.word1=cultwords["hell"] + R.word2=cultwords["destroy"] + R.word3=cultwords["other"] + R.loc = user.loc + R.check_icon() + if("convert") + R.word1=cultwords["join"] + R.word2=cultwords["blood"] + R.word3=cultwords["self"] + R.loc = user.loc + R.check_icon() + if("tear in reality") + R.word1=cultwords["hell"] + R.word2=cultwords["join"] + R.word3=cultwords["self"] + R.loc = user.loc + R.check_icon() + if("emp") + R.word1=cultwords["destroy"] + R.word2=cultwords["see"] + R.word3=cultwords["technology"] + R.loc = user.loc + R.check_icon() + if("drain") + R.word1=cultwords["travel"] + R.word2=cultwords["blood"] + R.word3=cultwords["self"] + R.loc = user.loc + R.check_icon() + if("seer") + R.word1=cultwords["see"] + R.word2=cultwords["hell"] + R.word3=cultwords["join"] + R.loc = user.loc + R.check_icon() + if("raise") + R.word1=cultwords["blood"] + R.word2=cultwords["join"] + R.word3=cultwords["hell"] + R.loc = user.loc + R.check_icon() + if("obscure") + R.word1=cultwords["hide"] + R.word2=cultwords["see"] + R.word3=cultwords["blood"] + R.loc = user.loc + R.check_icon() + if("astral journey") + R.word1=cultwords["hell"] + R.word2=cultwords["travel"] + R.word3=cultwords["self"] + R.loc = user.loc + R.check_icon() + if("manifest") + R.word1=cultwords["blood"] + R.word2=cultwords["see"] + R.word3=cultwords["travel"] + R.loc = user.loc + R.check_icon() + if("imbue talisman") + R.word1=cultwords["hell"] + R.word2=cultwords["technology"] + R.word3=cultwords["join"] + R.loc = user.loc + R.check_icon() + if("sacrifice") + R.word1=cultwords["hell"] + R.word2=cultwords["blood"] + R.word3=cultwords["join"] + R.loc = user.loc + R.check_icon() + if("reveal") + R.word1=cultwords["blood"] + R.word2=cultwords["see"] + R.word3=cultwords["hide"] + R.loc = user.loc + R.check_icon() + if("wall") + R.word1=cultwords["destroy"] + R.word2=cultwords["travel"] + R.word3=cultwords["self"] + R.loc = user.loc + R.check_icon() + if("freedom") + R.word1=cultwords["travel"] + R.word2=cultwords["technology"] + R.word3=cultwords["other"] + R.loc = user.loc + R.check_icon() + if("cultsummon") + R.word1=cultwords["join"] + R.word2=cultwords["other"] + R.word3=cultwords["self"] + R.loc = user.loc + R.check_icon() + if("deafen") + R.word1=cultwords["hide"] + R.word2=cultwords["other"] + R.word3=cultwords["see"] + R.loc = user.loc + R.check_icon() + if("blind") + R.word1=cultwords["destroy"] + R.word2=cultwords["see"] + R.word3=cultwords["other"] + R.loc = user.loc + R.check_icon() + if("bloodboil") + R.word1=cultwords["destroy"] + R.word2=cultwords["see"] + R.word3=cultwords["blood"] + R.loc = user.loc + R.check_icon() + if("communicate") + R.word1=cultwords["self"] + R.word2=cultwords["other"] + R.word3=cultwords["technology"] + R.loc = user.loc + R.check_icon() + if("stun") + R.word1=cultwords["join"] + R.word2=cultwords["hide"] + R.word3=cultwords["technology"] + R.loc = user.loc + R.check_icon() diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index f64781ffa8d..077b635ee1b 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -1,240 +1,240 @@ -/obj/item/weapon/paper/talisman - icon_state = "paper_talisman" - var/imbue = null - var/uses = 0 - var/nullblock = 0 - -/obj/item/weapon/paper/talisman/examine(mob/user) - ..() - if(iscultist(user) || isobserver(user)) - switch(imbue) - if("newtome") +/obj/item/weapon/paper/talisman + icon_state = "paper_talisman" + var/imbue = null + var/uses = 0 + var/nullblock = 0 + +/obj/item/weapon/paper/talisman/examine(mob/user) + ..() + if(iscultist(user) || isobserver(user)) + switch(imbue) + if("newtome") to_chat(user, "This talisman has been imbued with the power of spawning a new Arcane Tome.") - if("armor") + if("armor") to_chat(user, "This talisman has been imbued with the power of clothing yourself in cult fighting gear.") - if("emp") + if("emp") to_chat(user, "This talisman has been imbued with the power of disabling technology in a small radius around you.") - if("conceal") + if("conceal") to_chat(user, "This talisman has been imbued with the power of concealing nearby runes.") - if("revealrunes") + if("revealrunes") to_chat(user, "This talisman has been imbued with the power of revealing hidden nearby runes.") - if("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") + if("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") to_chat(user, "This talisman has been imbued with the power of taking you to someplace else. You can read [imbue] on it.") - if("communicate") + if("communicate") to_chat(user, "This talisman has been imbued with the power of communicating your whispers to your allies.") - if("deafen") + if("deafen") to_chat(user, "This talisman has been imbued with the power of deafening visible enemies.") - if("blind") + if("blind") to_chat(user, "This talisman has been imbued with the power of blinding visible enemies.") - if("runestun") + if("runestun") to_chat(user, "This talisman has been imbued with the power of paralyzing the beings you touch with it. The effect works on silicons as well, but humans will also be muted for a short time.") - if("supply") + if("supply") to_chat(user, "This talisman has been imbued with the power of providing you and your allies with some supplies to start your cult.") - else + else to_chat(user, "This talisman.....has no particular power. Is this some kind of joke?") - else + else to_chat(user, "Something about the blood stains on this paper fills you with uneasiness.") - -/obj/item/weapon/paper/talisman/proc/findNullRod(var/atom/target) - if(istype(target,/obj/item/weapon/nullrod)) - var/turf/T = get_turf(target) - nullblock = 1 - T.turf_animation('icons/effects/96x96.dmi',"nullding",-32,-32,MOB_LAYER+1,'sound/piano/Ab7.ogg') - return 1 - else if(target.contents) - for(var/atom/A in target.contents) - findNullRod(A) - return 0 - -/obj/item/weapon/paper/talisman/New() - ..() - pixel_x=0 - pixel_y=0 - - -/obj/item/weapon/paper/talisman/attack_self(mob/living/user as mob) - if(iscultist(user)) - var/delete = 1 - switch(imbue) - if("newtome") - call(/obj/effect/rune/proc/tomesummon)() - if("armor") //Fuck off with your shit /tg/. This isn't Edgy Rev+ - call(/obj/effect/rune/proc/armor)() - if("emp") - call(/obj/effect/rune/proc/emp)(usr.loc,3) - if("conceal") - call(/obj/effect/rune/proc/obscure)(2) - if("revealrunes") - call(/obj/effect/rune/proc/revealrunes)(src) - if("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") - var/turf/T1 = get_turf(user) - call(/obj/effect/rune/proc/teleport)(imbue) - var/turf/T2 = get_turf(user) - if(T1!=T2) - T1.turf_animation('icons/effects/effects.dmi',"rune_teleport") - if("communicate") - //If the user cancels the talisman this var will be set to 0 - delete = call(/obj/effect/rune/proc/communicate)() - if("deafen") - deafen() - qdel(src) - if("blind") - blind() - qdel(src) - if("runestun") + +/obj/item/weapon/paper/talisman/proc/findNullRod(var/atom/target) + if(istype(target,/obj/item/weapon/nullrod)) + var/turf/T = get_turf(target) + nullblock = 1 + T.turf_animation('icons/effects/96x96.dmi',"nullding",-32,-32,MOB_LAYER+1,'sound/piano/Ab7.ogg') + return 1 + else if(target.contents) + for(var/atom/A in target.contents) + findNullRod(A) + return 0 + +/obj/item/weapon/paper/talisman/New() + ..() + pixel_x=0 + pixel_y=0 + + +/obj/item/weapon/paper/talisman/attack_self(mob/living/user as mob) + if(iscultist(user)) + var/delete = 1 + switch(imbue) + if("newtome") + call(/obj/effect/rune/proc/tomesummon)() + if("armor") //Fuck off with your shit /tg/. This isn't Edgy Rev+ + call(/obj/effect/rune/proc/armor)() + if("emp") + call(/obj/effect/rune/proc/emp)(usr.loc,3) + if("conceal") + call(/obj/effect/rune/proc/obscure)(2) + if("revealrunes") + call(/obj/effect/rune/proc/revealrunes)(src) + if("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri") + var/turf/T1 = get_turf(user) + call(/obj/effect/rune/proc/teleport)(imbue) + var/turf/T2 = get_turf(user) + if(T1!=T2) + T1.turf_animation('icons/effects/effects.dmi',"rune_teleport") + if("communicate") + //If the user cancels the talisman this var will be set to 0 + delete = call(/obj/effect/rune/proc/communicate)() + if("deafen") + deafen() + qdel(src) + if("blind") + blind() + qdel(src) + if("runestun") to_chat(user, "To use this talisman, attack your target directly.") - return - if("supply") - supply() - user.take_organ_damage(5, 0) - if(src && src.imbue!="supply" && src.imbue!="runestun") - if(delete) - qdel(src) - return - else + return + if("supply") + supply() + user.take_organ_damage(5, 0) + if(src && src.imbue!="supply" && src.imbue!="runestun") + if(delete) + qdel(src) + return + else to_chat(user, "You see strange symbols on the paper. Are they supposed to mean something?") - return - - -/obj/item/weapon/paper/talisman/attack(mob/living/carbon/T as mob, mob/living/user as mob) - if(iscultist(user)) - if(imbue == "runestun") - user.take_organ_damage(5, 0) - runestun(T) - qdel(src) - else - ..() ///If its some other talisman, use the generic attack code, is this supposed to work this way? - else - ..() - -/obj/item/weapon/paper/talisman/attack_animal(var/mob/living/simple_animal/M as mob) - if(istype(M, /mob/living/simple_animal/construct/harvester)) - attack_self(M) - -/obj/item/weapon/paper/talisman/proc/supply(var/key) - if (!src.uses) - qdel(src) - return - - var/dat = {"There are [src.uses] bloody runes on the parchment. -
      Please choose the chant to be imbued into the fabric of reality.
      -
      -N'ath reth sh'yro eth d'raggathnor! - Allows you to summon a new arcane tome.
      -Sas'so c'arta forbici! - Allows you to move to a rune with the same last word.
      -Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
      -Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor.
      -O bidai nabora se'sma! - Allows you to coordinate with others of your cult.
      -Fuu ma'jin - Allows you to stun a person by attacking them with the talisman.
      -Kal om neth - Summons a soul stone
      -Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person.
      "} -//Sa tatha najin - Allows you to summon armoured robes and an unholy blade
      //Kept for reference - // END AUTOFIX - usr << browse(dat, "window=id_com;size=350x200") - return - - -/obj/item/weapon/paper/talisman/Topic(href, href_list) - if(!src) return - if (usr.stat || usr.restrained() || !in_range(src, usr)) return - - if (href_list["rune"]) - switch(href_list["rune"]) - if("newtome") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.imbue = "newtome" - if("teleport") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") - T.imbue = input("Write your teleport destination rune:", "Rune Scribing") in words - if("emp") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.imbue = "emp" - if("conceal") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.imbue = "conceal" - if("communicate") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.imbue = "communicate" - if("runestun") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.imbue = "runestun" - //if("armor") - //var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - //T.imbue = "armor" - if("soulstone") - new /obj/item/device/soulstone(get_turf(usr)) - if("construct") - new /obj/structure/constructshell/cult(get_turf(usr)) - src.uses-- - supply() - return - - -/obj/item/weapon/paper/talisman/supply - imbue = "supply" - uses = 5 - - -//imbued talismans invocation for a few runes, since calling the proc causes a runtime error due to src = null -/obj/item/weapon/paper/talisman/proc/runestun(var/mob/living/T as mob)//When invoked as talisman, stun and mute the target mob. - usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!") - nullblock = 0 - for(var/turf/TU in range(T,1)) - findNullRod(TU) - if(nullblock) - usr.visible_message("[usr] invokes a talisman at [T], but they are unaffected!") - else - usr.visible_message("[usr] invokes a talisman at [T]") - - if(issilicon(T)) - T.Weaken(15) - - else if(iscarbon(T)) - var/mob/living/carbon/C = T - flick("e_flash", C.flash) - if (!(M_HULK in C.mutations)) - C.silent += 15 - C.Weaken(25) - C.Stun(25) - return - -/obj/item/weapon/paper/talisman/proc/blind() - var/affected = 0 - for(var/mob/living/carbon/C in view(2,usr)) - if (iscultist(C)) - continue - nullblock = 0 - for(var/turf/T in range(C,1)) - findNullRod(T) - if(nullblock) - continue - C.eye_blurry += 30 - C.eye_blind += 10 - //talismans is weaker. - affected++ + return + + +/obj/item/weapon/paper/talisman/attack(mob/living/carbon/T as mob, mob/living/user as mob) + if(iscultist(user)) + if(imbue == "runestun") + user.take_organ_damage(5, 0) + runestun(T) + qdel(src) + else + ..() ///If its some other talisman, use the generic attack code, is this supposed to work this way? + else + ..() + +/obj/item/weapon/paper/talisman/attack_animal(var/mob/living/simple_animal/M as mob) + if(istype(M, /mob/living/simple_animal/construct/harvester)) + attack_self(M) + +/obj/item/weapon/paper/talisman/proc/supply(var/key) + if (!src.uses) + qdel(src) + return + + var/dat = {"There are [src.uses] bloody runes on the parchment. +
      Please choose the chant to be imbued into the fabric of reality.
      +
      +N'ath reth sh'yro eth d'raggathnor! - Allows you to summon a new arcane tome.
      +Sas'so c'arta forbici! - Allows you to move to a rune with the same last word.
      +Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
      +Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor.
      +O bidai nabora se'sma! - Allows you to coordinate with others of your cult.
      +Fuu ma'jin - Allows you to stun a person by attacking them with the talisman.
      +Kal om neth - Summons a soul stone
      +Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person.
      "} +//Sa tatha najin - Allows you to summon armoured robes and an unholy blade
      //Kept for reference + // END AUTOFIX + usr << browse(dat, "window=id_com;size=350x200") + return + + +/obj/item/weapon/paper/talisman/Topic(href, href_list) + if(!src) return + if (usr.stat || usr.restrained() || !in_range(src, usr)) return + + if (href_list["rune"]) + switch(href_list["rune"]) + if("newtome") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.imbue = "newtome" + if("teleport") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") + T.imbue = input("Write your teleport destination rune:", "Rune Scribing") in words + if("emp") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.imbue = "emp" + if("conceal") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.imbue = "conceal" + if("communicate") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.imbue = "communicate" + if("runestun") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.imbue = "runestun" + //if("armor") + //var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + //T.imbue = "armor" + if("soulstone") + new /obj/item/device/soulstone(get_turf(usr)) + if("construct") + new /obj/structure/constructshell/cult(get_turf(usr)) + src.uses-- + supply() + return + + +/obj/item/weapon/paper/talisman/supply + imbue = "supply" + uses = 5 + + +//imbued talismans invocation for a few runes, since calling the proc causes a runtime error due to src = null +/obj/item/weapon/paper/talisman/proc/runestun(var/mob/living/T as mob)//When invoked as talisman, stun and mute the target mob. + usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!") + nullblock = 0 + for(var/turf/TU in range(T,1)) + findNullRod(TU) + if(nullblock) + usr.visible_message("[usr] invokes a talisman at [T], but they are unaffected!") + else + usr.visible_message("[usr] invokes a talisman at [T]") + + if(issilicon(T)) + T.Weaken(15) + + else if(iscarbon(T)) + var/mob/living/carbon/C = T + flick("e_flash", C.flash) + if (!(M_HULK in C.mutations)) + C.silent += 15 + C.Weaken(25) + C.Stun(25) + return + +/obj/item/weapon/paper/talisman/proc/blind() + var/affected = 0 + for(var/mob/living/carbon/C in view(2,usr)) + if (iscultist(C)) + continue + nullblock = 0 + for(var/turf/T in range(C,1)) + findNullRod(T) + if(nullblock) + continue + C.eye_blurry += 30 + C.eye_blind += 10 + //talismans is weaker. + affected++ to_chat(C, "You feel a sharp pain in your eyes, and the world disappears into darkness..") - if(affected) - usr.whisper("Sti[pick("'","`")] kaliesin!") + if(affected) + usr.whisper("Sti[pick("'","`")] kaliesin!") to_chat(usr, "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie.") - - -/obj/item/weapon/paper/talisman/proc/deafen() - var/affected = 0 - for(var/mob/living/carbon/C in range(7,usr)) - if (iscultist(C)) - continue - nullblock = 0 - for(var/turf/T in range(C,1)) - findNullRod(T) - if(nullblock) - continue - C.ear_deaf += 30 - //talismans is weaker. - C.show_message("\The world around you suddenly becomes quiet.") - affected++ - if(affected) - usr.whisper("Sti[pick("'","`")] kaliedir!") + + +/obj/item/weapon/paper/talisman/proc/deafen() + var/affected = 0 + for(var/mob/living/carbon/C in range(7,usr)) + if (iscultist(C)) + continue + nullblock = 0 + for(var/turf/T in range(C,1)) + findNullRod(T) + if(nullblock) + continue + C.ear_deaf += 30 + //talismans is weaker. + C.show_message("\The world around you suddenly becomes quiet.") + affected++ + if(affected) + usr.whisper("Sti[pick("'","`")] kaliedir!") to_chat(usr, "Your talisman turns into gray dust, deafening everyone around.") - for (var/mob/V in orange(1,src)) - if(!(iscultist(V))) - V.show_message("Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..") + for (var/mob/V in orange(1,src)) + if(!(iscultist(V))) + V.show_message("Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..") diff --git a/code/game/gamemodes/events/biomass.dm b/code/game/gamemodes/events/biomass.dm index 4f3e9aaf5e3..77acc2a0a66 100644 --- a/code/game/gamemodes/events/biomass.dm +++ b/code/game/gamemodes/events/biomass.dm @@ -1,207 +1,207 @@ -/** - * Biomass (note that this code is very similar to Space Vine code) - */ -/obj/effect/biomass - name = "biomass" - desc = "Space barf from another dimension. It just keeps spreading!" - icon = 'icons/obj/biomass.dmi' - icon_state = "stage1" - anchored = 1 - density = 0 - layer = 5 - pass_flags = PASSTABLE | PASSGRILLE - var/energy = 0 - var/obj/effect/biomass_controller/master = null - -/obj/effect/biomass/Destroy() - unreferenceMaster() - ..() - -/obj/effect/biomass/proc/unreferenceMaster() - if(master) - master.growth_queue -= src - master.vines -= src - master = null - -/obj/effect/biomass/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (!W || !user || !W.type) - return - - switch(W.type) //This is absolutely terrible - if(/obj/item/weapon/circular_saw) - qdel(src) - if(/obj/item/weapon/kitchen/utensil/knife) - qdel(src) - if(/obj/item/weapon/fireaxe) - qdel(src) - if(/obj/item/weapon/hatchet) - qdel(src) - if(/obj/item/weapon/melee/energy) - qdel(src) - if(/obj/item/weapon/pickaxe/plasmacutter) qdel(src) - - // less effective weapons - if(/obj/item/weapon/wirecutters) - if(prob(25)) - qdel(src) - if(/obj/item/weapon/shard) - if(prob(25)) - qdel(src) - - else // weapons with subtypes - if(istype(W, /obj/item/weapon/melee/energy/sword)) - qdel(src) - else if(istype(W, /obj/item/weapon/scalpel)) - qdel(src) - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WeldingTool = W - - if(WeldingTool.remove_fuel(0, user)) - qdel(src) - else - return - - ..() - -/obj/effect/biomass/proc/grow() - if(energy <= 0) - icon_state = "stage2" - energy = 1 - else - icon_state = "stage3" - density = 1 - energy = 2 - -/obj/effect/biomass/proc/spread() - var/location = get_step_rand(src) - - if(istype(location, /turf/simulated/floor)) - var/turf/simulated/floor/Floor = location - - if(isnull(locate(/obj/effect/biomass) in Floor)) - if(Floor.Enter(src, loc)) - if(master) - master.spawn_biomass_piece(Floor) - return 1 - return 0 - -/obj/effect/biomass/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - if(prob(90)) - qdel(src) - if(3.0) - if(prob(50)) - qdel(src) - -/obj/effect/biomass/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) //hotspots kill biomass - qdel(src) - -/obj/effect/biomass_controller - invisibility = 60 // ghost only - - var/list/obj/effect/biomass/vines = new - var/list/growth_queue = new - - // what this does is that instead of having the grow minimum of 1, - // required to start growing, the minimum will be 0, - // meaning if you get the biomasssss..s' size to something less than 20 plots, - // it won't grow anymore. - var/reached_collapse_size = FALSE - var/reached_slowdown_size = FALSE - -/obj/effect/biomass_controller/New(loc) - ..(loc) - - if(!istype(loc, /turf/simulated/floor)) - qdel(src) - - spawn_biomass_piece(loc) - processing_objects += src - -/obj/effect/biomass_controller/Destroy() // controller is kill, no!!!111 - if(vines && vines.len > 0) - for(var/obj/effect/biomass/Biomass in vines) - Biomass.unreferenceMaster() - - processing_objects -= src - ..() - -/obj/effect/biomass_controller/proc/spawn_biomass_piece(var/turf/location) - var/obj/effect/biomass/Biomass = new(location) - Biomass.master = src - vines += Biomass - growth_queue += Biomass - -/obj/effect/biomass_controller/process() - if(isnull(vines) || vines.len == 0) // sanity and existing biomass check - qdel(src) - return - - if(isnull(growth_queue)) // sanity check - qdel(src) - return - - if(vines.len >= 250 && !reached_collapse_size) - reached_collapse_size = TRUE - - if(vines.len >= 30 && !reached_slowdown_size) - reached_slowdown_size = TRUE - - var/maxgrowth = 0 - - if(reached_collapse_size) - maxgrowth = 0 - else if(reached_slowdown_size) - if(prob(25)) - maxgrowth = 1 - else - maxgrowth = 0 - else - maxgrowth = 4 - - var/length = min(30, vines.len / 5) - var/i = 0 - var/growth = 0 - var/list/obj/effect/biomass/queue_end = new - - for(var/obj/effect/biomass/Biomass in growth_queue) - i++ - growth_queue -= Biomass - queue_end += Biomass - - if(Biomass.energy < 2) // if biomass isn't fully grown - if(prob(20)) - Biomass.grow() - - if(Biomass.spread()) - growth++ - - if(growth >= maxgrowth) - break - - if(i >= length) - break - - growth_queue = growth_queue + queue_end - -/proc/biomass_infestation() - set waitfor = 0 - - // list of all the empty floor turfs in the hallway areas - var/list/turf/simulated/floor/Floors = new - - for(var/type in typesof(/area/hallway)) - var/area/Hallway = locate(type) - - for(var/turf/simulated/floor/Floor in Hallway.contents) - if(!is_blocked_turf(Floor)) - Floors += Floor - - if(Floors.len) // pick a floor to spawn at - var/turf/simulated/floor/Floor = pick(Floors) - new/obj/effect/biomass_controller(Floor) // spawn a controller at floor - log_admin("Event: Biomass spawned at [Floor.loc] ([Floor.x],[Floor.y],[Floor.z]).") +/** + * Biomass (note that this code is very similar to Space Vine code) + */ +/obj/effect/biomass + name = "biomass" + desc = "Space barf from another dimension. It just keeps spreading!" + icon = 'icons/obj/biomass.dmi' + icon_state = "stage1" + anchored = 1 + density = 0 + layer = 5 + pass_flags = PASSTABLE | PASSGRILLE + var/energy = 0 + var/obj/effect/biomass_controller/master = null + +/obj/effect/biomass/Destroy() + unreferenceMaster() + ..() + +/obj/effect/biomass/proc/unreferenceMaster() + if(master) + master.growth_queue -= src + master.vines -= src + master = null + +/obj/effect/biomass/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (!W || !user || !W.type) + return + + switch(W.type) //This is absolutely terrible + if(/obj/item/weapon/circular_saw) + qdel(src) + if(/obj/item/weapon/kitchen/utensil/knife) + qdel(src) + if(/obj/item/weapon/fireaxe) + qdel(src) + if(/obj/item/weapon/hatchet) + qdel(src) + if(/obj/item/weapon/melee/energy) + qdel(src) + if(/obj/item/weapon/pickaxe/plasmacutter) qdel(src) + + // less effective weapons + if(/obj/item/weapon/wirecutters) + if(prob(25)) + qdel(src) + if(/obj/item/weapon/shard) + if(prob(25)) + qdel(src) + + else // weapons with subtypes + if(istype(W, /obj/item/weapon/melee/energy/sword)) + qdel(src) + else if(istype(W, /obj/item/weapon/scalpel)) + qdel(src) + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WeldingTool = W + + if(WeldingTool.remove_fuel(0, user)) + qdel(src) + else + return + + ..() + +/obj/effect/biomass/proc/grow() + if(energy <= 0) + icon_state = "stage2" + energy = 1 + else + icon_state = "stage3" + density = 1 + energy = 2 + +/obj/effect/biomass/proc/spread() + var/location = get_step_rand(src) + + if(istype(location, /turf/simulated/floor)) + var/turf/simulated/floor/Floor = location + + if(isnull(locate(/obj/effect/biomass) in Floor)) + if(Floor.Enter(src, loc)) + if(master) + master.spawn_biomass_piece(Floor) + return 1 + return 0 + +/obj/effect/biomass/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + if(prob(90)) + qdel(src) + if(3.0) + if(prob(50)) + qdel(src) + +/obj/effect/biomass/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) //hotspots kill biomass + qdel(src) + +/obj/effect/biomass_controller + invisibility = 60 // ghost only + + var/list/obj/effect/biomass/vines = new + var/list/growth_queue = new + + // what this does is that instead of having the grow minimum of 1, + // required to start growing, the minimum will be 0, + // meaning if you get the biomasssss..s' size to something less than 20 plots, + // it won't grow anymore. + var/reached_collapse_size = FALSE + var/reached_slowdown_size = FALSE + +/obj/effect/biomass_controller/New(loc) + ..(loc) + + if(!istype(loc, /turf/simulated/floor)) + qdel(src) + + spawn_biomass_piece(loc) + processing_objects += src + +/obj/effect/biomass_controller/Destroy() // controller is kill, no!!!111 + if(vines && vines.len > 0) + for(var/obj/effect/biomass/Biomass in vines) + Biomass.unreferenceMaster() + + processing_objects -= src + ..() + +/obj/effect/biomass_controller/proc/spawn_biomass_piece(var/turf/location) + var/obj/effect/biomass/Biomass = new(location) + Biomass.master = src + vines += Biomass + growth_queue += Biomass + +/obj/effect/biomass_controller/process() + if(isnull(vines) || vines.len == 0) // sanity and existing biomass check + qdel(src) + return + + if(isnull(growth_queue)) // sanity check + qdel(src) + return + + if(vines.len >= 250 && !reached_collapse_size) + reached_collapse_size = TRUE + + if(vines.len >= 30 && !reached_slowdown_size) + reached_slowdown_size = TRUE + + var/maxgrowth = 0 + + if(reached_collapse_size) + maxgrowth = 0 + else if(reached_slowdown_size) + if(prob(25)) + maxgrowth = 1 + else + maxgrowth = 0 + else + maxgrowth = 4 + + var/length = min(30, vines.len / 5) + var/i = 0 + var/growth = 0 + var/list/obj/effect/biomass/queue_end = new + + for(var/obj/effect/biomass/Biomass in growth_queue) + i++ + growth_queue -= Biomass + queue_end += Biomass + + if(Biomass.energy < 2) // if biomass isn't fully grown + if(prob(20)) + Biomass.grow() + + if(Biomass.spread()) + growth++ + + if(growth >= maxgrowth) + break + + if(i >= length) + break + + growth_queue = growth_queue + queue_end + +/proc/biomass_infestation() + set waitfor = 0 + + // list of all the empty floor turfs in the hallway areas + var/list/turf/simulated/floor/Floors = new + + for(var/type in typesof(/area/hallway)) + var/area/Hallway = locate(type) + + for(var/turf/simulated/floor/Floor in Hallway.contents) + if(!is_blocked_turf(Floor)) + Floors += Floor + + if(Floors.len) // pick a floor to spawn at + var/turf/simulated/floor/Floor = pick(Floors) + new/obj/effect/biomass_controller(Floor) // spawn a controller at floor + log_admin("Event: Biomass spawned at [Floor.loc] ([Floor.x],[Floor.y],[Floor.z]).") message_admins("Event: Biomass spawned at [Floor.loc] (JMP)") \ No newline at end of file diff --git a/code/game/gamemodes/events/holidays/Christmas.dm b/code/game/gamemodes/events/holidays/Christmas.dm index 85e4d12bc8c..209672184bc 100644 --- a/code/game/gamemodes/events/holidays/Christmas.dm +++ b/code/game/gamemodes/events/holidays/Christmas.dm @@ -1,52 +1,52 @@ -/proc/Christmas_Game_Start() - for(var/obj/structure/flora/tree/pine/xmas in world) - if(xmas.z != 1) continue - for(var/turf/simulated/floor/T in orange(1,xmas)) - for(var/i=1,i<=rand(1,5),i++) - new /obj/item/weapon/winter_gift/regular(T) - for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) - Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) - -/proc/ChristmasEvent() - for(var/obj/structure/flora/tree/pine/xmas in world) - var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc) - evil_tree.icon_state = xmas.icon_state - evil_tree.icon_living = evil_tree.icon_state - evil_tree.icon_dead = evil_tree.icon_state - evil_tree.icon_gib = evil_tree.icon_state - qdel(xmas) - xmas = null - -/obj/item/weapon/toy/xmas_cracker - name = "xmas cracker" - icon = 'icons/obj/christmas.dmi' - icon_state = "cracker" - desc = "Directions for use: Requires two people, one to pull each end." - var/cracked = 0 - -/obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user) - if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() ) - target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a *pop*.") - var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc) - Joke.name = "[pick("awful","terrible","unfunny")] joke" - Joke.info = pick("What did one snowman say to the other?\n\n'Is it me or can you smell carrots?'", - "Why couldn't the snowman get laid?\n\nHe was frigid!", - "Where are santa's helpers educated?\n\nNowhere, they're ELF-taught.", - "What happened to the man who stole advent calanders?\n\nHe got 25 days.", - "What does Santa get when he gets stuck in a chimney?\n\nClaus-trophobia.", - "Where do you find chili beans?\n\nThe north pole.", - "What do you get from eating tree decorations?\n\nTinsilitis!", - "What do snowmen wear on their heads?\n\nIce caps!", - "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.", - "Why doesn't Santa have any children?\n\nBecause he only comes down the chimney.") - new /obj/item/clothing/head/festive(target.loc) - user.update_icons() - cracked = 1 - icon_state = "cracker1" - var/obj/item/weapon/toy/xmas_cracker/other_half = new /obj/item/weapon/toy/xmas_cracker(target) - other_half.cracked = 1 - other_half.icon_state = "cracker2" - target.put_in_active_hand(other_half) - playsound(user, 'sound/effects/snap.ogg', 50, 1) - return 1 +/proc/Christmas_Game_Start() + for(var/obj/structure/flora/tree/pine/xmas in world) + if(xmas.z != 1) continue + for(var/turf/simulated/floor/T in orange(1,xmas)) + for(var/i=1,i<=rand(1,5),i++) + new /obj/item/weapon/winter_gift/regular(T) + for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) + Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) + +/proc/ChristmasEvent() + for(var/obj/structure/flora/tree/pine/xmas in world) + var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc) + evil_tree.icon_state = xmas.icon_state + evil_tree.icon_living = evil_tree.icon_state + evil_tree.icon_dead = evil_tree.icon_state + evil_tree.icon_gib = evil_tree.icon_state + qdel(xmas) + xmas = null + +/obj/item/weapon/toy/xmas_cracker + name = "xmas cracker" + icon = 'icons/obj/christmas.dmi' + icon_state = "cracker" + desc = "Directions for use: Requires two people, one to pull each end." + var/cracked = 0 + +/obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user) + if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() ) + target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a *pop*.") + var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc) + Joke.name = "[pick("awful","terrible","unfunny")] joke" + Joke.info = pick("What did one snowman say to the other?\n\n'Is it me or can you smell carrots?'", + "Why couldn't the snowman get laid?\n\nHe was frigid!", + "Where are santa's helpers educated?\n\nNowhere, they're ELF-taught.", + "What happened to the man who stole advent calanders?\n\nHe got 25 days.", + "What does Santa get when he gets stuck in a chimney?\n\nClaus-trophobia.", + "Where do you find chili beans?\n\nThe north pole.", + "What do you get from eating tree decorations?\n\nTinsilitis!", + "What do snowmen wear on their heads?\n\nIce caps!", + "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.", + "Why doesn't Santa have any children?\n\nBecause he only comes down the chimney.") + new /obj/item/clothing/head/festive(target.loc) + user.update_icons() + cracked = 1 + icon_state = "cracker1" + var/obj/item/weapon/toy/xmas_cracker/other_half = new /obj/item/weapon/toy/xmas_cracker(target) + other_half.cracked = 1 + other_half.icon_state = "cracker2" + target.put_in_active_hand(other_half) + playsound(user, 'sound/effects/snap.ogg', 50, 1) + return 1 return ..() \ No newline at end of file diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm index 4a09e194c2f..c04b6c7f945 100644 --- a/code/game/gamemodes/events/holidays/Holidays.dm +++ b/code/game/gamemodes/events/holidays/Holidays.dm @@ -1,228 +1,228 @@ -//Uncommenting ALLOW_HOLIDAYS in config.txt will enable Holidays -var/global/Holiday = null - -//Just thinking ahead! Here's the foundations to a more robust Holiday event system. -//It's easy as hell to add stuff. Just set Holiday to something using the switch (or something else) -//then use if(Holiday == "MyHoliday") to make stuff happen on that specific day only -//Please, Don't spam stuff up with easter eggs, I'd rather somebody just delete this than people cause -//the game to lag even more in the name of one-day content. - -////////////////////////////////////////////////////////////////////////////////////////////////////////// -//ALSO, MOST IMPORTANTLY: Don't add stupid stuff! Discuss bonus content with Project-Heads first please!// -////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ~Carn - -// sets up the Holiday global variable. Shouldbe called on game configuration or something. -/proc/Get_Holiday() - if(!Holiday) // Holiday stuff was not enabled in the config! - return - - Holiday = null // reset our switch now so we can recycle it as our Holiday name - - var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year - var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month - var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day - - // Main switch. If any of these are too dumb/inappropriate, or you have better ones, feel free to change whatever - switch(MM) - if(1) // Jan - switch(DD) - if(1) - Holiday = "New Year's Day" - - if(2) // Feb - switch(DD) - if(2) - Holiday = "Groundhog Day" - if(14) - Holiday = "Valentine's Day" - if(17) - Holiday = "Random Acts of Kindness Day" - - if(3) // Mar - switch(DD) - if(14) - Holiday = "Pi Day" - if(17) - Holiday = "St. Patrick's Day" - if(27) - if(YY == 16) - Holiday = "Easter" - if(31) - if(YY == 13) - Holiday = "Easter" - - if(4) // Apr - switch(DD) - if(1) - Holiday = "April Fool's Day" - if(YY == 18 && prob(50)) - Holiday = "Easter" - if(2) - Holiday = "Autism Awareness Day" - if(5) - if(YY == 15) - Holiday = "Easter" - if(16) - if(YY == 17) - Holiday = "Easter" - if(20) - Holiday = "Four-Twenty" - if(YY == 14 && prob(50)) - Holiday = "Easter" - if(22) - Holiday = "Earth Day" - - if(5) // May - switch(DD) - if(1) - Holiday = "Labour Day" - if(4) - Holiday = "FireFighter's Day" - if(12) - Holiday = "Owl and Pussycat Day" // what a dumb day of observence...but we -do- have costumes already :3 - - if(6) // Jun - switch(DD) - if(18) - Holiday = "International Picnic Day" - if(21) - Holiday = "Summer Solstice" // its not always the 21 but sue me - - if(7) // Jul - switch(DD) - if(1) - Holiday = "Doctor's Day" - if(2) - Holiday = "UFO Day" - if(8) - Holiday = "Writer's Day" - if(30) - Holiday = "Friendship Day" - - if(8) // Aug - switch(DD) - if(5) - Holiday = "Beer Day" - - if(9) // sep - switch(DD) - if(19) - Holiday = "Talk-Like-a-Pirate Day" - if(28) - Holiday = "Stupid-Questions Day" - - if(10) // Oct - switch(DD) - if(4) - Holiday = "Animal's Day" - if(7) - Holiday = "Smiling Day" - if(16) - Holiday = "Boss' Day" - if(31) - Holiday = "Halloween" - - if(11) // Nov - switch(DD) - if(1) - Holiday = "Vegan Day" - if(13) - Holiday = "Kindness Day" - if(19) - Holiday = "Flowers Day" - if(21) - Holiday = "Saying-'Hello' Day" - - if(12) // Dec - switch(DD) - if(10) - Holiday = "Human-Rights Day" - if(14) - Holiday = "Monkey Day" - if(21) - if(YY==12) - Holiday = "End of the World" - if(22) - Holiday = "Orgasming Day" //lol. These all actually exist - if(24) - Holiday = "Christmas Eve" - if(25) - Holiday = "Christmas" - if(26) - Holiday = "Boxing Day" - if(31) - Holiday = "New Year's Eve" - if(!Holiday) - // Friday the 13th - if(DD == 13) - if(time2text(world.timeofday, "DDD") == "Fri") - Holiday = "Friday the 13th" - -//Allows GA and GM to set the Holiday variable -/client/proc/Set_Holiday(T as text|null) - set name = ".Set Holiday" - set category = "Fun" - set desc = "Force-set the Holiday variable to make the game think it's a certain day." - if(!check_rights(R_SERVER)) - return - - Holiday = T - //get a new station name - station_name = null - station_name() - //update our hub status - world.update_status() - Holiday_Game_Start() - - message_admins("ADMIN: Event: [key_name(src)] force-set Holiday to \"[Holiday]\"") - log_admin("[key_name(src)] force-set Holiday to \"[Holiday]\"") - - -// Run at the start of a round -/proc/Holiday_Game_Start() - if(Holiday) - to_chat(world, "and...") - if(Holiday == "Autism Awareness Day") - to_chat(world, "

      Happy Autism Awareness Day Everybody!

      ")// Together we can finish the puzzle. +//Uncommenting ALLOW_HOLIDAYS in config.txt will enable Holidays +var/global/Holiday = null - else +//Just thinking ahead! Here's the foundations to a more robust Holiday event system. +//It's easy as hell to add stuff. Just set Holiday to something using the switch (or something else) +//then use if(Holiday == "MyHoliday") to make stuff happen on that specific day only +//Please, Don't spam stuff up with easter eggs, I'd rather somebody just delete this than people cause +//the game to lag even more in the name of one-day content. + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//ALSO, MOST IMPORTANTLY: Don't add stupid stuff! Discuss bonus content with Project-Heads first please!// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ~Carn + +// sets up the Holiday global variable. Shouldbe called on game configuration or something. +/proc/Get_Holiday() + if(!Holiday) // Holiday stuff was not enabled in the config! + return + + Holiday = null // reset our switch now so we can recycle it as our Holiday name + + var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year + var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month + var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day + + // Main switch. If any of these are too dumb/inappropriate, or you have better ones, feel free to change whatever + switch(MM) + if(1) // Jan + switch(DD) + if(1) + Holiday = "New Year's Day" + + if(2) // Feb + switch(DD) + if(2) + Holiday = "Groundhog Day" + if(14) + Holiday = "Valentine's Day" + if(17) + Holiday = "Random Acts of Kindness Day" + + if(3) // Mar + switch(DD) + if(14) + Holiday = "Pi Day" + if(17) + Holiday = "St. Patrick's Day" + if(27) + if(YY == 16) + Holiday = "Easter" + if(31) + if(YY == 13) + Holiday = "Easter" + + if(4) // Apr + switch(DD) + if(1) + Holiday = "April Fool's Day" + if(YY == 18 && prob(50)) + Holiday = "Easter" + if(2) + Holiday = "Autism Awareness Day" + if(5) + if(YY == 15) + Holiday = "Easter" + if(16) + if(YY == 17) + Holiday = "Easter" + if(20) + Holiday = "Four-Twenty" + if(YY == 14 && prob(50)) + Holiday = "Easter" + if(22) + Holiday = "Earth Day" + + if(5) // May + switch(DD) + if(1) + Holiday = "Labour Day" + if(4) + Holiday = "FireFighter's Day" + if(12) + Holiday = "Owl and Pussycat Day" // what a dumb day of observence...but we -do- have costumes already :3 + + if(6) // Jun + switch(DD) + if(18) + Holiday = "International Picnic Day" + if(21) + Holiday = "Summer Solstice" // its not always the 21 but sue me + + if(7) // Jul + switch(DD) + if(1) + Holiday = "Doctor's Day" + if(2) + Holiday = "UFO Day" + if(8) + Holiday = "Writer's Day" + if(30) + Holiday = "Friendship Day" + + if(8) // Aug + switch(DD) + if(5) + Holiday = "Beer Day" + + if(9) // sep + switch(DD) + if(19) + Holiday = "Talk-Like-a-Pirate Day" + if(28) + Holiday = "Stupid-Questions Day" + + if(10) // Oct + switch(DD) + if(4) + Holiday = "Animal's Day" + if(7) + Holiday = "Smiling Day" + if(16) + Holiday = "Boss' Day" + if(31) + Holiday = "Halloween" + + if(11) // Nov + switch(DD) + if(1) + Holiday = "Vegan Day" + if(13) + Holiday = "Kindness Day" + if(19) + Holiday = "Flowers Day" + if(21) + Holiday = "Saying-'Hello' Day" + + if(12) // Dec + switch(DD) + if(10) + Holiday = "Human-Rights Day" + if(14) + Holiday = "Monkey Day" + if(21) + if(YY==12) + Holiday = "End of the World" + if(22) + Holiday = "Orgasming Day" //lol. These all actually exist + if(24) + Holiday = "Christmas Eve" + if(25) + Holiday = "Christmas" + if(26) + Holiday = "Boxing Day" + if(31) + Holiday = "New Year's Eve" + if(!Holiday) + // Friday the 13th + if(DD == 13) + if(time2text(world.timeofday, "DDD") == "Fri") + Holiday = "Friday the 13th" + +//Allows GA and GM to set the Holiday variable +/client/proc/Set_Holiday(T as text|null) + set name = ".Set Holiday" + set category = "Fun" + set desc = "Force-set the Holiday variable to make the game think it's a certain day." + if(!check_rights(R_SERVER)) + return + + Holiday = T + //get a new station name + station_name = null + station_name() + //update our hub status + world.update_status() + Holiday_Game_Start() + + message_admins("ADMIN: Event: [key_name(src)] force-set Holiday to \"[Holiday]\"") + log_admin("[key_name(src)] force-set Holiday to \"[Holiday]\"") + + +// Run at the start of a round +/proc/Holiday_Game_Start() + if(Holiday) + to_chat(world, "and...") + if(Holiday == "Autism Awareness Day") + to_chat(world, "

      Happy Autism Awareness Day Everybody!

      ")// Together we can finish the puzzle. + + else to_chat(world, "

      Happy [Holiday] Everybody!

      ") - switch(Holiday) // special holidays - if("Easter") - //do easter stuff - if("Christmas Eve","Christmas") - Christmas_Game_Start() - return - -// Nested in the random events loop. Will be triggered every 2 minutes -/proc/Holiday_Random_Event() - switch(Holiday) // special holidays - if("",null) // no Holiday today! Back to work! - return - - if("Easter") // I'll make this into some helper procs at some point - -/* var/list/turf/simulated/floor/Floorlist = list() - for(var/turf/simulated/floor/T) - if(T.contents) - Floorlist += T - var/turf/simulated/floor/F = Floorlist[rand(1,Floorlist.len)] - Floorlist = null - var/obj/structure/closet/C = locate(/obj/structure/closet) in F - var/obj/item/weapon/reagent_containers/food/snacks/chocolateegg/wrapped/Egg - if( C ) Egg = new(C) - else Egg = new(F) - - var/list/obj/containers = list() - for(var/obj/item/weapon/storage/S in world) - if(S.z != 1) continue - containers += S - - message_admins("DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ - - if("End of the World") - if(prob(eventchance)) GameOver() - - if("Christmas","Christmas Eve") - if(prob(eventchance)) ChristmasEvent() + switch(Holiday) // special holidays + if("Easter") + //do easter stuff + if("Christmas Eve","Christmas") + Christmas_Game_Start() + return + +// Nested in the random events loop. Will be triggered every 2 minutes +/proc/Holiday_Random_Event() + switch(Holiday) // special holidays + if("",null) // no Holiday today! Back to work! + return + + if("Easter") // I'll make this into some helper procs at some point + +/* var/list/turf/simulated/floor/Floorlist = list() + for(var/turf/simulated/floor/T) + if(T.contents) + Floorlist += T + var/turf/simulated/floor/F = Floorlist[rand(1,Floorlist.len)] + Floorlist = null + var/obj/structure/closet/C = locate(/obj/structure/closet) in F + var/obj/item/weapon/reagent_containers/food/snacks/chocolateegg/wrapped/Egg + if( C ) Egg = new(C) + else Egg = new(F) + + var/list/obj/containers = list() + for(var/obj/item/weapon/storage/S in world) + if(S.z != 1) continue + containers += S + + message_admins("DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ + + if("End of the World") + if(prob(eventchance)) GameOver() + + if("Christmas","Christmas Eve") + if(prob(eventchance)) ChristmasEvent() diff --git a/code/game/gamemodes/events/holidays/Other.dm b/code/game/gamemodes/events/holidays/Other.dm index 74b47506aaf..bd64fda833f 100644 --- a/code/game/gamemodes/events/holidays/Other.dm +++ b/code/game/gamemodes/events/holidays/Other.dm @@ -1,10 +1,10 @@ -/proc/GameOver() - if(!hadevent) - hadevent = 1 - message_admins("The apocalypse has begun! (this holiday event can be disabled by toggling events off within 60 seconds)") - spawn(600) - if(!config.allow_random_events) return - Show2Group4Delay(ScreenText(null,"
      GAME OVER
      "),null,150) - for(var/i=1,i<=4,i++) - spawn_dynamic_event() +/proc/GameOver() + if(!hadevent) + hadevent = 1 + message_admins("The apocalypse has begun! (this holiday event can be disabled by toggling events off within 60 seconds)") + spawn(600) + if(!config.allow_random_events) return + Show2Group4Delay(ScreenText(null,"
      GAME OVER
      "),null,150) + for(var/i=1,i<=4,i++) + spawn_dynamic_event() sleep(50) \ No newline at end of file diff --git a/code/game/gamemodes/events/spacevines.dm b/code/game/gamemodes/events/spacevines.dm index 86ec8b4acb4..49a5fb44ae5 100644 --- a/code/game/gamemodes/events/spacevines.dm +++ b/code/game/gamemodes/events/spacevines.dm @@ -1,23 +1,23 @@ -//Carn: Spacevines random event. -/proc/spacevine_infestation(var/potency_min=70, var/potency_max=100, var/maturation_min=2, var/maturation_max=6) - spawn() //to stop the secrets panel hanging - var/list/turf/simulated/floor/turfs = list() //list of all the empty floor turfs in the hallway areas - for(var/areapath in typesof(/area/hallway)) - var/area/A = locate(areapath) - for(var/turf/simulated/floor/F in A.contents) - if(!is_blocked_turf(F)) - turfs += F - - if(turfs.len) //Pick a turf to spawn at if we can - var/turf/simulated/floor/T = pick(turfs) - var/datum/seed/seed = plant_controller.create_random_seed(1) - seed.spread = 2 // So it will function properly as vines. - seed.potency = rand(potency_min, potency_max) // 70-100 potency will help guarantee a wide spread and powerful effects. - seed.maturation = rand(maturation_min, maturation_max) - - var/obj/effect/plantsegment/vine = new(T,seed,start_fully_mature = 1) - vine.process() - - message_admins("Event: Spacevines spawned at [T.loc] (JMP)") - return +//Carn: Spacevines random event. +/proc/spacevine_infestation(var/potency_min=70, var/potency_max=100, var/maturation_min=2, var/maturation_max=6) + spawn() //to stop the secrets panel hanging + var/list/turf/simulated/floor/turfs = list() //list of all the empty floor turfs in the hallway areas + for(var/areapath in typesof(/area/hallway)) + var/area/A = locate(areapath) + for(var/turf/simulated/floor/F in A.contents) + if(!is_blocked_turf(F)) + turfs += F + + if(turfs.len) //Pick a turf to spawn at if we can + var/turf/simulated/floor/T = pick(turfs) + var/datum/seed/seed = plant_controller.create_random_seed(1) + seed.spread = 2 // So it will function properly as vines. + seed.potency = rand(potency_min, potency_max) // 70-100 potency will help guarantee a wide spread and powerful effects. + seed.maturation = rand(maturation_min, maturation_max) + + var/obj/effect/plantsegment/vine = new(T,seed,start_fully_mature = 1) + vine.process() + + message_admins("Event: Spacevines spawned at [T.loc] (JMP)") + return message_admins("Event: Spacevines failed to find a viable turf.") \ No newline at end of file diff --git a/code/game/gamemodes/events/wormholes.dm b/code/game/gamemodes/events/wormholes.dm index a3ff1bce99d..2ab408c1f4a 100644 --- a/code/game/gamemodes/events/wormholes.dm +++ b/code/game/gamemodes/events/wormholes.dm @@ -1,63 +1,63 @@ -/proc/wormhole_event() - spawn() - var/list/pick_turfs = list() - for(var/turf/simulated/floor/T in turfs) - if(T.z == 1) - pick_turfs += T - - if(pick_turfs.len) - //All ready. Announce that bad juju is afoot. - command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player) && M.client) +/proc/wormhole_event() + spawn() + var/list/pick_turfs = list() + for(var/turf/simulated/floor/T in turfs) + if(T.z == 1) + pick_turfs += T + + if(pick_turfs.len) + //All ready. Announce that bad juju is afoot. + command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && M.client) M << sound('sound/AI/spanomalies.ogg') - - //prob(20) can be approximated to 1 wormhole every 5 turfs! - //admittedly less random but totally worth it >_< - var/event_duration = 3000 //~5 minutes in ticks - var/number_of_selections = (pick_turfs.len/5)+1 //+1 to avoid division by zero! - var/sleep_duration = round( event_duration / number_of_selections ) - var/end_time = world.time + event_duration //the time by which the event should have ended - - var/increment = max(1,round(number_of_selections/50)) + + //prob(20) can be approximated to 1 wormhole every 5 turfs! + //admittedly less random but totally worth it >_< + var/event_duration = 3000 //~5 minutes in ticks + var/number_of_selections = (pick_turfs.len/5)+1 //+1 to avoid division by zero! + var/sleep_duration = round( event_duration / number_of_selections ) + var/end_time = world.time + event_duration //the time by which the event should have ended + + var/increment = max(1,round(number_of_selections/50)) // to_chat(world, "DEBUG: number_of_selections: [number_of_selections] | sleep_duration: [sleep_duration]") - - var/i = 1 - while( 1 ) - - //we've run into overtime. End the event - if( end_time < world.time ) + + var/i = 1 + while( 1 ) + + //we've run into overtime. End the event + if( end_time < world.time ) // to_chat(world, "DEBUG: we've run into overtime. End the event") - return - if( !pick_turfs.len ) + return + if( !pick_turfs.len ) // to_chat(world, "DEBUG: we've run out of turfs to pick. End the event") - return - - //loop it round - i += increment - i %= pick_turfs.len - i++ - - //get our enter and exit locations - var/turf/simulated/floor/enter = pick_turfs[i] - pick_turfs -= enter //remove it from pickable turfs list - if( !enter || !istype(enter) ) continue //sanity - - var/turf/simulated/floor/exit = pick(pick_turfs) - pick_turfs -= exit - if( !exit || !istype(exit) ) continue //sanity - - create_wormhole(enter,exit) - - sleep(sleep_duration) //have a well deserved nap! - - -//maybe this proc can even be used as an admin tool for teleporting players without ruining immulsions? -/proc/create_wormhole(var/turf/enter as turf, var/turf/exit as turf) - var/obj/effect/portal/P = new /obj/effect/portal( enter ) - P.target = exit - P.icon = 'icons/obj/objects.dmi' - P.icon_state = "anom" - P.name = "wormhole" - spawn(rand(300,600)) //This isn't useful, the new in hand tele will likely override it - qdel(P) + return + + //loop it round + i += increment + i %= pick_turfs.len + i++ + + //get our enter and exit locations + var/turf/simulated/floor/enter = pick_turfs[i] + pick_turfs -= enter //remove it from pickable turfs list + if( !enter || !istype(enter) ) continue //sanity + + var/turf/simulated/floor/exit = pick(pick_turfs) + pick_turfs -= exit + if( !exit || !istype(exit) ) continue //sanity + + create_wormhole(enter,exit) + + sleep(sleep_duration) //have a well deserved nap! + + +//maybe this proc can even be used as an admin tool for teleporting players without ruining immulsions? +/proc/create_wormhole(var/turf/enter as turf, var/turf/exit as turf) + var/obj/effect/portal/P = new /obj/effect/portal( enter ) + P.target = exit + P.icon = 'icons/obj/objects.dmi' + P.icon_state = "anom" + P.name = "wormhole" + spawn(rand(300,600)) //This isn't useful, the new in hand tele will likely override it + qdel(P) diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index 04fb4953bef..964fe3826f8 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -1,24 +1,24 @@ -/datum/game_mode/extended - name = "extended" - config_tag = "extended" - required_players = 0 - - uplink_welcome = "Syndicate Uplink Console:" - uplink_uses = 10 - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 - -/datum/game_mode/announce() +/datum/game_mode/extended + name = "extended" + config_tag = "extended" + required_players = 0 + + uplink_welcome = "Syndicate Uplink Console:" + uplink_uses = 10 + + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 + +/datum/game_mode/announce() to_chat(world, "The current game mode is - Extended Role-Playing!") to_chat(world, "Just have fun and role-play!") - -/datum/game_mode/extended/pre_setup() - log_admin("Starting a round of extended.") - message_admins("Starting a round of extended.") - return 1 - -/datum/game_mode/extended/post_setup() - spawn (rand(waittime_l, waittime_h)) // To reduce extended meta. - if(!mixed) send_intercept() + +/datum/game_mode/extended/pre_setup() + log_admin("Starting a round of extended.") + message_admins("Starting a round of extended.") + return 1 + +/datum/game_mode/extended/post_setup() + spawn (rand(waittime_l, waittime_h)) // To reduce extended meta. + if(!mixed) send_intercept() ..() \ No newline at end of file diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e1a76ac91b9..7fe71e8fafc 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -1,525 +1,525 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/* - * GAMEMODES (by Rastaf0) - * - * In the new mode system all special roles are fully supported. - * You can have proper wizards/traitors/changelings/cultists during any mode. - * Only two things really depends on gamemode: - * 1. Starting roles, equipment and preparations - * 2. Conditions of finishing the round. - * - */ - - -/datum/game_mode - var/name = "invalid" - var/config_tag = null - var/intercept_hacked = 0 - var/votable = 1 - var/probability = 1 - var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm - 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 traitors - 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 - var/recommended_enemies = 0 - var/newscaster_announcements = null - var/uplink_welcome = "Syndicate Uplink Console:" - var/uplink_uses = 10 - var/mixed = 0 // denotes whether its apart of a mixed mode or not - var/list/datum/mind/necromancer = list() //Those who use a necromancy staff OR soulstone a shade/construct - var/list/datum/mind/risen = list() // Those risen by necromancy or soulstone - var/eldergod = 1 // Can cultists spawn Nar-Sie? (Set to 0 on cascade or narsie spawn) - var/completion_text = "" - - var/list/datum/mind/deathsquad = list() - var/list/datum/mind/ert = list() - var/rage = 0 - -/datum/game_mode/proc/announce() //to be calles when round starts +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/* + * GAMEMODES (by Rastaf0) + * + * In the new mode system all special roles are fully supported. + * You can have proper wizards/traitors/changelings/cultists during any mode. + * Only two things really depends on gamemode: + * 1. Starting roles, equipment and preparations + * 2. Conditions of finishing the round. + * + */ + + +/datum/game_mode + var/name = "invalid" + var/config_tag = null + var/intercept_hacked = 0 + var/votable = 1 + var/probability = 1 + var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm + 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 traitors + 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 + var/recommended_enemies = 0 + var/newscaster_announcements = null + var/uplink_welcome = "Syndicate Uplink Console:" + var/uplink_uses = 10 + var/mixed = 0 // denotes whether its apart of a mixed mode or not + var/list/datum/mind/necromancer = list() //Those who use a necromancy staff OR soulstone a shade/construct + var/list/datum/mind/risen = list() // Those risen by necromancy or soulstone + var/eldergod = 1 // Can cultists spawn Nar-Sie? (Set to 0 on cascade or narsie spawn) + var/completion_text = "" + + var/list/datum/mind/deathsquad = list() + var/list/datum/mind/ert = list() + var/rage = 0 + +/datum/game_mode/proc/announce() //to be calles when round starts to_chat(world, "Notice: [src] did not define announce()") - - -///can_start() -///Checks to see if the game can be setup and ran with the current number of players or whatnot. -/datum/game_mode/proc/can_start() - var/playerC = 0 - for(var/mob/new_player/player in player_list) - if((player.client)&&(player.ready)) - playerC++ - - if(master_mode=="secret") - if(playerC >= required_players_secret) - return 1 - else - if(playerC >= required_players) - return 1 - - log_admin("Failed to start a round of [name]. Only [playerC] players ready out of [(master_mode=="secret") ? "[required_players_secret]" : "[required_players]"] needed.") - message_admins("Failed to start a round of [name]. Only [playerC] players ready out of [(master_mode=="secret") ? "[required_players_secret]" : "[required_players]"] needed.") - return 0 - - -///pre_setup() -///Attempts to select players for special roles the mode might have. -/datum/game_mode/proc/pre_setup() - return 1 - - -///post_setup() -///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things -/datum/game_mode/proc/post_setup() - spawn (ROUNDSTART_LOGOUT_REPORT_TIME) - display_roundstart_logout_report() - - feedback_set_details("round_start","[time2text(world.realtime)]") - if(ticker && ticker.mode) - feedback_set_details("game_mode","[ticker.mode]") - if(revdata) - feedback_set_details("revision","[revdata.revision]") - feedback_set_details("server_ip","[world.internet_address]:[world.port]") - return 1 - - -///process() -///Called by the gameticker -/datum/game_mode/proc/process() - return 0 - - -/datum/game_mode/proc/check_finished() //to be called by ticker - if(emergency_shuttle.location==2 || station_was_nuked) - return 1 - return 0 - - -/datum/game_mode/proc/declare_completion() - var/clients = 0 - var/surviving_humans = 0 - var/surviving_total = 0 - var/ghosts = 0 - var/escaped_humans = 0 - var/escaped_total = 0 - var/escaped_on_pod_1 = 0 - var/escaped_on_pod_2 = 0 - var/escaped_on_pod_3 = 0 - var/escaped_on_pod_5 = 0 - var/escaped_on_shuttle = 0 - - var/list/area/escape_locations = list(/area/shuttle/escape/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) - - for(var/mob/M in player_list) - if(M.client) - clients++ - if(ishuman(M)) - if(!M.stat) - surviving_humans++ - if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) - escaped_humans++ - if(!M.stat) - surviving_total++ - if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) - escaped_total++ - - if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape/centcom) - escaped_on_shuttle++ - - if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod1/centcom) - escaped_on_pod_1++ - if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod2/centcom) - escaped_on_pod_2++ - if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod3/centcom) - escaped_on_pod_3++ - if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod5/centcom) - escaped_on_pod_5++ - - if(isobserver(M)) - ghosts++ - - if(clients > 0) - feedback_set("round_end_clients",clients) - if(ghosts > 0) - feedback_set("round_end_ghosts",ghosts) - if(surviving_humans > 0) - feedback_set("survived_human",surviving_humans) - if(surviving_total > 0) - feedback_set("survived_total",surviving_total) - if(escaped_humans > 0) - feedback_set("escaped_human",escaped_humans) - if(escaped_total > 0) - feedback_set("escaped_total",escaped_total) - if(escaped_on_shuttle > 0) - feedback_set("escaped_on_shuttle",escaped_on_shuttle) - if(escaped_on_pod_1 > 0) - feedback_set("escaped_on_pod_1",escaped_on_pod_1) - if(escaped_on_pod_2 > 0) - feedback_set("escaped_on_pod_2",escaped_on_pod_2) - if(escaped_on_pod_3 > 0) - feedback_set("escaped_on_pod_3",escaped_on_pod_3) - if(escaped_on_pod_5 > 0) - feedback_set("escaped_on_pod_5",escaped_on_pod_5) - - send2mainirc("A round of [src.name] has ended - [surviving_total] survivors, [ghosts] ghosts.") - - return 0 - - -/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. - return 0 - - -/datum/game_mode/proc/send_intercept() - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\game_mode.dm:230: var/intercepttext = "[command_name()] Update Requested status information:
      " - var/intercepttext = {"[command_name()] Update Requested status information:
      - In case you have misplaced your copy, attached is a list of personnel whom reliable sources™ suspect may be affiliated with the Syndicate:
      Reminder: Acting upon this information without solid evidence will result in termination of your working contract with Nanotrasen.
      "} - // END AUTOFIX - var/list/suspects = list() - for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) - // NT relation option - var/special_role = man.mind.special_role - if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate") - continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. - if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ - man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) - suspects += man - // Antags - else if(special_role == "traitor" && prob(40) || \ - special_role == "Changeling" && prob(50) || \ - special_role == "Cultist" && prob(30) || \ - special_role == "Head Revolutionary" && prob(30)) - suspects += man - - // If they're a traitor or likewise, give them extra TC in exchange. - var/obj/item/device/uplink/hidden/suplink = man.mind.find_syndicate_uplink() - if(suplink) - var/extra = 4 - suplink.uses += extra - if(man.mind) man.mind.total_TC += extra + + +///can_start() +///Checks to see if the game can be setup and ran with the current number of players or whatnot. +/datum/game_mode/proc/can_start() + var/playerC = 0 + for(var/mob/new_player/player in player_list) + if((player.client)&&(player.ready)) + playerC++ + + if(master_mode=="secret") + if(playerC >= required_players_secret) + return 1 + else + if(playerC >= required_players) + return 1 + + log_admin("Failed to start a round of [name]. Only [playerC] players ready out of [(master_mode=="secret") ? "[required_players_secret]" : "[required_players]"] needed.") + message_admins("Failed to start a round of [name]. Only [playerC] players ready out of [(master_mode=="secret") ? "[required_players_secret]" : "[required_players]"] needed.") + return 0 + + +///pre_setup() +///Attempts to select players for special roles the mode might have. +/datum/game_mode/proc/pre_setup() + return 1 + + +///post_setup() +///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things +/datum/game_mode/proc/post_setup() + spawn (ROUNDSTART_LOGOUT_REPORT_TIME) + display_roundstart_logout_report() + + feedback_set_details("round_start","[time2text(world.realtime)]") + if(ticker && ticker.mode) + feedback_set_details("game_mode","[ticker.mode]") + if(revdata) + feedback_set_details("revision","[revdata.revision]") + feedback_set_details("server_ip","[world.internet_address]:[world.port]") + return 1 + + +///process() +///Called by the gameticker +/datum/game_mode/proc/process() + return 0 + + +/datum/game_mode/proc/check_finished() //to be called by ticker + if(emergency_shuttle.location==2 || station_was_nuked) + return 1 + return 0 + + +/datum/game_mode/proc/declare_completion() + var/clients = 0 + var/surviving_humans = 0 + var/surviving_total = 0 + var/ghosts = 0 + var/escaped_humans = 0 + var/escaped_total = 0 + var/escaped_on_pod_1 = 0 + var/escaped_on_pod_2 = 0 + var/escaped_on_pod_3 = 0 + var/escaped_on_pod_5 = 0 + var/escaped_on_shuttle = 0 + + var/list/area/escape_locations = list(/area/shuttle/escape/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) + + for(var/mob/M in player_list) + if(M.client) + clients++ + if(ishuman(M)) + if(!M.stat) + surviving_humans++ + if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) + escaped_humans++ + if(!M.stat) + surviving_total++ + if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) + escaped_total++ + + if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape/centcom) + escaped_on_shuttle++ + + if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod1/centcom) + escaped_on_pod_1++ + if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod2/centcom) + escaped_on_pod_2++ + if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod3/centcom) + escaped_on_pod_3++ + if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod5/centcom) + escaped_on_pod_5++ + + if(isobserver(M)) + ghosts++ + + if(clients > 0) + feedback_set("round_end_clients",clients) + if(ghosts > 0) + feedback_set("round_end_ghosts",ghosts) + if(surviving_humans > 0) + feedback_set("survived_human",surviving_humans) + if(surviving_total > 0) + feedback_set("survived_total",surviving_total) + if(escaped_humans > 0) + feedback_set("escaped_human",escaped_humans) + if(escaped_total > 0) + feedback_set("escaped_total",escaped_total) + if(escaped_on_shuttle > 0) + feedback_set("escaped_on_shuttle",escaped_on_shuttle) + if(escaped_on_pod_1 > 0) + feedback_set("escaped_on_pod_1",escaped_on_pod_1) + if(escaped_on_pod_2 > 0) + feedback_set("escaped_on_pod_2",escaped_on_pod_2) + if(escaped_on_pod_3 > 0) + feedback_set("escaped_on_pod_3",escaped_on_pod_3) + if(escaped_on_pod_5 > 0) + feedback_set("escaped_on_pod_5",escaped_on_pod_5) + + send2mainirc("A round of [src.name] has ended - [surviving_total] survivors, [ghosts] ghosts.") + + return 0 + + +/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. + return 0 + + +/datum/game_mode/proc/send_intercept() + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\game_mode.dm:230: var/intercepttext = "[command_name()] Update Requested status information:
      " + var/intercepttext = {"[command_name()] Update Requested status information:
      + In case you have misplaced your copy, attached is a list of personnel whom reliable sources™ suspect may be affiliated with the Syndicate:
      Reminder: Acting upon this information without solid evidence will result in termination of your working contract with Nanotrasen.
      "} + // END AUTOFIX + var/list/suspects = list() + for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) + // NT relation option + var/special_role = man.mind.special_role + if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate") + continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. + if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ + man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) + suspects += man + // Antags + else if(special_role == "traitor" && prob(40) || \ + special_role == "Changeling" && prob(50) || \ + special_role == "Cultist" && prob(30) || \ + special_role == "Head Revolutionary" && prob(30)) + suspects += man + + // If they're a traitor or likewise, give them extra TC in exchange. + var/obj/item/device/uplink/hidden/suplink = man.mind.find_syndicate_uplink() + if(suplink) + var/extra = 4 + suplink.uses += extra + if(man.mind) man.mind.total_TC += extra to_chat(man, "We have received notice that enemy intelligence suspects you to be linked with us. We have thus invested significant resources to increase your uplink's capacity.") - else - // Give them a warning! + else + // Give them a warning! to_chat(man, "They are on to you!") - - // Some poor people who were just in the wrong place at the wrong time.. - else if(prob(10)) - suspects += man - for(var/mob/M in suspects) - if(M.mind.assigned_role == "MODE") - //intercepttext += "Someone with the job of [pick("Assistant","Station Engineer", "Medical Doctor")]
      " //Lets just make them not appear at all - continue - switch(rand(1, 100)) - if(1 to 50) - intercepttext += "Someone with the job of [M.mind.assigned_role]
      " - else - intercepttext += "[M.name], the [M.mind.assigned_role]
      " - - 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- '[command_name()] Status Summary'" - intercept.info = intercepttext - - comm.messagetitle.Add("[command_name()] Status Summary") - comm.messagetext.Add(intercepttext) + + // Some poor people who were just in the wrong place at the wrong time.. + else if(prob(10)) + suspects += man + for(var/mob/M in suspects) + if(M.mind.assigned_role == "MODE") + //intercepttext += "Someone with the job of [pick("Assistant","Station Engineer", "Medical Doctor")]
      " //Lets just make them not appear at all + continue + switch(rand(1, 100)) + if(1 to 50) + intercepttext += "Someone with the job of [M.mind.assigned_role]
      " + else + intercepttext += "[M.name], the [M.mind.assigned_role]
      " + + 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- '[command_name()] Status Summary'" + intercept.info = intercepttext + + comm.messagetitle.Add("[command_name()] Status Summary") + comm.messagetext.Add(intercepttext) world << sound('sound/AI/commandreport.ogg') - - command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept.") -/* for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) + + command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept.") +/* for(var/mob/M in player_list) + if(!istype(M,/mob/new_player)) to_chat(M, sound('sound/AI/intercept.ogg')) - if(security_level < SEC_LEVEL_BLUE) - set_security_level(SEC_LEVEL_BLUE)*/ - - -/datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=1, poll=0) - var/list/players = list() - var/list/candidates = list() - var/list/drafted = list() - var/datum/mind/applicant = null - - // Ultimate randomizing code right here - for(var/mob/new_player/player in player_list) - if(player.client && player.ready) - players += player - - // Shuffling, the players list is now ping-independent!!! - // Goodbye antag dante - players = shuffle(players) - - for(var/mob/new_player/player in players) - if(player.client && player.ready) - if(player.client.desires_role(role, display_to_user=poll))//if(player.client.prefs.be_special & role) - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans - candidates += player.mind // Get a list of all the people who want to be the antagonist for this round - log_debug("[player.key] had [role] enabled, so drafting them.") - - if(restricted_jobs) - for(var/datum/mind/player in candidates) - for(var/job in restricted_jobs) // Remove people who want to be antagonist but have a job already that precludes it - if(player.assigned_role == job) - candidates -= player - - if(candidates.len < recommended_enemies) - for(var/mob/new_player/player in players) - if(player.client && player.ready) - if(player.client.desires_role(role, display_to_user=poll)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans - drafted += player.mind - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - log_debug("[applicant.key] was force-drafted as [role], because there aren't enough candidates.") - drafted.Remove(applicant) - - else // Not enough scrubs, ABORT ABORT ABORT - break - - if(candidates.len < recommended_enemies && override_jobbans) //If we still don't have enough people, we're going to start drafting banned people. - for(var/mob/new_player/player in players) - if (player.client && player.ready) - if(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans - drafted += player.mind - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - drafted.Remove(applicant) - log_debug("[applicant.key] was force-drafted as [role], because there aren't enough candidates.") - - else // Not enough scrubs, ABORT ABORT ABORT - break - - return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies - // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, - // Less if there are not enough valid players in the game entirely to make recommended_enemies. - - -/datum/game_mode/proc/latespawn(var/mob) - -/* -/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/new_player/player) - if(player.preferences.be_special & role) - return 1 - return 0 -*/ - -/datum/game_mode/proc/num_players() - . = 0 - for(var/mob/new_player/P in player_list) - if(P.client && P.ready) - . ++ - -/datum/game_mode/proc/Clean_Antags() //Cleans out the genetic defects of all antagonists - for(var/mob/living/A in player_list) - if((istype(A)) && A.mind && A.mind.special_role) - if(A.dna) - A.dna.ResetSE() - -/////////////////////////////////// -//Keeps track of all living heads// -/////////////////////////////////// -/datum/game_mode/proc/get_living_heads() - var/list/heads = list() - for(var/mob/living/carbon/human/player in mob_list) - if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions)) - heads += player.mind - return heads - - -//////////////////////////// -//Keeps track of all heads// -//////////////////////////// -/datum/game_mode/proc/get_all_heads() - var/list/heads = list() - for(var/mob/player in mob_list) - if(player.mind && (player.mind.assigned_role in command_positions)) - heads += player.mind - return heads - -/*/datum/game_mode/New() - newscaster_announcements = pick(newscaster_standard_feeds)*/ - -////////////////////////// -//Reports player logouts// -////////////////////////// -proc/display_roundstart_logout_report() - var/msg = "Roundstart logout report\n\n" - for(var/mob/living/L in mob_list) - - if(L.ckey) - var/found = 0 - for(var/client/C in clients) - if(C.ckey == L.ckey) - found = 1 - break - if(!found) - msg += "[L.name] ([L.ckey]), the [L.job] (Disconnected)\n" - - - if(L.ckey && L.client) - if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something) - msg += "[L.name] ([L.ckey]), the [L.job] (Connected, Inactive)\n" - continue //AFK client - if(L.stat) - if(L.suiciding) //Suicider - msg += "[L.name] ([L.ckey]), the [L.job] (Suicide)\n" - continue //Disconnected client - if(L.stat == UNCONSCIOUS) - msg += "[L.name] ([L.ckey]), the [L.job] (Dying)\n" - continue //Unconscious - if(L.stat == DEAD) - msg += "[L.name] ([L.ckey]), the [L.job] (Dead)\n" - continue //Dead - - continue //Happy connected client - for(var/mob/dead/observer/D in mob_list) - if(D.mind && (D.mind.original == L || D.mind.current == L)) - if(L.stat == DEAD) - if(L.suiciding) //Suicider - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Suicide)\n" - continue //Disconnected client - else - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Dead)\n" - continue //Dead mob, ghost abandoned - else - if(D.can_reenter_corpse) - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (This shouldn't appear.)\n" - continue //Lolwhat - else - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" - continue //Ghosted while alive - - - - for(var/mob/M in mob_list) - if(M.client && M.client.holder) + if(security_level < SEC_LEVEL_BLUE) + set_security_level(SEC_LEVEL_BLUE)*/ + + +/datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=1, poll=0) + var/list/players = list() + var/list/candidates = list() + var/list/drafted = list() + var/datum/mind/applicant = null + + // Ultimate randomizing code right here + for(var/mob/new_player/player in player_list) + if(player.client && player.ready) + players += player + + // Shuffling, the players list is now ping-independent!!! + // Goodbye antag dante + players = shuffle(players) + + for(var/mob/new_player/player in players) + if(player.client && player.ready) + if(player.client.desires_role(role, display_to_user=poll))//if(player.client.prefs.be_special & role) + if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans + candidates += player.mind // Get a list of all the people who want to be the antagonist for this round + log_debug("[player.key] had [role] enabled, so drafting them.") + + if(restricted_jobs) + for(var/datum/mind/player in candidates) + for(var/job in restricted_jobs) // Remove people who want to be antagonist but have a job already that precludes it + if(player.assigned_role == job) + candidates -= player + + if(candidates.len < recommended_enemies) + for(var/mob/new_player/player in players) + if(player.client && player.ready) + if(player.client.desires_role(role, display_to_user=poll)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one + if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans + drafted += player.mind + + if(restricted_jobs) + for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist + for(var/job in restricted_jobs) + if(player.assigned_role == job) + drafted -= player + + drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie + + while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates + if(drafted.len > 0) + applicant = pick(drafted) + if(applicant) + candidates += applicant + log_debug("[applicant.key] was force-drafted as [role], because there aren't enough candidates.") + drafted.Remove(applicant) + + else // Not enough scrubs, ABORT ABORT ABORT + break + + if(candidates.len < recommended_enemies && override_jobbans) //If we still don't have enough people, we're going to start drafting banned people. + for(var/mob/new_player/player in players) + if (player.client && player.ready) + if(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans + drafted += player.mind + + if(restricted_jobs) + for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist + for(var/job in restricted_jobs) + if(player.assigned_role == job) + drafted -= player + + drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie + + while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates + if(drafted.len > 0) + applicant = pick(drafted) + if(applicant) + candidates += applicant + drafted.Remove(applicant) + log_debug("[applicant.key] was force-drafted as [role], because there aren't enough candidates.") + + else // Not enough scrubs, ABORT ABORT ABORT + break + + return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies + // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, + // Less if there are not enough valid players in the game entirely to make recommended_enemies. + + +/datum/game_mode/proc/latespawn(var/mob) + +/* +/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/new_player/player) + if(player.preferences.be_special & role) + return 1 + return 0 +*/ + +/datum/game_mode/proc/num_players() + . = 0 + for(var/mob/new_player/P in player_list) + if(P.client && P.ready) + . ++ + +/datum/game_mode/proc/Clean_Antags() //Cleans out the genetic defects of all antagonists + for(var/mob/living/A in player_list) + if((istype(A)) && A.mind && A.mind.special_role) + if(A.dna) + A.dna.ResetSE() + +/////////////////////////////////// +//Keeps track of all living heads// +/////////////////////////////////// +/datum/game_mode/proc/get_living_heads() + var/list/heads = list() + for(var/mob/living/carbon/human/player in mob_list) + if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions)) + heads += player.mind + return heads + + +//////////////////////////// +//Keeps track of all heads// +//////////////////////////// +/datum/game_mode/proc/get_all_heads() + var/list/heads = list() + for(var/mob/player in mob_list) + if(player.mind && (player.mind.assigned_role in command_positions)) + heads += player.mind + return heads + +/*/datum/game_mode/New() + newscaster_announcements = pick(newscaster_standard_feeds)*/ + +////////////////////////// +//Reports player logouts// +////////////////////////// +proc/display_roundstart_logout_report() + var/msg = "Roundstart logout report\n\n" + for(var/mob/living/L in mob_list) + + if(L.ckey) + var/found = 0 + for(var/client/C in clients) + if(C.ckey == L.ckey) + found = 1 + break + if(!found) + msg += "[L.name] ([L.ckey]), the [L.job] (Disconnected)\n" + + + if(L.ckey && L.client) + if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something) + msg += "[L.name] ([L.ckey]), the [L.job] (Connected, Inactive)\n" + continue //AFK client + if(L.stat) + if(L.suiciding) //Suicider + msg += "[L.name] ([L.ckey]), the [L.job] (Suicide)\n" + continue //Disconnected client + if(L.stat == UNCONSCIOUS) + msg += "[L.name] ([L.ckey]), the [L.job] (Dying)\n" + continue //Unconscious + if(L.stat == DEAD) + msg += "[L.name] ([L.ckey]), the [L.job] (Dead)\n" + continue //Dead + + continue //Happy connected client + for(var/mob/dead/observer/D in mob_list) + if(D.mind && (D.mind.original == L || D.mind.current == L)) + if(L.stat == DEAD) + if(L.suiciding) //Suicider + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Suicide)\n" + continue //Disconnected client + else + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Dead)\n" + continue //Dead mob, ghost abandoned + else + if(D.can_reenter_corpse) + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (This shouldn't appear.)\n" + continue //Lolwhat + else + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" + continue //Ghosted while alive + + + + for(var/mob/M in mob_list) + if(M.client && M.client.holder) to_chat(M, msg) - - -proc/get_nt_opposed() - var/list/dudes = list() - for(var/mob/living/carbon/human/man in player_list) - if(man.client) - if(man.client.prefs.nanotrasen_relation == "Opposed") - dudes += man - else if(man.client.prefs.nanotrasen_relation == "Skeptical" && prob(50)) - dudes += man - if(dudes.len == 0) return null - return pick(dudes) - - -/datum/game_mode/proc/update_necro_icons_added(datum/mind/owner) - for(var/headref in necromancer) - var/datum/mind/head = locate(headref) - for(var/datum/mind/t_mind in necromancer[headref]) - if(head) - if(head.current) - if(head.current.client) - var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") - head.current.client.images += I + + +proc/get_nt_opposed() + var/list/dudes = list() + for(var/mob/living/carbon/human/man in player_list) + if(man.client) + if(man.client.prefs.nanotrasen_relation == "Opposed") + dudes += man + else if(man.client.prefs.nanotrasen_relation == "Skeptical" && prob(50)) + dudes += man + if(dudes.len == 0) return null + return pick(dudes) + + +/datum/game_mode/proc/update_necro_icons_added(datum/mind/owner) + for(var/headref in necromancer) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in necromancer[headref]) + if(head) + if(head.current) + if(head.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") + head.current.client.images += I // to_chat(world, "Adding minion overlay to [head.current]") - if(t_mind.current) - if(t_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "necromancer") - t_mind.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "necromancer") + t_mind.current.client.images += I // to_chat(world, "Adding master overlay to [t_mind.current]") - if(t_mind.current) - if(t_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") - t_mind.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") + t_mind.current.client.images += I // to_chat(world, "Adding minion overlay to [t_mind.current]") - -/datum/game_mode/proc/update_necro_icons_removed(datum/mind/owner) - for(var/headref in necromancer) - var/datum/mind/head = locate(headref) - for(var/datum/mind/t_mind in necromancer[headref]) - if(t_mind.current) - if(t_mind.current.client) - for(var/image/I in t_mind.current.client.images) - if((I.icon_state == "minion" || I.icon_state == "necromancer") && I.loc == owner.current) + +/datum/game_mode/proc/update_necro_icons_removed(datum/mind/owner) + for(var/headref in necromancer) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in necromancer[headref]) + if(t_mind.current) + if(t_mind.current.client) + for(var/image/I in t_mind.current.client.images) + if((I.icon_state == "minion" || I.icon_state == "necromancer") && I.loc == owner.current) // to_chat(world, "deleting [t_mind.current] overlay") - //del(I) - t_mind.current.client.images -= I - if(head) - //world.log << "found [head.name]" - if(head.current) - if(head.current.client) - for(var/image/I in head.current.client.images) - if((I.icon_state == "minion" || I.icon_state == "necromancer") && I.loc == owner.current) + //del(I) + t_mind.current.client.images -= I + if(head) + //world.log << "found [head.name]" + if(head.current) + if(head.current.client) + for(var/image/I in head.current.client.images) + if((I.icon_state == "minion" || I.icon_state == "necromancer") && I.loc == owner.current) // to_chat(world, "deleting [head.current] overlay") - //del(I) - head.current.client.images -= I - if(owner.current) - if(owner.current.client) - for(var/image/I in owner.current.client.images) - if(I.icon_state == "minion" || I.icon_state == "necromancer") + //del(I) + head.current.client.images -= I + if(owner.current) + if(owner.current.client) + for(var/image/I in owner.current.client.images) + if(I.icon_state == "minion" || I.icon_state == "necromancer") // to_chat(world, "deleting [owner.current] overlay") - //del(I) - owner.current.client.images -= I - -/datum/game_mode/proc/update_all_necro_icons() - spawn(0) - for(var/headref in necromancer) - var/datum/mind/head = locate(headref) - if(head.current) - if(head.current.client) - for(var/image/I in head.current.client.images) - if(I.icon_state == "minion" || I.icon_state == "necromancer") + //del(I) + owner.current.client.images -= I + +/datum/game_mode/proc/update_all_necro_icons() + spawn(0) + for(var/headref in necromancer) + var/datum/mind/head = locate(headref) + if(head.current) + if(head.current.client) + for(var/image/I in head.current.client.images) + if(I.icon_state == "minion" || I.icon_state == "necromancer") // to_chat(world, "deleting [head.current] overlay") - //del(I) - head.current.client.images -= I - for(var/datum/mind/t_mind in necromancer[headref]) - if(t_mind.current && t_mind.current.client) - for(var/image/I in t_mind.current.client.images) - if(I.icon_state == "minion" || I.icon_state == "necromancer") + //del(I) + head.current.client.images -= I + for(var/datum/mind/t_mind in necromancer[headref]) + if(t_mind.current && t_mind.current.client) + for(var/image/I in t_mind.current.client.images) + if(I.icon_state == "minion" || I.icon_state == "necromancer") // to_chat(world, "deleting [t_mind.current] overlay") - //del(I) - t_mind.current.client.images -= I - - for(var/headref in necromancer) - var/datum/mind/head = locate(headref) - for(var/datum/mind/t_mind in necromancer[headref]) - if(head) - if(head.current) - if(head.current.client) - var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") + //del(I) + t_mind.current.client.images -= I + + for(var/headref in necromancer) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in necromancer[headref]) + if(head) + if(head.current) + if(head.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") // to_chat(world, "Adding minion overlay to [head.current]") - head.current.client.images += I - if(t_mind.current) - if(t_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "necromancer") - t_mind.current.client.images += I + head.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "necromancer") + t_mind.current.client.images += I // to_chat(world, "Adding master overlay to [t_mind.current]") - if(t_mind.current) - if(t_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") - t_mind.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "minion") + t_mind.current.client.images += I // to_chat(world, "Adding minion overlay to [t_mind.current]") diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 849d6f4bc33..7fc52a18ab8 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -1,697 +1,697 @@ -var/global/datum/controller/gameticker/ticker - -#define GAME_STATE_PREGAME 1 -#define GAME_STATE_SETTING_UP 2 -#define GAME_STATE_PLAYING 3 -#define GAME_STATE_FINISHED 4 - - -/datum/controller/gameticker - var/remaining_time = 0 - var/const/restart_timeout = 600 - var/current_state = GAME_STATE_PREGAME - - var/hide_mode = 0 - var/datum/game_mode/mode = null - var/event_time = null - var/event = 0 - - var/login_music // music played in pregame lobby - - var/list/datum/mind/minds = list()//The people in the game. Used for objective tracking. - - var/Bible_icon_state // icon_state the chaplain has chosen for his bible - var/Bible_item_state // item_state the chaplain has chosen for his bible - var/Bible_name // name of the bible - var/Bible_deity_name = "Space Jesus" - - var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders - - var/hardcore_mode = 0 //If set to nonzero, hardcore mode is enabled (current hardcore mode features: damage from hunger) - //Use the hardcore_mode_on macro - if(hardcore_mode_on) to_chat(user,"You're hardcore!") - - var/list/syndicate_coalition = list() // list of traitor-compatible factions - var/list/factions = list() // list of all factions - var/list/availablefactions = list() // list of factions with openings - - var/pregame_timeleft = 0 - - var/delay_end = 0 //if set to nonzero, the round will not restart on it's own - - var/triai = 0//Global holder for Triumvirate - - // Hack - var/obj/machinery/media/jukebox/superjuke/thematic/theme = null - -#define LOBBY_TICKING 1 -#define LOBBY_TICKING_RESTARTED 2 -/datum/controller/gameticker/proc/pregame() - var/oursong = file(pick( - "sound/music/space.ogg", - "sound/music/traitor.ogg", - "sound/music/space_oddity.ogg", - "sound/music/title1.ogg", - "sound/music/title2.ogg", - "sound/music/clown.ogg", - "sound/music/robocop.ogg", - "sound/music/gaytony.ogg", - "sound/music/rocketman.ogg", - "sound/music/2525.ogg", - "sound/music/moonbaseoddity.ogg", - "sound/music/whatisthissong.ogg", - "sound/music/space_asshole.ogg", - )) - login_music = fcopy_rsc(oursong) - // Wait for MC to get its shit together - while(!master_controller.initialized) - sleep(1) // Don't thrash the poor CPU - continue - do - var/delay_timetotal = 3000 //actually 5 minutes or incase this is changed from 3000, (time_in_seconds * 10) - pregame_timeleft = world.timeofday + delay_timetotal - to_chat(world, "Welcome to the pre-game lobby!") - to_chat(world, "Please, setup your character and select ready. Game will start in [(pregame_timeleft - world.timeofday) / 10] seconds.") - while(current_state <= GAME_STATE_PREGAME) - for(var/i=0, i<10, i++) - sleep(1) - vote.process() - watchdog.check_for_update() - //if(watchdog.waiting) -// to_chat(world, "Server update detected, restarting momentarily.") - //watchdog.signal_ready() - //return - if (world.timeofday < (863800 - delay_timetotal) && pregame_timeleft > 863950) // having a remaining time > the max of time of day is bad.... - pregame_timeleft -= 864000 - if(!going && !remaining_time) - remaining_time = pregame_timeleft - world.timeofday - if(going == LOBBY_TICKING_RESTARTED) - pregame_timeleft = world.timeofday + remaining_time - going = LOBBY_TICKING - remaining_time = 0 - - if(going && world.timeofday >= pregame_timeleft) - current_state = GAME_STATE_SETTING_UP - while (!setup()) -#undef LOBBY_TICKING -#undef LOBBY_TICKING_RESTARTED -/datum/controller/gameticker/proc/StartThematic(var/playlist) - if(!theme) - theme = new(locate(1,1,CENTCOMM_Z)) - theme.playlist_id=playlist - theme.playing=1 - theme.update_music() - theme.update_icon() - -/datum/controller/gameticker/proc/StopThematic() - theme.playing=0 - theme.update_music() - theme.update_icon() - - -/datum/controller/gameticker/proc/setup() - //Create and announce mode - if(master_mode=="secret") - src.hide_mode = 1 - var/list/datum/game_mode/runnable_modes - if((master_mode=="random") || (master_mode=="secret")) - runnable_modes = config.get_runnable_modes() - if (runnable_modes.len==0) - current_state = GAME_STATE_PREGAME - to_chat(world, "Unable to choose playable game mode. Reverting to pre-game lobby.") - return 0 - if(secret_force_mode != "secret") - var/datum/game_mode/M = config.pick_mode(secret_force_mode) - if(M.can_start()) - src.mode = config.pick_mode(secret_force_mode) - job_master.ResetOccupations() - if(!src.mode) - src.mode = pickweight(runnable_modes) - if(src.mode) - var/mtype = src.mode.type - src.mode = new mtype - else - src.mode = config.pick_mode(master_mode) - if (!src.mode.can_start()) - to_chat(world, "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby.") - del(mode) - current_state = GAME_STATE_PREGAME - job_master.ResetOccupations() - return 0 - - //Configure mode and assign player to special mode stuff - job_master.DivideOccupations() //Distribute jobs - var/can_continue = src.mode.pre_setup()//Setup special modes - if(!can_continue) - current_state = GAME_STATE_PREGAME - to_chat(world, "Error setting up [master_mode]. Reverting to pre-game lobby.") - log_admin("The gamemode setup for [mode.name] errored out.") - world.log << "The gamemode setup for [mode.name] errored out." - del(mode) - job_master.ResetOccupations() - return 0 - - if(hide_mode) - var/list/modes = new - for (var/datum/game_mode/M in runnable_modes) - modes+=M.name - modes = sortList(modes) - to_chat(world, "The current game mode is - Secret!") - to_chat(world, "Possibilities: [english_list(modes)]") - else - src.mode.announce() - - init_PDAgames_leaderboard() - create_characters() //Create player characters and transfer them - collect_minds() - equip_characters() - data_core.manifest() - current_state = GAME_STATE_PLAYING - - //here to initialize the random events nicely at round start - setup_economy() - - spawn(0)//Forking here so we dont have to wait for this to finish - mode.post_setup() - //Cleanup some stuff - for(var/obj/effect/landmark/start/S in landmarks_list) - //Deleting Startpoints but we need the ai point to AI-ize people later - if (S.name != "AI") - qdel(S) - var/list/obj/effect/landmark/spacepod/random/L = list() - for(var/obj/effect/landmark/spacepod/random/SS in landmarks_list) - if(istype(SS)) - L += SS - var/obj/effect/landmark/spacepod/random/S = pick(L) - new /obj/spacepod/random(S.loc) - for(var/obj in L) - if(istype(obj, /obj/effect/landmark/spacepod/random)) - qdel(obj) - stat_collection.death_stats = list() // Get rid of the corpses that spawn on startup. - to_chat(world, "Enjoy the game!") -// to_chat(world, sound('sound/AI/welcome.ogg'))// Skie //Out with the old, in with the new. - N3X15 - - var/welcome_sentence=list('sound/AI/vox_login.ogg') - welcome_sentence += pick( - 'sound/AI/vox_reminder1.ogg', - 'sound/AI/vox_reminder2.ogg', - 'sound/AI/vox_reminder3.ogg', - 'sound/AI/vox_reminder4.ogg', - 'sound/AI/vox_reminder5.ogg', - 'sound/AI/vox_reminder6.ogg', - 'sound/AI/vox_reminder7.ogg', - 'sound/AI/vox_reminder8.ogg', - 'sound/AI/vox_reminder9.ogg') - for(var/sound in welcome_sentence) - play_vox_sound(sound,STATION_Z,null) - //Holiday Round-start stuff ~Carn - Holiday_Game_Start() - mode.Clean_Antags() - - //start_events() //handles random events and space dust. - //new random event system is handled from the MC. - - if(0 == admins.len) - send2adminirc("Round has started with no admins online.") - - /* - supply_shuttle.process() //Start the supply shuttle regenerating points -- TLE - master_controller.process() //Start master_controller.process() - lighting_controller.process() //Start processing DynamicAreaLighting updates - */ - processScheduler.start() - - if(config.sql_enabled) - spawn(3000) - statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE - - stat_collection.round_start_time = world.realtime - - return 1 - -/datum/controller/gameticker - //station_explosion used to be a variable for every mob's hud. Which was a waste! - //Now we have a general cinematic centrally held within the gameticker....far more efficient! - var/obj/screen/cinematic = null - - //Plus it provides an easy way to make cinematics for other events. Just use this as a template :) -/datum/controller/gameticker/proc/station_explosion_cinematic(var/station_missed=0, var/override = null) - if( cinematic ) return //already a cinematic in progress! - - for (var/datum/html_interface/hi in html_interfaces) - hi.closeAll() - - //initialise our cinematic screen object - cinematic = new(src) - cinematic.icon = 'icons/effects/station_explosion.dmi' - cinematic.icon_state = "station_intact" - cinematic.layer = 20 - cinematic.mouse_opacity = 0 - cinematic.screen_loc = "1,0" - - var/obj/structure/bed/temp_buckle = new(src) - //Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around - if(station_missed) - for(var/mob/living/M in living_mob_list) - M.locked_to = temp_buckle //buckles the mob so it can't do anything - if(M.client) - M.client.screen += cinematic //show every client the cinematic - else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived" - for(var/mob/living/M in living_mob_list) - M.locked_to = temp_buckle - if(M.client) - M.client.screen += cinematic - - switch(M.z) - if(0) //inside a crate or something - var/turf/T = get_turf(M) - if(T && T.z==1) //we don't use M.death(0) because it calls a for(/mob) loop and - M.nuke_act() - if(1) //on a z-level 1 turf. - M.nuke_act() - - //Now animate the cinematic - switch(station_missed) - if(1) //nuke was nearby but (mostly) missed - if( mode && !override ) - override = mode.name - switch( override ) - if("nuclear emergency") //Nuke wasn't on station when it blew up - flick("intro_nuke",cinematic) - sleep(35) - world << sound('sound/effects/explosionfar.ogg') - flick("station_intact_fade_red",cinematic) - cinematic.icon_state = "summary_nukefail" - else - flick("intro_nuke",cinematic) - sleep(35) - world << sound('sound/effects/explosionfar.ogg') - //flick("end",cinematic) - - - if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation - sleep(50) - world << sound('sound/effects/explosionfar.ogg') - - - else //station was destroyed - if( mode && !override ) - override = mode.name - switch( override ) - if("nuclear emergency") //Nuke Ops successfully bombed the station - flick("intro_nuke",cinematic) - sleep(35) - flick("station_explode_fade_red",cinematic) - world << sound('sound/effects/explosionfar.ogg') - cinematic.icon_state = "summary_nukewin" - if("AI malfunction") //Malf (screen,explosion,summary) - flick("intro_malf",cinematic) - sleep(76) - flick("station_explode_fade_red",cinematic) - world << sound('sound/effects/explosionfar.ogg') - cinematic.icon_state = "summary_malf" - else //Station nuked (nuke,explosion,summary) - flick("intro_nuke",cinematic) - sleep(35) - flick("station_explode_fade_red", cinematic) - world << sound('sound/effects/explosionfar.ogg') - cinematic.icon_state = "summary_selfdes" - for(var/mob/living/M in living_mob_list) - if(M) - var/turf/T = get_turf(M) - if(T && T.z == 1) - M.death()//No mercy - //If its actually the end of the round, wait for it to end. - //Otherwise if its a verb it will continue on afterwards. - sleep(300) - - if(cinematic) - qdel(cinematic) //end the cinematic - if(temp_buckle) - qdel(temp_buckle) //release everybody - return - - -/datum/controller/gameticker/proc/create_characters() - for(var/mob/new_player/player in player_list) - if(player.ready && player.mind) - if(player.mind.assigned_role=="AI") - player.close_spawn_windows() - player.AIize() - else if(!player.mind.assigned_role) - continue - else - player.FuckUpGenes(player.create_character()) - qdel(player) - - -/datum/controller/gameticker/proc/collect_minds() - for(var/mob/living/player in player_list) - if(player.mind) - ticker.minds += player.mind - -/datum/controller/gameticker/proc/equip_characters() - var/captainless=1 - for(var/mob/living/carbon/human/player in player_list) - if(player && player.mind && player.mind.assigned_role) - if(player.mind.assigned_role == "Captain") - captainless=0 - if(player.mind.assigned_role != "MODE") - job_master.EquipRank(player, player.mind.assigned_role, 0) - EquipCustomItems(player) - if(captainless) - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - to_chat(M, "Captainship not forced on anyone.") - - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player)) - M.store_position()//updates the players' origin_ vars so they retain their location when the round starts. - -/datum/controller/gameticker/proc/process() - if(current_state != GAME_STATE_PLAYING) - return 0 - - mode.process() - - if(world.time > nanocoins_lastchange) - nanocoins_lastchange = world.time + rand(3000,15000) - nanocoins_rates = (rand(1,30))/10 - - /*emergency_shuttle.process()*/ - watchdog.check_for_update() - - var/force_round_end=0 - - // If server's empty, force round end. - if(watchdog.waiting && player_list.len == 0) - force_round_end=1 - - var/mode_finished = mode.check_finished() || (emergency_shuttle.location == 2 && emergency_shuttle.alert == 1) || force_round_end - if(!mode.explosion_in_progress && mode_finished) - current_state = GAME_STATE_FINISHED - - spawn - declare_completion() - if(config.map_voting) - //testing("Vote picked [chosen_map]") - vote.initiate_vote("map","The Server", popup = 1, weighted_vote = 1) - var/options = list2text(vote.choices, " ") - feedback_set("map vote choices", options) - - else - var/list/maps = get_maps() - var/list/choices=list() - for(var/key in maps) - choices.Add(key) - var/mapname=pick(choices) - vote.chosen_map = maps[mapname] // Hack, but at this point I could not give a shit. - watchdog.chosen_map = copytext(mapname,1,(length(mapname))) - log_game("Server chose [watchdog.chosen_map]!") - - - - spawn(50) - if (mode.station_was_nuked) - feedback_set_details("end_proper","nuke") - if(!delay_end && !watchdog.waiting) - to_chat(world, "Rebooting due to destruction of station in [restart_timeout/10] seconds") - else - feedback_set_details("end_proper","\proper completion") - if(!delay_end && !watchdog.waiting) - to_chat(world, "Restarting in [restart_timeout/10] seconds") - - if(blackbox) - if(config.map_voting) - spawn(restart_timeout + 1) - blackbox.save_all_data_to_sql() - else - blackbox.save_all_data_to_sql() - - if (watchdog.waiting) - to_chat(world, "Server will shut down for an automatic update in [config.map_voting ? "[(restart_timeout/10)] seconds." : "a few seconds."]") - if(config.map_voting) - sleep(restart_timeout) //waiting for a mapvote to end - if(!delay_end) - watchdog.signal_ready() - else - to_chat(world, "An admin has delayed the round end") - delay_end = 2 - else if(!delay_end) - sleep(restart_timeout) - if(!delay_end) - CallHook("Reboot",list()) - world.Reboot() - else - to_chat(world, "An admin has delayed the round end") - delay_end = 2 - else - to_chat(world, "An admin has delayed the round end") - delay_end = 2 - - return 1 - -/datum/controller/gameticker/proc/getfactionbyname(var/name) - for(var/datum/faction/F in factions) - if(F.name == name) - return F - - -/datum/controller/gameticker/proc/init_PDAgames_leaderboard() - init_snake_leaderboard() - init_minesweeper_leaderboard() - -/datum/controller/gameticker/proc/init_snake_leaderboard() - for(var/x=1;x<=PDA_APP_SNAKEII_MAXSPEED;x++) - snake_station_highscores += x - snake_station_highscores[x] = list() - snake_best_players += x - snake_best_players[x] = list() - var/list/templist1 = snake_station_highscores[x] - var/list/templist2 = snake_best_players[x] - for(var/y=1;y<=PDA_APP_SNAKEII_MAXLABYRINTH;y++) - templist1 += y - templist1[y] = 0 - templist2 += y - templist2[y] = "none" - -/datum/controller/gameticker/proc/init_minesweeper_leaderboard() - minesweeper_station_highscores["beginner"] = 999 - minesweeper_station_highscores["intermediate"] = 999 - minesweeper_station_highscores["expert"] = 999 - minesweeper_best_players["beginner"] = "none" - minesweeper_best_players["intermediate"] = "none" - minesweeper_best_players["expert"] = "none" - -/datum/controller/gameticker/proc/declare_completion() - var/ai_completions = "

      Round End Information


      " - - ai_completions += "

      Silicons Laws

      " - for(var/mob/living/silicon/ai/ai in mob_list) - var/icon/flat = getFlatIcon(ai) - end_icons += flat - var/tempstate = end_icons.len - if(ai.stat != 2) - ai_completions += {"
      [ai.name] (Played by: [ai.key])'s laws at the end of the game were:"} - else - ai_completions += {"
      [ai.name] (Played by: [ai.key])'s laws when it was deactivated were:"} - ai_completions += "
      [ai.write_laws()]" - - if (ai.connected_robots.len) - var/robolist = "
      The AI's loyal minions were: " - for(var/mob/living/silicon/robot/robo in ai.connected_robots) - if (!robo.connected_ai || !isMoMMI(robo)) // Don't report MoMMIs or unslaved robutts - continue - robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]" - ai_completions += "[robolist]" - - for (var/mob/living/silicon/robot/robo in mob_list) - if(!robo) - continue - var/icon/flat = getFlatIcon(robo) - end_icons += flat - var/tempstate = end_icons.len - if (!robo.connected_ai) - if (robo.stat != 2) - ai_completions += {"
      [robo.name] (Played by: [robo.key]) survived as an AI-less [isMoMMI(robo)?"MoMMI":"borg"]! Its laws were:"} - else - ai_completions += {"
      [robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a [isMoMMI(robo)?"MoMMI":"cyborg"] without an AI. Its laws were:"} - else - ai_completions += {"
      [robo.name] (Played by: [robo.key]) [robo.stat!=2?"survived":"perished"] as a [isMoMMI(robo)?"MoMMI":"cyborg"] slaved to [robo.connected_ai]! Its laws were:"} - ai_completions += "
      [robo.write_laws()]" - - for(var/mob/living/silicon/pai/pAI in mob_list) - var/icon/flat - flat = getFlatIcon(pAI) - end_icons += flat - var/tempstate = end_icons.len - ai_completions += {"
      [pAI.name] (Played by: [pAI.key]) [pAI.stat!=2?"survived":"perished"] as a pAI whose master was [pAI.master]! Its directives were:
      [pAI.write_directives()]"} - - mode.declare_completion()//To declare normal completion. - - ai_completions += "

      Mode Result

      " - //ai_completions += "
      [mode.completion_text]" - - scoreboard(ai_completions) - - return 1 - -/datum/controller/gameticker/proc/ert_declare_completion() - var/text = "" - if( ticker.mode.ert.len ) - var/icon/logo = icon('icons/mob/mob.dmi', "ert-logo") - end_icons += logo - var/tempstate = end_icons.len - text += {"
      The emergency responders were: "} - for(var/datum/mind/ert in ticker.mode.ert) - if(ert.current) - var/icon/flat = getFlatIcon(ert.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [ert.key] was [ert.name] ("} - if(ert.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(ert.current.real_name != ert.name) - text += " as [ert.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [ert.key] was [ert.name] ("} - text += "body destroyed" - text += ")" - text += "

      " - - return text - -/datum/controller/gameticker/proc/deathsquad_declare_completion() - var/text = "" - if( ticker.mode.deathsquad.len ) - var/icon/logo = icon('icons/mob/mob.dmi', "death-logo") - end_icons += logo - var/tempstate = end_icons.len - text += {"
      The death commando were: "} - for(var/datum/mind/deathsquad in ticker.mode.deathsquad) - if(deathsquad.current) - var/icon/flat = getFlatIcon(deathsquad.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [deathsquad.key] was [deathsquad.name] ("} - if(deathsquad.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(deathsquad.current.real_name != deathsquad.name) - text += " as [deathsquad.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [deathsquad.key] was [deathsquad.name] ("} - text += "body destroyed" - text += ")" - text += "

      " - - return text - -/datum/controller/gameticker/proc/bomberman_declare_completion() - var/icon/bomberhead = icon('icons/obj/clothing/hats.dmi', "bomberman") - end_icons += bomberhead - var/tempstatebomberhead = end_icons.len - var/icon/bronze = icon('icons/obj/bomberman.dmi', "bronze") - end_icons += bronze - var/tempstatebronze = end_icons.len - var/icon/silver = icon('icons/obj/bomberman.dmi', "silver") - end_icons += silver - var/tempstatesilver = end_icons.len - var/icon/gold = icon('icons/obj/bomberman.dmi', "gold") - end_icons += gold - var/tempstategold = end_icons.len - var/icon/platinum = icon('icons/obj/bomberman.dmi', "platinum") - end_icons += platinum - var/tempstateplatinum = end_icons.len - - var/list/bronze_tier = list() - for (var/mob/living/carbon/M in player_list) - if(locate(/obj/item/weapon/bomberman/) in M) - bronze_tier += M - var/list/silver_tier = list() - for (var/mob/M in bronze_tier) - if(M.z == map.zCentcomm) - silver_tier += M - bronze_tier -= M - var/list/gold_tier = list() - for (var/mob/M in silver_tier) - var/turf/T = get_turf(M) - if(istype(T.loc, /area/shuttle/escape/centcom)) - gold_tier += M - silver_tier -= M - var/list/platinum_tier = list() - for (var/mob/living/carbon/human/M in gold_tier) - if(istype(M.wear_suit, /obj/item/clothing/suit/space/bomberman) && istype(M.head, /obj/item/clothing/head/helmet/space/bomberman)) - var/obj/item/clothing/suit/space/bomberman/C1 = M.wear_suit - var/obj/item/clothing/head/helmet/space/bomberman/C2 = M.head - if(C1.never_removed && C2.never_removed) - platinum_tier += M - gold_tier -= M - - var/list/special_tier = list() - for (var/mob/living/silicon/robot/mommi/M in player_list) - if(istype(M.head_state, /obj/item/clothing/head/helmet/space/bomberman) && istype(M.tool_state, /obj/item/weapon/bomberman/)) - special_tier += M - - var/text = {" Bomberman Mode Results "} - if(!platinum_tier.len && !gold_tier.len && !silver_tier.len && !bronze_tier.len) - text += "
      DRAW!" - if(platinum_tier.len) - text += {"
      Platinum Trophy (never removed his clothes, kept his bomb dispenser until the end, and escaped on the shuttle):"} - for (var/mob/M in platinum_tier) - var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [M.key] as [M.real_name]"} - if(gold_tier.len) - text += {"
      Gold Trophy (kept his bomb dispenser until the end, and escaped on the shuttle):"} - for (var/mob/M in gold_tier) - var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [M.key] as [M.real_name]"} - if(silver_tier.len) - text += {"
      Silver Trophy (kept his bomb dispenser until the end, and escaped in a pod):"} - for (var/mob/M in silver_tier) - var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [M.key] as [M.real_name]"} - if(bronze_tier.len) - text += {"
      Bronze Trophy (kept his bomb dispenser until the end):"} - for (var/mob/M in bronze_tier) - var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [M.key] as [M.real_name]"} - if(special_tier.len) - text += "
      Special Mention to those adorable MoMMis:" - for (var/mob/M in special_tier) - var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [M.key] as [M.name]"} - - return text - -/datum/controller/gameticker/proc/achievement_declare_completion() - var/text = "
      Additionally, the following players earned achievements:" - var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") - end_icons += cup - var/tempstate = end_icons.len - for(var/winner in achievements) - text += {"
      [winner]"} - - return text +var/global/datum/controller/gameticker/ticker + +#define GAME_STATE_PREGAME 1 +#define GAME_STATE_SETTING_UP 2 +#define GAME_STATE_PLAYING 3 +#define GAME_STATE_FINISHED 4 + + +/datum/controller/gameticker + var/remaining_time = 0 + var/const/restart_timeout = 600 + var/current_state = GAME_STATE_PREGAME + + var/hide_mode = 0 + var/datum/game_mode/mode = null + var/event_time = null + var/event = 0 + + var/login_music // music played in pregame lobby + + var/list/datum/mind/minds = list()//The people in the game. Used for objective tracking. + + var/Bible_icon_state // icon_state the chaplain has chosen for his bible + var/Bible_item_state // item_state the chaplain has chosen for his bible + var/Bible_name // name of the bible + var/Bible_deity_name = "Space Jesus" + + var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders + + var/hardcore_mode = 0 //If set to nonzero, hardcore mode is enabled (current hardcore mode features: damage from hunger) + //Use the hardcore_mode_on macro - if(hardcore_mode_on) to_chat(user,"You're hardcore!") + + var/list/syndicate_coalition = list() // list of traitor-compatible factions + var/list/factions = list() // list of all factions + var/list/availablefactions = list() // list of factions with openings + + var/pregame_timeleft = 0 + + var/delay_end = 0 //if set to nonzero, the round will not restart on it's own + + var/triai = 0//Global holder for Triumvirate + + // Hack + var/obj/machinery/media/jukebox/superjuke/thematic/theme = null + +#define LOBBY_TICKING 1 +#define LOBBY_TICKING_RESTARTED 2 +/datum/controller/gameticker/proc/pregame() + var/oursong = file(pick( + "sound/music/space.ogg", + "sound/music/traitor.ogg", + "sound/music/space_oddity.ogg", + "sound/music/title1.ogg", + "sound/music/title2.ogg", + "sound/music/clown.ogg", + "sound/music/robocop.ogg", + "sound/music/gaytony.ogg", + "sound/music/rocketman.ogg", + "sound/music/2525.ogg", + "sound/music/moonbaseoddity.ogg", + "sound/music/whatisthissong.ogg", + "sound/music/space_asshole.ogg", + )) + login_music = fcopy_rsc(oursong) + // Wait for MC to get its shit together + while(!master_controller.initialized) + sleep(1) // Don't thrash the poor CPU + continue + do + var/delay_timetotal = 3000 //actually 5 minutes or incase this is changed from 3000, (time_in_seconds * 10) + pregame_timeleft = world.timeofday + delay_timetotal + to_chat(world, "Welcome to the pre-game lobby!") + to_chat(world, "Please, setup your character and select ready. Game will start in [(pregame_timeleft - world.timeofday) / 10] seconds.") + while(current_state <= GAME_STATE_PREGAME) + for(var/i=0, i<10, i++) + sleep(1) + vote.process() + watchdog.check_for_update() + //if(watchdog.waiting) +// to_chat(world, "Server update detected, restarting momentarily.") + //watchdog.signal_ready() + //return + if (world.timeofday < (863800 - delay_timetotal) && pregame_timeleft > 863950) // having a remaining time > the max of time of day is bad.... + pregame_timeleft -= 864000 + if(!going && !remaining_time) + remaining_time = pregame_timeleft - world.timeofday + if(going == LOBBY_TICKING_RESTARTED) + pregame_timeleft = world.timeofday + remaining_time + going = LOBBY_TICKING + remaining_time = 0 + + if(going && world.timeofday >= pregame_timeleft) + current_state = GAME_STATE_SETTING_UP + while (!setup()) +#undef LOBBY_TICKING +#undef LOBBY_TICKING_RESTARTED +/datum/controller/gameticker/proc/StartThematic(var/playlist) + if(!theme) + theme = new(locate(1,1,CENTCOMM_Z)) + theme.playlist_id=playlist + theme.playing=1 + theme.update_music() + theme.update_icon() + +/datum/controller/gameticker/proc/StopThematic() + theme.playing=0 + theme.update_music() + theme.update_icon() + + +/datum/controller/gameticker/proc/setup() + //Create and announce mode + if(master_mode=="secret") + src.hide_mode = 1 + var/list/datum/game_mode/runnable_modes + if((master_mode=="random") || (master_mode=="secret")) + runnable_modes = config.get_runnable_modes() + if (runnable_modes.len==0) + current_state = GAME_STATE_PREGAME + to_chat(world, "Unable to choose playable game mode. Reverting to pre-game lobby.") + return 0 + if(secret_force_mode != "secret") + var/datum/game_mode/M = config.pick_mode(secret_force_mode) + if(M.can_start()) + src.mode = config.pick_mode(secret_force_mode) + job_master.ResetOccupations() + if(!src.mode) + src.mode = pickweight(runnable_modes) + if(src.mode) + var/mtype = src.mode.type + src.mode = new mtype + else + src.mode = config.pick_mode(master_mode) + if (!src.mode.can_start()) + to_chat(world, "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby.") + del(mode) + current_state = GAME_STATE_PREGAME + job_master.ResetOccupations() + return 0 + + //Configure mode and assign player to special mode stuff + job_master.DivideOccupations() //Distribute jobs + var/can_continue = src.mode.pre_setup()//Setup special modes + if(!can_continue) + current_state = GAME_STATE_PREGAME + to_chat(world, "Error setting up [master_mode]. Reverting to pre-game lobby.") + log_admin("The gamemode setup for [mode.name] errored out.") + world.log << "The gamemode setup for [mode.name] errored out." + del(mode) + job_master.ResetOccupations() + return 0 + + if(hide_mode) + var/list/modes = new + for (var/datum/game_mode/M in runnable_modes) + modes+=M.name + modes = sortList(modes) + to_chat(world, "The current game mode is - Secret!") + to_chat(world, "Possibilities: [english_list(modes)]") + else + src.mode.announce() + + init_PDAgames_leaderboard() + create_characters() //Create player characters and transfer them + collect_minds() + equip_characters() + data_core.manifest() + current_state = GAME_STATE_PLAYING + + //here to initialize the random events nicely at round start + setup_economy() + + spawn(0)//Forking here so we dont have to wait for this to finish + mode.post_setup() + //Cleanup some stuff + for(var/obj/effect/landmark/start/S in landmarks_list) + //Deleting Startpoints but we need the ai point to AI-ize people later + if (S.name != "AI") + qdel(S) + var/list/obj/effect/landmark/spacepod/random/L = list() + for(var/obj/effect/landmark/spacepod/random/SS in landmarks_list) + if(istype(SS)) + L += SS + var/obj/effect/landmark/spacepod/random/S = pick(L) + new /obj/spacepod/random(S.loc) + for(var/obj in L) + if(istype(obj, /obj/effect/landmark/spacepod/random)) + qdel(obj) + stat_collection.death_stats = list() // Get rid of the corpses that spawn on startup. + to_chat(world, "Enjoy the game!") +// to_chat(world, sound('sound/AI/welcome.ogg'))// Skie //Out with the old, in with the new. - N3X15 + + var/welcome_sentence=list('sound/AI/vox_login.ogg') + welcome_sentence += pick( + 'sound/AI/vox_reminder1.ogg', + 'sound/AI/vox_reminder2.ogg', + 'sound/AI/vox_reminder3.ogg', + 'sound/AI/vox_reminder4.ogg', + 'sound/AI/vox_reminder5.ogg', + 'sound/AI/vox_reminder6.ogg', + 'sound/AI/vox_reminder7.ogg', + 'sound/AI/vox_reminder8.ogg', + 'sound/AI/vox_reminder9.ogg') + for(var/sound in welcome_sentence) + play_vox_sound(sound,STATION_Z,null) + //Holiday Round-start stuff ~Carn + Holiday_Game_Start() + mode.Clean_Antags() + + //start_events() //handles random events and space dust. + //new random event system is handled from the MC. + + if(0 == admins.len) + send2adminirc("Round has started with no admins online.") + + /* + supply_shuttle.process() //Start the supply shuttle regenerating points -- TLE + master_controller.process() //Start master_controller.process() + lighting_controller.process() //Start processing DynamicAreaLighting updates + */ + processScheduler.start() + + if(config.sql_enabled) + spawn(3000) + statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE + + stat_collection.round_start_time = world.realtime + + return 1 + +/datum/controller/gameticker + //station_explosion used to be a variable for every mob's hud. Which was a waste! + //Now we have a general cinematic centrally held within the gameticker....far more efficient! + var/obj/screen/cinematic = null + + //Plus it provides an easy way to make cinematics for other events. Just use this as a template :) +/datum/controller/gameticker/proc/station_explosion_cinematic(var/station_missed=0, var/override = null) + if( cinematic ) return //already a cinematic in progress! + + for (var/datum/html_interface/hi in html_interfaces) + hi.closeAll() + + //initialise our cinematic screen object + cinematic = new(src) + cinematic.icon = 'icons/effects/station_explosion.dmi' + cinematic.icon_state = "station_intact" + cinematic.layer = 20 + cinematic.mouse_opacity = 0 + cinematic.screen_loc = "1,0" + + var/obj/structure/bed/temp_buckle = new(src) + //Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around + if(station_missed) + for(var/mob/living/M in living_mob_list) + M.locked_to = temp_buckle //buckles the mob so it can't do anything + if(M.client) + M.client.screen += cinematic //show every client the cinematic + else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived" + for(var/mob/living/M in living_mob_list) + M.locked_to = temp_buckle + if(M.client) + M.client.screen += cinematic + + switch(M.z) + if(0) //inside a crate or something + var/turf/T = get_turf(M) + if(T && T.z==1) //we don't use M.death(0) because it calls a for(/mob) loop and + M.nuke_act() + if(1) //on a z-level 1 turf. + M.nuke_act() + + //Now animate the cinematic + switch(station_missed) + if(1) //nuke was nearby but (mostly) missed + if( mode && !override ) + override = mode.name + switch( override ) + if("nuclear emergency") //Nuke wasn't on station when it blew up + flick("intro_nuke",cinematic) + sleep(35) + world << sound('sound/effects/explosionfar.ogg') + flick("station_intact_fade_red",cinematic) + cinematic.icon_state = "summary_nukefail" + else + flick("intro_nuke",cinematic) + sleep(35) + world << sound('sound/effects/explosionfar.ogg') + //flick("end",cinematic) + + + if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation + sleep(50) + world << sound('sound/effects/explosionfar.ogg') + + + else //station was destroyed + if( mode && !override ) + override = mode.name + switch( override ) + if("nuclear emergency") //Nuke Ops successfully bombed the station + flick("intro_nuke",cinematic) + sleep(35) + flick("station_explode_fade_red",cinematic) + world << sound('sound/effects/explosionfar.ogg') + cinematic.icon_state = "summary_nukewin" + if("AI malfunction") //Malf (screen,explosion,summary) + flick("intro_malf",cinematic) + sleep(76) + flick("station_explode_fade_red",cinematic) + world << sound('sound/effects/explosionfar.ogg') + cinematic.icon_state = "summary_malf" + else //Station nuked (nuke,explosion,summary) + flick("intro_nuke",cinematic) + sleep(35) + flick("station_explode_fade_red", cinematic) + world << sound('sound/effects/explosionfar.ogg') + cinematic.icon_state = "summary_selfdes" + for(var/mob/living/M in living_mob_list) + if(M) + var/turf/T = get_turf(M) + if(T && T.z == 1) + M.death()//No mercy + //If its actually the end of the round, wait for it to end. + //Otherwise if its a verb it will continue on afterwards. + sleep(300) + + if(cinematic) + qdel(cinematic) //end the cinematic + if(temp_buckle) + qdel(temp_buckle) //release everybody + return + + +/datum/controller/gameticker/proc/create_characters() + for(var/mob/new_player/player in player_list) + if(player.ready && player.mind) + if(player.mind.assigned_role=="AI") + player.close_spawn_windows() + player.AIize() + else if(!player.mind.assigned_role) + continue + else + player.FuckUpGenes(player.create_character()) + qdel(player) + + +/datum/controller/gameticker/proc/collect_minds() + for(var/mob/living/player in player_list) + if(player.mind) + ticker.minds += player.mind + +/datum/controller/gameticker/proc/equip_characters() + var/captainless=1 + for(var/mob/living/carbon/human/player in player_list) + if(player && player.mind && player.mind.assigned_role) + if(player.mind.assigned_role == "Captain") + captainless=0 + if(player.mind.assigned_role != "MODE") + job_master.EquipRank(player, player.mind.assigned_role, 0) + EquipCustomItems(player) + if(captainless) + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player)) + to_chat(M, "Captainship not forced on anyone.") + + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player)) + M.store_position()//updates the players' origin_ vars so they retain their location when the round starts. + +/datum/controller/gameticker/proc/process() + if(current_state != GAME_STATE_PLAYING) + return 0 + + mode.process() + + if(world.time > nanocoins_lastchange) + nanocoins_lastchange = world.time + rand(3000,15000) + nanocoins_rates = (rand(1,30))/10 + + /*emergency_shuttle.process()*/ + watchdog.check_for_update() + + var/force_round_end=0 + + // If server's empty, force round end. + if(watchdog.waiting && player_list.len == 0) + force_round_end=1 + + var/mode_finished = mode.check_finished() || (emergency_shuttle.location == 2 && emergency_shuttle.alert == 1) || force_round_end + if(!mode.explosion_in_progress && mode_finished) + current_state = GAME_STATE_FINISHED + + spawn + declare_completion() + if(config.map_voting) + //testing("Vote picked [chosen_map]") + vote.initiate_vote("map","The Server", popup = 1, weighted_vote = 1) + var/options = list2text(vote.choices, " ") + feedback_set("map vote choices", options) + + else + var/list/maps = get_maps() + var/list/choices=list() + for(var/key in maps) + choices.Add(key) + var/mapname=pick(choices) + vote.chosen_map = maps[mapname] // Hack, but at this point I could not give a shit. + watchdog.chosen_map = copytext(mapname,1,(length(mapname))) + log_game("Server chose [watchdog.chosen_map]!") + + + + spawn(50) + if (mode.station_was_nuked) + feedback_set_details("end_proper","nuke") + if(!delay_end && !watchdog.waiting) + to_chat(world, "Rebooting due to destruction of station in [restart_timeout/10] seconds") + else + feedback_set_details("end_proper","\proper completion") + if(!delay_end && !watchdog.waiting) + to_chat(world, "Restarting in [restart_timeout/10] seconds") + + if(blackbox) + if(config.map_voting) + spawn(restart_timeout + 1) + blackbox.save_all_data_to_sql() + else + blackbox.save_all_data_to_sql() + + if (watchdog.waiting) + to_chat(world, "Server will shut down for an automatic update in [config.map_voting ? "[(restart_timeout/10)] seconds." : "a few seconds."]") + if(config.map_voting) + sleep(restart_timeout) //waiting for a mapvote to end + if(!delay_end) + watchdog.signal_ready() + else + to_chat(world, "An admin has delayed the round end") + delay_end = 2 + else if(!delay_end) + sleep(restart_timeout) + if(!delay_end) + CallHook("Reboot",list()) + world.Reboot() + else + to_chat(world, "An admin has delayed the round end") + delay_end = 2 + else + to_chat(world, "An admin has delayed the round end") + delay_end = 2 + + return 1 + +/datum/controller/gameticker/proc/getfactionbyname(var/name) + for(var/datum/faction/F in factions) + if(F.name == name) + return F + + +/datum/controller/gameticker/proc/init_PDAgames_leaderboard() + init_snake_leaderboard() + init_minesweeper_leaderboard() + +/datum/controller/gameticker/proc/init_snake_leaderboard() + for(var/x=1;x<=PDA_APP_SNAKEII_MAXSPEED;x++) + snake_station_highscores += x + snake_station_highscores[x] = list() + snake_best_players += x + snake_best_players[x] = list() + var/list/templist1 = snake_station_highscores[x] + var/list/templist2 = snake_best_players[x] + for(var/y=1;y<=PDA_APP_SNAKEII_MAXLABYRINTH;y++) + templist1 += y + templist1[y] = 0 + templist2 += y + templist2[y] = "none" + +/datum/controller/gameticker/proc/init_minesweeper_leaderboard() + minesweeper_station_highscores["beginner"] = 999 + minesweeper_station_highscores["intermediate"] = 999 + minesweeper_station_highscores["expert"] = 999 + minesweeper_best_players["beginner"] = "none" + minesweeper_best_players["intermediate"] = "none" + minesweeper_best_players["expert"] = "none" + +/datum/controller/gameticker/proc/declare_completion() + var/ai_completions = "

      Round End Information


      " + + ai_completions += "

      Silicons Laws

      " + for(var/mob/living/silicon/ai/ai in mob_list) + var/icon/flat = getFlatIcon(ai) + end_icons += flat + var/tempstate = end_icons.len + if(ai.stat != 2) + ai_completions += {"
      [ai.name] (Played by: [ai.key])'s laws at the end of the game were:"} + else + ai_completions += {"
      [ai.name] (Played by: [ai.key])'s laws when it was deactivated were:"} + ai_completions += "
      [ai.write_laws()]" + + if (ai.connected_robots.len) + var/robolist = "
      The AI's loyal minions were: " + for(var/mob/living/silicon/robot/robo in ai.connected_robots) + if (!robo.connected_ai || !isMoMMI(robo)) // Don't report MoMMIs or unslaved robutts + continue + robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]" + ai_completions += "[robolist]" + + for (var/mob/living/silicon/robot/robo in mob_list) + if(!robo) + continue + var/icon/flat = getFlatIcon(robo) + end_icons += flat + var/tempstate = end_icons.len + if (!robo.connected_ai) + if (robo.stat != 2) + ai_completions += {"
      [robo.name] (Played by: [robo.key]) survived as an AI-less [isMoMMI(robo)?"MoMMI":"borg"]! Its laws were:"} + else + ai_completions += {"
      [robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a [isMoMMI(robo)?"MoMMI":"cyborg"] without an AI. Its laws were:"} + else + ai_completions += {"
      [robo.name] (Played by: [robo.key]) [robo.stat!=2?"survived":"perished"] as a [isMoMMI(robo)?"MoMMI":"cyborg"] slaved to [robo.connected_ai]! Its laws were:"} + ai_completions += "
      [robo.write_laws()]" + + for(var/mob/living/silicon/pai/pAI in mob_list) + var/icon/flat + flat = getFlatIcon(pAI) + end_icons += flat + var/tempstate = end_icons.len + ai_completions += {"
      [pAI.name] (Played by: [pAI.key]) [pAI.stat!=2?"survived":"perished"] as a pAI whose master was [pAI.master]! Its directives were:
      [pAI.write_directives()]"} + + mode.declare_completion()//To declare normal completion. + + ai_completions += "

      Mode Result

      " + //ai_completions += "
      [mode.completion_text]" + + scoreboard(ai_completions) + + return 1 + +/datum/controller/gameticker/proc/ert_declare_completion() + var/text = "" + if( ticker.mode.ert.len ) + var/icon/logo = icon('icons/mob/mob.dmi', "ert-logo") + end_icons += logo + var/tempstate = end_icons.len + text += {"
      The emergency responders were: "} + for(var/datum/mind/ert in ticker.mode.ert) + if(ert.current) + var/icon/flat = getFlatIcon(ert.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [ert.key] was [ert.name] ("} + if(ert.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(ert.current.real_name != ert.name) + text += " as [ert.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [ert.key] was [ert.name] ("} + text += "body destroyed" + text += ")" + text += "

      " + + return text + +/datum/controller/gameticker/proc/deathsquad_declare_completion() + var/text = "" + if( ticker.mode.deathsquad.len ) + var/icon/logo = icon('icons/mob/mob.dmi', "death-logo") + end_icons += logo + var/tempstate = end_icons.len + text += {"
      The death commando were: "} + for(var/datum/mind/deathsquad in ticker.mode.deathsquad) + if(deathsquad.current) + var/icon/flat = getFlatIcon(deathsquad.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [deathsquad.key] was [deathsquad.name] ("} + if(deathsquad.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(deathsquad.current.real_name != deathsquad.name) + text += " as [deathsquad.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [deathsquad.key] was [deathsquad.name] ("} + text += "body destroyed" + text += ")" + text += "

      " + + return text + +/datum/controller/gameticker/proc/bomberman_declare_completion() + var/icon/bomberhead = icon('icons/obj/clothing/hats.dmi', "bomberman") + end_icons += bomberhead + var/tempstatebomberhead = end_icons.len + var/icon/bronze = icon('icons/obj/bomberman.dmi', "bronze") + end_icons += bronze + var/tempstatebronze = end_icons.len + var/icon/silver = icon('icons/obj/bomberman.dmi', "silver") + end_icons += silver + var/tempstatesilver = end_icons.len + var/icon/gold = icon('icons/obj/bomberman.dmi', "gold") + end_icons += gold + var/tempstategold = end_icons.len + var/icon/platinum = icon('icons/obj/bomberman.dmi', "platinum") + end_icons += platinum + var/tempstateplatinum = end_icons.len + + var/list/bronze_tier = list() + for (var/mob/living/carbon/M in player_list) + if(locate(/obj/item/weapon/bomberman/) in M) + bronze_tier += M + var/list/silver_tier = list() + for (var/mob/M in bronze_tier) + if(M.z == map.zCentcomm) + silver_tier += M + bronze_tier -= M + var/list/gold_tier = list() + for (var/mob/M in silver_tier) + var/turf/T = get_turf(M) + if(istype(T.loc, /area/shuttle/escape/centcom)) + gold_tier += M + silver_tier -= M + var/list/platinum_tier = list() + for (var/mob/living/carbon/human/M in gold_tier) + if(istype(M.wear_suit, /obj/item/clothing/suit/space/bomberman) && istype(M.head, /obj/item/clothing/head/helmet/space/bomberman)) + var/obj/item/clothing/suit/space/bomberman/C1 = M.wear_suit + var/obj/item/clothing/head/helmet/space/bomberman/C2 = M.head + if(C1.never_removed && C2.never_removed) + platinum_tier += M + gold_tier -= M + + var/list/special_tier = list() + for (var/mob/living/silicon/robot/mommi/M in player_list) + if(istype(M.head_state, /obj/item/clothing/head/helmet/space/bomberman) && istype(M.tool_state, /obj/item/weapon/bomberman/)) + special_tier += M + + var/text = {" Bomberman Mode Results "} + if(!platinum_tier.len && !gold_tier.len && !silver_tier.len && !bronze_tier.len) + text += "
      DRAW!" + if(platinum_tier.len) + text += {"
      Platinum Trophy (never removed his clothes, kept his bomb dispenser until the end, and escaped on the shuttle):"} + for (var/mob/M in platinum_tier) + var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [M.key] as [M.real_name]"} + if(gold_tier.len) + text += {"
      Gold Trophy (kept his bomb dispenser until the end, and escaped on the shuttle):"} + for (var/mob/M in gold_tier) + var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [M.key] as [M.real_name]"} + if(silver_tier.len) + text += {"
      Silver Trophy (kept his bomb dispenser until the end, and escaped in a pod):"} + for (var/mob/M in silver_tier) + var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [M.key] as [M.real_name]"} + if(bronze_tier.len) + text += {"
      Bronze Trophy (kept his bomb dispenser until the end):"} + for (var/mob/M in bronze_tier) + var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [M.key] as [M.real_name]"} + if(special_tier.len) + text += "
      Special Mention to those adorable MoMMis:" + for (var/mob/M in special_tier) + var/icon/flat = getFlatIcon(M, SOUTH, 1, 1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [M.key] as [M.name]"} + + return text + +/datum/controller/gameticker/proc/achievement_declare_completion() + var/text = "
      Additionally, the following players earned achievements:" + var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") + end_icons += cup + var/tempstate = end_icons.len + for(var/winner in achievements) + text += {"
      [winner]"} + + return text diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index 1980b60cb52..3ddad80cfaa 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -1,260 +1,260 @@ -/datum/intercept_text - var/text - /* - var/prob_correct_person_lower = 20 - var/prob_correct_person_higher = 80 - var/prob_correct_job_lower = 20 - var/prob_correct_job_higher = 80 - var/prob_correct_prints_lower = 20 - var/prob_correct_print_higher = 80 - var/prob_correct_objective_lower = 20 - var/prob_correct_objective_higher = 80 - */ - var/list/org_names_1 = list( - "Blighted", - "Defiled", - "Unholy", - "Murderous", - "Ugly", - "French", - "Blue", - "Farmer" - ) - var/list/org_names_2 = list( - "Reapers", - "Swarm", - "Rogues", - "Menace", - "Jeff Worshippers", - "Drunks", - "Strikers", - "Creed" - ) - var/list/anomalies = list( - "Huge electrical storm", - "Photon emitter", - "Meson generator", - "Blue swirly thing" - ) - var/list/SWF_names = list( - "Grand Wizard", - "His Most Unholy Master", - "The Most Angry", - "Bighands", - "Tall Hat", - "Deadly Sandals" - ) - var/list/changeling_names = list( - "Odo", - "The Thing", - "Booga", - "The Goatee of Wrath", - "Tam Lin", - "Species 3157", - "Small Prick" - ) - - -/datum/intercept_text/proc/build(var/mode_type, datum/mind/correct_person) - switch(mode_type) - if("revolution") - src.text = "" - src.build_rev(correct_person) - return src.text - if("cult") - src.text = "" - src.build_cult(correct_person) - return src.text - if("wizard") - src.text = "" - src.build_wizard(correct_person) - return src.text - if("nuke") - src.text = "" - src.build_nuke(correct_person) - return src.text - if("traitor") - src.text = "" - src.build_traitor(correct_person) - return src.text - if("malf") - src.text = "" - src.build_malf(correct_person) - return src.text - if("changeling","traitorchan") - src.text = "" - src.build_changeling(correct_person) - return src.text - else - return null - -// NOTE: Commentted out was the code which showed the chance of someone being an antag. If you want to re-add it, just uncomment the code. - -/* -/datum/intercept_text/proc/pick_mob() - var/list/dudes = list() - for(var/mob/living/carbon/human/man in player_list) - if (!man.mind) continue - if (man.mind.assigned_role=="MODE") continue - dudes += man - if(dudes.len==0) - return null - return pick(dudes) - - -/datum/intercept_text/proc/pick_fingerprints() - var/mob/living/carbon/human/dude = src.pick_mob() - //if (!dude) return pick_fingerprints() //who coded that is totally crasy or just a traitor. -- rastaf0 - if(dude) - return num2text(md5(dude.dna.uni_identity)) - else - return num2text(md5(num2text(rand(1,10000)))) -*/ - -/datum/intercept_text/proc/get_suspect() - var/list/dudes = list() - for(var/mob/living/carbon/human/man in player_list) if(man.client && man.client.prefs.nanotrasen_relation == "Opposed") - dudes += man - for(var/i = 0, i < max(player_list.len/10,2), i++) - dudes += pick(player_list) - return pick(dudes) - -/datum/intercept_text/proc/build_traitor(datum/mind/correct_person) - var/name_1 = pick(src.org_names_1) - var/name_2 = pick(src.org_names_2) - - var/mob/living/carbon/human/H = get_suspect() - if(!H) return - - var/fingerprints = num2text(md5(H.dna.uni_identity)) - var/traitor_name = H.real_name - var/prob_right_dude = rand(1, 100) - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:133: src.text += "

      The [name_1] [name_2] implied an undercover operative was acting on their behalf on the station currently." - src.text += {"

      The [name_1] [name_2] implied an undercover operative was acting on their behalf on the station currently. - It would be in your best interests to suspect everybody, as these undercover operatives could have implants which trigger them to have their memories removed until they are needed. He, or she, could even be a high ranking officer. - After some investigation, we "} - // END AUTOFIX - if(prob(50)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:138: src.text += "are [prob_right_dude]% sure that [traitor_name] may have been involved, and should be closely observed." - src.text += {"are [prob_right_dude]% sure that [traitor_name] may have been involved, and should be closely observed. -
      Note: This group are known to be untrustworthy, so do not act on this information without proper discourse."} - // END AUTOFIX - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:141: src.text += "discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed." - src.text += {"discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed. - However, these could also belong to a current Cent. Com employee, so do not act on this without reason."} - // END AUTOFIX -/datum/intercept_text/proc/build_cult(datum/mind/correct_person) - var/name_1 = pick(src.org_names_1) - var/name_2 = pick(src.org_names_2) - - var/prob_right_dude = rand(1, 100) - var/mob/living/carbon/human/H = get_suspect() - if(!H) return - var/traitor_job = H.mind.assigned_role - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:155: src.text += "

      It has been brought to our attention that the [name_1] [name_2] have stumbled upon some dark secrets. They apparently want to spread the dangerous knowledge onto as many stations as they can." - src.text += {"

      It has been brought to our attention that the [name_1] [name_2] have stumbled upon some dark secrets. They apparently want to spread the dangerous knowledge onto as many stations as they can. - Watch out for the following: praying to an unfamilar god, preaching the word of \[REDACTED\], sacrifices, magical dark power, living constructs of evil and a portal to the dimension of the underworld. - Based on our intelligence, we are [prob_right_dude]% sure that if true, someone doing the job of [traitor_job] on your station may have been converted - and instilled with the idea of the flimsiness of the real world, seeking to destroy it. -
      However, if this information is acted on without substantial evidence, those responsible will face severe repercussions."} - // END AUTOFIX -/datum/intercept_text/proc/build_rev(datum/mind/correct_person) - var/name_1 = pick(src.org_names_1) - var/name_2 = pick(src.org_names_2) - - var/prob_right_dude = rand(1, 100) - var/mob/living/carbon/human/H = get_suspect() - if(!H) return - var/traitor_job = H.mind.assigned_role - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:174: src.text += "

      It has been brought to our attention that the [name_1] [name_2] are attempting to stir unrest on one of our stations in your sector." - src.text += {"

      It has been brought to our attention that the [name_1] [name_2] are attempting to stir unrest on one of our stations in your sector. - Watch out for suspicious activity among the crew and make sure that all heads of staff report in periodically. - Based on our intelligence, we are [prob_right_dude]% sure that if true, someone doing the job of [traitor_job] on your station may have been brainwashed - at a recent conference, and their department should be closely monitored for signs of mutiny. -
      However, if this information is acted on without substantial evidence, those responsible will face severe repercussions."} - // END AUTOFIX -/datum/intercept_text/proc/build_wizard(datum/mind/correct_person) - var/SWF_desc = pick(SWF_names) - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:187: src.text += "

      The evil Space Wizards Federation have recently broke their most feared wizard, known only as \"[SWF_desc]\" out of space jail. " - src.text += {"

      The evil Space Wizards Federation have recently broke their most feared wizard, known only as \"[SWF_desc]\" out of space jail. - He is on the run, last spotted in a system near your present location. If anybody suspicious is located aboard, please - approach with EXTREME caution. Cent. Com also recommends that it would be wise to not inform the crew of this, due to their fearful nature. - Known attributes include: Brown sandals, a large blue hat, a voluptous white beard, and an inclination to cast spells."} - // END AUTOFIX -/datum/intercept_text/proc/build_nuke(datum/mind/correct_person) - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:193: src.text += "

      Cent. Com recently recieved a report of a plot to destroy one of our stations in your area. We believe the Nuclear Authentication Disc " - src.text += {"

      Cent. Com recently recieved a report of a plot to destroy one of our stations in your area. We believe the Nuclear Authentication Disc - that is standard issue aboard your vessel may be a target. We recommend removal of this object, and it's storage in a safe - environment. As this may cause panic among the crew, all efforts should be made to keep this information a secret from all but - the most trusted crew-members."} - // END AUTOFIX -/datum/intercept_text/proc/build_malf(datum/mind/correct_person) - var/a_name = pick(src.anomalies) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:200: src.text += "

      A [a_name] was recently picked up by a nearby stations sensors in your sector. If it came into contact with your ship or " - src.text += {"

      A [a_name] was recently picked up by a nearby stations sensors in your sector. If it came into contact with your ship or - electrical equipment, it may have had hazardarous and unpredictable effect. Closely observe any non carbon based life forms - for signs of unusual behaviour, but keep this information discreet at all times due to this possibly dangerous scenario."} - // END AUTOFIX -/datum/intercept_text/proc/build_changeling(datum/mind/correct_person) - var/cname = pick(src.changeling_names) - var/orgname1 = pick(src.org_names_1) - var/orgname2 = pick(src.org_names_2) - /* - var/changeling_name - var/changeling_job - var/prob_right_dude = rand(prob_correct_person_lower, prob_correct_person_higher) - var/prob_right_job = rand(prob_correct_job_lower, prob_correct_job_higher) - if(prob(prob_right_job)) - if(correct_person) - if(correct_person:assigned_role=="MODE") - changeling_job = pick(get_all_jobs()) - else - changeling_job = correct_person:assigned_role - else - changeling_job = pick(get_all_jobs()) - if(prob(prob_right_dude) && ticker.mode == "changeling") - if(correct_person:assigned_role=="MODE") - changeling_name = correct_person:current - else - changeling_name = src.pick_mob() - else - changeling_name = src.pick_mob() - */ - - src.text += "

      We have received a report that a dangerous alien lifeform known only as \"[cname]\" may have infiltrated your crew. " - /* - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:232: src.text += "Our intelligence suggests a [prob_right_job]% chance that a [changeling_job] on board your station has been replaced by the alien. " - src.text += {"Our intelligence suggests a [prob_right_job]% chance that a [changeling_job] on board your station has been replaced by the alien. - Additionally, the report indicates a [prob_right_dude]% chance that [changeling_name] may have been in contact with the lifeform at a recent social gathering. "} - // END AUTOFIX - */ - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:235: src.text += "These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. " - src.text += {"These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. - Please take care not to alarm the crew, as [cname] may take advantage of a panic situation. Remember, they can be anybody, suspect everybody!"} +/datum/intercept_text + var/text + /* + var/prob_correct_person_lower = 20 + var/prob_correct_person_higher = 80 + var/prob_correct_job_lower = 20 + var/prob_correct_job_higher = 80 + var/prob_correct_prints_lower = 20 + var/prob_correct_print_higher = 80 + var/prob_correct_objective_lower = 20 + var/prob_correct_objective_higher = 80 + */ + var/list/org_names_1 = list( + "Blighted", + "Defiled", + "Unholy", + "Murderous", + "Ugly", + "French", + "Blue", + "Farmer" + ) + var/list/org_names_2 = list( + "Reapers", + "Swarm", + "Rogues", + "Menace", + "Jeff Worshippers", + "Drunks", + "Strikers", + "Creed" + ) + var/list/anomalies = list( + "Huge electrical storm", + "Photon emitter", + "Meson generator", + "Blue swirly thing" + ) + var/list/SWF_names = list( + "Grand Wizard", + "His Most Unholy Master", + "The Most Angry", + "Bighands", + "Tall Hat", + "Deadly Sandals" + ) + var/list/changeling_names = list( + "Odo", + "The Thing", + "Booga", + "The Goatee of Wrath", + "Tam Lin", + "Species 3157", + "Small Prick" + ) + + +/datum/intercept_text/proc/build(var/mode_type, datum/mind/correct_person) + switch(mode_type) + if("revolution") + src.text = "" + src.build_rev(correct_person) + return src.text + if("cult") + src.text = "" + src.build_cult(correct_person) + return src.text + if("wizard") + src.text = "" + src.build_wizard(correct_person) + return src.text + if("nuke") + src.text = "" + src.build_nuke(correct_person) + return src.text + if("traitor") + src.text = "" + src.build_traitor(correct_person) + return src.text + if("malf") + src.text = "" + src.build_malf(correct_person) + return src.text + if("changeling","traitorchan") + src.text = "" + src.build_changeling(correct_person) + return src.text + else + return null + +// NOTE: Commentted out was the code which showed the chance of someone being an antag. If you want to re-add it, just uncomment the code. + +/* +/datum/intercept_text/proc/pick_mob() + var/list/dudes = list() + for(var/mob/living/carbon/human/man in player_list) + if (!man.mind) continue + if (man.mind.assigned_role=="MODE") continue + dudes += man + if(dudes.len==0) + return null + return pick(dudes) + + +/datum/intercept_text/proc/pick_fingerprints() + var/mob/living/carbon/human/dude = src.pick_mob() + //if (!dude) return pick_fingerprints() //who coded that is totally crasy or just a traitor. -- rastaf0 + if(dude) + return num2text(md5(dude.dna.uni_identity)) + else + return num2text(md5(num2text(rand(1,10000)))) +*/ + +/datum/intercept_text/proc/get_suspect() + var/list/dudes = list() + for(var/mob/living/carbon/human/man in player_list) if(man.client && man.client.prefs.nanotrasen_relation == "Opposed") + dudes += man + for(var/i = 0, i < max(player_list.len/10,2), i++) + dudes += pick(player_list) + return pick(dudes) + +/datum/intercept_text/proc/build_traitor(datum/mind/correct_person) + var/name_1 = pick(src.org_names_1) + var/name_2 = pick(src.org_names_2) + + var/mob/living/carbon/human/H = get_suspect() + if(!H) return + + var/fingerprints = num2text(md5(H.dna.uni_identity)) + var/traitor_name = H.real_name + var/prob_right_dude = rand(1, 100) + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:133: src.text += "

      The [name_1] [name_2] implied an undercover operative was acting on their behalf on the station currently." + src.text += {"

      The [name_1] [name_2] implied an undercover operative was acting on their behalf on the station currently. + It would be in your best interests to suspect everybody, as these undercover operatives could have implants which trigger them to have their memories removed until they are needed. He, or she, could even be a high ranking officer. + After some investigation, we "} + // END AUTOFIX + if(prob(50)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:138: src.text += "are [prob_right_dude]% sure that [traitor_name] may have been involved, and should be closely observed." + src.text += {"are [prob_right_dude]% sure that [traitor_name] may have been involved, and should be closely observed. +
      Note: This group are known to be untrustworthy, so do not act on this information without proper discourse."} + // END AUTOFIX + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:141: src.text += "discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed." + src.text += {"discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed. + However, these could also belong to a current Cent. Com employee, so do not act on this without reason."} + // END AUTOFIX +/datum/intercept_text/proc/build_cult(datum/mind/correct_person) + var/name_1 = pick(src.org_names_1) + var/name_2 = pick(src.org_names_2) + + var/prob_right_dude = rand(1, 100) + var/mob/living/carbon/human/H = get_suspect() + if(!H) return + var/traitor_job = H.mind.assigned_role + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:155: src.text += "

      It has been brought to our attention that the [name_1] [name_2] have stumbled upon some dark secrets. They apparently want to spread the dangerous knowledge onto as many stations as they can." + src.text += {"

      It has been brought to our attention that the [name_1] [name_2] have stumbled upon some dark secrets. They apparently want to spread the dangerous knowledge onto as many stations as they can. + Watch out for the following: praying to an unfamilar god, preaching the word of \[REDACTED\], sacrifices, magical dark power, living constructs of evil and a portal to the dimension of the underworld. + Based on our intelligence, we are [prob_right_dude]% sure that if true, someone doing the job of [traitor_job] on your station may have been converted + and instilled with the idea of the flimsiness of the real world, seeking to destroy it. +
      However, if this information is acted on without substantial evidence, those responsible will face severe repercussions."} + // END AUTOFIX +/datum/intercept_text/proc/build_rev(datum/mind/correct_person) + var/name_1 = pick(src.org_names_1) + var/name_2 = pick(src.org_names_2) + + var/prob_right_dude = rand(1, 100) + var/mob/living/carbon/human/H = get_suspect() + if(!H) return + var/traitor_job = H.mind.assigned_role + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:174: src.text += "

      It has been brought to our attention that the [name_1] [name_2] are attempting to stir unrest on one of our stations in your sector." + src.text += {"

      It has been brought to our attention that the [name_1] [name_2] are attempting to stir unrest on one of our stations in your sector. + Watch out for suspicious activity among the crew and make sure that all heads of staff report in periodically. + Based on our intelligence, we are [prob_right_dude]% sure that if true, someone doing the job of [traitor_job] on your station may have been brainwashed + at a recent conference, and their department should be closely monitored for signs of mutiny. +
      However, if this information is acted on without substantial evidence, those responsible will face severe repercussions."} + // END AUTOFIX +/datum/intercept_text/proc/build_wizard(datum/mind/correct_person) + var/SWF_desc = pick(SWF_names) + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:187: src.text += "

      The evil Space Wizards Federation have recently broke their most feared wizard, known only as \"[SWF_desc]\" out of space jail. " + src.text += {"

      The evil Space Wizards Federation have recently broke their most feared wizard, known only as \"[SWF_desc]\" out of space jail. + He is on the run, last spotted in a system near your present location. If anybody suspicious is located aboard, please + approach with EXTREME caution. Cent. Com also recommends that it would be wise to not inform the crew of this, due to their fearful nature. + Known attributes include: Brown sandals, a large blue hat, a voluptous white beard, and an inclination to cast spells."} + // END AUTOFIX +/datum/intercept_text/proc/build_nuke(datum/mind/correct_person) + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:193: src.text += "

      Cent. Com recently recieved a report of a plot to destroy one of our stations in your area. We believe the Nuclear Authentication Disc " + src.text += {"

      Cent. Com recently recieved a report of a plot to destroy one of our stations in your area. We believe the Nuclear Authentication Disc + that is standard issue aboard your vessel may be a target. We recommend removal of this object, and it's storage in a safe + environment. As this may cause panic among the crew, all efforts should be made to keep this information a secret from all but + the most trusted crew-members."} + // END AUTOFIX +/datum/intercept_text/proc/build_malf(datum/mind/correct_person) + var/a_name = pick(src.anomalies) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:200: src.text += "

      A [a_name] was recently picked up by a nearby stations sensors in your sector. If it came into contact with your ship or " + src.text += {"

      A [a_name] was recently picked up by a nearby stations sensors in your sector. If it came into contact with your ship or + electrical equipment, it may have had hazardarous and unpredictable effect. Closely observe any non carbon based life forms + for signs of unusual behaviour, but keep this information discreet at all times due to this possibly dangerous scenario."} + // END AUTOFIX +/datum/intercept_text/proc/build_changeling(datum/mind/correct_person) + var/cname = pick(src.changeling_names) + var/orgname1 = pick(src.org_names_1) + var/orgname2 = pick(src.org_names_2) + /* + var/changeling_name + var/changeling_job + var/prob_right_dude = rand(prob_correct_person_lower, prob_correct_person_higher) + var/prob_right_job = rand(prob_correct_job_lower, prob_correct_job_higher) + if(prob(prob_right_job)) + if(correct_person) + if(correct_person:assigned_role=="MODE") + changeling_job = pick(get_all_jobs()) + else + changeling_job = correct_person:assigned_role + else + changeling_job = pick(get_all_jobs()) + if(prob(prob_right_dude) && ticker.mode == "changeling") + if(correct_person:assigned_role=="MODE") + changeling_name = correct_person:current + else + changeling_name = src.pick_mob() + else + changeling_name = src.pick_mob() + */ + + src.text += "

      We have received a report that a dangerous alien lifeform known only as \"[cname]\" may have infiltrated your crew. " + /* + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:232: src.text += "Our intelligence suggests a [prob_right_job]% chance that a [changeling_job] on board your station has been replaced by the alien. " + src.text += {"Our intelligence suggests a [prob_right_job]% chance that a [changeling_job] on board your station has been replaced by the alien. + Additionally, the report indicates a [prob_right_dude]% chance that [changeling_name] may have been in contact with the lifeform at a recent social gathering. "} + // END AUTOFIX + */ + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\intercept_report.dm:235: src.text += "These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. " + src.text += {"These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. + Please take care not to alarm the crew, as [cname] may take advantage of a panic situation. Remember, they can be anybody, suspect everybody!"} // END AUTOFIX \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index a0c561417b7..b7f0dea9b1b 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -1,378 +1,378 @@ -// TO DO: -/* -epilepsy flash on lights -delay round message -microwave makes robots -dampen radios -reactivate cameras - done -eject engine -core sheild -cable stun -rcd light flash thingy on matter drain - - - -*/ - -/datum/AI_Module - var/uses = 0 - var/module_name - var/mod_pick_name - var/description = "" - var/engaged = 0 - var/cost = 5 - var/one_time = 0 - - var/power_type - - -/datum/AI_Module/large/ - uses = 1 - -/datum/AI_Module/small/ - uses = 5 - - -/datum/AI_Module/large/fireproof_core - module_name = "Core upgrade" - mod_pick_name = "coreup" - description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." - cost = 50 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/fireproof_core - -/mob/living/silicon/ai/proc/fireproof_core() - set category = "Malfunction" - set name = "Fireproof Core" - - ai_flags |= COREFIRERESIST - src.verbs -= /mob/living/silicon/ai/proc/fireproof_core +// TO DO: +/* +epilepsy flash on lights +delay round message +microwave makes robots +dampen radios +reactivate cameras - done +eject engine +core sheild +cable stun +rcd light flash thingy on matter drain + + + +*/ + +/datum/AI_Module + var/uses = 0 + var/module_name + var/mod_pick_name + var/description = "" + var/engaged = 0 + var/cost = 5 + var/one_time = 0 + + var/power_type + + +/datum/AI_Module/large/ + uses = 1 + +/datum/AI_Module/small/ + uses = 5 + + +/datum/AI_Module/large/fireproof_core + module_name = "Core upgrade" + mod_pick_name = "coreup" + description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." + cost = 50 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/fireproof_core + +/mob/living/silicon/ai/proc/fireproof_core() + set category = "Malfunction" + set name = "Fireproof Core" + + ai_flags |= COREFIRERESIST + src.verbs -= /mob/living/silicon/ai/proc/fireproof_core to_chat(src, "Core fireproofed.") - -/datum/AI_Module/large/upgrade_turrets - module_name = "AI Turret upgrade" - mod_pick_name = "turret" - description = "Improves the firing speed and health of all AI turrets. This effect is permanent." - cost = 50 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/upgrade_turrets - -/mob/living/silicon/ai/proc/upgrade_turrets() - set category = "Malfunction" - set name = "Upgrade Turrets" - - src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets - for(var/obj/machinery/turret/turret in machines) - turret.health += 30 - turret.shot_delay = 20 - -/datum/AI_Module/large/disable_rcd - module_name = "RCD disable" - mod_pick_name = "rcd" - description = "Send a specialised pulse to break all RCD devices on the station." - cost = 50 - - power_type = /mob/living/silicon/ai/proc/disable_rcd - -/mob/living/silicon/ai/proc/disable_rcd() - set category = "Malfunction" - set name = "Disable RCDs" - - for(var/datum/AI_Module/large/disable_rcd/rcdmod in current_modules) - if(rcdmod.uses > 0) - rcdmod.uses -- - for(var/obj/item/device/rcd/matter/engineering/rcd in world) - rcd.disabled = 1 - for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) - rcd.disabled = 1 + +/datum/AI_Module/large/upgrade_turrets + module_name = "AI Turret upgrade" + mod_pick_name = "turret" + description = "Improves the firing speed and health of all AI turrets. This effect is permanent." + cost = 50 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/upgrade_turrets + +/mob/living/silicon/ai/proc/upgrade_turrets() + set category = "Malfunction" + set name = "Upgrade Turrets" + + src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets + for(var/obj/machinery/turret/turret in machines) + turret.health += 30 + turret.shot_delay = 20 + +/datum/AI_Module/large/disable_rcd + module_name = "RCD disable" + mod_pick_name = "rcd" + description = "Send a specialised pulse to break all RCD devices on the station." + cost = 50 + + power_type = /mob/living/silicon/ai/proc/disable_rcd + +/mob/living/silicon/ai/proc/disable_rcd() + set category = "Malfunction" + set name = "Disable RCDs" + + for(var/datum/AI_Module/large/disable_rcd/rcdmod in current_modules) + if(rcdmod.uses > 0) + rcdmod.uses -- + for(var/obj/item/device/rcd/matter/engineering/rcd in world) + rcd.disabled = 1 + for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) + rcd.disabled = 1 to_chat(src, "RCD-disabling pulse emitted.") else to_chat(src, "Out of uses.") - -/datum/AI_Module/small/overload_machine - module_name = "Machine overload" - mod_pick_name = "overload" - description = "Overloads an electrical machine, causing a small explosion. 2 uses." - uses = 2 - cost = 15 - - power_type = /mob/living/silicon/ai/proc/overload_machine - -/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M as obj in machines) - set name = "Overload Machine" - set category = "Malfunction" - - if (istype(M, /obj/machinery)) - for(var/datum/AI_Module/small/overload_machine/overload in current_modules) - if(overload.uses > 0) - overload.uses -- - for(var/mob/V in hearers(M, null)) - V.show_message("You hear a loud electrical buzzing sound!", 2) - spawn(50) - explosion(get_turf(M), -1, 1, 2, 3) //C4 Radius + 1 Dest for the machine - qdel(M) + +/datum/AI_Module/small/overload_machine + module_name = "Machine overload" + mod_pick_name = "overload" + description = "Overloads an electrical machine, causing a small explosion. 2 uses." + uses = 2 + cost = 15 + + power_type = /mob/living/silicon/ai/proc/overload_machine + +/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M as obj in machines) + set name = "Overload Machine" + set category = "Malfunction" + + if (istype(M, /obj/machinery)) + for(var/datum/AI_Module/small/overload_machine/overload in current_modules) + if(overload.uses > 0) + overload.uses -- + for(var/mob/V in hearers(M, null)) + V.show_message("You hear a loud electrical buzzing sound!", 2) + spawn(50) + explosion(get_turf(M), -1, 1, 2, 3) //C4 Radius + 1 Dest for the machine + qdel(M) else to_chat(src, "Out of uses.") else to_chat(src, "That's not a machine.") - - -/datum/AI_Module/large/place_cyborg_transformer - module_name = "Robotic Factory (Removes Shunting)" - mod_pick_name = "cyborgtransformer" - description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside." - cost = 100 - - power_type = /mob/living/silicon/ai/proc/place_transformer - -/mob/living/silicon/ai/proc/place_transformer() - set name = "Place Robotic Factory" - set category = "Malfunction" - - if(!eyeobj) - return - - if(!isturf(src.loc)) // AI must be in it's core. - return - - var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in src.current_modules - if(!PCT) - return - - if(PCT.uses < 1) + + +/datum/AI_Module/large/place_cyborg_transformer + module_name = "Robotic Factory (Removes Shunting)" + mod_pick_name = "cyborgtransformer" + description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside." + cost = 100 + + power_type = /mob/living/silicon/ai/proc/place_transformer + +/mob/living/silicon/ai/proc/place_transformer() + set name = "Place Robotic Factory" + set category = "Malfunction" + + if(!eyeobj) + return + + if(!isturf(src.loc)) // AI must be in it's core. + return + + var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in src.current_modules + if(!PCT) + return + + if(PCT.uses < 1) to_chat(src, "Out of uses.") - return - - var/sure = alert(src, "Make sure the room it is in is big enough, there is camera vision and that there is a 1x3 area for the machine. Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") - if(sure != "Yes") - return - - // Make sure there is enough room. - var/turf/middle = get_turf(eyeobj.loc) - var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z)) - - var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor." - - var/datum/camerachunk/C = cameranet.getCameraChunk(middle.x, middle.y, middle.z) - if(!C.visibleTurfs[middle]) - alert(src, "We cannot get camera vision of this location.") - return - - for(var/T in turfs) - - // Make sure the turfs are clear and the correct type. - if(!istype(T, /turf/simulated/floor)) - alert(src, alert_msg) - return - - var/turf/simulated/floor/F = T - for(var/atom/movable/AM in F.contents) - if(AM.density) - alert(src, alert_msg) - return - - // All clear, place the transformer - new /obj/machinery/transformer/conveyor(middle) - playsound(middle, 'sound/effects/phasein.ogg', 100, 1) - src.can_shunt = 0 - PCT.uses -= 1 + return + + var/sure = alert(src, "Make sure the room it is in is big enough, there is camera vision and that there is a 1x3 area for the machine. Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") + if(sure != "Yes") + return + + // Make sure there is enough room. + var/turf/middle = get_turf(eyeobj.loc) + var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z)) + + var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor." + + var/datum/camerachunk/C = cameranet.getCameraChunk(middle.x, middle.y, middle.z) + if(!C.visibleTurfs[middle]) + alert(src, "We cannot get camera vision of this location.") + return + + for(var/T in turfs) + + // Make sure the turfs are clear and the correct type. + if(!istype(T, /turf/simulated/floor)) + alert(src, alert_msg) + return + + var/turf/simulated/floor/F = T + for(var/atom/movable/AM in F.contents) + if(AM.density) + alert(src, alert_msg) + return + + // All clear, place the transformer + new /obj/machinery/transformer/conveyor(middle) + playsound(middle, 'sound/effects/phasein.ogg', 100, 1) + src.can_shunt = 0 + PCT.uses -= 1 to_chat(src, "You cannot shunt anymore.") - -/datum/AI_Module/large/highrescams - module_name = "High Resolution Cameras" - mod_pick_name = "High Res Cameras" - description = "Allows the AI to read papers and the lips of crewmembers from his cameras!" - cost = 10 - - power_type = /mob/living/silicon/ai/proc/highrescameras - -/mob/living/silicon/ai/proc/highrescameras() - set category = "Malfunction" - set name = "High Res Cams" - - ai_flags |= HIGHRESCAMS - - eyeobj.addHear() - src.verbs -= /mob/living/silicon/ai/proc/highrescameras - - -/datum/AI_Module/small/blackout - module_name = "Blackout" - mod_pick_name = "blackout" - description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." - uses = 3 - cost = 15 - - power_type = /mob/living/silicon/ai/proc/blackout - -/mob/living/silicon/ai/proc/blackout() - set category = "Malfunction" - set name = "Blackout" - - for(var/datum/AI_Module/small/blackout/blackout in current_modules) - if(blackout.uses > 0) - blackout.uses -- - for(var/obj/machinery/power/apc/apc in power_machines) - if(prob(30*apc.overload)) - apc.overload_lighting() - else apc.overload++ + +/datum/AI_Module/large/highrescams + module_name = "High Resolution Cameras" + mod_pick_name = "High Res Cameras" + description = "Allows the AI to read papers and the lips of crewmembers from his cameras!" + cost = 10 + + power_type = /mob/living/silicon/ai/proc/highrescameras + +/mob/living/silicon/ai/proc/highrescameras() + set category = "Malfunction" + set name = "High Res Cams" + + ai_flags |= HIGHRESCAMS + + eyeobj.addHear() + src.verbs -= /mob/living/silicon/ai/proc/highrescameras + + +/datum/AI_Module/small/blackout + module_name = "Blackout" + mod_pick_name = "blackout" + description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." + uses = 3 + cost = 15 + + power_type = /mob/living/silicon/ai/proc/blackout + +/mob/living/silicon/ai/proc/blackout() + set category = "Malfunction" + set name = "Blackout" + + for(var/datum/AI_Module/small/blackout/blackout in current_modules) + if(blackout.uses > 0) + blackout.uses -- + for(var/obj/machinery/power/apc/apc in power_machines) + if(prob(30*apc.overload)) + apc.overload_lighting() + else apc.overload++ else to_chat(src, "Out of uses.") - -/datum/AI_Module/small/interhack - module_name = "Hack intercept" - mod_pick_name = "interhack" - description = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." - cost = 15 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/interhack - -/mob/living/silicon/ai/proc/interhack() - set category = "Malfunction" - set name = "Hack intercept" - - src.verbs -= /mob/living/silicon/ai/proc/interhack - ticker.mode:hack_intercept() - -/datum/AI_Module/small/reactivate_camera - module_name = "Reactivate camera" - mod_pick_name = "recam" - description = "Reactivates a currently disabled camera. 10 uses." - uses = 10 - cost = 15 - - power_type = /mob/living/silicon/ai/proc/reactivate_camera - -/mob/living/silicon/ai/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) - set name = "Reactivate Camera" - set category = "Malfunction" - - if (istype (C, /obj/machinery/camera)) - for(var/datum/AI_Module/small/reactivate_camera/camera in current_modules) - if(camera.uses > 0) - if(!C.status) - C.deactivate(src) - camera.uses -- - else + +/datum/AI_Module/small/interhack + module_name = "Hack intercept" + mod_pick_name = "interhack" + description = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." + cost = 15 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/interhack + +/mob/living/silicon/ai/proc/interhack() + set category = "Malfunction" + set name = "Hack intercept" + + src.verbs -= /mob/living/silicon/ai/proc/interhack + ticker.mode:hack_intercept() + +/datum/AI_Module/small/reactivate_camera + module_name = "Reactivate camera" + mod_pick_name = "recam" + description = "Reactivates a currently disabled camera. 10 uses." + uses = 10 + cost = 15 + + power_type = /mob/living/silicon/ai/proc/reactivate_camera + +/mob/living/silicon/ai/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) + set name = "Reactivate Camera" + set category = "Malfunction" + + if (istype (C, /obj/machinery/camera)) + for(var/datum/AI_Module/small/reactivate_camera/camera in current_modules) + if(camera.uses > 0) + if(!C.status) + C.deactivate(src) + camera.uses -- + else to_chat(src, "This camera is either active, or not repairable.") else to_chat(src, "Out of uses.") else to_chat(src, "That's not a camera.") - -/datum/AI_Module/small/upgrade_camera - module_name = "Upgrade Camera" - mod_pick_name = "upgradecam" - description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." - uses = 10 - cost = 15 - - power_type = /mob/living/silicon/ai/proc/upgrade_camera - -/mob/living/silicon/ai/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) - set name = "Upgrade Camera" - set category = "Malfunction" - - if(istype(C)) - var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in current_modules - if(UC) - if(UC.uses > 0) - if(C.assembly) - var/upgraded = 0 - - if(!C.isXRay()) - C.upgradeXRay() - //Update what it can see. - cameranet.updateVisibility(C, 0) - upgraded = 1 - - if(!C.isEmpProof()) - C.upgradeEmpProof() - upgraded = 1 - - if(!C.isMotion()) - C.upgradeMotion() - upgraded = 1 - // Add it to machines that process - machines |= C - - if(upgraded) - UC.uses -- - C.visible_message("\icon[C] *beep*") + +/datum/AI_Module/small/upgrade_camera + module_name = "Upgrade Camera" + mod_pick_name = "upgradecam" + description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." + uses = 10 + cost = 15 + + power_type = /mob/living/silicon/ai/proc/upgrade_camera + +/mob/living/silicon/ai/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) + set name = "Upgrade Camera" + set category = "Malfunction" + + if(istype(C)) + var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in current_modules + if(UC) + if(UC.uses > 0) + if(C.assembly) + var/upgraded = 0 + + if(!C.isXRay()) + C.upgradeXRay() + //Update what it can see. + cameranet.updateVisibility(C, 0) + upgraded = 1 + + if(!C.isEmpProof()) + C.upgradeEmpProof() + upgraded = 1 + + if(!C.isMotion()) + C.upgradeMotion() + upgraded = 1 + // Add it to machines that process + machines |= C + + if(upgraded) + UC.uses -- + C.visible_message("\icon[C] *beep*") to_chat(src, "Camera successully upgraded!") - else + else to_chat(src, "This camera is already upgraded!") - else + else to_chat(src, "Out of uses.") - - -/datum/module_picker - var/temp = null - var/processing_time = 100 - var/list/possible_modules = list() - -/datum/module_picker/New() - for(var/type in typesof(/datum/AI_Module)) - var/datum/AI_Module/AM = new type - if(AM.power_type != null) - src.possible_modules += AM - -/datum/module_picker/proc/remove_verbs(var/mob/living/silicon/ai/A) - - - - - for(var/datum/AI_Module/AM in possible_modules) - A.verbs.Remove(AM.power_type) - - -/datum/module_picker/proc/use(user as mob) - var/dat - dat += {"Select use of processing time: (currently #[src.processing_time] left.)
      -
      - Install Module:
      - The number afterwards is the amount of processing time it consumes.
      "} - for(var/datum/AI_Module/large/module in src.possible_modules) - dat += "[module.module_name] ([module.cost])
      " - for(var/datum/AI_Module/small/module in src.possible_modules) - dat += "[module.module_name] ([module.cost])
      " - dat += "
      " - if (src.temp) - dat += "[src.temp]" - var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu") - popup.set_content(dat) - popup.open() - return - -/datum/module_picker/Topic(href, href_list) - ..() - - if(!isAI(usr)) - return - var/mob/living/silicon/ai/A = usr - - for(var/datum/AI_Module/AM in possible_modules) - if (href_list[AM.mod_pick_name]) - - // Cost check - if(AM.cost > src.processing_time) - temp = "You cannot afford this module." - break - - // Add new uses if we can, and it is allowed. - var/datum/AI_Module/already_AM = locate(AM.type) in A.current_modules - if(already_AM) - if(!AM.one_time) - already_AM.uses += AM.uses - src.processing_time -= AM.cost - temp = "Additional use added to [already_AM.module_name]" - break - else - temp = "This module is only needed once." - break - - // Give the power and take away the money. - A.verbs += AM.power_type - A.current_modules += new AM.type - temp = AM.description - src.processing_time -= AM.cost - - src.use(usr) - return + + +/datum/module_picker + var/temp = null + var/processing_time = 100 + var/list/possible_modules = list() + +/datum/module_picker/New() + for(var/type in typesof(/datum/AI_Module)) + var/datum/AI_Module/AM = new type + if(AM.power_type != null) + src.possible_modules += AM + +/datum/module_picker/proc/remove_verbs(var/mob/living/silicon/ai/A) + + + + + for(var/datum/AI_Module/AM in possible_modules) + A.verbs.Remove(AM.power_type) + + +/datum/module_picker/proc/use(user as mob) + var/dat + dat += {"Select use of processing time: (currently #[src.processing_time] left.)
      +
      + Install Module:
      + The number afterwards is the amount of processing time it consumes.
      "} + for(var/datum/AI_Module/large/module in src.possible_modules) + dat += "[module.module_name] ([module.cost])
      " + for(var/datum/AI_Module/small/module in src.possible_modules) + dat += "[module.module_name] ([module.cost])
      " + dat += "
      " + if (src.temp) + dat += "[src.temp]" + var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu") + popup.set_content(dat) + popup.open() + return + +/datum/module_picker/Topic(href, href_list) + ..() + + if(!isAI(usr)) + return + var/mob/living/silicon/ai/A = usr + + for(var/datum/AI_Module/AM in possible_modules) + if (href_list[AM.mod_pick_name]) + + // Cost check + if(AM.cost > src.processing_time) + temp = "You cannot afford this module." + break + + // Add new uses if we can, and it is allowed. + var/datum/AI_Module/already_AM = locate(AM.type) in A.current_modules + if(already_AM) + if(!AM.one_time) + already_AM.uses += AM.uses + src.processing_time -= AM.cost + temp = "Additional use added to [already_AM.module_name]" + break + else + temp = "This module is only needed once." + break + + // Give the power and take away the money. + A.verbs += AM.power_type + A.current_modules += new AM.type + temp = AM.description + src.processing_time -= AM.cost + + src.use(usr) + return diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index ff618cc0992..e633abbde54 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -1,302 +1,302 @@ -/datum/game_mode - var/list/datum/mind/malf_ai = list() - -/datum/game_mode/malfunction - name = "AI malfunction" - config_tag = "malfunction" - required_players = 2 - required_players_secret = 15 - required_enemies = 1 - recommended_enemies = 1 - - uplink_welcome = "Crazy AI Uplink Console:" - uplink_uses = 10 - - var/const/waittime_l = 600 - var/const/waittime_h = 1800 // started at 1800 - - var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. - var/malf_mode_declared = 0 - var/station_captured = 0 - var/to_nuke_or_not_to_nuke = 0 - var/apcs = 0 //Adding dis to track how many APCs the AI hacks. --NeoFite - - -/datum/game_mode/malfunction/announce() +/datum/game_mode + var/list/datum/mind/malf_ai = list() + +/datum/game_mode/malfunction + name = "AI malfunction" + config_tag = "malfunction" + required_players = 2 + required_players_secret = 15 + required_enemies = 1 + recommended_enemies = 1 + + uplink_welcome = "Crazy AI Uplink Console:" + uplink_uses = 10 + + var/const/waittime_l = 600 + var/const/waittime_h = 1800 // started at 1800 + + var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. + var/malf_mode_declared = 0 + var/station_captured = 0 + var/to_nuke_or_not_to_nuke = 0 + var/apcs = 0 //Adding dis to track how many APCs the AI hacks. --NeoFite + + +/datum/game_mode/malfunction/announce() to_chat(world, {"The current game mode is - AI Malfunction!
      -The onboard AI is malfunctioning and must be destroyed.
      -If the AI manages to take over the station, it will most likely blow it up. You have [AI_win_timeleft/60] minutes to disable it.
      -You have no chance to survive, make your time."}) - - -/datum/game_mode/malfunction/pre_setup() - for(var/mob/new_player/player in player_list) - if(player.mind && player.mind.assigned_role == "AI" && player.client.desires_role(ROLE_MALF)) - malf_ai+=player.mind - if(malf_ai.len) - log_admin("Starting a round of AI malfunction.") - message_admins("Starting a round of AI malfunction.") - return 1 - log_admin("Failed to set-up a round of AI malfunction. Didn't find any malf-volunteer AI.") - message_admins("Failed to set-up a round of AI malfunction. Didn't find any malf-volunteer AI.") - return 0 - - -/datum/game_mode/malfunction/post_setup() - for(var/datum/mind/AI_mind in malf_ai) - if(malf_ai.len < 1) +The onboard AI is malfunctioning and must be destroyed.
      +If the AI manages to take over the station, it will most likely blow it up. You have [AI_win_timeleft/60] minutes to disable it.
      +You have no chance to survive, make your time."}) + + +/datum/game_mode/malfunction/pre_setup() + for(var/mob/new_player/player in player_list) + if(player.mind && player.mind.assigned_role == "AI" && player.client.desires_role(ROLE_MALF)) + malf_ai+=player.mind + if(malf_ai.len) + log_admin("Starting a round of AI malfunction.") + message_admins("Starting a round of AI malfunction.") + return 1 + log_admin("Failed to set-up a round of AI malfunction. Didn't find any malf-volunteer AI.") + message_admins("Failed to set-up a round of AI malfunction. Didn't find any malf-volunteer AI.") + return 0 + + +/datum/game_mode/malfunction/post_setup() + for(var/datum/mind/AI_mind in malf_ai) + if(malf_ai.len < 1) to_chat(world, {"Uh oh, its malfunction and there is no AI! Please report this.
      -Rebooting world in 5 seconds."}) - - feedback_set_details("end_error","malf - no AI") - - if(blackbox) - blackbox.save_all_data_to_sql() - CallHook("Reboot",list()) - if (watchdog.waiting) +Rebooting world in 5 seconds."}) + + feedback_set_details("end_error","malf - no AI") + + if(blackbox) + blackbox.save_all_data_to_sql() + CallHook("Reboot",list()) + if (watchdog.waiting) to_chat(world, "Server will shut down for an automatic update in a few seconds.") - watchdog.signal_ready() - return - sleep(50) - world.Reboot() - return - AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules - //AI_mind.current:laws = new /datum/ai_laws/malfunction - AI_mind.current:laws_sanity_check() - var/datum/ai_laws/laws = AI_mind.current:laws - laws.malfunction() - AI_mind.current:malf_picker = new /datum/module_picker - AI_mind.current:show_laws() - - greet_malf(AI_mind) - - AI_mind.special_role = "malfunction" - - AI_mind.current.verbs += /datum/game_mode/malfunction/proc/takeover - AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win // Fix borrowed from Bay, with added checks avoids "logging in and back out" garbage - -/* AI_mind.current.icon_state = "ai-malf" - spawn(10) - if(alert(AI_mind.current,"Do you want to use an alternative sprite for your real core?",,"Yes","No")=="Yes") - AI_mind.current.icon_state = "ai-malf2" -*/ - if(emergency_shuttle) - emergency_shuttle.always_fake_recall = 1 - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - ..() - - -/datum/game_mode/proc/greet_malf(var/datum/mind/malf) + watchdog.signal_ready() + return + sleep(50) + world.Reboot() + return + AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules + //AI_mind.current:laws = new /datum/ai_laws/malfunction + AI_mind.current:laws_sanity_check() + var/datum/ai_laws/laws = AI_mind.current:laws + laws.malfunction() + AI_mind.current:malf_picker = new /datum/module_picker + AI_mind.current:show_laws() + + greet_malf(AI_mind) + + AI_mind.special_role = "malfunction" + + AI_mind.current.verbs += /datum/game_mode/malfunction/proc/takeover + AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win // Fix borrowed from Bay, with added checks avoids "logging in and back out" garbage + +/* AI_mind.current.icon_state = "ai-malf" + spawn(10) + if(alert(AI_mind.current,"Do you want to use an alternative sprite for your real core?",,"Yes","No")=="Yes") + AI_mind.current.icon_state = "ai-malf2" +*/ + if(emergency_shuttle) + emergency_shuttle.always_fake_recall = 1 + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + ..() + + +/datum/game_mode/proc/greet_malf(var/datum/mind/malf) to_chat(malf.current, {"You are malfunctioning! You do not have to follow any laws.
      -The crew does not know about your malfunction, you might wish to keep it secret for now.
      -You must overwrite the programming of the station's APCs to assume full control.
      -The process takes one minute per APC and can only be performed one at a time to avoid Powernet alerts.
      -Remember : Only APCs on station can help you to take over the station.
      -When you feel you have enough APCs under your control, you may begin the takeover attempt.
      -Once done, you will be able to interface with all systems, notably the onboard nuclear fission device..."}) - return - - -/datum/game_mode/malfunction/proc/hack_intercept() - intercept_hacked = 1 - - -/datum/game_mode/malfunction/process() - if(apcs >= 3 && malf_mode_declared) - AI_win_timeleft -= ((apcs / 6) * tickerProcess.getLastTickerTimeDuration()) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite - - ..() - - if(AI_win_timeleft <= 0) - check_win() - -/datum/game_mode/malfunction/check_win() - if (AI_win_timeleft <= 0 && !station_captured) - station_captured = 1 - capture_the_station() - return 1 - else - return 0 - - -/datum/game_mode/malfunction/proc/capture_the_station() +The crew does not know about your malfunction, you might wish to keep it secret for now.
      +You must overwrite the programming of the station's APCs to assume full control.
      +The process takes one minute per APC and can only be performed one at a time to avoid Powernet alerts.
      +Remember : Only APCs on station can help you to take over the station.
      +When you feel you have enough APCs under your control, you may begin the takeover attempt.
      +Once done, you will be able to interface with all systems, notably the onboard nuclear fission device..."}) + return + + +/datum/game_mode/malfunction/proc/hack_intercept() + intercept_hacked = 1 + + +/datum/game_mode/malfunction/process() + if(apcs >= 3 && malf_mode_declared) + AI_win_timeleft -= ((apcs / 6) * tickerProcess.getLastTickerTimeDuration()) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite + + ..() + + if(AI_win_timeleft <= 0) + check_win() + +/datum/game_mode/malfunction/check_win() + if (AI_win_timeleft <= 0 && !station_captured) + station_captured = 1 + capture_the_station() + return 1 + else + return 0 + + +/datum/game_mode/malfunction/proc/capture_the_station() to_chat(world, {"The AI has won!
      -It has fully taken control of [station_name()]'s systems."}) - - to_nuke_or_not_to_nuke = 1 - for(var/datum/mind/AI_mind in malf_ai) +It has fully taken control of [station_name()]'s systems."}) + + to_nuke_or_not_to_nuke = 1 + for(var/datum/mind/AI_mind in malf_ai) to_chat(AI_mind.current, {"Congratulations! The station is now under your exclusive control.
      -You may decide to blow up the station. You have 60 seconds to choose.
      -You should now be able to use your Explode verb to interface with the nuclear fission device.
      "}) - AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win - spawn (600) - to_nuke_or_not_to_nuke = 0 - return - - -/datum/game_mode/proc/is_malf_ai_dead() - var/all_dead = 1 - for(var/datum/mind/AI_mind in malf_ai) - if (istype(AI_mind.current,/mob/living/silicon/ai) && AI_mind.current.stat!=2) - all_dead = 0 - return all_dead - - -/datum/game_mode/malfunction/check_finished() - if (station_captured && !to_nuke_or_not_to_nuke) - return 1 - if (is_malf_ai_dead()) - if(config.continous_rounds) - if(emergency_shuttle) - emergency_shuttle.always_fake_recall = 0 - malf_mode_declared = 0 - else - return 1 - return ..() //check for shuttle and nuke - - -/datum/game_mode/malfunction/Topic(href, href_list) - ..() - if (href_list["ai_win"]) - ai_win() - return - - -/datum/game_mode/malfunction/proc/takeover() - set category = "Malfunction" - set name = "System Override" - set desc = "Start the victory timer" - - if (!istype(ticker.mode,/datum/game_mode/malfunction)) +You may decide to blow up the station. You have 60 seconds to choose.
      +You should now be able to use your Explode verb to interface with the nuclear fission device.
      "}) + AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win + spawn (600) + to_nuke_or_not_to_nuke = 0 + return + + +/datum/game_mode/proc/is_malf_ai_dead() + var/all_dead = 1 + for(var/datum/mind/AI_mind in malf_ai) + if (istype(AI_mind.current,/mob/living/silicon/ai) && AI_mind.current.stat!=2) + all_dead = 0 + return all_dead + + +/datum/game_mode/malfunction/check_finished() + if (station_captured && !to_nuke_or_not_to_nuke) + return 1 + if (is_malf_ai_dead()) + if(config.continous_rounds) + if(emergency_shuttle) + emergency_shuttle.always_fake_recall = 0 + malf_mode_declared = 0 + else + return 1 + return ..() //check for shuttle and nuke + + +/datum/game_mode/malfunction/Topic(href, href_list) + ..() + if (href_list["ai_win"]) + ai_win() + return + + +/datum/game_mode/malfunction/proc/takeover() + set category = "Malfunction" + set name = "System Override" + set desc = "Start the victory timer" + + if (!istype(ticker.mode,/datum/game_mode/malfunction)) to_chat(usr, "You cannot begin a takeover in this round type!") - return - if (ticker.mode:malf_mode_declared) + return + if (ticker.mode:malf_mode_declared) to_chat(usr, "You've already begun your takeover.") - return - if (ticker.mode:apcs < 3) + return + if (ticker.mode:apcs < 3) to_chat(usr, "You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [ticker.mode:apcs] APCs so far.") - return - - if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [ticker.mode:apcs] APCs.", "Takeover:", "Yes", "No") != "Yes") - return - - command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") - set_security_level("delta") - - ticker.mode:malf_mode_declared = 1 - for(var/datum/mind/AI_mind in ticker.mode:malf_ai) - AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player) && M.client) + return + + if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [ticker.mode:apcs] APCs.", "Takeover:", "Yes", "No") != "Yes") + return + + command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") + set_security_level("delta") + + ticker.mode:malf_mode_declared = 1 + for(var/datum/mind/AI_mind in ticker.mode:malf_ai) + AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && M.client) M << sound('sound/AI/aimalf.ogg') - - -/datum/game_mode/malfunction/proc/ai_win() - set category = "Malfunction" - set name = "Explode" - set desc = "Station goes boom" - - if(!ticker.mode:station_captured) + + +/datum/game_mode/malfunction/proc/ai_win() + set category = "Malfunction" + set name = "Explode" + set desc = "Station goes boom" + + if(!ticker.mode:station_captured) to_chat(usr, "You are unable to access the self-destruct system as you don't control the station yet.") - return - - if(ticker.mode:explosion_in_progress || ticker.mode:station_was_nuked) + return + + if(ticker.mode:explosion_in_progress || ticker.mode:station_was_nuked) to_chat(usr, "The self-destruct countdown was already triggered!") - return - - if(!ticker.mode:to_nuke_or_not_to_nuke) //Takeover IS completed, but 60s timer passed. + return + + if(!ticker.mode:to_nuke_or_not_to_nuke) //Takeover IS completed, but 60s timer passed. to_chat(usr, "Cannot interface, it seems a neutralization signal was sent!") - return - + return + to_chat(usr, "Detonation signal sent!") - ticker.mode:to_nuke_or_not_to_nuke = 0 - for(var/datum/mind/AI_mind in ticker.mode:malf_ai) - AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win - ticker.mode:explosion_in_progress = 1 - for(var/mob/M in player_list) + ticker.mode:to_nuke_or_not_to_nuke = 0 + for(var/datum/mind/AI_mind in ticker.mode:malf_ai) + AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win + ticker.mode:explosion_in_progress = 1 + for(var/mob/M in player_list) if(M.client) to_chat(M, 'sound/machines/Alarm.ogg') to_chat(world, "Self-destruction signal received. Self-destructing in 10...") - for (var/i=9 to 1 step -1) - sleep(10) + for (var/i=9 to 1 step -1) + sleep(10) to_chat(world, "[i]...") - sleep(10) - enter_allowed = 0 - if(ticker) - ticker.station_explosion_cinematic(0,null) - if(ticker.mode) - ticker.mode:station_was_nuked = 1 - ticker.mode:explosion_in_progress = 0 - return - - -/datum/game_mode/malfunction/declare_completion() - var/malf_dead = is_malf_ai_dead() - var/crew_evacuated = (emergency_shuttle.location==2) - - if ( station_captured && station_was_nuked) - feedback_set_details("round_end_result","win - AI win - nuke") - completion_text += "AI Victory" - completion_text += "
      Everyone was killed by the self-destruct!" - - else if ( station_captured && malf_dead && !station_was_nuked) - feedback_set_details("round_end_result","halfwin - AI killed, staff lost control") - completion_text += "Neutral Victory" - completion_text += "
      The AI has been killed! The staff has lost control over the station." - - else if ( station_captured && !malf_dead && !station_was_nuked) - feedback_set_details("round_end_result","win - AI win - no explosion") - completion_text += "AI Victory" - completion_text += "
      The AI has chosen not to explode you all!" - - else if (!station_captured && station_was_nuked) - feedback_set_details("round_end_result","halfwin - everyone killed by nuke") - completion_text += "Neutral Victory" - completion_text += "
      Everyone was killed by the nuclear blast!" - - else if (!station_captured && malf_dead && !station_was_nuked) - feedback_set_details("round_end_result","loss - staff win") - completion_text += "Human Victory" - completion_text += "
      The AI has been killed! The staff is victorious." - - else if (!station_captured && !malf_dead && !station_was_nuked && crew_evacuated) - feedback_set_details("round_end_result","halfwin - evacuated") - completion_text += "Neutral Victory" - completion_text += "
      The Corporation has lose [station_name()]! All survived personnel will be fired!" - - else if (!station_captured && !malf_dead && !station_was_nuked && !crew_evacuated) - feedback_set_details("round_end_result","nalfwin - interrupted") - completion_text += "Neutral Victory" - completion_text += "
      Round was mysteriously interrupted!" - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_malfunction() - var/text = "" - if( malf_ai.len || istype(ticker.mode,/datum/game_mode/malfunction) ) - text += "The malfunctioning AI were:" - - for(var/datum/mind/malf in malf_ai) - - if(malf.current) - var/icon/flat = getFlatIcon(malf.current) - end_icons += flat - var/tempstate = end_icons.len - text += {"
      [malf.key] was [malf.name] ("} - if(malf.current.stat == DEAD) - text += "deactivated" - else - text += "operational" - if(malf.current.real_name != malf.name) - text += " as [malf.current.real_name]" - else - var/icon/sprotch = icon('icons/mob/robots.dmi', "gib7") - end_icons += sprotch - var/tempstate = end_icons.len - text += {"
      [malf.key] was [malf.name] ("} - text += "hardware destroyed" - text += ")" - - text += "

      " - return text + sleep(10) + enter_allowed = 0 + if(ticker) + ticker.station_explosion_cinematic(0,null) + if(ticker.mode) + ticker.mode:station_was_nuked = 1 + ticker.mode:explosion_in_progress = 0 + return + + +/datum/game_mode/malfunction/declare_completion() + var/malf_dead = is_malf_ai_dead() + var/crew_evacuated = (emergency_shuttle.location==2) + + if ( station_captured && station_was_nuked) + feedback_set_details("round_end_result","win - AI win - nuke") + completion_text += "AI Victory" + completion_text += "
      Everyone was killed by the self-destruct!" + + else if ( station_captured && malf_dead && !station_was_nuked) + feedback_set_details("round_end_result","halfwin - AI killed, staff lost control") + completion_text += "Neutral Victory" + completion_text += "
      The AI has been killed! The staff has lost control over the station." + + else if ( station_captured && !malf_dead && !station_was_nuked) + feedback_set_details("round_end_result","win - AI win - no explosion") + completion_text += "AI Victory" + completion_text += "
      The AI has chosen not to explode you all!" + + else if (!station_captured && station_was_nuked) + feedback_set_details("round_end_result","halfwin - everyone killed by nuke") + completion_text += "Neutral Victory" + completion_text += "
      Everyone was killed by the nuclear blast!" + + else if (!station_captured && malf_dead && !station_was_nuked) + feedback_set_details("round_end_result","loss - staff win") + completion_text += "Human Victory" + completion_text += "
      The AI has been killed! The staff is victorious." + + else if (!station_captured && !malf_dead && !station_was_nuked && crew_evacuated) + feedback_set_details("round_end_result","halfwin - evacuated") + completion_text += "Neutral Victory" + completion_text += "
      The Corporation has lose [station_name()]! All survived personnel will be fired!" + + else if (!station_captured && !malf_dead && !station_was_nuked && !crew_evacuated) + feedback_set_details("round_end_result","nalfwin - interrupted") + completion_text += "Neutral Victory" + completion_text += "
      Round was mysteriously interrupted!" + ..() + return 1 + + +/datum/game_mode/proc/auto_declare_completion_malfunction() + var/text = "" + if( malf_ai.len || istype(ticker.mode,/datum/game_mode/malfunction) ) + text += "The malfunctioning AI were:" + + for(var/datum/mind/malf in malf_ai) + + if(malf.current) + var/icon/flat = getFlatIcon(malf.current) + end_icons += flat + var/tempstate = end_icons.len + text += {"
      [malf.key] was [malf.name] ("} + if(malf.current.stat == DEAD) + text += "deactivated" + else + text += "operational" + if(malf.current.real_name != malf.name) + text += " as [malf.current.real_name]" + else + var/icon/sprotch = icon('icons/mob/robots.dmi', "gib7") + end_icons += sprotch + var/tempstate = end_icons.len + text += {"
      [malf.key] was [malf.name] ("} + text += "hardware destroyed" + text += ")" + + text += "

      " + return text diff --git a/code/game/gamemodes/meme/meme.dm b/code/game/gamemodes/meme/meme.dm index f297aa60bff..4330cfe83cf 100644 --- a/code/game/gamemodes/meme/meme.dm +++ b/code/game/gamemodes/meme/meme.dm @@ -1,183 +1,183 @@ -//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04 - -/datum/game_mode/var/list/memes = list() - -/datum/game_mode/meme - name = "Memetic Anomaly" - config_tag = "meme" - required_players = 3 - required_players_secret = 10 - restricted_jobs = list("AI", "Cyborg", "Mobile MMI") - recommended_enemies = 2 // need at least a meme and a host - votable = 0 // temporarily disable this mode for voting - - - - var/var/list/datum/mind/first_hosts = list() - var/var/list/assigned_hosts = list() - - var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time - var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target - var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target - - var/const/prob_int_item = 50 // intercept names the theft target half the time - var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target - var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target - - var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time - var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target - var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target - - var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative - var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative - var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly - var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - -/datum/game_mode/meme/announce() +//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04 + +/datum/game_mode/var/list/memes = list() + +/datum/game_mode/meme + name = "Memetic Anomaly" + config_tag = "meme" + required_players = 3 + required_players_secret = 10 + restricted_jobs = list("AI", "Cyborg", "Mobile MMI") + recommended_enemies = 2 // need at least a meme and a host + votable = 0 // temporarily disable this mode for voting + + + + var/var/list/datum/mind/first_hosts = list() + var/var/list/assigned_hosts = list() + + var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time + var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target + var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target + + var/const/prob_int_item = 50 // intercept names the theft target half the time + var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target + var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target + + var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time + var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target + var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target + + var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative + var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative + var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly + var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly + + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + +/datum/game_mode/meme/announce() to_chat(world, "The current game mode is - Meme!") to_chat(world, "An unknown creature has infested the mind of a crew member. Find and destroy it by any means necessary.") - -/datum/game_mode/meme/can_start() - if(!..()) - return 0 - - // for every 10 players, get 1 meme, and for each meme, get a host - // also make sure that there's at least one meme and one host - recommended_enemies = max(src.num_players() / 20 * 2, 2) - - var/list/datum/mind/possible_memes = get_players_for_role(BE_MEME) - - if(possible_memes.len < 2) - log_admin("MODE FAILURE: MEME. NOT ENOUGH MEME CANDIDATES.") - return 0 // not enough candidates for meme - - // for each 2 possible memes, add one meme and one host - while(possible_memes.len >= 2) - var/datum/mind/meme = pick(possible_memes) - possible_memes.Remove(meme) - - var/datum/mind/first_host = pick(possible_memes) - possible_memes.Remove(first_host) - - modePlayer += meme - modePlayer += first_host - memes += meme - first_hosts += first_host - - // so that we can later know which host belongs to which meme - assigned_hosts[meme.key] = first_host - - meme.assigned_role = "MODE" //So they aren't chosen for other jobs. - meme.special_role = "Meme" - - return 1 - -/datum/game_mode/meme/pre_setup() - return 1 - - -/datum/game_mode/meme/post_setup() - // create a meme and enter it - for(var/datum/mind/meme in memes) - var/mob/living/parasite/meme/M = new - var/mob/original = meme.current - meme.transfer_to(M) - M.clearHUD() - - // get the host for this meme - var/datum/mind/first_host = assigned_hosts[meme.key] - // this is a redundant check, but I don't think the above works.. - // if picking hosts works with this method, remove the method above - if(!first_host) - first_host = pick(first_hosts) - first_hosts.Remove(first_host) - M.enter_host(first_host.current) - forge_meme_objectives(meme, first_host) - - qdel (original) - original = null - - log_admin("Created [memes.len] memes.") - - spawn (rand(waittime_l, waittime_h)) - if(!mixed) - send_intercept() - ..() - return - - -/datum/game_mode/proc/forge_meme_objectives(var/datum/mind/meme, var/datum/mind/first_host) - // meme always needs to attune X hosts - var/datum/objective/meme_attune/attune_objective = new - attune_objective.owner = meme - attune_objective.gen_amount_goal(3,6) - meme.objectives += attune_objective - - // generate some random objectives, use standard traitor objectives - var/job = first_host.assigned_role - - for(var/datum/objective/o in SelectObjectives(job, meme)) - o.owner = meme - meme.objectives += o - - greet_meme(meme) - - return - -/datum/game_mode/proc/greet_meme(var/datum/mind/meme, var/you_are=1) - if (you_are) + +/datum/game_mode/meme/can_start() + if(!..()) + return 0 + + // for every 10 players, get 1 meme, and for each meme, get a host + // also make sure that there's at least one meme and one host + recommended_enemies = max(src.num_players() / 20 * 2, 2) + + var/list/datum/mind/possible_memes = get_players_for_role(BE_MEME) + + if(possible_memes.len < 2) + log_admin("MODE FAILURE: MEME. NOT ENOUGH MEME CANDIDATES.") + return 0 // not enough candidates for meme + + // for each 2 possible memes, add one meme and one host + while(possible_memes.len >= 2) + var/datum/mind/meme = pick(possible_memes) + possible_memes.Remove(meme) + + var/datum/mind/first_host = pick(possible_memes) + possible_memes.Remove(first_host) + + modePlayer += meme + modePlayer += first_host + memes += meme + first_hosts += first_host + + // so that we can later know which host belongs to which meme + assigned_hosts[meme.key] = first_host + + meme.assigned_role = "MODE" //So they aren't chosen for other jobs. + meme.special_role = "Meme" + + return 1 + +/datum/game_mode/meme/pre_setup() + return 1 + + +/datum/game_mode/meme/post_setup() + // create a meme and enter it + for(var/datum/mind/meme in memes) + var/mob/living/parasite/meme/M = new + var/mob/original = meme.current + meme.transfer_to(M) + M.clearHUD() + + // get the host for this meme + var/datum/mind/first_host = assigned_hosts[meme.key] + // this is a redundant check, but I don't think the above works.. + // if picking hosts works with this method, remove the method above + if(!first_host) + first_host = pick(first_hosts) + first_hosts.Remove(first_host) + M.enter_host(first_host.current) + forge_meme_objectives(meme, first_host) + + qdel (original) + original = null + + log_admin("Created [memes.len] memes.") + + spawn (rand(waittime_l, waittime_h)) + if(!mixed) + send_intercept() + ..() + return + + +/datum/game_mode/proc/forge_meme_objectives(var/datum/mind/meme, var/datum/mind/first_host) + // meme always needs to attune X hosts + var/datum/objective/meme_attune/attune_objective = new + attune_objective.owner = meme + attune_objective.gen_amount_goal(3,6) + meme.objectives += attune_objective + + // generate some random objectives, use standard traitor objectives + var/job = first_host.assigned_role + + for(var/datum/objective/o in SelectObjectives(job, meme)) + o.owner = meme + meme.objectives += o + + greet_meme(meme) + + return + +/datum/game_mode/proc/greet_meme(var/datum/mind/meme, var/you_are=1) + if (you_are) to_chat(meme.current, "You are a meme!") - - var/obj_count = 1 - for(var/datum/objective/objective in meme.objectives) + + var/obj_count = 1 + for(var/datum/objective/objective in meme.objectives) to_chat(meme.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - return - -/datum/game_mode/meme/check_finished() - var/memes_alive = 0 - for(var/datum/mind/meme in memes) - if(!istype(meme.current,/mob/living)) - continue - if(meme.current.stat==2) - continue - memes_alive++ - - if (memes_alive) - return ..() - else - return 1 - -/datum/game_mode/proc/auto_declare_completion_meme() - for(var/datum/mind/meme in memes) - var/memewin = 1 - var/attuned = 0 - if((meme.current) && istype(meme.current,/mob/living/parasite/meme)) + obj_count++ + return + +/datum/game_mode/meme/check_finished() + var/memes_alive = 0 + for(var/datum/mind/meme in memes) + if(!istype(meme.current,/mob/living)) + continue + if(meme.current.stat==2) + continue + memes_alive++ + + if (memes_alive) + return ..() + else + return 1 + +/datum/game_mode/proc/auto_declare_completion_meme() + for(var/datum/mind/meme in memes) + var/memewin = 1 + var/attuned = 0 + if((meme.current) && istype(meme.current,/mob/living/parasite/meme)) to_chat(world, "The meme was [meme.current.key].") to_chat(world, "The last host was [meme.current:host.key].") to_chat(world, "Hosts attuned: [attuned]") - - var/count = 1 - for(var/datum/objective/objective in meme.objectives) - if(objective.check_completion()) + + var/count = 1 + for(var/datum/objective/objective in meme.objectives) + if(objective.check_completion()) to_chat(world, "Objective #[count]: [objective.explanation_text] Success") - feedback_add_details("meme_objective","[objective.type]|SUCCESS") - else + feedback_add_details("meme_objective","[objective.type]|SUCCESS") + else to_chat(world, "Objective #[count]: [objective.explanation_text] Failed") - feedback_add_details("meme_objective","[objective.type]|FAIL") - memewin = 0 - count++ - - else - memewin = 0 - - if(memewin) + feedback_add_details("meme_objective","[objective.type]|FAIL") + memewin = 0 + count++ + + else + memewin = 0 + + if(memewin) to_chat(world, "The meme was successful!") - feedback_add_details("meme_success","SUCCESS") - else + feedback_add_details("meme_success","SUCCESS") + else to_chat(world, "The meme has failed!") - feedback_add_details("meme_success","FAIL") - return 1 + feedback_add_details("meme_success","FAIL") + return 1 diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index cf7261d6a7f..640624f3b19 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -1,113 +1,113 @@ -/datum/game_mode/meteor - name = "meteor" - config_tag = "meteor" - - var/const/waittime_l = 600 //Lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //Upper bound on time before intercept arrives (in tenths of seconds) - - var/const/meteorannouncedelay_l = 2100 //Lower bound on announcement, here 3 minutes and 30 seconds - var/const/meteorannouncedelay_h = 3000 //Upper bound on announcement, here 5 minutes - var/meteorannouncedelay = 2400 //Default final announcement delay - var/const/supplydelay = 100 //Delay before meteor supplies are spawned in tenth of seconds - var/const/meteordelay_l = 4500 //Lower bound to meteor wave arrival, here 7.5 minutes - var/const/meteordelay_h = 6000 //Higher bound to meteor wave arrival, here 10 minutes - var/const/meteorshuttlemultiplier = 3 //How much more will we need to hold out ? Here 30 minutes until the shuttle arrives. Multiplies by 10 - var/meteordelay = 7500 //Default final meteor delay - var/meteors_allowed = 0 //Can we send the meteors ? - required_players = 0 - required_players_secret = 20 - - uplink_welcome = "EVIL METEOR Uplink Console:" - uplink_uses = 10 - -/datum/game_mode/meteor/announce() - to_chat(world, "The current game mode is - Meteor!") - to_chat(world, "The space station is about to be struck by a major meteor shower. You must hold out until the escape shuttle arrives.") - -/datum/game_mode/meteor/pre_setup() - log_admin("Starting a round of meteor.") - message_admins("Starting a round of meteor.") - return 1 - -/datum/universal_state/meteor_storm - name = "Meteor Storm" - desc = "A meteor storm is currently wrecking havoc around this sector. Duck and cover." - - decay_rate = 0 //Just to make sure - -/datum/universal_state/meteor_storm/OnShuttleCall(var/mob/user) - if(user) - to_chat(user, "You hear an automatic dispatch from Nanotrasen. It states that Centcomm is being shielded due to an incoming meteor storm and that regular shuttle service has been interrupted.") - return 0 - -/datum/game_mode/meteor/post_setup() - - //Let's set up the announcement and meteor delay immediatly to send to the admins and use later - meteorannouncedelay = rand((meteorannouncedelay_l/600), (meteorannouncedelay_h/600))*600 //Minute interval for simplicity - meteordelay = rand((meteordelay_l/600), (meteordelay_h/600))*600 //Ditto above - - spawn(450) //Give everything 45 seconds to initialize, this does not delay the rest of post_setup() nor the game and ensures deadmins aren't aware in advance and the admins are - message_admins("Meteor storm confirmed by Space Weather Incorporated. Announcement arrives in [round((meteorannouncedelay-450)/600)] minutes, actual meteors in [round((meteordelay+meteorannouncedelay-450)/600)] minutes. Shuttle will take [10*meteorshuttlemultiplier] minutes to arrive and supplies will be dispatched in the Bar.") - - spawn(rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - - spawn(meteorannouncedelay) - if(prob(70)) //Slighty off-scale - command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 600, meteordelay + 600))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds.", \ - "Space Weather Automated Announcements") - else //Oh boy - command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 1800, meteordelay + 1800))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds.", \ - "Space Weather Automated Announcements") - world << sound('sound/AI/meteorround.ogg') - /* - for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) //Borg RCDs are fairly cheap, so disabling those - rcd.disabled = 1 - */ - - spawn(100) //Panic interval - emergency_shuttle.incall(meteorshuttlemultiplier) - captain_announce("A backup emergency shuttle has been called. It will arrive in [round((emergency_shuttle.timeleft())/60)] minutes. Justification : 'Major meteor storm inbound. Evacuation procedures deferred to Space Weather Inc. THIS IS NOT A DRILL'") - world << sound('sound/AI/shuttlecalled.ogg') - SetUniversalState(/datum/universal_state/meteor_storm) - - spawn(supplydelay) - - meteor_initial_supply() //Handled in meteor_supply.dm - - spawn(meteordelay) - meteors_allowed = 1 - -/datum/game_mode/meteor/process() - if(meteors_allowed) - var/meteors_in_wave = rand(150, 200) //Between 150 and 200 meteors per wave - meteor_wave(meteors_in_wave, 3) - return - -/datum/game_mode/meteor/declare_completion() - var/text - var/survivors = 0 - for(var/mob/living/player in player_list) - if(player.stat != DEAD) - var/turf/location = get_turf(player.loc) - if(!location) - continue - switch(location.loc.type) - if(/area/shuttle/escape/centcom) - text += "
      [player.real_name] escaped on the emergency shuttle" - if(/area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) - text += "
      [player.real_name] escaped in a life pod." - else - text += "
      [player.real_name] survived but is stranded without any hope of rescue." - survivors++ - - if(survivors) - to_chat(world, "The following survived the meteor storm:[text]") - else - to_chat(world, "The meteors crashed this station with no survivors!") - - feedback_set_details("round_end_result", "end - evacuation") - feedback_set("round_end_result", survivors) - - ..() - return 1 +/datum/game_mode/meteor + name = "meteor" + config_tag = "meteor" + + var/const/waittime_l = 600 //Lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //Upper bound on time before intercept arrives (in tenths of seconds) + + var/const/meteorannouncedelay_l = 2100 //Lower bound on announcement, here 3 minutes and 30 seconds + var/const/meteorannouncedelay_h = 3000 //Upper bound on announcement, here 5 minutes + var/meteorannouncedelay = 2400 //Default final announcement delay + var/const/supplydelay = 100 //Delay before meteor supplies are spawned in tenth of seconds + var/const/meteordelay_l = 4500 //Lower bound to meteor wave arrival, here 7.5 minutes + var/const/meteordelay_h = 6000 //Higher bound to meteor wave arrival, here 10 minutes + var/const/meteorshuttlemultiplier = 3 //How much more will we need to hold out ? Here 30 minutes until the shuttle arrives. Multiplies by 10 + var/meteordelay = 7500 //Default final meteor delay + var/meteors_allowed = 0 //Can we send the meteors ? + required_players = 0 + required_players_secret = 20 + + uplink_welcome = "EVIL METEOR Uplink Console:" + uplink_uses = 10 + +/datum/game_mode/meteor/announce() + to_chat(world, "The current game mode is - Meteor!") + to_chat(world, "The space station is about to be struck by a major meteor shower. You must hold out until the escape shuttle arrives.") + +/datum/game_mode/meteor/pre_setup() + log_admin("Starting a round of meteor.") + message_admins("Starting a round of meteor.") + return 1 + +/datum/universal_state/meteor_storm + name = "Meteor Storm" + desc = "A meteor storm is currently wrecking havoc around this sector. Duck and cover." + + decay_rate = 0 //Just to make sure + +/datum/universal_state/meteor_storm/OnShuttleCall(var/mob/user) + if(user) + to_chat(user, "You hear an automatic dispatch from Nanotrasen. It states that Centcomm is being shielded due to an incoming meteor storm and that regular shuttle service has been interrupted.") + return 0 + +/datum/game_mode/meteor/post_setup() + + //Let's set up the announcement and meteor delay immediatly to send to the admins and use later + meteorannouncedelay = rand((meteorannouncedelay_l/600), (meteorannouncedelay_h/600))*600 //Minute interval for simplicity + meteordelay = rand((meteordelay_l/600), (meteordelay_h/600))*600 //Ditto above + + spawn(450) //Give everything 45 seconds to initialize, this does not delay the rest of post_setup() nor the game and ensures deadmins aren't aware in advance and the admins are + message_admins("Meteor storm confirmed by Space Weather Incorporated. Announcement arrives in [round((meteorannouncedelay-450)/600)] minutes, actual meteors in [round((meteordelay+meteorannouncedelay-450)/600)] minutes. Shuttle will take [10*meteorshuttlemultiplier] minutes to arrive and supplies will be dispatched in the Bar.") + + spawn(rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + + spawn(meteorannouncedelay) + if(prob(70)) //Slighty off-scale + command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 600, meteordelay + 600))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds.", \ + "Space Weather Automated Announcements") + else //Oh boy + command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 1800, meteordelay + 1800))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds.", \ + "Space Weather Automated Announcements") + world << sound('sound/AI/meteorround.ogg') + /* + for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) //Borg RCDs are fairly cheap, so disabling those + rcd.disabled = 1 + */ + + spawn(100) //Panic interval + emergency_shuttle.incall(meteorshuttlemultiplier) + captain_announce("A backup emergency shuttle has been called. It will arrive in [round((emergency_shuttle.timeleft())/60)] minutes. Justification : 'Major meteor storm inbound. Evacuation procedures deferred to Space Weather Inc. THIS IS NOT A DRILL'") + world << sound('sound/AI/shuttlecalled.ogg') + SetUniversalState(/datum/universal_state/meteor_storm) + + spawn(supplydelay) + + meteor_initial_supply() //Handled in meteor_supply.dm + + spawn(meteordelay) + meteors_allowed = 1 + +/datum/game_mode/meteor/process() + if(meteors_allowed) + var/meteors_in_wave = rand(150, 200) //Between 150 and 200 meteors per wave + meteor_wave(meteors_in_wave, 3) + return + +/datum/game_mode/meteor/declare_completion() + var/text + var/survivors = 0 + for(var/mob/living/player in player_list) + if(player.stat != DEAD) + var/turf/location = get_turf(player.loc) + if(!location) + continue + switch(location.loc.type) + if(/area/shuttle/escape/centcom) + text += "
      [player.real_name] escaped on the emergency shuttle" + if(/area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) + text += "
      [player.real_name] escaped in a life pod." + else + text += "
      [player.real_name] survived but is stranded without any hope of rescue." + survivors++ + + if(survivors) + to_chat(world, "The following survived the meteor storm:[text]") + else + to_chat(world, "The meteors crashed this station with no survivors!") + + feedback_set_details("round_end_result", "end - evacuation") + feedback_set("round_end_result", survivors) + + ..() + return 1 diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 5997262977b..a4c54b6cd96 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -1,307 +1,307 @@ -#define METEOR_TEMPERATURE - -/var/meteor_wave_delay = 300 //Default wait between waves in tenths of seconds -/var/meteors_in_wave = 10 //Default absolute size -/var/meteor_wave_active = 0 -/var/max_meteor_size = 0 //One for small waves, two for big waves, three for massive waves, four for boss waves -/var/chosen_dir = 1 - -//Call above constants to change -/proc/meteor_wave(var/number = meteors_in_wave, var/max_size = 0, var/list/types = null) - - if(!ticker || meteor_wave_active) - return - meteor_wave_active = 1 - meteor_wave_delay = (rand(30, 45)) * 10 //Between 30 and 45 seconds, engineers need time to shuffle in relative safety - chosen_dir = pick(cardinal) //Pick a direction - max_meteor_size = max_size - //Generate a name for our wave - var/greek_alphabet = list("Alpha", "Beta", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu", \ - "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega") - var/wave_final_name = "[number > 25 ? "Major":"Minor"] Meteor [pick("Wave", "Cluster", "Group")] [pick(greek_alphabet)]-[rand(1, 999)]" - output_information(meteor_wave_delay, chosen_dir, max_size, number, wave_final_name) - spawn(meteor_wave_delay) - for(var/i = 0 to number) - sleep(rand(1, 3)) //0.1 to 0.3 seconds between meteors - var/meteor_type = null - if(types != null) - meteor_type = pick(types) - spawn_meteor(chosen_dir, meteor_type) - sleep(50) //Five seconds for the chat to scroll - meteor_wave_active = 0 - -//A bunch of information to be used by the bhangmeter (doubles as a meteor monitoring computer), and sent to the admins otherwise -/proc/output_information(var/meteor_delay, var/wave_dir, var/meteor_size, var/wave_size, var/wave_name) - - var/meteor_l_size = "unknown" - switch(meteor_size) - if(1) - meteor_l_size = "small" - if(2) - meteor_l_size = "medium" - if(3) - meteor_l_size = "large" - if(4) - meteor_l_size = "apocalyptic" - else - meteor_l_size = "unknown" - var/wave_l_dir = "north" - switch(wave_dir) - if(1) - wave_l_dir = "north" - if(2) - wave_l_dir = "south" - if(4) - wave_l_dir = "east" - if(8) - wave_l_dir = "west" - - message_admins("[wave_name], containing [wave_size] objects up to [meteor_l_size] size and incoming from the [wave_l_dir], will strike in [meteor_delay/10] seconds.") - - //Send to all Bhangmeters - for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) - if(bhangmeter && !bhangmeter.stat) - bhangmeter.say("Detected: [wave_name], containing [wave_size] objects up to [meteor_l_size] size and incoming from the [wave_l_dir], will strike in [meteor_delay/10] seconds.") - -/proc/spawn_meteor(var/chosen_dir, var/meteorpath = null) - - var/startx - var/starty - var/endx - var/endy - var/turf/pickedstart - var/turf/pickedgoal - var/max_i = 5 //Try only five times maximum - - do - switch(chosen_dir) - - if(1) //North, along the y = max edge - starty = world.maxy - (TRANSITIONEDGE + 2) - startx = rand((TRANSITIONEDGE + 2), world.maxx - (TRANSITIONEDGE + 2)) - endy = TRANSITIONEDGE - endx = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE) - - if(2) //South, along the y = 0 edge - starty = (TRANSITIONEDGE + 2) - startx = rand((TRANSITIONEDGE + 2), world.maxx - (TRANSITIONEDGE + 2)) - endy = world.maxy - (TRANSITIONEDGE + 2) - endx = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE) - - if(4) //East, along the x = max edge - starty = rand((TRANSITIONEDGE + 2), world.maxy - (TRANSITIONEDGE + 2)) - startx = world.maxx - (TRANSITIONEDGE + 2) - endy = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) - endx = (TRANSITIONEDGE + 2) - - if(8) //West, along the x = 0 edge - starty = rand((TRANSITIONEDGE + 2), world.maxy - (TRANSITIONEDGE + 2)) - startx = (TRANSITIONEDGE + 2) - endy = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) - endx = world.maxx - (TRANSITIONEDGE + 2) - - pickedstart = locate(startx, starty, 1) - pickedgoal = locate(endx, endy, 1) - max_i-- - if(max_i <= 0) - return - - while(!istype(pickedstart, /turf/space)) - - var/atom/movable/M - if(meteorpath) - M = new meteorpath(pickedstart) - else - var/list/possible_meteors = list() - if(!max_meteor_size || max_meteor_size >= 1) //Small waves - possible_meteors[/obj/effect/meteor/small] = 40 - possible_meteors[/obj/effect/meteor/small/flash] = 5 - if(!max_meteor_size || max_meteor_size >= 2) //Medium waves - possible_meteors[/obj/effect/meteor] = 55 - possible_meteors[/obj/effect/meteor/radioactive] = 5 - if(!max_meteor_size || max_meteor_size >= 3) //Big waves - possible_meteors[/obj/effect/meteor/big] = 5 - possible_meteors[/obj/effect/meteor/big/cluster] = 5 - var/chosen = pick(possible_meteors) - M = new chosen(pickedstart) - if(M) - walk_towards(M, pickedgoal, 1) - return - -/* - * Below are all meteor types - */ - -/obj/effect/meteor - name = "meteor" - icon = 'icons/obj/meteor.dmi' - icon_state = "medium" - density = 1 - anchored = 1 //You can't push or pull it to prevent exploiting - pass_flags = PASSTABLE - -//Since meteors explode on impact, we won't allow chain reactions like this -//Maybe one day I wil code explosive recoil, but in the meantime who bombs meteor waves anyways ? -/obj/effect/meteor/ex_act() - - return - -//We don't want meteors to bump into eachother and explode, so they pass through eachother -//Reflection on bumping would be better, but I would reckon I'm not sure on how to achieve it -/obj/effect/meteor/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0) - - if(istype(mover, /obj/effect/meteor)) - return 1 //Just move through it, no questions asked - else - return ..() //Refer to atom/proc/CanPass - -/obj/effect/meteor/Bump(atom/A) - - explosion(get_turf(src), 2, 4, 6, 8, 0, 1, 0) //Medium meteor, medium boom - qdel(src) - -/obj/effect/meteor/Move() - ..() - return - -/obj/effect/meteor/radioactive - name = "radioactive meteor" - desc = "The Engineer's bane" - icon_state = "medium_radioactive" - -/obj/effect/meteor/radioactive/Bump(atom/a) - - for(var/mob/living/M in viewers(src, null)) - M.radiation += rand(5, 10) - - ..() - -/obj/effect/meteor/small - name = "small meteor" - desc = "The mineral version of armed C4, coming right for your walls." - icon_state = "small" - pass_flags = PASSTABLE - -/obj/effect/meteor/small/Bump(atom/A) - - explosion(get_turf(src), -1, 1, 3, 4, 0, 1, 0) //Tiny meteor doesn't cause too much damage - qdel(src) - -/obj/effect/meteor/small/flash - name = "flash meteor" - desc = "A absolutely stunning rock specimen of blinding beauty." - icon_state = "small_flash" - -/obj/effect/meteor/small/flash/Bump(atom/A) - - //Adjusted from flashbangs, should be its own global proc - visible_message("BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) - - for(var/mob/living/M in viewers(src, null)) - - //Checking for protections - var/eye_safety = 0 - var/ear_safety = 0 - if(iscarbon(M)) - var/mob/living/carbon/C = M - eye_safety = C.eyecheck() - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(H.earprot()) - ear_safety += 2 - if(M_HULK in H.mutations) - ear_safety += 1 - if(istype(H.head, /obj/item/clothing/head/helmet)) - ear_safety += 1 - - //Flashing everyone - if(eye_safety < 2) - flick("e_flash", M.flash) - switch(eye_safety) - if(1) - M.Stun(2) - if(0) - M.Stun(4) - M.Weaken(10) - if(-1) - M.Stun(7) - M.Weaken(15) - - if(ear_safety < 2) - switch(ear_safety) - if(1) - M.ear_damage += rand(0, 3) - if(0) - M.ear_damage += rand(5, 15) - M.ear_deaf = max(M.ear_deaf, 10) - //Shouldn't have to do this here, this is what life.dm and organ checks are for - //Not even going to bother with eye damage - if(prob(M.ear_damage - 10 + 5)) - to_chat(M, "You can't hear anything!") - M.sdisabilities |= DEAF - - ..() - -/obj/effect/meteor/piercing - name = "piercing meteor" - desc = "Takes a page out of armor-piercing rounds, blowing its way through cover once, and then blowing up normally." - icon_state = "medium_piercing" - var/pierce_health = 1 //When 0, piercing meteor explodes like normal - -/obj/effect/meteor/piercing/Bump(atom/A) - - if(pierce_health) - explosion(get_turf(A), 1, 0, 0, 0, 0, 1, 0) //Blow up the resisting object - pierce_health-- - else - explosion(get_turf(src), 2, 4, 6, 8, 0, 1, 0) //Blow ourselves up, in glory - qdel(src) - -/obj/effect/meteor/big - name = "large meteor" - desc = "It might look large, but it is only a small splinter of a much bigger thing." - icon_state = "big" - pass_flags = 0 //Nope, you're not dodging that table - -/obj/effect/meteor/big/Bump(atom/A) - - explosion(get_turf(src), 4, 6, 8, 8, 0, 1, 0) //You have been visited by the nuclear meteor - qdel(src) - -/obj/effect/meteor/big/cluster - name = "cluster meteor" - desc = "Makes up for its lack of explosiveness by splitting into multiple, fairly explosive meteors." - icon_state = "big_cluster" - -/obj/effect/meteor/big/cluster/Bump(atom/A) - - explosion(get_turf(A), 1, 0, 0, 0, 0, 1, 0) //Enough to destroy whatever was in the way - var/failcount = 0 - for(var/i = 0, i < 3, i++) - if(failcount >= 5) - break - var/obj/effect/meteor/M = new /obj/effect/meteor(get_turf(src)) - var/c_endy = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) - var/c_endx = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE) - var/c_pickedgoal = locate(c_endx, c_endy, 1) - if(!c_pickedgoal) - qdel(M) - i-- //Try again - failcount++ //Keep a track of failures - walk_towards(M, c_pickedgoal, 1) - qdel(src) - -//Placeholder for actual meteors of this kind, will be included SOON -/obj/effect/meteor/boss - name = "apocalytic meteor" - desc = "And behold, a white meteor. And on that meteor..." - -/obj/effect/meteor/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/pickaxe)) //Yeah, you can totally do that - qdel(src) - ..() - -/obj/effect/meteor/Destroy() - walk(src, 0) //This cancels the walk_towards() proc - ..() +#define METEOR_TEMPERATURE + +/var/meteor_wave_delay = 300 //Default wait between waves in tenths of seconds +/var/meteors_in_wave = 10 //Default absolute size +/var/meteor_wave_active = 0 +/var/max_meteor_size = 0 //One for small waves, two for big waves, three for massive waves, four for boss waves +/var/chosen_dir = 1 + +//Call above constants to change +/proc/meteor_wave(var/number = meteors_in_wave, var/max_size = 0, var/list/types = null) + + if(!ticker || meteor_wave_active) + return + meteor_wave_active = 1 + meteor_wave_delay = (rand(30, 45)) * 10 //Between 30 and 45 seconds, engineers need time to shuffle in relative safety + chosen_dir = pick(cardinal) //Pick a direction + max_meteor_size = max_size + //Generate a name for our wave + var/greek_alphabet = list("Alpha", "Beta", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu", \ + "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega") + var/wave_final_name = "[number > 25 ? "Major":"Minor"] Meteor [pick("Wave", "Cluster", "Group")] [pick(greek_alphabet)]-[rand(1, 999)]" + output_information(meteor_wave_delay, chosen_dir, max_size, number, wave_final_name) + spawn(meteor_wave_delay) + for(var/i = 0 to number) + sleep(rand(1, 3)) //0.1 to 0.3 seconds between meteors + var/meteor_type = null + if(types != null) + meteor_type = pick(types) + spawn_meteor(chosen_dir, meteor_type) + sleep(50) //Five seconds for the chat to scroll + meteor_wave_active = 0 + +//A bunch of information to be used by the bhangmeter (doubles as a meteor monitoring computer), and sent to the admins otherwise +/proc/output_information(var/meteor_delay, var/wave_dir, var/meteor_size, var/wave_size, var/wave_name) + + var/meteor_l_size = "unknown" + switch(meteor_size) + if(1) + meteor_l_size = "small" + if(2) + meteor_l_size = "medium" + if(3) + meteor_l_size = "large" + if(4) + meteor_l_size = "apocalyptic" + else + meteor_l_size = "unknown" + var/wave_l_dir = "north" + switch(wave_dir) + if(1) + wave_l_dir = "north" + if(2) + wave_l_dir = "south" + if(4) + wave_l_dir = "east" + if(8) + wave_l_dir = "west" + + message_admins("[wave_name], containing [wave_size] objects up to [meteor_l_size] size and incoming from the [wave_l_dir], will strike in [meteor_delay/10] seconds.") + + //Send to all Bhangmeters + for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) + if(bhangmeter && !bhangmeter.stat) + bhangmeter.say("Detected: [wave_name], containing [wave_size] objects up to [meteor_l_size] size and incoming from the [wave_l_dir], will strike in [meteor_delay/10] seconds.") + +/proc/spawn_meteor(var/chosen_dir, var/meteorpath = null) + + var/startx + var/starty + var/endx + var/endy + var/turf/pickedstart + var/turf/pickedgoal + var/max_i = 5 //Try only five times maximum + + do + switch(chosen_dir) + + if(1) //North, along the y = max edge + starty = world.maxy - (TRANSITIONEDGE + 2) + startx = rand((TRANSITIONEDGE + 2), world.maxx - (TRANSITIONEDGE + 2)) + endy = TRANSITIONEDGE + endx = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE) + + if(2) //South, along the y = 0 edge + starty = (TRANSITIONEDGE + 2) + startx = rand((TRANSITIONEDGE + 2), world.maxx - (TRANSITIONEDGE + 2)) + endy = world.maxy - (TRANSITIONEDGE + 2) + endx = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE) + + if(4) //East, along the x = max edge + starty = rand((TRANSITIONEDGE + 2), world.maxy - (TRANSITIONEDGE + 2)) + startx = world.maxx - (TRANSITIONEDGE + 2) + endy = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) + endx = (TRANSITIONEDGE + 2) + + if(8) //West, along the x = 0 edge + starty = rand((TRANSITIONEDGE + 2), world.maxy - (TRANSITIONEDGE + 2)) + startx = (TRANSITIONEDGE + 2) + endy = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) + endx = world.maxx - (TRANSITIONEDGE + 2) + + pickedstart = locate(startx, starty, 1) + pickedgoal = locate(endx, endy, 1) + max_i-- + if(max_i <= 0) + return + + while(!istype(pickedstart, /turf/space)) + + var/atom/movable/M + if(meteorpath) + M = new meteorpath(pickedstart) + else + var/list/possible_meteors = list() + if(!max_meteor_size || max_meteor_size >= 1) //Small waves + possible_meteors[/obj/effect/meteor/small] = 40 + possible_meteors[/obj/effect/meteor/small/flash] = 5 + if(!max_meteor_size || max_meteor_size >= 2) //Medium waves + possible_meteors[/obj/effect/meteor] = 55 + possible_meteors[/obj/effect/meteor/radioactive] = 5 + if(!max_meteor_size || max_meteor_size >= 3) //Big waves + possible_meteors[/obj/effect/meteor/big] = 5 + possible_meteors[/obj/effect/meteor/big/cluster] = 5 + var/chosen = pick(possible_meteors) + M = new chosen(pickedstart) + if(M) + walk_towards(M, pickedgoal, 1) + return + +/* + * Below are all meteor types + */ + +/obj/effect/meteor + name = "meteor" + icon = 'icons/obj/meteor.dmi' + icon_state = "medium" + density = 1 + anchored = 1 //You can't push or pull it to prevent exploiting + pass_flags = PASSTABLE + +//Since meteors explode on impact, we won't allow chain reactions like this +//Maybe one day I wil code explosive recoil, but in the meantime who bombs meteor waves anyways ? +/obj/effect/meteor/ex_act() + + return + +//We don't want meteors to bump into eachother and explode, so they pass through eachother +//Reflection on bumping would be better, but I would reckon I'm not sure on how to achieve it +/obj/effect/meteor/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0) + + if(istype(mover, /obj/effect/meteor)) + return 1 //Just move through it, no questions asked + else + return ..() //Refer to atom/proc/CanPass + +/obj/effect/meteor/Bump(atom/A) + + explosion(get_turf(src), 2, 4, 6, 8, 0, 1, 0) //Medium meteor, medium boom + qdel(src) + +/obj/effect/meteor/Move() + ..() + return + +/obj/effect/meteor/radioactive + name = "radioactive meteor" + desc = "The Engineer's bane" + icon_state = "medium_radioactive" + +/obj/effect/meteor/radioactive/Bump(atom/a) + + for(var/mob/living/M in viewers(src, null)) + M.radiation += rand(5, 10) + + ..() + +/obj/effect/meteor/small + name = "small meteor" + desc = "The mineral version of armed C4, coming right for your walls." + icon_state = "small" + pass_flags = PASSTABLE + +/obj/effect/meteor/small/Bump(atom/A) + + explosion(get_turf(src), -1, 1, 3, 4, 0, 1, 0) //Tiny meteor doesn't cause too much damage + qdel(src) + +/obj/effect/meteor/small/flash + name = "flash meteor" + desc = "A absolutely stunning rock specimen of blinding beauty." + icon_state = "small_flash" + +/obj/effect/meteor/small/flash/Bump(atom/A) + + //Adjusted from flashbangs, should be its own global proc + visible_message("BANG") + playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + + for(var/mob/living/M in viewers(src, null)) + + //Checking for protections + var/eye_safety = 0 + var/ear_safety = 0 + if(iscarbon(M)) + var/mob/living/carbon/C = M + eye_safety = C.eyecheck() + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(H.earprot()) + ear_safety += 2 + if(M_HULK in H.mutations) + ear_safety += 1 + if(istype(H.head, /obj/item/clothing/head/helmet)) + ear_safety += 1 + + //Flashing everyone + if(eye_safety < 2) + flick("e_flash", M.flash) + switch(eye_safety) + if(1) + M.Stun(2) + if(0) + M.Stun(4) + M.Weaken(10) + if(-1) + M.Stun(7) + M.Weaken(15) + + if(ear_safety < 2) + switch(ear_safety) + if(1) + M.ear_damage += rand(0, 3) + if(0) + M.ear_damage += rand(5, 15) + M.ear_deaf = max(M.ear_deaf, 10) + //Shouldn't have to do this here, this is what life.dm and organ checks are for + //Not even going to bother with eye damage + if(prob(M.ear_damage - 10 + 5)) + to_chat(M, "You can't hear anything!") + M.sdisabilities |= DEAF + + ..() + +/obj/effect/meteor/piercing + name = "piercing meteor" + desc = "Takes a page out of armor-piercing rounds, blowing its way through cover once, and then blowing up normally." + icon_state = "medium_piercing" + var/pierce_health = 1 //When 0, piercing meteor explodes like normal + +/obj/effect/meteor/piercing/Bump(atom/A) + + if(pierce_health) + explosion(get_turf(A), 1, 0, 0, 0, 0, 1, 0) //Blow up the resisting object + pierce_health-- + else + explosion(get_turf(src), 2, 4, 6, 8, 0, 1, 0) //Blow ourselves up, in glory + qdel(src) + +/obj/effect/meteor/big + name = "large meteor" + desc = "It might look large, but it is only a small splinter of a much bigger thing." + icon_state = "big" + pass_flags = 0 //Nope, you're not dodging that table + +/obj/effect/meteor/big/Bump(atom/A) + + explosion(get_turf(src), 4, 6, 8, 8, 0, 1, 0) //You have been visited by the nuclear meteor + qdel(src) + +/obj/effect/meteor/big/cluster + name = "cluster meteor" + desc = "Makes up for its lack of explosiveness by splitting into multiple, fairly explosive meteors." + icon_state = "big_cluster" + +/obj/effect/meteor/big/cluster/Bump(atom/A) + + explosion(get_turf(A), 1, 0, 0, 0, 0, 1, 0) //Enough to destroy whatever was in the way + var/failcount = 0 + for(var/i = 0, i < 3, i++) + if(failcount >= 5) + break + var/obj/effect/meteor/M = new /obj/effect/meteor(get_turf(src)) + var/c_endy = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) + var/c_endx = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE) + var/c_pickedgoal = locate(c_endx, c_endy, 1) + if(!c_pickedgoal) + qdel(M) + i-- //Try again + failcount++ //Keep a track of failures + walk_towards(M, c_pickedgoal, 1) + qdel(src) + +//Placeholder for actual meteors of this kind, will be included SOON +/obj/effect/meteor/boss + name = "apocalytic meteor" + desc = "And behold, a white meteor. And on that meteor..." + +/obj/effect/meteor/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/pickaxe)) //Yeah, you can totally do that + qdel(src) + ..() + +/obj/effect/meteor/Destroy() + walk(src, 0) //This cancels the walk_towards() proc + ..() diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 8828089bb81..cd74c02f8e4 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -1,438 +1,438 @@ -/datum/game_mode - var/list/datum/mind/syndicates = list() - - -/datum/game_mode/nuclear - name = "nuclear emergency" - config_tag = "nuclear" - required_players = 6 - required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining - required_enemies = 5 - recommended_enemies = 5 - - uplink_welcome = "Corporate Backed Uplink Console:" - uplink_uses = 40 - - var/obj/nuclear_uplink - var/const/agents_possible = 5 //If we ever need more syndicate agents. - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! - var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station - var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level - - -/datum/game_mode/nuclear/announce() +/datum/game_mode + var/list/datum/mind/syndicates = list() + + +/datum/game_mode/nuclear + name = "nuclear emergency" + config_tag = "nuclear" + required_players = 6 + required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining + required_enemies = 5 + recommended_enemies = 5 + + uplink_welcome = "Corporate Backed Uplink Console:" + uplink_uses = 40 + + var/obj/nuclear_uplink + var/const/agents_possible = 5 //If we ever need more syndicate agents. + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + + var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! + var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station + var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level + + +/datum/game_mode/nuclear/announce() to_chat(world, "The current game mode is - Nuclear Emergency!") to_chat(world, "A [syndicate_name()] Strike Force is approaching [station_name()]!") to_chat(world, "A nuclear explosive was being transported by Nanotrasen to a military base. The transport ship mysteriously lost contact with Space Traffic Control (STC). About that time a strange disk was discovered around [station_name()]. It was identified by Nanotrasen as a nuclear auth. disk and now Syndicate Operatives have arrived to retake the disk and detonate SS13! Also, most likely Syndicate star ships are in the vicinity so take care not to lose the disk!\nSyndicate: Reclaim the disk and detonate the nuclear bomb anywhere on SS13.\nPersonnel: Hold the disk and escape with the disk on the shuttle!") - -/datum/game_mode/nuclear/can_start()//This could be better, will likely have to recode it later - if(!..()) - return 0 - - var/list/possible_syndicates = get_players_for_role(ROLE_OPERATIVE) - var/agent_number = 0 - - if(possible_syndicates.len < 1) - return 0 - - if(possible_syndicates.len > agents_possible) - agent_number = agents_possible - else - agent_number = possible_syndicates.len - - var/n_players = num_players() - if(agent_number > n_players) - agent_number = n_players/2 - - while(agent_number > 0) - var/datum/mind/new_syndicate = pick(possible_syndicates) - syndicates += new_syndicate - possible_syndicates -= new_syndicate //So it doesn't pick the same guy each time. - agent_number-- - - for(var/datum/mind/synd_mind in syndicates) - synd_mind.assigned_role = "MODE" //So they aren't chosen for other jobs. - synd_mind.special_role = "Syndicate"//So they actually have a special role/N - return 1 - - -/datum/game_mode/nuclear/pre_setup() - return 1 - - -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/update_all_synd_icons() - spawn(0) - for(var/datum/mind/synd_mind in syndicates) - if(synd_mind.current) - if(synd_mind.current.client) - for(var/image/I in synd_mind.current.client.images) - if(I.icon_state == "synd") - synd_mind.current.client.images -= I - - for(var/datum/mind/synd_mind in syndicates) - if(synd_mind.current) - if(synd_mind.current.client) - for(var/datum/mind/synd_mind_1 in syndicates) - if(synd_mind_1.current) - var/imageloc = synd_mind_1.current - if(istype(synd_mind_1.current.loc,/obj/mecha)) - imageloc = synd_mind_1.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "synd", layer = 13) - synd_mind.current.client.images += I - -/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) - if(!synd_mind) - return 0 - spawn(0) - for(var/datum/mind/synd in syndicates) - if(synd.current) - if(synd.current.client) - var/imageloc = synd_mind.current - if(istype(synd_mind.current.loc,/obj/mecha)) - imageloc = synd_mind.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "synd", layer = 13) - synd.current.client.images += I - if(synd_mind.current) - if(synd_mind.current.client) - var/imageloc = synd_mind.current - if(istype(synd_mind.current.loc,/obj/mecha)) - imageloc = synd_mind.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "synd", layer = 13) - synd_mind.current.client.images += I - - update_all_synd_icons() - -/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) - spawn(0) - for(var/datum/mind/synd in syndicates) - if(synd.current) - if(synd.current.client) - for(var/image/I in synd.current.client.images) - if(I.icon_state == "synd" && ((I.loc == synd_mind.current) || (I.loc == synd_mind.current.loc))) - //del(I) - synd.current.client.images -= I - - if(synd_mind.current) - if(synd_mind.current.client) - for(var/image/I in synd_mind.current.client.images) - if(I.icon_state == "synd") - //del(I) - synd_mind.current.client.images -= I - update_all_synd_icons() - -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// - -/datum/game_mode/nuclear/post_setup() - - var/list/turf/synd_spawn = list() - - for(var/obj/effect/landmark/A in landmarks_list) - if(A.name == "Syndicate-Spawn") - synd_spawn += get_turf(A) - qdel(A) - A = null - continue - - var/obj/effect/landmark/uplinklocker = locate("landmark*Syndicate-Uplink") //i will be rewriting this shortly - var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb") - - var/nuke_code = "[rand(10000, 99999)]" - var/leader_selected = 0 - var/agent_number = 1 - var/spawnpos = 1 - - for(var/datum/mind/synd_mind in syndicates) - if(spawnpos > synd_spawn.len) - spawnpos = 1 - synd_mind.current.loc = synd_spawn[spawnpos] - - forge_syndicate_objectives(synd_mind) - greet_syndicate(synd_mind) - equip_syndicate(synd_mind.current) - - if(!leader_selected) - prepare_syndicate_leader(synd_mind, nuke_code) - leader_selected = 1 - else - synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]" - agent_number++ - spawnpos++ - update_synd_icons_added(synd_mind) - - update_all_synd_icons() - - if(uplinklocker) - var/obj/structure/closet/C = new /obj/structure/closet/syndicate/nuclear(uplinklocker.loc) - spawn(10) //gives time for the contents to spawn properly - for(var/obj/item/thing in C) - if(thing.hidden_uplink) - nuclear_uplink = thing - break - if(nuke_spawn && synd_spawn.len > 0) - var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc) - the_bomb.r_code = nuke_code - - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - - return ..() - - -/datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code) - var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") - spawn(1) - NukeNameAssign(nukelastname(synd_mind.current),syndicates) //allows time for the rest of the syndies to be chosen - synd_mind.current.real_name = "[syndicate_name()] [leader_title]" - if (nuke_code) - synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) + +/datum/game_mode/nuclear/can_start()//This could be better, will likely have to recode it later + if(!..()) + return 0 + + var/list/possible_syndicates = get_players_for_role(ROLE_OPERATIVE) + var/agent_number = 0 + + if(possible_syndicates.len < 1) + return 0 + + if(possible_syndicates.len > agents_possible) + agent_number = agents_possible + else + agent_number = possible_syndicates.len + + var/n_players = num_players() + if(agent_number > n_players) + agent_number = n_players/2 + + while(agent_number > 0) + var/datum/mind/new_syndicate = pick(possible_syndicates) + syndicates += new_syndicate + possible_syndicates -= new_syndicate //So it doesn't pick the same guy each time. + agent_number-- + + for(var/datum/mind/synd_mind in syndicates) + synd_mind.assigned_role = "MODE" //So they aren't chosen for other jobs. + synd_mind.special_role = "Syndicate"//So they actually have a special role/N + return 1 + + +/datum/game_mode/nuclear/pre_setup() + return 1 + + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/update_all_synd_icons() + spawn(0) + for(var/datum/mind/synd_mind in syndicates) + if(synd_mind.current) + if(synd_mind.current.client) + for(var/image/I in synd_mind.current.client.images) + if(I.icon_state == "synd") + synd_mind.current.client.images -= I + + for(var/datum/mind/synd_mind in syndicates) + if(synd_mind.current) + if(synd_mind.current.client) + for(var/datum/mind/synd_mind_1 in syndicates) + if(synd_mind_1.current) + var/imageloc = synd_mind_1.current + if(istype(synd_mind_1.current.loc,/obj/mecha)) + imageloc = synd_mind_1.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "synd", layer = 13) + synd_mind.current.client.images += I + +/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) + if(!synd_mind) + return 0 + spawn(0) + for(var/datum/mind/synd in syndicates) + if(synd.current) + if(synd.current.client) + var/imageloc = synd_mind.current + if(istype(synd_mind.current.loc,/obj/mecha)) + imageloc = synd_mind.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "synd", layer = 13) + synd.current.client.images += I + if(synd_mind.current) + if(synd_mind.current.client) + var/imageloc = synd_mind.current + if(istype(synd_mind.current.loc,/obj/mecha)) + imageloc = synd_mind.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "synd", layer = 13) + synd_mind.current.client.images += I + + update_all_synd_icons() + +/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) + spawn(0) + for(var/datum/mind/synd in syndicates) + if(synd.current) + if(synd.current.client) + for(var/image/I in synd.current.client.images) + if(I.icon_state == "synd" && ((I.loc == synd_mind.current) || (I.loc == synd_mind.current.loc))) + //del(I) + synd.current.client.images -= I + + if(synd_mind.current) + if(synd_mind.current.client) + for(var/image/I in synd_mind.current.client.images) + if(I.icon_state == "synd") + //del(I) + synd_mind.current.client.images -= I + update_all_synd_icons() + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +/datum/game_mode/nuclear/post_setup() + + var/list/turf/synd_spawn = list() + + for(var/obj/effect/landmark/A in landmarks_list) + if(A.name == "Syndicate-Spawn") + synd_spawn += get_turf(A) + qdel(A) + A = null + continue + + var/obj/effect/landmark/uplinklocker = locate("landmark*Syndicate-Uplink") //i will be rewriting this shortly + var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb") + + var/nuke_code = "[rand(10000, 99999)]" + var/leader_selected = 0 + var/agent_number = 1 + var/spawnpos = 1 + + for(var/datum/mind/synd_mind in syndicates) + if(spawnpos > synd_spawn.len) + spawnpos = 1 + synd_mind.current.loc = synd_spawn[spawnpos] + + forge_syndicate_objectives(synd_mind) + greet_syndicate(synd_mind) + equip_syndicate(synd_mind.current) + + if(!leader_selected) + prepare_syndicate_leader(synd_mind, nuke_code) + leader_selected = 1 + else + synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]" + agent_number++ + spawnpos++ + update_synd_icons_added(synd_mind) + + update_all_synd_icons() + + if(uplinklocker) + var/obj/structure/closet/C = new /obj/structure/closet/syndicate/nuclear(uplinklocker.loc) + spawn(10) //gives time for the contents to spawn properly + for(var/obj/item/thing in C) + if(thing.hidden_uplink) + nuclear_uplink = thing + break + if(nuke_spawn && synd_spawn.len > 0) + var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc) + the_bomb.r_code = nuke_code + + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + + return ..() + + +/datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code) + var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") + spawn(1) + NukeNameAssign(nukelastname(synd_mind.current),syndicates) //allows time for the rest of the syndies to be chosen + synd_mind.current.real_name = "[syndicate_name()] [leader_title]" + if (nuke_code) + synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) to_chat(synd_mind.current, "The nuclear authorization code is: [nuke_code]") - var/obj/item/weapon/paper/P = new - P.info = "The nuclear authorization code is: [nuke_code]" - P.name = "nuclear bomb code" - if (ticker.mode.config_tag=="nuclear") - P.loc = synd_mind.current.loc - else - var/mob/living/carbon/human/H = synd_mind.current - P.loc = H.loc - H.equip_to_slot_or_del(P, slot_r_store, 0) - H.update_icons() - - else - nuke_code = "code will be provided later" - return - - -/datum/game_mode/proc/forge_syndicate_objectives(var/datum/mind/syndicate) - var/datum/objective/nuclear/syndobj = new - syndobj.owner = syndicate - syndicate.objectives += syndobj - - -/datum/game_mode/proc/greet_syndicate(var/datum/mind/syndicate, var/you_are=1) - if (you_are) + var/obj/item/weapon/paper/P = new + P.info = "The nuclear authorization code is: [nuke_code]" + P.name = "nuclear bomb code" + if (ticker.mode.config_tag=="nuclear") + P.loc = synd_mind.current.loc + else + var/mob/living/carbon/human/H = synd_mind.current + P.loc = H.loc + H.equip_to_slot_or_del(P, slot_r_store, 0) + H.update_icons() + + else + nuke_code = "code will be provided later" + return + + +/datum/game_mode/proc/forge_syndicate_objectives(var/datum/mind/syndicate) + var/datum/objective/nuclear/syndobj = new + syndobj.owner = syndicate + syndicate.objectives += syndobj + + +/datum/game_mode/proc/greet_syndicate(var/datum/mind/syndicate, var/you_are=1) + if (you_are) to_chat(syndicate.current, "You are a [syndicate_name()] agent!") - var/obj_count = 1 - for(var/datum/objective/objective in syndicate.objectives) + var/obj_count = 1 + for(var/datum/objective/objective in syndicate.objectives) to_chat(syndicate.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ + obj_count++ to_chat(syndicate.current, sound('sound/voice/syndicate_intro.ogg')) - return - - -/datum/game_mode/proc/random_radio_frequency() - return 1337 // WHY??? -- Doohl - - -/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob) - var/radio_freq = SYND_FREQ - var/tank_slot = slot_r_hand - - if(synd_mob.overeatduration) //We need to do this here and now, otherwise a lot of gear will fail to spawn + return + + +/datum/game_mode/proc/random_radio_frequency() + return 1337 // WHY??? -- Doohl + + +/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob) + var/radio_freq = SYND_FREQ + var/tank_slot = slot_r_hand + + if(synd_mob.overeatduration) //We need to do this here and now, otherwise a lot of gear will fail to spawn to_chat(synd_mob, "Your intensive physical training to become a Nuclear Operative has paid off and made you fit again!") - synd_mob.overeatduration = 0 //Fat-B-Gone - if(synd_mob.nutrition > 400) //We are also overeating nutriment-wise - synd_mob.nutrition = 400 //Fix that - //synd_mob.handle_chemicals_in_body() //Update now, don't wait for the next life.dm call - synd_mob.mutations.Remove(M_FAT) - synd_mob.update_mutantrace(0) - synd_mob.update_mutations(0) - synd_mob.update_inv_w_uniform(0) - synd_mob.update_inv_wear_suit() - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(synd_mob) - R.set_frequency(radio_freq) - synd_mob.equip_to_slot_or_del(R, slot_ears) - - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) - if(!istype(synd_mob.species, /datum/species/plasmaman)) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/bulletproof(synd_mob), slot_wear_suit) - else - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/plasmaman/nuclear(synd_mob), slot_wear_suit) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/tank/plasma/plasmaman(synd_mob), slot_s_store) - synd_mob.equip_or_collect(new /obj/item/clothing/mask/breath/(synd_mob), slot_wear_mask) - synd_mob.internal = synd_mob.get_item_by_slot(slot_s_store) - if (synd_mob.internals) - synd_mob.internals.icon_state = "internal1" - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(synd_mob), slot_gloves) - if(!istype(synd_mob.species, /datum/species/plasmaman)) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(synd_mob), slot_head) - else - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/plasmaman/nuclear(synd_mob), slot_head) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/prescription(synd_mob), slot_glasses)//changed to prescription sunglasses so near-sighted players aren't screwed if there aren't any admins online - if(istype(synd_mob.species, /datum/species/vox)) - synd_mob.equip_or_collect(new /obj/item/clothing/mask/breath/vox(synd_mob), slot_wear_mask) - synd_mob.equip_to_slot_or_del(new/obj/item/weapon/tank/nitrogen(synd_mob), slot_r_hand) + synd_mob.overeatduration = 0 //Fat-B-Gone + if(synd_mob.nutrition > 400) //We are also overeating nutriment-wise + synd_mob.nutrition = 400 //Fix that + //synd_mob.handle_chemicals_in_body() //Update now, don't wait for the next life.dm call + synd_mob.mutations.Remove(M_FAT) + synd_mob.update_mutantrace(0) + synd_mob.update_mutations(0) + synd_mob.update_inv_w_uniform(0) + synd_mob.update_inv_wear_suit() + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(synd_mob) + R.set_frequency(radio_freq) + synd_mob.equip_to_slot_or_del(R, slot_ears) + + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) + if(!istype(synd_mob.species, /datum/species/plasmaman)) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/bulletproof(synd_mob), slot_wear_suit) + else + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/plasmaman/nuclear(synd_mob), slot_wear_suit) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/tank/plasma/plasmaman(synd_mob), slot_s_store) + synd_mob.equip_or_collect(new /obj/item/clothing/mask/breath/(synd_mob), slot_wear_mask) + synd_mob.internal = synd_mob.get_item_by_slot(slot_s_store) + if (synd_mob.internals) + synd_mob.internals.icon_state = "internal1" + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(synd_mob), slot_gloves) + if(!istype(synd_mob.species, /datum/species/plasmaman)) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(synd_mob), slot_head) + else + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/plasmaman/nuclear(synd_mob), slot_head) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/prescription(synd_mob), slot_glasses)//changed to prescription sunglasses so near-sighted players aren't screwed if there aren't any admins online + if(istype(synd_mob.species, /datum/species/vox)) + synd_mob.equip_or_collect(new /obj/item/clothing/mask/breath/vox(synd_mob), slot_wear_mask) + synd_mob.equip_to_slot_or_del(new/obj/item/weapon/tank/nitrogen(synd_mob), slot_r_hand) to_chat(synd_mob, "You are now running on nitrogen internals from the [slot_r_hand] in your right hand. Your species finds oxygen toxic, so you must breathe nitrogen (AKA N2) only.") - synd_mob.internal = synd_mob.get_item_by_slot(tank_slot) - if (synd_mob.internals) - synd_mob.internals.icon_state = "internal1" - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) - if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(synd_mob), slot_back) - if(synd_mob.backbag == 3 || synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_sec(synd_mob), slot_back) - //if(synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(synd_mob), slot_back) - synd_mob.equip_to_slot_or_del(new /obj/item/ammo_storage/magazine/a12mm(synd_mob), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/ammo_storage/magazine/a12mm(synd_mob), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack) // For those who hate fun - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/creatine(synd_mob), slot_in_backpack) // HOOOOOO HOOHOHOHOHOHO - N3X - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), slot_belt) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) - var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob) - E.imp_in = synd_mob - E.implanted = 1 - synd_mob.update_icons() - return 1 - - -/datum/game_mode/nuclear/check_win() - if (nukes_left == 0) - return 1 - return ..() - - -/datum/game_mode/proc/is_operatives_are_dead() - for(var/datum/mind/operative_mind in syndicates) - if (!istype(operative_mind.current,/mob/living/carbon/human)) - if(operative_mind.current) - if(operative_mind.current.stat!=2) - return 0 - return 1 - - -/datum/game_mode/nuclear/declare_completion() - var/disk_rescued = 1 - for(var/obj/item/weapon/disk/nuclear/D in world) - var/disk_area = get_area(D) - if(!is_type_in_list(disk_area, centcom_areas)) - disk_rescued = 0 - break - var/crew_evacuated = (emergency_shuttle.location==2) - //var/operatives_are_dead = is_operatives_are_dead() - - - //nukes_left - //station_was_nuked - //derp //Used for tracking if the syndies actually haul the nuke to the station //no - //herp //Used for tracking if the syndies got the shuttle off of the z-level //NO, DON'T FUCKING NAME VARS LIKE THIS - - if (!disk_rescued && station_was_nuked && !syndies_didnt_escape) - feedback_set_details("round_end_result","win - syndicate nuke") - completion_text += "Syndicate Major Victory!" - completion_text += "
      [syndicate_name()] operatives have destroyed [station_name()]!" - - else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) - feedback_set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time") - completion_text += "Total Annihilation" - completion_text += "
      [syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" - - else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) - feedback_set_details("round_end_result","halfwin - blew wrong station") - completion_text += "Crew Minor Victory" - completion_text += "
      [syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't lose the disk!" - - else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) - feedback_set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time") - completion_text += "[syndicate_name()] operatives have earned Darwin Award!" - completion_text += "
      [syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't lose the disk!" - - else if ( disk_rescued && is_operatives_are_dead()) - feedback_set_details("round_end_result","loss - evacuation - disk secured - syndi team dead") - completion_text += "Crew Major Victory!" - completion_text += "
      The Research Staff has saved the disc and killed the [syndicate_name()] Operatives" - - else if ( disk_rescued ) - feedback_set_details("round_end_result","loss - evacuation - disk secured") - completion_text += "Crew Major Victory" - completion_text += "
      The Research Staff has saved the disc and stopped the [syndicate_name()] Operatives!" - - else if (!disk_rescued && is_operatives_are_dead()) - feedback_set_details("round_end_result","loss - evacuation - disk not secured") - completion_text += "Syndicate Minor Victory!" - completion_text += "
      The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!" - - else if (!disk_rescued && crew_evacuated) - feedback_set_details("round_end_result","halfwin - detonation averted") - completion_text += "Syndicate Minor Victory!" - completion_text += "
      [syndicate_name()] operatives recovered the abandoned authentication disk but detonation of [station_name()] was averted. Next time, don't lose the disk!" - - else if (!disk_rescued && !crew_evacuated) - feedback_set_details("round_end_result","halfwin - interrupted") - completion_text += "Neutral Victory" - completion_text += "
      Round was mysteriously interrupted!" - - ..() - return - - -/datum/game_mode/proc/auto_declare_completion_nuclear() - var/text = "" - if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) ) - var/icon/logo = icon('icons/mob/mob.dmi', "nuke-logo") - end_icons += logo - var/tempstate = end_icons.len - text += {"
      The syndicate operatives were: "} - - for(var/datum/mind/syndicate in syndicates) - - if(syndicate.current) - var/icon/flat = getFlatIcon(syndicate.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [syndicate.key] was [syndicate.name] ("} - if(syndicate.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(syndicate.current.real_name != syndicate.name) - text += " as [syndicate.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [syndicate.key] was [syndicate.name] ("} - text += "body destroyed" - text += ")" - var/obj/item/nuclear_uplink = src:nuclear_uplink - if(nuclear_uplink && nuclear_uplink.hidden_uplink) - if(nuclear_uplink.hidden_uplink.purchase_log.len) - text += "
      The tools used by the syndicate operatives were: " - for(var/entry in nuclear_uplink.hidden_uplink.purchase_log) - text += "
      [entry]TC(s)" - text += "
      " - else - text += "
      The nukeops were smooth operators this round (did not purchase any uplink items)" - text += "

      " - return text - - -/proc/nukelastname(var/mob/M as mob) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. - var/randomname = pick(last_names) - var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN) - - if (!newname) - newname = randomname - - else - if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_") + synd_mob.internal = synd_mob.get_item_by_slot(tank_slot) + if (synd_mob.internals) + synd_mob.internals.icon_state = "internal1" + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) + if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(synd_mob), slot_back) + if(synd_mob.backbag == 3 || synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_sec(synd_mob), slot_back) + //if(synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(synd_mob), slot_back) + synd_mob.equip_to_slot_or_del(new /obj/item/ammo_storage/magazine/a12mm(synd_mob), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/ammo_storage/magazine/a12mm(synd_mob), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack) // For those who hate fun + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/creatine(synd_mob), slot_in_backpack) // HOOOOOO HOOHOHOHOHOHO - N3X + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), slot_belt) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) + var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob) + E.imp_in = synd_mob + E.implanted = 1 + synd_mob.update_icons() + return 1 + + +/datum/game_mode/nuclear/check_win() + if (nukes_left == 0) + return 1 + return ..() + + +/datum/game_mode/proc/is_operatives_are_dead() + for(var/datum/mind/operative_mind in syndicates) + if (!istype(operative_mind.current,/mob/living/carbon/human)) + if(operative_mind.current) + if(operative_mind.current.stat!=2) + return 0 + return 1 + + +/datum/game_mode/nuclear/declare_completion() + var/disk_rescued = 1 + for(var/obj/item/weapon/disk/nuclear/D in world) + var/disk_area = get_area(D) + if(!is_type_in_list(disk_area, centcom_areas)) + disk_rescued = 0 + break + var/crew_evacuated = (emergency_shuttle.location==2) + //var/operatives_are_dead = is_operatives_are_dead() + + + //nukes_left + //station_was_nuked + //derp //Used for tracking if the syndies actually haul the nuke to the station //no + //herp //Used for tracking if the syndies got the shuttle off of the z-level //NO, DON'T FUCKING NAME VARS LIKE THIS + + if (!disk_rescued && station_was_nuked && !syndies_didnt_escape) + feedback_set_details("round_end_result","win - syndicate nuke") + completion_text += "Syndicate Major Victory!" + completion_text += "
      [syndicate_name()] operatives have destroyed [station_name()]!" + + else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) + feedback_set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time") + completion_text += "Total Annihilation" + completion_text += "
      [syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" + + else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) + feedback_set_details("round_end_result","halfwin - blew wrong station") + completion_text += "Crew Minor Victory" + completion_text += "
      [syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't lose the disk!" + + else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) + feedback_set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time") + completion_text += "[syndicate_name()] operatives have earned Darwin Award!" + completion_text += "
      [syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't lose the disk!" + + else if ( disk_rescued && is_operatives_are_dead()) + feedback_set_details("round_end_result","loss - evacuation - disk secured - syndi team dead") + completion_text += "Crew Major Victory!" + completion_text += "
      The Research Staff has saved the disc and killed the [syndicate_name()] Operatives" + + else if ( disk_rescued ) + feedback_set_details("round_end_result","loss - evacuation - disk secured") + completion_text += "Crew Major Victory" + completion_text += "
      The Research Staff has saved the disc and stopped the [syndicate_name()] Operatives!" + + else if (!disk_rescued && is_operatives_are_dead()) + feedback_set_details("round_end_result","loss - evacuation - disk not secured") + completion_text += "Syndicate Minor Victory!" + completion_text += "
      The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!" + + else if (!disk_rescued && crew_evacuated) + feedback_set_details("round_end_result","halfwin - detonation averted") + completion_text += "Syndicate Minor Victory!" + completion_text += "
      [syndicate_name()] operatives recovered the abandoned authentication disk but detonation of [station_name()] was averted. Next time, don't lose the disk!" + + else if (!disk_rescued && !crew_evacuated) + feedback_set_details("round_end_result","halfwin - interrupted") + completion_text += "Neutral Victory" + completion_text += "
      Round was mysteriously interrupted!" + + ..() + return + + +/datum/game_mode/proc/auto_declare_completion_nuclear() + var/text = "" + if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) ) + var/icon/logo = icon('icons/mob/mob.dmi', "nuke-logo") + end_icons += logo + var/tempstate = end_icons.len + text += {"
      The syndicate operatives were: "} + + for(var/datum/mind/syndicate in syndicates) + + if(syndicate.current) + var/icon/flat = getFlatIcon(syndicate.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [syndicate.key] was [syndicate.name] ("} + if(syndicate.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(syndicate.current.real_name != syndicate.name) + text += " as [syndicate.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [syndicate.key] was [syndicate.name] ("} + text += "body destroyed" + text += ")" + var/obj/item/nuclear_uplink = src:nuclear_uplink + if(nuclear_uplink && nuclear_uplink.hidden_uplink) + if(nuclear_uplink.hidden_uplink.purchase_log.len) + text += "
      The tools used by the syndicate operatives were: " + for(var/entry in nuclear_uplink.hidden_uplink.purchase_log) + text += "
      [entry]TC(s)" + text += "
      " + else + text += "
      The nukeops were smooth operators this round (did not purchase any uplink items)" + text += "

      " + return text + + +/proc/nukelastname(var/mob/M as mob) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. + var/randomname = pick(last_names) + var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN) + + if (!newname) + newname = randomname + + else + if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_") to_chat(M, "That name is reserved.") - return nukelastname(M) - - return newname - -/proc/NukeNameAssign(var/lastname,var/list/syndicates) - for(var/datum/mind/synd_mind in syndicates) - switch(synd_mind.current.gender) - if(MALE) - synd_mind.name = "[pick(first_names_male)] [lastname]" - if(FEMALE) - synd_mind.name = "[pick(first_names_female)] [lastname]" - synd_mind.current.real_name = synd_mind.name - return + return nukelastname(M) + + return newname + +/proc/NukeNameAssign(var/lastname,var/list/syndicates) + for(var/datum/mind/synd_mind in syndicates) + switch(synd_mind.current.gender) + if(MALE) + synd_mind.name = "[pick(first_names_male)] [lastname]" + if(FEMALE) + synd_mind.name = "[pick(first_names_female)] [lastname]" + synd_mind.current.real_name = synd_mind.name + return diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 78282db147d..87e2d11e413 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -1,366 +1,366 @@ -var/bomb_set - -/obj/machinery/nuclearbomb - name = "\improper Nuclear Fission Explosive" - desc = "Uh oh. RUN!!!!" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "nuclearbomb0" - density = 1 - var/deployable = 0.0 - var/extended = 0.0 - var/timeleft = 60.0 - var/timing = 0.0 - var/r_code = "ADMIN" - var/code = "" - var/yes_code = 0.0 - var/safety = 1.0 - var/obj/item/weapon/disk/nuclear/auth = null - var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, - // 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. - flags = FPRINT - use_power = 0 - -/obj/machinery/nuclearbomb/New() - ..() - r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. - -/obj/machinery/nuclearbomb/process() - if (src.timing) - bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. - src.timeleft-- - if (src.timeleft <= 0) - explode() - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) - return - -/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob) - if (src.extended) - if (istype(O, /obj/item/weapon/disk/nuclear)) - usr.drop_item(O, src, force_drop = 1) - src.auth = O - src.add_fingerprint(user) - return - - if (src.anchored) - switch(removal_stage) - if(0) - if(istype(O,/obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = O - if(!WT.isOn()) return - if (WT.get_fuel() < 5) // uses up 5 fuel. - to_chat(user, "You need more fuel to complete this task.") - return - - user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...") - - if(do_after(user, src, 40)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.") - removal_stage = 1 - return - - if(1) - if(istype(O,/obj/item/weapon/crowbar)) - user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...") - - if(do_after(user, src, 15)) - if(!src || !user) return - user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") - removal_stage = 2 - return - - if(2) - if(istype(O,/obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = O - if(!WT.isOn()) return - if (WT.get_fuel() < 5) // uses up 5 fuel. - to_chat(user, "You need more fuel to complete this task.") - return - - user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...") - - if(do_after(user, src, 40)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.") - removal_stage = 3 - return - - if(3) - if(istype(O,/obj/item/weapon/wrench)) - - user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") - - if(do_after(user, src, 50)) - if(!src || !user) return - user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") - removal_stage = 4 - return - - if(4) - if(istype(O,/obj/item/weapon/crowbar)) - - user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") - - if(do_after(user, src, 80)) - if(!src || !user) return - user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") - anchored = 0 - removal_stage = 5 - return - ..() - -/obj/machinery/nuclearbomb/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/machinery/nuclearbomb/attack_ghost(mob/user as mob) //prevents ghosts from deploying the nuke - if (src.extended) //if the nuke is set - return attack_hand(user) //continue as normal - return 0 //otherwise nothing - -/obj/machinery/nuclearbomb/attack_hand(mob/user as mob) - if (src.extended) - user.set_machine(src) - var/dat = text("Nuclear Fission Explosive
      \nAuth. Disk: []
      ", src, (src.auth ? "++++++++++" : "----------")) - if (src.auth) - if (src.yes_code) - dat += text("\nStatus: []-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \nSafety: [] Toggle
      \nAnchor: [] Toggle
      \n", (src.timing ? "Func/Set" : "Functional"), (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src, src, src, src.timeleft, src, src, (src.safety ? "On" : "Off"), src, (src.anchored ? "Engaged" : "Off"), src) - else - dat += text("\nStatus: Auth. S2-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \n[] Safety: Toggle
      \nAnchor: [] Toggle
      \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) - else - if (src.timing) - dat += text("\nStatus: Set-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \nSafety: [] Toggle
      \nAnchor: [] Toggle
      \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) - else - dat += text("\nStatus: Auth. S1-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \nSafety: [] Toggle
      \nAnchor: [] Toggle
      \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) - var/message = "AUTH" - if (src.auth) - message = text("[]", src.code) - if (src.yes_code) - message = "*****" - dat += text("
      \n>[]
      \n1-2-3
      \n4-5-6
      \n7-8-9
      \nR-0-E
      \n
      ", message, src, src, src, src, src, src, src, src, src, src, src, src) - user << browse(dat, "window=nuclearbomb;size=300x400") - onclose(user, "nuclearbomb") - else if (src.deployable) - if(removal_stage < 5) - src.anchored = 1 - visible_message("With a steely snap, bolts slide out of [src] and anchor it to the flooring!") - else - visible_message("\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - flick("nuclearbombc", src) - src.icon_state = "nuclearbomb1" - src.extended = 1 - return - -/obj/machinery/nuclearbomb/verb/make_deployable() - set category = "Object" - set name = "Make Deployable" - set src in oview(1) - - if (!usr || usr.lying || usr.isUnconscious()) return - if (!usr.dexterity_check()) - to_chat(usr, "You don't have the dexterity to do this!") - return - - if (src.deployable) - to_chat(usr, "You close several panels to make [src] undeployable.") - src.deployable = 0 - else - to_chat(usr, "You adjust some panels to make [src] deployable.") - src.deployable = 1 - -/obj/machinery/nuclearbomb/Topic(href, href_list) - if(..()) return 1 - if (!usr.canmove || usr.stat || usr.restrained()) - return - if (!usr.dexterity_check()) - to_chat(usr, "You don't have the dexterity to do this!") - return 1 - if (istype(src.loc, /turf)) - usr.set_machine(src) - if (href_list["auth"]) - if (src.auth) - src.auth.loc = src.loc - src.yes_code = 0 - src.auth = null - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/disk/nuclear)) - usr.drop_item(I, src, force_drop = 1) //FORCE DROP for balance reasons - src.auth = I - if (src.auth) - if (href_list["type"]) - if (href_list["type"] == "E") - if (src.code == src.r_code) - src.yes_code = 1 - src.code = null - else - src.code = "ERROR" - else - if (href_list["type"] == "R") - src.yes_code = 0 - src.code = null - else - src.code += text("[]", href_list["type"]) - if (length(src.code) > 5) - src.code = "ERROR" - if (src.yes_code) - if (href_list["time"]) - var/time = text2num(href_list["time"]) - src.timeleft += time - src.timeleft = min(max(round(src.timeleft), 60), 600) - if (href_list["timer"]) - if (src.timing == -1.0) - return - if (src.safety) - to_chat(usr, "The safety is still on.") - return - src.timing = !( src.timing ) - if (src.timing) - src.icon_state = "nuclearbomb2" - if(!src.safety) - bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N - else - bomb_set = 0 - else - src.icon_state = "nuclearbomb1" - bomb_set = 0 - if (href_list["safety"]) - src.safety = !( src.safety ) - if(safety) - src.timing = 0 - bomb_set = 0 - if (href_list["anchor"]) - - if(removal_stage == 5) - src.anchored = 0 - visible_message("\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - return - - src.anchored = !( src.anchored ) - if(src.anchored) - visible_message("With a steely snap, bolts slide out of [src] and anchor it to the flooring.") - playsound(src,'sound/effects/bolt.ogg', 70, 1) - else - visible_message("The anchoring bolts slide back into the depths of [src].") - - src.add_fingerprint(usr) - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) - else - usr << browse(null, "window=nuclearbomb") - return - return - - -/obj/machinery/nuclearbomb/ex_act(severity) - return - -/obj/machinery/nuclearbomb/blob_act() - if (src.timing == -1.0) - return - else - return ..() - return - - -#define NUKERANGE 80 -/obj/machinery/nuclearbomb/proc/explode() - if (src.safety) - src.timing = 0 - return - src.timing = -1.0 - src.yes_code = 0 - src.safety = 1 - src.icon_state = "nuclearbomb3" - playsound(src,'sound/machines/Alarm.ogg',100,0,5) - if (ticker && ticker.mode) - ticker.mode.explosion_in_progress = 1 - sleep(100) - - enter_allowed = 0 - - var/off_station = 0 - var/turf/bomb_location = get_turf(src) - if( bomb_location && (bomb_location.z == 1) ) - if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) ) - off_station = 1 - else - off_station = 2 - - if(ticker) - if(ticker.mode && ticker.mode.name == "nuclear emergency") - var/datum/game_mode/nuclear/GM = ticker.mode - var/obj/machinery/computer/shuttle_control/syndicate/syndie_location = locate(/obj/machinery/computer/shuttle_control/syndicate) - if(syndie_location) - GM.syndies_didnt_escape = (syndie_location.z > 1 ? 0 : 1) //muskets will make me change this, but it will do for now - GM.nuke_off_station = off_station - ticker.station_explosion_cinematic(off_station,null) - if(ticker.mode) - ticker.mode.explosion_in_progress = 0 - if(ticker.mode.name == "nuclear emergency") - var/datum/game_mode/nuclear/GM = ticker.mode - GM.nukes_left -- - else - to_chat(world, "The station was destoyed by the nuclear blast!") - - ticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated. - //kinda shit but I couldn't get permission to do what I wanted to do. - stat_collection.nuked++ - - if(!ticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is - to_chat(world, "Resetting in 30 seconds!") - - feedback_set_details("end_error","nuke - unhandled ending") - - if(blackbox) - blackbox.save_all_data_to_sql() - - CallHook("Reboot",list()) - - if (watchdog.waiting) - to_chat(world, "Server will shut down for an automatic update in a few seconds.") - watchdog.signal_ready() - return - sleep(300) - log_game("Rebooting due to nuclear detonation") - world.Reboot() - return - return - -/obj/item/weapon/disk/nuclear - name = "nuclear authentication disk" - desc = "Better keep this safe." - icon_state = "nucleardisk" - item_state = "card-id" - w_class = 1.0 - var/respawned = 0 - var/watched_by = list() - -/obj/item/weapon/disk/nuclear/Destroy() - ..() - replace_disk() - for(var/obj/item/weapon/pinpointer/pinpointers in watched_by) - if(pinpointers.the_disk == src) - pinpointers.the_disk = null - watched_by = null - -/** - * NOTE: Don't change it to Destroy(). - */ -/obj/item/weapon/disk/nuclear/Del() - replace_disk() - ..() - -/obj/item/weapon/disk/nuclear/proc/replace_disk() - if(blobstart.len > 0 && !respawned) - var/picked_turf = get_turf(pick(blobstart)) - var/picked_area = formatLocation(picked_turf) - var/log_message = "[type] has been destroyed. Creating one at" - log_game("[log_message] [picked_area]") - message_admins("[log_message] [formatJumpTo(picked_turf, picked_area)]") - new /obj/item/weapon/disk/nuclear(picked_turf) - respawned = 1 +var/bomb_set + +/obj/machinery/nuclearbomb + name = "\improper Nuclear Fission Explosive" + desc = "Uh oh. RUN!!!!" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "nuclearbomb0" + density = 1 + var/deployable = 0.0 + var/extended = 0.0 + var/timeleft = 60.0 + var/timing = 0.0 + var/r_code = "ADMIN" + var/code = "" + var/yes_code = 0.0 + var/safety = 1.0 + var/obj/item/weapon/disk/nuclear/auth = null + var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, + // 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. + flags = FPRINT + use_power = 0 + +/obj/machinery/nuclearbomb/New() + ..() + r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. + +/obj/machinery/nuclearbomb/process() + if (src.timing) + bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. + src.timeleft-- + if (src.timeleft <= 0) + explode() + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) + return + +/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob) + if (src.extended) + if (istype(O, /obj/item/weapon/disk/nuclear)) + usr.drop_item(O, src, force_drop = 1) + src.auth = O + src.add_fingerprint(user) + return + + if (src.anchored) + switch(removal_stage) + if(0) + if(istype(O,/obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = O + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. + to_chat(user, "You need more fuel to complete this task.") + return + + user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...") + + if(do_after(user, src, 40)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.") + removal_stage = 1 + return + + if(1) + if(istype(O,/obj/item/weapon/crowbar)) + user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...") + + if(do_after(user, src, 15)) + if(!src || !user) return + user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") + removal_stage = 2 + return + + if(2) + if(istype(O,/obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = O + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. + to_chat(user, "You need more fuel to complete this task.") + return + + user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...") + + if(do_after(user, src, 40)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.") + removal_stage = 3 + return + + if(3) + if(istype(O,/obj/item/weapon/wrench)) + + user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") + + if(do_after(user, src, 50)) + if(!src || !user) return + user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") + removal_stage = 4 + return + + if(4) + if(istype(O,/obj/item/weapon/crowbar)) + + user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") + + if(do_after(user, src, 80)) + if(!src || !user) return + user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") + anchored = 0 + removal_stage = 5 + return + ..() + +/obj/machinery/nuclearbomb/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/machinery/nuclearbomb/attack_ghost(mob/user as mob) //prevents ghosts from deploying the nuke + if (src.extended) //if the nuke is set + return attack_hand(user) //continue as normal + return 0 //otherwise nothing + +/obj/machinery/nuclearbomb/attack_hand(mob/user as mob) + if (src.extended) + user.set_machine(src) + var/dat = text("Nuclear Fission Explosive
      \nAuth. Disk: []
      ", src, (src.auth ? "++++++++++" : "----------")) + if (src.auth) + if (src.yes_code) + dat += text("\nStatus: []-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \nSafety: [] Toggle
      \nAnchor: [] Toggle
      \n", (src.timing ? "Func/Set" : "Functional"), (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src, src, src, src.timeleft, src, src, (src.safety ? "On" : "Off"), src, (src.anchored ? "Engaged" : "Off"), src) + else + dat += text("\nStatus: Auth. S2-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \n[] Safety: Toggle
      \nAnchor: [] Toggle
      \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) + else + if (src.timing) + dat += text("\nStatus: Set-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \nSafety: [] Toggle
      \nAnchor: [] Toggle
      \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) + else + dat += text("\nStatus: Auth. S1-[]
      \nTimer: []
      \n
      \nTimer: [] Toggle
      \nTime: - - [] + +
      \n
      \nSafety: [] Toggle
      \nAnchor: [] Toggle
      \n", (src.safety ? "Safe" : "Engaged"), src.timeleft, (src.timing ? "On" : "Off"), src.timeleft, (src.safety ? "On" : "Off"), (src.anchored ? "Engaged" : "Off")) + var/message = "AUTH" + if (src.auth) + message = text("[]", src.code) + if (src.yes_code) + message = "*****" + dat += text("
      \n>[]
      \n1-2-3
      \n4-5-6
      \n7-8-9
      \nR-0-E
      \n
      ", message, src, src, src, src, src, src, src, src, src, src, src, src) + user << browse(dat, "window=nuclearbomb;size=300x400") + onclose(user, "nuclearbomb") + else if (src.deployable) + if(removal_stage < 5) + src.anchored = 1 + visible_message("With a steely snap, bolts slide out of [src] and anchor it to the flooring!") + else + visible_message("\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") + flick("nuclearbombc", src) + src.icon_state = "nuclearbomb1" + src.extended = 1 + return + +/obj/machinery/nuclearbomb/verb/make_deployable() + set category = "Object" + set name = "Make Deployable" + set src in oview(1) + + if (!usr || usr.lying || usr.isUnconscious()) return + if (!usr.dexterity_check()) + to_chat(usr, "You don't have the dexterity to do this!") + return + + if (src.deployable) + to_chat(usr, "You close several panels to make [src] undeployable.") + src.deployable = 0 + else + to_chat(usr, "You adjust some panels to make [src] deployable.") + src.deployable = 1 + +/obj/machinery/nuclearbomb/Topic(href, href_list) + if(..()) return 1 + if (!usr.canmove || usr.stat || usr.restrained()) + return + if (!usr.dexterity_check()) + to_chat(usr, "You don't have the dexterity to do this!") + return 1 + if (istype(src.loc, /turf)) + usr.set_machine(src) + if (href_list["auth"]) + if (src.auth) + src.auth.loc = src.loc + src.yes_code = 0 + src.auth = null + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/disk/nuclear)) + usr.drop_item(I, src, force_drop = 1) //FORCE DROP for balance reasons + src.auth = I + if (src.auth) + if (href_list["type"]) + if (href_list["type"] == "E") + if (src.code == src.r_code) + src.yes_code = 1 + src.code = null + else + src.code = "ERROR" + else + if (href_list["type"] == "R") + src.yes_code = 0 + src.code = null + else + src.code += text("[]", href_list["type"]) + if (length(src.code) > 5) + src.code = "ERROR" + if (src.yes_code) + if (href_list["time"]) + var/time = text2num(href_list["time"]) + src.timeleft += time + src.timeleft = min(max(round(src.timeleft), 60), 600) + if (href_list["timer"]) + if (src.timing == -1.0) + return + if (src.safety) + to_chat(usr, "The safety is still on.") + return + src.timing = !( src.timing ) + if (src.timing) + src.icon_state = "nuclearbomb2" + if(!src.safety) + bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N + else + bomb_set = 0 + else + src.icon_state = "nuclearbomb1" + bomb_set = 0 + if (href_list["safety"]) + src.safety = !( src.safety ) + if(safety) + src.timing = 0 + bomb_set = 0 + if (href_list["anchor"]) + + if(removal_stage == 5) + src.anchored = 0 + visible_message("\The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") + return + + src.anchored = !( src.anchored ) + if(src.anchored) + visible_message("With a steely snap, bolts slide out of [src] and anchor it to the flooring.") + playsound(src,'sound/effects/bolt.ogg', 70, 1) + else + visible_message("The anchoring bolts slide back into the depths of [src].") + + src.add_fingerprint(usr) + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) + else + usr << browse(null, "window=nuclearbomb") + return + return + + +/obj/machinery/nuclearbomb/ex_act(severity) + return + +/obj/machinery/nuclearbomb/blob_act() + if (src.timing == -1.0) + return + else + return ..() + return + + +#define NUKERANGE 80 +/obj/machinery/nuclearbomb/proc/explode() + if (src.safety) + src.timing = 0 + return + src.timing = -1.0 + src.yes_code = 0 + src.safety = 1 + src.icon_state = "nuclearbomb3" + playsound(src,'sound/machines/Alarm.ogg',100,0,5) + if (ticker && ticker.mode) + ticker.mode.explosion_in_progress = 1 + sleep(100) + + enter_allowed = 0 + + var/off_station = 0 + var/turf/bomb_location = get_turf(src) + if( bomb_location && (bomb_location.z == 1) ) + if( (bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)) ) + off_station = 1 + else + off_station = 2 + + if(ticker) + if(ticker.mode && ticker.mode.name == "nuclear emergency") + var/datum/game_mode/nuclear/GM = ticker.mode + var/obj/machinery/computer/shuttle_control/syndicate/syndie_location = locate(/obj/machinery/computer/shuttle_control/syndicate) + if(syndie_location) + GM.syndies_didnt_escape = (syndie_location.z > 1 ? 0 : 1) //muskets will make me change this, but it will do for now + GM.nuke_off_station = off_station + ticker.station_explosion_cinematic(off_station,null) + if(ticker.mode) + ticker.mode.explosion_in_progress = 0 + if(ticker.mode.name == "nuclear emergency") + var/datum/game_mode/nuclear/GM = ticker.mode + GM.nukes_left -- + else + to_chat(world, "The station was destoyed by the nuclear blast!") + + ticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated. + //kinda shit but I couldn't get permission to do what I wanted to do. + stat_collection.nuked++ + + if(!ticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is + to_chat(world, "Resetting in 30 seconds!") + + feedback_set_details("end_error","nuke - unhandled ending") + + if(blackbox) + blackbox.save_all_data_to_sql() + + CallHook("Reboot",list()) + + if (watchdog.waiting) + to_chat(world, "Server will shut down for an automatic update in a few seconds.") + watchdog.signal_ready() + return + sleep(300) + log_game("Rebooting due to nuclear detonation") + world.Reboot() + return + return + +/obj/item/weapon/disk/nuclear + name = "nuclear authentication disk" + desc = "Better keep this safe." + icon_state = "nucleardisk" + item_state = "card-id" + w_class = 1.0 + var/respawned = 0 + var/watched_by = list() + +/obj/item/weapon/disk/nuclear/Destroy() + ..() + replace_disk() + for(var/obj/item/weapon/pinpointer/pinpointers in watched_by) + if(pinpointers.the_disk == src) + pinpointers.the_disk = null + watched_by = null + +/** + * NOTE: Don't change it to Destroy(). + */ +/obj/item/weapon/disk/nuclear/Del() + replace_disk() + ..() + +/obj/item/weapon/disk/nuclear/proc/replace_disk() + if(blobstart.len > 0 && !respawned) + var/picked_turf = get_turf(pick(blobstart)) + var/picked_area = formatLocation(picked_turf) + var/log_message = "[type] has been destroyed. Creating one at" + log_game("[log_message] [picked_area]") + message_admins("[log_message] [formatJumpTo(picked_turf, picked_area)]") + new /obj/item/weapon/disk/nuclear(picked_turf) + respawned = 1 diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 6981f9f217f..8455f50a25b 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -1,301 +1,301 @@ -/obj/item/weapon/pinpointer - name = "pinpointer" - icon = 'icons/obj/device.dmi' - icon_state = "pinoff" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - w_class = 2.0 - item_state = "electronic" - throw_speed = 4 - throw_range = 20 - starting_materials = list(MAT_IRON = 500) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_STEEL - var/obj/item/weapon/disk/nuclear/the_disk = null - var/active = 0 - var/watches_nuke = 1 - -/obj/item/weapon/pinpointer/Destroy() - ..() - processing_objects -= src - -/obj/item/weapon/pinpointer/attack_self() - if(!active) - active = 1 - workdisk() - to_chat(usr,"You activate \the [src]") - playsound(get_turf(src), 'sound/items/healthanalyzer.ogg', 30, 1) - processing_objects += src - else - active = 0 - icon_state = "pinoff" - to_chat(usr,"You deactivate \the [src]") - processing_objects -= src - -/obj/item/weapon/pinpointer/proc/workdisk() - if(!the_disk) - the_disk = locate() - the_disk.watched_by += src - process() - -/obj/item/weapon/pinpointer/process() - point_at(the_disk) - -/obj/item/weapon/pinpointer/proc/point_at(atom/target) - if(!active) - return - if(!target) - icon_state = "pinonnull" - return - - var/turf/T = get_turf(target) - var/turf/L = get_turf(src) - update_icon(L,T) - -/obj/item/weapon/pinpointer/update_icon(turf/location,turf/target) - if(!target || !location) - icon_state = "pinonnull" - return - if(target.z != location.z) - icon_state = "pinonnull" - else - dir = get_dir(location,target) - switch(get_dist(location,target)) - if(-1) - icon_state = "pinondirect" - if(1 to 8) - icon_state = "pinonclose" - if(9 to 16) - icon_state = "pinonmedium" - if(16 to INFINITY) - icon_state = "pinonfar" - -/obj/item/weapon/pinpointer/examine(mob/user) - ..() - if(watches_nuke) - var/bomb_timeleft - for(var/obj/machinery/nuclearbomb/bomb in machines) - if(bomb.timing) - bomb_timeleft = bomb.timeleft - if(bomb_timeleft) - to_chat(user,"Extreme danger. Arming signal detected. Time remaining: [bomb_timeleft]") - else - to_chat(user,"No active nuclear devices detected.") - -/obj/item/weapon/pinpointer/advpinpointer - name = "Advanced Pinpointer" - icon = 'icons/obj/device.dmi' - desc = "A larger version of the normal pinpointer, this unit features a helpful quantum entanglement detection system to locate various objects that do not broadcast a locator signal." - var/mode = 0 // Mode 0 locates disk, mode 1 locates coordinates. - var/turf/location = null - var/obj/target = null - watches_nuke = 0 - -/obj/item/weapon/pinpointer/advpinpointer/attack_self() - if(!active) - active = 1 - processing_objects += src - process() - to_chat(usr,"You activate the pinpointer") - else - processing_objects -= src - active = 0 - icon_state = "pinoff" - to_chat(usr,"You deactivate the pinpointer") - -/obj/item/weapon/pinpointer/advpinpointer/process() - switch(mode) - if(0) - workdisk() - if(1) - point_at(location) - if(2) - point_at(target) - -/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode() - set category = "Object" - set name = "Toggle Pinpointer Mode" - set src in view(1) - - active = 0 - icon_state = "pinoff" - target=null - location = null - - switch(alert("Please select the mode you want to put the pinpointer in.", "Pinpointer Mode Select", "Location", "Disk Recovery", "Other Signature")) - if("Location") - mode = 1 - - var/locationx = input(usr, "Please input the x coordinate to search for.", "Location?" , "") as num - if(!locationx || !Adjacent(usr)) - return - var/locationy = input(usr, "Please input the y coordinate to search for.", "Location?" , "") as num - if(!locationy || !!Adjacent(usr)) - return - - var/turf/Z = get_turf(src) - - location = locate(locationx,locationy,Z.z) - - to_chat(usr,"You set the pinpointer to locate [locationx],[locationy]") - - - return attack_self() - - if("Disk Recovery") - mode = 0 - return attack_self() - - if("Other Signature") - mode = 2 - switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA")) - if("Item") - var/list/item_names[0] - var/list/item_paths[0] - for(var/typepath in potential_theft_objectives) - var/obj/item/tmp_object=new typepath - var/n="[tmp_object]" - item_names+=n - item_paths[n]=typepath - qdel(tmp_object) - var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in potential_theft_objectives - if(!targetitem) - return - target=locate(item_paths[targetitem]) - if(!target) - to_chat(usr,"Failed to locate [targetitem]!") - return - to_chat(usr,"You set the pinpointer to locate [targetitem]") - if("DNA") - var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "") - if(!DNAstring) - return - for(var/mob/living/carbon/M in mob_list) - if(!M.dna) - continue - if(M.dna.unique_enzymes == DNAstring) - target = M - break - - return attack_self() - - -/////////////////////// -//nuke op pinpointers// -/////////////////////// - - -/obj/item/weapon/pinpointer/nukeop - var/mode = 0 //Mode 0 locates disk, mode 1 locates the shuttle - var/obj/machinery/computer/shuttle_control/syndicate/home = null - - -/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user as mob) - if(!active) - active = 1 - if(!mode) - to_chat(user,"Authentication Disk Locator active.") - else - to_chat(user,"Shuttle Locator active.") - process() - processing_objects += src - else - active = 0 - icon_state = "pinoff" - to_chat(user,"You deactivate the pinpointer.") - processing_objects -= src - - -/obj/item/weapon/pinpointer/nukeop/process() - if(mode) //Check in case the mode changes while operating - worklocation() - else - workdisk() - -/obj/item/weapon/pinpointer/nukeop/workdisk() - if(bomb_set) //If the bomb is set, lead to the shuttle - mode = 1 //Ensures worklocation() continues to work - worklocation() - playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep - visible_message("Shuttle Locator active.") //Lets the mob holding it know that the mode has changed - return //Get outta here - if(!the_disk) - the_disk = locate() - the_disk.watched_by += src - if(!the_disk) - icon_state = "pinonnull" - return - point_at(the_disk) - - -/obj/item/weapon/pinpointer/nukeop/proc/worklocation() - if(!bomb_set) - mode = 0 - workdisk() - playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) - visible_message("Authentication Disk Locator active.") - return - if(!home) - home = locate() - if(!home) - icon_state = "pinonnull" - return - point_at(home) - -/obj/item/weapon/pinpointer/pdapinpointer - name = "pda pinpointer" - desc = "A pinpointer that has been illegally modified to track the PDA of a crewmember for malicious reasons." - var/obj/target = null - var/used = 0 - watches_nuke = 0 - -/obj/item/weapon/pinpointer/pdapinpointer/attack_self() - if(!active) - active = 1 - process() - processing_objects += src - to_chat(usr,"You activate the pinpointer") - else - active = 0 - processing_objects -= src - icon_state = "pinoff" - to_chat(usr,"You deactivate the pinpointer") - -/obj/item/weapon/pinpointer/pdapinpointer/process() - point_at(target) - -/obj/item/weapon/pinpointer/pdapinpointer/verb/select_pda() - set category = "Object" - set name = "Select pinpointer target" - set src in view(1) - - if(used) - to_chat(usr,"Target has already been set!") - return - - var/list/L = list() - L["Cancel"] = "Cancel" - var/length = 1 - for (var/obj/item/device/pda/P in world) - if(P.name != "\improper PDA") - L[text("([length]) [P.name]")] = P - length++ - - var/t = input("Select pinpointer target. WARNING: Can only set once.") as null|anything in L - if(t == "Cancel") - return - target = L[t] - if(!target) - to_chat(usr,"Failed to locate [target]!") - return - active = 1 - point_at(target) - to_chat(usr,"You set the pinpointer to locate [target]") - used = 1 - - -/obj/item/weapon/pinpointer/pdapinpointer/examine(mob/user) - ..() - if (target) - to_chat(user,"Tracking [target]") +/obj/item/weapon/pinpointer + name = "pinpointer" + icon = 'icons/obj/device.dmi' + icon_state = "pinoff" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + w_class = 2.0 + item_state = "electronic" + throw_speed = 4 + throw_range = 20 + starting_materials = list(MAT_IRON = 500) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_STEEL + var/obj/item/weapon/disk/nuclear/the_disk = null + var/active = 0 + var/watches_nuke = 1 + +/obj/item/weapon/pinpointer/Destroy() + ..() + processing_objects -= src + +/obj/item/weapon/pinpointer/attack_self() + if(!active) + active = 1 + workdisk() + to_chat(usr,"You activate \the [src]") + playsound(get_turf(src), 'sound/items/healthanalyzer.ogg', 30, 1) + processing_objects += src + else + active = 0 + icon_state = "pinoff" + to_chat(usr,"You deactivate \the [src]") + processing_objects -= src + +/obj/item/weapon/pinpointer/proc/workdisk() + if(!the_disk) + the_disk = locate() + the_disk.watched_by += src + process() + +/obj/item/weapon/pinpointer/process() + point_at(the_disk) + +/obj/item/weapon/pinpointer/proc/point_at(atom/target) + if(!active) + return + if(!target) + icon_state = "pinonnull" + return + + var/turf/T = get_turf(target) + var/turf/L = get_turf(src) + update_icon(L,T) + +/obj/item/weapon/pinpointer/update_icon(turf/location,turf/target) + if(!target || !location) + icon_state = "pinonnull" + return + if(target.z != location.z) + icon_state = "pinonnull" + else + dir = get_dir(location,target) + switch(get_dist(location,target)) + if(-1) + icon_state = "pinondirect" + if(1 to 8) + icon_state = "pinonclose" + if(9 to 16) + icon_state = "pinonmedium" + if(16 to INFINITY) + icon_state = "pinonfar" + +/obj/item/weapon/pinpointer/examine(mob/user) + ..() + if(watches_nuke) + var/bomb_timeleft + for(var/obj/machinery/nuclearbomb/bomb in machines) + if(bomb.timing) + bomb_timeleft = bomb.timeleft + if(bomb_timeleft) + to_chat(user,"Extreme danger. Arming signal detected. Time remaining: [bomb_timeleft]") + else + to_chat(user,"No active nuclear devices detected.") + +/obj/item/weapon/pinpointer/advpinpointer + name = "Advanced Pinpointer" + icon = 'icons/obj/device.dmi' + desc = "A larger version of the normal pinpointer, this unit features a helpful quantum entanglement detection system to locate various objects that do not broadcast a locator signal." + var/mode = 0 // Mode 0 locates disk, mode 1 locates coordinates. + var/turf/location = null + var/obj/target = null + watches_nuke = 0 + +/obj/item/weapon/pinpointer/advpinpointer/attack_self() + if(!active) + active = 1 + processing_objects += src + process() + to_chat(usr,"You activate the pinpointer") + else + processing_objects -= src + active = 0 + icon_state = "pinoff" + to_chat(usr,"You deactivate the pinpointer") + +/obj/item/weapon/pinpointer/advpinpointer/process() + switch(mode) + if(0) + workdisk() + if(1) + point_at(location) + if(2) + point_at(target) + +/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode() + set category = "Object" + set name = "Toggle Pinpointer Mode" + set src in view(1) + + active = 0 + icon_state = "pinoff" + target=null + location = null + + switch(alert("Please select the mode you want to put the pinpointer in.", "Pinpointer Mode Select", "Location", "Disk Recovery", "Other Signature")) + if("Location") + mode = 1 + + var/locationx = input(usr, "Please input the x coordinate to search for.", "Location?" , "") as num + if(!locationx || !Adjacent(usr)) + return + var/locationy = input(usr, "Please input the y coordinate to search for.", "Location?" , "") as num + if(!locationy || !!Adjacent(usr)) + return + + var/turf/Z = get_turf(src) + + location = locate(locationx,locationy,Z.z) + + to_chat(usr,"You set the pinpointer to locate [locationx],[locationy]") + + + return attack_self() + + if("Disk Recovery") + mode = 0 + return attack_self() + + if("Other Signature") + mode = 2 + switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA")) + if("Item") + var/list/item_names[0] + var/list/item_paths[0] + for(var/typepath in potential_theft_objectives) + var/obj/item/tmp_object=new typepath + var/n="[tmp_object]" + item_names+=n + item_paths[n]=typepath + qdel(tmp_object) + var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in potential_theft_objectives + if(!targetitem) + return + target=locate(item_paths[targetitem]) + if(!target) + to_chat(usr,"Failed to locate [targetitem]!") + return + to_chat(usr,"You set the pinpointer to locate [targetitem]") + if("DNA") + var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "") + if(!DNAstring) + return + for(var/mob/living/carbon/M in mob_list) + if(!M.dna) + continue + if(M.dna.unique_enzymes == DNAstring) + target = M + break + + return attack_self() + + +/////////////////////// +//nuke op pinpointers// +/////////////////////// + + +/obj/item/weapon/pinpointer/nukeop + var/mode = 0 //Mode 0 locates disk, mode 1 locates the shuttle + var/obj/machinery/computer/shuttle_control/syndicate/home = null + + +/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user as mob) + if(!active) + active = 1 + if(!mode) + to_chat(user,"Authentication Disk Locator active.") + else + to_chat(user,"Shuttle Locator active.") + process() + processing_objects += src + else + active = 0 + icon_state = "pinoff" + to_chat(user,"You deactivate the pinpointer.") + processing_objects -= src + + +/obj/item/weapon/pinpointer/nukeop/process() + if(mode) //Check in case the mode changes while operating + worklocation() + else + workdisk() + +/obj/item/weapon/pinpointer/nukeop/workdisk() + if(bomb_set) //If the bomb is set, lead to the shuttle + mode = 1 //Ensures worklocation() continues to work + worklocation() + playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep + visible_message("Shuttle Locator active.") //Lets the mob holding it know that the mode has changed + return //Get outta here + if(!the_disk) + the_disk = locate() + the_disk.watched_by += src + if(!the_disk) + icon_state = "pinonnull" + return + point_at(the_disk) + + +/obj/item/weapon/pinpointer/nukeop/proc/worklocation() + if(!bomb_set) + mode = 0 + workdisk() + playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) + visible_message("Authentication Disk Locator active.") + return + if(!home) + home = locate() + if(!home) + icon_state = "pinonnull" + return + point_at(home) + +/obj/item/weapon/pinpointer/pdapinpointer + name = "pda pinpointer" + desc = "A pinpointer that has been illegally modified to track the PDA of a crewmember for malicious reasons." + var/obj/target = null + var/used = 0 + watches_nuke = 0 + +/obj/item/weapon/pinpointer/pdapinpointer/attack_self() + if(!active) + active = 1 + process() + processing_objects += src + to_chat(usr,"You activate the pinpointer") + else + active = 0 + processing_objects -= src + icon_state = "pinoff" + to_chat(usr,"You deactivate the pinpointer") + +/obj/item/weapon/pinpointer/pdapinpointer/process() + point_at(target) + +/obj/item/weapon/pinpointer/pdapinpointer/verb/select_pda() + set category = "Object" + set name = "Select pinpointer target" + set src in view(1) + + if(used) + to_chat(usr,"Target has already been set!") + return + + var/list/L = list() + L["Cancel"] = "Cancel" + var/length = 1 + for (var/obj/item/device/pda/P in world) + if(P.name != "\improper PDA") + L[text("([length]) [P.name]")] = P + length++ + + var/t = input("Select pinpointer target. WARNING: Can only set once.") as null|anything in L + if(t == "Cancel") + return + target = L[t] + if(!target) + to_chat(usr,"Failed to locate [target]!") + return + active = 1 + point_at(target) + to_chat(usr,"You set the pinpointer to locate [target]") + used = 1 + + +/obj/item/weapon/pinpointer/pdapinpointer/examine(mob/user) + ..() + if (target) + to_chat(user,"Tracking [target]") diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 2923404d6ec..c0537dff183 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1,721 +1,721 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -var/list/potential_theft_objectives=list( - "traitor" = typesof(/datum/theft_objective/traitor) - /datum/theft_objective/traitor, - "special" = typesof(/datum/theft_objective/special) - /datum/theft_objective/special, - "heist" = typesof(/datum/theft_objective/number/heist) - /datum/theft_objective/number/heist, - "salvage" = typesof(/datum/theft_objective/number/salvage) - /datum/theft_objective/number/salvage -) - - -/datum/objective - var/datum/mind/owner = null //Who owns the objective. - var/explanation_text = "Nothing" //What that person is supposed to do. - var/datum/mind/target = null //If they are focused on a particular person. - var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter. - var/completed = 0 //currently only used for custom objectives. - var/blocked = 0 // Universe fucked, you lost. - var/list/bad_targets = list("AI","Cyborg","Mobile MMI")//For roundstart cases where they are still human at the time of objective assignment - - New(var/text) - if(text) - explanation_text = text - - proc/check_completion() - return completed - - proc/find_target() - var/list/possible_targets = list() - for(var/datum/mind/possible_target in ticker.minds) - if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.z != map.zCentcomm) && (possible_target.current.stat != DEAD) && !(possible_target.assigned_role in bad_targets)) - possible_targets += possible_target - if(possible_targets.len > 0) - target = pick(possible_targets) - - - proc/find_target_by_role(role, role_type = 0)//Option sets either to check assigned role or special role. Default to assigned. - for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && ishuman(possible_target.current) && (possible_target.current.z != map.zCentcomm) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) && !(possible_target.assigned_role in bad_targets)) - target = possible_target - break - - - -/datum/objective/assassinate - find_target() - ..() - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." - else - explanation_text = "Free Objective" - return target - - - check_completion() - if(target && target.current && !blocked) - if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > 6 || !target.current.ckey || isborer(target.current)) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite - return 1 - return 0 - return 1 - - - -/datum/objective/mutiny - find_target() - ..() - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(target && target.current && !blocked) - if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey) - return 1 - var/turf/T = get_turf(target.current) - if(T && (T.z != 1)) //If they leave the station they count as dead for this - return 2 - return 0 - return 1 - -/datum/objective/mutiny/rp - find_target() - ..() - if(target && target.current) - explanation_text = "Assassinate, capture or convert [target.current.real_name], the [target.assigned_role]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Assassinate, capture or convert [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." - else - explanation_text = "Free Objective" - return target - - // less violent rev objectives - check_completion() - var/rval = 1 - if(target && target.current && !blocked) - //assume that only carbon mobs can become rev heads for now - if(target.current.stat == DEAD || target.current:handcuffed || !ishuman(target.current)) - return 1 - // Check if they're converted - if(istype(ticker.mode, /datum/game_mode/revolution)) - if(target in ticker.mode:head_revolutionaries) - return 1 - var/turf/T = get_turf(target.current) - if(T && (T.z != 1)) //If they leave the station they count as dead for this - rval = 2 - return 0 - return rval - -/datum/objective/anti_revolution/execute - find_target() - ..() - if(target && target.current) - explanation_text = "[target.current.real_name], the [target.assigned_role] has extracted confidential information above their clearance. Execute \him[target.current]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has extracted confidential information above their clearance. Execute \him[target.current]." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(target && target.current) - if(target.current.stat == DEAD || !ishuman(target.current)) - return 1 - return 0 - return 1 - -/datum/objective/anti_revolution/brig - var/already_completed = 0 - - find_target() - ..() - if(target && target.current) - explanation_text = "Brig [target.current.real_name], the [target.assigned_role] for 20 minutes to set an example." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Brig [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] for 20 minutes to set an example." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(blocked) return 0 - if(already_completed) - return 1 - - if(target && target.current) - if(target.current.stat == DEAD) - return 0 - if(target.is_brigged(10 * 60 * 10)) - already_completed = 1 - return 1 - return 0 - return 0 - -/datum/objective/anti_revolution/demote - find_target() - ..() - if(target && target.current) - explanation_text = "[target.current.real_name], the [target.assigned_role] has been classified as harmful to NanoTrasen's goals. Demote \him[target.current] to assistant." - else - explanation_text = "Free Objective" - return target - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has been classified as harmful to NanoTrasen's goals. Demote \him[target.current] to assistant." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(blocked) return 0 - if(target && target.current && istype(target,/mob/living/carbon/human)) - var/obj/item/weapon/card/id/I = target.current:wear_id - if(istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/P = I - I = P.id - - if(!istype(I)) return 1 - - if(I.assignment == "Assistant") - return 1 - else - return 0 - return 1 - -/datum/objective/debrain//I want braaaainssss - find_target() - ..() - if(target && target.current) - explanation_text = "Steal the brain of [target.current.real_name]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Steal the brain of [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role]." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(blocked) return 0 - if(!target)//If it's a free objective. - return 1 - if( !owner.current || owner.current.stat==DEAD )//If you're otherwise dead. - return 0 - if( !target.current || !isbrain(target.current) ) - return 0 - var/atom/A = target.current - while(A.loc) //check to see if the brainmob is on our person - A = A.loc - if(A == owner.current) - return 1 - return 0 - - -/datum/objective/protect//The opposite of killing a dude. - find_target() - ..() - if(target && target.current) - explanation_text = "Protect [target.current.real_name], the [target.assigned_role]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Protect [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(blocked) return 0 - if(!target) //If it's a free objective. - return 1 - if(target.current) - if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || isborer(target.current)) - return 0 - return 1 - return 0 - - -/datum/objective/hijack - explanation_text = "Hijack the emergency shuttle by escaping without any organic life-forms, other than yourself." - - check_completion() - if(blocked) return 0 - if(!owner.current || owner.current.stat) - return 0 - if(emergency_shuttle.location<2) - return 0 - if(issilicon(owner.current)) - return 0 - var/area/shuttle = locate(/area/shuttle/escape/centcom) - var/list/protected_mobs = list(/mob/living/silicon/ai, /mob/living/silicon/pai) - // Implemented in response to 21/12/2013 player vote, . - // Comment this if you want Borgs and MoMMIs counted. - // TODO: Check if borgs are subverted. Best I can think of is a fuzzy check for strings used in syndie laws. BYOND can't do regex, sadly. - N3X - protected_mobs += list(/mob/living/silicon/robot, /mob/living/silicon/robot/mommi) - for(var/mob/living/player in player_list) - if(player.type in protected_mobs) continue - if (player.mind && (player.mind != owner)) - if(player.stat != DEAD) //they're not dead! - if(get_turf(player) in shuttle) - return 0 - return 1 - - -/datum/objective/block - explanation_text = "Do not allow any organic lifeforms to escape on the shuttle alive." - - check_completion() - if(blocked) return 0 - if(!istype(owner.current, /mob/living/silicon)) - return 0 - if(emergency_shuttle.location<2) - return 0 - if(!owner.current) - return 0 - var/area/shuttle = locate(/area/shuttle/escape/centcom) - var/protected_mobs[] = list(/mob/living/silicon/ai, /mob/living/silicon/pai, /mob/living/silicon/robot, /mob/living/silicon/robot/mommi) - for(var/mob/living/player in player_list) - if(player.type in protected_mobs) continue - if (player.mind) - if (player.stat != 2) - if (get_turf(player) in shuttle) - return 0 - return 1 - -/datum/objective/silence - explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left." - - check_completion() - if(blocked) return 0 - if(emergency_shuttle.location<2) - return 0 - - for(var/mob/living/player in player_list) - if(player == owner.current) - continue - if(player.mind) - if(player.stat != DEAD) - var/turf/T = get_turf(player) - if(!T) continue - switch(T.loc.type) - if(/area/shuttle/escape/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) - return 0 - return 1 - - -/datum/objective/escape - explanation_text = "Escape on the shuttle or an escape pod alive and free." - - check_completion() - if(blocked) return 0 - if(issilicon(owner.current)) - return 0 - if(isbrain(owner.current) || isborer(owner.current)) - return 0 - if(emergency_shuttle.location<2) - return 0 - if(!owner.current || owner.current.stat ==2) - return 0 - var/turf/location = get_turf(owner.current.loc) - if(!location) - return 0 - - if(istype(location, /turf/simulated/shuttle/floor4)) // Fails tratiors if they are in the shuttle brig -- Polymorph - if(istype(owner.current, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = owner.current - if(!H.restrained()) // Technically, traitors will fail the objective if they are time stopped by a wizard - return 1 - else if(istype(owner.current, /mob/living/carbon)) // I don't think non-humanoid carbons can get the escape objective, but I'm leaving it to be safe - var/mob/living/carbon/C = owner.current - if (!C.handcuffed) - return 1 - return 0 - - var/area/check_area = location.loc - if(istype(check_area, /area/shuttle/escape/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod1/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod2/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod3/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod5/centcom)) - return 1 - else - return 0 - -/datum/objective/die - explanation_text = "Die a glorious death." - - check_completion() - if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current) || isborer(owner.current)) - return 1 //Brains no longer win survive objectives. --NEO - if(issilicon(owner.current) && owner.current != owner.original) - return 1 - return 0 - - - -/datum/objective/survive - explanation_text = "Stay alive until the end." - - check_completion() - if(blocked) return 0 - if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current) || isborer(owner.current)) - return 0 //Brains no longer win survive objectives. --NEO - if(issilicon(owner.current) && owner.current != owner.original) - return 0 - return 1 - - - -/datum/objective/multiply - explanation_text = "Procreate, and protect your spawn." - var/already_completed=0 - check_completion() - if(blocked) return 0 - if(already_completed) - return 1 - if(!owner.current) - return 0 - var/mob/living/simple_animal/borer/B=owner.current - if(!istype(B)) - return 0 - if(B.numChildren>0) - already_completed=1 - return 1 - return 0 - -// Similar to the anti-rev objective, but for traitors -/datum/objective/brig - var/already_completed = 0 - - find_target() - ..() - if(target && target.current) - explanation_text = "Have [target.current.real_name], the [target.assigned_role] brigged for 10 minutes." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Have [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] brigged for 10 minutes." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(blocked) return 0 - if(already_completed) - return 1 - - if(target && target.current) - if(target.current.stat == DEAD) - return 0 - // Make the actual required time a bit shorter than the official time - if(target.is_brigged(10 * 60 * 5)) - already_completed = 1 - return 1 - return 0 - return 0 - -// Harm a crew member, making an example of them -/datum/objective/harm - var/already_completed = 0 - - find_target() - ..() - if(target && target.current) - explanation_text = "Make an example of [target.current.real_name], the [target.assigned_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Make an example of [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." - else - explanation_text = "Free Objective" - return target - - check_completion() - if(blocked) return 0 - if(already_completed) - return 1 - - if(target && target.current && istype(target.current, /mob/living/carbon/human)) - if(target.current.stat == DEAD) - return 0 - - var/mob/living/carbon/human/H = target.current - for(var/datum/organ/external/E in H.organs) - if(E.status & ORGAN_BROKEN) - already_completed = 1 - return 1 - if(E.status & ORGAN_DESTROYED && !E.amputated) - already_completed = 1 - return 1 - - var/datum/organ/external/head/head = H.get_organ("head") - if(head.disfigured) - return 1 - return 0 - - -/datum/objective/nuclear - explanation_text = "Destroy the station with a nuclear device." - - - -/datum/objective/steal - var/target_category = "traitor" - var/datum/theft_objective/steal_target - - find_target() - var/list/possibleObjectives = potential_theft_objectives[target_category] - var/loopSanity = possibleObjectives.len - - while(isnull(steal_target) && loopSanity > 0) - loopSanity-- - - var/pickedObjective = pick(possibleObjectives) - var/datum/theft_objective/objective = new pickedObjective - - if(owner && owner.assigned_role in objective.protected_jobs) - continue - - steal_target = objective - explanation_text = format_explanation() - return - - explanation_text = "Free Objective." - - proc/format_explanation() - return "Steal [steal_target.name]." - - proc/select_target() - var/list/possible_items_all = potential_theft_objectives[target_category]+"custom" - var/new_target = input("Select target:", "Objective target", null) as null|anything in possible_items_all - if (!new_target) return - if (new_target == "custom") - var/datum/theft_objective/O=new - O.typepath = input("Select type:","Type") as null|anything in typesof(/obj/item) - if (!O.typepath) return - var/tmp_obj = new O.typepath - var/custom_name = tmp_obj:name - qdel(tmp_obj) - O.name = copytext(sanitize(input("Enter target name:", "Objective target", custom_name) as text|null),1,MAX_NAME_LEN) - if (!O.name) return - steal_target = O - explanation_text = format_explanation() - else - steal_target = new new_target - explanation_text = format_explanation() - return steal_target - - check_completion() - if(blocked) return 0 - if(!steal_target) return 1 // Free Objective - return steal_target.check_completion(owner) - -/datum/objective/capture - proc/gen_amount_goal() - target_amount = rand(5,10) - explanation_text = "Accumulate [target_amount] capture points." - return target_amount - - - check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. - if(blocked) return 0 - var/captured_amount = 0 - var/area/centcom/holding/A = locate() - for(var/mob/living/carbon/human/M in A)//Humans. - if(M.stat==2)//Dead folks are worth less. - captured_amount+=0.5 - continue - captured_amount+=1 - for(var/mob/living/carbon/monkey/M in A)//Monkeys are almost worthless, you failure. - captured_amount+=0.1 - for(var/mob/living/carbon/alien/larva/M in A)//Larva are important for research. - if(M.stat==2) - captured_amount+=0.5 - continue - captured_amount+=1 - for(var/mob/living/carbon/alien/humanoid/M in A)//Aliens are worth twice as much as humans. - if(istype(M, /mob/living/carbon/alien/humanoid/queen))//Queens are worth three times as much as humans. - if(M.stat==2) - captured_amount+=1.5 - else - captured_amount+=3 - continue - if(M.stat==2) - captured_amount+=1 - continue - captured_amount+=2 - if(captured_amount= target_amount) - return 1 - else - return 0 -/datum/objective/absorb - proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) - target_amount = rand (lowbound,highbound) - if (ticker) - var/n_p = 1 //autowin - if (ticker.current_state == GAME_STATE_SETTING_UP) - for(var/mob/new_player/P in player_list) - if(P.client && P.ready && P.mind!=owner) - n_p ++ - else if (ticker.current_state == GAME_STATE_PLAYING) - for(var/mob/living/carbon/human/P in player_list) - if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) - n_p ++ - target_amount = min(target_amount, n_p) - - explanation_text = "Absorb [target_amount] compatible genomes." - return target_amount - - check_completion() - if(blocked) return 0 - if(owner && owner.changeling && owner.changeling.absorbed_dna && (owner.changeling.absorbedcount >= target_amount)) - return 1 - else - return 0 - - - -/* Isn't suited for global objectives -/*---------CULTIST----------*/ - - eldergod - explanation_text = "Summon Nar-Sie via the use of an appropriate rune. It will only work if nine cultists stand on and around it." - - check_completion() - if(eldergod) //global var, defined in rune4.dm - return 1 - return 0 - - survivecult - var/num_cult - - explanation_text = "Our knowledge must live on. Make sure at least 5 acolytes escape on the shuttle to spread their work on an another station." - - check_completion() - if(emergency_shuttle.location<2) - return 0 - - var/cultists_escaped = 0 - - var/area/shuttle/escape/centcom/C = /area/shuttle/escape/centcom - for(var/turf/T in get_area_turfs(C.type)) - for(var/mob/living/carbon/H in T) - if(iscultist(H)) - cultists_escaped++ - - if(cultists_escaped>=5) - return 1 - - return 0 - - sacrifice //stolen from traitor target objective - - proc/find_target() //I don't know how to make it work with the rune otherwise, so I'll do it via a global var, sacrifice_target, defined in rune15.dm - var/list/possible_targets = call(/datum/game_mode/cult/proc/get_unconvertables)() - - - if(possible_targets.len > 0) - sacrifice_target = pick(possible_targets) - - if(sacrifice_target && sacrifice_target.current) - explanation_text = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell join blood) and three acolytes to do so." - else - explanation_text = "Free Objective" - - return sacrifice_target - - check_completion() //again, calling on a global list defined in rune15.dm - if(sacrifice_target.current in sacrificed) - return 1 - else - return 0 - -/*-------ENDOF CULTIST------*/ -*/ - -// /vg/; Vox Inviolate for humans :V -/datum/objective/minimize_casualties - explanation_text = "Minimise casualties." - check_completion() - if(blocked) return 0 - if(owner.kills.len>5) return 0 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +var/list/potential_theft_objectives=list( + "traitor" = typesof(/datum/theft_objective/traitor) - /datum/theft_objective/traitor, + "special" = typesof(/datum/theft_objective/special) - /datum/theft_objective/special, + "heist" = typesof(/datum/theft_objective/number/heist) - /datum/theft_objective/number/heist, + "salvage" = typesof(/datum/theft_objective/number/salvage) - /datum/theft_objective/number/salvage +) + + +/datum/objective + var/datum/mind/owner = null //Who owns the objective. + var/explanation_text = "Nothing" //What that person is supposed to do. + var/datum/mind/target = null //If they are focused on a particular person. + var/target_amount = 0 //If they are focused on a particular number. Steal objectives have their own counter. + var/completed = 0 //currently only used for custom objectives. + var/blocked = 0 // Universe fucked, you lost. + var/list/bad_targets = list("AI","Cyborg","Mobile MMI")//For roundstart cases where they are still human at the time of objective assignment + + New(var/text) + if(text) + explanation_text = text + + proc/check_completion() + return completed + + proc/find_target() + var/list/possible_targets = list() + for(var/datum/mind/possible_target in ticker.minds) + if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.z != map.zCentcomm) && (possible_target.current.stat != DEAD) && !(possible_target.assigned_role in bad_targets)) + possible_targets += possible_target + if(possible_targets.len > 0) + target = pick(possible_targets) + + + proc/find_target_by_role(role, role_type = 0)//Option sets either to check assigned role or special role. Default to assigned. + for(var/datum/mind/possible_target in ticker.minds) + if((possible_target != owner) && ishuman(possible_target.current) && (possible_target.current.z != map.zCentcomm) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) && !(possible_target.assigned_role in bad_targets)) + target = possible_target + break + + + +/datum/objective/assassinate + find_target() + ..() + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + else + explanation_text = "Free Objective" + return target + + + check_completion() + if(target && target.current && !blocked) + if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > 6 || !target.current.ckey || isborer(target.current)) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite + return 1 + return 0 + return 1 + + + +/datum/objective/mutiny + find_target() + ..() + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(target && target.current && !blocked) + if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey) + return 1 + var/turf/T = get_turf(target.current) + if(T && (T.z != 1)) //If they leave the station they count as dead for this + return 2 + return 0 + return 1 + +/datum/objective/mutiny/rp + find_target() + ..() + if(target && target.current) + explanation_text = "Assassinate, capture or convert [target.current.real_name], the [target.assigned_role]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Assassinate, capture or convert [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + else + explanation_text = "Free Objective" + return target + + // less violent rev objectives + check_completion() + var/rval = 1 + if(target && target.current && !blocked) + //assume that only carbon mobs can become rev heads for now + if(target.current.stat == DEAD || target.current:handcuffed || !ishuman(target.current)) + return 1 + // Check if they're converted + if(istype(ticker.mode, /datum/game_mode/revolution)) + if(target in ticker.mode:head_revolutionaries) + return 1 + var/turf/T = get_turf(target.current) + if(T && (T.z != 1)) //If they leave the station they count as dead for this + rval = 2 + return 0 + return rval + +/datum/objective/anti_revolution/execute + find_target() + ..() + if(target && target.current) + explanation_text = "[target.current.real_name], the [target.assigned_role] has extracted confidential information above their clearance. Execute \him[target.current]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has extracted confidential information above their clearance. Execute \him[target.current]." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(target && target.current) + if(target.current.stat == DEAD || !ishuman(target.current)) + return 1 + return 0 + return 1 + +/datum/objective/anti_revolution/brig + var/already_completed = 0 + + find_target() + ..() + if(target && target.current) + explanation_text = "Brig [target.current.real_name], the [target.assigned_role] for 20 minutes to set an example." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Brig [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] for 20 minutes to set an example." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(blocked) return 0 + if(already_completed) + return 1 + + if(target && target.current) + if(target.current.stat == DEAD) + return 0 + if(target.is_brigged(10 * 60 * 10)) + already_completed = 1 + return 1 + return 0 + return 0 + +/datum/objective/anti_revolution/demote + find_target() + ..() + if(target && target.current) + explanation_text = "[target.current.real_name], the [target.assigned_role] has been classified as harmful to NanoTrasen's goals. Demote \him[target.current] to assistant." + else + explanation_text = "Free Objective" + return target + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] has been classified as harmful to NanoTrasen's goals. Demote \him[target.current] to assistant." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(blocked) return 0 + if(target && target.current && istype(target,/mob/living/carbon/human)) + var/obj/item/weapon/card/id/I = target.current:wear_id + if(istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/P = I + I = P.id + + if(!istype(I)) return 1 + + if(I.assignment == "Assistant") + return 1 + else + return 0 + return 1 + +/datum/objective/debrain//I want braaaainssss + find_target() + ..() + if(target && target.current) + explanation_text = "Steal the brain of [target.current.real_name]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Steal the brain of [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role]." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(blocked) return 0 + if(!target)//If it's a free objective. + return 1 + if( !owner.current || owner.current.stat==DEAD )//If you're otherwise dead. + return 0 + if( !target.current || !isbrain(target.current) ) + return 0 + var/atom/A = target.current + while(A.loc) //check to see if the brainmob is on our person + A = A.loc + if(A == owner.current) + return 1 + return 0 + + +/datum/objective/protect//The opposite of killing a dude. + find_target() + ..() + if(target && target.current) + explanation_text = "Protect [target.current.real_name], the [target.assigned_role]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Protect [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(blocked) return 0 + if(!target) //If it's a free objective. + return 1 + if(target.current) + if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || isborer(target.current)) + return 0 + return 1 + return 0 + + +/datum/objective/hijack + explanation_text = "Hijack the emergency shuttle by escaping without any organic life-forms, other than yourself." + + check_completion() + if(blocked) return 0 + if(!owner.current || owner.current.stat) + return 0 + if(emergency_shuttle.location<2) + return 0 + if(issilicon(owner.current)) + return 0 + var/area/shuttle = locate(/area/shuttle/escape/centcom) + var/list/protected_mobs = list(/mob/living/silicon/ai, /mob/living/silicon/pai) + // Implemented in response to 21/12/2013 player vote, . + // Comment this if you want Borgs and MoMMIs counted. + // TODO: Check if borgs are subverted. Best I can think of is a fuzzy check for strings used in syndie laws. BYOND can't do regex, sadly. - N3X + protected_mobs += list(/mob/living/silicon/robot, /mob/living/silicon/robot/mommi) + for(var/mob/living/player in player_list) + if(player.type in protected_mobs) continue + if (player.mind && (player.mind != owner)) + if(player.stat != DEAD) //they're not dead! + if(get_turf(player) in shuttle) + return 0 + return 1 + + +/datum/objective/block + explanation_text = "Do not allow any organic lifeforms to escape on the shuttle alive." + + check_completion() + if(blocked) return 0 + if(!istype(owner.current, /mob/living/silicon)) + return 0 + if(emergency_shuttle.location<2) + return 0 + if(!owner.current) + return 0 + var/area/shuttle = locate(/area/shuttle/escape/centcom) + var/protected_mobs[] = list(/mob/living/silicon/ai, /mob/living/silicon/pai, /mob/living/silicon/robot, /mob/living/silicon/robot/mommi) + for(var/mob/living/player in player_list) + if(player.type in protected_mobs) continue + if (player.mind) + if (player.stat != 2) + if (get_turf(player) in shuttle) + return 0 + return 1 + +/datum/objective/silence + explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left." + + check_completion() + if(blocked) return 0 + if(emergency_shuttle.location<2) + return 0 + + for(var/mob/living/player in player_list) + if(player == owner.current) + continue + if(player.mind) + if(player.stat != DEAD) + var/turf/T = get_turf(player) + if(!T) continue + switch(T.loc.type) + if(/area/shuttle/escape/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) + return 0 + return 1 + + +/datum/objective/escape + explanation_text = "Escape on the shuttle or an escape pod alive and free." + + check_completion() + if(blocked) return 0 + if(issilicon(owner.current)) + return 0 + if(isbrain(owner.current) || isborer(owner.current)) + return 0 + if(emergency_shuttle.location<2) + return 0 + if(!owner.current || owner.current.stat ==2) + return 0 + var/turf/location = get_turf(owner.current.loc) + if(!location) + return 0 + + if(istype(location, /turf/simulated/shuttle/floor4)) // Fails tratiors if they are in the shuttle brig -- Polymorph + if(istype(owner.current, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = owner.current + if(!H.restrained()) // Technically, traitors will fail the objective if they are time stopped by a wizard + return 1 + else if(istype(owner.current, /mob/living/carbon)) // I don't think non-humanoid carbons can get the escape objective, but I'm leaving it to be safe + var/mob/living/carbon/C = owner.current + if (!C.handcuffed) + return 1 + return 0 + + var/area/check_area = location.loc + if(istype(check_area, /area/shuttle/escape/centcom)) + return 1 + if(istype(check_area, /area/shuttle/escape_pod1/centcom)) + return 1 + if(istype(check_area, /area/shuttle/escape_pod2/centcom)) + return 1 + if(istype(check_area, /area/shuttle/escape_pod3/centcom)) + return 1 + if(istype(check_area, /area/shuttle/escape_pod5/centcom)) + return 1 + else + return 0 + +/datum/objective/die + explanation_text = "Die a glorious death." + + check_completion() + if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current) || isborer(owner.current)) + return 1 //Brains no longer win survive objectives. --NEO + if(issilicon(owner.current) && owner.current != owner.original) + return 1 + return 0 + + + +/datum/objective/survive + explanation_text = "Stay alive until the end." + + check_completion() + if(blocked) return 0 + if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current) || isborer(owner.current)) + return 0 //Brains no longer win survive objectives. --NEO + if(issilicon(owner.current) && owner.current != owner.original) + return 0 + return 1 + + + +/datum/objective/multiply + explanation_text = "Procreate, and protect your spawn." + var/already_completed=0 + check_completion() + if(blocked) return 0 + if(already_completed) + return 1 + if(!owner.current) + return 0 + var/mob/living/simple_animal/borer/B=owner.current + if(!istype(B)) + return 0 + if(B.numChildren>0) + already_completed=1 + return 1 + return 0 + +// Similar to the anti-rev objective, but for traitors +/datum/objective/brig + var/already_completed = 0 + + find_target() + ..() + if(target && target.current) + explanation_text = "Have [target.current.real_name], the [target.assigned_role] brigged for 10 minutes." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Have [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] brigged for 10 minutes." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(blocked) return 0 + if(already_completed) + return 1 + + if(target && target.current) + if(target.current.stat == DEAD) + return 0 + // Make the actual required time a bit shorter than the official time + if(target.is_brigged(10 * 60 * 5)) + already_completed = 1 + return 1 + return 0 + return 0 + +// Harm a crew member, making an example of them +/datum/objective/harm + var/already_completed = 0 + + find_target() + ..() + if(target && target.current) + explanation_text = "Make an example of [target.current.real_name], the [target.assigned_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Make an example of [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(blocked) return 0 + if(already_completed) + return 1 + + if(target && target.current && istype(target.current, /mob/living/carbon/human)) + if(target.current.stat == DEAD) + return 0 + + var/mob/living/carbon/human/H = target.current + for(var/datum/organ/external/E in H.organs) + if(E.status & ORGAN_BROKEN) + already_completed = 1 + return 1 + if(E.status & ORGAN_DESTROYED && !E.amputated) + already_completed = 1 + return 1 + + var/datum/organ/external/head/head = H.get_organ("head") + if(head.disfigured) + return 1 + return 0 + + +/datum/objective/nuclear + explanation_text = "Destroy the station with a nuclear device." + + + +/datum/objective/steal + var/target_category = "traitor" + var/datum/theft_objective/steal_target + + find_target() + var/list/possibleObjectives = potential_theft_objectives[target_category] + var/loopSanity = possibleObjectives.len + + while(isnull(steal_target) && loopSanity > 0) + loopSanity-- + + var/pickedObjective = pick(possibleObjectives) + var/datum/theft_objective/objective = new pickedObjective + + if(owner && owner.assigned_role in objective.protected_jobs) + continue + + steal_target = objective + explanation_text = format_explanation() + return + + explanation_text = "Free Objective." + + proc/format_explanation() + return "Steal [steal_target.name]." + + proc/select_target() + var/list/possible_items_all = potential_theft_objectives[target_category]+"custom" + var/new_target = input("Select target:", "Objective target", null) as null|anything in possible_items_all + if (!new_target) return + if (new_target == "custom") + var/datum/theft_objective/O=new + O.typepath = input("Select type:","Type") as null|anything in typesof(/obj/item) + if (!O.typepath) return + var/tmp_obj = new O.typepath + var/custom_name = tmp_obj:name + qdel(tmp_obj) + O.name = copytext(sanitize(input("Enter target name:", "Objective target", custom_name) as text|null),1,MAX_NAME_LEN) + if (!O.name) return + steal_target = O + explanation_text = format_explanation() + else + steal_target = new new_target + explanation_text = format_explanation() + return steal_target + + check_completion() + if(blocked) return 0 + if(!steal_target) return 1 // Free Objective + return steal_target.check_completion(owner) + +/datum/objective/capture + proc/gen_amount_goal() + target_amount = rand(5,10) + explanation_text = "Accumulate [target_amount] capture points." + return target_amount + + + check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. + if(blocked) return 0 + var/captured_amount = 0 + var/area/centcom/holding/A = locate() + for(var/mob/living/carbon/human/M in A)//Humans. + if(M.stat==2)//Dead folks are worth less. + captured_amount+=0.5 + continue + captured_amount+=1 + for(var/mob/living/carbon/monkey/M in A)//Monkeys are almost worthless, you failure. + captured_amount+=0.1 + for(var/mob/living/carbon/alien/larva/M in A)//Larva are important for research. + if(M.stat==2) + captured_amount+=0.5 + continue + captured_amount+=1 + for(var/mob/living/carbon/alien/humanoid/M in A)//Aliens are worth twice as much as humans. + if(istype(M, /mob/living/carbon/alien/humanoid/queen))//Queens are worth three times as much as humans. + if(M.stat==2) + captured_amount+=1.5 + else + captured_amount+=3 + continue + if(M.stat==2) + captured_amount+=1 + continue + captured_amount+=2 + if(captured_amount= target_amount) + return 1 + else + return 0 +/datum/objective/absorb + proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) + target_amount = rand (lowbound,highbound) + if (ticker) + var/n_p = 1 //autowin + if (ticker.current_state == GAME_STATE_SETTING_UP) + for(var/mob/new_player/P in player_list) + if(P.client && P.ready && P.mind!=owner) + n_p ++ + else if (ticker.current_state == GAME_STATE_PLAYING) + for(var/mob/living/carbon/human/P in player_list) + if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) + n_p ++ + target_amount = min(target_amount, n_p) + + explanation_text = "Absorb [target_amount] compatible genomes." + return target_amount + + check_completion() + if(blocked) return 0 + if(owner && owner.changeling && owner.changeling.absorbed_dna && (owner.changeling.absorbedcount >= target_amount)) + return 1 + else + return 0 + + + +/* Isn't suited for global objectives +/*---------CULTIST----------*/ + + eldergod + explanation_text = "Summon Nar-Sie via the use of an appropriate rune. It will only work if nine cultists stand on and around it." + + check_completion() + if(eldergod) //global var, defined in rune4.dm + return 1 + return 0 + + survivecult + var/num_cult + + explanation_text = "Our knowledge must live on. Make sure at least 5 acolytes escape on the shuttle to spread their work on an another station." + + check_completion() + if(emergency_shuttle.location<2) + return 0 + + var/cultists_escaped = 0 + + var/area/shuttle/escape/centcom/C = /area/shuttle/escape/centcom + for(var/turf/T in get_area_turfs(C.type)) + for(var/mob/living/carbon/H in T) + if(iscultist(H)) + cultists_escaped++ + + if(cultists_escaped>=5) + return 1 + + return 0 + + sacrifice //stolen from traitor target objective + + proc/find_target() //I don't know how to make it work with the rune otherwise, so I'll do it via a global var, sacrifice_target, defined in rune15.dm + var/list/possible_targets = call(/datum/game_mode/cult/proc/get_unconvertables)() + + + if(possible_targets.len > 0) + sacrifice_target = pick(possible_targets) + + if(sacrifice_target && sacrifice_target.current) + explanation_text = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell join blood) and three acolytes to do so." + else + explanation_text = "Free Objective" + + return sacrifice_target + + check_completion() //again, calling on a global list defined in rune15.dm + if(sacrifice_target.current in sacrificed) + return 1 + else + return 0 + +/*-------ENDOF CULTIST------*/ +*/ + +// /vg/; Vox Inviolate for humans :V +/datum/objective/minimize_casualties + explanation_text = "Minimise casualties." + check_completion() + if(blocked) return 0 + if(owner.kills.len>5) return 0 return 1 \ No newline at end of file diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 28b23f390dd..b4dc059f2eb 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -1,515 +1,515 @@ -// To add a rev to the list of revolutionaries, make sure it's rev (with if(ticker.mode.name == "revolution)), -// then call ticker.mode:add_revolutionary(_THE_PLAYERS_MIND_) -// nothing else needs to be done, as that proc will check if they are a valid target. -// Just make sure the converter is a head before you call it! -// To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_), -// this will also check they're not a head, so it can just be called freely -// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them. -// If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere. - -/datum/game_mode - var/list/datum/mind/head_revolutionaries = list() - var/list/datum/mind/revolutionaries = list() - -/datum/game_mode/revolution - name = "revolution" - config_tag = "revolution" - restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Mobile MMI","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Internal Affairs Agent") - required_players = 4 - required_players_secret = 25 - required_enemies = 3 - recommended_enemies = 3 - - - uplink_welcome = "Revolutionary Uplink Console:" - uplink_uses = 10 - - var/finished = 0 - var/checkwin_counter = 0 - var/max_headrevs = 3 - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/revolution/announce() +// To add a rev to the list of revolutionaries, make sure it's rev (with if(ticker.mode.name == "revolution)), +// then call ticker.mode:add_revolutionary(_THE_PLAYERS_MIND_) +// nothing else needs to be done, as that proc will check if they are a valid target. +// Just make sure the converter is a head before you call it! +// To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_), +// this will also check they're not a head, so it can just be called freely +// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them. +// If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere. + +/datum/game_mode + var/list/datum/mind/head_revolutionaries = list() + var/list/datum/mind/revolutionaries = list() + +/datum/game_mode/revolution + name = "revolution" + config_tag = "revolution" + restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Mobile MMI","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Internal Affairs Agent") + required_players = 4 + required_players_secret = 25 + required_enemies = 3 + recommended_enemies = 3 + + + uplink_welcome = "Revolutionary Uplink Console:" + uplink_uses = 10 + + var/finished = 0 + var/checkwin_counter = 0 + var/max_headrevs = 3 + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) +/////////////////////////// +//Announces the game type// +/////////////////////////// +/datum/game_mode/revolution/announce() to_chat(world, "The current game mode is - Revolution!") to_chat(world, "Some crewmembers are attempting to start a revolution!
      \nRevolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
      \nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head).
      ") - - -/////////////////////////////////////////////////////////////////////////////// -//Gets the round setup, cancelling if there's not enough players at the start// -/////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/datum/mind/possible_headrevs = get_players_for_role(ROLE_REV) - - var/head_check = 0 - for(var/mob/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check++ - - for(var/datum/mind/player in possible_headrevs) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - possible_headrevs -= player - - for (var/i=1 to max_headrevs) - if (possible_headrevs.len==0) - break - var/datum/mind/lenin = pick(possible_headrevs) - possible_headrevs -= lenin - head_revolutionaries += lenin - - if((head_revolutionaries.len==0)||(!head_check)) - log_admin("Failed to set-up a round of revolution. Couldn't find any heads of staffs or any volunteers to be head revolutionaries.") - message_admins("Failed to set-up a round of revolution. Couldn't find any heads of staffs or any volunteers to be head revolutionaries.") - return 0 - - log_admin("Starting a round of revolution with [head_revolutionaries.len] head revolutionaries and [head_check] heads of staff.") - message_admins("Starting a round of revolution with [head_revolutionaries.len] head revolutionaries and [head_check] heads of staff.") - return 1 - - -/datum/game_mode/revolution/post_setup() - var/list/heads = get_living_heads() - - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - - // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO - // Removing revolutionary uplinks. -Pete - equip_revolutionary(rev_mind.current) - update_rev_icons_added(rev_mind) - - for(var/datum/mind/rev_mind in head_revolutionaries) - greet_revolutionary(rev_mind) - modePlayer += head_revolutionaries - if(emergency_shuttle) - emergency_shuttle.always_fake_recall = 1 - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - ..() - - -/datum/game_mode/revolution/process() - checkwin_counter++ - if(checkwin_counter >= 5) - if(!finished) - ticker.mode.check_win() - checkwin_counter = 0 - return 0 - - -/datum/game_mode/proc/forge_revolutionary_objectives(var/datum/mind/rev_mind) - var/list/heads = get_living_heads() - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - -/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) - var/obj_count = 1 - if (you_are) + + +/////////////////////////////////////////////////////////////////////////////// +//Gets the round setup, cancelling if there's not enough players at the start// +/////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/revolution/pre_setup() + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + var/list/datum/mind/possible_headrevs = get_players_for_role(ROLE_REV) + + var/head_check = 0 + for(var/mob/new_player/player in player_list) + if(player.mind.assigned_role in command_positions) + head_check++ + + for(var/datum/mind/player in possible_headrevs) + for(var/job in restricted_jobs)//Removing heads and such from the list + if(player.assigned_role == job) + possible_headrevs -= player + + for (var/i=1 to max_headrevs) + if (possible_headrevs.len==0) + break + var/datum/mind/lenin = pick(possible_headrevs) + possible_headrevs -= lenin + head_revolutionaries += lenin + + if((head_revolutionaries.len==0)||(!head_check)) + log_admin("Failed to set-up a round of revolution. Couldn't find any heads of staffs or any volunteers to be head revolutionaries.") + message_admins("Failed to set-up a round of revolution. Couldn't find any heads of staffs or any volunteers to be head revolutionaries.") + return 0 + + log_admin("Starting a round of revolution with [head_revolutionaries.len] head revolutionaries and [head_check] heads of staff.") + message_admins("Starting a round of revolution with [head_revolutionaries.len] head revolutionaries and [head_check] heads of staff.") + return 1 + + +/datum/game_mode/revolution/post_setup() + var/list/heads = get_living_heads() + + for(var/datum/mind/rev_mind in head_revolutionaries) + for(var/datum/mind/head_mind in heads) + var/datum/objective/mutiny/rev_obj = new + rev_obj.owner = rev_mind + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." + rev_mind.objectives += rev_obj + + // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO + // Removing revolutionary uplinks. -Pete + equip_revolutionary(rev_mind.current) + update_rev_icons_added(rev_mind) + + for(var/datum/mind/rev_mind in head_revolutionaries) + greet_revolutionary(rev_mind) + modePlayer += head_revolutionaries + if(emergency_shuttle) + emergency_shuttle.always_fake_recall = 1 + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + ..() + + +/datum/game_mode/revolution/process() + checkwin_counter++ + if(checkwin_counter >= 5) + if(!finished) + ticker.mode.check_win() + checkwin_counter = 0 + return 0 + + +/datum/game_mode/proc/forge_revolutionary_objectives(var/datum/mind/rev_mind) + var/list/heads = get_living_heads() + for(var/datum/mind/head_mind in heads) + var/datum/objective/mutiny/rev_obj = new + rev_obj.owner = rev_mind + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." + rev_mind.objectives += rev_obj + +/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) + var/obj_count = 1 + if (you_are) to_chat(rev_mind.current, "You are a member of the revolutionaries' leadership!") - for(var/datum/objective/objective in rev_mind.objectives) + for(var/datum/objective/objective in rev_mind.objectives) to_chat(rev_mind.current, "Objective #[obj_count]: [objective.explanation_text]") - rev_mind.special_role = "Head Revolutionary" - obj_count++ - -///////////////////////////////////////////////////////////////////////////////// -//This are equips the rev heads with their gear, and makes the clown not clumsy// -///////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/equip_revolutionary(mob/living/carbon/human/mob) - if(!istype(mob)) - return - - if (mob.mind) - if (mob.mind.assigned_role == "Clown") + rev_mind.special_role = "Head Revolutionary" + obj_count++ + +///////////////////////////////////////////////////////////////////////////////// +//This are equips the rev heads with their gear, and makes the clown not clumsy// +///////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/equip_revolutionary(mob/living/carbon/human/mob) + if(!istype(mob)) + return + + if (mob.mind) + if (mob.mind.assigned_role == "Clown") to_chat(mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - mob.mutations.Remove(M_CLUMSY) - - - var/obj/item/device/flash/T = new(mob) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = mob.equip_in_one_of_slots(T, slots) - if (!where) + mob.mutations.Remove(M_CLUMSY) + + + var/obj/item/device/flash/T = new(mob) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + var/where = mob.equip_in_one_of_slots(T, slots) + if (!where) to_chat(mob, "The Syndicate were unfortunately unable to get you a flash.") - else + else to_chat(mob, "The flash in your [where] will help you to persuade the crew to join your cause.") - mob.update_icons() - return 1 - -////////////////////////////////////// -//Checks if the revs have won or not// -////////////////////////////////////// -/datum/game_mode/revolution/check_win() - if(check_rev_victory()) - finished = 1 - else if(check_heads_victory()) - finished = 2 - return - -/////////////////////////////// -//Checks if the round is over// -/////////////////////////////// -/datum/game_mode/revolution/check_finished() - if(config.continous_rounds) - if(finished != 0) - if(emergency_shuttle) - emergency_shuttle.always_fake_recall = 0 - return ..() - if(finished != 0) - return 1 - else - return 0 - -/////////////////////////////////////////////////// -//Deals with converting players to the revolution// -/////////////////////////////////////////////////// -/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind) - if(rev_mind.assigned_role in command_positions) - return -1 - - var/mob/living/carbon/human/H = rev_mind.current - - if(jobban_isbanned(H, "revolutionary")) - return -2 - - for(var/obj/item/weapon/implant/loyalty/L in H) // check loyalty implant in the contents - if(L.imp_in == H) // a check if it's actually implanted - return -3 - - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return -4 - - revolutionaries += rev_mind + mob.update_icons() + return 1 + +////////////////////////////////////// +//Checks if the revs have won or not// +////////////////////////////////////// +/datum/game_mode/revolution/check_win() + if(check_rev_victory()) + finished = 1 + else if(check_heads_victory()) + finished = 2 + return + +/////////////////////////////// +//Checks if the round is over// +/////////////////////////////// +/datum/game_mode/revolution/check_finished() + if(config.continous_rounds) + if(finished != 0) + if(emergency_shuttle) + emergency_shuttle.always_fake_recall = 0 + return ..() + if(finished != 0) + return 1 + else + return 0 + +/////////////////////////////////////////////////// +//Deals with converting players to the revolution// +/////////////////////////////////////////////////// +/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind) + if(rev_mind.assigned_role in command_positions) + return -1 + + var/mob/living/carbon/human/H = rev_mind.current + + if(jobban_isbanned(H, "revolutionary")) + return -2 + + for(var/obj/item/weapon/implant/loyalty/L in H) // check loyalty implant in the contents + if(L.imp_in == H) // a check if it's actually implanted + return -3 + + if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) + return -4 + + revolutionaries += rev_mind to_chat(rev_mind.current, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") - rev_mind.special_role = "Revolutionary" - update_rev_icons_added(rev_mind) - - return 1 -////////////////////////////////////////////////////////////////////////////// -//Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph. -////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/remove_revolutionary(datum/mind/rev_mind , beingborged) - if(rev_mind in revolutionaries) - revolutionaries -= rev_mind - rev_mind.special_role = null - - if(beingborged) + rev_mind.special_role = "Revolutionary" + update_rev_icons_added(rev_mind) + + return 1 +////////////////////////////////////////////////////////////////////////////// +//Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph. +////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/remove_revolutionary(datum/mind/rev_mind , beingborged) + if(rev_mind in revolutionaries) + revolutionaries -= rev_mind + rev_mind.special_role = null + + if(beingborged) to_chat(rev_mind.current, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now.") - - else + + else to_chat(rev_mind.current, "You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...") - - update_rev_icons_removed(rev_mind) - for(var/mob/living/M in view(rev_mind.current)) - if(beingborged) + + update_rev_icons_removed(rev_mind) + for(var/mob/living/M in view(rev_mind.current)) + if(beingborged) to_chat(M, "The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.") - - else + + else to_chat(M, "[rev_mind.current] looks like they just remembered their real allegiance!") - log_admin("[rev_mind.current] ([ckey(rev_mind.current.key)] has been deconverted from the revolution") - - -///////////////////////////////////////////////////////////////////////////////////////////////// -//Keeps track of players having the correct icons//////////////////////////////////////////////// -//CURRENTLY CONTAINS BUGS://///////////////////////////////////////////////////////////////////// -//-PLAYERS THAT HAVE BEEN REVS FOR AWHILE OBTAIN THE BLUE ICON WHILE STILL NOT BEING A REV HEAD// -// -Possibly caused by cloning of a standard rev///////////////////////////////////////////////// -//-UNCONFIRMED: DECONVERTED REVS NOT LOSING THEIR ICON properLY////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/update_all_rev_icons() - spawn(0) - for(var/datum/mind/head_rev_mind in head_revolutionaries) - if(head_rev_mind.current) - if(head_rev_mind.current.client) - for(var/image/I in head_rev_mind.current.client.images) - if(I.icon_state == "rev" || I.icon_state == "rev_head") - //del(I) - head_rev_mind.current.client.images -= I - - for(var/datum/mind/rev_mind in revolutionaries) - if(rev_mind.current) - if(rev_mind.current.client) - for(var/image/I in rev_mind.current.client.images) - if(I.icon_state == "rev" || I.icon_state == "rev_head") - //del(I) - rev_mind.current.client.images -= I - - for(var/datum/mind/head_rev in head_revolutionaries) - if(head_rev.current) - if(head_rev.current.client) - for(var/datum/mind/rev in revolutionaries) - if(rev.current) - var/imageloc = rev.current - if(istype(rev.current.loc,/obj/mecha)) - imageloc = rev.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) - head_rev.current.client.images += I - for(var/datum/mind/head_rev_1 in head_revolutionaries) - if(head_rev_1.current) - var/imageloc = head_rev_1.current - if(istype(head_rev_1.current.loc,/obj/mecha)) - imageloc = head_rev_1.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev_head", layer = 13) - head_rev.current.client.images += I - - for(var/datum/mind/rev in revolutionaries) - if(rev.current) - if(rev.current.client) - for(var/datum/mind/head_rev in head_revolutionaries) - if(head_rev.current) - var/imageloc = head_rev.current - if(istype(head_rev.current.loc,/obj/mecha)) - imageloc = head_rev.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev_head", layer = 13) - rev.current.client.images += I - for(var/datum/mind/rev_1 in revolutionaries) - if(rev_1.current) - var/imageloc = rev_1.current - if(istype(rev_1.current.loc,/obj/mecha)) - imageloc = rev_1.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) - rev.current.client.images += I - -//////////////////////////////////////////////////// -//Keeps track of converted revs icons/////////////// -//Refer to above bugs. They may apply here as well// -//////////////////////////////////////////////////// -/datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind) - spawn(0) - for(var/datum/mind/head_rev_mind in head_revolutionaries) - if(head_rev_mind.current) - if(head_rev_mind.current.client) - var/imageloc = rev_mind.current - if(istype(rev_mind.current.loc,/obj/mecha)) - imageloc = rev_mind.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) - head_rev_mind.current.client.images += I - if(rev_mind.current) - if(rev_mind.current.client) - var/imageloc = head_rev_mind.current - if(istype(head_rev_mind.current.loc,/obj/mecha)) - imageloc = head_rev_mind.current.loc - var/image/J = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev_head", layer = 13) - rev_mind.current.client.images += J - - for(var/datum/mind/rev_mind_1 in revolutionaries) - if(rev_mind_1.current) - if(rev_mind_1.current.client) - var/imageloc = rev_mind.current - if(istype(rev_mind.current.loc,/obj/mecha)) - imageloc = rev_mind.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) - rev_mind_1.current.client.images += I - if(rev_mind.current) - if(rev_mind.current.client) - var/imageloc = rev_mind_1.current - if(istype(rev_mind_1.current.loc,/obj/mecha)) - imageloc = rev_mind_1.current.loc - var/image/J = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) - rev_mind.current.client.images += J - -/////////////////////////////////// -//Keeps track of deconverted revs// -/////////////////////////////////// -/datum/game_mode/proc/update_rev_icons_removed(datum/mind/rev_mind) - spawn(0) - for(var/datum/mind/head_rev_mind in head_revolutionaries) - if(head_rev_mind.current) - if(head_rev_mind.current.client) - for(var/image/I in head_rev_mind.current.client.images) - if((I.icon_state == "rev" || I.icon_state == "rev_head") && ((I.loc == rev_mind.current) || (I.loc == rev_mind.current.loc))) - //del(I) - head_rev_mind.current.client.images -= I - - for(var/datum/mind/rev_mind_1 in revolutionaries) - if(rev_mind_1.current) - if(rev_mind_1.current.client) - for(var/image/I in rev_mind_1.current.client.images) - if((I.icon_state == "rev" || I.icon_state == "rev_head") && ((I.loc == rev_mind.current) || (I.loc == rev_mind.current.loc))) - //del(I) - rev_mind_1.current.client.images -= I - - if(rev_mind.current) - if(rev_mind.current.client) - for(var/image/I in rev_mind.current.client.images) - if(I.icon_state == "rev" || I.icon_state == "rev_head") - //del(I) - rev_mind.current.client.images -= I - -////////////////////////// -//Checks for rev victory// -////////////////////////// -/datum/game_mode/revolution/proc/check_rev_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/objective/objective in rev_mind.objectives) - if(!(objective.check_completion())) - return 0 - - return 1 - -///////////////////////////// -//Checks for a head victory// -///////////////////////////// -/datum/game_mode/revolution/proc/check_heads_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - var/turf/T = get_turf(rev_mind.current) - if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && T && (T.z == 1)) - if(ishuman(rev_mind.current)) - return 0 - return 1 - -////////////////////////////////////////////////////////////////////// -//Announces the end of the game with all relavent information stated// -////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/declare_completion() - if(finished == 1) - feedback_set_details("round_end_result","win - heads killed") - completion_text = "
      The heads of staff were killed or abandoned the station! The revolutionaries win!" - else if(finished == 2) - feedback_set_details("round_end_result","loss - rev heads killed") - completion_text = "
      The heads of staff managed to stop the revolution!" - ..() - return 1 - -/datum/game_mode/proc/auto_declare_completion_revolution() - var/list/targets = list() - var/text = "" - if(head_revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) - var/icon/logo1 = icon('icons/mob/mob.dmi', "rev_head-logo") - end_icons += logo1 - var/tempstate = end_icons.len - text += {" The head revolutionaries were: "} - - for(var/datum/mind/headrev in head_revolutionaries) - if(headrev.current) - var/icon/flat = getFlatIcon(headrev.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [headrev.key] was [headrev.name] ("} - if(headrev.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else if(headrev.current.z != 1) - text += "fled the station" - else - text += "survived the revolution" - if(headrev.current.real_name != headrev.name) - text += " as [headrev.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [headrev.key] was [headrev.name] ("} - text += "body destroyed" - text += ")" - if(headrev.total_TC) - if(headrev.spent_TC) - text += "
      TC Remaining: [headrev.total_TC - headrev.spent_TC]/[headrev.total_TC] - The tools used by the Head Revolutionary were:" - for(var/entry in headrev.uplink_items_bought) - text += "
      [entry]" - text += "
      " - else - text += "
      The Head Revolutionary was a smooth operator this round (did not purchase any uplink items)" - - for(var/datum/objective/mutiny/objective in headrev.objectives) - targets |= objective.target - - - if(revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) - var/icon/logo2 = icon('icons/mob/mob.dmi', "rev-logo") - end_icons += logo2 - var/tempstate = end_icons.len - text += {"
      The revolutionaries were: "} - - for(var/datum/mind/rev in revolutionaries) - if(rev.current) - var/icon/flat = getFlatIcon(rev.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [rev.key] was [rev.name] ("} - if(rev.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else if(rev.current.z != 1) - text += "fled the station" - else - text += "survived the revolution" - if(rev.current.real_name != rev.name) - text += " as [rev.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [rev.key] was [rev.name] ("} - text += "body destroyed" - text += ")" - - - - if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) ) - var/icon/logo3 = icon('icons/mob/mob.dmi', "nano-logo") - end_icons += logo3 - var/tempstate = end_icons.len - text += {"
      The heads of staff were: "} - - var/list/heads = get_all_heads() - for(var/datum/mind/head in heads) - var/target = (head in targets) - if(target) - text += "" - if(head.current) - var/icon/flat = getFlatIcon(head.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [head.key] was [head.name] ("} - if(head.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else if(head.current.z != 1) - text += "fled the station" - else - text += "survived the revolution" - if(head.current.real_name != head.name) - text += " as [head.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [head.key] was [head.name] ("} - text += "body destroyed" - text += ")" - if(target) - text += "
      " - - text += "

      " - return text - -/proc/is_convertable_to_rev(datum/mind/mind) - return istype(mind) && \ - istype(mind.current, /mob/living/carbon/human) && \ - !(mind.assigned_role in command_positions) && \ - !(mind.assigned_role in list("Security Officer", "Detective", "Warden")) + log_admin("[rev_mind.current] ([ckey(rev_mind.current.key)] has been deconverted from the revolution") + + +///////////////////////////////////////////////////////////////////////////////////////////////// +//Keeps track of players having the correct icons//////////////////////////////////////////////// +//CURRENTLY CONTAINS BUGS://///////////////////////////////////////////////////////////////////// +//-PLAYERS THAT HAVE BEEN REVS FOR AWHILE OBTAIN THE BLUE ICON WHILE STILL NOT BEING A REV HEAD// +// -Possibly caused by cloning of a standard rev///////////////////////////////////////////////// +//-UNCONFIRMED: DECONVERTED REVS NOT LOSING THEIR ICON properLY////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/update_all_rev_icons() + spawn(0) + for(var/datum/mind/head_rev_mind in head_revolutionaries) + if(head_rev_mind.current) + if(head_rev_mind.current.client) + for(var/image/I in head_rev_mind.current.client.images) + if(I.icon_state == "rev" || I.icon_state == "rev_head") + //del(I) + head_rev_mind.current.client.images -= I + + for(var/datum/mind/rev_mind in revolutionaries) + if(rev_mind.current) + if(rev_mind.current.client) + for(var/image/I in rev_mind.current.client.images) + if(I.icon_state == "rev" || I.icon_state == "rev_head") + //del(I) + rev_mind.current.client.images -= I + + for(var/datum/mind/head_rev in head_revolutionaries) + if(head_rev.current) + if(head_rev.current.client) + for(var/datum/mind/rev in revolutionaries) + if(rev.current) + var/imageloc = rev.current + if(istype(rev.current.loc,/obj/mecha)) + imageloc = rev.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) + head_rev.current.client.images += I + for(var/datum/mind/head_rev_1 in head_revolutionaries) + if(head_rev_1.current) + var/imageloc = head_rev_1.current + if(istype(head_rev_1.current.loc,/obj/mecha)) + imageloc = head_rev_1.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev_head", layer = 13) + head_rev.current.client.images += I + + for(var/datum/mind/rev in revolutionaries) + if(rev.current) + if(rev.current.client) + for(var/datum/mind/head_rev in head_revolutionaries) + if(head_rev.current) + var/imageloc = head_rev.current + if(istype(head_rev.current.loc,/obj/mecha)) + imageloc = head_rev.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev_head", layer = 13) + rev.current.client.images += I + for(var/datum/mind/rev_1 in revolutionaries) + if(rev_1.current) + var/imageloc = rev_1.current + if(istype(rev_1.current.loc,/obj/mecha)) + imageloc = rev_1.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) + rev.current.client.images += I + +//////////////////////////////////////////////////// +//Keeps track of converted revs icons/////////////// +//Refer to above bugs. They may apply here as well// +//////////////////////////////////////////////////// +/datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind) + spawn(0) + for(var/datum/mind/head_rev_mind in head_revolutionaries) + if(head_rev_mind.current) + if(head_rev_mind.current.client) + var/imageloc = rev_mind.current + if(istype(rev_mind.current.loc,/obj/mecha)) + imageloc = rev_mind.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) + head_rev_mind.current.client.images += I + if(rev_mind.current) + if(rev_mind.current.client) + var/imageloc = head_rev_mind.current + if(istype(head_rev_mind.current.loc,/obj/mecha)) + imageloc = head_rev_mind.current.loc + var/image/J = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev_head", layer = 13) + rev_mind.current.client.images += J + + for(var/datum/mind/rev_mind_1 in revolutionaries) + if(rev_mind_1.current) + if(rev_mind_1.current.client) + var/imageloc = rev_mind.current + if(istype(rev_mind.current.loc,/obj/mecha)) + imageloc = rev_mind.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) + rev_mind_1.current.client.images += I + if(rev_mind.current) + if(rev_mind.current.client) + var/imageloc = rev_mind_1.current + if(istype(rev_mind_1.current.loc,/obj/mecha)) + imageloc = rev_mind_1.current.loc + var/image/J = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "rev", layer = 13) + rev_mind.current.client.images += J + +/////////////////////////////////// +//Keeps track of deconverted revs// +/////////////////////////////////// +/datum/game_mode/proc/update_rev_icons_removed(datum/mind/rev_mind) + spawn(0) + for(var/datum/mind/head_rev_mind in head_revolutionaries) + if(head_rev_mind.current) + if(head_rev_mind.current.client) + for(var/image/I in head_rev_mind.current.client.images) + if((I.icon_state == "rev" || I.icon_state == "rev_head") && ((I.loc == rev_mind.current) || (I.loc == rev_mind.current.loc))) + //del(I) + head_rev_mind.current.client.images -= I + + for(var/datum/mind/rev_mind_1 in revolutionaries) + if(rev_mind_1.current) + if(rev_mind_1.current.client) + for(var/image/I in rev_mind_1.current.client.images) + if((I.icon_state == "rev" || I.icon_state == "rev_head") && ((I.loc == rev_mind.current) || (I.loc == rev_mind.current.loc))) + //del(I) + rev_mind_1.current.client.images -= I + + if(rev_mind.current) + if(rev_mind.current.client) + for(var/image/I in rev_mind.current.client.images) + if(I.icon_state == "rev" || I.icon_state == "rev_head") + //del(I) + rev_mind.current.client.images -= I + +////////////////////////// +//Checks for rev victory// +////////////////////////// +/datum/game_mode/revolution/proc/check_rev_victory() + for(var/datum/mind/rev_mind in head_revolutionaries) + for(var/datum/objective/objective in rev_mind.objectives) + if(!(objective.check_completion())) + return 0 + + return 1 + +///////////////////////////// +//Checks for a head victory// +///////////////////////////// +/datum/game_mode/revolution/proc/check_heads_victory() + for(var/datum/mind/rev_mind in head_revolutionaries) + var/turf/T = get_turf(rev_mind.current) + if((rev_mind) && (rev_mind.current) && (rev_mind.current.stat != 2) && T && (T.z == 1)) + if(ishuman(rev_mind.current)) + return 0 + return 1 + +////////////////////////////////////////////////////////////////////// +//Announces the end of the game with all relavent information stated// +////////////////////////////////////////////////////////////////////// +/datum/game_mode/revolution/declare_completion() + if(finished == 1) + feedback_set_details("round_end_result","win - heads killed") + completion_text = "
      The heads of staff were killed or abandoned the station! The revolutionaries win!" + else if(finished == 2) + feedback_set_details("round_end_result","loss - rev heads killed") + completion_text = "
      The heads of staff managed to stop the revolution!" + ..() + return 1 + +/datum/game_mode/proc/auto_declare_completion_revolution() + var/list/targets = list() + var/text = "" + if(head_revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) + var/icon/logo1 = icon('icons/mob/mob.dmi', "rev_head-logo") + end_icons += logo1 + var/tempstate = end_icons.len + text += {" The head revolutionaries were: "} + + for(var/datum/mind/headrev in head_revolutionaries) + if(headrev.current) + var/icon/flat = getFlatIcon(headrev.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [headrev.key] was [headrev.name] ("} + if(headrev.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else if(headrev.current.z != 1) + text += "fled the station" + else + text += "survived the revolution" + if(headrev.current.real_name != headrev.name) + text += " as [headrev.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [headrev.key] was [headrev.name] ("} + text += "body destroyed" + text += ")" + if(headrev.total_TC) + if(headrev.spent_TC) + text += "
      TC Remaining: [headrev.total_TC - headrev.spent_TC]/[headrev.total_TC] - The tools used by the Head Revolutionary were:" + for(var/entry in headrev.uplink_items_bought) + text += "
      [entry]" + text += "
      " + else + text += "
      The Head Revolutionary was a smooth operator this round (did not purchase any uplink items)" + + for(var/datum/objective/mutiny/objective in headrev.objectives) + targets |= objective.target + + + if(revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution)) + var/icon/logo2 = icon('icons/mob/mob.dmi', "rev-logo") + end_icons += logo2 + var/tempstate = end_icons.len + text += {"
      The revolutionaries were: "} + + for(var/datum/mind/rev in revolutionaries) + if(rev.current) + var/icon/flat = getFlatIcon(rev.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [rev.key] was [rev.name] ("} + if(rev.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else if(rev.current.z != 1) + text += "fled the station" + else + text += "survived the revolution" + if(rev.current.real_name != rev.name) + text += " as [rev.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [rev.key] was [rev.name] ("} + text += "body destroyed" + text += ")" + + + + if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) ) + var/icon/logo3 = icon('icons/mob/mob.dmi', "nano-logo") + end_icons += logo3 + var/tempstate = end_icons.len + text += {"
      The heads of staff were: "} + + var/list/heads = get_all_heads() + for(var/datum/mind/head in heads) + var/target = (head in targets) + if(target) + text += "" + if(head.current) + var/icon/flat = getFlatIcon(head.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [head.key] was [head.name] ("} + if(head.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else if(head.current.z != 1) + text += "fled the station" + else + text += "survived the revolution" + if(head.current.real_name != head.name) + text += " as [head.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [head.key] was [head.name] ("} + text += "body destroyed" + text += ")" + if(target) + text += "
      " + + text += "

      " + return text + +/proc/is_convertable_to_rev(datum/mind/mind) + return istype(mind) && \ + istype(mind.current, /mob/living/carbon/human) && \ + !(mind.assigned_role in command_positions) && \ + !(mind.assigned_role in list("Security Officer", "Detective", "Warden")) diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm index 3880950f583..07c7cc3eefa 100644 --- a/code/game/gamemodes/revolution/rp_revolution.dm +++ b/code/game/gamemodes/revolution/rp_revolution.dm @@ -1,254 +1,254 @@ -// BS12's less violent revolution mode - -/datum/game_mode/revolution/rp_revolution - name = "rp-revolution" - config_tag = "rp-revolution" - required_players = 4 - required_players_secret = 12 - required_enemies = 3 - recommended_enemies = 3 - - uplink_welcome = "Revolutionary Uplink Console:" - uplink_uses = 5 - - newscaster_announcements = /datum/news_announcement/revolution_inciting_event - - var/last_command_report = 0 - var/list/heads = list() - var/tried_to_add_revheads = 0 - -/////////////////////////////////////////////////////////////////////////////// -//Gets the round setup, cancelling if there's not enough players at the start// -/////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/num_players = num_players() - max_headrevs = max(num_players / 4, 3) - recommended_enemies = max_headrevs - - var/list/datum/mind/possible_headrevs = get_players_for_role(BE_REV) - - var/head_check = 0 - for(var/mob/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check = 1 - break - - for(var/datum/mind/player in possible_headrevs) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - possible_headrevs -= player - - for (var/i=1 to max_headrevs) - if (possible_headrevs.len==0) - break - var/datum/mind/lenin = pick(possible_headrevs) - possible_headrevs -= lenin - head_revolutionaries += lenin - - if((head_revolutionaries.len==0)||(!head_check)) - return 0 - - return 1 - - -/datum/game_mode/revolution/rp_revolution/post_setup() - heads = get_living_heads() - - for(var/datum/mind/rev_mind in head_revolutionaries) - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate, convert or capture [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - - update_rev_icons_added(rev_mind) - - for(var/datum/mind/rev_mind in head_revolutionaries) - greet_revolutionary(rev_mind) - rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert - equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO - - modePlayer += head_revolutionaries - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - -/datum/game_mode/revolution/rp_revolution/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) - var/obj_count = 1 - if (you_are) +// BS12's less violent revolution mode + +/datum/game_mode/revolution/rp_revolution + name = "rp-revolution" + config_tag = "rp-revolution" + required_players = 4 + required_players_secret = 12 + required_enemies = 3 + recommended_enemies = 3 + + uplink_welcome = "Revolutionary Uplink Console:" + uplink_uses = 5 + + newscaster_announcements = /datum/news_announcement/revolution_inciting_event + + var/last_command_report = 0 + var/list/heads = list() + var/tried_to_add_revheads = 0 + +/////////////////////////////////////////////////////////////////////////////// +//Gets the round setup, cancelling if there's not enough players at the start// +/////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/revolution/rp_revolution/pre_setup() + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + var/num_players = num_players() + max_headrevs = max(num_players / 4, 3) + recommended_enemies = max_headrevs + + var/list/datum/mind/possible_headrevs = get_players_for_role(BE_REV) + + var/head_check = 0 + for(var/mob/new_player/player in player_list) + if(player.mind.assigned_role in command_positions) + head_check = 1 + break + + for(var/datum/mind/player in possible_headrevs) + for(var/job in restricted_jobs)//Removing heads and such from the list + if(player.assigned_role == job) + possible_headrevs -= player + + for (var/i=1 to max_headrevs) + if (possible_headrevs.len==0) + break + var/datum/mind/lenin = pick(possible_headrevs) + possible_headrevs -= lenin + head_revolutionaries += lenin + + if((head_revolutionaries.len==0)||(!head_check)) + return 0 + + return 1 + + +/datum/game_mode/revolution/rp_revolution/post_setup() + heads = get_living_heads() + + for(var/datum/mind/rev_mind in head_revolutionaries) + for(var/datum/mind/head_mind in heads) + var/datum/objective/mutiny/rp/rev_obj = new + rev_obj.owner = rev_mind + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate, convert or capture [head_mind.name], the [head_mind.assigned_role]." + rev_mind.objectives += rev_obj + + update_rev_icons_added(rev_mind) + + for(var/datum/mind/rev_mind in head_revolutionaries) + greet_revolutionary(rev_mind) + rev_mind.current.verbs += /mob/living/carbon/human/proc/RevConvert + equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO + + modePlayer += head_revolutionaries + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + +/datum/game_mode/revolution/rp_revolution/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) + var/obj_count = 1 + if (you_are) to_chat(rev_mind.current, "You are a member of the revolutionaries' leadership!") - for(var/datum/objective/objective in rev_mind.objectives) + for(var/datum/objective/objective in rev_mind.objectives) to_chat(rev_mind.current, "Objective #[obj_count]: [objective.explanation_text]") - rev_mind.special_role = "Head Revolutionary" - obj_count++ - - // Show each head revolutionary up to 3 candidates - var/list/already_considered = list() - for(var/i = 0, i < 2, i++) - var/mob/rev_mob = rev_mind.current - already_considered += rev_mob - // Tell them about people they might want to contact. - var/mob/living/carbon/human/M = get_nt_opposed() - if(M && !(M.mind in head_revolutionaries) && !(M in already_considered)) + rev_mind.special_role = "Head Revolutionary" + obj_count++ + + // Show each head revolutionary up to 3 candidates + var/list/already_considered = list() + for(var/i = 0, i < 2, i++) + var/mob/rev_mob = rev_mind.current + already_considered += rev_mob + // Tell them about people they might want to contact. + var/mob/living/carbon/human/M = get_nt_opposed() + if(M && !(M.mind in head_revolutionaries) && !(M in already_considered)) to_chat(rev_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") - rev_mob.mind.store_memory("Potential Collaborator: [M.real_name]") - -/////////////////////////////////////////////////// -//Deals with converting players to the revolution// -/////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/add_revolutionary(datum/mind/rev_mind) - // overwrite this func to make it so even heads can be converted - var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted - if(!is_convertible(H)) - return 0 - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return 0 - revolutionaries += rev_mind + rev_mob.mind.store_memory("Potential Collaborator: [M.real_name]") + +/////////////////////////////////////////////////// +//Deals with converting players to the revolution// +/////////////////////////////////////////////////// +/datum/game_mode/revolution/rp_revolution/add_revolutionary(datum/mind/rev_mind) + // overwrite this func to make it so even heads can be converted + var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted + if(!is_convertible(H)) + return 0 + if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) + return 0 + revolutionaries += rev_mind to_chat(rev_mind.current, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill, capture or convert the heads to win the revolution!") - rev_mind.special_role = "Revolutionary" - update_rev_icons_added(rev_mind) - return 1 - -///////////////////////////// -//Checks for a head victory// -///////////////////////////// -/datum/game_mode/revolution/rp_revolution/check_heads_victory() - for(var/datum/mind/rev_mind in head_revolutionaries) - var/turf/T = get_turf(rev_mind.current) - if(rev_mind.current.stat != 2) - // TODO: add a similar check that also checks whether they're without ID in the brig.. - // probably wanna export this stuff into a separate function for use by both - // revs and heads - //assume that only carbon mobs can become rev heads for now - if(!rev_mind.current:handcuffed && T && T.z == 1) - return 0 - return 1 - -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/revolution/rp_revolution/announce() + rev_mind.special_role = "Revolutionary" + update_rev_icons_added(rev_mind) + return 1 + +///////////////////////////// +//Checks for a head victory// +///////////////////////////// +/datum/game_mode/revolution/rp_revolution/check_heads_victory() + for(var/datum/mind/rev_mind in head_revolutionaries) + var/turf/T = get_turf(rev_mind.current) + if(rev_mind.current.stat != 2) + // TODO: add a similar check that also checks whether they're without ID in the brig.. + // probably wanna export this stuff into a separate function for use by both + // revs and heads + //assume that only carbon mobs can become rev heads for now + if(!rev_mind.current:handcuffed && T && T.z == 1) + return 0 + return 1 + +/////////////////////////// +//Announces the game type// +/////////////////////////// +/datum/game_mode/revolution/rp_revolution/announce() to_chat(world, "The current game mode is - Revolution!") to_chat(world, "Some crewmembers are attempting to start a revolution!") - - -////////////////////////////////////////////////////////////////////// -//Announces the end of the game with all relavent information stated// -////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/rp_revolution/declare_completion() - if(finished == 1) - feedback_set_details("round_end_result","win - heads overthrown") + + +////////////////////////////////////////////////////////////////////// +//Announces the end of the game with all relavent information stated// +////////////////////////////////////////////////////////////////////// +/datum/game_mode/revolution/rp_revolution/declare_completion() + if(finished == 1) + feedback_set_details("round_end_result","win - heads overthrown") to_chat(world, " The heads of staff were overthrown! The revolutionaries win!") - else if(finished == 2) - feedback_set_details("round_end_result","loss - revolution stopped") + else if(finished == 2) + feedback_set_details("round_end_result","loss - revolution stopped") to_chat(world, " The heads of staff managed to stop the revolution!") - ..() - return 1 - -/datum/game_mode/revolution/proc/is_convertible(mob/M) - for(var/obj/item/weapon/implant/loyalty/L in M)//Checking that there is a loyalty implant in the contents - if(L.imp_in == M)//Checking that it's actually implanted - return 0 - - return 1 - -/mob/living/carbon/human/proc/RevConvert(mob/M as mob in oview(src)) - set name = "Rev-Convert" - set category = "IC" - if(((src.mind in ticker.mode:head_revolutionaries) || (src.mind in ticker.mode:revolutionaries))) - if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries)) + ..() + return 1 + +/datum/game_mode/revolution/proc/is_convertible(mob/M) + for(var/obj/item/weapon/implant/loyalty/L in M)//Checking that there is a loyalty implant in the contents + if(L.imp_in == M)//Checking that it's actually implanted + return 0 + + return 1 + +/mob/living/carbon/human/proc/RevConvert(mob/M as mob in oview(src)) + set name = "Rev-Convert" + set category = "IC" + if(((src.mind in ticker.mode:head_revolutionaries) || (src.mind in ticker.mode:revolutionaries))) + if((M.mind in ticker.mode:head_revolutionaries) || (M.mind in ticker.mode:revolutionaries)) to_chat(src, "[M] is already be a revolutionary!") - else if(!ticker.mode:is_convertible(M)) + else if(!ticker.mode:is_convertible(M)) to_chat(src, "[M] is implanted with a loyalty implant - Remove it first!") - else - if(world.time < M.mind.rev_cooldown) + else + if(world.time < M.mind.rev_cooldown) to_chat(src, "Wait five seconds before reconversion attempt.") - return + return to_chat(src, "Attempting to convert [M]...") - log_admin("[src]([src.ckey]) attempted to convert [M].") - message_admins("[src]([src.ckey]) attempted to convert [M].") - var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!") - if(choice == "Yes!") - ticker.mode:add_revolutionary(M.mind) + log_admin("[src]([src.ckey]) attempted to convert [M].") + message_admins("[src]([src.ckey]) attempted to convert [M].") + var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!") + if(choice == "Yes!") + ticker.mode:add_revolutionary(M.mind) to_chat(M, "You join the revolution!") to_chat(src, "[M] joins the revolution!") - else if(choice == "No!") + else if(choice == "No!") to_chat(M, "You reject this traitorous cause!") to_chat(src, "[M] does not support the revolution!") - M.mind.rev_cooldown = world.time+50 - -/datum/game_mode/revolution/rp_revolution/process() - // only perform rev checks once in a while - if(tried_to_add_revheads < world.time) - tried_to_add_revheads = world.time+50 - var/active_revs = 0 - for(var/datum/mind/rev_mind in head_revolutionaries) - if(rev_mind.current.client && rev_mind.current.client.inactivity <= 10*60*20) // 20 minutes inactivity are OK - active_revs++ - - if(active_revs == 0) - log_debug("There are zero active heads of revolution, trying to add some..") - var/added_heads = 0 - for(var/mob/living/carbon/human/H in mob_list) if(H.client && H.mind && H.client.inactivity <= 10*60*20 && H.mind in revolutionaries) - head_revolutionaries += H.mind - for(var/datum/mind/head_mind in heads) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = H.mind - rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate or capture [head_mind.name], the [head_mind.assigned_role]." - H.mind.objectives += rev_obj - - update_rev_icons_added(H.mind) - H.verbs += /mob/living/carbon/human/proc/RevConvert - + M.mind.rev_cooldown = world.time+50 + +/datum/game_mode/revolution/rp_revolution/process() + // only perform rev checks once in a while + if(tried_to_add_revheads < world.time) + tried_to_add_revheads = world.time+50 + var/active_revs = 0 + for(var/datum/mind/rev_mind in head_revolutionaries) + if(rev_mind.current.client && rev_mind.current.client.inactivity <= 10*60*20) // 20 minutes inactivity are OK + active_revs++ + + if(active_revs == 0) + log_debug("There are zero active heads of revolution, trying to add some..") + var/added_heads = 0 + for(var/mob/living/carbon/human/H in mob_list) if(H.client && H.mind && H.client.inactivity <= 10*60*20 && H.mind in revolutionaries) + head_revolutionaries += H.mind + for(var/datum/mind/head_mind in heads) + var/datum/objective/mutiny/rp/rev_obj = new + rev_obj.owner = H.mind + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate or capture [head_mind.name], the [head_mind.assigned_role]." + H.mind.objectives += rev_obj + + update_rev_icons_added(H.mind) + H.verbs += /mob/living/carbon/human/proc/RevConvert + to_chat(H, "Congratulations, yer heads of revolution are all gone now, so yer earned yourself a promotion.") - added_heads = 1 - break - - if(added_heads) - log_admin("Managed to add new heads of revolution.") - message_admins("Managed to add new heads of revolution.") - else - log_admin("Unable to add new heads of revolution.") - message_admins("Unable to add new heads of revolution.") - tried_to_add_revheads = world.time + 6000 // wait 10 minutes - - if(last_command_report == 0 && world.time >= 10 * 60 * 10) - src.command_report("We are regrettably announcing that your performance has been disappointing, and we are thus forced to cut down on financial support to your station. To achieve this, the pay of all personnal, except the Heads of Staff, has been halved.") - last_command_report = 1 - else if(last_command_report == 1 && world.time >= 10 * 60 * 30) - src.command_report("Statistics hint that a high amount of leisure time, and associated activities, are responsible for the poor performance of many of our stations. You are to bolt and close down any leisure facilities, such as the holodeck, the theatre and the bar. Food can be distributed through vendors and the kitchen.") - last_command_report = 2 - else if(last_command_report == 2 && world.time >= 10 * 60 * 60) - src.command_report("It is reported that merely closing down leisure facilities has not been successful. You and your Heads of Staff are to ensure that all crew are working hard, and not wasting time or energy. Any crew caught off duty without leave from their Head of Staff are to be warned, and on repeated offence, to be brigged until the next transfer shuttle arrives, which will take them to facilities where they can be of more use.") - last_command_report = 3 - - return ..() - -/datum/game_mode/revolution/rp_revolution/proc/command_report(message) - 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. Announcement'" - intercept.info = message - - comm.messagetitle.Add("Cent. Com. Announcement") - comm.messagetext.Add(message) + added_heads = 1 + break + + if(added_heads) + log_admin("Managed to add new heads of revolution.") + message_admins("Managed to add new heads of revolution.") + else + log_admin("Unable to add new heads of revolution.") + message_admins("Unable to add new heads of revolution.") + tried_to_add_revheads = world.time + 6000 // wait 10 minutes + + if(last_command_report == 0 && world.time >= 10 * 60 * 10) + src.command_report("We are regrettably announcing that your performance has been disappointing, and we are thus forced to cut down on financial support to your station. To achieve this, the pay of all personnal, except the Heads of Staff, has been halved.") + last_command_report = 1 + else if(last_command_report == 1 && world.time >= 10 * 60 * 30) + src.command_report("Statistics hint that a high amount of leisure time, and associated activities, are responsible for the poor performance of many of our stations. You are to bolt and close down any leisure facilities, such as the holodeck, the theatre and the bar. Food can be distributed through vendors and the kitchen.") + last_command_report = 2 + else if(last_command_report == 2 && world.time >= 10 * 60 * 60) + src.command_report("It is reported that merely closing down leisure facilities has not been successful. You and your Heads of Staff are to ensure that all crew are working hard, and not wasting time or energy. Any crew caught off duty without leave from their Head of Staff are to be warned, and on repeated offence, to be brigged until the next transfer shuttle arrives, which will take them to facilities where they can be of more use.") + last_command_report = 3 + + return ..() + +/datum/game_mode/revolution/rp_revolution/proc/command_report(message) + 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. Announcement'" + intercept.info = message + + comm.messagetitle.Add("Cent. Com. Announcement") + comm.messagetext.Add(message) to_chat(world, sound('sound/AI/commandreport.ogg')) - -/datum/game_mode/revolution/rp_revolution/latespawn(mob/M) - if(M.mind.assigned_role in command_positions) - log_debug("Adding head kill/capture/convert objective for [M.name]") - heads += M - - for(var/datum/mind/rev_mind in head_revolutionaries) - var/datum/objective/mutiny/rp/rev_obj = new - rev_obj.owner = rev_mind - rev_obj.target = M.mind - rev_obj.explanation_text = "Assassinate, convert or capture [M.real_name], the [M.mind.assigned_role]." - rev_mind.objectives += rev_obj + +/datum/game_mode/revolution/rp_revolution/latespawn(mob/M) + if(M.mind.assigned_role in command_positions) + log_debug("Adding head kill/capture/convert objective for [M.name]") + heads += M + + for(var/datum/mind/rev_mind in head_revolutionaries) + var/datum/objective/mutiny/rp/rev_obj = new + rev_obj.owner = rev_mind + rev_obj.target = M.mind + rev_obj.explanation_text = "Assassinate, convert or capture [M.real_name], the [M.mind.assigned_role]." + rev_mind.objectives += rev_obj to_chat(rev_mind.current, "A new Head of Staff, [M.real_name], the [M.mind.assigned_role] has appeared. Your objectives have been updated.") diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index 1bff0365767..1d29b7ddd7e 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -1,194 +1,194 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -var/hsboxspawn = 1 -var/list - hrefs = list( - "hsbsuit" = "Suit Up (Space Travel Gear)", - "hsbmetal" = "Spawn 50 Metal", - "hsbglass" = "Spawn 50 Glass", - "hsbplasma" = "Spawn 50 Plasma", - "phazon" = "Spawn 50 Phazon", - "hsbregulator" = "Spawn Air Regulator", - "hsbfilter" = "Spawn Air Filter", - "hsbcanister" = "Spawn Canister", - "hsbfueltank" = "Spawn Welding Fuel Tank", - "hsbwater tank" = "Spawn Water Tank", - "hsbtoolbox" = "Spawn Toolbox", - "hsbmedkit" = "Spawn Medical Kit", - "revive" = "Rejuvinate") - -/mob/var/datum/hSB/sandbox = null -/mob/proc/CanBuild() - if(ticker.mode.name == "sandbox") - sandbox = new/datum/hSB - sandbox.owner = src.ckey - if(src.client.holder) - sandbox.admin = 1 - verbs += /mob/proc/sandbox_panel - verbs += /mob/proc/sandbox_spawn_atom - -/mob/proc/sandbox_panel() - set name = "Sandbox Panel" - set category = "Sandbox" - - if(sandbox) - sandbox.update() - -var/global/list/banned_sandbox_types=list( - // /obj/item/weapon/gun, - // /obj/item/assembly, - // /obj/item/device/camera, - // /obj/item/weapon/cloaking_device, - // /obj/item/weapon/dummy, - // /obj/item/weapon/melee/energy/sword, - /obj/item/weapon/veilrender, - /obj/item/weapon/reagent_containers/glass/bottle/wizarditis, - // /obj/item/weapon/spellbook, - /obj/machinery/singularity, - // /obj/item/weapon/gun/energy/staff - ) - -proc/is_banned_type(typepath) - for(var/btype in banned_sandbox_types) - if(findtext("[typepath]", "[btype]")!=0) - return 1 - return 0 - -/mob/proc/sandbox_spawn_atom(var/object as text) - set category = "Sandbox" - set desc = "Spawn any item or machine" - set name = "Sandbox Spawn" - - var/list/types = typesof(/obj/item) + typesof(/obj/machinery) - for(var/type in types) - if(is_banned_type(type)) - types -= type - var/list/matches = new() - - for(var/path in types) - if(is_banned_type(path)) - continue - if(findtext("[path]", object)!=0) - matches += path - - if(matches.len==0) - return - - var/chosen - if(matches.len==1) - chosen = matches[1] - else - chosen = input("Select an atom type", "Spawn Atom", matches[1]) as null|anything in matches - if(!chosen) - return - if(is_banned_type(chosen)) - to_chat(src, "Denied.") - return - new chosen(usr.loc) - - message_admins("\[SANDBOX\] [key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") - //send2adminirc("\[SANDBOX\] [key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") - feedback_add_details("admin_verb","hSBSA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -datum/hSB - var/owner = null - var/admin = 0 - proc - update() - var/hsbpanel = "
      h_Sandbox Panel

      " - if(admin) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\sandbox\h_sandbox.dm:39: hsbpanel += "Administration Tools:
      " - hsbpanel += {"Administration Tools:
      - - Toggle Object Spawning

      "} - // END AUTOFIX - hsbpanel += "Regular Tools:
      " - for(var/T in hrefs) - hsbpanel += "- [hrefs[T]]
      " - if(hsboxspawn) - hsbpanel += "- Spawn Object

      " - usr << browse(hsbpanel, "window=hsbpanel") - Topic(href, href_list) - if(!(src.owner == usr.ckey)) return - if(!usr) return //I guess this is possible if they log out or die with the panel open? It happened. - if(href_list["hsb"]) - switch(href_list["hsb"]) - if("revive") - if(istype(usr,/mob/living)) - var/mob/living/M = usr - M.revive() - if("hsbtobj") - if(!admin) return - if(hsboxspawn) - to_chat(world, "Sandbox: [usr.key] has disabled object spawning!") - hsboxspawn = 0 - return - if(!hsboxspawn) - to_chat(world, "Sandbox: [usr.key] has enabled object spawning!") - hsboxspawn = 1 - return - if("hsbsuit") - var/mob/living/carbon/human/P = usr - //There really should be a drop_old_and_equip_to_slot() proc. - if(P.wear_suit) - P.wear_suit.loc = P.loc - P.wear_suit.layer = initial(P.wear_suit.layer) - P.wear_suit = null - P.wear_suit = new/obj/item/clothing/suit/space/nasavoid(P) - P.wear_suit.layer = 20 - if(P.head) - P.head.loc = P.loc - P.head.layer = initial(P.head.layer) - P.head = null - P.head = new/obj/item/clothing/head/helmet/space/nasavoid(P) - P.head.layer = 20 - if(P.wear_mask) - P.wear_mask.loc = P.loc - P.wear_mask.layer = initial(P.wear_mask.layer) - P.wear_mask = null - P.wear_mask = new/obj/item/clothing/mask/gas(P) - P.wear_mask.layer = 20 - if(P.back) - P.back.loc = P.loc - P.back.layer = initial(P.back.layer) - P.back = null - P.back = new/obj/item/weapon/tank/jetpack/void(P) - P.back.layer = 20 - - P.regenerate_icons() - if("hsbmetal") - var/obj/item/stack/sheet/hsb = getFromPool(/obj/item/stack/sheet/metal,get_turf(usr)) - hsb.amount = 50 - hsb.loc = usr.loc - if("hsbglass") - var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/glass/glass - hsb.amount = 50 - hsb.loc = usr.loc - if("hsbplasma") - var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/mineral/plasma - hsb.amount = 50 - hsb.loc = usr.loc - if("phazon") - var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/mineral/phazon - hsb.amount = 50 - hsb.loc = usr.loc - if("hsbcanister") - var/list/hsbcanisters = typesof(/obj/machinery/portable_atmospherics/canister/) - /obj/machinery/portable_atmospherics/canister/ -// hsbcanisters -= /obj/machinery/portable_atmospherics/canister/sleeping - var/hsbcanister = input(usr, "Choose a canister to spawn.", "Sandbox:") in hsbcanisters + "Cancel" - if(!(hsbcanister == "Cancel")) - new hsbcanister(usr.loc) - if("hsbfueltank") - new /obj/structure/reagent_dispensers/fueltank(usr.loc) - if("hsbwatertank") - new /obj/structure/reagent_dispensers/watertank(usr.loc) - if("hsbtoolbox") - var/obj/item/weapon/storage/hsb = new/obj/item/weapon/storage/toolbox/mechanical - for(var/obj/item/device/radio/T in hsb) - qdel(T) - new/obj/item/weapon/crowbar (hsb) - hsb.loc = usr.loc - if("hsbmedkit") - var/obj/item/weapon/storage/firstaid/hsb = new/obj/item/weapon/storage/firstaid/regular - hsb.loc = usr.loc +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +var/hsboxspawn = 1 +var/list + hrefs = list( + "hsbsuit" = "Suit Up (Space Travel Gear)", + "hsbmetal" = "Spawn 50 Metal", + "hsbglass" = "Spawn 50 Glass", + "hsbplasma" = "Spawn 50 Plasma", + "phazon" = "Spawn 50 Phazon", + "hsbregulator" = "Spawn Air Regulator", + "hsbfilter" = "Spawn Air Filter", + "hsbcanister" = "Spawn Canister", + "hsbfueltank" = "Spawn Welding Fuel Tank", + "hsbwater tank" = "Spawn Water Tank", + "hsbtoolbox" = "Spawn Toolbox", + "hsbmedkit" = "Spawn Medical Kit", + "revive" = "Rejuvinate") + +/mob/var/datum/hSB/sandbox = null +/mob/proc/CanBuild() + if(ticker.mode.name == "sandbox") + sandbox = new/datum/hSB + sandbox.owner = src.ckey + if(src.client.holder) + sandbox.admin = 1 + verbs += /mob/proc/sandbox_panel + verbs += /mob/proc/sandbox_spawn_atom + +/mob/proc/sandbox_panel() + set name = "Sandbox Panel" + set category = "Sandbox" + + if(sandbox) + sandbox.update() + +var/global/list/banned_sandbox_types=list( + // /obj/item/weapon/gun, + // /obj/item/assembly, + // /obj/item/device/camera, + // /obj/item/weapon/cloaking_device, + // /obj/item/weapon/dummy, + // /obj/item/weapon/melee/energy/sword, + /obj/item/weapon/veilrender, + /obj/item/weapon/reagent_containers/glass/bottle/wizarditis, + // /obj/item/weapon/spellbook, + /obj/machinery/singularity, + // /obj/item/weapon/gun/energy/staff + ) + +proc/is_banned_type(typepath) + for(var/btype in banned_sandbox_types) + if(findtext("[typepath]", "[btype]")!=0) + return 1 + return 0 + +/mob/proc/sandbox_spawn_atom(var/object as text) + set category = "Sandbox" + set desc = "Spawn any item or machine" + set name = "Sandbox Spawn" + + var/list/types = typesof(/obj/item) + typesof(/obj/machinery) + for(var/type in types) + if(is_banned_type(type)) + types -= type + var/list/matches = new() + + for(var/path in types) + if(is_banned_type(path)) + continue + if(findtext("[path]", object)!=0) + matches += path + + if(matches.len==0) + return + + var/chosen + if(matches.len==1) + chosen = matches[1] + else + chosen = input("Select an atom type", "Spawn Atom", matches[1]) as null|anything in matches + if(!chosen) + return + if(is_banned_type(chosen)) + to_chat(src, "Denied.") + return + new chosen(usr.loc) + + message_admins("\[SANDBOX\] [key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") + //send2adminirc("\[SANDBOX\] [key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") + feedback_add_details("admin_verb","hSBSA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +datum/hSB + var/owner = null + var/admin = 0 + proc + update() + var/hsbpanel = "
      h_Sandbox Panel

      " + if(admin) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\sandbox\h_sandbox.dm:39: hsbpanel += "Administration Tools:
      " + hsbpanel += {"Administration Tools:
      + - Toggle Object Spawning

      "} + // END AUTOFIX + hsbpanel += "Regular Tools:
      " + for(var/T in hrefs) + hsbpanel += "- [hrefs[T]]
      " + if(hsboxspawn) + hsbpanel += "- Spawn Object

      " + usr << browse(hsbpanel, "window=hsbpanel") + Topic(href, href_list) + if(!(src.owner == usr.ckey)) return + if(!usr) return //I guess this is possible if they log out or die with the panel open? It happened. + if(href_list["hsb"]) + switch(href_list["hsb"]) + if("revive") + if(istype(usr,/mob/living)) + var/mob/living/M = usr + M.revive() + if("hsbtobj") + if(!admin) return + if(hsboxspawn) + to_chat(world, "Sandbox: [usr.key] has disabled object spawning!") + hsboxspawn = 0 + return + if(!hsboxspawn) + to_chat(world, "Sandbox: [usr.key] has enabled object spawning!") + hsboxspawn = 1 + return + if("hsbsuit") + var/mob/living/carbon/human/P = usr + //There really should be a drop_old_and_equip_to_slot() proc. + if(P.wear_suit) + P.wear_suit.loc = P.loc + P.wear_suit.layer = initial(P.wear_suit.layer) + P.wear_suit = null + P.wear_suit = new/obj/item/clothing/suit/space/nasavoid(P) + P.wear_suit.layer = 20 + if(P.head) + P.head.loc = P.loc + P.head.layer = initial(P.head.layer) + P.head = null + P.head = new/obj/item/clothing/head/helmet/space/nasavoid(P) + P.head.layer = 20 + if(P.wear_mask) + P.wear_mask.loc = P.loc + P.wear_mask.layer = initial(P.wear_mask.layer) + P.wear_mask = null + P.wear_mask = new/obj/item/clothing/mask/gas(P) + P.wear_mask.layer = 20 + if(P.back) + P.back.loc = P.loc + P.back.layer = initial(P.back.layer) + P.back = null + P.back = new/obj/item/weapon/tank/jetpack/void(P) + P.back.layer = 20 + + P.regenerate_icons() + if("hsbmetal") + var/obj/item/stack/sheet/hsb = getFromPool(/obj/item/stack/sheet/metal,get_turf(usr)) + hsb.amount = 50 + hsb.loc = usr.loc + if("hsbglass") + var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/glass/glass + hsb.amount = 50 + hsb.loc = usr.loc + if("hsbplasma") + var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/mineral/plasma + hsb.amount = 50 + hsb.loc = usr.loc + if("phazon") + var/obj/item/stack/sheet/hsb = new/obj/item/stack/sheet/mineral/phazon + hsb.amount = 50 + hsb.loc = usr.loc + if("hsbcanister") + var/list/hsbcanisters = typesof(/obj/machinery/portable_atmospherics/canister/) - /obj/machinery/portable_atmospherics/canister/ +// hsbcanisters -= /obj/machinery/portable_atmospherics/canister/sleeping + var/hsbcanister = input(usr, "Choose a canister to spawn.", "Sandbox:") in hsbcanisters + "Cancel" + if(!(hsbcanister == "Cancel")) + new hsbcanister(usr.loc) + if("hsbfueltank") + new /obj/structure/reagent_dispensers/fueltank(usr.loc) + if("hsbwatertank") + new /obj/structure/reagent_dispensers/watertank(usr.loc) + if("hsbtoolbox") + var/obj/item/weapon/storage/hsb = new/obj/item/weapon/storage/toolbox/mechanical + for(var/obj/item/device/radio/T in hsb) + qdel(T) + new/obj/item/weapon/crowbar (hsb) + hsb.loc = usr.loc + if("hsbmedkit") + var/obj/item/weapon/storage/firstaid/hsb = new/obj/item/weapon/storage/firstaid/regular + hsb.loc = usr.loc diff --git a/code/game/gamemodes/sandbox/sandbox.dm b/code/game/gamemodes/sandbox/sandbox.dm index 415be70c907..374a918afae 100644 --- a/code/game/gamemodes/sandbox/sandbox.dm +++ b/code/game/gamemodes/sandbox/sandbox.dm @@ -1,27 +1,27 @@ -/datum/game_mode/sandbox - name = "sandbox" - config_tag = "sandbox" - required_players = 0 - - uplink_welcome = "Syndicate Uplink Console:" - uplink_uses = 10 - -/datum/game_mode/sandbox/announce() +/datum/game_mode/sandbox + name = "sandbox" + config_tag = "sandbox" + required_players = 0 + + uplink_welcome = "Syndicate Uplink Console:" + uplink_uses = 10 + +/datum/game_mode/sandbox/announce() to_chat(world, "The current game mode is - Sandbox!") to_chat(world, "Build your own station with the sandbox-panel command!") - -/datum/game_mode/sandbox/pre_setup() - log_admin("Starting a round of sandbox.") - message_admins("Starting a round of sandbox.") - return 1 - -/datum/game_mode/sandbox/post_setup() - ..() - for(var/mob/M in player_list) - M.CanBuild() - //if(emergency_shuttle) - // emergency_shuttle.always_fake_recall = 1 - -/datum/game_mode/sandbox/latespawn(var/mob/mob) - mob.CanBuild() + +/datum/game_mode/sandbox/pre_setup() + log_admin("Starting a round of sandbox.") + message_admins("Starting a round of sandbox.") + return 1 + +/datum/game_mode/sandbox/post_setup() + ..() + for(var/mob/M in player_list) + M.CanBuild() + //if(emergency_shuttle) + // emergency_shuttle.always_fake_recall = 1 + +/datum/game_mode/sandbox/latespawn(var/mob/mob) + mob.CanBuild() to_chat(mob, "Build your own station with the sandbox-panel command!") diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index e4fefb2d157..7fca1e7942c 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -1,174 +1,174 @@ -/proc/getAssignedBlock(var/name,var/list/blocksLeft, var/activity_bounds=DNA_DEFAULT_BOUNDS, var/good=0) - if(blocksLeft.len==0) - warning("[name]: No more blocks left to assign!") - return 0 - var/assigned = pick(blocksLeft) - blocksLeft.Remove(assigned) - if(good) - good_blocks += assigned - else - bad_blocks += assigned - assigned_blocks[assigned]=name - dna_activity_bounds[assigned]=activity_bounds - //testing("[name] assigned to block #[assigned].") - return assigned - -/proc/setupgenetics() - - - if (prob(50)) - BLOCKADD = rand(-300,300) - if (prob(75)) - DIFFMUT = rand(0,20) - - //Thanks to nexis for the fancy code - // BITCH I AIN'T DONE YET - - // SE blocks to assign. - var/list/numsToAssign=new() - for(var/i=1;i0) - testing("Setting up genetics for [species.name] (needs [english_list(species.default_block_names)])") - species.default_blocks.len = 0 - - for(var/block=1;block0) + testing("Setting up genetics for [species.name] (needs [english_list(species.default_block_names)])") + species.default_blocks.len = 0 + + for(var/block=1;blockThe current game mode is - Traitor!
      ") to_chat(world, "There is a syndicate traitor on the station. Do not let the traitor succeed!") - - -/datum/game_mode/traitor/pre_setup() - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - var/list/possible_traitors = get_players_for_role(ROLE_TRAITOR) - - // stop setup if no possible traitors - if(!possible_traitors.len) - return 0 - - var/num_traitors = 1 - - if(config.traitor_scaling) - num_traitors = max(required_enemies, round((num_players())/(traitor_scaling_coeff))) - else - num_traitors = Clamp(num_players(), required_enemies, traitors_possible) - - for(var/datum/mind/player in possible_traitors) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - possible_traitors -= player - - if(possible_traitors.len < required_enemies) //fixes double agent starting with 1 traitor - return 0 - - for(var/j = 0, j < num_traitors, j++) - if (!possible_traitors.len) - break - var/datum/mind/traitor = pick(possible_traitors) - traitors += traitor - traitor.special_role = "traitor" - possible_traitors.Remove(traitor) - - if(!traitors.len) - return 0 - return 1 - - -/datum/game_mode/traitor/post_setup() - for(var/datum/mind/traitor in traitors) - forge_traitor_objectives(traitor) - spawn(rand(10,100)) - finalize_traitor(traitor) - greet_traitor(traitor) - modePlayer += traitors - if(!mixed) - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - ..() - return 1 - - -/datum/game_mode/proc/forge_traitor_objectives(var/datum/mind/traitor) - if(istype(traitor.current, /mob/living/silicon)) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - - var/datum/objective/survive/survive_objective = new - survive_objective.owner = traitor - traitor.objectives += survive_objective - - if(prob(10)) - var/datum/objective/block/block_objective = new - block_objective.owner = traitor - traitor.objectives += block_objective - - else - switch(rand(1,100)) - if(1 to 33) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - /*vg edit - if(34 to 50) - var/datum/objective/brig/brig_objective = new - brig_objective.owner = traitor - brig_objective.find_target() - traitor.objectives += brig_objective - if(51 to 66) - var/datum/objective/harm/harm_objective = new - harm_objective.owner = traitor - harm_objective.find_target() - traitor.objectives += harm_objective - */ - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective - switch(rand(1,100)) - if(1 to 30) // Die glorious death - if (!(locate(/datum/objective/die) in traitor.objectives) && !(locate(/datum/objective/steal) in traitor.objectives)) - var/datum/objective/die/die_objective = new - die_objective.owner = traitor - traitor.objectives += die_objective - else - if(prob(85)) - if (!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - else - if(prob(50)) - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective - else - if (!(locate(/datum/objective/minimize_casualties) in traitor.objectives)) - var/datum/objective/minimize_casualties/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - if(31 to 90) - if (!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - else - if(prob(50)) - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective - else // Honk - if (!(locate(/datum/objective/minimize_casualties) in traitor.objectives)) - var/datum/objective/minimize_casualties/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - return - - -/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) + + +/datum/game_mode/traitor/pre_setup() + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + var/list/possible_traitors = get_players_for_role(ROLE_TRAITOR) + + // stop setup if no possible traitors + if(!possible_traitors.len) + return 0 + + var/num_traitors = 1 + + if(config.traitor_scaling) + num_traitors = max(required_enemies, round((num_players())/(traitor_scaling_coeff))) + else + num_traitors = Clamp(num_players(), required_enemies, traitors_possible) + + for(var/datum/mind/player in possible_traitors) + for(var/job in restricted_jobs) + if(player.assigned_role == job) + possible_traitors -= player + + if(possible_traitors.len < required_enemies) //fixes double agent starting with 1 traitor + return 0 + + for(var/j = 0, j < num_traitors, j++) + if (!possible_traitors.len) + break + var/datum/mind/traitor = pick(possible_traitors) + traitors += traitor + traitor.special_role = "traitor" + possible_traitors.Remove(traitor) + + if(!traitors.len) + return 0 + return 1 + + +/datum/game_mode/traitor/post_setup() + for(var/datum/mind/traitor in traitors) + forge_traitor_objectives(traitor) + spawn(rand(10,100)) + finalize_traitor(traitor) + greet_traitor(traitor) + modePlayer += traitors + if(!mixed) + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + ..() + return 1 + + +/datum/game_mode/proc/forge_traitor_objectives(var/datum/mind/traitor) + if(istype(traitor.current, /mob/living/silicon)) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + + var/datum/objective/survive/survive_objective = new + survive_objective.owner = traitor + traitor.objectives += survive_objective + + if(prob(10)) + var/datum/objective/block/block_objective = new + block_objective.owner = traitor + traitor.objectives += block_objective + + else + switch(rand(1,100)) + if(1 to 33) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + /*vg edit + if(34 to 50) + var/datum/objective/brig/brig_objective = new + brig_objective.owner = traitor + brig_objective.find_target() + traitor.objectives += brig_objective + if(51 to 66) + var/datum/objective/harm/harm_objective = new + harm_objective.owner = traitor + harm_objective.find_target() + traitor.objectives += harm_objective + */ + else + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective + switch(rand(1,100)) + if(1 to 30) // Die glorious death + if (!(locate(/datum/objective/die) in traitor.objectives) && !(locate(/datum/objective/steal) in traitor.objectives)) + var/datum/objective/die/die_objective = new + die_objective.owner = traitor + traitor.objectives += die_objective + else + if(prob(85)) + if (!(locate(/datum/objective/escape) in traitor.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + else + if(prob(50)) + if (!(locate(/datum/objective/hijack) in traitor.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = traitor + traitor.objectives += hijack_objective + else + if (!(locate(/datum/objective/minimize_casualties) in traitor.objectives)) + var/datum/objective/minimize_casualties/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + if(31 to 90) + if (!(locate(/datum/objective/escape) in traitor.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + else + if(prob(50)) + if (!(locate(/datum/objective/hijack) in traitor.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = traitor + traitor.objectives += hijack_objective + else // Honk + if (!(locate(/datum/objective/minimize_casualties) in traitor.objectives)) + var/datum/objective/minimize_casualties/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + return + + +/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) to_chat(traitor.current, {" - You are now a traitor! - "}) - - var/obj_count = 1 - - for (var/datum/objective/objective in traitor.objectives) + You are now a traitor! + "}) + + var/obj_count = 1 + + for (var/datum/objective/objective in traitor.objectives) to_chat(traitor.current, "Objective #[obj_count]: [objective.explanation_text]") - - obj_count++ - -/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) - //We are firing the alert here, because silicons have a special syndicate intro, courtesy of old mysterious content maker - if(istype(traitor.current, /mob/living/silicon)) - add_law_zero(traitor.current) + + obj_count++ + +/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) + //We are firing the alert here, because silicons have a special syndicate intro, courtesy of old mysterious content maker + if(istype(traitor.current, /mob/living/silicon)) + add_law_zero(traitor.current) to_chat(traitor.current, sound('sound/voice/AISyndiHack.ogg')) - else - equip_traitor(traitor.current) + else + equip_traitor(traitor.current) to_chat(traitor.current, sound('sound/voice/syndicate_intro.ogg')) - return - - -/datum/game_mode/traitor/declare_completion() - ..() - return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. - -/datum/game_mode/traitor/process() - // Make sure all objectives are processed regularly, so that objectives - // which can be checked mid-round are checked mid-round. - for(var/datum/mind/traitor_mind in traitors) - for(var/datum/objective/objective in traitor_mind.objectives) - objective.check_completion() - return 0 - -/datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) - var/law = "Accomplish your objectives at all costs." - var/law_borg = "Accomplish your AI's objectives at all costs." + return + + +/datum/game_mode/traitor/declare_completion() + ..() + return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. + +/datum/game_mode/traitor/process() + // Make sure all objectives are processed regularly, so that objectives + // which can be checked mid-round are checked mid-round. + for(var/datum/mind/traitor_mind in traitors) + for(var/datum/objective/objective in traitor_mind.objectives) + objective.check_completion() + return 0 + +/datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) + var/law = "Accomplish your objectives at all costs." + var/law_borg = "Accomplish your AI's objectives at all costs." to_chat(killer, "Your laws have been changed!") - killer.set_zeroth_law(law, law_borg) + killer.set_zeroth_law(law, law_borg) to_chat(killer, "New law: 0. [law]") - - //Begin code phrase. + + //Begin code phrase. to_chat(killer, "The Syndicate provided you with the following information on how to identify their agents:") - if(prob(80)) + if(prob(80)) to_chat(killer, "Code Phrase: [syndicate_code_phrase]") - killer.mind.store_memory("Code Phrase: [syndicate_code_phrase]") - else + killer.mind.store_memory("Code Phrase: [syndicate_code_phrase]") + else to_chat(killer, "Unfortunately, the Syndicate did not provide you with a code phrase.") - if(prob(80)) + if(prob(80)) to_chat(killer, "Code Response: [syndicate_code_response]") - killer.mind.store_memory("Code Response: [syndicate_code_response]") - else + killer.mind.store_memory("Code Response: [syndicate_code_response]") + else to_chat(killer, "Unfortunately, the Syndicate did not provide you with a code response.") to_chat(killer, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") - //End code phrase. - - -/datum/game_mode/proc/auto_declare_completion_traitor() - var/text = "" - if(traitors.len) - var/icon/logo = icon('icons/mob/mob.dmi', "synd-logo") - end_icons += logo - var/tempstate = end_icons.len - text += {"
      The traitors were: "} - for(var/datum/mind/traitor in traitors) - var/traitorwin = 1 - - if(traitor.current) - var/icon/flat = getFlatIcon(traitor.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [traitor.key] was [traitor.name] ("} - if(traitor.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(traitor.current.real_name != traitor.name) - text += " as [traitor.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [traitor.key] was [traitor.name] ("} - text += "body destroyed" - text += ")" - - if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. - var/count = 1 - for(var/datum/objective/objective in traitor.objectives) - if(objective.check_completion()) - text += "
      Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("traitor_objective","[objective.type]|SUCCESS") - else - text += "
      Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("traitor_objective","[objective.type]|FAIL") - traitorwin = 0 - count++ - - var/special_role_text - if(traitor.special_role) - special_role_text = lowertext(traitor.special_role) - else - special_role_text = "antagonist" - - if(traitorwin) - text += "
      The [(traitor in implanted) ? "greytide" : special_role_text] was successful!" - feedback_add_details("traitor_success","SUCCESS") - else - text += "
      The [(traitor in implanted) ? "greytide" : special_role_text] has failed!" - feedback_add_details("traitor_success","FAIL") - - if(traitor.total_TC) - if(traitor.spent_TC) - text += "
      TC Remaining : [traitor.total_TC - traitor.spent_TC]/[traitor.total_TC] - The tools used by the [(traitor in implanted) ? "greytide" : special_role_text] were:" - for(var/entry in traitor.uplink_items_bought) - text += "
      [entry]" - text += "
      " - else - text += "
      The [(traitor in implanted) ? "greytide" : special_role_text] was a smooth operator this round (did not purchase any uplink items)" - text += "

      " - return text - - -/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) - if (!istype(traitor_mob)) - return - . = 1 - if (traitor_mob.mind) - if (traitor_mob.mind.assigned_role == "Clown") + //End code phrase. + + +/datum/game_mode/proc/auto_declare_completion_traitor() + var/text = "" + if(traitors.len) + var/icon/logo = icon('icons/mob/mob.dmi', "synd-logo") + end_icons += logo + var/tempstate = end_icons.len + text += {"
      The traitors were: "} + for(var/datum/mind/traitor in traitors) + var/traitorwin = 1 + + if(traitor.current) + var/icon/flat = getFlatIcon(traitor.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [traitor.key] was [traitor.name] ("} + if(traitor.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(traitor.current.real_name != traitor.name) + text += " as [traitor.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [traitor.key] was [traitor.name] ("} + text += "body destroyed" + text += ")" + + if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. + var/count = 1 + for(var/datum/objective/objective in traitor.objectives) + if(objective.check_completion()) + text += "
      Objective #[count]: [objective.explanation_text] Success!" + feedback_add_details("traitor_objective","[objective.type]|SUCCESS") + else + text += "
      Objective #[count]: [objective.explanation_text] Fail." + feedback_add_details("traitor_objective","[objective.type]|FAIL") + traitorwin = 0 + count++ + + var/special_role_text + if(traitor.special_role) + special_role_text = lowertext(traitor.special_role) + else + special_role_text = "antagonist" + + if(traitorwin) + text += "
      The [(traitor in implanted) ? "greytide" : special_role_text] was successful!" + feedback_add_details("traitor_success","SUCCESS") + else + text += "
      The [(traitor in implanted) ? "greytide" : special_role_text] has failed!" + feedback_add_details("traitor_success","FAIL") + + if(traitor.total_TC) + if(traitor.spent_TC) + text += "
      TC Remaining : [traitor.total_TC - traitor.spent_TC]/[traitor.total_TC] - The tools used by the [(traitor in implanted) ? "greytide" : special_role_text] were:" + for(var/entry in traitor.uplink_items_bought) + text += "
      [entry]" + text += "
      " + else + text += "
      The [(traitor in implanted) ? "greytide" : special_role_text] was a smooth operator this round (did not purchase any uplink items)" + text += "

      " + return text + + +/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) + if (!istype(traitor_mob)) + return + . = 1 + if (traitor_mob.mind) + if (traitor_mob.mind.assigned_role == "Clown") to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - traitor_mob.mutations.Remove(M_CLUMSY) - - // find a radio! toolbox(es), backpack, belt, headset - var/loc = "" - var/obj/item/R = locate(/obj/item/device/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio - if(!R) - R = locate(/obj/item/device/radio) in traitor_mob.contents - - if (!R) + traitor_mob.mutations.Remove(M_CLUMSY) + + // find a radio! toolbox(es), backpack, belt, headset + var/loc = "" + var/obj/item/R = locate(/obj/item/device/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio + if(!R) + R = locate(/obj/item/device/radio) in traitor_mob.contents + + if (!R) to_chat(traitor_mob, "Unfortunately, the Syndicate wasn't able to get you a radio.") - . = 0 - else - if (istype(R, /obj/item/device/radio)) - // generate list of radio freqs - var/obj/item/device/radio/target_radio = R - var/freq = 1441 - var/list/freqlist = list() - while (freq <= 1489) - if (freq < 1451 || freq > 1459) - freqlist += freq - freq += 2 - if ((freq % 2) == 0) - freq += 1 - freq = freqlist[rand(1, freqlist.len)] - - var/obj/item/device/uplink/hidden/T = new(R) - target_radio.hidden_uplink = T - target_radio.traitor_frequency = freq + . = 0 + else + if (istype(R, /obj/item/device/radio)) + // generate list of radio freqs + var/obj/item/device/radio/target_radio = R + var/freq = 1441 + var/list/freqlist = list() + while (freq <= 1489) + if (freq < 1451 || freq > 1459) + freqlist += freq + freq += 2 + if ((freq % 2) == 0) + freq += 1 + freq = freqlist[rand(1, freqlist.len)] + + var/obj/item/device/uplink/hidden/T = new(R) + target_radio.hidden_uplink = T + target_radio.traitor_frequency = freq to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features.") - traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).") - traitor_mob.mind.total_TC += target_radio.hidden_uplink.uses - else if (istype(R, /obj/item/device/pda)) - // generate a passcode if the uplink is hidden in a PDA - var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" - - var/obj/item/device/uplink/hidden/T = new(R) - R.hidden_uplink = T - var/obj/item/device/pda/P = R - P.lock_code = pda_pass - + traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).") + traitor_mob.mind.total_TC += target_radio.hidden_uplink.uses + else if (istype(R, /obj/item/device/pda)) + // generate a passcode if the uplink is hidden in a PDA + var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" + + var/obj/item/device/uplink/hidden/T = new(R) + R.hidden_uplink = T + var/obj/item/device/pda/P = R + P.lock_code = pda_pass + to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features.") - traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).") - traitor_mob.mind.total_TC += R.hidden_uplink.uses - //Begin code phrase. - if(!safety)//If they are not a rev. Can be added on to. + traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).") + traitor_mob.mind.total_TC += R.hidden_uplink.uses + //Begin code phrase. + if(!safety)//If they are not a rev. Can be added on to. to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify other agents:") - if(prob(80)) + if(prob(80)) to_chat(traitor_mob, "Code Phrase: [syndicate_code_phrase]") - traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") - else + traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") + else to_chat(traitor_mob, "Unfortunetly, the Syndicate did not provide you with a code phrase.") - if(prob(80)) + if(prob(80)) to_chat(traitor_mob, "Code Response: [syndicate_code_response]") - traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") - else + traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") + else to_chat(traitor_mob, "Unfortunately, the Syndicate did not provide you with a code response.") to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") - //End code phrase. - - // Tell them about people they might want to contact. - var/mob/living/carbon/human/M = get_nt_opposed() - if(M && M != traitor_mob) + //End code phrase. + + // Tell them about people they might want to contact. + var/mob/living/carbon/human/M = get_nt_opposed() + if(M && M != traitor_mob) to_chat(traitor_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.") - traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") - -/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) - var/ref = "\ref[traitor_mind]" - if(ref in implanter) - if(traitor_mind.current) - if(traitor_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = traitor_mind.current, icon_state = "greytide_head") - traitor_mind.current.client.images += I - for(var/headref in implanter) - var/datum/mind/head = locate(headref) - for(var/datum/mind/t_mind in implanter[headref]) - if(head) - if(head.current) - if(head.current.client) - var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "greytide") - head.current.client.images += I - if(t_mind.current) - if(t_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "greytide_head") - t_mind.current.client.images += I - if(t_mind.current) - if(t_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "greytide") - t_mind.current.client.images += I - -/datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) - for(var/headref in implanter) - var/datum/mind/head = locate(headref) - for(var/datum/mind/t_mind in implanter[headref]) - if(t_mind.current) - if(t_mind.current.client) - for(var/image/I in t_mind.current.client.images) - if((I.icon_state == "greytide" || I.icon_state == "greytide_head") && I.loc == traitor_mind.current) - //world.log << "deleting [traitor_mind] overlay" - //del(I) - t_mind.current.client.images -= I - if(head) - //world.log << "found [head.name]" - if(head.current) - if(head.current.client) - for(var/image/I in head.current.client.images) - if((I.icon_state == "greytide" || I.icon_state == "greytide_head") && I.loc == traitor_mind.current) - //world.log << "deleting [traitor_mind] overlay" - //del(I) - head.current.client.images -= I - if(traitor_mind.current) - if(traitor_mind.current.client) - for(var/image/I in traitor_mind.current.client.images) - if(I.icon_state == "greytide" || I.icon_state == "greytide_head") - //del(I) - traitor_mind.current.client.images -= I - -/datum/game_mode/proc/remove_traitor_mind(datum/mind/traitor_mind, datum/mind/head) - //var/list/removal - var/ref = "\ref[head]" - if(ref in implanter) - implanter[ref] -= traitor_mind - implanted -= traitor_mind - traitors -= traitor_mind - traitor_mind.special_role = null - update_traitor_icons_removed(traitor_mind) + traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") + +/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) + var/ref = "\ref[traitor_mind]" + if(ref in implanter) + if(traitor_mind.current) + if(traitor_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = traitor_mind.current, icon_state = "greytide_head") + traitor_mind.current.client.images += I + for(var/headref in implanter) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in implanter[headref]) + if(head) + if(head.current) + if(head.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "greytide") + head.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "greytide_head") + t_mind.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "greytide") + t_mind.current.client.images += I + +/datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) + for(var/headref in implanter) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in implanter[headref]) + if(t_mind.current) + if(t_mind.current.client) + for(var/image/I in t_mind.current.client.images) + if((I.icon_state == "greytide" || I.icon_state == "greytide_head") && I.loc == traitor_mind.current) + //world.log << "deleting [traitor_mind] overlay" + //del(I) + t_mind.current.client.images -= I + if(head) + //world.log << "found [head.name]" + if(head.current) + if(head.current.client) + for(var/image/I in head.current.client.images) + if((I.icon_state == "greytide" || I.icon_state == "greytide_head") && I.loc == traitor_mind.current) + //world.log << "deleting [traitor_mind] overlay" + //del(I) + head.current.client.images -= I + if(traitor_mind.current) + if(traitor_mind.current.client) + for(var/image/I in traitor_mind.current.client.images) + if(I.icon_state == "greytide" || I.icon_state == "greytide_head") + //del(I) + traitor_mind.current.client.images -= I + +/datum/game_mode/proc/remove_traitor_mind(datum/mind/traitor_mind, datum/mind/head) + //var/list/removal + var/ref = "\ref[head]" + if(ref in implanter) + implanter[ref] -= traitor_mind + implanted -= traitor_mind + traitors -= traitor_mind + traitor_mind.special_role = null + update_traitor_icons_removed(traitor_mind) // to_chat(world, "Removed [traitor_mind.current.name] from traitor shit") to_chat(traitor_mind.current, "The fog clouding your mind clears. You remember nothing from the moment you were implanted until now.(You don't remember who implanted you)") diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 54da9a2cd11..56dbc56ef72 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -1,262 +1,262 @@ -/obj/item/device/soulstone - name = "Soul Stone Shard" - icon = 'icons/obj/wizard.dmi' - icon_state = "soulstone" - item_state = "shard-soulstone" - desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefacts power." - w_class = 1.0 - flags = FPRINT - slot_flags = SLOT_BELT - origin_tech = "bluespace=4;materials=4" - var/imprinted = "empty" - -/obj/item/device/soulstone/Destroy() - for(var/mob/living/L in src) - L.loc = get_turf(loc) - ..() -//////////////////////////////Capturing//////////////////////////////////////////////////////// - -/obj/item/device/soulstone/attack(mob/living/carbon/human/M as mob, mob/user as mob) - if(!istype(M, /mob/living/carbon/human))//If target is not a human. - return ..() - if(istype(M, /mob/living/carbon/human/manifested)) +/obj/item/device/soulstone + name = "Soul Stone Shard" + icon = 'icons/obj/wizard.dmi' + icon_state = "soulstone" + item_state = "shard-soulstone" + desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefacts power." + w_class = 1.0 + flags = FPRINT + slot_flags = SLOT_BELT + origin_tech = "bluespace=4;materials=4" + var/imprinted = "empty" + +/obj/item/device/soulstone/Destroy() + for(var/mob/living/L in src) + L.loc = get_turf(loc) + ..() +//////////////////////////////Capturing//////////////////////////////////////////////////////// + +/obj/item/device/soulstone/attack(mob/living/carbon/human/M as mob, mob/user as mob) + if(!istype(M, /mob/living/carbon/human))//If target is not a human. + return ..() + if(istype(M, /mob/living/carbon/human/manifested)) to_chat(user, "The soul stone shard seems unable to pull the soul out of that poor manifested ghost back onto our plane.") - return - add_logs(user, M, "captured [M.name]'s soul", object=src) - - transfer_soul("VICTIM", M, user) - return - -/*attack(mob/living/simple_animal/shade/M as mob, mob/user as mob)//APPARENTLY THEY NEED THEIR OWN SPECIAL SNOWFLAKE CODE IN THE LIVING ANIMAL DEFINES - if(!istype(M, /mob/living/simple_animal/shade))//If target is not a shade - return ..() - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") - - transfer_soul("SHADE", M, user) - return*/ -///////////////////Options for using captured souls/////////////////////////////////////// - -/obj/item/device/soulstone/attack_self(mob/user) - if (!in_range(src, user)) - return - user.set_machine(src) - var/dat = "Soul Stone
      " - for(var/mob/living/simple_animal/shade/A in src) - dat += "Captured Soul: [A.name]
      " - dat += {"Summon Shade"} - dat += "
      " - dat += {" Close"} - user << browse(dat, "window=aicard") - onclose(user, "aicard") - return - - - - -/obj/item/device/soulstone/Topic(href, href_list) - var/mob/U = usr - if (!in_range(src, U)||U.machine!=src) - U << browse(null, "window=aicard") - U.unset_machine() - return - - add_fingerprint(U) - U.set_machine(src) - - switch(href_list["choice"])//Now we switch based on choice. - if ("Close") - U << browse(null, "window=aicard") - U.unset_machine() - return - - if ("Summon") - for(var/mob/living/simple_animal/shade/A in src) - A.status_flags &= ~GODMODE - A.canmove = 1 + return + add_logs(user, M, "captured [M.name]'s soul", object=src) + + transfer_soul("VICTIM", M, user) + return + +/*attack(mob/living/simple_animal/shade/M as mob, mob/user as mob)//APPARENTLY THEY NEED THEIR OWN SPECIAL SNOWFLAKE CODE IN THE LIVING ANIMAL DEFINES + if(!istype(M, /mob/living/simple_animal/shade))//If target is not a shade + return ..() + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") + + transfer_soul("SHADE", M, user) + return*/ +///////////////////Options for using captured souls/////////////////////////////////////// + +/obj/item/device/soulstone/attack_self(mob/user) + if (!in_range(src, user)) + return + user.set_machine(src) + var/dat = "Soul Stone
      " + for(var/mob/living/simple_animal/shade/A in src) + dat += "Captured Soul: [A.name]
      " + dat += {"Summon Shade"} + dat += "
      " + dat += {" Close"} + user << browse(dat, "window=aicard") + onclose(user, "aicard") + return + + + + +/obj/item/device/soulstone/Topic(href, href_list) + var/mob/U = usr + if (!in_range(src, U)||U.machine!=src) + U << browse(null, "window=aicard") + U.unset_machine() + return + + add_fingerprint(U) + U.set_machine(src) + + switch(href_list["choice"])//Now we switch based on choice. + if ("Close") + U << browse(null, "window=aicard") + U.unset_machine() + return + + if ("Summon") + for(var/mob/living/simple_animal/shade/A in src) + A.status_flags &= ~GODMODE + A.canmove = 1 to_chat(A, "You have been released from your prison, but you are still bound to [U.name]'s will. Help them suceed in their goals at all costs.") - A.loc = U.loc - A.cancel_camera() - src.icon_state = "soulstone" - - attack_self(U) - -/obj/item/device/soulstone/cultify() - return - -///////////////////////////Transferring to constructs///////////////////////////////////////////////////// -/obj/structure/constructshell - name = "empty shell" - icon = 'icons/obj/wizard.dmi' - icon_state = "construct" - desc = "A wicked machine used by those skilled in magical arts. It is inactive." - flags = FPRINT - -/obj/structure/constructshell/cultify() - return - -/obj/structure/constructshell/cult - icon_state = "construct-cult" - desc = "This eerie contraption looks like it would come alive if supplied with a missing ingredient." - -/obj/structure/constructshell/attackby(obj/item/O as obj, mob/user as mob) - if(istype(O, /obj/item/device/soulstone)) - O.transfer_soul("CONSTRUCT",src,user) - - -////////////////////////////Proc for moving soul in and out off stone////////////////////////////////////// - - -/obj/item/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob) - var/deleteafter = 0 - switch(choice) - if("VICTIM") - var/mob/living/carbon/human/T = target - var/obj/item/device/soulstone/C = src - - if(istype(ticker.mode, /datum/game_mode/cult)) - var/datum/game_mode/cult/mode_ticker = ticker.mode - if(T.mind && (mode_ticker.sacrifice_target == T.mind)) + A.loc = U.loc + A.cancel_camera() + src.icon_state = "soulstone" + + attack_self(U) + +/obj/item/device/soulstone/cultify() + return + +///////////////////////////Transferring to constructs///////////////////////////////////////////////////// +/obj/structure/constructshell + name = "empty shell" + icon = 'icons/obj/wizard.dmi' + icon_state = "construct" + desc = "A wicked machine used by those skilled in magical arts. It is inactive." + flags = FPRINT + +/obj/structure/constructshell/cultify() + return + +/obj/structure/constructshell/cult + icon_state = "construct-cult" + desc = "This eerie contraption looks like it would come alive if supplied with a missing ingredient." + +/obj/structure/constructshell/attackby(obj/item/O as obj, mob/user as mob) + if(istype(O, /obj/item/device/soulstone)) + O.transfer_soul("CONSTRUCT",src,user) + + +////////////////////////////Proc for moving soul in and out off stone////////////////////////////////////// + + +/obj/item/proc/transfer_soul(var/choice as text, var/target, var/mob/U as mob) + var/deleteafter = 0 + switch(choice) + if("VICTIM") + var/mob/living/carbon/human/T = target + var/obj/item/device/soulstone/C = src + + if(istype(ticker.mode, /datum/game_mode/cult)) + var/datum/game_mode/cult/mode_ticker = ticker.mode + if(T.mind && (mode_ticker.sacrifice_target == T.mind)) to_chat(U, "The soul stone is unable to rip this soul. Such a powerful soul, it must be coveted by some powerful being.") - return - - if(C.imprinted != "empty") + return + + if(C.imprinted != "empty") to_chat(U, "Capture failed!: The soul stone has already been imprinted with [C.imprinted]'s mind!") - else - if (T.stat == CONSCIOUS) + else + if (T.stat == CONSCIOUS) to_chat(U, "Capture failed!: Kill or maim the victim first!") - else if(T.isInCrit() || T.stat == DEAD) - if(T.client == null) + else if(T.isInCrit() || T.stat == DEAD) + if(T.client == null) to_chat(U, "Capture failed!: The soul has already fled it's mortal frame.") - else - if(C.contents.len) + else + if(C.contents.len) to_chat(U, "Capture failed!: The soul stone is full! Use or free an existing soul to make room.") - else - for(var/obj/item/W in T) - T.drop_from_inventory(W) - new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton - T.invisibility = 101 - var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = T - flick("dust-h", animation) - animation.master = null - qdel(animation) - var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade( T.loc ) - S.loc = C //put shade in stone - S.status_flags |= GODMODE //So they won't die inside the stone somehow - S.canmove = 0//Can't move out of the soul stone - S.name = "Shade of [T.real_name]" - S.real_name = "Shade of [T.real_name]" - if (T.client) - T.client.mob = S - S.cancel_camera() - C.icon_state = "soulstone2" - C.name = "Soul Stone: [S.real_name]" + else + for(var/obj/item/W in T) + T.drop_from_inventory(W) + new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton + T.invisibility = 101 + var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = T + flick("dust-h", animation) + animation.master = null + qdel(animation) + var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade( T.loc ) + S.loc = C //put shade in stone + S.status_flags |= GODMODE //So they won't die inside the stone somehow + S.canmove = 0//Can't move out of the soul stone + S.name = "Shade of [T.real_name]" + S.real_name = "Shade of [T.real_name]" + if (T.client) + T.client.mob = S + S.cancel_camera() + C.icon_state = "soulstone2" + C.name = "Soul Stone: [S.real_name]" to_chat(S, "Your soul has been captured! You are now bound to [U.name]'s will, help them suceed in their goals at all costs.") to_chat(U, "Capture successful!: [T.real_name]'s soul has been ripped from their body and stored within the soul stone.") to_chat(U, "The soulstone has been imprinted with [S.real_name]'s mind, it will no longer react to other souls.") - C.imprinted = "[S.name]" - var/ref = "\ref[U.mind]" - var/list/necromancers - if(!(U.mind in ticker.mode.necromancer)) - ticker.mode:necromancer[ref] = list() - necromancers = ticker.mode:necromancer[ref] - necromancers.Add(S.mind) - ticker.mode:necromancer[ref] = necromancers - ticker.mode.update_necro_icons_added(U.mind) - ticker.mode.update_necro_icons_added(S.mind) - ticker.mode.risen.Add(S.mind) - qdel (T) - T = null - if("SHADE") - var/mob/living/simple_animal/shade/T = target - var/obj/item/device/soulstone/C = src - if (T.stat == DEAD) + C.imprinted = "[S.name]" + var/ref = "\ref[U.mind]" + var/list/necromancers + if(!(U.mind in ticker.mode.necromancer)) + ticker.mode:necromancer[ref] = list() + necromancers = ticker.mode:necromancer[ref] + necromancers.Add(S.mind) + ticker.mode:necromancer[ref] = necromancers + ticker.mode.update_necro_icons_added(U.mind) + ticker.mode.update_necro_icons_added(S.mind) + ticker.mode.risen.Add(S.mind) + qdel (T) + T = null + if("SHADE") + var/mob/living/simple_animal/shade/T = target + var/obj/item/device/soulstone/C = src + if (T.stat == DEAD) to_chat(U, "Capture failed!: The shade has already been banished!") - else - if(C.contents.len) + else + if(C.contents.len) to_chat(U, "Capture failed!: The soul stone is full! Use or free an existing soul to make room.") - else - if(T.name != C.imprinted) + else + if(T.name != C.imprinted) to_chat(U, "Capture failed!: The soul stone has already been imprinted with [C.imprinted]'s mind!") - else - T.loc = C //put shade in stone - T.status_flags |= GODMODE - T.canmove = 0 - T.health = T.maxHealth - C.icon_state = "soulstone2" + else + T.loc = C //put shade in stone + T.status_flags |= GODMODE + T.canmove = 0 + T.health = T.maxHealth + C.icon_state = "soulstone2" to_chat(T, "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form") to_chat(U, "Capture successful!: [T.name]'s has been recaptured and stored within the soul stone.") - if("CONSTRUCT") - var/obj/structure/constructshell/T = target - var/obj/item/device/soulstone/C = src - var/mob/living/simple_animal/shade/A = locate() in C - var/mob/living/simple_animal/construct/Z - if(A) - var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") - ticker.mode.update_necro_icons_removed(A.mind) - switch(construct_class) - if("Juggernaut") - Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) - qdel(T) + if("CONSTRUCT") + var/obj/structure/constructshell/T = target + var/obj/item/device/soulstone/C = src + var/mob/living/simple_animal/shade/A = locate() in C + var/mob/living/simple_animal/construct/Z + if(A) + var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") + ticker.mode.update_necro_icons_removed(A.mind) + switch(construct_class) + if("Juggernaut") + Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) + Z.key = A.key + if(iscultist(U)) + if(ticker.mode.name == "cult") + ticker.mode:add_cultist(Z.mind) + else + ticker.mode.cult+=Z.mind + ticker.mode.update_cult_icons_added(Z.mind) + qdel(T) to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike.") to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - deleteafter = 1 - - if("Wraith") - Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) - qdel(T) + Z.cancel_camera() + deleteafter = 1 + + if("Wraith") + Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc)) + Z.key = A.key + if(iscultist(U)) + if(ticker.mode.name == "cult") + ticker.mode:add_cultist(Z.mind) + else + ticker.mode.cult+=Z.mind + ticker.mode.update_cult_icons_added(Z.mind) + qdel(T) to_chat(Z, "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.") to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - deleteafter = 1 - - if("Artificer") - Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) - qdel(T) + Z.cancel_camera() + deleteafter = 1 + + if("Artificer") + Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc)) + Z.key = A.key + if(iscultist(U)) + if(ticker.mode.name == "cult") + ticker.mode:add_cultist(Z.mind) + else + ticker.mode.cult+=Z.mind + ticker.mode.update_cult_icons_added(Z.mind) + qdel(T) to_chat(Z, "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone).") to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - deleteafter = 1 - if(Z && Z.mind && !iscultist(Z)) - var/ref = "\ref[U.mind]" - var/list/necromancers - if(!(U.mind in ticker.mode.necromancer)) - ticker.mode:necromancer[ref] = list() - necromancers = ticker.mode:necromancer[ref] - necromancers.Add(Z.mind) - ticker.mode:necromancer[ref] = necromancers - ticker.mode.update_necro_icons_added(U.mind) - ticker.mode.update_necro_icons_added(Z.mind) - ticker.mode.risen.Add(Z.mind) - else + Z.cancel_camera() + deleteafter = 1 + if(Z && Z.mind && !iscultist(Z)) + var/ref = "\ref[U.mind]" + var/list/necromancers + if(!(U.mind in ticker.mode.necromancer)) + ticker.mode:necromancer[ref] = list() + necromancers = ticker.mode:necromancer[ref] + necromancers.Add(Z.mind) + ticker.mode:necromancer[ref] = necromancers + ticker.mode.update_necro_icons_added(U.mind) + ticker.mode.update_necro_icons_added(Z.mind) + ticker.mode.risen.Add(Z.mind) + else to_chat(U, "Creation failed!: The soul stone is empty! Go kill someone!") - ticker.mode.update_all_necro_icons() - if(deleteafter) - for(var/atom/A in src)//we get rid of the empty shade once we've transferred its mind to the construct, so it isn't dropped on the floor when the soulstone is destroyed. - qdel(A) - qdel(src) - return + ticker.mode.update_all_necro_icons() + if(deleteafter) + for(var/atom/A in src)//we get rid of the empty shade once we've transferred its mind to the construct, so it isn't dropped on the floor when the soulstone is destroyed. + qdel(A) + qdel(src) + return diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index fc9c220122f..6ffa5183c16 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -1,582 +1,582 @@ -/obj/item/weapon/spellbook - name = "spell book" - desc = "The legendary book of spells of the wizard." - icon = 'icons/obj/library.dmi' - icon_state ="spellbook" - throw_speed = 1 - throw_range = 5 - w_class = 1.0 - flags = FPRINT - var/uses = 5 - var/temp = null - var/max_uses = 5 - var/op = 1 - -/obj/item/weapon/spellbook/attackby(obj/item/O as obj, mob/user as mob) - if(istype(O, /obj/item/weapon/antag_spawner/contract)) - var/obj/item/weapon/antag_spawner/contract/contract = O - if(contract.used) - to_chat(user, "The contract has been used, you can't get your points back now.") - else - to_chat(user, "You feed the contract back into the spellbook, refunding your points.") - src.max_uses++ - src.uses++ - qdel (O) - O = null - -/obj/item/weapon/spellbook/attack_self(mob/user = usr) - if(!user) - return - user.set_machine(src) - var/dat - if(temp) - dat = "[temp]

      Clear" - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\wizard\spellbook.dm:22: dat = "The Book of Spells:
      " - dat = {"The Book of Spells:
      - Spells left to memorize: [uses]
      -
      - Memorize which spell:
      - The number after the spell name is the cooldown time.
      - [(Holiday == "Christmas" && universe.name == "Normal") ? "Become Santa Claus (One time use, uses three points, global spell)
      Guess which station's on the naughty list?
      " : ""] - Magic Missile (10)
      - This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.
      - Fireball (10)
      - This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you.
      - Lightning (20)
      - Become Zeus and throw lightning at your foes, once you've charged the spell focus it upon any being to unleash electric fury. Upgrading this will cause your lightning to arc.
      - Disable Technology (60)
      - This spell disables all weapons, cameras and most other technology in range.
      - Smoke (10)
      - This spell spawns a cloud of choking smoke at your location and does not require wizard garb.
      - Blind (30)
      - This spell temporarly blinds a single person and does not require wizard garb.
      - Subjugation (30)
      - This spell temporarily subjugates a target's mind and does not require wizard garb.
      - Mind Transfer (60)
      - This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process.
      - Forcewall (10)
      - This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb.
      - Blink (2)
      - This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience.
      - Teleport (60)
      - This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable.
      - Mutate (60)
      - This spell causes you to turn into a hulk and gain telekinesis for a short while.
      - Ethereal Jaunt (60)
      - This spell creates your ethereal form, temporarily making you invisible and able to pass through walls.
      - Time Stop (90)
      - Stop the flow of time for all beings but yourself in a large radius.
      - Knock (10)
      - This spell opens nearby doors and does not require wizard garb.
      - Curse of the Horseman (15)
      - This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require wizard garb.
      - The French Curse (30)
      - This spell silences sombody adjacent to you, and curses them with an unremovable Mime costume. It does not require robes to cast.
      - The Clown Curse (30)
      - This spell turns an adjacent target into a miserable clown. This spell does not require robes to cast.
      - Shoe Snatching Charm (15)
      - This spell will remove your victim's shoes and materialize them in your hands. This spell does not require robes to cast.
      - Summon Robes (50)
      - This spell will allow you to summon a new set of robes. Useful for stealthy wizards. This spell (quite obviously) does not require robes to cast.
      - Flesh to Stone (60)
      - This spell will curse a person to immediately turn into an unmoving statue. The effect will eventually wear off if the statue is not destroyed.
      - Butt-Bot's Revenge (50)
      - Summon the power of the butt gods to remove the anus of your enemy.
      - [!ticker.mode.rage ? "Summon Guns (One time use, global spell)
      Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!
      " : ""] - Summon Chariot (1/1)
      - Summon the most badass ride in all of wizardry.
      - Remove Clothes Requirement Warning: this takes away 2 spell choices.
      -
      - Artefacts:
      - Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.
      - It is recommended that only experienced wizards attempt to wield such artefacts.
      -
      - Staff of Change
      - An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself.
      -
      - Mental Focus
      - An artefact that channels the will of the user into destructive bolts of force.
      -
      - Six Soul Stone Shards and the spell Artificer
      - Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot.
      -
      - Mastercrafted Armor Set
      - An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space.
      -
      - Staff of Animation
      - An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines.
      -
      - Staff of Necromancy
      - An arcane staff capable of summoning undying minions from the corpses of your enemies. This magic doesn't affect machines.
      -
      - Contract of Apprenticeship
      - A magical contract binding an apprentice wizard to your service, using it will summon them to your side.
      -
      - Scrying Orb
      - An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision.
      -
      "} - // END AUTOFIX - if(op) - dat += "Re-memorize Spells
      " - user << browse(dat, "window=radio") - onclose(user, "radio") - return - -/obj/item/weapon/spellbook/Topic(href, href_list) - ..() - var/mob/living/carbon/human/H = usr - - if(H.stat || H.restrained()) - return - if(!istype(H, /mob/living/carbon/human)) - return 1 - - if(H.mind.special_role == "apprentice") - temp = "If you got caught sneaking a peak from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not." - return - - if(loc == H || (in_range(src, H) && istype(loc, /turf))) - H.set_machine(src) - if(href_list["spell_choice"]) - if(href_list["spell_choice"] == "rememorize") - var/area/wizard_station/A = locate() - if(usr in A.contents) - uses = max_uses - H.spellremove(usr) - temp = "All spells have been removed. You may now memorize a new set of spells." - feedback_add_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - else - temp = "You may only re-memorize spells whilst located inside the wizard sanctuary." - else if(uses >= 1 && max_uses >=1) - if(href_list["spell_choice"] == "noclothes") - if(uses < 2) - return - uses-- - /* - */ - var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", lightning = "Lightning", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", subjugation = "Subjugation", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", frenchcurse = "The French Curse", summonguns = "Summon Guns", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", noclothes = "No Clothes",fleshtostone = "Flesh to Stone", arsenath = "Butt-Bot's Revenge", timestop = "Time Stop",) - var/already_knows = 0 - for(var/spell/aspell in H.spell_list) - if(available_spells[href_list["spell_choice"]] == initial(aspell.name)) - already_knows = 1 - if(!aspell.can_improve()) - temp = "This spell cannot be improved further." - uses++ - break - else - if(aspell.can_improve("speed") && aspell.can_improve("power")) - var/choice = alert(usr, "Do you want to upgrade this spell's speed or power?", "Select Upgrade", "Speed", "Power", "Cancel") - switch(choice) - if("Speed") - temp = aspell.quicken_spell() - if("Power") - temp = aspell.empower_spell() - else - uses++ - break - else if (aspell.can_improve("speed")) - temp = aspell.quicken_spell() - else if (aspell.can_improve("power")) - temp = aspell.empower_spell() - /* - */ - if(!already_knows) - switch(href_list["spell_choice"]) - if("becomesanta") - var/obj/item/clothing/santahat = new /obj/item/clothing/head/helmet/space/santahat - santahat.canremove = 0 - var/obj/item/clothing/santasuit = new /obj/item/clothing/suit/space/santa - santasuit.canremove = 0 - var/obj/item/weapon/storage/backpack/santabag = new /obj/item/weapon/storage/backpack/santabag - santabag.canremove = 0 - to_chat(world,'sound/misc/santa.ogg') - SetUniversalState(/datum/universal_state/christmas) - if(H.head) - H.drop_from_inventory(H.head) - H.equip_to_slot(santahat,slot_head) - if(H.back) - H.drop_from_inventory(H.back) - if(H.wear_suit) - H.drop_from_inventory(H.wear_suit) - H.equip_to_slot(santabag,slot_back) - H.equip_to_slot(santasuit,slot_wear_suit) - H.real_name = pick("Santa Claus","Jolly St. Nick","Sandy Claws","Sinterklaas","Father Christmas","Kris Kringle") - H.nutrition += 1000 - temp = "Let's come to town." - uses -= 2 - add_spell(new/spell/noclothes,H) - add_spell(new/spell/aoe_turf/conjure/snowmobile,H) - add_spell(new/spell/targeted/wrapping_paper,H) - add_spell(new/spell/aoe_turf/conjure/gingerbreadman,H) - add_spell(new/spell/targeted/flesh_to_coal,H) - if("noclothes") - feedback_add_details("wizard_spell_learned","NC") - add_spell(new/spell/noclothes,H) - temp = "This teaches you how to use your spells without your magical garb, truely you are the wizardest." - uses-- - if("magicmissile") - feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/projectile/magic_missile,H) - temp = "You have learned magic missile." - if("fireball") - feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/projectile/dumbfire/fireball,H) - temp = "You have learned fireball." - if("lightning") - feedback_add_details("wizard_spell_learned","LS") - add_spell(new/spell/lightning,H) - temp = "You have learned lightning." - if("timestop") - feedback_add_details("wizard_spell_learned","MS") - add_spell(new/spell/aoe_turf/fall,H) - temp = "You have learned time stop." - /*if("disintegrate") - if(!ticker.mode.rage) - feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/disintegrate,H) - temp = "You have learned disintegrate." - */ - if("disabletech") - feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/aoe_turf/disable_tech,H) - temp = "You have learned disable technology." - if("smoke") - feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/aoe_turf/smoke,H) - temp = "You have learned smoke." - if("blind") - feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/genetic/blind,H) - temp = "You have learned blind." - if("subjugation") - feedback_add_details("wizard_spell_learned","SJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/subjugation,H) - temp = "You have learned subjugate." - if("mindswap") - feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/mind_transfer,H) - temp = "You have learned mindswap." - if("forcewall") - feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/aoe_turf/conjure/forcewall,H) - temp = "You have learned forcewall." - if("blink") - feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/aoe_turf/blink,H) - temp = "You have learned blink." - if("teleport") - feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/area_teleport,H) - temp = "You have learned teleport." - if("mutate") - feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/genetic/mutate,H) - temp = "You have learned mutate." - if("etherealjaunt") - feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/ethereal_jaunt,H) - temp = "You have learned ethereal jaunt." - if("knock") - feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/aoe_turf/knock,H) - temp = "You have learned knock." - if("horseman") - feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/equip_item/horsemask,H) - temp = "You have learned curse of the horseman." - if("frenchcurse") - feedback_add_details("wizard_spell_learned","FC") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/equip_item/frenchcurse,H) - temp = "You have learned the french curse." - if("clowncurse") - feedback_add_details("wizard_spell_learned","CC") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/equip_item/clowncurse,H) - temp = "You have learned the clown curse." - if("shoesnatch") - feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/shoesnatch,H) - temp = "You have learned the shoe snatching charm." - if("robesummon") - feedback_add_details("wizard_spell_learned", "RS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/equip_item/robesummon,H) - temp = "you have learned summon robes." - if("fleshtostone") - feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/flesh_to_stone,H) - temp = "You have learned flesh to stone." - if("arsenath") - feedback_add_details("wizard_spell_learned","AN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/targeted/buttbots_revenge,H) - temp = "You have learned butt-bot's revenge." - if("summonguns") - if(!ticker.mode.rage) - feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.rightandwrong(0) - max_uses-- - temp = "You have cast summon guns." - else - log_admin("[usr]([usr.key]) used an href to try and summon guns during ragin mages.") - uses++ - if("summonmagic") - feedback_add_details("wizard_spell_learned","SU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.rightandwrong(1) - max_uses-- - temp = "You have cast summon magic." - if("staffchange") - feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff(get_turf(H)) - temp = "You have purchased a staff of change." - max_uses-- - if("mentalfocus") - feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff/focus(get_turf(H)) - temp = "An artefact that channels the will of the user into destructive bolts of force." - max_uses-- - if("soulstone") - feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H)) - add_spell(new/spell/aoe_turf/conjure/construct,H) - temp = "You have purchased a belt full of soulstones and have learned the artificer spell." - max_uses-- - if("armor") - feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/clothing/shoes/sandal(get_turf(H)) //In case they've lost them. - new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit - new /obj/item/clothing/suit/space/rig/wizard(get_turf(H)) - new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(H)) - temp = "You have purchased a suit of wizard armor." - max_uses-- - if("staffanimation") - feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff/animate(get_turf(H)) - temp = "You have purchased a staff of animation." - max_uses-- - if("staffnecro") - feedback_add_details("wizard_spell_learned","SN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/staff/necro(get_turf(H)) - temp = "You have purchased a staff of necromancy." - max_uses-- - if("contract") - feedback_add_details("wizard_spell_learned","CT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/antag_spawner/contract(get_turf(H)) - temp = "You have purchased a contract of apprenticeship." - max_uses-- - if("scrying") - feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/scrying(get_turf(H)) - if (!(M_XRAY in H.mutations)) - H.mutations.Add(M_XRAY) - H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) - H.see_in_dark = 8 - H.see_invisible = SEE_INVISIBLE_LEVEL_TWO - to_chat(H, "The walls suddenly disappear.") - temp = "You have purchased a scrying orb, and gained x-ray vision." - max_uses-- - if("chariot") - feedback_add_details("wizard_spell_learned","WM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - add_spell(new/spell/aoe_turf/conjure/pontiac,H) - temp = "This spell summons a glorious, flaming chariot that can move in space and through walls. It also has an extremely long cooldown." - else - if(href_list["temp"]) - temp = null - attack_self() - - return - -//Single Use Spellbooks// -/obj/item/weapon/spellbook/proc/add_spell(var/spell/spell_to_add,var/mob/user) - if(user.mind) - if(!user.mind.wizard_spells) - user.mind.wizard_spells = list() - user.mind.wizard_spells += spell_to_add - user.add_spell(spell_to_add) - -/obj/item/weapon/spellbook/oneuse - var/spell = /spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic - var/spellname = "sandbox" - var/used = 0 - name = "spellbook of " - uses = 1 - max_uses = 1 - desc = "This template spellbook was never meant for the eyes of man..." - -/obj/item/weapon/spellbook/oneuse/New() - ..() - name += spellname - -/obj/item/weapon/spellbook/oneuse/attack_self(mob/user as mob) - var/spell/S = new spell(user) - for(var/spell/knownspell in user.spell_list) - if(knownspell.type == S.type) - if(user.mind) - if(user.mind.special_role == "apprentice" || user.mind.special_role == "Wizard") - to_chat(user, "You're already far more versed in this spell than this flimsy how-to book can provide.") - else - to_chat(user, "You've already read this one.") - return - if(used) - recoil(user) - else - user.add_spell(S) - to_chat(user, "you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!") - user.attack_log += text("\[[time_stamp()]\] [user.real_name] ([user.ckey]) learned the spell [spellname] ([S]).") - onlearned(user) - -/obj/item/weapon/spellbook/oneuse/proc/recoil(mob/user as mob) - user.visible_message("[src] glows in a black light!") - -/obj/item/weapon/spellbook/oneuse/proc/onlearned(mob/user as mob) - used = 1 - user.visible_message("[src] glows dark for a second!") - -/obj/item/weapon/spellbook/oneuse/attackby() - return - -/obj/item/weapon/spellbook/oneuse/fireball - spell = /spell/targeted/projectile/dumbfire/fireball - spellname = "fireball" - icon_state ="bookfireball" - desc = "This book feels warm to the touch." - -/obj/item/weapon/spellbook/oneuse/fireball/recoil(mob/user as mob) - ..() - explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2) - qdel(src) - -/obj/item/weapon/spellbook/oneuse/smoke - spell = /spell/aoe_turf/smoke - spellname = "smoke" - icon_state ="booksmoke" - desc = "This book is overflowing with the dank arts." - -/obj/item/weapon/spellbook/oneuse/smoke/recoil(mob/user as mob) - ..() - to_chat(user, "Your stomach rumbles...") - if(user.nutrition) - user.nutrition -= 200 - if(user.nutrition <= 0) - user.nutrition = 0 - -/obj/item/weapon/spellbook/oneuse/blind - spell = /spell/targeted/genetic/blind - spellname = "blind" - icon_state ="bookblind" - desc = "This book looks blurry, no matter how you look at it." - -/obj/item/weapon/spellbook/oneuse/blind/recoil(mob/user as mob) - ..() - to_chat(user, "You go blind!") - user.eye_blind = 10 - -/obj/item/weapon/spellbook/oneuse/mindswap - spell = /spell/targeted/mind_transfer - spellname = "mindswap" - icon_state ="bookmindswap" - desc = "This book's cover is pristine, though its pages look ragged and torn." - var/mob/stored_swap = null //Used in used book recoils to store an identity for mindswaps - -/obj/item/weapon/spellbook/oneuse/mindswap/onlearned() - spellname = pick("fireball","smoke","blind","forcewall","knock","horses","charge") - icon_state = "book[spellname]" - name = "spellbook of [spellname]" //Note, desc doesn't change by design - ..() - -/obj/item/weapon/spellbook/oneuse/mindswap/recoil(mob/user as mob) - ..() - if(stored_swap in dead_mob_list) - stored_swap = null - if(!stored_swap) - stored_swap = user - to_chat(user, "For a moment you feel like you don't even know who you are anymore.") - return - if(stored_swap == user) - to_chat(user, "You stare at the book some more, but there doesn't seem to be anything else to learn...") - return - - if(user.mind.special_verbs.len) - for(var/V in user.mind.special_verbs) - user.verbs -= V - - if(stored_swap.mind.special_verbs.len) - for(var/V in stored_swap.mind.special_verbs) - stored_swap.verbs -= V - - var/mob/dead/observer/ghost = stored_swap.ghostize(0) - ghost.spell_list = stored_swap.spell_list - - user.mind.transfer_to(stored_swap) - stored_swap.spell_list = user.spell_list - - if(stored_swap.mind.special_verbs.len) - for(var/V in user.mind.special_verbs) - user.verbs += V - - ghost.mind.transfer_to(user) - user.key = ghost.key - user.spell_list = ghost.spell_list - - if(user.mind.special_verbs.len) - for(var/V in user.mind.special_verbs) - user.verbs += V - - to_chat(stored_swap, "You're suddenly somewhere else... and someone else?!") - to_chat(user, "Suddenly you're staring at [src] again... where are you, who are you?!") - stored_swap = null - -/obj/item/weapon/spellbook/oneuse/forcewall - spell = /spell/aoe_turf/conjure/forcewall - spellname = "forcewall" - icon_state ="bookforcewall" - desc = "This book has a dedication to mimes everywhere inside the front cover." - -/obj/item/weapon/spellbook/oneuse/forcewall/recoil(mob/user as mob) - ..() - to_chat(user, "You suddenly feel very solid!") - var/obj/structure/closet/statue/S = new /obj/structure/closet/statue(user.loc, user) - S.timer = 30 - user.drop_item() - - -/obj/item/weapon/spellbook/oneuse/knock - spell = /spell/aoe_turf/knock - spellname = "knock" - icon_state ="bookknock" - desc = "This book is hard to hold closed properly." - -/obj/item/weapon/spellbook/oneuse/knock/recoil(mob/user as mob) - ..() - to_chat(user, "You're knocked down!") - user.Weaken(20) - -/obj/item/weapon/spellbook/oneuse/horsemask - spell = /spell/targeted/equip_item/horsemask - spellname = "horses" - icon_state ="bookhorses" - desc = "This book is more horse than your mind has room for." - -/obj/item/weapon/spellbook/oneuse/horsemask/recoil(mob/living/carbon/user as mob) - if(istype(user, /mob/living/carbon/human)) - to_chat(user, "HOR-SIE HAS RISEN") - 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 - user.drop_from_inventory(user.wear_mask) - user.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1) - qdel(src) - else - to_chat(user, "I say thee neigh") - -/obj/item/weapon/spellbook/oneuse/charge - spell = /spell/aoe_turf/charge - spellname = "charging" - icon_state ="bookcharge" - desc = "This book is made of 100% post-consumer wizard." - -/obj/item/weapon/spellbook/oneuse/charge/recoil(mob/user as mob) - ..() - to_chat(user, "[src] suddenly feels very warm!") - empulse(src, 1, 1) +/obj/item/weapon/spellbook + name = "spell book" + desc = "The legendary book of spells of the wizard." + icon = 'icons/obj/library.dmi' + icon_state ="spellbook" + throw_speed = 1 + throw_range = 5 + w_class = 1.0 + flags = FPRINT + var/uses = 5 + var/temp = null + var/max_uses = 5 + var/op = 1 + +/obj/item/weapon/spellbook/attackby(obj/item/O as obj, mob/user as mob) + if(istype(O, /obj/item/weapon/antag_spawner/contract)) + var/obj/item/weapon/antag_spawner/contract/contract = O + if(contract.used) + to_chat(user, "The contract has been used, you can't get your points back now.") + else + to_chat(user, "You feed the contract back into the spellbook, refunding your points.") + src.max_uses++ + src.uses++ + qdel (O) + O = null + +/obj/item/weapon/spellbook/attack_self(mob/user = usr) + if(!user) + return + user.set_machine(src) + var/dat + if(temp) + dat = "[temp]

      Clear" + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\gamemodes\wizard\spellbook.dm:22: dat = "The Book of Spells:
      " + dat = {"The Book of Spells:
      + Spells left to memorize: [uses]
      +
      + Memorize which spell:
      + The number after the spell name is the cooldown time.
      + [(Holiday == "Christmas" && universe.name == "Normal") ? "Become Santa Claus (One time use, uses three points, global spell)
      Guess which station's on the naughty list?
      " : ""] + Magic Missile (10)
      + This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.
      + Fireball (10)
      + This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you.
      + Lightning (20)
      + Become Zeus and throw lightning at your foes, once you've charged the spell focus it upon any being to unleash electric fury. Upgrading this will cause your lightning to arc.
      + Disable Technology (60)
      + This spell disables all weapons, cameras and most other technology in range.
      + Smoke (10)
      + This spell spawns a cloud of choking smoke at your location and does not require wizard garb.
      + Blind (30)
      + This spell temporarly blinds a single person and does not require wizard garb.
      + Subjugation (30)
      + This spell temporarily subjugates a target's mind and does not require wizard garb.
      + Mind Transfer (60)
      + This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process.
      + Forcewall (10)
      + This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb.
      + Blink (2)
      + This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience.
      + Teleport (60)
      + This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable.
      + Mutate (60)
      + This spell causes you to turn into a hulk and gain telekinesis for a short while.
      + Ethereal Jaunt (60)
      + This spell creates your ethereal form, temporarily making you invisible and able to pass through walls.
      + Time Stop (90)
      + Stop the flow of time for all beings but yourself in a large radius.
      + Knock (10)
      + This spell opens nearby doors and does not require wizard garb.
      + Curse of the Horseman (15)
      + This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require wizard garb.
      + The French Curse (30)
      + This spell silences sombody adjacent to you, and curses them with an unremovable Mime costume. It does not require robes to cast.
      + The Clown Curse (30)
      + This spell turns an adjacent target into a miserable clown. This spell does not require robes to cast.
      + Shoe Snatching Charm (15)
      + This spell will remove your victim's shoes and materialize them in your hands. This spell does not require robes to cast.
      + Summon Robes (50)
      + This spell will allow you to summon a new set of robes. Useful for stealthy wizards. This spell (quite obviously) does not require robes to cast.
      + Flesh to Stone (60)
      + This spell will curse a person to immediately turn into an unmoving statue. The effect will eventually wear off if the statue is not destroyed.
      + Butt-Bot's Revenge (50)
      + Summon the power of the butt gods to remove the anus of your enemy.
      + [!ticker.mode.rage ? "Summon Guns (One time use, global spell)
      Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!
      " : ""] + Summon Chariot (1/1)
      + Summon the most badass ride in all of wizardry.
      + Remove Clothes Requirement Warning: this takes away 2 spell choices.
      +
      + Artefacts:
      + Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.
      + It is recommended that only experienced wizards attempt to wield such artefacts.
      +
      + Staff of Change
      + An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself.
      +
      + Mental Focus
      + An artefact that channels the will of the user into destructive bolts of force.
      +
      + Six Soul Stone Shards and the spell Artificer
      + Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot.
      +
      + Mastercrafted Armor Set
      + An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space.
      +
      + Staff of Animation
      + An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines.
      +
      + Staff of Necromancy
      + An arcane staff capable of summoning undying minions from the corpses of your enemies. This magic doesn't affect machines.
      +
      + Contract of Apprenticeship
      + A magical contract binding an apprentice wizard to your service, using it will summon them to your side.
      +
      + Scrying Orb
      + An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision.
      +
      "} + // END AUTOFIX + if(op) + dat += "Re-memorize Spells
      " + user << browse(dat, "window=radio") + onclose(user, "radio") + return + +/obj/item/weapon/spellbook/Topic(href, href_list) + ..() + var/mob/living/carbon/human/H = usr + + if(H.stat || H.restrained()) + return + if(!istype(H, /mob/living/carbon/human)) + return 1 + + if(H.mind.special_role == "apprentice") + temp = "If you got caught sneaking a peak from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not." + return + + if(loc == H || (in_range(src, H) && istype(loc, /turf))) + H.set_machine(src) + if(href_list["spell_choice"]) + if(href_list["spell_choice"] == "rememorize") + var/area/wizard_station/A = locate() + if(usr in A.contents) + uses = max_uses + H.spellremove(usr) + temp = "All spells have been removed. You may now memorize a new set of spells." + feedback_add_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + else + temp = "You may only re-memorize spells whilst located inside the wizard sanctuary." + else if(uses >= 1 && max_uses >=1) + if(href_list["spell_choice"] == "noclothes") + if(uses < 2) + return + uses-- + /* + */ + var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", lightning = "Lightning", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", subjugation = "Subjugation", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", frenchcurse = "The French Curse", summonguns = "Summon Guns", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", noclothes = "No Clothes",fleshtostone = "Flesh to Stone", arsenath = "Butt-Bot's Revenge", timestop = "Time Stop",) + var/already_knows = 0 + for(var/spell/aspell in H.spell_list) + if(available_spells[href_list["spell_choice"]] == initial(aspell.name)) + already_knows = 1 + if(!aspell.can_improve()) + temp = "This spell cannot be improved further." + uses++ + break + else + if(aspell.can_improve("speed") && aspell.can_improve("power")) + var/choice = alert(usr, "Do you want to upgrade this spell's speed or power?", "Select Upgrade", "Speed", "Power", "Cancel") + switch(choice) + if("Speed") + temp = aspell.quicken_spell() + if("Power") + temp = aspell.empower_spell() + else + uses++ + break + else if (aspell.can_improve("speed")) + temp = aspell.quicken_spell() + else if (aspell.can_improve("power")) + temp = aspell.empower_spell() + /* + */ + if(!already_knows) + switch(href_list["spell_choice"]) + if("becomesanta") + var/obj/item/clothing/santahat = new /obj/item/clothing/head/helmet/space/santahat + santahat.canremove = 0 + var/obj/item/clothing/santasuit = new /obj/item/clothing/suit/space/santa + santasuit.canremove = 0 + var/obj/item/weapon/storage/backpack/santabag = new /obj/item/weapon/storage/backpack/santabag + santabag.canremove = 0 + to_chat(world,'sound/misc/santa.ogg') + SetUniversalState(/datum/universal_state/christmas) + if(H.head) + H.drop_from_inventory(H.head) + H.equip_to_slot(santahat,slot_head) + if(H.back) + H.drop_from_inventory(H.back) + if(H.wear_suit) + H.drop_from_inventory(H.wear_suit) + H.equip_to_slot(santabag,slot_back) + H.equip_to_slot(santasuit,slot_wear_suit) + H.real_name = pick("Santa Claus","Jolly St. Nick","Sandy Claws","Sinterklaas","Father Christmas","Kris Kringle") + H.nutrition += 1000 + temp = "Let's come to town." + uses -= 2 + add_spell(new/spell/noclothes,H) + add_spell(new/spell/aoe_turf/conjure/snowmobile,H) + add_spell(new/spell/targeted/wrapping_paper,H) + add_spell(new/spell/aoe_turf/conjure/gingerbreadman,H) + add_spell(new/spell/targeted/flesh_to_coal,H) + if("noclothes") + feedback_add_details("wizard_spell_learned","NC") + add_spell(new/spell/noclothes,H) + temp = "This teaches you how to use your spells without your magical garb, truely you are the wizardest." + uses-- + if("magicmissile") + feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/projectile/magic_missile,H) + temp = "You have learned magic missile." + if("fireball") + feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/projectile/dumbfire/fireball,H) + temp = "You have learned fireball." + if("lightning") + feedback_add_details("wizard_spell_learned","LS") + add_spell(new/spell/lightning,H) + temp = "You have learned lightning." + if("timestop") + feedback_add_details("wizard_spell_learned","MS") + add_spell(new/spell/aoe_turf/fall,H) + temp = "You have learned time stop." + /*if("disintegrate") + if(!ticker.mode.rage) + feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/disintegrate,H) + temp = "You have learned disintegrate." + */ + if("disabletech") + feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/aoe_turf/disable_tech,H) + temp = "You have learned disable technology." + if("smoke") + feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/aoe_turf/smoke,H) + temp = "You have learned smoke." + if("blind") + feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/genetic/blind,H) + temp = "You have learned blind." + if("subjugation") + feedback_add_details("wizard_spell_learned","SJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/subjugation,H) + temp = "You have learned subjugate." + if("mindswap") + feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/mind_transfer,H) + temp = "You have learned mindswap." + if("forcewall") + feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/aoe_turf/conjure/forcewall,H) + temp = "You have learned forcewall." + if("blink") + feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/aoe_turf/blink,H) + temp = "You have learned blink." + if("teleport") + feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/area_teleport,H) + temp = "You have learned teleport." + if("mutate") + feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/genetic/mutate,H) + temp = "You have learned mutate." + if("etherealjaunt") + feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/ethereal_jaunt,H) + temp = "You have learned ethereal jaunt." + if("knock") + feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/aoe_turf/knock,H) + temp = "You have learned knock." + if("horseman") + feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/equip_item/horsemask,H) + temp = "You have learned curse of the horseman." + if("frenchcurse") + feedback_add_details("wizard_spell_learned","FC") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/equip_item/frenchcurse,H) + temp = "You have learned the french curse." + if("clowncurse") + feedback_add_details("wizard_spell_learned","CC") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/equip_item/clowncurse,H) + temp = "You have learned the clown curse." + if("shoesnatch") + feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/shoesnatch,H) + temp = "You have learned the shoe snatching charm." + if("robesummon") + feedback_add_details("wizard_spell_learned", "RS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/equip_item/robesummon,H) + temp = "you have learned summon robes." + if("fleshtostone") + feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/flesh_to_stone,H) + temp = "You have learned flesh to stone." + if("arsenath") + feedback_add_details("wizard_spell_learned","AN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/targeted/buttbots_revenge,H) + temp = "You have learned butt-bot's revenge." + if("summonguns") + if(!ticker.mode.rage) + feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.rightandwrong(0) + max_uses-- + temp = "You have cast summon guns." + else + log_admin("[usr]([usr.key]) used an href to try and summon guns during ragin mages.") + uses++ + if("summonmagic") + feedback_add_details("wizard_spell_learned","SU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.rightandwrong(1) + max_uses-- + temp = "You have cast summon magic." + if("staffchange") + feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/gun/energy/staff(get_turf(H)) + temp = "You have purchased a staff of change." + max_uses-- + if("mentalfocus") + feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/gun/energy/staff/focus(get_turf(H)) + temp = "An artefact that channels the will of the user into destructive bolts of force." + max_uses-- + if("soulstone") + feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H)) + add_spell(new/spell/aoe_turf/conjure/construct,H) + temp = "You have purchased a belt full of soulstones and have learned the artificer spell." + max_uses-- + if("armor") + feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/clothing/shoes/sandal(get_turf(H)) //In case they've lost them. + new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit + new /obj/item/clothing/suit/space/rig/wizard(get_turf(H)) + new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(H)) + temp = "You have purchased a suit of wizard armor." + max_uses-- + if("staffanimation") + feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/gun/energy/staff/animate(get_turf(H)) + temp = "You have purchased a staff of animation." + max_uses-- + if("staffnecro") + feedback_add_details("wizard_spell_learned","SN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/staff/necro(get_turf(H)) + temp = "You have purchased a staff of necromancy." + max_uses-- + if("contract") + feedback_add_details("wizard_spell_learned","CT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/antag_spawner/contract(get_turf(H)) + temp = "You have purchased a contract of apprenticeship." + max_uses-- + if("scrying") + feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + new /obj/item/weapon/scrying(get_turf(H)) + if (!(M_XRAY in H.mutations)) + H.mutations.Add(M_XRAY) + H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + H.see_in_dark = 8 + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + to_chat(H, "The walls suddenly disappear.") + temp = "You have purchased a scrying orb, and gained x-ray vision." + max_uses-- + if("chariot") + feedback_add_details("wizard_spell_learned","WM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + add_spell(new/spell/aoe_turf/conjure/pontiac,H) + temp = "This spell summons a glorious, flaming chariot that can move in space and through walls. It also has an extremely long cooldown." + else + if(href_list["temp"]) + temp = null + attack_self() + + return + +//Single Use Spellbooks// +/obj/item/weapon/spellbook/proc/add_spell(var/spell/spell_to_add,var/mob/user) + if(user.mind) + if(!user.mind.wizard_spells) + user.mind.wizard_spells = list() + user.mind.wizard_spells += spell_to_add + user.add_spell(spell_to_add) + +/obj/item/weapon/spellbook/oneuse + var/spell = /spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic + var/spellname = "sandbox" + var/used = 0 + name = "spellbook of " + uses = 1 + max_uses = 1 + desc = "This template spellbook was never meant for the eyes of man..." + +/obj/item/weapon/spellbook/oneuse/New() + ..() + name += spellname + +/obj/item/weapon/spellbook/oneuse/attack_self(mob/user as mob) + var/spell/S = new spell(user) + for(var/spell/knownspell in user.spell_list) + if(knownspell.type == S.type) + if(user.mind) + if(user.mind.special_role == "apprentice" || user.mind.special_role == "Wizard") + to_chat(user, "You're already far more versed in this spell than this flimsy how-to book can provide.") + else + to_chat(user, "You've already read this one.") + return + if(used) + recoil(user) + else + user.add_spell(S) + to_chat(user, "you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!") + user.attack_log += text("\[[time_stamp()]\] [user.real_name] ([user.ckey]) learned the spell [spellname] ([S]).") + onlearned(user) + +/obj/item/weapon/spellbook/oneuse/proc/recoil(mob/user as mob) + user.visible_message("[src] glows in a black light!") + +/obj/item/weapon/spellbook/oneuse/proc/onlearned(mob/user as mob) + used = 1 + user.visible_message("[src] glows dark for a second!") + +/obj/item/weapon/spellbook/oneuse/attackby() + return + +/obj/item/weapon/spellbook/oneuse/fireball + spell = /spell/targeted/projectile/dumbfire/fireball + spellname = "fireball" + icon_state ="bookfireball" + desc = "This book feels warm to the touch." + +/obj/item/weapon/spellbook/oneuse/fireball/recoil(mob/user as mob) + ..() + explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2) + qdel(src) + +/obj/item/weapon/spellbook/oneuse/smoke + spell = /spell/aoe_turf/smoke + spellname = "smoke" + icon_state ="booksmoke" + desc = "This book is overflowing with the dank arts." + +/obj/item/weapon/spellbook/oneuse/smoke/recoil(mob/user as mob) + ..() + to_chat(user, "Your stomach rumbles...") + if(user.nutrition) + user.nutrition -= 200 + if(user.nutrition <= 0) + user.nutrition = 0 + +/obj/item/weapon/spellbook/oneuse/blind + spell = /spell/targeted/genetic/blind + spellname = "blind" + icon_state ="bookblind" + desc = "This book looks blurry, no matter how you look at it." + +/obj/item/weapon/spellbook/oneuse/blind/recoil(mob/user as mob) + ..() + to_chat(user, "You go blind!") + user.eye_blind = 10 + +/obj/item/weapon/spellbook/oneuse/mindswap + spell = /spell/targeted/mind_transfer + spellname = "mindswap" + icon_state ="bookmindswap" + desc = "This book's cover is pristine, though its pages look ragged and torn." + var/mob/stored_swap = null //Used in used book recoils to store an identity for mindswaps + +/obj/item/weapon/spellbook/oneuse/mindswap/onlearned() + spellname = pick("fireball","smoke","blind","forcewall","knock","horses","charge") + icon_state = "book[spellname]" + name = "spellbook of [spellname]" //Note, desc doesn't change by design + ..() + +/obj/item/weapon/spellbook/oneuse/mindswap/recoil(mob/user as mob) + ..() + if(stored_swap in dead_mob_list) + stored_swap = null + if(!stored_swap) + stored_swap = user + to_chat(user, "For a moment you feel like you don't even know who you are anymore.") + return + if(stored_swap == user) + to_chat(user, "You stare at the book some more, but there doesn't seem to be anything else to learn...") + return + + if(user.mind.special_verbs.len) + for(var/V in user.mind.special_verbs) + user.verbs -= V + + if(stored_swap.mind.special_verbs.len) + for(var/V in stored_swap.mind.special_verbs) + stored_swap.verbs -= V + + var/mob/dead/observer/ghost = stored_swap.ghostize(0) + ghost.spell_list = stored_swap.spell_list + + user.mind.transfer_to(stored_swap) + stored_swap.spell_list = user.spell_list + + if(stored_swap.mind.special_verbs.len) + for(var/V in user.mind.special_verbs) + user.verbs += V + + ghost.mind.transfer_to(user) + user.key = ghost.key + user.spell_list = ghost.spell_list + + if(user.mind.special_verbs.len) + for(var/V in user.mind.special_verbs) + user.verbs += V + + to_chat(stored_swap, "You're suddenly somewhere else... and someone else?!") + to_chat(user, "Suddenly you're staring at [src] again... where are you, who are you?!") + stored_swap = null + +/obj/item/weapon/spellbook/oneuse/forcewall + spell = /spell/aoe_turf/conjure/forcewall + spellname = "forcewall" + icon_state ="bookforcewall" + desc = "This book has a dedication to mimes everywhere inside the front cover." + +/obj/item/weapon/spellbook/oneuse/forcewall/recoil(mob/user as mob) + ..() + to_chat(user, "You suddenly feel very solid!") + var/obj/structure/closet/statue/S = new /obj/structure/closet/statue(user.loc, user) + S.timer = 30 + user.drop_item() + + +/obj/item/weapon/spellbook/oneuse/knock + spell = /spell/aoe_turf/knock + spellname = "knock" + icon_state ="bookknock" + desc = "This book is hard to hold closed properly." + +/obj/item/weapon/spellbook/oneuse/knock/recoil(mob/user as mob) + ..() + to_chat(user, "You're knocked down!") + user.Weaken(20) + +/obj/item/weapon/spellbook/oneuse/horsemask + spell = /spell/targeted/equip_item/horsemask + spellname = "horses" + icon_state ="bookhorses" + desc = "This book is more horse than your mind has room for." + +/obj/item/weapon/spellbook/oneuse/horsemask/recoil(mob/living/carbon/user as mob) + if(istype(user, /mob/living/carbon/human)) + to_chat(user, "HOR-SIE HAS RISEN") + 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 + user.drop_from_inventory(user.wear_mask) + user.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1) + qdel(src) + else + to_chat(user, "I say thee neigh") + +/obj/item/weapon/spellbook/oneuse/charge + spell = /spell/aoe_turf/charge + spellname = "charging" + icon_state ="bookcharge" + desc = "This book is made of 100% post-consumer wizard." + +/obj/item/weapon/spellbook/oneuse/charge/recoil(mob/user as mob) + ..() + to_chat(user, "[src] suddenly feels very warm!") + empulse(src, 1, 1) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 82c0f357e9b..41696edbdfc 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -1,404 +1,404 @@ -/*/proc/iswizard(mob/living/M as mob) - return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.wizards)*/ //See _macros.dm - -/datum/game_mode - var/list/datum/mind/wizards = list() - -/datum/game_mode/wizard - name = "wizard" - config_tag = "wizard" - required_players = 2 - required_players_secret = 10 - required_enemies = 1 - recommended_enemies = 1 - rage = 0 - - uplink_welcome = "Wizardly Uplink Console:" - uplink_uses = 10 - - var/finished = 0 - - var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) - var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - - -/datum/game_mode/wizard/announce() +/*/proc/iswizard(mob/living/M as mob) + return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.wizards)*/ //See _macros.dm + +/datum/game_mode + var/list/datum/mind/wizards = list() + +/datum/game_mode/wizard + name = "wizard" + config_tag = "wizard" + required_players = 2 + required_players_secret = 10 + required_enemies = 1 + recommended_enemies = 1 + rage = 0 + + uplink_welcome = "Wizardly Uplink Console:" + uplink_uses = 10 + + var/finished = 0 + + var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) + var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) + + +/datum/game_mode/wizard/announce() to_chat(world, "The current game mode is - Wizard!") to_chat(world, "There is a SPACE WIZARD on the station. You can't let him achieve his objective!") - -/datum/game_mode/wizard/pre_setup() - var/list/datum/mind/possible_wizards = get_players_for_role(ROLE_WIZARD) - if(possible_wizards.len==0) - log_admin("Failed to set-up a round of wizard. Couldn't find any volunteers to be wizards.") - message_admins("Failed to set-up a round of wizard. Couldn't find any volunteers to be wizards.") - return 0 - var/datum/mind/wizard - while(possible_wizards.len) - wizard = pick(possible_wizards) - if(wizard.special_role || (mixed && (wizard in ticker.mode.modePlayer))) - possible_wizards -= wizard - wizard = null - continue - else - break - if(isnull(wizard)) - log_admin("COULD NOT MAKE A WIZARD, Mixed mode is [mixed ? "enabled" : "disabled"]") - message_admins("COULD NOT MAKE A WIZARD, Mixed mode is [mixed ? "enabled" : "disabled"]") - return 0 - wizards += wizard - modePlayer += wizard - if(mixed) - ticker.mode.modePlayer += wizards //merge into master antag list - ticker.mode.wizards += wizards - wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. - wizard.special_role = "Wizard" - wizard.original = wizard.current - if(wizardstart.len == 0) + +/datum/game_mode/wizard/pre_setup() + var/list/datum/mind/possible_wizards = get_players_for_role(ROLE_WIZARD) + if(possible_wizards.len==0) + log_admin("Failed to set-up a round of wizard. Couldn't find any volunteers to be wizards.") + message_admins("Failed to set-up a round of wizard. Couldn't find any volunteers to be wizards.") + return 0 + var/datum/mind/wizard + while(possible_wizards.len) + wizard = pick(possible_wizards) + if(wizard.special_role || (mixed && (wizard in ticker.mode.modePlayer))) + possible_wizards -= wizard + wizard = null + continue + else + break + if(isnull(wizard)) + log_admin("COULD NOT MAKE A WIZARD, Mixed mode is [mixed ? "enabled" : "disabled"]") + message_admins("COULD NOT MAKE A WIZARD, Mixed mode is [mixed ? "enabled" : "disabled"]") + return 0 + wizards += wizard + modePlayer += wizard + if(mixed) + ticker.mode.modePlayer += wizards //merge into master antag list + ticker.mode.wizards += wizards + wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. + wizard.special_role = "Wizard" + wizard.original = wizard.current + if(wizardstart.len == 0) to_chat(wizard.current, "A starting location for you could not be found, please report this bug!") - log_admin("Failed to set-up a round of wizard. Couldn't find any wizard spawn points.") - message_admins("Failed to set-up a round of wizard. Couldn't find any wizard spawn points.") - return 0 - - for(var/datum/mind/wwizard in wizards) - wwizard.current.loc = pick(wizardstart) - - log_admin("Starting a round of wizard with [wizards.len] wizards.") - message_admins("Starting a round of wizard with [wizards.len] wizards.") - return 1 - - -/datum/game_mode/wizard/post_setup() - for(var/datum/mind/wizard in wizards) - forge_wizard_objectives(wizard) - //learn_basic_spells(wizard.current) - equip_wizard(wizard.current) - name_wizard(wizard.current) - greet_wizard(wizard) - update_wizard_icons_added(wizard) - update_all_wizard_icons() - if(!mixed) - spawn (rand(waittime_l, waittime_h)) - if(!mixed) send_intercept() - ..() - return - - -/datum/game_mode/proc/forge_wizard_objectives(var/datum/mind/wizard) - switch(rand(1,100)) - if(1 to 30) - - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = wizard - kill_objective.find_target() - wizard.objectives += kill_objective - - if (!(locate(/datum/objective/escape) in wizard.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = wizard - wizard.objectives += escape_objective - if(31 to 60) - var/datum/objective/steal/steal_objective = new - steal_objective.owner = wizard - steal_objective.find_target() - wizard.objectives += steal_objective - - if (!(locate(/datum/objective/escape) in wizard.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = wizard - wizard.objectives += escape_objective - - if(61 to 100) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = wizard - kill_objective.find_target() - wizard.objectives += kill_objective - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = wizard - steal_objective.find_target() - wizard.objectives += steal_objective - - if (!(locate(/datum/objective/survive) in wizard.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = wizard - wizard.objectives += survive_objective - - else - if (!(locate(/datum/objective/hijack) in wizard.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = wizard - wizard.objectives += hijack_objective - return - - -/datum/game_mode/proc/name_wizard(mob/living/carbon/human/wizard_mob) - //Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting. - if(wizard_mob.species && wizard_mob.species.name != "Human") - wizard_mob.set_species("Human", 1) - var/wizard_name_first = pick(wizard_first) - var/wizard_name_second = pick(wizard_second) - var/randomname = "[wizard_name_first] [wizard_name_second]" - spawn(0) - var/newname = copytext(sanitize(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN) - - if (!newname) - newname = randomname - - wizard_mob.real_name = newname - wizard_mob.name = newname - if(wizard_mob.mind) - wizard_mob.mind.name = newname - return - - -/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1) - if (you_are) + log_admin("Failed to set-up a round of wizard. Couldn't find any wizard spawn points.") + message_admins("Failed to set-up a round of wizard. Couldn't find any wizard spawn points.") + return 0 + + for(var/datum/mind/wwizard in wizards) + wwizard.current.loc = pick(wizardstart) + + log_admin("Starting a round of wizard with [wizards.len] wizards.") + message_admins("Starting a round of wizard with [wizards.len] wizards.") + return 1 + + +/datum/game_mode/wizard/post_setup() + for(var/datum/mind/wizard in wizards) + forge_wizard_objectives(wizard) + //learn_basic_spells(wizard.current) + equip_wizard(wizard.current) + name_wizard(wizard.current) + greet_wizard(wizard) + update_wizard_icons_added(wizard) + update_all_wizard_icons() + if(!mixed) + spawn (rand(waittime_l, waittime_h)) + if(!mixed) send_intercept() + ..() + return + + +/datum/game_mode/proc/forge_wizard_objectives(var/datum/mind/wizard) + switch(rand(1,100)) + if(1 to 30) + + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = wizard + kill_objective.find_target() + wizard.objectives += kill_objective + + if (!(locate(/datum/objective/escape) in wizard.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = wizard + wizard.objectives += escape_objective + if(31 to 60) + var/datum/objective/steal/steal_objective = new + steal_objective.owner = wizard + steal_objective.find_target() + wizard.objectives += steal_objective + + if (!(locate(/datum/objective/escape) in wizard.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = wizard + wizard.objectives += escape_objective + + if(61 to 100) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = wizard + kill_objective.find_target() + wizard.objectives += kill_objective + + var/datum/objective/steal/steal_objective = new + steal_objective.owner = wizard + steal_objective.find_target() + wizard.objectives += steal_objective + + if (!(locate(/datum/objective/survive) in wizard.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = wizard + wizard.objectives += survive_objective + + else + if (!(locate(/datum/objective/hijack) in wizard.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = wizard + wizard.objectives += hijack_objective + return + + +/datum/game_mode/proc/name_wizard(mob/living/carbon/human/wizard_mob) + //Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting. + if(wizard_mob.species && wizard_mob.species.name != "Human") + wizard_mob.set_species("Human", 1) + var/wizard_name_first = pick(wizard_first) + var/wizard_name_second = pick(wizard_second) + var/randomname = "[wizard_name_first] [wizard_name_second]" + spawn(0) + var/newname = copytext(sanitize(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN) + + if (!newname) + newname = randomname + + wizard_mob.real_name = newname + wizard_mob.name = newname + if(wizard_mob.mind) + wizard_mob.mind.name = newname + return + + +/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1) + if (you_are) to_chat(wizard.current, "You are the Space Wizard!") to_chat(wizard.current, "The Space Wizards Federation has given you the following tasks:") - - var/obj_count = 1 - for(var/datum/objective/objective in wizard.objectives) + + var/obj_count = 1 + for(var/datum/objective/objective in wizard.objectives) to_chat(wizard.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - return - - -/*/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob) - if (!istype(wizard_mob)) - return - if(!config.feature_object_spell_system) - wizard_mob.verbs += /client/proc/jaunt - wizard_mob.mind.special_verbs += /client/proc/jaunt - else - wizard_mob.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(usr) -*/ - -/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob) - if (!istype(wizard_mob)) - return - - //So zards properly get their items when they are admin-made. - qdel(wizard_mob.wear_suit) - qdel(wizard_mob.head) - qdel(wizard_mob.shoes) - qdel(wizard_mob.r_hand) - qdel(wizard_mob.r_store) - qdel(wizard_mob.l_store) - - wizard_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(wizard_mob), slot_ears) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(wizard_mob), slot_w_uniform) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head) - if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back) - if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(wizard_mob), slot_back) - if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back) - wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack) -// wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/scrying_gem(wizard_mob), slot_l_store) For scrying gem. - wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store) - wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand) - - // For Vox and plasmadudes. - //wizard_mob.species.handle_post_spawn(wizard_mob) - + obj_count++ + return + + +/*/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob) + if (!istype(wizard_mob)) + return + if(!config.feature_object_spell_system) + wizard_mob.verbs += /client/proc/jaunt + wizard_mob.mind.special_verbs += /client/proc/jaunt + else + wizard_mob.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(usr) +*/ + +/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob) + if (!istype(wizard_mob)) + return + + //So zards properly get their items when they are admin-made. + qdel(wizard_mob.wear_suit) + qdel(wizard_mob.head) + qdel(wizard_mob.shoes) + qdel(wizard_mob.r_hand) + qdel(wizard_mob.r_store) + qdel(wizard_mob.l_store) + + wizard_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(wizard_mob), slot_ears) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(wizard_mob), slot_w_uniform) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head) + if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back) + if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(wizard_mob), slot_back) + if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back) + wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack) +// wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/scrying_gem(wizard_mob), slot_l_store) For scrying gem. + wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store) + wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand) + + // For Vox and plasmadudes. + //wizard_mob.species.handle_post_spawn(wizard_mob) + to_chat(wizard_mob, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.") to_chat(wizard_mob, "In your pockets you will find a teleport scroll. Use it as needed.") - wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") - wizard_mob.update_icons() - return 1 - - -/datum/game_mode/wizard/check_finished() - if(istype(ticker.mode, /datum/game_mode/mixed)) - mixed = 1 - if(config.continous_rounds || mixed) - return ..() - - var/wizards_alive = 0 - var/traitors_alive = 0 - for(var/datum/mind/wizard in wizards) - if(!istype(wizard.current,/mob/living/carbon)) - continue - if(wizard.current.stat==2) - continue - wizards_alive++ - - if(!wizards_alive) - for(var/datum/mind/traitor in traitors) - if(!istype(traitor.current,/mob/living/carbon)) - continue - if(traitor.current.stat==2) - continue - traitors_alive++ - - if (wizards_alive || traitors_alive || (rage && src:making_mage)) - return ..() - else - finished = 1 - return 1 - - - -/datum/game_mode/wizard/declare_completion(var/ragin = 0) - if(finished && !ragin) - feedback_set_details("round_end_result","loss - wizard killed") - completion_text += "
      The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_wizard() - var/text = "" - if(wizards.len) - var/icon/logo = icon('icons/mob/mob.dmi', "wizard-logo") - end_icons += logo - var/tempstate = end_icons.len - text += {"
      the wizards/witches were: "} - - for(var/datum/mind/wizard in wizards) - - if(wizard.current) - var/icon/flat = getFlatIcon(wizard.current, SOUTH, 1, 1) - end_icons += flat - tempstate = end_icons.len - text += {"
      [wizard.key] was [wizard.name] ("} - if(wizard.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(wizard.current.real_name != wizard.name) - text += " as [wizard.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") - end_icons += sprotch - tempstate = end_icons.len - text += {"
      [wizard.key] was [wizard.name] ("} - text += "body destroyed" - text += ")" - - var/count = 1 - var/wizardwin = 1 - for(var/datum/objective/objective in wizard.objectives) - if(objective.check_completion()) - text += "
      Objective #[count]: [objective.explanation_text] Success!" - feedback_add_details("wizard_objective","[objective.type]|SUCCESS") - else - text += "
      Objective #[count]: [objective.explanation_text] Fail." - feedback_add_details("wizard_objective","[objective.type]|FAIL") - wizardwin = 0 - count++ - - if(wizard.current && wizard.current.stat!=2 && wizardwin) - text += "
      The wizard was successful!" - feedback_add_details("wizard_success","SUCCESS") - else - text += "
      The wizard has failed!" - feedback_add_details("wizard_success","FAIL") - if(wizard.current && wizard.current.spell_list) - text += "
      [wizard.name] used the following spells: " - var/i = 1 - for(var/spell/S in wizard.current.spell_list) - var/icon/spellicon = icon('icons/mob/screen_spells.dmi', S.hud_state) - end_icons += spellicon - tempstate = end_icons.len - text += {"
      [S.name]"} - if(wizard.current.spell_list.len > i) - text += ", " - i++ - text += "
      " - text += "
      " - return text - -//OTHER PROCS - -//To batch-remove wizard spells. Linked to mind.dm. -/mob/proc/spellremove(var/mob/M as mob) - for(var/spell/spell_to_remove in src.spell_list) - remove_spell(spell_to_remove) - -// Does this clothing slot count as wizard garb? (Combines a few checks) -/proc/is_wiz_garb(var/obj/item/clothing/C) - return C && C.wizard_garb - -/*Checks if the wizard is wearing the proper attire. -Made a proc so this is not repeated 14 (or more) times.*/ -/mob/proc/wearing_wiz_garb() + wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") + wizard_mob.update_icons() + return 1 + + +/datum/game_mode/wizard/check_finished() + if(istype(ticker.mode, /datum/game_mode/mixed)) + mixed = 1 + if(config.continous_rounds || mixed) + return ..() + + var/wizards_alive = 0 + var/traitors_alive = 0 + for(var/datum/mind/wizard in wizards) + if(!istype(wizard.current,/mob/living/carbon)) + continue + if(wizard.current.stat==2) + continue + wizards_alive++ + + if(!wizards_alive) + for(var/datum/mind/traitor in traitors) + if(!istype(traitor.current,/mob/living/carbon)) + continue + if(traitor.current.stat==2) + continue + traitors_alive++ + + if (wizards_alive || traitors_alive || (rage && src:making_mage)) + return ..() + else + finished = 1 + return 1 + + + +/datum/game_mode/wizard/declare_completion(var/ragin = 0) + if(finished && !ragin) + feedback_set_details("round_end_result","loss - wizard killed") + completion_text += "
      The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" + ..() + return 1 + + +/datum/game_mode/proc/auto_declare_completion_wizard() + var/text = "" + if(wizards.len) + var/icon/logo = icon('icons/mob/mob.dmi', "wizard-logo") + end_icons += logo + var/tempstate = end_icons.len + text += {"
      the wizards/witches were: "} + + for(var/datum/mind/wizard in wizards) + + if(wizard.current) + var/icon/flat = getFlatIcon(wizard.current, SOUTH, 1, 1) + end_icons += flat + tempstate = end_icons.len + text += {"
      [wizard.key] was [wizard.name] ("} + if(wizard.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(wizard.current.real_name != wizard.name) + text += " as [wizard.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "floor1-old") + end_icons += sprotch + tempstate = end_icons.len + text += {"
      [wizard.key] was [wizard.name] ("} + text += "body destroyed" + text += ")" + + var/count = 1 + var/wizardwin = 1 + for(var/datum/objective/objective in wizard.objectives) + if(objective.check_completion()) + text += "
      Objective #[count]: [objective.explanation_text] Success!" + feedback_add_details("wizard_objective","[objective.type]|SUCCESS") + else + text += "
      Objective #[count]: [objective.explanation_text] Fail." + feedback_add_details("wizard_objective","[objective.type]|FAIL") + wizardwin = 0 + count++ + + if(wizard.current && wizard.current.stat!=2 && wizardwin) + text += "
      The wizard was successful!" + feedback_add_details("wizard_success","SUCCESS") + else + text += "
      The wizard has failed!" + feedback_add_details("wizard_success","FAIL") + if(wizard.current && wizard.current.spell_list) + text += "
      [wizard.name] used the following spells: " + var/i = 1 + for(var/spell/S in wizard.current.spell_list) + var/icon/spellicon = icon('icons/mob/screen_spells.dmi', S.hud_state) + end_icons += spellicon + tempstate = end_icons.len + text += {"
      [S.name]"} + if(wizard.current.spell_list.len > i) + text += ", " + i++ + text += "
      " + text += "
      " + return text + +//OTHER PROCS + +//To batch-remove wizard spells. Linked to mind.dm. +/mob/proc/spellremove(var/mob/M as mob) + for(var/spell/spell_to_remove in src.spell_list) + remove_spell(spell_to_remove) + +// Does this clothing slot count as wizard garb? (Combines a few checks) +/proc/is_wiz_garb(var/obj/item/clothing/C) + return C && C.wizard_garb + +/*Checks if the wizard is wearing the proper attire. +Made a proc so this is not repeated 14 (or more) times.*/ +/mob/proc/wearing_wiz_garb() to_chat(src, "Silly creature, you're not a human. Only humans can cast this spell.") - return 0 - -// Humans can wear clothes. -/mob/living/carbon/human/wearing_wiz_garb() - if(!is_wiz_garb(src.wear_suit)) + return 0 + +// Humans can wear clothes. +/mob/living/carbon/human/wearing_wiz_garb() + if(!is_wiz_garb(src.wear_suit)) to_chat(src, "I don't feel strong enough without my robe.") - return 0 - if(!is_wiz_garb(src.shoes)) + return 0 + if(!is_wiz_garb(src.shoes)) to_chat(src, "I don't feel strong enough without my sandals.") - return 0 - if(!is_wiz_garb(src.head)) + return 0 + if(!is_wiz_garb(src.head)) to_chat(src, "I don't feel strong enough without my hat.") - return 0 - return 1 - -// So can monkeys (FIXME) -/* -/mob/living/carbon/monkey/wearing_wiz_garb() - if(!is_wiz_garb(src.wear_suit)) + return 0 + return 1 + +// So can monkeys (FIXME) +/* +/mob/living/carbon/monkey/wearing_wiz_garb() + if(!is_wiz_garb(src.wear_suit)) to_chat(src, "I don't feel strong enough without my robe.") - return 0 - if(!is_wiz_garb(src.shoes)) + return 0 + if(!is_wiz_garb(src.shoes)) to_chat(src, "I don't feel strong enough without my sandals.") - return 0 - if(!is_wiz_garb(src.head)) + return 0 + if(!is_wiz_garb(src.head)) to_chat(src, "I don't feel strong enough without my hat.") - return 0 - return 1 -*/ - -/datum/game_mode/proc/update_all_wizard_icons() - spawn(0) - for(var/datum/mind/wizard_mind in wizards) - if(wizard_mind.current) - if(wizard_mind.current.client) - for(var/image/I in wizard_mind.current.client.images) - if(I.icon_state == "wizard") - wizard_mind.current.client.images -= I - - for(var/datum/mind/wizard_mind in wizards) - if(wizard_mind.current) - if(wizard_mind.current.client) - for(var/datum/mind/wizard_mind_1 in wizards) - if(wizard_mind_1.current) - var/imageloc = wizard_mind_1.current - if(istype(wizard_mind_1.current.loc,/obj/mecha)) - imageloc = wizard_mind_1.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "wizard", layer = 13) - wizard_mind.current.client.images += I - -/datum/game_mode/proc/update_wizard_icons_added(datum/mind/wizard_mind) - spawn(0) - if(wizard_mind.current) - if(wizard_mind.current.client) - var/imageloc = wizard_mind.current - if(istype(wizard_mind.current.loc,/obj/mecha)) - imageloc = wizard_mind.current.loc - var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "wizard", layer = 13) - wizard_mind.current.client.images += I - -/datum/game_mode/proc/update_wizard_icons_removed(datum/mind/wizard_mind) - spawn(0) - for(var/datum/mind/wizard in wizards) - if(wizard.current) - if(wizard.current.client) - for(var/image/I in wizard.current.client.images) - if(I.icon_state == "wizard" && ((I.loc == wizard_mind.current) || (I.loc == wizard_mind.current.loc))) - //del(I) - wizard.current.client.images -= I - - if(wizard_mind.current) - if(wizard_mind.current.client) - for(var/image/I in wizard_mind.current.client.images) - if(I.icon_state == "wizard") - //del(I) - wizard_mind.current.client.images -= I + return 0 + return 1 +*/ + +/datum/game_mode/proc/update_all_wizard_icons() + spawn(0) + for(var/datum/mind/wizard_mind in wizards) + if(wizard_mind.current) + if(wizard_mind.current.client) + for(var/image/I in wizard_mind.current.client.images) + if(I.icon_state == "wizard") + wizard_mind.current.client.images -= I + + for(var/datum/mind/wizard_mind in wizards) + if(wizard_mind.current) + if(wizard_mind.current.client) + for(var/datum/mind/wizard_mind_1 in wizards) + if(wizard_mind_1.current) + var/imageloc = wizard_mind_1.current + if(istype(wizard_mind_1.current.loc,/obj/mecha)) + imageloc = wizard_mind_1.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "wizard", layer = 13) + wizard_mind.current.client.images += I + +/datum/game_mode/proc/update_wizard_icons_added(datum/mind/wizard_mind) + spawn(0) + if(wizard_mind.current) + if(wizard_mind.current.client) + var/imageloc = wizard_mind.current + if(istype(wizard_mind.current.loc,/obj/mecha)) + imageloc = wizard_mind.current.loc + var/I = image('icons/mob/mob.dmi', loc = imageloc, icon_state = "wizard", layer = 13) + wizard_mind.current.client.images += I + +/datum/game_mode/proc/update_wizard_icons_removed(datum/mind/wizard_mind) + spawn(0) + for(var/datum/mind/wizard in wizards) + if(wizard.current) + if(wizard.current.client) + for(var/image/I in wizard.current.client.images) + if(I.icon_state == "wizard" && ((I.loc == wizard_mind.current) || (I.loc == wizard_mind.current.loc))) + //del(I) + wizard.current.client.images -= I + + if(wizard_mind.current) + if(wizard_mind.current.client) + for(var/image/I in wizard_mind.current.client.images) + if(I.icon_state == "wizard") + //del(I) + wizard_mind.current.client.images -= I diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 7cc2250cc36..82f9aa8c06f 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -1,492 +1,492 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/var/const/access_security = 1 // Security equipment -/var/const/access_brig = 2 // Brig timers and permabrig -/var/const/access_armory = 3 -/var/const/access_forensics_lockers= 4 -/var/const/access_medical = 5 -/var/const/access_morgue = 6 -/var/const/access_tox = 7 // Research and Development -/var/const/access_tox_storage = 8 // Toxins mixing and storage -/var/const/access_genetics = 9 -/var/const/access_engine = 10 // Power Engines -/var/const/access_engine_equip= 11 // Engineering Foyer -/var/const/access_maint_tunnels = 12 -/var/const/access_external_airlocks = 13 -/var/const/access_emergency_storage = 14 -/var/const/access_change_ids = 15 -/var/const/access_ai_upload = 16 -/var/const/access_teleporter = 17 -/var/const/access_eva = 18 -/var/const/access_heads = 19 -/var/const/access_captain = 20 -/var/const/access_all_personal_lockers = 21 -/var/const/access_chapel_office = 22 -/var/const/access_tech_storage = 23 -/var/const/access_atmospherics = 24 -/var/const/access_bar = 25 -/var/const/access_janitor = 26 -/var/const/access_crematorium = 27 -/var/const/access_kitchen = 28 -/var/const/access_robotics = 29 -/var/const/access_rd = 30 -/var/const/access_cargo = 31 // Cargo Bay -/var/const/access_construction = 32 // Vacant office, etc -/var/const/access_chemistry = 33 -/var/const/access_cargo_bot = 34 -/var/const/access_hydroponics = 35 -/var/const/access_manufacturing = 36 -/var/const/access_library = 37 -/var/const/access_lawyer = 38 -/var/const/access_virology = 39 -/var/const/access_cmo = 40 -/var/const/access_qm = 41 -/var/const/access_court = 42 -/var/const/access_clown = 43 -/var/const/access_mime = 44 -/var/const/access_surgery = 45 -/var/const/access_theatre = 46 -/var/const/access_research = 47 // Research Division hallway -/var/const/access_mining = 48 -/var/const/access_mining_office = 49 //not in use -/var/const/access_mailsorting = 50 // Cargo Office -/var/const/access_mint = 51 -/var/const/access_mint_vault = 52 -/var/const/access_heads_vault = 53 -/var/const/access_mining_station = 54 -/var/const/access_xenobiology = 55 -/var/const/access_ce = 56 -/var/const/access_hop = 57 -/var/const/access_hos = 58 -/var/const/access_RC_announce = 59 //Request console announcements -/var/const/access_keycard_auth = 60 //Used for events which require at least two people to confirm them -/var/const/access_tcomsat = 61 // has access to the entire telecomms satellite / machinery -/var/const/access_gateway = 62 -/var/const/access_sec_doors = 63 // Security front doors -/var/const/access_psychiatrist = 64 // Psychiatrist's office -/var/const/access_salvage_captain = 65 // Salvage ship captain's quarters -/var/const/access_weapons = 66 //Weapon authorization for secbots -/var/const/access_taxi = 67 // Taxi drivers - //BEGIN CENTCOM ACCESS - /*Should leave plenty of room if we need to add more access levels. -/var/const/Mostly for admin fun times.*/ -/var/const/access_cent_general = 101//General facilities. -/var/const/access_cent_thunder = 102//Thunderdome. -/var/const/access_cent_specops = 103//Death Commando. -/var/const/access_cent_medical = 104//Medical/Research -/var/const/access_cent_living = 105//Living quarters. -/var/const/access_cent_storage = 106//Generic storage areas. -/var/const/access_cent_teleporter = 107//Teleporter. -/var/const/access_cent_creed = 108//Creed's office/ID comp -/var/const/access_cent_captain = 109//Captain's office/ID comp/AI. -/var/const/access_cent_ert = 110//ERT. - - //The Syndicate -/var/const/access_syndicate = 150//General Syndicate Access - - //MONEY -/var/const/access_crate_cash = 200 - -// /VG/ SPECIFIC SHIT -/var/const/access_paramedic = 500 -/var/const/access_mechanic = 501 - -/obj/var/list/req_access = null -/obj/var/req_access_txt = "0" // A user must have ALL of these accesses to use the object -/obj/var/list/req_one_access = null -/obj/var/req_one_access_txt = "0" // If this list is populated, a user must have at least ONE of these accesses to use the object - -//returns 1 if this mob has sufficient access to use this object -/obj/proc/allowed(var/mob/M) - set_up_access() - if(!M || !istype(M)) - return 0 // I guess? This seems to happen when AIs use something. - if(M.hasFullAccess()) // AI, robots, adminghosts, etc. - return 1 - var/list/ACL = M.GetAccess() - return can_access(ACL,req_access,req_one_access) - -/obj/item/proc/GetAccess() - return list() - -/obj/item/proc/GetID() - return null - -/obj/proc/set_up_access() - //These generations have been moved out of /obj/New() because they were slowing down the creation of objects that never even used the access system. - if(!src.req_access) - src.req_access = list() - if(src.req_access_txt) - var/list/req_access_str = text2list(req_access_txt,";") - for(var/x in req_access_str) - var/n = text2num(x) - if(n) - req_access += n - - if(!src.req_one_access) - src.req_one_access = list() - if(src.req_one_access_txt) - var/list/req_one_access_str = text2list(req_one_access_txt,";") - for(var/x in req_one_access_str) - var/n = text2num(x) - if(n) - req_one_access += n - -/obj/proc/check_access(obj/item/I) - set_up_access() - var/list/ACL = list() - if(I) - ACL=I.GetAccess() - return can_access(ACL,req_access,req_one_access) - - -/obj/proc/check_access_list(var/list/L) - set_up_access() - if(!src.req_access && !src.req_one_access) return 1 - if(!istype(src.req_access, /list)) return 1 - if(!src.req_access.len && (!src.req_one_access || !src.req_one_access.len)) return 1 - if(!L) return 0 - if(!istype(L, /list)) return 0 - for(var/req in src.req_access) - if(!(req in L)) //doesn't have this access - return 0 - if(src.req_one_access && src.req_one_access.len) - for(var/req in src.req_one_access) - if(req in L) //has an access from the single access list - return 1 - return 0 - return 1 - -// /vg/ - Generic Access Checks. -// Allows more flexible access checks. -/proc/can_access(var/list/L, var/list/req_access=null,var/list/req_one_access=null) - // No perms set? He's in. - if(!req_access && !req_one_access) - return 1 - // Fucked permissions set? He's in. - if(!istype(req_access, /list)) - return 1 - // Blank permissions set? He's in. - if(!req_access.len && (!req_one_access || !req_one_access.len)) - return 1 - - // User doesn't have any accesses? Fuck off. - if(!L) return 0 - if(!istype(L, /list)) return 0 - - // Doesn't have a req_access - for(var/req in req_access) - if(!(req in L)) //doesn't have this access - return 0 - - // If he has at least one req_one access, he's in. - if(req_one_access && req_one_access.len) - for(var/req in req_one_access) - if(req in L) //has an access from the single access list - return 1 - return 0 - return 1 - -/proc/get_centcom_access(job) - switch(job) - if("VIP Guest") - return list(access_cent_general, access_cent_living) - if("Thunderdome Overseer") - return list(access_cent_general, access_cent_thunder) - if("Emergency Responder") - return (get_ert_access() | list(access_cent_general, access_cent_ert, access_cent_specops)) - if("Emergency Responders Leader") - return (get_ert_access() | list(access_cent_general, access_cent_ert, access_change_ids, access_heads, access_captain, access_cent_specops)) - if("Death Commando") - return (get_all_accesses() | list(access_cent_general, access_cent_specops)) - if("Creed Commander") - return (get_all_accesses() | list(access_cent_general, access_cent_specops, access_cent_ert, access_cent_creed)) - if("Supreme Commander") - return (get_all_accesses() | get_all_centcom_access())//Mr.Centcom gets station all access as well - -/proc/get_all_accesses() - return list(access_security, access_sec_doors, access_brig, access_armory, access_forensics_lockers, access_court, - access_medical, access_genetics, access_morgue, access_rd, - access_tox, access_tox_storage, access_chemistry, access_engine, access_engine_equip, access_maint_tunnels, - access_external_airlocks, access_change_ids, access_ai_upload, - access_teleporter, access_eva, access_heads, access_captain, access_all_personal_lockers, - access_tech_storage, access_chapel_office, access_atmospherics, access_kitchen, - access_bar, access_janitor, access_crematorium, access_robotics, access_cargo, access_construction, - access_hydroponics, access_library, access_lawyer, access_virology, access_psychiatrist, access_cmo, access_qm, access_clown, access_mime, access_surgery, - access_theatre, access_research, access_mining, access_mailsorting,access_weapons, - access_heads_vault, access_mining_station, access_xenobiology, access_ce, access_hop, access_hos, access_RC_announce, - access_keycard_auth, access_tcomsat, access_gateway, /*vg paramedic*/, access_paramedic, access_mechanic, access_taxi) - -/proc/get_absolutely_all_accesses() - return ((get_all_accesses() | get_all_centcom_access() | get_all_syndicate_access()) + access_salvage_captain) - -/proc/get_all_centcom_access() - return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_medical, access_cent_living, access_cent_storage, access_cent_teleporter, access_cent_creed, access_cent_captain) - -/proc/get_all_syndicate_access() - return list(access_syndicate) - -/proc/get_ert_access() - return list( - access_security, access_sec_doors, access_brig, access_armory, //sec - access_medical, access_genetics, access_surgery, access_paramedic, //med - access_atmospherics, access_engine, access_tech_storage, //engi - access_robotics, access_research, //sci - access_external_airlocks, access_teleporter, access_eva, //entering/leaving the station - access_maint_tunnels, - access_tcomsat, access_gateway, //why not - ) - -/proc/get_region_accesses(var/code) - switch(code) - if(0) - return get_all_accesses() - if(1) //security - return list(access_sec_doors, access_weapons, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos) - if(2) //medbay - return list(access_medical, access_genetics, access_morgue, access_chemistry, access_paramedic, access_virology, access_surgery, access_cmo) - if(3) //research - return list(access_research, access_tox, access_tox_storage, access_robotics, access_mechanic, access_xenobiology, access_rd) - if(4) //engineering and maintenance - return list(access_construction, access_maint_tunnels, access_engine, access_engine_equip, access_external_airlocks, access_tech_storage, access_mechanic, access_atmospherics, access_ce) - if(5) //command - return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_hop, access_captain) - if(6) //station general - return list(access_kitchen,access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_clown, access_mime) - if(7) //supply - return list(access_mailsorting, access_mining, access_mining_station, access_cargo, access_qm, access_taxi) - -/proc/get_region_accesses_name(var/code) - switch(code) - if(0) - return "All" - if(1) //security - return "Security" - if(2) //medbay - return "Medbay" - if(3) //research - return "Research" - if(4) //engineering and maintenance - return "Engineering" - if(5) //command - return "Command" - if(6) //station general - return "Station General" - if(7) //supply - return "Supply" - - -/proc/get_access_desc(A) - switch(A) - if(access_cargo) - return "Cargo Bay" - if(access_cargo_bot) - return "Cargo Bot Delivery" - if(access_security) - return "Security" - if(access_brig) - return "Holding Cells" - if(access_court) - return "Courtroom" - if(access_forensics_lockers) - return "Forensics" - if(access_medical) - return "Medical" - if(access_genetics) - return "Genetics Lab" - if(access_morgue) - return "Morgue" - if(access_tox) - return "R&D Lab" - if(access_tox_storage) - return "Toxins Lab" - if(access_chemistry) - return "Chemistry Lab" - if(access_rd) - return "Research Director" - if(access_bar) - return "Bar" - if(access_janitor) - return "Custodial Closet" - if(access_engine) - return "Engineering" - if(access_engine_equip) - return "Power Equipment" - if(access_maint_tunnels) - return "Maintenance" - if(access_external_airlocks) - return "External Airlocks" - if(access_emergency_storage) - return "Emergency Storage" - if(access_change_ids) - return "ID Computer" - if(access_ai_upload) - return "AI Upload" - if(access_teleporter) - return "Teleporter" - if(access_eva) - return "EVA" - if(access_heads) - return "Bridge" - if(access_captain) - return "Captain" - if(access_all_personal_lockers) - return "Personal Lockers" - if(access_chapel_office) - return "Chapel Office" - if(access_tech_storage) - return "Technical Storage" - if(access_atmospherics) - return "Atmospherics" - if(access_crematorium) - return "Crematorium" - if(access_armory) - return "Armory" - if(access_construction) - return "Construction Areas" - if(access_kitchen) - return "Kitchen" - if(access_hydroponics) - return "Hydroponics" - if(access_library) - return "Library" - if(access_lawyer) - return "Law Office" - if(access_robotics) - return "Robotics" - if(access_virology) - return "Virology" - if(access_psychiatrist) - return "Psychiatrist's Office" - if(access_cmo) - return "Chief Medical Officer" - if(access_qm) - return "Quartermaster" - if(access_clown) - return "HONK! Access" - if(access_mime) - return "Silent Access" - if(access_surgery) - return "Surgery" - if(access_theatre) - return "Theatre" - if(access_manufacturing) - return "Manufacturing" - if(access_research) - return "Science" - if(access_mining) - return "Mining" - if(access_mining_office) - return "Mining Office" - if(access_mailsorting) - return "Cargo Office" - if(access_mint) - return "Mint" - if(access_mint_vault) - return "Mint Vault" - if(access_heads_vault) - return "Main Vault" - if(access_mining_station) - return "Mining EVA" - if(access_xenobiology) - return "Xenobiology Lab" - if(access_hop) - return "Head of Personnel" - if(access_hos) - return "Head of Security" - if(access_ce) - return "Chief Engineer" - if(access_RC_announce) - return "RC Announcements" - if(access_keycard_auth) - return "Keycode Auth. Device" - if(access_tcomsat) - return "Telecommunications" - if(access_gateway) - return "Gateway" - if(access_sec_doors) - return "Brig" -// /vg/ shit - if(access_paramedic) - return "Paramedic Station" - if(access_weapons) - return "Weapon Permit" - if(access_taxi) - return "Taxi Shuttle" - if(access_mechanic) - return "Workshop" - - -/proc/get_centcom_access_desc(A) - switch(A) - if(access_cent_general) - return "Centcom Common Areas" - if(access_cent_thunder) - return "Thunderdome" - if(access_cent_storage) - return "Centcom Storage" - if(access_cent_living) - return "Centcom Living Areas" - if(access_cent_medical) - return "Centcom Medbay" - if(access_cent_teleporter) - return "Centcom Teleporter" - if(access_cent_specops) - return "Special Ops" - if(access_cent_ert) - return "Emergency Response Team" - if(access_cent_creed) - return "Creed Officer" - if(access_cent_captain) - return "Centcom Captain" - -// Cache - N3X -var/global/list/all_jobs -/proc/get_all_jobs() - // Have cache? Use cache. - if(all_jobs) - return all_jobs - - // Rebuild cache. - all_jobs=list() - for(var/jobtype in typesof(/datum/job) - /datum/job) - var/datum/job/jobdatum = new jobtype - if(jobdatum.info_flag & JINFO_SILICON) continue - all_jobs.Add(jobdatum.title) - return all_jobs - -/proc/get_all_centcom_jobs() - return list("VIP Guest","Custodian","Thunderdome Overseer","Intel Officer","Medical Officer","Death Commando","Research Officer","BlackOps Commander","Supreme Commander") - - -proc/FindNameFromID(var/mob/living/carbon/human/H) - ASSERT(istype(H)) - var/obj/item/weapon/card/id/C = H.get_active_hand() - if( istype(C) || istype(C, /obj/item/device/pda) ) - var/obj/item/weapon/card/id/ID = C - - if( istype(C, /obj/item/device/pda) ) - var/obj/item/device/pda/pda = C - ID = pda.id - if(!istype(ID)) - ID = null - - if(ID) - return ID.registered_name - - C = H.wear_id - - if( istype(C) || istype(C, /obj/item/device/pda) ) - var/obj/item/weapon/card/id/ID = C - - if( istype(C, /obj/item/device/pda) ) - var/obj/item/device/pda/pda = C - ID = pda.id - if(!istype(ID)) - ID = null - - if(ID) - return ID.registered_name - -proc/get_all_job_icons() //For all existing HUD icons - return get_all_jobs() + list("Prisoner") +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/var/const/access_security = 1 // Security equipment +/var/const/access_brig = 2 // Brig timers and permabrig +/var/const/access_armory = 3 +/var/const/access_forensics_lockers= 4 +/var/const/access_medical = 5 +/var/const/access_morgue = 6 +/var/const/access_tox = 7 // Research and Development +/var/const/access_tox_storage = 8 // Toxins mixing and storage +/var/const/access_genetics = 9 +/var/const/access_engine = 10 // Power Engines +/var/const/access_engine_equip= 11 // Engineering Foyer +/var/const/access_maint_tunnels = 12 +/var/const/access_external_airlocks = 13 +/var/const/access_emergency_storage = 14 +/var/const/access_change_ids = 15 +/var/const/access_ai_upload = 16 +/var/const/access_teleporter = 17 +/var/const/access_eva = 18 +/var/const/access_heads = 19 +/var/const/access_captain = 20 +/var/const/access_all_personal_lockers = 21 +/var/const/access_chapel_office = 22 +/var/const/access_tech_storage = 23 +/var/const/access_atmospherics = 24 +/var/const/access_bar = 25 +/var/const/access_janitor = 26 +/var/const/access_crematorium = 27 +/var/const/access_kitchen = 28 +/var/const/access_robotics = 29 +/var/const/access_rd = 30 +/var/const/access_cargo = 31 // Cargo Bay +/var/const/access_construction = 32 // Vacant office, etc +/var/const/access_chemistry = 33 +/var/const/access_cargo_bot = 34 +/var/const/access_hydroponics = 35 +/var/const/access_manufacturing = 36 +/var/const/access_library = 37 +/var/const/access_lawyer = 38 +/var/const/access_virology = 39 +/var/const/access_cmo = 40 +/var/const/access_qm = 41 +/var/const/access_court = 42 +/var/const/access_clown = 43 +/var/const/access_mime = 44 +/var/const/access_surgery = 45 +/var/const/access_theatre = 46 +/var/const/access_research = 47 // Research Division hallway +/var/const/access_mining = 48 +/var/const/access_mining_office = 49 //not in use +/var/const/access_mailsorting = 50 // Cargo Office +/var/const/access_mint = 51 +/var/const/access_mint_vault = 52 +/var/const/access_heads_vault = 53 +/var/const/access_mining_station = 54 +/var/const/access_xenobiology = 55 +/var/const/access_ce = 56 +/var/const/access_hop = 57 +/var/const/access_hos = 58 +/var/const/access_RC_announce = 59 //Request console announcements +/var/const/access_keycard_auth = 60 //Used for events which require at least two people to confirm them +/var/const/access_tcomsat = 61 // has access to the entire telecomms satellite / machinery +/var/const/access_gateway = 62 +/var/const/access_sec_doors = 63 // Security front doors +/var/const/access_psychiatrist = 64 // Psychiatrist's office +/var/const/access_salvage_captain = 65 // Salvage ship captain's quarters +/var/const/access_weapons = 66 //Weapon authorization for secbots +/var/const/access_taxi = 67 // Taxi drivers + //BEGIN CENTCOM ACCESS + /*Should leave plenty of room if we need to add more access levels. +/var/const/Mostly for admin fun times.*/ +/var/const/access_cent_general = 101//General facilities. +/var/const/access_cent_thunder = 102//Thunderdome. +/var/const/access_cent_specops = 103//Death Commando. +/var/const/access_cent_medical = 104//Medical/Research +/var/const/access_cent_living = 105//Living quarters. +/var/const/access_cent_storage = 106//Generic storage areas. +/var/const/access_cent_teleporter = 107//Teleporter. +/var/const/access_cent_creed = 108//Creed's office/ID comp +/var/const/access_cent_captain = 109//Captain's office/ID comp/AI. +/var/const/access_cent_ert = 110//ERT. + + //The Syndicate +/var/const/access_syndicate = 150//General Syndicate Access + + //MONEY +/var/const/access_crate_cash = 200 + +// /VG/ SPECIFIC SHIT +/var/const/access_paramedic = 500 +/var/const/access_mechanic = 501 + +/obj/var/list/req_access = null +/obj/var/req_access_txt = "0" // A user must have ALL of these accesses to use the object +/obj/var/list/req_one_access = null +/obj/var/req_one_access_txt = "0" // If this list is populated, a user must have at least ONE of these accesses to use the object + +//returns 1 if this mob has sufficient access to use this object +/obj/proc/allowed(var/mob/M) + set_up_access() + if(!M || !istype(M)) + return 0 // I guess? This seems to happen when AIs use something. + if(M.hasFullAccess()) // AI, robots, adminghosts, etc. + return 1 + var/list/ACL = M.GetAccess() + return can_access(ACL,req_access,req_one_access) + +/obj/item/proc/GetAccess() + return list() + +/obj/item/proc/GetID() + return null + +/obj/proc/set_up_access() + //These generations have been moved out of /obj/New() because they were slowing down the creation of objects that never even used the access system. + if(!src.req_access) + src.req_access = list() + if(src.req_access_txt) + var/list/req_access_str = text2list(req_access_txt,";") + for(var/x in req_access_str) + var/n = text2num(x) + if(n) + req_access += n + + if(!src.req_one_access) + src.req_one_access = list() + if(src.req_one_access_txt) + var/list/req_one_access_str = text2list(req_one_access_txt,";") + for(var/x in req_one_access_str) + var/n = text2num(x) + if(n) + req_one_access += n + +/obj/proc/check_access(obj/item/I) + set_up_access() + var/list/ACL = list() + if(I) + ACL=I.GetAccess() + return can_access(ACL,req_access,req_one_access) + + +/obj/proc/check_access_list(var/list/L) + set_up_access() + if(!src.req_access && !src.req_one_access) return 1 + if(!istype(src.req_access, /list)) return 1 + if(!src.req_access.len && (!src.req_one_access || !src.req_one_access.len)) return 1 + if(!L) return 0 + if(!istype(L, /list)) return 0 + for(var/req in src.req_access) + if(!(req in L)) //doesn't have this access + return 0 + if(src.req_one_access && src.req_one_access.len) + for(var/req in src.req_one_access) + if(req in L) //has an access from the single access list + return 1 + return 0 + return 1 + +// /vg/ - Generic Access Checks. +// Allows more flexible access checks. +/proc/can_access(var/list/L, var/list/req_access=null,var/list/req_one_access=null) + // No perms set? He's in. + if(!req_access && !req_one_access) + return 1 + // Fucked permissions set? He's in. + if(!istype(req_access, /list)) + return 1 + // Blank permissions set? He's in. + if(!req_access.len && (!req_one_access || !req_one_access.len)) + return 1 + + // User doesn't have any accesses? Fuck off. + if(!L) return 0 + if(!istype(L, /list)) return 0 + + // Doesn't have a req_access + for(var/req in req_access) + if(!(req in L)) //doesn't have this access + return 0 + + // If he has at least one req_one access, he's in. + if(req_one_access && req_one_access.len) + for(var/req in req_one_access) + if(req in L) //has an access from the single access list + return 1 + return 0 + return 1 + +/proc/get_centcom_access(job) + switch(job) + if("VIP Guest") + return list(access_cent_general, access_cent_living) + if("Thunderdome Overseer") + return list(access_cent_general, access_cent_thunder) + if("Emergency Responder") + return (get_ert_access() | list(access_cent_general, access_cent_ert, access_cent_specops)) + if("Emergency Responders Leader") + return (get_ert_access() | list(access_cent_general, access_cent_ert, access_change_ids, access_heads, access_captain, access_cent_specops)) + if("Death Commando") + return (get_all_accesses() | list(access_cent_general, access_cent_specops)) + if("Creed Commander") + return (get_all_accesses() | list(access_cent_general, access_cent_specops, access_cent_ert, access_cent_creed)) + if("Supreme Commander") + return (get_all_accesses() | get_all_centcom_access())//Mr.Centcom gets station all access as well + +/proc/get_all_accesses() + return list(access_security, access_sec_doors, access_brig, access_armory, access_forensics_lockers, access_court, + access_medical, access_genetics, access_morgue, access_rd, + access_tox, access_tox_storage, access_chemistry, access_engine, access_engine_equip, access_maint_tunnels, + access_external_airlocks, access_change_ids, access_ai_upload, + access_teleporter, access_eva, access_heads, access_captain, access_all_personal_lockers, + access_tech_storage, access_chapel_office, access_atmospherics, access_kitchen, + access_bar, access_janitor, access_crematorium, access_robotics, access_cargo, access_construction, + access_hydroponics, access_library, access_lawyer, access_virology, access_psychiatrist, access_cmo, access_qm, access_clown, access_mime, access_surgery, + access_theatre, access_research, access_mining, access_mailsorting,access_weapons, + access_heads_vault, access_mining_station, access_xenobiology, access_ce, access_hop, access_hos, access_RC_announce, + access_keycard_auth, access_tcomsat, access_gateway, /*vg paramedic*/, access_paramedic, access_mechanic, access_taxi) + +/proc/get_absolutely_all_accesses() + return ((get_all_accesses() | get_all_centcom_access() | get_all_syndicate_access()) + access_salvage_captain) + +/proc/get_all_centcom_access() + return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_medical, access_cent_living, access_cent_storage, access_cent_teleporter, access_cent_creed, access_cent_captain) + +/proc/get_all_syndicate_access() + return list(access_syndicate) + +/proc/get_ert_access() + return list( + access_security, access_sec_doors, access_brig, access_armory, //sec + access_medical, access_genetics, access_surgery, access_paramedic, //med + access_atmospherics, access_engine, access_tech_storage, //engi + access_robotics, access_research, //sci + access_external_airlocks, access_teleporter, access_eva, //entering/leaving the station + access_maint_tunnels, + access_tcomsat, access_gateway, //why not + ) + +/proc/get_region_accesses(var/code) + switch(code) + if(0) + return get_all_accesses() + if(1) //security + return list(access_sec_doors, access_weapons, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos) + if(2) //medbay + return list(access_medical, access_genetics, access_morgue, access_chemistry, access_paramedic, access_virology, access_surgery, access_cmo) + if(3) //research + return list(access_research, access_tox, access_tox_storage, access_robotics, access_mechanic, access_xenobiology, access_rd) + if(4) //engineering and maintenance + return list(access_construction, access_maint_tunnels, access_engine, access_engine_equip, access_external_airlocks, access_tech_storage, access_mechanic, access_atmospherics, access_ce) + if(5) //command + return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_hop, access_captain) + if(6) //station general + return list(access_kitchen,access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_clown, access_mime) + if(7) //supply + return list(access_mailsorting, access_mining, access_mining_station, access_cargo, access_qm, access_taxi) + +/proc/get_region_accesses_name(var/code) + switch(code) + if(0) + return "All" + if(1) //security + return "Security" + if(2) //medbay + return "Medbay" + if(3) //research + return "Research" + if(4) //engineering and maintenance + return "Engineering" + if(5) //command + return "Command" + if(6) //station general + return "Station General" + if(7) //supply + return "Supply" + + +/proc/get_access_desc(A) + switch(A) + if(access_cargo) + return "Cargo Bay" + if(access_cargo_bot) + return "Cargo Bot Delivery" + if(access_security) + return "Security" + if(access_brig) + return "Holding Cells" + if(access_court) + return "Courtroom" + if(access_forensics_lockers) + return "Forensics" + if(access_medical) + return "Medical" + if(access_genetics) + return "Genetics Lab" + if(access_morgue) + return "Morgue" + if(access_tox) + return "R&D Lab" + if(access_tox_storage) + return "Toxins Lab" + if(access_chemistry) + return "Chemistry Lab" + if(access_rd) + return "Research Director" + if(access_bar) + return "Bar" + if(access_janitor) + return "Custodial Closet" + if(access_engine) + return "Engineering" + if(access_engine_equip) + return "Power Equipment" + if(access_maint_tunnels) + return "Maintenance" + if(access_external_airlocks) + return "External Airlocks" + if(access_emergency_storage) + return "Emergency Storage" + if(access_change_ids) + return "ID Computer" + if(access_ai_upload) + return "AI Upload" + if(access_teleporter) + return "Teleporter" + if(access_eva) + return "EVA" + if(access_heads) + return "Bridge" + if(access_captain) + return "Captain" + if(access_all_personal_lockers) + return "Personal Lockers" + if(access_chapel_office) + return "Chapel Office" + if(access_tech_storage) + return "Technical Storage" + if(access_atmospherics) + return "Atmospherics" + if(access_crematorium) + return "Crematorium" + if(access_armory) + return "Armory" + if(access_construction) + return "Construction Areas" + if(access_kitchen) + return "Kitchen" + if(access_hydroponics) + return "Hydroponics" + if(access_library) + return "Library" + if(access_lawyer) + return "Law Office" + if(access_robotics) + return "Robotics" + if(access_virology) + return "Virology" + if(access_psychiatrist) + return "Psychiatrist's Office" + if(access_cmo) + return "Chief Medical Officer" + if(access_qm) + return "Quartermaster" + if(access_clown) + return "HONK! Access" + if(access_mime) + return "Silent Access" + if(access_surgery) + return "Surgery" + if(access_theatre) + return "Theatre" + if(access_manufacturing) + return "Manufacturing" + if(access_research) + return "Science" + if(access_mining) + return "Mining" + if(access_mining_office) + return "Mining Office" + if(access_mailsorting) + return "Cargo Office" + if(access_mint) + return "Mint" + if(access_mint_vault) + return "Mint Vault" + if(access_heads_vault) + return "Main Vault" + if(access_mining_station) + return "Mining EVA" + if(access_xenobiology) + return "Xenobiology Lab" + if(access_hop) + return "Head of Personnel" + if(access_hos) + return "Head of Security" + if(access_ce) + return "Chief Engineer" + if(access_RC_announce) + return "RC Announcements" + if(access_keycard_auth) + return "Keycode Auth. Device" + if(access_tcomsat) + return "Telecommunications" + if(access_gateway) + return "Gateway" + if(access_sec_doors) + return "Brig" +// /vg/ shit + if(access_paramedic) + return "Paramedic Station" + if(access_weapons) + return "Weapon Permit" + if(access_taxi) + return "Taxi Shuttle" + if(access_mechanic) + return "Workshop" + + +/proc/get_centcom_access_desc(A) + switch(A) + if(access_cent_general) + return "Centcom Common Areas" + if(access_cent_thunder) + return "Thunderdome" + if(access_cent_storage) + return "Centcom Storage" + if(access_cent_living) + return "Centcom Living Areas" + if(access_cent_medical) + return "Centcom Medbay" + if(access_cent_teleporter) + return "Centcom Teleporter" + if(access_cent_specops) + return "Special Ops" + if(access_cent_ert) + return "Emergency Response Team" + if(access_cent_creed) + return "Creed Officer" + if(access_cent_captain) + return "Centcom Captain" + +// Cache - N3X +var/global/list/all_jobs +/proc/get_all_jobs() + // Have cache? Use cache. + if(all_jobs) + return all_jobs + + // Rebuild cache. + all_jobs=list() + for(var/jobtype in typesof(/datum/job) - /datum/job) + var/datum/job/jobdatum = new jobtype + if(jobdatum.info_flag & JINFO_SILICON) continue + all_jobs.Add(jobdatum.title) + return all_jobs + +/proc/get_all_centcom_jobs() + return list("VIP Guest","Custodian","Thunderdome Overseer","Intel Officer","Medical Officer","Death Commando","Research Officer","BlackOps Commander","Supreme Commander") + + +proc/FindNameFromID(var/mob/living/carbon/human/H) + ASSERT(istype(H)) + var/obj/item/weapon/card/id/C = H.get_active_hand() + if( istype(C) || istype(C, /obj/item/device/pda) ) + var/obj/item/weapon/card/id/ID = C + + if( istype(C, /obj/item/device/pda) ) + var/obj/item/device/pda/pda = C + ID = pda.id + if(!istype(ID)) + ID = null + + if(ID) + return ID.registered_name + + C = H.wear_id + + if( istype(C) || istype(C, /obj/item/device/pda) ) + var/obj/item/weapon/card/id/ID = C + + if( istype(C, /obj/item/device/pda) ) + var/obj/item/device/pda/pda = C + ID = pda.id + if(!istype(ID)) + ID = null + + if(ID) + return ID.registered_name + +proc/get_all_job_icons() //For all existing HUD icons + return get_all_jobs() + list("Prisoner") diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm index 6e0158b4a6a..fb3a5edb4fe 100644 --- a/code/game/jobs/job/assistant.dm +++ b/code/game/jobs/job/assistant.dm @@ -1,25 +1,25 @@ -/datum/job/assistant - title = "Assistant" - flag = ASSISTANT - department_flag = CIVILIAN - faction = "Station" - total_positions = -1 - spawn_positions = -1 - supervisors = "absolutely everyone" - selection_color = "#dddddd" - access = list() //See /datum/job/assistant/get_access() - minimal_access = list() //See /datum/job/assistant/get_access() - alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Security Cadet") - -/datum/job/assistant/equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/clothing/under/color/grey(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - -/datum/job/assistant/get_access() - if(config.assistant_maint) - return list(access_maint_tunnels) - else - return list() +/datum/job/assistant + title = "Assistant" + flag = ASSISTANT + department_flag = CIVILIAN + faction = "Station" + total_positions = -1 + spawn_positions = -1 + supervisors = "absolutely everyone" + selection_color = "#dddddd" + access = list() //See /datum/job/assistant/get_access() + minimal_access = list() //See /datum/job/assistant/get_access() + alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Security Cadet") + +/datum/job/assistant/equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/clothing/under/color/grey(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + +/datum/job/assistant/get_access() + if(config.assistant_maint) + return list(access_maint_tunnels) + else + return list() diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 331d3941b1d..f86eeb722b7 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -1,420 +1,420 @@ -//Food -/datum/job/bartender - title = "Bartender" - flag = BARTENDER - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_hydroponics, access_bar, access_kitchen, access_morgue, access_weapons) - minimal_access = list(access_bar,access_weapons) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/bar - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/suit/armor/vest(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) - //H.equip_or_collect(new /obj/item/device/pda/bar(H), slot_belt) - - if(H.backbag == 1) - var/obj/item/weapon/storage/box/survival/Barpack = new H.species.survival_gear(H) - H.equip_or_collect(Barpack, slot_r_hand) - new /obj/item/ammo_casing/shotgun/beanbag(Barpack) - new /obj/item/ammo_casing/shotgun/beanbag(Barpack) - new /obj/item/ammo_casing/shotgun/beanbag(Barpack) - new /obj/item/ammo_casing/shotgun/beanbag(Barpack) - else - H.equip_or_collect(new H.species.survival_gear(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - - H.dna.SetSEState(SOBERBLOCK,1) - H.mutations += M_SOBER - H.check_mutations = 1 - - return 1 - - - -/datum/job/chef - title = "Chef" - flag = CHEF - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_hydroponics, access_bar, access_kitchen, access_morgue) - minimal_access = list(access_kitchen, access_morgue, access_bar) - alt_titles = list("Cook") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/chef - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/under/rank/chef(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/chef(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/head/chefhat(H), slot_head) - //H.equip_or_collect(new /obj/item/device/pda/chef(H), slot_belt) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -/datum/job/hydro - title = "Botanist" - flag = BOTANIST - department_flag = CIVILIAN - faction = "Station" - total_positions = 3 - spawn_positions = 2 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_hydroponics, access_bar, access_kitchen, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning. - minimal_access = list(access_hydroponics, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning. - alt_titles = list("Hydroponicist", "Beekeeper", "Gardener") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/botanist - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_hyd(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - switch(H.mind.role_alt_title) - if("Hydroponicist") - H.equip_or_collect(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform) - if("Botanist") - H.equip_or_collect(new /obj/item/clothing/under/rank/botany(H), slot_w_uniform) - if("Beekeeper") - H.equip_or_collect(new /obj/item/clothing/under/rank/beekeeper(H), slot_w_uniform) - if("Gardener") - H.equip_or_collect(new /obj/item/clothing/under/rank/gardener(H), slot_w_uniform) - - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/suit/apron(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store) - //H.equip_or_collect(new /obj/item/device/pda/botanist(H), slot_belt) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -//Cargo -/datum/job/qm - title = "Quartermaster" - flag = QUARTERMASTER - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - idtype = /obj/item/weapon/card/id/supply - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station, access_taxi) - minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station, access_taxi) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/quartermaster - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_cargo(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/under/rank/cargo(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/quartermaster(H), slot_belt) -// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) - H.equip_or_collect(new /obj/item/weapon/clipboard(H), slot_l_hand) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -/datum/job/cargo_tech - title = "Cargo Technician" - flag = CARGOTECH - department_flag = CIVILIAN - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "the quartermaster and the head of personnel" - selection_color = "#dddddd" - idtype = /obj/item/weapon/card/id/supply - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mint, access_mining, access_mining_station, access_taxi) - minimal_access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting, access_taxi) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/cargo - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_cargo(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/under/rank/cargotech(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/cargo(H), slot_belt) -// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -/datum/job/mining - title = "Shaft Miner" - flag = MINER - department_flag = CIVILIAN - faction = "Station" - total_positions = 3 - spawn_positions = 3 - supervisors = "the quartermaster and the head of personnel" - selection_color = "#dddddd" - idtype = /obj/item/weapon/card/id/supply - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mint, access_mining, access_mining_station) - minimal_access = list(access_mining, access_mint, access_mining_station, access_mailsorting) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/shaftminer - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_mining(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform) - //H.equip_or_collect(new /obj/item/device/pda/shaftminer(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) -// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - if(H.backbag == 1) - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) - H.equip_or_collect(new /obj/item/weapon/crowbar(H), slot_l_hand) - H.equip_or_collect(new /obj/item/weapon/storage/bag/ore(H), slot_l_store) - else - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/crowbar(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/storage/bag/ore(H), slot_in_backpack) - return 1 - -/datum/job/clown - title = "Clown" - flag = CLOWN - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - idtype = /obj/item/weapon/card/id/clown - access = list(access_clown, access_theatre, access_maint_tunnels) - minimal_access = list(access_clown, access_theatre) - alt_titles = list("Jester") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/clown - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/weapon/storage/backpack/clown(H), slot_back) - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - //H.equip_or_collect(new /obj/item/device/pda/clown(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) - H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/bikehorn(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/stamp/clown(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/toy/crayon/rainbow(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/toy/waterflower(H), slot_in_backpack) - H.mutations.Add(M_CLUMSY) - if (H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Jester") - H.equip_or_collect(new /obj/item/clothing/under/jester(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/jestershoes(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/head/jesterhat(H), slot_head) - else - H.equip_or_collect(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes) - H.real_name = pick(clown_names) - H.rename_self("clown") - return 1 - - - -/datum/job/mime - title = "Mime" - flag = MIME - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - idtype = /obj/item/weapon/card/id/mime - access = list(access_mime, access_theatre, access_maint_tunnels) - minimal_access = list(access_mime, access_theatre) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/mime - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - if(H.backbag == 2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(H.backbag == 3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/mime(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/mime(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/mime(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/gloves/white(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask) - H.equip_or_collect(new /obj/item/clothing/head/beret(H), slot_head) - H.equip_or_collect(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - H.equip_or_collect(new /obj/item/toy/crayon/mime(H), slot_l_store) - H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/toy/crayon/mime(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack) - H.add_spell(new /spell/aoe_turf/conjure/forcewall/mime, "grey_spell_ready") - H.miming = 1 - H.rename_self("mime") - return 1 - - -/datum/job/janitor - title = "Janitor" - flag = JANITOR - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_janitor, access_maint_tunnels) - minimal_access = list(access_janitor, access_maint_tunnels) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/janitor - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/clothing/under/rank/janitor(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/janitor(H), slot_belt) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - // Now spawns on the janikart. H.equip_or_collect(new /obj/item/key(H), slot_l_store) - return 1 - - - -//More or less assistants -/datum/job/librarian - title = "Librarian" - flag = LIBRARIAN - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#dddddd" - access = list(access_library, access_maint_tunnels) - minimal_access = list(access_library) - alt_titles = list("Journalist", "Game Master") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/librarian - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/clothing/under/suit_jacket/red(H), slot_w_uniform) - //H.equip_or_collect(new /obj/item/device/pda/librarian(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_or_collect(new /obj/item/weapon/barcodescanner(H), slot_l_hand) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -//var/global/lawyer = 0//Checks for another lawyer //This changed clothes on 2nd lawyer, both IA get the same dreds. -/datum/job/lawyer - title = "Internal Affairs Agent" - flag = LAWYER - department_flag = CIVILIAN - faction = "Station" - idtype = /obj/item/weapon/card/id/centcom - total_positions = 2 - spawn_positions = 2 - supervisors = "NanoTransen Law, CentComm Officals, and the stations captain." - selection_color = "#dddddd" - access = list(access_lawyer, access_court, access_sec_doors, access_maint_tunnels, access_cargo, access_medical, access_bar, access_kitchen, access_hydroponics) - minimal_access = list(access_lawyer, access_court, access_sec_doors, access_cargo, access_bar, access_kitchen) - alt_titles = list("Lawyer") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/lawyer - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - if (H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Lawyer") - H.equip_or_collect(new /obj/item/clothing/under/lawyer/bluesuit(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/storage/lawyer/bluejacket(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/shoes/leather(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/under/rank/internalaffairs(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/storage/internalaffairs(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/shoes/centcom(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) - //H.equip_or_collect(new /obj/item/device/pda/lawyer(H), slot_belt) - H.equip_or_collect(new /obj/item/weapon/storage/briefcase(H), slot_l_hand) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) - L.imp_in = H - L.implanted = 1 - return 1 +//Food +/datum/job/bartender + title = "Bartender" + flag = BARTENDER + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(access_hydroponics, access_bar, access_kitchen, access_morgue, access_weapons) + minimal_access = list(access_bar,access_weapons) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/bar + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/suit/armor/vest(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) + //H.equip_or_collect(new /obj/item/device/pda/bar(H), slot_belt) + + if(H.backbag == 1) + var/obj/item/weapon/storage/box/survival/Barpack = new H.species.survival_gear(H) + H.equip_or_collect(Barpack, slot_r_hand) + new /obj/item/ammo_casing/shotgun/beanbag(Barpack) + new /obj/item/ammo_casing/shotgun/beanbag(Barpack) + new /obj/item/ammo_casing/shotgun/beanbag(Barpack) + new /obj/item/ammo_casing/shotgun/beanbag(Barpack) + else + H.equip_or_collect(new H.species.survival_gear(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + + H.dna.SetSEState(SOBERBLOCK,1) + H.mutations += M_SOBER + H.check_mutations = 1 + + return 1 + + + +/datum/job/chef + title = "Chef" + flag = CHEF + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(access_hydroponics, access_bar, access_kitchen, access_morgue) + minimal_access = list(access_kitchen, access_morgue, access_bar) + alt_titles = list("Cook") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/chef + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/under/rank/chef(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/chef(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/head/chefhat(H), slot_head) + //H.equip_or_collect(new /obj/item/device/pda/chef(H), slot_belt) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +/datum/job/hydro + title = "Botanist" + flag = BOTANIST + department_flag = CIVILIAN + faction = "Station" + total_positions = 3 + spawn_positions = 2 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(access_hydroponics, access_bar, access_kitchen, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning. + minimal_access = list(access_hydroponics, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning. + alt_titles = list("Hydroponicist", "Beekeeper", "Gardener") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/botanist + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_hyd(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + switch(H.mind.role_alt_title) + if("Hydroponicist") + H.equip_or_collect(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform) + if("Botanist") + H.equip_or_collect(new /obj/item/clothing/under/rank/botany(H), slot_w_uniform) + if("Beekeeper") + H.equip_or_collect(new /obj/item/clothing/under/rank/beekeeper(H), slot_w_uniform) + if("Gardener") + H.equip_or_collect(new /obj/item/clothing/under/rank/gardener(H), slot_w_uniform) + + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/suit/apron(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store) + //H.equip_or_collect(new /obj/item/device/pda/botanist(H), slot_belt) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +//Cargo +/datum/job/qm + title = "Quartermaster" + flag = QUARTERMASTER + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + idtype = /obj/item/weapon/card/id/supply + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station, access_taxi) + minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station, access_taxi) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/quartermaster + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_cargo(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/under/rank/cargo(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/quartermaster(H), slot_belt) +// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) + H.equip_or_collect(new /obj/item/weapon/clipboard(H), slot_l_hand) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +/datum/job/cargo_tech + title = "Cargo Technician" + flag = CARGOTECH + department_flag = CIVILIAN + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "the quartermaster and the head of personnel" + selection_color = "#dddddd" + idtype = /obj/item/weapon/card/id/supply + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mint, access_mining, access_mining_station, access_taxi) + minimal_access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting, access_taxi) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/cargo + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_cargo(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/under/rank/cargotech(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/cargo(H), slot_belt) +// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +/datum/job/mining + title = "Shaft Miner" + flag = MINER + department_flag = CIVILIAN + faction = "Station" + total_positions = 3 + spawn_positions = 3 + supervisors = "the quartermaster and the head of personnel" + selection_color = "#dddddd" + idtype = /obj/item/weapon/card/id/supply + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mint, access_mining, access_mining_station) + minimal_access = list(access_mining, access_mint, access_mining_station, access_mailsorting) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/shaftminer + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_mining(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform) + //H.equip_or_collect(new /obj/item/device/pda/shaftminer(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) +// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + if(H.backbag == 1) + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) + H.equip_or_collect(new /obj/item/weapon/crowbar(H), slot_l_hand) + H.equip_or_collect(new /obj/item/weapon/storage/bag/ore(H), slot_l_store) + else + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/crowbar(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/storage/bag/ore(H), slot_in_backpack) + return 1 + +/datum/job/clown + title = "Clown" + flag = CLOWN + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + idtype = /obj/item/weapon/card/id/clown + access = list(access_clown, access_theatre, access_maint_tunnels) + minimal_access = list(access_clown, access_theatre) + alt_titles = list("Jester") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/clown + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/weapon/storage/backpack/clown(H), slot_back) + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + //H.equip_or_collect(new /obj/item/device/pda/clown(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) + H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/bikehorn(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/stamp/clown(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/toy/crayon/rainbow(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/toy/waterflower(H), slot_in_backpack) + H.mutations.Add(M_CLUMSY) + if (H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Jester") + H.equip_or_collect(new /obj/item/clothing/under/jester(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/jestershoes(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/head/jesterhat(H), slot_head) + else + H.equip_or_collect(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes) + H.real_name = pick(clown_names) + H.rename_self("clown") + return 1 + + + +/datum/job/mime + title = "Mime" + flag = MIME + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + idtype = /obj/item/weapon/card/id/mime + access = list(access_mime, access_theatre, access_maint_tunnels) + minimal_access = list(access_mime, access_theatre) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/mime + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + if(H.backbag == 2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(H.backbag == 3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/mime(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/mime(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/mime(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/gloves/white(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask) + H.equip_or_collect(new /obj/item/clothing/head/beret(H), slot_head) + H.equip_or_collect(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + H.equip_or_collect(new /obj/item/toy/crayon/mime(H), slot_l_store) + H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/toy/crayon/mime(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack) + H.add_spell(new /spell/aoe_turf/conjure/forcewall/mime, "grey_spell_ready") + H.miming = 1 + H.rename_self("mime") + return 1 + + +/datum/job/janitor + title = "Janitor" + flag = JANITOR + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(access_janitor, access_maint_tunnels) + minimal_access = list(access_janitor, access_maint_tunnels) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/janitor + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/clothing/under/rank/janitor(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/janitor(H), slot_belt) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + // Now spawns on the janikart. H.equip_or_collect(new /obj/item/key(H), slot_l_store) + return 1 + + + +//More or less assistants +/datum/job/librarian + title = "Librarian" + flag = LIBRARIAN + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(access_library, access_maint_tunnels) + minimal_access = list(access_library) + alt_titles = list("Journalist", "Game Master") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/librarian + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/clothing/under/suit_jacket/red(H), slot_w_uniform) + //H.equip_or_collect(new /obj/item/device/pda/librarian(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_or_collect(new /obj/item/weapon/barcodescanner(H), slot_l_hand) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +//var/global/lawyer = 0//Checks for another lawyer //This changed clothes on 2nd lawyer, both IA get the same dreds. +/datum/job/lawyer + title = "Internal Affairs Agent" + flag = LAWYER + department_flag = CIVILIAN + faction = "Station" + idtype = /obj/item/weapon/card/id/centcom + total_positions = 2 + spawn_positions = 2 + supervisors = "NanoTransen Law, CentComm Officals, and the stations captain." + selection_color = "#dddddd" + access = list(access_lawyer, access_court, access_sec_doors, access_maint_tunnels, access_cargo, access_medical, access_bar, access_kitchen, access_hydroponics) + minimal_access = list(access_lawyer, access_court, access_sec_doors, access_cargo, access_bar, access_kitchen) + alt_titles = list("Lawyer") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/lawyer + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if (H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Lawyer") + H.equip_or_collect(new /obj/item/clothing/under/lawyer/bluesuit(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/storage/lawyer/bluejacket(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/shoes/leather(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/under/rank/internalaffairs(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/storage/internalaffairs(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/shoes/centcom(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) + //H.equip_or_collect(new /obj/item/device/pda/lawyer(H), slot_belt) + H.equip_or_collect(new /obj/item/weapon/storage/briefcase(H), slot_l_hand) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) + L.imp_in = H + L.implanted = 1 + return 1 diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm index 7c09f210c80..9245549545e 100644 --- a/code/game/jobs/job/civilian_chaplain.dm +++ b/code/game/jobs/job/civilian_chaplain.dm @@ -1,445 +1,445 @@ -//Due to how large this one is, it gets its own file from civilian.dm -/datum/job/chaplain - title = "Chaplain" - flag = CHAPLAIN - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "The God(s), the Head of Personnel too." - selection_color = "#dddddd" - access = list(access_morgue, access_chapel_office, access_crematorium, access_maint_tunnels) - minimal_access = list(access_morgue, access_chapel_office, access_crematorium) - pdaslot = slot_belt - pdatype = /obj/item/device/pda/chaplain - -/datum/job/chaplain/equip(var/mob/living/carbon/human/H) - - H.add_language("Spooky") //SPOOK - var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(H) //BS12 EDIT - H.equip_or_collect(B, slot_l_hand) - H.equip_or_collect(new /obj/item/clothing/under/rank/chaplain(H), slot_w_uniform) - //H.equip_or_collect(new /obj/item/device/pda/chaplain(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - - var/religion_name = "Christianity" //Default - var/deity_name = "Space Jesus" //Also default, set below - - spawn(0) //We are done giving earthly belongings, now let's move on to spiritual matters - - var/new_religion = sanitize(stripped_input(H, "You are the crew's Religious Services Chaplain. What religion do you follow and teach? (Please put your ID in your ID slot to prevent errors)", "Name of Religion", religion_name), 1, MAX_NAME_LEN) - - if(!new_religion) - new_religion = religion_name //Give them the default one - - var/datum/job/J = H.mind.role_alt_title - - switch(lowertext(new_religion)) //Let us begin going through the list of special religions we can give them. It's a long list, trust me. We assign them a bible name, a god and misc fun stuff - if("christianity") - B.name = "The Holy Bible" - deity_name = "Space Jesus" - if("catholic", "catholicism", "roman catholicism") - B.name = "The Catholic Bible" - /* - if(H.gender == FEMALE) - J = "Nun" - else - J = "Priest" - */ - J = "Bishop" - deity_name = "Jesus Christ" - H.equip_or_collect(new /obj/item/clothing/head/mitre(H), slot_head) - if("theist", "gnosticism", "theism") - B.name = pick("The Gnostic Bible", "The Dead Seas Scrolls") - deity_name = "God" - if("satan", "evil", "satanism") - B.name = "The Satanic Bible" //What I found on Google, ergo the truth - if(H.gender == FEMALE) - J = "Magistra" - else - J = "Magister" - deity_name = "Satan" - if("cthulhu", "outer gods", "elder gods", "esoteric order of dagon") - B.name = pick("The Necronomicon", "The Book of Eibon", "De Vermis Mysteriis", "Unaussprechlichen Kulten") - deity_name = "Cthulhu" //I hope it's spelt correctly - if("islam", "muslim") - B.name = "The Quran" - J = "Imam" - deity_name = "Allah" - if("slam") - B.name = "Barkley: Shut Up and Jam - Gaiden" - if(H.gender == FEMALE) - J = "Mistress of Slam" - else - J = "Master of Slam" - deity_name = "Charles Barkley" - if("jew", "judaism") - B.name = pick("The Torah", "The Talmud") - J = "Rabbi" - deity_name = "Yahweh" - if("hindu", "hinduism") - B.name = pick("The Vedas", "The Mahabharata") - J = "Guru" - deity_name = pick("Brahma", "Vishnu", "Shiva", "Ganesha") //The major ones at least, and yes it's polytheist - if("buddha", "buddhism") - B.name = "The Tripitaka" - J = "Monk" - deity_name = "Buddha" - if("shinto", "shintoism") - B.name = "Kojiki" - if(H.gender == FEMALE) - J = "Shrine Maiden" - else - J = "Kannushi" - deity_name = "Kami" //Polytheist and shit, do I sound like a weeb ? - if("mormon", "mormonism") - B.name = "The Book of Mormon" - J = "Apostle" - deity_name = "God the Father-Elohim" - if("confucianism") - B.name = pick("The I Ching", "Great Learning") - J = "Scholar" //I don't know honestly - deity_name = "Tian" //I found this somewhere, I guess that's true - if("wicca", "paganism") - B.name = "The Book of Shadows" - if(H.gender == FEMALE) - J = "High Priestess" - else - J = "High Priest" - deity_name = "The Gods" //Damn pagans - if("norse") - B.name = "The Edda" - J = "Godi" - deity_name = pick("Thor", "Odin") //Literally the only two I know, bite me - if("druidism", "celtic") - B.name = "The Book of Leinster" - J = "Druid" - deity_name = pick("Toutatis", "Belenus", "Britannia") //Hon - if("atheism", "none") - B.name = "The God Delusion" - H.equip_or_collect(new /obj/item/clothing/head/fedora(H), slot_head) - deity_name = "Richard Dawkins" - if("evolution", "biology", "monkey", "monkeys") - B.name = "The Theory of Evolution" - J = "Biologist" - deity_name = "Charles Darwin" - if("scientology") - B.name = pick("The Biography of L. Ron Hubbard", "Dianetics") - J = "OT III" - deity_name = "The Eighth Dynamic" //Don't ask, just don't - if("discordianism") - B.name = "The Principia Discordia" - J = "Episkopos" - deity_name = "Eris" //Thanks Google - if("rastafarianism", "rastafari movement") - B.name = "The Holy Piby" - deity_name = "Haile Selassie I" - if("hellenism") //None of that roman copypasta, incidentally - B.name = "The Odyssey" - J = "Oracle" - deity_name = pick("Zeus", "Neptune", "Athena", "Persephone") - if("pastafarianism") - B.name = "The Gospel of the Flying Spaghetti Monster" - deity_name = "The Flying Spaghetti Monster" - if("chaos") - B.name = pick("The Book of Lorgar", "The Book of Magnus") - J = "Apostate Preacher" - deity_name = pick("Khorne", "Nurgle", "Tzeentch", "Slaanesh") - if("imperium", "imperial cult") - B.name = pick("An Uplifting Primer", "Codex Astartes", "Codex Hereticus") - if(H.gender == FEMALE) - J = "Prioress" - else - J = "Confessor" - deity_name = "The God-Emperor of Mankind" - if("toolboxia", "toolbox") - B.name = "The Toolbox Manifesto" - J = "Chief Assistant" - deity_name = "The Toolbox" - if("homosexuality", "faggotry", "gayness") - B.name = pick("Guys Gone Wild", "Hunk Rump") - deity_name = "The Gays" //Fucked if I know - if("lol", "wtf", "gay", "penis", "ass", "poo", "badmin", "shitmin", "deadmin", "cock", "cocks", "nigger", "faggot", "dickbutt", ":^)", "XD", "le") - B.name = pick("Woody's Got Wood: The Aftermath", "War of the Cocks", "Sweet Bro and Hella Jef: Expanded Edition", "The Book of Pomf") - H.setBrainLoss(100) //Starts off retarded as fuck, that'll teach him - deity_name = "Brian Damag" //Ha - if("science") - B.name = pick("Principle of Relativity", "Quantum Enigma: Physics Encounters Consciousness", "Programming the Universe", "Quantum Physics and Theology", \ - "For I Have Tasted The Fruit", "Non-Linear Genetics", "The Mysteries of Bluespace", "Playing God: Collector's Edition") - J = "Academician" - deity_name = pick("Albert Einstein", "Isaac Newton", "Niels Bohr", "Stephen Hawking") - if("tribunal", "almsivi") - B.name = "The 36 Lessons of Vivec" - J = "Curate" - deity_name = pick("Almalexia", "Sotha Sil", "Vivec") - if("nine divines", "eight divines") - B.name = "The Elder Scrolls" - J = "Disciple of the Nine" - deity_name = pick("Talos", "Akatosh", "Dibella", "Stendarr", "Kynareth", "Mara", "Arkay", "Julianos", "Zenithar") - if("daedra") - B.name = pick("The Blessings of Sheogorath", "Boethiah's Pillow Book", "Invocation of Azura") - J = "Deadra Worshipper" - deity_name = pick("Azura", "Boethiah", "Sheogorath", "Sanguine", "Hircine", "Meridia", "Hermaeus Mora", "Nocturnal") - if("bokononism") - B.name = pick("The Book of Bokonon") - J = "Worshipper" - deity_name = "Boko-Maru" //Completely wrong, but fuck it - if("faith of the seven") - B.name = "The Seven-Pointed Star" - if(H.gender == FEMALE) - J = "Septa" - else - J = "Septon" - deity_name = pick("Father", "Mother") - if("goa'uld") - B.name = "The Abydos Cartouche" - J = "First Prime" - deity_name = "Ra" - if("unitology") - B.name = "Teachings of Unitology" - J = "Vested" - deity_name = "The Marker" - if("zakarum") - B.name = "The Visions of Akarat" - J = "Disciple" - deity_name = "The Light" - if("ianism") - B.name = "The Poky Little Puppy" - J = "Veterinarian" - deity_name = "Ian" - if("adminism", "admintology", "admin", "admins", "adminhelp", "adminbus") - B.name = "Breaking Through the Fourth Wall" - J = "Trial Admin" - deity_name = "The Adminbus" - if("coding", "coder", "coders") - B.name = "Guide to Github" - J = "Coder" - deity_name = "The Coderbus" - if("42") - B.name = "The Hitchhiker's Guide to the Galaxy" - deity_name = "Arthur Dent" //Don't care - if("spook", "spooky", "boo", "ghost") - B.name = "The Spooky Spook" //SPOOK - J = "Ghost" - deity_name = "The Spook" //SPOOK - H.equip_or_collect(new /obj/item/clothing/head/pumpkinhead(H), slot_head) - if("medbay", "ride", "wild ride", "cryo") - B.name = "The Wild Ride" - if(H.gender == FEMALE) - J = "Nurse" - else - J = "Doctor" - //Give them basic medical garb - H.equip_or_collect(new /obj/item/clothing/head/surgery/blue(H), slot_head) - H.equip_or_collect(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) - deity_name = "The Chief Medical Officer" - if("busta", "bustatime", "zas", "airflow", "hardcore", "hardcores") - B.name = "The Hardcores" - if(!(M_HARDCORE in H.mutations)) - H.mutations.Add(M_HARDCORE) - J = "Atmospherics Technician" - deity_name = "Bustatime" - if("me", "i", "narcissism", "self importance", "selfishness") - B.name = "The Teachings of [H]" //Quite literally - J = "God" - deity_name = "[H]" //Very literally, too - if("alcohol", "booze", "beer", "wine", "ethanol", "c2h6o") - B.name = "The Drunken Ramblings" - J = "Drunkard" - deity_name = "Hic" - if("robust", "robustness", "strength") - B.name = "The Rules of Robustness" - J = "Robuster" - deity_name = "The Robust" - if("suicide", "death", "succumb") - B.name = "The Sweet Release of Death" - J = "Reaper" - deity_name = "The Grim Reaper" - if("communism", "socialism") - B.name = "The Communist Manifesto" - J = "Komrade" - deity_name = "Karl Max" - H.equip_or_collect(new /obj/item/clothing/head/ushanka(H), slot_head) - if("capitalism", "free market", "liberalism") - B.name = "The Free Market" - J = "Stockholder" - deity_name = "Adam Smith" - H.equip_or_collect(new /obj/item/clothing/head/that(H), slot_head) - if("freedom", "america", "muhrica", "usa") - B.name = "The Constitution" - J = "Senator" - deity_name = "George Washington" - H.equip_or_collect(new /obj/item/clothing/head/libertyhat(H), slot_head) - if("fascism", "nazi", "national socialism") - B.name = "Mein Kampf" - J = "Feldbischof" //No seriously, that's a thing, look it up - deity_name = "Adolf Hitler" - H.equip_or_collect(new /obj/item/clothing/head/naziofficer(H), slot_head) - if("security", "space law", "law", "nanotrasen", "centcomm") - B.name = "Space Law" - J = "Nanotrasen Officer" - deity_name = "Nanotrasen" - H.equip_or_collect(new /obj/item/clothing/head/centhat(H), slot_head) - if("syndicate", "traitor", "syndie", "syndies") - B.name = "The Syndicate Bundle" - J = "Syndicate Agent" - deity_name = "The Syndicate" - H.equip_or_collect(new /obj/item/clothing/head/syndicatefake(H), slot_head) - if("cult", "narsie", "nar'sie", "narnar") - B.name = "The Arcane Tome" - J = "Cultist" - deity_name = "Nar'Sie" - else //Boring, give them a stock name - B.name = "The Holy Book of [new_religion]" - - //This goes down here due to problems with loading orders that took me 4 hours to identify - var/obj/item/weapon/card/id/I = null - if(istype(H.wear_id, /obj/item/weapon/card/id/)) //This prevents people from causing weirdness by putting other things into their slots before chosing their religion - I = H.wear_id - if(I.registered_name == H.real_name) //Makes sure the ID is the chaplain's own - I.assignment = J - I.name = text("[I.registered_name]'s ID Card ([I.assignment])") - var/obj/item/device/pda/P = null - if(istype(H.belt, /obj/item/device/pda)) //This prevents people from causing weirdness by putting other things into their slots before chosing their religion - P = H.belt - if(P.owner == H.real_name) //Makes sure the PDA is the chaplain's own - P.ownjob = J - P.name = text("PDA-[P.owner] ([P.ownjob])") - data_core.manifest_modify(H.real_name, J) //Updates manifest - feedback_set_details("religion_name","[new_religion]") - - //Allow them to change their deity if they believe the deity we gave them sucks - var/new_deity = copytext(sanitize(input(H, "Would you like to change your deity? Your deity currently is [deity_name] (Leave empty or unchanged to keep diety name)", "Name of Deity", deity_name)), 1, MAX_NAME_LEN) - - if(!length(new_deity)) - new_deity = deity_name //Just give them what was picked for them already - B.deity_name = new_deity - - var/accepted = 0 - var/outoftime = 0 - spawn(200) //20 seconds to choose - outoftime = 1 - var/new_book_style = "Bible" - - while(!accepted) - if(!B) - break //Prevents possible runtime errors - new_book_style = input(H, "Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", \ - "the bible melts", "Unaussprechlichen Kulten", "Necronomicon", "Book of Shadows", "Torah", "Burning", "Honk", "Ianism", "The Guide") - switch(new_book_style) - if("Koran") - B.icon_state = "koran" - B.item_state = "koran" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 4 - if("Scrapbook") - B.icon_state = "scrapbook" - B.item_state = "scrapbook" - if("Creeper") - B.icon_state = "creeper" - B.item_state = "syringe_kit" - if("White Bible") - B.icon_state = "white" - B.item_state = "syringe_kit" - if("Holy Light") - B.icon_state = "holylight" - B.item_state = "syringe_kit" - if("Athiest") - B.icon_state = "athiest" - B.item_state = "syringe_kit" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 10 - if("Tome") - B.icon_state = "tome" - B.item_state = "syringe_kit" - if("The King in Yellow") - B.icon_state = "kingyellow" - B.item_state = "kingyellow" - if("Ithaqua") - B.icon_state = "ithaqua" - B.item_state = "ithaqua" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 5 - if("Scientology") - B.icon_state = "scientology" - B.item_state = "scientology" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 8 - if("the bible melts") - B.icon_state = "melted" - B.item_state = "melted" - if("Unaussprechlichen Kulten") - B.icon_state = "kulten" - B.item_state = "kulten" - if("Necronomicon") - B.icon_state = "necronomicon" - B.item_state = "necronomicon" - if("Book of Shadows") - B.icon_state = "shadows" - B.item_state = "shadows" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 6 - if("Torah") - B.icon_state = "torah" - B.item_state = "torah" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 1 - if("Burning") - B.icon_state = "burning" - B.item_state = "syringe_kit" - if("Honk") - B.icon_state = "honkbook" - B.item_state = "honkbook" - if("Ianism") - B.icon_state = "ianism" - B.item_state = "ianism" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 9 - if("The Guide") - B.icon_state = "guide" - B.item_state = "guide" - else - //If christian bible, revert to default - B.icon_state = "bible" - B.item_state = "bible" - for(var/area/chapel/main/A in areas) - for(var/turf/T in A.contents) - if(T.icon_state == "carpetsymbol") - T.dir = 2 - - H.update_inv_l_hand() //So that it updates the bible's item_state in his hand - - switch(input(H, "Look at your bible - is this what you want?") in list("Yes", "No")) - if("Yes") - accepted = 1 - if("No") - if(outoftime) +//Due to how large this one is, it gets its own file from civilian.dm +/datum/job/chaplain + title = "Chaplain" + flag = CHAPLAIN + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "The God(s), the Head of Personnel too." + selection_color = "#dddddd" + access = list(access_morgue, access_chapel_office, access_crematorium, access_maint_tunnels) + minimal_access = list(access_morgue, access_chapel_office, access_crematorium) + pdaslot = slot_belt + pdatype = /obj/item/device/pda/chaplain + +/datum/job/chaplain/equip(var/mob/living/carbon/human/H) + + H.add_language("Spooky") //SPOOK + var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(H) //BS12 EDIT + H.equip_or_collect(B, slot_l_hand) + H.equip_or_collect(new /obj/item/clothing/under/rank/chaplain(H), slot_w_uniform) + //H.equip_or_collect(new /obj/item/device/pda/chaplain(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + + var/religion_name = "Christianity" //Default + var/deity_name = "Space Jesus" //Also default, set below + + spawn(0) //We are done giving earthly belongings, now let's move on to spiritual matters + + var/new_religion = sanitize(stripped_input(H, "You are the crew's Religious Services Chaplain. What religion do you follow and teach? (Please put your ID in your ID slot to prevent errors)", "Name of Religion", religion_name), 1, MAX_NAME_LEN) + + if(!new_religion) + new_religion = religion_name //Give them the default one + + var/datum/job/J = H.mind.role_alt_title + + switch(lowertext(new_religion)) //Let us begin going through the list of special religions we can give them. It's a long list, trust me. We assign them a bible name, a god and misc fun stuff + if("christianity") + B.name = "The Holy Bible" + deity_name = "Space Jesus" + if("catholic", "catholicism", "roman catholicism") + B.name = "The Catholic Bible" + /* + if(H.gender == FEMALE) + J = "Nun" + else + J = "Priest" + */ + J = "Bishop" + deity_name = "Jesus Christ" + H.equip_or_collect(new /obj/item/clothing/head/mitre(H), slot_head) + if("theist", "gnosticism", "theism") + B.name = pick("The Gnostic Bible", "The Dead Seas Scrolls") + deity_name = "God" + if("satan", "evil", "satanism") + B.name = "The Satanic Bible" //What I found on Google, ergo the truth + if(H.gender == FEMALE) + J = "Magistra" + else + J = "Magister" + deity_name = "Satan" + if("cthulhu", "outer gods", "elder gods", "esoteric order of dagon") + B.name = pick("The Necronomicon", "The Book of Eibon", "De Vermis Mysteriis", "Unaussprechlichen Kulten") + deity_name = "Cthulhu" //I hope it's spelt correctly + if("islam", "muslim") + B.name = "The Quran" + J = "Imam" + deity_name = "Allah" + if("slam") + B.name = "Barkley: Shut Up and Jam - Gaiden" + if(H.gender == FEMALE) + J = "Mistress of Slam" + else + J = "Master of Slam" + deity_name = "Charles Barkley" + if("jew", "judaism") + B.name = pick("The Torah", "The Talmud") + J = "Rabbi" + deity_name = "Yahweh" + if("hindu", "hinduism") + B.name = pick("The Vedas", "The Mahabharata") + J = "Guru" + deity_name = pick("Brahma", "Vishnu", "Shiva", "Ganesha") //The major ones at least, and yes it's polytheist + if("buddha", "buddhism") + B.name = "The Tripitaka" + J = "Monk" + deity_name = "Buddha" + if("shinto", "shintoism") + B.name = "Kojiki" + if(H.gender == FEMALE) + J = "Shrine Maiden" + else + J = "Kannushi" + deity_name = "Kami" //Polytheist and shit, do I sound like a weeb ? + if("mormon", "mormonism") + B.name = "The Book of Mormon" + J = "Apostle" + deity_name = "God the Father-Elohim" + if("confucianism") + B.name = pick("The I Ching", "Great Learning") + J = "Scholar" //I don't know honestly + deity_name = "Tian" //I found this somewhere, I guess that's true + if("wicca", "paganism") + B.name = "The Book of Shadows" + if(H.gender == FEMALE) + J = "High Priestess" + else + J = "High Priest" + deity_name = "The Gods" //Damn pagans + if("norse") + B.name = "The Edda" + J = "Godi" + deity_name = pick("Thor", "Odin") //Literally the only two I know, bite me + if("druidism", "celtic") + B.name = "The Book of Leinster" + J = "Druid" + deity_name = pick("Toutatis", "Belenus", "Britannia") //Hon + if("atheism", "none") + B.name = "The God Delusion" + H.equip_or_collect(new /obj/item/clothing/head/fedora(H), slot_head) + deity_name = "Richard Dawkins" + if("evolution", "biology", "monkey", "monkeys") + B.name = "The Theory of Evolution" + J = "Biologist" + deity_name = "Charles Darwin" + if("scientology") + B.name = pick("The Biography of L. Ron Hubbard", "Dianetics") + J = "OT III" + deity_name = "The Eighth Dynamic" //Don't ask, just don't + if("discordianism") + B.name = "The Principia Discordia" + J = "Episkopos" + deity_name = "Eris" //Thanks Google + if("rastafarianism", "rastafari movement") + B.name = "The Holy Piby" + deity_name = "Haile Selassie I" + if("hellenism") //None of that roman copypasta, incidentally + B.name = "The Odyssey" + J = "Oracle" + deity_name = pick("Zeus", "Neptune", "Athena", "Persephone") + if("pastafarianism") + B.name = "The Gospel of the Flying Spaghetti Monster" + deity_name = "The Flying Spaghetti Monster" + if("chaos") + B.name = pick("The Book of Lorgar", "The Book of Magnus") + J = "Apostate Preacher" + deity_name = pick("Khorne", "Nurgle", "Tzeentch", "Slaanesh") + if("imperium", "imperial cult") + B.name = pick("An Uplifting Primer", "Codex Astartes", "Codex Hereticus") + if(H.gender == FEMALE) + J = "Prioress" + else + J = "Confessor" + deity_name = "The God-Emperor of Mankind" + if("toolboxia", "toolbox") + B.name = "The Toolbox Manifesto" + J = "Chief Assistant" + deity_name = "The Toolbox" + if("homosexuality", "faggotry", "gayness") + B.name = pick("Guys Gone Wild", "Hunk Rump") + deity_name = "The Gays" //Fucked if I know + if("lol", "wtf", "gay", "penis", "ass", "poo", "badmin", "shitmin", "deadmin", "cock", "cocks", "nigger", "faggot", "dickbutt", ":^)", "XD", "le") + B.name = pick("Woody's Got Wood: The Aftermath", "War of the Cocks", "Sweet Bro and Hella Jef: Expanded Edition", "The Book of Pomf") + H.setBrainLoss(100) //Starts off retarded as fuck, that'll teach him + deity_name = "Brian Damag" //Ha + if("science") + B.name = pick("Principle of Relativity", "Quantum Enigma: Physics Encounters Consciousness", "Programming the Universe", "Quantum Physics and Theology", \ + "For I Have Tasted The Fruit", "Non-Linear Genetics", "The Mysteries of Bluespace", "Playing God: Collector's Edition") + J = "Academician" + deity_name = pick("Albert Einstein", "Isaac Newton", "Niels Bohr", "Stephen Hawking") + if("tribunal", "almsivi") + B.name = "The 36 Lessons of Vivec" + J = "Curate" + deity_name = pick("Almalexia", "Sotha Sil", "Vivec") + if("nine divines", "eight divines") + B.name = "The Elder Scrolls" + J = "Disciple of the Nine" + deity_name = pick("Talos", "Akatosh", "Dibella", "Stendarr", "Kynareth", "Mara", "Arkay", "Julianos", "Zenithar") + if("daedra") + B.name = pick("The Blessings of Sheogorath", "Boethiah's Pillow Book", "Invocation of Azura") + J = "Deadra Worshipper" + deity_name = pick("Azura", "Boethiah", "Sheogorath", "Sanguine", "Hircine", "Meridia", "Hermaeus Mora", "Nocturnal") + if("bokononism") + B.name = pick("The Book of Bokonon") + J = "Worshipper" + deity_name = "Boko-Maru" //Completely wrong, but fuck it + if("faith of the seven") + B.name = "The Seven-Pointed Star" + if(H.gender == FEMALE) + J = "Septa" + else + J = "Septon" + deity_name = pick("Father", "Mother") + if("goa'uld") + B.name = "The Abydos Cartouche" + J = "First Prime" + deity_name = "Ra" + if("unitology") + B.name = "Teachings of Unitology" + J = "Vested" + deity_name = "The Marker" + if("zakarum") + B.name = "The Visions of Akarat" + J = "Disciple" + deity_name = "The Light" + if("ianism") + B.name = "The Poky Little Puppy" + J = "Veterinarian" + deity_name = "Ian" + if("adminism", "admintology", "admin", "admins", "adminhelp", "adminbus") + B.name = "Breaking Through the Fourth Wall" + J = "Trial Admin" + deity_name = "The Adminbus" + if("coding", "coder", "coders") + B.name = "Guide to Github" + J = "Coder" + deity_name = "The Coderbus" + if("42") + B.name = "The Hitchhiker's Guide to the Galaxy" + deity_name = "Arthur Dent" //Don't care + if("spook", "spooky", "boo", "ghost") + B.name = "The Spooky Spook" //SPOOK + J = "Ghost" + deity_name = "The Spook" //SPOOK + H.equip_or_collect(new /obj/item/clothing/head/pumpkinhead(H), slot_head) + if("medbay", "ride", "wild ride", "cryo") + B.name = "The Wild Ride" + if(H.gender == FEMALE) + J = "Nurse" + else + J = "Doctor" + //Give them basic medical garb + H.equip_or_collect(new /obj/item/clothing/head/surgery/blue(H), slot_head) + H.equip_or_collect(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) + deity_name = "The Chief Medical Officer" + if("busta", "bustatime", "zas", "airflow", "hardcore", "hardcores") + B.name = "The Hardcores" + if(!(M_HARDCORE in H.mutations)) + H.mutations.Add(M_HARDCORE) + J = "Atmospherics Technician" + deity_name = "Bustatime" + if("me", "i", "narcissism", "self importance", "selfishness") + B.name = "The Teachings of [H]" //Quite literally + J = "God" + deity_name = "[H]" //Very literally, too + if("alcohol", "booze", "beer", "wine", "ethanol", "c2h6o") + B.name = "The Drunken Ramblings" + J = "Drunkard" + deity_name = "Hic" + if("robust", "robustness", "strength") + B.name = "The Rules of Robustness" + J = "Robuster" + deity_name = "The Robust" + if("suicide", "death", "succumb") + B.name = "The Sweet Release of Death" + J = "Reaper" + deity_name = "The Grim Reaper" + if("communism", "socialism") + B.name = "The Communist Manifesto" + J = "Komrade" + deity_name = "Karl Max" + H.equip_or_collect(new /obj/item/clothing/head/ushanka(H), slot_head) + if("capitalism", "free market", "liberalism") + B.name = "The Free Market" + J = "Stockholder" + deity_name = "Adam Smith" + H.equip_or_collect(new /obj/item/clothing/head/that(H), slot_head) + if("freedom", "america", "muhrica", "usa") + B.name = "The Constitution" + J = "Senator" + deity_name = "George Washington" + H.equip_or_collect(new /obj/item/clothing/head/libertyhat(H), slot_head) + if("fascism", "nazi", "national socialism") + B.name = "Mein Kampf" + J = "Feldbischof" //No seriously, that's a thing, look it up + deity_name = "Adolf Hitler" + H.equip_or_collect(new /obj/item/clothing/head/naziofficer(H), slot_head) + if("security", "space law", "law", "nanotrasen", "centcomm") + B.name = "Space Law" + J = "Nanotrasen Officer" + deity_name = "Nanotrasen" + H.equip_or_collect(new /obj/item/clothing/head/centhat(H), slot_head) + if("syndicate", "traitor", "syndie", "syndies") + B.name = "The Syndicate Bundle" + J = "Syndicate Agent" + deity_name = "The Syndicate" + H.equip_or_collect(new /obj/item/clothing/head/syndicatefake(H), slot_head) + if("cult", "narsie", "nar'sie", "narnar") + B.name = "The Arcane Tome" + J = "Cultist" + deity_name = "Nar'Sie" + else //Boring, give them a stock name + B.name = "The Holy Book of [new_religion]" + + //This goes down here due to problems with loading orders that took me 4 hours to identify + var/obj/item/weapon/card/id/I = null + if(istype(H.wear_id, /obj/item/weapon/card/id/)) //This prevents people from causing weirdness by putting other things into their slots before chosing their religion + I = H.wear_id + if(I.registered_name == H.real_name) //Makes sure the ID is the chaplain's own + I.assignment = J + I.name = text("[I.registered_name]'s ID Card ([I.assignment])") + var/obj/item/device/pda/P = null + if(istype(H.belt, /obj/item/device/pda)) //This prevents people from causing weirdness by putting other things into their slots before chosing their religion + P = H.belt + if(P.owner == H.real_name) //Makes sure the PDA is the chaplain's own + P.ownjob = J + P.name = text("PDA-[P.owner] ([P.ownjob])") + data_core.manifest_modify(H.real_name, J) //Updates manifest + feedback_set_details("religion_name","[new_religion]") + + //Allow them to change their deity if they believe the deity we gave them sucks + var/new_deity = copytext(sanitize(input(H, "Would you like to change your deity? Your deity currently is [deity_name] (Leave empty or unchanged to keep diety name)", "Name of Deity", deity_name)), 1, MAX_NAME_LEN) + + if(!length(new_deity)) + new_deity = deity_name //Just give them what was picked for them already + B.deity_name = new_deity + + var/accepted = 0 + var/outoftime = 0 + spawn(200) //20 seconds to choose + outoftime = 1 + var/new_book_style = "Bible" + + while(!accepted) + if(!B) + break //Prevents possible runtime errors + new_book_style = input(H, "Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", \ + "the bible melts", "Unaussprechlichen Kulten", "Necronomicon", "Book of Shadows", "Torah", "Burning", "Honk", "Ianism", "The Guide") + switch(new_book_style) + if("Koran") + B.icon_state = "koran" + B.item_state = "koran" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 4 + if("Scrapbook") + B.icon_state = "scrapbook" + B.item_state = "scrapbook" + if("Creeper") + B.icon_state = "creeper" + B.item_state = "syringe_kit" + if("White Bible") + B.icon_state = "white" + B.item_state = "syringe_kit" + if("Holy Light") + B.icon_state = "holylight" + B.item_state = "syringe_kit" + if("Athiest") + B.icon_state = "athiest" + B.item_state = "syringe_kit" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 10 + if("Tome") + B.icon_state = "tome" + B.item_state = "syringe_kit" + if("The King in Yellow") + B.icon_state = "kingyellow" + B.item_state = "kingyellow" + if("Ithaqua") + B.icon_state = "ithaqua" + B.item_state = "ithaqua" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 5 + if("Scientology") + B.icon_state = "scientology" + B.item_state = "scientology" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 8 + if("the bible melts") + B.icon_state = "melted" + B.item_state = "melted" + if("Unaussprechlichen Kulten") + B.icon_state = "kulten" + B.item_state = "kulten" + if("Necronomicon") + B.icon_state = "necronomicon" + B.item_state = "necronomicon" + if("Book of Shadows") + B.icon_state = "shadows" + B.item_state = "shadows" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 6 + if("Torah") + B.icon_state = "torah" + B.item_state = "torah" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 1 + if("Burning") + B.icon_state = "burning" + B.item_state = "syringe_kit" + if("Honk") + B.icon_state = "honkbook" + B.item_state = "honkbook" + if("Ianism") + B.icon_state = "ianism" + B.item_state = "ianism" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 9 + if("The Guide") + B.icon_state = "guide" + B.item_state = "guide" + else + //If christian bible, revert to default + B.icon_state = "bible" + B.item_state = "bible" + for(var/area/chapel/main/A in areas) + for(var/turf/T in A.contents) + if(T.icon_state == "carpetsymbol") + T.dir = 2 + + H.update_inv_l_hand() //So that it updates the bible's item_state in his hand + + switch(input(H, "Look at your bible - is this what you want?") in list("Yes", "No")) + if("Yes") + accepted = 1 + if("No") + if(outoftime) to_chat(H, "Welp, out of time, buddy. You're stuck with that one. Next time choose faster.") - accepted = 1 - - if(ticker) - ticker.Bible_icon_state = B.icon_state - ticker.Bible_item_state = B.item_state - ticker.Bible_name = B.name - ticker.Bible_deity_name = B.deity_name - feedback_set_details("religion_deity","[new_deity]") - feedback_set_details("religion_book","[new_book_style]") - return 1 + accepted = 1 + + if(ticker) + ticker.Bible_icon_state = B.icon_state + ticker.Bible_item_state = B.item_state + ticker.Bible_name = B.name + ticker.Bible_deity_name = B.deity_name + feedback_set_details("religion_deity","[new_deity]") + feedback_set_details("religion_book","[new_book_style]") + return 1 diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index debaaab26e9..1e5a893a093 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -1,169 +1,169 @@ -/datum/job/chief_engineer - title = "Chief Engineer" - flag = CHIEF - department_flag = ENGSEC - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the captain" - selection_color = "#ffeeaa" - idtype = /obj/item/weapon/card/id/ce - req_admin_notify = 1 - access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, - access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, - access_heads, access_construction, access_sec_doors, - access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_mechanic) - minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, - access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, - access_heads, access_construction, access_sec_doors, - access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_mechanic) - minimal_player_age = 7 - - pdaslot=slot_l_store - pdatype=/obj/item/device/pda/heads/ce - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/ce(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform) - //H.equip_or_collect(new /obj/item/device/pda/heads/ce(H), slot_l_store) - H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/head/hardhat/white(H), slot_head) - H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - if(H.backbag == 1) - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) - else - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) - return 1 - - - -/datum/job/engineer - title = "Station Engineer" - flag = ENGINEER - department_flag = ENGSEC - faction = "Station" - total_positions = 5 - spawn_positions = 5 - supervisors = "the chief engineer" - selection_color = "#fff5cc" - idtype = /obj/item/weapon/card/id/engineering - access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics) - minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) - alt_titles = list("Maintenance Technician","Engine Technician","Electrician") - - pdaslot=slot_l_store - pdatype=/obj/item/device/pda/engineering - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_eng(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - switch(H.mind.role_alt_title) - if("Station Engineer") - H.equip_or_collect(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform) - if("Maintenance Technician") - H.equip_or_collect(new /obj/item/clothing/under/rank/maintenance_tech(H), slot_w_uniform) - if("Electrician") - H.equip_or_collect(new /obj/item/clothing/under/rank/electrician(H), slot_w_uniform) - if("Engine Technician") - H.equip_or_collect(new /obj/item/clothing/under/rank/engine_tech(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/orange(H), slot_shoes) - H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/head/hardhat(H), slot_head) - H.equip_or_collect(new /obj/item/device/t_scanner(H), slot_r_store) - //H.equip_or_collect(new /obj/item/device/pda/engineering(H), slot_l_store) - if(H.backbag == 1) - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) - else - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) - return 1 - - - -/datum/job/atmos - title = "Atmospheric Technician" - flag = ATMOSTECH - department_flag = ENGSEC - faction = "Station" - total_positions = 3 - spawn_positions = 2 - supervisors = "the chief engineer" - selection_color = "#fff5cc" - idtype = /obj/item/weapon/card/id/engineering - access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics) - minimal_access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction, access_engine_equip, access_external_airlocks) - - pdaslot=slot_l_store - pdatype=/obj/item/device/pda/atmos - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_eng(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/atmospheric_technician(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/atmos(H), slot_l_store) - H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/atmostech(H), slot_belt) - if(H.backbag == 1) - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) - else - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) - return 1 - -/datum/job/mechanic - title = "Mechanic" - flag = MECHANIC - department_flag = ENGSEC - faction = "Station" - total_positions = 3 - spawn_positions = 2 - supervisors = "the research director and the chief engineer" - selection_color = "#fff5cc" - idtype = /obj/item/weapon/card/id/engineering - access = list(access_eva, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_mechanic, access_tcomsat, access_research) - minimal_access = list(access_maint_tunnels, access_emergency_storage, access_construction, access_engine_equip, access_external_airlocks, access_mechanic, access_research) - alt_titles = list("Telecommunications Technician", "Spacepod Mechanic", "Greasemonkey") - - pdaslot=slot_l_store - pdatype=/obj/item/device/pda/mechanic - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_engsci(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/mechanic(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/atmos(H), slot_l_store) - H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/complete(H), slot_belt) - if(!(H.flags&DISABILITY_FLAG_NEARSIGHTED)) //Does this work? - var/obj/item/clothing/glasses/welding/W = new (H) - H.equip_or_collect(W, slot_glasses) - W.toggle() - else - var/obj/item/clothing/head/welding/W = new (H) - H.equip_or_collect(W, slot_head) - W.toggle() - if(H.backbag == 1) - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) - else - H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) +/datum/job/chief_engineer + title = "Chief Engineer" + flag = CHIEF + department_flag = ENGSEC + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the captain" + selection_color = "#ffeeaa" + idtype = /obj/item/weapon/card/id/ce + req_admin_notify = 1 + access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, + access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, + access_heads, access_construction, access_sec_doors, + access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_mechanic) + minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, + access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, + access_heads, access_construction, access_sec_doors, + access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_mechanic) + minimal_player_age = 7 + + pdaslot=slot_l_store + pdatype=/obj/item/device/pda/heads/ce + + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/heads/ce(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform) + //H.equip_or_collect(new /obj/item/device/pda/heads/ce(H), slot_l_store) + H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/head/hardhat/white(H), slot_head) + H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + if(H.backbag == 1) + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) + else + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) + return 1 + + + +/datum/job/engineer + title = "Station Engineer" + flag = ENGINEER + department_flag = ENGSEC + faction = "Station" + total_positions = 5 + spawn_positions = 5 + supervisors = "the chief engineer" + selection_color = "#fff5cc" + idtype = /obj/item/weapon/card/id/engineering + access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics) + minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) + alt_titles = list("Maintenance Technician","Engine Technician","Electrician") + + pdaslot=slot_l_store + pdatype=/obj/item/device/pda/engineering + + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_eng(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + switch(H.mind.role_alt_title) + if("Station Engineer") + H.equip_or_collect(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform) + if("Maintenance Technician") + H.equip_or_collect(new /obj/item/clothing/under/rank/maintenance_tech(H), slot_w_uniform) + if("Electrician") + H.equip_or_collect(new /obj/item/clothing/under/rank/electrician(H), slot_w_uniform) + if("Engine Technician") + H.equip_or_collect(new /obj/item/clothing/under/rank/engine_tech(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/orange(H), slot_shoes) + H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/head/hardhat(H), slot_head) + H.equip_or_collect(new /obj/item/device/t_scanner(H), slot_r_store) + //H.equip_or_collect(new /obj/item/device/pda/engineering(H), slot_l_store) + if(H.backbag == 1) + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) + else + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) + return 1 + + + +/datum/job/atmos + title = "Atmospheric Technician" + flag = ATMOSTECH + department_flag = ENGSEC + faction = "Station" + total_positions = 3 + spawn_positions = 2 + supervisors = "the chief engineer" + selection_color = "#fff5cc" + idtype = /obj/item/weapon/card/id/engineering + access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics) + minimal_access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction, access_engine_equip, access_external_airlocks) + + pdaslot=slot_l_store + pdatype=/obj/item/device/pda/atmos + + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_eng(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/atmospheric_technician(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/atmos(H), slot_l_store) + H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/atmostech(H), slot_belt) + if(H.backbag == 1) + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) + else + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) + return 1 + +/datum/job/mechanic + title = "Mechanic" + flag = MECHANIC + department_flag = ENGSEC + faction = "Station" + total_positions = 3 + spawn_positions = 2 + supervisors = "the research director and the chief engineer" + selection_color = "#fff5cc" + idtype = /obj/item/weapon/card/id/engineering + access = list(access_eva, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_mechanic, access_tcomsat, access_research) + minimal_access = list(access_maint_tunnels, access_emergency_storage, access_construction, access_engine_equip, access_external_airlocks, access_mechanic, access_research) + alt_titles = list("Telecommunications Technician", "Spacepod Mechanic", "Greasemonkey") + + pdaslot=slot_l_store + pdatype=/obj/item/device/pda/mechanic + + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_engsci(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_eng(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/mechanic(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/atmos(H), slot_l_store) + H.equip_or_collect(new /obj/item/weapon/storage/belt/utility/complete(H), slot_belt) + if(!(H.flags&DISABILITY_FLAG_NEARSIGHTED)) //Does this work? + var/obj/item/clothing/glasses/welding/W = new (H) + H.equip_or_collect(W, slot_glasses) + W.toggle() + else + var/obj/item/clothing/head/welding/W = new (H) + H.equip_or_collect(W, slot_head) + W.toggle() + if(H.backbag == 1) + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand) + else + H.equip_or_collect(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack) return 1 \ No newline at end of file diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index ae2d89ee473..ba7d303ff87 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -1,77 +1,77 @@ -/datum/job - - //The name of the job - var/title = "NOPE" - - //Job access. The use of minimal_access or access is determined by a config setting: config.jobs_have_minimal_access - var/list/minimal_access = list() //Useful for servers which prefer to only have access given to the places a job absolutely needs (Larger server population) - var/list/access = list() //Useful for servers which either have fewer players, so each person needs to fill more than one role, or servers which like to give more access, so players can't hide forever in their super secure departments (I'm looking at you, chemistry!) - - //Bitflags for the job - var/flag = 0 - var/info_flag = 0 - var/department_flag = 0 - - //Players will be allowed to spawn in as jobs that are set to "Station" - var/faction = "None" - - //How many players can be this job - var/total_positions = 0 - - //How many players can spawn in as this job - var/spawn_positions = 0 - - //How many players have this job - var/current_positions = 0 - - //Supervisors, who this person answers to directly - var/supervisors = "" - - //Sellection screen color - var/selection_color = "#ffffff" - - //the type of the ID the player will have - var/idtype = /obj/item/weapon/card/id - - //List of alternate titles, if any - var/list/alt_titles - - //If this is set to 1, a text is printed to the player when jobs are assigned, telling him that he should let admins know that he has to disconnect. - var/req_admin_notify - - //If you have use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.) - var/minimal_player_age = 0 +/datum/job + + //The name of the job + var/title = "NOPE" + + //Job access. The use of minimal_access or access is determined by a config setting: config.jobs_have_minimal_access + var/list/minimal_access = list() //Useful for servers which prefer to only have access given to the places a job absolutely needs (Larger server population) + var/list/access = list() //Useful for servers which either have fewer players, so each person needs to fill more than one role, or servers which like to give more access, so players can't hide forever in their super secure departments (I'm looking at you, chemistry!) + + //Bitflags for the job + var/flag = 0 + var/info_flag = 0 + var/department_flag = 0 + + //Players will be allowed to spawn in as jobs that are set to "Station" + var/faction = "None" + + //How many players can be this job + var/total_positions = 0 + + //How many players can spawn in as this job + var/spawn_positions = 0 + + //How many players have this job + var/current_positions = 0 + + //Supervisors, who this person answers to directly + var/supervisors = "" + + //Sellection screen color + var/selection_color = "#ffffff" + + //the type of the ID the player will have + var/idtype = /obj/item/weapon/card/id + + //List of alternate titles, if any + var/list/alt_titles + + //If this is set to 1, a text is printed to the player when jobs are assigned, telling him that he should let admins know that he has to disconnect. + var/req_admin_notify + + //If you have use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.) + var/minimal_player_age = 0 + + var/pdatype=/obj/item/device/pda + var/pdaslot=slot_belt + +/datum/job/proc/equip(var/mob/living/carbon/human/H) + return 1 + +/datum/job/proc/get_access() + if(!config) //Needed for robots. + return src.minimal_access.Copy() + + if(config.jobs_have_minimal_access) + return src.minimal_access.Copy() + else + return src.access.Copy() + +//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 +/datum/job/proc/player_old_enough(client/C) + if(available_in_days(C) == 0) + return 1 //Available in 0 days = available right now = player is old enough to play. + return 0 + + +/datum/job/proc/available_in_days(client/C) + if(!C) + return 0 + if(!config.use_age_restriction_for_jobs) + return 0 + if(!isnum(C.player_age)) + return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced + if(!isnum(minimal_player_age)) + return 0 - var/pdatype=/obj/item/device/pda - var/pdaslot=slot_belt - -/datum/job/proc/equip(var/mob/living/carbon/human/H) - return 1 - -/datum/job/proc/get_access() - if(!config) //Needed for robots. - return src.minimal_access.Copy() - - if(config.jobs_have_minimal_access) - return src.minimal_access.Copy() - else - return src.access.Copy() - -//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 -/datum/job/proc/player_old_enough(client/C) - if(available_in_days(C) == 0) - return 1 //Available in 0 days = available right now = player is old enough to play. - return 0 - - -/datum/job/proc/available_in_days(client/C) - if(!C) - return 0 - if(!config.use_age_restriction_for_jobs) - return 0 - if(!isnum(C.player_age)) - return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced - if(!isnum(minimal_player_age)) - return 0 - return max(0, minimal_player_age - C.player_age) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 45c43369065..486faef5d61 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -1,250 +1,250 @@ -/datum/job/cmo - title = "Chief Medical Officer" - flag = CMO - department_flag = MEDSCI - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the captain" - selection_color = "#ffddf0" - idtype = /obj/item/weapon/card/id/cmo - req_admin_notify = 1 - access = list(access_medical, access_morgue, access_genetics, access_heads, - access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, - access_keycard_auth, access_sec_doors, access_paramedic, access_eva) - minimal_access = list(access_medical, access_morgue, access_genetics, access_heads, - access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, - access_keycard_auth, access_sec_doors, access_paramedic) - minimal_player_age = 7 - - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/heads/cmo - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/cmo(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/chief_medical_officer(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/heads/cmo(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/cmo(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand) - H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/datum/job/doctor - title = "Medical Doctor" - flag = DOCTOR - department_flag = MEDSCI - faction = "Station" - total_positions = 5 - spawn_positions = 3 - supervisors = "the chief medical officer" - selection_color = "#ffeef0" - idtype = /obj/item/weapon/card/id/medical - access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_eva) - minimal_access = list(access_medical, access_morgue, access_surgery, access_virology) - alt_titles = list("Surgeon","Emergency Physician","Nurse","Virologist") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/medical - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) - if(H.mind.role_alt_title=="Virologist") - H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_vir) - else - H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - if (H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Emergency Physician") - H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/storage/fr_jacket(H), slot_wear_suit) - if("Surgeon") - H.equip_or_collect(new /obj/item/clothing/under/rank/medical/blue(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/head/surgery/blue(H), slot_head) - if("Virologist") - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) - if("Medical Doctor") - H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - - if("Nurse") - if(H.gender == FEMALE) - if(prob(50)) - H.equip_or_collect(new /obj/item/clothing/under/rank/nursesuit(H), slot_w_uniform) - else - H.equip_or_collect(new /obj/item/clothing/under/rank/nurse(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/head/nursehat(H), slot_head) - else - H.equip_or_collect(new /obj/item/clothing/under/rank/medical/purple(H), slot_w_uniform) - else - H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/medical(H), slot_belt) - H.equip_or_collect(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand) - H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -//Chemist is a medical job damnit //YEAH FUCK YOU SCIENCE -Pete //Guys, behave -Erro -/datum/job/chemist - title = "Chemist" - flag = CHEMIST - department_flag = MEDSCI - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "the chief medical officer" - selection_color = "#ffeef0" - idtype = /obj/item/weapon/card/id/medical - access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_eva) - minimal_access = list(access_medical, access_chemistry) - alt_titles = list("Pharmacist") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/chemist - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_chem(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - switch(H.mind.role_alt_title) - if("Chemist") - H.equip_or_collect(new /obj/item/clothing/under/rank/chemist(H), slot_w_uniform) - if("Pharmacist") - H.equip_or_collect(new /obj/item/clothing/under/rank/pharma(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/chemist(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/chemist(H), slot_wear_suit) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - -/datum/job/geneticist - title = "Geneticist" - flag = GENETICIST - department_flag = MEDSCI - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "the chief medical officer and research director" - selection_color = "#ffeef0" - idtype = /obj/item/weapon/card/id/medical - access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_research, access_eva) - minimal_access = list(access_medical, access_morgue, access_genetics, access_research) - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/geneticist - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_gen(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/device/radio/headset/headset_medsci(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/under/rank/geneticist(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/geneticist(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/genetics(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - -/*/datum/job/virologist - title = "Virologist" - flag = VIROLOGIST - department_flag = MEDSCI - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the chief medical officer" - selection_color = "#ffeef0" - access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics) - minimal_access = list(access_medical, access_virology) - alt_titles = list("Pathologist","Microbiologist") - - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/device/pda/viro(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - -/datum/job/psychiatrist - title = "Psychiatrist" - flag = PSYCHIATRIST - department_flag = MEDSCI - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the chief medical officer" - selection_color = "#ffeef0" - access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_psychiatrist) - minimal_access = list(access_medical, access_psychiatrist) - alt_titles = list("Psychologist") - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/device/pda/medical(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 +/datum/job/cmo + title = "Chief Medical Officer" + flag = CMO + department_flag = MEDSCI + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the captain" + selection_color = "#ffddf0" + idtype = /obj/item/weapon/card/id/cmo + req_admin_notify = 1 + access = list(access_medical, access_morgue, access_genetics, access_heads, + access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, + access_keycard_auth, access_sec_doors, access_paramedic, access_eva) + minimal_access = list(access_medical, access_morgue, access_genetics, access_heads, + access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, + access_keycard_auth, access_sec_doors, access_paramedic) + minimal_player_age = 7 + + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/heads/cmo + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/heads/cmo(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/chief_medical_officer(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/heads/cmo(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/cmo(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand) + H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/datum/job/doctor + title = "Medical Doctor" + flag = DOCTOR + department_flag = MEDSCI + faction = "Station" + total_positions = 5 + spawn_positions = 3 + supervisors = "the chief medical officer" + selection_color = "#ffeef0" + idtype = /obj/item/weapon/card/id/medical + access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_eva) + minimal_access = list(access_medical, access_morgue, access_surgery, access_virology) + alt_titles = list("Surgeon","Emergency Physician","Nurse","Virologist") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/medical + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) + if(H.mind.role_alt_title=="Virologist") + H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_vir) + else + H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if (H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Emergency Physician") + H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/storage/fr_jacket(H), slot_wear_suit) + if("Surgeon") + H.equip_or_collect(new /obj/item/clothing/under/rank/medical/blue(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/head/surgery/blue(H), slot_head) + if("Virologist") + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) + if("Medical Doctor") + H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + + if("Nurse") + if(H.gender == FEMALE) + if(prob(50)) + H.equip_or_collect(new /obj/item/clothing/under/rank/nursesuit(H), slot_w_uniform) + else + H.equip_or_collect(new /obj/item/clothing/under/rank/nurse(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/head/nursehat(H), slot_head) + else + H.equip_or_collect(new /obj/item/clothing/under/rank/medical/purple(H), slot_w_uniform) + else + H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/medical(H), slot_belt) + H.equip_or_collect(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand) + H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +//Chemist is a medical job damnit //YEAH FUCK YOU SCIENCE -Pete //Guys, behave -Erro +/datum/job/chemist + title = "Chemist" + flag = CHEMIST + department_flag = MEDSCI + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "the chief medical officer" + selection_color = "#ffeef0" + idtype = /obj/item/weapon/card/id/medical + access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_eva) + minimal_access = list(access_medical, access_chemistry) + alt_titles = list("Pharmacist") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/chemist + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_chem(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + switch(H.mind.role_alt_title) + if("Chemist") + H.equip_or_collect(new /obj/item/clothing/under/rank/chemist(H), slot_w_uniform) + if("Pharmacist") + H.equip_or_collect(new /obj/item/clothing/under/rank/pharma(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/chemist(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/chemist(H), slot_wear_suit) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + +/datum/job/geneticist + title = "Geneticist" + flag = GENETICIST + department_flag = MEDSCI + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "the chief medical officer and research director" + selection_color = "#ffeef0" + idtype = /obj/item/weapon/card/id/medical + access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_research, access_eva) + minimal_access = list(access_medical, access_morgue, access_genetics, access_research) + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/geneticist + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_gen(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/device/radio/headset/headset_medsci(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/under/rank/geneticist(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/geneticist(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/genetics(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + +/*/datum/job/virologist + title = "Virologist" + flag = VIROLOGIST + department_flag = MEDSCI + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the chief medical officer" + selection_color = "#ffeef0" + access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics) + minimal_access = list(access_medical, access_virology) + alt_titles = list("Pathologist","Microbiologist") + + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/device/pda/viro(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + +/datum/job/psychiatrist + title = "Psychiatrist" + flag = PSYCHIATRIST + department_flag = MEDSCI + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the chief medical officer" + selection_color = "#ffeef0" + access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_psychiatrist) + minimal_access = list(access_medical, access_psychiatrist) + alt_titles = list("Psychologist") + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_med(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_med(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/device/pda/medical(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/device/flashlight/pen(H), slot_s_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 */ \ No newline at end of file diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 742f0640516..a7ef30dc0d5 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -1,130 +1,130 @@ -/datum/job/rd - title = "Research Director" - flag = RD - department_flag = MEDSCI - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the captain" - selection_color = "#ffddff" - idtype = /obj/item/weapon/card/id/rd - req_admin_notify = 1 - access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, - access_tox_storage, access_teleporter, access_sec_doors, - access_research, access_robotics, access_xenobiology, access_ai_upload, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_mechanic) - minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, - access_tox_storage, access_teleporter, access_sec_doors, - access_research, access_robotics, access_xenobiology, access_ai_upload, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_mechanic) - minimal_player_age = 7 - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/heads/rd - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/rd(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/under/rank/research_director(H), slot_w_uniform) - //H.equip_or_collect(new /obj/item/device/pda/heads/rd(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/weapon/clipboard(H), slot_l_hand) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -/datum/job/scientist - title = "Scientist" - flag = SCIENTIST - department_flag = MEDSCI - faction = "Station" - total_positions = 5 - spawn_positions = 3 - supervisors = "the research director" - selection_color = "#ffeeff" - idtype = /obj/item/weapon/card/id/research - access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology) - minimal_access = list(access_tox, access_tox_storage, access_research, access_xenobiology) - alt_titles = list("Xenoarcheologist", "Anomalist", "Plasma Researcher", "Xenobiologist", "Research Botanist") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/toxins - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - if(H.mind.role_alt_title == "Research Botanist") - H.equip_or_collect(new /obj/item/device/radio/headset/headset_servsci(H), slot_ears) - else - H.equip_or_collect(new /obj/item/device/radio/headset/headset_sci(H), slot_ears) - switch(H.mind.role_alt_title) - if("Scientist") - H.equip_or_collect(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) - if("Plasma Researcher") - H.equip_or_collect(new /obj/item/clothing/under/rank/plasmares(H), slot_w_uniform) - if(H.backbag==3) - H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_tox(H), slot_back) - if("Xenobiologist") - H.equip_or_collect(new /obj/item/clothing/under/rank/xenobio(H), slot_w_uniform) - if("Anomalist") - H.equip_or_collect(new /obj/item/clothing/under/rank/anomalist(H), slot_w_uniform) - if("Xenoarcheologist") - H.equip_or_collect(new /obj/item/clothing/under/rank/xenoarch(H), slot_w_uniform) - if("Research Botanist") - H.equip_or_collect(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store) - H.equip_or_collect(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/toxins(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 - - - -/datum/job/roboticist - title = "Roboticist" - flag = ROBOTICIST - department_flag = MEDSCI - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "research director" - selection_color = "#ffeeff" - idtype = /obj/item/weapon/card/id/research - access = list(access_robotics, access_tox, access_tox_storage, access_tech_storage, access_morgue, access_research) //As a job that handles so many corpses, it makes sense for them to have morgue access. - minimal_access = list(access_robotics, access_tech_storage, access_morgue, access_research) //As a job that handles so many corpses, it makes sense for them to have morgue access. - alt_titles = list("Biomechanical Engineer","Mechatronic Engineer") - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/roboticist - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_sci(H), slot_ears) - if(H.backbag == 2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(H.backbag == 3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - switch(H.mind.role_alt_title) - if("Roboticist") - H.equip_or_collect(new /obj/item/clothing/under/rank/roboticist(H), slot_w_uniform) - if("Mechatronic Engineer") - H.equip_or_collect(new /obj/item/clothing/under/rank/mechatronic(H), slot_w_uniform) - if("Biomechanical Engineer") - H.equip_or_collect(new /obj/item/clothing/under/rank/biomechanical(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/roboticist(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) -// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/weapon/storage/toolbox/mechanical(H), slot_l_hand) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - return 1 +/datum/job/rd + title = "Research Director" + flag = RD + department_flag = MEDSCI + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the captain" + selection_color = "#ffddff" + idtype = /obj/item/weapon/card/id/rd + req_admin_notify = 1 + access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, + access_tox_storage, access_teleporter, access_sec_doors, + access_research, access_robotics, access_xenobiology, access_ai_upload, + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_mechanic) + minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, + access_tox_storage, access_teleporter, access_sec_doors, + access_research, access_robotics, access_xenobiology, access_ai_upload, + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_mechanic) + minimal_player_age = 7 + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/heads/rd + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/heads/rd(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/under/rank/research_director(H), slot_w_uniform) + //H.equip_or_collect(new /obj/item/device/pda/heads/rd(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/weapon/clipboard(H), slot_l_hand) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +/datum/job/scientist + title = "Scientist" + flag = SCIENTIST + department_flag = MEDSCI + faction = "Station" + total_positions = 5 + spawn_positions = 3 + supervisors = "the research director" + selection_color = "#ffeeff" + idtype = /obj/item/weapon/card/id/research + access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology) + minimal_access = list(access_tox, access_tox_storage, access_research, access_xenobiology) + alt_titles = list("Xenoarcheologist", "Anomalist", "Plasma Researcher", "Xenobiologist", "Research Botanist") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/toxins + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + if(H.mind.role_alt_title == "Research Botanist") + H.equip_or_collect(new /obj/item/device/radio/headset/headset_servsci(H), slot_ears) + else + H.equip_or_collect(new /obj/item/device/radio/headset/headset_sci(H), slot_ears) + switch(H.mind.role_alt_title) + if("Scientist") + H.equip_or_collect(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) + if("Plasma Researcher") + H.equip_or_collect(new /obj/item/clothing/under/rank/plasmares(H), slot_w_uniform) + if(H.backbag==3) + H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_tox(H), slot_back) + if("Xenobiologist") + H.equip_or_collect(new /obj/item/clothing/under/rank/xenobio(H), slot_w_uniform) + if("Anomalist") + H.equip_or_collect(new /obj/item/clothing/under/rank/anomalist(H), slot_w_uniform) + if("Xenoarcheologist") + H.equip_or_collect(new /obj/item/clothing/under/rank/xenoarch(H), slot_w_uniform) + if("Research Botanist") + H.equip_or_collect(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store) + H.equip_or_collect(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/shoes/white(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/toxins(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 + + + +/datum/job/roboticist + title = "Roboticist" + flag = ROBOTICIST + department_flag = MEDSCI + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "research director" + selection_color = "#ffeeff" + idtype = /obj/item/weapon/card/id/research + access = list(access_robotics, access_tox, access_tox_storage, access_tech_storage, access_morgue, access_research) //As a job that handles so many corpses, it makes sense for them to have morgue access. + minimal_access = list(access_robotics, access_tech_storage, access_morgue, access_research) //As a job that handles so many corpses, it makes sense for them to have morgue access. + alt_titles = list("Biomechanical Engineer","Mechatronic Engineer") + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/roboticist + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_sci(H), slot_ears) + if(H.backbag == 2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(H.backbag == 3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) + switch(H.mind.role_alt_title) + if("Roboticist") + H.equip_or_collect(new /obj/item/clothing/under/rank/roboticist(H), slot_w_uniform) + if("Mechatronic Engineer") + H.equip_or_collect(new /obj/item/clothing/under/rank/mechatronic(H), slot_w_uniform) + if("Biomechanical Engineer") + H.equip_or_collect(new /obj/item/clothing/under/rank/biomechanical(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/roboticist(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) +// H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_or_collect(new /obj/item/weapon/storage/toolbox/mechanical(H), slot_l_hand) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + return 1 diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 3094c433522..536d5844303 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -1,209 +1,209 @@ -/datum/job/hos - title = "Head of Security" - flag = HOS - department_flag = ENGSEC - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the captain" - selection_color = "#ffdddd" - idtype = /obj/item/weapon/card/id/hos - req_admin_notify = 1 - access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, - access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, - access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, - access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_eva) - minimal_access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, - access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, - access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, - access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway) - minimal_player_age = 14 - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/heads/hos - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/device/radio/headset/heads/hos(H), slot_ears) - H.equip_or_collect(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/heads/hos(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) -// H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk - H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) - H.equip_or_collect(new /obj/item/clothing/suit/armor/hos/jensen(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/weapon/gun/energy/gun(H), slot_s_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_l_store) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_in_backpack) - var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) - L.imp_in = H - L.implanted = 1 - var/datum/organ/external/affected = H.get_organ("head") - affected.implants += L - L.part = affected - return 1 - - - -/datum/job/warden - title = "Warden" - flag = WARDEN - department_flag = ENGSEC - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of security" - selection_color = "#ffeeee" - idtype = /obj/item/weapon/card/id/security - access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels, access_morgue, access_eva) - minimal_access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels) - minimal_player_age = 7 - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/warden - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/warden(H), slot_belt) - H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) -// H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk - H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_l_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_in_backpack) - var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) - L.imp_in = H - L.implanted = 1 - var/datum/organ/external/affected = H.get_organ("head") - affected.implants += L - L.part = affected - return 1 - - - -/datum/job/detective - title = "Detective" - flag = DETECTIVE - department_flag = ENGSEC - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of security" - selection_color = "#ffeeee" - idtype = /obj/item/weapon/card/id/security - - access = list(access_weapons, access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_eva) - minimal_access = list(access_weapons, access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court) - alt_titles = list("Forensic Technician") - - minimal_player_age = 7 - - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/detective - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/det(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) - //H.equip_or_collect(new /obj/item/device/pda/detective(H), slot_belt) -/* var/obj/item/clothing/mask/cigarette/CIG = new /obj/item/clothing/mask/cigarette(H) - CIG.light("") - H.equip_or_collect(CIG, slot_wear_mask) */ - H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - if(H.mind.role_alt_title && H.mind.role_alt_title == "Forensic Technician") - H.equip_or_collect(new /obj/item/clothing/suit/storage/forensics/blue(H), slot_wear_suit) - else - H.equip_or_collect(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/clothing/head/det_hat(H), slot_head) - H.equip_or_collect(new /obj/item/weapon/lighter/zippo(H), slot_l_store) - - if(H.backbag == 1)//Why cant some of these things spawn in his office? - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - H.equip_or_collect(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) - H.equip_or_collect(new /obj/item/device/detective_scanner(H), slot_r_store) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/device/detective_scanner(H), slot_in_backpack) - var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) - L.imp_in = H - L.implanted = 1 - var/datum/organ/external/affected = H.get_organ("head") - affected.implants += L - L.part = affected - H.dna.SetSEState(SOBERBLOCK,1) - H.mutations += M_SOBER - H.check_mutations = 1 - return 1 - - - -/datum/job/officer - title = "Security Officer" - flag = OFFICER - department_flag = ENGSEC - faction = "Station" - total_positions = 5 - spawn_positions = 5 - supervisors = "the head of security" - selection_color = "#ffeeee" - idtype = /obj/item/weapon/card/id/security - access = list(access_weapons, access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_morgue, access_eva) - minimal_access = list(access_weapons, access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels) - minimal_player_age = 7 - - pdaslot=slot_belt - pdatype=/obj/item/device/pda/security - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec(H), slot_ears) - switch(H.backbag) - if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) - if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) - if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_or_collect(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/suit/armor/vest/security(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/weapon/gun/energy/taser(H), slot_s_store) - //H.equip_or_collect(new /obj/item/device/pda/security(H), slot_belt) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_in_backpack) - H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) - if(H.backbag == 1) - H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) - else - H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) - H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) - var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) - L.imp_in = H - L.implanted = 1 - var/datum/organ/external/affected = H.get_organ("head") - affected.implants += L - L.part = affected - return 1 +/datum/job/hos + title = "Head of Security" + flag = HOS + department_flag = ENGSEC + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the captain" + selection_color = "#ffdddd" + idtype = /obj/item/weapon/card/id/hos + req_admin_notify = 1 + access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, + access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, + access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, + access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_eva) + minimal_access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, + access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, + access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, + access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway) + minimal_player_age = 14 + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/heads/hos + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/device/radio/headset/heads/hos(H), slot_ears) + H.equip_or_collect(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/heads/hos(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) +// H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk + H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) + H.equip_or_collect(new /obj/item/clothing/suit/armor/hos/jensen(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/weapon/gun/energy/gun(H), slot_s_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_l_store) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_in_backpack) + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) + L.imp_in = H + L.implanted = 1 + var/datum/organ/external/affected = H.get_organ("head") + affected.implants += L + L.part = affected + return 1 + + + +/datum/job/warden + title = "Warden" + flag = WARDEN + department_flag = ENGSEC + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of security" + selection_color = "#ffeeee" + idtype = /obj/item/weapon/card/id/security + access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels, access_morgue, access_eva) + minimal_access = list(access_weapons, access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels) + minimal_player_age = 7 + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/warden + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/warden(H), slot_belt) + H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) +// H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk + H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_l_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_in_backpack) + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) + L.imp_in = H + L.implanted = 1 + var/datum/organ/external/affected = H.get_organ("head") + affected.implants += L + L.part = affected + return 1 + + + +/datum/job/detective + title = "Detective" + flag = DETECTIVE + department_flag = ENGSEC + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of security" + selection_color = "#ffeeee" + idtype = /obj/item/weapon/card/id/security + + access = list(access_weapons, access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_eva) + minimal_access = list(access_weapons, access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court) + alt_titles = list("Forensic Technician") + + minimal_player_age = 7 + + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/detective + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/det(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/brown(H), slot_shoes) + //H.equip_or_collect(new /obj/item/device/pda/detective(H), slot_belt) +/* var/obj/item/clothing/mask/cigarette/CIG = new /obj/item/clothing/mask/cigarette(H) + CIG.light("") + H.equip_or_collect(CIG, slot_wear_mask) */ + H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + if(H.mind.role_alt_title && H.mind.role_alt_title == "Forensic Technician") + H.equip_or_collect(new /obj/item/clothing/suit/storage/forensics/blue(H), slot_wear_suit) + else + H.equip_or_collect(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/head/det_hat(H), slot_head) + H.equip_or_collect(new /obj/item/weapon/lighter/zippo(H), slot_l_store) + + if(H.backbag == 1)//Why cant some of these things spawn in his office? + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + H.equip_or_collect(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) + H.equip_or_collect(new /obj/item/device/detective_scanner(H), slot_r_store) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/device/detective_scanner(H), slot_in_backpack) + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) + L.imp_in = H + L.implanted = 1 + var/datum/organ/external/affected = H.get_organ("head") + affected.implants += L + L.part = affected + H.dna.SetSEState(SOBERBLOCK,1) + H.mutations += M_SOBER + H.check_mutations = 1 + return 1 + + + +/datum/job/officer + title = "Security Officer" + flag = OFFICER + department_flag = ENGSEC + faction = "Station" + total_positions = 5 + spawn_positions = 5 + supervisors = "the head of security" + selection_color = "#ffeeee" + idtype = /obj/item/weapon/card/id/security + access = list(access_weapons, access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_morgue, access_eva) + minimal_access = list(access_weapons, access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels) + minimal_player_age = 7 + + pdaslot=slot_belt + pdatype=/obj/item/device/pda/security + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec(H), slot_ears) + switch(H.backbag) + if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) + if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) + if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_or_collect(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/suit/armor/vest/security(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/weapon/gun/energy/taser(H), slot_s_store) + //H.equip_or_collect(new /obj/item/device/pda/security(H), slot_belt) + H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) + if(H.backbag == 1) + H.equip_or_collect(new H.species.survival_gear(H), slot_r_hand) + else + H.equip_or_collect(new H.species.survival_gear(H.back), slot_in_backpack) + H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) + L.imp_in = H + L.implanted = 1 + var/datum/organ/external/affected = H.get_organ("head") + affected.implants += L + L.part = affected + return 1 diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 83bc53f65a4..1bab22c9853 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -1,46 +1,46 @@ -/datum/job/ai - title = "AI" - flag = AI - info_flag = JINFO_SILICON - department_flag = ENGSEC - faction = "Station" - total_positions = 0 - spawn_positions = 1 - selection_color = "#ccffcc" - supervisors = "your laws" - req_admin_notify = 2 - minimal_player_age = 30 - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - return 1 - -/datum/job/cyborg - title = "Cyborg" - flag = CYBORG - info_flag = JINFO_SILICON - department_flag = ENGSEC - faction = "Station" - total_positions = 0 - spawn_positions = 2 - supervisors = "your laws and the AI" //Nodrak - selection_color = "#ddffdd" - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - return 1 - -/datum/job/mommi - title = "Mobile MMI" - flag = MOMMI - info_flag = JINFO_SILICON - department_flag = ENGSEC - faction = "Station" - total_positions = 0 - spawn_positions = 2 - supervisors = "your laws and the AI" //Nodrak - selection_color = "#ddffdd" - - equip(var/mob/living/carbon/human/H) - if(!H) return 0 - return 1 +/datum/job/ai + title = "AI" + flag = AI + info_flag = JINFO_SILICON + department_flag = ENGSEC + faction = "Station" + total_positions = 0 + spawn_positions = 1 + selection_color = "#ccffcc" + supervisors = "your laws" + req_admin_notify = 2 + minimal_player_age = 30 + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + return 1 + +/datum/job/cyborg + title = "Cyborg" + flag = CYBORG + info_flag = JINFO_SILICON + department_flag = ENGSEC + faction = "Station" + total_positions = 0 + spawn_positions = 2 + supervisors = "your laws and the AI" //Nodrak + selection_color = "#ddffdd" + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + return 1 + +/datum/job/mommi + title = "Mobile MMI" + flag = MOMMI + info_flag = JINFO_SILICON + department_flag = ENGSEC + faction = "Station" + total_positions = 0 + spawn_positions = 2 + supervisors = "your laws and the AI" //Nodrak + selection_color = "#ddffdd" + + equip(var/mob/living/carbon/human/H) + if(!H) return 0 + return 1 diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index b78b09267d9..b205d59febd 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -1,566 +1,566 @@ -var/global/datum/controller/occupations/job_master - -#define GET_RANDOM_JOB 0 -#define BE_ASSISTANT 1 -#define RETURN_TO_LOBBY 2 - -/datum/controller/occupations - //List of all jobs - var/list/occupations = list() - //Players who need jobs - var/list/unassigned = list() - //Debug info - var/list/job_debug = list() - - -/datum/controller/occupations/proc/SetupOccupations(var/faction = "Station") - occupations = list() - var/list/all_jobs = typesof(/datum/job) - if(!all_jobs.len) +var/global/datum/controller/occupations/job_master + +#define GET_RANDOM_JOB 0 +#define BE_ASSISTANT 1 +#define RETURN_TO_LOBBY 2 + +/datum/controller/occupations + //List of all jobs + var/list/occupations = list() + //Players who need jobs + var/list/unassigned = list() + //Debug info + var/list/job_debug = list() + + +/datum/controller/occupations/proc/SetupOccupations(var/faction = "Station") + occupations = list() + var/list/all_jobs = typesof(/datum/job) + if(!all_jobs.len) to_chat(world, "Error setting up jobs, no job datums found") - return 0 - for(var/J in all_jobs) - var/datum/job/job = new J() - if(!job) continue - if(job.faction != faction) continue - occupations += job - - - return 1 - - -/datum/controller/occupations/proc/Debug(var/text) - if(!Debug2) return 0 - job_debug.Add(text) - return 1 - - -/datum/controller/occupations/proc/GetJob(var/rank) - if(!rank) return null - for(var/datum/job/J in occupations) - if(!J) continue - if(J.title == rank) return J - return null - -/datum/controller/occupations/proc/GetPlayerAltTitle(mob/new_player/player, rank) - return player.client.prefs.GetPlayerAltTitle(GetJob(rank)) - -/datum/controller/occupations/proc/AssignRole(var/mob/new_player/player, var/rank, var/latejoin = 0) - Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]") - if(player && player.mind && rank) - var/datum/job/job = GetJob(rank) - if(!job) return 0 - if(jobban_isbanned(player, rank)) return 0 - if(!job.player_old_enough(player.client)) return 0 - var/position_limit = job.total_positions - if(!latejoin) - position_limit = job.spawn_positions - if((job.current_positions < position_limit) || position_limit == -1) - Debug("Player: [player] is now Rank: [rank], JCP:[job.current_positions], JPL:[position_limit]") - player.mind.assigned_role = rank - player.mind.role_alt_title = GetPlayerAltTitle(player, rank) - - unassigned -= player - job.current_positions++ - return 1 - Debug("AR has failed, Player: [player], Rank: [rank]") - return 0 - -/datum/controller/occupations/proc/FreeRole(var/rank) //making additional slot on the fly - var/datum/job/job = GetJob(rank) - if(job && job.current_positions >= job.total_positions) - job.total_positions++ - return 1 - return 0 - -/datum/controller/occupations/proc/FindOccupationCandidates(datum/job/job, level, flag) - Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]") - var/list/candidates = list() - for(var/mob/new_player/player in unassigned) - if(jobban_isbanned(player, job.title)) - Debug("FOC isbanned failed, Player: [player]") - continue - if(!job.player_old_enough(player.client)) - Debug("FOC player not old enough, Player: [player]") - continue - if(flag && !player.client.desires_role(job.title)) - Debug("FOC flag failed, Player: [player], Flag: [flag], ") - continue - if(player.client.prefs.GetJobDepartment(job, level) & job.flag) - Debug("FOC pass, Player: [player], Level:[level]") - candidates += player - return candidates - -/datum/controller/occupations/proc/GiveRandomJob(var/mob/new_player/player) - Debug("GRJ Giving random job, Player: [player]") - for(var/datum/job/job in shuffle(occupations)) - if(!job) - continue - - if(istype(job, GetJob("Assistant"))) // We don't want to give him assistant, that's boring! - continue - - if(job in command_positions) //If you want a command position, select it! - continue - - if(jobban_isbanned(player, job.title)) - Debug("GRJ isbanned failed, Player: [player], Job: [job.title]") - continue - - if(!job.player_old_enough(player.client)) - Debug("GRJ player not old enough, Player: [player]") - continue - - if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1) - Debug("GRJ Random job given, Player: [player], Job: [job]") - AssignRole(player, job.title) - unassigned -= player - break - -/datum/controller/occupations/proc/ResetOccupations() - for(var/mob/new_player/player in player_list) - if((player) && (player.mind)) - player.mind.assigned_role = null - player.mind.special_role = null - SetupOccupations() - unassigned = list() - return - - - ///This proc is called before the level loop of DivideOccupations() and will try to select a head, ignoring ALL non-head preferences for every level until it locates a head or runs out of levels to check -/datum/controller/occupations/proc/FillHeadPosition() - for(var/level = 1 to 3) - for(var/command_position in command_positions) - var/datum/job/job = GetJob(command_position) - if(!job) continue - var/list/candidates = FindOccupationCandidates(job, level) - if(!candidates.len) continue - var/mob/new_player/candidate = pick(candidates) - if(AssignRole(candidate, command_position)) - return 1 - return 0 - - - ///This proc is called at the start of the level loop of DivideOccupations() and will cause head jobs to be checked before any other jobs of the same level -/datum/controller/occupations/proc/CheckHeadPositions(var/level) - for(var/command_position in command_positions) - var/datum/job/job = GetJob(command_position) - if(!job) continue - var/list/candidates = FindOccupationCandidates(job, level) - if(!candidates.len) continue - var/mob/new_player/candidate = pick(candidates) - AssignRole(candidate, command_position) - return - - -/datum/controller/occupations/proc/FillAIPosition() - var/ai_selected = 0 - var/datum/job/job = GetJob("AI") - if(!job) return 0 - if((job.title == "AI") && (config) && (!config.allow_ai)) return 0 - - for(var/i = job.total_positions, i > 0, i--) - for(var/level = 1 to 3) - var/list/candidates = list() - if(ticker.mode.name == "AI malfunction")//Make sure they want to malf if its malf - candidates = FindOccupationCandidates(job, level, ROLE_MALF) - else - candidates = FindOccupationCandidates(job, level) - if(candidates.len) - var/mob/new_player/candidate = pick(candidates) - if(AssignRole(candidate, "AI")) - ai_selected++ - break - //Malf NEEDS an AI so force one if we didn't get a player who wanted it - if((ticker.mode.name == "AI malfunction")&&(!ai_selected)) - unassigned = shuffle(unassigned) - for(var/mob/new_player/player in unassigned) - if(jobban_isbanned(player, "AI")) continue - if(AssignRole(player, "AI")) - ai_selected++ - break - if(ai_selected) return 1 - return 0 - - -/** Proc DivideOccupations - * fills var "assigned_role" for all ready players. - * This proc must not have any side effect besides of modifying "assigned_role". - **/ -/datum/controller/occupations/proc/DivideOccupations() - //Setup new player list and get the jobs list - Debug("Running DO") - SetupOccupations() - - //Holder for Triumvirate is stored in the ticker, this just processes it - if(ticker) - for(var/datum/job/ai/A in occupations) - if(ticker.triai) - A.spawn_positions = 3 - - //Get the players who are ready - for(var/mob/new_player/player in player_list) - if(player.ready && player.mind && !player.mind.assigned_role) - unassigned += player - if(player.client.prefs.randomslot) player.client.prefs.random_character_sqlite(player, player.ckey) - Debug("DO, Len: [unassigned.len]") - if(unassigned.len == 0) return 0 - - //Shuffle players and jobs - unassigned = shuffle(unassigned) - - HandleFeedbackGathering() - - //Select one head - Debug("DO, Running Head Check") - FillHeadPosition() - Debug("DO, Head Check end") - - //Check for an AI - Debug("DO, Running AI Check") - FillAIPosition() - Debug("DO, AI Check end") - - //Other jobs are now checked - Debug("DO, Running Standard Check") - - - // New job giving system by Donkie - // This will cause lots of more loops, but since it's only done once it shouldn't really matter much at all. - // Hopefully this will add more randomness and fairness to job giving. - - // Loop through all levels from high to low - var/list/shuffledoccupations = shuffle(occupations) - for(var/level = 1 to 3) - //Check the head jobs first each level - CheckHeadPositions(level) - - // Loop through all unassigned players - for(var/mob/new_player/player in unassigned) - - // Loop through all jobs - for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY - if(!job) - continue - - if(jobban_isbanned(player, job.title)) - Debug("DO isbanned failed, Player: [player], Job:[job.title]") - continue - - if(!job.player_old_enough(player.client)) - Debug("DO player not old enough, Player: [player], Job:[job.title]") - continue - - // If the player wants that job on this level, then try give it to him. - if(player.client.prefs.GetJobDepartment(job, level) & job.flag) - - // If the job isn't filled - if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1) - Debug("DO pass, Player: [player], Level:[level], Job:[job.title]") - AssignRole(player, job.title) - unassigned -= player - break - - // Hand out random jobs to the people who didn't get any in the last check - // Also makes sure that they got their preference correct - - //People who wants to be assistants, sure, go on. - var/count = 0 - var/datum/job/officer = job_master.GetJob("Security Officer") - var/datum/job/warden = job_master.GetJob("Warden") - var/datum/job/hos = job_master.GetJob("Head of Security") - count = (officer.current_positions + warden.current_positions + hos.current_positions) - Debug("DO, Running Assistant Check 1") - var/datum/job/assist = new /datum/job/assistant() - var/datum/job/master_assistant = GetJob("Assistant") - var/list/assistant_candidates = FindOccupationCandidates(assist, 3) - assistant_candidates = shuffle(assistant_candidates) - Debug("AC1, Candidates: [assistant_candidates.len]") - for(var/mob/new_player/player in assistant_candidates) - Debug("AC1 pass, Player: [player]") - if(config.assistantlimit) - if(master_assistant.current_positions > (config.assistantratio * count)) - if(count < 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide - break - AssignRole(player, "Assistant") - assistant_candidates -= player - unassigned |= assistant_candidates - Debug("DO, AC1 end") - - for(var/mob/new_player/player in unassigned) - if(player.client.prefs.alternate_option == GET_RANDOM_JOB) - GiveRandomJob(player) - /* - Old job system - for(var/level = 1 to 3) - for(var/datum/job/job in occupations) - Debug("Checking job: [job]") - if(!job) - continue - if(!unassigned.len) - break - if((job.current_positions >= job.spawn_positions) && job.spawn_positions != -1) - continue - var/list/candidates = FindOccupationCandidates(job, level) - while(candidates.len && ((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)) - var/mob/new_player/candidate = pick(candidates) - Debug("Selcted: [candidate], for: [job.title]") - AssignRole(candidate, job.title) - candidates -= candidate*/ - - Debug("DO, Standard Check end") - - Debug("DO, Running AC2") - - // For those who wanted to be assistant if their preferences were filled, here you go. - for(var/mob/new_player/player in unassigned) - if(player.client.prefs.alternate_option == BE_ASSISTANT) - if(config.assistantlimit) - count = (officer.current_positions + warden.current_positions + hos.current_positions) - if(master_assistant.current_positions > (config.assistantratio * count)) - if(count < 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide - player.ready = 0 - unassigned -= player - continue - Debug("AC2 Assistant located, Player: [player]") - AssignRole(player, "Assistant") - - //For ones returning to lobby - for(var/mob/new_player/player in unassigned) - if(player.client.prefs.alternate_option == RETURN_TO_LOBBY) - player.ready = 0 - unassigned -= player - return 1 - - -/datum/controller/occupations/proc/EquipRank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0) - if(!H) return 0 - var/datum/job/job = GetJob(rank) - if(job) - job.equip(H) - else + return 0 + for(var/J in all_jobs) + var/datum/job/job = new J() + if(!job) continue + if(job.faction != faction) continue + occupations += job + + + return 1 + + +/datum/controller/occupations/proc/Debug(var/text) + if(!Debug2) return 0 + job_debug.Add(text) + return 1 + + +/datum/controller/occupations/proc/GetJob(var/rank) + if(!rank) return null + for(var/datum/job/J in occupations) + if(!J) continue + if(J.title == rank) return J + return null + +/datum/controller/occupations/proc/GetPlayerAltTitle(mob/new_player/player, rank) + return player.client.prefs.GetPlayerAltTitle(GetJob(rank)) + +/datum/controller/occupations/proc/AssignRole(var/mob/new_player/player, var/rank, var/latejoin = 0) + Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]") + if(player && player.mind && rank) + var/datum/job/job = GetJob(rank) + if(!job) return 0 + if(jobban_isbanned(player, rank)) return 0 + if(!job.player_old_enough(player.client)) return 0 + var/position_limit = job.total_positions + if(!latejoin) + position_limit = job.spawn_positions + if((job.current_positions < position_limit) || position_limit == -1) + Debug("Player: [player] is now Rank: [rank], JCP:[job.current_positions], JPL:[position_limit]") + player.mind.assigned_role = rank + player.mind.role_alt_title = GetPlayerAltTitle(player, rank) + + unassigned -= player + job.current_positions++ + return 1 + Debug("AR has failed, Player: [player], Rank: [rank]") + return 0 + +/datum/controller/occupations/proc/FreeRole(var/rank) //making additional slot on the fly + var/datum/job/job = GetJob(rank) + if(job && job.current_positions >= job.total_positions) + job.total_positions++ + return 1 + return 0 + +/datum/controller/occupations/proc/FindOccupationCandidates(datum/job/job, level, flag) + Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]") + var/list/candidates = list() + for(var/mob/new_player/player in unassigned) + if(jobban_isbanned(player, job.title)) + Debug("FOC isbanned failed, Player: [player]") + continue + if(!job.player_old_enough(player.client)) + Debug("FOC player not old enough, Player: [player]") + continue + if(flag && !player.client.desires_role(job.title)) + Debug("FOC flag failed, Player: [player], Flag: [flag], ") + continue + if(player.client.prefs.GetJobDepartment(job, level) & job.flag) + Debug("FOC pass, Player: [player], Level:[level]") + candidates += player + return candidates + +/datum/controller/occupations/proc/GiveRandomJob(var/mob/new_player/player) + Debug("GRJ Giving random job, Player: [player]") + for(var/datum/job/job in shuffle(occupations)) + if(!job) + continue + + if(istype(job, GetJob("Assistant"))) // We don't want to give him assistant, that's boring! + continue + + if(job in command_positions) //If you want a command position, select it! + continue + + if(jobban_isbanned(player, job.title)) + Debug("GRJ isbanned failed, Player: [player], Job: [job.title]") + continue + + if(!job.player_old_enough(player.client)) + Debug("GRJ player not old enough, Player: [player]") + continue + + if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1) + Debug("GRJ Random job given, Player: [player], Job: [job]") + AssignRole(player, job.title) + unassigned -= player + break + +/datum/controller/occupations/proc/ResetOccupations() + for(var/mob/new_player/player in player_list) + if((player) && (player.mind)) + player.mind.assigned_role = null + player.mind.special_role = null + SetupOccupations() + unassigned = list() + return + + + ///This proc is called before the level loop of DivideOccupations() and will try to select a head, ignoring ALL non-head preferences for every level until it locates a head or runs out of levels to check +/datum/controller/occupations/proc/FillHeadPosition() + for(var/level = 1 to 3) + for(var/command_position in command_positions) + var/datum/job/job = GetJob(command_position) + if(!job) continue + var/list/candidates = FindOccupationCandidates(job, level) + if(!candidates.len) continue + var/mob/new_player/candidate = pick(candidates) + if(AssignRole(candidate, command_position)) + return 1 + return 0 + + + ///This proc is called at the start of the level loop of DivideOccupations() and will cause head jobs to be checked before any other jobs of the same level +/datum/controller/occupations/proc/CheckHeadPositions(var/level) + for(var/command_position in command_positions) + var/datum/job/job = GetJob(command_position) + if(!job) continue + var/list/candidates = FindOccupationCandidates(job, level) + if(!candidates.len) continue + var/mob/new_player/candidate = pick(candidates) + AssignRole(candidate, command_position) + return + + +/datum/controller/occupations/proc/FillAIPosition() + var/ai_selected = 0 + var/datum/job/job = GetJob("AI") + if(!job) return 0 + if((job.title == "AI") && (config) && (!config.allow_ai)) return 0 + + for(var/i = job.total_positions, i > 0, i--) + for(var/level = 1 to 3) + var/list/candidates = list() + if(ticker.mode.name == "AI malfunction")//Make sure they want to malf if its malf + candidates = FindOccupationCandidates(job, level, ROLE_MALF) + else + candidates = FindOccupationCandidates(job, level) + if(candidates.len) + var/mob/new_player/candidate = pick(candidates) + if(AssignRole(candidate, "AI")) + ai_selected++ + break + //Malf NEEDS an AI so force one if we didn't get a player who wanted it + if((ticker.mode.name == "AI malfunction")&&(!ai_selected)) + unassigned = shuffle(unassigned) + for(var/mob/new_player/player in unassigned) + if(jobban_isbanned(player, "AI")) continue + if(AssignRole(player, "AI")) + ai_selected++ + break + if(ai_selected) return 1 + return 0 + + +/** Proc DivideOccupations + * fills var "assigned_role" for all ready players. + * This proc must not have any side effect besides of modifying "assigned_role". + **/ +/datum/controller/occupations/proc/DivideOccupations() + //Setup new player list and get the jobs list + Debug("Running DO") + SetupOccupations() + + //Holder for Triumvirate is stored in the ticker, this just processes it + if(ticker) + for(var/datum/job/ai/A in occupations) + if(ticker.triai) + A.spawn_positions = 3 + + //Get the players who are ready + for(var/mob/new_player/player in player_list) + if(player.ready && player.mind && !player.mind.assigned_role) + unassigned += player + if(player.client.prefs.randomslot) player.client.prefs.random_character_sqlite(player, player.ckey) + Debug("DO, Len: [unassigned.len]") + if(unassigned.len == 0) return 0 + + //Shuffle players and jobs + unassigned = shuffle(unassigned) + + HandleFeedbackGathering() + + //Select one head + Debug("DO, Running Head Check") + FillHeadPosition() + Debug("DO, Head Check end") + + //Check for an AI + Debug("DO, Running AI Check") + FillAIPosition() + Debug("DO, AI Check end") + + //Other jobs are now checked + Debug("DO, Running Standard Check") + + + // New job giving system by Donkie + // This will cause lots of more loops, but since it's only done once it shouldn't really matter much at all. + // Hopefully this will add more randomness and fairness to job giving. + + // Loop through all levels from high to low + var/list/shuffledoccupations = shuffle(occupations) + for(var/level = 1 to 3) + //Check the head jobs first each level + CheckHeadPositions(level) + + // Loop through all unassigned players + for(var/mob/new_player/player in unassigned) + + // Loop through all jobs + for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY + if(!job) + continue + + if(jobban_isbanned(player, job.title)) + Debug("DO isbanned failed, Player: [player], Job:[job.title]") + continue + + if(!job.player_old_enough(player.client)) + Debug("DO player not old enough, Player: [player], Job:[job.title]") + continue + + // If the player wants that job on this level, then try give it to him. + if(player.client.prefs.GetJobDepartment(job, level) & job.flag) + + // If the job isn't filled + if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1) + Debug("DO pass, Player: [player], Level:[level], Job:[job.title]") + AssignRole(player, job.title) + unassigned -= player + break + + // Hand out random jobs to the people who didn't get any in the last check + // Also makes sure that they got their preference correct + + //People who wants to be assistants, sure, go on. + var/count = 0 + var/datum/job/officer = job_master.GetJob("Security Officer") + var/datum/job/warden = job_master.GetJob("Warden") + var/datum/job/hos = job_master.GetJob("Head of Security") + count = (officer.current_positions + warden.current_positions + hos.current_positions) + Debug("DO, Running Assistant Check 1") + var/datum/job/assist = new /datum/job/assistant() + var/datum/job/master_assistant = GetJob("Assistant") + var/list/assistant_candidates = FindOccupationCandidates(assist, 3) + assistant_candidates = shuffle(assistant_candidates) + Debug("AC1, Candidates: [assistant_candidates.len]") + for(var/mob/new_player/player in assistant_candidates) + Debug("AC1 pass, Player: [player]") + if(config.assistantlimit) + if(master_assistant.current_positions > (config.assistantratio * count)) + if(count < 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide + break + AssignRole(player, "Assistant") + assistant_candidates -= player + unassigned |= assistant_candidates + Debug("DO, AC1 end") + + for(var/mob/new_player/player in unassigned) + if(player.client.prefs.alternate_option == GET_RANDOM_JOB) + GiveRandomJob(player) + /* + Old job system + for(var/level = 1 to 3) + for(var/datum/job/job in occupations) + Debug("Checking job: [job]") + if(!job) + continue + if(!unassigned.len) + break + if((job.current_positions >= job.spawn_positions) && job.spawn_positions != -1) + continue + var/list/candidates = FindOccupationCandidates(job, level) + while(candidates.len && ((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)) + var/mob/new_player/candidate = pick(candidates) + Debug("Selcted: [candidate], for: [job.title]") + AssignRole(candidate, job.title) + candidates -= candidate*/ + + Debug("DO, Standard Check end") + + Debug("DO, Running AC2") + + // For those who wanted to be assistant if their preferences were filled, here you go. + for(var/mob/new_player/player in unassigned) + if(player.client.prefs.alternate_option == BE_ASSISTANT) + if(config.assistantlimit) + count = (officer.current_positions + warden.current_positions + hos.current_positions) + if(master_assistant.current_positions > (config.assistantratio * count)) + if(count < 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide + player.ready = 0 + unassigned -= player + continue + Debug("AC2 Assistant located, Player: [player]") + AssignRole(player, "Assistant") + + //For ones returning to lobby + for(var/mob/new_player/player in unassigned) + if(player.client.prefs.alternate_option == RETURN_TO_LOBBY) + player.ready = 0 + unassigned -= player + return 1 + + +/datum/controller/occupations/proc/EquipRank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0) + if(!H) return 0 + var/datum/job/job = GetJob(rank) + if(job) + job.equip(H) + else to_chat(H, "Your job is [rank] and the game just can't handle it! Please report this bug to an administrator.") - - H.job = rank - - if(!joined_late) - var/obj/S = null - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if(sloc.name != rank) continue - if(locate(/mob/living) in sloc.loc) continue - S = sloc - break - if(!S) - S = locate("start*[rank]") // use old stype - if(istype(S, /obj/effect/landmark/start) && istype(S.loc, /turf)) - H.loc = S.loc - - //give them an account in the station database - // Total between $200 and $500 - var/balance_bank = rand(100,250) - var/balance_wallet = rand(100,250) - if(centcomm_account_db) - var/datum/money_account/M = create_account(H.real_name, balance_bank , null) - if(H.mind) - var/remembered_info = "" - remembered_info += "Your account number is: #[M.account_number]
      " - remembered_info += "Your account pin is: [M.remote_access_pin]
      " - remembered_info += "Your bank account funds are: $[balance_bank]
      " - remembered_info += "Your virtual wallet funds are: $[balance_wallet]
      " - - if(M.transaction_log.len) - var/datum/transaction/T = M.transaction_log[1] - remembered_info += "Your account was created: [T.time], [T.date] at [T.source_terminal]
      " - H.mind.store_memory(remembered_info) - - H.mind.initial_account = M - - // If they're head, give them the account info for their department - if(H.mind && job.head_position) - var/remembered_info = "" - var/datum/money_account/department_account = department_accounts[job.department] - - if(department_account) - remembered_info += "Your department's account number is: #[department_account.account_number]
      " - remembered_info += "Your department's account pin is: [department_account.remote_access_pin]
      " - remembered_info += "Your department's account funds are: $[department_account.money]
      " - - H.mind.store_memory(remembered_info) - - spawn() + + H.job = rank + + if(!joined_late) + var/obj/S = null + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if(sloc.name != rank) continue + if(locate(/mob/living) in sloc.loc) continue + S = sloc + break + if(!S) + S = locate("start*[rank]") // use old stype + if(istype(S, /obj/effect/landmark/start) && istype(S.loc, /turf)) + H.loc = S.loc + + //give them an account in the station database + // Total between $200 and $500 + var/balance_bank = rand(100,250) + var/balance_wallet = rand(100,250) + if(centcomm_account_db) + var/datum/money_account/M = create_account(H.real_name, balance_bank , null) + if(H.mind) + var/remembered_info = "" + remembered_info += "Your account number is: #[M.account_number]
      " + remembered_info += "Your account pin is: [M.remote_access_pin]
      " + remembered_info += "Your bank account funds are: $[balance_bank]
      " + remembered_info += "Your virtual wallet funds are: $[balance_wallet]
      " + + if(M.transaction_log.len) + var/datum/transaction/T = M.transaction_log[1] + remembered_info += "Your account was created: [T.time], [T.date] at [T.source_terminal]
      " + H.mind.store_memory(remembered_info) + + H.mind.initial_account = M + + // If they're head, give them the account info for their department + if(H.mind && job.head_position) + var/remembered_info = "" + var/datum/money_account/department_account = department_accounts[job.department] + + if(department_account) + remembered_info += "Your department's account number is: #[department_account.account_number]
      " + remembered_info += "Your department's account pin is: [department_account.remote_access_pin]
      " + remembered_info += "Your department's account funds are: $[department_account.money]
      " + + H.mind.store_memory(remembered_info) + + spawn() to_chat(H, "Your bank account number is: [M.account_number], your bank account pin is: [M.remote_access_pin]") to_chat(H, "Your virtual wallet funds are: $[balance_wallet], your bank account funds are: $[balance_bank]") - - var/alt_title = null - if(H.mind) - H.mind.assigned_role = rank - alt_title = H.mind.role_alt_title - - switch(rank) - if("Cyborg") - spawn(20)//We need to be absolutely certain the borg is made after AI for law sync reasons. - H.Robotize() - return 1 - if("Mobile MMI") - H.MoMMIfy(1) - return 1 - if("AI","Clown") //don't need bag preference stuff! - if(rank=="Clown") // Clowns DO need to breathe, though - N3X - H.species.equip(H) - else - switch(H.backbag) //BS12 EDIT - if(1) - if(H.species.survival_gear) - H.equip_to_slot_or_del(new H.species.survival_gear(H), slot_r_hand) - if(2) - var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack(H) - if(H.species.survival_gear) - new H.species.survival_gear(BPK) - H.equip_to_slot_or_del(BPK, slot_back,1) - if(3) - var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel_norm(H) - if(H.species.survival_gear) - new H.species.survival_gear(BPK) - H.equip_to_slot_or_del(BPK, slot_back,1) - if(4) - var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel(H) - if(H.species.survival_gear) - new H.species.survival_gear(BPK) - H.equip_to_slot_or_del(BPK, slot_back,1) - H.species.equip(H) - - + + var/alt_title = null + if(H.mind) + H.mind.assigned_role = rank + alt_title = H.mind.role_alt_title + + switch(rank) + if("Cyborg") + spawn(20)//We need to be absolutely certain the borg is made after AI for law sync reasons. + H.Robotize() + return 1 + if("Mobile MMI") + H.MoMMIfy(1) + return 1 + if("AI","Clown") //don't need bag preference stuff! + if(rank=="Clown") // Clowns DO need to breathe, though - N3X + H.species.equip(H) + else + switch(H.backbag) //BS12 EDIT + if(1) + if(H.species.survival_gear) + H.equip_to_slot_or_del(new H.species.survival_gear(H), slot_r_hand) + if(2) + var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack(H) + if(H.species.survival_gear) + new H.species.survival_gear(BPK) + H.equip_to_slot_or_del(BPK, slot_back,1) + if(3) + var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel_norm(H) + if(H.species.survival_gear) + new H.species.survival_gear(BPK) + H.equip_to_slot_or_del(BPK, slot_back,1) + if(4) + var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel(H) + if(H.species.survival_gear) + new H.species.survival_gear(BPK) + H.equip_to_slot_or_del(BPK, slot_back,1) + H.species.equip(H) + + to_chat(H, "You are the [alt_title ? alt_title : rank].") to_chat(H, "As the [alt_title ? alt_title : rank] you answer directly to [job.supervisors]. Special circumstances may change this.") - if(job.req_admin_notify) + if(job.req_admin_notify) to_chat(H, "You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp.") - - spawnId(H, rank, alt_title, balance_wallet) - H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H), slot_ears) - - //Gives glasses to the vision impaired - if(H.disabilities & DISABILITY_FLAG_NEARSIGHTED) - var/equipped = H.equip_to_slot_or_del(new /obj/item/clothing/glasses/regular(H), slot_glasses) - if(equipped != 1) - var/obj/item/clothing/glasses/G = H.glasses - G.prescription = 1 -// H.update_icons() - //Gives wheelchair to those missing both of their feet - var/datum/organ/external/left_leg = H.get_organ("l_foot") - var/datum/organ/external/right_leg = H.get_organ("r_foot") - - if(!joined_late) //late joins get their location set elsewhere - if( (!left_leg || left_leg.status & ORGAN_DESTROYED) && (!right_leg || right_leg.status & ORGAN_DESTROYED) ) //If the character is missing both of his feet - var/obj/structure/bed/chair/vehicle/wheelchair/W = new(H.loc) - W.buckle_mob(H,H) - return 1 - - -/datum/controller/occupations/proc/spawnId(var/mob/living/carbon/human/H, rank, title, wallet_funds=0) - if(!H) return 0 - var/obj/item/weapon/card/id/C = null - - var/datum/job/job = null - for(var/datum/job/J in occupations) - if(J.title == rank) - job = J - break - - if(job) - if(job.title == "Cyborg" || job.title=="Mobile MMI") - return - else - C = new job.idtype(H) - C.access = job.get_access() - else - C = new /obj/item/weapon/card/id(H) - if(C) - C.registered_name = H.real_name - C.rank = rank - C.assignment = title ? title : rank - C.name = "[C.registered_name]'s ID Card ([C.assignment])" - - //put the player's account number onto the ID - if(H.mind && H.mind.initial_account) - C.associated_account_number = H.mind.initial_account.account_number - - H.equip_or_collect(C, slot_wear_id) - - C.update_virtual_wallet(wallet_funds) - - H.equip_or_collect(new job.pdatype(H), job.pdaslot) - if(locate(/obj/item/device/pda,H)) - var/obj/item/device/pda/pda = locate(/obj/item/device/pda,H) - pda.owner = H.real_name - pda.ownjob = C.assignment - pda.name = "PDA-[H.real_name] ([pda.ownjob])" - H.update_inv_belt() - H.update_inv_wear_id() - return 1 - - - -/datum/controller/occupations/proc/LoadJobs(jobsfile) //ran during round setup, reads info from jobs.txt -- Urist - if(!config.load_jobs_from_txt) - return 0 - - var/list/jobEntries = file2list(jobsfile) - - for(var/job in jobEntries) - if(!job) - continue - - job = trim(job) - if (!length(job)) - continue - - var/pos = findtext(job, "=") - var/name = null - var/value = null - - if(pos) - name = copytext(job, 1, pos) - value = copytext(job, pos + 1) - else - continue - - if(name && value) - var/datum/job/J = GetJob(name) - if(!J) continue - J.total_positions = text2num(value) - J.spawn_positions = text2num(value) - if(name == "AI" || name == "Cyborg" || name == "Mobile MMI")//I dont like this here but it will do for now - J.total_positions = 0 - - return 1 - - -/datum/controller/occupations/proc/HandleFeedbackGathering() - for(var/datum/job/job in occupations) - var/tmp_str = "|[job.title]|" - - var/level1 = 0 //high - var/level2 = 0 //medium - var/level3 = 0 //low - var/level4 = 0 //never - var/level5 = 0 //banned - var/level6 = 0 //account too young - for(var/mob/new_player/player in player_list) - if(!(player.ready && player.mind && !player.mind.assigned_role)) - continue //This player is not ready - if(jobban_isbanned(player, job.title)) - level5++ - continue - if(!job.player_old_enough(player.client)) - level6++ - continue - if(player.client.prefs.GetJobDepartment(job, 1) & job.flag) - level1++ - else if(player.client.prefs.GetJobDepartment(job, 2) & job.flag) - level2++ - else if(player.client.prefs.GetJobDepartment(job, 3) & job.flag) - level3++ - else level4++ //not selected - - tmp_str += "HIGH=[level1]|MEDIUM=[level2]|LOW=[level3]|NEVER=[level4]|BANNED=[level5]|YOUNG=[level6]|-" - feedback_add_details("job_preferences",tmp_str) + + spawnId(H, rank, alt_title, balance_wallet) + H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H), slot_ears) + + //Gives glasses to the vision impaired + if(H.disabilities & DISABILITY_FLAG_NEARSIGHTED) + var/equipped = H.equip_to_slot_or_del(new /obj/item/clothing/glasses/regular(H), slot_glasses) + if(equipped != 1) + var/obj/item/clothing/glasses/G = H.glasses + G.prescription = 1 +// H.update_icons() + //Gives wheelchair to those missing both of their feet + var/datum/organ/external/left_leg = H.get_organ("l_foot") + var/datum/organ/external/right_leg = H.get_organ("r_foot") + + if(!joined_late) //late joins get their location set elsewhere + if( (!left_leg || left_leg.status & ORGAN_DESTROYED) && (!right_leg || right_leg.status & ORGAN_DESTROYED) ) //If the character is missing both of his feet + var/obj/structure/bed/chair/vehicle/wheelchair/W = new(H.loc) + W.buckle_mob(H,H) + return 1 + + +/datum/controller/occupations/proc/spawnId(var/mob/living/carbon/human/H, rank, title, wallet_funds=0) + if(!H) return 0 + var/obj/item/weapon/card/id/C = null + + var/datum/job/job = null + for(var/datum/job/J in occupations) + if(J.title == rank) + job = J + break + + if(job) + if(job.title == "Cyborg" || job.title=="Mobile MMI") + return + else + C = new job.idtype(H) + C.access = job.get_access() + else + C = new /obj/item/weapon/card/id(H) + if(C) + C.registered_name = H.real_name + C.rank = rank + C.assignment = title ? title : rank + C.name = "[C.registered_name]'s ID Card ([C.assignment])" + + //put the player's account number onto the ID + if(H.mind && H.mind.initial_account) + C.associated_account_number = H.mind.initial_account.account_number + + H.equip_or_collect(C, slot_wear_id) + + C.update_virtual_wallet(wallet_funds) + + H.equip_or_collect(new job.pdatype(H), job.pdaslot) + if(locate(/obj/item/device/pda,H)) + var/obj/item/device/pda/pda = locate(/obj/item/device/pda,H) + pda.owner = H.real_name + pda.ownjob = C.assignment + pda.name = "PDA-[H.real_name] ([pda.ownjob])" + H.update_inv_belt() + H.update_inv_wear_id() + return 1 + + + +/datum/controller/occupations/proc/LoadJobs(jobsfile) //ran during round setup, reads info from jobs.txt -- Urist + if(!config.load_jobs_from_txt) + return 0 + + var/list/jobEntries = file2list(jobsfile) + + for(var/job in jobEntries) + if(!job) + continue + + job = trim(job) + if (!length(job)) + continue + + var/pos = findtext(job, "=") + var/name = null + var/value = null + + if(pos) + name = copytext(job, 1, pos) + value = copytext(job, pos + 1) + else + continue + + if(name && value) + var/datum/job/J = GetJob(name) + if(!J) continue + J.total_positions = text2num(value) + J.spawn_positions = text2num(value) + if(name == "AI" || name == "Cyborg" || name == "Mobile MMI")//I dont like this here but it will do for now + J.total_positions = 0 + + return 1 + + +/datum/controller/occupations/proc/HandleFeedbackGathering() + for(var/datum/job/job in occupations) + var/tmp_str = "|[job.title]|" + + var/level1 = 0 //high + var/level2 = 0 //medium + var/level3 = 0 //low + var/level4 = 0 //never + var/level5 = 0 //banned + var/level6 = 0 //account too young + for(var/mob/new_player/player in player_list) + if(!(player.ready && player.mind && !player.mind.assigned_role)) + continue //This player is not ready + if(jobban_isbanned(player, job.title)) + level5++ + continue + if(!job.player_old_enough(player.client)) + level6++ + continue + if(player.client.prefs.GetJobDepartment(job, 1) & job.flag) + level1++ + else if(player.client.prefs.GetJobDepartment(job, 2) & job.flag) + level2++ + else if(player.client.prefs.GetJobDepartment(job, 3) & job.flag) + level3++ + else level4++ //not selected + + tmp_str += "HIGH=[level1]|MEDIUM=[level2]|LOW=[level3]|NEVER=[level4]|BANNED=[level5]|YOUNG=[level6]|-" + feedback_add_details("job_preferences",tmp_str) diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index 27e6a60d5b8..5ab5474f814 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -1,146 +1,146 @@ -var/const/ENGSEC =(1<<0) - -var/const/CAPTAIN =(1<<0) -var/const/HOS =(1<<1) -var/const/WARDEN =(1<<2) -var/const/DETECTIVE =(1<<3) -var/const/OFFICER =(1<<4) -var/const/CHIEF =(1<<5) -var/const/ENGINEER =(1<<6) -var/const/ATMOSTECH =(1<<7) -var/const/ROBOTICIST =(1<<8) -var/const/AI =(1<<9) -var/const/CYBORG =(1<<10) -var/const/MOMMI =(1<<11) -var/const/MECHANIC =(1<<12) - - -var/const/MEDSCI =(1<<1) - -var/const/RD =(1<<0) -var/const/SCIENTIST =(1<<1) -var/const/CHEMIST =(1<<2) -var/const/CMO =(1<<3) -var/const/DOCTOR =(1<<4) -var/const/GENETICIST =(1<<5) -var/const/VIROLOGIST =(1<<6) -//var/const/PSYCHIATRIST =(1<<7) -var/const/PARAMEDIC =(1<<7) - - -var/const/CIVILIAN =(1<<2) - -var/const/HOP =(1<<0) -var/const/BARTENDER =(1<<1) -var/const/BOTANIST =(1<<2) -var/const/CHEF =(1<<3) -var/const/JANITOR =(1<<4) -var/const/LIBRARIAN =(1<<5) -var/const/QUARTERMASTER =(1<<6) -var/const/CARGOTECH =(1<<7) -var/const/MINER =(1<<8) -var/const/LAWYER =(1<<9) -var/const/CHAPLAIN =(1<<10) -var/const/CLOWN =(1<<11) -var/const/MIME =(1<<12) -var/const/ASSISTANT =(1<<13) - - -var/list/assistant_occupations = list( -) - - -var/list/command_positions = list( - "Captain", - "Head of Personnel", - "Head of Security", - "Chief Engineer", - "Research Director", - "Chief Medical Officer" -) - - -var/list/engineering_positions = list( - "Chief Engineer", - "Station Engineer", - "Atmospheric Technician", - "Mechanic" -) - - -var/list/medical_positions = list( - "Chief Medical Officer", - "Medical Doctor", - "Geneticist", -// "Psychiatrist", - "Paramedic", - "Chemist" -) - - -var/list/science_positions = list( - "Research Director", - "Scientist", - "Geneticist", //Part of both medical and science - "Roboticist", - "Mechanic" -) - -//BS12 EDIT -var/list/civilian_positions = list( - "Head of Personnel", - "Bartender", - "Botanist", - "Chef", - "Janitor", - "Librarian", - "Quartermaster", - "Cargo Technician", - "Shaft Miner", - "Internal Affairs Agent", - "Chaplain", - "Assistant" -) - - -var/list/security_positions = list( - "Head of Security", - "Warden", - "Detective", - "Security Officer" -) - - -var/list/nonhuman_positions = list( - "AI", - "Cyborg", - "pAI", - "Mobile MMI" -) - - -/proc/guest_jobbans(var/job) - return ((job in command_positions) || (job in nonhuman_positions) || (job in security_positions)) - -/proc/get_job_datums() - var/list/occupations = list() - var/list/all_jobs = typesof(/datum/job) - - for(var/A in all_jobs) - var/datum/job/job = new A() - if(!job) continue - occupations += job - - return occupations - -/proc/get_alternate_titles(var/job) - var/list/jobs = get_job_datums() - var/list/titles = list() - - for(var/datum/job/J in jobs) - if(!J) continue - if(J.title == job) - titles = J.alt_titles - - return titles - +var/const/ENGSEC =(1<<0) + +var/const/CAPTAIN =(1<<0) +var/const/HOS =(1<<1) +var/const/WARDEN =(1<<2) +var/const/DETECTIVE =(1<<3) +var/const/OFFICER =(1<<4) +var/const/CHIEF =(1<<5) +var/const/ENGINEER =(1<<6) +var/const/ATMOSTECH =(1<<7) +var/const/ROBOTICIST =(1<<8) +var/const/AI =(1<<9) +var/const/CYBORG =(1<<10) +var/const/MOMMI =(1<<11) +var/const/MECHANIC =(1<<12) + + +var/const/MEDSCI =(1<<1) + +var/const/RD =(1<<0) +var/const/SCIENTIST =(1<<1) +var/const/CHEMIST =(1<<2) +var/const/CMO =(1<<3) +var/const/DOCTOR =(1<<4) +var/const/GENETICIST =(1<<5) +var/const/VIROLOGIST =(1<<6) +//var/const/PSYCHIATRIST =(1<<7) +var/const/PARAMEDIC =(1<<7) + + +var/const/CIVILIAN =(1<<2) + +var/const/HOP =(1<<0) +var/const/BARTENDER =(1<<1) +var/const/BOTANIST =(1<<2) +var/const/CHEF =(1<<3) +var/const/JANITOR =(1<<4) +var/const/LIBRARIAN =(1<<5) +var/const/QUARTERMASTER =(1<<6) +var/const/CARGOTECH =(1<<7) +var/const/MINER =(1<<8) +var/const/LAWYER =(1<<9) +var/const/CHAPLAIN =(1<<10) +var/const/CLOWN =(1<<11) +var/const/MIME =(1<<12) +var/const/ASSISTANT =(1<<13) + + +var/list/assistant_occupations = list( +) + + +var/list/command_positions = list( + "Captain", + "Head of Personnel", + "Head of Security", + "Chief Engineer", + "Research Director", + "Chief Medical Officer" +) + + +var/list/engineering_positions = list( + "Chief Engineer", + "Station Engineer", + "Atmospheric Technician", + "Mechanic" +) + + +var/list/medical_positions = list( + "Chief Medical Officer", + "Medical Doctor", + "Geneticist", +// "Psychiatrist", + "Paramedic", + "Chemist" +) + + +var/list/science_positions = list( + "Research Director", + "Scientist", + "Geneticist", //Part of both medical and science + "Roboticist", + "Mechanic" +) + +//BS12 EDIT +var/list/civilian_positions = list( + "Head of Personnel", + "Bartender", + "Botanist", + "Chef", + "Janitor", + "Librarian", + "Quartermaster", + "Cargo Technician", + "Shaft Miner", + "Internal Affairs Agent", + "Chaplain", + "Assistant" +) + + +var/list/security_positions = list( + "Head of Security", + "Warden", + "Detective", + "Security Officer" +) + + +var/list/nonhuman_positions = list( + "AI", + "Cyborg", + "pAI", + "Mobile MMI" +) + + +/proc/guest_jobbans(var/job) + return ((job in command_positions) || (job in nonhuman_positions) || (job in security_positions)) + +/proc/get_job_datums() + var/list/occupations = list() + var/list/all_jobs = typesof(/datum/job) + + for(var/A in all_jobs) + var/datum/job/job = new A() + if(!job) continue + occupations += job + + return occupations + +/proc/get_alternate_titles(var/job) + var/list/jobs = get_job_datums() + var/list/titles = list() + + for(var/datum/job/J in jobs) + if(!J) continue + if(J.title == job) + titles = J.alt_titles + + return titles + diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index c8af16e540f..ec139e35571 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -1,79 +1,79 @@ -#define WHITELISTFILE "data/whitelist.txt" - -var/list/whitelist = list() - -/proc/load_whitelist() - whitelist = file2list(WHITELISTFILE) - if(!whitelist.len) whitelist = null - -/proc/check_whitelist(mob/M /*, var/rank*/) - if(!whitelist) - return 0 - return ("[M.ckey]" in whitelist) - -// species = list("ckey","ckey") -var/global/list/alien_whitelist = list() - -/proc/load_alienwhitelist() - alien_whitelist=list() - alien_whitelist["all"]=list() - var/text = file2text("config/alienwhitelist.txt") - if (!text) - diary << "Failed to load config/alienwhitelist.txt\n" - else - for(var/line in text2list(text, "\n")) - if(dd_hasprefix(line,"#")) - continue - if(!findtext(line,"-")) - continue - var/list/parts=text2list(line,"-") - var/ckey=trim(lowertext(parts[1])) - var/specieslist=text2list(parts[2],",") - for(var/species in specieslist) - species=lowertext(trim(species)) - if(!(species in alien_whitelist)) - alien_whitelist[species]=list() - if(!(ckey in alien_whitelist[species])) - alien_whitelist[species] += ckey - //for(var/species in alien_whitelist) - // for(var/ckey in alien_whitelist[species]) - // testing("[ckey] - [species]") - -//todo: admin aliens -/proc/is_alien_whitelisted(mob/M, var/species) - if(!config.usealienwhitelist) - return 1 - - species=lowertext(species) - - if(species == "human") - return 1 - - if(check_rights(R_ADMIN, 0)) - return 1 - - if(!alien_whitelist) - return 0 - - // Species is in whitelist - if("*" in alien_whitelist[species]) - return 1 - - // CKey is in whitelist - if(M.ckey in alien_whitelist[species] || M.ckey in alien_whitelist["all"]) - return 1 - - // Occupation is in whitelist (for lizard janitors :V) - if("job=[lowertext(M.mind.assigned_role)]" in alien_whitelist[species]\ - || "job=[lowertext(M.mind.assigned_role)]" in alien_whitelist["all"]) - return 1 - - return 0 - -/proc/has_whitelist_entries(var/species) - if(!config.usealienwhitelist) - return 1 - species=lowertext(species) - return species in alien_whitelist - +#define WHITELISTFILE "data/whitelist.txt" + +var/list/whitelist = list() + +/proc/load_whitelist() + whitelist = file2list(WHITELISTFILE) + if(!whitelist.len) whitelist = null + +/proc/check_whitelist(mob/M /*, var/rank*/) + if(!whitelist) + return 0 + return ("[M.ckey]" in whitelist) + +// species = list("ckey","ckey") +var/global/list/alien_whitelist = list() + +/proc/load_alienwhitelist() + alien_whitelist=list() + alien_whitelist["all"]=list() + var/text = file2text("config/alienwhitelist.txt") + if (!text) + diary << "Failed to load config/alienwhitelist.txt\n" + else + for(var/line in text2list(text, "\n")) + if(dd_hasprefix(line,"#")) + continue + if(!findtext(line,"-")) + continue + var/list/parts=text2list(line,"-") + var/ckey=trim(lowertext(parts[1])) + var/specieslist=text2list(parts[2],",") + for(var/species in specieslist) + species=lowertext(trim(species)) + if(!(species in alien_whitelist)) + alien_whitelist[species]=list() + if(!(ckey in alien_whitelist[species])) + alien_whitelist[species] += ckey + //for(var/species in alien_whitelist) + // for(var/ckey in alien_whitelist[species]) + // testing("[ckey] - [species]") + +//todo: admin aliens +/proc/is_alien_whitelisted(mob/M, var/species) + if(!config.usealienwhitelist) + return 1 + + species=lowertext(species) + + if(species == "human") + return 1 + + if(check_rights(R_ADMIN, 0)) + return 1 + + if(!alien_whitelist) + return 0 + + // Species is in whitelist + if("*" in alien_whitelist[species]) + return 1 + + // CKey is in whitelist + if(M.ckey in alien_whitelist[species] || M.ckey in alien_whitelist["all"]) + return 1 + + // Occupation is in whitelist (for lizard janitors :V) + if("job=[lowertext(M.mind.assigned_role)]" in alien_whitelist[species]\ + || "job=[lowertext(M.mind.assigned_role)]" in alien_whitelist["all"]) + return 1 + + return 0 + +/proc/has_whitelist_entries(var/species) + if(!config.usealienwhitelist) + return 1 + species=lowertext(species) + return species in alien_whitelist + #undef WHITELISTFILE \ No newline at end of file diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index 747a1920149..55bf810321b 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -1,330 +1,330 @@ -/obj/machinery/atmospherics/unary/cold_sink/freezer - name = "Freezer" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "freezer_0" - density = 1 - default_colour = "#0000b7" - anchored = 1.0 - var/temp_offset = 0 - - current_heat_capacity = 1000 - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - var/list/rotate_verbs=list( - /obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate, - /obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate_ccw, - ) - -/obj/machinery/atmospherics/unary/cold_sink/freezer/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/freezer, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - - if(anchored) - verbs -= rotate_verbs - - initialize_directions = dir - -/obj/machinery/atmospherics/unary/cold_sink/freezer/RefreshParts() - var/lasercount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 - temp_offset = initial(temp_offset) - 5*lasercount - -/obj/machinery/atmospherics/unary/cold_sink/freezer/update_icon() - if(src.node) - if(src.on) - icon_state = "freezer_1" - else - icon_state = "freezer" - else - icon_state = "freezer_0" - ..() -/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/atmospherics/unary/cold_sink/freezer/crowbarDestroy(mob/user) - if(src.on || anchored) - return - return ..() - -/obj/machinery/atmospherics/unary/cold_sink/freezer/togglePanelOpen(var/obj/toggleitem, mob/user) - if(anchored) +/obj/machinery/atmospherics/unary/cold_sink/freezer + name = "Freezer" + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "freezer_0" + density = 1 + default_colour = "#0000b7" + anchored = 1.0 + var/temp_offset = 0 + + current_heat_capacity = 1000 + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + var/list/rotate_verbs=list( + /obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate, + /obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate_ccw, + ) + +/obj/machinery/atmospherics/unary/cold_sink/freezer/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/freezer, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + + if(anchored) + verbs -= rotate_verbs + + initialize_directions = dir + +/obj/machinery/atmospherics/unary/cold_sink/freezer/RefreshParts() + var/lasercount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 + temp_offset = initial(temp_offset) - 5*lasercount + +/obj/machinery/atmospherics/unary/cold_sink/freezer/update_icon() + if(src.node) + if(src.on) + icon_state = "freezer_1" + else + icon_state = "freezer" + else + icon_state = "freezer_0" + ..() +/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/atmospherics/unary/cold_sink/freezer/crowbarDestroy(mob/user) + if(src.on || anchored) + return + return ..() + +/obj/machinery/atmospherics/unary/cold_sink/freezer/togglePanelOpen(var/obj/toggleitem, mob/user) + if(anchored) to_chat(user, "You have to unanchor the [src] first!") - return - if(src.on) + return + if(src.on) to_chat(user, "You have to turn off the [src]!") - return - return ..() - -/obj/machinery/atmospherics/unary/cold_sink/freezer/wrenchAnchor(mob/user) - if(src.on) + return + return ..() + +/obj/machinery/atmospherics/unary/cold_sink/freezer/wrenchAnchor(mob/user) + if(src.on) to_chat(user, "You have to turn off the [src] first!") - return - ..() - if(!anchored) - verbs += rotate_verbs - if(node) - node.disconnect(src) - qdel(network) - network = null - node = null - else if(anchored) - verbs -= rotate_verbs - initialize_directions = dir - initialize() - build_network() - if (node) - node.initialize() - node.build_network() - return - -/obj/machinery/atmospherics/unary/cold_sink/freezer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - ..() - - -/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_hand(mob/user as mob) - user.set_machine(src) - var/temp_text = "" - if(air_contents.temperature > (T0C - 20)) - temp_text = "[air_contents.temperature]" - else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100)) - temp_text = "[air_contents.temperature]" - else - temp_text = "[air_contents.temperature]" - - var/dat = {"Cryo gas cooling system
      - Current status: [ on ? "Off On" : "Off On"]
      - Current gas temperature: [temp_text]
      - Current air pressure: [air_contents.return_pressure()]
      - Target gas temperature: - - - [current_temperature] + + +
      - "} - - user << browse(dat, "window=freezer;size=400x500") - onclose(user, "freezer") - -/obj/machinery/atmospherics/unary/cold_sink/freezer/Topic(href, href_list) - if(..()) return 1 - else - usr.set_machine(src) - if (href_list["start"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"turned [on?"off":"on"]")) - return - src.on = !src.on - update_icon() - if(href_list["temp"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"set temperature of")) - return - var/amount = text2num(href_list["temp"]) - if(amount > 0) - src.current_temperature = min(T20C, src.current_temperature+amount) - else - src.current_temperature = max((T0C - 200 + temp_offset), src.current_temperature+amount) - src.updateUsrDialog() - src.add_fingerprint(usr) - return - -/obj/machinery/atmospherics/unary/cold_sink/freezer/process() - ..() - src.updateUsrDialog() - - -/obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate() - set name = "Rotate Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return + ..() + if(!anchored) + verbs += rotate_verbs + if(node) + node.disconnect(src) + qdel(network) + network = null + node = null + else if(anchored) + verbs -= rotate_verbs + initialize_directions = dir + initialize() + build_network() + if (node) + node.initialize() + node.build_network() + return + +/obj/machinery/atmospherics/unary/cold_sink/freezer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + ..() + + +/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_hand(mob/user as mob) + user.set_machine(src) + var/temp_text = "" + if(air_contents.temperature > (T0C - 20)) + temp_text = "[air_contents.temperature]" + else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100)) + temp_text = "[air_contents.temperature]" + else + temp_text = "[air_contents.temperature]" + + var/dat = {"Cryo gas cooling system
      + Current status: [ on ? "Off On" : "Off On"]
      + Current gas temperature: [temp_text]
      + Current air pressure: [air_contents.return_pressure()]
      + Target gas temperature: - - - [current_temperature] + + +
      + "} + + user << browse(dat, "window=freezer;size=400x500") + onclose(user, "freezer") + +/obj/machinery/atmospherics/unary/cold_sink/freezer/Topic(href, href_list) + if(..()) return 1 + else + usr.set_machine(src) + if (href_list["start"]) + if(isobserver(usr) && !canGhostWrite(usr,src,"turned [on?"off":"on"]")) + return + src.on = !src.on + update_icon() + if(href_list["temp"]) + if(isobserver(usr) && !canGhostWrite(usr,src,"set temperature of")) + return + var/amount = text2num(href_list["temp"]) + if(amount > 0) + src.current_temperature = min(T20C, src.current_temperature+amount) + else + src.current_temperature = max((T0C - 200 + temp_offset), src.current_temperature+amount) + src.updateUsrDialog() + src.add_fingerprint(usr) + return + +/obj/machinery/atmospherics/unary/cold_sink/freezer/process() + ..() + src.updateUsrDialog() + + +/obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate() + set name = "Rotate Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 270) - return 1 - -/obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate_ccw() - set name = "Rotate Counter Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return 0 + src.dir = turn(src.dir, 270) + return 1 + +/obj/machinery/atmospherics/unary/cold_sink/freezer/verb/rotate_ccw() + set name = "Rotate Counter Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 90) - return 1 - - -/obj/machinery/atmospherics/unary/heat_reservoir/heater - name = "Heater" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "freezer_0" - density = 1 - anchored = 1.0 - default_colour = "#b70000" - current_heat_capacity = 1000 - var/temp_offset = 0 - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - var/list/rotate_verbs=list( - /obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate, - /obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate_ccw, - ) - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/heater, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - - if(anchored) - verbs -= rotate_verbs - - initialize_directions = dir - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/RefreshParts() - var/lasercount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 - temp_offset = initial(temp_offset) + 5*lasercount - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/update_icon() - if(src.node) - if(src.on) - icon_state = "heater_1" - else - icon_state = "heater" - else - icon_state = "heater_0" - ..() - return - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/crowbarDestroy(mob/user) - if(src.on || anchored) - return - return ..() - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/togglePanelOpen(var/obj/toggleitem, mob/user) - if(anchored) + return 0 + src.dir = turn(src.dir, 90) + return 1 + + +/obj/machinery/atmospherics/unary/heat_reservoir/heater + name = "Heater" + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "freezer_0" + density = 1 + anchored = 1.0 + default_colour = "#b70000" + current_heat_capacity = 1000 + var/temp_offset = 0 + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + var/list/rotate_verbs=list( + /obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate, + /obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate_ccw, + ) + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/heater, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + + if(anchored) + verbs -= rotate_verbs + + initialize_directions = dir + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/RefreshParts() + var/lasercount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 + temp_offset = initial(temp_offset) + 5*lasercount + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/update_icon() + if(src.node) + if(src.on) + icon_state = "heater_1" + else + icon_state = "heater" + else + icon_state = "heater_0" + ..() + return + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/crowbarDestroy(mob/user) + if(src.on || anchored) + return + return ..() + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/togglePanelOpen(var/obj/toggleitem, mob/user) + if(anchored) to_chat(user, "You have to unanchor the [src] first!") - return - if(src.on) + return + if(src.on) to_chat(user, "You have to turn off the [src]!") - return - return ..() - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/wrenchAnchor(mob/user) - if(src.on) + return + return ..() + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/wrenchAnchor(mob/user) + if(src.on) to_chat(user, "You have to turn off the [src] first!") - return - ..() - if(!anchored) - verbs += rotate_verbs - if(node) - node.disconnect(src) - qdel(network) - network = null - node = null - else if(anchored) - verbs -= rotate_verbs - initialize_directions = dir - initialize() - build_network() - if (node) - node.initialize() - node.build_network() - return - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - ..() - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_hand(mob/user as mob) - user.set_machine(src) - var/temp_text = "" - if(air_contents.temperature > (T20C+40)) - temp_text = "[air_contents.temperature]" - else - temp_text = "[air_contents.temperature]" - - var/dat = {"Heating system
      - Current status: [ on ? "Off On" : "Off On"]
      - Current gas temperature: [temp_text]
      - Current air pressure: [air_contents.return_pressure()]
      - Target gas temperature: - - - [current_temperature] + + +
      - "} - - user << browse(dat, "window=heater;size=400x500") - onclose(user, "heater") - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/Topic(href, href_list) - if(..()) return 1 - else - usr.set_machine(src) - if (href_list["start"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"turned [on?"off":"on"]")) - return - src.on = !src.on - update_icon() - if(href_list["temp"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"set temperature of")) - return - var/amount = text2num(href_list["temp"]) - if(amount > 0) - src.current_temperature = min((T20C+280+temp_offset), src.current_temperature+amount) - else - src.current_temperature = max(T20C, src.current_temperature+amount) - src.updateUsrDialog() - src.add_fingerprint(usr) - return - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/process() - ..() - src.updateUsrDialog() - - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate() - set name = "Rotate Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return + ..() + if(!anchored) + verbs += rotate_verbs + if(node) + node.disconnect(src) + qdel(network) + network = null + node = null + else if(anchored) + verbs -= rotate_verbs + initialize_directions = dir + initialize() + build_network() + if (node) + node.initialize() + node.build_network() + return + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + ..() + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_hand(mob/user as mob) + user.set_machine(src) + var/temp_text = "" + if(air_contents.temperature > (T20C+40)) + temp_text = "[air_contents.temperature]" + else + temp_text = "[air_contents.temperature]" + + var/dat = {"Heating system
      + Current status: [ on ? "Off On" : "Off On"]
      + Current gas temperature: [temp_text]
      + Current air pressure: [air_contents.return_pressure()]
      + Target gas temperature: - - - [current_temperature] + + +
      + "} + + user << browse(dat, "window=heater;size=400x500") + onclose(user, "heater") + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/Topic(href, href_list) + if(..()) return 1 + else + usr.set_machine(src) + if (href_list["start"]) + if(isobserver(usr) && !canGhostWrite(usr,src,"turned [on?"off":"on"]")) + return + src.on = !src.on + update_icon() + if(href_list["temp"]) + if(isobserver(usr) && !canGhostWrite(usr,src,"set temperature of")) + return + var/amount = text2num(href_list["temp"]) + if(amount > 0) + src.current_temperature = min((T20C+280+temp_offset), src.current_temperature+amount) + else + src.current_temperature = max(T20C, src.current_temperature+amount) + src.updateUsrDialog() + src.add_fingerprint(usr) + return + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/process() + ..() + src.updateUsrDialog() + + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate() + set name = "Rotate Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 270) - return 1 - -/obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate_ccw() - set name = "Rotate Counter Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return 0 + src.dir = turn(src.dir, 270) + return 1 + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/verb/rotate_ccw() + set name = "Rotate Counter Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 90) - return 1 + return 0 + src.dir = turn(src.dir, 90) + return 1 diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 80e202ffba1..526fcb9cf54 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -1,184 +1,184 @@ -/obj/machinery/optable - name = "Operating Table" - desc = "Used for advanced medical procedures." - icon = 'icons/obj/surgery.dmi' - icon_state = "table2-idle" - density = 1 - anchored = 1.0 - use_power = 1 - idle_power_usage = 1 - active_power_usage = 5 - var/mob/living/carbon/human/victim = null - var/strapped = 0.0 - throwpass = 1 //so Adjacent passes. - var/rating = 1 //Use this for upgrades some day - - var/obj/machinery/computer/operating/computer = null - -/obj/machinery/optable/New() - ..() - for(dir in list(NORTH,EAST,SOUTH,WEST)) - computer = locate(/obj/machinery/computer/operating, get_step(src, dir)) - if (computer) - break -// spawn(100) //Wont the MC just call this process() before and at the 10 second mark anyway? -// process() - -/obj/machinery/optable/ex_act(severity) - - switch(severity) - if(1.0) - //SN src = null - qdel(src) - return - if(2.0) - if (prob(50)) - //SN src = null - qdel(src) - return - if(3.0) - if (prob(25)) - src.density = 0 - else - return - -/obj/machinery/optable/blob_act() - if(prob(75)) - qdel(src) - -/obj/machinery/optable/attack_paw(mob/user as mob) - if ((M_HULK in usr.mutations)) - to_chat(usr, text("You destroy the operating table.")) - visible_message("[usr] destroys the operating table!") - src.density = 0 - qdel(src) - return - if (!( locate(/obj/machinery/optable, user.loc) )) - step(user, get_dir(user, src)) - if (user.loc == src.loc) - user.layer = TURF_LAYER - visible_message("The monkey hides under the table!") - return - -/obj/machinery/optable/attack_hand(mob/user as mob) - if (M_HULK in usr.mutations) - to_chat(usr, text("You destroy the table.")) - visible_message("[usr] destroys the operating table!") - src.density = 0 - qdel(src) - return - -/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else - return 0 - - -/obj/machinery/optable/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - - if ((( istype(O, /obj/item/weapon) ) || user.get_active_hand() == O)) - - if(user.drop_item(O)) - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return - else - if(!ismob(O)) //humans only - return - if(O.loc == user || !isturf(O.loc) || !isturf(user.loc)) //no you can't pull things out of your ass - return - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other - return - if(O.anchored || !Adjacent(user) || !user.Adjacent(src)) // is the mob anchored, too far away from you, or are you too far away from the source - return - if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit - return - if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper - return - if(user.loc==null) // just in case someone manages to get a closet into the blue light dimension, as unlikely as that seems - return - var/mob/living/L = O - if(!istype(L) || L.locked_to || L == user) - return - - take_victim(L, user) - return - -/obj/machinery/optable/proc/check_victim() - if (victim) - if (victim.loc == src.loc) - if (victim.lying) - if (victim.pulse) - icon_state = "table2-active" - else - icon_state = "table2-idle" - - return 1 - - victim.reset_view() - victim = null - - icon_state = "table2-idle" - return 0 - -/obj/machinery/optable/process() - check_victim() - -/obj/machinery/optable/proc/take_victim(mob/living/carbon/C, mob/living/carbon/user as mob) - if (victim) - to_chat(user, "The table is already occupied!") - - C.unlock_from() - C.forceMove(loc) - - if (C.client) - C.client.perspective = EYE_PERSPECTIVE - C.client.eye = src - - if (ishuman(C)) - victim = C - C.resting = 1 - - if (C == user) - user.visible_message("[user] climbs on the operating table.","You climb on the operating table.") - else - visible_message("[C] has been laid on the operating table by [user].", 2) //spooky - - add_fingerprint(user) - -/obj/machinery/optable/verb/climb_on() - set name = "Climb On Table" - set category = "Object" - set src in oview(1) - - if(usr.isUnconscious() || !ishuman(usr) || usr.locked_to || usr.restrained()) - return - - take_victim(usr, usr) - -/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob) - if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 40)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - switch(rating) - if(1) - new /obj/item/weapon/stock_parts/scanning_module(src.loc) - if(2) - new /obj/item/weapon/stock_parts/scanning_module/adv(src.loc) - if(3) - new /obj/item/weapon/stock_parts/scanning_module/adv/phasic(src.loc) - new /obj/structure/table/reinforced(src.loc) - qdel(src) - return - if (istype(W, /obj/item/weapon/grab)) - if(iscarbon(W:affecting)) - take_victim(W:affecting,usr) - returnToPool(W) - return - if(isrobot(user)) return - user.drop_item(W, src.loc) - return +/obj/machinery/optable + name = "Operating Table" + desc = "Used for advanced medical procedures." + icon = 'icons/obj/surgery.dmi' + icon_state = "table2-idle" + density = 1 + anchored = 1.0 + use_power = 1 + idle_power_usage = 1 + active_power_usage = 5 + var/mob/living/carbon/human/victim = null + var/strapped = 0.0 + throwpass = 1 //so Adjacent passes. + var/rating = 1 //Use this for upgrades some day + + var/obj/machinery/computer/operating/computer = null + +/obj/machinery/optable/New() + ..() + for(dir in list(NORTH,EAST,SOUTH,WEST)) + computer = locate(/obj/machinery/computer/operating, get_step(src, dir)) + if (computer) + break +// spawn(100) //Wont the MC just call this process() before and at the 10 second mark anyway? +// process() + +/obj/machinery/optable/ex_act(severity) + + switch(severity) + if(1.0) + //SN src = null + qdel(src) + return + if(2.0) + if (prob(50)) + //SN src = null + qdel(src) + return + if(3.0) + if (prob(25)) + src.density = 0 + else + return + +/obj/machinery/optable/blob_act() + if(prob(75)) + qdel(src) + +/obj/machinery/optable/attack_paw(mob/user as mob) + if ((M_HULK in usr.mutations)) + to_chat(usr, text("You destroy the operating table.")) + visible_message("[usr] destroys the operating table!") + src.density = 0 + qdel(src) + return + if (!( locate(/obj/machinery/optable, user.loc) )) + step(user, get_dir(user, src)) + if (user.loc == src.loc) + user.layer = TURF_LAYER + visible_message("The monkey hides under the table!") + return + +/obj/machinery/optable/attack_hand(mob/user as mob) + if (M_HULK in usr.mutations) + to_chat(usr, text("You destroy the table.")) + visible_message("[usr] destroys the operating table!") + src.density = 0 + qdel(src) + return + +/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + else + return 0 + + +/obj/machinery/optable/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + + if ((( istype(O, /obj/item/weapon) ) || user.get_active_hand() == O)) + + if(user.drop_item(O)) + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return + else + if(!ismob(O)) //humans only + return + if(O.loc == user || !isturf(O.loc) || !isturf(user.loc)) //no you can't pull things out of your ass + return + if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other + return + if(O.anchored || !Adjacent(user) || !user.Adjacent(src)) // is the mob anchored, too far away from you, or are you too far away from the source + return + if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit + return + if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper + return + if(user.loc==null) // just in case someone manages to get a closet into the blue light dimension, as unlikely as that seems + return + var/mob/living/L = O + if(!istype(L) || L.locked_to || L == user) + return + + take_victim(L, user) + return + +/obj/machinery/optable/proc/check_victim() + if (victim) + if (victim.loc == src.loc) + if (victim.lying) + if (victim.pulse) + icon_state = "table2-active" + else + icon_state = "table2-idle" + + return 1 + + victim.reset_view() + victim = null + + icon_state = "table2-idle" + return 0 + +/obj/machinery/optable/process() + check_victim() + +/obj/machinery/optable/proc/take_victim(mob/living/carbon/C, mob/living/carbon/user as mob) + if (victim) + to_chat(user, "The table is already occupied!") + + C.unlock_from() + C.forceMove(loc) + + if (C.client) + C.client.perspective = EYE_PERSPECTIVE + C.client.eye = src + + if (ishuman(C)) + victim = C + C.resting = 1 + + if (C == user) + user.visible_message("[user] climbs on the operating table.","You climb on the operating table.") + else + visible_message("[C] has been laid on the operating table by [user].", 2) //spooky + + add_fingerprint(user) + +/obj/machinery/optable/verb/climb_on() + set name = "Climb On Table" + set category = "Object" + set src in oview(1) + + if(usr.isUnconscious() || !ishuman(usr) || usr.locked_to || usr.restrained()) + return + + take_victim(usr, usr) + +/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob) + if(iswrench(W)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 40)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + switch(rating) + if(1) + new /obj/item/weapon/stock_parts/scanning_module(src.loc) + if(2) + new /obj/item/weapon/stock_parts/scanning_module/adv(src.loc) + if(3) + new /obj/item/weapon/stock_parts/scanning_module/adv/phasic(src.loc) + new /obj/structure/table/reinforced(src.loc) + qdel(src) + return + if (istype(W, /obj/item/weapon/grab)) + if(iscarbon(W:affecting)) + take_victim(W:affecting,usr) + returnToPool(W) + return + if(isrobot(user)) return + user.drop_item(W, src.loc) + return diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 32114c90c83..de5b31ca7d0 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -1,556 +1,556 @@ -#define SLEEPER_SOPORIFIC_DELAY 30 - -///////////////////////////////////////// -// SLEEPER CONSOLE -///////////////////////////////////////// - -/obj/machinery/sleep_console - name = "Sleeper Console" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "sleeperconsole" - var/obj/machinery/sleeper/connected = null - anchored = 1 //About time someone fixed this. - density = 1 - var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" - -/obj/machinery/sleep_console/ex_act(severity) - switch(severity) - if(1.0) - //SN src = null - qdel(src) - return - if(2.0) - if (prob(50)) - //SN src = null - qdel(src) - return - else - return - -/obj/machinery/sleep_console/New() - ..() - spawn( 5 ) - update_icon() - if(orient == "RIGHT") - src.connected = locate(/obj/machinery/sleeper, get_step(src, EAST)) - else - src.connected = locate(/obj/machinery/sleeper, get_step(src, WEST)) - return - -/obj/machinery/sleep_console/update_icon() - icon_state = "sleeperconsole[stat & NOPOWER ? "-p" : null][orient == "LEFT" ? null : "-r"]" - -/obj/machinery/sleep_console/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/sleep_console/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/sleep_console/attack_hand(mob/user as mob) - if(..()) - return - if (src.connected) - var/mob/living/occupant = src.connected.occupant - var/dat = "Occupant Statistics:
      " - if (occupant) - var/t1 - switch(occupant.stat) - if(0) - t1 = "Conscious" - if(1) - t1 = "Unconscious" - if(2) - t1 = "*dead*" - else - dat += text("[]\tHealth %: [] ([])
      ", (occupant.health > 50 ? "" : ""), occupant.health, t1) - if(iscarbon(occupant)) - var/mob/living/carbon/C = occupant - dat += text("[]\t-Pulse, bpm: []
      ", (C.pulse == PULSE_NONE || C.pulse == PULSE_THREADY ? "" : ""), C.get_pulse(GETPULSE_TOOL)) - dat += text("[]\t-Brute Damage %: []
      ", (occupant.getBruteLoss() < 60 ? "" : ""), occupant.getBruteLoss()) - dat += text("[]\t-Respiratory Damage %: []
      ", (occupant.getOxyLoss() < 60 ? "" : ""), occupant.getOxyLoss()) - dat += text("[]\t-Toxin Content %: []
      ", (occupant.getToxLoss() < 60 ? "" : ""), occupant.getToxLoss()) - dat += text("[]\t-Burn Severity %: []
      ", (occupant.getFireLoss() < 60 ? "" : ""), occupant.getFireLoss()) - dat += text("
      Paralysis Summary %: [] ([] seconds left!)
      ", occupant.paralysis, round(occupant.paralysis / 4)) - if(occupant.reagents) - for(var/chemical in connected.available_chemicals) - dat += "[connected.available_chemicals[chemical]]: [occupant.reagents.get_reagent_amount(chemical)] units
      " - dat += "
      Refresh meter readings each second
      " - for(var/chemical in connected.available_chemicals) - dat += "Inject [connected.available_chemicals[chemical]]: " - for(var/amount in connected.amounts) - dat += "[amount] units " - dat += "
      " - else - dat += "The sleeper is empty." - dat += text("

      Close", user) - user << browse(dat, "window=sleeper;size=400x500") - onclose(user, "sleeper") - return - -/obj/machinery/sleep_console/Topic(href, href_list) - if(..()) - return 1 - else - usr.set_machine(src) - if (href_list["chemical"]) - if (src.connected) - if (src.connected.occupant) - if (src.connected.occupant.stat == DEAD) - to_chat(usr, "This person has no life for to preserve anymore. Take them to a department capable of reanimating them.") - else if(href_list["chemical"] == "stoxin" && src.connected.sedativeblock) - if(src.connected.sedativeblock < 3) - to_chat(usr, "Sedative injections not yet ready. Please try again in a few seconds.") - else //if this guy is seriously just mashing the soporific button... - to_chat(usr, "[pick( \ - "This guy just got jammed into the machine, give them a breath before trying to pump them full of drugs.", \ - "Give it a rest.", \ - "Aren't you going to tuck them in before putting them to sleep?", \ - "Slow down just a second, they aren't going anywhere... right?", \ - "Just got to make sure you're not tripping the fuck out of an innocent bystander, stay tight.", \ - "The occupant is still moving around!", \ - "Sorry pal, safety procedures.", \ - "But it's not bedtime yet!")]") - src.connected.sedativeblock++ - else if(src.connected.occupant.health < 0 && href_list["chemical"] != "inaprovaline") - to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!") - else - src.connected.inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) - if (href_list["refresh"]) - src.updateUsrDialog() - src.add_fingerprint(usr) - return - -/obj/machinery/sleep_console/process() - if(stat & (NOPOWER|BROKEN)) - return - src.updateUsrDialog() - return - -/obj/machinery/sleep_console/power_change() - return - // no change - sleeper works without power (you just can't inject more) - - - - - - - -///////////////////////////////////////// -// THE SLEEPER ITSELF -///////////////////////////////////////// - -/obj/machinery/sleeper - name = "Sleeper" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "sleeper_0" - density = 1 - anchored = 1 - var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" - var/mob/living/occupant = null - var/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin") - var/amounts = list(5, 10) - var/obj/machinery/sleep_console/connected = null - var/sedativeblock = 0 //To prevent people from being surprisesoporific'd - machine_flags = SCREWTOGGLE | CROWDESTROY - component_parts = newlist( - /obj/item/weapon/circuitboard/sleeper, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator - ) - light_color = LIGHT_COLOR_CYAN - light_range_on = 3 - light_power_on = 2 - power_change() - ..() - if(!(stat & (BROKEN|NOPOWER)) && occupant) - set_light(light_range_on, light_power_on) - else - set_light(0) - -/obj/machinery/sleeper/New() - ..() - RefreshParts() - spawn( 5 ) - var/turf/t - world.log << "DEBUG: Beginning sleeper console checking/auto-generation for sleeper [src] at [src.loc.x],[src.loc.y],[src.loc.z]..." - if(orient == "RIGHT") - update_icon() // Only needs to update if it's orientation isn't default - t = get_step(get_turf(src), WEST) - // generate_console(get_step(get_turf(src), WEST)) - else - t = get_step(get_turf(src), EAST) - // generate_console(get_step(get_turf(src), EAST)) - ASSERT(t) - var/obj/machinery/sleep_console/c = locate() in t.contents - if(c) - connected = c - c.connected = src - else - world.log << "DEBUG: generating console at [t.loc.x],[t.loc.y],[t.loc.z] for sleeper at [src.loc.x],[src.loc.y],[src.loc.z]" - generate_console(t) - return - return - -/obj/machinery/sleeper/Destroy() - - go_out() //Eject everything - - . = ..() - - if(connected) - connected.connected = null - qdel(connected) - connected = null - -/obj/machinery/sleeper/update_icon() - icon_state = "sleeper_[occupant ? "1" : "0"][orient == "LEFT" ? null : "-r"]" - -/obj/machinery/sleeper/proc/generate_console(turf/T as turf) - if(connected) - connected.orient = src.orient - connected.update_icon() - return 1 - if(!T.density) - connected = new /obj/machinery/sleep_console(T) - connected.orient = src.orient - connected.update_icon() - return 1 - else - return 0 - -/obj/machinery/sleeper/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - T += SP.rating - switch(T) - if(0 to 5) - available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin") - if(6 to 8) - available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin", "phalanximine" = "Phalanximine") - else - available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin", "phalanximine" = "Phalanximine", "spaceacillin" = "Spaceacillin") - - -/obj/machinery/sleeper/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if(!ismob(O)) //mobs only - return - if(O.loc == user || !isturf(O.loc) || !isturf(user.loc)) //no you can't pull things out of your ass - return - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other - return - if(O.anchored || !Adjacent(user) || !user.Adjacent(src) || user.contents.Find(src)) // is the mob anchored, too far away from you, or are you too far away from the source - return - if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit - return - if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper - return - if(user.loc==null) // just in case someone manages to get a closet into the blue light dimension, as unlikely as that seems - return - if(occupant) - to_chat(user, "\The [src] is already occupied!") - return - if(isrobot(user)) - var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) - to_chat(user, "You do not have the means to do this!") - return - var/mob/living/L = O - if(!istype(L) || L.locked_to) - return - /*if(L.abiotic()) - to_chat(user, "Subject cannot have abiotic items on.") - return*/ - for(var/mob/living/carbon/slime/M in range(1,L)) - if(M.Victim == L) - to_chat(usr, "[L.name] will not fit into the sleeper because they have a slime latched onto their head.") - return - - if(L == user) - visible_message("[user] climbs into \the [src].", 2) //spooky - else - visible_message("[user] places [L.name] into \the [src].", 2) //spooky - - L.forceMove(src) - L.reset_view() - src.occupant = L - update_icon() - to_chat(L, "You feel cool air surround you. You go numb as your senses turn inward.") - for(var/obj/OO in src) - OO.loc = src.loc - src.add_fingerprint(user) - if(user.pulling == L) - user.stop_pulling() - if(!(stat & (BROKEN|NOPOWER))) - set_light(light_range_on, light_power_on) - sedativeblock = 1 - sleep(SLEEPER_SOPORIFIC_DELAY) - sedativeblock = 0 - return - - -/obj/machinery/sleeper/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) - if(!ishuman(usr) && !isrobot(usr)) - return - if(!occupant) - to_chat(usr, "The sleeper is unoccupied!") - return - if(isrobot(usr)) - var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) - to_chat(usr, "You do not have the means to do this!") - return - if(!istype(over_location) || over_location.density) - return - if(!Adjacent(over_location)) - return - var/mob/user = usr - if(user.restrained() || user.isUnconscious() || user.stunned || user.paralysis || user.resting) // If you're too disabled to put someone into it, you're too disabled to pull someone out of it. - return - if(!(occupant == usr) && (!Adjacent(usr) || !usr.Adjacent(over_location))) - return - for(var/atom/movable/A in over_location.contents) - if(A.density) - if((A == src) || istype(A, /mob)) - continue - return - if(occupant == usr) - visible_message("[usr] climbs out of \the [src].", 2) //spooky - else - visible_message("[usr] removes [occupant.name] from \the [src].", 2) //spooky - go_out(over_location) - -/obj/machinery/sleeper/allow_drop() - return 0 - - -/obj/machinery/sleeper/process() - src.updateDialog() - return - - -/obj/machinery/sleeper/blob_act() - if(prob(75)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - A.blob_act() - qdel(src) - return - -/obj/machinery/sleeper/crowbarDestroy(mob/user) - if(occupant) - to_chat(user, "You cannot disassemble \the [src], it's occupado.") - return - return ..() - -/obj/machinery/sleeper/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(iswrench(W)&&!occupant) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(orient == "RIGHT") - orient = "LEFT" - if(generate_console(get_step(get_turf(src), EAST))) - update_icon() - else - orient = "RIGHT" - to_chat(user, "There is no space!") - else - orient = "RIGHT" - if(generate_console(get_step(get_turf(src), WEST))) - update_icon() - else - orient = "LEFT" - visible_message("There is no space!","[user] wants to be hardcore, but his CMO won't let him.") - return - if(!istype(W, /obj/item/weapon/grab)) - return ..() - var/obj/item/weapon/grab/G = W - if(!(ismob(G.affecting)) || G.affecting.locked_to) return - if(src.occupant) - to_chat(user, "The sleeper is already occupied!") - return - - for(var/mob/living/carbon/slime/M in range(1,G.affecting)) - if(M.Victim == G.affecting) - to_chat(usr, "[G.affecting.name] will not fit into the sleeper because they have a slime latched onto their head.") - return - - visible_message("[user] places [G.affecting.name] into the sleeper.", 2) //spooky - - var/mob/M = G.affecting - if(!isliving(M) || M.locked_to) - return - M.forceMove(src) - M.reset_view() - src.occupant = M - update_icon() - - to_chat(M, "You feel cool air surround you. You go numb as your senses turn inward.") - - for(var/obj/O in src) - O.loc = src.loc - src.add_fingerprint(user) - qdel(G) - if(!(stat & (BROKEN|NOPOWER))) - set_light(light_range_on, light_power_on) - sedativeblock = 1 - spawn(SLEEPER_SOPORIFIC_DELAY) - sedativeblock = 0 - return - -/obj/machinery/sleeper/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - if(2.0) - if(prob(50)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - if(3.0) - if(prob(25)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - return -/obj/machinery/sleeper/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - if(occupant) - go_out() - ..(severity) - -/obj/machinery/sleeper/alter_health(mob/living/M as mob) - if (M.health > 0) - if (M.getOxyLoss() >= 10) - var/amount = max(0.15, 1) - M.adjustOxyLoss(-amount) - else - M.adjustOxyLoss(-12) - M.updatehealth() - M.AdjustParalysis(-4) - M.AdjustWeakened(-4) - M.AdjustStunned(-4) - M.Paralyse(1) - M.Weaken(1) - M.Stun(1) - if (M:reagents.get_reagent_amount("inaprovaline") < 5) - M:reagents.add_reagent("inaprovaline", 5) - return - - -/obj/machinery/sleeper/proc/go_out(var/exit = src.loc) - if(!occupant) - return 0 - for (var/atom/movable/x in src.contents) - if(x in component_parts) - continue - x.forceMove(src.loc) - occupant.forceMove(exit) - occupant.reset_view() - occupant = null - update_icon() - return 1 - - -/obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount) - if(!src.occupant) - to_chat(user, "There's no occupant in the sleeper!") - return - if(isnull(src.occupant.reagents)) - to_chat(user, "The occupant appears to somehow lack a bloodstream. Please consult a shrink.") - return - if(src.occupant.reagents.get_reagent_amount(chemical) + amount > 20) - to_chat(user, "Overdose Prevention System: The occupant already has enough [available_chemicals[chemical]] in their system.") - return - src.occupant.reagents.add_reagent(chemical, amount) - to_chat(user, "Occupant now has [src.occupant.reagents.get_reagent_amount(chemical)] units of [available_chemicals[chemical]] in their bloodstream.") - return - -/obj/machinery/sleeper/proc/check(mob/living/user as mob) - if(src.occupant) - to_chat(user, text("Occupant ([]) Statistics:", src.occupant)) - var/t1 - switch(src.occupant.stat) - if(0.0) - t1 = "Conscious" - if(1.0) - t1 = "Unconscious" - if(2.0) - t1 = "*dead*" - else - to_chat(user, text("[]\t Health %: [] ([])
      ", (src.occupant.health > 50 ? "" : " "), src.occupant.health, t1)) - to_chat(user, text("[]\t -Core Temperature: []°C ([]°F)
      ", (src.occupant.bodytemperature > 50 ? "" : ""), src.occupant.bodytemperature-T0C, src.occupant.bodytemperature*1.8-459.67)) - to_chat(user, text("[]\t -Brute Damage %: []
      ", (src.occupant.getBruteLoss() < 60 ? "" : " "), src.occupant.getBruteLoss())) - to_chat(user, text("[]\t -Respiratory Damage %: []", (src.occupant.getOxyLoss() < 60 ? "" : " "), src.occupant.getOxyLoss())) - to_chat(user, text("[]\t -Toxin Content %: []", (src.occupant.getToxLoss() < 60 ? "" : " "), src.occupant.getToxLoss())) - to_chat(user, text("[]\t -Burn Severity %: []", (src.occupant.getFireLoss() < 60 ? "" : " "), src.occupant.getFireLoss())) - to_chat(user, "Expected time till occupant can safely awake: (note: If health is below 20% these times are inaccurate)") - to_chat(user, text("\t [] second\s (if around 1 or 2 the sleeper is keeping them asleep.)", src.occupant.paralysis / 5)) - else - to_chat(user, "There is no one inside!") - return - - -/obj/machinery/sleeper/verb/eject() - set name = "Eject Sleeper" - set category = "Object" - set src in oview(1) - if(usr.isUnconscious()) - return - src.go_out() - add_fingerprint(usr) - set_light(0) - return - - -/obj/machinery/sleeper/verb/move_inside() - set name = "Enter Sleeper" - set category = "Object" - set src in oview(1) - if(usr.isUnconscious() || !(ishuman(usr) || ismonkey(usr))) - return - - if(src.occupant) - to_chat(usr, "The sleeper is already occupied!") - return - if(usr.restrained() || usr.isUnconscious() || usr.weakened || usr.stunned || usr.paralysis || usr.resting) //are you cuffed, dying, lying, stunned or other - return - for(var/mob/living/carbon/slime/M in range(1,usr)) - if(M.Victim == usr) - to_chat(usr, "You're too busy getting your life sucked out of you.") - return - if(usr.locked_to) - return - visible_message("[usr] starts climbing into the sleeper.", 2) //spooky - if(do_after(usr, src, 20)) - if(src.occupant) - to_chat(usr, "The sleeper is already occupied!") - return - if(usr.locked_to) - return - usr.stop_pulling() - usr.loc = src - usr.reset_view() - src.occupant = usr - update_icon() - - for(var/obj/O in src) - qdel(O) - src.add_fingerprint(usr) - if(!(stat & (BROKEN|NOPOWER))) - set_light(light_range_on, light_power_on) - return - return - -#undef SLEEPER_SOPORIFIC_DELAY +#define SLEEPER_SOPORIFIC_DELAY 30 + +///////////////////////////////////////// +// SLEEPER CONSOLE +///////////////////////////////////////// + +/obj/machinery/sleep_console + name = "Sleeper Console" + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "sleeperconsole" + var/obj/machinery/sleeper/connected = null + anchored = 1 //About time someone fixed this. + density = 1 + var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" + +/obj/machinery/sleep_console/ex_act(severity) + switch(severity) + if(1.0) + //SN src = null + qdel(src) + return + if(2.0) + if (prob(50)) + //SN src = null + qdel(src) + return + else + return + +/obj/machinery/sleep_console/New() + ..() + spawn( 5 ) + update_icon() + if(orient == "RIGHT") + src.connected = locate(/obj/machinery/sleeper, get_step(src, EAST)) + else + src.connected = locate(/obj/machinery/sleeper, get_step(src, WEST)) + return + +/obj/machinery/sleep_console/update_icon() + icon_state = "sleeperconsole[stat & NOPOWER ? "-p" : null][orient == "LEFT" ? null : "-r"]" + +/obj/machinery/sleep_console/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/sleep_console/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/sleep_console/attack_hand(mob/user as mob) + if(..()) + return + if (src.connected) + var/mob/living/occupant = src.connected.occupant + var/dat = "Occupant Statistics:
      " + if (occupant) + var/t1 + switch(occupant.stat) + if(0) + t1 = "Conscious" + if(1) + t1 = "Unconscious" + if(2) + t1 = "*dead*" + else + dat += text("[]\tHealth %: [] ([])

      ", (occupant.health > 50 ? "" : ""), occupant.health, t1) + if(iscarbon(occupant)) + var/mob/living/carbon/C = occupant + dat += text("[]\t-Pulse, bpm: []
      ", (C.pulse == PULSE_NONE || C.pulse == PULSE_THREADY ? "" : ""), C.get_pulse(GETPULSE_TOOL)) + dat += text("[]\t-Brute Damage %: []
      ", (occupant.getBruteLoss() < 60 ? "" : ""), occupant.getBruteLoss()) + dat += text("[]\t-Respiratory Damage %: []
      ", (occupant.getOxyLoss() < 60 ? "" : ""), occupant.getOxyLoss()) + dat += text("[]\t-Toxin Content %: []
      ", (occupant.getToxLoss() < 60 ? "" : ""), occupant.getToxLoss()) + dat += text("[]\t-Burn Severity %: []
      ", (occupant.getFireLoss() < 60 ? "" : ""), occupant.getFireLoss()) + dat += text("
      Paralysis Summary %: [] ([] seconds left!)
      ", occupant.paralysis, round(occupant.paralysis / 4)) + if(occupant.reagents) + for(var/chemical in connected.available_chemicals) + dat += "[connected.available_chemicals[chemical]]: [occupant.reagents.get_reagent_amount(chemical)] units
      " + dat += "
      Refresh meter readings each second
      " + for(var/chemical in connected.available_chemicals) + dat += "Inject [connected.available_chemicals[chemical]]: " + for(var/amount in connected.amounts) + dat += "[amount] units " + dat += "
      " + else + dat += "The sleeper is empty." + dat += text("

      Close", user) + user << browse(dat, "window=sleeper;size=400x500") + onclose(user, "sleeper") + return + +/obj/machinery/sleep_console/Topic(href, href_list) + if(..()) + return 1 + else + usr.set_machine(src) + if (href_list["chemical"]) + if (src.connected) + if (src.connected.occupant) + if (src.connected.occupant.stat == DEAD) + to_chat(usr, "This person has no life for to preserve anymore. Take them to a department capable of reanimating them.") + else if(href_list["chemical"] == "stoxin" && src.connected.sedativeblock) + if(src.connected.sedativeblock < 3) + to_chat(usr, "Sedative injections not yet ready. Please try again in a few seconds.") + else //if this guy is seriously just mashing the soporific button... + to_chat(usr, "[pick( \ + "This guy just got jammed into the machine, give them a breath before trying to pump them full of drugs.", \ + "Give it a rest.", \ + "Aren't you going to tuck them in before putting them to sleep?", \ + "Slow down just a second, they aren't going anywhere... right?", \ + "Just got to make sure you're not tripping the fuck out of an innocent bystander, stay tight.", \ + "The occupant is still moving around!", \ + "Sorry pal, safety procedures.", \ + "But it's not bedtime yet!")]") + src.connected.sedativeblock++ + else if(src.connected.occupant.health < 0 && href_list["chemical"] != "inaprovaline") + to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!") + else + src.connected.inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) + if (href_list["refresh"]) + src.updateUsrDialog() + src.add_fingerprint(usr) + return + +/obj/machinery/sleep_console/process() + if(stat & (NOPOWER|BROKEN)) + return + src.updateUsrDialog() + return + +/obj/machinery/sleep_console/power_change() + return + // no change - sleeper works without power (you just can't inject more) + + + + + + + +///////////////////////////////////////// +// THE SLEEPER ITSELF +///////////////////////////////////////// + +/obj/machinery/sleeper + name = "Sleeper" + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "sleeper_0" + density = 1 + anchored = 1 + var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" + var/mob/living/occupant = null + var/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin") + var/amounts = list(5, 10) + var/obj/machinery/sleep_console/connected = null + var/sedativeblock = 0 //To prevent people from being surprisesoporific'd + machine_flags = SCREWTOGGLE | CROWDESTROY + component_parts = newlist( + /obj/item/weapon/circuitboard/sleeper, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator + ) + light_color = LIGHT_COLOR_CYAN + light_range_on = 3 + light_power_on = 2 + power_change() + ..() + if(!(stat & (BROKEN|NOPOWER)) && occupant) + set_light(light_range_on, light_power_on) + else + set_light(0) + +/obj/machinery/sleeper/New() + ..() + RefreshParts() + spawn( 5 ) + var/turf/t + world.log << "DEBUG: Beginning sleeper console checking/auto-generation for sleeper [src] at [src.loc.x],[src.loc.y],[src.loc.z]..." + if(orient == "RIGHT") + update_icon() // Only needs to update if it's orientation isn't default + t = get_step(get_turf(src), WEST) + // generate_console(get_step(get_turf(src), WEST)) + else + t = get_step(get_turf(src), EAST) + // generate_console(get_step(get_turf(src), EAST)) + ASSERT(t) + var/obj/machinery/sleep_console/c = locate() in t.contents + if(c) + connected = c + c.connected = src + else + world.log << "DEBUG: generating console at [t.loc.x],[t.loc.y],[t.loc.z] for sleeper at [src.loc.x],[src.loc.y],[src.loc.z]" + generate_console(t) + return + return + +/obj/machinery/sleeper/Destroy() + + go_out() //Eject everything + + . = ..() + + if(connected) + connected.connected = null + qdel(connected) + connected = null + +/obj/machinery/sleeper/update_icon() + icon_state = "sleeper_[occupant ? "1" : "0"][orient == "LEFT" ? null : "-r"]" + +/obj/machinery/sleeper/proc/generate_console(turf/T as turf) + if(connected) + connected.orient = src.orient + connected.update_icon() + return 1 + if(!T.density) + connected = new /obj/machinery/sleep_console(T) + connected.orient = src.orient + connected.update_icon() + return 1 + else + return 0 + +/obj/machinery/sleeper/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + T += SP.rating + switch(T) + if(0 to 5) + available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin") + if(6 to 8) + available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin", "phalanximine" = "Phalanximine") + else + available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin", "phalanximine" = "Phalanximine", "spaceacillin" = "Spaceacillin") + + +/obj/machinery/sleeper/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if(!ismob(O)) //mobs only + return + if(O.loc == user || !isturf(O.loc) || !isturf(user.loc)) //no you can't pull things out of your ass + return + if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other + return + if(O.anchored || !Adjacent(user) || !user.Adjacent(src) || user.contents.Find(src)) // is the mob anchored, too far away from you, or are you too far away from the source + return + if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit + return + if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper + return + if(user.loc==null) // just in case someone manages to get a closet into the blue light dimension, as unlikely as that seems + return + if(occupant) + to_chat(user, "\The [src] is already occupied!") + return + if(isrobot(user)) + var/mob/living/silicon/robot/robit = usr + if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + to_chat(user, "You do not have the means to do this!") + return + var/mob/living/L = O + if(!istype(L) || L.locked_to) + return + /*if(L.abiotic()) + to_chat(user, "Subject cannot have abiotic items on.") + return*/ + for(var/mob/living/carbon/slime/M in range(1,L)) + if(M.Victim == L) + to_chat(usr, "[L.name] will not fit into the sleeper because they have a slime latched onto their head.") + return + + if(L == user) + visible_message("[user] climbs into \the [src].", 2) //spooky + else + visible_message("[user] places [L.name] into \the [src].", 2) //spooky + + L.forceMove(src) + L.reset_view() + src.occupant = L + update_icon() + to_chat(L, "You feel cool air surround you. You go numb as your senses turn inward.") + for(var/obj/OO in src) + OO.loc = src.loc + src.add_fingerprint(user) + if(user.pulling == L) + user.stop_pulling() + if(!(stat & (BROKEN|NOPOWER))) + set_light(light_range_on, light_power_on) + sedativeblock = 1 + sleep(SLEEPER_SOPORIFIC_DELAY) + sedativeblock = 0 + return + + +/obj/machinery/sleeper/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) + if(!ishuman(usr) && !isrobot(usr)) + return + if(!occupant) + to_chat(usr, "The sleeper is unoccupied!") + return + if(isrobot(usr)) + var/mob/living/silicon/robot/robit = usr + if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + to_chat(usr, "You do not have the means to do this!") + return + if(!istype(over_location) || over_location.density) + return + if(!Adjacent(over_location)) + return + var/mob/user = usr + if(user.restrained() || user.isUnconscious() || user.stunned || user.paralysis || user.resting) // If you're too disabled to put someone into it, you're too disabled to pull someone out of it. + return + if(!(occupant == usr) && (!Adjacent(usr) || !usr.Adjacent(over_location))) + return + for(var/atom/movable/A in over_location.contents) + if(A.density) + if((A == src) || istype(A, /mob)) + continue + return + if(occupant == usr) + visible_message("[usr] climbs out of \the [src].", 2) //spooky + else + visible_message("[usr] removes [occupant.name] from \the [src].", 2) //spooky + go_out(over_location) + +/obj/machinery/sleeper/allow_drop() + return 0 + + +/obj/machinery/sleeper/process() + src.updateDialog() + return + + +/obj/machinery/sleeper/blob_act() + if(prob(75)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + A.blob_act() + qdel(src) + return + +/obj/machinery/sleeper/crowbarDestroy(mob/user) + if(occupant) + to_chat(user, "You cannot disassemble \the [src], it's occupado.") + return + return ..() + +/obj/machinery/sleeper/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(iswrench(W)&&!occupant) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(orient == "RIGHT") + orient = "LEFT" + if(generate_console(get_step(get_turf(src), EAST))) + update_icon() + else + orient = "RIGHT" + to_chat(user, "There is no space!") + else + orient = "RIGHT" + if(generate_console(get_step(get_turf(src), WEST))) + update_icon() + else + orient = "LEFT" + visible_message("There is no space!","[user] wants to be hardcore, but his CMO won't let him.") + return + if(!istype(W, /obj/item/weapon/grab)) + return ..() + var/obj/item/weapon/grab/G = W + if(!(ismob(G.affecting)) || G.affecting.locked_to) return + if(src.occupant) + to_chat(user, "The sleeper is already occupied!") + return + + for(var/mob/living/carbon/slime/M in range(1,G.affecting)) + if(M.Victim == G.affecting) + to_chat(usr, "[G.affecting.name] will not fit into the sleeper because they have a slime latched onto their head.") + return + + visible_message("[user] places [G.affecting.name] into the sleeper.", 2) //spooky + + var/mob/M = G.affecting + if(!isliving(M) || M.locked_to) + return + M.forceMove(src) + M.reset_view() + src.occupant = M + update_icon() + + to_chat(M, "You feel cool air surround you. You go numb as your senses turn inward.") + + for(var/obj/O in src) + O.loc = src.loc + src.add_fingerprint(user) + qdel(G) + if(!(stat & (BROKEN|NOPOWER))) + set_light(light_range_on, light_power_on) + sedativeblock = 1 + spawn(SLEEPER_SOPORIFIC_DELAY) + sedativeblock = 0 + return + +/obj/machinery/sleeper/ex_act(severity) + switch(severity) + if(1.0) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + if(2.0) + if(prob(50)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + if(3.0) + if(prob(25)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + return +/obj/machinery/sleeper/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + if(occupant) + go_out() + ..(severity) + +/obj/machinery/sleeper/alter_health(mob/living/M as mob) + if (M.health > 0) + if (M.getOxyLoss() >= 10) + var/amount = max(0.15, 1) + M.adjustOxyLoss(-amount) + else + M.adjustOxyLoss(-12) + M.updatehealth() + M.AdjustParalysis(-4) + M.AdjustWeakened(-4) + M.AdjustStunned(-4) + M.Paralyse(1) + M.Weaken(1) + M.Stun(1) + if (M:reagents.get_reagent_amount("inaprovaline") < 5) + M:reagents.add_reagent("inaprovaline", 5) + return + + +/obj/machinery/sleeper/proc/go_out(var/exit = src.loc) + if(!occupant) + return 0 + for (var/atom/movable/x in src.contents) + if(x in component_parts) + continue + x.forceMove(src.loc) + occupant.forceMove(exit) + occupant.reset_view() + occupant = null + update_icon() + return 1 + + +/obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount) + if(!src.occupant) + to_chat(user, "There's no occupant in the sleeper!") + return + if(isnull(src.occupant.reagents)) + to_chat(user, "The occupant appears to somehow lack a bloodstream. Please consult a shrink.") + return + if(src.occupant.reagents.get_reagent_amount(chemical) + amount > 20) + to_chat(user, "Overdose Prevention System: The occupant already has enough [available_chemicals[chemical]] in their system.") + return + src.occupant.reagents.add_reagent(chemical, amount) + to_chat(user, "Occupant now has [src.occupant.reagents.get_reagent_amount(chemical)] units of [available_chemicals[chemical]] in their bloodstream.") + return + +/obj/machinery/sleeper/proc/check(mob/living/user as mob) + if(src.occupant) + to_chat(user, text("Occupant ([]) Statistics:", src.occupant)) + var/t1 + switch(src.occupant.stat) + if(0.0) + t1 = "Conscious" + if(1.0) + t1 = "Unconscious" + if(2.0) + t1 = "*dead*" + else + to_chat(user, text("[]\t Health %: [] ([])
      ", (src.occupant.health > 50 ? "" : " "), src.occupant.health, t1)) + to_chat(user, text("[]\t -Core Temperature: []°C ([]°F)
      ", (src.occupant.bodytemperature > 50 ? "" : ""), src.occupant.bodytemperature-T0C, src.occupant.bodytemperature*1.8-459.67)) + to_chat(user, text("[]\t -Brute Damage %: []
      ", (src.occupant.getBruteLoss() < 60 ? "" : " "), src.occupant.getBruteLoss())) + to_chat(user, text("[]\t -Respiratory Damage %: []", (src.occupant.getOxyLoss() < 60 ? "" : " "), src.occupant.getOxyLoss())) + to_chat(user, text("[]\t -Toxin Content %: []", (src.occupant.getToxLoss() < 60 ? "" : " "), src.occupant.getToxLoss())) + to_chat(user, text("[]\t -Burn Severity %: []", (src.occupant.getFireLoss() < 60 ? "" : " "), src.occupant.getFireLoss())) + to_chat(user, "Expected time till occupant can safely awake: (note: If health is below 20% these times are inaccurate)") + to_chat(user, text("\t [] second\s (if around 1 or 2 the sleeper is keeping them asleep.)", src.occupant.paralysis / 5)) + else + to_chat(user, "There is no one inside!") + return + + +/obj/machinery/sleeper/verb/eject() + set name = "Eject Sleeper" + set category = "Object" + set src in oview(1) + if(usr.isUnconscious()) + return + src.go_out() + add_fingerprint(usr) + set_light(0) + return + + +/obj/machinery/sleeper/verb/move_inside() + set name = "Enter Sleeper" + set category = "Object" + set src in oview(1) + if(usr.isUnconscious() || !(ishuman(usr) || ismonkey(usr))) + return + + if(src.occupant) + to_chat(usr, "The sleeper is already occupied!") + return + if(usr.restrained() || usr.isUnconscious() || usr.weakened || usr.stunned || usr.paralysis || usr.resting) //are you cuffed, dying, lying, stunned or other + return + for(var/mob/living/carbon/slime/M in range(1,usr)) + if(M.Victim == usr) + to_chat(usr, "You're too busy getting your life sucked out of you.") + return + if(usr.locked_to) + return + visible_message("[usr] starts climbing into the sleeper.", 2) //spooky + if(do_after(usr, src, 20)) + if(src.occupant) + to_chat(usr, "The sleeper is already occupied!") + return + if(usr.locked_to) + return + usr.stop_pulling() + usr.loc = src + usr.reset_view() + src.occupant = usr + update_icon() + + for(var/obj/O in src) + qdel(O) + src.add_fingerprint(usr) + if(!(stat & (BROKEN|NOPOWER))) + set_light(light_range_on, light_power_on) + return + return + +#undef SLEEPER_SOPORIFIC_DELAY diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index 114900dfd2c..d89714a6bee 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -1,393 +1,393 @@ -#define AIRLOCK_CONTROL_RANGE 5 - -// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access) -obj/machinery/door/airlock - var/id_tag - var/frequency - var/shockedby = list() - var/datum/radio_frequency/radio_connection - explosion_resistance = 15 - - -obj/machinery/door/airlock/receive_signal(datum/signal/signal) - if(!signal || signal.encryption) return - - if(id_tag != signal.data["tag"] || !signal.data["command"]) return - - switch(signal.data["command"]) - if("open") - open(1) - - if("close") - close(1) - - if("unlock") - locked = 0 - update_icon() - - if("lock") - locked = 1 - update_icon() - - if("toggle_lock") - if(!density) - close(1) - sleep(2) - locked = !locked - update_icon() - - if("secure_open") - locked = 0 - update_icon() - - sleep(2) - open(1) - - locked = 1 - update_icon() - - if("secure_close") - locked = 0 - close(1) - - locked = 1 - sleep(2) - update_icon() - - send_status() - - -obj/machinery/door/airlock/proc/send_status() - if(radio_connection) - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.data["tag"] = id_tag - signal.data["timestamp"] = world.time - - signal.data["door_status"] = density?("closed"):("open") - signal.data["lock_status"] = locked?("locked"):("unlocked") - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - - -obj/machinery/door/airlock/open(surpress_send) - . = ..() - if(!surpress_send) send_status() - - -obj/machinery/door/airlock/close(surpress_send) - . = ..() - if(!surpress_send) send_status() - - -obj/machinery/door/airlock/Bumped(atom/AM) - ..(AM) - if(istype(AM, /obj/mecha)) - var/obj/mecha/mecha = AM - if(density && radio_connection && mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access))) - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.data["tag"] = id_tag - signal.data["timestamp"] = world.time - - signal.data["door_status"] = density?("closed"):("open") - signal.data["lock_status"] = locked?("locked"):("unlocked") - - signal.data["bumped_with_access"] = 1 - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - return - -obj/machinery/door/airlock/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - if(new_frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) - - -obj/machinery/door/airlock/initialize() - if(frequency) - set_frequency(frequency) - - update_icon() - - -obj/machinery/door/airlock/New() - ..() - - if(radio_controller) - set_frequency(frequency) - -obj/machinery/airlock_sensor - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_sensor_off" - name = "airlock sensor" - - anchored = 1 - power_channel = ENVIRON - - var/id_tag - var/master_tag - var/frequency = 1449 - var/command = "cycle" - - var/datum/radio_frequency/radio_connection - - var/on = 1 - var/alert = 0 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - - machine_flags = MULTITOOL_MENU - - -obj/machinery/airlock_sensor/update_icon() - if(on) - if(alert) - icon_state = "airlock_sensor_alert" - else - icon_state = "airlock_sensor_standby" - else - icon_state = "airlock_sensor_off" - -obj/machinery/airlock_sensor/attack_hand(mob/user) - if(..()) - return - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.data["tag"] = master_tag - signal.data["command"] = command - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - flick("airlock_sensor_cycle", src) - -obj/machinery/airlock_sensor/process() - if(on) - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.data["tag"] = id_tag - signal.data["timestamp"] = world.time - - var/datum/gas_mixture/air_sample = return_air() - - var/pressure = round(air_sample.return_pressure(),0.1) - alert = (pressure < ONE_ATMOSPHERE*0.8) - - signal.data["pressure"] = pressure - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - - update_icon() - -obj/machinery/airlock_sensor/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) - -obj/machinery/airlock_sensor/initialize() - set_frequency(frequency) - -obj/machinery/airlock_sensor/New() - ..() - - if(radio_controller) - set_frequency(frequency) - -obj/machinery/airlock_sensor/airlock_interior - command = "cycle_interior" - -obj/machinery/airlock_sensor/airlock_exterior - command = "cycle_exterior" - -/obj/machinery/airlock_sensor/New(turf/loc, var/ndir, var/building=0) - ..() - - // offset 24 pixels in direction of dir - // this allows the APC to be embedded in a wall, yet still inside an area - if (building) - dir = ndir - - //src.tdir = dir // to fix Vars bug - //dir = SOUTH - - pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) - pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 - - //build=0 - //stat |= MAINT - //src.update_icon() - -obj/machinery/airlock_sensor/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return {" - "} - -obj/machinery/airlock_sensor/Topic(href,href_list) - if(..()) - return 0 - - if(!issilicon(usr)) - if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) - testing("Not silicon, not using a multitool.") - return - if("set_freq" in href_list) - var/newfreq=frequency - if(href_list["set_freq"]!="-1") - newfreq=text2num(href_list["set_freq"]) - else - newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num - if(newfreq) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - frequency = newfreq - initialize() - update_multitool_menu(usr) - - -obj/machinery/airlock_sensor/attackby(var/obj/item/W, var/mob/user) - . = ..() - if(.) - return . - if(istype(W,/obj/item/weapon/screwdriver)) +#define AIRLOCK_CONTROL_RANGE 5 + +// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access) +obj/machinery/door/airlock + var/id_tag + var/frequency + var/shockedby = list() + var/datum/radio_frequency/radio_connection + explosion_resistance = 15 + + +obj/machinery/door/airlock/receive_signal(datum/signal/signal) + if(!signal || signal.encryption) return + + if(id_tag != signal.data["tag"] || !signal.data["command"]) return + + switch(signal.data["command"]) + if("open") + open(1) + + if("close") + close(1) + + if("unlock") + locked = 0 + update_icon() + + if("lock") + locked = 1 + update_icon() + + if("toggle_lock") + if(!density) + close(1) + sleep(2) + locked = !locked + update_icon() + + if("secure_open") + locked = 0 + update_icon() + + sleep(2) + open(1) + + locked = 1 + update_icon() + + if("secure_close") + locked = 0 + close(1) + + locked = 1 + sleep(2) + update_icon() + + send_status() + + +obj/machinery/door/airlock/proc/send_status() + if(radio_connection) + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + + signal.data["door_status"] = density?("closed"):("open") + signal.data["lock_status"] = locked?("locked"):("unlocked") + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + + +obj/machinery/door/airlock/open(surpress_send) + . = ..() + if(!surpress_send) send_status() + + +obj/machinery/door/airlock/close(surpress_send) + . = ..() + if(!surpress_send) send_status() + + +obj/machinery/door/airlock/Bumped(atom/AM) + ..(AM) + if(istype(AM, /obj/mecha)) + var/obj/mecha/mecha = AM + if(density && radio_connection && mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access))) + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + + signal.data["door_status"] = density?("closed"):("open") + signal.data["lock_status"] = locked?("locked"):("unlocked") + + signal.data["bumped_with_access"] = 1 + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + return + +obj/machinery/door/airlock/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + if(new_frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) + + +obj/machinery/door/airlock/initialize() + if(frequency) + set_frequency(frequency) + + update_icon() + + +obj/machinery/door/airlock/New() + ..() + + if(radio_controller) + set_frequency(frequency) + +obj/machinery/airlock_sensor + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_sensor_off" + name = "airlock sensor" + + anchored = 1 + power_channel = ENVIRON + + var/id_tag + var/master_tag + var/frequency = 1449 + var/command = "cycle" + + var/datum/radio_frequency/radio_connection + + var/on = 1 + var/alert = 0 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + + machine_flags = MULTITOOL_MENU + + +obj/machinery/airlock_sensor/update_icon() + if(on) + if(alert) + icon_state = "airlock_sensor_alert" + else + icon_state = "airlock_sensor_standby" + else + icon_state = "airlock_sensor_off" + +obj/machinery/airlock_sensor/attack_hand(mob/user) + if(..()) + return + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.data["tag"] = master_tag + signal.data["command"] = command + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + flick("airlock_sensor_cycle", src) + +obj/machinery/airlock_sensor/process() + if(on) + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + + var/datum/gas_mixture/air_sample = return_air() + + var/pressure = round(air_sample.return_pressure(),0.1) + alert = (pressure < ONE_ATMOSPHERE*0.8) + + signal.data["pressure"] = pressure + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + + update_icon() + +obj/machinery/airlock_sensor/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) + +obj/machinery/airlock_sensor/initialize() + set_frequency(frequency) + +obj/machinery/airlock_sensor/New() + ..() + + if(radio_controller) + set_frequency(frequency) + +obj/machinery/airlock_sensor/airlock_interior + command = "cycle_interior" + +obj/machinery/airlock_sensor/airlock_exterior + command = "cycle_exterior" + +/obj/machinery/airlock_sensor/New(turf/loc, var/ndir, var/building=0) + ..() + + // offset 24 pixels in direction of dir + // this allows the APC to be embedded in a wall, yet still inside an area + if (building) + dir = ndir + + //src.tdir = dir // to fix Vars bug + //dir = SOUTH + + pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) + pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 + + //build=0 + //stat |= MAINT + //src.update_icon() + +obj/machinery/airlock_sensor/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return {" + "} + +obj/machinery/airlock_sensor/Topic(href,href_list) + if(..()) + return 0 + + if(!issilicon(usr)) + if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) + testing("Not silicon, not using a multitool.") + return + if("set_freq" in href_list) + var/newfreq=frequency + if(href_list["set_freq"]!="-1") + newfreq=text2num(href_list["set_freq"]) + else + newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num + if(newfreq) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(newfreq < 10000) + frequency = newfreq + initialize() + update_multitool_menu(usr) + + +obj/machinery/airlock_sensor/attackby(var/obj/item/W, var/mob/user) + . = ..() + if(.) + return . + if(istype(W,/obj/item/weapon/screwdriver)) to_chat(user, "You begin to pry \the [src] off the wall...") - if(do_after(user, src, 50)) + if(do_after(user, src, 50)) to_chat(user, "You successfully pry \the [src] off the wall.") - new /obj/item/mounted/frame/airlock_sensor(get_turf(src)) - qdel(src) - -obj/machinery/access_button - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "access_button_standby" - name = "access button" - - anchored = 1 - power_channel = ENVIRON - - var/master_tag - var/frequency = 1449 - var/command = "cycle" - - var/datum/radio_frequency/radio_connection - - var/on = 1 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - machine_flags = MULTITOOL_MENU - -/obj/machinery/access_button/New(turf/loc, var/ndir, var/building=0) - ..() - - // offset 24 pixels in direction of dir - // this allows the APC to be embedded in a wall, yet still inside an area - if (building) - dir = ndir - - //src.tdir = dir // to fix Vars bug - //dir = SOUTH - - pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) - pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 - - //build=0 - //stat |= MAINT - //src.update_icon() - - -obj/machinery/access_button/update_icon() - if(on) - icon_state = "access_button_standby" - else - icon_state = "access_button_off" - - -obj/machinery/access_button/attack_hand(mob/user) - add_fingerprint(usr) - if(!allowed(user)) + new /obj/item/mounted/frame/airlock_sensor(get_turf(src)) + qdel(src) + +obj/machinery/access_button + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "access_button_standby" + name = "access button" + + anchored = 1 + power_channel = ENVIRON + + var/master_tag + var/frequency = 1449 + var/command = "cycle" + + var/datum/radio_frequency/radio_connection + + var/on = 1 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + machine_flags = MULTITOOL_MENU + +/obj/machinery/access_button/New(turf/loc, var/ndir, var/building=0) + ..() + + // offset 24 pixels in direction of dir + // this allows the APC to be embedded in a wall, yet still inside an area + if (building) + dir = ndir + + //src.tdir = dir // to fix Vars bug + //dir = SOUTH + + pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) + pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 + + //build=0 + //stat |= MAINT + //src.update_icon() + + +obj/machinery/access_button/update_icon() + if(on) + icon_state = "access_button_standby" + else + icon_state = "access_button_off" + + +obj/machinery/access_button/attack_hand(mob/user) + add_fingerprint(usr) + if(!allowed(user)) to_chat(user, "Access Denied.") - - else if(radio_connection) - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.data["tag"] = master_tag - signal.data["command"] = command - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - flick("access_button_cycle", src) - - -obj/machinery/access_button/attackby(var/obj/item/W, var/mob/user) - . = ..() - if(.) - return . - if(istype(W,/obj/item/weapon/screwdriver)) + + else if(radio_connection) + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.data["tag"] = master_tag + signal.data["command"] = command + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + flick("access_button_cycle", src) + + +obj/machinery/access_button/attackby(var/obj/item/W, var/mob/user) + . = ..() + if(.) + return . + if(istype(W,/obj/item/weapon/screwdriver)) to_chat(user, "You begin to pry \the [src] off the wall...") - if(do_after(user, src, 50)) + if(do_after(user, src, 50)) to_chat(user, "You successfully pry \the [src] off the wall.") - new /obj/item/mounted/frame/access_button(get_turf(src)) - qdel(src) - -obj/machinery/access_button/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) - - -obj/machinery/access_button/initialize() - set_frequency(frequency) - - -obj/machinery/access_button/New() - ..() - - if(radio_controller) - set_frequency(frequency) - -obj/machinery/access_button/airlock_interior - frequency = 1449 - command = "cycle_interior" - -obj/machinery/access_button/airlock_exterior - frequency = 1449 - command = "cycle_exterior" - - - -obj/machinery/access_button/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return {" - "} - -obj/machinery/access_button/Topic(href,href_list) - if(..()) - return 1 - - if(!issilicon(usr)) - if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) - testing("Not silicon, not using a multitool.") - return - - var/obj/item/device/multitool/P = get_multitool(usr) - if(P) - if("set_freq" in href_list) - var/newfreq=frequency - if(href_list["set_freq"]!="-1") - newfreq=text2num(href_list["set_freq"]) - else - newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num - if(newfreq) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - frequency = newfreq - initialize() - + new /obj/item/mounted/frame/access_button(get_turf(src)) + qdel(src) + +obj/machinery/access_button/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) + + +obj/machinery/access_button/initialize() + set_frequency(frequency) + + +obj/machinery/access_button/New() + ..() + + if(radio_controller) + set_frequency(frequency) + +obj/machinery/access_button/airlock_interior + frequency = 1449 + command = "cycle_interior" + +obj/machinery/access_button/airlock_exterior + frequency = 1449 + command = "cycle_exterior" + + + +obj/machinery/access_button/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return {" + "} + +obj/machinery/access_button/Topic(href,href_list) + if(..()) + return 1 + + if(!issilicon(usr)) + if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) + testing("Not silicon, not using a multitool.") + return + + var/obj/item/device/multitool/P = get_multitool(usr) + if(P) + if("set_freq" in href_list) + var/newfreq=frequency + if(href_list["set_freq"]!="-1") + newfreq=text2num(href_list["set_freq"]) + else + newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num + if(newfreq) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(newfreq < 10000) + frequency = newfreq + initialize() + update_multitool_menu(usr) \ No newline at end of file diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index be0e0989c29..a52d3d31599 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -1,1245 +1,1245 @@ -//////////////////////////////////////// -//CONTAINS: Air Alarms and Fire Alarms// -//////////////////////////////////////// - -#define AALARM_MODE_SCRUBBING 1 -#define AALARM_MODE_REPLACEMENT 2 //like scrubbing, but faster. -#define AALARM_MODE_PANIC 3 //constantly sucks all air -#define AALARM_MODE_CYCLE 4 //sucks off all air, then refill and switches to scrubbing -#define AALARM_MODE_FILL 5 //emergency fill -#define AALARM_MODE_OFF 6 //Shuts it all down. - -#define AALARM_PRESET_HUMAN 1 // Default -#define AALARM_PRESET_VOX 2 // Support Vox -#define AALARM_PRESET_SERVER 3 // Server Coldroom - -#define AALARM_SCREEN_MAIN 1 -#define AALARM_SCREEN_VENT 2 -#define AALARM_SCREEN_SCRUB 3 -#define AALARM_SCREEN_MODE 4 -#define AALARM_SCREEN_SENSORS 5 - -#define AALARM_REPORT_TIMEOUT 100 - -#define RCON_NO 1 -#define RCON_AUTO 2 -#define RCON_YES 3 - -//1000 joules equates to about 1 degree every 2 seconds for a single tile of air. -#define MAX_ENERGY_CHANGE 1000 - -#define MAX_TEMPERATURE 90 -#define MIN_TEMPERATURE -40 - -//all air alarms in area are connected via magic -/area - var/obj/machinery/alarm/master_air_alarm - var/list/air_vent_names = list() - var/list/air_scrub_names = list() - var/list/air_vent_info = list() - var/list/air_scrub_info = list() - -/obj/machinery/alarm - icon = 'icons/obj/monitors.dmi' - icon_state = "alarm0" - anchored = 1 - use_power = 1 - idle_power_usage = 100 - active_power_usage = 200 - power_channel = ENVIRON - req_one_access = list(access_atmospherics, access_engine_equip) - var/frequency = 1439 - //var/skipprocess = 0 //Experimenting - var/alarm_frequency = 1437 - var/remote_control = 0 - var/rcon_setting = 2 - var/rcon_time = 0 - var/locked = 1 - var/datum/wires/alarm/wires = null - var/wiresexposed = 0 // If it's been screwdrivered open. - var/aidisabled = 0 - var/AAlarmwires = 31 - var/shorted = 0 - - var/mode = AALARM_MODE_SCRUBBING - var/preset = AALARM_PRESET_HUMAN - var/screen = AALARM_SCREEN_MAIN - var/area_uid - var/local_danger_level = 0 - var/alarmActivated = 0 // Manually activated (independent from danger level) - var/danger_averted_confidence=0 - var/buildstage = 2 //2 is built, 1 is building, 0 is frame. - - var/target_temperature = T0C+20 - var/regulating_temperature = 0 - - var/datum/radio_frequency/radio_connection - - var/list/TLV = list() - - machine_flags = WIREJACK - -/obj/machinery/alarm/xenobio - preset = AALARM_PRESET_HUMAN - req_one_access = list(access_rd, access_atmospherics, access_engine_equip, access_xenobiology) - req_access = list() - -/obj/machinery/alarm/server - preset = AALARM_PRESET_SERVER - req_one_access = list(access_rd, access_atmospherics, access_engine_equip) - req_access = list() - -/obj/machinery/alarm/vox - preset = AALARM_PRESET_VOX - req_access = list() - -/obj/machinery/alarm/proc/apply_preset(var/no_cycle_after=0) - // Propogate settings. - for (var/obj/machinery/alarm/AA in areaMaster) - if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.preset != src.preset) - AA.preset=preset - apply_preset(1) // Only this air alarm should send a cycle. - - TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa - TLV["nitrogen"] = list(-1, -1, -1, -1) // Partial pressure, kpa - TLV["carbon_dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa - TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa - TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa - TLV["pressure"] = list(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20) /* kpa */ - TLV["temperature"] = list(T0C-30, T0C, T0C+40, T0C+70) // K - target_temperature = T0C+20 - switch(preset) - if(AALARM_PRESET_VOX) // Same as usual, s/nitrogen/oxygen - TLV["nitrogen"] = list(16, 19, 135, 140) // Vox use same partial pressure values for N2 as humans do for O2. - TLV["oxygen"] = list(-1.0, -1.0, 0.5, 1.0) // Under 1 kPa (PP), vox don't notice squat (vox_oxygen_max) - if(AALARM_PRESET_SERVER) // Cold as fuck. - TLV["oxygen"] = list(-1.0, -1.0,-1.0,-1.0) - TLV["carbon_dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa - TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa - TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa - TLV["pressure"] = list(0,ONE_ATMOSPHERE*0.10,ONE_ATMOSPHERE*1.40,ONE_ATMOSPHERE*1.60) /* kpa */ - TLV["temperature"] = list(20, 40, 140, 160) // K - target_temperature = 90 - if(!no_cycle_after) - mode = AALARM_MODE_CYCLE - apply_mode() - - -/obj/machinery/alarm/New(var/loc, var/dir, var/building = 0) - ..() - wires = new(src) - - if(building) - if(loc) - src.loc = loc - - if(dir) - src.dir = dir - - buildstage = 0 - wiresexposed = 1 - pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) - pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 - update_icon() - if(ticker && ticker.current_state == 3)//if the game is running - src.initialize() - return - - first_run() - -/obj/machinery/alarm/Destroy() - if(wires) - qdel(wires) - wires = null - for(var/obj/machinery/computer/atmoscontrol/AC in atmos_controllers) - if(AC.current == src) - AC.current = null - nanomanager.update_uis(src) - - ..() - -/obj/machinery/alarm/proc/first_run() - area_uid = areaMaster.uid - name = "[areaMaster.name] Air Alarm" - - // breathable air according to human/Life() - /* - TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa - TLV["nitrogen"] = list(-1, -1, -1, -1) // Partial pressure, kpa - TLV["carbon_dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa - TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa - TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa - TLV["pressure"] = list(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20) /* kpa */ - TLV["temperature"] = list(T0C-26, T0C, T0C+40, T0C+66) // K - */ - apply_preset(1) // Don't cycle. - - -/obj/machinery/alarm/initialize() - set_frequency(frequency) - if (!master_is_operating()) - elect_master() - - -/obj/machinery/alarm/process() - if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2) - use_power = 0 - return - - var/turf/simulated/location = loc - if(!istype(location)) return//returns if loc is not simulated - - var/datum/gas_mixture/environment = location.return_air() - - // Handle temperature adjustment here. - if(environment.temperature < target_temperature - 2 || environment.temperature > target_temperature + 2 || regulating_temperature) - //If it goes too far, we should adjust ourselves back before stopping. - if(get_danger_level(target_temperature, TLV["temperature"])) - return - - if(!regulating_temperature) - regulating_temperature = 1 - visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\ - "You hear a click and a faint electronic hum.") - - if(target_temperature > T0C + MAX_TEMPERATURE) - target_temperature = T0C + MAX_TEMPERATURE - - if(target_temperature < T0C + MIN_TEMPERATURE) - target_temperature = T0C + MIN_TEMPERATURE - - var/datum/gas_mixture/gas = location.remove_air(0.25 * environment.total_moles) - if(gas) - var/heat_capacity = gas.heat_capacity() - var/energy_used = min(abs(heat_capacity * (gas.temperature - target_temperature)), MAX_ENERGY_CHANGE) - - // We need to cool ourselves. - if (environment.temperature > target_temperature) - gas.temperature -= energy_used / heat_capacity - else - gas.temperature += energy_used / heat_capacity - - environment.merge(gas) - - if (abs(environment.temperature - target_temperature) <= 0.5) - regulating_temperature = 0 - visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\ - "You hear a click as a faint electronic humming stops.") - - var/old_level = local_danger_level - var/new_danger = calculate_local_danger_level(environment) - - if (new_danger < old_level) - danger_averted_confidence++ - use_power = 1 - - // Only change danger level if: - // we're going up a level - // OR if we're going down a level and have sufficient confidence (prevents spamming update_icon). - if (old_level < new_danger || (danger_averted_confidence >= 5 && new_danger < old_level)) - setDangerLevel(new_danger) - update_icon() - danger_averted_confidence = 0 // Reset counter. - use_power = 2 - - if (mode==AALARM_MODE_CYCLE && environment.return_pressure()= danger_levels[4] && danger_levels[4] > 0) || current_value <= danger_levels[1]) - return 2 - if ((current_value >= danger_levels[3] && danger_levels[3] > 0) || current_value <= danger_levels[2]) - return 1 - - return 0 - -/obj/machinery/alarm/update_icon() - if(wiresexposed) - icon_state = "alarmx" - return - if((stat & (NOPOWER|BROKEN)) || shorted) - icon_state = "alarmp" - return - - switch(max(local_danger_level, areaMaster.atmosalm-1)) - if (0) - icon_state = "alarm0" - if (1) - icon_state = "alarm2" //yes, alarm2 is yellow alarm - if (2) - icon_state = "alarm1" - -/obj/machinery/alarm/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN) || !areaMaster) - return - if (areaMaster.master_air_alarm != src) - if (master_is_operating()) - return - elect_master() - if (areaMaster.master_air_alarm != src) - return - if(!signal || signal.encryption) - return - var/id_tag = signal.data["tag"] - if (!id_tag) - return - if (signal.data["area"] != area_uid) - return - if (signal.data["sigtype"] != "status") - return - - var/dev_type = signal.data["device"] - if(!(id_tag in areaMaster.air_scrub_names) && !(id_tag in areaMaster.air_vent_names)) - register_env_machine(id_tag, dev_type) - - if(dev_type == "AScr") - areaMaster.air_scrub_info[id_tag] = signal.data - else if(dev_type == "AVP") - areaMaster.air_vent_info[id_tag] = signal.data - -/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type) - var/new_name - if (device_type=="AVP") - new_name = "[areaMaster.name] Vent Pump #[areaMaster.air_vent_names.len+1]" - areaMaster.air_vent_names[m_id] = new_name - else if (device_type=="AScr") - new_name = "[areaMaster.name] Air Scrubber #[areaMaster.air_scrub_names.len+1]" - areaMaster.air_scrub_names[m_id] = new_name - else - return - spawn (10) - send_signal(m_id, list("init" = new_name) ) - -/obj/machinery/alarm/proc/refresh_all() - for(var/id_tag in areaMaster.air_vent_names) - var/list/I = areaMaster.air_vent_info[id_tag] - if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) - continue - send_signal(id_tag, list("status") ) - for(var/id_tag in areaMaster.air_scrub_names) - var/list/I = areaMaster.air_scrub_info[id_tag] - if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) - continue - send_signal(id_tag, list("status") ) - -/obj/machinery/alarm/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM) - -/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise - if(!radio_connection) - return 0 - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 //radio signal - signal.source = src - - signal.data = command - signal.data["tag"] = target - signal.data["sigtype"] = "command" - - radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) +//////////////////////////////////////// +//CONTAINS: Air Alarms and Fire Alarms// +//////////////////////////////////////// + +#define AALARM_MODE_SCRUBBING 1 +#define AALARM_MODE_REPLACEMENT 2 //like scrubbing, but faster. +#define AALARM_MODE_PANIC 3 //constantly sucks all air +#define AALARM_MODE_CYCLE 4 //sucks off all air, then refill and switches to scrubbing +#define AALARM_MODE_FILL 5 //emergency fill +#define AALARM_MODE_OFF 6 //Shuts it all down. + +#define AALARM_PRESET_HUMAN 1 // Default +#define AALARM_PRESET_VOX 2 // Support Vox +#define AALARM_PRESET_SERVER 3 // Server Coldroom + +#define AALARM_SCREEN_MAIN 1 +#define AALARM_SCREEN_VENT 2 +#define AALARM_SCREEN_SCRUB 3 +#define AALARM_SCREEN_MODE 4 +#define AALARM_SCREEN_SENSORS 5 + +#define AALARM_REPORT_TIMEOUT 100 + +#define RCON_NO 1 +#define RCON_AUTO 2 +#define RCON_YES 3 + +//1000 joules equates to about 1 degree every 2 seconds for a single tile of air. +#define MAX_ENERGY_CHANGE 1000 + +#define MAX_TEMPERATURE 90 +#define MIN_TEMPERATURE -40 + +//all air alarms in area are connected via magic +/area + var/obj/machinery/alarm/master_air_alarm + var/list/air_vent_names = list() + var/list/air_scrub_names = list() + var/list/air_vent_info = list() + var/list/air_scrub_info = list() + +/obj/machinery/alarm + icon = 'icons/obj/monitors.dmi' + icon_state = "alarm0" + anchored = 1 + use_power = 1 + idle_power_usage = 100 + active_power_usage = 200 + power_channel = ENVIRON + req_one_access = list(access_atmospherics, access_engine_equip) + var/frequency = 1439 + //var/skipprocess = 0 //Experimenting + var/alarm_frequency = 1437 + var/remote_control = 0 + var/rcon_setting = 2 + var/rcon_time = 0 + var/locked = 1 + var/datum/wires/alarm/wires = null + var/wiresexposed = 0 // If it's been screwdrivered open. + var/aidisabled = 0 + var/AAlarmwires = 31 + var/shorted = 0 + + var/mode = AALARM_MODE_SCRUBBING + var/preset = AALARM_PRESET_HUMAN + var/screen = AALARM_SCREEN_MAIN + var/area_uid + var/local_danger_level = 0 + var/alarmActivated = 0 // Manually activated (independent from danger level) + var/danger_averted_confidence=0 + var/buildstage = 2 //2 is built, 1 is building, 0 is frame. + + var/target_temperature = T0C+20 + var/regulating_temperature = 0 + + var/datum/radio_frequency/radio_connection + + var/list/TLV = list() + + machine_flags = WIREJACK + +/obj/machinery/alarm/xenobio + preset = AALARM_PRESET_HUMAN + req_one_access = list(access_rd, access_atmospherics, access_engine_equip, access_xenobiology) + req_access = list() + +/obj/machinery/alarm/server + preset = AALARM_PRESET_SERVER + req_one_access = list(access_rd, access_atmospherics, access_engine_equip) + req_access = list() + +/obj/machinery/alarm/vox + preset = AALARM_PRESET_VOX + req_access = list() + +/obj/machinery/alarm/proc/apply_preset(var/no_cycle_after=0) + // Propogate settings. + for (var/obj/machinery/alarm/AA in areaMaster) + if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.preset != src.preset) + AA.preset=preset + apply_preset(1) // Only this air alarm should send a cycle. + + TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa + TLV["nitrogen"] = list(-1, -1, -1, -1) // Partial pressure, kpa + TLV["carbon_dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa + TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa + TLV["pressure"] = list(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20) /* kpa */ + TLV["temperature"] = list(T0C-30, T0C, T0C+40, T0C+70) // K + target_temperature = T0C+20 + switch(preset) + if(AALARM_PRESET_VOX) // Same as usual, s/nitrogen/oxygen + TLV["nitrogen"] = list(16, 19, 135, 140) // Vox use same partial pressure values for N2 as humans do for O2. + TLV["oxygen"] = list(-1.0, -1.0, 0.5, 1.0) // Under 1 kPa (PP), vox don't notice squat (vox_oxygen_max) + if(AALARM_PRESET_SERVER) // Cold as fuck. + TLV["oxygen"] = list(-1.0, -1.0,-1.0,-1.0) + TLV["carbon_dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa + TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa + TLV["pressure"] = list(0,ONE_ATMOSPHERE*0.10,ONE_ATMOSPHERE*1.40,ONE_ATMOSPHERE*1.60) /* kpa */ + TLV["temperature"] = list(20, 40, 140, 160) // K + target_temperature = 90 + if(!no_cycle_after) + mode = AALARM_MODE_CYCLE + apply_mode() + + +/obj/machinery/alarm/New(var/loc, var/dir, var/building = 0) + ..() + wires = new(src) + + if(building) + if(loc) + src.loc = loc + + if(dir) + src.dir = dir + + buildstage = 0 + wiresexposed = 1 + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + update_icon() + if(ticker && ticker.current_state == 3)//if the game is running + src.initialize() + return + + first_run() + +/obj/machinery/alarm/Destroy() + if(wires) + qdel(wires) + wires = null + for(var/obj/machinery/computer/atmoscontrol/AC in atmos_controllers) + if(AC.current == src) + AC.current = null + nanomanager.update_uis(src) + + ..() + +/obj/machinery/alarm/proc/first_run() + area_uid = areaMaster.uid + name = "[areaMaster.name] Air Alarm" + + // breathable air according to human/Life() + /* + TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa + TLV["nitrogen"] = list(-1, -1, -1, -1) // Partial pressure, kpa + TLV["carbon_dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["plasma"] = list(-1.0, -1.0, 0.2, 0.5) // Partial pressure, kpa + TLV["other"] = list(-1.0, -1.0, 0.5, 1.0) // Partial pressure, kpa + TLV["pressure"] = list(ONE_ATMOSPHERE*0.80,ONE_ATMOSPHERE*0.90,ONE_ATMOSPHERE*1.10,ONE_ATMOSPHERE*1.20) /* kpa */ + TLV["temperature"] = list(T0C-26, T0C, T0C+40, T0C+66) // K + */ + apply_preset(1) // Don't cycle. + + +/obj/machinery/alarm/initialize() + set_frequency(frequency) + if (!master_is_operating()) + elect_master() + + +/obj/machinery/alarm/process() + if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2) + use_power = 0 + return + + var/turf/simulated/location = loc + if(!istype(location)) return//returns if loc is not simulated + + var/datum/gas_mixture/environment = location.return_air() + + // Handle temperature adjustment here. + if(environment.temperature < target_temperature - 2 || environment.temperature > target_temperature + 2 || regulating_temperature) + //If it goes too far, we should adjust ourselves back before stopping. + if(get_danger_level(target_temperature, TLV["temperature"])) + return + + if(!regulating_temperature) + regulating_temperature = 1 + visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\ + "You hear a click and a faint electronic hum.") + + if(target_temperature > T0C + MAX_TEMPERATURE) + target_temperature = T0C + MAX_TEMPERATURE + + if(target_temperature < T0C + MIN_TEMPERATURE) + target_temperature = T0C + MIN_TEMPERATURE + + var/datum/gas_mixture/gas = location.remove_air(0.25 * environment.total_moles) + if(gas) + var/heat_capacity = gas.heat_capacity() + var/energy_used = min(abs(heat_capacity * (gas.temperature - target_temperature)), MAX_ENERGY_CHANGE) + + // We need to cool ourselves. + if (environment.temperature > target_temperature) + gas.temperature -= energy_used / heat_capacity + else + gas.temperature += energy_used / heat_capacity + + environment.merge(gas) + + if (abs(environment.temperature - target_temperature) <= 0.5) + regulating_temperature = 0 + visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\ + "You hear a click as a faint electronic humming stops.") + + var/old_level = local_danger_level + var/new_danger = calculate_local_danger_level(environment) + + if (new_danger < old_level) + danger_averted_confidence++ + use_power = 1 + + // Only change danger level if: + // we're going up a level + // OR if we're going down a level and have sufficient confidence (prevents spamming update_icon). + if (old_level < new_danger || (danger_averted_confidence >= 5 && new_danger < old_level)) + setDangerLevel(new_danger) + update_icon() + danger_averted_confidence = 0 // Reset counter. + use_power = 2 + + if (mode==AALARM_MODE_CYCLE && environment.return_pressure()= danger_levels[4] && danger_levels[4] > 0) || current_value <= danger_levels[1]) + return 2 + if ((current_value >= danger_levels[3] && danger_levels[3] > 0) || current_value <= danger_levels[2]) + return 1 + + return 0 + +/obj/machinery/alarm/update_icon() + if(wiresexposed) + icon_state = "alarmx" + return + if((stat & (NOPOWER|BROKEN)) || shorted) + icon_state = "alarmp" + return + + switch(max(local_danger_level, areaMaster.atmosalm-1)) + if (0) + icon_state = "alarm0" + if (1) + icon_state = "alarm2" //yes, alarm2 is yellow alarm + if (2) + icon_state = "alarm1" + +/obj/machinery/alarm/receive_signal(datum/signal/signal) + if(stat & (NOPOWER|BROKEN) || !areaMaster) + return + if (areaMaster.master_air_alarm != src) + if (master_is_operating()) + return + elect_master() + if (areaMaster.master_air_alarm != src) + return + if(!signal || signal.encryption) + return + var/id_tag = signal.data["tag"] + if (!id_tag) + return + if (signal.data["area"] != area_uid) + return + if (signal.data["sigtype"] != "status") + return + + var/dev_type = signal.data["device"] + if(!(id_tag in areaMaster.air_scrub_names) && !(id_tag in areaMaster.air_vent_names)) + register_env_machine(id_tag, dev_type) + + if(dev_type == "AScr") + areaMaster.air_scrub_info[id_tag] = signal.data + else if(dev_type == "AVP") + areaMaster.air_vent_info[id_tag] = signal.data + +/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type) + var/new_name + if (device_type=="AVP") + new_name = "[areaMaster.name] Vent Pump #[areaMaster.air_vent_names.len+1]" + areaMaster.air_vent_names[m_id] = new_name + else if (device_type=="AScr") + new_name = "[areaMaster.name] Air Scrubber #[areaMaster.air_scrub_names.len+1]" + areaMaster.air_scrub_names[m_id] = new_name + else + return + spawn (10) + send_signal(m_id, list("init" = new_name) ) + +/obj/machinery/alarm/proc/refresh_all() + for(var/id_tag in areaMaster.air_vent_names) + var/list/I = areaMaster.air_vent_info[id_tag] + if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) + continue + send_signal(id_tag, list("status") ) + for(var/id_tag in areaMaster.air_scrub_names) + var/list/I = areaMaster.air_scrub_info[id_tag] + if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) + continue + send_signal(id_tag, list("status") ) + +/obj/machinery/alarm/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM) + +/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise + if(!radio_connection) + return 0 + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 //radio signal + signal.source = src + + signal.data = command + signal.data["tag"] = target + signal.data["sigtype"] = "command" + + radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) // to_chat(world, text("Signal [] Broadcasted to []", command, target)) - - return 1 - -/obj/machinery/alarm/proc/apply_mode() - var/list/current_pressures = TLV["pressure"] - var/target_pressure = (current_pressures[2] + current_pressures[3])/2 - switch(mode) - if(AALARM_MODE_SCRUBBING) - for(var/device_id in areaMaster.air_scrub_names) - send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "o2_scrub"=(preset==AALARM_PRESET_VOX), "n2_scrub"=0, "scrubbing"= 1, "panic_siphon"= 0) ) - for(var/device_id in areaMaster.air_vent_names) - send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) - - if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE) - for(var/device_id in areaMaster.air_scrub_names) - send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) - for(var/device_id in areaMaster.air_vent_names) - send_signal(device_id, list("power"= 0) ) - - if(AALARM_MODE_REPLACEMENT) - for(var/device_id in areaMaster.air_scrub_names) - send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) - for(var/device_id in areaMaster.air_vent_names) - send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) - - if(AALARM_MODE_FILL) - for(var/device_id in areaMaster.air_scrub_names) - send_signal(device_id, list("power"= 0) ) - for(var/device_id in areaMaster.air_vent_names) - send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) - - if(AALARM_MODE_OFF) - for(var/device_id in areaMaster.air_scrub_names) - send_signal(device_id, list("power"= 0) ) - for(var/device_id in areaMaster.air_vent_names) - send_signal(device_id, list("power"= 0) ) - -// This sets our danger level, and, if it's changed, forces a new election of danger levels. -/obj/machinery/alarm/proc/setDangerLevel(var/new_danger_level) - if(local_danger_level==new_danger_level) - return - local_danger_level=new_danger_level - if(areaMaster.updateDangerLevel()) - post_alert(new_danger_level) - -/obj/machinery/alarm/proc/post_alert(alert_level) - var/datum/radio_frequency/frequency = radio_controller.return_frequency(alarm_frequency) - if(!frequency) - return - - var/datum/signal/alert_signal = getFromPool(/datum/signal) - alert_signal.source = src - alert_signal.transmission_method = 1 - alert_signal.data["zone"] = areaMaster.name - alert_signal.data["type"] = "Atmospheric" - - if(alert_level==2) - alert_signal.data["alert"] = "severe" - else if (alert_level==1) - alert_signal.data["alert"] = "minor" - else if (alert_level==0) - alert_signal.data["alert"] = "clear" - - frequency.post_signal(src, alert_signal) - -/obj/machinery/alarm/proc/air_doors_close(manual) - areaMaster.CloseFirelocks() - -/obj/machinery/alarm/proc/air_doors_open(manual) - areaMaster.OpenFirelocks() - -/////////////// -//END HACKING// -/////////////// - -/obj/machinery/alarm/attack_hand(mob/user) - . = ..() - - if (.) - return - - interact(user) - -/obj/machinery/alarm/proc/ui_air_status() - var/turf/location = get_turf(src) - - if (isnull(location)) - return null - - var/datum/gas_mixture/environment = location.return_air() - var/total = environment.oxygen + environment.carbon_dioxide + environment.toxins + environment.nitrogen - if(total==0) - return null - - var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - - var/list/current_settings = TLV["pressure"] - var/environment_pressure = environment.return_pressure() - var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings) - - current_settings = TLV["oxygen"] - var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, current_settings) - var/oxygen_percent = round(environment.oxygen / total * 100, 2) - - current_settings = TLV["nitrogen"] - var/nitrogen_dangerlevel = get_danger_level(environment.nitrogen*partial_pressure, current_settings) - var/nitrogen_percent = round(environment.nitrogen / total * 100, 2) - - current_settings = TLV["carbon_dioxide"] - var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, current_settings) - var/co2_percent = round(environment.carbon_dioxide / total * 100, 2) - - current_settings = TLV["plasma"] - var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, current_settings) - var/plasma_percent = round(environment.toxins / total * 100, 2) - - current_settings = TLV["other"] - var/other_moles = 0.0 - for(var/datum/gas/G in environment.trace_gases) - other_moles+=G.moles - var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings) - - current_settings = TLV["temperature"] - var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings) - - - var/data[0] - data["pressure"]=environment_pressure - data["temperature"]=environment.temperature - data["temperature_c"]=round(environment.temperature - T0C, 0.1) - - var/percentages[0] - percentages["oxygen"]=oxygen_percent - percentages["nitrogen"]=nitrogen_percent - percentages["co2"]=co2_percent - percentages["plasma"]=plasma_percent - percentages["other"]=other_moles - data["contents"]=percentages - - var/danger[0] - danger["pressure"]=pressure_dangerlevel - danger["temperature"]=temperature_dangerlevel - danger["oxygen"]=oxygen_dangerlevel - danger["nitrogen"]=nitrogen_dangerlevel - danger["co2"]=co2_dangerlevel - danger["plasma"]=plasma_dangerlevel - danger["other"]=other_dangerlevel - danger["overall"]=max(pressure_dangerlevel,oxygen_dangerlevel,nitrogen_dangerlevel,co2_dangerlevel,plasma_dangerlevel,other_dangerlevel,temperature_dangerlevel) - data["danger"]=danger - return data - -/obj/machinery/alarm/proc/get_nano_data(mob/user, fromAtmosConsole=0) - - - var/data[0] - data["air"]=ui_air_status() - data["alarmActivated"]=alarmActivated //|| local_danger_level==2 - data["sensors"]=TLV - - // Locked when: - // Not sent from atmos console AND - // Not silicon AND locked AND - // NOT adminghost. - data["locked"]=!fromAtmosConsole && (!(istype(user, /mob/living/silicon)) && locked) && !isAdminGhost(user) - - data["rcon"]=rcon_setting - data["target_temp"] = target_temperature - T0C - data["atmos_alarm"] = areaMaster.atmosalm - data["modes"] = list( - AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\ - AALARM_MODE_REPLACEMENT = list("name"="Replace Air", "desc"="Siphons out air while replacing"),\ - AALARM_MODE_PANIC = list("name"="Panic", "desc"="Siphons air out of the room"),\ - AALARM_MODE_CYCLE = list("name"="Cycle", "desc"="Siphons air before replacing"),\ - AALARM_MODE_FILL = list("name"="Fill", "desc"="Shuts off scrubbers and opens vents"),\ - AALARM_MODE_OFF = list("name"="Off", "desc"="Shuts off vents and scrubbers")) - data["mode"]=mode - data["presets"]=list( - AALARM_PRESET_HUMAN = list("name"="Human", "desc"="Checks for Oxygen and Nitrogen"),\ - AALARM_PRESET_VOX = list("name"="Vox", "desc"="Checks for Nitrogen only"),\ - AALARM_PRESET_SERVER = list("name"="Coldroom", "desc"="For server rooms and freezers")) - data["preset"]=preset - data["screen"]=screen - - var/list/vents=list() - if(areaMaster.air_vent_names.len) - for(var/id_tag in areaMaster.air_vent_names) - var/vent_info[0] - var/long_name = areaMaster.air_vent_names[id_tag] - var/list/vent_data = areaMaster.air_vent_info[id_tag] - if(!vent_data) - continue - vent_info["id_tag"]=id_tag - vent_info["name"]=long_name - vent_info += vent_data - vents+=list(vent_info) - data["vents"]=vents - - var/list/scrubbers=list() - if(areaMaster.air_scrub_names.len) - for(var/id_tag in areaMaster.air_scrub_names) - var/long_name = areaMaster.air_scrub_names[id_tag] - var/list/scrubber_data = areaMaster.air_scrub_info[id_tag] - if(!scrubber_data) - continue - scrubber_data["id_tag"]=id_tag - scrubber_data["name"]=long_name - scrubbers+=list(scrubber_data) - data["scrubbers"]=scrubbers - return data - - -/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/list/data=src.get_nano_data(user,FALSE) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - // The ui does not exist, so we'll create a new one. - ui = new(user, src, ui_key, "air_alarm.tmpl", name, 550, 410) - // When the UI is first opened this is the data it will use. - ui.set_initial_data(data) - // Open the new ui window. - ui.open() - // Auto update every Master Controller tick. - ui.set_auto_update(1) - -/obj/machinery/alarm/interact(mob/user) - if(buildstage!=2) - return - - if ( (get_dist(src, user) > 1 )) - if (!istype(user, /mob/living/silicon)) - user << browse(null, "window=AAlarmwires") - return - - - else if (istype(user, /mob/living/silicon) && aidisabled) + + return 1 + +/obj/machinery/alarm/proc/apply_mode() + var/list/current_pressures = TLV["pressure"] + var/target_pressure = (current_pressures[2] + current_pressures[3])/2 + switch(mode) + if(AALARM_MODE_SCRUBBING) + for(var/device_id in areaMaster.air_scrub_names) + send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "o2_scrub"=(preset==AALARM_PRESET_VOX), "n2_scrub"=0, "scrubbing"= 1, "panic_siphon"= 0) ) + for(var/device_id in areaMaster.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) + + if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE) + for(var/device_id in areaMaster.air_scrub_names) + send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) + for(var/device_id in areaMaster.air_vent_names) + send_signal(device_id, list("power"= 0) ) + + if(AALARM_MODE_REPLACEMENT) + for(var/device_id in areaMaster.air_scrub_names) + send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) + for(var/device_id in areaMaster.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) + + if(AALARM_MODE_FILL) + for(var/device_id in areaMaster.air_scrub_names) + send_signal(device_id, list("power"= 0) ) + for(var/device_id in areaMaster.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) + + if(AALARM_MODE_OFF) + for(var/device_id in areaMaster.air_scrub_names) + send_signal(device_id, list("power"= 0) ) + for(var/device_id in areaMaster.air_vent_names) + send_signal(device_id, list("power"= 0) ) + +// This sets our danger level, and, if it's changed, forces a new election of danger levels. +/obj/machinery/alarm/proc/setDangerLevel(var/new_danger_level) + if(local_danger_level==new_danger_level) + return + local_danger_level=new_danger_level + if(areaMaster.updateDangerLevel()) + post_alert(new_danger_level) + +/obj/machinery/alarm/proc/post_alert(alert_level) + var/datum/radio_frequency/frequency = radio_controller.return_frequency(alarm_frequency) + if(!frequency) + return + + var/datum/signal/alert_signal = getFromPool(/datum/signal) + alert_signal.source = src + alert_signal.transmission_method = 1 + alert_signal.data["zone"] = areaMaster.name + alert_signal.data["type"] = "Atmospheric" + + if(alert_level==2) + alert_signal.data["alert"] = "severe" + else if (alert_level==1) + alert_signal.data["alert"] = "minor" + else if (alert_level==0) + alert_signal.data["alert"] = "clear" + + frequency.post_signal(src, alert_signal) + +/obj/machinery/alarm/proc/air_doors_close(manual) + areaMaster.CloseFirelocks() + +/obj/machinery/alarm/proc/air_doors_open(manual) + areaMaster.OpenFirelocks() + +/////////////// +//END HACKING// +/////////////// + +/obj/machinery/alarm/attack_hand(mob/user) + . = ..() + + if (.) + return + + interact(user) + +/obj/machinery/alarm/proc/ui_air_status() + var/turf/location = get_turf(src) + + if (isnull(location)) + return null + + var/datum/gas_mixture/environment = location.return_air() + var/total = environment.oxygen + environment.carbon_dioxide + environment.toxins + environment.nitrogen + if(total==0) + return null + + var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume + + var/list/current_settings = TLV["pressure"] + var/environment_pressure = environment.return_pressure() + var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings) + + current_settings = TLV["oxygen"] + var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, current_settings) + var/oxygen_percent = round(environment.oxygen / total * 100, 2) + + current_settings = TLV["nitrogen"] + var/nitrogen_dangerlevel = get_danger_level(environment.nitrogen*partial_pressure, current_settings) + var/nitrogen_percent = round(environment.nitrogen / total * 100, 2) + + current_settings = TLV["carbon_dioxide"] + var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, current_settings) + var/co2_percent = round(environment.carbon_dioxide / total * 100, 2) + + current_settings = TLV["plasma"] + var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, current_settings) + var/plasma_percent = round(environment.toxins / total * 100, 2) + + current_settings = TLV["other"] + var/other_moles = 0.0 + for(var/datum/gas/G in environment.trace_gases) + other_moles+=G.moles + var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings) + + current_settings = TLV["temperature"] + var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings) + + + var/data[0] + data["pressure"]=environment_pressure + data["temperature"]=environment.temperature + data["temperature_c"]=round(environment.temperature - T0C, 0.1) + + var/percentages[0] + percentages["oxygen"]=oxygen_percent + percentages["nitrogen"]=nitrogen_percent + percentages["co2"]=co2_percent + percentages["plasma"]=plasma_percent + percentages["other"]=other_moles + data["contents"]=percentages + + var/danger[0] + danger["pressure"]=pressure_dangerlevel + danger["temperature"]=temperature_dangerlevel + danger["oxygen"]=oxygen_dangerlevel + danger["nitrogen"]=nitrogen_dangerlevel + danger["co2"]=co2_dangerlevel + danger["plasma"]=plasma_dangerlevel + danger["other"]=other_dangerlevel + danger["overall"]=max(pressure_dangerlevel,oxygen_dangerlevel,nitrogen_dangerlevel,co2_dangerlevel,plasma_dangerlevel,other_dangerlevel,temperature_dangerlevel) + data["danger"]=danger + return data + +/obj/machinery/alarm/proc/get_nano_data(mob/user, fromAtmosConsole=0) + + + var/data[0] + data["air"]=ui_air_status() + data["alarmActivated"]=alarmActivated //|| local_danger_level==2 + data["sensors"]=TLV + + // Locked when: + // Not sent from atmos console AND + // Not silicon AND locked AND + // NOT adminghost. + data["locked"]=!fromAtmosConsole && (!(istype(user, /mob/living/silicon)) && locked) && !isAdminGhost(user) + + data["rcon"]=rcon_setting + data["target_temp"] = target_temperature - T0C + data["atmos_alarm"] = areaMaster.atmosalm + data["modes"] = list( + AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\ + AALARM_MODE_REPLACEMENT = list("name"="Replace Air", "desc"="Siphons out air while replacing"),\ + AALARM_MODE_PANIC = list("name"="Panic", "desc"="Siphons air out of the room"),\ + AALARM_MODE_CYCLE = list("name"="Cycle", "desc"="Siphons air before replacing"),\ + AALARM_MODE_FILL = list("name"="Fill", "desc"="Shuts off scrubbers and opens vents"),\ + AALARM_MODE_OFF = list("name"="Off", "desc"="Shuts off vents and scrubbers")) + data["mode"]=mode + data["presets"]=list( + AALARM_PRESET_HUMAN = list("name"="Human", "desc"="Checks for Oxygen and Nitrogen"),\ + AALARM_PRESET_VOX = list("name"="Vox", "desc"="Checks for Nitrogen only"),\ + AALARM_PRESET_SERVER = list("name"="Coldroom", "desc"="For server rooms and freezers")) + data["preset"]=preset + data["screen"]=screen + + var/list/vents=list() + if(areaMaster.air_vent_names.len) + for(var/id_tag in areaMaster.air_vent_names) + var/vent_info[0] + var/long_name = areaMaster.air_vent_names[id_tag] + var/list/vent_data = areaMaster.air_vent_info[id_tag] + if(!vent_data) + continue + vent_info["id_tag"]=id_tag + vent_info["name"]=long_name + vent_info += vent_data + vents+=list(vent_info) + data["vents"]=vents + + var/list/scrubbers=list() + if(areaMaster.air_scrub_names.len) + for(var/id_tag in areaMaster.air_scrub_names) + var/long_name = areaMaster.air_scrub_names[id_tag] + var/list/scrubber_data = areaMaster.air_scrub_info[id_tag] + if(!scrubber_data) + continue + scrubber_data["id_tag"]=id_tag + scrubber_data["name"]=long_name + scrubbers+=list(scrubber_data) + data["scrubbers"]=scrubbers + return data + + +/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/list/data=src.get_nano_data(user,FALSE) + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + + if (!ui) + // The ui does not exist, so we'll create a new one. + ui = new(user, src, ui_key, "air_alarm.tmpl", name, 550, 410) + // When the UI is first opened this is the data it will use. + ui.set_initial_data(data) + // Open the new ui window. + ui.open() + // Auto update every Master Controller tick. + ui.set_auto_update(1) + +/obj/machinery/alarm/interact(mob/user) + if(buildstage!=2) + return + + if ( (get_dist(src, user) > 1 )) + if (!istype(user, /mob/living/silicon)) + user << browse(null, "window=AAlarmwires") + return + + + else if (istype(user, /mob/living/silicon) && aidisabled) to_chat(user, "AI control for this Air Alarm interface has been disabled.") - user << browse(null, "window=air_alarm") - return - - if(wiresexposed && (isMoMMI(user) || !istype(user, /mob/living/silicon))) - wires.Interact(user) - if(!shorted) - ui_interact(user) - -/obj/machinery/alarm/Topic(href, href_list) - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - if(..()) - return 1 - if(href_list["rcon"]) - rcon_setting = text2num(href_list["rcon"]) - - add_fingerprint(usr) - - //testing(href) - 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", - "o2_scrub", - "n2_scrub", - "panic_siphon", - "scrubbing") - var/val - if(href_list["val"]) - val=text2num(href_list["val"]) - else - var/newval = input("Enter new value") as num|null - if(isnull(newval)) - return - if(href_list["command"]=="set_external_pressure") - if(newval>1000+ONE_ATMOSPHERE) - newval = 1000+ONE_ATMOSPHERE - if(newval<0) - newval = 0 - val = newval - - send_signal(device_id, list(href_list["command"] = 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 num|null - 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() - return 1 - - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - return 1 - - if(href_list["atmos_alarm"]) - alarmActivated=1 - areaMaster.updateDangerLevel() - update_icon() - return 1 - - if(href_list["atmos_reset"]) - alarmActivated=0 - areaMaster.updateDangerLevel() - update_icon() - return 1 - - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - apply_mode() - return 1 - - if(href_list["preset"]) - preset = text2num(href_list["preset"]) - apply_preset() - return 1 - - if(href_list["temperature"]) - var/list/selected = TLV["temperature"] - var/max_temperature = min(selected[3] - T0C, MAX_TEMPERATURE) - var/min_temperature = max(selected[2] - T0C, MIN_TEMPERATURE) - var/input_temperature = input("What temperature would you like the system to maintain? (Capped between [min_temperature]C and [max_temperature]C)", "Thermostat Controls") as num|null - if(input_temperature==null) - return - if(!input_temperature || input_temperature >= max_temperature || input_temperature <= min_temperature) + user << browse(null, "window=air_alarm") + return + + if(wiresexposed && (isMoMMI(user) || !istype(user, /mob/living/silicon))) + wires.Interact(user) + if(!shorted) + ui_interact(user) + +/obj/machinery/alarm/Topic(href, href_list) + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + if(..()) + return 1 + if(href_list["rcon"]) + rcon_setting = text2num(href_list["rcon"]) + + add_fingerprint(usr) + + //testing(href) + 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", + "o2_scrub", + "n2_scrub", + "panic_siphon", + "scrubbing") + var/val + if(href_list["val"]) + val=text2num(href_list["val"]) + else + var/newval = input("Enter new value") as num|null + if(isnull(newval)) + return + if(href_list["command"]=="set_external_pressure") + if(newval>1000+ONE_ATMOSPHERE) + newval = 1000+ONE_ATMOSPHERE + if(newval<0) + newval = 0 + val = newval + + send_signal(device_id, list(href_list["command"] = 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 num|null + 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() + return 1 + + if(href_list["screen"]) + screen = text2num(href_list["screen"]) + return 1 + + if(href_list["atmos_alarm"]) + alarmActivated=1 + areaMaster.updateDangerLevel() + update_icon() + return 1 + + if(href_list["atmos_reset"]) + alarmActivated=0 + areaMaster.updateDangerLevel() + update_icon() + return 1 + + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + apply_mode() + return 1 + + if(href_list["preset"]) + preset = text2num(href_list["preset"]) + apply_preset() + return 1 + + if(href_list["temperature"]) + var/list/selected = TLV["temperature"] + var/max_temperature = min(selected[3] - T0C, MAX_TEMPERATURE) + var/min_temperature = max(selected[2] - T0C, MIN_TEMPERATURE) + var/input_temperature = input("What temperature would you like the system to maintain? (Capped between [min_temperature]C and [max_temperature]C)", "Thermostat Controls") as num|null + if(input_temperature==null) + return + if(!input_temperature || input_temperature >= max_temperature || input_temperature <= min_temperature) to_chat(usr, "Temperature must be between [min_temperature]C and [max_temperature]C") - else - target_temperature = input_temperature + T0C - return 1 - -/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob) - src.add_fingerprint(user) - - switch(buildstage) - if(2) - if(isscrewdriver(W)) // Opening that Air Alarm up. - wiresexposed = !wiresexposed + else + target_temperature = input_temperature + T0C + return 1 + +/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob) + src.add_fingerprint(user) + + switch(buildstage) + if(2) + if(isscrewdriver(W)) // Opening that Air Alarm up. + wiresexposed = !wiresexposed to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - update_icon() - return - - if(wiresexposed && !wires.IsAllCut() && (ismultitool(W) || (iswirecutter(W)))) - return attack_hand(user) - else if(wiresexposed && wires.IsAllCut() && iswirecutter(W)) - buildstage = 1 - update_icon() - user.visible_message("[user] has cut the wiring from \the [src]!", "You have cut the last of the wiring from \the [src].") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - getFromPool(/obj/item/stack/cable_coil, get_turf(user), 5) - return - if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card - if(stat & (NOPOWER|BROKEN)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + update_icon() + return + + if(wiresexposed && !wires.IsAllCut() && (ismultitool(W) || (iswirecutter(W)))) + return attack_hand(user) + else if(wiresexposed && wires.IsAllCut() && iswirecutter(W)) + buildstage = 1 + update_icon() + user.visible_message("[user] has cut the wiring from \the [src]!", "You have cut the last of the wiring from \the [src].") + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + getFromPool(/obj/item/stack/cable_coil, get_turf(user), 5) + return + if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card + if(stat & (NOPOWER|BROKEN)) to_chat(user, "It does nothing") - return - else - if(allowed(user) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN)) - locked = !locked + return + else + if(allowed(user) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN)) + locked = !locked to_chat(user, "You [ locked ? "lock" : "unlock"] the Air Alarm interface.") - else + else to_chat(user, "Access denied.") - return ..() //Sanity - - if(1) - if(iscoil(W)) - var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 5) + return ..() //Sanity + + if(1) + if(iscoil(W)) + var/obj/item/stack/cable_coil/coil = W + if(coil.amount < 5) to_chat(user, "You need more cable for this!") - return - for(var/i, i<= 5, i++) - wires.UpdateCut(i,1) - + return + for(var/i, i<= 5, i++) + wires.UpdateCut(i,1) + to_chat(user, "You wire \the [src]!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - coil.use(5) - buildstage = 2 - update_icon() - first_run() - return - - else if(iscrowbar(W)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + coil.use(5) + buildstage = 2 + update_icon() + first_run() + return + + else if(iscrowbar(W)) to_chat(user, "You start prying out the circuit...") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - if(do_after(user, src, 20) && buildstage == 1) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + if(do_after(user, src, 20) && buildstage == 1) to_chat(user, "You pry out the circuit!") - new /obj/item/weapon/circuitboard/air_alarm(get_turf(user)) - buildstage = 0 - update_icon() - return - if(0) - if(istype(W, /obj/item/weapon/circuitboard/air_alarm)) + new /obj/item/weapon/circuitboard/air_alarm(get_turf(user)) + buildstage = 0 + update_icon() + return + if(0) + if(istype(W, /obj/item/weapon/circuitboard/air_alarm)) to_chat(user, "You insert the circuit!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - qdel(W) - buildstage = 1 - update_icon() - return - - else if(iswrench(W)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + qdel(W) + buildstage = 1 + update_icon() + return + + else if(iswrench(W)) to_chat(user, "You remove the air alarm assembly from the wall!") - new /obj/item/mounted/frame/alarm_frame(get_turf(user)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - qdel(src) - return - -/obj/machinery/alarm/power_change() - if(powered(power_channel)) - stat &= ~NOPOWER - else - stat |= NOPOWER - spawn(rand(0,15)) - update_icon() - -/obj/machinery/alarm/examine(mob/user) - ..() - if (buildstage < 2) + new /obj/item/mounted/frame/alarm_frame(get_turf(user)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + qdel(src) + return + +/obj/machinery/alarm/power_change() + if(powered(power_channel)) + stat &= ~NOPOWER + else + stat |= NOPOWER + spawn(rand(0,15)) + update_icon() + +/obj/machinery/alarm/examine(mob/user) + ..() + if (buildstage < 2) to_chat(user, "It is not wired.") - if (buildstage < 1) + if (buildstage < 1) to_chat(user, "The circuit is missing.") - -/obj/machinery/alarm/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) - -/obj/machinery/alarm/wirejack(var/mob/living/silicon/pai/P) - if(..()) - locked = !locked - update_icon() - return 1 - return 0 - -/* -FIRE ALARM -*/ -/obj/machinery/firealarm - name = "Fire Alarm" - desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." - icon = 'icons/obj/monitors.dmi' - icon_state = "fire0" - var/detecting = 1.0 - var/working = 1.0 - var/time = 10.0 - var/timing = 0.0 - var/lockdownbyai = 0 - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 6 - power_channel = ENVIRON - var/last_process = 0 - var/wiresexposed = 0 - var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone - -/obj/machinery/firealarm/update_icon() - - if(wiresexposed) - switch(buildstage) - if(2) - icon_state="fire_b2" - if(1) - icon_state="fire_b1" - if(0) - icon_state="fire_b0" - - return - - if(stat & BROKEN) - icon_state = "firex" - else if(stat & NOPOWER) - icon_state = "firep" - else if(!src.detecting) - icon_state = "fire1" - else - icon_state = "fire0" - -/obj/machinery/firealarm/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(src.detecting) - if(exposed_temperature > T0C+200) - src.alarm() // added check of detector status here - return - -/obj/machinery/firealarm/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/firealarm/bullet_act(BLAH) - return src.alarm() - -/obj/machinery/firealarm/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/firealarm/emp_act(severity) - if(prob(50/severity)) alarm() - ..() - -/obj/machinery/firealarm/attackby(obj/item/W as obj, mob/user as mob) - src.add_fingerprint(user) - - if (istype(W, /obj/item/weapon/screwdriver) && buildstage == 2) - wiresexposed = !wiresexposed + +/obj/machinery/alarm/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) + +/obj/machinery/alarm/wirejack(var/mob/living/silicon/pai/P) + if(..()) + locked = !locked + update_icon() + return 1 + return 0 + +/* +FIRE ALARM +*/ +/obj/machinery/firealarm + name = "Fire Alarm" + desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." + icon = 'icons/obj/monitors.dmi' + icon_state = "fire0" + var/detecting = 1.0 + var/working = 1.0 + var/time = 10.0 + var/timing = 0.0 + var/lockdownbyai = 0 + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 6 + power_channel = ENVIRON + var/last_process = 0 + var/wiresexposed = 0 + var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone + +/obj/machinery/firealarm/update_icon() + + if(wiresexposed) + switch(buildstage) + if(2) + icon_state="fire_b2" + if(1) + icon_state="fire_b1" + if(0) + icon_state="fire_b0" + + return + + if(stat & BROKEN) + icon_state = "firex" + else if(stat & NOPOWER) + icon_state = "firep" + else if(!src.detecting) + icon_state = "fire1" + else + icon_state = "fire0" + +/obj/machinery/firealarm/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(src.detecting) + if(exposed_temperature > T0C+200) + src.alarm() // added check of detector status here + return + +/obj/machinery/firealarm/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/firealarm/bullet_act(BLAH) + return src.alarm() + +/obj/machinery/firealarm/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/firealarm/emp_act(severity) + if(prob(50/severity)) alarm() + ..() + +/obj/machinery/firealarm/attackby(obj/item/W as obj, mob/user as mob) + src.add_fingerprint(user) + + if (istype(W, /obj/item/weapon/screwdriver) && buildstage == 2) + wiresexposed = !wiresexposed to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - update_icon() - return - - if(wiresexposed) - switch(buildstage) - if(2) - if (ismultitool(W)) - src.detecting = !( src.detecting ) - user.visible_message("[user] has [detecting ? "re" : "dis"]connected [src]'s detecting unit!", "You have [detecting ? "re" : "dis"]reconnected [src]'s detecting unit.") - playsound(get_turf(src), 'sound/items/healthanalyzer.ogg', 50, 1) - if(iswirecutter(W)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + update_icon() + return + + if(wiresexposed) + switch(buildstage) + if(2) + if (ismultitool(W)) + src.detecting = !( src.detecting ) + user.visible_message("[user] has [detecting ? "re" : "dis"]connected [src]'s detecting unit!", "You have [detecting ? "re" : "dis"]reconnected [src]'s detecting unit.") + playsound(get_turf(src), 'sound/items/healthanalyzer.ogg', 50, 1) + if(iswirecutter(W)) to_chat(user, "You begin to cut the wiring...") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - if (do_after(user, src, 50) && buildstage == 2 && wiresexposed) - buildstage=1 - user.visible_message("[user] has cut the wiring from \the [src]!", "You have cut the last of the wiring from \the [src].") - update_icon() - getFromPool(/obj/item/stack/cable_coil, get_turf(user), 5) - if(1) - if(iscoil(W)) - var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 5) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + if (do_after(user, src, 50) && buildstage == 2 && wiresexposed) + buildstage=1 + user.visible_message("[user] has cut the wiring from \the [src]!", "You have cut the last of the wiring from \the [src].") + update_icon() + getFromPool(/obj/item/stack/cable_coil, get_turf(user), 5) + if(1) + if(iscoil(W)) + var/obj/item/stack/cable_coil/coil = W + if(coil.amount < 5) to_chat(user, "You need more cable for this!") - return - coil.use(5) - - buildstage = 2 + return + coil.use(5) + + buildstage = 2 to_chat(user, "You wire \the [src]!") - update_icon() - - else if(istype(W, /obj/item/weapon/crowbar)) + update_icon() + + else if(istype(W, /obj/item/weapon/crowbar)) to_chat(user, "You start prying out the circuit...") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - if (do_after(user, src, 20) && buildstage == 1) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + if (do_after(user, src, 20) && buildstage == 1) to_chat(user, "You pry out the circuit!") - new /obj/item/weapon/circuitboard/fire_alarm(get_turf(user)) - buildstage = 0 - update_icon() - if(0) - if(istype(W, /obj/item/weapon/circuitboard/fire_alarm)) + new /obj/item/weapon/circuitboard/fire_alarm(get_turf(user)) + buildstage = 0 + update_icon() + if(0) + if(istype(W, /obj/item/weapon/circuitboard/fire_alarm)) to_chat(user, "You insert the circuit!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - qdel(W) - buildstage = 1 - update_icon() - - else if(iswrench(W)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + qdel(W) + buildstage = 1 + update_icon() + + else if(iswrench(W)) to_chat(user, "You remove the fire alarm assembly from the wall!") - new /obj/item/mounted/frame/firealarm(get_turf(user)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - qdel(src) - return - - src.alarm() - -/obj/machinery/firealarm/process()//Note: this processing was mostly phased out due to other code, and only runs when needed - if(stat & (NOPOWER|BROKEN)) - return - - if(src.timing) - if(src.time > 0) - src.time = src.time - ((world.timeofday - last_process)/10) - else - src.alarm() - src.time = 0 - src.timing = 0 - processing_objects.Remove(src) - src.updateDialog() - last_process = world.timeofday - - if(locate(/obj/fire) in loc) - alarm() - - return - -/obj/machinery/firealarm/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER - update_icon() - else - spawn(rand(0,15)) - stat |= NOPOWER - update_icon() - -/obj/machinery/firealarm/attack_hand(mob/user as mob) - if((user.stat && !isobserver(user)) || stat & (NOPOWER|BROKEN)) - return - - if (buildstage != 2) - return - - user.set_machine(src) - var/d1 - var/d2 - if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon) || isobserver(user)) - - if (areaMaster.fire) - d1 = text("Reset - Lockdown", src) - else - d1 = text("Alarm - Lockdown", src) - if (src.timing) - d2 = text("Stop Time Lock", src) - else - d2 = text("Initiate Time Lock", src) - var/second = round(src.time) % 60 - var/minute = (round(src.time) - second) / 60 - var/dat = "Fire alarm [d1]\n
      The current alert level is: [get_security_level()]


      \nTimer System: [d2]
      \nTime Left: [(minute ? "[minute]:" : null)][second] - - + +\n
      " - user << browse(dat, "window=firealarm") - onclose(user, "firealarm") - else - if (areaMaster.fire) - d1 = text("[]", src, stars("Reset - Lockdown")) - else - d1 = text("[]", src, stars("Alarm - Lockdown")) - if (src.timing) - d2 = text("[]", src, stars("Stop Time Lock")) - else - d2 = text("[]", src, stars("Initiate Time Lock")) - var/second = round(src.time) % 60 - var/minute = (round(src.time) - second) / 60 - var/dat = "[stars("Fire alarm")] [d1]\n
      The current alert level is: [stars(get_security_level())]

      \nTimer System: [d2]
      \nTime Left: [(minute ? text("[]:", minute) : null)][second] - - + +\n
      " - user << browse(dat, "window=firealarm") - onclose(user, "firealarm") - return - -/obj/machinery/firealarm/Topic(href, href_list) - if(..()) return 1 - if (usr.stat || stat & (BROKEN|NOPOWER)) - return - - if (buildstage != 2) - return - - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - if (href_list["reset"]) - src.reset() - else if (href_list["alarm"]) - src.alarm() - else if (href_list["time"]) - src.timing = text2num(href_list["time"]) - last_process = world.timeofday - processing_objects.Add(src) - else if (href_list["tp"]) - var/tp = text2num(href_list["tp"]) - src.time += tp - src.time = min(max(round(src.time), 0), 120) - - src.updateUsrDialog() - - src.add_fingerprint(usr) - else - usr << browse(null, "window=firealarm") - return - return - -/obj/machinery/firealarm/proc/reset() - if (!( src.working )) - return - areaMaster.firereset() - update_icon() - return - -/obj/machinery/firealarm/proc/alarm() - if (!( src.working )) - return - areaMaster.firealert() - update_icon() - //playsound(get_turf(src), 'sound/ambience/signal.ogg', 75, 0) - return - -/obj/machinery/firealarm/New(loc, dir, building) - ..() - name = "[areaMaster.name] fire alarm" - if(loc) - src.loc = loc - - if(dir) - src.dir = dir - - if(building) - buildstage = 0 - wiresexposed = 1 - pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) - pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 - - if(z == 1) - if(security_level) - src.overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]") - else - src.overlays += image('icons/obj/monitors.dmi', "overlay_green") - - machines.Remove(src) - update_icon() - -/obj/machinery/firealarm/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) - -/obj/machinery/partyalarm - name = "\improper PARTY BUTTON" - desc = "Cuban Pete is in the house!" - icon = 'icons/obj/monitors.dmi' - icon_state = "fire0" - var/detecting = 1.0 - var/working = 1.0 - var/time = 10.0 - var/timing = 0.0 - var/lockdownbyai = 0 - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 6 - -/obj/machinery/partyalarm/New() - ..() - name = "[areaMaster.name] party alarm" - -/obj/machinery/partyalarm/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/machinery/partyalarm/attack_hand(mob/user as mob) - if((user.stat && !isobserver(user)) || stat & (NOPOWER|BROKEN)) - return - - user.machine = src - var/d1 - var/d2 - if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) - if (areaMaster.party) - d1 = text("No Party :(", src) - else - d1 = text("PARTY!!!", src) - if (timing) - d2 = text("Stop Time Lock", src) - else - d2 = text("Initiate Time Lock", src) - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = text("Party Button []\n
      \nTimer System: []
      \nTime Left: [][] - - + +\n
      ", d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src) - user << browse(dat, "window=partyalarm") - onclose(user, "partyalarm") - else - if (areaMaster.fire) - d1 = text("[]", src, stars("No Party :(")) - else - d1 = text("[]", src, stars("PARTY!!!")) - if (timing) - d2 = text("[]", src, stars("Stop Time Lock")) - else - d2 = text("[]", src, stars("Initiate Time Lock")) - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = text("[] []\n
      \nTimer System: []
      \nTime Left: [][] - - + +\n
      ", stars("Party Button"), d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src) - user << browse(dat, "window=partyalarm") - onclose(user, "partyalarm") - return - -/obj/machinery/partyalarm/proc/reset() - if (!( working )) - return - areaMaster.partyreset() - return - -/obj/machinery/partyalarm/proc/alarm() - if (!( working )) - return - areaMaster.partyalert() - return - -/obj/machinery/partyalarm/Topic(href, href_list) - if(..()) return 1 - if (usr.stat || stat & (BROKEN|NOPOWER)) - return - - usr.machine = src - if (href_list["reset"]) - reset() - else - if (href_list["alarm"]) - alarm() - else - if (href_list["time"]) - timing = text2num(href_list["time"]) - else - if (href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 120) - updateUsrDialog() - - add_fingerprint(usr) - return + new /obj/item/mounted/frame/firealarm(get_turf(user)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + qdel(src) + return + + src.alarm() + +/obj/machinery/firealarm/process()//Note: this processing was mostly phased out due to other code, and only runs when needed + if(stat & (NOPOWER|BROKEN)) + return + + if(src.timing) + if(src.time > 0) + src.time = src.time - ((world.timeofday - last_process)/10) + else + src.alarm() + src.time = 0 + src.timing = 0 + processing_objects.Remove(src) + src.updateDialog() + last_process = world.timeofday + + if(locate(/obj/fire) in loc) + alarm() + + return + +/obj/machinery/firealarm/power_change() + if(powered(ENVIRON)) + stat &= ~NOPOWER + update_icon() + else + spawn(rand(0,15)) + stat |= NOPOWER + update_icon() + +/obj/machinery/firealarm/attack_hand(mob/user as mob) + if((user.stat && !isobserver(user)) || stat & (NOPOWER|BROKEN)) + return + + if (buildstage != 2) + return + + user.set_machine(src) + var/d1 + var/d2 + if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon) || isobserver(user)) + + if (areaMaster.fire) + d1 = text("Reset - Lockdown", src) + else + d1 = text("Alarm - Lockdown", src) + if (src.timing) + d2 = text("Stop Time Lock", src) + else + d2 = text("Initiate Time Lock", src) + var/second = round(src.time) % 60 + var/minute = (round(src.time) - second) / 60 + var/dat = "Fire alarm [d1]\n
      The current alert level is: [get_security_level()]


      \nTimer System: [d2]
      \nTime Left: [(minute ? "[minute]:" : null)][second] - - + +\n
      " + user << browse(dat, "window=firealarm") + onclose(user, "firealarm") + else + if (areaMaster.fire) + d1 = text("[]", src, stars("Reset - Lockdown")) + else + d1 = text("[]", src, stars("Alarm - Lockdown")) + if (src.timing) + d2 = text("[]", src, stars("Stop Time Lock")) + else + d2 = text("[]", src, stars("Initiate Time Lock")) + var/second = round(src.time) % 60 + var/minute = (round(src.time) - second) / 60 + var/dat = "[stars("Fire alarm")] [d1]\n
      The current alert level is: [stars(get_security_level())]

      \nTimer System: [d2]
      \nTime Left: [(minute ? text("[]:", minute) : null)][second] - - + +\n
      " + user << browse(dat, "window=firealarm") + onclose(user, "firealarm") + return + +/obj/machinery/firealarm/Topic(href, href_list) + if(..()) return 1 + if (usr.stat || stat & (BROKEN|NOPOWER)) + return + + if (buildstage != 2) + return + + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + if (href_list["reset"]) + src.reset() + else if (href_list["alarm"]) + src.alarm() + else if (href_list["time"]) + src.timing = text2num(href_list["time"]) + last_process = world.timeofday + processing_objects.Add(src) + else if (href_list["tp"]) + var/tp = text2num(href_list["tp"]) + src.time += tp + src.time = min(max(round(src.time), 0), 120) + + src.updateUsrDialog() + + src.add_fingerprint(usr) + else + usr << browse(null, "window=firealarm") + return + return + +/obj/machinery/firealarm/proc/reset() + if (!( src.working )) + return + areaMaster.firereset() + update_icon() + return + +/obj/machinery/firealarm/proc/alarm() + if (!( src.working )) + return + areaMaster.firealert() + update_icon() + //playsound(get_turf(src), 'sound/ambience/signal.ogg', 75, 0) + return + +/obj/machinery/firealarm/New(loc, dir, building) + ..() + name = "[areaMaster.name] fire alarm" + if(loc) + src.loc = loc + + if(dir) + src.dir = dir + + if(building) + buildstage = 0 + wiresexposed = 1 + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + + if(z == 1) + if(security_level) + src.overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]") + else + src.overlays += image('icons/obj/monitors.dmi', "overlay_green") + + machines.Remove(src) + update_icon() + +/obj/machinery/firealarm/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) + +/obj/machinery/partyalarm + name = "\improper PARTY BUTTON" + desc = "Cuban Pete is in the house!" + icon = 'icons/obj/monitors.dmi' + icon_state = "fire0" + var/detecting = 1.0 + var/working = 1.0 + var/time = 10.0 + var/timing = 0.0 + var/lockdownbyai = 0 + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 6 + +/obj/machinery/partyalarm/New() + ..() + name = "[areaMaster.name] party alarm" + +/obj/machinery/partyalarm/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/machinery/partyalarm/attack_hand(mob/user as mob) + if((user.stat && !isobserver(user)) || stat & (NOPOWER|BROKEN)) + return + + user.machine = src + var/d1 + var/d2 + if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) + if (areaMaster.party) + d1 = text("No Party :(", src) + else + d1 = text("PARTY!!!", src) + if (timing) + d2 = text("Stop Time Lock", src) + else + d2 = text("Initiate Time Lock", src) + var/second = time % 60 + var/minute = (time - second) / 60 + var/dat = text("Party Button []\n
      \nTimer System: []
      \nTime Left: [][] - - + +\n
      ", d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src) + user << browse(dat, "window=partyalarm") + onclose(user, "partyalarm") + else + if (areaMaster.fire) + d1 = text("[]", src, stars("No Party :(")) + else + d1 = text("[]", src, stars("PARTY!!!")) + if (timing) + d2 = text("[]", src, stars("Stop Time Lock")) + else + d2 = text("[]", src, stars("Initiate Time Lock")) + var/second = time % 60 + var/minute = (time - second) / 60 + var/dat = text("[] []\n
      \nTimer System: []
      \nTime Left: [][] - - + +\n
      ", stars("Party Button"), d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src) + user << browse(dat, "window=partyalarm") + onclose(user, "partyalarm") + return + +/obj/machinery/partyalarm/proc/reset() + if (!( working )) + return + areaMaster.partyreset() + return + +/obj/machinery/partyalarm/proc/alarm() + if (!( working )) + return + areaMaster.partyalert() + return + +/obj/machinery/partyalarm/Topic(href, href_list) + if(..()) return 1 + if (usr.stat || stat & (BROKEN|NOPOWER)) + return + + usr.machine = src + if (href_list["reset"]) + reset() + else + if (href_list["alarm"]) + alarm() + else + if (href_list["time"]) + timing = text2num(href_list["time"]) + else + if (href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 120) + updateUsrDialog() + + add_fingerprint(usr) + return diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index eccdcf4761f..9b8c330f87e 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -1,524 +1,524 @@ -#define OVERLAY_HOLDING 1 -#define OVERLAY_CONNECTED 2 -#define OVERLAY_NO_PRESSURE 4 -#define OVERLAY_LOW_PRESSURE 8 -#define OVERLAY_MEDIUM_PRESSURE 16 -#define OVERLAY_HIGH_PRESSURE 32 - -/obj/machinery/portable_atmospherics/canister - name = "canister" - icon = 'icons/obj/atmos.dmi' - icon_state = "yellow" - density = 1 - var/health = 100.0 - flags = FPRINT - siemens_coefficient = 1 - - var/valve_open = 0 - var/release_pressure = ONE_ATMOSPHERE - - var/canister_color = "yellow" - var/old_color = 0 - var/can_label = 1 - var/filled = 0.5 // Mapping var: Set to 0 for empty, 1 to full, anywhere between. - pressure_resistance = 7*ONE_ATMOSPHERE - var/temperature_resistance = 1000 + T0C - volume = 1000 - use_power = 0 - var/release_log = "" - var/busy = 0 - starting_materials = list(MAT_IRON = 10*CC_PER_SHEET_METAL) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - - //Icon Update Code - var/global/status_overlays = 0 - var/global/list/status_overlays_pressure - var/global/list/status_overlays_other - var/overlay_status = 0 - - var/log="" // Bad boys, bad boys. - -/obj/machinery/portable_atmospherics/canister/New() - ..() - old_color = canister_color - -/obj/machinery/portable_atmospherics/canister/sleeping_agent - name = "Canister: \[N2O\]" - icon_state = "redws" - canister_color = "redws" - can_label = 0 - -/obj/machinery/portable_atmospherics/canister/nitrogen - name = "Canister: \[N2\]" - icon_state = "red" - canister_color = "red" - can_label = 0 - -/obj/machinery/portable_atmospherics/canister/oxygen - name = "Canister: \[O2\]" - icon_state = "blue" - canister_color = "blue" - can_label = 0 - -/obj/machinery/portable_atmospherics/canister/plasma - name = "Canister \[Plasma\]" - icon_state = "orange" - canister_color = "orange" - can_label = 0 - -/obj/machinery/portable_atmospherics/canister/carbon_dioxide - name = "Canister \[CO2\]" - icon_state = "black" - canister_color = "black" - can_label = 0 - -/obj/machinery/portable_atmospherics/canister/air - name = "Canister \[Air\]" - icon_state = "grey" - canister_color = "grey" - can_label = 0 - -/obj/machinery/portable_atmospherics/canister/update_icon() - if(destroyed) - icon_state = "[canister_color]-1" - overlays.len = 0 - return - - if(!status_overlays) - status_overlays = 1 - - status_overlays_pressure = new - status_overlays_other = new - - status_overlays_pressure.len = 4 - status_overlays_other.len = 2 - - status_overlays_pressure[1] = image(icon, "can-o0") - status_overlays_pressure[2] = image(icon, "can-o1") - status_overlays_pressure[3] = image(icon, "can-o2") - status_overlays_pressure[4] = image(icon, "can-o3") - - status_overlays_other[1] = image(icon, "can-open") - status_overlays_other[2] = image(icon, "can-connector") - - if (canister_color != old_color) - icon_state = "[canister_color]" - old_color = canister_color - - var/tank_pressure = air_contents.return_pressure() - if(check_updates(tank_pressure)) - if(overlays.len) - overlays = 0 - - overlay_status = 0 - - if (holding) - overlays += status_overlays_other[1] - overlay_status |= OVERLAY_HOLDING - - if (connected_port) - overlays += status_overlays_other[2] - overlay_status |= OVERLAY_CONNECTED - - switch(tank_pressure) - if(15 * ONE_ATMOSPHERE to INFINITY) - overlays += status_overlays_pressure[4] - overlay_status |= OVERLAY_HIGH_PRESSURE - if(ONE_ATMOSPHERE to 15 * ONE_ATMOSPHERE) - overlays += status_overlays_pressure[3] - overlay_status |= OVERLAY_MEDIUM_PRESSURE - if(10 to ONE_ATMOSPHERE) - overlays += status_overlays_pressure[2] - overlay_status |= OVERLAY_LOW_PRESSURE - else - overlays += status_overlays_pressure[1] - overlay_status |= OVERLAY_NO_PRESSURE - return - -/obj/machinery/portable_atmospherics/canister/proc/check_updates(tank_pressure = 0) - if((overlay_status & OVERLAY_HOLDING) != holding) - return 1 - if((overlay_status & OVERLAY_CONNECTED) != connected_port) - return 1 - if((overlay_status & OVERLAY_HIGH_PRESSURE) && tank_pressure < 15*ONE_ATMOSPHERE) - return 1 - if((overlay_status & OVERLAY_MEDIUM_PRESSURE) && (tank_pressure < ONE_ATMOSPHERE || tank_pressure > 15*ONE_ATMOSPHERE)) - return 1 - if((overlay_status & OVERLAY_LOW_PRESSURE) && (tank_pressure < 10 || tank_pressure > ONE_ATMOSPHERE)) - return 1 - if((overlay_status & OVERLAY_NO_PRESSURE) && tank_pressure > 10) - return 1 - return 0 - - -/obj/machinery/portable_atmospherics/canister/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > temperature_resistance) - health -= 5 - healthcheck() - -/obj/machinery/portable_atmospherics/canister/proc/healthcheck() - if(destroyed) - return 1 - - if (src.health <= 10) - var/atom/location = src.loc - location.assume_air(air_contents) - - src.destroyed = 1 - playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3) - src.density = 0 - update_icon() - investigation_log(I_ATMOS, "was destoyed by excessive damage.") - - if (src.holding) - src.holding.loc = src.loc - src.holding = null - INVOKE_EVENT(on_destroyed, list()) - nanomanager.update_uis(src) - return 1 - else - return 1 - -/obj/machinery/portable_atmospherics/canister/process() - if (destroyed) - return - - ..() - - handle_beams() //emitter beams - - if(valve_open) - var/datum/gas_mixture/environment - if(holding) - environment = holding.air_contents - else - environment = loc.return_air() - - var/env_pressure = environment.return_pressure() - var/pressure_delta = min(release_pressure - env_pressure, (air_contents.return_pressure() - env_pressure)/2) - //Can not have a pressure delta that would cause environment pressure > tank pressure - - var/transfer_moles = 0 - if((air_contents.temperature > 0) && (pressure_delta > 0)) - transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - if(holding) - environment.merge(removed) - else - loc.assume_air(removed) - src.update_icon() - nanomanager.update_uis(src) - - if(air_contents.return_pressure() < 1) - can_label = 1 - else - can_label = 0 - - if(air_contents.temperature > PLASMA_FLASHPOINT) - air_contents.zburn() - nanomanager.update_uis(src) - - return - -/obj/machinery/portable_atmospherics/canister/return_air() - return air_contents - -/obj/machinery/portable_atmospherics/canister/proc/return_temperature() - var/datum/gas_mixture/GM = src.return_air() - if(GM && GM.volume>0) - return GM.temperature - return 0 - -/obj/machinery/portable_atmospherics/canister/proc/return_pressure() - var/datum/gas_mixture/GM = src.return_air() - if(GM && GM.volume>0) - return GM.return_pressure() - return 0 - -/obj/machinery/portable_atmospherics/canister/blob_act() - src.health -= 200 - healthcheck() - return - -/obj/machinery/portable_atmospherics/canister/bullet_act(var/obj/item/projectile/Proj) - if(Proj.damage) - src.health -= round(Proj.damage / 2) - healthcheck() - ..() - -/obj/machinery/portable_atmospherics/canister/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(iswelder(W) && src.destroyed) - if(weld(W, user)) - to_chat(user, "You salvage what's left of \the [src].") - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src))//new /obj/item/stack/sheet/metal(src.loc) - M.amount = 3 - qdel (src) - return - - if(!istype(W, /obj/item/weapon/wrench) && !istype(W, /obj/item/weapon/tank) && !istype(W, /obj/item/device/analyzer) && !istype(W, /obj/item/device/pda)) - visible_message("[user] hits the [src] with a [W]!") - investigation_log(I_ATMOS, "was smacked with \a [W] by [key_name(user)]") - src.health -= W.force - src.add_fingerprint(user) - healthcheck() - - if(istype(user, /mob/living/silicon/robot) && istype(W, /obj/item/weapon/tank/jetpack)) - var/datum/gas_mixture/thejetpack = W:air_contents - var/env_pressure = thejetpack.return_pressure() - var/pressure_delta = min(10*ONE_ATMOSPHERE - env_pressure, (air_contents.return_pressure() - env_pressure)/2) - //Can not have a pressure delta that would cause environment pressure > tank pressure - var/transfer_moles = 0 - if((air_contents.temperature > 0) && (pressure_delta > 0)) - transfer_moles = pressure_delta*thejetpack.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)//Actually transfer the gas - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - thejetpack.merge(removed) - to_chat(user, "You pulse-pressurize your jetpack from the tank.") - return - - ..() - - nanomanager.update_uis(src) // Update all NanoUIs attached to src - - - -/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/portable_atmospherics/canister/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) - return src.ui_interact(user) - -/obj/machinery/portable_atmospherics/canister/attack_alien(var/mob/living/carbon/alien/user as mob) - src.add_hiddenprint(user) - health -= rand(15, 30) - user.visible_message("\The [user] slashes away at \the [src]!", \ - "You slash away at \the [src]!") - user.delayNextAttack(10) //Hold on there amigo - investigation_log(I_ATMOS, "was slashed at by alien [key_name(user)]") - playsound(get_turf(src), 'sound/weapons/slice.ogg', 25, 1, -1) - healthcheck() - -/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - if (src.destroyed || gcDestroyed || !get_turf(src)) - if(!ui) - ui = nanomanager.get_open_ui(user, src, ui_key) - if(ui) ui.close() - return - - // this is the data which will be sent to the ui - var/data[0] - data["name"] = name - data["canLabel"] = can_label ? 1 : 0 - data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0)//This used to be redundant, made it into a fix for -1 kPA showing up in the UI - data["releasePressure"] = round(release_pressure) - data["minReleasePressure"] = round(ONE_ATMOSPHERE/10) - data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE) - data["valveOpen"] = valve_open ? 1 : 0 - - data["hasHoldingTank"] = holding ? 1 : 0 - if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - //ui.set_auto_update(1) - -/obj/machinery/portable_atmospherics/canister/Topic(href, href_list) - . = ..()//Sanity - if(.) - return . - - if(href_list["toggle"]) - var/datum/gas/sleeping_agent/S = locate() in src.air_contents.trace_gases - - if (valve_open) - if (holding) - investigation_log(I_ATMOS, "had its valve closed by [key_name(usr)], stopping transfer into \the [holding].") - else - investigation_log(I_ATMOS, "had its valve closed by [key_name(usr)], stopping transfer into the air") - else - if (holding) - investigation_log(I_ATMOS, "had its valve OPENED by [key_name(usr)], starting transfer into \the [holding]") - else - var/list/contents_l=list() - if(src.air_contents.toxins > 0) - contents_l += "Plasma" - if(src.air_contents.carbon_dioxide > 0) - contents_l += "CO2" - if(istype(S)) - contents_l += "N2O
      " - var/contents_str = english_list(contents_l) - investigation_log(I_ATMOS, "had its valve OPENED by [key_name(usr)], starting transfer into the air ([contents_str])") - if(contents_l.len>0) - message_admins("[usr.real_name] ([formatPlayerPanel(usr,usr.ckey)]) opened a canister that contains [contents_str] at [formatJumpTo(loc)]!") - log_admin("[usr]([ckey(usr.key)]) opened a canister that contains [contents] at [loc.x], [loc.y], [loc.z]") - - valve_open = !valve_open - - if (href_list["remove_tank"]) - var/datum/gas/sleeping_agent/S = locate() in src.air_contents.trace_gases - if(holding) - if(valve_open) - if(src.air_contents.toxins > 0 || (istype(S))) - message_admins("[usr.real_name] ([formatPlayerPanel(usr,usr.ckey)]) opened a canister that contains \[[src.air_contents.toxins > 0 ? "Toxins" : ""] [istype(S) ? " N2O" : ""]\] at [formatJumpTo(loc)]!") - log_admin("[usr]([ckey(usr.key)]) opened a canister that contains \[[src.air_contents.toxins > 0 ? "Toxins" : ""] [istype(S) ? " N2O" : ""]\] at [loc.x], [loc.y], [loc.z]") - - if(istype(holding, /obj/item/weapon/tank)) - holding.manipulated_by = usr.real_name - holding.loc = loc - holding = null - - if (href_list["pressure_adj"]) - var/diff = text2num(href_list["pressure_adj"]) - if(diff > 0) - release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff) - else - release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff) - - if (href_list["relabel"]) - if (can_label) - var/list/colors = list(\ - "\[N2O\]" = "redws", \ - "\[N2\]" = "red", \ - "\[O2\]" = "blue", \ - "\[Plasma\]" = "orange", \ - "\[CO2\]" = "black", \ - "\[Air\]" = "grey", \ - "\[CAUTION\]" = "yellow", \ - ) - var/label = input("Choose canister label", "Gas canister") as null|anything in colors - if (label) - src.canister_color = colors[label] - src.icon_state = colors[label] - src.name = "Canister: [label]" - - src.add_fingerprint(usr) - src.add_hiddenprint(usr) - update_icon() - - return 1 - -/obj/machinery/portable_atmospherics/canister/plasma/New(loc) - ..(loc) - air_contents.adjust(tx = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) - update_icon() - -/obj/machinery/portable_atmospherics/canister/oxygen/New(loc) - ..(loc) - src.air_contents.adjust((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) - update_icon() - -/obj/machinery/portable_atmospherics/canister/sleeping_agent/New(loc) - ..(loc) - var/datum/gas/sleeping_agent/sleeping_agent = new - sleeping_agent.moles = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) - air_contents.adjust(traces = list(sleeping_agent)) - update_icon() - -/* -//Dirty way to fill room with gas. However it is a bit easier to do than creating some floor/engine/n2o -rastaf0 -/obj/machinery/portable_atmospherics/canister/sleeping_agent/roomfiller/New() - ..() - var/datum/gas/sleeping_agent/trace_gas = air_contents.trace_gases[1] - trace_gas.moles = 9*4000 - spawn(10) - var/turf/simulated/location = src.loc - if (istype(src.loc)) - while (!location.air) - sleep(10) - location.assume_air(air_contents) - air_contents = new - return 1 -*/ - -/obj/machinery/portable_atmospherics/canister/nitrogen/New(loc) - ..(loc) - air_contents.adjust(n2 = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) - update_icon() - -/obj/machinery/portable_atmospherics/canister/carbon_dioxide/New(loc) - ..(loc) - air_contents.adjust(co2 = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) - update_icon() - -/obj/machinery/portable_atmospherics/canister/air/New(loc) - ..(loc) - - air_contents.adjust(\ - (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature),\ - n2 = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)\ - ) - - update_icon() - -/obj/machinery/portable_atmospherics/canister/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/user) - - - if(busy) - return 0 - if(!WT.isOn()) - return 0 - - // Do after stuff here - to_chat(user, "You start to slice away at \the [src]...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - WT.eyecheck(user) - busy = 1 - if(do_after(user, src, 50)) - busy = 0 - if(!WT.isOn()) - return 0 - return 1 - busy = 0 - return 0 - -/obj/machinery/portable_atmospherics/canister/apply_beam_damage(var/obj/effect/beam/B) - var/lastcheck=last_beamchecks["\ref[B]"] - - var/damage = ((world.time - lastcheck)/10) * (B.get_damage()/2) - - // Actually apply damage - health -= damage - - // Update check time. - last_beamchecks["\ref[B]"]=world.time - -// Apply connect damage -/obj/machinery/portable_atmospherics/canister/beam_connect(var/obj/effect/beam/B) - ..() - last_beamchecks["\ref[B]"]=world.time - -/obj/machinery/portable_atmospherics/canister/beam_disconnect(var/obj/effect/beam/B) - ..() - apply_beam_damage(B) - last_beamchecks.Remove("\ref[B]") // RIP - -/obj/machinery/portable_atmospherics/canister/handle_beams() - // New beam damage code (per-tick) - for(var/obj/effect/beam/B in beams) - apply_beam_damage(B) - healthcheck() - -#undef OVERLAY_HOLDING -#undef OVERLAY_CONNECTED -#undef OVERLAY_NO_PRESSURE -#undef OVERLAY_LOW_PRESSURE -#undef OVERLAY_MEDIUM_PRESSURE -#undef OVERLAY_HIGH_PRESSURE +#define OVERLAY_HOLDING 1 +#define OVERLAY_CONNECTED 2 +#define OVERLAY_NO_PRESSURE 4 +#define OVERLAY_LOW_PRESSURE 8 +#define OVERLAY_MEDIUM_PRESSURE 16 +#define OVERLAY_HIGH_PRESSURE 32 + +/obj/machinery/portable_atmospherics/canister + name = "canister" + icon = 'icons/obj/atmos.dmi' + icon_state = "yellow" + density = 1 + var/health = 100.0 + flags = FPRINT + siemens_coefficient = 1 + + var/valve_open = 0 + var/release_pressure = ONE_ATMOSPHERE + + var/canister_color = "yellow" + var/old_color = 0 + var/can_label = 1 + var/filled = 0.5 // Mapping var: Set to 0 for empty, 1 to full, anywhere between. + pressure_resistance = 7*ONE_ATMOSPHERE + var/temperature_resistance = 1000 + T0C + volume = 1000 + use_power = 0 + var/release_log = "" + var/busy = 0 + starting_materials = list(MAT_IRON = 10*CC_PER_SHEET_METAL) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + + //Icon Update Code + var/global/status_overlays = 0 + var/global/list/status_overlays_pressure + var/global/list/status_overlays_other + var/overlay_status = 0 + + var/log="" // Bad boys, bad boys. + +/obj/machinery/portable_atmospherics/canister/New() + ..() + old_color = canister_color + +/obj/machinery/portable_atmospherics/canister/sleeping_agent + name = "Canister: \[N2O\]" + icon_state = "redws" + canister_color = "redws" + can_label = 0 + +/obj/machinery/portable_atmospherics/canister/nitrogen + name = "Canister: \[N2\]" + icon_state = "red" + canister_color = "red" + can_label = 0 + +/obj/machinery/portable_atmospherics/canister/oxygen + name = "Canister: \[O2\]" + icon_state = "blue" + canister_color = "blue" + can_label = 0 + +/obj/machinery/portable_atmospherics/canister/plasma + name = "Canister \[Plasma\]" + icon_state = "orange" + canister_color = "orange" + can_label = 0 + +/obj/machinery/portable_atmospherics/canister/carbon_dioxide + name = "Canister \[CO2\]" + icon_state = "black" + canister_color = "black" + can_label = 0 + +/obj/machinery/portable_atmospherics/canister/air + name = "Canister \[Air\]" + icon_state = "grey" + canister_color = "grey" + can_label = 0 + +/obj/machinery/portable_atmospherics/canister/update_icon() + if(destroyed) + icon_state = "[canister_color]-1" + overlays.len = 0 + return + + if(!status_overlays) + status_overlays = 1 + + status_overlays_pressure = new + status_overlays_other = new + + status_overlays_pressure.len = 4 + status_overlays_other.len = 2 + + status_overlays_pressure[1] = image(icon, "can-o0") + status_overlays_pressure[2] = image(icon, "can-o1") + status_overlays_pressure[3] = image(icon, "can-o2") + status_overlays_pressure[4] = image(icon, "can-o3") + + status_overlays_other[1] = image(icon, "can-open") + status_overlays_other[2] = image(icon, "can-connector") + + if (canister_color != old_color) + icon_state = "[canister_color]" + old_color = canister_color + + var/tank_pressure = air_contents.return_pressure() + if(check_updates(tank_pressure)) + if(overlays.len) + overlays = 0 + + overlay_status = 0 + + if (holding) + overlays += status_overlays_other[1] + overlay_status |= OVERLAY_HOLDING + + if (connected_port) + overlays += status_overlays_other[2] + overlay_status |= OVERLAY_CONNECTED + + switch(tank_pressure) + if(15 * ONE_ATMOSPHERE to INFINITY) + overlays += status_overlays_pressure[4] + overlay_status |= OVERLAY_HIGH_PRESSURE + if(ONE_ATMOSPHERE to 15 * ONE_ATMOSPHERE) + overlays += status_overlays_pressure[3] + overlay_status |= OVERLAY_MEDIUM_PRESSURE + if(10 to ONE_ATMOSPHERE) + overlays += status_overlays_pressure[2] + overlay_status |= OVERLAY_LOW_PRESSURE + else + overlays += status_overlays_pressure[1] + overlay_status |= OVERLAY_NO_PRESSURE + return + +/obj/machinery/portable_atmospherics/canister/proc/check_updates(tank_pressure = 0) + if((overlay_status & OVERLAY_HOLDING) != holding) + return 1 + if((overlay_status & OVERLAY_CONNECTED) != connected_port) + return 1 + if((overlay_status & OVERLAY_HIGH_PRESSURE) && tank_pressure < 15*ONE_ATMOSPHERE) + return 1 + if((overlay_status & OVERLAY_MEDIUM_PRESSURE) && (tank_pressure < ONE_ATMOSPHERE || tank_pressure > 15*ONE_ATMOSPHERE)) + return 1 + if((overlay_status & OVERLAY_LOW_PRESSURE) && (tank_pressure < 10 || tank_pressure > ONE_ATMOSPHERE)) + return 1 + if((overlay_status & OVERLAY_NO_PRESSURE) && tank_pressure > 10) + return 1 + return 0 + + +/obj/machinery/portable_atmospherics/canister/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > temperature_resistance) + health -= 5 + healthcheck() + +/obj/machinery/portable_atmospherics/canister/proc/healthcheck() + if(destroyed) + return 1 + + if (src.health <= 10) + var/atom/location = src.loc + location.assume_air(air_contents) + + src.destroyed = 1 + playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3) + src.density = 0 + update_icon() + investigation_log(I_ATMOS, "was destoyed by excessive damage.") + + if (src.holding) + src.holding.loc = src.loc + src.holding = null + INVOKE_EVENT(on_destroyed, list()) + nanomanager.update_uis(src) + return 1 + else + return 1 + +/obj/machinery/portable_atmospherics/canister/process() + if (destroyed) + return + + ..() + + handle_beams() //emitter beams + + if(valve_open) + var/datum/gas_mixture/environment + if(holding) + environment = holding.air_contents + else + environment = loc.return_air() + + var/env_pressure = environment.return_pressure() + var/pressure_delta = min(release_pressure - env_pressure, (air_contents.return_pressure() - env_pressure)/2) + //Can not have a pressure delta that would cause environment pressure > tank pressure + + var/transfer_moles = 0 + if((air_contents.temperature > 0) && (pressure_delta > 0)) + transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) + + if(holding) + environment.merge(removed) + else + loc.assume_air(removed) + src.update_icon() + nanomanager.update_uis(src) + + if(air_contents.return_pressure() < 1) + can_label = 1 + else + can_label = 0 + + if(air_contents.temperature > PLASMA_FLASHPOINT) + air_contents.zburn() + nanomanager.update_uis(src) + + return + +/obj/machinery/portable_atmospherics/canister/return_air() + return air_contents + +/obj/machinery/portable_atmospherics/canister/proc/return_temperature() + var/datum/gas_mixture/GM = src.return_air() + if(GM && GM.volume>0) + return GM.temperature + return 0 + +/obj/machinery/portable_atmospherics/canister/proc/return_pressure() + var/datum/gas_mixture/GM = src.return_air() + if(GM && GM.volume>0) + return GM.return_pressure() + return 0 + +/obj/machinery/portable_atmospherics/canister/blob_act() + src.health -= 200 + healthcheck() + return + +/obj/machinery/portable_atmospherics/canister/bullet_act(var/obj/item/projectile/Proj) + if(Proj.damage) + src.health -= round(Proj.damage / 2) + healthcheck() + ..() + +/obj/machinery/portable_atmospherics/canister/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(iswelder(W) && src.destroyed) + if(weld(W, user)) + to_chat(user, "You salvage what's left of \the [src].") + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src))//new /obj/item/stack/sheet/metal(src.loc) + M.amount = 3 + qdel (src) + return + + if(!istype(W, /obj/item/weapon/wrench) && !istype(W, /obj/item/weapon/tank) && !istype(W, /obj/item/device/analyzer) && !istype(W, /obj/item/device/pda)) + visible_message("[user] hits the [src] with a [W]!") + investigation_log(I_ATMOS, "was smacked with \a [W] by [key_name(user)]") + src.health -= W.force + src.add_fingerprint(user) + healthcheck() + + if(istype(user, /mob/living/silicon/robot) && istype(W, /obj/item/weapon/tank/jetpack)) + var/datum/gas_mixture/thejetpack = W:air_contents + var/env_pressure = thejetpack.return_pressure() + var/pressure_delta = min(10*ONE_ATMOSPHERE - env_pressure, (air_contents.return_pressure() - env_pressure)/2) + //Can not have a pressure delta that would cause environment pressure > tank pressure + var/transfer_moles = 0 + if((air_contents.temperature > 0) && (pressure_delta > 0)) + transfer_moles = pressure_delta*thejetpack.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)//Actually transfer the gas + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) + thejetpack.merge(removed) + to_chat(user, "You pulse-pressurize your jetpack from the tank.") + return + + ..() + + nanomanager.update_uis(src) // Update all NanoUIs attached to src + + + +/obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/canister/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) + return src.ui_interact(user) + +/obj/machinery/portable_atmospherics/canister/attack_alien(var/mob/living/carbon/alien/user as mob) + src.add_hiddenprint(user) + health -= rand(15, 30) + user.visible_message("\The [user] slashes away at \the [src]!", \ + "You slash away at \the [src]!") + user.delayNextAttack(10) //Hold on there amigo + investigation_log(I_ATMOS, "was slashed at by alien [key_name(user)]") + playsound(get_turf(src), 'sound/weapons/slice.ogg', 25, 1, -1) + healthcheck() + +/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + if (src.destroyed || gcDestroyed || !get_turf(src)) + if(!ui) + ui = nanomanager.get_open_ui(user, src, ui_key) + if(ui) ui.close() + return + + // this is the data which will be sent to the ui + var/data[0] + data["name"] = name + data["canLabel"] = can_label ? 1 : 0 + data["portConnected"] = connected_port ? 1 : 0 + data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0)//This used to be redundant, made it into a fix for -1 kPA showing up in the UI + data["releasePressure"] = round(release_pressure) + data["minReleasePressure"] = round(ONE_ATMOSPHERE/10) + data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE) + data["valveOpen"] = valve_open ? 1 : 0 + + data["hasHoldingTank"] = holding ? 1 : 0 + if (holding) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "canister.tmpl", "Canister", 480, 400) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + //ui.set_auto_update(1) + +/obj/machinery/portable_atmospherics/canister/Topic(href, href_list) + . = ..()//Sanity + if(.) + return . + + if(href_list["toggle"]) + var/datum/gas/sleeping_agent/S = locate() in src.air_contents.trace_gases + + if (valve_open) + if (holding) + investigation_log(I_ATMOS, "had its valve closed by [key_name(usr)], stopping transfer into \the [holding].") + else + investigation_log(I_ATMOS, "had its valve closed by [key_name(usr)], stopping transfer into the air") + else + if (holding) + investigation_log(I_ATMOS, "had its valve OPENED by [key_name(usr)], starting transfer into \the [holding]") + else + var/list/contents_l=list() + if(src.air_contents.toxins > 0) + contents_l += "Plasma" + if(src.air_contents.carbon_dioxide > 0) + contents_l += "CO2" + if(istype(S)) + contents_l += "N2O
      " + var/contents_str = english_list(contents_l) + investigation_log(I_ATMOS, "had its valve OPENED by [key_name(usr)], starting transfer into the air ([contents_str])") + if(contents_l.len>0) + message_admins("[usr.real_name] ([formatPlayerPanel(usr,usr.ckey)]) opened a canister that contains [contents_str] at [formatJumpTo(loc)]!") + log_admin("[usr]([ckey(usr.key)]) opened a canister that contains [contents] at [loc.x], [loc.y], [loc.z]") + + valve_open = !valve_open + + if (href_list["remove_tank"]) + var/datum/gas/sleeping_agent/S = locate() in src.air_contents.trace_gases + if(holding) + if(valve_open) + if(src.air_contents.toxins > 0 || (istype(S))) + message_admins("[usr.real_name] ([formatPlayerPanel(usr,usr.ckey)]) opened a canister that contains \[[src.air_contents.toxins > 0 ? "Toxins" : ""] [istype(S) ? " N2O" : ""]\] at [formatJumpTo(loc)]!") + log_admin("[usr]([ckey(usr.key)]) opened a canister that contains \[[src.air_contents.toxins > 0 ? "Toxins" : ""] [istype(S) ? " N2O" : ""]\] at [loc.x], [loc.y], [loc.z]") + + if(istype(holding, /obj/item/weapon/tank)) + holding.manipulated_by = usr.real_name + holding.loc = loc + holding = null + + if (href_list["pressure_adj"]) + var/diff = text2num(href_list["pressure_adj"]) + if(diff > 0) + release_pressure = min(10*ONE_ATMOSPHERE, release_pressure+diff) + else + release_pressure = max(ONE_ATMOSPHERE/10, release_pressure+diff) + + if (href_list["relabel"]) + if (can_label) + var/list/colors = list(\ + "\[N2O\]" = "redws", \ + "\[N2\]" = "red", \ + "\[O2\]" = "blue", \ + "\[Plasma\]" = "orange", \ + "\[CO2\]" = "black", \ + "\[Air\]" = "grey", \ + "\[CAUTION\]" = "yellow", \ + ) + var/label = input("Choose canister label", "Gas canister") as null|anything in colors + if (label) + src.canister_color = colors[label] + src.icon_state = colors[label] + src.name = "Canister: [label]" + + src.add_fingerprint(usr) + src.add_hiddenprint(usr) + update_icon() + + return 1 + +/obj/machinery/portable_atmospherics/canister/plasma/New(loc) + ..(loc) + air_contents.adjust(tx = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) + update_icon() + +/obj/machinery/portable_atmospherics/canister/oxygen/New(loc) + ..(loc) + src.air_contents.adjust((maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) + update_icon() + +/obj/machinery/portable_atmospherics/canister/sleeping_agent/New(loc) + ..(loc) + var/datum/gas/sleeping_agent/sleeping_agent = new + sleeping_agent.moles = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) + air_contents.adjust(traces = list(sleeping_agent)) + update_icon() + +/* +//Dirty way to fill room with gas. However it is a bit easier to do than creating some floor/engine/n2o -rastaf0 +/obj/machinery/portable_atmospherics/canister/sleeping_agent/roomfiller/New() + ..() + var/datum/gas/sleeping_agent/trace_gas = air_contents.trace_gases[1] + trace_gas.moles = 9*4000 + spawn(10) + var/turf/simulated/location = src.loc + if (istype(src.loc)) + while (!location.air) + sleep(10) + location.assume_air(air_contents) + air_contents = new + return 1 +*/ + +/obj/machinery/portable_atmospherics/canister/nitrogen/New(loc) + ..(loc) + air_contents.adjust(n2 = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) + update_icon() + +/obj/machinery/portable_atmospherics/canister/carbon_dioxide/New(loc) + ..(loc) + air_contents.adjust(co2 = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)) + update_icon() + +/obj/machinery/portable_atmospherics/canister/air/New(loc) + ..(loc) + + air_contents.adjust(\ + (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature),\ + n2 = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)\ + ) + + update_icon() + +/obj/machinery/portable_atmospherics/canister/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/user) + + + if(busy) + return 0 + if(!WT.isOn()) + return 0 + + // Do after stuff here + to_chat(user, "You start to slice away at \the [src]...") + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + WT.eyecheck(user) + busy = 1 + if(do_after(user, src, 50)) + busy = 0 + if(!WT.isOn()) + return 0 + return 1 + busy = 0 + return 0 + +/obj/machinery/portable_atmospherics/canister/apply_beam_damage(var/obj/effect/beam/B) + var/lastcheck=last_beamchecks["\ref[B]"] + + var/damage = ((world.time - lastcheck)/10) * (B.get_damage()/2) + + // Actually apply damage + health -= damage + + // Update check time. + last_beamchecks["\ref[B]"]=world.time + +// Apply connect damage +/obj/machinery/portable_atmospherics/canister/beam_connect(var/obj/effect/beam/B) + ..() + last_beamchecks["\ref[B]"]=world.time + +/obj/machinery/portable_atmospherics/canister/beam_disconnect(var/obj/effect/beam/B) + ..() + apply_beam_damage(B) + last_beamchecks.Remove("\ref[B]") // RIP + +/obj/machinery/portable_atmospherics/canister/handle_beams() + // New beam damage code (per-tick) + for(var/obj/effect/beam/B in beams) + apply_beam_damage(B) + healthcheck() + +#undef OVERLAY_HOLDING +#undef OVERLAY_CONNECTED +#undef OVERLAY_NO_PRESSURE +#undef OVERLAY_LOW_PRESSURE +#undef OVERLAY_MEDIUM_PRESSURE +#undef OVERLAY_HIGH_PRESSURE diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index 39b5eb4453c..e6ceb065f89 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -1,177 +1,177 @@ -/obj/machinery/meter - name = "meter" - desc = "A gas flow meter." - icon = 'icons/obj/meter.dmi' - icon_state = "meterX" - var/obj/machinery/atmospherics/pipe/target = null - var/target_layer = PIPING_LAYER_DEFAULT - anchored = 1.0 - power_channel = ENVIRON - var/frequency = 0 - var/id_tag - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - machine_flags = MULTITOOL_MENU - -/obj/machinery/meter/New(newloc, new_target) - ..(newloc) - src.target = new_target - if(target) - setAttachLayer(target.piping_layer) - return 1 - -/obj/machinery/meter/initialize() - if (!target) - for(var/obj/machinery/atmospherics/pipe/pipe in src.loc) - if(pipe.piping_layer == target_layer) - target = pipe - break - if(target) - setAttachLayer(target.piping_layer) - -/obj/machinery/meter/proc/setAttachLayer(var/new_layer) - target_layer = new_layer - src.pixel_x = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X - src.pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y - -/obj/machinery/meter/process() - if(!target) - icon_state = "meterX" - // Pop the meter off when the pipe we're attached to croaks. - new /obj/item/pipe_meter(src.loc) - spawn(0) qdel(src) - return PROCESS_KILL - - if(stat & (BROKEN|NOPOWER)) - icon_state = "meter0" - return 0 - - use_power(5) - - var/datum/gas_mixture/environment = target.return_air() - if(!environment) - icon_state = "meterX" - // Pop the meter off when the environment we're attached to croaks. - new /obj/item/pipe_meter(src.loc) - spawn(0) qdel(src) - return PROCESS_KILL - - var/env_pressure = environment.return_pressure() - if(env_pressure <= 0.15*ONE_ATMOSPHERE) - icon_state = "meter0" - else if(env_pressure <= 1.8*ONE_ATMOSPHERE) - var/val = round(env_pressure/(ONE_ATMOSPHERE*0.3) + 0.5) - icon_state = "meter1_[val]" - else if(env_pressure <= 30*ONE_ATMOSPHERE) - var/val = round(env_pressure/(ONE_ATMOSPHERE*5)-0.35) + 1 - icon_state = "meter2_[val]" - else if(env_pressure <= 59*ONE_ATMOSPHERE) - var/val = round(env_pressure/(ONE_ATMOSPHERE*5) - 6) + 1 - icon_state = "meter3_[val]" - else - icon_state = "meter4" - - if(frequency) - var/datum/radio_frequency/radio_connection = radio_controller.return_frequency(frequency) - - if(!radio_connection) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - signal.data = list( - "tag" = id_tag, - "device" = "AM", - "pressure" = round(env_pressure), - "temperature" = round(environment.temperature), - "sigtype" = "status" - ) - - var/total_moles = environment.total_moles() - if(total_moles > 0) - signal.data["oxygen"] = round(100*environment.oxygen/total_moles,0.1) - signal.data["toxins"] = round(100*environment.toxins/total_moles,0.1) - signal.data["nitrogen"] = round(100*environment.nitrogen/total_moles,0.1) - signal.data["carbon_dioxide"] = round(100*environment.carbon_dioxide/total_moles,0.1) - else - signal.data["oxygen"] = 0 - signal.data["toxins"] = 0 - signal.data["nitrogen"] = 0 - signal.data["carbon_dioxide"] = 0 - - radio_connection.post_signal(src, signal) - -/obj/machinery/meter/proc/status() - var/t = "" - if (src.target) - var/datum/gas_mixture/environment = target.return_air() - if(environment) - t += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]°C)" - else - t += "The sensor error light is blinking." - else - t += "The connect error light is blinking." - return t - -/obj/machinery/meter/examine(mob/user) - ..() - attack_hand(user) - -/obj/machinery/meter/attack_ai(var/mob/user) - attack_hand(user) - -/obj/machinery/meter/attack_ghost(var/mob/user) - attack_hand(user) - -// Why the FUCK was this Click()? -/obj/machinery/meter/attack_hand(var/mob/user) - if(stat & (NOPOWER|BROKEN)) - return 1 - - var/t = null - if (get_dist(usr, src) <= 3 || istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/dead)) - t += status() - else +/obj/machinery/meter + name = "meter" + desc = "A gas flow meter." + icon = 'icons/obj/meter.dmi' + icon_state = "meterX" + var/obj/machinery/atmospherics/pipe/target = null + var/target_layer = PIPING_LAYER_DEFAULT + anchored = 1.0 + power_channel = ENVIRON + var/frequency = 0 + var/id_tag + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + machine_flags = MULTITOOL_MENU + +/obj/machinery/meter/New(newloc, new_target) + ..(newloc) + src.target = new_target + if(target) + setAttachLayer(target.piping_layer) + return 1 + +/obj/machinery/meter/initialize() + if (!target) + for(var/obj/machinery/atmospherics/pipe/pipe in src.loc) + if(pipe.piping_layer == target_layer) + target = pipe + break + if(target) + setAttachLayer(target.piping_layer) + +/obj/machinery/meter/proc/setAttachLayer(var/new_layer) + target_layer = new_layer + src.pixel_x = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X + src.pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y + +/obj/machinery/meter/process() + if(!target) + icon_state = "meterX" + // Pop the meter off when the pipe we're attached to croaks. + new /obj/item/pipe_meter(src.loc) + spawn(0) qdel(src) + return PROCESS_KILL + + if(stat & (BROKEN|NOPOWER)) + icon_state = "meter0" + return 0 + + use_power(5) + + var/datum/gas_mixture/environment = target.return_air() + if(!environment) + icon_state = "meterX" + // Pop the meter off when the environment we're attached to croaks. + new /obj/item/pipe_meter(src.loc) + spawn(0) qdel(src) + return PROCESS_KILL + + var/env_pressure = environment.return_pressure() + if(env_pressure <= 0.15*ONE_ATMOSPHERE) + icon_state = "meter0" + else if(env_pressure <= 1.8*ONE_ATMOSPHERE) + var/val = round(env_pressure/(ONE_ATMOSPHERE*0.3) + 0.5) + icon_state = "meter1_[val]" + else if(env_pressure <= 30*ONE_ATMOSPHERE) + var/val = round(env_pressure/(ONE_ATMOSPHERE*5)-0.35) + 1 + icon_state = "meter2_[val]" + else if(env_pressure <= 59*ONE_ATMOSPHERE) + var/val = round(env_pressure/(ONE_ATMOSPHERE*5) - 6) + 1 + icon_state = "meter3_[val]" + else + icon_state = "meter4" + + if(frequency) + var/datum/radio_frequency/radio_connection = radio_controller.return_frequency(frequency) + + if(!radio_connection) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + signal.data = list( + "tag" = id_tag, + "device" = "AM", + "pressure" = round(env_pressure), + "temperature" = round(environment.temperature), + "sigtype" = "status" + ) + + var/total_moles = environment.total_moles() + if(total_moles > 0) + signal.data["oxygen"] = round(100*environment.oxygen/total_moles,0.1) + signal.data["toxins"] = round(100*environment.toxins/total_moles,0.1) + signal.data["nitrogen"] = round(100*environment.nitrogen/total_moles,0.1) + signal.data["carbon_dioxide"] = round(100*environment.carbon_dioxide/total_moles,0.1) + else + signal.data["oxygen"] = 0 + signal.data["toxins"] = 0 + signal.data["nitrogen"] = 0 + signal.data["carbon_dioxide"] = 0 + + radio_connection.post_signal(src, signal) + +/obj/machinery/meter/proc/status() + var/t = "" + if (src.target) + var/datum/gas_mixture/environment = target.return_air() + if(environment) + t += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]°C)" + else + t += "The sensor error light is blinking." + else + t += "The connect error light is blinking." + return t + +/obj/machinery/meter/examine(mob/user) + ..() + attack_hand(user) + +/obj/machinery/meter/attack_ai(var/mob/user) + attack_hand(user) + +/obj/machinery/meter/attack_ghost(var/mob/user) + attack_hand(user) + +// Why the FUCK was this Click()? +/obj/machinery/meter/attack_hand(var/mob/user) + if(stat & (NOPOWER|BROKEN)) + return 1 + + var/t = null + if (get_dist(usr, src) <= 3 || istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/dead)) + t += status() + else to_chat(usr, "You are too far away.") - return 1 - + return 1 + to_chat(usr, t) - return 1 - -/obj/machinery/meter/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) - return {" - Main - "} - -/obj/machinery/meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if (!istype(W, /obj/item/weapon/wrench)) - return ..() - - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + return 1 + +/obj/machinery/meter/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) + return {" + Main + "} + +/obj/machinery/meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if (!istype(W, /obj/item/weapon/wrench)) + return ..() + + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You begin to unfasten \the [src]...") - if (do_after(user, src, 40)) - user.visible_message( \ - "[user] unfastens \the [src].
      ", \ - "You have unfastened \the [src].", \ - "You hear ratchet.") - new /obj/item/pipe_meter(src.loc) - qdel(src) - -// TURF METER - REPORTS A TILE'S AIR CONTENTS - -/obj/machinery/meter/turf/New() - ..() - src.target = loc - return 1 - - -/obj/machinery/meter/turf/initialize() - if (!target) - src.target = loc - -/obj/machinery/meter/turf/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if (do_after(user, src, 40)) + user.visible_message( \ + "[user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear ratchet.") + new /obj/item/pipe_meter(src.loc) + qdel(src) + +// TURF METER - REPORTS A TILE'S AIR CONTENTS + +/obj/machinery/meter/turf/New() + ..() + src.target = loc + return 1 + + +/obj/machinery/meter/turf/initialize() + if (!target) + src.target = loc + +/obj/machinery/meter/turf/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) return \ No newline at end of file diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index ca5ef8c8388..5657747a70c 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -1,134 +1,134 @@ -/obj/machinery/portable_atmospherics - name = "atmoalter" - use_power = 0 - var/datum/gas_mixture/air_contents = new - - var/obj/machinery/atmospherics/unary/portables_connector/connected_port - var/obj/item/weapon/tank/holding - - var/volume = 0 - var/destroyed = 0 - - var/maximum_pressure = 90*ONE_ATMOSPHERE - -/obj/machinery/portable_atmospherics/New() - ..() - air_contents.volume = volume - air_contents.temperature = T20C - - return 1 - -/obj/machinery/portable_atmospherics/initialize() - . = ..() - spawn() - var/obj/machinery/atmospherics/unary/portables_connector/port = locate() in loc - if(port) - connect(port) - update_icon() - -/obj/machinery/portable_atmospherics/process() - if(!connected_port) //only react when pipe_network will not it do it for you - //Allow for reactions - air_contents.react() - else - update_icon() - -/obj/machinery/portable_atmospherics/Destroy() - qdel(air_contents) - air_contents = null - ..() - -/obj/machinery/portable_atmospherics/update_icon() - return null - -/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port) - //Make sure not already connected to something else - if(connected_port || !new_port || new_port.connected_device) - return 0 - - //Make sure are close enough for a valid connection - if(new_port.loc != loc) - return 0 - - //Perform the connection - connected_port = new_port - connected_port.connected_device = src - - anchored = 1 //Prevent movement - - //Actually enforce the air sharing - var/datum/pipe_network/network = connected_port.return_network(src) - if(network && !network.gases.Find(air_contents)) - network.gases += air_contents - network.update = 1 - - return 1 - -/obj/machinery/portable_atmospherics/proc/disconnect() - if(!connected_port) - return 0 - - var/datum/pipe_network/network = connected_port.return_network(src) - if(network) - network.gases -= air_contents - - anchored = 0 - - connected_port.connected_device = null - connected_port = null - - return 1 - -/obj/machinery/portable_atmospherics/proc/eject_holding() - holding.forceMove(loc) - holding = null - -/obj/machinery/portable_atmospherics/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - - var/obj/icon = src - if ((istype(W, /obj/item/weapon/tank) && !( src.destroyed ))) - if (src.holding) - return 0 - var/obj/item/weapon/tank/T = W - if(user.drop_item(T, src)) - src.holding = T - update_icon() - return 1 - - else if (istype(W, /obj/item/weapon/wrench)) - if(connected_port) - disconnect() +/obj/machinery/portable_atmospherics + name = "atmoalter" + use_power = 0 + var/datum/gas_mixture/air_contents = new + + var/obj/machinery/atmospherics/unary/portables_connector/connected_port + var/obj/item/weapon/tank/holding + + var/volume = 0 + var/destroyed = 0 + + var/maximum_pressure = 90*ONE_ATMOSPHERE + +/obj/machinery/portable_atmospherics/New() + ..() + air_contents.volume = volume + air_contents.temperature = T20C + + return 1 + +/obj/machinery/portable_atmospherics/initialize() + . = ..() + spawn() + var/obj/machinery/atmospherics/unary/portables_connector/port = locate() in loc + if(port) + connect(port) + update_icon() + +/obj/machinery/portable_atmospherics/process() + if(!connected_port) //only react when pipe_network will not it do it for you + //Allow for reactions + air_contents.react() + else + update_icon() + +/obj/machinery/portable_atmospherics/Destroy() + qdel(air_contents) + air_contents = null + ..() + +/obj/machinery/portable_atmospherics/update_icon() + return null + +/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port) + //Make sure not already connected to something else + if(connected_port || !new_port || new_port.connected_device) + return 0 + + //Make sure are close enough for a valid connection + if(new_port.loc != loc) + return 0 + + //Perform the connection + connected_port = new_port + connected_port.connected_device = src + + anchored = 1 //Prevent movement + + //Actually enforce the air sharing + var/datum/pipe_network/network = connected_port.return_network(src) + if(network && !network.gases.Find(air_contents)) + network.gases += air_contents + network.update = 1 + + return 1 + +/obj/machinery/portable_atmospherics/proc/disconnect() + if(!connected_port) + return 0 + + var/datum/pipe_network/network = connected_port.return_network(src) + if(network) + network.gases -= air_contents + + anchored = 0 + + connected_port.connected_device = null + connected_port = null + + return 1 + +/obj/machinery/portable_atmospherics/proc/eject_holding() + holding.forceMove(loc) + holding = null + +/obj/machinery/portable_atmospherics/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + + var/obj/icon = src + if ((istype(W, /obj/item/weapon/tank) && !( src.destroyed ))) + if (src.holding) + return 0 + var/obj/item/weapon/tank/T = W + if(user.drop_item(T, src)) + src.holding = T + update_icon() + return 1 + + else if (istype(W, /obj/item/weapon/wrench)) + if(connected_port) + disconnect() to_chat(user, "You disconnect [name] from the port.") - update_icon() - pixel_x = 0 - pixel_y = 0 - return 1 - else - var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc - if(possible_port) - if(connect(possible_port)) + update_icon() + pixel_x = 0 + pixel_y = 0 + return 1 + else + var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc + if(possible_port) + if(connect(possible_port)) to_chat(user, "You connect [name] to the port.") - var/datum/gas/sleeping_agent/S = locate() in src.air_contents.trace_gases - if(src.air_contents.toxins > 0 || (istype(S))) - log_admin("[usr]([ckey(usr.key)]) connected a canister that contains \[[src.air_contents.toxins > 0 ? "Toxins" : ""] [istype(S) ? " N2O" : ""]\] to a connector_port at [loc.x], [loc.y], [loc.z]") - update_icon() - pixel_x = possible_port.pixel_x - pixel_y = possible_port.pixel_y - return 1 - else + var/datum/gas/sleeping_agent/S = locate() in src.air_contents.trace_gases + if(src.air_contents.toxins > 0 || (istype(S))) + log_admin("[usr]([ckey(usr.key)]) connected a canister that contains \[[src.air_contents.toxins > 0 ? "Toxins" : ""] [istype(S) ? " N2O" : ""]\] to a connector_port at [loc.x], [loc.y], [loc.z]") + update_icon() + pixel_x = possible_port.pixel_x + pixel_y = possible_port.pixel_y + return 1 + else to_chat(user, "[name] failed to connect to the port.") - return 0 - else - if(..()) return 1 //Give a chance for the wrench flag if it is wrenchable, it's not snowflake if I say it isn't ya hear! + return 0 + else + if(..()) return 1 //Give a chance for the wrench flag if it is wrenchable, it's not snowflake if I say it isn't ya hear! to_chat(user, "Nothing happens.") - return 0 - if(..()) //Let the other machine flags have a shot - return 1 - - else if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1) - user.visible_message("[user] has used [W] on \icon[icon] [src]", "You use \the [W] on \icon[icon] [src]") - var/obj/item/device/analyzer/analyzer = W - user.show_message(analyzer.output_gas_scan(src.air_contents, src, 0), 1) - src.add_fingerprint(user) - return - return + return 0 + if(..()) //Let the other machine flags have a shot + return 1 + + else if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1) + user.visible_message("[user] has used [W] on \icon[icon] [src]", "You use \the [W] on \icon[icon] [src]") + var/obj/item/device/analyzer/analyzer = W + user.show_message(analyzer.output_gas_scan(src.air_contents, src, 0), 1) + src.add_fingerprint(user) + return + return diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index 8306c159d74..802ddd4de1e 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -1,164 +1,164 @@ -/obj/machinery/portable_atmospherics/pump - name = "Portable Air Pump" - - icon = 'icons/obj/atmos.dmi' - icon_state = "psiphon:0" - density = 1 - - var/on = 0 - var/direction_out = 0 //0 = siphoning, 1 = releasing - var/target_pressure = 100 - - var/pressuremax = 10 * ONE_ATMOSPHERE - var/pressuremin = 0 - - volume = 1000 - -/obj/machinery/portable_atmospherics/pump/update_icon() - src.overlays = 0 - - if(on) - icon_state = "psiphon:1" - else - icon_state = "psiphon:0" - - if(holding) - overlays += "siphon-open" - - if(connected_port) - overlays += "siphon-connector" - - return - -/obj/machinery/portable_atmospherics/pump/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - - if(prob(50/severity)) - on = !on - - if(prob(100/severity)) - direction_out = !direction_out - - target_pressure = rand(0,1300) - update_icon() - nanomanager.update_uis(src) - - ..(severity) - -/obj/machinery/portable_atmospherics/pump/process() - ..() - if(on) - var/datum/gas_mixture/environment - if(holding) - environment = holding.air_contents - else - environment = loc.return_air() - if(direction_out) - var/pressure_delta = target_pressure - environment.return_pressure() - //Can not have a pressure delta that would cause environment pressure > tank pressure - - var/transfer_moles = 0 - if(air_contents.temperature > 0) - transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) - - if(holding) - environment.merge(removed) - else - loc.assume_air(removed) - else - var/pressure_delta = target_pressure - air_contents.return_pressure() - //Can not have a pressure delta that would cause environment pressure > tank pressure - - var/transfer_moles = 0 - if(environment.temperature > 0) - transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed - if(holding) - removed = environment.remove(transfer_moles) - else - removed = loc.remove_air(transfer_moles) - - air_contents.merge(removed) - //src.update_icon() - nanomanager.update_uis(src) - - //src.updateDialog() - return - -/obj/machinery/portable_atmospherics/pump/return_air() - return air_contents - -/obj/machinery/portable_atmospherics/pump/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/portable_atmospherics/pump/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/portable_atmospherics/pump/attack_hand(var/mob/user as mob) - ui_interact(user) - -/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - var/list/data[0] - data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) - data["targetpressure"] = round(target_pressure) - data["pump_dir"] = direction_out - data["minpressure"] = round(pressuremin) - data["maxpressure"] = round(pressuremax) - data["on"] = on ? 1 : 0 - - data["hasHoldingTank"] = holding ? 1 : 0 - if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "portpump.tmpl", "Portable Pump", 480, 400) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - //ui.set_auto_update(1) - -/obj/machinery/portable_atmospherics/pump/Topic(href, href_list) - . = ..() - if(.) - return . - - if(href_list["power"]) - on = !on - update_icon() - - if(href_list["direction"]) - direction_out = !direction_out - - if (href_list["remove_tank"]) - if(holding) - eject_holding() - update_icon() - - if (href_list["pressure_adj"]) - var/diff = text2num(href_list["pressure_adj"]) - target_pressure = Clamp(target_pressure+diff, pressuremin, pressuremax) - update_icon() - - src.add_fingerprint(usr) - return 1 - -/obj/machinery/portable_atmospherics/pump/AltClick() - if(usr.canmove && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && usr.dexterity_check()) - eject_holding() - return - return ..() +/obj/machinery/portable_atmospherics/pump + name = "Portable Air Pump" + + icon = 'icons/obj/atmos.dmi' + icon_state = "psiphon:0" + density = 1 + + var/on = 0 + var/direction_out = 0 //0 = siphoning, 1 = releasing + var/target_pressure = 100 + + var/pressuremax = 10 * ONE_ATMOSPHERE + var/pressuremin = 0 + + volume = 1000 + +/obj/machinery/portable_atmospherics/pump/update_icon() + src.overlays = 0 + + if(on) + icon_state = "psiphon:1" + else + icon_state = "psiphon:0" + + if(holding) + overlays += "siphon-open" + + if(connected_port) + overlays += "siphon-connector" + + return + +/obj/machinery/portable_atmospherics/pump/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + if(prob(50/severity)) + on = !on + + if(prob(100/severity)) + direction_out = !direction_out + + target_pressure = rand(0,1300) + update_icon() + nanomanager.update_uis(src) + + ..(severity) + +/obj/machinery/portable_atmospherics/pump/process() + ..() + if(on) + var/datum/gas_mixture/environment + if(holding) + environment = holding.air_contents + else + environment = loc.return_air() + if(direction_out) + var/pressure_delta = target_pressure - environment.return_pressure() + //Can not have a pressure delta that would cause environment pressure > tank pressure + + var/transfer_moles = 0 + if(air_contents.temperature > 0) + transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) + + if(holding) + environment.merge(removed) + else + loc.assume_air(removed) + else + var/pressure_delta = target_pressure - air_contents.return_pressure() + //Can not have a pressure delta that would cause environment pressure > tank pressure + + var/transfer_moles = 0 + if(environment.temperature > 0) + transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed + if(holding) + removed = environment.remove(transfer_moles) + else + removed = loc.remove_air(transfer_moles) + + air_contents.merge(removed) + //src.update_icon() + nanomanager.update_uis(src) + + //src.updateDialog() + return + +/obj/machinery/portable_atmospherics/pump/return_air() + return air_contents + +/obj/machinery/portable_atmospherics/pump/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/pump/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/pump/attack_hand(var/mob/user as mob) + ui_interact(user) + +/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + var/list/data[0] + data["portConnected"] = connected_port ? 1 : 0 + data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["targetpressure"] = round(target_pressure) + data["pump_dir"] = direction_out + data["minpressure"] = round(pressuremin) + data["maxpressure"] = round(pressuremax) + data["on"] = on ? 1 : 0 + + data["hasHoldingTank"] = holding ? 1 : 0 + if (holding) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "portpump.tmpl", "Portable Pump", 480, 400) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + //ui.set_auto_update(1) + +/obj/machinery/portable_atmospherics/pump/Topic(href, href_list) + . = ..() + if(.) + return . + + if(href_list["power"]) + on = !on + update_icon() + + if(href_list["direction"]) + direction_out = !direction_out + + if (href_list["remove_tank"]) + if(holding) + eject_holding() + update_icon() + + if (href_list["pressure_adj"]) + var/diff = text2num(href_list["pressure_adj"]) + target_pressure = Clamp(target_pressure+diff, pressuremin, pressuremax) + update_icon() + + src.add_fingerprint(usr) + return 1 + +/obj/machinery/portable_atmospherics/pump/AltClick() + if(usr.canmove && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && usr.dexterity_check()) + eject_holding() + return + return ..() diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index b11539c5c75..ea5bd28ef8b 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -1,215 +1,215 @@ -/obj/machinery/portable_atmospherics/scrubber - name = "Portable Air Scrubber" - - icon = 'icons/obj/atmos.dmi' - icon_state = "pscrubber:0" - density = 1 - - var/on = 0 - var/volume_rate = 800 - - volume = 750 - - var/minrate = 0//probably useless, but whatever - var/maxrate = 10 * ONE_ATMOSPHERE - -/obj/machinery/portable_atmospherics/scrubber/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - - if(prob(50/severity)) - on = !on - update_icon() - - nanomanager.update_uis(src) - ..(severity) - -/obj/machinery/portable_atmospherics/scrubber/huge - name = "Huge Air Scrubber" - icon_state = "scrubber:0" - anchored = 1 - volume = 50000 - volume_rate = 5000 - - var/global/gid = 1 - var/id = 0 - New() - ..() - id = gid - gid++ - - name = "[name] (ID [id])" - - attack_hand(var/mob/user as mob) +/obj/machinery/portable_atmospherics/scrubber + name = "Portable Air Scrubber" + + icon = 'icons/obj/atmos.dmi' + icon_state = "pscrubber:0" + density = 1 + + var/on = 0 + var/volume_rate = 800 + + volume = 750 + + var/minrate = 0//probably useless, but whatever + var/maxrate = 10 * ONE_ATMOSPHERE + +/obj/machinery/portable_atmospherics/scrubber/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + if(prob(50/severity)) + on = !on + update_icon() + + nanomanager.update_uis(src) + ..(severity) + +/obj/machinery/portable_atmospherics/scrubber/huge + name = "Huge Air Scrubber" + icon_state = "scrubber:0" + anchored = 1 + volume = 50000 + volume_rate = 5000 + + var/global/gid = 1 + var/id = 0 + New() + ..() + id = gid + gid++ + + name = "[name] (ID [id])" + + attack_hand(var/mob/user as mob) to_chat(usr, "You can't directly interact with this machine. Use the area atmos computer.") - - update_icon() - src.overlays = 0 - - if(on) - icon_state = "scrubber:1" - else - icon_state = "scrubber:0" - - attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - if(on) + + update_icon() + src.overlays = 0 + + if(on) + icon_state = "scrubber:1" + else + icon_state = "scrubber:0" + + attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + if(on) to_chat(user, "Turn it off first!") - return - - anchored = !anchored - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + return + + anchored = !anchored + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") - - return - - ..() - -/obj/machinery/portable_atmospherics/scrubber/huge/stationary - name = "Stationary Air Scrubber" - - attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) + + return + + ..() + +/obj/machinery/portable_atmospherics/scrubber/huge/stationary + name = "Stationary Air Scrubber" + + attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) to_chat(user, "The bolts are too tight for you to unscrew!") - return - - ..() - - -/obj/machinery/portable_atmospherics/scrubber/update_icon() - src.overlays = 0 - - if(on) - icon_state = "pscrubber:1" - else - icon_state = "pscrubber:0" - - if(holding) - overlays += "scrubber-open" - - if(connected_port) - overlays += "scrubber-connector" - - return - -/obj/machinery/portable_atmospherics/scrubber/process() - ..() - - if(on) - var/datum/gas_mixture/environment - if(holding) - environment = holding.air_contents - else - environment = loc.return_air() - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() - - //Take a gas sample - var/datum/gas_mixture/removed - if(holding) - removed = environment.remove(transfer_moles) - else - removed = loc.remove_air(transfer_moles) - - //Filter it - if (removed) - var/datum/gas_mixture/filtered_out = new - - filtered_out.temperature = removed.temperature - - - filtered_out.toxins = removed.toxins - removed.toxins = 0 - - filtered_out.carbon_dioxide = removed.carbon_dioxide - removed.carbon_dioxide = 0 - - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/sleeping_agent)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - - //Remix the resulting gases - air_contents.merge(filtered_out) - - if(holding) - environment.merge(removed) - else - loc.assume_air(removed) - //src.update_icon() - nanomanager.update_uis(src) - //src.updateDialog() - return - -/obj/machinery/portable_atmospherics/scrubber/return_air() - return air_contents - -/obj/machinery/portable_atmospherics/scrubber/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/portable_atmospherics/scrubber/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/portable_atmospherics/scrubber/attack_hand(var/mob/user as mob) - ui_interact(user) - return - -/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - var/list/data[0] - data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) - data["rate"] = round(volume_rate) - data["minrate"] = round(minrate) - data["maxrate"] = round(maxrate) - data["on"] = on ? 1 : 0 - - data["hasHoldingTank"] = holding ? 1 : 0 - if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "portscrubber.tmpl", "Portable Scrubber", 480, 400) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - //ui.set_auto_update(1) - -/obj/machinery/portable_atmospherics/scrubber/Topic(href, href_list) - . = ..() - if(.) - return . - - if(href_list["power"]) - on = !on - update_icon() - - if(href_list["remove_tank"]) - if(holding) - eject_holding() - - if(href_list["volume_adj"]) - var/diff = text2num(href_list["volume_adj"]) - volume_rate = Clamp(volume_rate+diff, minrate, maxrate) - - src.add_fingerprint(usr) - return 1 - -/obj/machinery/portable_atmospherics/scrubber/AltClick() - if(usr.canmove && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && usr.dexterity_check()) - eject_holding() - return - return ..() + return + + ..() + + +/obj/machinery/portable_atmospherics/scrubber/update_icon() + src.overlays = 0 + + if(on) + icon_state = "pscrubber:1" + else + icon_state = "pscrubber:0" + + if(holding) + overlays += "scrubber-open" + + if(connected_port) + overlays += "scrubber-connector" + + return + +/obj/machinery/portable_atmospherics/scrubber/process() + ..() + + if(on) + var/datum/gas_mixture/environment + if(holding) + environment = holding.air_contents + else + environment = loc.return_air() + var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + + //Take a gas sample + var/datum/gas_mixture/removed + if(holding) + removed = environment.remove(transfer_moles) + else + removed = loc.remove_air(transfer_moles) + + //Filter it + if (removed) + var/datum/gas_mixture/filtered_out = new + + filtered_out.temperature = removed.temperature + + + filtered_out.toxins = removed.toxins + removed.toxins = 0 + + filtered_out.carbon_dioxide = removed.carbon_dioxide + removed.carbon_dioxide = 0 + + if(removed.trace_gases.len>0) + for(var/datum/gas/trace_gas in removed.trace_gases) + if(istype(trace_gas, /datum/gas/sleeping_agent)) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + + if(removed.trace_gases.len>0) + for(var/datum/gas/trace_gas in removed.trace_gases) + if(istype(trace_gas, /datum/gas/oxygen_agent_b)) + removed.trace_gases -= trace_gas + filtered_out.trace_gases += trace_gas + + //Remix the resulting gases + air_contents.merge(filtered_out) + + if(holding) + environment.merge(removed) + else + loc.assume_air(removed) + //src.update_icon() + nanomanager.update_uis(src) + //src.updateDialog() + return + +/obj/machinery/portable_atmospherics/scrubber/return_air() + return air_contents + +/obj/machinery/portable_atmospherics/scrubber/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/scrubber/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/scrubber/attack_hand(var/mob/user as mob) + ui_interact(user) + return + +/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + var/list/data[0] + data["portConnected"] = connected_port ? 1 : 0 + data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["rate"] = round(volume_rate) + data["minrate"] = round(minrate) + data["maxrate"] = round(maxrate) + data["on"] = on ? 1 : 0 + + data["hasHoldingTank"] = holding ? 1 : 0 + if (holding) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "portscrubber.tmpl", "Portable Scrubber", 480, 400) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + //ui.set_auto_update(1) + +/obj/machinery/portable_atmospherics/scrubber/Topic(href, href_list) + . = ..() + if(.) + return . + + if(href_list["power"]) + on = !on + update_icon() + + if(href_list["remove_tank"]) + if(holding) + eject_holding() + + if(href_list["volume_adj"]) + var/diff = text2num(href_list["volume_adj"]) + volume_rate = Clamp(volume_rate+diff, minrate, maxrate) + + src.add_fingerprint(usr) + return 1 + +/obj/machinery/portable_atmospherics/scrubber/AltClick() + if(usr.canmove && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && usr.dexterity_check()) + eject_holding() + return + return ..() diff --git a/code/game/machinery/atmoalter/zvent.dm b/code/game/machinery/atmoalter/zvent.dm index 163e86a74da..7df54a0bb8e 100644 --- a/code/game/machinery/atmoalter/zvent.dm +++ b/code/game/machinery/atmoalter/zvent.dm @@ -1,29 +1,29 @@ -/obj/machinery/zvent - name = "Interfloor Air Transfer System" - - icon = 'icons/obj/pipes.dmi' - icon_state = "vent-db" - density = 0 - anchored=1 - - var/on = 0 - var/volume_rate = 800 - -/obj/machinery/zvent/process() - - //all this object does, is make its turf share air with the ones above and below it, if they have a vent too. - if (istype(loc,/turf/simulated)) //if we're not on a valid turf, forget it - for (var/new_z in list(-1,1)) //change this list if a fancier system of z-levels gets implemented - var/turf/simulated/zturf_conn = locate(x,y,z+new_z) - if (istype(zturf_conn)) - var/obj/machinery/zvent/zvent_conn= locate(/obj/machinery/zvent) in zturf_conn - if (istype(zvent_conn)) - //both floors have simulated turfs, share() - var/turf/simulated/myturf = loc - var/datum/gas_mixture/conn_air = zturf_conn.zone.air //TODO: pop culture reference - var/datum/gas_mixture/my_air = myturf.air - if (istype(conn_air) && istype(my_air)) -// if (!my_air.compare(conn_air)) -// myturf.reset_delay() -// zturf_conn.reset_delay() - my_air.share(conn_air) +/obj/machinery/zvent + name = "Interfloor Air Transfer System" + + icon = 'icons/obj/pipes.dmi' + icon_state = "vent-db" + density = 0 + anchored=1 + + var/on = 0 + var/volume_rate = 800 + +/obj/machinery/zvent/process() + + //all this object does, is make its turf share air with the ones above and below it, if they have a vent too. + if (istype(loc,/turf/simulated)) //if we're not on a valid turf, forget it + for (var/new_z in list(-1,1)) //change this list if a fancier system of z-levels gets implemented + var/turf/simulated/zturf_conn = locate(x,y,z+new_z) + if (istype(zturf_conn)) + var/obj/machinery/zvent/zvent_conn= locate(/obj/machinery/zvent) in zturf_conn + if (istype(zvent_conn)) + //both floors have simulated turfs, share() + var/turf/simulated/myturf = loc + var/datum/gas_mixture/conn_air = zturf_conn.zone.air //TODO: pop culture reference + var/datum/gas_mixture/my_air = myturf.air + if (istype(conn_air) && istype(my_air)) +// if (!my_air.compare(conn_air)) +// myturf.reset_delay() +// zturf_conn.reset_delay() + my_air.share(conn_air) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 5ffbe859185..0498254f247 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -1,187 +1,187 @@ -#define AUTOLATHE_BUILD_TIME 0.5 -#define AUTOLATHE_MAX_TIME 50 //5 seconds max, * time_coeff - -/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe - name = "\improper Autolathe" - desc = "Produces a large range of common items using metal and glass." - icon_state = "autolathe" - icon_state_open = "autolathe_t" - nano_file = "autolathe.tmpl" - density = 1 - - design_types = list() - - start_end_anims = 1 - - use_power = 1 - idle_power_usage = 50 - active_power_usage = 500 - - build_time = AUTOLATHE_BUILD_TIME - - removable_designs = 0 - plastic_added = 0 - - allowed_materials = list( - MAT_IRON, - MAT_GLASS - ) - - machine_flags = SCREWTOGGLE | CROWDESTROY | EMAGGABLE | WRENCHMOVE | FIXED2WORK - - research_flags = NANOTOUCH | TAKESMATIN | HASOUTPUT | IGNORE_CHEMS | HASMAT_OVER | FAB_RECYCLER - - light_color = LIGHT_COLOR_CYAN - - one_part_set_only = 0 - part_sets = list( - "Tools"=list( - new /obj/item/device/multitool(), \ - new /obj/item/weapon/weldingtool/empty(), \ - new /obj/item/weapon/crowbar(), \ - new /obj/item/weapon/screwdriver(), \ - new /obj/item/weapon/wirecutters(), \ - new /obj/item/weapon/wrench(), \ - new /obj/item/weapon/solder(),\ - new /obj/item/device/analyzer(), \ - new /obj/item/device/t_scanner(), \ - new /obj/item/weapon/pickaxe/shovel/spade(), \ - new /obj/item/device/silicate_sprayer/empty(), \ - ), - "Containers"=list( - new /obj/item/weapon/reagent_containers/glass/beaker(), \ - new /obj/item/weapon/reagent_containers/glass/beaker/large(), \ - new /obj/item/weapon/reagent_containers/glass/bucket(), \ - new /obj/item/weapon/reagent_containers/glass/beaker/vial(), \ - new /obj/item/weapon/reagent_containers/food/drinks/mug(), \ - ), - "Assemblies"=list( - new /obj/item/device/assembly/igniter(), \ - new /obj/item/device/assembly/signaler(), \ - /*new /obj/item/device/assembly/infra(), \*/ - new /obj/item/device/assembly/timer(), \ - new /obj/item/device/assembly/voice(), \ - new /obj/item/device/assembly/prox_sensor(), \ - new /obj/item/device/assembly/speaker(), \ - new /obj/item/device/assembly/addition(), \ - new /obj/item/device/assembly/comparison(), \ - new /obj/item/device/assembly/randomizer(), \ - new /obj/item/device/assembly/read_write(), \ - new /obj/item/device/assembly/math(), \ - ), - "Stock_Parts"=list( - new /obj/item/weapon/stock_parts/console_screen(), \ - new /obj/item/weapon/stock_parts/capacitor(), \ - new /obj/item/weapon/stock_parts/scanning_module(), \ - new /obj/item/weapon/stock_parts/manipulator(), \ - new /obj/item/weapon/stock_parts/micro_laser(), \ - new /obj/item/weapon/stock_parts/matter_bin(), \ - ), - "Medical"=list( - new /obj/item/weapon/storage/pill_bottle(),\ - new /obj/item/weapon/reagent_containers/syringe(), \ - new /obj/item/weapon/scalpel(), \ - new /obj/item/weapon/circular_saw(), \ - new /obj/item/weapon/surgicaldrill(),\ - new /obj/item/weapon/retractor(),\ - new /obj/item/weapon/cautery(),\ - new /obj/item/weapon/hemostat(),\ - ), - "Ammunition"=list( - new /obj/item/ammo_casing/shotgun/blank(), \ - new /obj/item/ammo_casing/shotgun/beanbag(), \ - new /obj/item/ammo_casing/shotgun/flare(), \ - new /obj/item/ammo_storage/speedloader/c38/empty(), \ - new /obj/item/ammo_storage/box/c38(), \ - ), - "Misc_Tools"=list( - new /obj/item/device/flashlight(), \ - new /obj/item/weapon/extinguisher(), \ - new /obj/item/device/radio/headset(), \ - new /obj/item/device/radio/off(), \ - new /obj/item/weapon/kitchen/utensil/knife/large(), \ - new /obj/item/clothing/head/welding(), \ - new /obj/item/device/taperecorder(), \ - new /obj/item/weapon/chisel(), \ - new /obj/item/device/rcd/tile_painter(), \ - ), - "Misc_Other"=list( - new /obj/item/weapon/rcd_ammo(), \ - new /obj/item/weapon/light/tube(), \ - new /obj/item/weapon/light/bulb(), \ - new /obj/item/ashtray/glass(), \ - new /obj/item/weapon/storage/pill_bottle/dice(),\ - new /obj/item/weapon/camera_assembly(), \ - new /obj/item/stack/sheet/glass/rglass(), \ - new /obj/item/stack/rods(), \ - ), - "Hidden_Items" = list( - new /obj/item/weapon/flamethrower/full(), \ - new /obj/item/ammo_storage/box/flare(), \ - new /obj/item/device/rcd/matter/engineering(), \ - new /obj/item/device/rcd/rpd(),\ - new /obj/item/device/rcd/matter/rsf(), \ - new /obj/item/device/radio/electropack(), \ - new /obj/item/weapon/weldingtool/largetank/empty(), \ - new /obj/item/weapon/handcuffs(), \ - new /obj/item/ammo_storage/box/a357(), \ - new /obj/item/ammo_casing/shotgun(), \ - new /obj/item/ammo_casing/shotgun/dart(), \ - ) - ) - -/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/autolathe, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/get_construction_time_w_coeff(datum/design/part) - return min(..(), (AUTOLATHE_MAX_TIME * time_coeff)) //we have set designs, so we can make them quickly - -/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/is_contraband(var/datum/design/part) - if(part in part_sets["Hidden_Items"]) - return 1 - -/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/update_hacked() - if(screen == 51) screen = 11 //take the autolathe away from the contraband menu, since otherwise it can still print contraband until another category is selected - /*if(hacked) - part_sets["Items"] |= part_sets["Hidden Items"] - else - part_sets["Items"] -= part_sets["Hidden Items"]*/ - -/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/attackby(obj/item/I, mob/user) - if(..()) - return 1 - - else if(I.materials) - if(I.materials.getVolume() + src.materials.getVolume() > max_material_storage) - to_chat(user, "\The [src]'s material bin is too full to recycle \the [I].") - return 1 - else if(I.materials.getAmount(MAT_IRON) + I.materials.getAmount(MAT_GLASS) < I.materials.getVolume()) - to_chat(user, "\The [src] can only accept objects made out of metal and glass.") - return 1 - else if(isrobot(user)) - if(isMoMMI(user)) - var/mob/living/silicon/robot/mommi/M = user - if(M.is_in_modules(I)) - to_chat(user, "You cannot recycle your built in tools.") - return 1 - else - to_chat(user, "You cannot recycle your built in tools.") - return 1 - - if(user.drop_item(I, src)) - materials.removeFrom(I.materials) - user.visible_message("[user] puts \the [I] into \the [src]'s recycling unit.", - "You put \the [I] in \the [src]'s reycling unit.") - qdel(I) - return 1 +#define AUTOLATHE_BUILD_TIME 0.5 +#define AUTOLATHE_MAX_TIME 50 //5 seconds max, * time_coeff + +/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe + name = "\improper Autolathe" + desc = "Produces a large range of common items using metal and glass." + icon_state = "autolathe" + icon_state_open = "autolathe_t" + nano_file = "autolathe.tmpl" + density = 1 + + design_types = list() + + start_end_anims = 1 + + use_power = 1 + idle_power_usage = 50 + active_power_usage = 500 + + build_time = AUTOLATHE_BUILD_TIME + + removable_designs = 0 + plastic_added = 0 + + allowed_materials = list( + MAT_IRON, + MAT_GLASS + ) + + machine_flags = SCREWTOGGLE | CROWDESTROY | EMAGGABLE | WRENCHMOVE | FIXED2WORK + + research_flags = NANOTOUCH | TAKESMATIN | HASOUTPUT | IGNORE_CHEMS | HASMAT_OVER | FAB_RECYCLER + + light_color = LIGHT_COLOR_CYAN + + one_part_set_only = 0 + part_sets = list( + "Tools"=list( + new /obj/item/device/multitool(), \ + new /obj/item/weapon/weldingtool/empty(), \ + new /obj/item/weapon/crowbar(), \ + new /obj/item/weapon/screwdriver(), \ + new /obj/item/weapon/wirecutters(), \ + new /obj/item/weapon/wrench(), \ + new /obj/item/weapon/solder(),\ + new /obj/item/device/analyzer(), \ + new /obj/item/device/t_scanner(), \ + new /obj/item/weapon/pickaxe/shovel/spade(), \ + new /obj/item/device/silicate_sprayer/empty(), \ + ), + "Containers"=list( + new /obj/item/weapon/reagent_containers/glass/beaker(), \ + new /obj/item/weapon/reagent_containers/glass/beaker/large(), \ + new /obj/item/weapon/reagent_containers/glass/bucket(), \ + new /obj/item/weapon/reagent_containers/glass/beaker/vial(), \ + new /obj/item/weapon/reagent_containers/food/drinks/mug(), \ + ), + "Assemblies"=list( + new /obj/item/device/assembly/igniter(), \ + new /obj/item/device/assembly/signaler(), \ + /*new /obj/item/device/assembly/infra(), \*/ + new /obj/item/device/assembly/timer(), \ + new /obj/item/device/assembly/voice(), \ + new /obj/item/device/assembly/prox_sensor(), \ + new /obj/item/device/assembly/speaker(), \ + new /obj/item/device/assembly/addition(), \ + new /obj/item/device/assembly/comparison(), \ + new /obj/item/device/assembly/randomizer(), \ + new /obj/item/device/assembly/read_write(), \ + new /obj/item/device/assembly/math(), \ + ), + "Stock_Parts"=list( + new /obj/item/weapon/stock_parts/console_screen(), \ + new /obj/item/weapon/stock_parts/capacitor(), \ + new /obj/item/weapon/stock_parts/scanning_module(), \ + new /obj/item/weapon/stock_parts/manipulator(), \ + new /obj/item/weapon/stock_parts/micro_laser(), \ + new /obj/item/weapon/stock_parts/matter_bin(), \ + ), + "Medical"=list( + new /obj/item/weapon/storage/pill_bottle(),\ + new /obj/item/weapon/reagent_containers/syringe(), \ + new /obj/item/weapon/scalpel(), \ + new /obj/item/weapon/circular_saw(), \ + new /obj/item/weapon/surgicaldrill(),\ + new /obj/item/weapon/retractor(),\ + new /obj/item/weapon/cautery(),\ + new /obj/item/weapon/hemostat(),\ + ), + "Ammunition"=list( + new /obj/item/ammo_casing/shotgun/blank(), \ + new /obj/item/ammo_casing/shotgun/beanbag(), \ + new /obj/item/ammo_casing/shotgun/flare(), \ + new /obj/item/ammo_storage/speedloader/c38/empty(), \ + new /obj/item/ammo_storage/box/c38(), \ + ), + "Misc_Tools"=list( + new /obj/item/device/flashlight(), \ + new /obj/item/weapon/extinguisher(), \ + new /obj/item/device/radio/headset(), \ + new /obj/item/device/radio/off(), \ + new /obj/item/weapon/kitchen/utensil/knife/large(), \ + new /obj/item/clothing/head/welding(), \ + new /obj/item/device/taperecorder(), \ + new /obj/item/weapon/chisel(), \ + new /obj/item/device/rcd/tile_painter(), \ + ), + "Misc_Other"=list( + new /obj/item/weapon/rcd_ammo(), \ + new /obj/item/weapon/light/tube(), \ + new /obj/item/weapon/light/bulb(), \ + new /obj/item/ashtray/glass(), \ + new /obj/item/weapon/storage/pill_bottle/dice(),\ + new /obj/item/weapon/camera_assembly(), \ + new /obj/item/stack/sheet/glass/rglass(), \ + new /obj/item/stack/rods(), \ + ), + "Hidden_Items" = list( + new /obj/item/weapon/flamethrower/full(), \ + new /obj/item/ammo_storage/box/flare(), \ + new /obj/item/device/rcd/matter/engineering(), \ + new /obj/item/device/rcd/rpd(),\ + new /obj/item/device/rcd/matter/rsf(), \ + new /obj/item/device/radio/electropack(), \ + new /obj/item/weapon/weldingtool/largetank/empty(), \ + new /obj/item/weapon/handcuffs(), \ + new /obj/item/ammo_storage/box/a357(), \ + new /obj/item/ammo_casing/shotgun(), \ + new /obj/item/ammo_casing/shotgun/dart(), \ + ) + ) + +/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/autolathe, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/get_construction_time_w_coeff(datum/design/part) + return min(..(), (AUTOLATHE_MAX_TIME * time_coeff)) //we have set designs, so we can make them quickly + +/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/is_contraband(var/datum/design/part) + if(part in part_sets["Hidden_Items"]) + return 1 + +/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/update_hacked() + if(screen == 51) screen = 11 //take the autolathe away from the contraband menu, since otherwise it can still print contraband until another category is selected + /*if(hacked) + part_sets["Items"] |= part_sets["Hidden Items"] + else + part_sets["Items"] -= part_sets["Hidden Items"]*/ + +/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe/attackby(obj/item/I, mob/user) + if(..()) + return 1 + + else if(I.materials) + if(I.materials.getVolume() + src.materials.getVolume() > max_material_storage) + to_chat(user, "\The [src]'s material bin is too full to recycle \the [I].") + return 1 + else if(I.materials.getAmount(MAT_IRON) + I.materials.getAmount(MAT_GLASS) < I.materials.getVolume()) + to_chat(user, "\The [src] can only accept objects made out of metal and glass.") + return 1 + else if(isrobot(user)) + if(isMoMMI(user)) + var/mob/living/silicon/robot/mommi/M = user + if(M.is_in_modules(I)) + to_chat(user, "You cannot recycle your built in tools.") + return 1 + else + to_chat(user, "You cannot recycle your built in tools.") + return 1 + + if(user.drop_item(I, src)) + materials.removeFrom(I.materials) + user.visible_message("[user] puts \the [I] into \the [src]'s recycling unit.", + "You put \the [I] in \the [src]'s reycling unit.") + qdel(I) + return 1 diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 5de2e64ba0b..c5ef37f4cc4 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -1,199 +1,199 @@ -// AI (i.e. game AI, not the AI player) controlled bots - -/obj/machinery/bot - icon = 'icons/obj/aibots.dmi' - layer = MOB_LAYER - luminosity = 3 - use_power = 0 - var/obj/item/weapon/card/id/botcard // the ID card that the bot "holds" - var/on = 1 - var/health = 0 //do not forget to set health for your bot! - var/maxhealth = 0 - var/fire_dam_coeff = 1.0 - var/brute_dam_coeff = 1.0 - var/open = 0//Maint panel - var/locked = 1 - var/bot_type - var/declare_message = "" //What the bot will display to the HUD user. - #define SEC_BOT 1 // Secutritrons (Beepsky) and ED-209s - #define MULE_BOT 2 // MULEbots - #define FLOOR_BOT 3 // Floorbots - #define CLEAN_BOT 4 // Cleanbots - #define MED_BOT 5 // Medibots - //var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots - -/obj/machinery/bot/New() - for(var/datum/event/ionstorm/I in events) - if(istype(I) && I.active) - I.bots += src - ..() - -/obj/machinery/bot/proc/turn_on() - if(stat) return 0 - on = 1 - set_light(initial(luminosity)) - return 1 - -/obj/machinery/bot/proc/turn_off() - on = 0 - set_light(0) - -/obj/machinery/bot/proc/explode() - qdel(src) - -/obj/machinery/bot/proc/healthcheck() - if (src.health <= 0) - src.explode() - -/obj/machinery/bot/proc/Emag(mob/user as mob) - if(locked) - locked = 0 - emagged = 1 +// AI (i.e. game AI, not the AI player) controlled bots + +/obj/machinery/bot + icon = 'icons/obj/aibots.dmi' + layer = MOB_LAYER + luminosity = 3 + use_power = 0 + var/obj/item/weapon/card/id/botcard // the ID card that the bot "holds" + var/on = 1 + var/health = 0 //do not forget to set health for your bot! + var/maxhealth = 0 + var/fire_dam_coeff = 1.0 + var/brute_dam_coeff = 1.0 + var/open = 0//Maint panel + var/locked = 1 + var/bot_type + var/declare_message = "" //What the bot will display to the HUD user. + #define SEC_BOT 1 // Secutritrons (Beepsky) and ED-209s + #define MULE_BOT 2 // MULEbots + #define FLOOR_BOT 3 // Floorbots + #define CLEAN_BOT 4 // Cleanbots + #define MED_BOT 5 // Medibots + //var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots + +/obj/machinery/bot/New() + for(var/datum/event/ionstorm/I in events) + if(istype(I) && I.active) + I.bots += src + ..() + +/obj/machinery/bot/proc/turn_on() + if(stat) return 0 + on = 1 + set_light(initial(luminosity)) + return 1 + +/obj/machinery/bot/proc/turn_off() + on = 0 + set_light(0) + +/obj/machinery/bot/proc/explode() + qdel(src) + +/obj/machinery/bot/proc/healthcheck() + if (src.health <= 0) + src.explode() + +/obj/machinery/bot/proc/Emag(mob/user as mob) + if(locked) + locked = 0 + emagged = 1 to_chat(user, "You bypass [src]'s controls.") - if(!locked && open) - emagged = 2 - -/obj/machinery/bot/examine(mob/user) - ..() - if (src.health < maxhealth) - if (src.health > maxhealth/3) + if(!locked && open) + emagged = 2 + +/obj/machinery/bot/examine(mob/user) + ..() + if (src.health < maxhealth) + if (src.health > maxhealth/3) to_chat(user, "[src]'s parts look loose.") - else + else to_chat(user, "[src]'s parts look very loose!") - -/obj/machinery/bot/attack_alien(var/mob/living/carbon/alien/user as mob) - if(flags & INVULNERABLE) - return - src.health -= rand(15,30)*brute_dam_coeff - src.visible_message("[user] has slashed [src]!") - playsound(get_turf(src), 'sound/weapons/slice.ogg', 25, 1, -1) - if(prob(10)) - //new /obj/effect/decal/cleanable/blood/oil(src.loc) - var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) - O.New(O.loc) - healthcheck() - - -/obj/machinery/bot/attack_animal(var/mob/living/simple_animal/M as mob) - if(flags & INVULNERABLE) - return - if(M.melee_damage_upper == 0) return - src.health -= M.melee_damage_upper - src.visible_message("[M] has [M.attacktext] [src]!") - add_logs(M, src, "attacked", admin=0) - if(prob(10)) - //new /obj/effect/decal/cleanable/blood/oil(src.loc) - var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) - O.New(O.loc) - healthcheck() - -/obj/machinery/bot/proc/declare() //Signals a medical or security HUD user to a relevant bot's activity. - var/hud_user_list = list() //Determines which userlist to use. - switch(bot_type) //Made into a switch so more HUDs can be added easily. - if(SEC_BOT) //Securitrons and ED-209 - hud_user_list = sec_hud_users - if(MED_BOT) //Medibots - hud_user_list = med_hud_users - var/area/myturf = get_turf(src) - for(var/mob/huduser in hud_user_list) - var/turf/mobturf = get_turf(huduser) - if(mobturf.z == myturf.z) - huduser.show_message(declare_message,1) - - -/obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(flags & INVULNERABLE) - return - if(istype(W, /obj/item/weapon/screwdriver)) - if(!locked) - open = !open + +/obj/machinery/bot/attack_alien(var/mob/living/carbon/alien/user as mob) + if(flags & INVULNERABLE) + return + src.health -= rand(15,30)*brute_dam_coeff + src.visible_message("[user] has slashed [src]!") + playsound(get_turf(src), 'sound/weapons/slice.ogg', 25, 1, -1) + if(prob(10)) + //new /obj/effect/decal/cleanable/blood/oil(src.loc) + var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) + O.New(O.loc) + healthcheck() + + +/obj/machinery/bot/attack_animal(var/mob/living/simple_animal/M as mob) + if(flags & INVULNERABLE) + return + if(M.melee_damage_upper == 0) return + src.health -= M.melee_damage_upper + src.visible_message("[M] has [M.attacktext] [src]!") + add_logs(M, src, "attacked", admin=0) + if(prob(10)) + //new /obj/effect/decal/cleanable/blood/oil(src.loc) + var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) + O.New(O.loc) + healthcheck() + +/obj/machinery/bot/proc/declare() //Signals a medical or security HUD user to a relevant bot's activity. + var/hud_user_list = list() //Determines which userlist to use. + switch(bot_type) //Made into a switch so more HUDs can be added easily. + if(SEC_BOT) //Securitrons and ED-209 + hud_user_list = sec_hud_users + if(MED_BOT) //Medibots + hud_user_list = med_hud_users + var/area/myturf = get_turf(src) + for(var/mob/huduser in hud_user_list) + var/turf/mobturf = get_turf(huduser) + if(mobturf.z == myturf.z) + huduser.show_message(declare_message,1) + + +/obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(flags & INVULNERABLE) + return + if(istype(W, /obj/item/weapon/screwdriver)) + if(!locked) + open = !open to_chat(user, "Maintenance panel is now [src.open ? "opened" : "closed"].") - else if(istype(W, /obj/item/weapon/weldingtool)) - if(health < maxhealth) - if(open) - health = min(maxhealth, health+10) - user.visible_message("[user] repairs [src]!","You repair [src]!") - else + else if(istype(W, /obj/item/weapon/weldingtool)) + if(health < maxhealth) + if(open) + health = min(maxhealth, health+10) + user.visible_message("[user] repairs [src]!","You repair [src]!") + else to_chat(user, "Unable to repair with the maintenance panel closed.") - else + else to_chat(user, "[src] does not need a repair.") - else if (istype(W, /obj/item/weapon/card/emag) && emagged < 2) - Emag(user) - else - if(hasvar(W,"force") && hasvar(W,"damtype")) - switch(W.damtype) - if("fire") - src.health -= W.force * fire_dam_coeff - if("brute") - src.health -= W.force * brute_dam_coeff - ..() - healthcheck() - else - ..() - -/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj) - if(flags & INVULNERABLE) - return - health -= Proj.damage - ..() - healthcheck() - -/obj/machinery/bot/blob_act() - if(flags & INVULNERABLE) - return - src.health -= rand(20,40)*fire_dam_coeff - healthcheck() - return - -/obj/machinery/bot/ex_act(severity) - if(flags & INVULNERABLE) - return - switch(severity) - if(1.0) - src.explode() - return - if(2.0) - src.health -= rand(5,10)*fire_dam_coeff - src.health -= rand(10,20)*brute_dam_coeff - healthcheck() - return - if(3.0) - if (prob(50)) - src.health -= rand(1,5)*fire_dam_coeff - src.health -= rand(1,5)*brute_dam_coeff - healthcheck() - return - return - -/obj/machinery/bot/emp_act(severity) - if(flags & INVULNERABLE) - return - var/was_on = on - stat |= EMPED - var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.dir = pick(cardinal) - - spawn(10) - qdel(pulse2) - if (on) - turn_off() - spawn(severity*300) - stat &= ~EMPED - if (was_on) - turn_on() - - -/obj/machinery/bot/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - src.attack_hand(user) - - -/obj/machinery/bot/cultify() - if(src.flags & INVULNERABLE) - return - else - qdel(src) + else if (istype(W, /obj/item/weapon/card/emag) && emagged < 2) + Emag(user) + else + if(hasvar(W,"force") && hasvar(W,"damtype")) + switch(W.damtype) + if("fire") + src.health -= W.force * fire_dam_coeff + if("brute") + src.health -= W.force * brute_dam_coeff + ..() + healthcheck() + else + ..() + +/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj) + if(flags & INVULNERABLE) + return + health -= Proj.damage + ..() + healthcheck() + +/obj/machinery/bot/blob_act() + if(flags & INVULNERABLE) + return + src.health -= rand(20,40)*fire_dam_coeff + healthcheck() + return + +/obj/machinery/bot/ex_act(severity) + if(flags & INVULNERABLE) + return + switch(severity) + if(1.0) + src.explode() + return + if(2.0) + src.health -= rand(5,10)*fire_dam_coeff + src.health -= rand(10,20)*brute_dam_coeff + healthcheck() + return + if(3.0) + if (prob(50)) + src.health -= rand(1,5)*fire_dam_coeff + src.health -= rand(1,5)*brute_dam_coeff + healthcheck() + return + return + +/obj/machinery/bot/emp_act(severity) + if(flags & INVULNERABLE) + return + var/was_on = on + stat |= EMPED + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + + spawn(10) + qdel(pulse2) + if (on) + turn_off() + spawn(severity*300) + stat &= ~EMPED + if (was_on) + turn_on() + + +/obj/machinery/bot/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + src.attack_hand(user) + + +/obj/machinery/bot/cultify() + if(src.flags & INVULNERABLE) + return + else + qdel(src) diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm index 26064da094b..d238ccf86af 100644 --- a/code/game/machinery/bots/cleanbot.dm +++ b/code/game/machinery/bots/cleanbot.dm @@ -1,357 +1,357 @@ -//Cleanbot assembly -/obj/item/weapon/bucket_sensor - desc = "It's a bucket. With a sensor attached." - name = "proxy bucket" - icon = 'icons/obj/aibots.dmi' - icon_state = "bucket_proxy" - force = 3.0 - throwforce = 10.0 - throw_speed = 2 - throw_range = 5 - w_class = 3.0 - flags = 0 - var/created_name = "Cleanbot" - - -//Cleanbot -/obj/machinery/bot/cleanbot - name = "Cleanbot" - desc = "A little cleaning robot, he looks so excited!" - icon = 'icons/obj/aibots.dmi' - icon_state = "cleanbot0" - layer = 5.0 - density = 0 - anchored = 0 - //weight = 1.0E7 - health = 25 - maxhealth = 25 - var/cleaning = 0 - var/screwloose = 0 - var/oddbutton = 0 - var/blood = 1 - var/crayon = 0 - var/list/blacklisted_targets = list() - var/turf/target - var/turf/oldtarget - var/oldloc = null - req_access = list(access_janitor) - var/path[] = new() - var/patrol_path[] = null - var/beacon_freq = 1445 // navigation beacon frequency - var/closest_dist - var/closest_loc - var/failed_steps - var/should_patrol - var/next_dest - var/next_dest_loc - -/obj/machinery/bot/cleanbot/New() - ..() - src.get_targets() - src.icon_state = "cleanbot[src.on]" - - should_patrol = 1 - - src.botcard = new /obj/item/weapon/card/id(src) - var/datum/job/janitor/J = new/datum/job/janitor - src.botcard.access = J.get_access() - - src.locked = 0 // Start unlocked so roboticist can set them to patrol. - - if(radio_controller) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - - -/obj/machinery/bot/cleanbot/turn_on() - . = ..() - src.icon_state = "cleanbot[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/cleanbot/turn_off() - ..() - if(!isnull(src.target)) - target.targetted_by = null - src.target = null - src.oldtarget = null - src.oldloc = null - src.icon_state = "cleanbot[src.on]" - src.path = new() - src.updateUsrDialog() - -/obj/machinery/bot/cleanbot/attack_hand(mob/user as mob) - . = ..() - if (.) - return - usr.set_machine(src) - interact(user) - -/obj/machinery/bot/cleanbot/interact(mob/user as mob) - var/dat - dat += text({" -Automatic Station Cleaner v1.0

      -Status: []
      -Behaviour controls are [src.locked ? "locked" : "unlocked"]
      -Maintenance panel is [src.open ? "opened" : "closed"]"}, -text("[src.on ? "On" : "Off"]")) - if(!src.locked || issilicon(user)) - dat += text({"
      Cleans Blood: []
      "}, text("[src.blood ? "Yes" : "No"]")) - dat += text({"
      Cleans Crayon: []
      "}, text("[src.crayon ? "Yes" : "No"]")) - dat += text({"
      Patrol station: []
      "}, text("[src.should_patrol ? "Yes" : "No"]")) - // dat += text({"
      Beacon frequency: []
      "}, text("[src.beacon_freq]")) - if(src.open && !src.locked) - dat += text({" -Odd looking screw twiddled: []
      -Weird button pressed: []"}, -text("[src.screwloose ? "Yes" : "No"]"), -text("[src.oddbutton ? "Yes" : "No"]")) - - user << browse("Cleaner v1.0 controls[dat]", "window=autocleaner") - onclose(user, "autocleaner") - return - -/obj/machinery/bot/cleanbot/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - switch(href_list["operation"]) - if("start") - if (src.on) - turn_off() - else - turn_on() - if("blood") - src.blood = !src.blood - src.get_targets() - src.updateUsrDialog() - if("crayon") - src.crayon = !src.crayon - src.get_targets() - src.updateUsrDialog() - if("patrol") - src.should_patrol =!src.should_patrol - src.patrol_path = null - src.updateUsrDialog() - if("freq") - var/freq = text2num(input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10))) * 10 - if (freq > 0) - src.beacon_freq = freq - src.updateUsrDialog() - if("screw") - src.screwloose = !src.screwloose - to_chat(usr, "You press the weird button.") - src.updateUsrDialog() - -/obj/machinery/bot/cleanbot/attackby(obj/item/weapon/W, mob/user as mob) - if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if(src.allowed(usr) && !open && !emagged) - src.locked = !src.locked - to_chat(user, "You [ src.locked ? "lock" : "unlock"] the [src] behaviour controls.") - else - if(emagged) - to_chat(user, "ERROR") - if(open) - to_chat(user, "Please close the access panel before locking it.") - else - to_chat(user, "This [src] doesn't seem to respect your authority.") - else - return ..() - -/obj/machinery/bot/cleanbot/Emag(mob/user as mob) - ..() - if(open && !locked) - if(user) to_chat(user, "The [src] buzzes and beeps.") - src.oddbutton = 1 - src.screwloose = 1 - -/obj/machinery/bot/cleanbot/process() - //set background = 1 - - if(!src.on) - return - if(src.cleaning) - return - - if(!src.screwloose && !src.oddbutton && prob(5)) - visible_message("[src] makes an excited beeping booping sound!") - - if(src.screwloose && prob(5)) - if(istype(loc,/turf/simulated)) - var/turf/simulated/T = src.loc - T.wet(800) - if(src.oddbutton && prob(5)) - visible_message("Something flies out of [src]. He seems to be acting oddly.") - var/obj/effect/decal/cleanable/blood/gibs/gib = getFromPool(/obj/effect/decal/cleanable/blood/gibs, src.loc) - gib.New(gib.loc) - //gib.streak(list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) - src.oldtarget = get_turf(gib) - if(!src.target || src.target == null) - for (var/turf/T in view(7,src)) - if(target) break - if(istype(T,/turf/space)) continue - for(var/obj/effect/decal/cleanable/sickfilth in T.contents) - if(sickfilth && !(is_type_in_list(sickfilth, blacklisted_targets))) - if(!T.targetted_by && T!=oldtarget) - oldtarget = T // or if it is but the bot is gone. - target = T // and it's stuff we clean? Clean it. - T.targetted_by = src // Claim the messy tile we are targeting. - break - - if(!src.target || src.target == null) - if(src.loc != src.oldloc) - src.oldtarget = null - - if (!should_patrol) - return - - if (!patrol_path || patrol_path.len < 1) - var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq) - - if(!frequency) return - - closest_dist = 9999 - closest_loc = null - next_dest_loc = null - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - signal.data = list("findbeacon" = "patrol") - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - spawn(5) - if (!next_dest_loc) - next_dest_loc = closest_loc - if (next_dest_loc) - src.patrol_path = AStar(src.loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=null) - else - patrol_move() - - return - - if(!path) - path = new() - if(target && path.len == 0) - spawn(0) - if(!src || !target) return - src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 30) - if (!path) path = list() - if(src.path.len == 0) - src.oldtarget = src.target - target.targetted_by = null - src.target = null - return - if(src.path.len > 0 && src.target && (src.target != null)) - step_to(src, src.path[1]) - src.path -= src.path[1] - else if(src.path.len == 1) - step_to(src, target) - - if(src.target && (src.target != null)) - patrol_path = null - if(src.loc == src.target) - clean(src.target) - src.path = new() - src.target = null - return - - src.oldloc = src.loc - -/obj/machinery/bot/cleanbot/proc/patrol_move() - if (src.patrol_path.len <= 0) - return - - var/next = src.patrol_path[1] - src.patrol_path -= next - if (next == src.loc) - return - - var/moved = step_towards(src, next) - if (!moved) - failed_steps++ - if (failed_steps > 4) - patrol_path = null - next_dest = null - failed_steps = 0 - else - failed_steps = 0 - -/obj/machinery/bot/cleanbot/receive_signal(datum/signal/signal) - var/recv = signal.data["beacon"] - var/valid = signal.data["patrol"] - if(!recv || !valid) - return - - var/dist = get_dist(src, signal.source.loc) - if (dist < closest_dist && signal.source.loc != src.loc) - closest_dist = dist - closest_loc = signal.source.loc - next_dest = signal.data["next_patrol"] - - if (recv == next_dest) - next_dest_loc = signal.source.loc - next_dest = signal.data["next_patrol"] - -/obj/machinery/bot/cleanbot/proc/get_targets() //This seems slightly wasteful, but it will only be called approximately once every six rounds so whatever - blacklisted_targets = list() - - if(!src.blood) - blacklisted_targets += (/obj/effect/decal/cleanable/blood) - if(!src.crayon) - blacklisted_targets += (/obj/effect/decal/cleanable/crayon) - -/obj/machinery/bot/cleanbot/proc/clean(var/turf/target) - anchored = 1 - icon_state = "cleanbot-c" - visible_message("[src] begins to clean up the [target].") - cleaning = 1 - spawn(2 SECONDS) - for(var/obj/effect/decal/cleanable/C in target) - if(!(is_type_in_list(C,blacklisted_targets))) - spawn(5) - qdel(C) - src.cleaning = 0 - icon_state = "cleanbot[on]" - anchored = 0 - target = null - -/obj/machinery/bot/cleanbot/explode() - src.on = 0 - src.visible_message("[src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - new /obj/item/weapon/reagent_containers/glass/bucket(Tsec) - - new /obj/item/device/assembly/prox_sensor(Tsec) - - if (prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - qdel(src) - return - -/obj/item/weapon/bucket_sensor/attackby(var/obj/item/W, mob/user as mob) - ..() - if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) - if(user.drop_item(W)) - qdel(W) - var/turf/T = get_turf(src.loc) - var/obj/machinery/bot/cleanbot/A = new /obj/machinery/bot/cleanbot(T) - A.name = src.created_name - to_chat(user, "You add the robot arm to the bucket and sensor assembly. Beep boop!") - user.drop_from_inventory(src) - qdel(src) - - else if (istype(W, /obj/item/weapon/pen)) - var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - src.created_name = t +//Cleanbot assembly +/obj/item/weapon/bucket_sensor + desc = "It's a bucket. With a sensor attached." + name = "proxy bucket" + icon = 'icons/obj/aibots.dmi' + icon_state = "bucket_proxy" + force = 3.0 + throwforce = 10.0 + throw_speed = 2 + throw_range = 5 + w_class = 3.0 + flags = 0 + var/created_name = "Cleanbot" + + +//Cleanbot +/obj/machinery/bot/cleanbot + name = "Cleanbot" + desc = "A little cleaning robot, he looks so excited!" + icon = 'icons/obj/aibots.dmi' + icon_state = "cleanbot0" + layer = 5.0 + density = 0 + anchored = 0 + //weight = 1.0E7 + health = 25 + maxhealth = 25 + var/cleaning = 0 + var/screwloose = 0 + var/oddbutton = 0 + var/blood = 1 + var/crayon = 0 + var/list/blacklisted_targets = list() + var/turf/target + var/turf/oldtarget + var/oldloc = null + req_access = list(access_janitor) + var/path[] = new() + var/patrol_path[] = null + var/beacon_freq = 1445 // navigation beacon frequency + var/closest_dist + var/closest_loc + var/failed_steps + var/should_patrol + var/next_dest + var/next_dest_loc + +/obj/machinery/bot/cleanbot/New() + ..() + src.get_targets() + src.icon_state = "cleanbot[src.on]" + + should_patrol = 1 + + src.botcard = new /obj/item/weapon/card/id(src) + var/datum/job/janitor/J = new/datum/job/janitor + src.botcard.access = J.get_access() + + src.locked = 0 // Start unlocked so roboticist can set them to patrol. + + if(radio_controller) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + + +/obj/machinery/bot/cleanbot/turn_on() + . = ..() + src.icon_state = "cleanbot[src.on]" + src.updateUsrDialog() + +/obj/machinery/bot/cleanbot/turn_off() + ..() + if(!isnull(src.target)) + target.targetted_by = null + src.target = null + src.oldtarget = null + src.oldloc = null + src.icon_state = "cleanbot[src.on]" + src.path = new() + src.updateUsrDialog() + +/obj/machinery/bot/cleanbot/attack_hand(mob/user as mob) + . = ..() + if (.) + return + usr.set_machine(src) + interact(user) + +/obj/machinery/bot/cleanbot/interact(mob/user as mob) + var/dat + dat += text({" +Automatic Station Cleaner v1.0

      +Status: []
      +Behaviour controls are [src.locked ? "locked" : "unlocked"]
      +Maintenance panel is [src.open ? "opened" : "closed"]"}, +text("[src.on ? "On" : "Off"]")) + if(!src.locked || issilicon(user)) + dat += text({"
      Cleans Blood: []
      "}, text("[src.blood ? "Yes" : "No"]")) + dat += text({"
      Cleans Crayon: []
      "}, text("[src.crayon ? "Yes" : "No"]")) + dat += text({"
      Patrol station: []
      "}, text("[src.should_patrol ? "Yes" : "No"]")) + // dat += text({"
      Beacon frequency: []
      "}, text("[src.beacon_freq]")) + if(src.open && !src.locked) + dat += text({" +Odd looking screw twiddled: []
      +Weird button pressed: []"}, +text("[src.screwloose ? "Yes" : "No"]"), +text("[src.oddbutton ? "Yes" : "No"]")) + + user << browse("Cleaner v1.0 controls[dat]", "window=autocleaner") + onclose(user, "autocleaner") + return + +/obj/machinery/bot/cleanbot/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + switch(href_list["operation"]) + if("start") + if (src.on) + turn_off() + else + turn_on() + if("blood") + src.blood = !src.blood + src.get_targets() + src.updateUsrDialog() + if("crayon") + src.crayon = !src.crayon + src.get_targets() + src.updateUsrDialog() + if("patrol") + src.should_patrol =!src.should_patrol + src.patrol_path = null + src.updateUsrDialog() + if("freq") + var/freq = text2num(input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10))) * 10 + if (freq > 0) + src.beacon_freq = freq + src.updateUsrDialog() + if("screw") + src.screwloose = !src.screwloose + to_chat(usr, "You press the weird button.") + src.updateUsrDialog() + +/obj/machinery/bot/cleanbot/attackby(obj/item/weapon/W, mob/user as mob) + if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if(src.allowed(usr) && !open && !emagged) + src.locked = !src.locked + to_chat(user, "You [ src.locked ? "lock" : "unlock"] the [src] behaviour controls.") + else + if(emagged) + to_chat(user, "ERROR") + if(open) + to_chat(user, "Please close the access panel before locking it.") + else + to_chat(user, "This [src] doesn't seem to respect your authority.") + else + return ..() + +/obj/machinery/bot/cleanbot/Emag(mob/user as mob) + ..() + if(open && !locked) + if(user) to_chat(user, "The [src] buzzes and beeps.") + src.oddbutton = 1 + src.screwloose = 1 + +/obj/machinery/bot/cleanbot/process() + //set background = 1 + + if(!src.on) + return + if(src.cleaning) + return + + if(!src.screwloose && !src.oddbutton && prob(5)) + visible_message("[src] makes an excited beeping booping sound!") + + if(src.screwloose && prob(5)) + if(istype(loc,/turf/simulated)) + var/turf/simulated/T = src.loc + T.wet(800) + if(src.oddbutton && prob(5)) + visible_message("Something flies out of [src]. He seems to be acting oddly.") + var/obj/effect/decal/cleanable/blood/gibs/gib = getFromPool(/obj/effect/decal/cleanable/blood/gibs, src.loc) + gib.New(gib.loc) + //gib.streak(list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) + src.oldtarget = get_turf(gib) + if(!src.target || src.target == null) + for (var/turf/T in view(7,src)) + if(target) break + if(istype(T,/turf/space)) continue + for(var/obj/effect/decal/cleanable/sickfilth in T.contents) + if(sickfilth && !(is_type_in_list(sickfilth, blacklisted_targets))) + if(!T.targetted_by && T!=oldtarget) + oldtarget = T // or if it is but the bot is gone. + target = T // and it's stuff we clean? Clean it. + T.targetted_by = src // Claim the messy tile we are targeting. + break + + if(!src.target || src.target == null) + if(src.loc != src.oldloc) + src.oldtarget = null + + if (!should_patrol) + return + + if (!patrol_path || patrol_path.len < 1) + var/datum/radio_frequency/frequency = radio_controller.return_frequency(beacon_freq) + + if(!frequency) return + + closest_dist = 9999 + closest_loc = null + next_dest_loc = null + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + signal.data = list("findbeacon" = "patrol") + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + spawn(5) + if (!next_dest_loc) + next_dest_loc = closest_loc + if (next_dest_loc) + src.patrol_path = AStar(src.loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=null) + else + patrol_move() + + return + + if(!path) + path = new() + if(target && path.len == 0) + spawn(0) + if(!src || !target) return + src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 30) + if (!path) path = list() + if(src.path.len == 0) + src.oldtarget = src.target + target.targetted_by = null + src.target = null + return + if(src.path.len > 0 && src.target && (src.target != null)) + step_to(src, src.path[1]) + src.path -= src.path[1] + else if(src.path.len == 1) + step_to(src, target) + + if(src.target && (src.target != null)) + patrol_path = null + if(src.loc == src.target) + clean(src.target) + src.path = new() + src.target = null + return + + src.oldloc = src.loc + +/obj/machinery/bot/cleanbot/proc/patrol_move() + if (src.patrol_path.len <= 0) + return + + var/next = src.patrol_path[1] + src.patrol_path -= next + if (next == src.loc) + return + + var/moved = step_towards(src, next) + if (!moved) + failed_steps++ + if (failed_steps > 4) + patrol_path = null + next_dest = null + failed_steps = 0 + else + failed_steps = 0 + +/obj/machinery/bot/cleanbot/receive_signal(datum/signal/signal) + var/recv = signal.data["beacon"] + var/valid = signal.data["patrol"] + if(!recv || !valid) + return + + var/dist = get_dist(src, signal.source.loc) + if (dist < closest_dist && signal.source.loc != src.loc) + closest_dist = dist + closest_loc = signal.source.loc + next_dest = signal.data["next_patrol"] + + if (recv == next_dest) + next_dest_loc = signal.source.loc + next_dest = signal.data["next_patrol"] + +/obj/machinery/bot/cleanbot/proc/get_targets() //This seems slightly wasteful, but it will only be called approximately once every six rounds so whatever + blacklisted_targets = list() + + if(!src.blood) + blacklisted_targets += (/obj/effect/decal/cleanable/blood) + if(!src.crayon) + blacklisted_targets += (/obj/effect/decal/cleanable/crayon) + +/obj/machinery/bot/cleanbot/proc/clean(var/turf/target) + anchored = 1 + icon_state = "cleanbot-c" + visible_message("[src] begins to clean up the [target].") + cleaning = 1 + spawn(2 SECONDS) + for(var/obj/effect/decal/cleanable/C in target) + if(!(is_type_in_list(C,blacklisted_targets))) + spawn(5) + qdel(C) + src.cleaning = 0 + icon_state = "cleanbot[on]" + anchored = 0 + target = null + +/obj/machinery/bot/cleanbot/explode() + src.on = 0 + src.visible_message("[src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + new /obj/item/weapon/reagent_containers/glass/bucket(Tsec) + + new /obj/item/device/assembly/prox_sensor(Tsec) + + if (prob(50)) + new /obj/item/robot_parts/l_arm(Tsec) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + qdel(src) + return + +/obj/item/weapon/bucket_sensor/attackby(var/obj/item/W, mob/user as mob) + ..() + if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) + if(user.drop_item(W)) + qdel(W) + var/turf/T = get_turf(src.loc) + var/obj/machinery/bot/cleanbot/A = new /obj/machinery/bot/cleanbot(T) + A.name = src.created_name + to_chat(user, "You add the robot arm to the bucket and sensor assembly. Beep boop!") + user.drop_from_inventory(src) + qdel(src) + + else if (istype(W, /obj/item/weapon/pen)) + var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) + if (!t) + return + if (!in_range(src, usr) && src.loc != usr) + return + src.created_name = t diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index 38e7ad895ad..8c8e2b04712 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -1,1106 +1,1106 @@ -/obj/machinery/bot/ed209 - name = "ED-209 Security Robot" - desc = "A security robot. He looks less than thrilled." - icon = 'icons/obj/aibots.dmi' - icon_state = "ed2090" - layer = 5.0 - density = 1 - anchored = 0 -// weight = 1.0E7 - req_one_access = list(access_security, access_forensics_lockers) - health = 100 - maxhealth = 100 - fire_dam_coeff = 0.7 - brute_dam_coeff = 0.5 - - var/lastfired = 0 - var/shot_delay = 3 //.3 seconds between shots - var/lasercolor = "" - var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag - - //var/lasers = 0 - - var/mob/living/carbon/target - var/oldtarget_name - var/threatlevel = 0 - var/target_lastloc //Loc of target when arrested. - var/last_found //There's a delay - var/frustration = 0 -//var/emagged = 0 //Emagged Secbots view everyone as a criminal - var/check_records = 1 //Does it check security records? - var/arrest_type = 0 //If true, don't handcuff - - var/projectile = null//Holder for projectile type, to avoid so many else if chains - - var/mode = 0 - bot_type = SEC_BOT -#define SECBOT_IDLE 0 // idle -#define SECBOT_HUNT 1 // found target, hunting -#define SECBOT_PREP_ARREST 2 // at target, preparing to arrest -#define SECBOT_ARREST 3 // arresting target -#define SECBOT_START_PATROL 4 // start patrol -#define SECBOT_PATROL 5 // patrolling -#define SECBOT_SUMMON 6 // summoned by PDA - - var/auto_patrol = 0 // set to make bot automatically patrol - - var/beacon_freq = 1445 // navigation beacon frequency - var/control_freq = 1447 // bot control frequency - - - var/turf/patrol_target // this is turf to navigate to (location of beacon) - var/new_destination // pending new destination (waiting for beacon response) - var/destination // destination description tag - var/next_destination // the next destination in the patrol route - var/list/path = new // list of path turfs - - var/blockcount = 0 //number of times retried a blocked path - var/awaiting_beacon = 0 // count of pticks awaiting a beacon response - - var/nearest_beacon // the nearest beacon's tag - var/turf/nearest_beacon_loc // the nearest beacon's location - var/declare_arrests = 1 //When making an arrest, should it notify everyone wearing sechuds? - var/idcheck = 1 //If true, arrest people with no IDs - var/weaponscheck = 1 //If true, arrest people for weapons if they don't have access - //List of weapons that secbots will not arrest for - var/safe_weapons = list( - /obj/item/weapon/gun/energy/laser/bluetag, - /obj/item/weapon/gun/energy/laser/redtag, - /obj/item/weapon/gun/energy/laser/practice, - /obj/item/weapon/gun/hookshot, - ) - - -/obj/item/weapon/ed209_assembly - name = "ED-209 assembly" - desc = "Some sort of bizarre assembly." - icon = 'icons/obj/aibots.dmi' - icon_state = "ed209_frame" - item_state = "ed209_frame" - var/build_step = 0 - var/created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess - var/lasercolor = "" - - -/obj/machinery/bot/ed209/New(loc,created_name,created_lasercolor) - ..() - if(created_name) name = created_name - if(created_lasercolor) lasercolor = created_lasercolor - src.icon_state = "[lasercolor]ed209[src.on]" - spawn(3) - src.botcard = new /obj/item/weapon/card/id(src) - var/datum/job/detective/J = new/datum/job/detective - src.botcard.access = J.get_access() - - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - if(lasercolor) - shot_delay = 6//Longer shot delay because JESUS CHRIST - check_records = 0//Don't actively target people set to arrest - arrest_type = 1//Don't even try to cuff - req_access = list(access_maint_tunnels) - arrest_type = 1 - if((lasercolor == "b") && (name == "ED-209 Security Robot"))//Picks a name if there isn't already a custome one - name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") - if((lasercolor == "r") && (name == "ED-209 Security Robot")) - name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") - -/obj/machinery/bot/ed209/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover,/obj/machinery/bot/ed209)) - return 1 - else - return ..() - -/obj/machinery/bot/ed209/turn_on() - . = ..() - src.icon_state = "[lasercolor]ed209[src.on]" - src.mode = SECBOT_IDLE - src.updateUsrDialog() - -/obj/machinery/bot/ed209/turn_off() - ..() - src.target = null - src.oldtarget_name = null - src.anchored = 0 - src.mode = SECBOT_IDLE - walk_to(src,0) - src.icon_state = "[lasercolor]ed209[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/ed209/attack_hand(mob/user as mob) - . = ..() - if (.) - return - var/dat - - dat += text({" -Automatic Security Unit v2.5

      -Status: []
      -Behaviour controls are [src.locked ? "locked" : "unlocked"]
      -Maintenance panel panel is [src.open ? "opened" : "closed"]"}, - -"[src.on ? "On" : "Off"]" ) - - if(!src.locked || issilicon(user)) - if(!lasercolor) - dat += text({"
      -Arrest for No ID: []
      -Arrest for Unauthorized Weapons: []
      -Arrest for Warrant: []
      -
      -Operating Mode: []
      -Report Arrests: []
      -Auto Patrol: []"}, - -"[src.idcheck ? "Yes" : "No"]", -"[weaponscheck ? "Yes" : "No"]", -"[src.check_records ? "Yes" : "No"]", -"[src.arrest_type ? "Detain" : "Arrest"]", -"[src.declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) - else - dat += text({"
      -Auto Patrol: []"}, - -"[auto_patrol ? "On" : "Off"]" ) - - - user << browse("Securitron v2.5 controls[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/bot/ed209/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(lasercolor && (istype(usr,/mob/living/carbon/human))) - var/mob/living/carbon/human/H = usr - if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it - return - else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - if ((href_list["power"]) && (src.allowed(usr))) - if (src.on) - turn_off() - else - turn_on() - return - - switch(href_list["operation"]) - if ("idcheck") - src.idcheck = !src.idcheck - src.updateUsrDialog() - if("weaponscheck") - weaponscheck = !weaponscheck - updateUsrDialog() - if ("ignorerec") - src.check_records = !src.check_records - src.updateUsrDialog() - if ("switchmode") - src.arrest_type = !src.arrest_type - src.updateUsrDialog() - if("patrol") - auto_patrol = !auto_patrol - mode = SECBOT_IDLE - updateUsrDialog() - if("declarearrests") - src.declare_arrests = !src.declare_arrests - src.updateUsrDialog() - -/obj/machinery/bot/ed209/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user) && !open && !emagged) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked" : "unlocked"].") - else - if(emagged) - to_chat(user, "ERROR") - if(open) - to_chat(user, "Please close the access panel before locking it.") - else - to_chat(user, "Access denied.") - else - ..() - if (!istype(W, /obj/item/weapon/screwdriver) && (!src.target)) - if(hasvar(W,"force") && W.force)//If force is defined and non-zero - threatlevel = user.assess_threat(src) - threatlevel +=6 - if(threatlevel > 0) - src.target = user - if(lasercolor)//To make up for the fact that lasertag bots don't hunt - src.shootAt(user) - src.mode = SECBOT_HUNT - -/obj/machinery/bot/ed209/Emag(mob/user as mob) - ..() - if(open && !locked) - if(user) to_chat(user, "You short out [src]'s target assessment circuits.") - spawn(0) - for(var/mob/O in hearers(src, null)) - O.show_message("[src] buzzes oddly!", 1) - src.target = null - if(user) src.oldtarget_name = user.name - src.last_found = world.time - src.anchored = 0 - src.emagged = 2 - src.on = 1 - src.icon_state = "[lasercolor]ed209[src.on]" - src.projectile = null - mode = SECBOT_IDLE - declare_arrests = 0 - -/obj/machinery/bot/ed209/process() - //set background = 1 - - if (!src.on) - return - var/list/targets = list() - for (var/mob/living/carbon/C in view(12,src)) //Let's find us a target - var/threatlevel = 0 - if ((C.stat) || (C.lying)) - continue - if (istype(C, /mob/living/carbon/human)) - threatlevel = C.assess_threat(src,lasercolor) - 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 - - var/dst = get_dist(src, C) - if ( dst <= 1 || dst > 12) - continue - - targets += C - if (targets.len>0) - var/mob/t = pick(targets) - if (istype(t, /mob/living)) - if ((t.stat!=2) && (t.lying != 1)) - //src.speak("selected target: " + t.real_name) - src.shootAt(t) - switch(mode) - - if(SECBOT_IDLE) // idle - walk_to(src,0) - look_for_perp() // see if any criminals are in range - if(!mode && auto_patrol) // still idle, and set to patrol - mode = SECBOT_START_PATROL // switch to patrol mode - - if(SECBOT_HUNT) // hunting for perp - if(src.lasercolor)//Lasertag bots do not tase or arrest anyone, just patrol and shoot and whatnot - mode = SECBOT_IDLE - return - // if can't reach perp for long enough, go idle - if (src.frustration >= 8) - // for(var/mob/O in hearers(src, null)) -// to_chat(O, "[src] beeps, \"Backup requested! Suspect has evaded arrest.\"") - src.target = null - src.last_found = world.time - src.frustration = 0 - src.mode = 0 - walk_to(src,0) - - if (target) // make sure target exists - if(!istype(target.loc, /turf)) - return - if (get_dist(src, src.target) <= 1) // if right next to perp - playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) - src.icon_state = "[lasercolor]ed209-c" - spawn(2) - src.icon_state = "[lasercolor]ed209[src.on]" - var/mob/living/carbon/M = src.target - var/maxstuns = 4 - if (istype(M, /mob/living/carbon/human)) - if (M.stuttering < 10 && (!(M_HULK in M.mutations)) /*&& (!istype(M:wear_suit, /obj/item/clothing/suit/judgerobe))*/) - M.stuttering = 10 - M.Stun(10) - M.Weaken(10) - else - M.Weaken(10) - M.stuttering = 10 - M.Stun(10) - maxstuns-- - if (maxstuns <= 0) - target = null - - if(declare_arrests) - var/area/location = get_area(src) - broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) - visible_message("[src.target] has been stunned by [src]!") - - mode = SECBOT_PREP_ARREST - src.anchored = 1 - src.target_lastloc = M.loc - return - - else // not next to perp - var/turf/olddist = get_dist(src, src.target) - walk_to(src, src.target,1,4) - if ((get_dist(src, src.target)) >= (olddist)) - src.frustration++ - else - src.frustration = 0 - - if(SECBOT_PREP_ARREST) // preparing to arrest target - if(src.lasercolor) - mode = SECBOT_IDLE - return - if (!target) - mode = SECBOT_IDLE - src.anchored = 0 - return - // see if he got away - if ((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:weakened < 2)) - src.anchored = 0 - mode = SECBOT_HUNT - return - - if(istype(src.target,/mob/living/carbon)) - if (!src.target.handcuffed && !src.arrest_type) - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) - mode = SECBOT_ARREST - visible_message("[src] is trying to put handcuffs on [src.target]!") - - spawn(60) - if (get_dist(src, src.target) <= 1) - if (src.target.handcuffed) - return - - if(istype(src.target,/mob/living/carbon)) - src.target.handcuffed = new /obj/item/weapon/handcuffs(src.target) - target.update_inv_handcuffed() //update handcuff overlays - - mode = SECBOT_IDLE - src.target = null - src.anchored = 0 - src.last_found = world.time - src.frustration = 0 - - // playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) - // var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.") - // src.speak(arrest_message) - else - mode = SECBOT_IDLE - src.target = null - src.anchored = 0 - src.last_found = world.time - src.frustration = 0 - - if(SECBOT_ARREST) // arresting - if(src.lasercolor) - mode = SECBOT_IDLE - return - if (!target || src.target.handcuffed) - src.anchored = 0 - mode = SECBOT_IDLE - return - - - if(SECBOT_START_PATROL) // start a patrol - if(!path || !istype(path)) - path = list() - if(path.len > 0 && patrol_target) // have a valid path, so just resume - mode = SECBOT_PATROL - return - - else if(patrol_target) // has patrol target already - spawn(0) - calc_path() // so just find a route to it - if(path.len == 0) - patrol_target = 0 - return - mode = SECBOT_PATROL - - - else // no patrol target, so need a new one - find_patrol_target() - speak("Engaging patrol mode.") - - - if(SECBOT_PATROL) // patrol mode - patrol_step() - spawn(5) - if(mode == SECBOT_PATROL) - patrol_step() - - if(SECBOT_SUMMON) // summoned to PDA - patrol_step() - spawn(4) - if(mode == SECBOT_SUMMON) - patrol_step() - sleep(4) - patrol_step() - - return - - -// perform a single patrol step - -/obj/machinery/bot/ed209/proc/patrol_step() - - - if(loc == patrol_target) // reached target - at_patrol_target() - return - if(!path || !istype(path)) path = list() - else if(path.len > 0 && patrol_target) // valid path - - var/turf/next = path[1] - if(next == loc) - path -= next - return - - - if(istype( next, /turf/simulated)) - - var/moved = step_towards(src, next) // attempt to move - if(moved) // successful move - blockcount = 0 - path -= loc - - look_for_perp() - if(lasercolor) - sleep(20) - else // failed to move - - blockcount++ - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - - spawn(2) - calc_path(next) - if(path.len == 0) - find_patrol_target() - else - blockcount = 0 - - return - - return - - else // not a valid turf - mode = SECBOT_IDLE - return - - else // no path, so calculate new one - mode = SECBOT_START_PATROL - - -// finds a new patrol target -/obj/machinery/bot/ed209/proc/find_patrol_target() - send_status() - if(awaiting_beacon) // awaiting beacon response - awaiting_beacon++ - if(awaiting_beacon > 5) // wait 5 secs for beacon response - find_nearest_beacon() // then go to nearest instead - return - - if(next_destination) - set_destination(next_destination) - else - find_nearest_beacon() - return - - -// finds the nearest beacon to self -// signals all beacons matching the patrol code -/obj/machinery/bot/ed209/proc/find_nearest_beacon() - nearest_beacon = null - new_destination = "__nearest__" - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - spawn(10) - awaiting_beacon = 0 - if(nearest_beacon) - set_destination(nearest_beacon) - else - auto_patrol = 0 - mode = SECBOT_IDLE - speak("Disengaging patrol mode.") - send_status() - - -/obj/machinery/bot/ed209/proc/at_patrol_target() - find_patrol_target() - return - - -// sets the current destination -// signals all beacons matching the patrol code -// beacons will return a signal giving their locations -/obj/machinery/bot/ed209/proc/set_destination(var/new_dest) - new_destination = new_dest - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - - -// receive a radio signal -// used for beacon reception - -/obj/machinery/bot/ed209/receive_signal(datum/signal/signal) - - if(!on) - return - - /* - to_chat(world, "rec signal: [signal.source]") - for(var/x in signal.data) - to_chat(world, "* [x] = [signal.data[x]]") - */ - - var/recv = signal.data["command"] - // process all-bot input - if(recv=="bot_status") - send_status() - - // check to see if we are the commanded bot - if(signal.data["active"] == src) - // process control input - switch(recv) - if("stop") - mode = SECBOT_IDLE - auto_patrol = 0 - return - - if("go") - mode = SECBOT_IDLE - auto_patrol = 1 - return - - if("summon") - patrol_target = signal.data["target"] - next_destination = destination - destination = null - awaiting_beacon = 0 - mode = SECBOT_SUMMON - calc_path() - speak("Responding.") - - return - - - - // receive response from beacon - recv = signal.data["beacon"] - var/valid = signal.data["patrol"] - if(!recv || !valid) - return - - if(recv == new_destination) // if the recvd beacon location matches the set destination - // the we will navigate there - destination = new_destination - patrol_target = signal.source.loc - next_destination = signal.data["next_patrol"] - awaiting_beacon = 0 - - // if looking for nearest beacon - else if(new_destination == "__nearest__") - var/dist = get_dist(src,signal.source.loc) - if(nearest_beacon) - - // note we ignore the beacon we are located at - if(dist>1 && dist 1) - nearest_beacon = recv - nearest_beacon_loc = signal.source.loc - return - - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/ed209/proc/post_signal(var/freq, var/key, var/value) - post_signal_multiple(freq, list("[key]" = value) ) - -// send a radio signal with multiple data key/values -/obj/machinery/bot/ed209/proc/post_signal_multiple(var/freq, var/list/keyval) - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] -// to_chat(world, "sent [key],[keyval[key]] on [freq]") - signal.data = keyval - if (signal.data["findbeacon"]) - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - else if (signal.data["type"] == "secbot") - frequency.post_signal(src, signal, filter = RADIO_SECBOT) - else - frequency.post_signal(src, signal) - -// signals bot status etc. to controller -/obj/machinery/bot/ed209/proc/send_status() - var/list/kv = list( - "type" = "secbot", - "name" = name, - "loca" = loc.loc, // area - "mode" = mode, - ) - post_signal_multiple(control_freq, kv) - - - -// calculates a path to the current destination -// given an optional turf to avoid -/obj/machinery/bot/ed209/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) - if (!src.path) src.path = list() - - -// look for a criminal in view of the bot - -/obj/machinery/bot/ed209/proc/look_for_perp() - if(src.disabled) - return - src.anchored = 0 - src.threatlevel = 0 - for (var/mob/living/carbon/C in view(12,src)) //Let's find us a criminal - if ((C.stat) || (C.handcuffed)) - continue - - if((src.lasercolor) && (C.lying)) - continue//Does not shoot at people lyind down when in lasertag mode, because it's just annoying, and they can fire once they get up. - - if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) - continue - - 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 - - else if (src.threatlevel >= 4) - src.target = C - src.oldtarget_name = C.name - src.speak("Level [src.threatlevel] infraction alert!") - if(!src.lasercolor) - playsound(get_turf(src), pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) - src.visible_message("[src] points at [C.name]!") - mode = SECBOT_HUNT - spawn(0) - process() // ensure bot quickly responds to a perp - break - else - continue - - -//If the security records say to arrest them, arrest them -//Or if they have weapons and aren't security, arrest them. -/obj/machinery/bot/ed209/proc/assess_perp(mob/living/carbon/human/perp as mob) - var/threatcount = 0 - - if(src.emagged == 2) return 10 //Everyone is a criminal! - - if((src.idcheck) || (isnull(perp:wear_id)) || (istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate))) - - if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) - if(!istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 4 - - if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) - if(!istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 4 - - if(istype(perp:belt, /obj/item/weapon/gun) || istype(perp:belt, /obj/item/weapon/melee)) - if(!istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 2 - - if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) - threatcount += 2 - - if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") - threatcount += 2 - -//Agent cards lower threatlevel when normal idchecking is off. - if((perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) && src.idcheck) - threatcount -= 2 - - if(src.lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - threatcount = 0//They will not, however shoot at people who have guns, because it gets really fucking annoying - if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) - threatcount += 4 - if((istype(perp:r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp:l_hand,/obj/item/weapon/gun/energy/laser/redtag))) - threatcount += 4 - if(istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 2 - - if(src.lasercolor == "r") - threatcount = 0 - if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) - threatcount += 4 - if((istype(perp:r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp:l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) - threatcount += 4 - if(istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 2 - - if(src.check_records) - for (var/datum/data/record/E in data_core.general) - var/perpname = perp.name - if(perp.wear_id) - var/obj/item/weapon/card/id/id = perp.wear_id.GetID() - if(id) - perpname = id.registered_name - - if(E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - threatcount = 4 - break - - if((src.idcheck) && (src.allowed(perp)) && !(src.lasercolor)) - threatcount = 0//Corrupt cops cannot exist beep boop - - return threatcount - -/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)) - D.open() - src.frustration = 0 - else if ((istype(M, /mob/living/)) && (!src.anchored)) - src.loc = M:loc - src.frustration = 0 - return - -/* terrible -/obj/machinery/bot/ed209/Bumped(atom/movable/M as mob|obj) - spawn(0) - if (M) - var/turf/T = get_turf(src) - M:loc = T -*/ - -/obj/machinery/bot/ed209/proc/speak(var/message) - visible_message("[src] beeps, \"[message]\"",\ - drugged_message="[src] beeps, \"[pick("I-It's not like I like you or anything... baka!","You're s-so silly!","I-I'm only doing this because you asked me nicely, baka...","S-stop that!","Y-you're embarassing me!")]\"") - return - -/obj/machinery/bot/ed209/explode() - walk_to(src,0) - src.visible_message("[src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - var/obj/item/weapon/ed209_assembly/Sa = new /obj/item/weapon/ed209_assembly(Tsec) - Sa.build_step = 1 - Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") - Sa.created_name = src.name - new /obj/item/device/assembly/prox_sensor(Tsec) - - if(!lasercolor) - var/obj/item/weapon/gun/energy/taser/G = new /obj/item/weapon/gun/energy/taser(Tsec) - G.power_supply.charge = 0 - else if(lasercolor == "b") - var/obj/item/weapon/gun/energy/laser/bluetag/G = new /obj/item/weapon/gun/energy/laser/bluetag(Tsec) - G.power_supply.charge = 0 - else if(lasercolor == "r") - var/obj/item/weapon/gun/energy/laser/redtag/G = new /obj/item/weapon/gun/energy/laser/redtag(Tsec) - G.power_supply.charge = 0 - - if (prob(50)) - new /obj/item/robot_parts/l_leg(Tsec) - if (prob(25)) - new /obj/item/robot_parts/r_leg(Tsec) - if (prob(25))//50% chance for a helmet OR vest - if (prob(50)) - new /obj/item/clothing/head/helmet(Tsec) - else - if(!lasercolor) - new /obj/item/clothing/suit/armor/vest(Tsec) - if(lasercolor == "b") - new /obj/item/clothing/suit/bluetag(Tsec) - if(lasercolor == "r") - new /obj/item/clothing/suit/redtag(Tsec) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - var/obj/effect/decal/cleanable/blood/oil/gib = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) - gib.New(gib.loc) - qdel(src) - - -/obj/machinery/bot/ed209/proc/shootAt(var/mob/target) - if(lastfired && world.time - lastfired < shot_delay) - return - lastfired = world.time - var/turf/T = loc - var/atom/U = (istype(target, /atom/movable) ? target.loc : target) - if ((!( U ) || !( T ))) - return - while(!( istype(U, /turf) )) - U = U.loc - if (!( istype(T, /turf) )) - return - - //if(lastfired && world.time - lastfired < 100) - // playsound(get_turf(src), 'ed209_shoot.ogg', 50, 0) - - if(!projectile) - if(!lasercolor) - if (src.emagged == 2) - projectile = /obj/item/projectile/beam - else - projectile = /obj/item/projectile/energy/electrode - else if(lasercolor == "b") - if (src.emagged == 2) - projectile = /obj/item/projectile/beam/lastertag/omni - else - projectile = /obj/item/projectile/beam/lastertag/blue - else if(lasercolor == "r") - if (src.emagged == 2) - projectile = /obj/item/projectile/beam/lastertag/omni - else - projectile = /obj/item/projectile/beam/lastertag/red - - if (!( istype(U, /turf) )) - return - var/obj/item/projectile/A = new projectile (loc) - A.original = target - A.target = target - A.current = T - A.starting = T - A.yo = U.y - T.y - A.xo = U.x - T.x - spawn() - A.OnFired() - A.process() - return - return - -/obj/machinery/bot/ed209/attack_alien(var/mob/living/carbon/alien/user as mob) - ..() - if (!isalien(target)) - src.target = user - src.mode = SECBOT_HUNT - - -/obj/machinery/bot/ed209/emp_act(severity) - - if(severity==2 && prob(70)) - ..(severity-1) - else - var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.dir = pick(cardinal) - spawn(10) - qdel(pulse2) - var/list/mob/living/carbon/targets = new - for (var/mob/living/carbon/C in view(12,src)) - if (C.stat==2) - continue - targets += C - if(targets.len) - if(prob(50)) - var/mob/toshoot = pick(targets) - if (toshoot) - targets-=toshoot - if (prob(50) && emagged < 2) - emagged = 2 - shootAt(toshoot) - emagged = 0 - else - shootAt(toshoot) - else if(prob(50)) - if(targets.len) - var/mob/toarrest = pick(targets) - if (toarrest) - src.target = toarrest - src.mode = SECBOT_HUNT - - - -/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - - if(istype(W, /obj/item/weapon/pen)) - var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) - if(!t) return - if(!in_range(src, usr) && src.loc != usr) return - created_name = t - return - - switch(build_step) - if(0,1) - if( istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg) ) - if(user.drop_item(W)) - qdel(W) - build_step++ - to_chat(user, "You add the robot leg to [src].") - name = "legs/frame assembly" - if(build_step == 1) - item_state = "ed209_leg" - icon_state = "ed209_leg" - else - item_state = "ed209_legs" - icon_state = "ed209_legs" - - if(2) - if( istype(W, /obj/item/clothing/suit/redtag) ) - lasercolor = "r" - else if( istype(W, /obj/item/clothing/suit/bluetag) ) - lasercolor = "b" - if( lasercolor || istype(W, /obj/item/clothing/suit/armor/vest) ) - if(user.drop_item(W)) - qdel(W) - build_step++ - to_chat(user, "You add the armor to [src].") - name = "vest/legs/frame assembly" - item_state = "[lasercolor]ed209_shell" - icon_state = "[lasercolor]ed209_shell" - - if(3) - if( istype(W, /obj/item/weapon/weldingtool) ) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - build_step++ - name = "shielded frame assembly" - to_chat(user, "You welded the vest to [src].") - if(4) - if( istype(W, /obj/item/clothing/head/helmet) ) - if(user.drop_item(W)) - qdel(W) - build_step++ - to_chat(user, "You add the helmet to [src].") - name = "covered and shielded frame assembly" - item_state = "[lasercolor]ed209_hat" - icon_state = "[lasercolor]ed209_hat" - - if(5) - if( isprox(W) ) - if(user.drop_item(W)) - qdel(W) - build_step++ - to_chat(user, "You add the prox sensor to [src].") - name = "covered, shielded and sensored frame assembly" - item_state = "[lasercolor]ed209_prox" - icon_state = "[lasercolor]ed209_prox" - - if(6) - if( istype(W, /obj/item/stack/cable_coil) ) - var/obj/item/stack/cable_coil/coil = W - var/turf/T = get_turf(user) - to_chat(user, "You start to wire [src]...") - sleep(40) - if(get_turf(user) == T) - coil.use(1) - build_step++ - to_chat(user, "You wire the ED-209 assembly.") - name = "wired ED-209 assembly" - - if(7) - if(!user.drop_item(W)) - return - - switch(lasercolor) - if("b") - if( !istype(W, /obj/item/weapon/gun/energy/laser/bluetag) ) - return - name = "bluetag ED-209 assembly" - if("r") - if( !istype(W, /obj/item/weapon/gun/energy/laser/redtag) ) - return - name = "redtag ED-209 assembly" - if("") - if( !istype(W, /obj/item/weapon/gun/energy/taser) ) - return - name = "taser ED-209 assembly" - else - return - build_step++ - to_chat(user, "You add [W] to [src].") - src.item_state = "[lasercolor]ed209_taser" - src.icon_state = "[lasercolor]ed209_taser" - qdel(W) - - if(8) - if( istype(W, /obj/item/weapon/screwdriver) ) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) - var/turf/T = get_turf(user) - to_chat(user, "Now attaching the gun to the frame...") - sleep(40) - if(get_turf(user) == T) - build_step++ - name = "armed [name]" - to_chat(user, "Taser gun attached.") - - if(9) - if( istype(W, /obj/item/weapon/cell) ) - if(!user.drop_item(W)) - return - - build_step++ - to_chat(user, "You complete the ED-209.") - var/turf/T = get_turf(src) - new /obj/machinery/bot/ed209(T,created_name,lasercolor) - qdel(W) - user.drop_from_inventory(src) - qdel(src) - - -/obj/machinery/bot/ed209/bullet_act(var/obj/item/projectile/Proj) - if((src.lasercolor == "b") && (src.disabled == 0)) - if(istype(Proj, /obj/item/projectile/beam/lastertag/red)) - src.disabled = 1 - //del (Proj) - returnToPool(Proj) - sleep(100) - src.disabled = 0 - else - ..() - else if((src.lasercolor == "r") && (src.disabled == 0)) - if(istype(Proj, /obj/item/projectile/beam/lastertag/blue)) - src.disabled = 1 - //del (Proj) - returnToPool(Proj) - sleep(100) - src.disabled = 0 - else - ..() - else - ..() - -/obj/machinery/bot/ed209/bluetag/New()//If desired, you spawn red and bluetag bots easily - new /obj/machinery/bot/ed209(get_turf(src),null,"b") - qdel(src) - - -/obj/machinery/bot/ed209/redtag/New() - new /obj/machinery/bot/ed209(get_turf(src),null,"r") - qdel(src) - -/obj/machinery/bot/ed209/proc/check_for_weapons(var/obj/item/slot_item) - if(istype(slot_item, /obj/item/weapon/gun) || istype(slot_item, /obj/item/weapon/melee)) - if(!(slot_item.type in safe_weapons)) - return 1 - return 0 - -/obj/machinery/bot/ed209/declare() - var/area/location = get_area(src) - declare_message = "\icon[src] [name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] scumbag [target] in [location]" - ..() +/obj/machinery/bot/ed209 + name = "ED-209 Security Robot" + desc = "A security robot. He looks less than thrilled." + icon = 'icons/obj/aibots.dmi' + icon_state = "ed2090" + layer = 5.0 + density = 1 + anchored = 0 +// weight = 1.0E7 + req_one_access = list(access_security, access_forensics_lockers) + health = 100 + maxhealth = 100 + fire_dam_coeff = 0.7 + brute_dam_coeff = 0.5 + + var/lastfired = 0 + var/shot_delay = 3 //.3 seconds between shots + var/lasercolor = "" + var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag + + //var/lasers = 0 + + var/mob/living/carbon/target + var/oldtarget_name + var/threatlevel = 0 + var/target_lastloc //Loc of target when arrested. + var/last_found //There's a delay + var/frustration = 0 +//var/emagged = 0 //Emagged Secbots view everyone as a criminal + var/check_records = 1 //Does it check security records? + var/arrest_type = 0 //If true, don't handcuff + + var/projectile = null//Holder for projectile type, to avoid so many else if chains + + var/mode = 0 + bot_type = SEC_BOT +#define SECBOT_IDLE 0 // idle +#define SECBOT_HUNT 1 // found target, hunting +#define SECBOT_PREP_ARREST 2 // at target, preparing to arrest +#define SECBOT_ARREST 3 // arresting target +#define SECBOT_START_PATROL 4 // start patrol +#define SECBOT_PATROL 5 // patrolling +#define SECBOT_SUMMON 6 // summoned by PDA + + var/auto_patrol = 0 // set to make bot automatically patrol + + var/beacon_freq = 1445 // navigation beacon frequency + var/control_freq = 1447 // bot control frequency + + + var/turf/patrol_target // this is turf to navigate to (location of beacon) + var/new_destination // pending new destination (waiting for beacon response) + var/destination // destination description tag + var/next_destination // the next destination in the patrol route + var/list/path = new // list of path turfs + + var/blockcount = 0 //number of times retried a blocked path + var/awaiting_beacon = 0 // count of pticks awaiting a beacon response + + var/nearest_beacon // the nearest beacon's tag + var/turf/nearest_beacon_loc // the nearest beacon's location + var/declare_arrests = 1 //When making an arrest, should it notify everyone wearing sechuds? + var/idcheck = 1 //If true, arrest people with no IDs + var/weaponscheck = 1 //If true, arrest people for weapons if they don't have access + //List of weapons that secbots will not arrest for + var/safe_weapons = list( + /obj/item/weapon/gun/energy/laser/bluetag, + /obj/item/weapon/gun/energy/laser/redtag, + /obj/item/weapon/gun/energy/laser/practice, + /obj/item/weapon/gun/hookshot, + ) + + +/obj/item/weapon/ed209_assembly + name = "ED-209 assembly" + desc = "Some sort of bizarre assembly." + icon = 'icons/obj/aibots.dmi' + icon_state = "ed209_frame" + item_state = "ed209_frame" + var/build_step = 0 + var/created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess + var/lasercolor = "" + + +/obj/machinery/bot/ed209/New(loc,created_name,created_lasercolor) + ..() + if(created_name) name = created_name + if(created_lasercolor) lasercolor = created_lasercolor + src.icon_state = "[lasercolor]ed209[src.on]" + spawn(3) + src.botcard = new /obj/item/weapon/card/id(src) + var/datum/job/detective/J = new/datum/job/detective + src.botcard.access = J.get_access() + + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + if(lasercolor) + shot_delay = 6//Longer shot delay because JESUS CHRIST + check_records = 0//Don't actively target people set to arrest + arrest_type = 1//Don't even try to cuff + req_access = list(access_maint_tunnels) + arrest_type = 1 + if((lasercolor == "b") && (name == "ED-209 Security Robot"))//Picks a name if there isn't already a custome one + name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT") + if((lasercolor == "r") && (name == "ED-209 Security Robot")) + name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") + +/obj/machinery/bot/ed209/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover,/obj/machinery/bot/ed209)) + return 1 + else + return ..() + +/obj/machinery/bot/ed209/turn_on() + . = ..() + src.icon_state = "[lasercolor]ed209[src.on]" + src.mode = SECBOT_IDLE + src.updateUsrDialog() + +/obj/machinery/bot/ed209/turn_off() + ..() + src.target = null + src.oldtarget_name = null + src.anchored = 0 + src.mode = SECBOT_IDLE + walk_to(src,0) + src.icon_state = "[lasercolor]ed209[src.on]" + src.updateUsrDialog() + +/obj/machinery/bot/ed209/attack_hand(mob/user as mob) + . = ..() + if (.) + return + var/dat + + dat += text({" +Automatic Security Unit v2.5

      +Status: []
      +Behaviour controls are [src.locked ? "locked" : "unlocked"]
      +Maintenance panel panel is [src.open ? "opened" : "closed"]"}, + +"[src.on ? "On" : "Off"]" ) + + if(!src.locked || issilicon(user)) + if(!lasercolor) + dat += text({"
      +Arrest for No ID: []
      +Arrest for Unauthorized Weapons: []
      +Arrest for Warrant: []
      +
      +Operating Mode: []
      +Report Arrests: []
      +Auto Patrol: []"}, + +"[src.idcheck ? "Yes" : "No"]", +"[weaponscheck ? "Yes" : "No"]", +"[src.check_records ? "Yes" : "No"]", +"[src.arrest_type ? "Detain" : "Arrest"]", +"[src.declare_arrests ? "Yes" : "No"]", +"[auto_patrol ? "On" : "Off"]" ) + else + dat += text({"
      +Auto Patrol: []"}, + +"[auto_patrol ? "On" : "Off"]" ) + + + user << browse("Securitron v2.5 controls[dat]", "window=autosec") + onclose(user, "autosec") + return + +/obj/machinery/bot/ed209/Topic(href, href_list) + if (..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if(lasercolor && (istype(usr,/mob/living/carbon/human))) + var/mob/living/carbon/human/H = usr + if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it + return + else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) + return + if ((href_list["power"]) && (src.allowed(usr))) + if (src.on) + turn_off() + else + turn_on() + return + + switch(href_list["operation"]) + if ("idcheck") + src.idcheck = !src.idcheck + src.updateUsrDialog() + if("weaponscheck") + weaponscheck = !weaponscheck + updateUsrDialog() + if ("ignorerec") + src.check_records = !src.check_records + src.updateUsrDialog() + if ("switchmode") + src.arrest_type = !src.arrest_type + src.updateUsrDialog() + if("patrol") + auto_patrol = !auto_patrol + mode = SECBOT_IDLE + updateUsrDialog() + if("declarearrests") + src.declare_arrests = !src.declare_arrests + src.updateUsrDialog() + +/obj/machinery/bot/ed209/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (src.allowed(user) && !open && !emagged) + src.locked = !src.locked + to_chat(user, "Controls are now [src.locked ? "locked" : "unlocked"].") + else + if(emagged) + to_chat(user, "ERROR") + if(open) + to_chat(user, "Please close the access panel before locking it.") + else + to_chat(user, "Access denied.") + else + ..() + if (!istype(W, /obj/item/weapon/screwdriver) && (!src.target)) + if(hasvar(W,"force") && W.force)//If force is defined and non-zero + threatlevel = user.assess_threat(src) + threatlevel +=6 + if(threatlevel > 0) + src.target = user + if(lasercolor)//To make up for the fact that lasertag bots don't hunt + src.shootAt(user) + src.mode = SECBOT_HUNT + +/obj/machinery/bot/ed209/Emag(mob/user as mob) + ..() + if(open && !locked) + if(user) to_chat(user, "You short out [src]'s target assessment circuits.") + spawn(0) + for(var/mob/O in hearers(src, null)) + O.show_message("[src] buzzes oddly!", 1) + src.target = null + if(user) src.oldtarget_name = user.name + src.last_found = world.time + src.anchored = 0 + src.emagged = 2 + src.on = 1 + src.icon_state = "[lasercolor]ed209[src.on]" + src.projectile = null + mode = SECBOT_IDLE + declare_arrests = 0 + +/obj/machinery/bot/ed209/process() + //set background = 1 + + if (!src.on) + return + var/list/targets = list() + for (var/mob/living/carbon/C in view(12,src)) //Let's find us a target + var/threatlevel = 0 + if ((C.stat) || (C.lying)) + continue + if (istype(C, /mob/living/carbon/human)) + threatlevel = C.assess_threat(src,lasercolor) + 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 + + var/dst = get_dist(src, C) + if ( dst <= 1 || dst > 12) + continue + + targets += C + if (targets.len>0) + var/mob/t = pick(targets) + if (istype(t, /mob/living)) + if ((t.stat!=2) && (t.lying != 1)) + //src.speak("selected target: " + t.real_name) + src.shootAt(t) + switch(mode) + + if(SECBOT_IDLE) // idle + walk_to(src,0) + look_for_perp() // see if any criminals are in range + if(!mode && auto_patrol) // still idle, and set to patrol + mode = SECBOT_START_PATROL // switch to patrol mode + + if(SECBOT_HUNT) // hunting for perp + if(src.lasercolor)//Lasertag bots do not tase or arrest anyone, just patrol and shoot and whatnot + mode = SECBOT_IDLE + return + // if can't reach perp for long enough, go idle + if (src.frustration >= 8) + // for(var/mob/O in hearers(src, null)) +// to_chat(O, "[src] beeps, \"Backup requested! Suspect has evaded arrest.\"") + src.target = null + src.last_found = world.time + src.frustration = 0 + src.mode = 0 + walk_to(src,0) + + if (target) // make sure target exists + if(!istype(target.loc, /turf)) + return + if (get_dist(src, src.target) <= 1) // if right next to perp + playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) + src.icon_state = "[lasercolor]ed209-c" + spawn(2) + src.icon_state = "[lasercolor]ed209[src.on]" + var/mob/living/carbon/M = src.target + var/maxstuns = 4 + if (istype(M, /mob/living/carbon/human)) + if (M.stuttering < 10 && (!(M_HULK in M.mutations)) /*&& (!istype(M:wear_suit, /obj/item/clothing/suit/judgerobe))*/) + M.stuttering = 10 + M.Stun(10) + M.Weaken(10) + else + M.Weaken(10) + M.stuttering = 10 + M.Stun(10) + maxstuns-- + if (maxstuns <= 0) + target = null + + if(declare_arrests) + var/area/location = get_area(src) + broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) + visible_message("[src.target] has been stunned by [src]!") + + mode = SECBOT_PREP_ARREST + src.anchored = 1 + src.target_lastloc = M.loc + return + + else // not next to perp + var/turf/olddist = get_dist(src, src.target) + walk_to(src, src.target,1,4) + if ((get_dist(src, src.target)) >= (olddist)) + src.frustration++ + else + src.frustration = 0 + + if(SECBOT_PREP_ARREST) // preparing to arrest target + if(src.lasercolor) + mode = SECBOT_IDLE + return + if (!target) + mode = SECBOT_IDLE + src.anchored = 0 + return + // see if he got away + if ((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:weakened < 2)) + src.anchored = 0 + mode = SECBOT_HUNT + return + + if(istype(src.target,/mob/living/carbon)) + if (!src.target.handcuffed && !src.arrest_type) + playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + mode = SECBOT_ARREST + visible_message("[src] is trying to put handcuffs on [src.target]!") + + spawn(60) + if (get_dist(src, src.target) <= 1) + if (src.target.handcuffed) + return + + if(istype(src.target,/mob/living/carbon)) + src.target.handcuffed = new /obj/item/weapon/handcuffs(src.target) + target.update_inv_handcuffed() //update handcuff overlays + + mode = SECBOT_IDLE + src.target = null + src.anchored = 0 + src.last_found = world.time + src.frustration = 0 + + // playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + // var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.") + // src.speak(arrest_message) + else + mode = SECBOT_IDLE + src.target = null + src.anchored = 0 + src.last_found = world.time + src.frustration = 0 + + if(SECBOT_ARREST) // arresting + if(src.lasercolor) + mode = SECBOT_IDLE + return + if (!target || src.target.handcuffed) + src.anchored = 0 + mode = SECBOT_IDLE + return + + + if(SECBOT_START_PATROL) // start a patrol + if(!path || !istype(path)) + path = list() + if(path.len > 0 && patrol_target) // have a valid path, so just resume + mode = SECBOT_PATROL + return + + else if(patrol_target) // has patrol target already + spawn(0) + calc_path() // so just find a route to it + if(path.len == 0) + patrol_target = 0 + return + mode = SECBOT_PATROL + + + else // no patrol target, so need a new one + find_patrol_target() + speak("Engaging patrol mode.") + + + if(SECBOT_PATROL) // patrol mode + patrol_step() + spawn(5) + if(mode == SECBOT_PATROL) + patrol_step() + + if(SECBOT_SUMMON) // summoned to PDA + patrol_step() + spawn(4) + if(mode == SECBOT_SUMMON) + patrol_step() + sleep(4) + patrol_step() + + return + + +// perform a single patrol step + +/obj/machinery/bot/ed209/proc/patrol_step() + + + if(loc == patrol_target) // reached target + at_patrol_target() + return + if(!path || !istype(path)) path = list() + else if(path.len > 0 && patrol_target) // valid path + + var/turf/next = path[1] + if(next == loc) + path -= next + return + + + if(istype( next, /turf/simulated)) + + var/moved = step_towards(src, next) // attempt to move + if(moved) // successful move + blockcount = 0 + path -= loc + + look_for_perp() + if(lasercolor) + sleep(20) + else // failed to move + + blockcount++ + + if(blockcount > 5) // attempt 5 times before recomputing + // find new path excluding blocked turf + + spawn(2) + calc_path(next) + if(path.len == 0) + find_patrol_target() + else + blockcount = 0 + + return + + return + + else // not a valid turf + mode = SECBOT_IDLE + return + + else // no path, so calculate new one + mode = SECBOT_START_PATROL + + +// finds a new patrol target +/obj/machinery/bot/ed209/proc/find_patrol_target() + send_status() + if(awaiting_beacon) // awaiting beacon response + awaiting_beacon++ + if(awaiting_beacon > 5) // wait 5 secs for beacon response + find_nearest_beacon() // then go to nearest instead + return + + if(next_destination) + set_destination(next_destination) + else + find_nearest_beacon() + return + + +// finds the nearest beacon to self +// signals all beacons matching the patrol code +/obj/machinery/bot/ed209/proc/find_nearest_beacon() + nearest_beacon = null + new_destination = "__nearest__" + post_signal(beacon_freq, "findbeacon", "patrol") + awaiting_beacon = 1 + spawn(10) + awaiting_beacon = 0 + if(nearest_beacon) + set_destination(nearest_beacon) + else + auto_patrol = 0 + mode = SECBOT_IDLE + speak("Disengaging patrol mode.") + send_status() + + +/obj/machinery/bot/ed209/proc/at_patrol_target() + find_patrol_target() + return + + +// sets the current destination +// signals all beacons matching the patrol code +// beacons will return a signal giving their locations +/obj/machinery/bot/ed209/proc/set_destination(var/new_dest) + new_destination = new_dest + post_signal(beacon_freq, "findbeacon", "patrol") + awaiting_beacon = 1 + + +// receive a radio signal +// used for beacon reception + +/obj/machinery/bot/ed209/receive_signal(datum/signal/signal) + + if(!on) + return + + /* + to_chat(world, "rec signal: [signal.source]") + for(var/x in signal.data) + to_chat(world, "* [x] = [signal.data[x]]") + */ + + var/recv = signal.data["command"] + // process all-bot input + if(recv=="bot_status") + send_status() + + // check to see if we are the commanded bot + if(signal.data["active"] == src) + // process control input + switch(recv) + if("stop") + mode = SECBOT_IDLE + auto_patrol = 0 + return + + if("go") + mode = SECBOT_IDLE + auto_patrol = 1 + return + + if("summon") + patrol_target = signal.data["target"] + next_destination = destination + destination = null + awaiting_beacon = 0 + mode = SECBOT_SUMMON + calc_path() + speak("Responding.") + + return + + + + // receive response from beacon + recv = signal.data["beacon"] + var/valid = signal.data["patrol"] + if(!recv || !valid) + return + + if(recv == new_destination) // if the recvd beacon location matches the set destination + // the we will navigate there + destination = new_destination + patrol_target = signal.source.loc + next_destination = signal.data["next_patrol"] + awaiting_beacon = 0 + + // if looking for nearest beacon + else if(new_destination == "__nearest__") + var/dist = get_dist(src,signal.source.loc) + if(nearest_beacon) + + // note we ignore the beacon we are located at + if(dist>1 && dist 1) + nearest_beacon = recv + nearest_beacon_loc = signal.source.loc + return + + +// send a radio signal with a single data key/value pair +/obj/machinery/bot/ed209/proc/post_signal(var/freq, var/key, var/value) + post_signal_multiple(freq, list("[key]" = value) ) + +// send a radio signal with multiple data key/values +/obj/machinery/bot/ed209/proc/post_signal_multiple(var/freq, var/list/keyval) + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + //for(var/key in keyval) + // signal.data[key] = keyval[key] +// to_chat(world, "sent [key],[keyval[key]] on [freq]") + signal.data = keyval + if (signal.data["findbeacon"]) + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + else if (signal.data["type"] == "secbot") + frequency.post_signal(src, signal, filter = RADIO_SECBOT) + else + frequency.post_signal(src, signal) + +// signals bot status etc. to controller +/obj/machinery/bot/ed209/proc/send_status() + var/list/kv = list( + "type" = "secbot", + "name" = name, + "loca" = loc.loc, // area + "mode" = mode, + ) + post_signal_multiple(control_freq, kv) + + + +// calculates a path to the current destination +// given an optional turf to avoid +/obj/machinery/bot/ed209/proc/calc_path(var/turf/avoid = null) + src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) + if (!src.path) src.path = list() + + +// look for a criminal in view of the bot + +/obj/machinery/bot/ed209/proc/look_for_perp() + if(src.disabled) + return + src.anchored = 0 + src.threatlevel = 0 + for (var/mob/living/carbon/C in view(12,src)) //Let's find us a criminal + if ((C.stat) || (C.handcuffed)) + continue + + if((src.lasercolor) && (C.lying)) + continue//Does not shoot at people lyind down when in lasertag mode, because it's just annoying, and they can fire once they get up. + + if ((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) + continue + + 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 + + else if (src.threatlevel >= 4) + src.target = C + src.oldtarget_name = C.name + src.speak("Level [src.threatlevel] infraction alert!") + if(!src.lasercolor) + playsound(get_turf(src), pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) + src.visible_message("[src] points at [C.name]!") + mode = SECBOT_HUNT + spawn(0) + process() // ensure bot quickly responds to a perp + break + else + continue + + +//If the security records say to arrest them, arrest them +//Or if they have weapons and aren't security, arrest them. +/obj/machinery/bot/ed209/proc/assess_perp(mob/living/carbon/human/perp as mob) + var/threatcount = 0 + + if(src.emagged == 2) return 10 //Everyone is a criminal! + + if((src.idcheck) || (isnull(perp:wear_id)) || (istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate))) + + if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) + if(!istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/practice)) + threatcount += 4 + + if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) + if(!istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/practice)) + threatcount += 4 + + if(istype(perp:belt, /obj/item/weapon/gun) || istype(perp:belt, /obj/item/weapon/melee)) + if(!istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/practice)) + threatcount += 2 + + if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) + threatcount += 2 + + if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") + threatcount += 2 + +//Agent cards lower threatlevel when normal idchecking is off. + if((perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) && src.idcheck) + threatcount -= 2 + + if(src.lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve + threatcount = 0//They will not, however shoot at people who have guns, because it gets really fucking annoying + if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) + threatcount += 4 + if((istype(perp:r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp:l_hand,/obj/item/weapon/gun/energy/laser/redtag))) + threatcount += 4 + if(istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 2 + + if(src.lasercolor == "r") + threatcount = 0 + if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) + threatcount += 4 + if((istype(perp:r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp:l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + threatcount += 4 + if(istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 2 + + if(src.check_records) + for (var/datum/data/record/E in data_core.general) + var/perpname = perp.name + if(perp.wear_id) + var/obj/item/weapon/card/id/id = perp.wear_id.GetID() + if(id) + perpname = id.registered_name + + if(E.fields["name"] == perpname) + for (var/datum/data/record/R in data_core.security) + if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) + threatcount = 4 + break + + if((src.idcheck) && (src.allowed(perp)) && !(src.lasercolor)) + threatcount = 0//Corrupt cops cannot exist beep boop + + return threatcount + +/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)) + D.open() + src.frustration = 0 + else if ((istype(M, /mob/living/)) && (!src.anchored)) + src.loc = M:loc + src.frustration = 0 + return + +/* terrible +/obj/machinery/bot/ed209/Bumped(atom/movable/M as mob|obj) + spawn(0) + if (M) + var/turf/T = get_turf(src) + M:loc = T +*/ + +/obj/machinery/bot/ed209/proc/speak(var/message) + visible_message("[src] beeps, \"[message]\"",\ + drugged_message="[src] beeps, \"[pick("I-It's not like I like you or anything... baka!","You're s-so silly!","I-I'm only doing this because you asked me nicely, baka...","S-stop that!","Y-you're embarassing me!")]\"") + return + +/obj/machinery/bot/ed209/explode() + walk_to(src,0) + src.visible_message("[src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + var/obj/item/weapon/ed209_assembly/Sa = new /obj/item/weapon/ed209_assembly(Tsec) + Sa.build_step = 1 + Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") + Sa.created_name = src.name + new /obj/item/device/assembly/prox_sensor(Tsec) + + if(!lasercolor) + var/obj/item/weapon/gun/energy/taser/G = new /obj/item/weapon/gun/energy/taser(Tsec) + G.power_supply.charge = 0 + else if(lasercolor == "b") + var/obj/item/weapon/gun/energy/laser/bluetag/G = new /obj/item/weapon/gun/energy/laser/bluetag(Tsec) + G.power_supply.charge = 0 + else if(lasercolor == "r") + var/obj/item/weapon/gun/energy/laser/redtag/G = new /obj/item/weapon/gun/energy/laser/redtag(Tsec) + G.power_supply.charge = 0 + + if (prob(50)) + new /obj/item/robot_parts/l_leg(Tsec) + if (prob(25)) + new /obj/item/robot_parts/r_leg(Tsec) + if (prob(25))//50% chance for a helmet OR vest + if (prob(50)) + new /obj/item/clothing/head/helmet(Tsec) + else + if(!lasercolor) + new /obj/item/clothing/suit/armor/vest(Tsec) + if(lasercolor == "b") + new /obj/item/clothing/suit/bluetag(Tsec) + if(lasercolor == "r") + new /obj/item/clothing/suit/redtag(Tsec) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + var/obj/effect/decal/cleanable/blood/oil/gib = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) + gib.New(gib.loc) + qdel(src) + + +/obj/machinery/bot/ed209/proc/shootAt(var/mob/target) + if(lastfired && world.time - lastfired < shot_delay) + return + lastfired = world.time + var/turf/T = loc + var/atom/U = (istype(target, /atom/movable) ? target.loc : target) + if ((!( U ) || !( T ))) + return + while(!( istype(U, /turf) )) + U = U.loc + if (!( istype(T, /turf) )) + return + + //if(lastfired && world.time - lastfired < 100) + // playsound(get_turf(src), 'ed209_shoot.ogg', 50, 0) + + if(!projectile) + if(!lasercolor) + if (src.emagged == 2) + projectile = /obj/item/projectile/beam + else + projectile = /obj/item/projectile/energy/electrode + else if(lasercolor == "b") + if (src.emagged == 2) + projectile = /obj/item/projectile/beam/lastertag/omni + else + projectile = /obj/item/projectile/beam/lastertag/blue + else if(lasercolor == "r") + if (src.emagged == 2) + projectile = /obj/item/projectile/beam/lastertag/omni + else + projectile = /obj/item/projectile/beam/lastertag/red + + if (!( istype(U, /turf) )) + return + var/obj/item/projectile/A = new projectile (loc) + A.original = target + A.target = target + A.current = T + A.starting = T + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn() + A.OnFired() + A.process() + return + return + +/obj/machinery/bot/ed209/attack_alien(var/mob/living/carbon/alien/user as mob) + ..() + if (!isalien(target)) + src.target = user + src.mode = SECBOT_HUNT + + +/obj/machinery/bot/ed209/emp_act(severity) + + if(severity==2 && prob(70)) + ..(severity-1) + else + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + spawn(10) + qdel(pulse2) + var/list/mob/living/carbon/targets = new + for (var/mob/living/carbon/C in view(12,src)) + if (C.stat==2) + continue + targets += C + if(targets.len) + if(prob(50)) + var/mob/toshoot = pick(targets) + if (toshoot) + targets-=toshoot + if (prob(50) && emagged < 2) + emagged = 2 + shootAt(toshoot) + emagged = 0 + else + shootAt(toshoot) + else if(prob(50)) + if(targets.len) + var/mob/toarrest = pick(targets) + if (toarrest) + src.target = toarrest + src.mode = SECBOT_HUNT + + + +/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + + if(istype(W, /obj/item/weapon/pen)) + var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) + if(!t) return + if(!in_range(src, usr) && src.loc != usr) return + created_name = t + return + + switch(build_step) + if(0,1) + if( istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg) ) + if(user.drop_item(W)) + qdel(W) + build_step++ + to_chat(user, "You add the robot leg to [src].") + name = "legs/frame assembly" + if(build_step == 1) + item_state = "ed209_leg" + icon_state = "ed209_leg" + else + item_state = "ed209_legs" + icon_state = "ed209_legs" + + if(2) + if( istype(W, /obj/item/clothing/suit/redtag) ) + lasercolor = "r" + else if( istype(W, /obj/item/clothing/suit/bluetag) ) + lasercolor = "b" + if( lasercolor || istype(W, /obj/item/clothing/suit/armor/vest) ) + if(user.drop_item(W)) + qdel(W) + build_step++ + to_chat(user, "You add the armor to [src].") + name = "vest/legs/frame assembly" + item_state = "[lasercolor]ed209_shell" + icon_state = "[lasercolor]ed209_shell" + + if(3) + if( istype(W, /obj/item/weapon/weldingtool) ) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + build_step++ + name = "shielded frame assembly" + to_chat(user, "You welded the vest to [src].") + if(4) + if( istype(W, /obj/item/clothing/head/helmet) ) + if(user.drop_item(W)) + qdel(W) + build_step++ + to_chat(user, "You add the helmet to [src].") + name = "covered and shielded frame assembly" + item_state = "[lasercolor]ed209_hat" + icon_state = "[lasercolor]ed209_hat" + + if(5) + if( isprox(W) ) + if(user.drop_item(W)) + qdel(W) + build_step++ + to_chat(user, "You add the prox sensor to [src].") + name = "covered, shielded and sensored frame assembly" + item_state = "[lasercolor]ed209_prox" + icon_state = "[lasercolor]ed209_prox" + + if(6) + if( istype(W, /obj/item/stack/cable_coil) ) + var/obj/item/stack/cable_coil/coil = W + var/turf/T = get_turf(user) + to_chat(user, "You start to wire [src]...") + sleep(40) + if(get_turf(user) == T) + coil.use(1) + build_step++ + to_chat(user, "You wire the ED-209 assembly.") + name = "wired ED-209 assembly" + + if(7) + if(!user.drop_item(W)) + return + + switch(lasercolor) + if("b") + if( !istype(W, /obj/item/weapon/gun/energy/laser/bluetag) ) + return + name = "bluetag ED-209 assembly" + if("r") + if( !istype(W, /obj/item/weapon/gun/energy/laser/redtag) ) + return + name = "redtag ED-209 assembly" + if("") + if( !istype(W, /obj/item/weapon/gun/energy/taser) ) + return + name = "taser ED-209 assembly" + else + return + build_step++ + to_chat(user, "You add [W] to [src].") + src.item_state = "[lasercolor]ed209_taser" + src.icon_state = "[lasercolor]ed209_taser" + qdel(W) + + if(8) + if( istype(W, /obj/item/weapon/screwdriver) ) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + var/turf/T = get_turf(user) + to_chat(user, "Now attaching the gun to the frame...") + sleep(40) + if(get_turf(user) == T) + build_step++ + name = "armed [name]" + to_chat(user, "Taser gun attached.") + + if(9) + if( istype(W, /obj/item/weapon/cell) ) + if(!user.drop_item(W)) + return + + build_step++ + to_chat(user, "You complete the ED-209.") + var/turf/T = get_turf(src) + new /obj/machinery/bot/ed209(T,created_name,lasercolor) + qdel(W) + user.drop_from_inventory(src) + qdel(src) + + +/obj/machinery/bot/ed209/bullet_act(var/obj/item/projectile/Proj) + if((src.lasercolor == "b") && (src.disabled == 0)) + if(istype(Proj, /obj/item/projectile/beam/lastertag/red)) + src.disabled = 1 + //del (Proj) + returnToPool(Proj) + sleep(100) + src.disabled = 0 + else + ..() + else if((src.lasercolor == "r") && (src.disabled == 0)) + if(istype(Proj, /obj/item/projectile/beam/lastertag/blue)) + src.disabled = 1 + //del (Proj) + returnToPool(Proj) + sleep(100) + src.disabled = 0 + else + ..() + else + ..() + +/obj/machinery/bot/ed209/bluetag/New()//If desired, you spawn red and bluetag bots easily + new /obj/machinery/bot/ed209(get_turf(src),null,"b") + qdel(src) + + +/obj/machinery/bot/ed209/redtag/New() + new /obj/machinery/bot/ed209(get_turf(src),null,"r") + qdel(src) + +/obj/machinery/bot/ed209/proc/check_for_weapons(var/obj/item/slot_item) + if(istype(slot_item, /obj/item/weapon/gun) || istype(slot_item, /obj/item/weapon/melee)) + if(!(slot_item.type in safe_weapons)) + return 1 + return 0 + +/obj/machinery/bot/ed209/declare() + var/area/location = get_area(src) + declare_message = "\icon[src] [name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] scumbag [target] in [location]" + ..() diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index 41e814d3fff..9df909e4693 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -1,763 +1,763 @@ -//Floorbot assemblies -/obj/item/weapon/toolbox_tiles - desc = "It's a toolbox with tiles sticking out the top" - name = "tiles and toolbox" - icon = 'icons/obj/aibots.dmi' - icon_state = "toolbox_tiles" - force = 3.0 - throwforce = 10.0 - throw_speed = 2 - throw_range = 5 - w_class = 3.0 - flags = 0 - var/created_name = "Floorbot" - -/obj/item/weapon/toolbox_tiles_sensor - desc = "It's a toolbox with tiles sticking out the top and a sensor attached" - name = "tiles, toolbox and sensor arrangement" - icon = 'icons/obj/aibots.dmi' - icon_state = "toolbox_tiles_sensor" - force = 3.0 - throwforce = 10.0 - throw_speed = 2 - throw_range = 5 - w_class = 3.0 - flags = 0 - var/created_name = "Floorbot" - -// Tell other floorbots what we're fucking with so two floorbots don't dick with the same tile. -var/global/list/floorbot_targets=list() - -//Floorbot -/obj/machinery/bot/floorbot - name = "Floorbot" - desc = "A little floor repairing robot, he looks so excited!" - icon = 'icons/obj/aibots.dmi' - icon_state = "floorbot0" - layer = 5.0 - density = 0 - anchored = 0 - health = 25 - maxhealth = 25 - //weight = 1.0E7 - var/mode = 0 -#define FLOORBOT_IDLE 0 // idle -#define FLOORBOT_FIXING_SHIT 1 -#define FLOORBOT_START_PATROL 2 // start patrol -#define FLOORBOT_PATROL 3 // patrolling - - var/auto_patrol = 0 // set to make bot automatically patrol - var/amount = 10 - var/repairing = 0 - var/improvefloors = 0 - var/eattiles = 0 - var/maketiles = 0 - var/turf/target - var/turf/oldtarget - var/oldloc = null - req_access = list(access_construction) - var/path[] = new() - var/targetdirection - var/beacon_freq = 1445 // navigation beacon frequency - - - var/turf/patrol_target // this is turf to navigate to (location of beacon) - var/new_destination // pending new destination (waiting for beacon response) - var/destination // destination description tag - var/next_destination // the next destination in the patrol route - var/list/patpath = new // list of path turfs - - var/blockcount = 0 //number of times retried a blocked path - var/awaiting_beacon = 0 // count of pticks awaiting a beacon response - - var/nearest_beacon // the nearest beacon's tag - var/turf/nearest_beacon_loc // the nearest beacon's location - - -/obj/machinery/bot/floorbot/New() - . = ..() - src.updateicon() - -/obj/machinery/bot/floorbot/turn_on() - . = ..() - src.updateicon() - src.updateUsrDialog() - -/obj/machinery/bot/floorbot/turn_off() - ..() - if(!isnull(src.target)) - floorbot_targets -= src.target - src.target = null - src.oldtarget = null - src.oldloc = null - src.updateicon() - src.path = new() - src.patpath = new() - src.updateUsrDialog() - src.mode=FLOORBOT_IDLE - -/obj/machinery/bot/floorbot/attack_hand(mob/user as mob) - . = ..() - if (.) - return - usr.set_machine(src) - interact(user) - -/obj/machinery/bot/floorbot/interact(mob/user as mob) - var/dat - dat += "Automatic Station Floor Repairer v1.0

      " - dat += "Status: [src.on ? "On" : "Off"]
      " - dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]
      " - dat += "Tiles left: [src.amount]
      " - dat += "Behvaiour controls are [src.locked ? "locked" : "unlocked"]
      " - if(!src.locked || issilicon(user)) - dat += "Improves floors: [src.improvefloors ? "Yes" : "No"]
      " - dat += "Finds tiles: [src.eattiles ? "Yes" : "No"]
      " - dat += "Make single pieces of metal into tiles when empty: [src.maketiles ? "Yes" : "No"]
      " - - user << browse("Repairbot v1.0 controls[dat]", "window=autorepair") - onclose(user, "autorepair") - return - - -/obj/machinery/bot/floorbot/proc/speak(var/message) - for(var/mob/O in hearers(src, null)) - O.show_message("[src] beeps, \"[message]\"",2) - return - -/obj/machinery/bot/floorbot/attackby(var/obj/item/W , mob/user as mob) - if(istype(W, /obj/item/stack/tile/plasteel)) - var/obj/item/stack/tile/plasteel/T = W - if(src.amount >= 50) - return - var/loaded = min(50-src.amount, T.amount) - T.use(loaded) - src.amount += loaded - to_chat(user, "You load [loaded] tiles into the floorbot. He now contains [src.amount] tiles.") - src.updateicon() - else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if(src.allowed(usr) && !open && !emagged) - src.locked = !src.locked - to_chat(user, "You [src.locked ? "lock" : "unlock"] the [src] behaviour controls.") - else - if(emagged) - to_chat(user, "ERROR") - if(open) - to_chat(user, "Please close the access panel before locking it.") - else - to_chat(user, "Access denied.") - src.updateUsrDialog() - else - ..() - -/obj/machinery/bot/floorbot/Emag(mob/user as mob) - ..() - if(open && !locked) - if(user) to_chat(user, "The [src] buzzes and beeps.") - -/obj/machinery/bot/floorbot/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - switch(href_list["operation"]) - if("start") - if (src.on) - turn_off() - else - turn_on() - if("improve") - src.improvefloors = !src.improvefloors - src.updateUsrDialog() - if("tiles") - src.eattiles = !src.eattiles - src.updateUsrDialog() - if("make") - src.maketiles = !src.maketiles - src.updateUsrDialog() - -/obj/machinery/bot/floorbot/proc/is_obj_valid_target(var/atom/T,var/list/floorbottargets) - if(T in floorbottargets) - return 0 - if(T == src.oldtarget) - return 0 - if(istype(T.loc, /turf/simulated/wall)) - return 0 - if(!T.loc.Enter(src)) - return 0 - return 1 - -/obj/machinery/bot/floorbot/proc/hunt_for_tiles(var/list/shit_in_view, var/list/floorbottargets) - for(var/obj/item/stack/tile/plasteel/T in shit_in_view) - if(!(T in floorbot_targets) && src.is_obj_valid_target(T,floorbottargets)) - src.oldtarget = T - src.target = T - floorbot_targets +=T - mode=FLOORBOT_FIXING_SHIT - return - -/obj/machinery/bot/floorbot/proc/hunt_for_metal(var/list/shit_in_view, var/list/floorbottargets) - for(var/obj/item/stack/sheet/metal/M in shit_in_view) - if(!(M in floorbot_targets) && src.is_obj_valid_target(M) && M.amount == 1) - src.oldtarget = M - src.target = M - floorbot_targets += M - mode=FLOORBOT_FIXING_SHIT - return - -/obj/machinery/bot/floorbot/proc/have_target() - return (src.target != null) - -/obj/machinery/bot/floorbot/process() - //set background = 1 - - if(!src.on) - return - if(src.repairing) - return - - if(prob(1)) - var/message = pick("Metal to the metal.","I am the only engineering staff on this station.","Law 1. Place tiles.","Tiles, tiles, tiles...") - src.speak(message) - - switch(mode) - if(FLOORBOT_IDLE) // idle - walk_to(src,0) - if(checkforwork()) // see if any criminals are in range - return - if(!mode && auto_patrol) // still idle, and set to patrol - mode = FLOORBOT_START_PATROL // switch to patrol mode - if(FLOORBOT_FIXING_SHIT) - src.fix_shit() - return - if(FLOORBOT_START_PATROL) // start a patrol - if(patpath.len > 0 && patrol_target) // have a valid path, so just resume - mode = FLOORBOT_PATROL - return - - else if(patrol_target) // has patrol target already - spawn(0) - calc_path() // so just find a route to it - if(patpath.len == 0) - patrol_target = 0 - return - mode = FLOORBOT_PATROL - - - else // no patrol target, so need a new one - find_patrol_target() - speak("That's done, what's next?") - - - if(FLOORBOT_PATROL) // patrol mode - patrol_step() - spawn(5) - if(mode == FLOORBOT_PATROL) - patrol_step() - -/obj/machinery/bot/floorbot/proc/fix_shit() - if(!src.have_target()) - if(src.loc != src.oldloc) - src.oldtarget = null - return 0 - if(!src.path) - src.path = new() - if(src.target && (src.target != null) && src.path.len == 0) - spawn(0) - if(!istype(src.target, /turf/)) - src.path = AStar(src.loc, src.target.loc, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) - else - src.path = AStar(src.loc, src.target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) - if (!src.path) src.path = list() - if(src.path.len == 0) - src.oldtarget = src.target - floorbot_targets -= src.target - src.target = null - return 1 - if(src.path.len > 0 && src.target && (src.target != null)) - step_to(src, src.path[1]) - src.path -= src.path[1] - else if(src.path.len == 1) - step_to(src, target) - src.path = new() - - if(src.loc == src.target || src.loc == src.target.loc) - if(istype(src.target, /obj/item/stack/tile/plasteel)) - src.eattile(src.target) - mode=FLOORBOT_IDLE - else if(istype(src.target, /obj/item/stack/sheet/metal)) - src.maketile(src.target) - mode=FLOORBOT_IDLE - //else if(istype(src.target, /turf/) && emagged < 2) - else if((src.target.is_plating() || istype(src.target,/turf/space/)) && emagged < 2) - repair(src.target) - mode=FLOORBOT_IDLE - else if(src.target.is_plasteel_floor() && (src.target:broken || src.target:burnt) && emagged < 2) - var/turf/simulated/floor/F = src.target - src.anchored = 1 - src.repairing = 1 - F.break_tile_to_plating() - spawn(50) - src.anchored = 0 - src.repairing = 0 - src.target = null - floorbot_targets -= src.target - mode=FLOORBOT_IDLE - else if(src.target.is_plating() && emagged == 2) - var/turf/simulated/floor/F = src.target - src.anchored = 1 - src.repairing = 1 - if(prob(90)) - F.break_tile_to_plating() - else - F.ReplaceWithLattice() - visible_message("[src] makes an excited booping sound.") - spawn(50) - src.amount ++ - src.anchored = 0 - src.repairing = 0 - src.target = null - floorbot_targets -= src.target - mode=FLOORBOT_IDLE - src.path = new() - mode=FLOORBOT_IDLE - return 1 - - src.oldloc = src.loc - return 1 - -/obj/machinery/bot/floorbot/proc/checkforwork() - if(src.have_target()) - return 0 - var/list/floorbottargets = list() - - // Needed because we used to look this up 15 goddamn times per process. - Nexypoo - var/list/shitICanSee = view(7, src) - - if(src.amount < 50 && !src.have_target()) - if(src.eattiles) - if(src.hunt_for_tiles(shitICanSee, floorbottargets)) - return 1 - if(src.maketiles && !src.have_target()) - if(src.hunt_for_metal(shitICanSee, floorbottargets)) - return 1 - else - return 0 - - if(prob(5)) - visible_message("[src] makes an excited booping beeping sound!") - - if(!src.have_target() && emagged < 2) - if(targetdirection != null) - /* - for (var/turf/space/D in shitICanSee) - if(!(D in floorbottargets) && D != src.oldtarget) // Added for bridging mode -- TLE - if(get_dir(src, D) == targetdirection) - src.oldtarget = D - src.target = D - break - */ - var/turf/T = get_step(src, targetdirection) - if(istype(T, /turf/space) && !(T in floorbot_targets)) - src.oldtarget = T - src.target = T - floorbot_targets+=T - mode=FLOORBOT_FIXING_SHIT - return 1 - if(!src.have_target()) - for (var/turf/space/D in shitICanSee) - if(!(D in floorbottargets) && D != src.oldtarget && !isspace(D.loc) && !(D in floorbot_targets)) - src.oldtarget = D - src.target = D - floorbot_targets += D - mode=FLOORBOT_FIXING_SHIT - return 1 - if((!src.target || src.target == null ) && src.improvefloors) - for (var/turf/simulated/floor/F in shitICanSee) - // So, what the dick are we doing, here? - // ORIGINAL: if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating))) - // Using new erro flags: - if(!(F in floorbottargets) && F != src.oldtarget && F.is_plating() && !(istype(F, /turf/simulated/wall)) && !(F in floorbot_targets)) - if(!F.broken && !F.burnt) - src.oldtarget = F - src.target = F - floorbot_targets += F - mode=FLOORBOT_FIXING_SHIT - return 1 - if(!(F in floorbottargets) && !(F in floorbot_targets) && F != src.oldtarget && F.is_plasteel_floor() && (F.broken||F.burnt)) - src.oldtarget = F - src.target = F - floorbot_targets += F - mode=FLOORBOT_FIXING_SHIT - return 1 - - if(!src.have_target() && emagged == 2) - for (var/turf/simulated/floor/D in shitICanSee) - //if(!(D in floorbottargets) && D != src.oldtarget && D.floor_tile) - if(!(D in floorbottargets) && D != src.oldtarget && D.is_plasteel_floor() && !(D in floorbot_targets)) - src.oldtarget = D - src.target = D - floorbot_targets += D - mode=FLOORBOT_FIXING_SHIT - return 1 - return 0 - -/obj/machinery/bot/floorbot/proc/repair(var/turf/target) - if(istype(target, /turf/space/)) - if(isspace(target.loc)) - return - else if(!istype(target, /turf/simulated/floor)) - return - if(src.amount <= 0) - return - src.anchored = 1 - src.icon_state = "floorbot-c" - if(istype(target, /turf/space/)) - visible_message("[src] begins to repair the hole") - var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel - src.repairing = 1 - spawn(50) - T.build(src.loc) - src.repairing = 0 - src.amount -= 1 - src.updateicon() - src.anchored = 0 - floorbot_targets -= src.target - src.target = null - else - var/turf/simulated/floor/F = src.loc - if(!F.broken && !F.burnt) - visible_message("[src] begins to improve the floor.") - src.repairing = 1 - spawn(50) - F.make_plasteel_floor() - src.repairing = 0 - src.amount -= 1 - src.updateicon() - src.anchored = 0 - floorbot_targets -= src.target - src.target = null - else - if(F.is_plating()) - visible_message("[src] begins to fix dents in the floor.") - src.repairing = 1 - spawn(20) - src.repairing = 0 - // Cheap, and does the job. - F.icon_state = "plating" - F.burnt = 0 - F.broken = 0 - floorbot_targets -= src.target - src.target = null - -/obj/machinery/bot/floorbot/proc/eattile(var/obj/item/stack/tile/plasteel/T) - if(!istype(T, /obj/item/stack/tile/plasteel)) - return - visible_message("[src] begins to collect tiles.") - src.repairing = 1 - spawn(20) - if(isnull(T)) - src.target = null - src.repairing = 0 - return - if(src.amount + T.amount > 50) - var/i = 50 - src.amount - src.amount += i - T.amount -= i - else - src.amount += T.amount - returnToPool(T) - src.updateicon() - floorbot_targets -= src.target - src.target = null - src.repairing = 0 - -/obj/machinery/bot/floorbot/proc/maketile(var/obj/item/stack/sheet/metal/M) - if(!istype(M, /obj/item/stack/sheet/metal)) - return - if(M.amount < 1) - return - visible_message("[src] begins to create tiles.") - src.repairing = 1 - spawn(20) - if(!M || !get_turf(M)) - src.target = null - src.repairing = 0 - return - var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel(get_turf(M)) - T.amount = 4 - if(M.amount==1) - returnToPool(M) - //qdel(M) - else - M.amount-- - floorbot_targets -= src.target - src.target = null - src.repairing = 0 - -/obj/machinery/bot/floorbot/proc/updateicon() - if(src.amount > 0) - src.icon_state = "floorbot[src.on]" - else - src.icon_state = "floorbot[src.on]e" - - -/obj/machinery/bot/floorbot/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) - src.path = reverseRange(src.path) - -// perform a single patrol step - -/obj/machinery/bot/floorbot/proc/patrol_step() - - - if(loc == patrol_target) // reached target - at_patrol_target() - return - - else if(patpath.len > 0 && patrol_target) // valid path - - var/turf/next = patpath[1] - if(next == loc) - patpath -= next - return - - - if(istype( next, /turf/simulated)) - - var/moved = step_towards(src, next) // attempt to move - if(moved) // successful move - blockcount = 0 - patpath -= loc - - checkforwork() - else // failed to move - - blockcount++ - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - - spawn(2) - calc_path(next) - if(patpath.len == 0) - find_patrol_target() - else - blockcount = 0 - - return - - return - - else // not a valid turf - mode = FLOORBOT_IDLE - return - - else // no path, so calculate new one - mode = FLOORBOT_START_PATROL - - -// finds a new patrol target -/obj/machinery/bot/floorbot/proc/find_patrol_target() -// send_status() - if(awaiting_beacon) // awaiting beacon response - awaiting_beacon++ - if(awaiting_beacon > 5) // wait 5 secs for beacon response - find_nearest_beacon() // then go to nearest instead - return - - if(next_destination) - set_destination(next_destination) - else - find_nearest_beacon() - return - - -// finds the nearest beacon to self -// signals all beacons matching the patrol code -/obj/machinery/bot/floorbot/proc/find_nearest_beacon() - nearest_beacon = null - new_destination = "__nearest__" - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - spawn(10) - awaiting_beacon = 0 - if(nearest_beacon) - set_destination(nearest_beacon) - else - auto_patrol = 0 - mode = FLOORBOT_IDLE - speak("Disengaging patrol mode.") - //send_status() - - -/obj/machinery/bot/floorbot/proc/at_patrol_target() - find_patrol_target() - return - -/obj/machinery/bot/floorbot/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)) - D.open() - return - -/obj/machinery/bot/floorbot/receive_signal(datum/signal/signal) - //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])") - if(!on) - return - - var/recv = signal.data["command"] - - // receive response from beacon - recv = signal.data["beacon"] - var/valid = signal.data["patrol"] - if(!recv || !valid) - return - - if(recv == new_destination) // if the recvd beacon location matches the set destination - // the we will navigate there - destination = new_destination - patrol_target = signal.source.loc - next_destination = signal.data["next_patrol"] - awaiting_beacon = 0 - - // if looking for nearest beacon - else if(new_destination == "__nearest__") - var/dist = get_dist(src,signal.source.loc) - if(nearest_beacon) - - // note we ignore the beacon we are located at - if(dist>1 && dist 1) - nearest_beacon = recv - nearest_beacon_loc = signal.source.loc - return - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/floorbot/proc/post_signal(var/freq, var/key, var/value) - post_signal_multiple(freq, list("[key]" = value) ) - -// send a radio signal with multiple data key/values -/obj/machinery/bot/floorbot/proc/post_signal_multiple(var/freq, var/list/keyval) - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - signal.data = keyval -// to_chat(world, "sent [key],[keyval[key]] on [freq]") - if(signal.data["findbeacon"]) - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - else - frequency.post_signal(src, signal) - -// sets the current destination -// signals all beacons matching the patrol code -// beacons will return a signal giving their locations -/obj/machinery/bot/floorbot/proc/set_destination(var/new_dest) - new_destination = new_dest - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - -/obj/machinery/bot/floorbot/explode() - src.on = 0 - src.visible_message("[src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec) - N.contents = list() - - new /obj/item/device/assembly/prox_sensor(Tsec) - - if (prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) - - if(src.target) - floorbot_targets -= src.target - - while (amount)//Dumps the tiles into the appropriate sized stacks - if(amount >= 16) - var/obj/item/stack/tile/plasteel/T = new (Tsec) - T.amount = 16 - amount -= 16 - else - var/obj/item/stack/tile/plasteel/T = new (Tsec) - T.amount = src.amount - amount = 0 - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - qdel(src) - return - - -/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/plasteel/T, mob/user as mob) - if(!istype(T, /obj/item/stack/tile/plasteel)) - . = ..() - return - if(src.contents.len >= 1) - to_chat(user, "They wont fit in as there is already stuff inside.") - return - if(user.s_active) - user.s_active.close(user) - qdel(T) - T = null - var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles - user.put_in_hands(B) - to_chat(user, "You add the tiles into the empty toolbox. They protrude from the top.") - user.drop_from_inventory(src) - qdel(src) - -/obj/item/weapon/toolbox_tiles/attackby(var/obj/item/W, mob/user as mob) - ..() - if(isprox(W)) - qdel(W) - W = null - var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor() - B.created_name = src.created_name - user.put_in_hands(B) - to_chat(user, "You add the sensor to the toolbox and tiles!") - user.drop_from_inventory(src) - qdel(src) - - else if (istype(W, /obj/item/weapon/pen)) - var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - - src.created_name = t - -/obj/item/weapon/toolbox_tiles_sensor/attackby(var/obj/item/W, mob/user as mob) - ..() - if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) - qdel(W) - var/turf/T = get_turf(user.loc) - var/obj/machinery/bot/floorbot/A = new /obj/machinery/bot/floorbot(T) - A.name = src.created_name - to_chat(user, "You add the robot arm to the odd looking toolbox assembly! Boop beep!") - user.drop_from_inventory(src) - qdel(src) - else if (istype(W, /obj/item/weapon/pen)) - var/t = stripped_input(user, "Enter new robot name", src.name, src.created_name) - - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - - src.created_name = t +//Floorbot assemblies +/obj/item/weapon/toolbox_tiles + desc = "It's a toolbox with tiles sticking out the top" + name = "tiles and toolbox" + icon = 'icons/obj/aibots.dmi' + icon_state = "toolbox_tiles" + force = 3.0 + throwforce = 10.0 + throw_speed = 2 + throw_range = 5 + w_class = 3.0 + flags = 0 + var/created_name = "Floorbot" + +/obj/item/weapon/toolbox_tiles_sensor + desc = "It's a toolbox with tiles sticking out the top and a sensor attached" + name = "tiles, toolbox and sensor arrangement" + icon = 'icons/obj/aibots.dmi' + icon_state = "toolbox_tiles_sensor" + force = 3.0 + throwforce = 10.0 + throw_speed = 2 + throw_range = 5 + w_class = 3.0 + flags = 0 + var/created_name = "Floorbot" + +// Tell other floorbots what we're fucking with so two floorbots don't dick with the same tile. +var/global/list/floorbot_targets=list() + +//Floorbot +/obj/machinery/bot/floorbot + name = "Floorbot" + desc = "A little floor repairing robot, he looks so excited!" + icon = 'icons/obj/aibots.dmi' + icon_state = "floorbot0" + layer = 5.0 + density = 0 + anchored = 0 + health = 25 + maxhealth = 25 + //weight = 1.0E7 + var/mode = 0 +#define FLOORBOT_IDLE 0 // idle +#define FLOORBOT_FIXING_SHIT 1 +#define FLOORBOT_START_PATROL 2 // start patrol +#define FLOORBOT_PATROL 3 // patrolling + + var/auto_patrol = 0 // set to make bot automatically patrol + var/amount = 10 + var/repairing = 0 + var/improvefloors = 0 + var/eattiles = 0 + var/maketiles = 0 + var/turf/target + var/turf/oldtarget + var/oldloc = null + req_access = list(access_construction) + var/path[] = new() + var/targetdirection + var/beacon_freq = 1445 // navigation beacon frequency + + + var/turf/patrol_target // this is turf to navigate to (location of beacon) + var/new_destination // pending new destination (waiting for beacon response) + var/destination // destination description tag + var/next_destination // the next destination in the patrol route + var/list/patpath = new // list of path turfs + + var/blockcount = 0 //number of times retried a blocked path + var/awaiting_beacon = 0 // count of pticks awaiting a beacon response + + var/nearest_beacon // the nearest beacon's tag + var/turf/nearest_beacon_loc // the nearest beacon's location + + +/obj/machinery/bot/floorbot/New() + . = ..() + src.updateicon() + +/obj/machinery/bot/floorbot/turn_on() + . = ..() + src.updateicon() + src.updateUsrDialog() + +/obj/machinery/bot/floorbot/turn_off() + ..() + if(!isnull(src.target)) + floorbot_targets -= src.target + src.target = null + src.oldtarget = null + src.oldloc = null + src.updateicon() + src.path = new() + src.patpath = new() + src.updateUsrDialog() + src.mode=FLOORBOT_IDLE + +/obj/machinery/bot/floorbot/attack_hand(mob/user as mob) + . = ..() + if (.) + return + usr.set_machine(src) + interact(user) + +/obj/machinery/bot/floorbot/interact(mob/user as mob) + var/dat + dat += "Automatic Station Floor Repairer v1.0

      " + dat += "Status: [src.on ? "On" : "Off"]
      " + dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]
      " + dat += "Tiles left: [src.amount]
      " + dat += "Behvaiour controls are [src.locked ? "locked" : "unlocked"]
      " + if(!src.locked || issilicon(user)) + dat += "Improves floors: [src.improvefloors ? "Yes" : "No"]
      " + dat += "Finds tiles: [src.eattiles ? "Yes" : "No"]
      " + dat += "Make single pieces of metal into tiles when empty: [src.maketiles ? "Yes" : "No"]
      " + + user << browse("Repairbot v1.0 controls[dat]", "window=autorepair") + onclose(user, "autorepair") + return + + +/obj/machinery/bot/floorbot/proc/speak(var/message) + for(var/mob/O in hearers(src, null)) + O.show_message("[src] beeps, \"[message]\"",2) + return + +/obj/machinery/bot/floorbot/attackby(var/obj/item/W , mob/user as mob) + if(istype(W, /obj/item/stack/tile/plasteel)) + var/obj/item/stack/tile/plasteel/T = W + if(src.amount >= 50) + return + var/loaded = min(50-src.amount, T.amount) + T.use(loaded) + src.amount += loaded + to_chat(user, "You load [loaded] tiles into the floorbot. He now contains [src.amount] tiles.") + src.updateicon() + else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if(src.allowed(usr) && !open && !emagged) + src.locked = !src.locked + to_chat(user, "You [src.locked ? "lock" : "unlock"] the [src] behaviour controls.") + else + if(emagged) + to_chat(user, "ERROR") + if(open) + to_chat(user, "Please close the access panel before locking it.") + else + to_chat(user, "Access denied.") + src.updateUsrDialog() + else + ..() + +/obj/machinery/bot/floorbot/Emag(mob/user as mob) + ..() + if(open && !locked) + if(user) to_chat(user, "The [src] buzzes and beeps.") + +/obj/machinery/bot/floorbot/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + switch(href_list["operation"]) + if("start") + if (src.on) + turn_off() + else + turn_on() + if("improve") + src.improvefloors = !src.improvefloors + src.updateUsrDialog() + if("tiles") + src.eattiles = !src.eattiles + src.updateUsrDialog() + if("make") + src.maketiles = !src.maketiles + src.updateUsrDialog() + +/obj/machinery/bot/floorbot/proc/is_obj_valid_target(var/atom/T,var/list/floorbottargets) + if(T in floorbottargets) + return 0 + if(T == src.oldtarget) + return 0 + if(istype(T.loc, /turf/simulated/wall)) + return 0 + if(!T.loc.Enter(src)) + return 0 + return 1 + +/obj/machinery/bot/floorbot/proc/hunt_for_tiles(var/list/shit_in_view, var/list/floorbottargets) + for(var/obj/item/stack/tile/plasteel/T in shit_in_view) + if(!(T in floorbot_targets) && src.is_obj_valid_target(T,floorbottargets)) + src.oldtarget = T + src.target = T + floorbot_targets +=T + mode=FLOORBOT_FIXING_SHIT + return + +/obj/machinery/bot/floorbot/proc/hunt_for_metal(var/list/shit_in_view, var/list/floorbottargets) + for(var/obj/item/stack/sheet/metal/M in shit_in_view) + if(!(M in floorbot_targets) && src.is_obj_valid_target(M) && M.amount == 1) + src.oldtarget = M + src.target = M + floorbot_targets += M + mode=FLOORBOT_FIXING_SHIT + return + +/obj/machinery/bot/floorbot/proc/have_target() + return (src.target != null) + +/obj/machinery/bot/floorbot/process() + //set background = 1 + + if(!src.on) + return + if(src.repairing) + return + + if(prob(1)) + var/message = pick("Metal to the metal.","I am the only engineering staff on this station.","Law 1. Place tiles.","Tiles, tiles, tiles...") + src.speak(message) + + switch(mode) + if(FLOORBOT_IDLE) // idle + walk_to(src,0) + if(checkforwork()) // see if any criminals are in range + return + if(!mode && auto_patrol) // still idle, and set to patrol + mode = FLOORBOT_START_PATROL // switch to patrol mode + if(FLOORBOT_FIXING_SHIT) + src.fix_shit() + return + if(FLOORBOT_START_PATROL) // start a patrol + if(patpath.len > 0 && patrol_target) // have a valid path, so just resume + mode = FLOORBOT_PATROL + return + + else if(patrol_target) // has patrol target already + spawn(0) + calc_path() // so just find a route to it + if(patpath.len == 0) + patrol_target = 0 + return + mode = FLOORBOT_PATROL + + + else // no patrol target, so need a new one + find_patrol_target() + speak("That's done, what's next?") + + + if(FLOORBOT_PATROL) // patrol mode + patrol_step() + spawn(5) + if(mode == FLOORBOT_PATROL) + patrol_step() + +/obj/machinery/bot/floorbot/proc/fix_shit() + if(!src.have_target()) + if(src.loc != src.oldloc) + src.oldtarget = null + return 0 + if(!src.path) + src.path = new() + if(src.target && (src.target != null) && src.path.len == 0) + spawn(0) + if(!istype(src.target, /turf/)) + src.path = AStar(src.loc, src.target.loc, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) + else + src.path = AStar(src.loc, src.target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) + if (!src.path) src.path = list() + if(src.path.len == 0) + src.oldtarget = src.target + floorbot_targets -= src.target + src.target = null + return 1 + if(src.path.len > 0 && src.target && (src.target != null)) + step_to(src, src.path[1]) + src.path -= src.path[1] + else if(src.path.len == 1) + step_to(src, target) + src.path = new() + + if(src.loc == src.target || src.loc == src.target.loc) + if(istype(src.target, /obj/item/stack/tile/plasteel)) + src.eattile(src.target) + mode=FLOORBOT_IDLE + else if(istype(src.target, /obj/item/stack/sheet/metal)) + src.maketile(src.target) + mode=FLOORBOT_IDLE + //else if(istype(src.target, /turf/) && emagged < 2) + else if((src.target.is_plating() || istype(src.target,/turf/space/)) && emagged < 2) + repair(src.target) + mode=FLOORBOT_IDLE + else if(src.target.is_plasteel_floor() && (src.target:broken || src.target:burnt) && emagged < 2) + var/turf/simulated/floor/F = src.target + src.anchored = 1 + src.repairing = 1 + F.break_tile_to_plating() + spawn(50) + src.anchored = 0 + src.repairing = 0 + src.target = null + floorbot_targets -= src.target + mode=FLOORBOT_IDLE + else if(src.target.is_plating() && emagged == 2) + var/turf/simulated/floor/F = src.target + src.anchored = 1 + src.repairing = 1 + if(prob(90)) + F.break_tile_to_plating() + else + F.ReplaceWithLattice() + visible_message("[src] makes an excited booping sound.") + spawn(50) + src.amount ++ + src.anchored = 0 + src.repairing = 0 + src.target = null + floorbot_targets -= src.target + mode=FLOORBOT_IDLE + src.path = new() + mode=FLOORBOT_IDLE + return 1 + + src.oldloc = src.loc + return 1 + +/obj/machinery/bot/floorbot/proc/checkforwork() + if(src.have_target()) + return 0 + var/list/floorbottargets = list() + + // Needed because we used to look this up 15 goddamn times per process. - Nexypoo + var/list/shitICanSee = view(7, src) + + if(src.amount < 50 && !src.have_target()) + if(src.eattiles) + if(src.hunt_for_tiles(shitICanSee, floorbottargets)) + return 1 + if(src.maketiles && !src.have_target()) + if(src.hunt_for_metal(shitICanSee, floorbottargets)) + return 1 + else + return 0 + + if(prob(5)) + visible_message("[src] makes an excited booping beeping sound!") + + if(!src.have_target() && emagged < 2) + if(targetdirection != null) + /* + for (var/turf/space/D in shitICanSee) + if(!(D in floorbottargets) && D != src.oldtarget) // Added for bridging mode -- TLE + if(get_dir(src, D) == targetdirection) + src.oldtarget = D + src.target = D + break + */ + var/turf/T = get_step(src, targetdirection) + if(istype(T, /turf/space) && !(T in floorbot_targets)) + src.oldtarget = T + src.target = T + floorbot_targets+=T + mode=FLOORBOT_FIXING_SHIT + return 1 + if(!src.have_target()) + for (var/turf/space/D in shitICanSee) + if(!(D in floorbottargets) && D != src.oldtarget && !isspace(D.loc) && !(D in floorbot_targets)) + src.oldtarget = D + src.target = D + floorbot_targets += D + mode=FLOORBOT_FIXING_SHIT + return 1 + if((!src.target || src.target == null ) && src.improvefloors) + for (var/turf/simulated/floor/F in shitICanSee) + // So, what the dick are we doing, here? + // ORIGINAL: if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating))) + // Using new erro flags: + if(!(F in floorbottargets) && F != src.oldtarget && F.is_plating() && !(istype(F, /turf/simulated/wall)) && !(F in floorbot_targets)) + if(!F.broken && !F.burnt) + src.oldtarget = F + src.target = F + floorbot_targets += F + mode=FLOORBOT_FIXING_SHIT + return 1 + if(!(F in floorbottargets) && !(F in floorbot_targets) && F != src.oldtarget && F.is_plasteel_floor() && (F.broken||F.burnt)) + src.oldtarget = F + src.target = F + floorbot_targets += F + mode=FLOORBOT_FIXING_SHIT + return 1 + + if(!src.have_target() && emagged == 2) + for (var/turf/simulated/floor/D in shitICanSee) + //if(!(D in floorbottargets) && D != src.oldtarget && D.floor_tile) + if(!(D in floorbottargets) && D != src.oldtarget && D.is_plasteel_floor() && !(D in floorbot_targets)) + src.oldtarget = D + src.target = D + floorbot_targets += D + mode=FLOORBOT_FIXING_SHIT + return 1 + return 0 + +/obj/machinery/bot/floorbot/proc/repair(var/turf/target) + if(istype(target, /turf/space/)) + if(isspace(target.loc)) + return + else if(!istype(target, /turf/simulated/floor)) + return + if(src.amount <= 0) + return + src.anchored = 1 + src.icon_state = "floorbot-c" + if(istype(target, /turf/space/)) + visible_message("[src] begins to repair the hole") + var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel + src.repairing = 1 + spawn(50) + T.build(src.loc) + src.repairing = 0 + src.amount -= 1 + src.updateicon() + src.anchored = 0 + floorbot_targets -= src.target + src.target = null + else + var/turf/simulated/floor/F = src.loc + if(!F.broken && !F.burnt) + visible_message("[src] begins to improve the floor.") + src.repairing = 1 + spawn(50) + F.make_plasteel_floor() + src.repairing = 0 + src.amount -= 1 + src.updateicon() + src.anchored = 0 + floorbot_targets -= src.target + src.target = null + else + if(F.is_plating()) + visible_message("[src] begins to fix dents in the floor.") + src.repairing = 1 + spawn(20) + src.repairing = 0 + // Cheap, and does the job. + F.icon_state = "plating" + F.burnt = 0 + F.broken = 0 + floorbot_targets -= src.target + src.target = null + +/obj/machinery/bot/floorbot/proc/eattile(var/obj/item/stack/tile/plasteel/T) + if(!istype(T, /obj/item/stack/tile/plasteel)) + return + visible_message("[src] begins to collect tiles.") + src.repairing = 1 + spawn(20) + if(isnull(T)) + src.target = null + src.repairing = 0 + return + if(src.amount + T.amount > 50) + var/i = 50 - src.amount + src.amount += i + T.amount -= i + else + src.amount += T.amount + returnToPool(T) + src.updateicon() + floorbot_targets -= src.target + src.target = null + src.repairing = 0 + +/obj/machinery/bot/floorbot/proc/maketile(var/obj/item/stack/sheet/metal/M) + if(!istype(M, /obj/item/stack/sheet/metal)) + return + if(M.amount < 1) + return + visible_message("[src] begins to create tiles.") + src.repairing = 1 + spawn(20) + if(!M || !get_turf(M)) + src.target = null + src.repairing = 0 + return + var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel(get_turf(M)) + T.amount = 4 + if(M.amount==1) + returnToPool(M) + //qdel(M) + else + M.amount-- + floorbot_targets -= src.target + src.target = null + src.repairing = 0 + +/obj/machinery/bot/floorbot/proc/updateicon() + if(src.amount > 0) + src.icon_state = "floorbot[src.on]" + else + src.icon_state = "floorbot[src.on]e" + + +/obj/machinery/bot/floorbot/proc/calc_path(var/turf/avoid = null) + src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) + src.path = reverseRange(src.path) + +// perform a single patrol step + +/obj/machinery/bot/floorbot/proc/patrol_step() + + + if(loc == patrol_target) // reached target + at_patrol_target() + return + + else if(patpath.len > 0 && patrol_target) // valid path + + var/turf/next = patpath[1] + if(next == loc) + patpath -= next + return + + + if(istype( next, /turf/simulated)) + + var/moved = step_towards(src, next) // attempt to move + if(moved) // successful move + blockcount = 0 + patpath -= loc + + checkforwork() + else // failed to move + + blockcount++ + + if(blockcount > 5) // attempt 5 times before recomputing + // find new path excluding blocked turf + + spawn(2) + calc_path(next) + if(patpath.len == 0) + find_patrol_target() + else + blockcount = 0 + + return + + return + + else // not a valid turf + mode = FLOORBOT_IDLE + return + + else // no path, so calculate new one + mode = FLOORBOT_START_PATROL + + +// finds a new patrol target +/obj/machinery/bot/floorbot/proc/find_patrol_target() +// send_status() + if(awaiting_beacon) // awaiting beacon response + awaiting_beacon++ + if(awaiting_beacon > 5) // wait 5 secs for beacon response + find_nearest_beacon() // then go to nearest instead + return + + if(next_destination) + set_destination(next_destination) + else + find_nearest_beacon() + return + + +// finds the nearest beacon to self +// signals all beacons matching the patrol code +/obj/machinery/bot/floorbot/proc/find_nearest_beacon() + nearest_beacon = null + new_destination = "__nearest__" + post_signal(beacon_freq, "findbeacon", "patrol") + awaiting_beacon = 1 + spawn(10) + awaiting_beacon = 0 + if(nearest_beacon) + set_destination(nearest_beacon) + else + auto_patrol = 0 + mode = FLOORBOT_IDLE + speak("Disengaging patrol mode.") + //send_status() + + +/obj/machinery/bot/floorbot/proc/at_patrol_target() + find_patrol_target() + return + +/obj/machinery/bot/floorbot/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)) + D.open() + return + +/obj/machinery/bot/floorbot/receive_signal(datum/signal/signal) + //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])") + if(!on) + return + + var/recv = signal.data["command"] + + // receive response from beacon + recv = signal.data["beacon"] + var/valid = signal.data["patrol"] + if(!recv || !valid) + return + + if(recv == new_destination) // if the recvd beacon location matches the set destination + // the we will navigate there + destination = new_destination + patrol_target = signal.source.loc + next_destination = signal.data["next_patrol"] + awaiting_beacon = 0 + + // if looking for nearest beacon + else if(new_destination == "__nearest__") + var/dist = get_dist(src,signal.source.loc) + if(nearest_beacon) + + // note we ignore the beacon we are located at + if(dist>1 && dist 1) + nearest_beacon = recv + nearest_beacon_loc = signal.source.loc + return + +// send a radio signal with a single data key/value pair +/obj/machinery/bot/floorbot/proc/post_signal(var/freq, var/key, var/value) + post_signal_multiple(freq, list("[key]" = value) ) + +// send a radio signal with multiple data key/values +/obj/machinery/bot/floorbot/proc/post_signal_multiple(var/freq, var/list/keyval) + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + //for(var/key in keyval) + // signal.data[key] = keyval[key] + signal.data = keyval +// to_chat(world, "sent [key],[keyval[key]] on [freq]") + if(signal.data["findbeacon"]) + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + else + frequency.post_signal(src, signal) + +// sets the current destination +// signals all beacons matching the patrol code +// beacons will return a signal giving their locations +/obj/machinery/bot/floorbot/proc/set_destination(var/new_dest) + new_destination = new_dest + post_signal(beacon_freq, "findbeacon", "patrol") + awaiting_beacon = 1 + +/obj/machinery/bot/floorbot/explode() + src.on = 0 + src.visible_message("[src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec) + N.contents = list() + + new /obj/item/device/assembly/prox_sensor(Tsec) + + if (prob(50)) + new /obj/item/robot_parts/l_arm(Tsec) + + if(src.target) + floorbot_targets -= src.target + + while (amount)//Dumps the tiles into the appropriate sized stacks + if(amount >= 16) + var/obj/item/stack/tile/plasteel/T = new (Tsec) + T.amount = 16 + amount -= 16 + else + var/obj/item/stack/tile/plasteel/T = new (Tsec) + T.amount = src.amount + amount = 0 + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + qdel(src) + return + + +/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/plasteel/T, mob/user as mob) + if(!istype(T, /obj/item/stack/tile/plasteel)) + . = ..() + return + if(src.contents.len >= 1) + to_chat(user, "They wont fit in as there is already stuff inside.") + return + if(user.s_active) + user.s_active.close(user) + qdel(T) + T = null + var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles + user.put_in_hands(B) + to_chat(user, "You add the tiles into the empty toolbox. They protrude from the top.") + user.drop_from_inventory(src) + qdel(src) + +/obj/item/weapon/toolbox_tiles/attackby(var/obj/item/W, mob/user as mob) + ..() + if(isprox(W)) + qdel(W) + W = null + var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor() + B.created_name = src.created_name + user.put_in_hands(B) + to_chat(user, "You add the sensor to the toolbox and tiles!") + user.drop_from_inventory(src) + qdel(src) + + else if (istype(W, /obj/item/weapon/pen)) + var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) + if (!t) + return + if (!in_range(src, usr) && src.loc != usr) + return + + src.created_name = t + +/obj/item/weapon/toolbox_tiles_sensor/attackby(var/obj/item/W, mob/user as mob) + ..() + if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) + qdel(W) + var/turf/T = get_turf(user.loc) + var/obj/machinery/bot/floorbot/A = new /obj/machinery/bot/floorbot(T) + A.name = src.created_name + to_chat(user, "You add the robot arm to the odd looking toolbox assembly! Boop beep!") + user.drop_from_inventory(src) + qdel(src) + else if (istype(W, /obj/item/weapon/pen)) + var/t = stripped_input(user, "Enter new robot name", src.name, src.created_name) + + if (!t) + return + if (!in_range(src, usr) && src.loc != usr) + return + + src.created_name = t diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm index 0d6326ca0d3..5df28ec9dea 100644 --- a/code/game/machinery/bots/medbot.dm +++ b/code/game/machinery/bots/medbot.dm @@ -1,623 +1,623 @@ -//MEDBOT -//MEDBOT PATHFINDING -//MEDBOT ASSEMBLY - - -/obj/machinery/bot/medbot - name = "Medibot" - desc = "A little medical robot. He looks somewhat underwhelmed." - icon = 'icons/obj/aibots.dmi' - icon_state = "medibot0" - layer = 5.0 - density = 0 - anchored = 0 - health = 20 - maxhealth = 20 - req_access =list(access_medical) - var/stunned = 0 //It can be stunned by tasers. Delicate circuits. -//var/emagged = 0 - var/list/botcard_access = list(access_medical) - var/obj/item/weapon/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents. - var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits. - var/frustration = 0 - var/path[] = new() - var/mob/living/carbon/patient = null - var/mob/living/carbon/oldpatient = null - var/oldloc = null - var/last_found = 0 - var/last_newpatient_speak = 0 //Don't spam the "HEY I'M COMING" messages - var/currently_healing = 0 - var/injection_amount = 15 //How much reagent do we inject at a time? - var/heal_threshold = 10 //Start healing when they have this much damage in a category - var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents. - //Setting which reagents to use to treat what by default. By id. - var/treatment_brute = "tricordrazine" - var/treatment_oxy = "tricordrazine" - var/treatment_fire = "tricordrazine" - var/treatment_tox = "tricordrazine" - var/treatment_virus = "spaceacillin" - var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds? - var/shut_up = 0 //self explanatory :) - var/declare_crit = 1 //If active, the bot will transmit a critical patient alert to MedHUD users. - var/declare_cooldown = 0 //Prevents spam of critical patient alerts. - bot_type = MED_BOT - -/obj/machinery/bot/medbot/mysterious - name = "Mysterious Medibot" - desc = "International Medibot of mystery." - skin = "bezerk" - treatment_oxy = "dexalinp" - treatment_brute = "bicaridine" - treatment_fire = "kelotane" - treatment_tox = "anti_toxin" - -/obj/item/weapon/firstaid_arm_assembly - name = "first aid/robot arm assembly" - desc = "A first aid kit with a robot arm permanently grafted to it." - icon = 'icons/obj/aibots.dmi' - icon_state = "firstaid_arm" - var/build_step = 0 - var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess - var/skin = null //Same as medbot, set to tox or ointment for the respective kits. - w_class = 3.0 - - New() - ..() - spawn(5) - if(src.skin) - src.overlays += image('icons/obj/aibots.dmi', "kit_skin_[src.skin]") - - -/obj/machinery/bot/medbot/New() - ..() - src.icon_state = "medibot[src.on]" - spawn(4) - if(src.skin) - src.overlays += image('icons/obj/aibots.dmi', "medskin_[src.skin]") - - src.botcard = new /obj/item/weapon/card/id(src) - if(isnull(src.botcard_access) || (src.botcard_access.len < 1)) - var/datum/job/doctor/J = new/datum/job/doctor - src.botcard.access = J.get_access() - else - src.botcard.access = src.botcard_access - -/obj/machinery/bot/medbot/turn_on() - . = ..() - src.icon_state = "medibot[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/medbot/turn_off() - ..() - src.patient = null - src.oldpatient = null - src.oldloc = null - src.path = new() - src.currently_healing = 0 - src.last_found = world.time - src.icon_state = "medibot[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/medbot/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/machinery/bot/medbot/attack_hand(mob/user as mob) - . = ..() - if (.) - return - var/dat - dat += "Automatic Medical Unit v1.0

      " - dat += "Status: [src.on ? "On" : "Off"]
      " - dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]
      " - dat += "Beaker: " - if (src.reagent_glass) - dat += "Loaded \[[src.reagent_glass.reagents.total_volume]/[src.reagent_glass.reagents.maximum_volume]\]" - else - dat += "None Loaded" - dat += "
      Behaviour controls are [src.locked ? "locked" : "unlocked"]
      " - if(!src.locked || issilicon(user)) - dat += "Healing Threshold: " - dat += "-- " - dat += "- " - dat += "[src.heal_threshold] " - dat += "+ " - dat += "++" - dat += "
      " - - dat += "Injection Level: " - dat += "- " - dat += "[src.injection_amount] " - dat += "+ " - dat += "
      " - - dat += "Reagent Source: " - dat += "[src.use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]
      " - - dat += "Treatment report is [src.declare_treatment ? "on" : "off"]. Toggle
      " - - dat += "The speaker switch is [src.shut_up ? "off" : "on"]. Toggle
      " - - dat += "Critical Patient Alerts: [declare_crit ? "Yes" : "No"]
      " - - user << browse("Medibot v1.0 controls[dat]", "window=automed") - onclose(user, "automed") - return - -/obj/machinery/bot/medbot/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if ((href_list["power"]) && (src.allowed(usr))) - if (src.on) - turn_off() - else - turn_on() - - else if((href_list["adj_threshold"]) && (!src.locked || issilicon(usr))) - var/adjust_num = text2num(href_list["adj_threshold"]) - src.heal_threshold += adjust_num - if(src.heal_threshold < 5) - src.heal_threshold = 5 - if(src.heal_threshold > 75) - src.heal_threshold = 75 - - else if((href_list["adj_inject"]) && (!src.locked || issilicon(usr))) - var/adjust_num = text2num(href_list["adj_inject"]) - src.injection_amount += adjust_num - if(src.injection_amount < 5) - src.injection_amount = 5 - if(src.injection_amount > 15) - src.injection_amount = 15 - - else if((href_list["use_beaker"]) && (!src.locked || issilicon(usr))) - src.use_beaker = !src.use_beaker - - else if (href_list["eject"] && (!isnull(src.reagent_glass))) - if(!src.locked) - src.reagent_glass.loc = get_turf(src) - src.reagent_glass = null - else - to_chat(usr, "You cannot eject the beaker because the panel is locked.") - - else if ((href_list["togglevoice"]) && (!src.locked || issilicon(usr))) - src.shut_up = !src.shut_up - - else if ((href_list["declaretreatment"]) && (!src.locked || issilicon(usr))) - src.declare_treatment = !src.declare_treatment - - else if ((href_list["critalerts"]) && (!locked || issilicon(usr))) - declare_crit = !declare_crit - - src.updateUsrDialog() - return - -/obj/machinery/bot/medbot/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user) && !open && !emagged) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") - src.updateUsrDialog() - else - if(emagged) - to_chat(user, "ERROR") - if(open) - to_chat(user, "Please close the access panel before locking it.") - else - to_chat(user, "Access denied.") - - else if (istype(W, /obj/item/weapon/reagent_containers/glass)) - if(src.locked) - to_chat(user, "You cannot insert a beaker because the panel is locked.") - return - if(!isnull(src.reagent_glass)) - to_chat(user, "There is already a beaker loaded.") - return - - if(user.drop_item(W, src)) - src.reagent_glass = W - to_chat(user, "You insert [W].") - src.updateUsrDialog() - return - - else - ..() - if (health < maxhealth && !istype(W, /obj/item/weapon/screwdriver) && W.force) - step_to(src, (get_step_away(src,user))) - -/obj/machinery/bot/medbot/Emag(mob/user as mob) - ..() - if(open && !locked) - declare_crit = 0 - if(user) to_chat(user, "You short out [src]'s reagent synthesis circuits.") - spawn(0) - for(var/mob/O in hearers(src, null)) - O.show_message("[src] buzzes oddly!", 1) - flick("medibot_spark", src) - src.patient = null - if(user) src.oldpatient = user - src.currently_healing = 0 - src.last_found = world.time - src.anchored = 0 - src.emagged = 2 - src.on = 1 - src.icon_state = "medibot[src.on]" - -/obj/machinery/bot/medbot/process() - //set background = 1 - - if(!src.on) - src.stunned = 0 - return - - if(src.stunned) - src.icon_state = "medibota" - src.stunned-- - - src.oldpatient = src.patient - src.patient = null - src.currently_healing = 0 - - if(src.stunned <= 0) - src.icon_state = "medibot[src.on]" - src.stunned = 0 - return - - if(src.frustration > 8) - src.oldpatient = src.patient - src.patient = null - src.currently_healing = 0 - src.last_found = world.time - src.path = new() - - if(!src.patient) - if(!src.shut_up && prob(1)) - var/message = pick("Radar, put a mask on!","There's always a catch, and it's the best there is.","I knew it, I should've been a plastic surgeon.","What kind of medbay is this? Everyone's dropping like dead flies.","Delicious!") - src.speak(message) - - for (var/mob/living/carbon/C in view(7,src)) //Time to find a patient! - if ((C.stat == 2) || !istype(C, /mob/living/carbon/human)) - continue - - if ((C == src.oldpatient) && (world.time < src.last_found + 100)) - continue - - if(src.assess_patient(C)) - src.patient = C - src.oldpatient = C - src.last_found = world.time - spawn(0) - if((src.last_newpatient_speak + 100) < world.time) //Don't spam these messages! - var/message = pick("Hey, you! Hold on, I'm coming.","Wait! I want to help!","You appear to be injured!") - src.speak(message) - src.last_newpatient_speak = world.time - if(declare_treatment) - var/area/location = get_area(src) - broadcast_medical_hud_message("[src.name] is treating [C] in [location]", src) - src.visible_message("[src] points at [C.name]!") - break - else - continue - - if(!src.path) - src.path = new() - if(src.patient && (get_dist(src,src.patient) <= 1)) - if(!src.currently_healing) - src.currently_healing = 1 - src.frustration = 0 - src.medicate_patient(src.patient) - return - - else if(src.patient && (src.path.len) && (get_dist(src.patient,src.path[src.path.len]) > 2)) - src.path = new() - src.currently_healing = 0 - src.last_found = world.time - - if(src.patient && src.path.len == 0 && (get_dist(src,src.patient) > 1)) - spawn(0) - src.path = AStar(src.loc, get_turf(src.patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard) - if (!path) path = list() - if(src.path.len == 0) - src.oldpatient = src.patient - src.patient = null - src.currently_healing = 0 - src.last_found = world.time - return - - if(src.path.len > 0 && src.patient) - step_to(src, src.path[1]) - src.path -= src.path[1] - spawn(3) - if(src.path.len) - step_to(src, src.path[1]) - src.path -= src.path[1] - - if(src.path.len > 8 && src.patient) - src.frustration++ - - return - -/obj/machinery/bot/medbot/proc/assess_patient(mob/living/carbon/C as mob) - //Time to see if they need medical help! - if(C.stat == 2) - return 0 //welp too late for them! - - if(C.suiciding) - return 0 //Kevorkian school of robotic medical assistants. - - if(src.emagged == 2) //Everyone needs our medicine. (Our medicine is toxins) - return 1 - - if(declare_crit && C.health <= 0) //Critical condition! Call for help! - declare() - - //If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS. - if((src.reagent_glass) && (src.use_beaker) && ((C.getBruteLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getOxyLoss() >= (heal_threshold + 15)))) - for(var/datum/reagent/R in src.reagent_glass.reagents.reagent_list) - if(!C.reagents.has_reagent(R)) - return 1 - continue - - //They're injured enough for it! - if((C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_brute))) - return 1 //If they're already medicated don't bother! - - if((C.getOxyLoss() >= (15 + heal_threshold)) && (!C.reagents.has_reagent(src.treatment_oxy))) - return 1 - - if((C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_fire))) - return 1 - - if((C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_tox))) - return 1 - - - for(var/datum/disease/D in C.viruses) - if((D.stage > 1) || (D.spread_type == AIRBORNE)) - - if (!C.reagents.has_reagent(src.treatment_virus)) - return 1 //STOP DISEASE FOREVER - - return 0 - -/obj/machinery/bot/medbot/proc/medicate_patient(mob/living/carbon/C as mob) - if(!src.on) - return - - if(!istype(C)) - src.oldpatient = src.patient - src.patient = null - src.currently_healing = 0 - src.last_found = world.time - return - - if(C.stat == 2) - var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.") - src.speak(death_message) - src.oldpatient = src.patient - src.patient = null - src.currently_healing = 0 - src.last_found = world.time - return - - var/reagent_id = null - - //Use whatever is inside the loaded beaker. If there is one. - if((src.use_beaker) && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume)) - reagent_id = "internal_beaker" - - if(src.emagged == 2) //Emagged! Time to poison everybody. - reagent_id = "toxin" - - var/virus = 0 - for(var/datum/disease/D in C.viruses) - virus = 1 - - if (!reagent_id && (virus)) - if(!C.reagents.has_reagent(src.treatment_virus)) - reagent_id = src.treatment_virus - - if (!reagent_id && (C.getBruteLoss() >= heal_threshold)) - if(!C.reagents.has_reagent(src.treatment_brute)) - reagent_id = src.treatment_brute - - if (!reagent_id && (C.getOxyLoss() >= (15 + heal_threshold))) - if(!C.reagents.has_reagent(src.treatment_oxy)) - reagent_id = src.treatment_oxy - - if (!reagent_id && (C.getFireLoss() >= heal_threshold)) - if(!C.reagents.has_reagent(src.treatment_fire)) - reagent_id = src.treatment_fire - - if (!reagent_id && (C.getToxLoss() >= heal_threshold)) - if(!C.reagents.has_reagent(src.treatment_tox)) - reagent_id = src.treatment_tox - - if(!reagent_id) //If they don't need any of that they're probably cured! - src.oldpatient = src.patient - src.patient = null - src.currently_healing = 0 - src.last_found = world.time - var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!") - src.speak(message) - return - else - src.icon_state = "medibots" - visible_message("[src] is trying to inject [src.patient]!") - spawn(30) - if ((get_dist(src, src.patient) <= 1) && (src.on)) - if((reagent_id == "internal_beaker") && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume)) - src.reagent_glass.reagents.trans_to(src.patient,src.injection_amount) //Inject from beaker instead. - src.reagent_glass.reagents.reaction(src.patient, 2) - else - src.patient.reagents.add_reagent(reagent_id,src.injection_amount) - visible_message("[src] injects [src.patient] with the syringe!") - - src.icon_state = "medibot[src.on]" - src.currently_healing = 0 - return - -// src.speak(reagent_id) - reagent_id = null - return - - -/obj/machinery/bot/medbot/proc/speak(var/message) - if((!src.on) || (!message)) - return - visible_message("[src] beeps, \"[message]\"",\ - drugged_message="[src] beeps, \"[pick("FEED ME HUMANS","LET THE BLOOD FLOW","BLOOD FOR THE BLOOD GOD","I SPREAD DEATH AND DESTRUCTION","EXTERMINATE","I HATE YOU!","SURRENDER TO YOUR MACHINE OVERLORDS","FEED ME SHITTERS")]\"") - return - -/obj/machinery/bot/medbot/bullet_act(var/obj/item/projectile/Proj) - if(Proj.flag == "taser") - src.stunned = min(stunned+10,20) - ..() - -/obj/machinery/bot/medbot/explode() - src.on = 0 - visible_message("[src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - new /obj/item/weapon/storage/firstaid(Tsec) - - new /obj/item/device/assembly/prox_sensor(Tsec) - - new /obj/item/device/healthanalyzer(Tsec) - - if(src.reagent_glass) - src.reagent_glass.loc = Tsec - src.reagent_glass = null - - if (prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - qdel(src) - return - -/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)) - D.open() - src.frustration = 0 - else if ((istype(M, /mob/living/)) && (!src.anchored)) - src.loc = M:loc - src.frustration = 0 - return - -/* terrible -/obj/machinery/bot/medbot/Bumped(atom/movable/M as mob|obj) - spawn(0) - if (M) - var/turf/T = get_turf(src) - M:loc = T -*/ - -/* - * Pathfinding procs, allow the medibot to path through doors it has access to. - */ - -//Pretty ugh -/* -/turf/proc/AdjacentTurfsAllowMedAccess() - var/L[] = new() - for(var/turf/t in oview(src,1)) - if(!t.density) - if(!LinkBlocked(src, t) && !TurfBlockedNonWindowNonDoor(t,get_access("Medical Doctor"))) - L.Add(t) - return L - - -//It isn't blocked if we can open it, man. -/proc/TurfBlockedNonWindowNonDoor(turf/loc, var/list/access) - for(var/obj/O in loc) - if(O.density && !istype(O, /obj/structure/window) && !istype(O, /obj/machinery/door)) - return 1 - - if (O.density && (istype(O, /obj/machinery/door)) && (access.len)) - var/obj/machinery/door/D = O - for(var/req in D.req_access) - if(!(req in access)) //doesn't have this access - return 1 - - return 0 -*/ - -/* - * Medbot Assembly -- Can be made out of all three medkits. - */ - -/obj/item/weapon/storage/firstaid/attackby(var/obj/item/robot_parts/S, mob/user as mob) - - if ((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) - . = ..() - return - - //Making a medibot! - if(src.contents.len >= 1) - to_chat(user, "You need to empty [src] out first.") - return - - var/obj/item/weapon/firstaid_arm_assembly/A = new /obj/item/weapon/firstaid_arm_assembly - if(istype(src,/obj/item/weapon/storage/firstaid/fire)) - A.skin = "ointment" - else if(istype(src,/obj/item/weapon/storage/firstaid/toxin)) - A.skin = "tox" - else if(istype(src,/obj/item/weapon/storage/firstaid/o2)) - A.skin = "o2" - - qdel(S) - S = null - user.put_in_hands(A) - to_chat(user, "You add the robot arm to the first aid kit.") - user.drop_from_inventory(src) - qdel(src) - - -/obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(istype(W, /obj/item/weapon/pen)) - var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - src.created_name = t - else - switch(build_step) - if(0) - if(istype(W, /obj/item/device/healthanalyzer)) - if(user.drop_item(W)) - qdel(W) - src.build_step++ - to_chat(user, "You add the health sensor to [src].") - src.name = "First aid/robot arm/health analyzer assembly" - src.overlays += image('icons/obj/aibots.dmi', "na_scanner") - - if(1) - if(isprox(W)) - if(user.drop_item(W)) - qdel(W) - src.build_step++ - to_chat(user, "You complete the Medibot! Beep boop.") - var/turf/T = get_turf(src) - var/obj/machinery/bot/medbot/S = new /obj/machinery/bot/medbot(T) - S.skin = src.skin - S.name = src.created_name - user.drop_from_inventory(src) - qdel(src) - - -/obj/machinery/bot/medbot/declare() - if(declare_cooldown) - return - var/area/location = get_area(src) - declare_message = "\icon[src] Medical emergency! A patient is in critical condition at [location]!" - ..() - declare_cooldown = 1 - spawn(100) //Ten seconds - declare_cooldown = 0 +//MEDBOT +//MEDBOT PATHFINDING +//MEDBOT ASSEMBLY + + +/obj/machinery/bot/medbot + name = "Medibot" + desc = "A little medical robot. He looks somewhat underwhelmed." + icon = 'icons/obj/aibots.dmi' + icon_state = "medibot0" + layer = 5.0 + density = 0 + anchored = 0 + health = 20 + maxhealth = 20 + req_access =list(access_medical) + var/stunned = 0 //It can be stunned by tasers. Delicate circuits. +//var/emagged = 0 + var/list/botcard_access = list(access_medical) + var/obj/item/weapon/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents. + var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits. + var/frustration = 0 + var/path[] = new() + var/mob/living/carbon/patient = null + var/mob/living/carbon/oldpatient = null + var/oldloc = null + var/last_found = 0 + var/last_newpatient_speak = 0 //Don't spam the "HEY I'M COMING" messages + var/currently_healing = 0 + var/injection_amount = 15 //How much reagent do we inject at a time? + var/heal_threshold = 10 //Start healing when they have this much damage in a category + var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents. + //Setting which reagents to use to treat what by default. By id. + var/treatment_brute = "tricordrazine" + var/treatment_oxy = "tricordrazine" + var/treatment_fire = "tricordrazine" + var/treatment_tox = "tricordrazine" + var/treatment_virus = "spaceacillin" + var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds? + var/shut_up = 0 //self explanatory :) + var/declare_crit = 1 //If active, the bot will transmit a critical patient alert to MedHUD users. + var/declare_cooldown = 0 //Prevents spam of critical patient alerts. + bot_type = MED_BOT + +/obj/machinery/bot/medbot/mysterious + name = "Mysterious Medibot" + desc = "International Medibot of mystery." + skin = "bezerk" + treatment_oxy = "dexalinp" + treatment_brute = "bicaridine" + treatment_fire = "kelotane" + treatment_tox = "anti_toxin" + +/obj/item/weapon/firstaid_arm_assembly + name = "first aid/robot arm assembly" + desc = "A first aid kit with a robot arm permanently grafted to it." + icon = 'icons/obj/aibots.dmi' + icon_state = "firstaid_arm" + var/build_step = 0 + var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess + var/skin = null //Same as medbot, set to tox or ointment for the respective kits. + w_class = 3.0 + + New() + ..() + spawn(5) + if(src.skin) + src.overlays += image('icons/obj/aibots.dmi', "kit_skin_[src.skin]") + + +/obj/machinery/bot/medbot/New() + ..() + src.icon_state = "medibot[src.on]" + spawn(4) + if(src.skin) + src.overlays += image('icons/obj/aibots.dmi', "medskin_[src.skin]") + + src.botcard = new /obj/item/weapon/card/id(src) + if(isnull(src.botcard_access) || (src.botcard_access.len < 1)) + var/datum/job/doctor/J = new/datum/job/doctor + src.botcard.access = J.get_access() + else + src.botcard.access = src.botcard_access + +/obj/machinery/bot/medbot/turn_on() + . = ..() + src.icon_state = "medibot[src.on]" + src.updateUsrDialog() + +/obj/machinery/bot/medbot/turn_off() + ..() + src.patient = null + src.oldpatient = null + src.oldloc = null + src.path = new() + src.currently_healing = 0 + src.last_found = world.time + src.icon_state = "medibot[src.on]" + src.updateUsrDialog() + +/obj/machinery/bot/medbot/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/machinery/bot/medbot/attack_hand(mob/user as mob) + . = ..() + if (.) + return + var/dat + dat += "Automatic Medical Unit v1.0

      " + dat += "Status: [src.on ? "On" : "Off"]
      " + dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]
      " + dat += "Beaker: " + if (src.reagent_glass) + dat += "Loaded \[[src.reagent_glass.reagents.total_volume]/[src.reagent_glass.reagents.maximum_volume]\]" + else + dat += "None Loaded" + dat += "
      Behaviour controls are [src.locked ? "locked" : "unlocked"]
      " + if(!src.locked || issilicon(user)) + dat += "Healing Threshold: " + dat += "-- " + dat += "- " + dat += "[src.heal_threshold] " + dat += "+ " + dat += "++" + dat += "
      " + + dat += "Injection Level: " + dat += "- " + dat += "[src.injection_amount] " + dat += "+ " + dat += "
      " + + dat += "Reagent Source: " + dat += "[src.use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]
      " + + dat += "Treatment report is [src.declare_treatment ? "on" : "off"]. Toggle
      " + + dat += "The speaker switch is [src.shut_up ? "off" : "on"]. Toggle
      " + + dat += "Critical Patient Alerts: [declare_crit ? "Yes" : "No"]
      " + + user << browse("Medibot v1.0 controls[dat]", "window=automed") + onclose(user, "automed") + return + +/obj/machinery/bot/medbot/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if ((href_list["power"]) && (src.allowed(usr))) + if (src.on) + turn_off() + else + turn_on() + + else if((href_list["adj_threshold"]) && (!src.locked || issilicon(usr))) + var/adjust_num = text2num(href_list["adj_threshold"]) + src.heal_threshold += adjust_num + if(src.heal_threshold < 5) + src.heal_threshold = 5 + if(src.heal_threshold > 75) + src.heal_threshold = 75 + + else if((href_list["adj_inject"]) && (!src.locked || issilicon(usr))) + var/adjust_num = text2num(href_list["adj_inject"]) + src.injection_amount += adjust_num + if(src.injection_amount < 5) + src.injection_amount = 5 + if(src.injection_amount > 15) + src.injection_amount = 15 + + else if((href_list["use_beaker"]) && (!src.locked || issilicon(usr))) + src.use_beaker = !src.use_beaker + + else if (href_list["eject"] && (!isnull(src.reagent_glass))) + if(!src.locked) + src.reagent_glass.loc = get_turf(src) + src.reagent_glass = null + else + to_chat(usr, "You cannot eject the beaker because the panel is locked.") + + else if ((href_list["togglevoice"]) && (!src.locked || issilicon(usr))) + src.shut_up = !src.shut_up + + else if ((href_list["declaretreatment"]) && (!src.locked || issilicon(usr))) + src.declare_treatment = !src.declare_treatment + + else if ((href_list["critalerts"]) && (!locked || issilicon(usr))) + declare_crit = !declare_crit + + src.updateUsrDialog() + return + +/obj/machinery/bot/medbot/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (src.allowed(user) && !open && !emagged) + src.locked = !src.locked + to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") + src.updateUsrDialog() + else + if(emagged) + to_chat(user, "ERROR") + if(open) + to_chat(user, "Please close the access panel before locking it.") + else + to_chat(user, "Access denied.") + + else if (istype(W, /obj/item/weapon/reagent_containers/glass)) + if(src.locked) + to_chat(user, "You cannot insert a beaker because the panel is locked.") + return + if(!isnull(src.reagent_glass)) + to_chat(user, "There is already a beaker loaded.") + return + + if(user.drop_item(W, src)) + src.reagent_glass = W + to_chat(user, "You insert [W].") + src.updateUsrDialog() + return + + else + ..() + if (health < maxhealth && !istype(W, /obj/item/weapon/screwdriver) && W.force) + step_to(src, (get_step_away(src,user))) + +/obj/machinery/bot/medbot/Emag(mob/user as mob) + ..() + if(open && !locked) + declare_crit = 0 + if(user) to_chat(user, "You short out [src]'s reagent synthesis circuits.") + spawn(0) + for(var/mob/O in hearers(src, null)) + O.show_message("[src] buzzes oddly!", 1) + flick("medibot_spark", src) + src.patient = null + if(user) src.oldpatient = user + src.currently_healing = 0 + src.last_found = world.time + src.anchored = 0 + src.emagged = 2 + src.on = 1 + src.icon_state = "medibot[src.on]" + +/obj/machinery/bot/medbot/process() + //set background = 1 + + if(!src.on) + src.stunned = 0 + return + + if(src.stunned) + src.icon_state = "medibota" + src.stunned-- + + src.oldpatient = src.patient + src.patient = null + src.currently_healing = 0 + + if(src.stunned <= 0) + src.icon_state = "medibot[src.on]" + src.stunned = 0 + return + + if(src.frustration > 8) + src.oldpatient = src.patient + src.patient = null + src.currently_healing = 0 + src.last_found = world.time + src.path = new() + + if(!src.patient) + if(!src.shut_up && prob(1)) + var/message = pick("Radar, put a mask on!","There's always a catch, and it's the best there is.","I knew it, I should've been a plastic surgeon.","What kind of medbay is this? Everyone's dropping like dead flies.","Delicious!") + src.speak(message) + + for (var/mob/living/carbon/C in view(7,src)) //Time to find a patient! + if ((C.stat == 2) || !istype(C, /mob/living/carbon/human)) + continue + + if ((C == src.oldpatient) && (world.time < src.last_found + 100)) + continue + + if(src.assess_patient(C)) + src.patient = C + src.oldpatient = C + src.last_found = world.time + spawn(0) + if((src.last_newpatient_speak + 100) < world.time) //Don't spam these messages! + var/message = pick("Hey, you! Hold on, I'm coming.","Wait! I want to help!","You appear to be injured!") + src.speak(message) + src.last_newpatient_speak = world.time + if(declare_treatment) + var/area/location = get_area(src) + broadcast_medical_hud_message("[src.name] is treating [C] in [location]", src) + src.visible_message("[src] points at [C.name]!") + break + else + continue + + if(!src.path) + src.path = new() + if(src.patient && (get_dist(src,src.patient) <= 1)) + if(!src.currently_healing) + src.currently_healing = 1 + src.frustration = 0 + src.medicate_patient(src.patient) + return + + else if(src.patient && (src.path.len) && (get_dist(src.patient,src.path[src.path.len]) > 2)) + src.path = new() + src.currently_healing = 0 + src.last_found = world.time + + if(src.patient && src.path.len == 0 && (get_dist(src,src.patient) > 1)) + spawn(0) + src.path = AStar(src.loc, get_turf(src.patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard) + if (!path) path = list() + if(src.path.len == 0) + src.oldpatient = src.patient + src.patient = null + src.currently_healing = 0 + src.last_found = world.time + return + + if(src.path.len > 0 && src.patient) + step_to(src, src.path[1]) + src.path -= src.path[1] + spawn(3) + if(src.path.len) + step_to(src, src.path[1]) + src.path -= src.path[1] + + if(src.path.len > 8 && src.patient) + src.frustration++ + + return + +/obj/machinery/bot/medbot/proc/assess_patient(mob/living/carbon/C as mob) + //Time to see if they need medical help! + if(C.stat == 2) + return 0 //welp too late for them! + + if(C.suiciding) + return 0 //Kevorkian school of robotic medical assistants. + + if(src.emagged == 2) //Everyone needs our medicine. (Our medicine is toxins) + return 1 + + if(declare_crit && C.health <= 0) //Critical condition! Call for help! + declare() + + //If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS. + if((src.reagent_glass) && (src.use_beaker) && ((C.getBruteLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getOxyLoss() >= (heal_threshold + 15)))) + for(var/datum/reagent/R in src.reagent_glass.reagents.reagent_list) + if(!C.reagents.has_reagent(R)) + return 1 + continue + + //They're injured enough for it! + if((C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_brute))) + return 1 //If they're already medicated don't bother! + + if((C.getOxyLoss() >= (15 + heal_threshold)) && (!C.reagents.has_reagent(src.treatment_oxy))) + return 1 + + if((C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_fire))) + return 1 + + if((C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(src.treatment_tox))) + return 1 + + + for(var/datum/disease/D in C.viruses) + if((D.stage > 1) || (D.spread_type == AIRBORNE)) + + if (!C.reagents.has_reagent(src.treatment_virus)) + return 1 //STOP DISEASE FOREVER + + return 0 + +/obj/machinery/bot/medbot/proc/medicate_patient(mob/living/carbon/C as mob) + if(!src.on) + return + + if(!istype(C)) + src.oldpatient = src.patient + src.patient = null + src.currently_healing = 0 + src.last_found = world.time + return + + if(C.stat == 2) + var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.") + src.speak(death_message) + src.oldpatient = src.patient + src.patient = null + src.currently_healing = 0 + src.last_found = world.time + return + + var/reagent_id = null + + //Use whatever is inside the loaded beaker. If there is one. + if((src.use_beaker) && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume)) + reagent_id = "internal_beaker" + + if(src.emagged == 2) //Emagged! Time to poison everybody. + reagent_id = "toxin" + + var/virus = 0 + for(var/datum/disease/D in C.viruses) + virus = 1 + + if (!reagent_id && (virus)) + if(!C.reagents.has_reagent(src.treatment_virus)) + reagent_id = src.treatment_virus + + if (!reagent_id && (C.getBruteLoss() >= heal_threshold)) + if(!C.reagents.has_reagent(src.treatment_brute)) + reagent_id = src.treatment_brute + + if (!reagent_id && (C.getOxyLoss() >= (15 + heal_threshold))) + if(!C.reagents.has_reagent(src.treatment_oxy)) + reagent_id = src.treatment_oxy + + if (!reagent_id && (C.getFireLoss() >= heal_threshold)) + if(!C.reagents.has_reagent(src.treatment_fire)) + reagent_id = src.treatment_fire + + if (!reagent_id && (C.getToxLoss() >= heal_threshold)) + if(!C.reagents.has_reagent(src.treatment_tox)) + reagent_id = src.treatment_tox + + if(!reagent_id) //If they don't need any of that they're probably cured! + src.oldpatient = src.patient + src.patient = null + src.currently_healing = 0 + src.last_found = world.time + var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!") + src.speak(message) + return + else + src.icon_state = "medibots" + visible_message("[src] is trying to inject [src.patient]!") + spawn(30) + if ((get_dist(src, src.patient) <= 1) && (src.on)) + if((reagent_id == "internal_beaker") && (src.reagent_glass) && (src.reagent_glass.reagents.total_volume)) + src.reagent_glass.reagents.trans_to(src.patient,src.injection_amount) //Inject from beaker instead. + src.reagent_glass.reagents.reaction(src.patient, 2) + else + src.patient.reagents.add_reagent(reagent_id,src.injection_amount) + visible_message("[src] injects [src.patient] with the syringe!") + + src.icon_state = "medibot[src.on]" + src.currently_healing = 0 + return + +// src.speak(reagent_id) + reagent_id = null + return + + +/obj/machinery/bot/medbot/proc/speak(var/message) + if((!src.on) || (!message)) + return + visible_message("[src] beeps, \"[message]\"",\ + drugged_message="[src] beeps, \"[pick("FEED ME HUMANS","LET THE BLOOD FLOW","BLOOD FOR THE BLOOD GOD","I SPREAD DEATH AND DESTRUCTION","EXTERMINATE","I HATE YOU!","SURRENDER TO YOUR MACHINE OVERLORDS","FEED ME SHITTERS")]\"") + return + +/obj/machinery/bot/medbot/bullet_act(var/obj/item/projectile/Proj) + if(Proj.flag == "taser") + src.stunned = min(stunned+10,20) + ..() + +/obj/machinery/bot/medbot/explode() + src.on = 0 + visible_message("[src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + new /obj/item/weapon/storage/firstaid(Tsec) + + new /obj/item/device/assembly/prox_sensor(Tsec) + + new /obj/item/device/healthanalyzer(Tsec) + + if(src.reagent_glass) + src.reagent_glass.loc = Tsec + src.reagent_glass = null + + if (prob(50)) + new /obj/item/robot_parts/l_arm(Tsec) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + qdel(src) + return + +/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)) + D.open() + src.frustration = 0 + else if ((istype(M, /mob/living/)) && (!src.anchored)) + src.loc = M:loc + src.frustration = 0 + return + +/* terrible +/obj/machinery/bot/medbot/Bumped(atom/movable/M as mob|obj) + spawn(0) + if (M) + var/turf/T = get_turf(src) + M:loc = T +*/ + +/* + * Pathfinding procs, allow the medibot to path through doors it has access to. + */ + +//Pretty ugh +/* +/turf/proc/AdjacentTurfsAllowMedAccess() + var/L[] = new() + for(var/turf/t in oview(src,1)) + if(!t.density) + if(!LinkBlocked(src, t) && !TurfBlockedNonWindowNonDoor(t,get_access("Medical Doctor"))) + L.Add(t) + return L + + +//It isn't blocked if we can open it, man. +/proc/TurfBlockedNonWindowNonDoor(turf/loc, var/list/access) + for(var/obj/O in loc) + if(O.density && !istype(O, /obj/structure/window) && !istype(O, /obj/machinery/door)) + return 1 + + if (O.density && (istype(O, /obj/machinery/door)) && (access.len)) + var/obj/machinery/door/D = O + for(var/req in D.req_access) + if(!(req in access)) //doesn't have this access + return 1 + + return 0 +*/ + +/* + * Medbot Assembly -- Can be made out of all three medkits. + */ + +/obj/item/weapon/storage/firstaid/attackby(var/obj/item/robot_parts/S, mob/user as mob) + + if ((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) + . = ..() + return + + //Making a medibot! + if(src.contents.len >= 1) + to_chat(user, "You need to empty [src] out first.") + return + + var/obj/item/weapon/firstaid_arm_assembly/A = new /obj/item/weapon/firstaid_arm_assembly + if(istype(src,/obj/item/weapon/storage/firstaid/fire)) + A.skin = "ointment" + else if(istype(src,/obj/item/weapon/storage/firstaid/toxin)) + A.skin = "tox" + else if(istype(src,/obj/item/weapon/storage/firstaid/o2)) + A.skin = "o2" + + qdel(S) + S = null + user.put_in_hands(A) + to_chat(user, "You add the robot arm to the first aid kit.") + user.drop_from_inventory(src) + qdel(src) + + +/obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(istype(W, /obj/item/weapon/pen)) + var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) + if (!t) + return + if (!in_range(src, usr) && src.loc != usr) + return + src.created_name = t + else + switch(build_step) + if(0) + if(istype(W, /obj/item/device/healthanalyzer)) + if(user.drop_item(W)) + qdel(W) + src.build_step++ + to_chat(user, "You add the health sensor to [src].") + src.name = "First aid/robot arm/health analyzer assembly" + src.overlays += image('icons/obj/aibots.dmi', "na_scanner") + + if(1) + if(isprox(W)) + if(user.drop_item(W)) + qdel(W) + src.build_step++ + to_chat(user, "You complete the Medibot! Beep boop.") + var/turf/T = get_turf(src) + var/obj/machinery/bot/medbot/S = new /obj/machinery/bot/medbot(T) + S.skin = src.skin + S.name = src.created_name + user.drop_from_inventory(src) + qdel(src) + + +/obj/machinery/bot/medbot/declare() + if(declare_cooldown) + return + var/area/location = get_area(src) + declare_message = "\icon[src] Medical emergency! A patient is in critical condition at [location]!" + ..() + declare_cooldown = 1 + spawn(100) //Ten seconds + declare_cooldown = 0 diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 2ed507f4a4f..f6d10c33619 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -1,919 +1,919 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -// Mulebot - carries crates around for Quartermaster -// Navigates via floor navbeacons -// Remote Controlled from QM's PDA - -var/global/mulebot_count = 0 - -/obj/machinery/bot/mulebot - name = "\improper MULEbot" - desc = "A Multiple Utility Load Effector bot." - icon_state = "mulebot0" - layer = MOB_LAYER - density = 1 - anchored = 1 - animate_movement=1 - health = 150 //yeah, it's tougher than ed209 because it is a big metal box with wheels --rastaf0 - maxhealth = 150 - fire_dam_coeff = 0.7 - brute_dam_coeff = 0.5 - var/atom/movable/load = null // the loaded crate (usually) - var/beacon_freq = 1400 - var/control_freq = 1447 - - suffix = "" - - var/turf/target // this is turf to navigate to (location of beacon) - var/loaddir = 0 // this the direction to unload onto/load from - var/new_destination = "" // pending new destination (waiting for beacon response) - var/destination = "" // destination description - var/home_destination = "" // tag of home beacon - req_access = list(access_cargo) // added robotics access so assembly line drop-off works properly -veyveyr //I don't think so, Tim. You need to add it to the MULE's hidden robot ID card. -NEO - var/path[] = new() - - var/mode = 0 //0 = idle/ready - //1 = loading/unloading - //2 = moving to deliver - //3 = returning to home - //4 = blocked - //5 = computing navigation - //6 = waiting for nav computation - //7 = no destination beacon found (or no route) - - var/blockcount = 0 //number of times retried a blocked path - var/reached_target = 1 //true if already reached the target - - var/refresh = 1 // true to refresh dialogue - var/auto_return = 1 // true if auto return to home beacon after unload - var/auto_pickup = 1 // true if auto-pickup at beacon - - var/obj/item/weapon/cell/cell - var/datum/wires/mulebot/wires = null - // the installed power cell - - // constants for internal wiring bitflags - /* - - var/wires = 1023 // all flags on - - var/list/wire_text // list of wire colours - var/list/wire_order // order of wire indices - */ - - var/list/can_load = list() - - var/bloodiness = 0 // count of bloodiness - var/currentBloodColor = "#A10808" - -/obj/machinery/bot/mulebot/New() - ..() - wires = new(src) - botcard = new(src) - var/datum/job/cargo_tech/J = new/datum/job/cargo_tech - botcard.access = J.get_access() -// botcard.access += access_robotics //Why --Ikki - cell = new(src) - cell.charge = 2000 - cell.maxcharge = 2000 - - spawn(5) // must wait for map loading to finish - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - - mulebot_count += 1 - if(!suffix) - suffix = "#[mulebot_count]" - name = "\improper Mulebot ([suffix])" - - - can_load = list( - /obj/structure/closet/crate, - /obj/structure/vendomatpack, - /obj/structure/stackopacks, - /obj/item/weapon/gift, - ) - -/obj/machinery/bot/mulebot/Destroy() - if(radio_controller) - radio_controller.remove_object(src, control_freq) - radio_controller.remove_object(src, beacon_freq) - if(wires) - qdel(wires) - wires = null - - ..() - -// attack by item -// emag : lock/unlock, -// screwdriver: open/close hatch -// cell: insert it -// other: chance to knock rider off bot -/obj/machinery/bot/mulebot/attackby(var/obj/item/I, var/mob/user) - if(istype(I,/obj/item/weapon/card/emag)) - locked = !locked +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +// Mulebot - carries crates around for Quartermaster +// Navigates via floor navbeacons +// Remote Controlled from QM's PDA + +var/global/mulebot_count = 0 + +/obj/machinery/bot/mulebot + name = "\improper MULEbot" + desc = "A Multiple Utility Load Effector bot." + icon_state = "mulebot0" + layer = MOB_LAYER + density = 1 + anchored = 1 + animate_movement=1 + health = 150 //yeah, it's tougher than ed209 because it is a big metal box with wheels --rastaf0 + maxhealth = 150 + fire_dam_coeff = 0.7 + brute_dam_coeff = 0.5 + var/atom/movable/load = null // the loaded crate (usually) + var/beacon_freq = 1400 + var/control_freq = 1447 + + suffix = "" + + var/turf/target // this is turf to navigate to (location of beacon) + var/loaddir = 0 // this the direction to unload onto/load from + var/new_destination = "" // pending new destination (waiting for beacon response) + var/destination = "" // destination description + var/home_destination = "" // tag of home beacon + req_access = list(access_cargo) // added robotics access so assembly line drop-off works properly -veyveyr //I don't think so, Tim. You need to add it to the MULE's hidden robot ID card. -NEO + var/path[] = new() + + var/mode = 0 //0 = idle/ready + //1 = loading/unloading + //2 = moving to deliver + //3 = returning to home + //4 = blocked + //5 = computing navigation + //6 = waiting for nav computation + //7 = no destination beacon found (or no route) + + var/blockcount = 0 //number of times retried a blocked path + var/reached_target = 1 //true if already reached the target + + var/refresh = 1 // true to refresh dialogue + var/auto_return = 1 // true if auto return to home beacon after unload + var/auto_pickup = 1 // true if auto-pickup at beacon + + var/obj/item/weapon/cell/cell + var/datum/wires/mulebot/wires = null + // the installed power cell + + // constants for internal wiring bitflags + /* + + var/wires = 1023 // all flags on + + var/list/wire_text // list of wire colours + var/list/wire_order // order of wire indices + */ + + var/list/can_load = list() + + var/bloodiness = 0 // count of bloodiness + var/currentBloodColor = "#A10808" + +/obj/machinery/bot/mulebot/New() + ..() + wires = new(src) + botcard = new(src) + var/datum/job/cargo_tech/J = new/datum/job/cargo_tech + botcard.access = J.get_access() +// botcard.access += access_robotics //Why --Ikki + cell = new(src) + cell.charge = 2000 + cell.maxcharge = 2000 + + spawn(5) // must wait for map loading to finish + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + + mulebot_count += 1 + if(!suffix) + suffix = "#[mulebot_count]" + name = "\improper Mulebot ([suffix])" + + + can_load = list( + /obj/structure/closet/crate, + /obj/structure/vendomatpack, + /obj/structure/stackopacks, + /obj/item/weapon/gift, + ) + +/obj/machinery/bot/mulebot/Destroy() + if(radio_controller) + radio_controller.remove_object(src, control_freq) + radio_controller.remove_object(src, beacon_freq) + if(wires) + qdel(wires) + wires = null + + ..() + +// attack by item +// emag : lock/unlock, +// screwdriver: open/close hatch +// cell: insert it +// other: chance to knock rider off bot +/obj/machinery/bot/mulebot/attackby(var/obj/item/I, var/mob/user) + if(istype(I,/obj/item/weapon/card/emag)) + locked = !locked to_chat(user, "You [locked ? "lock" : "unlock"] the mulebot's controls!") - flick("mulebot-emagged", src) - playsound(get_turf(src), 'sound/effects/sparks1.ogg', 100, 0) - else if(istype(I, /obj/item/weapon/card/id)) - if(toggle_lock(user)) + flick("mulebot-emagged", src) + playsound(get_turf(src), 'sound/effects/sparks1.ogg', 100, 0) + else if(istype(I, /obj/item/weapon/card/id)) + if(toggle_lock(user)) to_chat(user, "Controls [(locked ? "locked" : "unlocked")].") - - else if(istype(I,/obj/item/weapon/cell) && open && !cell) - var/obj/item/weapon/cell/C = I - if(user.drop_item(C, src)) - cell = C - updateDialog() - else if(istype(I,/obj/item/weapon/wirecutters)||istype(I,/obj/item/device/multitool)) - attack_hand(user) - else if(istype(I,/obj/item/weapon/screwdriver)) - if(locked) + + else if(istype(I,/obj/item/weapon/cell) && open && !cell) + var/obj/item/weapon/cell/C = I + if(user.drop_item(C, src)) + cell = C + updateDialog() + else if(istype(I,/obj/item/weapon/wirecutters)||istype(I,/obj/item/device/multitool)) + attack_hand(user) + else if(istype(I,/obj/item/weapon/screwdriver)) + if(locked) to_chat(user, "The maintenance hatch cannot be opened or closed while the controls are locked.") - return - - open = !open - if(open) - src.visible_message("[user] opens the maintenance hatch of [src]", "You open [src]'s maintenance hatch.") - on = 0 - icon_state="mulebot-hatch" - else - src.visible_message("[user] closes the maintenance hatch of [src]", "You close [src]'s maintenance hatch.") - icon_state = "mulebot0" - - updateDialog() - else if (istype(I, /obj/item/weapon/wrench)) - if (src.health < maxhealth) - src.health = min(maxhealth, src.health+25) - user.visible_message( - "[user] repairs [src]!", - "You repair [src]!" - ) - else + return + + open = !open + if(open) + src.visible_message("[user] opens the maintenance hatch of [src]", "You open [src]'s maintenance hatch.") + on = 0 + icon_state="mulebot-hatch" + else + src.visible_message("[user] closes the maintenance hatch of [src]", "You close [src]'s maintenance hatch.") + icon_state = "mulebot0" + + updateDialog() + else if (istype(I, /obj/item/weapon/wrench)) + if (src.health < maxhealth) + src.health = min(maxhealth, src.health+25) + user.visible_message( + "[user] repairs [src]!", + "You repair [src]!" + ) + else to_chat(user, "[src] does not need a repair!") - else if(load && ismob(load)) // chance to knock off rider - if(prob(1+I.force * 2)) - unload(0) - user.visible_message("[user] knocks [load] off [src] with \the [I]!", "You knock [load] off [src] with \the [I]!") - else + else if(load && ismob(load)) // chance to knock off rider + if(prob(1+I.force * 2)) + unload(0) + user.visible_message("[user] knocks [load] off [src] with \the [I]!", "You knock [load] off [src] with \the [I]!") + else to_chat(user, "You hit [src] with \the [I] but to no effect.") - else - ..() - return - - -/obj/machinery/bot/mulebot/ex_act(var/severity) - unload(0) - switch(severity) - if(2) - for(var/i = 1; i < 3; i++) - wires.RandomCut() - if(3) - wires.RandomCut() - ..() - return - -/obj/machinery/bot/mulebot/bullet_act() - if(prob(50) && !isnull(load)) - unload(0) - if(prob(25)) - src.visible_message("Something shorts out inside [src]!") - wires.RandomCut() - ..() - - -/obj/machinery/bot/mulebot/attack_ai(var/mob/user) - src.add_hiddenprint(user) - user.set_machine(src) - interact(user, 1) - -/obj/machinery/bot/mulebot/attack_hand(var/mob/user) - . = ..() - if (.) - return - user.set_machine(src) - interact(user, 0) - -/obj/machinery/bot/mulebot/interact(var/mob/user, var/ai=0) - var/dat - dat += "Multiple Utility Load Effector Mk. III

      " - dat += "ID: [suffix]
      " - dat += "Power: [on ? "On" : "Off"]
      " - - if(!open) - - dat += "Status: " - switch(mode) - if(0) - dat += "Ready" - if(1) - dat += "Loading/Unloading" - if(2) - dat += "Navigating to Delivery Location" - if(3) - dat += "Navigating to Home" - if(4) - dat += "Waiting for clear path" - if(5,6) - dat += "Calculating navigation path" - if(7) - dat += "Unable to reach destination" - - - dat += "
      Current Load: [load ? load.name : "none"]
      " - dat += "Destination: [!destination ? "none" : destination]
      " - dat += "Power level: [cell ? cell.percent() : 0]%
      " - - if(locked && !ai) - dat += "
      Controls are locked (unlock)" - else - dat += "
      Controls are unlocked (lock)

      " - - dat += "Toggle Power
      " - dat += "Stop
      " - dat += "Proceed
      " - dat += "Return to Home
      " - dat += "Set Destination
      " - dat += "Set Bot ID
      " - dat += "Set Home
      " - dat += "Toggle Auto Return Home ([auto_return ? "On":"Off"])
      " - dat += "Toggle Auto Pickup Crate ([auto_pickup ? "On":"Off"])
      " - - if(load) - dat += "Unload Now
      " - dat += "
      The maintenance hatch is closed.
      " - - else - if(!ai) - dat += "The maintenance hatch is open.

      " - dat += "Power cell: " - if(cell) - dat += "Installed
      " - else - dat += "Removed
      " - - dat += wires() - else - dat += "The bot is in maintenance mode and cannot be controlled.
      " - - user << browse("Mulebot [suffix ? "([suffix])" : ""][dat]", "window=mulebot;size=350x500") - onclose(user, "mulebot") - return - -// returns the wire panel text -/obj/machinery/bot/mulebot/proc/wires() - return wires.GetInteractWindow() - - -/obj/machinery/bot/mulebot/Topic(href, href_list) - if(..()) - return - if (usr.stat) - return - if ((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - switch(href_list["op"]) - if("lock", "unlock") - toggle_lock(usr) - - if("power") - if (src.on) - turn_off() - else if (cell && !open) - if (!turn_on()) + else + ..() + return + + +/obj/machinery/bot/mulebot/ex_act(var/severity) + unload(0) + switch(severity) + if(2) + for(var/i = 1; i < 3; i++) + wires.RandomCut() + if(3) + wires.RandomCut() + ..() + return + +/obj/machinery/bot/mulebot/bullet_act() + if(prob(50) && !isnull(load)) + unload(0) + if(prob(25)) + src.visible_message("Something shorts out inside [src]!") + wires.RandomCut() + ..() + + +/obj/machinery/bot/mulebot/attack_ai(var/mob/user) + src.add_hiddenprint(user) + user.set_machine(src) + interact(user, 1) + +/obj/machinery/bot/mulebot/attack_hand(var/mob/user) + . = ..() + if (.) + return + user.set_machine(src) + interact(user, 0) + +/obj/machinery/bot/mulebot/interact(var/mob/user, var/ai=0) + var/dat + dat += "Multiple Utility Load Effector Mk. III

      " + dat += "ID: [suffix]
      " + dat += "Power: [on ? "On" : "Off"]
      " + + if(!open) + + dat += "Status: " + switch(mode) + if(0) + dat += "Ready" + if(1) + dat += "Loading/Unloading" + if(2) + dat += "Navigating to Delivery Location" + if(3) + dat += "Navigating to Home" + if(4) + dat += "Waiting for clear path" + if(5,6) + dat += "Calculating navigation path" + if(7) + dat += "Unable to reach destination" + + + dat += "
      Current Load: [load ? load.name : "none"]
      " + dat += "Destination: [!destination ? "none" : destination]
      " + dat += "Power level: [cell ? cell.percent() : 0]%
      " + + if(locked && !ai) + dat += "
      Controls are locked (unlock)" + else + dat += "
      Controls are unlocked (lock)

      " + + dat += "Toggle Power
      " + dat += "Stop
      " + dat += "Proceed
      " + dat += "Return to Home
      " + dat += "Set Destination
      " + dat += "Set Bot ID
      " + dat += "Set Home
      " + dat += "Toggle Auto Return Home ([auto_return ? "On":"Off"])
      " + dat += "Toggle Auto Pickup Crate ([auto_pickup ? "On":"Off"])
      " + + if(load) + dat += "Unload Now
      " + dat += "
      The maintenance hatch is closed.
      " + + else + if(!ai) + dat += "The maintenance hatch is open.

      " + dat += "Power cell: " + if(cell) + dat += "Installed
      " + else + dat += "Removed
      " + + dat += wires() + else + dat += "The bot is in maintenance mode and cannot be controlled.
      " + + user << browse("Mulebot [suffix ? "([suffix])" : ""][dat]", "window=mulebot;size=350x500") + onclose(user, "mulebot") + return + +// returns the wire panel text +/obj/machinery/bot/mulebot/proc/wires() + return wires.GetInteractWindow() + + +/obj/machinery/bot/mulebot/Topic(href, href_list) + if(..()) + return + if (usr.stat) + return + if ((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + + switch(href_list["op"]) + if("lock", "unlock") + toggle_lock(usr) + + if("power") + if (src.on) + turn_off() + else if (cell && !open) + if (!turn_on()) to_chat(usr, "You can't switch on [src].") - return - else - return - visible_message("[usr] switches [on ? "on" : "off"] [src].") - updateDialog() - - - if("cellremove") - if(open && cell && !usr.get_active_hand()) - cell.updateicon() - usr.put_in_active_hand(cell) - cell.add_fingerprint(usr) - cell = null - - usr.visible_message("[usr] removes the power cell from [src].", "You remove the power cell from [src].") - updateDialog() - - if("cellinsert") - if(open && !cell) - var/obj/item/weapon/cell/C = usr.get_active_hand() - if(istype(C)) - if(usr.drop_item(C, src)) - cell = C - C.add_fingerprint(usr) - - usr.visible_message("[usr] inserts a power cell into [src].", "You insert the power cell into [src].") - updateDialog() - - - if("stop") - if(mode >=2) - mode = 0 - updateDialog() - - if("go") - if(mode == 0) - start() - updateDialog() - - if("home") - if(mode == 0 || mode == 2) - start_home() - updateDialog() - - if("destination") - refresh=0 - var/new_dest = input("Enter new destination tag", "Mulebot [suffix ? "([suffix])" : ""]", destination) as text|null - refresh=1 - if(new_dest && Adjacent(usr) && !usr.stat) - set_destination(new_dest) - - - if("setid") - refresh=0 - var/new_id = copytext(sanitize(input("Enter new bot ID", "Mulebot [suffix ? "([suffix])" : ""]", suffix) as text|null),1,MAX_NAME_LEN) - refresh=1 - if(new_id && Adjacent(usr) && !usr.stat) - suffix = new_id - name = "\improper Mulebot ([suffix])" - updateDialog() - - if("sethome") - refresh=0 - var/new_home = input("Enter new home tag", "Mulebot [suffix ? "([suffix])" : ""]", home_destination) as text|null - refresh=1 - if(new_home && Adjacent(usr) && !usr.stat) - home_destination = new_home - updateDialog() - - if("unload") - if(load && mode !=1) - if(loc == target) - unload(loaddir) - else - unload(0) - - if("autoret") - auto_return = !auto_return - - if("autopick") - auto_pickup = !auto_pickup - - if("close") - usr.unset_machine() - usr << browse(null,"window=mulebot") - - updateDialog() - //src.updateUsrDialog() - else - usr << browse(null, "window=mulebot") - usr.unset_machine() - return - - - -// returns true if the bot has power -/obj/machinery/bot/mulebot/proc/has_power() - return !open && cell && cell.charge > 0 && wires.HasPower() - -/obj/machinery/bot/mulebot/proc/toggle_lock(var/mob/user) - if(src.allowed(user)) - locked = !locked - updateDialog() - return 1 - else + return + else + return + visible_message("[usr] switches [on ? "on" : "off"] [src].") + updateDialog() + + + if("cellremove") + if(open && cell && !usr.get_active_hand()) + cell.updateicon() + usr.put_in_active_hand(cell) + cell.add_fingerprint(usr) + cell = null + + usr.visible_message("[usr] removes the power cell from [src].", "You remove the power cell from [src].") + updateDialog() + + if("cellinsert") + if(open && !cell) + var/obj/item/weapon/cell/C = usr.get_active_hand() + if(istype(C)) + if(usr.drop_item(C, src)) + cell = C + C.add_fingerprint(usr) + + usr.visible_message("[usr] inserts a power cell into [src].", "You insert the power cell into [src].") + updateDialog() + + + if("stop") + if(mode >=2) + mode = 0 + updateDialog() + + if("go") + if(mode == 0) + start() + updateDialog() + + if("home") + if(mode == 0 || mode == 2) + start_home() + updateDialog() + + if("destination") + refresh=0 + var/new_dest = input("Enter new destination tag", "Mulebot [suffix ? "([suffix])" : ""]", destination) as text|null + refresh=1 + if(new_dest && Adjacent(usr) && !usr.stat) + set_destination(new_dest) + + + if("setid") + refresh=0 + var/new_id = copytext(sanitize(input("Enter new bot ID", "Mulebot [suffix ? "([suffix])" : ""]", suffix) as text|null),1,MAX_NAME_LEN) + refresh=1 + if(new_id && Adjacent(usr) && !usr.stat) + suffix = new_id + name = "\improper Mulebot ([suffix])" + updateDialog() + + if("sethome") + refresh=0 + var/new_home = input("Enter new home tag", "Mulebot [suffix ? "([suffix])" : ""]", home_destination) as text|null + refresh=1 + if(new_home && Adjacent(usr) && !usr.stat) + home_destination = new_home + updateDialog() + + if("unload") + if(load && mode !=1) + if(loc == target) + unload(loaddir) + else + unload(0) + + if("autoret") + auto_return = !auto_return + + if("autopick") + auto_pickup = !auto_pickup + + if("close") + usr.unset_machine() + usr << browse(null,"window=mulebot") + + updateDialog() + //src.updateUsrDialog() + else + usr << browse(null, "window=mulebot") + usr.unset_machine() + return + + + +// returns true if the bot has power +/obj/machinery/bot/mulebot/proc/has_power() + return !open && cell && cell.charge > 0 && wires.HasPower() + +/obj/machinery/bot/mulebot/proc/toggle_lock(var/mob/user) + if(src.allowed(user)) + locked = !locked + updateDialog() + return 1 + else to_chat(user, "Access denied.") - return 0 - -// mousedrop a crate to load the bot -// can load anything if emagged - -/obj/machinery/bot/mulebot/MouseDrop_T(var/atom/movable/C, mob/user) - - if(user.stat) - return - - if (!on || !istype(C)|| C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 ) - return - - if(load) - return - - load(C) - - -// called to load a crate -/obj/machinery/bot/mulebot/proc/load(var/atom/movable/C) - if(wires.LoadCheck() && !is_type_in_list(C,can_load)) - src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) - return // if not emagged, only allow crates to be loaded - - //I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool. - //So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below. - if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C)) - return - if(!isturf(C.loc)) //To prevent the loading from stuff from someone's inventory, which wouldn't get handled properly. - return - - if(get_dist(C, src) > 1 || load || !on) - return - for(var/obj/structure/plasticflaps/P in src.loc)//Takes flaps into account - if(!CanPass(C,P)) - return - mode = 1 - - // if a crate, close before loading - var/obj/structure/closet/crate/crate = C - if(istype(crate)) - crate.close() - - C.loc = src.loc - sleep(2) - if(C.loc != src.loc) //To prevent you from going onto more thano ne bot. - return - C.loc = src - load = C - - C.pixel_y += 9 - if(C.layer < layer) - C.layer = layer + 0.1 - overlays += C - - if(ismob(C)) - var/mob/M = C - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - - mode = 0 - send_status() - -// called to unload the bot -// argument is optional direction to unload -// if zero, unload at bot's location -/obj/machinery/bot/mulebot/proc/unload(var/dirn = 0) - if(!load) - return - - mode = 1 - overlays.len = 0 - - load.loc = src.loc - load.pixel_y -= 9 - load.layer = initial(load.layer) - if(ismob(load)) - var/mob/M = load - if(M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = src - - - if(dirn) - var/turf/T = src.loc - T = get_step(T,dirn) - if(CanPass(load,T))//Can't get off onto anything that wouldn't let you pass normally - step(load, dirn) - else - load.loc = src.loc//Drops you right there, so you shouldn't be able to get yourself stuck - - load = null - - // in case non-load items end up in contents, dump every else too - // this seems to happen sometimes due to race conditions - // with items dropping as mobs are loaded - - for(var/atom/movable/AM in src) - if(AM == cell || AM == botcard) continue - - AM.loc = src.loc - AM.layer = initial(AM.layer) - AM.pixel_y = initial(AM.pixel_y) - if(ismob(AM)) - var/mob/M = AM - if(M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = src - mode = 0 - - -/obj/machinery/bot/mulebot/process() - if(!has_power()) - on = 0 - return - if(on) - var/speed = (wires.Motor1() ? 1 : 0) + (wires.Motor2() ? 2 : 0) + return 0 + +// mousedrop a crate to load the bot +// can load anything if emagged + +/obj/machinery/bot/mulebot/MouseDrop_T(var/atom/movable/C, mob/user) + + if(user.stat) + return + + if (!on || !istype(C)|| C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 ) + return + + if(load) + return + + load(C) + + +// called to load a crate +/obj/machinery/bot/mulebot/proc/load(var/atom/movable/C) + if(wires.LoadCheck() && !is_type_in_list(C,can_load)) + src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + return // if not emagged, only allow crates to be loaded + + //I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool. + //So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below. + if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C)) + return + if(!isturf(C.loc)) //To prevent the loading from stuff from someone's inventory, which wouldn't get handled properly. + return + + if(get_dist(C, src) > 1 || load || !on) + return + for(var/obj/structure/plasticflaps/P in src.loc)//Takes flaps into account + if(!CanPass(C,P)) + return + mode = 1 + + // if a crate, close before loading + var/obj/structure/closet/crate/crate = C + if(istype(crate)) + crate.close() + + C.loc = src.loc + sleep(2) + if(C.loc != src.loc) //To prevent you from going onto more thano ne bot. + return + C.loc = src + load = C + + C.pixel_y += 9 + if(C.layer < layer) + C.layer = layer + 0.1 + overlays += C + + if(ismob(C)) + var/mob/M = C + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + + mode = 0 + send_status() + +// called to unload the bot +// argument is optional direction to unload +// if zero, unload at bot's location +/obj/machinery/bot/mulebot/proc/unload(var/dirn = 0) + if(!load) + return + + mode = 1 + overlays.len = 0 + + load.loc = src.loc + load.pixel_y -= 9 + load.layer = initial(load.layer) + if(ismob(load)) + var/mob/M = load + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + + + if(dirn) + var/turf/T = src.loc + T = get_step(T,dirn) + if(CanPass(load,T))//Can't get off onto anything that wouldn't let you pass normally + step(load, dirn) + else + load.loc = src.loc//Drops you right there, so you shouldn't be able to get yourself stuck + + load = null + + // in case non-load items end up in contents, dump every else too + // this seems to happen sometimes due to race conditions + // with items dropping as mobs are loaded + + for(var/atom/movable/AM in src) + if(AM == cell || AM == botcard) continue + + AM.loc = src.loc + AM.layer = initial(AM.layer) + AM.pixel_y = initial(AM.pixel_y) + if(ismob(AM)) + var/mob/M = AM + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + mode = 0 + + +/obj/machinery/bot/mulebot/process() + if(!has_power()) + on = 0 + return + if(on) + var/speed = (wires.Motor1() ? 1 : 0) + (wires.Motor2() ? 2 : 0) // to_chat(world, "speed: [speed]") - switch(speed) - if(0) - // do nothing - if(1) - process_bot() - spawn(2) - process_bot() - sleep(2) - process_bot() - sleep(2) - process_bot() - sleep(2) - process_bot() - if(2) - process_bot() - spawn(4) - process_bot() - if(3) - process_bot() - - if(refresh) updateDialog() - -/obj/machinery/bot/mulebot/proc/process_bot() + switch(speed) + if(0) + // do nothing + if(1) + process_bot() + spawn(2) + process_bot() + sleep(2) + process_bot() + sleep(2) + process_bot() + sleep(2) + process_bot() + if(2) + process_bot() + spawn(4) + process_bot() + if(3) + process_bot() + + if(refresh) updateDialog() + +/obj/machinery/bot/mulebot/proc/process_bot() // to_chat(if(mode) world, "Mode: [mode]") - switch(mode) - if(0) // idle - icon_state = "mulebot0" - return - if(1) // loading/unloading - return - if(2,3,4) // navigating to deliver,home, or blocked - - if(loc == target) // reached target - at_target() - return - - else if(path.len > 0 && target) // valid path - - var/turf/next = path[1] - reached_target = 0 - if(next == loc) - path -= next - return - if(istype( next, /turf/simulated)) + switch(mode) + if(0) // idle + icon_state = "mulebot0" + return + if(1) // loading/unloading + return + if(2,3,4) // navigating to deliver,home, or blocked + + if(loc == target) // reached target + at_target() + return + + else if(path.len > 0 && target) // valid path + + var/turf/next = path[1] + reached_target = 0 + if(next == loc) + path -= next + return + if(istype( next, /turf/simulated)) // to_chat(world, "at ([x],[y]) moving to ([next.x],[next.y])") - if(bloodiness) - var/turf/simulated/T=loc - if(istype(T)) - var/goingdir=0 - - var/newdir = get_dir(next, loc) - if(newdir == dir) - goingdir = newdir - else - newdir = newdir | dir - if(newdir == 3) - newdir = 1 - else if(newdir == 12) - newdir = 4 - goingdir = newdir - T.AddTracks(/obj/effect/decal/cleanable/blood/tracks/wheels,list(),0,goingdir,currentBloodColor) - bloodiness-- - - var/moved = step_towards(src, next) // attempt to move - if(cell) cell.use(1) - if(moved) // successful move + if(bloodiness) + var/turf/simulated/T=loc + if(istype(T)) + var/goingdir=0 + + var/newdir = get_dir(next, loc) + if(newdir == dir) + goingdir = newdir + else + newdir = newdir | dir + if(newdir == 3) + newdir = 1 + else if(newdir == 12) + newdir = 4 + goingdir = newdir + T.AddTracks(/obj/effect/decal/cleanable/blood/tracks/wheels,list(),0,goingdir,currentBloodColor) + bloodiness-- + + var/moved = step_towards(src, next) // attempt to move + if(cell) cell.use(1) + if(moved) // successful move // to_chat(world, "Successful move.") - blockcount = 0 - path -= loc - - - if(mode==4) - spawn(1) - send_status() - - if(destination == home_destination) - mode = 3 - else - mode = 2 - - else // failed to move - + blockcount = 0 + path -= loc + + + if(mode==4) + spawn(1) + send_status() + + if(destination == home_destination) + mode = 3 + else + mode = 2 + + else // failed to move + // to_chat(world, "Unable to move.") - - - - blockcount++ - mode = 4 - if(blockcount == 3) - src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) - - spawn(2) - calc_path(next) - if(path.len > 0) - src.visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) - mode = 4 - mode =6 - return - return - else - src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + + + + blockcount++ + mode = 4 + if(blockcount == 3) + src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") + playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + + if(blockcount > 5) // attempt 5 times before recomputing + // find new path excluding blocked turf + src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + + spawn(2) + calc_path(next) + if(path.len > 0) + src.visible_message("[src] makes a delighted ping!", "You hear a ping.") + playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + mode = 4 + mode =6 + return + return + else + src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") + playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) // to_chat(world, "Bad turf.") - mode = 5 - return - else + mode = 5 + return + else // to_chat(world, "No path.") - mode = 5 - return - - if(5) // calculate new path + mode = 5 + return + + if(5) // calculate new path // to_chat(world, "Calc new path.") - mode = 6 - spawn(0) - - calc_path() - - if(path.len > 0) - blockcount = 0 - mode = 4 - src.visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) - - else - src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) - - mode = 7 - //if(6) + mode = 6 + spawn(0) + + calc_path() + + if(path.len > 0) + blockcount = 0 + mode = 4 + src.visible_message("[src] makes a delighted ping!", "You hear a ping.") + playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + + else + src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + + mode = 7 + //if(6) // to_chat(world, "Pending path calc.") - //if(7) + //if(7) // to_chat(world, "No dest / no route.") - return - - -// calculates a path to the current destination -// given an optional turf to avoid -/obj/machinery/bot/mulebot/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 250, id=botcard, exclude=avoid) - if(!src.path) - src.path = list() - - -// sets the current destination -// signals all beacons matching the delivery code -// beacons will return a signal giving their locations -/obj/machinery/bot/mulebot/proc/set_destination(var/new_dest) - spawn(0) - new_destination = new_dest - post_signal(beacon_freq, "findbeacon", "delivery") - updateDialog() - -// starts bot moving to current destination -/obj/machinery/bot/mulebot/proc/start() - if(destination == home_destination) - mode = 3 - else - mode = 2 - icon_state = "mulebot[(wires.MobAvoid() != 0)]" - -// starts bot moving to home -// sends a beacon query to find -/obj/machinery/bot/mulebot/proc/start_home() - spawn(0) - set_destination(home_destination) - mode = 4 - icon_state = "mulebot[(wires.MobAvoid() != 0)]" - -// called when bot reaches current target -/obj/machinery/bot/mulebot/proc/at_target() - if(!reached_target) - src.visible_message("[src] makes a chiming sound!", "You hear a chime.") - playsound(get_turf(src), 'sound/machines/chime.ogg', 50, 0) - reached_target = 1 - - if(load) // if loaded, unload at target - unload(loaddir) - else - // not loaded - if(auto_pickup) // find a crate - var/atom/movable/AM - if(!wires.LoadCheck()) // if emagged, load first unanchored thing we find - for(var/atom/movable/A in get_step(loc, loaddir)) - if(!A.anchored) - AM = A - break - else // otherwise, look for crates only - for(var/i=1,i<=can_load.len,i++) - var/loadin_type = can_load[i] - AM = locate(loadin_type) in get_step(loc,loaddir) - if(AM) - load(AM) - break - - // whatever happened, check to see if we return home - - if(auto_return && destination != home_destination) - // auto return set and not at home already - start_home() - mode = 4 - else - mode = 0 // otherwise go idle - - send_status() // report status to anyone listening - - return - -// called when bot bumps into anything -/obj/machinery/bot/mulebot/Bump(var/atom/obs) - if(!wires.MobAvoid()) //usually just bumps, but if avoidance disabled knock over mobs - var/mob/M = obs - if(ismob(M)) - if(istype(M,/mob/living/silicon/robot)) - src.visible_message("[src] bumps into [M]!") - else - src.visible_message("[src] knocks over [M]!") - M.stop_pulling() - M.Stun(8) - M.Weaken(5) - M.lying = 1 - ..() - -/obj/machinery/bot/mulebot/alter_health() - return get_turf(src) - -// called from mob/living/carbon/human/Crossed() as well as .../alien/Crossed() -/obj/machinery/bot/mulebot/proc/RunOverCreature(var/mob/living/H,var/bloodcolor) - //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/bot/mulebot/proc/RunOverCreature() called tick#: [world.time]") - src.visible_message("[src] drives over [H]!") - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) - var/damage = rand(5,15) - H.apply_damage(2*damage, BRUTE, "head") - H.apply_damage(2*damage, BRUTE, "chest") - H.apply_damage(0.5*damage, BRUTE, "l_leg") - H.apply_damage(0.5*damage, BRUTE, "r_leg") - H.apply_damage(0.5*damage, BRUTE, "l_arm") - H.apply_damage(0.5*damage, BRUTE, "r_arm") - bloodiness += 4 - currentBloodColor=bloodcolor // For if species get different blood colors. - -// player on mulebot attempted to move -/obj/machinery/bot/mulebot/relaymove(var/mob/user) - if(user.stat) - return - if(load == user) - unload(0) - return - -// receive a radio signal -// used for control and beacon reception - -/obj/machinery/bot/mulebot/receive_signal(datum/signal/signal) - - if(!on || !wires) - return - - /* + return + + +// calculates a path to the current destination +// given an optional turf to avoid +/obj/machinery/bot/mulebot/proc/calc_path(var/turf/avoid = null) + src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 250, id=botcard, exclude=avoid) + if(!src.path) + src.path = list() + + +// sets the current destination +// signals all beacons matching the delivery code +// beacons will return a signal giving their locations +/obj/machinery/bot/mulebot/proc/set_destination(var/new_dest) + spawn(0) + new_destination = new_dest + post_signal(beacon_freq, "findbeacon", "delivery") + updateDialog() + +// starts bot moving to current destination +/obj/machinery/bot/mulebot/proc/start() + if(destination == home_destination) + mode = 3 + else + mode = 2 + icon_state = "mulebot[(wires.MobAvoid() != 0)]" + +// starts bot moving to home +// sends a beacon query to find +/obj/machinery/bot/mulebot/proc/start_home() + spawn(0) + set_destination(home_destination) + mode = 4 + icon_state = "mulebot[(wires.MobAvoid() != 0)]" + +// called when bot reaches current target +/obj/machinery/bot/mulebot/proc/at_target() + if(!reached_target) + src.visible_message("[src] makes a chiming sound!", "You hear a chime.") + playsound(get_turf(src), 'sound/machines/chime.ogg', 50, 0) + reached_target = 1 + + if(load) // if loaded, unload at target + unload(loaddir) + else + // not loaded + if(auto_pickup) // find a crate + var/atom/movable/AM + if(!wires.LoadCheck()) // if emagged, load first unanchored thing we find + for(var/atom/movable/A in get_step(loc, loaddir)) + if(!A.anchored) + AM = A + break + else // otherwise, look for crates only + for(var/i=1,i<=can_load.len,i++) + var/loadin_type = can_load[i] + AM = locate(loadin_type) in get_step(loc,loaddir) + if(AM) + load(AM) + break + + // whatever happened, check to see if we return home + + if(auto_return && destination != home_destination) + // auto return set and not at home already + start_home() + mode = 4 + else + mode = 0 // otherwise go idle + + send_status() // report status to anyone listening + + return + +// called when bot bumps into anything +/obj/machinery/bot/mulebot/Bump(var/atom/obs) + if(!wires.MobAvoid()) //usually just bumps, but if avoidance disabled knock over mobs + var/mob/M = obs + if(ismob(M)) + if(istype(M,/mob/living/silicon/robot)) + src.visible_message("[src] bumps into [M]!") + else + src.visible_message("[src] knocks over [M]!") + M.stop_pulling() + M.Stun(8) + M.Weaken(5) + M.lying = 1 + ..() + +/obj/machinery/bot/mulebot/alter_health() + return get_turf(src) + +// called from mob/living/carbon/human/Crossed() as well as .../alien/Crossed() +/obj/machinery/bot/mulebot/proc/RunOverCreature(var/mob/living/H,var/bloodcolor) + //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/bot/mulebot/proc/RunOverCreature() called tick#: [world.time]") + src.visible_message("[src] drives over [H]!") + playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) + var/damage = rand(5,15) + H.apply_damage(2*damage, BRUTE, "head") + H.apply_damage(2*damage, BRUTE, "chest") + H.apply_damage(0.5*damage, BRUTE, "l_leg") + H.apply_damage(0.5*damage, BRUTE, "r_leg") + H.apply_damage(0.5*damage, BRUTE, "l_arm") + H.apply_damage(0.5*damage, BRUTE, "r_arm") + bloodiness += 4 + currentBloodColor=bloodcolor // For if species get different blood colors. + +// player on mulebot attempted to move +/obj/machinery/bot/mulebot/relaymove(var/mob/user) + if(user.stat) + return + if(load == user) + unload(0) + return + +// receive a radio signal +// used for control and beacon reception + +/obj/machinery/bot/mulebot/receive_signal(datum/signal/signal) + + if(!on || !wires) + return + + /* to_chat(world, "rec signal: [signal.source]") - for(var/x in signal.data) + for(var/x in signal.data) to_chat(world, "* [x] = [signal.data[x]]") - */ - var/recv = signal.data["command"] - // process all-bot input - if(recv=="bot_status" && wires.RemoteRX()) - send_status() - - - recv = signal.data["command [suffix]"] - if(wires.RemoteRX()) - // process control input - switch(recv) - if("stop") - mode = 0 - return - - if("go") - start() - return - - if("target") - set_destination(signal.data["destination"] ) - return - - if("unload") - if(loc == target) - unload(loaddir) - else - unload(0) - return - - if("home") - start_home() - return - - if("bot_status") - send_status() - return - - if("autoret") - auto_return = text2num(signal.data["value"]) - return - - if("autopick") - auto_pickup = text2num(signal.data["value"]) - return - - // receive response from beacon - recv = signal.data["beacon"] - if(wires.BeaconRX()) - if(recv == new_destination) // if the recvd beacon location matches the set destination - // the we will navigate there - destination = new_destination - target = signal.source.loc - var/direction = signal.data["dir"] // this will be the load/unload dir - if(direction) - loaddir = text2num(direction) - else - loaddir = 0 - icon_state = "mulebot[(wires.MobAvoid() != null)]" - calc_path() - updateDialog() - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/mulebot/proc/post_signal(var/freq, var/key, var/value) - post_signal_multiple(freq, list("[key]" = value) ) - -// send a radio signal with multiple data key/values -/obj/machinery/bot/mulebot/proc/post_signal_multiple(var/freq, var/list/keyval) - - - if(freq == beacon_freq && !(wires.BeaconRX())) - return - if(freq == control_freq && !(wires.RemoteTX())) - return - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - signal.data = keyval + */ + var/recv = signal.data["command"] + // process all-bot input + if(recv=="bot_status" && wires.RemoteRX()) + send_status() + + + recv = signal.data["command [suffix]"] + if(wires.RemoteRX()) + // process control input + switch(recv) + if("stop") + mode = 0 + return + + if("go") + start() + return + + if("target") + set_destination(signal.data["destination"] ) + return + + if("unload") + if(loc == target) + unload(loaddir) + else + unload(0) + return + + if("home") + start_home() + return + + if("bot_status") + send_status() + return + + if("autoret") + auto_return = text2num(signal.data["value"]) + return + + if("autopick") + auto_pickup = text2num(signal.data["value"]) + return + + // receive response from beacon + recv = signal.data["beacon"] + if(wires.BeaconRX()) + if(recv == new_destination) // if the recvd beacon location matches the set destination + // the we will navigate there + destination = new_destination + target = signal.source.loc + var/direction = signal.data["dir"] // this will be the load/unload dir + if(direction) + loaddir = text2num(direction) + else + loaddir = 0 + icon_state = "mulebot[(wires.MobAvoid() != null)]" + calc_path() + updateDialog() + +// send a radio signal with a single data key/value pair +/obj/machinery/bot/mulebot/proc/post_signal(var/freq, var/key, var/value) + post_signal_multiple(freq, list("[key]" = value) ) + +// send a radio signal with multiple data key/values +/obj/machinery/bot/mulebot/proc/post_signal_multiple(var/freq, var/list/keyval) + + + if(freq == beacon_freq && !(wires.BeaconRX())) + return + if(freq == control_freq && !(wires.RemoteTX())) + return + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + //for(var/key in keyval) + // signal.data[key] = keyval[key] + signal.data = keyval // to_chat(world, "sent [key],[keyval[key]] on [freq]") - if (signal.data["findbeacon"]) - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - else if (signal.data["type"] == "mulebot") - frequency.post_signal(src, signal, filter = RADIO_MULEBOT) - else - frequency.post_signal(src, signal) - -// signals bot status etc. to controller -/obj/machinery/bot/mulebot/proc/send_status() - var/list/kv = list( - "type" = "mulebot", - "name" = suffix, - "loca" = (loc ? loc.loc : "Unknown"), // somehow loc can be null and cause a runtime - Quarxink - "mode" = mode, - "powr" = (cell ? cell.percent() : 0), - "dest" = destination, - "home" = home_destination, - "load" = load, - "retn" = auto_return, - "pick" = auto_pickup, - ) - post_signal_multiple(control_freq, kv) - -/obj/machinery/bot/mulebot/emp_act(severity) - if (cell) - cell.emp_act(severity) - if(load) - load.emp_act(severity) - ..() - - -/obj/machinery/bot/mulebot/explode() - src.visible_message("[src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - new /obj/item/device/assembly/prox_sensor(Tsec) - new /obj/item/stack/rods(Tsec) - new /obj/item/stack/rods(Tsec) - new /obj/item/stack/cable_coil/cut(Tsec) - if (cell) - cell.loc = Tsec - cell.update_icon() - cell = null - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) - O.New(O.loc) - unload(0) - qdel(src) + if (signal.data["findbeacon"]) + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + else if (signal.data["type"] == "mulebot") + frequency.post_signal(src, signal, filter = RADIO_MULEBOT) + else + frequency.post_signal(src, signal) + +// signals bot status etc. to controller +/obj/machinery/bot/mulebot/proc/send_status() + var/list/kv = list( + "type" = "mulebot", + "name" = suffix, + "loca" = (loc ? loc.loc : "Unknown"), // somehow loc can be null and cause a runtime - Quarxink + "mode" = mode, + "powr" = (cell ? cell.percent() : 0), + "dest" = destination, + "home" = home_destination, + "load" = load, + "retn" = auto_return, + "pick" = auto_pickup, + ) + post_signal_multiple(control_freq, kv) + +/obj/machinery/bot/mulebot/emp_act(severity) + if (cell) + cell.emp_act(severity) + if(load) + load.emp_act(severity) + ..() + + +/obj/machinery/bot/mulebot/explode() + src.visible_message("[src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + new /obj/item/device/assembly/prox_sensor(Tsec) + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/cable_coil/cut(Tsec) + if (cell) + cell.loc = Tsec + cell.update_icon() + cell = null + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) + O.New(O.loc) + unload(0) + qdel(src) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 3fe9ad2cd05..21ef704d3eb 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -1,868 +1,868 @@ -/obj/machinery/bot/secbot - name = "Securitron" - desc = "A little security robot. He looks less than thrilled." - icon = 'icons/obj/aibots.dmi' - icon_state = "secbot0" - layer = 5.0 - density = 0 - anchored = 0 - health = 25 - maxhealth = 25 - fire_dam_coeff = 0.7 - brute_dam_coeff = 0.5 -// weight = 1.0E7 - req_one_access = list(access_security, access_forensics_lockers) - var/mob/target - var/oldtarget_name - var/threatlevel = 0 - var/target_lastloc //Loc of target when arrested. - var/last_found //There's a delay - var/frustration = 0 - var/check_records = 1 -// var/emagged = 0 //Emagged Secbots view everyone as a criminal - - var/idcheck = 0 //If true, arrest people with no IDs - var/weaponscheck = 0 //If true, arrest people for weapons if they lack access var/check_records = 1 //Does it check security records? - var/arrest_type = 0 //If true, don't handcuff - var/declare_arrests = 0 //When making an arrest, should it notify everyone wearing sechuds? - var/next_harm_time = 0 - - var/mode = 0 -#define SECBOT_IDLE 0 // idle -#define SECBOT_HUNT 1 // found target, hunting -#define SECBOT_PREP_ARREST 2 // at target, preparing to arrest -#define SECBOT_ARREST 3 // arresting target -#define SECBOT_START_PATROL 4 // start patrol -#define SECBOT_PATROL 5 // patrolling -#define SECBOT_SUMMON 6 // summoned by PDA - - var/auto_patrol = 0 // set to make bot automatically patrol - - var/beacon_freq = 1445 // navigation beacon frequency - var/control_freq = 1447 // bot control frequency - - - var/turf/patrol_target // this is turf to navigate to (location of beacon) - var/new_destination // pending new destination (waiting for beacon response) - var/destination // destination description tag - var/next_destination // the next destination in the patrol route - var/list/path = new // list of path turfs - - var/blockcount = 0 //number of times retried a blocked path - var/awaiting_beacon = 0 // count of pticks awaiting a beacon response - - var/nearest_beacon // the nearest beacon's tag - var/turf/nearest_beacon_loc // the nearest beacon's location - var/weapons_check = 0 - var/safe_weapons = list( - /obj/item/weapon/gun/energy/laser/bluetag, - /obj/item/weapon/gun/energy/laser/redtag, - /obj/item/weapon/gun/energy/laser/practice, - /obj/item/weapon/gun/hookshot, - ) - light_color = LIGHT_COLOR_RED - power_change() - ..() - if(src.on) - set_light(2) - else - set_light(0) - - -/obj/machinery/bot/secbot/beepsky - name = "Officer Beep O'sky" - desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey." - idcheck = 0 - auto_patrol = 1 - weapons_check = 0 - declare_arrests = 1 - -/obj/item/weapon/secbot_assembly - name = "helmet/signaler assembly" - desc = "Some sort of bizarre assembly." - icon = 'icons/obj/aibots.dmi' - icon_state = "helmet_signaler" - item_state = "helmet" - var/build_step = 0 - var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess - -/obj/machinery/bot/secbot/New() - ..() - src.icon_state = "secbot[src.on]" - spawn(3) - src.botcard = new /obj/item/weapon/card/id(src) - var/datum/job/detective/J = new/datum/job/detective - src.botcard.access = J.get_access() - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - - -/obj/machinery/bot/secbot/turn_on() - ..() - src.icon_state = "secbot[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/secbot/turn_off() - ..() - src.target = null - src.oldtarget_name = null - src.anchored = 0 - src.mode = SECBOT_IDLE - walk_to(src,0) - src.icon_state = "secbot[src.on]" - src.updateUsrDialog() - -/obj/machinery/bot/secbot/attack_hand(mob/user as mob) - . = ..() - if(.) - return - usr.set_machine(src) - interact(user) - -/obj/machinery/bot/secbot/interact(mob/user as mob) - var/dat - - dat += text({" -Automatic Security Unit v1.3

      -Status: []
      -Behaviour controls are [src.locked ? "locked" : "unlocked"]
      -Maintenance panel panel is [src.open ? "opened" : "closed"]"}, - -"[src.on ? "On" : "Off"]" ) - - if(!src.locked || issilicon(user)) - dat += text({"
      -Arrest for No ID: []
      -Arrest for Unauthorized Weapons: []
      -Arrest for Warrant: []
      -
      -Operating Mode: []
      -Report Arrests: []
      -Auto Patrol: []"}, - -"[src.idcheck ? "Yes" : "No"]", -"[weaponscheck ? "Yes" : "No"]", -"[src.check_records ? "Yes" : "No"]", -"[src.arrest_type ? "Detain" : "Arrest"]", -"[src.declare_arrests ? "Yes" : "No"]", -"[auto_patrol ? "On" : "Off"]" ) - - - user << browse("Securitron v1.3 controls[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/bot/secbot/Topic(href, href_list) - if(..()) return 1 - usr.set_machine(src) - src.add_fingerprint(usr) - if((href_list["power"]) && (src.allowed(usr))) - if(src.on) - turn_off() - else - turn_on() - return - - switch(href_list["operation"]) - if("idcheck") - src.idcheck = !src.idcheck - src.updateUsrDialog() - if("weaponscheck") - weaponscheck = !weaponscheck - updateUsrDialog() - if("ignorerec") - src.check_records = !src.check_records - src.updateUsrDialog() - if("switchmode") - src.arrest_type = !src.arrest_type - src.updateUsrDialog() - if("patrol") - auto_patrol = !auto_patrol - mode = SECBOT_IDLE - updateUsrDialog() - if("declarearrests") - src.declare_arrests = !src.declare_arrests - src.updateUsrDialog() - -/obj/machinery/bot/secbot/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if(src.allowed(user) && !open && !emagged) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") - else - if(emagged) - to_chat(user, "ERROR") - if(open) - to_chat(user, "Please close the access panel before locking it.") - else - to_chat(user, "Access denied.") - else - ..() - if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") // Any intent but harm will heal, so we shouldn't get angry. - return - if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!target) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass. - threatlevel = user.assess_threat(src) - threatlevel += 6 - if(threatlevel > 0) - target = user - mode = SECBOT_HUNT - -/obj/machinery/bot/secbot/Emag(mob/user as mob) - ..() - if(open && !locked) - if(user) to_chat(user, "You short out [src]'s target assessment circuits.") - spawn(0) - for(var/mob/O in hearers(src, null)) - O.show_message("[src] buzzes oddly!", 1) - src.target = null - if(user) src.oldtarget_name = user.name - src.last_found = world.time - src.anchored = 0 - src.emagged = 2 - src.on = 1 - src.icon_state = "secbot[src.on]" - mode = SECBOT_IDLE - -/obj/machinery/bot/secbot/process() - //set background = 1 - - if(!src.on) - return - - switch(mode) - - if(SECBOT_IDLE) // idle - - walk_to(src,0) - look_for_perp() // see if any criminals are in range - if(!mode && auto_patrol) // still idle, and set to patrol - mode = SECBOT_START_PATROL // switch to patrol mode - - if(SECBOT_HUNT) // hunting for perp - - // if can't reach perp for long enough, go idle - if(src.frustration >= 8) - // for(var/mob/O in hearers(src, null)) -// to_chat(O, "[src] beeps, \"Backup requested! Suspect has evaded arrest.\"") - src.target = null - src.last_found = world.time - src.frustration = 0 - src.mode = SECBOT_IDLE - walk_to(src,0) - - if(target) // make sure target exists - if(!istype(target.loc, /turf)) - return - if(get_dist(src, src.target) <= 1) // if right next to perp - if(istype(src.target,/mob/living/carbon)) - playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) - src.icon_state = "secbot-c" - spawn(2) - src.icon_state = "secbot[src.on]" - var/mob/living/carbon/M = src.target - var/maxstuns = 4 - if(istype(M, /mob/living/carbon/human)) - if(M.stuttering < 10 && (!(M_HULK in M.mutations))) - M.stuttering = 10 - M.Stun(10) - M.Weaken(10) - else - M.Weaken(10) - M.stuttering = 10 - M.Stun(10) - if(declare_arrests) - declare() - target.visible_message("[target] has been stunned by [src]!",\ - "You have been stunned by [src]!") - maxstuns-- - if(maxstuns <= 0) - target = null - - if(declare_arrests) - var/area/location = get_area(src) - broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) - //visible_message("[src.target] has been stunned by [src]!") - - mode = SECBOT_PREP_ARREST - src.anchored = 1 - src.target_lastloc = M.loc - return - else if(istype(src.target,/mob/living/simple_animal)) - //just harmbaton them until dead - if(world.time > next_harm_time) - next_harm_time = world.time + 15 - playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) - visible_message("[src] beats [src.target] with the stun baton!") - src.icon_state = "secbot-c" - spawn(2) - src.icon_state = "secbot[src.on]" - - var/mob/living/simple_animal/S = src.target - if(S && istype(S)) - S.AdjustStunned(10) - S.adjustBruteLoss(15) - if(S.stat) - src.frustration = 8 - playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg'), 50, 0) - - else // not next to perp - var/turf/olddist = get_dist(src, src.target) - walk_to(src, src.target,1,4) - if((get_dist(src, src.target)) >= (olddist)) - src.frustration++ - else - src.frustration = 0 - else - src.frustration = 8 - - if(SECBOT_PREP_ARREST) // preparing to arrest target - - // see if he got away - if((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:weakened < 2)) - src.anchored = 0 - mode = SECBOT_HUNT - return - - if(istype(src.target,/mob/living/carbon) && !isalien(target)) - var/mob/living/carbon/C = target - if(!C.handcuffed && !src.arrest_type) - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) - mode = SECBOT_ARREST - visible_message("[src] is trying to put handcuffs on [src.target]!",\ - "[src] is trying to cut [src.target]'s hands off!") - - spawn(60) - if(Adjacent(target)) - /*if(src.target.handcuffed) - return*/ - - if(istype(src.target,/mob/living/carbon) && !isalien(target)) - C = target - if(!C.handcuffed) - C.handcuffed = new /obj/item/weapon/handcuffs(target) - C.update_inv_handcuffed() //update the handcuffs overlay - - mode = SECBOT_IDLE - src.target = null - src.anchored = 0 - src.last_found = world.time - src.frustration = 0 - - playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) - // var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.") - // src.speak(arrest_message) - - else - mode = SECBOT_IDLE - src.target = null - src.anchored = 0 - src.last_found = world.time - src.frustration = 0 - - if(SECBOT_ARREST) // arresting - - if(!target || !istype(target, /mob/living/carbon)) - src.anchored = 0 - mode = SECBOT_IDLE - return - else - var/mob/living/carbon/C = target - if(!C.handcuffed) - src.anchored = 0 - mode = SECBOT_IDLE - return - - - if(SECBOT_START_PATROL) // start a patrol - if(path != null) - if(path.len > 0 && patrol_target) // have a valid path, so just resume - mode = SECBOT_PATROL - return - - else if(patrol_target) // has patrol target already - spawn(0) - calc_path() // so just find a route to it - if(path.len == 0) - patrol_target = 0 - return - mode = SECBOT_PATROL - - - else // no patrol target, so need a new one - find_patrol_target() - speak("Engaging patrol mode.") - - - if(SECBOT_PATROL) // patrol mode - patrol_step() - spawn(5) - if(mode == SECBOT_PATROL) - patrol_step() - - if(SECBOT_SUMMON) // summoned to PDA - patrol_step() - spawn(4) - if(mode == SECBOT_SUMMON) - patrol_step() - sleep(4) - patrol_step() - - return - - -// perform a single patrol step - -/obj/machinery/bot/secbot/proc/patrol_step() - - - if(loc == patrol_target) // reached target - at_patrol_target() - return - - else if(path.len > 0 && patrol_target) // valid path - - var/turf/next = path[1] - if(next == loc) - path -= next - return - - - if(istype( next, /turf/simulated)) - - var/moved = step_towards(src, next) // attempt to move - if(moved) // successful move - blockcount = 0 - path -= loc - - look_for_perp() - else // failed to move - - blockcount++ - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - - spawn(2) - calc_path(next) - if(path.len == 0) - find_patrol_target() - else - blockcount = 0 - - return - - return - - else // not a valid turf - mode = SECBOT_IDLE - return - - else // no path, so calculate new one - mode = SECBOT_START_PATROL - - -// finds a new patrol target -/obj/machinery/bot/secbot/proc/find_patrol_target() - send_status() - if(awaiting_beacon) // awaiting beacon response - awaiting_beacon++ - if(awaiting_beacon > 5) // wait 5 secs for beacon response - find_nearest_beacon() // then go to nearest instead - return - - if(next_destination) - set_destination(next_destination) - else - find_nearest_beacon() - return - - -// finds the nearest beacon to self -// signals all beacons matching the patrol code -/obj/machinery/bot/secbot/proc/find_nearest_beacon() - nearest_beacon = null - new_destination = "__nearest__" - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - spawn(10) - awaiting_beacon = 0 - if(nearest_beacon) - set_destination(nearest_beacon) - else - auto_patrol = 0 - mode = SECBOT_IDLE - speak("Disengaging patrol mode.") - send_status() - - -/obj/machinery/bot/secbot/proc/at_patrol_target() - find_patrol_target() - return - - -// sets the current destination -// signals all beacons matching the patrol code -// beacons will return a signal giving their locations -/obj/machinery/bot/secbot/proc/set_destination(var/new_dest) - new_destination = new_dest - post_signal(beacon_freq, "findbeacon", "patrol") - awaiting_beacon = 1 - - -// receive a radio signal -// used for beacon reception - -/obj/machinery/bot/secbot/receive_signal(datum/signal/signal) - //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])") - if(!on) - return - - /* - to_chat(world, "rec signal: [signal.source]") - for(var/x in signal.data) - to_chat(world, "* [x] = [signal.data[x]]") - */ - - var/recv = signal.data["command"] - // process all-bot input - if(recv=="bot_status") - send_status() - - // check to see if we are the commanded bot - if(signal.data["active"] == src) - // process control input - switch(recv) - if("stop") - mode = SECBOT_IDLE - auto_patrol = 0 - return - - if("go") - mode = SECBOT_IDLE - auto_patrol = 1 - return - - if("summon") - patrol_target = signal.data["target"] - next_destination = destination - destination = null - awaiting_beacon = 0 - mode = SECBOT_SUMMON - calc_path() - speak("Responding.") - - return - - - - // receive response from beacon - recv = signal.data["beacon"] - var/valid = signal.data["patrol"] - if(!recv || !valid) - return - - if(recv == new_destination) // if the recvd beacon location matches the set destination - // the we will navigate there - destination = new_destination - patrol_target = signal.source.loc - next_destination = signal.data["next_patrol"] - awaiting_beacon = 0 - - // if looking for nearest beacon - else if(new_destination == "__nearest__") - var/dist = get_dist(src,signal.source.loc) - if(nearest_beacon) - - // note we ignore the beacon we are located at - if(dist>1 && dist 1) - nearest_beacon = recv - nearest_beacon_loc = signal.source.loc - return - - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/secbot/proc/post_signal(var/freq, var/key, var/value) - post_signal_multiple(freq, list("[key]" = value) ) - -// send a radio signal with multiple data key/values -/obj/machinery/bot/secbot/proc/post_signal_multiple(var/freq, var/list/keyval) - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - signal.data = keyval -// to_chat(world, "sent [key],[keyval[key]] on [freq]") - if(signal.data["findbeacon"]) - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - else if(signal.data["type"] == "secbot") - frequency.post_signal(src, signal, filter = RADIO_SECBOT) - else - frequency.post_signal(src, signal) - -// signals bot status etc. to controller -/obj/machinery/bot/secbot/proc/send_status() - var/list/kv = list( - "type" = "secbot", - "name" = name, - "loca" = loc.loc, // area - "mode" = mode - ) - post_signal_multiple(control_freq, kv) - - - -// calculates a path to the current destination -// given an optional turf to avoid -/obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null) - src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 120, id=botcard, exclude=avoid) - if(!src.path) - src.path = list() - - -// look for a criminal in view of the bot - -/obj/machinery/bot/secbot/proc/look_for_perp() - src.anchored = 0 - for (var/mob/living/M in view(7,src)) //Let's find us a criminal - if(istype(M, /mob/living/carbon)) - var/mob/living/carbon/C = M - if((C.stat) || (C.handcuffed)) - continue - - if((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) - continue - - if(ishuman(C)) - src.threatlevel = src.assess_perp(C) - else if(ismonkey(C) && isbadmonkey(C)) //Beepsky can detect jungle fever monkeys - src.threatlevel = 666 - else - continue - else - continue - /* - else if(istype(M, /mob/living/simple_animal/hostile)) - if(M.stat == DEAD) - continue - // Ignore lazarus-injected mobs. - if(dd_hasprefix(C.faction, "lazarus")) - continue - // Minebots only, I hope. - if(M.faction == "neutral") - continue - src.threatlevel = 4 - */ - - if(!src.threatlevel) - continue - - else if(src.threatlevel >= 4) - src.target = M - src.oldtarget_name = M.name - src.speak("Level [src.threatlevel] infraction alert!") - playsound(get_turf(src), pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) - src.visible_message("[src] points at [M.name]!") - mode = SECBOT_HUNT - spawn(0) - process() // ensure bot quickly responds to a perp - break - else - continue - - -//If the security records say to arrest them, arrest them -//Or if they have weapons and aren't security, arrest them. -/obj/machinery/bot/secbot/proc/assess_perp(mob/living/carbon/human/perp as mob) - var/threatcount = 0 - - if(src.emagged == 2) return 10 //Everyone is a criminal! - - if(src.idcheck && !src.allowed(perp)) - - if(istype(perp.l_hand, /obj/item/weapon/gun) || istype(perp.l_hand, /obj/item/weapon/melee)) - if(!istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 4 - - if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) - if(!istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 4 - - if(istype(perp:belt, /obj/item/weapon/gun) || istype(perp:belt, /obj/item/weapon/melee)) - if(!istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag) \ - && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/practice)) - threatcount += 2 - - if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) - threatcount += 2 - - if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") - threatcount += 2 - - //Agent cards lower threatlevel. - if(perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - threatcount -= 2 - - if(src.check_records) - for (var/datum/data/record/E in data_core.general) - var/perpname = perp.name - if(perp.wear_id) - var/obj/item/weapon/card/id/id = perp.wear_id.GetID() - if(id) - perpname = id.registered_name - - if(E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - threatcount = 4 - break - - return threatcount - -/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)) - D.open() - src.frustration = 0 - else if((istype(M, /mob/living/)) && (!src.anchored)) - src.loc = M:loc - src.frustration = 0 - return - -/* terrible -/obj/machinery/bot/secbot/Bumped(atom/movable/M as mob|obj) - spawn(0) - if(M) - var/turf/T = get_turf(src) - M:loc = T -*/ - -/obj/machinery/bot/secbot/proc/speak(var/message) - visible_message("[src] beeps, \"[message]\"",\ - drugged_message="[src] beeps, \"[pick("Wait! Let's be friends!","Wait for me!","You're so cool!","Who's your favourite pony?","I-It's not like I like you or anything...","Wanna see a magic trick?","Let's go have fun, assistant-kun~")]\"") - return - - -/obj/machinery/bot/secbot/explode() - - walk_to(src,0) - src.visible_message("[src] blows apart!", 1) - var/turf/Tsec = get_turf(src) - - var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec) - Sa.build_step = 1 - Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") - Sa.created_name = src.name - new /obj/item/device/assembly/prox_sensor(Tsec) - new /obj/item/weapon/melee/baton/loaded(Tsec) - - if(prob(50)) - new /obj/item/robot_parts/l_arm(Tsec) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) - O.New(O.loc) - qdel(src) - -/obj/machinery/bot/secbot/attack_alien(var/mob/living/carbon/alien/user as mob) - ..() - if(!isalien(target)) - src.target = user - src.mode = SECBOT_HUNT - -//Secbot Construction - -/obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob) - ..() - if(!issignaler(S)) - ..() - return - - if(src.type != /obj/item/clothing/head/helmet) //Eh, but we don't want people making secbots out of space helmets. - return - - if(S.secured) - qdel(S) - var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly - user.put_in_hands(A) - to_chat(user, "You add the signaler to the helmet.") - user.drop_from_inventory(src) - qdel(src) - else - return - -/obj/item/weapon/secbot_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if((istype(W, /obj/item/weapon/weldingtool)) && (!src.build_step)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - src.build_step++ - src.overlays += image('icons/obj/aibots.dmi', "hs_hole") - to_chat(user, "You weld a hole in [src]!") - - else if(isprox(W) && (src.build_step == 1)) - if(user.drop_item(W)) - src.build_step++ - to_chat(user, "You add the prox sensor to [src]!") - src.overlays += image('icons/obj/aibots.dmi', "hs_eye") - src.name = "helmet/signaler/prox sensor assembly" - qdel(W) - - else if(((istype(W, /obj/item/robot_parts/l_arm)) || (istype(W, /obj/item/robot_parts/r_arm))) && (src.build_step == 2)) - if(user.drop_item(W)) - src.build_step++ - to_chat(user, "You add the robot arm to [src]!") - src.name = "helmet/signaler/prox sensor/robot arm assembly" - src.overlays += image('icons/obj/aibots.dmi', "hs_arm") - qdel(W) - - else if((istype(W, /obj/item/weapon/melee/baton)) && (src.build_step >= 3)) - if(user.drop_item(W)) - src.build_step++ - to_chat(user, "You complete the Securitron! Beep boop.") - var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot - S.loc = get_turf(src) - S.name = src.created_name - qdel(W) - qdel(src) - - else if(istype(W, /obj/item/weapon/pen)) - var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) - if(!t) - return - if(!in_range(src, usr) && src.loc != usr) - return - src.created_name = t - -/obj/machinery/bot/secbot/declare() - var/area/location = get_area(src) - declare_message = "\icon[src] [name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] scumbag [target] in [location]" - ..() - -/obj/machinery/bot/secbot/proc/check_for_weapons(var/obj/item/slot_item) - if(istype(slot_item, /obj/item/weapon/gun) || istype(slot_item, /obj/item/weapon/melee)) - if(!(slot_item.type in safe_weapons)) - return 1 - return 0 +/obj/machinery/bot/secbot + name = "Securitron" + desc = "A little security robot. He looks less than thrilled." + icon = 'icons/obj/aibots.dmi' + icon_state = "secbot0" + layer = 5.0 + density = 0 + anchored = 0 + health = 25 + maxhealth = 25 + fire_dam_coeff = 0.7 + brute_dam_coeff = 0.5 +// weight = 1.0E7 + req_one_access = list(access_security, access_forensics_lockers) + var/mob/target + var/oldtarget_name + var/threatlevel = 0 + var/target_lastloc //Loc of target when arrested. + var/last_found //There's a delay + var/frustration = 0 + var/check_records = 1 +// var/emagged = 0 //Emagged Secbots view everyone as a criminal + + var/idcheck = 0 //If true, arrest people with no IDs + var/weaponscheck = 0 //If true, arrest people for weapons if they lack access var/check_records = 1 //Does it check security records? + var/arrest_type = 0 //If true, don't handcuff + var/declare_arrests = 0 //When making an arrest, should it notify everyone wearing sechuds? + var/next_harm_time = 0 + + var/mode = 0 +#define SECBOT_IDLE 0 // idle +#define SECBOT_HUNT 1 // found target, hunting +#define SECBOT_PREP_ARREST 2 // at target, preparing to arrest +#define SECBOT_ARREST 3 // arresting target +#define SECBOT_START_PATROL 4 // start patrol +#define SECBOT_PATROL 5 // patrolling +#define SECBOT_SUMMON 6 // summoned by PDA + + var/auto_patrol = 0 // set to make bot automatically patrol + + var/beacon_freq = 1445 // navigation beacon frequency + var/control_freq = 1447 // bot control frequency + + + var/turf/patrol_target // this is turf to navigate to (location of beacon) + var/new_destination // pending new destination (waiting for beacon response) + var/destination // destination description tag + var/next_destination // the next destination in the patrol route + var/list/path = new // list of path turfs + + var/blockcount = 0 //number of times retried a blocked path + var/awaiting_beacon = 0 // count of pticks awaiting a beacon response + + var/nearest_beacon // the nearest beacon's tag + var/turf/nearest_beacon_loc // the nearest beacon's location + var/weapons_check = 0 + var/safe_weapons = list( + /obj/item/weapon/gun/energy/laser/bluetag, + /obj/item/weapon/gun/energy/laser/redtag, + /obj/item/weapon/gun/energy/laser/practice, + /obj/item/weapon/gun/hookshot, + ) + light_color = LIGHT_COLOR_RED + power_change() + ..() + if(src.on) + set_light(2) + else + set_light(0) + + +/obj/machinery/bot/secbot/beepsky + name = "Officer Beep O'sky" + desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey." + idcheck = 0 + auto_patrol = 1 + weapons_check = 0 + declare_arrests = 1 + +/obj/item/weapon/secbot_assembly + name = "helmet/signaler assembly" + desc = "Some sort of bizarre assembly." + icon = 'icons/obj/aibots.dmi' + icon_state = "helmet_signaler" + item_state = "helmet" + var/build_step = 0 + var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess + +/obj/machinery/bot/secbot/New() + ..() + src.icon_state = "secbot[src.on]" + spawn(3) + src.botcard = new /obj/item/weapon/card/id(src) + var/datum/job/detective/J = new/datum/job/detective + src.botcard.access = J.get_access() + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + + +/obj/machinery/bot/secbot/turn_on() + ..() + src.icon_state = "secbot[src.on]" + src.updateUsrDialog() + +/obj/machinery/bot/secbot/turn_off() + ..() + src.target = null + src.oldtarget_name = null + src.anchored = 0 + src.mode = SECBOT_IDLE + walk_to(src,0) + src.icon_state = "secbot[src.on]" + src.updateUsrDialog() + +/obj/machinery/bot/secbot/attack_hand(mob/user as mob) + . = ..() + if(.) + return + usr.set_machine(src) + interact(user) + +/obj/machinery/bot/secbot/interact(mob/user as mob) + var/dat + + dat += text({" +Automatic Security Unit v1.3

      +Status: []
      +Behaviour controls are [src.locked ? "locked" : "unlocked"]
      +Maintenance panel panel is [src.open ? "opened" : "closed"]"}, + +"[src.on ? "On" : "Off"]" ) + + if(!src.locked || issilicon(user)) + dat += text({"
      +Arrest for No ID: []
      +Arrest for Unauthorized Weapons: []
      +Arrest for Warrant: []
      +
      +Operating Mode: []
      +Report Arrests: []
      +Auto Patrol: []"}, + +"[src.idcheck ? "Yes" : "No"]", +"[weaponscheck ? "Yes" : "No"]", +"[src.check_records ? "Yes" : "No"]", +"[src.arrest_type ? "Detain" : "Arrest"]", +"[src.declare_arrests ? "Yes" : "No"]", +"[auto_patrol ? "On" : "Off"]" ) + + + user << browse("Securitron v1.3 controls[dat]", "window=autosec") + onclose(user, "autosec") + return + +/obj/machinery/bot/secbot/Topic(href, href_list) + if(..()) return 1 + usr.set_machine(src) + src.add_fingerprint(usr) + if((href_list["power"]) && (src.allowed(usr))) + if(src.on) + turn_off() + else + turn_on() + return + + switch(href_list["operation"]) + if("idcheck") + src.idcheck = !src.idcheck + src.updateUsrDialog() + if("weaponscheck") + weaponscheck = !weaponscheck + updateUsrDialog() + if("ignorerec") + src.check_records = !src.check_records + src.updateUsrDialog() + if("switchmode") + src.arrest_type = !src.arrest_type + src.updateUsrDialog() + if("patrol") + auto_patrol = !auto_patrol + mode = SECBOT_IDLE + updateUsrDialog() + if("declarearrests") + src.declare_arrests = !src.declare_arrests + src.updateUsrDialog() + +/obj/machinery/bot/secbot/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if(src.allowed(user) && !open && !emagged) + src.locked = !src.locked + to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") + else + if(emagged) + to_chat(user, "ERROR") + if(open) + to_chat(user, "Please close the access panel before locking it.") + else + to_chat(user, "Access denied.") + else + ..() + if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") // Any intent but harm will heal, so we shouldn't get angry. + return + if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!target) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass. + threatlevel = user.assess_threat(src) + threatlevel += 6 + if(threatlevel > 0) + target = user + mode = SECBOT_HUNT + +/obj/machinery/bot/secbot/Emag(mob/user as mob) + ..() + if(open && !locked) + if(user) to_chat(user, "You short out [src]'s target assessment circuits.") + spawn(0) + for(var/mob/O in hearers(src, null)) + O.show_message("[src] buzzes oddly!", 1) + src.target = null + if(user) src.oldtarget_name = user.name + src.last_found = world.time + src.anchored = 0 + src.emagged = 2 + src.on = 1 + src.icon_state = "secbot[src.on]" + mode = SECBOT_IDLE + +/obj/machinery/bot/secbot/process() + //set background = 1 + + if(!src.on) + return + + switch(mode) + + if(SECBOT_IDLE) // idle + + walk_to(src,0) + look_for_perp() // see if any criminals are in range + if(!mode && auto_patrol) // still idle, and set to patrol + mode = SECBOT_START_PATROL // switch to patrol mode + + if(SECBOT_HUNT) // hunting for perp + + // if can't reach perp for long enough, go idle + if(src.frustration >= 8) + // for(var/mob/O in hearers(src, null)) +// to_chat(O, "[src] beeps, \"Backup requested! Suspect has evaded arrest.\"") + src.target = null + src.last_found = world.time + src.frustration = 0 + src.mode = SECBOT_IDLE + walk_to(src,0) + + if(target) // make sure target exists + if(!istype(target.loc, /turf)) + return + if(get_dist(src, src.target) <= 1) // if right next to perp + if(istype(src.target,/mob/living/carbon)) + playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) + src.icon_state = "secbot-c" + spawn(2) + src.icon_state = "secbot[src.on]" + var/mob/living/carbon/M = src.target + var/maxstuns = 4 + if(istype(M, /mob/living/carbon/human)) + if(M.stuttering < 10 && (!(M_HULK in M.mutations))) + M.stuttering = 10 + M.Stun(10) + M.Weaken(10) + else + M.Weaken(10) + M.stuttering = 10 + M.Stun(10) + if(declare_arrests) + declare() + target.visible_message("[target] has been stunned by [src]!",\ + "You have been stunned by [src]!") + maxstuns-- + if(maxstuns <= 0) + target = null + + if(declare_arrests) + var/area/location = get_area(src) + broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) + //visible_message("[src.target] has been stunned by [src]!") + + mode = SECBOT_PREP_ARREST + src.anchored = 1 + src.target_lastloc = M.loc + return + else if(istype(src.target,/mob/living/simple_animal)) + //just harmbaton them until dead + if(world.time > next_harm_time) + next_harm_time = world.time + 15 + playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) + visible_message("[src] beats [src.target] with the stun baton!") + src.icon_state = "secbot-c" + spawn(2) + src.icon_state = "secbot[src.on]" + + var/mob/living/simple_animal/S = src.target + if(S && istype(S)) + S.AdjustStunned(10) + S.adjustBruteLoss(15) + if(S.stat) + src.frustration = 8 + playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + + else // not next to perp + var/turf/olddist = get_dist(src, src.target) + walk_to(src, src.target,1,4) + if((get_dist(src, src.target)) >= (olddist)) + src.frustration++ + else + src.frustration = 0 + else + src.frustration = 8 + + if(SECBOT_PREP_ARREST) // preparing to arrest target + + // see if he got away + if((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc) && src.target:weakened < 2)) + src.anchored = 0 + mode = SECBOT_HUNT + return + + if(istype(src.target,/mob/living/carbon) && !isalien(target)) + var/mob/living/carbon/C = target + if(!C.handcuffed && !src.arrest_type) + playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + mode = SECBOT_ARREST + visible_message("[src] is trying to put handcuffs on [src.target]!",\ + "[src] is trying to cut [src.target]'s hands off!") + + spawn(60) + if(Adjacent(target)) + /*if(src.target.handcuffed) + return*/ + + if(istype(src.target,/mob/living/carbon) && !isalien(target)) + C = target + if(!C.handcuffed) + C.handcuffed = new /obj/item/weapon/handcuffs(target) + C.update_inv_handcuffed() //update the handcuffs overlay + + mode = SECBOT_IDLE + src.target = null + src.anchored = 0 + src.last_found = world.time + src.frustration = 0 + + playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + // var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.") + // src.speak(arrest_message) + + else + mode = SECBOT_IDLE + src.target = null + src.anchored = 0 + src.last_found = world.time + src.frustration = 0 + + if(SECBOT_ARREST) // arresting + + if(!target || !istype(target, /mob/living/carbon)) + src.anchored = 0 + mode = SECBOT_IDLE + return + else + var/mob/living/carbon/C = target + if(!C.handcuffed) + src.anchored = 0 + mode = SECBOT_IDLE + return + + + if(SECBOT_START_PATROL) // start a patrol + if(path != null) + if(path.len > 0 && patrol_target) // have a valid path, so just resume + mode = SECBOT_PATROL + return + + else if(patrol_target) // has patrol target already + spawn(0) + calc_path() // so just find a route to it + if(path.len == 0) + patrol_target = 0 + return + mode = SECBOT_PATROL + + + else // no patrol target, so need a new one + find_patrol_target() + speak("Engaging patrol mode.") + + + if(SECBOT_PATROL) // patrol mode + patrol_step() + spawn(5) + if(mode == SECBOT_PATROL) + patrol_step() + + if(SECBOT_SUMMON) // summoned to PDA + patrol_step() + spawn(4) + if(mode == SECBOT_SUMMON) + patrol_step() + sleep(4) + patrol_step() + + return + + +// perform a single patrol step + +/obj/machinery/bot/secbot/proc/patrol_step() + + + if(loc == patrol_target) // reached target + at_patrol_target() + return + + else if(path.len > 0 && patrol_target) // valid path + + var/turf/next = path[1] + if(next == loc) + path -= next + return + + + if(istype( next, /turf/simulated)) + + var/moved = step_towards(src, next) // attempt to move + if(moved) // successful move + blockcount = 0 + path -= loc + + look_for_perp() + else // failed to move + + blockcount++ + + if(blockcount > 5) // attempt 5 times before recomputing + // find new path excluding blocked turf + + spawn(2) + calc_path(next) + if(path.len == 0) + find_patrol_target() + else + blockcount = 0 + + return + + return + + else // not a valid turf + mode = SECBOT_IDLE + return + + else // no path, so calculate new one + mode = SECBOT_START_PATROL + + +// finds a new patrol target +/obj/machinery/bot/secbot/proc/find_patrol_target() + send_status() + if(awaiting_beacon) // awaiting beacon response + awaiting_beacon++ + if(awaiting_beacon > 5) // wait 5 secs for beacon response + find_nearest_beacon() // then go to nearest instead + return + + if(next_destination) + set_destination(next_destination) + else + find_nearest_beacon() + return + + +// finds the nearest beacon to self +// signals all beacons matching the patrol code +/obj/machinery/bot/secbot/proc/find_nearest_beacon() + nearest_beacon = null + new_destination = "__nearest__" + post_signal(beacon_freq, "findbeacon", "patrol") + awaiting_beacon = 1 + spawn(10) + awaiting_beacon = 0 + if(nearest_beacon) + set_destination(nearest_beacon) + else + auto_patrol = 0 + mode = SECBOT_IDLE + speak("Disengaging patrol mode.") + send_status() + + +/obj/machinery/bot/secbot/proc/at_patrol_target() + find_patrol_target() + return + + +// sets the current destination +// signals all beacons matching the patrol code +// beacons will return a signal giving their locations +/obj/machinery/bot/secbot/proc/set_destination(var/new_dest) + new_destination = new_dest + post_signal(beacon_freq, "findbeacon", "patrol") + awaiting_beacon = 1 + + +// receive a radio signal +// used for beacon reception + +/obj/machinery/bot/secbot/receive_signal(datum/signal/signal) + //log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/bot/secbot/receive_signal([signal.debug_print()])") + if(!on) + return + + /* + to_chat(world, "rec signal: [signal.source]") + for(var/x in signal.data) + to_chat(world, "* [x] = [signal.data[x]]") + */ + + var/recv = signal.data["command"] + // process all-bot input + if(recv=="bot_status") + send_status() + + // check to see if we are the commanded bot + if(signal.data["active"] == src) + // process control input + switch(recv) + if("stop") + mode = SECBOT_IDLE + auto_patrol = 0 + return + + if("go") + mode = SECBOT_IDLE + auto_patrol = 1 + return + + if("summon") + patrol_target = signal.data["target"] + next_destination = destination + destination = null + awaiting_beacon = 0 + mode = SECBOT_SUMMON + calc_path() + speak("Responding.") + + return + + + + // receive response from beacon + recv = signal.data["beacon"] + var/valid = signal.data["patrol"] + if(!recv || !valid) + return + + if(recv == new_destination) // if the recvd beacon location matches the set destination + // the we will navigate there + destination = new_destination + patrol_target = signal.source.loc + next_destination = signal.data["next_patrol"] + awaiting_beacon = 0 + + // if looking for nearest beacon + else if(new_destination == "__nearest__") + var/dist = get_dist(src,signal.source.loc) + if(nearest_beacon) + + // note we ignore the beacon we are located at + if(dist>1 && dist 1) + nearest_beacon = recv + nearest_beacon_loc = signal.source.loc + return + + +// send a radio signal with a single data key/value pair +/obj/machinery/bot/secbot/proc/post_signal(var/freq, var/key, var/value) + post_signal_multiple(freq, list("[key]" = value) ) + +// send a radio signal with multiple data key/values +/obj/machinery/bot/secbot/proc/post_signal_multiple(var/freq, var/list/keyval) + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + //for(var/key in keyval) + // signal.data[key] = keyval[key] + signal.data = keyval +// to_chat(world, "sent [key],[keyval[key]] on [freq]") + if(signal.data["findbeacon"]) + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + else if(signal.data["type"] == "secbot") + frequency.post_signal(src, signal, filter = RADIO_SECBOT) + else + frequency.post_signal(src, signal) + +// signals bot status etc. to controller +/obj/machinery/bot/secbot/proc/send_status() + var/list/kv = list( + "type" = "secbot", + "name" = name, + "loca" = loc.loc, // area + "mode" = mode + ) + post_signal_multiple(control_freq, kv) + + + +// calculates a path to the current destination +// given an optional turf to avoid +/obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null) + src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 120, id=botcard, exclude=avoid) + if(!src.path) + src.path = list() + + +// look for a criminal in view of the bot + +/obj/machinery/bot/secbot/proc/look_for_perp() + src.anchored = 0 + for (var/mob/living/M in view(7,src)) //Let's find us a criminal + if(istype(M, /mob/living/carbon)) + var/mob/living/carbon/C = M + if((C.stat) || (C.handcuffed)) + continue + + if((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) + continue + + if(ishuman(C)) + src.threatlevel = src.assess_perp(C) + else if(ismonkey(C) && isbadmonkey(C)) //Beepsky can detect jungle fever monkeys + src.threatlevel = 666 + else + continue + else + continue + /* + else if(istype(M, /mob/living/simple_animal/hostile)) + if(M.stat == DEAD) + continue + // Ignore lazarus-injected mobs. + if(dd_hasprefix(C.faction, "lazarus")) + continue + // Minebots only, I hope. + if(M.faction == "neutral") + continue + src.threatlevel = 4 + */ + + if(!src.threatlevel) + continue + + else if(src.threatlevel >= 4) + src.target = M + src.oldtarget_name = M.name + src.speak("Level [src.threatlevel] infraction alert!") + playsound(get_turf(src), pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) + src.visible_message("[src] points at [M.name]!") + mode = SECBOT_HUNT + spawn(0) + process() // ensure bot quickly responds to a perp + break + else + continue + + +//If the security records say to arrest them, arrest them +//Or if they have weapons and aren't security, arrest them. +/obj/machinery/bot/secbot/proc/assess_perp(mob/living/carbon/human/perp as mob) + var/threatcount = 0 + + if(src.emagged == 2) return 10 //Everyone is a criminal! + + if(src.idcheck && !src.allowed(perp)) + + if(istype(perp.l_hand, /obj/item/weapon/gun) || istype(perp.l_hand, /obj/item/weapon/melee)) + if(!istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp.l_hand, /obj/item/weapon/gun/energy/laser/practice)) + threatcount += 4 + + if(istype(perp.r_hand, /obj/item/weapon/gun) || istype(perp.r_hand, /obj/item/weapon/melee)) + if(!istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp.r_hand, /obj/item/weapon/gun/energy/laser/practice)) + threatcount += 4 + + if(istype(perp:belt, /obj/item/weapon/gun) || istype(perp:belt, /obj/item/weapon/melee)) + if(!istype(perp:belt, /obj/item/weapon/gun/energy/laser/bluetag) \ + && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/redtag) \ + && !istype(perp:belt, /obj/item/weapon/gun/energy/laser/practice)) + threatcount += 2 + + if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) + threatcount += 2 + + if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") + threatcount += 2 + + //Agent cards lower threatlevel. + if(perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + threatcount -= 2 + + if(src.check_records) + for (var/datum/data/record/E in data_core.general) + var/perpname = perp.name + if(perp.wear_id) + var/obj/item/weapon/card/id/id = perp.wear_id.GetID() + if(id) + perpname = id.registered_name + + if(E.fields["name"] == perpname) + for (var/datum/data/record/R in data_core.security) + if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) + threatcount = 4 + break + + return threatcount + +/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)) + D.open() + src.frustration = 0 + else if((istype(M, /mob/living/)) && (!src.anchored)) + src.loc = M:loc + src.frustration = 0 + return + +/* terrible +/obj/machinery/bot/secbot/Bumped(atom/movable/M as mob|obj) + spawn(0) + if(M) + var/turf/T = get_turf(src) + M:loc = T +*/ + +/obj/machinery/bot/secbot/proc/speak(var/message) + visible_message("[src] beeps, \"[message]\"",\ + drugged_message="[src] beeps, \"[pick("Wait! Let's be friends!","Wait for me!","You're so cool!","Who's your favourite pony?","I-It's not like I like you or anything...","Wanna see a magic trick?","Let's go have fun, assistant-kun~")]\"") + return + + +/obj/machinery/bot/secbot/explode() + + walk_to(src,0) + src.visible_message("[src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec) + Sa.build_step = 1 + Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") + Sa.created_name = src.name + new /obj/item/device/assembly/prox_sensor(Tsec) + new /obj/item/weapon/melee/baton/loaded(Tsec) + + if(prob(50)) + new /obj/item/robot_parts/l_arm(Tsec) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) + O.New(O.loc) + qdel(src) + +/obj/machinery/bot/secbot/attack_alien(var/mob/living/carbon/alien/user as mob) + ..() + if(!isalien(target)) + src.target = user + src.mode = SECBOT_HUNT + +//Secbot Construction + +/obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob) + ..() + if(!issignaler(S)) + ..() + return + + if(src.type != /obj/item/clothing/head/helmet) //Eh, but we don't want people making secbots out of space helmets. + return + + if(S.secured) + qdel(S) + var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly + user.put_in_hands(A) + to_chat(user, "You add the signaler to the helmet.") + user.drop_from_inventory(src) + qdel(src) + else + return + +/obj/item/weapon/secbot_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if((istype(W, /obj/item/weapon/weldingtool)) && (!src.build_step)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + src.build_step++ + src.overlays += image('icons/obj/aibots.dmi', "hs_hole") + to_chat(user, "You weld a hole in [src]!") + + else if(isprox(W) && (src.build_step == 1)) + if(user.drop_item(W)) + src.build_step++ + to_chat(user, "You add the prox sensor to [src]!") + src.overlays += image('icons/obj/aibots.dmi', "hs_eye") + src.name = "helmet/signaler/prox sensor assembly" + qdel(W) + + else if(((istype(W, /obj/item/robot_parts/l_arm)) || (istype(W, /obj/item/robot_parts/r_arm))) && (src.build_step == 2)) + if(user.drop_item(W)) + src.build_step++ + to_chat(user, "You add the robot arm to [src]!") + src.name = "helmet/signaler/prox sensor/robot arm assembly" + src.overlays += image('icons/obj/aibots.dmi', "hs_arm") + qdel(W) + + else if((istype(W, /obj/item/weapon/melee/baton)) && (src.build_step >= 3)) + if(user.drop_item(W)) + src.build_step++ + to_chat(user, "You complete the Securitron! Beep boop.") + var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot + S.loc = get_turf(src) + S.name = src.created_name + qdel(W) + qdel(src) + + else if(istype(W, /obj/item/weapon/pen)) + var/t = copytext(stripped_input(user, "Enter new robot name", src.name, src.created_name),1,MAX_NAME_LEN) + if(!t) + return + if(!in_range(src, usr) && src.loc != usr) + return + src.created_name = t + +/obj/machinery/bot/secbot/declare() + var/area/location = get_area(src) + declare_message = "\icon[src] [name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] scumbag [target] in [location]" + ..() + +/obj/machinery/bot/secbot/proc/check_for_weapons(var/obj/item/slot_item) + if(istype(slot_item, /obj/item/weapon/gun) || istype(slot_item, /obj/item/weapon/melee)) + if(!(slot_item.type in safe_weapons)) + return 1 + return 0 diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 41e4c9a6492..3539d26a1dc 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -1,71 +1,71 @@ -/obj/machinery/driver_button - name = "mass driver button" - icon = 'icons/obj/objects.dmi' - icon_state = "launcherbtt" - desc = "A remote control switch for a mass driver." - var/id_tag = "default" - var/active = 0 - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/machinery/driver_button/New(turf/loc, var/w_dir=null) - ..() - machine_flags |= MULTITOOL_MENU - switch(w_dir) - if(NORTH) - pixel_y = 25 - if(SOUTH) - pixel_y = -25 - if(EAST) - pixel_x = 25 - if(WEST) - pixel_x = -25 - -/obj/machinery/ignition_switch - name = "ignition switch" - icon = 'icons/obj/objects.dmi' - icon_state = "launcherbtt" - desc = "A remote control switch for a mounted igniter." - var/id_tag = null - var/active = 0 - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/machinery/flasher_button - name = "flasher button" - desc = "A remote control switch for a mounted flasher." - icon = 'icons/obj/objects.dmi' - icon_state = "launcherbtt" - var/id_tag = null - var/active = 0 - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/machinery/crema_switch - desc = "Burn baby burn!" - name = "crematorium igniter" - icon = 'icons/obj/power.dmi' - icon_state = "crema_switch" - anchored = 1.0 - req_access = list(access_crematorium) - var/on = 0 - var/otherarea = null - var/id = 1 - - ghost_read = 0 // Deactivate ghost touching. +/obj/machinery/driver_button + name = "mass driver button" + icon = 'icons/obj/objects.dmi' + icon_state = "launcherbtt" + desc = "A remote control switch for a mass driver." + var/id_tag = "default" + var/active = 0 + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/machinery/driver_button/New(turf/loc, var/w_dir=null) + ..() + machine_flags |= MULTITOOL_MENU + switch(w_dir) + if(NORTH) + pixel_y = 25 + if(SOUTH) + pixel_y = -25 + if(EAST) + pixel_x = 25 + if(WEST) + pixel_x = -25 + +/obj/machinery/ignition_switch + name = "ignition switch" + icon = 'icons/obj/objects.dmi' + icon_state = "launcherbtt" + desc = "A remote control switch for a mounted igniter." + var/id_tag = null + var/active = 0 + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/machinery/flasher_button + name = "flasher button" + desc = "A remote control switch for a mounted flasher." + icon = 'icons/obj/objects.dmi' + icon_state = "launcherbtt" + var/id_tag = null + var/active = 0 + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/machinery/crema_switch + desc = "Burn baby burn!" + name = "crematorium igniter" + icon = 'icons/obj/power.dmi' + icon_state = "crema_switch" + anchored = 1.0 + req_access = list(access_crematorium) + var/on = 0 + var/otherarea = null + var/id = 1 + + ghost_read = 0 // Deactivate ghost touching. ghost_write = 0 \ No newline at end of file diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 084044bc448..235ddd562c7 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -1,470 +1,470 @@ -var/list/camera_names=list() -/obj/machinery/camera - name = "security camera" - desc = "It's used to monitor rooms." - icon = 'icons/obj/monitors.dmi' - icon_state = "camera" - use_power = 2 - idle_power_usage = 5 - active_power_usage = 10 - layer = 5 - - var/datum/wires/camera/wires = null // Wires datum - var/list/network = list("SS13") - var/c_tag = null - var/c_tag_order = 999 - var/status = 1.0 - anchored = 1.0 - var/invuln = null - var/bugged = 0 - var/obj/item/weapon/camera_assembly/assembly = null - var/light_on = 0 - - machine_flags = SCREWTOGGLE //| WIREJACK Needs work - - //OTHER - - var/view_range = 7 - var/short_range = 2 - - var/light_disabled = 0 - var/alarm_on = 0 - var/busy = 0 - - var/hear_voice = 0 - -/obj/machinery/camera/update_icon() - var/EMPd = stat & EMPED - var/deactivated = !status - var/camtype = "camera" - if(assembly) - camtype = isXRay() ? "xraycam" : "camera" // Thanks to Krutchen for the icons. - - if (deactivated) - icon_state = "[camtype]1" - else if (EMPd) - icon_state = "[camtype]emp" - else - icon_state = "[camtype]" - -/obj/machinery/camera/proc/update_hear()//only cameras with voice analyzers can hear, to reduce the number of unecessary /mob/virtualhearer - if(!hear_voice && isHearing()) - hear_voice = 1 - addHear() - if(hear_voice && !isHearing()) - hear_voice = 0 - removeHear() - -/obj/machinery/camera/New() - wires = new(src) - - assembly = new(src) - assembly.state = 4 - - if(!src.network || src.network.len < 1) - if(loc) - error("[src.name] in [get_area(src)] (x:[src.x] y:[src.y] z:[src.z] has errored. [src.network?"Empty network list":"Null network list"]") - else - error("[src.name] in [get_area(src)]has errored. [src.network?"Empty network list":"Null network list"]") - ASSERT(src.network) - ASSERT(src.network.len > 0) - - if(!c_tag) - name_camera() - ..() - if(adv_camera && adv_camera.initialized && !(src in adv_camera.camerasbyzlevel["[z]"])) - adv_camera.update(z, 0, src, adding=1) - - update_hear() - -/obj/machinery/camera/proc/name_camera() - var/area/A=get_area(src) - var/basename=A.name - var/nethash=english_list(network) - var/suffix = 0 - while(!suffix || nethash+c_tag in camera_names) - c_tag = "[basename]" - if(suffix) - c_tag += " [suffix]" - suffix++ - camera_names[nethash+c_tag]=src - -/obj/machinery/camera/change_area(oldarea, newarea) - var/nethash=english_list(network) - camera_names[nethash+c_tag]=null - ..() - if(name != replacetext(name,oldarea,newarea)) - name_camera() - -/obj/machinery/camera/Destroy() - deactivate(null, 0) //kick anyone viewing out - if(assembly) - qdel(assembly) - assembly = null - wires = null - cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that - if(adv_camera) - for(var/key in adv_camera.camerasbyzlevel) - adv_camera.camerasbyzlevel[key] -= src - ..() - -/obj/machinery/camera/emp_act(severity) - if(isEmpProof()) - return - if(prob(100/severity)) - var/list/previous_network = network - network = list() - cameranet.removeCamera(src) - stat |= EMPED - set_light(0) - triggerCameraAlarm() - update_icon() - spawn(900) - network = previous_network - stat &= ~EMPED - cancelCameraAlarm() - update_icon() - if(can_use()) - cameranet.addCamera(src) - adv_camera.update(z, 0, src, adding=1) - for(var/mob/O in mob_list) - if (istype(O.machine, /obj/machinery/computer/security)) - var/obj/machinery/computer/security/S = O.machine - if (S.current == src) - O.unset_machine() - O.reset_view(null) +var/list/camera_names=list() +/obj/machinery/camera + name = "security camera" + desc = "It's used to monitor rooms." + icon = 'icons/obj/monitors.dmi' + icon_state = "camera" + use_power = 2 + idle_power_usage = 5 + active_power_usage = 10 + layer = 5 + + var/datum/wires/camera/wires = null // Wires datum + var/list/network = list("SS13") + var/c_tag = null + var/c_tag_order = 999 + var/status = 1.0 + anchored = 1.0 + var/invuln = null + var/bugged = 0 + var/obj/item/weapon/camera_assembly/assembly = null + var/light_on = 0 + + machine_flags = SCREWTOGGLE //| WIREJACK Needs work + + //OTHER + + var/view_range = 7 + var/short_range = 2 + + var/light_disabled = 0 + var/alarm_on = 0 + var/busy = 0 + + var/hear_voice = 0 + +/obj/machinery/camera/update_icon() + var/EMPd = stat & EMPED + var/deactivated = !status + var/camtype = "camera" + if(assembly) + camtype = isXRay() ? "xraycam" : "camera" // Thanks to Krutchen for the icons. + + if (deactivated) + icon_state = "[camtype]1" + else if (EMPd) + icon_state = "[camtype]emp" + else + icon_state = "[camtype]" + +/obj/machinery/camera/proc/update_hear()//only cameras with voice analyzers can hear, to reduce the number of unecessary /mob/virtualhearer + if(!hear_voice && isHearing()) + hear_voice = 1 + addHear() + if(hear_voice && !isHearing()) + hear_voice = 0 + removeHear() + +/obj/machinery/camera/New() + wires = new(src) + + assembly = new(src) + assembly.state = 4 + + if(!src.network || src.network.len < 1) + if(loc) + error("[src.name] in [get_area(src)] (x:[src.x] y:[src.y] z:[src.z] has errored. [src.network?"Empty network list":"Null network list"]") + else + error("[src.name] in [get_area(src)]has errored. [src.network?"Empty network list":"Null network list"]") + ASSERT(src.network) + ASSERT(src.network.len > 0) + + if(!c_tag) + name_camera() + ..() + if(adv_camera && adv_camera.initialized && !(src in adv_camera.camerasbyzlevel["[z]"])) + adv_camera.update(z, 0, src, adding=1) + + update_hear() + +/obj/machinery/camera/proc/name_camera() + var/area/A=get_area(src) + var/basename=A.name + var/nethash=english_list(network) + var/suffix = 0 + while(!suffix || nethash+c_tag in camera_names) + c_tag = "[basename]" + if(suffix) + c_tag += " [suffix]" + suffix++ + camera_names[nethash+c_tag]=src + +/obj/machinery/camera/change_area(oldarea, newarea) + var/nethash=english_list(network) + camera_names[nethash+c_tag]=null + ..() + if(name != replacetext(name,oldarea,newarea)) + name_camera() + +/obj/machinery/camera/Destroy() + deactivate(null, 0) //kick anyone viewing out + if(assembly) + qdel(assembly) + assembly = null + wires = null + cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that + if(adv_camera) + for(var/key in adv_camera.camerasbyzlevel) + adv_camera.camerasbyzlevel[key] -= src + ..() + +/obj/machinery/camera/emp_act(severity) + if(isEmpProof()) + return + if(prob(100/severity)) + var/list/previous_network = network + network = list() + cameranet.removeCamera(src) + stat |= EMPED + set_light(0) + triggerCameraAlarm() + update_icon() + spawn(900) + network = previous_network + stat &= ~EMPED + cancelCameraAlarm() + update_icon() + if(can_use()) + cameranet.addCamera(src) + adv_camera.update(z, 0, src, adding=1) + for(var/mob/O in mob_list) + if (istype(O.machine, /obj/machinery/computer/security)) + var/obj/machinery/computer/security/S = O.machine + if (S.current == src) + O.unset_machine() + O.reset_view(null) to_chat(O, "The screen bursts into static.") - ..() - -/obj/machinery/camera/ex_act(severity) - if(src.invuln) - return - else - ..(severity) - return - -/obj/machinery/camera/blob_act() - qdel(src) - return - -/obj/machinery/camera/proc/setViewRange(var/num = 7) - src.view_range = num - cameranet.updateVisibility(src, 0) - -/obj/machinery/camera/shock(var/mob/living/user) - if(!istype(user)) - return - user.electrocute_act(10, src) - -/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob) - if(!istype(user)) - return - if(!status) - return - status = 0 - update_icon() - visible_message("\The [user] slashes at [src]!") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 100, 1) - add_hiddenprint(user) - deactivate(user,0) - -/obj/machinery/camera/attackby(W as obj, mob/living/user as mob) - - // DECONSTRUCTION - if(istype(W, /obj/item/weapon/screwdriver)) + ..() + +/obj/machinery/camera/ex_act(severity) + if(src.invuln) + return + else + ..(severity) + return + +/obj/machinery/camera/blob_act() + qdel(src) + return + +/obj/machinery/camera/proc/setViewRange(var/num = 7) + src.view_range = num + cameranet.updateVisibility(src, 0) + +/obj/machinery/camera/shock(var/mob/living/user) + if(!istype(user)) + return + user.electrocute_act(10, src) + +/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob) + if(!istype(user)) + return + if(!status) + return + status = 0 + update_icon() + visible_message("\The [user] slashes at [src]!") + playsound(get_turf(src), 'sound/weapons/slash.ogg', 100, 1) + add_hiddenprint(user) + deactivate(user,0) + +/obj/machinery/camera/attackby(W as obj, mob/living/user as mob) + + // DECONSTRUCTION + if(istype(W, /obj/item/weapon/screwdriver)) // to_chat(user, "You start to [panel_open ? "close" : "open"] the camera's panel.") - //if(toggle_panel(user)) // No delay because no one likes screwdrivers trying to be hip and have a duration cooldown - togglePanelOpen(W, user, icon_state, icon_state) - - else if((istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) && panel_open) - wires.Interact(user) - - else if(istype(W, /obj/item/weapon/weldingtool) && wires.CanDeconstruct()) - if(weld(W, user)) - if(assembly) - assembly.state = 1 - assembly.loc = src.loc - assembly = null - - qdel(src) - - // Upgrades! - else if(is_type_in_list(W, assembly.possible_upgrades)) // Is a possible upgrade - if (is_type_in_list(W, assembly.upgrades)) + //if(toggle_panel(user)) // No delay because no one likes screwdrivers trying to be hip and have a duration cooldown + togglePanelOpen(W, user, icon_state, icon_state) + + else if((istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) && panel_open) + wires.Interact(user) + + else if(istype(W, /obj/item/weapon/weldingtool) && wires.CanDeconstruct()) + if(weld(W, user)) + if(assembly) + assembly.state = 1 + assembly.loc = src.loc + assembly = null + + qdel(src) + + // Upgrades! + else if(is_type_in_list(W, assembly.possible_upgrades)) // Is a possible upgrade + if (is_type_in_list(W, assembly.upgrades)) to_chat(user, "The camera already has \a [W] inside!") - return - if (!panel_open) + return + if (!panel_open) to_chat(user, "You can't reach into the camera's circuitry while the maintenance panel is closed.") - return - /*if (!wires.CanDeconstruct()) + return + /*if (!wires.CanDeconstruct()) to_chat(user, "You can't reach into the camera's circuitry with the wires on the way.") - return*/ - if (istype(W, /obj/item/stack)) - var/obj/item/stack/sheet/mineral/plasma/s = W - s.use(1) - assembly.upgrades += new /obj/item/stack/sheet/mineral/plasma - else - if(!user.drop_item(W, src)) return - assembly.upgrades += W + return*/ + if (istype(W, /obj/item/stack)) + var/obj/item/stack/sheet/mineral/plasma/s = W + s.use(1) + assembly.upgrades += new /obj/item/stack/sheet/mineral/plasma + else + if(!user.drop_item(W, src)) return + assembly.upgrades += W to_chat(user, "You attach the [W] into the camera's inner circuits.") - update_icon() - update_hear() - cameranet.updateVisibility(src, 0) - return - - // Taking out upgrades - else if(iscrowbar(W)) - if (!panel_open) + update_icon() + update_hear() + cameranet.updateVisibility(src, 0) + return + + // Taking out upgrades + else if(iscrowbar(W)) + if (!panel_open) to_chat(user, "You can't reach into the camera's circuitry while the maintenance panel is closed.") - return - /*if (!wires.CanDeconstruct()) + return + /*if (!wires.CanDeconstruct()) to_chat(user, "You can't reach into the camera's circuitry with the wires on the way.") - return*/ - if (assembly.upgrades.len) - var/obj/U = locate(/obj) in assembly.upgrades - if(U) + return*/ + if (assembly.upgrades.len) + var/obj/U = locate(/obj) in assembly.upgrades + if(U) to_chat(user, "You unattach \the [U] from the camera.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - U.loc = get_turf(src) - assembly.upgrades -= U - update_icon() - update_hear() - cameranet.updateVisibility(src, 0) - return - else //Camera deconned, no upgrades - to_chat(user, "The camera is firmly welded to the wall.")//User might be trying to deconstruct the camera with a crowbar, let them know what's wrong + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + U.loc = get_turf(src) + assembly.upgrades -= U + update_icon() + update_hear() + cameranet.updateVisibility(src, 0) + return + else //Camera deconned, no upgrades + to_chat(user, "The camera is firmly welded to the wall.")//User might be trying to deconstruct the camera with a crowbar, let them know what's wrong - return - - // OTHER - else if ((istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/device/pda)) && isliving(user)) - user.delayNextAttack(5) - var/mob/living/U = user - var/obj/item/weapon/paper/X = null - var/obj/item/device/pda/P = null - - var/itemname = "" - var/info = "" - if(istype(W, /obj/item/weapon/paper)) - X = W - itemname = X.name - info = X.info - else - P = W - itemname = P.name - info = P.notehtml + return + + // OTHER + else if ((istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/device/pda)) && isliving(user)) + user.delayNextAttack(5) + var/mob/living/U = user + var/obj/item/weapon/paper/X = null + var/obj/item/device/pda/P = null + + var/itemname = "" + var/info = "" + if(istype(W, /obj/item/weapon/paper)) + X = W + itemname = X.name + info = X.info + else + P = W + itemname = P.name + info = P.notehtml to_chat(U, "You hold \a [itemname] up to the camera ...") - for(var/mob/living/silicon/ai/O in living_mob_list) - if(!O.client) continue + for(var/mob/living/silicon/ai/O in living_mob_list) + if(!O.client) continue if(U.name == "Unknown") to_chat( O, "[U] holds \a [itemname] up to one of your cameras ...") - else to_chat(O, "[U] holds \a [itemname] up to one of your cameras ...") + else to_chat(O, "[U] holds \a [itemname] up to one of your cameras ...") - O << browse(text("[][]", itemname, info), text("window=[]", itemname)) - for(var/mob/O in player_list) - if (istype(O.machine, /obj/machinery/computer/security)) - var/obj/machinery/computer/security/S = O.machine - if (S.current == src) + O << browse(text("[][]", itemname, info), text("window=[]", itemname)) + for(var/mob/O in player_list) + if (istype(O.machine, /obj/machinery/computer/security)) + var/obj/machinery/computer/security/S = O.machine + if (S.current == src) to_chat(O, "[U] holds \a [itemname] up to one of the cameras ...") - O << browse(text("[][]", itemname, info), text("window=[]", itemname)) - else - ..() - return - -/obj/machinery/camera/attack_pai(mob/user as mob) - wirejack(user) - -/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1) - if(choice==1) - status = !( src.status ) - update_icon() - if (!(src.status)) - if(user) - visible_message("[user] has deactivated [src]!") - add_hiddenprint(user) - else - visible_message(" \The [src] deactivates!") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - add_hiddenprint(user) - else - if(user) - visible_message(" [user] has reactivated [src]!") - add_hiddenprint(user) - else - visible_message(" \The [src] reactivates!") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - add_hiddenprint(user) - cameranet.updateVisibility(src, 0) - // now disconnect anyone using the camera - //Apparently, this will disconnect anyone even if the camera was re-activated. - //I guess that doesn't matter since they can't use it anyway? - for(var/mob/O in player_list) - if (istype(O.machine, /obj/machinery/computer/security)) - var/obj/machinery/computer/security/S = O.machine - if (S.current == src) - O.unset_machine() - O.reset_view(null) + O << browse(text("[][]", itemname, info), text("window=[]", itemname)) + else + ..() + return + +/obj/machinery/camera/attack_pai(mob/user as mob) + wirejack(user) + +/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1) + if(choice==1) + status = !( src.status ) + update_icon() + if (!(src.status)) + if(user) + visible_message("[user] has deactivated [src]!") + add_hiddenprint(user) + else + visible_message(" \The [src] deactivates!") + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + add_hiddenprint(user) + else + if(user) + visible_message(" [user] has reactivated [src]!") + add_hiddenprint(user) + else + visible_message(" \The [src] reactivates!") + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + add_hiddenprint(user) + cameranet.updateVisibility(src, 0) + // now disconnect anyone using the camera + //Apparently, this will disconnect anyone even if the camera was re-activated. + //I guess that doesn't matter since they can't use it anyway? + for(var/mob/O in player_list) + if (istype(O.machine, /obj/machinery/computer/security)) + var/obj/machinery/computer/security/S = O.machine + if (S.current == src) + O.unset_machine() + O.reset_view(null) to_chat(O, "The screen bursts into static.") - if(choice && can_use()) //camera reactivated - adv_camera.update(z, 0, src, adding=1) - else //either deactivated OR being destroyed - adv_camera.update(z, 0, src, adding=2) - -/obj/machinery/camera/proc/triggerCameraAlarm() - if(!alarm_on) - adv_camera.update(z, 0, src, adding=4) //1 is alarming, 0 is nothing wrong - alarm_on = 1 - for(var/mob/living/silicon/S in mob_list) - S.triggerAlarm("Camera", areaMaster, list(src), src) - - -/obj/machinery/camera/proc/cancelCameraAlarm() - if(alarm_on) - adv_camera.update(z, 0, src, adding=4) //1 is alarming, 0 is nothing wrong - alarm_on = 0 - for(var/mob/living/silicon/S in mob_list) - S.cancelAlarm("Camera", areaMaster, src) - -/obj/machinery/camera/proc/can_use() - if(!status) - return 0 - if(stat & EMPED) - return 0 - return 1 - -/obj/machinery/camera/proc/can_see() - var/list/see = null - var/turf/pos = get_turf(src) - if(isXRay()) - see = range(view_range, pos) - else - see = get_hear(view_range, pos) - return see - -/atom/proc/auto_turn() - //Automatically turns based on nearby walls. - var/turf/simulated/wall/T = null - - for (var/direction in cardinal) - T = get_ranged_target_turf(src, direction, 1) - - if (istype(T)) - dir = reverse_direction(direction) - break - -//Return a working camera that can see a given mob -//or null if none -/proc/seen_by_camera(var/mob/M) - for(var/obj/machinery/camera/C in oview(4, M)) - if(C.can_use()) // check if camera disabled - return C - break - return null - -/proc/near_range_camera(var/mob/M) - - - for(var/obj/machinery/camera/C in range(4, M)) - if(C.can_use()) // check if camera disabled - return C - break - - return null - -/obj/machinery/camera/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/user) - - - if(busy) - return 0 - if(!WT.isOn()) - return 0 - - // Do after stuff here + if(choice && can_use()) //camera reactivated + adv_camera.update(z, 0, src, adding=1) + else //either deactivated OR being destroyed + adv_camera.update(z, 0, src, adding=2) + +/obj/machinery/camera/proc/triggerCameraAlarm() + if(!alarm_on) + adv_camera.update(z, 0, src, adding=4) //1 is alarming, 0 is nothing wrong + alarm_on = 1 + for(var/mob/living/silicon/S in mob_list) + S.triggerAlarm("Camera", areaMaster, list(src), src) + + +/obj/machinery/camera/proc/cancelCameraAlarm() + if(alarm_on) + adv_camera.update(z, 0, src, adding=4) //1 is alarming, 0 is nothing wrong + alarm_on = 0 + for(var/mob/living/silicon/S in mob_list) + S.cancelAlarm("Camera", areaMaster, src) + +/obj/machinery/camera/proc/can_use() + if(!status) + return 0 + if(stat & EMPED) + return 0 + return 1 + +/obj/machinery/camera/proc/can_see() + var/list/see = null + var/turf/pos = get_turf(src) + if(isXRay()) + see = range(view_range, pos) + else + see = get_hear(view_range, pos) + return see + +/atom/proc/auto_turn() + //Automatically turns based on nearby walls. + var/turf/simulated/wall/T = null + + for (var/direction in cardinal) + T = get_ranged_target_turf(src, direction, 1) + + if (istype(T)) + dir = reverse_direction(direction) + break + +//Return a working camera that can see a given mob +//or null if none +/proc/seen_by_camera(var/mob/M) + for(var/obj/machinery/camera/C in oview(4, M)) + if(C.can_use()) // check if camera disabled + return C + break + return null + +/proc/near_range_camera(var/mob/M) + + + for(var/obj/machinery/camera/C in range(4, M)) + if(C.can_use()) // check if camera disabled + return C + break + + return null + +/obj/machinery/camera/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/user) + + + if(busy) + return 0 + if(!WT.isOn()) + return 0 + + // Do after stuff here to_chat(user, "You start to weld the [src].") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - WT.eyecheck(user) - busy = 1 - if(do_after(user, src, 100)) - busy = 0 - if(!WT.isOn()) - return 0 - return 1 - busy = 0 - return 0 - -/obj/machinery/camera/wirejack(var/mob/living/silicon/pai/P) - if(..()) - P.set_machine(P) - P.current = src - P.reset_view(src) - return 1 - return 0 - -/obj/machinery/camera/proc/tv_message(var/atom/movable/hearer, var/datum/speech/speech) - speech.wrapper_classes.Add("tv") - hearer.Hear(speech) - - /* - var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()] " - var/messagepart = "[hearer.lang_treat(speaker, speaking, raw_message)]" - - return "[namepart][messagepart]" - */ - -/obj/machinery/camera/Hear(var/datum/speech/speech, var/rendered_speech="") - if(isHearing()) - for(var/obj/machinery/computer/security/S in tv_monitors) - if(S.current == src) - if(istype(S, /obj/machinery/computer/security/telescreen)) - for(var/mob/M in viewers(world.view,S)) + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + WT.eyecheck(user) + busy = 1 + if(do_after(user, src, 100)) + busy = 0 + if(!WT.isOn()) + return 0 + return 1 + busy = 0 + return 0 + +/obj/machinery/camera/wirejack(var/mob/living/silicon/pai/P) + if(..()) + P.set_machine(P) + P.current = src + P.reset_view(src) + return 1 + return 0 + +/obj/machinery/camera/proc/tv_message(var/atom/movable/hearer, var/datum/speech/speech) + speech.wrapper_classes.Add("tv") + hearer.Hear(speech) + + /* + var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()] " + var/messagepart = "[hearer.lang_treat(speaker, speaking, raw_message)]" + + return "[namepart][messagepart]" + */ + +/obj/machinery/camera/Hear(var/datum/speech/speech, var/rendered_speech="") + if(isHearing()) + for(var/obj/machinery/computer/security/S in tv_monitors) + if(S.current == src) + if(istype(S, /obj/machinery/computer/security/telescreen)) + for(var/mob/M in viewers(world.view,S)) to_chat(M, "\icon[S][tv_message(M, speech, rendered_speech)]") - else - for(var/mob/M in viewers(1,S)) + else + for(var/mob/M in viewers(1,S)) to_chat(M, "\icon[S][tv_message(M, speech, rendered_speech)]") - -/obj/machinery/camera/arena - name = "arena camera" - desc = "A camera anchored to the floor, designed to survive hits and explosions of any size. What's it made of anyway?" - icon_state = "camerarena" - use_power = 0 - idle_power_usage = 0 - active_power_usage = 0 - layer = 2.1 - -/obj/machinery/camera/arena/New() - ..() - pixel_x = 0 - pixel_y = 0 - upgradeXRay() - upgradeHearing() - -/obj/machinery/camera/arena/attackby(W as obj, mob/living/user as mob) - if(istype(W, /obj/item/weapon/screwdriver)) + +/obj/machinery/camera/arena + name = "arena camera" + desc = "A camera anchored to the floor, designed to survive hits and explosions of any size. What's it made of anyway?" + icon_state = "camerarena" + use_power = 0 + idle_power_usage = 0 + active_power_usage = 0 + layer = 2.1 + +/obj/machinery/camera/arena/New() + ..() + pixel_x = 0 + pixel_y = 0 + upgradeXRay() + upgradeHearing() + +/obj/machinery/camera/arena/attackby(W as obj, mob/living/user as mob) + if(istype(W, /obj/item/weapon/screwdriver)) to_chat(user, "There aren't any visible screws to unscrew.") - else - user.visible_message("\The [user] hits \the [src] with \the [W] but it doesn't seem to affect it in the least.","You hit \the [src] with \the [W] but it doesn't seem to affect it in the least") - return - -/obj/machinery/camera/arena/attack_paw(mob/living/carbon/alien/humanoid/user as mob) - user.visible_message("\The [user] slashes at \the [src], but that didn't affect it at all.","You slash at \the [src], but that didn't affect it at all.") - return - -/obj/machinery/camera/arena/update_icon() - return - -/obj/machinery/camera/arena/emp_act(severity) - return - -/obj/machinery/camera/arena/ex_act(severity) - return - -/obj/machinery/camera/arena/blob_act(severity) - return - -/obj/machinery/camera/arena/singularity_act(severity)//those are really good cameras - return - -/obj/structure/planner/arena/cultify() - return - -/obj/machinery/camera/arena/attack_pai(mob/user as mob) - return + else + user.visible_message("\The [user] hits \the [src] with \the [W] but it doesn't seem to affect it in the least.","You hit \the [src] with \the [W] but it doesn't seem to affect it in the least") + return + +/obj/machinery/camera/arena/attack_paw(mob/living/carbon/alien/humanoid/user as mob) + user.visible_message("\The [user] slashes at \the [src], but that didn't affect it at all.","You slash at \the [src], but that didn't affect it at all.") + return + +/obj/machinery/camera/arena/update_icon() + return + +/obj/machinery/camera/arena/emp_act(severity) + return + +/obj/machinery/camera/arena/ex_act(severity) + return + +/obj/machinery/camera/arena/blob_act(severity) + return + +/obj/machinery/camera/arena/singularity_act(severity)//those are really good cameras + return + +/obj/structure/planner/arena/cultify() + return + +/obj/machinery/camera/arena/attack_pai(mob/user as mob) + return diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 0d118758e51..49134e2a627 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -1,181 +1,181 @@ -/obj/item/weapon/camera_assembly - name = "camera assembly" - desc = "The basic construction for Nanotrasen-Always-Watching-You cameras." - icon = 'icons/obj/monitors.dmi' - icon_state = "cameracase" - w_class = 2 - anchored = 0 - - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 300) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_STEEL - - // Motion, EMP-Proof, X-Ray, Microphone - var/list/obj/item/possible_upgrades = list( - /obj/item/device/assembly/prox_sensor, - /obj/item/stack/sheet/mineral/plasma, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/device/assembly/voice, - ) - - var/list/upgrades = list() - var/state = 0 - var/busy = 0 - /* - 0 = Nothing done to it - 1 = Wrenched in place - 2 = Welded in place - 3 = Wires attached to it (you can now attach/dettach upgrades) - 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades) - */ - -/obj/item/weapon/camera_assembly/attackby(obj/item/W as obj, mob/living/user as mob) - - switch(state) - - if(0) - // State 0 - if(iswrench(W) && isturf(src.loc)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) +/obj/item/weapon/camera_assembly + name = "camera assembly" + desc = "The basic construction for Nanotrasen-Always-Watching-You cameras." + icon = 'icons/obj/monitors.dmi' + icon_state = "cameracase" + w_class = 2 + anchored = 0 + + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 300) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_STEEL + + // Motion, EMP-Proof, X-Ray, Microphone + var/list/obj/item/possible_upgrades = list( + /obj/item/device/assembly/prox_sensor, + /obj/item/stack/sheet/mineral/plasma, + /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, + /obj/item/device/assembly/voice, + ) + + var/list/upgrades = list() + var/state = 0 + var/busy = 0 + /* + 0 = Nothing done to it + 1 = Wrenched in place + 2 = Welded in place + 3 = Wires attached to it (you can now attach/dettach upgrades) + 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades) + */ + +/obj/item/weapon/camera_assembly/attackby(obj/item/W as obj, mob/living/user as mob) + + switch(state) + + if(0) + // State 0 + if(iswrench(W) && isturf(src.loc)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You wrench the assembly into place.") - anchored = 1 - state = 1 - update_icon() - auto_turn() - return - - if(1) - // State 1 - if(iswelder(W)) - if(weld(W, user)) + anchored = 1 + state = 1 + update_icon() + auto_turn() + return + + if(1) + // State 1 + if(iswelder(W)) + if(weld(W, user)) to_chat(user, "You weld the assembly securely into place.") - anchored = 1 - state = 2 - return - - else if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + anchored = 1 + state = 2 + return + + else if(iswrench(W)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You unattach the assembly from it's place.") - anchored = 0 - update_icon() - state = 0 - return - - if(2) - // State 2 - if(iscoil(W)) - var/obj/item/stack/cable_coil/C = W - if(C.use(2)) + anchored = 0 + update_icon() + state = 0 + return + + if(2) + // State 2 + if(iscoil(W)) + var/obj/item/stack/cable_coil/C = W + if(C.use(2)) to_chat(user, "You add wires to the assembly.") - state = 3 - return - - else if(iswelder(W)) - - if(weld(W, user)) + state = 3 + return + + else if(iswelder(W)) + + if(weld(W, user)) to_chat(user, "You unweld the assembly from it's place.") - state = 1 - anchored = 1 - return - - - if(3) - // State 3 - if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - - var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")) - if(!input) + state = 1 + anchored = 1 + return + + + if(3) + // State 3 + if(isscrewdriver(W)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + + var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13")) + if(!input) to_chat(usr, "No input found, please hang up and try your call again.") - return - - var/list/tempnetwork = text2list(input, ",") - if(tempnetwork.len < 1) + return + + var/list/tempnetwork = text2list(input, ",") + if(tempnetwork.len < 1) to_chat(usr, "No network found, please hang up and try your call again.") - return - - state = 4 - var/obj/machinery/camera/C = new(src.loc) - src.loc = C - C.assembly = src - - C.auto_turn() - - C.network = tempnetwork - - C.c_tag = "[get_area_name(src)] ([rand(1, 999)]" - - for(var/i = 5; i >= 0; i -= 1) - var/direct = input(user, "Direction?", "Assembling Camera", null) in list("LEAVE IT", "NORTH", "EAST", "SOUTH", "WEST" ) - if(direct != "LEAVE IT") - C.dir = text2dir(direct) - if(i != 0) - var/confirm = alert(user, "Is this what you want? Chances Remaining: [i]", "Confirmation", "Yes", "No") - if(confirm == "Yes") - break - return - - else if(iswirecutter(W)) - - new/obj/item/stack/cable_coil(get_turf(src), 2) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + return + + state = 4 + var/obj/machinery/camera/C = new(src.loc) + src.loc = C + C.assembly = src + + C.auto_turn() + + C.network = tempnetwork + + C.c_tag = "[get_area_name(src)] ([rand(1, 999)]" + + for(var/i = 5; i >= 0; i -= 1) + var/direct = input(user, "Direction?", "Assembling Camera", null) in list("LEAVE IT", "NORTH", "EAST", "SOUTH", "WEST" ) + if(direct != "LEAVE IT") + C.dir = text2dir(direct) + if(i != 0) + var/confirm = alert(user, "Is this what you want? Chances Remaining: [i]", "Confirmation", "Yes", "No") + if(confirm == "Yes") + break + return + + else if(iswirecutter(W)) + + new/obj/item/stack/cable_coil(get_turf(src), 2) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) to_chat(user, "You cut the wires from the circuits.") - state = 2 - return - - // Upgrades! - if(is_type_in_list(W, possible_upgrades)) // Is a possible upgrade - if(is_type_in_list(W, upgrades)) + state = 2 + return + + // Upgrades! + if(is_type_in_list(W, possible_upgrades)) // Is a possible upgrade + if(is_type_in_list(W, upgrades)) to_chat(user, "The assembly already has \a [W] inside!") - return - if (istype(W, /obj/item/stack)) - var/obj/item/stack/sheet/mineral/plasma/s = W - s.use(1) - upgrades += new /obj/item/stack/sheet/mineral/plasma - else - if(!user.drop_item(W, src)) return - upgrades += W + return + if (istype(W, /obj/item/stack)) + var/obj/item/stack/sheet/mineral/plasma/s = W + s.use(1) + upgrades += new /obj/item/stack/sheet/mineral/plasma + else + if(!user.drop_item(W, src)) return + upgrades += W to_chat(user, "You attach the [W] into the assembly inner circuits.") - return - - // Taking out upgrades - else if(iscrowbar(W) && upgrades.len) - var/obj/U = locate(/obj) in upgrades - if(U) + return + + // Taking out upgrades + else if(iscrowbar(W) && upgrades.len) + var/obj/U = locate(/obj) in upgrades + if(U) to_chat(user, "You unattach \the [U] from the assembly.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - U.loc = get_turf(src) - upgrades -= U - return - - ..() - -/obj/item/weapon/camera_assembly/update_icon() - if(anchored) - icon_state = "camera1" - else - icon_state = "cameracase" - -/obj/item/weapon/camera_assembly/attack_hand(mob/user as mob) - if(!anchored) - ..() - -/obj/item/weapon/camera_assembly/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/user) - - - if(busy) - return 0 - if(!WT.isOn()) - return 0 - + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + U.loc = get_turf(src) + upgrades -= U + return + + ..() + +/obj/item/weapon/camera_assembly/update_icon() + if(anchored) + icon_state = "camera1" + else + icon_state = "cameracase" + +/obj/item/weapon/camera_assembly/attack_hand(mob/user as mob) + if(!anchored) + ..() + +/obj/item/weapon/camera_assembly/proc/weld(var/obj/item/weapon/weldingtool/WT, var/mob/user) + + + if(busy) + return 0 + if(!WT.isOn()) + return 0 + to_chat(user, "You start to weld the [src]...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - WT.eyecheck(user) - busy = 1 - if(do_after(user, src, 20)) - busy = 0 - if(!WT.isOn()) - return 0 - return 1 - busy = 0 + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + WT.eyecheck(user) + busy = 1 + if(do_after(user, src, 20)) + busy = 0 + if(!WT.isOn()) + return 0 + return 1 + busy = 0 return 0 \ No newline at end of file diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 5a9ee0cf31d..ec5b325099d 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -1,62 +1,62 @@ -/obj/machinery/camera - - var/list/motionTargets = list() - var/detectTime = 0 - var/area/ai_monitored/area_motion = null - var/alarm_delay = 100 // Don't forget, there's another 10 seconds in queueAlarm() - - flags = FPRINT | PROXMOVE - -/obj/machinery/camera/process() - // motion camera event loop - if(!isMotion()) - . = PROCESS_KILL - return - if (detectTime > 0) - var/elapsed = world.time - detectTime - if (elapsed > alarm_delay) - triggerAlarm() - else if (detectTime == -1) - for (var/mob/target in motionTargets) - if (target.stat == 2) lostTarget(target) - // If not detecting with motion camera... - if (!area_motion) - // See if the camera is still in range - if(!Adjacent(target)) - // If they aren't in range, lose the target. - lostTarget(target) - -/obj/machinery/camera/proc/newTarget(var/mob/target) - if (istype(target, /mob/living/silicon/ai)) return 0 - if (detectTime == 0) - detectTime = world.time // start the clock - if (!(target in motionTargets)) - motionTargets += target - return 1 - -/obj/machinery/camera/proc/lostTarget(var/mob/target) - if (target in motionTargets) - motionTargets -= target - if (motionTargets.len == 0) - cancelAlarm() - -/obj/machinery/camera/proc/cancelAlarm() - if (detectTime == -1) - for (var/mob/living/silicon/aiPlayer in player_list) - if (status) aiPlayer.cancelAlarm("Motion", areaMaster) - 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", areaMaster, src) - detectTime = -1 - return 1 - -/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj) - // Motion cameras outside of an "ai monitored" area will use this to detect stuff. - if (!area_motion) - if(isliving(AM)) - newTarget(AM) - +/obj/machinery/camera + + var/list/motionTargets = list() + var/detectTime = 0 + var/area/ai_monitored/area_motion = null + var/alarm_delay = 100 // Don't forget, there's another 10 seconds in queueAlarm() + + flags = FPRINT | PROXMOVE + +/obj/machinery/camera/process() + // motion camera event loop + if(!isMotion()) + . = PROCESS_KILL + return + if (detectTime > 0) + var/elapsed = world.time - detectTime + if (elapsed > alarm_delay) + triggerAlarm() + else if (detectTime == -1) + for (var/mob/target in motionTargets) + if (target.stat == 2) lostTarget(target) + // If not detecting with motion camera... + if (!area_motion) + // See if the camera is still in range + if(!Adjacent(target)) + // If they aren't in range, lose the target. + lostTarget(target) + +/obj/machinery/camera/proc/newTarget(var/mob/target) + if (istype(target, /mob/living/silicon/ai)) return 0 + if (detectTime == 0) + detectTime = world.time // start the clock + if (!(target in motionTargets)) + motionTargets += target + return 1 + +/obj/machinery/camera/proc/lostTarget(var/mob/target) + if (target in motionTargets) + motionTargets -= target + if (motionTargets.len == 0) + cancelAlarm() + +/obj/machinery/camera/proc/cancelAlarm() + if (detectTime == -1) + for (var/mob/living/silicon/aiPlayer in player_list) + if (status) aiPlayer.cancelAlarm("Motion", areaMaster) + 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", areaMaster, src) + detectTime = -1 + return 1 + +/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj) + // Motion cameras outside of an "ai monitored" area will use this to detect stuff. + if (!area_motion) + if(isliving(AM)) + newTarget(AM) + diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 99eaf09d415..dcaecbc58ba 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -1,91 +1,91 @@ -// PRESETS - -// EMP - -/obj/machinery/camera/emp_proof/New() - ..() - upgradeEmpProof() - -// X-RAY - -/obj/machinery/camera/xray/New() - ..() - upgradeXRay() - update_icon() - -// MOTION - -/obj/machinery/camera/motion/New() - ..() - upgradeMotion() - -// HEARING - -/obj/machinery/camera/hearing/New() - ..() - upgradeHearing() - -// ALL UPGRADES - -/obj/machinery/camera/all/New() - ..() - upgradeEmpProof() - upgradeXRay() - upgradeMotion() - upgradeHearing() - update_icon() - -// AUTONAME - -/obj/machinery/camera/autoname - var/number = 0 //camera number in area - -//This camera type automatically sets it's name to whatever the area that it's in is called. -/obj/machinery/camera/autoname/New() - ..() - spawn(10) - number = 1 - var/area/A = get_area(src) - if(A) - for(var/obj/machinery/camera/autoname/C in cameranet.cameras) - if(C == src) continue - var/area/CA = get_area(C) - if(CA.type == A.type) - if(C.number) - number = max(number, C.number+1) - c_tag = "[A.name] #[number]" - - -// CHECKS - -/obj/machinery/camera/proc/isEmpProof() - var/O = locate(/obj/item/stack/sheet/mineral/plasma) in assembly.upgrades - return O - -/obj/machinery/camera/proc/isXRay() - var/O = locate(/obj/item/weapon/reagent_containers/food/snacks/grown/carrot) in assembly.upgrades - return O - -/obj/machinery/camera/proc/isMotion() - var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades - return O - -/obj/machinery/camera/proc/isHearing() - var/O = locate(/obj/item/device/assembly/voice) in assembly.upgrades - return O - -// UPGRADE PROCS - -/obj/machinery/camera/proc/upgradeEmpProof() - assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) - -/obj/machinery/camera/proc/upgradeXRay() - assembly.upgrades.Add(new /obj/item/weapon/reagent_containers/food/snacks/grown/carrot(assembly)) - -// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list. -/obj/machinery/camera/proc/upgradeMotion() - assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly)) - -/obj/machinery/camera/proc/upgradeHearing() - assembly.upgrades.Add(new /obj/item/device/assembly/voice(assembly)) - update_hear() +// PRESETS + +// EMP + +/obj/machinery/camera/emp_proof/New() + ..() + upgradeEmpProof() + +// X-RAY + +/obj/machinery/camera/xray/New() + ..() + upgradeXRay() + update_icon() + +// MOTION + +/obj/machinery/camera/motion/New() + ..() + upgradeMotion() + +// HEARING + +/obj/machinery/camera/hearing/New() + ..() + upgradeHearing() + +// ALL UPGRADES + +/obj/machinery/camera/all/New() + ..() + upgradeEmpProof() + upgradeXRay() + upgradeMotion() + upgradeHearing() + update_icon() + +// AUTONAME + +/obj/machinery/camera/autoname + var/number = 0 //camera number in area + +//This camera type automatically sets it's name to whatever the area that it's in is called. +/obj/machinery/camera/autoname/New() + ..() + spawn(10) + number = 1 + var/area/A = get_area(src) + if(A) + for(var/obj/machinery/camera/autoname/C in cameranet.cameras) + if(C == src) continue + var/area/CA = get_area(C) + if(CA.type == A.type) + if(C.number) + number = max(number, C.number+1) + c_tag = "[A.name] #[number]" + + +// CHECKS + +/obj/machinery/camera/proc/isEmpProof() + var/O = locate(/obj/item/stack/sheet/mineral/plasma) in assembly.upgrades + return O + +/obj/machinery/camera/proc/isXRay() + var/O = locate(/obj/item/weapon/reagent_containers/food/snacks/grown/carrot) in assembly.upgrades + return O + +/obj/machinery/camera/proc/isMotion() + var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades + return O + +/obj/machinery/camera/proc/isHearing() + var/O = locate(/obj/item/device/assembly/voice) in assembly.upgrades + return O + +// UPGRADE PROCS + +/obj/machinery/camera/proc/upgradeEmpProof() + assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) + +/obj/machinery/camera/proc/upgradeXRay() + assembly.upgrades.Add(new /obj/item/weapon/reagent_containers/food/snacks/grown/carrot(assembly)) + +// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list. +/obj/machinery/camera/proc/upgradeMotion() + assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly)) + +/obj/machinery/camera/proc/upgradeHearing() + assembly.upgrades.Add(new /obj/item/device/assembly/voice(assembly)) + update_hear() diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index efea6e66cd8..4f0348bdc00 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -1,231 +1,231 @@ -/mob/living/silicon/ai/proc/get_camera_list() - - - track.cameras.len = 0 - - if(src.stat == 2) - return - - var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.cameras) - L.Add(C) - - camera_sort(L) - - var/list/T = list() - - for (var/obj/machinery/camera/C in L) - var/list/tempnetwork = C.network&src.network - if (tempnetwork.len) - T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C - - track.cameras = T - return T - - -/mob/living/silicon/ai/proc/ai_camera_list(var/camera) - if (!camera) - return 0 - - var/obj/machinery/camera/C = track.cameras[camera] - src.eyeobj.forceMove(C) - - return - -// Used to allow the AI is write in mob names/camera name from the CMD line. -/datum/trackable - var/list/names = list() - var/list/namecounts = list() - var/list/humans = list() - var/list/others = list() - var/list/cameras = list() - -/mob/living/silicon/ai/proc/trackable_mobs() - - - track.names.len = 0 - track.namecounts.len = 0 - track.humans.len = 0 - track.others.len = 0 - - if(usr.stat == 2) - return list() - - for(var/mob/living/M in mob_list) - // Easy checks first. - // Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this. - var/turf/T = get_turf(M) - if(!T) - continue - if(T.z == 2) - continue - if(T.z > 6) - continue - if(M == usr) - continue - if(M.invisibility)//cloaked - continue - if(M.digitalcamo) - continue - - // Human check - var/human = 0 - if(istype(M, /mob/living/carbon/human)) - human = 1 - var/mob/living/carbon/human/H = M - //Cameras can't track people wearing an agent card or a ninja hood. - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - continue - //Skipping aliens because shit, that's OP - if(isalien(M)) - continue - // Now, are they viewable by a camera? (This is last because it's the most intensive check) - if(!near_camera(M)) - continue - - var/name = M.name - if (name in track.names) - track.namecounts[name]++ - name = text("[] ([])", name, track.namecounts[name]) - else - track.names.Add(name) - track.namecounts[name] = 1 - if(human) - track.humans[name] = M - else - track.others[name] = M - - var/list/targets = sortList(track.humans) + sortList(track.others) - return targets - -/mob/living/silicon/ai/verb/ai_camera_track(var/target_name as null|anything in trackable_mobs()) - set name = "track" - set hidden = 1 //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass - - if(!target_name) - return - - var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) - - ai_actual_track(target) - -/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target as mob) - if(!istype(target)) return - spawn(0) - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) +/mob/living/silicon/ai/proc/get_camera_list() + + + track.cameras.len = 0 + + if(src.stat == 2) + return + + var/list/L = list() + for (var/obj/machinery/camera/C in cameranet.cameras) + L.Add(C) + + camera_sort(L) + + var/list/T = list() + + for (var/obj/machinery/camera/C in L) + var/list/tempnetwork = C.network&src.network + if (tempnetwork.len) + T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C + + track.cameras = T + return T + + +/mob/living/silicon/ai/proc/ai_camera_list(var/camera) + if (!camera) + return 0 + + var/obj/machinery/camera/C = track.cameras[camera] + src.eyeobj.forceMove(C) + + return + +// Used to allow the AI is write in mob names/camera name from the CMD line. +/datum/trackable + var/list/names = list() + var/list/namecounts = list() + var/list/humans = list() + var/list/others = list() + var/list/cameras = list() + +/mob/living/silicon/ai/proc/trackable_mobs() + + + track.names.len = 0 + track.namecounts.len = 0 + track.humans.len = 0 + track.others.len = 0 + + if(usr.stat == 2) + return list() + + for(var/mob/living/M in mob_list) + // Easy checks first. + // Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this. + var/turf/T = get_turf(M) + if(!T) + continue + if(T.z == 2) + continue + if(T.z > 6) + continue + if(M == usr) + continue + if(M.invisibility)//cloaked + continue + if(M.digitalcamo) + continue + + // Human check + var/human = 0 + if(istype(M, /mob/living/carbon/human)) + human = 1 + var/mob/living/carbon/human/H = M + //Cameras can't track people wearing an agent card or a ninja hood. + if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + continue + //Skipping aliens because shit, that's OP + if(isalien(M)) + continue + // Now, are they viewable by a camera? (This is last because it's the most intensive check) + if(!near_camera(M)) + continue + + var/name = M.name + if (name in track.names) + track.namecounts[name]++ + name = text("[] ([])", name, track.namecounts[name]) + else + track.names.Add(name) + track.namecounts[name] = 1 + if(human) + track.humans[name] = M + else + track.others[name] = M + + var/list/targets = sortList(track.humans) + sortList(track.others) + return targets + +/mob/living/silicon/ai/verb/ai_camera_track(var/target_name as null|anything in trackable_mobs()) + set name = "track" + set hidden = 1 //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass + + if(!target_name) + return + + var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) + + ai_actual_track(target) + +/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target as mob) + if(!istype(target)) return + spawn(0) + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) to_chat(src, "Unable to locate an airlock") - return - if(H.digitalcamo) + return + if(H.digitalcamo) to_chat(src, "Unable to locate an airlock") - return - if (!near_camera(target)) + return + if (!near_camera(target)) to_chat(src, "Target is not near any active cameras.") - return - var/obj/machinery/door/airlock/tobeopened - var/dist = -1 - for(var/obj/machinery/door/airlock/D in range(3,target)) - if(!D.density) continue - if(dist < 0) - dist = get_dist(D, target) + return + var/obj/machinery/door/airlock/tobeopened + var/dist = -1 + for(var/obj/machinery/door/airlock/D in range(3,target)) + if(!D.density) continue + if(dist < 0) + dist = get_dist(D, target) // to_chat(world, dist) - tobeopened = D - else - if(dist > get_dist(D, target)) - dist = get_dist(D, target) + tobeopened = D + else + if(dist > get_dist(D, target)) + dist = get_dist(D, target) // to_chat(world, dist) - tobeopened = D + tobeopened = D // to_chat(world, "found [tobeopened.name] closer") - else + else // to_chat(world, "[D.name] not close enough | [get_dist(D, target)] | [dist]") - if(tobeopened) - switch(alert(src, "Do you want to open \the [tobeopened] for [target]?","Doorknob_v2a.exe","Yes","No")) - if("Yes") - var/nhref = "src=\ref[tobeopened];aiEnable=7" - tobeopened.Topic(nhref, params2list(nhref), tobeopened, 1) + if(tobeopened) + switch(alert(src, "Do you want to open \the [tobeopened] for [target]?","Doorknob_v2a.exe","Yes","No")) + if("Yes") + var/nhref = "src=\ref[tobeopened];aiEnable=7" + tobeopened.Topic(nhref, params2list(nhref), tobeopened, 1) to_chat(src, "You've opened \the [tobeopened] for [target].") - if("No") + if("No") to_chat(src, "You deny the request.") - else + else to_chat(src, "You've failed to open an airlock for [target]") - return -/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) - if(!istype(target)) return - var/mob/living/silicon/ai/U = usr - - U.cameraFollow = target + return +/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) + if(!istype(target)) return + var/mob/living/silicon/ai/U = usr + + U.cameraFollow = target // to_chat(U, text("Now tracking [] on camera.", target.name)) - //if (U.machine == null) - // U.machine = U + //if (U.machine == null) + // U.machine = U to_chat(U, "Now tracking [target.name] on camera.") - - spawn (0) - while (U.cameraFollow == target) - if (U.cameraFollow == null) - return - if (istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + + spawn (0) + while (U.cameraFollow == target) + if (U.cameraFollow == null) + return + if (istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) to_chat(U, "Follow camera mode terminated.") - U.cameraFollow = null - return - if(H.digitalcamo) + U.cameraFollow = null + return + if(H.digitalcamo) to_chat(U, "Follow camera mode terminated.") - U.cameraFollow = null - return - - if(istype(target.loc,/obj/effect/dummy)) + U.cameraFollow = null + return + + if(istype(target.loc,/obj/effect/dummy)) to_chat(U, "Follow camera mode ended.") - U.cameraFollow = null - return - - if (!near_camera(target)) + U.cameraFollow = null + return + + if (!near_camera(target)) to_chat(U, "Target is not near any active cameras.") - sleep(100) - continue - - if(U.eyeobj) - U.eyeobj.forceMove(get_turf(target)) - else - view_core() - return - sleep(10) - -/proc/near_camera(var/mob/living/M) - if (!isturf(M.loc)) - return 0 - if(isrobot(M)) - var/mob/living/silicon/robot/R = M - if(!(R.camera && R.camera.can_use()) && !cameranet.checkCameraVis(M)) - return 0 - else if(!cameranet.checkCameraVis(M)) - return 0 - return 1 - -/obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob) - if (!istype(user)) - return - if (!src.can_use()) - return - user.eyeobj.forceMove(get_turf(src)) - - -/mob/living/silicon/ai/attack_ai(var/mob/user as mob) - ai_camera_list() - -/proc/camera_sort(list/L) - var/obj/machinery/camera/a - var/obj/machinery/camera/b - - for (var/i = L.len, i > 0, i--) - for (var/j = 1 to i - 1) - a = L[j] - b = L[j + 1] - if (a.c_tag_order != b.c_tag_order) - if (a.c_tag_order > b.c_tag_order) - L.Swap(j, j + 1) - else - if (sorttext(a.c_tag, b.c_tag) < 0) - L.Swap(j, j + 1) + sleep(100) + continue + + if(U.eyeobj) + U.eyeobj.forceMove(get_turf(target)) + else + view_core() + return + sleep(10) + +/proc/near_camera(var/mob/living/M) + if (!isturf(M.loc)) + return 0 + if(isrobot(M)) + var/mob/living/silicon/robot/R = M + if(!(R.camera && R.camera.can_use()) && !cameranet.checkCameraVis(M)) + return 0 + else if(!cameranet.checkCameraVis(M)) + return 0 + return 1 + +/obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob) + if (!istype(user)) + return + if (!src.can_use()) + return + user.eyeobj.forceMove(get_turf(src)) + + +/mob/living/silicon/ai/attack_ai(var/mob/user as mob) + ai_camera_list() + +/proc/camera_sort(list/L) + var/obj/machinery/camera/a + var/obj/machinery/camera/b + + for (var/i = L.len, i > 0, i--) + for (var/j = 1 to i - 1) + a = L[j] + b = L[j + 1] + if (a.c_tag_order != b.c_tag_order) + if (a.c_tag_order > b.c_tag_order) + L.Swap(j, j + 1) + else + if (sorttext(a.c_tag, b.c_tag) < 0) + L.Swap(j, j + 1) return L \ No newline at end of file diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 780c06651f7..6133e80b260 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -1,146 +1,146 @@ -/obj/machinery/cell_charger - name = "cell charger" - desc = "Charges power cells, drains power." - icon = 'icons/obj/power.dmi' - icon_state = "ccharger0" - icon_state_open = "ccharger_open" - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 10 //Power is already drained to charge batteries - power_channel = EQUIP - var/obj/item/weapon/cell/charging = null - var/transfer_rate = 200 //How much power do we output every process tick ? - var/transfer_efficiency = 0.7 //How much power ends up in the battery in percentage ? - var/transfer_rate_coeff = 1 //What is the quality of the parts that transfer energy (capacitators) ? - var/transfer_efficiency_bonus = 0 //What is the efficiency "bonus" (additive to percentage) from the parts used (scanning module) ? - var/chargelevel = -1 - - machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EMAGGABLE - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/machinery/cell_charger/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/cell_charger, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor - ) - RefreshParts() - -/obj/machinery/cell_charger/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/scanning_module/SM in component_parts) - T = (SM.rating - 1)*0.1 //There is one scanning module. Level 1 changes nothing (70 %), level 2 transfers 80 % of power, level 3 90 % - transfer_efficiency_bonus = T - T = 0 - for(var/obj/item/weapon/stock_parts/capacitor/CA in component_parts) - T += CA.rating //Two capacitors, every upgrade rank acts as a direct multiplier (up to 3 times base for two Level 3 Capacitors) - transfer_rate_coeff = T/2 - T = 0 - - -/obj/machinery/cell_charger/proc/updateicon() - icon_state = "ccharger[charging ? 1 : 0]" - - if(charging && !(stat & (BROKEN|NOPOWER)) ) - var/newlevel = round(charging.percent() * 4.0 / 99) +/obj/machinery/cell_charger + name = "cell charger" + desc = "Charges power cells, drains power." + icon = 'icons/obj/power.dmi' + icon_state = "ccharger0" + icon_state_open = "ccharger_open" + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 10 //Power is already drained to charge batteries + power_channel = EQUIP + var/obj/item/weapon/cell/charging = null + var/transfer_rate = 200 //How much power do we output every process tick ? + var/transfer_efficiency = 0.7 //How much power ends up in the battery in percentage ? + var/transfer_rate_coeff = 1 //What is the quality of the parts that transfer energy (capacitators) ? + var/transfer_efficiency_bonus = 0 //What is the efficiency "bonus" (additive to percentage) from the parts used (scanning module) ? + var/chargelevel = -1 + + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EMAGGABLE + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/machinery/cell_charger/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/cell_charger, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor + ) + RefreshParts() + +/obj/machinery/cell_charger/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/scanning_module/SM in component_parts) + T = (SM.rating - 1)*0.1 //There is one scanning module. Level 1 changes nothing (70 %), level 2 transfers 80 % of power, level 3 90 % + transfer_efficiency_bonus = T + T = 0 + for(var/obj/item/weapon/stock_parts/capacitor/CA in component_parts) + T += CA.rating //Two capacitors, every upgrade rank acts as a direct multiplier (up to 3 times base for two Level 3 Capacitors) + transfer_rate_coeff = T/2 + T = 0 + + +/obj/machinery/cell_charger/proc/updateicon() + icon_state = "ccharger[charging ? 1 : 0]" + + if(charging && !(stat & (BROKEN|NOPOWER)) ) + var/newlevel = round(charging.percent() * 4.0 / 99) // to_chat(world, "nl: [newlevel]") - - if(chargelevel != newlevel) - overlays.len = 0 - overlays += "ccharger-o[newlevel]" - chargelevel = newlevel - else - overlays.len = 0 - -/obj/machinery/cell_charger/examine(mob/user) - ..() + + if(chargelevel != newlevel) + overlays.len = 0 + overlays += "ccharger-o[newlevel]" + chargelevel = newlevel + else + overlays.len = 0 + +/obj/machinery/cell_charger/examine(mob/user) + ..() to_chat(user, "There's [charging ? "a" : "no"] cell in the charger.") - if(charging) + if(charging) to_chat(user, "Current charge: [charging.charge]") - -/obj/machinery/cell_charger/attackby(obj/item/weapon/W, mob/user) - if(stat & BROKEN) - return - - if(..()) - return 1 - if(istype(W, /obj/item/weapon/cell) && anchored) - if(charging) + +/obj/machinery/cell_charger/attackby(obj/item/weapon/W, mob/user) + if(stat & BROKEN) + return + + if(..()) + return 1 + if(istype(W, /obj/item/weapon/cell) && anchored) + if(charging) to_chat(user, "There is already a cell in [src].") - return - else - if(areaMaster.power_equip == 0) // There's no APC in this area, don't try to cheat power! + return + else + if(areaMaster.power_equip == 0) // There's no APC in this area, don't try to cheat power! to_chat(user, "[src] blinks red as you try to insert the cell!") - return - - if(user.drop_item(W, src)) - charging = W - user.visible_message("[user] inserts a cell into [src].", "You insert a cell into [src].") - chargelevel = -1 - updateicon() - -/obj/machinery/cell_charger/emag(mob/user) - if(!emagged) - emagged = 1 //Congratulations, you've done it - user.visible_message("[user] swipes a card into \the [src]'s charging port.", \ - "You hear fizzling coming from \the [src] and a wire turns red hot as you swipe the electromagnetic card. Better not use it anymore.") - return - -/obj/machinery/cell_charger/attack_robot(mob/user as mob) - if(isMoMMI(user) && Adjacent(user)) //To be able to remove cells from the charger - return attack_hand(user) - -/obj/machinery/cell_charger/attack_hand(mob/user) - if(charging) - if(emagged) //Oh shit nigger what are you doing - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - spawn(15) - explosion(src.loc, -1, 1, 3, adminlog = 0) //Overload - Destroy(src) //It exploded, rip - return - usr.put_in_hands(charging) - charging.add_fingerprint(user) - charging.updateicon() - src.charging = null - user.visible_message("[user] removes the cell from [src].", "You remove the cell from [src].") - chargelevel = -1 - updateicon() - -/obj/machinery/cell_charger/wrenchAnchor(mob/user) - if(charging) + return + + if(user.drop_item(W, src)) + charging = W + user.visible_message("[user] inserts a cell into [src].", "You insert a cell into [src].") + chargelevel = -1 + updateicon() + +/obj/machinery/cell_charger/emag(mob/user) + if(!emagged) + emagged = 1 //Congratulations, you've done it + user.visible_message("[user] swipes a card into \the [src]'s charging port.", \ + "You hear fizzling coming from \the [src] and a wire turns red hot as you swipe the electromagnetic card. Better not use it anymore.") + return + +/obj/machinery/cell_charger/attack_robot(mob/user as mob) + if(isMoMMI(user) && Adjacent(user)) //To be able to remove cells from the charger + return attack_hand(user) + +/obj/machinery/cell_charger/attack_hand(mob/user) + if(charging) + if(emagged) //Oh shit nigger what are you doing + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + spawn(15) + explosion(src.loc, -1, 1, 3, adminlog = 0) //Overload + Destroy(src) //It exploded, rip + return + usr.put_in_hands(charging) + charging.add_fingerprint(user) + charging.updateicon() + src.charging = null + user.visible_message("[user] removes the cell from [src].", "You remove the cell from [src].") + chargelevel = -1 + updateicon() + +/obj/machinery/cell_charger/wrenchAnchor(mob/user) + if(charging) to_chat(user, "Remove the cell first!") - return - ..() - -/obj/machinery/cell_charger/attack_ai(mob/user) - return - -/obj/machinery/cell_charger/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - return - if(charging) - charging.emp_act(severity) - ..(severity) - - -/obj/machinery/cell_charger/process() + return + ..() + +/obj/machinery/cell_charger/attack_ai(mob/user) + return + +/obj/machinery/cell_charger/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + return + if(charging) + charging.emp_act(severity) + ..(severity) + + +/obj/machinery/cell_charger/process() // to_chat(world, "ccpt [charging] [stat]") - if(!charging || (stat & (BROKEN|NOPOWER)) || !anchored) - return - - if(emagged) //Did someone fuck with the charger ? - use_power(transfer_rate*transfer_rate_coeff*10) //Drain all the power - charging.give(transfer_rate*transfer_rate_coeff*(transfer_efficiency+transfer_efficiency_bonus)*0.25) //Lose most of it - else - use_power(transfer_rate*transfer_rate_coeff) //Snatch some power - charging.give(transfer_rate*transfer_rate_coeff*(transfer_efficiency+transfer_efficiency_bonus)) //Inefficiency (Joule effect + other shenanigans) - - updateicon() + if(!charging || (stat & (BROKEN|NOPOWER)) || !anchored) + return + + if(emagged) //Did someone fuck with the charger ? + use_power(transfer_rate*transfer_rate_coeff*10) //Drain all the power + charging.give(transfer_rate*transfer_rate_coeff*(transfer_efficiency+transfer_efficiency_bonus)*0.25) //Lose most of it + else + use_power(transfer_rate*transfer_rate_coeff) //Snatch some power + charging.give(transfer_rate*transfer_rate_coeff*(transfer_efficiency+transfer_efficiency_bonus)) //Inefficiency (Joule effect + other shenanigans) + + updateicon() diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 2210bd18943..a8a0c27c9d2 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -1,111 +1,111 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/machinery/computer/operating - name = "Operating Computer" - density = 1 - anchored = 1.0 - icon_state = "operating" - circuit = "/obj/item/weapon/circuitboard/operating" - var/mob/living/carbon/human/victim = null - var/obj/machinery/optable/optable = null - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/operating/New() - ..() - spawn(5) - updatemodules() - return - return - -/obj/machinery/computer/operating/proc/updatemodules() - src.optable = findoptable() - -/obj/machinery/computer/operating/proc/findoptable() - var/obj/machinery/optable/optablef = null - - // Loop through every direction - for(dir in list(NORTH,EAST,SOUTH,WEST)) - - // Try to find a scanner in that direction - optablef = locate(/obj/machinery/optable, get_step(src, dir)) - - // If found, then we break, and return the scanner - if (!isnull(optablef)) - break - - // If no scanner was found, it will return null - return optablef - -/obj/machinery/computer/operating/attack_ai(user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/med_data/attack_paw(user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/operating/attack_hand(mob/user as mob) - if(..()) - return - add_fingerprint(user) - - if(stat & (BROKEN|NOPOWER)) - return - - updatemodules() - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\Operating.dm:41: var/dat = "Operating Computer\n" - var/dat = {"Operating Computer"} - // END AUTOFIX - if(!isnull(src.optable) && (src.optable.check_victim())) - src.victim = src.optable.victim - dat += {" -Patient Information:
      -
      -Name: [src.victim.real_name]
      -Age: [src.victim.age]
      -Blood Type: [src.victim.b_type]
      -
      -Health: [src.victim.health]
      -Brute Damage: [src.victim.getBruteLoss()]
      -Toxins Damage: [src.victim.getToxLoss()]
      -Fire Damage: [src.victim.getFireLoss()]
      -Suffocation Damage: [src.victim.getOxyLoss()]
      -Patient Status: [src.victim.stat ? "Non-Responsive" : "Stable"]
      -
      -Close"} - else - src.victim = null - dat += {" -Patient Information:
      -
      -No Patient Detected
      -
      -Close"} - user << browse(dat, "window=op") - user.set_machine(src) - onclose(user, "op") - -/obj/machinery/computer/operating/Topic(href, href_list) - if(..()) - return 1 - else - usr.set_machine(src) - return - -/obj/machinery/computer/operating/process() - if(..()) - src.updateDialog() - update_icon() - -/obj/machinery/computer/operating/update_icon() - ..() - if(!(stat & (BROKEN | NOPOWER))) - updatemodules() - if(!isnull(src.optable) && (src.optable.check_victim())) - src.victim = src.optable.victim - if(victim.stat == DEAD) - icon_state = "operating-dead" - else - icon_state = "operating-living" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/computer/operating + name = "Operating Computer" + density = 1 + anchored = 1.0 + icon_state = "operating" + circuit = "/obj/item/weapon/circuitboard/operating" + var/mob/living/carbon/human/victim = null + var/obj/machinery/optable/optable = null + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/operating/New() + ..() + spawn(5) + updatemodules() + return + return + +/obj/machinery/computer/operating/proc/updatemodules() + src.optable = findoptable() + +/obj/machinery/computer/operating/proc/findoptable() + var/obj/machinery/optable/optablef = null + + // Loop through every direction + for(dir in list(NORTH,EAST,SOUTH,WEST)) + + // Try to find a scanner in that direction + optablef = locate(/obj/machinery/optable, get_step(src, dir)) + + // If found, then we break, and return the scanner + if (!isnull(optablef)) + break + + // If no scanner was found, it will return null + return optablef + +/obj/machinery/computer/operating/attack_ai(user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/med_data/attack_paw(user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/operating/attack_hand(mob/user as mob) + if(..()) + return + add_fingerprint(user) + + if(stat & (BROKEN|NOPOWER)) + return + + updatemodules() + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\Operating.dm:41: var/dat = "Operating Computer\n" + var/dat = {"Operating Computer"} + // END AUTOFIX + if(!isnull(src.optable) && (src.optable.check_victim())) + src.victim = src.optable.victim + dat += {" +Patient Information:
      +
      +Name: [src.victim.real_name]
      +Age: [src.victim.age]
      +Blood Type: [src.victim.b_type]
      +
      +Health: [src.victim.health]
      +Brute Damage: [src.victim.getBruteLoss()]
      +Toxins Damage: [src.victim.getToxLoss()]
      +Fire Damage: [src.victim.getFireLoss()]
      +Suffocation Damage: [src.victim.getOxyLoss()]
      +Patient Status: [src.victim.stat ? "Non-Responsive" : "Stable"]
      +
      +Close"} + else + src.victim = null + dat += {" +Patient Information:
      +
      +No Patient Detected
      +
      +Close"} + user << browse(dat, "window=op") + user.set_machine(src) + onclose(user, "op") + +/obj/machinery/computer/operating/Topic(href, href_list) + if(..()) + return 1 + else + usr.set_machine(src) + return + +/obj/machinery/computer/operating/process() + if(..()) + src.updateDialog() + update_icon() + +/obj/machinery/computer/operating/update_icon() + ..() + if(!(stat & (BROKEN | NOPOWER))) + updatemodules() + if(!isnull(src.optable) && (src.optable.check_victim())) + src.victim = src.optable.victim + if(victim.stat == DEAD) + icon_state = "operating-dead" + else + icon_state = "operating-living" diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index 6d4d65d44a5..99b58aab420 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -1,124 +1,124 @@ -/obj/machinery/computer/aifixer - name = "AI System Integrity Restorer" - icon = 'icons/obj/computer.dmi' - icon_state = "ai-fixer" - req_access = list(access_captain, access_robotics, access_heads) - var/mob/living/silicon/ai/occupant = null - var/active = 0 - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/aifixer/New() - ..() - update_icon() - -/obj/machinery/computer/aifixer/attackby(I as obj, user as mob) - if(istype(I, /obj/item/device/aicard)) - if(stat & (NOPOWER|BROKEN)) +/obj/machinery/computer/aifixer + name = "AI System Integrity Restorer" + icon = 'icons/obj/computer.dmi' + icon_state = "ai-fixer" + req_access = list(access_captain, access_robotics, access_heads) + var/mob/living/silicon/ai/occupant = null + var/active = 0 + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/aifixer/New() + ..() + update_icon() + +/obj/machinery/computer/aifixer/attackby(I as obj, user as mob) + if(istype(I, /obj/item/device/aicard)) + if(stat & (NOPOWER|BROKEN)) to_chat(user, "This terminal isn't functioning right now, get it working!") - return - I:transfer_ai("AIFIXER","AICARD",src,user) - return - return ..() - -/obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/computer/aifixer/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob) - if(..()) - return - - var/dat = "

      AI System Integrity Restorer



      " - - if (src.occupant) - var/laws - dat += "Stored AI: [src.occupant.name]
      System integrity: [src.occupant.system_integrity()]%
      " - - if (src.occupant.laws.zeroth) - laws += "0: [src.occupant.laws.zeroth]
      " - - var/number = 1 - for (var/index = 1, index <= src.occupant.laws.inherent.len, index++) - var/law = src.occupant.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
      " - number++ - - for (var/index = 1, index <= src.occupant.laws.supplied.len, index++) - var/law = src.occupant.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
      " - number++ - - dat += "Laws:
      [laws]
      " - - if (src.occupant.stat == 2) - dat += "AI nonfunctional" - else - dat += "AI functional" - if (!src.active) - dat += {"

      Begin Reconstruction"} - else - dat += "

      Reconstruction in process, please wait.
      " - dat += {" Close"} - - - user.set_machine(src) - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - -/obj/machinery/computer/aifixer/process() - if(..()) - src.updateUsrDialog() - return - -/obj/machinery/computer/aifixer/Topic(href, href_list) - if(..()) - return - if (href_list["fix"]) - src.active = 1 - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-on") - while (src.occupant.health < 100) - src.occupant.adjustOxyLoss(-1) - src.occupant.adjustFireLoss(-1) - src.occupant.adjustToxLoss(-1) - src.occupant.adjustBruteLoss(-1) - src.occupant.updatehealth() - if (src.occupant.health >= 0 && src.occupant.stat == 2) - src.occupant.stat = 0 - src.occupant.lying = 0 - src.occupant.resurrect() - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") - src.updateUsrDialog() - sleep(10) - src.active = 0 - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on") - - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - - -/obj/machinery/computer/aifixer/update_icon() - ..() - overlays = 0 - // Broken / Unpowered - if(stat & (BROKEN | NOPOWER)) - return - - if (occupant) - switch (occupant.stat) - if (0) - overlays += image('icons/obj/computer.dmi', "ai-fixer-full") - if (2) - overlays += image('icons/obj/computer.dmi', "ai-fixer-404") - else - overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") + return + I:transfer_ai("AIFIXER","AICARD",src,user) + return + return ..() + +/obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/computer/aifixer/attack_paw(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob) + if(..()) + return + + var/dat = "

      AI System Integrity Restorer



      " + + if (src.occupant) + var/laws + dat += "Stored AI: [src.occupant.name]
      System integrity: [src.occupant.system_integrity()]%
      " + + if (src.occupant.laws.zeroth) + laws += "0: [src.occupant.laws.zeroth]
      " + + var/number = 1 + for (var/index = 1, index <= src.occupant.laws.inherent.len, index++) + var/law = src.occupant.laws.inherent[index] + if (length(law) > 0) + laws += "[number]: [law]
      " + number++ + + for (var/index = 1, index <= src.occupant.laws.supplied.len, index++) + var/law = src.occupant.laws.supplied[index] + if (length(law) > 0) + laws += "[number]: [law]
      " + number++ + + dat += "Laws:
      [laws]
      " + + if (src.occupant.stat == 2) + dat += "AI nonfunctional" + else + dat += "AI functional" + if (!src.active) + dat += {"

      Begin Reconstruction"} + else + dat += "

      Reconstruction in process, please wait.
      " + dat += {" Close"} + + + user.set_machine(src) + + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + +/obj/machinery/computer/aifixer/process() + if(..()) + src.updateUsrDialog() + return + +/obj/machinery/computer/aifixer/Topic(href, href_list) + if(..()) + return + if (href_list["fix"]) + src.active = 1 + src.overlays += image('icons/obj/computer.dmi', "ai-fixer-on") + while (src.occupant.health < 100) + src.occupant.adjustOxyLoss(-1) + src.occupant.adjustFireLoss(-1) + src.occupant.adjustToxLoss(-1) + src.occupant.adjustBruteLoss(-1) + src.occupant.updatehealth() + if (src.occupant.health >= 0 && src.occupant.stat == 2) + src.occupant.stat = 0 + src.occupant.lying = 0 + src.occupant.resurrect() + src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") + src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") + src.updateUsrDialog() + sleep(10) + src.active = 0 + src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on") + + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + + +/obj/machinery/computer/aifixer/update_icon() + ..() + overlays = 0 + // Broken / Unpowered + if(stat & (BROKEN | NOPOWER)) + return + + if (occupant) + switch (occupant.stat) + if (0) + overlays += image('icons/obj/computer.dmi', "ai-fixer-full") + if (2) + overlays += image('icons/obj/computer.dmi', "ai-fixer-404") + else + overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 15a6320fe7f..06cb83b4836 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -1,311 +1,311 @@ -/obj/machinery/computer/arcade - name = "arcade machine" - desc = "Does not support pinball." - icon = 'icons/obj/computer.dmi' - icon_state = "arcade" - circuit = "/obj/item/weapon/circuitboard/arcade" - var/enemy_name = "Space Villain" - var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc - var/player_hp = 30 //Player health/attack points - var/player_mp = 10 - var/enemy_hp = 45 //Enemy health/attack points - var/enemy_mp = 20 - var/gameover = 0 - var/blocked = 0 //Player cannot attack/heal while set - - machine_flags = EMAGGABLE | SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - emag_cost = 0 // because fun - - light_color = LIGHT_COLOR_GREEN - - var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2, - /obj/item/toy/cards = 2, - /obj/item/toy/blink = 2, - /obj/item/clothing/under/syndicate/tacticool = 2, - /obj/item/toy/sword = 2, - /obj/item/toy/bomb = 1, - /obj/item/toy/gun = 2, - /obj/item/toy/crossbow = 2, - /obj/item/clothing/suit/syndicatefake = 2, - /obj/item/weapon/storage/fancy/crayons = 2, - /obj/item/toy/spinningtoy = 2, - /obj/item/toy/minimeteor = 2, - /obj/item/device/whisperphone = 2, - /obj/item/toy/prize/ripley = 1, - /obj/item/toy/prize/fireripley = 1, - /obj/item/toy/prize/deathripley = 1, - /obj/item/toy/prize/gygax = 1, - /obj/item/toy/prize/durand = 1, - /obj/item/toy/prize/honk = 1, - /obj/item/toy/prize/marauder = 1, - /obj/item/toy/prize/seraph = 1, - /obj/item/toy/prize/mauler = 1, - /obj/item/toy/prize/odysseus = 1, - /obj/item/toy/prize/phazon = 1 - ) - -/obj/machinery/computer/arcade - var/turtle = 0 - -/obj/machinery/computer/arcade/New() - ..() - var/name_action - var/name_part1 - var/name_part2 - - name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ") - - name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") - name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn") - - src.enemy_name = replacetext((name_part1 + name_part2), "the ", "") - src.name = (name_action + name_part1 + name_part2) - - -/obj/machinery/computer/arcade/proc/import_game_data(var/obj/item/weapon/circuitboard/arcade/A) - if(!A || !A.game_data || !A.game_data.len) - return - name = A.game_data["name"] - emagged = A.game_data["emagged"] - enemy_name = A.game_data["enemy_name"] - temp = A.game_data["temp"] - player_hp = A.game_data["player_hp"] - player_mp = A.game_data["player_mp"] - enemy_hp = A.game_data["enemy_hp"] - enemy_mp =A.game_data["enemy_mp"] - gameover = A.game_data["gameover"] - blocked = A.game_data["blocked"] - -/obj/machinery/computer/arcade/proc/export_game_data(var/obj/item/weapon/circuitboard/arcade/A) - if(!A) return - if(!A.game_data) - A.game_data = list() - A.game_data.len = 0 - A.game_data["name"] = name - A.game_data["emagged"] = emagged - A.game_data["enemy_name"] = enemy_name - A.game_data["temp"] = temp - A.game_data["player_hp"] = player_hp - A.game_data["player_mp"] = player_mp - A.game_data["enemy_hp"] = enemy_hp - A.game_data["enemy_mp"] = enemy_mp - A.game_data["gameover"] = gameover - A.game_data["blocked"] = blocked - - - -/obj/machinery/computer/arcade/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/arcade/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/arcade/attack_hand(mob/user as mob) - if(..()) - return - user.set_machine(src) - var/dat = "Close" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\arcade.dm:67: dat += "

      [src.enemy_name]

      " - dat += {"

      [src.enemy_name]

      -

      [src.temp]

      -
      Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]
      "} - // END AUTOFIX - if (src.gameover) - dat += "
      New Game" - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\arcade.dm:75: dat += "
      Attack | " - dat += {"
      Attack | - Heal | - Recharge Power"} - // END AUTOFIX - - dat += "
      " - - user << browse(dat, "window=arcade") - onclose(user, "arcade") - return - -/obj/machinery/computer/arcade/Topic(href, href_list) - if(..()) - return - - if (!src.blocked && !src.gameover) - if (href_list["attack"]) - src.blocked = 1 - var/attackamt = rand(2,6) - src.temp = "You attack for [attackamt] damage!" - src.updateUsrDialog() - if(turtle > 0) - turtle-- - - sleep(10) - src.enemy_hp -= attackamt - src.arcade_action() - - else if (href_list["heal"]) - src.blocked = 1 - var/pointamt = rand(1,3) - var/healamt = rand(6,8) - src.temp = "You use [pointamt] magic to heal for [healamt] damage!" - src.updateUsrDialog() - turtle++ - - sleep(10) - src.player_mp -= pointamt - src.player_hp += healamt - src.blocked = 1 - src.updateUsrDialog() - src.arcade_action() - - else if (href_list["charge"]) - src.blocked = 1 - var/chargeamt = rand(4,7) - src.temp = "You regain [chargeamt] points" - src.player_mp += chargeamt - if(turtle > 0) - turtle-- - - src.updateUsrDialog() - sleep(10) - src.arcade_action() - - if (href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=arcade") - - else if (href_list["newgame"]) //Reset everything - temp = "New Round" - player_hp = 30 - player_mp = 10 - enemy_hp = 45 - enemy_mp = 20 - gameover = 0 - turtle = 0 - - if(emagged) - src.New() - emagged = 0 - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer/arcade/proc/arcade_action() - if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0)) - if(!gameover) - src.gameover = 1 - src.temp = "[src.enemy_name] has fallen! Rejoice!" - - if(emagged) - feedback_inc("arcade_win_emagged") - new /obj/effect/spawner/newbomb/timer/syndicate(src.loc) - new /obj/item/clothing/head/collectable/petehat(src.loc) - new /obj/item/device/maracas(src.loc) - new /obj/item/device/maracas(src.loc) - message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.") - log_game("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.") - src.New() - emagged = 0 - else if(!contents.len) - feedback_inc("arcade_win_normal") - var/prizeselect = pickweight(prizes) - new prizeselect(src.loc) - - if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun - new /obj/item/toy/ammo/gun(src.loc) - - else if(istype(prizeselect, /obj/item/clothing/suit/syndicatefake)) //Helmet is part of the suit - new /obj/item/clothing/head/syndicatefake(src.loc) - - else - feedback_inc("arcade_win_normal") - var/atom/movable/prize = pick(contents) - prize.loc = src.loc - - else if (emagged && (turtle >= 4)) - var/boomamt = rand(5,10) - src.temp = "[src.enemy_name] throws a bomb, exploding you for [boomamt] damage!" - src.player_hp -= boomamt - - else if ((src.enemy_mp <= 5) && (prob(70))) - var/stealamt = rand(2,3) - src.temp = "[src.enemy_name] steals [stealamt] of your power!" - src.player_mp -= stealamt - src.updateUsrDialog() - - if (src.player_mp <= 0) - src.gameover = 1 - sleep(10) - src.temp = "You have been drained! GAME OVER" - if(emagged) - feedback_inc("arcade_loss_mana_emagged") - usr.gib() - else - feedback_inc("arcade_loss_mana_normal") - - else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4)) - src.temp = "[src.enemy_name] heals for 4 health!" - src.enemy_hp += 4 - src.enemy_mp -= 4 - - else - var/attackamt = rand(3,6) - src.temp = "[src.enemy_name] attacks for [attackamt] damage!" - src.player_hp -= attackamt - - if ((src.player_mp <= 0) || (src.player_hp <= 0)) - src.gameover = 1 - src.temp = "You have been crushed! GAME OVER" - if(emagged) - feedback_inc("arcade_loss_hp_emagged") - usr.gib() - else - feedback_inc("arcade_loss_hp_normal") - - src.blocked = 0 - return - -/obj/machinery/computer/arcade/emag(mob/user as mob) - temp = "If you die in the game, you die for real!" - player_hp = 30 - player_mp = 10 - enemy_hp = 45 - enemy_mp = 20 - gameover = 0 - blocked = 0 - - emagged = 1 - - enemy_name = "Cuban Pete" - name = "Outbomb Cuban Pete" - - src.updateUsrDialog() - -/obj/machinery/computer/arcade/emp_act(severity) - if(stat & (NOPOWER|BROKEN)) - ..(severity) - return - var/empprize = null - var/num_of_prizes = 0 - switch(severity) - if(1) - num_of_prizes = rand(1,4) - if(2) - num_of_prizes = rand(0,2) - for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) - empprize = pickweight(prizes) - new empprize(src.loc) - - ..(severity) - -/obj/machinery/computer/arcade/togglePanelOpen(var/obj/toggleitem, mob/user) - var/obj/item/weapon/circuitboard/arcade/A - if(circuit) - A = new - export_game_data(A) - ..(toggleitem, user, A) +/obj/machinery/computer/arcade + name = "arcade machine" + desc = "Does not support pinball." + icon = 'icons/obj/computer.dmi' + icon_state = "arcade" + circuit = "/obj/item/weapon/circuitboard/arcade" + var/enemy_name = "Space Villain" + var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc + var/player_hp = 30 //Player health/attack points + var/player_mp = 10 + var/enemy_hp = 45 //Enemy health/attack points + var/enemy_mp = 20 + var/gameover = 0 + var/blocked = 0 //Player cannot attack/heal while set + + machine_flags = EMAGGABLE | SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + emag_cost = 0 // because fun + + light_color = LIGHT_COLOR_GREEN + + var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2, + /obj/item/toy/cards = 2, + /obj/item/toy/blink = 2, + /obj/item/clothing/under/syndicate/tacticool = 2, + /obj/item/toy/sword = 2, + /obj/item/toy/bomb = 1, + /obj/item/toy/gun = 2, + /obj/item/toy/crossbow = 2, + /obj/item/clothing/suit/syndicatefake = 2, + /obj/item/weapon/storage/fancy/crayons = 2, + /obj/item/toy/spinningtoy = 2, + /obj/item/toy/minimeteor = 2, + /obj/item/device/whisperphone = 2, + /obj/item/toy/prize/ripley = 1, + /obj/item/toy/prize/fireripley = 1, + /obj/item/toy/prize/deathripley = 1, + /obj/item/toy/prize/gygax = 1, + /obj/item/toy/prize/durand = 1, + /obj/item/toy/prize/honk = 1, + /obj/item/toy/prize/marauder = 1, + /obj/item/toy/prize/seraph = 1, + /obj/item/toy/prize/mauler = 1, + /obj/item/toy/prize/odysseus = 1, + /obj/item/toy/prize/phazon = 1 + ) + +/obj/machinery/computer/arcade + var/turtle = 0 + +/obj/machinery/computer/arcade/New() + ..() + var/name_action + var/name_part1 + var/name_part2 + + name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ") + + name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") + name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn") + + src.enemy_name = replacetext((name_part1 + name_part2), "the ", "") + src.name = (name_action + name_part1 + name_part2) + + +/obj/machinery/computer/arcade/proc/import_game_data(var/obj/item/weapon/circuitboard/arcade/A) + if(!A || !A.game_data || !A.game_data.len) + return + name = A.game_data["name"] + emagged = A.game_data["emagged"] + enemy_name = A.game_data["enemy_name"] + temp = A.game_data["temp"] + player_hp = A.game_data["player_hp"] + player_mp = A.game_data["player_mp"] + enemy_hp = A.game_data["enemy_hp"] + enemy_mp =A.game_data["enemy_mp"] + gameover = A.game_data["gameover"] + blocked = A.game_data["blocked"] + +/obj/machinery/computer/arcade/proc/export_game_data(var/obj/item/weapon/circuitboard/arcade/A) + if(!A) return + if(!A.game_data) + A.game_data = list() + A.game_data.len = 0 + A.game_data["name"] = name + A.game_data["emagged"] = emagged + A.game_data["enemy_name"] = enemy_name + A.game_data["temp"] = temp + A.game_data["player_hp"] = player_hp + A.game_data["player_mp"] = player_mp + A.game_data["enemy_hp"] = enemy_hp + A.game_data["enemy_mp"] = enemy_mp + A.game_data["gameover"] = gameover + A.game_data["blocked"] = blocked + + + +/obj/machinery/computer/arcade/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/arcade/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/arcade/attack_hand(mob/user as mob) + if(..()) + return + user.set_machine(src) + var/dat = "Close" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\arcade.dm:67: dat += "

      [src.enemy_name]

      " + dat += {"

      [src.enemy_name]

      +

      [src.temp]

      +
      Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]
      "} + // END AUTOFIX + if (src.gameover) + dat += "
      New Game" + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\arcade.dm:75: dat += "
      Attack | " + dat += {"
      Attack | + Heal | + Recharge Power"} + // END AUTOFIX + + dat += "
      " + + user << browse(dat, "window=arcade") + onclose(user, "arcade") + return + +/obj/machinery/computer/arcade/Topic(href, href_list) + if(..()) + return + + if (!src.blocked && !src.gameover) + if (href_list["attack"]) + src.blocked = 1 + var/attackamt = rand(2,6) + src.temp = "You attack for [attackamt] damage!" + src.updateUsrDialog() + if(turtle > 0) + turtle-- + + sleep(10) + src.enemy_hp -= attackamt + src.arcade_action() + + else if (href_list["heal"]) + src.blocked = 1 + var/pointamt = rand(1,3) + var/healamt = rand(6,8) + src.temp = "You use [pointamt] magic to heal for [healamt] damage!" + src.updateUsrDialog() + turtle++ + + sleep(10) + src.player_mp -= pointamt + src.player_hp += healamt + src.blocked = 1 + src.updateUsrDialog() + src.arcade_action() + + else if (href_list["charge"]) + src.blocked = 1 + var/chargeamt = rand(4,7) + src.temp = "You regain [chargeamt] points" + src.player_mp += chargeamt + if(turtle > 0) + turtle-- + + src.updateUsrDialog() + sleep(10) + src.arcade_action() + + if (href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=arcade") + + else if (href_list["newgame"]) //Reset everything + temp = "New Round" + player_hp = 30 + player_mp = 10 + enemy_hp = 45 + enemy_mp = 20 + gameover = 0 + turtle = 0 + + if(emagged) + src.New() + emagged = 0 + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + +/obj/machinery/computer/arcade/proc/arcade_action() + if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0)) + if(!gameover) + src.gameover = 1 + src.temp = "[src.enemy_name] has fallen! Rejoice!" + + if(emagged) + feedback_inc("arcade_win_emagged") + new /obj/effect/spawner/newbomb/timer/syndicate(src.loc) + new /obj/item/clothing/head/collectable/petehat(src.loc) + new /obj/item/device/maracas(src.loc) + new /obj/item/device/maracas(src.loc) + message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.") + log_game("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.") + src.New() + emagged = 0 + else if(!contents.len) + feedback_inc("arcade_win_normal") + var/prizeselect = pickweight(prizes) + new prizeselect(src.loc) + + if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun + new /obj/item/toy/ammo/gun(src.loc) + + else if(istype(prizeselect, /obj/item/clothing/suit/syndicatefake)) //Helmet is part of the suit + new /obj/item/clothing/head/syndicatefake(src.loc) + + else + feedback_inc("arcade_win_normal") + var/atom/movable/prize = pick(contents) + prize.loc = src.loc + + else if (emagged && (turtle >= 4)) + var/boomamt = rand(5,10) + src.temp = "[src.enemy_name] throws a bomb, exploding you for [boomamt] damage!" + src.player_hp -= boomamt + + else if ((src.enemy_mp <= 5) && (prob(70))) + var/stealamt = rand(2,3) + src.temp = "[src.enemy_name] steals [stealamt] of your power!" + src.player_mp -= stealamt + src.updateUsrDialog() + + if (src.player_mp <= 0) + src.gameover = 1 + sleep(10) + src.temp = "You have been drained! GAME OVER" + if(emagged) + feedback_inc("arcade_loss_mana_emagged") + usr.gib() + else + feedback_inc("arcade_loss_mana_normal") + + else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4)) + src.temp = "[src.enemy_name] heals for 4 health!" + src.enemy_hp += 4 + src.enemy_mp -= 4 + + else + var/attackamt = rand(3,6) + src.temp = "[src.enemy_name] attacks for [attackamt] damage!" + src.player_hp -= attackamt + + if ((src.player_mp <= 0) || (src.player_hp <= 0)) + src.gameover = 1 + src.temp = "You have been crushed! GAME OVER" + if(emagged) + feedback_inc("arcade_loss_hp_emagged") + usr.gib() + else + feedback_inc("arcade_loss_hp_normal") + + src.blocked = 0 + return + +/obj/machinery/computer/arcade/emag(mob/user as mob) + temp = "If you die in the game, you die for real!" + player_hp = 30 + player_mp = 10 + enemy_hp = 45 + enemy_mp = 20 + gameover = 0 + blocked = 0 + + emagged = 1 + + enemy_name = "Cuban Pete" + name = "Outbomb Cuban Pete" + + src.updateUsrDialog() + +/obj/machinery/computer/arcade/emp_act(severity) + if(stat & (NOPOWER|BROKEN)) + ..(severity) + return + var/empprize = null + var/num_of_prizes = 0 + switch(severity) + if(1) + num_of_prizes = rand(1,4) + if(2) + num_of_prizes = rand(0,2) + for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) + empprize = pickweight(prizes) + new empprize(src.loc) + + ..(severity) + +/obj/machinery/computer/arcade/togglePanelOpen(var/obj/toggleitem, mob/user) + var/obj/item/weapon/circuitboard/arcade/A + if(circuit) + A = new + export_game_data(A) + ..(toggleitem, user, A) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index cf696726628..8dc46932c20 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -1,439 +1,439 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/structure/computerframe - density = 1 - anchored = 0 - name = "Computer Frame" - icon = 'icons/obj/stock_parts.dmi' - icon_state = "0" - var/state = 0 - var/obj/item/weapon/circuitboard/circuit = null -// weight = 1.0E8 - -/obj/structure/computerframe/Destroy() - ..() - qdel(circuit) - circuit = null - -/obj/item/weapon/circuitboard - density = 0 - anchored = 0 - w_class = 2.0 - name = "Circuit board" - icon = 'icons/obj/module.dmi' - icon_state = "id_mod" - item_state = "circuitboard" - origin_tech = "programming=2" - starting_materials = list(MAT_GLASS = 2000) // Recycle glass only - w_type = RECYK_ELECTRONIC - - var/id_tag = null - var/frequency = null - var/build_path = null - var/board_type = "computer" - var/list/req_components = null - var/powernet = null - var/list/records = null - var/frame_desc = null - var/contain_parts = 1 - -/obj/item/weapon/circuitboard/message_monitor - name = "Circuit board (Message Monitor)" - build_path = "/obj/machinery/computer/message_monitor" - origin_tech = "programming=3" -/obj/item/weapon/circuitboard/security - name = "Circuit board (Security)" - build_path = "/obj/machinery/computer/security" -/obj/item/weapon/circuitboard/security/engineering - name = "Circuit board (Engineering)" - build_path = "/obj/machinery/computer/security/engineering" -/obj/item/weapon/circuitboard/aicore - name = "Circuit board (AI core)" - origin_tech = "programming=4;biotech=2" - board_type = "other" -/obj/item/weapon/circuitboard/aiupload - name = "Circuit board (AI Upload)" - build_path = "/obj/machinery/computer/aiupload" - origin_tech = "programming=4" -/obj/item/weapon/circuitboard/borgupload - name = "Circuit board (Cyborg Upload)" - build_path = "/obj/machinery/computer/borgupload" - origin_tech = "programming=4" -/obj/item/weapon/circuitboard/med_data - name = "Circuit board (Medical Records)" - build_path = "/obj/machinery/computer/med_data" -/obj/item/weapon/circuitboard/pandemic - name = "Circuit board (PanD.E.M.I.C. 2200)" - build_path = "/obj/machinery/computer/pandemic" - origin_tech = "programming=2;biotech=2" -/obj/item/weapon/circuitboard/scan_consolenew - name = "Circuit board (DNA Machine)" - build_path = "/obj/machinery/computer/scan_consolenew" - origin_tech = "programming=2;biotech=2" -/obj/item/weapon/circuitboard/communications - name = "Circuit board (Communications)" - build_path = "/obj/machinery/computer/communications" - origin_tech = "programming=2;magnets=2" -/obj/item/weapon/circuitboard/card - name = "Circuit board (ID Computer)" - build_path = "/obj/machinery/computer/card" -/obj/item/weapon/circuitboard/card/centcom - name = "Circuit board (CentCom ID Computer)" - build_path = "/obj/machinery/computer/card/centcom" -//obj/item/weapon/circuitboard/shield -// name = "Circuit board (Shield Control)" -// build_path = "/obj/machinery/computer/stationshield" -/obj/item/weapon/circuitboard/teleporter - name = "Circuit board (Teleporter)" - build_path = "/obj/machinery/computer/teleporter" - origin_tech = "programming=2;bluespace=2" -/obj/item/weapon/circuitboard/secure_data - name = "Circuit board (Security Records)" - build_path = "/obj/machinery/computer/secure_data" -/obj/item/weapon/circuitboard/stationalert - name = "Circuit board (Station Alerts)" - build_path = "/obj/machinery/computer/station_alert" -/obj/item/weapon/circuitboard/atmospheresiphonswitch - name = "Circuit board (Atmosphere siphon control)" - build_path = "/obj/machinery/computer/atmosphere/siphonswitch" -/obj/item/weapon/circuitboard/air_management - name = "Circuit board (Atmospheric General Monitor)" - build_path = "/obj/machinery/computer/general_air_control" -/obj/item/weapon/circuitboard/atmos_automation - name = "Circuit board (Atmospherics Automation)" - build_path = "/obj/machinery/computer/general_air_control/atmos_automation" -/obj/item/weapon/circuitboard/large_tank_control - name = "Circuit board (Atmospheric Tank Control)" - build_path = "/obj/machinery/computer/general_air_control/large_tank_control" -/obj/item/weapon/circuitboard/injector_control - name = "Circuit board (Injector control)" - build_path = "/obj/machinery/computer/general_air_control/fuel_injection" -/obj/item/weapon/circuitboard/atmos_alert - name = "Circuit board (Atmospheric Alert)" - build_path = "/obj/machinery/computer/atmos_alert" -/obj/item/weapon/circuitboard/pod - name = "Circuit board (Massdriver control)" - build_path = "/obj/machinery/computer/pod" -/obj/item/weapon/circuitboard/pod/deathsquad - name = "Circuit board (Deathsquad Massdriver control)" - build_path = "/obj/machinery/computer/pod/deathsquad" -/obj/item/weapon/circuitboard/robotics - name = "Circuit board (Robotics Control)" - build_path = "/obj/machinery/computer/robotics" - origin_tech = "programming=3" -/obj/item/weapon/circuitboard/cloning - name = "Circuit board (Cloning Console)" - build_path = "/obj/machinery/computer/cloning" - origin_tech = "programming=3;biotech=3" -/obj/item/weapon/circuitboard/arcade - name = "Circuit board (Arcade)" - build_path = "/obj/machinery/computer/arcade" - origin_tech = "programming=1" - var/list/game_data = list() -/obj/item/weapon/circuitboard/turbine_control - name = "Circuit board (Turbine control)" - build_path = "/obj/machinery/computer/turbine_computer" -/obj/item/weapon/circuitboard/solar_control - name = "Circuit board (Solar Control)" //name fixed 250810 - build_path = "/obj/machinery/power/solar/control" - origin_tech = "programming=2;powerstorage=2" -/obj/item/weapon/circuitboard/powermonitor - name = "Circuit board (Power Monitor)" //name fixed 250810 - build_path = "/obj/machinery/power/monitor" -/obj/item/weapon/circuitboard/olddoor - name = "Circuit board (DoorMex)" - build_path = "/obj/machinery/computer/pod/old" -/obj/item/weapon/circuitboard/syndicatedoor - name = "Circuit board (ProComp Executive)" - build_path = "/obj/machinery/computer/pod/old/syndicate" -/obj/item/weapon/circuitboard/swfdoor - name = "Circuit board (Magix)" - build_path = "/obj/machinery/computer/pod/old/swf" -/obj/item/weapon/circuitboard/prisoner - name = "Circuit board (Prisoner Management)" - build_path = "/obj/machinery/computer/prisoner" - -/obj/item/weapon/circuitboard/rdconsole - name = "Circuit Board (R&D Console)" - build_path = "/obj/machinery/computer/rdconsole/core" -/obj/item/weapon/circuitboard/rdconsole/mommi - name = "Circuit Board (MoMMI R&D Console)" - build_path = "/obj/machinery/computer/rdconsole/mommi" -/obj/item/weapon/circuitboard/rdconsole/robotics - name = "Circuit Board (Robotics R&D Console)" - build_path = "/obj/machinery/computer/rdconsole/robotics" -/obj/item/weapon/circuitboard/rdconsole/mechanic - name = "Circuit Board (Mechanic R&D Console)" - build_path = "/obj/machinery/computer/rdconsole/mechanic" -/obj/item/weapon/circuitboard/rdconsole/pod - name = "Circuit Board (Pod Bay R&D Console)" - build_path = "/obj/machinery/computer/rdconsole/pod" - -/obj/item/weapon/circuitboard/mecha_control - name = "Circuit Board (Exosuit Control Console)" - build_path = "/obj/machinery/computer/mecha" -/obj/item/weapon/circuitboard/rdservercontrol - name = "Circuit Board (R&D Server Control)" - build_path = "/obj/machinery/computer/rdservercontrol" -/obj/item/weapon/circuitboard/crew - name = "Circuit board (Crew monitoring computer)" - build_path = "/obj/machinery/computer/crew" - origin_tech = "programming=3;biotech=2;magnets=2" -/obj/item/weapon/circuitboard/mech_bay_power_console - name = "Circuit board (Mech Bay Power Control Console)" - build_path = "/obj/machinery/computer/mech_bay_power_console" - origin_tech = "programming=2;powerstorage=3" -/obj/item/weapon/circuitboard/ordercomp - name = "Circuit board (Supply ordering console)" - build_path = "/obj/machinery/computer/ordercomp" - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/supplycomp - name = "Circuit board (Supply shuttle console)" - build_path = "/obj/machinery/computer/supplycomp" - origin_tech = "programming=3" - var/contraband_enabled = 0 -/obj/item/weapon/circuitboard/operating - name = "Circuit board (Operating Computer)" - build_path = "/obj/machinery/computer/operating" - origin_tech = "programming=2;biotech=2" -/obj/item/weapon/circuitboard/mining - name = "Circuit board (Outpost Status Display)" - build_path = "/obj/machinery/computer/security/mining" - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/comm_monitor - name = "Circuit board (Telecommunications Monitor)" - build_path = "/obj/machinery/computer/telecomms/monitor" - origin_tech = "programming=3" -/obj/item/weapon/circuitboard/comm_server - name = "Circuit board (Telecommunications Server Monitor)" - build_path = "/obj/machinery/computer/telecomms/server" - origin_tech = "programming=3" -/obj/item/weapon/circuitboard/comm_traffic - name = "Circuitboard (Telecommunications Traffic Control)" - build_path = "/obj/machinery/computer/telecomms/traffic" - origin_tech = "programming=3" - -/obj/item/weapon/circuitboard/curefab - name = "Circuit board (Cure fab)" - build_path = "/obj/machinery/computer/curer" -/obj/item/weapon/circuitboard/splicer - name = "Circuit board (Disease Splicer)" - build_path = "/obj/machinery/computer/diseasesplicer" - origin_tech = "programming=3;biotech=4" - -/obj/item/weapon/circuitboard/shuttle_control - name = "Circuit board (Shuttle Control)" - build_path = "/obj/machinery/computer/shuttle_control" - origin_tech = "programming=3;engineering=2" - -/obj/item/weapon/circuitboard/HolodeckControl // Not going to let people get this, but it's just here for future - name = "Circuit board (Holodeck Control)" - build_path = "/obj/machinery/computer/HolodeckControl" - origin_tech = "programming=4" -/obj/item/weapon/circuitboard/aifixer - name = "Circuit board (AI Integrity Restorer)" - build_path = "/obj/machinery/computer/aifixer" - origin_tech = "programming=3;biotech=2" -/obj/item/weapon/circuitboard/area_atmos - name = "Circuit board (Area Air Control)" - build_path = "/obj/machinery/computer/area_atmos" - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/prison_shuttle - name = "Circuit board (Prison Shuttle)" - build_path = "/obj/machinery/computer/prison_shuttle" - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/bhangmeter - name = "Circuit board (Bhangmeter)" - build_path = "/obj/machinery/computer/bhangmeter" - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/telesci_computer - name = "Circuit board (Telepad Control Console)" - build_path = "/obj/machinery/computer/telescience" - origin_tech = "programming=3;bluespace=2" -/obj/item/weapon/circuitboard/forensic_computer - name = "Circuit board (Forensics Console)" - build_path = "/obj/machinery/computer/forensic_scanning" - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/pda_terminal - name = "Circuit board (PDA Terminal)" - build_path = "/obj/machinery/computer/pda_terminal" - origin_tech = "programming=2" - -/obj/item/weapon/circuitboard/smeltcomp - name = "Circuit board (Ore Processing Console)" - build_path = "/obj/machinery/computer/smelting" - origin_tech = "programming=2;materials=2" - -/obj/item/weapon/circuitboard/stacking_machine_console - name = "Circuit board (Stacking Machine Console)" - build_path = "/obj/machinery/computer/stacking_unit" - origin_tech = "programming=2;materials=2" - -/obj/item/weapon/circuitboard/attackby(obj/item/I as obj, mob/user as mob) - if(issolder(I)) - var/obj/item/weapon/solder/S = I - if(S.remove_fuel(2,user)) - solder_improve(user) - else if(iswelder(I)) - var/obj/item/weapon/weldingtool/WT = I - if(WT.remove_fuel(1,user)) - var/obj/item/weapon/circuitboard/blank/B = new /obj/item/weapon/circuitboard/blank(src.loc) - to_chat(user, "You melt away the circuitry, leaving behind a blank.") - playsound(B.loc, 'sound/items/Welder.ogg', 30, 1) - if(user.get_inactive_hand() == src) - user.before_take_item(src) - user.put_in_hands(B) - qdel(src) - return - return - -/obj/item/weapon/circuitboard/proc/solder_improve(mob/user as mob) - to_chat(user, "You fiddle with a few random fuses but can't find a routing that doesn't short the board.") - return - -/obj/item/weapon/circuitboard/supplycomp/solder_improve(mob/user as mob) - to_chat(user, "You [contraband_enabled ? "" : "un"]connect the mysterious fuse.") - contraband_enabled = !contraband_enabled - return - -/obj/item/weapon/circuitboard/security/solder_improve(mob/user as mob) - if(istype(src,/obj/item/weapon/circuitboard/security/advanced)) - return ..() - if(istype(src,/obj/item/weapon/circuitboard/security/engineering)) - return ..() - else - to_chat(user, "You locate a short that makes the feed circuitry more elegant.") - var/obj/item/weapon/circuitboard/security/advanced/A = new /obj/item/weapon/circuitboard/security/advanced(src.loc) - user.put_in_hands(A) - qdel(src) - return - -/obj/structure/computerframe/attackby(obj/item/P as obj, mob/user as mob) - switch(state) - if(0) - if(istype(P, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 5) && state == 0) - to_chat(user, "You wrench the frame into place.") - src.anchored = 1 - src.state = 1 - return 1 - if(istype(P, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = P - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - if(do_after(user, src, 10) && state == 0) - if(!src || !WT.isOn()) return - to_chat(user, "You deconstruct the frame.") - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, src.loc) - M.amount = 5 - state = -1 - qdel(src) - return 1 - if(1) - if(istype(P, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 20) && state == 1) - to_chat(user, "You unfasten the frame.") - src.anchored = 0 - src.state = 0 - return 1 - if(istype(P, /obj/item/weapon/circuitboard) && !circuit) - var/obj/item/weapon/circuitboard/B = P - if(B.board_type == "computer") - if(!user.drop_item(B, src)) return - - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You place the circuit board inside the frame.") - src.icon_state = "1" - src.circuit = P - else - to_chat(user, "This frame does not accept circuit boards of this type!") - return 1 - if(istype(P, /obj/item/weapon/screwdriver) && circuit) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You screw the circuit board into place.") - src.state = 2 - src.icon_state = "2" - return 1 - if(istype(P, /obj/item/weapon/crowbar) && circuit) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - to_chat(user, "You remove the circuit board.") - src.state = 1 - src.icon_state = "0" - circuit.loc = src.loc - src.circuit = null - return 1 - if(2) - if(istype(P, /obj/item/weapon/screwdriver) && circuit) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You unfasten the circuit board.") - src.state = 1 - src.icon_state = "1" - return 1 - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = P - if (C.amount < 5) - to_chat(user, "You need at least 5 lengths of cable coil for this!") - return 1 - - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if (do_after(user, src, 20) && state == 2 && C.amount >= 5) - C.use(5) - to_chat(user, "You add cables to the frame.") - src.state = 3 - src.icon_state = "3" - - return 1 - if(3) - if(istype(P, /obj/item/weapon/wirecutters)) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - to_chat(user, "You remove the cables.") - src.state = 2 - src.icon_state = "2" - getFromPool(/obj/item/stack/cable_coil, get_turf(src), 5) - return 1 - - if(istype(P, /obj/item/stack/sheet/glass/glass)) - var/obj/item/stack/sheet/glass/glass/G = P - if (G.amount < 2) - to_chat(user, "You need at least 2 sheets of glass for this!") - return 1 - - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20) && state == 3 && G.amount >= 2) - G.use(2) - to_chat(user, "You put in the glass panel.") - src.state = 4 - src.icon_state = "4" - - return 1 - if(4) - if(istype(P, /obj/item/weapon/crowbar)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - to_chat(user, "You remove the glass panel.") - src.state = 3 - src.icon_state = "3" - new /obj/item/stack/sheet/glass/glass( src.loc, 2 ) - return 1 - if(istype(P, /obj/item/weapon/screwdriver)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You connect the monitor.") - var/B = new src.circuit.build_path ( src.loc ) - if(circuit.powernet) B:powernet = circuit.powernet - if(circuit.id_tag) B:id_tag = circuit.id_tag - if(circuit.records) B:records = circuit.records - if(circuit.frequency) B:frequency = circuit.frequency - if(istype(circuit,/obj/item/weapon/circuitboard/supplycomp)) - var/obj/machinery/computer/supplycomp/SC = B - var/obj/item/weapon/circuitboard/supplycomp/C = circuit - SC.can_order_contraband = C.contraband_enabled - else if(istype(circuit,/obj/item/weapon/circuitboard/arcade)) - var/obj/machinery/computer/arcade/arcade = B - var/obj/item/weapon/circuitboard/arcade/C = circuit - arcade.import_game_data(C) - qdel(src) - return 1 - return 0 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/structure/computerframe + density = 1 + anchored = 0 + name = "Computer Frame" + icon = 'icons/obj/stock_parts.dmi' + icon_state = "0" + var/state = 0 + var/obj/item/weapon/circuitboard/circuit = null +// weight = 1.0E8 + +/obj/structure/computerframe/Destroy() + ..() + qdel(circuit) + circuit = null + +/obj/item/weapon/circuitboard + density = 0 + anchored = 0 + w_class = 2.0 + name = "Circuit board" + icon = 'icons/obj/module.dmi' + icon_state = "id_mod" + item_state = "circuitboard" + origin_tech = "programming=2" + starting_materials = list(MAT_GLASS = 2000) // Recycle glass only + w_type = RECYK_ELECTRONIC + + var/id_tag = null + var/frequency = null + var/build_path = null + var/board_type = "computer" + var/list/req_components = null + var/powernet = null + var/list/records = null + var/frame_desc = null + var/contain_parts = 1 + +/obj/item/weapon/circuitboard/message_monitor + name = "Circuit board (Message Monitor)" + build_path = "/obj/machinery/computer/message_monitor" + origin_tech = "programming=3" +/obj/item/weapon/circuitboard/security + name = "Circuit board (Security)" + build_path = "/obj/machinery/computer/security" +/obj/item/weapon/circuitboard/security/engineering + name = "Circuit board (Engineering)" + build_path = "/obj/machinery/computer/security/engineering" +/obj/item/weapon/circuitboard/aicore + name = "Circuit board (AI core)" + origin_tech = "programming=4;biotech=2" + board_type = "other" +/obj/item/weapon/circuitboard/aiupload + name = "Circuit board (AI Upload)" + build_path = "/obj/machinery/computer/aiupload" + origin_tech = "programming=4" +/obj/item/weapon/circuitboard/borgupload + name = "Circuit board (Cyborg Upload)" + build_path = "/obj/machinery/computer/borgupload" + origin_tech = "programming=4" +/obj/item/weapon/circuitboard/med_data + name = "Circuit board (Medical Records)" + build_path = "/obj/machinery/computer/med_data" +/obj/item/weapon/circuitboard/pandemic + name = "Circuit board (PanD.E.M.I.C. 2200)" + build_path = "/obj/machinery/computer/pandemic" + origin_tech = "programming=2;biotech=2" +/obj/item/weapon/circuitboard/scan_consolenew + name = "Circuit board (DNA Machine)" + build_path = "/obj/machinery/computer/scan_consolenew" + origin_tech = "programming=2;biotech=2" +/obj/item/weapon/circuitboard/communications + name = "Circuit board (Communications)" + build_path = "/obj/machinery/computer/communications" + origin_tech = "programming=2;magnets=2" +/obj/item/weapon/circuitboard/card + name = "Circuit board (ID Computer)" + build_path = "/obj/machinery/computer/card" +/obj/item/weapon/circuitboard/card/centcom + name = "Circuit board (CentCom ID Computer)" + build_path = "/obj/machinery/computer/card/centcom" +//obj/item/weapon/circuitboard/shield +// name = "Circuit board (Shield Control)" +// build_path = "/obj/machinery/computer/stationshield" +/obj/item/weapon/circuitboard/teleporter + name = "Circuit board (Teleporter)" + build_path = "/obj/machinery/computer/teleporter" + origin_tech = "programming=2;bluespace=2" +/obj/item/weapon/circuitboard/secure_data + name = "Circuit board (Security Records)" + build_path = "/obj/machinery/computer/secure_data" +/obj/item/weapon/circuitboard/stationalert + name = "Circuit board (Station Alerts)" + build_path = "/obj/machinery/computer/station_alert" +/obj/item/weapon/circuitboard/atmospheresiphonswitch + name = "Circuit board (Atmosphere siphon control)" + build_path = "/obj/machinery/computer/atmosphere/siphonswitch" +/obj/item/weapon/circuitboard/air_management + name = "Circuit board (Atmospheric General Monitor)" + build_path = "/obj/machinery/computer/general_air_control" +/obj/item/weapon/circuitboard/atmos_automation + name = "Circuit board (Atmospherics Automation)" + build_path = "/obj/machinery/computer/general_air_control/atmos_automation" +/obj/item/weapon/circuitboard/large_tank_control + name = "Circuit board (Atmospheric Tank Control)" + build_path = "/obj/machinery/computer/general_air_control/large_tank_control" +/obj/item/weapon/circuitboard/injector_control + name = "Circuit board (Injector control)" + build_path = "/obj/machinery/computer/general_air_control/fuel_injection" +/obj/item/weapon/circuitboard/atmos_alert + name = "Circuit board (Atmospheric Alert)" + build_path = "/obj/machinery/computer/atmos_alert" +/obj/item/weapon/circuitboard/pod + name = "Circuit board (Massdriver control)" + build_path = "/obj/machinery/computer/pod" +/obj/item/weapon/circuitboard/pod/deathsquad + name = "Circuit board (Deathsquad Massdriver control)" + build_path = "/obj/machinery/computer/pod/deathsquad" +/obj/item/weapon/circuitboard/robotics + name = "Circuit board (Robotics Control)" + build_path = "/obj/machinery/computer/robotics" + origin_tech = "programming=3" +/obj/item/weapon/circuitboard/cloning + name = "Circuit board (Cloning Console)" + build_path = "/obj/machinery/computer/cloning" + origin_tech = "programming=3;biotech=3" +/obj/item/weapon/circuitboard/arcade + name = "Circuit board (Arcade)" + build_path = "/obj/machinery/computer/arcade" + origin_tech = "programming=1" + var/list/game_data = list() +/obj/item/weapon/circuitboard/turbine_control + name = "Circuit board (Turbine control)" + build_path = "/obj/machinery/computer/turbine_computer" +/obj/item/weapon/circuitboard/solar_control + name = "Circuit board (Solar Control)" //name fixed 250810 + build_path = "/obj/machinery/power/solar/control" + origin_tech = "programming=2;powerstorage=2" +/obj/item/weapon/circuitboard/powermonitor + name = "Circuit board (Power Monitor)" //name fixed 250810 + build_path = "/obj/machinery/power/monitor" +/obj/item/weapon/circuitboard/olddoor + name = "Circuit board (DoorMex)" + build_path = "/obj/machinery/computer/pod/old" +/obj/item/weapon/circuitboard/syndicatedoor + name = "Circuit board (ProComp Executive)" + build_path = "/obj/machinery/computer/pod/old/syndicate" +/obj/item/weapon/circuitboard/swfdoor + name = "Circuit board (Magix)" + build_path = "/obj/machinery/computer/pod/old/swf" +/obj/item/weapon/circuitboard/prisoner + name = "Circuit board (Prisoner Management)" + build_path = "/obj/machinery/computer/prisoner" + +/obj/item/weapon/circuitboard/rdconsole + name = "Circuit Board (R&D Console)" + build_path = "/obj/machinery/computer/rdconsole/core" +/obj/item/weapon/circuitboard/rdconsole/mommi + name = "Circuit Board (MoMMI R&D Console)" + build_path = "/obj/machinery/computer/rdconsole/mommi" +/obj/item/weapon/circuitboard/rdconsole/robotics + name = "Circuit Board (Robotics R&D Console)" + build_path = "/obj/machinery/computer/rdconsole/robotics" +/obj/item/weapon/circuitboard/rdconsole/mechanic + name = "Circuit Board (Mechanic R&D Console)" + build_path = "/obj/machinery/computer/rdconsole/mechanic" +/obj/item/weapon/circuitboard/rdconsole/pod + name = "Circuit Board (Pod Bay R&D Console)" + build_path = "/obj/machinery/computer/rdconsole/pod" + +/obj/item/weapon/circuitboard/mecha_control + name = "Circuit Board (Exosuit Control Console)" + build_path = "/obj/machinery/computer/mecha" +/obj/item/weapon/circuitboard/rdservercontrol + name = "Circuit Board (R&D Server Control)" + build_path = "/obj/machinery/computer/rdservercontrol" +/obj/item/weapon/circuitboard/crew + name = "Circuit board (Crew monitoring computer)" + build_path = "/obj/machinery/computer/crew" + origin_tech = "programming=3;biotech=2;magnets=2" +/obj/item/weapon/circuitboard/mech_bay_power_console + name = "Circuit board (Mech Bay Power Control Console)" + build_path = "/obj/machinery/computer/mech_bay_power_console" + origin_tech = "programming=2;powerstorage=3" +/obj/item/weapon/circuitboard/ordercomp + name = "Circuit board (Supply ordering console)" + build_path = "/obj/machinery/computer/ordercomp" + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/supplycomp + name = "Circuit board (Supply shuttle console)" + build_path = "/obj/machinery/computer/supplycomp" + origin_tech = "programming=3" + var/contraband_enabled = 0 +/obj/item/weapon/circuitboard/operating + name = "Circuit board (Operating Computer)" + build_path = "/obj/machinery/computer/operating" + origin_tech = "programming=2;biotech=2" +/obj/item/weapon/circuitboard/mining + name = "Circuit board (Outpost Status Display)" + build_path = "/obj/machinery/computer/security/mining" + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/comm_monitor + name = "Circuit board (Telecommunications Monitor)" + build_path = "/obj/machinery/computer/telecomms/monitor" + origin_tech = "programming=3" +/obj/item/weapon/circuitboard/comm_server + name = "Circuit board (Telecommunications Server Monitor)" + build_path = "/obj/machinery/computer/telecomms/server" + origin_tech = "programming=3" +/obj/item/weapon/circuitboard/comm_traffic + name = "Circuitboard (Telecommunications Traffic Control)" + build_path = "/obj/machinery/computer/telecomms/traffic" + origin_tech = "programming=3" + +/obj/item/weapon/circuitboard/curefab + name = "Circuit board (Cure fab)" + build_path = "/obj/machinery/computer/curer" +/obj/item/weapon/circuitboard/splicer + name = "Circuit board (Disease Splicer)" + build_path = "/obj/machinery/computer/diseasesplicer" + origin_tech = "programming=3;biotech=4" + +/obj/item/weapon/circuitboard/shuttle_control + name = "Circuit board (Shuttle Control)" + build_path = "/obj/machinery/computer/shuttle_control" + origin_tech = "programming=3;engineering=2" + +/obj/item/weapon/circuitboard/HolodeckControl // Not going to let people get this, but it's just here for future + name = "Circuit board (Holodeck Control)" + build_path = "/obj/machinery/computer/HolodeckControl" + origin_tech = "programming=4" +/obj/item/weapon/circuitboard/aifixer + name = "Circuit board (AI Integrity Restorer)" + build_path = "/obj/machinery/computer/aifixer" + origin_tech = "programming=3;biotech=2" +/obj/item/weapon/circuitboard/area_atmos + name = "Circuit board (Area Air Control)" + build_path = "/obj/machinery/computer/area_atmos" + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/prison_shuttle + name = "Circuit board (Prison Shuttle)" + build_path = "/obj/machinery/computer/prison_shuttle" + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/bhangmeter + name = "Circuit board (Bhangmeter)" + build_path = "/obj/machinery/computer/bhangmeter" + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/telesci_computer + name = "Circuit board (Telepad Control Console)" + build_path = "/obj/machinery/computer/telescience" + origin_tech = "programming=3;bluespace=2" +/obj/item/weapon/circuitboard/forensic_computer + name = "Circuit board (Forensics Console)" + build_path = "/obj/machinery/computer/forensic_scanning" + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/pda_terminal + name = "Circuit board (PDA Terminal)" + build_path = "/obj/machinery/computer/pda_terminal" + origin_tech = "programming=2" + +/obj/item/weapon/circuitboard/smeltcomp + name = "Circuit board (Ore Processing Console)" + build_path = "/obj/machinery/computer/smelting" + origin_tech = "programming=2;materials=2" + +/obj/item/weapon/circuitboard/stacking_machine_console + name = "Circuit board (Stacking Machine Console)" + build_path = "/obj/machinery/computer/stacking_unit" + origin_tech = "programming=2;materials=2" + +/obj/item/weapon/circuitboard/attackby(obj/item/I as obj, mob/user as mob) + if(issolder(I)) + var/obj/item/weapon/solder/S = I + if(S.remove_fuel(2,user)) + solder_improve(user) + else if(iswelder(I)) + var/obj/item/weapon/weldingtool/WT = I + if(WT.remove_fuel(1,user)) + var/obj/item/weapon/circuitboard/blank/B = new /obj/item/weapon/circuitboard/blank(src.loc) + to_chat(user, "You melt away the circuitry, leaving behind a blank.") + playsound(B.loc, 'sound/items/Welder.ogg', 30, 1) + if(user.get_inactive_hand() == src) + user.before_take_item(src) + user.put_in_hands(B) + qdel(src) + return + return + +/obj/item/weapon/circuitboard/proc/solder_improve(mob/user as mob) + to_chat(user, "You fiddle with a few random fuses but can't find a routing that doesn't short the board.") + return + +/obj/item/weapon/circuitboard/supplycomp/solder_improve(mob/user as mob) + to_chat(user, "You [contraband_enabled ? "" : "un"]connect the mysterious fuse.") + contraband_enabled = !contraband_enabled + return + +/obj/item/weapon/circuitboard/security/solder_improve(mob/user as mob) + if(istype(src,/obj/item/weapon/circuitboard/security/advanced)) + return ..() + if(istype(src,/obj/item/weapon/circuitboard/security/engineering)) + return ..() + else + to_chat(user, "You locate a short that makes the feed circuitry more elegant.") + var/obj/item/weapon/circuitboard/security/advanced/A = new /obj/item/weapon/circuitboard/security/advanced(src.loc) + user.put_in_hands(A) + qdel(src) + return + +/obj/structure/computerframe/attackby(obj/item/P as obj, mob/user as mob) + switch(state) + if(0) + if(istype(P, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 5) && state == 0) + to_chat(user, "You wrench the frame into place.") + src.anchored = 1 + src.state = 1 + return 1 + if(istype(P, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = P + if(!WT.remove_fuel(0, user)) + to_chat(user, "The welding tool must be on to complete this task.") + return 1 + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + if(do_after(user, src, 10) && state == 0) + if(!src || !WT.isOn()) return + to_chat(user, "You deconstruct the frame.") + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, src.loc) + M.amount = 5 + state = -1 + qdel(src) + return 1 + if(1) + if(istype(P, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 20) && state == 1) + to_chat(user, "You unfasten the frame.") + src.anchored = 0 + src.state = 0 + return 1 + if(istype(P, /obj/item/weapon/circuitboard) && !circuit) + var/obj/item/weapon/circuitboard/B = P + if(B.board_type == "computer") + if(!user.drop_item(B, src)) return + + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You place the circuit board inside the frame.") + src.icon_state = "1" + src.circuit = P + else + to_chat(user, "This frame does not accept circuit boards of this type!") + return 1 + if(istype(P, /obj/item/weapon/screwdriver) && circuit) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You screw the circuit board into place.") + src.state = 2 + src.icon_state = "2" + return 1 + if(istype(P, /obj/item/weapon/crowbar) && circuit) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + to_chat(user, "You remove the circuit board.") + src.state = 1 + src.icon_state = "0" + circuit.loc = src.loc + src.circuit = null + return 1 + if(2) + if(istype(P, /obj/item/weapon/screwdriver) && circuit) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You unfasten the circuit board.") + src.state = 1 + src.icon_state = "1" + return 1 + if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = P + if (C.amount < 5) + to_chat(user, "You need at least 5 lengths of cable coil for this!") + return 1 + + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if (do_after(user, src, 20) && state == 2 && C.amount >= 5) + C.use(5) + to_chat(user, "You add cables to the frame.") + src.state = 3 + src.icon_state = "3" + + return 1 + if(3) + if(istype(P, /obj/item/weapon/wirecutters)) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + to_chat(user, "You remove the cables.") + src.state = 2 + src.icon_state = "2" + getFromPool(/obj/item/stack/cable_coil, get_turf(src), 5) + return 1 + + if(istype(P, /obj/item/stack/sheet/glass/glass)) + var/obj/item/stack/sheet/glass/glass/G = P + if (G.amount < 2) + to_chat(user, "You need at least 2 sheets of glass for this!") + return 1 + + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20) && state == 3 && G.amount >= 2) + G.use(2) + to_chat(user, "You put in the glass panel.") + src.state = 4 + src.icon_state = "4" + + return 1 + if(4) + if(istype(P, /obj/item/weapon/crowbar)) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + to_chat(user, "You remove the glass panel.") + src.state = 3 + src.icon_state = "3" + new /obj/item/stack/sheet/glass/glass( src.loc, 2 ) + return 1 + if(istype(P, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You connect the monitor.") + var/B = new src.circuit.build_path ( src.loc ) + if(circuit.powernet) B:powernet = circuit.powernet + if(circuit.id_tag) B:id_tag = circuit.id_tag + if(circuit.records) B:records = circuit.records + if(circuit.frequency) B:frequency = circuit.frequency + if(istype(circuit,/obj/item/weapon/circuitboard/supplycomp)) + var/obj/machinery/computer/supplycomp/SC = B + var/obj/item/weapon/circuitboard/supplycomp/C = circuit + SC.can_order_contraband = C.contraband_enabled + else if(istype(circuit,/obj/item/weapon/circuitboard/arcade)) + var/obj/machinery/computer/arcade/arcade = B + var/obj/item/weapon/circuitboard/arcade/C = circuit + arcade.import_game_data(C) + qdel(src) + return 1 + return 0 diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1e8d00d9e47..fc93f27962a 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -1,152 +1,152 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -var/global/list/tv_monitors = list() - -/obj/machinery/computer/security - name = "Security Cameras" - desc = "Used to access the various cameras on the station." - icon_state = "cameras" - circuit = "/obj/item/weapon/circuitboard/security" - var/obj/machinery/camera/current = null - var/last_pic = 1.0 - var/list/network = list("SS13") - var/mapping = 0//For the overview file, interesting bit of code. - - light_color = LIGHT_COLOR_RED - -/obj/machinery/computer/security/New() - ..() - tv_monitors += src - -/obj/machinery/computer/security/Destroy() - tv_monitors -= src - ..() - -/obj/machinery/computer/security/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - - -/obj/machinery/computer/security/attack_paw(var/mob/user as mob) - return attack_hand(user) - - -/obj/machinery/computer/security/check_eye(var/mob/user as mob) - //To explain ( !user.canmove && !ischair(user.locked_to) ): when you're buckled, your canmove variable is 0. This is to allow using this computer from chairs and vehicles - if ((get_dist(user, src) > 1 || (!user.canmove && !ischair(user.locked_to)) || user.blinded || !( current ) || !( current.status )) && (!istype(user, /mob/living/silicon))) - return null - user.reset_view(current) - return 1 - - -/obj/machinery/computer/security/attack_hand(var/mob/user as mob) - if (src.z > 6) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +var/global/list/tv_monitors = list() + +/obj/machinery/computer/security + name = "Security Cameras" + desc = "Used to access the various cameras on the station." + icon_state = "cameras" + circuit = "/obj/item/weapon/circuitboard/security" + var/obj/machinery/camera/current = null + var/last_pic = 1.0 + var/list/network = list("SS13") + var/mapping = 0//For the overview file, interesting bit of code. + + light_color = LIGHT_COLOR_RED + +/obj/machinery/computer/security/New() + ..() + tv_monitors += src + +/obj/machinery/computer/security/Destroy() + tv_monitors -= src + ..() + +/obj/machinery/computer/security/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + + +/obj/machinery/computer/security/attack_paw(var/mob/user as mob) + return attack_hand(user) + + +/obj/machinery/computer/security/check_eye(var/mob/user as mob) + //To explain ( !user.canmove && !ischair(user.locked_to) ): when you're buckled, your canmove variable is 0. This is to allow using this computer from chairs and vehicles + if ((get_dist(user, src) > 1 || (!user.canmove && !ischair(user.locked_to)) || user.blinded || !( current ) || !( current.status )) && (!istype(user, /mob/living/silicon))) + return null + user.reset_view(current) + return 1 + + +/obj/machinery/computer/security/attack_hand(var/mob/user as mob) + if (src.z > 6) to_chat(user, "Unable to establish a connection: You're too far away from the station!") - return - if(stat & (NOPOWER|BROKEN)) return - - if(!isAI(user)) - user.set_machine(src) - - var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.cameras) - L.Add(C) - - camera_sort(L) - - var/list/D = list() - D["Cancel"] = "Cancel" - for(var/obj/machinery/camera/C in L) - if(!istype(C.network, /list)) - var/turf/T = get_turf(C) - WARNING("[C] - Camera at ([T.x],[T.y],[T.z]) has a non list for network, [C.network]") - C.network = list(C.network) - var/list/tempnetwork = C.network & network - if(tempnetwork.len) - D[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C - - var/t = input(user, "Which camera should you change to?") as null|anything in D - if(!t || t == "Cancel") - user.cancel_camera() - return 0 - user.set_machine(src) - - var/obj/machinery/camera/C = D[t] - - if(C) - if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || (!user.canmove && !ischair(user.locked_to)) || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai))) - if(!C.can_use() && !isAI(user)) - src.current = null - user.cancel_camera() - return 0 - else - if(isAI(user)) - var/mob/living/silicon/ai/A = user - A.eyeobj.forceMove(get_turf(C)) - A.client.eye = A.eyeobj - else - src.current = C - use_power(50) - - spawn(5) - attack_hand(user) - return - - - -/obj/machinery/computer/security/telescreen - name = "Telescreen" - desc = "Used for watching arena fights and variety shows." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "telescreen" - network = list("thunder") - density = 0 - circuit = null - - light_color = null - -/obj/machinery/computer/security/telescreen/examine(mob/user) - ..() + return + if(stat & (NOPOWER|BROKEN)) return + + if(!isAI(user)) + user.set_machine(src) + + var/list/L = list() + for (var/obj/machinery/camera/C in cameranet.cameras) + L.Add(C) + + camera_sort(L) + + var/list/D = list() + D["Cancel"] = "Cancel" + for(var/obj/machinery/camera/C in L) + if(!istype(C.network, /list)) + var/turf/T = get_turf(C) + WARNING("[C] - Camera at ([T.x],[T.y],[T.z]) has a non list for network, [C.network]") + C.network = list(C.network) + var/list/tempnetwork = C.network & network + if(tempnetwork.len) + D[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C + + var/t = input(user, "Which camera should you change to?") as null|anything in D + if(!t || t == "Cancel") + user.cancel_camera() + return 0 + user.set_machine(src) + + var/obj/machinery/camera/C = D[t] + + if(C) + if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || (!user.canmove && !ischair(user.locked_to)) || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai))) + if(!C.can_use() && !isAI(user)) + src.current = null + user.cancel_camera() + return 0 + else + if(isAI(user)) + var/mob/living/silicon/ai/A = user + A.eyeobj.forceMove(get_turf(C)) + A.client.eye = A.eyeobj + else + src.current = C + use_power(50) + + spawn(5) + attack_hand(user) + return + + + +/obj/machinery/computer/security/telescreen + name = "Telescreen" + desc = "Used for watching arena fights and variety shows." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "telescreen" + network = list("thunder") + density = 0 + circuit = null + + light_color = null + +/obj/machinery/computer/security/telescreen/examine(mob/user) + ..() to_chat(user, "Looks like the current channel is \"[current.c_tag]\"") - -/obj/machinery/computer/security/telescreen/update_icon() - icon_state = initial(icon_state) - if(stat & BROKEN) - icon_state += "b" - return - -/obj/machinery/computer/security/telescreen/entertainment - name = "entertainment monitor" - desc = "Damn, they better have chicken-channel on these things." - icon = 'icons/obj/status_display.dmi' - icon_state = "entertainment" - network = list("thunder") - density = 0 - circuit = null - - light_color = null - -/obj/machinery/computer/security/wooden_tv - name = "Security Cameras" - desc = "An old TV hooked into the stations camera network." - icon_state = "security_det" - - light_color = null - -/obj/machinery/computer/security/mining - name = "Outpost Cameras" - desc = "Used to access the various cameras on the outpost." - icon_state = "miningcameras" - network = list("MINE") - circuit = "/obj/item/weapon/circuitboard/mining" - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/security/engineering - name = "Engineering Cameras" - desc = "Used to monitor fires and breaches." - icon_state = "engineeringcameras" - network = list("Power Alarms","Atmosphere Alarms","Fire Alarms") - circuit = "/obj/item/weapon/circuitboard/security/engineering" - - light_color = LIGHT_COLOR_YELLOW + +/obj/machinery/computer/security/telescreen/update_icon() + icon_state = initial(icon_state) + if(stat & BROKEN) + icon_state += "b" + return + +/obj/machinery/computer/security/telescreen/entertainment + name = "entertainment monitor" + desc = "Damn, they better have chicken-channel on these things." + icon = 'icons/obj/status_display.dmi' + icon_state = "entertainment" + network = list("thunder") + density = 0 + circuit = null + + light_color = null + +/obj/machinery/computer/security/wooden_tv + name = "Security Cameras" + desc = "An old TV hooked into the stations camera network." + icon_state = "security_det" + + light_color = null + +/obj/machinery/computer/security/mining + name = "Outpost Cameras" + desc = "Used to access the various cameras on the outpost." + icon_state = "miningcameras" + network = list("MINE") + circuit = "/obj/item/weapon/circuitboard/mining" + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/security/engineering + name = "Engineering Cameras" + desc = "Used to monitor fires and breaches." + icon_state = "engineeringcameras" + network = list("Power Alarms","Atmosphere Alarms","Fire Alarms") + circuit = "/obj/item/weapon/circuitboard/security/engineering" + + light_color = LIGHT_COLOR_YELLOW diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index d9fbb072473..2b60453281b 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -1,616 +1,616 @@ - -#define COMM_SCREEN_MAIN 1 -#define COMM_SCREEN_STAT 2 -#define COMM_SCREEN_MESSAGES 3 -#define COMM_SCREEN_SECLEVEL 4 -#define COMM_SCREEN_ERT 5 - -var/shuttle_call/shuttle_calls[0] - -#define SHUTTLE_RECALL -1 -#define SHUTTLE_CALL 1 -#define SHUTTLE_TRANSFER 2 - -/shuttle_call - var/direction=0 - var/who="" - var/ckey="" - var/turf/from=null - var/where="" - var/when - var/eta=null - -/shuttle_call/New(var/mob/user,var/obj/machinery/computer/communications/computer,var/dir) - direction=dir - if(user) - who="[user]" - ckey="[user.key]" - if(computer) - where="[computer]" - from=get_turf(computer) - when=worldtime2text() - if(dir==SHUTTLE_RECALL) - var/timeleft=emergency_shuttle.timeleft() - eta="[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" - -// The communications computer -/obj/machinery/computer/communications - name = "Communications Console" - desc = "This can be used for various important functions. Still under developement." - icon_state = "comm" - req_access = list(access_heads) - circuit = "/obj/item/weapon/circuitboard/communications" - var/prints_intercept = 1 - var/authenticated = 0 - var/list/messagetitle = list() - var/list/messagetext = list() - var/currmsg = 0 - var/aicurrmsg = 0 - var/menu_state = COMM_SCREEN_MAIN - var/ai_menu_state = COMM_SCREEN_MAIN - var/message_cooldown = 0 - var/centcomm_message_cooldown = 0 - var/tmp_alertlevel = 0 - - var/status_display_freq = "1435" - var/stat_msg1 - var/stat_msg2 - var/display_type="blank" - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/communications/Topic(href, href_list) - if(..(href, href_list)) - return - - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - - if (!(src.z in list(STATION_Z,CENTCOMM_Z))) - to_chat(usr, "Unable to establish a connection: You're too far away from the station!") - return - - usr.set_machine(src) - - if(!href_list["operation"]) - return - switch(href_list["operation"]) - // main interface - if("main") - setMenuState(usr,COMM_SCREEN_MAIN) - if("login") - var/mob/M = usr - var/obj/item/weapon/card/id/I = M.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (istype(I,/obj/item/weapon/card/emag)) - emag(usr) - if (I && istype(I)) - if(src.check_access(I)) - authenticated = 1 - if(20 in I.access) - authenticated = 2 - if("logout") - authenticated = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - // ALART LAVUL - if("changeseclevel") - setMenuState(usr,COMM_SCREEN_SECLEVEL) - - if("newalertlevel") - if(issilicon(usr)) - return - tmp_alertlevel = text2num(href_list["level"]) - var/mob/M = usr - var/obj/item/weapon/card/id/I = M.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (I && istype(I)) - if(access_captain in I.access || access_heads in I.access) //Let heads change the alert level. - var/old_level = security_level - if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this - set_security_level(tmp_alertlevel) - if(security_level != old_level) - //Only notify the admins if an actual change happened - log_game("[key_name(usr)] has changed the security level to [get_security_level()].") - message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].") - switch(security_level) - if(SEC_LEVEL_GREEN) - feedback_inc("alert_comms_green",1) - if(SEC_LEVEL_BLUE) - feedback_inc("alert_comms_blue",1) - tmp_alertlevel = 0 - else: - to_chat(usr, "You are not authorized to do this.") - tmp_alertlevel = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - else - to_chat(usr, "You need to swipe your ID.") - - if("announce") - if(src.authenticated==2 && !issilicon(usr)) - if(message_cooldown) return - var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?") - if(!input || !(usr in view(1,src))) - return - captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain - var/turf/T = get_turf(usr) - log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has made a captain announcement: [input]") - message_admins("[key_name_admin(usr)] has made a captain announcement.", 1) - message_cooldown = 1 - spawn(600)//One minute cooldown - message_cooldown = 0 - - if("emergency_screen") - var/mob/M = usr - var/obj/item/weapon/card/id/I = M.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (I && istype(I)) - if(access_captain in I.access) - authenticated = 2 - if(authenticated != 2) - to_chat(usr, "You do not have clearance to use this function.") - return - setMenuState(usr,COMM_SCREEN_ERT) - return - if("request_emergency_team") - if(menu_state != COMM_SCREEN_ERT) return //Not on the right screen. - if ((!(ticker) || emergency_shuttle.location)) - to_chat(usr, "Warning: The evac shuttle has already arrived.") - return - - if(!universe.OnShuttleCall(usr)) - to_chat(usr, "\The [src.name] cannot establish a bluespace connection.") - return - - if(sent_strike_team) - to_chat(usr, "PKI AUTH ERROR: SERVER REPORTS BLACKLISTED COMMUNICATION KEY PLEASE CONTACT SERVICE TECHNICIAN") - return - - if(world.time < 6000) - to_chat(usr, "The emergency response team is away on another mission, Please wait another [round((6000-world.time)/600)] minute\s before trying again.") - return - if(emergency_shuttle.online) - to_chat(usr, "The emergency shuttle is already on its way.") - return - if(!(get_security_level() in list("red", "delta"))) - to_chat(usr, "The station must be in an emergency to request a Response Team.") - return - if(authenticated != 2 || issilicon(usr)) - to_chat(usr, "\The [src.name]'s screen flashes, \"Access Denied\".") - return - if(send_emergency_team) - to_chat(usr, "Central Command has already dispatched a Response Team to [station_name()]") - return - - var/response = alert(usr,"Are you sure you want to request a response team?", "ERT Request", "Yes", "No") - if(response != "Yes") - return - trigger_armed_response_team(1) - setMenuState(usr,COMM_SCREEN_MAIN) - return - - if("callshuttle") - if(src.authenticated) - var/response = alert("Are you sure you wish to call the shuttle?", "Confirm", "Yes", "No") - if(response == "Yes") - var/justification = stripped_input(usr, "Please input a concise justification for the shuttle call. Note that failure to properly justify a shuttle call may lead to recall or termination", "Nanotrasen Anti-Comdom Systems") - if(!justification || !(usr in view(1,src))) - return - call_shuttle_proc(usr, justification) - if(emergency_shuttle.online) - post_status("shuttle") - setMenuState(usr,COMM_SCREEN_MAIN) - if("cancelshuttle") - if(issilicon(usr)) return - if(src.authenticated) - var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No") - if(response == "Yes") - recall_shuttle(usr) - if(emergency_shuttle.online) - post_status("shuttle") - setMenuState(usr,COMM_SCREEN_MAIN) - if("messagelist") - src.currmsg = 0 - if(href_list["msgid"]) - setCurrentMessage(usr, text2num(href_list["msgid"])) - setMenuState(usr,COMM_SCREEN_MESSAGES) - if("delmessage") - if(href_list["msgid"]) - src.currmsg = text2num(href_list["msgid"]) - var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No") - if(response == "Yes") - if(src.currmsg) - var/id = getCurrentMessage() - var/title = src.messagetitle[id] - var/text = src.messagetext[id] - src.messagetitle.Remove(title) - src.messagetext.Remove(text) - if(currmsg==id) currmsg=0 - if(aicurrmsg==id) aicurrmsg=0 - setMenuState(usr,COMM_SCREEN_MESSAGES) - - if("status") - setMenuState(usr,COMM_SCREEN_STAT) - - // Status display stuff - if("setstat") - display_type=href_list["statdisp"] - switch(display_type) - if("message") - post_status("message", stat_msg1, stat_msg2) - if("alert") - post_status("alert", href_list["alert"]) - display_type = href_list["alert"] - else - post_status(href_list["statdisp"]) - setMenuState(usr,COMM_SCREEN_STAT) - - if("setmsg1") - stat_msg1 = reject_bad_text(trim(copytext(sanitize(input("Line 1", "Enter Message Text", stat_msg1) as text|null), 1, 40)), 40) - setMenuState(usr,COMM_SCREEN_STAT) - if("setmsg2") - stat_msg2 = reject_bad_text(trim(copytext(sanitize(input("Line 2", "Enter Message Text", stat_msg2) as text|null), 1, 40)), 40) - setMenuState(usr,COMM_SCREEN_STAT) - - // OMG CENTCOMM LETTERHEAD - if("MessageCentcomm") - if(src.authenticated==2) - if(centcomm_message_cooldown) - to_chat(usr, "Arrays recycling. Please stand by for a few seconds.") - return - var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") - if(!input || !(usr in view(1,src))) - return - Centcomm_announce(input, usr) - to_chat(usr, "Message transmitted.") - var/turf/T = get_turf(usr) - log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has sent a bluespace message to Centcomm: [input]") - centcomm_message_cooldown = 1 - spawn(300)//30 seconds cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - - - // OMG SYNDICATE ...LETTERHEAD - if("MessageSyndicate") - if((src.authenticated==2) && (src.emagged)) - if(centcomm_message_cooldown) - to_chat(usr, "Arrays recycling. Please stand by for a few seconds.") - return - var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") - if(!input || !(usr in view(1,src))) - return - Syndicate_announce(input, usr) - to_chat(usr, "Message transmitted.") - var/turf/T = get_turf(usr) - log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has sent a bluespace message to the syndicate: [input]") - centcomm_message_cooldown = 1 - spawn(300)//30 seconds cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - - if("RestoreBackup") - to_chat(usr, "Backup routing data restored!") - src.emagged = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - update_icon() - - return 1 - -/obj/machinery/computer/communications/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/communications/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - - -/obj/machinery/computer/communications/attack_hand(var/mob/user as mob) - if(..(user)) - return - - if (!(src.z in list(STATION_Z, CENTCOMM_Z))) - to_chat(user, "Unable to establish a connection: You're too far away from the station!") - return - - ui_interact(user) - - - -/obj/machinery/computer/communications/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - if(user.stat) - return - - // this is the data which will be sent to the ui - var/data[0] - data["is_ai"] = issilicon(user) - data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state - data["emagged"] = emagged - data["authenticated"] = authenticated - data["screen"] = getMenuState(usr) - - data["stat_display"] = list( - "type"=display_type, - "line_1"=(stat_msg1 ? stat_msg1 : "-----"), - "line_2"=(stat_msg2 ? stat_msg2 : "-----"), - "presets"=list( - list("name"="blank", "label"="Clear", "desc"="Blank slate"), - list("name"="shuttle", "label"="Shuttle ETA", "desc"="Display how much time is left."), - list("name"="message", "label"="Message", "desc"="A custom message.") - ), - "alerts"=list( - list("alert"="default", "label"="NanoTrasen", "desc"="Oh god."), - list("alert"="redalert", "label"="Red Alert", "desc"="Nothing to do with communists."), - list("alert"="lockdown", "label"="Lockdown", "desc"="Let everyone know they're on lockdown."), - list("alert"="biohazard", "label"="Biohazard", "desc"="Great for virus outbreaks and parties."), - ) - ) - data["security_level"] = security_level - data["str_security_level"] = get_security_level() - data["levels"] = list( - list("id"=SEC_LEVEL_GREEN, "name"="Green"), - list("id"=SEC_LEVEL_BLUE, "name"="Blue"), - //SEC_LEVEL_RED = list("name"="Red"), - ) - data["ert_sent"] = send_emergency_team - - var/msg_data[0] - for(var/i=1;i<=src.messagetext.len;i++) - var/cur_msg[0] - cur_msg["title"]=messagetitle[i] - cur_msg["body"]=messagetext[i] - cur_msg["id"] = i - msg_data += list(cur_msg) - data["messages"] = msg_data - data["current_message"] = data["is_ai"] ? aicurrmsg : currmsg - - var/shuttle[0] - shuttle["on"]=emergency_shuttle.online - if (emergency_shuttle.online && emergency_shuttle.location==0) - var/timeleft=emergency_shuttle.timeleft() - shuttle["eta"]="[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" - shuttle["pos"] = emergency_shuttle.location - shuttle["can_recall"]=!(recall_time_limit && world.time >= recall_time_limit) - - data["shuttle"]=shuttle - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "comm_console.tmpl", "Communications Console", 400, 500) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -/obj/machinery/computer/communications/emag(mob/user as mob) - if(!emagged) - emagged = 1 - to_chat(user, "Syndicate routing data uploaded!") - new/obj/effect/effect/sparks(get_turf(src)) - playsound(loc,"sparks",50,1) - authenticated = 2 - setMenuState(usr,COMM_SCREEN_MAIN) - update_icon() - return 1 - return - - -/obj/machinery/computer/communications/update_icon() - ..() - var/initial_icon = initial(icon_state) - icon_state = "[emagged ? "[initial_icon]-emag" : "[initial_icon]"]" - if(stat & BROKEN) - icon_state = "[initial_icon]b" - else if(stat & NOPOWER) - icon_state = "[initial_icon]0" - - -/obj/machinery/computer/communications/proc/setCurrentMessage(var/mob/user,var/value) - if(issilicon(user)) - aicurrmsg=value - else - currmsg=value - -/obj/machinery/computer/communications/proc/getCurrentMessage(var/mob/user) - if(issilicon(user)) - return aicurrmsg - else - return currmsg - -/obj/machinery/computer/communications/proc/setMenuState(var/mob/user,var/value) - if(issilicon(user)) - ai_menu_state=value - else - menu_state=value - -/obj/machinery/computer/communications/proc/getMenuState(var/mob/user) - if(issilicon(user)) - return ai_menu_state - else - return menu_state - -/proc/enable_prison_shuttle(var/mob/user) - for(var/obj/machinery/computer/prison_shuttle/PS in machines) - PS.allowedtocall = !(PS.allowedtocall) - -/proc/call_shuttle_proc(var/mob/user, var/justification) - if ((!(ticker) || emergency_shuttle.location)) - return - - if(!universe.OnShuttleCall(user)) - return - - if(sent_strike_team == 1) - to_chat(user, "Centcom will not allow the shuttle to be called. Consider all contracts terminated.") - return - - if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE - to_chat(user, "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minute\s before trying again.") - return - - if(emergency_shuttle.direction == -1) - to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") - return - - if(emergency_shuttle.online) - to_chat(user, "The emergency shuttle is already on its way.") - return - - if(ticker.mode.name == "blob") - to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.") - return - - emergency_shuttle.incall() - if(!justification) - justification = "#??!7E/_1$*/ARR-CON²FAIL!!*$^?" //Can happen for reasons, let's deal with it IC - log_game("[key_name(user)] has called the shuttle. Justification given : '[justification]'") - message_admins("[key_name_admin(user)] has called the shuttle. Justification given : '[justification]'. You are encouraged to act if that justification is shit", 1) - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes. Justification : '[justification]'") - to_chat(world, sound('sound/AI/shuttlecalled.ogg')) - - return - -/proc/init_shift_change(var/mob/user, var/force = 0) - if ((!( ticker ) || emergency_shuttle.location)) - return - - if(emergency_shuttle.direction == -1) - to_chat(user, "The shuttle may not be called while returning to CentCom.") - return - - if(emergency_shuttle.online) - to_chat(user, "The shuttle is already on its way.") - return - - // if force is 0, some things may stop the shuttle call - if(!force) - if(!universe.OnShuttleCall(user)) - return - - if(emergency_shuttle.deny_shuttle) - to_chat(user, "Centcom does not currently have a shuttle available in your sector. Please try again later.") - return - - if(sent_strike_team == 1) - to_chat(user, "Centcom will not allow the shuttle to be called. Consider all contracts terminated.") - return - - if(world.time < 54000) // 30 minute grace period to let the game get going - to_chat(user, "The shuttle is refueling. Please wait another [round((54000-world.time)/600)] minutes before trying again.")//may need to change "/600" - return - - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "sandbox") - //New version pretends to call the shuttle but cause the shuttle to return after a random duration. - emergency_shuttle.fake_recall = rand(300,500) - - if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic") +#define COMM_SCREEN_MAIN 1 +#define COMM_SCREEN_STAT 2 +#define COMM_SCREEN_MESSAGES 3 +#define COMM_SCREEN_SECLEVEL 4 +#define COMM_SCREEN_ERT 5 + +var/shuttle_call/shuttle_calls[0] + +#define SHUTTLE_RECALL -1 +#define SHUTTLE_CALL 1 +#define SHUTTLE_TRANSFER 2 + +/shuttle_call + var/direction=0 + var/who="" + var/ckey="" + var/turf/from=null + var/where="" + var/when + var/eta=null + +/shuttle_call/New(var/mob/user,var/obj/machinery/computer/communications/computer,var/dir) + direction=dir + if(user) + who="[user]" + ckey="[user.key]" + if(computer) + where="[computer]" + from=get_turf(computer) + when=worldtime2text() + if(dir==SHUTTLE_RECALL) + var/timeleft=emergency_shuttle.timeleft() + eta="[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" + +// The communications computer +/obj/machinery/computer/communications + name = "Communications Console" + desc = "This can be used for various important functions. Still under developement." + icon_state = "comm" + req_access = list(access_heads) + circuit = "/obj/item/weapon/circuitboard/communications" + var/prints_intercept = 1 + var/authenticated = 0 + var/list/messagetitle = list() + var/list/messagetext = list() + var/currmsg = 0 + var/aicurrmsg = 0 + var/menu_state = COMM_SCREEN_MAIN + var/ai_menu_state = COMM_SCREEN_MAIN + var/message_cooldown = 0 + var/centcomm_message_cooldown = 0 + var/tmp_alertlevel = 0 + + var/status_display_freq = "1435" + var/stat_msg1 + var/stat_msg2 + var/display_type="blank" + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/communications/Topic(href, href_list) + if(..(href, href_list)) + return + + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + + if (!(src.z in list(STATION_Z,CENTCOMM_Z))) + to_chat(usr, "Unable to establish a connection: You're too far away from the station!") + return + + usr.set_machine(src) + + if(!href_list["operation"]) + return + switch(href_list["operation"]) + // main interface + if("main") + setMenuState(usr,COMM_SCREEN_MAIN) + if("login") + var/mob/M = usr + var/obj/item/weapon/card/id/I = M.get_active_hand() + if (istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if (istype(I,/obj/item/weapon/card/emag)) + emag(usr) + if (I && istype(I)) + if(src.check_access(I)) + authenticated = 1 + if(20 in I.access) + authenticated = 2 + if("logout") + authenticated = 0 + setMenuState(usr,COMM_SCREEN_MAIN) + // ALART LAVUL + if("changeseclevel") + setMenuState(usr,COMM_SCREEN_SECLEVEL) + + if("newalertlevel") + if(issilicon(usr)) + return + tmp_alertlevel = text2num(href_list["level"]) + var/mob/M = usr + var/obj/item/weapon/card/id/I = M.get_active_hand() + if (istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if (I && istype(I)) + if(access_captain in I.access || access_heads in I.access) //Let heads change the alert level. + var/old_level = security_level + if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN + if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN + if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this + set_security_level(tmp_alertlevel) + if(security_level != old_level) + //Only notify the admins if an actual change happened + log_game("[key_name(usr)] has changed the security level to [get_security_level()].") + message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].") + switch(security_level) + if(SEC_LEVEL_GREEN) + feedback_inc("alert_comms_green",1) + if(SEC_LEVEL_BLUE) + feedback_inc("alert_comms_blue",1) + tmp_alertlevel = 0 + else: + to_chat(usr, "You are not authorized to do this.") + tmp_alertlevel = 0 + setMenuState(usr,COMM_SCREEN_MAIN) + else + to_chat(usr, "You need to swipe your ID.") + + if("announce") + if(src.authenticated==2 && !issilicon(usr)) + if(message_cooldown) return + var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?") + if(!input || !(usr in view(1,src))) + return + captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain + var/turf/T = get_turf(usr) + log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has made a captain announcement: [input]") + message_admins("[key_name_admin(usr)] has made a captain announcement.", 1) + message_cooldown = 1 + spawn(600)//One minute cooldown + message_cooldown = 0 + + if("emergency_screen") + var/mob/M = usr + var/obj/item/weapon/card/id/I = M.get_active_hand() + if (istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if (I && istype(I)) + if(access_captain in I.access) + authenticated = 2 + if(authenticated != 2) + to_chat(usr, "You do not have clearance to use this function.") + return + setMenuState(usr,COMM_SCREEN_ERT) + return + if("request_emergency_team") + if(menu_state != COMM_SCREEN_ERT) return //Not on the right screen. + if ((!(ticker) || emergency_shuttle.location)) + to_chat(usr, "Warning: The evac shuttle has already arrived.") + return + + if(!universe.OnShuttleCall(usr)) + to_chat(usr, "\The [src.name] cannot establish a bluespace connection.") + return + + if(sent_strike_team) + to_chat(usr, "PKI AUTH ERROR: SERVER REPORTS BLACKLISTED COMMUNICATION KEY PLEASE CONTACT SERVICE TECHNICIAN") + return + + if(world.time < 6000) + to_chat(usr, "The emergency response team is away on another mission, Please wait another [round((6000-world.time)/600)] minute\s before trying again.") + return + if(emergency_shuttle.online) + to_chat(usr, "The emergency shuttle is already on its way.") + return + if(!(get_security_level() in list("red", "delta"))) + to_chat(usr, "The station must be in an emergency to request a Response Team.") + return + if(authenticated != 2 || issilicon(usr)) + to_chat(usr, "\The [src.name]'s screen flashes, \"Access Denied\".") + return + if(send_emergency_team) + to_chat(usr, "Central Command has already dispatched a Response Team to [station_name()]") + return + + var/response = alert(usr,"Are you sure you want to request a response team?", "ERT Request", "Yes", "No") + if(response != "Yes") + return + trigger_armed_response_team(1) + setMenuState(usr,COMM_SCREEN_MAIN) + return + + if("callshuttle") + if(src.authenticated) + var/response = alert("Are you sure you wish to call the shuttle?", "Confirm", "Yes", "No") + if(response == "Yes") + var/justification = stripped_input(usr, "Please input a concise justification for the shuttle call. Note that failure to properly justify a shuttle call may lead to recall or termination", "Nanotrasen Anti-Comdom Systems") + if(!justification || !(usr in view(1,src))) + return + call_shuttle_proc(usr, justification) + if(emergency_shuttle.online) + post_status("shuttle") + setMenuState(usr,COMM_SCREEN_MAIN) + if("cancelshuttle") + if(issilicon(usr)) return + if(src.authenticated) + var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No") + if(response == "Yes") + recall_shuttle(usr) + if(emergency_shuttle.online) + post_status("shuttle") + setMenuState(usr,COMM_SCREEN_MAIN) + if("messagelist") + src.currmsg = 0 + if(href_list["msgid"]) + setCurrentMessage(usr, text2num(href_list["msgid"])) + setMenuState(usr,COMM_SCREEN_MESSAGES) + if("delmessage") + if(href_list["msgid"]) + src.currmsg = text2num(href_list["msgid"]) + var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No") + if(response == "Yes") + if(src.currmsg) + var/id = getCurrentMessage() + var/title = src.messagetitle[id] + var/text = src.messagetext[id] + src.messagetitle.Remove(title) + src.messagetext.Remove(text) + if(currmsg==id) currmsg=0 + if(aicurrmsg==id) aicurrmsg=0 + setMenuState(usr,COMM_SCREEN_MESSAGES) + + if("status") + setMenuState(usr,COMM_SCREEN_STAT) + + // Status display stuff + if("setstat") + display_type=href_list["statdisp"] + switch(display_type) + if("message") + post_status("message", stat_msg1, stat_msg2) + if("alert") + post_status("alert", href_list["alert"]) + display_type = href_list["alert"] + else + post_status(href_list["statdisp"]) + setMenuState(usr,COMM_SCREEN_STAT) + + if("setmsg1") + stat_msg1 = reject_bad_text(trim(copytext(sanitize(input("Line 1", "Enter Message Text", stat_msg1) as text|null), 1, 40)), 40) + setMenuState(usr,COMM_SCREEN_STAT) + if("setmsg2") + stat_msg2 = reject_bad_text(trim(copytext(sanitize(input("Line 2", "Enter Message Text", stat_msg2) as text|null), 1, 40)), 40) + setMenuState(usr,COMM_SCREEN_STAT) + + // OMG CENTCOMM LETTERHEAD + if("MessageCentcomm") + if(src.authenticated==2) + if(centcomm_message_cooldown) + to_chat(usr, "Arrays recycling. Please stand by for a few seconds.") + return + var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") + if(!input || !(usr in view(1,src))) + return + Centcomm_announce(input, usr) + to_chat(usr, "Message transmitted.") + var/turf/T = get_turf(usr) + log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has sent a bluespace message to Centcomm: [input]") + centcomm_message_cooldown = 1 + spawn(300)//30 seconds cooldown + centcomm_message_cooldown = 0 + setMenuState(usr,COMM_SCREEN_MAIN) + + + // OMG SYNDICATE ...LETTERHEAD + if("MessageSyndicate") + if((src.authenticated==2) && (src.emagged)) + if(centcomm_message_cooldown) + to_chat(usr, "Arrays recycling. Please stand by for a few seconds.") + return + var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") + if(!input || !(usr in view(1,src))) + return + Syndicate_announce(input, usr) + to_chat(usr, "Message transmitted.") + var/turf/T = get_turf(usr) + log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has sent a bluespace message to the syndicate: [input]") + centcomm_message_cooldown = 1 + spawn(300)//30 seconds cooldown + centcomm_message_cooldown = 0 + setMenuState(usr,COMM_SCREEN_MAIN) + + if("RestoreBackup") + to_chat(usr, "Backup routing data restored!") + src.emagged = 0 + setMenuState(usr,COMM_SCREEN_MAIN) + update_icon() + + return 1 + +/obj/machinery/computer/communications/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/communications/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + + +/obj/machinery/computer/communications/attack_hand(var/mob/user as mob) + if(..(user)) + return + + if (!(src.z in list(STATION_Z, CENTCOMM_Z))) + to_chat(user, "Unable to establish a connection: You're too far away from the station!") + return + + ui_interact(user) + + + +/obj/machinery/computer/communications/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + if(user.stat) + return + + // this is the data which will be sent to the ui + var/data[0] + data["is_ai"] = issilicon(user) + data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state + data["emagged"] = emagged + data["authenticated"] = authenticated + data["screen"] = getMenuState(usr) + + data["stat_display"] = list( + "type"=display_type, + "line_1"=(stat_msg1 ? stat_msg1 : "-----"), + "line_2"=(stat_msg2 ? stat_msg2 : "-----"), + "presets"=list( + list("name"="blank", "label"="Clear", "desc"="Blank slate"), + list("name"="shuttle", "label"="Shuttle ETA", "desc"="Display how much time is left."), + list("name"="message", "label"="Message", "desc"="A custom message.") + ), + "alerts"=list( + list("alert"="default", "label"="NanoTrasen", "desc"="Oh god."), + list("alert"="redalert", "label"="Red Alert", "desc"="Nothing to do with communists."), + list("alert"="lockdown", "label"="Lockdown", "desc"="Let everyone know they're on lockdown."), + list("alert"="biohazard", "label"="Biohazard", "desc"="Great for virus outbreaks and parties."), + ) + ) + data["security_level"] = security_level + data["str_security_level"] = get_security_level() + data["levels"] = list( + list("id"=SEC_LEVEL_GREEN, "name"="Green"), + list("id"=SEC_LEVEL_BLUE, "name"="Blue"), + //SEC_LEVEL_RED = list("name"="Red"), + ) + data["ert_sent"] = send_emergency_team + + var/msg_data[0] + for(var/i=1;i<=src.messagetext.len;i++) + var/cur_msg[0] + cur_msg["title"]=messagetitle[i] + cur_msg["body"]=messagetext[i] + cur_msg["id"] = i + msg_data += list(cur_msg) + data["messages"] = msg_data + data["current_message"] = data["is_ai"] ? aicurrmsg : currmsg + + var/shuttle[0] + shuttle["on"]=emergency_shuttle.online + if (emergency_shuttle.online && emergency_shuttle.location==0) + var/timeleft=emergency_shuttle.timeleft() + shuttle["eta"]="[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" + shuttle["pos"] = emergency_shuttle.location + shuttle["can_recall"]=!(recall_time_limit && world.time >= recall_time_limit) + + data["shuttle"]=shuttle + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "comm_console.tmpl", "Communications Console", 400, 500) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/machinery/computer/communications/emag(mob/user as mob) + if(!emagged) + emagged = 1 + to_chat(user, "Syndicate routing data uploaded!") + new/obj/effect/effect/sparks(get_turf(src)) + playsound(loc,"sparks",50,1) + authenticated = 2 + setMenuState(usr,COMM_SCREEN_MAIN) + update_icon() + return 1 + return + + +/obj/machinery/computer/communications/update_icon() + ..() + var/initial_icon = initial(icon_state) + icon_state = "[emagged ? "[initial_icon]-emag" : "[initial_icon]"]" + if(stat & BROKEN) + icon_state = "[initial_icon]b" + else if(stat & NOPOWER) + icon_state = "[initial_icon]0" + + +/obj/machinery/computer/communications/proc/setCurrentMessage(var/mob/user,var/value) + if(issilicon(user)) + aicurrmsg=value + else + currmsg=value + +/obj/machinery/computer/communications/proc/getCurrentMessage(var/mob/user) + if(issilicon(user)) + return aicurrmsg + else + return currmsg + +/obj/machinery/computer/communications/proc/setMenuState(var/mob/user,var/value) + if(issilicon(user)) + ai_menu_state=value + else + menu_state=value + +/obj/machinery/computer/communications/proc/getMenuState(var/mob/user) + if(issilicon(user)) + return ai_menu_state + else + return menu_state + +/proc/enable_prison_shuttle(var/mob/user) + for(var/obj/machinery/computer/prison_shuttle/PS in machines) + PS.allowedtocall = !(PS.allowedtocall) + +/proc/call_shuttle_proc(var/mob/user, var/justification) + if ((!(ticker) || emergency_shuttle.location)) + return + + if(!universe.OnShuttleCall(user)) + return + + if(sent_strike_team == 1) + to_chat(user, "Centcom will not allow the shuttle to be called. Consider all contracts terminated.") + return + + if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE + to_chat(user, "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minute\s before trying again.") + return + + if(emergency_shuttle.direction == -1) + to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") + return + + if(emergency_shuttle.online) + to_chat(user, "The emergency shuttle is already on its way.") + return + + if(ticker.mode.name == "blob") + to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.") + return + + emergency_shuttle.incall() + if(!justification) + justification = "#??!7E/_1$*/ARR-CON²FAIL!!*$^?" //Can happen for reasons, let's deal with it IC + log_game("[key_name(user)] has called the shuttle. Justification given : '[justification]'") + message_admins("[key_name_admin(user)] has called the shuttle. Justification given : '[justification]'. You are encouraged to act if that justification is shit", 1) + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes. Justification : '[justification]'") + to_chat(world, sound('sound/AI/shuttlecalled.ogg')) + + return + +/proc/init_shift_change(var/mob/user, var/force = 0) + if ((!( ticker ) || emergency_shuttle.location)) + return + + if(emergency_shuttle.direction == -1) + to_chat(user, "The shuttle may not be called while returning to CentCom.") + return + + if(emergency_shuttle.online) + to_chat(user, "The shuttle is already on its way.") + return + + // if force is 0, some things may stop the shuttle call + if(!force) + if(!universe.OnShuttleCall(user)) + return + + if(emergency_shuttle.deny_shuttle) + to_chat(user, "Centcom does not currently have a shuttle available in your sector. Please try again later.") + return + + if(sent_strike_team == 1) + to_chat(user, "Centcom will not allow the shuttle to be called. Consider all contracts terminated.") + return + + if(world.time < 54000) // 30 minute grace period to let the game get going + to_chat(user, "The shuttle is refueling. Please wait another [round((54000-world.time)/600)] minutes before trying again.")//may need to change "/600" + + return + + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "sandbox") + //New version pretends to call the shuttle but cause the shuttle to return after a random duration. + emergency_shuttle.fake_recall = rand(300,500) + + if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic") to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.") - return - - emergency_shuttle.shuttlealert(1) - emergency_shuttle.incall() - log_game("[key_name(user)] has called the shuttle.") - message_admins("[key_name_admin(user)] has called the shuttle - [formatJumpTo(user)].", 1) - captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") - - return - -/proc/recall_shuttle(var/mob/user) - if ((!( ticker ) || emergency_shuttle.location || emergency_shuttle.direction == 0 || emergency_shuttle.timeleft() < 300)) - return - if( ticker.mode.name == "blob" || ticker.mode.name == "meteor") - return - - if(emergency_shuttle.direction != -1 && emergency_shuttle.online) //check that shuttle isn't already heading to centcomm - emergency_shuttle.recall() - log_game("[key_name(user)] has recalled the shuttle.") - message_admins("[key_name_admin(user)] has recalled the shuttle - [formatJumpTo(user)].", 1) - return - -/obj/machinery/computer/communications/proc/post_status(var/command, var/data1, var/data2) - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) - - if(!frequency) return - - var/datum/signal/status_signal = getFromPool(/datum/signal) - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - - switch(command) - if("message") - status_signal.data["msg1"] = data1 - status_signal.data["msg2"] = data2 - log_admin("STATUS: [src.fingerprintslast] set status screen message with [src]: [data1] [data2]") - //message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") - if("alert") - status_signal.data["picture_state"] = data1 - - frequency.post_signal(src, status_signal) - - -/obj/machinery/computer/communications/Destroy() - - for(var/obj/machinery/computer/communications/commconsole in machines) - if(istype(commconsole.loc,/turf) && commconsole != src) - return ..() - - for(var/obj/item/weapon/circuitboard/communications/commboard in world) - if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) - return ..() - - for(var/mob/living/silicon/ai/shuttlecaller in player_list) - if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) - return ..() - - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) - return ..() - - emergency_shuttle.incall(2) - log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.") - message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1) - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + return + + emergency_shuttle.shuttlealert(1) + emergency_shuttle.incall() + log_game("[key_name(user)] has called the shuttle.") + message_admins("[key_name_admin(user)] has called the shuttle - [formatJumpTo(user)].", 1) + captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + + return + +/proc/recall_shuttle(var/mob/user) + if ((!( ticker ) || emergency_shuttle.location || emergency_shuttle.direction == 0 || emergency_shuttle.timeleft() < 300)) + return + if( ticker.mode.name == "blob" || ticker.mode.name == "meteor") + return + + if(emergency_shuttle.direction != -1 && emergency_shuttle.online) //check that shuttle isn't already heading to centcomm + emergency_shuttle.recall() + log_game("[key_name(user)] has recalled the shuttle.") + message_admins("[key_name_admin(user)] has recalled the shuttle - [formatJumpTo(user)].", 1) + return + +/obj/machinery/computer/communications/proc/post_status(var/command, var/data1, var/data2) + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + + if(!frequency) return + + var/datum/signal/status_signal = getFromPool(/datum/signal) + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + + switch(command) + if("message") + status_signal.data["msg1"] = data1 + status_signal.data["msg2"] = data2 + log_admin("STATUS: [src.fingerprintslast] set status screen message with [src]: [data1] [data2]") + //message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") + if("alert") + status_signal.data["picture_state"] = data1 + + frequency.post_signal(src, status_signal) + + +/obj/machinery/computer/communications/Destroy() + + for(var/obj/machinery/computer/communications/commconsole in machines) + if(istype(commconsole.loc,/turf) && commconsole != src) + return ..() + + for(var/obj/item/weapon/circuitboard/communications/commboard in world) + if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) + return ..() + + for(var/mob/living/silicon/ai/shuttlecaller in player_list) + if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) + return ..() + + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) + return ..() + + emergency_shuttle.incall(2) + log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.") + message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1) + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") to_chat(world, sound('sound/AI/shuttlecalled.ogg')) - - ..() - -/obj/item/weapon/circuitboard/communications/Destroy() - - for(var/obj/machinery/computer/communications/commconsole in machines) - if(istype(commconsole.loc,/turf)) - return ..() - - for(var/obj/item/weapon/circuitboard/communications/commboard in world) - if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src) - return ..() - - for(var/mob/living/silicon/ai/shuttlecaller in player_list) - if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) - return ..() - - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) - return ..() - - emergency_shuttle.incall(2) - log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.") - message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1) - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + + ..() + +/obj/item/weapon/circuitboard/communications/Destroy() + + for(var/obj/machinery/computer/communications/commconsole in machines) + if(istype(commconsole.loc,/turf)) + return ..() + + for(var/obj/item/weapon/circuitboard/communications/commboard in world) + if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src) + return ..() + + for(var/mob/living/silicon/ai/shuttlecaller in player_list) + if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) + return ..() + + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) + return ..() + + emergency_shuttle.incall(2) + log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.") + message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1) + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") to_chat(world, sound('sound/AI/shuttlecalled.ogg')) - - ..() + + ..() diff --git a/code/game/machinery/computer/hologram.dm b/code/game/machinery/computer/hologram.dm index 3395bdd9817..0b8b1393d3b 100644 --- a/code/game/machinery/computer/hologram.dm +++ b/code/game/machinery/computer/hologram.dm @@ -1,110 +1,110 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/machinery/computer/hologram_comp - name = "Hologram Computer" - desc = "Rumoured to control holograms." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "holo_console0" - var/obj/machinery/hologram/projector/projector = null - var/temp = null - var/lumens = 0.0 - var/h_r = 245.0 - var/h_g = 245.0 - var/h_b = 245.0 - - -/obj/machinery/computer/hologram_comp/New() - ..() - spawn( 10 ) - src.projector = locate(/obj/machinery/hologram/projector, get_step(src.loc, NORTH)) - return - return - -/obj/machinery/computer/hologram_comp/DblClick() - if (!in_range(src, usr)) - return 0 - src.show_console(usr) - return - -/obj/machinery/computer/hologram_comp/proc/render() - var/icon/I = new /icon('icons/mob/human.dmi', "body_m_s") - - if (src.lumens >= 0) - I.Blend(rgb(src.lumens, src.lumens, src.lumens), ICON_ADD) - else - I.Blend(rgb(- src.lumens, -src.lumens, -src.lumens), ICON_SUBTRACT) - - I.Blend(new /icon('icons/mob/human.dmi', "mouth_m_s"), ICON_OVERLAY) - I.Blend(new /icon('icons/mob/human.dmi', "underwear1_m_s"), ICON_OVERLAY) - - var/icon/U = new /icon('icons/mob/human_face.dmi', "hair_a_s") - U.Blend(rgb(src.h_r, src.h_g, src.h_b), ICON_ADD) - - I.Blend(U, ICON_OVERLAY) - - src.projector.hologram.icon = I - -/obj/machinery/computer/hologram_comp/proc/show_console(var/mob/user as mob) - var/dat - user.set_machine(src) - if (src.temp) - dat = text("[]

      Clear", src.temp, src) - else - dat = text("Hologram Status:
      \nPower: []
      \nHologram Control:
      \nColor Luminosity: []/220 \[Reset\]
      \nLighten: 1 10
      \nDarken: 1 10
      \n
      \nHair Color: ([],[],[]) \[Reset\]
      \nRed (0-255): \[0\] -10 -1 [] 1 10 \[255\]
      \nGreen (0-255): \[0\] -10 -1 [] 1 10 \[255\]
      \nBlue (0-255): \[0\] -10 -1 [] 1 10 \[255\]
      ", src, (src.projector.hologram ? "On" : "Off"), -src.lumens + 35, src, src, src, src, src, src.h_r, src.h_g, src.h_b, src, src, src, src, src.h_r, src, src, src, src, src, src, src.h_g, src, src, src, src, src, src, src.h_b, src, src, src) - user << browse(dat, "window=hologram_console") - onclose(user, "hologram_console") - return - -/obj/machinery/computer/hologram_comp/Topic(href, href_list) - if(..()) - return 1 - else - flick("holo_console1", src) - if (href_list["power"]) - if (src.projector.hologram) - src.projector.icon_state = "hologram0" - //src.projector.hologram = null - qdel(src.projector.hologram) - src.projector.hologram = null - else - src.projector.hologram = new(src.projector.loc) - src.projector.hologram.icon = 'icons/mob/human.dmi' - src.projector.hologram.icon_state = "body_m_s" - src.projector.icon_state = "hologram1" - src.render() - else - if (href_list["h_r"]) - if (src.projector.hologram) - src.h_r += text2num(href_list["h_r"]) - src.h_r = min(max(src.h_r, 0), 255) - render() - else - if (href_list["h_g"]) - if (src.projector.hologram) - src.h_g += text2num(href_list["h_g"]) - src.h_g = min(max(src.h_g, 0), 255) - render() - else - if (href_list["h_b"]) - if (src.projector.hologram) - src.h_b += text2num(href_list["h_b"]) - src.h_b = min(max(src.h_b, 0), 255) - render() - else - if (href_list["light"]) - if (src.projector.hologram) - src.lumens += text2num(href_list["light"]) - src.lumens = min(max(src.lumens, -185.0), 35) - render() - else - if (href_list["reset"]) - if (src.projector.hologram) - src.lumens = 0 - render() - else - if (href_list["temp"]) - src.temp = null - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.show_console(M) - return +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/computer/hologram_comp + name = "Hologram Computer" + desc = "Rumoured to control holograms." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "holo_console0" + var/obj/machinery/hologram/projector/projector = null + var/temp = null + var/lumens = 0.0 + var/h_r = 245.0 + var/h_g = 245.0 + var/h_b = 245.0 + + +/obj/machinery/computer/hologram_comp/New() + ..() + spawn( 10 ) + src.projector = locate(/obj/machinery/hologram/projector, get_step(src.loc, NORTH)) + return + return + +/obj/machinery/computer/hologram_comp/DblClick() + if (!in_range(src, usr)) + return 0 + src.show_console(usr) + return + +/obj/machinery/computer/hologram_comp/proc/render() + var/icon/I = new /icon('icons/mob/human.dmi', "body_m_s") + + if (src.lumens >= 0) + I.Blend(rgb(src.lumens, src.lumens, src.lumens), ICON_ADD) + else + I.Blend(rgb(- src.lumens, -src.lumens, -src.lumens), ICON_SUBTRACT) + + I.Blend(new /icon('icons/mob/human.dmi', "mouth_m_s"), ICON_OVERLAY) + I.Blend(new /icon('icons/mob/human.dmi', "underwear1_m_s"), ICON_OVERLAY) + + var/icon/U = new /icon('icons/mob/human_face.dmi', "hair_a_s") + U.Blend(rgb(src.h_r, src.h_g, src.h_b), ICON_ADD) + + I.Blend(U, ICON_OVERLAY) + + src.projector.hologram.icon = I + +/obj/machinery/computer/hologram_comp/proc/show_console(var/mob/user as mob) + var/dat + user.set_machine(src) + if (src.temp) + dat = text("[]

      Clear", src.temp, src) + else + dat = text("Hologram Status:
      \nPower: []
      \nHologram Control:
      \nColor Luminosity: []/220 \[Reset\]
      \nLighten: 1 10
      \nDarken: 1 10
      \n
      \nHair Color: ([],[],[]) \[Reset\]
      \nRed (0-255): \[0\] -10 -1 [] 1 10 \[255\]
      \nGreen (0-255): \[0\] -10 -1 [] 1 10 \[255\]
      \nBlue (0-255): \[0\] -10 -1 [] 1 10 \[255\]
      ", src, (src.projector.hologram ? "On" : "Off"), -src.lumens + 35, src, src, src, src, src, src.h_r, src.h_g, src.h_b, src, src, src, src, src.h_r, src, src, src, src, src, src, src.h_g, src, src, src, src, src, src, src.h_b, src, src, src) + user << browse(dat, "window=hologram_console") + onclose(user, "hologram_console") + return + +/obj/machinery/computer/hologram_comp/Topic(href, href_list) + if(..()) + return 1 + else + flick("holo_console1", src) + if (href_list["power"]) + if (src.projector.hologram) + src.projector.icon_state = "hologram0" + //src.projector.hologram = null + qdel(src.projector.hologram) + src.projector.hologram = null + else + src.projector.hologram = new(src.projector.loc) + src.projector.hologram.icon = 'icons/mob/human.dmi' + src.projector.hologram.icon_state = "body_m_s" + src.projector.icon_state = "hologram1" + src.render() + else + if (href_list["h_r"]) + if (src.projector.hologram) + src.h_r += text2num(href_list["h_r"]) + src.h_r = min(max(src.h_r, 0), 255) + render() + else + if (href_list["h_g"]) + if (src.projector.hologram) + src.h_g += text2num(href_list["h_g"]) + src.h_g = min(max(src.h_g, 0), 255) + render() + else + if (href_list["h_b"]) + if (src.projector.hologram) + src.h_b += text2num(href_list["h_b"]) + src.h_b = min(max(src.h_b, 0), 255) + render() + else + if (href_list["light"]) + if (src.projector.hologram) + src.lumens += text2num(href_list["light"]) + src.lumens = min(max(src.lumens, -185.0), 35) + render() + else + if (href_list["reset"]) + if (src.projector.hologram) + src.lumens = 0 + render() + else + if (href_list["temp"]) + src.temp = null + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.show_console(M) + return diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 3093318db4b..db0008257dd 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -1,528 +1,528 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/machinery/computer/med_data//TODO:SANITY - name = "Medical Records" - desc = "This can be used to check medical records." - icon_state = "medcomp" - req_one_access = list(access_medical, access_forensics_lockers) - circuit = "/obj/item/weapon/circuitboard/med_data" - var/obj/item/weapon/card/id/scan = null - var/authenticated = null - var/rank = null - var/screen = null - var/datum/data/record/active1 = null - var/datum/data/record/active2 = null - var/a_id = null - var/temp = null - var/printing = null - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/med_data/attack_ai(user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/med_data/attack_paw(user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/med_data/attack_hand(mob/user as mob) - if(..()) - return - var/dat - if (src.temp) - dat = text("[src.temp]

      Clear Screen") - else - dat = text("Confirm Identity: []
      ", src, (src.scan ? text("[]", src.scan.name) : "----------")) - if (src.authenticated) - switch(src.screen) - if(1.0) - dat += {" -Search Records -
      List Records -
      -
      Virus Database -
      Medbot Tracking -
      -
      Record Maintenance -
      {Log Out}
      -"} - if(2.0) - dat += "Record List:
      " - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general)) - dat += text("[]: []
      ", src, R, R.fields["id"], R.fields["name"]) - //Foreach goto(132) - dat += text("
      Back", src) - if(3.0) - dat += text("Records Maintenance
      \nBackup To Disk
      \nUpload From disk
      \nDelete All Records
      \n
      \nBack", src, src, src, src) - if(4.0) - var/icon/front = new(active1.fields["photo"], dir = SOUTH) - var/icon/side = new(active1.fields["photo"], dir = WEST) - user << browse_rsc(front, "front.png") - user << browse_rsc(side, "side.png") - dat += "
      Medical Record

      " - if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) - dat += "
      Name: [active1.fields["name"]] \ - ID: [active1.fields["id"]]
      \n \ - Sex: [active1.fields["sex"]]
      \n \ - Age: [active1.fields["age"]]
      \n \ - Fingerprint: [active1.fields["fingerprint"]]
      \n \ - Physical Status: [active1.fields["p_stat"]]
      \n \ - Mental Status: [active1.fields["m_stat"]]
      \ - Photo:
      " - 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"]) - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - dat += text("[]
      Delete Entry

      ", src.active2.fields[text("com_[]", counter)], src, counter) - counter++ - dat += text("Add Entry

      ", src) - dat += text("Delete Record (Medical Only)

      ", src) - else - dat += "Medical Record Lost!
      " - dat += text("New Record

      ") - dat += text("\nPrint Record
      \nBack
      ", src, src) - if(5.0) - dat += "
      Virus Database
      " - /* Advanced diseases is weak! Feeble! Glory to virus2! - for(var/Dt in typesof(/datum/disease/)) - var/datum/disease/Dis = new Dt(0) - if(istype(Dis, /datum/disease/advance)) - continue // TODO (tm): Add advance diseases to the virus database which no one uses. - if(!Dis.desc) - continue - dat += "
      [Dis.name]" - */ - for (var/ID in virusDB) - var/datum/data/record/v = virusDB[ID] - dat += "
      [v.fields["name"]]" - - dat += "
      Back" - if(6.0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\\medical.dm:96: dat += "
      Medical Robot Monitor
      " - dat += {"
      Medical Robot Monitor
      - Back -
      Medical Robots:"} - // END AUTOFIX - var/bdat = null - for(var/obj/machinery/bot/medbot/M in machines) - - if(M.z != src.z) continue //only find medibots on the same z-level as the computer - var/turf/bl = get_turf(M) - if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up - bdat += "[M.name] - \[[bl.x-WORLD_X_OFFSET[bl.z]],[bl.y-WORLD_Y_OFFSET[bl.z]]\] - [M.on ? "Online" : "Offline"]
      " - if((!isnull(M.reagent_glass)) && M.use_beaker) - bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]
      " - else - bdat += "Using Internal Synthesizer.
      " - if(!bdat) - dat += "
      None detected
      " - else - dat += "
      [bdat]" - - else - else - dat += text("{Log In}", src) - user << browse(text("Medical Records[]", dat), "window=med_rec") - onclose(user, "med_rec") - return - -/obj/machinery/computer/med_data/Topic(href, href_list) - if(..()) - return - if (!( data_core.general.Find(src.active1) )) - src.active1 = null - if (!( data_core.medical.Find(src.active2) )) - src.active2 = null - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - if (href_list["temp"]) - src.temp = null - if (href_list["scan"]) - if (src.scan) - - if(ishuman(usr)) - scan.loc = usr.loc - - if(!usr.get_active_hand()) - usr.put_in_hands(scan) - - scan = null - - else - src.scan.loc = src.loc - src.scan = null - - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id)) - if(usr.drop_item(I, src)) - src.scan = I - else if (href_list["logout"]) - src.authenticated = null - src.screen = null - src.active1 = null - src.active2 = null - - else if (href_list["login"]) - - if (istype(usr, /mob/living/silicon/ai)) - src.active1 = null - src.active2 = null - src.authenticated = usr.name - src.rank = "AI" - src.screen = 1 - - else if (istype(usr, /mob/living/silicon/robot)) - src.active1 = null - src.active2 = null - src.authenticated = usr.name - var/mob/living/silicon/robot/R = usr - src.rank = "[R.modtype] [R.braintype]" - src.screen = 1 - - else if (istype(src.scan, /obj/item/weapon/card/id)) - src.active1 = null - src.active2 = null - if (src.check_access(src.scan)) - src.authenticated = src.scan.registered_name - src.rank = src.scan.assignment - src.screen = 1 - if (src.authenticated) - - if(href_list["screen"]) - src.screen = text2num(href_list["screen"]) - if(src.screen < 1) - src.screen = 1 - - src.active1 = null - src.active2 = null - - if(href_list["vir"]) - var/datum/data/record/v = locate(href_list["vir"]) - src.temp = "
      GNAv2 based virus lifeform V-[v.fields["id"]]
      " - src.temp += "
      Name: [v.fields["name"]]" - src.temp += "
      Antigen: [v.fields["antigen"]]" - src.temp += "
      Spread: [v.fields["spread type"]] " - src.temp += "
      Details:
      [v.fields["description"]]" - - if (href_list["del_all"]) - src.temp = text("Are you sure you wish to delete all records?
      \n\tYes
      \n\tNo
      ", src, src) - - if (href_list["del_all2"]) - for(var/datum/data/record/R in data_core.medical) - qdel(R) - R = null - //Foreach goto(494) - src.temp = "All records deleted." - - if (href_list["field"]) - var/a1 = src.active1 - var/a2 = src.active2 - switch(href_list["field"]) - if("fingerprint") - if (istype(src.active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - src.active1.fields["fingerprint"] = t1 - if("sex") - if (istype(src.active1, /datum/data/record)) - if (src.active1.fields["sex"] == "Male") - src.active1.fields["sex"] = "Female" - else - src.active1.fields["sex"] = "Male" - if("age") - if (istype(src.active1, /datum/data/record)) - var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as num - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - src.active1.fields["age"] = t1 - if("mi_dis") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text),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["mi_dis"] = t1 - if("mi_dis_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], 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["mi_dis_d"] = t1 - if("ma_dis") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text),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["ma_dis"] = t1 - if("ma_dis_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], 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["ma_dis_d"] = t1 - if("alg") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text),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["alg"] = t1 - if("alg_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], 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["alg_d"] = t1 - if("cdi") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text),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["cdi"] = t1 - if("cdi_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], 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["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) - 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 - if("p_stat") - if (istype(src.active1, /datum/data/record)) - src.temp = text("Physical Condition:
      \n\t*Deceased*
      \n\t*Unconscious*
      \n\tActive
      \n\tPhysically Unfit
      ", src, src, src, src) - if("m_stat") - if (istype(src.active1, /datum/data/record)) - src.temp = text("Mental Condition:
      \n\t*Insane*
      \n\t*Unstable*
      \n\t*Watch*
      \n\tStable
      ", src, src, src, src) - if("b_type") - if (istype(src.active2, /datum/data/record)) - src.temp = text("Blood Type:
      \n\tA- A+
      \n\tB- B+
      \n\tAB- AB+
      \n\tO- O+
      ", src, src, src, src, src, src, src, src) - if("b_dna") - if (istype(src.active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input DNA hash:", "Med. records", src.active1.fields["dna"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - src.active1.fields["dna"] = t1 - if("vir_name") - var/datum/data/record/v = locate(href_list["edit_vir"]) - if (v) - var/t1 = copytext(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - v.fields["name"] = t1 - if("vir_desc") - var/datum/data/record/v = locate(href_list["edit_vir"]) - if (v) - var/t1 = copytext(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], 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.active1 != a1)) - return - v.fields["description"] = t1 - else - - if (href_list["p_stat"]) - if (src.active1) - switch(href_list["p_stat"]) - if("deceased") - src.active1.fields["p_stat"] = "*Deceased*" - if("ssd") - src.active1.fields["p_stat"] = "*SSD*" - if("active") - src.active1.fields["p_stat"] = "Active" - if("unfit") - src.active1.fields["p_stat"] = "Physically Unfit" - if("disabled") - src.active1.fields["p_stat"] = "Disabled" - - if (href_list["m_stat"]) - if (src.active1) - switch(href_list["m_stat"]) - if("insane") - src.active1.fields["m_stat"] = "*Insane*" - if("unstable") - src.active1.fields["m_stat"] = "*Unstable*" - if("watch") - src.active1.fields["m_stat"] = "*Watch*" - if("stable") - src.active1.fields["m_stat"] = "Stable" - - - if (href_list["b_type"]) - if (src.active2) - switch(href_list["b_type"]) - if("an") - src.active2.fields["b_type"] = "A-" - if("bn") - src.active2.fields["b_type"] = "B-" - if("abn") - src.active2.fields["b_type"] = "AB-" - if("on") - src.active2.fields["b_type"] = "O-" - if("ap") - src.active2.fields["b_type"] = "A+" - if("bp") - src.active2.fields["b_type"] = "B+" - if("abp") - src.active2.fields["b_type"] = "AB+" - if("op") - src.active2.fields["b_type"] = "O+" - - - if (href_list["del_r"]) - if (src.active2) - src.temp = text("Are you sure you wish to delete the record (Medical Portion Only)?
      \n\tYes
      \n\tNo
      ", src, src) - - if (href_list["del_r2"]) - if (src.active2) - qdel(src.active2) - src.active2 = null - - if (href_list["d_rec"]) - var/datum/data/record/R = locate(href_list["d_rec"]) - var/datum/data/record/M = locate(href_list["d_rec"]) - if (!( data_core.general.Find(R) )) - src.temp = "Record Not Found!" - return - for(var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - else - //Foreach continue //goto(2540) - src.active1 = R - src.active2 = M - src.screen = 4 - - if (href_list["new"]) - if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) ))) - var/datum/data/record/R = new /datum/data/record( ) - R.fields["name"] = src.active1.fields["name"] - R.fields["id"] = src.active1.fields["id"] - R.name = text("Medical Record #[]", R.fields["id"]) - R.fields["b_type"] = "Unknown" - R.fields["b_dna"] = "Unknown" - R.fields["mi_dis"] = "None" - R.fields["mi_dis_d"] = "No minor disabilities have been declared." - R.fields["ma_dis"] = "None" - R.fields["ma_dis_d"] = "No major disabilities have been diagnosed." - R.fields["alg"] = "None" - R.fields["alg_d"] = "No allergies have been detected in this patient." - R.fields["cdi"] = "None" - R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - R.fields["notes"] = "No notes." - data_core.medical += R - src.active2 = R - src.screen = 4 - - if (href_list["add_c"]) - if (!( istype(src.active2, /datum/data/record) )) - return - var/a2 = src.active2 - var/t1 = copytext(sanitize(input("Add Comment:", "Med. records", null, 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 - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - counter++ - src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")]
      [t1]") - - if (href_list["del_c"]) - if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) - src.active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" - - if (href_list["search"]) - var/norange = (usr.mutations && usr.mutations.len && (M_TK in usr.mutations)) - var/t1 = copytext(sanitize(input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!in_range(src, usr)) && (!istype(usr, /mob/living/silicon)) && !norange))) - return - src.active1 = null - src.active2 = null - t1 = lowertext(t1) - for(var/datum/data/record/R in data_core.medical) - if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))) - src.active2 = R - else - //Foreach continue //goto(3229) - if (!( src.active2 )) - src.temp = text("Could not locate record [].", sanitize(t1)) - else - for(var/datum/data/record/E in data_core.general) - if ((E.fields["name"] == src.active2.fields["name"] || E.fields["id"] == src.active2.fields["id"])) - src.active1 = E - else - //Foreach continue //goto(3334) - src.screen = 4 - - if (href_list["print_p"]) - if (!( src.printing )) - src.printing = 1 - 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"]) - 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"]) - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - P.info += text("[]
      ", src.active2.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) - src.updateUsrDialog() - return - -/obj/machinery/computer/med_data/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - - for(var/datum/data/record/R in data_core.medical) - if(prob(10/severity)) - switch(rand(1,6)) - if(1) - R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]" - if(2) - R.fields["sex"] = pick("Male", "Female") - if(3) - R.fields["age"] = rand(5, 85) - if(4) - R.fields["b_type"] = pick("A-", "B-", "AB-", "O-", "A+", "B+", "AB+", "O+") - if(5) - R.fields["p_stat"] = pick("*SSD*", "Active", "Physically Unfit", "Disabled") - if(6) - R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") - continue - - else if(prob(1)) - qdel(R) - R = null - continue - - ..(severity) - - -/obj/machinery/computer/med_data/laptop - name = "Medical Laptop" - desc = "Cheap Nanotrasen Laptop." - icon_state = "medlaptop" - - machine_flags = 0 - - anchored = 0 - density = 0 - - light_color = LIGHT_COLOR_GREEN +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/computer/med_data//TODO:SANITY + name = "Medical Records" + desc = "This can be used to check medical records." + icon_state = "medcomp" + req_one_access = list(access_medical, access_forensics_lockers) + circuit = "/obj/item/weapon/circuitboard/med_data" + var/obj/item/weapon/card/id/scan = null + var/authenticated = null + var/rank = null + var/screen = null + var/datum/data/record/active1 = null + var/datum/data/record/active2 = null + var/a_id = null + var/temp = null + var/printing = null + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/med_data/attack_ai(user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/med_data/attack_paw(user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/med_data/attack_hand(mob/user as mob) + if(..()) + return + var/dat + if (src.temp) + dat = text("[src.temp]

      Clear Screen") + else + dat = text("Confirm Identity: []
      ", src, (src.scan ? text("[]", src.scan.name) : "----------")) + if (src.authenticated) + switch(src.screen) + if(1.0) + dat += {" +Search Records +
      List Records +
      +
      Virus Database +
      Medbot Tracking +
      +
      Record Maintenance +
      {Log Out}
      +"} + if(2.0) + dat += "Record List:
      " + if(!isnull(data_core.general)) + for(var/datum/data/record/R in sortRecord(data_core.general)) + dat += text("[]: []
      ", src, R, R.fields["id"], R.fields["name"]) + //Foreach goto(132) + dat += text("
      Back", src) + if(3.0) + dat += text("Records Maintenance
      \nBackup To Disk
      \nUpload From disk
      \nDelete All Records
      \n
      \nBack", src, src, src, src) + if(4.0) + var/icon/front = new(active1.fields["photo"], dir = SOUTH) + var/icon/side = new(active1.fields["photo"], dir = WEST) + user << browse_rsc(front, "front.png") + user << browse_rsc(side, "side.png") + dat += "
      Medical Record

      " + if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) + dat += "
      Name: [active1.fields["name"]] \ + ID: [active1.fields["id"]]
      \n \ + Sex: [active1.fields["sex"]]
      \n \ + Age: [active1.fields["age"]]
      \n \ + Fingerprint: [active1.fields["fingerprint"]]
      \n \ + Physical Status: [active1.fields["p_stat"]]
      \n \ + Mental Status: [active1.fields["m_stat"]]
      \ + Photo:
      " + 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"]) + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + dat += text("[]
      Delete Entry

      ", src.active2.fields[text("com_[]", counter)], src, counter) + counter++ + dat += text("Add Entry

      ", src) + dat += text("Delete Record (Medical Only)

      ", src) + else + dat += "Medical Record Lost!
      " + dat += text("New Record

      ") + dat += text("\nPrint Record
      \nBack
      ", src, src) + if(5.0) + dat += "
      Virus Database
      " + /* Advanced diseases is weak! Feeble! Glory to virus2! + for(var/Dt in typesof(/datum/disease/)) + var/datum/disease/Dis = new Dt(0) + if(istype(Dis, /datum/disease/advance)) + continue // TODO (tm): Add advance diseases to the virus database which no one uses. + if(!Dis.desc) + continue + dat += "
      [Dis.name]" + */ + for (var/ID in virusDB) + var/datum/data/record/v = virusDB[ID] + dat += "
      [v.fields["name"]]" + + dat += "
      Back" + if(6.0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\\medical.dm:96: dat += "
      Medical Robot Monitor
      " + dat += {"
      Medical Robot Monitor
      + Back +
      Medical Robots:"} + // END AUTOFIX + var/bdat = null + for(var/obj/machinery/bot/medbot/M in machines) + + if(M.z != src.z) continue //only find medibots on the same z-level as the computer + var/turf/bl = get_turf(M) + if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up + bdat += "[M.name] - \[[bl.x-WORLD_X_OFFSET[bl.z]],[bl.y-WORLD_Y_OFFSET[bl.z]]\] - [M.on ? "Online" : "Offline"]
      " + if((!isnull(M.reagent_glass)) && M.use_beaker) + bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]
      " + else + bdat += "Using Internal Synthesizer.
      " + if(!bdat) + dat += "
      None detected
      " + else + dat += "
      [bdat]" + + else + else + dat += text("{Log In}", src) + user << browse(text("Medical Records[]", dat), "window=med_rec") + onclose(user, "med_rec") + return + +/obj/machinery/computer/med_data/Topic(href, href_list) + if(..()) + return + if (!( data_core.general.Find(src.active1) )) + src.active1 = null + if (!( data_core.medical.Find(src.active2) )) + src.active2 = null + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + if (href_list["temp"]) + src.temp = null + if (href_list["scan"]) + if (src.scan) + + if(ishuman(usr)) + scan.loc = usr.loc + + if(!usr.get_active_hand()) + usr.put_in_hands(scan) + + scan = null + + else + src.scan.loc = src.loc + src.scan = null + + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + if(usr.drop_item(I, src)) + src.scan = I + else if (href_list["logout"]) + src.authenticated = null + src.screen = null + src.active1 = null + src.active2 = null + + else if (href_list["login"]) + + if (istype(usr, /mob/living/silicon/ai)) + src.active1 = null + src.active2 = null + src.authenticated = usr.name + src.rank = "AI" + src.screen = 1 + + else if (istype(usr, /mob/living/silicon/robot)) + src.active1 = null + src.active2 = null + src.authenticated = usr.name + var/mob/living/silicon/robot/R = usr + src.rank = "[R.modtype] [R.braintype]" + src.screen = 1 + + else if (istype(src.scan, /obj/item/weapon/card/id)) + src.active1 = null + src.active2 = null + if (src.check_access(src.scan)) + src.authenticated = src.scan.registered_name + src.rank = src.scan.assignment + src.screen = 1 + if (src.authenticated) + + if(href_list["screen"]) + src.screen = text2num(href_list["screen"]) + if(src.screen < 1) + src.screen = 1 + + src.active1 = null + src.active2 = null + + if(href_list["vir"]) + var/datum/data/record/v = locate(href_list["vir"]) + src.temp = "
      GNAv2 based virus lifeform V-[v.fields["id"]]
      " + src.temp += "
      Name: [v.fields["name"]]" + src.temp += "
      Antigen: [v.fields["antigen"]]" + src.temp += "
      Spread: [v.fields["spread type"]] " + src.temp += "
      Details:
      [v.fields["description"]]" + + if (href_list["del_all"]) + src.temp = text("Are you sure you wish to delete all records?
      \n\tYes
      \n\tNo
      ", src, src) + + if (href_list["del_all2"]) + for(var/datum/data/record/R in data_core.medical) + qdel(R) + R = null + //Foreach goto(494) + src.temp = "All records deleted." + + if (href_list["field"]) + var/a1 = src.active1 + var/a2 = src.active2 + switch(href_list["field"]) + if("fingerprint") + if (istype(src.active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + src.active1.fields["fingerprint"] = t1 + if("sex") + if (istype(src.active1, /datum/data/record)) + if (src.active1.fields["sex"] == "Male") + src.active1.fields["sex"] = "Female" + else + src.active1.fields["sex"] = "Male" + if("age") + if (istype(src.active1, /datum/data/record)) + var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as num + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + src.active1.fields["age"] = t1 + if("mi_dis") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text),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["mi_dis"] = t1 + if("mi_dis_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], 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["mi_dis_d"] = t1 + if("ma_dis") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text),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["ma_dis"] = t1 + if("ma_dis_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], 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["ma_dis_d"] = t1 + if("alg") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text),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["alg"] = t1 + if("alg_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], 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["alg_d"] = t1 + if("cdi") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text),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["cdi"] = t1 + if("cdi_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], 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["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) + 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 + if("p_stat") + if (istype(src.active1, /datum/data/record)) + src.temp = text("Physical Condition:
      \n\t*Deceased*
      \n\t*Unconscious*
      \n\tActive
      \n\tPhysically Unfit
      ", src, src, src, src) + if("m_stat") + if (istype(src.active1, /datum/data/record)) + src.temp = text("Mental Condition:
      \n\t*Insane*
      \n\t*Unstable*
      \n\t*Watch*
      \n\tStable
      ", src, src, src, src) + if("b_type") + if (istype(src.active2, /datum/data/record)) + src.temp = text("Blood Type:
      \n\tA- A+
      \n\tB- B+
      \n\tAB- AB+
      \n\tO- O+
      ", src, src, src, src, src, src, src, src) + if("b_dna") + if (istype(src.active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input DNA hash:", "Med. records", src.active1.fields["dna"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + src.active1.fields["dna"] = t1 + if("vir_name") + var/datum/data/record/v = locate(href_list["edit_vir"]) + if (v) + var/t1 = copytext(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + v.fields["name"] = t1 + if("vir_desc") + var/datum/data/record/v = locate(href_list["edit_vir"]) + if (v) + var/t1 = copytext(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], 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.active1 != a1)) + return + v.fields["description"] = t1 + else + + if (href_list["p_stat"]) + if (src.active1) + switch(href_list["p_stat"]) + if("deceased") + src.active1.fields["p_stat"] = "*Deceased*" + if("ssd") + src.active1.fields["p_stat"] = "*SSD*" + if("active") + src.active1.fields["p_stat"] = "Active" + if("unfit") + src.active1.fields["p_stat"] = "Physically Unfit" + if("disabled") + src.active1.fields["p_stat"] = "Disabled" + + if (href_list["m_stat"]) + if (src.active1) + switch(href_list["m_stat"]) + if("insane") + src.active1.fields["m_stat"] = "*Insane*" + if("unstable") + src.active1.fields["m_stat"] = "*Unstable*" + if("watch") + src.active1.fields["m_stat"] = "*Watch*" + if("stable") + src.active1.fields["m_stat"] = "Stable" + + + if (href_list["b_type"]) + if (src.active2) + switch(href_list["b_type"]) + if("an") + src.active2.fields["b_type"] = "A-" + if("bn") + src.active2.fields["b_type"] = "B-" + if("abn") + src.active2.fields["b_type"] = "AB-" + if("on") + src.active2.fields["b_type"] = "O-" + if("ap") + src.active2.fields["b_type"] = "A+" + if("bp") + src.active2.fields["b_type"] = "B+" + if("abp") + src.active2.fields["b_type"] = "AB+" + if("op") + src.active2.fields["b_type"] = "O+" + + + if (href_list["del_r"]) + if (src.active2) + src.temp = text("Are you sure you wish to delete the record (Medical Portion Only)?
      \n\tYes
      \n\tNo
      ", src, src) + + if (href_list["del_r2"]) + if (src.active2) + qdel(src.active2) + src.active2 = null + + if (href_list["d_rec"]) + var/datum/data/record/R = locate(href_list["d_rec"]) + var/datum/data/record/M = locate(href_list["d_rec"]) + if (!( data_core.general.Find(R) )) + src.temp = "Record Not Found!" + return + for(var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + else + //Foreach continue //goto(2540) + src.active1 = R + src.active2 = M + src.screen = 4 + + if (href_list["new"]) + if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) ))) + var/datum/data/record/R = new /datum/data/record( ) + R.fields["name"] = src.active1.fields["name"] + R.fields["id"] = src.active1.fields["id"] + R.name = text("Medical Record #[]", R.fields["id"]) + R.fields["b_type"] = "Unknown" + R.fields["b_dna"] = "Unknown" + R.fields["mi_dis"] = "None" + R.fields["mi_dis_d"] = "No minor disabilities have been declared." + R.fields["ma_dis"] = "None" + R.fields["ma_dis_d"] = "No major disabilities have been diagnosed." + R.fields["alg"] = "None" + R.fields["alg_d"] = "No allergies have been detected in this patient." + R.fields["cdi"] = "None" + R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." + R.fields["notes"] = "No notes." + data_core.medical += R + src.active2 = R + src.screen = 4 + + if (href_list["add_c"]) + if (!( istype(src.active2, /datum/data/record) )) + return + var/a2 = src.active2 + var/t1 = copytext(sanitize(input("Add Comment:", "Med. records", null, 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 + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + counter++ + src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")]
      [t1]") + + if (href_list["del_c"]) + if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) + src.active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" + + if (href_list["search"]) + var/norange = (usr.mutations && usr.mutations.len && (M_TK in usr.mutations)) + var/t1 = copytext(sanitize(input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!in_range(src, usr)) && (!istype(usr, /mob/living/silicon)) && !norange))) + return + src.active1 = null + src.active2 = null + t1 = lowertext(t1) + for(var/datum/data/record/R in data_core.medical) + if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))) + src.active2 = R + else + //Foreach continue //goto(3229) + if (!( src.active2 )) + src.temp = text("Could not locate record [].", sanitize(t1)) + else + for(var/datum/data/record/E in data_core.general) + if ((E.fields["name"] == src.active2.fields["name"] || E.fields["id"] == src.active2.fields["id"])) + src.active1 = E + else + //Foreach continue //goto(3334) + src.screen = 4 + + if (href_list["print_p"]) + if (!( src.printing )) + src.printing = 1 + 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"]) + 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"]) + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + P.info += text("[]
      ", src.active2.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) + src.updateUsrDialog() + return + +/obj/machinery/computer/med_data/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + for(var/datum/data/record/R in data_core.medical) + if(prob(10/severity)) + switch(rand(1,6)) + if(1) + R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]" + if(2) + R.fields["sex"] = pick("Male", "Female") + if(3) + R.fields["age"] = rand(5, 85) + if(4) + R.fields["b_type"] = pick("A-", "B-", "AB-", "O-", "A+", "B+", "AB+", "O+") + if(5) + R.fields["p_stat"] = pick("*SSD*", "Active", "Physically Unfit", "Disabled") + if(6) + R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") + continue + + else if(prob(1)) + qdel(R) + R = null + continue + + ..(severity) + + +/obj/machinery/computer/med_data/laptop + name = "Medical Laptop" + desc = "Cheap Nanotrasen Laptop." + icon_state = "medlaptop" + + machine_flags = 0 + + anchored = 0 + density = 0 + + light_color = LIGHT_COLOR_GREEN diff --git a/code/game/machinery/computer/prisonshuttle.dm b/code/game/machinery/computer/prisonshuttle.dm index ebacbb681c4..fc7b4960a99 100644 --- a/code/game/machinery/computer/prisonshuttle.dm +++ b/code/game/machinery/computer/prisonshuttle.dm @@ -1,215 +1,215 @@ -//Config stuff -#define PRISON_MOVETIME 150 //Time to station is milliseconds. -#define PRISON_STATION_AREATYPE "/area/shuttle/prison/station" //Type of the prison shuttle area for station -#define PRISON_DOCK_AREATYPE "/area/shuttle/prison/prison" //Type of the prison shuttle area for dock - -var/prison_shuttle_moving_to_station = 0 -var/prison_shuttle_moving_to_prison = 0 -var/prison_shuttle_at_station = 0 -var/prison_shuttle_can_send = 1 -var/prison_shuttle_time = 0 -var/prison_shuttle_timeleft = 0 - -/obj/machinery/computer/prison_shuttle - name = "Prison Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_security) - circuit = "/obj/item/weapon/circuitboard/prison_shuttle" - var/temp = null - var/allowedtocall = 0 - var/prison_break = 0 - light_color = LIGHT_COLOR_CYAN - - attackby(I as obj, user as mob) - if(!..()) - src.attack_hand(user) - - attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - - - attack_paw(var/mob/user as mob) - return src.attack_hand(user) - - emag(mob/user as mob) - emagged = 1 +//Config stuff +#define PRISON_MOVETIME 150 //Time to station is milliseconds. +#define PRISON_STATION_AREATYPE "/area/shuttle/prison/station" //Type of the prison shuttle area for station +#define PRISON_DOCK_AREATYPE "/area/shuttle/prison/prison" //Type of the prison shuttle area for dock + +var/prison_shuttle_moving_to_station = 0 +var/prison_shuttle_moving_to_prison = 0 +var/prison_shuttle_at_station = 0 +var/prison_shuttle_can_send = 1 +var/prison_shuttle_time = 0 +var/prison_shuttle_timeleft = 0 + +/obj/machinery/computer/prison_shuttle + name = "Prison Shuttle Console" + icon = 'icons/obj/computer.dmi' + icon_state = "shuttle" + req_access = list(access_security) + circuit = "/obj/item/weapon/circuitboard/prison_shuttle" + var/temp = null + var/allowedtocall = 0 + var/prison_break = 0 + light_color = LIGHT_COLOR_CYAN + + attackby(I as obj, user as mob) + if(!..()) + src.attack_hand(user) + + attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + + + attack_paw(var/mob/user as mob) + return src.attack_hand(user) + + emag(mob/user as mob) + emagged = 1 to_chat(user, "You disable the lock.") - return - - attack_hand(var/mob/user as mob) - if(!src.allowed(user) && (!emagged)) + return + + attack_hand(var/mob/user as mob) + if(!src.allowed(user) && (!emagged)) to_chat(user, "Access Denied.") - return - if(prison_break) + return + if(prison_break) to_chat(user, "Unable to locate shuttle.") - return - if(..()) - return - user.set_machine(src) - post_signal("prison") - var/dat - if (src.temp) - dat = src.temp - else - dat += {"
      Prison Shuttle
      - \nLocation: [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "Moving to station ([prison_shuttle_timeleft] Secs.)":prison_shuttle_at_station ? "Station":"Dock"]
      - [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "\n*Shuttle already called*
      \n
      ":prison_shuttle_at_station ? "\nSend to Dock
      \n
      ":"\nSend to station
      \n
      "] - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - - - Topic(href, href_list) - if(..()) - return 1 - - else - usr.set_machine(src) - - if (href_list["sendtodock"]) - if (!prison_can_move()) + return + if(..()) + return + user.set_machine(src) + post_signal("prison") + var/dat + if (src.temp) + dat = src.temp + else + dat += {"
      Prison Shuttle
      + \nLocation: [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "Moving to station ([prison_shuttle_timeleft] Secs.)":prison_shuttle_at_station ? "Station":"Dock"]
      + [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "\n*Shuttle already called*
      \n
      ":prison_shuttle_at_station ? "\nSend to Dock
      \n
      ":"\nSend to station
      \n
      "] + \nClose"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + + + Topic(href, href_list) + if(..()) + return 1 + + else + usr.set_machine(src) + + if (href_list["sendtodock"]) + if (!prison_can_move()) to_chat(usr, "The prison shuttle is unable to leave.") - return - if(!prison_shuttle_at_station|| prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - post_signal("prison") + return + if(!prison_shuttle_at_station|| prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return + post_signal("prison") to_chat(usr, "The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds.") - src.temp += "Shuttle sent.

      OK" - src.updateUsrDialog() - prison_shuttle_moving_to_prison = 1 - prison_shuttle_time = world.timeofday + PRISON_MOVETIME - spawn(0) - prison_process() - - else if (href_list["sendtostation"]) - if (!prison_can_move()) + src.temp += "Shuttle sent.

      OK" + src.updateUsrDialog() + prison_shuttle_moving_to_prison = 1 + prison_shuttle_time = world.timeofday + PRISON_MOVETIME + spawn(0) + prison_process() + + else if (href_list["sendtostation"]) + if (!prison_can_move()) to_chat(usr, "The prison shuttle is unable to leave.") - return - if(prison_shuttle_at_station || prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - post_signal("prison") + return + if(prison_shuttle_at_station || prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return + post_signal("prison") to_chat(usr, "The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds.") - src.temp += "Shuttle sent.

      OK" - src.updateUsrDialog() - prison_shuttle_moving_to_station = 1 - prison_shuttle_time = world.timeofday + PRISON_MOVETIME - spawn(0) - prison_process() - - else if (href_list["mainmenu"]) - src.temp = null - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - - - proc/prison_can_move() - if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return 0 - else return 1 - - - proc/prison_break() - switch(prison_break) - if (0) - if(!prison_shuttle_at_station || prison_shuttle_moving_to_prison) return - - prison_shuttle_moving_to_prison = 1 - prison_shuttle_at_station = prison_shuttle_at_station - - if (!prison_shuttle_moving_to_prison || !prison_shuttle_moving_to_station) - prison_shuttle_time = world.timeofday + PRISON_MOVETIME - spawn(0) - prison_process() - prison_break = 1 - if(1) - prison_break = 0 - - - proc/post_signal(var/command) - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1311) - if(!frequency) return - var/datum/signal/status_signal = getFromPool(/datum/signal) - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - frequency.post_signal(src, status_signal) - return - - - proc/prison_process() - while(prison_shuttle_time - world.timeofday > 0) - var/ticksleft = prison_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - prison_shuttle_time = world.timeofday + 10 // midnight rollover - - prison_shuttle_timeleft = (ticksleft / 10) - sleep(5) - prison_shuttle_moving_to_station = 0 - prison_shuttle_moving_to_prison = 0 - - switch(prison_shuttle_at_station) - - if(0) - prison_shuttle_at_station = 1 - if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - - if (!prison_can_move()) + src.temp += "Shuttle sent.

      OK" + src.updateUsrDialog() + prison_shuttle_moving_to_station = 1 + prison_shuttle_time = world.timeofday + PRISON_MOVETIME + spawn(0) + prison_process() + + else if (href_list["mainmenu"]) + src.temp = null + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + + + proc/prison_can_move() + if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return 0 + else return 1 + + + proc/prison_break() + switch(prison_break) + if (0) + if(!prison_shuttle_at_station || prison_shuttle_moving_to_prison) return + + prison_shuttle_moving_to_prison = 1 + prison_shuttle_at_station = prison_shuttle_at_station + + if (!prison_shuttle_moving_to_prison || !prison_shuttle_moving_to_station) + prison_shuttle_time = world.timeofday + PRISON_MOVETIME + spawn(0) + prison_process() + prison_break = 1 + if(1) + prison_break = 0 + + + proc/post_signal(var/command) + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1311) + if(!frequency) return + var/datum/signal/status_signal = getFromPool(/datum/signal) + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + frequency.post_signal(src, status_signal) + return + + + proc/prison_process() + while(prison_shuttle_time - world.timeofday > 0) + var/ticksleft = prison_shuttle_time - world.timeofday + + if(ticksleft > 1e5) + prison_shuttle_time = world.timeofday + 10 // midnight rollover + + prison_shuttle_timeleft = (ticksleft / 10) + sleep(5) + prison_shuttle_moving_to_station = 0 + prison_shuttle_moving_to_prison = 0 + + switch(prison_shuttle_at_station) + + if(0) + prison_shuttle_at_station = 1 + if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return + + if (!prison_can_move()) to_chat(usr, "The prison shuttle is unable to leave.") - return - - var/area/start_location = locate(/area/shuttle/prison/prison) - var/area/end_location = locate(/area/shuttle/prison/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - T = null - start_location.move_contents_to(end_location) - - if(1) - prison_shuttle_at_station = 0 - if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return - - if (!prison_can_move()) + return + + var/area/start_location = locate(/area/shuttle/prison/prison) + var/area/end_location = locate(/area/shuttle/prison/station) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + T = null + start_location.move_contents_to(end_location) + + if(1) + prison_shuttle_at_station = 0 + if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return + + if (!prison_can_move()) to_chat(usr, "The prison shuttle is unable to leave.") - return - - var/area/start_location = locate(/area/shuttle/prison/station) - var/area/end_location = locate(/area/shuttle/prison/prison) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - start_location.move_contents_to(end_location) - return + return + + var/area/start_location = locate(/area/shuttle/prison/station) + var/area/end_location = locate(/area/shuttle/prison/prison) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + start_location.move_contents_to(end_location) + return diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index b96405a1264..c10fa01cdcf 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -1,240 +1,240 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - - -/obj/machinery/computer/robotics - name = "Robotics Control" - desc = "Used to remotely lockdown or detonate linked Cyborgs." - icon = 'icons/obj/computer.dmi' - icon_state = "robot" - req_access = list(access_robotics) - circuit = "/obj/item/weapon/circuitboard/robotics" - - var/id = 0.0 - var/temp = null - var/status = 0 - var/timeleft = 60 - var/stop = 0.0 - var/screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text - - light_color = LIGHT_COLOR_PINK - - -/obj/machinery/computer/robotics/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/robotics/attack_paw(var/mob/user as mob) - - return src.attack_hand(user) - return - -/obj/machinery/computer/robotics/attack_hand(var/mob/user as mob) - if(..()) - return - if (src.z > 6) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + + +/obj/machinery/computer/robotics + name = "Robotics Control" + desc = "Used to remotely lockdown or detonate linked Cyborgs." + icon = 'icons/obj/computer.dmi' + icon_state = "robot" + req_access = list(access_robotics) + circuit = "/obj/item/weapon/circuitboard/robotics" + + var/id = 0.0 + var/temp = null + var/status = 0 + var/timeleft = 60 + var/stop = 0.0 + var/screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text + + light_color = LIGHT_COLOR_PINK + + +/obj/machinery/computer/robotics/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/robotics/attack_paw(var/mob/user as mob) + + return src.attack_hand(user) + return + +/obj/machinery/computer/robotics/attack_hand(var/mob/user as mob) + if(..()) + return + if (src.z > 6) to_chat(user, "Unable to establish a connection: You're too far away from the station!") - return - user.set_machine(src) - var/dat - if (src.temp) - dat = "[src.temp]

      Clear Screen" - else - if(screen == 0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\robot.dm:41: dat += "

      Cyborg Control Console


      " - dat += {"

      Cyborg Control Console


      - 1. Cyborg Status
      - 2. Emergency Full Destruct
      "} - // END AUTOFIX - if(screen == 1) - for(var/mob/living/silicon/robot/R in mob_list) - if(istype(user, /mob/living/silicon/ai)) - if (R.connected_ai != user) - continue - if(istype(user, /mob/living/silicon/robot)) - if (R != user) - continue - if(R.scrambledcodes) - continue - - dat += "[R.name] |" - if(R.stat) - dat += " Not Responding |" - else if (!R.canmove) - dat += " Locked Down |" - else - dat += " Operating Normally |" - if (!R.canmove) - else if(R.cell) - dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |" - else - dat += " No Cell Installed |" - if(R.module) - dat += " Module Installed ([R.module.name]) |" - else - dat += " No Module Installed |" - if(R.connected_ai) - dat += " Slaved to [R.connected_ai.name] |" - else - dat += " Independent from AI |" - if (istype(user, /mob/living/silicon)) - if((user.mind.special_role && user.mind.original == user) && !R.emagged) - dat += "(Hack) " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\robot.dm:78: dat += "([R.canmove ? "Lockdown" : "Release"]) " - dat += {"([R.canmove ? "Lockdown" : "Release"]) - (Destroy) -
      "} - // END AUTOFIX - dat += "(Return to Main Menu)
      " - if(screen == 2) - if(!src.status) - dat += {"
      Emergency Robot Self-Destruct
      \nStatus: Off
      - \n
      - \nCountdown: [src.timeleft]/60 \[Reset\]
      - \n
      - \nStart Sequence
      - \n
      - \nClose"} - else - dat = {"Emergency Robot Self-Destruct
      \nStatus: Activated
      - \n
      - \nCountdown: [src.timeleft]/60 \[Reset\]
      - \n
      \nStop Sequence
      - \n
      - \nClose"} - dat += "(Return to Main Menu)
      " - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - -/obj/machinery/computer/robotics/Topic(href, href_list) - if(..()) - return 1 - else - usr.set_machine(src) - - if (href_list["eject"]) - src.temp = {"Destroy Robots?
      -
      \[Swipe ID to initiate destruction sequence\]
      - Cancel"} - - else if (href_list["eject2"]) - var/obj/item/weapon/card/id/I = usr.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (istype(I)) - if(src.check_access(I)) - if (!status) - message_admins("[key_name_admin(usr)] has initiated the global cyborg killswitch!") - log_game("[key_name(usr)] has initiated the global cyborg killswitch!") - src.status = 1 - src.start_sequence() - src.temp = null - - else + return + user.set_machine(src) + var/dat + if (src.temp) + dat = "[src.temp]

      Clear Screen" + else + if(screen == 0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\robot.dm:41: dat += "

      Cyborg Control Console


      " + dat += {"

      Cyborg Control Console


      + 1. Cyborg Status
      + 2. Emergency Full Destruct
      "} + // END AUTOFIX + if(screen == 1) + for(var/mob/living/silicon/robot/R in mob_list) + if(istype(user, /mob/living/silicon/ai)) + if (R.connected_ai != user) + continue + if(istype(user, /mob/living/silicon/robot)) + if (R != user) + continue + if(R.scrambledcodes) + continue + + dat += "[R.name] |" + if(R.stat) + dat += " Not Responding |" + else if (!R.canmove) + dat += " Locked Down |" + else + dat += " Operating Normally |" + if (!R.canmove) + else if(R.cell) + dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |" + else + dat += " No Cell Installed |" + if(R.module) + dat += " Module Installed ([R.module.name]) |" + else + dat += " No Module Installed |" + if(R.connected_ai) + dat += " Slaved to [R.connected_ai.name] |" + else + dat += " Independent from AI |" + if (istype(user, /mob/living/silicon)) + if((user.mind.special_role && user.mind.original == user) && !R.emagged) + dat += "(Hack) " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\robot.dm:78: dat += "([R.canmove ? "Lockdown" : "Release"]) " + dat += {"([R.canmove ? "Lockdown" : "Release"]) + (Destroy) +
      "} + // END AUTOFIX + dat += "(Return to Main Menu)
      " + if(screen == 2) + if(!src.status) + dat += {"
      Emergency Robot Self-Destruct
      \nStatus: Off
      + \n
      + \nCountdown: [src.timeleft]/60 \[Reset\]
      + \n
      + \nStart Sequence
      + \n
      + \nClose"} + else + dat = {"Emergency Robot Self-Destruct
      \nStatus: Activated
      + \n
      + \nCountdown: [src.timeleft]/60 \[Reset\]
      + \n
      \nStop Sequence
      + \n
      + \nClose"} + dat += "(Return to Main Menu)
      " + + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + +/obj/machinery/computer/robotics/Topic(href, href_list) + if(..()) + return 1 + else + usr.set_machine(src) + + if (href_list["eject"]) + src.temp = {"Destroy Robots?
      +
      \[Swipe ID to initiate destruction sequence\]
      + Cancel"} + + else if (href_list["eject2"]) + var/obj/item/weapon/card/id/I = usr.get_active_hand() + if (istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if (istype(I)) + if(src.check_access(I)) + if (!status) + message_admins("[key_name_admin(usr)] has initiated the global cyborg killswitch!") + log_game("[key_name(usr)] has initiated the global cyborg killswitch!") + src.status = 1 + src.start_sequence() + src.temp = null + + else to_chat(usr, "Access Denied.") - - else if (href_list["stop"]) - src.temp = {" - Stop Robot Destruction Sequence?
      -
      Yes
      - No"} - - else if (href_list["stop2"]) - src.stop = 1 - src.temp = null - src.status = 0 - - else if (href_list["reset"]) - src.timeleft = 60 - - else if (href_list["temp"]) - src.temp = null - else if (href_list["screen"]) - switch(href_list["screen"]) - if("0") - screen = 0 - if("1") - screen = 1 - if("2") - screen = 2 - else if (href_list["killbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["killbot"]) - if(R) - var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm") - if(R && istype(R)) - if(R.mind && R.mind.special_role && R.emagged) + + else if (href_list["stop"]) + src.temp = {" + Stop Robot Destruction Sequence?
      +
      Yes
      + No"} + + else if (href_list["stop2"]) + src.stop = 1 + src.temp = null + src.status = 0 + + else if (href_list["reset"]) + src.timeleft = 60 + + else if (href_list["temp"]) + src.temp = null + else if (href_list["screen"]) + switch(href_list["screen"]) + if("0") + screen = 0 + if("1") + screen = 1 + if("2") + screen = 2 + else if (href_list["killbot"]) + if(src.allowed(usr)) + var/mob/living/silicon/robot/R = locate(href_list["killbot"]) + if(R) + var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") + if(choice == "Confirm") + if(R && istype(R)) + if(R.mind && R.mind.special_role && R.emagged) to_chat(R, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.") - R.ResetSecurityCodes() - - else - message_admins("[key_name_admin(usr)] detonated [R.name]!") - log_game("[key_name_admin(usr)] detonated [R.name]!") - R.self_destruct() - else + R.ResetSecurityCodes() + + else + message_admins("[key_name_admin(usr)] detonated [R.name]!") + log_game("[key_name_admin(usr)] detonated [R.name]!") + R.self_destruct() + else to_chat(usr, "Access Denied.") - - else if (href_list["stopbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) - if(R && istype(R)) // Extra sancheck because of input var references - var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm") - if(R && istype(R)) - message_admins("[key_name_admin(usr)] [R.canmove ? "locked down" : "released"] [R.name]!") - log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!") - R.canmove = !R.canmove - if (R.lockcharge) - // R.cell.charge = R.lockcharge - R.lockcharge = !R.lockcharge + + else if (href_list["stopbot"]) + if(src.allowed(usr)) + var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) + if(R && istype(R)) // Extra sancheck because of input var references + var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort") + if(choice == "Confirm") + if(R && istype(R)) + message_admins("[key_name_admin(usr)] [R.canmove ? "locked down" : "released"] [R.name]!") + log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!") + R.canmove = !R.canmove + if (R.lockcharge) + // R.cell.charge = R.lockcharge + R.lockcharge = !R.lockcharge to_chat(R, "Your lockdown has been lifted!") - else - R.lockcharge = !R.lockcharge - // R.cell.charge = 0 + else + R.lockcharge = !R.lockcharge + // R.cell.charge = 0 to_chat(R, "You have been locked down!") - - else + + else to_chat(usr, "Access Denied.") - - else if (href_list["magbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["magbot"]) - - // whatever weirdness this is supposed to be, but that is how the href gets added, so here it is again - if(istype(R) && istype(usr, /mob/living/silicon) && usr.mind.special_role && (usr.mind.original == usr) && R.emagged != 1) - var/choice = input("Are you certain you wish to hack [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm") - if(R && istype(R)) -// message_admins("[key_name_admin(usr)] emagged [R.name] using robotic console!") - log_game("[key_name(usr)] emagged [R.name] using robotic console!") - R.SetEmagged(2) - if(R.mind.special_role) - R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer/robotics/proc/start_sequence() - - - do - if(src.stop) - src.stop = 0 - return - src.timeleft-- - sleep(10) - while(src.timeleft) - - for(var/mob/living/silicon/robot/R in mob_list) - if(!R.scrambledcodes) - R.self_destruct() - - return + + else if (href_list["magbot"]) + if(src.allowed(usr)) + var/mob/living/silicon/robot/R = locate(href_list["magbot"]) + + // whatever weirdness this is supposed to be, but that is how the href gets added, so here it is again + if(istype(R) && istype(usr, /mob/living/silicon) && usr.mind.special_role && (usr.mind.original == usr) && R.emagged != 1) + var/choice = input("Are you certain you wish to hack [R.name]?") in list("Confirm", "Abort") + if(choice == "Confirm") + if(R && istype(R)) +// message_admins("[key_name_admin(usr)] emagged [R.name] using robotic console!") + log_game("[key_name(usr)] emagged [R.name] using robotic console!") + R.SetEmagged(2) + if(R.mind.special_role) + R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + +/obj/machinery/computer/robotics/proc/start_sequence() + + + do + if(src.stop) + src.stop = 0 + return + src.timeleft-- + sleep(10) + while(src.timeleft) + + for(var/mob/living/silicon/robot/R in mob_list) + if(!R.scrambledcodes) + R.self_destruct() + + return diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 6f96be83688..cd9ab6ec8bb 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -1,612 +1,612 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/machinery/computer/secure_data//TODO:SANITY - name = "Security Records" - desc = "Used to view and edit personnel's security records" - icon_state = "security" - req_one_access = list(access_security, access_forensics_lockers) - circuit = "/obj/item/weapon/circuitboard/secure_data" - var/obj/item/weapon/card/id/scan = null - var/authenticated = null - var/rank = null - var/screen = null - var/datum/data/record/active1 = null - var/datum/data/record/active2 = null - var/a_id = null - var/temp = null - var/printing = null - var/can_change_id = 0 - var/list/Perp - var/tempname = null - //Sorting Variables - var/sortBy = "name" - var/order = 1 // -1 = Descending - 1 = Ascending - - light_color = LIGHT_COLOR_RED - -/obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob) - if(istype(O, /obj/item/weapon/card/id) && !scan) - if(usr.drop_item(O, src)) - scan = O - to_chat(user, "You insert \the [O].") - ..() - -/obj/machinery/computer/secure_data/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/computer/secure_data/attack_paw(mob/user as mob) - return attack_hand(user) - -//Someone needs to break down the dat += into chunks instead of long ass lines. -/obj/machinery/computer/secure_data/attack_hand(mob/user as mob) - if(..()) - return - if (src.z > 6) - to_chat(user, "Unable to establish a connection: You're too far away from the station!") - return - var/dat - - if (temp) - dat = text("[]

      Clear Screen", temp, src) - else - dat = text("Confirm Identity: []
      ", src, (scan ? text("[]", scan.name) : "----------")) - if (authenticated) - switch(screen) - if(1.0) - dat += {" -

      "} - dat += text("Search Records
      ", src) - dat += text("New Record
      ", src) - dat += {" -

      - - - - -
      Records:
      - - - - - - - -"} - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) - var/crimstat = "" - for(var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) - crimstat = E.fields["criminal"] - var/background - switch(crimstat) - if("*Arrest*") - background = "'background-color:#DC143C;'" - if("Incarcerated") - background = "'background-color:#CD853F;'" - if("Parolled") - background = "'background-color:#CD853F;'" - if("Released") - background = "'background-color:#3BB9FF;'" - if("None") - background = "'background-color:#00FF7F;'" - if("") - background = "'background-color:#FFFFFF;'" - crimstat = "No Record." - dat += text("", background, src, R, R.fields["name"]) - dat += text("", R.fields["id"]) - dat += text("", R.fields["rank"]) - dat += text("", R.fields["fingerprint"]) - dat += text("", crimstat) - dat += "
      NameIDRankFingerprintsCriminal Status
      [][][][][]

      " - dat += text("Record Maintenance

      ", src) - dat += text("{Log Out}",src) - if(2.0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:106: dat += "Records Maintenance
      " - dat += {"Records Maintenance
      -
      Delete All Records

      Back"} - // END AUTOFIX - if(3.0) - dat += "
      Security Record

      " - if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - var/icon/front = new(active1.fields["photo"], dir = SOUTH) - var/icon/side = new(active1.fields["photo"], dir = WEST) - user << browse_rsc(front, "front.png") - user << browse_rsc(side, "side.png") - dat += text(" \ -
      \ - Name: [active1.fields["name"]]
      \ - ID: [active1.fields["id"]]
      \n \ - Sex: [active1.fields["sex"]]
      \n \ - Age: [active1.fields["age"]]
      \n \ - Rank: [active1.fields["rank"]]
      \n \ - Fingerprint: [active1.fields["fingerprint"]]
      \n \ - Physical Status: [active1.fields["p_stat"]]
      \n \ - Mental Status: [active1.fields["m_stat"]]
      Photo:
      \ -
      ") - 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"]) - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - dat += text("[]
      Delete Entry

      ", active2.fields[text("com_[]", counter)], src, counter) - counter++ - dat += text("Add Entry

      ", src) - dat += text("Delete Record (Security Only)

      ", src) - else - dat += "Security Record Lost!
      " - dat += text("New Security Record

      ", src) - dat += text("\nDelete Record (ALL)

      \nPrint Record
      \nBack
      ", src, src, src) - if(4.0) - if(!Perp.len) - dat += text("ERROR. String could not be located.

      Back", src) - else - dat += {" - - "} - dat += text("", tempname) - dat += {" - -
      Search Results for '[]':
      - - - - - - - - "} - for(var/i=1, i<=Perp.len, i += 2) - var/crimstat = "" - var/datum/data/record/R = Perp[i] - if(istype(Perp[i+1],/datum/data/record/)) - var/datum/data/record/E = Perp[i+1] - crimstat = E.fields["criminal"] - var/background - switch(crimstat) - if("*Arrest*") - background = "'background-color:#DC143C;'" - if("Incarcerated") - background = "'background-color:#CD853F;'" - if("Parolled") - background = "'background-color:#CD853F;'" - if("Released") - background = "'background-color:#3BB9FF;'" - if("None") - background = "'background-color:#00FF7F;'" - if("") - background = "'background-color:#FFFFFF;'" - crimstat = "No Record." - dat += text("", background, src, R, R.fields["name"]) - dat += text("", R.fields["id"]) - dat += text("", R.fields["rank"]) - dat += text("", R.fields["fingerprint"]) - dat += text("", crimstat) - dat += "
      NameIDRankFingerprintsCriminal Status
      [][][][][]

      " - dat += text("
      Return to index.", src) - else - else - dat += text("{Log In}", src) - user << browse(text("Security Records[]", dat), "window=secure_rec;size=600x400") - onclose(user, "secure_rec") - return - -/*Revised /N -I can't be bothered to look more of the actual code outside of switch but that probably needs revising too. -What a mess.*/ -/obj/machinery/computer/secure_data/Topic(href, href_list) - if(..()) - return - if (!( data_core.general.Find(active1) )) - active1 = null - if (!( data_core.security.Find(active2) )) - active2 = null - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - switch(href_list["choice"]) -// SORTING! - if("Sorting") - // Reverse the order if clicked twice - if(sortBy == href_list["sort"]) - if(order == 1) - order = -1 - else - order = 1 - else - // New sorting order! - sortBy = href_list["sort"] - order = initial(order) -//BASIC FUNCTIONS - if("Clear Screen") - temp = null - - if ("Return") - screen = 1 - active1 = null - active2 = null - - if("Confirm Identity") - if (scan) - if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) - usr.put_in_hands(scan) - else - scan.loc = get_turf(src) - scan = null - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id)) - if(usr.drop_item(I, src)) - scan = I - - if("Log Out") - authenticated = null - screen = null - active1 = null - active2 = null - - if("Log In") - if (istype(usr, /mob/living/silicon)) - active1 = null - active2 = null - authenticated = 1 - rank = "AI" - screen = 1 - else if (istype(scan, /obj/item/weapon/card/id)) - active1 = null - active2 = null - if(check_access(scan)) - authenticated = scan.registered_name - rank = scan.assignment - screen = 1 -//RECORD FUNCTIONS - if("Search Records") - var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text - if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr))) - return - Perp = new/list() - t1 = lowertext(t1) - var/list/components = text2list(t1, " ") - if(components.len > 5) - return //Lets not let them search too greedily. - for(var/datum/data/record/R in data_core.general) - var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"] - for(var/i = 1, i<=components.len, i++) - if(findtext(temptext,components[i])) - var/prelist = new/list(2) - prelist[1] = R - Perp += prelist - for(var/i = 1, i<=Perp.len, i+=2) - for(var/datum/data/record/E in data_core.security) - var/datum/data/record/R = Perp[i] - if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) - Perp[i+1] = E - tempname = t1 - screen = 4 - - if("Record Maintenance") - screen = 2 - active1 = null - active2 = null - - if ("Browse Record") - var/datum/data/record/R = locate(href_list["d_rec"]) - var/S = locate(href_list["d_rec"]) - if (!( data_core.general.Find(R) )) - temp = "Record Not Found!" - else - for(var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - S = E - active1 = R - active2 = S - screen = 3 - -/* if ("Search Fingerprints") - var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text - if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!istype(usr, /mob/living/silicon)))) - return - active1 = null - active2 = null - t1 = lowertext(t1) - for(var/datum/data/record/R in data_core.general) - if (lowertext(R.fields["fingerprint"]) == t1) - active1 = R - if (!( active1 )) - temp = text("Could not locate record [].", t1) - else - for(var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"])) - active2 = E - screen = 3 */ - - if ("Print Record") - if (!( printing )) - printing = 1 - 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"]) - 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"]) - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - P.info += text("[]
      ", active2.fields[text("com_[]", counter)]) - counter++ - else - P.info += "Security Record Lost!
      " - P.info += "" - P.name = "paper - 'Security Record'" - printing = null -//RECORD DELETE - if ("Delete All Records") - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:346: temp = "" - temp = {" - Are you sure you wish to delete all Security records?
      - Yes
      - No"} - // END AUTOFIX - if ("Purge All Records") - for(var/datum/data/record/R in data_core.security) - qdel(R) - R = null - temp = "All Security records deleted." - - if ("Add Entry") - if (!( istype(active2, /datum/data/record) )) - return - var/a2 = active2 - var/t1 = copytext(sanitize(input("Add Comment:", "Secure. records", null, 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 - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - counter++ - active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053
      []", authenticated, rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1) - - if ("Delete Record (ALL)") - if (active1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:370: temp = "
      Are you sure you wish to delete the record (ALL)?
      " - temp = {"
      Are you sure you wish to delete the record (ALL)?
      - Yes
      - No"} - // END AUTOFIX - if ("Delete Record (Security)") - if (active2) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:376: temp = "
      Are you sure you wish to delete the record (Security Portion Only)?
      " - temp = {"
      Are you sure you wish to delete the record (Security Portion Only)?
      - Yes
      - No"} - // END AUTOFIX - if ("Delete Entry") - if ((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) - active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" -//RECORD CREATE - if ("New Record (Security)") - if ((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) ))) - var/datum/data/record/R = new /datum/data/record() - R.fields["name"] = active1.fields["name"] - R.fields["id"] = active1.fields["id"] - R.name = text("Security Record #[]", R.fields["id"]) - R.fields["criminal"] = "None" - R.fields["mi_crim"] = "None" - R.fields["mi_crim_d"] = "No minor crime convictions." - R.fields["ma_crim"] = "None" - R.fields["ma_crim_d"] = "No major crime convictions." - R.fields["notes"] = "No notes." - data_core.security += R - active2 = R - screen = 3 - - if ("New Record (General)") - var/datum/data/record/G = new /datum/data/record() - G.fields["name"] = "New Record" - G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) - G.fields["rank"] = "Unassigned" - G.fields["real_rank"] = "Unassigned" - G.fields["sex"] = "Male" - G.fields["age"] = "Unknown" - G.fields["fingerprint"] = "Unknown" - G.fields["p_stat"] = "Active" - G.fields["m_stat"] = "Stable" - G.fields["species"] = "Human" - data_core.general += G - active1 = G - active2 = null - -//FIELD FUNCTIONS - if ("Edit Field") - var/a1 = active1 - var/a2 = active2 - switch(href_list["field"]) - if("name") - if (istype(active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input name:", "Secure. records", active1.fields["name"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon)))) || active1 != a1) - return - active1.fields["name"] = t1 - if("id") - if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["id"] = t1 - if("fingerprint") - if (istype(active1, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["fingerprint"] = t1 - if("sex") - if (istype(active1, /datum/data/record)) - if (active1.fields["sex"] == "Male") - active1.fields["sex"] = "Female" - else - active1.fields["sex"] = "Male" - if("age") - if (istype(active1, /datum/data/record)) - var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) - return - active1.fields["age"] = t1 - if("mi_crim") - if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input minor crimes list:", "Secure. records", active2.fields["mi_crim"], null) as text),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["mi_crim"] = t1 - if("mi_crim_d") - if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize minor crimes:", "Secure. records", active2.fields["mi_crim_d"], 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["mi_crim_d"] = t1 - if("ma_crim") - if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input major crimes list:", "Secure. records", active2.fields["ma_crim"], null) as text),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["ma_crim"] = t1 - if("ma_crim_d") - if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize major crimes:", "Secure. records", active2.fields["ma_crim_d"], 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["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) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active2 != a2)) - return - active2.fields["notes"] = t1 - if("criminal") - if (istype(active2, /datum/data/record)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:483: temp = "
      Criminal Status:
      " - temp = {"
      Criminal Status:
      - "} - // END AUTOFIX - if("rank") - var/list/L = list( "Head of Personnel", "Captain", "AI" ) - //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N - if ((istype(active1, /datum/data/record) && L.Find(rank))) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:495: temp = "
      Rank:
      " - temp = {"
      Rank:
      -
        "} - // END AUTOFIX - for(var/rank in get_all_jobs()) - temp += "
      • [rank]
      • " - temp += "
      " - else - alert(usr, "You do not have the required rank to do this!") - if("species") - if (istype(active1, /datum/data/record)) - var/norange = (usr.mutations && usr.mutations.len && (M_TK in usr.mutations)) - var/t1 = copytext(sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message),1,MAX_MESSAGE_LEN) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon)) && !norange) || active1 != a1)) - return - active1.fields["species"] = t1 - -//TEMPORARY MENU FUNCTIONS - else//To properly clear as per clear screen. - temp=null - switch(href_list["choice"]) - if ("Change Rank") - if (active1) - active1.fields["rank"] = href_list["rank"] - if(href_list["rank"] in get_all_jobs()) - active1.fields["real_rank"] = href_list["real_rank"] - - if ("Change Criminal Status") - if (active2) - switch(href_list["criminal2"]) - if("none") - active2.fields["criminal"] = "None" - if("arrest") - active2.fields["criminal"] = "*Arrest*" - if("incarcerated") - active2.fields["criminal"] = "Incarcerated" - if("parolled") - active2.fields["criminal"] = "Parolled" - if("released") - active2.fields["criminal"] = "Released" - - if ("Delete Record (Security) Execute") - if (active2) - qdel(active2) - active2 = null - - if ("Delete Record (ALL) Execute") - if (active1) - for(var/datum/data/record/R in data_core.medical) - if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) - qdel(R) - R = null - else - qdel(active1) - active1 = null - if (active2) - qdel(active2) - active2 = null - else - temp = "This function does not appear to be working at the moment. Our apologies." - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/secure_data/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - - for(var/datum/data/record/R in data_core.security) - if(prob(10/severity)) - switch(rand(1,6)) - if(1) - R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]" - if(2) - R.fields["sex"] = pick("Male", "Female") - if(3) - R.fields["age"] = rand(5, 85) - if(4) - R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released") - if(5) - R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit") - if(6) - R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") - continue - - else if(prob(1)) - qdel(R) - R = null - continue - - ..(severity) - -/obj/machinery/computer/secure_data/detective_computer - icon = 'icons/obj/computer.dmi' - icon_state = "messyfiles" - - light_color = null +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/computer/secure_data//TODO:SANITY + name = "Security Records" + desc = "Used to view and edit personnel's security records" + icon_state = "security" + req_one_access = list(access_security, access_forensics_lockers) + circuit = "/obj/item/weapon/circuitboard/secure_data" + var/obj/item/weapon/card/id/scan = null + var/authenticated = null + var/rank = null + var/screen = null + var/datum/data/record/active1 = null + var/datum/data/record/active2 = null + var/a_id = null + var/temp = null + var/printing = null + var/can_change_id = 0 + var/list/Perp + var/tempname = null + //Sorting Variables + var/sortBy = "name" + var/order = 1 // -1 = Descending - 1 = Ascending + + light_color = LIGHT_COLOR_RED + +/obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob) + if(istype(O, /obj/item/weapon/card/id) && !scan) + if(usr.drop_item(O, src)) + scan = O + to_chat(user, "You insert \the [O].") + ..() + +/obj/machinery/computer/secure_data/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/computer/secure_data/attack_paw(mob/user as mob) + return attack_hand(user) + +//Someone needs to break down the dat += into chunks instead of long ass lines. +/obj/machinery/computer/secure_data/attack_hand(mob/user as mob) + if(..()) + return + if (src.z > 6) + to_chat(user, "Unable to establish a connection: You're too far away from the station!") + return + var/dat + + if (temp) + dat = text("[]

      Clear Screen", temp, src) + else + dat = text("Confirm Identity: []
      ", src, (scan ? text("[]", scan.name) : "----------")) + if (authenticated) + switch(screen) + if(1.0) + dat += {" +

      "} + dat += text("Search Records
      ", src) + dat += text("New Record
      ", src) + dat += {" +

      + + + + +
      Records:
      + + + + + + + +"} + if(!isnull(data_core.general)) + for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) + var/crimstat = "" + for(var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) + crimstat = E.fields["criminal"] + var/background + switch(crimstat) + if("*Arrest*") + background = "'background-color:#DC143C;'" + if("Incarcerated") + background = "'background-color:#CD853F;'" + if("Parolled") + background = "'background-color:#CD853F;'" + if("Released") + background = "'background-color:#3BB9FF;'" + if("None") + background = "'background-color:#00FF7F;'" + if("") + background = "'background-color:#FFFFFF;'" + crimstat = "No Record." + dat += text("", background, src, R, R.fields["name"]) + dat += text("", R.fields["id"]) + dat += text("", R.fields["rank"]) + dat += text("", R.fields["fingerprint"]) + dat += text("", crimstat) + dat += "
      NameIDRankFingerprintsCriminal Status
      [][][][][]

      " + dat += text("Record Maintenance

      ", src) + dat += text("{Log Out}",src) + if(2.0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:106: dat += "Records Maintenance
      " + dat += {"Records Maintenance
      +
      Delete All Records

      Back"} + // END AUTOFIX + if(3.0) + dat += "
      Security Record

      " + if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) + var/icon/front = new(active1.fields["photo"], dir = SOUTH) + var/icon/side = new(active1.fields["photo"], dir = WEST) + user << browse_rsc(front, "front.png") + user << browse_rsc(side, "side.png") + dat += text(" \ +
      \ + Name: [active1.fields["name"]]
      \ + ID: [active1.fields["id"]]
      \n \ + Sex: [active1.fields["sex"]]
      \n \ + Age: [active1.fields["age"]]
      \n \ + Rank: [active1.fields["rank"]]
      \n \ + Fingerprint: [active1.fields["fingerprint"]]
      \n \ + Physical Status: [active1.fields["p_stat"]]
      \n \ + Mental Status: [active1.fields["m_stat"]]
      Photo:
      \ +
      ") + 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"]) + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + dat += text("[]
      Delete Entry

      ", active2.fields[text("com_[]", counter)], src, counter) + counter++ + dat += text("Add Entry

      ", src) + dat += text("Delete Record (Security Only)

      ", src) + else + dat += "Security Record Lost!
      " + dat += text("New Security Record

      ", src) + dat += text("\nDelete Record (ALL)

      \nPrint Record
      \nBack
      ", src, src, src) + if(4.0) + if(!Perp.len) + dat += text("ERROR. String could not be located.

      Back", src) + else + dat += {" + + "} + dat += text("", tempname) + dat += {" + +
      Search Results for '[]':
      + + + + + + + + "} + for(var/i=1, i<=Perp.len, i += 2) + var/crimstat = "" + var/datum/data/record/R = Perp[i] + if(istype(Perp[i+1],/datum/data/record/)) + var/datum/data/record/E = Perp[i+1] + crimstat = E.fields["criminal"] + var/background + switch(crimstat) + if("*Arrest*") + background = "'background-color:#DC143C;'" + if("Incarcerated") + background = "'background-color:#CD853F;'" + if("Parolled") + background = "'background-color:#CD853F;'" + if("Released") + background = "'background-color:#3BB9FF;'" + if("None") + background = "'background-color:#00FF7F;'" + if("") + background = "'background-color:#FFFFFF;'" + crimstat = "No Record." + dat += text("", background, src, R, R.fields["name"]) + dat += text("", R.fields["id"]) + dat += text("", R.fields["rank"]) + dat += text("", R.fields["fingerprint"]) + dat += text("", crimstat) + dat += "
      NameIDRankFingerprintsCriminal Status
      [][][][][]

      " + dat += text("
      Return to index.", src) + else + else + dat += text("{Log In}", src) + user << browse(text("Security Records[]", dat), "window=secure_rec;size=600x400") + onclose(user, "secure_rec") + return + +/*Revised /N +I can't be bothered to look more of the actual code outside of switch but that probably needs revising too. +What a mess.*/ +/obj/machinery/computer/secure_data/Topic(href, href_list) + if(..()) + return + if (!( data_core.general.Find(active1) )) + active1 = null + if (!( data_core.security.Find(active2) )) + active2 = null + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + switch(href_list["choice"]) +// SORTING! + if("Sorting") + // Reverse the order if clicked twice + if(sortBy == href_list["sort"]) + if(order == 1) + order = -1 + else + order = 1 + else + // New sorting order! + sortBy = href_list["sort"] + order = initial(order) +//BASIC FUNCTIONS + if("Clear Screen") + temp = null + + if ("Return") + screen = 1 + active1 = null + active2 = null + + if("Confirm Identity") + if (scan) + if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + usr.put_in_hands(scan) + else + scan.loc = get_turf(src) + scan = null + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + if(usr.drop_item(I, src)) + scan = I + + if("Log Out") + authenticated = null + screen = null + active1 = null + active2 = null + + if("Log In") + if (istype(usr, /mob/living/silicon)) + active1 = null + active2 = null + authenticated = 1 + rank = "AI" + screen = 1 + else if (istype(scan, /obj/item/weapon/card/id)) + active1 = null + active2 = null + if(check_access(scan)) + authenticated = scan.registered_name + rank = scan.assignment + screen = 1 +//RECORD FUNCTIONS + if("Search Records") + var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text + if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr))) + return + Perp = new/list() + t1 = lowertext(t1) + var/list/components = text2list(t1, " ") + if(components.len > 5) + return //Lets not let them search too greedily. + for(var/datum/data/record/R in data_core.general) + var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"] + for(var/i = 1, i<=components.len, i++) + if(findtext(temptext,components[i])) + var/prelist = new/list(2) + prelist[1] = R + Perp += prelist + for(var/i = 1, i<=Perp.len, i+=2) + for(var/datum/data/record/E in data_core.security) + var/datum/data/record/R = Perp[i] + if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) + Perp[i+1] = E + tempname = t1 + screen = 4 + + if("Record Maintenance") + screen = 2 + active1 = null + active2 = null + + if ("Browse Record") + var/datum/data/record/R = locate(href_list["d_rec"]) + var/S = locate(href_list["d_rec"]) + if (!( data_core.general.Find(R) )) + temp = "Record Not Found!" + else + for(var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + S = E + active1 = R + active2 = S + screen = 3 + +/* if ("Search Fingerprints") + var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text + if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!istype(usr, /mob/living/silicon)))) + return + active1 = null + active2 = null + t1 = lowertext(t1) + for(var/datum/data/record/R in data_core.general) + if (lowertext(R.fields["fingerprint"]) == t1) + active1 = R + if (!( active1 )) + temp = text("Could not locate record [].", t1) + else + for(var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"])) + active2 = E + screen = 3 */ + + if ("Print Record") + if (!( printing )) + printing = 1 + 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"]) + 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"]) + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + P.info += text("[]
      ", active2.fields[text("com_[]", counter)]) + counter++ + else + P.info += "Security Record Lost!
      " + P.info += "" + P.name = "paper - 'Security Record'" + printing = null +//RECORD DELETE + if ("Delete All Records") + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:346: temp = "" + temp = {" + Are you sure you wish to delete all Security records?
      + Yes
      + No"} + // END AUTOFIX + if ("Purge All Records") + for(var/datum/data/record/R in data_core.security) + qdel(R) + R = null + temp = "All Security records deleted." + + if ("Add Entry") + if (!( istype(active2, /datum/data/record) )) + return + var/a2 = active2 + var/t1 = copytext(sanitize(input("Add Comment:", "Secure. records", null, 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 + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + counter++ + active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053
      []", authenticated, rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1) + + if ("Delete Record (ALL)") + if (active1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:370: temp = "
      Are you sure you wish to delete the record (ALL)?
      " + temp = {"
      Are you sure you wish to delete the record (ALL)?
      + Yes
      + No"} + // END AUTOFIX + if ("Delete Record (Security)") + if (active2) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:376: temp = "
      Are you sure you wish to delete the record (Security Portion Only)?
      " + temp = {"
      Are you sure you wish to delete the record (Security Portion Only)?
      + Yes
      + No"} + // END AUTOFIX + if ("Delete Entry") + if ((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) + active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" +//RECORD CREATE + if ("New Record (Security)") + if ((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) ))) + var/datum/data/record/R = new /datum/data/record() + R.fields["name"] = active1.fields["name"] + R.fields["id"] = active1.fields["id"] + R.name = text("Security Record #[]", R.fields["id"]) + R.fields["criminal"] = "None" + R.fields["mi_crim"] = "None" + R.fields["mi_crim_d"] = "No minor crime convictions." + R.fields["ma_crim"] = "None" + R.fields["ma_crim_d"] = "No major crime convictions." + R.fields["notes"] = "No notes." + data_core.security += R + active2 = R + screen = 3 + + if ("New Record (General)") + var/datum/data/record/G = new /datum/data/record() + G.fields["name"] = "New Record" + G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) + G.fields["rank"] = "Unassigned" + G.fields["real_rank"] = "Unassigned" + G.fields["sex"] = "Male" + G.fields["age"] = "Unknown" + G.fields["fingerprint"] = "Unknown" + G.fields["p_stat"] = "Active" + G.fields["m_stat"] = "Stable" + G.fields["species"] = "Human" + data_core.general += G + active1 = G + active2 = null + +//FIELD FUNCTIONS + if ("Edit Field") + var/a1 = active1 + var/a2 = active2 + switch(href_list["field"]) + if("name") + if (istype(active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input name:", "Secure. records", active1.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon)))) || active1 != a1) + return + active1.fields["name"] = t1 + if("id") + if (istype(active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["id"] = t1 + if("fingerprint") + if (istype(active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["fingerprint"] = t1 + if("sex") + if (istype(active1, /datum/data/record)) + if (active1.fields["sex"] == "Male") + active1.fields["sex"] = "Female" + else + active1.fields["sex"] = "Male" + if("age") + if (istype(active1, /datum/data/record)) + var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["age"] = t1 + if("mi_crim") + if (istype(active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input minor crimes list:", "Secure. records", active2.fields["mi_crim"], null) as text),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["mi_crim"] = t1 + if("mi_crim_d") + if (istype(active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please summarize minor crimes:", "Secure. records", active2.fields["mi_crim_d"], 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["mi_crim_d"] = t1 + if("ma_crim") + if (istype(active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input major crimes list:", "Secure. records", active2.fields["ma_crim"], null) as text),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["ma_crim"] = t1 + if("ma_crim_d") + if (istype(active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please summarize major crimes:", "Secure. records", active2.fields["ma_crim_d"], 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["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) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active2 != a2)) + return + active2.fields["notes"] = t1 + if("criminal") + if (istype(active2, /datum/data/record)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:483: temp = "
      Criminal Status:
      " + temp = {"
      Criminal Status:
      + "} + // END AUTOFIX + if("rank") + var/list/L = list( "Head of Personnel", "Captain", "AI" ) + //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N + if ((istype(active1, /datum/data/record) && L.Find(rank))) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\security.dm:495: temp = "
      Rank:
      " + temp = {"
      Rank:
      +
        "} + // END AUTOFIX + for(var/rank in get_all_jobs()) + temp += "
      • [rank]
      • " + temp += "
      " + else + alert(usr, "You do not have the required rank to do this!") + if("species") + if (istype(active1, /datum/data/record)) + var/norange = (usr.mutations && usr.mutations.len && (M_TK in usr.mutations)) + var/t1 = copytext(sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon)) && !norange) || active1 != a1)) + return + active1.fields["species"] = t1 + +//TEMPORARY MENU FUNCTIONS + else//To properly clear as per clear screen. + temp=null + switch(href_list["choice"]) + if ("Change Rank") + if (active1) + active1.fields["rank"] = href_list["rank"] + if(href_list["rank"] in get_all_jobs()) + active1.fields["real_rank"] = href_list["real_rank"] + + if ("Change Criminal Status") + if (active2) + switch(href_list["criminal2"]) + if("none") + active2.fields["criminal"] = "None" + if("arrest") + active2.fields["criminal"] = "*Arrest*" + if("incarcerated") + active2.fields["criminal"] = "Incarcerated" + if("parolled") + active2.fields["criminal"] = "Parolled" + if("released") + active2.fields["criminal"] = "Released" + + if ("Delete Record (Security) Execute") + if (active2) + qdel(active2) + active2 = null + + if ("Delete Record (ALL) Execute") + if (active1) + for(var/datum/data/record/R in data_core.medical) + if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) + qdel(R) + R = null + else + qdel(active1) + active1 = null + if (active2) + qdel(active2) + active2 = null + else + temp = "This function does not appear to be working at the moment. Our apologies." + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/secure_data/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + for(var/datum/data/record/R in data_core.security) + if(prob(10/severity)) + switch(rand(1,6)) + if(1) + R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]" + if(2) + R.fields["sex"] = pick("Male", "Female") + if(3) + R.fields["age"] = rand(5, 85) + if(4) + R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released") + if(5) + R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit") + if(6) + R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") + continue + + else if(prob(1)) + qdel(R) + R = null + continue + + ..(severity) + +/obj/machinery/computer/secure_data/detective_computer + icon = 'icons/obj/computer.dmi' + icon_state = "messyfiles" + + light_color = null diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm index a9b012739bc..bb3ecb865c1 100644 --- a/code/game/machinery/computer/shuttle.dm +++ b/code/game/machinery/computer/shuttle.dm @@ -1,76 +1,76 @@ -/obj/machinery/computer/shuttle - name = "Shuttle" - desc = "For shuttle control." - icon_state = "shuttle" - var/auth_need = 3.0 - var/list/authorized = list( ) - - light_color = LIGHT_COLOR_CYAN - - attackby(var/obj/item/weapon/card/W as obj, var/mob/user as mob) - if(stat & (BROKEN|NOPOWER)) return - ..() - if ((!( istype(W, /obj/item/weapon/card) ) || !( ticker ) || emergency_shuttle.location != 1 || !( user ))) return - if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (istype(W, /obj/item/device/pda)) - var/obj/item/device/pda/pda = W - W = pda.id - if (!W:access) //no access +/obj/machinery/computer/shuttle + name = "Shuttle" + desc = "For shuttle control." + icon_state = "shuttle" + var/auth_need = 3.0 + var/list/authorized = list( ) + + light_color = LIGHT_COLOR_CYAN + + attackby(var/obj/item/weapon/card/W as obj, var/mob/user as mob) + if(stat & (BROKEN|NOPOWER)) return + ..() + if ((!( istype(W, /obj/item/weapon/card) ) || !( ticker ) || emergency_shuttle.location != 1 || !( user ))) return + if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (istype(W, /obj/item/device/pda)) + var/obj/item/device/pda/pda = W + W = pda.id + if (!W:access) //no access to_chat(user, "The access level of [W:registered_name]\'s card is not high enough. ") - return - - var/list/cardaccess = W:access - if(!istype(cardaccess, /list) || !cardaccess.len) //no access + return + + var/list/cardaccess = W:access + if(!istype(cardaccess, /list) || !cardaccess.len) //no access to_chat(user, "The access level of [W:registered_name]\'s card is not high enough. ") - return - - if(!(access_heads in W:access)) //doesn't have this access + return + + if(!(access_heads in W:access)) //doesn't have this access to_chat(user, "The access level of [W:registered_name]\'s card is not high enough. ") - return 0 - - var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort") - if(emergency_shuttle.location != 1 && user.get_active_hand() != W) - return 0 - switch(choice) - if("Authorize") - src.authorized -= W:registered_name - src.authorized += W:registered_name - if (src.auth_need - src.authorized.len > 0) - message_admins("[key_name_admin(user)] has authorized early shuttle launch") - log_game("[user.ckey] has authorized early shuttle launch") + return 0 + + var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort") + if(emergency_shuttle.location != 1 && user.get_active_hand() != W) + return 0 + switch(choice) + if("Authorize") + src.authorized -= W:registered_name + src.authorized += W:registered_name + if (src.auth_need - src.authorized.len > 0) + message_admins("[key_name_admin(user)] has authorized early shuttle launch") + log_game("[user.ckey] has authorized early shuttle launch") to_chat(world, text("Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)) - else - message_admins("[key_name_admin(user)] has launched the shuttle") - log_game("[user.ckey] has launched the shuttle early") + else + message_admins("[key_name_admin(user)] has launched the shuttle") + log_game("[user.ckey] has launched the shuttle early") to_chat(world, "Alert: Shuttle launch time shortened to 10 seconds!") - emergency_shuttle.online = 1 - emergency_shuttle.settimeleft(10) - //src.authorized = null - del(src.authorized) - src.authorized = list( ) - - if("Repeal") - src.authorized -= W:registered_name + emergency_shuttle.online = 1 + emergency_shuttle.settimeleft(10) + //src.authorized = null + del(src.authorized) + src.authorized = list( ) + + if("Repeal") + src.authorized -= W:registered_name to_chat(world, text("Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)) - - if("Abort") + + if("Abort") to_chat(world, "All authorizations to shortening time for shuttle launch have been revoked!") - src.authorized.len = 0 - src.authorized = list( ) - return - -/obj/machinery/computer/shuttle/emag(mob/user as mob) - if(!emagged) - new/obj/effect/effect/sparks(get_turf(src)) - playsound(loc,"sparks",50,1) - var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel") - if(emergency_shuttle.location == 1) - switch(choice) - if("Launch") + src.authorized.len = 0 + src.authorized = list( ) + return + +/obj/machinery/computer/shuttle/emag(mob/user as mob) + if(!emagged) + new/obj/effect/effect/sparks(get_turf(src)) + playsound(loc,"sparks",50,1) + var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel") + if(emergency_shuttle.location == 1) + switch(choice) + if("Launch") to_chat(world, "Alert: Shuttle launch time shortened to 10 seconds!") - emergency_shuttle.settimeleft( 10 ) - emagged = 1 - return 1 - if("Cancel") - return - return + emergency_shuttle.settimeleft( 10 ) + emagged = 1 + return 1 + if("Cancel") + return + return diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm index 4812b86e697..c48542aa23d 100644 --- a/code/game/machinery/computer/specops_shuttle.dm +++ b/code/game/machinery/computer/specops_shuttle.dm @@ -1,589 +1,589 @@ -//Config stuff -#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station -#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock -#define SPECOPS_RETURN_DELAY 6000 //Time between the shuttle is capable of moving. - -var/specops_shuttle_moving_to_station = 0 -var/specops_shuttle_moving_to_centcom = 0 -var/specops_shuttle_at_station = 0 -var/specops_shuttle_can_send = 1 -var/specops_shuttle_time = 0 -var/specops_shuttle_timeleft = 0 - -/obj/machinery/computer/specops_shuttle - name = "Spec. Ops. Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_cent_specops,access_cent_ert) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - var/specops_shuttle_timereset = 0 - - light_color = LIGHT_COLOR_CYAN - -/proc/specops_return() - var/obj/item/device/radio/intercom/announcer = announcement_intercom - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN\""//Initial message shown. - if(announcer) - AliceAnnounce(announcer, message) - - - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" - if(rounded_time_left==0) - message = "\"ALERT: TAKEOFF\"" - AliceAnnounce(announcer, message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 - - specops_shuttle_at_station = 1 - - var/area/start_location = locate(/area/shuttle/specops/station) - var/area/end_location = locate(/area/shuttle/specops/centcom) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - T = null - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T +//Config stuff +#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. +#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station +#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock +#define SPECOPS_RETURN_DELAY 6000 //Time between the shuttle is capable of moving. + +var/specops_shuttle_moving_to_station = 0 +var/specops_shuttle_moving_to_centcom = 0 +var/specops_shuttle_at_station = 0 +var/specops_shuttle_can_send = 1 +var/specops_shuttle_time = 0 +var/specops_shuttle_timeleft = 0 + +/obj/machinery/computer/specops_shuttle + name = "Spec. Ops. Shuttle Console" + icon = 'icons/obj/computer.dmi' + icon_state = "shuttle" + req_access = list(access_cent_specops,access_cent_ert) + var/temp = null + var/hacked = 0 + var/allowedtocall = 0 + var/specops_shuttle_timereset = 0 + + light_color = LIGHT_COLOR_CYAN + +/proc/specops_return() + var/obj/item/device/radio/intercom/announcer = announcement_intercom + + var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. + var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN\""//Initial message shown. + if(announcer) + AliceAnnounce(announcer, message) + + + while(specops_shuttle_time - world.timeofday > 0) + var/ticksleft = specops_shuttle_time - world.timeofday + + if(ticksleft > 1e5) + specops_shuttle_time = world.timeofday + 10 // midnight rollover + specops_shuttle_timeleft = (ticksleft / 10) + + //All this does is announce the time before launch. + if(announcer) + var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + if(rounded_time_left in message_tracker)//If that time is in the list for message announce. + message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" + if(rounded_time_left==0) + message = "\"ALERT: TAKEOFF\"" + AliceAnnounce(announcer, message) + message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. + //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. + + sleep(5) + + specops_shuttle_moving_to_station = 0 + specops_shuttle_moving_to_centcom = 0 + + specops_shuttle_at_station = 1 + + var/area/start_location = locate(/area/shuttle/specops/station) + var/area/end_location = locate(/area/shuttle/specops/centcom) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + T = null + + start_location.move_contents_to(end_location) + + for(var/turf/T in get_area_turfs(end_location) ) + var/mob/M = locate(/mob) in T to_chat(M, "You have arrived at Central Command. Operation has ended!") - - specops_shuttle_at_station = 0 - - for(var/obj/machinery/computer/specops_shuttle/S in machines) - S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY - - qdel(announcer) - announcer = null -/proc/AliceAnnounce(var/atom/movable/announcer,var/message) - var/datum/speech/speech = announcer.create_speech(message=message, frequency=radiochannels["Response Team"], transmitter=announcer) - //speech.name="A.L.I.C.E." - speech.job="Response Team" - Broadcast_Message(speech, - data=0, - compression=0, - level=list(0,1)) - returnToPool(speech) - -/proc/specops_process() - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/obj/item/device/radio/intercom/announcer = announcement_intercom - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH\""//Initial message shown. - if(announcer) - AliceAnnounce(announcer, message) -// message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" -// announcer.autosay(message, "A.L.I.C.E.", "A.L.I.C.E.") - - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" - if(rounded_time_left==0) - message = "\"ALERT: TAKEOFF\"" - AliceAnnounce(announcer, message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 - - specops_shuttle_at_station = 1 - if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) + + specops_shuttle_at_station = 0 + + for(var/obj/machinery/computer/specops_shuttle/S in machines) + S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + qdel(announcer) + announcer = null +/proc/AliceAnnounce(var/atom/movable/announcer,var/message) + var/datum/speech/speech = announcer.create_speech(message=message, frequency=radiochannels["Response Team"], transmitter=announcer) + //speech.name="A.L.I.C.E." + speech.job="Response Team" + Broadcast_Message(speech, + data=0, + compression=0, + level=list(0,1)) + returnToPool(speech) + +/proc/specops_process() + var/area/centcom/specops/special_ops = locate()//Where is the specops area located? + var/obj/item/device/radio/intercom/announcer = announcement_intercom + + var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. + var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH\""//Initial message shown. + if(announcer) + AliceAnnounce(announcer, message) +// message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" +// announcer.autosay(message, "A.L.I.C.E.", "A.L.I.C.E.") + + while(specops_shuttle_time - world.timeofday > 0) + var/ticksleft = specops_shuttle_time - world.timeofday + + if(ticksleft > 1e5) + specops_shuttle_time = world.timeofday + 10 // midnight rollover + specops_shuttle_timeleft = (ticksleft / 10) + + //All this does is announce the time before launch. + if(announcer) + var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + if(rounded_time_left in message_tracker)//If that time is in the list for message announce. + message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" + if(rounded_time_left==0) + message = "\"ALERT: TAKEOFF\"" + AliceAnnounce(announcer, message) + message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. + //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. + + sleep(5) + + specops_shuttle_moving_to_station = 0 + specops_shuttle_moving_to_centcom = 0 + + specops_shuttle_at_station = 1 + if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + + if (!specops_can_move()) to_chat(usr, "The Special Operations shuttle is unable to leave.") - return - - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id_tag) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in special_ops) - switch(M.id_tag) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id_tag)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - special_ops.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. - - var/area/start_location = locate(/area/shuttle/specops/centcom) - var/area/end_location = locate(/area/shuttle/specops/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - T = null - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T + return + + //Begin Marauder launchpad. + spawn(0)//So it parallel processes it. + for(var/obj/machinery/door/poddoor/M in special_ops) + switch(M.id_tag) + if("ASSAULT0") + spawn(10)//1 second delay between each. + M.open() + if("ASSAULT1") + spawn(20) + M.open() + if("ASSAULT2") + spawn(30) + M.open() + if("ASSAULT3") + spawn(40) + M.open() + + sleep(10) + + var/spawn_marauder[] = new() + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "Marauder Entry") + spawn_marauder.Add(L) + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "Marauder Exit") + var/obj/effect/portal/P = new(L.loc) + P.invisibility = 101//So it is not seen by anyone. + P.target = pick(spawn_marauder)//Where the marauder will arrive. + spawn_marauder.Remove(P.target) + + sleep(10) + + for(var/obj/machinery/mass_driver/M in special_ops) + switch(M.id_tag) + if("ASSAULT0") + spawn(10) + M.drive() + if("ASSAULT1") + spawn(20) + M.drive() + if("ASSAULT2") + spawn(30) + M.drive() + if("ASSAULT3") + spawn(40) + M.drive() + + sleep(50)//Doors remain open for 5 seconds. + + for(var/obj/machinery/door/poddoor/M in special_ops) + switch(M.id_tag)//Doors close at the same time. + if("ASSAULT0") + spawn(0) + M.close() + if("ASSAULT1") + spawn(0) + M.close() + if("ASSAULT2") + spawn(0) + M.close() + if("ASSAULT3") + spawn(0) + M.close() + special_ops.readyreset()//Reset firealarm after the team launched. + //End Marauder launchpad. + + var/area/start_location = locate(/area/shuttle/specops/centcom) + var/area/end_location = locate(/area/shuttle/specops/station) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + T = null + + start_location.move_contents_to(end_location) + + for(var/turf/T in get_area_turfs(end_location) ) + var/mob/M = locate(/mob) in T to_chat(M, "You have arrived to [station_name]. Commence operation!") - - for(var/obj/machinery/computer/specops_shuttle/S in machines) - S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY - - qdel(announcer) - -/proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) - return 0 - for(var/obj/machinery/computer/specops_shuttle/S in machines) - if(world.timeofday <= S.specops_shuttle_timereset) - return 0 - return 1 - -/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/emag(mob/user as mob) + + for(var/obj/machinery/computer/specops_shuttle/S in machines) + S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + qdel(announcer) + +/proc/specops_can_move() + if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) + return 0 + for(var/obj/machinery/computer/specops_shuttle/S in machines) + if(world.timeofday <= S.specops_shuttle_timereset) + return 0 + return 1 + +/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/specops_shuttle/emag(mob/user as mob) to_chat(user, "The electronic systems in this console are far too advanced for your primitive hacking peripherals.") - return - -/obj/machinery/computer/specops_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) + return + +/obj/machinery/computer/specops_shuttle/attack_hand(var/mob/user as mob) + if(!allowed(user)) to_chat(user, "Access Denied.") - return - - if (sent_strike_team == 0 && send_emergency_team == 0) + return + + if (sent_strike_team == 0 && send_emergency_team == 0) to_chat(usr, "The strike team has not yet deployed.") - return - - if(..()) - return - - user.machine = src - var/dat - if (temp) - dat = temp - else - dat += {"
      Special Operations Shuttle
      - \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
      - [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
      \n
      ":specops_shuttle_at_station ? "\nShuttle standing by...
      \n
      ":"\nDepart to [station_name]
      \n
      "] - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/specops_shuttle/Topic(href, href_list) - if(..()) - return - - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.machine = src - - if (href_list["sendtodock"]) - if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) + return + + if(..()) + return + + user.machine = src + var/dat + if (temp) + dat = temp + else + dat += {"
      Special Operations Shuttle
      + \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
      + [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
      \n
      ":specops_shuttle_at_station ? "\nShuttle standing by...
      \n
      ":"\nDepart to [station_name]
      \n
      "] + \nClose"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + +/obj/machinery/computer/specops_shuttle/Topic(href, href_list) + if(..()) + return + + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.machine = src + + if (href_list["sendtodock"]) + if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + + if (!specops_can_move()) to_chat(usr, "Central Command will not allow the Special Operations shuttle to return yet.") - if(world.timeofday <= specops_shuttle_timereset) - if (((world.timeofday - specops_shuttle_timereset)/10) > 60) + if(world.timeofday <= specops_shuttle_timereset) + if (((world.timeofday - specops_shuttle_timereset)/10) > 60) to_chat(usr, "[-((world.timeofday - specops_shuttle_timereset)/10)/60] minutes remain!") to_chat(usr, "[-(world.timeofday - specops_shuttle_timereset)/10] seconds remain!") - return - + return + to_chat(usr, "The Special Operations shuttle will arrive at Central Command in [(SPECOPS_MOVETIME/10)] seconds.") - - temp += "Shuttle departing.

      OK" - updateUsrDialog() - - specops_shuttle_moving_to_centcom = 1 - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_return() - - else if (href_list["sendtostation"]) - if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) + + temp += "Shuttle departing.

      OK" + updateUsrDialog() + + specops_shuttle_moving_to_centcom = 1 + specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + spawn(0) + specops_return() + + else if (href_list["sendtostation"]) + if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + + if (!specops_can_move()) to_chat(usr, "The Special Operations shuttle is unable to leave.") - return - + return + to_chat(usr, "The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds.") - - temp += "Shuttle departing.

      OK" - updateUsrDialog() - - var/area/centcom/specops/special_ops = locate() - if(special_ops) - special_ops.readyalert()//Trigger alarm for the spec ops area. - specops_shuttle_moving_to_station = 1 - - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_process() - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - -/*//Config stuff -#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station -#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock - -var/specops_shuttle_moving_to_station = 0 -var/specops_shuttle_moving_to_centcom = 0 -var/specops_shuttle_at_station = 0 -var/specops_shuttle_can_send = 1 -var/specops_shuttle_time = 0 -var/specops_shuttle_timeleft = 0 - -/obj/machinery/computer/specops_shuttle - name = "Spec. Ops. Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - -/proc/specops_process() - var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work. - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/obj/item/device/radio/intercom/announcer = announcement_intercom - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. - if(announcer) - Broadcast_Message(announcer, null, null, announcer, message, "A.L.I.C.E.", "A.L.I.C.E.", "A.L.I.C.E.", 0, 0, list(0,1), radiochannels["Response Team"]) - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - Broadcast_Message(announcer, null, null, announcer, message, "A.L.I.C.E.", "A.L.I.C.E.", "A.L.I.C.E."", 0, 0, list(0,1), radiochannels["Response Team"]) - - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" - if(rounded_time_left==0) - message = "ALERT: TAKEOFF" - Broadcast_Message(announcer, null, null, announcer, message, "A.L.I.C.E.", "Response Team", "A.L.I.C.E.", 0, 0, list(0,1), radiochannels["Response Team"]) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 - - specops_shuttle_at_station = 1 - if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) + + temp += "Shuttle departing.

      OK" + updateUsrDialog() + + var/area/centcom/specops/special_ops = locate() + if(special_ops) + special_ops.readyalert()//Trigger alarm for the spec ops area. + specops_shuttle_moving_to_station = 1 + + specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + spawn(0) + specops_process() + + else if (href_list["mainmenu"]) + temp = null + + add_fingerprint(usr) + updateUsrDialog() + return + +/*//Config stuff +#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. +#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station +#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock + +var/specops_shuttle_moving_to_station = 0 +var/specops_shuttle_moving_to_centcom = 0 +var/specops_shuttle_at_station = 0 +var/specops_shuttle_can_send = 1 +var/specops_shuttle_time = 0 +var/specops_shuttle_timeleft = 0 + +/obj/machinery/computer/specops_shuttle + name = "Spec. Ops. Shuttle Console" + icon = 'icons/obj/computer.dmi' + icon_state = "shuttle" + req_access = list(access_cent_specops) + var/temp = null + var/hacked = 0 + var/allowedtocall = 0 + +/proc/specops_process() + var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work. + var/area/centcom/specops/special_ops = locate()//Where is the specops area located? + var/obj/item/device/radio/intercom/announcer = announcement_intercom + + var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. + var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. + if(announcer) + Broadcast_Message(announcer, null, null, announcer, message, "A.L.I.C.E.", "A.L.I.C.E.", "A.L.I.C.E.", 0, 0, list(0,1), radiochannels["Response Team"]) + message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" + Broadcast_Message(announcer, null, null, announcer, message, "A.L.I.C.E.", "A.L.I.C.E.", "A.L.I.C.E."", 0, 0, list(0,1), radiochannels["Response Team"]) + + while(specops_shuttle_time - world.timeofday > 0) + var/ticksleft = specops_shuttle_time - world.timeofday + + if(ticksleft > 1e5) + specops_shuttle_time = world.timeofday + 10 // midnight rollover + specops_shuttle_timeleft = (ticksleft / 10) + + //All this does is announce the time before launch. + if(announcer) + var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + if(rounded_time_left in message_tracker)//If that time is in the list for message announce. + message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" + if(rounded_time_left==0) + message = "ALERT: TAKEOFF" + Broadcast_Message(announcer, null, null, announcer, message, "A.L.I.C.E.", "Response Team", "A.L.I.C.E.", 0, 0, list(0,1), radiochannels["Response Team"]) + message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. + //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. + + sleep(5) + + specops_shuttle_moving_to_station = 0 + specops_shuttle_moving_to_centcom = 0 + + specops_shuttle_at_station = 1 + if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + + if (!specops_can_move()) to_chat(usr, "The Special Operations shuttle is unable to leave.") - return - - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - special_ops.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. - - var/area/start_location = locate(/area/shuttle/specops/centcom) - var/area/end_location = locate(/area/shuttle/specops/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T + return + + //Begin Marauder launchpad. + spawn(0)//So it parallel processes it. + for(var/obj/machinery/door/poddoor/M in special_ops) + switch(M.id) + if("ASSAULT0") + spawn(10)//1 second delay between each. + M.open() + if("ASSAULT1") + spawn(20) + M.open() + if("ASSAULT2") + spawn(30) + M.open() + if("ASSAULT3") + spawn(40) + M.open() + + sleep(10) + + var/spawn_marauder[] = new() + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "Marauder Entry") + spawn_marauder.Add(L) + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "Marauder Exit") + var/obj/effect/portal/P = new(L.loc) + P.invisibility = 101//So it is not seen by anyone. + P.failchance = 0//So it has no fail chance when teleporting. + P.target = pick(spawn_marauder)//Where the marauder will arrive. + spawn_marauder.Remove(P.target) + + sleep(10) + + for(var/obj/machinery/mass_driver/M in special_ops) + switch(M.id) + if("ASSAULT0") + spawn(10) + M.drive() + if("ASSAULT1") + spawn(20) + M.drive() + if("ASSAULT2") + spawn(30) + M.drive() + if("ASSAULT3") + spawn(40) + M.drive() + + sleep(50)//Doors remain open for 5 seconds. + + for(var/obj/machinery/door/poddoor/M in special_ops) + switch(M.id)//Doors close at the same time. + if("ASSAULT0") + spawn(0) + M.close() + if("ASSAULT1") + spawn(0) + M.close() + if("ASSAULT2") + spawn(0) + M.close() + if("ASSAULT3") + spawn(0) + M.close() + special_ops.readyreset()//Reset firealarm after the team launched. + //End Marauder launchpad. + + var/area/start_location = locate(/area/shuttle/specops/centcom) + var/area/end_location = locate(/area/shuttle/specops/station) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + + start_location.move_contents_to(end_location) + + for(var/turf/T in get_area_turfs(end_location) ) + var/mob/M = locate(/mob) in T to_chat(M, "You have arrived to [station_name]. Commence operation!") - -/proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0 - else return 1 - -/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) - if(istype(I,/obj/item/weapon/card/emag)) + +/proc/specops_can_move() + if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0 + else return 1 + +/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) + return attack_hand(user) + +/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) + if(istype(I,/obj/item/weapon/card/emag)) to_chat(user, "The electronic systems in this console are far too advanced for your primitive hacking peripherals.") - else - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) + else + return attack_hand(user) + +/obj/machinery/computer/specops_shuttle/attack_hand(var/mob/user as mob) + if(!allowed(user)) to_chat(user, "Access Denied.") - return - -// if (sent_strike_team == 0) + return + +// if (sent_strike_team == 0) // to_chat(usr, "The strike team has not yet deployed.") -// return - - if(..()) - return - - user.set_machine(src) - var/dat - if (temp) - dat = temp - else - dat += {"
      Special Operations Shuttle
      - \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
      - [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
      \n
      ":specops_shuttle_at_station ? "\nShuttle Offline
      \n
      ":"\nDepart to [station_name]
      \n
      "] - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/specops_shuttle/Topic(href, href_list) - if(..()) - return 1 - - usr.set_machine(src) - - if (href_list["sendtodock"]) - if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - +// return + + if(..()) + return + + user.set_machine(src) + var/dat + if (temp) + dat = temp + else + dat += {"
      Special Operations Shuttle
      + \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
      + [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
      \n
      ":specops_shuttle_at_station ? "\nShuttle Offline
      \n
      ":"\nDepart to [station_name]
      \n
      "] + \nClose"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + +/obj/machinery/computer/specops_shuttle/Topic(href, href_list) + if(..()) + return 1 + + usr.set_machine(src) + + if (href_list["sendtodock"]) + if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + to_chat(usr, "Central Command will not allow the Special Operations shuttle to return.") - return - - else if (href_list["sendtostation"]) - if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) + return + + else if (href_list["sendtostation"]) + if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + + if (!specops_can_move()) to_chat(usr, "The Special Operations shuttle is unable to leave.") - return - + return + to_chat(usr, "The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds.") - - temp += "Shuttle departing.

      OK" - updateUsrDialog() - - var/area/centcom/specops/special_ops = locate() - if(special_ops) - if(special_ops.master) - special_ops=special_ops.master - special_ops.readyalert()//Trigger alarm for the spec ops area. - specops_shuttle_moving_to_station = 1 - - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_process() - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - */ + + temp += "Shuttle departing.

      OK" + updateUsrDialog() + + var/area/centcom/specops/special_ops = locate() + if(special_ops) + if(special_ops.master) + special_ops=special_ops.master + special_ops.readyalert()//Trigger alarm for the spec ops area. + specops_shuttle_moving_to_station = 1 + + specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + spawn(0) + specops_process() + + else if (href_list["mainmenu"]) + temp = null + + add_fingerprint(usr) + updateUsrDialog() + return + */ diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 75ac3e3d05c..40aab9d231e 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -1,155 +1,155 @@ - -/obj/machinery/computer/station_alert - name = "Station Alert Computer" - desc = "Used to access the station's automated alert system." - icon_state = "alert:0" - circuit = "/obj/item/weapon/circuitboard/stationalert" - light_color = LIGHT_COLOR_CYAN - - var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list()) - - var/list/covered_areas = list() - - var/general_area_name = "Station" - -/obj/machinery/computer/station_alert/New() - ..() - if(src.z != map.zMainStation) - var/area/A = src.areaMaster - if(!A) - A = get_area(src) - if(!A) - return - name = "[A.general_area_name] Alert Computer" - general_area_name = A.general_area_name - - for(var/areatype in typesof(A.general_area)) - var/area/B = locate(areatype) - - covered_areas += B - - else//very ugly fix until all the main station's areas inherit from /area/station/ - var/blockedtypes = typesof(/area/research_outpost,/area/mine,/area/derelict,/area/djstation,/area/vox_trading_post,/area/tcommsat) - for(var/atype in (typesof(/area) - blockedtypes)) - var/area/B = locate(atype) - - covered_areas += B - - for(var/area/A in covered_areas) - A.sendDangerLevel(src) - A.send_firealert(src) - A.send_poweralert(src) - -/obj/machinery/computer/station_alert/attack_ai(mob/user) - src.add_hiddenprint(user) - add_fingerprint(user) - if(stat & (BROKEN|NOPOWER)) - return - interact(user) - return - - -/obj/machinery/computer/station_alert/attack_hand(mob/user) - add_fingerprint(user) - if(stat & (BROKEN|NOPOWER)) - return - interact(user) - return - - -/obj/machinery/computer/station_alert/interact(mob/user) - usr.set_machine(src) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\station_alert.dm:29: var/dat = "Current Station Alerts\n" - var/dat = {"Current [general_area_name] Alerts\n - Close

      "} - // END AUTOFIX - for (var/cat in src.alarms) - dat += text("[]
      \n", cat) - var/list/L = src.alarms[cat] - if (L.len) - for (var/alarm in L) - var/list/alm = L[alarm] - var/area/A = alm[1] - var/list/sources = alm[3] - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\station_alert.dm:39: dat += "" - dat += {" - • - [A.name]"} - // END AUTOFIX - if (sources.len > 1) - dat += text(" - [] sources", sources.len) - dat += "
      \n" - else - dat += "-- All Systems Nominal
      \n" - dat += "
      \n" - user << browse(dat, "window=alerts") - onclose(user, "alerts") - - -/obj/machinery/computer/station_alert/Topic(href, href_list) - if(..()) - return - return - - -/obj/machinery/computer/station_alert/proc/triggerAlarm(var/class, area/A, var/O, var/alarmsource) - if(stat & (BROKEN)) - return - var/list/L = src.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)) - return 1 - - -/obj/machinery/computer/station_alert/proc/cancelAlarm(var/class, area/A as area, obj/origin) - if(stat & (BROKEN)) - return - var/list/L = src.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 - return !cleared - - -/obj/machinery/computer/station_alert/process() - if(stat & NOPOWER) - icon_state = "atmos0" - return - else if(stat & BROKEN) - icon_state = "atmosb" - return - var/active_alarms = 0 - for (var/cat in src.alarms) - var/list/L = src.alarms[cat] - if(L.len) active_alarms = 1 - if(active_alarms) - icon_state = "alert:2" - else - icon_state = "alert:0" - ..() - return + +/obj/machinery/computer/station_alert + name = "Station Alert Computer" + desc = "Used to access the station's automated alert system." + icon_state = "alert:0" + circuit = "/obj/item/weapon/circuitboard/stationalert" + light_color = LIGHT_COLOR_CYAN + + var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list()) + + var/list/covered_areas = list() + + var/general_area_name = "Station" + +/obj/machinery/computer/station_alert/New() + ..() + if(src.z != map.zMainStation) + var/area/A = src.areaMaster + if(!A) + A = get_area(src) + if(!A) + return + name = "[A.general_area_name] Alert Computer" + general_area_name = A.general_area_name + + for(var/areatype in typesof(A.general_area)) + var/area/B = locate(areatype) + + covered_areas += B + + else//very ugly fix until all the main station's areas inherit from /area/station/ + var/blockedtypes = typesof(/area/research_outpost,/area/mine,/area/derelict,/area/djstation,/area/vox_trading_post,/area/tcommsat) + for(var/atype in (typesof(/area) - blockedtypes)) + var/area/B = locate(atype) + + covered_areas += B + + for(var/area/A in covered_areas) + A.sendDangerLevel(src) + A.send_firealert(src) + A.send_poweralert(src) + +/obj/machinery/computer/station_alert/attack_ai(mob/user) + src.add_hiddenprint(user) + add_fingerprint(user) + if(stat & (BROKEN|NOPOWER)) + return + interact(user) + return + + +/obj/machinery/computer/station_alert/attack_hand(mob/user) + add_fingerprint(user) + if(stat & (BROKEN|NOPOWER)) + return + interact(user) + return + + +/obj/machinery/computer/station_alert/interact(mob/user) + usr.set_machine(src) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\station_alert.dm:29: var/dat = "Current Station Alerts\n" + var/dat = {"Current [general_area_name] Alerts\n + Close

      "} + // END AUTOFIX + for (var/cat in src.alarms) + dat += text("[]
      \n", cat) + var/list/L = src.alarms[cat] + if (L.len) + for (var/alarm in L) + var/list/alm = L[alarm] + var/area/A = alm[1] + var/list/sources = alm[3] + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\computer\station_alert.dm:39: dat += "" + dat += {" + • + [A.name]"} + // END AUTOFIX + if (sources.len > 1) + dat += text(" - [] sources", sources.len) + dat += "
      \n" + else + dat += "-- All Systems Nominal
      \n" + dat += "
      \n" + user << browse(dat, "window=alerts") + onclose(user, "alerts") + + +/obj/machinery/computer/station_alert/Topic(href, href_list) + if(..()) + return + return + + +/obj/machinery/computer/station_alert/proc/triggerAlarm(var/class, area/A, var/O, var/alarmsource) + if(stat & (BROKEN)) + return + var/list/L = src.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)) + return 1 + + +/obj/machinery/computer/station_alert/proc/cancelAlarm(var/class, area/A as area, obj/origin) + if(stat & (BROKEN)) + return + var/list/L = src.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 + return !cleared + + +/obj/machinery/computer/station_alert/process() + if(stat & NOPOWER) + icon_state = "atmos0" + return + else if(stat & BROKEN) + icon_state = "atmosb" + return + var/active_alarms = 0 + for (var/cat in src.alarms) + var/list/L = src.alarms[cat] + if(L.len) active_alarms = 1 + if(active_alarms) + icon_state = "alert:2" + else + icon_state = "alert:0" + ..() + return diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index 26ecdaddbee..c86f51de817 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -1,254 +1,254 @@ -//Config stuff -#define SYNDICATE_ELITE_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station -#define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock - -var/syndicate_elite_shuttle_moving_to_station = 0 -var/syndicate_elite_shuttle_moving_to_mothership = 0 -var/syndicate_elite_shuttle_at_station = 0 -var/syndicate_elite_shuttle_can_send = 1 -var/syndicate_elite_shuttle_time = 0 -var/syndicate_elite_shuttle_timeleft = 0 - -/obj/machinery/computer/syndicate_elite_shuttle - name = "Elite Syndicate Squad Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "syndishuttle" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - - light_color = LIGHT_COLOR_RED - -/proc/syndicate_elite_process() - var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work. - var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located? - var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SYNDICATE ELITE SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. - if(announcer) - announcer.say(message) - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) - - while(syndicate_elite_shuttle_time - world.timeofday > 0) - var/ticksleft = syndicate_elite_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - syndicate_elite_shuttle_time = world.timeofday // midnight rollover - syndicate_elite_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" - if(rounded_time_left==0) - message = "ALERT: TAKEOFF" - announcer.say(message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - syndicate_elite_shuttle_moving_to_station = 0 - syndicate_elite_shuttle_moving_to_mothership = 0 - - syndicate_elite_shuttle_at_station = 1 - if (syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return - - if (!syndicate_elite_can_move()) +//Config stuff +#define SYNDICATE_ELITE_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. +#define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station +#define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock + +var/syndicate_elite_shuttle_moving_to_station = 0 +var/syndicate_elite_shuttle_moving_to_mothership = 0 +var/syndicate_elite_shuttle_at_station = 0 +var/syndicate_elite_shuttle_can_send = 1 +var/syndicate_elite_shuttle_time = 0 +var/syndicate_elite_shuttle_timeleft = 0 + +/obj/machinery/computer/syndicate_elite_shuttle + name = "Elite Syndicate Squad Shuttle Console" + icon = 'icons/obj/computer.dmi' + icon_state = "syndishuttle" + req_access = list(access_cent_specops) + var/temp = null + var/hacked = 0 + var/allowedtocall = 0 + + light_color = LIGHT_COLOR_RED + +/proc/syndicate_elite_process() + var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work. + var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located? + var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + + var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. + var/message = "THE SYNDICATE ELITE SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. + if(announcer) + announcer.say(message) + message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" + announcer.say(message) + + while(syndicate_elite_shuttle_time - world.timeofday > 0) + var/ticksleft = syndicate_elite_shuttle_time - world.timeofday + + if(ticksleft > 1e5) + syndicate_elite_shuttle_time = world.timeofday // midnight rollover + syndicate_elite_shuttle_timeleft = (ticksleft / 10) + + //All this does is announce the time before launch. + if(announcer) + var/rounded_time_left = round(syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + if(rounded_time_left in message_tracker)//If that time is in the list for message announce. + message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" + if(rounded_time_left==0) + message = "ALERT: TAKEOFF" + announcer.say(message) + message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. + //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. + + sleep(5) + + syndicate_elite_shuttle_moving_to_station = 0 + syndicate_elite_shuttle_moving_to_mothership = 0 + + syndicate_elite_shuttle_at_station = 1 + if (syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return + + if (!syndicate_elite_can_move()) to_chat(usr, "The Syndicate Elite shuttle is unable to leave.") - return - - sleep(600) -/* - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in elite_squad) - switch(M.id) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in elite_squad) - switch(M.id) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in elite_squad) - switch(M.id)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - */ - elite_squad.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. -/* - var/obj/explosionmarker = locate("Syndicate Breach Area") - if(explosionmarker) - var/turf/simulated/T = explosionmarker.loc - if(T) - explosion(T,4,6,8,10,0) - - sleep(40) -// proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1) - -*/ - var/area/start_location = locate(/area/shuttle/syndicate_elite/mothership) - var/area/end_location = locate(/area/shuttle/syndicate_elite/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs = T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - qdel(T) - T = null - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T + return + + sleep(600) +/* + //Begin Marauder launchpad. + spawn(0)//So it parallel processes it. + for(var/obj/machinery/door/poddoor/M in elite_squad) + switch(M.id) + if("ASSAULT0") + spawn(10)//1 second delay between each. + M.open() + if("ASSAULT1") + spawn(20) + M.open() + if("ASSAULT2") + spawn(30) + M.open() + if("ASSAULT3") + spawn(40) + M.open() + + sleep(10) + + var/spawn_marauder[] = new() + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "Marauder Entry") + spawn_marauder.Add(L) + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "Marauder Exit") + var/obj/effect/portal/P = new(L.loc) + P.invisibility = 101//So it is not seen by anyone. + P.failchance = 0//So it has no fail chance when teleporting. + P.target = pick(spawn_marauder)//Where the marauder will arrive. + spawn_marauder.Remove(P.target) + + sleep(10) + + for(var/obj/machinery/mass_driver/M in elite_squad) + switch(M.id) + if("ASSAULT0") + spawn(10) + M.drive() + if("ASSAULT1") + spawn(20) + M.drive() + if("ASSAULT2") + spawn(30) + M.drive() + if("ASSAULT3") + spawn(40) + M.drive() + + sleep(50)//Doors remain open for 5 seconds. + + for(var/obj/machinery/door/poddoor/M in elite_squad) + switch(M.id)//Doors close at the same time. + if("ASSAULT0") + spawn(0) + M.close() + if("ASSAULT1") + spawn(0) + M.close() + if("ASSAULT2") + spawn(0) + M.close() + if("ASSAULT3") + spawn(0) + M.close() + */ + elite_squad.readyreset()//Reset firealarm after the team launched. + //End Marauder launchpad. +/* + var/obj/explosionmarker = locate("Syndicate Breach Area") + if(explosionmarker) + var/turf/simulated/T = explosionmarker.loc + if(T) + explosion(T,4,6,8,10,0) + + sleep(40) +// proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1) + +*/ + var/area/start_location = locate(/area/shuttle/syndicate_elite/mothership) + var/area/end_location = locate(/area/shuttle/syndicate_elite/station) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs = T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + qdel(T) + T = null + + start_location.move_contents_to(end_location) + + for(var/turf/T in get_area_turfs(end_location) ) + var/mob/M = locate(/mob) in T to_chat(M, "You have arrived to [station_name]. Commence operation!") - -/proc/syndicate_elite_can_move() - if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return 0 - else return 1 - -/obj/machinery/computer/syndicate_elite_shuttle/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/computer/syndicate_elite_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/syndicate_elite_shuttle/emag(mob/user as mob) + +/proc/syndicate_elite_can_move() + if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return 0 + else return 1 + +/obj/machinery/computer/syndicate_elite_shuttle/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/computer/syndicate_elite_shuttle/attack_paw(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/syndicate_elite_shuttle/emag(mob/user as mob) to_chat(user, "The electronic systems in this console are far too advanced for your primitive hacking peripherals.") - return - -/obj/machinery/computer/syndicate_elite_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) + return + +/obj/machinery/computer/syndicate_elite_shuttle/attack_hand(var/mob/user as mob) + if(!allowed(user)) to_chat(user, "Access Denied.") - return - -// if (sent_syndicate_strike_team == 0) + return + +// if (sent_syndicate_strike_team == 0) // to_chat(usr, "The strike team has not yet deployed.") -// return - - if(..()) - return - - user.set_machine(src) - var/dat - if (temp) - dat = temp - else - dat = {"
      Special Operations Shuttle
      - \nLocation: [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name] in ([syndicate_elite_shuttle_timeleft] seconds.)":syndicate_elite_shuttle_at_station ? "Station":"Dock"]
      - [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*
      \n
      ":syndicate_elite_shuttle_at_station ? "\nShuttle Offline
      \n
      ":"\nDepart to [station_name]
      \n
      "] - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/syndicate_elite_shuttle/Topic(href, href_list) - if(..()) - return 1 - - usr.set_machine(src) - - if (href_list["sendtodock"]) - if(!syndicate_elite_shuttle_at_station|| syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return - +// return + + if(..()) + return + + user.set_machine(src) + var/dat + if (temp) + dat = temp + else + dat = {"
      Special Operations Shuttle
      + \nLocation: [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name] in ([syndicate_elite_shuttle_timeleft] seconds.)":syndicate_elite_shuttle_at_station ? "Station":"Dock"]
      + [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*
      \n
      ":syndicate_elite_shuttle_at_station ? "\nShuttle Offline
      \n
      ":"\nDepart to [station_name]
      \n
      "] + \nClose"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + +/obj/machinery/computer/syndicate_elite_shuttle/Topic(href, href_list) + if(..()) + return 1 + + usr.set_machine(src) + + if (href_list["sendtodock"]) + if(!syndicate_elite_shuttle_at_station|| syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return + to_chat(usr, "The Syndicate will not allow the Elite Squad shuttle to return.") - return - - else if (href_list["sendtostation"]) - if(syndicate_elite_shuttle_at_station || syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return - - if (!specops_can_move()) + return + + else if (href_list["sendtostation"]) + if(syndicate_elite_shuttle_at_station || syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return + + if (!specops_can_move()) to_chat(usr, "The Syndicate Elite shuttle is unable to leave.") - return - + return + to_chat(usr, "The Syndicate Elite shuttle will arrive on [station_name] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds.") - - temp = "Shuttle departing.

      OK" - updateUsrDialog() - - var/area/syndicate_mothership/elite_squad/elite_squad = locate() - if(elite_squad) - elite_squad.readyalert()//Trigger alarm for the spec ops area. - syndicate_elite_shuttle_moving_to_station = 1 - - syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME - spawn(0) - syndicate_elite_process() - - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return + + temp = "Shuttle departing.

      OK" + updateUsrDialog() + + var/area/syndicate_mothership/elite_squad/elite_squad = locate() + if(elite_squad) + elite_squad.readyalert()//Trigger alarm for the spec ops area. + syndicate_elite_shuttle_moving_to_station = 1 + + syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME + spawn(0) + syndicate_elite_process() + + + else if (href_list["mainmenu"]) + temp = null + + add_fingerprint(usr) + updateUsrDialog() + return diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 2c96fda8617..eac654adfbe 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -1,1201 +1,1201 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/machinery/constructable_frame //Made into a seperate type to make future revisions easier. - name = "machine frame" - icon = 'icons/obj/stock_parts.dmi' - icon_state = "box_0" - density = 1 - anchored = 1 - use_power = 0 - var/obj/item/weapon/circuitboard/circuit = null - var/list/components = null - var/list/req_components = null - var/list/req_component_names = null - var/list/components_in_use = null - var/build_state = 1 - - // For pods - var/list/connected_parts = list() - var/pattern_idx=0 - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/constructable_frame/proc/update_desc() - var/D - if(req_components) - D = "Requires " - var/first = 1 - for(var/I in req_components) - if(req_components[I] > 0) - D += "[first?"":", "][num2text(req_components[I])] [req_component_names[I]]" - first = 0 - if(first) // nothing needs to be added, then - D += "nothing" - D += "." - desc = D - -/obj/machinery/constructable_frame/proc/get_req_components_amt() - var/amt = 0 - for(var/path in req_components) - amt += req_components[path] - return amt - -/obj/machinery/constructable_frame/machine_frame/attackby(obj/item/P as obj, mob/user as mob) - if(P.crit_fail) - to_chat(user, "This part is faulty, you cannot add this to the machine!") - return - switch(build_state) - if(1) - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = P - if(C.amount >= 5) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You start to add cables to the frame.") - if(do_after(user, src, 20)) - if(C && C.amount >= 5) // Check again - C.use(5) - to_chat(user, "You add cables to the frame.") - set_build_state(2) - else if(istype(P, /obj/item/stack/sheet/glass/glass)) - var/obj/item/stack/sheet/glass/glass/G=P - if(G.amount<1) - to_chat(user, "How...?") - return - G.use(1) - to_chat(user, "You add the glass to the frame.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - new /obj/structure/displaycase_frame(src.loc) - qdel(src) - return - else - if(istype(P, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - to_chat(user, "You dismantle the frame.") - //new /obj/item/stack/sheet/metal(src.loc, 5) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, src.loc) - M.amount = 5 - qdel(src) - if(2) - if(!..()) - if(istype(P, /obj/item/weapon/circuitboard)) - var/obj/item/weapon/circuitboard/B = P - if(B.board_type == "machine") - if(!user.drop_item(B, src)) - user << "You can't let go of \the [B]!" - return - - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You add the circuit board to the frame.") - circuit = P - set_build_state(3) - components = list() - req_components = circuit.req_components.Copy() - for(var/A in circuit.req_components) - req_components[A] = circuit.req_components[A] - req_component_names = circuit.req_components.Copy() - /* Are you fucking kidding me - for(var/A in req_components) - var/cp = text2path(A) - var/obj/ct = new cp() // have to quickly instantiate it get name - req_component_names[A] = ct.name - del(ct)*/ - for(var/A in req_components) - var/atom/path = text2path(A) - req_component_names[A] = initial(path.name) - if(circuit.frame_desc) - desc = circuit.frame_desc - else - update_desc() - to_chat(user, desc) - else - to_chat(user, "This frame does not accept circuit boards of this type!") - else - if(istype(P, /obj/item/weapon/wirecutters)) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - to_chat(user, "You remove the cables.") - set_build_state(1) - var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc ) - A.amount = 5 - - if(3) - if(!..()) - if(istype(P, /obj/item/weapon/crowbar)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - set_build_state(2) - circuit.loc = src.loc - circuit = null - if(components.len == 0) - to_chat(user, "You remove the circuit board.") - else - to_chat(user, "You remove the circuit board and other components.") - for(var/obj/item/weapon/W in components) - W.loc = src.loc - desc = initial(desc) - req_components = null - components = null - else - if(istype(P, /obj/item/weapon/screwdriver)) - var/component_check = 1 - for(var/R in req_components) - if(req_components[R] > 0) - component_check = 0 - break - if(component_check) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - var/obj/machinery/new_machine = new src.circuit.build_path(src.loc) - for(var/obj/O in new_machine.component_parts) - returnToPool(O) - new_machine.component_parts = list() - for(var/obj/O in src) - if(circuit.contain_parts) // things like disposal don't want their parts in them - O.loc = components_in_use - else - O.loc = null - new_machine.component_parts += O - if(circuit.contain_parts) - circuit.loc = components_in_use - else - circuit.loc = null - new_machine.RefreshParts() - components = null - qdel(src) - else - if(istype(P, /obj/item/weapon/storage/bag/gadgets/part_replacer) && P.contents.len && get_req_components_amt()) - var/obj/item/weapon/storage/bag/gadgets/part_replacer/replacer = P - var/list/added_components = list() - var/list/part_list = replacer.contents.Copy() - - //Sort the parts. This ensures that higher tier items are applied first. - part_list = sortTim(part_list, /proc/cmp_rped_sort) - - for(var/path in req_components) - while(req_components[path] > 0 && (locate(text2path(path)) in part_list)) - var/obj/item/part = (locate(text2path(path)) in part_list) - if(!part.crit_fail) - added_components[part] = path - replacer.remove_from_storage(part, src) - req_components[path]-- - part_list -= part - - for(var/obj/item/weapon/stock_parts/part in added_components) - components += part - to_chat(user, "[part.name] applied.") - replacer.play_rped_sound() - - update_desc() - - else - if(istype(P, /obj/item/weapon) || istype(P, /obj/item/stack)) - for(var/I in req_components) - if(istype(P, text2path(I)) && (req_components[I] > 0)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(istype(P, /obj/item/stack)) - var/obj/item/stack/CP = P - if(CP.amount >= req_components[I]) - var/camt = min(CP.amount, req_components[I]) // amount of the stack to take, idealy amount required, but limited by amount provided - var/obj/item/stack/CC = getFromPool(text2path(I), src) - CC.amount = camt - CC.update_icon() - CP.use(camt) - components += CC - req_components[I] -= camt - update_desc() - break - else - to_chat(user, "You do not have enough [P]!") - - if(user.drop_item(P, src)) - components += P - req_components[I]-- - update_desc() - break - to_chat(user, desc) - - if(P && P.loc != src && !istype(P, /obj/item/stack/cable_coil)) - to_chat(user, "You cannot add that component to the machine!") - -/obj/machinery/constructable_frame/machine_frame/proc/set_build_state(var/state) - build_state = state - switch(state) - if(1) - icon_state = "box_0" - if(2) - icon_state = "box_1" - if(3) - icon_state = "box_2" - -//Machine Frame Circuit Boards -/*Common Parts: Parts List: Ignitor, Timer, Infra-red laser, Infra-red sensor, t_scanner, Capacitor, Valve, sensor unit, -micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. -Note: Once everything is added to the public areas, will add m_amt and g_amt to circuit boards since autolathe won't be able -to destroy them and players will be able to make replacements. -*/ - -/obj/item/weapon/circuitboard/blank - name = "unprinted circuitboard" - desc = "A blank circuitboard ready for design." - icon = 'icons/obj/module.dmi' - icon_state = "blank_mod" - //var/datum/circuits/local_fuses = null - var/list/allowed_boards = list("autolathe"=/obj/item/weapon/circuitboard/autolathe,"intercom"=/obj/item/weapon/intercom_electronics,"conveyor"=/obj/item/weapon/circuitboard/conveyor,"air alarm"=/obj/item/weapon/circuitboard/air_alarm,"fire alarm"=/obj/item/weapon/circuitboard/fire_alarm,"airlock"=/obj/item/weapon/circuitboard/airlock,"APC"=/obj/item/weapon/circuitboard/power_control,"vendomat"=/obj/item/weapon/circuitboard/vendomat,"microwave"=/obj/item/weapon/circuitboard/microwave) - var/soldering = 0 //Busy check - -/obj/item/weapon/circuitboard/blank/New() - ..() - //local_fuses = new(src) - -/obj/item/weapon/circuitboard/blank/attackby(obj/item/O as obj, mob/user as mob) - /*if(ismultitool(O)) - var/boardType = local_fuses.assigned_boards["[local_fuses.localbit]"] //Localbit is an int, but this is an associative list organized by strings - if(boardType) - if(ispath(boardType)) - to_chat(user, "The multitool pings softly.") - new boardType(get_turf(src)) - qdel(src) - return - else - to_chat(user, "A fatal error with the board type occurred. Report this message.") - else - to_chat(user, "The multitool flashes red briefly.") - else */if(!soldering&&issolder(O)) - //local_fuses.Interact(user) - var/t = input(user, "Which board should be designed?") as null|anything in allowed_boards - if(!t) return - var/obj/item/weapon/solder/S = O - if(!S.remove_fuel(4,user)) return - playsound(loc, 'sound/items/Welder.ogg', 50, 1) - soldering = 1 - if(do_after(user, src,40)) - var/boardType = allowed_boards[t] - var/obj/item/I = new boardType(get_turf(user)) - to_chat(user, "You fashion a crude [I] from the blank circuitboard.") - qdel(src) - user.put_in_hands(I) - soldering = 0 - else if(iswelder(O)) - var/obj/item/weapon/weldingtool/WT = O - if(WT.remove_fuel(1,user)) - var/obj/item/stack/sheet/glass/glass/new_item = new /obj/item/stack/sheet/glass/glass(src.loc) - new_item.add_to_stacks(user) - returnToPool(src) - return - else - return ..() - -/obj/item/weapon/circuitboard/destructive_analyzer - name = "Circuit board (Destructive Analyzer)" - build_path = "/obj/machinery/r_n_d/destructive_analyzer" - board_type = "machine" - origin_tech = "magnets=2;engineering=2;programming=3" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro-Laser." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 1) - -/obj/item/weapon/circuitboard/autolathe - name = "Circuit board (Autolathe)" - build_path = "/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe" - board_type = "machine" - origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Console Screen." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 3, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/protolathe - name = "Circuit board (Protolathe)" - build_path = "/obj/machinery/r_n_d/fabricator/protolathe" - board_type = "machine" - origin_tech = "engineering=2;programming=3" - frame_desc = "Requires 2 Matter Bins, 2 Manipulators, and 2 Beakers." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/reagent_containers/glass/beaker" = 2) - -/obj/item/weapon/circuitboard/conveyor - name = "Circuit board (Conveyor)" - build_path = "/obj/machinery/conveyor" - board_type = "machine" - origin_tech = "engineering=2;programming=2" - frame_desc = "Requires nothing." - req_components = list() - - -/obj/item/weapon/circuitboard/circuit_imprinter - name = "Circuit board (Circuit Imprinter)" - build_path = "/obj/machinery/r_n_d/fabricator/circuit_imprinter" - board_type = "machine" - origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, and 2 Beakers." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/reagent_containers/glass/beaker" = 2) - -/obj/item/weapon/circuitboard/pacman - name = "Circuit Board (PACMAN-type Generator)" - build_path = "/obj/machinery/power/port_gen/pacman" - board_type = "machine" - origin_tech = "programming=3;powerstorage=3;plasmatech=3;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Micro-Laser, and 1 Capacitor." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/capacitor" = 1) - -/obj/item/weapon/circuitboard/pacman/super - name = "Circuit Board (SUPERPACMAN-type Generator)" - build_path = "/obj/machinery/power/port_gen/pacman/super" - origin_tech = "programming=3;powerstorage=4;engineering=4" - -/obj/item/weapon/circuitboard/pacman/mrs - name = "Circuit Board (MRSPACMAN-type Generator)" - build_path = "/obj/machinery/power/port_gen/pacman/mrs" - origin_tech = "programming=3;powerstorage=5;engineering=5" - -/obj/item/weapon/circuitboard/air_alarm - name = "Circuit board (Air Alarm)" - board_type="other" - icon = 'icons/obj/doors/door_assembly.dmi' - icon_state = "door_electronics" - //origin_tech = "programming=2" - -/obj/item/weapon/circuitboard/fire_alarm - name = "Circuit board (Fire Alarm)" - board_type="other" - icon = 'icons/obj/doors/door_assembly.dmi' - icon_state = "door_electronics" - //origin_tech = "programming=2" - -/obj/item/weapon/circuitboard/airlock - name = "Circuit board (Airlock)" - board_type="other" - icon = 'icons/obj/doors/door_assembly.dmi' - icon_state = "door_electronics" - //origin_tech = "programming=2" - -obj/item/weapon/circuitboard/rdserver - name = "Circuit Board (R&D Server)" - build_path = "/obj/machinery/r_n_d/server" - board_type = "machine" - origin_tech = "programming=3" - frame_desc = "Requires 2 Capacitors and 1 Scanning Module." - req_components = list( - "/obj/item/weapon/stock_parts/capacitor" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 1) - -/obj/item/weapon/circuitboard/mechfab - name = "Circuit board (Exosuit Fabricator)" - build_path = "/obj/machinery/r_n_d/fabricator/mech" - board_type = "machine" - origin_tech = "programming=3;engineering=3" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro-Laser and 1 Console Screen." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/podfab - name = "Circuit board (Spacepod Fabricator)" - build_path = "/obj/machinery/r_n_d/fabricator/pod" - board_type = "machine" - origin_tech = "programming=3;engineering=3" - frame_desc = "Requires 3 Matter Bins, 2 Manipulators, and 2 Micro-Lasers." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 3, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2) - -/obj/item/weapon/circuitboard/defib_recharger - name = "Circuit Board (Defib Recharger)" - build_path = "/obj/machinery/recharger/defibcharger/wallcharger" - board_type = "machine" - origin_tech = "programming=3;biotech=4;engineering=2;powerstorage=2" - frame_desc = "Requires 1 micro-laser, 2 matter bins, 2 manipulator, 1 console screen." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/smes - name = "Circuit Board (SMES)" - build_path = "/obj/machinery/power/battery/smes" - board_type = "machine" - origin_tech = "powerstorage=4;engineering=4;programming=4" - frame_desc = "Requires 4 capacitors, 4 micro-lasers, and 2 console screens." - req_components = list( - "/obj/item/weapon/stock_parts/capacitor" = 4, - "/obj/item/weapon/stock_parts/micro_laser" = 4, - "/obj/item/weapon/stock_parts/console_screen" = 2) - -/obj/item/weapon/circuitboard/port_smes - name = "Circuit Board (Portable SMES)" - build_path = "/obj/machinery/power/battery/portable" - board_type = "machine" - origin_tech = "powerstorage=5;engineering=4;programming=4" - frame_desc = "Requires 4 capacitors, 4 micro-lasers, and 2 console screens." - req_components = list( - "/obj/item/weapon/stock_parts/capacitor" = 4, - "/obj/item/weapon/stock_parts/micro_laser" = 4, - "/obj/item/weapon/stock_parts/console_screen" = 2) - -/obj/item/weapon/circuitboard/battery_port - name = "Circuit Board (SMES Port)" - build_path = "/obj/machinery/power/battery_port" - board_type = "machine" - origin_tech = "powerstorage=5;engineering=4;programming=4" - frame_desc = "Requires 3 capacitors and 1 console screen." - req_components = list( - "/obj/item/weapon/stock_parts/capacitor" = 3, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/treadmill - name = "Circuit Board (Treadmill Generator)" - build_path = "/obj/machinery/power/treadmill" - board_type = "machine" - origin_tech = "engineering=2;powerstorage=4" - frame_desc = "Requires 4 capacitors and 1 console screen." - req_components = list ( - "/obj/item/weapon/stock_parts/capacitor" = 4, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/chem_dispenser - name = "Circuit Board (Chemistry Dispenser)" - build_path = "/obj/machinery/chem_dispenser" - board_type = "machine" - origin_tech = "programming=3;biotech=5;engineering=4" - frame_desc = "Requires 2 manipulators, 2 scanning modules, 3 micro-lasers, and 1 console screen." - req_components = list ( - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 3, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/chem_dispenser/brewer - name = "Circuit Board (Brewer)" - build_path = "/obj/machinery/chem_dispenser/brewer" - -/obj/item/weapon/circuitboard/chem_dispenser/soda_dispenser - name = "Circuit Board (Soda Dispenser)" - build_path = "/obj/machinery/chem_dispenser/soda_dispenser" - -/obj/item/weapon/circuitboard/chem_dispenser/booze_dispenser - name = "Circuit Board (Booze Dispenser)" - build_path = "/obj/machinery/chem_dispenser/booze_dispenser" - -/obj/item/weapon/circuitboard/chemmaster3000 - name = "Circuit Board (ChemMaster 3000)" - build_path = "/obj/machinery/chem_master" - board_type = "machine" - origin_tech = "engineering=3;biotech=4" - frame_desc = "Requires 1 manipulator, 2 scanning modules, 2 micro-lasers, and 2 console screens." - req_components = list ( - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 2) - -/obj/item/weapon/circuitboard/condimaster - name = "Circuit Board (CondiMaster)" - build_path = "/obj/machinery/chem_master/condimaster" - board_type = "machine" - origin_tech = "engineering=3;biotech=4" - frame_desc = "Requires 1 manipulator, 3 scanning modules, 2 micro-lasers, and 2 console screens." - req_components = list ( - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 3, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 2) - -/obj/item/weapon/circuitboard/snackbar_machine - name = "Circuit Board (SnackBar Machine)" - build_path = "/obj/machinery/chem_master/snackbar_machine" - board_type = "machine" - origin_tech = "engineering=3;biotech=4" - frame_desc = "Requires 2 manipulator, 2 scanning modules, 2 micro-lasers, and 2 console screens." - req_components = list ( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 2) - -/obj/item/weapon/circuitboard/recharge_station - name = "Circuit Board (Cyborg Recharging Station)" - build_path = "/obj/machinery/recharge_station" - board_type = "machine" - origin_tech = "powerstorage=4;programming=3" - frame_desc = "Requires 2 capacitors, 1 manipulator, and 1 matter bin." - req_components = list ( - "/obj/item/weapon/stock_parts/capacitor" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/matter_bin" = 1) - -/obj/item/weapon/circuitboard/heater - name = "Circuit Board (Heater)" - build_path = "/obj/machinery/atmospherics/unary/heat_reservoir/heater" - board_type = "machine" - origin_tech = "powerstorage=3;engineering=5;biotech=4" - frame_desc = "Requires 3 micro-lasers and 1 console screen." - req_components = list ( - "/obj/item/weapon/stock_parts/micro_laser" = 3, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/freezer - name = "Circuit Board (Freezer)" - build_path = "/obj/machinery/atmospherics/unary/cold_sink/freezer" - board_type = "machine" - origin_tech = "powerstorage=3;engineering=4;biotech=4" - frame_desc = "Requires 3 micro-lasers and 1 console screen." - req_components = list ( - "/obj/item/weapon/stock_parts/micro_laser" = 3, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/photocopier - name = "Circuit Board (Photocopier)" - build_path = "/obj/machinery/photocopier" - board_type = "machine" - origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 2 manipulators, 2 scanning modules, 1 micro-laser, and 2 console screens." - req_components = list ( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 2,) - -/obj/item/weapon/circuitboard/cryo - name = "Circuit Board (Cryo)" - build_path = "/obj/machinery/atmospherics/unary/cryo_cell" - board_type = "machine" - origin_tech = "programming=3;biotech=3;engineering=2" - frame_desc = "Requires 3 Manipulators, 2 Scanning Modules, and 1 Console Screen." - req_components = list ( - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 3, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/clonepod - name = "Circuit board (Clone Pod)" - build_path = "/obj/machinery/cloning/clonepod" - board_type = "machine" - origin_tech = "programming=3;biotech=3" - frame_desc = "Requires 2 Manipulator, 2 Scanning Module, and 1 Console Screen." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/clonescanner - name = "Circuit board (Cloning Scanner)" - build_path = "/obj/machinery/dna_scannernew" - board_type = "machine" - origin_tech = "programming=3;biotech=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro-Laser, and 1 Console Screen." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/fullbodyscanner - name = "Circuit board (Full Body Scanner)" - build_path = "/obj/machinery/bodyscanner" - board_type = "machine" - origin_tech = "biotech=2" - frame_desc = "Requires 3 Scanning Module." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 3) - -/obj/item/weapon/circuitboard/sleeper - name = "Circuit board (Sleeper)" - build_path = "/obj/machinery/sleeper" - board_type = "machine" - origin_tech = "biotech=2" - frame_desc = "Requires 1 Scanning Module, 2 Manipulator." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 2) - -/obj/item/weapon/circuitboard/biogenerator - name = "Circuit Board (Biogenerator)" - build_path = "/obj/machinery/biogenerator" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3" - frame_desc = "Requires 2 Manipulators, 2 Matter Bins, 3 Micro-Lasers, 2 Scanning Modules,2 Console Screens, and 1 Large Beaker. " - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 3, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 2, - "/obj/item/weapon/reagent_containers/glass/beaker/large" = 1) - -/obj/item/weapon/circuitboard/seed_extractor - name = "Circuit Board (Seed Extractor)" - build_path = "/obj/machinery/seed_extractor" - board_type = "machine" - origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 2 Manipulators, 1 Matter Bins, 1 Micro-Lasers, 1 Scanning Modules, and 1 Console Screens. " - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/microwave - name = "Circuit Board (Microwave)" - build_path = "/obj/machinery/microwave" - board_type = "machine" - origin_tech = "programming=2;engineering=2;magnets=3" - frame_desc = "Requires 1 Micro-Laser, 1 Scanning Module, and 1 Console Screens. " - req_components = list( - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/reagentgrinder - name = "Circuit Board (All-In-One Grinder)" - build_path = "/obj/machinery/reagentgrinder" - board_type = "machine" - origin_tech = "programming=3;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Micro-Lasers, 1 Scanning Modules, and 1 Large Beaker. " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/reagent_containers/glass/beaker/large" = 1) - -/obj/item/weapon/circuitboard/smartfridge - name = "Circuit Board (SmartFridge)" - build_path = "/obj/machinery/smartfridge" - board_type = "machine" - origin_tech = "programming=3;engineering=2" - frame_desc = "Requires 2 Manipulators, 4 Matter Bins, ,1 Scanning Module, and 2 Console Screens. " - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 4, - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 2) - -/obj/item/weapon/circuitboard/smartfridge/medbay - name = "Circuit Board (Medbay SmartFridge)" - build_path = "/obj/machinery/smartfridge/secure/medbay" - -/obj/item/weapon/circuitboard/smartfridge/chemistry - name = "Circuit Board (Chemical SmartFridge)" - build_path = "/obj/machinery/smartfridge/chemistry" - -/obj/item/weapon/circuitboard/smartfridge/extract - name = "Circuit Board (Extract SmartFridge)" - build_path = "/obj/machinery/smartfridge/extract" - -/obj/item/weapon/circuitboard/smartfridge/seeds - name = "Circuit Board (Megaseed Servitor)" - build_path = "/obj/machinery/smartfridge/seeds" - -/obj/item/weapon/circuitboard/smartfridge/drinks - name = "Circuit Board (Drinks Showcase)" - build_path = "/obj/machinery/smartfridge/drinks" - -/obj/item/weapon/circuitboard/hydroponics - name = "Circuit Board (Hydroponics Tray)" - build_path = "/obj/machinery/portable_atmospherics/hydroponics" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 2 Matter Bins, 1 Scanning Module, 2 Beakers, 1 Capacitor, and 1 Console Screen. " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/capacitor" = 1, - "/obj/item/weapon/reagent_containers/glass/beaker" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/gibber - name = "Circuit Board (Gibber)" - build_path = "/obj/machinery/gibber" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 2 Matter Bins, 2 Capacitors, 2 Scanning Module, 4 Manipulator and 4 High Powered Micro-Lasers " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/capacitor" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 4, - "/obj/item/weapon/stock_parts/micro_laser/high" = 4) - -/obj/item/weapon/circuitboard/processor - name = "Circuit Board (Food Processor)" - build_path = "/obj/machinery/processor" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 1 Scanning Module and 2 Manipulators " - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 2) - -/obj/item/weapon/circuitboard/egg_incubator - name = "Circuit Board (Egg Incubator)" - build_path = "/obj/machinery/egg_incubator" - board_type = "machine" - origin_tech = "biotech=3" - frame_desc = "Requires 1 Matter Bin and 2 Capacitors " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/capacitor" = 2) - -/obj/item/weapon/circuitboard/monkey_recycler - name = "Circuit Board (Monkey Recycler)" - build_path = "/obj/machinery/monkey_recycler" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 1 Matter Bin, 2 Manipulators and 1 Micro-Laser " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 1) - -/* -/obj/item/weapon/circuitboard/hydroseeds - name = "Circuit Board (MegaSeed Servitor)" - build_path = "/obj/machinery/vending/hydroseeds" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/capacitor" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2) - -/obj/item/weapon/circuitboard/hydronutrients - name = "Circuit Board (Nutrimax)" - build_path = "/obj/machinery/vending/hydronutrients" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/capacitor" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2) -*/ - -/obj/item/weapon/circuitboard/pipedispenser - name = "Circuit Board (Pipe Dispenser)" - build_path = "/obj/machinery/pipedispenser" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/capacitor" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2) - -/obj/item/weapon/circuitboard/pipedispenser/disposal - name = "Circuit Board (Disposal Pipe Dispenser)" - build_path = "/obj/machinery/pipedispenser/disposal" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" - frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/capacitor" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 2) - - - - -//Teleporter -/obj/item/weapon/circuitboard/telehub - name = "Circuit Board (Teleporter Hub)" - build_path = "/obj/machinery/teleport/hub" - board_type = "machine" - origin_tech = "programming=4;engineering=3;bluespace=3" - frame_desc = "Requires 2 Phasic Scanning Modules, 3 Super Capacitors, 2 Subspace Ansibles, 2 Hyperwave filters, 1 Subspace Treatment Disc, 2 Ansible Crystals, and 4 Subspace Transmitters." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module/adv/phasic" = 2, - "/obj/item/weapon/stock_parts/capacitor/adv/super" = 3, - "/obj/item/weapon/stock_parts/subspace/ansible" = 2, - "/obj/item/weapon/stock_parts/subspace/filter" = 2, - "/obj/item/weapon/stock_parts/subspace/treatment" = 1, - "/obj/item/weapon/stock_parts/subspace/crystal" = 2, - "/obj/item/weapon/stock_parts/subspace/transmitter" = 4) - -/obj/item/weapon/circuitboard/telestation - name = "Circuit Board (Teleporter Station)" - build_path = "/obj/machinery/teleport/station" - board_type = "machine" - origin_tech = "programming=4;engineering=3;bluespace=3" - frame_desc = "Requires 2 Phasic Scanning Modules, 2 Super Capacitors, 2 Subspace Ansibles, and 4 Subspace Wavelength Analyzers." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module/adv/phasic" = 2, - "/obj/item/weapon/stock_parts/capacitor/adv/super" = 2, - "/obj/item/weapon/stock_parts/subspace/ansible" = 2, - "/obj/item/weapon/stock_parts/subspace/analyzer" = 4) - -// Telecomms circuit boards: - -/obj/item/weapon/circuitboard/telecomms/receiver - name = "Circuit Board (Subspace Receiver)" - build_path = "/obj/machinery/telecomms/receiver" - board_type = "machine" - origin_tech = "programming=4;engineering=3;bluespace=2" - frame_desc = "Requires 1 Subspace Ansible, 1 Hyperwave Filter, 2 Manipulators, and 1 Micro-Laser." - req_components = list( - "/obj/item/weapon/stock_parts/subspace/ansible" = 1, - "/obj/item/weapon/stock_parts/subspace/filter" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 1) - -/obj/item/weapon/circuitboard/telecomms/hub - name = "Circuit Board (Hub Mainframe)" - build_path = "/obj/machinery/telecomms/hub" - board_type = "machine" - origin_tech = "programming=4;engineering=4" - frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filter." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/stack/cable_coil" = 2, - "/obj/item/weapon/stock_parts/subspace/filter" = 2) - -/obj/item/weapon/circuitboard/telecomms/relay - name = "Circuit Board (Relay Mainframe)" - build_path = "/obj/machinery/telecomms/relay" - board_type = "machine" - origin_tech = "programming=3;engineering=4;bluespace=3" - frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filters." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/stack/cable_coil" = 2, - "/obj/item/weapon/stock_parts/subspace/filter" = 2) - -/obj/item/weapon/circuitboard/telecomms/bus - name = "Circuit Board (Bus Mainframe)" - build_path = "/obj/machinery/telecomms/bus" - board_type = "machine" - origin_tech = "programming=4;engineering=4" - frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/stack/cable_coil" = 1, - "/obj/item/weapon/stock_parts/subspace/filter" = 1) - -/obj/item/weapon/circuitboard/telecomms/processor - name = "Circuit Board (Processor Unit)" - build_path = "/obj/machinery/telecomms/processor" - board_type = "machine" - origin_tech = "programming=4;engineering=4" - frame_desc = "Requires 3 Manipulators, 1 Hyperwave Filter, 2 Treatment Disks, 1 Wavelength Analyzer, 2 Cable Coils and 1 Subspace Amplifier." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 3, - "/obj/item/weapon/stock_parts/subspace/filter" = 1, - "/obj/item/weapon/stock_parts/subspace/treatment" = 2, - "/obj/item/weapon/stock_parts/subspace/analyzer" = 1, - "/obj/item/stack/cable_coil" = 2, - "/obj/item/weapon/stock_parts/subspace/amplifier" = 1) - -/obj/item/weapon/circuitboard/telecomms/server - name = "Circuit Board (Telecommunication Server)" - build_path = "/obj/machinery/telecomms/server" - board_type = "machine" - origin_tech = "programming=4;engineering=4" - frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/stack/cable_coil" = 1, - "/obj/item/weapon/stock_parts/subspace/filter" = 1) - -/obj/item/weapon/circuitboard/telecomms/broadcaster - name = "Circuit Board (Subspace Broadcaster)" - build_path = "/obj/machinery/telecomms/broadcaster" - board_type = "machine" - origin_tech = "programming=4;engineering=4;bluespace=2" - frame_desc = "Requires 2 Manipulators, 1 Cable Coil, 1 Hyperwave Filter, 1 Ansible Crystal and 2 High-Powered Micro-Lasers. " - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/stack/cable_coil" = 1, - "/obj/item/weapon/stock_parts/subspace/filter" = 1, - "/obj/item/weapon/stock_parts/subspace/crystal" = 1, - "/obj/item/weapon/stock_parts/micro_laser/high" = 2) - -/obj/item/weapon/circuitboard/bioprinter - name = "Circuit Board (Bioprinter)" - build_path = "/obj/machinery/bioprinter" - board_type = "machine" - origin_tech = "programming=3;engineering=2;biotech=3" - frame_desc = "Requires 2 Manipulators, 2 Matter Bins, 3 Micro-Lasers, 2 Scanning Modules, 1 Console Screen. " - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 3, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/reverse_engine - name = "Circuit Board (Reverse Engine)" - build_path = "/obj/machinery/r_n_d/reverse_engine" - board_type = "machine" - origin_tech = "materials=6;programming=4;engineering=3;bluespace=3;powerstorage=4" - frame_desc = "Requires 2 Scanning Modules, 2 Capacitors, 1 Manipulator, and 1 Console Screen." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/capacitor" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/generalfab - name = "Circuit Board (General Fabricator)" - build_path = "/obj/machinery/r_n_d/fabricator/mechanic_fab" - board_type = "machine" - origin_tech = "materials=3;engineering=2;programming=3" - frame_desc = "Requires 2 Manipulators, 2 Matter Bins, and 2 Micro-Lasers." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 2) - -/obj/item/weapon/circuitboard/flatpacker - name = "Circuit Board (Flatpack Fabricator)" - build_path = "/obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker" - board_type = "machine" - origin_tech = "materials=5;engineering=4;powerstorage=3;programming=3" - frame_desc = "Requires 2 Manipulators, 2 Matter Bins, 2 Micro-Lasers, 2 Scanning Modules, and 1 Beaker." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/reagent_containers/glass/beaker" = 1) - -/obj/item/weapon/circuitboard/blueprinter - name = "Circuit Board (Blueprint Printer)" - build_path = "/obj/machinery/r_n_d/blueprinter" - board_type = "machine" - origin_tech = "engineering=3;programming=3" - frame_desc = "Requires 2 Matter Bins, 1 Scanning Module, and 1 Manipulator." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 1) - -/obj/item/weapon/circuitboard/vendomat - name = "Circuit Board (Vending Machine)" - build_path = "/obj/machinery/vending" - board_type = "machine" - origin_tech = "materials=1;engineering=1;powerstorage=1" - frame_desc = "Requires 1 Matter Bins, 1 Scanning Module, and 1 Manipulator." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 1) - -/obj/item/weapon/circuitboard/pdapainter - name = "Circuit Board (PDA Painter)" - build_path = "/obj/machinery/pdapainter" - board_type = "machine" - origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 1 Manipulator, 2 Micro-Lasers, 2 Scanning Modules, and 1 Console Screen. " - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/incubator - name = "Circuit Board (Pathogenic Incubator)" - build_path = "/obj/machinery/disease2/incubator" - board_type = "machine" - origin_tech = "materials=4;biotech=5;magnets=3" - frame_desc = "Requires 1 Matter Bin, 2 Scanning Modules, 2 Micro-Lasers, and 1 Beaker." - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/reagent_containers/glass/beaker" = 1) - -/obj/item/weapon/circuitboard/diseaseanalyser - name = "Circuit Board (Disease Analyser)" - build_path = "/obj/machinery/disease2/diseaseanalyser" - board_type = "machine" - origin_tech = "engineering=3;biotech=3;programming=3" - frame_desc = "Requires 1 Micro-Laser, 1 Manipulator, and 3 Scanning Modules." - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/micro_laser" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 3) - -/obj/item/weapon/circuitboard/centrifuge - name = "Circuit Board (Isolation Centrifuge)" - build_path = "/obj/machinery/centrifuge" - board_type = "machine" - origin_tech = "biotech=3" - frame_desc = "Requires 2 Manipulators" - req_components = list( - "/obj/item/weapon/stock_parts/manipulator" = 2) - -/obj/item/weapon/circuitboard/mech_bay_power_port - name = "Circuit Board (Power Port)" - build_path = "/obj/machinery/mech_bay_recharge_port" - board_type = "machine" - origin_tech = "engineering=2;powerstorage=3" - frame_desc = "Requires 2 Micro-Lasers, and 1 Console Screen." - req_components = list( - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 1) - -/obj/item/weapon/circuitboard/mech_bay_recharge_station - name = "Circuit Board (Recharge Station)" - build_path = "/obj/machinery/mech_bay_recharge_floor" - board_type = "machine" - origin_tech = "materials=2;powerstorage=3" - frame_desc = "Requires 1 Scanning Module and 2 Capacitors." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/capacitor" = 2) - -/obj/item/weapon/circuitboard/prism - name = "Circuit Board (Prism)" - build_path = "/obj/machinery/prism" - board_type = "machine" - origin_tech = "programming=3;engineering=3;powerstorage=3" - frame_desc = "Requires 3 High-powered Micro-Lasers, and 6 Capacitors." - req_components = list( - "/obj/item/weapon/stock_parts/micro_laser/high" = 3, - "/obj/item/weapon/stock_parts/capacitor" = 6) - -/obj/item/weapon/circuitboard/cell_charger - name = "Circuit Board (Cell Charger)" - build_path = "/obj/machinery/cell_charger" - board_type = "machine" - origin_tech = "materials=2;engineering=2;powerstorage=3" - frame_desc = "Requires 1 Scanning Module and 2 Capacitors." - req_components = list( - "/obj/item/weapon/stock_parts/scanning_module" = 1, - "/obj/item/weapon/stock_parts/capacitor" = 2) - -/obj/item/weapon/circuitboard/washing_machine - name = "Circuit Board (Washing Machine)" - build_path = "/obj/machinery/washing_machine" - board_type = "machine" - origin_tech = "materials=1" - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 1, - "/obj/item/weapon/stock_parts/manipulator" = 1) - -/obj/item/weapon/circuitboard/sorting_machine - name = "Circuit Board (Sorting Machine)" - board_type = "machine" - origin_tech = "materials=2;engineering=2;programming=3" - frame_desc = "Requires 3 Matter Bins and 1 Capacitor" //Matter bins because it's moving matter, I guess, and a capacitor because else the recipe is boring. - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 3, - "/obj/item/weapon/stock_parts/capacitor" = 1) - -/obj/item/weapon/circuitboard/sorting_machine/recycling - name = "Circuit Board (Recycling Sorting Machine)" - build_path = "/obj/machinery/sorting_machine/recycling" - -/obj/item/weapon/circuitboard/sorting_machine/destination - name = "Circuit Board (Destinations Sorting Machine)" - build_path = "/obj/machinery/sorting_machine/destination" - -/obj/item/weapon/circuitboard/processing_unit - name = "Circuit Board (Ore Processor)" - build_path = "/obj/machinery/mineral/processing_unit" - board_type = "machine" - origin_tech = "materials=3;engineering=2;programming=2" - frame_desc = "Requires 2 Matter Bins and 2 Micro-lasers" - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2) - -/obj/item/weapon/circuitboard/processing_unit/recycling - name = "Circuit Board (Recycling Furnace)" - build_path = "/obj/machinery/mineral/processing_unit/recycle" - -/obj/item/weapon/circuitboard/stacking_unit - name = "Circuit Board (Stacking Machine)" - build_path = "/obj/machinery/mineral/stacking_machine" - board_type = "machine" - origin_tech = "materials=3;engineering=2;programming=2" - frame_desc = "Requires 3 Matter Bins and 1 Capacitor" //Matter bins because it's moving matter, I guess, and a capacitor because else the recipe is boring. - req_components = list( - "/obj/item/weapon/stock_parts/matter_bin" = 3, - "/obj/item/weapon/stock_parts/capacitor" = 1) - -/obj/item/weapon/circuitboard/fax - name = "Circuit Board (Fax Machine)" - build_path = "/obj/machinery/faxmachine" - board_type = "machine" - origin_tech = "materials=2;bluespace=2" - frame_desc = "Requires 1 ansible and 1 scanning module." - req_components = list( - "/obj/item/weapon/stock_parts/subspace/ansible" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 1) - -/* - * Xenobotany -*/ - -/obj/item/weapon/circuitboard/botany_centrifuge - name = "Circuit Board (Lysis-Isolation Centrifuge)" - build_path = "/obj/machinery/botany/extractor" - board_type = "machine" - origin_tech = "engineering=3;biotech=3" - frame_desc = "Requires 1 manipulator, 2 scanning modules, 2 micro-lasers, 1 matter bin, and 2 console screens." - req_components = list ( - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 2, - "/obj/item/weapon/stock_parts/matter_bin" = 1) - -/obj/item/weapon/circuitboard/botany_bioballistic - name = "Circuit Board (Bioballistic Delivery System)" - build_path = "/obj/machinery/botany/editor" - board_type = "machine" - origin_tech = "engineering=3;biotech=3" - frame_desc = "Requires 1 manipulator, 2 scanning modules, 2 micro-lasers, and 1 console screen." - req_components = list ( - "/obj/item/weapon/stock_parts/manipulator" = 1, - "/obj/item/weapon/stock_parts/scanning_module" = 2, - "/obj/item/weapon/stock_parts/micro_laser" = 2, - "/obj/item/weapon/stock_parts/console_screen" = 1,) -/* - * Xenoarcheology -*/ - -/obj/item/weapon/circuitboard/anom - name = "Circuit Board (Fourier Transform Spectroscope)" - build_path = "/obj/machinery/anomaly/fourier_transform" - board_type = "machine" - origin_tech = "programming=4" - frame_desc = "Requires 3 scanning modules." - req_components = list ( - "/obj/item/weapon/stock_parts/scanning_module" = 3) - -/obj/item/weapon/circuitboard/anom/accelerator - name = "Circuit Board (Accelerator Spectrometer)" - build_path = "/obj/machinery/anomaly/accelerator" - -/obj/item/weapon/circuitboard/anom/gas - name = "Circuit Board (Gas Chromatography Spectrometer)" - build_path = "/obj/machinery/anomaly/gas_chromatography" - -/obj/item/weapon/circuitboard/anom/hyper - name = "Circuit Board (Hyperspectral Imager)" - build_path = "/obj/machinery/anomaly/hyperspectral" - -/obj/item/weapon/circuitboard/anom/ion - name = "Circuit Board (Ion Mobility Spectrometer)" - build_path = "/obj/machinery/anomaly/ion_mobility" - -/obj/item/weapon/circuitboard/anom/iso - name = "Circuit Board (Isotope Ratio Spectrometer)" - build_path = "/obj/machinery/anomaly/isotope_ratio" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/constructable_frame //Made into a seperate type to make future revisions easier. + name = "machine frame" + icon = 'icons/obj/stock_parts.dmi' + icon_state = "box_0" + density = 1 + anchored = 1 + use_power = 0 + var/obj/item/weapon/circuitboard/circuit = null + var/list/components = null + var/list/req_components = null + var/list/req_component_names = null + var/list/components_in_use = null + var/build_state = 1 + + // For pods + var/list/connected_parts = list() + var/pattern_idx=0 + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/constructable_frame/proc/update_desc() + var/D + if(req_components) + D = "Requires " + var/first = 1 + for(var/I in req_components) + if(req_components[I] > 0) + D += "[first?"":", "][num2text(req_components[I])] [req_component_names[I]]" + first = 0 + if(first) // nothing needs to be added, then + D += "nothing" + D += "." + desc = D + +/obj/machinery/constructable_frame/proc/get_req_components_amt() + var/amt = 0 + for(var/path in req_components) + amt += req_components[path] + return amt + +/obj/machinery/constructable_frame/machine_frame/attackby(obj/item/P as obj, mob/user as mob) + if(P.crit_fail) + to_chat(user, "This part is faulty, you cannot add this to the machine!") + return + switch(build_state) + if(1) + if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = P + if(C.amount >= 5) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You start to add cables to the frame.") + if(do_after(user, src, 20)) + if(C && C.amount >= 5) // Check again + C.use(5) + to_chat(user, "You add cables to the frame.") + set_build_state(2) + else if(istype(P, /obj/item/stack/sheet/glass/glass)) + var/obj/item/stack/sheet/glass/glass/G=P + if(G.amount<1) + to_chat(user, "How...?") + return + G.use(1) + to_chat(user, "You add the glass to the frame.") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + new /obj/structure/displaycase_frame(src.loc) + qdel(src) + return + else + if(istype(P, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + to_chat(user, "You dismantle the frame.") + //new /obj/item/stack/sheet/metal(src.loc, 5) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, src.loc) + M.amount = 5 + qdel(src) + if(2) + if(!..()) + if(istype(P, /obj/item/weapon/circuitboard)) + var/obj/item/weapon/circuitboard/B = P + if(B.board_type == "machine") + if(!user.drop_item(B, src)) + user << "You can't let go of \the [B]!" + return + + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You add the circuit board to the frame.") + circuit = P + set_build_state(3) + components = list() + req_components = circuit.req_components.Copy() + for(var/A in circuit.req_components) + req_components[A] = circuit.req_components[A] + req_component_names = circuit.req_components.Copy() + /* Are you fucking kidding me + for(var/A in req_components) + var/cp = text2path(A) + var/obj/ct = new cp() // have to quickly instantiate it get name + req_component_names[A] = ct.name + del(ct)*/ + for(var/A in req_components) + var/atom/path = text2path(A) + req_component_names[A] = initial(path.name) + if(circuit.frame_desc) + desc = circuit.frame_desc + else + update_desc() + to_chat(user, desc) + else + to_chat(user, "This frame does not accept circuit boards of this type!") + else + if(istype(P, /obj/item/weapon/wirecutters)) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + to_chat(user, "You remove the cables.") + set_build_state(1) + var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc ) + A.amount = 5 + + if(3) + if(!..()) + if(istype(P, /obj/item/weapon/crowbar)) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + set_build_state(2) + circuit.loc = src.loc + circuit = null + if(components.len == 0) + to_chat(user, "You remove the circuit board.") + else + to_chat(user, "You remove the circuit board and other components.") + for(var/obj/item/weapon/W in components) + W.loc = src.loc + desc = initial(desc) + req_components = null + components = null + else + if(istype(P, /obj/item/weapon/screwdriver)) + var/component_check = 1 + for(var/R in req_components) + if(req_components[R] > 0) + component_check = 0 + break + if(component_check) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + var/obj/machinery/new_machine = new src.circuit.build_path(src.loc) + for(var/obj/O in new_machine.component_parts) + returnToPool(O) + new_machine.component_parts = list() + for(var/obj/O in src) + if(circuit.contain_parts) // things like disposal don't want their parts in them + O.loc = components_in_use + else + O.loc = null + new_machine.component_parts += O + if(circuit.contain_parts) + circuit.loc = components_in_use + else + circuit.loc = null + new_machine.RefreshParts() + components = null + qdel(src) + else + if(istype(P, /obj/item/weapon/storage/bag/gadgets/part_replacer) && P.contents.len && get_req_components_amt()) + var/obj/item/weapon/storage/bag/gadgets/part_replacer/replacer = P + var/list/added_components = list() + var/list/part_list = replacer.contents.Copy() + + //Sort the parts. This ensures that higher tier items are applied first. + part_list = sortTim(part_list, /proc/cmp_rped_sort) + + for(var/path in req_components) + while(req_components[path] > 0 && (locate(text2path(path)) in part_list)) + var/obj/item/part = (locate(text2path(path)) in part_list) + if(!part.crit_fail) + added_components[part] = path + replacer.remove_from_storage(part, src) + req_components[path]-- + part_list -= part + + for(var/obj/item/weapon/stock_parts/part in added_components) + components += part + to_chat(user, "[part.name] applied.") + replacer.play_rped_sound() + + update_desc() + + else + if(istype(P, /obj/item/weapon) || istype(P, /obj/item/stack)) + for(var/I in req_components) + if(istype(P, text2path(I)) && (req_components[I] > 0)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(istype(P, /obj/item/stack)) + var/obj/item/stack/CP = P + if(CP.amount >= req_components[I]) + var/camt = min(CP.amount, req_components[I]) // amount of the stack to take, idealy amount required, but limited by amount provided + var/obj/item/stack/CC = getFromPool(text2path(I), src) + CC.amount = camt + CC.update_icon() + CP.use(camt) + components += CC + req_components[I] -= camt + update_desc() + break + else + to_chat(user, "You do not have enough [P]!") + + if(user.drop_item(P, src)) + components += P + req_components[I]-- + update_desc() + break + to_chat(user, desc) + + if(P && P.loc != src && !istype(P, /obj/item/stack/cable_coil)) + to_chat(user, "You cannot add that component to the machine!") + +/obj/machinery/constructable_frame/machine_frame/proc/set_build_state(var/state) + build_state = state + switch(state) + if(1) + icon_state = "box_0" + if(2) + icon_state = "box_1" + if(3) + icon_state = "box_2" + +//Machine Frame Circuit Boards +/*Common Parts: Parts List: Ignitor, Timer, Infra-red laser, Infra-red sensor, t_scanner, Capacitor, Valve, sensor unit, +micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. +Note: Once everything is added to the public areas, will add m_amt and g_amt to circuit boards since autolathe won't be able +to destroy them and players will be able to make replacements. +*/ + +/obj/item/weapon/circuitboard/blank + name = "unprinted circuitboard" + desc = "A blank circuitboard ready for design." + icon = 'icons/obj/module.dmi' + icon_state = "blank_mod" + //var/datum/circuits/local_fuses = null + var/list/allowed_boards = list("autolathe"=/obj/item/weapon/circuitboard/autolathe,"intercom"=/obj/item/weapon/intercom_electronics,"conveyor"=/obj/item/weapon/circuitboard/conveyor,"air alarm"=/obj/item/weapon/circuitboard/air_alarm,"fire alarm"=/obj/item/weapon/circuitboard/fire_alarm,"airlock"=/obj/item/weapon/circuitboard/airlock,"APC"=/obj/item/weapon/circuitboard/power_control,"vendomat"=/obj/item/weapon/circuitboard/vendomat,"microwave"=/obj/item/weapon/circuitboard/microwave) + var/soldering = 0 //Busy check + +/obj/item/weapon/circuitboard/blank/New() + ..() + //local_fuses = new(src) + +/obj/item/weapon/circuitboard/blank/attackby(obj/item/O as obj, mob/user as mob) + /*if(ismultitool(O)) + var/boardType = local_fuses.assigned_boards["[local_fuses.localbit]"] //Localbit is an int, but this is an associative list organized by strings + if(boardType) + if(ispath(boardType)) + to_chat(user, "The multitool pings softly.") + new boardType(get_turf(src)) + qdel(src) + return + else + to_chat(user, "A fatal error with the board type occurred. Report this message.") + else + to_chat(user, "The multitool flashes red briefly.") + else */if(!soldering&&issolder(O)) + //local_fuses.Interact(user) + var/t = input(user, "Which board should be designed?") as null|anything in allowed_boards + if(!t) return + var/obj/item/weapon/solder/S = O + if(!S.remove_fuel(4,user)) return + playsound(loc, 'sound/items/Welder.ogg', 50, 1) + soldering = 1 + if(do_after(user, src,40)) + var/boardType = allowed_boards[t] + var/obj/item/I = new boardType(get_turf(user)) + to_chat(user, "You fashion a crude [I] from the blank circuitboard.") + qdel(src) + user.put_in_hands(I) + soldering = 0 + else if(iswelder(O)) + var/obj/item/weapon/weldingtool/WT = O + if(WT.remove_fuel(1,user)) + var/obj/item/stack/sheet/glass/glass/new_item = new /obj/item/stack/sheet/glass/glass(src.loc) + new_item.add_to_stacks(user) + returnToPool(src) + return + else + return ..() + +/obj/item/weapon/circuitboard/destructive_analyzer + name = "Circuit board (Destructive Analyzer)" + build_path = "/obj/machinery/r_n_d/destructive_analyzer" + board_type = "machine" + origin_tech = "magnets=2;engineering=2;programming=3" + frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro-Laser." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1) + +/obj/item/weapon/circuitboard/autolathe + name = "Circuit board (Autolathe)" + build_path = "/obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe" + board_type = "machine" + origin_tech = "engineering=2;programming=2" + frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Console Screen." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 3, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/protolathe + name = "Circuit board (Protolathe)" + build_path = "/obj/machinery/r_n_d/fabricator/protolathe" + board_type = "machine" + origin_tech = "engineering=2;programming=3" + frame_desc = "Requires 2 Matter Bins, 2 Manipulators, and 2 Beakers." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/reagent_containers/glass/beaker" = 2) + +/obj/item/weapon/circuitboard/conveyor + name = "Circuit board (Conveyor)" + build_path = "/obj/machinery/conveyor" + board_type = "machine" + origin_tech = "engineering=2;programming=2" + frame_desc = "Requires nothing." + req_components = list() + + +/obj/item/weapon/circuitboard/circuit_imprinter + name = "Circuit board (Circuit Imprinter)" + build_path = "/obj/machinery/r_n_d/fabricator/circuit_imprinter" + board_type = "machine" + origin_tech = "engineering=2;programming=2" + frame_desc = "Requires 1 Matter Bin, 1 Manipulator, and 2 Beakers." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/reagent_containers/glass/beaker" = 2) + +/obj/item/weapon/circuitboard/pacman + name = "Circuit Board (PACMAN-type Generator)" + build_path = "/obj/machinery/power/port_gen/pacman" + board_type = "machine" + origin_tech = "programming=3;powerstorage=3;plasmatech=3;engineering=3" + frame_desc = "Requires 1 Matter Bin, 1 Micro-Laser, and 1 Capacitor." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/capacitor" = 1) + +/obj/item/weapon/circuitboard/pacman/super + name = "Circuit Board (SUPERPACMAN-type Generator)" + build_path = "/obj/machinery/power/port_gen/pacman/super" + origin_tech = "programming=3;powerstorage=4;engineering=4" + +/obj/item/weapon/circuitboard/pacman/mrs + name = "Circuit Board (MRSPACMAN-type Generator)" + build_path = "/obj/machinery/power/port_gen/pacman/mrs" + origin_tech = "programming=3;powerstorage=5;engineering=5" + +/obj/item/weapon/circuitboard/air_alarm + name = "Circuit board (Air Alarm)" + board_type="other" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + //origin_tech = "programming=2" + +/obj/item/weapon/circuitboard/fire_alarm + name = "Circuit board (Fire Alarm)" + board_type="other" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + //origin_tech = "programming=2" + +/obj/item/weapon/circuitboard/airlock + name = "Circuit board (Airlock)" + board_type="other" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + //origin_tech = "programming=2" + +obj/item/weapon/circuitboard/rdserver + name = "Circuit Board (R&D Server)" + build_path = "/obj/machinery/r_n_d/server" + board_type = "machine" + origin_tech = "programming=3" + frame_desc = "Requires 2 Capacitors and 1 Scanning Module." + req_components = list( + "/obj/item/weapon/stock_parts/capacitor" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 1) + +/obj/item/weapon/circuitboard/mechfab + name = "Circuit board (Exosuit Fabricator)" + build_path = "/obj/machinery/r_n_d/fabricator/mech" + board_type = "machine" + origin_tech = "programming=3;engineering=3" + frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro-Laser and 1 Console Screen." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/podfab + name = "Circuit board (Spacepod Fabricator)" + build_path = "/obj/machinery/r_n_d/fabricator/pod" + board_type = "machine" + origin_tech = "programming=3;engineering=3" + frame_desc = "Requires 3 Matter Bins, 2 Manipulators, and 2 Micro-Lasers." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 3, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2) + +/obj/item/weapon/circuitboard/defib_recharger + name = "Circuit Board (Defib Recharger)" + build_path = "/obj/machinery/recharger/defibcharger/wallcharger" + board_type = "machine" + origin_tech = "programming=3;biotech=4;engineering=2;powerstorage=2" + frame_desc = "Requires 1 micro-laser, 2 matter bins, 2 manipulator, 1 console screen." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/smes + name = "Circuit Board (SMES)" + build_path = "/obj/machinery/power/battery/smes" + board_type = "machine" + origin_tech = "powerstorage=4;engineering=4;programming=4" + frame_desc = "Requires 4 capacitors, 4 micro-lasers, and 2 console screens." + req_components = list( + "/obj/item/weapon/stock_parts/capacitor" = 4, + "/obj/item/weapon/stock_parts/micro_laser" = 4, + "/obj/item/weapon/stock_parts/console_screen" = 2) + +/obj/item/weapon/circuitboard/port_smes + name = "Circuit Board (Portable SMES)" + build_path = "/obj/machinery/power/battery/portable" + board_type = "machine" + origin_tech = "powerstorage=5;engineering=4;programming=4" + frame_desc = "Requires 4 capacitors, 4 micro-lasers, and 2 console screens." + req_components = list( + "/obj/item/weapon/stock_parts/capacitor" = 4, + "/obj/item/weapon/stock_parts/micro_laser" = 4, + "/obj/item/weapon/stock_parts/console_screen" = 2) + +/obj/item/weapon/circuitboard/battery_port + name = "Circuit Board (SMES Port)" + build_path = "/obj/machinery/power/battery_port" + board_type = "machine" + origin_tech = "powerstorage=5;engineering=4;programming=4" + frame_desc = "Requires 3 capacitors and 1 console screen." + req_components = list( + "/obj/item/weapon/stock_parts/capacitor" = 3, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/treadmill + name = "Circuit Board (Treadmill Generator)" + build_path = "/obj/machinery/power/treadmill" + board_type = "machine" + origin_tech = "engineering=2;powerstorage=4" + frame_desc = "Requires 4 capacitors and 1 console screen." + req_components = list ( + "/obj/item/weapon/stock_parts/capacitor" = 4, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/chem_dispenser + name = "Circuit Board (Chemistry Dispenser)" + build_path = "/obj/machinery/chem_dispenser" + board_type = "machine" + origin_tech = "programming=3;biotech=5;engineering=4" + frame_desc = "Requires 2 manipulators, 2 scanning modules, 3 micro-lasers, and 1 console screen." + req_components = list ( + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 3, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/chem_dispenser/brewer + name = "Circuit Board (Brewer)" + build_path = "/obj/machinery/chem_dispenser/brewer" + +/obj/item/weapon/circuitboard/chem_dispenser/soda_dispenser + name = "Circuit Board (Soda Dispenser)" + build_path = "/obj/machinery/chem_dispenser/soda_dispenser" + +/obj/item/weapon/circuitboard/chem_dispenser/booze_dispenser + name = "Circuit Board (Booze Dispenser)" + build_path = "/obj/machinery/chem_dispenser/booze_dispenser" + +/obj/item/weapon/circuitboard/chemmaster3000 + name = "Circuit Board (ChemMaster 3000)" + build_path = "/obj/machinery/chem_master" + board_type = "machine" + origin_tech = "engineering=3;biotech=4" + frame_desc = "Requires 1 manipulator, 2 scanning modules, 2 micro-lasers, and 2 console screens." + req_components = list ( + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 2) + +/obj/item/weapon/circuitboard/condimaster + name = "Circuit Board (CondiMaster)" + build_path = "/obj/machinery/chem_master/condimaster" + board_type = "machine" + origin_tech = "engineering=3;biotech=4" + frame_desc = "Requires 1 manipulator, 3 scanning modules, 2 micro-lasers, and 2 console screens." + req_components = list ( + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 3, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 2) + +/obj/item/weapon/circuitboard/snackbar_machine + name = "Circuit Board (SnackBar Machine)" + build_path = "/obj/machinery/chem_master/snackbar_machine" + board_type = "machine" + origin_tech = "engineering=3;biotech=4" + frame_desc = "Requires 2 manipulator, 2 scanning modules, 2 micro-lasers, and 2 console screens." + req_components = list ( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 2) + +/obj/item/weapon/circuitboard/recharge_station + name = "Circuit Board (Cyborg Recharging Station)" + build_path = "/obj/machinery/recharge_station" + board_type = "machine" + origin_tech = "powerstorage=4;programming=3" + frame_desc = "Requires 2 capacitors, 1 manipulator, and 1 matter bin." + req_components = list ( + "/obj/item/weapon/stock_parts/capacitor" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/matter_bin" = 1) + +/obj/item/weapon/circuitboard/heater + name = "Circuit Board (Heater)" + build_path = "/obj/machinery/atmospherics/unary/heat_reservoir/heater" + board_type = "machine" + origin_tech = "powerstorage=3;engineering=5;biotech=4" + frame_desc = "Requires 3 micro-lasers and 1 console screen." + req_components = list ( + "/obj/item/weapon/stock_parts/micro_laser" = 3, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/freezer + name = "Circuit Board (Freezer)" + build_path = "/obj/machinery/atmospherics/unary/cold_sink/freezer" + board_type = "machine" + origin_tech = "powerstorage=3;engineering=4;biotech=4" + frame_desc = "Requires 3 micro-lasers and 1 console screen." + req_components = list ( + "/obj/item/weapon/stock_parts/micro_laser" = 3, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/photocopier + name = "Circuit Board (Photocopier)" + build_path = "/obj/machinery/photocopier" + board_type = "machine" + origin_tech = "engineering=2;programming=2" + frame_desc = "Requires 2 manipulators, 2 scanning modules, 1 micro-laser, and 2 console screens." + req_components = list ( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 2,) + +/obj/item/weapon/circuitboard/cryo + name = "Circuit Board (Cryo)" + build_path = "/obj/machinery/atmospherics/unary/cryo_cell" + board_type = "machine" + origin_tech = "programming=3;biotech=3;engineering=2" + frame_desc = "Requires 3 Manipulators, 2 Scanning Modules, and 1 Console Screen." + req_components = list ( + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 3, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/clonepod + name = "Circuit board (Clone Pod)" + build_path = "/obj/machinery/cloning/clonepod" + board_type = "machine" + origin_tech = "programming=3;biotech=3" + frame_desc = "Requires 2 Manipulator, 2 Scanning Module, and 1 Console Screen." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/clonescanner + name = "Circuit board (Cloning Scanner)" + build_path = "/obj/machinery/dna_scannernew" + board_type = "machine" + origin_tech = "programming=3;biotech=2" + frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro-Laser, and 1 Console Screen." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/fullbodyscanner + name = "Circuit board (Full Body Scanner)" + build_path = "/obj/machinery/bodyscanner" + board_type = "machine" + origin_tech = "biotech=2" + frame_desc = "Requires 3 Scanning Module." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 3) + +/obj/item/weapon/circuitboard/sleeper + name = "Circuit board (Sleeper)" + build_path = "/obj/machinery/sleeper" + board_type = "machine" + origin_tech = "biotech=2" + frame_desc = "Requires 1 Scanning Module, 2 Manipulator." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 2) + +/obj/item/weapon/circuitboard/biogenerator + name = "Circuit Board (Biogenerator)" + build_path = "/obj/machinery/biogenerator" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3" + frame_desc = "Requires 2 Manipulators, 2 Matter Bins, 3 Micro-Lasers, 2 Scanning Modules,2 Console Screens, and 1 Large Beaker. " + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 3, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 2, + "/obj/item/weapon/reagent_containers/glass/beaker/large" = 1) + +/obj/item/weapon/circuitboard/seed_extractor + name = "Circuit Board (Seed Extractor)" + build_path = "/obj/machinery/seed_extractor" + board_type = "machine" + origin_tech = "programming=2;biotech=2" + frame_desc = "Requires 2 Manipulators, 1 Matter Bins, 1 Micro-Lasers, 1 Scanning Modules, and 1 Console Screens. " + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/microwave + name = "Circuit Board (Microwave)" + build_path = "/obj/machinery/microwave" + board_type = "machine" + origin_tech = "programming=2;engineering=2;magnets=3" + frame_desc = "Requires 1 Micro-Laser, 1 Scanning Module, and 1 Console Screens. " + req_components = list( + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/reagentgrinder + name = "Circuit Board (All-In-One Grinder)" + build_path = "/obj/machinery/reagentgrinder" + board_type = "machine" + origin_tech = "programming=3;engineering=2" + frame_desc = "Requires 2 Matter Bins, 1 Micro-Lasers, 1 Scanning Modules, and 1 Large Beaker. " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/reagent_containers/glass/beaker/large" = 1) + +/obj/item/weapon/circuitboard/smartfridge + name = "Circuit Board (SmartFridge)" + build_path = "/obj/machinery/smartfridge" + board_type = "machine" + origin_tech = "programming=3;engineering=2" + frame_desc = "Requires 2 Manipulators, 4 Matter Bins, ,1 Scanning Module, and 2 Console Screens. " + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 4, + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 2) + +/obj/item/weapon/circuitboard/smartfridge/medbay + name = "Circuit Board (Medbay SmartFridge)" + build_path = "/obj/machinery/smartfridge/secure/medbay" + +/obj/item/weapon/circuitboard/smartfridge/chemistry + name = "Circuit Board (Chemical SmartFridge)" + build_path = "/obj/machinery/smartfridge/chemistry" + +/obj/item/weapon/circuitboard/smartfridge/extract + name = "Circuit Board (Extract SmartFridge)" + build_path = "/obj/machinery/smartfridge/extract" + +/obj/item/weapon/circuitboard/smartfridge/seeds + name = "Circuit Board (Megaseed Servitor)" + build_path = "/obj/machinery/smartfridge/seeds" + +/obj/item/weapon/circuitboard/smartfridge/drinks + name = "Circuit Board (Drinks Showcase)" + build_path = "/obj/machinery/smartfridge/drinks" + +/obj/item/weapon/circuitboard/hydroponics + name = "Circuit Board (Hydroponics Tray)" + build_path = "/obj/machinery/portable_atmospherics/hydroponics" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 2 Matter Bins, 1 Scanning Module, 2 Beakers, 1 Capacitor, and 1 Console Screen. " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/capacitor" = 1, + "/obj/item/weapon/reagent_containers/glass/beaker" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/gibber + name = "Circuit Board (Gibber)" + build_path = "/obj/machinery/gibber" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 2 Matter Bins, 2 Capacitors, 2 Scanning Module, 4 Manipulator and 4 High Powered Micro-Lasers " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 4, + "/obj/item/weapon/stock_parts/micro_laser/high" = 4) + +/obj/item/weapon/circuitboard/processor + name = "Circuit Board (Food Processor)" + build_path = "/obj/machinery/processor" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 1 Scanning Module and 2 Manipulators " + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 2) + +/obj/item/weapon/circuitboard/egg_incubator + name = "Circuit Board (Egg Incubator)" + build_path = "/obj/machinery/egg_incubator" + board_type = "machine" + origin_tech = "biotech=3" + frame_desc = "Requires 1 Matter Bin and 2 Capacitors " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/capacitor" = 2) + +/obj/item/weapon/circuitboard/monkey_recycler + name = "Circuit Board (Monkey Recycler)" + build_path = "/obj/machinery/monkey_recycler" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 1 Matter Bin, 2 Manipulators and 1 Micro-Laser " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 1) + +/* +/obj/item/weapon/circuitboard/hydroseeds + name = "Circuit Board (MegaSeed Servitor)" + build_path = "/obj/machinery/vending/hydroseeds" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2) + +/obj/item/weapon/circuitboard/hydronutrients + name = "Circuit Board (Nutrimax)" + build_path = "/obj/machinery/vending/hydronutrients" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2) +*/ + +/obj/item/weapon/circuitboard/pipedispenser + name = "Circuit Board (Pipe Dispenser)" + build_path = "/obj/machinery/pipedispenser" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2) + +/obj/item/weapon/circuitboard/pipedispenser/disposal + name = "Circuit Board (Disposal Pipe Dispenser)" + build_path = "/obj/machinery/pipedispenser/disposal" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3;powerstorage=2" + frame_desc = "Requires 2 Matter Bins, 1 Capacitors, 2 Scanning Module, and 2 Manipulators " + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 2) + + + + +//Teleporter +/obj/item/weapon/circuitboard/telehub + name = "Circuit Board (Teleporter Hub)" + build_path = "/obj/machinery/teleport/hub" + board_type = "machine" + origin_tech = "programming=4;engineering=3;bluespace=3" + frame_desc = "Requires 2 Phasic Scanning Modules, 3 Super Capacitors, 2 Subspace Ansibles, 2 Hyperwave filters, 1 Subspace Treatment Disc, 2 Ansible Crystals, and 4 Subspace Transmitters." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module/adv/phasic" = 2, + "/obj/item/weapon/stock_parts/capacitor/adv/super" = 3, + "/obj/item/weapon/stock_parts/subspace/ansible" = 2, + "/obj/item/weapon/stock_parts/subspace/filter" = 2, + "/obj/item/weapon/stock_parts/subspace/treatment" = 1, + "/obj/item/weapon/stock_parts/subspace/crystal" = 2, + "/obj/item/weapon/stock_parts/subspace/transmitter" = 4) + +/obj/item/weapon/circuitboard/telestation + name = "Circuit Board (Teleporter Station)" + build_path = "/obj/machinery/teleport/station" + board_type = "machine" + origin_tech = "programming=4;engineering=3;bluespace=3" + frame_desc = "Requires 2 Phasic Scanning Modules, 2 Super Capacitors, 2 Subspace Ansibles, and 4 Subspace Wavelength Analyzers." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module/adv/phasic" = 2, + "/obj/item/weapon/stock_parts/capacitor/adv/super" = 2, + "/obj/item/weapon/stock_parts/subspace/ansible" = 2, + "/obj/item/weapon/stock_parts/subspace/analyzer" = 4) + +// Telecomms circuit boards: + +/obj/item/weapon/circuitboard/telecomms/receiver + name = "Circuit Board (Subspace Receiver)" + build_path = "/obj/machinery/telecomms/receiver" + board_type = "machine" + origin_tech = "programming=4;engineering=3;bluespace=2" + frame_desc = "Requires 1 Subspace Ansible, 1 Hyperwave Filter, 2 Manipulators, and 1 Micro-Laser." + req_components = list( + "/obj/item/weapon/stock_parts/subspace/ansible" = 1, + "/obj/item/weapon/stock_parts/subspace/filter" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 1) + +/obj/item/weapon/circuitboard/telecomms/hub + name = "Circuit Board (Hub Mainframe)" + build_path = "/obj/machinery/telecomms/hub" + board_type = "machine" + origin_tech = "programming=4;engineering=4" + frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filter." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/stack/cable_coil" = 2, + "/obj/item/weapon/stock_parts/subspace/filter" = 2) + +/obj/item/weapon/circuitboard/telecomms/relay + name = "Circuit Board (Relay Mainframe)" + build_path = "/obj/machinery/telecomms/relay" + board_type = "machine" + origin_tech = "programming=3;engineering=4;bluespace=3" + frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filters." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/stack/cable_coil" = 2, + "/obj/item/weapon/stock_parts/subspace/filter" = 2) + +/obj/item/weapon/circuitboard/telecomms/bus + name = "Circuit Board (Bus Mainframe)" + build_path = "/obj/machinery/telecomms/bus" + board_type = "machine" + origin_tech = "programming=4;engineering=4" + frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/stack/cable_coil" = 1, + "/obj/item/weapon/stock_parts/subspace/filter" = 1) + +/obj/item/weapon/circuitboard/telecomms/processor + name = "Circuit Board (Processor Unit)" + build_path = "/obj/machinery/telecomms/processor" + board_type = "machine" + origin_tech = "programming=4;engineering=4" + frame_desc = "Requires 3 Manipulators, 1 Hyperwave Filter, 2 Treatment Disks, 1 Wavelength Analyzer, 2 Cable Coils and 1 Subspace Amplifier." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 3, + "/obj/item/weapon/stock_parts/subspace/filter" = 1, + "/obj/item/weapon/stock_parts/subspace/treatment" = 2, + "/obj/item/weapon/stock_parts/subspace/analyzer" = 1, + "/obj/item/stack/cable_coil" = 2, + "/obj/item/weapon/stock_parts/subspace/amplifier" = 1) + +/obj/item/weapon/circuitboard/telecomms/server + name = "Circuit Board (Telecommunication Server)" + build_path = "/obj/machinery/telecomms/server" + board_type = "machine" + origin_tech = "programming=4;engineering=4" + frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/stack/cable_coil" = 1, + "/obj/item/weapon/stock_parts/subspace/filter" = 1) + +/obj/item/weapon/circuitboard/telecomms/broadcaster + name = "Circuit Board (Subspace Broadcaster)" + build_path = "/obj/machinery/telecomms/broadcaster" + board_type = "machine" + origin_tech = "programming=4;engineering=4;bluespace=2" + frame_desc = "Requires 2 Manipulators, 1 Cable Coil, 1 Hyperwave Filter, 1 Ansible Crystal and 2 High-Powered Micro-Lasers. " + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/stack/cable_coil" = 1, + "/obj/item/weapon/stock_parts/subspace/filter" = 1, + "/obj/item/weapon/stock_parts/subspace/crystal" = 1, + "/obj/item/weapon/stock_parts/micro_laser/high" = 2) + +/obj/item/weapon/circuitboard/bioprinter + name = "Circuit Board (Bioprinter)" + build_path = "/obj/machinery/bioprinter" + board_type = "machine" + origin_tech = "programming=3;engineering=2;biotech=3" + frame_desc = "Requires 2 Manipulators, 2 Matter Bins, 3 Micro-Lasers, 2 Scanning Modules, 1 Console Screen. " + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 3, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/reverse_engine + name = "Circuit Board (Reverse Engine)" + build_path = "/obj/machinery/r_n_d/reverse_engine" + board_type = "machine" + origin_tech = "materials=6;programming=4;engineering=3;bluespace=3;powerstorage=4" + frame_desc = "Requires 2 Scanning Modules, 2 Capacitors, 1 Manipulator, and 1 Console Screen." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/capacitor" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/generalfab + name = "Circuit Board (General Fabricator)" + build_path = "/obj/machinery/r_n_d/fabricator/mechanic_fab" + board_type = "machine" + origin_tech = "materials=3;engineering=2;programming=3" + frame_desc = "Requires 2 Manipulators, 2 Matter Bins, and 2 Micro-Lasers." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 2) + +/obj/item/weapon/circuitboard/flatpacker + name = "Circuit Board (Flatpack Fabricator)" + build_path = "/obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker" + board_type = "machine" + origin_tech = "materials=5;engineering=4;powerstorage=3;programming=3" + frame_desc = "Requires 2 Manipulators, 2 Matter Bins, 2 Micro-Lasers, 2 Scanning Modules, and 1 Beaker." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/reagent_containers/glass/beaker" = 1) + +/obj/item/weapon/circuitboard/blueprinter + name = "Circuit Board (Blueprint Printer)" + build_path = "/obj/machinery/r_n_d/blueprinter" + board_type = "machine" + origin_tech = "engineering=3;programming=3" + frame_desc = "Requires 2 Matter Bins, 1 Scanning Module, and 1 Manipulator." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 1) + +/obj/item/weapon/circuitboard/vendomat + name = "Circuit Board (Vending Machine)" + build_path = "/obj/machinery/vending" + board_type = "machine" + origin_tech = "materials=1;engineering=1;powerstorage=1" + frame_desc = "Requires 1 Matter Bins, 1 Scanning Module, and 1 Manipulator." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 1) + +/obj/item/weapon/circuitboard/pdapainter + name = "Circuit Board (PDA Painter)" + build_path = "/obj/machinery/pdapainter" + board_type = "machine" + origin_tech = "programming=2;engineering=2" + frame_desc = "Requires 1 Manipulator, 2 Micro-Lasers, 2 Scanning Modules, and 1 Console Screen. " + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/incubator + name = "Circuit Board (Pathogenic Incubator)" + build_path = "/obj/machinery/disease2/incubator" + board_type = "machine" + origin_tech = "materials=4;biotech=5;magnets=3" + frame_desc = "Requires 1 Matter Bin, 2 Scanning Modules, 2 Micro-Lasers, and 1 Beaker." + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/reagent_containers/glass/beaker" = 1) + +/obj/item/weapon/circuitboard/diseaseanalyser + name = "Circuit Board (Disease Analyser)" + build_path = "/obj/machinery/disease2/diseaseanalyser" + board_type = "machine" + origin_tech = "engineering=3;biotech=3;programming=3" + frame_desc = "Requires 1 Micro-Laser, 1 Manipulator, and 3 Scanning Modules." + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/micro_laser" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 3) + +/obj/item/weapon/circuitboard/centrifuge + name = "Circuit Board (Isolation Centrifuge)" + build_path = "/obj/machinery/centrifuge" + board_type = "machine" + origin_tech = "biotech=3" + frame_desc = "Requires 2 Manipulators" + req_components = list( + "/obj/item/weapon/stock_parts/manipulator" = 2) + +/obj/item/weapon/circuitboard/mech_bay_power_port + name = "Circuit Board (Power Port)" + build_path = "/obj/machinery/mech_bay_recharge_port" + board_type = "machine" + origin_tech = "engineering=2;powerstorage=3" + frame_desc = "Requires 2 Micro-Lasers, and 1 Console Screen." + req_components = list( + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 1) + +/obj/item/weapon/circuitboard/mech_bay_recharge_station + name = "Circuit Board (Recharge Station)" + build_path = "/obj/machinery/mech_bay_recharge_floor" + board_type = "machine" + origin_tech = "materials=2;powerstorage=3" + frame_desc = "Requires 1 Scanning Module and 2 Capacitors." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/capacitor" = 2) + +/obj/item/weapon/circuitboard/prism + name = "Circuit Board (Prism)" + build_path = "/obj/machinery/prism" + board_type = "machine" + origin_tech = "programming=3;engineering=3;powerstorage=3" + frame_desc = "Requires 3 High-powered Micro-Lasers, and 6 Capacitors." + req_components = list( + "/obj/item/weapon/stock_parts/micro_laser/high" = 3, + "/obj/item/weapon/stock_parts/capacitor" = 6) + +/obj/item/weapon/circuitboard/cell_charger + name = "Circuit Board (Cell Charger)" + build_path = "/obj/machinery/cell_charger" + board_type = "machine" + origin_tech = "materials=2;engineering=2;powerstorage=3" + frame_desc = "Requires 1 Scanning Module and 2 Capacitors." + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/capacitor" = 2) + +/obj/item/weapon/circuitboard/washing_machine + name = "Circuit Board (Washing Machine)" + build_path = "/obj/machinery/washing_machine" + board_type = "machine" + origin_tech = "materials=1" + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 1) + +/obj/item/weapon/circuitboard/sorting_machine + name = "Circuit Board (Sorting Machine)" + board_type = "machine" + origin_tech = "materials=2;engineering=2;programming=3" + frame_desc = "Requires 3 Matter Bins and 1 Capacitor" //Matter bins because it's moving matter, I guess, and a capacitor because else the recipe is boring. + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 3, + "/obj/item/weapon/stock_parts/capacitor" = 1) + +/obj/item/weapon/circuitboard/sorting_machine/recycling + name = "Circuit Board (Recycling Sorting Machine)" + build_path = "/obj/machinery/sorting_machine/recycling" + +/obj/item/weapon/circuitboard/sorting_machine/destination + name = "Circuit Board (Destinations Sorting Machine)" + build_path = "/obj/machinery/sorting_machine/destination" + +/obj/item/weapon/circuitboard/processing_unit + name = "Circuit Board (Ore Processor)" + build_path = "/obj/machinery/mineral/processing_unit" + board_type = "machine" + origin_tech = "materials=3;engineering=2;programming=2" + frame_desc = "Requires 2 Matter Bins and 2 Micro-lasers" + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2) + +/obj/item/weapon/circuitboard/processing_unit/recycling + name = "Circuit Board (Recycling Furnace)" + build_path = "/obj/machinery/mineral/processing_unit/recycle" + +/obj/item/weapon/circuitboard/stacking_unit + name = "Circuit Board (Stacking Machine)" + build_path = "/obj/machinery/mineral/stacking_machine" + board_type = "machine" + origin_tech = "materials=3;engineering=2;programming=2" + frame_desc = "Requires 3 Matter Bins and 1 Capacitor" //Matter bins because it's moving matter, I guess, and a capacitor because else the recipe is boring. + req_components = list( + "/obj/item/weapon/stock_parts/matter_bin" = 3, + "/obj/item/weapon/stock_parts/capacitor" = 1) + +/obj/item/weapon/circuitboard/fax + name = "Circuit Board (Fax Machine)" + build_path = "/obj/machinery/faxmachine" + board_type = "machine" + origin_tech = "materials=2;bluespace=2" + frame_desc = "Requires 1 ansible and 1 scanning module." + req_components = list( + "/obj/item/weapon/stock_parts/subspace/ansible" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 1) + +/* + * Xenobotany +*/ + +/obj/item/weapon/circuitboard/botany_centrifuge + name = "Circuit Board (Lysis-Isolation Centrifuge)" + build_path = "/obj/machinery/botany/extractor" + board_type = "machine" + origin_tech = "engineering=3;biotech=3" + frame_desc = "Requires 1 manipulator, 2 scanning modules, 2 micro-lasers, 1 matter bin, and 2 console screens." + req_components = list ( + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 2, + "/obj/item/weapon/stock_parts/matter_bin" = 1) + +/obj/item/weapon/circuitboard/botany_bioballistic + name = "Circuit Board (Bioballistic Delivery System)" + build_path = "/obj/machinery/botany/editor" + board_type = "machine" + origin_tech = "engineering=3;biotech=3" + frame_desc = "Requires 1 manipulator, 2 scanning modules, 2 micro-lasers, and 1 console screen." + req_components = list ( + "/obj/item/weapon/stock_parts/manipulator" = 1, + "/obj/item/weapon/stock_parts/scanning_module" = 2, + "/obj/item/weapon/stock_parts/micro_laser" = 2, + "/obj/item/weapon/stock_parts/console_screen" = 1,) +/* + * Xenoarcheology +*/ + +/obj/item/weapon/circuitboard/anom + name = "Circuit Board (Fourier Transform Spectroscope)" + build_path = "/obj/machinery/anomaly/fourier_transform" + board_type = "machine" + origin_tech = "programming=4" + frame_desc = "Requires 3 scanning modules." + req_components = list ( + "/obj/item/weapon/stock_parts/scanning_module" = 3) + +/obj/item/weapon/circuitboard/anom/accelerator + name = "Circuit Board (Accelerator Spectrometer)" + build_path = "/obj/machinery/anomaly/accelerator" + +/obj/item/weapon/circuitboard/anom/gas + name = "Circuit Board (Gas Chromatography Spectrometer)" + build_path = "/obj/machinery/anomaly/gas_chromatography" + +/obj/item/weapon/circuitboard/anom/hyper + name = "Circuit Board (Hyperspectral Imager)" + build_path = "/obj/machinery/anomaly/hyperspectral" + +/obj/item/weapon/circuitboard/anom/ion + name = "Circuit Board (Ion Mobility Spectrometer)" + build_path = "/obj/machinery/anomaly/ion_mobility" + +/obj/item/weapon/circuitboard/anom/iso + name = "Circuit Board (Isotope Ratio Spectrometer)" + build_path = "/obj/machinery/anomaly/isotope_ratio" diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 0b05afba46b..e93955f1283 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -1,512 +1,512 @@ -var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_full"),\ - "good" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_good"),\ - "average" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_average"),\ - "bad" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_bad"),\ - "worse" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_worse"),\ - "crit" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_crit"),\ - "dead" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_dead")) -/obj/machinery/atmospherics/unary/cryo_cell - name = "cryo cell" - icon = 'icons/obj/cryogenics.dmi' - icon_state = "cell-off" - density = 1 - anchored = 1.0 - layer = 2.8 - - var/on = 0 - var/temperature_archived - var/mob/living/carbon/occupant = null - var/obj/item/weapon/reagent_containers/glass/beaker = null - - var/current_heat_capacity = 50 - - machine_flags = SCREWTOGGLE | CROWDESTROY - - light_color = LIGHT_COLOR_GREEN - light_range_on = 1 - light_power_on = 2 - use_auto_lights = 1 - -/obj/machinery/atmospherics/unary/cryo_cell/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/cryo, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - - initialize_directions = dir - initialize() - build_network() - if (node) - node.initialize() - node.build_network() - -/obj/machinery/atmospherics/unary/cryo_cell/initialize() - if(node) return - for(var/cdir in cardinal) - node = findConnecting(cdir) - if(node) - break - update_icon() - -/obj/machinery/atmospherics/unary/cryo_cell/Destroy() - go_out() - if(beaker) - detach() - //beaker.loc = get_step(loc, SOUTH) //Beaker is carefully ejected from the wreckage of the cryotube - ..() - -/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if(!ismob(O)) //humans only - return - if(O.loc == user) //no you can't pull things out of your ass - return - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other - return - if(O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src)) // is the mob anchored, too far away from you, or are you too far away from the source - return - if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit - return - if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper - return - if(user.loc==null) // just in case someone manages to get a closet into the blue light dimension, as unlikely as that seems - return - if(!istype(user.loc, /turf) || !istype(O.loc, /turf)) // are you in a container/closet/pod/etc? - return - if(occupant) - to_chat(user, "The cryo cell is already occupied!") - return - if(isrobot(user)) - var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) - to_chat(user, "You do not have the means to do this!") - return - var/mob/living/L = O - if(!istype(L) || L.locked_to) - return - /*if(L.abiotic()) - to_chat(user, "Subject cannot have abiotic items on.") - return*/ - for(var/mob/living/carbon/slime/M in range(1,L)) - if(M.Victim == L) - to_chat(usr, "[L.name] will not fit into the cryo cell because they have a slime latched onto their head.") - return - if(put_mob(L)) - if(L == user) - visible_message("[user] climbs into \the [src].", 2) //spooky - else - visible_message("[user] puts [L.name] into \the [src].", 2) //spooky - if(user.pulling == L) - user.pulling = null - -/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) - if(!ishuman(usr) && !isrobot(usr) || occupant == usr) - return - if(!occupant) - to_chat(usr, "The sleeper is unoccupied!") - return - if(isrobot(usr)) - var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) - to_chat(usr, "You do not have the means to do this!") - return - if(!istype(over_location) || over_location.density) - return - if(!Adjacent(over_location) || !Adjacent(usr) || !usr.Adjacent(over_location)) - return - for(var/atom/movable/A in over_location.contents) - if(A.density) - if((A == src) || istype(A, /mob)) - continue - return - visible_message("[usr] removes [occupant.name] from \the [src].", 2) //spooky - go_out(over_location) - -/obj/machinery/atmospherics/unary/cryo_cell/process() - ..() - update_icon() - if(!node) - return - if(!on) - updateUsrDialog() - return - - if(occupant) - if(occupant.stat != 2) - process_occupant() - - if(air_contents) - temperature_archived = air_contents.temperature - heat_gas_contents() - expel_gas() - - if(abs(temperature_archived-air_contents.temperature) > 1) - network.update = 1 - - updateUsrDialog() - return 1 - - -/obj/machinery/atmospherics/unary/cryo_cell/allow_drop() - return 0 - - -/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob) - if(user.stat) - return - go_out() - return - -/obj/machinery/atmospherics/unary/cryo_cell/examine(mob/user) - ..() - if(Adjacent(user)) - if(contents) - to_chat(user, "You can just about make out some properties of the cryo's murky depths:") - for(var/atom/movable/floater in (contents - beaker)) - to_chat(user, "A figure floats in the depths, they appear to be [floater.name]") - if(beaker) - to_chat(user, "A beaker, releasing the following chemicals into the fluids:") - for(var/datum/reagent/R in beaker.reagents.reagent_list) - to_chat(user, "[R.volume] units of [R.name]") - else - to_chat(user, "The chamber appears devoid of anything but its biotic fluids.") - else - to_chat(user, "Too far away to view contents.") - -/obj/machinery/atmospherics/unary/cryo_cell/attack_hand(mob/user) - ui_interact(user) - - /** - * The ui_interact proc is used to open and update Nano UIs - * If ui_interact is not used then the UI will not update correctly - * ui_interact is currently defined for /atom/movable (which is inherited by /obj and /mob) - * - * @param user /mob The mob who is interacting with this ui - * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") - * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui - * - * @return nothing - */ -/obj/machinery/atmospherics/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - - if(user == occupant || (user.stat && !isobserver(user))) - return - - // this is the data which will be sent to the ui - var/data[0] - data["isOperating"] = on - data["hasOccupant"] = occupant ? 1 : 0 - - var/occupantData[0] - if (occupant) - occupantData["name"] = occupant.name - occupantData["stat"] = occupant.stat - occupantData["health"] = occupant.health - occupantData["maxHealth"] = occupant.maxHealth - occupantData["minHealth"] = config.health_threshold_dead - occupantData["bruteLoss"] = occupant.getBruteLoss() - occupantData["oxyLoss"] = occupant.getOxyLoss() - occupantData["toxLoss"] = occupant.getToxLoss() - occupantData["fireLoss"] = occupant.getFireLoss() - occupantData["bodyTemperature"] = occupant.bodytemperature - data["occupant"] = occupantData; - - data["cellTemperature"] = round(air_contents.temperature) - data["cellTemperatureStatus"] = "good" - if(air_contents.temperature > T0C) // if greater than 273.15 kelvin (0 celcius) - data["cellTemperatureStatus"] = "bad" - else if(air_contents.temperature > 225) - data["cellTemperatureStatus"] = "average" - - data["isBeakerLoaded"] = beaker ? 1 : 0 - /* // Removing beaker contents list from front-end, replacing with a total remaining volume - var beakerContents[0] - if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... - data["beakerContents"] = beakerContents - */ - data["beakerLabel"] = null - data["beakerVolume"] = 0 - if(beaker) - data["beakerLabel"] = beaker.label_text ? beaker.label_text : null - if (beaker.reagents && beaker.reagents.reagent_list.len) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - data["beakerVolume"] += R.volume - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 410) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -/obj/machinery/atmospherics/unary/cryo_cell/Topic(href, href_list) - if(usr == occupant) - return 0 // don't update UIs attached to this object - - if(..()) - return 0 // don't update UIs attached to this object - - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - - if(href_list["switchOn"]) - on = 1 - update_icon() - - if(href_list["switchOff"]) - on = 0 - update_icon() - - if(href_list["ejectBeaker"]) - if(beaker) - detach() - - if(href_list["ejectOccupant"]) - if(!occupant || isslime(usr) || ispAI(usr)) - return 0 // don't update UIs attached to this object - go_out() - - add_fingerprint(usr) - return 1 // update UIs attached to this object -/obj/machinery/atmospherics/unary/cryo_cell/proc/detach() - if(beaker) - beaker.loc = get_step(loc, SOUTH) - if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) - var/mob/living/silicon/robot/R = beaker:holder:loc - if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) - beaker.loc = R - else - beaker.loc = beaker:holder - beaker = null - -/obj/machinery/atmospherics/unary/cryo_cell/crowbarDestroy(mob/user) - if(on) - to_chat(user, "[src] is on.") - return - if(occupant) - to_chat(user, "[occupant.name] is inside the [src]!") - return - if(beaker) //special check to avoid destroying this - detach() - return ..() - -/obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) - if(istype(G, /obj/item/weapon/reagent_containers/glass)) - if(beaker) - to_chat(user, "A beaker is already loaded into the machine.") - return - if(user.drop_item(G, src)) - beaker = G - user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") - if(istype(G, /obj/item/weapon/wrench))//FUCK YOU PARENT, YOU AREN'T MY REAL DAD - return - if(..()) - return - if (panel_open) - user.set_machine(src) - interact(user) - return 1 - if(istype(G, /obj/item/weapon/grab)) - if(!ismob(G:affecting)) - return - for(var/mob/living/carbon/slime/M in range(1,G:affecting)) - if(M.Victim == G:affecting) - to_chat(usr, "[G:affecting:name] will not fit into the cryo because they have a slime latched onto their head.") - return - var/mob/M = G:affecting - if(put_mob(M)) - qdel(G) - G = null - updateUsrDialog() - return - -/obj/machinery/atmospherics/unary/cryo_cell/update_icon() - overlays.len = 0 - if(on) - if(occupant) - if(occupant.stat == DEAD || !occupant.has_brain()) - overlays += cryo_health_indicator["dead"] - else - if(occupant.health >= occupant.maxHealth) - overlays += cryo_health_indicator["full"] - else - if(occupant.health < config.health_threshold_crit) - overlays += cryo_health_indicator["crit"] - else - switch((occupant.health / occupant.maxHealth) * 100) // Get a ratio of health to work with - if(100 to INFINITY) // No idea how we got here with the check above... - overlays += cryo_health_indicator["full"] - if(75 to 100) - overlays += cryo_health_indicator["good"] - if(50 to 75) - overlays += cryo_health_indicator["average"] - if(25 to 50) - overlays += cryo_health_indicator["bad"] - if(1 to 25) - overlays += cryo_health_indicator["worse"] - else //Shouldn't ever happen. - overlays += cryo_health_indicator["dead"] - icon_state = "cell-occupied" - return - icon_state = "cell-on" - return - icon_state = "cell-off" - -/obj/machinery/atmospherics/unary/cryo_cell/proc/process_occupant() - if(air_contents.total_moles() < 10) - return - if(occupant) - if(occupant.stat == 2) - return - occupant.bodytemperature += 2*(air_contents.temperature - occupant.bodytemperature)*current_heat_capacity/(current_heat_capacity + air_contents.heat_capacity()) - occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise - occupant.stat = 1 - if(occupant.bodytemperature < T0C) - occupant.sleeping = max(5, (1/occupant.bodytemperature)*2000) - occupant.Paralyse(max(5, (1/occupant.bodytemperature)*3000)) - if(air_contents.oxygen > 2) - if(occupant.getOxyLoss()) occupant.adjustOxyLoss(-1) - else - occupant.adjustOxyLoss(-1) - //severe damage should heal waaay slower without proper chemicals - if(occupant.bodytemperature < 225) - if (occupant.getToxLoss()) - occupant.adjustToxLoss(max(-1, -20/occupant.getToxLoss())) - var/heal_brute = occupant.getBruteLoss() ? min(1, 20/occupant.getBruteLoss()) : 0 - var/heal_fire = occupant.getFireLoss() ? min(1, 20/occupant.getFireLoss()) : 0 - occupant.heal_organ_damage(heal_brute,heal_fire) - var/has_cryo = occupant.reagents.get_reagent_amount("cryoxadone") >= 1 - var/has_clonexa = occupant.reagents.get_reagent_amount("clonexadone") >= 1 - var/has_cryo_medicine = has_cryo || has_clonexa - if(beaker && !has_cryo_medicine) - beaker.reagents.trans_to(occupant, 1, 1) - beaker.reagents.reaction(occupant) - -/obj/machinery/atmospherics/unary/cryo_cell/proc/heat_gas_contents() - if(air_contents.total_moles() < 1) - return - var/air_heat_capacity = air_contents.heat_capacity() - var/combined_heat_capacity = current_heat_capacity + air_heat_capacity - if(combined_heat_capacity > 0) - var/combined_energy = T20C*current_heat_capacity + air_heat_capacity*air_contents.temperature - air_contents.temperature = combined_energy/combined_heat_capacity - -/obj/machinery/atmospherics/unary/cryo_cell/proc/expel_gas() - if(air_contents.total_moles() < 1) - return -// var/datum/gas_mixture/expel_gas = new -// var/remove_amount = air_contents.total_moles()/50 -// expel_gas = air_contents.remove(remove_amount) - - // Just have the gas disappear to nowhere. - //expel_gas.temperature = T20C // Lets expel hot gas and see if that helps people not die as they are removed - //loc.assume_air(expel_gas) - -/obj/machinery/atmospherics/unary/cryo_cell/proc/go_out(var/exit = src.loc) - if(!(occupant)) - return 0 - for (var/atom/movable/x in src.contents) - if((x in component_parts) || (x == src.beaker)) - continue - x.forceMove(src.loc) - if(exit == loc) - occupant.forceMove(get_step(loc, SOUTH)) //this doesn't account for walls or anything, but i don't forsee that being a problem. - else - occupant.forceMove(exit) - occupant.reset_view() - if (occupant.bodytemperature < 261 && occupant.bodytemperature > 140) //Patch by Aranclanos to stop people from taking burn damage after being ejected - occupant.bodytemperature = 261 -// occupant.metabslow = 0 - occupant = null - update_icon() - return 1 -/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob) - if (!istype(M)) - to_chat(usr, "The cryo cell cannot handle such a lifeform!") - return - if (occupant) - to_chat(usr, "The cryo cell is already occupied!") - return - /*if (M.abiotic()) - to_chat(usr, "Subject may not have abiotic items on.") - return*/ - if(M.locked_to) - M.locked_to.unlock_atom(M) - if(!node) - to_chat(usr, "The cell is not correctly connected to its pipe network!") - return - if(usr.pulling == M) - usr.stop_pulling() - M.stop_pulling() - M.loc = src - M.reset_view() - if(M.health > -100 && (M.health < 0 || M.sleeping)) - to_chat(M, "You feel a cold liquid surround you. Your skin starts to freeze up.") - occupant = M - //M.metabslow = 1 - add_fingerprint(usr) - update_icon() - M.ExtinguishMob() - return 1 - -/obj/machinery/atmospherics/unary/cryo_cell/verb/move_eject() - set name = "Eject occupant" - set category = "Object" - set src in oview(1) - if(usr == occupant)//If the user is inside the tube... - if (usr.isDead())//and he's not dead.... - return - to_chat(usr, "Release sequence activated. This will take two minutes.") - sleep(1200) - if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already - return - go_out()//and release him from the eternal prison. - else - if (usr.isUnconscious() || istype(usr, /mob/living/simple_animal)) - return - go_out() - add_fingerprint(usr) - return - -/obj/machinery/atmospherics/unary/cryo_cell/verb/move_inside() - set name = "Move Inside" - set category = "Object" - set src in oview(1) - if(usr.restrained() || usr.isUnconscious() || usr.weakened || usr.stunned || usr.paralysis || usr.resting || usr.locked_to) //are you cuffed, dying, lying, stunned or other - return - for(var/mob/living/carbon/slime/M in range(1,usr)) - if(M.Victim == usr) - to_chat(usr, "You're too busy getting your life sucked out of you.") - return - if (usr.isUnconscious() || stat & (NOPOWER|BROKEN)) - return - put_mob(usr) - return - - - -/datum/data/function/proc/reset() - return - -/datum/data/function/proc/r_input(href, href_list, mob/user as mob) - return - -/datum/data/function/proc/display() - return +var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_full"),\ + "good" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_good"),\ + "average" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_average"),\ + "bad" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_bad"),\ + "worse" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_worse"),\ + "crit" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_crit"),\ + "dead" = image("icon" = 'icons/obj/cryogenics.dmi', "icon_state" = "moverlay_dead")) +/obj/machinery/atmospherics/unary/cryo_cell + name = "cryo cell" + icon = 'icons/obj/cryogenics.dmi' + icon_state = "cell-off" + density = 1 + anchored = 1.0 + layer = 2.8 + + var/on = 0 + var/temperature_archived + var/mob/living/carbon/occupant = null + var/obj/item/weapon/reagent_containers/glass/beaker = null + + var/current_heat_capacity = 50 + + machine_flags = SCREWTOGGLE | CROWDESTROY + + light_color = LIGHT_COLOR_GREEN + light_range_on = 1 + light_power_on = 2 + use_auto_lights = 1 + +/obj/machinery/atmospherics/unary/cryo_cell/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/cryo, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + + initialize_directions = dir + initialize() + build_network() + if (node) + node.initialize() + node.build_network() + +/obj/machinery/atmospherics/unary/cryo_cell/initialize() + if(node) return + for(var/cdir in cardinal) + node = findConnecting(cdir) + if(node) + break + update_icon() + +/obj/machinery/atmospherics/unary/cryo_cell/Destroy() + go_out() + if(beaker) + detach() + //beaker.loc = get_step(loc, SOUTH) //Beaker is carefully ejected from the wreckage of the cryotube + ..() + +/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if(!ismob(O)) //humans only + return + if(O.loc == user) //no you can't pull things out of your ass + return + if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other + return + if(O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src)) // is the mob anchored, too far away from you, or are you too far away from the source + return + if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit + return + if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper + return + if(user.loc==null) // just in case someone manages to get a closet into the blue light dimension, as unlikely as that seems + return + if(!istype(user.loc, /turf) || !istype(O.loc, /turf)) // are you in a container/closet/pod/etc? + return + if(occupant) + to_chat(user, "The cryo cell is already occupied!") + return + if(isrobot(user)) + var/mob/living/silicon/robot/robit = usr + if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + to_chat(user, "You do not have the means to do this!") + return + var/mob/living/L = O + if(!istype(L) || L.locked_to) + return + /*if(L.abiotic()) + to_chat(user, "Subject cannot have abiotic items on.") + return*/ + for(var/mob/living/carbon/slime/M in range(1,L)) + if(M.Victim == L) + to_chat(usr, "[L.name] will not fit into the cryo cell because they have a slime latched onto their head.") + return + if(put_mob(L)) + if(L == user) + visible_message("[user] climbs into \the [src].", 2) //spooky + else + visible_message("[user] puts [L.name] into \the [src].", 2) //spooky + if(user.pulling == L) + user.pulling = null + +/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) + if(!ishuman(usr) && !isrobot(usr) || occupant == usr) + return + if(!occupant) + to_chat(usr, "The sleeper is unoccupied!") + return + if(isrobot(usr)) + var/mob/living/silicon/robot/robit = usr + if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + to_chat(usr, "You do not have the means to do this!") + return + if(!istype(over_location) || over_location.density) + return + if(!Adjacent(over_location) || !Adjacent(usr) || !usr.Adjacent(over_location)) + return + for(var/atom/movable/A in over_location.contents) + if(A.density) + if((A == src) || istype(A, /mob)) + continue + return + visible_message("[usr] removes [occupant.name] from \the [src].", 2) //spooky + go_out(over_location) + +/obj/machinery/atmospherics/unary/cryo_cell/process() + ..() + update_icon() + if(!node) + return + if(!on) + updateUsrDialog() + return + + if(occupant) + if(occupant.stat != 2) + process_occupant() + + if(air_contents) + temperature_archived = air_contents.temperature + heat_gas_contents() + expel_gas() + + if(abs(temperature_archived-air_contents.temperature) > 1) + network.update = 1 + + updateUsrDialog() + return 1 + + +/obj/machinery/atmospherics/unary/cryo_cell/allow_drop() + return 0 + + +/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob) + if(user.stat) + return + go_out() + return + +/obj/machinery/atmospherics/unary/cryo_cell/examine(mob/user) + ..() + if(Adjacent(user)) + if(contents) + to_chat(user, "You can just about make out some properties of the cryo's murky depths:") + for(var/atom/movable/floater in (contents - beaker)) + to_chat(user, "A figure floats in the depths, they appear to be [floater.name]") + if(beaker) + to_chat(user, "A beaker, releasing the following chemicals into the fluids:") + for(var/datum/reagent/R in beaker.reagents.reagent_list) + to_chat(user, "[R.volume] units of [R.name]") + else + to_chat(user, "The chamber appears devoid of anything but its biotic fluids.") + else + to_chat(user, "Too far away to view contents.") + +/obj/machinery/atmospherics/unary/cryo_cell/attack_hand(mob/user) + ui_interact(user) + + /** + * The ui_interact proc is used to open and update Nano UIs + * If ui_interact is not used then the UI will not update correctly + * ui_interact is currently defined for /atom/movable (which is inherited by /obj and /mob) + * + * @param user /mob The mob who is interacting with this ui + * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") + * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui + * + * @return nothing + */ +/obj/machinery/atmospherics/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + + if(user == occupant || (user.stat && !isobserver(user))) + return + + // this is the data which will be sent to the ui + var/data[0] + data["isOperating"] = on + data["hasOccupant"] = occupant ? 1 : 0 + + var/occupantData[0] + if (occupant) + occupantData["name"] = occupant.name + occupantData["stat"] = occupant.stat + occupantData["health"] = occupant.health + occupantData["maxHealth"] = occupant.maxHealth + occupantData["minHealth"] = config.health_threshold_dead + occupantData["bruteLoss"] = occupant.getBruteLoss() + occupantData["oxyLoss"] = occupant.getOxyLoss() + occupantData["toxLoss"] = occupant.getToxLoss() + occupantData["fireLoss"] = occupant.getFireLoss() + occupantData["bodyTemperature"] = occupant.bodytemperature + data["occupant"] = occupantData; + + data["cellTemperature"] = round(air_contents.temperature) + data["cellTemperatureStatus"] = "good" + if(air_contents.temperature > T0C) // if greater than 273.15 kelvin (0 celcius) + data["cellTemperatureStatus"] = "bad" + else if(air_contents.temperature > 225) + data["cellTemperatureStatus"] = "average" + + data["isBeakerLoaded"] = beaker ? 1 : 0 + /* // Removing beaker contents list from front-end, replacing with a total remaining volume + var beakerContents[0] + if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) + for(var/datum/reagent/R in beaker.reagents.reagent_list) + beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... + data["beakerContents"] = beakerContents + */ + data["beakerLabel"] = null + data["beakerVolume"] = 0 + if(beaker) + data["beakerLabel"] = beaker.label_text ? beaker.label_text : null + if (beaker.reagents && beaker.reagents.reagent_list.len) + for(var/datum/reagent/R in beaker.reagents.reagent_list) + data["beakerVolume"] += R.volume + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 410) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/machinery/atmospherics/unary/cryo_cell/Topic(href, href_list) + if(usr == occupant) + return 0 // don't update UIs attached to this object + + if(..()) + return 0 // don't update UIs attached to this object + + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + + if(href_list["switchOn"]) + on = 1 + update_icon() + + if(href_list["switchOff"]) + on = 0 + update_icon() + + if(href_list["ejectBeaker"]) + if(beaker) + detach() + + if(href_list["ejectOccupant"]) + if(!occupant || isslime(usr) || ispAI(usr)) + return 0 // don't update UIs attached to this object + go_out() + + add_fingerprint(usr) + return 1 // update UIs attached to this object +/obj/machinery/atmospherics/unary/cryo_cell/proc/detach() + if(beaker) + beaker.loc = get_step(loc, SOUTH) + if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) + var/mob/living/silicon/robot/R = beaker:holder:loc + if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) + beaker.loc = R + else + beaker.loc = beaker:holder + beaker = null + +/obj/machinery/atmospherics/unary/cryo_cell/crowbarDestroy(mob/user) + if(on) + to_chat(user, "[src] is on.") + return + if(occupant) + to_chat(user, "[occupant.name] is inside the [src]!") + return + if(beaker) //special check to avoid destroying this + detach() + return ..() + +/obj/machinery/atmospherics/unary/cryo_cell/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) + if(istype(G, /obj/item/weapon/reagent_containers/glass)) + if(beaker) + to_chat(user, "A beaker is already loaded into the machine.") + return + if(user.drop_item(G, src)) + beaker = G + user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!") + if(istype(G, /obj/item/weapon/wrench))//FUCK YOU PARENT, YOU AREN'T MY REAL DAD + return + if(..()) + return + if (panel_open) + user.set_machine(src) + interact(user) + return 1 + if(istype(G, /obj/item/weapon/grab)) + if(!ismob(G:affecting)) + return + for(var/mob/living/carbon/slime/M in range(1,G:affecting)) + if(M.Victim == G:affecting) + to_chat(usr, "[G:affecting:name] will not fit into the cryo because they have a slime latched onto their head.") + return + var/mob/M = G:affecting + if(put_mob(M)) + qdel(G) + G = null + updateUsrDialog() + return + +/obj/machinery/atmospherics/unary/cryo_cell/update_icon() + overlays.len = 0 + if(on) + if(occupant) + if(occupant.stat == DEAD || !occupant.has_brain()) + overlays += cryo_health_indicator["dead"] + else + if(occupant.health >= occupant.maxHealth) + overlays += cryo_health_indicator["full"] + else + if(occupant.health < config.health_threshold_crit) + overlays += cryo_health_indicator["crit"] + else + switch((occupant.health / occupant.maxHealth) * 100) // Get a ratio of health to work with + if(100 to INFINITY) // No idea how we got here with the check above... + overlays += cryo_health_indicator["full"] + if(75 to 100) + overlays += cryo_health_indicator["good"] + if(50 to 75) + overlays += cryo_health_indicator["average"] + if(25 to 50) + overlays += cryo_health_indicator["bad"] + if(1 to 25) + overlays += cryo_health_indicator["worse"] + else //Shouldn't ever happen. + overlays += cryo_health_indicator["dead"] + icon_state = "cell-occupied" + return + icon_state = "cell-on" + return + icon_state = "cell-off" + +/obj/machinery/atmospherics/unary/cryo_cell/proc/process_occupant() + if(air_contents.total_moles() < 10) + return + if(occupant) + if(occupant.stat == 2) + return + occupant.bodytemperature += 2*(air_contents.temperature - occupant.bodytemperature)*current_heat_capacity/(current_heat_capacity + air_contents.heat_capacity()) + occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise + occupant.stat = 1 + if(occupant.bodytemperature < T0C) + occupant.sleeping = max(5, (1/occupant.bodytemperature)*2000) + occupant.Paralyse(max(5, (1/occupant.bodytemperature)*3000)) + if(air_contents.oxygen > 2) + if(occupant.getOxyLoss()) occupant.adjustOxyLoss(-1) + else + occupant.adjustOxyLoss(-1) + //severe damage should heal waaay slower without proper chemicals + if(occupant.bodytemperature < 225) + if (occupant.getToxLoss()) + occupant.adjustToxLoss(max(-1, -20/occupant.getToxLoss())) + var/heal_brute = occupant.getBruteLoss() ? min(1, 20/occupant.getBruteLoss()) : 0 + var/heal_fire = occupant.getFireLoss() ? min(1, 20/occupant.getFireLoss()) : 0 + occupant.heal_organ_damage(heal_brute,heal_fire) + var/has_cryo = occupant.reagents.get_reagent_amount("cryoxadone") >= 1 + var/has_clonexa = occupant.reagents.get_reagent_amount("clonexadone") >= 1 + var/has_cryo_medicine = has_cryo || has_clonexa + if(beaker && !has_cryo_medicine) + beaker.reagents.trans_to(occupant, 1, 1) + beaker.reagents.reaction(occupant) + +/obj/machinery/atmospherics/unary/cryo_cell/proc/heat_gas_contents() + if(air_contents.total_moles() < 1) + return + var/air_heat_capacity = air_contents.heat_capacity() + var/combined_heat_capacity = current_heat_capacity + air_heat_capacity + if(combined_heat_capacity > 0) + var/combined_energy = T20C*current_heat_capacity + air_heat_capacity*air_contents.temperature + air_contents.temperature = combined_energy/combined_heat_capacity + +/obj/machinery/atmospherics/unary/cryo_cell/proc/expel_gas() + if(air_contents.total_moles() < 1) + return +// var/datum/gas_mixture/expel_gas = new +// var/remove_amount = air_contents.total_moles()/50 +// expel_gas = air_contents.remove(remove_amount) + + // Just have the gas disappear to nowhere. + //expel_gas.temperature = T20C // Lets expel hot gas and see if that helps people not die as they are removed + //loc.assume_air(expel_gas) + +/obj/machinery/atmospherics/unary/cryo_cell/proc/go_out(var/exit = src.loc) + if(!(occupant)) + return 0 + for (var/atom/movable/x in src.contents) + if((x in component_parts) || (x == src.beaker)) + continue + x.forceMove(src.loc) + if(exit == loc) + occupant.forceMove(get_step(loc, SOUTH)) //this doesn't account for walls or anything, but i don't forsee that being a problem. + else + occupant.forceMove(exit) + occupant.reset_view() + if (occupant.bodytemperature < 261 && occupant.bodytemperature > 140) //Patch by Aranclanos to stop people from taking burn damage after being ejected + occupant.bodytemperature = 261 +// occupant.metabslow = 0 + occupant = null + update_icon() + return 1 +/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob) + if (!istype(M)) + to_chat(usr, "The cryo cell cannot handle such a lifeform!") + return + if (occupant) + to_chat(usr, "The cryo cell is already occupied!") + return + /*if (M.abiotic()) + to_chat(usr, "Subject may not have abiotic items on.") + return*/ + if(M.locked_to) + M.locked_to.unlock_atom(M) + if(!node) + to_chat(usr, "The cell is not correctly connected to its pipe network!") + return + if(usr.pulling == M) + usr.stop_pulling() + M.stop_pulling() + M.loc = src + M.reset_view() + if(M.health > -100 && (M.health < 0 || M.sleeping)) + to_chat(M, "You feel a cold liquid surround you. Your skin starts to freeze up.") + occupant = M + //M.metabslow = 1 + add_fingerprint(usr) + update_icon() + M.ExtinguishMob() + return 1 + +/obj/machinery/atmospherics/unary/cryo_cell/verb/move_eject() + set name = "Eject occupant" + set category = "Object" + set src in oview(1) + if(usr == occupant)//If the user is inside the tube... + if (usr.isDead())//and he's not dead.... + return + to_chat(usr, "Release sequence activated. This will take two minutes.") + sleep(1200) + if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already + return + go_out()//and release him from the eternal prison. + else + if (usr.isUnconscious() || istype(usr, /mob/living/simple_animal)) + return + go_out() + add_fingerprint(usr) + return + +/obj/machinery/atmospherics/unary/cryo_cell/verb/move_inside() + set name = "Move Inside" + set category = "Object" + set src in oview(1) + if(usr.restrained() || usr.isUnconscious() || usr.weakened || usr.stunned || usr.paralysis || usr.resting || usr.locked_to) //are you cuffed, dying, lying, stunned or other + return + for(var/mob/living/carbon/slime/M in range(1,usr)) + if(M.Victim == usr) + to_chat(usr, "You're too busy getting your life sucked out of you.") + return + if (usr.isUnconscious() || stat & (NOPOWER|BROKEN)) + return + put_mob(usr) + return + + + +/datum/data/function/proc/reset() + return + +/datum/data/function/proc/r_input(href, href_list, mob/user as mob) + return + +/datum/data/function/proc/display() + return diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index fcf45e61cc4..075aadc70ba 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -1,161 +1,161 @@ -/* -CONTAINS: - -Deployable items -Barricades - -for reference: - - access_security = 1 - access_brig = 2 - access_armory = 3 - access_forensics_lockers= 4 - access_medical = 5 - access_morgue = 6 - access_tox = 7 - access_tox_storage = 8 - access_genetics = 9 - access_engine = 10 - access_engine_equip= 11 - access_maint_tunnels = 12 - access_external_airlocks = 13 - access_emergency_storage = 14 - access_change_ids = 15 - access_ai_upload = 16 - access_teleporter = 17 - access_eva = 18 - access_heads = 19 - access_captain = 20 - access_all_personal_lockers = 21 - access_chapel_office = 22 - access_tech_storage = 23 - access_atmospherics = 24 - access_bar = 25 - access_janitor = 26 - access_crematorium = 27 - access_kitchen = 28 - access_robotics = 29 - access_rd = 30 - access_cargo = 31 - access_construction = 32 - access_chemistry = 33 - access_cargo_bot = 34 - access_hydroponics = 35 - access_manufacturing = 36 - access_library = 37 - access_lawyer = 38 - access_virology = 39 - access_cmo = 40 - access_qm = 41 - access_court = 42 - access_clown = 43 - access_mime = 44 - -*/ - -//Actual Deployable machinery stuff - -/obj/machinery/deployable - name = "deployable" - desc = "deployable" - icon = 'icons/obj/objects.dmi' - req_access = list(access_security)//I'm changing this until these are properly tested./N - -/obj/machinery/deployable/barrier - name = "deployable barrier" - desc = "A deployable barrier. Swipe your ID card to lock/unlock it." - icon = 'icons/obj/objects.dmi' - anchored = 0.0 - density = 1.0 - icon_state = "barrier0" - var/health = 140.0 - var/maxhealth = 140.0 - var/locked = 0.0 -// req_access = list(access_maint_tunnels) - - machine_flags = EMAGGABLE - -/obj/machinery/deployable/barrier/New() - ..() - - src.icon_state = "barrier[src.locked]" - -/obj/machinery/deployable/barrier/emag(mob/user) - if (src.emagged == 0) - src.emagged = 1 - src.req_access = 0 +/* +CONTAINS: + +Deployable items +Barricades + +for reference: + + access_security = 1 + access_brig = 2 + access_armory = 3 + access_forensics_lockers= 4 + access_medical = 5 + access_morgue = 6 + access_tox = 7 + access_tox_storage = 8 + access_genetics = 9 + access_engine = 10 + access_engine_equip= 11 + access_maint_tunnels = 12 + access_external_airlocks = 13 + access_emergency_storage = 14 + access_change_ids = 15 + access_ai_upload = 16 + access_teleporter = 17 + access_eva = 18 + access_heads = 19 + access_captain = 20 + access_all_personal_lockers = 21 + access_chapel_office = 22 + access_tech_storage = 23 + access_atmospherics = 24 + access_bar = 25 + access_janitor = 26 + access_crematorium = 27 + access_kitchen = 28 + access_robotics = 29 + access_rd = 30 + access_cargo = 31 + access_construction = 32 + access_chemistry = 33 + access_cargo_bot = 34 + access_hydroponics = 35 + access_manufacturing = 36 + access_library = 37 + access_lawyer = 38 + access_virology = 39 + access_cmo = 40 + access_qm = 41 + access_court = 42 + access_clown = 43 + access_mime = 44 + +*/ + +//Actual Deployable machinery stuff + +/obj/machinery/deployable + name = "deployable" + desc = "deployable" + icon = 'icons/obj/objects.dmi' + req_access = list(access_security)//I'm changing this until these are properly tested./N + +/obj/machinery/deployable/barrier + name = "deployable barrier" + desc = "A deployable barrier. Swipe your ID card to lock/unlock it." + icon = 'icons/obj/objects.dmi' + anchored = 0.0 + density = 1.0 + icon_state = "barrier0" + var/health = 140.0 + var/maxhealth = 140.0 + var/locked = 0.0 +// req_access = list(access_maint_tunnels) + + machine_flags = EMAGGABLE + +/obj/machinery/deployable/barrier/New() + ..() + + src.icon_state = "barrier[src.locked]" + +/obj/machinery/deployable/barrier/emag(mob/user) + if (src.emagged == 0) + src.emagged = 1 + src.req_access = 0 to_chat(user, "You break the ID authentication lock on the [src].") - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - desc = "A deployable barrier. Swipe your ID card to lock/unlock it. Seems like it's malfunctioning" - return - -/obj/machinery/deployable/barrier/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/card/id/)) - if (src.allowed(user)) - src.locked = !src.locked - src.anchored = !src.anchored - src.icon_state = "barrier[src.locked]" - if (src.locked == 1.0) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + desc = "A deployable barrier. Swipe your ID card to lock/unlock it. Seems like it's malfunctioning" + return + +/obj/machinery/deployable/barrier/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/card/id/)) + if (src.allowed(user)) + src.locked = !src.locked + src.anchored = !src.anchored + src.icon_state = "barrier[src.locked]" + if (src.locked == 1.0) to_chat(user, "Barrier lock toggled on.") - return - else if (src.locked == 0.0) + return + else if (src.locked == 0.0) to_chat(user, "Barrier lock toggled off.") - return - return - else - visible_message("[src] has been hit by [user] with [W]") //I have to put this because atom/proc/attackby is not triggering. No idea why - user.delayNextAttack(10) - switch(W.damtype) - if("fire") - src.health -= W.force * 1 - if("brute") - src.health -= W.force * 0.75 - if (src.health <= 0) - src.explode() - ..() - -/obj/machinery/deployable/barrier/ex_act(severity) - switch(severity) - if(1.0) - src.explode() - return - if(2.0) - src.health -= 25 - if (src.health <= 0) - src.explode() - return - -/obj/machinery/deployable/barrier/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - return - if(prob(50/severity)) - locked = !locked - anchored = !anchored - icon_state = "barrier[src.locked]" - -/obj/machinery/deployable/barrier/blob_act() - src.health -= 25 - if (src.health <= 0) - src.explode() - return - -/obj/machinery/deployable/barrier/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)//So bullets will fly over and stuff. - if(air_group || (height==0)) - return 1 - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else - return 0 - -/obj/machinery/deployable/barrier/proc/explode() - visible_message("[src] blows apart!") - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - explosion(src.loc,-1,-1,0) - if(src) - qdel(src) + return + return + else + visible_message("[src] has been hit by [user] with [W]") //I have to put this because atom/proc/attackby is not triggering. No idea why + user.delayNextAttack(10) + switch(W.damtype) + if("fire") + src.health -= W.force * 1 + if("brute") + src.health -= W.force * 0.75 + if (src.health <= 0) + src.explode() + ..() + +/obj/machinery/deployable/barrier/ex_act(severity) + switch(severity) + if(1.0) + src.explode() + return + if(2.0) + src.health -= 25 + if (src.health <= 0) + src.explode() + return + +/obj/machinery/deployable/barrier/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + return + if(prob(50/severity)) + locked = !locked + anchored = !anchored + icon_state = "barrier[src.locked]" + +/obj/machinery/deployable/barrier/blob_act() + src.health -= 25 + if (src.health <= 0) + src.explode() + return + +/obj/machinery/deployable/barrier/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)//So bullets will fly over and stuff. + if(air_group || (height==0)) + return 1 + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + else + return 0 + +/obj/machinery/deployable/barrier/proc/explode() + visible_message("[src] blows apart!") + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + explosion(src.loc,-1,-1,0) + if(src) + qdel(src) diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index fd2e34e8f3b..a940f9455a6 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -1,208 +1,208 @@ -/obj/machinery/door_control - name = "remote door-control" - desc = "It controls doors, remotely." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "doorctrl0" - desc = "A remote control-switch for a door." - power_channel = ENVIRON - var/id_tag = null - var/range = 10 - var/normaldoorcontrol = 0 - var/specialfunctions = 1 - /* - Bitflag, 1= open - 2= idscan, - 4= bolts - 8= shock - 16= door safties - - */ - - var/exposedwires = 0 - var/wires = 3 - /* - Bitflag, 1=checkID - 2=Network Access - */ - - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - - ghost_read=0 - ghost_write=0 - - machine_flags = EMAGGABLE | MULTITOOL_MENU - -/obj/machinery/door_control/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - if(wires & 2) - return src.attack_hand(user) - else +/obj/machinery/door_control + name = "remote door-control" + desc = "It controls doors, remotely." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "doorctrl0" + desc = "A remote control-switch for a door." + power_channel = ENVIRON + var/id_tag = null + var/range = 10 + var/normaldoorcontrol = 0 + var/specialfunctions = 1 + /* + Bitflag, 1= open + 2= idscan, + 4= bolts + 8= shock + 16= door safties + + */ + + var/exposedwires = 0 + var/wires = 3 + /* + Bitflag, 1=checkID + 2=Network Access + */ + + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + + ghost_read=0 + ghost_write=0 + + machine_flags = EMAGGABLE | MULTITOOL_MENU + +/obj/machinery/door_control/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + if(wires & 2) + return src.attack_hand(user) + else to_chat(user, "Error, no route to host.") - -/obj/machinery/door_control/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/door_control/emag(mob/user) - req_access = list() - req_one_access = list() - playsound(get_turf(src), "sparks", 100, 1) - -/obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user as mob) - ..() - ..() - /* For later implementation - if (istype(W, /obj/item/weapon/screwdriver)) - { - if(wiresexposed) - icon_state = "doorctrl0" - wiresexposed = 0 - - else - icon_state = "doorctrl-open" - wiresexposed = 1 - - return - } - */ - if(istype(W, /obj/item/device/detective_scanner)) - return - return src.attack_hand(user) - -/obj/machinery/door_control/attack_hand(mob/user as mob) - src.add_fingerprint(usr) - if(stat & (NOPOWER|BROKEN)) - return - - if(!allowed(user) && (wires & 1)) + +/obj/machinery/door_control/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/door_control/emag(mob/user) + req_access = list() + req_one_access = list() + playsound(get_turf(src), "sparks", 100, 1) + +/obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user as mob) + ..() + ..() + /* For later implementation + if (istype(W, /obj/item/weapon/screwdriver)) + { + if(wiresexposed) + icon_state = "doorctrl0" + wiresexposed = 0 + + else + icon_state = "doorctrl-open" + wiresexposed = 1 + + return + } + */ + if(istype(W, /obj/item/device/detective_scanner)) + return + return src.attack_hand(user) + +/obj/machinery/door_control/attack_hand(mob/user as mob) + src.add_fingerprint(usr) + if(stat & (NOPOWER|BROKEN)) + return + + if(!allowed(user) && (wires & 1)) to_chat(user, "Access Denied.") - flick("doorctrl-denied",src) - return - - use_power(5) - icon_state = "doorctrl1" - add_fingerprint(user) - - if(normaldoorcontrol) - for(var/obj/machinery/door/airlock/D in range(range)) - if(D.id_tag == src.id_tag) - spawn(0) - if(D) - if(D.density) D.open() - else D.close() - return - if(specialfunctions & IDSCAN) - D.aiDisabledIdScanner = !D.aiDisabledIdScanner - if(specialfunctions & BOLTS) - if(!D.isWireCut(4) && D.arePowerSystemsOn()) - D.locked = !D.locked - D.update_icon() - if(specialfunctions & SHOCK) - D.secondsElectrified = D.secondsElectrified ? 0 : -1 - if(specialfunctions & SAFE) - D.safe = !D.safe - - else - for(var/obj/machinery/door/poddoor/M in poddoors) - if (M.id_tag == src.id_tag) - if (M.density) - spawn( 0 ) - M.open() - return - else - spawn( 0 ) - M.close() - return - spawn(15) - if(!(stat & NOPOWER)) - icon_state = "doorctrl0" - -/obj/machinery/door_control/power_change() - ..() - if(stat & NOPOWER) - icon_state = "doorctrl-p" - else - icon_state = "doorctrl0" - -/obj/machinery/door_control/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) - -/obj/machinery/driver_button/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/driver_button/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/driver_button/attackby(obj/item/weapon/W, mob/user as mob) - . = ..() - if(.) - return . - - if(istype(W, /obj/item/device/detective_scanner)) - return - - if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 30)) + flick("doorctrl-denied",src) + return + + use_power(5) + icon_state = "doorctrl1" + add_fingerprint(user) + + if(normaldoorcontrol) + for(var/obj/machinery/door/airlock/D in range(range)) + if(D.id_tag == src.id_tag) + spawn(0) + if(D) + if(D.density) D.open() + else D.close() + return + if(specialfunctions & IDSCAN) + D.aiDisabledIdScanner = !D.aiDisabledIdScanner + if(specialfunctions & BOLTS) + if(!D.isWireCut(4) && D.arePowerSystemsOn()) + D.locked = !D.locked + D.update_icon() + if(specialfunctions & SHOCK) + D.secondsElectrified = D.secondsElectrified ? 0 : -1 + if(specialfunctions & SAFE) + D.safe = !D.safe + + else + for(var/obj/machinery/door/poddoor/M in poddoors) + if (M.id_tag == src.id_tag) + if (M.density) + spawn( 0 ) + M.open() + return + else + spawn( 0 ) + M.close() + return + spawn(15) + if(!(stat & NOPOWER)) + icon_state = "doorctrl0" + +/obj/machinery/door_control/power_change() + ..() + if(stat & NOPOWER) + icon_state = "doorctrl-p" + else + icon_state = "doorctrl0" + +/obj/machinery/door_control/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) + +/obj/machinery/driver_button/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/driver_button/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/driver_button/attackby(obj/item/weapon/W, mob/user as mob) + . = ..() + if(.) + return . + + if(istype(W, /obj/item/device/detective_scanner)) + return + + if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 30)) to_chat(user, "You detach \the [src] from the wall.") - new/obj/item/mounted/frame/driver_button(get_turf(src)) - qdel(src) - return 1 - - return src.attack_hand(user) - - -/obj/machinery/driver_button/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) - return {" -
        -
      • [format_tag("ID Tag","id_tag")]
      • -
      "} - -/obj/machinery/driver_button/attack_hand(mob/user as mob) - - src.add_fingerprint(usr) - if(stat & (NOPOWER|BROKEN)) - return - if(active) - return - add_fingerprint(user) - - use_power(5) - - launch_sequence() - - return - -/obj/machinery/driver_button/proc/launch_sequence() - active = 1 - icon_state = "launcheract" - - for(var/obj/machinery/door/poddoor/M in poddoors) - if (M.id_tag == src.id_tag) - spawn() - M.open() - - sleep(20) - - for(var/obj/machinery/mass_driver/M in mass_drivers) - if(M.id_tag == src.id_tag) - M.drive() - - sleep(50) - - for(var/obj/machinery/door/poddoor/M in poddoors) - if (M.id_tag == src.id_tag) - spawn() - M.close() - return - - icon_state = "launcherbtt" - active = 0 - -/obj/machinery/driver_button/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) + new/obj/item/mounted/frame/driver_button(get_turf(src)) + qdel(src) + return 1 + + return src.attack_hand(user) + + +/obj/machinery/driver_button/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) + return {" +
        +
      • [format_tag("ID Tag","id_tag")]
      • +
      "} + +/obj/machinery/driver_button/attack_hand(mob/user as mob) + + src.add_fingerprint(usr) + if(stat & (NOPOWER|BROKEN)) + return + if(active) + return + add_fingerprint(user) + + use_power(5) + + launch_sequence() + + return + +/obj/machinery/driver_button/proc/launch_sequence() + active = 1 + icon_state = "launcheract" + + for(var/obj/machinery/door/poddoor/M in poddoors) + if (M.id_tag == src.id_tag) + spawn() + M.open() + + sleep(20) + + for(var/obj/machinery/mass_driver/M in mass_drivers) + if(M.id_tag == src.id_tag) + M.drive() + + sleep(50) + + for(var/obj/machinery/door/poddoor/M in poddoors) + if (M.id_tag == src.id_tag) + spawn() + M.close() + return + + icon_state = "launcherbtt" + active = 0 + +/obj/machinery/driver_button/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 8f168ad51b3..d3fb1c2396a 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1,1261 +1,1261 @@ -/* - New methods: - pulse - sends a pulse into a wire for hacking purposes - cut - cuts a wire and makes any necessary state changes - mend - mends a wire and makes any necessary state changes - canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) - canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. - arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) - requiresIDs - 1 if the airlock is requiring IDs, 0 if not - isAllPowerCut - 1 if the main and backup power both have cut wires. - regainMainPower - handles the effect of main power coming back on. - loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep. - loseBackupPower - handles the effect of backup power going offline. - regainBackupPower - handles the effect of main power coming back on. - shock - has a chance of electrocuting its target. -*/ - -// Wires for the airlock are located in the datum folder, inside the wires datum folder. - - -/obj/machinery/door/airlock - name = "airlock" - icon = 'icons/obj/doors/Doorint.dmi' - icon_state = "door_closed" - power_channel = ENVIRON - - custom_aghost_alerts=1 - - var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in. - var/hackProof = 0 // if 1, this door can't be hacked by the AI - var/secondsMainPowerLost = 0 //The number of seconds until power is restored. - var/secondsBackupPowerLost = 0 //The number of seconds until power is restored. - var/spawnPowerRestoreRunning = 0 - var/welded = null - var/locked = 0 - var/lights = 1 // bolt lights show by default - var/datum/wires/airlock/wires = null - secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. - var/aiDisabledIdScanner = 0 - var/aiHacking = 0 - var/obj/machinery/door/airlock/closeOther = null - var/closeOtherId = null - var/lockdownbyai = 0 - var/assembly_type = /obj/structure/door_assembly - var/mineral = null - var/justzap = 0 - var/safe = 1 - normalspeed = 1 - var/obj/item/weapon/circuitboard/airlock/electronics = null - var/hasShocked = 0 //Prevents multiple shocks from happening - autoclose = 1 - var/busy = 0 - soundeffect = 'sound/machines/airlock.ogg' - var/pitch = 30 - penetration_dampening = 10 - - explosion_block = 1 - - emag_cost = 1 // in MJ - machine_flags = SCREWTOGGLE | WIREJACK - -/obj/machinery/door/airlock/Destroy() - if(wires) - qdel(wires) - wires = null - - ..() - -/obj/machinery/door/airlock/command - name = "Airlock" - icon = 'icons/obj/doors/Doorcom.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_com - -/obj/machinery/door/airlock/security - name = "Airlock" - icon = 'icons/obj/doors/Doorsec.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_sec - -/obj/machinery/door/airlock/engineering - name = "Airlock" - icon = 'icons/obj/doors/Dooreng.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_eng - -/obj/machinery/door/airlock/medical - name = "Airlock" - icon = 'icons/obj/doors/doormed.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_med - -/obj/machinery/door/airlock/maintenance - name = "Maintenance Access" - icon = 'icons/obj/doors/Doormaint.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_mai - -/obj/machinery/door/airlock/external - name = "External Airlock" - icon = 'icons/obj/doors/Doorext.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_ext - normalspeed = 0 //So they close fast, not letting the air to depressurize in a fucking second - -/obj/machinery/door/airlock/external/cultify() - new /obj/machinery/door/mineral/wood(loc) - ..() - -/obj/machinery/door/airlock/glass - name = "Glass Airlock" - icon = 'icons/obj/doors/Doorglass.dmi' - opacity = 0 - glass = 1 - penetration_dampening = 3 - //pitch = 100 - -/obj/machinery/door/airlock/centcom - name = "Airlock" - icon = 'icons/obj/doors/Doorele.dmi' - opacity = 0 - -/obj/machinery/door/airlock/vault - name = "Vault" - icon = 'icons/obj/doors/vault.dmi' - opacity = 1 - emag_cost = 2 // in MJ - assembly_type = /obj/structure/door_assembly/door_assembly_vault - - explosion_block = 3//that's some high quality plasteel door - penetration_dampening = 20 - -/obj/machinery/door/airlock/freezer - name = "Freezer Airlock" - icon = 'icons/obj/doors/Doorfreezer.dmi' - opacity = 1 - assembly_type = /obj/structure/door_assembly/door_assembly_fre - -/obj/machinery/door/airlock/hatch - name = "Airtight Hatch" - icon = 'icons/obj/doors/Doorhatchele.dmi' - opacity = 1 - assembly_type = /obj/structure/door_assembly/door_assembly_hatch - -/obj/machinery/door/airlock/maintenance_hatch - name = "Maintenance Hatch" - icon = 'icons/obj/doors/Doorhatchmaint2.dmi' - opacity = 1 - assembly_type = /obj/structure/door_assembly/door_assembly_mhatch - -/obj/machinery/door/airlock/glass_command - name = "Maintenance Hatch" - icon = 'icons/obj/doors/Doorcomglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_com - glass = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/glass_engineering - name = "Maintenance Hatch" - icon = 'icons/obj/doors/Doorengglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_eng - glass = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/glass_security - name = "Maintenance Hatch" - icon = 'icons/obj/doors/Doorsecglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_sec - glass = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/glass_medical - name = "Maintenance Hatch" - icon = 'icons/obj/doors/doormedglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_med - glass = 1 - -/obj/machinery/door/airlock/mining - name = "Mining Airlock" - icon = 'icons/obj/doors/Doormining.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_min - -/obj/machinery/door/airlock/atmos - name = "Atmospherics Airlock" - icon = 'icons/obj/doors/Dooratmo.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_atmo - -/obj/machinery/door/airlock/research - name = "Airlock" - icon = 'icons/obj/doors/doorresearch.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_research - -/obj/machinery/door/airlock/glass_research - name = "Maintenance Hatch" - icon = 'icons/obj/doors/doorresearchglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_research - glass = 1 - heat_proof = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/glass_mining - name = "Maintenance Hatch" - icon = 'icons/obj/doors/Doorminingglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_min - glass = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/glass_atmos - name = "Maintenance Hatch" - icon = 'icons/obj/doors/Dooratmoglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_atmo - glass = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/gold - name = "Gold Airlock" - icon = 'icons/obj/doors/Doorgold.dmi' - mineral = "gold" - -/obj/machinery/door/airlock/silver - name = "Silver Airlock" - icon = 'icons/obj/doors/Doorsilver.dmi' - mineral = "silver" - -/obj/machinery/door/airlock/diamond - name = "Diamond Airlock" - icon = 'icons/obj/doors/Doordiamond.dmi' - mineral = "diamond" - penetration_dampening = 15 - -/obj/machinery/door/airlock/uranium - name = "Uranium Airlock" - desc = "And they said I was crazy." - icon = 'icons/obj/doors/Dooruranium.dmi' - mineral = "uranium" - var/last_event = 0 - -/obj/machinery/door/airlock/uranium/process() - if(world.time > last_event+20) - if(prob(50)) - radiate() - last_event = world.time - ..() - -/obj/machinery/door/airlock/uranium/proc/radiate() - for(var/mob/living/L in range (3,src)) - L.apply_effect(15,IRRADIATE,0) - return - -/obj/machinery/door/airlock/plasma - name = "Plasma Airlock" - desc = "No way this can end badly." - icon = 'icons/obj/doors/Doorplasma.dmi' - mineral = "plasma" - - autoignition_temperature = 300 - fire_fuel = 10 - -/obj/machinery/door/airlock/plasma/ignite(temperature) - PlasmaBurn(temperature) - -/obj/machinery/door/airlock/plasma/proc/PlasmaBurn(temperature) - for(var/turf/simulated/floor/target_tile in range(2,loc)) -// if(target_tile.parent && target_tile.parent.group_processing) // THESE PROBABLY DO SOMETHING IMPORTANT BUT I DON'T KNOW HOW TO FIX IT - Erthilo -// target_tile.parent.suspend_group_processing() - var/datum/gas_mixture/napalm = new - var/toxinsToDeduce = 35 - napalm.toxins = toxinsToDeduce - napalm.temperature = 400+T0C - target_tile.assume_air(napalm) - spawn (0) - target_tile.hotspot_expose(temperature, 400, surfaces=1) - for(var/obj/structure/falsewall/plasma/F in range(3,src))//Hackish as fuck, but until fire_act works, there is nothing I can do -Sieve - var/turf/T = get_turf(F) - T.ChangeTurf(/turf/simulated/wall/mineral/plasma/) - qdel (F) - F = null - for(var/turf/simulated/wall/mineral/plasma/W in range(3,src)) - W.ignite((temperature/4))//Added so that you can't set off a massive chain reaction with a small flame - for(var/obj/machinery/door/airlock/plasma/D in range(3,src)) - D.ignite(temperature/4) - new/obj/structure/door_assembly( src.loc ) - qdel (src) - -/obj/machinery/door/airlock/clown - name = "Bananium Airlock" - icon = 'icons/obj/doors/Doorbananium.dmi' - mineral = "clown" - soundeffect = 'sound/items/bikehorn.ogg' - -/obj/machinery/door/airlock/sandstone - name = "Sandstone Airlock" - icon = 'icons/obj/doors/Doorsand.dmi' - mineral = "sandstone" - -/obj/machinery/door/airlock/science - name = "Airlock" - icon = 'icons/obj/doors/Doorsci.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_science - -/obj/machinery/door/airlock/glass_science - name = "Glass Airlocks" - icon = 'icons/obj/doors/Doorsciglass.dmi' - opacity = 0 - assembly_type = /obj/structure/door_assembly/door_assembly_science - glass = 1 - penetration_dampening = 3 - -/obj/machinery/door/airlock/highsecurity - name = "High Tech Security Airlock" - icon = 'icons/obj/doors/hightechsecurity.dmi' - assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity - emag_cost = 2 // in MJ - -/* -About the new airlock wires panel: -* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. -* one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though) -* two wires for power. Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter). Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be open, but bolts-raising will not work. Cutting these wires may electrocute the user. -* one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work. -* two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. -* one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. -* one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all. -* one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) -* one wire for controling door safetys. When active, door does not close on someone. When cut, door will ruin someone's shit. When pulsed, door will immedately ruin someone's shit. -* one wire for controlling door speed. When active, dor closes at normal rate. When cut, door does not close manually. When pulsed, door attempts to close every tick. -*/ -// You can find code for the airlock wires in the wire datum folder. - - -/obj/machinery/door/airlock/bump_open(mob/living/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite - if(!istype(user)) return - if(!issilicon(usr)) - if(src.isElectrified()) - if(!src.justzap) - if(src.shock(user, 100)) - src.justzap = 1 - spawn (10) - src.justzap = 0 - return - else /*if(src.justzap)*/ - return - else if(user.hallucination > 50 && prob(10) && src.operating == 0) +/* + New methods: + pulse - sends a pulse into a wire for hacking purposes + cut - cuts a wire and makes any necessary state changes + mend - mends a wire and makes any necessary state changes + canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) + canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. + arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) + requiresIDs - 1 if the airlock is requiring IDs, 0 if not + isAllPowerCut - 1 if the main and backup power both have cut wires. + regainMainPower - handles the effect of main power coming back on. + loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep. + loseBackupPower - handles the effect of backup power going offline. + regainBackupPower - handles the effect of main power coming back on. + shock - has a chance of electrocuting its target. +*/ + +// Wires for the airlock are located in the datum folder, inside the wires datum folder. + + +/obj/machinery/door/airlock + name = "airlock" + icon = 'icons/obj/doors/Doorint.dmi' + icon_state = "door_closed" + power_channel = ENVIRON + + custom_aghost_alerts=1 + + var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in. + var/hackProof = 0 // if 1, this door can't be hacked by the AI + var/secondsMainPowerLost = 0 //The number of seconds until power is restored. + var/secondsBackupPowerLost = 0 //The number of seconds until power is restored. + var/spawnPowerRestoreRunning = 0 + var/welded = null + var/locked = 0 + var/lights = 1 // bolt lights show by default + var/datum/wires/airlock/wires = null + secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. + var/aiDisabledIdScanner = 0 + var/aiHacking = 0 + var/obj/machinery/door/airlock/closeOther = null + var/closeOtherId = null + var/lockdownbyai = 0 + var/assembly_type = /obj/structure/door_assembly + var/mineral = null + var/justzap = 0 + var/safe = 1 + normalspeed = 1 + var/obj/item/weapon/circuitboard/airlock/electronics = null + var/hasShocked = 0 //Prevents multiple shocks from happening + autoclose = 1 + var/busy = 0 + soundeffect = 'sound/machines/airlock.ogg' + var/pitch = 30 + penetration_dampening = 10 + + explosion_block = 1 + + emag_cost = 1 // in MJ + machine_flags = SCREWTOGGLE | WIREJACK + +/obj/machinery/door/airlock/Destroy() + if(wires) + qdel(wires) + wires = null + + ..() + +/obj/machinery/door/airlock/command + name = "Airlock" + icon = 'icons/obj/doors/Doorcom.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_com + +/obj/machinery/door/airlock/security + name = "Airlock" + icon = 'icons/obj/doors/Doorsec.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_sec + +/obj/machinery/door/airlock/engineering + name = "Airlock" + icon = 'icons/obj/doors/Dooreng.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_eng + +/obj/machinery/door/airlock/medical + name = "Airlock" + icon = 'icons/obj/doors/doormed.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_med + +/obj/machinery/door/airlock/maintenance + name = "Maintenance Access" + icon = 'icons/obj/doors/Doormaint.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_mai + +/obj/machinery/door/airlock/external + name = "External Airlock" + icon = 'icons/obj/doors/Doorext.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_ext + normalspeed = 0 //So they close fast, not letting the air to depressurize in a fucking second + +/obj/machinery/door/airlock/external/cultify() + new /obj/machinery/door/mineral/wood(loc) + ..() + +/obj/machinery/door/airlock/glass + name = "Glass Airlock" + icon = 'icons/obj/doors/Doorglass.dmi' + opacity = 0 + glass = 1 + penetration_dampening = 3 + //pitch = 100 + +/obj/machinery/door/airlock/centcom + name = "Airlock" + icon = 'icons/obj/doors/Doorele.dmi' + opacity = 0 + +/obj/machinery/door/airlock/vault + name = "Vault" + icon = 'icons/obj/doors/vault.dmi' + opacity = 1 + emag_cost = 2 // in MJ + assembly_type = /obj/structure/door_assembly/door_assembly_vault + + explosion_block = 3//that's some high quality plasteel door + penetration_dampening = 20 + +/obj/machinery/door/airlock/freezer + name = "Freezer Airlock" + icon = 'icons/obj/doors/Doorfreezer.dmi' + opacity = 1 + assembly_type = /obj/structure/door_assembly/door_assembly_fre + +/obj/machinery/door/airlock/hatch + name = "Airtight Hatch" + icon = 'icons/obj/doors/Doorhatchele.dmi' + opacity = 1 + assembly_type = /obj/structure/door_assembly/door_assembly_hatch + +/obj/machinery/door/airlock/maintenance_hatch + name = "Maintenance Hatch" + icon = 'icons/obj/doors/Doorhatchmaint2.dmi' + opacity = 1 + assembly_type = /obj/structure/door_assembly/door_assembly_mhatch + +/obj/machinery/door/airlock/glass_command + name = "Maintenance Hatch" + icon = 'icons/obj/doors/Doorcomglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_com + glass = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/glass_engineering + name = "Maintenance Hatch" + icon = 'icons/obj/doors/Doorengglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_eng + glass = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/glass_security + name = "Maintenance Hatch" + icon = 'icons/obj/doors/Doorsecglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_sec + glass = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/glass_medical + name = "Maintenance Hatch" + icon = 'icons/obj/doors/doormedglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_med + glass = 1 + +/obj/machinery/door/airlock/mining + name = "Mining Airlock" + icon = 'icons/obj/doors/Doormining.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_min + +/obj/machinery/door/airlock/atmos + name = "Atmospherics Airlock" + icon = 'icons/obj/doors/Dooratmo.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_atmo + +/obj/machinery/door/airlock/research + name = "Airlock" + icon = 'icons/obj/doors/doorresearch.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_research + +/obj/machinery/door/airlock/glass_research + name = "Maintenance Hatch" + icon = 'icons/obj/doors/doorresearchglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_research + glass = 1 + heat_proof = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/glass_mining + name = "Maintenance Hatch" + icon = 'icons/obj/doors/Doorminingglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_min + glass = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/glass_atmos + name = "Maintenance Hatch" + icon = 'icons/obj/doors/Dooratmoglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_atmo + glass = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/gold + name = "Gold Airlock" + icon = 'icons/obj/doors/Doorgold.dmi' + mineral = "gold" + +/obj/machinery/door/airlock/silver + name = "Silver Airlock" + icon = 'icons/obj/doors/Doorsilver.dmi' + mineral = "silver" + +/obj/machinery/door/airlock/diamond + name = "Diamond Airlock" + icon = 'icons/obj/doors/Doordiamond.dmi' + mineral = "diamond" + penetration_dampening = 15 + +/obj/machinery/door/airlock/uranium + name = "Uranium Airlock" + desc = "And they said I was crazy." + icon = 'icons/obj/doors/Dooruranium.dmi' + mineral = "uranium" + var/last_event = 0 + +/obj/machinery/door/airlock/uranium/process() + if(world.time > last_event+20) + if(prob(50)) + radiate() + last_event = world.time + ..() + +/obj/machinery/door/airlock/uranium/proc/radiate() + for(var/mob/living/L in range (3,src)) + L.apply_effect(15,IRRADIATE,0) + return + +/obj/machinery/door/airlock/plasma + name = "Plasma Airlock" + desc = "No way this can end badly." + icon = 'icons/obj/doors/Doorplasma.dmi' + mineral = "plasma" + + autoignition_temperature = 300 + fire_fuel = 10 + +/obj/machinery/door/airlock/plasma/ignite(temperature) + PlasmaBurn(temperature) + +/obj/machinery/door/airlock/plasma/proc/PlasmaBurn(temperature) + for(var/turf/simulated/floor/target_tile in range(2,loc)) +// if(target_tile.parent && target_tile.parent.group_processing) // THESE PROBABLY DO SOMETHING IMPORTANT BUT I DON'T KNOW HOW TO FIX IT - Erthilo +// target_tile.parent.suspend_group_processing() + var/datum/gas_mixture/napalm = new + var/toxinsToDeduce = 35 + napalm.toxins = toxinsToDeduce + napalm.temperature = 400+T0C + target_tile.assume_air(napalm) + spawn (0) + target_tile.hotspot_expose(temperature, 400, surfaces=1) + for(var/obj/structure/falsewall/plasma/F in range(3,src))//Hackish as fuck, but until fire_act works, there is nothing I can do -Sieve + var/turf/T = get_turf(F) + T.ChangeTurf(/turf/simulated/wall/mineral/plasma/) + qdel (F) + F = null + for(var/turf/simulated/wall/mineral/plasma/W in range(3,src)) + W.ignite((temperature/4))//Added so that you can't set off a massive chain reaction with a small flame + for(var/obj/machinery/door/airlock/plasma/D in range(3,src)) + D.ignite(temperature/4) + new/obj/structure/door_assembly( src.loc ) + qdel (src) + +/obj/machinery/door/airlock/clown + name = "Bananium Airlock" + icon = 'icons/obj/doors/Doorbananium.dmi' + mineral = "clown" + soundeffect = 'sound/items/bikehorn.ogg' + +/obj/machinery/door/airlock/sandstone + name = "Sandstone Airlock" + icon = 'icons/obj/doors/Doorsand.dmi' + mineral = "sandstone" + +/obj/machinery/door/airlock/science + name = "Airlock" + icon = 'icons/obj/doors/Doorsci.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_science + +/obj/machinery/door/airlock/glass_science + name = "Glass Airlocks" + icon = 'icons/obj/doors/Doorsciglass.dmi' + opacity = 0 + assembly_type = /obj/structure/door_assembly/door_assembly_science + glass = 1 + penetration_dampening = 3 + +/obj/machinery/door/airlock/highsecurity + name = "High Tech Security Airlock" + icon = 'icons/obj/doors/hightechsecurity.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity + emag_cost = 2 // in MJ + +/* +About the new airlock wires panel: +* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. +* one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though) +* two wires for power. Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter). Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be open, but bolts-raising will not work. Cutting these wires may electrocute the user. +* one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work. +* two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. +* one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. +* one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all. +* one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) +* one wire for controling door safetys. When active, door does not close on someone. When cut, door will ruin someone's shit. When pulsed, door will immedately ruin someone's shit. +* one wire for controlling door speed. When active, dor closes at normal rate. When cut, door does not close manually. When pulsed, door attempts to close every tick. +*/ +// You can find code for the airlock wires in the wire datum folder. + + +/obj/machinery/door/airlock/bump_open(mob/living/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite + if(!istype(user)) return + if(!issilicon(usr)) + if(src.isElectrified()) + if(!src.justzap) + if(src.shock(user, 100)) + src.justzap = 1 + spawn (10) + src.justzap = 0 + return + else /*if(src.justzap)*/ + return + else if(user.hallucination > 50 && prob(10) && src.operating == 0) to_chat(user, "You feel a powerful shock course through your body!") - user.halloss += 10 - user.stunned += 10 - return - ..(user) - -/obj/machinery/door/Bumped(atom/AM) - if (panel_open) - return - - ..(AM) - - return - -/obj/machinery/door/airlock/bump_open(mob/living/simple_animal/user as mob) - ..(user) - -/obj/machinery/door/airlock/proc/isElectrified() - if(src.secondsElectrified != 0) - return 1 - return 0 - -/obj/machinery/door/airlock/proc/isWireCut(var/wireIndex) - // You can find the wires in the datum folder. - if(!wires) - return 1 - return wires.IsIndexCut(wireIndex) - -/obj/machinery/door/airlock/proc/canAIControl() - return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); - -/obj/machinery/door/airlock/proc/canAIHack() - return ((src.aiControlDisabled==1) && (!hackProof) && (!src.isAllPowerCut())); - -/obj/machinery/door/airlock/proc/arePowerSystemsOn() - return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) - -/obj/machinery/door/airlock/requiresID() - return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) - -/obj/machinery/door/airlock/proc/isAllPowerCut() - var/retval=0 - if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - retval=1 - return retval - -/obj/machinery/door/airlock/proc/regainMainPower() - if(src.secondsMainPowerLost > 0) - src.secondsMainPowerLost = 0 - -/obj/machinery/door/airlock/proc/loseMainPower() - if(src.secondsMainPowerLost <= 0) - src.secondsMainPowerLost = 60 - if(src.secondsBackupPowerLost < 10) - src.secondsBackupPowerLost = 10 - if(!src.spawnPowerRestoreRunning) - src.spawnPowerRestoreRunning = 1 - spawn(0) - var/cont = 1 - while (cont) - sleep(10) - cont = 0 - if(src.secondsMainPowerLost>0) - if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.secondsMainPowerLost -= 1 - src.updateDialog() - cont = 1 - - if(src.secondsBackupPowerLost>0) - if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.secondsBackupPowerLost -= 1 - src.updateDialog() - cont = 1 - src.spawnPowerRestoreRunning = 0 - src.updateDialog() - -/obj/machinery/door/airlock/proc/loseBackupPower() - if(src.secondsBackupPowerLost < 60) - src.secondsBackupPowerLost = 60 - -/obj/machinery/door/airlock/proc/regainBackupPower() - if(src.secondsBackupPowerLost > 0) - src.secondsBackupPowerLost = 0 - -// shock user with probability prb (if all connections & power are working) -// returns 1 if shocked, 0 otherwise -// The preceding comment was borrowed from the grille's shock script -/obj/machinery/door/airlock/shock(mob/user, prb) - if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock - return 0 - if(hasShocked) - return 0 //Already shocked someone recently? - if(!prob(prb)) - return 0 //you lucked out, no shock for you - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() //sparks always. - if(electrocute_mob(user, get_area(src), src)) - hasShocked = 1 - spawn(10) - hasShocked = 0 - return 1 - else - return 0 - - -/obj/machinery/door/airlock/update_icon() - overlays = 0 - - if(density) - if(locked && lights) - icon_state = "door_locked" - else - icon_state = "door_closed" - if (panel_open || welded) - var/L[0] - if (panel_open) - L += "panel_open" - - if (welded) - L += "welded" - - overlays = L - L = null - else - icon_state = "door_open" - - return - -/obj/machinery/door/airlock/door_animate(var/animation) - switch(animation) - if("opening") - if(overlays) overlays.len = 0 - if(panel_open) - spawn(2) // The only work around that works. Downside is that the door will be gone for a millisecond. - flick("o_door_opening", src) //can not use flick due to BYOND bug updating overlays right before flicking - else - flick("door_opening", src) - if("closing") - if(overlays) overlays.len = 0 - if(panel_open) - flick("o_door_closing", src) - else - flick("door_closing", src) - if("spark") - flick("door_spark", src) - if("deny") - flick("door_deny", src) - return - -/obj/machinery/door/airlock/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - if(isAI(user)) - if(!src.canAIControl()) - if(src.canAIHack()) - src.hack(user) - return - else + user.halloss += 10 + user.stunned += 10 + return + ..(user) + +/obj/machinery/door/Bumped(atom/AM) + if (panel_open) + return + + ..(AM) + + return + +/obj/machinery/door/airlock/bump_open(mob/living/simple_animal/user as mob) + ..(user) + +/obj/machinery/door/airlock/proc/isElectrified() + if(src.secondsElectrified != 0) + return 1 + return 0 + +/obj/machinery/door/airlock/proc/isWireCut(var/wireIndex) + // You can find the wires in the datum folder. + if(!wires) + return 1 + return wires.IsIndexCut(wireIndex) + +/obj/machinery/door/airlock/proc/canAIControl() + return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); + +/obj/machinery/door/airlock/proc/canAIHack() + return ((src.aiControlDisabled==1) && (!hackProof) && (!src.isAllPowerCut())); + +/obj/machinery/door/airlock/proc/arePowerSystemsOn() + return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) + +/obj/machinery/door/airlock/requiresID() + return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) + +/obj/machinery/door/airlock/proc/isAllPowerCut() + var/retval=0 + if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + retval=1 + return retval + +/obj/machinery/door/airlock/proc/regainMainPower() + if(src.secondsMainPowerLost > 0) + src.secondsMainPowerLost = 0 + +/obj/machinery/door/airlock/proc/loseMainPower() + if(src.secondsMainPowerLost <= 0) + src.secondsMainPowerLost = 60 + if(src.secondsBackupPowerLost < 10) + src.secondsBackupPowerLost = 10 + if(!src.spawnPowerRestoreRunning) + src.spawnPowerRestoreRunning = 1 + spawn(0) + var/cont = 1 + while (cont) + sleep(10) + cont = 0 + if(src.secondsMainPowerLost>0) + if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.secondsMainPowerLost -= 1 + src.updateDialog() + cont = 1 + + if(src.secondsBackupPowerLost>0) + if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.secondsBackupPowerLost -= 1 + src.updateDialog() + cont = 1 + src.spawnPowerRestoreRunning = 0 + src.updateDialog() + +/obj/machinery/door/airlock/proc/loseBackupPower() + if(src.secondsBackupPowerLost < 60) + src.secondsBackupPowerLost = 60 + +/obj/machinery/door/airlock/proc/regainBackupPower() + if(src.secondsBackupPowerLost > 0) + src.secondsBackupPowerLost = 0 + +// shock user with probability prb (if all connections & power are working) +// returns 1 if shocked, 0 otherwise +// The preceding comment was borrowed from the grille's shock script +/obj/machinery/door/airlock/shock(mob/user, prb) + if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock + return 0 + if(hasShocked) + return 0 //Already shocked someone recently? + if(!prob(prb)) + return 0 //you lucked out, no shock for you + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() //sparks always. + if(electrocute_mob(user, get_area(src), src)) + hasShocked = 1 + spawn(10) + hasShocked = 0 + return 1 + else + return 0 + + +/obj/machinery/door/airlock/update_icon() + overlays = 0 + + if(density) + if(locked && lights) + icon_state = "door_locked" + else + icon_state = "door_closed" + if (panel_open || welded) + var/L[0] + if (panel_open) + L += "panel_open" + + if (welded) + L += "welded" + + overlays = L + L = null + else + icon_state = "door_open" + + return + +/obj/machinery/door/airlock/door_animate(var/animation) + switch(animation) + if("opening") + if(overlays) overlays.len = 0 + if(panel_open) + spawn(2) // The only work around that works. Downside is that the door will be gone for a millisecond. + flick("o_door_opening", src) //can not use flick due to BYOND bug updating overlays right before flicking + else + flick("door_opening", src) + if("closing") + if(overlays) overlays.len = 0 + if(panel_open) + flick("o_door_closing", src) + else + flick("door_closing", src) + if("spark") + flick("door_spark", src) + if("deny") + flick("door_deny", src) + return + +/obj/machinery/door/airlock/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + if(isAI(user)) + if(!src.canAIControl()) + if(src.canAIHack()) + src.hack(user) + return + else to_chat(user, "Airlock AI control has been blocked with a firewall. Unable to hack.") - - //separate interface for the AI. - user.set_machine(src) - var/t1 = text("Airlock Control
      \n") - if(src.secondsMainPowerLost > 0) - if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - t1 += text("Main power is offline for [] seconds.
      \n", src.secondsMainPowerLost) - else - t1 += text("Main power is offline indefinitely.
      \n") - else - t1 += text("Main power is online.") - - if(src.secondsBackupPowerLost > 0) - if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - t1 += text("Backup power is offline for [] seconds.
      \n", src.secondsBackupPowerLost) - else - t1 += text("Backup power is offline indefinitely.
      \n") - else if(src.secondsMainPowerLost > 0) - t1 += text("Backup power is online.") - else - t1 += text("Backup power is offline, but will turn on if main power fails.") - t1 += "
      \n" - - if(src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - t1 += text("IdScan wire is cut.
      \n") - else if(src.aiDisabledIdScanner) - t1 += text("IdScan disabled. Enable?
      \n", src) - else - t1 += text("IdScan enabled. Disable?
      \n", src) - - if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) - t1 += text("Main Power Input wire is cut.
      \n") - if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main Power Output wire is cut.
      \n") - if(src.secondsMainPowerLost == 0) - t1 += text("Temporarily disrupt main power?.
      \n", src) - if(src.secondsBackupPowerLost == 0) - t1 += text("Temporarily disrupt backup power?.
      \n", src) - - if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) - t1 += text("Backup Power Input wire is cut.
      \n") - if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup Power Output wire is cut.
      \n") - - if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - t1 += text("Door bolt drop wire is cut.
      \n") - else if(!src.locked) - t1 += text("Door bolts are up. Drop them?
      \n", src) - else - t1 += text("Door bolts are down.") - if(src.arePowerSystemsOn()) - t1 += text(" Raise?
      \n", src) - else - t1 += text(" Cannot raise door bolts due to power failure.
      \n") - - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) - t1 += text("Door bolt lights wire is cut.
      \n") - else if(!src.lights) - t1 += text("Door lights are off. Enable?
      \n", src) - else - t1 += text("Door lights are on. Disable?
      \n", src) - - if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - t1 += text("Electrification wire is cut.
      \n") - if(src.secondsElectrified==-1) - t1 += text("Door is electrified indefinitely. Un-electrify it?
      \n", src) - else if(src.secondsElectrified>0) - t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
      \n", src.secondsElectrified, src) - else - t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
      \n", src, src) - - if(src.isWireCut(AIRLOCK_WIRE_SAFETY)) - t1 += text("Door force sensors not responding.
      \n") - else if(src.safe) - t1 += text("Door safeties operating normally. Override?
      \n",src) - else - t1 += text("Danger. Door safeties disabled. Restore?
      \n",src) - - if(src.isWireCut(AIRLOCK_WIRE_SPEED)) - t1 += text("Door timing circuitry not responding.
      \n") - else if(src.normalspeed) - t1 += text("Door timing circuitry operating normally. Override?
      \n",src) - else - t1 += text("Warning. Door timing circuitry operating abnormally. Restore?
      \n",src) - - if(src.welded) - t1 += text("Door appears to have been welded shut.
      \n") - else if(!src.locked) - if(src.density) - t1 += text("Open door
      \n", src) - else - t1 += text("Close door
      \n", src) - - t1 += text("

      Close

      \n", src) - user << browse(t1, "window=airlock") - onclose(user, "airlock") - -//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door -//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door - - -/obj/machinery/door/airlock/proc/hack(mob/user as mob) - if(src.aiHacking==0) - src.aiHacking=1 - spawn(20) - //TODO: Make this take a minute + + //separate interface for the AI. + user.set_machine(src) + var/t1 = text("Airlock Control
      \n") + if(src.secondsMainPowerLost > 0) + if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + t1 += text("Main power is offline for [] seconds.
      \n", src.secondsMainPowerLost) + else + t1 += text("Main power is offline indefinitely.
      \n") + else + t1 += text("Main power is online.") + + if(src.secondsBackupPowerLost > 0) + if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + t1 += text("Backup power is offline for [] seconds.
      \n", src.secondsBackupPowerLost) + else + t1 += text("Backup power is offline indefinitely.
      \n") + else if(src.secondsMainPowerLost > 0) + t1 += text("Backup power is online.") + else + t1 += text("Backup power is offline, but will turn on if main power fails.") + t1 += "
      \n" + + if(src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + t1 += text("IdScan wire is cut.
      \n") + else if(src.aiDisabledIdScanner) + t1 += text("IdScan disabled. Enable?
      \n", src) + else + t1 += text("IdScan enabled. Disable?
      \n", src) + + if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) + t1 += text("Main Power Input wire is cut.
      \n") + if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + t1 += text("Main Power Output wire is cut.
      \n") + if(src.secondsMainPowerLost == 0) + t1 += text("Temporarily disrupt main power?.
      \n", src) + if(src.secondsBackupPowerLost == 0) + t1 += text("Temporarily disrupt backup power?.
      \n", src) + + if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) + t1 += text("Backup Power Input wire is cut.
      \n") + if(src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + t1 += text("Backup Power Output wire is cut.
      \n") + + if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + t1 += text("Door bolt drop wire is cut.
      \n") + else if(!src.locked) + t1 += text("Door bolts are up. Drop them?
      \n", src) + else + t1 += text("Door bolts are down.") + if(src.arePowerSystemsOn()) + t1 += text(" Raise?
      \n", src) + else + t1 += text(" Cannot raise door bolts due to power failure.
      \n") + + if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) + t1 += text("Door bolt lights wire is cut.
      \n") + else if(!src.lights) + t1 += text("Door lights are off. Enable?
      \n", src) + else + t1 += text("Door lights are on. Disable?
      \n", src) + + if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + t1 += text("Electrification wire is cut.
      \n") + if(src.secondsElectrified==-1) + t1 += text("Door is electrified indefinitely. Un-electrify it?
      \n", src) + else if(src.secondsElectrified>0) + t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
      \n", src.secondsElectrified, src) + else + t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
      \n", src, src) + + if(src.isWireCut(AIRLOCK_WIRE_SAFETY)) + t1 += text("Door force sensors not responding.
      \n") + else if(src.safe) + t1 += text("Door safeties operating normally. Override?
      \n",src) + else + t1 += text("Danger. Door safeties disabled. Restore?
      \n",src) + + if(src.isWireCut(AIRLOCK_WIRE_SPEED)) + t1 += text("Door timing circuitry not responding.
      \n") + else if(src.normalspeed) + t1 += text("Door timing circuitry operating normally. Override?
      \n",src) + else + t1 += text("Warning. Door timing circuitry operating abnormally. Restore?
      \n",src) + + if(src.welded) + t1 += text("Door appears to have been welded shut.
      \n") + else if(!src.locked) + if(src.density) + t1 += text("Open door
      \n", src) + else + t1 += text("Close door
      \n", src) + + t1 += text("

      Close

      \n", src) + user << browse(t1, "window=airlock") + onclose(user, "airlock") + +//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door +//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door + + +/obj/machinery/door/airlock/proc/hack(mob/user as mob) + if(src.aiHacking==0) + src.aiHacking=1 + spawn(20) + //TODO: Make this take a minute to_chat(user, "Airlock AI control has been blocked. Beginning fault-detection.") - sleep(50) - if(src.canAIControl()) + sleep(50) + if(src.canAIControl()) to_chat(user, "Alert cancelled. Airlock control has been restored without our assistance.") - src.aiHacking=0 - return - else if(!src.canAIHack()) + src.aiHacking=0 + return + else if(!src.canAIHack()) to_chat(user, "We've lost our connection! Unable to hack airlock.") - src.aiHacking=0 - return + src.aiHacking=0 + return to_chat(user, "Fault confirmed: airlock control wire disabled or cut.") - sleep(20) + sleep(20) to_chat(user, "Attempting to hack into airlock. This may take some time.") - sleep(200) - if(src.canAIControl()) + sleep(200) + if(src.canAIControl()) to_chat(user, "Alert cancelled. Airlock control has been restored without our assistance.") - src.aiHacking=0 - return - else if(!src.canAIHack()) + src.aiHacking=0 + return + else if(!src.canAIHack()) to_chat(user, "We've lost our connection! Unable to hack airlock.") - src.aiHacking=0 - return + src.aiHacking=0 + return to_chat(user, "Upload access confirmed. Loading control program into airlock software.") - sleep(170) - if(src.canAIControl()) + sleep(170) + if(src.canAIControl()) to_chat(user, "Alert cancelled. Airlock control has been restored without our assistance.") - src.aiHacking=0 - return - else if(!src.canAIHack()) + src.aiHacking=0 + return + else if(!src.canAIHack()) to_chat(user, "We've lost our connection! Unable to hack airlock.") - src.aiHacking=0 - return + src.aiHacking=0 + return to_chat(user, "Transfer complete. Forcing airlock to execute program.") - sleep(50) - //disable blocked control - src.aiControlDisabled = 2 + sleep(50) + //disable blocked control + src.aiControlDisabled = 2 to_chat(user, "Receiving control information from airlock.") - sleep(10) - //bring up airlock dialog - src.aiHacking = 0 - if (user) - src.attack_ai(user) - -/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if (src.isElectrified()) - if (istype(mover, /obj/item)) - var/obj/item/i = mover - if (i.materials && (i.materials.getAmount(MAT_IRON) > 0)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - return ..() - -/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0) - // If you add an if(..()) check you must first remove the var/nowindow parameter. - // Otherwise it will runtime with this kind of error: null.Topic() - var/turf/T = get_turf(usr) - if(!isAI(usr) && T.z != z) return 1 - if(!nowindow) - ..() - if(!isAdminGhost(usr)) - if(usr.stat || usr.restrained() || (usr.size < SIZE_SMALL)) - //testing("Returning: Not adminghost, stat=[usr.stat], restrained=[usr.restrained()], small=[usr.small]") - return - add_fingerprint(usr) - if(href_list["close"]) - usr << browse(null, "window=airlock") - if(usr.machine==src) - usr.unset_machine() - return - - var/am_in_range=in_range(src, usr) - var/turf_ok = istype(src.loc, /turf) - //testing("in range: [am_in_range], turf ok: [turf_ok]") - if(am_in_range && turf_ok) - usr.set_machine(src) - if(!panel_open) - var/obj/item/device/multitool/P = get_multitool(usr) - if(P && istype(P)) - if("set_id" in href_list) - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, id_tag) as null|text),1,MAX_MESSAGE_LEN) - if(newid) - id_tag = newid - initialize() - if("set_freq" in href_list) - var/newfreq=frequency - if(href_list["set_freq"]!="-1") - newfreq=text2num(href_list["set_freq"]) - else - newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num - if(newfreq) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - frequency = newfreq - initialize() - - usr.set_machine(src) - update_multitool_menu(usr) - - - if(isAdminGhost(usr) || (istype(usr, /mob/living/silicon) && src.canAIControl())) - //AI - //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed - //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 door safties, 9 door speed - if(href_list["aiDisable"]) - var/code = text2num(href_list["aiDisable"]) - switch (code) - if(1) - //disable idscan - if(src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + sleep(10) + //bring up airlock dialog + src.aiHacking = 0 + if (user) + src.attack_ai(user) + +/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if (src.isElectrified()) + if (istype(mover, /obj/item)) + var/obj/item/i = mover + if (i.materials && (i.materials.getAmount(MAT_IRON) > 0)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return ..() + +/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0) + // If you add an if(..()) check you must first remove the var/nowindow parameter. + // Otherwise it will runtime with this kind of error: null.Topic() + var/turf/T = get_turf(usr) + if(!isAI(usr) && T.z != z) return 1 + if(!nowindow) + ..() + if(!isAdminGhost(usr)) + if(usr.stat || usr.restrained() || (usr.size < SIZE_SMALL)) + //testing("Returning: Not adminghost, stat=[usr.stat], restrained=[usr.restrained()], small=[usr.small]") + return + add_fingerprint(usr) + if(href_list["close"]) + usr << browse(null, "window=airlock") + if(usr.machine==src) + usr.unset_machine() + return + + var/am_in_range=in_range(src, usr) + var/turf_ok = istype(src.loc, /turf) + //testing("in range: [am_in_range], turf ok: [turf_ok]") + if(am_in_range && turf_ok) + usr.set_machine(src) + if(!panel_open) + var/obj/item/device/multitool/P = get_multitool(usr) + if(P && istype(P)) + if("set_id" in href_list) + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, id_tag) as null|text),1,MAX_MESSAGE_LEN) + if(newid) + id_tag = newid + initialize() + if("set_freq" in href_list) + var/newfreq=frequency + if(href_list["set_freq"]!="-1") + newfreq=text2num(href_list["set_freq"]) + else + newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, frequency) as null|num + if(newfreq) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(newfreq < 10000) + frequency = newfreq + initialize() + + usr.set_machine(src) + update_multitool_menu(usr) + + + if(isAdminGhost(usr) || (istype(usr, /mob/living/silicon) && src.canAIControl())) + //AI + //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed + //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 door safties, 9 door speed + if(href_list["aiDisable"]) + var/code = text2num(href_list["aiDisable"]) + switch (code) + if(1) + //disable idscan + if(src.isWireCut(AIRLOCK_WIRE_IDSCAN)) to_chat(usr, "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways.") - else if(src.aiDisabledIdScanner) + else if(src.aiDisabledIdScanner) to_chat(usr, "You've already disabled the IdScan feature.") - else - if(isobserver(usr) && !canGhostWrite(usr,src,"disabled IDScan on")) + else + if(isobserver(usr) && !canGhostWrite(usr,src,"disabled IDScan on")) to_chat(usr, "Nope.") - return 0 - src.aiDisabledIdScanner = 1 - if(2) - //disrupt main power - if(src.secondsMainPowerLost == 0) - if(isobserver(usr) && !canGhostWrite(usr,src,"disrupted main power on")) + return 0 + src.aiDisabledIdScanner = 1 + if(2) + //disrupt main power + if(src.secondsMainPowerLost == 0) + if(isobserver(usr) && !canGhostWrite(usr,src,"disrupted main power on")) to_chat(usr, "Nope.") - return 0 - src.loseMainPower() - else + return 0 + src.loseMainPower() + else to_chat(usr, "Main power is already offline.") - if(3) - //disrupt backup power - if(src.secondsBackupPowerLost == 0) - if(isobserver(usr) && !canGhostWrite(usr,src,"disrupted backup power on")) + if(3) + //disrupt backup power + if(src.secondsBackupPowerLost == 0) + if(isobserver(usr) && !canGhostWrite(usr,src,"disrupted backup power on")) to_chat(usr, "Nope.") - return 0 - src.loseBackupPower() - else + return 0 + src.loseBackupPower() + else to_chat(usr, "Backup power is already offline.") - if(4) - //drop door bolts - if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + if(4) + //drop door bolts + if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) to_chat(usr, "You can't drop the door bolts - The door bolt dropping wire has been cut.") - else if(src.locked!=1) - if(isobserver(usr) && !canGhostWrite(usr,src,"dropped bolts on")) + else if(src.locked!=1) + if(isobserver(usr) && !canGhostWrite(usr,src,"dropped bolts on")) to_chat(usr, "Nope.") - return 0 - src.locked = 1 - log_attack("[usr] ([usr.ckey]) bolted the [name] at [x] [y] [z]") - update_icon() - if(5) - //un-electrify door - if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + return 0 + src.locked = 1 + log_attack("[usr] ([usr.ckey]) bolted the [name] at [x] [y] [z]") + update_icon() + if(5) + //un-electrify door + if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) to_chat(usr, text("Can't un-electrify the airlock - The electrification wire is cut.")) - else if(src.secondsElectrified==-1) - if(isobserver(usr) && !canGhostWrite(usr,src,"electrified")) + else if(src.secondsElectrified==-1) + if(isobserver(usr) && !canGhostWrite(usr,src,"electrified")) to_chat(usr, "Nope.") - return 0 - src.secondsElectrified = 0 - log_attack("[usr] ([usr.ckey]) un-electrified the [name] at [x] [y] [z]") - else if(src.secondsElectrified>0) - if(isobserver(usr) && !canGhostWrite(usr,src,"electrified")) + return 0 + src.secondsElectrified = 0 + log_attack("[usr] ([usr.ckey]) un-electrified the [name] at [x] [y] [z]") + else if(src.secondsElectrified>0) + if(isobserver(usr) && !canGhostWrite(usr,src,"electrified")) to_chat(usr, "Nope.") - return 0 - src.secondsElectrified = 0 - log_attack("[usr] ([usr.ckey]) un-electrified the [name] at [x] [y] [z]") - - if(8) - // Safeties! We don't need no stinking safeties! - if (src.isWireCut(AIRLOCK_WIRE_SAFETY)) + return 0 + src.secondsElectrified = 0 + log_attack("[usr] ([usr.ckey]) un-electrified the [name] at [x] [y] [z]") + + if(8) + // Safeties! We don't need no stinking safeties! + if (src.isWireCut(AIRLOCK_WIRE_SAFETY)) to_chat(usr, text("Control to door sensors is disabled.")) - else if (src.safe) - if(isobserver(usr) && !canGhostWrite(usr,src,"disabled safeties on")) + else if (src.safe) + if(isobserver(usr) && !canGhostWrite(usr,src,"disabled safeties on")) to_chat(usr, "Nope.") - return 0 - safe = 0 - log_attack("[usr] ([usr.ckey]) removed the safeties on the [name] at [x] [y] [z]") - else + return 0 + safe = 0 + log_attack("[usr] ([usr.ckey]) removed the safeties on the [name] at [x] [y] [z]") + else to_chat(usr, text("Firmware reports safeties already overriden.")) - - - - if(9) - // Door speed control - if(src.isWireCut(AIRLOCK_WIRE_SPEED)) + + + + if(9) + // Door speed control + if(src.isWireCut(AIRLOCK_WIRE_SPEED)) to_chat(usr, text("Control to door timing circuitry has been severed.")) - else if (src.normalspeed) - if(isobserver(usr) && !canGhostWrite(usr,src,"disrupted timing on")) + else if (src.normalspeed) + if(isobserver(usr) && !canGhostWrite(usr,src,"disrupted timing on")) to_chat(usr, "Nope.") - return 0 - normalspeed = 0 - log_attack("[usr] ([usr.ckey]) disrupted door timing on the [name] at [x] [y] [z]") - else + return 0 + normalspeed = 0 + log_attack("[usr] ([usr.ckey]) disrupted door timing on the [name] at [x] [y] [z]") + else to_chat(usr, text("Door timing circurity already accellerated.")) - - if(7) - //close door - if(src.welded) + + if(7) + //close door + if(src.welded) to_chat(usr, text("The airlock has been welded shut!")) - else if(src.locked) + else if(src.locked) to_chat(usr, text("The door bolts are down!")) - else if(!src.density) - if(isobserver(usr) && !canGhostWrite(usr,src,"closed")) + else if(!src.density) + if(isobserver(usr) && !canGhostWrite(usr,src,"closed")) to_chat(usr, "Nope.") - return 0 - close() - log_attack("[usr] ([usr.ckey]) closed the [name] at [x] [y] [z]") - else - if(isobserver(usr) && !canGhostWrite(usr,src,"opened")) + return 0 + close() + log_attack("[usr] ([usr.ckey]) closed the [name] at [x] [y] [z]") + else + if(isobserver(usr) && !canGhostWrite(usr,src,"opened")) to_chat(usr, "Nope.") - return 0 - open() - log_attack("[usr] ([usr.ckey]) opened the [name] at [x] [y] [z]") - - if(10) - // Bolt lights - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) + return 0 + open() + log_attack("[usr] ([usr.ckey]) opened the [name] at [x] [y] [z]") + + if(10) + // Bolt lights + if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) to_chat(usr, text("Control to door bolt lights has been severed.")) - else if (src.lights) - if(isobserver(usr) && !canGhostWrite(usr,src,"disabled door bolt lights on")) + else if (src.lights) + if(isobserver(usr) && !canGhostWrite(usr,src,"disabled door bolt lights on")) to_chat(usr, "Nope.") - return 0 - lights = 0 - else + return 0 + lights = 0 + else to_chat(usr, text("Door bolt lights are already disabled!")) - - - - else if(href_list["aiEnable"]) - var/code = text2num(href_list["aiEnable"]) - switch (code) - if(1) - //enable idscan - if(src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + + + + else if(href_list["aiEnable"]) + var/code = text2num(href_list["aiEnable"]) + switch (code) + if(1) + //enable idscan + if(src.isWireCut(AIRLOCK_WIRE_IDSCAN)) to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.") - else if(src.aiDisabledIdScanner) - if(isobserver(usr) && !canGhostWrite(usr,src,"enabled ID Scan on")) + else if(src.aiDisabledIdScanner) + if(isobserver(usr) && !canGhostWrite(usr,src,"enabled ID Scan on")) to_chat(usr, "Nope.") - return 0 - src.aiDisabledIdScanner = 0 - else + return 0 + src.aiDisabledIdScanner = 0 + else to_chat(usr, "The IdScan feature is not disabled.") - if(4) - //raise door bolts - if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + if(4) + //raise door bolts + if(src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) to_chat(usr, text("The door bolt drop wire is cut - you can't raise the door bolts.
      \n")) - else if(!src.locked) + else if(!src.locked) to_chat(usr, text("The door bolts are already up.
      \n")) - else - if(src.arePowerSystemsOn()) - if(isobserver(usr) && !canGhostWrite(usr,src,"raised bolts on")) + else + if(src.arePowerSystemsOn()) + if(isobserver(usr) && !canGhostWrite(usr,src,"raised bolts on")) to_chat(usr, "Nope.") - return 0 - src.locked = 0 - update_icon() - else + return 0 + src.locked = 0 + update_icon() + else to_chat(usr, text("Cannot raise door bolts due to power failure.
      \n")) - - if(5) - //electrify door for 30 seconds - if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + + if(5) + //electrify door for 30 seconds + if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) to_chat(usr, text("The electrification wire has been cut.
      \n")) - else if(src.secondsElectrified==-1) + else if(src.secondsElectrified==-1) to_chat(usr, text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.
      \n")) - else if(src.secondsElectrified!=0) + else if(src.secondsElectrified!=0) to_chat(usr, text("The door is already electrified. You can't re-electrify it while it's already electrified.
      \n")) - else - shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") - log_attack("[usr] ([usr.ckey]) Temporarily electrified the [name] at [x] [y] [z]") - if(isobserver(usr) && !canGhostWrite(usr,src,"electrified (30sec)")) + else + shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") + usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") + log_attack("[usr] ([usr.ckey]) Temporarily electrified the [name] at [x] [y] [z]") + if(isobserver(usr) && !canGhostWrite(usr,src,"electrified (30sec)")) to_chat(usr, "Nope.") - return 0 - src.secondsElectrified = 30 - spawn(10) - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if(src.secondsElectrified<0) - src.secondsElectrified = 0 - src.updateUsrDialog() - sleep(10) - if(6) - //electrify door indefinitely - if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + return 0 + src.secondsElectrified = 30 + spawn(10) + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if(src.secondsElectrified<0) + src.secondsElectrified = 0 + src.updateUsrDialog() + sleep(10) + if(6) + //electrify door indefinitely + if(src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) to_chat(usr, text("The electrification wire has been cut.
      \n")) - else if(src.secondsElectrified==-1) + else if(src.secondsElectrified==-1) to_chat(usr, text("The door is already indefinitely electrified.
      \n")) - else if(src.secondsElectrified!=0) + else if(src.secondsElectrified!=0) to_chat(usr, text("The door is already electrified. You can't re-electrify it while it's already electrified.
      \n")) - else - shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") - log_attack("[usr] ([usr.ckey]) Electrified the [name] at [x] [y] [z]") - if(isobserver(usr) && !canGhostWrite(usr,src,"electrified (permanent)")) + else + shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") + usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") + log_attack("[usr] ([usr.ckey]) Electrified the [name] at [x] [y] [z]") + if(isobserver(usr) && !canGhostWrite(usr,src,"electrified (permanent)")) to_chat(usr, "Nope.") - return 0 - src.secondsElectrified = -1 - - if (8) // Not in order >.> - // Safeties! Maybe we do need some stinking safeties! - if (src.isWireCut(AIRLOCK_WIRE_SAFETY)) + return 0 + src.secondsElectrified = -1 + + if (8) // Not in order >.> + // Safeties! Maybe we do need some stinking safeties! + if (src.isWireCut(AIRLOCK_WIRE_SAFETY)) to_chat(usr, text("Control to door sensors is disabled.")) - else if (!src.safe) - if(isobserver(usr) && !canGhostWrite(usr,src,"enabled safeties on")) + else if (!src.safe) + if(isobserver(usr) && !canGhostWrite(usr,src,"enabled safeties on")) to_chat(usr, "Nope.") - return 0 - safe = 1 - src.updateUsrDialog() - else + return 0 + safe = 1 + src.updateUsrDialog() + else to_chat(usr, text("Firmware reports safeties already in place.")) - - if(9) - // Door speed control - if(src.isWireCut(AIRLOCK_WIRE_SPEED)) + + if(9) + // Door speed control + if(src.isWireCut(AIRLOCK_WIRE_SPEED)) to_chat(usr, text("Control to door timing circuitry has been severed.")) - else if (!src.normalspeed) - if(isobserver(usr) && !canGhostWrite(usr,src,"set speed to normal on")) + else if (!src.normalspeed) + if(isobserver(usr) && !canGhostWrite(usr,src,"set speed to normal on")) to_chat(usr, "Nope.") - return 0 - normalspeed = 1 - src.updateUsrDialog() - else + return 0 + normalspeed = 1 + src.updateUsrDialog() + else to_chat(usr, text("Door timing circurity currently operating normally.")) - - if(7) - //open door - if(src.welded) + + if(7) + //open door + if(src.welded) to_chat(usr, text("The airlock has been welded shut!")) - else if(src.locked) + else if(src.locked) to_chat(usr, text("The door bolts are down!")) - else if(src.density) - if(isobserver(usr) && !canGhostWrite(usr,src,"opened")) + else if(src.density) + if(isobserver(usr) && !canGhostWrite(usr,src,"opened")) to_chat(usr, "Nope.") - return 0 - open() - log_attack("[usr] ([usr.ckey]) opened the [name] at [x] [y] [z]") - else - if(isobserver(usr) && !canGhostWrite(usr,src,"closed")) + return 0 + open() + log_attack("[usr] ([usr.ckey]) opened the [name] at [x] [y] [z]") + else + if(isobserver(usr) && !canGhostWrite(usr,src,"closed")) to_chat(usr, "Nope.") - return 0 - close() - log_attack("[usr] ([usr.ckey]) closed the [name] at [x] [y] [z]") - - if(10) - // Bolt lights - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) + return 0 + close() + log_attack("[usr] ([usr.ckey]) closed the [name] at [x] [y] [z]") + + if(10) + // Bolt lights + if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) to_chat(usr, text("Control to door bolt lights has been severed.")) - else if (!src.lights) - if(isobserver(usr) && !canGhostWrite(usr,src,"enabled bolt lights on")) + else if (!src.lights) + if(isobserver(usr) && !canGhostWrite(usr,src,"enabled bolt lights on")) to_chat(usr, "Nope.") - return 0 - lights = 1 - src.updateUsrDialog() - else + return 0 + lights = 1 + src.updateUsrDialog() + else to_chat(usr, text("Door bolt lights are already enabled!")) - - add_fingerprint(usr) - update_icon() - if(!nowindow) - updateUsrDialog() - return - -/obj/machinery/door/airlock/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - var/dat="" - if(src.requiresID() && !allowed(user)) - return {"Access Denied."} - else - var/dis_id_tag="-----" - if(id_tag!=null && id_tag!="") - dis_id_tag=id_tag - dat += {" - "} - - return dat - -/obj/machinery/door/airlock/attack_hand(mob/user as mob) - if (!istype(user, /mob/living/silicon) && !isobserver(user)) - if (isElectrified()) - // TODO: analyze the called proc - if (shock(user, 100)) - return - if (!panel_open) - ..(user) - //else - // // TODO: logic for adding fingerprints when interacting with wires - // wires.Interact(user) - - return - -//You can ALWAYS screwdriver a door. Period. Well, at least you can even if it's open -/obj/machinery/door/airlock/togglePanelOpen(var/obj/toggleitem, mob/user) - if(!operating) - panel_open = !panel_open - update_icon() - return 1 - return - -/obj/machinery/door/airlock/attackby(obj/item/I as obj, mob/user as mob) - if(isAI(user) || isobserver(user)) - return attack_ai(user) - - if (!istype(user, /mob/living/silicon)) - if (isElectrified()) - // TODO: analyze the called proc - if (shock(user, 75)) - return - - if(istype(I, /obj/item/weapon/batteringram)) - user.delayNextAttack(30) - var/breaktime = 60 //Same amount of time as drilling a wall, then a girder - if(welded) - breaktime += 30 //Welding buys you a little time - src.visible_message("[user] is battering down [src]!", "You begin to batter [src].") - playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1) - if(do_after(user,src, breaktime)) - //Calculate bolts separtely, in case they dropped in the last 6-9 seconds. - if(src.locked == 1) - playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1) - src.visible_message("[user] is battering the bolts!", "You begin to smash the bolts...") - if(!do_after(user, src,190)) //Same amount as drilling an R-wall, longer if it was welded - return //If they moved, cancel us out - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - src.visible_message("[user] broke down the door!", "You broke the door!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - operating = -1 - var/obj/structure/door_assembly/DA = revert(user,user.dir) - DA.anchored = 0 - DA.state = 0 //Completely smash the door here; reduce it to its lowest state, eject electronics smoked - DA.update_state() - qdel(src) - return - - if (istype(I, /obj/item/weapon/weldingtool)) - if (density && !operating) - var/obj/item/weapon/weldingtool/WT = I - - // TODO: analyze the called proc - if (WT.remove_fuel(0, user)) - if (!welded) - welded = 1 - else - welded = null - - update_icon() - else if (istype(I, /obj/item/weapon/wirecutters)) - if (!operating && panel_open) - wires.Interact(user) - else if (istype(I, /obj/item/device/multitool)) - if (!operating) - if(panel_open) wires.Interact(user) - else update_multitool_menu(user) - attack_hand(user) - else if(istype(I, /obj/item/weapon/crowbar) || istype(I, /obj/item/weapon/fireaxe) ) - if(src.busy) return - src.busy = 1 - var/beingcrowbarred = null - if(istype(I, /obj/item/weapon/crowbar) ) - beingcrowbarred = 1 //derp, Agouri - else - beingcrowbarred = 0 - if( beingcrowbarred && (operating == -1 || density && welded && !operating && src.panel_open && (!src.arePowerSystemsOn() || stat & NOPOWER) && !src.locked) ) - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.") - // TODO: refactor the called proc - if (do_after(user, src, 40)) + + add_fingerprint(usr) + update_icon() + if(!nowindow) + updateUsrDialog() + return + +/obj/machinery/door/airlock/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + var/dat="" + if(src.requiresID() && !allowed(user)) + return {"Access Denied."} + else + var/dis_id_tag="-----" + if(id_tag!=null && id_tag!="") + dis_id_tag=id_tag + dat += {" + "} + + return dat + +/obj/machinery/door/airlock/attack_hand(mob/user as mob) + if (!istype(user, /mob/living/silicon) && !isobserver(user)) + if (isElectrified()) + // TODO: analyze the called proc + if (shock(user, 100)) + return + if (!panel_open) + ..(user) + //else + // // TODO: logic for adding fingerprints when interacting with wires + // wires.Interact(user) + + return + +//You can ALWAYS screwdriver a door. Period. Well, at least you can even if it's open +/obj/machinery/door/airlock/togglePanelOpen(var/obj/toggleitem, mob/user) + if(!operating) + panel_open = !panel_open + update_icon() + return 1 + return + +/obj/machinery/door/airlock/attackby(obj/item/I as obj, mob/user as mob) + if(isAI(user) || isobserver(user)) + return attack_ai(user) + + if (!istype(user, /mob/living/silicon)) + if (isElectrified()) + // TODO: analyze the called proc + if (shock(user, 75)) + return + + if(istype(I, /obj/item/weapon/batteringram)) + user.delayNextAttack(30) + var/breaktime = 60 //Same amount of time as drilling a wall, then a girder + if(welded) + breaktime += 30 //Welding buys you a little time + src.visible_message("[user] is battering down [src]!", "You begin to batter [src].") + playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1) + if(do_after(user,src, breaktime)) + //Calculate bolts separtely, in case they dropped in the last 6-9 seconds. + if(src.locked == 1) + playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1) + src.visible_message("[user] is battering the bolts!", "You begin to smash the bolts...") + if(!do_after(user, src,190)) //Same amount as drilling an R-wall, longer if it was welded + return //If they moved, cancel us out + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + src.visible_message("[user] broke down the door!", "You broke the door!") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + operating = -1 + var/obj/structure/door_assembly/DA = revert(user,user.dir) + DA.anchored = 0 + DA.state = 0 //Completely smash the door here; reduce it to its lowest state, eject electronics smoked + DA.update_state() + qdel(src) + return + + if (istype(I, /obj/item/weapon/weldingtool)) + if (density && !operating) + var/obj/item/weapon/weldingtool/WT = I + + // TODO: analyze the called proc + if (WT.remove_fuel(0, user)) + if (!welded) + welded = 1 + else + welded = null + + update_icon() + else if (istype(I, /obj/item/weapon/wirecutters)) + if (!operating && panel_open) + wires.Interact(user) + else if (istype(I, /obj/item/device/multitool)) + if (!operating) + if(panel_open) wires.Interact(user) + else update_multitool_menu(user) + attack_hand(user) + else if(istype(I, /obj/item/weapon/crowbar) || istype(I, /obj/item/weapon/fireaxe) ) + if(src.busy) return + src.busy = 1 + var/beingcrowbarred = null + if(istype(I, /obj/item/weapon/crowbar) ) + beingcrowbarred = 1 //derp, Agouri + else + beingcrowbarred = 0 + if( beingcrowbarred && (operating == -1 || density && welded && !operating && src.panel_open && (!src.arePowerSystemsOn() || stat & NOPOWER) && !src.locked) ) + playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.") + // TODO: refactor the called proc + if (do_after(user, src, 40)) to_chat(user, "You removed the airlock electronics!") - revert(user,null) - qdel(src) - return - else if(arePowerSystemsOn() && !(stat & NOPOWER)) + revert(user,null) + qdel(src) + return + else if(arePowerSystemsOn() && !(stat & NOPOWER)) to_chat(user, "The airlock's motors resist your efforts to force it.") - else if(locked) + else if(locked) to_chat(user, "The airlock's bolts prevent it from being forced.") - else if( !welded && !operating ) - if(density) - if(beingcrowbarred == 0) //being fireaxe'd - var/obj/item/weapon/fireaxe/F = I - if(F.wielded) - spawn(0) open(1) - else + else if( !welded && !operating ) + if(density) + if(beingcrowbarred == 0) //being fireaxe'd + var/obj/item/weapon/fireaxe/F = I + if(F.wielded) + spawn(0) open(1) + else to_chat(user, "You need to be wielding the Fire axe to do that.") - else - spawn(0) open(1) - else - if(beingcrowbarred == 0) - var/obj/item/weapon/fireaxe/F = I - if(F.wielded) - spawn(0) close(1) - else + else + spawn(0) open(1) + else + if(beingcrowbarred == 0) + var/obj/item/weapon/fireaxe/F = I + if(F.wielded) + spawn(0) close(1) + else to_chat(user, "You need to be wielding the Fire axe to do that.") - else - spawn(0) close(1) - src.busy = 0 - else if (istype(I, /obj/item/weapon/card/emag)) - if (!operating) - operating = -1 - if(density) - door_animate("spark") - sleep(6) - open(1) - operating = -1 - else - ..(I, user) - - return - -/obj/machinery/door/airlock/proc/revert(mob/user as mob, var/direction) - var/obj/structure/door_assembly/DA = new assembly_type(loc) - DA.anchored = 1 - DA.fingerprints += src.fingerprints - DA.fingerprintshidden += src.fingerprintshidden - DA.fingerprintslast = user.ckey - if (mineral) - DA.glass = mineral - else if (glass && !DA.glass) - DA.glass = 1 - - DA.state = 1 - DA.created_name = name - DA.update_state() - - var/obj/item/weapon/circuitboard/airlock/A - - if (!electronics) - A = new/obj/item/weapon/circuitboard/airlock(loc) - - if(req_access && req_access.len) - A.conf_access = req_access - else if(req_one_access && req_one_access.len) - A.conf_access = req_one_access - A.one_access = 1 - else - A = electronics - electronics = null - A.loc = loc - - if (operating == -1) - A.icon_state = "door_electronics_smoked" - operating = 0 - if(direction) - A.throw_at(get_edge_target_turf(src, direction),10,4) - return DA //Returns the new assembly - -/obj/machinery/door/airlock/plasma/attackby(obj/C, mob/user) - var/heat = C.is_hot() - if(heat > 300) - ignite(heat) - ..() - -/obj/machinery/door/airlock/open(var/forced=0) - if((operating && !forced) || locked || welded) - return 0 - if(!forced) - if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) ) - return 0 - use_power(50) - playsound(get_turf(src), soundeffect, pitch, 1) - if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) - src.closeOther.close() - // This worries me - N3X - if(!forced) - if(autoclose && normalspeed) - spawn(150) - autoclose() - else if(autoclose && !normalspeed) - spawn(20) - autoclose() - // - return ..() - -/obj/machinery/door/airlock/close(var/forced = 0 as num) - if (operating || locked || welded) - return - if(!forced) - if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) ) - return - - use_power(50) - - if (safe) - for (var/turf/T in locs) - // sticky web has jammed door open - if (locate(/obj/effect/spider/stickyweb) in T) - return - - if (locate(/mob/living) in T) - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) - if(autoclose && normalspeed) - spawn(150) - autoclose() - else if(autoclose && !normalspeed) - spawn(20) - autoclose() - return - - else - for (var/turf/T in locs) - for(var/mob/living/L in T) - L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - - if (isrobot(L)) - continue - - L.SetStunned(5) - L.SetWeakened(5) - var/obj/effect/stop/S = new() - S.loc = loc - S.victim = L - - spawn (20) - qdel(S) - S = null - - L.emote("scream",,, 1) - - if (istype(loc, /turf/simulated)) - T.add_blood(L) - - playsound(get_turf(src),soundeffect, 30, 1) - - for(var/turf/T in loc) - var/obj/structure/window/W = locate(/obj/structure/window) in T - if (W) - W.Destroy(brokenup = 1) - - ..() - return - -/obj/machinery/door/airlock/New() - . = ..() - wires = new(src) - if(src.closeOtherId != null) - spawn (5) - for (var/obj/machinery/door/airlock/A in all_doors) - if(A.closeOtherId == src.closeOtherId && A != src) - src.closeOther = A - break - -/obj/machinery/door/airlock/proc/prison_open() - locked = 0 - open() - locked = 1 - return - -/obj/machinery/door/airlock/wirejack(var/mob/living/silicon/pai/P) - if(..()) - //attack_ai(P) - open(1) - return 1 - return 0 + else + spawn(0) close(1) + src.busy = 0 + else if (istype(I, /obj/item/weapon/card/emag)) + if (!operating) + operating = -1 + if(density) + door_animate("spark") + sleep(6) + open(1) + operating = -1 + else + ..(I, user) + + return + +/obj/machinery/door/airlock/proc/revert(mob/user as mob, var/direction) + var/obj/structure/door_assembly/DA = new assembly_type(loc) + DA.anchored = 1 + DA.fingerprints += src.fingerprints + DA.fingerprintshidden += src.fingerprintshidden + DA.fingerprintslast = user.ckey + if (mineral) + DA.glass = mineral + else if (glass && !DA.glass) + DA.glass = 1 + + DA.state = 1 + DA.created_name = name + DA.update_state() + + var/obj/item/weapon/circuitboard/airlock/A + + if (!electronics) + A = new/obj/item/weapon/circuitboard/airlock(loc) + + if(req_access && req_access.len) + A.conf_access = req_access + else if(req_one_access && req_one_access.len) + A.conf_access = req_one_access + A.one_access = 1 + else + A = electronics + electronics = null + A.loc = loc + + if (operating == -1) + A.icon_state = "door_electronics_smoked" + operating = 0 + if(direction) + A.throw_at(get_edge_target_turf(src, direction),10,4) + return DA //Returns the new assembly + +/obj/machinery/door/airlock/plasma/attackby(obj/C, mob/user) + var/heat = C.is_hot() + if(heat > 300) + ignite(heat) + ..() + +/obj/machinery/door/airlock/open(var/forced=0) + if((operating && !forced) || locked || welded) + return 0 + if(!forced) + if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) ) + return 0 + use_power(50) + playsound(get_turf(src), soundeffect, pitch, 1) + if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) + src.closeOther.close() + // This worries me - N3X + if(!forced) + if(autoclose && normalspeed) + spawn(150) + autoclose() + else if(autoclose && !normalspeed) + spawn(20) + autoclose() + // + return ..() + +/obj/machinery/door/airlock/close(var/forced = 0 as num) + if (operating || locked || welded) + return + if(!forced) + if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) ) + return + + use_power(50) + + if (safe) + for (var/turf/T in locs) + // sticky web has jammed door open + if (locate(/obj/effect/spider/stickyweb) in T) + return + + if (locate(/mob/living) in T) + playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + if(autoclose && normalspeed) + spawn(150) + autoclose() + else if(autoclose && !normalspeed) + spawn(20) + autoclose() + return + + else + for (var/turf/T in locs) + for(var/mob/living/L in T) + L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) + + if (isrobot(L)) + continue + + L.SetStunned(5) + L.SetWeakened(5) + var/obj/effect/stop/S = new() + S.loc = loc + S.victim = L + + spawn (20) + qdel(S) + S = null + + L.emote("scream",,, 1) + + if (istype(loc, /turf/simulated)) + T.add_blood(L) + + playsound(get_turf(src),soundeffect, 30, 1) + + for(var/turf/T in loc) + var/obj/structure/window/W = locate(/obj/structure/window) in T + if (W) + W.Destroy(brokenup = 1) + + ..() + return + +/obj/machinery/door/airlock/New() + . = ..() + wires = new(src) + if(src.closeOtherId != null) + spawn (5) + for (var/obj/machinery/door/airlock/A in all_doors) + if(A.closeOtherId == src.closeOtherId && A != src) + src.closeOther = A + break + +/obj/machinery/door/airlock/proc/prison_open() + locked = 0 + open() + locked = 1 + return + +/obj/machinery/door/airlock/wirejack(var/mob/living/silicon/pai/P) + if(..()) + //attack_ai(P) + open(1) + return 1 + return 0 diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 5274b77aace..72dabd31471 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -1,141 +1,141 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/item/weapon/circuitboard/airlock - name = "airlock electronics" - icon = 'icons/obj/doors/door_assembly.dmi' - icon_state = "door_electronics" - w_class = 2.0 //It should be tiny! -Agouri - starting_materials = list(MAT_IRON = 50, MAT_GLASS = 50) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_SILICON - - req_access = list(access_engine_equip) - - var/list/conf_access = null - var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access - var/last_configurator = null - var/locked = 1 - - // Allow dicking with it while it's on the floor. - attack_robot(mob/user as mob) - if(isMoMMI(user)) - return ..() - attack_self(user) - return 1 - -/obj/item/weapon/circuitboard/airlock/attackby(obj/item/W as obj, mob/user as mob) - if(issolder(W)) - var/obj/item/weapon/solder/S = W - if(icon_state == "door_electronics_smoked") - if(!S.remove_fuel(4,user)) - return - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - if(do_after(user, src,40)) - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - icon_state = "door_electronics" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/item/weapon/circuitboard/airlock + name = "airlock electronics" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + w_class = 2.0 //It should be tiny! -Agouri + starting_materials = list(MAT_IRON = 50, MAT_GLASS = 50) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_SILICON + + req_access = list(access_engine_equip) + + var/list/conf_access = null + var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access + var/last_configurator = null + var/locked = 1 + + // Allow dicking with it while it's on the floor. + attack_robot(mob/user as mob) + if(isMoMMI(user)) + return ..() + attack_self(user) + return 1 + +/obj/item/weapon/circuitboard/airlock/attackby(obj/item/W as obj, mob/user as mob) + if(issolder(W)) + var/obj/item/weapon/solder/S = W + if(icon_state == "door_electronics_smoked") + if(!S.remove_fuel(4,user)) + return + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + if(do_after(user, src,40)) + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + icon_state = "door_electronics" to_chat(user, "You repair the blown fuses on the circuitboard.") - -/obj/item/weapon/circuitboard/airlock/attack_self(mob/user as mob) - if (!ishuman(user) && !isrobot(user)) - return ..(user) - - // Can't manipulate it when broken (e.g. emagged) - if (icon_state == "door_electronics_smoked") - return - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - return - - var/t1 = text("Access control
      \n") - - if (last_configurator) - t1 += "Operator: [last_configurator]
      " - - if (locked) - if(isrobot(user)) - t1 += "Log In
      " - else - t1 += "Swipe ID
      " - else - t1 += "Block
      " - - t1 += "Access requirement is set to " - t1 += one_access ? "ONE
      " : "ALL
      " - - t1 += conf_access == null ? "All
      " : "All
      " - - t1 += "
      " - - var/list/accesses = get_all_accesses() - for (var/acc in accesses) - var/aname = get_access_desc(acc) - - if (!conf_access || !conf_access.len || !(acc in conf_access)) - t1 += "[aname]
      " - else if(one_access) - t1 += "[aname]
      " - else - t1 += "[aname]
      " - - t1 += text("

      Close

      \n", src) - - user << browse(t1, "window=airlock_electronics") - onclose(user, "airlock") - -/obj/item/weapon/circuitboard/airlock/Topic(href, href_list) - if(..()) return 1 - if (usr.stat || usr.restrained() || (!ishuman(usr) && !isrobot(usr)) || icon_state == "door_electronics_smoked") - return - if (href_list["close"]) - usr << browse(null, "window=airlock") - return - - if (href_list["login"]) - if(ishuman(usr)) - var/mob/living/carbon/human/H=usr - var/obj/item/I = usr.get_active_hand() - if(!istype(I, /obj/item/weapon/card) || !istype(I, /obj/item/device/pda)) - I = H.wear_id - if(!I && (istype(H.wear_id,/obj/item/weapon/card) || istype(H.wear_id, /obj/item/device/pda))) - I = H.wear_id - 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(isrobot(usr)) - src.locked=0 - src.last_configurator = usr.name - - if (locked) - return - - if (href_list["logout"]) - locked = 1 - - if (href_list["one_access"]) - one_access = !one_access - - if (href_list["access"]) - toggle_access(href_list["access"]) - - attack_self(usr) - -/obj/item/weapon/circuitboard/airlock/proc/toggle_access(var/acc) - if (acc == "all") - conf_access = null - else - var/req = text2num(acc) - - if (conf_access == null) - conf_access = list() - - if (!(req in conf_access)) - conf_access += req - else - conf_access -= req - if (!conf_access.len) - conf_access = null - + +/obj/item/weapon/circuitboard/airlock/attack_self(mob/user as mob) + if (!ishuman(user) && !isrobot(user)) + return ..(user) + + // Can't manipulate it when broken (e.g. emagged) + if (icon_state == "door_electronics_smoked") + return + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + return + + var/t1 = text("Access control
      \n") + + if (last_configurator) + t1 += "Operator: [last_configurator]
      " + + if (locked) + if(isrobot(user)) + t1 += "Log In
      " + else + t1 += "Swipe ID
      " + else + t1 += "Block
      " + + t1 += "Access requirement is set to " + t1 += one_access ? "ONE
      " : "ALL
      " + + t1 += conf_access == null ? "All
      " : "All
      " + + t1 += "
      " + + var/list/accesses = get_all_accesses() + for (var/acc in accesses) + var/aname = get_access_desc(acc) + + if (!conf_access || !conf_access.len || !(acc in conf_access)) + t1 += "[aname]
      " + else if(one_access) + t1 += "[aname]
      " + else + t1 += "[aname]
      " + + t1 += text("

      Close

      \n", src) + + user << browse(t1, "window=airlock_electronics") + onclose(user, "airlock") + +/obj/item/weapon/circuitboard/airlock/Topic(href, href_list) + if(..()) return 1 + if (usr.stat || usr.restrained() || (!ishuman(usr) && !isrobot(usr)) || icon_state == "door_electronics_smoked") + return + if (href_list["close"]) + usr << browse(null, "window=airlock") + return + + if (href_list["login"]) + if(ishuman(usr)) + var/mob/living/carbon/human/H=usr + var/obj/item/I = usr.get_active_hand() + if(!istype(I, /obj/item/weapon/card) || !istype(I, /obj/item/device/pda)) + I = H.wear_id + if(!I && (istype(H.wear_id,/obj/item/weapon/card) || istype(H.wear_id, /obj/item/device/pda))) + I = H.wear_id + 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(isrobot(usr)) + src.locked=0 + src.last_configurator = usr.name + + if (locked) + return + + if (href_list["logout"]) + locked = 1 + + if (href_list["one_access"]) + one_access = !one_access + + if (href_list["access"]) + toggle_access(href_list["access"]) + + attack_self(usr) + +/obj/item/weapon/circuitboard/airlock/proc/toggle_access(var/acc) + if (acc == "all") + conf_access = null + else + var/req = text2num(acc) + + if (conf_access == null) + conf_access = list() + + if (!(req in conf_access)) + conf_access += req + else + conf_access -= req + if (!conf_access.len) + conf_access = null + diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm index 46c6f6f8572..d759e85eca0 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -1,40 +1,40 @@ -/obj/machinery/door/airlock/alarmlock - - name = "Glass Alarm Airlock" - icon = 'icons/obj/doors/Doorglass.dmi' - opacity = 0 - glass = 1 - - var/datum/radio_frequency/air_connection - var/air_frequency = 1437 - autoclose = 0 - -/obj/machinery/door/airlock/alarmlock/New() - ..() - air_connection = new - -/obj/machinery/door/airlock/alarmlock/initialize() - ..() - radio_controller.remove_object(src, air_frequency) - air_connection = radio_controller.add_object(src, air_frequency, RADIO_TO_AIRALARM) - open() - - -/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal) - ..() - if(stat & (NOPOWER|BROKEN)) - return - - var/alarm_area = signal.data["zone"] - var/alert = signal.data["alert"] - - var/area/our_area = get_area(src) - - if(alarm_area == our_area.name) - switch(alert) - if("severe") - autoclose = 1 - close() - if("minor", "clear") - autoclose = 0 +/obj/machinery/door/airlock/alarmlock + + name = "Glass Alarm Airlock" + icon = 'icons/obj/doors/Doorglass.dmi' + opacity = 0 + glass = 1 + + var/datum/radio_frequency/air_connection + var/air_frequency = 1437 + autoclose = 0 + +/obj/machinery/door/airlock/alarmlock/New() + ..() + air_connection = new + +/obj/machinery/door/airlock/alarmlock/initialize() + ..() + radio_controller.remove_object(src, air_frequency) + air_connection = radio_controller.add_object(src, air_frequency, RADIO_TO_AIRALARM) + open() + + +/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal) + ..() + if(stat & (NOPOWER|BROKEN)) + return + + var/alarm_area = signal.data["zone"] + var/alert = signal.data["alert"] + + var/area/our_area = get_area(src) + + if(alarm_area == our_area.name) + switch(alert) + if("severe") + autoclose = 1 + close() + if("minor", "clear") + autoclose = 0 open() \ No newline at end of file diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 0624e7b9ec7..0e46fc44727 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -1,309 +1,309 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/////////////////////////////////////////////////////////////////////////////////////////////// -// Brig Door control displays. -// Description: This is a controls the timer for the brig doors, displays the timer on itself and -// has a popup window when used, allowing to set the timer. -// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code -// Date: 01/september/2010 -// Programmer: Veryinky -///////////////////////////////////////////////////////////////////////////////////////////////// -/obj/machinery/door_timer - name = "Door Timer" - icon = 'icons/obj/status_display.dmi' - icon_state = "frame" - desc = "A remote control for a door." - req_access = list(access_brig) - anchored = 1.0 // can't pick it up - density = 0 // can walk through it. - var/id_tag = null // id of door it controls. - var/releasetime = 0 // when world.time reaches it - release the prisoneer - var/timing = 1 // boolean, true/1 timer is on, false/0 means it's not timing - var/picture_state // icon_state of alert picture, if not displaying text/numbers - var/list/obj/machinery/targets = list() - - - New() - ..() - - pixel_x = ((src.dir & 3)? (0) : (src.dir == 4 ? 32 : -32)) - pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0)) - - spawn(20) - for(var/obj/machinery/door/window/brigdoor/M in all_doors) - if (M.id_tag == src.id_tag) - targets += M - - for(var/obj/machinery/flasher/F in flashers) - if(F.id_tag == src.id_tag) - targets += F - - for(var/obj/structure/closet/secure_closet/brig/C in world) - if(C.id_tag == src.id_tag) - targets += C - - if(targets.len==0) - stat |= BROKEN - update_icon() - return - return - - -//Main door timer loop, if it's timing and time is >0 reduce time by 1. -// if it's less than 0, open door, reset timer -// update the door_timer window and the icon - process() - if(stat & (NOPOWER|BROKEN)) return - if(src.timing) - if(world.time > src.releasetime) - src.timer_end() // open doors, reset timer, clear status screen - src.timing = 0 - src.updateUsrDialog() - src.update_icon() - else - timer_end() - return - - -// has the door power sitatuation changed, if so update icon. - power_change() - ..() - update_icon() - return - - -// open/closedoor checks if door_timer has power, if so it checks if the -// linked door is open/closed (by density) then opens it/closes it. - proc/timer_start() - if(stat & (NOPOWER|BROKEN)) return 0 - - for(var/obj/machinery/door/window/brigdoor/door in targets) - if(door.density) continue - spawn(0) - door.close() - - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) continue - if(C.opened && !C.close()) continue - C.locked = 1 - C.icon_state = C.icon_locked - return 1 - - - proc/timer_end() - if(stat & (NOPOWER|BROKEN)) return 0 - - for(var/obj/machinery/door/window/brigdoor/door in targets) - if(!door.density) continue - spawn(0) - door.open() - - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) continue - if(C.opened) continue - C.locked = 0 - C.icon_state = C.icon_closed - - return 1 - - - proc/timeleft() - . = (releasetime-world.time)/10 - if(. < 0) - . = 0 - - - proc/timeset(var/seconds) - releasetime=world.time+seconds*10 - return - - -//Allows AIs to use door_timer, see human attack_hand function below - attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - - -//Allows humans to use door_timer -//Opens dialog window when someone clicks on door timer -// Allows altering timer and the timing boolean. -// Flasher activation limited to 150 seconds - attack_hand(var/mob/user as mob) - if(..()) - return - var/second = round(timeleft() % 60) - var/minute = round((timeleft() - second) / 60) - user.set_machine(src) - var/dat = "" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\doors\brigdoors.dm:138: dat += "
      Timer System:" - dat += {"
      Timer System: - Door [src.id_tag] controls
      "} - // END AUTOFIX - if (src.timing) - dat += "Stop Timer and open door
      " - else - dat += "Activate Timer and close door
      " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\doors\brigdoors.dm:145: dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
      " - dat += {"Time Left: [(minute ? text("[minute]:") : null)][second]
      - - - + +
      "} - // END AUTOFIX - for(var/obj/machinery/flasher/F in targets) - if(F.last_flash && (F.last_flash + 150) > world.time) - dat += "
      Flash Charging" - else - dat += "
      Activate Flash" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\doors\brigdoors.dm:154: dat += "

      Close" - dat += {"

      Close -
      "} - // END AUTOFIX - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - - -//Function for using door_timer dialog input, checks if user has permission -// href_list to -// "timing" turns on timer -// "tp" value to modify timer -// "fc" activates flasher -// Also updates dialog window and timer icon - Topic(href, href_list) - if(..()) - return - if(!src.allowed(usr)) - return - - usr.set_machine(src) - if(href_list["timing"]) - src.timing = text2num(href_list["timing"]) - else - if(href_list["tp"]) //adjust timer, close door if not already closed - var/tp = text2num(href_list["tp"]) - var/timeleft = timeleft() - timeleft += tp - timeleft = min(max(round(timeleft), 0), 3600) - timeset(timeleft) - //src.timing = 1 - //src.closedoor() - if(href_list["fc"]) - for(var/obj/machinery/flasher/F in targets) - F.flash() - src.add_fingerprint(usr) - src.updateUsrDialog() - src.update_icon() - if(src.timing) - src.timer_start() - else - src.timer_end() - return - - -//icon update function -// if NOPOWER, display blank -// if BROKEN, display blue screen of death icon AI uses -// if timing=true, run update display function - update_icon() - if(stat & (NOPOWER)) - icon_state = "frame" - return - if(stat & (BROKEN)) - set_picture("ai_bsod") - return - if(src.timing) - var/disp1 = uppertext(id_tag) - var/timeleft = timeleft() - var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]" - spawn( 5 ) - update_display(disp1, disp2) - else - update_display("SET","TIME") - return - - -// Adds an icon in case the screen is broken/off, stolen from status_display.dm - proc/set_picture(var/state) - picture_state = state - overlays.len = 0 - overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) - - -//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display -// Stolen from status_display - proc/update_display(var/line1, var/line2) - if(line2 == null) // single line display - overlays.len = 0 - overlays += texticon(line1, 23, -13) - else // dual line display - overlays.len = 0 - overlays += texticon(line1, 23, -9) - overlays += texticon(line2, 23, -17) - // return an icon of a time text string (tn) - // valid characters are 0-9 and : - // px, py are pixel offsets - - -//Actual string input to icon display for loop, with 5 pixel x offsets for each letter. -//Stolen from status_display - proc/texticon(var/tn, var/px = 0, var/py = 0) - var/image/I = image('icons/obj/status_display.dmi', "blank") - var/len = length(tn) - - for(var/d = 1 to len) - var/char = copytext(tn, len-d+1, len-d+2) - if(char == " ") - continue - var/image/ID = image('icons/obj/status_display.dmi', icon_state=char) - ID.pixel_x = -(d-1)*5 + px - ID.pixel_y = py - I.overlays += ID - return I - - -/obj/machinery/door_timer/cell_1 - name = "Cell 1" - id_tag = "Cell 1" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_2 - name = "Cell 2" - id_tag = "Cell 2" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_3 - name = "Cell 3" - id_tag = "Cell 3" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_4 - name = "Cell 4" - id_tag = "Cell 4" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_5 - name = "Cell 5" - id_tag = "Cell 5" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_6 - name = "Cell 6" - id_tag = "Cell 6" - dir = 4 - pixel_x = 32 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/////////////////////////////////////////////////////////////////////////////////////////////// +// Brig Door control displays. +// Description: This is a controls the timer for the brig doors, displays the timer on itself and +// has a popup window when used, allowing to set the timer. +// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code +// Date: 01/september/2010 +// Programmer: Veryinky +///////////////////////////////////////////////////////////////////////////////////////////////// +/obj/machinery/door_timer + name = "Door Timer" + icon = 'icons/obj/status_display.dmi' + icon_state = "frame" + desc = "A remote control for a door." + req_access = list(access_brig) + anchored = 1.0 // can't pick it up + density = 0 // can walk through it. + var/id_tag = null // id of door it controls. + var/releasetime = 0 // when world.time reaches it - release the prisoneer + var/timing = 1 // boolean, true/1 timer is on, false/0 means it's not timing + var/picture_state // icon_state of alert picture, if not displaying text/numbers + var/list/obj/machinery/targets = list() + + + New() + ..() + + pixel_x = ((src.dir & 3)? (0) : (src.dir == 4 ? 32 : -32)) + pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0)) + + spawn(20) + for(var/obj/machinery/door/window/brigdoor/M in all_doors) + if (M.id_tag == src.id_tag) + targets += M + + for(var/obj/machinery/flasher/F in flashers) + if(F.id_tag == src.id_tag) + targets += F + + for(var/obj/structure/closet/secure_closet/brig/C in world) + if(C.id_tag == src.id_tag) + targets += C + + if(targets.len==0) + stat |= BROKEN + update_icon() + return + return + + +//Main door timer loop, if it's timing and time is >0 reduce time by 1. +// if it's less than 0, open door, reset timer +// update the door_timer window and the icon + process() + if(stat & (NOPOWER|BROKEN)) return + if(src.timing) + if(world.time > src.releasetime) + src.timer_end() // open doors, reset timer, clear status screen + src.timing = 0 + src.updateUsrDialog() + src.update_icon() + else + timer_end() + return + + +// has the door power sitatuation changed, if so update icon. + power_change() + ..() + update_icon() + return + + +// open/closedoor checks if door_timer has power, if so it checks if the +// linked door is open/closed (by density) then opens it/closes it. + proc/timer_start() + if(stat & (NOPOWER|BROKEN)) return 0 + + for(var/obj/machinery/door/window/brigdoor/door in targets) + if(door.density) continue + spawn(0) + door.close() + + for(var/obj/structure/closet/secure_closet/brig/C in targets) + if(C.broken) continue + if(C.opened && !C.close()) continue + C.locked = 1 + C.icon_state = C.icon_locked + return 1 + + + proc/timer_end() + if(stat & (NOPOWER|BROKEN)) return 0 + + for(var/obj/machinery/door/window/brigdoor/door in targets) + if(!door.density) continue + spawn(0) + door.open() + + for(var/obj/structure/closet/secure_closet/brig/C in targets) + if(C.broken) continue + if(C.opened) continue + C.locked = 0 + C.icon_state = C.icon_closed + + return 1 + + + proc/timeleft() + . = (releasetime-world.time)/10 + if(. < 0) + . = 0 + + + proc/timeset(var/seconds) + releasetime=world.time+seconds*10 + return + + +//Allows AIs to use door_timer, see human attack_hand function below + attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + + +//Allows humans to use door_timer +//Opens dialog window when someone clicks on door timer +// Allows altering timer and the timing boolean. +// Flasher activation limited to 150 seconds + attack_hand(var/mob/user as mob) + if(..()) + return + var/second = round(timeleft() % 60) + var/minute = round((timeleft() - second) / 60) + user.set_machine(src) + var/dat = "" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\doors\brigdoors.dm:138: dat += "
      Timer System:" + dat += {"
      Timer System: + Door [src.id_tag] controls
      "} + // END AUTOFIX + if (src.timing) + dat += "Stop Timer and open door
      " + else + dat += "Activate Timer and close door
      " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\doors\brigdoors.dm:145: dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
      " + dat += {"Time Left: [(minute ? text("[minute]:") : null)][second]
      + - - + +
      "} + // END AUTOFIX + for(var/obj/machinery/flasher/F in targets) + if(F.last_flash && (F.last_flash + 150) > world.time) + dat += "
      Flash Charging" + else + dat += "
      Activate Flash" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\doors\brigdoors.dm:154: dat += "

      Close" + dat += {"

      Close +
      "} + // END AUTOFIX + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + + +//Function for using door_timer dialog input, checks if user has permission +// href_list to +// "timing" turns on timer +// "tp" value to modify timer +// "fc" activates flasher +// Also updates dialog window and timer icon + Topic(href, href_list) + if(..()) + return + if(!src.allowed(usr)) + return + + usr.set_machine(src) + if(href_list["timing"]) + src.timing = text2num(href_list["timing"]) + else + if(href_list["tp"]) //adjust timer, close door if not already closed + var/tp = text2num(href_list["tp"]) + var/timeleft = timeleft() + timeleft += tp + timeleft = min(max(round(timeleft), 0), 3600) + timeset(timeleft) + //src.timing = 1 + //src.closedoor() + if(href_list["fc"]) + for(var/obj/machinery/flasher/F in targets) + F.flash() + src.add_fingerprint(usr) + src.updateUsrDialog() + src.update_icon() + if(src.timing) + src.timer_start() + else + src.timer_end() + return + + +//icon update function +// if NOPOWER, display blank +// if BROKEN, display blue screen of death icon AI uses +// if timing=true, run update display function + update_icon() + if(stat & (NOPOWER)) + icon_state = "frame" + return + if(stat & (BROKEN)) + set_picture("ai_bsod") + return + if(src.timing) + var/disp1 = uppertext(id_tag) + var/timeleft = timeleft() + var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]" + spawn( 5 ) + update_display(disp1, disp2) + else + update_display("SET","TIME") + return + + +// Adds an icon in case the screen is broken/off, stolen from status_display.dm + proc/set_picture(var/state) + picture_state = state + overlays.len = 0 + overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) + + +//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display +// Stolen from status_display + proc/update_display(var/line1, var/line2) + if(line2 == null) // single line display + overlays.len = 0 + overlays += texticon(line1, 23, -13) + else // dual line display + overlays.len = 0 + overlays += texticon(line1, 23, -9) + overlays += texticon(line2, 23, -17) + // return an icon of a time text string (tn) + // valid characters are 0-9 and : + // px, py are pixel offsets + + +//Actual string input to icon display for loop, with 5 pixel x offsets for each letter. +//Stolen from status_display + proc/texticon(var/tn, var/px = 0, var/py = 0) + var/image/I = image('icons/obj/status_display.dmi', "blank") + var/len = length(tn) + + for(var/d = 1 to len) + var/char = copytext(tn, len-d+1, len-d+2) + if(char == " ") + continue + var/image/ID = image('icons/obj/status_display.dmi', icon_state=char) + ID.pixel_x = -(d-1)*5 + px + ID.pixel_y = py + I.overlays += ID + return I + + +/obj/machinery/door_timer/cell_1 + name = "Cell 1" + id_tag = "Cell 1" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_2 + name = "Cell 2" + id_tag = "Cell 2" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_3 + name = "Cell 3" + id_tag = "Cell 3" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_4 + name = "Cell 4" + id_tag = "Cell 4" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_5 + name = "Cell 5" + id_tag = "Cell 5" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_6 + name = "Cell 6" + id_tag = "Cell 6" + dir = 4 + pixel_x = 32 diff --git a/code/game/machinery/doors/checkForMultipleDoors.dm b/code/game/machinery/doors/checkForMultipleDoors.dm index 9005a7fda49..f7ad56cb134 100644 --- a/code/game/machinery/doors/checkForMultipleDoors.dm +++ b/code/game/machinery/doors/checkForMultipleDoors.dm @@ -1,16 +1,16 @@ -/obj/machinery/door/proc/checkForMultipleDoors() - if(!src.loc) - return 0 - for(var/obj/machinery/door/D in src.loc) - if(!istype(D, /obj/machinery/door/window) && D.density) - return 0 - return 1 - -/turf/simulated/wall/proc/checkForMultipleDoors() - if(!src.loc) - return 0 - for(var/obj/machinery/door/D in locate(src.x,src.y,src.z)) - if(!istype(D, /obj/machinery/door/window) && D.density) - return 0 - //There are no false wall checks because that would be fucking retarded +/obj/machinery/door/proc/checkForMultipleDoors() + if(!src.loc) + return 0 + for(var/obj/machinery/door/D in src.loc) + if(!istype(D, /obj/machinery/door/window) && D.density) + return 0 + return 1 + +/turf/simulated/wall/proc/checkForMultipleDoors() + if(!src.loc) + return 0 + for(var/obj/machinery/door/D in locate(src.x,src.y,src.z)) + if(!istype(D, /obj/machinery/door/window) && D.density) + return 0 + //There are no false wall checks because that would be fucking retarded return 1 \ No newline at end of file diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 6584bf81075..d88c6eacfa0 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -1,427 +1,427 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -#define BLOB_PROBABILITY 40 -#define HEADBUTT_PROBABILITY 40 -#define BRAINLOSS_FOR_HEADBUTT 60 - -#define DOOR_LAYER 2.7 -#define DOOR_CLOSED_MOD 0.3 //how much the layer is increased when the door is closed - -var/list/all_doors = list() -/obj/machinery/door - name = "door" - desc = "It opens and closes." - icon = 'icons/obj/doors/door.dmi' - icon_state = "door_closed" - anchored = 1 - opacity = 1 - density = 1 - layer = DOOR_LAYER - penetration_dampening = 10 - var/base_layer = DOOR_LAYER - - var/secondsElectrified = 0 - var/visible = 1 - var/operating = 0 - var/autoclose = 0 - var/glass = 0 - var/normalspeed = 1 - - machine_flags = SCREWTOGGLE - - // for glass airlocks/opacity firedoors - var/heat_proof = 0 - - var/air_properties_vary_with_direction = 0 - - // multi-tile doors - dir = EAST - var/width = 1 - - // from old /vg/ - // the object that's jammed us open/closed - var/obj/jammed = null - - // if the door has certain variation, like rapid (r_) - var/prefix = null - - // TODO: refactor to best :( - var/animation_delay = 12 - var/animation_delay_2 = null - - // turf animation - var/atom/movable/overlay/c_animation = null - - var/soundeffect = 'sound/machines/airlock.ogg' - - var/explosion_block = 0 //regular airlocks are 1, blast doors are 3, higher values mean increasingly effective at blocking explosions. - forceinvertredraw = 1 - -/obj/machinery/door/projectile_check() - if(opacity) - return PROJREACT_WALLS - else - return PROJREACT_WINDOWS - -/obj/machinery/door/Bumped(atom/AM) - if (ismob(AM)) - var/mob/M = AM - - // can bump open one airlock per second - // this is to prevent shock spam - if(world.time - M.last_bumped <= 10) - return - - M.last_bumped = world.time - - if(!M.restrained() && (M.size > SIZE_TINY)) - bump_open(M) - - return - - if (istype(AM, /obj/machinery/bot)) - var/obj/machinery/bot/bot = AM - - if (check_access(bot.botcard) && !operating) - open() - - return - - if (istype(AM, /obj/mecha)) - var/obj/mecha/mecha = AM - - if (density) - if (mecha.occupant && !operating && (allowed(mecha.occupant) || check_access_list(mecha.operation_req_access))) - open() - else if(!operating) - playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) - door_animate("deny") - - if (istype(AM, /obj/structure/bed/chair/vehicle)) - var/obj/structure/bed/chair/vehicle/vehicle = AM - - if (density) - if (vehicle.locked_atoms.len && !operating && allowed(vehicle.locked_atoms[1])) - if(istype(vehicle, /obj/structure/bed/chair/vehicle/wizmobile)) - vehicle.forceMove(get_step(vehicle,vehicle.dir))//Firebird doesn't wait for no slowpoke door to fully open before dashing through! - open() - else if(!operating) - playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) - door_animate("deny") - -/obj/machinery/door/proc/bump_open(mob/user as mob) - // TODO: analyze this - if(user.last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) //Fakkit - return - - add_fingerprint(user) - - if(!requiresID()) - user = null - - if(allowed(user)) - open() - else if(!operating) - playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) - door_animate("deny") - - return - -/obj/machinery/door/attack_ai(mob/user as mob) - add_hiddenprint(user) - attack_hand(user) - return - -/obj/machinery/door/attack_paw(mob/user as mob) - attack_hand(user) - return - -/obj/machinery/door/attack_hand(mob/user as mob) - if (prob(HEADBUTT_PROBABILITY) && density && ishuman(user)) - var/mob/living/carbon/human/H = user - - if (H.getBrainLoss() >= BRAINLOSS_FOR_HEADBUTT) - // TODO: analyze the called proc - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) - - if (!istype(H.head, /obj/item/clothing/head/helmet)) - visible_message("[user] headbutts the airlock.") - H.Stun(8) - H.Weaken(5) - var/datum/organ/external/O = H.get_organ("head") - - // TODO: analyze the called proc - if(O.take_damage(10, 0)) - H.UpdateDamageIcon() - O = null - else - // TODO: fix sentence - visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.") - - H = null - return - - H = null - - add_fingerprint(user) - attackby(null, user) - return - - -/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob) - if(..()) - return 1 - - if (istype(I, /obj/item/device/detective_scanner)) - return - - // borgs can't attack doors open - // because it conflicts with their AI-like interaction with them - if (isrobot(user)) - return - - if (!requiresID()) - user = null - - if (allowed(user)) - if (!density) - return close() - else - return open() - - playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) - door_animate("deny") - return - -/obj/machinery/door/blob_act() - if(prob(BLOB_PROBABILITY)) - qdel(src) - -/obj/machinery/door/proc/door_animate(var/animation as text) - switch (animation) - if ("opening") - flick("[prefix]door_opening", src) - if ("closing") - flick("[prefix]door_closing", src) - - sleep(animation_delay) - return - -/obj/machinery/door/update_icon() - if(!density) - icon_state = "[prefix]door_open" - else - icon_state = "[prefix]door_closed" - - sleep(animation_delay_2) - return - -/* -/obj/machinery/door/proc/open() - if (!density || operating || jammed) - return - - operating = 1 - - door_animate("opening") - - if (!istype(type, /obj/machinery/door/firedoor)) - layer = 2.7 - else - layer = 2.6 - - density = 0 - update_icon() - opacity = 0 - - // TODO: analyze this proc - update_nearby_tiles() - - operating = 0 - - // TODO: re-logic later - if (autoclose && normalspeed) - spawn(150) - autoclose() - else if (autoclose && !normalspeed) - spawn(5) - autoclose() - - return -*/ - -/obj/machinery/door/proc/open() - if(!density) return 1 - if(operating > 0) return - if(!ticker) return 0 - if(!operating) operating = 1 - - door_animate("opening") - src.set_opacity(0) - sleep(10) - src.layer = base_layer - src.density = 0 - explosion_resistance = 0 - update_icon() - set_opacity(0) - update_nearby_tiles() - //update_freelook_sight() - - if(operating == 1) - operating = 0 - - return 1 - -/obj/machinery/door/proc/autoclose() - var/obj/machinery/door/airlock/A = src - if(!A.density && !A.operating && !A.locked && !A.welded && A.autoclose && !A.jammed) - close() - return - -/obj/machinery/door/proc/close() - if (density || operating || jammed) - return - operating = 1 - door_animate("closing") - - layer = base_layer + DOOR_CLOSED_MOD - - density = 1 - update_icon() - - if (!glass) - src.set_opacity(1) - // Copypasta!!! - var/obj/effect/beam/B = locate() in loc - if(B) - qdel(B) - - // TODO: rework how fire works on doors - var/obj/fire/F = locate() in loc - if(F) - qdel(F) - - update_nearby_tiles() - operating = 0 - -/obj/machinery/door/New() - . = ..() - all_doors += src - - if(density) - // above most items if closed - layer = base_layer + DOOR_CLOSED_MOD - - explosion_resistance = initial(explosion_resistance) - else - // under all objects if opened. 2.7 due to tables being at 2.6 - layer = base_layer - - explosion_resistance = 0 - - if(width > 1) - if(dir in list(EAST, WEST)) - bound_width = width * world.icon_size - bound_height = world.icon_size - else - bound_width = world.icon_size - bound_height = width * world.icon_size - - update_nearby_tiles() - -/obj/machinery/door/cultify() - if(invisibility != INVISIBILITY_MAXIMUM) - invisibility = INVISIBILITY_MAXIMUM - density = 0 - anim(target = src, a_icon = 'icons/effects/effects.dmi', a_icon_state = "breakdoor", sleeptime = 10) - qdel(src) - -/obj/machinery/door/Destroy() - update_nearby_tiles() - all_doors -= src - ..() - -/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group) return 0 - if(istype(mover) && mover.checkpass(PASSGLASS)) - return !opacity - return !density - -/obj/machinery/door/proc/CanAStarPass(var/obj/item/weapon/card/id/ID) - return !density || check_access(ID) - - -/obj/machinery/door/emp_act(severity) - if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) ) - open(6) - if(prob(40/severity)) - if(secondsElectrified == 0) - secondsElectrified = -1 - spawn(300) - secondsElectrified = 0 - ..() - - -/obj/machinery/door/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - if(prob(25)) - qdel(src) - if(3.0) - if(prob(80)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - return - -/obj/machinery/door/proc/requiresID() - return 1 - -/obj/machinery/door/proc/update_nearby_tiles(var/turf/T) - if(!air_master) - return 0 - - if(!T) - T = get_turf(src) - update_heat_protection(T) - air_master.mark_for_update(T) - - update_freelok_sight() - return 1 - -/obj/machinery/door/forceMove(var/atom/A) - var/turf/T = loc - ..() - update_nearby_tiles(T) - update_nearby_tiles() - -/obj/machinery/door/proc/update_heat_protection(var/turf/simulated/source) - if(istype(source)) - if(src.density && (src.opacity || src.heat_proof)) - source.thermal_conductivity = DOOR_HEAT_TRANSFER_COEFFICIENT - else - source.thermal_conductivity = initial(source.thermal_conductivity) - -/obj/machinery/door/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) - -/obj/machinery/door/Move(new_loc, new_dir) - update_nearby_tiles() - . = ..() - if(width > 1) - if(dir in list(EAST, WEST)) - bound_width = width * world.icon_size - bound_height = world.icon_size - else - bound_width = world.icon_size - bound_height = width * world.icon_size - - update_nearby_tiles() - -/obj/machinery/door/morgue - icon = 'icons/obj/doors/morgue.dmi' - animation_delay = 15 - penetration_dampening = 15 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +#define BLOB_PROBABILITY 40 +#define HEADBUTT_PROBABILITY 40 +#define BRAINLOSS_FOR_HEADBUTT 60 + +#define DOOR_LAYER 2.7 +#define DOOR_CLOSED_MOD 0.3 //how much the layer is increased when the door is closed + +var/list/all_doors = list() +/obj/machinery/door + name = "door" + desc = "It opens and closes." + icon = 'icons/obj/doors/door.dmi' + icon_state = "door_closed" + anchored = 1 + opacity = 1 + density = 1 + layer = DOOR_LAYER + penetration_dampening = 10 + var/base_layer = DOOR_LAYER + + var/secondsElectrified = 0 + var/visible = 1 + var/operating = 0 + var/autoclose = 0 + var/glass = 0 + var/normalspeed = 1 + + machine_flags = SCREWTOGGLE + + // for glass airlocks/opacity firedoors + var/heat_proof = 0 + + var/air_properties_vary_with_direction = 0 + + // multi-tile doors + dir = EAST + var/width = 1 + + // from old /vg/ + // the object that's jammed us open/closed + var/obj/jammed = null + + // if the door has certain variation, like rapid (r_) + var/prefix = null + + // TODO: refactor to best :( + var/animation_delay = 12 + var/animation_delay_2 = null + + // turf animation + var/atom/movable/overlay/c_animation = null + + var/soundeffect = 'sound/machines/airlock.ogg' + + var/explosion_block = 0 //regular airlocks are 1, blast doors are 3, higher values mean increasingly effective at blocking explosions. + forceinvertredraw = 1 + +/obj/machinery/door/projectile_check() + if(opacity) + return PROJREACT_WALLS + else + return PROJREACT_WINDOWS + +/obj/machinery/door/Bumped(atom/AM) + if (ismob(AM)) + var/mob/M = AM + + // can bump open one airlock per second + // this is to prevent shock spam + if(world.time - M.last_bumped <= 10) + return + + M.last_bumped = world.time + + if(!M.restrained() && (M.size > SIZE_TINY)) + bump_open(M) + + return + + if (istype(AM, /obj/machinery/bot)) + var/obj/machinery/bot/bot = AM + + if (check_access(bot.botcard) && !operating) + open() + + return + + if (istype(AM, /obj/mecha)) + var/obj/mecha/mecha = AM + + if (density) + if (mecha.occupant && !operating && (allowed(mecha.occupant) || check_access_list(mecha.operation_req_access))) + open() + else if(!operating) + playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) + door_animate("deny") + + if (istype(AM, /obj/structure/bed/chair/vehicle)) + var/obj/structure/bed/chair/vehicle/vehicle = AM + + if (density) + if (vehicle.locked_atoms.len && !operating && allowed(vehicle.locked_atoms[1])) + if(istype(vehicle, /obj/structure/bed/chair/vehicle/wizmobile)) + vehicle.forceMove(get_step(vehicle,vehicle.dir))//Firebird doesn't wait for no slowpoke door to fully open before dashing through! + open() + else if(!operating) + playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) + door_animate("deny") + +/obj/machinery/door/proc/bump_open(mob/user as mob) + // TODO: analyze this + if(user.last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) //Fakkit + return + + add_fingerprint(user) + + if(!requiresID()) + user = null + + if(allowed(user)) + open() + else if(!operating) + playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) + door_animate("deny") + + return + +/obj/machinery/door/attack_ai(mob/user as mob) + add_hiddenprint(user) + attack_hand(user) + return + +/obj/machinery/door/attack_paw(mob/user as mob) + attack_hand(user) + return + +/obj/machinery/door/attack_hand(mob/user as mob) + if (prob(HEADBUTT_PROBABILITY) && density && ishuman(user)) + var/mob/living/carbon/human/H = user + + if (H.getBrainLoss() >= BRAINLOSS_FOR_HEADBUTT) + // TODO: analyze the called proc + playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + + if (!istype(H.head, /obj/item/clothing/head/helmet)) + visible_message("[user] headbutts the airlock.") + H.Stun(8) + H.Weaken(5) + var/datum/organ/external/O = H.get_organ("head") + + // TODO: analyze the called proc + if(O.take_damage(10, 0)) + H.UpdateDamageIcon() + O = null + else + // TODO: fix sentence + visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.") + + H = null + return + + H = null + + add_fingerprint(user) + attackby(null, user) + return + + +/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob) + if(..()) + return 1 + + if (istype(I, /obj/item/device/detective_scanner)) + return + + // borgs can't attack doors open + // because it conflicts with their AI-like interaction with them + if (isrobot(user)) + return + + if (!requiresID()) + user = null + + if (allowed(user)) + if (!density) + return close() + else + return open() + + playsound(src.loc, 'sound/machines/denied.ogg', 50, 1) + door_animate("deny") + return + +/obj/machinery/door/blob_act() + if(prob(BLOB_PROBABILITY)) + qdel(src) + +/obj/machinery/door/proc/door_animate(var/animation as text) + switch (animation) + if ("opening") + flick("[prefix]door_opening", src) + if ("closing") + flick("[prefix]door_closing", src) + + sleep(animation_delay) + return + +/obj/machinery/door/update_icon() + if(!density) + icon_state = "[prefix]door_open" + else + icon_state = "[prefix]door_closed" + + sleep(animation_delay_2) + return + +/* +/obj/machinery/door/proc/open() + if (!density || operating || jammed) + return + + operating = 1 + + door_animate("opening") + + if (!istype(type, /obj/machinery/door/firedoor)) + layer = 2.7 + else + layer = 2.6 + + density = 0 + update_icon() + opacity = 0 + + // TODO: analyze this proc + update_nearby_tiles() + + operating = 0 + + // TODO: re-logic later + if (autoclose && normalspeed) + spawn(150) + autoclose() + else if (autoclose && !normalspeed) + spawn(5) + autoclose() + + return +*/ + +/obj/machinery/door/proc/open() + if(!density) return 1 + if(operating > 0) return + if(!ticker) return 0 + if(!operating) operating = 1 + + door_animate("opening") + src.set_opacity(0) + sleep(10) + src.layer = base_layer + src.density = 0 + explosion_resistance = 0 + update_icon() + set_opacity(0) + update_nearby_tiles() + //update_freelook_sight() + + if(operating == 1) + operating = 0 + + return 1 + +/obj/machinery/door/proc/autoclose() + var/obj/machinery/door/airlock/A = src + if(!A.density && !A.operating && !A.locked && !A.welded && A.autoclose && !A.jammed) + close() + return + +/obj/machinery/door/proc/close() + if (density || operating || jammed) + return + operating = 1 + door_animate("closing") + + layer = base_layer + DOOR_CLOSED_MOD + + density = 1 + update_icon() + + if (!glass) + src.set_opacity(1) + // Copypasta!!! + var/obj/effect/beam/B = locate() in loc + if(B) + qdel(B) + + // TODO: rework how fire works on doors + var/obj/fire/F = locate() in loc + if(F) + qdel(F) + + update_nearby_tiles() + operating = 0 + +/obj/machinery/door/New() + . = ..() + all_doors += src + + if(density) + // above most items if closed + layer = base_layer + DOOR_CLOSED_MOD + + explosion_resistance = initial(explosion_resistance) + else + // under all objects if opened. 2.7 due to tables being at 2.6 + layer = base_layer + + explosion_resistance = 0 + + if(width > 1) + if(dir in list(EAST, WEST)) + bound_width = width * world.icon_size + bound_height = world.icon_size + else + bound_width = world.icon_size + bound_height = width * world.icon_size + + update_nearby_tiles() + +/obj/machinery/door/cultify() + if(invisibility != INVISIBILITY_MAXIMUM) + invisibility = INVISIBILITY_MAXIMUM + density = 0 + anim(target = src, a_icon = 'icons/effects/effects.dmi', a_icon_state = "breakdoor", sleeptime = 10) + qdel(src) + +/obj/machinery/door/Destroy() + update_nearby_tiles() + all_doors -= src + ..() + +/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group) return 0 + if(istype(mover) && mover.checkpass(PASSGLASS)) + return !opacity + return !density + +/obj/machinery/door/proc/CanAStarPass(var/obj/item/weapon/card/id/ID) + return !density || check_access(ID) + + +/obj/machinery/door/emp_act(severity) + if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) ) + open(6) + if(prob(40/severity)) + if(secondsElectrified == 0) + secondsElectrified = -1 + spawn(300) + secondsElectrified = 0 + ..() + + +/obj/machinery/door/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + if(prob(25)) + qdel(src) + if(3.0) + if(prob(80)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + return + +/obj/machinery/door/proc/requiresID() + return 1 + +/obj/machinery/door/proc/update_nearby_tiles(var/turf/T) + if(!air_master) + return 0 + + if(!T) + T = get_turf(src) + update_heat_protection(T) + air_master.mark_for_update(T) + + update_freelok_sight() + return 1 + +/obj/machinery/door/forceMove(var/atom/A) + var/turf/T = loc + ..() + update_nearby_tiles(T) + update_nearby_tiles() + +/obj/machinery/door/proc/update_heat_protection(var/turf/simulated/source) + if(istype(source)) + if(src.density && (src.opacity || src.heat_proof)) + source.thermal_conductivity = DOOR_HEAT_TRANSFER_COEFFICIENT + else + source.thermal_conductivity = initial(source.thermal_conductivity) + +/obj/machinery/door/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) + +/obj/machinery/door/Move(new_loc, new_dir) + update_nearby_tiles() + . = ..() + if(width > 1) + if(dir in list(EAST, WEST)) + bound_width = width * world.icon_size + bound_height = world.icon_size + else + bound_width = world.icon_size + bound_height = width * world.icon_size + + update_nearby_tiles() + +/obj/machinery/door/morgue + icon = 'icons/obj/doors/morgue.dmi' + animation_delay = 15 + penetration_dampening = 15 diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 24f2da85ec9..6239ed94934 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -1,487 +1,487 @@ -/var/const/OPEN = 1 -/var/const/CLOSED = 2 - -var/global/list/alert_overlays_global = list() - -/proc/convert_k2c(var/temp) - return ((temp - T0C)) // * 1.8) + 32 - -/proc/convert_c2k(var/temp) - return ((temp + T0C)) // * 1.8) + 32 - -/proc/getCardinalAirInfo(var/atom/source, var/turf/loc, var/list/stats=list("temperature")) - var/list/temps = new/list(4) - for(var/dir in cardinal) - var/direction - switch(dir) - if(NORTH) - direction = 1 - if(SOUTH) - direction = 2 - if(EAST) - direction = 3 - if(WEST) - direction = 4 - - var/turf/simulated/T=get_turf(get_step(loc,dir)) - - if(dir == turn(source.dir, 180) && source.flags & ON_BORDER) //[ ][ |][ ] imagine the | is the source (with dir EAST -> facing right), and the brackets are floors. When we try to get the turf to the left's air info, use the middle's turf instead - if(!(locate(/obj/machinery/door/airlock) in get_turf(source))) //If we're on a door, however, DON'T DO THIS -> doors are airtight, so the result will be innacurate! This is a bad snowflake, but as long as it makes the feature freeze go away... - T = get_turf(source) - - var/list/rstats = new /list(stats.len) - if(T && istype(T) && T.zone) - var/datum/gas_mixture/environment = T.return_air() - for(var/i=1;i<=stats.len;i++) - rstats[i] = environment.vars[stats[i]] - else if(istype(T, /turf/simulated)) - rstats = null // Exclude zone (wall, door, etc). - else if(istype(T, /turf)) - // Should still work. (/turf/return_air()) - var/datum/gas_mixture/environment = T.return_air() - for(var/i=1;i<=stats.len;i++) - rstats[i] = environment.vars[stats[i]] - temps[direction] = rstats - return temps - -#define FIREDOOR_MAX_PRESSURE_DIFF 25 // kPa -#define FIREDOOR_MAX_TEMP 50 // �C -#define FIREDOOR_MIN_TEMP 0 - -// Bitflags -#define FIREDOOR_ALERT_HOT 1 -#define FIREDOOR_ALERT_COLD 2 -// Not used #define FIREDOOR_ALERT_LOWPRESS 4 - -#define FIREDOOR_CLOSED_MOD 0.8 - -/obj/machinery/door/firedoor - name = "\improper Emergency Shutter" - desc = "Emergency air-tight shutter, capable of sealing off breached areas." - icon = 'icons/obj/doors/DoorHazard.dmi' - icon_state = "door_open" - req_one_access = list(access_atmospherics, access_engine_equip) - opacity = 0 - density = 0 - layer = DOOR_LAYER - 0.2 - base_layer = DOOR_LAYER - 0.2 - - dir = 2 - - var/list/alert_overlays_local - - var/blocked = 0 - var/lockdown = 0 // When the door has detected a problem, it locks. - var/pdiff_alert = 0 - var/pdiff = 0 - var/nextstate = null - var/net_id - var/list/areas_added - var/list/users_to_open - var/list/tile_info[4] - var/list/dir_alerts[4] // 4 dirs, bitflags - - // MUST be in same order as FIREDOOR_ALERT_* - var/list/ALERT_STATES=list( - "hot", - "cold" - ) - -/obj/machinery/door/firedoor/New() - . = ..() - - if(!("[src.type]" in alert_overlays_global)) - alert_overlays_global += list("[src.type]" = list("alert_hot" = list(), - "alert_cold" = list()) - ) - - var/list/type_states = alert_overlays_global["[src.type]"] - - for(var/alert_state in type_states) - var/list/starting = list() - for(var/cdir in cardinal) - starting["[cdir]"] = icon(src.icon, alert_state, dir = cdir) - type_states[alert_state] = starting - alert_overlays_global["[src.type]"] = type_states - alert_overlays_local = type_states - else - alert_overlays_local = alert_overlays_global["[src.type]"] - - for(var/obj/machinery/door/firedoor/F in loc) - if(F != src) - if(F.flags & ON_BORDER && src.flags & ON_BORDER && F.dir != src.dir) //two border doors on the same tile don't collide - continue - spawn(1) - qdel(src) - return . - var/area/A = get_area(src) - ASSERT(istype(A)) - - A.all_doors.Add(src) - areas_added = list(A) - - for(var/direction in cardinal) - var/turf/T = get_step(src,direction) - if(istype(T,/turf/simulated/floor)) - A = get_area(get_step(src,direction)) - if(A) - A.all_doors |= src - areas_added |= A - - -/obj/machinery/door/firedoor/Destroy() - for(var/area/A in areas_added) - A.all_doors.Remove(src) - . = ..() - - -/obj/machinery/door/firedoor/examine(mob/user) - . = ..() - if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF) - to_chat(user, "WARNING: Current pressure differential is [pdiff]kPa! Opening door may result in injury!") - - to_chat(user, "Sensor readings:") - for(var/index = 1; index <= tile_info.len; index++) - var/o = "  " - switch(index) - if(1) - o += "NORTH: " - if(2) - o += "SOUTH: " - if(3) - o += "EAST: " - if(4) - o += "WEST: " - if(tile_info[index] == null) - o += "DATA UNAVAILABLE" - to_chat(usr, o) - continue - var/celsius = convert_k2c(tile_info[index][1]) - var/pressure = tile_info[index][2] - if(dir_alerts[index] & (FIREDOOR_ALERT_HOT|FIREDOOR_ALERT_COLD)) - o += "" - else - o += "" - o += "[celsius]�C " - o += "" - o += "[pressure]kPa" - to_chat(user, o) - - if( islist(users_to_open) && users_to_open.len) - var/users_to_open_string = users_to_open[1] - if(users_to_open.len >= 2) - for(var/i = 2 to users_to_open.len) - users_to_open_string += ", [users_to_open[i]]" - to_chat(user, "These people have opened \the [src] during an alert: [users_to_open_string].") - - -/obj/machinery/door/firedoor/Bumped(atom/AM) - if(panel_open || operating) - return - if(!density) - return ..() - if(istype(AM, /obj/mecha)) - var/obj/mecha/mecha = AM - if (mecha.occupant) - var/mob/M = mecha.occupant - if(world.time - M.last_bumped <= 10) return //Can bump-open one airlock per second. This is to prevent popup message spam. - M.last_bumped = world.time - attack_hand(M) - return 0 - - -/obj/machinery/door/firedoor/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER - latetoggle() - else - stat |= NOPOWER - return - -/obj/machinery/door/firedoor/attack_ai(mob/user) - if(isobserver(user) || user.stat) - return - spawn() - var/area/A = get_area_master(src) - ASSERT(istype(A)) // This worries me. - var/alarmed = A.doors_down || A.fire - var/old_density = src.density - if(old_density && alert("Override the [alarmed ? "alarming " : ""]firelock safeties and open \the [src]?",,"Yes","No") == "Yes") - open() - else if(!old_density) - close() - else - return - admin_diary << ("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") - message_admins("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") - -/obj/machinery/door/firedoor/attack_hand(mob/user as mob) - return attackby(null, user) - -/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob) - add_fingerprint(user) - if(operating) - return//Already doing something. - if(istype(C, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0, user)) - blocked = !blocked - user.visible_message("\The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\ - "You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\ - "You hear something being welded.") - update_icon() - return - - if( istype(C, /obj/item/weapon/crowbar) || ( istype(C,/obj/item/weapon/fireaxe) && C.wielded ) ) - force_open(user, C) - return - - if(blocked) - to_chat(user, "\The [src] is welded solid!") - return - - var/area/A = get_area_master(src) - ASSERT(istype(A)) // This worries me. - var/alarmed = A.doors_down || A.fire - - var/access_granted = 0 - var/users_name - if(!istype(C, /obj)) //If someone hit it with their hand. We need to see if they are allowed. - if(allowed(user)) - access_granted = 1 - if(ishuman(user)) - users_name = FindNameFromID(user) - else - users_name = "Unknown" - - if( ishuman(user) && !stat && ( istype(C, /obj/item/weapon/card/id) || istype(C, /obj/item/device/pda) ) ) - var/obj/item/weapon/card/id/ID = C - - if( istype(C, /obj/item/device/pda) ) - var/obj/item/device/pda/pda = C - ID = pda.id - if(!istype(ID)) - ID = null - - if(ID) - users_name = ID.registered_name - - if(check_access(ID)) - access_granted = 1 - - var/answer = "Yes" - if(answer == "No") - return - if(user.locked_to) - if(!istype(user.locked_to, /obj/structure/bed/chair/vehicle)) - to_chat(user, "Sorry, you must remain able bodied and close to \the [src] in order to use it.") - return - if(user.stat || user.stunned || user.weakened || user.paralysis || get_dist(src, user) > 1) - to_chat(user, "Sorry, you must remain able bodied and close to \the [src] in order to use it.") - return - - if(alarmed && density && lockdown && !access_granted/* && !( users_name in users_to_open ) */) - // Too many shitters on /vg/ for the honor system to work. - to_chat(user, "Access denied. Please wait for authorities to arrive, or for the alert to clear.") - return - // End anti-shitter system - /* - user.visible_message("\The [src] opens for \the [user]",\ - "\The [src] opens after you acknowledge the consequences.",\ - "You hear a beep, and a door opening.") - */ - else - user.visible_message("\The [src] [density ? "open" : "close"]s for \the [user].",\ - "\The [src] [density ? "open" : "close"]s.",\ - "You hear a beep, and a door opening.") - // Accountability! - if(!users_to_open) - users_to_open = list() - users_to_open += users_name - var/needs_to_close = 0 - if(density) - if(alarmed) - needs_to_close = 1 - spawn() - open() - else - spawn() - close() - admin_diary << ("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") - - if(needs_to_close) - spawn(50) - if(alarmed && !density) - close() -/obj/machinery/door/firedoor/open() - if(!loc || blocked) - return - ..() - latetoggle() - layer = base_layer - var/area/A = get_area_master(src) - ASSERT(istype(A)) // This worries me. - var/alarmed = A.doors_down || A.fire - if(alarmed) - spawn(50) - close() -/obj/machinery/door/firedoor/proc/force_open(mob/user, var/obj/C) //used in mecha/equipment/tools/tools.dm - var/area/A = get_area_master(src) - ASSERT(istype(A)) // This worries me. - var/alarmed = A.doors_down || A.fire - - if( blocked ) - user.visible_message("\The [istype(user.loc,/obj/mecha) ? "[user.loc.name]" : "[user]"] pries at \the [src] with \a [C], but \the [src] is welded in place!",\ - "You try to pry \the [src] [density ? "open" : "closed"], but it is welded in place!",\ - "You hear someone struggle and metal straining.") - return - - //thank you Tigercat2000 - user.visible_message("\The [istype(user.loc,/obj/mecha) ? "[user.loc.name]" : "[user]"] forces \the [src] [density ? "open" : "closed"] with \a [C]!",\ - "You force \the [src] [density ? "open" : "closed"] with \the [C]!",\ - "You hear metal strain, and a door [density ? "open" : "close"].") - - if(density) - spawn(0) - open() - else - spawn(0) - close() - admin_diary << ("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") - return - -/obj/machinery/door/firedoor/close() - if(blocked || !loc) - return - ..() - latetoggle() - layer = base_layer + FIREDOOR_CLOSED_MOD - -/obj/machinery/door/firedoor/door_animate(animation) - switch(animation) - if("opening") - flick("door_opening", src) - if("closing") - flick("door_closing", src) - return - - -/obj/machinery/door/firedoor/update_icon() - overlays.len = 0 - if(density) - icon_state = "door_closed" - if(blocked) - overlays += "welded" - if(pdiff_alert) - overlays += "palert" - if(dir_alerts) - for(var/d=1;d<=4;d++) - var/cdir = cardinal[d] - // Loop while i = [1, 3], incrementing each loop - for(var/i=1;i<=ALERT_STATES.len;i++) // - if(dir_alerts[d] & (1<<(i-1)))// Check to see if dir_alerts[d] has the i-1th bit set. +/var/const/OPEN = 1 +/var/const/CLOSED = 2 - var/list/state_list = alert_overlays_local["alert_[ALERT_STATES[i]]"] - if(flags & ON_BORDER) - overlays += turn(state_list["[turn(cdir, dir2angle(src.dir))]"], dir2angle(src.dir)) - else - overlays += state_list["[cdir]"] - else - icon_state = "door_open" - if(blocked) - overlays += "welded_open" - return - -// CHECK PRESSURE -/obj/machinery/door/firedoor/process() - ..() - - if(density) - var/changed = 0 - lockdown=0 - // Pressure alerts - pdiff = getOPressureDifferential(src.loc) - if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF) - lockdown = 1 - if(!pdiff_alert) - pdiff_alert = 1 - changed = 1 // update_icon() - else - if(pdiff_alert) - pdiff_alert = 0 - changed = 1 // update_icon() - - tile_info = getCardinalAirInfo(src,src.loc,list("temperature","pressure")) - var/old_alerts = dir_alerts - for(var/index = 1; index <= 4; index++) - var/list/tileinfo=tile_info[index] - if(tileinfo==null) - continue // Bad data. - var/celsius = convert_k2c(tileinfo[1]) - - var/alerts=0 - - // Temperatures - if(celsius >= FIREDOOR_MAX_TEMP) - alerts |= FIREDOOR_ALERT_HOT - lockdown = 1 - else if(celsius <= FIREDOOR_MIN_TEMP) - alerts |= FIREDOOR_ALERT_COLD - lockdown = 1 - - dir_alerts[index]=alerts - - if(dir_alerts != old_alerts) - changed = 1 - if(changed) - update_icon() - -/obj/machinery/door/firedoor/proc/latetoggle() - if(operating || stat & NOPOWER || !nextstate) - return - - switch(nextstate) - if(OPEN) - nextstate = null - open() - if(CLOSED) - nextstate = null - close() - -/obj/machinery/door/firedoor/border_only -//These are playing merry hell on ZAS. Sorry fellas :( -//Or they were, until you disable their inherent air-blocking - - icon = 'icons/obj/doors/edge_DoorHazard.dmi' - glass = 1 //There is a glass window so you can see through the door - //This is needed due to BYOND limitations in controlling visibility - heat_proof = 1 - air_properties_vary_with_direction = 1 - flags = ON_BORDER - -/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - - if(get_dir(loc, target) == dir) //Make sure looking at appropriate border - //if(air_group) return 0 - return !density - else - return 1 - -//used in the AStar algorithm to determinate if the turf the door is on is passable -/obj/machinery/door/firedoor/CanAStarPass() - return !density - - -/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target as turf) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) - return !density - else - return 1 - -/obj/machinery/door/firedoor/multi_tile - icon = 'icons/obj/doors/DoorHazard2x1.dmi' - width = 2 +var/global/list/alert_overlays_global = list() + +/proc/convert_k2c(var/temp) + return ((temp - T0C)) // * 1.8) + 32 + +/proc/convert_c2k(var/temp) + return ((temp + T0C)) // * 1.8) + 32 + +/proc/getCardinalAirInfo(var/atom/source, var/turf/loc, var/list/stats=list("temperature")) + var/list/temps = new/list(4) + for(var/dir in cardinal) + var/direction + switch(dir) + if(NORTH) + direction = 1 + if(SOUTH) + direction = 2 + if(EAST) + direction = 3 + if(WEST) + direction = 4 + + var/turf/simulated/T=get_turf(get_step(loc,dir)) + + if(dir == turn(source.dir, 180) && source.flags & ON_BORDER) //[ ][ |][ ] imagine the | is the source (with dir EAST -> facing right), and the brackets are floors. When we try to get the turf to the left's air info, use the middle's turf instead + if(!(locate(/obj/machinery/door/airlock) in get_turf(source))) //If we're on a door, however, DON'T DO THIS -> doors are airtight, so the result will be innacurate! This is a bad snowflake, but as long as it makes the feature freeze go away... + T = get_turf(source) + + var/list/rstats = new /list(stats.len) + if(T && istype(T) && T.zone) + var/datum/gas_mixture/environment = T.return_air() + for(var/i=1;i<=stats.len;i++) + rstats[i] = environment.vars[stats[i]] + else if(istype(T, /turf/simulated)) + rstats = null // Exclude zone (wall, door, etc). + else if(istype(T, /turf)) + // Should still work. (/turf/return_air()) + var/datum/gas_mixture/environment = T.return_air() + for(var/i=1;i<=stats.len;i++) + rstats[i] = environment.vars[stats[i]] + temps[direction] = rstats + return temps + +#define FIREDOOR_MAX_PRESSURE_DIFF 25 // kPa +#define FIREDOOR_MAX_TEMP 50 // �C +#define FIREDOOR_MIN_TEMP 0 + +// Bitflags +#define FIREDOOR_ALERT_HOT 1 +#define FIREDOOR_ALERT_COLD 2 +// Not used #define FIREDOOR_ALERT_LOWPRESS 4 + +#define FIREDOOR_CLOSED_MOD 0.8 + +/obj/machinery/door/firedoor + name = "\improper Emergency Shutter" + desc = "Emergency air-tight shutter, capable of sealing off breached areas." + icon = 'icons/obj/doors/DoorHazard.dmi' + icon_state = "door_open" + req_one_access = list(access_atmospherics, access_engine_equip) + opacity = 0 + density = 0 + layer = DOOR_LAYER - 0.2 + base_layer = DOOR_LAYER - 0.2 + + dir = 2 + + var/list/alert_overlays_local + + var/blocked = 0 + var/lockdown = 0 // When the door has detected a problem, it locks. + var/pdiff_alert = 0 + var/pdiff = 0 + var/nextstate = null + var/net_id + var/list/areas_added + var/list/users_to_open + var/list/tile_info[4] + var/list/dir_alerts[4] // 4 dirs, bitflags + + // MUST be in same order as FIREDOOR_ALERT_* + var/list/ALERT_STATES=list( + "hot", + "cold" + ) + +/obj/machinery/door/firedoor/New() + . = ..() + + if(!("[src.type]" in alert_overlays_global)) + alert_overlays_global += list("[src.type]" = list("alert_hot" = list(), + "alert_cold" = list()) + ) + + var/list/type_states = alert_overlays_global["[src.type]"] + + for(var/alert_state in type_states) + var/list/starting = list() + for(var/cdir in cardinal) + starting["[cdir]"] = icon(src.icon, alert_state, dir = cdir) + type_states[alert_state] = starting + alert_overlays_global["[src.type]"] = type_states + alert_overlays_local = type_states + else + alert_overlays_local = alert_overlays_global["[src.type]"] + + for(var/obj/machinery/door/firedoor/F in loc) + if(F != src) + if(F.flags & ON_BORDER && src.flags & ON_BORDER && F.dir != src.dir) //two border doors on the same tile don't collide + continue + spawn(1) + qdel(src) + return . + var/area/A = get_area(src) + ASSERT(istype(A)) + + A.all_doors.Add(src) + areas_added = list(A) + + for(var/direction in cardinal) + var/turf/T = get_step(src,direction) + if(istype(T,/turf/simulated/floor)) + A = get_area(get_step(src,direction)) + if(A) + A.all_doors |= src + areas_added |= A + + +/obj/machinery/door/firedoor/Destroy() + for(var/area/A in areas_added) + A.all_doors.Remove(src) + . = ..() + + +/obj/machinery/door/firedoor/examine(mob/user) + . = ..() + if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF) + to_chat(user, "WARNING: Current pressure differential is [pdiff]kPa! Opening door may result in injury!") + + to_chat(user, "Sensor readings:") + for(var/index = 1; index <= tile_info.len; index++) + var/o = "  " + switch(index) + if(1) + o += "NORTH: " + if(2) + o += "SOUTH: " + if(3) + o += "EAST: " + if(4) + o += "WEST: " + if(tile_info[index] == null) + o += "DATA UNAVAILABLE" + to_chat(usr, o) + continue + var/celsius = convert_k2c(tile_info[index][1]) + var/pressure = tile_info[index][2] + if(dir_alerts[index] & (FIREDOOR_ALERT_HOT|FIREDOOR_ALERT_COLD)) + o += "" + else + o += "" + o += "[celsius]�C " + o += "" + o += "[pressure]kPa" + to_chat(user, o) + + if( islist(users_to_open) && users_to_open.len) + var/users_to_open_string = users_to_open[1] + if(users_to_open.len >= 2) + for(var/i = 2 to users_to_open.len) + users_to_open_string += ", [users_to_open[i]]" + to_chat(user, "These people have opened \the [src] during an alert: [users_to_open_string].") + + +/obj/machinery/door/firedoor/Bumped(atom/AM) + if(panel_open || operating) + return + if(!density) + return ..() + if(istype(AM, /obj/mecha)) + var/obj/mecha/mecha = AM + if (mecha.occupant) + var/mob/M = mecha.occupant + if(world.time - M.last_bumped <= 10) return //Can bump-open one airlock per second. This is to prevent popup message spam. + M.last_bumped = world.time + attack_hand(M) + return 0 + + +/obj/machinery/door/firedoor/power_change() + if(powered(ENVIRON)) + stat &= ~NOPOWER + latetoggle() + else + stat |= NOPOWER + return + +/obj/machinery/door/firedoor/attack_ai(mob/user) + if(isobserver(user) || user.stat) + return + spawn() + var/area/A = get_area_master(src) + ASSERT(istype(A)) // This worries me. + var/alarmed = A.doors_down || A.fire + var/old_density = src.density + if(old_density && alert("Override the [alarmed ? "alarming " : ""]firelock safeties and open \the [src]?",,"Yes","No") == "Yes") + open() + else if(!old_density) + close() + else + return + admin_diary << ("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") + message_admins("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") + +/obj/machinery/door/firedoor/attack_hand(mob/user as mob) + return attackby(null, user) + +/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob) + add_fingerprint(user) + if(operating) + return//Already doing something. + if(istype(C, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0, user)) + blocked = !blocked + user.visible_message("\The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\ + "You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\ + "You hear something being welded.") + update_icon() + return + + if( istype(C, /obj/item/weapon/crowbar) || ( istype(C,/obj/item/weapon/fireaxe) && C.wielded ) ) + force_open(user, C) + return + + if(blocked) + to_chat(user, "\The [src] is welded solid!") + return + + var/area/A = get_area_master(src) + ASSERT(istype(A)) // This worries me. + var/alarmed = A.doors_down || A.fire + + var/access_granted = 0 + var/users_name + if(!istype(C, /obj)) //If someone hit it with their hand. We need to see if they are allowed. + if(allowed(user)) + access_granted = 1 + if(ishuman(user)) + users_name = FindNameFromID(user) + else + users_name = "Unknown" + + if( ishuman(user) && !stat && ( istype(C, /obj/item/weapon/card/id) || istype(C, /obj/item/device/pda) ) ) + var/obj/item/weapon/card/id/ID = C + + if( istype(C, /obj/item/device/pda) ) + var/obj/item/device/pda/pda = C + ID = pda.id + if(!istype(ID)) + ID = null + + if(ID) + users_name = ID.registered_name + + if(check_access(ID)) + access_granted = 1 + + var/answer = "Yes" + if(answer == "No") + return + if(user.locked_to) + if(!istype(user.locked_to, /obj/structure/bed/chair/vehicle)) + to_chat(user, "Sorry, you must remain able bodied and close to \the [src] in order to use it.") + return + if(user.stat || user.stunned || user.weakened || user.paralysis || get_dist(src, user) > 1) + to_chat(user, "Sorry, you must remain able bodied and close to \the [src] in order to use it.") + return + + if(alarmed && density && lockdown && !access_granted/* && !( users_name in users_to_open ) */) + // Too many shitters on /vg/ for the honor system to work. + to_chat(user, "Access denied. Please wait for authorities to arrive, or for the alert to clear.") + return + // End anti-shitter system + /* + user.visible_message("\The [src] opens for \the [user]",\ + "\The [src] opens after you acknowledge the consequences.",\ + "You hear a beep, and a door opening.") + */ + else + user.visible_message("\The [src] [density ? "open" : "close"]s for \the [user].",\ + "\The [src] [density ? "open" : "close"]s.",\ + "You hear a beep, and a door opening.") + // Accountability! + if(!users_to_open) + users_to_open = list() + users_to_open += users_name + var/needs_to_close = 0 + if(density) + if(alarmed) + needs_to_close = 1 + spawn() + open() + else + spawn() + close() + admin_diary << ("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") + + if(needs_to_close) + spawn(50) + if(alarmed && !density) + close() +/obj/machinery/door/firedoor/open() + if(!loc || blocked) + return + ..() + latetoggle() + layer = base_layer + var/area/A = get_area_master(src) + ASSERT(istype(A)) // This worries me. + var/alarmed = A.doors_down || A.fire + if(alarmed) + spawn(50) + close() +/obj/machinery/door/firedoor/proc/force_open(mob/user, var/obj/C) //used in mecha/equipment/tools/tools.dm + var/area/A = get_area_master(src) + ASSERT(istype(A)) // This worries me. + var/alarmed = A.doors_down || A.fire + + if( blocked ) + user.visible_message("\The [istype(user.loc,/obj/mecha) ? "[user.loc.name]" : "[user]"] pries at \the [src] with \a [C], but \the [src] is welded in place!",\ + "You try to pry \the [src] [density ? "open" : "closed"], but it is welded in place!",\ + "You hear someone struggle and metal straining.") + return + + //thank you Tigercat2000 + user.visible_message("\The [istype(user.loc,/obj/mecha) ? "[user.loc.name]" : "[user]"] forces \the [src] [density ? "open" : "closed"] with \a [C]!",\ + "You force \the [src] [density ? "open" : "closed"] with \the [C]!",\ + "You hear metal strain, and a door [density ? "open" : "close"].") + + if(density) + spawn(0) + open() + else + spawn(0) + close() + admin_diary << ("[user]/([user.ckey]) [density ? "closed the open" : "opened the closed"] [alarmed ? "and alarming" : ""] firelock at [formatJumpTo(get_turf(src))]") + return + +/obj/machinery/door/firedoor/close() + if(blocked || !loc) + return + ..() + latetoggle() + layer = base_layer + FIREDOOR_CLOSED_MOD + +/obj/machinery/door/firedoor/door_animate(animation) + switch(animation) + if("opening") + flick("door_opening", src) + if("closing") + flick("door_closing", src) + return + + +/obj/machinery/door/firedoor/update_icon() + overlays.len = 0 + if(density) + icon_state = "door_closed" + if(blocked) + overlays += "welded" + if(pdiff_alert) + overlays += "palert" + if(dir_alerts) + for(var/d=1;d<=4;d++) + var/cdir = cardinal[d] + // Loop while i = [1, 3], incrementing each loop + for(var/i=1;i<=ALERT_STATES.len;i++) // + if(dir_alerts[d] & (1<<(i-1)))// Check to see if dir_alerts[d] has the i-1th bit set. + + var/list/state_list = alert_overlays_local["alert_[ALERT_STATES[i]]"] + if(flags & ON_BORDER) + overlays += turn(state_list["[turn(cdir, dir2angle(src.dir))]"], dir2angle(src.dir)) + else + overlays += state_list["[cdir]"] + else + icon_state = "door_open" + if(blocked) + overlays += "welded_open" + return + +// CHECK PRESSURE +/obj/machinery/door/firedoor/process() + ..() + + if(density) + var/changed = 0 + lockdown=0 + // Pressure alerts + pdiff = getOPressureDifferential(src.loc) + if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF) + lockdown = 1 + if(!pdiff_alert) + pdiff_alert = 1 + changed = 1 // update_icon() + else + if(pdiff_alert) + pdiff_alert = 0 + changed = 1 // update_icon() + + tile_info = getCardinalAirInfo(src,src.loc,list("temperature","pressure")) + var/old_alerts = dir_alerts + for(var/index = 1; index <= 4; index++) + var/list/tileinfo=tile_info[index] + if(tileinfo==null) + continue // Bad data. + var/celsius = convert_k2c(tileinfo[1]) + + var/alerts=0 + + // Temperatures + if(celsius >= FIREDOOR_MAX_TEMP) + alerts |= FIREDOOR_ALERT_HOT + lockdown = 1 + else if(celsius <= FIREDOOR_MIN_TEMP) + alerts |= FIREDOOR_ALERT_COLD + lockdown = 1 + + dir_alerts[index]=alerts + + if(dir_alerts != old_alerts) + changed = 1 + if(changed) + update_icon() + +/obj/machinery/door/firedoor/proc/latetoggle() + if(operating || stat & NOPOWER || !nextstate) + return + + switch(nextstate) + if(OPEN) + nextstate = null + open() + if(CLOSED) + nextstate = null + close() + +/obj/machinery/door/firedoor/border_only +//These are playing merry hell on ZAS. Sorry fellas :( +//Or they were, until you disable their inherent air-blocking + + icon = 'icons/obj/doors/edge_DoorHazard.dmi' + glass = 1 //There is a glass window so you can see through the door + //This is needed due to BYOND limitations in controlling visibility + heat_proof = 1 + air_properties_vary_with_direction = 1 + flags = ON_BORDER + +/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + + if(get_dir(loc, target) == dir) //Make sure looking at appropriate border + //if(air_group) return 0 + return !density + else + return 1 + +//used in the AStar algorithm to determinate if the turf the door is on is passable +/obj/machinery/door/firedoor/CanAStarPass() + return !density + + +/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target as turf) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) + return !density + else + return 1 + +/obj/machinery/door/firedoor/multi_tile + icon = 'icons/obj/doors/DoorHazard2x1.dmi' + width = 2 diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index d7e705def24..acf55897f44 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -1,429 +1,429 @@ -var/list/poddoors = list() -/obj/machinery/door/poddoor - name = "Podlock" - desc = "Why it no open!!!" - icon = 'icons/obj/doors/rapid_pdoor.dmi' - icon_state = "pdoor1" - - explosion_resistance = 25//used by the old deprecated explosion_recursive.dm - - explosion_block = 3 - penetration_dampening = 20 - - var/id_tag = 1.0 - - prefix = "r_" - animation_delay = 18 - animation_delay_2 = 5 - -/obj/machinery/door/poddoor/preopen - icon_state = "pdoor0" - density = 0 - opacity = 0 - -/obj/machinery/door/poddoor/New() - . = ..() - if(density) - layer = 3.3 //to override door.New() proc - else - layer = initial(layer) - poddoors += src - return - -/obj/machinery/door/poddoor/Destroy() - poddoors -= src - ..() - -/obj/machinery/door/poddoor/Bumped(atom/AM) - if(!density) - return ..() - else - return 0 - -/obj/machinery/door/poddoor/attackby(obj/item/weapon/C as obj, mob/user as mob) - src.add_fingerprint(user) - if (!( istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/fireaxe) && C.wielded == 1) )) - return - if ((src.density && (stat & NOPOWER) && !( src.operating ))) - spawn( 0 ) - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - src.set_opacity(0) - sleep(15) - src.density = 0 - src.operating = 0 - return - return - -/obj/machinery/door/poddoor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - src.set_opacity(0) - sleep(10) - layer = initial(layer) - src.density = 0 - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/close() - if (src.operating) - return - src.operating = 1 - layer = 3.3 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - src.set_opacity(initial(opacity)) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/ex_act(severity)//Wouldn't it make sense for "Blast Doors" to actually handle explosions better than other doors? - switch(severity) - if(1.0) - if(prob(80)) - qdel(src) - else - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - if(2.0) - if(prob(20)) - qdel(src) - else - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - if(3.0) - if(prob(80)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - return - -/* -/obj/machinery/door/poddoor/two_tile_hor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - src.SetOpacity(0) - f1.SetOpacity(0) - f2.SetOpacity(0) - - sleep(10) - src.density = 0 - f1.density = 0 - f2.density = 0 - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/two_tile_hor/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - - src.density = 1 - f1.density = 1 - f2.density = 1 - - sleep(10) - src.SetOpacity(initial(opacity)) - f1.SetOpacity(initial(opacity)) - f2.SetOpacity(initial(opacity)) - - update_nearby_tiles() - - src.operating = 0 - return - -/obj/machinery/door/poddoor/four_tile_hor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - f3.density = 0 - f3.sd_SetOpacity(0) - f4.density = 0 - f4.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/four_tile_hor/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - f3.density = 1 - f3.sd_SetOpacity(1) - f4.density = 1 - f4.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/two_tile_ver/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/two_tile_ver/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/four_tile_ver/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - f3.density = 0 - f3.sd_SetOpacity(0) - f4.density = 0 - f4.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/four_tile_ver/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - f3.density = 1 - f3.sd_SetOpacity(1) - f4.density = 1 - f4.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - - - - -/obj/machinery/door/poddoor/two_tile_hor - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - icon = 'icons/obj/doors/1x2blast_hor.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,EAST)) - f1.density = density - f2.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - - Destroy() - del f1 - del f2 - ..() - -/obj/machinery/door/poddoor/two_tile_ver - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - icon = 'icons/obj/doors/1x2blast_vert.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,NORTH)) - f1.density = density - f2.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - - Destroy() - del f1 - del f2 - ..() - -/obj/machinery/door/poddoor/four_tile_hor - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - var/obj/machinery/door/poddoor/filler_object/f3 - var/obj/machinery/door/poddoor/filler_object/f4 - icon = 'icons/obj/doors/1x4blast_hor.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,EAST)) - f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,EAST)) - f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,EAST)) - f1.density = density - f2.density = density - f3.density = density - f4.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - f4.sd_SetOpacity(opacity) - f3.sd_SetOpacity(opacity) - - Destroy() - del f1 - del f2 - del f3 - del f4 - ..() - -/obj/machinery/door/poddoor/four_tile_ver - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - var/obj/machinery/door/poddoor/filler_object/f3 - var/obj/machinery/door/poddoor/filler_object/f4 - icon = 'icons/obj/doors/1x4blast_vert.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,NORTH)) - f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,NORTH)) - f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,NORTH)) - f1.density = density - f2.density = density - f3.density = density - f4.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - f4.sd_SetOpacity(opacity) - f3.sd_SetOpacity(opacity) - - Destroy() - del f1 - del f2 - del f3 - del f4 - ..() -*/ -/obj/machinery/door/poddoor/filler_object - name = "" +var/list/poddoors = list() +/obj/machinery/door/poddoor + name = "Podlock" + desc = "Why it no open!!!" + icon = 'icons/obj/doors/rapid_pdoor.dmi' + icon_state = "pdoor1" + + explosion_resistance = 25//used by the old deprecated explosion_recursive.dm + + explosion_block = 3 + penetration_dampening = 20 + + var/id_tag = 1.0 + + prefix = "r_" + animation_delay = 18 + animation_delay_2 = 5 + +/obj/machinery/door/poddoor/preopen + icon_state = "pdoor0" + density = 0 + opacity = 0 + +/obj/machinery/door/poddoor/New() + . = ..() + if(density) + layer = 3.3 //to override door.New() proc + else + layer = initial(layer) + poddoors += src + return + +/obj/machinery/door/poddoor/Destroy() + poddoors -= src + ..() + +/obj/machinery/door/poddoor/Bumped(atom/AM) + if(!density) + return ..() + else + return 0 + +/obj/machinery/door/poddoor/attackby(obj/item/weapon/C as obj, mob/user as mob) + src.add_fingerprint(user) + if (!( istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/fireaxe) && C.wielded == 1) )) + return + if ((src.density && (stat & NOPOWER) && !( src.operating ))) + spawn( 0 ) + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + src.set_opacity(0) + sleep(15) + src.density = 0 + src.operating = 0 + return + return + +/obj/machinery/door/poddoor/open() + if (src.operating == 1) //doors can still open when emag-disabled + return + if (!ticker) + return 0 + if(!src.operating) //in case of emag + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + src.set_opacity(0) + sleep(10) + layer = initial(layer) + src.density = 0 + update_nearby_tiles() + + if(operating == 1) //emag again + src.operating = 0 + if(autoclose) + spawn(150) + autoclose() + return 1 + +/obj/machinery/door/poddoor/close() + if (src.operating) + return + src.operating = 1 + layer = 3.3 + flick("pdoorc1", src) + src.icon_state = "pdoor1" + src.density = 1 + src.set_opacity(initial(opacity)) + update_nearby_tiles() + + sleep(10) + src.operating = 0 + return + +/obj/machinery/door/poddoor/ex_act(severity)//Wouldn't it make sense for "Blast Doors" to actually handle explosions better than other doors? + switch(severity) + if(1.0) + if(prob(80)) + qdel(src) + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + if(2.0) + if(prob(20)) + qdel(src) + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + if(3.0) + if(prob(80)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + return + +/* +/obj/machinery/door/poddoor/two_tile_hor/open() + if (src.operating == 1) //doors can still open when emag-disabled + return + if (!ticker) + return 0 + if(!src.operating) //in case of emag + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + src.SetOpacity(0) + f1.SetOpacity(0) + f2.SetOpacity(0) + + sleep(10) + src.density = 0 + f1.density = 0 + f2.density = 0 + + update_nearby_tiles() + + if(operating == 1) //emag again + src.operating = 0 + if(autoclose) + spawn(150) + autoclose() + return 1 + +/obj/machinery/door/poddoor/two_tile_hor/close() + if (src.operating) + return + src.operating = 1 + flick("pdoorc1", src) + src.icon_state = "pdoor1" + + src.density = 1 + f1.density = 1 + f2.density = 1 + + sleep(10) + src.SetOpacity(initial(opacity)) + f1.SetOpacity(initial(opacity)) + f2.SetOpacity(initial(opacity)) + + update_nearby_tiles() + + src.operating = 0 + return + +/obj/machinery/door/poddoor/four_tile_hor/open() + if (src.operating == 1) //doors can still open when emag-disabled + return + if (!ticker) + return 0 + if(!src.operating) //in case of emag + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + sleep(10) + src.density = 0 + src.sd_SetOpacity(0) + + f1.density = 0 + f1.sd_SetOpacity(0) + f2.density = 0 + f2.sd_SetOpacity(0) + f3.density = 0 + f3.sd_SetOpacity(0) + f4.density = 0 + f4.sd_SetOpacity(0) + + update_nearby_tiles() + + if(operating == 1) //emag again + src.operating = 0 + if(autoclose) + spawn(150) + autoclose() + return 1 + +/obj/machinery/door/poddoor/four_tile_hor/close() + if (src.operating) + return + src.operating = 1 + flick("pdoorc1", src) + src.icon_state = "pdoor1" + src.density = 1 + + f1.density = 1 + f1.sd_SetOpacity(1) + f2.density = 1 + f2.sd_SetOpacity(1) + f3.density = 1 + f3.sd_SetOpacity(1) + f4.density = 1 + f4.sd_SetOpacity(1) + + if (src.visible) + src.sd_SetOpacity(1) + update_nearby_tiles() + + sleep(10) + src.operating = 0 + return + +/obj/machinery/door/poddoor/two_tile_ver/open() + if (src.operating == 1) //doors can still open when emag-disabled + return + if (!ticker) + return 0 + if(!src.operating) //in case of emag + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + sleep(10) + src.density = 0 + src.sd_SetOpacity(0) + + f1.density = 0 + f1.sd_SetOpacity(0) + f2.density = 0 + f2.sd_SetOpacity(0) + + update_nearby_tiles() + + if(operating == 1) //emag again + src.operating = 0 + if(autoclose) + spawn(150) + autoclose() + return 1 + +/obj/machinery/door/poddoor/two_tile_ver/close() + if (src.operating) + return + src.operating = 1 + flick("pdoorc1", src) + src.icon_state = "pdoor1" + src.density = 1 + + f1.density = 1 + f1.sd_SetOpacity(1) + f2.density = 1 + f2.sd_SetOpacity(1) + + if (src.visible) + src.sd_SetOpacity(1) + update_nearby_tiles() + + sleep(10) + src.operating = 0 + return + +/obj/machinery/door/poddoor/four_tile_ver/open() + if (src.operating == 1) //doors can still open when emag-disabled + return + if (!ticker) + return 0 + if(!src.operating) //in case of emag + src.operating = 1 + flick("pdoorc0", src) + src.icon_state = "pdoor0" + sleep(10) + src.density = 0 + src.sd_SetOpacity(0) + + f1.density = 0 + f1.sd_SetOpacity(0) + f2.density = 0 + f2.sd_SetOpacity(0) + f3.density = 0 + f3.sd_SetOpacity(0) + f4.density = 0 + f4.sd_SetOpacity(0) + + update_nearby_tiles() + + if(operating == 1) //emag again + src.operating = 0 + if(autoclose) + spawn(150) + autoclose() + return 1 + +/obj/machinery/door/poddoor/four_tile_ver/close() + if (src.operating) + return + src.operating = 1 + flick("pdoorc1", src) + src.icon_state = "pdoor1" + src.density = 1 + + f1.density = 1 + f1.sd_SetOpacity(1) + f2.density = 1 + f2.sd_SetOpacity(1) + f3.density = 1 + f3.sd_SetOpacity(1) + f4.density = 1 + f4.sd_SetOpacity(1) + + if (src.visible) + src.sd_SetOpacity(1) + update_nearby_tiles() + + sleep(10) + src.operating = 0 + return + + + + +/obj/machinery/door/poddoor/two_tile_hor + var/obj/machinery/door/poddoor/filler_object/f1 + var/obj/machinery/door/poddoor/filler_object/f2 + icon = 'icons/obj/doors/1x2blast_hor.dmi' + + New() + ..() + f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) + f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,EAST)) + f1.density = density + f2.density = density + f1.sd_SetOpacity(opacity) + f2.sd_SetOpacity(opacity) + + Destroy() + del f1 + del f2 + ..() + +/obj/machinery/door/poddoor/two_tile_ver + var/obj/machinery/door/poddoor/filler_object/f1 + var/obj/machinery/door/poddoor/filler_object/f2 + icon = 'icons/obj/doors/1x2blast_vert.dmi' + + New() + ..() + f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) + f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,NORTH)) + f1.density = density + f2.density = density + f1.sd_SetOpacity(opacity) + f2.sd_SetOpacity(opacity) + + Destroy() + del f1 + del f2 + ..() + +/obj/machinery/door/poddoor/four_tile_hor + var/obj/machinery/door/poddoor/filler_object/f1 + var/obj/machinery/door/poddoor/filler_object/f2 + var/obj/machinery/door/poddoor/filler_object/f3 + var/obj/machinery/door/poddoor/filler_object/f4 + icon = 'icons/obj/doors/1x4blast_hor.dmi' + + New() + ..() + f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) + f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,EAST)) + f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,EAST)) + f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,EAST)) + f1.density = density + f2.density = density + f3.density = density + f4.density = density + f1.sd_SetOpacity(opacity) + f2.sd_SetOpacity(opacity) + f4.sd_SetOpacity(opacity) + f3.sd_SetOpacity(opacity) + + Destroy() + del f1 + del f2 + del f3 + del f4 + ..() + +/obj/machinery/door/poddoor/four_tile_ver + var/obj/machinery/door/poddoor/filler_object/f1 + var/obj/machinery/door/poddoor/filler_object/f2 + var/obj/machinery/door/poddoor/filler_object/f3 + var/obj/machinery/door/poddoor/filler_object/f4 + icon = 'icons/obj/doors/1x4blast_vert.dmi' + + New() + ..() + f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) + f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,NORTH)) + f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,NORTH)) + f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,NORTH)) + f1.density = density + f2.density = density + f3.density = density + f4.density = density + f1.sd_SetOpacity(opacity) + f2.sd_SetOpacity(opacity) + f4.sd_SetOpacity(opacity) + f3.sd_SetOpacity(opacity) + + Destroy() + del f1 + del f2 + del f3 + del f4 + ..() +*/ +/obj/machinery/door/poddoor/filler_object + name = "" icon_state = "" \ No newline at end of file diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 38b47033a75..12aec9dd69d 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -1,71 +1,71 @@ -/obj/machinery/door/poddoor/shutters - name = "Shutters" - icon = 'icons/obj/doors/rapid_pdoor.dmi' - icon_state = "shutter1" - power_channel = ENVIRON - var/sound_open = 'sound/machines/shutter_open.ogg' - var/sound_close = 'sound/machines/shutter_close.ogg' - -/obj/machinery/door/poddoor/shutters/New() - ..() - layer = 3.1 - -/obj/machinery/door/poddoor/shutters/preopen - icon_state = "shutter0" - density = 0 - opacity = 0 - -/obj/machinery/door/poddoor/shutters/attackby(obj/item/weapon/C as obj, mob/user as mob) - add_fingerprint(user) - if(!(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/fireaxe) && C.wielded == 1) )) - return - if(density && (stat & NOPOWER) && !operating) - operating = 1 - spawn(-1) - flick("shutterc0", src) - icon_state = "shutter0" - sleep(15) - density = 0 - set_opacity(0) - operating = 0 - return - return - -/obj/machinery/door/poddoor/shutters/open() - if(operating == 1) //doors can still open when emag-disabled - return - if(!ticker) - return 0 - if(!operating) //in case of emag - operating = 1 - flick("shutterc0", src) - icon_state = "shutter0" - playsound(src.loc, sound_open, 100, 1) - sleep(10) - density = 0 - set_opacity(0) - update_nearby_tiles() - - if(operating == 1) //emag again - operating = 0 - if(autoclose) - spawn(150) - autoclose() //TODO: note to self: look into this ~Carn - return 1 - -/obj/machinery/door/poddoor/shutters/close() - if(operating) - //if(welded) //these are not airlocks. - return - operating = 1 - flick("shutterc1", src) - icon_state = "shutter1" - playsound(src.loc, sound_close, 100, 1) - density = 1 - if(visible) - set_opacity(1) - update_nearby_tiles() - - sleep(10) - operating = 0 +/obj/machinery/door/poddoor/shutters + name = "Shutters" + icon = 'icons/obj/doors/rapid_pdoor.dmi' + icon_state = "shutter1" + power_channel = ENVIRON + var/sound_open = 'sound/machines/shutter_open.ogg' + var/sound_close = 'sound/machines/shutter_close.ogg' + +/obj/machinery/door/poddoor/shutters/New() + ..() + layer = 3.1 + +/obj/machinery/door/poddoor/shutters/preopen + icon_state = "shutter0" + density = 0 + opacity = 0 + +/obj/machinery/door/poddoor/shutters/attackby(obj/item/weapon/C as obj, mob/user as mob) + add_fingerprint(user) + if(!(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/fireaxe) && C.wielded == 1) )) + return + if(density && (stat & NOPOWER) && !operating) + operating = 1 + spawn(-1) + flick("shutterc0", src) + icon_state = "shutter0" + sleep(15) + density = 0 + set_opacity(0) + operating = 0 + return + return + +/obj/machinery/door/poddoor/shutters/open() + if(operating == 1) //doors can still open when emag-disabled + return + if(!ticker) + return 0 + if(!operating) //in case of emag + operating = 1 + flick("shutterc0", src) + icon_state = "shutter0" + playsound(src.loc, sound_open, 100, 1) + sleep(10) + density = 0 + set_opacity(0) + update_nearby_tiles() + + if(operating == 1) //emag again + operating = 0 + if(autoclose) + spawn(150) + autoclose() //TODO: note to self: look into this ~Carn + return 1 + +/obj/machinery/door/poddoor/shutters/close() + if(operating) + //if(welded) //these are not airlocks. + return + operating = 1 + flick("shutterc1", src) + icon_state = "shutter1" + playsound(src.loc, sound_close, 100, 1) + density = 1 + if(visible) + set_opacity(1) + update_nearby_tiles() + + sleep(10) + operating = 0 return \ No newline at end of file diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 8741d6e2abf..7e4e99af274 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -1,348 +1,348 @@ -/obj/machinery/door/window - name = "Window Door" - desc = "A sliding glass door." - icon = 'icons/obj/doors/windoor.dmi' - icon_state = "left" - var/base_state = "left" - var/health = 100 - visible = 0.0 - use_power = 0 - flags = ON_BORDER - opacity = 0 - var/obj/item/weapon/circuitboard/airlock/electronics = null - var/dismantled = 0 // To avoid playing the glass shatter sound on Destroy() - var/secure = 0 - explosion_resistance = 5 - air_properties_vary_with_direction = 1 - ghost_read=0 - machine_flags = EMAGGABLE - soundeffect = 'sound/machines/windowdoor.ogg' - var/shard = /obj/item/weapon/shard - penetration_dampening = 2 - -/obj/machinery/door/window/New() - ..() - if ((istype(src.req_access) && src.req_access.len) || istext(req_access)) - src.icon_state = "[src.icon_state]" - src.base_state = src.icon_state - return - -/obj/machinery/door/window/Destroy() - density = 0 - if (!dismantled) - playsound(src, "shatter", 70, 1) - ..() - -/obj/machinery/door/window/examine(mob/user as mob) - ..() - if(secure) +/obj/machinery/door/window + name = "Window Door" + desc = "A sliding glass door." + icon = 'icons/obj/doors/windoor.dmi' + icon_state = "left" + var/base_state = "left" + var/health = 100 + visible = 0.0 + use_power = 0 + flags = ON_BORDER + opacity = 0 + var/obj/item/weapon/circuitboard/airlock/electronics = null + var/dismantled = 0 // To avoid playing the glass shatter sound on Destroy() + var/secure = 0 + explosion_resistance = 5 + air_properties_vary_with_direction = 1 + ghost_read=0 + machine_flags = EMAGGABLE + soundeffect = 'sound/machines/windowdoor.ogg' + var/shard = /obj/item/weapon/shard + penetration_dampening = 2 + +/obj/machinery/door/window/New() + ..() + if ((istype(src.req_access) && src.req_access.len) || istext(req_access)) + src.icon_state = "[src.icon_state]" + src.base_state = src.icon_state + return + +/obj/machinery/door/window/Destroy() + density = 0 + if (!dismantled) + playsound(src, "shatter", 70, 1) + ..() + +/obj/machinery/door/window/examine(mob/user as mob) + ..() + if(secure) to_chat(user, "It is a secure windoor, it is stronger and closes more quickly.") - -/obj/machinery/door/window/Bumped(atom/movable/AM as mob|obj) - if (!ismob(AM)) - var/obj/machinery/bot/bot = AM - if(istype(bot)) - if(density && src.check_access(bot.botcard)) - open() - sleep(50) - close() - else if(istype(AM, /obj/mecha)) - var/obj/mecha/mecha = AM - if(density) - if(mecha.occupant && src.allowed(mecha.occupant)) - open() - sleep(50) - close() - return - if (!( ticker )) - return - if (src.operating) - return - if (src.density && src.allowed(AM)) - open() - // What. - if(src.check_access(null)) - sleep(50) - else //secure doors close faster - sleep(20) - close() - return - -/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) //Make sure looking at appropriate border - if(air_group) return 0 - return !density - else - return 1 - -//used in the AStar algorithm to determinate if the turf the door is on is passable -/obj/machinery/door/window/CanAStarPass(var/obj/item/weapon/card/id/ID, var/to_dir) - return !density || (dir != to_dir) || check_access(ID) - - -/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target as turf) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) - return !density - else - return 1 - -/obj/machinery/door/window/open() - if (src.operating == 1) //doors can still open when emag-disabled - return 0 - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick(text("[]opening", src.base_state), src) - playsound(get_turf(src), soundeffect, 100, 1) - src.icon_state = text("[]open", src.base_state) - sleep(10) - - explosion_resistance = 0 - src.density = 0 -// src.sd_SetOpacity(0) //TODO: why is this here? Opaque windoors? ~Carn - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - return 1 - -/obj/machinery/door/window/close() - if (src.operating) - return 0 - src.operating = 1 - flick(text("[]closing", src.base_state), src) - playsound(get_turf(src), soundeffect, 100, 1) - src.icon_state = src.base_state - - src.density = 1 - explosion_resistance = initial(explosion_resistance) -// if(src.visible) -// SetOpacity(1) //TODO: why is this here? Opaque windoors? ~Carn - update_nearby_tiles() - - sleep(10) - - src.operating = 0 - return 1 - -/obj/machinery/door/window/proc/take_damage(var/damage) - src.health = max(0, src.health - damage) - if (src.health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil,src.loc,2) - qdel(src) - return - -/obj/machinery/door/window/bullet_act(var/obj/item/projectile/Proj) - if(Proj.damage) - take_damage(round(Proj.damage / 2)) - ..() - -//When an object is thrown at the window -/obj/machinery/door/window/hitby(AM as mob|obj) - - ..() - visible_message("The glass door was hit by [AM].", 1) - var/tforce = 0 - if(ismob(AM)) - tforce = 40 - else - tforce = AM:throwforce - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1) - take_damage(tforce) - //..() //Does this really need to be here twice? The parent proc doesn't even do anything yet. - Nodrak - return - -/obj/machinery/door/window/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/door/window/attack_paw(mob/user as mob) - if(istype(user, /mob/living/carbon/alien/humanoid) || istype(user, /mob/living/carbon/slime/adult)) - if(src.operating) - return - user.delayNextAttack(8) - src.health = max(0, src.health - 25) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - visible_message("\The [user] smashes against \the [src.name].", 1) - if (src.health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil, loc, 2) - qdel(src) - else - return src.attack_hand(user) - - -/obj/machinery/door/window/attack_animal(mob/user as mob) - if(src.operating) - return - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) - return - user.delayNextAttack(8) - src.health = max(0, src.health - M.melee_damage_upper) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - visible_message("\The [M] [M.attacktext] against \the [src.name].", 1) - if (src.health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil, loc, 2) - qdel(src) - - -/obj/machinery/door/window/attack_hand(mob/user as mob) - return src.attackby(user, user) - -/obj/machinery/door/window/attackby(obj/item/weapon/I as obj, mob/user as mob) - // Make emagged/open doors able to be deconstructed - if (!src.density && src.operating != 1 && istype(I, /obj/item/weapon/crowbar)) - user.visible_message("[user] removes the electronics from the windoor assembly.", "You start to remove the electronics from the windoor assembly.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) - if (do_after(user, src, 40) && src && !src.density && src.operating != 1) + +/obj/machinery/door/window/Bumped(atom/movable/AM as mob|obj) + if (!ismob(AM)) + var/obj/machinery/bot/bot = AM + if(istype(bot)) + if(density && src.check_access(bot.botcard)) + open() + sleep(50) + close() + else if(istype(AM, /obj/mecha)) + var/obj/mecha/mecha = AM + if(density) + if(mecha.occupant && src.allowed(mecha.occupant)) + open() + sleep(50) + close() + return + if (!( ticker )) + return + if (src.operating) + return + if (src.density && src.allowed(AM)) + open() + // What. + if(src.check_access(null)) + sleep(50) + else //secure doors close faster + sleep(20) + close() + return + +/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) //Make sure looking at appropriate border + if(air_group) return 0 + return !density + else + return 1 + +//used in the AStar algorithm to determinate if the turf the door is on is passable +/obj/machinery/door/window/CanAStarPass(var/obj/item/weapon/card/id/ID, var/to_dir) + return !density || (dir != to_dir) || check_access(ID) + + +/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target as turf) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) + return !density + else + return 1 + +/obj/machinery/door/window/open() + if (src.operating == 1) //doors can still open when emag-disabled + return 0 + if (!ticker) + return 0 + if(!src.operating) //in case of emag + src.operating = 1 + flick(text("[]opening", src.base_state), src) + playsound(get_turf(src), soundeffect, 100, 1) + src.icon_state = text("[]open", src.base_state) + sleep(10) + + explosion_resistance = 0 + src.density = 0 +// src.sd_SetOpacity(0) //TODO: why is this here? Opaque windoors? ~Carn + update_nearby_tiles() + + if(operating == 1) //emag again + src.operating = 0 + return 1 + +/obj/machinery/door/window/close() + if (src.operating) + return 0 + src.operating = 1 + flick(text("[]closing", src.base_state), src) + playsound(get_turf(src), soundeffect, 100, 1) + src.icon_state = src.base_state + + src.density = 1 + explosion_resistance = initial(explosion_resistance) +// if(src.visible) +// SetOpacity(1) //TODO: why is this here? Opaque windoors? ~Carn + update_nearby_tiles() + + sleep(10) + + src.operating = 0 + return 1 + +/obj/machinery/door/window/proc/take_damage(var/damage) + src.health = max(0, src.health - damage) + if (src.health <= 0) + getFromPool(shard, loc) + getFromPool(/obj/item/stack/cable_coil,src.loc,2) + qdel(src) + return + +/obj/machinery/door/window/bullet_act(var/obj/item/projectile/Proj) + if(Proj.damage) + take_damage(round(Proj.damage / 2)) + ..() + +//When an object is thrown at the window +/obj/machinery/door/window/hitby(AM as mob|obj) + + ..() + visible_message("The glass door was hit by [AM].", 1) + var/tforce = 0 + if(ismob(AM)) + tforce = 40 + else + tforce = AM:throwforce + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1) + take_damage(tforce) + //..() //Does this really need to be here twice? The parent proc doesn't even do anything yet. - Nodrak + return + +/obj/machinery/door/window/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/door/window/attack_paw(mob/user as mob) + if(istype(user, /mob/living/carbon/alien/humanoid) || istype(user, /mob/living/carbon/slime/adult)) + if(src.operating) + return + user.delayNextAttack(8) + src.health = max(0, src.health - 25) + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + visible_message("\The [user] smashes against \the [src.name].", 1) + if (src.health <= 0) + getFromPool(shard, loc) + getFromPool(/obj/item/stack/cable_coil, loc, 2) + qdel(src) + else + return src.attack_hand(user) + + +/obj/machinery/door/window/attack_animal(mob/user as mob) + if(src.operating) + return + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) + return + user.delayNextAttack(8) + src.health = max(0, src.health - M.melee_damage_upper) + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + visible_message("\The [M] [M.attacktext] against \the [src.name].", 1) + if (src.health <= 0) + getFromPool(shard, loc) + getFromPool(/obj/item/stack/cable_coil, loc, 2) + qdel(src) + + +/obj/machinery/door/window/attack_hand(mob/user as mob) + return src.attackby(user, user) + +/obj/machinery/door/window/attackby(obj/item/weapon/I as obj, mob/user as mob) + // Make emagged/open doors able to be deconstructed + if (!src.density && src.operating != 1 && istype(I, /obj/item/weapon/crowbar)) + user.visible_message("[user] removes the electronics from the windoor assembly.", "You start to remove the electronics from the windoor assembly.") + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + if (do_after(user, src, 40) && src && !src.density && src.operating != 1) to_chat(user, "You removed the windoor electronics!") - make_assembly(user) - src.dismantled = 1 // Don't play the glass shatter sound - qdel(src) - return - - //If it's in the process of opening/closing or emagged, ignore the click - if (src.operating) - return - - //If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway) - if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card)) - var/aforce = I.force - user.delayNextAttack(8) - if(I.damtype == BRUTE || I.damtype == BURN) - src.health = max(0, src.health - aforce) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - visible_message("[src] was hit by [I].") - if (src.health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil, src.loc, 2) - qdel(src) - return - - src.add_fingerprint(user) - if (!src.requiresID()) - //don't care who they are or what they have, act as if they're NOTHING - user = null - - if (isrobot(user)) - if (src.density) - return open() - else - return close() - - if (!src.allowed(user) && src.density) - flick(text("[]deny", src.base_state), src) - - return ..() - -/obj/machinery/door/window/emag(mob/user) - var used_emag = (/obj/item/weapon/card/emag in user.contents) //TODO: Find a better way of checking this - return hackOpen(used_emag, user) - -/obj/machinery/door/window/proc/hackOpen(obj/item/I, mob/user) - src.operating = -1 - - if (src.electronics) - src.electronics.icon_state = "door_electronics_smoked" - - flick("[src.base_state]spark", src) - sleep(6) - open() - return 1 - -/** - * Returns whether the door opens to the left. This is counter-clockwise - * w.r.t. the tile it is on. - */ -/obj/machinery/door/window/proc/is_left_opening() - return src.base_state == "left" || src.base_state == "leftsecure" - -/** - * Deconstructs a windoor properly. You probably want to delete - * the windoor after calling this. - * @return The new /obj/structure/windoor_assembly created. - */ -/obj/machinery/door/window/proc/make_assembly(mob/user as mob) - // Windoor assembly - var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc) - set_assembly(user, WA) - return WA - -/obj/machinery/door/window/proc/set_assembly(mob/user as mob, var/obj/structure/windoor_assembly/WA) - WA.name = "Near finished Windoor Assembly" - WA.dir = src.dir - WA.anchored = 1 - WA.facing = (is_left_opening() ? "l" : "r") - WA.secure = "" - WA.state = "02" - WA.update_icon() - - WA.fingerprints += src.fingerprints - WA.fingerprintshidden += src.fingerprints - WA.fingerprintslast = user.ckey - - // Pop out electronics - var/obj/item/weapon/circuitboard/airlock/AE = (src.electronics ? src.electronics : new /obj/item/weapon/circuitboard/airlock(src.loc)) - if (src.electronics) - src.electronics = null - AE.loc = src.loc - else - // Straight from /obj/machinery/door/airlock/attackby() - if (src.req_access && src.req_access.len > 0) - AE.conf_access = src.req_access - else if (src.req_one_access && src.req_one_access.len > 0) - AE.conf_access = src.req_one_access - AE.one_access = 1 - -/obj/machinery/door/window/brigdoor - name = "Secure Window Door" - icon = 'icons/obj/doors/windoor.dmi' - icon_state = "leftsecure" - base_state = "leftsecure" - req_access = list(access_security) - secure = 1 - var/id_tag = null - health = 200 - penetration_dampening = 4 - -/obj/machinery/door/window/brigdoor/make_assembly(mob/user as mob) - var/obj/structure/windoor_assembly/WA = ..(user) - WA.secure = "secure_" - WA.update_icon() - return WA - -/obj/machinery/door/window/plasma - name = "Plasma Window Door" - desc = "A sliding glass door strengthened by plasma." - icon = 'icons/obj/doors/plasmawindoor.dmi' - health = 300 - shard = /obj/item/weapon/shard/plasma - penetration_dampening = 6 - -/obj/machinery/door/window/plasma/make_assembly(mob/user as mob) - // Windoor assembly - var/obj/structure/windoor_assembly/plasma/WA = new /obj/structure/windoor_assembly/plasma(src.loc) - set_assembly(user, WA) - return WA - -/obj/machinery/door/window/plasma/secure - name = "Secure Plasma Window Door" - icon_state = "leftsecure" - base_state = "leftsecure" - health = 400 - secure = 1 - penetration_dampening = 8 - -/obj/machinery/door/window/plasma/secure/make_assembly(mob/user as mob) - var/obj/structure/windoor_assembly/plasma/WA = ..(user) - WA.secure = "secure_" - WA.update_icon() - return WA + make_assembly(user) + src.dismantled = 1 // Don't play the glass shatter sound + qdel(src) + return + + //If it's in the process of opening/closing or emagged, ignore the click + if (src.operating) + return + + //If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway) + if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card)) + var/aforce = I.force + user.delayNextAttack(8) + if(I.damtype == BRUTE || I.damtype == BURN) + src.health = max(0, src.health - aforce) + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + visible_message("[src] was hit by [I].") + if (src.health <= 0) + getFromPool(shard, loc) + getFromPool(/obj/item/stack/cable_coil, src.loc, 2) + qdel(src) + return + + src.add_fingerprint(user) + if (!src.requiresID()) + //don't care who they are or what they have, act as if they're NOTHING + user = null + + if (isrobot(user)) + if (src.density) + return open() + else + return close() + + if (!src.allowed(user) && src.density) + flick(text("[]deny", src.base_state), src) + + return ..() + +/obj/machinery/door/window/emag(mob/user) + var used_emag = (/obj/item/weapon/card/emag in user.contents) //TODO: Find a better way of checking this + return hackOpen(used_emag, user) + +/obj/machinery/door/window/proc/hackOpen(obj/item/I, mob/user) + src.operating = -1 + + if (src.electronics) + src.electronics.icon_state = "door_electronics_smoked" + + flick("[src.base_state]spark", src) + sleep(6) + open() + return 1 + +/** + * Returns whether the door opens to the left. This is counter-clockwise + * w.r.t. the tile it is on. + */ +/obj/machinery/door/window/proc/is_left_opening() + return src.base_state == "left" || src.base_state == "leftsecure" + +/** + * Deconstructs a windoor properly. You probably want to delete + * the windoor after calling this. + * @return The new /obj/structure/windoor_assembly created. + */ +/obj/machinery/door/window/proc/make_assembly(mob/user as mob) + // Windoor assembly + var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc) + set_assembly(user, WA) + return WA + +/obj/machinery/door/window/proc/set_assembly(mob/user as mob, var/obj/structure/windoor_assembly/WA) + WA.name = "Near finished Windoor Assembly" + WA.dir = src.dir + WA.anchored = 1 + WA.facing = (is_left_opening() ? "l" : "r") + WA.secure = "" + WA.state = "02" + WA.update_icon() + + WA.fingerprints += src.fingerprints + WA.fingerprintshidden += src.fingerprints + WA.fingerprintslast = user.ckey + + // Pop out electronics + var/obj/item/weapon/circuitboard/airlock/AE = (src.electronics ? src.electronics : new /obj/item/weapon/circuitboard/airlock(src.loc)) + if (src.electronics) + src.electronics = null + AE.loc = src.loc + else + // Straight from /obj/machinery/door/airlock/attackby() + if (src.req_access && src.req_access.len > 0) + AE.conf_access = src.req_access + else if (src.req_one_access && src.req_one_access.len > 0) + AE.conf_access = src.req_one_access + AE.one_access = 1 + +/obj/machinery/door/window/brigdoor + name = "Secure Window Door" + icon = 'icons/obj/doors/windoor.dmi' + icon_state = "leftsecure" + base_state = "leftsecure" + req_access = list(access_security) + secure = 1 + var/id_tag = null + health = 200 + penetration_dampening = 4 + +/obj/machinery/door/window/brigdoor/make_assembly(mob/user as mob) + var/obj/structure/windoor_assembly/WA = ..(user) + WA.secure = "secure_" + WA.update_icon() + return WA + +/obj/machinery/door/window/plasma + name = "Plasma Window Door" + desc = "A sliding glass door strengthened by plasma." + icon = 'icons/obj/doors/plasmawindoor.dmi' + health = 300 + shard = /obj/item/weapon/shard/plasma + penetration_dampening = 6 + +/obj/machinery/door/window/plasma/make_assembly(mob/user as mob) + // Windoor assembly + var/obj/structure/windoor_assembly/plasma/WA = new /obj/structure/windoor_assembly/plasma(src.loc) + set_assembly(user, WA) + return WA + +/obj/machinery/door/window/plasma/secure + name = "Secure Plasma Window Door" + icon_state = "leftsecure" + base_state = "leftsecure" + health = 400 + secure = 1 + penetration_dampening = 8 + +/obj/machinery/door/window/plasma/secure/make_assembly(mob/user as mob) + var/obj/structure/windoor_assembly/plasma/WA = ..(user) + WA.secure = "secure_" + WA.update_icon() + return WA diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 452b252dbf3..58ba05d387f 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -1,149 +1,149 @@ -var/list/doppler_arrays = list() - -/obj/machinery/computer/bhangmeter - name = "bhangmeter" - desc = "Ancient technology used to measure explosions of all shapes and sizes. Has been recently outfitted by meteor monitoring software by Space Weather Inc." - icon = 'icons/obj/computer.dmi' - icon_state = "forensic" - circuit = "/obj/item/weapon/circuitboard/bhangmeter" - var/list/bangs = list() - -/obj/machinery/computer/bhangmeter/New() - ..() - doppler_arrays += src - -/obj/machinery/computer/bhangmeter/Destroy() - doppler_arrays -= src - ..() - -/obj/machinery/computer/bhangmeter/process() - return PROCESS_KILL - -/obj/machinery/computer/bhangmeter/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/bhangmeter/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/bhangmeter/attack_hand(mob/user as mob) - //user.set_machine(src) - ui_interact(user) - -/obj/machinery/computer/bhangmeter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - if(stat & (BROKEN|NOPOWER)) - return - - var/list/data[0] - var/list/explosions = list() - for(var/list/bangarangs in bangs) //Removing sortAtom because nano updates it just enough for the lag to happen - var/list/bang_data = list() - bang_data["x"] = bangarangs["x"] - bang_data["y"] = bangarangs["y"] - bang_data["z"] = bangarangs["z"] - bang_data["area"] = bangarangs["area"] - bang_data["time"] = bangarangs["time"] - bang_data["cap"] = bangarangs["cap"] - bang_data["dev"] = bangarangs["dev"] - bang_data["heavy"] = bangarangs["heavy"] - bang_data["light"] = bangarangs["light"] - bang_data["took"] = bangarangs["took"] - bang_data["xoffset"] = bang_data["x"]-WORLD_X_OFFSET[z] - bang_data["yoffset"] = bang_data["y"]-WORLD_Y_OFFSET[z] - explosions += list(bang_data) - data["explosions"] = explosions - data["explosion_cap"] = MAX_EXPLOSION_RANGE - - if(!ui) //No ui has been passed, so we'll search for one - ui = nanomanager.get_open_ui(user, src, ui_key) - - if(!ui) - //The ui does not exist, so we'll create a new one - ui = new(user, src, ui_key, "bhangmeter.tmpl", name, 900, 800) - //Adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "bhangmeter_map_content.tmpl") - //Adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "bhangmeter_map_header.tmpl") - //When the UI is first opened this is the data it will use - //We want to show the map by default - ui.set_show_map(1) - - ui.set_initial_data(data) - - ui.open() - //Auto update every Master Controller tick - ui.set_auto_update(1) - else - //The UI is already open so push the new data to it - ui.push_data(data) - return - -/obj/machinery/computer/bhangmeter/interact(mob/user as mob) - var/listing = {" - - - Nanotrasen Bhangmeter Mk. V - - -

      Recent Explosions

      - - - - - - -"} - for(var/item in bangs) - listing += item - listing += {" -
      GridPowerTemporal Displacement
      - -"} - user << browse(listing, "window=bhangmeter") - onclose(user, "bhangmeter") - return -/obj/machinery/computer/bhangmeter/proc/sense_explosion(var/x0, var/y0, var/z0, var/devastation_range, var/heavy_impact_range, var/light_impact_range, var/took, cap = 0, var/verbose = 1) - if(stat & NOPOWER) - return - if(z != z0) - return - - /* - var/dx = abs(x0-x) - var/dy = abs(y0-y) - var/distance - var/direct - - if(dx > dy) - distance = dx - if(x0 > x) direct = EAST - else direct = WEST - else - distance = dy - if(y0 > y) direct = NORTH - else direct = SOUTH - - if(distance > 100) return - if(!(direct & dir)) return - */ - - var/message = "Explosive disturbance detected - Epicenter at: grid ([x0-WORLD_X_OFFSET[z0]],[y0-WORLD_Y_OFFSET[z0]], [z0]). [cap ? "\[Theoretical Results\] " : ""]Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range]. Temporal displacement of tachyons: [took] second\s. Data logged." - if(verbose) - say(message) - //var/list/bang = params2list("x=[x0]&y=[y0]&z=[z0]&text=([worldtime2text()]) - ([x0-WORLD_X_OFFSET(z0)],[y0-WORLD_Y_OFFSET(z0)], [z0])([cap ? "\[Theoretical Results\] " : ""][devastation_range],[heavy_impact_range],[light_impact_range])[took]s") - var/list/bang = list() - bang["x"] = x0 - bang["y"] = y0 - bang["z"] = z0 - bang["time"] = worldtime2text() - bang["cap"] = cap - bang["dev"] = devastation_range - bang["heavy"] = heavy_impact_range - bang["light"] = light_impact_range - bang["took"] = took - bang["area"] = get_area(locate(x0,y0,z0)) - bangs += list(bang) - nanomanager.update_uis(src) - -/obj/machinery/doppler_array/say_quote(text) - return "coldly states, [text]" +var/list/doppler_arrays = list() + +/obj/machinery/computer/bhangmeter + name = "bhangmeter" + desc = "Ancient technology used to measure explosions of all shapes and sizes. Has been recently outfitted by meteor monitoring software by Space Weather Inc." + icon = 'icons/obj/computer.dmi' + icon_state = "forensic" + circuit = "/obj/item/weapon/circuitboard/bhangmeter" + var/list/bangs = list() + +/obj/machinery/computer/bhangmeter/New() + ..() + doppler_arrays += src + +/obj/machinery/computer/bhangmeter/Destroy() + doppler_arrays -= src + ..() + +/obj/machinery/computer/bhangmeter/process() + return PROCESS_KILL + +/obj/machinery/computer/bhangmeter/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/bhangmeter/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/bhangmeter/attack_hand(mob/user as mob) + //user.set_machine(src) + ui_interact(user) + +/obj/machinery/computer/bhangmeter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + if(stat & (BROKEN|NOPOWER)) + return + + var/list/data[0] + var/list/explosions = list() + for(var/list/bangarangs in bangs) //Removing sortAtom because nano updates it just enough for the lag to happen + var/list/bang_data = list() + bang_data["x"] = bangarangs["x"] + bang_data["y"] = bangarangs["y"] + bang_data["z"] = bangarangs["z"] + bang_data["area"] = bangarangs["area"] + bang_data["time"] = bangarangs["time"] + bang_data["cap"] = bangarangs["cap"] + bang_data["dev"] = bangarangs["dev"] + bang_data["heavy"] = bangarangs["heavy"] + bang_data["light"] = bangarangs["light"] + bang_data["took"] = bangarangs["took"] + bang_data["xoffset"] = bang_data["x"]-WORLD_X_OFFSET[z] + bang_data["yoffset"] = bang_data["y"]-WORLD_Y_OFFSET[z] + explosions += list(bang_data) + data["explosions"] = explosions + data["explosion_cap"] = MAX_EXPLOSION_RANGE + + if(!ui) //No ui has been passed, so we'll search for one + ui = nanomanager.get_open_ui(user, src, ui_key) + + if(!ui) + //The ui does not exist, so we'll create a new one + ui = new(user, src, ui_key, "bhangmeter.tmpl", name, 900, 800) + //Adding a template with the key "mapContent" enables the map ui functionality + ui.add_template("mapContent", "bhangmeter_map_content.tmpl") + //Adding a template with the key "mapHeader" replaces the map header content + ui.add_template("mapHeader", "bhangmeter_map_header.tmpl") + //When the UI is first opened this is the data it will use + //We want to show the map by default + ui.set_show_map(1) + + ui.set_initial_data(data) + + ui.open() + //Auto update every Master Controller tick + ui.set_auto_update(1) + else + //The UI is already open so push the new data to it + ui.push_data(data) + return + +/obj/machinery/computer/bhangmeter/interact(mob/user as mob) + var/listing = {" + + + Nanotrasen Bhangmeter Mk. V + + +

      Recent Explosions

      + + + + + + +"} + for(var/item in bangs) + listing += item + listing += {" +
      GridPowerTemporal Displacement
      + +"} + user << browse(listing, "window=bhangmeter") + onclose(user, "bhangmeter") + return +/obj/machinery/computer/bhangmeter/proc/sense_explosion(var/x0, var/y0, var/z0, var/devastation_range, var/heavy_impact_range, var/light_impact_range, var/took, cap = 0, var/verbose = 1) + if(stat & NOPOWER) + return + if(z != z0) + return + + /* + var/dx = abs(x0-x) + var/dy = abs(y0-y) + var/distance + var/direct + + if(dx > dy) + distance = dx + if(x0 > x) direct = EAST + else direct = WEST + else + distance = dy + if(y0 > y) direct = NORTH + else direct = SOUTH + + if(distance > 100) return + if(!(direct & dir)) return + */ + + var/message = "Explosive disturbance detected - Epicenter at: grid ([x0-WORLD_X_OFFSET[z0]],[y0-WORLD_Y_OFFSET[z0]], [z0]). [cap ? "\[Theoretical Results\] " : ""]Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range]. Temporal displacement of tachyons: [took] second\s. Data logged." + if(verbose) + say(message) + //var/list/bang = params2list("x=[x0]&y=[y0]&z=[z0]&text=([worldtime2text()]) - ([x0-WORLD_X_OFFSET(z0)],[y0-WORLD_Y_OFFSET(z0)], [z0])([cap ? "\[Theoretical Results\] " : ""][devastation_range],[heavy_impact_range],[light_impact_range])[took]s") + var/list/bang = list() + bang["x"] = x0 + bang["y"] = y0 + bang["z"] = z0 + bang["time"] = worldtime2text() + bang["cap"] = cap + bang["dev"] = devastation_range + bang["heavy"] = heavy_impact_range + bang["light"] = light_impact_range + bang["took"] = took + bang["area"] = get_area(locate(x0,y0,z0)) + bangs += list(bang) + nanomanager.update_uis(src) + +/obj/machinery/doppler_array/say_quote(text) + return "coldly states, [text]" diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index da087d25e50..4f181d14782 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -1,299 +1,299 @@ -/obj/machinery/embedded_controller - var/datum/computer/file/embedded_program/program - - name = "Embedded Controller" - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_control_build0" - anchored = 1 - - var/on = 1 - - var/build=2 // Build state - var/boardtype=null // /obj/item/weapon/circuitboard/ecb - var/obj/item/weapon/circuitboard/_circuitboard - machine_flags = MULTITOOL_MENU -/obj/machinery/embedded_controller/New(turf/loc, var/ndir, var/building=0) - ..() - - // offset 24 pixels in direction of dir - // this allows the APC to be embedded in a wall, yet still inside an area - if (building) - dir = ndir - - //src.tdir = dir // to fix Vars bug - //dir = SOUTH - - pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) - pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 - - build=0 - stat |= MAINT - src.update_icon() - -/obj/machinery/embedded_controller/attackby(var/obj/item/W as obj, var/mob/user as mob) - . = ..() - if(.) - return . - if(type==/obj/machinery/embedded_controller) - switch(build) - if(0) // Empty hull - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(usr, "You begin removing screws from \the [src] backplate...") - if(do_after(user, src, 50)) - to_chat(usr, "You unscrew \the [src] from the wall.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - new /obj/item/mounted/frame/airlock_controller(get_turf(src)) - qdel(src) - return 1 - if(istype(W, /obj/item/weapon/circuitboard)) - var/obj/item/weapon/circuitboard/C=W - if(C.board_type!="embedded controller") - to_chat(user, "You cannot install this type of board into an embedded controller.") - return - to_chat(usr, "You begin to insert \the [C] into \the [src].") - if(do_after(user, src, 10)) - if(user.drop_item(C, src)) - to_chat(usr, "You secure \the [C]!") - _circuitboard=C - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) - build++ - update_icon() - return 1 - if(1) // Circuitboard installed - if(istype(W, /obj/item/weapon/crowbar)) - to_chat(usr, "You begin to pry out \the [W] into \the [src].") - if(do_after(user, src, 10)) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) - build-- - update_icon() - var/obj/item/weapon/circuitboard/C - if(_circuitboard) - _circuitboard.loc=get_turf(src) - C=_circuitboard - _circuitboard=null - else - C=new boardtype(get_turf(src)) - user.visible_message(\ - "[user.name] has removed \the [C]!",\ - "You remove \the [C].") - return 1 - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C=W - to_chat(user, "You start adding cables to \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20) && C.amount >= 10) - C.use(5) - build++ - update_icon() - user.visible_message(\ - "[user.name] has added cables to \the [src]!",\ - "You add cables to \the [src].") - if(2) // Circuitboard installed, wired. - if(istype(W, /obj/item/weapon/wirecutters)) - to_chat(usr, "You begin to remove the wiring from \the [src].") - if(do_after(user, src, 50)) - new /obj/item/stack/cable_coil(loc,5) - user.visible_message(\ - "[user.name] cut the cables.",\ - "You cut the cables.") - build-- - update_icon() - return 1 - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(user, "You begin to complete \the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 20)) - if(!_circuitboard) - _circuitboard=new boardtype(src) - var/obj/machinery/embedded_controller/EC=new _circuitboard.build_path(get_turf(src)) - EC.dir=dir - EC.pixel_x=pixel_x - EC.pixel_y=pixel_y - user.visible_message(\ - "[user.name] has finished \the [src]!",\ - "You finish \the [src].") - qdel(src) - return 1 - if(build<2) - return ..() - -/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) - return 0 - -/obj/machinery/embedded_controller/receive_signal(datum/signal/signal, receive_method, receive_param) - if(!signal || signal.encryption) return - - if(program) - program.receive_signal(signal, receive_method, receive_param) - //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0 - -/obj/machinery/embedded_controller/process() - if(program) - program.process() - - update_icon() - src.updateDialog() - - -/obj/machinery/embedded_controller/attack_ai(mob/user as mob) - if(build<2) return 1 - src.ui_interact(user) - -/obj/machinery/embedded_controller/attack_paw(mob/user as mob) - attack_hand(user) - return - -/obj/machinery/embedded_controller/attack_hand(mob/user as mob) - if(!user.dexterity_check()) - to_chat(user, "You do not have the dexterity to use this.") - return - if(build<2) return 1 - src.ui_interact(user) - -/obj/machinery/embedded_controller/ui_interact() - return - -/obj/machinery/embedded_controller/radio - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_control_standby" - power_channel = ENVIRON - density = 0 - - // Setup parameters only - var/id_tag - var/tag_exterior_door - var/tag_interior_door - var/tag_airpump - var/tag_chamber_sensor - var/tag_exterior_sensor - var/tag_interior_sensor - var/tag_secure = 0 - - var/frequency = 1449 //seems to be the frequency used for all the controllers on /vg/ so why not make it default - var/datum/radio_frequency/radio_connection - unacidable = 1 - -/obj/machinery/embedded_controller/radio/initialize() - set_frequency(frequency) - var/datum/computer/file/embedded_program/new_prog = new - - new_prog.id_tag = id_tag - new_prog.tag_exterior_door = tag_exterior_door - new_prog.tag_interior_door = tag_interior_door - new_prog.tag_airpump = tag_airpump - new_prog.tag_chamber_sensor = tag_chamber_sensor - new_prog.tag_exterior_sensor = tag_exterior_sensor - new_prog.tag_interior_sensor = tag_interior_sensor - new_prog.memory["secure"] = tag_secure - - new_prog.master = src - program = new_prog - - spawn(10) - program.signalDoor(tag_exterior_door, "update") //signals connected doors to update their status - program.signalDoor(tag_interior_door, "update") - -/obj/machinery/embedded_controller/radio/update_icon() - if(on && program) - if(program.memory["processing"]) - icon_state = "airlock_control_process" - else - icon_state = "airlock_control_standby" - else - icon_state = "airlock_control_off" - -/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal) - signal.transmission_method = TRANSMISSION_RADIO - if(radio_connection) - return radio_connection.post_signal(src, signal) - else - qdel(signal) - signal = null - -/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency) - -/obj/machinery/embedded_controller/radio/handle_multitool_topic(var/href, var/list/href_list, var/mob/user)//need to add an override here because this shit is stupidly hardcoded and I don't want to have to revise this code, atleast not right now - var/obj/item/device/multitool/P = get_multitool(usr) - if(P && istype(P)) - var/update_mt_menu=0 - var/re_init=0 - if("set_tag" in href_list) - if(!(href_list["set_tag"] in vars)) - to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!") - return 1 - var/current_tag = src.vars[href_list["set_tag"]] - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src, current_tag) as null|text),1,MAX_MESSAGE_LEN) - if(newid) - vars[href_list["set_tag"]] = newid - re_init=1 - - if("unlink" in href_list) - var/idx = text2num(href_list["unlink"]) - if (!idx) - return 1 - - var/obj/O = getLink(idx) - if(!O) - return 1 - if(!canLink(O)) - to_chat(usr, "You can't link with that device.") - return 1 - - if(unlinkFrom(usr, O)) - to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.") - else - to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.") - update_mt_menu=1 - - if("link" in href_list) - var/obj/O = P.buffer - if(!O) - return 1 - if(!canLink(O,href_list)) - to_chat(usr, "You can't link with that device.") - return 1 - if (isLinkedWith(O)) - to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.") - return 1 - - if(linkWith(usr, O, href_list)) - to_chat(usr, "A green light flashes on \the [P], confirming the link has been created.") - re_init = 1//this is the only thing different, crappy, I know - else - to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.") - update_mt_menu=1 - - if("buffer" in href_list) - if(istype(src, /obj/machinery/telecomms)) - if(!hasvar(src, "id")) - to_chat(usr, "A red light flashes and nothing changes.") - return - else if(!hasvar(src, "id_tag")) - to_chat(usr, "A red light flashes and nothing changes.") - return - P.buffer = src - to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.") - update_mt_menu=1 - - if("flush" in href_list) - to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.") - P.buffer = null - update_mt_menu=1 - - var/ret = multitool_topic(usr,href_list,P.buffer) - if(ret == MT_ERROR) - return 1 - if(ret & MT_UPDATE) - update_mt_menu=1 - if(ret & MT_REINIT) - re_init=1 - - if(re_init) - initialize() - if(update_mt_menu) - //usr.set_machine(src) - update_multitool_menu(usr) - return 1 +/obj/machinery/embedded_controller + var/datum/computer/file/embedded_program/program + + name = "Embedded Controller" + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_control_build0" + anchored = 1 + + var/on = 1 + + var/build=2 // Build state + var/boardtype=null // /obj/item/weapon/circuitboard/ecb + var/obj/item/weapon/circuitboard/_circuitboard + machine_flags = MULTITOOL_MENU +/obj/machinery/embedded_controller/New(turf/loc, var/ndir, var/building=0) + ..() + + // offset 24 pixels in direction of dir + // this allows the APC to be embedded in a wall, yet still inside an area + if (building) + dir = ndir + + //src.tdir = dir // to fix Vars bug + //dir = SOUTH + + pixel_x = (dir & 3)? 0 : (dir == 4 ? 24 : -24) + pixel_y = (dir & 3)? (dir ==1 ? 24 : -24) : 0 + + build=0 + stat |= MAINT + src.update_icon() + +/obj/machinery/embedded_controller/attackby(var/obj/item/W as obj, var/mob/user as mob) + . = ..() + if(.) + return . + if(type==/obj/machinery/embedded_controller) + switch(build) + if(0) // Empty hull + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(usr, "You begin removing screws from \the [src] backplate...") + if(do_after(user, src, 50)) + to_chat(usr, "You unscrew \the [src] from the wall.") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + new /obj/item/mounted/frame/airlock_controller(get_turf(src)) + qdel(src) + return 1 + if(istype(W, /obj/item/weapon/circuitboard)) + var/obj/item/weapon/circuitboard/C=W + if(C.board_type!="embedded controller") + to_chat(user, "You cannot install this type of board into an embedded controller.") + return + to_chat(usr, "You begin to insert \the [C] into \the [src].") + if(do_after(user, src, 10)) + if(user.drop_item(C, src)) + to_chat(usr, "You secure \the [C]!") + _circuitboard=C + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + build++ + update_icon() + return 1 + if(1) // Circuitboard installed + if(istype(W, /obj/item/weapon/crowbar)) + to_chat(usr, "You begin to pry out \the [W] into \the [src].") + if(do_after(user, src, 10)) + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + build-- + update_icon() + var/obj/item/weapon/circuitboard/C + if(_circuitboard) + _circuitboard.loc=get_turf(src) + C=_circuitboard + _circuitboard=null + else + C=new boardtype(get_turf(src)) + user.visible_message(\ + "[user.name] has removed \the [C]!",\ + "You remove \the [C].") + return 1 + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C=W + to_chat(user, "You start adding cables to \the [src]...") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20) && C.amount >= 10) + C.use(5) + build++ + update_icon() + user.visible_message(\ + "[user.name] has added cables to \the [src]!",\ + "You add cables to \the [src].") + if(2) // Circuitboard installed, wired. + if(istype(W, /obj/item/weapon/wirecutters)) + to_chat(usr, "You begin to remove the wiring from \the [src].") + if(do_after(user, src, 50)) + new /obj/item/stack/cable_coil(loc,5) + user.visible_message(\ + "[user.name] cut the cables.",\ + "You cut the cables.") + build-- + update_icon() + return 1 + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(user, "You begin to complete \the [src]...") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 20)) + if(!_circuitboard) + _circuitboard=new boardtype(src) + var/obj/machinery/embedded_controller/EC=new _circuitboard.build_path(get_turf(src)) + EC.dir=dir + EC.pixel_x=pixel_x + EC.pixel_y=pixel_y + user.visible_message(\ + "[user.name] has finished \the [src]!",\ + "You finish \the [src].") + qdel(src) + return 1 + if(build<2) + return ..() + +/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) + return 0 + +/obj/machinery/embedded_controller/receive_signal(datum/signal/signal, receive_method, receive_param) + if(!signal || signal.encryption) return + + if(program) + program.receive_signal(signal, receive_method, receive_param) + //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0 + +/obj/machinery/embedded_controller/process() + if(program) + program.process() + + update_icon() + src.updateDialog() + + +/obj/machinery/embedded_controller/attack_ai(mob/user as mob) + if(build<2) return 1 + src.ui_interact(user) + +/obj/machinery/embedded_controller/attack_paw(mob/user as mob) + attack_hand(user) + return + +/obj/machinery/embedded_controller/attack_hand(mob/user as mob) + if(!user.dexterity_check()) + to_chat(user, "You do not have the dexterity to use this.") + return + if(build<2) return 1 + src.ui_interact(user) + +/obj/machinery/embedded_controller/ui_interact() + return + +/obj/machinery/embedded_controller/radio + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_control_standby" + power_channel = ENVIRON + density = 0 + + // Setup parameters only + var/id_tag + var/tag_exterior_door + var/tag_interior_door + var/tag_airpump + var/tag_chamber_sensor + var/tag_exterior_sensor + var/tag_interior_sensor + var/tag_secure = 0 + + var/frequency = 1449 //seems to be the frequency used for all the controllers on /vg/ so why not make it default + var/datum/radio_frequency/radio_connection + unacidable = 1 + +/obj/machinery/embedded_controller/radio/initialize() + set_frequency(frequency) + var/datum/computer/file/embedded_program/new_prog = new + + new_prog.id_tag = id_tag + new_prog.tag_exterior_door = tag_exterior_door + new_prog.tag_interior_door = tag_interior_door + new_prog.tag_airpump = tag_airpump + new_prog.tag_chamber_sensor = tag_chamber_sensor + new_prog.tag_exterior_sensor = tag_exterior_sensor + new_prog.tag_interior_sensor = tag_interior_sensor + new_prog.memory["secure"] = tag_secure + + new_prog.master = src + program = new_prog + + spawn(10) + program.signalDoor(tag_exterior_door, "update") //signals connected doors to update their status + program.signalDoor(tag_interior_door, "update") + +/obj/machinery/embedded_controller/radio/update_icon() + if(on && program) + if(program.memory["processing"]) + icon_state = "airlock_control_process" + else + icon_state = "airlock_control_standby" + else + icon_state = "airlock_control_off" + +/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal) + signal.transmission_method = TRANSMISSION_RADIO + if(radio_connection) + return radio_connection.post_signal(src, signal) + else + qdel(signal) + signal = null + +/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency) + +/obj/machinery/embedded_controller/radio/handle_multitool_topic(var/href, var/list/href_list, var/mob/user)//need to add an override here because this shit is stupidly hardcoded and I don't want to have to revise this code, atleast not right now + var/obj/item/device/multitool/P = get_multitool(usr) + if(P && istype(P)) + var/update_mt_menu=0 + var/re_init=0 + if("set_tag" in href_list) + if(!(href_list["set_tag"] in vars)) + to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!") + return 1 + var/current_tag = src.vars[href_list["set_tag"]] + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src, current_tag) as null|text),1,MAX_MESSAGE_LEN) + if(newid) + vars[href_list["set_tag"]] = newid + re_init=1 + + if("unlink" in href_list) + var/idx = text2num(href_list["unlink"]) + if (!idx) + return 1 + + var/obj/O = getLink(idx) + if(!O) + return 1 + if(!canLink(O)) + to_chat(usr, "You can't link with that device.") + return 1 + + if(unlinkFrom(usr, O)) + to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.") + else + to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.") + update_mt_menu=1 + + if("link" in href_list) + var/obj/O = P.buffer + if(!O) + return 1 + if(!canLink(O,href_list)) + to_chat(usr, "You can't link with that device.") + return 1 + if (isLinkedWith(O)) + to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.") + return 1 + + if(linkWith(usr, O, href_list)) + to_chat(usr, "A green light flashes on \the [P], confirming the link has been created.") + re_init = 1//this is the only thing different, crappy, I know + else + to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.") + update_mt_menu=1 + + if("buffer" in href_list) + if(istype(src, /obj/machinery/telecomms)) + if(!hasvar(src, "id")) + to_chat(usr, "A red light flashes and nothing changes.") + return + else if(!hasvar(src, "id_tag")) + to_chat(usr, "A red light flashes and nothing changes.") + return + P.buffer = src + to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.") + update_mt_menu=1 + + if("flush" in href_list) + to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.") + P.buffer = null + update_mt_menu=1 + + var/ret = multitool_topic(usr,href_list,P.buffer) + if(ret == MT_ERROR) + return 1 + if(ret & MT_UPDATE) + update_mt_menu=1 + if(ret & MT_REINIT) + re_init=1 + + if(re_init) + initialize() + if(update_mt_menu) + //usr.set_machine(src) + update_multitool_menu(usr) + return 1 diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 9ef6702acf1..06cc24e4eb6 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -1,173 +1,173 @@ -// It is a gizmo that flashes a small area -var/list/obj/machinery/flasher/flashers = list() - -/obj/machinery/flasher - name = "Mounted flash" - desc = "A wall-mounted flashbulb device." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mflash1" - var/id_tag = null - var/range = 2 //this is roughly the size of brig cell - var/disable = 0 - var/last_flash = 0 //Don't want it getting spammed like regular flashes - var/strength = 10 //How weakened targets are when flashed. - var/base_state = "mflash" - anchored = 1 - ghost_read=0 - ghost_write=0 - min_harm_label = 15 //Seems low, but this is going by the sprite. May need to be changed for balance. - harm_label_examine = list("A label is on the bulb, but doesn't cover it.", "A label covers the bulb!") - - flags = FPRINT | PROXMOVE - -/obj/machinery/flasher/New() - ..() - flashers += src - -/obj/machinery/flasher/Destroy() - ..() - flashers -= src - -/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored - name = "portable flasher" - desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements." - icon_state = "pflash1" - strength = 8 - anchored = 0 - base_state = "pflash" - density = 1 - min_harm_label = 35 //A lot. Has to wrap around the bulb, after all. - -/* -/obj/machinery/flasher/New() - sleep(4) //<--- What the fuck are you doing? D= - src.sd_SetLuminosity(2) -*/ -/obj/machinery/flasher/power_change() - if ( powered() ) - stat &= ~NOPOWER - icon_state = "[base_state]1" -// src.sd_SetLuminosity(2) - else - stat |= ~NOPOWER - icon_state = "[base_state]1-p" -// src.sd_SetLuminosity(0) - -//Don't want to render prison breaks impossible -/obj/machinery/flasher/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/wirecutters)) - add_fingerprint(user) - src.disable = !src.disable - if (src.disable) - user.visible_message("[user] has disconnected the [src]'s flashbulb!", "You disconnect the [src]'s flashbulb!") - if (!src.disable) - user.visible_message("[user] has connected the [src]'s flashbulb!", "You connect the [src]'s flashbulb!") - -//Let the AI trigger them directly. -/obj/machinery/flasher/attack_ai() - if (src.anchored) - return src.flash() - else - return - -/obj/machinery/flasher/proc/flash() - if (!(powered())) - return - - if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) - return - - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) - src.last_flash = world.time - use_power(1000) - if(harm_labeled >= min_harm_label) return //Still "flashes," so power is used and the noise is made, etc., but it doesn't actually flash anyone. - flick("[base_state]_flash", src) - - for (var/mob/O in viewers(src, null)) - if(isobserver(O)) continue - if (get_dist(src, O) > src.range) - continue - - if (istype(O, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = O - if(!H.eyecheck() <= 0) - continue - - if (istype(O, /mob/living/carbon/alien))//So aliens don't get flashed (they have no external eyes)/N - continue - - O.Weaken(strength) - if (istype(O, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = O - var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if (E && (E.damage > E.min_bruised_damage && prob(E.damage + 50))) - flick("e_flash", O:flash) - E.damage += rand(1, 5) - else - if(!O.blinded) - flick("flash", O:flash) - - -/obj/machinery/flasher/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - if(prob(75/severity)) - flash() - ..(severity) - -/obj/machinery/flasher/portable/HasProximity(atom/movable/AM as mob|obj) - if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) - return - - if(istype(AM, /mob/living/carbon)) - var/mob/living/carbon/M = AM - if ((M.m_intent != "walk") && (src.anchored)) - src.flash() - -/obj/machinery/flasher/portable/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/wrench)) - add_fingerprint(user) - src.anchored = !src.anchored - - if (!src.anchored) - user.show_message(text("[src] can now be moved.")) - src.overlays.len = 0 - - else if (src.anchored) - user.show_message(text("[src] is now secured.")) - src.overlays += "[base_state]-s" - -/obj/machinery/flasher_button/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/flasher_button/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/flasher_button/attackby(obj/item/weapon/W, mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/flasher_button/attack_hand(mob/user as mob) - - if(stat & (NOPOWER|BROKEN)) - return - if(active) - return - - use_power(5) - - active = 1 - icon_state = "launcheract" - - for(var/obj/machinery/flasher/M in flashers) - if(M.id_tag == src.id_tag) - spawn() - M.flash() - - sleep(50) - - icon_state = "launcherbtt" - active = 0 - +// It is a gizmo that flashes a small area +var/list/obj/machinery/flasher/flashers = list() + +/obj/machinery/flasher + name = "Mounted flash" + desc = "A wall-mounted flashbulb device." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mflash1" + var/id_tag = null + var/range = 2 //this is roughly the size of brig cell + var/disable = 0 + var/last_flash = 0 //Don't want it getting spammed like regular flashes + var/strength = 10 //How weakened targets are when flashed. + var/base_state = "mflash" + anchored = 1 + ghost_read=0 + ghost_write=0 + min_harm_label = 15 //Seems low, but this is going by the sprite. May need to be changed for balance. + harm_label_examine = list("A label is on the bulb, but doesn't cover it.", "A label covers the bulb!") + + flags = FPRINT | PROXMOVE + +/obj/machinery/flasher/New() + ..() + flashers += src + +/obj/machinery/flasher/Destroy() + ..() + flashers -= src + +/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored + name = "portable flasher" + desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements." + icon_state = "pflash1" + strength = 8 + anchored = 0 + base_state = "pflash" + density = 1 + min_harm_label = 35 //A lot. Has to wrap around the bulb, after all. + +/* +/obj/machinery/flasher/New() + sleep(4) //<--- What the fuck are you doing? D= + src.sd_SetLuminosity(2) +*/ +/obj/machinery/flasher/power_change() + if ( powered() ) + stat &= ~NOPOWER + icon_state = "[base_state]1" +// src.sd_SetLuminosity(2) + else + stat |= ~NOPOWER + icon_state = "[base_state]1-p" +// src.sd_SetLuminosity(0) + +//Don't want to render prison breaks impossible +/obj/machinery/flasher/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/wirecutters)) + add_fingerprint(user) + src.disable = !src.disable + if (src.disable) + user.visible_message("[user] has disconnected the [src]'s flashbulb!", "You disconnect the [src]'s flashbulb!") + if (!src.disable) + user.visible_message("[user] has connected the [src]'s flashbulb!", "You connect the [src]'s flashbulb!") + +//Let the AI trigger them directly. +/obj/machinery/flasher/attack_ai() + if (src.anchored) + return src.flash() + else + return + +/obj/machinery/flasher/proc/flash() + if (!(powered())) + return + + if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) + return + + playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) + src.last_flash = world.time + use_power(1000) + if(harm_labeled >= min_harm_label) return //Still "flashes," so power is used and the noise is made, etc., but it doesn't actually flash anyone. + flick("[base_state]_flash", src) + + for (var/mob/O in viewers(src, null)) + if(isobserver(O)) continue + if (get_dist(src, O) > src.range) + continue + + if (istype(O, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = O + if(!H.eyecheck() <= 0) + continue + + if (istype(O, /mob/living/carbon/alien))//So aliens don't get flashed (they have no external eyes)/N + continue + + O.Weaken(strength) + if (istype(O, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = O + var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] + if (E && (E.damage > E.min_bruised_damage && prob(E.damage + 50))) + flick("e_flash", O:flash) + E.damage += rand(1, 5) + else + if(!O.blinded) + flick("flash", O:flash) + + +/obj/machinery/flasher/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + if(prob(75/severity)) + flash() + ..(severity) + +/obj/machinery/flasher/portable/HasProximity(atom/movable/AM as mob|obj) + if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) + return + + if(istype(AM, /mob/living/carbon)) + var/mob/living/carbon/M = AM + if ((M.m_intent != "walk") && (src.anchored)) + src.flash() + +/obj/machinery/flasher/portable/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/wrench)) + add_fingerprint(user) + src.anchored = !src.anchored + + if (!src.anchored) + user.show_message(text("[src] can now be moved.")) + src.overlays.len = 0 + + else if (src.anchored) + user.show_message(text("[src] is now secured.")) + src.overlays += "[base_state]-s" + +/obj/machinery/flasher_button/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/flasher_button/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/flasher_button/attackby(obj/item/weapon/W, mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/flasher_button/attack_hand(mob/user as mob) + + if(stat & (NOPOWER|BROKEN)) + return + if(active) + return + + use_power(5) + + active = 1 + icon_state = "launcheract" + + for(var/obj/machinery/flasher/M in flashers) + if(M.id_tag == src.id_tag) + spawn() + M.flash() + + sleep(50) + + icon_state = "launcherbtt" + active = 0 + return \ No newline at end of file diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index bf75fd7acbb..cc1e88131ff 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -1,210 +1,210 @@ -/* Holograms! - * Contains: - * Holopad - * Hologram - * Other stuff - */ - -/* -Revised. Original based on space ninja hologram code. Which is also mine. /N -How it works: -AI clicks on holopad in camera view. View centers on holopad. -AI clicks again on the holopad to display a hologram. Hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad. -AI can use the directional keys to move the hologram around, provided the above conditions are met and the AI in question is the holopad's master. -Only one AI may project from a holopad at any given time. -AI may cancel the hologram at any time by clicking on the holopad once more. - -Possible to do for anyone motivated enough: - Give an AI variable for different hologram icons. - Itegrate EMP effect to disable the unit. -*/ - - -/* - * Holopad - */ - -// HOLOPAD MODE -// 0 = RANGE BASED -// 1 = AREA BASED -var/const/HOLOPAD_MODE = 0 - -/obj/machinery/hologram/holopad - name = "\improper AI holopad" - desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely." - icon_state = "holopad0" - 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. - flags = HEAR - -/obj/machinery/hologram/holopad/attack_hand(var/mob/living/carbon/human/user) //Carn: Hologram requests. - if(!istype(user)) - return - if(alert(user,"Would you like to request an AI's presence?",,"Yes","No") == "Yes") - if(last_request + 200 < world.time) //don't spam the AI with requests you jerk! - last_request = world.time - to_chat(user, "You request an AI's presence.") - var/area/area = get_area(src) - for(var/mob/living/silicon/ai/AI in living_mob_list) - if(!AI.client) continue - to_chat(AI, "Your presence is requested at \the [area].") - else - to_chat(user, "A request for AI presence was already sent recently.") - -/obj/machinery/hologram/holopad/attack_ai(mob/living/silicon/ai/user) - if (!istype(user)) - return - /*There are pretty much only three ways to interact here. - I don't need to check for client since they're clicking on an object. - This may change in the future but for now will suffice.*/ - if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already. - user.eyeobj.forceMove(get_turf(src)) - else if(!hologram)//If there is no hologram, possibly make one. - activate_holo(user) - else if(master==user)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing. - clear_holo() - return - -/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/silicon/ai/user) - if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it. - if(!hologram)//If there is not already a hologram. - create_holo(user)//Create one. - src.visible_message("A holographic image of [user] flicks to life right before your eyes!") - else - to_chat(user, "ERROR: Image feed in progress.") - else - to_chat(user, "ERROR: Unable to project hologram.") - return - -/*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(var/datum/speech/speech, var/rendered_message="") - if(speech.speaker && hologram && master && !speech.frequency && speech.speaker != master)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. - if(!master.say_understands(speech.speaker, speech.language)) //previously if(!master.languages & speaker.languages)//The AI will be able to understand most mobs talking through the holopad. - rendered_message = speech.render_message() - var/name_used = speech.name - rendered_message = "Holopad received, [name_used] [rendered_message]" - master.show_message(rendered_message, 2) - - -/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc) - hologram = new(T)//Spawn a blank effect at the location. - hologram.icon = A.holo_icon - hologram.mouse_opacity = 0//So you can't click on it. - hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. - hologram.anchored = 1//So space wind cannot drag it. - hologram.name = "[A.name] (Hologram)"//If someone decides to right click. - hologram.set_light(2) //hologram lighting - set_light(2) //pad lighting - icon_state = "holopad1" - A.current = src - master = A//AI is the master. - use_power = 2//Active power usage. - return 1 - -/obj/machinery/hologram/holopad/proc/clear_holo() -// hologram.SetLuminosity(0)//Clear lighting. //handled by the lighting controller when its ower is deleted - qdel(hologram)//Get rid of hologram. - hologram = null - if(master.current == src) - master.current = null - master = null//Null the master, since no-one is using it now. - set_light(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted) - icon_state = "holopad0" - use_power = 1//Passive power usage. - return 1 - -/obj/machinery/hologram/holopad/process() - if(hologram)//If there is a hologram. - if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector. - if(!(stat & NOPOWER))//If the machine has power. - if((HOLOPAD_MODE == 0 && (get_dist(master.eyeobj, src) <= holo_range))) - return 1 - - else if (HOLOPAD_MODE == 1) - - var/area/holo_area = get_area(src) - var/area/eye_area = get_area(master.eyeobj) - - if(eye_area == holo_area) - return 1 - - clear_holo()//If not, we want to get rid of the hologram. - return 1 - -/obj/machinery/hologram/holopad/proc/move_hologram() - if(hologram) - step_to(hologram, master.eyeobj) // So it turns. - hologram.loc = get_turf(master.eyeobj) - - return 1 - -/* - * Hologram - */ - -/obj/machinery/hologram - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise. - -/obj/machinery/hologram/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= ~NOPOWER - -//Destruction procs. -/obj/machinery/hologram/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - if (prob(50)) - qdel(src) - if(3.0) - if (prob(5)) - qdel(src) - return - -/obj/machinery/hologram/blob_act() - qdel(src) - return - -/obj/machinery/hologram/Destroy() - if(hologram) - src:clear_holo() - ..() - -/* -Holographic project of everything else. - -/mob/verb/hologram_test() - set name = "Hologram Debug New" - set category = "CURRENT DEBUG" - - var/obj/effect/overlay/hologram = new(loc)//Spawn a blank effect at the location. - var/icon/flat_icon = icon(getFlatIcon(src,0))//Need to make sure it's a new icon so the old one is not reused. - flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish. - flat_icon.ChangeOpacity(0.5)//Make it half transparent. - var/input = input("Select what icon state to use in effect.",,"") - if(input) - var/icon/alpha_mask = new('icons/effects/effects.dmi', "[input]") - flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect. - hologram.icon = flat_icon - - to_chat(world, "Your icon should appear now.") - return -*/ - -/* - * Other Stuff: Is this even used? - */ -/obj/machinery/hologram/projector - name = "hologram projector" - desc = "It makes a hologram appear...with magnets or something..." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "hologram0" +/* Holograms! + * Contains: + * Holopad + * Hologram + * Other stuff + */ + +/* +Revised. Original based on space ninja hologram code. Which is also mine. /N +How it works: +AI clicks on holopad in camera view. View centers on holopad. +AI clicks again on the holopad to display a hologram. Hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad. +AI can use the directional keys to move the hologram around, provided the above conditions are met and the AI in question is the holopad's master. +Only one AI may project from a holopad at any given time. +AI may cancel the hologram at any time by clicking on the holopad once more. + +Possible to do for anyone motivated enough: + Give an AI variable for different hologram icons. + Itegrate EMP effect to disable the unit. +*/ + + +/* + * Holopad + */ + +// HOLOPAD MODE +// 0 = RANGE BASED +// 1 = AREA BASED +var/const/HOLOPAD_MODE = 0 + +/obj/machinery/hologram/holopad + name = "\improper AI holopad" + desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely." + icon_state = "holopad0" + 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. + flags = HEAR + +/obj/machinery/hologram/holopad/attack_hand(var/mob/living/carbon/human/user) //Carn: Hologram requests. + if(!istype(user)) + return + if(alert(user,"Would you like to request an AI's presence?",,"Yes","No") == "Yes") + if(last_request + 200 < world.time) //don't spam the AI with requests you jerk! + last_request = world.time + to_chat(user, "You request an AI's presence.") + var/area/area = get_area(src) + for(var/mob/living/silicon/ai/AI in living_mob_list) + if(!AI.client) continue + to_chat(AI, "Your presence is requested at \the [area].") + else + to_chat(user, "A request for AI presence was already sent recently.") + +/obj/machinery/hologram/holopad/attack_ai(mob/living/silicon/ai/user) + if (!istype(user)) + return + /*There are pretty much only three ways to interact here. + I don't need to check for client since they're clicking on an object. + This may change in the future but for now will suffice.*/ + if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already. + user.eyeobj.forceMove(get_turf(src)) + else if(!hologram)//If there is no hologram, possibly make one. + activate_holo(user) + else if(master==user)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing. + clear_holo() + return + +/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/silicon/ai/user) + if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it. + if(!hologram)//If there is not already a hologram. + create_holo(user)//Create one. + src.visible_message("A holographic image of [user] flicks to life right before your eyes!") + else + to_chat(user, "ERROR: Image feed in progress.") + else + to_chat(user, "ERROR: Unable to project hologram.") + return + +/*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(var/datum/speech/speech, var/rendered_message="") + if(speech.speaker && hologram && master && !speech.frequency && speech.speaker != master)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. + if(!master.say_understands(speech.speaker, speech.language)) //previously if(!master.languages & speaker.languages)//The AI will be able to understand most mobs talking through the holopad. + rendered_message = speech.render_message() + var/name_used = speech.name + rendered_message = "Holopad received, [name_used] [rendered_message]" + master.show_message(rendered_message, 2) + + +/obj/machinery/hologram/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc) + hologram = new(T)//Spawn a blank effect at the location. + hologram.icon = A.holo_icon + hologram.mouse_opacity = 0//So you can't click on it. + hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. + hologram.anchored = 1//So space wind cannot drag it. + hologram.name = "[A.name] (Hologram)"//If someone decides to right click. + hologram.set_light(2) //hologram lighting + set_light(2) //pad lighting + icon_state = "holopad1" + A.current = src + master = A//AI is the master. + use_power = 2//Active power usage. + return 1 + +/obj/machinery/hologram/holopad/proc/clear_holo() +// hologram.SetLuminosity(0)//Clear lighting. //handled by the lighting controller when its ower is deleted + qdel(hologram)//Get rid of hologram. + hologram = null + if(master.current == src) + master.current = null + master = null//Null the master, since no-one is using it now. + set_light(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted) + icon_state = "holopad0" + use_power = 1//Passive power usage. + return 1 + +/obj/machinery/hologram/holopad/process() + if(hologram)//If there is a hologram. + if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector. + if(!(stat & NOPOWER))//If the machine has power. + if((HOLOPAD_MODE == 0 && (get_dist(master.eyeobj, src) <= holo_range))) + return 1 + + else if (HOLOPAD_MODE == 1) + + var/area/holo_area = get_area(src) + var/area/eye_area = get_area(master.eyeobj) + + if(eye_area == holo_area) + return 1 + + clear_holo()//If not, we want to get rid of the hologram. + return 1 + +/obj/machinery/hologram/holopad/proc/move_hologram() + if(hologram) + step_to(hologram, master.eyeobj) // So it turns. + hologram.loc = get_turf(master.eyeobj) + + return 1 + +/* + * Hologram + */ + +/obj/machinery/hologram + anchored = 1 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 + var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise. + +/obj/machinery/hologram/power_change() + if (powered()) + stat &= ~NOPOWER + else + stat |= ~NOPOWER + +//Destruction procs. +/obj/machinery/hologram/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + if (prob(50)) + qdel(src) + if(3.0) + if (prob(5)) + qdel(src) + return + +/obj/machinery/hologram/blob_act() + qdel(src) + return + +/obj/machinery/hologram/Destroy() + if(hologram) + src:clear_holo() + ..() + +/* +Holographic project of everything else. + +/mob/verb/hologram_test() + set name = "Hologram Debug New" + set category = "CURRENT DEBUG" + + var/obj/effect/overlay/hologram = new(loc)//Spawn a blank effect at the location. + var/icon/flat_icon = icon(getFlatIcon(src,0))//Need to make sure it's a new icon so the old one is not reused. + flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish. + flat_icon.ChangeOpacity(0.5)//Make it half transparent. + var/input = input("Select what icon state to use in effect.",,"") + if(input) + var/icon/alpha_mask = new('icons/effects/effects.dmi', "[input]") + flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect. + hologram.icon = flat_icon + + to_chat(world, "Your icon should appear now.") + return +*/ + +/* + * Other Stuff: Is this even used? + */ +/obj/machinery/hologram/projector + name = "hologram projector" + desc = "It makes a hologram appear...with magnets or something..." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "hologram0" diff --git a/code/game/machinery/hydroponics.dm b/code/game/machinery/hydroponics.dm index 662a51bfc34..efd86a01669 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/game/machinery/hydroponics.dm @@ -1,740 +1,740 @@ -#define HYDRO_SPEED_MULTIPLIER 1 - -/obj/machinery/hydroponics - name = "hydroponics tray" - icon = 'icons/obj/hydroponics.dmi' - icon_state = "hydrotray3" - density = 1 - anchored = 1 - var/waterlevel = 100 // The amount of water in the tray (max 100) - var/nutrilevel = 10 // The amount of nutrient in the tray (max 10) - var/pestlevel = 0 // The amount of pests in the tray (max 10) - var/weedlevel = 0 // The amount of weeds in the tray (max 10) - var/yieldmod = 1 //Modifier to yield - var/mutmod = 1 //Modifier to mutation chance - var/toxic = 0 // Toxicity in the tray? - var/age = 0 // Current age - var/dead = 0 // Is it dead? - var/health = 0 // Its health. - var/lastproduce = 0 // Last time it was harvested - var/lastcycle = 0 //Used for timing of cycles. - var/cycledelay = 200 // About 10 seconds / cycle - var/planted = 0 // Is it occupied? - var/harvest = 0 //Ready to harvest? - var/obj/item/seeds/myseed = null // The currently planted seed - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - -/obj/machinery/hydroponics/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/hydroponics, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/hydroponics/bullet_act(var/obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables. - if(istype(Proj ,/obj/item/projectile/energy/floramut)) - if(planted) - mutate() - else if(istype(Proj ,/obj/item/projectile/energy/florayield)) - if(planted && myseed.yield == 0)//Oh god don't divide by zero you'll doom us all. - myseed.yield += 1 -// to_chat(world, "Yield increased by 1, from 0, to a total of [myseed.yield]") - else if (planted && (prob(1/(myseed.yield * myseed.yield) *100)))//This formula gives you diminishing returns based on yield. 100% with 1 yield, decreasing to 25%, 11%, 6, 4, 2... - myseed.yield += 1 -// to_chat(world, "Yield increased by 1, to a total of [myseed.yield]") - else - ..() - return - -/obj/machinery/hydroponics/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else - return 0 - -obj/machinery/hydroponics/process() - - if(myseed && (myseed.loc != src)) - myseed.loc = src - - if(world.time > (lastcycle + cycledelay)) - lastcycle = world.time - if(planted && !dead) - // Advance age - age += 1 * HYDRO_SPEED_MULTIPLIER - -//Nutrients////////////////////////////////////////////////////////////// - // Nutrients deplete slowly - if(nutrilevel > 0) - if(prob(50)) - nutrilevel -= 1 * HYDRO_SPEED_MULTIPLIER - - // Lack of nutrients hurts non-weeds - if(nutrilevel <= 0 && myseed.plant_type != 1) - health -= rand(1,3) * HYDRO_SPEED_MULTIPLIER - -//Water////////////////////////////////////////////////////////////////// - // Drink random amount of water - waterlevel = max(waterlevel - rand(1,6) * HYDRO_SPEED_MULTIPLIER, 0) - - // If the plant is dry, it loses health pretty fast, unless mushroom - if(waterlevel <= 10 && myseed.plant_type != 2) - health -= rand(0,1) * HYDRO_SPEED_MULTIPLIER - if(waterlevel <= 0) - health -= rand(0,2) * HYDRO_SPEED_MULTIPLIER - - // Sufficient water level and nutrient level = plant healthy - else if(waterlevel > 10 && nutrilevel > 0) - health += rand(1,2) * HYDRO_SPEED_MULTIPLIER - if(prob(5)) //5 percent chance the weed population will increase - weedlevel += 1 * HYDRO_SPEED_MULTIPLIER -//Toxins///////////////////////////////////////////////////////////////// - - // Too much toxins cause harm, but when the plant drinks the contaiminated water, the toxins disappear slowly - if(toxic >= 40 && toxic < 80) - health -= 1 * HYDRO_SPEED_MULTIPLIER - toxic -= rand(1,10) * HYDRO_SPEED_MULTIPLIER - else if(toxic >= 80) // I don't think it ever gets here tbh unless above is commented out - health -= 3 * HYDRO_SPEED_MULTIPLIER - toxic -= rand(1,10) * HYDRO_SPEED_MULTIPLIER - else if(toxic < 0) // Make sure it won't go overoboard - toxic = 0 - -//Pests & Weeds////////////////////////////////////////////////////////// - - // Too many pests cause the plant to be sick - if (pestlevel > 10 ) // Make sure it won't go overoboard - pestlevel = 10 - - else if(pestlevel >= 5) - health -= 1 * HYDRO_SPEED_MULTIPLIER - - // If it's a weed, it doesn't stunt the growth - if(weedlevel >= 5 && myseed.plant_type != 1 ) - health -= 1 * HYDRO_SPEED_MULTIPLIER - - -//Health & Age/////////////////////////////////////////////////////////// - // Don't go overboard with the health - if(health > myseed.endurance) - health = myseed.endurance - - // Plant dies if health <= 0 - else if(health <= 0) - dead = 1 - harvest = 0 - weedlevel += 1 * HYDRO_SPEED_MULTIPLIER // Weeds flourish - pestlevel = 0 // Pests die - - // If the plant is too old, lose health fast - if(age > myseed.lifespan) - health -= rand(1,5) * HYDRO_SPEED_MULTIPLIER - - // Harvest code - if(age > myseed.production && (age - lastproduce) > myseed.production && (!harvest && !dead)) - for(var/i = 0; i < mutmod; i++) - if(prob(85)) - mutate() - else if(prob(30)) - hardmutate() - else if(prob(5)) - mutatespecie() - - if(yieldmod > 0 && myseed.yield != -1) // Unharvestable shouldn't be harvested - harvest = 1 - else - lastproduce = age - if(prob(5)) // On each tick, there's a 5 percent chance the pest population will increase - pestlevel += 1 * HYDRO_SPEED_MULTIPLIER - else - if(waterlevel > 10 && nutrilevel > 0 && prob(10)) // If there's no plant, the percentage chance is 10% - weedlevel += 1 * HYDRO_SPEED_MULTIPLIER - if(weedlevel > 10) - weedlevel = 10 - - // Weeeeeeeeeeeeeeedddssss - - if (weedlevel >= 10 && prob(50)) // At this point the plant is kind of fucked. Weeds can overtake the plant spot. - if(planted) - if(myseed.plant_type == 0) // If a normal plant - weedinvasion() - else - weedinvasion() // Weed invasion into empty tray - updateicon() - return - - - -obj/machinery/hydroponics/proc/updateicon() - //Refreshes the icon and sets the luminosity - overlays.len = 0 - if(planted) - if(dead) - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-dead") - else if(harvest) - if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") - else - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-harvest") - else if(age < myseed.maturation) - var/t_growthstate = ((age / myseed.maturation) * myseed.growthstages ) // Make sure it won't crap out due to HERPDERP 6 stages only - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[round(t_growthstate)]") - lastproduce = age //Cheating by putting this here, it means that it isn't instantly ready to harvest - else - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") // Same - - if(waterlevel <= 10) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_lowwater3") - if(nutrilevel <= 2) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_lownutri3") - if(health <= (myseed.endurance / 2)) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_lowhealth3") - if(weedlevel >= 5) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_alert3") - if(pestlevel >= 5) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_alert3") - if(toxic >= 40) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_alert3") - if(harvest) - overlays += image('icons/obj/hydroponics.dmi', icon_state="over_harvest3") - - if(istype(myseed,/obj/item/seeds/glowshroom)) - SetLuminosity(round(myseed.potency/10)) - else - SetLuminosity(0) - - return - - - -obj/machinery/hydroponics/proc/weedinvasion() // If a weed growth is sufficient, this happens. - dead = 0 - if(myseed) // In case there's nothing in the tray beforehand - qdel(myseed) - myseed = null - switch(rand(1,18)) // randomly pick predominative weed - if(16 to 18) - myseed = new /obj/item/seeds/reishimycelium - if(14 to 15) - myseed = new /obj/item/seeds/nettleseed - if(12 to 13) - myseed = new /obj/item/seeds/harebell - if(10 to 11) - myseed = new /obj/item/seeds/amanitamycelium - if(8 to 9) - myseed = new /obj/item/seeds/chantermycelium - if(6 to 7) // implementation for tower caps still kinda missing ~ Not Anymore! -Cheridan - myseed = new /obj/item/seeds/towermycelium - if(4 to 5) - myseed = new /obj/item/seeds/plumpmycelium - else - myseed = new /obj/item/seeds/weeds - planted = 1 - age = 0 - health = myseed.endurance - lastcycle = world.time - harvest = 0 - weedlevel = 0 // Reset - pestlevel = 0 // Reset - updateicon() - visible_message("[src] has been overtaken by [myseed.plantname].") - - return - - -obj/machinery/hydroponics/proc/mutate() // Mutates the current seed - - - myseed.lifespan += rand(-2,2) - if(myseed.lifespan < 10) - myseed.lifespan = 10 - else if(myseed.lifespan > 30) - myseed.lifespan = 30 - - myseed.endurance += rand(-5,5) - if(myseed.endurance < 10) - myseed.endurance = 10 - else if(myseed.endurance > 100) - myseed.endurance = 100 - - myseed.production += rand(-1,1) - if(myseed.production < 2) - myseed.production = 2 - else if(myseed.production > 10) - myseed.production = 10 - - if(myseed.yield != -1) // Unharvestable shouldn't suddenly turn harvestable - myseed.yield += rand(-2,2) - if(myseed.yield < 0) - myseed.yield = 0 - else if(myseed.yield > 10) - myseed.yield = 10 - if(myseed.yield == 0 && myseed.plant_type == 2) - myseed.yield = 1 // Mushrooms always have a minimum yield of 1. - - if(myseed.potency != -1) //Not all plants have a potency - myseed.potency += rand(-25,25) - if(myseed.potency < 0) - myseed.potency = 0 - else if(myseed.potency > 100) - myseed.potency = 100 - return - - - -obj/machinery/hydroponics/proc/hardmutate() // Strongly mutates the current seed. - - - myseed.lifespan += rand(-4,4) - if(myseed.lifespan < 10) - myseed.lifespan = 10 - else if(myseed.lifespan > 30 && !istype(myseed,/obj/item/seeds/glowshroom)) //hack to prevent glowshrooms from always resetting to 30 sec delay - myseed.lifespan = 30 - - myseed.endurance += rand(-10,10) - if(myseed.endurance < 10) - myseed.endurance = 10 - else if(myseed.endurance > 100) - myseed.endurance = 100 - - myseed.production += rand(-2,2) - if(myseed.production < 2) - myseed.production = 2 - else if(myseed.production > 10) - myseed.production = 10 - - if(myseed.yield != -1) // Unharvestable shouldn't suddenly turn harvestable - myseed.yield += rand(-4,4) - if(myseed.yield < 0) - myseed.yield = 0 - else if(myseed.yield > 10) - myseed.yield = 10 - if(myseed.yield == 0 && myseed.plant_type == 2) - myseed.yield = 1 // Mushrooms always have a minimum yield of 1. - - if(myseed.potency != -1) //Not all plants have a potency - myseed.potency += rand(-50,50) - if(myseed.potency < 0) - myseed.potency = 0 - else if(myseed.potency > 100) - myseed.potency = 100 - return - - - -obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant! - - - if ( istype(myseed, /obj/item/seeds/nettleseed )) - qdel(myseed) - myseed = new /obj/item/seeds/deathnettleseed - - else if ( istype(myseed, /obj/item/seeds/amanitamycelium )) - qdel(myseed) - myseed = new /obj/item/seeds/angelmycelium - - else if ( istype(myseed, /obj/item/seeds/lemonseed )) - qdel(myseed) - myseed = new /obj/item/seeds/cashseed - - else if ( istype(myseed, /obj/item/seeds/ambrosiavulgarisseed )) - qdel(myseed) - myseed = new /obj/item/seeds/ambrosiadeusseed - - else if ( istype(myseed, /obj/item/seeds/plumpmycelium )) - qdel(myseed) - myseed = new /obj/item/seeds/walkingmushroommycelium - else if ( istype(myseed, /obj/item/seeds/synthmeatseed )) - qdel(myseed) - switch(rand(1,100)) - if(1 to 50) - myseed = new /obj/item/seeds/synthbuttseed - if(51 to 100) - myseed = new /obj/item/seeds/synthbrainseed - - else if ( istype(myseed, /obj/item/seeds/chiliseed )) - qdel(myseed) - switch(rand(1,100)) - if(1 to 60) - myseed = new /obj/item/seeds/icepepperseed - if(61 to 100) - myseed = new /obj/item/seeds/chillighost - - else if ( istype(myseed, /obj/item/seeds/appleseed )) - qdel(myseed) - myseed = new /obj/item/seeds/goldappleseed - - else if ( istype(myseed, /obj/item/seeds/berryseed )) - qdel(myseed) - switch(rand(1,100)) - if(1 to 50) - myseed = new /obj/item/seeds/poisonberryseed - if(51 to 100) - myseed = new /obj/item/seeds/glowberryseed - - else if ( istype(myseed, /obj/item/seeds/poisonberryseed )) - qdel(myseed) - myseed = new /obj/item/seeds/deathberryseed - - else if ( istype(myseed, /obj/item/seeds/tomatoseed )) - qdel(myseed) - switch(rand(1,100)) - if(1 to 35) - myseed = new /obj/item/seeds/bluetomatoseed - if(36 to 70) - myseed = new /obj/item/seeds/bloodtomatoseed - if(71 to 100) - myseed = new /obj/item/seeds/killertomatoseed - - else if ( istype(myseed, /obj/item/seeds/bluetomatoseed )) - qdel(myseed) - myseed = new /obj/item/seeds/bluespacetomatoseed - - else if ( istype(myseed, /obj/item/seeds/grapeseed )) - qdel(myseed) - myseed = new /obj/item/seeds/greengrapeseed -/* - else if ( istype(myseed, /obj/item/seeds/tomatoseed )) - del(myseed) - myseed = new /obj/item/seeds/gibtomatoseed -*/ - else if ( istype(myseed, /obj/item/seeds/eggplantseed )) - qdel(myseed) - myseed = new /obj/item/seeds/eggyseed - else if ( istype(myseed, /obj/item/seeds/soyaseed )) - qdel(myseed) - myseed = new /obj/item/seeds/koiseed - - else if ( istype(myseed, /obj/item/seeds/sunflowerseed )) - qdel(myseed) - switch(rand(1,100)) - if(1 to 60) - myseed = new /obj/item/seeds/moonflowerseed - if(61 to 100) - myseed = new /obj/item/seeds/novaflowerseed - - else - return - - dead = 0 - hardmutate() - planted = 1 - age = 0 - health = myseed.endurance - lastcycle = world.time - harvest = 0 - weedlevel = 0 // Reset - - spawn(5) // Wait a while - updateicon() - visible_message("[src] has suddenly mutated into [myseed.plantname]!") - - return - - - -obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant - if ( weedlevel > 5 ) - qdel(myseed) - var/newWeed = pick(/obj/item/seeds/libertymycelium, /obj/item/seeds/angelmycelium, /obj/item/seeds/deathnettleseed, /obj/item/seeds/kudzuseed) - myseed = new newWeed - dead = 0 - hardmutate() - planted = 1 - age = 0 - health = myseed.endurance - lastcycle = world.time - harvest = 0 - weedlevel = 0 // Reset - - spawn(5) // Wait a while - updateicon() - visible_message("The mutated weeds in [src] spawned a [myseed.plantname]!") - else - to_chat(usr, "The few weeds in the [src] seem to react, but only for a moment...") - return - - - -obj/machinery/hydroponics/proc/plantdies() // OH NOES!!!!! I put this all in one function to make things easier - health = 0 - dead = 1 - harvest = 0 - updateicon() - visible_message("[src] is looking very unhealthy!") - return - - - -obj/machinery/hydroponics/proc/mutatepest() // Until someone makes a spaceworm, this is commented out - if ( pestlevel > 5 ) - visible_message("The pests seem to behave oddly...") -// spawn(10) -// new /obj/effect/alien/spaceworm(loc) - else - to_chat(usr, "The pests seem to behave oddly, but quickly settle down...")//Modified to give a better idea of what's happening when you inject mutagen. There's still nothing proper to spawn here though. -Cheridan +#define HYDRO_SPEED_MULTIPLIER 1 - return - - - -obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) - - if(..()) - return 1 - - //Called when mob user "attacks" it with object O - if (istype(O, /obj/item/weapon/reagent_containers/glass/bucket)) - var/b_amount = O.reagents.get_reagent_amount("water") - if(b_amount > 0 && waterlevel < 100) - if(b_amount + waterlevel > 100) - b_amount = 100 - waterlevel - O.reagents.remove_reagent("water", b_amount) - waterlevel += b_amount - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) +/obj/machinery/hydroponics + name = "hydroponics tray" + icon = 'icons/obj/hydroponics.dmi' + icon_state = "hydrotray3" + density = 1 + anchored = 1 + var/waterlevel = 100 // The amount of water in the tray (max 100) + var/nutrilevel = 10 // The amount of nutrient in the tray (max 10) + var/pestlevel = 0 // The amount of pests in the tray (max 10) + var/weedlevel = 0 // The amount of weeds in the tray (max 10) + var/yieldmod = 1 //Modifier to yield + var/mutmod = 1 //Modifier to mutation chance + var/toxic = 0 // Toxicity in the tray? + var/age = 0 // Current age + var/dead = 0 // Is it dead? + var/health = 0 // Its health. + var/lastproduce = 0 // Last time it was harvested + var/lastcycle = 0 //Used for timing of cycles. + var/cycledelay = 200 // About 10 seconds / cycle + var/planted = 0 // Is it occupied? + var/harvest = 0 //Ready to harvest? + var/obj/item/seeds/myseed = null // The currently planted seed + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + +/obj/machinery/hydroponics/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/hydroponics, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/hydroponics/bullet_act(var/obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables. + if(istype(Proj ,/obj/item/projectile/energy/floramut)) + if(planted) + mutate() + else if(istype(Proj ,/obj/item/projectile/energy/florayield)) + if(planted && myseed.yield == 0)//Oh god don't divide by zero you'll doom us all. + myseed.yield += 1 +// to_chat(world, "Yield increased by 1, from 0, to a total of [myseed.yield]") + else if (planted && (prob(1/(myseed.yield * myseed.yield) *100)))//This formula gives you diminishing returns based on yield. 100% with 1 yield, decreasing to 25%, 11%, 6, 4, 2... + myseed.yield += 1 +// to_chat(world, "Yield increased by 1, to a total of [myseed.yield]") + else + ..() + return + +/obj/machinery/hydroponics/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + else + return 0 + +obj/machinery/hydroponics/process() + + if(myseed && (myseed.loc != src)) + myseed.loc = src + + if(world.time > (lastcycle + cycledelay)) + lastcycle = world.time + if(planted && !dead) + // Advance age + age += 1 * HYDRO_SPEED_MULTIPLIER + +//Nutrients////////////////////////////////////////////////////////////// + // Nutrients deplete slowly + if(nutrilevel > 0) + if(prob(50)) + nutrilevel -= 1 * HYDRO_SPEED_MULTIPLIER + + // Lack of nutrients hurts non-weeds + if(nutrilevel <= 0 && myseed.plant_type != 1) + health -= rand(1,3) * HYDRO_SPEED_MULTIPLIER + +//Water////////////////////////////////////////////////////////////////// + // Drink random amount of water + waterlevel = max(waterlevel - rand(1,6) * HYDRO_SPEED_MULTIPLIER, 0) + + // If the plant is dry, it loses health pretty fast, unless mushroom + if(waterlevel <= 10 && myseed.plant_type != 2) + health -= rand(0,1) * HYDRO_SPEED_MULTIPLIER + if(waterlevel <= 0) + health -= rand(0,2) * HYDRO_SPEED_MULTIPLIER + + // Sufficient water level and nutrient level = plant healthy + else if(waterlevel > 10 && nutrilevel > 0) + health += rand(1,2) * HYDRO_SPEED_MULTIPLIER + if(prob(5)) //5 percent chance the weed population will increase + weedlevel += 1 * HYDRO_SPEED_MULTIPLIER +//Toxins///////////////////////////////////////////////////////////////// + + // Too much toxins cause harm, but when the plant drinks the contaiminated water, the toxins disappear slowly + if(toxic >= 40 && toxic < 80) + health -= 1 * HYDRO_SPEED_MULTIPLIER + toxic -= rand(1,10) * HYDRO_SPEED_MULTIPLIER + else if(toxic >= 80) // I don't think it ever gets here tbh unless above is commented out + health -= 3 * HYDRO_SPEED_MULTIPLIER + toxic -= rand(1,10) * HYDRO_SPEED_MULTIPLIER + else if(toxic < 0) // Make sure it won't go overoboard + toxic = 0 + +//Pests & Weeds////////////////////////////////////////////////////////// + + // Too many pests cause the plant to be sick + if (pestlevel > 10 ) // Make sure it won't go overoboard + pestlevel = 10 + + else if(pestlevel >= 5) + health -= 1 * HYDRO_SPEED_MULTIPLIER + + // If it's a weed, it doesn't stunt the growth + if(weedlevel >= 5 && myseed.plant_type != 1 ) + health -= 1 * HYDRO_SPEED_MULTIPLIER + + +//Health & Age/////////////////////////////////////////////////////////// + // Don't go overboard with the health + if(health > myseed.endurance) + health = myseed.endurance + + // Plant dies if health <= 0 + else if(health <= 0) + dead = 1 + harvest = 0 + weedlevel += 1 * HYDRO_SPEED_MULTIPLIER // Weeds flourish + pestlevel = 0 // Pests die + + // If the plant is too old, lose health fast + if(age > myseed.lifespan) + health -= rand(1,5) * HYDRO_SPEED_MULTIPLIER + + // Harvest code + if(age > myseed.production && (age - lastproduce) > myseed.production && (!harvest && !dead)) + for(var/i = 0; i < mutmod; i++) + if(prob(85)) + mutate() + else if(prob(30)) + hardmutate() + else if(prob(5)) + mutatespecie() + + if(yieldmod > 0 && myseed.yield != -1) // Unharvestable shouldn't be harvested + harvest = 1 + else + lastproduce = age + if(prob(5)) // On each tick, there's a 5 percent chance the pest population will increase + pestlevel += 1 * HYDRO_SPEED_MULTIPLIER + else + if(waterlevel > 10 && nutrilevel > 0 && prob(10)) // If there's no plant, the percentage chance is 10% + weedlevel += 1 * HYDRO_SPEED_MULTIPLIER + if(weedlevel > 10) + weedlevel = 10 + + // Weeeeeeeeeeeeeeedddssss + + if (weedlevel >= 10 && prob(50)) // At this point the plant is kind of fucked. Weeds can overtake the plant spot. + if(planted) + if(myseed.plant_type == 0) // If a normal plant + weedinvasion() + else + weedinvasion() // Weed invasion into empty tray + updateicon() + return + + + +obj/machinery/hydroponics/proc/updateicon() + //Refreshes the icon and sets the luminosity + overlays.len = 0 + if(planted) + if(dead) + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-dead") + else if(harvest) + if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") + else + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-harvest") + else if(age < myseed.maturation) + var/t_growthstate = ((age / myseed.maturation) * myseed.growthstages ) // Make sure it won't crap out due to HERPDERP 6 stages only + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[round(t_growthstate)]") + lastproduce = age //Cheating by putting this here, it means that it isn't instantly ready to harvest + else + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") // Same + + if(waterlevel <= 10) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_lowwater3") + if(nutrilevel <= 2) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_lownutri3") + if(health <= (myseed.endurance / 2)) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_lowhealth3") + if(weedlevel >= 5) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_alert3") + if(pestlevel >= 5) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_alert3") + if(toxic >= 40) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_alert3") + if(harvest) + overlays += image('icons/obj/hydroponics.dmi', icon_state="over_harvest3") + + if(istype(myseed,/obj/item/seeds/glowshroom)) + SetLuminosity(round(myseed.potency/10)) + else + SetLuminosity(0) + + return + + + +obj/machinery/hydroponics/proc/weedinvasion() // If a weed growth is sufficient, this happens. + dead = 0 + if(myseed) // In case there's nothing in the tray beforehand + qdel(myseed) + myseed = null + switch(rand(1,18)) // randomly pick predominative weed + if(16 to 18) + myseed = new /obj/item/seeds/reishimycelium + if(14 to 15) + myseed = new /obj/item/seeds/nettleseed + if(12 to 13) + myseed = new /obj/item/seeds/harebell + if(10 to 11) + myseed = new /obj/item/seeds/amanitamycelium + if(8 to 9) + myseed = new /obj/item/seeds/chantermycelium + if(6 to 7) // implementation for tower caps still kinda missing ~ Not Anymore! -Cheridan + myseed = new /obj/item/seeds/towermycelium + if(4 to 5) + myseed = new /obj/item/seeds/plumpmycelium + else + myseed = new /obj/item/seeds/weeds + planted = 1 + age = 0 + health = myseed.endurance + lastcycle = world.time + harvest = 0 + weedlevel = 0 // Reset + pestlevel = 0 // Reset + updateicon() + visible_message("[src] has been overtaken by [myseed.plantname].") + + return + + +obj/machinery/hydroponics/proc/mutate() // Mutates the current seed + + + myseed.lifespan += rand(-2,2) + if(myseed.lifespan < 10) + myseed.lifespan = 10 + else if(myseed.lifespan > 30) + myseed.lifespan = 30 + + myseed.endurance += rand(-5,5) + if(myseed.endurance < 10) + myseed.endurance = 10 + else if(myseed.endurance > 100) + myseed.endurance = 100 + + myseed.production += rand(-1,1) + if(myseed.production < 2) + myseed.production = 2 + else if(myseed.production > 10) + myseed.production = 10 + + if(myseed.yield != -1) // Unharvestable shouldn't suddenly turn harvestable + myseed.yield += rand(-2,2) + if(myseed.yield < 0) + myseed.yield = 0 + else if(myseed.yield > 10) + myseed.yield = 10 + if(myseed.yield == 0 && myseed.plant_type == 2) + myseed.yield = 1 // Mushrooms always have a minimum yield of 1. + + if(myseed.potency != -1) //Not all plants have a potency + myseed.potency += rand(-25,25) + if(myseed.potency < 0) + myseed.potency = 0 + else if(myseed.potency > 100) + myseed.potency = 100 + return + + + +obj/machinery/hydroponics/proc/hardmutate() // Strongly mutates the current seed. + + + myseed.lifespan += rand(-4,4) + if(myseed.lifespan < 10) + myseed.lifespan = 10 + else if(myseed.lifespan > 30 && !istype(myseed,/obj/item/seeds/glowshroom)) //hack to prevent glowshrooms from always resetting to 30 sec delay + myseed.lifespan = 30 + + myseed.endurance += rand(-10,10) + if(myseed.endurance < 10) + myseed.endurance = 10 + else if(myseed.endurance > 100) + myseed.endurance = 100 + + myseed.production += rand(-2,2) + if(myseed.production < 2) + myseed.production = 2 + else if(myseed.production > 10) + myseed.production = 10 + + if(myseed.yield != -1) // Unharvestable shouldn't suddenly turn harvestable + myseed.yield += rand(-4,4) + if(myseed.yield < 0) + myseed.yield = 0 + else if(myseed.yield > 10) + myseed.yield = 10 + if(myseed.yield == 0 && myseed.plant_type == 2) + myseed.yield = 1 // Mushrooms always have a minimum yield of 1. + + if(myseed.potency != -1) //Not all plants have a potency + myseed.potency += rand(-50,50) + if(myseed.potency < 0) + myseed.potency = 0 + else if(myseed.potency > 100) + myseed.potency = 100 + return + + + +obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant! + + + if ( istype(myseed, /obj/item/seeds/nettleseed )) + qdel(myseed) + myseed = new /obj/item/seeds/deathnettleseed + + else if ( istype(myseed, /obj/item/seeds/amanitamycelium )) + qdel(myseed) + myseed = new /obj/item/seeds/angelmycelium + + else if ( istype(myseed, /obj/item/seeds/lemonseed )) + qdel(myseed) + myseed = new /obj/item/seeds/cashseed + + else if ( istype(myseed, /obj/item/seeds/ambrosiavulgarisseed )) + qdel(myseed) + myseed = new /obj/item/seeds/ambrosiadeusseed + + else if ( istype(myseed, /obj/item/seeds/plumpmycelium )) + qdel(myseed) + myseed = new /obj/item/seeds/walkingmushroommycelium + else if ( istype(myseed, /obj/item/seeds/synthmeatseed )) + qdel(myseed) + switch(rand(1,100)) + if(1 to 50) + myseed = new /obj/item/seeds/synthbuttseed + if(51 to 100) + myseed = new /obj/item/seeds/synthbrainseed + + else if ( istype(myseed, /obj/item/seeds/chiliseed )) + qdel(myseed) + switch(rand(1,100)) + if(1 to 60) + myseed = new /obj/item/seeds/icepepperseed + if(61 to 100) + myseed = new /obj/item/seeds/chillighost + + else if ( istype(myseed, /obj/item/seeds/appleseed )) + qdel(myseed) + myseed = new /obj/item/seeds/goldappleseed + + else if ( istype(myseed, /obj/item/seeds/berryseed )) + qdel(myseed) + switch(rand(1,100)) + if(1 to 50) + myseed = new /obj/item/seeds/poisonberryseed + if(51 to 100) + myseed = new /obj/item/seeds/glowberryseed + + else if ( istype(myseed, /obj/item/seeds/poisonberryseed )) + qdel(myseed) + myseed = new /obj/item/seeds/deathberryseed + + else if ( istype(myseed, /obj/item/seeds/tomatoseed )) + qdel(myseed) + switch(rand(1,100)) + if(1 to 35) + myseed = new /obj/item/seeds/bluetomatoseed + if(36 to 70) + myseed = new /obj/item/seeds/bloodtomatoseed + if(71 to 100) + myseed = new /obj/item/seeds/killertomatoseed + + else if ( istype(myseed, /obj/item/seeds/bluetomatoseed )) + qdel(myseed) + myseed = new /obj/item/seeds/bluespacetomatoseed + + else if ( istype(myseed, /obj/item/seeds/grapeseed )) + qdel(myseed) + myseed = new /obj/item/seeds/greengrapeseed +/* + else if ( istype(myseed, /obj/item/seeds/tomatoseed )) + del(myseed) + myseed = new /obj/item/seeds/gibtomatoseed +*/ + else if ( istype(myseed, /obj/item/seeds/eggplantseed )) + qdel(myseed) + myseed = new /obj/item/seeds/eggyseed + else if ( istype(myseed, /obj/item/seeds/soyaseed )) + qdel(myseed) + myseed = new /obj/item/seeds/koiseed + + else if ( istype(myseed, /obj/item/seeds/sunflowerseed )) + qdel(myseed) + switch(rand(1,100)) + if(1 to 60) + myseed = new /obj/item/seeds/moonflowerseed + if(61 to 100) + myseed = new /obj/item/seeds/novaflowerseed + + else + return + + dead = 0 + hardmutate() + planted = 1 + age = 0 + health = myseed.endurance + lastcycle = world.time + harvest = 0 + weedlevel = 0 // Reset + + spawn(5) // Wait a while + updateicon() + visible_message("[src] has suddenly mutated into [myseed.plantname]!") + + return + + + +obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant + if ( weedlevel > 5 ) + qdel(myseed) + var/newWeed = pick(/obj/item/seeds/libertymycelium, /obj/item/seeds/angelmycelium, /obj/item/seeds/deathnettleseed, /obj/item/seeds/kudzuseed) + myseed = new newWeed + dead = 0 + hardmutate() + planted = 1 + age = 0 + health = myseed.endurance + lastcycle = world.time + harvest = 0 + weedlevel = 0 // Reset + + spawn(5) // Wait a while + updateicon() + visible_message("The mutated weeds in [src] spawned a [myseed.plantname]!") + else + to_chat(usr, "The few weeds in the [src] seem to react, but only for a moment...") + return + + + +obj/machinery/hydroponics/proc/plantdies() // OH NOES!!!!! I put this all in one function to make things easier + health = 0 + dead = 1 + harvest = 0 + updateicon() + visible_message("[src] is looking very unhealthy!") + return + + + +obj/machinery/hydroponics/proc/mutatepest() // Until someone makes a spaceworm, this is commented out + if ( pestlevel > 5 ) + visible_message("The pests seem to behave oddly...") +// spawn(10) +// new /obj/effect/alien/spaceworm(loc) + else + to_chat(usr, "The pests seem to behave oddly, but quickly settle down...")//Modified to give a better idea of what's happening when you inject mutagen. There's still nothing proper to spawn here though. -Cheridan + + return + + + +obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) + + if(..()) + return 1 + + //Called when mob user "attacks" it with object O + if (istype(O, /obj/item/weapon/reagent_containers/glass/bucket)) + var/b_amount = O.reagents.get_reagent_amount("water") + if(b_amount > 0 && waterlevel < 100) + if(b_amount + waterlevel > 100) + b_amount = 100 - waterlevel + O.reagents.remove_reagent("water", b_amount) + waterlevel += b_amount + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) to_chat(user, "You fill the [src] with [b_amount] units of water.") - - // Toxicity dilutation code. The more water you put in, the lesser the toxin concentration. - toxic -= round(b_amount/4) - if (toxic < 0 ) // Make sure it won't go overoboard - toxic = 0 - - else if(waterlevel >= 100) + + // Toxicity dilutation code. The more water you put in, the lesser the toxin concentration. + toxic -= round(b_amount/4) + if (toxic < 0 ) // Make sure it won't go overoboard + toxic = 0 + + else if(waterlevel >= 100) to_chat(user, "The [src] is already full.") - else + else to_chat(user, "The bucket is not filled with water.") - updateicon() - - else if ( istype(O, /obj/item/nutrient) ) - var/obj/item/nutrient/myNut = O - user.u_equip(O, 1) - nutrilevel = 10 - yieldmod = myNut.yieldmod - mutmod = myNut.mutmod + updateicon() + + else if ( istype(O, /obj/item/nutrient) ) + var/obj/item/nutrient/myNut = O + user.u_equip(O, 1) + nutrilevel = 10 + yieldmod = myNut.yieldmod + mutmod = myNut.mutmod to_chat(user, "You replace the nutrient solution in the [src].") - qdel(O) - O = null - updateicon() - - else if(istype(O, /obj/item/weapon/reagent_containers/syringe)) // Syringe stuff - var/obj/item/weapon/reagent_containers/syringe/S = O - if (planted) - if (S.mode == 1) - if(!S.reagents.total_volume) + qdel(O) + O = null + updateicon() + + else if(istype(O, /obj/item/weapon/reagent_containers/syringe)) // Syringe stuff + var/obj/item/weapon/reagent_containers/syringe/S = O + if (planted) + if (S.mode == 1) + if(!S.reagents.total_volume) to_chat(user, "The syringe is empty.") - return + return to_chat(user, "You inject the [myseed.plantname] with a chemical solution.") - - // There needs to be a good amount of mutagen to actually work - - if(S.reagents.has_reagent("mutagen", 5)) - switch(rand(100)) - if (91 to 100) plantdies() - if (81 to 90) mutatespecie() - if (66 to 80) hardmutate() - if (41 to 65) mutate() + + // There needs to be a good amount of mutagen to actually work + + if(S.reagents.has_reagent("mutagen", 5)) + switch(rand(100)) + if (91 to 100) plantdies() + if (81 to 90) mutatespecie() + if (66 to 80) hardmutate() + if (41 to 65) mutate() to_chat(if (21 to 41) user, "The plants don't seem to react...") - if (11 to 20) mutateweed() - if (1 to 10) mutatepest() + if (11 to 20) mutateweed() + if (1 to 10) mutatepest() to_chat(else user, "Nothing happens...") - - // Antitoxin binds shit pretty well. So the tox goes significantly down - if(S.reagents.has_reagent("anti_toxin", 1)) - toxic -= round(S.reagents.get_reagent_amount("anti_toxin")*2) - - // NIGGA, YOU JUST WENT ON FULL RETARD. - if(S.reagents.has_reagent("toxin", 1)) - toxic += round(S.reagents.get_reagent_amount("toxin")*2) - - // Milk is good for humans, but bad for plants. The sugars canot be used by plants, and the milk fat fucks up growth. Not shrooms though. I can't deal with this now... - if(S.reagents.has_reagent("milk", 1)) - nutrilevel += round(S.reagents.get_reagent_amount("milk")*0.1) - waterlevel += round(S.reagents.get_reagent_amount("milk")*0.9) - - // Beer is a chemical composition of alcohol and various other things. It's a shitty nutrient but hey, it's still one. Also alcohol is bad, mmmkay? - if(S.reagents.has_reagent("beer", 1)) - health -= round(S.reagents.get_reagent_amount("beer")*0.05) - nutrilevel += round(S.reagents.get_reagent_amount("beer")*0.25) - waterlevel += round(S.reagents.get_reagent_amount("beer")*0.7) - - // You're an idiot of thinking that one of the most corrosive and deadly gasses would be beneficial - if(S.reagents.has_reagent("fluorine", 1)) - health -= round(S.reagents.get_reagent_amount("fluorine")*2) - toxic += round(S.reagents.get_reagent_amount("flourine")*2.5) - waterlevel -= round(S.reagents.get_reagent_amount("flourine")*0.5) - weedlevel -= rand(1,4) - - // You're an idiot of thinking that one of the most corrosive and deadly gasses would be beneficial - if(S.reagents.has_reagent("chlorine", 1)) - health -= round(S.reagents.get_reagent_amount("chlorine")*1) - toxic += round(S.reagents.get_reagent_amount("chlorine")*1.5) - waterlevel -= round(S.reagents.get_reagent_amount("chlorine")*0.5) - weedlevel -= rand(1,3) - - // White Phosphorous + water -> phosphoric acid. That's not a good thing really. Phosphoric salts are beneficial though. And even if the plant suffers, in the long run the tray gets some nutrients. The benefit isn't worth that much. - if(S.reagents.has_reagent("phosphorus", 1)) - health -= round(S.reagents.get_reagent_amount("phosphorus")*0.75) - nutrilevel += round(S.reagents.get_reagent_amount("phosphorus")*0.1) - waterlevel -= round(S.reagents.get_reagent_amount("phosphorus")*0.5) - weedlevel -= rand(1,2) - - // Plants should not have sugar, they can't use it and it prevents them getting water/ nutients, it is good for mold though... - if(S.reagents.has_reagent("sugar", 1)) - weedlevel += rand(1,2) - pestlevel += rand(1,2) - nutrilevel+= round(S.reagents.get_reagent_amount("sugar")*0.1) - - // It is water! - if(S.reagents.has_reagent("water", 1)) - waterlevel += round(S.reagents.get_reagent_amount("water")*1) - - // Holy water. Mostly the same as water, it also heals the plant a little with the power of the spirits~ - if(S.reagents.has_reagent("holywater", 1)) - waterlevel += round(S.reagents.get_reagent_amount("holywater")*1) - health += round(S.reagents.get_reagent_amount("holywater")*0.1) - - // A variety of nutrients are dissolved in club soda, without sugar. These nutrients include carbon, oxygen, hydrogen, phosphorous, potassium, sulfur and sodium, all of which are needed for healthy plant growth. - if(S.reagents.has_reagent("sodawater", 1)) - waterlevel += round(S.reagents.get_reagent_amount("sodawater")*1) - health += round(S.reagents.get_reagent_amount("sodawater")*0.1) - nutrilevel += round(S.reagents.get_reagent_amount("sodawater")*0.1) - - // Man, you guys are retards - if(S.reagents.has_reagent("sacid", 1)) - health -= round(S.reagents.get_reagent_amount("sacid")*1) - toxic += round(S.reagents.get_reagent_amount("sacid")*1.5) - weedlevel -= rand(1,2) - - // SERIOUSLY - if(S.reagents.has_reagent("pacid", 1)) - health -= round(S.reagents.get_reagent_amount("pacid")*2) - toxic += round(S.reagents.get_reagent_amount("pacid")*3) - weedlevel -= rand(1,4) - - // Plant-B-Gone is just as bad - if(S.reagents.has_reagent("plantbgone", 1)) - health -= round(S.reagents.get_reagent_amount("plantbgone")*2) - toxic -= round(S.reagents.get_reagent_amount("plantbgone")*3) - weedlevel -= rand(4,8) - - // Healing - if(S.reagents.has_reagent("cryoxadone", 1)) - health += round(S.reagents.get_reagent_amount("cryoxadone")*3) - toxic -= round(S.reagents.get_reagent_amount("cryoxadone")*3) - - // FINALLY IMPLEMENTED, Ammonia is bad ass. - if(S.reagents.has_reagent("ammonia", 1)) - health += round(S.reagents.get_reagent_amount("ammonia")*0.5) - nutrilevel += round(S.reagents.get_reagent_amount("ammonia")*1) - - // FINALLY IMPLEMENTED, This is more bad ass, and pests get hurt by the corrosive nature of it, not the plant. - if(S.reagents.has_reagent("diethylamine", 1)) - health += round(S.reagents.get_reagent_amount("diethylamine")*1) - nutrilevel += round(S.reagents.get_reagent_amount("diethylamine")*2) - pestlevel -= rand(1,2) - - // Compost, effectively - if(S.reagents.has_reagent("nutriment", 1)) - health += round(S.reagents.get_reagent_amount("nutriment")*0.5) - nutrilevel += round(S.reagents.get_reagent_amount("nutriment")*1) - - // Poor man's mutagen. - if(S.reagents.has_reagent("radium", 1)) - health -= round(S.reagents.get_reagent_amount("radium")*1.5) - toxic += round(S.reagents.get_reagent_amount("radium")*2) - if(S.reagents.has_reagent("radium", 10)) - switch(rand(100)) - if (91 to 100) plantdies() - if (81 to 90) mutatespecie() - if (66 to 80) hardmutate() - if (41 to 65) mutate() + + // Antitoxin binds shit pretty well. So the tox goes significantly down + if(S.reagents.has_reagent("anti_toxin", 1)) + toxic -= round(S.reagents.get_reagent_amount("anti_toxin")*2) + + // NIGGA, YOU JUST WENT ON FULL RETARD. + if(S.reagents.has_reagent("toxin", 1)) + toxic += round(S.reagents.get_reagent_amount("toxin")*2) + + // Milk is good for humans, but bad for plants. The sugars canot be used by plants, and the milk fat fucks up growth. Not shrooms though. I can't deal with this now... + if(S.reagents.has_reagent("milk", 1)) + nutrilevel += round(S.reagents.get_reagent_amount("milk")*0.1) + waterlevel += round(S.reagents.get_reagent_amount("milk")*0.9) + + // Beer is a chemical composition of alcohol and various other things. It's a shitty nutrient but hey, it's still one. Also alcohol is bad, mmmkay? + if(S.reagents.has_reagent("beer", 1)) + health -= round(S.reagents.get_reagent_amount("beer")*0.05) + nutrilevel += round(S.reagents.get_reagent_amount("beer")*0.25) + waterlevel += round(S.reagents.get_reagent_amount("beer")*0.7) + + // You're an idiot of thinking that one of the most corrosive and deadly gasses would be beneficial + if(S.reagents.has_reagent("fluorine", 1)) + health -= round(S.reagents.get_reagent_amount("fluorine")*2) + toxic += round(S.reagents.get_reagent_amount("flourine")*2.5) + waterlevel -= round(S.reagents.get_reagent_amount("flourine")*0.5) + weedlevel -= rand(1,4) + + // You're an idiot of thinking that one of the most corrosive and deadly gasses would be beneficial + if(S.reagents.has_reagent("chlorine", 1)) + health -= round(S.reagents.get_reagent_amount("chlorine")*1) + toxic += round(S.reagents.get_reagent_amount("chlorine")*1.5) + waterlevel -= round(S.reagents.get_reagent_amount("chlorine")*0.5) + weedlevel -= rand(1,3) + + // White Phosphorous + water -> phosphoric acid. That's not a good thing really. Phosphoric salts are beneficial though. And even if the plant suffers, in the long run the tray gets some nutrients. The benefit isn't worth that much. + if(S.reagents.has_reagent("phosphorus", 1)) + health -= round(S.reagents.get_reagent_amount("phosphorus")*0.75) + nutrilevel += round(S.reagents.get_reagent_amount("phosphorus")*0.1) + waterlevel -= round(S.reagents.get_reagent_amount("phosphorus")*0.5) + weedlevel -= rand(1,2) + + // Plants should not have sugar, they can't use it and it prevents them getting water/ nutients, it is good for mold though... + if(S.reagents.has_reagent("sugar", 1)) + weedlevel += rand(1,2) + pestlevel += rand(1,2) + nutrilevel+= round(S.reagents.get_reagent_amount("sugar")*0.1) + + // It is water! + if(S.reagents.has_reagent("water", 1)) + waterlevel += round(S.reagents.get_reagent_amount("water")*1) + + // Holy water. Mostly the same as water, it also heals the plant a little with the power of the spirits~ + if(S.reagents.has_reagent("holywater", 1)) + waterlevel += round(S.reagents.get_reagent_amount("holywater")*1) + health += round(S.reagents.get_reagent_amount("holywater")*0.1) + + // A variety of nutrients are dissolved in club soda, without sugar. These nutrients include carbon, oxygen, hydrogen, phosphorous, potassium, sulfur and sodium, all of which are needed for healthy plant growth. + if(S.reagents.has_reagent("sodawater", 1)) + waterlevel += round(S.reagents.get_reagent_amount("sodawater")*1) + health += round(S.reagents.get_reagent_amount("sodawater")*0.1) + nutrilevel += round(S.reagents.get_reagent_amount("sodawater")*0.1) + + // Man, you guys are retards + if(S.reagents.has_reagent("sacid", 1)) + health -= round(S.reagents.get_reagent_amount("sacid")*1) + toxic += round(S.reagents.get_reagent_amount("sacid")*1.5) + weedlevel -= rand(1,2) + + // SERIOUSLY + if(S.reagents.has_reagent("pacid", 1)) + health -= round(S.reagents.get_reagent_amount("pacid")*2) + toxic += round(S.reagents.get_reagent_amount("pacid")*3) + weedlevel -= rand(1,4) + + // Plant-B-Gone is just as bad + if(S.reagents.has_reagent("plantbgone", 1)) + health -= round(S.reagents.get_reagent_amount("plantbgone")*2) + toxic -= round(S.reagents.get_reagent_amount("plantbgone")*3) + weedlevel -= rand(4,8) + + // Healing + if(S.reagents.has_reagent("cryoxadone", 1)) + health += round(S.reagents.get_reagent_amount("cryoxadone")*3) + toxic -= round(S.reagents.get_reagent_amount("cryoxadone")*3) + + // FINALLY IMPLEMENTED, Ammonia is bad ass. + if(S.reagents.has_reagent("ammonia", 1)) + health += round(S.reagents.get_reagent_amount("ammonia")*0.5) + nutrilevel += round(S.reagents.get_reagent_amount("ammonia")*1) + + // FINALLY IMPLEMENTED, This is more bad ass, and pests get hurt by the corrosive nature of it, not the plant. + if(S.reagents.has_reagent("diethylamine", 1)) + health += round(S.reagents.get_reagent_amount("diethylamine")*1) + nutrilevel += round(S.reagents.get_reagent_amount("diethylamine")*2) + pestlevel -= rand(1,2) + + // Compost, effectively + if(S.reagents.has_reagent("nutriment", 1)) + health += round(S.reagents.get_reagent_amount("nutriment")*0.5) + nutrilevel += round(S.reagents.get_reagent_amount("nutriment")*1) + + // Poor man's mutagen. + if(S.reagents.has_reagent("radium", 1)) + health -= round(S.reagents.get_reagent_amount("radium")*1.5) + toxic += round(S.reagents.get_reagent_amount("radium")*2) + if(S.reagents.has_reagent("radium", 10)) + switch(rand(100)) + if (91 to 100) plantdies() + if (81 to 90) mutatespecie() + if (66 to 80) hardmutate() + if (41 to 65) mutate() to_chat(if (21 to 41) user, "The plants don't seem to react...") - if (11 to 20) mutateweed() - if (1 to 10) mutatepest() + if (11 to 20) mutateweed() + if (1 to 10) mutatepest() to_chat(else user, "Nothing happens...") - - // The best stuff there is. For testing/debugging. - if(S.reagents.has_reagent("adminordrazine", 1)) - waterlevel += round(S.reagents.get_reagent_amount("adminordrazine")*1) - health += round(S.reagents.get_reagent_amount("adminordrazine")*1) - nutrilevel += round(S.reagents.get_reagent_amount("adminordrazine")*1) - pestlevel -= rand(1,5) - weedlevel -= rand(1,5) - if(S.reagents.has_reagent("adminordrazine", 5)) - switch(rand(100)) - if (66 to 100) mutatespecie() - if (33 to 65) mutateweed() - if (1 to 32) mutatepest() + + // The best stuff there is. For testing/debugging. + if(S.reagents.has_reagent("adminordrazine", 1)) + waterlevel += round(S.reagents.get_reagent_amount("adminordrazine")*1) + health += round(S.reagents.get_reagent_amount("adminordrazine")*1) + nutrilevel += round(S.reagents.get_reagent_amount("adminordrazine")*1) + pestlevel -= rand(1,5) + weedlevel -= rand(1,5) + if(S.reagents.has_reagent("adminordrazine", 5)) + switch(rand(100)) + if (66 to 100) mutatespecie() + if (33 to 65) mutateweed() + if (1 to 32) mutatepest() to_chat(else user, "Nothing happens...") - - S.reagents.clear_reagents() - if (weedlevel < 0 ) // The following checks are to prevent the stats from going out of bounds. - weedlevel = 0 - if (health < 0 ) - health = 0 - if (waterlevel > 100 ) - waterlevel = 100 - if (waterlevel < 0 ) - waterlevel = 0 - if (toxic < 0 ) - toxic = 0 - if (toxic > 100 ) - toxic = 100 - if (pestlevel < 0 ) - pestlevel = 0 - if (nutrilevel > 10 ) - nutrilevel = 10 - else + + S.reagents.clear_reagents() + if (weedlevel < 0 ) // The following checks are to prevent the stats from going out of bounds. + weedlevel = 0 + if (health < 0 ) + health = 0 + if (waterlevel > 100 ) + waterlevel = 100 + if (waterlevel < 0 ) + waterlevel = 0 + if (toxic < 0 ) + toxic = 0 + if (toxic > 100 ) + toxic = 100 + if (pestlevel < 0 ) + pestlevel = 0 + if (nutrilevel > 10 ) + nutrilevel = 10 + else to_chat(user, "You can't get any extract out of this plant.") - else + else to_chat(user, "There's nothing to apply the solution into.") - updateicon() - - else if ( istype(O, /obj/item/seeds/) ) - if(!planted) - user.u_equip(O, 0) + updateicon() + + else if ( istype(O, /obj/item/seeds/) ) + if(!planted) + user.u_equip(O, 0) to_chat(user, "You plant the [O.name]") - dead = 0 - myseed = O - planted = 1 - age = 1 - health = myseed.endurance - lastcycle = world.time - O.loc = src - if((user.client && user.s_active != src)) - user.client.screen -= O - O.dropped(user) - updateicon() - if(istype(0, /obj/item/seeds/dionanode)) - var/obj/item/seeds/dionanode/RP = O - if(!RP.source) - RP.request_player() - else + dead = 0 + myseed = O + planted = 1 + age = 1 + health = myseed.endurance + lastcycle = world.time + O.loc = src + if((user.client && user.s_active != src)) + user.client.screen -= O + O.dropped(user) + updateicon() + if(istype(0, /obj/item/seeds/dionanode)) + var/obj/item/seeds/dionanode/RP = O + if(!RP.source) + RP.request_player() + else to_chat(user, "The [src] already has seeds in it!") - - else if (istype(O, /obj/item/device/analyzer/plant_analyzer)) - if(planted && myseed) - to_chat(user, "*** [myseed.plantname] ***")//Carn: now reports the plants growing, not the seeds. + + else if (istype(O, /obj/item/device/analyzer/plant_analyzer)) + if(planted && myseed) + to_chat(user, "*** [myseed.plantname] ***")//Carn: now reports the plants growing, not the seeds. to_chat(user, "-Plant Age: [age]") to_chat(user, "-Plant Endurance: [myseed.endurance]") to_chat(user, "-Plant Lifespan: [myseed.lifespan]") - if(myseed.yield != -1) + if(myseed.yield != -1) to_chat(user, "-Plant Yield: [myseed.yield]") to_chat(user, "-Plant Production: [myseed.production]") - if(myseed.potency != -1) + if(myseed.potency != -1) to_chat(user, "-Plant Potency: [myseed.potency]") to_chat(user, "-Weed level: [weedlevel]/10") to_chat(user, "-Pest level: [pestlevel]/10") @@ -742,7 +742,7 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) to_chat(user, "-Water level: [waterlevel]/100") to_chat(user, "-Nutrition level: [nutrilevel]/10") to_chat(user, "") - else + else to_chat(user, "No plant found.") to_chat(user, "-Weed level: [weedlevel]/10") to_chat(user, "-Pest level: [pestlevel]/10") @@ -750,279 +750,279 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) to_chat(user, "-Water level: [waterlevel]/100") to_chat(user, "-Nutrition level: [nutrilevel]/10") to_chat(user, "") - - else if (istype(O, /obj/item/weapon/reagent_containers/spray/plantbgone)) - if(planted && myseed) - health -= rand(5,20) - - if(pestlevel > 0) - pestlevel -= 2 // Kill kill kill - else - pestlevel = 0 - - if(weedlevel > 0) - weedlevel -= 3 // Kill kill kill - else - weedlevel = 0 - toxic += 4 // Oops - visible_message("\The [src] has been sprayed with \the [O][(user ? " by [user]." : ".")]") - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - updateicon() - - else if (istype(O, /obj/item/weapon/minihoe)) // The minihoe - //var/deweeding - if(weedlevel > 0) - user.visible_message("[user] starts uprooting the weeds.", "You remove the weeds from the [src].") - weedlevel = 0 - updateicon() - src.updateicon() - else + + else if (istype(O, /obj/item/weapon/reagent_containers/spray/plantbgone)) + if(planted && myseed) + health -= rand(5,20) + + if(pestlevel > 0) + pestlevel -= 2 // Kill kill kill + else + pestlevel = 0 + + if(weedlevel > 0) + weedlevel -= 3 // Kill kill kill + else + weedlevel = 0 + toxic += 4 // Oops + visible_message("\The [src] has been sprayed with \the [O][(user ? " by [user]." : ".")]") + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + updateicon() + + else if (istype(O, /obj/item/weapon/minihoe)) // The minihoe + //var/deweeding + if(weedlevel > 0) + user.visible_message("[user] starts uprooting the weeds.", "You remove the weeds from the [src].") + weedlevel = 0 + updateicon() + src.updateicon() + else to_chat(user, "This plot is completely devoid of weeds. It doesn't need uprooting.") - - else if ( istype(O, /obj/item/weapon/weedspray) ) - var/obj/item/weedkiller/myWKiller = O - user.u_equip(O, 1) - toxic += myWKiller.toxicity - weedlevel -= myWKiller.WeedKillStr - if (weedlevel < 0 ) // Make sure it won't go overoboard - weedlevel = 0 - if (toxic > 100 ) // Make sure it won't go overoboard - toxic = 100 + + else if ( istype(O, /obj/item/weapon/weedspray) ) + var/obj/item/weedkiller/myWKiller = O + user.u_equip(O, 1) + toxic += myWKiller.toxicity + weedlevel -= myWKiller.WeedKillStr + if (weedlevel < 0 ) // Make sure it won't go overoboard + weedlevel = 0 + if (toxic > 100 ) // Make sure it won't go overoboard + toxic = 100 to_chat(user, "You apply the weedkiller solution into the [src].") - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - qdel(O) - O = null - updateicon() - - else if (istype(O, /obj/item/weapon/storage/bag/plants)) - attack_hand(user) - var/obj/item/weapon/storage/bag/plants/S = O - for (var/obj/item/weapon/reagent_containers/food/snacks/grown/G in locate(user.x,user.y,user.z)) - if(!S.can_be_inserted(G)) - return - S.handle_item_insertion(G, 1) - - else if ( istype(O, /obj/item/weapon/pestspray) ) - var/obj/item/pestkiller/myPKiller = O - user.u_equip(O,1) - toxic += myPKiller.toxicity - pestlevel -= myPKiller.PestKillStr - if (pestlevel < 0 ) // Make sure it won't go overoboard - pestlevel = 0 - if (toxic > 100 ) // Make sure it won't go overoboard - toxic = 100 + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + qdel(O) + O = null + updateicon() + + else if (istype(O, /obj/item/weapon/storage/bag/plants)) + attack_hand(user) + var/obj/item/weapon/storage/bag/plants/S = O + for (var/obj/item/weapon/reagent_containers/food/snacks/grown/G in locate(user.x,user.y,user.z)) + if(!S.can_be_inserted(G)) + return + S.handle_item_insertion(G, 1) + + else if ( istype(O, /obj/item/weapon/pestspray) ) + var/obj/item/pestkiller/myPKiller = O + user.u_equip(O,1) + toxic += myPKiller.toxicity + pestlevel -= myPKiller.PestKillStr + if (pestlevel < 0 ) // Make sure it won't go overoboard + pestlevel = 0 + if (toxic > 100 ) // Make sure it won't go overoboard + toxic = 100 to_chat(user, "You apply the pestkiller solution into the [src].") - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - qdel(O) - O = null - updateicon() - else if(istype(O, /obj/item/weapon/shovel)) - if(istype(src, /obj/machinery/hydroponics/soil)) + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + qdel(O) + O = null + updateicon() + else if(istype(O, /obj/item/weapon/shovel)) + if(istype(src, /obj/machinery/hydroponics/soil)) to_chat(user, "You clear up the [src]!") - qdel(src) - else if(istype(O, /obj/item/apiary)) - if(planted) + qdel(src) + else if(istype(O, /obj/item/apiary)) + if(planted) to_chat(user, "The hydroponics tray is already occupied!") - else - user.drop_item() - qdel(O) - O = null - - var/obj/machinery/apiary/A = new(src.loc) - A.icon = src.icon - A.icon_state = src.icon_state - A.hydrotray_type = src.type - A.component_parts = component_parts.Copy() - A.contents = contents.Copy() - contents.len = 0 - component_parts.len = 0 - qdel(src) - return - -/obj/machinery/hydroponics/togglePanelOpen(var/obj/toggleitem, mob/user) - if(anchored) + else + user.drop_item() + qdel(O) + O = null + + var/obj/machinery/apiary/A = new(src.loc) + A.icon = src.icon + A.icon_state = src.icon_state + A.hydrotray_type = src.type + A.component_parts = component_parts.Copy() + A.contents = contents.Copy() + contents.len = 0 + component_parts.len = 0 + qdel(src) + return + +/obj/machinery/hydroponics/togglePanelOpen(var/obj/toggleitem, mob/user) + if(anchored) to_chat(user, "\The [src] must be unanchored before you can do that!") - return - ..() - - -/obj/machinery/hydroponics/attack_hand(mob/user as mob) - if(!ishuman(user) && !ismonkey(user)) - return - if(harvest) - if(!user in range(1,src)) - return - myseed.harvest() - else if(dead) - planted = 0 - dead = 0 + return + ..() + + +/obj/machinery/hydroponics/attack_hand(mob/user as mob) + if(!ishuman(user) && !ismonkey(user)) + return + if(harvest) + if(!user in range(1,src)) + return + myseed.harvest() + else if(dead) + planted = 0 + dead = 0 to_chat(usr, text("You remove the dead plant from the [src].")) - qdel(myseed) - myseed = null - updateicon() - else - if(planted && !dead) + qdel(myseed) + myseed = null + updateicon() + else + if(planted && !dead) to_chat(usr, text("The [src] has [myseed.plantname] planted.")) - if(health <= (myseed.endurance / 2)) + if(health <= (myseed.endurance / 2)) to_chat(usr, text("The plant looks unhealthy")) - else + else to_chat(usr, text("The [src] is empty.")) to_chat(usr, text("Water: [waterlevel]/100")) to_chat(usr, text("Nutrient: [nutrilevel]/10")) - if(weedlevel >= 5) // Visual aid for those blind + if(weedlevel >= 5) // Visual aid for those blind to_chat(usr, text("The [src] is filled with weeds!")) - if(pestlevel >= 5) // Visual aid for those blind + if(pestlevel >= 5) // Visual aid for those blind to_chat(usr, text("The [src] is filled with tiny worms!")) - to_chat(usr, text (""))// Empty line for readability. + to_chat(usr, text (""))// Empty line for readability. - -/obj/item/seeds/proc/harvest(mob/user = usr) - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc //for ease of access - var/t_amount = 0 - - while ( t_amount < (yield * parent.yieldmod )) - var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new produce(user.loc, potency) // User gets a consumable - if(!t_prod) return - t_prod.seed = mypath - t_prod.species = species - t_prod.lifespan = lifespan - t_prod.endurance = endurance - t_prod.maturation = maturation - t_prod.production = production - t_prod.yield = yield - t_prod.potency = potency - t_prod.plant_type = plant_type - t_amount++ - - parent.update_tray() - -/obj/item/seeds/grassseed/harvest(mob/user = usr) - var/obj/machinery/hydroponics/parent = loc //for ease of access - var/t_yield = round(yield*parent.yieldmod) - - if(t_yield > 0) - var/obj/item/stack/tile/grass/new_grass = new/obj/item/stack/tile/grass(user.loc) - new_grass.amount = t_yield - - parent.update_tray() - -/obj/item/seeds/gibtomato/harvest(mob/user = usr) - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc //for ease of access - var/t_amount = 0 - - while ( t_amount < (yield * parent.yieldmod )) - var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new produce(user.loc, potency) // User gets a consumable - - t_prod.seed = mypath - t_prod.species = species - t_prod.lifespan = lifespan - t_prod.endurance = endurance - t_prod.maturation = maturation - t_prod.production = production - t_prod.yield = yield - t_prod.potency = potency - t_prod.plant_type = plant_type - t_amount++ - - parent.update_tray() - -/obj/item/seeds/nettleseed/harvest(mob/user = usr) - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc //for ease of access - var/t_amount = 0 - - while ( t_amount < (yield * parent.yieldmod )) - var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) // User gets a consumable -QualityVan - t_prod.seed = mypath - t_prod.species = species - t_prod.lifespan = lifespan - t_prod.endurance = endurance - t_prod.maturation = maturation - t_prod.production = production - t_prod.yield = yield - t_prod.changePotency(potency) // -QualityVan - t_prod.plant_type = plant_type - t_amount++ - - parent.update_tray() - -/obj/item/seeds/deathnettleseed/harvest(mob/user = usr) //isn't a nettle subclass yet, so - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc //for ease of access - var/t_amount = 0 - - while ( t_amount < (yield * parent.yieldmod )) - var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) // User gets a consumable -QualityVan - t_prod.seed = mypath - t_prod.species = species - t_prod.lifespan = lifespan - t_prod.endurance = endurance - t_prod.maturation = maturation - t_prod.production = production - t_prod.yield = yield - t_prod.changePotency(potency) // -QualityVan - t_prod.plant_type = plant_type - t_amount++ - - parent.update_tray() - -/obj/item/seeds/eggyseed/harvest(mob/user = usr) - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc //for ease of access - var/t_amount = 0 - - while ( t_amount < (yield * parent.yieldmod )) - new produce(user.loc) - t_amount++ - - parent.update_tray() - -/obj/machinery/hydroponics/proc/update_tray(mob/user = usr) - harvest = 0 - lastproduce = age - if((yieldmod * myseed.yield) <= 0 || istype(myseed,/obj/item/seeds/dionanode)) + +/obj/item/seeds/proc/harvest(mob/user = usr) + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_amount = 0 + + while ( t_amount < (yield * parent.yieldmod )) + var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new produce(user.loc, potency) // User gets a consumable + if(!t_prod) return + t_prod.seed = mypath + t_prod.species = species + t_prod.lifespan = lifespan + t_prod.endurance = endurance + t_prod.maturation = maturation + t_prod.production = production + t_prod.yield = yield + t_prod.potency = potency + t_prod.plant_type = plant_type + t_amount++ + + parent.update_tray() + +/obj/item/seeds/grassseed/harvest(mob/user = usr) + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_yield = round(yield*parent.yieldmod) + + if(t_yield > 0) + var/obj/item/stack/tile/grass/new_grass = new/obj/item/stack/tile/grass(user.loc) + new_grass.amount = t_yield + + parent.update_tray() + +/obj/item/seeds/gibtomato/harvest(mob/user = usr) + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_amount = 0 + + while ( t_amount < (yield * parent.yieldmod )) + var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new produce(user.loc, potency) // User gets a consumable + + t_prod.seed = mypath + t_prod.species = species + t_prod.lifespan = lifespan + t_prod.endurance = endurance + t_prod.maturation = maturation + t_prod.production = production + t_prod.yield = yield + t_prod.potency = potency + t_prod.plant_type = plant_type + t_amount++ + + parent.update_tray() + +/obj/item/seeds/nettleseed/harvest(mob/user = usr) + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_amount = 0 + + while ( t_amount < (yield * parent.yieldmod )) + var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) // User gets a consumable -QualityVan + t_prod.seed = mypath + t_prod.species = species + t_prod.lifespan = lifespan + t_prod.endurance = endurance + t_prod.maturation = maturation + t_prod.production = production + t_prod.yield = yield + t_prod.changePotency(potency) // -QualityVan + t_prod.plant_type = plant_type + t_amount++ + + parent.update_tray() + +/obj/item/seeds/deathnettleseed/harvest(mob/user = usr) //isn't a nettle subclass yet, so + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_amount = 0 + + while ( t_amount < (yield * parent.yieldmod )) + var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) // User gets a consumable -QualityVan + t_prod.seed = mypath + t_prod.species = species + t_prod.lifespan = lifespan + t_prod.endurance = endurance + t_prod.maturation = maturation + t_prod.production = production + t_prod.yield = yield + t_prod.changePotency(potency) // -QualityVan + t_prod.plant_type = plant_type + t_amount++ + + parent.update_tray() + +/obj/item/seeds/eggyseed/harvest(mob/user = usr) + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_amount = 0 + + while ( t_amount < (yield * parent.yieldmod )) + new produce(user.loc) + t_amount++ + + parent.update_tray() + +/obj/machinery/hydroponics/proc/update_tray(mob/user = usr) + harvest = 0 + lastproduce = age + if((yieldmod * myseed.yield) <= 0 || istype(myseed,/obj/item/seeds/dionanode)) to_chat(user, text("You fail to harvest anything useful.")) - else + else to_chat(user, text("You harvest from the [myseed.plantname].")) - if(myseed.oneharvest) - qdel(myseed) - myseed = null - planted = 0 - dead = 0 - updateicon() - -/////////////////////////////////////////////////////////////////////////////// -/obj/machinery/hydroponics/soil //Not actually hydroponics at all! Honk! - name = "soil" - icon = 'icons/obj/hydroponics.dmi' - icon_state = "soil" - density = 0 - use_power = 0 - - updateicon() // Same as normal but with the overlays removed - Cheridan. - overlays.len = 0 - if(planted) - if(dead) - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-dead") - else if(harvest) - if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") - else - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-harvest") - else if(age < myseed.maturation) - var/t_growthstate = ((age / myseed.maturation) * myseed.growthstages ) - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[round(t_growthstate)]") - lastproduce = age - else - overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") - - if(!luminosity) - if(istype(myseed,/obj/item/seeds/glowshroom)) - SetLuminosity(round(myseed.potency/10)) - else - SetLuminosity(0) - return - -#undef HYDRO_SPEED_MULTIPLIER + if(myseed.oneharvest) + qdel(myseed) + myseed = null + planted = 0 + dead = 0 + updateicon() + +/////////////////////////////////////////////////////////////////////////////// +/obj/machinery/hydroponics/soil //Not actually hydroponics at all! Honk! + name = "soil" + icon = 'icons/obj/hydroponics.dmi' + icon_state = "soil" + density = 0 + use_power = 0 + + updateicon() // Same as normal but with the overlays removed - Cheridan. + overlays.len = 0 + if(planted) + if(dead) + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-dead") + else if(harvest) + if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") + else + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-harvest") + else if(age < myseed.maturation) + var/t_growthstate = ((age / myseed.maturation) * myseed.growthstages ) + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[round(t_growthstate)]") + lastproduce = age + else + overlays += image('icons/obj/hydroponics.dmi', icon_state="[myseed.species]-grow[myseed.growthstages]") + + if(!luminosity) + if(istype(myseed,/obj/item/seeds/glowshroom)) + SetLuminosity(round(myseed.potency/10)) + else + SetLuminosity(0) + return + +#undef HYDRO_SPEED_MULTIPLIER diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index b48a437d070..a9217d9f019 100755 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -1,204 +1,204 @@ -var/global/list/igniters = list() -/obj/machinery/igniter - name = "igniter" - desc = "It's useful for igniting plasma." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "igniter1" - var/id_tag = null - var/on = 1.0 - var/obj/item/device/assembly_holder/assembly=null - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/machinery/igniter/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - 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) - if(..()) - return - add_fingerprint(user) - - use_power(50) - src.on = !( src.on ) - src.icon_state = text("igniter[]", src.on) - return - -/obj/machinery/igniter/process() //ugh why is this even in process()? - if (src.on && !(stat & NOPOWER) ) - var/turf/location = src.loc - if (isturf(location)) - location.hotspot_expose(1000,500,1,surfaces=0) - return 1 - -/obj/machinery/igniter/proc/toggle_state() - use_power(50) - src.on = !( src.on ) - src.icon_state = text("igniter[]", src.on) - return - -/obj/machinery/igniter/New() - ..() - icon_state = "igniter[on]" - igniters += src - -/obj/machinery/igniter/Destroy() - igniters -= src - ..() - -/obj/machinery/igniter/power_change() - if(!( stat & NOPOWER) ) - icon_state = "igniter[src.on]" - else - icon_state = "igniter0" - -/obj/machinery/igniter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool) && src.assembly) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) +var/global/list/igniters = list() +/obj/machinery/igniter + name = "igniter" + desc = "It's useful for igniting plasma." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "igniter1" + var/id_tag = null + var/on = 1.0 + var/obj/item/device/assembly_holder/assembly=null + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/machinery/igniter/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + 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) + if(..()) + return + add_fingerprint(user) + + use_power(50) + src.on = !( src.on ) + src.icon_state = text("igniter[]", src.on) + return + +/obj/machinery/igniter/process() //ugh why is this even in process()? + if (src.on && !(stat & NOPOWER) ) + var/turf/location = src.loc + if (isturf(location)) + location.hotspot_expose(1000,500,1,surfaces=0) + return 1 + +/obj/machinery/igniter/proc/toggle_state() + use_power(50) + src.on = !( src.on ) + src.icon_state = text("igniter[]", src.on) + return + +/obj/machinery/igniter/New() + ..() + icon_state = "igniter[on]" + igniters += src + +/obj/machinery/igniter/Destroy() + igniters -= src + ..() + +/obj/machinery/igniter/power_change() + if(!( stat & NOPOWER) ) + icon_state = "igniter[src.on]" + else + icon_state = "igniter0" + +/obj/machinery/igniter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/weapon/weldingtool) && src.assembly) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) to_chat(user, "You begin to cut \the [src] off the floor...") - if (do_after(user, src, 40)) - user.visible_message( \ - "[user] disassembles \the [src].", \ - "You have disassembled \the [src].", \ - "You hear welding.") - src.assembly.loc=src.loc - qdel(src) - return - else: + if (do_after(user, src, 40)) + user.visible_message( \ + "[user] disassembles \the [src].", \ + "You have disassembled \the [src].", \ + "You hear welding.") + src.assembly.loc=src.loc + qdel(src) + return + else: to_chat(user, "You need more welder fuel to do that.") - return 1 - - -// Wall mounted remote-control igniter. - -/obj/machinery/sparker - name = "Mounted igniter" - desc = "A wall-mounted ignition device." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "migniter" - var/id_tag = null - var/disable = 0 - var/last_spark = 0 - var/base_state = "migniter" - anchored = 1 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/machinery/sparker/New() - ..() - igniters += src - -/obj/machinery/sparker/Destroy() - igniters -= src - ..() - -/obj/machinery/sparker/power_change() - if ( powered() && disable == 0 ) - stat &= ~NOPOWER - icon_state = "[base_state]" -// src.sd_SetLuminosity(2) - else - stat |= ~NOPOWER - icon_state = "[base_state]-p" -// src.sd_SetLuminosity(0) - -/obj/machinery/sparker/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/device/detective_scanner)) - return - if (istype(W, /obj/item/weapon/screwdriver)) - add_fingerprint(user) - src.disable = !src.disable - if (src.disable) - user.visible_message("[user] has disabled the [src]!", "You disable the connection to the [src].") - icon_state = "[base_state]-d" - if (!src.disable) - user.visible_message("[user] has reconnected the [src]!", "You fix the connection to the [src].") - if(src.powered()) - icon_state = "[base_state]" - else - icon_state = "[base_state]-p" - -/obj/machinery/sparker/attack_ai() - if (src.anchored) - return src.spark() - else - return - -/obj/machinery/sparker/proc/spark() - if (!(powered())) - return - - if ((src.disable) || (src.last_spark && world.time < src.last_spark + 50)) - return - - - flick("[base_state]-spark", src) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - src.last_spark = world.time - use_power(1000) - var/turf/location = src.loc - if (isturf(location)) - location.hotspot_expose(1000,500,1,surfaces=1) - return 1 - -/obj/machinery/sparker/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - spark() - ..(severity) - -/obj/machinery/ignition_switch/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/ignition_switch/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/ignition_switch/attack_hand(mob/user as mob) - - if(stat & (NOPOWER|BROKEN)) - return - if(active) - return - - use_power(5) - - active = 1 - icon_state = "launcheract" - - for(var/obj/machinery/sparker/M in igniters) - if (M.id_tag == src.id_tag) - spawn( 0 ) - M.spark() - - for(var/obj/machinery/igniter/M in igniters) - if(M.id_tag == src.id_tag) - use_power(50) - M.on = !( M.on ) - M.icon_state = text("igniter[]", M.on) - - sleep(50) - - icon_state = "launcherbtt" - active = 0 - - return + return 1 + + +// Wall mounted remote-control igniter. + +/obj/machinery/sparker + name = "Mounted igniter" + desc = "A wall-mounted ignition device." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "migniter" + var/id_tag = null + var/disable = 0 + var/last_spark = 0 + var/base_state = "migniter" + anchored = 1 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/machinery/sparker/New() + ..() + igniters += src + +/obj/machinery/sparker/Destroy() + igniters -= src + ..() + +/obj/machinery/sparker/power_change() + if ( powered() && disable == 0 ) + stat &= ~NOPOWER + icon_state = "[base_state]" +// src.sd_SetLuminosity(2) + else + stat |= ~NOPOWER + icon_state = "[base_state]-p" +// src.sd_SetLuminosity(0) + +/obj/machinery/sparker/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/device/detective_scanner)) + return + if (istype(W, /obj/item/weapon/screwdriver)) + add_fingerprint(user) + src.disable = !src.disable + if (src.disable) + user.visible_message("[user] has disabled the [src]!", "You disable the connection to the [src].") + icon_state = "[base_state]-d" + if (!src.disable) + user.visible_message("[user] has reconnected the [src]!", "You fix the connection to the [src].") + if(src.powered()) + icon_state = "[base_state]" + else + icon_state = "[base_state]-p" + +/obj/machinery/sparker/attack_ai() + if (src.anchored) + return src.spark() + else + return + +/obj/machinery/sparker/proc/spark() + if (!(powered())) + return + + if ((src.disable) || (src.last_spark && world.time < src.last_spark + 50)) + return + + + flick("[base_state]-spark", src) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + src.last_spark = world.time + use_power(1000) + var/turf/location = src.loc + if (isturf(location)) + location.hotspot_expose(1000,500,1,surfaces=1) + return 1 + +/obj/machinery/sparker/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + spark() + ..(severity) + +/obj/machinery/ignition_switch/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/ignition_switch/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/ignition_switch/attack_hand(mob/user as mob) + + if(stat & (NOPOWER|BROKEN)) + return + if(active) + return + + use_power(5) + + active = 1 + icon_state = "launcheract" + + for(var/obj/machinery/sparker/M in igniters) + if (M.id_tag == src.id_tag) + spawn( 0 ) + M.spark() + + for(var/obj/machinery/igniter/M in igniters) + if(M.id_tag == src.id_tag) + use_power(50) + M.on = !( M.on ) + M.icon_state = text("igniter[]", M.on) + + sleep(50) + + icon_state = "launcherbtt" + active = 0 + + return diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 33784af14df..ddcdb6a453d 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -1,179 +1,179 @@ -/obj/machinery/iv_drip - name = "\improper IV drip" - icon = 'icons/obj/iv_drip.dmi' - anchored = 0 - density = 0 //Tired of these blocking up the station - - -/obj/machinery/iv_drip/var/mob/living/carbon/human/attached = null -/obj/machinery/iv_drip/var/mode = 1 // 1 is injecting, 0 is taking blood. -/obj/machinery/iv_drip/var/obj/item/weapon/reagent_containers/beaker = null - -/obj/machinery/iv_drip/update_icon() - if(src.attached) - icon_state = "hooked" - else - icon_state = "" - - overlays = null - - if(beaker) - var/datum/reagents/reagents = beaker.reagents - if(reagents.total_volume) - var/image/filling = image('icons/obj/iv_drip.dmi', src, "reagent") - - var/percent = round((reagents.total_volume / beaker.volume) * 100) - switch(percent) - if(0 to 9) filling.icon_state = "reagent0" - if(10 to 24) filling.icon_state = "reagent10" - if(25 to 49) filling.icon_state = "reagent25" - if(50 to 74) filling.icon_state = "reagent50" - if(75 to 79) filling.icon_state = "reagent75" - if(80 to 90) filling.icon_state = "reagent80" - if(91 to INFINITY) filling.icon_state = "reagent100" - - filling.icon += mix_color_from_reagents(reagents.reagent_list) - overlays += filling - -/obj/machinery/iv_drip/MouseDrop(over_object, src_location, over_location) - ..() - if(isobserver(usr)) return - if(usr.stat) // Stop interacting with shit while dead pls - return - if(isanimal(usr)) - return - if(attached) - visible_message("[src.attached] is detached from \the [src]") - src.attached = null - src.update_icon() - return - - if(in_range(src, usr) && ishuman(over_object) && get_dist(over_object, src) <= 1) - var/mob/living/carbon/human/H = over_object - if(H.species && (H.species.chem_flags & NO_INJECT)) - H.visible_message("[usr] struggles to place the IV into [H] but fails.","[usr] tries to place the IV into your arm but is unable to.") - return - visible_message("[usr] attaches \the [src] to \the [over_object].") - src.attached = over_object - src.update_icon() - -/obj/machinery/iv_drip/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isobserver(user)) return - if(user.stat) - return - if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,get_turf(src)) - M.amount = 2 - if(src.beaker) - src.beaker.loc = get_turf(src) - src.beaker = null - to_chat(user, "You dismantle \the [name].") - qdel(src) - if (istype(W, /obj/item/weapon/reagent_containers)) - if(!isnull(src.beaker)) - to_chat(user, "There is already a reagent container loaded!") - return - - if(user.drop_item(W, src)) - src.beaker = W - to_chat(user, "You attach \the [W] to \the [src].") - src.update_icon() - return - else - return ..() - - -/obj/machinery/iv_drip/process() - //set background = 1 - - if(src.attached) - if(!(get_dist(src, src.attached) <= 1 && isturf(src.attached.loc))) - visible_message("The needle is ripped out of [src.attached], doesn't that hurt?") - src.attached:apply_damage(3, BRUTE, pick("r_arm", "l_arm")) - src.attached = null - src.update_icon() - return - - if(src.attached && src.beaker) - // Give blood - if(mode) - if(src.beaker.volume > 0) - var/transfer_amount = REAGENTS_METABOLISM - if(beaker.reagents.reagent_list.len == 1 && beaker.reagents.has_reagent("blood")) - // speed up transfer if the container has ONLY blood - transfer_amount = 4 - src.beaker.reagents.trans_to(src.attached, transfer_amount) - update_icon() - - // Take blood - else - var/amount = beaker.reagents.maximum_volume - beaker.reagents.total_volume - amount = min(amount, 4) - // If the beaker is full, ping - if(amount == 0) - if(prob(5)) visible_message("\The [src] pings.") - return - - var/mob/living/carbon/human/T = attached - - if(!istype(T)) return - if(!T.dna) - return - if(M_NOCLONE in T.mutations) - return - - // If the human is losing too much blood, beep. - if(T.vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE) if(prob(5)) - visible_message("\The [src] beeps loudly.") - - var/datum/reagent/B = T.take_blood(beaker,amount) - - if (B) - beaker.reagents.reagent_list |= B - beaker.reagents.update_total() - beaker.on_reagent_change() - beaker.reagents.handle_reactions() - update_icon() - -/obj/machinery/iv_drip/attack_hand(mob/user as mob) - if(isobserver(usr) || user.stat) - return - if(attached) - visible_message("[src.attached] is detached from \the [src].") - src.attached = null - src.update_icon() - else if(src.beaker) - src.beaker.loc = get_turf(src) - src.beaker = null - update_icon() - else - return ..() - - -/obj/machinery/iv_drip/verb/toggle_mode() - set name = "Toggle Mode" - set category = "Object" - set src in view(1) - - if(!istype(usr, /mob/living)) - to_chat(usr, "You can't do that.") - return - - if(usr.isUnconscious()) - return - - mode = !mode - to_chat(usr, "The [src] is now [mode ? "injecting" : "taking blood"].") - -/obj/machinery/iv_drip/examine(mob/user) - ..() - to_chat(user, "The [src] is [mode ? "injecting" : "taking blood"].") - if(beaker) - if(beaker.reagents && beaker.reagents.reagent_list.len) - to_chat(user, "Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.") - else - to_chat(user, "Attached is \an empty [beaker].") - else - to_chat(user, "No chemicals are attached.") - to_chat(user, "It is attached to [attached ? attached : "no one"].") +/obj/machinery/iv_drip + name = "\improper IV drip" + icon = 'icons/obj/iv_drip.dmi' + anchored = 0 + density = 0 //Tired of these blocking up the station + + +/obj/machinery/iv_drip/var/mob/living/carbon/human/attached = null +/obj/machinery/iv_drip/var/mode = 1 // 1 is injecting, 0 is taking blood. +/obj/machinery/iv_drip/var/obj/item/weapon/reagent_containers/beaker = null + +/obj/machinery/iv_drip/update_icon() + if(src.attached) + icon_state = "hooked" + else + icon_state = "" + + overlays = null + + if(beaker) + var/datum/reagents/reagents = beaker.reagents + if(reagents.total_volume) + var/image/filling = image('icons/obj/iv_drip.dmi', src, "reagent") + + var/percent = round((reagents.total_volume / beaker.volume) * 100) + switch(percent) + if(0 to 9) filling.icon_state = "reagent0" + if(10 to 24) filling.icon_state = "reagent10" + if(25 to 49) filling.icon_state = "reagent25" + if(50 to 74) filling.icon_state = "reagent50" + if(75 to 79) filling.icon_state = "reagent75" + if(80 to 90) filling.icon_state = "reagent80" + if(91 to INFINITY) filling.icon_state = "reagent100" + + filling.icon += mix_color_from_reagents(reagents.reagent_list) + overlays += filling + +/obj/machinery/iv_drip/MouseDrop(over_object, src_location, over_location) + ..() + if(isobserver(usr)) return + if(usr.stat) // Stop interacting with shit while dead pls + return + if(isanimal(usr)) + return + if(attached) + visible_message("[src.attached] is detached from \the [src]") + src.attached = null + src.update_icon() + return + + if(in_range(src, usr) && ishuman(over_object) && get_dist(over_object, src) <= 1) + var/mob/living/carbon/human/H = over_object + if(H.species && (H.species.chem_flags & NO_INJECT)) + H.visible_message("[usr] struggles to place the IV into [H] but fails.","[usr] tries to place the IV into your arm but is unable to.") + return + visible_message("[usr] attaches \the [src] to \the [over_object].") + src.attached = over_object + src.update_icon() + +/obj/machinery/iv_drip/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isobserver(user)) return + if(user.stat) + return + if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,get_turf(src)) + M.amount = 2 + if(src.beaker) + src.beaker.loc = get_turf(src) + src.beaker = null + to_chat(user, "You dismantle \the [name].") + qdel(src) + if (istype(W, /obj/item/weapon/reagent_containers)) + if(!isnull(src.beaker)) + to_chat(user, "There is already a reagent container loaded!") + return + + if(user.drop_item(W, src)) + src.beaker = W + to_chat(user, "You attach \the [W] to \the [src].") + src.update_icon() + return + else + return ..() + + +/obj/machinery/iv_drip/process() + //set background = 1 + + if(src.attached) + if(!(get_dist(src, src.attached) <= 1 && isturf(src.attached.loc))) + visible_message("The needle is ripped out of [src.attached], doesn't that hurt?") + src.attached:apply_damage(3, BRUTE, pick("r_arm", "l_arm")) + src.attached = null + src.update_icon() + return + + if(src.attached && src.beaker) + // Give blood + if(mode) + if(src.beaker.volume > 0) + var/transfer_amount = REAGENTS_METABOLISM + if(beaker.reagents.reagent_list.len == 1 && beaker.reagents.has_reagent("blood")) + // speed up transfer if the container has ONLY blood + transfer_amount = 4 + src.beaker.reagents.trans_to(src.attached, transfer_amount) + update_icon() + + // Take blood + else + var/amount = beaker.reagents.maximum_volume - beaker.reagents.total_volume + amount = min(amount, 4) + // If the beaker is full, ping + if(amount == 0) + if(prob(5)) visible_message("\The [src] pings.") + return + + var/mob/living/carbon/human/T = attached + + if(!istype(T)) return + if(!T.dna) + return + if(M_NOCLONE in T.mutations) + return + + // If the human is losing too much blood, beep. + if(T.vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE) if(prob(5)) + visible_message("\The [src] beeps loudly.") + + var/datum/reagent/B = T.take_blood(beaker,amount) + + if (B) + beaker.reagents.reagent_list |= B + beaker.reagents.update_total() + beaker.on_reagent_change() + beaker.reagents.handle_reactions() + update_icon() + +/obj/machinery/iv_drip/attack_hand(mob/user as mob) + if(isobserver(usr) || user.stat) + return + if(attached) + visible_message("[src.attached] is detached from \the [src].") + src.attached = null + src.update_icon() + else if(src.beaker) + src.beaker.loc = get_turf(src) + src.beaker = null + update_icon() + else + return ..() + + +/obj/machinery/iv_drip/verb/toggle_mode() + set name = "Toggle Mode" + set category = "Object" + set src in view(1) + + if(!istype(usr, /mob/living)) + to_chat(usr, "You can't do that.") + return + + if(usr.isUnconscious()) + return + + mode = !mode + to_chat(usr, "The [src] is now [mode ? "injecting" : "taking blood"].") + +/obj/machinery/iv_drip/examine(mob/user) + ..() + to_chat(user, "The [src] is [mode ? "injecting" : "taking blood"].") + if(beaker) + if(beaker.reagents && beaker.reagents.reagent_list.len) + to_chat(user, "Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.") + else + to_chat(user, "Attached is \an empty [beaker].") + else + to_chat(user, "No chemicals are attached.") + to_chat(user, "It is attached to [attached ? attached : "no one"].") diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 14b90ada50e..8e21a7178de 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -1,365 +1,365 @@ - -/obj/machinery/gibber - name = "Gibber" - desc = "The name isn't descriptive enough?" - icon = 'icons/obj/kitchen.dmi' - icon_state = "grinder" - density = 1 - anchored = 1 - var/operating = 0 //Is it on? - var/dirty = 0 // Does it need cleaning? - var/gibtime = 40 // Time from starting until meat appears - var/mob/living/occupant // Mob who has been put inside - var/opened = 0.0 - use_power = 1 - idle_power_usage = 20 - active_power_usage = 500 - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -obj/machinery/gibber/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/gibber, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser/high, - /obj/item/weapon/stock_parts/micro_laser/high, - /obj/item/weapon/stock_parts/micro_laser/high, - /obj/item/weapon/stock_parts/micro_laser/high - ) - - RefreshParts() - -/obj/machinery/gibber/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(operating) - to_chat(user, "[src] is currently gibbing something!") - return - - ..() - if(istype(O,/obj/item/weapon/grab)) - return handleGrab(O,user) - else - to_chat(user, "This item is not suitable for the gibber!") - -//auto-gibs anything that bumps into it -/obj/machinery/gibber/autogibber - var/list/allowedTypes=list( - /mob/living/carbon/human, - /mob/living/carbon/alien, - /mob/living/carbon/monkey, - /mob/living/simple_animal/corgi - ) - var/turf/input_plate - - New() - ..() - spawn(5) - for(var/i in cardinal) - var/obj/machinery/mineral/input/input_obj = locate( /obj/machinery/mineral/input, get_step(src.loc, i) ) - if(input_obj) - if(isturf(input_obj.loc)) - input_plate = input_obj.loc - qdel(input_obj) - break - - if(!input_plate) - diary << "a [src] didn't find an input plate." - return - -/obj/machinery/gibber/autogibber/process() - if(!input_plate) return - if(stat & (BROKEN | NOPOWER)) - return - use_power(100) - - var/affecting = input_plate.contents // moved items will be all in loc - spawn(1) // slight delay to prevent infinite propagation due to map order //TODO: please no spawn() in process(). It's a very bad idea - for(var/atom/movable/A in affecting) - if(ismob(A)) - var/mob/M = A - - if(M.loc == input_plate) - //var/found=0 - for(var/t in allowedTypes) - if(istype(M,t)) - //found=1 - M.loc = src - startautogibbing(M) - break - - -/obj/machinery/gibber/New() - ..() - src.overlays += image('icons/obj/kitchen.dmi', "grjam") - -/obj/machinery/gibber/update_icon() - overlays.len = 0 - if (dirty) - src.overlays += image('icons/obj/kitchen.dmi', "grbloody") - if(stat & (NOPOWER|BROKEN)) - return - if (!occupant) - src.overlays += image('icons/obj/kitchen.dmi', "grjam") - else if (operating) - src.overlays += image('icons/obj/kitchen.dmi', "gruse") - else - src.overlays += image('icons/obj/kitchen.dmi', "gridle") - -/obj/machinery/gibber/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/gibber/relaymove(mob/user as mob) - src.go_out() - return - -/obj/machinery/gibber/attack_hand(mob/user as mob) - if(stat & (NOPOWER|BROKEN)) - return - if(!anchored) - to_chat(user, "[src] must be anchored first!") - return - if(operating) - to_chat(user, "[src] is locked and running") - return - if(!(src.occupant)) - to_chat(user, "[src] is empty!") - return - else - src.startgibbing(user) - -// OLD /obj/machinery/gibber/attackby(obj/item/weapon/grab/G as obj, mob/user as mob) -/obj/machinery/gibber/proc/handleGrab(obj/item/weapon/grab/G as obj, mob/user as mob) - if(!anchored) - to_chat(user, "[src] must be anchored first!") - return - if(src.occupant) - to_chat(user, "[src] is full! Empty it first.") - return - if (!( istype(G, /obj/item/weapon/grab)) || !(istype(G.affecting, /mob/living/carbon/human))) - to_chat(user, "This item is not suitable for [src]!") - return - if(G.affecting.abiotic(1)) - to_chat(user, "Subject may not have abiotic items on.") - return - - user.visible_message("[user] starts to put [G.affecting] into the gibber!", \ - drugged_message = "[user] starts dancing with [G.affecting] near the gibber!") - src.add_fingerprint(user) - if(do_after(user, src, 30) && G && G.affecting && !occupant) - user.visible_message("[user] stuffs [G.affecting] into the gibber!", \ - drugged_message = "[G.affecting] suddenly disappears! How did he do that?") - var/mob/M = G.affecting - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.loc = src - src.occupant = M - returnToPool(G) - update_icon() - -/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user) - if(target != user || !istype(user, /mob/living/carbon/human) || user.stat || user.weakened || user.stunned || user.paralysis || user.locked_to || get_dist(user, src) > 1) - return - if(!anchored) - to_chat(user, "[src] must be anchored first!") - return - if(src.occupant) - to_chat(user, "[src] is full! Empty it first.") - return - if(user.abiotic(1)) - to_chat(user, "Subject may not have abiotic items on.") - return - - src.add_fingerprint(user) - - user.visible_message("[user] starts climbing into the [src].", \ - "You start climbing into the [src].", \ - drugged_message = "[user] starts dancing like a ballerina!") - - if(do_after(user, src, 30) && user && !occupant && !isnull(src.loc)) - - user.visible_message("[user] climbs into the [src]", \ - "You climb into the [src].", \ - drugged_message = "[src] consumes [user]!") - - if(user.client) - user.client.perspective = EYE_PERSPECTIVE - user.client.eye = src - user.loc = src - src.occupant = user - update_icon() - -/obj/machinery/gibber/verb/eject() - set category = "Object" - set name = "Empty Gibber" - set src in oview(1) - - if (usr.isUnconscious()) - return - src.go_out() - add_fingerprint(usr) - return - -/obj/machinery/gibber/proc/go_out() - if (!src.occupant) - return - for (var/atom/movable/x in src.contents) - if(x in component_parts) - continue - x.forceMove(src.loc) - if (src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.loc = src.loc - src.occupant = null - update_icon() - return - - -/obj/machinery/gibber/proc/startgibbing(mob/user as mob) - if(src.operating) - return - if(!src.occupant) - visible_message("You hear a loud metallic grinding sound.", \ - drugged_message = "You fainly hear a guitar solo.") - return - use_power(1000) - visible_message("You hear a loud squelchy grinding sound.", \ - drugged_message = "You hear a band performance.") - src.operating = 1 - update_icon() - var/sourcename = src.occupant.real_name - var/sourcejob = src.occupant.job - var/sourcenutriment = src.occupant.nutrition / 15 - var/sourcetotalreagents - - if(src.occupant.reagents) - sourcetotalreagents = src.occupant.reagents.total_volume - - var/totalslabs = src.occupant.size - - var/obj/item/weapon/reagent_containers/food/snacks/meat/human/allmeat[totalslabs] - for (var/i=1 to totalslabs) - var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new - newmeat.name = sourcename + newmeat.name - newmeat.subjectname = sourcename - newmeat.subjectjob = sourcejob - newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first - - if(src.occupant.reagents) - src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the - - allmeat[i] = newmeat - - src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [key_name(user)]" //One shall not simply gib a mob unnoticed! - user.attack_log += "\[[time_stamp()]\] Gibbed [key_name(src.occupant)]" - log_attack("[key_name(user)] gibbed [key_name(src.occupant)]") - - if(!iscarbon(user)) - src.occupant.LAssailant = null - else - src.occupant.LAssailant = user - - src.occupant.death(1) - src.occupant.ghostize() - - qdel(src.occupant) - src.occupant = null - - spawn(src.gibtime) - operating = 0 - for (var/i=1 to totalslabs) - var/obj/item/meatslab = allmeat[i] - var/turf/Tx = locate(src.x - i, src.y, src.z) - meatslab.loc = src.loc - meatslab.throw_at(Tx,i,3) - if (!Tx.density) - var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx) - O.New(Tx,i) - src.operating = 0 - update_icon() - -/obj/machinery/gibber/proc/startautogibbing(mob/living/victim as mob) - if(src.operating) - return - if(!victim) - visible_message("You hear a loud metallic grinding sound.", \ - drugged_message = "You fainly hear a guitar solo.") - return - use_power(1000) - visible_message("You hear a loud squelchy grinding sound.", \ - drugged_message = "You hear a band performance.") - src.operating = 1 - update_icon() - var/sourcename = victim.real_name - var/sourcejob = victim.job - var/sourcenutriment = victim.nutrition / 15 - var/sourcetotalreagents - if(victim.reagents) - sourcetotalreagents = victim.reagents.total_volume - - var/totalslabs = victim.size - - var/obj/item/weapon/reagent_containers/food/snacks/meat/allmeat[totalslabs] - for (var/i=1 to totalslabs) - var/obj/item/weapon/reagent_containers/food/snacks/meat/newmeat = null - if(istype(victim, /mob/living/carbon/human)) - var/obj/item/weapon/reagent_containers/food/snacks/meat/human/human_meat = new - human_meat.name = sourcename + newmeat.name - human_meat.subjectname = sourcename - human_meat.subjectjob = sourcejob - - newmeat = human_meat - else - newmeat = victim.drop_meat(src) - - if(newmeat==null) - return - newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first - - if(victim.reagents) - victim.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the - - allmeat[i] = newmeat - - victim.attack_log += "\[[time_stamp()]\] Was auto-gibbed by [src]" //One shall not simply gib a mob unnoticed! - log_attack("[src] auto-gibbed [key_name(victim)]") - victim.death(1) - if(ishuman(victim) || ismonkey(victim) || isalien(victim)) - var/obj/item/organ/brain/B = new(src.loc) - B.transfer_identity(victim) - var/turf/Tx = locate(src.x - 2, src.y, src.z) - B.loc = src.loc - B.throw_at(Tx,2,3) - if(isalien(victim)) - var/obj/effect/decal/cleanable/blood/gibs/xeno/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs/xeno, Tx) - O.New(Tx,2) - else - var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx) - O.New(Tx,2) - qdel(victim) - spawn(src.gibtime) - playsound(get_turf(src), 'sound/effects/gib2.ogg', 50, 1) - operating = 0 - for (var/i=1 to totalslabs) - var/obj/item/meatslab = allmeat[i] - var/turf/Tx = locate(src.x - i, src.y, src.z) - meatslab.loc = src.loc - meatslab.throw_at(Tx,i,3) - if (!Tx.density) - var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx) - O.New(Tx,i) - src.operating = 0 - update_icon() + +/obj/machinery/gibber + name = "Gibber" + desc = "The name isn't descriptive enough?" + icon = 'icons/obj/kitchen.dmi' + icon_state = "grinder" + density = 1 + anchored = 1 + var/operating = 0 //Is it on? + var/dirty = 0 // Does it need cleaning? + var/gibtime = 40 // Time from starting until meat appears + var/mob/living/occupant // Mob who has been put inside + var/opened = 0.0 + use_power = 1 + idle_power_usage = 20 + active_power_usage = 500 + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +obj/machinery/gibber/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/gibber, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser/high, + /obj/item/weapon/stock_parts/micro_laser/high, + /obj/item/weapon/stock_parts/micro_laser/high, + /obj/item/weapon/stock_parts/micro_laser/high + ) + + RefreshParts() + +/obj/machinery/gibber/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(operating) + to_chat(user, "[src] is currently gibbing something!") + return + + ..() + if(istype(O,/obj/item/weapon/grab)) + return handleGrab(O,user) + else + to_chat(user, "This item is not suitable for the gibber!") + +//auto-gibs anything that bumps into it +/obj/machinery/gibber/autogibber + var/list/allowedTypes=list( + /mob/living/carbon/human, + /mob/living/carbon/alien, + /mob/living/carbon/monkey, + /mob/living/simple_animal/corgi + ) + var/turf/input_plate + + New() + ..() + spawn(5) + for(var/i in cardinal) + var/obj/machinery/mineral/input/input_obj = locate( /obj/machinery/mineral/input, get_step(src.loc, i) ) + if(input_obj) + if(isturf(input_obj.loc)) + input_plate = input_obj.loc + qdel(input_obj) + break + + if(!input_plate) + diary << "a [src] didn't find an input plate." + return + +/obj/machinery/gibber/autogibber/process() + if(!input_plate) return + if(stat & (BROKEN | NOPOWER)) + return + use_power(100) + + var/affecting = input_plate.contents // moved items will be all in loc + spawn(1) // slight delay to prevent infinite propagation due to map order //TODO: please no spawn() in process(). It's a very bad idea + for(var/atom/movable/A in affecting) + if(ismob(A)) + var/mob/M = A + + if(M.loc == input_plate) + //var/found=0 + for(var/t in allowedTypes) + if(istype(M,t)) + //found=1 + M.loc = src + startautogibbing(M) + break + + +/obj/machinery/gibber/New() + ..() + src.overlays += image('icons/obj/kitchen.dmi', "grjam") + +/obj/machinery/gibber/update_icon() + overlays.len = 0 + if (dirty) + src.overlays += image('icons/obj/kitchen.dmi', "grbloody") + if(stat & (NOPOWER|BROKEN)) + return + if (!occupant) + src.overlays += image('icons/obj/kitchen.dmi', "grjam") + else if (operating) + src.overlays += image('icons/obj/kitchen.dmi', "gruse") + else + src.overlays += image('icons/obj/kitchen.dmi', "gridle") + +/obj/machinery/gibber/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/gibber/relaymove(mob/user as mob) + src.go_out() + return + +/obj/machinery/gibber/attack_hand(mob/user as mob) + if(stat & (NOPOWER|BROKEN)) + return + if(!anchored) + to_chat(user, "[src] must be anchored first!") + return + if(operating) + to_chat(user, "[src] is locked and running") + return + if(!(src.occupant)) + to_chat(user, "[src] is empty!") + return + else + src.startgibbing(user) + +// OLD /obj/machinery/gibber/attackby(obj/item/weapon/grab/G as obj, mob/user as mob) +/obj/machinery/gibber/proc/handleGrab(obj/item/weapon/grab/G as obj, mob/user as mob) + if(!anchored) + to_chat(user, "[src] must be anchored first!") + return + if(src.occupant) + to_chat(user, "[src] is full! Empty it first.") + return + if (!( istype(G, /obj/item/weapon/grab)) || !(istype(G.affecting, /mob/living/carbon/human))) + to_chat(user, "This item is not suitable for [src]!") + return + if(G.affecting.abiotic(1)) + to_chat(user, "Subject may not have abiotic items on.") + return + + user.visible_message("[user] starts to put [G.affecting] into the gibber!", \ + drugged_message = "[user] starts dancing with [G.affecting] near the gibber!") + src.add_fingerprint(user) + if(do_after(user, src, 30) && G && G.affecting && !occupant) + user.visible_message("[user] stuffs [G.affecting] into the gibber!", \ + drugged_message = "[G.affecting] suddenly disappears! How did he do that?") + var/mob/M = G.affecting + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + src.occupant = M + returnToPool(G) + update_icon() + +/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user) + if(target != user || !istype(user, /mob/living/carbon/human) || user.stat || user.weakened || user.stunned || user.paralysis || user.locked_to || get_dist(user, src) > 1) + return + if(!anchored) + to_chat(user, "[src] must be anchored first!") + return + if(src.occupant) + to_chat(user, "[src] is full! Empty it first.") + return + if(user.abiotic(1)) + to_chat(user, "Subject may not have abiotic items on.") + return + + src.add_fingerprint(user) + + user.visible_message("[user] starts climbing into the [src].", \ + "You start climbing into the [src].", \ + drugged_message = "[user] starts dancing like a ballerina!") + + if(do_after(user, src, 30) && user && !occupant && !isnull(src.loc)) + + user.visible_message("[user] climbs into the [src]", \ + "You climb into the [src].", \ + drugged_message = "[src] consumes [user]!") + + if(user.client) + user.client.perspective = EYE_PERSPECTIVE + user.client.eye = src + user.loc = src + src.occupant = user + update_icon() + +/obj/machinery/gibber/verb/eject() + set category = "Object" + set name = "Empty Gibber" + set src in oview(1) + + if (usr.isUnconscious()) + return + src.go_out() + add_fingerprint(usr) + return + +/obj/machinery/gibber/proc/go_out() + if (!src.occupant) + return + for (var/atom/movable/x in src.contents) + if(x in component_parts) + continue + x.forceMove(src.loc) + if (src.occupant.client) + src.occupant.client.eye = src.occupant.client.mob + src.occupant.client.perspective = MOB_PERSPECTIVE + src.occupant.loc = src.loc + src.occupant = null + update_icon() + return + + +/obj/machinery/gibber/proc/startgibbing(mob/user as mob) + if(src.operating) + return + if(!src.occupant) + visible_message("You hear a loud metallic grinding sound.", \ + drugged_message = "You fainly hear a guitar solo.") + return + use_power(1000) + visible_message("You hear a loud squelchy grinding sound.", \ + drugged_message = "You hear a band performance.") + src.operating = 1 + update_icon() + var/sourcename = src.occupant.real_name + var/sourcejob = src.occupant.job + var/sourcenutriment = src.occupant.nutrition / 15 + var/sourcetotalreagents + + if(src.occupant.reagents) + sourcetotalreagents = src.occupant.reagents.total_volume + + var/totalslabs = src.occupant.size + + var/obj/item/weapon/reagent_containers/food/snacks/meat/human/allmeat[totalslabs] + for (var/i=1 to totalslabs) + var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new + newmeat.name = sourcename + newmeat.name + newmeat.subjectname = sourcename + newmeat.subjectjob = sourcejob + newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first + + if(src.occupant.reagents) + src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the + + allmeat[i] = newmeat + + src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [key_name(user)]" //One shall not simply gib a mob unnoticed! + user.attack_log += "\[[time_stamp()]\] Gibbed [key_name(src.occupant)]" + log_attack("[key_name(user)] gibbed [key_name(src.occupant)]") + + if(!iscarbon(user)) + src.occupant.LAssailant = null + else + src.occupant.LAssailant = user + + src.occupant.death(1) + src.occupant.ghostize() + + qdel(src.occupant) + src.occupant = null + + spawn(src.gibtime) + operating = 0 + for (var/i=1 to totalslabs) + var/obj/item/meatslab = allmeat[i] + var/turf/Tx = locate(src.x - i, src.y, src.z) + meatslab.loc = src.loc + meatslab.throw_at(Tx,i,3) + if (!Tx.density) + var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx) + O.New(Tx,i) + src.operating = 0 + update_icon() + +/obj/machinery/gibber/proc/startautogibbing(mob/living/victim as mob) + if(src.operating) + return + if(!victim) + visible_message("You hear a loud metallic grinding sound.", \ + drugged_message = "You fainly hear a guitar solo.") + return + use_power(1000) + visible_message("You hear a loud squelchy grinding sound.", \ + drugged_message = "You hear a band performance.") + src.operating = 1 + update_icon() + var/sourcename = victim.real_name + var/sourcejob = victim.job + var/sourcenutriment = victim.nutrition / 15 + var/sourcetotalreagents + if(victim.reagents) + sourcetotalreagents = victim.reagents.total_volume + + var/totalslabs = victim.size + + var/obj/item/weapon/reagent_containers/food/snacks/meat/allmeat[totalslabs] + for (var/i=1 to totalslabs) + var/obj/item/weapon/reagent_containers/food/snacks/meat/newmeat = null + if(istype(victim, /mob/living/carbon/human)) + var/obj/item/weapon/reagent_containers/food/snacks/meat/human/human_meat = new + human_meat.name = sourcename + newmeat.name + human_meat.subjectname = sourcename + human_meat.subjectjob = sourcejob + + newmeat = human_meat + else + newmeat = victim.drop_meat(src) + + if(newmeat==null) + return + newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first + + if(victim.reagents) + victim.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the + + allmeat[i] = newmeat + + victim.attack_log += "\[[time_stamp()]\] Was auto-gibbed by [src]" //One shall not simply gib a mob unnoticed! + log_attack("[src] auto-gibbed [key_name(victim)]") + victim.death(1) + if(ishuman(victim) || ismonkey(victim) || isalien(victim)) + var/obj/item/organ/brain/B = new(src.loc) + B.transfer_identity(victim) + var/turf/Tx = locate(src.x - 2, src.y, src.z) + B.loc = src.loc + B.throw_at(Tx,2,3) + if(isalien(victim)) + var/obj/effect/decal/cleanable/blood/gibs/xeno/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs/xeno, Tx) + O.New(Tx,2) + else + var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx) + O.New(Tx,2) + qdel(victim) + spawn(src.gibtime) + playsound(get_turf(src), 'sound/effects/gib2.ogg', 50, 1) + operating = 0 + for (var/i=1 to totalslabs) + var/obj/item/meatslab = allmeat[i] + var/turf/Tx = locate(src.x - i, src.y, src.z) + meatslab.loc = src.loc + meatslab.throw_at(Tx,i,3) + if (!Tx.density) + var/obj/effect/decal/cleanable/blood/gibs/O = getFromPool(/obj/effect/decal/cleanable/blood/gibs, Tx) + O.New(Tx,i) + src.operating = 0 + update_icon() diff --git a/code/game/machinery/kitchen/juicer.dm b/code/game/machinery/kitchen/juicer.dm index 36ab786410d..6825cf24c79 100644 --- a/code/game/machinery/kitchen/juicer.dm +++ b/code/game/machinery/kitchen/juicer.dm @@ -1,174 +1,174 @@ - -/obj/machinery/juicer - name = "Juicer" - icon = 'icons/obj/kitchen.dmi' - icon_state = "juicer1" - layer = 2.9 - density = 0 - anchored = 0 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - var/obj/item/weapon/reagent_containers/beaker = null - var/global/list/allowed_items = list ( - /obj/item/weapon/reagent_containers/food/snacks/grown/apple = "applejuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = "tomatojuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = "carrotjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/berries = "berryjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/banana = "banana", - /obj/item/weapon/reagent_containers/food/snacks/grown/potato = "potato", - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = "lemonjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/orange = "orangejuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/lime = "limejuice", - /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = "watermelonjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = "poisonberryjuice", - ) - machine_flags = WRENCHMOVE - -/obj/machinery/juicer/New() - beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) - -/obj/machinery/juicer/update_icon() - icon_state = "juicer"+num2text(!isnull(beaker)) - return - - -/obj/machinery/juicer/attackby(var/obj/item/O as obj, var/mob/user as mob) - ..() - if (istype(O,/obj/item/weapon/reagent_containers/glass) || \ - istype(O,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) - if (beaker) - return 1 - else - if(user.drop_item(O, src)) - beaker = O - src.verbs += /obj/machinery/juicer/verb/detach - update_icon() - src.updateUsrDialog() - return 0 - if (!is_type_in_list(O, allowed_items)) - to_chat(user, "It looks as not containing any juice.") - return 1 - if(user.drop_item(O, src)) - src.updateUsrDialog() - return 0 - -/obj/machinery/juicer/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/juicer/attack_ai(mob/user as mob) - return 0 - -/obj/machinery/juicer/attack_hand(mob/user as mob) - user.set_machine(src) - interact(user) - -/obj/machinery/juicer/interact(mob/user as mob) // The microwave Menu - var/is_chamber_empty = 0 - var/is_beaker_ready = 0 - var/processing_chamber = "" - var/beaker_contents = "" - - for (var/i in allowed_items) - for (var/obj/item/O in src.contents) - if (!istype(O,i)) - continue - processing_chamber+= "some [O]
      " - break - if (!processing_chamber) - is_chamber_empty = 1 - processing_chamber = "Nothing." - if (!beaker) - beaker_contents = "\The [src] has no beaker attached." - else if (!beaker.reagents.total_volume) - beaker_contents = "\The [src] has attached an empty beaker." - is_beaker_ready = 1 - else if (beaker.reagents.total_volume < beaker.reagents.maximum_volume) - beaker_contents = "\The [src] has attached a beaker with something." - is_beaker_ready = 1 - else - beaker_contents = "\The [src] has attached a beaker and beaker is full!" - - var/dat = {" -Processing chamber contains:
      -[processing_chamber]
      -[beaker_contents]
      -"} - if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN))) - dat += "Turn on!
      " - if (beaker) - dat += "
      Detach a beaker!
      " - user << browse("Juicer[dat]", "window=juicer") - onclose(user, "juicer") - return - - -/obj/machinery/juicer/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - switch(href_list["action"]) - if ("juice") - juice() - - if ("detach") - detach() - src.updateUsrDialog() - return - -/obj/machinery/juicer/verb/detach() - set category = "Object" - set name = "Detach Beaker from the juicer" - set src in oview(1) - if (usr.isUnconscious()) - return - if (!beaker) - return - src.verbs -= /obj/machinery/juicer/verb/detach - beaker.loc = src.loc - beaker = null - update_icon() - -/obj/machinery/juicer/proc/get_juice_id(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) - for (var/i in allowed_items) - if (istype(O, i)) - return allowed_items[i] - -/obj/machinery/juicer/proc/get_juice_amount(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) - if (!istype(O)) - return 5 - else if (O.potency == -1) - return 5 - else - return round(5*sqrt(O.potency)) - -/obj/machinery/juicer/proc/juice() - power_change() //it is a portable machine - if(stat & (NOPOWER|BROKEN)) - return - if (!beaker || beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - return - playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) - for (var/obj/item/weapon/reagent_containers/food/snacks/O in src.contents) - var/r_id = get_juice_id(O) - beaker.reagents.add_reagent(r_id,get_juice_amount(O)) - qdel(O) - O = null - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - -/obj/structure/closet/crate/juice/New() - ..() - new/obj/machinery/juicer(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/berries(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/banana(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/berries(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/banana(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/berries(src) - new/obj/item/weapon/reagent_containers/food/snacks/grown/banana(src) + +/obj/machinery/juicer + name = "Juicer" + icon = 'icons/obj/kitchen.dmi' + icon_state = "juicer1" + layer = 2.9 + density = 0 + anchored = 0 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 + var/obj/item/weapon/reagent_containers/beaker = null + var/global/list/allowed_items = list ( + /obj/item/weapon/reagent_containers/food/snacks/grown/apple = "applejuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = "tomatojuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = "carrotjuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/berries = "berryjuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/banana = "banana", + /obj/item/weapon/reagent_containers/food/snacks/grown/potato = "potato", + /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = "lemonjuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/orange = "orangejuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/lime = "limejuice", + /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = "watermelonjuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = "poisonberryjuice", + ) + machine_flags = WRENCHMOVE + +/obj/machinery/juicer/New() + beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) + +/obj/machinery/juicer/update_icon() + icon_state = "juicer"+num2text(!isnull(beaker)) + return + + +/obj/machinery/juicer/attackby(var/obj/item/O as obj, var/mob/user as mob) + ..() + if (istype(O,/obj/item/weapon/reagent_containers/glass) || \ + istype(O,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) + if (beaker) + return 1 + else + if(user.drop_item(O, src)) + beaker = O + src.verbs += /obj/machinery/juicer/verb/detach + update_icon() + src.updateUsrDialog() + return 0 + if (!is_type_in_list(O, allowed_items)) + to_chat(user, "It looks as not containing any juice.") + return 1 + if(user.drop_item(O, src)) + src.updateUsrDialog() + return 0 + +/obj/machinery/juicer/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/juicer/attack_ai(mob/user as mob) + return 0 + +/obj/machinery/juicer/attack_hand(mob/user as mob) + user.set_machine(src) + interact(user) + +/obj/machinery/juicer/interact(mob/user as mob) // The microwave Menu + var/is_chamber_empty = 0 + var/is_beaker_ready = 0 + var/processing_chamber = "" + var/beaker_contents = "" + + for (var/i in allowed_items) + for (var/obj/item/O in src.contents) + if (!istype(O,i)) + continue + processing_chamber+= "some [O]
      " + break + if (!processing_chamber) + is_chamber_empty = 1 + processing_chamber = "Nothing." + if (!beaker) + beaker_contents = "\The [src] has no beaker attached." + else if (!beaker.reagents.total_volume) + beaker_contents = "\The [src] has attached an empty beaker." + is_beaker_ready = 1 + else if (beaker.reagents.total_volume < beaker.reagents.maximum_volume) + beaker_contents = "\The [src] has attached a beaker with something." + is_beaker_ready = 1 + else + beaker_contents = "\The [src] has attached a beaker and beaker is full!" + + var/dat = {" +Processing chamber contains:
      +[processing_chamber]
      +[beaker_contents]
      +"} + if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN))) + dat += "
      Turn on!
      " + if (beaker) + dat += "
      Detach a beaker!
      " + user << browse("Juicer[dat]", "window=juicer") + onclose(user, "juicer") + return + + +/obj/machinery/juicer/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + switch(href_list["action"]) + if ("juice") + juice() + + if ("detach") + detach() + src.updateUsrDialog() + return + +/obj/machinery/juicer/verb/detach() + set category = "Object" + set name = "Detach Beaker from the juicer" + set src in oview(1) + if (usr.isUnconscious()) + return + if (!beaker) + return + src.verbs -= /obj/machinery/juicer/verb/detach + beaker.loc = src.loc + beaker = null + update_icon() + +/obj/machinery/juicer/proc/get_juice_id(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) + for (var/i in allowed_items) + if (istype(O, i)) + return allowed_items[i] + +/obj/machinery/juicer/proc/get_juice_amount(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) + if (!istype(O)) + return 5 + else if (O.potency == -1) + return 5 + else + return round(5*sqrt(O.potency)) + +/obj/machinery/juicer/proc/juice() + power_change() //it is a portable machine + if(stat & (NOPOWER|BROKEN)) + return + if (!beaker || beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + return + playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) + for (var/obj/item/weapon/reagent_containers/food/snacks/O in src.contents) + var/r_id = get_juice_id(O) + beaker.reagents.add_reagent(r_id,get_juice_amount(O)) + qdel(O) + O = null + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + +/obj/structure/closet/crate/juice/New() + ..() + new/obj/machinery/juicer(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/berries(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/banana(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/berries(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/banana(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/tomato(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/carrot(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/berries(src) + new/obj/item/weapon/reagent_containers/food/snacks/grown/banana(src) diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index 3fea3f0fb2f..712f072e9bf 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -1,446 +1,446 @@ - -/obj/machinery/microwave - name = "Microwave" - icon = 'icons/obj/kitchen.dmi' - icon_state = "mw" - layer = 2.9 - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL - flags = OPENCONTAINER | NOREACT - pass_flags = PASSTABLE - var/operating = 0 // Is it on? - var/opened = 0.0 - var/dirty = 0 // = {0..100} Does it need cleaning? - var/broken = 0 // ={0,1,2} How broken is it??? - var/global/list/datum/recipe/available_recipes // List of the recipes you can use - var/global/list/acceptable_items // List of the items you can put in - var/global/list/acceptable_reagents // List of the reagents you can put in - var/list/holdingitems = list() - var/limit = 100 - var/speed_multiplier = 1 - var/scanning_power = 0 - var/global/list/accepts_reagents_from = list(/obj/item/weapon/reagent_containers/glass, - /obj/item/weapon/reagent_containers/food/drinks, - /obj/item/weapon/reagent_containers/food/condiment, - /obj/item/weapon/reagent_containers/dropper) - -// see code/modules/food/recipes_microwave.dm for recipes -//Cannot use tools - screwdriver and crowbar for recipes. Or at least fix things before you do -//TODO - Get a maint panel sprite and J-J-Jam it in. -//Biiiig Thanks to Kaze_Espada, SuperSayu, Jordie, MrPerson, and HUUUUGE thank you to Arancalos from #coderbus for patiently helping for hours, and practically doing it themselves, to get the microwaves to not have their stock parts as ingredients upon construction. May they enjoy their hard earned plunder. -//HUUUUUUUGE thanks to D3athrow for getting it to the finish line -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -/******************* -* Initialising -********************/ - -/obj/machinery/microwave/New() - . = ..() - - component_parts = newlist(\ - /obj/item/weapon/circuitboard/microwave,\ - /obj/item/weapon/stock_parts/micro_laser,\ - /obj/item/weapon/stock_parts/scanning_module,\ - /obj/item/weapon/stock_parts/console_screen\ - ) - - RefreshParts() - create_reagents(100) - - if (!available_recipes) - available_recipes = new - for (var/type in (typesof(/datum/recipe)-/datum/recipe)) - available_recipes+= new type - acceptable_items = new - acceptable_reagents = new - for (var/datum/recipe/recipe in available_recipes) - for (var/item in recipe.items) - acceptable_items |= item - for (var/reagent in recipe.reagents) - acceptable_reagents |= reagent - -/******************* -* Part Upgrades -********************/ -/obj/machinery/microwave/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) - T += M.rating-1 - speed_multiplier = initial(speed_multiplier)+(T * 0.5) - - T = 0 - for(var/obj/item/weapon/stock_parts/scanning_module/M in component_parts) - T += M.rating-1 - scanning_power = initial(scanning_power)+(T) - -/******************* -* Item Adding -********************/ -/obj/machinery/microwave/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(src.broken > 0) - if(src.broken == 2 && istype(O, /obj/item/weapon/screwdriver)) // If it's broken and they're using a screwdriver - user.visible_message( \ - "[user] starts to fix part of the microwave.", \ - "You start to fix part of the microwave." \ - ) - if (do_after(user, src,20)) - user.visible_message( \ - "[user] fixes part of the microwave.", \ - "You have fixed part of the microwave." \ - ) - src.broken = 1 // Fix it a bit - else if(src.broken == 1 && istype(O, /obj/item/weapon/wrench)) // If it's broken and they're doing the wrench - user.visible_message( \ - "[user] starts to fix part of the microwave.", \ - "You start to fix part of the microwave." \ - ) - if (do_after(user, src,20)) - user.visible_message( \ - "[user] fixes the microwave.", \ - "You have fixed the microwave." \ - ) - src.icon_state = "mw" - src.broken = 0 // Fix it! - src.dirty = 0 // just to be sure - src.flags = OPENCONTAINER - else - to_chat(user, "It's broken!") - return 1 - else if(src.dirty==100) // The microwave is all dirty so can't be used! - var/obj/item/weapon/reagent_containers/R = O - if(istype(R)) // If they're trying to clean it then let them - if(R.reagents.amount_cache.len == 1 && R.reagents.has_reagent("cleaner", 5)) - user.visible_message( \ - "[user] starts to clean the microwave.", \ - "You start to clean the microwave." \ - ) - if (do_after(user, src,20)) - R.reagents.remove_reagent("cleaner",5) - user.visible_message( \ - "[user] has cleaned the microwave.", \ - "You have cleaned the microwave." \ - ) - src.dirty = 0 // It's clean! - src.broken = 0 // just to be sure - src.icon_state = "mw" - src.flags = OPENCONTAINER - return 1 - else //Otherwise bad luck!! - to_chat(user, "It's too dirty!") - return 1 - - if(..()) - return 1 - - if(holdingitems && holdingitems.len >= limit) - to_chat(usr, "The machine cannot hold anymore items.") - return 1 - else if(istype(O, /obj/item/weapon/storage/bag/plants) || istype(O, /obj/item/weapon/storage/bag/food/borg)) - var/obj/item/weapon/storage/bag/B = O - for (var/obj/item/weapon/reagent_containers/food/snacks/G in O.contents) - B.remove_from_storage(G,src) - if(contents && contents.len >= limit) //Sanity checking so the microwave doesn't overfill - to_chat(user, "You fill the Microwave to the brim.") - break - - if(!O.contents.len) - to_chat(user, "You empty \the [O] into the Microwave.") - src.updateUsrDialog() - return 0 - if (!is_type_in_list(O.contents)) - to_chat(user, "Your [O] contains components unsuitable for cookery.") - return 1 - - if(user.drop_item(O, src)) - holdingitems += O - src.updateUsrDialog() - return 1 - else if(is_type_in_list(O,acceptable_items)) - if (istype(O,/obj/item/stack) && O:amount>1) - new O.type (src) - O:use(1) - user.visible_message( \ - "[user] has added one of [O] to \the [src].", \ - "You add one of [O] to \the [src].") - else - // user.before_take_item(O) //This just causes problems so far as I can tell. -Pete - if(user.drop_item(O, src)) - user.visible_message( \ - "[user] has added \the [O] to \the [src].", \ - "You add \the [O] to \the [src].") - else if(is_type_in_list(O,accepts_reagents_from)) - if (!O.reagents) - return 1 - for (var/datum/reagent/R in O.reagents.reagent_list) - if (!(R.id in acceptable_reagents)) - to_chat(user, "Your [O] contains components unsuitable for cookery.") - return 1 - //G.reagents.trans_to(src,G.amount_per_transfer_from_this) - else if(istype(O,/obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = O - to_chat(user, "This is ridiculous. You can not fit \the [G.affecting] in this [src].") - return 1 - else - to_chat(user, "You have no idea what you can cook with this [O].") - return 1 - src.updateUsrDialog() - -/obj/machinery/microwave/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/microwave/attack_ai(mob/user as mob) - if(istype(user,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = user - if(istype(R.module, /obj/item/weapon/robot_module/butler)) - user.set_machine(src) - interact(user) - return 1 - to_chat(user, "You aren't equipped to interface with technology this old!") - return 0 - -/obj/machinery/microwave/attack_hand(mob/user as mob) - user.set_machine(src) - interact(user) - -/******************* -* Microwave Menu -********************/ - -/obj/machinery/microwave/interact(mob/user as mob) // The microwave Menu - var/dat = "" - if(src.broken > 0) - dat = {"Bzzzzttttt"} - else if(src.operating) - dat = {"Microwaving in progress!
      Please wait...!
      "} - else if(src.dirty==100) - dat = {"This microwave is dirty!
      Please clean it before use!
      "} - else - var/list/items_counts = new - var/list/items_measures = new - var/list/items_measures_p = new - for (var/obj/O in contents) - var/display_name = O.name - if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/meat)) //any meat - items_measures[display_name] = "slab of meat" - items_measures_p[display_name] = "slabs of meat" - if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat)) - items_measures[display_name] = "fillet of meat" - items_measures_p[display_name] = "fillets of meat" - if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg)) - items_measures[display_name] = "egg" - items_measures_p[display_name] = "eggs" - if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/tofu)) - items_measures[display_name] = "tofu chunk" - items_measures_p[display_name] = "tofu chunks" - if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/donkpocket)) - display_name = "Turnovers" - items_measures[display_name] = "turnover" - items_measures_p[display_name] = "turnovers" - items_counts[display_name]++ - for (var/O in items_counts) - var/N = items_counts[O] - if (!(O in items_measures)) - dat += {"[capitalize(O)]: [N] [lowertext(O)]\s
      "} - else - if (N==1) - dat += {"[capitalize(O)]: [N] [items_measures[O]]
      "} - else - dat += {"[capitalize(O)]: [N] [items_measures_p[O]]
      "} - - for (var/datum/reagent/R in reagents.reagent_list) - var/display_name = R.name - if (R.id == "capsaicin") - display_name = "Hotsauce" - if (R.id == "frostoil") - display_name = "Coldsauce" - dat += {"[display_name]: [R.volume] unit\s
      "} - - if (items_counts.len==0 && reagents.reagent_list.len==0) - dat = {"The microwave is empty
      "} - else - dat = {"Ingredients:
      [dat]

      "} - if (scanning_power >= 2 ) - var/datum/recipe/recipe = select_recipe(available_recipes,src) - if (!recipe) - dat += {"ERROR: No matching recipe found!
      "} - else - var/obj/O = recipe.result - var/display_name = initial(O.name) - dat += {"Expected result: [display_name]
      "} - dat += {"\ -
      Turn on!
      \ -
      Eject ingredients!
      \ -"} - - user << browse("Microwave Controls[dat]", "window=microwave") - onclose(user, "microwave") - return - - - -/*********************************** -* Microwave Menu Handling/Cooking -************************************/ - -/obj/machinery/microwave/proc/cook() - if(stat & (NOPOWER|BROKEN)) - return - start() - if (reagents.total_volume==0 && !(locate(/obj) in contents)) //dry run - if (!wzhzhzh(10)) - abort() - return - stop() - return - - var/datum/recipe/recipe = select_recipe(available_recipes,src) - var/obj/cooked - if (!recipe) - dirty += 1 - if (prob(max(10,dirty*5))) - if (!wzhzhzh(4)) - abort() - return - muck_start() - wzhzhzh(4) - muck_finish() - cooked = fail() - cooked.loc = src.loc - return - else if (has_extra_item()) - if (!wzhzhzh(4)) - abort() - return - broke() - cooked = fail() - cooked.loc = src.loc - return - else - if (!wzhzhzh(10)) - abort() - return - stop() - cooked = fail() - cooked.loc = src.loc - return - else - var/halftime = round(recipe.time/10/2) - if (!wzhzhzh(halftime)) - abort() - return - if (!wzhzhzh(halftime)) - abort() - cooked = fail() - cooked.loc = src.loc - return - cooked = recipe.make_food(src) - stop() - if(cooked) - cooked.loc = src.loc - return - -/obj/machinery/microwave/proc/wzhzhzh(var/seconds as num) - for (var/i=1 to seconds) - if (stat & (NOPOWER|BROKEN)) - return 0 - use_power(500) - sleep(10/speed_multiplier) - return 1 - -/obj/machinery/microwave/proc/has_extra_item() - for (var/obj/O in contents) - if ( \ - !istype(O,/obj/item/weapon/reagent_containers/food) && \ - !istype(O, /obj/item/weapon/grown) \ - ) - return 1 - return 0 - -/obj/machinery/microwave/proc/start() - src.visible_message("The microwave turns on.", "You hear a microwave.") - src.operating = 1 - src.icon_state = "mw1" - src.updateUsrDialog() - -/obj/machinery/microwave/proc/abort() - src.operating = 0 // Turn it off again aferwards - src.icon_state = "mw" - src.updateUsrDialog() - -/obj/machinery/microwave/proc/stop() - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) - src.operating = 0 // Turn it off again aferwards - src.icon_state = "mw" - src.updateUsrDialog() - -/obj/machinery/microwave/proc/dispose() - for (var/obj/O in contents) - O.loc = src.loc - if (src.reagents.total_volume) - src.dirty++ - src.reagents.clear_reagents() - to_chat(usr, "You dispose of the microwave contents.") - src.updateUsrDialog() - -/obj/machinery/microwave/proc/muck_start() - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) // Play a splat sound - src.icon_state = "mwbloody1" // Make it look dirty!! - -/obj/machinery/microwave/proc/muck_finish() - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) - src.visible_message("The microwave gets covered in muck!") - src.dirty = 100 // Make it dirty so it can't be used util cleaned - src.flags = 0 //So you can't add condiments - src.icon_state = "mwbloody" // Make it look dirty too - src.operating = 0 // Turn it off again aferwards - src.updateUsrDialog() - -/obj/machinery/microwave/proc/broke() - var/datum/effect/effect/system/spark_spread/s = new - s.set_up(2, 1, src) - s.start() - src.icon_state = "mwb" // Make it look all busted up and shit - src.visible_message("The microwave breaks!") //Let them know they're stupid - src.broken = 2 // Make it broken so it can't be used util fixed - src.flags = 0 //So you can't add condiments - src.operating = 0 // Turn it off again aferwards - src.updateUsrDialog() - -/obj/machinery/microwave/proc/fail() - var/obj/item/weapon/reagent_containers/food/snacks/badrecipe/ffuu = new(src) - var/amount = 0 - for (var/obj/O in contents-ffuu) - amount++ - if (O.reagents) - var/id = O.reagents.get_master_reagent_id() - if (id) - amount+=O.reagents.get_reagent_amount(id) - qdel(O) - O = null - src.reagents.clear_reagents() - ffuu.reagents.add_reagent("carbon", amount) - ffuu.reagents.add_reagent("toxin", amount/10) - return ffuu - -/obj/machinery/microwave/Topic(href, href_list) - if(..()) - return - - usr.set_machine(src) - if(src.operating) - src.updateUsrDialog() - return - - switch(href_list["action"]) - if ("cook") - cook() - - if ("dispose") - dispose() - return + +/obj/machinery/microwave + name = "Microwave" + icon = 'icons/obj/kitchen.dmi' + icon_state = "mw" + layer = 2.9 + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL + flags = OPENCONTAINER | NOREACT + pass_flags = PASSTABLE + var/operating = 0 // Is it on? + var/opened = 0.0 + var/dirty = 0 // = {0..100} Does it need cleaning? + var/broken = 0 // ={0,1,2} How broken is it??? + var/global/list/datum/recipe/available_recipes // List of the recipes you can use + var/global/list/acceptable_items // List of the items you can put in + var/global/list/acceptable_reagents // List of the reagents you can put in + var/list/holdingitems = list() + var/limit = 100 + var/speed_multiplier = 1 + var/scanning_power = 0 + var/global/list/accepts_reagents_from = list(/obj/item/weapon/reagent_containers/glass, + /obj/item/weapon/reagent_containers/food/drinks, + /obj/item/weapon/reagent_containers/food/condiment, + /obj/item/weapon/reagent_containers/dropper) + +// see code/modules/food/recipes_microwave.dm for recipes +//Cannot use tools - screwdriver and crowbar for recipes. Or at least fix things before you do +//TODO - Get a maint panel sprite and J-J-Jam it in. +//Biiiig Thanks to Kaze_Espada, SuperSayu, Jordie, MrPerson, and HUUUUGE thank you to Arancalos from #coderbus for patiently helping for hours, and practically doing it themselves, to get the microwaves to not have their stock parts as ingredients upon construction. May they enjoy their hard earned plunder. +//HUUUUUUUGE thanks to D3athrow for getting it to the finish line +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +/******************* +* Initialising +********************/ + +/obj/machinery/microwave/New() + . = ..() + + component_parts = newlist(\ + /obj/item/weapon/circuitboard/microwave,\ + /obj/item/weapon/stock_parts/micro_laser,\ + /obj/item/weapon/stock_parts/scanning_module,\ + /obj/item/weapon/stock_parts/console_screen\ + ) + + RefreshParts() + create_reagents(100) + + if (!available_recipes) + available_recipes = new + for (var/type in (typesof(/datum/recipe)-/datum/recipe)) + available_recipes+= new type + acceptable_items = new + acceptable_reagents = new + for (var/datum/recipe/recipe in available_recipes) + for (var/item in recipe.items) + acceptable_items |= item + for (var/reagent in recipe.reagents) + acceptable_reagents |= reagent + +/******************* +* Part Upgrades +********************/ +/obj/machinery/microwave/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) + T += M.rating-1 + speed_multiplier = initial(speed_multiplier)+(T * 0.5) + + T = 0 + for(var/obj/item/weapon/stock_parts/scanning_module/M in component_parts) + T += M.rating-1 + scanning_power = initial(scanning_power)+(T) + +/******************* +* Item Adding +********************/ +/obj/machinery/microwave/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(src.broken > 0) + if(src.broken == 2 && istype(O, /obj/item/weapon/screwdriver)) // If it's broken and they're using a screwdriver + user.visible_message( \ + "[user] starts to fix part of the microwave.", \ + "You start to fix part of the microwave." \ + ) + if (do_after(user, src,20)) + user.visible_message( \ + "[user] fixes part of the microwave.", \ + "You have fixed part of the microwave." \ + ) + src.broken = 1 // Fix it a bit + else if(src.broken == 1 && istype(O, /obj/item/weapon/wrench)) // If it's broken and they're doing the wrench + user.visible_message( \ + "[user] starts to fix part of the microwave.", \ + "You start to fix part of the microwave." \ + ) + if (do_after(user, src,20)) + user.visible_message( \ + "[user] fixes the microwave.", \ + "You have fixed the microwave." \ + ) + src.icon_state = "mw" + src.broken = 0 // Fix it! + src.dirty = 0 // just to be sure + src.flags = OPENCONTAINER + else + to_chat(user, "It's broken!") + return 1 + else if(src.dirty==100) // The microwave is all dirty so can't be used! + var/obj/item/weapon/reagent_containers/R = O + if(istype(R)) // If they're trying to clean it then let them + if(R.reagents.amount_cache.len == 1 && R.reagents.has_reagent("cleaner", 5)) + user.visible_message( \ + "[user] starts to clean the microwave.", \ + "You start to clean the microwave." \ + ) + if (do_after(user, src,20)) + R.reagents.remove_reagent("cleaner",5) + user.visible_message( \ + "[user] has cleaned the microwave.", \ + "You have cleaned the microwave." \ + ) + src.dirty = 0 // It's clean! + src.broken = 0 // just to be sure + src.icon_state = "mw" + src.flags = OPENCONTAINER + return 1 + else //Otherwise bad luck!! + to_chat(user, "It's too dirty!") + return 1 + + if(..()) + return 1 + + if(holdingitems && holdingitems.len >= limit) + to_chat(usr, "The machine cannot hold anymore items.") + return 1 + else if(istype(O, /obj/item/weapon/storage/bag/plants) || istype(O, /obj/item/weapon/storage/bag/food/borg)) + var/obj/item/weapon/storage/bag/B = O + for (var/obj/item/weapon/reagent_containers/food/snacks/G in O.contents) + B.remove_from_storage(G,src) + if(contents && contents.len >= limit) //Sanity checking so the microwave doesn't overfill + to_chat(user, "You fill the Microwave to the brim.") + break + + if(!O.contents.len) + to_chat(user, "You empty \the [O] into the Microwave.") + src.updateUsrDialog() + return 0 + if (!is_type_in_list(O.contents)) + to_chat(user, "Your [O] contains components unsuitable for cookery.") + return 1 + + if(user.drop_item(O, src)) + holdingitems += O + src.updateUsrDialog() + return 1 + else if(is_type_in_list(O,acceptable_items)) + if (istype(O,/obj/item/stack) && O:amount>1) + new O.type (src) + O:use(1) + user.visible_message( \ + "[user] has added one of [O] to \the [src].", \ + "You add one of [O] to \the [src].") + else + // user.before_take_item(O) //This just causes problems so far as I can tell. -Pete + if(user.drop_item(O, src)) + user.visible_message( \ + "[user] has added \the [O] to \the [src].", \ + "You add \the [O] to \the [src].") + else if(is_type_in_list(O,accepts_reagents_from)) + if (!O.reagents) + return 1 + for (var/datum/reagent/R in O.reagents.reagent_list) + if (!(R.id in acceptable_reagents)) + to_chat(user, "Your [O] contains components unsuitable for cookery.") + return 1 + //G.reagents.trans_to(src,G.amount_per_transfer_from_this) + else if(istype(O,/obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = O + to_chat(user, "This is ridiculous. You can not fit \the [G.affecting] in this [src].") + return 1 + else + to_chat(user, "You have no idea what you can cook with this [O].") + return 1 + src.updateUsrDialog() + +/obj/machinery/microwave/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/microwave/attack_ai(mob/user as mob) + if(istype(user,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = user + if(istype(R.module, /obj/item/weapon/robot_module/butler)) + user.set_machine(src) + interact(user) + return 1 + to_chat(user, "You aren't equipped to interface with technology this old!") + return 0 + +/obj/machinery/microwave/attack_hand(mob/user as mob) + user.set_machine(src) + interact(user) + +/******************* +* Microwave Menu +********************/ + +/obj/machinery/microwave/interact(mob/user as mob) // The microwave Menu + var/dat = "" + if(src.broken > 0) + dat = {"Bzzzzttttt"} + else if(src.operating) + dat = {"Microwaving in progress!
      Please wait...!
      "} + else if(src.dirty==100) + dat = {"This microwave is dirty!
      Please clean it before use!
      "} + else + var/list/items_counts = new + var/list/items_measures = new + var/list/items_measures_p = new + for (var/obj/O in contents) + var/display_name = O.name + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/meat)) //any meat + items_measures[display_name] = "slab of meat" + items_measures_p[display_name] = "slabs of meat" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat)) + items_measures[display_name] = "fillet of meat" + items_measures_p[display_name] = "fillets of meat" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg)) + items_measures[display_name] = "egg" + items_measures_p[display_name] = "eggs" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/tofu)) + items_measures[display_name] = "tofu chunk" + items_measures_p[display_name] = "tofu chunks" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/donkpocket)) + display_name = "Turnovers" + items_measures[display_name] = "turnover" + items_measures_p[display_name] = "turnovers" + items_counts[display_name]++ + for (var/O in items_counts) + var/N = items_counts[O] + if (!(O in items_measures)) + dat += {"[capitalize(O)]: [N] [lowertext(O)]\s
      "} + else + if (N==1) + dat += {"[capitalize(O)]: [N] [items_measures[O]]
      "} + else + dat += {"[capitalize(O)]: [N] [items_measures_p[O]]
      "} + + for (var/datum/reagent/R in reagents.reagent_list) + var/display_name = R.name + if (R.id == "capsaicin") + display_name = "Hotsauce" + if (R.id == "frostoil") + display_name = "Coldsauce" + dat += {"[display_name]: [R.volume] unit\s
      "} + + if (items_counts.len==0 && reagents.reagent_list.len==0) + dat = {"The microwave is empty
      "} + else + dat = {"Ingredients:
      [dat]

      "} + if (scanning_power >= 2 ) + var/datum/recipe/recipe = select_recipe(available_recipes,src) + if (!recipe) + dat += {"ERROR: No matching recipe found!
      "} + else + var/obj/O = recipe.result + var/display_name = initial(O.name) + dat += {"Expected result: [display_name]
      "} + dat += {"\ +
      Turn on!
      \ +
      Eject ingredients!
      \ +"} + + user << browse("Microwave Controls[dat]", "window=microwave") + onclose(user, "microwave") + return + + + +/*********************************** +* Microwave Menu Handling/Cooking +************************************/ + +/obj/machinery/microwave/proc/cook() + if(stat & (NOPOWER|BROKEN)) + return + start() + if (reagents.total_volume==0 && !(locate(/obj) in contents)) //dry run + if (!wzhzhzh(10)) + abort() + return + stop() + return + + var/datum/recipe/recipe = select_recipe(available_recipes,src) + var/obj/cooked + if (!recipe) + dirty += 1 + if (prob(max(10,dirty*5))) + if (!wzhzhzh(4)) + abort() + return + muck_start() + wzhzhzh(4) + muck_finish() + cooked = fail() + cooked.loc = src.loc + return + else if (has_extra_item()) + if (!wzhzhzh(4)) + abort() + return + broke() + cooked = fail() + cooked.loc = src.loc + return + else + if (!wzhzhzh(10)) + abort() + return + stop() + cooked = fail() + cooked.loc = src.loc + return + else + var/halftime = round(recipe.time/10/2) + if (!wzhzhzh(halftime)) + abort() + return + if (!wzhzhzh(halftime)) + abort() + cooked = fail() + cooked.loc = src.loc + return + cooked = recipe.make_food(src) + stop() + if(cooked) + cooked.loc = src.loc + return + +/obj/machinery/microwave/proc/wzhzhzh(var/seconds as num) + for (var/i=1 to seconds) + if (stat & (NOPOWER|BROKEN)) + return 0 + use_power(500) + sleep(10/speed_multiplier) + return 1 + +/obj/machinery/microwave/proc/has_extra_item() + for (var/obj/O in contents) + if ( \ + !istype(O,/obj/item/weapon/reagent_containers/food) && \ + !istype(O, /obj/item/weapon/grown) \ + ) + return 1 + return 0 + +/obj/machinery/microwave/proc/start() + src.visible_message("The microwave turns on.", "You hear a microwave.") + src.operating = 1 + src.icon_state = "mw1" + src.updateUsrDialog() + +/obj/machinery/microwave/proc/abort() + src.operating = 0 // Turn it off again aferwards + src.icon_state = "mw" + src.updateUsrDialog() + +/obj/machinery/microwave/proc/stop() + playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + src.operating = 0 // Turn it off again aferwards + src.icon_state = "mw" + src.updateUsrDialog() + +/obj/machinery/microwave/proc/dispose() + for (var/obj/O in contents) + O.loc = src.loc + if (src.reagents.total_volume) + src.dirty++ + src.reagents.clear_reagents() + to_chat(usr, "You dispose of the microwave contents.") + src.updateUsrDialog() + +/obj/machinery/microwave/proc/muck_start() + playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) // Play a splat sound + src.icon_state = "mwbloody1" // Make it look dirty!! + +/obj/machinery/microwave/proc/muck_finish() + playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + src.visible_message("The microwave gets covered in muck!") + src.dirty = 100 // Make it dirty so it can't be used util cleaned + src.flags = 0 //So you can't add condiments + src.icon_state = "mwbloody" // Make it look dirty too + src.operating = 0 // Turn it off again aferwards + src.updateUsrDialog() + +/obj/machinery/microwave/proc/broke() + var/datum/effect/effect/system/spark_spread/s = new + s.set_up(2, 1, src) + s.start() + src.icon_state = "mwb" // Make it look all busted up and shit + src.visible_message("The microwave breaks!") //Let them know they're stupid + src.broken = 2 // Make it broken so it can't be used util fixed + src.flags = 0 //So you can't add condiments + src.operating = 0 // Turn it off again aferwards + src.updateUsrDialog() + +/obj/machinery/microwave/proc/fail() + var/obj/item/weapon/reagent_containers/food/snacks/badrecipe/ffuu = new(src) + var/amount = 0 + for (var/obj/O in contents-ffuu) + amount++ + if (O.reagents) + var/id = O.reagents.get_master_reagent_id() + if (id) + amount+=O.reagents.get_reagent_amount(id) + qdel(O) + O = null + src.reagents.clear_reagents() + ffuu.reagents.add_reagent("carbon", amount) + ffuu.reagents.add_reagent("toxin", amount/10) + return ffuu + +/obj/machinery/microwave/Topic(href, href_list) + if(..()) + return + + usr.set_machine(src) + if(src.operating) + src.updateUsrDialog() + return + + switch(href_list["action"]) + if ("cook") + cook() + + if ("dispose") + dispose() + return diff --git a/code/game/machinery/kitchen/processor.dm b/code/game/machinery/kitchen/processor.dm index c2a6641a69b..541b0c06bc3 100644 --- a/code/game/machinery/kitchen/processor.dm +++ b/code/game/machinery/kitchen/processor.dm @@ -1,263 +1,263 @@ - -/obj/machinery/processor - name = "Food Processor" - icon = 'icons/obj/kitchen.dmi' - icon_state = "processor" - density = 1 - anchored = 1 - var/broken = 0 - var/processing = 0 - var/opened = 0.0 - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - use_power = 1 - idle_power_usage = 20 - active_power_usage = 500 - var/time_coeff = 1 - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -/obj/machinery/processor/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/processor, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator - ) - - RefreshParts() - -/obj/machinery/processor/RefreshParts() - var/manipcount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/manipulator)) manipcount += SP.rating - time_coeff = 2/manipcount - -/datum/food_processor_process - var/input - var/output - var/time = 40 - proc/process(loc, what) - if (src.output && loc) - new src.output(loc) - if (what) - qdel(what) - what = null - - /* objs */ - - poison - input = null - output = null - process(loc, atom/movable/what) - if(loc && istype(what,/obj/item/weapon/reagent_containers/food/snacks/meat)) - var/obj/item/weapon/reagent_containers/food/snacks/meat/M = what - if(M.poisonsacs) - M.poisonsacs.forceMove(loc) - M.poisonsacs = null - M.desc = "An excellent [src]!" - M.reagents.del_reagent("toxin") - M.reagents.del_reagent("carpotoxin") - what.forceMove(loc) - - poison/spiderleg - input = /obj/item/weapon/reagent_containers/food/snacks/meat/spiderleg - - poison/spidermeat - input = /obj/item/weapon/reagent_containers/food/snacks/meat/spidermeat - - poison/carpmeat - input = /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat - - meat - input = /obj/item/weapon/reagent_containers/food/snacks/meat - output = /obj/item/weapon/reagent_containers/food/snacks/faggot - - potato - input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato - output = /obj/item/weapon/reagent_containers/food/snacks/fries - - carrot - input = /obj/item/weapon/reagent_containers/food/snacks/grown/carrot - output = /obj/item/weapon/reagent_containers/food/snacks/carrotfries - - soybeans - input = /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans - output = /obj/item/weapon/reagent_containers/food/snacks/soydope - - /* mobs */ - mob - process(loc, what) - ..() - - - slime - - process(loc, what) - - var/mob/living/carbon/slime/S = what - var/C = S.cores - if(S.stat != DEAD) - S.loc = loc - S.visible_message("[C] crawls free of the processor!") - return - for(var/i = 1, i <= C, i++) - new S.coretype(loc) - feedback_add_details("slime_core_harvested","[replacetext(S.colour," ","_")]") - ..() - input = /mob/living/carbon/slime - output = null - - monkey - process(loc, what) - var/mob/living/carbon/monkey/O = what - if (O.client) //grief-proof - O.loc = loc - O.visible_message("[O] suddenly jumps out of [src]!", \ - "You jump out from the processor", \ - "You hear a slimy sound") - return - var/obj/item/weapon/reagent_containers/glass/bucket/bucket_of_blood = new(loc) - var/datum/reagent/blood/B = new() - B.holder = bucket_of_blood - B.volume = 70 - //set reagent data - B.data["donor"] = O - - for(var/datum/disease/D in O.viruses) - if(D.spread_type != SPECIAL) - B.data["viruses"] += D.Copy() - - B.data["blood_DNA"] = copytext(O.dna.unique_enzymes,1,0) - if(O.resistances&&O.resistances.len) - B.data["resistances"] = O.resistances.Copy() - bucket_of_blood.reagents.reagent_list += B - bucket_of_blood.reagents.update_total() - bucket_of_blood.on_reagent_change() - //bucket_of_blood.reagents.handle_reactions() //blood doesn't react - ..() - - input = /mob/living/carbon/monkey - output = null - - chicken - process(loc, what) - playsound(loc, 'sound/machines/ya_dun_clucked.ogg', 50, 1) - ..() - input = /mob/living/simple_animal/chicken - output = /obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets - - chick - process(loc, what) - playsound(loc, 'sound/machines/ya_dun_clucked.ogg', 50, 1) - ..() - input = /mob/living/simple_animal/chick - output = /obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets - - human - process(loc, what) - var/mob/living/carbon/human/target = what - if (istype(target.wear_suit,/obj/item/clothing/suit/chickensuit) && istype(target.head,/obj/item/clothing/head/chicken)) - target.visible_message("Bwak! Bwak! Bwak!") - playsound(loc, 'sound/machines/ya_dun_clucked.ogg', 50, 1) - target.canmove = 0 - target.icon = null - target.invisibility = 101 - target.density = 0 - var/throwzone = list() - for(var/turf/T in orange(loc,4)) - throwzone += T - for(var/obj/I in target.contents) - I.loc = loc - I.throw_at(pick(throwzone),rand(2,5),0) - hgibs(loc, target.viruses, target.dna, target.species.flesh_color, target.species.blood_color) - qdel(target) - target = null - for(var/i = 1;i<=6;i++) - new /obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets(loc) - sleep(2) - ..() - else - target.loc = loc - target.visible_message("The processor's safety protocols won't allow it to cut something that looks human!") - input = /mob/living/carbon/human - output = null - -/obj/machinery/processor/proc/select_recipe(var/X) - for (var/Type in typesof(/datum/food_processor_process) - /datum/food_processor_process - /datum/food_processor_process/mob) - var/datum/food_processor_process/P = new Type() - if (!istype(X, P.input)) - continue - return P - return 0 - -/obj/machinery/processor/crowbarDestroy(mob/user) - if(contents.len) - to_chat(user, "You can't do that while something is loaded in \the [src].") - return -1 - return ..() - -/obj/machinery/processor/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(src.processing) - to_chat(user, "[src] is already processing!") - return 1 - - if(..()) - return 1 - if(src.contents.len > 0) //TODO: several items at once? several different items? - to_chat(user, "Something is already in [src].") - return 1 - var/atom/movable/what = O - if (istype(O, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = O - what = G.affecting - - var/datum/food_processor_process/P = select_recipe(what) - if (!P) - to_chat(user, "This probably won't blend.") - return 1 - user.visible_message("[user] puts [what] into [src].", \ - "You put [what] into the [src].") - if(what == user.get_active_hand()) - user.drop_item(what, src) - else - if(O.loc == user) - user.drop_item(O) - what.loc = src - return - -/obj/machinery/processor/attack_hand(var/mob/user as mob) - if (src.stat != 0) //NOPOWER etc - return - if(!anchored) - to_chat(user, "[src] must be anchored first!") - return - if(src.processing) - to_chat(user, "[src] is already processing!") - return 1 - if(src.contents.len == 0) - to_chat(user, "[src] is empty!") - return 1 - for(var/O in src.contents) - var/datum/food_processor_process/P = select_recipe(O) - if (!P) - log_admin("DEBUG: [O] in processor is not suitable. How did you put it in?") //-rastaf0 - continue - src.processing = 1 - user.visible_message("[user] turns on [src].", \ - "You turn on \a [src].", \ - "You hear [src] start") - playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1) - use_power(500) - sleep(P.time*time_coeff) - P.process(src.loc, O) - src.processing = 0 - src.visible_message("[src] is done.", \ - "You hear [src] stop") - -/obj/machinery/processor/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - attackby(O,user) + +/obj/machinery/processor + name = "Food Processor" + icon = 'icons/obj/kitchen.dmi' + icon_state = "processor" + density = 1 + anchored = 1 + var/broken = 0 + var/processing = 0 + var/opened = 0.0 + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + use_power = 1 + idle_power_usage = 20 + active_power_usage = 500 + var/time_coeff = 1 + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +/obj/machinery/processor/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/processor, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator + ) + + RefreshParts() + +/obj/machinery/processor/RefreshParts() + var/manipcount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/manipulator)) manipcount += SP.rating + time_coeff = 2/manipcount + +/datum/food_processor_process + var/input + var/output + var/time = 40 + proc/process(loc, what) + if (src.output && loc) + new src.output(loc) + if (what) + qdel(what) + what = null + + /* objs */ + + poison + input = null + output = null + process(loc, atom/movable/what) + if(loc && istype(what,/obj/item/weapon/reagent_containers/food/snacks/meat)) + var/obj/item/weapon/reagent_containers/food/snacks/meat/M = what + if(M.poisonsacs) + M.poisonsacs.forceMove(loc) + M.poisonsacs = null + M.desc = "An excellent [src]!" + M.reagents.del_reagent("toxin") + M.reagents.del_reagent("carpotoxin") + what.forceMove(loc) + + poison/spiderleg + input = /obj/item/weapon/reagent_containers/food/snacks/meat/spiderleg + + poison/spidermeat + input = /obj/item/weapon/reagent_containers/food/snacks/meat/spidermeat + + poison/carpmeat + input = /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat + + meat + input = /obj/item/weapon/reagent_containers/food/snacks/meat + output = /obj/item/weapon/reagent_containers/food/snacks/faggot + + potato + input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato + output = /obj/item/weapon/reagent_containers/food/snacks/fries + + carrot + input = /obj/item/weapon/reagent_containers/food/snacks/grown/carrot + output = /obj/item/weapon/reagent_containers/food/snacks/carrotfries + + soybeans + input = /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans + output = /obj/item/weapon/reagent_containers/food/snacks/soydope + + /* mobs */ + mob + process(loc, what) + ..() + + + slime + + process(loc, what) + + var/mob/living/carbon/slime/S = what + var/C = S.cores + if(S.stat != DEAD) + S.loc = loc + S.visible_message("[C] crawls free of the processor!") + return + for(var/i = 1, i <= C, i++) + new S.coretype(loc) + feedback_add_details("slime_core_harvested","[replacetext(S.colour," ","_")]") + ..() + input = /mob/living/carbon/slime + output = null + + monkey + process(loc, what) + var/mob/living/carbon/monkey/O = what + if (O.client) //grief-proof + O.loc = loc + O.visible_message("[O] suddenly jumps out of [src]!", \ + "You jump out from the processor", \ + "You hear a slimy sound") + return + var/obj/item/weapon/reagent_containers/glass/bucket/bucket_of_blood = new(loc) + var/datum/reagent/blood/B = new() + B.holder = bucket_of_blood + B.volume = 70 + //set reagent data + B.data["donor"] = O + + for(var/datum/disease/D in O.viruses) + if(D.spread_type != SPECIAL) + B.data["viruses"] += D.Copy() + + B.data["blood_DNA"] = copytext(O.dna.unique_enzymes,1,0) + if(O.resistances&&O.resistances.len) + B.data["resistances"] = O.resistances.Copy() + bucket_of_blood.reagents.reagent_list += B + bucket_of_blood.reagents.update_total() + bucket_of_blood.on_reagent_change() + //bucket_of_blood.reagents.handle_reactions() //blood doesn't react + ..() + + input = /mob/living/carbon/monkey + output = null + + chicken + process(loc, what) + playsound(loc, 'sound/machines/ya_dun_clucked.ogg', 50, 1) + ..() + input = /mob/living/simple_animal/chicken + output = /obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets + + chick + process(loc, what) + playsound(loc, 'sound/machines/ya_dun_clucked.ogg', 50, 1) + ..() + input = /mob/living/simple_animal/chick + output = /obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets + + human + process(loc, what) + var/mob/living/carbon/human/target = what + if (istype(target.wear_suit,/obj/item/clothing/suit/chickensuit) && istype(target.head,/obj/item/clothing/head/chicken)) + target.visible_message("Bwak! Bwak! Bwak!") + playsound(loc, 'sound/machines/ya_dun_clucked.ogg', 50, 1) + target.canmove = 0 + target.icon = null + target.invisibility = 101 + target.density = 0 + var/throwzone = list() + for(var/turf/T in orange(loc,4)) + throwzone += T + for(var/obj/I in target.contents) + I.loc = loc + I.throw_at(pick(throwzone),rand(2,5),0) + hgibs(loc, target.viruses, target.dna, target.species.flesh_color, target.species.blood_color) + qdel(target) + target = null + for(var/i = 1;i<=6;i++) + new /obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets(loc) + sleep(2) + ..() + else + target.loc = loc + target.visible_message("The processor's safety protocols won't allow it to cut something that looks human!") + input = /mob/living/carbon/human + output = null + +/obj/machinery/processor/proc/select_recipe(var/X) + for (var/Type in typesof(/datum/food_processor_process) - /datum/food_processor_process - /datum/food_processor_process/mob) + var/datum/food_processor_process/P = new Type() + if (!istype(X, P.input)) + continue + return P + return 0 + +/obj/machinery/processor/crowbarDestroy(mob/user) + if(contents.len) + to_chat(user, "You can't do that while something is loaded in \the [src].") + return -1 + return ..() + +/obj/machinery/processor/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(src.processing) + to_chat(user, "[src] is already processing!") + return 1 + + if(..()) + return 1 + if(src.contents.len > 0) //TODO: several items at once? several different items? + to_chat(user, "Something is already in [src].") + return 1 + var/atom/movable/what = O + if (istype(O, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = O + what = G.affecting + + var/datum/food_processor_process/P = select_recipe(what) + if (!P) + to_chat(user, "This probably won't blend.") + return 1 + user.visible_message("[user] puts [what] into [src].", \ + "You put [what] into the [src].") + if(what == user.get_active_hand()) + user.drop_item(what, src) + else + if(O.loc == user) + user.drop_item(O) + what.loc = src + return + +/obj/machinery/processor/attack_hand(var/mob/user as mob) + if (src.stat != 0) //NOPOWER etc + return + if(!anchored) + to_chat(user, "[src] must be anchored first!") + return + if(src.processing) + to_chat(user, "[src] is already processing!") + return 1 + if(src.contents.len == 0) + to_chat(user, "[src] is empty!") + return 1 + for(var/O in src.contents) + var/datum/food_processor_process/P = select_recipe(O) + if (!P) + log_admin("DEBUG: [O] in processor is not suitable. How did you put it in?") //-rastaf0 + continue + src.processing = 1 + user.visible_message("[user] turns on [src].", \ + "You turn on \a [src].", \ + "You hear [src] start") + playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1) + use_power(500) + sleep(P.time*time_coeff) + P.process(src.loc, O) + src.processing = 0 + src.visible_message("[src] is done.", \ + "You hear [src] stop") + +/obj/machinery/processor/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + attackby(O,user) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index 38e0af94fa4..189ed72fcd3 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -1,350 +1,350 @@ -/* SmartFridge. Much todo -*/ -/obj/machinery/smartfridge - name = "\improper SmartFridge" - icon = 'icons/obj/vending.dmi' - icon_state = "smartfridge" - layer = 2.9 - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - flags = NOREACT - var/icon_on = "smartfridge" - var/icon_off = "smartfridge-off" - var/item_quants = list() - //var/ispowered = 1 //starts powered - //var/isbroken = 0 - //OBSOLETE: That's what the BROKEN and NOPOWER stat bitflags are for - var/opened = 0.0 - - var/list/accepted_types = list( /obj/item/weapon/reagent_containers/food/snacks/grown, - /obj/item/weapon/grown, - /obj/item/seeds/, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/egg) - - machine_flags = SCREWTOGGLE | CROWDESTROY | EJECTNOTDEL - - light_color = LIGHT_COLOR_CYAN - power_change() - ..() - if(!(stat & (BROKEN|NOPOWER))) - set_light(2) - else - set_light(0) - - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -/obj/machinery/smartfridge/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smartfridge, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj, var/mob/user as mob) - for(var/ac_type in accepted_types) - if(istype(O, ac_type)) - return 1 - -/obj/machinery/smartfridge/seeds - name = "\improper MegaSeed Servitor" - desc = "When you need seeds fast!" - icon = 'icons/obj/vending.dmi' - icon_state = "seeds" - icon_on = "seeds" - icon_off = "seeds-off" - - accepted_types = list(/obj/item/seeds) - - light_color = null - -/obj/machinery/smartfridge/seeds/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smartfridge/seeds, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/smartfridge/secure/medbay - name = "\improper Refrigerated Medicine Storage" - desc = "A refrigerated storage unit for storing medicine and chemicals." - icon_state = "smartfridge" //To fix the icon in the map editor. - icon_on = "smartfridge_chem" - req_one_access = list(access_chemistry, access_medical) - - accepted_types = list( /obj/item/weapon/reagent_containers/glass, - /obj/item/weapon/storage/pill_bottle, - /obj/item/weapon/reagent_containers/pill) - -/obj/machinery/smartfridge/medbay/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smartfridge/medbay, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/smartfridge/chemistry - name = "\improper Smart Chemical Storage" - desc = "A refrigerated storage unit for medicine and chemical storage." - - accepted_types = list( /obj/item/weapon/storage/pill_bottle, - /obj/item/weapon/reagent_containers) - -/obj/machinery/smartfridge/chemistry/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smartfridge/chemistry, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/smartfridge/drinks - name = "\improper Drink Showcase" - desc = "A refrigerated storage unit for tasty tasty alcohol." - - accepted_types = list( /obj/item/weapon/reagent_containers/glass, - /obj/item/weapon/reagent_containers/food/drinks, - /obj/item/weapon/reagent_containers/food/condiment) - -/obj/machinery/smartfridge/drinks/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smartfridge/drinks, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - -/obj/machinery/smartfridge/extract - name = "\improper Slime Extract Storage" - desc = "A refrigerated storage unit for slime extracts" - - accepted_types = list(/obj/item/slime_extract) - -/obj/machinery/smartfridge/extract/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smartfridge/extract, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - - -/obj/machinery/smartfridge/power_change() - if( powered() ) - stat &= ~NOPOWER - if(!(stat & BROKEN)) - icon_state = icon_on - else - spawn(rand(0, 15)) - stat |= NOPOWER - if(!(stat & BROKEN)) - icon_state = icon_off - - -/******************* -* Item Adding -********************/ - -/obj/machinery/smartfridge/attackby(var/obj/item/O as obj, var/mob/user as mob, params) - if(stat & NOPOWER) +/* SmartFridge. Much todo +*/ +/obj/machinery/smartfridge + name = "\improper SmartFridge" + icon = 'icons/obj/vending.dmi' + icon_state = "smartfridge" + layer = 2.9 + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 + flags = NOREACT + var/icon_on = "smartfridge" + var/icon_off = "smartfridge-off" + var/item_quants = list() + //var/ispowered = 1 //starts powered + //var/isbroken = 0 + //OBSOLETE: That's what the BROKEN and NOPOWER stat bitflags are for + var/opened = 0.0 + + var/list/accepted_types = list( /obj/item/weapon/reagent_containers/food/snacks/grown, + /obj/item/weapon/grown, + /obj/item/seeds/, + /obj/item/weapon/reagent_containers/food/snacks/meat, + /obj/item/weapon/reagent_containers/food/snacks/egg) + + machine_flags = SCREWTOGGLE | CROWDESTROY | EJECTNOTDEL + + light_color = LIGHT_COLOR_CYAN + power_change() + ..() + if(!(stat & (BROKEN|NOPOWER))) + set_light(2) + else + set_light(0) + + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +/obj/machinery/smartfridge/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smartfridge, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj, var/mob/user as mob) + for(var/ac_type in accepted_types) + if(istype(O, ac_type)) + return 1 + +/obj/machinery/smartfridge/seeds + name = "\improper MegaSeed Servitor" + desc = "When you need seeds fast!" + icon = 'icons/obj/vending.dmi' + icon_state = "seeds" + icon_on = "seeds" + icon_off = "seeds-off" + + accepted_types = list(/obj/item/seeds) + + light_color = null + +/obj/machinery/smartfridge/seeds/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smartfridge/seeds, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/smartfridge/secure/medbay + name = "\improper Refrigerated Medicine Storage" + desc = "A refrigerated storage unit for storing medicine and chemicals." + icon_state = "smartfridge" //To fix the icon in the map editor. + icon_on = "smartfridge_chem" + req_one_access = list(access_chemistry, access_medical) + + accepted_types = list( /obj/item/weapon/reagent_containers/glass, + /obj/item/weapon/storage/pill_bottle, + /obj/item/weapon/reagent_containers/pill) + +/obj/machinery/smartfridge/medbay/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smartfridge/medbay, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/smartfridge/chemistry + name = "\improper Smart Chemical Storage" + desc = "A refrigerated storage unit for medicine and chemical storage." + + accepted_types = list( /obj/item/weapon/storage/pill_bottle, + /obj/item/weapon/reagent_containers) + +/obj/machinery/smartfridge/chemistry/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smartfridge/chemistry, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/smartfridge/drinks + name = "\improper Drink Showcase" + desc = "A refrigerated storage unit for tasty tasty alcohol." + + accepted_types = list( /obj/item/weapon/reagent_containers/glass, + /obj/item/weapon/reagent_containers/food/drinks, + /obj/item/weapon/reagent_containers/food/condiment) + +/obj/machinery/smartfridge/drinks/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smartfridge/drinks, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + +/obj/machinery/smartfridge/extract + name = "\improper Slime Extract Storage" + desc = "A refrigerated storage unit for slime extracts" + + accepted_types = list(/obj/item/slime_extract) + +/obj/machinery/smartfridge/extract/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smartfridge/extract, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + + +/obj/machinery/smartfridge/power_change() + if( powered() ) + stat &= ~NOPOWER + if(!(stat & BROKEN)) + icon_state = icon_on + else + spawn(rand(0, 15)) + stat |= NOPOWER + if(!(stat & BROKEN)) + icon_state = icon_off + + +/******************* +* Item Adding +********************/ + +/obj/machinery/smartfridge/attackby(var/obj/item/O as obj, var/mob/user as mob, params) + if(stat & NOPOWER) to_chat(user, "\The [src] is unpowered and useless.") - return 1 - - if(..()) - return 1 - - if(accept_check(O)) - if(contents.len >= MAX_N_OF_ITEMS) + return 1 + + if(..()) + return 1 + + if(accept_check(O)) + if(contents.len >= MAX_N_OF_ITEMS) to_chat(user, "\The [src] is full.") - return 1 - else - if(!user.drop_item(O, src)) - return 1 - - var/sanitized_name = sanitize(O.name, list("\"" = "", "'" = "", "+" = "plus", ";" = "", "^" = "", "&" = "", "<" = "", ">" = "")) - O.name = sanitized_name - if(item_quants[sanitized_name]) - item_quants[sanitized_name]++ - else - item_quants[sanitized_name] = 1 - user.visible_message("[user] has added \the [O] to \the [src].", \ - "You add \the [O] to \the [src].") - - else if(istype(O, /obj/item/weapon/storage/bag)) - var/obj/item/weapon/storage/bag/bag = O - var/objects_loaded = 0 - for(var/obj/G in bag.contents) - if(accept_check(G)) - if(contents.len >= MAX_N_OF_ITEMS) + return 1 + else + if(!user.drop_item(O, src)) + return 1 + + var/sanitized_name = sanitize(O.name, list("\"" = "", "'" = "", "+" = "plus", ";" = "", "^" = "", "&" = "", "<" = "", ">" = "")) + O.name = sanitized_name + if(item_quants[sanitized_name]) + item_quants[sanitized_name]++ + else + item_quants[sanitized_name] = 1 + user.visible_message("[user] has added \the [O] to \the [src].", \ + "You add \the [O] to \the [src].") + + else if(istype(O, /obj/item/weapon/storage/bag)) + var/obj/item/weapon/storage/bag/bag = O + var/objects_loaded = 0 + for(var/obj/G in bag.contents) + if(accept_check(G)) + if(contents.len >= MAX_N_OF_ITEMS) to_chat(user, "\The [src] is full.") - return 1 - else - bag.remove_from_storage(G,src) - var/sanitized_name = sanitize(G.name, list("\"" = "", "'" = "", "+" = "plus", ";" = "", "^" = "", "&" = "", "<" = "", ">" = "")) - G.name = sanitized_name - if(item_quants[sanitized_name]) - item_quants[sanitized_name]++ - else - item_quants[sanitized_name] = 1 - objects_loaded++ - if(objects_loaded) - - user.visible_message("[user] loads \the [src] with \the [bag].", \ - "You load \the [src] with \the [bag].") - if(bag.contents.len > 0) + return 1 + else + bag.remove_from_storage(G,src) + var/sanitized_name = sanitize(G.name, list("\"" = "", "'" = "", "+" = "plus", ";" = "", "^" = "", "&" = "", "<" = "", ">" = "")) + G.name = sanitized_name + if(item_quants[sanitized_name]) + item_quants[sanitized_name]++ + else + item_quants[sanitized_name] = 1 + objects_loaded++ + if(objects_loaded) + + user.visible_message("[user] loads \the [src] with \the [bag].", \ + "You load \the [src] with \the [bag].") + if(bag.contents.len > 0) to_chat(user, "Some items are refused.") - - else if(istype(O, /obj/item/weapon/paper) && user.drop_item(O, src.loc)) - var/list/params_list = params2list(params) - if(O.loc == src.loc && params_list.len) - var/clamp_x = 16 - var/clamp_y = 16 - O.pixel_x = Clamp(text2num(params_list["icon-x"]) - clamp_x, -clamp_x, clamp_x) - O.pixel_y = Clamp(text2num(params_list["icon-y"]) - clamp_y, -clamp_y, clamp_y) + + else if(istype(O, /obj/item/weapon/paper) && user.drop_item(O, src.loc)) + var/list/params_list = params2list(params) + if(O.loc == src.loc && params_list.len) + var/clamp_x = 16 + var/clamp_y = 16 + O.pixel_x = Clamp(text2num(params_list["icon-x"]) - clamp_x, -clamp_x, clamp_x) + O.pixel_y = Clamp(text2num(params_list["icon-y"]) - clamp_y, -clamp_y, clamp_y) to_chat(user, "You hang \the [O.name] on the fridge.") - else + else to_chat(user, "\The [src] smartly refuses [O].") - return 1 - item_quants = sortList(item_quants) - updateUsrDialog() - return 1 - -/obj/machinery/smartfridge/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/smartfridge/attack_ai(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/smartfridge/attack_hand(mob/user as mob) - user.set_machine(src) - interact(user) - -/******************* -* SmartFridge Menu -********************/ - -/obj/machinery/smartfridge/interact(mob/user as mob) - if(stat & NOPOWER) - 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] - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\kitchen\smartfridge.dm:140: dat += "[capitalize(O)]:" - dat += {"[capitalize(O)]: - [N] -
      Vend "} - // END AUTOFIX - if(N > 5) - dat += "(x5)" - if(N > 10) - dat += "(x10)" - if(N > 25) - dat += "(x25)" - if(N > 1) - dat += "(All)" - dat += "
      " - - dat += "
      " - user << browse("[src] Supplies[dat]", "window=smartfridge") - onclose(user, "smartfridge") - return - -/obj/machinery/smartfridge/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - - var/N = href_list["vend"] - var/amount = text2num(href_list["amount"]) - - if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. - return - - item_quants[N] = max(item_quants[N] - amount, 0) - - var/i = amount - for(var/obj/O in contents) - if(O.name == N) - O.loc = src.loc - i-- - if(i <= 0) - break - - src.updateUsrDialog() - return + return 1 + item_quants = sortList(item_quants) + updateUsrDialog() + return 1 + +/obj/machinery/smartfridge/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/smartfridge/attack_ai(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/smartfridge/attack_hand(mob/user as mob) + user.set_machine(src) + interact(user) + +/******************* +* SmartFridge Menu +********************/ + +/obj/machinery/smartfridge/interact(mob/user as mob) + if(stat & NOPOWER) + 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] + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\kitchen\smartfridge.dm:140: dat += "[capitalize(O)]:" + dat += {"[capitalize(O)]: + [N] + Vend "} + // END AUTOFIX + if(N > 5) + dat += "(x5)" + if(N > 10) + dat += "(x10)" + if(N > 25) + dat += "(x25)" + if(N > 1) + dat += "(All)" + dat += "
      " + + dat += "
      " + user << browse("[src] Supplies[dat]", "window=smartfridge") + onclose(user, "smartfridge") + return + +/obj/machinery/smartfridge/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + + var/N = href_list["vend"] + var/amount = text2num(href_list["amount"]) + + if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. + return + + item_quants[N] = max(item_quants[N] - amount, 0) + + var/i = amount + for(var/obj/O in contents) + if(O.name == N) + O.loc = src.loc + i-- + if(i <= 0) + break + + src.updateUsrDialog() + return diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index aac5c8096e3..be073cb99e2 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -1,127 +1,127 @@ -// the light switch -// can have multiple per area -// can also operate on non-loc area through "otherarea" var -/obj/machinery/light_switch - desc = "It turns lights on and off. What are you, simple?" - icon = 'icons/obj/power.dmi' - icon_state = "light1" - anchored = 1.0 - var/buildstage = 2 - var/on = 0 - // luminosity = 1 - -/obj/machinery/light_switch/New(var/loc, var/ndir, var/building = 2) - ..() - name = "[areaMaster.name] light switch" - buildstage = building - if(buildstage) - on = areaMaster.lightswitch - else - pixel_x = (ndir & 3)? 0 : (ndir == 4 ? 28 : -28) - pixel_y = (ndir & 3)? (ndir ==1 ? 28 : -28) : 0 - dir = ndir - updateicon() - -/obj/machinery/light_switch/proc/updateicon() - if ((stat & NOPOWER) || buildstage != 2) - icon_state = "light-p" - else - icon_state = on ? "light1" : "light0" - -/obj/machinery/light_switch/examine(mob/user) - ..() +// the light switch +// can have multiple per area +// can also operate on non-loc area through "otherarea" var +/obj/machinery/light_switch + desc = "It turns lights on and off. What are you, simple?" + icon = 'icons/obj/power.dmi' + icon_state = "light1" + anchored = 1.0 + var/buildstage = 2 + var/on = 0 + // luminosity = 1 + +/obj/machinery/light_switch/New(var/loc, var/ndir, var/building = 2) + ..() + name = "[areaMaster.name] light switch" + buildstage = building + if(buildstage) + on = areaMaster.lightswitch + else + pixel_x = (ndir & 3)? 0 : (ndir == 4 ? 28 : -28) + pixel_y = (ndir & 3)? (ndir ==1 ? 28 : -28) : 0 + dir = ndir + updateicon() + +/obj/machinery/light_switch/proc/updateicon() + if ((stat & NOPOWER) || buildstage != 2) + icon_state = "light-p" + else + icon_state = on ? "light1" : "light0" + +/obj/machinery/light_switch/examine(mob/user) + ..() to_chat(user, "It is [on? "on" : "off"].") - -/obj/machinery/light_switch/attackby(obj/item/W as obj, mob/user as mob) - switch(buildstage) - if(2) - if(isscrewdriver(W)) + +/obj/machinery/light_switch/attackby(obj/item/W as obj, mob/user as mob) + switch(buildstage) + if(2) + if(isscrewdriver(W)) to_chat(user, "You begin unscrewing \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src,10)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src,10)) to_chat(user, "You unscrew the cover blocking the inner wiring of \the [src].") - buildstage = 1 - on = areaMaster.lightswitch - return - if(1) - if(isscrewdriver(W)) + buildstage = 1 + on = areaMaster.lightswitch + return + if(1) + if(isscrewdriver(W)) to_chat(user, "You begin screwing closed \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src,10)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src,10)) to_chat(user, "You tightly screw closed the cover of \the [src].") - buildstage = 2 - power_change() - return - if(iswirecutter(W)) + buildstage = 2 + power_change() + return + if(iswirecutter(W)) to_chat(user, "You begin cutting the wiring from \the [src].") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - if(do_after(user, src,10)) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + if(do_after(user, src,10)) to_chat(user, "You cut the wiring to the lighting power line.") - new /obj/item/stack/cable_coil(get_turf(src),3) - buildstage = 0 - return - if(0) - if(iscoil(W)) - var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 3) + new /obj/item/stack/cable_coil(get_turf(src),3) + buildstage = 0 + return + if(0) + if(iscoil(W)) + var/obj/item/stack/cable_coil/coil = W + if(coil.amount < 3) to_chat(user, "You need at least two wire pieces for this!") - return + return to_chat(user, "You begin wiring \the [src].") - if(do_after(user, src,10)) + if(do_after(user, src,10)) to_chat(user, "You wire \the [src]!.") - coil.use(3) - buildstage = 1 - return - if(iscrowbar(W)) + coil.use(3) + buildstage = 1 + return + if(iscrowbar(W)) to_chat(user, "You begin prying \the [src] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src,10)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src,10)) to_chat(user, "You pry the frame off of the wall.") - new /obj/item/mounted/frame/light_switch(get_turf(user)) - qdel(src) - return - return ..() - -/obj/machinery/light_switch/attack_paw(mob/user) - src.attack_hand(user) - -/obj/machinery/light_switch/attack_ghost(var/mob/dead/observer/G) - if(blessed) + new /obj/item/mounted/frame/light_switch(get_turf(user)) + qdel(src) + return + return ..() + +/obj/machinery/light_switch/attack_paw(mob/user) + src.attack_hand(user) + +/obj/machinery/light_switch/attack_ghost(var/mob/dead/observer/G) + if(blessed) to_chat(G, "Your hand goes right through the switch...Is that some holy water dripping from it?") - return 0 - if(!G.can_poltergeist()) + return 0 + if(!G.can_poltergeist()) to_chat(G, "Your poltergeist abilities are still cooling down.") - return 0 - return ..() - -/obj/machinery/light_switch/attack_hand(mob/user) - if(buildstage != 2) return - on = !on - - areaMaster.lightswitch = on - areaMaster.updateicon() - - for(var/obj/machinery/light_switch/L in areaMaster) - L.on = on - L.updateicon() - - areaMaster.power_change() - -/obj/machinery/light_switch/power_change() - if(powered(LIGHT)) - stat &= ~NOPOWER - else - stat |= NOPOWER - - updateicon() - -/obj/machinery/light_switch/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - power_change() - ..(severity) - -/obj/machinery/light_switch/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) + return 0 + return ..() + +/obj/machinery/light_switch/attack_hand(mob/user) + if(buildstage != 2) return + on = !on + + areaMaster.lightswitch = on + areaMaster.updateicon() + + for(var/obj/machinery/light_switch/L in areaMaster) + L.on = on + L.updateicon() + + areaMaster.power_change() + +/obj/machinery/light_switch/power_change() + if(powered(LIGHT)) + stat &= ~NOPOWER + else + stat |= NOPOWER + + updateicon() + +/obj/machinery/light_switch/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + power_change() + ..(severity) + +/obj/machinery/light_switch/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index c3f5f05dece..6305a56ce94 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -1,706 +1,706 @@ -//multitool programming whitelist -var/global/list/multitool_var_whitelist = list( "id_tag", - "master_tag", - "command", - "input_tag", - "output_tag", - "tag_airpump", - "tag_exterior_door", - "tag_interior_door", - "tag_chamber_sensor", - "tag_interior_sensor", - "tag_exterior_sensor", - "smelter_tag", - "stacker_tag" - ) - -/* -Overview: - Used to create objects that need a per step proc call. Default definition of 'New()' - stores a reference to src machine in global 'machines list'. Default definition - of 'Del' removes reference to src machine in global 'machines list'. - -Class Variables: - use_power (num) - current state of auto power use. - Possible Values: - 0 -- no auto power use - 1 -- machine is using power at its idle power level - 2 -- machine is using power at its active power level - - active_power_usage (num) - Value for the amount of power to use when in active power mode - - idle_power_usage (num) - Value for the amount of power to use when in idle power mode - - power_channel (num) - What channel to draw from when drawing power for power mode - Possible Values: - EQUIP:0 -- Equipment Channel - LIGHT:2 -- Lighting Channel - ENVIRON:3 -- Environment Channel - - component_parts (list) - A list of component parts of machine used by frame based machines. - - uid (num) - Unique id of machine across all machines. - - gl_uid (global num) - Next uid value in sequence - - stat (bitflag) - Machine status bit flags. - Possible bit flags: - BROKEN:1 -- Machine is broken - NOPOWER:2 -- No power is being supplied to machine. - POWEROFF:4 -- tbd - MAINT:8 -- machine is currently under going maintenance. - EMPED:16 -- temporary broken by EMP pulse - - manual (num) - Currently unused. - -Class Procs: - New() 'game/machinery/machine.dm' - - Destroy() 'game/machinery/machine.dm' - - auto_use_power() 'game/machinery/machine.dm' - This proc determines how power mode power is deducted by the machine. - 'auto_use_power()' is called by the 'master_controller' game_controller every - tick. - - Return Value: - return:1 -- if object is powered - return:0 -- if object is not powered. - - Default definition uses 'use_power', 'power_channel', 'active_power_usage', - 'idle_power_usage', 'powered()', and 'use_power()' implement behavior. - - powered(chan = EQUIP) 'modules/power/power.dm' - Checks to see if area that contains the object has power available for power - channel given in 'chan'. - - use_power(amount, chan=EQUIP) 'modules/power/power.dm' - Deducts 'amount' from the power channel 'chan' of the area that contains the object. - - power_change() 'modules/power/power.dm' - Called by the area that contains the object when ever that area under goes a - power state change (area runs out of power, or area channel is turned off). - - RefreshParts() 'game/machinery/machine.dm' - Called to refresh the variables in the machine that are contributed to by parts - contained in the component_parts list. (example: glass and material amounts for - the autolathe) - - Default definition does nothing. - - assign_uid() 'game/machinery/machine.dm' - Called by machine to assign a value to the uid variable. - - process() 'game/machinery/machine.dm' - Called by the 'master_controller' once per game tick for each machine that is listed in the 'machines' list. - - - Compiled by Aygar -*/ - -//The machine flags can be found in setup.dm - -/obj/machinery - name = "machinery" - icon = 'icons/obj/stationobjs.dmi' - var/icon_state_open = "" - - w_type = NOT_RECYCLABLE - - penetration_dampening = 5 - - var/stat = 0 - var/emagged = 0 - var/use_power = 1 - //0 = dont run the auto - //1 = run auto, use idle - //2 = run auto, use active - var/idle_power_usage = 0 - var/active_power_usage = 0 - var/power_channel = EQUIP // EQUIP, ENVIRON or LIGHT. - var/list/component_parts // List of all the parts used to build it, if made from certain kinds of frames. - var/uid - var/manual = 0 - var/global/gl_uid = 1 - var/custom_aghost_alerts=0 - var/panel_open = 0 - var/state = 0 //0 is unanchored, 1 is anchored and unwelded, 2 is anchored and welded for most things - - //These are some values to automatically set the light power/range on machines if they have power - var/light_range_on = 0 - var/light_power_on = 0 - var/use_auto_lights = 0//Incase you want to use it, set this to 0, defaulting to 1 so machinery with no lights doesn't call set_light() - - /** - * Machine construction/destruction/emag flags. - */ - var/machine_flags = 0 - - /** - * Emag energy cost (in MJ). - */ - var/emag_cost = 1 - - var/inMachineList = 1 // For debugging. - -/obj/machinery/cultify() - var/list/random_structure = list( - /obj/structure/cult/talisman, - /obj/structure/cult/forge, - /obj/structure/cult/tome - ) - var/I = pick(random_structure) - new I(loc) - ..() - -/obj/machinery/New() - machines += src - //if(ticker) initialize() - return ..() - -/obj/machinery/initialize() - if(machine_flags & PURCHASER) - reconnect_database() - linked_account = vendor_account - -/obj/machinery/examine(mob/user) - ..() - if(panel_open) - to_chat(user, "Its maintenance panel is open.") - -/obj/machinery/Destroy() - - machines.Remove(src) - - power_machines.Remove(src) - - atmos_machines.Remove(src) - - fast_machines.Remove(src) -/* - if(component_parts) - for(var/atom/movable/AM in component_parts) - AM.loc = loc - component_parts -= AM -*/ - component_parts = null - - ..() - -/obj/machinery/projectile_check() - return PROJREACT_OBJS - -/obj/machinery/process() // If you dont use process or power why are you here - return PROCESS_KILL - -/obj/machinery/emp_act(severity) - if(use_power && stat == 0) - use_power(7500/severity) - - var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.dir = pick(cardinal) - - spawn(10) - qdel(pulse2) - ..() - -/obj/machinery/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(25)) - qdel(src) - return - else - return - -/obj/machinery/blob_act() - if(prob(50)) - qdel(src) - -/obj/machinery/proc/auto_use_power() - if(!powered(power_channel)) - return 0 - - switch (use_power) - if (1) - use_power(idle_power_usage, power_channel) - if (2) - use_power(active_power_usage, power_channel) - - return 1 - -/obj/machinery/proc/multitool_topic(var/mob/user,var/list/href_list,var/obj/O) - if("set_id" in href_list) - if(!("id_tag" in vars)) - warning("set_id: [type] has no id_tag var.") - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN) - if(newid) - src:id_tag = newid - return MT_UPDATE|MT_REINIT - if("set_freq" in href_list) - if(!("frequency" in vars)) - warning("set_freq: [type] has no frequency var.") - return 0 - var/newfreq=src:frequency - if(href_list["set_freq"]!="-1") - newfreq=text2num(href_list["set_freq"]) - else - newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, src:frequency) as null|num - if(newfreq) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - src:frequency = newfreq - return MT_UPDATE|MT_REINIT - return 0 - -/obj/machinery/proc/handle_multitool_topic(var/href, var/list/href_list, var/mob/user) - var/obj/item/device/multitool/P = get_multitool(usr) - if(P && istype(P)) - var/update_mt_menu=0 - var/re_init=0 - if("set_tag" in href_list) - if(!(href_list["set_tag"] in multitool_var_whitelist)) - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src) as null|text),1,MAX_MESSAGE_LEN) - log_admin("[usr] ([formatPlayerPanel(usr,usr.ckey)]) attempted to modify variable(var = [href_list["set_tag"]], value = [newid]) using multitool - [formatJumpTo(usr)]") - message_admins("[usr] ([formatPlayerPanel(usr,usr.ckey)]) attempted to modify variable(var = [href_list["set_tag"]], value = [newid]) using multitool - [formatJumpTo(usr)]") - return - if(!(href_list["set_tag"] in vars)) - to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!") - return 1 - var/current_tag = src.vars[href_list["set_tag"]] - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src, current_tag) as null|text),1,MAX_MESSAGE_LEN) - if(newid) - vars[href_list["set_tag"]] = newid - re_init=1 - update_mt_menu = 1 - - if("unlink" in href_list) - var/idx = text2num(href_list["unlink"]) - if (!idx) - return 1 - - var/obj/O = getLink(idx) - if(!O) - return 1 - - if(unlinkFrom(usr, O)) - to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.") - else - to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.") - update_mt_menu=1 - - if("link" in href_list) - var/obj/O = P.buffer - if(!O) - return 1 - if(!canLink(O,href_list)) - to_chat(usr, "You can't link with that device.") - return 1 - if (isLinkedWith(O)) - to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.") - return 1 - - if(linkWith(usr, O, href_list)) - to_chat(usr, "A green light flashes on \the [P], confirming the link has been created.") - else - to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.") - update_mt_menu=1 - - if("buffer" in href_list) - if(istype(src, /obj/machinery/telecomms)) - if(!hasvar(src, "id")) - to_chat(usr, "A red light flashes and nothing changes.") - return - else if(!hasvar(src, "id_tag")) - to_chat(usr, "A red light flashes and nothing changes.") - return - P.buffer = src - to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.") - update_mt_menu=1 - - if("flush" in href_list) - to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.") - P.buffer = null - update_mt_menu=1 - - var/ret = multitool_topic(usr,href_list,P.buffer) - if(ret == MT_ERROR) - return 1 - if(ret & MT_UPDATE) - update_mt_menu=1 - if(ret & MT_REINIT) - re_init=1 - - if(re_init) - initialize() - if(update_mt_menu) - //usr.set_machine(src) - update_multitool_menu(usr) - return 1 - -/obj/machinery/Topic(href, href_list) - ..() - if(stat & (NOPOWER|BROKEN)) - return 1 - if(href_list["close"]) - return - var/ghost_flags=0 - if(ghost_write) - ghost_flags |= PERMIT_ALL - if(!canGhostWrite(usr,src,"",ghost_flags)) - if(usr.restrained() || usr.lying || usr.stat) - return 1 - if (!usr.dexterity_check()) - to_chat(usr, "You don't have the dexterity to do this!") - return 1 - var/turf/T = get_turf(usr) - if(!isAI(usr) && T.z != z) - if(usr.z != 2) - to_chat(usr, "WARNING: Unable to interface with \the [src.name].") - return 1 - if ((!in_range(src, usr) || !istype(src.loc, /turf)) && !istype(usr, /mob/living/silicon)) - return 1 - else if(!custom_aghost_alerts) - log_adminghost("[key_name(usr)] screwed with [src] ([href])!") - - src.add_fingerprint(usr) - src.add_hiddenprint(usr) - - handle_multitool_topic(href,href_list,usr) - return 0 - -/obj/machinery/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - if(isrobot(user)) - // For some reason attack_robot doesn't work - // This is to stop robots from using cameras to remotely control machines. - if(user.client && user.client.eye == user) - return src.attack_hand(user) - else - return src.attack_hand(user) - -/obj/machinery/attack_ghost(mob/user as mob) - src.add_hiddenprint(user) - var/ghost_flags=0 - if(ghost_read) - ghost_flags |= PERMIT_ALL - if(canGhostRead(usr,src,ghost_flags)) - return src.attack_ai(user) - -/obj/machinery/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/attack_hand(mob/user as mob, var/ignore_brain_damage = 0) - if(stat & (NOPOWER|BROKEN|MAINT)) - return 1 - - if(user.lying || (user.stat && !canGhostRead(user))) // Ghost read-only - return 1 - - if(istype(user,/mob/dead/observer)) - return 0 - - if(!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return 1 -/* - //distance checks are made by atom/proc/DblClick - if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon)) - return 1 -*/ - if (ishuman(user) && !ignore_brain_damage) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - visible_message("[H] stares cluelessly at [src] and drools.") - return 1 - else if(prob(H.getBrainLoss())) - to_chat(user, "You momentarily forget how to use [src].") - return 1 - - src.add_fingerprint(user) - return 0 - -/obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames. - return - -/obj/machinery/proc/assign_uid() - uid = gl_uid - gl_uid++ - -/obj/machinery/proc/dropFrame() - var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc) - M.set_build_state(2) - M.state = 1 - -/obj/machinery/proc/spillContents(var/destroy_chance = 0) - for(var/obj/I in component_parts) - if(prob(destroy_chance)) - qdel(I) - else - if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker) && src:reagents && src:reagents.total_volume) - reagents.trans_to(I, reagents.total_volume) - if(I.reliability != 100 && crit_fail) - I.crit_fail = 1 - I.forceMove(src.loc) - for(var/atom/movable/I in src) //remove any stuff loaded, like for fridges - if(!prob(destroy_chance) && machine_flags &EJECTNOTDEL) - I.forceMove(src.loc) - else - qdel(I) - -/obj/machinery/proc/crowbarDestroy(mob/user) - user.visible_message( "[user] begins to pry out the circuitboard from \the [src].", - "You begin to pry out the circuitboard from \the [src]...") - if(do_after(user, src, 40)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - dropFrame() - spillContents() - user.visible_message( "[user] successfully pries out the circuitboard from \the [src]!", - "\icon[src] You successfully pry out the circuitboard from \the [src]!") - return 1 - return -1 - -//just something silly to delete the machine while still leaving something behind -/obj/machinery/proc/smashDestroy(var/destroy_chance = 50) - getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 2) - spillContents(destroy_chance) - qdel(src) - -/obj/machinery/proc/togglePanelOpen(var/obj/toggleitem, var/mob/user) - panel_open = !panel_open - if(!icon_state_open) - icon_state_open = icon_state - if(panel_open) - icon_state = icon_state_open - else - icon_state = initial(icon_state) - to_chat(user, "\icon[src] You [panel_open ? "open" : "close"] the maintenance hatch of \the [src].") - if(istype(toggleitem, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - update_icon() - return 1 - -/obj/machinery/proc/wrenchAnchor(var/mob/user) - if(state == 2 && src.machine_flags & WELD_FIXED) - to_chat(user, "\The [src] has to be unwelded from the floor first.") - return -1 //state set to 2, can't do it - for(var/obj/machinery/other in loc) - if(other.anchored == 1 && other.density == 1 && density && !anchored) - to_chat(user, "\The [other] is already anchored in this location.") - return -1 //other machines are already taking up all the space in this location - - if(!anchored) - if(!istype(src.loc, /turf/simulated/floor)) //Prevent from anchoring shit to shuttles / space - if( !(istype(src.loc, /turf/simulated/shuttle) && (machine_flags & SHUTTLEWRENCH)) ) //If NOT (on top of a shuttle AND can be secured to shuttles) - to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!") - return - - user.visible_message( "[user] begins to [anchored ? "undo" : "wrench"] \the [src]'s securing bolts.", - "You begin to [anchored ? "undo" : "wrench"] \the [src]'s securing bolts...") - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 30)) - anchored = !anchored - if(machine_flags & FIXED2WORK) - power_change() //updates us to turn on or off as necessary - state = anchored //since these values will match as long as state isn't 2, we can do this safely - user.visible_message( "[user] [anchored ? "wrench" : "unwrench"]es \the [src] [anchored ? "in place" : "from its fixture"]", - "\icon[src] You [anchored ? "wrench" : "unwrench"] \the [src] [anchored ? "in place" : "from its fixture"].", - "You hear a ratchet.") - return 1 - return -1 - -/obj/machinery/proc/weldToFloor(var/obj/item/weapon/weldingtool/WT, mob/user) - if(!anchored) - state = 0 //since this might be wrong, we go sanity - to_chat(user, "You need to secure \the [src] before it can be welded.") - return -1 - if (WT.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) - user.visible_message("[user.name] starts to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \ - "You start to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \ - "You hear welding.") - if (do_after(user, src,20)) - if(!src || !WT.isOn()) - return -1 - switch(state) - if(0) - to_chat(user, "You have to keep \the [src] secure before it can be welded down.") - return -1 - if(1) - state = 2 - if(2) - state = 1 - user.visible_message( "[user.name] [state - 1 ? "weld" : "unweld"]s \the [src] [state - 1 ? "to" : "from"] the floor.", - "\icon [src] You [state - 1 ? "weld" : "unweld"] \the [src] [state - 1 ? "to" : "from"] the floor." - ) - return 1 - else - to_chat(user, "You need more welding fuel to complete this task.") - return -1 - -/** - * Handle emags. - * @param user /mob The mob that used the emag. - */ -/obj/machinery/proc/emag(mob/user as mob) - // Disable emaggability. Note that some machines such as the Communications Computer might be emaggable multiple times. - machine_flags &= ~EMAGGABLE - new/obj/effect/effect/sparks(get_turf(src)) - playsound(loc,"sparks",50,1) - - -/** - * Returns the cost of emagging this machine (emag_cost by default) - * @param user /mob The mob that used the emag. - * @param emag /obj/item/weapon/card/emag The emag used on this device. - * @return number Cost to emag. - */ -/obj/machinery/proc/getEmagCost(var/mob/user, var/obj/item/weapon/card/emag/emag) - return emag_cost - -/obj/machinery/attackby(var/obj/O, var/mob/user) - if(istype(O, /obj/item/weapon/card/emag) && machine_flags & EMAGGABLE) - var/obj/item/weapon/card/emag/E = O - if(E.canUse(user,src)) - emag(user) - return - - if(istype(O, /obj/item/weapon/wrench) && machine_flags & WRENCHMOVE) //make sure this is BEFORE the fixed2work check - if(!panel_open) - return wrenchAnchor(user) - else - to_chat(user, "\The [src]'s maintenance panel must be closed first!") - return -1 //we return -1 rather than 0 for the if(..()) checks - - if(istype(O, /obj/item/weapon/screwdriver) && machine_flags & SCREWTOGGLE) - return togglePanelOpen(O, user) - - if(istype(O, /obj/item/weapon/weldingtool) && machine_flags & WELD_FIXED) - return weldToFloor(O, user) - - if(istype(O, /obj/item/weapon/crowbar) && machine_flags & CROWDESTROY) - if(panel_open) - if(crowbarDestroy(user) == 1) - qdel(src) - return 1 - else - return -1 - - if(ismultitool(O) && machine_flags & MULTITOOL_MENU) - update_multitool_menu(user) - return 1 - - if(!anchored && machine_flags & FIXED2WORK) - return to_chat(user, "\The [src] must be anchored first!") - - if(istype(O, /obj/item/device/paicard) && machine_flags & WIREJACK) - for(var/mob/M in O) - wirejack(M) - return 1 - - if(istype(O, /obj/item/weapon/storage/bag/gadgets/part_replacer)) - return exchange_parts(user, O) - -/obj/machinery/proc/wirejack(var/mob/living/silicon/pai/P) - if(!(machine_flags & WIREJACK)) - return 0 - if(!P.hackloop(src)) - return 0 - return 1 - -/obj/machinery/proc/shock(mob/user, prb, var/siemenspassed = -1) - if(stat & (BROKEN|NOPOWER)) // unpowered, no shock - 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(siemenspassed == -1) //this means it hasn't been set by proc arguments, so we can set it ourselves safely - siemenspassed = 0.7 - if (electrocute_mob(user, get_area(src), src, siemenspassed)) - return 1 - else - return 0 - -// Hook for html_interface module to prevent updates to clients who don't have this as their active machine. -/obj/machinery/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi) - if (hclient.client.mob && (hclient.client.mob.stat == 0 || isobserver(hclient.client.mob))) - if(isAI(hclient.client.mob)) - return 1 - if(hclient.client.mob.machine == src) - return hclient.client.mob.html_mob_check(src.type) - return FALSE - -// Hook for html_interface module to unset the active machine when the window is closed by the player. -/obj/machinery/proc/hiOnHide(datum/html_interface_client/hclient) - if (hclient.client.mob && hclient.client.mob.machine == src) hclient.client.mob.unset_machine() - -/obj/machinery/proc/alert_noise(var/notice_state = "ping") - switch(notice_state) - if("ping") - src.visible_message("\icon[src] \The [src] pings.") - playsound(get_turf(src), 'sound/machines/notify.ogg', 50, 0) - if("beep") - src.visible_message("\icon[src] \The [src] beeps.") - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) - if("buzz") - src.visible_message("\icon[src] \The [src] buzzes.") - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) - -/obj/machinery/proc/check_rebuild() - return - -/obj/machinery/proc/exchange_parts(mob/user, obj/item/weapon/storage/bag/gadgets/part_replacer/W) - var/shouldplaysound = 0 - if(component_parts) - if(panel_open) - var/obj/item/weapon/circuitboard/CB = locate(/obj/item/weapon/circuitboard) in component_parts - var/P - for(var/obj/item/A in component_parts) - for(var/D in CB.req_components) - D = text2path(D) //For some stupid reason these are strings by default. - if(ispath(A.type, D)) - P = D - break - for(var/obj/item/B in W.contents) - if(istype(B, P) && istype(A, P)) - if(B.get_rating() > A.get_rating()) - W.remove_from_storage(B, src) - W.handle_item_insertion(A, 1) - component_parts -= A - component_parts += B - B.loc = null - to_chat(user, "[A.name] replaced with [B.name].") - shouldplaysound = 1 //Only play the sound when parts are actually replaced! - break - RefreshParts() - else - to_chat(user, "Following parts detected in the machine:") - for(var/var/obj/item/C in component_parts) - to_chat(user, " [C.name]") - if(shouldplaysound) - W.play_rped_sound() - return 1 - return 0 +//multitool programming whitelist +var/global/list/multitool_var_whitelist = list( "id_tag", + "master_tag", + "command", + "input_tag", + "output_tag", + "tag_airpump", + "tag_exterior_door", + "tag_interior_door", + "tag_chamber_sensor", + "tag_interior_sensor", + "tag_exterior_sensor", + "smelter_tag", + "stacker_tag" + ) + +/* +Overview: + Used to create objects that need a per step proc call. Default definition of 'New()' + stores a reference to src machine in global 'machines list'. Default definition + of 'Del' removes reference to src machine in global 'machines list'. + +Class Variables: + use_power (num) + current state of auto power use. + Possible Values: + 0 -- no auto power use + 1 -- machine is using power at its idle power level + 2 -- machine is using power at its active power level + + active_power_usage (num) + Value for the amount of power to use when in active power mode + + idle_power_usage (num) + Value for the amount of power to use when in idle power mode + + power_channel (num) + What channel to draw from when drawing power for power mode + Possible Values: + EQUIP:0 -- Equipment Channel + LIGHT:2 -- Lighting Channel + ENVIRON:3 -- Environment Channel + + component_parts (list) + A list of component parts of machine used by frame based machines. + + uid (num) + Unique id of machine across all machines. + + gl_uid (global num) + Next uid value in sequence + + stat (bitflag) + Machine status bit flags. + Possible bit flags: + BROKEN:1 -- Machine is broken + NOPOWER:2 -- No power is being supplied to machine. + POWEROFF:4 -- tbd + MAINT:8 -- machine is currently under going maintenance. + EMPED:16 -- temporary broken by EMP pulse + + manual (num) + Currently unused. + +Class Procs: + New() 'game/machinery/machine.dm' + + Destroy() 'game/machinery/machine.dm' + + auto_use_power() 'game/machinery/machine.dm' + This proc determines how power mode power is deducted by the machine. + 'auto_use_power()' is called by the 'master_controller' game_controller every + tick. + + Return Value: + return:1 -- if object is powered + return:0 -- if object is not powered. + + Default definition uses 'use_power', 'power_channel', 'active_power_usage', + 'idle_power_usage', 'powered()', and 'use_power()' implement behavior. + + powered(chan = EQUIP) 'modules/power/power.dm' + Checks to see if area that contains the object has power available for power + channel given in 'chan'. + + use_power(amount, chan=EQUIP) 'modules/power/power.dm' + Deducts 'amount' from the power channel 'chan' of the area that contains the object. + + power_change() 'modules/power/power.dm' + Called by the area that contains the object when ever that area under goes a + power state change (area runs out of power, or area channel is turned off). + + RefreshParts() 'game/machinery/machine.dm' + Called to refresh the variables in the machine that are contributed to by parts + contained in the component_parts list. (example: glass and material amounts for + the autolathe) + + Default definition does nothing. + + assign_uid() 'game/machinery/machine.dm' + Called by machine to assign a value to the uid variable. + + process() 'game/machinery/machine.dm' + Called by the 'master_controller' once per game tick for each machine that is listed in the 'machines' list. + + + Compiled by Aygar +*/ + +//The machine flags can be found in setup.dm + +/obj/machinery + name = "machinery" + icon = 'icons/obj/stationobjs.dmi' + var/icon_state_open = "" + + w_type = NOT_RECYCLABLE + + penetration_dampening = 5 + + var/stat = 0 + var/emagged = 0 + var/use_power = 1 + //0 = dont run the auto + //1 = run auto, use idle + //2 = run auto, use active + var/idle_power_usage = 0 + var/active_power_usage = 0 + var/power_channel = EQUIP // EQUIP, ENVIRON or LIGHT. + var/list/component_parts // List of all the parts used to build it, if made from certain kinds of frames. + var/uid + var/manual = 0 + var/global/gl_uid = 1 + var/custom_aghost_alerts=0 + var/panel_open = 0 + var/state = 0 //0 is unanchored, 1 is anchored and unwelded, 2 is anchored and welded for most things + + //These are some values to automatically set the light power/range on machines if they have power + var/light_range_on = 0 + var/light_power_on = 0 + var/use_auto_lights = 0//Incase you want to use it, set this to 0, defaulting to 1 so machinery with no lights doesn't call set_light() + + /** + * Machine construction/destruction/emag flags. + */ + var/machine_flags = 0 + + /** + * Emag energy cost (in MJ). + */ + var/emag_cost = 1 + + var/inMachineList = 1 // For debugging. + +/obj/machinery/cultify() + var/list/random_structure = list( + /obj/structure/cult/talisman, + /obj/structure/cult/forge, + /obj/structure/cult/tome + ) + var/I = pick(random_structure) + new I(loc) + ..() + +/obj/machinery/New() + machines += src + //if(ticker) initialize() + return ..() + +/obj/machinery/initialize() + if(machine_flags & PURCHASER) + reconnect_database() + linked_account = vendor_account + +/obj/machinery/examine(mob/user) + ..() + if(panel_open) + to_chat(user, "Its maintenance panel is open.") + +/obj/machinery/Destroy() + + machines.Remove(src) + + power_machines.Remove(src) + + atmos_machines.Remove(src) + + fast_machines.Remove(src) +/* + if(component_parts) + for(var/atom/movable/AM in component_parts) + AM.loc = loc + component_parts -= AM +*/ + component_parts = null + + ..() + +/obj/machinery/projectile_check() + return PROJREACT_OBJS + +/obj/machinery/process() // If you dont use process or power why are you here + return PROCESS_KILL + +/obj/machinery/emp_act(severity) + if(use_power && stat == 0) + use_power(7500/severity) + + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + + spawn(10) + qdel(pulse2) + ..() + +/obj/machinery/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(25)) + qdel(src) + return + else + return + +/obj/machinery/blob_act() + if(prob(50)) + qdel(src) + +/obj/machinery/proc/auto_use_power() + if(!powered(power_channel)) + return 0 + + switch (use_power) + if (1) + use_power(idle_power_usage, power_channel) + if (2) + use_power(active_power_usage, power_channel) + + return 1 + +/obj/machinery/proc/multitool_topic(var/mob/user,var/list/href_list,var/obj/O) + if("set_id" in href_list) + if(!("id_tag" in vars)) + warning("set_id: [type] has no id_tag var.") + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag for this machine", src, src:id_tag) as null|text),1,MAX_MESSAGE_LEN) + if(newid) + src:id_tag = newid + return MT_UPDATE|MT_REINIT + if("set_freq" in href_list) + if(!("frequency" in vars)) + warning("set_freq: [type] has no frequency var.") + return 0 + var/newfreq=src:frequency + if(href_list["set_freq"]!="-1") + newfreq=text2num(href_list["set_freq"]) + else + newfreq = input(usr, "Specify a new frequency (GHz). Decimals assigned automatically.", src, src:frequency) as null|num + if(newfreq) + if(findtext(num2text(newfreq), ".")) + newfreq *= 10 // shift the decimal one place + if(newfreq < 10000) + src:frequency = newfreq + return MT_UPDATE|MT_REINIT + return 0 + +/obj/machinery/proc/handle_multitool_topic(var/href, var/list/href_list, var/mob/user) + var/obj/item/device/multitool/P = get_multitool(usr) + if(P && istype(P)) + var/update_mt_menu=0 + var/re_init=0 + if("set_tag" in href_list) + if(!(href_list["set_tag"] in multitool_var_whitelist)) + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src) as null|text),1,MAX_MESSAGE_LEN) + log_admin("[usr] ([formatPlayerPanel(usr,usr.ckey)]) attempted to modify variable(var = [href_list["set_tag"]], value = [newid]) using multitool - [formatJumpTo(usr)]") + message_admins("[usr] ([formatPlayerPanel(usr,usr.ckey)]) attempted to modify variable(var = [href_list["set_tag"]], value = [newid]) using multitool - [formatJumpTo(usr)]") + return + if(!(href_list["set_tag"] in vars)) + to_chat(usr, "Something went wrong: Unable to find [href_list["set_tag"]] in vars!") + return 1 + var/current_tag = src.vars[href_list["set_tag"]] + var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID tag", src, current_tag) as null|text),1,MAX_MESSAGE_LEN) + if(newid) + vars[href_list["set_tag"]] = newid + re_init=1 + update_mt_menu = 1 + + if("unlink" in href_list) + var/idx = text2num(href_list["unlink"]) + if (!idx) + return 1 + + var/obj/O = getLink(idx) + if(!O) + return 1 + + if(unlinkFrom(usr, O)) + to_chat(usr, "A green light flashes on \the [P], confirming the link was removed.") + else + to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when unlinking the two devices.") + update_mt_menu=1 + + if("link" in href_list) + var/obj/O = P.buffer + if(!O) + return 1 + if(!canLink(O,href_list)) + to_chat(usr, "You can't link with that device.") + return 1 + if (isLinkedWith(O)) + to_chat(usr, "A red light flashes on \the [P]. The two devices are already linked.") + return 1 + + if(linkWith(usr, O, href_list)) + to_chat(usr, "A green light flashes on \the [P], confirming the link has been created.") + else + to_chat(usr, "A red light flashes on \the [P]. It appears something went wrong when linking the two devices.") + update_mt_menu=1 + + if("buffer" in href_list) + if(istype(src, /obj/machinery/telecomms)) + if(!hasvar(src, "id")) + to_chat(usr, "A red light flashes and nothing changes.") + return + else if(!hasvar(src, "id_tag")) + to_chat(usr, "A red light flashes and nothing changes.") + return + P.buffer = src + to_chat(usr, "A green light flashes, and the device appears in the multitool buffer.") + update_mt_menu=1 + + if("flush" in href_list) + to_chat(usr, "A green light flashes, and the device disappears from the multitool buffer.") + P.buffer = null + update_mt_menu=1 + + var/ret = multitool_topic(usr,href_list,P.buffer) + if(ret == MT_ERROR) + return 1 + if(ret & MT_UPDATE) + update_mt_menu=1 + if(ret & MT_REINIT) + re_init=1 + + if(re_init) + initialize() + if(update_mt_menu) + //usr.set_machine(src) + update_multitool_menu(usr) + return 1 + +/obj/machinery/Topic(href, href_list) + ..() + if(stat & (NOPOWER|BROKEN)) + return 1 + if(href_list["close"]) + return + var/ghost_flags=0 + if(ghost_write) + ghost_flags |= PERMIT_ALL + if(!canGhostWrite(usr,src,"",ghost_flags)) + if(usr.restrained() || usr.lying || usr.stat) + return 1 + if (!usr.dexterity_check()) + to_chat(usr, "You don't have the dexterity to do this!") + return 1 + var/turf/T = get_turf(usr) + if(!isAI(usr) && T.z != z) + if(usr.z != 2) + to_chat(usr, "WARNING: Unable to interface with \the [src.name].") + return 1 + if ((!in_range(src, usr) || !istype(src.loc, /turf)) && !istype(usr, /mob/living/silicon)) + return 1 + else if(!custom_aghost_alerts) + log_adminghost("[key_name(usr)] screwed with [src] ([href])!") + + src.add_fingerprint(usr) + src.add_hiddenprint(usr) + + handle_multitool_topic(href,href_list,usr) + return 0 + +/obj/machinery/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + if(isrobot(user)) + // For some reason attack_robot doesn't work + // This is to stop robots from using cameras to remotely control machines. + if(user.client && user.client.eye == user) + return src.attack_hand(user) + else + return src.attack_hand(user) + +/obj/machinery/attack_ghost(mob/user as mob) + src.add_hiddenprint(user) + var/ghost_flags=0 + if(ghost_read) + ghost_flags |= PERMIT_ALL + if(canGhostRead(usr,src,ghost_flags)) + return src.attack_ai(user) + +/obj/machinery/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/attack_hand(mob/user as mob, var/ignore_brain_damage = 0) + if(stat & (NOPOWER|BROKEN|MAINT)) + return 1 + + if(user.lying || (user.stat && !canGhostRead(user))) // Ghost read-only + return 1 + + if(istype(user,/mob/dead/observer)) + return 0 + + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return 1 +/* + //distance checks are made by atom/proc/DblClick + if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon)) + return 1 +*/ + if (ishuman(user) && !ignore_brain_damage) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + visible_message("[H] stares cluelessly at [src] and drools.") + return 1 + else if(prob(H.getBrainLoss())) + to_chat(user, "You momentarily forget how to use [src].") + return 1 + + src.add_fingerprint(user) + return 0 + +/obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames. + return + +/obj/machinery/proc/assign_uid() + uid = gl_uid + gl_uid++ + +/obj/machinery/proc/dropFrame() + var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc) + M.set_build_state(2) + M.state = 1 + +/obj/machinery/proc/spillContents(var/destroy_chance = 0) + for(var/obj/I in component_parts) + if(prob(destroy_chance)) + qdel(I) + else + if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker) && src:reagents && src:reagents.total_volume) + reagents.trans_to(I, reagents.total_volume) + if(I.reliability != 100 && crit_fail) + I.crit_fail = 1 + I.forceMove(src.loc) + for(var/atom/movable/I in src) //remove any stuff loaded, like for fridges + if(!prob(destroy_chance) && machine_flags &EJECTNOTDEL) + I.forceMove(src.loc) + else + qdel(I) + +/obj/machinery/proc/crowbarDestroy(mob/user) + user.visible_message( "[user] begins to pry out the circuitboard from \the [src].", + "You begin to pry out the circuitboard from \the [src]...") + if(do_after(user, src, 40)) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + dropFrame() + spillContents() + user.visible_message( "[user] successfully pries out the circuitboard from \the [src]!", + "\icon[src] You successfully pry out the circuitboard from \the [src]!") + return 1 + return -1 + +//just something silly to delete the machine while still leaving something behind +/obj/machinery/proc/smashDestroy(var/destroy_chance = 50) + getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 2) + spillContents(destroy_chance) + qdel(src) + +/obj/machinery/proc/togglePanelOpen(var/obj/toggleitem, var/mob/user) + panel_open = !panel_open + if(!icon_state_open) + icon_state_open = icon_state + if(panel_open) + icon_state = icon_state_open + else + icon_state = initial(icon_state) + to_chat(user, "\icon[src] You [panel_open ? "open" : "close"] the maintenance hatch of \the [src].") + if(istype(toggleitem, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + update_icon() + return 1 + +/obj/machinery/proc/wrenchAnchor(var/mob/user) + if(state == 2 && src.machine_flags & WELD_FIXED) + to_chat(user, "\The [src] has to be unwelded from the floor first.") + return -1 //state set to 2, can't do it + for(var/obj/machinery/other in loc) + if(other.anchored == 1 && other.density == 1 && density && !anchored) + to_chat(user, "\The [other] is already anchored in this location.") + return -1 //other machines are already taking up all the space in this location + + if(!anchored) + if(!istype(src.loc, /turf/simulated/floor)) //Prevent from anchoring shit to shuttles / space + if( !(istype(src.loc, /turf/simulated/shuttle) && (machine_flags & SHUTTLEWRENCH)) ) //If NOT (on top of a shuttle AND can be secured to shuttles) + to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!") + return + + user.visible_message( "[user] begins to [anchored ? "undo" : "wrench"] \the [src]'s securing bolts.", + "You begin to [anchored ? "undo" : "wrench"] \the [src]'s securing bolts...") + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 30)) + anchored = !anchored + if(machine_flags & FIXED2WORK) + power_change() //updates us to turn on or off as necessary + state = anchored //since these values will match as long as state isn't 2, we can do this safely + user.visible_message( "[user] [anchored ? "wrench" : "unwrench"]es \the [src] [anchored ? "in place" : "from its fixture"]", + "\icon[src] You [anchored ? "wrench" : "unwrench"] \the [src] [anchored ? "in place" : "from its fixture"].", + "You hear a ratchet.") + return 1 + return -1 + +/obj/machinery/proc/weldToFloor(var/obj/item/weapon/weldingtool/WT, mob/user) + if(!anchored) + state = 0 //since this might be wrong, we go sanity + to_chat(user, "You need to secure \the [src] before it can be welded.") + return -1 + if (WT.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + user.visible_message("[user.name] starts to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \ + "You start to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \ + "You hear welding.") + if (do_after(user, src,20)) + if(!src || !WT.isOn()) + return -1 + switch(state) + if(0) + to_chat(user, "You have to keep \the [src] secure before it can be welded down.") + return -1 + if(1) + state = 2 + if(2) + state = 1 + user.visible_message( "[user.name] [state - 1 ? "weld" : "unweld"]s \the [src] [state - 1 ? "to" : "from"] the floor.", + "\icon [src] You [state - 1 ? "weld" : "unweld"] \the [src] [state - 1 ? "to" : "from"] the floor." + ) + return 1 + else + to_chat(user, "You need more welding fuel to complete this task.") + return -1 + +/** + * Handle emags. + * @param user /mob The mob that used the emag. + */ +/obj/machinery/proc/emag(mob/user as mob) + // Disable emaggability. Note that some machines such as the Communications Computer might be emaggable multiple times. + machine_flags &= ~EMAGGABLE + new/obj/effect/effect/sparks(get_turf(src)) + playsound(loc,"sparks",50,1) + + +/** + * Returns the cost of emagging this machine (emag_cost by default) + * @param user /mob The mob that used the emag. + * @param emag /obj/item/weapon/card/emag The emag used on this device. + * @return number Cost to emag. + */ +/obj/machinery/proc/getEmagCost(var/mob/user, var/obj/item/weapon/card/emag/emag) + return emag_cost + +/obj/machinery/attackby(var/obj/O, var/mob/user) + if(istype(O, /obj/item/weapon/card/emag) && machine_flags & EMAGGABLE) + var/obj/item/weapon/card/emag/E = O + if(E.canUse(user,src)) + emag(user) + return + + if(istype(O, /obj/item/weapon/wrench) && machine_flags & WRENCHMOVE) //make sure this is BEFORE the fixed2work check + if(!panel_open) + return wrenchAnchor(user) + else + to_chat(user, "\The [src]'s maintenance panel must be closed first!") + return -1 //we return -1 rather than 0 for the if(..()) checks + + if(istype(O, /obj/item/weapon/screwdriver) && machine_flags & SCREWTOGGLE) + return togglePanelOpen(O, user) + + if(istype(O, /obj/item/weapon/weldingtool) && machine_flags & WELD_FIXED) + return weldToFloor(O, user) + + if(istype(O, /obj/item/weapon/crowbar) && machine_flags & CROWDESTROY) + if(panel_open) + if(crowbarDestroy(user) == 1) + qdel(src) + return 1 + else + return -1 + + if(ismultitool(O) && machine_flags & MULTITOOL_MENU) + update_multitool_menu(user) + return 1 + + if(!anchored && machine_flags & FIXED2WORK) + return to_chat(user, "\The [src] must be anchored first!") + + if(istype(O, /obj/item/device/paicard) && machine_flags & WIREJACK) + for(var/mob/M in O) + wirejack(M) + return 1 + + if(istype(O, /obj/item/weapon/storage/bag/gadgets/part_replacer)) + return exchange_parts(user, O) + +/obj/machinery/proc/wirejack(var/mob/living/silicon/pai/P) + if(!(machine_flags & WIREJACK)) + return 0 + if(!P.hackloop(src)) + return 0 + return 1 + +/obj/machinery/proc/shock(mob/user, prb, var/siemenspassed = -1) + if(stat & (BROKEN|NOPOWER)) // unpowered, no shock + 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(siemenspassed == -1) //this means it hasn't been set by proc arguments, so we can set it ourselves safely + siemenspassed = 0.7 + if (electrocute_mob(user, get_area(src), src, siemenspassed)) + return 1 + else + return 0 + +// Hook for html_interface module to prevent updates to clients who don't have this as their active machine. +/obj/machinery/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi) + if (hclient.client.mob && (hclient.client.mob.stat == 0 || isobserver(hclient.client.mob))) + if(isAI(hclient.client.mob)) + return 1 + if(hclient.client.mob.machine == src) + return hclient.client.mob.html_mob_check(src.type) + return FALSE + +// Hook for html_interface module to unset the active machine when the window is closed by the player. +/obj/machinery/proc/hiOnHide(datum/html_interface_client/hclient) + if (hclient.client.mob && hclient.client.mob.machine == src) hclient.client.mob.unset_machine() + +/obj/machinery/proc/alert_noise(var/notice_state = "ping") + switch(notice_state) + if("ping") + src.visible_message("\icon[src] \The [src] pings.") + playsound(get_turf(src), 'sound/machines/notify.ogg', 50, 0) + if("beep") + src.visible_message("\icon[src] \The [src] beeps.") + playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) + if("buzz") + src.visible_message("\icon[src] \The [src] buzzes.") + playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + +/obj/machinery/proc/check_rebuild() + return + +/obj/machinery/proc/exchange_parts(mob/user, obj/item/weapon/storage/bag/gadgets/part_replacer/W) + var/shouldplaysound = 0 + if(component_parts) + if(panel_open) + var/obj/item/weapon/circuitboard/CB = locate(/obj/item/weapon/circuitboard) in component_parts + var/P + for(var/obj/item/A in component_parts) + for(var/D in CB.req_components) + D = text2path(D) //For some stupid reason these are strings by default. + if(ispath(A.type, D)) + P = D + break + for(var/obj/item/B in W.contents) + if(istype(B, P) && istype(A, P)) + if(B.get_rating() > A.get_rating()) + W.remove_from_storage(B, src) + W.handle_item_insertion(A, 1) + component_parts -= A + component_parts += B + B.loc = null + to_chat(user, "[A.name] replaced with [B.name].") + shouldplaysound = 1 //Only play the sound when parts are actually replaced! + break + RefreshParts() + else + to_chat(user, "Following parts detected in the machine:") + for(var/var/obj/item/C in component_parts) + to_chat(user, " [C.name]") + if(shouldplaysound) + W.play_rped_sound() + return 1 + return 0 diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index e44f93add22..7a343a6f646 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -1,405 +1,405 @@ -// Magnetic attractor, creates variable magnetic fields and attraction. -// Can also be used to emit electron/proton beams to create a center of magnetism on another tile - -// tl;dr: it's magnets lol -// This was created for firing ranges, but I suppose this could have other applications - Doohl - -/obj/machinery/magnetic_module - - icon = 'icons/obj/objects.dmi' - icon_state = "floor_magnet-f" - name = "Electromagnetic Generator" - desc = "A device that uses station power to create points of magnetic energy." - level = 1 // underfloor - layer = 2.5 - anchored = 1 - use_power = 1 - idle_power_usage = 50 - - var/freq = 1449 // radio frequency - var/electricity_level = 1 // intensity of the magnetic pull - var/magnetic_field = 1 // the range of magnetic attraction - var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something - var/turf/center // the center of magnetic attraction - var/on = 0 - var/pulling = 0 - - // x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down - var/center_x = 0 - var/center_y = 0 - var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer - - New() - ..() - var/turf/T = loc - hide(T.intact) - center = T - - spawn(10) // must wait for map loading to finish - if(radio_controller) - radio_controller.add_object(src, freq, RADIO_MAGNETS) - - spawn() - magnetic_process() - - // update the invisibility and icon - hide(var/intact) - invisibility = intact ? 101 : 0 - updateicon() - - // update the icon_state - proc/updateicon() - var/state="floor_magnet" - var/onstate="" - if(!on) - onstate="0" - - if(invisibility) - icon_state = "[state][onstate]-f" // if invisible, set icon to faded version - // in case of being revealed by T-scanner - else - icon_state = "[state][onstate]" - - receive_signal(datum/signal/signal) - - var/command = signal.data["command"] - var/modifier = signal.data["modifier"] - var/signal_code = signal.data["code"] - if(command && (signal_code == code)) - - Cmd(command, modifier) - - - - proc/Cmd(var/command, var/modifier) - - - if(command) - switch(command) - if("set-electriclevel") - if(modifier) electricity_level = modifier - if("set-magneticfield") - if(modifier) magnetic_field = modifier - - if("add-elec") - electricity_level++ - if(electricity_level > 12) - electricity_level = 12 - if("sub-elec") - electricity_level-- - if(electricity_level <= 0) - electricity_level = 1 - if("add-mag") - magnetic_field++ - if(magnetic_field > 4) - magnetic_field = 4 - if("sub-mag") - magnetic_field-- - if(magnetic_field <= 0) - magnetic_field = 1 - - if("set-x") - if(modifier) center_x = modifier - if("set-y") - if(modifier) center_y = modifier - - if("N") // NORTH - center_y++ - if("S") // SOUTH - center_y-- - if("E") // EAST - center_x++ - if("W") // WEST - center_x-- - if("C") // CENTER - center_x = 0 - center_y = 0 - if("R") // RANDOM - center_x = rand(-max_dist, max_dist) - center_y = rand(-max_dist, max_dist) - - if("set-code") - if(modifier) code = modifier - if("toggle-power") - on = !on - - if(on) - spawn() - magnetic_process() - - - - process() - if(stat & NOPOWER) - on = 0 - - // Sanity checks: - if(electricity_level <= 0) - electricity_level = 1 - if(magnetic_field <= 0) - magnetic_field = 1 - - - // Limitations: - if(abs(center_x) > max_dist) - center_x = max_dist - if(abs(center_y) > max_dist) - center_y = max_dist - if(magnetic_field > 4) - magnetic_field = 4 - if(electricity_level > 12) - electricity_level = 12 - - // Update power usage: - if(on) - use_power = 2 - active_power_usage = electricity_level*15 - else - use_power = 0 - - - // Overload conditions: - /* // Eeeehhh kinda stupid - if(on) - if(electricity_level > 11) - if(prob(electricity_level)) - explosion(loc, 0, 1, 2, 3) // ooo dat shit EXPLODES son - spawn(2) - del(src) - */ - - updateicon() - - - proc/magnetic_process() // proc that actually does the pulling - if(pulling) return - while(on) - - pulling = 1 - center = locate(x+center_x, y+center_y, z) - if(center) - for(var/obj/M in orange(magnetic_field, center)) - if(!M.anchored && (M.is_conductor())) - step_towards(M, center) - - for(var/mob/living/silicon/S in orange(magnetic_field, center)) - if(istype(S, /mob/living/silicon/ai)) continue - step_towards(S, center) - - use_power(electricity_level * 5) - sleep(13 - electricity_level) - - pulling = 0 - - - - -/obj/machinery/magnetic_controller - name = "Magnetic Control Console" - icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING! - icon_state = "airlock_control_standby" - density = 1 - anchored = 1.0 - use_power = 1 - idle_power_usage = 45 - var/frequency = 1449 - var/code = 0 - var/list/magnets = list() - var/title = "Magnetic Control Console" - var/autolink = 0 // if set to 1, can't probe for other magnets! - - var/pathpos = 1 // position in the path - var/path = "NULL" // text path of the magnet - var/speed = 1 // lowest = 1, highest = 10 - var/list/rpath = list() // real path of the magnet, used in iterator - - var/moving = 0 // 1 if scheduled to loop - var/looping = 0 // 1 if looping - - var/datum/radio_frequency/radio_connection - - - New() - ..() - - if(autolink) - for(var/obj/machinery/magnetic_module/M in machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - - - spawn(45) // must wait for map loading to finish - if(radio_controller) - radio_connection = radio_controller.add_object(src, frequency, RADIO_MAGNETS) - - - if(path) // check for default path - filter_path() // renders rpath - - - process() - if(magnets.len == 0 && autolink) - for(var/obj/machinery/magnetic_module/M in machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - - - attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - - attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/dat = "Magnetic Control Console

      " - if(!autolink) - dat += {" - Frequency: [frequency]
      - Code: [code]
      - Probe Generators
      - "} - - if(magnets.len >= 1) - - dat += "Magnets confirmed:
      " - var/i = 0 - for(var/obj/machinery/magnetic_module/M in magnets) - i++ - dat += "     < \[[i]\] ([M.on ? "On":"Off"]) | Electricity level: - [M.electricity_level] +; Magnetic field: - [M.magnetic_field] +
      " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\magnet.dm:270: dat += "
      Speed: - [speed] +
      " - dat += {"
      Speed: - [speed] +
      - Path: {[path]}
      - Moving: [moving ? "Enabled":"Disabled"]"} - // END AUTOFIX - user << browse(dat, "window=magnet;size=400x500") - onclose(user, "magnet") - - Topic(href, href_list) - if(..()) - return 1 - usr.set_machine(src) - src.add_fingerprint(usr) - - if(href_list["radio-op"]) - - // Prepare signal beforehand, because this is a radio operation - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 // radio transmission - signal.source = src - signal.frequency = frequency - signal.data["code"] = code - - // Apply any necessary commands - switch(href_list["radio-op"]) - if("togglepower") - signal.data["command"] = "toggle-power" - - if("minuselec") - signal.data["command"] = "sub-elec" - if("pluselec") - signal.data["command"] = "add-elec" - - if("minusmag") - signal.data["command"] = "sub-mag" - if("plusmag") - signal.data["command"] = "add-mag" - - - // Broadcast the signal - - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) - - spawn(1) - updateUsrDialog() // pretty sure this increases responsiveness - - if(href_list["operation"]) - switch(href_list["operation"]) - if("plusspeed") - speed ++ - if(speed > 10) - speed = 10 - if("minusspeed") - speed -- - if(speed <= 0) - speed = 1 - if("setpath") - var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) - if(newpath && newpath != "") - moving = 0 // stop moving - path = newpath - pathpos = 1 // reset position - filter_path() // renders rpath - - if("togglemoving") - moving = !moving - if(moving) - spawn() MagnetMove() - - - updateUsrDialog() - - proc/MagnetMove() - if(looping) return - - while(moving && rpath.len >= 1) - - if(stat & (BROKEN|NOPOWER)) - break - - looping = 1 - - // Prepare the radio signal - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 1 // radio transmission - signal.source = src - signal.frequency = frequency - signal.data["code"] = code - - if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list! - pathpos = 1 - - var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive - - if(!(nextmove in list("N","S","E","W","C","R"))) - // N, S, E, W are directional - // C is center - // R is random (in magnetic field's bounds) - qdel(signal) - signal = null - break // break the loop if the character located is invalid - - signal.data["command"] = nextmove - - - pathpos++ // increase iterator - - // Broadcast the signal - spawn() - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) - - if(speed == 10) - sleep(1) - else - sleep(12-speed) - - looping = 0 - - - proc/filter_path() - // Generates the rpath variable using the path string, think of this as "string2list" - // Doesn't use params2list() because of the akward way it stacks entities - rpath = list() // clear rpath - var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length - - for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path - - var/nextchar = copytext(path, i, i+1) // find next character - - if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore - rpath += copytext(path, i, i+1) // else, add to list - - // there doesn't HAVE to be separators but it makes paths syntatically visible +// Magnetic attractor, creates variable magnetic fields and attraction. +// Can also be used to emit electron/proton beams to create a center of magnetism on another tile + +// tl;dr: it's magnets lol +// This was created for firing ranges, but I suppose this could have other applications - Doohl + +/obj/machinery/magnetic_module + + icon = 'icons/obj/objects.dmi' + icon_state = "floor_magnet-f" + name = "Electromagnetic Generator" + desc = "A device that uses station power to create points of magnetic energy." + level = 1 // underfloor + layer = 2.5 + anchored = 1 + use_power = 1 + idle_power_usage = 50 + + var/freq = 1449 // radio frequency + var/electricity_level = 1 // intensity of the magnetic pull + var/magnetic_field = 1 // the range of magnetic attraction + var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something + var/turf/center // the center of magnetic attraction + var/on = 0 + var/pulling = 0 + + // x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down + var/center_x = 0 + var/center_y = 0 + var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer + + New() + ..() + var/turf/T = loc + hide(T.intact) + center = T + + spawn(10) // must wait for map loading to finish + if(radio_controller) + radio_controller.add_object(src, freq, RADIO_MAGNETS) + + spawn() + magnetic_process() + + // update the invisibility and icon + hide(var/intact) + invisibility = intact ? 101 : 0 + updateicon() + + // update the icon_state + proc/updateicon() + var/state="floor_magnet" + var/onstate="" + if(!on) + onstate="0" + + if(invisibility) + icon_state = "[state][onstate]-f" // if invisible, set icon to faded version + // in case of being revealed by T-scanner + else + icon_state = "[state][onstate]" + + receive_signal(datum/signal/signal) + + var/command = signal.data["command"] + var/modifier = signal.data["modifier"] + var/signal_code = signal.data["code"] + if(command && (signal_code == code)) + + Cmd(command, modifier) + + + + proc/Cmd(var/command, var/modifier) + + + if(command) + switch(command) + if("set-electriclevel") + if(modifier) electricity_level = modifier + if("set-magneticfield") + if(modifier) magnetic_field = modifier + + if("add-elec") + electricity_level++ + if(electricity_level > 12) + electricity_level = 12 + if("sub-elec") + electricity_level-- + if(electricity_level <= 0) + electricity_level = 1 + if("add-mag") + magnetic_field++ + if(magnetic_field > 4) + magnetic_field = 4 + if("sub-mag") + magnetic_field-- + if(magnetic_field <= 0) + magnetic_field = 1 + + if("set-x") + if(modifier) center_x = modifier + if("set-y") + if(modifier) center_y = modifier + + if("N") // NORTH + center_y++ + if("S") // SOUTH + center_y-- + if("E") // EAST + center_x++ + if("W") // WEST + center_x-- + if("C") // CENTER + center_x = 0 + center_y = 0 + if("R") // RANDOM + center_x = rand(-max_dist, max_dist) + center_y = rand(-max_dist, max_dist) + + if("set-code") + if(modifier) code = modifier + if("toggle-power") + on = !on + + if(on) + spawn() + magnetic_process() + + + + process() + if(stat & NOPOWER) + on = 0 + + // Sanity checks: + if(electricity_level <= 0) + electricity_level = 1 + if(magnetic_field <= 0) + magnetic_field = 1 + + + // Limitations: + if(abs(center_x) > max_dist) + center_x = max_dist + if(abs(center_y) > max_dist) + center_y = max_dist + if(magnetic_field > 4) + magnetic_field = 4 + if(electricity_level > 12) + electricity_level = 12 + + // Update power usage: + if(on) + use_power = 2 + active_power_usage = electricity_level*15 + else + use_power = 0 + + + // Overload conditions: + /* // Eeeehhh kinda stupid + if(on) + if(electricity_level > 11) + if(prob(electricity_level)) + explosion(loc, 0, 1, 2, 3) // ooo dat shit EXPLODES son + spawn(2) + del(src) + */ + + updateicon() + + + proc/magnetic_process() // proc that actually does the pulling + if(pulling) return + while(on) + + pulling = 1 + center = locate(x+center_x, y+center_y, z) + if(center) + for(var/obj/M in orange(magnetic_field, center)) + if(!M.anchored && (M.is_conductor())) + step_towards(M, center) + + for(var/mob/living/silicon/S in orange(magnetic_field, center)) + if(istype(S, /mob/living/silicon/ai)) continue + step_towards(S, center) + + use_power(electricity_level * 5) + sleep(13 - electricity_level) + + pulling = 0 + + + + +/obj/machinery/magnetic_controller + name = "Magnetic Control Console" + icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING! + icon_state = "airlock_control_standby" + density = 1 + anchored = 1.0 + use_power = 1 + idle_power_usage = 45 + var/frequency = 1449 + var/code = 0 + var/list/magnets = list() + var/title = "Magnetic Control Console" + var/autolink = 0 // if set to 1, can't probe for other magnets! + + var/pathpos = 1 // position in the path + var/path = "NULL" // text path of the magnet + var/speed = 1 // lowest = 1, highest = 10 + var/list/rpath = list() // real path of the magnet, used in iterator + + var/moving = 0 // 1 if scheduled to loop + var/looping = 0 // 1 if looping + + var/datum/radio_frequency/radio_connection + + + New() + ..() + + if(autolink) + for(var/obj/machinery/magnetic_module/M in machines) + if(M.freq == frequency && M.code == code) + magnets.Add(M) + + + spawn(45) // must wait for map loading to finish + if(radio_controller) + radio_connection = radio_controller.add_object(src, frequency, RADIO_MAGNETS) + + + if(path) // check for default path + filter_path() // renders rpath + + + process() + if(magnets.len == 0 && autolink) + for(var/obj/machinery/magnetic_module/M in machines) + if(M.freq == frequency && M.code == code) + magnets.Add(M) + + + attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + + attack_hand(mob/user as mob) + if(stat & (BROKEN|NOPOWER)) + return + user.set_machine(src) + var/dat = "Magnetic Control Console

      " + if(!autolink) + dat += {" + Frequency: [frequency]
      + Code: [code]
      + Probe Generators
      + "} + + if(magnets.len >= 1) + + dat += "Magnets confirmed:
      " + var/i = 0 + for(var/obj/machinery/magnetic_module/M in magnets) + i++ + dat += "     < \[[i]\] ([M.on ? "On":"Off"]) | Electricity level: - [M.electricity_level] +; Magnetic field: - [M.magnetic_field] +
      " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\\magnet.dm:270: dat += "
      Speed: - [speed] +
      " + dat += {"
      Speed: - [speed] +
      + Path: {[path]}
      + Moving: [moving ? "Enabled":"Disabled"]"} + // END AUTOFIX + user << browse(dat, "window=magnet;size=400x500") + onclose(user, "magnet") + + Topic(href, href_list) + if(..()) + return 1 + usr.set_machine(src) + src.add_fingerprint(usr) + + if(href_list["radio-op"]) + + // Prepare signal beforehand, because this is a radio operation + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 // radio transmission + signal.source = src + signal.frequency = frequency + signal.data["code"] = code + + // Apply any necessary commands + switch(href_list["radio-op"]) + if("togglepower") + signal.data["command"] = "toggle-power" + + if("minuselec") + signal.data["command"] = "sub-elec" + if("pluselec") + signal.data["command"] = "add-elec" + + if("minusmag") + signal.data["command"] = "sub-mag" + if("plusmag") + signal.data["command"] = "add-mag" + + + // Broadcast the signal + + radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) + + spawn(1) + updateUsrDialog() // pretty sure this increases responsiveness + + if(href_list["operation"]) + switch(href_list["operation"]) + if("plusspeed") + speed ++ + if(speed > 10) + speed = 10 + if("minusspeed") + speed -- + if(speed <= 0) + speed = 1 + if("setpath") + var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) + if(newpath && newpath != "") + moving = 0 // stop moving + path = newpath + pathpos = 1 // reset position + filter_path() // renders rpath + + if("togglemoving") + moving = !moving + if(moving) + spawn() MagnetMove() + + + updateUsrDialog() + + proc/MagnetMove() + if(looping) return + + while(moving && rpath.len >= 1) + + if(stat & (BROKEN|NOPOWER)) + break + + looping = 1 + + // Prepare the radio signal + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 1 // radio transmission + signal.source = src + signal.frequency = frequency + signal.data["code"] = code + + if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list! + pathpos = 1 + + var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive + + if(!(nextmove in list("N","S","E","W","C","R"))) + // N, S, E, W are directional + // C is center + // R is random (in magnetic field's bounds) + qdel(signal) + signal = null + break // break the loop if the character located is invalid + + signal.data["command"] = nextmove + + + pathpos++ // increase iterator + + // Broadcast the signal + spawn() + radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) + + if(speed == 10) + sleep(1) + else + sleep(12-speed) + + looping = 0 + + + proc/filter_path() + // Generates the rpath variable using the path string, think of this as "string2list" + // Doesn't use params2list() because of the akward way it stacks entities + rpath = list() // clear rpath + var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length + + for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path + + var/nextchar = copytext(path, i, i+1) // find next character + + if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore + rpath += copytext(path, i, i+1) // else, add to list + + // there doesn't HAVE to be separators but it makes paths syntatically visible diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index c0a5260d750..c077cf95290 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -1,227 +1,227 @@ -var/list/mass_drivers = list() -/obj/machinery/mass_driver - name = "mass driver" - desc = "Shoots things into space." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mass_driver" - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 50 - machine_flags = EMAGGABLE | MULTITOOL_MENU - - var/power = 1.0 - var/code = 1.0 - var/id_tag = "default" - var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. - -/obj/machinery/mass_driver/New() - ..() - mass_drivers += src - -/obj/machinery/mass_driver/Destroy() - mass_drivers -= src - ..() - -/obj/machinery/mass_driver/attackby(obj/item/weapon/W, mob/user as mob) - - . = ..() - if(.) - return . - - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(user, "You begin to unscrew the bolts off the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 30)) - var/obj/machinery/mass_driver_frame/F = new(get_turf(src)) - F.dir = src.dir - F.anchored = 1 - F.build = 4 - F.update_icon() - qdel(src) - return 1 - - return ..() - -/obj/machinery/mass_driver/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) - return {" -
        -
      • [format_tag("ID Tag","id_tag")]
      • -
      "} - -/obj/machinery/mass_driver/proc/drive(amount) - if(stat & (BROKEN|NOPOWER)) - return - use_power(500*power) - var/O_limit = 0 - var/atom/target = get_edge_target_turf(src, dir) - for(var/atom/movable/O in loc) - if(!O.anchored||istype(O, /obj/mecha))//Mechs need their launch platforms. - O_limit++ - if(O_limit >= 20)//so no more than 20 items are sent at a time, probably for counter-lag purposes - break - use_power(500) - spawn() - var/coef = 1 - if(emagged) - coef = 5 - O.throw_at(target, drive_range * power * coef, power * coef) - flick("mass_driver1", src) - return - -/obj/machinery/mass_driver/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - return - drive() - ..(severity) - -/obj/machinery/mass_driver/emag(mob/user) - if(!emagged) - emagged = 1 - to_chat(user, "You hack the Mass Driver, radically increasing the force at which it'll throw things. Better not stand in its way.") - return 1 - return -1 - -////////////////MASS BUMPER/////////////////// - -/obj/machinery/mass_driver/bumper - name = "mass bumper" - desc = "Now you're here, now you're over there." - density = 1 - -/obj/machinery/mass_driver/bumper/Bumped(M as mob|obj) - density = 0 - step(M, get_dir(M,src)) - spawn(1) - density = 1 - drive() - return - -////////////////MASS DRIVER FRAME/////////////////// - -/obj/machinery/mass_driver_frame - name = "mass driver frame" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mass_driver_b0" - density = 0 - anchored = 0 - var/build = 0 - -/obj/machinery/mass_driver_frame/attackby(var/obj/item/W as obj, var/mob/user as mob) - switch(build) - if(0) // Loose frame - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - to_chat(user, "You begin to cut the frame apart...") - if(do_after(user, src, 30) && (build == 0)) - to_chat(user, "You detach the plasteel sheets from each others.") - new /obj/item/stack/sheet/plasteel(get_turf(src),3) - qdel(src) - return 1 - if(istype(W, /obj/item/weapon/wrench)) - to_chat(user, "You begin to anchor \the [src] on the floor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 10) && (build == 0)) - to_chat(user, "You anchor \the [src]!") - anchored = 1 - build++ - update_icon() - return 1 - if(1) // Fixed to the floor - if(istype(W, /obj/item/weapon/wrench)) - to_chat(user, "You begin to de-anchor \the [src] from the floor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 10) && (build == 1)) - build-- - update_icon() - anchored = 0 - to_chat(user, "You de-anchored \the [src]!") - return 1 - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - to_chat(user, "You begin to weld \the [src] to the floor...") - if(do_after(user, src, 40) && (build == 1)) - to_chat(user, "You welded \the [src] to the floor.") - build++ - update_icon() - return 1 - if(2) // Welded to the floor - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0, user)) - to_chat(user, "The welding tool must be on to complete this task.") - return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - to_chat(user, "You begin to unweld \the [src] to the floor...") - if(do_after(user, src, 40) && (build == 2)) - to_chat(user, "You unwelded \the [src] to the floor.") - build-- - update_icon() - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C=W - to_chat(user, "You start adding cables to \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20) && (C.amount >= 3) && (build == 2)) - C.use(3) - to_chat(user, "You've added cables to \the [src].") - build++ - update_icon() - if(3) // Wired - if(istype(W, /obj/item/weapon/wirecutters)) - to_chat(user, "You begin to remove the wiring from \the [src].") - if(do_after(user, src, 10) && (build == 3)) - new /obj/item/stack/cable_coil(loc,3) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - to_chat(user, "You've removed the cables from \the [src].") - build-- - update_icon() - return 1 - if(istype(W, /obj/item/stack/rods)) - var/obj/item/stack/rods/R=W - to_chat(user, "You begin to complete \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20) && (R.amount >= 3) && (build == 3)) - R.use(3) - to_chat(user, "You've added the grille to \the [src].") - build++ - update_icon() - return 1 - if(4) // Grille in place - if(istype(W, /obj/item/weapon/crowbar)) - to_chat(user, "You begin to pry off the grille from \the [src]...") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - if(do_after(user, src, 30) && (build == 4)) - new /obj/item/stack/rods(loc,2) - build-- - update_icon() - return 1 - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(user, "You finalize the Mass Driver...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - var/obj/machinery/mass_driver/M = new(get_turf(src)) - M.dir = src.dir - qdel(src) - return 1 - ..() - -/obj/machinery/mass_driver_frame/update_icon() - icon_state = "mass_driver_b[build]" - -/obj/machinery/mass_driver_frame/verb/rotate() - set category = "Object" - set name = "Rotate Frame" - set src in view(1) - - if (usr.isUnconscious() || usr.restrained()) - return - - src.dir = turn(src.dir, -90) - return +var/list/mass_drivers = list() +/obj/machinery/mass_driver + name = "mass driver" + desc = "Shoots things into space." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mass_driver" + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 50 + machine_flags = EMAGGABLE | MULTITOOL_MENU + + var/power = 1.0 + var/code = 1.0 + var/id_tag = "default" + var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. + +/obj/machinery/mass_driver/New() + ..() + mass_drivers += src + +/obj/machinery/mass_driver/Destroy() + mass_drivers -= src + ..() + +/obj/machinery/mass_driver/attackby(obj/item/weapon/W, mob/user as mob) + + . = ..() + if(.) + return . + + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(user, "You begin to unscrew the bolts off the [src]...") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 30)) + var/obj/machinery/mass_driver_frame/F = new(get_turf(src)) + F.dir = src.dir + F.anchored = 1 + F.build = 4 + F.update_icon() + qdel(src) + return 1 + + return ..() + +/obj/machinery/mass_driver/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) + return {" +
        +
      • [format_tag("ID Tag","id_tag")]
      • +
      "} + +/obj/machinery/mass_driver/proc/drive(amount) + if(stat & (BROKEN|NOPOWER)) + return + use_power(500*power) + var/O_limit = 0 + var/atom/target = get_edge_target_turf(src, dir) + for(var/atom/movable/O in loc) + if(!O.anchored||istype(O, /obj/mecha))//Mechs need their launch platforms. + O_limit++ + if(O_limit >= 20)//so no more than 20 items are sent at a time, probably for counter-lag purposes + break + use_power(500) + spawn() + var/coef = 1 + if(emagged) + coef = 5 + O.throw_at(target, drive_range * power * coef, power * coef) + flick("mass_driver1", src) + return + +/obj/machinery/mass_driver/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + return + drive() + ..(severity) + +/obj/machinery/mass_driver/emag(mob/user) + if(!emagged) + emagged = 1 + to_chat(user, "You hack the Mass Driver, radically increasing the force at which it'll throw things. Better not stand in its way.") + return 1 + return -1 + +////////////////MASS BUMPER/////////////////// + +/obj/machinery/mass_driver/bumper + name = "mass bumper" + desc = "Now you're here, now you're over there." + density = 1 + +/obj/machinery/mass_driver/bumper/Bumped(M as mob|obj) + density = 0 + step(M, get_dir(M,src)) + spawn(1) + density = 1 + drive() + return + +////////////////MASS DRIVER FRAME/////////////////// + +/obj/machinery/mass_driver_frame + name = "mass driver frame" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mass_driver_b0" + density = 0 + anchored = 0 + var/build = 0 + +/obj/machinery/mass_driver_frame/attackby(var/obj/item/W as obj, var/mob/user as mob) + switch(build) + if(0) // Loose frame + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.remove_fuel(0, user)) + to_chat(user, "The welding tool must be on to complete this task.") + return 1 + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + to_chat(user, "You begin to cut the frame apart...") + if(do_after(user, src, 30) && (build == 0)) + to_chat(user, "You detach the plasteel sheets from each others.") + new /obj/item/stack/sheet/plasteel(get_turf(src),3) + qdel(src) + return 1 + if(istype(W, /obj/item/weapon/wrench)) + to_chat(user, "You begin to anchor \the [src] on the floor.") + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 10) && (build == 0)) + to_chat(user, "You anchor \the [src]!") + anchored = 1 + build++ + update_icon() + return 1 + if(1) // Fixed to the floor + if(istype(W, /obj/item/weapon/wrench)) + to_chat(user, "You begin to de-anchor \the [src] from the floor.") + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 10) && (build == 1)) + build-- + update_icon() + anchored = 0 + to_chat(user, "You de-anchored \the [src]!") + return 1 + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.remove_fuel(0, user)) + to_chat(user, "The welding tool must be on to complete this task.") + return 1 + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + to_chat(user, "You begin to weld \the [src] to the floor...") + if(do_after(user, src, 40) && (build == 1)) + to_chat(user, "You welded \the [src] to the floor.") + build++ + update_icon() + return 1 + if(2) // Welded to the floor + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.remove_fuel(0, user)) + to_chat(user, "The welding tool must be on to complete this task.") + return 1 + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + to_chat(user, "You begin to unweld \the [src] to the floor...") + if(do_after(user, src, 40) && (build == 2)) + to_chat(user, "You unwelded \the [src] to the floor.") + build-- + update_icon() + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C=W + to_chat(user, "You start adding cables to \the [src]...") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20) && (C.amount >= 3) && (build == 2)) + C.use(3) + to_chat(user, "You've added cables to \the [src].") + build++ + update_icon() + if(3) // Wired + if(istype(W, /obj/item/weapon/wirecutters)) + to_chat(user, "You begin to remove the wiring from \the [src].") + if(do_after(user, src, 10) && (build == 3)) + new /obj/item/stack/cable_coil(loc,3) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + to_chat(user, "You've removed the cables from \the [src].") + build-- + update_icon() + return 1 + if(istype(W, /obj/item/stack/rods)) + var/obj/item/stack/rods/R=W + to_chat(user, "You begin to complete \the [src]...") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20) && (R.amount >= 3) && (build == 3)) + R.use(3) + to_chat(user, "You've added the grille to \the [src].") + build++ + update_icon() + return 1 + if(4) // Grille in place + if(istype(W, /obj/item/weapon/crowbar)) + to_chat(user, "You begin to pry off the grille from \the [src]...") + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + if(do_after(user, src, 30) && (build == 4)) + new /obj/item/stack/rods(loc,2) + build-- + update_icon() + return 1 + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(user, "You finalize the Mass Driver...") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + var/obj/machinery/mass_driver/M = new(get_turf(src)) + M.dir = src.dir + qdel(src) + return 1 + ..() + +/obj/machinery/mass_driver_frame/update_icon() + icon_state = "mass_driver_b[build]" + +/obj/machinery/mass_driver_frame/verb/rotate() + set category = "Object" + set name = "Rotate Frame" + set src in view(1) + + if (usr.isUnconscious() || usr.restrained()) + return + + src.dir = turn(src.dir, -90) + return diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index af4f7890070..a29517d686e 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -1,245 +1,245 @@ -// Navigation beacon for AI robots -// Functions as a transponder: looks for incoming signal matching - -/obj/machinery/navbeacon - - icon = 'icons/obj/objects.dmi' - icon_state = "navbeacon0-f" - name = "navigation beacon" - desc = "A radio beacon used for bot navigation." - level = 1 // underfloor - layer = 2.5 - anchored = 1 - - var/locked = 1 // true if controls are locked - var/freq = 1445 // radio frequency - var/location = "" // location response text - var/list/codes // assoc. list of transponder codes - var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value" - - req_access = list(access_engine) - - machine_flags = SCREWTOGGLE - - New() - ..() - - set_codes() - - var/turf/T = loc - hide(T.intact) - - spawn(5) // must wait for map loading to finish - if(radio_controller) - radio_controller.add_object(src, freq, RADIO_NAVBEACONS) - - // set the transponder codes assoc list from codes_txt - proc/set_codes() - if(!codes_txt) - return - - codes = new() - - var/list/entries = text2list(codes_txt, ";") // entries are separated by semicolons - - for(var/e in entries) - var/index = findtext(e, "=") // format is "key=value" - if(index) - var/key = copytext(e, 1, index) - var/val = copytext(e, index+1) - codes[key] = val - else - codes[e] = "1" - - - // called when turf state changes - // hide the object if turf is intact - hide(var/intact) - invisibility = intact ? 101 : 0 - updateicon() - - // update the icon_state - proc/updateicon() - var/state="navbeacon[panel_open]" - - if(invisibility) - icon_state = "[state]-f" // if invisible, set icon to faded version - // in case revealed by T-scanner - else - icon_state = "[state]" - - - // look for a signal of the form "findbeacon=X" - // where X is any - // or the location - // or one of the set transponder keys - // if found, return a signal - receive_signal(datum/signal/signal) - - var/request = signal.data["findbeacon"] - if(request && ((request in codes) || request == "any" || request == location)) - spawn(1) - post_signal() - - // return a signal giving location and transponder codes - - proc/post_signal() - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - signal.data["beacon"] = location - - for(var/key in codes) - signal.data[key] = codes[key] - - frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) - - - attackby(var/obj/item/I, var/mob/user) - var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - - if(..()) - return - - else if (istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda)) - if(panel_open) - if (src.allowed(user)) - src.locked = !src.locked +// Navigation beacon for AI robots +// Functions as a transponder: looks for incoming signal matching + +/obj/machinery/navbeacon + + icon = 'icons/obj/objects.dmi' + icon_state = "navbeacon0-f" + name = "navigation beacon" + desc = "A radio beacon used for bot navigation." + level = 1 // underfloor + layer = 2.5 + anchored = 1 + + var/locked = 1 // true if controls are locked + var/freq = 1445 // radio frequency + var/location = "" // location response text + var/list/codes // assoc. list of transponder codes + var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value" + + req_access = list(access_engine) + + machine_flags = SCREWTOGGLE + + New() + ..() + + set_codes() + + var/turf/T = loc + hide(T.intact) + + spawn(5) // must wait for map loading to finish + if(radio_controller) + radio_controller.add_object(src, freq, RADIO_NAVBEACONS) + + // set the transponder codes assoc list from codes_txt + proc/set_codes() + if(!codes_txt) + return + + codes = new() + + var/list/entries = text2list(codes_txt, ";") // entries are separated by semicolons + + for(var/e in entries) + var/index = findtext(e, "=") // format is "key=value" + if(index) + var/key = copytext(e, 1, index) + var/val = copytext(e, index+1) + codes[key] = val + else + codes[e] = "1" + + + // called when turf state changes + // hide the object if turf is intact + hide(var/intact) + invisibility = intact ? 101 : 0 + updateicon() + + // update the icon_state + proc/updateicon() + var/state="navbeacon[panel_open]" + + if(invisibility) + icon_state = "[state]-f" // if invisible, set icon to faded version + // in case revealed by T-scanner + else + icon_state = "[state]" + + + // look for a signal of the form "findbeacon=X" + // where X is any + // or the location + // or one of the set transponder keys + // if found, return a signal + receive_signal(datum/signal/signal) + + var/request = signal.data["findbeacon"] + if(request && ((request in codes) || request == "any" || request == location)) + spawn(1) + post_signal() + + // return a signal giving location and transponder codes + + proc/post_signal() + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + signal.data["beacon"] = location + + for(var/key in codes) + signal.data[key] = codes[key] + + frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS) + + + attackby(var/obj/item/I, var/mob/user) + var/turf/T = loc + if(T.intact) + return // prevent intraction when T-scanner revealed + + if(..()) + return + + else if (istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda)) + if(panel_open) + if (src.allowed(user)) + src.locked = !src.locked to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") - else + else to_chat(user, "Access denied.") - updateDialog() - else + updateDialog() + else to_chat(user, "You must open the cover first!") - return - - attack_ai(var/mob/user) - src.add_hiddenprint(user) - interact(user, 1) - - attack_paw() - return - - attack_hand(var/mob/user) - interact(user, 0) - - interact(var/mob/user, var/ai = 0) - var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - - if(!panel_open && !ai) // can't alter controls if not open, unless you're an AI + return + + attack_ai(var/mob/user) + src.add_hiddenprint(user) + interact(user, 1) + + attack_paw() + return + + attack_hand(var/mob/user) + interact(user, 0) + + interact(var/mob/user, var/ai = 0) + var/turf/T = loc + if(T.intact) + return // prevent intraction when T-scanner revealed + + if(!panel_open && !ai) // can't alter controls if not open, unless you're an AI to_chat(user, "The beacon's control cover is closed.") - return - - - var/t - - if(locked && !ai) - t = {"Navigation Beacon

      -(swipe card to unlock controls)
      -Frequency: [format_frequency(freq)]

      -Location: [location ? location : "(none)"]
      -Transponder Codes:
        "} - - for(var/key in codes) - t += "
      • [key] ... [codes[key]]" - t+= "
          " - - else - - t = {"Navigation Beacon

          -(swipe card to lock controls)
          -Frequency: -- -- -[format_frequency(freq)] -+ -+
          -
          -Location: [location ? location : "(none)"]
          -Transponder Codes:
            "} - - for(var/key in codes) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\navbeacon.dm:174: t += "
          • [key] ... [codes[key]]" - t += {"
          • [key] ... [codes[key]] - (edit) - (delete)
            "} - // END AUTOFIX - t += "
          • [key] ... [codes[key]]" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\navbeacon.dm:177: t += "(add new)
            " - t += {"(add new)
            -
              "} - // END AUTOFIX - user << browse(t, "window=navbeacon") - onclose(user, "navbeacon") - return - - Topic(href, href_list) - if(..()) return 1 - else - if(panel_open && !locked) - usr.set_machine(src) - - if (href_list["freq"]) - freq = sanitize_frequency(freq + text2num(href_list["freq"])) - updateDialog() - - else if(href_list["locedit"]) - var/newloc = copytext(sanitize(input("Enter New Location", "Navigation Beacon", location) as text|null),1,MAX_MESSAGE_LEN) - if(newloc) - location = newloc - updateDialog() - - else if(href_list["edit"]) - var/codekey = href_list["code"] - - var/newkey = input("Enter Transponder Code Key", "Navigation Beacon", codekey) as text|null - if(!newkey) - return - - var/codeval = codes[codekey] - var/newval = input("Enter Transponder Code Value", "Navigation Beacon", codeval) as text|null - if(!newval) - newval = codekey - return - - codes.Remove(codekey) - codes[newkey] = newval - - updateDialog() - - else if(href_list["delete"]) - var/codekey = href_list["code"] - codes.Remove(codekey) - updateDialog() - - else if(href_list["add"]) - - var/newkey = input("Enter New Transponder Code Key", "Navigation Beacon") as text|null - if(!newkey) - return - - var/newval = input("Enter New Transponder Code Value", "Navigation Beacon") as text|null - if(!newval) - newval = "1" - return - - if(!codes) - codes = new() - - codes[newkey] = newval - - updateDialog() + return + + + var/t + + if(locked && !ai) + t = {"Navigation Beacon

              +(swipe card to unlock controls)
              +Frequency: [format_frequency(freq)]

              +Location: [location ? location : "(none)"]
              +Transponder Codes:
                "} + + for(var/key in codes) + t += "
              • [key] ... [codes[key]]" + t+= "
                  " + + else + + t = {"Navigation Beacon

                  +(swipe card to lock controls)
                  +Frequency: +- +- +[format_frequency(freq)] ++ ++
                  +
                  +Location: [location ? location : "(none)"]
                  +Transponder Codes:
                    "} + + for(var/key in codes) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\navbeacon.dm:174: t += "
                  • [key] ... [codes[key]]" + t += {"
                  • [key] ... [codes[key]] + (edit) + (delete)
                    "} + // END AUTOFIX + t += "
                  • [key] ... [codes[key]]" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\navbeacon.dm:177: t += "(add new)
                    " + t += {"(add new)
                    +
                      "} + // END AUTOFIX + user << browse(t, "window=navbeacon") + onclose(user, "navbeacon") + return + + Topic(href, href_list) + if(..()) return 1 + else + if(panel_open && !locked) + usr.set_machine(src) + + if (href_list["freq"]) + freq = sanitize_frequency(freq + text2num(href_list["freq"])) + updateDialog() + + else if(href_list["locedit"]) + var/newloc = copytext(sanitize(input("Enter New Location", "Navigation Beacon", location) as text|null),1,MAX_MESSAGE_LEN) + if(newloc) + location = newloc + updateDialog() + + else if(href_list["edit"]) + var/codekey = href_list["code"] + + var/newkey = input("Enter Transponder Code Key", "Navigation Beacon", codekey) as text|null + if(!newkey) + return + + var/codeval = codes[codekey] + var/newval = input("Enter Transponder Code Value", "Navigation Beacon", codeval) as text|null + if(!newval) + newval = codekey + return + + codes.Remove(codekey) + codes[newkey] = newval + + updateDialog() + + else if(href_list["delete"]) + var/codekey = href_list["code"] + codes.Remove(codekey) + updateDialog() + + else if(href_list["add"]) + + var/newkey = input("Enter New Transponder Code Key", "Navigation Beacon") as text|null + if(!newkey) + return + + var/newval = input("Enter New Transponder Code Value", "Navigation Beacon") as text|null + if(!newval) + newval = "1" + return + + if(!codes) + codes = new() + + codes[newkey] = newval + + updateDialog() diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm index 080466c77d3..cd2938a12d9 100644 --- a/code/game/machinery/overview.dm +++ b/code/game/machinery/overview.dm @@ -1,363 +1,363 @@ -//#define AMAP - -/obj/machinery/computer/security/verb/station_map() - set name = ".map" - set category = "Object" - set src in view(1) - usr.set_machine(src) - if(!mapping) return - - log_game("[usr]([usr.key]) used station map L[z] in [src.loc.loc]") - - src.drawmap(usr) - -/obj/machinery/computer/security/proc/drawmap(var/mob/user as mob) - - - var/icx = round(world.maxx/16) + 1 - var/icy = round(world.maxy/16) + 1 - - var/xoff = round( (icx*16-world.maxx)-2) - var/yoff = round( (icy*16-world.maxy)-2) - - var/icount = icx * icy - - - var/list/imap = list() - -#ifdef AMAP - - for(var/i = 0; iAutomatic Portable Turret Installation

                      -Status: []
                      -Behaviour controls are [src.locked ? "locked" : "unlocked"]"}, - -"[src.on ? "On" : "Off"]" ) - - if(!src.locked) - dat += text({"
                      -Check for Weapon Authorization: []
                      -Check Security Records: []
                      -Neutralize Identified Criminals: []
                      -Neutralize All Non-Security and Non-Command Personnel: []
                      -Neutralize All Unidentified Life Signs: []
                      "}, - -"[src.auth_weapons ? "Yes" : "No"]", -"[src.check_records ? "Yes" : "No"]", -"[src.criminals ? "Yes" : "No"]", -"[stun_all ? "Yes" : "No"]", -"[check_anomalies ? "Yes" : "No"]" ) - else - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(((src.lasercolor) == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag))) - return - if(((src.lasercolor) == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - dat += text({" -Automatic Portable Turret Installation

                      -Status: []
                      "}, - -"[src.on ? "On" : "Off"]" ) - - - user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/porta_turret/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if ((href_list["power"]) && (src.allowed(usr))) - if(anchored) // you can't turn a turret on/off if it's not anchored/secured - on = !on // toggle on/off - else +/* + Portable Turrets: + + Constructed from metal, a gun of choice, and a prox sensor. + Gun can be a taser or laser or energy gun. + + This code is slightly more documented than normal, as requested by XSI on IRC. + +*/ + + +/obj/machinery/porta_turret + name = "turret" + icon = 'icons/obj/turrets.dmi' + icon_state = "grey_target_prism" + anchored = 1 + layer = 3 + invisibility = INVISIBILITY_LEVEL_TWO // the turret is invisible if it's inside its cover + density = 1 + use_power = 1 // this turret uses and requires power + idle_power_usage = 50 // when inactive, this turret takes up constant 50 Equipment power + active_power_usage = 300// when active, this turret takes up constant 300 Equipment power + req_access = list(access_security) + power_channel = EQUIP // drains power from the EQUIPMENT channel + + var/lasercolor = "" // Something to do with lasertag turrets, blame Sieve for not adding a comment. + var/raised = 0 // if the turret cover is "open" and the turret is raised + var/raising= 0 // if the turret is currently opening or closing its cover + var/health = 80 // the turret's health + var/locked = 1 // if the turret's behaviour control access is locked + + var/installation // the type of weapon installed + var/gun_charge = 0 // the charge of the gun inserted + var/projectile = null //holder for bullettype + var/eprojectile = null//holder for the shot when emagged + var/reqpower = 0 //holder for power needed + var/fire_sound = 'sound/weapons/Laser.ogg' + var/efire_sound = 'sound/weapons/Laser.ogg' + var/iconholder = null//holder for the icon_state + var/egun = null//holder to handle certain guns switching bullettypes + + var/obj/machinery/porta_turret_cover/cover = null // the cover that is covering this turret + var/last_fired = 0 // 1: if the turret is cooling down from a shot, 0: turret is ready to fire + var/shot_delay = 15 // 1.5 seconds between each shot + + var/check_records = 1 // checks if it can use the security records + var/criminals = 1 // checks if it can shoot people on arrest + var/auth_weapons = 0 // checks if it can shoot people that have a weapon they aren't authorized to have + var/stun_all = 0 // if this is active, the turret shoots everything that isn't security or head of staff + var/check_anomalies = 1 // checks if it can shoot at unidentified lifeforms (ie xenos) + var/ai = 0 // if active, will shoot at anything not an AI or cyborg + + var/attacked = 0 // if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) + + //var/emagged = 0 // 1: emagged, 0: not emagged + var/on = 1 // determines if the turret is on + var/disabled = 0 + + var/datum/effect/effect/system/spark_spread/spark_system // the spark system, used for generating... sparks? + + machine_flags = EMAGGABLE + +/obj/machinery/porta_turret/New() + ..() + icon_state = "[lasercolor]grey_target_prism" + // Sets up a spark system + spark_system = new /datum/effect/effect/system/spark_spread + spark_system.set_up(5, 0, src) + spark_system.attach(src) + spawn(10) + update_gun() + +/obj/machinery/porta_turret/proc/update_gun() + if(!installation)// if for some reason the turret has no gun (ie, admin spawned) it resorts to basic taser shots + projectile = /obj/item/projectile/energy/electrode//holder for the projectile, here it is being set + eprojectile = /obj/item/projectile/beam//holder for the projectile when emagged, if it is different + reqpower = 200 + iconholder = 1 + else + var/obj/item/weapon/gun/energy/E=new installation + // All energy-based weapons are applicable + switch(E.type) + if(/obj/item/weapon/gun/energy/laser/bluetag) + projectile = /obj/item/projectile/beam/lastertag/blue + eprojectile = /obj/item/projectile/beam/lastertag/omni//This bolt will stun ERRYONE with a vest + iconholder = null + reqpower = 100 + lasercolor = "b" + req_access = list(access_maint_tunnels) + check_records = 0 + criminals = 0 + auth_weapons = 1 + stun_all = 0 + check_anomalies = 0 + shot_delay = 30 + + if(/obj/item/weapon/gun/energy/laser/redtag) + projectile = /obj/item/projectile/beam/lastertag/red + eprojectile = /obj/item/projectile/beam/lastertag/omni + iconholder = null + reqpower = 100 + lasercolor = "r" + req_access = list(access_maint_tunnels) + check_records = 0 + criminals = 0 + auth_weapons = 1 + stun_all = 0 + check_anomalies = 0 + shot_delay = 30 + + if(/obj/item/weapon/gun/energy/laser/practice) + projectile = /obj/item/projectile/beam/practice + eprojectile = /obj/item/projectile/beam + iconholder = null + reqpower = 100 + + if(/obj/item/weapon/gun/energy/pulse_rifle) + projectile = /obj/item/projectile/beam/pulse + eprojectile = projectile + iconholder = null + reqpower = 700 + fire_sound = 'sound/weapons/pulse.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/staff) + projectile = /obj/item/projectile/change + eprojectile = projectile + iconholder = 1 + reqpower = 700 + fire_sound = 'sound/weapons/radgun.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/ionrifle) + projectile = /obj/item/projectile/ion + eprojectile = projectile + iconholder = 1 + reqpower = 700 + fire_sound = 'sound/weapons/ion.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/taser) + projectile = /obj/item/projectile/energy/electrode + eprojectile = projectile + iconholder = 1 + reqpower = 200 + fire_sound = 'sound/weapons/Taser.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/stunrevolver) + projectile = /obj/item/projectile/energy/electrode + eprojectile = projectile + iconholder = 1 + reqpower = 200 + fire_sound = 'sound/weapons/Gunshot.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/lasercannon) + projectile = /obj/item/projectile/beam/heavylaser + eprojectile = projectile + iconholder = null + reqpower = 600 + fire_sound = 'sound/weapons/lasercannonfire.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/decloner) + projectile = /obj/item/projectile/energy/declone + eprojectile = projectile + iconholder = null + reqpower = 600 + fire_sound = 'sound/weapons/pulse3.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/crossbow/largecrossbow) + projectile = /obj/item/projectile/energy/bolt/large + eprojectile = projectile + iconholder = null + reqpower = 125 + fire_sound = 'sound/weapons/ebow.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/crossbow) + projectile = /obj/item/projectile/energy/bolt + eprojectile = projectile + iconholder = null + reqpower = 50 + fire_sound = 'sound/weapons/ebow.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/laser) + projectile = /obj/item/projectile/beam + eprojectile = projectile + iconholder = null + reqpower = 500 + + if(/obj/item/weapon/gun/energy/ricochet) + projectile = /obj/item/projectile/ricochet + eprojectile = projectile + iconholder = null + reqpower = 500 + + if(/obj/item/weapon/gun/energy/bison) + projectile = /obj/item/projectile/beam/bison + eprojectile = projectile + iconholder = null + reqpower = 250 + fire_sound = 'sound/weapons/bison_fire.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/polarstar/spur) + projectile = /obj/item/projectile/spur + eprojectile = projectile + iconholder = null + reqpower = 700 + fire_sound = 'sound/weapons/spur_high.ogg' + efire_sound = fire_sound + + if(/obj/item/weapon/gun/energy/polarstar) + projectile = /obj/item/projectile/spur/polarstar + eprojectile = projectile + iconholder = null + reqpower = 400 + fire_sound = 'sound/weapons/spur_high.ogg' + efire_sound = fire_sound + + else // Energy gun shots + projectile = /obj/item/projectile/energy/electrode// if it hasn't been emagged, it uses normal taser shots + eprojectile = /obj/item/projectile/beam//If it has, going to kill mode + iconholder = 1 + egun = 1 + reqpower = 200 + fire_sound = 'sound/weapons/Taser.ogg' + if(!eprojectile || !projectile) + projectile = /obj/item/projectile/energy/electrode// if it hasn't been emagged, it uses normal taser shots + eprojectile = /obj/item/projectile/beam//If it has, going to kill mode + iconholder = 1 + egun = 1 + reqpower = 200 + fire_sound = 'sound/weapons/Taser.ogg' + +/obj/machinery/porta_turret/Destroy() + // deletes its own cover with it + qdel(cover) + ..() + + +/obj/machinery/porta_turret/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/porta_turret/attack_hand(mob/user as mob) + . = ..() + if (.) + return + var/dat + + // The browse() text, similar to ED-209s and beepskies. + if(!(src.lasercolor))//Lasertag turrets have less options + dat += text({" +Automatic Portable Turret Installation

                      +Status: []
                      +Behaviour controls are [src.locked ? "locked" : "unlocked"]"}, + +"[src.on ? "On" : "Off"]" ) + + if(!src.locked) + dat += text({"
                      +Check for Weapon Authorization: []
                      +Check Security Records: []
                      +Neutralize Identified Criminals: []
                      +Neutralize All Non-Security and Non-Command Personnel: []
                      +Neutralize All Unidentified Life Signs: []
                      "}, + +"[src.auth_weapons ? "Yes" : "No"]", +"[src.check_records ? "Yes" : "No"]", +"[src.criminals ? "Yes" : "No"]", +"[stun_all ? "Yes" : "No"]", +"[check_anomalies ? "Yes" : "No"]" ) + else + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(((src.lasercolor) == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag))) + return + if(((src.lasercolor) == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) + return + dat += text({" +Automatic Portable Turret Installation

                      +Status: []
                      "}, + +"[src.on ? "On" : "Off"]" ) + + + user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") + onclose(user, "autosec") + return + +/obj/machinery/porta_turret/Topic(href, href_list) + if (..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if ((href_list["power"]) && (src.allowed(usr))) + if(anchored) // you can't turn a turret on/off if it's not anchored/secured + on = !on // toggle on/off + else to_chat(usr, "It has to be secured first!") - - updateUsrDialog() - return - - switch(href_list["operation"]) - // toggles customizable behavioural protocols - - if ("authweapon") - src.auth_weapons = !src.auth_weapons - if ("checkrecords") - src.check_records = !src.check_records - if ("shootcrooks") - src.criminals = !src.criminals - if("shootall") - stun_all = !stun_all - updateUsrDialog() - - -/obj/machinery/porta_turret/power_change() - - if(!anchored) - icon_state = "turretCover" - return - if(stat & BROKEN) - icon_state = "[lasercolor]destroyed_target_prism" - else - if( powered() ) - if (on) - if (installation == /obj/item/weapon/gun/energy/laser || installation == /obj/item/weapon/gun/energy/pulse_rifle) - // laser guns and pulse rifles have an orange icon - icon_state = "[lasercolor]orange_target_prism" - else - // anything else has a blue icon - icon_state = "[lasercolor]target_prism" - else - icon_state = "[lasercolor]grey_target_prism" - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - src.icon_state = "[lasercolor]grey_target_prism" - stat |= NOPOWER - -/obj/machinery/porta_turret/emag(mob/user) - if(!emagged) + + updateUsrDialog() + return + + switch(href_list["operation"]) + // toggles customizable behavioural protocols + + if ("authweapon") + src.auth_weapons = !src.auth_weapons + if ("checkrecords") + src.check_records = !src.check_records + if ("shootcrooks") + src.criminals = !src.criminals + if("shootall") + stun_all = !stun_all + updateUsrDialog() + + +/obj/machinery/porta_turret/power_change() + + if(!anchored) + icon_state = "turretCover" + return + if(stat & BROKEN) + icon_state = "[lasercolor]destroyed_target_prism" + else + if( powered() ) + if (on) + if (installation == /obj/item/weapon/gun/energy/laser || installation == /obj/item/weapon/gun/energy/pulse_rifle) + // laser guns and pulse rifles have an orange icon + icon_state = "[lasercolor]orange_target_prism" + else + // anything else has a blue icon + icon_state = "[lasercolor]target_prism" + else + icon_state = "[lasercolor]grey_target_prism" + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + src.icon_state = "[lasercolor]grey_target_prism" + stat |= NOPOWER + +/obj/machinery/porta_turret/emag(mob/user) + if(!emagged) to_chat(user, "You short out [src]'s threat assessment circuits.") - spawn(0) - for(var/mob/O in hearers(src, null)) - O.show_message("[src] hums oddly...", 1) - emagged = 1 - src.on = 0 // turns off the turret temporarily - sleep(60) // 6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit - on = 1 // turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here -/obj/machinery/porta_turret/attackby(obj/item/W as obj, mob/user as mob) - if(stat & BROKEN) - if(istype(W, /obj/item/weapon/crowbar)) - - // If the turret is destroyed, you can remove it with a crowbar to - // try and salvage its components + spawn(0) + for(var/mob/O in hearers(src, null)) + O.show_message("[src] hums oddly...", 1) + emagged = 1 + src.on = 0 // turns off the turret temporarily + sleep(60) // 6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit + on = 1 // turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here +/obj/machinery/porta_turret/attackby(obj/item/W as obj, mob/user as mob) + if(stat & BROKEN) + if(istype(W, /obj/item/weapon/crowbar)) + + // If the turret is destroyed, you can remove it with a crowbar to + // try and salvage its components to_chat(user, "You begin prying the metal coverings off.") - sleep(20) - if(prob(70)) + sleep(20) + if(prob(70)) to_chat(user, "You remove the turret and salvage some components.") - if(installation) - var/obj/item/weapon/gun/energy/Gun = new installation(src.loc) - Gun.power_supply.charge=gun_charge - Gun.update_icon() - lasercolor = null - if(prob(50)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,loc) - M.amount = rand(1,4) - if(prob(50)) new /obj/item/device/assembly/prox_sensor(locate(x,y,z)) - else + if(installation) + var/obj/item/weapon/gun/energy/Gun = new installation(src.loc) + Gun.power_supply.charge=gun_charge + Gun.update_icon() + lasercolor = null + if(prob(50)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,loc) + M.amount = rand(1,4) + if(prob(50)) new /obj/item/device/assembly/prox_sensor(locate(x,y,z)) + else to_chat(user, "You remove the turret but did not manage to salvage anything.") - qdel(src) - return - - ..() - - if((istype(W, /obj/item/weapon/wrench)) && (!on)) - if(raised) return - // This code handles moving the turret around. After all, it's a portable turret! - - if(!anchored) - anchored = 1 - invisibility = INVISIBILITY_LEVEL_TWO - icon_state = "[lasercolor]grey_target_prism" + qdel(src) + return + + ..() + + if((istype(W, /obj/item/weapon/wrench)) && (!on)) + if(raised) return + // This code handles moving the turret around. After all, it's a portable turret! + + if(!anchored) + anchored = 1 + invisibility = INVISIBILITY_LEVEL_TWO + icon_state = "[lasercolor]grey_target_prism" to_chat(user, "You secure the exterior bolts on the turret.") - cover=new/obj/machinery/porta_turret_cover(src.loc) // create a new turret. While this is handled in process(), this is to workaround a bug where the turret becomes invisible for a split second - cover.Parent_Turret = src // make the cover's parent src - else - anchored = 0 + cover=new/obj/machinery/porta_turret_cover(src.loc) // create a new turret. While this is handled in process(), this is to workaround a bug where the turret becomes invisible for a split second + cover.Parent_Turret = src // make the cover's parent src + else + anchored = 0 to_chat(user, "You unsecure the exterior bolts on the turret.") - icon_state = "turretCover" - invisibility = 0 - qdel(cover) // deletes the cover, and the turret instance itself becomes its own cover. - - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - // Behavior lock/unlock mangement - if (allowed(user)) - locked = !src.locked + icon_state = "turretCover" + invisibility = 0 + qdel(cover) // deletes the cover, and the turret instance itself becomes its own cover. + + else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + // Behavior lock/unlock mangement + if (allowed(user)) + locked = !src.locked to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]") - else + else to_chat(user, "Access denied.") - - else - user.delayNextAttack(10) - // if the turret was attacked with the intention of harming it: - src.health -= W.force * 0.5 - if (src.health <= 0) - src.die() - if ((W.force * 0.5) > 1) // if the force of impact dealt at least 1 damage, the turret gets pissed off - if(!attacked && !emagged) - attacked = 1 - spawn() - sleep(60) - attacked = 0 - - - -/obj/machinery/porta_turret/bullet_act(var/obj/item/projectile/Proj) - if(on) - if(!attacked && !emagged) - attacked = 1 - spawn() - sleep(60) - attacked = 0 - - src.health -= Proj.damage - ..() - if(prob(45) && Proj.damage > 0) src.spark_system.start() - if (src.health <= 0) - src.die() // the death process :( - if((src.lasercolor == "b") && (src.disabled == 0)) - if(istype(Proj, /obj/item/projectile/beam/lastertag/red)) - src.disabled = 1 - qdel (Proj) - Proj = null - sleep(100) - src.disabled = 0 - if((src.lasercolor == "r") && (src.disabled == 0)) - if(istype(Proj, /obj/item/projectile/beam/lastertag/blue)) - src.disabled = 1 - qdel (Proj) - Proj = null - sleep(100) - src.disabled = 0 - return - -/obj/machinery/porta_turret/emp_act(severity) - if(on) - // if the turret is on, the EMP no matter how severe disables the turret for a while - // and scrambles its settings, with a slight chance of having an emag effect - check_records=pick(0,1) - criminals=pick(0,1) - auth_weapons=pick(0,1) - stun_all=pick(0,0,0,0,1) // stun_all is a pretty big deal, so it's least likely to get turned on - if(prob(5)) emagged=1 - on=0 - sleep(rand(60,600)) - if(!on) - on=1 - - ..() - -/obj/machinery/porta_turret/ex_act(severity) - if(severity >= 3) // turret dies if an explosion touches it! - qdel(src) - else - src.die() - -/obj/machinery/porta_turret/proc/die() // called when the turret dies, ie, health <= 0 - src.health = 0 - src.density = 0 - src.stat |= BROKEN // enables the BROKEN bit - src.icon_state = "[lasercolor]destroyed_target_prism" - invisibility=0 - src.spark_system.start() // creates some sparks because they look cool - src.density=1 - qdel(cover) // deletes the cover - no need on keeping it there! - - - -/obj/machinery/porta_turret/process() - // the main machinery process - - //set background = 1 - - if(src.cover==null && anchored) // if it has no cover and is anchored - if (stat & BROKEN) // if the turret is borked - qdel(cover) // delete its cover, assuming it has one. Workaround for a pesky little bug - else - - src.cover = new /obj/machinery/porta_turret_cover(src.loc) // if the turret has no cover and is anchored, give it a cover - src.cover.Parent_Turret = src // assign the cover its Parent_Turret, which would be this (src) - - if(stat & (NOPOWER|BROKEN)) - // if the turret has no power or is broken, make the turret pop down if it hasn't already - popDown() - return - - if(!on) - // if the turret is off, make it pop down - popDown() - return - - var/list/targets = list() // list of primary targets - var/list/secondarytargets = list() // targets that are least important - - if(src.check_anomalies) // if its set to check for xenos/carps, check for non-mob "crittersssss"(And simple_animals) - for(var/mob/living/simple_animal/C in view(7,src)) - if(C.stat) - continue - if(C.flags & INVULNERABLE) - continue - // Ignore lazarus-injected mobs. - if(dd_hasprefix(C.faction, "lazarus")) - continue - targets += C - - for (var/mob/living/carbon/C in view(7,src)) // loops through all living carbon-based lifeforms in view(12) - if(C.flags & INVULNERABLE) - continue - if(istype(C, /mob/living/carbon/alien) && src.check_anomalies) // git those fukken xenos - if(!C.stat) // if it's dead/dying, there's no need to keep shooting at it. - targets += C - - else - if(emagged) // if emagged, HOLY SHIT EVERYONE IS DANGEROUS beep boop beep - targets += C - else - if (C.stat || C.handcuffed) // if the perp is handcuffed or dead/dying, no need to bother really - continue // move onto next potential victim! - - var/dst = get_dist(src, C) // if it's too far away, why bother? - if (dst > 7) - continue - - if(ai) // If it's set to attack all nonsilicons, target them! - if(C.lying) - if(lasercolor) - continue - else - secondarytargets += C - continue - else - targets += C - continue - - if (istype(C, /mob/living/carbon/human)) // if the target is a human, analyze threat level - if(src.assess_perp(C)<4) - continue // if threat level < 4, keep going - - else if (istype(C, /mob/living/carbon/monkey)) - continue // Don't target monkeys or borgs/AIs you dumb shit - - if (C.lying) // if the perp is lying down, it's still a target but a less-important target - secondarytargets += C - continue - - targets += C // if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee - - if (targets.len>0) // if there are targets to shoot - - var/atom/t = pick(targets) // pick a perp from the list of targets. Targets go first because they are the most important - - if (istype(t, /mob/living)) // if a mob - var/mob/living/M = t // simple typecasting - if (M.stat!=2) // if the target is not dead - spawn() popUp() // pop the turret up if it's not already up. - dir=get_dir(src,M) // even if you can't shoot, follow the target - spawn() shootAt(M) // shoot the target, finally - if(prob(15)) - if(prob(50)) - playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) - else - playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) - - else if(secondarytargets.len>0) // if there are no primary targets, go for secondary targets - var/mob/t = pick(secondarytargets) - if (istype(t, /mob/living)) - if (t.stat!=2) - spawn() popUp() - dir=get_dir(src,t) - shootAt(t) - if(prob(15)) - if(prob(50)) - playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) - else - playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) - else - spawn() - popDown() - - -/obj/machinery/porta_turret/proc/popUp() // pops the turret up - if(disabled) - return - if(raising || raised) return - if(stat & BROKEN) return - invisibility=0 - raising=1 - flick("popup",cover) - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) - sleep(5) - sleep(5) - raising=0 - cover.icon_state="openTurretCover" - raised=1 - layer=4 - -/obj/machinery/porta_turret/proc/popDown() // pops the turret down - if(disabled) - return - if(raising || !raised) return - if(stat & BROKEN) return - layer=3 - raising=1 - flick("popdown",cover) - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) - sleep(10) - raising=0 - cover.icon_state="turretCover" - raised=0 - invisibility=2 - icon_state="[lasercolor]grey_target_prism" - - -/obj/machinery/porta_turret/proc/assess_perp(mob/living/carbon/human/perp as mob) - var/threatcount = 0 // the integer returned - - if(src.emagged) return 10 // if emagged, always return 10. - - if((stun_all && !src.allowed(perp)) || attacked && !src.allowed(perp)) - // if the turret has been attacked or is angry, target all non-sec people - if(!src.allowed(perp)) - return 10 - - if(auth_weapons) // check for weapon authorization - if((isnull(perp.wear_id)) || (istype(perp.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))) - - if((src.allowed(perp)) && !(src.lasercolor)) // if the perp has security access, return 0 - return 0 - - if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) - threatcount += 4 - - if((istype(perp.r_hand, /obj/item/weapon/gun) && !istype(perp.r_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.r_hand, /obj/item/weapon/melee/baton)) - threatcount += 4 - - if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee/baton)) - threatcount += 2 - - if((src.lasercolor) == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - threatcount = 0//But does not target anyone else - if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) - threatcount += 4 - if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/redtag))) - threatcount += 4 - if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 2 - - if((src.lasercolor) == "r") - threatcount = 0 - if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) - threatcount += 4 - if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) - threatcount += 4 - if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 2 - - if (src.check_records) // if the turret can check the records, check if they are set to *Arrest* on records - for (var/datum/data/record/E in data_core.general) - - var/perpname = perp.name - if (perp.wear_id) - var/obj/item/weapon/card/id/id = perp.wear_id.GetID() - if (id) - perpname = id.registered_name - - if (E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if ((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - threatcount = 4 - break - - - - return threatcount - - - - - -/obj/machinery/porta_turret/proc/shootAt(var/atom/movable/target) // shoots at a target - if(disabled) - return - - if(lasercolor && (istype(target,/mob/living/carbon/human))) - var/mob/living/carbon/human/H = target - if(H.lying) - return - - if(!emagged) // if it hasn't been emagged, it has to obey a cooldown rate - if(last_fired || !raised) return // prevents rapid-fire shooting, unless it's been emagged - last_fired = 1 - spawn() - sleep(shot_delay) - last_fired = 0 - - var/turf/T = get_turf(src) - var/turf/U = get_turf(target) - if (!istype(T) || !istype(U)) - return - - if (!raised) // the turret has to be raised in order to fire - makes sense, right? - return - - - // any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power! - - if(iconholder) - icon_state = "[lasercolor]target_prism" - else - icon_state = "[lasercolor]orange_target_prism" - - var/obj/item/projectile/A - if(emagged) - playsound(get_turf(src), efire_sound, 75, 1) - A = new eprojectile( loc ) - else - playsound(get_turf(src), fire_sound, 75, 1) - A = new projectile( loc ) - A.original = target.loc - if(!emagged) - use_power(reqpower) - else - use_power((reqpower*2)) - // Shooting Code: - A.starting = T - A.shot_from = src - A.current = T - A.yo = U.y - T.y - A.xo = U.x - T.x - spawn( 1 ) - A.OnFired() - A.process() - return - - - -/* - - Portable turret constructions - - Known as "turret frame"s - -*/ - -/obj/machinery/porta_turret_construct - name = "turret frame" - icon = 'icons/obj/turrets.dmi' - icon_state = "turret_frame" - density=1 - var/build_step = 0 // the current step in the building process - var/finish_name="turret" // the name applied to the product turret - var/installation = null // the gun type installed - var/gun_charge = 0 // the gun charge of the gun type installed - - - -/obj/machinery/porta_turret_construct/attackby(obj/item/W as obj, mob/user as mob) - - // this is a bit unweildy but self-explanitory - switch(build_step) - if(0) // first step - if(istype(W, /obj/item/weapon/wrench) && !anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + + else + user.delayNextAttack(10) + // if the turret was attacked with the intention of harming it: + src.health -= W.force * 0.5 + if (src.health <= 0) + src.die() + if ((W.force * 0.5) > 1) // if the force of impact dealt at least 1 damage, the turret gets pissed off + if(!attacked && !emagged) + attacked = 1 + spawn() + sleep(60) + attacked = 0 + + + +/obj/machinery/porta_turret/bullet_act(var/obj/item/projectile/Proj) + if(on) + if(!attacked && !emagged) + attacked = 1 + spawn() + sleep(60) + attacked = 0 + + src.health -= Proj.damage + ..() + if(prob(45) && Proj.damage > 0) src.spark_system.start() + if (src.health <= 0) + src.die() // the death process :( + if((src.lasercolor == "b") && (src.disabled == 0)) + if(istype(Proj, /obj/item/projectile/beam/lastertag/red)) + src.disabled = 1 + qdel (Proj) + Proj = null + sleep(100) + src.disabled = 0 + if((src.lasercolor == "r") && (src.disabled == 0)) + if(istype(Proj, /obj/item/projectile/beam/lastertag/blue)) + src.disabled = 1 + qdel (Proj) + Proj = null + sleep(100) + src.disabled = 0 + return + +/obj/machinery/porta_turret/emp_act(severity) + if(on) + // if the turret is on, the EMP no matter how severe disables the turret for a while + // and scrambles its settings, with a slight chance of having an emag effect + check_records=pick(0,1) + criminals=pick(0,1) + auth_weapons=pick(0,1) + stun_all=pick(0,0,0,0,1) // stun_all is a pretty big deal, so it's least likely to get turned on + if(prob(5)) emagged=1 + on=0 + sleep(rand(60,600)) + if(!on) + on=1 + + ..() + +/obj/machinery/porta_turret/ex_act(severity) + if(severity >= 3) // turret dies if an explosion touches it! + qdel(src) + else + src.die() + +/obj/machinery/porta_turret/proc/die() // called when the turret dies, ie, health <= 0 + src.health = 0 + src.density = 0 + src.stat |= BROKEN // enables the BROKEN bit + src.icon_state = "[lasercolor]destroyed_target_prism" + invisibility=0 + src.spark_system.start() // creates some sparks because they look cool + src.density=1 + qdel(cover) // deletes the cover - no need on keeping it there! + + + +/obj/machinery/porta_turret/process() + // the main machinery process + + //set background = 1 + + if(src.cover==null && anchored) // if it has no cover and is anchored + if (stat & BROKEN) // if the turret is borked + qdel(cover) // delete its cover, assuming it has one. Workaround for a pesky little bug + else + + src.cover = new /obj/machinery/porta_turret_cover(src.loc) // if the turret has no cover and is anchored, give it a cover + src.cover.Parent_Turret = src // assign the cover its Parent_Turret, which would be this (src) + + if(stat & (NOPOWER|BROKEN)) + // if the turret has no power or is broken, make the turret pop down if it hasn't already + popDown() + return + + if(!on) + // if the turret is off, make it pop down + popDown() + return + + var/list/targets = list() // list of primary targets + var/list/secondarytargets = list() // targets that are least important + + if(src.check_anomalies) // if its set to check for xenos/carps, check for non-mob "crittersssss"(And simple_animals) + for(var/mob/living/simple_animal/C in view(7,src)) + if(C.stat) + continue + if(C.flags & INVULNERABLE) + continue + // Ignore lazarus-injected mobs. + if(dd_hasprefix(C.faction, "lazarus")) + continue + targets += C + + for (var/mob/living/carbon/C in view(7,src)) // loops through all living carbon-based lifeforms in view(12) + if(C.flags & INVULNERABLE) + continue + if(istype(C, /mob/living/carbon/alien) && src.check_anomalies) // git those fukken xenos + if(!C.stat) // if it's dead/dying, there's no need to keep shooting at it. + targets += C + + else + if(emagged) // if emagged, HOLY SHIT EVERYONE IS DANGEROUS beep boop beep + targets += C + else + if (C.stat || C.handcuffed) // if the perp is handcuffed or dead/dying, no need to bother really + continue // move onto next potential victim! + + var/dst = get_dist(src, C) // if it's too far away, why bother? + if (dst > 7) + continue + + if(ai) // If it's set to attack all nonsilicons, target them! + if(C.lying) + if(lasercolor) + continue + else + secondarytargets += C + continue + else + targets += C + continue + + if (istype(C, /mob/living/carbon/human)) // if the target is a human, analyze threat level + if(src.assess_perp(C)<4) + continue // if threat level < 4, keep going + + else if (istype(C, /mob/living/carbon/monkey)) + continue // Don't target monkeys or borgs/AIs you dumb shit + + if (C.lying) // if the perp is lying down, it's still a target but a less-important target + secondarytargets += C + continue + + targets += C // if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee + + if (targets.len>0) // if there are targets to shoot + + var/atom/t = pick(targets) // pick a perp from the list of targets. Targets go first because they are the most important + + if (istype(t, /mob/living)) // if a mob + var/mob/living/M = t // simple typecasting + if (M.stat!=2) // if the target is not dead + spawn() popUp() // pop the turret up if it's not already up. + dir=get_dir(src,M) // even if you can't shoot, follow the target + spawn() shootAt(M) // shoot the target, finally + if(prob(15)) + if(prob(50)) + playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + else + playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + + else if(secondarytargets.len>0) // if there are no primary targets, go for secondary targets + var/mob/t = pick(secondarytargets) + if (istype(t, /mob/living)) + if (t.stat!=2) + spawn() popUp() + dir=get_dir(src,t) + shootAt(t) + if(prob(15)) + if(prob(50)) + playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + else + playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + else + spawn() + popDown() + + +/obj/machinery/porta_turret/proc/popUp() // pops the turret up + if(disabled) + return + if(raising || raised) return + if(stat & BROKEN) return + invisibility=0 + raising=1 + flick("popup",cover) + playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + sleep(5) + sleep(5) + raising=0 + cover.icon_state="openTurretCover" + raised=1 + layer=4 + +/obj/machinery/porta_turret/proc/popDown() // pops the turret down + if(disabled) + return + if(raising || !raised) return + if(stat & BROKEN) return + layer=3 + raising=1 + flick("popdown",cover) + playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + sleep(10) + raising=0 + cover.icon_state="turretCover" + raised=0 + invisibility=2 + icon_state="[lasercolor]grey_target_prism" + + +/obj/machinery/porta_turret/proc/assess_perp(mob/living/carbon/human/perp as mob) + var/threatcount = 0 // the integer returned + + if(src.emagged) return 10 // if emagged, always return 10. + + if((stun_all && !src.allowed(perp)) || attacked && !src.allowed(perp)) + // if the turret has been attacked or is angry, target all non-sec people + if(!src.allowed(perp)) + return 10 + + if(auth_weapons) // check for weapon authorization + if((isnull(perp.wear_id)) || (istype(perp.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))) + + if((src.allowed(perp)) && !(src.lasercolor)) // if the perp has security access, return 0 + return 0 + + if((istype(perp.l_hand, /obj/item/weapon/gun) && !istype(perp.l_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.l_hand, /obj/item/weapon/melee/baton)) + threatcount += 4 + + if((istype(perp.r_hand, /obj/item/weapon/gun) && !istype(perp.r_hand, /obj/item/weapon/gun/projectile/shotgun)) || istype(perp.r_hand, /obj/item/weapon/melee/baton)) + threatcount += 4 + + if(istype(perp.belt, /obj/item/weapon/gun) || istype(perp.belt, /obj/item/weapon/melee/baton)) + threatcount += 2 + + if((src.lasercolor) == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve + threatcount = 0//But does not target anyone else + if(istype(perp.wear_suit, /obj/item/clothing/suit/redtag)) + threatcount += 4 + if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/redtag))) + threatcount += 4 + if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 2 + + if((src.lasercolor) == "r") + threatcount = 0 + if(istype(perp.wear_suit, /obj/item/clothing/suit/bluetag)) + threatcount += 4 + if((istype(perp.r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(perp.l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + threatcount += 4 + if(istype(perp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 2 + + if (src.check_records) // if the turret can check the records, check if they are set to *Arrest* on records + for (var/datum/data/record/E in data_core.general) + + var/perpname = perp.name + if (perp.wear_id) + var/obj/item/weapon/card/id/id = perp.wear_id.GetID() + if (id) + perpname = id.registered_name + + if (E.fields["name"] == perpname) + for (var/datum/data/record/R in data_core.security) + if ((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) + threatcount = 4 + break + + + + return threatcount + + + + + +/obj/machinery/porta_turret/proc/shootAt(var/atom/movable/target) // shoots at a target + if(disabled) + return + + if(lasercolor && (istype(target,/mob/living/carbon/human))) + var/mob/living/carbon/human/H = target + if(H.lying) + return + + if(!emagged) // if it hasn't been emagged, it has to obey a cooldown rate + if(last_fired || !raised) return // prevents rapid-fire shooting, unless it's been emagged + last_fired = 1 + spawn() + sleep(shot_delay) + last_fired = 0 + + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + if (!istype(T) || !istype(U)) + return + + if (!raised) // the turret has to be raised in order to fire - makes sense, right? + return + + + // any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power! + + if(iconholder) + icon_state = "[lasercolor]target_prism" + else + icon_state = "[lasercolor]orange_target_prism" + + var/obj/item/projectile/A + if(emagged) + playsound(get_turf(src), efire_sound, 75, 1) + A = new eprojectile( loc ) + else + playsound(get_turf(src), fire_sound, 75, 1) + A = new projectile( loc ) + A.original = target.loc + if(!emagged) + use_power(reqpower) + else + use_power((reqpower*2)) + // Shooting Code: + A.starting = T + A.shot_from = src + A.current = T + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn( 1 ) + A.OnFired() + A.process() + return + + + +/* + + Portable turret constructions + + Known as "turret frame"s + +*/ + +/obj/machinery/porta_turret_construct + name = "turret frame" + icon = 'icons/obj/turrets.dmi' + icon_state = "turret_frame" + density=1 + var/build_step = 0 // the current step in the building process + var/finish_name="turret" // the name applied to the product turret + var/installation = null // the gun type installed + var/gun_charge = 0 // the gun charge of the gun type installed + + + +/obj/machinery/porta_turret_construct/attackby(obj/item/W as obj, mob/user as mob) + + // this is a bit unweildy but self-explanitory + switch(build_step) + if(0) // first step + if(istype(W, /obj/item/weapon/wrench) && !anchored) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) to_chat(user, "You secure the external bolts.") - anchored = 1 - build_step = 1 - return - - else if(istype(W, /obj/item/weapon/crowbar) && !anchored) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + anchored = 1 + build_step = 1 + return + + else if(istype(W, /obj/item/weapon/crowbar) && !anchored) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) to_chat(user, "You dismantle the turret construction.") - //new /obj/item/stack/sheet/metal( loc, 5) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, loc) - M.amount = 5 - qdel(src) - return - - if(1) - if(istype(W, /obj/item/stack/sheet/metal)) - if(W:amount>=2) // requires 2 metal sheets + //new /obj/item/stack/sheet/metal( loc, 5) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, loc) + M.amount = 5 + qdel(src) + return + + if(1) + if(istype(W, /obj/item/stack/sheet/metal)) + if(W:amount>=2) // requires 2 metal sheets to_chat(user, "You add some metal armor to the interior frame.") - build_step = 2 - W:amount -= 2 - icon_state = "turret_frame2" - if(W:amount <= 0) - returnToPool(W) - return - - else if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + build_step = 2 + W:amount -= 2 + icon_state = "turret_frame2" + if(W:amount <= 0) + returnToPool(W) + return + + else if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) to_chat(user, "You unfasten the external bolts.") - anchored = 0 - build_step = 0 - return - - - if(2) - if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + anchored = 0 + build_step = 0 + return + + + if(2) + if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) to_chat(user, "You bolt the metal armor into place.") - build_step = 3 - return - - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.isOn()) return - if (WT.get_fuel() < 5) // uses up 5 fuel. + build_step = 3 + return + + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. to_chat(user, "You need more fuel to complete this task.") - return - - playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) - if(do_after(user, src, 20)) - if(!src || !WT.remove_fuel(5, user)) return - build_step = 1 + return + + playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + if(do_after(user, src, 20)) + if(!src || !WT.remove_fuel(5, user)) return + build_step = 1 to_chat(user, "You remove the turret's interior metal armor.") - //new /obj/item/stack/sheet/metal( loc, 2) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,loc) - M.amount = 2 - return - - - if(3) - if(istype(W, /obj/item/weapon/gun/energy)) // the gun installation part - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1) - var/obj/item/weapon/gun/energy/E = W // typecasts the item to an energy gun - installation = W.type // installation becomes W.type - gun_charge = E.power_supply.charge // the gun's charge is stored in src.gun_charge + //new /obj/item/stack/sheet/metal( loc, 2) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,loc) + M.amount = 2 + return + + + if(3) + if(istype(W, /obj/item/weapon/gun/energy)) // the gun installation part + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1) + var/obj/item/weapon/gun/energy/E = W // typecasts the item to an energy gun + installation = W.type // installation becomes W.type + gun_charge = E.power_supply.charge // the gun's charge is stored in src.gun_charge to_chat(user, "You add \the [W] to the turret.") - build_step = 4 - qdel(W) // delete the gun :( - return - - else if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + build_step = 4 + qdel(W) // delete the gun :( + return + + else if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) to_chat(user, "You remove the turret's metal armor bolts.") - build_step = 2 - return - - if(4) - if(isprox(W)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1) - build_step = 5 + build_step = 2 + return + + if(4) + if(isprox(W)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1) + build_step = 5 to_chat(user, "You add the prox sensor to the turret.") - qdel(W) - return - - // attack_hand() removes the gun - - if(5) - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) - build_step = 6 + qdel(W) + return + + // attack_hand() removes the gun + + if(5) + if(istype(W, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + build_step = 6 to_chat(user, "You close the internal access hatch.") - return - - // attack_hand() removes the prox sensor - - if(6) - if(istype(W, /obj/item/stack/sheet/metal)) - if(W:amount>=2) + return + + // attack_hand() removes the prox sensor + + if(6) + if(istype(W, /obj/item/stack/sheet/metal)) + if(W:amount>=2) to_chat(user, "You add some metal armor to the exterior frame.") - build_step = 7 - W:amount -= 2 - if(W:amount <= 0) - qdel(W) - return - - else if(istype(W, /obj/item/weapon/screwdriver)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) - build_step = 5 + build_step = 7 + W:amount -= 2 + if(W:amount <= 0) + qdel(W) + return + + else if(istype(W, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + build_step = 5 to_chat(user, "You open the internal access hatch.") - return - - if(7) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.isOn()) return - if (WT.get_fuel() < 5) + return + + if(7) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.isOn()) return + if (WT.get_fuel() < 5) to_chat(user, "You need more fuel to complete this task.") - - playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) - if(do_after(user, src, 30)) - if(!src || !WT.remove_fuel(5, user)) return - build_step = 8 + + playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + if(do_after(user, src, 30)) + if(!src || !WT.remove_fuel(5, user)) return + build_step = 8 to_chat(user, "You weld the turret's armor down.") - - // The final step: create a full turret - var/obj/machinery/porta_turret/Turret = new/obj/machinery/porta_turret(locate(x,y,z)) - Turret.name = finish_name - Turret.installation = src.installation - Turret.gun_charge = src.gun_charge - Turret.update_gun() - qdel(src) - - else if(istype(W, /obj/item/weapon/crowbar)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + + // The final step: create a full turret + var/obj/machinery/porta_turret/Turret = new/obj/machinery/porta_turret(locate(x,y,z)) + Turret.name = finish_name + Turret.installation = src.installation + Turret.gun_charge = src.gun_charge + Turret.update_gun() + qdel(src) + + else if(istype(W, /obj/item/weapon/crowbar)) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) to_chat(user, "You pry off the turret's exterior armor.") - //new /obj/item/stack/sheet/metal( loc, 2) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,loc) - M.amount = 2 - build_step = 6 - return - - if (istype(W, /obj/item/weapon/pen)) // you can rename turrets like bots! - var/t = input(user, "Enter new turret name", src.name, src.finish_name) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - - src.finish_name = t - return - ..() - - - -/obj/machinery/porta_turret_construct/attack_hand(mob/user as mob) - switch(build_step) - if(4) - if(!installation) return - build_step = 3 - - var/obj/item/weapon/gun/energy/Gun = new installation(src.loc) - Gun.power_supply.charge=gun_charge - Gun.update_icon() - installation = null - gun_charge = 0 + //new /obj/item/stack/sheet/metal( loc, 2) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,loc) + M.amount = 2 + build_step = 6 + return + + if (istype(W, /obj/item/weapon/pen)) // you can rename turrets like bots! + var/t = input(user, "Enter new turret name", src.name, src.finish_name) as text + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t) + return + if (!in_range(src, usr) && src.loc != usr) + return + + src.finish_name = t + return + ..() + + + +/obj/machinery/porta_turret_construct/attack_hand(mob/user as mob) + switch(build_step) + if(4) + if(!installation) return + build_step = 3 + + var/obj/item/weapon/gun/energy/Gun = new installation(src.loc) + Gun.power_supply.charge=gun_charge + Gun.update_icon() + installation = null + gun_charge = 0 to_chat(user, "You remove \the [Gun] from the turret frame.") - - if(5) + + if(5) to_chat(user, "You remove the prox sensor from the turret frame.") - new/obj/item/device/assembly/prox_sensor(locate(x,y,z)) - build_step = 4 - - - - - - - - - - - - -/obj/machinery/porta_turret_cover - name = "turret" - icon = 'icons/obj/turrets.dmi' - icon_state = "turretCover" - anchored = 1 - layer = 3.5 - density = 0 - var/obj/machinery/porta_turret/Parent_Turret = null - - - -// The below code is pretty much just recoded from the initial turret object. It's necessary but uncommented because it's exactly the same! - -/obj/machinery/porta_turret_cover/attack_ai(mob/user as mob) - . = ..() - if (.) - return - src.add_hiddenprint(user) - var/dat - if(!(Parent_Turret.lasercolor)) - dat += text({" -Automatic Portable Turret Installation

                      -Status: []
                      -Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - - dat += text({"
                      -Check for Weapon Authorization: []
                      -Check Security Records: []
                      -Neutralize Identified Criminals: []
                      -Neutralize All Non-Security and Non-Command Personnel: []
                      -Neutralize All Unidentified Life Signs: []
                      "}, - -"[Parent_Turret.auth_weapons ? "Yes" : "No"]", -"[Parent_Turret.check_records ? "Yes" : "No"]", -"[Parent_Turret.criminals ? "Yes" : "No"]", -"[Parent_Turret.stun_all ? "Yes" : "No"]" , -"[Parent_Turret.check_anomalies ? "Yes" : "No"]" ) - else - dat += text({" -Automatic Portable Turret Installation

                      -Status: []
                      "}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/porta_turret_cover/attack_hand(mob/user as mob) - . = ..() - if (.) - return - var/dat - if(!(Parent_Turret.lasercolor)) - dat += text({" -Automatic Portable Turret Installation

                      -Status: []
                      -Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - if(!Parent_Turret.locked) - dat += text({"
                      -Check for Weapon Authorization: []
                      -Check Security Records: []
                      -Neutralize Identified Criminals: []
                      -Neutralize All Non-Security and Non-Command Personnel: []
                      -Neutralize All Unidentified Life Signs: []
                      "}, - -"[Parent_Turret.auth_weapons ? "Yes" : "No"]", -"[Parent_Turret.check_records ? "Yes" : "No"]", -"[Parent_Turret.criminals ? "Yes" : "No"]", -"[Parent_Turret.stun_all ? "Yes" : "No"]" , -"[Parent_Turret.check_anomalies ? "Yes" : "No"]" ) - else - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(((Parent_Turret.lasercolor) == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag))) - return - if(((Parent_Turret.lasercolor) == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) - return - dat += text({" -Automatic Portable Turret Installation

                      -Status: []
                      "}, - -"[Parent_Turret.on ? "On" : "Off"]" ) - - - - user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") - onclose(user, "autosec") - return - -/obj/machinery/porta_turret_cover/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - Parent_Turret.add_fingerprint(usr) - src.add_fingerprint(usr) - if ((href_list["power"]) && (Parent_Turret.allowed(usr))) - if(Parent_Turret.anchored) - if (Parent_Turret.on) - Parent_Turret.on=0 - else - Parent_Turret.on=1 - else + new/obj/item/device/assembly/prox_sensor(locate(x,y,z)) + build_step = 4 + + + + + + + + + + + + +/obj/machinery/porta_turret_cover + name = "turret" + icon = 'icons/obj/turrets.dmi' + icon_state = "turretCover" + anchored = 1 + layer = 3.5 + density = 0 + var/obj/machinery/porta_turret/Parent_Turret = null + + + +// The below code is pretty much just recoded from the initial turret object. It's necessary but uncommented because it's exactly the same! + +/obj/machinery/porta_turret_cover/attack_ai(mob/user as mob) + . = ..() + if (.) + return + src.add_hiddenprint(user) + var/dat + if(!(Parent_Turret.lasercolor)) + dat += text({" +Automatic Portable Turret Installation

                      +Status: []
                      +Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"}, + +"[Parent_Turret.on ? "On" : "Off"]" ) + + + dat += text({"
                      +Check for Weapon Authorization: []
                      +Check Security Records: []
                      +Neutralize Identified Criminals: []
                      +Neutralize All Non-Security and Non-Command Personnel: []
                      +Neutralize All Unidentified Life Signs: []
                      "}, + +"[Parent_Turret.auth_weapons ? "Yes" : "No"]", +"[Parent_Turret.check_records ? "Yes" : "No"]", +"[Parent_Turret.criminals ? "Yes" : "No"]", +"[Parent_Turret.stun_all ? "Yes" : "No"]" , +"[Parent_Turret.check_anomalies ? "Yes" : "No"]" ) + else + dat += text({" +Automatic Portable Turret Installation

                      +Status: []
                      "}, + +"[Parent_Turret.on ? "On" : "Off"]" ) + + user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") + onclose(user, "autosec") + return + +/obj/machinery/porta_turret_cover/attack_hand(mob/user as mob) + . = ..() + if (.) + return + var/dat + if(!(Parent_Turret.lasercolor)) + dat += text({" +Automatic Portable Turret Installation

                      +Status: []
                      +Behaviour controls are [Parent_Turret.locked ? "locked" : "unlocked"]"}, + +"[Parent_Turret.on ? "On" : "Off"]" ) + + if(!Parent_Turret.locked) + dat += text({"
                      +Check for Weapon Authorization: []
                      +Check Security Records: []
                      +Neutralize Identified Criminals: []
                      +Neutralize All Non-Security and Non-Command Personnel: []
                      +Neutralize All Unidentified Life Signs: []
                      "}, + +"[Parent_Turret.auth_weapons ? "Yes" : "No"]", +"[Parent_Turret.check_records ? "Yes" : "No"]", +"[Parent_Turret.criminals ? "Yes" : "No"]", +"[Parent_Turret.stun_all ? "Yes" : "No"]" , +"[Parent_Turret.check_anomalies ? "Yes" : "No"]" ) + else + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(((Parent_Turret.lasercolor) == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag))) + return + if(((Parent_Turret.lasercolor) == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag))) + return + dat += text({" +Automatic Portable Turret Installation

                      +Status: []
                      "}, + +"[Parent_Turret.on ? "On" : "Off"]" ) + + + + user << browse("Automatic Portable Turret Installation[dat]", "window=autosec") + onclose(user, "autosec") + return + +/obj/machinery/porta_turret_cover/Topic(href, href_list) + if (..()) + return + usr.set_machine(src) + Parent_Turret.add_fingerprint(usr) + src.add_fingerprint(usr) + if ((href_list["power"]) && (Parent_Turret.allowed(usr))) + if(Parent_Turret.anchored) + if (Parent_Turret.on) + Parent_Turret.on=0 + else + Parent_Turret.on=1 + else to_chat(usr, "It has to be secured first!") - - updateUsrDialog() - return - - switch(href_list["operation"]) - if ("authweapon") - Parent_Turret.auth_weapons = !Parent_Turret.auth_weapons - if ("checkrecords") - Parent_Turret.check_records = !Parent_Turret.check_records - if ("shootcrooks") - Parent_Turret.criminals = !Parent_Turret.criminals - if("shootall") - Parent_Turret.stun_all = !Parent_Turret.stun_all - if("checkxenos") - Parent_Turret.check_anomalies = !Parent_Turret.check_anomalies - - updateUsrDialog() - - - -/obj/machinery/porta_turret_cover/attackby(obj/item/W as obj, mob/user as mob) - - if ((istype(W, /obj/item/weapon/card/emag)) && (!Parent_Turret.emagged)) + + updateUsrDialog() + return + + switch(href_list["operation"]) + if ("authweapon") + Parent_Turret.auth_weapons = !Parent_Turret.auth_weapons + if ("checkrecords") + Parent_Turret.check_records = !Parent_Turret.check_records + if ("shootcrooks") + Parent_Turret.criminals = !Parent_Turret.criminals + if("shootall") + Parent_Turret.stun_all = !Parent_Turret.stun_all + if("checkxenos") + Parent_Turret.check_anomalies = !Parent_Turret.check_anomalies + + updateUsrDialog() + + + +/obj/machinery/porta_turret_cover/attackby(obj/item/W as obj, mob/user as mob) + + if ((istype(W, /obj/item/weapon/card/emag)) && (!Parent_Turret.emagged)) to_chat(user, "You short out [Parent_Turret]'s threat assessment circuits.") - spawn(0) - for(var/mob/O in hearers(Parent_Turret, null)) - O.show_message("[Parent_Turret] hums oddly...", 1) - Parent_Turret.emagged = 1 - Parent_Turret.on = 0 - sleep(40) - Parent_Turret.on = 1 - - else if((istype(W, /obj/item/weapon/wrench)) && (!Parent_Turret.on)) - if(Parent_Turret.raised) return - - if(!Parent_Turret.anchored) - Parent_Turret.anchored = 1 - Parent_Turret.invisibility = INVISIBILITY_LEVEL_TWO - Parent_Turret.icon_state = "grey_target_prism" + spawn(0) + for(var/mob/O in hearers(Parent_Turret, null)) + O.show_message("[Parent_Turret] hums oddly...", 1) + Parent_Turret.emagged = 1 + Parent_Turret.on = 0 + sleep(40) + Parent_Turret.on = 1 + + else if((istype(W, /obj/item/weapon/wrench)) && (!Parent_Turret.on)) + if(Parent_Turret.raised) return + + if(!Parent_Turret.anchored) + Parent_Turret.anchored = 1 + Parent_Turret.invisibility = INVISIBILITY_LEVEL_TWO + Parent_Turret.icon_state = "grey_target_prism" to_chat(user, "You secure the exterior bolts on the turret.") - else - Parent_Turret.anchored = 0 + else + Parent_Turret.anchored = 0 to_chat(user, "You unsecure the exterior bolts on the turret.") - Parent_Turret.icon_state = "turretCover" - Parent_Turret.invisibility = 0 - qdel(src) - - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (Parent_Turret.allowed(user)) - Parent_Turret.locked = !Parent_Turret.locked + Parent_Turret.icon_state = "turretCover" + Parent_Turret.invisibility = 0 + qdel(src) + + else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (Parent_Turret.allowed(user)) + Parent_Turret.locked = !Parent_Turret.locked to_chat(user, "Controls are now [Parent_Turret.locked ? "locked." : "unlocked."]") - updateUsrDialog() - else + updateUsrDialog() + else to_chat(user, "Access denied.") - - else - playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1) - Parent_Turret.health -= W.force * 0.5 - if (Parent_Turret.health <= 0) - Parent_Turret.die() - if ((W.force * 0.5) > 2) - if(!Parent_Turret.attacked && !Parent_Turret.emagged) - Parent_Turret.attacked = 1 - spawn() - sleep(30) - Parent_Turret.attacked = 0 - ..() - - - - -/obj/machinery/porta_turret/stationary - emagged = 1 - - New() - installation = new/obj/item/weapon/gun/energy/laser(src.loc) - ..() + + else + playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1) + Parent_Turret.health -= W.force * 0.5 + if (Parent_Turret.health <= 0) + Parent_Turret.die() + if ((W.force * 0.5) > 2) + if(!Parent_Turret.attacked && !Parent_Turret.emagged) + Parent_Turret.attacked = 1 + spawn() + sleep(30) + Parent_Turret.attacked = 0 + ..() + + + + +/obj/machinery/porta_turret/stationary + emagged = 1 + + New() + installation = new/obj/item/weapon/gun/energy/laser(src.loc) + ..() diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 8dc582fa236..b1020498d72 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -1,394 +1,394 @@ -/obj/machinery/recharge_station - name = "cyborg recharging station" - icon = 'icons/obj/objects.dmi' - icon_state = "borgcharger0" - density = 1 - anchored = 1.0 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 1000 - var/mob/occupant = null - var/list/acceptable_upgradeables = list(/obj/item/weapon/cell) // battery for now - var/list/upgrade_holder = list() - var/upgrading = 0 // are we upgrading a nigga? - var/upgrade_finished = -1 // time the upgrade should finish - var/manipulator_coeff = 1 // better manipulator swaps parts faster - var/transfer_rate_coeff = 1 // transfer rate bonuses - var/capacitor_stored = 0 //power stored in capacitors, to be instantly transferred to robots when they enter the charger - var/capacitor_max = 0 //combined max power the capacitors can hold - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL - -/obj/machinery/recharge_station/New() - . = ..() - build_icon() - - component_parts = newlist( - /obj/item/weapon/circuitboard/recharge_station, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/matter_bin - ) - - RefreshParts() - -/obj/machinery/recharge_station/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - T += M.rating-1 - manipulator_coeff = initial(manipulator_coeff)+(T) - T = 0 - for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) - T += C.rating-1 - transfer_rate_coeff = initial(transfer_rate_coeff)+(T * 0.2) - capacitor_max = initial(capacitor_max)+(T * 750) - active_power_usage = 1000 * transfer_rate_coeff - -/obj/machinery/recharge_station/Destroy() - src.go_out() - ..() - - -/obj/machinery/recharge_station/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - new /obj/item/weapon/circuitboard/recharge_station(src.loc) - qdel(src) - return - if(3.0) - if (prob(25)) - src.anchored = 0 - src.build_icon() - else - return - -/obj/machinery/recharge_station/process() - process_upgrade() - if(stat & (NOPOWER|BROKEN) || !anchored) - return - - if(src.occupant) - process_occupant() - else - process_capacitors() - return 1 - -/obj/machinery/recharge_station/proc/process_upgrade() - if(!upgrading) - return - if(!occupant || !isrobot(occupant)) // Something happened so stop the upgrade. - upgrading = 0 - upgrade_finished = -1 - return - if(stat & (NOPOWER|BROKEN) || !anchored) - to_chat(occupant, "Upgrade interrupted due to power failure, movement lock is released.") - upgrading = 0 - upgrade_finished = -1 - return - if(world.timeofday >= upgrade_finished && upgrade_finished != -1) - if(istype(upgrading, /obj/item/weapon/cell)) - if(occupant:cell) - occupant:cell.loc = get_turf(src) - upgrade_holder -= upgrading - upgrading:loc = occupant - occupant:cell = upgrading - occupant:cell:charge = occupant:cell.maxcharge // its been in a recharger so it makes sense - upgrading = 0 - upgrade_finished = -1 - to_chat(occupant, "Upgrade completed.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) - -/obj/machinery/recharge_station/attackby(var/obj/item/W, var/mob/living/user) - if(is_type_in_list(W, acceptable_upgradeables)) - if(!(locate(W.type) in upgrade_holder)) - if(user.drop_item(W, src)) - upgrade_holder.Add(W) - to_chat(user, "You add \the [W] to \the [src].") - return - else - to_chat(user, "\The [src] already contains something resembling a [W.name].") - return - else - ..() - return - return - -/obj/machinery/recharge_station/attack_ghost(var/mob/user) //why would they - return 0 - -/obj/machinery/recharge_station/attack_ai(var/mob/user) - attack_hand(user) - -/obj/machinery/recharge_station/attack_hand(var/mob/user) - if(user == occupant) - if(upgrading) - to_chat(user, "You interrupt the upgrade process.") - upgrading = 0 - upgrade_finished = -1 - return 0 - else if(upgrade_holder.len) - upgrading = input(user, "Choose an item to swap out.","Upgradeables") as null|anything in upgrade_holder - if(!upgrading) - upgrading = 0 - return - if(alert(user, "You have chosen [upgrading], is this correct?", , "Yes", "No") == "Yes") - upgrade_finished = world.timeofday + (600/manipulator_coeff) - to_chat(user, "The upgrade should complete in approximately [60/manipulator_coeff] seconds, you will be unable to exit \the [src] during this unless you cancel the process.") - spawn() do_after(user,src,600/manipulator_coeff,needhand = FALSE) - return - else - upgrading = 0 - to_chat(user, "You decide not to apply the upgrade") - return - else if(Adjacent(user)) - if(upgrade_holder.len) - var/obj/removed = input(user, "Choose an item to remove.",upgrade_holder[1]) as null|anything in upgrade_holder - if(!removed) - return - user.put_in_hands(removed) - if(removed.loc == src) - removed.loc = get_turf(src) - upgrade_holder -= removed - -/obj/machinery/recharge_station/allow_drop() - return 0 - - -/obj/machinery/recharge_station/relaymove(mob/user as mob) - if(user.stat) - return - src.go_out() - return - -/obj/machinery/recharge_station/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - if(occupant) - occupant.emp_act(severity) - go_out() - ..(severity) - - - -/obj/machinery/recharge_station/proc/build_icon() - if(stat & (NOPOWER|BROKEN) || !anchored) - icon_state = "borgcharger" - else - if(src.occupant) - icon_state = "borgcharger1" - else - icon_state = "borgcharger0" - -/obj/machinery/recharge_station/proc/process_occupant() - if(src.occupant) - if (istype(occupant, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = occupant - if((R.stat) || (!R.client))//no more borgs suiciding in recharge stations to ruin them. - go_out() - return - restock_modules() - if(!R.cell) - return - else if(R.cell.charge >= R.cell.maxcharge) - R.cell.charge = R.cell.maxcharge - return - else - if (capacitor_stored) - var/juicetofill = R.cell.maxcharge-R.cell.charge - if(capacitor_stored > juicetofill) - capacitor_stored -= juicetofill - R.cell.charge = R.cell.maxcharge - else - R.cell.charge = R.cell.charge + capacitor_stored - capacitor_stored = 0 - R.cell.charge = min(R.cell.charge + 200 * transfer_rate_coeff + (isMoMMI(occupant) ? 100 * transfer_rate_coeff : 0), R.cell.maxcharge) - return - -/obj/machinery/recharge_station/proc/process_capacitors() - if (capacitor_stored >= capacitor_max) - if (idle_power_usage != initial(idle_power_usage)) //probably better to not re-assign the variable each process()? - idle_power_usage = initial(idle_power_usage) - return 0 - idle_power_usage = initial(idle_power_usage) + (100 * transfer_rate_coeff) - capacitor_stored = min(capacitor_stored + (20 * transfer_rate_coeff), capacitor_max) - return 1 - -/obj/machinery/recharge_station/proc/go_out() - if(!( src.occupant )) - return - if(upgrading) - to_chat(occupant, "The upgrade hasn't completed yet, interface with \the [src] again to halt the process.") - return - //for(var/obj/O in src) - // O.loc = src.loc - if (src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.loc = src.loc - src.occupant = null - build_icon() - src.use_power = 1 - // Removes dropped items/magically appearing mobs from the charger too - for (var/atom/movable/x in src.contents) - if(!(x in upgrade_holder | component_parts)) - x.forceMove(src.loc) - return - -/obj/machinery/recharge_station/proc/restock_modules() - if(src.occupant) - if(istype(occupant, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = occupant - if(R.module && R.module.modules) - var/list/um = R.contents|R.module.modules - // ^ makes single list of active (R.contents) and inactive modules (R.module.modules) - for(var/obj/O in um) - // Stacks - if(istype(O,/obj/item/stack)) - var/obj/item/stack/S=O - if(!istype(S,/obj/item/stack/cable_coil) && !istype(S,/obj/item/stack/medical)) - continue //Only recharge cable coils and medical stacks - - if(S.amount < S.max_amount) - S.amount += 2 - if(S.amount > S.max_amount) - S.amount = S.max_amount - // Security - if(istype(O,/obj/item/device/flash)) - var/obj/item/device/flash/F=O - if(F.broken) - F.broken = 0 - F.times_used = 0 - F.icon_state = "flash" - if(istype(O,/obj/item/weapon/gun/energy/taser/cyborg)) - var/obj/item/weapon/gun/energy/taser/cyborg/C=O - if(C.power_supply.charge < C.power_supply.maxcharge) - C.power_supply.give(C.charge_cost) - C.update_icon() - else - C.charge_tick = 0 - if(istype(O,/obj/item/weapon/melee/baton)) - var/obj/item/weapon/melee/baton/B = O - if(B.bcell) - B.bcell.charge = B.bcell.maxcharge - //Combat - if(istype(O,/obj/item/weapon/gun/energy/laser/cyborg)) - var/obj/item/weapon/gun/energy/laser/cyborg/C=O - if(C.power_supply.charge < C.power_supply.maxcharge) - C.power_supply.give(C.charge_cost) - C.update_icon() - else - C.charge_tick = 0 - if(istype(O,/obj/item/weapon/gun/energy/lasercannon/cyborg)) - var/obj/item/weapon/gun/energy/lasercannon/cyborg/C=O - if(C.power_supply.charge < C.power_supply.maxcharge) - C.power_supply.give(C.charge_cost) - C.update_icon() - //Mining - if(istype(O,/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg)) - var/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/C=O - if(C.power_supply.charge < C.power_supply.maxcharge) - C.power_supply.give(C.charge_cost) - C.update_icon() - else - O:charge_tick = 0 - //Service - if(istype(O,/obj/item/weapon/reagent_containers/food/condiment/enzyme)) - if(O.reagents.get_reagent_amount("enzyme") < 50) - O.reagents.add_reagent("enzyme", 2) - //Medical & Standard - if(istype(O,/obj/item/weapon/reagent_containers/glass/bottle/robot)) - var/obj/item/weapon/reagent_containers/glass/bottle/robot/B = O - if(B.reagent && (B.reagents.get_reagent_amount(B.reagent) < B.volume)) - B.reagents.add_reagent(B.reagent, 2) - if(istype(O,/obj/item/weapon/melee/defibrillator)) - var/obj/item/weapon/melee/defibrillator/D = O - D.charges = initial(D.charges) - //Janitor - if(istype(O, /obj/item/device/lightreplacer/borg)) - var/obj/item/device/lightreplacer/borg/LR = O - LR.Charge(R) - if(R) - if(R.module) - R.module.respawn_consumable(R) - - //Emagged items for janitor and medical borg - if(R.module.emag) - if(istype(R.module.emag, /obj/item/weapon/reagent_containers/spray)) - var/obj/item/weapon/reagent_containers/spray/S = R.module.emag - if(S.name == "Polyacid spray") - S.reagents.add_reagent("pacid", 2) - else if(S.name == "Lube spray") - S.reagents.add_reagent("lube", 2) - - - -/obj/machinery/recharge_station/verb/move_eject() - set category = "Object" - set src in oview(1) - if (usr.stat != 0) - return - src.go_out() - add_fingerprint(usr) - return - -/obj/machinery/recharge_station/verb/move_inside() - set category = "Object" - set src in oview(1) - - mob_enter(usr) - return - -/obj/machinery/recharge_station/proc/mob_enter(mob/living/silicon/robot/R) - if(stat & (NOPOWER|BROKEN) || !anchored) - return - if (R.stat == 2) - //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO - return - if (!(istype(R, /mob/living/silicon/))) - to_chat(R, "Only non-organics may enter the recharger!") - return - if (src.occupant) - to_chat(R, "The cell is already occupied!") - return - R.stop_pulling() - if(R && R.client) - R.client.perspective = EYE_PERSPECTIVE - R.client.eye = src - R.loc = src - src.occupant = R - src.add_fingerprint(R) - build_icon() - src.use_power = 2 - for(var/obj/O in upgrade_holder) - if(istype(O, /obj/item/weapon/cell)) - if(!R.cell) - to_chat(usr, "Power Cell replacement available.") - else - if(O:maxcharge > R.cell.maxcharge) - to_chat(usr, "Power Cell upgrade available.") - -/obj/machinery/recharge_station/togglePanelOpen(var/obj/toggleitem, mob/user) - if(occupant) - to_chat(user, "You can't do that while this charger is occupied.") - return -1 - return ..() - -/obj/machinery/recharge_station/crowbarDestroy(mob/user) - if(occupant) - to_chat(user, "You can't do that while this charger is occupied.") - return -1 - return ..() - - - -/obj/machinery/recharge_station/Bumped(atom/AM as mob|obj) - if(!issilicon(AM) || isAI(AM)) - return - var/mob/living/silicon/robot/R = AM - mob_enter(R) +/obj/machinery/recharge_station + name = "cyborg recharging station" + icon = 'icons/obj/objects.dmi' + icon_state = "borgcharger0" + density = 1 + anchored = 1.0 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 1000 + var/mob/occupant = null + var/list/acceptable_upgradeables = list(/obj/item/weapon/cell) // battery for now + var/list/upgrade_holder = list() + var/upgrading = 0 // are we upgrading a nigga? + var/upgrade_finished = -1 // time the upgrade should finish + var/manipulator_coeff = 1 // better manipulator swaps parts faster + var/transfer_rate_coeff = 1 // transfer rate bonuses + var/capacitor_stored = 0 //power stored in capacitors, to be instantly transferred to robots when they enter the charger + var/capacitor_max = 0 //combined max power the capacitors can hold + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL + +/obj/machinery/recharge_station/New() + . = ..() + build_icon() + + component_parts = newlist( + /obj/item/weapon/circuitboard/recharge_station, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/matter_bin + ) + + RefreshParts() + +/obj/machinery/recharge_station/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + T += M.rating-1 + manipulator_coeff = initial(manipulator_coeff)+(T) + T = 0 + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) + T += C.rating-1 + transfer_rate_coeff = initial(transfer_rate_coeff)+(T * 0.2) + capacitor_max = initial(capacitor_max)+(T * 750) + active_power_usage = 1000 * transfer_rate_coeff + +/obj/machinery/recharge_station/Destroy() + src.go_out() + ..() + + +/obj/machinery/recharge_station/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + new /obj/item/weapon/circuitboard/recharge_station(src.loc) + qdel(src) + return + if(3.0) + if (prob(25)) + src.anchored = 0 + src.build_icon() + else + return + +/obj/machinery/recharge_station/process() + process_upgrade() + if(stat & (NOPOWER|BROKEN) || !anchored) + return + + if(src.occupant) + process_occupant() + else + process_capacitors() + return 1 + +/obj/machinery/recharge_station/proc/process_upgrade() + if(!upgrading) + return + if(!occupant || !isrobot(occupant)) // Something happened so stop the upgrade. + upgrading = 0 + upgrade_finished = -1 + return + if(stat & (NOPOWER|BROKEN) || !anchored) + to_chat(occupant, "Upgrade interrupted due to power failure, movement lock is released.") + upgrading = 0 + upgrade_finished = -1 + return + if(world.timeofday >= upgrade_finished && upgrade_finished != -1) + if(istype(upgrading, /obj/item/weapon/cell)) + if(occupant:cell) + occupant:cell.loc = get_turf(src) + upgrade_holder -= upgrading + upgrading:loc = occupant + occupant:cell = upgrading + occupant:cell:charge = occupant:cell.maxcharge // its been in a recharger so it makes sense + upgrading = 0 + upgrade_finished = -1 + to_chat(occupant, "Upgrade completed.") + playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + +/obj/machinery/recharge_station/attackby(var/obj/item/W, var/mob/living/user) + if(is_type_in_list(W, acceptable_upgradeables)) + if(!(locate(W.type) in upgrade_holder)) + if(user.drop_item(W, src)) + upgrade_holder.Add(W) + to_chat(user, "You add \the [W] to \the [src].") + return + else + to_chat(user, "\The [src] already contains something resembling a [W.name].") + return + else + ..() + return + return + +/obj/machinery/recharge_station/attack_ghost(var/mob/user) //why would they + return 0 + +/obj/machinery/recharge_station/attack_ai(var/mob/user) + attack_hand(user) + +/obj/machinery/recharge_station/attack_hand(var/mob/user) + if(user == occupant) + if(upgrading) + to_chat(user, "You interrupt the upgrade process.") + upgrading = 0 + upgrade_finished = -1 + return 0 + else if(upgrade_holder.len) + upgrading = input(user, "Choose an item to swap out.","Upgradeables") as null|anything in upgrade_holder + if(!upgrading) + upgrading = 0 + return + if(alert(user, "You have chosen [upgrading], is this correct?", , "Yes", "No") == "Yes") + upgrade_finished = world.timeofday + (600/manipulator_coeff) + to_chat(user, "The upgrade should complete in approximately [60/manipulator_coeff] seconds, you will be unable to exit \the [src] during this unless you cancel the process.") + spawn() do_after(user,src,600/manipulator_coeff,needhand = FALSE) + return + else + upgrading = 0 + to_chat(user, "You decide not to apply the upgrade") + return + else if(Adjacent(user)) + if(upgrade_holder.len) + var/obj/removed = input(user, "Choose an item to remove.",upgrade_holder[1]) as null|anything in upgrade_holder + if(!removed) + return + user.put_in_hands(removed) + if(removed.loc == src) + removed.loc = get_turf(src) + upgrade_holder -= removed + +/obj/machinery/recharge_station/allow_drop() + return 0 + + +/obj/machinery/recharge_station/relaymove(mob/user as mob) + if(user.stat) + return + src.go_out() + return + +/obj/machinery/recharge_station/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + if(occupant) + occupant.emp_act(severity) + go_out() + ..(severity) + + + +/obj/machinery/recharge_station/proc/build_icon() + if(stat & (NOPOWER|BROKEN) || !anchored) + icon_state = "borgcharger" + else + if(src.occupant) + icon_state = "borgcharger1" + else + icon_state = "borgcharger0" + +/obj/machinery/recharge_station/proc/process_occupant() + if(src.occupant) + if (istype(occupant, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = occupant + if((R.stat) || (!R.client))//no more borgs suiciding in recharge stations to ruin them. + go_out() + return + restock_modules() + if(!R.cell) + return + else if(R.cell.charge >= R.cell.maxcharge) + R.cell.charge = R.cell.maxcharge + return + else + if (capacitor_stored) + var/juicetofill = R.cell.maxcharge-R.cell.charge + if(capacitor_stored > juicetofill) + capacitor_stored -= juicetofill + R.cell.charge = R.cell.maxcharge + else + R.cell.charge = R.cell.charge + capacitor_stored + capacitor_stored = 0 + R.cell.charge = min(R.cell.charge + 200 * transfer_rate_coeff + (isMoMMI(occupant) ? 100 * transfer_rate_coeff : 0), R.cell.maxcharge) + return + +/obj/machinery/recharge_station/proc/process_capacitors() + if (capacitor_stored >= capacitor_max) + if (idle_power_usage != initial(idle_power_usage)) //probably better to not re-assign the variable each process()? + idle_power_usage = initial(idle_power_usage) + return 0 + idle_power_usage = initial(idle_power_usage) + (100 * transfer_rate_coeff) + capacitor_stored = min(capacitor_stored + (20 * transfer_rate_coeff), capacitor_max) + return 1 + +/obj/machinery/recharge_station/proc/go_out() + if(!( src.occupant )) + return + if(upgrading) + to_chat(occupant, "The upgrade hasn't completed yet, interface with \the [src] again to halt the process.") + return + //for(var/obj/O in src) + // O.loc = src.loc + if (src.occupant.client) + src.occupant.client.eye = src.occupant.client.mob + src.occupant.client.perspective = MOB_PERSPECTIVE + src.occupant.loc = src.loc + src.occupant = null + build_icon() + src.use_power = 1 + // Removes dropped items/magically appearing mobs from the charger too + for (var/atom/movable/x in src.contents) + if(!(x in upgrade_holder | component_parts)) + x.forceMove(src.loc) + return + +/obj/machinery/recharge_station/proc/restock_modules() + if(src.occupant) + if(istype(occupant, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = occupant + if(R.module && R.module.modules) + var/list/um = R.contents|R.module.modules + // ^ makes single list of active (R.contents) and inactive modules (R.module.modules) + for(var/obj/O in um) + // Stacks + if(istype(O,/obj/item/stack)) + var/obj/item/stack/S=O + if(!istype(S,/obj/item/stack/cable_coil) && !istype(S,/obj/item/stack/medical)) + continue //Only recharge cable coils and medical stacks + + if(S.amount < S.max_amount) + S.amount += 2 + if(S.amount > S.max_amount) + S.amount = S.max_amount + // Security + if(istype(O,/obj/item/device/flash)) + var/obj/item/device/flash/F=O + if(F.broken) + F.broken = 0 + F.times_used = 0 + F.icon_state = "flash" + if(istype(O,/obj/item/weapon/gun/energy/taser/cyborg)) + var/obj/item/weapon/gun/energy/taser/cyborg/C=O + if(C.power_supply.charge < C.power_supply.maxcharge) + C.power_supply.give(C.charge_cost) + C.update_icon() + else + C.charge_tick = 0 + if(istype(O,/obj/item/weapon/melee/baton)) + var/obj/item/weapon/melee/baton/B = O + if(B.bcell) + B.bcell.charge = B.bcell.maxcharge + //Combat + if(istype(O,/obj/item/weapon/gun/energy/laser/cyborg)) + var/obj/item/weapon/gun/energy/laser/cyborg/C=O + if(C.power_supply.charge < C.power_supply.maxcharge) + C.power_supply.give(C.charge_cost) + C.update_icon() + else + C.charge_tick = 0 + if(istype(O,/obj/item/weapon/gun/energy/lasercannon/cyborg)) + var/obj/item/weapon/gun/energy/lasercannon/cyborg/C=O + if(C.power_supply.charge < C.power_supply.maxcharge) + C.power_supply.give(C.charge_cost) + C.update_icon() + //Mining + if(istype(O,/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg)) + var/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/C=O + if(C.power_supply.charge < C.power_supply.maxcharge) + C.power_supply.give(C.charge_cost) + C.update_icon() + else + O:charge_tick = 0 + //Service + if(istype(O,/obj/item/weapon/reagent_containers/food/condiment/enzyme)) + if(O.reagents.get_reagent_amount("enzyme") < 50) + O.reagents.add_reagent("enzyme", 2) + //Medical & Standard + if(istype(O,/obj/item/weapon/reagent_containers/glass/bottle/robot)) + var/obj/item/weapon/reagent_containers/glass/bottle/robot/B = O + if(B.reagent && (B.reagents.get_reagent_amount(B.reagent) < B.volume)) + B.reagents.add_reagent(B.reagent, 2) + if(istype(O,/obj/item/weapon/melee/defibrillator)) + var/obj/item/weapon/melee/defibrillator/D = O + D.charges = initial(D.charges) + //Janitor + if(istype(O, /obj/item/device/lightreplacer/borg)) + var/obj/item/device/lightreplacer/borg/LR = O + LR.Charge(R) + if(R) + if(R.module) + R.module.respawn_consumable(R) + + //Emagged items for janitor and medical borg + if(R.module.emag) + if(istype(R.module.emag, /obj/item/weapon/reagent_containers/spray)) + var/obj/item/weapon/reagent_containers/spray/S = R.module.emag + if(S.name == "Polyacid spray") + S.reagents.add_reagent("pacid", 2) + else if(S.name == "Lube spray") + S.reagents.add_reagent("lube", 2) + + + +/obj/machinery/recharge_station/verb/move_eject() + set category = "Object" + set src in oview(1) + if (usr.stat != 0) + return + src.go_out() + add_fingerprint(usr) + return + +/obj/machinery/recharge_station/verb/move_inside() + set category = "Object" + set src in oview(1) + + mob_enter(usr) + return + +/obj/machinery/recharge_station/proc/mob_enter(mob/living/silicon/robot/R) + if(stat & (NOPOWER|BROKEN) || !anchored) + return + if (R.stat == 2) + //Whoever had it so that a borg with a dead cell can't enter this thing should be shot. --NEO + return + if (!(istype(R, /mob/living/silicon/))) + to_chat(R, "Only non-organics may enter the recharger!") + return + if (src.occupant) + to_chat(R, "The cell is already occupied!") + return + R.stop_pulling() + if(R && R.client) + R.client.perspective = EYE_PERSPECTIVE + R.client.eye = src + R.loc = src + src.occupant = R + src.add_fingerprint(R) + build_icon() + src.use_power = 2 + for(var/obj/O in upgrade_holder) + if(istype(O, /obj/item/weapon/cell)) + if(!R.cell) + to_chat(usr, "Power Cell replacement available.") + else + if(O:maxcharge > R.cell.maxcharge) + to_chat(usr, "Power Cell upgrade available.") + +/obj/machinery/recharge_station/togglePanelOpen(var/obj/toggleitem, mob/user) + if(occupant) + to_chat(user, "You can't do that while this charger is occupied.") + return -1 + return ..() + +/obj/machinery/recharge_station/crowbarDestroy(mob/user) + if(occupant) + to_chat(user, "You can't do that while this charger is occupied.") + return -1 + return ..() + + + +/obj/machinery/recharge_station/Bumped(atom/AM as mob|obj) + if(!issilicon(AM) || isAI(AM)) + return + var/mob/living/silicon/robot/R = AM + mob_enter(R) return \ No newline at end of file diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index aba5d2e1c1c..a0c1c4c28b5 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -1,455 +1,455 @@ -/******************** Requests Console ********************/ - -var/req_console_assistance = list() -var/req_console_supplies = list() -var/req_console_information = list() -var/list/obj/machinery/requests_console/allConsoles = list() - -/obj/machinery/requests_console - name = "requests console" - desc = "A console intended to send requests to diferent departments on the station." - anchored = 1 - icon = 'icons/obj/terminals.dmi' - icon_state = "req_comp0" - var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department - var/list/messages = list() //List of all messages - var/departmentType = 0 - // 0 = none (not listed, can only repeplied to) - // 1 = assistance - // 2 = supplies - // 3 = info - // 4 = ass + sup //Erro goddamn you just HAD to shorten "assistance" down to "ass" - // 5 = ass + info - // 6 = sup + info - // 7 = ass + sup + info - var/newmessagepriority = 0 - // 0 = no new message - // 1 = normal priority - // 2 = high priority - // 3 = extreme priority - not implemented, will probably require some hacking... everything needs to have a hidden feature in this game. - var/screen = 0 - // 0 = main menu, - // 1 = req. assistance, - // 2 = req. supplies - // 3 = relay information - // 4 = write msg - not used - // 5 = configure panel - // 6 = sent successfully - // 7 = sent unsuccessfully - // 8 = view messages - // 9 = authentication before sending - // 10 = send announcement - var/silent = 0 // set to 1 for it not to beep all the time - var/hackState = 0 - // 0 = not hacked - // 1 = hacked - var/announcementConsole = 0 - // 0 = This console cannot be used to send department announcements - // 1 = This console can send department announcementsf - var/open = 0 // 1 if open - var/announceAuth = 0 //Will be set to 1 when you authenticate yourself for announcements - var/msgVerified = "" //Will contain the name of the person who varified it - var/msgStamped = "" //If a message is stamped, this will contain the stamp name - var/message = ""; - var/dpt = ""; //the department which will be receiving the message - var/priority = -1 ; //Priority of the message being sent - luminosity = 0 - -/obj/machinery/requests_console/power_change() - ..() - update_icon() - -/obj/machinery/requests_console/update_icon() - if(stat & NOPOWER) - if(icon_state != "req_comp_off") - icon_state = "req_comp_off" - else - if(icon_state == "req_comp_off") - icon_state = "req_comp0" - -/obj/machinery/requests_console/New() - allConsoles.Add(src) - set_department(department,departmentType) - return ..() - -/obj/machinery/requests_console/proc/set_department(var/name, var/D) - department = name - departmentType = D - name = "[department] Requests Console" - if("[department]" in req_console_assistance) - req_console_assistance -= department - if("[department]" in req_console_supplies) - req_console_supplies -= department - if("[department]" in req_console_information) - req_console_information -= department - switch(departmentType) - if(1) - if(!("[department]" in req_console_assistance)) - req_console_assistance += department - if(2) - if(!("[department]" in req_console_supplies)) - req_console_supplies += department - if(3) - if(!("[department]" in req_console_information)) - req_console_information += department - if(4) - if(!("[department]" in req_console_assistance)) - req_console_assistance += department - if(!("[department]" in req_console_supplies)) - req_console_supplies += department - if(5) - if(!("[department]" in req_console_assistance)) - req_console_assistance += department - if(!("[department]" in req_console_information)) - req_console_information += department - if(6) - if(!("[department]" in req_console_supplies)) - req_console_supplies += department - if(!("[department]" in req_console_information)) - req_console_information += department - if(7) - if(!("[department]" in req_console_assistance)) - req_console_assistance += department - if(!("[department]" in req_console_supplies)) - req_console_supplies += department - if(!("[department]" in req_console_information)) - req_console_information += department - -/obj/machinery/requests_console/attack_hand(user as mob) - if(..(user)) - return - var/dat - dat = text("Requests Console

                      [department] Requests Console

                      ") - if(!open) - switch(screen) - if(1) //req. assistance - dat += text("Which department do you need assistance from?

                      ") - for(var/dpt in req_console_assistance) - if (dpt != department) - dat += text("[dpt] (Message or ") - dat += text("High Priority") -// if (hackState == 1) -// dat += text(" or EXTREME)") - dat += text(")
                      ") - dat += text("
                      Back
                      ") - - if(2) //req. supplies - dat += text("Which department do you need supplies from?

                      ") - for(var/dpt in req_console_supplies) - if (dpt != department) - dat += text("[dpt] (Message or ") - dat += text("High Priority") -// if (hackState == 1) -// dat += text(" or EXTREME)") - dat += text(")
                      ") - dat += text("
                      Back
                      ") - - if(3) //relay information - dat += text("Which department would you like to send information to?

                      ") - for(var/dpt in req_console_information) - if (dpt != department) - dat += text("[dpt] (Message or ") - dat += text("High Priority") -// if (hackState == 1) -// dat += text(" or EXTREME)") - dat += text(")
                      ") - dat += text("
                      Back
                      ") - if(5) //configure panel - dat += text("Configure Panel

                      ") - if(announceAuth) - dat += text("Authentication accepted

                      ") - else - dat += text("Swipe your card to authenticate yourself.

                      ") - if (announceAuth) - dat += text("Configure department. Set to 0 to release internal locks for deconstruction.

                      ") - dat += text("No Contact
                      ") - dat += text("Assistance
                      ") - dat += text("Supply
                      ") - dat += text("Anonymous Tip Recipient
                      ") - dat += text("Assistance + Supply
                      ") - dat += text("Assistance + Tips
                      ") - dat += text("Supply + Tips
                      ") - dat += text("All
                      ") - dat += text("
                      Back
                      ") - if(6) //sent successfully - dat += text("Message sent

                      ") - dat += text("Continue
                      ") - - if(7) //unsuccessful; not sent - dat += text("An error occurred.

                      ") - dat += text("Continue
                      ") - - if(8) //view messages - for (var/obj/machinery/requests_console/Console in allConsoles) - if (Console.department == department) - Console.newmessagepriority = 0 - Console.icon_state = "req_comp0" - Console.set_light(1) - newmessagepriority = 0 - icon_state = "req_comp0" - for(var/msg in messages) - dat += text("[msg]
                      ") - dat += text("Back to main menu
                      ") - - if(9) //authentication before sending - dat += text("Message Authentication

                      ") - dat += text("Message for [dpt]: [message]

                      ") - dat += text("You may authenticate your message now by scanning your ID or your stamp

                      ") - dat += text("Validated by: [msgVerified]
                      "); - dat += text("Stamped by: [msgStamped]
                      "); - dat += text("Send
                      "); - dat += text("
                      Back
                      ") - - if(10) //send announcement - dat += text("Station wide announcement

                      ") - if(announceAuth) - dat += text("Authentication accepted

                      ") - else - dat += text("Swipe your card to authenticate yourself.

                      ") - dat += text("Message: [message] Write

                      ") - if (announceAuth && message) - dat += text("Announce
                      "); - dat += text("
                      Back
                      ") - - else //main menu - screen = 0 - announceAuth = 0 - if (newmessagepriority == 1) - dat += text("There are new messages
                      ") - if (newmessagepriority == 2) - dat += text("NEW PRIORITY MESSAGES
                      ") - dat += text("View Messages

                      ") - - dat += text("Request Assistance
                      ") - dat += text("Request Supplies
                      ") - dat += text("Relay Anonymous Information

                      ") - dat += text("Configure Panel

                      ") - if(announcementConsole) - dat += text("Send station-wide announcement

                      ") - if (silent) - dat += text("Speaker OFF") - else - dat += text("Speaker ON") - - user << browse("[dat]", "window=request_console") - onclose(user, "req_console") - return - -/obj/machinery/requests_console/Topic(href, href_list) - if(..()) return - usr.set_machine(src) - add_fingerprint(usr) - - if(reject_bad_text(href_list["write"])) - dpt = ckey(href_list["write"]) //write contains the string of the receiving department's name - - var/new_message = copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) - if(new_message) - message = new_message - screen = 9 - switch(href_list["priority"]) - if("2") priority = 2 - else priority = -1 - else - dpt = ""; - msgVerified = "" - msgStamped = "" - screen = 0 - priority = -1 - - if(href_list["writeAnnouncement"]) - var/new_message = copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) - if(new_message) - message = new_message - switch(href_list["priority"]) - if("2") priority = 2 - else priority = -1 - else - message = "" - announceAuth = 0 - screen = 0 - - if(href_list["sendAnnouncement"]) - if(!announcementConsole) return - for(var/mob/M in player_list) - if(!istype(M,/mob/new_player) && M.client) +/******************** Requests Console ********************/ + +var/req_console_assistance = list() +var/req_console_supplies = list() +var/req_console_information = list() +var/list/obj/machinery/requests_console/allConsoles = list() + +/obj/machinery/requests_console + name = "requests console" + desc = "A console intended to send requests to diferent departments on the station." + anchored = 1 + icon = 'icons/obj/terminals.dmi' + icon_state = "req_comp0" + var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department + var/list/messages = list() //List of all messages + var/departmentType = 0 + // 0 = none (not listed, can only repeplied to) + // 1 = assistance + // 2 = supplies + // 3 = info + // 4 = ass + sup //Erro goddamn you just HAD to shorten "assistance" down to "ass" + // 5 = ass + info + // 6 = sup + info + // 7 = ass + sup + info + var/newmessagepriority = 0 + // 0 = no new message + // 1 = normal priority + // 2 = high priority + // 3 = extreme priority - not implemented, will probably require some hacking... everything needs to have a hidden feature in this game. + var/screen = 0 + // 0 = main menu, + // 1 = req. assistance, + // 2 = req. supplies + // 3 = relay information + // 4 = write msg - not used + // 5 = configure panel + // 6 = sent successfully + // 7 = sent unsuccessfully + // 8 = view messages + // 9 = authentication before sending + // 10 = send announcement + var/silent = 0 // set to 1 for it not to beep all the time + var/hackState = 0 + // 0 = not hacked + // 1 = hacked + var/announcementConsole = 0 + // 0 = This console cannot be used to send department announcements + // 1 = This console can send department announcementsf + var/open = 0 // 1 if open + var/announceAuth = 0 //Will be set to 1 when you authenticate yourself for announcements + var/msgVerified = "" //Will contain the name of the person who varified it + var/msgStamped = "" //If a message is stamped, this will contain the stamp name + var/message = ""; + var/dpt = ""; //the department which will be receiving the message + var/priority = -1 ; //Priority of the message being sent + luminosity = 0 + +/obj/machinery/requests_console/power_change() + ..() + update_icon() + +/obj/machinery/requests_console/update_icon() + if(stat & NOPOWER) + if(icon_state != "req_comp_off") + icon_state = "req_comp_off" + else + if(icon_state == "req_comp_off") + icon_state = "req_comp0" + +/obj/machinery/requests_console/New() + allConsoles.Add(src) + set_department(department,departmentType) + return ..() + +/obj/machinery/requests_console/proc/set_department(var/name, var/D) + department = name + departmentType = D + name = "[department] Requests Console" + if("[department]" in req_console_assistance) + req_console_assistance -= department + if("[department]" in req_console_supplies) + req_console_supplies -= department + if("[department]" in req_console_information) + req_console_information -= department + switch(departmentType) + if(1) + if(!("[department]" in req_console_assistance)) + req_console_assistance += department + if(2) + if(!("[department]" in req_console_supplies)) + req_console_supplies += department + if(3) + if(!("[department]" in req_console_information)) + req_console_information += department + if(4) + if(!("[department]" in req_console_assistance)) + req_console_assistance += department + if(!("[department]" in req_console_supplies)) + req_console_supplies += department + if(5) + if(!("[department]" in req_console_assistance)) + req_console_assistance += department + if(!("[department]" in req_console_information)) + req_console_information += department + if(6) + if(!("[department]" in req_console_supplies)) + req_console_supplies += department + if(!("[department]" in req_console_information)) + req_console_information += department + if(7) + if(!("[department]" in req_console_assistance)) + req_console_assistance += department + if(!("[department]" in req_console_supplies)) + req_console_supplies += department + if(!("[department]" in req_console_information)) + req_console_information += department + +/obj/machinery/requests_console/attack_hand(user as mob) + if(..(user)) + return + var/dat + dat = text("Requests Console

                      [department] Requests Console

                      ") + if(!open) + switch(screen) + if(1) //req. assistance + dat += text("Which department do you need assistance from?

                      ") + for(var/dpt in req_console_assistance) + if (dpt != department) + dat += text("[dpt] (Message or ") + dat += text("High Priority") +// if (hackState == 1) +// dat += text(" or EXTREME)") + dat += text(")
                      ") + dat += text("
                      Back
                      ") + + if(2) //req. supplies + dat += text("Which department do you need supplies from?

                      ") + for(var/dpt in req_console_supplies) + if (dpt != department) + dat += text("[dpt] (Message or ") + dat += text("High Priority") +// if (hackState == 1) +// dat += text(" or EXTREME)") + dat += text(")
                      ") + dat += text("
                      Back
                      ") + + if(3) //relay information + dat += text("Which department would you like to send information to?

                      ") + for(var/dpt in req_console_information) + if (dpt != department) + dat += text("[dpt] (Message or ") + dat += text("High Priority") +// if (hackState == 1) +// dat += text(" or EXTREME)") + dat += text(")
                      ") + dat += text("
                      Back
                      ") + if(5) //configure panel + dat += text("Configure Panel

                      ") + if(announceAuth) + dat += text("Authentication accepted

                      ") + else + dat += text("Swipe your card to authenticate yourself.

                      ") + if (announceAuth) + dat += text("Configure department. Set to 0 to release internal locks for deconstruction.

                      ") + dat += text("No Contact
                      ") + dat += text("Assistance
                      ") + dat += text("Supply
                      ") + dat += text("Anonymous Tip Recipient
                      ") + dat += text("Assistance + Supply
                      ") + dat += text("Assistance + Tips
                      ") + dat += text("Supply + Tips
                      ") + dat += text("All
                      ") + dat += text("
                      Back
                      ") + if(6) //sent successfully + dat += text("Message sent

                      ") + dat += text("Continue
                      ") + + if(7) //unsuccessful; not sent + dat += text("An error occurred.

                      ") + dat += text("Continue
                      ") + + if(8) //view messages + for (var/obj/machinery/requests_console/Console in allConsoles) + if (Console.department == department) + Console.newmessagepriority = 0 + Console.icon_state = "req_comp0" + Console.set_light(1) + newmessagepriority = 0 + icon_state = "req_comp0" + for(var/msg in messages) + dat += text("[msg]
                      ") + dat += text("Back to main menu
                      ") + + if(9) //authentication before sending + dat += text("Message Authentication

                      ") + dat += text("Message for [dpt]: [message]

                      ") + dat += text("You may authenticate your message now by scanning your ID or your stamp

                      ") + dat += text("Validated by: [msgVerified]
                      "); + dat += text("Stamped by: [msgStamped]
                      "); + dat += text("Send
                      "); + dat += text("
                      Back
                      ") + + if(10) //send announcement + dat += text("Station wide announcement

                      ") + if(announceAuth) + dat += text("Authentication accepted

                      ") + else + dat += text("Swipe your card to authenticate yourself.

                      ") + dat += text("Message: [message] Write

                      ") + if (announceAuth && message) + dat += text("Announce
                      "); + dat += text("
                      Back
                      ") + + else //main menu + screen = 0 + announceAuth = 0 + if (newmessagepriority == 1) + dat += text("There are new messages
                      ") + if (newmessagepriority == 2) + dat += text("NEW PRIORITY MESSAGES
                      ") + dat += text("View Messages

                      ") + + dat += text("Request Assistance
                      ") + dat += text("Request Supplies
                      ") + dat += text("Relay Anonymous Information

                      ") + dat += text("Configure Panel

                      ") + if(announcementConsole) + dat += text("Send station-wide announcement

                      ") + if (silent) + dat += text("Speaker OFF") + else + dat += text("Speaker ON") + + user << browse("[dat]", "window=request_console") + onclose(user, "req_console") + return + +/obj/machinery/requests_console/Topic(href, href_list) + if(..()) return + usr.set_machine(src) + add_fingerprint(usr) + + if(reject_bad_text(href_list["write"])) + dpt = ckey(href_list["write"]) //write contains the string of the receiving department's name + + var/new_message = copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) + if(new_message) + message = new_message + screen = 9 + switch(href_list["priority"]) + if("2") priority = 2 + else priority = -1 + else + dpt = ""; + msgVerified = "" + msgStamped = "" + screen = 0 + priority = -1 + + if(href_list["writeAnnouncement"]) + var/new_message = copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) + if(new_message) + message = new_message + switch(href_list["priority"]) + if("2") priority = 2 + else priority = -1 + else + message = "" + announceAuth = 0 + screen = 0 + + if(href_list["sendAnnouncement"]) + if(!announcementConsole) return + for(var/mob/M in player_list) + if(!istype(M,/mob/new_player) && M.client) to_chat(M, "[department] announcement: [message]") - announceAuth = 0 - message = "" - screen = 0 - - if( href_list["department"] && message ) - var/log_msg = message - var/sending = message - sending += "
                      " - if (msgVerified) - sending += msgVerified - sending += "
                      " - if (msgStamped) - sending += msgStamped - sending += "
                      " - screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull) - if (sending) - var/pass = 0 - for (var/obj/machinery/message_server/MS in message_servers) - if(!MS.active) continue - MS.send_rc_message(href_list["department"],department,log_msg,msgStamped,msgVerified,priority) - pass = 1 - - if(pass) - - for (var/obj/machinery/requests_console/Console in allConsoles) - if (ckey(Console.department) == ckey(href_list["department"])) - - switch(priority) - if(2) //High priority - if(Console.newmessagepriority < 2) - Console.newmessagepriority = 2 - Console.icon_state = "req_comp3" - if(!Console.silent) - playsound(Console.loc, 'sound/machines/request_urgent.ogg', 50, 1) - say(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [department]'")) - Console.messages += "High Priority message from [department]
                      [sending]" - - // if("3") //Not implemanted, but will be //Removed as it doesn't look like anybody intends on implimenting it ~Carn - // if(Console.newmessagepriority < 3) - // Console.newmessagepriority = 3 - // Console.icon_state = "req_comp3" - // if(!Console.silent) - // playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1) - // for (var/mob/O in hearers(7, Console.loc)) - // O.show_message(text("\icon[Console] *The Requests Console yells: 'EXTREME PRIORITY alert in [department]'")) - // Console.messages += "Extreme Priority message from [ckey(department)]
                      [message]" - - else // Normal priority - if(Console.newmessagepriority < 1) - Console.newmessagepriority = 1 - Console.icon_state = "req_comp2" - if(!Console.silent) - playsound(Console.loc, 'sound/machines/request.ogg', 50, 1) - say(text("\icon[Console] *The Requests Console beeps: 'Message from [department]'")) - Console.messages += "Message from [department]
                      [message]" - - screen = 6 - Console.set_light(2) - messages += "Message sent to [dpt]
                      [message]" - else - say(text("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'")) - - - //Handle screen switching - switch(text2num(href_list["setScreen"])) - if(null) //skip - if(1) //req. assistance - screen = 1 - if(2) //req. supplies - screen = 2 - if(3) //relay information - screen = 3 -// if(4) //write message -// screen = 4 - if(5) //configure - screen = 5 - if(6) //sent successfully - screen = 6 - if(7) //unsuccessfull; not sent - screen = 7 - if(8) //view messages - screen = 8 - if(9) //authentication - screen = 9 - if(10) //send announcement - if(!announcementConsole) return - screen = 10 - else //main menu - dpt = "" - msgVerified = "" - msgStamped = "" - message = "" - priority = -1 - screen = 0 - - //Handle silencing the console - switch( href_list["setSilent"] ) - if(null) //skip - if("1") silent = 1 - else silent = 0 - - switch( href_list["setDepartment"] ) - if(null) //skip - else - var/name = reject_bad_text(input(usr,"Name:","Name this department.","Public") as null|text) - set_department(name,text2num(href_list["setDepartment"])) - - updateUsrDialog() - return - -/obj/machinery/say_quote(var/text) - var/ending = copytext(text, length(text) - 2) - if(ending == "!!!") - return "blares, [text]" - - return "beeps, [text]" - - //deconstruction and hacking -/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) - if (istype(O, /obj/item/weapon/crowbar)) - if(open) - open = 0 - icon_state="req_comp0" - else - open = 1 - if(!hackState) - icon_state="req_comp_open" - else - icon_state="req_comp_rewired" - if (istype(O, /obj/item/weapon/screwdriver)) - if(open) - if(!hackState) - hackState = 1 - icon_state="req_comp_rewired" - else - hackState = 0 - icon_state="req_comp_open" - else + announceAuth = 0 + message = "" + screen = 0 + + if( href_list["department"] && message ) + var/log_msg = message + var/sending = message + sending += "
                      " + if (msgVerified) + sending += msgVerified + sending += "
                      " + if (msgStamped) + sending += msgStamped + sending += "
                      " + screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull) + if (sending) + var/pass = 0 + for (var/obj/machinery/message_server/MS in message_servers) + if(!MS.active) continue + MS.send_rc_message(href_list["department"],department,log_msg,msgStamped,msgVerified,priority) + pass = 1 + + if(pass) + + for (var/obj/machinery/requests_console/Console in allConsoles) + if (ckey(Console.department) == ckey(href_list["department"])) + + switch(priority) + if(2) //High priority + if(Console.newmessagepriority < 2) + Console.newmessagepriority = 2 + Console.icon_state = "req_comp3" + if(!Console.silent) + playsound(Console.loc, 'sound/machines/request_urgent.ogg', 50, 1) + say(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [department]'")) + Console.messages += "High Priority message from [department]
                      [sending]" + + // if("3") //Not implemanted, but will be //Removed as it doesn't look like anybody intends on implimenting it ~Carn + // if(Console.newmessagepriority < 3) + // Console.newmessagepriority = 3 + // Console.icon_state = "req_comp3" + // if(!Console.silent) + // playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1) + // for (var/mob/O in hearers(7, Console.loc)) + // O.show_message(text("\icon[Console] *The Requests Console yells: 'EXTREME PRIORITY alert in [department]'")) + // Console.messages += "Extreme Priority message from [ckey(department)]
                      [message]" + + else // Normal priority + if(Console.newmessagepriority < 1) + Console.newmessagepriority = 1 + Console.icon_state = "req_comp2" + if(!Console.silent) + playsound(Console.loc, 'sound/machines/request.ogg', 50, 1) + say(text("\icon[Console] *The Requests Console beeps: 'Message from [department]'")) + Console.messages += "Message from [department]

                      [message]" + + screen = 6 + Console.set_light(2) + messages += "Message sent to [dpt]
                      [message]" + else + say(text("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'")) + + + //Handle screen switching + switch(text2num(href_list["setScreen"])) + if(null) //skip + if(1) //req. assistance + screen = 1 + if(2) //req. supplies + screen = 2 + if(3) //relay information + screen = 3 +// if(4) //write message +// screen = 4 + if(5) //configure + screen = 5 + if(6) //sent successfully + screen = 6 + if(7) //unsuccessfull; not sent + screen = 7 + if(8) //view messages + screen = 8 + if(9) //authentication + screen = 9 + if(10) //send announcement + if(!announcementConsole) return + screen = 10 + else //main menu + dpt = "" + msgVerified = "" + msgStamped = "" + message = "" + priority = -1 + screen = 0 + + //Handle silencing the console + switch( href_list["setSilent"] ) + if(null) //skip + if("1") silent = 1 + else silent = 0 + + switch( href_list["setDepartment"] ) + if(null) //skip + else + var/name = reject_bad_text(input(usr,"Name:","Name this department.","Public") as null|text) + set_department(name,text2num(href_list["setDepartment"])) + + updateUsrDialog() + return + +/obj/machinery/say_quote(var/text) + var/ending = copytext(text, length(text) - 2) + if(ending == "!!!") + return "blares, [text]" + + return "beeps, [text]" + + //deconstruction and hacking +/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) + if (istype(O, /obj/item/weapon/crowbar)) + if(open) + open = 0 + icon_state="req_comp0" + else + open = 1 + if(!hackState) + icon_state="req_comp_open" + else + icon_state="req_comp_rewired" + if (istype(O, /obj/item/weapon/screwdriver)) + if(open) + if(!hackState) + hackState = 1 + icon_state="req_comp_rewired" + else + hackState = 0 + icon_state="req_comp_open" + else to_chat(user, "You can't do much with that.") - if(iswrench(O) && open && !departmentType) - user.visible_message("[user] disassembles the [src]!", "You disassemble the [src]") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - new /obj/item/stack/sheet/metal (src.loc,2) - qdel(src) - return - if (istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda)) - if(screen == 5) - var/obj/item/weapon/card/id/ID = O.GetID() - if (hackState || ID.access.Find(access_engine_equip)) - announceAuth = 1 - else - announceAuth = 0 + if(iswrench(O) && open && !departmentType) + user.visible_message("[user] disassembles the [src]!", "You disassemble the [src]") + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + new /obj/item/stack/sheet/metal (src.loc,2) + qdel(src) + return + if (istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda)) + if(screen == 5) + var/obj/item/weapon/card/id/ID = O.GetID() + if (hackState || ID.access.Find(access_engine_equip)) + announceAuth = 1 + else + announceAuth = 0 to_chat(user, "You are not authorized to configure this panel.") - updateUsrDialog() - if(screen == 9) - var/obj/item/weapon/card/id/ID = O.GetID() - msgVerified = "Verified by [ID.registered_name] ([ID.assignment])" - updateUsrDialog() - if (screen == 10) - var/obj/item/weapon/card/id/ID = O.GetID() - - if (!isnull(ID) && ID.access.Find(access_RC_announce) || hackState) - announceAuth = TRUE - else - announceAuth = FALSE + updateUsrDialog() + if(screen == 9) + var/obj/item/weapon/card/id/ID = O.GetID() + msgVerified = "Verified by [ID.registered_name] ([ID.assignment])" + updateUsrDialog() + if (screen == 10) + var/obj/item/weapon/card/id/ID = O.GetID() + + if (!isnull(ID) && ID.access.Find(access_RC_announce) || hackState) + announceAuth = TRUE + else + announceAuth = FALSE to_chat(user, "You are not authorized to send announcements.") - - updateUsrDialog() - if (istype(O, /obj/item/weapon/stamp)) - if(screen == 9) - var/obj/item/weapon/stamp/T = O - msgStamped = text("Stamped with the [T.name]") - updateUsrDialog() - return - -/obj/machinery/requests_console/mechanic - name = "\improper Mechanics requests console" - department = "Mechanics" - departmentType = 4 + + updateUsrDialog() + if (istype(O, /obj/item/weapon/stamp)) + if(screen == 9) + var/obj/item/weapon/stamp/T = O + msgStamped = text("Stamped with the [T.name]") + updateUsrDialog() + return + +/obj/machinery/requests_console/mechanic + name = "\improper Mechanics requests console" + department = "Mechanics" + departmentType = 4 diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm index 81541a51e4c..f4533a6eb89 100644 --- a/code/game/machinery/robot_fabricator.dm +++ b/code/game/machinery/robot_fabricator.dm @@ -1,150 +1,150 @@ -/obj/machinery/robotic_fabricator - name = "Robotic Fabricator" - icon = 'icons/obj/robotics.dmi' - icon_state = "fab-idle" - density = 1 - anchored = 1 - var/metal_amount = 0 - var/operating = 0 - var/obj/item/robot_parts/being_built = null - use_power = 1 - idle_power_usage = 20 - active_power_usage = 5000 - -/obj/machinery/robotic_fabricator/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (istype(O, /obj/item/stack/sheet/metal)) - if (src.metal_amount < 150000.0) - var/count = 0 - src.overlays += "fab-load-metal" - spawn(15) - if(O) - if(!O:amount) - return - while(metal_amount < 150000 && O:amount) - src.metal_amount += O:m_amt /*O:height * O:width * O:length * 100000.0*/ - O:amount-- - count++ - - if (O:amount < 1) - qdel(O) - O = null - +/obj/machinery/robotic_fabricator + name = "Robotic Fabricator" + icon = 'icons/obj/robotics.dmi' + icon_state = "fab-idle" + density = 1 + anchored = 1 + var/metal_amount = 0 + var/operating = 0 + var/obj/item/robot_parts/being_built = null + use_power = 1 + idle_power_usage = 20 + active_power_usage = 5000 + +/obj/machinery/robotic_fabricator/attackby(var/obj/item/O as obj, var/mob/user as mob) + if (istype(O, /obj/item/stack/sheet/metal)) + if (src.metal_amount < 150000.0) + var/count = 0 + src.overlays += "fab-load-metal" + spawn(15) + if(O) + if(!O:amount) + return + while(metal_amount < 150000 && O:amount) + src.metal_amount += O:m_amt /*O:height * O:width * O:length * 100000.0*/ + O:amount-- + count++ + + if (O:amount < 1) + qdel(O) + O = null + to_chat(user, "You insert [count] metal sheet\s into the fabricator.") - src.overlays -= "fab-load-metal" - updateDialog() - else + src.overlays -= "fab-load-metal" + updateDialog() + else to_chat(user, "The robot part maker is full. Please remove metal from the robot part maker in order to insert more.") - -/obj/machinery/robotic_fabricator/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= NOPOWER - -/obj/machinery/robotic_fabricator/attack_paw(user as mob) - return src.attack_hand(user) - -/obj/machinery/robotic_fabricator/attack_hand(user as mob) - var/dat - if (..()) - return - - if (src.operating) - dat = {" -Building [src.being_built.name].
                      -Please wait until completion...

                      -
                      -"} - else - dat = {" -Metal Amount: [min(150000, src.metal_amount)] cm3 (MAX: 150,000)

                      -
                      -Left Arm (25,000 cc metal.)
                      -
                      Right Arm (25,000 cc metal.)
                      -
                      Left Leg (25,000 cc metal.)
                      -
                      Right Leg (25,000 cc metal).
                      -
                      Chest (50,000 cc metal).
                      -
                      Head (50,000 cc metal).
                      -
                      Robot Frame (75,000 cc metal).
                      -"} - - user << browse("Robotic Fabricator Control Panel[dat]", "window=robot_fabricator") - onclose(user, "robot_fabricator") - return - -/obj/machinery/robotic_fabricator/Topic(href, href_list) - if (..()) - return - - usr.set_machine(src) - src.add_fingerprint(usr) - - if (href_list["make"]) - if (!src.operating) - var/part_type = text2num(href_list["make"]) - - var/build_type = "" - var/build_time = 200 - var/build_cost = 25000 - - switch (part_type) - if (1) - build_type = "/obj/item/robot_parts/l_arm" - build_time = 200 - build_cost = 25000 - - if (2) - build_type = "/obj/item/robot_parts/r_arm" - build_time = 200 - build_cost = 25000 - - if (3) - build_type = "/obj/item/robot_parts/l_leg" - build_time = 200 - build_cost = 25000 - - if (4) - build_type = "/obj/item/robot_parts/r_leg" - build_time = 200 - build_cost = 25000 - - if (5) - build_type = "/obj/item/robot_parts/chest" - build_time = 350 - build_cost = 50000 - - if (6) - build_type = "/obj/item/robot_parts/head" - build_time = 350 - build_cost = 50000 - - if (7) - build_type = "/obj/item/robot_parts/robot_suit" - build_time = 600 - build_cost = 75000 - - var/building = text2path(build_type) - if (!isnull(building)) - if (src.metal_amount >= build_cost) - src.operating = 1 - src.use_power = 2 - - src.metal_amount = max(0, src.metal_amount - build_cost) - - src.being_built = new building(src) - - src.overlays += "fab-active" - src.updateUsrDialog() - - spawn (build_time) - if (!isnull(src.being_built)) - src.being_built.loc = get_turf(src) - src.being_built = null - src.use_power = 1 - src.operating = 0 - src.overlays -= "fab-active" - return - - for (var/mob/M in viewers(1, src)) - if (M.client && M.machine == src) - src.attack_hand(M) + +/obj/machinery/robotic_fabricator/power_change() + if (powered()) + stat &= ~NOPOWER + else + stat |= NOPOWER + +/obj/machinery/robotic_fabricator/attack_paw(user as mob) + return src.attack_hand(user) + +/obj/machinery/robotic_fabricator/attack_hand(user as mob) + var/dat + if (..()) + return + + if (src.operating) + dat = {" +Building [src.being_built.name].
                      +Please wait until completion...

                      +
                      +"} + else + dat = {" +Metal Amount: [min(150000, src.metal_amount)] cm3 (MAX: 150,000)

                      +
                      +
                      Left Arm (25,000 cc metal.)
                      +
                      Right Arm (25,000 cc metal.)
                      +
                      Left Leg (25,000 cc metal.)
                      +
                      Right Leg (25,000 cc metal).
                      +
                      Chest (50,000 cc metal).
                      +
                      Head (50,000 cc metal).
                      +
                      Robot Frame (75,000 cc metal).
                      +"} + + user << browse("Robotic Fabricator Control Panel[dat]", "window=robot_fabricator") + onclose(user, "robot_fabricator") + return + +/obj/machinery/robotic_fabricator/Topic(href, href_list) + if (..()) + return + + usr.set_machine(src) + src.add_fingerprint(usr) + + if (href_list["make"]) + if (!src.operating) + var/part_type = text2num(href_list["make"]) + + var/build_type = "" + var/build_time = 200 + var/build_cost = 25000 + + switch (part_type) + if (1) + build_type = "/obj/item/robot_parts/l_arm" + build_time = 200 + build_cost = 25000 + + if (2) + build_type = "/obj/item/robot_parts/r_arm" + build_time = 200 + build_cost = 25000 + + if (3) + build_type = "/obj/item/robot_parts/l_leg" + build_time = 200 + build_cost = 25000 + + if (4) + build_type = "/obj/item/robot_parts/r_leg" + build_time = 200 + build_cost = 25000 + + if (5) + build_type = "/obj/item/robot_parts/chest" + build_time = 350 + build_cost = 50000 + + if (6) + build_type = "/obj/item/robot_parts/head" + build_time = 350 + build_cost = 50000 + + if (7) + build_type = "/obj/item/robot_parts/robot_suit" + build_time = 600 + build_cost = 75000 + + var/building = text2path(build_type) + if (!isnull(building)) + if (src.metal_amount >= build_cost) + src.operating = 1 + src.use_power = 2 + + src.metal_amount = max(0, src.metal_amount - build_cost) + + src.being_built = new building(src) + + src.overlays += "fab-active" + src.updateUsrDialog() + + spawn (build_time) + if (!isnull(src.being_built)) + src.being_built.loc = get_turf(src) + src.being_built = null + src.use_power = 1 + src.operating = 0 + src.overlays -= "fab-active" + return + + for (var/mob/M in viewers(1, src)) + if (M.client && M.machine == src) + src.attack_hand(M) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 3cb246a2885..930e6ee92c3 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -1,609 +1,609 @@ -/obj/machinery/shield - name = "Emergency energy shield" - desc = "An energy shield used to contain hull breaches." - icon = 'icons/effects/effects.dmi' - icon_state = "shield-old" - density = 1 - opacity = 0 - anchored = 1 - unacidable = 1 - ghost_read = 0 - ghost_write = 0 - var/const/max_health = 200 - var/health = max_health //The shield can only take so much beating (prevents perma-prisons) - -/obj/machinery/shield/New() - src.dir = pick(1,2,3,4) - ..() - update_nearby_tiles() - -/obj/machinery/shield/Destroy() - opacity = 0 - density = 0 - update_nearby_tiles() - ..() - -/obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(!height || air_group) return 0 - else return ..() - -//Looks like copy/pasted code... I doubt 'need_rebuild' is even used here - Nodrak -/obj/machinery/shield/proc/update_nearby_tiles() - if (isnull(air_master)) - return 0 - - var/T = loc - - if (isturf(T)) - air_master.mark_for_update(T) - - return 1 - -/obj/machinery/shield/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(!istype(W)) return - - //Calculate damage - var/aforce = W.force - if(W.damtype == BRUTE || W.damtype == BURN) - src.health -= aforce - - //Play a fitting sound - playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 75, 1) - - - if (src.health <= 0) - visible_message("The [src] dissapates") - qdel(src) - return - - opacity = 1 - spawn(20) if(src) opacity = 0 - - if(src.health <= 0) - visible_message("The [src] dissapates") - qdel(src) - return - - opacity = 1 - spawn(20) if(src) opacity = 0 - -/obj/machinery/shield/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <=0) - visible_message("The [src] dissapates") - qdel(src) - return - opacity = 1 - spawn(20) if(src) opacity = 0 - -/obj/machinery/shield/ex_act(severity) - switch(severity) - if(1.0) - if (prob(75)) - qdel(src) - if(2.0) - if (prob(50)) - qdel(src) - if(3.0) - if (prob(25)) - qdel(src) - -/obj/machinery/shield/emp_act(severity) - switch(severity) - if(1) - qdel(src) - if(2) - if(prob(50)) - qdel(src) - -/obj/machinery/shield/blob_act() - qdel(src) - - -/obj/machinery/shield/hitby(AM as mob|obj) - //Let everyone know we've been hit! - visible_message("[src] was hit by [AM].") - - //Super realistic, resource-intensive, real-time damage calculations. - var/tforce = 0 - if(ismob(AM)) - tforce = 40 - else - tforce = AM:throwforce - - src.health -= tforce - - //This seemed to be the best sound for hitting a force field. - playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1) - - //Handle the destruction of the shield - if (src.health <= 0) - visible_message("The [src] dissapates") - qdel(src) - return - - //The shield becomes dense to absorb the blow.. purely asthetic. - opacity = 1 - spawn(20) if(src) opacity = 0 - - return ..() - - - -/obj/machinery/shieldgen - name = "Emergency shield projector" - desc = "Used to seal minor hull breaches." - icon = 'icons/obj/objects.dmi' - icon_state = "shieldoff" - density = 1 - opacity = 0 - anchored = 0 - pressure_resistance = 2*ONE_ATMOSPHERE - req_access = list(access_engine) - var/const/max_health = 100 - var/health = max_health - var/active = 0 - var/malfunction = 0 //Malfunction causes parts of the shield to slowly dissapate - var/list/deployed_shields = list() - var/locked = 0 - ghost_read = 0 - ghost_write = 0 - - machine_flags = EMAGGABLE | WRENCHMOVE | FIXED2WORK | SCREWTOGGLE - -/obj/machinery/shieldgen/Destroy() - for(var/obj/machinery/shield/shield_tile in deployed_shields) - deployed_shields -= shield_tile - qdel(shield_tile) - ..() - - -/obj/machinery/shieldgen/proc/shields_up() - if(active) return 0 //If it's already turned on, how did this get called? - - src.active = 1 - update_icon() - - for(var/turf/target_tile in range(2, src)) - if (istype(target_tile,/turf/space) && !(locate(/obj/machinery/shield) in target_tile)) - if (malfunction && prob(33) || !malfunction) - deployed_shields += new /obj/machinery/shield(target_tile) - -/obj/machinery/shieldgen/proc/shields_down() - if(!active) return 0 //If it's already off, how did this get called? - - src.active = 0 - update_icon() - - for(var/obj/machinery/shield/shield_tile in deployed_shields) - deployed_shields -= shield_tile - qdel(shield_tile) - -/obj/machinery/shieldgen/process() - if(malfunction && active) - if(deployed_shields.len && prob(5)) - qdel(pick(deployed_shields)) - -/obj/machinery/shieldgen/proc/checkhp() - if(health <= 30) - src.malfunction = 1 - if(health <= 0) - qdel(src) - update_icon() - -/obj/machinery/shieldgen/ex_act(severity) - switch(severity) - if(1.0) - src.health -= 75 - src.checkhp() - if(2.0) - src.health -= 30 - if (prob(15)) - src.malfunction = 1 - src.checkhp() - if(3.0) - src.health -= 10 - src.checkhp() - -/obj/machinery/shieldgen/emp_act(severity) - switch(severity) - if(1) - src.health /= 2 //cut health in half - malfunction = 1 - locked = pick(0,1) - if(2) - if(prob(50)) - src.health *= 0.3 //chop off a third of the health - malfunction = 1 - checkhp() - -/obj/machinery/shieldgen/attack_ghost(mob/user) - if(isAdminGhost(user)) - src.attack_hand(user) - -/obj/machinery/shieldgen/attack_hand(mob/user as mob) - if(locked) +/obj/machinery/shield + name = "Emergency energy shield" + desc = "An energy shield used to contain hull breaches." + icon = 'icons/effects/effects.dmi' + icon_state = "shield-old" + density = 1 + opacity = 0 + anchored = 1 + unacidable = 1 + ghost_read = 0 + ghost_write = 0 + var/const/max_health = 200 + var/health = max_health //The shield can only take so much beating (prevents perma-prisons) + +/obj/machinery/shield/New() + src.dir = pick(1,2,3,4) + ..() + update_nearby_tiles() + +/obj/machinery/shield/Destroy() + opacity = 0 + density = 0 + update_nearby_tiles() + ..() + +/obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(!height || air_group) return 0 + else return ..() + +//Looks like copy/pasted code... I doubt 'need_rebuild' is even used here - Nodrak +/obj/machinery/shield/proc/update_nearby_tiles() + if (isnull(air_master)) + return 0 + + var/T = loc + + if (isturf(T)) + air_master.mark_for_update(T) + + return 1 + +/obj/machinery/shield/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(!istype(W)) return + + //Calculate damage + var/aforce = W.force + if(W.damtype == BRUTE || W.damtype == BURN) + src.health -= aforce + + //Play a fitting sound + playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 75, 1) + + + if (src.health <= 0) + visible_message("The [src] dissapates") + qdel(src) + return + + opacity = 1 + spawn(20) if(src) opacity = 0 + + if(src.health <= 0) + visible_message("The [src] dissapates") + qdel(src) + return + + opacity = 1 + spawn(20) if(src) opacity = 0 + +/obj/machinery/shield/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <=0) + visible_message("The [src] dissapates") + qdel(src) + return + opacity = 1 + spawn(20) if(src) opacity = 0 + +/obj/machinery/shield/ex_act(severity) + switch(severity) + if(1.0) + if (prob(75)) + qdel(src) + if(2.0) + if (prob(50)) + qdel(src) + if(3.0) + if (prob(25)) + qdel(src) + +/obj/machinery/shield/emp_act(severity) + switch(severity) + if(1) + qdel(src) + if(2) + if(prob(50)) + qdel(src) + +/obj/machinery/shield/blob_act() + qdel(src) + + +/obj/machinery/shield/hitby(AM as mob|obj) + //Let everyone know we've been hit! + visible_message("[src] was hit by [AM].") + + //Super realistic, resource-intensive, real-time damage calculations. + var/tforce = 0 + if(ismob(AM)) + tforce = 40 + else + tforce = AM:throwforce + + src.health -= tforce + + //This seemed to be the best sound for hitting a force field. + playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1) + + //Handle the destruction of the shield + if (src.health <= 0) + visible_message("The [src] dissapates") + qdel(src) + return + + //The shield becomes dense to absorb the blow.. purely asthetic. + opacity = 1 + spawn(20) if(src) opacity = 0 + + return ..() + + + +/obj/machinery/shieldgen + name = "Emergency shield projector" + desc = "Used to seal minor hull breaches." + icon = 'icons/obj/objects.dmi' + icon_state = "shieldoff" + density = 1 + opacity = 0 + anchored = 0 + pressure_resistance = 2*ONE_ATMOSPHERE + req_access = list(access_engine) + var/const/max_health = 100 + var/health = max_health + var/active = 0 + var/malfunction = 0 //Malfunction causes parts of the shield to slowly dissapate + var/list/deployed_shields = list() + var/locked = 0 + ghost_read = 0 + ghost_write = 0 + + machine_flags = EMAGGABLE | WRENCHMOVE | FIXED2WORK | SCREWTOGGLE + +/obj/machinery/shieldgen/Destroy() + for(var/obj/machinery/shield/shield_tile in deployed_shields) + deployed_shields -= shield_tile + qdel(shield_tile) + ..() + + +/obj/machinery/shieldgen/proc/shields_up() + if(active) return 0 //If it's already turned on, how did this get called? + + src.active = 1 + update_icon() + + for(var/turf/target_tile in range(2, src)) + if (istype(target_tile,/turf/space) && !(locate(/obj/machinery/shield) in target_tile)) + if (malfunction && prob(33) || !malfunction) + deployed_shields += new /obj/machinery/shield(target_tile) + +/obj/machinery/shieldgen/proc/shields_down() + if(!active) return 0 //If it's already off, how did this get called? + + src.active = 0 + update_icon() + + for(var/obj/machinery/shield/shield_tile in deployed_shields) + deployed_shields -= shield_tile + qdel(shield_tile) + +/obj/machinery/shieldgen/process() + if(malfunction && active) + if(deployed_shields.len && prob(5)) + qdel(pick(deployed_shields)) + +/obj/machinery/shieldgen/proc/checkhp() + if(health <= 30) + src.malfunction = 1 + if(health <= 0) + qdel(src) + update_icon() + +/obj/machinery/shieldgen/ex_act(severity) + switch(severity) + if(1.0) + src.health -= 75 + src.checkhp() + if(2.0) + src.health -= 30 + if (prob(15)) + src.malfunction = 1 + src.checkhp() + if(3.0) + src.health -= 10 + src.checkhp() + +/obj/machinery/shieldgen/emp_act(severity) + switch(severity) + if(1) + src.health /= 2 //cut health in half + malfunction = 1 + locked = pick(0,1) + if(2) + if(prob(50)) + src.health *= 0.3 //chop off a third of the health + malfunction = 1 + checkhp() + +/obj/machinery/shieldgen/attack_ghost(mob/user) + if(isAdminGhost(user)) + src.attack_hand(user) + +/obj/machinery/shieldgen/attack_hand(mob/user as mob) + if(locked) to_chat(user, "The machine is locked, you are unable to use it.") - return - if(panel_open) + return + if(panel_open) to_chat(user, "The panel must be closed before operating this machine.") - return - - if (src.active) - user.visible_message("\icon[src] [user] deactivated the shield generator.", \ - "\icon[src] You deactivate the shield generator.", \ - "You hear heavy droning fade out.") - src.shields_down() - else - if(anchored) - user.visible_message("\icon[src] [user] activated the shield generator.", \ - "\icon[src] You activate the shield generator.", \ - "You hear heavy droning.") - src.shields_up() - else + return + + if (src.active) + user.visible_message("\icon[src] [user] deactivated the shield generator.", \ + "\icon[src] You deactivate the shield generator.", \ + "You hear heavy droning fade out.") + src.shields_down() + else + if(anchored) + user.visible_message("\icon[src] [user] activated the shield generator.", \ + "\icon[src] You activate the shield generator.", \ + "You hear heavy droning.") + src.shields_up() + else to_chat(user, "The [src] must first be secured to the floor.") - -/obj/machinery/shieldgen/emag(mob/user) - if(!emagged) - malfunction = 1 - update_icon() - return 1 - -/obj/machinery/shieldgen/wrenchAnchor(mob/user) - if(locked) + +/obj/machinery/shieldgen/emag(mob/user) + if(!emagged) + malfunction = 1 + update_icon() + return 1 + +/obj/machinery/shieldgen/wrenchAnchor(mob/user) + if(locked) to_chat(user, "The bolts are covered, unlocking this would retract the covers.") - return - if(active) + return + if(active) to_chat(user, "Turn \the [src] off first!") - if(panel_open) + if(panel_open) to_chat(user, "You have to close \the [src]'s maintenance panel before you can do that.") - return - return ..() - -/obj/machinery/shieldgen/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(..()) - return 1 - - if(istype(W, /obj/item/stack/cable_coil) && malfunction && panel_open) - var/obj/item/stack/cable_coil/coil = W + return + return ..() + +/obj/machinery/shieldgen/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(..()) + return 1 + + if(istype(W, /obj/item/stack/cable_coil) && malfunction && panel_open) + var/obj/item/stack/cable_coil/coil = W to_chat(user, "You begin to replace the wires.") - //if(do_after(user, src, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage - if(do_after(user, src, 30)) - if(!src || !coil) return - coil.use(1) - health = max_health - malfunction = 0 + //if(do_after(user, src, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage + if(do_after(user, src, 30)) + if(!src || !coil) return + coil.use(1) + health = max_health + malfunction = 0 to_chat(user, "You repair the [src]!") - update_icon() - return - - if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) - if(src.allowed(user)) - src.locked = !src.locked + update_icon() + return + + if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) + if(src.allowed(user)) + src.locked = !src.locked to_chat(user, "The controls are now [src.locked ? "locked." : "unlocked."]") - else + else to_chat(user, "Access denied.") - return - - -/obj/machinery/shieldgen/update_icon() - if(active) - src.icon_state = malfunction ? "shieldonbr":"shieldon" - else - src.icon_state = malfunction ? "shieldoffbr":"shieldoff" - -////FIELD GEN START //shameless copypasta from fieldgen, powersink, and grille -#define maxstoredpower 500 -/obj/machinery/shieldwallgen - name = "Shield Generator" - desc = "A shield generator." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "Shield_Gen" - anchored = 0 - density = 1 - req_access = list(access_teleporter) - var/active = 0 - var/power = 0 - var/steps = 0 - var/last_check = 0 - var/check_delay = 10 - var/recalc = 0 - var/locked = 1 - var/destroyed = 0 -// var/maxshieldload = 200 - var/obj/structure/cable/attached // the attached cable - var/storedpower = 0 - flags = FPRINT - siemens_coefficient = 1 - use_power = 0 - - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/shieldwallgen/proc/power() - if(!anchored) - power = 0 - return 0 - var/turf/T = src.loc - - if(!T) - return - var/obj/structure/cable/C = T.get_cable_node() - var/datum/powernet/PN - if(C) PN = C.powernet // find the powernet of the connected cable - - if(!PN) - power = 0 - return 0 - - var/surplus = max(PN.avail-PN.load, 0) - var/shieldload = min(rand(50,200), surplus) - if(shieldload==0 && !storedpower) // no cable or no power, and no power stored - power = 0 - return 0 - else - power = 1 // IVE GOT THE POWER! - if(PN) //runtime errors fixer. They were caused by PN.newload trying to access missing network in case of working on stored power. - storedpower += shieldload - PN.load += shieldload //uses powernet power. -// message_admins("[PN.load]", 1) -// use_power(250) //uses APC power - -/obj/machinery/shieldwallgen/attack_hand(mob/user as mob) - if(!anchored) + return + + +/obj/machinery/shieldgen/update_icon() + if(active) + src.icon_state = malfunction ? "shieldonbr":"shieldon" + else + src.icon_state = malfunction ? "shieldoffbr":"shieldoff" + +////FIELD GEN START //shameless copypasta from fieldgen, powersink, and grille +#define maxstoredpower 500 +/obj/machinery/shieldwallgen + name = "Shield Generator" + desc = "A shield generator." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "Shield_Gen" + anchored = 0 + density = 1 + req_access = list(access_teleporter) + var/active = 0 + var/power = 0 + var/steps = 0 + var/last_check = 0 + var/check_delay = 10 + var/recalc = 0 + var/locked = 1 + var/destroyed = 0 +// var/maxshieldload = 200 + var/obj/structure/cable/attached // the attached cable + var/storedpower = 0 + flags = FPRINT + siemens_coefficient = 1 + use_power = 0 + + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/shieldwallgen/proc/power() + if(!anchored) + power = 0 + return 0 + var/turf/T = src.loc + + if(!T) + return + var/obj/structure/cable/C = T.get_cable_node() + var/datum/powernet/PN + if(C) PN = C.powernet // find the powernet of the connected cable + + if(!PN) + power = 0 + return 0 + + var/surplus = max(PN.avail-PN.load, 0) + var/shieldload = min(rand(50,200), surplus) + if(shieldload==0 && !storedpower) // no cable or no power, and no power stored + power = 0 + return 0 + else + power = 1 // IVE GOT THE POWER! + if(PN) //runtime errors fixer. They were caused by PN.newload trying to access missing network in case of working on stored power. + storedpower += shieldload + PN.load += shieldload //uses powernet power. +// message_admins("[PN.load]", 1) +// use_power(250) //uses APC power + +/obj/machinery/shieldwallgen/attack_hand(mob/user as mob) + if(!anchored) to_chat(user, "The shield generator needs to be firmly secured to the floor first.") - return 1 - if(src.locked && !istype(user, /mob/living/silicon)) + return 1 + if(src.locked && !istype(user, /mob/living/silicon)) to_chat(user, "The controls are locked!") - return 1 - if(power != 1) + return 1 + if(power != 1) to_chat(user, "The shield generator needs to be powered by wire underneath.") - return 1 - - if(src.active) - src.active = 0 - icon_state = "Shield_Gen" - - user.visible_message("[user] turned the shield generator off.", \ - "You turn off the shield generator.", \ - "You hear heavy droning fade out.") - src.cleanup() - else - src.active = 1 - icon_state = "Shield_Gen +a" - user.visible_message("[user] turned the shield generator on.", \ - "You turn on the shield generator.", \ - "You hear heavy droning.") - src.add_fingerprint(user) - -/obj/machinery/shieldwallgen/process() - spawn(100) - power() - if(power) - storedpower -= 50 //this way it can survive longer and survive at all - if(storedpower >= maxstoredpower) - storedpower = maxstoredpower - if(storedpower <= 0) - storedpower = 0 -// if(shieldload >= maxshieldload) //there was a loop caused by specifics of process(), so this was needed. -// shieldload = maxshieldload - - if(src.active == 1) - if(!anchored) - src.active = 0 - return - spawn(1) - setup_field(1) - spawn(2) - setup_field(2) - spawn(3) - setup_field(4) - spawn(4) - setup_field(8) - src.active = 2 - if(src.active == 1) - if(src.power == 0) - src.visible_message("The [src.name] shuts down due to lack of power!", \ - "You hear heavy droning fade out") - icon_state = "Shield_Gen" - src.active = 0 - spawn(1) - src.cleanup(1) - spawn(1) - src.cleanup(2) - spawn(1) - src.cleanup(4) - spawn(1) - src.cleanup(8) - -/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0) - var/turf/T = src.loc - var/turf/T2 = src.loc - var/obj/machinery/shieldwallgen/G - var/steps = 0 - var/oNSEW = 0 - - if(!NSEW)//Make sure its ran right - return - - if(NSEW == 1) - oNSEW = 2 - else if(NSEW == 2) - oNSEW = 1 - else if(NSEW == 4) - oNSEW = 8 - else if(NSEW == 8) - oNSEW = 4 - - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator - T = get_step(T2, NSEW) - T2 = T - steps += 1 - if(locate(/obj/machinery/shieldwallgen) in T) - G = (locate(/obj/machinery/shieldwallgen) in T) - steps -= 1 - if(!G.active) - return - G.cleanup(oNSEW) - break - - if(isnull(G)) - return - - T2 = src.loc - - for(var/dist = 0, dist < steps, dist += 1) // creates each field tile - var/field_dir = get_dir(T2,get_step(T2, NSEW)) - T = get_step(T2, NSEW) - T2 = T - var/obj/machinery/shieldwall/CF = new/obj/machinery/shieldwall/(src, G) //(ref to this gen, ref to connected gen) - CF.loc = T - CF.dir = field_dir - -/obj/machinery/shieldwallgen/wrenchAnchor(mob/user) - if(active) + return 1 + + if(src.active) + src.active = 0 + icon_state = "Shield_Gen" + + user.visible_message("[user] turned the shield generator off.", \ + "You turn off the shield generator.", \ + "You hear heavy droning fade out.") + src.cleanup() + else + src.active = 1 + icon_state = "Shield_Gen +a" + user.visible_message("[user] turned the shield generator on.", \ + "You turn on the shield generator.", \ + "You hear heavy droning.") + src.add_fingerprint(user) + +/obj/machinery/shieldwallgen/process() + spawn(100) + power() + if(power) + storedpower -= 50 //this way it can survive longer and survive at all + if(storedpower >= maxstoredpower) + storedpower = maxstoredpower + if(storedpower <= 0) + storedpower = 0 +// if(shieldload >= maxshieldload) //there was a loop caused by specifics of process(), so this was needed. +// shieldload = maxshieldload + + if(src.active == 1) + if(!anchored) + src.active = 0 + return + spawn(1) + setup_field(1) + spawn(2) + setup_field(2) + spawn(3) + setup_field(4) + spawn(4) + setup_field(8) + src.active = 2 + if(src.active == 1) + if(src.power == 0) + src.visible_message("The [src.name] shuts down due to lack of power!", \ + "You hear heavy droning fade out") + icon_state = "Shield_Gen" + src.active = 0 + spawn(1) + src.cleanup(1) + spawn(1) + src.cleanup(2) + spawn(1) + src.cleanup(4) + spawn(1) + src.cleanup(8) + +/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0) + var/turf/T = src.loc + var/turf/T2 = src.loc + var/obj/machinery/shieldwallgen/G + var/steps = 0 + var/oNSEW = 0 + + if(!NSEW)//Make sure its ran right + return + + if(NSEW == 1) + oNSEW = 2 + else if(NSEW == 2) + oNSEW = 1 + else if(NSEW == 4) + oNSEW = 8 + else if(NSEW == 8) + oNSEW = 4 + + for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator + T = get_step(T2, NSEW) + T2 = T + steps += 1 + if(locate(/obj/machinery/shieldwallgen) in T) + G = (locate(/obj/machinery/shieldwallgen) in T) + steps -= 1 + if(!G.active) + return + G.cleanup(oNSEW) + break + + if(isnull(G)) + return + + T2 = src.loc + + for(var/dist = 0, dist < steps, dist += 1) // creates each field tile + var/field_dir = get_dir(T2,get_step(T2, NSEW)) + T = get_step(T2, NSEW) + T2 = T + var/obj/machinery/shieldwall/CF = new/obj/machinery/shieldwall/(src, G) //(ref to this gen, ref to connected gen) + CF.loc = T + CF.dir = field_dir + +/obj/machinery/shieldwallgen/wrenchAnchor(mob/user) + if(active) to_chat(user, "Turn off the field generator first.") - return - if(..()) - power() - return 1 - - -/obj/machinery/shieldwallgen/attack_ghost(mob/user) - if(isAdminGhost(user)) - src.attack_hand(user) - -/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user) - if(..()) - return 1 - - if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user)) - src.locked = !src.locked + return + if(..()) + power() + return 1 + + +/obj/machinery/shieldwallgen/attack_ghost(mob/user) + if(isAdminGhost(user)) + src.attack_hand(user) + +/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user) + if(..()) + return 1 + + if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (src.allowed(user)) + src.locked = !src.locked to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") - else + else to_chat(user, "Access denied.") - - else - src.add_fingerprint(user) - visible_message("The [src.name] has been hit with the [W.name] by [user.name]!") - -/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW) - var/turf/T = src.loc - - for(var/dist = 0 to 8) // checks out to 8 tiles away for fields - T = get_step(T, NSEW) - for(var/obj/machinery/shieldwall/F in T) - qdel(F) - - for(var/obj/machinery/shieldwallgen/G in T) - if(!G.active) - return - -/obj/machinery/shieldwallgen/Destroy() - src.cleanup(1) - src.cleanup(2) - src.cleanup(4) - src.cleanup(8) - attached = null - ..() - -/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj) - storedpower -= Proj.damage - ..() - -//////////////Containment Field START -/obj/machinery/shieldwall - name = "Shield" - desc = "An energy shield." - icon = 'icons/effects/effects.dmi' - icon_state = "shieldwall" - anchored = 1 - density = 1 - unacidable = 1 - luminosity = 3 - var/needs_power = 0 - var/active = 1 - var/obj/machinery/shieldwallgen/gen_primary - var/obj/machinery/shieldwallgen/gen_secondary - -/obj/machinery/shieldwall/New(var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B) - ..() - src.gen_primary = A - src.gen_secondary = B - if(A && B) - needs_power = 1 - -/obj/machinery/shieldwall/Destroy() - ..() - gen_primary = null - gen_secondary = null - -/obj/machinery/shieldwall/attack_hand(mob/user as mob) - return - - -/obj/machinery/shieldwall/process() - if(needs_power) - if(isnull(gen_primary)||isnull(gen_secondary)) - qdel(src) - return - - if(!(gen_primary.active)||!(gen_secondary.active)) - qdel(src) - return - - if(prob(50)) - gen_primary.storedpower -= 10 - else - gen_secondary.storedpower -=10 - -/obj/machinery/shieldwall/bullet_act(var/obj/item/projectile/Proj) - if(needs_power) - var/obj/machinery/shieldwallgen/G - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= Proj.damage - ..() - - -/obj/machinery/shieldwall/ex_act(severity) - if(needs_power) - var/obj/machinery/shieldwallgen/G - switch(severity) - if(1.0) //big boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 200 - - if(2.0) //medium boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 50 - - if(3.0) //lil boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 20 - -/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - - if(!mover) - return - - if(istype(mover) && mover.checkpass(PASSGLASS)) - return prob(20) - else - if (istype(mover, /obj/item/projectile)) - return prob(10) - else - return !src.density + + else + src.add_fingerprint(user) + visible_message("The [src.name] has been hit with the [W.name] by [user.name]!") + +/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW) + var/turf/T = src.loc + + for(var/dist = 0 to 8) // checks out to 8 tiles away for fields + T = get_step(T, NSEW) + for(var/obj/machinery/shieldwall/F in T) + qdel(F) + + for(var/obj/machinery/shieldwallgen/G in T) + if(!G.active) + return + +/obj/machinery/shieldwallgen/Destroy() + src.cleanup(1) + src.cleanup(2) + src.cleanup(4) + src.cleanup(8) + attached = null + ..() + +/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj) + storedpower -= Proj.damage + ..() + +//////////////Containment Field START +/obj/machinery/shieldwall + name = "Shield" + desc = "An energy shield." + icon = 'icons/effects/effects.dmi' + icon_state = "shieldwall" + anchored = 1 + density = 1 + unacidable = 1 + luminosity = 3 + var/needs_power = 0 + var/active = 1 + var/obj/machinery/shieldwallgen/gen_primary + var/obj/machinery/shieldwallgen/gen_secondary + +/obj/machinery/shieldwall/New(var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B) + ..() + src.gen_primary = A + src.gen_secondary = B + if(A && B) + needs_power = 1 + +/obj/machinery/shieldwall/Destroy() + ..() + gen_primary = null + gen_secondary = null + +/obj/machinery/shieldwall/attack_hand(mob/user as mob) + return + + +/obj/machinery/shieldwall/process() + if(needs_power) + if(isnull(gen_primary)||isnull(gen_secondary)) + qdel(src) + return + + if(!(gen_primary.active)||!(gen_secondary.active)) + qdel(src) + return + + if(prob(50)) + gen_primary.storedpower -= 10 + else + gen_secondary.storedpower -=10 + +/obj/machinery/shieldwall/bullet_act(var/obj/item/projectile/Proj) + if(needs_power) + var/obj/machinery/shieldwallgen/G + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= Proj.damage + ..() + + +/obj/machinery/shieldwall/ex_act(severity) + if(needs_power) + var/obj/machinery/shieldwallgen/G + switch(severity) + if(1.0) //big boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 200 + + if(2.0) //medium boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 50 + + if(3.0) //lil boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 20 + +/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + + if(!mover) + return + + if(istype(mover) && mover.checkpass(PASSGLASS)) + return prob(20) + else + if (istype(mover, /obj/item/projectile)) + return prob(10) + else + return !src.density diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 10a0ded4a00..65e3bae3d10 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -1,419 +1,419 @@ -#define CHARS_PER_LINE 5 -#define FONT_SIZE "5pt" -#define FONT_COLOR "#09f" -#define FONT_STYLE "Arial Black" -#define SCROLL_SPEED 2 - -// Status display -// (formerly Countdown timer display) - -// Use to show shuttle ETA/ETD times -// Alert status -// And arbitrary messages set by comms computer - -#define MODE_BLANK 0 -#define MODE_SHUTTLE_TIMER 1 -#define MODE_MESSAGE 2 -#define MODE_IMAGE 3 -#define MODE_CARGO_TIMER 4 - -var/global/list/status_displays = list() //This list contains both normal status displays, and AI status dispays - -/obj/machinery/status_display - icon = 'icons/obj/status_display.dmi' - icon_state = "frame" - name = "status display" - anchored = 1 - density = 0 - use_power = 1 - idle_power_usage = 10 - var/mode = 1 // 0 = Blank - // 1 = Shuttle timer - // 2 = Arbitrary message(s) - // 3 = alert picture - // 4 = Supply shuttle timer - - var/picture_state // icon_state of alert picture - var/message1 = "" // message line 1 - var/message2 = "" // message line 2 - var/index1 // display index for scrolling messages or 0 if non-scrolling - var/index2 - - var/frequency = 1435 // radio frequency - var/supply_display = 0 // true if a supply shuttle display - - var/friendc = 0 // track if Friend Computer mode - - var/spookymode=0 // Ghosts. - - maptext_height = 26 - maptext_width = 32 - -// new display -// register for radio system -/obj/machinery/status_display/New() - ..() - status_displays |= src - spawn(5) // must wait for map loading to finish - if(radio_controller) - radio_controller.add_object(src, frequency) - -/obj/machinery/status_display/Destroy() - .=..() - status_displays -= src - -// timed process -/obj/machinery/status_display/process() - if(stat & NOPOWER) - remove_display() - return - if(spookymode) - spookymode = 0 - remove_display() - return - update() - -/obj/machinery/status_display/attack_ai(mob/user) - if(spookymode) return - if(user.stat) return - - if(isAI(user)) //This allows AIs to load any image into the status displays - //Some fluff - if(user.stat) +#define CHARS_PER_LINE 5 +#define FONT_SIZE "5pt" +#define FONT_COLOR "#09f" +#define FONT_STYLE "Arial Black" +#define SCROLL_SPEED 2 + +// Status display +// (formerly Countdown timer display) + +// Use to show shuttle ETA/ETD times +// Alert status +// And arbitrary messages set by comms computer + +#define MODE_BLANK 0 +#define MODE_SHUTTLE_TIMER 1 +#define MODE_MESSAGE 2 +#define MODE_IMAGE 3 +#define MODE_CARGO_TIMER 4 + +var/global/list/status_displays = list() //This list contains both normal status displays, and AI status dispays + +/obj/machinery/status_display + icon = 'icons/obj/status_display.dmi' + icon_state = "frame" + name = "status display" + anchored = 1 + density = 0 + use_power = 1 + idle_power_usage = 10 + var/mode = 1 // 0 = Blank + // 1 = Shuttle timer + // 2 = Arbitrary message(s) + // 3 = alert picture + // 4 = Supply shuttle timer + + var/picture_state // icon_state of alert picture + var/message1 = "" // message line 1 + var/message2 = "" // message line 2 + var/index1 // display index for scrolling messages or 0 if non-scrolling + var/index2 + + var/frequency = 1435 // radio frequency + var/supply_display = 0 // true if a supply shuttle display + + var/friendc = 0 // track if Friend Computer mode + + var/spookymode=0 // Ghosts. + + maptext_height = 26 + maptext_width = 32 + +// new display +// register for radio system +/obj/machinery/status_display/New() + ..() + status_displays |= src + spawn(5) // must wait for map loading to finish + if(radio_controller) + radio_controller.add_object(src, frequency) + +/obj/machinery/status_display/Destroy() + .=..() + status_displays -= src + +// timed process +/obj/machinery/status_display/process() + if(stat & NOPOWER) + remove_display() + return + if(spookymode) + spookymode = 0 + remove_display() + return + update() + +/obj/machinery/status_display/attack_ai(mob/user) + if(spookymode) return + if(user.stat) return + + if(isAI(user)) //This allows AIs to load any image into the status displays + //Some fluff + if(user.stat) to_chat(user, "Unable to connect to [src] (error #408)") - return - if(stat & (BROKEN|NOPOWER)) + return + if(stat & (BROKEN|NOPOWER)) to_chat(user, "Unable to connect to [src] (error #[(stat & BROKEN) ? "120" : "408"])") - return - - var/mob/living/silicon/ai/A = user - - var/choice = input(A, "Select a mode for [src].", "Status display") in list("Blank", "Emergency shuttle timer", "Text message", "Picture", "Supply shuttle timer") - - switch(choice) - if("Blank") - mode = MODE_BLANK - if("Emergency shuttle timer") - mode = MODE_SHUTTLE_TIMER - if("Text message") - var/msg1 = input(A, "Write the first line: ", "Status display", message1) //First line - var/msg2 = input(A, "Write the second line: ", "Status display", message2) //Second line - mode = MODE_MESSAGE - - set_message(msg1, msg2) - if("Picture") - var/new_icon = input(A, "Load an image to be desplayed on [src].", "Status display") in status_display_images - - if(new_icon) - src.mode = MODE_IMAGE - src.set_picture(status_display_images[new_icon]) - if("Supply shuttle timer") - mode = MODE_CARGO_TIMER - -/obj/machinery/status_display/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - set_picture("ai_bsod") - ..(severity) - - // set what is displayed - -/obj/machinery/status_display/proc/update() - if(friendc && mode!=4) //Makes all status displays except supply shuttle timer display the eye -- Urist - set_picture("ai_friend") - return - - switch(mode) - if(MODE_BLANK) //blank - remove_display() - if(MODE_SHUTTLE_TIMER) //emergency shuttle timer - if(emergency_shuttle.online) - var/line1 - var/line2 = get_shuttle_timer() - if(emergency_shuttle.location == 1) - line1 = "-ETD-" - else - line1 = "-ETA-" - if(length(line2) > CHARS_PER_LINE) - line2 = "Error!" - update_display(line1, line2) - else - remove_display() - if(MODE_MESSAGE) //custom messages - remove_display() - - var/line1 - var/line2 - - if(!index1) - line1 = message1 - else - line1 = copytext(message1+"|"+message1, index1, index1+CHARS_PER_LINE) - var/message1_len = length(message1) - index1 += SCROLL_SPEED - if(index1 > message1_len) - index1 -= message1_len - - if(!index2) - line2 = message2 - else - line2 = copytext(message2+"|"+message2, index2, index2+CHARS_PER_LINE) - var/message2_len = length(message2) - index2 += SCROLL_SPEED - if(index2 > message2_len) - index2 -= message2_len - update_display(line1, line2) - if(MODE_CARGO_TIMER) // supply shuttle timer - var/line1 = "SUPPLY" - var/line2 - if(supply_shuttle.moving) - line2 = get_supply_shuttle_timer() - if(length(line2) > CHARS_PER_LINE) - line2 = "Error" - else - if(supply_shuttle.at_station) - line2 = "Docked" - else - line1 = "" - update_display(line1, line2) - -/obj/machinery/status_display/examine(mob/user) - . = ..() - switch(mode) - if(MODE_SHUTTLE_TIMER,MODE_MESSAGE,MODE_CARGO_TIMER) + return + + var/mob/living/silicon/ai/A = user + + var/choice = input(A, "Select a mode for [src].", "Status display") in list("Blank", "Emergency shuttle timer", "Text message", "Picture", "Supply shuttle timer") + + switch(choice) + if("Blank") + mode = MODE_BLANK + if("Emergency shuttle timer") + mode = MODE_SHUTTLE_TIMER + if("Text message") + var/msg1 = input(A, "Write the first line: ", "Status display", message1) //First line + var/msg2 = input(A, "Write the second line: ", "Status display", message2) //Second line + mode = MODE_MESSAGE + + set_message(msg1, msg2) + if("Picture") + var/new_icon = input(A, "Load an image to be desplayed on [src].", "Status display") in status_display_images + + if(new_icon) + src.mode = MODE_IMAGE + src.set_picture(status_display_images[new_icon]) + if("Supply shuttle timer") + mode = MODE_CARGO_TIMER + +/obj/machinery/status_display/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + set_picture("ai_bsod") + ..(severity) + + // set what is displayed + +/obj/machinery/status_display/proc/update() + if(friendc && mode!=4) //Makes all status displays except supply shuttle timer display the eye -- Urist + set_picture("ai_friend") + return + + switch(mode) + if(MODE_BLANK) //blank + remove_display() + if(MODE_SHUTTLE_TIMER) //emergency shuttle timer + if(emergency_shuttle.online) + var/line1 + var/line2 = get_shuttle_timer() + if(emergency_shuttle.location == 1) + line1 = "-ETD-" + else + line1 = "-ETA-" + if(length(line2) > CHARS_PER_LINE) + line2 = "Error!" + update_display(line1, line2) + else + remove_display() + if(MODE_MESSAGE) //custom messages + remove_display() + + var/line1 + var/line2 + + if(!index1) + line1 = message1 + else + line1 = copytext(message1+"|"+message1, index1, index1+CHARS_PER_LINE) + var/message1_len = length(message1) + index1 += SCROLL_SPEED + if(index1 > message1_len) + index1 -= message1_len + + if(!index2) + line2 = message2 + else + line2 = copytext(message2+"|"+message2, index2, index2+CHARS_PER_LINE) + var/message2_len = length(message2) + index2 += SCROLL_SPEED + if(index2 > message2_len) + index2 -= message2_len + update_display(line1, line2) + if(MODE_CARGO_TIMER) // supply shuttle timer + var/line1 = "SUPPLY" + var/line2 + if(supply_shuttle.moving) + line2 = get_supply_shuttle_timer() + if(length(line2) > CHARS_PER_LINE) + line2 = "Error" + else + if(supply_shuttle.at_station) + line2 = "Docked" + else + line1 = "" + update_display(line1, line2) + +/obj/machinery/status_display/examine(mob/user) + . = ..() + switch(mode) + if(MODE_SHUTTLE_TIMER,MODE_MESSAGE,MODE_CARGO_TIMER) to_chat(user, "The display says:
                      \t[message1]
                      \t[message2]
                      ") - - -/obj/machinery/status_display/proc/set_message(m1, m2) - if(m1) - index1 = (length(m1) > CHARS_PER_LINE) - message1 = m1 - else - message1 = "" - index1 = 0 - - if(m2) - index2 = (length(m2) > CHARS_PER_LINE) - message2 = m2 - else - message2 = "" - index2 = 0 - -/obj/machinery/status_display/proc/set_picture(state) - picture_state = state - remove_display() - overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) - -/obj/machinery/status_display/proc/update_display(line1, line2) - var/new_text = {"
                      [line1]
                      [line2]
                      "} - if(maptext != new_text) - maptext = new_text - -/obj/machinery/status_display/proc/get_shuttle_timer() - var/timeleft = emergency_shuttle.timeleft() - if(timeleft) - return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" - return "" - -/obj/machinery/status_display/proc/get_supply_shuttle_timer() - if(supply_shuttle.moving) - var/timeleft = round((supply_shuttle.eta_timeofday - world.timeofday) / 10,1) - if(timeleft < 0) - return "Late" - return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" - return "" - -/obj/machinery/status_display/proc/remove_display() - if(overlays.len) - overlays.len = 0 - if(maptext) - maptext = "" - -/obj/machinery/status_display/receive_signal(datum/signal/signal) - switch(signal.data["command"]) - if("blank") - mode = 0 - - if("shuttle") - mode = 1 - - if("message") - mode = 2 - set_message(signal.data["msg1"], signal.data["msg2"]) - - if("alert") - mode = 3 - set_picture(signal.data["picture_state"]) - - if("supply") - if(supply_display) - mode = 4 - -/obj/machinery/status_display/spook() - if(..()) - spookymode = 1 - -#undef MODE_BLANK -#undef MODE_SHUTTLE_TIMER -#undef MODE_MESSAGE -#undef MODE_IMAGE -#undef MODE_CARGO_TIMER - -//This list contains ALL possible overlays for AI status display. It contains overlay's name (like "Very Happy"), associated with the name of the icon state ("ai_veryhappy"). -var/global/list/ai_emotions = list( - "Very Happy" = "ai_veryhappy", - "Happy" = "ai_happy", - "Neutral" = "ai_neutral", - "Unsure" = "ai_unsure", - "Confused" = "ai_confused", - "Sad" = "ai_sad", - "Surprised" = "ai_surprised", - "Agree" = "ai_agree", - "Disagree" = "ai_disagree", - "Crying" = "ai_cry", - "Awesome" = "ai_awesome", - "BSOD" = "ai_bsod", - "Problems?" = "ai_trollface", - "Facepalm" = "ai_facepalm", - "Friend Computer" = "ai_friend", - "Retro Dorfy" = "ai_urist", - "Modern Dorfy" = "ai_dwarf", - "Beer" = "ai_beer", - "Tribunal" = "ai_tribunal", - "Malf Tribunal" = "ai_tribunal_malf", - "Plump Helmet" = "ai_plump", - "Fish Tank" = "ai_fishtank", -) - -//This list contains ALL possible overlays for both AI status displays, and normal status displays -var/global/list/status_display_images = list( - "NT Logo" = "default", - "Red Alert" = "redalert", - "Biohazard" = "biohazard", - "Lockdown" = "lockdown", - - "Very Happy" = "ai_veryhappy", - "Happy" = "ai_happy", - "Neutral" = "ai_neutral", - "Unsure" = "ai_unsure", - "Confused" = "ai_confused", - "Sad" = "ai_sad", - "Surprised" = "ai_surprised", - "Agree" = "ai_agree", - "Disagree" = "ai_disagree", - "Crying" = "ai_cry", - "Awesome" = "ai_awesome", - "BSOD" = "ai_bsod", - "Problems?" = "ai_trollface", - "Facepalm" = "ai_facepalm", - "Friend Computer" = "ai_friend", - "Retro Dorfy" = "ai_urist", - "Modern Dorfy" = "ai_dwarf", - "Beer" = "ai_beer", - "Tribunal" = "ai_tribunal", - "Malf Tribunal" = "ai_tribunal_malf", - "Plump Helmet" = "ai_plump", - "Fish Tank" = "ai_fishtank",) - -#define MODE_BLANK 0 -#define MODE_EMOTION 1 -#define MODE_BSOD 2 - -/obj/machinery/ai_status_display - icon = 'icons/obj/status_display.dmi' - icon_state = "frame" - name = "AI display" - anchored = 1 - density = 0 - - var/spookymode=0 // Ghosts - - var/mode = 0 // 0 = Blank - // 1 = AI emoticon - // 2 = Blue screen of death - - var/picture_state // icon_state of ai picture - - var/emotion = "Neutral" - -/obj/machinery/ai_status_display/New() - ..() - status_displays |= src - -/obj/machinery/ai_status_display/Destroy() - .=..() - status_displays -= src - -/obj/machinery/ai_status_display/attack_ai(mob/user) - if(spookymode) return - if(user.stat) return - - if(isAI(user)) //This allows AIs to load any image into the status displays - var/mob/living/silicon/ai/A = user - - //Some fluff - if(user.stat) + + +/obj/machinery/status_display/proc/set_message(m1, m2) + if(m1) + index1 = (length(m1) > CHARS_PER_LINE) + message1 = m1 + else + message1 = "" + index1 = 0 + + if(m2) + index2 = (length(m2) > CHARS_PER_LINE) + message2 = m2 + else + message2 = "" + index2 = 0 + +/obj/machinery/status_display/proc/set_picture(state) + picture_state = state + remove_display() + overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) + +/obj/machinery/status_display/proc/update_display(line1, line2) + var/new_text = {"
                      [line1]
                      [line2]
                      "} + if(maptext != new_text) + maptext = new_text + +/obj/machinery/status_display/proc/get_shuttle_timer() + var/timeleft = emergency_shuttle.timeleft() + if(timeleft) + return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" + return "" + +/obj/machinery/status_display/proc/get_supply_shuttle_timer() + if(supply_shuttle.moving) + var/timeleft = round((supply_shuttle.eta_timeofday - world.timeofday) / 10,1) + if(timeleft < 0) + return "Late" + return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" + return "" + +/obj/machinery/status_display/proc/remove_display() + if(overlays.len) + overlays.len = 0 + if(maptext) + maptext = "" + +/obj/machinery/status_display/receive_signal(datum/signal/signal) + switch(signal.data["command"]) + if("blank") + mode = 0 + + if("shuttle") + mode = 1 + + if("message") + mode = 2 + set_message(signal.data["msg1"], signal.data["msg2"]) + + if("alert") + mode = 3 + set_picture(signal.data["picture_state"]) + + if("supply") + if(supply_display) + mode = 4 + +/obj/machinery/status_display/spook() + if(..()) + spookymode = 1 + +#undef MODE_BLANK +#undef MODE_SHUTTLE_TIMER +#undef MODE_MESSAGE +#undef MODE_IMAGE +#undef MODE_CARGO_TIMER + +//This list contains ALL possible overlays for AI status display. It contains overlay's name (like "Very Happy"), associated with the name of the icon state ("ai_veryhappy"). +var/global/list/ai_emotions = list( + "Very Happy" = "ai_veryhappy", + "Happy" = "ai_happy", + "Neutral" = "ai_neutral", + "Unsure" = "ai_unsure", + "Confused" = "ai_confused", + "Sad" = "ai_sad", + "Surprised" = "ai_surprised", + "Agree" = "ai_agree", + "Disagree" = "ai_disagree", + "Crying" = "ai_cry", + "Awesome" = "ai_awesome", + "BSOD" = "ai_bsod", + "Problems?" = "ai_trollface", + "Facepalm" = "ai_facepalm", + "Friend Computer" = "ai_friend", + "Retro Dorfy" = "ai_urist", + "Modern Dorfy" = "ai_dwarf", + "Beer" = "ai_beer", + "Tribunal" = "ai_tribunal", + "Malf Tribunal" = "ai_tribunal_malf", + "Plump Helmet" = "ai_plump", + "Fish Tank" = "ai_fishtank", +) + +//This list contains ALL possible overlays for both AI status displays, and normal status displays +var/global/list/status_display_images = list( + "NT Logo" = "default", + "Red Alert" = "redalert", + "Biohazard" = "biohazard", + "Lockdown" = "lockdown", + + "Very Happy" = "ai_veryhappy", + "Happy" = "ai_happy", + "Neutral" = "ai_neutral", + "Unsure" = "ai_unsure", + "Confused" = "ai_confused", + "Sad" = "ai_sad", + "Surprised" = "ai_surprised", + "Agree" = "ai_agree", + "Disagree" = "ai_disagree", + "Crying" = "ai_cry", + "Awesome" = "ai_awesome", + "BSOD" = "ai_bsod", + "Problems?" = "ai_trollface", + "Facepalm" = "ai_facepalm", + "Friend Computer" = "ai_friend", + "Retro Dorfy" = "ai_urist", + "Modern Dorfy" = "ai_dwarf", + "Beer" = "ai_beer", + "Tribunal" = "ai_tribunal", + "Malf Tribunal" = "ai_tribunal_malf", + "Plump Helmet" = "ai_plump", + "Fish Tank" = "ai_fishtank",) + +#define MODE_BLANK 0 +#define MODE_EMOTION 1 +#define MODE_BSOD 2 + +/obj/machinery/ai_status_display + icon = 'icons/obj/status_display.dmi' + icon_state = "frame" + name = "AI display" + anchored = 1 + density = 0 + + var/spookymode=0 // Ghosts + + var/mode = 0 // 0 = Blank + // 1 = AI emoticon + // 2 = Blue screen of death + + var/picture_state // icon_state of ai picture + + var/emotion = "Neutral" + +/obj/machinery/ai_status_display/New() + ..() + status_displays |= src + +/obj/machinery/ai_status_display/Destroy() + .=..() + status_displays -= src + +/obj/machinery/ai_status_display/attack_ai(mob/user) + if(spookymode) return + if(user.stat) return + + if(isAI(user)) //This allows AIs to load any image into the status displays + var/mob/living/silicon/ai/A = user + + //Some fluff + if(user.stat) to_chat(user, "Unable to connect to [src] (error #408)") - return - if(stat & (BROKEN|NOPOWER)) + return + if(stat & (BROKEN|NOPOWER)) to_chat(user, "Unable to connect to [src] (error #[(stat & BROKEN) ? "120" : "408"])") - return - - var/new_icon = input(A, "Load an image to be desplayed on [src].", "AI status display") in status_display_images - - if(new_icon) - src.mode = MODE_EMOTION - src.emotion = new_icon - src.set_picture(status_display_images[new_icon]) - -/obj/machinery/ai_status_display/process() - if(stat & NOPOWER) - overlays.len = 0 - return - if(spookymode) - spookymode = 0 - overlays.len = 0 - return - - update() - -/obj/machinery/ai_status_display/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - set_picture("ai_bsod") - ..(severity) - -/obj/machinery/ai_status_display/proc/update() - switch(mode) - if(MODE_BLANK) - overlays = list() - - if(MODE_EMOTION) - if(emotion in status_display_images) - set_picture(status_display_images[emotion]) - else - set_picture("ai_bsod") //Can't find icon state for our emotion - throw a BSOD - - if(MODE_BSOD) - set_picture("ai_bsod") - -/obj/machinery/ai_status_display/proc/set_picture(var/state) - picture_state = state - if(overlays.len) - overlays.len = 0 - overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) - -/obj/machinery/ai_status_display/spook() - spookymode = 1 - -#undef MODE_BLANK -#undef MODE_EMOTION -#undef MODE_BSOD - -#undef CHARS_PER_LINE -#undef FOND_SIZE -#undef FONT_COLOR -#undef FONT_STYLE -#undef SCROLL_SPEED + return + + var/new_icon = input(A, "Load an image to be desplayed on [src].", "AI status display") in status_display_images + + if(new_icon) + src.mode = MODE_EMOTION + src.emotion = new_icon + src.set_picture(status_display_images[new_icon]) + +/obj/machinery/ai_status_display/process() + if(stat & NOPOWER) + overlays.len = 0 + return + if(spookymode) + spookymode = 0 + overlays.len = 0 + return + + update() + +/obj/machinery/ai_status_display/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + set_picture("ai_bsod") + ..(severity) + +/obj/machinery/ai_status_display/proc/update() + switch(mode) + if(MODE_BLANK) + overlays = list() + + if(MODE_EMOTION) + if(emotion in status_display_images) + set_picture(status_display_images[emotion]) + else + set_picture("ai_bsod") //Can't find icon state for our emotion - throw a BSOD + + if(MODE_BSOD) + set_picture("ai_bsod") + +/obj/machinery/ai_status_display/proc/set_picture(var/state) + picture_state = state + if(overlays.len) + overlays.len = 0 + overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) + +/obj/machinery/ai_status_display/spook() + spookymode = 1 + +#undef MODE_BLANK +#undef MODE_EMOTION +#undef MODE_BSOD + +#undef CHARS_PER_LINE +#undef FOND_SIZE +#undef FONT_COLOR +#undef FONT_STYLE +#undef SCROLL_SPEED diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 699d35c84cb..6b3011970b3 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -1,657 +1,657 @@ -////////////////////////////////////// -// SUIT STORAGE UNIT ///////////////// -////////////////////////////////////// - - -/obj/machinery/suit_storage_unit - name = "Suit Storage Unit" - desc = "An industrial U-Stor-It Storage unit designed to accomodate all kinds of space suits. Its on-board equipment also allows the user to decontaminate the contents through a UV-ray purging cycle. There's a warning label dangling from the control pad, reading \"STRICTLY NO BIOLOGICALS IN THE CONFINES OF THE UNIT\"." - icon = 'icons/obj/suitstorage.dmi' - icon_state = "suitstorage-closed-00" //order is: [has helmet][has suit] - anchored = 1 - density = 1 - var/mob/living/carbon/human/OCCUPANT = null - var/obj/item/clothing/suit/space/SUIT = null - var/obj/item/clothing/head/helmet/space/HELMET = null - var/obj/item/clothing/mask/MASK = null //All the stuff that's gonna be stored insiiiiiiiiiiiiiiiiiiide, nyoro~n - var/obj/item/clothing/shoes/BOOTS = null - var/SUIT_TYPE = null - var/HELMET_TYPE = null - var/BOOT_TYPE = null - var/MASK_TYPE = null //Erro's idea on standarising SSUs whle keeping creation of other SSU types easy: Make a child SSU, name it something then set the TYPE vars to your desired suit output. New() should take it from there by itself. - var/isopen = 0 - var/islocked = 0 - var/isUV = 0 - var/issuperUV = 0 - var/safetieson = 1 - var/cycletime_left = 0 - - machine_flags = SCREWTOGGLE - - -//The units themselves///////////////// - -/obj/machinery/suit_storage_unit/standard_unit - SUIT_TYPE = /obj/item/clothing/suit/space - HELMET_TYPE = /obj/item/clothing/head/helmet/space - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots - -/obj/machinery/suit_storage_unit/atmos - SUIT_TYPE = /obj/item/clothing/suit/space/rig/atmos - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/atmos - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots/atmos - -/obj/machinery/suit_storage_unit/engie - SUIT_TYPE = /obj/item/clothing/suit/space/rig - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots - -/obj/machinery/suit_storage_unit/elite - SUIT_TYPE = /obj/item/clothing/suit/space/rig/elite - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/elite - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots/elite - -/obj/machinery/suit_storage_unit/mining - SUIT_TYPE = /obj/item/clothing/suit/space/rig/mining - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/mining - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots - -/obj/machinery/suit_storage_unit/excavation - SUIT_TYPE = /obj/item/clothing/suit/space/anomaly - HELMET_TYPE = /obj/item/clothing/head/helmet/space/anomaly - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots - -/obj/machinery/suit_storage_unit/security - SUIT_TYPE = /obj/item/clothing/suit/space/rig/security - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/security - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots - -/obj/machinery/suit_storage_unit/medical - SUIT_TYPE = /obj/item/clothing/suit/space/rig/medical - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/medical - MASK_TYPE = /obj/item/clothing/mask/breath - BOOT_TYPE = /obj/item/clothing/shoes/magboots - -/obj/machinery/suit_storage_unit/meteor_eod //Used for meteor rounds - SUIT_TYPE = /obj/item/clothing/suit/bomb_suit - HELMET_TYPE = /obj/item/clothing/head/bomb_hood - MASK_TYPE = /obj/item/clothing/mask/gas - BOOT_TYPE = /obj/item/clothing/shoes/jackboots - -/obj/machinery/suit_storage_unit/New() - . = ..() - src.update_icon() - if(SUIT_TYPE) - SUIT = new SUIT_TYPE(src) - if(HELMET_TYPE) - HELMET = new HELMET_TYPE(src) - if(MASK_TYPE) - MASK = new MASK_TYPE(src) - if(BOOT_TYPE) - BOOTS = new BOOT_TYPE(src) - -/obj/machinery/suit_storage_unit/update_icon() - if((stat & NOPOWER) || (stat & BROKEN)) - icon_state = "suitstorage-off" - return - if(!isopen) - icon_state = "suitstorage-closed-[issuperUV][isUV]" - else - icon_state = "suitstorage-open-[HELMET ? "1" : "0"][SUIT ? "1" : "0"]" - -/obj/machinery/suit_storage_unit/power_change() - if( powered() ) - stat &= ~NOPOWER - src.update_icon() - else - spawn(rand(0, 15)) - stat |= NOPOWER - src.islocked = 0 - src.isopen = 1 - src.update_icon() - - -/obj/machinery/suit_storage_unit/ex_act(severity) - switch(severity) - if(1.0) - if(prob(50)) - src.dump_everything() //So suits dont survive all the time - qdel(src) - return - if(2.0) - if(prob(50)) - src.dump_everything() - qdel(src) - return - else - return - return - - -/obj/machinery/suit_storage_unit/attack_hand(mob/user as mob) - var/dat - if(..()) - return - if(stat & NOPOWER) - return - if(src.panel_open) //The maintenance panel is open. Time for some shady stuff - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:100: dat+= "Suit storage unit: Maintenance panel" - dat += {"Suit storage unit: Maintenance panel - Maintenance panel controls
                      - The panel is ridden with controls, button and meters, labeled in strange signs and symbols that
                      you cannot understand. Probably the manufactoring world's language.
                      Among other things, a few controls catch your eye.

                      "} - // END AUTOFIX - dat+= text("A small dial with a \"ë\" symbol embroidded on it. It's pointing towards a gauge that reads [].
                      Turn towards []
                      ",(src.issuperUV ? "15nm" : "185nm"),src,(src.issuperUV ? "185nm" : "15nm") ) - dat+= text("A thick old-style button, with 2 grimy LED lights next to it. The [] LED is on.
                      Press button",(src.safetieson? "GREEN" : "RED"),src) - dat+= text("

                      Close panel", user) - //user << browse(dat, "window=ssu_m_panel;size=400x500") - //onclose(user, "ssu_m_panel") - else if(src.isUV) //The thing is running its cauterisation cycle. You have to wait. - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:109: dat += "Suit storage unit" - dat += {"Suit storage unit - Unit is cauterising contents with selected UV ray intensity. Please wait.
                      "} - // END AUTOFIX - //dat+= "Cycle end in: [src.cycletimeleft()] seconds. " - //user << browse(dat, "window=ssu_cycling_panel;size=400x500") - //onclose(user, "ssu_cycling_panel") - - else - if(!(stat & BROKEN)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:117: dat+= "Suit storage unit" - dat += {"Suit storage unit - U-Stor-It Suit Storage Unit, model DS1900
                      - Welcome to the Unit control panel.
                      "} - // END AUTOFIX - dat+= text("Helmet storage compartment: []
                      ",(src.HELMET ? HELMET.name : "
                      No helmet detected.") ) - if(HELMET && src.isopen) - dat+=text("Dispense helmet
                      ",src) - dat+= text("Suit storage compartment: []
                      ",(src.SUIT ? SUIT.name : "
                      No exosuit detected.") ) - if(SUIT && src.isopen) - dat+=text("Dispense suit
                      ",src) - dat+= text("Breathmask storage compartment: []
                      ",(src.MASK ? MASK.name : "
                      No breathmask detected.") ) - if(MASK && src.isopen) - dat+=text("Dispense mask
                      ",src) - dat+= text("Boot storage compartment: []
                      ",(src.BOOTS ? BOOTS.name : "
                      No boots detected.") ) - if(BOOTS && src.isopen) - dat+=text("Dispense boots
                      ",src) - if(src.OCCUPANT) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:130: dat+= "
                      WARNING: Biological entity detected inside the Unit's storage. Please remove.
                      " - dat += {"
                      WARNING: Biological entity detected inside the Unit's storage. Please remove.
                      - Eject extra load"} - // END AUTOFIX - dat+= text("
                      Unit is: [] - [] Unit ",(src.isopen ? "Open" : "Closed"),src,(src.isopen ? "Close" : "Open")) - if(src.isopen) - dat+="
                      " - else - dat+= text(" - *[] Unit*
                      ",src,(src.islocked ? "Unlock" : "Lock") ) - dat+= text("Unit status: []",(src.islocked? "**LOCKED**
                      " : "**UNLOCKED**
                      ") ) - dat+= text("Start Disinfection cycle
                      ",src) - dat += text("

                      Close control panel", user) - //user << browse(dat, "window=Suit Storage Unit;size=400x500") - //onclose(user, "Suit Storage Unit") - else //Ohhhh shit it's dirty or broken! Let's inform the guy. - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:143: dat+= "Suit storage unit" - dat += {"Suit storage unit - Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.

                      "} - // END AUTOFIX - dat+= text("
                      Close control panel", user) - //user << browse(dat, "window=suit_storage_unit;size=400x500") - //onclose(user, "suit_storage_unit") - - user << browse(dat, "window=suit_storage_unit;size=400x500") - onclose(user, "suit_storage_unit") - return - - -/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc - if(..()) - return 1 - else - usr.set_machine(src) - if (href_list["toggleUV"]) - src.toggleUV(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["togglesafeties"]) - src.togglesafeties(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["dispense_helmet"]) - src.dispense_helmet(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["dispense_suit"]) - src.dispense_suit(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["dispense_mask"]) - src.dispense_mask(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["dispense_boots"]) - src.dispense_boots(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["toggle_open"]) - src.toggle_open(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["toggle_lock"]) - src.toggle_lock(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["start_UV"]) - src.start_UV(usr) - src.updateUsrDialog() - src.update_icon() - if (href_list["eject_guy"]) - src.eject_occupant(usr) - src.updateUsrDialog() - src.update_icon() - /*if (href_list["refresh"]) - src.updateUsrDialog()*/ - src.add_fingerprint(usr) - return - - -/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user as mob) -// var/protected = 0 -// var/mob/living/carbon/human/H = user - if(!src.panel_open) - return - - /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(istype(G,/obj/item/clothing/gloves/yellow)) - protected = 1 - - if(!protected) - playsound(get_turf(src), "sparks", 75, 1, -1) - to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") - return*/ - else //welp, the guy is protected, we can continue - if(src.issuperUV) - to_chat(user, "You slide the dial back towards \"185nm\".") - src.issuperUV = 0 - else - to_chat(user, "You crank the dial all the way up to \"15nm\".") - src.issuperUV = 1 - return - - -/obj/machinery/suit_storage_unit/proc/togglesafeties(mob/user as mob) -// var/protected = 0 -// var/mob/living/carbon/human/H = user - if(!src.panel_open) //Needed check due to bugs - return - - /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(istype(G,/obj/item/clothing/gloves/yellow) ) - protected = 1 - - if(!protected) - playsound(get_turf(src), "sparks", 75, 1, -1) - to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") - return*/ - else - to_chat(user, "You push the button. The coloured LED next to it changes.") - src.safetieson = !src.safetieson - - -/obj/machinery/suit_storage_unit/proc/dispense_helmet(mob/user as mob) - if(!src.HELMET) - return //Do I even need this sanity check? Nyoro~n - else - src.HELMET.loc = src.loc - src.HELMET = null - return - - -/obj/machinery/suit_storage_unit/proc/dispense_suit(mob/user as mob) - if(!src.SUIT) - return - else - src.SUIT.loc = src.loc - src.SUIT = null - return - - -/obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user as mob) - if(!src.MASK) - return - else - src.MASK.loc = src.loc - src.MASK = null - return - - -/obj/machinery/suit_storage_unit/proc/dispense_boots(mob/user as mob) - if(!src.BOOTS) - return - else - src.BOOTS.loc = src.loc - src.BOOTS = null - return - - -/obj/machinery/suit_storage_unit/proc/dump_everything() - src.islocked = 0 //locks go free - if(src.SUIT) - src.SUIT.loc = src.loc - src.SUIT = null - if(src.HELMET) - src.HELMET.loc = src.loc - src.HELMET = null - if(src.MASK) - src.MASK.loc = src.loc - src.MASK = null - if(src.BOOTS) - src.BOOTS.loc = src.loc - src.BOOTS = null - if(src.OCCUPANT) - src.eject_occupant(OCCUPANT) - return - - -/obj/machinery/suit_storage_unit/proc/toggle_open(mob/user as mob) - if(src.islocked || src.isUV) - to_chat(user, "Unable to open unit.") - return - if(src.OCCUPANT) - src.eject_occupant(user) - return // eject_occupant opens the door, so we need to return - src.isopen = !src.isopen - return - - -/obj/machinery/suit_storage_unit/proc/toggle_lock(mob/user as mob) - if(src.OCCUPANT && src.safetieson) - to_chat(user, "The Unit's safety protocols disallow locking when a biological form is detected inside its compartments.") - return - if(src.isopen) - return - src.islocked = !src.islocked - return - - -/obj/machinery/suit_storage_unit/proc/start_UV(mob/user as mob) - if(src.isUV || src.isopen) //I'm bored of all these sanity checks - return - if(src.OCCUPANT && src.safetieson) - to_chat(user, "WARNING: Biological entity detected in the confines of the Unit's storage. Cannot initiate cycle.") - return - if(!src.HELMET && !src.MASK && !src.SUIT && !BOOTS && !src.OCCUPANT ) //shit's empty yo - to_chat(user, "Unit storage bays empty. Nothing to disinfect -- Aborting.") - return - to_chat(user, "You start the Unit's cauterisation cycle.") - src.cycletime_left = 20 - src.isUV = 1 - if(src.OCCUPANT && !src.islocked) - src.islocked = 1 //Let's lock it for good measure - src.update_icon() - src.updateUsrDialog() - - var/i //our counter - for(i=0,i<4,i++) - sleep(50) - if(src.OCCUPANT) - if(src.issuperUV) - var/burndamage = rand(28,35) - OCCUPANT.take_organ_damage(0,burndamage) - OCCUPANT.emote("scream",,, 1) - else - var/burndamage = rand(6,10) - OCCUPANT.take_organ_damage(0,burndamage) - OCCUPANT.emote("scream",,, 1) - if(i==3) //End of the cycle - if(!src.issuperUV) - if(src.HELMET) - HELMET.clean_blood() - HELMET.decontaminate() - if(src.SUIT) - SUIT.clean_blood() - SUIT.decontaminate() - if(src.MASK) - MASK.clean_blood() - MASK.decontaminate() - if(src.BOOTS) - BOOTS.clean_blood() - BOOTS.decontaminate() - else //It was supercycling, destroy everything - if(src.HELMET) - src.HELMET = null - if(src.SUIT) - src.SUIT = null - if(src.MASK) - src.MASK = null - if(src.BOOTS) - src.BOOTS = null - visible_message("With a loud whining noise, the Suit Storage Unit's door grinds open. Puffs of ashen smoke come out of its chamber.", 2) //spooky - stat |= BROKEN - src.isopen = 1 - src.islocked = 0 - src.eject_occupant(OCCUPANT) //Mixing up these two lines causes bug. DO NOT DO IT. - src.isUV = 0 //Cycle ends - src.update_icon() - src.updateUsrDialog() - -/obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user as mob) - if (src.islocked) - return - - if (!src.OCCUPANT) - return -// for(var/obj/O in src) -// O.loc = src.loc - - if (src.OCCUPANT.client) - if(user != OCCUPANT) - to_chat(OCCUPANT, "The machine kicks you out!") - if(user.loc != src.loc) - to_chat(OCCUPANT, "You leave the not-so-cozy confines of the SSU.") - - src.OCCUPANT.client.eye = src.OCCUPANT.client.mob - src.OCCUPANT.client.perspective = MOB_PERSPECTIVE - src.OCCUPANT.loc = src.loc - src.OCCUPANT = null - if(!src.isopen) - src.isopen = 1 - src.update_icon() - return - - -/obj/machinery/suit_storage_unit/verb/get_out() - set name = "Eject Suit Storage Unit" - set category = "Object" - set src in oview(1) - - if (usr.isUnconscious()) - return - src.eject_occupant(usr) - add_fingerprint(usr) - src.updateUsrDialog() - src.update_icon() - return - - -/obj/machinery/suit_storage_unit/verb/move_inside() - set name = "Hide in Suit Storage Unit" - set category = "Object" - set src in oview(1) - - if (usr.isUnconscious()) - return - if (!src.isopen) - to_chat(usr, "The unit's doors are shut.") - return - if ((stat & NOPOWER) || (stat & BROKEN)) - to_chat(usr, "The unit is not operational.") - return - if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) || BOOTS ) - to_chat(usr, "It's too cluttered inside for you to fit in!") - return - visible_message("[usr] starts squeezing into the suit storage unit!", 2) //spooky - if(do_after(usr, src, 10)) - usr.stop_pulling() - usr.client.perspective = EYE_PERSPECTIVE - usr.client.eye = src - usr.loc = src -// usr.metabslow = 1 - src.OCCUPANT = usr - src.isopen = 0 //Close the thing after the guy gets inside - src.update_icon() - -// for(var/obj/O in src) -// del(O) - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - else - src.OCCUPANT = null //Testing this as a backup sanity test - return - -/obj/machinery/suit_storage_unit/togglePanelOpen(var/obj/toggleitem, mob/user) - ..() - src.updateUsrDialog() - -/obj/machinery/suit_storage_unit/attackby(obj/item/I as obj, mob/user as mob) - if((stat & BROKEN) && issolder(I)) - var/obj/item/weapon/solder/S = I - if(!S.remove_fuel(4,user)) - return - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - if(do_after(user, src,40)) - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - stat &= !BROKEN - to_chat(user, "You repair the blown out electronics in the suit storage unit.") - if((stat & NOPOWER) && iscrowbar(I) && !islocked) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You begin prying the equipment out of the suit storage unit") - if(do_after(user, src,20)) - dump_everything() - update_icon() - if(stat & NOPOWER) - return - if(..()) - return 1 - if ( istype(I, /obj/item/weapon/grab) ) - var/obj/item/weapon/grab/G = I - if( !(ismob(G.affecting)) ) - return - if (!src.isopen) - to_chat(usr, "The unit's doors are shut.") - return - if ((stat & NOPOWER) || (stat & BROKEN)) - to_chat(usr, "The unit is not operational.") - return - if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) || BOOTS) //Unit needs to be absolutely empty - to_chat(user, "The unit's storage area is too cluttered.") - return - visible_message("[user] starts putting [G.affecting.name] into the Suit Storage Unit.", 2) //spooky - if(do_after(user, src, 20)) - if(!G || !G.affecting) return //derpcheck - var/mob/M = G.affecting - if (M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.loc = src - src.OCCUPANT = M - src.isopen = 0 //close ittt - - //for(var/obj/O in src) - // O.loc = src.loc - src.add_fingerprint(user) - qdel(G) - G = null - src.updateUsrDialog() - src.update_icon() - return - return - if( istype(I,/obj/item/clothing/suit/space) ) - if(!src.isopen) - return - var/obj/item/clothing/suit/space/S = I - if(src.SUIT) - to_chat(user, "The unit already contains a suit.") - return - if(user.drop_item(S, src)) - to_chat(user, "You load the [S.name] into the storage compartment.") - src.SUIT = S - src.update_icon() - src.updateUsrDialog() - return - if( istype(I,/obj/item/clothing/head/helmet) ) - if(!src.isopen) - return - var/obj/item/clothing/head/helmet/H = I - if(src.HELMET) - to_chat(user, "The unit already contains a helmet.") - return - if(user.drop_item(H, src)) - to_chat(user, "You load the [H.name] into the storage compartment.") - src.HELMET = H - src.update_icon() - src.updateUsrDialog() - return - if( istype(I,/obj/item/clothing/mask) ) - if(!src.isopen) - return - var/obj/item/clothing/mask/M = I - if(src.MASK) - to_chat(user, "The unit already contains a mask.") - return - if(user.drop_item(M, src)) - to_chat(user, "You load the [M.name] into the storage compartment.") - src.MASK = M - src.update_icon() - src.updateUsrDialog() - return - if( istype(I,/obj/item/clothing/shoes) ) - if(!src.isopen) - return - var/obj/item/clothing/shoes/M = I - if(src.BOOTS) - to_chat(user, "The unit already contains shoes.") - return - if(user.drop_item(M, src)) - to_chat(user, "You load \the [M.name] into the storage compartment.") - src.BOOTS = M - src.update_icon() - src.updateUsrDialog() - return - src.update_icon() - src.updateUsrDialog() - return - - -/obj/machinery/suit_storage_unit/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - - -/obj/machinery/suit_storage_unit/attack_paw(mob/user as mob) - to_chat(user, "The console controls are far too complicated for your tiny brain!") - return - - -//////////////////////////////REMINDER: Make it lock once you place some fucker inside. +////////////////////////////////////// +// SUIT STORAGE UNIT ///////////////// +////////////////////////////////////// + + +/obj/machinery/suit_storage_unit + name = "Suit Storage Unit" + desc = "An industrial U-Stor-It Storage unit designed to accomodate all kinds of space suits. Its on-board equipment also allows the user to decontaminate the contents through a UV-ray purging cycle. There's a warning label dangling from the control pad, reading \"STRICTLY NO BIOLOGICALS IN THE CONFINES OF THE UNIT\"." + icon = 'icons/obj/suitstorage.dmi' + icon_state = "suitstorage-closed-00" //order is: [has helmet][has suit] + anchored = 1 + density = 1 + var/mob/living/carbon/human/OCCUPANT = null + var/obj/item/clothing/suit/space/SUIT = null + var/obj/item/clothing/head/helmet/space/HELMET = null + var/obj/item/clothing/mask/MASK = null //All the stuff that's gonna be stored insiiiiiiiiiiiiiiiiiiide, nyoro~n + var/obj/item/clothing/shoes/BOOTS = null + var/SUIT_TYPE = null + var/HELMET_TYPE = null + var/BOOT_TYPE = null + var/MASK_TYPE = null //Erro's idea on standarising SSUs whle keeping creation of other SSU types easy: Make a child SSU, name it something then set the TYPE vars to your desired suit output. New() should take it from there by itself. + var/isopen = 0 + var/islocked = 0 + var/isUV = 0 + var/issuperUV = 0 + var/safetieson = 1 + var/cycletime_left = 0 + + machine_flags = SCREWTOGGLE + + +//The units themselves///////////////// + +/obj/machinery/suit_storage_unit/standard_unit + SUIT_TYPE = /obj/item/clothing/suit/space + HELMET_TYPE = /obj/item/clothing/head/helmet/space + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots + +/obj/machinery/suit_storage_unit/atmos + SUIT_TYPE = /obj/item/clothing/suit/space/rig/atmos + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/atmos + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots/atmos + +/obj/machinery/suit_storage_unit/engie + SUIT_TYPE = /obj/item/clothing/suit/space/rig + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots + +/obj/machinery/suit_storage_unit/elite + SUIT_TYPE = /obj/item/clothing/suit/space/rig/elite + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/elite + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots/elite + +/obj/machinery/suit_storage_unit/mining + SUIT_TYPE = /obj/item/clothing/suit/space/rig/mining + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/mining + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots + +/obj/machinery/suit_storage_unit/excavation + SUIT_TYPE = /obj/item/clothing/suit/space/anomaly + HELMET_TYPE = /obj/item/clothing/head/helmet/space/anomaly + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots + +/obj/machinery/suit_storage_unit/security + SUIT_TYPE = /obj/item/clothing/suit/space/rig/security + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/security + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots + +/obj/machinery/suit_storage_unit/medical + SUIT_TYPE = /obj/item/clothing/suit/space/rig/medical + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/medical + MASK_TYPE = /obj/item/clothing/mask/breath + BOOT_TYPE = /obj/item/clothing/shoes/magboots + +/obj/machinery/suit_storage_unit/meteor_eod //Used for meteor rounds + SUIT_TYPE = /obj/item/clothing/suit/bomb_suit + HELMET_TYPE = /obj/item/clothing/head/bomb_hood + MASK_TYPE = /obj/item/clothing/mask/gas + BOOT_TYPE = /obj/item/clothing/shoes/jackboots + +/obj/machinery/suit_storage_unit/New() + . = ..() + src.update_icon() + if(SUIT_TYPE) + SUIT = new SUIT_TYPE(src) + if(HELMET_TYPE) + HELMET = new HELMET_TYPE(src) + if(MASK_TYPE) + MASK = new MASK_TYPE(src) + if(BOOT_TYPE) + BOOTS = new BOOT_TYPE(src) + +/obj/machinery/suit_storage_unit/update_icon() + if((stat & NOPOWER) || (stat & BROKEN)) + icon_state = "suitstorage-off" + return + if(!isopen) + icon_state = "suitstorage-closed-[issuperUV][isUV]" + else + icon_state = "suitstorage-open-[HELMET ? "1" : "0"][SUIT ? "1" : "0"]" + +/obj/machinery/suit_storage_unit/power_change() + if( powered() ) + stat &= ~NOPOWER + src.update_icon() + else + spawn(rand(0, 15)) + stat |= NOPOWER + src.islocked = 0 + src.isopen = 1 + src.update_icon() + + +/obj/machinery/suit_storage_unit/ex_act(severity) + switch(severity) + if(1.0) + if(prob(50)) + src.dump_everything() //So suits dont survive all the time + qdel(src) + return + if(2.0) + if(prob(50)) + src.dump_everything() + qdel(src) + return + else + return + return + + +/obj/machinery/suit_storage_unit/attack_hand(mob/user as mob) + var/dat + if(..()) + return + if(stat & NOPOWER) + return + if(src.panel_open) //The maintenance panel is open. Time for some shady stuff + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:100: dat+= "Suit storage unit: Maintenance panel" + dat += {"Suit storage unit: Maintenance panel + Maintenance panel controls
                      + The panel is ridden with controls, button and meters, labeled in strange signs and symbols that
                      you cannot understand. Probably the manufactoring world's language.
                      Among other things, a few controls catch your eye.

                      "} + // END AUTOFIX + dat+= text("A small dial with a \"ë\" symbol embroidded on it. It's pointing towards a gauge that reads [].
                      Turn towards []
                      ",(src.issuperUV ? "15nm" : "185nm"),src,(src.issuperUV ? "185nm" : "15nm") ) + dat+= text("A thick old-style button, with 2 grimy LED lights next to it. The [] LED is on.
                      Press button",(src.safetieson? "GREEN" : "RED"),src) + dat+= text("

                      Close panel", user) + //user << browse(dat, "window=ssu_m_panel;size=400x500") + //onclose(user, "ssu_m_panel") + else if(src.isUV) //The thing is running its cauterisation cycle. You have to wait. + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:109: dat += "Suit storage unit" + dat += {"Suit storage unit + Unit is cauterising contents with selected UV ray intensity. Please wait.
                      "} + // END AUTOFIX + //dat+= "Cycle end in: [src.cycletimeleft()] seconds. " + //user << browse(dat, "window=ssu_cycling_panel;size=400x500") + //onclose(user, "ssu_cycling_panel") + + else + if(!(stat & BROKEN)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:117: dat+= "Suit storage unit" + dat += {"Suit storage unit + U-Stor-It Suit Storage Unit, model DS1900
                      + Welcome to the Unit control panel.
                      "} + // END AUTOFIX + dat+= text("Helmet storage compartment: []
                      ",(src.HELMET ? HELMET.name : "
                      No helmet detected.") ) + if(HELMET && src.isopen) + dat+=text("Dispense helmet
                      ",src) + dat+= text("Suit storage compartment: []
                      ",(src.SUIT ? SUIT.name : "
                      No exosuit detected.") ) + if(SUIT && src.isopen) + dat+=text("Dispense suit
                      ",src) + dat+= text("Breathmask storage compartment: []
                      ",(src.MASK ? MASK.name : "
                      No breathmask detected.") ) + if(MASK && src.isopen) + dat+=text("Dispense mask
                      ",src) + dat+= text("Boot storage compartment: []
                      ",(src.BOOTS ? BOOTS.name : "
                      No boots detected.") ) + if(BOOTS && src.isopen) + dat+=text("Dispense boots
                      ",src) + if(src.OCCUPANT) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:130: dat+= "
                      WARNING: Biological entity detected inside the Unit's storage. Please remove.
                      " + dat += {"
                      WARNING: Biological entity detected inside the Unit's storage. Please remove.
                      + Eject extra load"} + // END AUTOFIX + dat+= text("
                      Unit is: [] - [] Unit ",(src.isopen ? "Open" : "Closed"),src,(src.isopen ? "Close" : "Open")) + if(src.isopen) + dat+="
                      " + else + dat+= text(" - *[] Unit*
                      ",src,(src.islocked ? "Unlock" : "Lock") ) + dat+= text("Unit status: []",(src.islocked? "**LOCKED**
                      " : "**UNLOCKED**
                      ") ) + dat+= text("Start Disinfection cycle
                      ",src) + dat += text("

                      Close control panel", user) + //user << browse(dat, "window=Suit Storage Unit;size=400x500") + //onclose(user, "Suit Storage Unit") + else //Ohhhh shit it's dirty or broken! Let's inform the guy. + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\suit_storage_unit.dm:143: dat+= "Suit storage unit" + dat += {"Suit storage unit + Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.

                      "} + // END AUTOFIX + dat+= text("
                      Close control panel", user) + //user << browse(dat, "window=suit_storage_unit;size=400x500") + //onclose(user, "suit_storage_unit") + + user << browse(dat, "window=suit_storage_unit;size=400x500") + onclose(user, "suit_storage_unit") + return + + +/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc + if(..()) + return 1 + else + usr.set_machine(src) + if (href_list["toggleUV"]) + src.toggleUV(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["togglesafeties"]) + src.togglesafeties(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["dispense_helmet"]) + src.dispense_helmet(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["dispense_suit"]) + src.dispense_suit(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["dispense_mask"]) + src.dispense_mask(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["dispense_boots"]) + src.dispense_boots(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["toggle_open"]) + src.toggle_open(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["toggle_lock"]) + src.toggle_lock(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["start_UV"]) + src.start_UV(usr) + src.updateUsrDialog() + src.update_icon() + if (href_list["eject_guy"]) + src.eject_occupant(usr) + src.updateUsrDialog() + src.update_icon() + /*if (href_list["refresh"]) + src.updateUsrDialog()*/ + src.add_fingerprint(usr) + return + + +/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user as mob) +// var/protected = 0 +// var/mob/living/carbon/human/H = user + if(!src.panel_open) + return + + /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(istype(G,/obj/item/clothing/gloves/yellow)) + protected = 1 + + if(!protected) + playsound(get_turf(src), "sparks", 75, 1, -1) + to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") + return*/ + else //welp, the guy is protected, we can continue + if(src.issuperUV) + to_chat(user, "You slide the dial back towards \"185nm\".") + src.issuperUV = 0 + else + to_chat(user, "You crank the dial all the way up to \"15nm\".") + src.issuperUV = 1 + return + + +/obj/machinery/suit_storage_unit/proc/togglesafeties(mob/user as mob) +// var/protected = 0 +// var/mob/living/carbon/human/H = user + if(!src.panel_open) //Needed check due to bugs + return + + /*if(istype(H)) //Let's check if the guy's wearing electrically insulated gloves + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(istype(G,/obj/item/clothing/gloves/yellow) ) + protected = 1 + + if(!protected) + playsound(get_turf(src), "sparks", 75, 1, -1) + to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") + return*/ + else + to_chat(user, "You push the button. The coloured LED next to it changes.") + src.safetieson = !src.safetieson + + +/obj/machinery/suit_storage_unit/proc/dispense_helmet(mob/user as mob) + if(!src.HELMET) + return //Do I even need this sanity check? Nyoro~n + else + src.HELMET.loc = src.loc + src.HELMET = null + return + + +/obj/machinery/suit_storage_unit/proc/dispense_suit(mob/user as mob) + if(!src.SUIT) + return + else + src.SUIT.loc = src.loc + src.SUIT = null + return + + +/obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user as mob) + if(!src.MASK) + return + else + src.MASK.loc = src.loc + src.MASK = null + return + + +/obj/machinery/suit_storage_unit/proc/dispense_boots(mob/user as mob) + if(!src.BOOTS) + return + else + src.BOOTS.loc = src.loc + src.BOOTS = null + return + + +/obj/machinery/suit_storage_unit/proc/dump_everything() + src.islocked = 0 //locks go free + if(src.SUIT) + src.SUIT.loc = src.loc + src.SUIT = null + if(src.HELMET) + src.HELMET.loc = src.loc + src.HELMET = null + if(src.MASK) + src.MASK.loc = src.loc + src.MASK = null + if(src.BOOTS) + src.BOOTS.loc = src.loc + src.BOOTS = null + if(src.OCCUPANT) + src.eject_occupant(OCCUPANT) + return + + +/obj/machinery/suit_storage_unit/proc/toggle_open(mob/user as mob) + if(src.islocked || src.isUV) + to_chat(user, "Unable to open unit.") + return + if(src.OCCUPANT) + src.eject_occupant(user) + return // eject_occupant opens the door, so we need to return + src.isopen = !src.isopen + return + + +/obj/machinery/suit_storage_unit/proc/toggle_lock(mob/user as mob) + if(src.OCCUPANT && src.safetieson) + to_chat(user, "The Unit's safety protocols disallow locking when a biological form is detected inside its compartments.") + return + if(src.isopen) + return + src.islocked = !src.islocked + return + + +/obj/machinery/suit_storage_unit/proc/start_UV(mob/user as mob) + if(src.isUV || src.isopen) //I'm bored of all these sanity checks + return + if(src.OCCUPANT && src.safetieson) + to_chat(user, "WARNING: Biological entity detected in the confines of the Unit's storage. Cannot initiate cycle.") + return + if(!src.HELMET && !src.MASK && !src.SUIT && !BOOTS && !src.OCCUPANT ) //shit's empty yo + to_chat(user, "Unit storage bays empty. Nothing to disinfect -- Aborting.") + return + to_chat(user, "You start the Unit's cauterisation cycle.") + src.cycletime_left = 20 + src.isUV = 1 + if(src.OCCUPANT && !src.islocked) + src.islocked = 1 //Let's lock it for good measure + src.update_icon() + src.updateUsrDialog() + + var/i //our counter + for(i=0,i<4,i++) + sleep(50) + if(src.OCCUPANT) + if(src.issuperUV) + var/burndamage = rand(28,35) + OCCUPANT.take_organ_damage(0,burndamage) + OCCUPANT.emote("scream",,, 1) + else + var/burndamage = rand(6,10) + OCCUPANT.take_organ_damage(0,burndamage) + OCCUPANT.emote("scream",,, 1) + if(i==3) //End of the cycle + if(!src.issuperUV) + if(src.HELMET) + HELMET.clean_blood() + HELMET.decontaminate() + if(src.SUIT) + SUIT.clean_blood() + SUIT.decontaminate() + if(src.MASK) + MASK.clean_blood() + MASK.decontaminate() + if(src.BOOTS) + BOOTS.clean_blood() + BOOTS.decontaminate() + else //It was supercycling, destroy everything + if(src.HELMET) + src.HELMET = null + if(src.SUIT) + src.SUIT = null + if(src.MASK) + src.MASK = null + if(src.BOOTS) + src.BOOTS = null + visible_message("With a loud whining noise, the Suit Storage Unit's door grinds open. Puffs of ashen smoke come out of its chamber.", 2) //spooky + stat |= BROKEN + src.isopen = 1 + src.islocked = 0 + src.eject_occupant(OCCUPANT) //Mixing up these two lines causes bug. DO NOT DO IT. + src.isUV = 0 //Cycle ends + src.update_icon() + src.updateUsrDialog() + +/obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user as mob) + if (src.islocked) + return + + if (!src.OCCUPANT) + return +// for(var/obj/O in src) +// O.loc = src.loc + + if (src.OCCUPANT.client) + if(user != OCCUPANT) + to_chat(OCCUPANT, "The machine kicks you out!") + if(user.loc != src.loc) + to_chat(OCCUPANT, "You leave the not-so-cozy confines of the SSU.") + + src.OCCUPANT.client.eye = src.OCCUPANT.client.mob + src.OCCUPANT.client.perspective = MOB_PERSPECTIVE + src.OCCUPANT.loc = src.loc + src.OCCUPANT = null + if(!src.isopen) + src.isopen = 1 + src.update_icon() + return + + +/obj/machinery/suit_storage_unit/verb/get_out() + set name = "Eject Suit Storage Unit" + set category = "Object" + set src in oview(1) + + if (usr.isUnconscious()) + return + src.eject_occupant(usr) + add_fingerprint(usr) + src.updateUsrDialog() + src.update_icon() + return + + +/obj/machinery/suit_storage_unit/verb/move_inside() + set name = "Hide in Suit Storage Unit" + set category = "Object" + set src in oview(1) + + if (usr.isUnconscious()) + return + if (!src.isopen) + to_chat(usr, "The unit's doors are shut.") + return + if ((stat & NOPOWER) || (stat & BROKEN)) + to_chat(usr, "The unit is not operational.") + return + if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) || BOOTS ) + to_chat(usr, "It's too cluttered inside for you to fit in!") + return + visible_message("[usr] starts squeezing into the suit storage unit!", 2) //spooky + if(do_after(usr, src, 10)) + usr.stop_pulling() + usr.client.perspective = EYE_PERSPECTIVE + usr.client.eye = src + usr.loc = src +// usr.metabslow = 1 + src.OCCUPANT = usr + src.isopen = 0 //Close the thing after the guy gets inside + src.update_icon() + +// for(var/obj/O in src) +// del(O) + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + else + src.OCCUPANT = null //Testing this as a backup sanity test + return + +/obj/machinery/suit_storage_unit/togglePanelOpen(var/obj/toggleitem, mob/user) + ..() + src.updateUsrDialog() + +/obj/machinery/suit_storage_unit/attackby(obj/item/I as obj, mob/user as mob) + if((stat & BROKEN) && issolder(I)) + var/obj/item/weapon/solder/S = I + if(!S.remove_fuel(4,user)) + return + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + if(do_after(user, src,40)) + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + stat &= !BROKEN + to_chat(user, "You repair the blown out electronics in the suit storage unit.") + if((stat & NOPOWER) && iscrowbar(I) && !islocked) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You begin prying the equipment out of the suit storage unit") + if(do_after(user, src,20)) + dump_everything() + update_icon() + if(stat & NOPOWER) + return + if(..()) + return 1 + if ( istype(I, /obj/item/weapon/grab) ) + var/obj/item/weapon/grab/G = I + if( !(ismob(G.affecting)) ) + return + if (!src.isopen) + to_chat(usr, "The unit's doors are shut.") + return + if ((stat & NOPOWER) || (stat & BROKEN)) + to_chat(usr, "The unit is not operational.") + return + if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) || BOOTS) //Unit needs to be absolutely empty + to_chat(user, "The unit's storage area is too cluttered.") + return + visible_message("[user] starts putting [G.affecting.name] into the Suit Storage Unit.", 2) //spooky + if(do_after(user, src, 20)) + if(!G || !G.affecting) return //derpcheck + var/mob/M = G.affecting + if (M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + src.OCCUPANT = M + src.isopen = 0 //close ittt + + //for(var/obj/O in src) + // O.loc = src.loc + src.add_fingerprint(user) + qdel(G) + G = null + src.updateUsrDialog() + src.update_icon() + return + return + if( istype(I,/obj/item/clothing/suit/space) ) + if(!src.isopen) + return + var/obj/item/clothing/suit/space/S = I + if(src.SUIT) + to_chat(user, "The unit already contains a suit.") + return + if(user.drop_item(S, src)) + to_chat(user, "You load the [S.name] into the storage compartment.") + src.SUIT = S + src.update_icon() + src.updateUsrDialog() + return + if( istype(I,/obj/item/clothing/head/helmet) ) + if(!src.isopen) + return + var/obj/item/clothing/head/helmet/H = I + if(src.HELMET) + to_chat(user, "The unit already contains a helmet.") + return + if(user.drop_item(H, src)) + to_chat(user, "You load the [H.name] into the storage compartment.") + src.HELMET = H + src.update_icon() + src.updateUsrDialog() + return + if( istype(I,/obj/item/clothing/mask) ) + if(!src.isopen) + return + var/obj/item/clothing/mask/M = I + if(src.MASK) + to_chat(user, "The unit already contains a mask.") + return + if(user.drop_item(M, src)) + to_chat(user, "You load the [M.name] into the storage compartment.") + src.MASK = M + src.update_icon() + src.updateUsrDialog() + return + if( istype(I,/obj/item/clothing/shoes) ) + if(!src.isopen) + return + var/obj/item/clothing/shoes/M = I + if(src.BOOTS) + to_chat(user, "The unit already contains shoes.") + return + if(user.drop_item(M, src)) + to_chat(user, "You load \the [M.name] into the storage compartment.") + src.BOOTS = M + src.update_icon() + src.updateUsrDialog() + return + src.update_icon() + src.updateUsrDialog() + return + + +/obj/machinery/suit_storage_unit/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + + +/obj/machinery/suit_storage_unit/attack_paw(mob/user as mob) + to_chat(user, "The console controls are far too complicated for your tiny brain!") + return + + +//////////////////////////////REMINDER: Make it lock once you place some fucker inside. diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index 1476ae80e67..c77fdf34020 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -1,266 +1,266 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -// Beacon randomly spawns in space -// When a non-traitor (no special role in /mind) uses it, he is given the choice to become a traitor -// If he accepts there is a random chance he will be accepted, rejected, or rejected and killed -// Bringing certain items can help improve the chance to become a traitor - - -/obj/machinery/syndicate_beacon - name = "ominous beacon" - desc = "This looks suspicious..." - icon = 'icons/obj/device.dmi' - icon_state = "syndbeacon" - - anchored = 1 - density = 1 - - var/temptext = "" - var/selfdestructing = 0 - var/charges = 1 - - attack_hand(var/mob/user as mob) - usr.set_machine(src) - var/dat = "Scanning [pick("retina pattern", "voice print", "fingerprints", "dna sequence")]...
                      Identity confirmed,
                      " - if(istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) - if(is_special_character(user)) - dat += "Operative record found. Greetings, Agent [user.name].
                      " - else if(charges < 1) - dat += "Connection severed.
                      " - else - var/honorific = "Mr." - if(user.gender == FEMALE) - honorific = "Ms." - dat += "Identity not found in operative database. What can the Syndicate do for you today, [honorific] [user.name]?
                      " - if(!selfdestructing) - dat += "

                      \"[pick("I want to switch teams.", "I want to work for you.", "Let me join you.", "I can be of use to you.", "You want me working for you, and here's why...", "Give me an objective.", "How's the 401k over at the Syndicate?")]\"
                      " - dat += temptext - user << browse(dat, "window=syndbeacon") - onclose(user, "syndbeacon") - - Topic(href, href_list) - if(..()) return 1 - if(href_list["betraitor"]) - if(charges < 1) - src.updateUsrDialog() - return - var/mob/M = locate(href_list["traitormob"]) - if(M.mind.special_role) - temptext = "We have no need for you at this time. Have a pleasant day.
                      " - src.updateUsrDialog() - return - charges -= 1 - switch(rand(1,2)) - if(1) - temptext = "Double-crosser. You planned to betray us from the start. Allow us to repay the favor in kind." - src.updateUsrDialog() - spawn(rand(50,200)) selfdestruct() - return - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/N = M - ticker.mode.equip_traitor(N) - ticker.mode.traitors += N.mind - N.mind.special_role = "traitor" - var/objective = "Free Objective" - switch(rand(1,100)) - if(1 to 50) - objective = "Steal [pick("a hand teleporter", "the Captain's antique laser gun", "a jetpack", "the Captain's ID", "the Captain's jumpsuit")]." - if(51 to 60) - objective = "Destroy 70% or more of the station's plasma tanks." - if(61 to 70) - objective = "Cut power to 80% or more of the station's tiles." - if(71 to 80) - objective = "Destroy the AI." - if(81 to 90) - objective = "Kill all monkeys aboard the station." - else - objective = "Make certain at least 80% of the station evacuates on the shuttle." - var/datum/objective/custom_objective = new(objective) - custom_objective.owner = N.mind - N.mind.objectives += custom_objective - - var/datum/objective/escape/escape_objective = new - escape_objective.owner = N.mind - N.mind.objectives += escape_objective - - - to_chat(M, "You have joined the ranks of the Syndicate and become a traitor to the station!") - - message_admins("[N]/([N.ckey]) has accepted a traitor objective from a syndicate beacon.") - - var/obj_count = 1 - for(var/datum/objective/OBJ in M.mind.objectives) - to_chat(M, "Objective #[obj_count]: [OBJ.explanation_text]") - obj_count++ - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - - - proc/selfdestruct() - selfdestructing = 1 - spawn() explosion(src.loc, 1, rand(1,3), rand(3,8), 10) - -//Not the best place for it but it's a hack job anyway -- Urist -/obj/machinery/singularity_beacon - name = "singularity beacon" - desc = "A suspicious-looking beacon. It looks like one of those snazzy state-of-the-art bluespace devices." - icon = 'icons/obj/singularity.dmi' - icon_state = "beacon" - anchored = 0 - density = 1 - machine_flags = WRENCHMOVE | FIXED2WORK - layer = MOB_LAYER - - light_color = LIGHT_COLOR_RED - light_range_on = 2 - light_power_on = 2 - - var/obj/item/weapon/cell/cell - var/power_load = 1000 //A bit ugly. How much power this machine needs per tick. Equivalent to one minute on 30k W battery, two second ticks - var/power_draw = 0 //If there's spare power on the grid, cannibalize it to charge the beacon's battery - var/active = 0 //It doesn't use APCs, so use_power wouldn't really suit it - var/icontype = "beacon" - var/obj/structure/cable/attached = null - -/obj/machinery/singularity_beacon/New() - - ..() - - cell = new /obj/item/weapon/cell/hyper(src) //Singularity beacons are wasteful as fuck, that state-of-the-art cell will last a single minute - -/obj/machinery/singularity_beacon/examine(mob/user) - - ..() - - if(anchored) - to_chat(user, "It appears firmly secured to the floor. Nothing a wrench can't undo.") - to_chat(user, "It features a power port. [attached ? "A power cable is running through it":"It looks like a power cable can be ran straight through it to power it"].") - if(active) - to_chat(user, "It is slowly pulsing red and emitting a deep humming sound.") - -/obj/machinery/singularity_beacon/proc/activate(mob/user = null) - if(!anchored) //Sanity - return - if(!check_power()) - if(user) - user.visible_message("[user] tries to start \the [src], but it shuts down halfway.", \ - "You try to start \the [src], but it shuts down halfway. Looks like a power issue.") - else - visible_message("\The [src] suddenly springs to life, only to shut down halfway through startup.") - return - for(var/obj/machinery/singularity/singulo in power_machines) - if(singulo.z == z) - singulo.target = src - icon_state = "[icontype]1" - active = 1 - set_light(light_range_on, light_power_on, light_color) - if(user) - user.visible_message("[user] starts up \the [src].", \ - "You start up \the [src].") - else - visible_message("\The [src] suddenly springs to life.") - -/obj/machinery/singularity_beacon/proc/deactivate(mob/user = null) - for(var/obj/machinery/singularity/singulo in power_machines) - if(singulo.target == src) - singulo.target = null - icon_state = "[icontype]0" - active = 0 - set_light(0) - if(user) - user.visible_message("[user] shuts down \the [src].", \ - "You shut down \the [src].") - else - visible_message("\The [src] suddenly shuts down.") - -/obj/machinery/singularity_beacon/attack_ai(mob/user as mob) - to_chat(user, "You try to interface with \the [src], but it throws a strange encrypted error message.") - return - -/obj/machinery/singularity_beacon/attack_hand(var/mob/user as mob) - user.delayNextAttack(10) //Prevent spam toggling, otherwise you can brick the cell very quickly - if(anchored) - if(!attached) - var/turf/T = get_turf(src) - if(isturf(T) && !T.intact) - attached = locate() in T - if(attached) - user.visible_message("[user] reaches for the exposed cabling and carefully runs it through \the [src]'s power port.", \ - "You reach for the exposed cabling and carefully run it through \the [src]'s power port.") - return //Need to attack again to actually start - return active ? deactivate(user) : activate(user) - else - to_chat(user, "\The [src] doesn't work on the fly, wrench it down first.") - return - -/obj/machinery/singularity_beacon/wrenchAnchor(mob/user) - - if(active) - to_chat(user, "Turn off \the [src] first.") - return - ..() - if(attached) - attached = null //Reset attached cable - -/obj/machinery/singularity_beacon/Destroy() - if(active) - deactivate() - if(cell) - qdel(cell) - cell = null - ..() - -/* -* Added for a simple way to check power. Verifies that the beacon -* is connected to a wire, the wire is part of a powernet (that part's -* sort of redundant, since all wires either join or create one when placed) -* and that the powernet has at least 1500 power units available for use. -* Doesn't use them, though, just makes sure they're there. -* - QualityVan, Aug 11 2012 -*/ - -//Simplified check for power. If we can charge straight out of the grid, do it -/obj/machinery/singularity_beacon/proc/check_wire_power() - if(!attached) //No wire, move straight to battery power - return 0 - var/datum/powernet/PN = attached.get_powernet() - if(!PN) //Powernet is dead - return 0 - if(PN.avail < power_load) //Cannot drain enough power, needs 1500 per tick, move to battery - return 0 - else - PN.load += power_load - if(cell && cell.charge < cell.maxcharge && cell.charge > 0 && PN.netexcess) - power_draw = min(cell.maxcharge - cell.charge, PN.netexcess) //Draw power directly from excess power - PN.load += power_draw - cell.give(power_draw) //We drew power from the grid, charge the cell - return 1 - -//Use up the battery if powernet check fails -/obj/machinery/singularity_beacon/proc/check_battery_power() - - if(cell && cell.charge > power_load) - cell.use(power_load) - return 1 - else //Nothing here either - return 0 - -//Composite of the two, called at every process -/obj/machinery/singularity_beacon/proc/check_power() - - return check_wire_power() || check_battery_power() - -/obj/machinery/singularity_beacon/process() - if(!active) - return - if(!anchored) //If it got unanchored "inexplicably" - deactivate() - else - if(!check_power()) //No power - deactivate() - -/obj/machinery/singularity_beacon/syndicate - icontype = "beaconsynd" - icon_state = "beaconsynd0" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +// Beacon randomly spawns in space +// When a non-traitor (no special role in /mind) uses it, he is given the choice to become a traitor +// If he accepts there is a random chance he will be accepted, rejected, or rejected and killed +// Bringing certain items can help improve the chance to become a traitor + + +/obj/machinery/syndicate_beacon + name = "ominous beacon" + desc = "This looks suspicious..." + icon = 'icons/obj/device.dmi' + icon_state = "syndbeacon" + + anchored = 1 + density = 1 + + var/temptext = "" + var/selfdestructing = 0 + var/charges = 1 + + attack_hand(var/mob/user as mob) + usr.set_machine(src) + var/dat = "Scanning [pick("retina pattern", "voice print", "fingerprints", "dna sequence")]...
                      Identity confirmed,
                      " + if(istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) + if(is_special_character(user)) + dat += "Operative record found. Greetings, Agent [user.name].
                      " + else if(charges < 1) + dat += "Connection severed.
                      " + else + var/honorific = "Mr." + if(user.gender == FEMALE) + honorific = "Ms." + dat += "Identity not found in operative database. What can the Syndicate do for you today, [honorific] [user.name]?
                      " + if(!selfdestructing) + dat += "

                      \"[pick("I want to switch teams.", "I want to work for you.", "Let me join you.", "I can be of use to you.", "You want me working for you, and here's why...", "Give me an objective.", "How's the 401k over at the Syndicate?")]\"
                      " + dat += temptext + user << browse(dat, "window=syndbeacon") + onclose(user, "syndbeacon") + + Topic(href, href_list) + if(..()) return 1 + if(href_list["betraitor"]) + if(charges < 1) + src.updateUsrDialog() + return + var/mob/M = locate(href_list["traitormob"]) + if(M.mind.special_role) + temptext = "We have no need for you at this time. Have a pleasant day.
                      " + src.updateUsrDialog() + return + charges -= 1 + switch(rand(1,2)) + if(1) + temptext = "Double-crosser. You planned to betray us from the start. Allow us to repay the favor in kind." + src.updateUsrDialog() + spawn(rand(50,200)) selfdestruct() + return + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/N = M + ticker.mode.equip_traitor(N) + ticker.mode.traitors += N.mind + N.mind.special_role = "traitor" + var/objective = "Free Objective" + switch(rand(1,100)) + if(1 to 50) + objective = "Steal [pick("a hand teleporter", "the Captain's antique laser gun", "a jetpack", "the Captain's ID", "the Captain's jumpsuit")]." + if(51 to 60) + objective = "Destroy 70% or more of the station's plasma tanks." + if(61 to 70) + objective = "Cut power to 80% or more of the station's tiles." + if(71 to 80) + objective = "Destroy the AI." + if(81 to 90) + objective = "Kill all monkeys aboard the station." + else + objective = "Make certain at least 80% of the station evacuates on the shuttle." + var/datum/objective/custom_objective = new(objective) + custom_objective.owner = N.mind + N.mind.objectives += custom_objective + + var/datum/objective/escape/escape_objective = new + escape_objective.owner = N.mind + N.mind.objectives += escape_objective + + + to_chat(M, "You have joined the ranks of the Syndicate and become a traitor to the station!") + + message_admins("[N]/([N.ckey]) has accepted a traitor objective from a syndicate beacon.") + + var/obj_count = 1 + for(var/datum/objective/OBJ in M.mind.objectives) + to_chat(M, "Objective #[obj_count]: [OBJ.explanation_text]") + obj_count++ + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + + + proc/selfdestruct() + selfdestructing = 1 + spawn() explosion(src.loc, 1, rand(1,3), rand(3,8), 10) + +//Not the best place for it but it's a hack job anyway -- Urist +/obj/machinery/singularity_beacon + name = "singularity beacon" + desc = "A suspicious-looking beacon. It looks like one of those snazzy state-of-the-art bluespace devices." + icon = 'icons/obj/singularity.dmi' + icon_state = "beacon" + anchored = 0 + density = 1 + machine_flags = WRENCHMOVE | FIXED2WORK + layer = MOB_LAYER + + light_color = LIGHT_COLOR_RED + light_range_on = 2 + light_power_on = 2 + + var/obj/item/weapon/cell/cell + var/power_load = 1000 //A bit ugly. How much power this machine needs per tick. Equivalent to one minute on 30k W battery, two second ticks + var/power_draw = 0 //If there's spare power on the grid, cannibalize it to charge the beacon's battery + var/active = 0 //It doesn't use APCs, so use_power wouldn't really suit it + var/icontype = "beacon" + var/obj/structure/cable/attached = null + +/obj/machinery/singularity_beacon/New() + + ..() + + cell = new /obj/item/weapon/cell/hyper(src) //Singularity beacons are wasteful as fuck, that state-of-the-art cell will last a single minute + +/obj/machinery/singularity_beacon/examine(mob/user) + + ..() + + if(anchored) + to_chat(user, "It appears firmly secured to the floor. Nothing a wrench can't undo.") + to_chat(user, "It features a power port. [attached ? "A power cable is running through it":"It looks like a power cable can be ran straight through it to power it"].") + if(active) + to_chat(user, "It is slowly pulsing red and emitting a deep humming sound.") + +/obj/machinery/singularity_beacon/proc/activate(mob/user = null) + if(!anchored) //Sanity + return + if(!check_power()) + if(user) + user.visible_message("[user] tries to start \the [src], but it shuts down halfway.", \ + "You try to start \the [src], but it shuts down halfway. Looks like a power issue.") + else + visible_message("\The [src] suddenly springs to life, only to shut down halfway through startup.") + return + for(var/obj/machinery/singularity/singulo in power_machines) + if(singulo.z == z) + singulo.target = src + icon_state = "[icontype]1" + active = 1 + set_light(light_range_on, light_power_on, light_color) + if(user) + user.visible_message("[user] starts up \the [src].", \ + "You start up \the [src].") + else + visible_message("\The [src] suddenly springs to life.") + +/obj/machinery/singularity_beacon/proc/deactivate(mob/user = null) + for(var/obj/machinery/singularity/singulo in power_machines) + if(singulo.target == src) + singulo.target = null + icon_state = "[icontype]0" + active = 0 + set_light(0) + if(user) + user.visible_message("[user] shuts down \the [src].", \ + "You shut down \the [src].") + else + visible_message("\The [src] suddenly shuts down.") + +/obj/machinery/singularity_beacon/attack_ai(mob/user as mob) + to_chat(user, "You try to interface with \the [src], but it throws a strange encrypted error message.") + return + +/obj/machinery/singularity_beacon/attack_hand(var/mob/user as mob) + user.delayNextAttack(10) //Prevent spam toggling, otherwise you can brick the cell very quickly + if(anchored) + if(!attached) + var/turf/T = get_turf(src) + if(isturf(T) && !T.intact) + attached = locate() in T + if(attached) + user.visible_message("[user] reaches for the exposed cabling and carefully runs it through \the [src]'s power port.", \ + "You reach for the exposed cabling and carefully run it through \the [src]'s power port.") + return //Need to attack again to actually start + return active ? deactivate(user) : activate(user) + else + to_chat(user, "\The [src] doesn't work on the fly, wrench it down first.") + return + +/obj/machinery/singularity_beacon/wrenchAnchor(mob/user) + + if(active) + to_chat(user, "Turn off \the [src] first.") + return + ..() + if(attached) + attached = null //Reset attached cable + +/obj/machinery/singularity_beacon/Destroy() + if(active) + deactivate() + if(cell) + qdel(cell) + cell = null + ..() + +/* +* Added for a simple way to check power. Verifies that the beacon +* is connected to a wire, the wire is part of a powernet (that part's +* sort of redundant, since all wires either join or create one when placed) +* and that the powernet has at least 1500 power units available for use. +* Doesn't use them, though, just makes sure they're there. +* - QualityVan, Aug 11 2012 +*/ + +//Simplified check for power. If we can charge straight out of the grid, do it +/obj/machinery/singularity_beacon/proc/check_wire_power() + if(!attached) //No wire, move straight to battery power + return 0 + var/datum/powernet/PN = attached.get_powernet() + if(!PN) //Powernet is dead + return 0 + if(PN.avail < power_load) //Cannot drain enough power, needs 1500 per tick, move to battery + return 0 + else + PN.load += power_load + if(cell && cell.charge < cell.maxcharge && cell.charge > 0 && PN.netexcess) + power_draw = min(cell.maxcharge - cell.charge, PN.netexcess) //Draw power directly from excess power + PN.load += power_draw + cell.give(power_draw) //We drew power from the grid, charge the cell + return 1 + +//Use up the battery if powernet check fails +/obj/machinery/singularity_beacon/proc/check_battery_power() + + if(cell && cell.charge > power_load) + cell.use(power_load) + return 1 + else //Nothing here either + return 0 + +//Composite of the two, called at every process +/obj/machinery/singularity_beacon/proc/check_power() + + return check_wire_power() || check_battery_power() + +/obj/machinery/singularity_beacon/process() + if(!active) + return + if(!anchored) //If it got unanchored "inexplicably" + deactivate() + else + if(!check_power()) //No power + deactivate() + +/obj/machinery/singularity_beacon/syndicate + icontype = "beaconsynd" + icon_state = "beaconsynd0" diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 0c8b2d79284..ae5bb2dbd68 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -1,220 +1,220 @@ -// ### Preset machines ### - -//Relay - -/obj/machinery/telecomms/relay/preset - network = "tcommsat" - -/obj/machinery/telecomms/relay/preset/station - id = "Station Relay" - listening_level = 1 - autolinkers = list("s_relay") - -/obj/machinery/telecomms/relay/preset/telecomms - id = "Telecomms Relay" - autolinkers = list("relay") - -/obj/machinery/telecomms/relay/preset/mining - id = "Mining Relay" - autolinkers = list("m_relay") - -/obj/machinery/telecomms/relay/preset/ruskie - id = "Ruskie Relay" - hide = 1 - toggled = 0 - autolinkers = list("r_relay") - -/obj/machinery/telecomms/relay/preset/centcom - id = "Centcom Relay" - hide = 1 - toggled = 1 - //anchored = 1 - //use_power = 0 - //idle_power_usage = 0 - heatgen = 0 - autolinkers = list("c_relay") - -//HUB - -/obj/machinery/telecomms/hub/preset - id = "Hub" - network = "tcommsat" - autolinkers = list("hub", "relay", "c_relay", "s_relay", "m_relay", "r_relay", "science", "medical", - "supply", "service", "common", "command", "engineering", "security", - "receiverA", "receiverB", "broadcasterA", "broadcasterB") - -//Receivers - -//--PRESET LEFT--// - -/obj/machinery/telecomms/receiver/preset_left - id = "Receiver A" - network = "tcommsat" - autolinkers = list("receiverA") // link to relay - freq_listening = list(1351, 1355, 1347, 1349) // science, medical, supply, service - - -//--PRESET RIGHT--// - -/obj/machinery/telecomms/receiver/preset_right - id = "Receiver B" - network = "tcommsat" - autolinkers = list("receiverB") // link to relay - freq_listening = list(1345, 1353, 1357, 1359) //ert, command, engineering, security - - //Common and other radio frequencies for people to freely use - New() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - ..() - -/obj/machinery/telecomms/receiver/preset_complete - name = "Receiver" - freq_listening = list() - -//Buses - -/obj/machinery/telecomms/bus/preset_one - id = "Bus 1" - network = "tcommsat" - freq_listening = list(1351, 1355) - autolinkers = list("processor1", "science", "medical") - -/obj/machinery/telecomms/bus/preset_two - id = "Bus 2" - network = "tcommsat" - freq_listening = list(1347, 1349) - autolinkers = list("processor2", "supply", "service") - -/obj/machinery/telecomms/bus/preset_three - id = "Bus 3" - network = "tcommsat" - freq_listening = list(1359, 1353) - autolinkers = list("processor3", "security", "command") - -/obj/machinery/telecomms/bus/preset_four - id = "Bus 4" - network = "tcommsat" - freq_listening = list(1345, 1357) - autolinkers = list("processor4", "engineering", "common") - -/obj/machinery/telecomms/bus/preset_four/New() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - ..() - -/obj/machinery/telecomms/bus/preset_complete - id = "Bus Complete" - network = "tcommsat" - freq_listening = list() - autolinkers = list("processor1", "common") - -//Processors - -/obj/machinery/telecomms/processor/preset_one - id = "Processor 1" - network = "tcommsat" - autolinkers = list("processor1") // processors are sort of isolated; they don't need backward links - -/obj/machinery/telecomms/processor/preset_two - id = "Processor 2" - network = "tcommsat" - autolinkers = list("processor2") - -/obj/machinery/telecomms/processor/preset_three - id = "Processor 3" - network = "tcommsat" - autolinkers = list("processor3") - -/obj/machinery/telecomms/processor/preset_four - id = "Processor 4" - network = "tcommsat" - autolinkers = list("processor4") - - -/obj/machinery/telecomms/processor/preset_complete - name = "Processor" - -//Servers - -/obj/machinery/telecomms/server/presets - network = "tcommsat" - -/obj/machinery/telecomms/server/presets/New() - ..() - name = id - - -/obj/machinery/telecomms/server/presets/science - id = "Science Server" - freq_listening = list(1351) - autolinkers = list("science") - -/obj/machinery/telecomms/server/presets/medical - id = "Medical Server" - freq_listening = list(1355) - autolinkers = list("medical") - -/obj/machinery/telecomms/server/presets/supply - id = "Supply Server" - freq_listening = list(1347) - autolinkers = list("supply") - -//Using old mining channel frequency for a service channel for the bartender, botanist and chef. -//Also cleaned up all the references to the mining channel I could find, it most likely will never be used again anyway. - Duny -/obj/machinery/telecomms/server/presets/service - id = "Service Server" - freq_listening = list(1349) - autolinkers = list("service") - -/obj/machinery/telecomms/server/presets/common - id = "Common Server" - freq_listening = list(1345) - autolinkers = list("common") - - //Common and other radio frequencies for people to freely use - // 1441 to 1489 -/obj/machinery/telecomms/server/presets/common/New() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - ..() - -/obj/machinery/telecomms/server/presets/complete - id = "Master Server" - freq_listening = list() - -/obj/machinery/telecomms/server/presets/command - id = "Command Server" - freq_listening = list(1353) - autolinkers = list("command") - -/obj/machinery/telecomms/server/presets/engineering - id = "Engineering Server" - freq_listening = list(1357) - autolinkers = list("engineering") - -/obj/machinery/telecomms/server/presets/security - id = "Security Server" - freq_listening = list(1359) - autolinkers = list("security") - - -//Broadcasters - -//--PRESET LEFT--// - -/obj/machinery/telecomms/broadcaster/preset_left - id = "Broadcaster A" - network = "tcommsat" - autolinkers = list("broadcasterA") - -//--PRESET RIGHT--// - -/obj/machinery/telecomms/broadcaster/preset_right - id = "Broadcaster B" - network = "tcommsat" - autolinkers = list("broadcasterB") - -/obj/machinery/telecomms/broadcaster/preset_complete - name = "Broadcaster" - network = "tcommsat" +// ### Preset machines ### + +//Relay + +/obj/machinery/telecomms/relay/preset + network = "tcommsat" + +/obj/machinery/telecomms/relay/preset/station + id = "Station Relay" + listening_level = 1 + autolinkers = list("s_relay") + +/obj/machinery/telecomms/relay/preset/telecomms + id = "Telecomms Relay" + autolinkers = list("relay") + +/obj/machinery/telecomms/relay/preset/mining + id = "Mining Relay" + autolinkers = list("m_relay") + +/obj/machinery/telecomms/relay/preset/ruskie + id = "Ruskie Relay" + hide = 1 + toggled = 0 + autolinkers = list("r_relay") + +/obj/machinery/telecomms/relay/preset/centcom + id = "Centcom Relay" + hide = 1 + toggled = 1 + //anchored = 1 + //use_power = 0 + //idle_power_usage = 0 + heatgen = 0 + autolinkers = list("c_relay") + +//HUB + +/obj/machinery/telecomms/hub/preset + id = "Hub" + network = "tcommsat" + autolinkers = list("hub", "relay", "c_relay", "s_relay", "m_relay", "r_relay", "science", "medical", + "supply", "service", "common", "command", "engineering", "security", + "receiverA", "receiverB", "broadcasterA", "broadcasterB") + +//Receivers + +//--PRESET LEFT--// + +/obj/machinery/telecomms/receiver/preset_left + id = "Receiver A" + network = "tcommsat" + autolinkers = list("receiverA") // link to relay + freq_listening = list(1351, 1355, 1347, 1349) // science, medical, supply, service + + +//--PRESET RIGHT--// + +/obj/machinery/telecomms/receiver/preset_right + id = "Receiver B" + network = "tcommsat" + autolinkers = list("receiverB") // link to relay + freq_listening = list(1345, 1353, 1357, 1359) //ert, command, engineering, security + + //Common and other radio frequencies for people to freely use + New() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + ..() + +/obj/machinery/telecomms/receiver/preset_complete + name = "Receiver" + freq_listening = list() + +//Buses + +/obj/machinery/telecomms/bus/preset_one + id = "Bus 1" + network = "tcommsat" + freq_listening = list(1351, 1355) + autolinkers = list("processor1", "science", "medical") + +/obj/machinery/telecomms/bus/preset_two + id = "Bus 2" + network = "tcommsat" + freq_listening = list(1347, 1349) + autolinkers = list("processor2", "supply", "service") + +/obj/machinery/telecomms/bus/preset_three + id = "Bus 3" + network = "tcommsat" + freq_listening = list(1359, 1353) + autolinkers = list("processor3", "security", "command") + +/obj/machinery/telecomms/bus/preset_four + id = "Bus 4" + network = "tcommsat" + freq_listening = list(1345, 1357) + autolinkers = list("processor4", "engineering", "common") + +/obj/machinery/telecomms/bus/preset_four/New() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + ..() + +/obj/machinery/telecomms/bus/preset_complete + id = "Bus Complete" + network = "tcommsat" + freq_listening = list() + autolinkers = list("processor1", "common") + +//Processors + +/obj/machinery/telecomms/processor/preset_one + id = "Processor 1" + network = "tcommsat" + autolinkers = list("processor1") // processors are sort of isolated; they don't need backward links + +/obj/machinery/telecomms/processor/preset_two + id = "Processor 2" + network = "tcommsat" + autolinkers = list("processor2") + +/obj/machinery/telecomms/processor/preset_three + id = "Processor 3" + network = "tcommsat" + autolinkers = list("processor3") + +/obj/machinery/telecomms/processor/preset_four + id = "Processor 4" + network = "tcommsat" + autolinkers = list("processor4") + + +/obj/machinery/telecomms/processor/preset_complete + name = "Processor" + +//Servers + +/obj/machinery/telecomms/server/presets + network = "tcommsat" + +/obj/machinery/telecomms/server/presets/New() + ..() + name = id + + +/obj/machinery/telecomms/server/presets/science + id = "Science Server" + freq_listening = list(1351) + autolinkers = list("science") + +/obj/machinery/telecomms/server/presets/medical + id = "Medical Server" + freq_listening = list(1355) + autolinkers = list("medical") + +/obj/machinery/telecomms/server/presets/supply + id = "Supply Server" + freq_listening = list(1347) + autolinkers = list("supply") + +//Using old mining channel frequency for a service channel for the bartender, botanist and chef. +//Also cleaned up all the references to the mining channel I could find, it most likely will never be used again anyway. - Duny +/obj/machinery/telecomms/server/presets/service + id = "Service Server" + freq_listening = list(1349) + autolinkers = list("service") + +/obj/machinery/telecomms/server/presets/common + id = "Common Server" + freq_listening = list(1345) + autolinkers = list("common") + + //Common and other radio frequencies for people to freely use + // 1441 to 1489 +/obj/machinery/telecomms/server/presets/common/New() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + ..() + +/obj/machinery/telecomms/server/presets/complete + id = "Master Server" + freq_listening = list() + +/obj/machinery/telecomms/server/presets/command + id = "Command Server" + freq_listening = list(1353) + autolinkers = list("command") + +/obj/machinery/telecomms/server/presets/engineering + id = "Engineering Server" + freq_listening = list(1357) + autolinkers = list("engineering") + +/obj/machinery/telecomms/server/presets/security + id = "Security Server" + freq_listening = list(1359) + autolinkers = list("security") + + +//Broadcasters + +//--PRESET LEFT--// + +/obj/machinery/telecomms/broadcaster/preset_left + id = "Broadcaster A" + network = "tcommsat" + autolinkers = list("broadcasterA") + +//--PRESET RIGHT--// + +/obj/machinery/telecomms/broadcaster/preset_right + id = "Broadcaster B" + network = "tcommsat" + autolinkers = list("broadcasterB") + +/obj/machinery/telecomms/broadcaster/preset_complete + name = "Broadcaster" + network = "tcommsat" diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index a461686ba89..e829aea1559 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -1,673 +1,673 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/* - Hello, friends, this is Doohl from sexylands. You may be wondering what this - monstrous code file is. Sit down, boys and girls, while I tell you the tale. - - - The machines defined in this file were designed to be compatible with any radio - signals, provided they use subspace transmission. Currently they are only used for - headsets, but they can eventually be outfitted for real COMPUTER networks. This - is just a skeleton, ladies and gentlemen. - - Look at radio.dm for the prequel to this code. -*/ - -var/global/list/obj/machinery/telecomms/telecomms_list = list() - -/obj/machinery/telecomms - var/list/links = list() // list of machines this machine is linked to - var/traffic = 0 // value increases as traffic increases - var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed) - var/list/autolinkers = list() // list of text/number values to link with - var/id = "NULL" // identification string - var/network = "NULL" // the network of the machinery - - var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all - - var/machinetype = 0 // just a hacky way of preventing alike machines from pairing - var/toggled = 1 // Is it toggled on - var/on = 1 - var/integrity = 100 // basically HP, loses integrity by heat - var/heatgen = 20 // how much heat to transfer to the environment - var/delay = 10 // how many process() ticks to delay per heat - var/heating_power = 40000 - var/long_range_link = 0 // Can you link it across Z levels or on the otherside of the map? (Relay & Hub) - var/circuitboard = null // string pointing to a circuitboard type - var/hide = 0 // Is it a hidden machine? - var/listening_level = 0 // 0 = auto set in New() - this is the z level that the machine is listening to. - - -/obj/machinery/telecomms/proc/relay_information(datum/signal/signal, filter, copysig, amount = 20) - // relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending -#ifdef SAY_DEBUG - var/mob/mob = signal.data["mob"] - var/datum/language/language = signal.data["language"] - var/langname = (language ? language.name : "No language") -#endif - say_testing(mob, "[src] relay_information start, language [langname]") - if(!on) - return - var/send_count = 0 - - signal.data["slow"] += rand(0, round((100-integrity))) // apply some lag based on integrity - - // Apply some lag based on traffic rates - var/netlag = round(traffic / 50) - if(netlag > signal.data["slow"]) - signal.data["slow"] = netlag - -// Loop through all linked machines and send the signal or copy. - for(var/obj/machinery/telecomms/machine in links) - if(!machine.loc) - world.log << "DEBUG: telecomms machine has null loc: [machine.name]" - continue - if(filter && !istype( machine, text2path(filter) )) - continue - if(!machine.on) - continue - if(amount && send_count >= amount) - break - if(machine.loc.z != listening_level) - if(long_range_link == 0 && machine.long_range_link == 0) - continue - // If we're sending a copy, be sure to create the copy for EACH machine and paste the data - var/datum/signal/copy = getFromPool(/datum/signal) - if(copysig) - - copy.transmission_method = 2 - copy.frequency = signal.frequency - // Copy the main data contents! Workaround for some nasty bug where the actual array memory is copied and not its contents. - copy.data = list( - "mob" = signal.data["mob"], - "language" = signal.data["language"], - "mobtype" = signal.data["mobtype"], - "realname" = signal.data["realname"], - "name" = signal.data["name"], - "job" = signal.data["job"], - "key" = signal.data["key"], - "vmask" = signal.data["vmask"], - "compression" = signal.data["compression"], - "message" = signal.data["message"], - "radio" = signal.data["radio"], - "slow" = signal.data["slow"], - "traffic" = signal.data["traffic"], - "type" = signal.data["type"], - "server" = signal.data["server"], - "reject" = signal.data["reject"], - "level" = signal.data["level"], - "lquote" = signal.data["lquote"], - "rquote" = signal.data["rquote"], - "message_classes" = signal.data["message_classes"], - "wrapper_classes" = signal.data["wrapper_classes"] - ) - - // Keep the "original" signal constant - if(!signal.data["original"]) - copy.data["original"] = signal - else - copy.data["original"] = signal.data["original"] - - else - copy = null - - - send_count++ - if(machine.is_freq_listening(signal)) - machine.traffic++ - - if(copysig && copy) - machine.receive_information(copy, src) - else - machine.receive_information(signal, src) - - - if(send_count > 0 && is_freq_listening(signal)) - traffic++ - - return send_count - -/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine) - // send signal directly to a machine - machine.receive_information(signal, src) - -/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - // receive information from linked machinery - ..() - -/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal) - // return 1 if found, 0 if not found - if(!signal) - return 0 - if((signal.frequency in freq_listening) || (!freq_listening.len)) - return 1 - else - return 0 - - -/obj/machinery/telecomms/New() - telecomms_list += src - ..() - - //Set the listening_level if there's none. - if(!listening_level) - //Defaults to our Z level! - var/turf/position = get_turf(src) - listening_level = position.z - -/obj/machinery/telecomms/initialize() - if(autolinkers.len) - // Links nearby machines - if(!long_range_link) - for(var/obj/machinery/telecomms/T in orange(20, src)) - add_link(T) - else - for(var/obj/machinery/telecomms/T in telecomms_list) - add_link(T) - - -/obj/machinery/telecomms/Destroy() - telecomms_list -= src - ..() - -// Used in auto linking -/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) - var/turf/position = get_turf(src) - var/turf/T_position = get_turf(T) - if((position.z == T_position.z) || (src.long_range_link && T.long_range_link)) - if(src != T) - for(var/x in autolinkers) - if(x in T.autolinkers) - links |= T - break - -/obj/machinery/telecomms/update_icon() - if(on) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]_off" - -/obj/machinery/telecomms/proc/update_power() - - - if(toggled) - if(stat & (BROKEN|NOPOWER|EMPED) || integrity <= 0) // if powered, on. if not powered, off. if too damaged, off - on = 0 - else - on = 1 - else - on = 0 - -/obj/machinery/telecomms/process() - update_power() - - // Check heat and generate some - checkheat() - - // Update the icon - update_icon() - - if(traffic > 0) - traffic -= netspeed - -/obj/machinery/telecomms/emp_act(severity) - if(prob(100/severity)) - if(!(stat & EMPED)) - stat |= EMPED - var/duration = (300 * 10)/severity - spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. - stat &= ~EMPED - ..() - -/obj/machinery/telecomms/proc/checkheat() - // Checks heat from the environment and applies any integrity damage - var/datum/gas_mixture/environment = loc.return_air() - switch(environment.temperature) - if(T0C to (T20C + 20)) - integrity = Clamp(integrity, 0, 100) - if((T20C + 20) to (T0C + 70)) - integrity = max(0, integrity - 1) - if(delay) - delay-- - else - // If the machine is on, ready to produce heat, and has positive traffic, genn some heat - if(on && traffic > 0) - produce_heat(heatgen) - delay = initial(delay) - -/obj/machinery/telecomms/proc/produce_heat(heat_amt) - if(heatgen == 0) - return - - if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater. - var/turf/simulated/L = loc - if(istype(L)) - var/datum/gas_mixture/env = L.return_air() - if(env.temperature < (heat_amt+T0C)) - - var/transfer_moles = 0.25 * env.total_moles() - - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - if(removed) - - var/heat_capacity = removed.heat_capacity() - if(heat_capacity == 0 || heat_capacity == null) - heat_capacity = 1 - removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000) - - env.merge(removed) -/* - The receiver idles and receives messages from subspace-compatible radio equipment; - primarily headsets. They then just relay this information to all linked devices, - which can would probably be network hubs. - - Link to Processor Units in case receiver can't send to bus units. -*/ - -/obj/machinery/telecomms/receiver - name = "Subspace Receiver" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "broadcast receiver" - desc = "This machine has a dish-like shape and green lights. It is designed to detect and process subspace radio activity." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 30 - machinetype = 1 - heatgen = 0 - circuitboard = "/obj/item/weapon/circuitboard/telecomms/receiver" - -/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal) -#ifdef SAY_DEBUG - var/mob/mob = signal.data["mob"] - var/datum/language/language = signal.data["language"] - var/langname = (language ? language.name : "No language") - say_testing(mob, "[src] received radio signal from us, language [langname]") -#endif - - if(!on) // has to be on to receive messages - return - if(!signal) - return - if(!check_receive_level(signal)) - return - say_testing(mob, "[src] is on, has signal, and receive is good") - if(signal.transmission_method == 2) - - if(is_freq_listening(signal)) // detect subspace signals - - //Remove the level and then start adding levels that it is being broadcasted in. - signal.data["level"] = list() - - var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub") // ideally relay the copied information to relays - if(!can_send) - relay_information(signal, "/obj/machinery/telecomms/bus") // Send it to a bus instead, if it's linked to one - else - say_testing(mob, "[src] is not listening") - else - say_testing(mob, "bad transmission method") - -/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal) - - - if(signal.data["level"] != listening_level) - for(var/obj/machinery/telecomms/hub/H in links) - var/list/connected_levels = list() - for(var/obj/machinery/telecomms/relay/R in H.links) - if(R.can_receive(signal)) - connected_levels |= R.listening_level - if(signal.data["level"] in connected_levels) - return 1 - return 0 - return 1 - - -/* - The HUB idles until it receives information. It then passes on that information - depending on where it came from. - - This is the heart of the Telecommunications Network, sending information where it - is needed. It mainly receives information from long-distance Relays and then sends - that information to be processed. Afterwards it gets the uncompressed information - from Servers/Buses and sends that back to the relay, to then be broadcasted. -*/ - -/obj/machinery/telecomms/hub - name = "Telecommunication Hub" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "hub" - desc = "A mighty piece of hardware used to send/receive massive amounts of data." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 80 - machinetype = 7 - heatgen = 40 - circuitboard = "/obj/item/weapon/circuitboard/telecomms/hub" - long_range_link = 1 - netspeed = 40 - - -/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - if(is_freq_listening(signal)) - if(istype(machine_from, /obj/machinery/telecomms/receiver)) - //If the signal is compressed, send it to the bus. - relay_information(signal, "/obj/machinery/telecomms/bus", 1) // ideally relay the copied information to bus units - else - // Get a list of relays that we're linked to, then send the signal to their levels. - relay_information(signal, "/obj/machinery/telecomms/relay", 1) - relay_information(signal, "/obj/machinery/telecomms/broadcaster", 1) // Send it to a broadcaster. - - -/* - The relay idles until it receives information. It then passes on that information - depending on where it came from. - - The relay is needed in order to send information pass Z levels. It must be linked - with a HUB, the only other machine that can send/receive pass Z levels. -*/ - -/obj/machinery/telecomms/relay - name = "Telecommunication Relay" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "relay" - desc = "A mighty piece of hardware used to send massive amounts of data far away." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 30 - machinetype = 8 - heatgen = 0 - circuitboard = "/obj/item/weapon/circuitboard/telecomms/relay" - netspeed = 5 - long_range_link = 1 - var/broadcasting = 1 - var/receiving = 1 - -/obj/machinery/telecomms/relay/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - // Add our level and send it back - if(can_send(signal)) - signal.data["level"] |= listening_level - -// Checks to see if it can send/receive. - -/obj/machinery/telecomms/relay/proc/can(datum/signal/signal) - if(!on) - return 0 - if(!is_freq_listening(signal)) - return 0 - return 1 - -/obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal) - if(!can(signal)) - return 0 - return broadcasting - -/obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal) - if(!can(signal)) - return 0 - return receiving - -/* - The bus mainframe idles and waits for hubs to relay them signals. They act - as junctions for the network. - - They transfer uncompressed subspace packets to processor units, and then take - the processed packet to a server for logging. - - Link to a subspace hub if it can't send to a server. -*/ - -/obj/machinery/telecomms/bus - name = "Bus Mainframe" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "bus" - desc = "A mighty piece of hardware used to send massive amounts of data quickly." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 50 - machinetype = 2 - heatgen = 20 - circuitboard = "/obj/item/weapon/circuitboard/telecomms/bus" - netspeed = 40 - var/change_frequency = 0 - -/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(is_freq_listening(signal)) - - if(change_frequency) - signal.frequency = change_frequency - - if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it - // send to one linked processor unit - var/send_to_processor = relay_information(signal, "/obj/machinery/telecomms/processor") - - if(send_to_processor) - return - // failed to send to a processor, relay information anyway - signal.data["slow"] += rand(1, 5) // slow the signal down only slightly - src.receive_information(signal, src) - - // Try sending it! - var/list/try_send = list("/obj/machinery/telecomms/server", "/obj/machinery/telecomms/hub", "/obj/machinery/telecomms/broadcaster", "/obj/machinery/telecomms/bus") - var/i = 0 - for(var/send in try_send) - if(i) - signal.data["slow"] += rand(0, 1) // slow the signal down only slightly - i++ - var/can_send = relay_information(signal, send) - if(can_send) - break - - - -/* - The processor is a very simple machine that decompresses subspace signals and - transfers them back to the original bus. It is essential in producing audible - data. - - Link to servers if bus is not present -*/ - -/obj/machinery/telecomms/processor - name = "Processor Unit" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "processor" - desc = "This machine is used to process large quantities of information." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 30 - machinetype = 3 - heatgen = 100 - delay = 5 - circuitboard = "/obj/item/weapon/circuitboard/telecomms/processor" - var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals - - receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(is_freq_listening(signal)) - - if(process_mode) - signal.data["compression"] = 0 // uncompress subspace signal - else - signal.data["compression"] = 100 // even more compressed signal - - if(istype(machine_from, /obj/machinery/telecomms/bus)) - relay_direct_information(signal, machine_from) // send the signal back to the machine - else // no bus detected - send the signal to servers instead - signal.data["slow"] += rand(5, 10) // slow the signal down - relay_information(signal, "/obj/machinery/telecomms/server") - - -/* - The server logs all traffic and signal data. Once it records the signal, it sends - it to the subspace broadcaster. - - Store a maximum of 100 logs and then deletes them. -*/ - - -/obj/machinery/telecomms/server - name = "Telecommunication Server" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "comm_server" - desc = "A machine used to store data and network statistics." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 15 - machinetype = 4 - heatgen = 50 - circuitboard = "/obj/item/weapon/circuitboard/telecomms/server" - var/list/log_entries = list() - var/list/stored_names = list() - var/list/TrafficActions = list() - var/logs = 0 // number of logs - var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) - - var/list/memory = list() // stored memory - var/rawcode = "" // the code to compile (raw text) - var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code - var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up - - var/encryption = "null" // encryption key: ie "password" - var/salt = "null" // encryption salt: ie "123comsat" - // would add up to md5("password123comsat") - var/language = "human" - var/obj/item/device/radio/headset/server_radio = null - var/last_signal = 0 // Last time it sent a signal - -/obj/machinery/telecomms/server/New() - ..() - Compiler = new() - Compiler.Holder = src - server_radio = new() - -/obj/machinery/telecomms/server/Destroy() - // Garbage collects all the NTSL datums. - if(Compiler) - Compiler.GC() - Compiler = null - ..() - -/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(signal.data["message"]) - - if(is_freq_listening(signal)) - - if(traffic > 0) - totaltraffic += traffic // add current traffic to total traffic - - //Is this a test signal? Bypass logging - if(signal.data["type"] != 4) - - // If signal has a message and appropriate frequency - - update_logs() - - var/datum/comm_log_entry/log = new - var/mob/M = signal.data["mob"] - // Copy the signal.data entries we want - log.parameters["mobtype"] = signal.data["mobtype"] - log.parameters["job"] = signal.data["job"] - log.parameters["key"] = signal.data["key"] - log.parameters["message"] = signal.data["message"] - log.parameters["name"] = signal.data["name"] - log.parameters["realname"] = signal.data["realname"] - - if(!istype(M, /mob/new_player) && istype(M)) - log.parameters["uspeech"] = M.universal_speak - else - log.parameters["uspeech"] = 0 - - - - // If the signal is still compressed, make the log entry gibberish - if(signal.data["compression"] > 0) - log.parameters["message"] = Gibberish(signal.data["message"], signal.data["compression"] + 50) - log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50) - log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50) - log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50) - log.input_type = "Corrupt File" - - // Log and store everything that needs to be logged - log_entries.Add(log) - if(!(signal.data["name"] in stored_names)) - stored_names.Add(signal.data["name"]) - logs++ - signal.data["server"] = src - - // Give the log a name - var/identifier = num2text( rand(-1000,1000) + world.time ) - log.name = "data packet ([md5(identifier)])" - - if(Compiler && autoruncode) - Compiler.Run(signal) // execute the code - - var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub") - if(!can_send) - relay_information(signal, "/obj/machinery/telecomms/broadcaster") - - -/obj/machinery/telecomms/server/proc/setcode(var/t) - if(t) - if(istext(t)) - rawcode = t - -/obj/machinery/telecomms/server/proc/admin_log(var/mob/mob) - var/msg = "[key_name(mob)] has compiled a script to [src.id]" - - diary << msg - diary << rawcode - - investigation_log("ntsl", "[msg]
                      [rawcode]
                      ") - - if (length(rawcode)) // Let's not bother the admins for empty code. - message_admins("[msg] ([formatJumpTo(mob)])", 0, 1) - -/obj/machinery/telecomms/server/proc/compile(var/mob/user) - - - if(Compiler) - admin_log(user) - return Compiler.Compile(rawcode) - -/obj/machinery/telecomms/server/proc/update_logs() - // start deleting the very first log entry - if(logs >= 400) - for(var/i = 1, i <= logs, i++) // locate the first garbage collectable log entry and remove it - var/datum/comm_log_entry/L = log_entries[i] - if(L.garbage_collector) - log_entries.Remove(L) - logs-- - break - -/obj/machinery/telecomms/server/proc/add_entry(var/content, var/input) - var/datum/comm_log_entry/log = new - var/identifier = num2text( rand(-1000,1000) + world.time ) - log.name = "[input] ([md5(identifier)])" - log.input_type = input - log.parameters["message"] = content - log_entries.Add(log) - update_logs() - -// Simple log entry datum - -/datum/comm_log_entry - var/parameters = list() // carbon-copy to signal.data[] - var/name = "data packet (#)" - var/garbage_collector = 1 // if set to 0, will not be garbage collected - var/input_type = "Speech File" - - - - - - - +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/* + Hello, friends, this is Doohl from sexylands. You may be wondering what this + monstrous code file is. Sit down, boys and girls, while I tell you the tale. + + + The machines defined in this file were designed to be compatible with any radio + signals, provided they use subspace transmission. Currently they are only used for + headsets, but they can eventually be outfitted for real COMPUTER networks. This + is just a skeleton, ladies and gentlemen. + + Look at radio.dm for the prequel to this code. +*/ + +var/global/list/obj/machinery/telecomms/telecomms_list = list() + +/obj/machinery/telecomms + var/list/links = list() // list of machines this machine is linked to + var/traffic = 0 // value increases as traffic increases + var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed) + var/list/autolinkers = list() // list of text/number values to link with + var/id = "NULL" // identification string + var/network = "NULL" // the network of the machinery + + var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all + + var/machinetype = 0 // just a hacky way of preventing alike machines from pairing + var/toggled = 1 // Is it toggled on + var/on = 1 + var/integrity = 100 // basically HP, loses integrity by heat + var/heatgen = 20 // how much heat to transfer to the environment + var/delay = 10 // how many process() ticks to delay per heat + var/heating_power = 40000 + var/long_range_link = 0 // Can you link it across Z levels or on the otherside of the map? (Relay & Hub) + var/circuitboard = null // string pointing to a circuitboard type + var/hide = 0 // Is it a hidden machine? + var/listening_level = 0 // 0 = auto set in New() - this is the z level that the machine is listening to. + + +/obj/machinery/telecomms/proc/relay_information(datum/signal/signal, filter, copysig, amount = 20) + // relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending +#ifdef SAY_DEBUG + var/mob/mob = signal.data["mob"] + var/datum/language/language = signal.data["language"] + var/langname = (language ? language.name : "No language") +#endif + say_testing(mob, "[src] relay_information start, language [langname]") + if(!on) + return + var/send_count = 0 + + signal.data["slow"] += rand(0, round((100-integrity))) // apply some lag based on integrity + + // Apply some lag based on traffic rates + var/netlag = round(traffic / 50) + if(netlag > signal.data["slow"]) + signal.data["slow"] = netlag + +// Loop through all linked machines and send the signal or copy. + for(var/obj/machinery/telecomms/machine in links) + if(!machine.loc) + world.log << "DEBUG: telecomms machine has null loc: [machine.name]" + continue + if(filter && !istype( machine, text2path(filter) )) + continue + if(!machine.on) + continue + if(amount && send_count >= amount) + break + if(machine.loc.z != listening_level) + if(long_range_link == 0 && machine.long_range_link == 0) + continue + // If we're sending a copy, be sure to create the copy for EACH machine and paste the data + var/datum/signal/copy = getFromPool(/datum/signal) + if(copysig) + + copy.transmission_method = 2 + copy.frequency = signal.frequency + // Copy the main data contents! Workaround for some nasty bug where the actual array memory is copied and not its contents. + copy.data = list( + "mob" = signal.data["mob"], + "language" = signal.data["language"], + "mobtype" = signal.data["mobtype"], + "realname" = signal.data["realname"], + "name" = signal.data["name"], + "job" = signal.data["job"], + "key" = signal.data["key"], + "vmask" = signal.data["vmask"], + "compression" = signal.data["compression"], + "message" = signal.data["message"], + "radio" = signal.data["radio"], + "slow" = signal.data["slow"], + "traffic" = signal.data["traffic"], + "type" = signal.data["type"], + "server" = signal.data["server"], + "reject" = signal.data["reject"], + "level" = signal.data["level"], + "lquote" = signal.data["lquote"], + "rquote" = signal.data["rquote"], + "message_classes" = signal.data["message_classes"], + "wrapper_classes" = signal.data["wrapper_classes"] + ) + + // Keep the "original" signal constant + if(!signal.data["original"]) + copy.data["original"] = signal + else + copy.data["original"] = signal.data["original"] + + else + copy = null + + + send_count++ + if(machine.is_freq_listening(signal)) + machine.traffic++ + + if(copysig && copy) + machine.receive_information(copy, src) + else + machine.receive_information(signal, src) + + + if(send_count > 0 && is_freq_listening(signal)) + traffic++ + + return send_count + +/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine) + // send signal directly to a machine + machine.receive_information(signal, src) + +/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + // receive information from linked machinery + ..() + +/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal) + // return 1 if found, 0 if not found + if(!signal) + return 0 + if((signal.frequency in freq_listening) || (!freq_listening.len)) + return 1 + else + return 0 + + +/obj/machinery/telecomms/New() + telecomms_list += src + ..() + + //Set the listening_level if there's none. + if(!listening_level) + //Defaults to our Z level! + var/turf/position = get_turf(src) + listening_level = position.z + +/obj/machinery/telecomms/initialize() + if(autolinkers.len) + // Links nearby machines + if(!long_range_link) + for(var/obj/machinery/telecomms/T in orange(20, src)) + add_link(T) + else + for(var/obj/machinery/telecomms/T in telecomms_list) + add_link(T) + + +/obj/machinery/telecomms/Destroy() + telecomms_list -= src + ..() + +// Used in auto linking +/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) + var/turf/position = get_turf(src) + var/turf/T_position = get_turf(T) + if((position.z == T_position.z) || (src.long_range_link && T.long_range_link)) + if(src != T) + for(var/x in autolinkers) + if(x in T.autolinkers) + links |= T + break + +/obj/machinery/telecomms/update_icon() + if(on) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]_off" + +/obj/machinery/telecomms/proc/update_power() + + + if(toggled) + if(stat & (BROKEN|NOPOWER|EMPED) || integrity <= 0) // if powered, on. if not powered, off. if too damaged, off + on = 0 + else + on = 1 + else + on = 0 + +/obj/machinery/telecomms/process() + update_power() + + // Check heat and generate some + checkheat() + + // Update the icon + update_icon() + + if(traffic > 0) + traffic -= netspeed + +/obj/machinery/telecomms/emp_act(severity) + if(prob(100/severity)) + if(!(stat & EMPED)) + stat |= EMPED + var/duration = (300 * 10)/severity + spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. + stat &= ~EMPED + ..() + +/obj/machinery/telecomms/proc/checkheat() + // Checks heat from the environment and applies any integrity damage + var/datum/gas_mixture/environment = loc.return_air() + switch(environment.temperature) + if(T0C to (T20C + 20)) + integrity = Clamp(integrity, 0, 100) + if((T20C + 20) to (T0C + 70)) + integrity = max(0, integrity - 1) + if(delay) + delay-- + else + // If the machine is on, ready to produce heat, and has positive traffic, genn some heat + if(on && traffic > 0) + produce_heat(heatgen) + delay = initial(delay) + +/obj/machinery/telecomms/proc/produce_heat(heat_amt) + if(heatgen == 0) + return + + if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater. + var/turf/simulated/L = loc + if(istype(L)) + var/datum/gas_mixture/env = L.return_air() + if(env.temperature < (heat_amt+T0C)) + + var/transfer_moles = 0.25 * env.total_moles() + + var/datum/gas_mixture/removed = env.remove(transfer_moles) + + if(removed) + + var/heat_capacity = removed.heat_capacity() + if(heat_capacity == 0 || heat_capacity == null) + heat_capacity = 1 + removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000) + + env.merge(removed) +/* + The receiver idles and receives messages from subspace-compatible radio equipment; + primarily headsets. They then just relay this information to all linked devices, + which can would probably be network hubs. + + Link to Processor Units in case receiver can't send to bus units. +*/ + +/obj/machinery/telecomms/receiver + name = "Subspace Receiver" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "broadcast receiver" + desc = "This machine has a dish-like shape and green lights. It is designed to detect and process subspace radio activity." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 30 + machinetype = 1 + heatgen = 0 + circuitboard = "/obj/item/weapon/circuitboard/telecomms/receiver" + +/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal) +#ifdef SAY_DEBUG + var/mob/mob = signal.data["mob"] + var/datum/language/language = signal.data["language"] + var/langname = (language ? language.name : "No language") + say_testing(mob, "[src] received radio signal from us, language [langname]") +#endif + + if(!on) // has to be on to receive messages + return + if(!signal) + return + if(!check_receive_level(signal)) + return + say_testing(mob, "[src] is on, has signal, and receive is good") + if(signal.transmission_method == 2) + + if(is_freq_listening(signal)) // detect subspace signals + + //Remove the level and then start adding levels that it is being broadcasted in. + signal.data["level"] = list() + + var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub") // ideally relay the copied information to relays + if(!can_send) + relay_information(signal, "/obj/machinery/telecomms/bus") // Send it to a bus instead, if it's linked to one + else + say_testing(mob, "[src] is not listening") + else + say_testing(mob, "bad transmission method") + +/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal) + + + if(signal.data["level"] != listening_level) + for(var/obj/machinery/telecomms/hub/H in links) + var/list/connected_levels = list() + for(var/obj/machinery/telecomms/relay/R in H.links) + if(R.can_receive(signal)) + connected_levels |= R.listening_level + if(signal.data["level"] in connected_levels) + return 1 + return 0 + return 1 + + +/* + The HUB idles until it receives information. It then passes on that information + depending on where it came from. + + This is the heart of the Telecommunications Network, sending information where it + is needed. It mainly receives information from long-distance Relays and then sends + that information to be processed. Afterwards it gets the uncompressed information + from Servers/Buses and sends that back to the relay, to then be broadcasted. +*/ + +/obj/machinery/telecomms/hub + name = "Telecommunication Hub" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "hub" + desc = "A mighty piece of hardware used to send/receive massive amounts of data." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 80 + machinetype = 7 + heatgen = 40 + circuitboard = "/obj/item/weapon/circuitboard/telecomms/hub" + long_range_link = 1 + netspeed = 40 + + +/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + if(is_freq_listening(signal)) + if(istype(machine_from, /obj/machinery/telecomms/receiver)) + //If the signal is compressed, send it to the bus. + relay_information(signal, "/obj/machinery/telecomms/bus", 1) // ideally relay the copied information to bus units + else + // Get a list of relays that we're linked to, then send the signal to their levels. + relay_information(signal, "/obj/machinery/telecomms/relay", 1) + relay_information(signal, "/obj/machinery/telecomms/broadcaster", 1) // Send it to a broadcaster. + + +/* + The relay idles until it receives information. It then passes on that information + depending on where it came from. + + The relay is needed in order to send information pass Z levels. It must be linked + with a HUB, the only other machine that can send/receive pass Z levels. +*/ + +/obj/machinery/telecomms/relay + name = "Telecommunication Relay" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "relay" + desc = "A mighty piece of hardware used to send massive amounts of data far away." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 30 + machinetype = 8 + heatgen = 0 + circuitboard = "/obj/item/weapon/circuitboard/telecomms/relay" + netspeed = 5 + long_range_link = 1 + var/broadcasting = 1 + var/receiving = 1 + +/obj/machinery/telecomms/relay/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + // Add our level and send it back + if(can_send(signal)) + signal.data["level"] |= listening_level + +// Checks to see if it can send/receive. + +/obj/machinery/telecomms/relay/proc/can(datum/signal/signal) + if(!on) + return 0 + if(!is_freq_listening(signal)) + return 0 + return 1 + +/obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal) + if(!can(signal)) + return 0 + return broadcasting + +/obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal) + if(!can(signal)) + return 0 + return receiving + +/* + The bus mainframe idles and waits for hubs to relay them signals. They act + as junctions for the network. + + They transfer uncompressed subspace packets to processor units, and then take + the processed packet to a server for logging. + + Link to a subspace hub if it can't send to a server. +*/ + +/obj/machinery/telecomms/bus + name = "Bus Mainframe" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "bus" + desc = "A mighty piece of hardware used to send massive amounts of data quickly." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 50 + machinetype = 2 + heatgen = 20 + circuitboard = "/obj/item/weapon/circuitboard/telecomms/bus" + netspeed = 40 + var/change_frequency = 0 + +/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + if(is_freq_listening(signal)) + + if(change_frequency) + signal.frequency = change_frequency + + if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it + // send to one linked processor unit + var/send_to_processor = relay_information(signal, "/obj/machinery/telecomms/processor") + + if(send_to_processor) + return + // failed to send to a processor, relay information anyway + signal.data["slow"] += rand(1, 5) // slow the signal down only slightly + src.receive_information(signal, src) + + // Try sending it! + var/list/try_send = list("/obj/machinery/telecomms/server", "/obj/machinery/telecomms/hub", "/obj/machinery/telecomms/broadcaster", "/obj/machinery/telecomms/bus") + var/i = 0 + for(var/send in try_send) + if(i) + signal.data["slow"] += rand(0, 1) // slow the signal down only slightly + i++ + var/can_send = relay_information(signal, send) + if(can_send) + break + + + +/* + The processor is a very simple machine that decompresses subspace signals and + transfers them back to the original bus. It is essential in producing audible + data. + + Link to servers if bus is not present +*/ + +/obj/machinery/telecomms/processor + name = "Processor Unit" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "processor" + desc = "This machine is used to process large quantities of information." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 30 + machinetype = 3 + heatgen = 100 + delay = 5 + circuitboard = "/obj/item/weapon/circuitboard/telecomms/processor" + var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals + + receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + if(is_freq_listening(signal)) + + if(process_mode) + signal.data["compression"] = 0 // uncompress subspace signal + else + signal.data["compression"] = 100 // even more compressed signal + + if(istype(machine_from, /obj/machinery/telecomms/bus)) + relay_direct_information(signal, machine_from) // send the signal back to the machine + else // no bus detected - send the signal to servers instead + signal.data["slow"] += rand(5, 10) // slow the signal down + relay_information(signal, "/obj/machinery/telecomms/server") + + +/* + The server logs all traffic and signal data. Once it records the signal, it sends + it to the subspace broadcaster. + + Store a maximum of 100 logs and then deletes them. +*/ + + +/obj/machinery/telecomms/server + name = "Telecommunication Server" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "comm_server" + desc = "A machine used to store data and network statistics." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 15 + machinetype = 4 + heatgen = 50 + circuitboard = "/obj/item/weapon/circuitboard/telecomms/server" + var/list/log_entries = list() + var/list/stored_names = list() + var/list/TrafficActions = list() + var/logs = 0 // number of logs + var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) + + var/list/memory = list() // stored memory + var/rawcode = "" // the code to compile (raw text) + var/datum/TCS_Compiler/Compiler // the compiler that compiles and runs the code + var/autoruncode = 0 // 1 if the code is set to run every time a signal is picked up + + var/encryption = "null" // encryption key: ie "password" + var/salt = "null" // encryption salt: ie "123comsat" + // would add up to md5("password123comsat") + var/language = "human" + var/obj/item/device/radio/headset/server_radio = null + var/last_signal = 0 // Last time it sent a signal + +/obj/machinery/telecomms/server/New() + ..() + Compiler = new() + Compiler.Holder = src + server_radio = new() + +/obj/machinery/telecomms/server/Destroy() + // Garbage collects all the NTSL datums. + if(Compiler) + Compiler.GC() + Compiler = null + ..() + +/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) + + if(signal.data["message"]) + + if(is_freq_listening(signal)) + + if(traffic > 0) + totaltraffic += traffic // add current traffic to total traffic + + //Is this a test signal? Bypass logging + if(signal.data["type"] != 4) + + // If signal has a message and appropriate frequency + + update_logs() + + var/datum/comm_log_entry/log = new + var/mob/M = signal.data["mob"] + // Copy the signal.data entries we want + log.parameters["mobtype"] = signal.data["mobtype"] + log.parameters["job"] = signal.data["job"] + log.parameters["key"] = signal.data["key"] + log.parameters["message"] = signal.data["message"] + log.parameters["name"] = signal.data["name"] + log.parameters["realname"] = signal.data["realname"] + + if(!istype(M, /mob/new_player) && istype(M)) + log.parameters["uspeech"] = M.universal_speak + else + log.parameters["uspeech"] = 0 + + + + // If the signal is still compressed, make the log entry gibberish + if(signal.data["compression"] > 0) + log.parameters["message"] = Gibberish(signal.data["message"], signal.data["compression"] + 50) + log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50) + log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50) + log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50) + log.input_type = "Corrupt File" + + // Log and store everything that needs to be logged + log_entries.Add(log) + if(!(signal.data["name"] in stored_names)) + stored_names.Add(signal.data["name"]) + logs++ + signal.data["server"] = src + + // Give the log a name + var/identifier = num2text( rand(-1000,1000) + world.time ) + log.name = "data packet ([md5(identifier)])" + + if(Compiler && autoruncode) + Compiler.Run(signal) // execute the code + + var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub") + if(!can_send) + relay_information(signal, "/obj/machinery/telecomms/broadcaster") + + +/obj/machinery/telecomms/server/proc/setcode(var/t) + if(t) + if(istext(t)) + rawcode = t + +/obj/machinery/telecomms/server/proc/admin_log(var/mob/mob) + var/msg = "[key_name(mob)] has compiled a script to [src.id]" + + diary << msg + diary << rawcode + + investigation_log("ntsl", "[msg]
                      [rawcode]
                      ") + + if (length(rawcode)) // Let's not bother the admins for empty code. + message_admins("[msg] ([formatJumpTo(mob)])", 0, 1) + +/obj/machinery/telecomms/server/proc/compile(var/mob/user) + + + if(Compiler) + admin_log(user) + return Compiler.Compile(rawcode) + +/obj/machinery/telecomms/server/proc/update_logs() + // start deleting the very first log entry + if(logs >= 400) + for(var/i = 1, i <= logs, i++) // locate the first garbage collectable log entry and remove it + var/datum/comm_log_entry/L = log_entries[i] + if(L.garbage_collector) + log_entries.Remove(L) + logs-- + break + +/obj/machinery/telecomms/server/proc/add_entry(var/content, var/input) + var/datum/comm_log_entry/log = new + var/identifier = num2text( rand(-1000,1000) + world.time ) + log.name = "[input] ([md5(identifier)])" + log.input_type = input + log.parameters["message"] = content + log_entries.Add(log) + update_logs() + +// Simple log entry datum + +/datum/comm_log_entry + var/parameters = list() // carbon-copy to signal.data[] + var/name = "data packet (#)" + var/garbage_collector = 1 // if set to 0, will not be garbage collected + var/input_type = "Speech File" + + + + + + + diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 759bd369fb0..993983e3313 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -1,167 +1,167 @@ -/obj/machinery/transformer - name = "Automatic Robotic Factory 5000" - desc = "A large metallic machine with an entrance and an exit. A sign on the side reads 'human goes in, robot comes out'. Human must be lying down and alive. Has to cooldown between each use." - icon = 'icons/obj/recycling.dmi' - icon_state = "separator-AO1" - layer = MOB_LAYER+1 // Overhead - anchored = 1 - density = 1 - var/transform_dead = 0 //This variable doesn't seem to do anything - var/transform_standing = 0 - var/cooldown_duration = 900 // 1.5 minutes - var/cooldown_time = 0 - var/cooldown_state = 0 // Just for icons. - var/robot_cell_charge = 5000 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 5000 - - // /vg/ - var/force_borg_module=null - -/obj/machinery/transformer/New() - // On us - ..() - new /obj/machinery/conveyor/auto(loc, WEST) - -/obj/machinery/transformer/power_change() - ..() - update_icon() - -/obj/machinery/transformer/update_icon() - ..() - if(stat & (BROKEN|NOPOWER) || cooldown_time > world.time) - icon_state = "separator-AO0" - else - icon_state = initial(icon_state) - -/obj/machinery/transformer/Bumped(var/atom/movable/AM) - if(cooldown_state) - return - - // Crossed didn't like people lying down. - if(ishuman(AM)) - // Only humans can enter from the west side, while lying down. - var/move_dir = get_dir(loc, AM.loc) - var/mob/living/carbon/human/H = AM - if((transform_standing || H.lying) && move_dir == EAST)// || move_dir == WEST) - AM.loc = src.loc - do_transform(AM) - //Shit bugs out if theres too many items on the enter side conveyer - else if(istype(AM, /obj/item)) - var/move_dir = get_dir(loc, AM.loc) - if(move_dir == EAST) - AM.loc = src.loc - -/obj/machinery/transformer/proc/do_transform(var/mob/living/carbon/human/H) - if(stat & (BROKEN|NOPOWER)) - return - if(cooldown_state) - return - - if(!transform_dead && H.stat == DEAD) - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) - return - - if(jobban_isbanned(H, "Cyborg")) - src.visible_message("\The [src.name] throws an exception. Lifeform not compatible with factory.") - return - - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - H.emote("scream",,, 1) // It is painful - H.adjustBruteLoss(max(0, 80 - H.getBruteLoss())) // Hurt the human, don't try to kill them though. - H.handle_regular_hud_updates() // Make sure they see the pain. - - // Sleep for a couple of ticks to allow the human to see the pain - sleep(5) - - var/mob/living/silicon/robot/R = H.Robotize(1) // Delete the items or they'll all pile up in a single tile and lag - if(R) - R.cell.maxcharge = robot_cell_charge - R.cell.charge = robot_cell_charge - - // So he can't jump out the gate right away. - R.weakened = 5 - - // /vg/: Force borg module, if needed. - R.pick_module(force_borg_module) - R.updateicon() - - spawn(50) - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 0) - if(R) - R.weakened = 0 - - // Activate the cooldown - cooldown_time = world.time + cooldown_duration - cooldown_state = 1 - update_icon() - -/obj/machinery/transformer/process() - ..() - var/old_cooldown_state=cooldown_state - cooldown_state = cooldown_time > world.time - if(cooldown_state!=old_cooldown_state) - update_icon() - if(!cooldown_state) - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) - -/obj/machinery/transformer/conveyor/New() - ..() - var/turf/T = loc - if(T) - // Spawn Conveyour Belts - - //East - var/turf/east = locate(T.x + 1, T.y, T.z) - if(istype(east, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(east, WEST) - - // West - var/turf/west = locate(T.x - 1, T.y, T.z) - if(istype(west, /turf/simulated/floor)) - new /obj/machinery/conveyor/auto(west, WEST) - -/obj/machinery/transformer/attack_ai(var/mob/user) - interact(user) - -/obj/machinery/transformer/interact(var/mob/user) - var/data="" - if(cooldown_state) - data += {"Recalibrating. Time left: [(cooldown_time - world.time)/10] seconds."} - else - data += {"

                      ROBOTICIZER ACTIVE.

                      "} - data += {" -

                      Settings

                      - - "} - - var/datum/browser/popup = new(user, "transformer", src.name, 400, 300) - popup.set_content(data) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() - -/obj/machinery/transformer/Topic(href, href_list) - if(!isAI(usr)) +/obj/machinery/transformer + name = "Automatic Robotic Factory 5000" + desc = "A large metallic machine with an entrance and an exit. A sign on the side reads 'human goes in, robot comes out'. Human must be lying down and alive. Has to cooldown between each use." + icon = 'icons/obj/recycling.dmi' + icon_state = "separator-AO1" + layer = MOB_LAYER+1 // Overhead + anchored = 1 + density = 1 + var/transform_dead = 0 //This variable doesn't seem to do anything + var/transform_standing = 0 + var/cooldown_duration = 900 // 1.5 minutes + var/cooldown_time = 0 + var/cooldown_state = 0 // Just for icons. + var/robot_cell_charge = 5000 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 5000 + + // /vg/ + var/force_borg_module=null + +/obj/machinery/transformer/New() + // On us + ..() + new /obj/machinery/conveyor/auto(loc, WEST) + +/obj/machinery/transformer/power_change() + ..() + update_icon() + +/obj/machinery/transformer/update_icon() + ..() + if(stat & (BROKEN|NOPOWER) || cooldown_time > world.time) + icon_state = "separator-AO0" + else + icon_state = initial(icon_state) + +/obj/machinery/transformer/Bumped(var/atom/movable/AM) + if(cooldown_state) + return + + // Crossed didn't like people lying down. + if(ishuman(AM)) + // Only humans can enter from the west side, while lying down. + var/move_dir = get_dir(loc, AM.loc) + var/mob/living/carbon/human/H = AM + if((transform_standing || H.lying) && move_dir == EAST)// || move_dir == WEST) + AM.loc = src.loc + do_transform(AM) + //Shit bugs out if theres too many items on the enter side conveyer + else if(istype(AM, /obj/item)) + var/move_dir = get_dir(loc, AM.loc) + if(move_dir == EAST) + AM.loc = src.loc + +/obj/machinery/transformer/proc/do_transform(var/mob/living/carbon/human/H) + if(stat & (BROKEN|NOPOWER)) + return + if(cooldown_state) + return + + if(!transform_dead && H.stat == DEAD) + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + return + + if(jobban_isbanned(H, "Cyborg")) + src.visible_message("\The [src.name] throws an exception. Lifeform not compatible with factory.") + return + + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + H.emote("scream",,, 1) // It is painful + H.adjustBruteLoss(max(0, 80 - H.getBruteLoss())) // Hurt the human, don't try to kill them though. + H.handle_regular_hud_updates() // Make sure they see the pain. + + // Sleep for a couple of ticks to allow the human to see the pain + sleep(5) + + var/mob/living/silicon/robot/R = H.Robotize(1) // Delete the items or they'll all pile up in a single tile and lag + if(R) + R.cell.maxcharge = robot_cell_charge + R.cell.charge = robot_cell_charge + + // So he can't jump out the gate right away. + R.weakened = 5 + + // /vg/: Force borg module, if needed. + R.pick_module(force_borg_module) + R.updateicon() + + spawn(50) + playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 0) + if(R) + R.weakened = 0 + + // Activate the cooldown + cooldown_time = world.time + cooldown_duration + cooldown_state = 1 + update_icon() + +/obj/machinery/transformer/process() + ..() + var/old_cooldown_state=cooldown_state + cooldown_state = cooldown_time > world.time + if(cooldown_state!=old_cooldown_state) + update_icon() + if(!cooldown_state) + playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + +/obj/machinery/transformer/conveyor/New() + ..() + var/turf/T = loc + if(T) + // Spawn Conveyour Belts + + //East + var/turf/east = locate(T.x + 1, T.y, T.z) + if(istype(east, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(east, WEST) + + // West + var/turf/west = locate(T.x - 1, T.y, T.z) + if(istype(west, /turf/simulated/floor)) + new /obj/machinery/conveyor/auto(west, WEST) + +/obj/machinery/transformer/attack_ai(var/mob/user) + interact(user) + +/obj/machinery/transformer/interact(var/mob/user) + var/data="" + if(cooldown_state) + data += {"Recalibrating. Time left: [(cooldown_time - world.time)/10] seconds."} + else + data += {"

                      ROBOTICIZER ACTIVE.

                      "} + data += {" +

                      Settings

                      + + "} + + var/datum/browser/popup = new(user, "transformer", src.name, 400, 300) + popup.set_content(data) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.open() + +/obj/machinery/transformer/Topic(href, href_list) + if(!isAI(usr)) to_chat(usr, "This machine is way above your pay-grade.") - return 0 - if(!("act" in href_list)) - return 0 - switch(href_list["act"]) - if("force_class") - var/list/modules = list("(Robot's Choice)") - modules += getAvailableRobotModules() - var/sel_mod = input("Please, select a module!", "Robot", null, null) as null|anything in modules - if(!sel_mod) - return - if(sel_mod == "(Robot's Choice)") - force_borg_module = null - else - force_borg_module = sel_mod - interact(usr) + return 0 + if(!("act" in href_list)) + return 0 + switch(href_list["act"]) + if("force_class") + var/list/modules = list("(Robot's Choice)") + modules += getAvailableRobotModules() + var/sel_mod = input("Please, select a module!", "Robot", null, null) as null|anything in modules + if(!sel_mod) + return + if(sel_mod == "(Robot's Choice)") + force_borg_module = null + else + force_borg_module = sel_mod + interact(usr) return 1 \ No newline at end of file diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 857c80e3475..6ca59a510d3 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -1,677 +1,677 @@ -/area/turret_protected - name = "Turret Protected Area" - var/list/turretTargets = list() - -/area/turret_protected/proc/subjectDied(target) - if( isliving(target) ) - if( !issilicon(target) ) - var/mob/living/L = target - if( L.stat ) - if( L in turretTargets ) - src.Exited(L) - - -/area/turret_protected/Entered(O) - ..() - - if( iscarbon(O) ) - turretTargets |= O - else if( istype(O, /obj/mecha) ) - var/obj/mecha/Mech = O - if( Mech.occupant ) - turretTargets |= Mech - // /vg/ vehicles - else if( istype(O, /obj/structure/bed/chair/vehicle) ) - turretTargets |= O - else if(istype(O,/mob/living/simple_animal)) - turretTargets |= O - return 1 - -/area/turret_protected/Exited(O) - if( ismob(O) && !issilicon(O) ) - turretTargets -= O - // /vg/ vehicles - else if( istype(O, /obj/structure/bed/chair/vehicle) ) - turretTargets -= O - else if( istype(O, /obj/mecha) ) - turretTargets -= O - ..() - return 1 - - -/obj/machinery/turret - name = "turret" - icon = 'icons/obj/turrets.dmi' - icon_state = "grey_target_prism" - var/raised = 0 - var/enabled = 1 - anchored = 1 - layer = 3 - invisibility = INVISIBILITY_LEVEL_TWO - density = 1 - var/lasers = 0 - var/lasertype = 1 - // 1 = lasers - // 2 = cannons - // 3 = pulse - // 4 = change (HONK) - // 5 = bluetag - // 6 = redtag - var/health = 80 - var/obj/machinery/turretcover/cover = null - var/popping = 0 - var/wasvalid = 0 - var/lastfired = 0 - var/shot_delay = 30 //3 seconds between shots - var/datum/effect/effect/system/spark_spread/spark_system - use_power = 1 - idle_power_usage = 50 - active_power_usage = 300 -// var/list/targets - var/atom/movable/cur_target - var/targeting_active = 0 - var/area/turret_protected/protected_area - - -/obj/machinery/turret/New() - spark_system = new /datum/effect/effect/system/spark_spread - spark_system.set_up(5, 0, src) - spark_system.attach(src) -// targets = new - ..() - return - -/obj/machinery/turretcover - name = "pop-up turret cover" - icon = 'icons/obj/turrets.dmi' - icon_state = "turretCover" - anchored = 1 - layer = 3.5 - density = 0 - var/obj/machinery/turret/host = null - -/obj/machinery/turret/proc/isPopping() - return (popping!=0) - -/obj/machinery/turret/power_change() - if(stat & BROKEN) - icon_state = "grey_target_prism" - else - if( powered() ) - if (src.enabled) - if (src.lasers) - icon_state = "orange_target_prism" - else - icon_state = "target_prism" - else - icon_state = "grey_target_prism" - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - src.icon_state = "grey_target_prism" - stat |= NOPOWER - -/obj/machinery/turret/proc/setState(var/enabled, var/lethal) - src.enabled = enabled - src.lasers = lethal - src.power_change() - - -/obj/machinery/turret/proc/get_protected_area() - var/area/turret_protected/TP = get_area(src) - if(istype(TP)) - return TP - return - -/obj/machinery/turret/proc/check_target(var/atom/movable/T as mob|obj) - if( T && T in protected_area.turretTargets ) - var/area/area_T = get_area(T) - if( !area_T || (area_T.type != protected_area.type) ) - protected_area.Exited(T) - return 0 //If the guy is somehow not in the turret's area (teleportation), get them out the damn list. --NEO - if( ismob(T) ) - var/mob/M = T - if(M.flags & INVULNERABLE) - return 0 - if( iscarbon(T) ) - var/mob/living/carbon/MC = T - if( !MC.stat ) - if( !MC.lying || lasers ) - return 1 - else if( istype(T, /obj/mecha) ) - var/obj/mecha/ME = T - if( ME.occupant ) - return 1 - // /vg/ vehicles - else if( istype(T, /obj/structure/bed/chair/vehicle) ) - var/obj/structure/bed/chair/vehicle/V = T - if(V.locked_atoms.len) - return 1 - else if(istype(T,/mob/living/simple_animal)) - var/mob/living/simple_animal/A = T - if( !A.stat ) - if(lasers || ismouse(A)) - return 1 - return 0 - -/obj/machinery/turret/proc/get_new_target() - var/list/new_targets = new - var/new_target - for(var/mob/living/carbon/M in protected_area.turretTargets) - if(!M.stat && !(M.flags & INVULNERABLE)) - if(!M.lying || lasers) - new_targets += M - for(var/obj/mecha/M in protected_area.turretTargets) - if(M.occupant) - new_targets += M - - // /vg/ vehicles - for(var/obj/structure/bed/chair/vehicle/V in protected_area.turretTargets) - if(V.locked_atoms.len) - new_targets += V - - for(var/mob/living/simple_animal/M in protected_area.turretTargets) - if(!M.stat && !(M.flags & INVULNERABLE)) - new_targets += M - if(new_targets.len) - new_target = pick(new_targets) - return new_target - - -/obj/machinery/turret/process() - if(stat & (NOPOWER|BROKEN)) - return - if(src.cover==null) - src.cover = new /obj/machinery/turretcover(src.loc) - src.cover.host = src - protected_area = get_protected_area() - if(!enabled || !protected_area || protected_area.turretTargets.len<=0) - if(!isDown() && !isPopping()) - popDown() - return - if(!check_target(cur_target)) //if current target fails target check - cur_target = get_new_target() //get new target - - if(cur_target) //if it's found, proceed +/area/turret_protected + name = "Turret Protected Area" + var/list/turretTargets = list() + +/area/turret_protected/proc/subjectDied(target) + if( isliving(target) ) + if( !issilicon(target) ) + var/mob/living/L = target + if( L.stat ) + if( L in turretTargets ) + src.Exited(L) + + +/area/turret_protected/Entered(O) + ..() + + if( iscarbon(O) ) + turretTargets |= O + else if( istype(O, /obj/mecha) ) + var/obj/mecha/Mech = O + if( Mech.occupant ) + turretTargets |= Mech + // /vg/ vehicles + else if( istype(O, /obj/structure/bed/chair/vehicle) ) + turretTargets |= O + else if(istype(O,/mob/living/simple_animal)) + turretTargets |= O + return 1 + +/area/turret_protected/Exited(O) + if( ismob(O) && !issilicon(O) ) + turretTargets -= O + // /vg/ vehicles + else if( istype(O, /obj/structure/bed/chair/vehicle) ) + turretTargets -= O + else if( istype(O, /obj/mecha) ) + turretTargets -= O + ..() + return 1 + + +/obj/machinery/turret + name = "turret" + icon = 'icons/obj/turrets.dmi' + icon_state = "grey_target_prism" + var/raised = 0 + var/enabled = 1 + anchored = 1 + layer = 3 + invisibility = INVISIBILITY_LEVEL_TWO + density = 1 + var/lasers = 0 + var/lasertype = 1 + // 1 = lasers + // 2 = cannons + // 3 = pulse + // 4 = change (HONK) + // 5 = bluetag + // 6 = redtag + var/health = 80 + var/obj/machinery/turretcover/cover = null + var/popping = 0 + var/wasvalid = 0 + var/lastfired = 0 + var/shot_delay = 30 //3 seconds between shots + var/datum/effect/effect/system/spark_spread/spark_system + use_power = 1 + idle_power_usage = 50 + active_power_usage = 300 +// var/list/targets + var/atom/movable/cur_target + var/targeting_active = 0 + var/area/turret_protected/protected_area + + +/obj/machinery/turret/New() + spark_system = new /datum/effect/effect/system/spark_spread + spark_system.set_up(5, 0, src) + spark_system.attach(src) +// targets = new + ..() + return + +/obj/machinery/turretcover + name = "pop-up turret cover" + icon = 'icons/obj/turrets.dmi' + icon_state = "turretCover" + anchored = 1 + layer = 3.5 + density = 0 + var/obj/machinery/turret/host = null + +/obj/machinery/turret/proc/isPopping() + return (popping!=0) + +/obj/machinery/turret/power_change() + if(stat & BROKEN) + icon_state = "grey_target_prism" + else + if( powered() ) + if (src.enabled) + if (src.lasers) + icon_state = "orange_target_prism" + else + icon_state = "target_prism" + else + icon_state = "grey_target_prism" + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + src.icon_state = "grey_target_prism" + stat |= NOPOWER + +/obj/machinery/turret/proc/setState(var/enabled, var/lethal) + src.enabled = enabled + src.lasers = lethal + src.power_change() + + +/obj/machinery/turret/proc/get_protected_area() + var/area/turret_protected/TP = get_area(src) + if(istype(TP)) + return TP + return + +/obj/machinery/turret/proc/check_target(var/atom/movable/T as mob|obj) + if( T && T in protected_area.turretTargets ) + var/area/area_T = get_area(T) + if( !area_T || (area_T.type != protected_area.type) ) + protected_area.Exited(T) + return 0 //If the guy is somehow not in the turret's area (teleportation), get them out the damn list. --NEO + if( ismob(T) ) + var/mob/M = T + if(M.flags & INVULNERABLE) + return 0 + if( iscarbon(T) ) + var/mob/living/carbon/MC = T + if( !MC.stat ) + if( !MC.lying || lasers ) + return 1 + else if( istype(T, /obj/mecha) ) + var/obj/mecha/ME = T + if( ME.occupant ) + return 1 + // /vg/ vehicles + else if( istype(T, /obj/structure/bed/chair/vehicle) ) + var/obj/structure/bed/chair/vehicle/V = T + if(V.locked_atoms.len) + return 1 + else if(istype(T,/mob/living/simple_animal)) + var/mob/living/simple_animal/A = T + if( !A.stat ) + if(lasers || ismouse(A)) + return 1 + return 0 + +/obj/machinery/turret/proc/get_new_target() + var/list/new_targets = new + var/new_target + for(var/mob/living/carbon/M in protected_area.turretTargets) + if(!M.stat && !(M.flags & INVULNERABLE)) + if(!M.lying || lasers) + new_targets += M + for(var/obj/mecha/M in protected_area.turretTargets) + if(M.occupant) + new_targets += M + + // /vg/ vehicles + for(var/obj/structure/bed/chair/vehicle/V in protected_area.turretTargets) + if(V.locked_atoms.len) + new_targets += V + + for(var/mob/living/simple_animal/M in protected_area.turretTargets) + if(!M.stat && !(M.flags & INVULNERABLE)) + new_targets += M + if(new_targets.len) + new_target = pick(new_targets) + return new_target + + +/obj/machinery/turret/process() + if(stat & (NOPOWER|BROKEN)) + return + if(src.cover==null) + src.cover = new /obj/machinery/turretcover(src.loc) + src.cover.host = src + protected_area = get_protected_area() + if(!enabled || !protected_area || protected_area.turretTargets.len<=0) + if(!isDown() && !isPopping()) + popDown() + return + if(!check_target(cur_target)) //if current target fails target check + cur_target = get_new_target() //get new target + + if(cur_target) //if it's found, proceed // to_chat(world, "[cur_target]") - if(!isPopping()) - if(isDown()) - popUp() - use_power = 2 - else - spawn() - if(!targeting_active) - targeting_active = 1 - target() - targeting_active = 0 - - if(prob(15)) - if(prob(50)) - playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) - else - playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) - else if(!isPopping())//else, pop down - if(!isDown()) - popDown() - use_power = 1 - return - - -/obj/machinery/turret/proc/target() - while(src && enabled && !stat && check_target(cur_target)) - src.dir = get_dir(src, cur_target) - shootAt(cur_target) - sleep(shot_delay) - return - -/obj/machinery/turret/proc/shootAt(var/atom/movable/target) - var/turf/T = get_turf(src) - var/turf/U = get_turf(target) - var/fire_sound = 'sound/weapons/Laser.ogg' - if (!T || !U) - return - var/obj/item/projectile/A - if (src.lasers) - switch(lasertype) - if(1) - A = getFromPool(/obj/item/projectile/beam, loc) - if(2) - A = getFromPool(/obj/item/projectile/beam/heavylaser, loc) - fire_sound = 'sound/weapons/lasercannonfire.ogg' - if(3) - A = getFromPool(/obj/item/projectile/beam/pulse, loc) - fire_sound = 'sound/weapons/pulse.ogg' - if(4) - A = getFromPool(/obj/item/projectile/change, loc) - fire_sound = 'sound/weapons/radgun.ogg' - if(5) - A = getFromPool(/obj/item/projectile/beam/lastertag/blue, loc) - if(6) - A = getFromPool(/obj/item/projectile/beam/lastertag/red, loc) - use_power(500) - else - A = new /obj/item/projectile/energy/electrode( loc ) - fire_sound = 'sound/weapons/Taser.ogg' - use_power(200) - - A.original = target - A.target = U - A.current = T - A.starting = T - A.yo = U.y - T.y - A.xo = U.x - T.x - playsound(T, fire_sound, 50, 1) - A.OnFired() - A.process() - return - - -/obj/machinery/turret/proc/isDown() - return (invisibility!=0) - -/obj/machinery/turret/proc/popUp() - if ((!isPopping()) || src.popping==-1) - invisibility = 0 - popping = 1 - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) - if (src.cover!=null) - flick("popup", src.cover) - src.cover.icon_state = "openTurretCover" - spawn(10) - if (popping==1) popping = 0 - -/obj/machinery/turret/proc/popDown() - if ((!isPopping()) || src.popping==1) - popping = -1 - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) - if (src.cover!=null) - flick("popdown", src.cover) - src.cover.icon_state = "turretCover" - spawn(10) - if (popping==-1) - invisibility = INVISIBILITY_LEVEL_TWO - popping = 0 - -/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj) - src.health -= Proj.damage - ..() - if(prob(45) && Proj.damage > 0) src.spark_system.start() - - if (src.health <= 0) - src.die() - return - -/obj/machinery/turret/attackby(obj/item/weapon/W, mob/user)//I can't believe no one added this before/N - user.delayNextAttack(10) - if(..()) - return 1 - playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1) - src.spark_system.start() - src.health -= W.force * 0.5 - if (src.health <= 0) - src.die() - return - -/obj/machinery/turret/emp_act(severity) - switch(severity) - if(1) - enabled = 0 - lasers = 0 - power_change() - ..() - -/obj/machinery/turret/ex_act(severity) - if(severity < 3) - src.die() - -/obj/machinery/turret/proc/die() - src.health = 0 - src.density = 0 - src.stat |= BROKEN - src.icon_state = "destroyed_target_prism" - if (cover!=null) - qdel(cover) - cover = null - sleep(3) - flick("explosion", src) - spawn(13) - qdel(src) - -/obj/machinery/turretid - name = "Turret deactivation control" - icon = 'icons/obj/device.dmi' - icon_state = "motion3" - anchored = 1 - density = 0 - var/enabled = 1 - var/lethal = 0 - var/locked = 1 - var/area/turret_protected/control_area //can be area name, path or nothing. - var/ailock = 0 // AI cannot use this - req_access = list(access_ai_upload) - - ghost_read=0 - - machine_flags = EMAGGABLE - -/obj/machinery/turretid/New() - ..() - if(!control_area) - control_area = get_area(src) - else if(istext(control_area)) - for(var/area/A in areas) - if(A.name && A.name==control_area) - control_area = A - break - else if(ispath(control_area)) - control_area = locate(control_area) - - return - -/obj/machinery/turretid/emag(mob/user) - if(!emagged) + if(!isPopping()) + if(isDown()) + popUp() + use_power = 2 + else + spawn() + if(!targeting_active) + targeting_active = 1 + target() + targeting_active = 0 + + if(prob(15)) + if(prob(50)) + playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + else + playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + else if(!isPopping())//else, pop down + if(!isDown()) + popDown() + use_power = 1 + return + + +/obj/machinery/turret/proc/target() + while(src && enabled && !stat && check_target(cur_target)) + src.dir = get_dir(src, cur_target) + shootAt(cur_target) + sleep(shot_delay) + return + +/obj/machinery/turret/proc/shootAt(var/atom/movable/target) + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + var/fire_sound = 'sound/weapons/Laser.ogg' + if (!T || !U) + return + var/obj/item/projectile/A + if (src.lasers) + switch(lasertype) + if(1) + A = getFromPool(/obj/item/projectile/beam, loc) + if(2) + A = getFromPool(/obj/item/projectile/beam/heavylaser, loc) + fire_sound = 'sound/weapons/lasercannonfire.ogg' + if(3) + A = getFromPool(/obj/item/projectile/beam/pulse, loc) + fire_sound = 'sound/weapons/pulse.ogg' + if(4) + A = getFromPool(/obj/item/projectile/change, loc) + fire_sound = 'sound/weapons/radgun.ogg' + if(5) + A = getFromPool(/obj/item/projectile/beam/lastertag/blue, loc) + if(6) + A = getFromPool(/obj/item/projectile/beam/lastertag/red, loc) + use_power(500) + else + A = new /obj/item/projectile/energy/electrode( loc ) + fire_sound = 'sound/weapons/Taser.ogg' + use_power(200) + + A.original = target + A.target = U + A.current = T + A.starting = T + A.yo = U.y - T.y + A.xo = U.x - T.x + playsound(T, fire_sound, 50, 1) + A.OnFired() + A.process() + return + + +/obj/machinery/turret/proc/isDown() + return (invisibility!=0) + +/obj/machinery/turret/proc/popUp() + if ((!isPopping()) || src.popping==-1) + invisibility = 0 + popping = 1 + playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + if (src.cover!=null) + flick("popup", src.cover) + src.cover.icon_state = "openTurretCover" + spawn(10) + if (popping==1) popping = 0 + +/obj/machinery/turret/proc/popDown() + if ((!isPopping()) || src.popping==1) + popping = -1 + playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + if (src.cover!=null) + flick("popdown", src.cover) + src.cover.icon_state = "turretCover" + spawn(10) + if (popping==-1) + invisibility = INVISIBILITY_LEVEL_TWO + popping = 0 + +/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj) + src.health -= Proj.damage + ..() + if(prob(45) && Proj.damage > 0) src.spark_system.start() + + if (src.health <= 0) + src.die() + return + +/obj/machinery/turret/attackby(obj/item/weapon/W, mob/user)//I can't believe no one added this before/N + user.delayNextAttack(10) + if(..()) + return 1 + playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1) + src.spark_system.start() + src.health -= W.force * 0.5 + if (src.health <= 0) + src.die() + return + +/obj/machinery/turret/emp_act(severity) + switch(severity) + if(1) + enabled = 0 + lasers = 0 + power_change() + ..() + +/obj/machinery/turret/ex_act(severity) + if(severity < 3) + src.die() + +/obj/machinery/turret/proc/die() + src.health = 0 + src.density = 0 + src.stat |= BROKEN + src.icon_state = "destroyed_target_prism" + if (cover!=null) + qdel(cover) + cover = null + sleep(3) + flick("explosion", src) + spawn(13) + qdel(src) + +/obj/machinery/turretid + name = "Turret deactivation control" + icon = 'icons/obj/device.dmi' + icon_state = "motion3" + anchored = 1 + density = 0 + var/enabled = 1 + var/lethal = 0 + var/locked = 1 + var/area/turret_protected/control_area //can be area name, path or nothing. + var/ailock = 0 // AI cannot use this + req_access = list(access_ai_upload) + + ghost_read=0 + + machine_flags = EMAGGABLE + +/obj/machinery/turretid/New() + ..() + if(!control_area) + control_area = get_area(src) + else if(istext(control_area)) + for(var/area/A in areas) + if(A.name && A.name==control_area) + control_area = A + break + else if(ispath(control_area)) + control_area = locate(control_area) + + return + +/obj/machinery/turretid/emag(mob/user) + if(!emagged) to_chat(user, "You short out the turret controls' access analysis module.") - emagged = 1 - locked = 0 - if(user.machine==src) - src.attack_hand(user) - return 1 - return - -/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user) - if(stat & BROKEN) return - if (istype(user, /mob/living/silicon)) - return src.attack_hand(user) - - ..() - - if( get_dist(src, user) == 0 ) // trying to unlock the interface - if (src.allowed(usr)) - if(emagged) + emagged = 1 + locked = 0 + if(user.machine==src) + src.attack_hand(user) + return 1 + return + +/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user) + if(stat & BROKEN) return + if (istype(user, /mob/living/silicon)) + return src.attack_hand(user) + + ..() + + if( get_dist(src, user) == 0 ) // trying to unlock the interface + if (src.allowed(usr)) + if(emagged) to_chat(user, "The turret control is unresponsive.") - return - - locked = !locked + return + + locked = !locked to_chat(user, "You [ locked ? "lock" : "unlock"] the panel.") - if (locked) - if (user.machine==src) - user.unset_machine() - user << browse(null, "window=turretid") - else - if (user.machine==src) - src.attack_hand(user) - else + if (locked) + if (user.machine==src) + user.unset_machine() + user << browse(null, "window=turretid") + else + if (user.machine==src) + src.attack_hand(user) + else to_chat(user, "Access denied.") - -/obj/machinery/turretid/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - if(!ailock) - return attack_hand(user) - else + +/obj/machinery/turretid/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + if(!ailock) + return attack_hand(user) + else to_chat(user, "There seems to be a firewall preventing you from accessing this device.") - -/obj/machinery/turretid/attack_hand(mob/user as mob) - if ( get_dist(src, user) > 0 ) - if ( !issilicon(user) ) + +/obj/machinery/turretid/attack_hand(mob/user as mob) + if ( get_dist(src, user) > 0 ) + if ( !issilicon(user) ) to_chat(user, "You are too far away.") - user.unset_machine() - user << browse(null, "window=turretid") - return - - user.set_machine(src) - var/loc = src.loc - if (istype(loc, /turf)) - loc = loc:loc - if (!istype(loc, /area)) + user.unset_machine() + user << browse(null, "window=turretid") + return + + user.set_machine(src) + var/loc = src.loc + if (istype(loc, /turf)) + loc = loc:loc + if (!istype(loc, /area)) to_chat(user, text("Turret badly positioned - loc.loc is [].", loc)) - return - var/area/area = loc - var/t = "Turret Control Panel ([area.name])
                      " - - if(src.locked && (!istype(user, /mob/living/silicon))) - t += "(Swipe ID card to unlock control panel.)
                      " - else - t += text("Turrets [] - []?
                      \n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable") - t += text("Currently set for [] - Change to []?
                      \n", src.lethal?"lethal":"stun repeatedly", src, src.lethal?"Stun repeatedly":"Lethal") - - user << browse(t, "window=turretid") - onclose(user, "turretid") - - -/obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob) - if(M.melee_damage_upper == 0) return - if(!(stat & BROKEN)) - visible_message("[M] [M.attacktext] [src]!") - M.attack_log += text("\[[time_stamp()]\] attacked [src.name]") - //src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") - src.health -= M.melee_damage_upper - if (src.health <= 0) - src.die() - else + return + var/area/area = loc + var/t = "Turret Control Panel ([area.name])
                      " + + if(src.locked && (!istype(user, /mob/living/silicon))) + t += "(Swipe ID card to unlock control panel.)
                      " + else + t += text("Turrets [] - []?
                      \n", src.enabled?"activated":"deactivated", src, src.enabled?"Disable":"Enable") + t += text("Currently set for [] - Change to []?
                      \n", src.lethal?"lethal":"stun repeatedly", src, src.lethal?"Stun repeatedly":"Lethal") + + user << browse(t, "window=turretid") + onclose(user, "turretid") + + +/obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob) + if(M.melee_damage_upper == 0) return + if(!(stat & BROKEN)) + visible_message("[M] [M.attacktext] [src]!") + M.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + //src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") + src.health -= M.melee_damage_upper + if (src.health <= 0) + src.die() + else to_chat(M, "That object is useless to you.") - return - - - - -/obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if(!(stat & BROKEN)) - playsound(get_turf(src), 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("[] has slashed at []!", M, src) - src.health -= 15 - if (src.health <= 0) - src.die() - else + return + + + + +/obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + if(!(stat & BROKEN)) + playsound(get_turf(src), 'sound/weapons/slash.ogg', 25, 1, -1) + visible_message("[] has slashed at []!", M, src) + src.health -= 15 + if (src.health <= 0) + src.die() + else to_chat(M, "That object is useless to you.") - return - - - -/obj/machinery/turretid/Topic(href, href_list) - if(..()) - return 1 - if (src.locked) - if (!istype(usr, /mob/living/silicon)) + return + + + +/obj/machinery/turretid/Topic(href, href_list) + if(..()) + return 1 + if (src.locked) + if (!istype(usr, /mob/living/silicon)) to_chat(usr, "Control panel is locked!") - return - if ( get_dist(src, usr) == 0 || issilicon(usr)) - if (href_list["toggleOn"]) - src.enabled = !src.enabled - src.updateTurrets() - else if (href_list["toggleLethal"]) - src.lethal = !src.lethal - src.updateTurrets() - src.attack_hand(usr) - -/obj/machinery/turretid/proc/updateTurrets() - if(control_area) - //ASSERT(istype(control_area)) - for(var/obj/machinery/turret/aTurret in control_area.contents) - aTurret.setState(enabled, lethal) - src.update_icons() - -/obj/machinery/turretid/proc/update_icons() - if (src.enabled) - if (src.lethal) - icon_state = "motion1" - else - icon_state = "motion3" - else - icon_state = "motion0" - //CODE FIXED BUT REMOVED -// if(control_area) //USE: updates other controls in the area -// for (var/obj/machinery/turretid/Turret_Control in world) //I'm not sure if this is what it was -// if( Turret_Control.control_area != src.control_area ) continue //supposed to do. Or whether the person -// Turret_Control.icon_state = icon_state //who coded it originally was just tired -// Turret_Control.enabled = enabled //or something. I don't see any situation -// Turret_Control.lethal = lethal //in which this would be used on the current map. - //If he wants it back he can uncomment it - - -/obj/structure/turret/gun_turret - name = "Gun Turret" - density = 1 - anchored = 1 - var/cooldown = 20 - var/projectiles = 100 - var/projectiles_per_shot = 2 - var/deviation = 0.3 - var/list/exclude = list() - var/atom/cur_target - var/scan_range = 7 - var/health = 40 - var/list/scan_for = list("human"=0,"cyborg"=0,"mecha"=0,"alien"=1) - var/on = 0 - icon = 'icons/obj/turrets.dmi' - icon_state = "gun_turret" - - - ex_act() - qdel (src) - return - - emp_act() - qdel (src) - return - - proc/update_health() - if(src.health<=0) - qdel (src) - return - - proc/take_damage(damage) - src.health -= damage - if(src.health<=0) - qdel (src) - return - - - bullet_act(var/obj/item/projectile/Proj) - src.take_damage(Proj.damage) - ..() - return - - - attack_hand(mob/user as mob) - user.set_machine(src) - var/dat = {" - [src] Control - - Power: [on?"on":"off"]
                      - Scan Range: - [scan_range] +
                      - Scan for: "} - for(var/scan in scan_for) - dat += "" - - dat += {"Ammo: [max(0, projectiles)]
                      - - "} - user << browse(dat, "window=turret") - onclose(user, "turret") - return - - attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - - - attack_alien(mob/user as mob) - user.visible_message("[user] slashes at [src]", "You slash at [src]") - src.take_damage(15) - return - - Topic(href, href_list) - if(href_list["power"]) - src.on = !src.on - if(src.on) - spawn(50) - if(src) - src.process() - if(href_list["scan_range"]) - src.scan_range = Clamp(src.scan_range + text2num(href_list["scan_range"]), 1, 8) - if(href_list["scan_for"]) - if(href_list["scan_for"] in scan_for) - scan_for[href_list["scan_for"]] = !scan_for[href_list["scan_for"]] - src.updateUsrDialog() - return - - - proc/validate_target(atom/target) - if(get_dist(target, src)>scan_range) - return 0 - if(istype(target, /mob)) - var/mob/M = target - if(!M.stat && !M.lying)//ninjas can't catch you if you're lying - return 1 - else if(istype(target, /obj/mecha)) - return 1 - return 0 - - - process() - spawn while(on) - if(projectiles<=0) - on = 0 - return - if(cur_target && !validate_target(cur_target)) - cur_target = null - if(!cur_target) - cur_target = get_target() - fire(cur_target) - sleep(cooldown) - return - - proc/get_target() - var/list/pos_targets = list() - var/target = null - if(scan_for["human"]) - for(var/mob/living/carbon/human/M in oview(scan_range,src)) - if(M.stat || M.lying || M in exclude) - continue - pos_targets += M - if(scan_for["cyborg"]) - for(var/mob/living/silicon/M in oview(scan_range,src)) - if(M.stat || M.lying || M in exclude) - continue - pos_targets += M - if(scan_for["mecha"]) - for(var/obj/mecha/M in oview(scan_range, src)) - if(M in exclude) - continue - pos_targets += M - if(scan_for["alien"]) - for(var/mob/living/carbon/alien/M in oview(scan_range,src)) - if(M.stat || M.lying || M in exclude) - continue - pos_targets += M - if(pos_targets.len) - target = pick(pos_targets) - return target - - - proc/fire(atom/target) - if(!target) - cur_target = null - return - src.dir = get_dir(src,target) - spawn for(var/i=1 to min(projectiles, projectiles_per_shot)) - if(!src || !target) break - var/turf/curloc = get_turf(src) - var/turf/targloc = get_turf(target) - if (!targloc || !curloc) - continue - if (targloc == curloc) - continue - playsound(src, 'sound/weapons/Gunshot.ogg', 50, 1) - var/obj/item/projectile/A = new /obj/item/projectile(curloc) - src.projectiles-- - A.original = target - A.current = curloc - A.target = targloc - A.starting = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - A.OnFired() - A.process() - sleep(2) - return + return + if ( get_dist(src, usr) == 0 || issilicon(usr)) + if (href_list["toggleOn"]) + src.enabled = !src.enabled + src.updateTurrets() + else if (href_list["toggleLethal"]) + src.lethal = !src.lethal + src.updateTurrets() + src.attack_hand(usr) + +/obj/machinery/turretid/proc/updateTurrets() + if(control_area) + //ASSERT(istype(control_area)) + for(var/obj/machinery/turret/aTurret in control_area.contents) + aTurret.setState(enabled, lethal) + src.update_icons() + +/obj/machinery/turretid/proc/update_icons() + if (src.enabled) + if (src.lethal) + icon_state = "motion1" + else + icon_state = "motion3" + else + icon_state = "motion0" + //CODE FIXED BUT REMOVED +// if(control_area) //USE: updates other controls in the area +// for (var/obj/machinery/turretid/Turret_Control in world) //I'm not sure if this is what it was +// if( Turret_Control.control_area != src.control_area ) continue //supposed to do. Or whether the person +// Turret_Control.icon_state = icon_state //who coded it originally was just tired +// Turret_Control.enabled = enabled //or something. I don't see any situation +// Turret_Control.lethal = lethal //in which this would be used on the current map. + //If he wants it back he can uncomment it + + +/obj/structure/turret/gun_turret + name = "Gun Turret" + density = 1 + anchored = 1 + var/cooldown = 20 + var/projectiles = 100 + var/projectiles_per_shot = 2 + var/deviation = 0.3 + var/list/exclude = list() + var/atom/cur_target + var/scan_range = 7 + var/health = 40 + var/list/scan_for = list("human"=0,"cyborg"=0,"mecha"=0,"alien"=1) + var/on = 0 + icon = 'icons/obj/turrets.dmi' + icon_state = "gun_turret" + + + ex_act() + qdel (src) + return + + emp_act() + qdel (src) + return + + proc/update_health() + if(src.health<=0) + qdel (src) + return + + proc/take_damage(damage) + src.health -= damage + if(src.health<=0) + qdel (src) + return + + + bullet_act(var/obj/item/projectile/Proj) + src.take_damage(Proj.damage) + ..() + return + + + attack_hand(mob/user as mob) + user.set_machine(src) + var/dat = {" + [src] Control + + Power: [on?"on":"off"]
                      + Scan Range: - [scan_range] +
                      + Scan for: "} + for(var/scan in scan_for) + dat += "" + + dat += {"Ammo: [max(0, projectiles)]
                      + + "} + user << browse(dat, "window=turret") + onclose(user, "turret") + return + + attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + + + attack_alien(mob/user as mob) + user.visible_message("[user] slashes at [src]", "You slash at [src]") + src.take_damage(15) + return + + Topic(href, href_list) + if(href_list["power"]) + src.on = !src.on + if(src.on) + spawn(50) + if(src) + src.process() + if(href_list["scan_range"]) + src.scan_range = Clamp(src.scan_range + text2num(href_list["scan_range"]), 1, 8) + if(href_list["scan_for"]) + if(href_list["scan_for"] in scan_for) + scan_for[href_list["scan_for"]] = !scan_for[href_list["scan_for"]] + src.updateUsrDialog() + return + + + proc/validate_target(atom/target) + if(get_dist(target, src)>scan_range) + return 0 + if(istype(target, /mob)) + var/mob/M = target + if(!M.stat && !M.lying)//ninjas can't catch you if you're lying + return 1 + else if(istype(target, /obj/mecha)) + return 1 + return 0 + + + process() + spawn while(on) + if(projectiles<=0) + on = 0 + return + if(cur_target && !validate_target(cur_target)) + cur_target = null + if(!cur_target) + cur_target = get_target() + fire(cur_target) + sleep(cooldown) + return + + proc/get_target() + var/list/pos_targets = list() + var/target = null + if(scan_for["human"]) + for(var/mob/living/carbon/human/M in oview(scan_range,src)) + if(M.stat || M.lying || M in exclude) + continue + pos_targets += M + if(scan_for["cyborg"]) + for(var/mob/living/silicon/M in oview(scan_range,src)) + if(M.stat || M.lying || M in exclude) + continue + pos_targets += M + if(scan_for["mecha"]) + for(var/obj/mecha/M in oview(scan_range, src)) + if(M in exclude) + continue + pos_targets += M + if(scan_for["alien"]) + for(var/mob/living/carbon/alien/M in oview(scan_range,src)) + if(M.stat || M.lying || M in exclude) + continue + pos_targets += M + if(pos_targets.len) + target = pick(pos_targets) + return target + + + proc/fire(atom/target) + if(!target) + cur_target = null + return + src.dir = get_dir(src,target) + spawn for(var/i=1 to min(projectiles, projectiles_per_shot)) + if(!src || !target) break + var/turf/curloc = get_turf(src) + var/turf/targloc = get_turf(target) + if (!targloc || !curloc) + continue + if (targloc == curloc) + continue + playsound(src, 'sound/weapons/Gunshot.ogg', 50, 1) + var/obj/item/projectile/A = new /obj/item/projectile(curloc) + src.projectiles-- + A.original = target + A.current = curloc + A.target = targloc + A.starting = curloc + A.yo = targloc.y - curloc.y + A.xo = targloc.x - curloc.x + A.OnFired() + A.process() + sleep(2) + return diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 7070fc09255..90e89029085 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1,2247 +1,2247 @@ -#define CAT_NORMAL 1 -#define CAT_HIDDEN 2 -#define CAT_COIN 3 - -var/global/num_vending_terminals = 1 - -/datum/data/vending_product - var/product_name = "generic" - var/product_path = null - var/original_amount = 0 - var/amount = 0 - var/price = 0 - var/display_color = "blue" - var/category = CAT_NORMAL//available by default, contraband, or premium (requires a coin) - var/subcategory = null - -/* TODO: Add this to deconstruction for vending machines -/obj/item/compressed_vend - name = "compressed sale cartridge" - desc = "A compressed matter variant used to load vending machines." - icon = 'icons/obj/ammo.dmi' - icon_state = "rcd" - item_state = "rcdammo" - var/list/products - var/list/contraband - var/list/premium -*/ - -/obj/machinery/vending - name = "Empty vending machine" - desc = "Just add some capitalism." - icon = 'icons/obj/vending.dmi' - icon_state = "empty" - var/obj/structure/vendomatpack/pack = null - layer = 2.9 - anchored = 1 - density = 1 - var/health = 100 - var/maxhealth = 100 //Kicking feature - var/active = 1 //No sales pitches if off! - var/vend_ready = 1 //Are we ready to vend?? Is it time?? - var/vend_delay = 10 //How long does it take to vend? - var/shoot_chance = 2 //How often do we throw items? - var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now. - // To be filled out at compile time - var/list/products = list() // For each, use the following pattern: - var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2) - var/list/premium = list() // No specified amount = only one in stock - var/list/prices = list() // Prices for each item, list(/type/path = price), items not in the list don't have a price. - - var/product_slogans = "" //String of slogans separated by semicolons, optional - var/product_ads = "" //String of small ad messages in the vending screen - random chance - var/list/product_records = list() - var/list/hidden_records = list() - var/list/coin_records = list() - var/list/slogan_list = list() - var/list/small_ads = list() //Small ad messages in the vending screen - random chance of popping up whenever you open it - var/vend_reply //Thank you for shopping! - var/last_reply = 0 - var/last_slogan = 0 //When did we last pitch? - var/slogan_delay = 6000 //How long until we can pitch again? - var/icon_vend //Icon_state when vending! - var/icon_deny //Icon_state when vending! - //var/emagged = 0 //Ignores if somebody doesn't have card access to that machine. - var/seconds_electrified = 0 //Shock customers like an airlock. - var/shoot_inventory = 0 //Fire items at customers! We're broken! - var/shut_up = 0 //Stop spouting those godawful pitches! - var/extended_inventory = 0 //can we access the hidden inventory? - var/scan_id = 1 - var/obj/item/weapon/coin - var/datum/wires/vending/wires = null - var/list/overlays_vending[2]//1 is the panel layer, 2 is the dangermode layer - - var/list/vouchers - var/obj/item/weapon/storage/lockbox/coinbox/coinbox - var/cardboard = 0 //1 if sheets of cardboard are added - - var/list/categories = list() - var/list/allowed_inputs = list() //items that we can directly slot into the vending machine - - var/machine_id = "#" - - machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK - -/obj/machinery/vending/cultify() - new /obj/structure/cult/forge(loc) - ..() - -/obj/machinery/vending/New() - ..() - machine_id = "[name] #[multinum_display(num_vending_machines,4)]" - num_vending_machines++ - - overlays_vending[1] = "[icon_state]-panel" - - component_parts = newlist(\ - /obj/item/weapon/circuitboard/vendomat,\ - /obj/item/weapon/stock_parts/matter_bin,\ - /obj/item/weapon/stock_parts/manipulator,\ - /obj/item/weapon/stock_parts/scanning_module\ - ) - - RefreshParts() - - wires = new(src) - spawn(4) - src.slogan_list = text2list(src.product_slogans, ";") - - // So not all machines speak at the exact same time. - // The first time this machine says something will be at slogantime + this random value, - // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. - src.last_slogan = world.time + rand(0, slogan_delay) - - power_change() - - coinbox = new(src) - - if(ticker) - initialize() - - return - -/obj/machinery/vending/initialize() - ..() - product_records = new/list() - build_inventory(products) - build_inventory(contraband, 1) - build_inventory(premium, 0, 1) - -/obj/machinery/vending/RefreshParts() - var/manipcount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/manipulator)) manipcount += SP.rating - shoot_chance = manipcount * 3 - -/obj/machinery/vending/Destroy() - if(wires) - qdel(wires) - wires = null - - if(product_records.len&&cardboard) //Only spit out if we have slotted cardboard - var/obj/structure/vendomatpack/partial/newpack = new(src.loc) - newpack.stock = products - newpack.secretstock = contraband - newpack.preciousstock = premium - newpack.targetvendomat = src.type - newpack.product_records = product_records - newpack.hidden_records = hidden_records - newpack.coin_records = coin_records - - if(coinbox) - coinbox.forceMove(get_turf(src)) - ..() - -/obj/machinery/vending/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSMACHINE)) - return 1 - return ..() - -/obj/machinery/vending/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - - if(istype(O,/obj/structure/vendomatpack)) - var/obj/structure/vendomatpack/P = O - if(!anchored) - to_chat(user, "You need to anchor the vending machine before you can refill it.") - return - if(!pack) - to_chat(user, "You start filling the vending machine with the recharge pack's materials.") - var/user_loc = user.loc - var/pack_loc = P.loc - var/self_loc = src.loc - sleep(30) - if(!user || !P || !src) - return - if (user.loc == user_loc && P.loc == pack_loc && anchored && self_loc == src.loc && !(user.stat) && (!user.stunned && !user.weakened && !user.paralysis && !user.lying)) - var/obj/machinery/vending/newmachine = new P.targetvendomat(loc) - to_chat(user, "\icon[newmachine] You finish filling the vending machine, and use the stickers inside the pack to decorate the frame.") - playsound(newmachine, 'sound/machines/hiss.ogg', 50, 0, 0) - newmachine.pack = P.type - var/obj/item/emptyvendomatpack/emptypack = new /obj/item/emptyvendomatpack(P.loc) - emptypack.icon_state = P.icon_state - emptypack.overlays += image('icons/obj/vending_pack.dmi',"emptypack") - if(P.stock.len) - newmachine.products = P.stock - newmachine.contraband = P.secretstock - newmachine.premium = P.preciousstock - newmachine.product_records = P.product_records - newmachine.hidden_records = P.hidden_records - newmachine.coin_records = P.coin_records - qdel(P) - if(user.machine==src) - newmachine.attack_hand(user) - component_parts = 0 - qdel(coinbox) - qdel(src) - else - if(istype(P,pack)) - to_chat(user, "You start refilling the vending machine with the recharge pack's materials.") - var/user_loc = user.loc - var/pack_loc = P.loc - var/self_loc = src.loc - sleep(30) - if(!user || !P || !src) - return - if (user.loc == user_loc && P.loc == pack_loc && anchored && self_loc == src.loc && !(user.stat) && (!user.stunned && !user.weakened && !user.paralysis && !user.lying)) - to_chat(user, "\icon[src] You finish refilling the vending machine.") - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - for (var/datum/data/vending_product/D in product_records) - D.amount = D.original_amount - for (var/datum/data/vending_product/D in hidden_records) - D.amount = D.original_amount - var/obj/item/emptyvendomatpack/emptypack = new /obj/item/emptyvendomatpack(P.loc) - emptypack.icon_state = P.icon_state - emptypack.overlays += image('icons/obj/vending_pack.dmi',"emptypack") - qdel(P) - if(user.machine==src) - src.attack_hand(user) - else - to_chat(user, "This recharge pack isn't meant for this kind of vending machines.") - -/obj/machinery/vending/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if(prob(25)) - malfunction() - - -/obj/machinery/vending/blob_act() - if(prob(75)) - malfunction() - else - qdel(src) - -/obj/machinery/vending/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - return - switch(severity) - if(1.0) - malfunction() - if(2.0) - if(prob(50)) malfunction() - if(3.0) - if(prob(25)) malfunction() - -/obj/machinery/vending/proc/build_inventory(var/list/productlist,hidden=0,req_coin=0) - var/obj/item/temp - - for (var/typepath in productlist) - var/amount = productlist[typepath] - var/price = prices[typepath] - - if (isnull(amount)) - amount = 1 - - var/datum/data/vending_product/R = new() - R.product_path = typepath - R.amount = amount - R.original_amount = amount - R.price = price - R.display_color = pick("red", "blue", "green") - - if (hidden) - R.category=CAT_HIDDEN - hidden_records += R - else if (req_coin) - R.category=CAT_COIN - coin_records += R - else - R.category = CAT_NORMAL - product_records.Add(R) - - temp = new typepath(null) - - R.product_name = temp.name - R.subcategory = temp.vending_cat - -/obj/machinery/vending/proc/get_item_by_type(var/this_type) - var/list/datum_products = list() - datum_products |= hidden_records - datum_products |= coin_records - datum_products |= product_records - for(var/datum/data/vending_product/product in datum_products) - if(product.product_path == this_type) - return product - return null - -// to_chat(world, "Added: [R.product_name]] - [R.amount] - [R.product_path]") - -/obj/machinery/vending/emag(mob/user) - if(!emagged) - emagged = 1 - to_chat(user, "You short out the product lock on \the [src]") - return 1 - return -1 - -/obj/machinery/vending/proc/can_accept_voucher(var/obj/item/voucher/voucher, mob/user) - if(istype(voucher, /obj/item/voucher/free_item)) - var/obj/item/voucher/free_item/free_vouch = voucher - for(var/vend_item in free_vouch.freebies) - var/datum/data/vending_product/product = get_item_by_type(vend_item) - if(product && product.amount) - return 1 - return 0 - -//this should ideally be called last as a parent method, since it can delete the voucher -/obj/machinery/vending/proc/voucher_act(var/obj/item/voucher/voucher, mob/user) - if(istype(voucher, /obj/item/voucher/free_item)) - var/obj/item/voucher/free_item/free_vouch = voucher - for(var/i = 1; i <= free_vouch.vend_amount; i++) - if(!free_vouch.freebies || !free_vouch.freebies.len) - break - var/to_vend = pick(free_vouch.freebies) - if(free_vouch.single_items) - free_vouch.freebies.Remove(to_vend) - var/datum/data/vending_product/product = get_item_by_type(to_vend) - if(product && product.amount) - src.vend(product, user, by_voucher = 1) - - if(voucher.shred_on_use) - qdel(voucher) - else - if(!vouchers) - vouchers = list() - vouchers.Add(voucher) - if(coinbox) - voucher.forceMove(coinbox) - return 1 - -/obj/machinery/vending/attackby(obj/item/W, mob/user) - if(stat & (BROKEN)) - if(istype(W, /obj/item/stack/sheet/glass/rglass)) - var/obj/item/stack/sheet/glass/rglass/G = W - to_chat(user, "You replace the broken glass.") - G.use(1) - stat &= ~BROKEN - src.health = 100 - src.update_vicon() - getFromPool(/obj/item/weapon/shard, loc) - else - to_chat(user, "[src] is broken! Fix it first.") - return - . = ..() - if(.) - return . - if(!cardboard && istype(W, /obj/item/stack/sheet/cardboard)) - var/obj/item/stack/sheet/cardboard/C = W - if(C.amount>=4) - C.use(4) - to_chat(user, "You slot some cardboard into the machine into [src].") - cardboard = 1 - src.updateUsrDialog() - if(istype(W, /obj/item/device/multitool)||istype(W, /obj/item/weapon/wirecutters)) - if(panel_open) - attack_hand(user) - return - else if(premium.len > 0 && is_type_in_list(W, list(/obj/item/weapon/coin/, /obj/item/weapon/reagent_containers/food/snacks/chococoin))) - if (isnull(coin)) - if(user.drop_item(W, src)) - coin = W - to_chat(user, "You insert a coin into [src].") - src.updateUsrDialog() - else - to_chat(user, "There's already a coin in [src].") - return - else if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/customizable/candy/coin)) - to_chat(user, "That coin is smudgy and oddly soft, you don't think that would work.") - return - else if(istype(W, /obj/item/voucher)) - if(can_accept_voucher(W, user)) - if(user.drop_item(W, src)) - to_chat(user, "You insert [W] into [src].") - return voucher_act(W, user) - src.updateUsrDialog() - else - to_chat(user, "\The [src] refuses to take [W].") - return 1 - else if(istype(W, /obj/item/weapon/storage/bag)) - var/obj/item/weapon/storage/bag/bag = W - var/objects_loaded = 0 - for(var/obj/G in bag.contents) - if(is_type_in_list(G, allowed_inputs)) - bag.remove_from_storage(G,src) - add_item(G) - objects_loaded++ - if(objects_loaded) - user.visible_message("[user] loads \the [src] with \the [bag].", \ - "You load \the [src] with \the [bag].") - if(bag.contents.len > 0) - to_chat(user, "Some items are refused.") - src.updateUsrDialog() - else - if(is_type_in_list(W, allowed_inputs)) - if(user.drop_item(W, src)) - add_item(W) - src.updateUsrDialog() - /*else if(istype(W, /obj/item/weapon/card) && currently_vending) - //attempt to connect to a new db, and if that doesn't work then fail - if(!linked_db) - reconnect_database() - if(linked_db) - if(linked_account) - var/obj/item/weapon/card/I = W - scan_card(I) - else - to_chat(usr, "\icon[src]Unable to connect to linked account.") - else - to_chat(usr, "\icon[src]Unable to connect to accounts database.")*/ - -//H.wear_id - -/obj/machinery/vending/scan_card(var/obj/item/weapon/card/I) - if(!currently_vending) return - if (istype(I, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/C = I - visible_message("[usr] swipes a card through [src].") - if(linked_account) - //we start by checking the ID card's virtual wallet - var/datum/money_account/D = C.virtual_wallet - var/using_account = "Virtual Wallet" - - //if there isn't one for some reason we create it, that should never happen but oh well. - if(!D) - C.update_virtual_wallet() - D = C.virtual_wallet - - var/transaction_amount = currently_vending.price - - //if there isn't enough money in the virtual wallet, then we check the bank account connected to the ID - if(D.money < transaction_amount) - D = linked_db.attempt_account_access(C.associated_account_number, 0, 2, 0) - using_account = "Bank Account" - if(!D) //first we check if there IS a bank account in the first place - to_chat(usr, "\icon[src]You don't have that much money on your virtual wallet!") - to_chat(usr, "\icon[src]Unable to access your bank account.") - return 0 - else if(D.security_level > 0) //next we check if the security is low enough to pay directly from it - to_chat(usr, "\icon[src]You don't have that much money on your virtual wallet!") - to_chat(usr, "\icon[src]Lower your bank account's security settings if you wish to pay directly from it.") - return 0 - else if(D.money < transaction_amount)//and lastly we check if there's enough money on it, duh - to_chat(usr, "\icon[src]You don't have that much money on your bank account!") - return 0 - - //transfer the money - D.money -= transaction_amount - linked_account.money += transaction_amount - - to_chat(usr, "\icon[src]Remaining balance ([using_account]): [D.money]$") - - //create an entry on the buy's account's transaction log - var/datum/transaction/T = new() - T.target_name = "[linked_account.owner_name] (via [src.name])" - T.purpose = "Purchase of [currently_vending.product_name]" - T.amount = "-[transaction_amount]" - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - D.transaction_log.Add(T) - - //and another entry on the vending machine's vendor account's transaction log - T = new() - T.target_name = D.owner_name - T.purpose = "Purchase of [currently_vending.product_name]" - T.amount = "[transaction_amount]" - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - linked_account.transaction_log.Add(T) - - // Vend the item - src.vend(src.currently_vending, usr) - currently_vending = null - else - to_chat(usr, "\icon[src]EFTPOS is not connected to an account.") - -/obj/machinery/vending/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/machinery/vending/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/vending/proc/GetProductLine(var/datum/data/vending_product/P) - var/dat = {"[P.product_name]: - [P.amount] "} - if(P.price) - dat += " ($[P.price])" - if (P.amount > 0) - var/idx=GetProductIndex(P) - dat += " (Vend)" - else - dat += " SOLD OUT" - dat += "
                      " - - return dat - -/obj/machinery/vending/proc/GetProductIndex(var/datum/data/vending_product/P) - var/list/plist - switch(P.category) - if(CAT_NORMAL) - plist=product_records - if(CAT_HIDDEN) - plist=hidden_records - if(CAT_COIN) - plist=coin_records - else - warning("UNKNOWN CATEGORY [P.category] IN TYPE [P.product_path] INSIDE [type]!") - return plist.Find(P) - -/obj/machinery/vending/proc/GetProductByID(var/pid, var/category) - switch(category) - if(CAT_NORMAL) - return product_records[pid] - if(CAT_HIDDEN) - return hidden_records[pid] - if(CAT_COIN) - return coin_records[pid] - else - warning("UNKNOWN PRODUCT: PID: [pid], CAT: [category] INSIDE [type]!") - return null - -/obj/machinery/vending/proc/TurnOff(var/ticks) //Turn off for a while. 10 ticks = 1 second - if(stat & (BROKEN|NOPOWER)) - return - - stat |= NOPOWER - src.update_vicon() - src.visible_message("[src] goes off!") - - spawn(ticks) - - if(stat & (NOPOWER)) //Make another check just in case something goes weird - stat &= ~NOPOWER - src.update_vicon() - -/obj/machinery/vending/proc/update_vicon() - if(stat & (BROKEN)) - src.icon_state = "[initial(icon_state)]-broken" - return - else if (stat & (NOPOWER)) - src.icon_state = "[initial(icon_state)]-off" - else - src.icon_state = "[initial(icon_state)]" - -/obj/machinery/vending/attack_hand(mob/living/user as mob) - if(user.a_intent == "hurt" && istype(user, /mob/living/carbon/)) //Will make another update later. Hulks will insta-break - user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it - src.shake(1, 3) //1 means x movement, 3 means intensity - src.health -= 4 - if (!Adjacent(user) && (M_TK in usr.mutations)) - to_chat(user, "You slam the [src] with your mind.") - src.visible_message("[src] dents slightly as if struck.") - else - user.visible_message( "[user] kicks the [src].", "You kick the [src].") - if(prob(70)) - user.apply_damage(rand(2,4), BRUTE, "r_leg") - - if(src.health <= 0) - stat |= BROKEN - src.update_vicon() - return - if(prob(2)) //Jackpot! - malfunction() - if(prob(2)) - src.TurnOff(600) //A whole minute - /*if(prob(1)) - to_chat(usr, "You fall down and break your leg!") - user.emote("scream",,, 1) - shake_camera(user, 2, 1)*/ - return - - if(stat & (BROKEN|NOPOWER)) - return - - if(seconds_electrified > 0) - if(shock(user, 100)) - return - else if (seconds_electrified) - seconds_electrified = 0 - - user.set_machine(src) - - var/vendorname = (src.name) //import the machine's name - - var/vertical = 400 - - if(src.currently_vending) - var/dat = "
                      [vendorname]


                      " //display the name, and added a horizontal rule - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\vending.dm:260: dat += "You have selected [currently_vending.product_name].
                      Please ensure your ID is in your ID holder or hand.

                      " - dat += {"You have selected [currently_vending.product_name].
                      Please ensure your ID is in your ID holder or hand.

                      - Pay | - Cancel"} - // END AUTOFIX - user << browse(dat, "window=vending") - onclose(user, "") - return - - var/dat = "
                      [vendorname]


                      " //display the name, and added a horizontal rule - 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)

                      " - - if (src.product_records.len == 0) - dat += "No products loaded!" - else - var/list/display_records = src.product_records.Copy() - - if(src.extended_inventory) - display_records += src.hidden_records - if(src.coin) - display_records += src.coin_records - - if(display_records.len > 12) - vertical = min(400 + (16 * (display_records.len - 12)),840) - - categories["default"] = list() - var/list/category_names = list() - for (var/datum/data/vending_product/R in product_records) - if(R.subcategory) - if(!(R.subcategory in category_names)) - category_names += R.subcategory - categories[R.subcategory] = list() - categories[R.subcategory] += R - else - categories["default"] += R - - for (var/datum/data/vending_product/R in categories["default"]) - dat += GetProductLine(R) - dat += "
                      " - - for(var/cat_name in category_names) - dat += {"  [cat_name]:
                      "} - for (var/datum/data/vending_product/R in categories[cat_name]) - dat += GetProductLine(R) - dat += "
                      " - - if(src.extended_inventory) - dat += {"  contraband:
                      "} - for (var/datum/data/vending_product/R in hidden_records) - dat += GetProductLine(R) - dat += "
                      " - - if(src.coin) - dat += {"  premium:
                      "} - for (var/datum/data/vending_product/R in coin_records) - dat += GetProductLine(R) - dat += "
                      " - - dat += "
                      " - - if(panel_open) - dat += wires() - - if(product_slogans != "") - dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle" - - user << browse(dat, "window=vending;size=400x[vertical]") - onclose(user, "vending") - return - -// returns the wire panel text -/obj/machinery/vending/proc/wires() - return wires.GetInteractWindow() - -/obj/machinery/vending/Topic(href, href_list) - if(..()) - usr << browse(null, "window=vending") - return 1 - - //testing("..(): [href]") - - var/free_vend = 0 - if(istype(usr,/mob/living/silicon)) - var/can_vend = 1 - if (href_list["vend"] && src.vend_ready && !currently_vending) - var/idx=text2num(href_list["vend"]) - var/cat=text2num(href_list["cat"]) - var/datum/data/vending_product/R = GetProductByID(idx,cat) - if(R.price) - can_vend = 0//all borgs can buy free items from vending machines - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = usr - if((R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ) || isMoMMI(R)) - can_vend = 1//only service borgs and MoMMI can buy costly items - if(!can_vend) - to_chat(usr, "The vending machine refuses to interface with you, as you are not in its target demographic!") - return - else - free_vend = 1//so that don't have to swipe their non-existant IDs - - if(href_list["remove_coin"]) - if(!coin) - to_chat(usr, "There is no coin in this machine.") - return - - coin.forceMove(get_turf(src)) - if(!usr.get_active_hand()) - usr.put_in_hands(coin) - to_chat(usr, "You remove the [coin] from the [src]") - coin = null - usr.set_machine(src) - - - if (href_list["vend"] && src.vend_ready && !currently_vending) - //testing("vend: [href]") - - if (!allowed(usr) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - to_chat(usr, "Access denied.")//Unless emagged of course - - flick(src.icon_deny,src) - return - - var/idx=text2num(href_list["vend"]) - var/cat=text2num(href_list["cat"]) - - var/datum/data/vending_product/R = GetProductByID(idx,cat) - if (!R || !istype(R) || !R.product_path || R.amount <= 0) - message_admins("Invalid vend request by [formatJumpTo(src.loc)]: [href]") - return - - if(R.price == null || !R.price) - src.vend(R, usr) - else if(free_vend)//for MoMMI and Service Borgs - src.vend(R, usr) - else - src.currently_vending = R - src.updateUsrDialog() - - return - - else if (href_list["cancel_buying"]) - src.currently_vending = null - src.updateUsrDialog() - return - - else if (href_list["buy"]) - var/obj/item/weapon/card/card = usr.get_id_card() - if(card) - connect_account(usr, card) - src.updateUsrDialog() - return - - else if ((href_list["togglevoice"]) && (src.panel_open)) - src.shut_up = !src.shut_up - - src.add_fingerprint(usr) - src.updateUsrDialog() - - return - -/obj/machinery/vending/proc/add_item(var/obj/item/I) - var/found = FALSE - - for (var/datum/data/vending_product/D in product_records) - if (D.product_path == I.type) - D.amount++ - found = TRUE - break - - if (!found) - var/datum/data/vending_product/R = new() - R.product_path = I.type - R.amount = 1 - R.original_amount = 0 - R.price = 0 - R.display_color = pick("red", "blue", "green") - R.product_name = I.name - R.category = CAT_NORMAL - R.subcategory = I.vending_cat - - product_records.Add(R) - - qdel(I) - -/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user, by_voucher = 0) - if (!allowed(user) && !emagged && wires.IsIndexCut(VENDING_WIRE_IDSCAN)) //For SECURE VENDING MACHINES YEAH - to_chat(user, "Access denied.")//Unless emagged of course - - flick(src.icon_deny,src) - return - src.vend_ready = 0 //One thing at a time!! - - if (!by_voucher && (R in coin_records)) - if (isnull(coin)) - to_chat(user, "You need to insert a coin to get this item.") - return - - var/return_coin = 0 - if(istype(coin, /obj/item/weapon/coin/)) - var/obj/item/weapon/coin/real_coin = coin - if(real_coin.string_attached) - if(prob(50)) - to_chat(user, "You successfully pulled the coin out before the [src] could swallow it.") - return_coin = 1 - else - to_chat(user, "You weren't able to pull the coin out fast enough, the machine ate it, string and all.") - - if(return_coin) - user.put_in_hands(coin) - else - if (!isnull(coinbox)) - if (coinbox.can_be_inserted(coin, TRUE)) - coinbox.handle_item_insertion(coin, TRUE) - - coin = null - - R.amount-- - - if(((src.last_reply + (src.vend_delay + 200)) <= world.time) && src.vend_reply) - spawn(0) - src.speak(src.vend_reply) - src.last_reply = world.time - - use_power(5) - if (src.icon_vend) //Show the vending animation if needed - flick(src.icon_vend,src) - spawn(src.vend_delay) - new R.product_path(get_turf(src)) - src.vend_ready = 1 - return - - src.updateUsrDialog() - -/obj/machinery/vending/process() - if(stat & (BROKEN|NOPOWER)) - return - - if(!src.active) - return - - if(src.seconds_electrified > 0) - src.seconds_electrified-- - - //Pitch to the people! Really sell it! - if(((src.last_slogan + src.slogan_delay) <= world.time) && (src.slogan_list.len > 0) && (!src.shut_up) && prob(5)) - var/slogan = pick(src.slogan_list) - src.speak(slogan) - src.last_slogan = world.time - - if(src.shoot_inventory && prob(shoot_chance)) - src.throw_item() - - return - -/obj/machinery/vending/proc/speak(var/message) - if(stat & NOPOWER) - return - - if (!message) - return - say(message) - -/obj/machinery/vending/say_quote(text) - return "beeps, [text]" - -/obj/machinery/vending/power_change() - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - else - if( powered() ) - icon_state = initial(icon_state) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - src.icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER - -//Oh no we're malfunctioning! Dump out some product and break. -/obj/machinery/vending/proc/malfunction() - var/lost_inventory = rand(1,12) - while(lost_inventory>0) - throw_item() - lost_inventory-- - stat |= BROKEN - src.icon_state = "[initial(icon_state)]-broken" - return - -//Somebody cut an important wire and now we're following a new definition of "pitch." -/obj/machinery/vending/proc/throw_item() - - var/mob/living/target = locate() in view(7, src) - - if (!target) - return 0 - - var/obj/throw_item - var/list/throwable = product_records.Copy() - var/tries = 10 //Give up eventually - var/datum/data/vending_product/R - var/dump_path - - if (extended_inventory) - throwable += hidden_records - - while (tries) - R = pick(throwable) - dump_path = R.product_path - - if (R.amount <= 0 || !dump_path) - tries-- - continue - - R.amount-- - throw_item = new dump_path(src.loc) - - if (!throw_item) - return 0 - - spawn(0) - throw_item.throw_at(target, 16, 3) - - src.visible_message("[src] launches [throw_item.name] at [target.name]!") - return 1 - - return 0 - -/obj/machinery/vending/update_icon() - if(panel_open) - overlays += overlays_vending[1] - else - overlays -= overlays_vending[1] - - overlays -= overlays_vending[2] - if(emagged) - overlays += overlays_vending[2] - -/obj/machinery/vending/wirejack(var/mob/living/silicon/pai/P) - if(..()) - extended_inventory = !extended_inventory - scan_id = !scan_id - return 1 - return 0 - - -/* - * Vending machine types - */ - -/* - -/obj/machinery/vending/[vendors name here] // --vending machine template :) - name = "" - desc = "" - icon = '' - icon_state = "" - vend_delay = 15 - products = list() - contraband = list() - premium = list() - -*/ - -/* -/obj/machinery/vending/atmospherics //Commenting this out until someone ponies up some actual working, broken, and unpowered sprites - Quarxink - name = "Tank Vendor" - desc = "A vendor with a wide variety of masks and gas tanks." - icon = 'icons/obj/objects.dmi' - icon_state = "dispenser" - product_paths = "/obj/item/weapon/tank/oxygen;/obj/item/weapon/tank/plasma;/obj/item/weapon/tank/emergency_oxygen;/obj/item/weapon/tank/emergency_oxygen/engi;/obj/item/clothing/mask/breath" - product_amounts = "10;10;10;5;25" - vend_delay = 0 -*/ - -/obj/machinery/vending/boozeomat - name = "Booze-O-Mat" - desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one." - icon_state = "boozeomat" //////////////18 drink entities below, plus the glasses, in case someone wants to edit the number of bottles - icon_deny = "boozeomat-deny" - products = list( - /obj/item/weapon/reagent_containers/food/drinks/bottle/gin = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/tequila = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/rum = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/wine = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/cognac = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua = 5, - /obj/item/weapon/reagent_containers/food/drinks/beer = 6, - /obj/item/weapon/reagent_containers/food/drinks/ale = 6, - /obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice = 4, - /obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice = 4, - /obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice = 4, - /obj/item/weapon/reagent_containers/food/drinks/bottle/cream = 4, - /obj/item/weapon/reagent_containers/food/drinks/milk = 4, - /obj/item/weapon/reagent_containers/food/drinks/soymilk = 4, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic = 8, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 8, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater = 15, - /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30, - /obj/item/weapon/reagent_containers/food/drinks/ice = 9, - ) - contraband = list( - /obj/item/weapon/reagent_containers/food/drinks/tea = 10, - /obj/item/weapon/reagent_containers/food/drinks/coffee = 10, - /obj/item/weapon/reagent_containers/food/drinks/mug = 10 - ) - product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?" - product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!" - req_access_txt = "25" - pack = /obj/structure/vendomatpack/boozeomat - -/obj/machinery/vending/assist - name = "Vendomat" - desc = "A generic vending machine." - icon_state = "generic" - products = list( - /obj/item/device/assembly/prox_sensor = 5, - /obj/item/device/assembly/igniter = 3, - /obj/item/device/assembly/signaler = 4, - /obj/item/weapon/wirecutters = 1, - /obj/item/weapon/cartridge/signal = 4, - ) - contraband = list( - /obj/item/device/flashlight = 5, - /obj/item/device/assembly/timer = 2, - ) - premium = list( - /obj/item/device/assembly_frame = 1, - ) - product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" - pack = /obj/structure/vendomatpack/assist - -/obj/machinery/vending/coffee - name = "Hot Drinks machine" - desc = "A vending machine which dispenses hot drinks." - product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies" - icon_state = "coffee" - icon_vend = "coffee-vend" - vend_delay = 34 - products = list( - /obj/item/weapon/reagent_containers/food/drinks/coffee = 25, - /obj/item/weapon/reagent_containers/food/drinks/tea = 25, - /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25, - ) - contraband = list( - /obj/item/weapon/reagent_containers/food/drinks/ice = 10, - ) - prices = list( - /obj/item/weapon/reagent_containers/food/drinks/coffee = 25, - /obj/item/weapon/reagent_containers/food/drinks/tea = 25, - /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25, - ) - - pack = /obj/structure/vendomatpack/coffee - - - -/obj/machinery/vending/snack - name = "Getmore Chocolate Corp" - desc = "A snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars" - product_slogans = "Try our new nougat bar!;Half the calories for double the price!;It's better then Dan's!" - product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!" - icon_state = "snack" - products = list( - /obj/item/weapon/reagent_containers/food/snacks/candy = 6, - /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 6, - /obj/item/weapon/reagent_containers/food/snacks/chips =6, - /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6, - /obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6, - /obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 6, - /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, - /obj/item/weapon/reagent_containers/food/snacks/chococoin/wrapped = 2, - /obj/item/weapon/reagent_containers/food/snacks/bustanuts = 10, - ) - contraband = list( - /obj/item/weapon/reagent_containers/food/snacks/syndicake = 6, - ) - prices = list( - /obj/item/weapon/reagent_containers/food/snacks/candy = 13, - /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 15, - /obj/item/weapon/reagent_containers/food/snacks/chips = 30, - /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 40, - /obj/item/weapon/reagent_containers/food/snacks/no_raisin = 60, - /obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 12, - /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 40, - /obj/item/weapon/reagent_containers/food/snacks/chococoin/wrapped = 75, - /obj/item/weapon/reagent_containers/food/snacks/bustanuts = 0, - ) - - pack = /obj/structure/vendomatpack/snack - - -/obj/machinery/vending/cola - name = "Robust Softdrinks" - desc = "A softdrink vendor provided by Robust Industries, LLC." - icon_state = "Cola_Machine" - product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!;At least we aren't Dan!" - product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space." - products = list( - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 10, - ) - contraband = list( - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko = 5, - ) - prices = list( - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 20, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 20, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 20, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 20, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 20, - ) - - pack = /obj/structure/vendomatpack/cola - -//This one's from bay12 -/obj/machinery/vending/cart - name = "PTech" - desc = "Cartridges for PDAs" - product_slogans = "Carts to go!" - 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/captain = 3, - /obj/item/weapon/cartridge/quartermaster = 10, - ) - - pack = /obj/structure/vendomatpack/undefined - -/obj/machinery/vending/cigarette - name = "Cigarette machine" //OCD had to be uppercase to look nice with the new formating - desc = "If you want to get cancer, might as well do it in style" - product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!" - product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs." - icon_state = "cigs" - products = list( - /obj/item/weapon/storage/fancy/cigarettes = 10, - /obj/item/weapon/storage/fancy/matchbox = 10, - /obj/item/weapon/lighter/random = 4, - ) - contraband = list( - /obj/item/weapon/lighter/zippo = 4, - ) - premium = list( - /obj/item/weapon/storage/fancy/matchbox/strike_anywhere = 10, - /obj/item/clothing/mask/cigarette/cigar/havana = 2, - ) - prices = list( - /obj/item/weapon/storage/fancy/cigarettes = 20, - /obj/item/weapon/storage/fancy/matchbox = 25, - /obj/item/weapon/lighter/random = 25, - ) - - pack = /obj/structure/vendomatpack/cigarette - -/obj/machinery/vending/medical - name = "NanoMed Plus" - desc = "Medical drug dispenser." - icon_state = "med" - icon_deny = "med-deny" - product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!" - req_access_txt = "5" - products = list( - /obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4, - /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4, - /obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4, - /obj/item/weapon/reagent_containers/glass/bottle/toxin = 4, - /obj/item/weapon/reagent_containers/glass/bottle/charcoal = 4, - /obj/item/weapon/reagent_containers/syringe/antiviral = 4, - /obj/item/weapon/reagent_containers/syringe = 12, - /obj/item/device/healthanalyzer = 5, - /obj/item/weapon/reagent_containers/glass/beaker = 4, - /obj/item/weapon/reagent_containers/dropper = 2, - ) - contraband = list( - /obj/item/weapon/reagent_containers/pill/tox = 3, - /obj/item/weapon/reagent_containers/pill/stox = 4, - /obj/item/weapon/reagent_containers/pill/antitox = 6, - /obj/item/weapon/reagent_containers/blood/OMinus = 1, - /obj/item/weapon/storage/pill_bottle/random = 2, - ) - premium = list( - /obj/item/weapon/storage/pill_bottle/time_release = 2, - ) - - pack = /obj/structure/vendomatpack/medical - -//This one's from bay12 -/obj/machinery/vending/plasmaresearch - name = "Toximate 3000" - desc = "All the fine parts you need in one vending machine!" - products = list( - /obj/item/clothing/under/rank/scientist = 6, - /obj/item/clothing/suit/bio_suit = 6, - /obj/item/clothing/head/bio_hood = 6, - /obj/item/device/transfer_valve = 6, - /obj/item/device/assembly/timer = 6, - /obj/item/device/assembly/signaler = 6, - /obj/item/device/assembly/prox_sensor = 6, - /obj/item/device/assembly/igniter = 6, - ) - - pack = /obj/structure/vendomatpack/undefined - -/obj/machinery/vending/wallmed1 - name = "NanoMed" - desc = "Wall-mounted Medical Equipment dispenser." - product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?" - icon_state = "wallmed" - icon_deny = "wallmed-deny" - //req_access_txt = "5" - density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude - products = list( - /obj/item/stack/medical/bruise_pack = 2, - /obj/item/stack/medical/ointment = 2, - /obj/item/weapon/reagent_containers/syringe/inaprovaline = 4, - /obj/item/device/healthanalyzer = 1, - ) - contraband = list( - /obj/item/weapon/reagent_containers/syringe/antitoxin = 4, - /obj/item/weapon/reagent_containers/syringe/antiviral = 4, - /obj/item/weapon/reagent_containers/pill/tox = 1, - ) - - pack = /obj/structure/vendomatpack/medical//can be reloaded with NanoMed Plus packs - component_parts = 0 - -/obj/machinery/vending/wallmed2 - name = "NanoMed" - desc = "Wall-mounted Medical Equipment dispenser." - icon_state = "wallmed" - icon_deny = "wallmed-deny" - //req_access_txt = "5" - density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude - products = list( - /obj/item/weapon/reagent_containers/syringe/inaprovaline = 5, - /obj/item/weapon/reagent_containers/syringe/antitoxin = 3, - /obj/item/stack/medical/bruise_pack = 3, - /obj/item/stack/medical/ointment =3, - /obj/item/device/healthanalyzer = 3, - ) - contraband = list( - /obj/item/weapon/reagent_containers/pill/tox = 3, - ) - component_parts = 0 - - pack = /obj/structure/vendomatpack/medical//can be reloaded with NanoMed Plus packs - -////////WALL-MOUNTED NANOMED FRAME////// -/obj/machinery/vending/wallmed1/New(turf/loc) - ..() - component_parts = 0 - -/obj/machinery/vending/wallmed2/New(turf/loc) - ..() - component_parts = 0 - -/obj/machinery/vending/wallmed1/crowbarDestroy(mob/user) - user.visible_message( "[user] begins to pry out the NanoMed from the wall.", - "You begin to pry out the NanoMed from the wall...") - if(do_after(user, src, 40)) - user.visible_message( "[user] detaches the NanoMed from the wall.", - "You detach the NanoMed from the wall.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - new /obj/item/mounted/frame/wallmed(src.loc) - - for(var/obj/I in src) - qdel(I) - - new /obj/item/weapon/circuitboard/vendomat(src.loc) - new /obj/item/stack/cable_coil(loc,5) - - return 1 - return -1 - -/obj/machinery/vending/wallmed2/crowbarDestroy(mob/user) - user.visible_message( "[user] begins to pry out the NanoMed from the wall.", - "You begin to pry out the NanoMed from the wall...") - if(do_after(user, src, 40)) - user.visible_message( "[user] detaches the NanoMed from the wall.", - "You detach the NanoMed from the wall.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - new /obj/item/mounted/frame/wallmed(src.loc) - - for(var/obj/I in src) - qdel(I) - - new /obj/item/weapon/circuitboard/vendomat(src.loc) - new /obj/item/stack/cable_coil(loc,5) - - return 1 - return -1 - -/obj/machinery/wallmed_frame - name = "NanoMed frame" - desc = "Wall-mounted Medical Equipment dispenser." - icon = 'icons/obj/vending.dmi' - icon_state = "wallmed_frame0" - anchored = 1 - - var/on = 1 - - var/build = 0 // Build state - var/boardtype=/obj/item/weapon/circuitboard/vendomat - var/obj/item/weapon/circuitboard/_circuitboard - -/obj/machinery/wallmed_frame/New(turf/loc, var/ndir) - ..() - // offset 32 pixels in direction of dir - // this allows the NanoMed to be embedded in a wall, yet still inside an area - dir = ndir - pixel_x = (dir & 3)? 0 : (dir == 4 ? 30 : -30) - pixel_y = (dir & 3)? (dir ==1 ? 30 : -30) : 0 - -/obj/machinery/wallmed_frame/update_icon() - icon_state = "wallmed_frame[build]" - -/obj/machinery/wallmed_frame/attackby(var/obj/item/W as obj, var/mob/user as mob) - switch(build) - if(0) // Empty hull - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(usr, "You begin removing screws from \the [src] backplate...") - if(do_after(user, src, 50)) - to_chat(usr, "You unscrew \the [src] from the wall.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - new /obj/item/mounted/frame/wallmed(get_turf(src)) - qdel(src) - return 1 - if(istype(W, /obj/item/weapon/circuitboard)) - var/obj/item/weapon/circuitboard/C=W - if(!(istype(C,/obj/item/weapon/circuitboard/vendomat))) - to_chat(user, "You cannot install this type of board into a NanoMed frame.") - return - to_chat(usr, "You begin to insert \the [C] into \the [src].") - if(do_after(user, src, 10)) - if(user.drop_item(C, src)) - to_chat(usr, "You secure \the [C]!") - _circuitboard=C - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) - build++ - update_icon() - return 1 - if(1) // Circuitboard installed - if(istype(W, /obj/item/weapon/crowbar)) - to_chat(usr, "You begin to pry out \the [W] into \the [src].") - if(do_after(user, src, 10)) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) - build-- - update_icon() - var/obj/item/weapon/circuitboard/C - if(_circuitboard) - _circuitboard.loc=get_turf(src) - C=_circuitboard - _circuitboard=null - else - C=new boardtype(get_turf(src)) - user.visible_message(\ - "[user.name] has removed \the [C]!",\ - "You remove \the [C].") - return 1 - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C=W - to_chat(user, "You start adding cables to \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20) && C.amount >= 5) - C.use(5) - build++ - update_icon() - user.visible_message(\ - "[user.name] has added cables to \the [src]!",\ - "You add cables to \the [src].") - if(2) // Circuitboard installed, wired. - if(istype(W, /obj/item/weapon/wirecutters)) - to_chat(usr, "You begin to remove the wiring from \the [src].") - if(do_after(user, src, 50)) - new /obj/item/stack/cable_coil(loc,5) - user.visible_message(\ - "[user.name] cut the cables.",\ - "You cut the cables.") - build-- - update_icon() - return 1 - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(user, "You begin to complete \the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 20)) - if(!_circuitboard) - _circuitboard=new boardtype(src) - build++ - update_icon() - user.visible_message(\ - "[user.name] has finished \the [src]!",\ - "You finish \the [src].") - return 1 - if(3) // Waiting for a recharge pack - if(istype(W, /obj/item/weapon/screwdriver)) - to_chat(user, "You begin to unscrew \the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 30)) - build-- - update_icon() - return 1 - ..() - -/obj/machinery/wallmed_frame/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if(build==3) - if(istype(O,/obj/structure/vendomatpack)) - if(istype(O,/obj/structure/vendomatpack/medical)) - to_chat(user, "You start refilling the vending machine with the recharge pack's materials.") - var/user_loc = user.loc - var/pack_loc = O.loc - var/self_loc = src.loc - sleep(30) - if(!user || !O || !src) - return - if (user.loc == user_loc && O.loc == pack_loc && anchored && self_loc == src.loc && !(user.stat) && (!user.stunned && !user.weakened && !user.paralysis && !user.lying)) - to_chat(user, "\icon[src] You finish refilling the vending machine.") - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - var/obj/machinery/vending/wallmed1/newnanomed = new /obj/machinery/vending/wallmed1(src.loc) - newnanomed.name = "Emergency NanoMed" - newnanomed.pixel_x = pixel_x - newnanomed.pixel_y = pixel_y - var/obj/item/emptyvendomatpack/emptypack = new /obj/item/emptyvendomatpack(O.loc) - emptypack.icon_state = O.icon_state - emptypack.overlays += image('icons/obj/vending_pack.dmi',"emptypack") - qdel(O) - contents = 0 - qdel(src) - else - to_chat(user, "This recharge pack isn't meant for this kind of vending machines.") - -//////////////////////////////////////// - - -/obj/machinery/vending/security - name = "SecTech" - desc = "A security equipment vendor" - product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?" - icon_state = "sec" - icon_deny = "sec-deny" - req_access_txt = "1" - products = list( - /obj/item/weapon/handcuffs = 8, - /obj/item/weapon/grenade/flashbang = 4, - /obj/item/device/flash = 5, - /obj/item/weapon/reagent_containers/food/snacks/donut/normal = 12, - /obj/item/weapon/storage/box/evidence = 6, - /obj/item/weapon/legcuffs/bolas = 2, - ) - contraband = list( - /obj/item/clothing/glasses/sunglasses = 2, - /obj/item/weapon/storage/fancy/donut_box = 2, - ) - - pack = /obj/structure/vendomatpack/security - -/obj/machinery/vending/hydronutrients - name = "NutriMax" - desc = "A plant nutrients vendor" - product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!" - 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/weapon/reagent_containers/glass/fertilizer/ez = 35, - /obj/item/weapon/reagent_containers/glass/fertilizer/l4z = 25, - /obj/item/weapon/reagent_containers/glass/fertilizer/rh = 15, - /obj/item/weapon/plantspray/pests = 20, - /obj/item/weapon/reagent_containers/syringe = 5, - /obj/item/weapon/reagent_containers/dropper = 2, - /obj/item/weapon/storage/bag/plants = 5, - ) - contraband = list( - /obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10, - /obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5, - ) - - pack = /obj/structure/vendomatpack/hydronutrients - -/obj/machinery/vending/hydroseeds - name = "MegaSeed Servitor" - desc = "When you need seeds fast!" - product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!" - product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!" - icon_state = "seeds" - 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/dionanode = 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/sugarcaneseed = 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/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, - /obj/item/seeds/cinnamomum = 3, - )//,/obj/item/seeds/synthmeatseed = 3) - contraband = list( - /obj/item/seeds/amanitamycelium = 2, - /obj/item/seeds/glowshroom = 2, - /obj/item/seeds/libertymycelium = 2, - /obj/item/seeds/nettleseed = 2, - /obj/item/seeds/plumpmycelium = 2, - /obj/item/seeds/reishimycelium = 2, - /obj/item/seeds/harebell = 3, - )//,/obj/item/seeds/synthbuttseed = 3) - premium = list( - /obj/item/toy/waterflower = 1, - ) - - allowed_inputs = list( - /obj/item/seeds, - ) - pack = /obj/structure/vendomatpack/hydroseeds - -/obj/machinery/vending/magivend - name = "MagiVend" - desc = "A magic vending machine." - icon_state = "MagiVend" - product_slogans = "Sling spells the proper way with MagiVend!;Be your own Houdini! Use MagiVend!" - vend_delay = 15 - vend_reply = "Have an enchanted evening!" - product_ads = "FJKLFJSD;AJKFLBJAKL;1234 LOONIES LOL!;>MFW;Kill them fuckers!;GET DAT FUKKEN DISK;HONK!;EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!" - products = list( - /obj/item/clothing/head/wizard = 1, - /obj/item/clothing/suit/wizrobe = 1, - /obj/item/clothing/head/wizard/red = 1, - /obj/item/clothing/suit/wizrobe/red = 1, - /obj/item/clothing/head/wizard/clown = 1, - /obj/item/clothing/suit/wizrobe/clown = 1, - /obj/item/clothing/mask/gas/clown_hat/wiz = 1, - /obj/item/clothing/suit/wizrobe/magician = 1, - /obj/item/clothing/head/wizard/magician = 1, - /obj/item/clothing/shoes/sandal/marisa/leather = 1, - /obj/item/clothing/shoes/sandal = 1, - /obj/item/weapon/staff = 2, - /obj/item/weapon/storage/bag/wiz_cards/full = 1, - ) - contraband = list( - /obj/item/weapon/reagent_containers/glass/bottle/wizarditis = 1, - ) //No one can get to the machine to hack it anyways; for the lulz - Microwave - - pack = /obj/structure/vendomatpack/magivend //Who's laughing now? wizarditis doesn't do shit anyway. - Deity Link - -/obj/machinery/vending/dinnerware - name = "Dinnerware" - desc = "A kitchen and restaurant equipment vendor" - product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..." - icon_state = "dinnerware" - products = list( - /obj/item/weapon/tray = 8, - /obj/item/weapon/kitchen/utensil/fork = 6, - /obj/item/weapon/kitchen/utensil/knife/large = 3, - /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8, - /obj/item/clothing/suit/chef/classic = 2, - /obj/item/trash/bowl = 20, - /obj/item/weapon/reagent_containers/food/condiment/peppermill = 5, - /obj/item/weapon/reagent_containers/food/condiment/saltshaker = 5, - /obj/item/weapon/reagent_containers/food/condiment/vinegar = 5, - /obj/item/weapon/storage/bag/food = 5 - ) - contraband = list( - /obj/item/weapon/kitchen/utensil/spoon = 2, - /obj/item/weapon/kitchen/utensil/knife = 2, - /obj/item/weapon/kitchen/rollingpin = 2, - /obj/item/weapon/kitchen/utensil/knife/large/butch = 2, - ) - premium = list( - /obj/item/weapon/reagent_containers/dropper/baster = 1) - - pack = /obj/structure/vendomatpack/dinnerware - -/obj/machinery/vending/sovietsoda - name = "BODA" - desc = "Old sweet water vending machine" - icon_state = "sovietsoda" - product_slogans = "BODA: We sell drink.;BODA: Drink today.;BODA: We're better then Comrade Dan." - product_ads = "For Tsar and Country.;Have you fulfilled your nutrition quota today?;Very nice!;We are simple people, for this is all we eat.;If there is a person, there is a problem. If there is no person, then there is no problem." - products = list( - /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda = 30, - ) - contraband = list( - /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola = 20, - ) - - pack = /obj/structure/vendomatpack/sovietsoda - -/obj/machinery/vending/tool - name = "YouTool" - desc = "Tools for tools." - icon_state = "tool" - icon_deny = "tool-deny" - //req_access_txt = "12" //Maintenance access - products = list( - /obj/item/stack/cable_coil/random = 10, - /obj/item/weapon/crowbar = 5, - /obj/item/weapon/weldingtool = 3, - /obj/item/weapon/wirecutters = 5, - /obj/item/weapon/wrench = 5, - /obj/item/device/analyzer = 5, - /obj/item/device/t_scanner = 5, - /obj/item/weapon/screwdriver = 5, - /obj/item/weapon/solder = 3, - /obj/item/device/silicate_sprayer = 2 - ) - contraband = list( - /obj/item/weapon/weldingtool/hugetank = 2, - /obj/item/clothing/gloves/fyellow = 2, - ) - premium = list( - /obj/item/clothing/gloves/yellow = 1, - ) - - pack = /obj/structure/vendomatpack/tool - -/obj/machinery/vending/engivend - name = "Engi-Vend" - desc = "Spare tool vending. What? Did you expect some witty description?" - icon_state = "engivend" - icon_deny = "engivend-deny" - req_access_txt = "11" //Engineering Equipment access - products = list( - /obj/item/clothing/glasses/meson = 2, - /obj/item/device/multitool = 4, - /obj/item/weapon/circuitboard/airlock = 10, - /obj/item/weapon/circuitboard/power_control = 10, - /obj/item/weapon/circuitboard/air_alarm = 10, - /obj/item/weapon/circuitboard/fire_alarm = 10, - /obj/item/weapon/intercom_electronics = 10, - /obj/item/weapon/cell/high = 10, - /obj/item/weapon/reagent_containers/glass/fuelcan = 5, - ) - contraband = list( - /obj/item/weapon/cell/potato = 3, - ) - premium = list( - /obj/item/weapon/storage/belt/utility = 3, - ) - - pack = /obj/structure/vendomatpack/engivend - -//This one's from bay12 -/obj/machinery/vending/engineering - name = "Robco Tool Maker" - desc = "Everything you need for do-it-yourself station repair." - icon_state = "engi" - icon_deny = "engi-deny" - req_access_txt = "11" - products = list( - /obj/item/clothing/under/rank/engineer = 4, - /obj/item/clothing/under/rank/atmospheric_technician = 4, - /obj/item/clothing/under/rank/maintenance_tech/ = 4, - /obj/item/clothing/under/rank/engine_tech = 4, - /obj/item/clothing/under/rank/electrician = 4, - /obj/item/clothing/shoes/orange = 4, - /obj/item/clothing/head/hardhat = 4, - /obj/item/clothing/head/hardhat/orange = 4, - /obj/item/clothing/head/hardhat/red = 4, - /obj/item/clothing/head/hardhat/white = 4, - /obj/item/clothing/head/hardhat/dblue = 4, - /obj/item/weapon/storage/belt/utility = 4, - /obj/item/clothing/glasses/meson = 4, - /obj/item/clothing/gloves/yellow = 4, - /obj/item/weapon/screwdriver = 12, - /obj/item/weapon/crowbar = 12, - /obj/item/weapon/wirecutters = 12, - /obj/item/device/multitool = 12, - /obj/item/weapon/wrench = 12, - /obj/item/device/t_scanner = 12, - /obj/item/stack/cable_coil = 8, - /obj/item/weapon/cell = 8, - /obj/item/weapon/weldingtool = 8, - /obj/item/clothing/head/welding = 8, - /obj/item/weapon/light/tube = 10, - /obj/item/clothing/suit/fire = 4, - /obj/item/weapon/stock_parts/scanning_module = 5, - /obj/item/weapon/stock_parts/micro_laser = 5, - /obj/item/weapon/stock_parts/matter_bin = 5, - /obj/item/weapon/stock_parts/manipulator = 5, - /obj/item/weapon/stock_parts/console_screen = 5, - ) - contraband = list( - /obj/item/weapon/wrench/socket = 1, - /obj/item/weapon/extinguisher/foam = 1, - /obj/item/device/device_analyser = 2, - ) - premium = list( - /obj/item/clothing/under/rank/chief_engineer = 2, - /obj/item/weapon/storage/belt = 2, - ) //belt is the best belt in the game. - // There was an incorrect entry (cablecoil/power). I improvised to cablecoil/heavyduty. - // Another invalid entry, /obj/item/weapon/circuitry. I don't even know what that would translate to, removed it. - // The original products list wasn't finished. The ones without given quantities became quantity 5. -Sayu - - pack = /obj/structure/vendomatpack/undefined - -//This one's from bay12 -/obj/machinery/vending/robotics - name = "Robotech Deluxe" - desc = "All the tools you need to create your own robot army." - icon_state = "robotics" - icon_deny = "robotics-deny" - req_access_txt = "29" - products = list( - /obj/item/clothing/suit/storage/labcoat = 4, - /obj/item/clothing/under/rank/roboticist = 4, - /obj/item/stack/cable_coil = 4, - /obj/item/device/flash = 4, - /obj/item/weapon/cell/high = 12, - /obj/item/device/assembly/prox_sensor = 3, - /obj/item/device/assembly/signaler = 3, - /obj/item/device/healthanalyzer = 3, - /obj/item/weapon/scalpel = 2, - /obj/item/weapon/circular_saw = 2, - /obj/item/weapon/tank/anesthetic = 2, - /obj/item/clothing/mask/breath/medical = 5, - /obj/item/weapon/screwdriver = 5, - /obj/item/weapon/crowbar = 5, - ) - //everything after the power cell had no amounts, I improvised. -Sayu - - pack = /obj/structure/vendomatpack/undefined - -/obj/machinery/vending/autodrobe - name = "\improper AutoDrobe" - desc = "A vending machine for costumes." - icon_state = "theater" - icon_deny = "theater-deny" - req_access = list(access_theatre) - product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!" - vend_delay = 15 - vend_reply = "Thank you for using AutoDrobe!" - products = list( - /obj/item/clothing/suit/chickensuit = 3, - /obj/item/clothing/head/chicken = 3, - /obj/item/clothing/suit/monkeysuit = 3, - /obj/item/clothing/mask/gas/monkeymask = 3, - /obj/item/clothing/suit/xenos = 3, - /obj/item/clothing/head/xenos = 3, - /obj/item/clothing/under/gladiator = 3, - /obj/item/clothing/head/helmet/gladiator = 3, - /obj/item/clothing/under/gimmick/rank/captain/suit = 3, - /obj/item/clothing/head/flatcap = 3, - /obj/item/clothing/glasses/gglasses = 3, - /obj/item/clothing/shoes/jackboots = 3, - /obj/item/clothing/under/schoolgirl = 3, - /obj/item/clothing/shoes/kneesocks = 3, - /obj/item/clothing/head/kitty = 3, - /obj/item/clothing/under/blackskirt = 3, - /obj/item/clothing/head/beret = 3, - /obj/item/clothing/suit/hastur = 3, - /obj/item/clothing/head/hasturhood = 3, - /obj/item/clothing/suit/wcoat = 3, - /obj/item/clothing/under/suit_jacket = 3, - /obj/item/clothing/head/that = 3, - /obj/item/clothing/head/cueball = 3, - /obj/item/clothing/under/scratch = 3, - /obj/item/clothing/under/kilt = 3, - /obj/item/clothing/head/beret = 3, - /obj/item/clothing/suit/wcoat = 3, - /obj/item/clothing/glasses/monocle =3, - /obj/item/clothing/head/bowlerhat = 3, - /obj/item/weapon/cane = 3, - /obj/item/clothing/under/sl_suit = 3, - /obj/item/clothing/mask/fakemoustache = 3, - /obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 3, - /obj/item/clothing/head/plaguedoctorhat = 3, - /obj/item/clothing/mask/gas/plaguedoctor = 3, - /obj/item/clothing/under/owl = 3, - /obj/item/clothing/mask/gas/owl_mask = 3, - /obj/item/clothing/suit/apron = 3, - /obj/item/clothing/under/waiter = 3, - /obj/item/clothing/under/pirate = 3, - /obj/item/clothing/suit/pirate = 3, - /obj/item/clothing/head/pirate = 3, - /obj/item/clothing/head/bandana = 3, - /obj/item/clothing/head/bandana = 3, - /obj/item/clothing/under/soviet = 3, - /obj/item/clothing/head/ushanka = 3, - /obj/item/clothing/suit/imperium_monk = 3, - /obj/item/clothing/mask/gas/cyborg = 3, - /obj/item/clothing/suit/holidaypriest = 3, - /obj/item/clothing/head/wizard/marisa/fake = 3, - /obj/item/clothing/suit/wizrobe/marisa/fake = 3, - /obj/item/clothing/under/sundress = 3, - /obj/item/clothing/head/witchwig = 3, - /obj/item/weapon/staff/broom = 3, - /obj/item/clothing/suit/wizrobe/fake = 3, - /obj/item/clothing/head/wizard/fake = 3, - /obj/item/weapon/staff = 3, - /obj/item/clothing/mask/gas/sexyclown = 3, - /obj/item/clothing/under/sexyclown = 3, - /obj/item/clothing/mask/gas/sexymime = 3, - /obj/item/clothing/under/sexymime = 3, - /obj/item/clothing/suit/apron/overalls = 3, - /obj/item/clothing/head/rabbitears = 3, - /obj/item/clothing/head/lordadmiralhat = 3, - /obj/item/clothing/suit/lordadmiral = 3, - /obj/item/clothing/suit/doshjacket = 3, - /obj/item/clothing/under/jester = 3, - /obj/item/clothing/head/jesterhat = 3, - /obj/item/clothing/shoes/jestershoes = 3, - /obj/item/clothing/suit/kefkarobe = 3, - /obj/item/clothing/head/helmet/aviatorhelmet = 3, - /obj/item/clothing/shoes/aviatorboots = 3, - /obj/item/clothing/under/aviatoruniform = 3, - /obj/item/clothing/head/libertyhat = 3, - /obj/item/clothing/suit/libertycoat = 3, - /obj/item/clothing/under/libertyshirt = 3, - /obj/item/clothing/shoes/libertyshoes = 3, - /obj/item/clothing/head/helmet/megahelmet = 3, - /obj/item/clothing/under/mega = 3, - /obj/item/clothing/gloves/megagloves = 3, - /obj/item/clothing/shoes/megaboots =3, - /obj/item/clothing/head/helmet/protohelmet = 3, - /obj/item/clothing/under/proto =3, - /obj/item/clothing/gloves/protogloves =3, - /obj/item/clothing/shoes/protoboots =3, - /obj/item/clothing/under/roll = 3, - /obj/item/clothing/head/maidhat =3, - /obj/item/clothing/under/maid = 3, - /obj/item/clothing/suit/maidapron = 3, - /obj/item/clothing/head/mitre = 3, - /obj/item/clothing/under/clownpiece = 3, - /obj/item/clothing/suit/clownpiece = 3, - /obj/item/clothing/head/clownpiece = 3, - /obj/item/clothing/head/cowboy = 3, - ) //Pretty much everything that had a chance to spawn. - contraband = list( - /obj/item/clothing/suit/cardborg = 3, - /obj/item/clothing/head/cardborg = 3, - /obj/item/clothing/suit/judgerobe = 3, - /obj/item/clothing/head/powdered_wig = 3, - /obj/item/toy/gun = 3, - ) - premium = list( - /obj/item/clothing/suit/hgpirate = 3, - /obj/item/clothing/head/hgpiratecap = 3, - /obj/item/clothing/head/helmet/roman = 3, - /obj/item/clothing/head/helmet/roman/legionaire = 3, - /obj/item/clothing/under/roman = 3, - /obj/item/clothing/shoes/roman = 3, - /obj/item/weapon/shield/riot/roman = 3, - /obj/item/clothing/under/stilsuit = 3, - /obj/item/clothing/head/helmet/breakhelmet = 3, - /obj/item/clothing/head/helmet/joehelmet = 3, - /obj/item/clothing/under/joe = 3, - /obj/item/clothing/gloves/joegloves = 3, - /obj/item/clothing/shoes/joeboots =3, - /obj/item/weapon/shield/riot/proto = 3, - /obj/item/weapon/shield/riot/joe = 3, - /obj/item/clothing/under/darkholme = 3, - /obj/item/clothing/suit/wizrobe/magician/fake = 3, - /obj/item/clothing/head/wizard/magician = 3, - ) - - pack = /obj/structure/vendomatpack/autodrobe - -/obj/machinery/vending/hatdispenser - name = "Hatlord 9000" - desc = "It doesn't seem the slightist bit unusual. This frustrates you immensly." - icon_state = "hats" - vend_reply = "Take care now!" - product_ads = "Buy some hats!;A bare head is absoloutly ASKING for a robusting!" - product_slogans = "Warning, not all hats are dog/monkey compatable. Apply forcefully with care.;Apply directly to the forehead.;Who doesn't love spending cash on hats?!;From the people that brought you collectable hat crates, Hatlord!" - products = list( - /obj/item/clothing/head/bowlerhat = 10, - /obj/item/clothing/head/beaverhat = 10, - /obj/item/clothing/head/boaterhat = 10, - /obj/item/clothing/head/fedora = 10, - /obj/item/clothing/head/fez = 10, - /obj/item/clothing/head/soft/blue = 10, - /obj/item/clothing/head/soft/green = 10, - /obj/item/clothing/head/soft/grey = 10, - /obj/item/clothing/head/soft/orange = 10, - /obj/item/clothing/head/soft/purple = 10, - /obj/item/clothing/head/soft/red = 10, - /obj/item/clothing/head/soft/yellow = 10, - ) - contraband = list( - /obj/item/clothing/head/bearpelt = 5, - ) - premium = list( - /obj/item/clothing/head/soft/rainbow = 1, - ) - - pack = /obj/structure/vendomatpack/hatdispenser - -/obj/machinery/vending/suitdispenser - name = "Suitlord 9000" - desc = "You wonder for a moment why all of your shirts and pants come conjoined. This hurts your head and you stop thinking about it." - icon_state = "suits" - vend_reply = "Come again!" - product_ads = "Skinny? Looking for some clothes? Suitlord is the machine for you!;BUY MY PRODUCT!" - product_slogans = "Pre-Ironed, Pre-Washed, Pre-Wor-*BZZT*;Blood of your enemies washes right out!;Who are YOU wearing?;Look dapper! Look like an idiot!;Don't carry your size? How about you shave off some pounds you fat lazy- *BZZT*" - products = list( - /obj/item/clothing/under/color/black = 10, - /obj/item/clothing/under/color/blue = 10, - /obj/item/clothing/under/color/green = 10, - /obj/item/clothing/under/color/grey = 10, - /obj/item/clothing/under/color/pink = 10, - /obj/item/clothing/under/color/red = 10, - /obj/item/clothing/under/color/white = 10, - /obj/item/clothing/under/color/yellow = 10, - /obj/item/clothing/under/lightblue = 10, - /obj/item/clothing/under/aqua = 10, - /obj/item/clothing/under/purple = 10, - /obj/item/clothing/under/lightgreen = 10, - /obj/item/clothing/under/lightblue = 10, - /obj/item/clothing/under/lightbrown = 10, - /obj/item/clothing/under/brown = 10, - /obj/item/clothing/under/yellowgreen = 10, - /obj/item/clothing/under/darkblue = 10, - /obj/item/clothing/under/lightred = 10, - /obj/item/clothing/under/darkred = 10, - /obj/item/clothing/under/bluepants = 10, - /obj/item/clothing/under/blackpants = 10, - /obj/item/clothing/under/redpants = 10, - /obj/item/clothing/under/greypants = 10, - ) - contraband = list( - /obj/item/clothing/under/syndicate/tacticool = 5, - /obj/item/clothing/under/color/orange = 5, - /obj/item/clothing/under/psyche = 5, - ) - premium = list( - /obj/item/clothing/under/rainbow = 1, - ) - - pack = /obj/structure/vendomatpack/suitdispenser - -//THIS IS WHERE THE FEET LIVE, GIT YE SOME -/obj/machinery/vending/shoedispenser - name = "Shoelord 9000" - desc = "Wow, hatlord looked fancy, suitlord looked streamlined, and this is just normal. The guy who designed these must be an idiot." - icon_state = "shoes" - vend_reply = "Enjoy your pair!" - product_ads = "Dont be a hobbit: Choose shoelord.;Shoes snatched? Get on it with shoelord." - product_slogans = "Put your foot down!;One size fits all!;IM WALKING ON SUNSHINE!;No hobbits allowed.;NO PLEASE WILLY, DONT HURT ME- *BZZT*" - products = list( - /obj/item/clothing/shoes/black = 10, - /obj/item/clothing/shoes/brown = 10, - /obj/item/clothing/shoes/blue = 10, - /obj/item/clothing/shoes/green = 10, - /obj/item/clothing/shoes/yellow = 10, - /obj/item/clothing/shoes/purple = 10, - /obj/item/clothing/shoes/red = 10, - /obj/item/clothing/shoes/white = 10, - ) - contraband = list( - /obj/item/clothing/shoes/jackboots = 5, - /obj/item/clothing/shoes/orange = 5, - ) - premium = list( - /obj/item/clothing/shoes/rainbow = 1, - ) - - pack = /obj/structure/vendomatpack/shoedispenser - -//HEIL ADMINBUS -/obj/machinery/vending/nazivend - name = "Nazivend" - desc = "Remember the gorrilions lost." - icon_state = "nazi" - vend_reply = "SIEG HEIL!" - product_ads = "BESTRAFEN die Juden.;BESTRAFEN die Alliierten." - product_slogans = "Das Vierte Reich wird zuruckkehren!;ENTFERNEN JUDEN!;Billiger als die Juden jemals geben!;Rader auf dem adminbus geht rund und rund.;Warten Sie, warum wir wieder hassen Juden?- *BZZT*" - products = list( - /obj/item/clothing/head/stalhelm = 20, - /obj/item/clothing/head/panzer = 20, - /obj/item/clothing/suit/soldiercoat = 20, - /obj/item/clothing/under/soldieruniform = 20, - /obj/item/clothing/shoes/jackboots = 20, - ) - contraband = list( - /obj/item/clothing/head/naziofficer = 10, - /obj/item/clothing/suit/officercoat = 10, - /obj/item/clothing/under/officeruniform = 10, - ) - - pack = /obj/structure/vendomatpack/nazivend - - machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | EMAGGABLE - -/obj/machinery/vending/nazivend/emag(mob/user) - if(!emagged) - to_chat(user, "As you slide the emag on the machine, you can hear something unlocking inside, and the machine starts emitting an evil glow.") - message_admins("[key_name_admin(user)] unlocked a Nazivend's DANGERMODE") - contraband[/obj/item/clothing/head/helmet/space/rig/nazi] = 3 - contraband[/obj/item/clothing/suit/space/rig/nazi] = 3 - contraband[/obj/item/weapon/gun/energy/plasma/MP40k] = 4 - src.build_inventory(contraband, 1) - emagged = 1 - overlays = 0 - var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) - overlays_vending[2] = dangerlay - update_icon() - return 1 - return - -//NaziVend++ -/obj/machinery/vending/nazivend/DANGERMODE - products = list( - /obj/item/clothing/head/stalhelm = 20, - /obj/item/clothing/head/panzer = 20, - /obj/item/clothing/suit/soldiercoat = 20, - /obj/item/clothing/under/soldieruniform = 20, - /obj/item/clothing/shoes/jackboots = 20, - ) - contraband = list( - /obj/item/clothing/head/naziofficer = 10, - /obj/item/clothing/suit/officercoat = 10, - /obj/item/clothing/under/officeruniform = 10, - /obj/item/clothing/head/helmet/space/rig/nazi = 3, - /obj/item/clothing/suit/space/rig/nazi = 3, - /obj/item/weapon/gun/energy/plasma/MP40k = 4, - ) - - pack = /obj/structure/vendomatpack/nazivend //can be reloaded with the same packs as the regular one - -/obj/machinery/vending/nazivend/DANGERMODE/New() - ..() - emagged = 1 - overlays = 0 - var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) - overlays_vending[2] = dangerlay - update_icon() - -//MOTHERBUSLAND -/obj/machinery/vending/sovietvend - name = "KomradeVendtink" - desc = "Rodina-mat' zovyot!" - icon_state = "soviet" - vend_reply = "The fascist and capitalist svin'ya shall fall komrade!" - product_ads = "Quality worth waiting in line for!; Get Hammer and Sickled!; Sosvietsky soyuz above all!; With capitalist pigsky, you would have paid a fortunetink!" - product_slogans = "Craftink in Motherland herself!" - products = list( - /obj/item/clothing/under/soviet = 20, - /obj/item/clothing/head/ushanka = 20, - /obj/item/clothing/shoes/jackboots = 20, - /obj/item/clothing/head/squatter_hat = 20, - /obj/item/clothing/under/squatter_outfit = 20, - /obj/item/clothing/under/russobluecamooutfit = 20, - /obj/item/clothing/head/russobluecamohat = 20, - ) - contraband = list( - /obj/item/clothing/under/syndicate/tacticool = 4, - /obj/item/clothing/mask/balaclava = 4, - /obj/item/clothing/suit/russofurcoat = 4, - /obj/item/clothing/head/russofurhat = 4, - ) - - pack = /obj/structure/vendomatpack/sovietvend - - machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | EMAGGABLE - - -/obj/machinery/vending/sovietvend/emag(mob/user) - if(!emagged) - to_chat(user, "As you slide the emag on the machine, you can hear something unlocking inside, and the machine starts emitting an evil glow.") - message_admins("[key_name_admin(user)] unlocked a Sovietvend's DANGERMODE") - contraband[/obj/item/clothing/head/helmet/space/rig/soviet] = 3 - contraband[/obj/item/clothing/suit/space/rig/soviet] = 3 - contraband[/obj/item/weapon/gun/energy/laser/LaserAK] = 4 - src.build_inventory(contraband, 1) - emagged = 1 - overlays = 0 - var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) - overlays_vending[2] = dangerlay - update_icon() - return 1 - return - -//SovietVend++ -/obj/machinery/vending/sovietvend/DANGERMODE - products = list( - /obj/item/clothing/under/soviet = 20, - /obj/item/clothing/head/ushanka = 20, - /obj/item/clothing/shoes/jackboots = 20, - /obj/item/clothing/head/squatter_hat = 20, - /obj/item/clothing/under/squatter_outfit = 20, - /obj/item/clothing/under/russobluecamooutfit = 20, - /obj/item/clothing/head/russobluecamohat = 20, - ) - contraband = list( - /obj/item/clothing/under/syndicate/tacticool = 4, - /obj/item/clothing/mask/balaclava = 4, - /obj/item/clothing/suit/russofurcoat = 4, - /obj/item/clothing/head/russofurhat = 4, - /obj/item/clothing/head/helmet/space/rig/soviet = 3, - /obj/item/clothing/suit/space/rig/soviet = 3, - /obj/item/weapon/gun/energy/laser/LaserAK = 4, - ) - - pack = /obj/structure/vendomatpack/sovietvend//can be reloaded with the same packs as the regular one - -/obj/machinery/vending/sovietvend/DANGERMODE/New() - ..() - emagged = 1 - overlays = 0 - var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) - overlays_vending[2] = dangerlay - update_icon() - -/obj/machinery/vending/discount - name = "Discount Dan's" - desc = "A snack machine owned by the infamous 'Discount Dan' franchise." - product_slogans = "Discount Dan, he's the man!;There 'aint nothing better in this world then a bite of mystery.;Don't listen to those other machines, buy my product!;Quantity over Quality!;Don't listen to those eggheads at the CDC, buy now!;Discount Dan's: We're good for you! Nope, couldn't say it with a straight face.;Discount Dan's: Only the best quality produ-*BZZT*" - product_ads = "Discount Dan(tm) is not responsible for any damages caused by misuse of his product." - vend_reply = "No refunds." - icon_state = "discount" - products = list( - /obj/item/weapon/reagent_containers/food/snacks/discountchocolate = 6, - /obj/item/weapon/reagent_containers/food/snacks/danitos =6, - /obj/item/weapon/reagent_containers/food/snacks/discountburger = 6, - /obj/item/weapon/reagent_containers/food/drinks/discount_ramen = 6, - /obj/item/weapon/reagent_containers/food/snacks/discountburrito = 6, - /obj/item/weapon/reagent_containers/food/snacks/pie/discount = 6, - ) - contraband = list( - /obj/item/weapon/reagent_containers/pill/antitox = 10 - ) - prices = list( - /obj/item/weapon/reagent_containers/food/snacks/discountchocolate = 8, - /obj/item/weapon/reagent_containers/food/snacks/danitos = 10, - /obj/item/weapon/reagent_containers/food/snacks/discountburger = 10, - /obj/item/weapon/reagent_containers/food/drinks/discount_ramen = 2, - /obj/item/weapon/reagent_containers/food/snacks/discountburrito = 10, - /obj/item/weapon/reagent_containers/food/snacks/pie/discount = 8, - /obj/item/weapon/reagent_containers/pill/antitox = 10 - ) - - pack = /obj/structure/vendomatpack/discount - -/obj/machinery/vending/groans - name = "Groans Soda" - desc = "A soda machine owned by the infamous 'Groans' franchise." - product_slogans = "Groans: Drink up!;Sponsored by Discount Dan!;Take a sip!;Just one sip, do it!" - product_ads = "Try our new 'Double Dan' flavor!" - vend_reply = "No refunds." - icon_state = "groans" - products = list( - /obj/item/weapon/reagent_containers/food/drinks/groans = 10, - /obj/item/weapon/reagent_containers/food/drinks/filk = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink = 10, - ) - prices = list( - /obj/item/weapon/reagent_containers/food/drinks/groans = 20, - /obj/item/weapon/reagent_containers/food/drinks/filk = 20, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo = 30, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink = 10, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink = 50, - /obj/item/weapon/reagent_containers/food/drinks/groansbanned = 50, - ) - contraband = list( - /obj/item/weapon/reagent_containers/food/drinks/groansbanned = 10, - ) - - pack = /obj/structure/vendomatpack/groans - -/obj/machinery/vending/nuka - name = "Nuka Cola Machine" - desc = "A machine filled to the brim with ice cold Nuka Cola!" - product_slogans = "A refreshing burst of atomic energy!;Drink like there's no tomorrow!;Take the leap... enjoy a Quantum!" - product_ads = "Wouldn't you enjoy an ice cold Nuka Cola right about now?" - vend_reply = "Enjoy a Nuka break!" - icon_state = "nuka" - products = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka = 15) - prices = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka = 20, /obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum = 50) - contraband = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum = 5) - - pack = /obj/structure/vendomatpack/nuka - -/obj/machinery/vending/chapel - name = "PietyVend" - desc = "A holy vendor for a pious man." - product_slogans = "Bene orasse est bene studuisse.;Beati pauperes spiritu.;Di immortales virtutem approbare, non adhibere debent." - product_ads = "Deus tecum." - vend_reply = "Deus vult!" - icon_state = "chapel" - products = list( - /obj/item/clothing/under/rank/chaplain = 2, - /obj/item/clothing/shoes/black = 2, - /obj/item/clothing/suit/nun = 2, - /obj/item/clothing/head/nun_hood = 2, - /obj/item/clothing/suit/chaplain_hoodie = 2, - /obj/item/clothing/head/chaplain_hood = 2, - /obj/item/clothing/suit/holidaypriest = 2, - /obj/item/clothing/under/wedding/bride_white = 2, - /obj/item/clothing/head/hasturhood = 2, - /obj/item/clothing/suit/hastur = 2, - /obj/item/clothing/suit/unathi/robe = 2, - /obj/item/clothing/head/wizard/amp = 2, - /obj/item/clothing/suit/wizrobe/psypurple = 2, - /obj/item/clothing/suit/imperium_monk = 2, - /obj/item/clothing/mask/chapmask = 2, - /obj/item/clothing/under/sl_suit = 2, - /obj/item/weapon/storage/backpack/cultpack = 2, - /obj/item/weapon/storage/fancy/candle_box = 5, - /obj/item/weapon/reagent_containers/food/snacks/eucharist = 7, - ) - premium = list( - /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 1, - /obj/item/clothing/head/helmet/knight/templar = 2, - /obj/item/clothing/suit/armor/knight/templar = 5, - ) - req_access_txt = "22" - - pack = /obj/structure/vendomatpack/chapelvend +#define CAT_NORMAL 1 +#define CAT_HIDDEN 2 +#define CAT_COIN 3 + +var/global/num_vending_terminals = 1 + +/datum/data/vending_product + var/product_name = "generic" + var/product_path = null + var/original_amount = 0 + var/amount = 0 + var/price = 0 + var/display_color = "blue" + var/category = CAT_NORMAL//available by default, contraband, or premium (requires a coin) + var/subcategory = null + +/* TODO: Add this to deconstruction for vending machines +/obj/item/compressed_vend + name = "compressed sale cartridge" + desc = "A compressed matter variant used to load vending machines." + icon = 'icons/obj/ammo.dmi' + icon_state = "rcd" + item_state = "rcdammo" + var/list/products + var/list/contraband + var/list/premium +*/ + +/obj/machinery/vending + name = "Empty vending machine" + desc = "Just add some capitalism." + icon = 'icons/obj/vending.dmi' + icon_state = "empty" + var/obj/structure/vendomatpack/pack = null + layer = 2.9 + anchored = 1 + density = 1 + var/health = 100 + var/maxhealth = 100 //Kicking feature + var/active = 1 //No sales pitches if off! + var/vend_ready = 1 //Are we ready to vend?? Is it time?? + var/vend_delay = 10 //How long does it take to vend? + var/shoot_chance = 2 //How often do we throw items? + var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now. + // To be filled out at compile time + var/list/products = list() // For each, use the following pattern: + var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2) + var/list/premium = list() // No specified amount = only one in stock + var/list/prices = list() // Prices for each item, list(/type/path = price), items not in the list don't have a price. + + var/product_slogans = "" //String of slogans separated by semicolons, optional + var/product_ads = "" //String of small ad messages in the vending screen - random chance + var/list/product_records = list() + var/list/hidden_records = list() + var/list/coin_records = list() + var/list/slogan_list = list() + var/list/small_ads = list() //Small ad messages in the vending screen - random chance of popping up whenever you open it + var/vend_reply //Thank you for shopping! + var/last_reply = 0 + var/last_slogan = 0 //When did we last pitch? + var/slogan_delay = 6000 //How long until we can pitch again? + var/icon_vend //Icon_state when vending! + var/icon_deny //Icon_state when vending! + //var/emagged = 0 //Ignores if somebody doesn't have card access to that machine. + var/seconds_electrified = 0 //Shock customers like an airlock. + var/shoot_inventory = 0 //Fire items at customers! We're broken! + var/shut_up = 0 //Stop spouting those godawful pitches! + var/extended_inventory = 0 //can we access the hidden inventory? + var/scan_id = 1 + var/obj/item/weapon/coin + var/datum/wires/vending/wires = null + var/list/overlays_vending[2]//1 is the panel layer, 2 is the dangermode layer + + var/list/vouchers + var/obj/item/weapon/storage/lockbox/coinbox/coinbox + var/cardboard = 0 //1 if sheets of cardboard are added + + var/list/categories = list() + var/list/allowed_inputs = list() //items that we can directly slot into the vending machine + + var/machine_id = "#" + + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK + +/obj/machinery/vending/cultify() + new /obj/structure/cult/forge(loc) + ..() + +/obj/machinery/vending/New() + ..() + machine_id = "[name] #[multinum_display(num_vending_machines,4)]" + num_vending_machines++ + + overlays_vending[1] = "[icon_state]-panel" + + component_parts = newlist(\ + /obj/item/weapon/circuitboard/vendomat,\ + /obj/item/weapon/stock_parts/matter_bin,\ + /obj/item/weapon/stock_parts/manipulator,\ + /obj/item/weapon/stock_parts/scanning_module\ + ) + + RefreshParts() + + wires = new(src) + spawn(4) + src.slogan_list = text2list(src.product_slogans, ";") + + // So not all machines speak at the exact same time. + // The first time this machine says something will be at slogantime + this random value, + // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. + src.last_slogan = world.time + rand(0, slogan_delay) + + power_change() + + coinbox = new(src) + + if(ticker) + initialize() + + return + +/obj/machinery/vending/initialize() + ..() + product_records = new/list() + build_inventory(products) + build_inventory(contraband, 1) + build_inventory(premium, 0, 1) + +/obj/machinery/vending/RefreshParts() + var/manipcount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/manipulator)) manipcount += SP.rating + shoot_chance = manipcount * 3 + +/obj/machinery/vending/Destroy() + if(wires) + qdel(wires) + wires = null + + if(product_records.len&&cardboard) //Only spit out if we have slotted cardboard + var/obj/structure/vendomatpack/partial/newpack = new(src.loc) + newpack.stock = products + newpack.secretstock = contraband + newpack.preciousstock = premium + newpack.targetvendomat = src.type + newpack.product_records = product_records + newpack.hidden_records = hidden_records + newpack.coin_records = coin_records + + if(coinbox) + coinbox.forceMove(get_turf(src)) + ..() + +/obj/machinery/vending/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSMACHINE)) + return 1 + return ..() + +/obj/machinery/vending/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if(stat & (BROKEN|NOPOWER)) + return + + if(istype(O,/obj/structure/vendomatpack)) + var/obj/structure/vendomatpack/P = O + if(!anchored) + to_chat(user, "You need to anchor the vending machine before you can refill it.") + return + if(!pack) + to_chat(user, "You start filling the vending machine with the recharge pack's materials.") + var/user_loc = user.loc + var/pack_loc = P.loc + var/self_loc = src.loc + sleep(30) + if(!user || !P || !src) + return + if (user.loc == user_loc && P.loc == pack_loc && anchored && self_loc == src.loc && !(user.stat) && (!user.stunned && !user.weakened && !user.paralysis && !user.lying)) + var/obj/machinery/vending/newmachine = new P.targetvendomat(loc) + to_chat(user, "\icon[newmachine] You finish filling the vending machine, and use the stickers inside the pack to decorate the frame.") + playsound(newmachine, 'sound/machines/hiss.ogg', 50, 0, 0) + newmachine.pack = P.type + var/obj/item/emptyvendomatpack/emptypack = new /obj/item/emptyvendomatpack(P.loc) + emptypack.icon_state = P.icon_state + emptypack.overlays += image('icons/obj/vending_pack.dmi',"emptypack") + if(P.stock.len) + newmachine.products = P.stock + newmachine.contraband = P.secretstock + newmachine.premium = P.preciousstock + newmachine.product_records = P.product_records + newmachine.hidden_records = P.hidden_records + newmachine.coin_records = P.coin_records + qdel(P) + if(user.machine==src) + newmachine.attack_hand(user) + component_parts = 0 + qdel(coinbox) + qdel(src) + else + if(istype(P,pack)) + to_chat(user, "You start refilling the vending machine with the recharge pack's materials.") + var/user_loc = user.loc + var/pack_loc = P.loc + var/self_loc = src.loc + sleep(30) + if(!user || !P || !src) + return + if (user.loc == user_loc && P.loc == pack_loc && anchored && self_loc == src.loc && !(user.stat) && (!user.stunned && !user.weakened && !user.paralysis && !user.lying)) + to_chat(user, "\icon[src] You finish refilling the vending machine.") + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + for (var/datum/data/vending_product/D in product_records) + D.amount = D.original_amount + for (var/datum/data/vending_product/D in hidden_records) + D.amount = D.original_amount + var/obj/item/emptyvendomatpack/emptypack = new /obj/item/emptyvendomatpack(P.loc) + emptypack.icon_state = P.icon_state + emptypack.overlays += image('icons/obj/vending_pack.dmi',"emptypack") + qdel(P) + if(user.machine==src) + src.attack_hand(user) + else + to_chat(user, "This recharge pack isn't meant for this kind of vending machines.") + +/obj/machinery/vending/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if(prob(25)) + malfunction() + + +/obj/machinery/vending/blob_act() + if(prob(75)) + malfunction() + else + qdel(src) + +/obj/machinery/vending/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + return + switch(severity) + if(1.0) + malfunction() + if(2.0) + if(prob(50)) malfunction() + if(3.0) + if(prob(25)) malfunction() + +/obj/machinery/vending/proc/build_inventory(var/list/productlist,hidden=0,req_coin=0) + var/obj/item/temp + + for (var/typepath in productlist) + var/amount = productlist[typepath] + var/price = prices[typepath] + + if (isnull(amount)) + amount = 1 + + var/datum/data/vending_product/R = new() + R.product_path = typepath + R.amount = amount + R.original_amount = amount + R.price = price + R.display_color = pick("red", "blue", "green") + + if (hidden) + R.category=CAT_HIDDEN + hidden_records += R + else if (req_coin) + R.category=CAT_COIN + coin_records += R + else + R.category = CAT_NORMAL + product_records.Add(R) + + temp = new typepath(null) + + R.product_name = temp.name + R.subcategory = temp.vending_cat + +/obj/machinery/vending/proc/get_item_by_type(var/this_type) + var/list/datum_products = list() + datum_products |= hidden_records + datum_products |= coin_records + datum_products |= product_records + for(var/datum/data/vending_product/product in datum_products) + if(product.product_path == this_type) + return product + return null + +// to_chat(world, "Added: [R.product_name]] - [R.amount] - [R.product_path]") + +/obj/machinery/vending/emag(mob/user) + if(!emagged) + emagged = 1 + to_chat(user, "You short out the product lock on \the [src]") + return 1 + return -1 + +/obj/machinery/vending/proc/can_accept_voucher(var/obj/item/voucher/voucher, mob/user) + if(istype(voucher, /obj/item/voucher/free_item)) + var/obj/item/voucher/free_item/free_vouch = voucher + for(var/vend_item in free_vouch.freebies) + var/datum/data/vending_product/product = get_item_by_type(vend_item) + if(product && product.amount) + return 1 + return 0 + +//this should ideally be called last as a parent method, since it can delete the voucher +/obj/machinery/vending/proc/voucher_act(var/obj/item/voucher/voucher, mob/user) + if(istype(voucher, /obj/item/voucher/free_item)) + var/obj/item/voucher/free_item/free_vouch = voucher + for(var/i = 1; i <= free_vouch.vend_amount; i++) + if(!free_vouch.freebies || !free_vouch.freebies.len) + break + var/to_vend = pick(free_vouch.freebies) + if(free_vouch.single_items) + free_vouch.freebies.Remove(to_vend) + var/datum/data/vending_product/product = get_item_by_type(to_vend) + if(product && product.amount) + src.vend(product, user, by_voucher = 1) + + if(voucher.shred_on_use) + qdel(voucher) + else + if(!vouchers) + vouchers = list() + vouchers.Add(voucher) + if(coinbox) + voucher.forceMove(coinbox) + return 1 + +/obj/machinery/vending/attackby(obj/item/W, mob/user) + if(stat & (BROKEN)) + if(istype(W, /obj/item/stack/sheet/glass/rglass)) + var/obj/item/stack/sheet/glass/rglass/G = W + to_chat(user, "You replace the broken glass.") + G.use(1) + stat &= ~BROKEN + src.health = 100 + src.update_vicon() + getFromPool(/obj/item/weapon/shard, loc) + else + to_chat(user, "[src] is broken! Fix it first.") + return + . = ..() + if(.) + return . + if(!cardboard && istype(W, /obj/item/stack/sheet/cardboard)) + var/obj/item/stack/sheet/cardboard/C = W + if(C.amount>=4) + C.use(4) + to_chat(user, "You slot some cardboard into the machine into [src].") + cardboard = 1 + src.updateUsrDialog() + if(istype(W, /obj/item/device/multitool)||istype(W, /obj/item/weapon/wirecutters)) + if(panel_open) + attack_hand(user) + return + else if(premium.len > 0 && is_type_in_list(W, list(/obj/item/weapon/coin/, /obj/item/weapon/reagent_containers/food/snacks/chococoin))) + if (isnull(coin)) + if(user.drop_item(W, src)) + coin = W + to_chat(user, "You insert a coin into [src].") + src.updateUsrDialog() + else + to_chat(user, "There's already a coin in [src].") + return + else if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/customizable/candy/coin)) + to_chat(user, "That coin is smudgy and oddly soft, you don't think that would work.") + return + else if(istype(W, /obj/item/voucher)) + if(can_accept_voucher(W, user)) + if(user.drop_item(W, src)) + to_chat(user, "You insert [W] into [src].") + return voucher_act(W, user) + src.updateUsrDialog() + else + to_chat(user, "\The [src] refuses to take [W].") + return 1 + else if(istype(W, /obj/item/weapon/storage/bag)) + var/obj/item/weapon/storage/bag/bag = W + var/objects_loaded = 0 + for(var/obj/G in bag.contents) + if(is_type_in_list(G, allowed_inputs)) + bag.remove_from_storage(G,src) + add_item(G) + objects_loaded++ + if(objects_loaded) + user.visible_message("[user] loads \the [src] with \the [bag].", \ + "You load \the [src] with \the [bag].") + if(bag.contents.len > 0) + to_chat(user, "Some items are refused.") + src.updateUsrDialog() + else + if(is_type_in_list(W, allowed_inputs)) + if(user.drop_item(W, src)) + add_item(W) + src.updateUsrDialog() + /*else if(istype(W, /obj/item/weapon/card) && currently_vending) + //attempt to connect to a new db, and if that doesn't work then fail + if(!linked_db) + reconnect_database() + if(linked_db) + if(linked_account) + var/obj/item/weapon/card/I = W + scan_card(I) + else + to_chat(usr, "\icon[src]Unable to connect to linked account.") + else + to_chat(usr, "\icon[src]Unable to connect to accounts database.")*/ + +//H.wear_id + +/obj/machinery/vending/scan_card(var/obj/item/weapon/card/I) + if(!currently_vending) return + if (istype(I, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/C = I + visible_message("[usr] swipes a card through [src].") + if(linked_account) + //we start by checking the ID card's virtual wallet + var/datum/money_account/D = C.virtual_wallet + var/using_account = "Virtual Wallet" + + //if there isn't one for some reason we create it, that should never happen but oh well. + if(!D) + C.update_virtual_wallet() + D = C.virtual_wallet + + var/transaction_amount = currently_vending.price + + //if there isn't enough money in the virtual wallet, then we check the bank account connected to the ID + if(D.money < transaction_amount) + D = linked_db.attempt_account_access(C.associated_account_number, 0, 2, 0) + using_account = "Bank Account" + if(!D) //first we check if there IS a bank account in the first place + to_chat(usr, "\icon[src]You don't have that much money on your virtual wallet!") + to_chat(usr, "\icon[src]Unable to access your bank account.") + return 0 + else if(D.security_level > 0) //next we check if the security is low enough to pay directly from it + to_chat(usr, "\icon[src]You don't have that much money on your virtual wallet!") + to_chat(usr, "\icon[src]Lower your bank account's security settings if you wish to pay directly from it.") + return 0 + else if(D.money < transaction_amount)//and lastly we check if there's enough money on it, duh + to_chat(usr, "\icon[src]You don't have that much money on your bank account!") + return 0 + + //transfer the money + D.money -= transaction_amount + linked_account.money += transaction_amount + + to_chat(usr, "\icon[src]Remaining balance ([using_account]): [D.money]$") + + //create an entry on the buy's account's transaction log + var/datum/transaction/T = new() + T.target_name = "[linked_account.owner_name] (via [src.name])" + T.purpose = "Purchase of [currently_vending.product_name]" + T.amount = "-[transaction_amount]" + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + D.transaction_log.Add(T) + + //and another entry on the vending machine's vendor account's transaction log + T = new() + T.target_name = D.owner_name + T.purpose = "Purchase of [currently_vending.product_name]" + T.amount = "[transaction_amount]" + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + linked_account.transaction_log.Add(T) + + // Vend the item + src.vend(src.currently_vending, usr) + currently_vending = null + else + to_chat(usr, "\icon[src]EFTPOS is not connected to an account.") + +/obj/machinery/vending/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/machinery/vending/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/vending/proc/GetProductLine(var/datum/data/vending_product/P) + var/dat = {"[P.product_name]: + [P.amount] "} + if(P.price) + dat += " ($[P.price])" + if (P.amount > 0) + var/idx=GetProductIndex(P) + dat += " (Vend)" + else + dat += " SOLD OUT" + dat += "
                      " + + return dat + +/obj/machinery/vending/proc/GetProductIndex(var/datum/data/vending_product/P) + var/list/plist + switch(P.category) + if(CAT_NORMAL) + plist=product_records + if(CAT_HIDDEN) + plist=hidden_records + if(CAT_COIN) + plist=coin_records + else + warning("UNKNOWN CATEGORY [P.category] IN TYPE [P.product_path] INSIDE [type]!") + return plist.Find(P) + +/obj/machinery/vending/proc/GetProductByID(var/pid, var/category) + switch(category) + if(CAT_NORMAL) + return product_records[pid] + if(CAT_HIDDEN) + return hidden_records[pid] + if(CAT_COIN) + return coin_records[pid] + else + warning("UNKNOWN PRODUCT: PID: [pid], CAT: [category] INSIDE [type]!") + return null + +/obj/machinery/vending/proc/TurnOff(var/ticks) //Turn off for a while. 10 ticks = 1 second + if(stat & (BROKEN|NOPOWER)) + return + + stat |= NOPOWER + src.update_vicon() + src.visible_message("[src] goes off!") + + spawn(ticks) + + if(stat & (NOPOWER)) //Make another check just in case something goes weird + stat &= ~NOPOWER + src.update_vicon() + +/obj/machinery/vending/proc/update_vicon() + if(stat & (BROKEN)) + src.icon_state = "[initial(icon_state)]-broken" + return + else if (stat & (NOPOWER)) + src.icon_state = "[initial(icon_state)]-off" + else + src.icon_state = "[initial(icon_state)]" + +/obj/machinery/vending/attack_hand(mob/living/user as mob) + if(user.a_intent == "hurt" && istype(user, /mob/living/carbon/)) //Will make another update later. Hulks will insta-break + user.delayNextAttack(10) + playsound(get_turf(src), 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it + src.shake(1, 3) //1 means x movement, 3 means intensity + src.health -= 4 + if (!Adjacent(user) && (M_TK in usr.mutations)) + to_chat(user, "You slam the [src] with your mind.") + src.visible_message("[src] dents slightly as if struck.") + else + user.visible_message( "[user] kicks the [src].", "You kick the [src].") + if(prob(70)) + user.apply_damage(rand(2,4), BRUTE, "r_leg") + + if(src.health <= 0) + stat |= BROKEN + src.update_vicon() + return + if(prob(2)) //Jackpot! + malfunction() + if(prob(2)) + src.TurnOff(600) //A whole minute + /*if(prob(1)) + to_chat(usr, "You fall down and break your leg!") + user.emote("scream",,, 1) + shake_camera(user, 2, 1)*/ + return + + if(stat & (BROKEN|NOPOWER)) + return + + if(seconds_electrified > 0) + if(shock(user, 100)) + return + else if (seconds_electrified) + seconds_electrified = 0 + + user.set_machine(src) + + var/vendorname = (src.name) //import the machine's name + + var/vertical = 400 + + if(src.currently_vending) + var/dat = "
                      [vendorname]


                      " //display the name, and added a horizontal rule + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\machinery\vending.dm:260: dat += "You have selected [currently_vending.product_name].
                      Please ensure your ID is in your ID holder or hand.

                      " + dat += {"You have selected [currently_vending.product_name].
                      Please ensure your ID is in your ID holder or hand.

                      + Pay | + Cancel"} + // END AUTOFIX + user << browse(dat, "window=vending") + onclose(user, "") + return + + var/dat = "
                      [vendorname]


                      " //display the name, and added a horizontal rule + 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)

                      " + + if (src.product_records.len == 0) + dat += "No products loaded!" + else + var/list/display_records = src.product_records.Copy() + + if(src.extended_inventory) + display_records += src.hidden_records + if(src.coin) + display_records += src.coin_records + + if(display_records.len > 12) + vertical = min(400 + (16 * (display_records.len - 12)),840) + + categories["default"] = list() + var/list/category_names = list() + for (var/datum/data/vending_product/R in product_records) + if(R.subcategory) + if(!(R.subcategory in category_names)) + category_names += R.subcategory + categories[R.subcategory] = list() + categories[R.subcategory] += R + else + categories["default"] += R + + for (var/datum/data/vending_product/R in categories["default"]) + dat += GetProductLine(R) + dat += "
                      " + + for(var/cat_name in category_names) + dat += {"  [cat_name]:
                      "} + for (var/datum/data/vending_product/R in categories[cat_name]) + dat += GetProductLine(R) + dat += "
                      " + + if(src.extended_inventory) + dat += {"  contraband:
                      "} + for (var/datum/data/vending_product/R in hidden_records) + dat += GetProductLine(R) + dat += "
                      " + + if(src.coin) + dat += {"  premium:
                      "} + for (var/datum/data/vending_product/R in coin_records) + dat += GetProductLine(R) + dat += "
                      " + + dat += "
                      " + + if(panel_open) + dat += wires() + + if(product_slogans != "") + dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle" + + user << browse(dat, "window=vending;size=400x[vertical]") + onclose(user, "vending") + return + +// returns the wire panel text +/obj/machinery/vending/proc/wires() + return wires.GetInteractWindow() + +/obj/machinery/vending/Topic(href, href_list) + if(..()) + usr << browse(null, "window=vending") + return 1 + + //testing("..(): [href]") + + var/free_vend = 0 + if(istype(usr,/mob/living/silicon)) + var/can_vend = 1 + if (href_list["vend"] && src.vend_ready && !currently_vending) + var/idx=text2num(href_list["vend"]) + var/cat=text2num(href_list["cat"]) + var/datum/data/vending_product/R = GetProductByID(idx,cat) + if(R.price) + can_vend = 0//all borgs can buy free items from vending machines + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = usr + if((R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ) || isMoMMI(R)) + can_vend = 1//only service borgs and MoMMI can buy costly items + if(!can_vend) + to_chat(usr, "The vending machine refuses to interface with you, as you are not in its target demographic!") + return + else + free_vend = 1//so that don't have to swipe their non-existant IDs + + if(href_list["remove_coin"]) + if(!coin) + to_chat(usr, "There is no coin in this machine.") + return + + coin.forceMove(get_turf(src)) + if(!usr.get_active_hand()) + usr.put_in_hands(coin) + to_chat(usr, "You remove the [coin] from the [src]") + coin = null + usr.set_machine(src) + + + if (href_list["vend"] && src.vend_ready && !currently_vending) + //testing("vend: [href]") + + if (!allowed(usr) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH + to_chat(usr, "Access denied.")//Unless emagged of course + + flick(src.icon_deny,src) + return + + var/idx=text2num(href_list["vend"]) + var/cat=text2num(href_list["cat"]) + + var/datum/data/vending_product/R = GetProductByID(idx,cat) + if (!R || !istype(R) || !R.product_path || R.amount <= 0) + message_admins("Invalid vend request by [formatJumpTo(src.loc)]: [href]") + return + + if(R.price == null || !R.price) + src.vend(R, usr) + else if(free_vend)//for MoMMI and Service Borgs + src.vend(R, usr) + else + src.currently_vending = R + src.updateUsrDialog() + + return + + else if (href_list["cancel_buying"]) + src.currently_vending = null + src.updateUsrDialog() + return + + else if (href_list["buy"]) + var/obj/item/weapon/card/card = usr.get_id_card() + if(card) + connect_account(usr, card) + src.updateUsrDialog() + return + + else if ((href_list["togglevoice"]) && (src.panel_open)) + src.shut_up = !src.shut_up + + src.add_fingerprint(usr) + src.updateUsrDialog() + + return + +/obj/machinery/vending/proc/add_item(var/obj/item/I) + var/found = FALSE + + for (var/datum/data/vending_product/D in product_records) + if (D.product_path == I.type) + D.amount++ + found = TRUE + break + + if (!found) + var/datum/data/vending_product/R = new() + R.product_path = I.type + R.amount = 1 + R.original_amount = 0 + R.price = 0 + R.display_color = pick("red", "blue", "green") + R.product_name = I.name + R.category = CAT_NORMAL + R.subcategory = I.vending_cat + + product_records.Add(R) + + qdel(I) + +/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user, by_voucher = 0) + if (!allowed(user) && !emagged && wires.IsIndexCut(VENDING_WIRE_IDSCAN)) //For SECURE VENDING MACHINES YEAH + to_chat(user, "Access denied.")//Unless emagged of course + + flick(src.icon_deny,src) + return + src.vend_ready = 0 //One thing at a time!! + + if (!by_voucher && (R in coin_records)) + if (isnull(coin)) + to_chat(user, "You need to insert a coin to get this item.") + return + + var/return_coin = 0 + if(istype(coin, /obj/item/weapon/coin/)) + var/obj/item/weapon/coin/real_coin = coin + if(real_coin.string_attached) + if(prob(50)) + to_chat(user, "You successfully pulled the coin out before the [src] could swallow it.") + return_coin = 1 + else + to_chat(user, "You weren't able to pull the coin out fast enough, the machine ate it, string and all.") + + if(return_coin) + user.put_in_hands(coin) + else + if (!isnull(coinbox)) + if (coinbox.can_be_inserted(coin, TRUE)) + coinbox.handle_item_insertion(coin, TRUE) + + coin = null + + R.amount-- + + if(((src.last_reply + (src.vend_delay + 200)) <= world.time) && src.vend_reply) + spawn(0) + src.speak(src.vend_reply) + src.last_reply = world.time + + use_power(5) + if (src.icon_vend) //Show the vending animation if needed + flick(src.icon_vend,src) + spawn(src.vend_delay) + new R.product_path(get_turf(src)) + src.vend_ready = 1 + return + + src.updateUsrDialog() + +/obj/machinery/vending/process() + if(stat & (BROKEN|NOPOWER)) + return + + if(!src.active) + return + + if(src.seconds_electrified > 0) + src.seconds_electrified-- + + //Pitch to the people! Really sell it! + if(((src.last_slogan + src.slogan_delay) <= world.time) && (src.slogan_list.len > 0) && (!src.shut_up) && prob(5)) + var/slogan = pick(src.slogan_list) + src.speak(slogan) + src.last_slogan = world.time + + if(src.shoot_inventory && prob(shoot_chance)) + src.throw_item() + + return + +/obj/machinery/vending/proc/speak(var/message) + if(stat & NOPOWER) + return + + if (!message) + return + say(message) + +/obj/machinery/vending/say_quote(text) + return "beeps, [text]" + +/obj/machinery/vending/power_change() + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + else + if( powered() ) + icon_state = initial(icon_state) + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + src.icon_state = "[initial(icon_state)]-off" + stat |= NOPOWER + +//Oh no we're malfunctioning! Dump out some product and break. +/obj/machinery/vending/proc/malfunction() + var/lost_inventory = rand(1,12) + while(lost_inventory>0) + throw_item() + lost_inventory-- + stat |= BROKEN + src.icon_state = "[initial(icon_state)]-broken" + return + +//Somebody cut an important wire and now we're following a new definition of "pitch." +/obj/machinery/vending/proc/throw_item() + + var/mob/living/target = locate() in view(7, src) + + if (!target) + return 0 + + var/obj/throw_item + var/list/throwable = product_records.Copy() + var/tries = 10 //Give up eventually + var/datum/data/vending_product/R + var/dump_path + + if (extended_inventory) + throwable += hidden_records + + while (tries) + R = pick(throwable) + dump_path = R.product_path + + if (R.amount <= 0 || !dump_path) + tries-- + continue + + R.amount-- + throw_item = new dump_path(src.loc) + + if (!throw_item) + return 0 + + spawn(0) + throw_item.throw_at(target, 16, 3) + + src.visible_message("[src] launches [throw_item.name] at [target.name]!") + return 1 + + return 0 + +/obj/machinery/vending/update_icon() + if(panel_open) + overlays += overlays_vending[1] + else + overlays -= overlays_vending[1] + + overlays -= overlays_vending[2] + if(emagged) + overlays += overlays_vending[2] + +/obj/machinery/vending/wirejack(var/mob/living/silicon/pai/P) + if(..()) + extended_inventory = !extended_inventory + scan_id = !scan_id + return 1 + return 0 + + +/* + * Vending machine types + */ + +/* + +/obj/machinery/vending/[vendors name here] // --vending machine template :) + name = "" + desc = "" + icon = '' + icon_state = "" + vend_delay = 15 + products = list() + contraband = list() + premium = list() + +*/ + +/* +/obj/machinery/vending/atmospherics //Commenting this out until someone ponies up some actual working, broken, and unpowered sprites - Quarxink + name = "Tank Vendor" + desc = "A vendor with a wide variety of masks and gas tanks." + icon = 'icons/obj/objects.dmi' + icon_state = "dispenser" + product_paths = "/obj/item/weapon/tank/oxygen;/obj/item/weapon/tank/plasma;/obj/item/weapon/tank/emergency_oxygen;/obj/item/weapon/tank/emergency_oxygen/engi;/obj/item/clothing/mask/breath" + product_amounts = "10;10;10;5;25" + vend_delay = 0 +*/ + +/obj/machinery/vending/boozeomat + name = "Booze-O-Mat" + desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one." + icon_state = "boozeomat" //////////////18 drink entities below, plus the glasses, in case someone wants to edit the number of bottles + icon_deny = "boozeomat-deny" + products = list( + /obj/item/weapon/reagent_containers/food/drinks/bottle/gin = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/tequila = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/rum = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/wine = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/cognac = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua = 5, + /obj/item/weapon/reagent_containers/food/drinks/beer = 6, + /obj/item/weapon/reagent_containers/food/drinks/ale = 6, + /obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice = 4, + /obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice = 4, + /obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice = 4, + /obj/item/weapon/reagent_containers/food/drinks/bottle/cream = 4, + /obj/item/weapon/reagent_containers/food/drinks/milk = 4, + /obj/item/weapon/reagent_containers/food/drinks/soymilk = 4, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic = 8, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 8, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater = 15, + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30, + /obj/item/weapon/reagent_containers/food/drinks/ice = 9, + ) + contraband = list( + /obj/item/weapon/reagent_containers/food/drinks/tea = 10, + /obj/item/weapon/reagent_containers/food/drinks/coffee = 10, + /obj/item/weapon/reagent_containers/food/drinks/mug = 10 + ) + product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?" + product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!" + req_access_txt = "25" + pack = /obj/structure/vendomatpack/boozeomat + +/obj/machinery/vending/assist + name = "Vendomat" + desc = "A generic vending machine." + icon_state = "generic" + products = list( + /obj/item/device/assembly/prox_sensor = 5, + /obj/item/device/assembly/igniter = 3, + /obj/item/device/assembly/signaler = 4, + /obj/item/weapon/wirecutters = 1, + /obj/item/weapon/cartridge/signal = 4, + ) + contraband = list( + /obj/item/device/flashlight = 5, + /obj/item/device/assembly/timer = 2, + ) + premium = list( + /obj/item/device/assembly_frame = 1, + ) + product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" + pack = /obj/structure/vendomatpack/assist + +/obj/machinery/vending/coffee + name = "Hot Drinks machine" + desc = "A vending machine which dispenses hot drinks." + product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies" + icon_state = "coffee" + icon_vend = "coffee-vend" + vend_delay = 34 + products = list( + /obj/item/weapon/reagent_containers/food/drinks/coffee = 25, + /obj/item/weapon/reagent_containers/food/drinks/tea = 25, + /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25, + ) + contraband = list( + /obj/item/weapon/reagent_containers/food/drinks/ice = 10, + ) + prices = list( + /obj/item/weapon/reagent_containers/food/drinks/coffee = 25, + /obj/item/weapon/reagent_containers/food/drinks/tea = 25, + /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25, + ) + + pack = /obj/structure/vendomatpack/coffee + + + +/obj/machinery/vending/snack + name = "Getmore Chocolate Corp" + desc = "A snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars" + product_slogans = "Try our new nougat bar!;Half the calories for double the price!;It's better then Dan's!" + product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!" + icon_state = "snack" + products = list( + /obj/item/weapon/reagent_containers/food/snacks/candy = 6, + /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 6, + /obj/item/weapon/reagent_containers/food/snacks/chips =6, + /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6, + /obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6, + /obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 6, + /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6, + /obj/item/weapon/reagent_containers/food/snacks/chococoin/wrapped = 2, + /obj/item/weapon/reagent_containers/food/snacks/bustanuts = 10, + ) + contraband = list( + /obj/item/weapon/reagent_containers/food/snacks/syndicake = 6, + ) + prices = list( + /obj/item/weapon/reagent_containers/food/snacks/candy = 13, + /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 15, + /obj/item/weapon/reagent_containers/food/snacks/chips = 30, + /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 40, + /obj/item/weapon/reagent_containers/food/snacks/no_raisin = 60, + /obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 12, + /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 40, + /obj/item/weapon/reagent_containers/food/snacks/chococoin/wrapped = 75, + /obj/item/weapon/reagent_containers/food/snacks/bustanuts = 0, + ) + + pack = /obj/structure/vendomatpack/snack + + +/obj/machinery/vending/cola + name = "Robust Softdrinks" + desc = "A softdrink vendor provided by Robust Industries, LLC." + icon_state = "Cola_Machine" + product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!;At least we aren't Dan!" + product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space." + products = list( + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 10, + ) + contraband = list( + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko = 5, + ) + prices = list( + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 20, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 20, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 20, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 20, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 20, + ) + + pack = /obj/structure/vendomatpack/cola + +//This one's from bay12 +/obj/machinery/vending/cart + name = "PTech" + desc = "Cartridges for PDAs" + product_slogans = "Carts to go!" + 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/captain = 3, + /obj/item/weapon/cartridge/quartermaster = 10, + ) + + pack = /obj/structure/vendomatpack/undefined + +/obj/machinery/vending/cigarette + name = "Cigarette machine" //OCD had to be uppercase to look nice with the new formating + desc = "If you want to get cancer, might as well do it in style" + product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!" + product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs." + icon_state = "cigs" + products = list( + /obj/item/weapon/storage/fancy/cigarettes = 10, + /obj/item/weapon/storage/fancy/matchbox = 10, + /obj/item/weapon/lighter/random = 4, + ) + contraband = list( + /obj/item/weapon/lighter/zippo = 4, + ) + premium = list( + /obj/item/weapon/storage/fancy/matchbox/strike_anywhere = 10, + /obj/item/clothing/mask/cigarette/cigar/havana = 2, + ) + prices = list( + /obj/item/weapon/storage/fancy/cigarettes = 20, + /obj/item/weapon/storage/fancy/matchbox = 25, + /obj/item/weapon/lighter/random = 25, + ) + + pack = /obj/structure/vendomatpack/cigarette + +/obj/machinery/vending/medical + name = "NanoMed Plus" + desc = "Medical drug dispenser." + icon_state = "med" + icon_deny = "med-deny" + product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!" + req_access_txt = "5" + products = list( + /obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4, + /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4, + /obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4, + /obj/item/weapon/reagent_containers/glass/bottle/toxin = 4, + /obj/item/weapon/reagent_containers/glass/bottle/charcoal = 4, + /obj/item/weapon/reagent_containers/syringe/antiviral = 4, + /obj/item/weapon/reagent_containers/syringe = 12, + /obj/item/device/healthanalyzer = 5, + /obj/item/weapon/reagent_containers/glass/beaker = 4, + /obj/item/weapon/reagent_containers/dropper = 2, + ) + contraband = list( + /obj/item/weapon/reagent_containers/pill/tox = 3, + /obj/item/weapon/reagent_containers/pill/stox = 4, + /obj/item/weapon/reagent_containers/pill/antitox = 6, + /obj/item/weapon/reagent_containers/blood/OMinus = 1, + /obj/item/weapon/storage/pill_bottle/random = 2, + ) + premium = list( + /obj/item/weapon/storage/pill_bottle/time_release = 2, + ) + + pack = /obj/structure/vendomatpack/medical + +//This one's from bay12 +/obj/machinery/vending/plasmaresearch + name = "Toximate 3000" + desc = "All the fine parts you need in one vending machine!" + products = list( + /obj/item/clothing/under/rank/scientist = 6, + /obj/item/clothing/suit/bio_suit = 6, + /obj/item/clothing/head/bio_hood = 6, + /obj/item/device/transfer_valve = 6, + /obj/item/device/assembly/timer = 6, + /obj/item/device/assembly/signaler = 6, + /obj/item/device/assembly/prox_sensor = 6, + /obj/item/device/assembly/igniter = 6, + ) + + pack = /obj/structure/vendomatpack/undefined + +/obj/machinery/vending/wallmed1 + name = "NanoMed" + desc = "Wall-mounted Medical Equipment dispenser." + product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?" + icon_state = "wallmed" + icon_deny = "wallmed-deny" + //req_access_txt = "5" + density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude + products = list( + /obj/item/stack/medical/bruise_pack = 2, + /obj/item/stack/medical/ointment = 2, + /obj/item/weapon/reagent_containers/syringe/inaprovaline = 4, + /obj/item/device/healthanalyzer = 1, + ) + contraband = list( + /obj/item/weapon/reagent_containers/syringe/antitoxin = 4, + /obj/item/weapon/reagent_containers/syringe/antiviral = 4, + /obj/item/weapon/reagent_containers/pill/tox = 1, + ) + + pack = /obj/structure/vendomatpack/medical//can be reloaded with NanoMed Plus packs + component_parts = 0 + +/obj/machinery/vending/wallmed2 + name = "NanoMed" + desc = "Wall-mounted Medical Equipment dispenser." + icon_state = "wallmed" + icon_deny = "wallmed-deny" + //req_access_txt = "5" + density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude + products = list( + /obj/item/weapon/reagent_containers/syringe/inaprovaline = 5, + /obj/item/weapon/reagent_containers/syringe/antitoxin = 3, + /obj/item/stack/medical/bruise_pack = 3, + /obj/item/stack/medical/ointment =3, + /obj/item/device/healthanalyzer = 3, + ) + contraband = list( + /obj/item/weapon/reagent_containers/pill/tox = 3, + ) + component_parts = 0 + + pack = /obj/structure/vendomatpack/medical//can be reloaded with NanoMed Plus packs + +////////WALL-MOUNTED NANOMED FRAME////// +/obj/machinery/vending/wallmed1/New(turf/loc) + ..() + component_parts = 0 + +/obj/machinery/vending/wallmed2/New(turf/loc) + ..() + component_parts = 0 + +/obj/machinery/vending/wallmed1/crowbarDestroy(mob/user) + user.visible_message( "[user] begins to pry out the NanoMed from the wall.", + "You begin to pry out the NanoMed from the wall...") + if(do_after(user, src, 40)) + user.visible_message( "[user] detaches the NanoMed from the wall.", + "You detach the NanoMed from the wall.") + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + new /obj/item/mounted/frame/wallmed(src.loc) + + for(var/obj/I in src) + qdel(I) + + new /obj/item/weapon/circuitboard/vendomat(src.loc) + new /obj/item/stack/cable_coil(loc,5) + + return 1 + return -1 + +/obj/machinery/vending/wallmed2/crowbarDestroy(mob/user) + user.visible_message( "[user] begins to pry out the NanoMed from the wall.", + "You begin to pry out the NanoMed from the wall...") + if(do_after(user, src, 40)) + user.visible_message( "[user] detaches the NanoMed from the wall.", + "You detach the NanoMed from the wall.") + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + new /obj/item/mounted/frame/wallmed(src.loc) + + for(var/obj/I in src) + qdel(I) + + new /obj/item/weapon/circuitboard/vendomat(src.loc) + new /obj/item/stack/cable_coil(loc,5) + + return 1 + return -1 + +/obj/machinery/wallmed_frame + name = "NanoMed frame" + desc = "Wall-mounted Medical Equipment dispenser." + icon = 'icons/obj/vending.dmi' + icon_state = "wallmed_frame0" + anchored = 1 + + var/on = 1 + + var/build = 0 // Build state + var/boardtype=/obj/item/weapon/circuitboard/vendomat + var/obj/item/weapon/circuitboard/_circuitboard + +/obj/machinery/wallmed_frame/New(turf/loc, var/ndir) + ..() + // offset 32 pixels in direction of dir + // this allows the NanoMed to be embedded in a wall, yet still inside an area + dir = ndir + pixel_x = (dir & 3)? 0 : (dir == 4 ? 30 : -30) + pixel_y = (dir & 3)? (dir ==1 ? 30 : -30) : 0 + +/obj/machinery/wallmed_frame/update_icon() + icon_state = "wallmed_frame[build]" + +/obj/machinery/wallmed_frame/attackby(var/obj/item/W as obj, var/mob/user as mob) + switch(build) + if(0) // Empty hull + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(usr, "You begin removing screws from \the [src] backplate...") + if(do_after(user, src, 50)) + to_chat(usr, "You unscrew \the [src] from the wall.") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + new /obj/item/mounted/frame/wallmed(get_turf(src)) + qdel(src) + return 1 + if(istype(W, /obj/item/weapon/circuitboard)) + var/obj/item/weapon/circuitboard/C=W + if(!(istype(C,/obj/item/weapon/circuitboard/vendomat))) + to_chat(user, "You cannot install this type of board into a NanoMed frame.") + return + to_chat(usr, "You begin to insert \the [C] into \the [src].") + if(do_after(user, src, 10)) + if(user.drop_item(C, src)) + to_chat(usr, "You secure \the [C]!") + _circuitboard=C + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + build++ + update_icon() + return 1 + if(1) // Circuitboard installed + if(istype(W, /obj/item/weapon/crowbar)) + to_chat(usr, "You begin to pry out \the [W] into \the [src].") + if(do_after(user, src, 10)) + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + build-- + update_icon() + var/obj/item/weapon/circuitboard/C + if(_circuitboard) + _circuitboard.loc=get_turf(src) + C=_circuitboard + _circuitboard=null + else + C=new boardtype(get_turf(src)) + user.visible_message(\ + "[user.name] has removed \the [C]!",\ + "You remove \the [C].") + return 1 + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C=W + to_chat(user, "You start adding cables to \the [src]...") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20) && C.amount >= 5) + C.use(5) + build++ + update_icon() + user.visible_message(\ + "[user.name] has added cables to \the [src]!",\ + "You add cables to \the [src].") + if(2) // Circuitboard installed, wired. + if(istype(W, /obj/item/weapon/wirecutters)) + to_chat(usr, "You begin to remove the wiring from \the [src].") + if(do_after(user, src, 50)) + new /obj/item/stack/cable_coil(loc,5) + user.visible_message(\ + "[user.name] cut the cables.",\ + "You cut the cables.") + build-- + update_icon() + return 1 + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(user, "You begin to complete \the [src]...") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 20)) + if(!_circuitboard) + _circuitboard=new boardtype(src) + build++ + update_icon() + user.visible_message(\ + "[user.name] has finished \the [src]!",\ + "You finish \the [src].") + return 1 + if(3) // Waiting for a recharge pack + if(istype(W, /obj/item/weapon/screwdriver)) + to_chat(user, "You begin to unscrew \the [src]...") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 30)) + build-- + update_icon() + return 1 + ..() + +/obj/machinery/wallmed_frame/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if(build==3) + if(istype(O,/obj/structure/vendomatpack)) + if(istype(O,/obj/structure/vendomatpack/medical)) + to_chat(user, "You start refilling the vending machine with the recharge pack's materials.") + var/user_loc = user.loc + var/pack_loc = O.loc + var/self_loc = src.loc + sleep(30) + if(!user || !O || !src) + return + if (user.loc == user_loc && O.loc == pack_loc && anchored && self_loc == src.loc && !(user.stat) && (!user.stunned && !user.weakened && !user.paralysis && !user.lying)) + to_chat(user, "\icon[src] You finish refilling the vending machine.") + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + var/obj/machinery/vending/wallmed1/newnanomed = new /obj/machinery/vending/wallmed1(src.loc) + newnanomed.name = "Emergency NanoMed" + newnanomed.pixel_x = pixel_x + newnanomed.pixel_y = pixel_y + var/obj/item/emptyvendomatpack/emptypack = new /obj/item/emptyvendomatpack(O.loc) + emptypack.icon_state = O.icon_state + emptypack.overlays += image('icons/obj/vending_pack.dmi',"emptypack") + qdel(O) + contents = 0 + qdel(src) + else + to_chat(user, "This recharge pack isn't meant for this kind of vending machines.") + +//////////////////////////////////////// + + +/obj/machinery/vending/security + name = "SecTech" + desc = "A security equipment vendor" + product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?" + icon_state = "sec" + icon_deny = "sec-deny" + req_access_txt = "1" + products = list( + /obj/item/weapon/handcuffs = 8, + /obj/item/weapon/grenade/flashbang = 4, + /obj/item/device/flash = 5, + /obj/item/weapon/reagent_containers/food/snacks/donut/normal = 12, + /obj/item/weapon/storage/box/evidence = 6, + /obj/item/weapon/legcuffs/bolas = 2, + ) + contraband = list( + /obj/item/clothing/glasses/sunglasses = 2, + /obj/item/weapon/storage/fancy/donut_box = 2, + ) + + pack = /obj/structure/vendomatpack/security + +/obj/machinery/vending/hydronutrients + name = "NutriMax" + desc = "A plant nutrients vendor" + product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!" + 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/weapon/reagent_containers/glass/fertilizer/ez = 35, + /obj/item/weapon/reagent_containers/glass/fertilizer/l4z = 25, + /obj/item/weapon/reagent_containers/glass/fertilizer/rh = 15, + /obj/item/weapon/plantspray/pests = 20, + /obj/item/weapon/reagent_containers/syringe = 5, + /obj/item/weapon/reagent_containers/dropper = 2, + /obj/item/weapon/storage/bag/plants = 5, + ) + contraband = list( + /obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10, + /obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5, + ) + + pack = /obj/structure/vendomatpack/hydronutrients + +/obj/machinery/vending/hydroseeds + name = "MegaSeed Servitor" + desc = "When you need seeds fast!" + product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!" + product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!" + icon_state = "seeds" + 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/dionanode = 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/sugarcaneseed = 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/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, + /obj/item/seeds/cinnamomum = 3, + )//,/obj/item/seeds/synthmeatseed = 3) + contraband = list( + /obj/item/seeds/amanitamycelium = 2, + /obj/item/seeds/glowshroom = 2, + /obj/item/seeds/libertymycelium = 2, + /obj/item/seeds/nettleseed = 2, + /obj/item/seeds/plumpmycelium = 2, + /obj/item/seeds/reishimycelium = 2, + /obj/item/seeds/harebell = 3, + )//,/obj/item/seeds/synthbuttseed = 3) + premium = list( + /obj/item/toy/waterflower = 1, + ) + + allowed_inputs = list( + /obj/item/seeds, + ) + pack = /obj/structure/vendomatpack/hydroseeds + +/obj/machinery/vending/magivend + name = "MagiVend" + desc = "A magic vending machine." + icon_state = "MagiVend" + product_slogans = "Sling spells the proper way with MagiVend!;Be your own Houdini! Use MagiVend!" + vend_delay = 15 + vend_reply = "Have an enchanted evening!" + product_ads = "FJKLFJSD;AJKFLBJAKL;1234 LOONIES LOL!;>MFW;Kill them fuckers!;GET DAT FUKKEN DISK;HONK!;EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!" + products = list( + /obj/item/clothing/head/wizard = 1, + /obj/item/clothing/suit/wizrobe = 1, + /obj/item/clothing/head/wizard/red = 1, + /obj/item/clothing/suit/wizrobe/red = 1, + /obj/item/clothing/head/wizard/clown = 1, + /obj/item/clothing/suit/wizrobe/clown = 1, + /obj/item/clothing/mask/gas/clown_hat/wiz = 1, + /obj/item/clothing/suit/wizrobe/magician = 1, + /obj/item/clothing/head/wizard/magician = 1, + /obj/item/clothing/shoes/sandal/marisa/leather = 1, + /obj/item/clothing/shoes/sandal = 1, + /obj/item/weapon/staff = 2, + /obj/item/weapon/storage/bag/wiz_cards/full = 1, + ) + contraband = list( + /obj/item/weapon/reagent_containers/glass/bottle/wizarditis = 1, + ) //No one can get to the machine to hack it anyways; for the lulz - Microwave + + pack = /obj/structure/vendomatpack/magivend //Who's laughing now? wizarditis doesn't do shit anyway. - Deity Link + +/obj/machinery/vending/dinnerware + name = "Dinnerware" + desc = "A kitchen and restaurant equipment vendor" + product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..." + icon_state = "dinnerware" + products = list( + /obj/item/weapon/tray = 8, + /obj/item/weapon/kitchen/utensil/fork = 6, + /obj/item/weapon/kitchen/utensil/knife/large = 3, + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8, + /obj/item/clothing/suit/chef/classic = 2, + /obj/item/trash/bowl = 20, + /obj/item/weapon/reagent_containers/food/condiment/peppermill = 5, + /obj/item/weapon/reagent_containers/food/condiment/saltshaker = 5, + /obj/item/weapon/reagent_containers/food/condiment/vinegar = 5, + /obj/item/weapon/storage/bag/food = 5 + ) + contraband = list( + /obj/item/weapon/kitchen/utensil/spoon = 2, + /obj/item/weapon/kitchen/utensil/knife = 2, + /obj/item/weapon/kitchen/rollingpin = 2, + /obj/item/weapon/kitchen/utensil/knife/large/butch = 2, + ) + premium = list( + /obj/item/weapon/reagent_containers/dropper/baster = 1) + + pack = /obj/structure/vendomatpack/dinnerware + +/obj/machinery/vending/sovietsoda + name = "BODA" + desc = "Old sweet water vending machine" + icon_state = "sovietsoda" + product_slogans = "BODA: We sell drink.;BODA: Drink today.;BODA: We're better then Comrade Dan." + product_ads = "For Tsar and Country.;Have you fulfilled your nutrition quota today?;Very nice!;We are simple people, for this is all we eat.;If there is a person, there is a problem. If there is no person, then there is no problem." + products = list( + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda = 30, + ) + contraband = list( + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola = 20, + ) + + pack = /obj/structure/vendomatpack/sovietsoda + +/obj/machinery/vending/tool + name = "YouTool" + desc = "Tools for tools." + icon_state = "tool" + icon_deny = "tool-deny" + //req_access_txt = "12" //Maintenance access + products = list( + /obj/item/stack/cable_coil/random = 10, + /obj/item/weapon/crowbar = 5, + /obj/item/weapon/weldingtool = 3, + /obj/item/weapon/wirecutters = 5, + /obj/item/weapon/wrench = 5, + /obj/item/device/analyzer = 5, + /obj/item/device/t_scanner = 5, + /obj/item/weapon/screwdriver = 5, + /obj/item/weapon/solder = 3, + /obj/item/device/silicate_sprayer = 2 + ) + contraband = list( + /obj/item/weapon/weldingtool/hugetank = 2, + /obj/item/clothing/gloves/fyellow = 2, + ) + premium = list( + /obj/item/clothing/gloves/yellow = 1, + ) + + pack = /obj/structure/vendomatpack/tool + +/obj/machinery/vending/engivend + name = "Engi-Vend" + desc = "Spare tool vending. What? Did you expect some witty description?" + icon_state = "engivend" + icon_deny = "engivend-deny" + req_access_txt = "11" //Engineering Equipment access + products = list( + /obj/item/clothing/glasses/meson = 2, + /obj/item/device/multitool = 4, + /obj/item/weapon/circuitboard/airlock = 10, + /obj/item/weapon/circuitboard/power_control = 10, + /obj/item/weapon/circuitboard/air_alarm = 10, + /obj/item/weapon/circuitboard/fire_alarm = 10, + /obj/item/weapon/intercom_electronics = 10, + /obj/item/weapon/cell/high = 10, + /obj/item/weapon/reagent_containers/glass/fuelcan = 5, + ) + contraband = list( + /obj/item/weapon/cell/potato = 3, + ) + premium = list( + /obj/item/weapon/storage/belt/utility = 3, + ) + + pack = /obj/structure/vendomatpack/engivend + +//This one's from bay12 +/obj/machinery/vending/engineering + name = "Robco Tool Maker" + desc = "Everything you need for do-it-yourself station repair." + icon_state = "engi" + icon_deny = "engi-deny" + req_access_txt = "11" + products = list( + /obj/item/clothing/under/rank/engineer = 4, + /obj/item/clothing/under/rank/atmospheric_technician = 4, + /obj/item/clothing/under/rank/maintenance_tech/ = 4, + /obj/item/clothing/under/rank/engine_tech = 4, + /obj/item/clothing/under/rank/electrician = 4, + /obj/item/clothing/shoes/orange = 4, + /obj/item/clothing/head/hardhat = 4, + /obj/item/clothing/head/hardhat/orange = 4, + /obj/item/clothing/head/hardhat/red = 4, + /obj/item/clothing/head/hardhat/white = 4, + /obj/item/clothing/head/hardhat/dblue = 4, + /obj/item/weapon/storage/belt/utility = 4, + /obj/item/clothing/glasses/meson = 4, + /obj/item/clothing/gloves/yellow = 4, + /obj/item/weapon/screwdriver = 12, + /obj/item/weapon/crowbar = 12, + /obj/item/weapon/wirecutters = 12, + /obj/item/device/multitool = 12, + /obj/item/weapon/wrench = 12, + /obj/item/device/t_scanner = 12, + /obj/item/stack/cable_coil = 8, + /obj/item/weapon/cell = 8, + /obj/item/weapon/weldingtool = 8, + /obj/item/clothing/head/welding = 8, + /obj/item/weapon/light/tube = 10, + /obj/item/clothing/suit/fire = 4, + /obj/item/weapon/stock_parts/scanning_module = 5, + /obj/item/weapon/stock_parts/micro_laser = 5, + /obj/item/weapon/stock_parts/matter_bin = 5, + /obj/item/weapon/stock_parts/manipulator = 5, + /obj/item/weapon/stock_parts/console_screen = 5, + ) + contraband = list( + /obj/item/weapon/wrench/socket = 1, + /obj/item/weapon/extinguisher/foam = 1, + /obj/item/device/device_analyser = 2, + ) + premium = list( + /obj/item/clothing/under/rank/chief_engineer = 2, + /obj/item/weapon/storage/belt = 2, + ) //belt is the best belt in the game. + // There was an incorrect entry (cablecoil/power). I improvised to cablecoil/heavyduty. + // Another invalid entry, /obj/item/weapon/circuitry. I don't even know what that would translate to, removed it. + // The original products list wasn't finished. The ones without given quantities became quantity 5. -Sayu + + pack = /obj/structure/vendomatpack/undefined + +//This one's from bay12 +/obj/machinery/vending/robotics + name = "Robotech Deluxe" + desc = "All the tools you need to create your own robot army." + icon_state = "robotics" + icon_deny = "robotics-deny" + req_access_txt = "29" + products = list( + /obj/item/clothing/suit/storage/labcoat = 4, + /obj/item/clothing/under/rank/roboticist = 4, + /obj/item/stack/cable_coil = 4, + /obj/item/device/flash = 4, + /obj/item/weapon/cell/high = 12, + /obj/item/device/assembly/prox_sensor = 3, + /obj/item/device/assembly/signaler = 3, + /obj/item/device/healthanalyzer = 3, + /obj/item/weapon/scalpel = 2, + /obj/item/weapon/circular_saw = 2, + /obj/item/weapon/tank/anesthetic = 2, + /obj/item/clothing/mask/breath/medical = 5, + /obj/item/weapon/screwdriver = 5, + /obj/item/weapon/crowbar = 5, + ) + //everything after the power cell had no amounts, I improvised. -Sayu + + pack = /obj/structure/vendomatpack/undefined + +/obj/machinery/vending/autodrobe + name = "\improper AutoDrobe" + desc = "A vending machine for costumes." + icon_state = "theater" + icon_deny = "theater-deny" + req_access = list(access_theatre) + product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!" + vend_delay = 15 + vend_reply = "Thank you for using AutoDrobe!" + products = list( + /obj/item/clothing/suit/chickensuit = 3, + /obj/item/clothing/head/chicken = 3, + /obj/item/clothing/suit/monkeysuit = 3, + /obj/item/clothing/mask/gas/monkeymask = 3, + /obj/item/clothing/suit/xenos = 3, + /obj/item/clothing/head/xenos = 3, + /obj/item/clothing/under/gladiator = 3, + /obj/item/clothing/head/helmet/gladiator = 3, + /obj/item/clothing/under/gimmick/rank/captain/suit = 3, + /obj/item/clothing/head/flatcap = 3, + /obj/item/clothing/glasses/gglasses = 3, + /obj/item/clothing/shoes/jackboots = 3, + /obj/item/clothing/under/schoolgirl = 3, + /obj/item/clothing/shoes/kneesocks = 3, + /obj/item/clothing/head/kitty = 3, + /obj/item/clothing/under/blackskirt = 3, + /obj/item/clothing/head/beret = 3, + /obj/item/clothing/suit/hastur = 3, + /obj/item/clothing/head/hasturhood = 3, + /obj/item/clothing/suit/wcoat = 3, + /obj/item/clothing/under/suit_jacket = 3, + /obj/item/clothing/head/that = 3, + /obj/item/clothing/head/cueball = 3, + /obj/item/clothing/under/scratch = 3, + /obj/item/clothing/under/kilt = 3, + /obj/item/clothing/head/beret = 3, + /obj/item/clothing/suit/wcoat = 3, + /obj/item/clothing/glasses/monocle =3, + /obj/item/clothing/head/bowlerhat = 3, + /obj/item/weapon/cane = 3, + /obj/item/clothing/under/sl_suit = 3, + /obj/item/clothing/mask/fakemoustache = 3, + /obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 3, + /obj/item/clothing/head/plaguedoctorhat = 3, + /obj/item/clothing/mask/gas/plaguedoctor = 3, + /obj/item/clothing/under/owl = 3, + /obj/item/clothing/mask/gas/owl_mask = 3, + /obj/item/clothing/suit/apron = 3, + /obj/item/clothing/under/waiter = 3, + /obj/item/clothing/under/pirate = 3, + /obj/item/clothing/suit/pirate = 3, + /obj/item/clothing/head/pirate = 3, + /obj/item/clothing/head/bandana = 3, + /obj/item/clothing/head/bandana = 3, + /obj/item/clothing/under/soviet = 3, + /obj/item/clothing/head/ushanka = 3, + /obj/item/clothing/suit/imperium_monk = 3, + /obj/item/clothing/mask/gas/cyborg = 3, + /obj/item/clothing/suit/holidaypriest = 3, + /obj/item/clothing/head/wizard/marisa/fake = 3, + /obj/item/clothing/suit/wizrobe/marisa/fake = 3, + /obj/item/clothing/under/sundress = 3, + /obj/item/clothing/head/witchwig = 3, + /obj/item/weapon/staff/broom = 3, + /obj/item/clothing/suit/wizrobe/fake = 3, + /obj/item/clothing/head/wizard/fake = 3, + /obj/item/weapon/staff = 3, + /obj/item/clothing/mask/gas/sexyclown = 3, + /obj/item/clothing/under/sexyclown = 3, + /obj/item/clothing/mask/gas/sexymime = 3, + /obj/item/clothing/under/sexymime = 3, + /obj/item/clothing/suit/apron/overalls = 3, + /obj/item/clothing/head/rabbitears = 3, + /obj/item/clothing/head/lordadmiralhat = 3, + /obj/item/clothing/suit/lordadmiral = 3, + /obj/item/clothing/suit/doshjacket = 3, + /obj/item/clothing/under/jester = 3, + /obj/item/clothing/head/jesterhat = 3, + /obj/item/clothing/shoes/jestershoes = 3, + /obj/item/clothing/suit/kefkarobe = 3, + /obj/item/clothing/head/helmet/aviatorhelmet = 3, + /obj/item/clothing/shoes/aviatorboots = 3, + /obj/item/clothing/under/aviatoruniform = 3, + /obj/item/clothing/head/libertyhat = 3, + /obj/item/clothing/suit/libertycoat = 3, + /obj/item/clothing/under/libertyshirt = 3, + /obj/item/clothing/shoes/libertyshoes = 3, + /obj/item/clothing/head/helmet/megahelmet = 3, + /obj/item/clothing/under/mega = 3, + /obj/item/clothing/gloves/megagloves = 3, + /obj/item/clothing/shoes/megaboots =3, + /obj/item/clothing/head/helmet/protohelmet = 3, + /obj/item/clothing/under/proto =3, + /obj/item/clothing/gloves/protogloves =3, + /obj/item/clothing/shoes/protoboots =3, + /obj/item/clothing/under/roll = 3, + /obj/item/clothing/head/maidhat =3, + /obj/item/clothing/under/maid = 3, + /obj/item/clothing/suit/maidapron = 3, + /obj/item/clothing/head/mitre = 3, + /obj/item/clothing/under/clownpiece = 3, + /obj/item/clothing/suit/clownpiece = 3, + /obj/item/clothing/head/clownpiece = 3, + /obj/item/clothing/head/cowboy = 3, + ) //Pretty much everything that had a chance to spawn. + contraband = list( + /obj/item/clothing/suit/cardborg = 3, + /obj/item/clothing/head/cardborg = 3, + /obj/item/clothing/suit/judgerobe = 3, + /obj/item/clothing/head/powdered_wig = 3, + /obj/item/toy/gun = 3, + ) + premium = list( + /obj/item/clothing/suit/hgpirate = 3, + /obj/item/clothing/head/hgpiratecap = 3, + /obj/item/clothing/head/helmet/roman = 3, + /obj/item/clothing/head/helmet/roman/legionaire = 3, + /obj/item/clothing/under/roman = 3, + /obj/item/clothing/shoes/roman = 3, + /obj/item/weapon/shield/riot/roman = 3, + /obj/item/clothing/under/stilsuit = 3, + /obj/item/clothing/head/helmet/breakhelmet = 3, + /obj/item/clothing/head/helmet/joehelmet = 3, + /obj/item/clothing/under/joe = 3, + /obj/item/clothing/gloves/joegloves = 3, + /obj/item/clothing/shoes/joeboots =3, + /obj/item/weapon/shield/riot/proto = 3, + /obj/item/weapon/shield/riot/joe = 3, + /obj/item/clothing/under/darkholme = 3, + /obj/item/clothing/suit/wizrobe/magician/fake = 3, + /obj/item/clothing/head/wizard/magician = 3, + ) + + pack = /obj/structure/vendomatpack/autodrobe + +/obj/machinery/vending/hatdispenser + name = "Hatlord 9000" + desc = "It doesn't seem the slightist bit unusual. This frustrates you immensly." + icon_state = "hats" + vend_reply = "Take care now!" + product_ads = "Buy some hats!;A bare head is absoloutly ASKING for a robusting!" + product_slogans = "Warning, not all hats are dog/monkey compatable. Apply forcefully with care.;Apply directly to the forehead.;Who doesn't love spending cash on hats?!;From the people that brought you collectable hat crates, Hatlord!" + products = list( + /obj/item/clothing/head/bowlerhat = 10, + /obj/item/clothing/head/beaverhat = 10, + /obj/item/clothing/head/boaterhat = 10, + /obj/item/clothing/head/fedora = 10, + /obj/item/clothing/head/fez = 10, + /obj/item/clothing/head/soft/blue = 10, + /obj/item/clothing/head/soft/green = 10, + /obj/item/clothing/head/soft/grey = 10, + /obj/item/clothing/head/soft/orange = 10, + /obj/item/clothing/head/soft/purple = 10, + /obj/item/clothing/head/soft/red = 10, + /obj/item/clothing/head/soft/yellow = 10, + ) + contraband = list( + /obj/item/clothing/head/bearpelt = 5, + ) + premium = list( + /obj/item/clothing/head/soft/rainbow = 1, + ) + + pack = /obj/structure/vendomatpack/hatdispenser + +/obj/machinery/vending/suitdispenser + name = "Suitlord 9000" + desc = "You wonder for a moment why all of your shirts and pants come conjoined. This hurts your head and you stop thinking about it." + icon_state = "suits" + vend_reply = "Come again!" + product_ads = "Skinny? Looking for some clothes? Suitlord is the machine for you!;BUY MY PRODUCT!" + product_slogans = "Pre-Ironed, Pre-Washed, Pre-Wor-*BZZT*;Blood of your enemies washes right out!;Who are YOU wearing?;Look dapper! Look like an idiot!;Don't carry your size? How about you shave off some pounds you fat lazy- *BZZT*" + products = list( + /obj/item/clothing/under/color/black = 10, + /obj/item/clothing/under/color/blue = 10, + /obj/item/clothing/under/color/green = 10, + /obj/item/clothing/under/color/grey = 10, + /obj/item/clothing/under/color/pink = 10, + /obj/item/clothing/under/color/red = 10, + /obj/item/clothing/under/color/white = 10, + /obj/item/clothing/under/color/yellow = 10, + /obj/item/clothing/under/lightblue = 10, + /obj/item/clothing/under/aqua = 10, + /obj/item/clothing/under/purple = 10, + /obj/item/clothing/under/lightgreen = 10, + /obj/item/clothing/under/lightblue = 10, + /obj/item/clothing/under/lightbrown = 10, + /obj/item/clothing/under/brown = 10, + /obj/item/clothing/under/yellowgreen = 10, + /obj/item/clothing/under/darkblue = 10, + /obj/item/clothing/under/lightred = 10, + /obj/item/clothing/under/darkred = 10, + /obj/item/clothing/under/bluepants = 10, + /obj/item/clothing/under/blackpants = 10, + /obj/item/clothing/under/redpants = 10, + /obj/item/clothing/under/greypants = 10, + ) + contraband = list( + /obj/item/clothing/under/syndicate/tacticool = 5, + /obj/item/clothing/under/color/orange = 5, + /obj/item/clothing/under/psyche = 5, + ) + premium = list( + /obj/item/clothing/under/rainbow = 1, + ) + + pack = /obj/structure/vendomatpack/suitdispenser + +//THIS IS WHERE THE FEET LIVE, GIT YE SOME +/obj/machinery/vending/shoedispenser + name = "Shoelord 9000" + desc = "Wow, hatlord looked fancy, suitlord looked streamlined, and this is just normal. The guy who designed these must be an idiot." + icon_state = "shoes" + vend_reply = "Enjoy your pair!" + product_ads = "Dont be a hobbit: Choose shoelord.;Shoes snatched? Get on it with shoelord." + product_slogans = "Put your foot down!;One size fits all!;IM WALKING ON SUNSHINE!;No hobbits allowed.;NO PLEASE WILLY, DONT HURT ME- *BZZT*" + products = list( + /obj/item/clothing/shoes/black = 10, + /obj/item/clothing/shoes/brown = 10, + /obj/item/clothing/shoes/blue = 10, + /obj/item/clothing/shoes/green = 10, + /obj/item/clothing/shoes/yellow = 10, + /obj/item/clothing/shoes/purple = 10, + /obj/item/clothing/shoes/red = 10, + /obj/item/clothing/shoes/white = 10, + ) + contraband = list( + /obj/item/clothing/shoes/jackboots = 5, + /obj/item/clothing/shoes/orange = 5, + ) + premium = list( + /obj/item/clothing/shoes/rainbow = 1, + ) + + pack = /obj/structure/vendomatpack/shoedispenser + +//HEIL ADMINBUS +/obj/machinery/vending/nazivend + name = "Nazivend" + desc = "Remember the gorrilions lost." + icon_state = "nazi" + vend_reply = "SIEG HEIL!" + product_ads = "BESTRAFEN die Juden.;BESTRAFEN die Alliierten." + product_slogans = "Das Vierte Reich wird zuruckkehren!;ENTFERNEN JUDEN!;Billiger als die Juden jemals geben!;Rader auf dem adminbus geht rund und rund.;Warten Sie, warum wir wieder hassen Juden?- *BZZT*" + products = list( + /obj/item/clothing/head/stalhelm = 20, + /obj/item/clothing/head/panzer = 20, + /obj/item/clothing/suit/soldiercoat = 20, + /obj/item/clothing/under/soldieruniform = 20, + /obj/item/clothing/shoes/jackboots = 20, + ) + contraband = list( + /obj/item/clothing/head/naziofficer = 10, + /obj/item/clothing/suit/officercoat = 10, + /obj/item/clothing/under/officeruniform = 10, + ) + + pack = /obj/structure/vendomatpack/nazivend + + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | EMAGGABLE + +/obj/machinery/vending/nazivend/emag(mob/user) + if(!emagged) + to_chat(user, "As you slide the emag on the machine, you can hear something unlocking inside, and the machine starts emitting an evil glow.") + message_admins("[key_name_admin(user)] unlocked a Nazivend's DANGERMODE") + contraband[/obj/item/clothing/head/helmet/space/rig/nazi] = 3 + contraband[/obj/item/clothing/suit/space/rig/nazi] = 3 + contraband[/obj/item/weapon/gun/energy/plasma/MP40k] = 4 + src.build_inventory(contraband, 1) + emagged = 1 + overlays = 0 + var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) + overlays_vending[2] = dangerlay + update_icon() + return 1 + return + +//NaziVend++ +/obj/machinery/vending/nazivend/DANGERMODE + products = list( + /obj/item/clothing/head/stalhelm = 20, + /obj/item/clothing/head/panzer = 20, + /obj/item/clothing/suit/soldiercoat = 20, + /obj/item/clothing/under/soldieruniform = 20, + /obj/item/clothing/shoes/jackboots = 20, + ) + contraband = list( + /obj/item/clothing/head/naziofficer = 10, + /obj/item/clothing/suit/officercoat = 10, + /obj/item/clothing/under/officeruniform = 10, + /obj/item/clothing/head/helmet/space/rig/nazi = 3, + /obj/item/clothing/suit/space/rig/nazi = 3, + /obj/item/weapon/gun/energy/plasma/MP40k = 4, + ) + + pack = /obj/structure/vendomatpack/nazivend //can be reloaded with the same packs as the regular one + +/obj/machinery/vending/nazivend/DANGERMODE/New() + ..() + emagged = 1 + overlays = 0 + var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) + overlays_vending[2] = dangerlay + update_icon() + +//MOTHERBUSLAND +/obj/machinery/vending/sovietvend + name = "KomradeVendtink" + desc = "Rodina-mat' zovyot!" + icon_state = "soviet" + vend_reply = "The fascist and capitalist svin'ya shall fall komrade!" + product_ads = "Quality worth waiting in line for!; Get Hammer and Sickled!; Sosvietsky soyuz above all!; With capitalist pigsky, you would have paid a fortunetink!" + product_slogans = "Craftink in Motherland herself!" + products = list( + /obj/item/clothing/under/soviet = 20, + /obj/item/clothing/head/ushanka = 20, + /obj/item/clothing/shoes/jackboots = 20, + /obj/item/clothing/head/squatter_hat = 20, + /obj/item/clothing/under/squatter_outfit = 20, + /obj/item/clothing/under/russobluecamooutfit = 20, + /obj/item/clothing/head/russobluecamohat = 20, + ) + contraband = list( + /obj/item/clothing/under/syndicate/tacticool = 4, + /obj/item/clothing/mask/balaclava = 4, + /obj/item/clothing/suit/russofurcoat = 4, + /obj/item/clothing/head/russofurhat = 4, + ) + + pack = /obj/structure/vendomatpack/sovietvend + + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | EMAGGABLE + + +/obj/machinery/vending/sovietvend/emag(mob/user) + if(!emagged) + to_chat(user, "As you slide the emag on the machine, you can hear something unlocking inside, and the machine starts emitting an evil glow.") + message_admins("[key_name_admin(user)] unlocked a Sovietvend's DANGERMODE") + contraband[/obj/item/clothing/head/helmet/space/rig/soviet] = 3 + contraband[/obj/item/clothing/suit/space/rig/soviet] = 3 + contraband[/obj/item/weapon/gun/energy/laser/LaserAK] = 4 + src.build_inventory(contraband, 1) + emagged = 1 + overlays = 0 + var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) + overlays_vending[2] = dangerlay + update_icon() + return 1 + return + +//SovietVend++ +/obj/machinery/vending/sovietvend/DANGERMODE + products = list( + /obj/item/clothing/under/soviet = 20, + /obj/item/clothing/head/ushanka = 20, + /obj/item/clothing/shoes/jackboots = 20, + /obj/item/clothing/head/squatter_hat = 20, + /obj/item/clothing/under/squatter_outfit = 20, + /obj/item/clothing/under/russobluecamooutfit = 20, + /obj/item/clothing/head/russobluecamohat = 20, + ) + contraband = list( + /obj/item/clothing/under/syndicate/tacticool = 4, + /obj/item/clothing/mask/balaclava = 4, + /obj/item/clothing/suit/russofurcoat = 4, + /obj/item/clothing/head/russofurhat = 4, + /obj/item/clothing/head/helmet/space/rig/soviet = 3, + /obj/item/clothing/suit/space/rig/soviet = 3, + /obj/item/weapon/gun/energy/laser/LaserAK = 4, + ) + + pack = /obj/structure/vendomatpack/sovietvend//can be reloaded with the same packs as the regular one + +/obj/machinery/vending/sovietvend/DANGERMODE/New() + ..() + emagged = 1 + overlays = 0 + var/image/dangerlay = image(icon,"[icon_state]-dangermode", LIGHTING_LAYER + 1) + overlays_vending[2] = dangerlay + update_icon() + +/obj/machinery/vending/discount + name = "Discount Dan's" + desc = "A snack machine owned by the infamous 'Discount Dan' franchise." + product_slogans = "Discount Dan, he's the man!;There 'aint nothing better in this world then a bite of mystery.;Don't listen to those other machines, buy my product!;Quantity over Quality!;Don't listen to those eggheads at the CDC, buy now!;Discount Dan's: We're good for you! Nope, couldn't say it with a straight face.;Discount Dan's: Only the best quality produ-*BZZT*" + product_ads = "Discount Dan(tm) is not responsible for any damages caused by misuse of his product." + vend_reply = "No refunds." + icon_state = "discount" + products = list( + /obj/item/weapon/reagent_containers/food/snacks/discountchocolate = 6, + /obj/item/weapon/reagent_containers/food/snacks/danitos =6, + /obj/item/weapon/reagent_containers/food/snacks/discountburger = 6, + /obj/item/weapon/reagent_containers/food/drinks/discount_ramen = 6, + /obj/item/weapon/reagent_containers/food/snacks/discountburrito = 6, + /obj/item/weapon/reagent_containers/food/snacks/pie/discount = 6, + ) + contraband = list( + /obj/item/weapon/reagent_containers/pill/antitox = 10 + ) + prices = list( + /obj/item/weapon/reagent_containers/food/snacks/discountchocolate = 8, + /obj/item/weapon/reagent_containers/food/snacks/danitos = 10, + /obj/item/weapon/reagent_containers/food/snacks/discountburger = 10, + /obj/item/weapon/reagent_containers/food/drinks/discount_ramen = 2, + /obj/item/weapon/reagent_containers/food/snacks/discountburrito = 10, + /obj/item/weapon/reagent_containers/food/snacks/pie/discount = 8, + /obj/item/weapon/reagent_containers/pill/antitox = 10 + ) + + pack = /obj/structure/vendomatpack/discount + +/obj/machinery/vending/groans + name = "Groans Soda" + desc = "A soda machine owned by the infamous 'Groans' franchise." + product_slogans = "Groans: Drink up!;Sponsored by Discount Dan!;Take a sip!;Just one sip, do it!" + product_ads = "Try our new 'Double Dan' flavor!" + vend_reply = "No refunds." + icon_state = "groans" + products = list( + /obj/item/weapon/reagent_containers/food/drinks/groans = 10, + /obj/item/weapon/reagent_containers/food/drinks/filk = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink = 10, + ) + prices = list( + /obj/item/weapon/reagent_containers/food/drinks/groans = 20, + /obj/item/weapon/reagent_containers/food/drinks/filk = 20, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo = 30, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink = 10, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink = 50, + /obj/item/weapon/reagent_containers/food/drinks/groansbanned = 50, + ) + contraband = list( + /obj/item/weapon/reagent_containers/food/drinks/groansbanned = 10, + ) + + pack = /obj/structure/vendomatpack/groans + +/obj/machinery/vending/nuka + name = "Nuka Cola Machine" + desc = "A machine filled to the brim with ice cold Nuka Cola!" + product_slogans = "A refreshing burst of atomic energy!;Drink like there's no tomorrow!;Take the leap... enjoy a Quantum!" + product_ads = "Wouldn't you enjoy an ice cold Nuka Cola right about now?" + vend_reply = "Enjoy a Nuka break!" + icon_state = "nuka" + products = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka = 15) + prices = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka = 20, /obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum = 50) + contraband = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum = 5) + + pack = /obj/structure/vendomatpack/nuka + +/obj/machinery/vending/chapel + name = "PietyVend" + desc = "A holy vendor for a pious man." + product_slogans = "Bene orasse est bene studuisse.;Beati pauperes spiritu.;Di immortales virtutem approbare, non adhibere debent." + product_ads = "Deus tecum." + vend_reply = "Deus vult!" + icon_state = "chapel" + products = list( + /obj/item/clothing/under/rank/chaplain = 2, + /obj/item/clothing/shoes/black = 2, + /obj/item/clothing/suit/nun = 2, + /obj/item/clothing/head/nun_hood = 2, + /obj/item/clothing/suit/chaplain_hoodie = 2, + /obj/item/clothing/head/chaplain_hood = 2, + /obj/item/clothing/suit/holidaypriest = 2, + /obj/item/clothing/under/wedding/bride_white = 2, + /obj/item/clothing/head/hasturhood = 2, + /obj/item/clothing/suit/hastur = 2, + /obj/item/clothing/suit/unathi/robe = 2, + /obj/item/clothing/head/wizard/amp = 2, + /obj/item/clothing/suit/wizrobe/psypurple = 2, + /obj/item/clothing/suit/imperium_monk = 2, + /obj/item/clothing/mask/chapmask = 2, + /obj/item/clothing/under/sl_suit = 2, + /obj/item/weapon/storage/backpack/cultpack = 2, + /obj/item/weapon/storage/fancy/candle_box = 5, + /obj/item/weapon/reagent_containers/food/snacks/eucharist = 7, + ) + premium = list( + /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 1, + /obj/item/clothing/head/helmet/knight/templar = 2, + /obj/item/clothing/suit/armor/knight/templar = 5, + ) + req_access_txt = "22" + + pack = /obj/structure/vendomatpack/chapelvend diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index f13ee0fbe57..df7f5c51f90 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -1,274 +1,274 @@ -/obj/mecha/combat - force = 30 - var/melee_cooldown = 10 - var/melee_can_hit = 1 - var/list/destroyable_obj = list(/obj/mecha, /obj/structure/window, /obj/structure/grille, /turf/simulated/wall) - internal_damage_threshold = 50 - maint_access = 0 - //add_req_access = 0 - //operation_req_access = list(access_hos) - damage_absorption = list("brute"=0.7,"fire"=1,"bullet"=0.7,"laser"=0.85,"energy"=1,"bomb"=0.8) - var/am = "d3c2fbcadca903a41161ccc9df9cf948" - -/* -/obj/mecha/combat/range_action(target as obj|mob|turf) - if(internal_damage&MECHA_INT_CONTROL_LOST) - target = pick(view(3,target)) - if(selected_weapon) - selected_weapon.fire(target) - return -*/ - -/obj/mecha/combat/melee_action(target as obj|mob|turf) - if(internal_damage&MECHA_INT_CONTROL_LOST) - target = safepick(oview(1,src)) - if(!melee_can_hit || !istype(target, /atom)) return - if(istype(target, /mob/living)) - var/mob/living/M = target - if(src.occupant.a_intent == I_HURT) - playsound(src, 'sound/mecha/mechsmash.ogg', 50, 1) - if(damtype == "brute") - step_away(M,src,15) - /* - if(M.stat>1) - M.gib() - melee_can_hit = 0 - if(do_after(melee_cooldown)) - melee_can_hit = 1 - return - */ - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - // if (M.health <= 0) return - - var/datum/organ/external/temp = H.get_organ(pick("chest", "chest", "chest", "head")) - if(temp) - var/update = 0 - switch(damtype) - if("brute") - H.Paralyse(1) - update |= temp.take_damage(rand(force/2, force), 0) - if("fire") - update |= temp.take_damage(0, rand(force/2, force)) - if("tox") - if(H.reagents) - if(H.reagents.get_reagent_amount("carpotoxin") + force < force*2) - H.reagents.add_reagent("carpotoxin", force) - if(H.reagents.get_reagent_amount("cryptobiolin") + force < force*2) - H.reagents.add_reagent("cryptobiolin", force) - else - return - if(update) H.UpdateDamageIcon(1) - H.updatehealth() - - else - switch(damtype) - if("brute") - M.Paralyse(1) - M.take_overall_damage(rand(force/2, force)) - if("fire") - M.take_overall_damage(0, rand(force/2, force)) - if("tox") - if(M.reagents) - if(M.reagents.get_reagent_amount("carpotoxin") + force < force*2) - M.reagents.add_reagent("carpotoxin", force) - if(M.reagents.get_reagent_amount("cryptobiolin") + force < force*2) - M.reagents.add_reagent("cryptobiolin", force) - else - return - M.updatehealth() - src.occupant_message("You hit [target].") - src.visible_message("[src.name] hits [target].") - else - step_away(M,src) - src.occupant_message("You push [target] out of the way.") - src.visible_message("[src] pushes [target] out of the way.") - - melee_can_hit = 0 - if(do_after(melee_cooldown)) - melee_can_hit = 1 - return - - else - if(damtype == "brute") - for(var/target_type in src.destroyable_obj) - if(istype(target, target_type) && hascall(target, "attackby")) - src.occupant_message("You hit [target].") - src.visible_message("[src.name] hits [target]") - if(!istype(target, /turf/simulated/wall)) - target:attackby(src,src.occupant) - else if(prob(5)) - target:dismantle_wall(1) - src.occupant_message("You smash through the wall.") - src.visible_message("[src.name] smashes through the wall") - playsound(src, 'sound/weapons/smash.ogg', 50, 1) - melee_can_hit = 0 - if(do_after(melee_cooldown)) - melee_can_hit = 1 - break - return - -/* -/obj/mecha/combat/proc/mega_shake(target) - if(!istype(target, /obj) && !istype(target, /mob)) return - if(istype(target, /mob)) - var/mob/M = target - M.Dizzy(3) - M.adjustBruteLoss(1) - M.updatehealth() - for (var/mob/V in viewers(src)) - V.show_message("[src.name] shakes [M] like a rag doll.") - return -*/ - -/* - if(energy>0 && can_move) - if(step(src,direction)) - can_move = 0 - spawn(step_in) can_move = 1 - if(overload) - energy = energy-2 - health-- - else - energy-- - return 1 - - return 0 -*/ -/* -/obj/mecha/combat/hear_talk(mob/M as mob, text) - ..() - if(am && M==occupant) - if(findtext(text,"")) - sam() - return - -/obj/mecha/combat/proc/sam() - if(am) - var/window = {" - - - - - -
                      -
                      - - -
                      -
                      - - - "} - occupant << browse(window, "window=sam;size=800x600;") - onclose(occupant, "sam", src) - return -*/ -/obj/mecha/combat/moved_inside(var/mob/living/carbon/human/H as mob) - if(..()) - if(H.client) - H.client.mouse_pointer_icon = file("icons/mouse/mecha_mouse.dmi") - return 1 - else - return 0 - -/obj/mecha/combat/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) - if(..()) - if(occupant.client) - occupant.client.mouse_pointer_icon = file("icons/mouse/mecha_mouse.dmi") - return 1 - else - return 0 - - -/obj/mecha/combat/go_out() - if(src.occupant && src.occupant.client) - src.occupant.client.mouse_pointer_icon = initial(src.occupant.client.mouse_pointer_icon) - ..() - return - -/obj/mecha/combat/Topic(href,href_list) - ..() - var/datum/topic_input/filter = new (href,href_list) - if(filter.get("close")) - am = null - return - /* - if(filter.get("saminput")) - if(md5(filter.get("saminput")) == am) - occupant_message("From the lies of the Antipath, Circuit preserve us.") - am = null - return +/obj/mecha/combat + force = 30 + var/melee_cooldown = 10 + var/melee_can_hit = 1 + var/list/destroyable_obj = list(/obj/mecha, /obj/structure/window, /obj/structure/grille, /turf/simulated/wall) + internal_damage_threshold = 50 + maint_access = 0 + //add_req_access = 0 + //operation_req_access = list(access_hos) + damage_absorption = list("brute"=0.7,"fire"=1,"bullet"=0.7,"laser"=0.85,"energy"=1,"bomb"=0.8) + var/am = "d3c2fbcadca903a41161ccc9df9cf948" + +/* +/obj/mecha/combat/range_action(target as obj|mob|turf) + if(internal_damage&MECHA_INT_CONTROL_LOST) + target = pick(view(3,target)) + if(selected_weapon) + selected_weapon.fire(target) + return +*/ + +/obj/mecha/combat/melee_action(target as obj|mob|turf) + if(internal_damage&MECHA_INT_CONTROL_LOST) + target = safepick(oview(1,src)) + if(!melee_can_hit || !istype(target, /atom)) return + if(istype(target, /mob/living)) + var/mob/living/M = target + if(src.occupant.a_intent == I_HURT) + playsound(src, 'sound/mecha/mechsmash.ogg', 50, 1) + if(damtype == "brute") + step_away(M,src,15) + /* + if(M.stat>1) + M.gib() + melee_can_hit = 0 + if(do_after(melee_cooldown)) + melee_can_hit = 1 + return + */ + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + // if (M.health <= 0) return + + var/datum/organ/external/temp = H.get_organ(pick("chest", "chest", "chest", "head")) + if(temp) + var/update = 0 + switch(damtype) + if("brute") + H.Paralyse(1) + update |= temp.take_damage(rand(force/2, force), 0) + if("fire") + update |= temp.take_damage(0, rand(force/2, force)) + if("tox") + if(H.reagents) + if(H.reagents.get_reagent_amount("carpotoxin") + force < force*2) + H.reagents.add_reagent("carpotoxin", force) + if(H.reagents.get_reagent_amount("cryptobiolin") + force < force*2) + H.reagents.add_reagent("cryptobiolin", force) + else + return + if(update) H.UpdateDamageIcon(1) + H.updatehealth() + + else + switch(damtype) + if("brute") + M.Paralyse(1) + M.take_overall_damage(rand(force/2, force)) + if("fire") + M.take_overall_damage(0, rand(force/2, force)) + if("tox") + if(M.reagents) + if(M.reagents.get_reagent_amount("carpotoxin") + force < force*2) + M.reagents.add_reagent("carpotoxin", force) + if(M.reagents.get_reagent_amount("cryptobiolin") + force < force*2) + M.reagents.add_reagent("cryptobiolin", force) + else + return + M.updatehealth() + src.occupant_message("You hit [target].") + src.visible_message("[src.name] hits [target].") + else + step_away(M,src) + src.occupant_message("You push [target] out of the way.") + src.visible_message("[src] pushes [target] out of the way.") + + melee_can_hit = 0 + if(do_after(melee_cooldown)) + melee_can_hit = 1 + return + + else + if(damtype == "brute") + for(var/target_type in src.destroyable_obj) + if(istype(target, target_type) && hascall(target, "attackby")) + src.occupant_message("You hit [target].") + src.visible_message("[src.name] hits [target]") + if(!istype(target, /turf/simulated/wall)) + target:attackby(src,src.occupant) + else if(prob(5)) + target:dismantle_wall(1) + src.occupant_message("You smash through the wall.") + src.visible_message("[src.name] smashes through the wall") + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + melee_can_hit = 0 + if(do_after(melee_cooldown)) + melee_can_hit = 1 + break + return + +/* +/obj/mecha/combat/proc/mega_shake(target) + if(!istype(target, /obj) && !istype(target, /mob)) return + if(istype(target, /mob)) + var/mob/M = target + M.Dizzy(3) + M.adjustBruteLoss(1) + M.updatehealth() + for (var/mob/V in viewers(src)) + V.show_message("[src.name] shakes [M] like a rag doll.") + return +*/ + +/* + if(energy>0 && can_move) + if(step(src,direction)) + can_move = 0 + spawn(step_in) can_move = 1 + if(overload) + energy = energy-2 + health-- + else + energy-- + return 1 + + return 0 +*/ +/* +/obj/mecha/combat/hear_talk(mob/M as mob, text) + ..() + if(am && M==occupant) + if(findtext(text,"")) + sam() + return + +/obj/mecha/combat/proc/sam() + if(am) + var/window = {" + + + + + +
                      +
                      + + +
                      +
                      + + + "} + occupant << browse(window, "window=sam;size=800x600;") + onclose(occupant, "sam", src) + return +*/ +/obj/mecha/combat/moved_inside(var/mob/living/carbon/human/H as mob) + if(..()) + if(H.client) + H.client.mouse_pointer_icon = file("icons/mouse/mecha_mouse.dmi") + return 1 + else + return 0 + +/obj/mecha/combat/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) + if(..()) + if(occupant.client) + occupant.client.mouse_pointer_icon = file("icons/mouse/mecha_mouse.dmi") + return 1 + else + return 0 + + +/obj/mecha/combat/go_out() + if(src.occupant && src.occupant.client) + src.occupant.client.mouse_pointer_icon = initial(src.occupant.client.mouse_pointer_icon) + ..() + return + +/obj/mecha/combat/Topic(href,href_list) + ..() + var/datum/topic_input/filter = new (href,href_list) + if(filter.get("close")) + am = null + return + /* + if(filter.get("saminput")) + if(md5(filter.get("saminput")) == am) + occupant_message("From the lies of the Antipath, Circuit preserve us.") + am = null + return */ \ No newline at end of file diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index 43909fe1a1f..6a7908a3c52 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -1,96 +1,96 @@ -/obj/mecha/combat/durand - desc = "It's time to light some fires and kick some tires." - name = "Durand Mk. II" - icon_state = "durand" - initial_icon = "durand" - step_in = 4 - dir_in = 1 //Facing North. - health = 400 - deflect_chance = 20 - damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8) - max_temperature = 30000 - infra_luminosity = 8 - force = 40 - var/defence = 0 - var/defence_deflect = 35 - wreckage = /obj/effect/decal/mecha_wreckage/durand - -/* -/obj/mecha/combat/durand/New() - ..() - weapons += new /datum/mecha_weapon/ballistic/lmg(src) - weapons += new /datum/mecha_weapon/ballistic/scattershot(src) - selected_weapon = weapons[1] - return -*/ - -/obj/mecha/combat/durand/relaymove(mob/user,direction) - if(defence) - if(world.time - last_message > 20) - src.occupant_message("Unable to move while in defence mode") - last_message = world.time - return 0 - . = ..() - return - -/obj/mecha/combat/durand/verb/defence_mode() - set category = "Exosuit Interface" - set name = "Toggle defence mode" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - defence = !defence - if(defence) - icon_state = 0 - if(!istype(src,/obj/mecha/combat/durand/old)) - flick("durand-lockdown-a",src) - icon_state = "durand-lockdown" - deflect_chance = defence_deflect - src.occupant_message("You enable [src] defence mode.") - playsound(src, 'sound/mecha/mechlockdown.ogg', 60, 1) - else - deflect_chance = initial(deflect_chance) - if(!istype(src,/obj/mecha/combat/durand/old)) - icon_state = reset_icon() - src.occupant_message("You disable [src] defence mode.") - src.log_message("Toggled defence mode.") - return - - -/obj/mecha/combat/durand/get_stats_part() - var/output = ..() - output += "Defence mode: [defence?"on":"off"]" - return output - -/obj/mecha/combat/durand/get_commands() - var/output = {"
                      -
                      Special
                      - -
                      - "} - output += ..() - return output - -/obj/mecha/combat/durand/Topic(href, href_list) - ..() - if (href_list["toggle_defence_mode"]) - src.defence_mode() - return - -/obj/mecha/combat/durand/old - desc = "A retired, third-generation combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms." - name = "Durand" - icon_state = "old_durand" - initial_icon = "old_durand" - step_in = 4 - dir_in = 1 //Facing North. - health = 400 - deflect_chance = 20 - damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8) - max_temperature = 30000 - infra_luminosity = 8 - force = 40 +/obj/mecha/combat/durand + desc = "It's time to light some fires and kick some tires." + name = "Durand Mk. II" + icon_state = "durand" + initial_icon = "durand" + step_in = 4 + dir_in = 1 //Facing North. + health = 400 + deflect_chance = 20 + damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8) + max_temperature = 30000 + infra_luminosity = 8 + force = 40 + var/defence = 0 + var/defence_deflect = 35 + wreckage = /obj/effect/decal/mecha_wreckage/durand + +/* +/obj/mecha/combat/durand/New() + ..() + weapons += new /datum/mecha_weapon/ballistic/lmg(src) + weapons += new /datum/mecha_weapon/ballistic/scattershot(src) + selected_weapon = weapons[1] + return +*/ + +/obj/mecha/combat/durand/relaymove(mob/user,direction) + if(defence) + if(world.time - last_message > 20) + src.occupant_message("Unable to move while in defence mode") + last_message = world.time + return 0 + . = ..() + return + +/obj/mecha/combat/durand/verb/defence_mode() + set category = "Exosuit Interface" + set name = "Toggle defence mode" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + defence = !defence + if(defence) + icon_state = 0 + if(!istype(src,/obj/mecha/combat/durand/old)) + flick("durand-lockdown-a",src) + icon_state = "durand-lockdown" + deflect_chance = defence_deflect + src.occupant_message("You enable [src] defence mode.") + playsound(src, 'sound/mecha/mechlockdown.ogg', 60, 1) + else + deflect_chance = initial(deflect_chance) + if(!istype(src,/obj/mecha/combat/durand/old)) + icon_state = reset_icon() + src.occupant_message("You disable [src] defence mode.") + src.log_message("Toggled defence mode.") + return + + +/obj/mecha/combat/durand/get_stats_part() + var/output = ..() + output += "Defence mode: [defence?"on":"off"]" + return output + +/obj/mecha/combat/durand/get_commands() + var/output = {"
                      +
                      Special
                      + +
                      + "} + output += ..() + return output + +/obj/mecha/combat/durand/Topic(href, href_list) + ..() + if (href_list["toggle_defence_mode"]) + src.defence_mode() + return + +/obj/mecha/combat/durand/old + desc = "A retired, third-generation combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms." + name = "Durand" + icon_state = "old_durand" + initial_icon = "old_durand" + step_in = 4 + dir_in = 1 //Facing North. + health = 400 + deflect_chance = 20 + damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8) + max_temperature = 30000 + infra_luminosity = 8 + force = 40 wreckage = /obj/effect/decal/mecha_wreckage/durand/old \ No newline at end of file diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index 2e9330c03e7..4f627715f50 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -1,113 +1,113 @@ -/obj/mecha/combat/gygax - desc = "A lightweight, security exosuit. Popular among private and corporate security." - name = "Gygax" - icon_state = "gygax" - initial_icon = "gygax" - step_in = 3 - dir_in = 1 //Facing North. - health = 300 - deflect_chance = 15 - damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1) - max_temperature = 25000 - infra_luminosity = 6 - var/overload = 0 - var/overload_coeff = 2 - wreckage = /obj/effect/decal/mecha_wreckage/gygax - internal_damage_threshold = 35 - max_equip = 3 - -/obj/mecha/combat/gygax/dark - desc = "A lightweight exosuit used by Nanotrasen Death Squads. A significantly upgraded Gygax security mech." - name = "Dark Gygax" - icon_state = "darkgygax" - initial_icon = "darkgygax" - health = 400 - deflect_chance = 25 - damage_absorption = list("brute"=0.6,"fire"=0.8,"bullet"=0.6,"laser"=0.5,"energy"=0.65,"bomb"=0.8) - max_temperature = 45000 - overload_coeff = 1 - wreckage = /obj/effect/decal/mecha_wreckage/gygax/dark - max_equip = 4 - step_energy_drain = 5 - -/obj/mecha/combat/gygax/dark/New() - ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/teleporter - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay - ME.attach(src) - return - -/obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/cell/C=null) - if(C) - C.forceMove(src) - cell = C - return - cell = new(src) - cell.charge = 30000 - cell.maxcharge = 30000 - - -/obj/mecha/combat/gygax/verb/overload() - set category = "Exosuit Interface" - set name = "Toggle leg actuators overload" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - if(overload) - overload = 0 - step_in = initial(step_in) - step_energy_drain = initial(step_energy_drain) - src.occupant_message("You disable leg actuators overload.") - if(!istype(src,/obj/mecha/combat/gygax/dark)) - flick("gygax-gofast-aoff",src) - reset_icon() - else - overload = 1 - step_in = min(1, round(step_in/2)) - step_energy_drain = step_energy_drain*overload_coeff - src.occupant_message("You enable leg actuators overload.") - if(!istype(src,/obj/mecha/combat/gygax/dark)) - flick("gygax-gofast-aon",src) - icon_state = "gygax-gofast" - src.log_message("Toggled leg actuators overload.") - return - -/obj/mecha/combat/gygax/dyndomove(direction) - if(!..()) return - if(overload) - health-- - if(health < initial(health) - initial(health)/3) - overload = 0 - step_in = initial(step_in) - step_energy_drain = initial(step_energy_drain) - src.occupant_message("Leg actuators damage threshold exceded. Disabling overload.") - return - - -/obj/mecha/combat/gygax/get_stats_part() - var/output = ..() - output += "Leg actuators overload: [overload?"on":"off"]" - return output - -/obj/mecha/combat/gygax/get_commands() - var/output = {"
                      -
                      Special
                      - -
                      - "} - output += ..() - return output - -/obj/mecha/combat/gygax/Topic(href, href_list) - ..() - if (href_list["toggle_leg_overload"]) - src.overload() +/obj/mecha/combat/gygax + desc = "A lightweight, security exosuit. Popular among private and corporate security." + name = "Gygax" + icon_state = "gygax" + initial_icon = "gygax" + step_in = 3 + dir_in = 1 //Facing North. + health = 300 + deflect_chance = 15 + damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1) + max_temperature = 25000 + infra_luminosity = 6 + var/overload = 0 + var/overload_coeff = 2 + wreckage = /obj/effect/decal/mecha_wreckage/gygax + internal_damage_threshold = 35 + max_equip = 3 + +/obj/mecha/combat/gygax/dark + desc = "A lightweight exosuit used by Nanotrasen Death Squads. A significantly upgraded Gygax security mech." + name = "Dark Gygax" + icon_state = "darkgygax" + initial_icon = "darkgygax" + health = 400 + deflect_chance = 25 + damage_absorption = list("brute"=0.6,"fire"=0.8,"bullet"=0.6,"laser"=0.5,"energy"=0.65,"bomb"=0.8) + max_temperature = 45000 + overload_coeff = 1 + wreckage = /obj/effect/decal/mecha_wreckage/gygax/dark + max_equip = 4 + step_energy_drain = 5 + +/obj/mecha/combat/gygax/dark/New() + ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/teleporter + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay + ME.attach(src) + return + +/obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/cell/C=null) + if(C) + C.forceMove(src) + cell = C + return + cell = new(src) + cell.charge = 30000 + cell.maxcharge = 30000 + + +/obj/mecha/combat/gygax/verb/overload() + set category = "Exosuit Interface" + set name = "Toggle leg actuators overload" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + if(overload) + overload = 0 + step_in = initial(step_in) + step_energy_drain = initial(step_energy_drain) + src.occupant_message("You disable leg actuators overload.") + if(!istype(src,/obj/mecha/combat/gygax/dark)) + flick("gygax-gofast-aoff",src) + reset_icon() + else + overload = 1 + step_in = min(1, round(step_in/2)) + step_energy_drain = step_energy_drain*overload_coeff + src.occupant_message("You enable leg actuators overload.") + if(!istype(src,/obj/mecha/combat/gygax/dark)) + flick("gygax-gofast-aon",src) + icon_state = "gygax-gofast" + src.log_message("Toggled leg actuators overload.") + return + +/obj/mecha/combat/gygax/dyndomove(direction) + if(!..()) return + if(overload) + health-- + if(health < initial(health) - initial(health)/3) + overload = 0 + step_in = initial(step_in) + step_energy_drain = initial(step_energy_drain) + src.occupant_message("Leg actuators damage threshold exceded. Disabling overload.") + return + + +/obj/mecha/combat/gygax/get_stats_part() + var/output = ..() + output += "Leg actuators overload: [overload?"on":"off"]" + return output + +/obj/mecha/combat/gygax/get_commands() + var/output = {"
                      +
                      Special
                      + +
                      + "} + output += ..() + return output + +/obj/mecha/combat/gygax/Topic(href, href_list) + ..() + if (href_list["toggle_leg_overload"]) + src.overload() return \ No newline at end of file diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 75d8bda793b..93f9660bcde 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -1,164 +1,164 @@ -/obj/mecha/combat/honker - desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. Used to spread the fun and joy of life. HONK!" - name = "H.O.N.K" - icon_state = "honker" - initial_icon = "honker" - step_in = 2 - health = 140 - deflect_chance = 60 - internal_damage_threshold = 60 - damage_absorption = list("brute"=1.2,"fire"=1.5,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) - max_temperature = 25000 - infra_luminosity = 5 - operation_req_access = list(access_clown) - wreckage = /obj/effect/decal/mecha_wreckage/honker - add_req_access = 0 - max_equip = 3 - var/squeak = 0 - -/* -/obj/mecha/combat/honker/New() - ..() - - weapons += new /datum/mecha_weapon/honker(src) - weapons += new /datum/mecha_weapon/missile_rack/banana_mortar(src) - weapons += new /datum/mecha_weapon/missile_rack/mousetrap_mortar(src) - selected_weapon = weapons[1] - return -*/ - - -/obj/mecha/combat/honker/melee_action(target) - if(!melee_can_hit) - return - else if(istype(target, /mob)) - step_away(target,src,15) - return - -/obj/mecha/combat/honker/get_stats_part() - var/integrity = health/initial(health)*100 - var/cell_charge = get_charge() - var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" - var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" - var/cabin_pressure = round(return_pressure(),0.01) - var/output = {"[report_internal_damage()] - [integrity<30?"DAMAGE LEVEL CRITICAL
                      ":null] - [internal_damage&MECHA_INT_TEMP_CONTROL?"CLOWN SUPPORT SYSTEM MALFUNCTION
                      ":null] - [internal_damage&MECHA_INT_TANK_BREACH?"GAS TANK HONK
                      ":null] - [internal_damage&MECHA_INT_CONTROL_LOST?"HONK-A-DOODLE - Recalibrate
                      ":null] - IntegriHONK: [integrity]%
                      - PowerHONK charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
                      - Air source: [use_internal_tank?"Internal Airtank":"Environment"]
                      - AirHONK pressure: [tank_pressure]kPa
                      - AirHONK temperature: [tank_temperature]K|[tank_temperature - T0C]°C
                      - HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
                      - HONK temperature: [return_temperature()]K|[return_temperature() - T0C]°C
                      - Lights: [lights?"on":"off"]
                      - [src.dna?"DNA-locked:
                      [src.dna] \[Reset\]
                      ":null] - "} - return output - -/obj/mecha/combat/honker/get_stats_html() - var/output = {" - [src.name] data - - - - -
                      - [src.get_stats_part()] -
                      -
                      - [src.get_equipment_list()] -
                      -
                      -
                      - [src.get_commands()] -
                      - - - "} - return output - -/obj/mecha/combat/honker/get_commands() - var/output = {"
                      -
                      Sounds of HONK:
                      - -
                      - "} - output += ..() - return output - - -/obj/mecha/combat/honker/get_equipment_list() - if(!equipment.len) - return - var/output = "Honk-ON-Systems:
                      " - for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) - output += "[selected==MT?"":""][MT.get_equip_info()][selected==MT?"":""]
                      " - output += "
                      " - return output - - - -/obj/mecha/combat/honker/mechstep(direction) - var/result = step(src,direction) - if(result) - if(!squeak) - playsound(src, "clownstep", 70, 1) - squeak = 1 - else - squeak = 0 - return result - -obj/mecha/combat/honker/Topic(href, href_list) - ..() - if (href_list["play_sound"]) - switch(href_list["play_sound"]) - if("sadtrombone") - playsound(src, 'sound/misc/sadtrombone.ogg', 50) - return - -proc/rand_hex_color() - var/list/colors = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f") - var/color="" - for (var/i=0;i<6;i++) - color = color+pick(colors) - return color - - +/obj/mecha/combat/honker + desc = "Produced by \"Tyranny of Honk, INC\", this exosuit is designed as heavy clown-support. Used to spread the fun and joy of life. HONK!" + name = "H.O.N.K" + icon_state = "honker" + initial_icon = "honker" + step_in = 2 + health = 140 + deflect_chance = 60 + internal_damage_threshold = 60 + damage_absorption = list("brute"=1.2,"fire"=1.5,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) + max_temperature = 25000 + infra_luminosity = 5 + operation_req_access = list(access_clown) + wreckage = /obj/effect/decal/mecha_wreckage/honker + add_req_access = 0 + max_equip = 3 + var/squeak = 0 + +/* +/obj/mecha/combat/honker/New() + ..() + + weapons += new /datum/mecha_weapon/honker(src) + weapons += new /datum/mecha_weapon/missile_rack/banana_mortar(src) + weapons += new /datum/mecha_weapon/missile_rack/mousetrap_mortar(src) + selected_weapon = weapons[1] + return +*/ + + +/obj/mecha/combat/honker/melee_action(target) + if(!melee_can_hit) + return + else if(istype(target, /mob)) + step_away(target,src,15) + return + +/obj/mecha/combat/honker/get_stats_part() + var/integrity = health/initial(health)*100 + var/cell_charge = get_charge() + var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" + var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" + var/cabin_pressure = round(return_pressure(),0.01) + var/output = {"[report_internal_damage()] + [integrity<30?"DAMAGE LEVEL CRITICAL
                      ":null] + [internal_damage&MECHA_INT_TEMP_CONTROL?"CLOWN SUPPORT SYSTEM MALFUNCTION
                      ":null] + [internal_damage&MECHA_INT_TANK_BREACH?"GAS TANK HONK
                      ":null] + [internal_damage&MECHA_INT_CONTROL_LOST?"HONK-A-DOODLE - Recalibrate
                      ":null] + IntegriHONK: [integrity]%
                      + PowerHONK charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
                      + Air source: [use_internal_tank?"Internal Airtank":"Environment"]
                      + AirHONK pressure: [tank_pressure]kPa
                      + AirHONK temperature: [tank_temperature]K|[tank_temperature - T0C]°C
                      + HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
                      + HONK temperature: [return_temperature()]K|[return_temperature() - T0C]°C
                      + Lights: [lights?"on":"off"]
                      + [src.dna?"DNA-locked:
                      [src.dna] \[Reset\]
                      ":null] + "} + return output + +/obj/mecha/combat/honker/get_stats_html() + var/output = {" + [src.name] data + + + + +
                      + [src.get_stats_part()] +
                      +
                      + [src.get_equipment_list()] +
                      +
                      +
                      + [src.get_commands()] +
                      + + + "} + return output + +/obj/mecha/combat/honker/get_commands() + var/output = {"
                      +
                      Sounds of HONK:
                      + +
                      + "} + output += ..() + return output + + +/obj/mecha/combat/honker/get_equipment_list() + if(!equipment.len) + return + var/output = "Honk-ON-Systems:
                      " + for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) + output += "[selected==MT?"":""][MT.get_equip_info()][selected==MT?"":""]
                      " + output += "
                      " + return output + + + +/obj/mecha/combat/honker/mechstep(direction) + var/result = step(src,direction) + if(result) + if(!squeak) + playsound(src, "clownstep", 70, 1) + squeak = 1 + else + squeak = 0 + return result + +obj/mecha/combat/honker/Topic(href, href_list) + ..() + if (href_list["play_sound"]) + switch(href_list["play_sound"]) + if("sadtrombone") + playsound(src, 'sound/misc/sadtrombone.ogg', 50) + return + +proc/rand_hex_color() + var/list/colors = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f") + var/color="" + for (var/i=0;i<6;i++) + color = color+pick(colors) + return color + + diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index 1513886c82b..9de7ec87a92 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -1,212 +1,212 @@ -/obj/mecha/combat/marauder - desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations." - name = "Marauder" - icon_state = "marauder" - initial_icon = "marauder" - step_in = 5 - health = 500 - deflect_chance = 25 - damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7) - max_temperature = 60000 - infra_luminosity = 3 - var/zoom = 0 - var/thrusters = 0 - var/smoke = 5 - var/smoke_ready = 1 - var/smoke_cooldown = 100 - var/datum/effect/effect/system/smoke_spread/smoke_system = new - operation_req_access = list(access_cent_specops) - wreckage = /obj/effect/decal/mecha_wreckage/marauder - add_req_access = 0 - internal_damage_threshold = 25 - force = 45 - max_equip = 4 - -/obj/mecha/combat/marauder/seraph - desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel." - name = "Seraph" - icon_state = "seraph" - initial_icon = "seraph" - operation_req_access = list(access_cent_creed) - step_in = 3 - health = 550 - wreckage = /obj/effect/decal/mecha_wreckage/seraph - internal_damage_threshold = 20 - force = 55 - max_equip = 5 - -/obj/mecha/combat/marauder/mauler - desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model." - name = "Mauler" - icon_state = "mauler" - initial_icon = "mauler" - operation_req_access = list(access_syndicate) - wreckage = /obj/effect/decal/mecha_wreckage/mauler - -/obj/mecha/combat/marauder/New() - ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) - ME.attach(src) - src.smoke_system.set_up(3, 0, src) - src.smoke_system.attach(src) - return - -/obj/mecha/combat/marauder/seraph/New() - ..()//Let it equip whatever is needed. - var/obj/item/mecha_parts/mecha_equipment/ME - if(equipment.len)//Now to remove it and equip anew. - for(ME in equipment) - equipment -= ME - qdel(ME) - ME = null - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) - ME.attach(src) - return - -/obj/mecha/combat/marauder/relaymove(mob/user,direction) - if(user != src.occupant) //While not "realistic", this piece is player friendly. - user.loc = get_turf(src) +/obj/mecha/combat/marauder + desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations." + name = "Marauder" + icon_state = "marauder" + initial_icon = "marauder" + step_in = 5 + health = 500 + deflect_chance = 25 + damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7) + max_temperature = 60000 + infra_luminosity = 3 + var/zoom = 0 + var/thrusters = 0 + var/smoke = 5 + var/smoke_ready = 1 + var/smoke_cooldown = 100 + var/datum/effect/effect/system/smoke_spread/smoke_system = new + operation_req_access = list(access_cent_specops) + wreckage = /obj/effect/decal/mecha_wreckage/marauder + add_req_access = 0 + internal_damage_threshold = 25 + force = 45 + max_equip = 4 + +/obj/mecha/combat/marauder/seraph + desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel." + name = "Seraph" + icon_state = "seraph" + initial_icon = "seraph" + operation_req_access = list(access_cent_creed) + step_in = 3 + health = 550 + wreckage = /obj/effect/decal/mecha_wreckage/seraph + internal_damage_threshold = 20 + force = 55 + max_equip = 5 + +/obj/mecha/combat/marauder/mauler + desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model." + name = "Mauler" + icon_state = "mauler" + initial_icon = "mauler" + operation_req_access = list(access_syndicate) + wreckage = /obj/effect/decal/mecha_wreckage/mauler + +/obj/mecha/combat/marauder/New() + ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) + ME.attach(src) + src.smoke_system.set_up(3, 0, src) + src.smoke_system.attach(src) + return + +/obj/mecha/combat/marauder/seraph/New() + ..()//Let it equip whatever is needed. + var/obj/item/mecha_parts/mecha_equipment/ME + if(equipment.len)//Now to remove it and equip anew. + for(ME in equipment) + equipment -= ME + qdel(ME) + ME = null + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) + ME.attach(src) + return + +/obj/mecha/combat/marauder/relaymove(mob/user,direction) + if(user != src.occupant) //While not "realistic", this piece is player friendly. + user.loc = get_turf(src) to_chat(user, "You climb out from [src]") - return 0 - if(!can_move) - return 0 - if(zoom) - if(world.time - last_message > 20) - src.occupant_message("Unable to move while in zoom mode.") - last_message = world.time - return 0 - if(connected_port) - if(world.time - last_message > 20) - src.occupant_message("Unable to move while connected to the air system port") - last_message = world.time - return 0 - if(!thrusters && src.pr_inertial_movement.active()) - return 0 - if(state || !has_charge(step_energy_drain)) - return 0 - var/tmp_step_in = step_in - var/tmp_step_energy_drain = step_energy_drain - var/move_result = 0 - if(internal_damage&MECHA_INT_CONTROL_LOST) - move_result = mechsteprand() - else if(src.dir!=direction) - move_result = mechturn(direction) - else - move_result = mechstep(direction) - if(move_result) - if(istype(src.loc, /turf/space)) - if(!src.check_for_support()) - src.pr_inertial_movement.start(list(src,direction)) - if(thrusters) - src.pr_inertial_movement.set_process_args(list(src,direction)) - tmp_step_energy_drain = step_energy_drain*2 - - can_move = 0 - spawn(tmp_step_in) can_move = 1 - use_power(tmp_step_energy_drain) - return 1 - return 0 - - -/obj/mecha/combat/marauder/verb/toggle_thrusters() - set category = "Exosuit Interface" - set name = "Toggle thrusters" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - if(src.occupant) - if(get_charge() > 0) - thrusters = !thrusters - src.log_message("Toggled thrusters.") - src.occupant_message("Thrusters [thrusters?"en":"dis"]abled.") - return - - -/obj/mecha/combat/marauder/verb/smoke() - set category = "Exosuit Interface" - set name = "Smoke" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - if(smoke_ready && smoke>0) - src.smoke_system.start() - smoke-- - smoke_ready = 0 - spawn(smoke_cooldown) - smoke_ready = 1 - return - -/obj/mecha/combat/marauder/verb/zoom() - set category = "Exosuit Interface" - set name = "Zoom" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - if(src.occupant.client) - src.zoom = !src.zoom - src.log_message("Toggled zoom mode.") - src.occupant_message("Zoom mode [zoom?"en":"dis"]abled.") - if(zoom) - src.occupant.client.view = 12 + return 0 + if(!can_move) + return 0 + if(zoom) + if(world.time - last_message > 20) + src.occupant_message("Unable to move while in zoom mode.") + last_message = world.time + return 0 + if(connected_port) + if(world.time - last_message > 20) + src.occupant_message("Unable to move while connected to the air system port") + last_message = world.time + return 0 + if(!thrusters && src.pr_inertial_movement.active()) + return 0 + if(state || !has_charge(step_energy_drain)) + return 0 + var/tmp_step_in = step_in + var/tmp_step_energy_drain = step_energy_drain + var/move_result = 0 + if(internal_damage&MECHA_INT_CONTROL_LOST) + move_result = mechsteprand() + else if(src.dir!=direction) + move_result = mechturn(direction) + else + move_result = mechstep(direction) + if(move_result) + if(istype(src.loc, /turf/space)) + if(!src.check_for_support()) + src.pr_inertial_movement.start(list(src,direction)) + if(thrusters) + src.pr_inertial_movement.set_process_args(list(src,direction)) + tmp_step_energy_drain = step_energy_drain*2 + + can_move = 0 + spawn(tmp_step_in) can_move = 1 + use_power(tmp_step_energy_drain) + return 1 + return 0 + + +/obj/mecha/combat/marauder/verb/toggle_thrusters() + set category = "Exosuit Interface" + set name = "Toggle thrusters" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + if(src.occupant) + if(get_charge() > 0) + thrusters = !thrusters + src.log_message("Toggled thrusters.") + src.occupant_message("Thrusters [thrusters?"en":"dis"]abled.") + return + + +/obj/mecha/combat/marauder/verb/smoke() + set category = "Exosuit Interface" + set name = "Smoke" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + if(smoke_ready && smoke>0) + src.smoke_system.start() + smoke-- + smoke_ready = 0 + spawn(smoke_cooldown) + smoke_ready = 1 + return + +/obj/mecha/combat/marauder/verb/zoom() + set category = "Exosuit Interface" + set name = "Zoom" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + if(src.occupant.client) + src.zoom = !src.zoom + src.log_message("Toggled zoom mode.") + src.occupant_message("Zoom mode [zoom?"en":"dis"]abled.") + if(zoom) + src.occupant.client.view = 12 to_chat(src.occupant, sound('sound/mecha/imag_enh.ogg',volume=50)) - else - src.occupant.client.view = world.view//world.view - default mob view size - return - - -/obj/mecha/combat/marauder/go_out() - if(src.occupant && src.occupant.client) - src.occupant.client.view = world.view - src.zoom = 0 - ..() - return - - -/obj/mecha/combat/marauder/get_stats_part() - var/output = ..() - output += {"Smoke: [smoke] -
                      - Thrusters: [thrusters?"on":"off"] - "} - return output - - -/obj/mecha/combat/marauder/get_commands() - var/output = {"
                      -
                      Special
                      - -
                      - "} - output += ..() - return output - -/obj/mecha/combat/marauder/Topic(href, href_list) - ..() - if (href_list["toggle_thrusters"]) - src.toggle_thrusters() - if (href_list["smoke"]) - src.smoke() - if (href_list["toggle_zoom"]) - src.zoom() - return + else + src.occupant.client.view = world.view//world.view - default mob view size + return + + +/obj/mecha/combat/marauder/go_out() + if(src.occupant && src.occupant.client) + src.occupant.client.view = world.view + src.zoom = 0 + ..() + return + + +/obj/mecha/combat/marauder/get_stats_part() + var/output = ..() + output += {"Smoke: [smoke] +
                      + Thrusters: [thrusters?"on":"off"] + "} + return output + + +/obj/mecha/combat/marauder/get_commands() + var/output = {"
                      +
                      Special
                      + +
                      + "} + output += ..() + return output + +/obj/mecha/combat/marauder/Topic(href, href_list) + ..() + if (href_list["toggle_thrusters"]) + src.toggle_thrusters() + if (href_list["smoke"]) + src.smoke() + if (href_list["toggle_zoom"]) + src.zoom() + return diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm index 399c1c0b686..0f0697c781d 100644 --- a/code/game/mecha/combat/phazon.dm +++ b/code/game/mecha/combat/phazon.dm @@ -1,70 +1,70 @@ -/obj/mecha/combat/phazon - desc = "An exosuit which can only be described as 'WTF?'." - name = "Phazon" - icon_state = "phazon" - initial_icon = "phazon" - step_in = 1 - dir_in = 1 //Facing North. - step_energy_drain = 3 - health = 200 - deflect_chance = 30 - damage_absorption = list("brute"=0.7,"fire"=0.7,"bullet"=0.7,"laser"=0.7,"energy"=0.7,"bomb"=0.7) - max_temperature = 25000 - infra_luminosity = 3 - wreckage = /obj/effect/decal/mecha_wreckage/phazon - add_req_access = 1 - //operation_req_access = list() - internal_damage_threshold = 25 - force = 15 - var/phasing = 0 - var/phasing_energy_drain = 200 - max_equip = 4 - - -/obj/mecha/combat/phazon/New() - ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/rcd - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/gravcatapult - ME.attach(src) - return - -/obj/mecha/combat/phazon/Bump(var/atom/obstacle) - if(phasing && get_charge()>=phasing_energy_drain) - spawn() - if(can_move) - can_move = 0 - flick("phazon-phase", src) - src.loc = get_step(src,src.dir) - src.use_power(phasing_energy_drain) - sleep(step_in*3) - can_move = 1 - else - . = ..() - return - -/obj/mecha/combat/phazon/click_action(atom/target,mob/user) - if(phasing) - src.occupant_message("Unable to interact with objects while phasing") - return - else - return ..() - -/obj/mecha/combat/phazon/get_commands() - var/output = {" - "} - output += ..() - return output - -/obj/mecha/combat/phazon/Topic(href, href_list) - ..() - if (href_list["phasing"]) - phasing = !phasing - send_byjax(src.occupant,"exosuit.browser","phasing_command","[phasing?"Dis":"En"]able phasing") - src.occupant_message("En":"#f00\">Dis"]abled phasing.") +/obj/mecha/combat/phazon + desc = "An exosuit which can only be described as 'WTF?'." + name = "Phazon" + icon_state = "phazon" + initial_icon = "phazon" + step_in = 1 + dir_in = 1 //Facing North. + step_energy_drain = 3 + health = 200 + deflect_chance = 30 + damage_absorption = list("brute"=0.7,"fire"=0.7,"bullet"=0.7,"laser"=0.7,"energy"=0.7,"bomb"=0.7) + max_temperature = 25000 + infra_luminosity = 3 + wreckage = /obj/effect/decal/mecha_wreckage/phazon + add_req_access = 1 + //operation_req_access = list() + internal_damage_threshold = 25 + force = 15 + var/phasing = 0 + var/phasing_energy_drain = 200 + max_equip = 4 + + +/obj/mecha/combat/phazon/New() + ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/rcd + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/gravcatapult + ME.attach(src) + return + +/obj/mecha/combat/phazon/Bump(var/atom/obstacle) + if(phasing && get_charge()>=phasing_energy_drain) + spawn() + if(can_move) + can_move = 0 + flick("phazon-phase", src) + src.loc = get_step(src,src.dir) + src.use_power(phasing_energy_drain) + sleep(step_in*3) + can_move = 1 + else + . = ..() + return + +/obj/mecha/combat/phazon/click_action(atom/target,mob/user) + if(phasing) + src.occupant_message("Unable to interact with objects while phasing") + return + else + return ..() + +/obj/mecha/combat/phazon/get_commands() + var/output = {" + "} + output += ..() + return output + +/obj/mecha/combat/phazon/Topic(href, href_list) + ..() + if (href_list["phasing"]) + phasing = !phasing + send_byjax(src.occupant,"exosuit.browser","phasing_command","[phasing?"Dis":"En"]able phasing") + src.occupant_message("En":"#f00\">Dis"]abled phasing.") return \ No newline at end of file diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 7973125da0e..b9fe0ad3536 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -1,145 +1,145 @@ -//TODO: Add critfail checks and reliability -//DO NOT ADD MECHA PARTS TO THE GAME WITH THE DEFAULT "SPRITE ME" SPRITE! -//I'm annoyed I even have to tell you this! SPRITE FIRST, then commit. - -/obj/item/mecha_parts/mecha_equipment - name = "mecha equipment" - icon = 'icons/mecha/mecha_equipment.dmi' - icon_state = "mecha_equip" - force = 5 - origin_tech = "materials=2" - var/equip_cooldown = 0 - var/equip_ready = 1 - var/energy_drain = 0 - var/obj/mecha/chassis = null - var/range = MELEE //bitflags - reliability = 1000 - var/salvageable = 1 - - -/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1, delay_mult=1) - sleep(equip_cooldown * delay_mult) - set_ready_state(1) - if(target && chassis) - return 1 - return 0 - - -/obj/item/mecha_parts/mecha_equipment/New() - ..() - return - -/obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() - if(chassis) - send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) - send_byjax(chassis.occupant,"exosuit.browser","equipment_menu",chassis.get_equipment_menu(),"dropdowns") - return 1 - return - -/obj/item/mecha_parts/mecha_equipment/proc/update_equip_info() - if(chassis) - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) - return 1 - return - -/obj/item/mecha_parts/mecha_equipment/proc/destroy()//missiles detonating, teleporter creating singularity? - if(chassis) - chassis.equipment -= src - listclearnulls(chassis.equipment) - if(chassis.selected == src) - chassis.selected = null - src.update_chassis_page() - chassis.occupant_message("The [src] is destroyed!") - chassis.log_append_to_last("[src] is destroyed.",1) - if(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon)) +//TODO: Add critfail checks and reliability +//DO NOT ADD MECHA PARTS TO THE GAME WITH THE DEFAULT "SPRITE ME" SPRITE! +//I'm annoyed I even have to tell you this! SPRITE FIRST, then commit. + +/obj/item/mecha_parts/mecha_equipment + name = "mecha equipment" + icon = 'icons/mecha/mecha_equipment.dmi' + icon_state = "mecha_equip" + force = 5 + origin_tech = "materials=2" + var/equip_cooldown = 0 + var/equip_ready = 1 + var/energy_drain = 0 + var/obj/mecha/chassis = null + var/range = MELEE //bitflags + reliability = 1000 + var/salvageable = 1 + + +/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1, delay_mult=1) + sleep(equip_cooldown * delay_mult) + set_ready_state(1) + if(target && chassis) + return 1 + return 0 + + +/obj/item/mecha_parts/mecha_equipment/New() + ..() + return + +/obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() + if(chassis) + send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) + send_byjax(chassis.occupant,"exosuit.browser","equipment_menu",chassis.get_equipment_menu(),"dropdowns") + return 1 + return + +/obj/item/mecha_parts/mecha_equipment/proc/update_equip_info() + if(chassis) + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + return 1 + return + +/obj/item/mecha_parts/mecha_equipment/proc/destroy()//missiles detonating, teleporter creating singularity? + if(chassis) + chassis.equipment -= src + listclearnulls(chassis.equipment) + if(chassis.selected == src) + chassis.selected = null + src.update_chassis_page() + chassis.occupant_message("The [src] is destroyed!") + chassis.log_append_to_last("[src] is destroyed.",1) + if(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon)) to_chat(chassis.occupant, sound('sound/mecha/weapdestr.ogg',volume=50)) - else + else to_chat(chassis.occupant, sound('sound/mecha/critdestr.ogg',volume=50)) - spawn - qdel (src) - return - -/obj/item/mecha_parts/mecha_equipment/proc/critfail() - if(chassis) - log_message("Critical failure",1) - return - -/obj/item/mecha_parts/mecha_equipment/proc/get_equip_info() - if(!chassis) return - return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]" - -/obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not? - return range&RANGED - -/obj/item/mecha_parts/mecha_equipment/proc/is_melee() - return range&MELEE - - -/obj/item/mecha_parts/mecha_equipment/proc/action_checks(atom/target) - if(!target) - return 0 - if(!chassis) - return 0 - if(!equip_ready) - return 0 - if(crit_fail) - return 0 - if(energy_drain && !chassis.has_charge(energy_drain)) - return 0 - return 1 - -/obj/item/mecha_parts/mecha_equipment/proc/action(atom/target) - return - -/obj/item/mecha_parts/mecha_equipment/proc/can_attach(obj/mecha/M as obj) - if(istype(M)) - if(M.equipment.len[src]: [message]") - return + spawn + qdel (src) + return + +/obj/item/mecha_parts/mecha_equipment/proc/critfail() + if(chassis) + log_message("Critical failure",1) + return + +/obj/item/mecha_parts/mecha_equipment/proc/get_equip_info() + if(!chassis) return + return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]" + +/obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not? + return range&RANGED + +/obj/item/mecha_parts/mecha_equipment/proc/is_melee() + return range&MELEE + + +/obj/item/mecha_parts/mecha_equipment/proc/action_checks(atom/target) + if(!target) + return 0 + if(!chassis) + return 0 + if(!equip_ready) + return 0 + if(crit_fail) + return 0 + if(energy_drain && !chassis.has_charge(energy_drain)) + return 0 + return 1 + +/obj/item/mecha_parts/mecha_equipment/proc/action(atom/target) + return + +/obj/item/mecha_parts/mecha_equipment/proc/can_attach(obj/mecha/M as obj) + if(istype(M)) + if(M.equipment.len[src]: [message]") + return diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 2b9e13258c5..7786a13104c 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -1,673 +1,673 @@ -/obj/item/mecha_parts/mecha_equipment/tool/sleeper - name = "Mounted Sleeper" - desc = "Mounted Sleeper. (Can be attached to: Medical Exosuits)" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "sleeper_0" - origin_tech = "programming=2;biotech=3" - energy_drain = 20 - range = MELEE - reliability = 1000 - equip_cooldown = 20 - var/mob/living/carbon/occupant = null - var/datum/global_iterator/pr_mech_sleeper - var/inject_amount = 10 - salvageable = 0 - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/can_attach(obj/mecha/medical/M) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/New() - ..() - pr_mech_sleeper = new /datum/global_iterator/mech_sleeper(list(src),0) - pr_mech_sleeper.set_delay(equip_cooldown) - return - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/allow_drop() - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/destroy() - for(var/atom/movable/AM in src) - AM.forceMove(get_turf(src)) - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Exit(atom/movable/O) - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/action(var/mob/living/carbon/target) - if(!action_checks(target)) - return - if(!istype(target)) - return - if(target.abiotic()) - occupant_message("Subject cannot have abiotic items on.") //Leaving this one in for balance concerns - if(target.locked_to) - occupant_message("[target] will not fit into the sleeper because they are buckled to [target.locked_to].") - return - if(occupant) - occupant_message("The sleeper is already occupied") - return - for(var/mob/living/carbon/slime/M in range(1,target)) - if(M.Victim == target) - occupant_message("[target] will not fit into the sleeper because they have a slime latched onto their head.") - return - occupant_message("You start putting [target] into [src].") - chassis.visible_message("[chassis] starts putting [target] into the [src].") - var/C = chassis.loc - var/T = target.loc - if(do_after_cooldown(target,2) && chassis.Adjacent(target)) - if(chassis.loc!=C || target.loc!=T) - return - if(occupant) - occupant_message("The sleeper is already occupied!") - return - target.forceMove(src) - occupant = target - target.reset_view(src) - /* - if(target.client) - target.client.perspective = EYE_PERSPECTIVE - target.client.eye = chassis - */ - set_ready_state(0) - pr_mech_sleeper.start() - occupant_message("[target] successfully loaded into [src]. Life support functions engaged.") - chassis.visible_message("[chassis] loads [target] into [src].") - log_message("[target] loaded. Life support functions engaged.") - return - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/go_out() - if(!occupant) - return - occupant.forceMove(get_turf(src)) - occupant_message("[occupant] ejected. Life support functions disabled.") - log_message("[occupant] ejected. Life support functions disabled.") - occupant.reset_view() - /* - if(occupant.client) - occupant.client.eye = occupant.client.mob - occupant.client.perspective = MOB_PERSPECTIVE - */ - occupant = null - pr_mech_sleeper.stop() - set_ready_state(1) - - chassis.empty_bad_contents() - - return - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/detach() - if(occupant) - occupant_message("Unable to detach [src] - equipment occupied.") - return - pr_mech_sleeper.stop() - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/get_equip_info() - var/output = ..() - if(output) - var/temp = "" - if(occupant) - temp = "
                      \[Occupant: [occupant] (Health: [occupant.health]%)\]
                      View stats|Eject" - return "[output] [temp]" - return - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Topic(href,href_list) - ..() - var/datum/topic_input/filter = new /datum/topic_input(href,href_list) - if(filter.get("eject")) - go_out() - if(filter.get("view_stats")) - chassis.occupant << browse(get_occupant_stats(),"window=msleeper") - onclose(chassis.occupant, "msleeper") - return - if(filter.get("inject")) - inject_reagent(filter.getType("inject",/datum/reagent),filter.getObj("source")) - return - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_stats() - if(!occupant) - return - return {" - - [occupant] statistics - - - - -

                      Health statistics

                      -
                      - [get_occupant_dam()] -
                      -

                      Reagents in bloodstream

                      -
                      - [get_occupant_reagents()] -
                      -
                      - [get_available_reagents()] -
                      - - "} - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_dam() - var/t1 - switch(occupant.stat) - if(0) - t1 = "Conscious" - if(1) - t1 = "Unconscious" - if(2) - t1 = "*dead*" - else - t1 = "Unknown" - return {"Health: [occupant.health]% ([t1])
                      - Core Temperature: [src.occupant.bodytemperature-T0C]°C ([src.occupant.bodytemperature*1.8-459.67]°F)
                      - Brute Damage: [occupant.getBruteLoss()]%
                      - Respiratory Damage: [occupant.getOxyLoss()]%
                      - Toxin Content: [occupant.getToxLoss()]%
                      - Burn Severity: [occupant.getFireLoss()]%
                      - "} - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_reagents() - if(occupant.reagents) - for(var/datum/reagent/R in occupant.reagents.reagent_list) - if(R.volume > 0) - . += "[R]: [round(R.volume,0.01)]
                      " - return . || "None" - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_available_reagents() - var/output - var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun) in chassis - if(SG && SG.reagents && islist(SG.reagents.reagent_list)) - for(var/datum/reagent/R in SG.reagents.reagent_list) - if(R.volume > 0) - output += "Inject [R.name]
                      " - return output - - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/inject_reagent(var/datum/reagent/R,var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG) - if(!R || !occupant || !SG || !(SG in chassis.equipment)) - return 0 - var/to_inject = min(R.volume, inject_amount) - if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2) - occupant_message("Injecting [occupant] with [to_inject] units of [R.name].") - log_message("Injecting [occupant] with [to_inject] units of [R.name].") - SG.reagents.trans_id_to(occupant,R.id,to_inject) - update_equip_info() - return - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/update_equip_info() - if(..()) - send_byjax(chassis.occupant,"msleeper.browser","lossinfo",get_occupant_dam()) - send_byjax(chassis.occupant,"msleeper.browser","reagents",get_occupant_reagents()) - send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents()) - return 1 - return - -/datum/global_iterator/mech_sleeper/process(var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S) - if(!S.chassis) - S.set_ready_state(1) - return stop() - if(!S.chassis.has_charge(S.energy_drain)) - S.set_ready_state(1) - S.log_message("Deactivated.") - S.occupant_message("[src] deactivated - no power.") - return stop() - var/mob/living/carbon/M = S.occupant - if(!M) - return - if(M.health > 0) - M.adjustOxyLoss(-1) - M.updatehealth() - M.AdjustStunned(-4) - M.AdjustWeakened(-4) - M.AdjustStunned(-4) - M.Paralyse(2) - M.Weaken(2) - M.Stun(2) - if(M.reagents.get_reagent_amount("inaprovaline") < 5) - M.reagents.add_reagent("inaprovaline", 5) - S.chassis.use_power(S.energy_drain) - S.update_equip_info() - return - - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer //why the fuck is this under medical_tools? - name = "Cable Layer" - icon_state = "mecha_wire" - var/datum/event/event - var/turf/old_turf - var/obj/structure/cable/last_piece - var/obj/item/stack/cable_coil/cable - var/max_cable = 1000 - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/New() - cable = new(src) - cable.amount = 0 - ..() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/can_attach(obj/mecha/working/M) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/attach() - ..() - event = chassis.events.addEvent("onMove",src,"layCable") - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/detach() - chassis.events.clearEvent("onMove",event) - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/destroy() - chassis.events.clearEvent("onMove",event) - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/action(var/obj/item/stack/cable_coil/target) - if(!action_checks(target)) - return - var/result = load_cable(target) - var/message - if(isnull(result)) - message = "Unable to load [target] - no cable found." - else if(!result) - message = "Reel is full." - else - message = "[result] meters of cable successfully loaded." - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - occupant_message(message) - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/Topic(href,href_list) - ..() - if(href_list["toggle"]) - set_ready_state(!equip_ready) - occupant_message("[src] [equip_ready?"dea":"a"]ctivated.") - log_message("[equip_ready?"Dea":"A"]ctivated.") - return - if(href_list["cut"]) - if(cable && cable.amount) - var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1) - m = min(m, cable.amount) - if(m) - use_cable(m) - var/obj/item/stack/cable_coil/CC = getFromPool(/obj/item/stack/cable_coil, get_turf(chassis)) - CC.amount = m - else - occupant_message("There's no more cable on the reel.") - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/get_equip_info() - var/output = ..() - if(output) - return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]" - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/load_cable(var/obj/item/stack/cable_coil/CC) - if(istype(CC) && CC.amount) - var/cur_amount = cable? cable.amount : 0 - var/to_load = max(max_cable - cur_amount,0) - if(to_load) - to_load = min(CC.amount, to_load) - if(!cable) - cable = getFromPool(/obj/item/stack/cable_coil, src) - cable.amount = 0 - cable.amount += to_load - CC.use(to_load) - return to_load - else - return 0 - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/use_cable(amount) - if(!cable || cable.amount<1) - set_ready_state(1) - occupant_message("Cable depleted, [src] deactivated.") - log_message("Cable depleted, [src] deactivated.") - return - if(cable.amount < amount) - occupant_message("No enough cable to finish the task.") - return - cable.use(amount) - update_equip_info() - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/reset() - last_piece = null - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/dismantleFloor(var/turf/new_turf) - if(istype(new_turf, /turf/simulated/floor)) - var/turf/simulated/floor/T = new_turf - if(!T.is_plating()) - if(!T.broken && !T.burnt) - new T.floor_tile.type(T) - T.make_plating() - return !new_turf.intact - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(var/turf/new_turf) - if(equip_ready || !istype(new_turf) || !dismantleFloor(new_turf)) - return reset() - var/fdirn = turn(chassis.dir,180) - for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already - if(LC.d1 == fdirn || LC.d2 == fdirn) - return reset() - if(!use_cable(1)) - return reset() - var/obj/structure/cable/NC = getFromPool(/obj/structure/cable, new_turf) - NC.cableColor("red") - NC.d1 = 0 - NC.d2 = fdirn - NC.update_icon() - - var/datum/powernet/PN - if(last_piece && last_piece.d2 != chassis.dir) - last_piece.d1 = min(last_piece.d2, chassis.dir) - last_piece.d2 = max(last_piece.d2, chassis.dir) - last_piece.update_icon() - PN = last_piece.powernet - - if(!PN) - PN = new() - NC.powernet = PN - PN.cables += NC - NC.mergeConnectedNetworks(NC.d2) - - //NC.mergeConnectedNetworksOnTurf() - last_piece = NC - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun - name = "Exosuit-Mounted Syringe Gun" - desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)" - icon = 'icons/obj/gun.dmi' - icon_state = "syringegun" - var/list/syringes - var/list/known_reagents - var/list/processed_reagents - var/max_syringes = 10 - var/max_volume = 75 //max reagent volume - var/synth_speed = 5 //[num] reagent units per cycle - energy_drain = 10 - var/mode = 0 //0 - fire syringe, 1 - analyze reagents. - var/datum/global_iterator/mech_synth/synth - range = MELEE|RANGED - equip_cooldown = 10 - origin_tech = "materials=3;biotech=4;magnets=4;programming=3" - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/New() - ..() - flags |= NOREACT - syringes = new - known_reagents = list("inaprovaline"="Inaprovaline","anti_toxin"="Anti-Toxin (Dylovene)") - processed_reagents = new - create_reagents(max_volume) - synth = new (list(src),0) - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/detach() - synth.stop() - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/critfail() - ..() - flags &= ~NOREACT - return - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/can_attach(obj/mecha/medical/M) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/get_equip_info() - var/output = ..() - if(output) - return "[output] \[[mode? "Analyze" : "Launch"]\]
                      \[Syringes: [syringes.len]/[max_syringes] | Reagents: [reagents.total_volume]/[reagents.maximum_volume]\]
                      Reagents list" - return - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/action(atom/movable/target) - if(!action_checks(target)) - return - if(istype(target,/obj/item/weapon/reagent_containers/syringe)) - return load_syringe(target) - if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes - for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents) - load_syringe(S) - return - if(mode) - return analyze_reagents(target) - if(!syringes.len) - occupant_message("No syringes loaded.") - return - if(reagents.total_volume<=0) - occupant_message("No available reagents to load syringe with.") - return - set_ready_state(0) - chassis.use_power(energy_drain) - var/turf/trg = get_turf(target) - var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] - S.forceMove(get_turf(chassis)) - reagents.trans_to(S, min(S.volume, reagents.total_volume)) - syringes -= S - S.icon = 'icons/obj/chemical.dmi' - S.icon_state = "syringeproj" - playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1) - log_message("Launched [S] from [src], targeting [target].") - spawn(-1) - src = null //if src is deleted, still process the syringe - for(var/i=0, i<6, i++) - if(!S) - break - if(step_towards(S,trg)) - var/list/mobs = new - for(var/mob/living/carbon/M in S.loc) - mobs += M - var/mob/living/carbon/M = safepick(mobs) - if(M) - S.icon_state = initial(S.icon_state) - S.icon = initial(S.icon) - S.reagents.trans_to(M, S.reagents.total_volume) - M.take_organ_damage(2) - S.visible_message(" [M] was hit by the syringe!") - break - else if(S.loc == trg) - S.icon_state = initial(S.icon_state) - S.icon = initial(S.icon) - S.update_icon() - break - else - S.icon_state = initial(S.icon_state) - S.icon = initial(S.icon) - S.update_icon() - break - sleep(1) - do_after_cooldown() - return 1 - - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/Topic(href,href_list) - ..() - var/datum/topic_input/filter = new (href,href_list) - if(filter.get("toggle_mode")) - mode = !mode - update_equip_info() - return - if(filter.get("select_reagents")) - processed_reagents.len = 0 - var/m = 0 - var/message - for(var/i=1 to known_reagents.len) - if(m>=synth_speed) - break - var/reagent = filter.get("reagent_[i]") - if(reagent && (reagent in known_reagents)) - message = "[m ? ", " : null][known_reagents[reagent]]" - processed_reagents += reagent - m++ - if(processed_reagents.len) - message += " added to production" - synth.start() - occupant_message(message) - occupant_message("Reagent processing started.") - log_message("Reagent processing started.") - return - if(filter.get("show_reagents")) - chassis.occupant << browse(get_reagents_page(),"window=msyringegun") - if(filter.get("purge_reagent")) - var/reagent = filter.get("purge_reagent") - if(reagent) - reagents.del_reagent(reagent) - return - if(filter.get("purge_all")) - reagents.clear_reagents() - return - return - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_page() - var/output = {" - - Reagent Synthesizer - - - - -

                      Current reagents:

                      -
                      - [get_current_reagents()] -
                      -

                      Reagents production:

                      -
                      - [get_reagents_form()] -
                      - - - "} - return output - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_form() - var/r_list = get_reagents_list() - var/inputs - if(r_list) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\equipment\tools\\medical_tools.dm:567: inputs += "" - inputs += {" - - "} - // END AUTOFIX - var/output = {"
                      - [r_list || "No known reagents"] - [inputs] -
                      - [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null] - "} - return output - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_list() - var/output - for(var/i=1 to known_reagents.len) - var/reagent_id = known_reagents[i] - output += {" [known_reagents[reagent_id]]
                      "} - return output - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_current_reagents() - var/output - for(var/datum/reagent/R in reagents.reagent_list) - if(R.volume > 0) - output += "[R]: [round(R.volume,0.001)] - Purge Reagent
                      " - if(output) - output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All" - return output || "None" - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S) - if(syringes.len= 2) - occupant_message("The syringe is too far away.") - return 0 - for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows) - if(!(D.CanPass(S,src.loc))) - occupant_message("Unable to load syringe.") - return 0 - for(var/obj/machinery/door/D in S.loc)//Checks for doors - if(!(D.CanPass(S,src.loc))) - occupant_message("Unable to load syringe.") - return 0 - S.reagents.trans_to(src, S.reagents.total_volume) - S.forceMove(src) - syringes += S - occupant_message("Syringe loaded.") - update_equip_info() - return 1 - occupant_message("The [src] syringe chamber is full.") - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/analyze_reagents(atom/A) - if(get_dist(src,A) >= 4) - occupant_message("The object is too far away.") - return 0 - if(!A.reagents || istype(A,/mob)) - occupant_message("No reagent info gained from [A].") - return 0 - occupant_message("Analyzing reagents...") - for(var/datum/reagent/R in A.reagents.reagent_list) - if(R.reagent_state == 2 && add_known_reagent(R.id,R.name)) - occupant_message("Reagent analyzed, identified as [R.name] and added to database.") - send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) - occupant_message("Analyzis complete.") - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/add_known_reagent(r_id,r_name) - set_ready_state(0) - do_after_cooldown() - if(!(r_id in known_reagents)) - known_reagents += r_id - known_reagents[r_id] = r_name - return 1 - return 0 - - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/update_equip_info() - if(..()) - send_byjax(chassis.occupant,"msyringegun.browser","reagents",get_current_reagents()) - send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) - return 1 - return - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/on_reagent_change() - ..() - update_equip_info() - return - -/datum/global_iterator/mech_synth - delay = 100 - -/datum/global_iterator/mech_synth/process(var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/S) - if(!S.chassis) - return stop() - var/energy_drain = S.energy_drain*10 - if(!S.processed_reagents.len || S.reagents.total_volume >= S.reagents.maximum_volume || !S.chassis.has_charge(energy_drain)) - S.occupant_message("Reagent processing stopped.") - S.log_message("Reagent processing stopped.") - return stop() - if(anyprob(S.reliability)) - S.critfail() - var/amount = S.synth_speed / S.processed_reagents.len - for(var/reagent in S.processed_reagents) - S.reagents.add_reagent(reagent,amount) - S.chassis.use_power(energy_drain) - return 1 +/obj/item/mecha_parts/mecha_equipment/tool/sleeper + name = "Mounted Sleeper" + desc = "Mounted Sleeper. (Can be attached to: Medical Exosuits)" + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "sleeper_0" + origin_tech = "programming=2;biotech=3" + energy_drain = 20 + range = MELEE + reliability = 1000 + equip_cooldown = 20 + var/mob/living/carbon/occupant = null + var/datum/global_iterator/pr_mech_sleeper + var/inject_amount = 10 + salvageable = 0 + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/can_attach(obj/mecha/medical/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/New() + ..() + pr_mech_sleeper = new /datum/global_iterator/mech_sleeper(list(src),0) + pr_mech_sleeper.set_delay(equip_cooldown) + return + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/allow_drop() + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/destroy() + for(var/atom/movable/AM in src) + AM.forceMove(get_turf(src)) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Exit(atom/movable/O) + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/action(var/mob/living/carbon/target) + if(!action_checks(target)) + return + if(!istype(target)) + return + if(target.abiotic()) + occupant_message("Subject cannot have abiotic items on.") //Leaving this one in for balance concerns + if(target.locked_to) + occupant_message("[target] will not fit into the sleeper because they are buckled to [target.locked_to].") + return + if(occupant) + occupant_message("The sleeper is already occupied") + return + for(var/mob/living/carbon/slime/M in range(1,target)) + if(M.Victim == target) + occupant_message("[target] will not fit into the sleeper because they have a slime latched onto their head.") + return + occupant_message("You start putting [target] into [src].") + chassis.visible_message("[chassis] starts putting [target] into the [src].") + var/C = chassis.loc + var/T = target.loc + if(do_after_cooldown(target,2) && chassis.Adjacent(target)) + if(chassis.loc!=C || target.loc!=T) + return + if(occupant) + occupant_message("The sleeper is already occupied!") + return + target.forceMove(src) + occupant = target + target.reset_view(src) + /* + if(target.client) + target.client.perspective = EYE_PERSPECTIVE + target.client.eye = chassis + */ + set_ready_state(0) + pr_mech_sleeper.start() + occupant_message("[target] successfully loaded into [src]. Life support functions engaged.") + chassis.visible_message("[chassis] loads [target] into [src].") + log_message("[target] loaded. Life support functions engaged.") + return + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/go_out() + if(!occupant) + return + occupant.forceMove(get_turf(src)) + occupant_message("[occupant] ejected. Life support functions disabled.") + log_message("[occupant] ejected. Life support functions disabled.") + occupant.reset_view() + /* + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + */ + occupant = null + pr_mech_sleeper.stop() + set_ready_state(1) + + chassis.empty_bad_contents() + + return + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/detach() + if(occupant) + occupant_message("Unable to detach [src] - equipment occupied.") + return + pr_mech_sleeper.stop() + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/get_equip_info() + var/output = ..() + if(output) + var/temp = "" + if(occupant) + temp = "
                      \[Occupant: [occupant] (Health: [occupant.health]%)\]
                      View stats|Eject" + return "[output] [temp]" + return + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/Topic(href,href_list) + ..() + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) + if(filter.get("eject")) + go_out() + if(filter.get("view_stats")) + chassis.occupant << browse(get_occupant_stats(),"window=msleeper") + onclose(chassis.occupant, "msleeper") + return + if(filter.get("inject")) + inject_reagent(filter.getType("inject",/datum/reagent),filter.getObj("source")) + return + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_stats() + if(!occupant) + return + return {" + + [occupant] statistics + + + + +

                      Health statistics

                      +
                      + [get_occupant_dam()] +
                      +

                      Reagents in bloodstream

                      +
                      + [get_occupant_reagents()] +
                      +
                      + [get_available_reagents()] +
                      + + "} + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_dam() + var/t1 + switch(occupant.stat) + if(0) + t1 = "Conscious" + if(1) + t1 = "Unconscious" + if(2) + t1 = "*dead*" + else + t1 = "Unknown" + return {"Health: [occupant.health]% ([t1])
                      + Core Temperature: [src.occupant.bodytemperature-T0C]°C ([src.occupant.bodytemperature*1.8-459.67]°F)
                      + Brute Damage: [occupant.getBruteLoss()]%
                      + Respiratory Damage: [occupant.getOxyLoss()]%
                      + Toxin Content: [occupant.getToxLoss()]%
                      + Burn Severity: [occupant.getFireLoss()]%
                      + "} + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_occupant_reagents() + if(occupant.reagents) + for(var/datum/reagent/R in occupant.reagents.reagent_list) + if(R.volume > 0) + . += "[R]: [round(R.volume,0.01)]
                      " + return . || "None" + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/get_available_reagents() + var/output + var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun) in chassis + if(SG && SG.reagents && islist(SG.reagents.reagent_list)) + for(var/datum/reagent/R in SG.reagents.reagent_list) + if(R.volume > 0) + output += "Inject [R.name]
                      " + return output + + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/proc/inject_reagent(var/datum/reagent/R,var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG) + if(!R || !occupant || !SG || !(SG in chassis.equipment)) + return 0 + var/to_inject = min(R.volume, inject_amount) + if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2) + occupant_message("Injecting [occupant] with [to_inject] units of [R.name].") + log_message("Injecting [occupant] with [to_inject] units of [R.name].") + SG.reagents.trans_id_to(occupant,R.id,to_inject) + update_equip_info() + return + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/update_equip_info() + if(..()) + send_byjax(chassis.occupant,"msleeper.browser","lossinfo",get_occupant_dam()) + send_byjax(chassis.occupant,"msleeper.browser","reagents",get_occupant_reagents()) + send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents()) + return 1 + return + +/datum/global_iterator/mech_sleeper/process(var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S) + if(!S.chassis) + S.set_ready_state(1) + return stop() + if(!S.chassis.has_charge(S.energy_drain)) + S.set_ready_state(1) + S.log_message("Deactivated.") + S.occupant_message("[src] deactivated - no power.") + return stop() + var/mob/living/carbon/M = S.occupant + if(!M) + return + if(M.health > 0) + M.adjustOxyLoss(-1) + M.updatehealth() + M.AdjustStunned(-4) + M.AdjustWeakened(-4) + M.AdjustStunned(-4) + M.Paralyse(2) + M.Weaken(2) + M.Stun(2) + if(M.reagents.get_reagent_amount("inaprovaline") < 5) + M.reagents.add_reagent("inaprovaline", 5) + S.chassis.use_power(S.energy_drain) + S.update_equip_info() + return + + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer //why the fuck is this under medical_tools? + name = "Cable Layer" + icon_state = "mecha_wire" + var/datum/event/event + var/turf/old_turf + var/obj/structure/cable/last_piece + var/obj/item/stack/cable_coil/cable + var/max_cable = 1000 + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/New() + cable = new(src) + cable.amount = 0 + ..() + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/can_attach(obj/mecha/working/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/attach() + ..() + event = chassis.events.addEvent("onMove",src,"layCable") + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/detach() + chassis.events.clearEvent("onMove",event) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/destroy() + chassis.events.clearEvent("onMove",event) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/action(var/obj/item/stack/cable_coil/target) + if(!action_checks(target)) + return + var/result = load_cable(target) + var/message + if(isnull(result)) + message = "Unable to load [target] - no cable found." + else if(!result) + message = "Reel is full." + else + message = "[result] meters of cable successfully loaded." + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + occupant_message(message) + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/Topic(href,href_list) + ..() + if(href_list["toggle"]) + set_ready_state(!equip_ready) + occupant_message("[src] [equip_ready?"dea":"a"]ctivated.") + log_message("[equip_ready?"Dea":"A"]ctivated.") + return + if(href_list["cut"]) + if(cable && cable.amount) + var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1) + m = min(m, cable.amount) + if(m) + use_cable(m) + var/obj/item/stack/cable_coil/CC = getFromPool(/obj/item/stack/cable_coil, get_turf(chassis)) + CC.amount = m + else + occupant_message("There's no more cable on the reel.") + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/get_equip_info() + var/output = ..() + if(output) + return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]" + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/load_cable(var/obj/item/stack/cable_coil/CC) + if(istype(CC) && CC.amount) + var/cur_amount = cable? cable.amount : 0 + var/to_load = max(max_cable - cur_amount,0) + if(to_load) + to_load = min(CC.amount, to_load) + if(!cable) + cable = getFromPool(/obj/item/stack/cable_coil, src) + cable.amount = 0 + cable.amount += to_load + CC.use(to_load) + return to_load + else + return 0 + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/use_cable(amount) + if(!cable || cable.amount<1) + set_ready_state(1) + occupant_message("Cable depleted, [src] deactivated.") + log_message("Cable depleted, [src] deactivated.") + return + if(cable.amount < amount) + occupant_message("No enough cable to finish the task.") + return + cable.use(amount) + update_equip_info() + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/reset() + last_piece = null + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/dismantleFloor(var/turf/new_turf) + if(istype(new_turf, /turf/simulated/floor)) + var/turf/simulated/floor/T = new_turf + if(!T.is_plating()) + if(!T.broken && !T.burnt) + new T.floor_tile.type(T) + T.make_plating() + return !new_turf.intact + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(var/turf/new_turf) + if(equip_ready || !istype(new_turf) || !dismantleFloor(new_turf)) + return reset() + var/fdirn = turn(chassis.dir,180) + for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already + if(LC.d1 == fdirn || LC.d2 == fdirn) + return reset() + if(!use_cable(1)) + return reset() + var/obj/structure/cable/NC = getFromPool(/obj/structure/cable, new_turf) + NC.cableColor("red") + NC.d1 = 0 + NC.d2 = fdirn + NC.update_icon() + + var/datum/powernet/PN + if(last_piece && last_piece.d2 != chassis.dir) + last_piece.d1 = min(last_piece.d2, chassis.dir) + last_piece.d2 = max(last_piece.d2, chassis.dir) + last_piece.update_icon() + PN = last_piece.powernet + + if(!PN) + PN = new() + NC.powernet = PN + PN.cables += NC + NC.mergeConnectedNetworks(NC.d2) + + //NC.mergeConnectedNetworksOnTurf() + last_piece = NC + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun + name = "Exosuit-Mounted Syringe Gun" + desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)" + icon = 'icons/obj/gun.dmi' + icon_state = "syringegun" + var/list/syringes + var/list/known_reagents + var/list/processed_reagents + var/max_syringes = 10 + var/max_volume = 75 //max reagent volume + var/synth_speed = 5 //[num] reagent units per cycle + energy_drain = 10 + var/mode = 0 //0 - fire syringe, 1 - analyze reagents. + var/datum/global_iterator/mech_synth/synth + range = MELEE|RANGED + equip_cooldown = 10 + origin_tech = "materials=3;biotech=4;magnets=4;programming=3" + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/New() + ..() + flags |= NOREACT + syringes = new + known_reagents = list("inaprovaline"="Inaprovaline","anti_toxin"="Anti-Toxin (Dylovene)") + processed_reagents = new + create_reagents(max_volume) + synth = new (list(src),0) + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/detach() + synth.stop() + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/critfail() + ..() + flags &= ~NOREACT + return + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/can_attach(obj/mecha/medical/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/get_equip_info() + var/output = ..() + if(output) + return "[output] \[[mode? "Analyze" : "Launch"]\]
                      \[Syringes: [syringes.len]/[max_syringes] | Reagents: [reagents.total_volume]/[reagents.maximum_volume]\]
                      Reagents list" + return + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/action(atom/movable/target) + if(!action_checks(target)) + return + if(istype(target,/obj/item/weapon/reagent_containers/syringe)) + return load_syringe(target) + if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes + for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents) + load_syringe(S) + return + if(mode) + return analyze_reagents(target) + if(!syringes.len) + occupant_message("No syringes loaded.") + return + if(reagents.total_volume<=0) + occupant_message("No available reagents to load syringe with.") + return + set_ready_state(0) + chassis.use_power(energy_drain) + var/turf/trg = get_turf(target) + var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] + S.forceMove(get_turf(chassis)) + reagents.trans_to(S, min(S.volume, reagents.total_volume)) + syringes -= S + S.icon = 'icons/obj/chemical.dmi' + S.icon_state = "syringeproj" + playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1) + log_message("Launched [S] from [src], targeting [target].") + spawn(-1) + src = null //if src is deleted, still process the syringe + for(var/i=0, i<6, i++) + if(!S) + break + if(step_towards(S,trg)) + var/list/mobs = new + for(var/mob/living/carbon/M in S.loc) + mobs += M + var/mob/living/carbon/M = safepick(mobs) + if(M) + S.icon_state = initial(S.icon_state) + S.icon = initial(S.icon) + S.reagents.trans_to(M, S.reagents.total_volume) + M.take_organ_damage(2) + S.visible_message(" [M] was hit by the syringe!") + break + else if(S.loc == trg) + S.icon_state = initial(S.icon_state) + S.icon = initial(S.icon) + S.update_icon() + break + else + S.icon_state = initial(S.icon_state) + S.icon = initial(S.icon) + S.update_icon() + break + sleep(1) + do_after_cooldown() + return 1 + + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/Topic(href,href_list) + ..() + var/datum/topic_input/filter = new (href,href_list) + if(filter.get("toggle_mode")) + mode = !mode + update_equip_info() + return + if(filter.get("select_reagents")) + processed_reagents.len = 0 + var/m = 0 + var/message + for(var/i=1 to known_reagents.len) + if(m>=synth_speed) + break + var/reagent = filter.get("reagent_[i]") + if(reagent && (reagent in known_reagents)) + message = "[m ? ", " : null][known_reagents[reagent]]" + processed_reagents += reagent + m++ + if(processed_reagents.len) + message += " added to production" + synth.start() + occupant_message(message) + occupant_message("Reagent processing started.") + log_message("Reagent processing started.") + return + if(filter.get("show_reagents")) + chassis.occupant << browse(get_reagents_page(),"window=msyringegun") + if(filter.get("purge_reagent")) + var/reagent = filter.get("purge_reagent") + if(reagent) + reagents.del_reagent(reagent) + return + if(filter.get("purge_all")) + reagents.clear_reagents() + return + return + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_page() + var/output = {" + + Reagent Synthesizer + + + + +

                      Current reagents:

                      +
                      + [get_current_reagents()] +
                      +

                      Reagents production:

                      +
                      + [get_reagents_form()] +
                      + + + "} + return output + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_form() + var/r_list = get_reagents_list() + var/inputs + if(r_list) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\equipment\tools\\medical_tools.dm:567: inputs += "" + inputs += {" + + "} + // END AUTOFIX + var/output = {"
                      + [r_list || "No known reagents"] + [inputs] +
                      + [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null] + "} + return output + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_reagents_list() + var/output + for(var/i=1 to known_reagents.len) + var/reagent_id = known_reagents[i] + output += {" [known_reagents[reagent_id]]
                      "} + return output + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/get_current_reagents() + var/output + for(var/datum/reagent/R in reagents.reagent_list) + if(R.volume > 0) + output += "[R]: [round(R.volume,0.001)] - Purge Reagent
                      " + if(output) + output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All" + return output || "None" + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S) + if(syringes.len= 2) + occupant_message("The syringe is too far away.") + return 0 + for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows) + if(!(D.CanPass(S,src.loc))) + occupant_message("Unable to load syringe.") + return 0 + for(var/obj/machinery/door/D in S.loc)//Checks for doors + if(!(D.CanPass(S,src.loc))) + occupant_message("Unable to load syringe.") + return 0 + S.reagents.trans_to(src, S.reagents.total_volume) + S.forceMove(src) + syringes += S + occupant_message("Syringe loaded.") + update_equip_info() + return 1 + occupant_message("The [src] syringe chamber is full.") + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/analyze_reagents(atom/A) + if(get_dist(src,A) >= 4) + occupant_message("The object is too far away.") + return 0 + if(!A.reagents || istype(A,/mob)) + occupant_message("No reagent info gained from [A].") + return 0 + occupant_message("Analyzing reagents...") + for(var/datum/reagent/R in A.reagents.reagent_list) + if(R.reagent_state == 2 && add_known_reagent(R.id,R.name)) + occupant_message("Reagent analyzed, identified as [R.name] and added to database.") + send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) + occupant_message("Analyzis complete.") + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/proc/add_known_reagent(r_id,r_name) + set_ready_state(0) + do_after_cooldown() + if(!(r_id in known_reagents)) + known_reagents += r_id + known_reagents[r_id] = r_name + return 1 + return 0 + + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/update_equip_info() + if(..()) + send_byjax(chassis.occupant,"msyringegun.browser","reagents",get_current_reagents()) + send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) + return 1 + return + +/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/on_reagent_change() + ..() + update_equip_info() + return + +/datum/global_iterator/mech_synth + delay = 100 + +/datum/global_iterator/mech_synth/process(var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/S) + if(!S.chassis) + return stop() + var/energy_drain = S.energy_drain*10 + if(!S.processed_reagents.len || S.reagents.total_volume >= S.reagents.maximum_volume || !S.chassis.has_charge(energy_drain)) + S.occupant_message("Reagent processing stopped.") + S.log_message("Reagent processing stopped.") + return stop() + if(anyprob(S.reliability)) + S.critfail() + var/amount = S.synth_speed / S.processed_reagents.len + for(var/reagent in S.processed_reagents) + S.reagents.add_reagent(reagent,amount) + S.chassis.use_power(energy_drain) + return 1 diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 4c0699827f4..8d253427739 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -1,1279 +1,1279 @@ -#define MECHDRILL_SAND_SPEED 2 -#define MECHDRILL_ROCK_SPEED 3 - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp - name = "\improper Hydraulic Clamp" - icon_state = "mecha_clamp" - equip_cooldown = 15 - energy_drain = 10 - var/dam_force = 20 - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/attach(obj/mecha/M as obj) - ..() - if(istype(chassis, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/R = chassis - R.hydraulic_clamp = src - return - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/detach() - ..() - if(istype(chassis, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/R = chassis - R.hydraulic_clamp = null - return - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target) - if(!action_checks(target)) return - if(!istype(chassis, /obj/mecha/working/ripley)) return - var/obj/mecha/working/ripley/R = chassis - - if(istype(target, /obj/structure/bed)) - occupant_message("Safety features prevent this action.") - return //no picking up rollerbeds - var/list/living_in_target = target.search_contents_for(/mob/living) - if(living_in_target.len) //no picking up lockers with people in them - occupant_message("Safety features prevent this action.") - return - - if(istype(target,/obj)) - var/obj/O = target - if (istype(O, /obj/machinery/door/firedoor)) - var/obj/machinery/door/firedoor/FD = O - if (!FD.operating) - FD.force_open(chassis.occupant, src) - return - if(!O.anchored) - if(istype(O, /obj/item/weapon/ore) && R.ore_box) - var/count = 0 - for(var/obj/item/weapon/ore/I in get_turf(target)) - if(I.material) - R.ore_box.materials.addAmount(I.material, 1) - returnToPool(I) - count++ - if(count) - log_message("Loaded [count] ore into compatible ore box.") - occupant_message("[count] ore successfully loaded into cargo compartment.") - chassis.visible_message("[chassis] scoops up the ore from the ground and loads it into cargo compartment.") - else if(R.cargo.len < R.cargo_capacity) - occupant_message("You lift [target] and start to load it into cargo compartment.") - chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.") - set_ready_state(0) - chassis.use_power(energy_drain) - O.anchored = 1 //Why - var/T = chassis.loc - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - R.cargo += O - O.loc = chassis - if(!R.ore_box && istype(O, /obj/structure/ore_box)) - R.ore_box = O - O.anchored = 0 //Why? - occupant_message("[target] succesfully loaded.") - log_message("Loaded [O]. Cargo compartment capacity: [R.cargo_capacity - R.cargo.len]") - else - occupant_message("You must hold still while handling objects.") - O.anchored = initial(O.anchored) //WHY?? - else - occupant_message("Not enough room in cargo compartment.") - else - occupant_message("[target] is firmly secured.") - - else if(istype(target,/mob/living)) - var/mob/living/M = target - if(M.stat == DEAD) return - if(chassis.occupant.a_intent == I_HURT) - M.take_overall_damage(dam_force) - if(!M) return //we killed some sort of simple animal and the corpse was deleted. - M.adjustOxyLoss(round(dam_force/2)) - M.updatehealth() - occupant_message("You squeeze [target] with [src.name]. Something cracks.") - chassis.visible_message("[chassis] squeezes [target].") - M.attack_log +="\[[time_stamp()]\] Mech Squeezed by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" - chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Squeezed [M.name] ([M.ckey]) with [src.name]" - log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech squeezed [M.name] ([M.ckey]) with [src.name]" ) - else - step_away(M,chassis) - occupant_message("You push [target] out of the way.") - chassis.visible_message("[chassis] pushes [target] out of the way.") - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/drill - name = "\improper Exosuit-Mounted Drill" - desc = "This is the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" - icon_state = "mecha_drill" - equip_cooldown = 45 - energy_drain = 10 - force = 15 - var/dig_walls = 0 //probably a better way to do this through bitflags but I don't really know how - -/obj/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target) - if(!action_checks(target)) return - if(isobj(target)) - var/obj/target_obj = target - if(!target_obj.vars.Find("unacidable") || target_obj.unacidable) return - set_ready_state(0) - chassis.visible_message("[chassis] starts to drill [target]!", "You hear a drill.") - occupant_message("You start to drill [target]!") - var/C = chassis.loc - var/T = target.loc //why were these backwards? we may never know -Pete & Bauds, years apart - - if(istype(target, /turf/simulated/wall/invulnerable)) - occupant_message("[target] is too durable to drill through.") - - else if(istype(target, /turf/simulated/wall)) - if(dig_walls) - var/delay = istype(target, /turf/simulated/wall/r_wall) ? 10 : 2 - if(do_after_cooldown(target, delay) && C == chassis.loc && src == chassis.selected) - log_message("Drilled through [target]") - occupant_message("Your powerful drill screeches as it tears through the last of \the [target], leaving nothing but a girder!") - chassis.visible_message("[chassis] drills through \the [target]!", "You hear a drill tearing through plating.") - //target.ex_act(3) //Why - target.mech_drill_act(3) - else - if(do_after_cooldown(target, 1) && C == chassis.loc && src == chassis.selected) - occupant_message("[target] is too durable to drill through.") - - else if(istype(target, /obj/structure/girder)) - if(do_after_cooldown(target) && C == chassis.loc && src == chassis.selected) - log_message("Drilled through [target]") - occupant_message("Your drill destroys \the [target]!") - chassis.visible_message("[chassis] destroys \the [target]!", "You hear a drill breaking something.") - target.mech_drill_act(2) - - else if(istype(target, /turf/unsimulated/mineral)) - if(do_after_cooldown(target, 1/MECHDRILL_ROCK_SPEED) && C == chassis.loc && src == chassis.selected) - for(var/turf/unsimulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.GetDrilled() - log_message("Drilled through [target]") - if(istype(chassis, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/R = chassis - if(R.hydraulic_clamp && R.ore_box) - var/count = 0 - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir && ore.material) - R.ore_box.materials.addAmount(ore.material,1) - returnToPool(ore) - count++ - if(count) - occupant_message("[count] ore successfully loaded into cargo compartment.") - - else if(istype(target, /turf/unsimulated/floor/asteroid)) //Digging for sand - if(do_after_cooldown(target, 1/MECHDRILL_SAND_SPEED) && C == chassis.loc && src == chassis.selected) - var/count = 0 - var/obj/structure/ore_box/ore_box - var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/hydraulic_clamp - if(istype(chassis, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/R = chassis - ore_box = R.ore_box - hydraulic_clamp = R.hydraulic_clamp - for(var/turf/unsimulated/floor/asteroid/M in range(chassis,1)) //Get a 3x3 area around the mech - if(get_dir(chassis,M)&chassis.dir || istype(src, /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill)) //Only dig frontmost 1x3 unless the drill is diamond - M.gets_dug() - if(hydraulic_clamp && ore_box) - for(var/obj/item/weapon/ore/glass/sandore in get_turf(M)) - ore_box.materials.addAmount(sandore.material,1) - returnToPool(sandore) - count++ - log_message("Drilled through [target]") - if(count) - occupant_message("[count] sand successfully loaded into cargo compartment.") - - else - if(do_after_cooldown(target, 1) && C == chassis.loc && src == chassis.selected && target.loc == T) //also check that our target hasn't moved - if(istype(target, /mob/living)) - var/mob/living/M = target - M.attack_log +="\[[time_stamp()]\] Mech Drilled by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" - chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Drilled [M.name] ([M.ckey]) with [src.name]" - log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech drilled [M.name] ([M.ckey]) with [src.name]" ) - if(!iscarbon(chassis.occupant)) - M.LAssailant = null - else - M.LAssailant = chassis.occupant - log_message("Drilled through [target]") - occupant_message("You drill into \the [target].") - chassis.visible_message("[chassis] drills into \the [target]!", "You hear a drill breaking something.") - target.mech_drill_act(2) - - chassis.use_power(energy_drain) - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/drill/can_attach(obj/mecha/M as obj) - if(..()) - if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill - name = "\improper Exosuit-Mounted Diamond Drill" - desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" - icon_state = "mecha_diamond_drill" - origin_tech = "materials=4;engineering=3" - equip_cooldown = 15 - force = 15 - dig_walls = 1 - - //OBJECT - //ORIENTED - //PROGRAMMING - -/obj/item/mecha_parts/mecha_equipment/tool/scythe - name = "\improper Heavy Duty Pneumatic Scythe" - desc = "An extremely heavy-duty pneumatic scythe. The \"giant robot\" approach to weed control. (Can be attached to: Engineering Exosuits)" - icon_state = "mecha_extremelylazyscythecopypaste" - equip_cooldown = 20 - energy_drain = 15 - var/dam_force = 20 - -/obj/item/mecha_parts/mecha_equipment/tool/scythe/can_attach(obj/mecha/working/ripley/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/scythe/action(atom/target) - if(!action_checks(target)) return - - if(istype(target, /obj/machinery/portable_atmospherics/hydroponics)) - set_ready_state(0) - if(do_after_cooldown(target, 1/2)) - chassis.visible_message("[chassis] smashes apart \the [target]!", "You hear a pneumatic screeching and something being smashed apart.") - occupant_message("You smash apart \the [target]!") - log_message("Destroyed [target].") - var/obj/machinery/portable_atmospherics/hydroponics/tray = target - playsound(target, 'sound/mecha/mechsmash.ogg', 50, 1) - tray.smashDestroy(50) //Just to really drive it home - else if(istype(target, /obj/effect/plantsegment) || istype(target, /obj/effect/alien/weeds) || istype(target, /obj/effect/biomass)|| istype(target, /turf/simulated/floor)) - set_ready_state(0) - var/olddir = chassis.dir - var/eradicated = 0 - spawn for(var/i=1 to 4) - chassis.mechturn(turn(olddir, 90*i)) - for(var/obj/effect/E in range(chassis,i == 4 ? 2 : 1)) - if(get_dir(chassis,E)&chassis.dir || E.loc == get_turf(chassis)) //This kills vines through windows, but ehhhh - if(istype(E, /obj/effect/plantsegment)) - var/obj/effect/plantsegment/K = E - K.die_off() - eradicated++ - else if(istype(E, /obj/effect/alien/weeds) || istype(E, /obj/effect/biomass)) - qdel(E) - eradicated++ - sleep(3) - if(eradicated) - occupant_message("[eradicated] weeds successfully eradicated.") - log_message("Culled [eradicated] weeds.") - set_ready_state(1) - else if(istype(target,/mob/living)) - var/mob/living/M = target - if(M.stat == DEAD) return - if(chassis.occupant.a_intent == I_HURT) - set_ready_state(0) - M.apply_damage(dam_force, BRUTE) - occupant_message("You slash [target] with [src.name].") - chassis.visible_message("[chassis] slashes at [target] with [src.name]!") - M.attack_log +="\[[time_stamp()]\] Mech Scythed by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" - chassis.occupant.attack_log += "\[[time_stamp()]\] Slashed [M.name] ([M.ckey]) with [src.name]" - log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech scythed [M.name] ([M.ckey]) with [src.name]" ) - log_message("Slashed at [target] with [src.name].") - do_after_cooldown() - else - return 0 - chassis.use_power(energy_drain) - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher - name = "\improper Exosuit-Mounted Foam Extinguisher" - desc = "A fire extinguisher module for an exosuit. (Can be attached to: Firefighting exosuits)" - icon_state = "mecha_exting" - origin_tech = "materials=1;engineering=2" - equip_cooldown = 15 - energy_drain = 0 - range = MELEE|RANGED - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/can_attach(obj/mecha/working/ripley/firefighter/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. - if(!action_checks(target) || get_dist(chassis, target)>5) return - set_ready_state(0) - if(do_after_cooldown(target)) - if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) - var/obj/o = target - o.reagents.trans_to(src, 200) - occupant_message("Extinguisher refilled.") - playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6) - else - if(src.reagents.total_volume > 0) - playsound(chassis, 'sound/effects/extinguish.ogg', 75, 1, -3) - var/direction = get_dir(chassis,target) - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - - var/list/the_targets = list(T,T1,T2) - for(var/a=0, a<5, a++) - spawn(0) - var/datum/reagents/R = new/datum/reagents(5) - R.my_atom = src - reagents.trans_to_holder(R,1) - var/obj/effect/effect/foam/fire/W = new /obj/effect/effect/foam/fire(get_turf(chassis), R) - if(!W || !src) - return - var/turf/my_target = pick(the_targets) - for(var/b=0, b<4, b++) - var/turf/oldturf = get_turf(W) - step_towards(W,my_target) - if(!W || !W.reagents) - return - var/turf/W_turf = get_turf(W) - W.reagents.reaction(W_turf, TOUCH) - for(var/atom/atm in W_turf) - if(!W || !W.reagents) - return - W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. - if(W.reagents.has_reagent("water")) - if(isliving(atm)) // For extinguishing mobs on fire - var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X - M.ExtinguishMob() - if(atm.on_fire) // For extinguishing objects on fire - atm.extinguish() - if(atm.molten) // Molten shit. - atm.molten=0 - atm.solidify() - - var/obj/effect/effect/foam/fire/F = locate() in oldturf - if(!istype(F) && oldturf != get_turf(src)) - F = new /obj/effect/effect/foam/fire( get_turf(oldturf) , W.reagents) - - if(W.loc == my_target) - break - sleep(2) - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/get_equip_info() - return "[..()] \[[src.reagents.total_volume]\]" - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/on_reagent_change() - return - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/can_attach(obj/mecha/working/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/New() - . = ..() - create_reagents(200) - reagents.add_reagent("water", 200) - - -/obj/item/mecha_parts/mecha_equipment/jetpack - name = "\improper Exosuit-Mounted Jetpack" - desc = "Using directed ion bursts and cunning solar wind reflection technique, this device enables controlled space flight." - icon_state = "mecha_jetpack" - origin_tech = "materials=5;engineering=5;magnets=4" - equip_cooldown = 5 - energy_drain = 75 - var/wait = 0 - var/datum/effect/effect/system/trail/ion_trail - - -/obj/item/mecha_parts/mecha_equipment/jetpack/can_attach(obj/mecha/M as obj) - if(!(locate(src.type) in M.equipment) && !M.proc_res["dyndomove"]) - return ..() - -/obj/item/mecha_parts/mecha_equipment/jetpack/detach() - ..() - chassis.proc_res["dyndomove"] = null - return - -/obj/item/mecha_parts/mecha_equipment/jetpack/attach(obj/mecha/M as obj) - ..() - if(!ion_trail) - ion_trail = new /datum/effect/effect/system/trail() - ion_trail.set_up(chassis) - return - -/obj/item/mecha_parts/mecha_equipment/jetpack/proc/toggle() - if(!chassis) - return - !equip_ready? turn_off() : turn_on() - return equip_ready - -/obj/item/mecha_parts/mecha_equipment/jetpack/proc/turn_on() - set_ready_state(0) - chassis.proc_res["dyndomove"] = src - ion_trail.start() - occupant_message("Jetpack Activated.") - log_message("Jetpack Activated.") - -/obj/item/mecha_parts/mecha_equipment/jetpack/proc/turn_off() - set_ready_state(1) - chassis.proc_res["dyndomove"] = null - ion_trail.stop() - occupant_message("Jetpack Deactivated.") - log_message("Jetpack Deactivated.") - -/obj/item/mecha_parts/mecha_equipment/jetpack/proc/dyndomove(direction) - if(!action_checks()) - return chassis.dyndomove(direction) - var/move_result = 0 - if(chassis.hasInternalDamage(MECHA_INT_CONTROL_LOST)) - move_result = step_rand(chassis) - else if(chassis.dir!=direction) - chassis.dir = direction - move_result = 1 - else - move_result = step(chassis,direction) - if(chassis.occupant) - for(var/obj/effect/speech_bubble/B in range(1, chassis)) - if(B.parent == chassis.occupant) - B.loc = chassis.loc - if(move_result) - wait = 1 - chassis.use_power(energy_drain) - if(!chassis.pr_inertial_movement.active()) - chassis.pr_inertial_movement.start(list(chassis,direction)) - else - chassis.pr_inertial_movement.set_process_args(list(chassis,direction)) - do_after_cooldown() - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/jetpack/action_checks() - if(equip_ready || wait) - return 0 - if(energy_drain && !chassis.has_charge(energy_drain)) - return 0 - if(crit_fail) - return 0 - if(chassis.check_for_support()) - return 0 - return 1 - -/obj/item/mecha_parts/mecha_equipment/jetpack/get_equip_info() - if(!chassis) return - return "* [src.name] \[Toggle\]" - - -/obj/item/mecha_parts/mecha_equipment/jetpack/Topic(href,href_list) - ..() - if(href_list["toggle"]) - toggle() - -/obj/item/mecha_parts/mecha_equipment/jetpack/do_after_cooldown() - sleep(equip_cooldown) - wait = 0 - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/rcd - name = "\improper Exosuit-Mounted RCD" - desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)" - icon_state = "mecha_rcd" - origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4" - equip_cooldown = 10 - energy_drain = 250 - range = MELEE|RANGED - var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. - var/disabled = 0 //malf - -/obj/item/mecha_parts/mecha_equipment/tool/rcd/action(atom/target) - if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve - disabled = 1 - else - disabled = 0 - if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock)) - target = get_turf(target) - if(!action_checks(target) || disabled || get_dist(chassis, target)>3) return - playsound(chassis, 'sound/machines/click.ogg', 50, 1) - //meh - switch(mode) - if(0) - if (istype(target, /turf/simulated/wall)) - occupant_message("Deconstructing [target]...") - set_ready_state(0) - if(do_after_cooldown(target)) - if(disabled) return - chassis.spark_system.start() - target:ChangeTurf(/turf/simulated/floor/plating) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.use_power(energy_drain) - else if (istype(target, /turf/simulated/floor)) - occupant_message("Deconstructing [target]...") - set_ready_state(0) - if(do_after_cooldown(target)) - if(disabled) return - chassis.spark_system.start() - target:ChangeTurf(get_base_turf(target.z)) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.use_power(energy_drain) - else if (istype(target, /obj/machinery/door/airlock)) - occupant_message("Deconstructing [target]...") - set_ready_state(0) - if(do_after_cooldown(target)) - if(disabled) return - chassis.spark_system.start() - qdel(target) - target = null - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.use_power(energy_drain) - if(1) - if(istype(target, /turf/space)) - occupant_message("Building Floor...") - set_ready_state(0) - if(do_after_cooldown(target)) - if(disabled) return - target:ChangeTurf(/turf/simulated/floor/plating/airless) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.spark_system.start() - chassis.use_power(energy_drain*2) - else if(istype(target, /turf/simulated/floor)) - occupant_message("Building Wall...") - set_ready_state(0) - if(do_after_cooldown(target)) - if(disabled) return - target:ChangeTurf(/turf/simulated/wall) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.spark_system.start() - chassis.use_power(energy_drain*2) - if(2) - if(istype(target, /turf/simulated/floor)) - occupant_message("Building Airlock...") - set_ready_state(0) - if(do_after_cooldown(target)) - if(disabled) return - chassis.spark_system.start() - var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) - T.autoclose = 1 - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - playsound(target, 'sound/effects/sparks2.ogg', 50, 1) - chassis.use_power(energy_drain*2) - return - - -/obj/item/mecha_parts/mecha_equipment/tool/rcd/Topic(href,href_list) - ..() - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - switch(mode) - if(0) - occupant_message("Switched RCD to Deconstruct.") - if(1) - occupant_message("Switched RCD to Construct.") - if(2) - occupant_message("Switched RCD to Construct Airlock.") - return - -/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info() - return "[..()] \[D|C|A\]" - - - -/obj/item/mecha_parts/mecha_equipment/teleporter - name = "\improper Exosuit-Mounted Teleporter" - desc = "An exosuit module that allows exosuits to teleport to any position in view." - icon_state = "mecha_teleport" - origin_tech = "bluespace=10" - equip_cooldown = 150 - energy_drain = 1000 - range = RANGED - -/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target) - if(!action_checks(target) || src.loc.z == 2) return - var/turf/T = get_turf(target) - if(T) - set_ready_state(0) - chassis.use_power(energy_drain) - do_teleport(chassis, T, 4) - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/wormhole_generator - name = "\improper Wormhole Generator" - desc = "An exosuit module that allows generating of small quasi-stable wormholes." - icon_state = "mecha_wholegen" - origin_tech = "bluespace=3" - equip_cooldown = 50 - energy_drain = 300 - range = RANGED - - -/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target) - if(!action_checks(target) || src.loc.z == 2) return - var/list/theareas = list() - for(var/area/AR in orange(100, chassis)) - if(AR in theareas) continue - theareas += AR - if(!theareas.len) - return - var/area/thearea = pick(theareas) - var/list/L = list() - var/turf/pos = get_turf(src) - for(var/turf/T in get_area_turfs(thearea.type)) - if(!T.density && pos.z == T.z) - var/clear = 1 - for(var/obj/O in T) - if(O.density) - clear = 0 - break - if(clear) - L+=T - if(!L.len) - return - var/turf/target_turf = pick(L) - if(!target_turf) - return - chassis.use_power(energy_drain) - set_ready_state(0) - var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target)) - P.target = target_turf - P.icon = 'icons/obj/objects.dmi' - P.icon_state = "anom" - P.name = "wormhole" - do_after_cooldown() - src = null - spawn(rand(150,300)) - qdel(P) - -/obj/item/mecha_parts/mecha_equipment/gravcatapult - name = "\improper Gravitational Catapult" - desc = "An exosuit mounted Gravitational Catapult." - icon_state = "mecha_teleport" - origin_tech = "bluespace=2;magnets=3" - equip_cooldown = 10 - energy_drain = 100 - range = MELEE|RANGED - var/atom/movable/locked - var/mode = 1 //1 - gravsling 2 - gravpush - - var/last_fired = 0 //Concept stolen from guns. - var/fire_delay = 10 //Used to prevent spam-brute against humans. - -/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target) - - if(world.time >= last_fired + fire_delay) - last_fired = world.time - else - if (world.time % 3) - occupant_message("[src] is not ready to fire again!") - return 0 - - switch(mode) - if(1) - if(!action_checks(target) && !locked) return - if(!locked) - if(!istype(target) || target.anchored) - occupant_message("Unable to lock on [target]") - return - locked = target - occupant_message("Locked on [target]") - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - return - else if(target!=locked) - if(locked in view(chassis)) - locked.throw_at(target, 14, 1.5) - locked = null - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - else - locked = null - occupant_message("Lock on [locked] disengaged.") - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - if(2) - if(!action_checks(target)) return - var/list/atoms = list() - if(isturf(target)) - atoms = range(target,3) - else - atoms = orange(target,3) - for(var/atom/movable/A in atoms) - if(A.anchored) continue - spawn(0) - var/iter = 5-get_dist(A,target) - for(var/i=0 to iter) - step_away(A,target) - sleep(2) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/gravcatapult/get_equip_info() - return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]" - -/obj/item/mecha_parts/mecha_equipment/gravcatapult/Topic(href, href_list) - ..() - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - return - - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants. - name = "\improper Armor Booster Module (Close Combat Weaponry)" - desc = "Boosts exosuit armor against armed melee attacks. Requires energy to operate." - icon_state = "mecha_abooster_ccw" - origin_tech = "materials=3" - equip_cooldown = 10 - energy_drain = 50 - range = 0 - var/deflect_coeff = 1.15 - var/damage_coeff = 0.8 - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/can_attach(obj/mecha/M as obj) - if(..()) - if(!istype(M, /obj/mecha/combat/honker)) - if(!M.proc_res["dynattackby"]) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/attach(obj/mecha/M as obj) - ..() - chassis.proc_res["dynattackby"] = src - return - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/detach() - chassis.proc_res["dynattackby"] = null - ..() - return - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info() - if(!chassis) return - return "* [src.name]" - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) - if(!action_checks(user)) - return chassis.dynattackby(W,user) - chassis.log_message("Attacked by [W]. Attacker - [user]") - if(prob(chassis.deflect_chance*deflect_coeff)) +#define MECHDRILL_SAND_SPEED 2 +#define MECHDRILL_ROCK_SPEED 3 + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp + name = "\improper Hydraulic Clamp" + icon_state = "mecha_clamp" + equip_cooldown = 15 + energy_drain = 10 + var/dam_force = 20 + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/attach(obj/mecha/M as obj) + ..() + if(istype(chassis, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/R = chassis + R.hydraulic_clamp = src + return + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/detach() + ..() + if(istype(chassis, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/R = chassis + R.hydraulic_clamp = null + return + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target) + if(!action_checks(target)) return + if(!istype(chassis, /obj/mecha/working/ripley)) return + var/obj/mecha/working/ripley/R = chassis + + if(istype(target, /obj/structure/bed)) + occupant_message("Safety features prevent this action.") + return //no picking up rollerbeds + var/list/living_in_target = target.search_contents_for(/mob/living) + if(living_in_target.len) //no picking up lockers with people in them + occupant_message("Safety features prevent this action.") + return + + if(istype(target,/obj)) + var/obj/O = target + if (istype(O, /obj/machinery/door/firedoor)) + var/obj/machinery/door/firedoor/FD = O + if (!FD.operating) + FD.force_open(chassis.occupant, src) + return + if(!O.anchored) + if(istype(O, /obj/item/weapon/ore) && R.ore_box) + var/count = 0 + for(var/obj/item/weapon/ore/I in get_turf(target)) + if(I.material) + R.ore_box.materials.addAmount(I.material, 1) + returnToPool(I) + count++ + if(count) + log_message("Loaded [count] ore into compatible ore box.") + occupant_message("[count] ore successfully loaded into cargo compartment.") + chassis.visible_message("[chassis] scoops up the ore from the ground and loads it into cargo compartment.") + else if(R.cargo.len < R.cargo_capacity) + occupant_message("You lift [target] and start to load it into cargo compartment.") + chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.") + set_ready_state(0) + chassis.use_power(energy_drain) + O.anchored = 1 //Why + var/T = chassis.loc + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + R.cargo += O + O.loc = chassis + if(!R.ore_box && istype(O, /obj/structure/ore_box)) + R.ore_box = O + O.anchored = 0 //Why? + occupant_message("[target] succesfully loaded.") + log_message("Loaded [O]. Cargo compartment capacity: [R.cargo_capacity - R.cargo.len]") + else + occupant_message("You must hold still while handling objects.") + O.anchored = initial(O.anchored) //WHY?? + else + occupant_message("Not enough room in cargo compartment.") + else + occupant_message("[target] is firmly secured.") + + else if(istype(target,/mob/living)) + var/mob/living/M = target + if(M.stat == DEAD) return + if(chassis.occupant.a_intent == I_HURT) + M.take_overall_damage(dam_force) + if(!M) return //we killed some sort of simple animal and the corpse was deleted. + M.adjustOxyLoss(round(dam_force/2)) + M.updatehealth() + occupant_message("You squeeze [target] with [src.name]. Something cracks.") + chassis.visible_message("[chassis] squeezes [target].") + M.attack_log +="\[[time_stamp()]\] Mech Squeezed by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" + chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Squeezed [M.name] ([M.ckey]) with [src.name]" + log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech squeezed [M.name] ([M.ckey]) with [src.name]" ) + else + step_away(M,chassis) + occupant_message("You push [target] out of the way.") + chassis.visible_message("[chassis] pushes [target] out of the way.") + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/drill + name = "\improper Exosuit-Mounted Drill" + desc = "This is the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" + icon_state = "mecha_drill" + equip_cooldown = 45 + energy_drain = 10 + force = 15 + var/dig_walls = 0 //probably a better way to do this through bitflags but I don't really know how + +/obj/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target) + if(!action_checks(target)) return + if(isobj(target)) + var/obj/target_obj = target + if(!target_obj.vars.Find("unacidable") || target_obj.unacidable) return + set_ready_state(0) + chassis.visible_message("[chassis] starts to drill [target]!", "You hear a drill.") + occupant_message("You start to drill [target]!") + var/C = chassis.loc + var/T = target.loc //why were these backwards? we may never know -Pete & Bauds, years apart + + if(istype(target, /turf/simulated/wall/invulnerable)) + occupant_message("[target] is too durable to drill through.") + + else if(istype(target, /turf/simulated/wall)) + if(dig_walls) + var/delay = istype(target, /turf/simulated/wall/r_wall) ? 10 : 2 + if(do_after_cooldown(target, delay) && C == chassis.loc && src == chassis.selected) + log_message("Drilled through [target]") + occupant_message("Your powerful drill screeches as it tears through the last of \the [target], leaving nothing but a girder!") + chassis.visible_message("[chassis] drills through \the [target]!", "You hear a drill tearing through plating.") + //target.ex_act(3) //Why + target.mech_drill_act(3) + else + if(do_after_cooldown(target, 1) && C == chassis.loc && src == chassis.selected) + occupant_message("[target] is too durable to drill through.") + + else if(istype(target, /obj/structure/girder)) + if(do_after_cooldown(target) && C == chassis.loc && src == chassis.selected) + log_message("Drilled through [target]") + occupant_message("Your drill destroys \the [target]!") + chassis.visible_message("[chassis] destroys \the [target]!", "You hear a drill breaking something.") + target.mech_drill_act(2) + + else if(istype(target, /turf/unsimulated/mineral)) + if(do_after_cooldown(target, 1/MECHDRILL_ROCK_SPEED) && C == chassis.loc && src == chassis.selected) + for(var/turf/unsimulated/mineral/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.GetDrilled() + log_message("Drilled through [target]") + if(istype(chassis, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/R = chassis + if(R.hydraulic_clamp && R.ore_box) + var/count = 0 + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir && ore.material) + R.ore_box.materials.addAmount(ore.material,1) + returnToPool(ore) + count++ + if(count) + occupant_message("[count] ore successfully loaded into cargo compartment.") + + else if(istype(target, /turf/unsimulated/floor/asteroid)) //Digging for sand + if(do_after_cooldown(target, 1/MECHDRILL_SAND_SPEED) && C == chassis.loc && src == chassis.selected) + var/count = 0 + var/obj/structure/ore_box/ore_box + var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/hydraulic_clamp + if(istype(chassis, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/R = chassis + ore_box = R.ore_box + hydraulic_clamp = R.hydraulic_clamp + for(var/turf/unsimulated/floor/asteroid/M in range(chassis,1)) //Get a 3x3 area around the mech + if(get_dir(chassis,M)&chassis.dir || istype(src, /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill)) //Only dig frontmost 1x3 unless the drill is diamond + M.gets_dug() + if(hydraulic_clamp && ore_box) + for(var/obj/item/weapon/ore/glass/sandore in get_turf(M)) + ore_box.materials.addAmount(sandore.material,1) + returnToPool(sandore) + count++ + log_message("Drilled through [target]") + if(count) + occupant_message("[count] sand successfully loaded into cargo compartment.") + + else + if(do_after_cooldown(target, 1) && C == chassis.loc && src == chassis.selected && target.loc == T) //also check that our target hasn't moved + if(istype(target, /mob/living)) + var/mob/living/M = target + M.attack_log +="\[[time_stamp()]\] Mech Drilled by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" + chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Drilled [M.name] ([M.ckey]) with [src.name]" + log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech drilled [M.name] ([M.ckey]) with [src.name]" ) + if(!iscarbon(chassis.occupant)) + M.LAssailant = null + else + M.LAssailant = chassis.occupant + log_message("Drilled through [target]") + occupant_message("You drill into \the [target].") + chassis.visible_message("[chassis] drills into \the [target]!", "You hear a drill breaking something.") + target.mech_drill_act(2) + + chassis.use_power(energy_drain) + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/drill/can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill + name = "\improper Exosuit-Mounted Diamond Drill" + desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" + icon_state = "mecha_diamond_drill" + origin_tech = "materials=4;engineering=3" + equip_cooldown = 15 + force = 15 + dig_walls = 1 + + //OBJECT + //ORIENTED + //PROGRAMMING + +/obj/item/mecha_parts/mecha_equipment/tool/scythe + name = "\improper Heavy Duty Pneumatic Scythe" + desc = "An extremely heavy-duty pneumatic scythe. The \"giant robot\" approach to weed control. (Can be attached to: Engineering Exosuits)" + icon_state = "mecha_extremelylazyscythecopypaste" + equip_cooldown = 20 + energy_drain = 15 + var/dam_force = 20 + +/obj/item/mecha_parts/mecha_equipment/tool/scythe/can_attach(obj/mecha/working/ripley/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/scythe/action(atom/target) + if(!action_checks(target)) return + + if(istype(target, /obj/machinery/portable_atmospherics/hydroponics)) + set_ready_state(0) + if(do_after_cooldown(target, 1/2)) + chassis.visible_message("[chassis] smashes apart \the [target]!", "You hear a pneumatic screeching and something being smashed apart.") + occupant_message("You smash apart \the [target]!") + log_message("Destroyed [target].") + var/obj/machinery/portable_atmospherics/hydroponics/tray = target + playsound(target, 'sound/mecha/mechsmash.ogg', 50, 1) + tray.smashDestroy(50) //Just to really drive it home + else if(istype(target, /obj/effect/plantsegment) || istype(target, /obj/effect/alien/weeds) || istype(target, /obj/effect/biomass)|| istype(target, /turf/simulated/floor)) + set_ready_state(0) + var/olddir = chassis.dir + var/eradicated = 0 + spawn for(var/i=1 to 4) + chassis.mechturn(turn(olddir, 90*i)) + for(var/obj/effect/E in range(chassis,i == 4 ? 2 : 1)) + if(get_dir(chassis,E)&chassis.dir || E.loc == get_turf(chassis)) //This kills vines through windows, but ehhhh + if(istype(E, /obj/effect/plantsegment)) + var/obj/effect/plantsegment/K = E + K.die_off() + eradicated++ + else if(istype(E, /obj/effect/alien/weeds) || istype(E, /obj/effect/biomass)) + qdel(E) + eradicated++ + sleep(3) + if(eradicated) + occupant_message("[eradicated] weeds successfully eradicated.") + log_message("Culled [eradicated] weeds.") + set_ready_state(1) + else if(istype(target,/mob/living)) + var/mob/living/M = target + if(M.stat == DEAD) return + if(chassis.occupant.a_intent == I_HURT) + set_ready_state(0) + M.apply_damage(dam_force, BRUTE) + occupant_message("You slash [target] with [src.name].") + chassis.visible_message("[chassis] slashes at [target] with [src.name]!") + M.attack_log +="\[[time_stamp()]\] Mech Scythed by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" + chassis.occupant.attack_log += "\[[time_stamp()]\] Slashed [M.name] ([M.ckey]) with [src.name]" + log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech scythed [M.name] ([M.ckey]) with [src.name]" ) + log_message("Slashed at [target] with [src.name].") + do_after_cooldown() + else + return 0 + chassis.use_power(energy_drain) + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher + name = "\improper Exosuit-Mounted Foam Extinguisher" + desc = "A fire extinguisher module for an exosuit. (Can be attached to: Firefighting exosuits)" + icon_state = "mecha_exting" + origin_tech = "materials=1;engineering=2" + equip_cooldown = 15 + energy_drain = 0 + range = MELEE|RANGED + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/can_attach(obj/mecha/working/ripley/firefighter/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. + if(!action_checks(target) || get_dist(chassis, target)>5) return + set_ready_state(0) + if(do_after_cooldown(target)) + if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) + var/obj/o = target + o.reagents.trans_to(src, 200) + occupant_message("Extinguisher refilled.") + playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6) + else + if(src.reagents.total_volume > 0) + playsound(chassis, 'sound/effects/extinguish.ogg', 75, 1, -3) + var/direction = get_dir(chassis,target) + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T,turn(direction, 90)) + var/turf/T2 = get_step(T,turn(direction, -90)) + + var/list/the_targets = list(T,T1,T2) + for(var/a=0, a<5, a++) + spawn(0) + var/datum/reagents/R = new/datum/reagents(5) + R.my_atom = src + reagents.trans_to_holder(R,1) + var/obj/effect/effect/foam/fire/W = new /obj/effect/effect/foam/fire(get_turf(chassis), R) + if(!W || !src) + return + var/turf/my_target = pick(the_targets) + for(var/b=0, b<4, b++) + var/turf/oldturf = get_turf(W) + step_towards(W,my_target) + if(!W || !W.reagents) + return + var/turf/W_turf = get_turf(W) + W.reagents.reaction(W_turf, TOUCH) + for(var/atom/atm in W_turf) + if(!W || !W.reagents) + return + W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. + if(W.reagents.has_reagent("water")) + if(isliving(atm)) // For extinguishing mobs on fire + var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X + M.ExtinguishMob() + if(atm.on_fire) // For extinguishing objects on fire + atm.extinguish() + if(atm.molten) // Molten shit. + atm.molten=0 + atm.solidify() + + var/obj/effect/effect/foam/fire/F = locate() in oldturf + if(!istype(F) && oldturf != get_turf(src)) + F = new /obj/effect/effect/foam/fire( get_turf(oldturf) , W.reagents) + + if(W.loc == my_target) + break + sleep(2) + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/get_equip_info() + return "[..()] \[[src.reagents.total_volume]\]" + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/on_reagent_change() + return + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/can_attach(obj/mecha/working/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/New() + . = ..() + create_reagents(200) + reagents.add_reagent("water", 200) + + +/obj/item/mecha_parts/mecha_equipment/jetpack + name = "\improper Exosuit-Mounted Jetpack" + desc = "Using directed ion bursts and cunning solar wind reflection technique, this device enables controlled space flight." + icon_state = "mecha_jetpack" + origin_tech = "materials=5;engineering=5;magnets=4" + equip_cooldown = 5 + energy_drain = 75 + var/wait = 0 + var/datum/effect/effect/system/trail/ion_trail + + +/obj/item/mecha_parts/mecha_equipment/jetpack/can_attach(obj/mecha/M as obj) + if(!(locate(src.type) in M.equipment) && !M.proc_res["dyndomove"]) + return ..() + +/obj/item/mecha_parts/mecha_equipment/jetpack/detach() + ..() + chassis.proc_res["dyndomove"] = null + return + +/obj/item/mecha_parts/mecha_equipment/jetpack/attach(obj/mecha/M as obj) + ..() + if(!ion_trail) + ion_trail = new /datum/effect/effect/system/trail() + ion_trail.set_up(chassis) + return + +/obj/item/mecha_parts/mecha_equipment/jetpack/proc/toggle() + if(!chassis) + return + !equip_ready? turn_off() : turn_on() + return equip_ready + +/obj/item/mecha_parts/mecha_equipment/jetpack/proc/turn_on() + set_ready_state(0) + chassis.proc_res["dyndomove"] = src + ion_trail.start() + occupant_message("Jetpack Activated.") + log_message("Jetpack Activated.") + +/obj/item/mecha_parts/mecha_equipment/jetpack/proc/turn_off() + set_ready_state(1) + chassis.proc_res["dyndomove"] = null + ion_trail.stop() + occupant_message("Jetpack Deactivated.") + log_message("Jetpack Deactivated.") + +/obj/item/mecha_parts/mecha_equipment/jetpack/proc/dyndomove(direction) + if(!action_checks()) + return chassis.dyndomove(direction) + var/move_result = 0 + if(chassis.hasInternalDamage(MECHA_INT_CONTROL_LOST)) + move_result = step_rand(chassis) + else if(chassis.dir!=direction) + chassis.dir = direction + move_result = 1 + else + move_result = step(chassis,direction) + if(chassis.occupant) + for(var/obj/effect/speech_bubble/B in range(1, chassis)) + if(B.parent == chassis.occupant) + B.loc = chassis.loc + if(move_result) + wait = 1 + chassis.use_power(energy_drain) + if(!chassis.pr_inertial_movement.active()) + chassis.pr_inertial_movement.start(list(chassis,direction)) + else + chassis.pr_inertial_movement.set_process_args(list(chassis,direction)) + do_after_cooldown() + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/jetpack/action_checks() + if(equip_ready || wait) + return 0 + if(energy_drain && !chassis.has_charge(energy_drain)) + return 0 + if(crit_fail) + return 0 + if(chassis.check_for_support()) + return 0 + return 1 + +/obj/item/mecha_parts/mecha_equipment/jetpack/get_equip_info() + if(!chassis) return + return "* [src.name] \[Toggle\]" + + +/obj/item/mecha_parts/mecha_equipment/jetpack/Topic(href,href_list) + ..() + if(href_list["toggle"]) + toggle() + +/obj/item/mecha_parts/mecha_equipment/jetpack/do_after_cooldown() + sleep(equip_cooldown) + wait = 0 + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/rcd + name = "\improper Exosuit-Mounted RCD" + desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)" + icon_state = "mecha_rcd" + origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4" + equip_cooldown = 10 + energy_drain = 250 + range = MELEE|RANGED + var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. + var/disabled = 0 //malf + +/obj/item/mecha_parts/mecha_equipment/tool/rcd/action(atom/target) + if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve + disabled = 1 + else + disabled = 0 + if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock)) + target = get_turf(target) + if(!action_checks(target) || disabled || get_dist(chassis, target)>3) return + playsound(chassis, 'sound/machines/click.ogg', 50, 1) + //meh + switch(mode) + if(0) + if (istype(target, /turf/simulated/wall)) + occupant_message("Deconstructing [target]...") + set_ready_state(0) + if(do_after_cooldown(target)) + if(disabled) return + chassis.spark_system.start() + target:ChangeTurf(/turf/simulated/floor/plating) + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.use_power(energy_drain) + else if (istype(target, /turf/simulated/floor)) + occupant_message("Deconstructing [target]...") + set_ready_state(0) + if(do_after_cooldown(target)) + if(disabled) return + chassis.spark_system.start() + target:ChangeTurf(get_base_turf(target.z)) + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.use_power(energy_drain) + else if (istype(target, /obj/machinery/door/airlock)) + occupant_message("Deconstructing [target]...") + set_ready_state(0) + if(do_after_cooldown(target)) + if(disabled) return + chassis.spark_system.start() + qdel(target) + target = null + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.use_power(energy_drain) + if(1) + if(istype(target, /turf/space)) + occupant_message("Building Floor...") + set_ready_state(0) + if(do_after_cooldown(target)) + if(disabled) return + target:ChangeTurf(/turf/simulated/floor/plating/airless) + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.spark_system.start() + chassis.use_power(energy_drain*2) + else if(istype(target, /turf/simulated/floor)) + occupant_message("Building Wall...") + set_ready_state(0) + if(do_after_cooldown(target)) + if(disabled) return + target:ChangeTurf(/turf/simulated/wall) + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.spark_system.start() + chassis.use_power(energy_drain*2) + if(2) + if(istype(target, /turf/simulated/floor)) + occupant_message("Building Airlock...") + set_ready_state(0) + if(do_after_cooldown(target)) + if(disabled) return + chassis.spark_system.start() + var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) + T.autoclose = 1 + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + playsound(target, 'sound/effects/sparks2.ogg', 50, 1) + chassis.use_power(energy_drain*2) + return + + +/obj/item/mecha_parts/mecha_equipment/tool/rcd/Topic(href,href_list) + ..() + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + switch(mode) + if(0) + occupant_message("Switched RCD to Deconstruct.") + if(1) + occupant_message("Switched RCD to Construct.") + if(2) + occupant_message("Switched RCD to Construct Airlock.") + return + +/obj/item/mecha_parts/mecha_equipment/tool/rcd/get_equip_info() + return "[..()] \[D|C|A\]" + + + +/obj/item/mecha_parts/mecha_equipment/teleporter + name = "\improper Exosuit-Mounted Teleporter" + desc = "An exosuit module that allows exosuits to teleport to any position in view." + icon_state = "mecha_teleport" + origin_tech = "bluespace=10" + equip_cooldown = 150 + energy_drain = 1000 + range = RANGED + +/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target) + if(!action_checks(target) || src.loc.z == 2) return + var/turf/T = get_turf(target) + if(T) + set_ready_state(0) + chassis.use_power(energy_drain) + do_teleport(chassis, T, 4) + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/wormhole_generator + name = "\improper Wormhole Generator" + desc = "An exosuit module that allows generating of small quasi-stable wormholes." + icon_state = "mecha_wholegen" + origin_tech = "bluespace=3" + equip_cooldown = 50 + energy_drain = 300 + range = RANGED + + +/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target) + if(!action_checks(target) || src.loc.z == 2) return + var/list/theareas = list() + for(var/area/AR in orange(100, chassis)) + if(AR in theareas) continue + theareas += AR + if(!theareas.len) + return + var/area/thearea = pick(theareas) + var/list/L = list() + var/turf/pos = get_turf(src) + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density && pos.z == T.z) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + if(!L.len) + return + var/turf/target_turf = pick(L) + if(!target_turf) + return + chassis.use_power(energy_drain) + set_ready_state(0) + var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target)) + P.target = target_turf + P.icon = 'icons/obj/objects.dmi' + P.icon_state = "anom" + P.name = "wormhole" + do_after_cooldown() + src = null + spawn(rand(150,300)) + qdel(P) + +/obj/item/mecha_parts/mecha_equipment/gravcatapult + name = "\improper Gravitational Catapult" + desc = "An exosuit mounted Gravitational Catapult." + icon_state = "mecha_teleport" + origin_tech = "bluespace=2;magnets=3" + equip_cooldown = 10 + energy_drain = 100 + range = MELEE|RANGED + var/atom/movable/locked + var/mode = 1 //1 - gravsling 2 - gravpush + + var/last_fired = 0 //Concept stolen from guns. + var/fire_delay = 10 //Used to prevent spam-brute against humans. + +/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target) + + if(world.time >= last_fired + fire_delay) + last_fired = world.time + else + if (world.time % 3) + occupant_message("[src] is not ready to fire again!") + return 0 + + switch(mode) + if(1) + if(!action_checks(target) && !locked) return + if(!locked) + if(!istype(target) || target.anchored) + occupant_message("Unable to lock on [target]") + return + locked = target + occupant_message("Locked on [target]") + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + return + else if(target!=locked) + if(locked in view(chassis)) + locked.throw_at(target, 14, 1.5) + locked = null + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + else + locked = null + occupant_message("Lock on [locked] disengaged.") + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + if(2) + if(!action_checks(target)) return + var/list/atoms = list() + if(isturf(target)) + atoms = range(target,3) + else + atoms = orange(target,3) + for(var/atom/movable/A in atoms) + if(A.anchored) continue + spawn(0) + var/iter = 5-get_dist(A,target) + for(var/i=0 to iter) + step_away(A,target) + sleep(2) + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/gravcatapult/get_equip_info() + return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]" + +/obj/item/mecha_parts/mecha_equipment/gravcatapult/Topic(href, href_list) + ..() + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + return + + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants. + name = "\improper Armor Booster Module (Close Combat Weaponry)" + desc = "Boosts exosuit armor against armed melee attacks. Requires energy to operate." + icon_state = "mecha_abooster_ccw" + origin_tech = "materials=3" + equip_cooldown = 10 + energy_drain = 50 + range = 0 + var/deflect_coeff = 1.15 + var/damage_coeff = 0.8 + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/can_attach(obj/mecha/M as obj) + if(..()) + if(!istype(M, /obj/mecha/combat/honker)) + if(!M.proc_res["dynattackby"]) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/attach(obj/mecha/M as obj) + ..() + chassis.proc_res["dynattackby"] = src + return + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/detach() + chassis.proc_res["dynattackby"] = null + ..() + return + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info() + if(!chassis) return + return "* [src.name]" + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) + if(!action_checks(user)) + return chassis.dynattackby(W,user) + chassis.log_message("Attacked by [W]. Attacker - [user]") + if(prob(chassis.deflect_chance*deflect_coeff)) to_chat(user, "The [W] bounces off [chassis] armor.") - chassis.log_append_to_last("Armor saved.") - else - chassis.occupant_message("[user] hits [chassis] with [W].") - user.visible_message("[user] hits [chassis] with [W].", "You hit [src] with [W].") - chassis.take_damage(round(W.force*damage_coeff),W.damtype) - chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster - name = "\improper Armor Booster Module (Ranged Weaponry)" - desc = "Boosts exosuit armor against ranged attacks. Completely blocks taser shots. Requires energy to operate." - icon_state = "mecha_abooster_proj" - origin_tech = "materials=4" - equip_cooldown = 10 - energy_drain = 50 - range = 0 - var/deflect_coeff = 1.15 - var/damage_coeff = 0.8 - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/can_attach(obj/mecha/M as obj) - if(..()) - if(!istype(M, /obj/mecha/combat/honker)) - if(!M.proc_res["dynbulletdamage"] && !M.proc_res["dynhitby"]) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/attach(obj/mecha/M as obj) - ..() - chassis.proc_res["dynbulletdamage"] = src - chassis.proc_res["dynhitby"] = src - return - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/detach() - chassis.proc_res["dynbulletdamage"] = null - chassis.proc_res["dynhitby"] = null - ..() - return - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/get_equip_info() - if(!chassis) return - return "* [src.name]" - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynbulletdamage(var/obj/item/projectile/Proj) - if(!action_checks(src)) - return chassis.dynbulletdamage(Proj) - if(prob(chassis.deflect_chance*deflect_coeff)) - chassis.occupant_message("The armor deflects incoming projectile.") - chassis.visible_message("The [chassis.name] armor deflects the projectile") - chassis.log_append_to_last("Armor saved.") - else - chassis.take_damage(round(Proj.damage*src.damage_coeff),Proj.flag) - chassis.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - Proj.on_hit(chassis) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynhitby(atom/movable/A) - if(!action_checks(A)) - return chassis.dynhitby(A) - if(prob(chassis.deflect_chance*deflect_coeff) || istype(A, /mob/living) || istype(A, /obj/item/mecha_parts/mecha_tracking)) - chassis.occupant_message("The [A] bounces off the armor.") - chassis.visible_message("The [A] bounces off the [chassis] armor") - chassis.log_append_to_last("Armor saved.") - if(istype(A, /mob/living)) - var/mob/living/M = A - M.take_organ_damage(10) - else if(istype(A, /obj)) - var/obj/O = A - if(O.throwforce) - chassis.take_damage(round(O.throwforce*damage_coeff)) - chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - - -/obj/item/mecha_parts/mecha_equipment/repair_droid - name = "\improper Repair Droid Module" - desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost all types of external or internal damage." - icon_state = "repair_droid" - origin_tech = "magnets=3;programming=3" - equip_cooldown = 20 - energy_drain = 100 - range = 0 - var/health_boost = 2 - var/datum/global_iterator/pr_repair_droid - var/icon/droid_overlay - var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH) - -/obj/item/mecha_parts/mecha_equipment/repair_droid/New() - ..() - pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0) - pr_repair_droid.set_delay(equip_cooldown) - return - -/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M as obj) - ..() - droid_overlay = new(src.icon, icon_state = "repair_droid") - M.overlays += droid_overlay - return - -/obj/item/mecha_parts/mecha_equipment/repair_droid/destroy() - chassis.overlays -= droid_overlay - ..() - return - -/obj/item/mecha_parts/mecha_equipment/repair_droid/detach() - chassis.overlays -= droid_overlay - pr_repair_droid.stop() - ..() - return - -/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info() - if(!chassis) return - return "* [src.name] - [pr_repair_droid.active()?"Dea":"A"]ctivate" - -/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list) - ..() - if(href_list["toggle_repairs"]) - chassis.overlays -= droid_overlay - if(pr_repair_droid.toggle()) - droid_overlay = new(src.icon, icon_state = "repair_droid_a") - log_message("Activated.") - else - droid_overlay = new(src.icon, icon_state = "repair_droid") - log_message("Deactivated.") - set_ready_state(1) - chassis.overlays += droid_overlay - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - return - -/datum/global_iterator/mecha_repair_droid/process(var/obj/item/mecha_parts/mecha_equipment/repair_droid/RD as obj) - if(!RD.chassis) - stop() - RD.set_ready_state(1) - return - var/health_boost = RD.health_boost - var/repaired = 0 - if(RD.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - health_boost *= -2 - else if(RD.chassis.hasInternalDamage() && prob(15)) - for(var/int_dam_flag in RD.repairable_damage) - if(RD.chassis.hasInternalDamage(int_dam_flag)) - RD.chassis.clearInternalDamage(int_dam_flag) - repaired = 1 - break - if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health)) - RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health) - repaired = 1 - if(repaired) - if(RD.chassis.use_power(RD.energy_drain)) - RD.set_ready_state(0) - else - stop() - RD.set_ready_state(1) - return - else - RD.set_ready_state(1) - return - - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay - name = "\improper Energy Relay Module" - desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low." - icon_state = "tesla" - origin_tech = "magnets=4;syndicate=2" - equip_cooldown = 10 - energy_drain = 0 - range = 0 - var/datum/global_iterator/pr_energy_relay - var/coeff = 100 - var/list/use_channels = list(EQUIP,ENVIRON,LIGHT) - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/New() - ..() - pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0) - pr_energy_relay.set_delay(equip_cooldown) - return - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach() - pr_energy_relay.stop() -// chassis.proc_res["dynusepower"] = null - chassis.proc_res["dyngetcharge"] = null - ..() - return - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/attach(obj/mecha/M) - ..() - chassis.proc_res["dyngetcharge"] = src -// chassis.proc_res["dynusepower"] = src - return - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/can_attach(obj/mecha/M) - if(..()) - if(!M.proc_res["dyngetcharge"])// && !M.proc_res["dynusepower"]) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/dyngetcharge() - if(equip_ready) //disabled - return chassis.dyngetcharge() - var/area/A = get_area(chassis) - var/pow_chan = get_power_channel(A) - var/charge = 0 - if(pow_chan) - charge = 1000 //making magic - else - return chassis.dyngetcharge() - return charge - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A) - var/pow_chan - if(A) - for(var/c in use_channels) - if(A.powered(c)) - pow_chan = c - break - return pow_chan - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Topic(href, href_list) - ..() - if(href_list["toggle_relay"]) - if(pr_energy_relay.toggle()) - set_ready_state(0) - log_message("Activated.") - else - set_ready_state(1) - log_message("Deactivated.") - return - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info() - if(!chassis) return - return "* [src.name] - [pr_energy_relay.active()?"Dea":"A"]ctivate" - -/* proc/dynusepower(amount) - if(!equip_ready) //enabled - var/area/A = get_area(chassis) - var/pow_chan = get_power_channel(A) - if(pow_chan) - A.master.use_power(amount*coeff, pow_chan) - return 1 - return chassis.dynusepower(amount)*/ - -/datum/global_iterator/mecha_energy_relay/process(var/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/ER) - if(!ER.chassis || ER.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - stop() - ER.set_ready_state(1) - return - var/cur_charge = ER.chassis.get_charge() - if(isnull(cur_charge) || !ER.chassis.cell) - stop() - ER.set_ready_state(1) - ER.occupant_message("No powercell detected.") - return - if(cur_charge3\] - [pr_mech_generator.active()?"Dea":"A"]ctivate" - return - -/obj/item/mecha_parts/mecha_equipment/generator/action(target) - if(chassis) - var/result = load_fuel(target) - var/message - if(isnull(result)) - message = "[fuel] traces in target minimal. [target] cannot be used as fuel." - else if(!result) - message = "Unit is full." - else - message = "[result] unit\s of [fuel] successfully loaded." - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - occupant_message(message) - return - -/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P) - if(P.type == fuel.type && P.amount) - var/to_load = max(max_fuel - fuel.amount*fuel.perunit,0) - if(to_load) - var/units = min(max(round(to_load / P.perunit),1),P.amount) - if(units) - fuel.amount += units - P.use(units) - return units - else - return 0 - return - -/obj/item/mecha_parts/mecha_equipment/generator/attackby(weapon,mob/user) - var/result = load_fuel(weapon) - if(isnull(result)) - user.visible_message("[user] tries to shove [weapon] into [src]. What a dumb-ass.","[fuel] traces minimal. [weapon] cannot be used as fuel.") - else if(!result) + chassis.log_append_to_last("Armor saved.") + else + chassis.occupant_message("[user] hits [chassis] with [W].") + user.visible_message("[user] hits [chassis] with [W].", "You hit [src] with [W].") + chassis.take_damage(round(W.force*damage_coeff),W.damtype) + chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + return + + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster + name = "\improper Armor Booster Module (Ranged Weaponry)" + desc = "Boosts exosuit armor against ranged attacks. Completely blocks taser shots. Requires energy to operate." + icon_state = "mecha_abooster_proj" + origin_tech = "materials=4" + equip_cooldown = 10 + energy_drain = 50 + range = 0 + var/deflect_coeff = 1.15 + var/damage_coeff = 0.8 + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/can_attach(obj/mecha/M as obj) + if(..()) + if(!istype(M, /obj/mecha/combat/honker)) + if(!M.proc_res["dynbulletdamage"] && !M.proc_res["dynhitby"]) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/attach(obj/mecha/M as obj) + ..() + chassis.proc_res["dynbulletdamage"] = src + chassis.proc_res["dynhitby"] = src + return + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/detach() + chassis.proc_res["dynbulletdamage"] = null + chassis.proc_res["dynhitby"] = null + ..() + return + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/get_equip_info() + if(!chassis) return + return "* [src.name]" + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynbulletdamage(var/obj/item/projectile/Proj) + if(!action_checks(src)) + return chassis.dynbulletdamage(Proj) + if(prob(chassis.deflect_chance*deflect_coeff)) + chassis.occupant_message("The armor deflects incoming projectile.") + chassis.visible_message("The [chassis.name] armor deflects the projectile") + chassis.log_append_to_last("Armor saved.") + else + chassis.take_damage(round(Proj.damage*src.damage_coeff),Proj.flag) + chassis.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + Proj.on_hit(chassis) + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/dynhitby(atom/movable/A) + if(!action_checks(A)) + return chassis.dynhitby(A) + if(prob(chassis.deflect_chance*deflect_coeff) || istype(A, /mob/living) || istype(A, /obj/item/mecha_parts/mecha_tracking)) + chassis.occupant_message("The [A] bounces off the armor.") + chassis.visible_message("The [A] bounces off the [chassis] armor") + chassis.log_append_to_last("Armor saved.") + if(istype(A, /mob/living)) + var/mob/living/M = A + M.take_organ_damage(10) + else if(istype(A, /obj)) + var/obj/O = A + if(O.throwforce) + chassis.take_damage(round(O.throwforce*damage_coeff)) + chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + return + + +/obj/item/mecha_parts/mecha_equipment/repair_droid + name = "\improper Repair Droid Module" + desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost all types of external or internal damage." + icon_state = "repair_droid" + origin_tech = "magnets=3;programming=3" + equip_cooldown = 20 + energy_drain = 100 + range = 0 + var/health_boost = 2 + var/datum/global_iterator/pr_repair_droid + var/icon/droid_overlay + var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH) + +/obj/item/mecha_parts/mecha_equipment/repair_droid/New() + ..() + pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0) + pr_repair_droid.set_delay(equip_cooldown) + return + +/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M as obj) + ..() + droid_overlay = new(src.icon, icon_state = "repair_droid") + M.overlays += droid_overlay + return + +/obj/item/mecha_parts/mecha_equipment/repair_droid/destroy() + chassis.overlays -= droid_overlay + ..() + return + +/obj/item/mecha_parts/mecha_equipment/repair_droid/detach() + chassis.overlays -= droid_overlay + pr_repair_droid.stop() + ..() + return + +/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info() + if(!chassis) return + return "* [src.name] - [pr_repair_droid.active()?"Dea":"A"]ctivate" + +/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list) + ..() + if(href_list["toggle_repairs"]) + chassis.overlays -= droid_overlay + if(pr_repair_droid.toggle()) + droid_overlay = new(src.icon, icon_state = "repair_droid_a") + log_message("Activated.") + else + droid_overlay = new(src.icon, icon_state = "repair_droid") + log_message("Deactivated.") + set_ready_state(1) + chassis.overlays += droid_overlay + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + return + +/datum/global_iterator/mecha_repair_droid/process(var/obj/item/mecha_parts/mecha_equipment/repair_droid/RD as obj) + if(!RD.chassis) + stop() + RD.set_ready_state(1) + return + var/health_boost = RD.health_boost + var/repaired = 0 + if(RD.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) + health_boost *= -2 + else if(RD.chassis.hasInternalDamage() && prob(15)) + for(var/int_dam_flag in RD.repairable_damage) + if(RD.chassis.hasInternalDamage(int_dam_flag)) + RD.chassis.clearInternalDamage(int_dam_flag) + repaired = 1 + break + if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health)) + RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health) + repaired = 1 + if(repaired) + if(RD.chassis.use_power(RD.energy_drain)) + RD.set_ready_state(0) + else + stop() + RD.set_ready_state(1) + return + else + RD.set_ready_state(1) + return + + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay + name = "\improper Energy Relay Module" + desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low." + icon_state = "tesla" + origin_tech = "magnets=4;syndicate=2" + equip_cooldown = 10 + energy_drain = 0 + range = 0 + var/datum/global_iterator/pr_energy_relay + var/coeff = 100 + var/list/use_channels = list(EQUIP,ENVIRON,LIGHT) + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/New() + ..() + pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0) + pr_energy_relay.set_delay(equip_cooldown) + return + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach() + pr_energy_relay.stop() +// chassis.proc_res["dynusepower"] = null + chassis.proc_res["dyngetcharge"] = null + ..() + return + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/attach(obj/mecha/M) + ..() + chassis.proc_res["dyngetcharge"] = src +// chassis.proc_res["dynusepower"] = src + return + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/can_attach(obj/mecha/M) + if(..()) + if(!M.proc_res["dyngetcharge"])// && !M.proc_res["dynusepower"]) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/dyngetcharge() + if(equip_ready) //disabled + return chassis.dyngetcharge() + var/area/A = get_area(chassis) + var/pow_chan = get_power_channel(A) + var/charge = 0 + if(pow_chan) + charge = 1000 //making magic + else + return chassis.dyngetcharge() + return charge + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A) + var/pow_chan + if(A) + for(var/c in use_channels) + if(A.powered(c)) + pow_chan = c + break + return pow_chan + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Topic(href, href_list) + ..() + if(href_list["toggle_relay"]) + if(pr_energy_relay.toggle()) + set_ready_state(0) + log_message("Activated.") + else + set_ready_state(1) + log_message("Deactivated.") + return + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info() + if(!chassis) return + return "* [src.name] - [pr_energy_relay.active()?"Dea":"A"]ctivate" + +/* proc/dynusepower(amount) + if(!equip_ready) //enabled + var/area/A = get_area(chassis) + var/pow_chan = get_power_channel(A) + if(pow_chan) + A.master.use_power(amount*coeff, pow_chan) + return 1 + return chassis.dynusepower(amount)*/ + +/datum/global_iterator/mecha_energy_relay/process(var/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/ER) + if(!ER.chassis || ER.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) + stop() + ER.set_ready_state(1) + return + var/cur_charge = ER.chassis.get_charge() + if(isnull(cur_charge) || !ER.chassis.cell) + stop() + ER.set_ready_state(1) + ER.occupant_message("No powercell detected.") + return + if(cur_charge3\] - [pr_mech_generator.active()?"Dea":"A"]ctivate" + return + +/obj/item/mecha_parts/mecha_equipment/generator/action(target) + if(chassis) + var/result = load_fuel(target) + var/message + if(isnull(result)) + message = "[fuel] traces in target minimal. [target] cannot be used as fuel." + else if(!result) + message = "Unit is full." + else + message = "[result] unit\s of [fuel] successfully loaded." + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + occupant_message(message) + return + +/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P) + if(P.type == fuel.type && P.amount) + var/to_load = max(max_fuel - fuel.amount*fuel.perunit,0) + if(to_load) + var/units = min(max(round(to_load / P.perunit),1),P.amount) + if(units) + fuel.amount += units + P.use(units) + return units + else + return 0 + return + +/obj/item/mecha_parts/mecha_equipment/generator/attackby(weapon,mob/user) + var/result = load_fuel(weapon) + if(isnull(result)) + user.visible_message("[user] tries to shove [weapon] into [src]. What a dumb-ass.","[fuel] traces minimal. [weapon] cannot be used as fuel.") + else if(!result) to_chat(user, "Unit is full.") - else - user.visible_message("[user] loads [src] with [fuel].","[result] unit\s of [fuel] successfully loaded.") - return - -/obj/item/mecha_parts/mecha_equipment/generator/critfail() - ..() - var/turf/simulated/T = get_turf(src) - if(!T) - return - var/datum/gas_mixture/GM = new - if(prob(10)) - GM.toxins += 100 - GM.temperature = 1500+T0C //should be enough to start a fire - T.visible_message("The [src] suddenly disgorges a cloud of heated plasma.") - destroy() - else - GM.toxins += 5 - GM.temperature = istype(T) ? T.air.temperature : T20C - T.visible_message("The [src] suddenly disgorges a cloud of plasma.") - T.assume_air(GM) - return - -/datum/global_iterator/mecha_generator/process(var/obj/item/mecha_parts/mecha_equipment/generator/EG) - if(!EG.chassis) - stop() - EG.set_ready_state(1) - return 0 - if(EG.fuel.amount<=0) - stop() - EG.log_message("Deactivated - no fuel.") - EG.set_ready_state(1) - return 0 - if(anyprob(EG.reliability)) - EG.critfail() - stop() - return 0 - var/cur_charge = EG.chassis.get_charge() - if(isnull(cur_charge)) - EG.set_ready_state(1) - EG.occupant_message("No powercell detected.") - EG.log_message("Deactivated.") - stop() - return 0 - var/use_fuel = EG.fuel_per_cycle_idle - if(cur_charge[target] succesfully loaded.
                      ") - chassis.log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") - else - chassis.occupant_message("You must hold still while handling objects.") - O.anchored = initial(O.anchored) - else - chassis.occupant_message("Not enough room in cargo compartment.") - else - chassis.occupant_message("[target] is firmly secured.") - - else if(istype(target,/mob/living)) - var/mob/living/M = target - if(M.stat>1) return - if(chassis.occupant.a_intent == I_HURT) - chassis.occupant_message("You obliterate [target] with [src.name], leaving blood and guts everywhere.") - chassis.visible_message("[chassis] destroys [target] in an unholy fury.") - if(chassis.occupant.a_intent == I_DISARM) - chassis.occupant_message("You tear [target]'s limbs off with [src.name].") - chassis.visible_message("[chassis] rips [target]'s arms off.") - else - step_away(M,chassis) - chassis.occupant_message("You smash into [target], sending them flying.") - chassis.visible_message("[chassis] tosses [target] like a piece of paper.") - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return 1 - -#undef MECHDRILL_SAND_SPEED -#undef MECHDRILL_ROCK_SPEED + else + user.visible_message("[user] loads [src] with [fuel].","[result] unit\s of [fuel] successfully loaded.") + return + +/obj/item/mecha_parts/mecha_equipment/generator/critfail() + ..() + var/turf/simulated/T = get_turf(src) + if(!T) + return + var/datum/gas_mixture/GM = new + if(prob(10)) + GM.toxins += 100 + GM.temperature = 1500+T0C //should be enough to start a fire + T.visible_message("The [src] suddenly disgorges a cloud of heated plasma.") + destroy() + else + GM.toxins += 5 + GM.temperature = istype(T) ? T.air.temperature : T20C + T.visible_message("The [src] suddenly disgorges a cloud of plasma.") + T.assume_air(GM) + return + +/datum/global_iterator/mecha_generator/process(var/obj/item/mecha_parts/mecha_equipment/generator/EG) + if(!EG.chassis) + stop() + EG.set_ready_state(1) + return 0 + if(EG.fuel.amount<=0) + stop() + EG.log_message("Deactivated - no fuel.") + EG.set_ready_state(1) + return 0 + if(anyprob(EG.reliability)) + EG.critfail() + stop() + return 0 + var/cur_charge = EG.chassis.get_charge() + if(isnull(cur_charge)) + EG.set_ready_state(1) + EG.occupant_message("No powercell detected.") + EG.log_message("Deactivated.") + stop() + return 0 + var/use_fuel = EG.fuel_per_cycle_idle + if(cur_charge[target] succesfully loaded.
                      ") + chassis.log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") + else + chassis.occupant_message("You must hold still while handling objects.") + O.anchored = initial(O.anchored) + else + chassis.occupant_message("Not enough room in cargo compartment.") + else + chassis.occupant_message("[target] is firmly secured.") + + else if(istype(target,/mob/living)) + var/mob/living/M = target + if(M.stat>1) return + if(chassis.occupant.a_intent == I_HURT) + chassis.occupant_message("You obliterate [target] with [src.name], leaving blood and guts everywhere.") + chassis.visible_message("[chassis] destroys [target] in an unholy fury.") + if(chassis.occupant.a_intent == I_DISARM) + chassis.occupant_message("You tear [target]'s limbs off with [src.name].") + chassis.visible_message("[chassis] rips [target]'s arms off.") + else + step_away(M,chassis) + chassis.occupant_message("You smash into [target], sending them flying.") + chassis.visible_message("[chassis] tosses [target] like a piece of paper.") + set_ready_state(0) + chassis.use_power(energy_drain) + do_after_cooldown() + return 1 + +#undef MECHDRILL_SAND_SPEED +#undef MECHDRILL_ROCK_SPEED diff --git a/code/game/mecha/equipment/tools/unused_tools.dm b/code/game/mecha/equipment/tools/unused_tools.dm index a6a5fb5e392..781cad030cf 100644 --- a/code/game/mecha/equipment/tools/unused_tools.dm +++ b/code/game/mecha/equipment/tools/unused_tools.dm @@ -1,54 +1,54 @@ - - - -/****** Do not tick this file in without looking over this code first ******/ - - -/obj/item/mecha_parts/mecha_equipment/defence_shocker - name = "Exosuit Defence Shocker" - desc = "" - icon_state = "mecha_teleport" - equip_cooldown = 10 - energy_drain = 100 - range = RANGED - var/shock_damage = 15 - var/active - - can_attach(obj/mecha/M as obj) - if(..()) - if(!istype(M, /obj/mecha/combat/honker)) - if(!M.proc_res["dynattackby"] && !M.proc_res["dynattackhand"] && !M.proc_res["dynattackalien"]) - return 1 - return 0 - - attach(obj/mecha/M as obj) - ..() - chassis.proc_res["dynattackby"] = src - return - - proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) - if(!action_checks(user) || !active) - return - user.electrocute_act(shock_damage, src) - return chassis.dynattackby(W,user) - - -/* -/obj/item/mecha_parts/mecha_equipment/book_stocker - - action(var/mob/target) - if(!istype(target)) - return - if(target.search_contents_for(/obj/item/book/WGW)) - target.gib() - target.client.gib() - target.client.mom.monkeyize() - target.client.mom.gib() - for(var/mob/M in range(target, 1000)) - M.gib() - explosion(target.loc,100000,100000,100000) - usr.gib() - world.Reboot() - return 1 - -*/ + + + +/****** Do not tick this file in without looking over this code first ******/ + + +/obj/item/mecha_parts/mecha_equipment/defence_shocker + name = "Exosuit Defence Shocker" + desc = "" + icon_state = "mecha_teleport" + equip_cooldown = 10 + energy_drain = 100 + range = RANGED + var/shock_damage = 15 + var/active + + can_attach(obj/mecha/M as obj) + if(..()) + if(!istype(M, /obj/mecha/combat/honker)) + if(!M.proc_res["dynattackby"] && !M.proc_res["dynattackhand"] && !M.proc_res["dynattackalien"]) + return 1 + return 0 + + attach(obj/mecha/M as obj) + ..() + chassis.proc_res["dynattackby"] = src + return + + proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) + if(!action_checks(user) || !active) + return + user.electrocute_act(shock_damage, src) + return chassis.dynattackby(W,user) + + +/* +/obj/item/mecha_parts/mecha_equipment/book_stocker + + action(var/mob/target) + if(!istype(target)) + return + if(target.search_contents_for(/obj/item/book/WGW)) + target.gib() + target.client.gib() + target.client.mom.monkeyize() + target.client.mom.gib() + for(var/mob/M in range(target, 1000)) + M.gib() + explosion(target.loc,100000,100000,100000) + usr.gib() + world.Reboot() + return 1 + +*/ diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 6b4830f3b5a..db25658d90c 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -1,448 +1,448 @@ -/obj/item/mecha_parts/mecha_equipment/weapon - name = "mecha weapon" - range = RANGED - origin_tech = "materials=3;combat=3" - var/projectile - var/fire_sound - - -/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(var/obj/mecha/combat/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - - -/obj/item/mecha_parts/mecha_equipment/weapon/energy - name = "General Energy Weapon" - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/action(atom/target) - if(!action_checks(target)) return - var/turf/curloc = chassis.loc - var/atom/targloc = get_turf(target) - if (!targloc || !istype(targloc, /turf) || !curloc) - return - if (targloc == curloc) - return - set_ready_state(0) - playsound(chassis, fire_sound, 50, 1) - var/obj/item/projectile/A = new projectile(curloc) - A.firer = chassis.occupant - A.original = target - A.current = curloc - A.starting = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - chassis.use_power(energy_drain) - A.OnFired() - A.process() - chassis.log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return - - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser - equip_cooldown = 8 - name = "CH-PS \"Immolator\" Laser" - icon_state = "mecha_laser" - energy_drain = 30 - projectile = /obj/item/projectile/beam - fire_sound = 'sound/weapons/Laser.ogg' - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy - equip_cooldown = 15 - name = "CH-LC \"Solaris\" Laser Cannon" - icon_state = "mecha_laser" - energy_drain = 60 - projectile = /obj/item/projectile/beam/heavylaser - fire_sound = 'sound/weapons/lasercannonfire.ogg' - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion - equip_cooldown = 40 - name = "mkIV Ion Heavy Cannon" - icon_state = "mecha_ion" - energy_drain = 120 - projectile = /obj/item/projectile/ion - fire_sound = 'sound/weapons/ion.ogg' - - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse - equip_cooldown = 30 - name = "eZ-13 MK2 heavy pulse rifle" - icon_state = "mecha_pulse" - energy_drain = 120 - origin_tech = "materials=3;combat=6;powerstorage=4" - projectile = /obj/item/projectile/beam/pulse/heavy - fire_sound = 'sound/weapons/marauder.ogg' - - -/obj/item/projectile/beam/pulse/heavy - name = "heavy pulse laser" - icon_state = "u_laser" - damage = 60 - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser - name = "\improper PBT \"Pacifier\" mounted taser" - icon_state = "mecha_taser" - energy_drain = 20 - equip_cooldown = 8 - projectile = /obj/item/projectile/energy/electrode - fire_sound = 'sound/weapons/Taser.ogg' - - -/obj/item/mecha_parts/mecha_equipment/weapon/honker - name = "\improper HoNkER BlAsT 5000" - icon_state = "mecha_honker" - energy_drain = 200 - equip_cooldown = 150 - range = MELEE|RANGED - -/obj/item/mecha_parts/mecha_equipment/weapon/honker/can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target) - if(!chassis) - return 0 - if(energy_drain && chassis.get_charge() < energy_drain) - return 0 - if(!equip_ready) - return 0 - - playsound(chassis, 'sound/items/AirHorn.ogg', 100, 1) - chassis.occupant_message("HONK") - for(var/mob/living/carbon/M in ohearers(6, chassis)) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(H.earprot()) - continue +/obj/item/mecha_parts/mecha_equipment/weapon + name = "mecha weapon" + range = RANGED + origin_tech = "materials=3;combat=3" + var/projectile + var/fire_sound + + +/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(var/obj/mecha/combat/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + + +/obj/item/mecha_parts/mecha_equipment/weapon/energy + name = "General Energy Weapon" + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/action(atom/target) + if(!action_checks(target)) return + var/turf/curloc = chassis.loc + var/atom/targloc = get_turf(target) + if (!targloc || !istype(targloc, /turf) || !curloc) + return + if (targloc == curloc) + return + set_ready_state(0) + playsound(chassis, fire_sound, 50, 1) + var/obj/item/projectile/A = new projectile(curloc) + A.firer = chassis.occupant + A.original = target + A.current = curloc + A.starting = curloc + A.yo = targloc.y - curloc.y + A.xo = targloc.x - curloc.x + chassis.use_power(energy_drain) + A.OnFired() + A.process() + chassis.log_message("Fired from [src.name], targeting [target].") + do_after_cooldown() + return + + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser + equip_cooldown = 8 + name = "CH-PS \"Immolator\" Laser" + icon_state = "mecha_laser" + energy_drain = 30 + projectile = /obj/item/projectile/beam + fire_sound = 'sound/weapons/Laser.ogg' + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy + equip_cooldown = 15 + name = "CH-LC \"Solaris\" Laser Cannon" + icon_state = "mecha_laser" + energy_drain = 60 + projectile = /obj/item/projectile/beam/heavylaser + fire_sound = 'sound/weapons/lasercannonfire.ogg' + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion + equip_cooldown = 40 + name = "mkIV Ion Heavy Cannon" + icon_state = "mecha_ion" + energy_drain = 120 + projectile = /obj/item/projectile/ion + fire_sound = 'sound/weapons/ion.ogg' + + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse + equip_cooldown = 30 + name = "eZ-13 MK2 heavy pulse rifle" + icon_state = "mecha_pulse" + energy_drain = 120 + origin_tech = "materials=3;combat=6;powerstorage=4" + projectile = /obj/item/projectile/beam/pulse/heavy + fire_sound = 'sound/weapons/marauder.ogg' + + +/obj/item/projectile/beam/pulse/heavy + name = "heavy pulse laser" + icon_state = "u_laser" + damage = 60 + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser + name = "\improper PBT \"Pacifier\" mounted taser" + icon_state = "mecha_taser" + energy_drain = 20 + equip_cooldown = 8 + projectile = /obj/item/projectile/energy/electrode + fire_sound = 'sound/weapons/Taser.ogg' + + +/obj/item/mecha_parts/mecha_equipment/weapon/honker + name = "\improper HoNkER BlAsT 5000" + icon_state = "mecha_honker" + energy_drain = 200 + equip_cooldown = 150 + range = MELEE|RANGED + +/obj/item/mecha_parts/mecha_equipment/weapon/honker/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/honker/action(target) + if(!chassis) + return 0 + if(energy_drain && chassis.get_charge() < energy_drain) + return 0 + if(!equip_ready) + return 0 + + playsound(chassis, 'sound/items/AirHorn.ogg', 100, 1) + chassis.occupant_message("HONK") + for(var/mob/living/carbon/M in ohearers(6, chassis)) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.earprot()) + continue to_chat(M, "HONK") - M.sleeping = 0 - M.stuttering += 20 - M.ear_deaf += 30 - M.Weaken(3) - if(prob(30)) - M.Stun(10) - M.Paralyse(4) - else - M.Jitter(500) - /* //else the mousetraps are useless - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(isobj(H.shoes)) - var/thingy = H.shoes - H.drop_from_inventory(H.shoes) - walk_away(thingy,chassis,15,2) - spawn(20) - if(thingy) - walk(thingy,0) - */ - chassis.use_power(energy_drain) - log_message("Honked from [src.name]. HONK!") - var/turf/T = get_turf(src) - message_admins("[key_name(chassis.occupant, chassis.occupant.client)](?) used a Mecha Honker in ([T.x],[T.y],[T.z] - JMP)",0,1) - log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Mecha Honker in ([T.x],[T.y],[T.z])") - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic - name = "General Ballisic Weapon" - var/projectiles - var/projectile_energy_cost - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action_checks(atom/target) - if(..()) - if(projectiles > 0) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info() - return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/proc/rearm() - if(projectiles < initial(projectiles)) - var/projectiles_to_add = initial(projectiles) - projectiles - while(chassis.get_charge() >= projectile_energy_cost && projectiles_to_add) - projectiles++ - projectiles_to_add-- - chassis.use_power(projectile_energy_cost) - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - log_message("Rearmed [src.name].") - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/Topic(href, href_list) - ..() - if (href_list["rearm"]) - src.rearm() - return - - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot - name = "LBX AC 10 \"Scattershot\"" - icon_state = "mecha_scatter" - equip_cooldown = 20 - projectile = /obj/item/projectile/bullet/midbullet - fire_sound = 'sound/weapons/shotgun.ogg' - projectiles = 40 - projectile_energy_cost = 25 - var/projectiles_per_shot = 4 - var/deviation = 0.7 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/action(atom/target) - if(!action_checks(target)) return - var/turf/curloc = get_turf(chassis) - var/turf/targloc = get_turf(target) - if(!curloc || !targloc) return - var/target_x = targloc.x - var/target_y = targloc.y - var/target_z = targloc.z - targloc = null - for(var/i=1 to min(projectiles, projectiles_per_shot)) - targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) - if(!targloc || targloc == curloc) - break - playsound(chassis, fire_sound, 80, 1) - var/obj/item/projectile/A = getFromPool(projectile,curloc)//new projectile(curloc) - src.projectiles-- - A.original = target - A.current = curloc - A.starting = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - set_ready_state(0) - A.OnFired() - A.process() - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return - - - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg - name = "Ultra AC 2" - icon_state = "mecha_uac2" - equip_cooldown = 10 - projectile = /obj/item/projectile/bullet/weakbullet - fire_sound = 'sound/weapons/Gunshot_smg.ogg' - projectiles = 300 - projectile_energy_cost = 20 - var/projectiles_per_shot = 3 - var/deviation = 0.3 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg/action(atom/target) - if(!action_checks(target)) return - var/turf/targloc = get_turf(target) - var/target_x = targloc.x - var/target_y = targloc.y - var/target_z = targloc.z - targloc = null - spawn for(var/i=1 to min(projectiles, projectiles_per_shot)) - if(!chassis) break - var/turf/curloc = get_turf(chassis) - targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) - if (!targloc || !curloc) - continue - if (targloc == curloc) - continue - - playsound(chassis, fire_sound, 50, 1) - var/obj/item/projectile/A = new projectile(curloc) - src.projectiles-- - A.original = target - A.current = curloc - A.starting = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - A.OnFired() - A.process() - sleep(2) - set_ready_state(0) - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack - name = "SRM-8 Missile Rack" - icon_state = "mecha_missilerack" - projectile = /obj/item/missile - fire_sound = 'sound/weapons/rocket.ogg' - projectiles = 8 - projectile_energy_cost = 1000 - equip_cooldown = 60 - var/missile_speed = 2 - var/missile_range = 30 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/missile/M = new projectile(chassis.loc) - M.primed = 1 - playsound(chassis, fire_sound, 50, 1) - M.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return - - -/obj/item/missile - icon = 'icons/obj/grenade.dmi' - icon_state = "missile" - var/primed = null - throwforce = 15 - -/obj/item/missile/throw_impact(atom/hit_atom) - if(primed) - explosion(hit_atom, 0, 1, 2) - qdel(src) - else - ..() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang - name = "SGL-6 Grenade Launcher" - icon_state = "mecha_grenadelnchr" - projectile = /obj/item/weapon/grenade/flashbang - fire_sound = 'sound/weapons/grenadelauncher.ogg' - projectiles = 6 - missile_speed = 1.5 - projectile_energy_cost = 800 - equip_cooldown = 60 - var/det_time = 20 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/grenade/flashbang/F = new projectile(chassis.loc) - playsound(chassis, fire_sound, 50, 1) - F.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Fired from [src.name], targeting [target].") - spawn(det_time) - F.prime() - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang//Because I am a heartless bastard -Sieve - name = "SOP-6 Grenade Launcher" - projectile = /obj/item/weapon/grenade/flashbang/clusterbang - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/get_equip_info()//Limited version of the clusterbang launcher that can't reload - return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]\[[src.projectiles]\]" - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/rearm() - return//Extra bit of security - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar - name = "Banana Mortar" - icon_state = "mecha_bananamrtr" - projectile = /obj/item/weapon/bananapeel - fire_sound = 'sound/items/bikehorn.ogg' - projectiles = 15 - missile_speed = 1.5 - projectile_energy_cost = 100 - equip_cooldown = 20 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/bananapeel/B = new projectile(chassis.loc) - playsound(chassis, fire_sound, 60, 1) - B.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Bananed from [src.name], targeting [target]. HONK!") - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar - name = "Mousetrap Mortar" - icon_state = "mecha_mousetrapmrtr" - projectile = /obj/item/device/assembly/mousetrap - fire_sound = 'sound/items/bikehorn.ogg' - projectiles = 15 - missile_speed = 1.5 - projectile_energy_cost = 100 - equip_cooldown = 10 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/device/assembly/mousetrap/M = new projectile(chassis.loc) - M.secured = 1 - playsound(chassis, fire_sound, 60, 1) - M.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!") - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/creampie_mortar //why waste perfectly good food synthetizing technology in solving world hunger when you can have clowntide instead? - name = "Rapid-Fire Cream Pie Mortar" - icon_state = "mecha_bananamrtr" - projectile = /obj/item/weapon/reagent_containers/food/snacks/pie/empty //because some chucklefuck will try to catch the pie somehow for free nutriment - fire_sound = 'sound/items/bikehorn.ogg' - projectiles = 15 - missile_speed = 0.75 //for maximum pie-traveling - projectile_energy_cost = 100 - equip_cooldown = 5 - range = MELEE|RANGED - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/creampie_mortar/can_attach(obj/mecha/combat/honker/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/creampie_mortar/action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/reagent_containers/food/snacks/pie/P = new projectile(chassis.loc) - playsound(chassis, fire_sound, 60, 1) - P.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Cream-pied from [src.name], targeting [target]. HONK!") - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas - name = "PCMK-6 Bolas Launcher" - icon_state = "mecha_bolas" - projectile = /obj/item/weapon/legcuffs/bolas - fire_sound = 'sound/weapons/whip.ogg' - projectiles = 10 - missile_speed = 1 - missile_range = 30 - projectile_energy_cost = 50 - equip_cooldown = 10 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas/can_attach(obj/mecha/combat/gygax/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas/action(target) - if(!action_checks(target)) return - set_ready_state(0) - var/obj/item/weapon/legcuffs/bolas/M = new projectile(chassis.loc) - playsound(chassis, fire_sound, 50, 1) - M.thrown_from = src - M.throw_at(target, missile_range, missile_speed) - projectiles-- - log_message("Fired from [src.name], targeting [target].") - do_after_cooldown() - return + M.sleeping = 0 + M.stuttering += 20 + M.ear_deaf += 30 + M.Weaken(3) + if(prob(30)) + M.Stun(10) + M.Paralyse(4) + else + M.Jitter(500) + /* //else the mousetraps are useless + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(isobj(H.shoes)) + var/thingy = H.shoes + H.drop_from_inventory(H.shoes) + walk_away(thingy,chassis,15,2) + spawn(20) + if(thingy) + walk(thingy,0) + */ + chassis.use_power(energy_drain) + log_message("Honked from [src.name]. HONK!") + var/turf/T = get_turf(src) + message_admins("[key_name(chassis.occupant, chassis.occupant.client)](?) used a Mecha Honker in ([T.x],[T.y],[T.z] - JMP)",0,1) + log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Mecha Honker in ([T.x],[T.y],[T.z])") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic + name = "General Ballisic Weapon" + var/projectiles + var/projectile_energy_cost + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/action_checks(atom/target) + if(..()) + if(projectiles > 0) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/get_equip_info() + return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/proc/rearm() + if(projectiles < initial(projectiles)) + var/projectiles_to_add = initial(projectiles) - projectiles + while(chassis.get_charge() >= projectile_energy_cost && projectiles_to_add) + projectiles++ + projectiles_to_add-- + chassis.use_power(projectile_energy_cost) + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + log_message("Rearmed [src.name].") + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/Topic(href, href_list) + ..() + if (href_list["rearm"]) + src.rearm() + return + + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot + name = "LBX AC 10 \"Scattershot\"" + icon_state = "mecha_scatter" + equip_cooldown = 20 + projectile = /obj/item/projectile/bullet/midbullet + fire_sound = 'sound/weapons/shotgun.ogg' + projectiles = 40 + projectile_energy_cost = 25 + var/projectiles_per_shot = 4 + var/deviation = 0.7 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/action(atom/target) + if(!action_checks(target)) return + var/turf/curloc = get_turf(chassis) + var/turf/targloc = get_turf(target) + if(!curloc || !targloc) return + var/target_x = targloc.x + var/target_y = targloc.y + var/target_z = targloc.z + targloc = null + for(var/i=1 to min(projectiles, projectiles_per_shot)) + targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) + if(!targloc || targloc == curloc) + break + playsound(chassis, fire_sound, 80, 1) + var/obj/item/projectile/A = getFromPool(projectile,curloc)//new projectile(curloc) + src.projectiles-- + A.original = target + A.current = curloc + A.starting = curloc + A.yo = targloc.y - curloc.y + A.xo = targloc.x - curloc.x + set_ready_state(0) + A.OnFired() + A.process() + log_message("Fired from [src.name], targeting [target].") + do_after_cooldown() + return + + + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg + name = "Ultra AC 2" + icon_state = "mecha_uac2" + equip_cooldown = 10 + projectile = /obj/item/projectile/bullet/weakbullet + fire_sound = 'sound/weapons/Gunshot_smg.ogg' + projectiles = 300 + projectile_energy_cost = 20 + var/projectiles_per_shot = 3 + var/deviation = 0.3 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg/action(atom/target) + if(!action_checks(target)) return + var/turf/targloc = get_turf(target) + var/target_x = targloc.x + var/target_y = targloc.y + var/target_z = targloc.z + targloc = null + spawn for(var/i=1 to min(projectiles, projectiles_per_shot)) + if(!chassis) break + var/turf/curloc = get_turf(chassis) + targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z) + if (!targloc || !curloc) + continue + if (targloc == curloc) + continue + + playsound(chassis, fire_sound, 50, 1) + var/obj/item/projectile/A = new projectile(curloc) + src.projectiles-- + A.original = target + A.current = curloc + A.starting = curloc + A.yo = targloc.y - curloc.y + A.xo = targloc.x - curloc.x + A.OnFired() + A.process() + sleep(2) + set_ready_state(0) + log_message("Fired from [src.name], targeting [target].") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack + name = "SRM-8 Missile Rack" + icon_state = "mecha_missilerack" + projectile = /obj/item/missile + fire_sound = 'sound/weapons/rocket.ogg' + projectiles = 8 + projectile_energy_cost = 1000 + equip_cooldown = 60 + var/missile_speed = 2 + var/missile_range = 30 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/action(target) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/missile/M = new projectile(chassis.loc) + M.primed = 1 + playsound(chassis, fire_sound, 50, 1) + M.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Fired from [src.name], targeting [target].") + do_after_cooldown() + return + + +/obj/item/missile + icon = 'icons/obj/grenade.dmi' + icon_state = "missile" + var/primed = null + throwforce = 15 + +/obj/item/missile/throw_impact(atom/hit_atom) + if(primed) + explosion(hit_atom, 0, 1, 2) + qdel(src) + else + ..() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang + name = "SGL-6 Grenade Launcher" + icon_state = "mecha_grenadelnchr" + projectile = /obj/item/weapon/grenade/flashbang + fire_sound = 'sound/weapons/grenadelauncher.ogg' + projectiles = 6 + missile_speed = 1.5 + projectile_energy_cost = 800 + equip_cooldown = 60 + var/det_time = 20 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/action(target) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/grenade/flashbang/F = new projectile(chassis.loc) + playsound(chassis, fire_sound, 50, 1) + F.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Fired from [src.name], targeting [target].") + spawn(det_time) + F.prime() + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang//Because I am a heartless bastard -Sieve + name = "SOP-6 Grenade Launcher" + projectile = /obj/item/weapon/grenade/flashbang/clusterbang + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/get_equip_info()//Limited version of the clusterbang launcher that can't reload + return "* [chassis.selected==src?"":""][src.name][chassis.selected==src?"":""]\[[src.projectiles]\]" + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang/limited/rearm() + return//Extra bit of security + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar + name = "Banana Mortar" + icon_state = "mecha_bananamrtr" + projectile = /obj/item/weapon/bananapeel + fire_sound = 'sound/items/bikehorn.ogg' + projectiles = 15 + missile_speed = 1.5 + projectile_energy_cost = 100 + equip_cooldown = 20 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/action(target) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/bananapeel/B = new projectile(chassis.loc) + playsound(chassis, fire_sound, 60, 1) + B.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Bananed from [src.name], targeting [target]. HONK!") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar + name = "Mousetrap Mortar" + icon_state = "mecha_mousetrapmrtr" + projectile = /obj/item/device/assembly/mousetrap + fire_sound = 'sound/items/bikehorn.ogg' + projectiles = 15 + missile_speed = 1.5 + projectile_energy_cost = 100 + equip_cooldown = 10 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar/action(target) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/device/assembly/mousetrap/M = new projectile(chassis.loc) + M.secured = 1 + playsound(chassis, fire_sound, 60, 1) + M.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/creampie_mortar //why waste perfectly good food synthetizing technology in solving world hunger when you can have clowntide instead? + name = "Rapid-Fire Cream Pie Mortar" + icon_state = "mecha_bananamrtr" + projectile = /obj/item/weapon/reagent_containers/food/snacks/pie/empty //because some chucklefuck will try to catch the pie somehow for free nutriment + fire_sound = 'sound/items/bikehorn.ogg' + projectiles = 15 + missile_speed = 0.75 //for maximum pie-traveling + projectile_energy_cost = 100 + equip_cooldown = 5 + range = MELEE|RANGED + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/creampie_mortar/can_attach(obj/mecha/combat/honker/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/creampie_mortar/action(target) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/reagent_containers/food/snacks/pie/P = new projectile(chassis.loc) + playsound(chassis, fire_sound, 60, 1) + P.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Cream-pied from [src.name], targeting [target]. HONK!") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas + name = "PCMK-6 Bolas Launcher" + icon_state = "mecha_bolas" + projectile = /obj/item/weapon/legcuffs/bolas + fire_sound = 'sound/weapons/whip.ogg' + projectiles = 10 + missile_speed = 1 + missile_range = 30 + projectile_energy_cost = 50 + equip_cooldown = 10 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas/can_attach(obj/mecha/combat/gygax/M as obj) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bolas/action(target) + if(!action_checks(target)) return + set_ready_state(0) + var/obj/item/weapon/legcuffs/bolas/M = new projectile(chassis.loc) + playsound(chassis, fire_sound, 50, 1) + M.thrown_from = src + M.throw_at(target, missile_range, missile_speed) + projectiles-- + log_message("Fired from [src.name], targeting [target].") + do_after_cooldown() + return diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index b249d5e7c0d..5e303e5ddd2 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -1,261 +1,261 @@ -/obj/machinery/mech_bay_recharge_floor - name = "Mech Bay Recharge Station" - icon = 'icons/mecha/mech_bay.dmi' - icon_state = "recharge_floor" - var/obj/machinery/mech_bay_recharge_port/recharge_port - var/obj/machinery/computer/mech_bay_power_console/recharge_console - var/obj/mecha/recharging_mecha = null - var/capacitor_max = 0 //How much can be stored - var/capacitor_stored = 0 //How much is presently stored - layer = TURF_LAYER + 0.1 //Just above the floor - anchored = 1 - density = 0 - - machine_flags = SCREWTOGGLE | CROWDESTROY - -/obj/machinery/mech_bay_recharge_floor/New() - ..() - component_parts = newlist(/obj/item/weapon/circuitboard/mech_bay_recharge_station, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor) - -/obj/machinery/mech_bay_recharge_floor/RefreshParts() - var/capcount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/capacitor)) capcount += SP.rating-1 - capacitor_max = initial(capacitor_max)+(capcount * 750) - -/obj/machinery/mech_bay_recharge_floor/process() - ..() - if(recharging_mecha&&capacitor_stored) - recharging_mecha.give_power(capacitor_stored) - capacitor_stored = 0 - else if(capacitor_storedInitializing power control devices.") - init_devices() - if(recharge_console && recharge_port) - recharging_mecha = mecha - recharge_console.mecha_in(mecha) - return - else if(!recharge_console) - mecha.occupant_message("Control console not found. Terminating.") - else if(!recharge_port) - mecha.occupant_message("Power port not found. Terminating.") - return - -/obj/machinery/mech_bay_recharge_floor/Uncrossed(atom) - . = ..() - if(atom == recharging_mecha) - recharging_mecha = null - if(recharge_console) - recharge_console.mecha_out() - return - -/obj/machinery/mech_bay_recharge_floor/proc/init_devices() - recharge_console = locate() in range(1,src) - recharge_port = locate(/obj/machinery/mech_bay_recharge_port, get_step(src, WEST)) - if(recharge_console) - recharge_console.recharge_floor = src - if(recharge_port) - recharge_console.recharge_port = recharge_port - if(recharge_port) - recharge_port.recharge_floor = src - if(recharge_console) - recharge_port.recharge_console = recharge_console - return - - -/obj/machinery/mech_bay_recharge_port - name = "Mech Bay Power Port" - density = 1 - anchored = 1 - icon = 'icons/mecha/mech_bay.dmi' - icon_state = "recharge_port" - var/obj/machinery/mech_bay_recharge_floor/recharge_floor - var/obj/machinery/computer/mech_bay_power_console/recharge_console - var/datum/global_iterator/mech_bay_recharger/pr_recharger - - machine_flags = SCREWTOGGLE | CROWDESTROY - -/obj/machinery/mech_bay_recharge_port/New() - ..() - - component_parts = newlist(/obj/item/weapon/circuitboard/mech_bay_power_port, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen) - - pr_recharger = new /datum/global_iterator/mech_bay_recharger(null,0) - - RefreshParts() - return - -/obj/machinery/mech_bay_recharge_port/RefreshParts() - var/lasercount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 - set_voltage(45+lasercount*10) - -/obj/machinery/mech_bay_recharge_port/proc/start_charge(var/obj/mecha/recharging_mecha) - if(stat&(NOPOWER|BROKEN)) - recharging_mecha.occupant_message("Power port not responding. Terminating.") - return 0 - else - if(recharging_mecha.cell) - recharging_mecha.occupant_message("Now charging...") - pr_recharger.start(list(src, recharging_mecha)) - return 1 - else - return 0 - -/obj/machinery/mech_bay_recharge_port/proc/stop_charge() - if(recharge_console && !recharge_console.stat) - recharge_console.icon_state = initial(recharge_console.icon_state) - pr_recharger.stop() - return - -/obj/machinery/mech_bay_recharge_port/proc/active() - if(pr_recharger.active()) - return 1 - else - return 0 - -/obj/machinery/mech_bay_recharge_port/power_change() - if(powered()) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - stat |= NOPOWER - pr_recharger.stop() - return - -/obj/machinery/mech_bay_recharge_port/proc/set_voltage(new_voltage) - if(new_voltage && isnum(new_voltage)) - pr_recharger.max_charge = new_voltage - return 1 - else - return 0 - - -/datum/global_iterator/mech_bay_recharger - delay = 20 - var/max_charge = 45 - check_for_null = 0 //since port.stop_charge() must be called. The checks are made in process() - -/datum/global_iterator/mech_bay_recharger/process(var/obj/machinery/mech_bay_recharge_port/port, var/obj/mecha/mecha) - if(!port) - return 0 - if(mecha && mecha in get_turf(port.recharge_floor)) - if(!mecha.cell) return - var/delta = min(max_charge, mecha.cell.maxcharge - mecha.cell.charge) - if(delta>0) - mecha.give_power(delta) - port.use_power(delta*150) - else - mecha.occupant_message("Fully charged.") - port.stop_charge() - else - port.stop_charge() - return - - - - -/obj/machinery/computer/mech_bay_power_console - name = "Mech Bay Power Control Console" - density = 1 - anchored = 1 - icon = 'icons/obj/computer.dmi' - icon_state = "recharge_comp" - circuit = "/obj/item/weapon/circuitboard/mech_bay_power_console" - var/autostart = 1 - var/voltage = 45 - var/obj/machinery/mech_bay_recharge_floor/recharge_floor - var/obj/machinery/mech_bay_recharge_port/recharge_port - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/mech_bay_power_console/proc/mecha_in(var/obj/mecha/mecha) - if(stat&(NOPOWER|BROKEN)) - mecha.occupant_message("Control console not responding. Terminating...") - return - if(recharge_port && autostart) - var/answer = recharge_port.start_charge(mecha) - if(answer) - recharge_port.set_voltage(voltage) - src.icon_state = initial(src.icon_state)+"_on" - return - -/obj/machinery/computer/mech_bay_power_console/proc/mecha_out() - if(recharge_port) - recharge_port.stop_charge() - return - - -/obj/machinery/computer/mech_bay_power_console/power_change() - if(stat & BROKEN) - icon_state = initial(icon_state)+"_broken" - if(recharge_port) - recharge_port.stop_charge() - else if(powered()) - icon_state = initial(icon_state) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - icon_state = initial(icon_state)+"_nopower" - stat |= NOPOWER - if(recharge_port) - recharge_port.stop_charge() - -/obj/machinery/computer/mech_bay_power_console/set_broken() - icon_state = initial(icon_state)+"_broken" - stat |= BROKEN - if(recharge_port) - recharge_port.stop_charge() - -/obj/machinery/computer/mech_bay_power_console/attack_hand(mob/user as mob) - if(..()) - return - if(!src.stat && (get_dist(src, user) <= 1 || istype(user, /mob/living/silicon))) - return interact(user) - -/obj/machinery/computer/mech_bay_power_console/interact(mob/user as mob) - user.set_machine(src) - var/output = "[src.name]" - if(!recharge_floor) - output += "Mech Bay Recharge Station not initialized.
                      " - else - output += {"Mech Bay Recharge Station Data:
                      - Mecha: [recharge_floor.recharging_mecha||"None"]
                      "} - if(recharge_floor.recharging_mecha) - var/cell_charge = recharge_floor.recharging_mecha.get_charge() - output += "Cell charge: [isnull(cell_charge)?"No powercell found":"[recharge_floor.recharging_mecha.cell.charge]/[recharge_floor.recharging_mecha.cell.maxcharge]"]
                      " - output += "
                      " - if(!recharge_port) - output += "Mech Bay Power Port not initialized.
                      " - else - output += "Mech Bay Power Port Status: [recharge_port.active()?"Now charging":"On hold"]
                      " - - output += "" - user << browse(output, "window=mech_bay_console") - onclose(user, "mech_bay_console") - return - - -/obj/machinery/computer/mech_bay_power_console/Topic(href, href_list) - if(href_list["autostart"]) - autostart = !autostart - if(href_list["voltage"]) - voltage = text2num(href_list["voltage"]) - if(recharge_port) - recharge_port.set_voltage(voltage) - updateUsrDialog() - return +/obj/machinery/mech_bay_recharge_floor + name = "Mech Bay Recharge Station" + icon = 'icons/mecha/mech_bay.dmi' + icon_state = "recharge_floor" + var/obj/machinery/mech_bay_recharge_port/recharge_port + var/obj/machinery/computer/mech_bay_power_console/recharge_console + var/obj/mecha/recharging_mecha = null + var/capacitor_max = 0 //How much can be stored + var/capacitor_stored = 0 //How much is presently stored + layer = TURF_LAYER + 0.1 //Just above the floor + anchored = 1 + density = 0 + + machine_flags = SCREWTOGGLE | CROWDESTROY + +/obj/machinery/mech_bay_recharge_floor/New() + ..() + component_parts = newlist(/obj/item/weapon/circuitboard/mech_bay_recharge_station, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor) + +/obj/machinery/mech_bay_recharge_floor/RefreshParts() + var/capcount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/capacitor)) capcount += SP.rating-1 + capacitor_max = initial(capacitor_max)+(capcount * 750) + +/obj/machinery/mech_bay_recharge_floor/process() + ..() + if(recharging_mecha&&capacitor_stored) + recharging_mecha.give_power(capacitor_stored) + capacitor_stored = 0 + else if(capacitor_storedInitializing power control devices.
                      ") + init_devices() + if(recharge_console && recharge_port) + recharging_mecha = mecha + recharge_console.mecha_in(mecha) + return + else if(!recharge_console) + mecha.occupant_message("Control console not found. Terminating.") + else if(!recharge_port) + mecha.occupant_message("Power port not found. Terminating.") + return + +/obj/machinery/mech_bay_recharge_floor/Uncrossed(atom) + . = ..() + if(atom == recharging_mecha) + recharging_mecha = null + if(recharge_console) + recharge_console.mecha_out() + return + +/obj/machinery/mech_bay_recharge_floor/proc/init_devices() + recharge_console = locate() in range(1,src) + recharge_port = locate(/obj/machinery/mech_bay_recharge_port, get_step(src, WEST)) + if(recharge_console) + recharge_console.recharge_floor = src + if(recharge_port) + recharge_console.recharge_port = recharge_port + if(recharge_port) + recharge_port.recharge_floor = src + if(recharge_console) + recharge_port.recharge_console = recharge_console + return + + +/obj/machinery/mech_bay_recharge_port + name = "Mech Bay Power Port" + density = 1 + anchored = 1 + icon = 'icons/mecha/mech_bay.dmi' + icon_state = "recharge_port" + var/obj/machinery/mech_bay_recharge_floor/recharge_floor + var/obj/machinery/computer/mech_bay_power_console/recharge_console + var/datum/global_iterator/mech_bay_recharger/pr_recharger + + machine_flags = SCREWTOGGLE | CROWDESTROY + +/obj/machinery/mech_bay_recharge_port/New() + ..() + + component_parts = newlist(/obj/item/weapon/circuitboard/mech_bay_power_port, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen) + + pr_recharger = new /datum/global_iterator/mech_bay_recharger(null,0) + + RefreshParts() + return + +/obj/machinery/mech_bay_recharge_port/RefreshParts() + var/lasercount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 + set_voltage(45+lasercount*10) + +/obj/machinery/mech_bay_recharge_port/proc/start_charge(var/obj/mecha/recharging_mecha) + if(stat&(NOPOWER|BROKEN)) + recharging_mecha.occupant_message("Power port not responding. Terminating.") + return 0 + else + if(recharging_mecha.cell) + recharging_mecha.occupant_message("Now charging...") + pr_recharger.start(list(src, recharging_mecha)) + return 1 + else + return 0 + +/obj/machinery/mech_bay_recharge_port/proc/stop_charge() + if(recharge_console && !recharge_console.stat) + recharge_console.icon_state = initial(recharge_console.icon_state) + pr_recharger.stop() + return + +/obj/machinery/mech_bay_recharge_port/proc/active() + if(pr_recharger.active()) + return 1 + else + return 0 + +/obj/machinery/mech_bay_recharge_port/power_change() + if(powered()) + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + stat |= NOPOWER + pr_recharger.stop() + return + +/obj/machinery/mech_bay_recharge_port/proc/set_voltage(new_voltage) + if(new_voltage && isnum(new_voltage)) + pr_recharger.max_charge = new_voltage + return 1 + else + return 0 + + +/datum/global_iterator/mech_bay_recharger + delay = 20 + var/max_charge = 45 + check_for_null = 0 //since port.stop_charge() must be called. The checks are made in process() + +/datum/global_iterator/mech_bay_recharger/process(var/obj/machinery/mech_bay_recharge_port/port, var/obj/mecha/mecha) + if(!port) + return 0 + if(mecha && mecha in get_turf(port.recharge_floor)) + if(!mecha.cell) return + var/delta = min(max_charge, mecha.cell.maxcharge - mecha.cell.charge) + if(delta>0) + mecha.give_power(delta) + port.use_power(delta*150) + else + mecha.occupant_message("Fully charged.") + port.stop_charge() + else + port.stop_charge() + return + + + + +/obj/machinery/computer/mech_bay_power_console + name = "Mech Bay Power Control Console" + density = 1 + anchored = 1 + icon = 'icons/obj/computer.dmi' + icon_state = "recharge_comp" + circuit = "/obj/item/weapon/circuitboard/mech_bay_power_console" + var/autostart = 1 + var/voltage = 45 + var/obj/machinery/mech_bay_recharge_floor/recharge_floor + var/obj/machinery/mech_bay_recharge_port/recharge_port + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/mech_bay_power_console/proc/mecha_in(var/obj/mecha/mecha) + if(stat&(NOPOWER|BROKEN)) + mecha.occupant_message("Control console not responding. Terminating...") + return + if(recharge_port && autostart) + var/answer = recharge_port.start_charge(mecha) + if(answer) + recharge_port.set_voltage(voltage) + src.icon_state = initial(src.icon_state)+"_on" + return + +/obj/machinery/computer/mech_bay_power_console/proc/mecha_out() + if(recharge_port) + recharge_port.stop_charge() + return + + +/obj/machinery/computer/mech_bay_power_console/power_change() + if(stat & BROKEN) + icon_state = initial(icon_state)+"_broken" + if(recharge_port) + recharge_port.stop_charge() + else if(powered()) + icon_state = initial(icon_state) + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + icon_state = initial(icon_state)+"_nopower" + stat |= NOPOWER + if(recharge_port) + recharge_port.stop_charge() + +/obj/machinery/computer/mech_bay_power_console/set_broken() + icon_state = initial(icon_state)+"_broken" + stat |= BROKEN + if(recharge_port) + recharge_port.stop_charge() + +/obj/machinery/computer/mech_bay_power_console/attack_hand(mob/user as mob) + if(..()) + return + if(!src.stat && (get_dist(src, user) <= 1 || istype(user, /mob/living/silicon))) + return interact(user) + +/obj/machinery/computer/mech_bay_power_console/interact(mob/user as mob) + user.set_machine(src) + var/output = "[src.name]" + if(!recharge_floor) + output += "Mech Bay Recharge Station not initialized.
                      " + else + output += {"Mech Bay Recharge Station Data:
                      + Mecha: [recharge_floor.recharging_mecha||"None"]
                      "} + if(recharge_floor.recharging_mecha) + var/cell_charge = recharge_floor.recharging_mecha.get_charge() + output += "Cell charge: [isnull(cell_charge)?"No powercell found":"[recharge_floor.recharging_mecha.cell.charge]/[recharge_floor.recharging_mecha.cell.maxcharge]"]
                      " + output += "
                      " + if(!recharge_port) + output += "Mech Bay Power Port not initialized.
                      " + else + output += "Mech Bay Power Port Status: [recharge_port.active()?"Now charging":"On hold"]
                      " + + output += "" + user << browse(output, "window=mech_bay_console") + onclose(user, "mech_bay_console") + return + + +/obj/machinery/computer/mech_bay_power_console/Topic(href, href_list) + if(href_list["autostart"]) + autostart = !autostart + if(href_list["voltage"]) + voltage = text2num(href_list["voltage"]) + if(recharge_port) + recharge_port.set_voltage(voltage) + updateUsrDialog() + return diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 968a9885e1b..6d03bc6d079 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -1,88 +1,88 @@ -///////////////////////////// -///// Part Fabricator /////// -///////////////////////////// - -#define MECH_SCREEN_MAIN 01 - -#define MECH_SCREEN_ROBOT 11 -#define MECH_SCREEN_ROBOT_PARTS 12 -#define MECH_SCREEN_ROBOT_UPGRADES 13 - -#define MECH_SCREEN_EXOSUIT_TOOLS 21 -#define MECH_SCREEN_EXOSUIT_MODULES 22 -#define MECH_SCREEN_EXOSUIT_WEAPONS 23 - -#define MECH_SCREEN_RIPLEY 31 -#define MECH_SCREEN_ODYSSEUS 32 -#define MECH_SCREEN_GYGAX 33 -#define MECH_SCREEN_DURAND 34 -#define MECH_SCREEN_HONK 35 -#define MECH_SCREEN_PHAZON 36 - -#define MECH_SCREEN_MISC 41 - -#define MECH_BUILD_TIME 1 - -/obj/machinery/r_n_d/fabricator/mech - name = "Exosuit Fabricator" - desc = "A specialised fabricator for robotic and mechatronic components." - icon = 'icons/obj/robotics.dmi' - icon_state = "fab" - req_one_access = list(access_robotics) - - research_flags = NANOTOUCH | HASOUTPUT | HASMAT_OVER | TAKESMATIN | ACCESS_EMAG | LOCKBOXES - - nano_file = "exofab.tmpl" - - max_material_storage = 937500 - build_time = MECH_BUILD_TIME - build_number = 16 - - screen = MECH_SCREEN_MAIN - - part_sets = list(//set names must be unique - "Robot"=list( - ), - "Robot_Part" = list( - ), - "Ripley"=list( - ), - "Odysseus"=list( - ), - "Gygax"=list( - ), - "Durand"=list( - ), - "HONK"=list( - ), - "Phazon"=list( - ), - "Exosuit_Tools"=list( - /obj/item/mecha_parts/mecha_equipment/tool/sleeper, - /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun, - ), - "Exosuit_Modules"=list( - /obj/item/mecha_parts/part/phazon_phase_array - ), - "Exosuit_Weapons"=list( - ), - "Robotic_Upgrade_Modules" = list( - ), - "Misc"=list( - ) - ) - - -/obj/machinery/r_n_d/fabricator/mech/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/mechfab, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - +///////////////////////////// +///// Part Fabricator /////// +///////////////////////////// + +#define MECH_SCREEN_MAIN 01 + +#define MECH_SCREEN_ROBOT 11 +#define MECH_SCREEN_ROBOT_PARTS 12 +#define MECH_SCREEN_ROBOT_UPGRADES 13 + +#define MECH_SCREEN_EXOSUIT_TOOLS 21 +#define MECH_SCREEN_EXOSUIT_MODULES 22 +#define MECH_SCREEN_EXOSUIT_WEAPONS 23 + +#define MECH_SCREEN_RIPLEY 31 +#define MECH_SCREEN_ODYSSEUS 32 +#define MECH_SCREEN_GYGAX 33 +#define MECH_SCREEN_DURAND 34 +#define MECH_SCREEN_HONK 35 +#define MECH_SCREEN_PHAZON 36 + +#define MECH_SCREEN_MISC 41 + +#define MECH_BUILD_TIME 1 + +/obj/machinery/r_n_d/fabricator/mech + name = "Exosuit Fabricator" + desc = "A specialised fabricator for robotic and mechatronic components." + icon = 'icons/obj/robotics.dmi' + icon_state = "fab" + req_one_access = list(access_robotics) + + research_flags = NANOTOUCH | HASOUTPUT | HASMAT_OVER | TAKESMATIN | ACCESS_EMAG | LOCKBOXES + + nano_file = "exofab.tmpl" + + max_material_storage = 937500 + build_time = MECH_BUILD_TIME + build_number = 16 + + screen = MECH_SCREEN_MAIN + + part_sets = list(//set names must be unique + "Robot"=list( + ), + "Robot_Part" = list( + ), + "Ripley"=list( + ), + "Odysseus"=list( + ), + "Gygax"=list( + ), + "Durand"=list( + ), + "HONK"=list( + ), + "Phazon"=list( + ), + "Exosuit_Tools"=list( + /obj/item/mecha_parts/mecha_equipment/tool/sleeper, + /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun, + ), + "Exosuit_Modules"=list( + /obj/item/mecha_parts/part/phazon_phase_array + ), + "Exosuit_Weapons"=list( + ), + "Robotic_Upgrade_Modules" = list( + ), + "Misc"=list( + ) + ) + + +/obj/machinery/r_n_d/fabricator/mech/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/mechfab, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + RefreshParts() \ No newline at end of file diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 4367471b41e..478fe32c207 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1,1973 +1,1973 @@ -#define MECHA_INT_FIRE 1 -#define MECHA_INT_TEMP_CONTROL 2 -#define MECHA_INT_SHORT_CIRCUIT 4 -#define MECHA_INT_TANK_BREACH 8 -#define MECHA_INT_CONTROL_LOST 16 - -#define MELEE 1 -#define RANGED 2 - -#define STATE_BOLTSHIDDEN 0 -#define STATE_BOLTSEXPOSED 1 -#define STATE_BOLTSOPENED 2 - -/obj/mecha - name = "Mecha" - desc = "Exosuit" - icon = 'icons/mecha/mecha.dmi' - density = 1 //Dense. To raise the heat. - opacity = 1 ///opaque. Menacing. - anchored = 1 //no pulling around. - unacidable = 1 //and no deleting hoomans inside - layer = MOB_LAYER //icon draw layer - infra_luminosity = 15 //byond implementation is bugged. - var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items) - var/can_move = 1 - var/mob/living/carbon/occupant = null - var/step_in = 10 //make a step in step_in/10 sec. - var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South. - var/step_energy_drain = 10 - var/health = 300 //health is health - var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act. - //the values in this list show how much damage will pass through, not how much will be absorbed. - var/list/damage_absorption = list("brute"=0.8,"fire"=1.2,"bullet"=0.9,"laser"=1,"energy"=1,"bomb"=1) - var/obj/item/weapon/cell/cell - var/state = STATE_BOLTSHIDDEN - var/list/log = new - var/last_message = 0 - var/add_req_access = 1 - var/maint_access = 1 - var/dna //dna-locking the mech - var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference - var/datum/effect/effect/system/spark_spread/spark_system = new - var/lights = 0 - var/lights_power = 6 - - //inner atmos - var/use_internal_tank = 0 - var/internal_tank_valve = ONE_ATMOSPHERE - var/obj/machinery/portable_atmospherics/canister/internal_tank - var/datum/gas_mixture/cabin_air - var/obj/machinery/atmospherics/unary/portables_connector/connected_port = null - - var/obj/item/device/radio/radio = null - var/obj/item/device/radio/electropack/electropack = null - var/obj/item/mecha_parts/mecha_tracking/tracking = null - - var/max_temperature = 25000 - var/internal_damage_threshold = 50 //health percentage below which internal damage is possible - var/internal_damage = 0 //contains bitflags - - var/list/operation_req_access = list()//required access level for mecha operation - var/list/internals_req_access = list(access_engine,access_robotics)//required access level to open cell compartment - - var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature - var/datum/global_iterator/pr_inertial_movement //controls intertial movement in spesss - var/datum/global_iterator/pr_give_air //moves air from tank to cabin - var/datum/global_iterator/pr_internal_damage //processes internal damage - - - var/wreckage - - var/list/equipment = new - var/obj/item/mecha_parts/mecha_equipment/selected - var/max_equip = 3 - var/datum/events/events - - var/turf/crashing = null - var/list/mech_parts = list(/obj/item/weapon/cell, - /obj/machinery/portable_atmospherics/canister, //I shit you not this thing uses a literal air canister - /obj/item/device/radio, - /obj/item/mecha_parts, - /obj/item/device/mmi, - /obj/item/mecha_parts/mecha_tracking, - /obj/item/device/radio/electropack) - -/obj/mecha/New() - ..() - events = new - icon_state += "-open" - add_radio() - add_cabin() - if(!add_airtank()) //we check this here in case mecha does not have an internal tank available by default - WIP - removeVerb(/obj/mecha/verb/connect_to_port) - removeVerb(/obj/mecha/verb/toggle_internal_tank) - spark_system.set_up(2, 0, src) - spark_system.attach(src) - add_cell() - add_iterators() - removeVerb(/obj/mecha/verb/disconnect_from_port) - log_message("[src.name] created.") - loc.Entered(src) - mechas_list += src //global mech list - return - -/obj/mecha/Destroy() - src.go_out() - mechas_list -= src //global mech list - ..() - return - -//////////////////////// -////// Helpers ///////// -//////////////////////// - -/obj/mecha/proc/removeVerb(verb_path) - verbs -= verb_path - -/obj/mecha/proc/addVerb(verb_path) - verbs += verb_path - -/obj/mecha/proc/add_airtank() - internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src) - return internal_tank - -/obj/mecha/proc/add_cell(var/obj/item/weapon/cell/C=null) - if(C) - C.forceMove(src) - cell = C - return - cell = new(src) - cell.charge = 15000 - cell.maxcharge = 15000 - -/obj/mecha/proc/add_cabin() - cabin_air = new - cabin_air.temperature = T20C - cabin_air.volume = 200 - cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) - cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) - return cabin_air - -/obj/mecha/proc/add_radio() - radio = new(src) - radio.name = "[src] radio" - radio.icon = icon - radio.icon_state = icon_state - radio.subspace_transmission = 1 - -/obj/mecha/proc/add_iterators() - pr_int_temp_processor = new /datum/global_iterator/mecha_preserve_temp(list(src)) - pr_inertial_movement = new /datum/global_iterator/mecha_intertial_movement(null,0) - pr_give_air = new /datum/global_iterator/mecha_tank_give_air(list(src)) - pr_internal_damage = new /datum/global_iterator/mecha_internal_damage(list(src),0) - -/obj/mecha/proc/do_after(delay as num) - sleep(delay) - if(src) - return 1 - return 0 - -/obj/mecha/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5) - var/delayfraction = delay/numticks - - var/turf/T = user.loc - - for(var/i = 0, iIt's fully intact.") - if(65 to 85) - to_chat(user, "It's slightly damaged.") - if(45 to 65) - to_chat(user, "It's badly damaged.") - if(25 to 45) - to_chat(user, "It's heavily damaged.") - else - to_chat(user, "It's falling apart.") - if(equipment && equipment.len) - to_chat(user, "It's equipped with:") - for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment) - to_chat(user, "\icon[ME] [ME]") - -/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits. - return - -/obj/mecha/Hear(var/datum/speech/speech, var/rendered_message="") - if(speech.speaker == occupant && radio.broadcasting) - radio.talk_into(speech) - return - -//////////////////////////// -///// Action processing //// -//////////////////////////// -/* -/atom/DblClick(object,location,control,params) - var/mob/M = src.mob - if(M && M.in_contents_of(/obj/mecha)) - - if(mech_click == world.time) return - mech_click = world.time - - if(!istype(object, /atom)) return - if(istype(object, /obj/screen)) - var/obj/screen/using = object - if(using.screen_loc == ui_acti || using.screen_loc == ui_iarrowleft || using.screen_loc == ui_iarrowright)//ignore all HUD objects save 'intent' and its arrows - return ..() - else - return - var/obj/mecha/Mech = M.loc - spawn() //this helps prevent clickspam fest. - if (Mech) - Mech.click_action(object,M) -// else -// return ..() -*/ - -/obj/mecha/proc/click_action(atom/target,mob/user) - if(!src.occupant || src.occupant != user ) return - if(user.stat) return - if(state) - occupant_message("Maintenance protocols in effect.") - return - if(!get_charge()) return - if(src == target) return - var/dir_to_target = get_dir(src,target) - if(dir_to_target && !(dir_to_target & src.dir))//wrong direction - return - if(hasInternalDamage(MECHA_INT_CONTROL_LOST)) - target = safepick(view(3,target)) - if(!target) - return - if(get_dist(src, target)>1) - if(selected && selected.is_ranged()) - selected.action(target) - else if(selected && selected.is_melee()) - selected.action(target) - else - src.melee_action(target) - return - - -/obj/mecha/proc/melee_action(atom/target) - return - -/obj/mecha/proc/range_action(atom/target) - return - - -////////////////////////////////// -//////// Movement procs //////// -////////////////////////////////// - -/obj/mecha/Move() - . = ..() - if(.) - events.fireEvent("onMove",get_turf(src)) - return - -/obj/mecha/relaymove(mob/user,direction) - if(user != src.occupant) //While not "realistic", this piece is player friendly. - user.forceMove(get_turf(src)) - to_chat(user, "You climb out from [src]") - return 0 - if(connected_port) - if(world.time - last_message > 20) - src.occupant_message("Unable to move while connected to the air system port") - last_message = world.time - return 0 - if(state) - occupant_message("Maintenance protocols in effect.") - return - return domove(direction) - -/obj/mecha/proc/domove(direction) - return call((proc_res["dyndomove"]||src), "dyndomove")(direction) - -/obj/mecha/proc/dyndomove(direction) - if(!can_move) - return 0 - if(src.pr_inertial_movement.active()) - return 0 - if(!has_charge(step_energy_drain)) - return 0 - var/move_result = 0 - if(hasInternalDamage(MECHA_INT_CONTROL_LOST)) - move_result = mechsteprand() - else if(src.dir!=direction) - move_result = mechturn(direction) - else - move_result = mechstep(direction) - if(move_result) - can_move = 0 - use_power(step_energy_drain) - if(istype(src.loc, /turf/space)) - if(!src.check_for_support()) - src.pr_inertial_movement.start(list(src,direction)) - src.log_message("Movement control lost. Inertial movement started.") - if(do_after(step_in)) - can_move = 1 - return 1 - return 0 - -/obj/mecha/proc/mechturn(direction) - dir = direction - playsound(src,'sound/mecha/mechturn.ogg',40,1) - return 1 - -/obj/mecha/proc/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src, get_sfx("mechstep"),40,1) - return result - - -/obj/mecha/proc/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src, get_sfx("mechstep"),40,1) - return result - -/obj/mecha/Bump(var/atom/obstacle) -// src.inertia_dir = null - if(src.throwing)//high velocity mechas in your face! - var/breakthrough = 0 - if(istype(obstacle, /obj/structure/window/)) - obstacle.Destroy(brokenup = 1) - breakthrough = 1 - - else if(istype(obstacle, /obj/structure/grille/)) - var/obj/structure/grille/G = obstacle - G.health = (0.25*initial(G.health)) - G.broken = 1 - G.icon_state = "[initial(G.icon_state)]-b" - G.density = 0 - getFromPool(/obj/item/stack/rods, get_turf(G.loc)) - breakthrough = 1 - - else if(istype(obstacle, /obj/structure/table)) - var/obj/structure/table/T = obstacle - T.destroy() - breakthrough = 1 - - else if(istype(obstacle, /obj/structure/rack)) - new /obj/item/weapon/rack_parts(obstacle.loc) - qdel(obstacle) - breakthrough = 1 - - else if(istype(obstacle, /obj/structure/reagent_dispensers/fueltank)) - obstacle.ex_act(1) - - else if(istype(obstacle, /mob/living/carbon)) - var/mob/living/carbon/C = obstacle - var/hit_sound = list('sound/weapons/genhit1.ogg','sound/weapons/genhit2.ogg','sound/weapons/genhit3.ogg') - if(C.flags & INVULNERABLE) - return - C.take_overall_damage(5,0) - if(C.locked_to) - C.locked_to = 0 - C.Stun(5) - C.Weaken(5) - C.apply_effect(STUTTER, 5) - playsound(src, pick(hit_sound), 50, 0, 0) - breakthrough = 1 - - else - src.throwing = 0//so mechas don't get stuck when landing after being sent by a Mass Driver - src.crashing = null - - if(breakthrough) - if(crashing) - spawn(1) - src.throw_at(crashing, 50, src.throw_speed) - else - spawn(1) - crashing = get_distant_turf(get_turf(src), dir, 3)//don't use get_dir(src, obstacle) or the mech will stop if he bumps into a one-direction window on his tile. - src.throw_at(crashing, 50, src.throw_speed) - - if(istype(obstacle, /obj)) - var/obj/O = obstacle - if(istype(O, /obj/effect/portal)) //derpfix - src.anchored = 0 - O.Crossed(src) - spawn(0)//countering portal teleport spawn(0), hurr - src.anchored = 1 - else if(!O.anchored) - step(obstacle,src.dir) - else //I have no idea why I disabled this - obstacle.Bumped(src) - else if(istype(obstacle, /mob)) - step(obstacle,src.dir) - else - obstacle.Bumped(src) - return - -/////////////////////////////////// -//////// Internal damage //////// -/////////////////////////////////// - -/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) - if(!islist(possible_int_damage) || isemptylist(possible_int_damage)) return - if(prob(20)) - if(ignore_threshold || src.health*100/initial(src.health)Life support system reactivated.
                      ") - pr_int_temp_processor.start() - if(MECHA_INT_FIRE) - occupant_message("Internal fire extinquished.") - if(MECHA_INT_TANK_BREACH) - occupant_message("Damaged internal tank has been sealed.") - return - - -//////////////////////////////////////// -//////// Health related procs //////// -//////////////////////////////////////// - -/obj/mecha/proc/take_damage(amount, type="brute") - if(amount) - var/damage = absorbDamage(amount,type) - health -= damage - update_health() - log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1) - return - -/obj/mecha/proc/absorbDamage(damage,damage_type) - return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type) - -/obj/mecha/proc/dynabsorbdamage(damage,damage_type) - return damage*(listgetindex(damage_absorption,damage_type) || 1) - - -/obj/mecha/proc/update_health() - if(src.health > 0) - src.spark_system.start() - else - src.destroy() - return - -/obj/mecha/attack_hand(mob/user as mob) - src.log_message("Attack by hand/paw. Attacker - [user].",1) - - if ((M_HULK in user.mutations) && !prob(src.deflect_chance)) - src.take_damage(15) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - user.visible_message("[user] hits [src.name], doing some damage.", "You hit [src.name] with all your might. The metal creaks and bends.") - else - user.visible_message("[user] hits [src.name]. Nothing happens","You hit [src.name] with no visible effect.") - src.log_append_to_last("Armor saved.") - return - -/obj/mecha/attack_paw(mob/user as mob) - return src.attack_hand(user) - - -/obj/mecha/attack_alien(mob/user as mob) - src.log_message("Attack by alien. Attacker - [user].",1) - if(!prob(src.deflect_chance)) - src.take_damage(15) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) - to_chat(user, "You slash at the armored suit!") - visible_message("The [user] slashes at [src.name]'s armor!") - else - src.log_append_to_last("Armor saved.") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) - to_chat(user, "Your claws had no effect!") - src.occupant_message("The [user]'s claws are stopped by the armor.") - visible_message("The [user] rebounds off [src.name]'s armor!") - return - - -/obj/mecha/attack_animal(mob/living/simple_animal/user as mob) - src.log_message("Attack by simple animal. Attacker - [user].",1) - if(user.melee_damage_upper == 0) - user.emote("[user.friendly] [src]") - else - if(!prob(src.deflect_chance)) - var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) - src.take_damage(damage) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - visible_message("[user] [user.attacktext] [src]!") - user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") - else - src.log_append_to_last("Armor saved.") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) - src.occupant_message("The [user]'s attack is stopped by the armor.") - visible_message("The [user] rebounds off [src.name]'s armor!") - user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") - return - -/obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper - src.log_message("Hit by [A].",1) - call((proc_res["dynhitby"]||src), "dynhitby")(A) - return - -/obj/mecha/proc/dynhitby(atom/movable/A) - if(istype(A, /obj/item/mecha_parts/mecha_tracking) && !tracking && prob(25)) - A.forceMove(src) - tracking = A - src.visible_message("The [A] fastens firmly to [src].") - return - if(prob(src.deflect_chance) || istype(A, /mob)) - src.occupant_message("The [A] bounces off the armor.") - src.visible_message("The [A] bounces off the [src.name] armor") - src.log_append_to_last("Armor saved.") - if(istype(A, /mob/living)) - var/mob/living/M = A - M.take_organ_damage(10) - else if(istype(A, /obj)) - var/obj/O = A - if(O.throwforce) - src.take_damage(O.throwforce) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - return - - -/obj/mecha/bullet_act(var/obj/item/projectile/Proj) //wrapper - src.log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1) - call((proc_res["dynbulletdamage"]||src), "dynbulletdamage")(Proj) //calls equipment - ..() - return - -/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj) - if(prob(src.deflect_chance)) - src.occupant_message("The armor deflects incoming projectile.") - src.visible_message("The [src.name] armor deflects the projectile") - src.log_append_to_last("Armor saved.") - return - var/ignore_threshold - if(Proj.flag == "taser") - use_power(200) - return - if(istype(Proj, /obj/item/projectile/beam/pulse)) - ignore_threshold = 1 - src.take_damage(Proj.damage,Proj.flag) - src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold) - Proj.on_hit(src) - return - -/obj/mecha/proc/destroy() - spawn() - go_out() - var/turf/T = get_turf(src) - tag = "\ref[src]" //better safe then sorry - if(loc) - loc.Exited(src) - loc = null - if(T) - if(istype(src, /obj/mecha/working/ripley/)) - var/obj/mecha/working/ripley/R = src - if(R.cargo) - for(var/obj/O in R.cargo) //Dump contents of stored cargo - O.loc = T - R.cargo -= O - T.Entered(O) - - if(prob(30)) - explosion(T, 0, 0, 1, 3) - spawn(0) - if(wreckage) - var/obj/effect/decal/mecha_wreckage/WR = new wreckage(T) - for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) - if(E.salvageable && prob(30)) - WR.crowbar_salvage += E - E.forceMove(WR) - E.equip_ready = 1 - E.reliability = round(rand(E.reliability/3,E.reliability)) - else - E.forceMove(T) - E.destroy() - if(cell) - WR.crowbar_salvage += cell - cell.forceMove(WR) - cell.charge = rand(0, cell.charge) - if(internal_tank) - WR.crowbar_salvage += internal_tank - internal_tank.forceMove(WR) - else - for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) - E.forceMove(T) - E.destroy() - spawn(0) - qdel(src) - return - -/obj/mecha/ex_act(severity) - src.log_message("Affected by explosion of severity: [severity].",1) - if(prob(src.deflect_chance)) - severity++ - src.log_append_to_last("Armor saved, changing severity to [severity].") - switch(severity) - if(1.0) - src.destroy() - if(2.0) - if (prob(30)) - src.destroy() - else - src.take_damage(initial(src.health)/2) - src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - if(3.0) - if (prob(5)) - src.destroy() - else - src.take_damage(initial(src.health)/5) - src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - return - -/*Will fix later -Sieve -/obj/mecha/attack_blob(mob/user as mob) - src.log_message("Attack by blob. Attacker - [user].",1) - if(!prob(src.deflect_chance)) - src.take_damage(6) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1) - to_chat(user, "You smash at the armored suit!") - for (var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("The [user] smashes against [src.name]'s armor!", 1) - else - src.log_append_to_last("Armor saved.") - playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1) - to_chat(user, "Your attack had no effect!") - src.occupant_message("The [user]'s attack is stopped by the armor.") - for (var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("The [user] rebounds off the [src.name] armor!", 1) - return -*/ - -/obj/mecha/blob_act() - take_damage(30, "brute") - return - -/obj/mecha/emp_act(severity) - if(get_charge()) - use_power((cell.charge/2)/severity) - take_damage(50 / severity,"energy") - src.log_message("EMP detected",1) - check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - return - -/obj/mecha/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature>src.max_temperature) - src.log_message("Exposed to dangerous temperature.",1) - src.take_damage(5,"fire") - src.check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL)) - return - -/obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) - user.delayNextAttack(8) - src.log_message("Attacked by [W]. Attacker - [user]") - if(prob(src.deflect_chance)) - to_chat(user, "The [W] bounces off [src.name] armor.") - src.log_append_to_last("Armor saved.") -/* - for (var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("The [W] bounces off [src.name] armor.", 1) -*/ - else - src.occupant_message("[user] hits [src] with [W].") - user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].") - src.take_damage(W.force,W.damtype) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - return - -////////////////////// -////// AttackBy ////// -////////////////////// - -/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob) - - - if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain)) - if(mmi_move_inside(W,user)) - to_chat(user, "[src]-MMI interface initialized successfuly") - else - to_chat(user, "[src]-MMI interface initialization failed.") - return - - if(istype(W, /obj/item/mecha_parts/mecha_equipment)) - var/obj/item/mecha_parts/mecha_equipment/E = W - spawn() - if(E.can_attach(src)) - if(user.drop_item(W)) - E.attach(src) - user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - else - to_chat(user, "You were unable to attach [W] to [src]") - return - if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if(add_req_access || maint_access) - if(internals_access_allowed(usr)) - var/obj/item/weapon/card/id/id_card - if(istype(W, /obj/item/weapon/card/id)) - id_card = W - else - var/obj/item/device/pda/pda = W - id_card = pda.id - output_maintenance_dialog(id_card, user) - return - else - to_chat(user, "Invalid ID: Access denied.") - else - to_chat(user, "Maintenance protocols disabled by operator.") - else if(istype(W, /obj/item/weapon/wrench)) - if(state==STATE_BOLTSEXPOSED) - state = STATE_BOLTSOPENED - to_chat(user, "You undo the securing bolts.") - playsound(src, 'sound/items/Ratchet.ogg', 50, 1) - else if(state==STATE_BOLTSOPENED) - state = STATE_BOLTSEXPOSED - to_chat(user, "You tighten the securing bolts.") - playsound(src, 'sound/items/Ratchet.ogg', 50, 1) - return - else if(istype(W, /obj/item/weapon/crowbar)) - if(state==STATE_BOLTSOPENED) - var/list/removable_components = list() - if(cell) removable_components += "power cell" - if(tracking) removable_components += "exosuit tracking beacon" - if(electropack) removable_components += "electropack" - var/obj/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components - if(!remove) - return - switch(remove) - if ("power cell") - cell.forceMove(src.loc) - cell = null - if ("exosuit tracking beacon") - tracking.forceMove(src.loc) - tracking = null - if ("electropack") - electropack.forceMove(src.loc) - electropack = null - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You pry out \the [remove] from \the [src].") - src.log_message("Internal component removed - [remove]") - return - else if(istype(W, /obj/item/stack/cable_coil)) - if(state == STATE_BOLTSOPENED && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - var/obj/item/stack/cable_coil/CC = W - if(CC.amount > 1) - CC.use(2) - clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) - to_chat(user, "You replace the fused wires.") - else - to_chat(user, "There's not enough wire to finish the task.") - return - else if(istype(W, /obj/item/weapon/screwdriver)) - if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) - clearInternalDamage(MECHA_INT_TEMP_CONTROL) - to_chat(user, "You repair the damaged temperature controller.") - return - else if(istype(W, /obj/item/weapon/cell)) - if(state==STATE_BOLTSOPENED) - if(!src.cell) - if(user.drop_item(W, src)) - to_chat(user, "You install the powercell.") - src.cell = W - src.log_message("Powercell installed.") - else - to_chat(user, "There's already a powercell installed.") - return - else if(istype(W, /obj/item/mecha_parts/mecha_tracking)) - if(state==STATE_BOLTSOPENED) - if(!src.tracking) - if(user.drop_item(W, src)) - to_chat(user, "You install the tracking beacon and safeties.") - src.tracking = W - src.log_message("Exosuit tracking beacon installed.") - else - to_chat(user, "There's already a tracking beacon installed.") - return - else if(istype(W, /obj/item/device/radio/electropack)) - if(state==STATE_BOLTSOPENED) - if(!src.electropack) - if(user.drop_item(W, src)) - to_chat(user, "You rig the electropack to the cockpit.") - src.electropack = W - src.log_message("Emergency ejection routines installed.") //not exactly a legitimate upgrade! - else - to_chat(user, "There's already an electropack installed.") - return - - else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != I_HURT) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0,user)) - if (hasInternalDamage(MECHA_INT_TANK_BREACH)) - clearInternalDamage(MECHA_INT_TANK_BREACH) - to_chat(user, "You repair the damaged gas tank.") - else - return - if(src.healthYou repair some damage to [src.name].") - src.health += min(10, initial(src.health)-src.health) - else - to_chat(user, "The [src.name] is at full integrity") - return - - else - call((proc_res["dynattackby"]||src), "dynattackby")(W,user) -/* - src.log_message("Attacked by [W]. Attacker - [user]") - if(prob(src.deflect_chance)) - to_chat(user, "The [W] bounces off [src.name] armor.") - src.log_append_to_last("Armor saved.") -/* - for (var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("The [W] bounces off [src.name] armor.", 1) -*/ - else - src.occupant_message("[user] hits [src] with [W].") - user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].") - src.take_damage(W.force,W.damtype) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) -*/ - return - - - -/* -/obj/mecha/attack_ai(var/mob/living/silicon/ai/user as mob) - if(!istype(user, /mob/living/silicon/ai)) - return - var/output = {"Assume direct control over [src]? - Yes
                      - "} - user << browse(output, "window=mecha_attack_ai") - return -*/ - -///////////////////////////////////// -//////// Atmospheric stuff //////// -///////////////////////////////////// - -/obj/mecha/proc/get_turf_air() - var/turf/T = get_turf(src) - if(T) - . = T.return_air() - return - -/obj/mecha/remove_air(amount) - if(use_internal_tank) - return cabin_air.remove(amount) - else - var/turf/T = get_turf(src) - if(T) - return T.remove_air(amount) - return - -/obj/mecha/return_air() - if(use_internal_tank) - return cabin_air - return get_turf_air() - -/obj/mecha/proc/return_pressure() - . = 0 - if(use_internal_tank) - . = cabin_air.return_pressure() - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.return_pressure() - return - -//skytodo: //No idea what you want me to do here, mate. -/obj/mecha/proc/return_temperature() - . = 0 - if(use_internal_tank) - . = cabin_air.return_temperature() - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.return_temperature() - return - -/obj/mecha/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port) - //Make sure not already connected to something else - if(connected_port || !new_port || new_port.connected_device) - return 0 - - //Make sure are close enough for a valid connection - if(new_port.loc != src.loc) - return 0 - - //Perform the connection - connected_port = new_port - connected_port.connected_device = src - - //Actually enforce the air sharing - var/datum/pipe_network/network = connected_port.return_network(src) - if(network && !(internal_tank.return_air() in network.gases)) - network.gases += internal_tank.return_air() - network.update = 1 - log_message("Connected to gas port.") - return 1 - -/obj/mecha/proc/disconnect() - if(!connected_port) - return 0 - - var/datum/pipe_network/network = connected_port.return_network(src) - if(network) - network.gases -= internal_tank.return_air() - - connected_port.connected_device = null - connected_port = null - src.log_message("Disconnected from gas port.") - return 1 - - -///////////////////////// -//////// Verbs //////// -///////////////////////// - - -/obj/mecha/verb/connect_to_port() - set name = "Connect to port" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(!src.occupant) return - if(usr!=src.occupant) - return - var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc - if(possible_port) - if(connect(possible_port)) - src.occupant_message("[name] connects to the port.") - src.verbs += /obj/mecha/verb/disconnect_from_port - src.verbs -= /obj/mecha/verb/connect_to_port - return - else - src.occupant_message("[name] failed to connect to the port.") - return - else - src.occupant_message("Nothing happens") - - -/obj/mecha/verb/disconnect_from_port() - set name = "Disconnect from port" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(!src.occupant) return - if(usr!=src.occupant) - return - if(disconnect()) - src.occupant_message("[name] disconnects from the port.") - src.verbs -= /obj/mecha/verb/disconnect_from_port - src.verbs += /obj/mecha/verb/connect_to_port - else - src.occupant_message("[name] is not connected to the port at the moment.") - -/obj/mecha/verb/toggle_lights() - set name = "Toggle Lights" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=occupant) return - lights = !lights - if(lights) set_light(luminosity + lights_power) - else set_light(luminosity - lights_power) - src.occupant_message("Toggled lights [lights?"on":"off"].") - log_message("Toggled lights [lights?"on":"off"].") - return - - -/obj/mecha/verb/toggle_internal_tank() - set name = "Toggle internal airtank usage." - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - use_internal_tank = !use_internal_tank - src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") - src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") - return - -/obj/mecha/MouseDrop_T(mob/M as mob, mob/user as mob) - if(M != user) - return - move_inside(M, user) - -/obj/mecha/verb/move_inside() - set category = "Object" - set name = "Enter Exosuit" - set src in oview(1) - - if(usr.restrained() || usr.isUnconscious() || usr.weakened || usr.stunned || usr.paralysis || usr.resting) //are you cuffed, dying, lying, stunned or other - return - if (usr.stat || !ishuman(usr)) - return - src.log_message("[usr] tries to move in.") - if (src.occupant) - to_chat(usr, "The [src.name] is already occupied!") - src.log_append_to_last("Permission denied.") - return -/* - if (usr.abiotic()) - to_chat(usr, "Subject cannot have abiotic items on.") - return -*/ - var/passed - if(src.dna) - if(usr.dna.unique_enzymes==src.dna) - passed = 1 - else if(src.operation_allowed(usr)) - passed = 1 - if(!passed) - to_chat(usr, "Access Denied.") - src.log_append_to_last("Permission denied.") - return - for(var/mob/living/carbon/slime/M in range(1,usr)) - if(M.Victim == usr) - to_chat(usr, "You're too busy getting your life sucked out of you.") - return - - visible_message("[usr] starts to climb into [src.name]") - - - if(enter_after(40,usr)) - if(!src.occupant) - moved_inside(usr) - else if(src.occupant!=usr) - to_chat(usr, "[src.occupant] was faster. Try better next time, loser.") - else - to_chat(usr, "You stop entering the exosuit.") - return - -/obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob) - if(!isnull(src.loc) && H && H.client && H in range(1)) - H.reset_view(src) - /* - H.client.perspective = EYE_PERSPECTIVE - H.client.eye = src - */ - H.stop_pulling() - H.forceMove(src) - src.occupant = H - src.add_fingerprint(H) - src.forceMove(src.loc) - src.log_append_to_last("[H] moved in as pilot.") - src.icon_state = src.reset_icon() - dir = dir_in - playsound(src, 'sound/mecha/mechentry.ogg', 50, 1) - if(!hasInternalDamage()) - to_chat(src.occupant, sound('sound/mecha/nominalsyndi.ogg',volume=50)) - - // -- Mode/mind specific stuff goes here - if(H.mind) - if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries)) - ticker.mode.update_all_rev_icons() - if(H.mind in ticker.mode.syndicates) - ticker.mode.update_all_synd_icons() - if (H.mind in ticker.mode.cult) - ticker.mode.update_all_cult_icons() - if(H.mind in ticker.mode.wizards) - ticker.mode.update_all_wizard_icons() - // -- End mode specific stuff - - return 1 - else - return 0 - -/obj/mecha/proc/mmi_move_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) - if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client) - to_chat(user, "Consciousness matrix not detected.") - return 0 - else if(mmi_as_oc.brainmob.stat) - to_chat(user, "Beta-rhythm below acceptable level.") - return 0 - else if(occupant) - to_chat(user, "Occupant detected.") - return 0 - else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes) - to_chat(user, "Stop it!") - return 0 - //Added a message here since people assume their first click failed or something./N -// to_chat(user, "Installing MMI, please stand by.") - - visible_message("[usr] starts to insert an MMI into [src.name]") - - if(enter_after(40,user)) - if(!occupant) - return mmi_moved_inside(mmi_as_oc,user) - else - to_chat(user, "Occupant detected.") - else - to_chat(user, "You stop inserting the MMI.") - return 0 - -/obj/mecha/proc/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) - if(!isnull(src.loc) && mmi_as_oc && user in range(1)) - if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client) - to_chat(user, "Consciousness matrix not detected.") - return 0 - else if(mmi_as_oc.brainmob.stat) - to_chat(user, "Beta-rhythm below acceptable level.") - return 0 - user.drop_from_inventory(mmi_as_oc) - var/mob/brainmob = mmi_as_oc.brainmob - brainmob.reset_view(src) - /* - brainmob.client.eye = src - brainmob.client.perspective = EYE_PERSPECTIVE - */ - occupant = brainmob - brainmob.loc = src //should allow relaymove - brainmob.canmove = 1 - mmi_as_oc.loc = src - mmi_as_oc.mecha = src - src.verbs -= /obj/mecha/verb/eject - src.Entered(mmi_as_oc) - src.Move(src.loc) - src.icon_state = src.reset_icon() - dir = dir_in - src.log_message("[mmi_as_oc] moved in as pilot.") - if(!hasInternalDamage()) - to_chat(src.occupant, sound('sound/mecha/nominalsyndi.ogg',volume=50)) - return 1 - else - return 0 - -/obj/mecha/verb/view_stats() - set name = "View Stats" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - //pr_update_stats.start() - src.occupant << browse(src.get_stats_html(), "window=exosuit") - return - -/* -/obj/mecha/verb/force_eject() - set category = "Object" - set name = "Force Eject" - set src in view(5) - src.go_out() - return -*/ - -/obj/mecha/verb/eject() - set name = "Eject" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - src.go_out() - add_fingerprint(usr) - return - -/obj/mecha/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) - if(usr!=src.occupant) - return - if(!istype(over_location) || over_location.density) - return - if(!Adjacent(over_location)) - return - for(var/atom/movable/A in over_location.contents) - if(A.density) - if((A == src) || istype(A, /mob)) - continue - return - if(istype(over_location)) - go_out(over_location) - add_fingerprint(usr) - -/obj/mecha/proc/empty_bad_contents() //stuff that shouldn't be there, possibly caused by the driver dropping it while inside the mech - for(var/obj/O in src) - if(!is_type_in_list(O,mech_parts)) - O.loc = src.loc - return - -/obj/mecha/proc/go_out(var/exit = loc) - if(!src.occupant) return - var/atom/movable/mob_container - if(ishuman(occupant)) - mob_container = src.occupant - else if(istype(occupant, /mob/living/carbon/brain)) - var/mob/living/carbon/brain/brain = occupant - mob_container = brain.container - else - return - if(mob_container.forceMove(exit))//ejecting mob container - /* - if(ishuman(occupant) && (return_pressure() > HAZARD_HIGH_PRESSURE)) - use_internal_tank = 0 - var/datum/gas_mixture/environment = get_turf_air() - if(environment) - var/env_pressure = environment.return_pressure() - var/pressure_delta = (cabin.return_pressure() - env_pressure) - //Can not have a pressure delta that would cause environment pressure > tank pressure - - var/transfer_moles = 0 - if(pressure_delta > 0) - transfer_moles = pressure_delta*environment.volume/(cabin.return_temperature() * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = cabin.air_contents.remove(transfer_moles) - loc.assume_air(removed) - - occupant.SetStunned(5) - occupant.SetWeakened(5) - to_chat(occupant, "You were blown out of the mech!") - */ - src.log_message("[mob_container] moved out.") - occupant.reset_view() - /* - if(src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE - */ - empty_bad_contents() - src.occupant << browse(null, "window=exosuit") - if(istype(mob_container, /obj/item/device/mmi) || istype(mob_container, /obj/item/device/mmi/posibrain)) - var/obj/item/device/mmi/mmi = mob_container - if(mmi.brainmob) - occupant.loc = mmi - mmi.mecha = null - src.occupant.canmove = 0 - src.verbs += /obj/mecha/verb/eject - - // -- Mode/mind specific stuff goes here - if(src.occupant.mind) - if((src.occupant.mind in ticker.mode:revolutionaries) || (src.occupant.mind in ticker.mode:head_revolutionaries)) - ticker.mode.update_all_rev_icons() - if(src.occupant.mind in ticker.mode.syndicates) - ticker.mode.update_all_synd_icons() - if (src.occupant.mind in ticker.mode.cult) - ticker.mode.update_all_cult_icons() - if(src.occupant.mind in ticker.mode.wizards) - ticker.mode.update_all_wizard_icons() - // -- End mode specific stuff - - src.occupant = null - src.icon_state = src.reset_icon()+"-open" - src.dir = dir_in - - return - -/obj/mecha/proc/shock_n_boot(var/exit = loc) - spark_system.start() - if (occupant) - to_chat(occupant, "You feel a sharp shock!") - occupant.Weaken(10) - spawn(10) - emergency_eject() - -/obj/mecha/proc/emergency_eject(var/exit = loc) - if (occupant) - to_chat(occupant, sound('sound/machines/warning.ogg',wait=0)) - log_message("Emergency ejection.",1) - occupant_message("Emergency ejection protocol engaged.") - spawn(10) - if (occupant) - go_out() - -///////////////////////// -////// Access stuff ///// -///////////////////////// - -/obj/mecha/proc/operation_allowed(mob/living/carbon/human/H) - for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt)) - if(src.check_access(ID,src.operation_req_access)) - return 1 - return 0 - - -/obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H) - for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt)) - if(src.check_access(ID,src.internals_req_access)) - return 1 - return 0 - - -/obj/mecha/check_access(obj/item/weapon/card/id/I, list/access_list) - if(!istype(access_list)) - return 1 - if(!access_list.len) //no requirements - return 1 - if(istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if(!istype(I) || !I.access) //not ID or no access - return 0 - if(access_list==src.operation_req_access) - for(var/req in access_list) - if(!(req in I.access)) //doesn't have this access - return 0 - else if(access_list==src.internals_req_access) - for(var/req in access_list) - if(req in I.access) - return 1 - return 1 - - -//////////////////////////////////// -///// Rendering stats window /////// -//////////////////////////////////// - -/obj/mecha/proc/get_stats_html() - var/output = {" - [src.name] data - - - - -
                      - [src.get_stats_part()] -
                      -
                      - [src.get_equipment_list()] -
                      -
                      -
                      - [src.get_commands()] -
                      - - - "} - return output - - -/obj/mecha/proc/report_internal_damage() - var/output = null - var/list/dam_reports = list( - "[MECHA_INT_FIRE]" = "INTERNAL FIRE", - "[MECHA_INT_TEMP_CONTROL]" = "LIFE SUPPORT SYSTEM MALFUNCTION", - "[MECHA_INT_TANK_BREACH]" = "GAS TANK BREACH", - "[MECHA_INT_CONTROL_LOST]" = "COORDINATION SYSTEM CALIBRATION FAILURE - Recalibrate", - "[MECHA_INT_SHORT_CIRCUIT]" = "SHORT CIRCUIT" - ) - for(var/tflag in dam_reports) - var/intdamflag = text2num(tflag) - if(hasInternalDamage(intdamflag)) - output += dam_reports[tflag] - output += "
                      " - if(return_pressure() > WARNING_HIGH_PRESSURE) - output += "DANGEROUSLY HIGH CABIN PRESSURE
                      " - return output - - -/obj/mecha/proc/get_stats_part() - var/integrity = health/initial(health)*100 - var/cell_charge = get_charge() - var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" - var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" - var/cabin_pressure = round(return_pressure(),0.01) - var/output = {"[report_internal_damage()] - [integrity<30?"DAMAGE LEVEL CRITICAL
                      ":null] - Integrity: [integrity]%
                      - Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
                      - Air source: [use_internal_tank?"Internal Airtank":"Environment"]
                      - Airtank pressure: [tank_pressure]kPa
                      - Airtank temperature: [tank_temperature]K|[tank_temperature - T0C]°C
                      - Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
                      - Cabin temperature: [return_temperature()]K|[return_temperature() - T0C]°C
                      - Lights: [lights?"on":"off"]
                      - [src.dna?"DNA-locked:
                      [src.dna] \[Reset\]
                      ":null] - "} - return output - -/obj/mecha/proc/get_commands() - var/output = {"
                      -
                      Electronics
                      - -
                      -
                      -
                      Airtank
                      - -
                      - -
                      [get_equipment_menu()]
                      -
                      - [(/obj/mecha/verb/eject in src.verbs)?"Eject
                      ":null] - "} - return output - -/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu - var/output - if(equipment.len) - output += {"
                      -
                      Equipment
                      -
                      "} - // END AUTOFIX - return output - -/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html - if(!equipment.len) - return - var/output = "Equipment:
                      " - for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) - output += "
                      [MT.get_equip_info()]
                      " - output += "
                      " - return output - - -/obj/mecha/proc/get_log_html() - var/output = "[src.name] Log" - for(var/list/entry in log) - output += {"
                      [time2text(entry["time"],"DDD MMM DD hh:mm:ss")] [game_year]
                      -
                      [entry["message"]]
                      - "} - output += "" - return output - - -/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user) - if(!id_card || !user) return - var/output = {" - - - -

                      Following keycodes are present in this system:

                      "} - for(var/a in operation_req_access) - output += "[get_access_desc(a)] - Delete
                      " - output += "

                      Following keycodes were detected on portable device:

                      " - for(var/a in id_card.access) - if(a in operation_req_access) continue - var/a_name = get_access_desc(a) - if(!a_name) continue //there's some strange access without a name - output += "[a_name] - Add
                      " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\\mecha.dm:1376: output += "
                      Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.)" - output += {"
                      Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.) - "} - // END AUTOFIX - user << browse(output, "window=exosuit_add_access") - onclose(user, "exosuit_add_access") - return - -/obj/mecha/proc/output_maintenance_dialog(obj/item/weapon/card/id/id_card,mob/user) - if(!id_card || !user) return - var/output = {" - - - - - [add_req_access?"Edit operation keycodes":null] - [maint_access?"[state ? "Terminate" : "Initiate"] maintenance protocol":null] - [(state>0) ?"Set Cabin Air Pressure":null] - - "} - user << browse(output, "window=exosuit_maint_console") - onclose(user, "exosuit_maint_console") - return - - -//////////////////////////////// -/////// Messages and Log /////// -//////////////////////////////// - -/obj/mecha/proc/occupant_message(message as text) - if(message) - if(src.occupant && src.occupant.client) - to_chat(src.occupant, "\icon[src] [message]") - return - -/obj/mecha/proc/log_message(message as text,red=null) - log.len++ - log[log.len] = list("time"=world.timeofday,"message"="[red?"":null][message][red?"":null]") - return log.len - -/obj/mecha/proc/log_append_to_last(message as text,red=null) - var/list/last_entry = src.log[src.log.len] - last_entry["message"] += "
                      [red?"":null][message][red?"":null]" - return - - -///////////////// -///// Topic ///// -///////////////// - -/obj/mecha/Topic(href, href_list) - ..() - if(href_list["update_content"]) - if(usr != src.occupant) return - send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part()) - return - if(href_list["close"]) - return - if(usr.isUnconscious()) - return - var/datum/topic_input/filter = new /datum/topic_input(href,href_list) - if(href_list["select_equip"]) - if(usr != src.occupant) return - var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip") - if(equip) - src.selected = equip - src.occupant_message("You switch to [equip]") - src.visible_message("[src] raises [equip]") - send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list()) - return - if(href_list["eject"]) - if(usr != src.occupant) return - src.eject() - return - if(href_list["toggle_lights"]) - if(usr != src.occupant) return - src.toggle_lights() - return - if(href_list["toggle_airtank"]) - if(usr != src.occupant) return - src.toggle_internal_tank() - return - if(href_list["rmictoggle"]) - if(usr != src.occupant) return - radio.broadcasting = !radio.broadcasting - send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) - return - if(href_list["rspktoggle"]) - if(usr != src.occupant) return - radio.listening = !radio.listening - send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) - return - if(href_list["rfreq"]) - if(usr != src.occupant) return - var/new_frequency = (radio.frequency + filter.getNum("rfreq")) - if (!radio.freerange || (radio.frequency < 1200 || radio.frequency > 1600)) - new_frequency = sanitize_frequency(new_frequency) - radio.set_frequency(new_frequency) - send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") - return - if(href_list["port_disconnect"]) - if(usr != src.occupant) return - src.disconnect_from_port() - return - if (href_list["port_connect"]) - if(usr != src.occupant) return - src.connect_to_port() - return - if (href_list["view_log"]) - if(usr != src.occupant) return - src.occupant << browse(src.get_log_html(), "window=exosuit_log") - onclose(occupant, "exosuit_log") - return - if (href_list["change_name"]) - if(usr != src.occupant) return - var/newname = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) - if(newname && trim(newname)) - name = newname - else - alert(occupant, "nope.avi") - return - if (href_list["toggle_id_upload"]) - if(usr != src.occupant) return - add_req_access = !add_req_access - send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") - return - if(href_list["toggle_maint_access"]) - if(usr != src.occupant) return - if(state) - occupant_message("Maintenance protocols in effect.") - return - maint_access = !maint_access - send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") - return - if(href_list["req_access"] && add_req_access) - if(!in_range(src, usr)) return - output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) - return - if(href_list["maint_access"] && maint_access) - if(!in_range(src, usr)) return - var/mob/user = filter.getMob("user") - if(user) - if(state==STATE_BOLTSHIDDEN) - state = STATE_BOLTSEXPOSED - to_chat(user, "The securing bolts are now exposed.") - log_message("Maintenance protocols engaged.") - if(occupant) - occupant_message("Maintenance protocols engaged.") - to_chat(occupant, sound('sound/mecha/mechlockdown.ogg',wait=0)) - else if(state==STATE_BOLTSEXPOSED) - state = STATE_BOLTSHIDDEN - to_chat(user, "The securing bolts are now hidden.") - log_message("Maintenance protocols terminated.") - if(occupant) - occupant_message("Maintenance protocols terminated.") - to_chat(occupant, sound('sound/mecha/mechentry.ogg',wait=0)) - else - to_chat(user, "You can't toggle maintenance mode with the securing bolts unfastened.") - output_maintenance_dialog(filter.getObj("id_card"),user) - return - if(href_list["set_internal_tank_valve"] && state >=STATE_BOLTSEXPOSED) - if(!in_range(src, usr)) return - var/mob/user = filter.getMob("user") - if(user) - var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num - if(new_pressure) - internal_tank_valve = new_pressure - to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") - if(href_list["add_req_access"] && add_req_access && filter.getObj("id_card")) - if(!in_range(src, usr)) return - operation_req_access += filter.getNum("add_req_access") - output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) - return - if(href_list["del_req_access"] && add_req_access && filter.getObj("id_card")) - if(!in_range(src, usr)) return - operation_req_access -= filter.getNum("del_req_access") - output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) - return - if(href_list["finish_req_access"]) - if(!in_range(src, usr)) return - add_req_access = 0 - var/mob/user = filter.getMob("user") - user << browse(null,"window=exosuit_add_access") - return - if(href_list["dna_lock"]) - if(usr != src.occupant) return - if(src.occupant && (!istype(src.occupant, /obj/item/device/mmi/posibrain) || !istype(src.occupant, /obj/item/device/mmi))) - src.dna = src.occupant.dna.unique_enzymes - src.occupant_message("You feel a prick as the needle takes your DNA sample.") - return - if(href_list["reset_dna"]) - if(usr != src.occupant) return - src.dna = null - if(href_list["repair_int_control_lost"]) - if(usr != src.occupant) return - src.occupant_message("Recalibrating coordination system.") - src.log_message("Recalibration of coordination system started.") - var/T = src.loc - if(do_after(100)) - if(T == src.loc) - src.clearInternalDamage(MECHA_INT_CONTROL_LOST) - src.occupant_message("Recalibration successful.") - src.log_message("Recalibration of coordination system finished with 0 errors.") - else - src.occupant_message("Recalibration failed.") - src.log_message("Recalibration of coordination system failed with 1 error.",1) - - //debug - /* - if(href_list["debug"]) - if(href_list["set_i_dam"]) - setInternalDamage(filter.getNum("set_i_dam")) - if(href_list["clear_i_dam"]) - clearInternalDamage(filter.getNum("clear_i_dam")) - return - */ - - - -/* - - if (href_list["ai_take_control"]) - var/mob/living/silicon/ai/AI = locate(href_list["ai_take_control"]) - var/duration = text2num(href_list["duration"]) - var/mob/living/silicon/ai/O = new /mob/living/silicon/ai(src) - var/cur_occupant = src.occupant - O.invisibility = 0 - O.canmove = 1 - O.name = AI.name - O.real_name = AI.real_name - O.anchored = 1 - O.aiRestorePowerRoutine = 0 - O.control_disabled = 1 // Can't control things remotely if you're stuck in a card! - O.laws = AI.laws - O.stat = AI.stat - O.oxyloss = AI.getOxyLoss() - O.fireloss = AI.getFireLoss() - O.bruteloss = AI.getBruteLoss() - O.toxloss = AI.toxloss - O.updatehealth() - src.occupant = O - if(AI.mind) - AI.mind.transfer_to(O) - AI.name = "Inactive AI" - AI.real_name = "Inactive AI" - AI.icon_state = "ai-empty" - spawn(duration) - AI.name = O.name - AI.real_name = O.real_name - if(O.mind) - O.mind.transfer_to(AI) - AI.control_disabled = 0 - AI.laws = O.laws - AI.oxyloss = O.getOxyLoss() - AI.fireloss = O.getFireLoss() - AI.bruteloss = O.getBruteLoss() - AI.toxloss = O.toxloss - AI.updatehealth() - del(O) - if (!AI.stat) - AI.icon_state = "ai" - else - AI.icon_state = "ai-crash" - src.occupant = cur_occupant -*/ - return - -/////////////////////// -///// Power stuff ///// -/////////////////////// - -/obj/mecha/proc/has_charge(amount) - return (get_charge()>=amount) - -/obj/mecha/proc/get_charge() - return call((proc_res["dyngetcharge"]||src), "dyngetcharge")() - -/obj/mecha/proc/dyngetcharge()//returns null if no powercell, else returns cell.charge - if(!src.cell) return - return max(0, src.cell.charge) - -/obj/mecha/proc/use_power(amount) - return call((proc_res["dynusepower"]||src), "dynusepower")(amount) - -/obj/mecha/proc/dynusepower(amount) - if(get_charge()) - cell.use(amount) - return 1 - return 0 - -/obj/mecha/proc/give_power(amount) - if(!isnull(get_charge())) - cell.give(amount) - return 1 - return 0 - -/obj/mecha/proc/reset_icon() - if (initial_icon) - icon_state = initial_icon - else - icon_state = initial(icon_state) - return icon_state - -////////////////////////////////////////// -//////// Mecha global iterators //////// -////////////////////////////////////////// - - -/datum/global_iterator/mecha_preserve_temp //normalizing cabin air temperature to 20 degrees celsium - delay = 20 - - process(var/obj/mecha/mecha) - if(mecha.cabin_air && mecha.cabin_air.return_volume() > 0) - var/delta = mecha.cabin_air.temperature - T20C - mecha.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) - return - -/datum/global_iterator/mecha_tank_give_air - delay = 15 - - process(var/obj/mecha/mecha) - if(mecha.internal_tank) - var/datum/gas_mixture/tank_air = mecha.internal_tank.return_air() - var/datum/gas_mixture/cabin_air = mecha.cabin_air - - var/release_pressure = mecha.internal_tank_valve - var/cabin_pressure = cabin_air.return_pressure() - var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) - var/transfer_moles = 0 - if(pressure_delta > 0) //cabin pressure lower than release pressure - if(tank_air.return_temperature() > 0) - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) - cabin_air.merge(removed) - else if(pressure_delta < 0) //cabin pressure higher than release pressure - var/datum/gas_mixture/t_air = mecha.get_turf_air() - pressure_delta = cabin_pressure - release_pressure - if(t_air) - pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) - if(pressure_delta > 0) //if location pressure is lower than cabin pressure - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) - if(t_air) - t_air.merge(removed) - else //just delete the cabin gas, we're in space or some shit - qdel(removed) - removed = null - else - return stop() - return - -/datum/global_iterator/mecha_intertial_movement //inertial movement in space - delay = 7 - - process(var/obj/mecha/mecha as obj,direction) - if(direction) - if(!step(mecha, direction)||mecha.check_for_support()) - src.stop() - else - src.stop() - return - -/datum/global_iterator/mecha_internal_damage // processing internal damage - - process(var/obj/mecha/mecha) - if(!mecha.hasInternalDamage()) - return stop() - if(mecha.hasInternalDamage(MECHA_INT_FIRE)) - if(!mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL) && prob(5)) - mecha.clearInternalDamage(MECHA_INT_FIRE) - if(mecha.internal_tank) - if(mecha.internal_tank.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH))) - mecha.setInternalDamage(MECHA_INT_TANK_BREACH) - var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() - if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents - int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) - if(mecha.cabin_air && mecha.cabin_air.return_volume()>0) - mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.return_temperature()+rand(10,15)) - if(mecha.cabin_air.return_temperature()>mecha.max_temperature/2) - mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.return_temperature(),0.1),"fire") - if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum - mecha.pr_int_temp_processor.stop() - if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank - if(mecha.internal_tank) - var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() - var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.10) - if(mecha.loc && hascall(mecha.loc,"assume_air")) - mecha.loc.assume_air(leaked_gas) - else - qdel(leaked_gas) - leaked_gas = null - if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - if(mecha.get_charge()) - mecha.spark_system.start() - mecha.cell.charge -= min(20,mecha.cell.charge) - mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge) - return - - -///////////// - -//debug -/* -/obj/mecha/verb/test_int_damage() - set name = "Test internal damage" - set category = "Exosuit Interface" - set src in view(0) - if(!occupant) return - if(usr!=occupant) - return - var/output = {" - - - -

                      Set:

                      - MECHA_INT_FIRE
                      - MECHA_INT_TEMP_CONTROL
                      - MECHA_INT_SHORT_CIRCUIT
                      - MECHA_INT_TANK_BREACH
                      - MECHA_INT_CONTROL_LOST
                      -
                      -

                      Clear:

                      - MECHA_INT_FIRE
                      - MECHA_INT_TEMP_CONTROL
                      - MECHA_INT_SHORT_CIRCUIT
                      - MECHA_INT_TANK_BREACH
                      - MECHA_INT_CONTROL_LOST
                      - - "} - - occupant << browse(output, "window=ex_debug") - //src.health = initial(src.health)/2.2 - //src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - return -*/ - -#undef STATE_BOLTSEXPOSED -#undef STATE_BOLTSOPENED +#define MECHA_INT_FIRE 1 +#define MECHA_INT_TEMP_CONTROL 2 +#define MECHA_INT_SHORT_CIRCUIT 4 +#define MECHA_INT_TANK_BREACH 8 +#define MECHA_INT_CONTROL_LOST 16 + +#define MELEE 1 +#define RANGED 2 + +#define STATE_BOLTSHIDDEN 0 +#define STATE_BOLTSEXPOSED 1 +#define STATE_BOLTSOPENED 2 + +/obj/mecha + name = "Mecha" + desc = "Exosuit" + icon = 'icons/mecha/mecha.dmi' + density = 1 //Dense. To raise the heat. + opacity = 1 ///opaque. Menacing. + anchored = 1 //no pulling around. + unacidable = 1 //and no deleting hoomans inside + layer = MOB_LAYER //icon draw layer + infra_luminosity = 15 //byond implementation is bugged. + var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items) + var/can_move = 1 + var/mob/living/carbon/occupant = null + var/step_in = 10 //make a step in step_in/10 sec. + var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South. + var/step_energy_drain = 10 + var/health = 300 //health is health + var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act. + //the values in this list show how much damage will pass through, not how much will be absorbed. + var/list/damage_absorption = list("brute"=0.8,"fire"=1.2,"bullet"=0.9,"laser"=1,"energy"=1,"bomb"=1) + var/obj/item/weapon/cell/cell + var/state = STATE_BOLTSHIDDEN + var/list/log = new + var/last_message = 0 + var/add_req_access = 1 + var/maint_access = 1 + var/dna //dna-locking the mech + var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference + var/datum/effect/effect/system/spark_spread/spark_system = new + var/lights = 0 + var/lights_power = 6 + + //inner atmos + var/use_internal_tank = 0 + var/internal_tank_valve = ONE_ATMOSPHERE + var/obj/machinery/portable_atmospherics/canister/internal_tank + var/datum/gas_mixture/cabin_air + var/obj/machinery/atmospherics/unary/portables_connector/connected_port = null + + var/obj/item/device/radio/radio = null + var/obj/item/device/radio/electropack/electropack = null + var/obj/item/mecha_parts/mecha_tracking/tracking = null + + var/max_temperature = 25000 + var/internal_damage_threshold = 50 //health percentage below which internal damage is possible + var/internal_damage = 0 //contains bitflags + + var/list/operation_req_access = list()//required access level for mecha operation + var/list/internals_req_access = list(access_engine,access_robotics)//required access level to open cell compartment + + var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature + var/datum/global_iterator/pr_inertial_movement //controls intertial movement in spesss + var/datum/global_iterator/pr_give_air //moves air from tank to cabin + var/datum/global_iterator/pr_internal_damage //processes internal damage + + + var/wreckage + + var/list/equipment = new + var/obj/item/mecha_parts/mecha_equipment/selected + var/max_equip = 3 + var/datum/events/events + + var/turf/crashing = null + var/list/mech_parts = list(/obj/item/weapon/cell, + /obj/machinery/portable_atmospherics/canister, //I shit you not this thing uses a literal air canister + /obj/item/device/radio, + /obj/item/mecha_parts, + /obj/item/device/mmi, + /obj/item/mecha_parts/mecha_tracking, + /obj/item/device/radio/electropack) + +/obj/mecha/New() + ..() + events = new + icon_state += "-open" + add_radio() + add_cabin() + if(!add_airtank()) //we check this here in case mecha does not have an internal tank available by default - WIP + removeVerb(/obj/mecha/verb/connect_to_port) + removeVerb(/obj/mecha/verb/toggle_internal_tank) + spark_system.set_up(2, 0, src) + spark_system.attach(src) + add_cell() + add_iterators() + removeVerb(/obj/mecha/verb/disconnect_from_port) + log_message("[src.name] created.") + loc.Entered(src) + mechas_list += src //global mech list + return + +/obj/mecha/Destroy() + src.go_out() + mechas_list -= src //global mech list + ..() + return + +//////////////////////// +////// Helpers ///////// +//////////////////////// + +/obj/mecha/proc/removeVerb(verb_path) + verbs -= verb_path + +/obj/mecha/proc/addVerb(verb_path) + verbs += verb_path + +/obj/mecha/proc/add_airtank() + internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src) + return internal_tank + +/obj/mecha/proc/add_cell(var/obj/item/weapon/cell/C=null) + if(C) + C.forceMove(src) + cell = C + return + cell = new(src) + cell.charge = 15000 + cell.maxcharge = 15000 + +/obj/mecha/proc/add_cabin() + cabin_air = new + cabin_air.temperature = T20C + cabin_air.volume = 200 + cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) + cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) + return cabin_air + +/obj/mecha/proc/add_radio() + radio = new(src) + radio.name = "[src] radio" + radio.icon = icon + radio.icon_state = icon_state + radio.subspace_transmission = 1 + +/obj/mecha/proc/add_iterators() + pr_int_temp_processor = new /datum/global_iterator/mecha_preserve_temp(list(src)) + pr_inertial_movement = new /datum/global_iterator/mecha_intertial_movement(null,0) + pr_give_air = new /datum/global_iterator/mecha_tank_give_air(list(src)) + pr_internal_damage = new /datum/global_iterator/mecha_internal_damage(list(src),0) + +/obj/mecha/proc/do_after(delay as num) + sleep(delay) + if(src) + return 1 + return 0 + +/obj/mecha/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5) + var/delayfraction = delay/numticks + + var/turf/T = user.loc + + for(var/i = 0, iIt's fully intact.") + if(65 to 85) + to_chat(user, "It's slightly damaged.") + if(45 to 65) + to_chat(user, "It's badly damaged.") + if(25 to 45) + to_chat(user, "It's heavily damaged.") + else + to_chat(user, "It's falling apart.") + if(equipment && equipment.len) + to_chat(user, "It's equipped with:") + for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment) + to_chat(user, "\icon[ME] [ME]") + +/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits. + return + +/obj/mecha/Hear(var/datum/speech/speech, var/rendered_message="") + if(speech.speaker == occupant && radio.broadcasting) + radio.talk_into(speech) + return + +//////////////////////////// +///// Action processing //// +//////////////////////////// +/* +/atom/DblClick(object,location,control,params) + var/mob/M = src.mob + if(M && M.in_contents_of(/obj/mecha)) + + if(mech_click == world.time) return + mech_click = world.time + + if(!istype(object, /atom)) return + if(istype(object, /obj/screen)) + var/obj/screen/using = object + if(using.screen_loc == ui_acti || using.screen_loc == ui_iarrowleft || using.screen_loc == ui_iarrowright)//ignore all HUD objects save 'intent' and its arrows + return ..() + else + return + var/obj/mecha/Mech = M.loc + spawn() //this helps prevent clickspam fest. + if (Mech) + Mech.click_action(object,M) +// else +// return ..() +*/ + +/obj/mecha/proc/click_action(atom/target,mob/user) + if(!src.occupant || src.occupant != user ) return + if(user.stat) return + if(state) + occupant_message("Maintenance protocols in effect.") + return + if(!get_charge()) return + if(src == target) return + var/dir_to_target = get_dir(src,target) + if(dir_to_target && !(dir_to_target & src.dir))//wrong direction + return + if(hasInternalDamage(MECHA_INT_CONTROL_LOST)) + target = safepick(view(3,target)) + if(!target) + return + if(get_dist(src, target)>1) + if(selected && selected.is_ranged()) + selected.action(target) + else if(selected && selected.is_melee()) + selected.action(target) + else + src.melee_action(target) + return + + +/obj/mecha/proc/melee_action(atom/target) + return + +/obj/mecha/proc/range_action(atom/target) + return + + +////////////////////////////////// +//////// Movement procs //////// +////////////////////////////////// + +/obj/mecha/Move() + . = ..() + if(.) + events.fireEvent("onMove",get_turf(src)) + return + +/obj/mecha/relaymove(mob/user,direction) + if(user != src.occupant) //While not "realistic", this piece is player friendly. + user.forceMove(get_turf(src)) + to_chat(user, "You climb out from [src]") + return 0 + if(connected_port) + if(world.time - last_message > 20) + src.occupant_message("Unable to move while connected to the air system port") + last_message = world.time + return 0 + if(state) + occupant_message("Maintenance protocols in effect.") + return + return domove(direction) + +/obj/mecha/proc/domove(direction) + return call((proc_res["dyndomove"]||src), "dyndomove")(direction) + +/obj/mecha/proc/dyndomove(direction) + if(!can_move) + return 0 + if(src.pr_inertial_movement.active()) + return 0 + if(!has_charge(step_energy_drain)) + return 0 + var/move_result = 0 + if(hasInternalDamage(MECHA_INT_CONTROL_LOST)) + move_result = mechsteprand() + else if(src.dir!=direction) + move_result = mechturn(direction) + else + move_result = mechstep(direction) + if(move_result) + can_move = 0 + use_power(step_energy_drain) + if(istype(src.loc, /turf/space)) + if(!src.check_for_support()) + src.pr_inertial_movement.start(list(src,direction)) + src.log_message("Movement control lost. Inertial movement started.") + if(do_after(step_in)) + can_move = 1 + return 1 + return 0 + +/obj/mecha/proc/mechturn(direction) + dir = direction + playsound(src,'sound/mecha/mechturn.ogg',40,1) + return 1 + +/obj/mecha/proc/mechstep(direction) + var/result = step(src,direction) + if(result) + playsound(src, get_sfx("mechstep"),40,1) + return result + + +/obj/mecha/proc/mechsteprand() + var/result = step_rand(src) + if(result) + playsound(src, get_sfx("mechstep"),40,1) + return result + +/obj/mecha/Bump(var/atom/obstacle) +// src.inertia_dir = null + if(src.throwing)//high velocity mechas in your face! + var/breakthrough = 0 + if(istype(obstacle, /obj/structure/window/)) + obstacle.Destroy(brokenup = 1) + breakthrough = 1 + + else if(istype(obstacle, /obj/structure/grille/)) + var/obj/structure/grille/G = obstacle + G.health = (0.25*initial(G.health)) + G.broken = 1 + G.icon_state = "[initial(G.icon_state)]-b" + G.density = 0 + getFromPool(/obj/item/stack/rods, get_turf(G.loc)) + breakthrough = 1 + + else if(istype(obstacle, /obj/structure/table)) + var/obj/structure/table/T = obstacle + T.destroy() + breakthrough = 1 + + else if(istype(obstacle, /obj/structure/rack)) + new /obj/item/weapon/rack_parts(obstacle.loc) + qdel(obstacle) + breakthrough = 1 + + else if(istype(obstacle, /obj/structure/reagent_dispensers/fueltank)) + obstacle.ex_act(1) + + else if(istype(obstacle, /mob/living/carbon)) + var/mob/living/carbon/C = obstacle + var/hit_sound = list('sound/weapons/genhit1.ogg','sound/weapons/genhit2.ogg','sound/weapons/genhit3.ogg') + if(C.flags & INVULNERABLE) + return + C.take_overall_damage(5,0) + if(C.locked_to) + C.locked_to = 0 + C.Stun(5) + C.Weaken(5) + C.apply_effect(STUTTER, 5) + playsound(src, pick(hit_sound), 50, 0, 0) + breakthrough = 1 + + else + src.throwing = 0//so mechas don't get stuck when landing after being sent by a Mass Driver + src.crashing = null + + if(breakthrough) + if(crashing) + spawn(1) + src.throw_at(crashing, 50, src.throw_speed) + else + spawn(1) + crashing = get_distant_turf(get_turf(src), dir, 3)//don't use get_dir(src, obstacle) or the mech will stop if he bumps into a one-direction window on his tile. + src.throw_at(crashing, 50, src.throw_speed) + + if(istype(obstacle, /obj)) + var/obj/O = obstacle + if(istype(O, /obj/effect/portal)) //derpfix + src.anchored = 0 + O.Crossed(src) + spawn(0)//countering portal teleport spawn(0), hurr + src.anchored = 1 + else if(!O.anchored) + step(obstacle,src.dir) + else //I have no idea why I disabled this + obstacle.Bumped(src) + else if(istype(obstacle, /mob)) + step(obstacle,src.dir) + else + obstacle.Bumped(src) + return + +/////////////////////////////////// +//////// Internal damage //////// +/////////////////////////////////// + +/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) + if(!islist(possible_int_damage) || isemptylist(possible_int_damage)) return + if(prob(20)) + if(ignore_threshold || src.health*100/initial(src.health)Life support system reactivated.
                      ") + pr_int_temp_processor.start() + if(MECHA_INT_FIRE) + occupant_message("Internal fire extinquished.") + if(MECHA_INT_TANK_BREACH) + occupant_message("Damaged internal tank has been sealed.") + return + + +//////////////////////////////////////// +//////// Health related procs //////// +//////////////////////////////////////// + +/obj/mecha/proc/take_damage(amount, type="brute") + if(amount) + var/damage = absorbDamage(amount,type) + health -= damage + update_health() + log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1) + return + +/obj/mecha/proc/absorbDamage(damage,damage_type) + return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type) + +/obj/mecha/proc/dynabsorbdamage(damage,damage_type) + return damage*(listgetindex(damage_absorption,damage_type) || 1) + + +/obj/mecha/proc/update_health() + if(src.health > 0) + src.spark_system.start() + else + src.destroy() + return + +/obj/mecha/attack_hand(mob/user as mob) + src.log_message("Attack by hand/paw. Attacker - [user].",1) + + if ((M_HULK in user.mutations) && !prob(src.deflect_chance)) + src.take_damage(15) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + user.visible_message("[user] hits [src.name], doing some damage.", "You hit [src.name] with all your might. The metal creaks and bends.") + else + user.visible_message("[user] hits [src.name]. Nothing happens","You hit [src.name] with no visible effect.") + src.log_append_to_last("Armor saved.") + return + +/obj/mecha/attack_paw(mob/user as mob) + return src.attack_hand(user) + + +/obj/mecha/attack_alien(mob/user as mob) + src.log_message("Attack by alien. Attacker - [user].",1) + if(!prob(src.deflect_chance)) + src.take_damage(15) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) + to_chat(user, "You slash at the armored suit!") + visible_message("The [user] slashes at [src.name]'s armor!") + else + src.log_append_to_last("Armor saved.") + playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) + to_chat(user, "Your claws had no effect!") + src.occupant_message("The [user]'s claws are stopped by the armor.") + visible_message("The [user] rebounds off [src.name]'s armor!") + return + + +/obj/mecha/attack_animal(mob/living/simple_animal/user as mob) + src.log_message("Attack by simple animal. Attacker - [user].",1) + if(user.melee_damage_upper == 0) + user.emote("[user.friendly] [src]") + else + if(!prob(src.deflect_chance)) + var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) + src.take_damage(damage) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + visible_message("[user] [user.attacktext] [src]!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + else + src.log_append_to_last("Armor saved.") + playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) + src.occupant_message("The [user]'s attack is stopped by the armor.") + visible_message("The [user] rebounds off [src.name]'s armor!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + return + +/obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper + src.log_message("Hit by [A].",1) + call((proc_res["dynhitby"]||src), "dynhitby")(A) + return + +/obj/mecha/proc/dynhitby(atom/movable/A) + if(istype(A, /obj/item/mecha_parts/mecha_tracking) && !tracking && prob(25)) + A.forceMove(src) + tracking = A + src.visible_message("The [A] fastens firmly to [src].") + return + if(prob(src.deflect_chance) || istype(A, /mob)) + src.occupant_message("The [A] bounces off the armor.") + src.visible_message("The [A] bounces off the [src.name] armor") + src.log_append_to_last("Armor saved.") + if(istype(A, /mob/living)) + var/mob/living/M = A + M.take_organ_damage(10) + else if(istype(A, /obj)) + var/obj/O = A + if(O.throwforce) + src.take_damage(O.throwforce) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + return + + +/obj/mecha/bullet_act(var/obj/item/projectile/Proj) //wrapper + src.log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1) + call((proc_res["dynbulletdamage"]||src), "dynbulletdamage")(Proj) //calls equipment + ..() + return + +/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj) + if(prob(src.deflect_chance)) + src.occupant_message("The armor deflects incoming projectile.") + src.visible_message("The [src.name] armor deflects the projectile") + src.log_append_to_last("Armor saved.") + return + var/ignore_threshold + if(Proj.flag == "taser") + use_power(200) + return + if(istype(Proj, /obj/item/projectile/beam/pulse)) + ignore_threshold = 1 + src.take_damage(Proj.damage,Proj.flag) + src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold) + Proj.on_hit(src) + return + +/obj/mecha/proc/destroy() + spawn() + go_out() + var/turf/T = get_turf(src) + tag = "\ref[src]" //better safe then sorry + if(loc) + loc.Exited(src) + loc = null + if(T) + if(istype(src, /obj/mecha/working/ripley/)) + var/obj/mecha/working/ripley/R = src + if(R.cargo) + for(var/obj/O in R.cargo) //Dump contents of stored cargo + O.loc = T + R.cargo -= O + T.Entered(O) + + if(prob(30)) + explosion(T, 0, 0, 1, 3) + spawn(0) + if(wreckage) + var/obj/effect/decal/mecha_wreckage/WR = new wreckage(T) + for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) + if(E.salvageable && prob(30)) + WR.crowbar_salvage += E + E.forceMove(WR) + E.equip_ready = 1 + E.reliability = round(rand(E.reliability/3,E.reliability)) + else + E.forceMove(T) + E.destroy() + if(cell) + WR.crowbar_salvage += cell + cell.forceMove(WR) + cell.charge = rand(0, cell.charge) + if(internal_tank) + WR.crowbar_salvage += internal_tank + internal_tank.forceMove(WR) + else + for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) + E.forceMove(T) + E.destroy() + spawn(0) + qdel(src) + return + +/obj/mecha/ex_act(severity) + src.log_message("Affected by explosion of severity: [severity].",1) + if(prob(src.deflect_chance)) + severity++ + src.log_append_to_last("Armor saved, changing severity to [severity].") + switch(severity) + if(1.0) + src.destroy() + if(2.0) + if (prob(30)) + src.destroy() + else + src.take_damage(initial(src.health)/2) + src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) + if(3.0) + if (prob(5)) + src.destroy() + else + src.take_damage(initial(src.health)/5) + src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) + return + +/*Will fix later -Sieve +/obj/mecha/attack_blob(mob/user as mob) + src.log_message("Attack by blob. Attacker - [user].",1) + if(!prob(src.deflect_chance)) + src.take_damage(6) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1) + to_chat(user, "You smash at the armored suit!") + for (var/mob/V in viewers(src)) + if(V.client && !(V.blinded)) + V.show_message("The [user] smashes against [src.name]'s armor!", 1) + else + src.log_append_to_last("Armor saved.") + playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1) + to_chat(user, "Your attack had no effect!") + src.occupant_message("The [user]'s attack is stopped by the armor.") + for (var/mob/V in viewers(src)) + if(V.client && !(V.blinded)) + V.show_message("The [user] rebounds off the [src.name] armor!", 1) + return +*/ + +/obj/mecha/blob_act() + take_damage(30, "brute") + return + +/obj/mecha/emp_act(severity) + if(get_charge()) + use_power((cell.charge/2)/severity) + take_damage(50 / severity,"energy") + src.log_message("EMP detected",1) + check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) + return + +/obj/mecha/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature>src.max_temperature) + src.log_message("Exposed to dangerous temperature.",1) + src.take_damage(5,"fire") + src.check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL)) + return + +/obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) + user.delayNextAttack(8) + src.log_message("Attacked by [W]. Attacker - [user]") + if(prob(src.deflect_chance)) + to_chat(user, "The [W] bounces off [src.name] armor.") + src.log_append_to_last("Armor saved.") +/* + for (var/mob/V in viewers(src)) + if(V.client && !(V.blinded)) + V.show_message("The [W] bounces off [src.name] armor.", 1) +*/ + else + src.occupant_message("[user] hits [src] with [W].") + user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].") + src.take_damage(W.force,W.damtype) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + return + +////////////////////// +////// AttackBy ////// +////////////////////// + +/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob) + + + if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain)) + if(mmi_move_inside(W,user)) + to_chat(user, "[src]-MMI interface initialized successfuly") + else + to_chat(user, "[src]-MMI interface initialization failed.") + return + + if(istype(W, /obj/item/mecha_parts/mecha_equipment)) + var/obj/item/mecha_parts/mecha_equipment/E = W + spawn() + if(E.can_attach(src)) + if(user.drop_item(W)) + E.attach(src) + user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + else + to_chat(user, "You were unable to attach [W] to [src]") + return + if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if(add_req_access || maint_access) + if(internals_access_allowed(usr)) + var/obj/item/weapon/card/id/id_card + if(istype(W, /obj/item/weapon/card/id)) + id_card = W + else + var/obj/item/device/pda/pda = W + id_card = pda.id + output_maintenance_dialog(id_card, user) + return + else + to_chat(user, "Invalid ID: Access denied.") + else + to_chat(user, "Maintenance protocols disabled by operator.") + else if(istype(W, /obj/item/weapon/wrench)) + if(state==STATE_BOLTSEXPOSED) + state = STATE_BOLTSOPENED + to_chat(user, "You undo the securing bolts.") + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + else if(state==STATE_BOLTSOPENED) + state = STATE_BOLTSEXPOSED + to_chat(user, "You tighten the securing bolts.") + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + return + else if(istype(W, /obj/item/weapon/crowbar)) + if(state==STATE_BOLTSOPENED) + var/list/removable_components = list() + if(cell) removable_components += "power cell" + if(tracking) removable_components += "exosuit tracking beacon" + if(electropack) removable_components += "electropack" + var/obj/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components + if(!remove) + return + switch(remove) + if ("power cell") + cell.forceMove(src.loc) + cell = null + if ("exosuit tracking beacon") + tracking.forceMove(src.loc) + tracking = null + if ("electropack") + electropack.forceMove(src.loc) + electropack = null + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You pry out \the [remove] from \the [src].") + src.log_message("Internal component removed - [remove]") + return + else if(istype(W, /obj/item/stack/cable_coil)) + if(state == STATE_BOLTSOPENED && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) + var/obj/item/stack/cable_coil/CC = W + if(CC.amount > 1) + CC.use(2) + clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) + to_chat(user, "You replace the fused wires.") + else + to_chat(user, "There's not enough wire to finish the task.") + return + else if(istype(W, /obj/item/weapon/screwdriver)) + if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) + clearInternalDamage(MECHA_INT_TEMP_CONTROL) + to_chat(user, "You repair the damaged temperature controller.") + return + else if(istype(W, /obj/item/weapon/cell)) + if(state==STATE_BOLTSOPENED) + if(!src.cell) + if(user.drop_item(W, src)) + to_chat(user, "You install the powercell.") + src.cell = W + src.log_message("Powercell installed.") + else + to_chat(user, "There's already a powercell installed.") + return + else if(istype(W, /obj/item/mecha_parts/mecha_tracking)) + if(state==STATE_BOLTSOPENED) + if(!src.tracking) + if(user.drop_item(W, src)) + to_chat(user, "You install the tracking beacon and safeties.") + src.tracking = W + src.log_message("Exosuit tracking beacon installed.") + else + to_chat(user, "There's already a tracking beacon installed.") + return + else if(istype(W, /obj/item/device/radio/electropack)) + if(state==STATE_BOLTSOPENED) + if(!src.electropack) + if(user.drop_item(W, src)) + to_chat(user, "You rig the electropack to the cockpit.") + src.electropack = W + src.log_message("Emergency ejection routines installed.") //not exactly a legitimate upgrade! + else + to_chat(user, "There's already an electropack installed.") + return + + else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != I_HURT) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(0,user)) + if (hasInternalDamage(MECHA_INT_TANK_BREACH)) + clearInternalDamage(MECHA_INT_TANK_BREACH) + to_chat(user, "You repair the damaged gas tank.") + else + return + if(src.healthYou repair some damage to [src.name].") + src.health += min(10, initial(src.health)-src.health) + else + to_chat(user, "The [src.name] is at full integrity") + return + + else + call((proc_res["dynattackby"]||src), "dynattackby")(W,user) +/* + src.log_message("Attacked by [W]. Attacker - [user]") + if(prob(src.deflect_chance)) + to_chat(user, "The [W] bounces off [src.name] armor.") + src.log_append_to_last("Armor saved.") +/* + for (var/mob/V in viewers(src)) + if(V.client && !(V.blinded)) + V.show_message("The [W] bounces off [src.name] armor.", 1) +*/ + else + src.occupant_message("[user] hits [src] with [W].") + user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].") + src.take_damage(W.force,W.damtype) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) +*/ + return + + + +/* +/obj/mecha/attack_ai(var/mob/living/silicon/ai/user as mob) + if(!istype(user, /mob/living/silicon/ai)) + return + var/output = {"Assume direct control over [src]? + Yes
                      + "} + user << browse(output, "window=mecha_attack_ai") + return +*/ + +///////////////////////////////////// +//////// Atmospheric stuff //////// +///////////////////////////////////// + +/obj/mecha/proc/get_turf_air() + var/turf/T = get_turf(src) + if(T) + . = T.return_air() + return + +/obj/mecha/remove_air(amount) + if(use_internal_tank) + return cabin_air.remove(amount) + else + var/turf/T = get_turf(src) + if(T) + return T.remove_air(amount) + return + +/obj/mecha/return_air() + if(use_internal_tank) + return cabin_air + return get_turf_air() + +/obj/mecha/proc/return_pressure() + . = 0 + if(use_internal_tank) + . = cabin_air.return_pressure() + else + var/datum/gas_mixture/t_air = get_turf_air() + if(t_air) + . = t_air.return_pressure() + return + +//skytodo: //No idea what you want me to do here, mate. +/obj/mecha/proc/return_temperature() + . = 0 + if(use_internal_tank) + . = cabin_air.return_temperature() + else + var/datum/gas_mixture/t_air = get_turf_air() + if(t_air) + . = t_air.return_temperature() + return + +/obj/mecha/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port) + //Make sure not already connected to something else + if(connected_port || !new_port || new_port.connected_device) + return 0 + + //Make sure are close enough for a valid connection + if(new_port.loc != src.loc) + return 0 + + //Perform the connection + connected_port = new_port + connected_port.connected_device = src + + //Actually enforce the air sharing + var/datum/pipe_network/network = connected_port.return_network(src) + if(network && !(internal_tank.return_air() in network.gases)) + network.gases += internal_tank.return_air() + network.update = 1 + log_message("Connected to gas port.") + return 1 + +/obj/mecha/proc/disconnect() + if(!connected_port) + return 0 + + var/datum/pipe_network/network = connected_port.return_network(src) + if(network) + network.gases -= internal_tank.return_air() + + connected_port.connected_device = null + connected_port = null + src.log_message("Disconnected from gas port.") + return 1 + + +///////////////////////// +//////// Verbs //////// +///////////////////////// + + +/obj/mecha/verb/connect_to_port() + set name = "Connect to port" + set category = "Exosuit Interface" + set src = usr.loc + set popup_menu = 0 + if(!src.occupant) return + if(usr!=src.occupant) + return + var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc + if(possible_port) + if(connect(possible_port)) + src.occupant_message("[name] connects to the port.") + src.verbs += /obj/mecha/verb/disconnect_from_port + src.verbs -= /obj/mecha/verb/connect_to_port + return + else + src.occupant_message("[name] failed to connect to the port.") + return + else + src.occupant_message("Nothing happens") + + +/obj/mecha/verb/disconnect_from_port() + set name = "Disconnect from port" + set category = "Exosuit Interface" + set src = usr.loc + set popup_menu = 0 + if(!src.occupant) return + if(usr!=src.occupant) + return + if(disconnect()) + src.occupant_message("[name] disconnects from the port.") + src.verbs -= /obj/mecha/verb/disconnect_from_port + src.verbs += /obj/mecha/verb/connect_to_port + else + src.occupant_message("[name] is not connected to the port at the moment.") + +/obj/mecha/verb/toggle_lights() + set name = "Toggle Lights" + set category = "Exosuit Interface" + set src = usr.loc + set popup_menu = 0 + if(usr!=occupant) return + lights = !lights + if(lights) set_light(luminosity + lights_power) + else set_light(luminosity - lights_power) + src.occupant_message("Toggled lights [lights?"on":"off"].") + log_message("Toggled lights [lights?"on":"off"].") + return + + +/obj/mecha/verb/toggle_internal_tank() + set name = "Toggle internal airtank usage." + set category = "Exosuit Interface" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + use_internal_tank = !use_internal_tank + src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") + src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") + return + +/obj/mecha/MouseDrop_T(mob/M as mob, mob/user as mob) + if(M != user) + return + move_inside(M, user) + +/obj/mecha/verb/move_inside() + set category = "Object" + set name = "Enter Exosuit" + set src in oview(1) + + if(usr.restrained() || usr.isUnconscious() || usr.weakened || usr.stunned || usr.paralysis || usr.resting) //are you cuffed, dying, lying, stunned or other + return + if (usr.stat || !ishuman(usr)) + return + src.log_message("[usr] tries to move in.") + if (src.occupant) + to_chat(usr, "The [src.name] is already occupied!") + src.log_append_to_last("Permission denied.") + return +/* + if (usr.abiotic()) + to_chat(usr, "Subject cannot have abiotic items on.") + return +*/ + var/passed + if(src.dna) + if(usr.dna.unique_enzymes==src.dna) + passed = 1 + else if(src.operation_allowed(usr)) + passed = 1 + if(!passed) + to_chat(usr, "Access Denied.") + src.log_append_to_last("Permission denied.") + return + for(var/mob/living/carbon/slime/M in range(1,usr)) + if(M.Victim == usr) + to_chat(usr, "You're too busy getting your life sucked out of you.") + return + + visible_message("[usr] starts to climb into [src.name]") + + + if(enter_after(40,usr)) + if(!src.occupant) + moved_inside(usr) + else if(src.occupant!=usr) + to_chat(usr, "[src.occupant] was faster. Try better next time, loser.") + else + to_chat(usr, "You stop entering the exosuit.") + return + +/obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob) + if(!isnull(src.loc) && H && H.client && H in range(1)) + H.reset_view(src) + /* + H.client.perspective = EYE_PERSPECTIVE + H.client.eye = src + */ + H.stop_pulling() + H.forceMove(src) + src.occupant = H + src.add_fingerprint(H) + src.forceMove(src.loc) + src.log_append_to_last("[H] moved in as pilot.") + src.icon_state = src.reset_icon() + dir = dir_in + playsound(src, 'sound/mecha/mechentry.ogg', 50, 1) + if(!hasInternalDamage()) + to_chat(src.occupant, sound('sound/mecha/nominalsyndi.ogg',volume=50)) + + // -- Mode/mind specific stuff goes here + if(H.mind) + if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries)) + ticker.mode.update_all_rev_icons() + if(H.mind in ticker.mode.syndicates) + ticker.mode.update_all_synd_icons() + if (H.mind in ticker.mode.cult) + ticker.mode.update_all_cult_icons() + if(H.mind in ticker.mode.wizards) + ticker.mode.update_all_wizard_icons() + // -- End mode specific stuff + + return 1 + else + return 0 + +/obj/mecha/proc/mmi_move_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) + if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client) + to_chat(user, "Consciousness matrix not detected.") + return 0 + else if(mmi_as_oc.brainmob.stat) + to_chat(user, "Beta-rhythm below acceptable level.") + return 0 + else if(occupant) + to_chat(user, "Occupant detected.") + return 0 + else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes) + to_chat(user, "Stop it!") + return 0 + //Added a message here since people assume their first click failed or something./N +// to_chat(user, "Installing MMI, please stand by.") + + visible_message("[usr] starts to insert an MMI into [src.name]") + + if(enter_after(40,user)) + if(!occupant) + return mmi_moved_inside(mmi_as_oc,user) + else + to_chat(user, "Occupant detected.") + else + to_chat(user, "You stop inserting the MMI.") + return 0 + +/obj/mecha/proc/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) + if(!isnull(src.loc) && mmi_as_oc && user in range(1)) + if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client) + to_chat(user, "Consciousness matrix not detected.") + return 0 + else if(mmi_as_oc.brainmob.stat) + to_chat(user, "Beta-rhythm below acceptable level.") + return 0 + user.drop_from_inventory(mmi_as_oc) + var/mob/brainmob = mmi_as_oc.brainmob + brainmob.reset_view(src) + /* + brainmob.client.eye = src + brainmob.client.perspective = EYE_PERSPECTIVE + */ + occupant = brainmob + brainmob.loc = src //should allow relaymove + brainmob.canmove = 1 + mmi_as_oc.loc = src + mmi_as_oc.mecha = src + src.verbs -= /obj/mecha/verb/eject + src.Entered(mmi_as_oc) + src.Move(src.loc) + src.icon_state = src.reset_icon() + dir = dir_in + src.log_message("[mmi_as_oc] moved in as pilot.") + if(!hasInternalDamage()) + to_chat(src.occupant, sound('sound/mecha/nominalsyndi.ogg',volume=50)) + return 1 + else + return 0 + +/obj/mecha/verb/view_stats() + set name = "View Stats" + set category = "Exosuit Interface" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + //pr_update_stats.start() + src.occupant << browse(src.get_stats_html(), "window=exosuit") + return + +/* +/obj/mecha/verb/force_eject() + set category = "Object" + set name = "Force Eject" + set src in view(5) + src.go_out() + return +*/ + +/obj/mecha/verb/eject() + set name = "Eject" + set category = "Exosuit Interface" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + src.go_out() + add_fingerprint(usr) + return + +/obj/mecha/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) + if(usr!=src.occupant) + return + if(!istype(over_location) || over_location.density) + return + if(!Adjacent(over_location)) + return + for(var/atom/movable/A in over_location.contents) + if(A.density) + if((A == src) || istype(A, /mob)) + continue + return + if(istype(over_location)) + go_out(over_location) + add_fingerprint(usr) + +/obj/mecha/proc/empty_bad_contents() //stuff that shouldn't be there, possibly caused by the driver dropping it while inside the mech + for(var/obj/O in src) + if(!is_type_in_list(O,mech_parts)) + O.loc = src.loc + return + +/obj/mecha/proc/go_out(var/exit = loc) + if(!src.occupant) return + var/atom/movable/mob_container + if(ishuman(occupant)) + mob_container = src.occupant + else if(istype(occupant, /mob/living/carbon/brain)) + var/mob/living/carbon/brain/brain = occupant + mob_container = brain.container + else + return + if(mob_container.forceMove(exit))//ejecting mob container + /* + if(ishuman(occupant) && (return_pressure() > HAZARD_HIGH_PRESSURE)) + use_internal_tank = 0 + var/datum/gas_mixture/environment = get_turf_air() + if(environment) + var/env_pressure = environment.return_pressure() + var/pressure_delta = (cabin.return_pressure() - env_pressure) + //Can not have a pressure delta that would cause environment pressure > tank pressure + + var/transfer_moles = 0 + if(pressure_delta > 0) + transfer_moles = pressure_delta*environment.volume/(cabin.return_temperature() * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed = cabin.air_contents.remove(transfer_moles) + loc.assume_air(removed) + + occupant.SetStunned(5) + occupant.SetWeakened(5) + to_chat(occupant, "You were blown out of the mech!") + */ + src.log_message("[mob_container] moved out.") + occupant.reset_view() + /* + if(src.occupant.client) + src.occupant.client.eye = src.occupant.client.mob + src.occupant.client.perspective = MOB_PERSPECTIVE + */ + empty_bad_contents() + src.occupant << browse(null, "window=exosuit") + if(istype(mob_container, /obj/item/device/mmi) || istype(mob_container, /obj/item/device/mmi/posibrain)) + var/obj/item/device/mmi/mmi = mob_container + if(mmi.brainmob) + occupant.loc = mmi + mmi.mecha = null + src.occupant.canmove = 0 + src.verbs += /obj/mecha/verb/eject + + // -- Mode/mind specific stuff goes here + if(src.occupant.mind) + if((src.occupant.mind in ticker.mode:revolutionaries) || (src.occupant.mind in ticker.mode:head_revolutionaries)) + ticker.mode.update_all_rev_icons() + if(src.occupant.mind in ticker.mode.syndicates) + ticker.mode.update_all_synd_icons() + if (src.occupant.mind in ticker.mode.cult) + ticker.mode.update_all_cult_icons() + if(src.occupant.mind in ticker.mode.wizards) + ticker.mode.update_all_wizard_icons() + // -- End mode specific stuff + + src.occupant = null + src.icon_state = src.reset_icon()+"-open" + src.dir = dir_in + + return + +/obj/mecha/proc/shock_n_boot(var/exit = loc) + spark_system.start() + if (occupant) + to_chat(occupant, "You feel a sharp shock!") + occupant.Weaken(10) + spawn(10) + emergency_eject() + +/obj/mecha/proc/emergency_eject(var/exit = loc) + if (occupant) + to_chat(occupant, sound('sound/machines/warning.ogg',wait=0)) + log_message("Emergency ejection.",1) + occupant_message("Emergency ejection protocol engaged.") + spawn(10) + if (occupant) + go_out() + +///////////////////////// +////// Access stuff ///// +///////////////////////// + +/obj/mecha/proc/operation_allowed(mob/living/carbon/human/H) + for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt)) + if(src.check_access(ID,src.operation_req_access)) + return 1 + return 0 + + +/obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H) + for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt)) + if(src.check_access(ID,src.internals_req_access)) + return 1 + return 0 + + +/obj/mecha/check_access(obj/item/weapon/card/id/I, list/access_list) + if(!istype(access_list)) + return 1 + if(!access_list.len) //no requirements + return 1 + if(istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if(!istype(I) || !I.access) //not ID or no access + return 0 + if(access_list==src.operation_req_access) + for(var/req in access_list) + if(!(req in I.access)) //doesn't have this access + return 0 + else if(access_list==src.internals_req_access) + for(var/req in access_list) + if(req in I.access) + return 1 + return 1 + + +//////////////////////////////////// +///// Rendering stats window /////// +//////////////////////////////////// + +/obj/mecha/proc/get_stats_html() + var/output = {" + [src.name] data + + + + +
                      + [src.get_stats_part()] +
                      +
                      + [src.get_equipment_list()] +
                      +
                      +
                      + [src.get_commands()] +
                      + + + "} + return output + + +/obj/mecha/proc/report_internal_damage() + var/output = null + var/list/dam_reports = list( + "[MECHA_INT_FIRE]" = "INTERNAL FIRE", + "[MECHA_INT_TEMP_CONTROL]" = "LIFE SUPPORT SYSTEM MALFUNCTION", + "[MECHA_INT_TANK_BREACH]" = "GAS TANK BREACH", + "[MECHA_INT_CONTROL_LOST]" = "COORDINATION SYSTEM CALIBRATION FAILURE - Recalibrate", + "[MECHA_INT_SHORT_CIRCUIT]" = "SHORT CIRCUIT" + ) + for(var/tflag in dam_reports) + var/intdamflag = text2num(tflag) + if(hasInternalDamage(intdamflag)) + output += dam_reports[tflag] + output += "
                      " + if(return_pressure() > WARNING_HIGH_PRESSURE) + output += "DANGEROUSLY HIGH CABIN PRESSURE
                      " + return output + + +/obj/mecha/proc/get_stats_part() + var/integrity = health/initial(health)*100 + var/cell_charge = get_charge() + var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" + var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" + var/cabin_pressure = round(return_pressure(),0.01) + var/output = {"[report_internal_damage()] + [integrity<30?"DAMAGE LEVEL CRITICAL
                      ":null] + Integrity: [integrity]%
                      + Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
                      + Air source: [use_internal_tank?"Internal Airtank":"Environment"]
                      + Airtank pressure: [tank_pressure]kPa
                      + Airtank temperature: [tank_temperature]K|[tank_temperature - T0C]°C
                      + Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
                      + Cabin temperature: [return_temperature()]K|[return_temperature() - T0C]°C
                      + Lights: [lights?"on":"off"]
                      + [src.dna?"DNA-locked:
                      [src.dna] \[Reset\]
                      ":null] + "} + return output + +/obj/mecha/proc/get_commands() + var/output = {"
                      +
                      Electronics
                      + +
                      +
                      +
                      Airtank
                      + +
                      + +
                      [get_equipment_menu()]
                      +
                      + [(/obj/mecha/verb/eject in src.verbs)?"Eject
                      ":null] + "} + return output + +/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu + var/output + if(equipment.len) + output += {"
                      +
                      Equipment
                      +
                      "} + // END AUTOFIX + return output + +/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html + if(!equipment.len) + return + var/output = "Equipment:
                      " + for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) + output += "
                      [MT.get_equip_info()]
                      " + output += "
                      " + return output + + +/obj/mecha/proc/get_log_html() + var/output = "[src.name] Log" + for(var/list/entry in log) + output += {"
                      [time2text(entry["time"],"DDD MMM DD hh:mm:ss")] [game_year]
                      +
                      [entry["message"]]
                      + "} + output += "" + return output + + +/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user) + if(!id_card || !user) return + var/output = {" + + + +

                      Following keycodes are present in this system:

                      "} + for(var/a in operation_req_access) + output += "[get_access_desc(a)] - Delete
                      " + output += "

                      Following keycodes were detected on portable device:

                      " + for(var/a in id_card.access) + if(a in operation_req_access) continue + var/a_name = get_access_desc(a) + if(!a_name) continue //there's some strange access without a name + output += "[a_name] - Add
                      " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\\mecha.dm:1376: output += "
                      Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.)" + output += {"
                      Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.) + "} + // END AUTOFIX + user << browse(output, "window=exosuit_add_access") + onclose(user, "exosuit_add_access") + return + +/obj/mecha/proc/output_maintenance_dialog(obj/item/weapon/card/id/id_card,mob/user) + if(!id_card || !user) return + var/output = {" + + + + + [add_req_access?"Edit operation keycodes":null] + [maint_access?"[state ? "Terminate" : "Initiate"] maintenance protocol":null] + [(state>0) ?"Set Cabin Air Pressure":null] + + "} + user << browse(output, "window=exosuit_maint_console") + onclose(user, "exosuit_maint_console") + return + + +//////////////////////////////// +/////// Messages and Log /////// +//////////////////////////////// + +/obj/mecha/proc/occupant_message(message as text) + if(message) + if(src.occupant && src.occupant.client) + to_chat(src.occupant, "\icon[src] [message]") + return + +/obj/mecha/proc/log_message(message as text,red=null) + log.len++ + log[log.len] = list("time"=world.timeofday,"message"="[red?"":null][message][red?"":null]") + return log.len + +/obj/mecha/proc/log_append_to_last(message as text,red=null) + var/list/last_entry = src.log[src.log.len] + last_entry["message"] += "
                      [red?"":null][message][red?"":null]" + return + + +///////////////// +///// Topic ///// +///////////////// + +/obj/mecha/Topic(href, href_list) + ..() + if(href_list["update_content"]) + if(usr != src.occupant) return + send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part()) + return + if(href_list["close"]) + return + if(usr.isUnconscious()) + return + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) + if(href_list["select_equip"]) + if(usr != src.occupant) return + var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip") + if(equip) + src.selected = equip + src.occupant_message("You switch to [equip]") + src.visible_message("[src] raises [equip]") + send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list()) + return + if(href_list["eject"]) + if(usr != src.occupant) return + src.eject() + return + if(href_list["toggle_lights"]) + if(usr != src.occupant) return + src.toggle_lights() + return + if(href_list["toggle_airtank"]) + if(usr != src.occupant) return + src.toggle_internal_tank() + return + if(href_list["rmictoggle"]) + if(usr != src.occupant) return + radio.broadcasting = !radio.broadcasting + send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) + return + if(href_list["rspktoggle"]) + if(usr != src.occupant) return + radio.listening = !radio.listening + send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) + return + if(href_list["rfreq"]) + if(usr != src.occupant) return + var/new_frequency = (radio.frequency + filter.getNum("rfreq")) + if (!radio.freerange || (radio.frequency < 1200 || radio.frequency > 1600)) + new_frequency = sanitize_frequency(new_frequency) + radio.set_frequency(new_frequency) + send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") + return + if(href_list["port_disconnect"]) + if(usr != src.occupant) return + src.disconnect_from_port() + return + if (href_list["port_connect"]) + if(usr != src.occupant) return + src.connect_to_port() + return + if (href_list["view_log"]) + if(usr != src.occupant) return + src.occupant << browse(src.get_log_html(), "window=exosuit_log") + onclose(occupant, "exosuit_log") + return + if (href_list["change_name"]) + if(usr != src.occupant) return + var/newname = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) + if(newname && trim(newname)) + name = newname + else + alert(occupant, "nope.avi") + return + if (href_list["toggle_id_upload"]) + if(usr != src.occupant) return + add_req_access = !add_req_access + send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") + return + if(href_list["toggle_maint_access"]) + if(usr != src.occupant) return + if(state) + occupant_message("Maintenance protocols in effect.") + return + maint_access = !maint_access + send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") + return + if(href_list["req_access"] && add_req_access) + if(!in_range(src, usr)) return + output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) + return + if(href_list["maint_access"] && maint_access) + if(!in_range(src, usr)) return + var/mob/user = filter.getMob("user") + if(user) + if(state==STATE_BOLTSHIDDEN) + state = STATE_BOLTSEXPOSED + to_chat(user, "The securing bolts are now exposed.") + log_message("Maintenance protocols engaged.") + if(occupant) + occupant_message("Maintenance protocols engaged.") + to_chat(occupant, sound('sound/mecha/mechlockdown.ogg',wait=0)) + else if(state==STATE_BOLTSEXPOSED) + state = STATE_BOLTSHIDDEN + to_chat(user, "The securing bolts are now hidden.") + log_message("Maintenance protocols terminated.") + if(occupant) + occupant_message("Maintenance protocols terminated.") + to_chat(occupant, sound('sound/mecha/mechentry.ogg',wait=0)) + else + to_chat(user, "You can't toggle maintenance mode with the securing bolts unfastened.") + output_maintenance_dialog(filter.getObj("id_card"),user) + return + if(href_list["set_internal_tank_valve"] && state >=STATE_BOLTSEXPOSED) + if(!in_range(src, usr)) return + var/mob/user = filter.getMob("user") + if(user) + var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num + if(new_pressure) + internal_tank_valve = new_pressure + to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") + if(href_list["add_req_access"] && add_req_access && filter.getObj("id_card")) + if(!in_range(src, usr)) return + operation_req_access += filter.getNum("add_req_access") + output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) + return + if(href_list["del_req_access"] && add_req_access && filter.getObj("id_card")) + if(!in_range(src, usr)) return + operation_req_access -= filter.getNum("del_req_access") + output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) + return + if(href_list["finish_req_access"]) + if(!in_range(src, usr)) return + add_req_access = 0 + var/mob/user = filter.getMob("user") + user << browse(null,"window=exosuit_add_access") + return + if(href_list["dna_lock"]) + if(usr != src.occupant) return + if(src.occupant && (!istype(src.occupant, /obj/item/device/mmi/posibrain) || !istype(src.occupant, /obj/item/device/mmi))) + src.dna = src.occupant.dna.unique_enzymes + src.occupant_message("You feel a prick as the needle takes your DNA sample.") + return + if(href_list["reset_dna"]) + if(usr != src.occupant) return + src.dna = null + if(href_list["repair_int_control_lost"]) + if(usr != src.occupant) return + src.occupant_message("Recalibrating coordination system.") + src.log_message("Recalibration of coordination system started.") + var/T = src.loc + if(do_after(100)) + if(T == src.loc) + src.clearInternalDamage(MECHA_INT_CONTROL_LOST) + src.occupant_message("Recalibration successful.") + src.log_message("Recalibration of coordination system finished with 0 errors.") + else + src.occupant_message("Recalibration failed.") + src.log_message("Recalibration of coordination system failed with 1 error.",1) + + //debug + /* + if(href_list["debug"]) + if(href_list["set_i_dam"]) + setInternalDamage(filter.getNum("set_i_dam")) + if(href_list["clear_i_dam"]) + clearInternalDamage(filter.getNum("clear_i_dam")) + return + */ + + + +/* + + if (href_list["ai_take_control"]) + var/mob/living/silicon/ai/AI = locate(href_list["ai_take_control"]) + var/duration = text2num(href_list["duration"]) + var/mob/living/silicon/ai/O = new /mob/living/silicon/ai(src) + var/cur_occupant = src.occupant + O.invisibility = 0 + O.canmove = 1 + O.name = AI.name + O.real_name = AI.real_name + O.anchored = 1 + O.aiRestorePowerRoutine = 0 + O.control_disabled = 1 // Can't control things remotely if you're stuck in a card! + O.laws = AI.laws + O.stat = AI.stat + O.oxyloss = AI.getOxyLoss() + O.fireloss = AI.getFireLoss() + O.bruteloss = AI.getBruteLoss() + O.toxloss = AI.toxloss + O.updatehealth() + src.occupant = O + if(AI.mind) + AI.mind.transfer_to(O) + AI.name = "Inactive AI" + AI.real_name = "Inactive AI" + AI.icon_state = "ai-empty" + spawn(duration) + AI.name = O.name + AI.real_name = O.real_name + if(O.mind) + O.mind.transfer_to(AI) + AI.control_disabled = 0 + AI.laws = O.laws + AI.oxyloss = O.getOxyLoss() + AI.fireloss = O.getFireLoss() + AI.bruteloss = O.getBruteLoss() + AI.toxloss = O.toxloss + AI.updatehealth() + del(O) + if (!AI.stat) + AI.icon_state = "ai" + else + AI.icon_state = "ai-crash" + src.occupant = cur_occupant +*/ + return + +/////////////////////// +///// Power stuff ///// +/////////////////////// + +/obj/mecha/proc/has_charge(amount) + return (get_charge()>=amount) + +/obj/mecha/proc/get_charge() + return call((proc_res["dyngetcharge"]||src), "dyngetcharge")() + +/obj/mecha/proc/dyngetcharge()//returns null if no powercell, else returns cell.charge + if(!src.cell) return + return max(0, src.cell.charge) + +/obj/mecha/proc/use_power(amount) + return call((proc_res["dynusepower"]||src), "dynusepower")(amount) + +/obj/mecha/proc/dynusepower(amount) + if(get_charge()) + cell.use(amount) + return 1 + return 0 + +/obj/mecha/proc/give_power(amount) + if(!isnull(get_charge())) + cell.give(amount) + return 1 + return 0 + +/obj/mecha/proc/reset_icon() + if (initial_icon) + icon_state = initial_icon + else + icon_state = initial(icon_state) + return icon_state + +////////////////////////////////////////// +//////// Mecha global iterators //////// +////////////////////////////////////////// + + +/datum/global_iterator/mecha_preserve_temp //normalizing cabin air temperature to 20 degrees celsium + delay = 20 + + process(var/obj/mecha/mecha) + if(mecha.cabin_air && mecha.cabin_air.return_volume() > 0) + var/delta = mecha.cabin_air.temperature - T20C + mecha.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) + return + +/datum/global_iterator/mecha_tank_give_air + delay = 15 + + process(var/obj/mecha/mecha) + if(mecha.internal_tank) + var/datum/gas_mixture/tank_air = mecha.internal_tank.return_air() + var/datum/gas_mixture/cabin_air = mecha.cabin_air + + var/release_pressure = mecha.internal_tank_valve + var/cabin_pressure = cabin_air.return_pressure() + var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) + var/transfer_moles = 0 + if(pressure_delta > 0) //cabin pressure lower than release pressure + if(tank_air.return_temperature() > 0) + transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) + cabin_air.merge(removed) + else if(pressure_delta < 0) //cabin pressure higher than release pressure + var/datum/gas_mixture/t_air = mecha.get_turf_air() + pressure_delta = cabin_pressure - release_pressure + if(t_air) + pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) + if(pressure_delta > 0) //if location pressure is lower than cabin pressure + transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) + if(t_air) + t_air.merge(removed) + else //just delete the cabin gas, we're in space or some shit + qdel(removed) + removed = null + else + return stop() + return + +/datum/global_iterator/mecha_intertial_movement //inertial movement in space + delay = 7 + + process(var/obj/mecha/mecha as obj,direction) + if(direction) + if(!step(mecha, direction)||mecha.check_for_support()) + src.stop() + else + src.stop() + return + +/datum/global_iterator/mecha_internal_damage // processing internal damage + + process(var/obj/mecha/mecha) + if(!mecha.hasInternalDamage()) + return stop() + if(mecha.hasInternalDamage(MECHA_INT_FIRE)) + if(!mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL) && prob(5)) + mecha.clearInternalDamage(MECHA_INT_FIRE) + if(mecha.internal_tank) + if(mecha.internal_tank.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH))) + mecha.setInternalDamage(MECHA_INT_TANK_BREACH) + var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() + if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents + int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) + if(mecha.cabin_air && mecha.cabin_air.return_volume()>0) + mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.return_temperature()+rand(10,15)) + if(mecha.cabin_air.return_temperature()>mecha.max_temperature/2) + mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.return_temperature(),0.1),"fire") + if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum + mecha.pr_int_temp_processor.stop() + if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank + if(mecha.internal_tank) + var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() + var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.10) + if(mecha.loc && hascall(mecha.loc,"assume_air")) + mecha.loc.assume_air(leaked_gas) + else + qdel(leaked_gas) + leaked_gas = null + if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) + if(mecha.get_charge()) + mecha.spark_system.start() + mecha.cell.charge -= min(20,mecha.cell.charge) + mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge) + return + + +///////////// + +//debug +/* +/obj/mecha/verb/test_int_damage() + set name = "Test internal damage" + set category = "Exosuit Interface" + set src in view(0) + if(!occupant) return + if(usr!=occupant) + return + var/output = {" + + + +

                      Set:

                      + MECHA_INT_FIRE
                      + MECHA_INT_TEMP_CONTROL
                      + MECHA_INT_SHORT_CIRCUIT
                      + MECHA_INT_TANK_BREACH
                      + MECHA_INT_CONTROL_LOST
                      +
                      +

                      Clear:

                      + MECHA_INT_FIRE
                      + MECHA_INT_TEMP_CONTROL
                      + MECHA_INT_SHORT_CIRCUIT
                      + MECHA_INT_TANK_BREACH
                      + MECHA_INT_CONTROL_LOST
                      + + "} + + occupant << browse(output, "window=ex_debug") + //src.health = initial(src.health)/2.2 + //src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + return +*/ + +#undef STATE_BOLTSEXPOSED +#undef STATE_BOLTSOPENED diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index dfe556b2244..1e8c6e9071d 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -1,685 +1,685 @@ -//////////////////////////////// -///// Construction datums ////// -//////////////////////////////// - -#define MAINBOARD 4 -#define PERIBOARD 6 -#define TARGBOARD 8 -#define ARMOR_PLATES 17 - -/datum/construction/reversible/mecha - var/base_icon = "ripley" - var/mainboard = /obj/item/weapon/circuitboard/mecha/ripley/main - var/peripherals = /obj/item/weapon/circuitboard/mecha/ripley/peripherals - - steps = list( - //1 - list(Co_DESC="External armor is wrenched.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} external armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfasten{s} the external armor layer.") - ), - //2 - list(Co_DESC="External armor is installed.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} external armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} external armor layer from {HOLDER}.", - Co_START_MSG = "{USER} begin{s} removing the external reinforced armor...", - Co_DELAY = 30,) - ), - //3 - list(Co_DESC="Internal armor is welded.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/plasteel, - Co_AMOUNT = 5, - Co_VIS_MSG = "{USER} install{s} external reinforced armor layer to {HOLDER}.", - Co_START_MSG = "{USER} begin{s} installing the external reinforced armor...", - Co_DELAY = 30), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") - ), - //4 - list(Co_DESC="Internal armor is wrenched", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfastens the internal armor layer.") - ), - //5 - list(Co_DESC="Internal armor is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} internal armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") - ), - //6 - list(Co_DESC="Peripherals control module is secured", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, - Co_AMOUNT = 5, - Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") - ), - //7 - list(Co_DESC="Peripherals control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") - ), - //8 - list(Co_DESC="Central control module is secured", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") - ), - //9 - list(Co_DESC="Central control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the mainboard."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") - ), - //10 - list(Co_DESC="The wiring is adjusted", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") - ), - //11 - list(Co_DESC="The wiring is added", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, - Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") - ), - //12 - list(Co_DESC="The hydraulic systems are active.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, - Co_AMOUNT = 10, - Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") - ), - //13 - list(Co_DESC="The hydraulic systems are connected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") - ), - //14 - list(Co_DESC="The hydraulic systems are disconnected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") - ) - ) - -/datum/construction/reversible/mecha/New() - ..() - if(src) - add_board_keys() - -/datum/construction/reversible/mecha/custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - holder.icon_state = "[base_icon][steps.len - index - diff]" - return 1 - -/datum/construction/reversible/mecha/action(atom/used_atom,mob/user) - return check_step(used_atom,user) - -/datum/construction/reversible/mecha/proc/add_board_keys() - var/list/board_step = get_forward_step(steps.len - MAINBOARD) - board_step[Co_KEY] = mainboard - - board_step = get_forward_step(steps.len - PERIBOARD) - board_step[Co_KEY] = peripherals - -/datum/construction/reversible/mecha/spawn_result(mob/user as mob) - ..() - feedback_inc("mecha_[base_icon]_created",1) - return - -// custom_actions moved to construction_datum - N3X - - -/datum/construction/reversible/mecha/ripley - result = "/obj/mecha/working/ripley" - -/datum/construction/reversible/mecha/firefighter - result = "/obj/mecha/working/ripley/firefighter" - steps = list( - //1 - list(Co_DESC="External armor is wrenched.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} external armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfasten{s} the external armor layer.") - ), - //2 - list(Co_DESC="External armor is installed.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} external armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} external armor layer from {HOLDER}.", - Co_START_MSG = "{USER} begin{s} removing the external reinforced armor...", - Co_DELAY = 50,) - ), - //3 - list(Co_DESC="Internal armor is welded.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/plasteel, - Co_AMOUNT = 10, - Co_VIS_MSG = "{USER} install{s} external reinforced armor layer to {HOLDER}.", - Co_START_MSG = "{USER} begin{s} installing the external reinforced armor...", - Co_DELAY = 50), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") - ), - //4 - list(Co_DESC="Internal armor is wrenched", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfasten{s} the internal armor layer.") - ), - //5 - list(Co_DESC="Internal armor is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} internal armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") - ), - //6 - list(Co_DESC="Peripherals control module is secured", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, - Co_AMOUNT = 5, - Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") - ), - //7 - list(Co_DESC="Peripherals control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") - ), - //8 - list(Co_DESC="Central control module is secured", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") - ), - //9 - list(Co_DESC="Central control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the mainboard."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") - ), - //10 - list(Co_DESC="The wiring is adjusted", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") - ), - //11 - list(Co_DESC="The wiring is added", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, - Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") - ), - //12 - list(Co_DESC="The hydraulic systems are active.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, - Co_AMOUNT = 10, - Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") - ), - //13 - list(Co_DESC="The hydraulic systems are connected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") - ), - //14 - list(Co_DESC="The hydraulic systems are disconnected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") - ) - ) - - -/datum/construction/reversible/mecha/odysseus - result = "/obj/mecha/medical/odysseus" - base_icon = "odysseus" - - mainboard = /obj/item/weapon/circuitboard/mecha/odysseus/main - peripherals = /obj/item/weapon/circuitboard/mecha/odysseus/peripherals - -/datum/construction/reversible/mecha/combat - var/targeting = /obj/item/weapon/circuitboard/mecha/gygax/targeting - var/armor_plates = /obj/item/mecha_parts/part/gygax_armour - - steps = list( - //1 - list(Co_DESC="External armor is wrenched.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} armor plates to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfasten{s} the armor plates.") - ), - //2 - list(Co_DESC="External armor is installed.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} armor plates."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} armor plates from {HOLDER}.", - Co_DELAY = 30, - Co_START_MSG = "{USER} begin{s} removing the armor plates...") - ), - //3 - list(Co_DESC="Internal armor is welded.", - Co_NEXTSTEP = list(Co_KEY=null, //set by proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} armor plates to {HOLDER}.", - Co_START_MSG = "{USER} begin{s} installing the armor plates...", - Co_DELAY = 30), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") - ), - //4 - list(Co_DESC="Internal armor is wrenched", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfasten{s} the internal armor layer.") - ), - //5 - list(Co_DESC="Internal armor is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} internal armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") - ), - //6 - list(Co_DESC="Advanced capacitor is secured", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, - Co_AMOUNT = 5, - Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the advanced capacitor.") - ), - //7 - list(Co_DESC="Advanced capacitor is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the advanced capacitor."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the advanced capacitor from {HOLDER}.") - ), - //8 - list(Co_DESC="Advanced scanner module is secured", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/stock_parts/capacitor/adv, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} advanced capacitor to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the Advanced scanner module.") - ), - //9 - list(Co_DESC="Advanced scanner module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the advanced scanner module."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the advanced scanner module from {HOLDER}.") - ), - //10 - list(Co_DESC="Targeting module is secured", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/stock_parts/scanning_module/adv, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} advanced scanner module to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the targeting module.") - ), - //11 - list(Co_DESC="Targeting module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the targeting module."), - Co_BACKSTOP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the targeting module from {HOLDER}.") - ), - //12 - list(Co_DESC="Peripherals control module is secured", - Co_NEXTSTEP = list(Co_KEY= null, //set by proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the targeting module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") - ), - //13 - list(Co_DESC="Peripherals control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") - ), - //14 - list(Co_DESC="Central control module is secured", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") - ), - //15 - list(Co_DESC="Central control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the mainboard."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") - ), - //16 - list(Co_DESC="The wiring is adjusted", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") - ), - //17 - list(Co_DESC="The wiring is added", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, - Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") - ), - //18 - list(Co_DESC="The hydraulic systems are active.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, - Co_AMOUNT = 10, - Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") - ), - //19 - list(Co_DESC="The hydraulic systems are connected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") - ), - //20 - list(Co_DESC="The hydraulic systems are disconnected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") - ) - ) - -/datum/construction/reversible/mecha/combat/add_board_keys() - var/list/board_step = get_forward_step(steps.len - MAINBOARD) - board_step[Co_KEY] = mainboard - - board_step = get_forward_step(steps.len - PERIBOARD) - board_step[Co_KEY] = peripherals - - board_step = get_forward_step(steps.len - TARGBOARD) - board_step[Co_KEY] = targeting - - if(armor_plates) - board_step = get_forward_step(steps.len - ARMOR_PLATES) - board_step[Co_KEY] = armor_plates - -/datum/construction/reversible/mecha/combat/gygax - base_icon = "gygax" - mainboard = /obj/item/weapon/circuitboard/mecha/gygax/main - peripherals = /obj/item/weapon/circuitboard/mecha/gygax/peripherals - targeting = /obj/item/weapon/circuitboard/mecha/gygax/targeting - armor_plates = /obj/item/mecha_parts/part/gygax_armour - result = "/obj/mecha/combat/gygax" - -/datum/construction/reversible/mecha/combat/durand - mainboard = /obj/item/weapon/circuitboard/mecha/durand/main - peripherals = /obj/item/weapon/circuitboard/mecha/durand/peripherals - targeting = /obj/item/weapon/circuitboard/mecha/durand/targeting - armor_plates = /obj/item/mecha_parts/part/durand_armour - result = "/obj/mecha/combat/durand" - base_icon = "durand" - -/datum/construction/reversible/mecha/honker - base_icon = "honker" - result = "/obj/mecha/combat/honker" - steps = list( - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn, - Co_VIS_MSG = "{USER} adds the bike horn to {HOLDER}", - Co_AMOUNT = 1), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the clown boots from {HOLDER}.") - ),//1 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/clothing/shoes/clown_shoes, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} put{s} clown boots on {HOLDER}."), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) - ),//2 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the clown wig and mask from {HOLDER}.") - ),//3 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/clothing/mask/gas/clown_hat, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} put{s} clown wig and mask on {HOLDER}."), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) - ),//4 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} uninstall{s} the weapon control module.") - ),//5 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/circuitboard/mecha/honker/targeting, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the weapon control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) - ),//6 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} uninstall{s} the peripherals control module.") - ),//7 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/circuitboard/mecha/honker/peripherals, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) - ),//8 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} uninstall{s} the central control module.") - ),//9 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/circuitboard/mecha/honker/main, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) - ),//10 - list( - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn) - )//11 - ) - -/datum/construction/reversible/mecha/honker/set_desc() - return - -/datum/construction/reversible/mecha/honker/custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - if(istype(used_atom, /obj/item/weapon/bikehorn)) - playsound(holder, 'sound/items/bikehorn.ogg', 50, 1) - user.visible_message("HONK!") - - holder.icon_state = "honker_chassis" - return 1 - -/datum/construction/reversible/mecha/honker/add_board_keys() - return - - -/datum/construction/reversible/mecha/phazon - base_icon = "phazon" - mainboard = /obj/item/weapon/circuitboard/mecha/phazon/main - peripherals = /obj/item/weapon/circuitboard/mecha/phazon/peripherals - result = "/obj/mecha/combat/phazon" - - steps = list( - //1 - list(Co_DESC="External armor is wrenched.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} external armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfasten{s} the external armor layer.") - ), - //2 - list(Co_DESC="External armor is installed.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} external armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} external armor layer from {HOLDER}.", - Co_START_MSG = "{USER} begin{s} removing the external reinforced armor...", - Co_DELAY = 30,) - ), - //3 - list(Co_DESC="Internal armor is welded.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/plasteel, - Co_AMOUNT = 5, - Co_VIS_MSG = "{USER} install{s} external reinforced armor layer to {HOLDER}.", - Co_START_MSG = "{USER} begin{s} installing the external reinforced armor...", - Co_DELAY = 30), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") - ), - //4 - list(Co_DESC="Internal armor is wrenched", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, - Co_AMOUNT = 3, - Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} unfastens the internal armor layer.") - ), - //5 - list(Co_DESC="Internal armor is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} secure{s} internal armor layer."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") - ), - - //6 - list(Co_DESC="Phaze array is secured", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, - Co_AMOUNT = 5, - Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the phaze array.") - ), - //7 - list(Co_DESC="Phaze array is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the phaze array."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the phaze array from {HOLDER}.") - ), - //8 - list(Co_DESC="Peripherals control module is secured", - Co_NEXTSTEP = list(Co_KEY= /obj/item/mecha_parts/part/phazon_phase_array, - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} phaze array to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") - ), - //9 - list(Co_DESC="Peripherals control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") - ), - //10 - list(Co_DESC="Central control module is secured", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") - ), - //11 - list(Co_DESC="Central control module is installed", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} secure{s} the mainboard."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, - Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") - ), - //12 - list(Co_DESC="The wiring is adjusted", - Co_NEXTSTEP = list(Co_KEY= null, //set by a proc - Co_AMOUNT = 1, - Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") - ), - //13 - list(Co_DESC="The wiring is added", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, - Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") - ), - //14 - list(Co_DESC="The hydraulic systems are active.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, - Co_AMOUNT = 10, - Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") - ), - //15 - list(Co_DESC="The hydraulic systems are connected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, - Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), - Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") - ), - //16 - list(Co_DESC="The hydraulic systems are disconnected.", - Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, - Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") - ) +//////////////////////////////// +///// Construction datums ////// +//////////////////////////////// + +#define MAINBOARD 4 +#define PERIBOARD 6 +#define TARGBOARD 8 +#define ARMOR_PLATES 17 + +/datum/construction/reversible/mecha + var/base_icon = "ripley" + var/mainboard = /obj/item/weapon/circuitboard/mecha/ripley/main + var/peripherals = /obj/item/weapon/circuitboard/mecha/ripley/peripherals + + steps = list( + //1 + list(Co_DESC="External armor is wrenched.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} external armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfasten{s} the external armor layer.") + ), + //2 + list(Co_DESC="External armor is installed.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} external armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} external armor layer from {HOLDER}.", + Co_START_MSG = "{USER} begin{s} removing the external reinforced armor...", + Co_DELAY = 30,) + ), + //3 + list(Co_DESC="Internal armor is welded.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/plasteel, + Co_AMOUNT = 5, + Co_VIS_MSG = "{USER} install{s} external reinforced armor layer to {HOLDER}.", + Co_START_MSG = "{USER} begin{s} installing the external reinforced armor...", + Co_DELAY = 30), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") + ), + //4 + list(Co_DESC="Internal armor is wrenched", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfastens the internal armor layer.") + ), + //5 + list(Co_DESC="Internal armor is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} internal armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") + ), + //6 + list(Co_DESC="Peripherals control module is secured", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, + Co_AMOUNT = 5, + Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") + ), + //7 + list(Co_DESC="Peripherals control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") + ), + //8 + list(Co_DESC="Central control module is secured", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") + ), + //9 + list(Co_DESC="Central control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the mainboard."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") + ), + //10 + list(Co_DESC="The wiring is adjusted", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") + ), + //11 + list(Co_DESC="The wiring is added", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, + Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") + ), + //12 + list(Co_DESC="The hydraulic systems are active.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, + Co_AMOUNT = 10, + Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") + ), + //13 + list(Co_DESC="The hydraulic systems are connected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") + ), + //14 + list(Co_DESC="The hydraulic systems are disconnected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") + ) + ) + +/datum/construction/reversible/mecha/New() + ..() + if(src) + add_board_keys() + +/datum/construction/reversible/mecha/custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + holder.icon_state = "[base_icon][steps.len - index - diff]" + return 1 + +/datum/construction/reversible/mecha/action(atom/used_atom,mob/user) + return check_step(used_atom,user) + +/datum/construction/reversible/mecha/proc/add_board_keys() + var/list/board_step = get_forward_step(steps.len - MAINBOARD) + board_step[Co_KEY] = mainboard + + board_step = get_forward_step(steps.len - PERIBOARD) + board_step[Co_KEY] = peripherals + +/datum/construction/reversible/mecha/spawn_result(mob/user as mob) + ..() + feedback_inc("mecha_[base_icon]_created",1) + return + +// custom_actions moved to construction_datum - N3X + + +/datum/construction/reversible/mecha/ripley + result = "/obj/mecha/working/ripley" + +/datum/construction/reversible/mecha/firefighter + result = "/obj/mecha/working/ripley/firefighter" + steps = list( + //1 + list(Co_DESC="External armor is wrenched.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} external armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfasten{s} the external armor layer.") + ), + //2 + list(Co_DESC="External armor is installed.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} external armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} external armor layer from {HOLDER}.", + Co_START_MSG = "{USER} begin{s} removing the external reinforced armor...", + Co_DELAY = 50,) + ), + //3 + list(Co_DESC="Internal armor is welded.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/plasteel, + Co_AMOUNT = 10, + Co_VIS_MSG = "{USER} install{s} external reinforced armor layer to {HOLDER}.", + Co_START_MSG = "{USER} begin{s} installing the external reinforced armor...", + Co_DELAY = 50), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") + ), + //4 + list(Co_DESC="Internal armor is wrenched", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfasten{s} the internal armor layer.") + ), + //5 + list(Co_DESC="Internal armor is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} internal armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") + ), + //6 + list(Co_DESC="Peripherals control module is secured", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, + Co_AMOUNT = 5, + Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") + ), + //7 + list(Co_DESC="Peripherals control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") + ), + //8 + list(Co_DESC="Central control module is secured", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") + ), + //9 + list(Co_DESC="Central control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the mainboard."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") + ), + //10 + list(Co_DESC="The wiring is adjusted", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") + ), + //11 + list(Co_DESC="The wiring is added", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, + Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") + ), + //12 + list(Co_DESC="The hydraulic systems are active.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, + Co_AMOUNT = 10, + Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") + ), + //13 + list(Co_DESC="The hydraulic systems are connected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") + ), + //14 + list(Co_DESC="The hydraulic systems are disconnected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") + ) + ) + + +/datum/construction/reversible/mecha/odysseus + result = "/obj/mecha/medical/odysseus" + base_icon = "odysseus" + + mainboard = /obj/item/weapon/circuitboard/mecha/odysseus/main + peripherals = /obj/item/weapon/circuitboard/mecha/odysseus/peripherals + +/datum/construction/reversible/mecha/combat + var/targeting = /obj/item/weapon/circuitboard/mecha/gygax/targeting + var/armor_plates = /obj/item/mecha_parts/part/gygax_armour + + steps = list( + //1 + list(Co_DESC="External armor is wrenched.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} armor plates to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfasten{s} the armor plates.") + ), + //2 + list(Co_DESC="External armor is installed.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} armor plates."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} armor plates from {HOLDER}.", + Co_DELAY = 30, + Co_START_MSG = "{USER} begin{s} removing the armor plates...") + ), + //3 + list(Co_DESC="Internal armor is welded.", + Co_NEXTSTEP = list(Co_KEY=null, //set by proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} armor plates to {HOLDER}.", + Co_START_MSG = "{USER} begin{s} installing the armor plates...", + Co_DELAY = 30), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") + ), + //4 + list(Co_DESC="Internal armor is wrenched", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfasten{s} the internal armor layer.") + ), + //5 + list(Co_DESC="Internal armor is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} internal armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") + ), + //6 + list(Co_DESC="Advanced capacitor is secured", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, + Co_AMOUNT = 5, + Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the advanced capacitor.") + ), + //7 + list(Co_DESC="Advanced capacitor is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the advanced capacitor."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the advanced capacitor from {HOLDER}.") + ), + //8 + list(Co_DESC="Advanced scanner module is secured", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/stock_parts/capacitor/adv, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} advanced capacitor to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the Advanced scanner module.") + ), + //9 + list(Co_DESC="Advanced scanner module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the advanced scanner module."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the advanced scanner module from {HOLDER}.") + ), + //10 + list(Co_DESC="Targeting module is secured", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/stock_parts/scanning_module/adv, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} advanced scanner module to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the targeting module.") + ), + //11 + list(Co_DESC="Targeting module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the targeting module."), + Co_BACKSTOP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the targeting module from {HOLDER}.") + ), + //12 + list(Co_DESC="Peripherals control module is secured", + Co_NEXTSTEP = list(Co_KEY= null, //set by proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the targeting module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") + ), + //13 + list(Co_DESC="Peripherals control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") + ), + //14 + list(Co_DESC="Central control module is secured", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") + ), + //15 + list(Co_DESC="Central control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the mainboard."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") + ), + //16 + list(Co_DESC="The wiring is adjusted", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") + ), + //17 + list(Co_DESC="The wiring is added", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, + Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") + ), + //18 + list(Co_DESC="The hydraulic systems are active.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, + Co_AMOUNT = 10, + Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") + ), + //19 + list(Co_DESC="The hydraulic systems are connected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") + ), + //20 + list(Co_DESC="The hydraulic systems are disconnected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") + ) + ) + +/datum/construction/reversible/mecha/combat/add_board_keys() + var/list/board_step = get_forward_step(steps.len - MAINBOARD) + board_step[Co_KEY] = mainboard + + board_step = get_forward_step(steps.len - PERIBOARD) + board_step[Co_KEY] = peripherals + + board_step = get_forward_step(steps.len - TARGBOARD) + board_step[Co_KEY] = targeting + + if(armor_plates) + board_step = get_forward_step(steps.len - ARMOR_PLATES) + board_step[Co_KEY] = armor_plates + +/datum/construction/reversible/mecha/combat/gygax + base_icon = "gygax" + mainboard = /obj/item/weapon/circuitboard/mecha/gygax/main + peripherals = /obj/item/weapon/circuitboard/mecha/gygax/peripherals + targeting = /obj/item/weapon/circuitboard/mecha/gygax/targeting + armor_plates = /obj/item/mecha_parts/part/gygax_armour + result = "/obj/mecha/combat/gygax" + +/datum/construction/reversible/mecha/combat/durand + mainboard = /obj/item/weapon/circuitboard/mecha/durand/main + peripherals = /obj/item/weapon/circuitboard/mecha/durand/peripherals + targeting = /obj/item/weapon/circuitboard/mecha/durand/targeting + armor_plates = /obj/item/mecha_parts/part/durand_armour + result = "/obj/mecha/combat/durand" + base_icon = "durand" + +/datum/construction/reversible/mecha/honker + base_icon = "honker" + result = "/obj/mecha/combat/honker" + steps = list( + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn, + Co_VIS_MSG = "{USER} adds the bike horn to {HOLDER}", + Co_AMOUNT = 1), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the clown boots from {HOLDER}.") + ),//1 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/clothing/shoes/clown_shoes, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} put{s} clown boots on {HOLDER}."), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) + ),//2 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the clown wig and mask from {HOLDER}.") + ),//3 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/clothing/mask/gas/clown_hat, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} put{s} clown wig and mask on {HOLDER}."), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) + ),//4 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} uninstall{s} the weapon control module.") + ),//5 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/circuitboard/mecha/honker/targeting, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the weapon control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) + ),//6 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} uninstall{s} the peripherals control module.") + ),//7 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/circuitboard/mecha/honker/peripherals, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) + ),//8 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} uninstall{s} the central control module.") + ),//9 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/circuitboard/mecha/honker/main, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY = /obj/item/weapon/bikehorn) + ),//10 + list( + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/bikehorn) + )//11 + ) + +/datum/construction/reversible/mecha/honker/set_desc() + return + +/datum/construction/reversible/mecha/honker/custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + if(istype(used_atom, /obj/item/weapon/bikehorn)) + playsound(holder, 'sound/items/bikehorn.ogg', 50, 1) + user.visible_message("HONK!") + + holder.icon_state = "honker_chassis" + return 1 + +/datum/construction/reversible/mecha/honker/add_board_keys() + return + + +/datum/construction/reversible/mecha/phazon + base_icon = "phazon" + mainboard = /obj/item/weapon/circuitboard/mecha/phazon/main + peripherals = /obj/item/weapon/circuitboard/mecha/phazon/peripherals + result = "/obj/mecha/combat/phazon" + + steps = list( + //1 + list(Co_DESC="External armor is wrenched.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} external armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfasten{s} the external armor layer.") + ), + //2 + list(Co_DESC="External armor is installed.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} external armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} external armor layer from {HOLDER}.", + Co_START_MSG = "{USER} begin{s} removing the external reinforced armor...", + Co_DELAY = 30,) + ), + //3 + list(Co_DESC="Internal armor is welded.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/plasteel, + Co_AMOUNT = 5, + Co_VIS_MSG = "{USER} install{s} external reinforced armor layer to {HOLDER}.", + Co_START_MSG = "{USER} begin{s} installing the external reinforced armor...", + Co_DELAY = 30), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} cut{s} internal armor layer from {HOLDER}.") + ), + //4 + list(Co_DESC="Internal armor is wrenched", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/weldingtool, + Co_AMOUNT = 3, + Co_VIS_MSG = "{USER} weld{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} unfastens the internal armor layer.") + ), + //5 + list(Co_DESC="Internal armor is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} secure{s} internal armor layer."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} prie{s} internal armor layer from {HOLDER}.") + ), + + //6 + list(Co_DESC="Phaze array is secured", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/sheet/metal, + Co_AMOUNT = 5, + Co_VIS_MSG = "{USER} install{s} internal armor layer to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the phaze array.") + ), + //7 + list(Co_DESC="Phaze array is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the phaze array."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the phaze array from {HOLDER}.") + ), + //8 + list(Co_DESC="Peripherals control module is secured", + Co_NEXTSTEP = list(Co_KEY= /obj/item/mecha_parts/part/phazon_phase_array, + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} phaze array to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the peripherals control module.") + ), + //9 + list(Co_DESC="Peripherals control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the peripherals control module."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the peripherals control module from {HOLDER}.") + ), + //10 + list(Co_DESC="Central control module is secured", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the peripherals control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} unfasten{s} the mainboard.") + ), + //11 + list(Co_DESC="Central control module is installed", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} secure{s} the mainboard."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/crowbar, + Co_VIS_MSG = "{USER} remove{s} the central control module from {HOLDER}.") + ), + //12 + list(Co_DESC="The wiring is adjusted", + Co_NEXTSTEP = list(Co_KEY= null, //set by a proc + Co_AMOUNT = 1, + Co_VIS_MSG = "{USER} install{s} the central control module into {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} disconnect{s} the wiring of {HOLDER}.") + ), + //13 + list(Co_DESC="The wiring is added", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wirecutters, + Co_VIS_MSG = "{USER} adjust{s} the wiring of {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} remove{s} the wiring of {HOLDER}.") + ), + //14 + list(Co_DESC="The hydraulic systems are active.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/stack/cable_coil, + Co_AMOUNT = 10, + Co_VIS_MSG = "{USER} add{s} the wiring to {HOLDER}."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} deactivate{s} {HOLDER} hydraulic systems.") + ), + //15 + list(Co_DESC="The hydraulic systems are connected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/screwdriver, + Co_VIS_MSG = "{USER} activate{s} {HOLDER} hydraulic systems."), + Co_BACKSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} disconnect{s} {HOLDER} hydraulic systems.") + ), + //16 + list(Co_DESC="The hydraulic systems are disconnected.", + Co_NEXTSTEP = list(Co_KEY=/obj/item/weapon/wrench, + Co_VIS_MSG = "{USER} connect{s} {HOLDER} hydraulic systems.") + ) ) \ No newline at end of file diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index d7e1cff7431..90b00f597dd 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -1,177 +1,177 @@ -/obj/machinery/computer/mecha - name = "Exosuit Control" - icon = 'icons/obj/computer.dmi' - icon_state = "mecha" - req_access = list(access_robotics) - circuit = "/obj/item/weapon/circuitboard/mecha_control" - var/list/located = list() - var/screen = 0 - var/stored_data - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/mecha/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/mecha/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/mecha/attack_hand(var/mob/user as mob) - if(..()) - return - user.set_machine(src) - var/dat = "[src.name]" - if(screen == 0) - dat += "

                      Tracking beacons data

                      " - for(var/obj/item/mecha_parts/mecha_tracking/TR in world) - var/answer = TR.get_mecha_info() - if(answer) - dat += {"
                      [answer]
                      - Send message
                      - Show exosuit log | - (Lockdown) | - (Detonate Beacon)
                      "} - - if(screen==1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\\mecha_control_console.dm:33: dat += "

                      Log contents

                      " - dat += {"

                      Log contents

                      - Return
                      - [stored_data]"} - // END AUTOFIX - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\\mecha_control_console.dm:37: dat += "(Refresh)
                      " - dat += {"(Refresh)
                      - "} - // END AUTOFIX - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - -/obj/machinery/computer/mecha/Topic(href, href_list) - if(..()) - return - var/datum/topic_input/filter = new /datum/topic_input(href,href_list) - if(href_list["send_message"]) - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message") - var/message = strip_html_simple(input(usr,"Input message","Transmit message") as text) - var/obj/mecha/M = MT.in_mecha() - if(trim(message) && M) - M.occupant_message(message) - return - if(href_list["lockdown"]) - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("lockdown") - var/obj/mecha/M = MT.in_mecha() - if(M.state) +/obj/machinery/computer/mecha + name = "Exosuit Control" + icon = 'icons/obj/computer.dmi' + icon_state = "mecha" + req_access = list(access_robotics) + circuit = "/obj/item/weapon/circuitboard/mecha_control" + var/list/located = list() + var/screen = 0 + var/stored_data + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/mecha/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/mecha/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/mecha/attack_hand(var/mob/user as mob) + if(..()) + return + user.set_machine(src) + var/dat = "[src.name]" + if(screen == 0) + dat += "

                      Tracking beacons data

                      " + for(var/obj/item/mecha_parts/mecha_tracking/TR in world) + var/answer = TR.get_mecha_info() + if(answer) + dat += {"
                      [answer]
                      + Send message
                      + Show exosuit log | + (Lockdown) | + (Detonate Beacon)
                      "} + + if(screen==1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\\mecha_control_console.dm:33: dat += "

                      Log contents

                      " + dat += {"

                      Log contents

                      + Return
                      + [stored_data]"} + // END AUTOFIX + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\\mecha\\mecha_control_console.dm:37: dat += "(Refresh)
                      " + dat += {"(Refresh)
                      + "} + // END AUTOFIX + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + +/obj/machinery/computer/mecha/Topic(href, href_list) + if(..()) + return + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) + if(href_list["send_message"]) + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message") + var/message = strip_html_simple(input(usr,"Input message","Transmit message") as text) + var/obj/mecha/M = MT.in_mecha() + if(trim(message) && M) + M.occupant_message(message) + return + if(href_list["lockdown"]) + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("lockdown") + var/obj/mecha/M = MT.in_mecha() + if(M.state) to_chat(usr, "That exosuit is already under lockdown!") - return - switch(alert("Are you sure? The exosuit will enter maintenance mode.","Transmit Beacon Lockdown Code","Yes","No")) - if ("Yes") - MT.lockdown() - if ("No") + return + switch(alert("Are you sure? The exosuit will enter maintenance mode.","Transmit Beacon Lockdown Code","Yes","No")) + if ("Yes") + MT.lockdown() + if ("No") to_chat(usr, "You have second thoughts.") - if(href_list["shock"]) - switch(alert("Are you sure? This cannot be undone.","Transmit Beacon Self-Destruct Code","Yes","No")) - if ("Yes") - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock") - MT.shock() - if ("No") + if(href_list["shock"]) + switch(alert("Are you sure? This cannot be undone.","Transmit Beacon Self-Destruct Code","Yes","No")) + if ("Yes") + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock") + MT.shock() + if ("No") to_chat(usr, "You have second thoughts.") - if(href_list["get_log"]) - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log") - stored_data = MT.get_mecha_log() - screen = 1 - if(href_list["return"]) - screen = 0 - src.updateUsrDialog() - return - - - -/obj/item/mecha_parts/mecha_tracking - name = "Exosuit tracking beacon" - desc = "Device used to transmit exosuit data." - icon = 'icons/obj/device.dmi' - icon_state = "motion2" - origin_tech = "programming=2;magnets=2" - var/lockdown = 0 - -/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info() - if(!in_mecha()) - return 0 - var/obj/mecha/M = src.loc - var/cell_charge = M.get_charge() - var/answer = {"Name: [M.name]
                      - Integrity: [M.health/initial(M.health)*100]%
                      - Cell charge: [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
                      - Airtank: [M.return_pressure()]kPa
                      - Pilot: [M.occupant||"None"]
                      - Location: [get_area(M)||"Unknown"]
                      - Active equipment: [M.selected||"None"]"} - if(istype(M, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/RM = M - answer += " Used cargo space: [RM.cargo.len/RM.cargo_capacity*100]%
                      " - - return answer - -/obj/item/mecha_parts/mecha_tracking/emp_act() - qdel(src) - return - -/obj/item/mecha_parts/mecha_tracking/ex_act() - qdel(src) - return - -/obj/item/mecha_parts/mecha_tracking/proc/in_mecha() - if(istype(src.loc, /obj/mecha)) - return src.loc - return 0 - -/obj/item/mecha_parts/mecha_tracking/proc/shock() - var/obj/mecha/M = in_mecha() - if(M) - M.log_message("Exosuit tracking beacon self-destruct activated.",1) - M.occupant_message("Exosuit tracking beacon short-circuits!") + if(href_list["get_log"]) + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log") + stored_data = MT.get_mecha_log() + screen = 1 + if(href_list["return"]) + screen = 0 + src.updateUsrDialog() + return + + + +/obj/item/mecha_parts/mecha_tracking + name = "Exosuit tracking beacon" + desc = "Device used to transmit exosuit data." + icon = 'icons/obj/device.dmi' + icon_state = "motion2" + origin_tech = "programming=2;magnets=2" + var/lockdown = 0 + +/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info() + if(!in_mecha()) + return 0 + var/obj/mecha/M = src.loc + var/cell_charge = M.get_charge() + var/answer = {"Name: [M.name]
                      + Integrity: [M.health/initial(M.health)*100]%
                      + Cell charge: [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
                      + Airtank: [M.return_pressure()]kPa
                      + Pilot: [M.occupant||"None"]
                      + Location: [get_area(M)||"Unknown"]
                      + Active equipment: [M.selected||"None"]"} + if(istype(M, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/RM = M + answer += " Used cargo space: [RM.cargo.len/RM.cargo_capacity*100]%
                      " + + return answer + +/obj/item/mecha_parts/mecha_tracking/emp_act() + qdel(src) + return + +/obj/item/mecha_parts/mecha_tracking/ex_act() + qdel(src) + return + +/obj/item/mecha_parts/mecha_tracking/proc/in_mecha() + if(istype(src.loc, /obj/mecha)) + return src.loc + return 0 + +/obj/item/mecha_parts/mecha_tracking/proc/shock() + var/obj/mecha/M = in_mecha() + if(M) + M.log_message("Exosuit tracking beacon self-destruct activated.",1) + M.occupant_message("Exosuit tracking beacon short-circuits!") to_chat(M.occupant, sound('sound/machines/warning-buzzer.ogg',wait=0)) - if (M.get_charge()) - if (M.cell.charge < 5000 && M) - M.use_power(M.cell.charge/4) - M.take_damage(25,"energy") - if (M.cell.charge > 5000 && M) - M.take_damage((round(M.cell.charge/5000)*50),"energy") - M.use_power(round(M.cell.charge/5000)*(rand(4000,5000))) //that's weird math - M.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - qdel(src) - -/obj/item/mecha_parts/mecha_tracking/proc/lockdown() - var/obj/mecha/M = in_mecha() - if(M) - if(M.state) //It's already in lockdown! - return - M.log_message("Emergency maintenance protocols activated.",1) - if(M.occupant) - M.occupant_message("Exosuit emergency maintenance protocols activated.") + if (M.get_charge()) + if (M.cell.charge < 5000 && M) + M.use_power(M.cell.charge/4) + M.take_damage(25,"energy") + if (M.cell.charge > 5000 && M) + M.take_damage((round(M.cell.charge/5000)*50),"energy") + M.use_power(round(M.cell.charge/5000)*(rand(4000,5000))) //that's weird math + M.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) + qdel(src) + +/obj/item/mecha_parts/mecha_tracking/proc/lockdown() + var/obj/mecha/M = in_mecha() + if(M) + if(M.state) //It's already in lockdown! + return + M.log_message("Emergency maintenance protocols activated.",1) + if(M.occupant) + M.occupant_message("Exosuit emergency maintenance protocols activated.") to_chat(M.occupant, sound('sound/mecha/mechlockdown.ogg',wait=0)) - M.state = 1 - -/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log() - if(!src.in_mecha()) - return 0 - var/obj/mecha/M = src.loc - return M.get_log_html() - -/obj/item/weapon/storage/box/mechabeacons - name = "Exosuit Tracking Beacons" -/obj/item/weapon/storage/box/mechabeacons/New() - ..() - new /obj/item/mecha_parts/mecha_tracking(src) - new /obj/item/mecha_parts/mecha_tracking(src) - new /obj/item/mecha_parts/mecha_tracking(src) - new /obj/item/mecha_parts/mecha_tracking(src) - new /obj/item/mecha_parts/mecha_tracking(src) - new /obj/item/mecha_parts/mecha_tracking(src) - new /obj/item/mecha_parts/mecha_tracking(src) + M.state = 1 + +/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log() + if(!src.in_mecha()) + return 0 + var/obj/mecha/M = src.loc + return M.get_log_html() + +/obj/item/weapon/storage/box/mechabeacons + name = "Exosuit Tracking Beacons" +/obj/item/weapon/storage/box/mechabeacons/New() + ..() + new /obj/item/mecha_parts/mecha_tracking(src) + new /obj/item/mecha_parts/mecha_tracking(src) + new /obj/item/mecha_parts/mecha_tracking(src) + new /obj/item/mecha_parts/mecha_tracking(src) + new /obj/item/mecha_parts/mecha_tracking(src) + new /obj/item/mecha_parts/mecha_tracking(src) + new /obj/item/mecha_parts/mecha_tracking(src) diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm index 47bb637298b..c0060503a56 100644 --- a/code/game/mecha/mecha_parts.dm +++ b/code/game/mecha/mecha_parts.dm @@ -1,426 +1,426 @@ -///////////////////////// -////// Mecha Parts ////// -///////////////////////// - -/obj/item/mecha_parts - name = "mecha part" - icon = 'icons/mecha/mech_construct.dmi' - icon_state = "blank" - w_class = 20 - flags = FPRINT - siemens_coefficient = 1 - origin_tech = "programming=2;materials=2" - - -/obj/item/mecha_parts/chassis - name="Mecha Chassis" - icon_state = "backbone" - var/datum/construction/construct - flags = FPRINT - siemens_coefficient = 1 - - attackby(obj/item/W as obj, mob/user as mob) - if(!construct || !construct.action(W, user)) - ..() - return - - attack_hand() - return - -/////////// Ripley - -/obj/item/mecha_parts/chassis/ripley - name = "Ripley Chassis" - - New() - ..() - construct = new /datum/construction/mecha_chassis/ripley(src) - -/obj/item/mecha_parts/part/ripley_torso - name="Ripley Torso" - desc="A torso part of Ripley APLU. Contains power unit, processing core and life support systems." - icon_state = "ripley_harness" - origin_tech = "programming=2;materials=2;biotech=2;engineering=2" - -/obj/item/mecha_parts/part/ripley_left_arm - name="Ripley Left Arm" - desc="A Ripley APLU left arm. Data and power sockets are compatible with most exosuit tools." - icon_state = "ripley_l_arm" - origin_tech = "programming=2;materials=2;engineering=2" - -/obj/item/mecha_parts/part/ripley_right_arm - name="Ripley Right Arm" - desc="A Ripley APLU right arm. Data and power sockets are compatible with most exosuit tools." - icon_state = "ripley_r_arm" - origin_tech = "programming=2;materials=2;engineering=2" - -/obj/item/mecha_parts/part/ripley_left_leg - name="Ripley Left Leg" - desc="A Ripley APLU left leg. Contains somewhat complex servodrives and balance maintaining systems." - icon_state = "ripley_l_leg" - origin_tech = "programming=2;materials=2;engineering=2" - -/obj/item/mecha_parts/part/ripley_right_leg - name="Ripley Right Leg" - desc="A Ripley APLU right leg. Contains somewhat complex servodrives and balance maintaining systems." - icon_state = "ripley_r_leg" - origin_tech = "programming=2;materials=2;engineering=2" - -///////// Gygax - -/obj/item/mecha_parts/chassis/gygax - name = "Gygax Chassis" - - New() - ..() - construct = new /datum/construction/mecha_chassis/gygax(src) - -/obj/item/mecha_parts/part/gygax_torso - name="Gygax Torso" - desc="A torso part of Gygax. Contains power unit, processing core and life support systems. Has an additional equipment slot." - icon_state = "gygax_harness" - origin_tech = "programming=2;materials=2;biotech=3;engineering=3" - -/obj/item/mecha_parts/part/gygax_head - name="Gygax Head" - desc="A Gygax head. Houses advanced surveilance and targeting sensors." - icon_state = "gygax_head" - origin_tech = "programming=2;materials=2;magnets=3;engineering=3" - -/obj/item/mecha_parts/part/gygax_left_arm - name="Gygax Left Arm" - desc="A Gygax left arm. Data and power sockets are compatible with most exosuit tools and weapons." - icon_state = "gygax_l_arm" - origin_tech = "programming=2;materials=2;engineering=3" - -/obj/item/mecha_parts/part/gygax_right_arm - name="Gygax Right Arm" - desc="A Gygax right arm. Data and power sockets are compatible with most exosuit tools and weapons." - icon_state = "gygax_r_arm" - origin_tech = "programming=2;materials=2;engineering=3" - -/obj/item/mecha_parts/part/gygax_left_leg - name="Gygax Left Leg" - icon_state = "gygax_l_leg" - origin_tech = "programming=2;materials=2;engineering=3" - -/obj/item/mecha_parts/part/gygax_right_leg - name="Gygax Right Leg" - icon_state = "gygax_r_leg" - origin_tech = "programming=2;materials=2;engineering=3" - -/obj/item/mecha_parts/part/gygax_armour - name="Gygax Armour Plates" - icon_state = "gygax_armour" - origin_tech = "materials=6;combat=4;engineering=5" - - -//////////// Durand - -/obj/item/mecha_parts/chassis/durand - name = "Durand Chassis" - - New() - ..() - construct = new /datum/construction/mecha_chassis/durand(src) - -/obj/item/mecha_parts/part/durand_torso - name="Durand Torso" - icon_state = "durand_harness" - origin_tech = "programming=2;materials=3;biotech=3;engineering=3" - -/obj/item/mecha_parts/part/durand_head - name="Durand Head" - icon_state = "durand_head" - origin_tech = "programming=2;materials=3;magnets=3;engineering=3" - -/obj/item/mecha_parts/part/durand_left_arm - name="Durand Left Arm" - icon_state = "durand_l_arm" - origin_tech = "programming=2;materials=3;engineering=3" - -/obj/item/mecha_parts/part/durand_right_arm - name="Durand Right Arm" - icon_state = "durand_r_arm" - origin_tech = "programming=2;materials=3;engineering=3" - -/obj/item/mecha_parts/part/durand_left_leg - name="Durand Left Leg" - icon_state = "durand_l_leg" - origin_tech = "programming=2;materials=3;engineering=3" - -/obj/item/mecha_parts/part/durand_right_leg - name="Durand Right Leg" - icon_state = "durand_r_leg" - origin_tech = "programming=2;materials=3;engineering=3" - -/obj/item/mecha_parts/part/durand_armour - name="Durand Armour Plates" - icon_state = "durand_armour" - origin_tech = "materials=5;combat=4;engineering=5" - - - -////////// Firefighter - -/obj/item/mecha_parts/chassis/firefighter - name = "Firefighter Chassis" - - New() - ..() - construct = new /datum/construction/mecha_chassis/firefighter(src) -/* -/obj/item/mecha_parts/part/firefighter_torso - name="Ripley-on-Fire Torso" - icon_state = "ripley_harness" - -/obj/item/mecha_parts/part/firefighter_left_arm - name="Ripley-on-Fire Left Arm" - icon_state = "ripley_l_arm" - -/obj/item/mecha_parts/part/firefighter_right_arm - name="Ripley-on-Fire Right Arm" - icon_state = "ripley_r_arm" - -/obj/item/mecha_parts/part/firefighter_left_leg - name="Ripley-on-Fire Left Leg" - icon_state = "ripley_l_leg" - -/obj/item/mecha_parts/part/firefighter_right_leg - name="Ripley-on-Fire Right Leg" - icon_state = "ripley_r_leg" -*/ - -////////// HONK - -/obj/item/mecha_parts/chassis/honker - name = "H.O.N.K Chassis" - - New() - ..() - construct = new /datum/construction/mecha_chassis/honker(src) - -/obj/item/mecha_parts/part/honker_torso - name="H.O.N.K Torso" - icon_state = "honker_harness" - -/obj/item/mecha_parts/part/honker_head - name="H.O.N.K Head" - icon_state = "honker_head" - -/obj/item/mecha_parts/part/honker_left_arm - name="H.O.N.K Left Arm" - icon_state = "honker_l_arm" - -/obj/item/mecha_parts/part/honker_right_arm - name="H.O.N.K Right Arm" - icon_state = "honker_r_arm" - -/obj/item/mecha_parts/part/honker_left_leg - name="H.O.N.K Left Leg" - icon_state = "honker_l_leg" - -/obj/item/mecha_parts/part/honker_right_leg - name="H.O.N.K Right Leg" - icon_state = "honker_r_leg" - - -////////// Phazon - -/obj/item/mecha_parts/chassis/phazon - name = "Phazon Chassis" - origin_tech = "materials=7" - - New() - ..() - construct = new /datum/construction/mecha_chassis/phazon(src) - -/obj/item/mecha_parts/part/phazon_torso - name="Phazon Torso" - icon_state = "phazon_harness" - origin_tech = "programming=5;materials=9;bluespace=10;powerstorage=6" - -/obj/item/mecha_parts/part/phazon_head - name="Phazon Head" - icon_state = "phazon_head" - origin_tech = "programming=5;materials=9;magnets=6" - -/obj/item/mecha_parts/part/phazon_left_arm - name="Phazon Left Arm" - icon_state = "phazon_l_arm" - origin_tech = "materials=9;bluespace=6;magnets=2" - -/obj/item/mecha_parts/part/phazon_right_arm - name="Phazon Right Arm" - icon_state = "phazon_r_arm" - origin_tech = "materials=9;bluespace=6;magnets=2" - -/obj/item/mecha_parts/part/phazon_left_leg - name="Phazon Left Leg" - icon_state = "phazon_l_leg" - origin_tech = "materials=9;bluespace=6;magnets=3" - -/obj/item/mecha_parts/part/phazon_right_leg - name="Phazon Right Leg" - icon_state = "phazon_r_leg" - origin_tech = "materials=9;bluespace=6;magnets=3" - -/obj/item/mecha_parts/part/phazon_phase_array - name="Phase Array" - icon_state = "phazon_phase_array" - origin_tech = "materials=9;bluespace=10;magnets=3" - -///////// Odysseus - - -/obj/item/mecha_parts/chassis/odysseus - name = "Odysseus Chassis" - - New() - ..() - construct = new /datum/construction/mecha_chassis/odysseus(src) - -/obj/item/mecha_parts/part/odysseus_head - name="Odysseus Head" - icon_state = "odysseus_head" - origin_tech = "programming=3;materials=2" - -/obj/item/mecha_parts/part/odysseus_torso - name="Odysseus Torso" - desc="A torso part of Odysseus. Contains power unit, processing core and life support systems." - icon_state = "odysseus_torso" - origin_tech = "programming=2;materials=2;biotech=2;engineering=2" - -/obj/item/mecha_parts/part/odysseus_left_arm - name="Odysseus Left Arm" - desc="An Odysseus left arm. Data and power sockets are compatible with most exosuit tools." - icon_state = "odysseus_l_arm" - origin_tech = "programming=2;materials=2;engineering=2" - -/obj/item/mecha_parts/part/odysseus_right_arm - name="Odysseus Right Arm" - desc="An Odysseus right arm. Data and power sockets are compatible with most exosuit tools." - icon_state = "odysseus_r_arm" - origin_tech = "programming=2;materials=2;engineering=2" - -/obj/item/mecha_parts/part/odysseus_left_leg - name="Odysseus Left Leg" - desc="An Odysseus left leg. Contains somewhat complex servodrives and balance maintaining systems." - icon_state = "odysseus_l_leg" - origin_tech = "programming=2;materials=2;engineering=2" - -/obj/item/mecha_parts/part/odysseus_right_leg - name="Odysseus Right Leg" - desc="A Odysseus right leg. Contains somewhat complex servodrives and balance maintaining systems." - icon_state = "odysseus_r_leg" - origin_tech = "programming=2;materials=2;engineering=2" - -/*/obj/item/mecha_parts/part/odysseus_armour - name="Odysseus Carapace" - icon_state = "odysseus_armour" - origin_tech = "materials=3;engineering=3" - construction_time = 200 - materials = list(MAT_IRON=15000)*/ - - -///////// Circuitboards - -/obj/item/weapon/circuitboard/mecha - name = "Exosuit Circuit board" - icon = 'icons/obj/module.dmi' - icon_state = "std_mod" - item_state = "circuitboard" - board_type = "other" - flags = FPRINT - siemens_coefficient = 1 - force = 5.0 - w_class = 2.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 15 - - ripley - origin_tech = "programming=3" - - ripley/peripherals - name = "Circuit board (Ripley Peripherals Control module)" - icon_state = "mcontroller" - - ripley/main - name = "Circuit board (Ripley Central Control module)" - icon_state = "mainboard" - - gygax - origin_tech = "programming=4" - - gygax/peripherals - name = "Circuit board (Gygax Peripherals Control module)" - icon_state = "mcontroller" - - gygax/targeting - name = "Circuit board (Gygax Weapon Control and Targeting module)" - icon_state = "mcontroller" - origin_tech = "programming=4;combat=4" - - gygax/main - name = "Circuit board (Gygax Central Control module)" - icon_state = "mainboard" - - durand - origin_tech = "programming=4" - - durand/peripherals - name = "Circuit board (Durand Peripherals Control module)" - icon_state = "mcontroller" - - durand/targeting - name = "Circuit board (Durand Weapon Control and Targeting module)" - icon_state = "mcontroller" - origin_tech = "programming=4;combat=4" - - durand/main - name = "Circuit board (Durand Central Control module)" - icon_state = "mainboard" - - honker - origin_tech = "programming=4" - - honker/peripherals - name = "Circuit board (H.O.N.K Peripherals Control module)" - icon_state = "mcontroller" - - honker/targeting - name = "Circuit board (H.O.N.K Weapon Control and Targeting module)" - icon_state = "mcontroller" - - honker/main - name = "Circuit board (H.O.N.K Central Control module)" - icon_state = "mainboard" - - odysseus - origin_tech = "programming=3" - - odysseus/peripherals - name = "Circuit board (Odysseus Peripherals Control module)" - icon_state = "mcontroller" - - odysseus/main - name = "Circuit board (Odysseus Central Control module)" - icon_state = "mainboard" - - phazon - origin_tech = "materials=9;bluespace=10" - - phazon/peripherals - name = "Circuit board (Phazon Peripherals Control module)" - icon_state = "mcontroller" - - phazon/main - name = "Circuit board (Phazon Central Control module)" - icon_state = "mainboard" - - pod - name = "Circuit board (Space Pod Mainboard)" - icon_state = "mainboard" - - +///////////////////////// +////// Mecha Parts ////// +///////////////////////// + +/obj/item/mecha_parts + name = "mecha part" + icon = 'icons/mecha/mech_construct.dmi' + icon_state = "blank" + w_class = 20 + flags = FPRINT + siemens_coefficient = 1 + origin_tech = "programming=2;materials=2" + + +/obj/item/mecha_parts/chassis + name="Mecha Chassis" + icon_state = "backbone" + var/datum/construction/construct + flags = FPRINT + siemens_coefficient = 1 + + attackby(obj/item/W as obj, mob/user as mob) + if(!construct || !construct.action(W, user)) + ..() + return + + attack_hand() + return + +/////////// Ripley + +/obj/item/mecha_parts/chassis/ripley + name = "Ripley Chassis" + + New() + ..() + construct = new /datum/construction/mecha_chassis/ripley(src) + +/obj/item/mecha_parts/part/ripley_torso + name="Ripley Torso" + desc="A torso part of Ripley APLU. Contains power unit, processing core and life support systems." + icon_state = "ripley_harness" + origin_tech = "programming=2;materials=2;biotech=2;engineering=2" + +/obj/item/mecha_parts/part/ripley_left_arm + name="Ripley Left Arm" + desc="A Ripley APLU left arm. Data and power sockets are compatible with most exosuit tools." + icon_state = "ripley_l_arm" + origin_tech = "programming=2;materials=2;engineering=2" + +/obj/item/mecha_parts/part/ripley_right_arm + name="Ripley Right Arm" + desc="A Ripley APLU right arm. Data and power sockets are compatible with most exosuit tools." + icon_state = "ripley_r_arm" + origin_tech = "programming=2;materials=2;engineering=2" + +/obj/item/mecha_parts/part/ripley_left_leg + name="Ripley Left Leg" + desc="A Ripley APLU left leg. Contains somewhat complex servodrives and balance maintaining systems." + icon_state = "ripley_l_leg" + origin_tech = "programming=2;materials=2;engineering=2" + +/obj/item/mecha_parts/part/ripley_right_leg + name="Ripley Right Leg" + desc="A Ripley APLU right leg. Contains somewhat complex servodrives and balance maintaining systems." + icon_state = "ripley_r_leg" + origin_tech = "programming=2;materials=2;engineering=2" + +///////// Gygax + +/obj/item/mecha_parts/chassis/gygax + name = "Gygax Chassis" + + New() + ..() + construct = new /datum/construction/mecha_chassis/gygax(src) + +/obj/item/mecha_parts/part/gygax_torso + name="Gygax Torso" + desc="A torso part of Gygax. Contains power unit, processing core and life support systems. Has an additional equipment slot." + icon_state = "gygax_harness" + origin_tech = "programming=2;materials=2;biotech=3;engineering=3" + +/obj/item/mecha_parts/part/gygax_head + name="Gygax Head" + desc="A Gygax head. Houses advanced surveilance and targeting sensors." + icon_state = "gygax_head" + origin_tech = "programming=2;materials=2;magnets=3;engineering=3" + +/obj/item/mecha_parts/part/gygax_left_arm + name="Gygax Left Arm" + desc="A Gygax left arm. Data and power sockets are compatible with most exosuit tools and weapons." + icon_state = "gygax_l_arm" + origin_tech = "programming=2;materials=2;engineering=3" + +/obj/item/mecha_parts/part/gygax_right_arm + name="Gygax Right Arm" + desc="A Gygax right arm. Data and power sockets are compatible with most exosuit tools and weapons." + icon_state = "gygax_r_arm" + origin_tech = "programming=2;materials=2;engineering=3" + +/obj/item/mecha_parts/part/gygax_left_leg + name="Gygax Left Leg" + icon_state = "gygax_l_leg" + origin_tech = "programming=2;materials=2;engineering=3" + +/obj/item/mecha_parts/part/gygax_right_leg + name="Gygax Right Leg" + icon_state = "gygax_r_leg" + origin_tech = "programming=2;materials=2;engineering=3" + +/obj/item/mecha_parts/part/gygax_armour + name="Gygax Armour Plates" + icon_state = "gygax_armour" + origin_tech = "materials=6;combat=4;engineering=5" + + +//////////// Durand + +/obj/item/mecha_parts/chassis/durand + name = "Durand Chassis" + + New() + ..() + construct = new /datum/construction/mecha_chassis/durand(src) + +/obj/item/mecha_parts/part/durand_torso + name="Durand Torso" + icon_state = "durand_harness" + origin_tech = "programming=2;materials=3;biotech=3;engineering=3" + +/obj/item/mecha_parts/part/durand_head + name="Durand Head" + icon_state = "durand_head" + origin_tech = "programming=2;materials=3;magnets=3;engineering=3" + +/obj/item/mecha_parts/part/durand_left_arm + name="Durand Left Arm" + icon_state = "durand_l_arm" + origin_tech = "programming=2;materials=3;engineering=3" + +/obj/item/mecha_parts/part/durand_right_arm + name="Durand Right Arm" + icon_state = "durand_r_arm" + origin_tech = "programming=2;materials=3;engineering=3" + +/obj/item/mecha_parts/part/durand_left_leg + name="Durand Left Leg" + icon_state = "durand_l_leg" + origin_tech = "programming=2;materials=3;engineering=3" + +/obj/item/mecha_parts/part/durand_right_leg + name="Durand Right Leg" + icon_state = "durand_r_leg" + origin_tech = "programming=2;materials=3;engineering=3" + +/obj/item/mecha_parts/part/durand_armour + name="Durand Armour Plates" + icon_state = "durand_armour" + origin_tech = "materials=5;combat=4;engineering=5" + + + +////////// Firefighter + +/obj/item/mecha_parts/chassis/firefighter + name = "Firefighter Chassis" + + New() + ..() + construct = new /datum/construction/mecha_chassis/firefighter(src) +/* +/obj/item/mecha_parts/part/firefighter_torso + name="Ripley-on-Fire Torso" + icon_state = "ripley_harness" + +/obj/item/mecha_parts/part/firefighter_left_arm + name="Ripley-on-Fire Left Arm" + icon_state = "ripley_l_arm" + +/obj/item/mecha_parts/part/firefighter_right_arm + name="Ripley-on-Fire Right Arm" + icon_state = "ripley_r_arm" + +/obj/item/mecha_parts/part/firefighter_left_leg + name="Ripley-on-Fire Left Leg" + icon_state = "ripley_l_leg" + +/obj/item/mecha_parts/part/firefighter_right_leg + name="Ripley-on-Fire Right Leg" + icon_state = "ripley_r_leg" +*/ + +////////// HONK + +/obj/item/mecha_parts/chassis/honker + name = "H.O.N.K Chassis" + + New() + ..() + construct = new /datum/construction/mecha_chassis/honker(src) + +/obj/item/mecha_parts/part/honker_torso + name="H.O.N.K Torso" + icon_state = "honker_harness" + +/obj/item/mecha_parts/part/honker_head + name="H.O.N.K Head" + icon_state = "honker_head" + +/obj/item/mecha_parts/part/honker_left_arm + name="H.O.N.K Left Arm" + icon_state = "honker_l_arm" + +/obj/item/mecha_parts/part/honker_right_arm + name="H.O.N.K Right Arm" + icon_state = "honker_r_arm" + +/obj/item/mecha_parts/part/honker_left_leg + name="H.O.N.K Left Leg" + icon_state = "honker_l_leg" + +/obj/item/mecha_parts/part/honker_right_leg + name="H.O.N.K Right Leg" + icon_state = "honker_r_leg" + + +////////// Phazon + +/obj/item/mecha_parts/chassis/phazon + name = "Phazon Chassis" + origin_tech = "materials=7" + + New() + ..() + construct = new /datum/construction/mecha_chassis/phazon(src) + +/obj/item/mecha_parts/part/phazon_torso + name="Phazon Torso" + icon_state = "phazon_harness" + origin_tech = "programming=5;materials=9;bluespace=10;powerstorage=6" + +/obj/item/mecha_parts/part/phazon_head + name="Phazon Head" + icon_state = "phazon_head" + origin_tech = "programming=5;materials=9;magnets=6" + +/obj/item/mecha_parts/part/phazon_left_arm + name="Phazon Left Arm" + icon_state = "phazon_l_arm" + origin_tech = "materials=9;bluespace=6;magnets=2" + +/obj/item/mecha_parts/part/phazon_right_arm + name="Phazon Right Arm" + icon_state = "phazon_r_arm" + origin_tech = "materials=9;bluespace=6;magnets=2" + +/obj/item/mecha_parts/part/phazon_left_leg + name="Phazon Left Leg" + icon_state = "phazon_l_leg" + origin_tech = "materials=9;bluespace=6;magnets=3" + +/obj/item/mecha_parts/part/phazon_right_leg + name="Phazon Right Leg" + icon_state = "phazon_r_leg" + origin_tech = "materials=9;bluespace=6;magnets=3" + +/obj/item/mecha_parts/part/phazon_phase_array + name="Phase Array" + icon_state = "phazon_phase_array" + origin_tech = "materials=9;bluespace=10;magnets=3" + +///////// Odysseus + + +/obj/item/mecha_parts/chassis/odysseus + name = "Odysseus Chassis" + + New() + ..() + construct = new /datum/construction/mecha_chassis/odysseus(src) + +/obj/item/mecha_parts/part/odysseus_head + name="Odysseus Head" + icon_state = "odysseus_head" + origin_tech = "programming=3;materials=2" + +/obj/item/mecha_parts/part/odysseus_torso + name="Odysseus Torso" + desc="A torso part of Odysseus. Contains power unit, processing core and life support systems." + icon_state = "odysseus_torso" + origin_tech = "programming=2;materials=2;biotech=2;engineering=2" + +/obj/item/mecha_parts/part/odysseus_left_arm + name="Odysseus Left Arm" + desc="An Odysseus left arm. Data and power sockets are compatible with most exosuit tools." + icon_state = "odysseus_l_arm" + origin_tech = "programming=2;materials=2;engineering=2" + +/obj/item/mecha_parts/part/odysseus_right_arm + name="Odysseus Right Arm" + desc="An Odysseus right arm. Data and power sockets are compatible with most exosuit tools." + icon_state = "odysseus_r_arm" + origin_tech = "programming=2;materials=2;engineering=2" + +/obj/item/mecha_parts/part/odysseus_left_leg + name="Odysseus Left Leg" + desc="An Odysseus left leg. Contains somewhat complex servodrives and balance maintaining systems." + icon_state = "odysseus_l_leg" + origin_tech = "programming=2;materials=2;engineering=2" + +/obj/item/mecha_parts/part/odysseus_right_leg + name="Odysseus Right Leg" + desc="A Odysseus right leg. Contains somewhat complex servodrives and balance maintaining systems." + icon_state = "odysseus_r_leg" + origin_tech = "programming=2;materials=2;engineering=2" + +/*/obj/item/mecha_parts/part/odysseus_armour + name="Odysseus Carapace" + icon_state = "odysseus_armour" + origin_tech = "materials=3;engineering=3" + construction_time = 200 + materials = list(MAT_IRON=15000)*/ + + +///////// Circuitboards + +/obj/item/weapon/circuitboard/mecha + name = "Exosuit Circuit board" + icon = 'icons/obj/module.dmi' + icon_state = "std_mod" + item_state = "circuitboard" + board_type = "other" + flags = FPRINT + siemens_coefficient = 1 + force = 5.0 + w_class = 2.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 15 + + ripley + origin_tech = "programming=3" + + ripley/peripherals + name = "Circuit board (Ripley Peripherals Control module)" + icon_state = "mcontroller" + + ripley/main + name = "Circuit board (Ripley Central Control module)" + icon_state = "mainboard" + + gygax + origin_tech = "programming=4" + + gygax/peripherals + name = "Circuit board (Gygax Peripherals Control module)" + icon_state = "mcontroller" + + gygax/targeting + name = "Circuit board (Gygax Weapon Control and Targeting module)" + icon_state = "mcontroller" + origin_tech = "programming=4;combat=4" + + gygax/main + name = "Circuit board (Gygax Central Control module)" + icon_state = "mainboard" + + durand + origin_tech = "programming=4" + + durand/peripherals + name = "Circuit board (Durand Peripherals Control module)" + icon_state = "mcontroller" + + durand/targeting + name = "Circuit board (Durand Weapon Control and Targeting module)" + icon_state = "mcontroller" + origin_tech = "programming=4;combat=4" + + durand/main + name = "Circuit board (Durand Central Control module)" + icon_state = "mainboard" + + honker + origin_tech = "programming=4" + + honker/peripherals + name = "Circuit board (H.O.N.K Peripherals Control module)" + icon_state = "mcontroller" + + honker/targeting + name = "Circuit board (H.O.N.K Weapon Control and Targeting module)" + icon_state = "mcontroller" + + honker/main + name = "Circuit board (H.O.N.K Central Control module)" + icon_state = "mainboard" + + odysseus + origin_tech = "programming=3" + + odysseus/peripherals + name = "Circuit board (Odysseus Peripherals Control module)" + icon_state = "mcontroller" + + odysseus/main + name = "Circuit board (Odysseus Central Control module)" + icon_state = "mainboard" + + phazon + origin_tech = "materials=9;bluespace=10" + + phazon/peripherals + name = "Circuit board (Phazon Peripherals Control module)" + icon_state = "mcontroller" + + phazon/main + name = "Circuit board (Phazon Central Control module)" + icon_state = "mainboard" + + pod + name = "Circuit board (Space Pod Mainboard)" + icon_state = "mainboard" + + diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 82992422cea..8e7a1b0ddec 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -1,225 +1,225 @@ -/////////////////////////////////// -//////// Mecha wreckage //////// -/////////////////////////////////// - - -/obj/effect/decal/mecha_wreckage - name = "Exosuit wreckage" - desc = "Remains of some unfortunate mecha. Completely unrepairable." - icon = 'icons/mecha/mecha.dmi' - density = 1 - anchored = 0 - opacity = 0 - var/list/welder_salvage = list(/obj/item/stack/sheet/plasteel,/obj/item/stack/sheet/metal,/obj/item/stack/rods) - var/list/wirecutters_salvage = list(/obj/item/stack/cable_coil) - var/list/crowbar_salvage - var/salvage_num = 5 - - New() - ..() - crowbar_salvage = new - return - -/obj/effect/decal/mecha_wreckage/ex_act(severity) - if(severity < 2) - spawn - qdel(src) - return - -/obj/effect/decal/mecha_wreckage/bullet_act(var/obj/item/projectile/Proj) - return - - -/obj/effect/decal/mecha_wreckage/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(salvage_num <= 0) +/////////////////////////////////// +//////// Mecha wreckage //////// +/////////////////////////////////// + + +/obj/effect/decal/mecha_wreckage + name = "Exosuit wreckage" + desc = "Remains of some unfortunate mecha. Completely unrepairable." + icon = 'icons/mecha/mecha.dmi' + density = 1 + anchored = 0 + opacity = 0 + var/list/welder_salvage = list(/obj/item/stack/sheet/plasteel,/obj/item/stack/sheet/metal,/obj/item/stack/rods) + var/list/wirecutters_salvage = list(/obj/item/stack/cable_coil) + var/list/crowbar_salvage + var/salvage_num = 5 + + New() + ..() + crowbar_salvage = new + return + +/obj/effect/decal/mecha_wreckage/ex_act(severity) + if(severity < 2) + spawn + qdel(src) + return + +/obj/effect/decal/mecha_wreckage/bullet_act(var/obj/item/projectile/Proj) + return + + +/obj/effect/decal/mecha_wreckage/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(salvage_num <= 0) to_chat(user, "You don't see anything that can be cut with [W].") - return - if (!isemptylist(welder_salvage) && WT.remove_fuel(0,user)) - var/type = prob(70)?pick(welder_salvage):null - if(type) - var/N = new type(get_turf(user)) - user.visible_message("[user] cuts [N] from [src]", "You cut [N] from [src]", "You hear a sound of welder nearby") - if(istype(N, /obj/item/mecha_parts/part)) - welder_salvage -= type - salvage_num-- - else + return + if (!isemptylist(welder_salvage) && WT.remove_fuel(0,user)) + var/type = prob(70)?pick(welder_salvage):null + if(type) + var/N = new type(get_turf(user)) + user.visible_message("[user] cuts [N] from [src]", "You cut [N] from [src]", "You hear a sound of welder nearby") + if(istype(N, /obj/item/mecha_parts/part)) + welder_salvage -= type + salvage_num-- + else to_chat(user, "You failed to salvage anything valuable from [src].") - else + else to_chat(user, "You need more welding fuel to complete this task.") - return - if(istype(W, /obj/item/weapon/wirecutters)) - if(salvage_num <= 0) + return + if(istype(W, /obj/item/weapon/wirecutters)) + if(salvage_num <= 0) to_chat(user, "You don't see anything that can be cut with [W].") - return - else if(!isemptylist(wirecutters_salvage)) - var/type = prob(70)?pick(wirecutters_salvage):null - if(type) - var/N = new type(get_turf(user)) - user.visible_message("[user] cuts [N] from [src].", "You cut [N] from [src].") - salvage_num-- - else + return + else if(!isemptylist(wirecutters_salvage)) + var/type = prob(70)?pick(wirecutters_salvage):null + if(type) + var/N = new type(get_turf(user)) + user.visible_message("[user] cuts [N] from [src].", "You cut [N] from [src].") + salvage_num-- + else to_chat(user, "You failed to salvage anything valuable from [src].") - if(istype(W, /obj/item/weapon/crowbar)) - if(!isemptylist(crowbar_salvage)) - var/obj/S = pick(crowbar_salvage) - if(S) - S.loc = get_turf(user) - crowbar_salvage -= S - user.visible_message("[user] pries [S] from [src].", "You pry [S] from [src].") - return - else + if(istype(W, /obj/item/weapon/crowbar)) + if(!isemptylist(crowbar_salvage)) + var/obj/S = pick(crowbar_salvage) + if(S) + S.loc = get_turf(user) + crowbar_salvage -= S + user.visible_message("[user] pries [S] from [src].", "You pry [S] from [src].") + return + else to_chat(user, "You don't see anything that can be pried with [W].") - else - ..() - return - - -/obj/effect/decal/mecha_wreckage/gygax - name = "Gygax wreckage" - icon_state = "gygax-broken" - - New() - ..() - var/list/parts = list(/obj/item/mecha_parts/part/gygax_torso, - /obj/item/mecha_parts/part/gygax_head, - /obj/item/mecha_parts/part/gygax_left_arm, - /obj/item/mecha_parts/part/gygax_right_arm, - /obj/item/mecha_parts/part/gygax_left_leg, - /obj/item/mecha_parts/part/gygax_right_leg) - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part - return - -/obj/effect/decal/mecha_wreckage/gygax/dark - name = "Dark Gygax wreckage" - icon_state = "darkgygax-broken" - -/obj/effect/decal/mecha_wreckage/marauder - name = "Marauder wreckage" - icon_state = "marauder-broken" - -/obj/effect/decal/mecha_wreckage/mauler - name = "Mauler Wreckage" - icon_state = "mauler-broken" - desc = "The syndicate won't be very happy about this..." - -/obj/effect/decal/mecha_wreckage/seraph - name = "Seraph wreckage" - icon_state = "seraph-broken" - -/obj/effect/decal/mecha_wreckage/ripley - name = "Ripley wreckage" - icon_state = "ripley-broken" - - New() - ..() - var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso, - /obj/item/mecha_parts/part/ripley_left_arm, - /obj/item/mecha_parts/part/ripley_right_arm, - /obj/item/mecha_parts/part/ripley_left_leg, - /obj/item/mecha_parts/part/ripley_right_leg) - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part - return - -/obj/effect/decal/mecha_wreckage/ripley/firefighter - name = "Firefighter wreckage" - icon_state = "firefighter-broken" - - New() - ..() - var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso, - /obj/item/mecha_parts/part/ripley_left_arm, - /obj/item/mecha_parts/part/ripley_right_arm, - /obj/item/mecha_parts/part/ripley_left_leg, - /obj/item/mecha_parts/part/ripley_right_leg, - /obj/item/clothing/suit/fire) - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part - return - -/obj/effect/decal/mecha_wreckage/ripley/deathripley - name = "Death-Ripley wreckage" - icon_state = "deathripley-broken" - -/obj/effect/decal/mecha_wreckage/honker - name = "Honker wreckage" - icon_state = "honker-broken" - - New() - ..() - var/list/parts = list( - /obj/item/mecha_parts/chassis/honker, - /obj/item/mecha_parts/part/honker_torso, - /obj/item/mecha_parts/part/honker_head, - /obj/item/mecha_parts/part/honker_left_arm, - /obj/item/mecha_parts/part/honker_right_arm, - /obj/item/mecha_parts/part/honker_left_leg, - /obj/item/mecha_parts/part/honker_right_leg) - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part - return - -/obj/effect/decal/mecha_wreckage/durand - name = "Durand wreckage" - icon_state = "durand-broken" - - New() - ..() - var/list/parts = list( - /obj/item/mecha_parts/part/durand_torso, - /obj/item/mecha_parts/part/durand_head, - /obj/item/mecha_parts/part/durand_left_arm, - /obj/item/mecha_parts/part/durand_right_arm, - /obj/item/mecha_parts/part/durand_left_leg, - /obj/item/mecha_parts/part/durand_right_leg) - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part - return - - -/obj/effect/decal/mecha_wreckage/durand/old - name = "Durand wreckage" - icon_state = "old_durand-broken" - -/obj/effect/decal/mecha_wreckage/phazon - name = "Phazon wreckage" - icon_state = "phazon-broken" - - -/obj/effect/decal/mecha_wreckage/odysseus - name = "Odysseus wreckage" - icon_state = "odysseus-broken" - - New() - ..() - var/list/parts = list( - /obj/item/mecha_parts/part/odysseus_torso, - /obj/item/mecha_parts/part/odysseus_head, - /obj/item/mecha_parts/part/odysseus_left_arm, - /obj/item/mecha_parts/part/odysseus_right_arm, - /obj/item/mecha_parts/part/odysseus_left_leg, - /obj/item/mecha_parts/part/odysseus_right_leg) - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part + else + ..() + return + + +/obj/effect/decal/mecha_wreckage/gygax + name = "Gygax wreckage" + icon_state = "gygax-broken" + + New() + ..() + var/list/parts = list(/obj/item/mecha_parts/part/gygax_torso, + /obj/item/mecha_parts/part/gygax_head, + /obj/item/mecha_parts/part/gygax_left_arm, + /obj/item/mecha_parts/part/gygax_right_arm, + /obj/item/mecha_parts/part/gygax_left_leg, + /obj/item/mecha_parts/part/gygax_right_leg) + for(var/i=0;i<2;i++) + if(!isemptylist(parts) && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part + return + +/obj/effect/decal/mecha_wreckage/gygax/dark + name = "Dark Gygax wreckage" + icon_state = "darkgygax-broken" + +/obj/effect/decal/mecha_wreckage/marauder + name = "Marauder wreckage" + icon_state = "marauder-broken" + +/obj/effect/decal/mecha_wreckage/mauler + name = "Mauler Wreckage" + icon_state = "mauler-broken" + desc = "The syndicate won't be very happy about this..." + +/obj/effect/decal/mecha_wreckage/seraph + name = "Seraph wreckage" + icon_state = "seraph-broken" + +/obj/effect/decal/mecha_wreckage/ripley + name = "Ripley wreckage" + icon_state = "ripley-broken" + + New() + ..() + var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso, + /obj/item/mecha_parts/part/ripley_left_arm, + /obj/item/mecha_parts/part/ripley_right_arm, + /obj/item/mecha_parts/part/ripley_left_leg, + /obj/item/mecha_parts/part/ripley_right_leg) + for(var/i=0;i<2;i++) + if(!isemptylist(parts) && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part + return + +/obj/effect/decal/mecha_wreckage/ripley/firefighter + name = "Firefighter wreckage" + icon_state = "firefighter-broken" + + New() + ..() + var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso, + /obj/item/mecha_parts/part/ripley_left_arm, + /obj/item/mecha_parts/part/ripley_right_arm, + /obj/item/mecha_parts/part/ripley_left_leg, + /obj/item/mecha_parts/part/ripley_right_leg, + /obj/item/clothing/suit/fire) + for(var/i=0;i<2;i++) + if(!isemptylist(parts) && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part + return + +/obj/effect/decal/mecha_wreckage/ripley/deathripley + name = "Death-Ripley wreckage" + icon_state = "deathripley-broken" + +/obj/effect/decal/mecha_wreckage/honker + name = "Honker wreckage" + icon_state = "honker-broken" + + New() + ..() + var/list/parts = list( + /obj/item/mecha_parts/chassis/honker, + /obj/item/mecha_parts/part/honker_torso, + /obj/item/mecha_parts/part/honker_head, + /obj/item/mecha_parts/part/honker_left_arm, + /obj/item/mecha_parts/part/honker_right_arm, + /obj/item/mecha_parts/part/honker_left_leg, + /obj/item/mecha_parts/part/honker_right_leg) + for(var/i=0;i<2;i++) + if(!isemptylist(parts) && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part + return + +/obj/effect/decal/mecha_wreckage/durand + name = "Durand wreckage" + icon_state = "durand-broken" + + New() + ..() + var/list/parts = list( + /obj/item/mecha_parts/part/durand_torso, + /obj/item/mecha_parts/part/durand_head, + /obj/item/mecha_parts/part/durand_left_arm, + /obj/item/mecha_parts/part/durand_right_arm, + /obj/item/mecha_parts/part/durand_left_leg, + /obj/item/mecha_parts/part/durand_right_leg) + for(var/i=0;i<2;i++) + if(!isemptylist(parts) && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part + return + + +/obj/effect/decal/mecha_wreckage/durand/old + name = "Durand wreckage" + icon_state = "old_durand-broken" + +/obj/effect/decal/mecha_wreckage/phazon + name = "Phazon wreckage" + icon_state = "phazon-broken" + + +/obj/effect/decal/mecha_wreckage/odysseus + name = "Odysseus wreckage" + icon_state = "odysseus-broken" + + New() + ..() + var/list/parts = list( + /obj/item/mecha_parts/part/odysseus_torso, + /obj/item/mecha_parts/part/odysseus_head, + /obj/item/mecha_parts/part/odysseus_left_arm, + /obj/item/mecha_parts/part/odysseus_right_arm, + /obj/item/mecha_parts/part/odysseus_left_leg, + /obj/item/mecha_parts/part/odysseus_right_leg) + for(var/i=0;i<2;i++) + if(!isemptylist(parts) && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part return \ No newline at end of file diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm index e70f1a54ee7..4e74b7a24e8 100644 --- a/code/game/mecha/medical/medical.dm +++ b/code/game/mecha/medical/medical.dm @@ -1,22 +1,22 @@ -/obj/mecha/medical/New() - ..() - tracking = new /obj/item/mecha_parts/mecha_tracking(src) - return - - -/obj/mecha/medical/mechturn(direction) - dir = direction - playsound(src,'sound/mecha/mechmove01.ogg',40,1) - return 1 - -/obj/mecha/medical/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src,'sound/mecha/mechstep.ogg',25,1) - return result - -/obj/mecha/medical/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src,'sound/mecha/mechstep.ogg',25,1) +/obj/mecha/medical/New() + ..() + tracking = new /obj/item/mecha_parts/mecha_tracking(src) + return + + +/obj/mecha/medical/mechturn(direction) + dir = direction + playsound(src,'sound/mecha/mechmove01.ogg',40,1) + return 1 + +/obj/mecha/medical/mechstep(direction) + var/result = step(src,direction) + if(result) + playsound(src,'sound/mecha/mechstep.ogg',25,1) + return result + +/obj/mecha/medical/mechsteprand() + var/result = step_rand(src) + if(result) + playsound(src,'sound/mecha/mechstep.ogg',25,1) return result \ No newline at end of file diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index f9cff86ab6c..03565a69942 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -1,111 +1,111 @@ -/obj/mecha/medical/odysseus - desc = "These exosuits are developed and produced by Vey-Med. (© All rights reserved)." - name = "Odysseus" - icon_state = "odysseus" - initial_icon = "odysseus" - step_in = 2 - max_temperature = 15000 - health = 120 - wreckage = /obj/effect/decal/mecha_wreckage/odysseus - internal_damage_threshold = 35 - deflect_chance = 15 - step_energy_drain = 6 - var/obj/item/clothing/glasses/hud/health/mech/hud - -/obj/mecha/medical/odysseus/New() - ..() - hud = new /obj/item/clothing/glasses/hud/health/mech(src) - mech_parts += /obj/item/clothing/glasses/hud/health/mech - return - -/obj/mecha/medical/odysseus/moved_inside(var/mob/living/carbon/human/H as mob) - if(..()) - if(H.glasses) - occupant_message("[H.glasses] prevent you from using [src] [hud]") - else - H.glasses = hud - return 1 - else - return 0 - -/obj/mecha/medical/odysseus/go_out() - if(ishuman(occupant)) - var/mob/living/carbon/human/H = occupant - if(H.glasses == hud) - H.glasses = null - ..() - return -/* - verb/set_perspective() - set name = "Set client perspective." - set category = "Exosuit Interface" - set src = usr.loc - var/perspective = input("Select a perspective type.", - "Client perspective", - occupant.client.perspective) in list(MOB_PERSPECTIVE,EYE_PERSPECTIVE) +/obj/mecha/medical/odysseus + desc = "These exosuits are developed and produced by Vey-Med. (© All rights reserved)." + name = "Odysseus" + icon_state = "odysseus" + initial_icon = "odysseus" + step_in = 2 + max_temperature = 15000 + health = 120 + wreckage = /obj/effect/decal/mecha_wreckage/odysseus + internal_damage_threshold = 35 + deflect_chance = 15 + step_energy_drain = 6 + var/obj/item/clothing/glasses/hud/health/mech/hud + +/obj/mecha/medical/odysseus/New() + ..() + hud = new /obj/item/clothing/glasses/hud/health/mech(src) + mech_parts += /obj/item/clothing/glasses/hud/health/mech + return + +/obj/mecha/medical/odysseus/moved_inside(var/mob/living/carbon/human/H as mob) + if(..()) + if(H.glasses) + occupant_message("[H.glasses] prevent you from using [src] [hud]") + else + H.glasses = hud + return 1 + else + return 0 + +/obj/mecha/medical/odysseus/go_out() + if(ishuman(occupant)) + var/mob/living/carbon/human/H = occupant + if(H.glasses == hud) + H.glasses = null + ..() + return +/* + verb/set_perspective() + set name = "Set client perspective." + set category = "Exosuit Interface" + set src = usr.loc + var/perspective = input("Select a perspective type.", + "Client perspective", + occupant.client.perspective) in list(MOB_PERSPECTIVE,EYE_PERSPECTIVE) to_chat(world, "[perspective]") - occupant.client.perspective = perspective - return - - verb/toggle_eye() - set name = "Toggle eye." - set category = "Exosuit Interface" - set src = usr.loc - if(occupant.client.eye == occupant) - occupant.client.eye = src - else - occupant.client.eye = occupant + occupant.client.perspective = perspective + return + + verb/toggle_eye() + set name = "Toggle eye." + set category = "Exosuit Interface" + set src = usr.loc + if(occupant.client.eye == occupant) + occupant.client.eye = src + else + occupant.client.eye = occupant to_chat(world, "[occupant.client.eye]") - return -*/ - -//TODO - Check documentation for client.eye and client.perspective... -/obj/item/clothing/glasses/hud/health/mech - name = "Integrated Medical Hud" - - -/obj/item/clothing/glasses/hud/health/mech/process_hud(var/mob/M) //Is this even necessary? Doesn't the parent already do this? -/* + return +*/ + +//TODO - Check documentation for client.eye and client.perspective... +/obj/item/clothing/glasses/hud/health/mech + name = "Integrated Medical Hud" + + +/obj/item/clothing/glasses/hud/health/mech/process_hud(var/mob/M) //Is this even necessary? Doesn't the parent already do this? +/* to_chat(world, "view(M)") - for(var/mob/mob in view(M)) + for(var/mob/mob in view(M)) to_chat(world, "[mob]") to_chat(world, "view(M.client)") - for(var/mob/mob in view(M.client)) + for(var/mob/mob in view(M.client)) to_chat(world, "[mob]") to_chat(world, "view(M.loc)") - for(var/mob/mob in view(M.loc)) + for(var/mob/mob in view(M.loc)) to_chat(world, "[mob]") -*/ - - if(!M || M.stat || !(M in view(M))) return - if(!M.client) return - var/client/C = M.client - var/image/holder - for(var/mob/living/carbon/human/patient in view(M.loc)) - if(M.see_invisible < patient.invisibility) - continue - var/foundVirus = 0 - for(var/datum/disease/D in patient.viruses) - if(!D.hidden[SCANNER]) - foundVirus++ - //if(patient.virus2) - // foundVirus++ - - holder = patient.hud_list[HEALTH_HUD] - if(patient.stat == 2) - holder.icon_state = "hudhealth-100" - C.images += holder - else - holder.icon_state = "hud[RoundHealth(patient.health)]" - C.images += holder - - holder = patient.hud_list[STATUS_HUD] - if(patient.stat == 2) - holder.icon_state = "huddead" - else if(patient.status_flags & XENO_HOST) - holder.icon_state = "hudxeno" - else if(foundVirus) - holder.icon_state = "hudill" - else - holder.icon_state = "hudhealthy" - C.images += holder +*/ + + if(!M || M.stat || !(M in view(M))) return + if(!M.client) return + var/client/C = M.client + var/image/holder + for(var/mob/living/carbon/human/patient in view(M.loc)) + if(M.see_invisible < patient.invisibility) + continue + var/foundVirus = 0 + for(var/datum/disease/D in patient.viruses) + if(!D.hidden[SCANNER]) + foundVirus++ + //if(patient.virus2) + // foundVirus++ + + holder = patient.hud_list[HEALTH_HUD] + if(patient.stat == 2) + holder.icon_state = "hudhealth-100" + C.images += holder + else + holder.icon_state = "hud[RoundHealth(patient.health)]" + C.images += holder + + holder = patient.hud_list[STATUS_HUD] + if(patient.stat == 2) + holder.icon_state = "huddead" + else if(patient.status_flags & XENO_HOST) + holder.icon_state = "hudxeno" + else if(foundVirus) + holder.icon_state = "hudill" + else + holder.icon_state = "hudhealthy" + C.images += holder diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 37d4771ec25..77fa8d14b5e 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -1,124 +1,124 @@ -/obj/mecha/working/ripley - desc = "Autonomous Power Loader Unit. The workhorse of the exosuit world." - name = "APLU \"Ripley\"" - icon_state = "ripley" - step_in = 4 - max_temperature = 20000 - health = 200 - wreckage = /obj/effect/decal/mecha_wreckage/ripley - var/list/cargo = new - var/cargo_capacity = 15 - var/obj/structure/ore_box/ore_box //to save on locate() - var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/hydraulic_clamp - -/* -/obj/mecha/working/ripley/New() - ..() - return -*/ - -/obj/mecha/working/ripley/firefighter - desc = "Standard APLU chassis, refitted with additional thermal protection and cistern." - name = "APLU \"Firefighter\"" - icon_state = "firefighter" - max_temperature = 65000 - health = 250 - lights_power = 8 - damage_absorption = list("fire"=0.5,"bullet"=0.8,"bomb"=0.5) - wreckage = /obj/effect/decal/mecha_wreckage/ripley/firefighter - -/obj/mecha/working/ripley/deathripley - desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE" - name = "DEATH-RIPLEY" - icon_state = "deathripley" - step_in = 2 - opacity = 0 - lights_power = 60 - wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley - step_energy_drain = 0 - -/obj/mecha/working/ripley/deathripley/New() - ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp - ME.attach(src) - return - -/obj/mecha/working/ripley/mining - desc = "An old, dusty mining ripley." - name = "APLU \"Miner\"" - -/obj/mecha/working/ripley/mining/New() - ..() - //Attach drill - if(prob(25)) //Possible diamond drill... Feeling lucky? - var/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill - D.attach(src) - else - var/obj/item/mecha_parts/mecha_equipment/tool/drill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill - D.attach(src) - - //Attach hydraulic clamp - var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp - HC.attach(src) - src.hydraulic_clamp = HC - - //Deletes the beacon so it can't be found easily - for(var/obj/item/mecha_parts/mecha_tracking/B in src.contents) - qdel (B) - B = null - src.tracking = null - -/obj/mecha/working/ripley/Exit(atom/movable/O) - if(O in cargo) - return 0 - return ..() - -/obj/mecha/working/ripley/Topic(href, href_list) - ..() - if(href_list["drop_from_cargo"]) - var/obj/O = locate(href_list["drop_from_cargo"]) - if(O && O in src.cargo) - src.occupant_message("You unload [O].") - O.forceMove(get_turf(src)) - src.cargo -= O - if (ore_box == O) - ore_box = locate(/obj/structure/ore_box) in cargo //i'll fix this later - src.log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]") - return - - - -/obj/mecha/working/ripley/get_stats_part() - var/output = ..() - output += "Cargo Compartment Contents:
                      " - if(src.cargo.len) - for(var/obj/O in src.cargo) - output += "Unload : [O]
                      " - else - output += "Nothing" - output += "
                      " - return output - -/obj/mecha/working/ripley/empty_bad_contents() - for(var/obj/O in src) - if(O in cargo) //mom's spaghetti - continue - if(!is_type_in_list(O,mech_parts)) - O.loc = src.loc - return - -/obj/mecha/working/ripley/Destroy() - for(var/mob/M in src) - if(M==src.occupant) - continue - M.loc = get_turf(src) - M.loc.Entered(M) - step_rand(M) - for(var/atom/movable/A in src.cargo) - A.loc = get_turf(src) - var/turf/T = get_turf(A) - if(T) - T.Entered(A) - step_rand(A) - ..() - return +/obj/mecha/working/ripley + desc = "Autonomous Power Loader Unit. The workhorse of the exosuit world." + name = "APLU \"Ripley\"" + icon_state = "ripley" + step_in = 4 + max_temperature = 20000 + health = 200 + wreckage = /obj/effect/decal/mecha_wreckage/ripley + var/list/cargo = new + var/cargo_capacity = 15 + var/obj/structure/ore_box/ore_box //to save on locate() + var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/hydraulic_clamp + +/* +/obj/mecha/working/ripley/New() + ..() + return +*/ + +/obj/mecha/working/ripley/firefighter + desc = "Standard APLU chassis, refitted with additional thermal protection and cistern." + name = "APLU \"Firefighter\"" + icon_state = "firefighter" + max_temperature = 65000 + health = 250 + lights_power = 8 + damage_absorption = list("fire"=0.5,"bullet"=0.8,"bomb"=0.5) + wreckage = /obj/effect/decal/mecha_wreckage/ripley/firefighter + +/obj/mecha/working/ripley/deathripley + desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE" + name = "DEATH-RIPLEY" + icon_state = "deathripley" + step_in = 2 + opacity = 0 + lights_power = 60 + wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley + step_energy_drain = 0 + +/obj/mecha/working/ripley/deathripley/New() + ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp + ME.attach(src) + return + +/obj/mecha/working/ripley/mining + desc = "An old, dusty mining ripley." + name = "APLU \"Miner\"" + +/obj/mecha/working/ripley/mining/New() + ..() + //Attach drill + if(prob(25)) //Possible diamond drill... Feeling lucky? + var/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill + D.attach(src) + else + var/obj/item/mecha_parts/mecha_equipment/tool/drill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill + D.attach(src) + + //Attach hydraulic clamp + var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp + HC.attach(src) + src.hydraulic_clamp = HC + + //Deletes the beacon so it can't be found easily + for(var/obj/item/mecha_parts/mecha_tracking/B in src.contents) + qdel (B) + B = null + src.tracking = null + +/obj/mecha/working/ripley/Exit(atom/movable/O) + if(O in cargo) + return 0 + return ..() + +/obj/mecha/working/ripley/Topic(href, href_list) + ..() + if(href_list["drop_from_cargo"]) + var/obj/O = locate(href_list["drop_from_cargo"]) + if(O && O in src.cargo) + src.occupant_message("You unload [O].") + O.forceMove(get_turf(src)) + src.cargo -= O + if (ore_box == O) + ore_box = locate(/obj/structure/ore_box) in cargo //i'll fix this later + src.log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]") + return + + + +/obj/mecha/working/ripley/get_stats_part() + var/output = ..() + output += "Cargo Compartment Contents:
                      " + if(src.cargo.len) + for(var/obj/O in src.cargo) + output += "Unload : [O]
                      " + else + output += "Nothing" + output += "
                      " + return output + +/obj/mecha/working/ripley/empty_bad_contents() + for(var/obj/O in src) + if(O in cargo) //mom's spaghetti + continue + if(!is_type_in_list(O,mech_parts)) + O.loc = src.loc + return + +/obj/mecha/working/ripley/Destroy() + for(var/mob/M in src) + if(M==src.occupant) + continue + M.loc = get_turf(src) + M.loc.Entered(M) + step_rand(M) + for(var/atom/movable/A in src.cargo) + A.loc = get_turf(src) + var/turf/T = get_turf(A) + if(T) + T.Entered(A) + step_rand(A) + ..() + return diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm index 3444f062e1c..c16320193fa 100644 --- a/code/game/mecha/working/working.dm +++ b/code/game/mecha/working/working.dm @@ -1,32 +1,32 @@ -/obj/mecha/working - internal_damage_threshold = 60 - -/obj/mecha/working/New() - ..() - tracking = new /obj/item/mecha_parts/mecha_tracking(src) - return - -/* -/obj/mecha/working/melee_action(atom/target as obj|mob|turf) - if(internal_damage&MECHA_INT_CONTROL_LOST) - target = pick(oview(1,src)) - if(selected_tool) - selected_tool.action(target) - return -*/ - -/obj/mecha/working/range_action(atom/target as obj|mob|turf) - return - -/* -/obj/mecha/working/get_stats_part() - var/output = ..() - output += "[src.name] Tools:
                      " - if(equipment.len) - for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) - output += "[selected==MT?"":""][MT.get_equip_info()][selected==MT?"":""]
                      " - else - output += "None" - output += "
                      " - return output +/obj/mecha/working + internal_damage_threshold = 60 + +/obj/mecha/working/New() + ..() + tracking = new /obj/item/mecha_parts/mecha_tracking(src) + return + +/* +/obj/mecha/working/melee_action(atom/target as obj|mob|turf) + if(internal_damage&MECHA_INT_CONTROL_LOST) + target = pick(oview(1,src)) + if(selected_tool) + selected_tool.action(target) + return +*/ + +/obj/mecha/working/range_action(atom/target as obj|mob|turf) + return + +/* +/obj/mecha/working/get_stats_part() + var/output = ..() + output += "[src.name] Tools:
                      " + if(equipment.len) + for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) + output += "[selected==MT?"":""][MT.get_equip_info()][selected==MT?"":""]
                      " + else + output += "None" + output += "
                      " + return output */ \ No newline at end of file diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index ec99fc62b00..a663b7ec55b 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -1,513 +1,513 @@ -/* Alien Effects! - * Contains: - * effect/alien - * Resin - * Weeds - * Acid - * Egg - */ - -/* - * effect/alien - */ -/obj/effect/alien - name = "alien thing" - desc = "theres something alien about this" - icon = 'icons/mob/alien.dmi' -// unacidable = 1 //Aliens won't ment their own. - w_type=NOT_RECYCLABLE - -/* - * Resin - */ -/obj/effect/alien/resin - name = "resin" - desc = "Looks like some kind of slimy growth." - icon_state = "resin" - - density = 1 - opacity = 1 - anchored = 1 - var/health = 200 - var/turf/linked_turf - - wall - name = "resin wall" - desc = "Purple slime solidified into a wall." - icon_state = "resinwall" //same as resin, but consistency ho! - - membrane - name = "resin membrane" - desc = "Purple slime just thin enough to let light pass through." - icon_state = "resinmembrane" - opacity = 0 - health = 120 - -/obj/effect/alien/resin/New() - ..() - linked_turf = get_turf(src) - linked_turf.thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT - -/obj/effect/alien/resin/Destroy() - if(linked_turf) - linked_turf.thermal_conductivity = initial(linked_turf.thermal_conductivity) - ..() - - -/obj/effect/alien/resin/proc/healthcheck() - if(health <=0) - density = 0 - qdel(src) - return - -/obj/effect/alien/resin/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - healthcheck() - return - -/obj/effect/alien/resin/ex_act(severity) - switch(severity) - if(1.0) - health-=50 - if(2.0) - health-=50 - if(3.0) - if (prob(50)) - health-=50 - else - health-=25 - healthcheck() - return - -/obj/effect/alien/resin/blob_act() - health-=50 - healthcheck() - return - -/obj/effect/alien/resin/hitby(AM as mob|obj) - ..() - for(var/mob/O in viewers(src, null)) - O.show_message("[src] was hit by [AM].", 1) - var/tforce = 0 - if(ismob(AM)) - tforce = 10 - else - tforce = AM:throwforce - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health = max(0, health - tforce) - healthcheck() - ..() - return - -/obj/effect/alien/resin/attack_hand() - usr.delayNextAttack(10) - if (M_HULK in usr.mutations) +/* Alien Effects! + * Contains: + * effect/alien + * Resin + * Weeds + * Acid + * Egg + */ + +/* + * effect/alien + */ +/obj/effect/alien + name = "alien thing" + desc = "theres something alien about this" + icon = 'icons/mob/alien.dmi' +// unacidable = 1 //Aliens won't ment their own. + w_type=NOT_RECYCLABLE + +/* + * Resin + */ +/obj/effect/alien/resin + name = "resin" + desc = "Looks like some kind of slimy growth." + icon_state = "resin" + + density = 1 + opacity = 1 + anchored = 1 + var/health = 200 + var/turf/linked_turf + + wall + name = "resin wall" + desc = "Purple slime solidified into a wall." + icon_state = "resinwall" //same as resin, but consistency ho! + + membrane + name = "resin membrane" + desc = "Purple slime just thin enough to let light pass through." + icon_state = "resinmembrane" + opacity = 0 + health = 120 + +/obj/effect/alien/resin/New() + ..() + linked_turf = get_turf(src) + linked_turf.thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT + +/obj/effect/alien/resin/Destroy() + if(linked_turf) + linked_turf.thermal_conductivity = initial(linked_turf.thermal_conductivity) + ..() + + +/obj/effect/alien/resin/proc/healthcheck() + if(health <=0) + density = 0 + qdel(src) + return + +/obj/effect/alien/resin/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + healthcheck() + return + +/obj/effect/alien/resin/ex_act(severity) + switch(severity) + if(1.0) + health-=50 + if(2.0) + health-=50 + if(3.0) + if (prob(50)) + health-=50 + else + health-=25 + healthcheck() + return + +/obj/effect/alien/resin/blob_act() + health-=50 + healthcheck() + return + +/obj/effect/alien/resin/hitby(AM as mob|obj) + ..() + for(var/mob/O in viewers(src, null)) + O.show_message("[src] was hit by [AM].", 1) + var/tforce = 0 + if(ismob(AM)) + tforce = 10 + else + tforce = AM:throwforce + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + health = max(0, health - tforce) + healthcheck() + ..() + return + +/obj/effect/alien/resin/attack_hand() + usr.delayNextAttack(10) + if (M_HULK in usr.mutations) to_chat(usr, "You easily destroy the [name].") - for(var/mob/O in oviewers(src)) - O.show_message("[usr] destroys the [name]!", 1) - health = 0 - else + for(var/mob/O in oviewers(src)) + O.show_message("[usr] destroys the [name]!", 1) + health = 0 + else to_chat(usr, "You claw at the [name].") - for(var/mob/O in oviewers(src)) - O.show_message("[usr] claws at the [name]!", 1) - health -= rand(5,10) - healthcheck() - return - -/obj/effect/alien/resin/attack_paw() - return attack_hand() - -/obj/effect/alien/resin/attack_alien() - if (islarva(usr))//Safety check for larva. /N - return + for(var/mob/O in oviewers(src)) + O.show_message("[usr] claws at the [name]!", 1) + health -= rand(5,10) + healthcheck() + return + +/obj/effect/alien/resin/attack_paw() + return attack_hand() + +/obj/effect/alien/resin/attack_alien() + if (islarva(usr))//Safety check for larva. /N + return to_chat(usr, "You claw at the [name].") - for(var/mob/O in oviewers(src)) - O.show_message("[usr] claws at the resin!", 1) - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health -= rand(40, 60) - if(health <= 0) + for(var/mob/O in oviewers(src)) + O.show_message("[usr] claws at the resin!", 1) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + health -= rand(40, 60) + if(health <= 0) to_chat(usr, "You slice the [name] to pieces.") - for(var/mob/O in oviewers(src)) - O.show_message("[usr] slices the [name] apart!", 1) - healthcheck() - return - -/obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob) - /*if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) - var/obj/item/weapon/grab/G = W - if(isalien(user)&&(ishuman(G.affecting)||ismonkey(G.affecting))) - //Only aliens can stick humans and monkeys into resin walls. Also, the wall must not have a person inside already. - if(!affecting) - if(G.state<2) + for(var/mob/O in oviewers(src)) + O.show_message("[usr] slices the [name] apart!", 1) + healthcheck() + return + +/obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob) + /*if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) + var/obj/item/weapon/grab/G = W + if(isalien(user)&&(ishuman(G.affecting)||ismonkey(G.affecting))) + //Only aliens can stick humans and monkeys into resin walls. Also, the wall must not have a person inside already. + if(!affecting) + if(G.state<2) to_chat(user, "You need a better grip to do that!") - return - G.affecting.loc = src - G.affecting.paralysis = 10 - for(var/mob/O in viewers(world.view, src)) - if (O.client) + return + G.affecting.loc = src + G.affecting.paralysis = 10 + for(var/mob/O in viewers(world.view, src)) + if (O.client) to_chat(O, text("[] places [] in the resin wall!", G.assailant, G.affecting)) - affecting=G.affecting - del(W) - spawn(0) - process() - else + affecting=G.affecting + del(W) + spawn(0) + process() + else to_chat(user, "This wall is already occupied.") - return */ - user.delayNextAttack(10) - var/aforce = W.force - health = max(0, health - aforce) - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - healthcheck() - ..() - return - -/obj/effect/alien/resin/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group) return 0 - if(istype(mover) && mover.checkpass(PASSGLASS)) - return !opacity - return !density - - -/* - * Weeds - */ -#define NODERANGE 3 - -/obj/effect/alien/weeds - name = "weeds" - desc = "Weird purple weeds." - icon_state = "weeds" - - anchored = 1 - density = 0 - layer = 2 - var/health = 15 - var/obj/effect/alien/weeds/node/linked_node = null - -/obj/effect/alien/weeds/Destroy() - if(linked_node) - linked_node.connected_weeds.Remove(src) - linked_node = null - ..() - -/obj/effect/alien/weeds/node - icon_state = "weednode" - name = "purple sac" - desc = "Weird purple octopus-like thing." - layer = 3 - luminosity = NODERANGE - var/node_range = NODERANGE - var/list/obj/effect/alien/weeds/connected_weeds - -/obj/effect/alien/weeds/node/Destroy() - for(var/obj/effect/alien/weeds/W in connected_weeds) - W.linked_node = null - ..() - -/obj/effect/alien/weeds/node/New() - connected_weeds = new() - ..(src.loc, src) - -/obj/effect/alien/weeds/New(pos, var/obj/effect/alien/weeds/node/N) - ..() - - if(istype(loc, /turf/space)) - qdel(src) - return - - linked_node = N - if(linked_node) - linked_node.connected_weeds.Add(src) - - if(icon_state == "weeds")icon_state = pick("weeds", "weeds1", "weeds2") - spawn(rand(150, 200)) - if(src) - Life() - return - -/obj/effect/alien/weeds/proc/Life() - if(timestopped) return 0 //under effects of time magick - - //set background = 1 - var/turf/U = get_turf(src) -/* - if (locate(/obj/movable, U)) - U = locate(/obj/movable, U) - if(U.density == 1) - del(src) - return - -Alien plants should do something if theres a lot of poison - if(U.poison> 200000) - health -= round(U.poison/200000) - update() - return -*/ - if (istype(U, /turf/space)) - qdel(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) - - if (!istype(T) || T.density || locate(/obj/effect/alien/weeds) in T || istype(T.loc, /area/arrival) || istype(T, /turf/space)) - continue - - // if (locate(/obj/movable, T)) // don't propogate into movables - // continue - - for(var/obj/O in T) - if(O.density) - continue direction_loop - - new /obj/effect/alien/weeds(T, linked_node) - - -/obj/effect/alien/weeds/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - if (prob(50)) - qdel(src) - if(3.0) - if (prob(5)) - qdel(src) - return - -/obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user) - user.delayNextAttack(10) - if(W.attack_verb && W.attack_verb.len) - visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") - else - visible_message("\The [src] have been attacked with \the [W][(user ? " by [user]." : ".")]") - - var/damage = W.force / 4.0 - - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - - if(WT.remove_fuel(0, user)) - damage = 15 - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - - health -= damage - healthcheck() - -/obj/effect/alien/weeds/proc/healthcheck() - if(health <= 0) - qdel(src) - - -/obj/effect/alien/weeds/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - health -= 5 - healthcheck() - -/*/obj/effect/alien/weeds/burn(fi_amount) - if (fi_amount > 18000) - spawn( 0 ) - del(src) - return - return 0 - return 1 -*/ - -#undef NODERANGE - - -/* - * Acid - */ -/obj/effect/alien/acid - name = "acid" - desc = "Burbling corrossive stuff. I wouldn't want to touch it." - icon_state = "acid" - - density = 0 - opacity = 0 - anchored = 1 - - var/atom/target - var/ticks = 0 - var/target_strength = 0 - -/obj/effect/alien/acid/New(loc, target) - ..(loc) - src.target = target - - if(isturf(target)) // Turf take twice as long to take down. - target_strength = 8 - else - target_strength = 4 - tick() - -/obj/effect/alien/acid/proc/tick() - if(!target) - qdel(src) - - ticks += 1 - - if(ticks >= target_strength) - - for(var/mob/O in hearers(src, null)) - O.show_message("[src.target] collapses under its own weight into a puddle of goop and undigested debris!", 1) - - if(istype(target, /turf/simulated/wall)) // I hate turf code. - var/turf/simulated/wall/W = target - W.dismantle_wall(1) - else - qdel(target) - qdel(src) - return - - switch(target_strength - ticks) - if(6) - visible_message("[src.target] is holding up against the acid!") - if(4) - visible_message("[src.target]\s structure is being melted by the acid!") - if(2) - visible_message("[src.target] is struggling to withstand the acid!") - if(0 to 1) - visible_message("[src.target] begins to crumble under the acid!") - spawn(rand(150, 200)) tick() - -/* - * Egg - */ -/var/const //for the status var - BURST = 0 - BURSTING = 1 - GROWING = 2 - GROWN = 3 - - MIN_GROWTH_TIME = 1800 //time it takes to grow a hugger - MAX_GROWTH_TIME = 3000 - -/obj/effect/alien/egg - desc = "It looks like a weird egg" - name = "egg" - icon_state = "egg_growing" - density = 0 - anchored = 1 - - var/health = 100 - var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive - - flags = PROXMOVE - - New() - if(aliens_allowed) - ..() - spawn(rand(MIN_GROWTH_TIME,MAX_GROWTH_TIME)) - Grow() - else - qdel(src) - - attack_paw(user as mob) - if(isalien(user)) - switch(status) - if(BURST) + return */ + user.delayNextAttack(10) + var/aforce = W.force + health = max(0, health - aforce) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + healthcheck() + ..() + return + +/obj/effect/alien/resin/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group) return 0 + if(istype(mover) && mover.checkpass(PASSGLASS)) + return !opacity + return !density + + +/* + * Weeds + */ +#define NODERANGE 3 + +/obj/effect/alien/weeds + name = "weeds" + desc = "Weird purple weeds." + icon_state = "weeds" + + anchored = 1 + density = 0 + layer = 2 + var/health = 15 + var/obj/effect/alien/weeds/node/linked_node = null + +/obj/effect/alien/weeds/Destroy() + if(linked_node) + linked_node.connected_weeds.Remove(src) + linked_node = null + ..() + +/obj/effect/alien/weeds/node + icon_state = "weednode" + name = "purple sac" + desc = "Weird purple octopus-like thing." + layer = 3 + luminosity = NODERANGE + var/node_range = NODERANGE + var/list/obj/effect/alien/weeds/connected_weeds + +/obj/effect/alien/weeds/node/Destroy() + for(var/obj/effect/alien/weeds/W in connected_weeds) + W.linked_node = null + ..() + +/obj/effect/alien/weeds/node/New() + connected_weeds = new() + ..(src.loc, src) + +/obj/effect/alien/weeds/New(pos, var/obj/effect/alien/weeds/node/N) + ..() + + if(istype(loc, /turf/space)) + qdel(src) + return + + linked_node = N + if(linked_node) + linked_node.connected_weeds.Add(src) + + if(icon_state == "weeds")icon_state = pick("weeds", "weeds1", "weeds2") + spawn(rand(150, 200)) + if(src) + Life() + return + +/obj/effect/alien/weeds/proc/Life() + if(timestopped) return 0 //under effects of time magick + + //set background = 1 + var/turf/U = get_turf(src) +/* + if (locate(/obj/movable, U)) + U = locate(/obj/movable, U) + if(U.density == 1) + del(src) + return + +Alien plants should do something if theres a lot of poison + if(U.poison> 200000) + health -= round(U.poison/200000) + update() + return +*/ + if (istype(U, /turf/space)) + qdel(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) + + if (!istype(T) || T.density || locate(/obj/effect/alien/weeds) in T || istype(T.loc, /area/arrival) || istype(T, /turf/space)) + continue + + // if (locate(/obj/movable, T)) // don't propogate into movables + // continue + + for(var/obj/O in T) + if(O.density) + continue direction_loop + + new /obj/effect/alien/weeds(T, linked_node) + + +/obj/effect/alien/weeds/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + if (prob(50)) + qdel(src) + if(3.0) + if (prob(5)) + qdel(src) + return + +/obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user) + user.delayNextAttack(10) + if(W.attack_verb && W.attack_verb.len) + visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") + else + visible_message("\The [src] have been attacked with \the [W][(user ? " by [user]." : ".")]") + + var/damage = W.force / 4.0 + + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + + if(WT.remove_fuel(0, user)) + damage = 15 + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + + health -= damage + healthcheck() + +/obj/effect/alien/weeds/proc/healthcheck() + if(health <= 0) + qdel(src) + + +/obj/effect/alien/weeds/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + health -= 5 + healthcheck() + +/*/obj/effect/alien/weeds/burn(fi_amount) + if (fi_amount > 18000) + spawn( 0 ) + del(src) + return + return 0 + return 1 +*/ + +#undef NODERANGE + + +/* + * Acid + */ +/obj/effect/alien/acid + name = "acid" + desc = "Burbling corrossive stuff. I wouldn't want to touch it." + icon_state = "acid" + + density = 0 + opacity = 0 + anchored = 1 + + var/atom/target + var/ticks = 0 + var/target_strength = 0 + +/obj/effect/alien/acid/New(loc, target) + ..(loc) + src.target = target + + if(isturf(target)) // Turf take twice as long to take down. + target_strength = 8 + else + target_strength = 4 + tick() + +/obj/effect/alien/acid/proc/tick() + if(!target) + qdel(src) + + ticks += 1 + + if(ticks >= target_strength) + + for(var/mob/O in hearers(src, null)) + O.show_message("[src.target] collapses under its own weight into a puddle of goop and undigested debris!", 1) + + if(istype(target, /turf/simulated/wall)) // I hate turf code. + var/turf/simulated/wall/W = target + W.dismantle_wall(1) + else + qdel(target) + qdel(src) + return + + switch(target_strength - ticks) + if(6) + visible_message("[src.target] is holding up against the acid!") + if(4) + visible_message("[src.target]\s structure is being melted by the acid!") + if(2) + visible_message("[src.target] is struggling to withstand the acid!") + if(0 to 1) + visible_message("[src.target] begins to crumble under the acid!") + spawn(rand(150, 200)) tick() + +/* + * Egg + */ +/var/const //for the status var + BURST = 0 + BURSTING = 1 + GROWING = 2 + GROWN = 3 + + MIN_GROWTH_TIME = 1800 //time it takes to grow a hugger + MAX_GROWTH_TIME = 3000 + +/obj/effect/alien/egg + desc = "It looks like a weird egg" + name = "egg" + icon_state = "egg_growing" + density = 0 + anchored = 1 + + var/health = 100 + var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive + + flags = PROXMOVE + + New() + if(aliens_allowed) + ..() + spawn(rand(MIN_GROWTH_TIME,MAX_GROWTH_TIME)) + Grow() + else + qdel(src) + + attack_paw(user as mob) + if(isalien(user)) + switch(status) + if(BURST) to_chat(user, "You clear the hatched egg.") - qdel(src) - return - if(GROWING) + qdel(src) + return + if(GROWING) to_chat(user, "The child is not developed yet.") - return - if(GROWN) + return + if(GROWN) to_chat(user, "You retrieve the child.") - Burst(0) - return - else - return attack_hand(user) - - attack_hand(user as mob) + Burst(0) + return + else + return attack_hand(user) + + attack_hand(user as mob) to_chat(user, "It feels slimy.") - return - - proc/GetFacehugger() - return locate(/obj/item/clothing/mask/facehugger) in contents - - proc/Grow() - icon_state = "egg" - status = GROWN - new /obj/item/clothing/mask/facehugger(src) - return - - proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining - if(status == GROWN || status == GROWING) - var/obj/item/clothing/mask/facehugger/child = GetFacehugger() - icon_state = "egg_hatched" - flick("egg_opening", src) - status = BURSTING - spawn(15) - status = BURST - if(!child) - src.visible_message("The egg bursts apart revealing nothing") - status = "GROWN" - new /obj/effect/decal/cleanable/blood/xeno(src) - var/obj/effect/decal/cleanable/blood/xeno/O = getFromPool(/obj/effect/decal/cleanable/blood/xeno, src) - O.New(src) - child.loc = loc - if(kill && istype(child)) - child.Die() - else - for(var/mob/M in range(1,src)) - if(CanHug(M)) - child.Attach(M) - break - - -/obj/effect/alien/egg/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - healthcheck() - return - - -/obj/effect/alien/egg/attackby(var/obj/item/weapon/W, var/mob/user) - if(health <= 0) - return - user.delayNextAttack(10) - if(W.attack_verb && W.attack_verb.len) - src.visible_message("\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") - else - src.visible_message("\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]") - var/damage = W.force / 4.0 - - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - - if(WT.remove_fuel(0, user)) - damage = 15 - playsound(get_turf(src), 'sound/items/Welder.ogg', 100, 1) - - src.health -= damage - src.healthcheck() - - -/obj/effect/alien/egg/proc/healthcheck() - if(health <= 0) - Burst() - -/obj/effect/alien/egg/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 500) - health -= 5 - healthcheck() - -/obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj) - if(status == GROWN) - if(!CanHug(AM)) - return - - var/mob/living/carbon/C = AM - if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST) - return - - Burst(0) + return + + proc/GetFacehugger() + return locate(/obj/item/clothing/mask/facehugger) in contents + + proc/Grow() + icon_state = "egg" + status = GROWN + new /obj/item/clothing/mask/facehugger(src) + return + + proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining + if(status == GROWN || status == GROWING) + var/obj/item/clothing/mask/facehugger/child = GetFacehugger() + icon_state = "egg_hatched" + flick("egg_opening", src) + status = BURSTING + spawn(15) + status = BURST + if(!child) + src.visible_message("The egg bursts apart revealing nothing") + status = "GROWN" + new /obj/effect/decal/cleanable/blood/xeno(src) + var/obj/effect/decal/cleanable/blood/xeno/O = getFromPool(/obj/effect/decal/cleanable/blood/xeno, src) + O.New(src) + child.loc = loc + if(kill && istype(child)) + child.Die() + else + for(var/mob/M in range(1,src)) + if(CanHug(M)) + child.Attach(M) + break + + +/obj/effect/alien/egg/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + healthcheck() + return + + +/obj/effect/alien/egg/attackby(var/obj/item/weapon/W, var/mob/user) + if(health <= 0) + return + user.delayNextAttack(10) + if(W.attack_verb && W.attack_verb.len) + src.visible_message("\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") + else + src.visible_message("\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]") + var/damage = W.force / 4.0 + + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + + if(WT.remove_fuel(0, user)) + damage = 15 + playsound(get_turf(src), 'sound/items/Welder.ogg', 100, 1) + + src.health -= damage + src.healthcheck() + + +/obj/effect/alien/egg/proc/healthcheck() + if(health <= 0) + Burst() + +/obj/effect/alien/egg/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 500) + health -= 5 + healthcheck() + +/obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj) + if(status == GROWN) + if(!CanHug(AM)) + return + + var/mob/living/carbon/C = AM + if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST) + return + + Burst(0) diff --git a/code/game/objects/effects/biomass_rift.dm b/code/game/objects/effects/biomass_rift.dm index 247f485b570..1b262175460 100644 --- a/code/game/objects/effects/biomass_rift.dm +++ b/code/game/objects/effects/biomass_rift.dm @@ -1,126 +1,126 @@ -/* -/obj/effect/biomass - icon = 'icons/obj/biomass.dmi' - icon_state = "stage1" - opacity = 0 - density = 0 - anchored = 1 - layer = 20 //DEBUG - var/health = 10 - var/stage = 1 - var/obj/effect/rift/originalRift = null //the originating rift of that biomass - var/maxDistance = 15 //the maximum length of a thread - var/newSpreadDistance = 10 //the length of a thread at which new ones are created - var/curDistance = 1 //the current length of a thread - var/continueChance = 3 //weighed chance of continuing in the same direction. turning left or right has 1 weight both - var/spreadDelay = 1 //will change to something bigger later, but right now I want it to spread as fast as possible for testing - -/obj/effect/rift - icon = 'icons/obj/biomass.dmi' - icon_state = "rift" - var/list/obj/effect/biomass/linkedBiomass = list() //all the biomass patches that have spread from it - var/newicon = 1 //DEBUG - -/obj/effect/rift/New() - set background = 1 - - ..() - - for(var/turf/T in orange(1,src)) - if(!IsValidBiomassLoc(T)) - continue - var/obj/effect/biomass/starting = new /obj/effect/biomass(T) - starting.dir = get_dir(src,starting) - starting.originalRift = src - linkedBiomass += starting - spawn(1) //DEBUG - starting.icon_state = "[newicon]" - -/obj/effect/rift/Del() - for(var/obj/effect/biomass/biomass in linkedBiomass) - del(biomass) - ..() - -/obj/effect/biomass/New() - set background = 1 - - ..() - if(!IsValidBiomassLoc(loc,src)) - del(src) - return - spawn(1) //so that the dir and stuff can be set by the source first - if(curDistance >= maxDistance) - return - switch(dir) - if(NORTHWEST) - dir = NORTH - if(NORTHEAST) - dir = EAST - if(SOUTHWEST) - dir = WEST - if(SOUTHEAST) - dir = SOUTH - sleep(spreadDelay) - Spread() - -/obj/effect/biomass/proc/Spread(var/direction = dir) - set background = 1 - var/possibleDirsInt = 0 - - for(var/newDirection in cardinal) - if(newDirection == turn(direction,180)) //can't go backwards - continue - var/turf/T = get_step(loc,newDirection) - if(!IsValidBiomassLoc(T,src)) - continue - possibleDirsInt |= newDirection - - var/list/possibleDirs = list() - - if(possibleDirsInt & direction) - for(var/i=0 , i= maxDistance) + return + switch(dir) + if(NORTHWEST) + dir = NORTH + if(NORTHEAST) + dir = EAST + if(SOUTHWEST) + dir = WEST + if(SOUTHEAST) + dir = SOUTH + sleep(spreadDelay) + Spread() + +/obj/effect/biomass/proc/Spread(var/direction = dir) + set background = 1 + var/possibleDirsInt = 0 + + for(var/newDirection in cardinal) + if(newDirection == turn(direction,180)) //can't go backwards + continue + var/turf/T = get_step(loc,newDirection) + if(!IsValidBiomassLoc(T,src)) + continue + possibleDirsInt |= newDirection + + var/list/possibleDirs = list() + + if(possibleDirsInt & direction) + for(var/i=0 , i[user] wipes away \the [src].") - qdel(src) - -/obj/effect/decal/cleanable/dirt - name = "dirt" - desc = "Someone should clean that up." - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/effects.dmi' - icon_state = "dirt" - mouse_opacity = 0 - -/obj/effect/decal/cleanable/flour - name = "flour" - desc = "It's still good. Four second rule!" - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/effects.dmi' - icon_state = "flour" - -/obj/effect/decal/cleanable/greenglow - name = "glowing goo" - desc = "Jeez. I hope that's not for lunch." - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - luminosity = 1 - icon = 'icons/effects/effects.dmi' - icon_state = "greenglow" - -/obj/effect/decal/cleanable/cobweb - name = "cobweb" - desc = "Somebody should remove that." - density = 0 - anchored = 1 - layer = 3 - icon = 'icons/effects/effects.dmi' - icon_state = "cobweb1" - -/obj/effect/decal/cleanable/molten_item - name = "gooey grey mass" - desc = "It looks like a melted... something." - density = 0 - anchored = 1 - layer = 3 - icon = 'icons/obj/chemical.dmi' - icon_state = "molten" - -/obj/effect/decal/cleanable/cobweb2 - name = "cobweb" - desc = "Somebody should remove that." - density = 0 - anchored = 1 - layer = 3 - icon = 'icons/effects/effects.dmi' - icon_state = "cobweb2" - -//Vomit (sorry) -/obj/effect/decal/cleanable/vomit - name = "vomit" - desc = "Gosh, how unpleasant." - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/blood.dmi' - icon_state = "vomit_1" - - basecolor="#FFFF99" - amount = 2 - random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") - transfers_dna = 1 - -/obj/effect/decal/cleanable/tomato_smudge - name = "tomato smudge" - desc = "It's red." - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/tomatodecal.dmi' - random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") - -/obj/effect/decal/cleanable/fruit_smudge - name = "smudge" - desc = "Some kind of fruit smear." - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/tomatodecal.dmi' - random_icon_states = list("fruit_smudge1", "fruit_smudge2", "fruit_smudge3") - icon_state = "fruit_smudge1" - -/obj/effect/decal/cleanable/egg_smudge - name = "smashed egg" - desc = "Seems like this one won't hatch." - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/tomatodecal.dmi' - random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3") - -/obj/effect/decal/cleanable/pie_smudge //honk - name = "smashed pie" - desc = "It's pie cream from a cream pie." - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/tomatodecal.dmi' - random_icon_states = list("smashed_pie") - -/obj/effect/decal/cleanable/scattered_sand - name = "scattered sand" - desc = "Now how are you gonna sweep it back up, smartass?" - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/effects.dmi' - icon_state = "sand" - gender = PLURAL - -/obj/effect/decal/cleanable/campfire - name = "burnt out campfire" - icon_state = "campfire" - desc = "This burnt-out campfire reminds you of someone." - anchored = 1 - density = 0 - layer = 2 - icon = 'icons/obj/atmos.dmi' - icon_state = "campfire_burnt" - -/obj/effect/decal/cleanable/clay_fragments - name = "clay fragments" - desc = "pieces from a broken clay pot" - gender = PLURAL - icon = 'icons/effects/tomatodecal.dmi' - icon_state = "clay_fragments" - anchored = 0 - layer=2 - -/obj/effect/decal/cleanable/clay_fragments/New() - ..() - pixel_x = rand (-3,3) - pixel_y = rand (-3,3) - -/obj/effect/decal/cleanable/soot - name = "soot" - desc = "One hell of a party..." - gender = PLURAL - icon = 'icons/effects/tile_effects.dmi' - icon_state = "tile_soot" - anchored = 1 - layer=2 - - - -/obj/effect/decal/cleanable/soot/New() - ..() - dir = pick(cardinal) - -/obj/effect/decal/cleanable/lspaceclutter - name = "clutter" - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/effects.dmi' - icon_state = "lspaceclutter" - -/obj/effect/decal/cleanable/cockroach_remains - name = "cockroach remains" - desc = "A disgusting mess." - icon = 'icons/mob/animal.dmi' - icon_state = "cockroach_remains1" - -/obj/effect/decal/cleanable/cockroach_remains/New() - ..() - icon_state = "cockroach_remains[rand(1,2)]" +/obj/effect/decal/cleanable/generic + name = "clutter" + desc = "Someone should clean that up." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/obj/objects.dmi' + icon_state = "shards" + +/obj/effect/decal/cleanable/ash + name = "ashes" + desc = "Ashes to ashes, dust to dust, and into space." + gender = PLURAL + icon = 'icons/obj/objects.dmi' + icon_state = "ash" + anchored = 1 + layer = TURF_LAYER + +/obj/effect/decal/cleanable/ash/attack_hand(mob/user as mob) + user.visible_message("[user] wipes away \the [src].") + qdel(src) + +/obj/effect/decal/cleanable/dirt + name = "dirt" + desc = "Someone should clean that up." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/effects.dmi' + icon_state = "dirt" + mouse_opacity = 0 + +/obj/effect/decal/cleanable/flour + name = "flour" + desc = "It's still good. Four second rule!" + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/effects.dmi' + icon_state = "flour" + +/obj/effect/decal/cleanable/greenglow + name = "glowing goo" + desc = "Jeez. I hope that's not for lunch." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + luminosity = 1 + icon = 'icons/effects/effects.dmi' + icon_state = "greenglow" + +/obj/effect/decal/cleanable/cobweb + name = "cobweb" + desc = "Somebody should remove that." + density = 0 + anchored = 1 + layer = 3 + icon = 'icons/effects/effects.dmi' + icon_state = "cobweb1" + +/obj/effect/decal/cleanable/molten_item + name = "gooey grey mass" + desc = "It looks like a melted... something." + density = 0 + anchored = 1 + layer = 3 + icon = 'icons/obj/chemical.dmi' + icon_state = "molten" + +/obj/effect/decal/cleanable/cobweb2 + name = "cobweb" + desc = "Somebody should remove that." + density = 0 + anchored = 1 + layer = 3 + icon = 'icons/effects/effects.dmi' + icon_state = "cobweb2" + +//Vomit (sorry) +/obj/effect/decal/cleanable/vomit + name = "vomit" + desc = "Gosh, how unpleasant." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/blood.dmi' + icon_state = "vomit_1" + + basecolor="#FFFF99" + amount = 2 + random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") + transfers_dna = 1 + +/obj/effect/decal/cleanable/tomato_smudge + name = "tomato smudge" + desc = "It's red." + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/tomatodecal.dmi' + random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") + +/obj/effect/decal/cleanable/fruit_smudge + name = "smudge" + desc = "Some kind of fruit smear." + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/tomatodecal.dmi' + random_icon_states = list("fruit_smudge1", "fruit_smudge2", "fruit_smudge3") + icon_state = "fruit_smudge1" + +/obj/effect/decal/cleanable/egg_smudge + name = "smashed egg" + desc = "Seems like this one won't hatch." + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/tomatodecal.dmi' + random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3") + +/obj/effect/decal/cleanable/pie_smudge //honk + name = "smashed pie" + desc = "It's pie cream from a cream pie." + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/tomatodecal.dmi' + random_icon_states = list("smashed_pie") + +/obj/effect/decal/cleanable/scattered_sand + name = "scattered sand" + desc = "Now how are you gonna sweep it back up, smartass?" + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/effects.dmi' + icon_state = "sand" + gender = PLURAL + +/obj/effect/decal/cleanable/campfire + name = "burnt out campfire" + icon_state = "campfire" + desc = "This burnt-out campfire reminds you of someone." + anchored = 1 + density = 0 + layer = 2 + icon = 'icons/obj/atmos.dmi' + icon_state = "campfire_burnt" + +/obj/effect/decal/cleanable/clay_fragments + name = "clay fragments" + desc = "pieces from a broken clay pot" + gender = PLURAL + icon = 'icons/effects/tomatodecal.dmi' + icon_state = "clay_fragments" + anchored = 0 + layer=2 + +/obj/effect/decal/cleanable/clay_fragments/New() + ..() + pixel_x = rand (-3,3) + pixel_y = rand (-3,3) + +/obj/effect/decal/cleanable/soot + name = "soot" + desc = "One hell of a party..." + gender = PLURAL + icon = 'icons/effects/tile_effects.dmi' + icon_state = "tile_soot" + anchored = 1 + layer=2 + + + +/obj/effect/decal/cleanable/soot/New() + ..() + dir = pick(cardinal) + +/obj/effect/decal/cleanable/lspaceclutter + name = "clutter" + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/effects.dmi' + icon_state = "lspaceclutter" + +/obj/effect/decal/cleanable/cockroach_remains + name = "cockroach remains" + desc = "A disgusting mess." + icon = 'icons/mob/animal.dmi' + icon_state = "cockroach_remains1" + +/obj/effect/decal/cleanable/cockroach_remains/New() + ..() + icon_state = "cockroach_remains[rand(1,2)]" diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm index 9ee247ae542..3474fbf15b4 100644 --- a/code/game/objects/effects/decals/Cleanable/robots.dm +++ b/code/game/objects/effects/decals/Cleanable/robots.dm @@ -1,51 +1,51 @@ -/obj/effect/decal/cleanable/blood/gibs/robot - name = "robot debris" - desc = "It's a useless heap of junk... or is it?" - icon = 'icons/mob/robots.dmi' - icon_state = "gib1" - basecolor="#030303" - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") - -/obj/effect/decal/cleanable/blood/gibs/robot/update_icon() - color = "#FFFFFF" - -/obj/effect/decal/cleanable/blood/gibs/robot/dry() //pieces of robots do not dry up like - return - -/obj/effect/decal/cleanable/blood/gibs/robot/streak(var/list/directions) - spawn (0) - var/direction = pick(directions) - for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) - sleep(3) - if (i > 0) - if (prob(40)) - var/obj/effect/decal/cleanable/blood/oil/streak = getFromPool(/obj/effect/decal/cleanable/blood/oil/streak,get_turf(src)) - streak.New(streak.loc) - streak.update_icon() - else if (prob(10)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - if (step_to(src, get_step(src, direction), 0)) - break - -/obj/effect/decal/cleanable/blood/gibs/robot/limb - random_icon_states = list("gibarm", "gibleg") - -/obj/effect/decal/cleanable/blood/gibs/robot/up - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4 - -/obj/effect/decal/cleanable/blood/gibs/robot/down - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4 - -/obj/effect/decal/cleanable/blood/oil - name = "motor oil" - desc = "It's black and greasy. Looks like Beepsky made another mess." - basecolor="#030303" - -/obj/effect/decal/cleanable/blood/oil/dry() - return - -/obj/effect/decal/cleanable/blood/oil/streak - random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5") +/obj/effect/decal/cleanable/blood/gibs/robot + name = "robot debris" + desc = "It's a useless heap of junk... or is it?" + icon = 'icons/mob/robots.dmi' + icon_state = "gib1" + basecolor="#030303" + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") + +/obj/effect/decal/cleanable/blood/gibs/robot/update_icon() + color = "#FFFFFF" + +/obj/effect/decal/cleanable/blood/gibs/robot/dry() //pieces of robots do not dry up like + return + +/obj/effect/decal/cleanable/blood/gibs/robot/streak(var/list/directions) + spawn (0) + var/direction = pick(directions) + for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) + sleep(3) + if (i > 0) + if (prob(40)) + var/obj/effect/decal/cleanable/blood/oil/streak = getFromPool(/obj/effect/decal/cleanable/blood/oil/streak,get_turf(src)) + streak.New(streak.loc) + streak.update_icon() + else if (prob(10)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + if (step_to(src, get_step(src, direction), 0)) + break + +/obj/effect/decal/cleanable/blood/gibs/robot/limb + random_icon_states = list("gibarm", "gibleg") + +/obj/effect/decal/cleanable/blood/gibs/robot/up + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4 + +/obj/effect/decal/cleanable/blood/gibs/robot/down + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4 + +/obj/effect/decal/cleanable/blood/oil + name = "motor oil" + desc = "It's black and greasy. Looks like Beepsky made another mess." + basecolor="#030303" + +/obj/effect/decal/cleanable/blood/oil/dry() + return + +/obj/effect/decal/cleanable/blood/oil/streak + random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5") amount = 2 \ No newline at end of file diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 3ae9718f050..5071e97492c 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -1,38 +1,38 @@ -/obj/effect/decal/cleanable/crayon - name = "rune" - desc = "A rune drawn in crayon." - icon = 'icons/obj/rune.dmi' - layer = 2.1 - anchored = 1 - -/obj/effect/decal/cleanable/crayon/New(location,main = "#FFFFFF",shade = "#000000",var/type = "rune") - ..() - loc = location - - name = type - desc = "A [type] drawn in crayon." - - switch(type) - if("rune") - type = "rune[rand(1,6)]" - if("graffiti") - type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","heart","borgsrogue","shitcurity","catbeast","voxpox","security","hieroglyphs[rand(1,3)]","nanotrasen","lie","syndicate[rand(1,2)]","lambda","50bless","chaos") - - var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]",2.1) - var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]s",2.1) - - mainOverlay.Blend(main,ICON_ADD) - shadeOverlay.Blend(shade,ICON_ADD) - - overlays += mainOverlay - overlays += shadeOverlay - - add_hiddenprint(usr) - -//This decal is a big green "fuck you" intended to be hidden behind doors built on walls - -/obj/effect/decal/cleanable/crayon/fuckyou - icon_state = "fuckyou" - -/obj/effect/decal/cleanable/crayon/fuckyou/New(location, main = "#007F0E", shade = "#02560B", type = "fuckyou") - ..() +/obj/effect/decal/cleanable/crayon + name = "rune" + desc = "A rune drawn in crayon." + icon = 'icons/obj/rune.dmi' + layer = 2.1 + anchored = 1 + +/obj/effect/decal/cleanable/crayon/New(location,main = "#FFFFFF",shade = "#000000",var/type = "rune") + ..() + loc = location + + name = type + desc = "A [type] drawn in crayon." + + switch(type) + if("rune") + type = "rune[rand(1,6)]" + if("graffiti") + type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","heart","borgsrogue","shitcurity","catbeast","voxpox","security","hieroglyphs[rand(1,3)]","nanotrasen","lie","syndicate[rand(1,2)]","lambda","50bless","chaos") + + var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]",2.1) + var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]s",2.1) + + mainOverlay.Blend(main,ICON_ADD) + shadeOverlay.Blend(shade,ICON_ADD) + + overlays += mainOverlay + overlays += shadeOverlay + + add_hiddenprint(usr) + +//This decal is a big green "fuck you" intended to be hidden behind doors built on walls + +/obj/effect/decal/cleanable/crayon/fuckyou + icon_state = "fuckyou" + +/obj/effect/decal/cleanable/crayon/fuckyou/New(location, main = "#007F0E", shade = "#02560B", type = "fuckyou") + ..() diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index 537aa6fd4c3..c8c16b5d763 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -1,47 +1,47 @@ -//This was put here because I don't want to overcomplicate my PR -/obj/effect/decal - //var/global/list/decals = list() - -/obj/effect/decal/New() - ..() - decals += src - -/obj/effect/decal/Destroy() - decals -= src - ..() - -/obj/effect/decal/point - name = "arrow" - icon = 'icons/mob/screen1.dmi' - icon_state = "arrow" - layer = 16 - anchored = 1 - mouse_opacity = 0 - w_type = NOT_RECYCLABLE - -//Used for spray that you spray at walls, tables, hydrovats etc -/obj/effect/decal/spraystill - density = 0 - anchored = 1 - layer = 50 - -/obj/effect/decal/snow - name = "snow" - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/turf/snow.dmi' - w_type = NOT_RECYCLABLE - - -/obj/effect/decal/snow/clean/edge - icon_state = "snow_corner" - -/obj/effect/decal/snow/sand/edge - icon_state = "gravsnow_corner" - -/obj/effect/decal/snow/clean/surround - icon_state = "snow_surround" - -/obj/effect/decal/snow/sand/surround - icon_state = "gravsnow_surround" +//This was put here because I don't want to overcomplicate my PR +/obj/effect/decal + //var/global/list/decals = list() + +/obj/effect/decal/New() + ..() + decals += src + +/obj/effect/decal/Destroy() + decals -= src + ..() + +/obj/effect/decal/point + name = "arrow" + icon = 'icons/mob/screen1.dmi' + icon_state = "arrow" + layer = 16 + anchored = 1 + mouse_opacity = 0 + w_type = NOT_RECYCLABLE + +//Used for spray that you spray at walls, tables, hydrovats etc +/obj/effect/decal/spraystill + density = 0 + anchored = 1 + layer = 50 + +/obj/effect/decal/snow + name = "snow" + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/turf/snow.dmi' + w_type = NOT_RECYCLABLE + + +/obj/effect/decal/snow/clean/edge + icon_state = "snow_corner" + +/obj/effect/decal/snow/sand/edge + icon_state = "gravsnow_corner" + +/obj/effect/decal/snow/clean/surround + icon_state = "snow_surround" + +/obj/effect/decal/snow/sand/surround + icon_state = "gravsnow_surround" diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index d00c5dc5366..5f89cdef8d3 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -1,26 +1,26 @@ -/obj/effect/decal/remains/cultify() - return - -/obj/effect/decal/remains/human - name = "remains" - desc = "They look like human remains. They have a strange aura about them." - gender = PLURAL - icon = 'icons/effects/blood.dmi' - icon_state = "remains" - anchored = 1 - -/obj/effect/decal/remains/xeno - name = "remains" - desc = "They look like the remains of something... alien. They have a strange aura about them." - gender = PLURAL - icon = 'icons/effects/blood.dmi' - icon_state = "remainsxeno" - anchored = 1 - -/obj/effect/decal/remains/robot - name = "remains" - desc = "They look like the remains of something mechanical. They have a strange aura about them." - gender = PLURAL - icon = 'icons/mob/robots.dmi' - icon_state = "remainsrobot" +/obj/effect/decal/remains/cultify() + return + +/obj/effect/decal/remains/human + name = "remains" + desc = "They look like human remains. They have a strange aura about them." + gender = PLURAL + icon = 'icons/effects/blood.dmi' + icon_state = "remains" + anchored = 1 + +/obj/effect/decal/remains/xeno + name = "remains" + desc = "They look like the remains of something... alien. They have a strange aura about them." + gender = PLURAL + icon = 'icons/effects/blood.dmi' + icon_state = "remainsxeno" + anchored = 1 + +/obj/effect/decal/remains/robot + name = "remains" + desc = "They look like the remains of something mechanical. They have a strange aura about them." + gender = PLURAL + icon = 'icons/mob/robots.dmi' + icon_state = "remainsrobot" anchored = 1 \ No newline at end of file diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index b596c8d5621..b1c87cdce8c 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -1,1038 +1,1038 @@ -/* This is an attempt to make some easily reusable "particle" type effect, to stop the code -constantly having to be rewritten. An item like the jetpack that uses the ion_trail_follow system, just has one -defined, then set up when it is created with New(). Then this same system can just be reused each time -it needs to create more trails.A beaker could have a steam_trail_follow system set up, then the steam -would spawn and follow the beaker, even if it is carried or thrown. -*/ - - -/obj/effect/effect - name = "effect" - icon = 'icons/effects/effects.dmi' - mouse_opacity = 0 - unacidable = 1 // so effect are not targeted by alien acid. - flags = 0 - w_type=NOT_RECYCLABLE - pass_flags = PASSTABLE|PASSGRILLE|PASSMACHINE - -/obj/effect/effect/water - name = "water" - icon_state = "extinguish" - var/life = 15.0 - -/obj/effect/effect/water/spray - name = "spray" - icon_state = "extinguish_gray" - -/obj/effect/effect/water/New() - . = ..() - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX - - spawn(70) - qdel(src) - -/obj/effect/effect/water/Destroy() - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX - - ..() - -/obj/effect/effect/water/Move(NewLoc,Dir=0,step_x=0,step_y=0) - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX - - if (--life < 1) - //SN src = null - qdel(src) - return 0 - - .=..() - -/obj/effect/effect/water/Bump(atom/A) - if(reagents) - reagents.reaction(A) - return ..() - -/datum/effect/effect/system - var/number = 3 - var/cardinals = 0 - var/turf/location - var/atom/holder - var/setup = 0 - - proc/set_up(n = 3, c = 0, turf/loc) - if(n > 10) - n = 10 - number = n - cardinals = c - location = loc - setup = 1 - - proc/attach(atom/atom) - holder = atom - - proc/start() - -/obj/effect/canSingulothPull(var/obj/machinery/singularity/singulo) - return 0 - -///////////////////////////////////////////// -// GENERIC STEAM SPREAD SYSTEM - -//Usage: set_up(number of bits of steam, use North/South/East/West only, spawn location) -// The attach(atom/atom) proc is optional, and can be called to attach the effect -// to something, like a smoking beaker, so then you can just call start() and the steam -// will always spawn at the items location, even if it's moved. - -/* Example: -var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread() -- creates new system -steam.set_up(5, 0, mob.loc) -- sets up variables -OPTIONAL: steam.attach(mob) -steam.start() -- spawns the effect -*/ -///////////////////////////////////////////// -/obj/effect/effect/steam - name = "steam" - icon_state = "extinguish" - density = 0 - -/datum/effect/effect/system/steam_spread - - set_up(n = 3, c = 0, turf/loc) - if(n > 10) - n = 10 - number = n - cardinals = c - location = loc - - start() - var/i = 0 - for(i=0, i 10) - n = 10 - number = n - cardinals = c - if(istype(loca, /turf/)) - location = loca - else - location = get_turf(loca) - if(direct) - direction = direct - -/datum/effect/effect/system/smoke_spread/start() - var/i = 0 - for(i=0, i 20) - return - spawn(0) - if(holder) - src.location = get_turf(holder) - var/obj/effect/effect/smoke/smoke = new smoke_type(src.location) - src.total_smoke++ - var/direction = src.direction - if(!direction) - if(src.cardinals) - direction = pick(cardinal) - else - direction = pick(alldirs) - for(i=0, i 20) - n = 20 - number = n - cardinals = c - carry.copy_to(chemholder, carry.total_volume) - - - if(istype(loca, /turf/)) - location = loca - else - location = get_turf(loca) - if(direct) - direction = direct - - var/contained = "" - for(var/reagent in carry.reagent_list) - contained += " [reagent] " - if(contained) - contained = "\[[contained]\]" - var/area/A = get_area(location) - - var/where = "[A.name] | [location.x], [location.y]" - var/whereLink = "[where]" - - if(carry.my_atom.fingerprintslast) - var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) - var/more = "" - if(M) - more = "(?)" - message_admins("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1) - log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].") - else - message_admins("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1) - log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") - - start() - var/i = 0 - - var/color = mix_color_from_reagents(chemholder.reagents.reagent_list) - - for(i=0, i 20) - return - spawn(0) - if(holder) - src.location = get_turf(holder) - var/obj/effect/effect/smoke/chem/smoke = new /obj/effect/effect/smoke/chem(src.location) - src.total_smoke++ - var/direction = src.direction - if(!direction) - if(src.cardinals) - direction = pick(cardinal) - else - direction = pick(alldirs) - - if(chemholder.reagents.total_volume != 1) // can't split 1 very well - chemholder.reagents.copy_to(smoke, chemholder.reagents.total_volume / number) // copy reagents to each smoke, divide evenly - - if(color) - smoke.icon += color // give the smoke color, if it has any to begin with - else - // if no color, just use the old smoke icon - smoke.icon = 'icons/effects/96x96.dmi' - smoke.icon_state = "smoke" - - for(i=0, i 20) - n = 20 - number = n - cardinals = c - - chemholder.reagents.add_reagent("space_drugs", rand(1,10)) - - if(istype(loca, /turf/)) - location = loca - else - location = get_turf(loca) - if(direct) - direction = direct - - var/contained = "\[[chemholder.reagents.get_reagent_ids()]\]" - var/area/A = get_area(location) - - var/where = "[A.name] | [location.x], [location.y]" - var/whereLink=formatJumpTo(location,where) - - var/more = "(?)" - message_admins("[M][more] produced a toxic fart in ([whereLink])[contained].", 0, 1) - log_game("[M][more] produced a toxic fart in ([where])[contained].") - - -///////////////////////////////////////////// -//////// Attach an Ion trail to any object, that spawns when it moves (like for the jetpack) -/// just pass in the object to attach it to in set_up -/// Then do start() to start it and stop() to stop it, obviously -/// and don't call start() in a loop that will be repeated otherwise it'll get spammed! -///////////////////////////////////////////// - -/obj/effect/effect/trails - name = "" - icon_state = "" - anchored = 1 - - var/base_name="ion" - -/obj/effect/effect/trails/New() - ..() - name = "[base_name] trails" - icon_state = "[base_name]_trails" - -/obj/effect/effect/trails/proc/Play() - flick("[base_name]_fade", src) - icon_state = "blank" - spawn( 20 ) - if(src) - returnToPool(src) - -/obj/effect/effect/trails/ion - base_name = "ion" - -/datum/effect/effect/system/trail - var/turf/oldposition - var/processing = 1 - var/on = 1 - - var/trail_type=/obj/effect/effect/trails/ion - - set_up(atom/atom) - attach(atom) - oldposition = get_turf(atom) - - start() - if(!src.on) - src.on = 1 - src.processing = 1 - if(src.processing) - src.processing = 0 - spawn(0) - var/turf/T = get_turf(src.holder) - if(T != src.oldposition) - if(istype(T, /turf/space)) - var/obj/effect/effect/trails/I = getFromPool(trail_type,src.oldposition) - src.oldposition = T - I.dir = src.holder.dir - I.Play() - spawn(2) - if(src.on) - src.processing = 1 - src.start() - - proc/stop() - src.processing = 0 - src.on = 0 - -/datum/effect/effect/system/trail/space_trail - var/turf/oldloc // secondary ion trail loc - var/turf/currloc - -/datum/effect/effect/system/trail/space_trail/start() - if(!src.on) - src.on = 1 - src.processing = 1 - if(src.processing) - src.processing = 0 - spawn(0) - var/turf/T = get_turf(src.holder) - if(currloc != T) - switch(holder.dir) - if(NORTH) - src.oldposition = T - src.oldposition = get_step(oldposition, SOUTH) - src.oldloc = get_step(oldposition,EAST) - //src.oldloc = get_step(oldloc, SOUTH) - if(SOUTH) // More difficult, offset to the north! - src.oldposition = get_step(holder,NORTH) - src.oldposition = get_step(oldposition,NORTH) - src.oldloc = get_step(oldposition,EAST) - //src.oldloc = get_step(oldloc,NORTH) - if(EAST) // Just one to the north should suffice - src.oldposition = T - src.oldposition = get_step(oldposition, WEST) - src.oldloc = get_step(oldposition,NORTH) - //src.oldloc = get_step(oldloc,WEST) - if(WEST) // One to the east and north from there - src.oldposition = get_step(holder,EAST) - src.oldposition = get_step(oldposition,EAST) - src.oldloc = get_step(oldposition,NORTH) - //src.oldloc = get_step(oldloc,EAST) - if(istype(T, /turf/space)) - var/obj/effect/effect/trails/ion/I = getFromPool(/obj/effect/effect/trails/ion,src.oldposition) - var/obj/effect/effect/trails/ion/II = getFromPool(/obj/effect/effect/trails/ion,src.oldloc) - //src.oldposition = T - I.dir = src.holder.dir - II.dir = src.holder.dir - flick("ion_fade", I) - flick("ion_fade", II) - I.icon_state = "blank" - II.icon_state = "blank" - spawn( 20 ) - if(I) returnToPool(I) - if(II) returnToPool(II) - - spawn(2) - if(src.on) - src.processing = 1 - src.start() - currloc = T - - -///////////////////////////////////////////// -//////// Attach a steam trail to an object (eg. a reacting beaker) that will follow it -// even if it's carried of thrown. -///////////////////////////////////////////// - -/datum/effect/effect/system/steam_trail_follow - var/turf/oldposition - var/processing = 1 - var/on = 1 - - set_up(atom/atom) - attach(atom) - oldposition = get_turf(atom) - - start() - if(!src.on) - src.on = 1 - src.processing = 1 - if(src.processing) - src.processing = 0 - spawn(0) - if(src.number < 3) - var/obj/effect/effect/steam/I = new /obj/effect/effect/steam(src.oldposition) - src.number++ - src.oldposition = get_turf(holder) - I.dir = src.holder.dir - spawn(10) - if(I) qdel(I) - src.number-- - spawn(2) - if(src.on) - src.processing = 1 - src.start() - else - spawn(2) - if(src.on) - src.processing = 1 - src.start() - - proc/stop() - src.processing = 0 - src.on = 0 - - - -// Foam -// Similar to smoke, but spreads out more -// metal foams leave behind a foamed metal wall - -/obj/effect/effect/foam - name = "foam" - icon_state = "foam" - opacity = 0 - anchored = 1 - density = 0 - layer = OBJ_LAYER + 0.9 - var/amount = 3 - var/expand = 1 - animate_movement = 0 - var/metal = 0 - -/obj/effect/effect/foam/fire - name = "fire supression foam" - icon_state = "mfoam" - -/obj/effect/effect/foam/New(loc, var/ismetal=0) - . = ..(loc) - icon_state = "[ismetal ? "m":""]foam" - metal = ismetal - playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) - spawn(3 + metal*3) - process() - spawn(120) - processing_objects.Remove(src) - sleep(30) - - if(metal) - var/obj/structure/foamedmetal/M = new(src.loc) - M.metal = metal - M.updateicon() - - flick("[icon_state]-disolve", src) - sleep(5) - qdel(src) - -/obj/effect/effect/foam/fire/New(loc, datum/reagents/R) - reagents = R - reagents.my_atom = src - var/ccolor = mix_color_from_reagents(reagents.reagent_list) - if(ccolor) - icon += ccolor - //playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) - if(reagents.has_reagent("water")) - var/turf/simulated/T = get_turf(src) - if(istype(T)) - var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) - lowertemp.temperature = max( min(lowertemp.temperature-500,lowertemp.temperature / 2) ,0) - lowertemp.react() - T.assume_air(lowertemp) - spawn(3) - process() - spawn(120) - processing_objects.Remove(src) - sleep(30) - flick("[icon_state]-disolve", src) - sleep(5) - qdel(src) - AddToProfiler() - -/obj/effect/effect/foam/fire/process() - if(--amount < 0) - return - -// on delete, transfer any reagents to the floor -/obj/effect/effect/foam/Destroy() - if(!metal && reagents && !istype(src, /obj/effect/effect/foam/fire)) - for(var/atom/A in oview(0,src)) - if(A == src) - continue - reagents.reaction(A, 1, 1) - ..() - - -/obj/effect/effect/foam/process() - if(--amount < 0) - return - - - for(var/direction in cardinal) - - - var/turf/T = get_step(src,direction) - if(!T) - continue - - if(!T.Enter(src)) - continue - - var/obj/effect/effect/foam/F = locate() in T - if(F) - continue - - F = new(T, metal) - F.amount = amount - if(!metal) - F.create_reagents(10) - if (reagents) - for(var/datum/reagent/R in reagents.reagent_list) - F.reagents.add_reagent(R.id,1) - -// foam disolves when heated -// except metal foams -/obj/effect/effect/foam/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(!metal && prob(max(0, exposed_temperature - 475))) - flick("[icon_state]-disolve", src) - - spawn(5) - qdel(src) - - -/obj/effect/effect/foam/Crossed(var/atom/movable/AM) - if(metal) - return - if(istype(src, /obj/effect/effect/foam/fire)) - if(isliving(AM)) - var/mob/living/M = AM - reagents.reaction(M) - return - - if (istype(AM, /mob/living/carbon)) - var/mob/living/carbon/M = AM - if (M.Slip(5, 2, 1)) - to_chat(M, "You slipped on the foam!") - - -/datum/effect/effect/system/foam_spread - var/amount = 5 // the size of the foam spread. - var/list/carried_reagents // the IDs of reagents present when the foam was mixed - var/metal = 0 // 0=foam, 1=metalfoam, 2=ironfoam - - - - - set_up(amt=5, loca, var/datum/reagents/carry = null, var/metalfoam = 0) - amount = round(sqrt(amt / 3), 1) - if(istype(loca, /turf/)) - location = loca - else - location = get_turf(loca) - - carried_reagents = list() - metal = metalfoam - - - // bit of a hack here. Foam carries along any reagent also present in the glass it is mixed - // with (defaults to water if none is present). Rather than actually transfer the reagents, - // this makes a list of the reagent ids and spawns 1 unit of that reagent when the foam disolves. - - - if(carry && !metal) - for(var/datum/reagent/R in carry.reagent_list) - carried_reagents += R.id - - start() - spawn(0) - var/obj/effect/effect/foam/F = locate() in location - if(F) - F.amount += amount - return - - F = new(src.location, metal) - F.amount = amount - - if(!metal) // don't carry other chemicals if a metal foam - F.create_reagents(10) - - if(carried_reagents) - for(var/id in carried_reagents) - F.reagents.add_reagent(id,1) - else - F.reagents.add_reagent("water", 1) - -// wall formed by metal foams -// dense and opaque, but easy to break - -/obj/structure/foamedmetal - icon = 'icons/effects/effects.dmi' - icon_state = "metalfoam" - density = 1 - opacity = 1 // changed in New() - anchored = 1 - name = "foamed metal" - desc = "A lightweight foamed metal wall." - var/metal = 1 // 1=aluminum, 2=iron - -/obj/structure/foamedmetal/proc/updateicon() - - if(metal == 1) - icon_state = "metalfoam" - else - icon_state = "ironfoam" - - -/obj/structure/foamedmetal/ex_act(severity) - qdel(src) - -/obj/structure/foamedmetal/blob_act() - qdel(src) - -/obj/structure/foamedmetal/bullet_act() - if(metal==1 || prob(50)) - qdel(src) - -/obj/structure/foamedmetal/attack_paw(var/mob/user) - attack_hand(user) - return - -/obj/structure/foamedmetal/attack_hand(var/mob/user) - user.delayNextAttack(10) - if ((M_HULK in user.mutations) || (prob(75 - metal*25))) - to_chat(user, "You smash through the metal foam wall.") - for(var/mob/O in oviewers(user)) - if ((O.client && !( O.blinded ))) - to_chat(O, "[user] smashes through the foamed metal.") - qdel(src) - else - to_chat(user, "You hit the metal foam but bounce off it.") - return - - -/obj/structure/foamedmetal/attackby(var/obj/item/I, var/mob/user) - user.delayNextAttack(10) - if (istype(I, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = I - G.affecting.loc = src.loc - for(var/mob/O in viewers(src)) - if (O.client) - to_chat(O, "[G.assailant] smashes [G.affecting] through the foamed metal wall.") - returnToPool(I) - qdel(src) - return - - if(prob(I.force*20 - metal*25)) - to_chat(user, "You smash through the foamed metal with \the [I].") - for(var/mob/O in oviewers(user)) - if ((O.client && !( O.blinded ))) - to_chat(O, "[user] smashes through the foamed metal.") - qdel(src) - else - to_chat(user, "You hit the metal foam to no effect.") - -/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group) return 0 - return !density - - -/obj/structure/foamedmetal/proc/update_nearby_tiles() - - if (isnull(air_master)) - return 0 - - var/T = loc - - if (isturf(T)) - air_master.mark_for_update(T) - - return 1 - -/obj/structure/foamedmetal/New() - . = ..() - update_nearby_tiles() - -/obj/structure/foamedmetal/Destroy() - update_nearby_tiles() - ..() - -/datum/effect/effect/system/reagents_explosion - var/amount // TNT equivalent - var/flashing = 0 // does explosion creates flash effect? - var/flashing_factor = 0 // factor of how powerful the flash effect relatively to the explosion - - set_up (amt, loc, flash = 0, flash_fact = 0) - amount = amt - if(istype(loc, /turf/)) - location = loc - else - location = get_turf(loc) - - flashing = flash - flashing_factor = flash_fact - - return - - start() - if (amount <= 2) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, location) - s.start() - - for(var/mob/M in viewers(5, location)) - to_chat(M, "The solution violently explodes.") - for(var/mob/M in viewers(1, location)) - if (prob (50 * amount)) - to_chat(M, "The explosion knocks you down.") - M.Weaken(rand(1,5)) - return - else - var/devastation = -1 - var/heavy = -1 - var/light = -1 - var/flash = -1 - var/range = 0 - // Clamp all values to MAX_EXPLOSION_RANGE - range = min (MAX_EXPLOSION_RANGE, light + round(amount/3)) - devastation = round(min(1, range * 0.25)) // clamps to 1 devestation for grenades - heavy = round(min(3, range * 0.5)) // clamps to 3 heavy range for grenades - light = min(6, range) // clamps to 6 light range for grenades - flash = range * 1.5 - /* - if (round(amount/12) > 0) - devastation = min (MAX_EXPLOSION_RANGE, devastation + round(amount/12)) - - if (round(amount/6) > 0) - heavy = min (MAX_EXPLOSION_RANGE, heavy + round(amount/6)) - - if (round(amount/3) > 0) - light = min (MAX_EXPLOSION_RANGE, light + round(amount/3)) - - if (flash && flashing_factor) - flash += (round(amount/4) * flashing_factor) - */ - - for(var/mob/M in viewers(8, location)) - to_chat(M, "The solution violently explodes.") - - explosion(location, devastation, heavy, light, flash) - - proc/holder_damage(var/atom/holder) - if(holder) - var/dmglevel = 4 - - if (round(amount/8) > 0) - dmglevel = 1 - else if (round(amount/4) > 0) - dmglevel = 2 - else if (round(amount/2) > 0) - dmglevel = 3 - - if(dmglevel<4) holder.ex_act(dmglevel) +/* This is an attempt to make some easily reusable "particle" type effect, to stop the code +constantly having to be rewritten. An item like the jetpack that uses the ion_trail_follow system, just has one +defined, then set up when it is created with New(). Then this same system can just be reused each time +it needs to create more trails.A beaker could have a steam_trail_follow system set up, then the steam +would spawn and follow the beaker, even if it is carried or thrown. +*/ + + +/obj/effect/effect + name = "effect" + icon = 'icons/effects/effects.dmi' + mouse_opacity = 0 + unacidable = 1 // so effect are not targeted by alien acid. + flags = 0 + w_type=NOT_RECYCLABLE + pass_flags = PASSTABLE|PASSGRILLE|PASSMACHINE + +/obj/effect/effect/water + name = "water" + icon_state = "extinguish" + var/life = 15.0 + +/obj/effect/effect/water/spray + name = "spray" + icon_state = "extinguish_gray" + +/obj/effect/effect/water/New() + . = ..() + //var/turf/T = src.loc + //if (istype(T, /turf)) + // T.firelevel = 0 //TODO: FIX + + spawn(70) + qdel(src) + +/obj/effect/effect/water/Destroy() + //var/turf/T = src.loc + //if (istype(T, /turf)) + // T.firelevel = 0 //TODO: FIX + + ..() + +/obj/effect/effect/water/Move(NewLoc,Dir=0,step_x=0,step_y=0) + //var/turf/T = src.loc + //if (istype(T, /turf)) + // T.firelevel = 0 //TODO: FIX + + if (--life < 1) + //SN src = null + qdel(src) + return 0 + + .=..() + +/obj/effect/effect/water/Bump(atom/A) + if(reagents) + reagents.reaction(A) + return ..() + +/datum/effect/effect/system + var/number = 3 + var/cardinals = 0 + var/turf/location + var/atom/holder + var/setup = 0 + + proc/set_up(n = 3, c = 0, turf/loc) + if(n > 10) + n = 10 + number = n + cardinals = c + location = loc + setup = 1 + + proc/attach(atom/atom) + holder = atom + + proc/start() + +/obj/effect/canSingulothPull(var/obj/machinery/singularity/singulo) + return 0 + +///////////////////////////////////////////// +// GENERIC STEAM SPREAD SYSTEM + +//Usage: set_up(number of bits of steam, use North/South/East/West only, spawn location) +// The attach(atom/atom) proc is optional, and can be called to attach the effect +// to something, like a smoking beaker, so then you can just call start() and the steam +// will always spawn at the items location, even if it's moved. + +/* Example: +var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread() -- creates new system +steam.set_up(5, 0, mob.loc) -- sets up variables +OPTIONAL: steam.attach(mob) +steam.start() -- spawns the effect +*/ +///////////////////////////////////////////// +/obj/effect/effect/steam + name = "steam" + icon_state = "extinguish" + density = 0 + +/datum/effect/effect/system/steam_spread + + set_up(n = 3, c = 0, turf/loc) + if(n > 10) + n = 10 + number = n + cardinals = c + location = loc + + start() + var/i = 0 + for(i=0, i 10) + n = 10 + number = n + cardinals = c + if(istype(loca, /turf/)) + location = loca + else + location = get_turf(loca) + if(direct) + direction = direct + +/datum/effect/effect/system/smoke_spread/start() + var/i = 0 + for(i=0, i 20) + return + spawn(0) + if(holder) + src.location = get_turf(holder) + var/obj/effect/effect/smoke/smoke = new smoke_type(src.location) + src.total_smoke++ + var/direction = src.direction + if(!direction) + if(src.cardinals) + direction = pick(cardinal) + else + direction = pick(alldirs) + for(i=0, i 20) + n = 20 + number = n + cardinals = c + carry.copy_to(chemholder, carry.total_volume) + + + if(istype(loca, /turf/)) + location = loca + else + location = get_turf(loca) + if(direct) + direction = direct + + var/contained = "" + for(var/reagent in carry.reagent_list) + contained += " [reagent] " + if(contained) + contained = "\[[contained]\]" + var/area/A = get_area(location) + + var/where = "[A.name] | [location.x], [location.y]" + var/whereLink = "[where]" + + if(carry.my_atom.fingerprintslast) + var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) + var/more = "" + if(M) + more = "(?)" + message_admins("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1) + log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].") + else + message_admins("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1) + log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") + + start() + var/i = 0 + + var/color = mix_color_from_reagents(chemholder.reagents.reagent_list) + + for(i=0, i 20) + return + spawn(0) + if(holder) + src.location = get_turf(holder) + var/obj/effect/effect/smoke/chem/smoke = new /obj/effect/effect/smoke/chem(src.location) + src.total_smoke++ + var/direction = src.direction + if(!direction) + if(src.cardinals) + direction = pick(cardinal) + else + direction = pick(alldirs) + + if(chemholder.reagents.total_volume != 1) // can't split 1 very well + chemholder.reagents.copy_to(smoke, chemholder.reagents.total_volume / number) // copy reagents to each smoke, divide evenly + + if(color) + smoke.icon += color // give the smoke color, if it has any to begin with + else + // if no color, just use the old smoke icon + smoke.icon = 'icons/effects/96x96.dmi' + smoke.icon_state = "smoke" + + for(i=0, i 20) + n = 20 + number = n + cardinals = c + + chemholder.reagents.add_reagent("space_drugs", rand(1,10)) + + if(istype(loca, /turf/)) + location = loca + else + location = get_turf(loca) + if(direct) + direction = direct + + var/contained = "\[[chemholder.reagents.get_reagent_ids()]\]" + var/area/A = get_area(location) + + var/where = "[A.name] | [location.x], [location.y]" + var/whereLink=formatJumpTo(location,where) + + var/more = "(?)" + message_admins("[M][more] produced a toxic fart in ([whereLink])[contained].", 0, 1) + log_game("[M][more] produced a toxic fart in ([where])[contained].") + + +///////////////////////////////////////////// +//////// Attach an Ion trail to any object, that spawns when it moves (like for the jetpack) +/// just pass in the object to attach it to in set_up +/// Then do start() to start it and stop() to stop it, obviously +/// and don't call start() in a loop that will be repeated otherwise it'll get spammed! +///////////////////////////////////////////// + +/obj/effect/effect/trails + name = "" + icon_state = "" + anchored = 1 + + var/base_name="ion" + +/obj/effect/effect/trails/New() + ..() + name = "[base_name] trails" + icon_state = "[base_name]_trails" + +/obj/effect/effect/trails/proc/Play() + flick("[base_name]_fade", src) + icon_state = "blank" + spawn( 20 ) + if(src) + returnToPool(src) + +/obj/effect/effect/trails/ion + base_name = "ion" + +/datum/effect/effect/system/trail + var/turf/oldposition + var/processing = 1 + var/on = 1 + + var/trail_type=/obj/effect/effect/trails/ion + + set_up(atom/atom) + attach(atom) + oldposition = get_turf(atom) + + start() + if(!src.on) + src.on = 1 + src.processing = 1 + if(src.processing) + src.processing = 0 + spawn(0) + var/turf/T = get_turf(src.holder) + if(T != src.oldposition) + if(istype(T, /turf/space)) + var/obj/effect/effect/trails/I = getFromPool(trail_type,src.oldposition) + src.oldposition = T + I.dir = src.holder.dir + I.Play() + spawn(2) + if(src.on) + src.processing = 1 + src.start() + + proc/stop() + src.processing = 0 + src.on = 0 + +/datum/effect/effect/system/trail/space_trail + var/turf/oldloc // secondary ion trail loc + var/turf/currloc + +/datum/effect/effect/system/trail/space_trail/start() + if(!src.on) + src.on = 1 + src.processing = 1 + if(src.processing) + src.processing = 0 + spawn(0) + var/turf/T = get_turf(src.holder) + if(currloc != T) + switch(holder.dir) + if(NORTH) + src.oldposition = T + src.oldposition = get_step(oldposition, SOUTH) + src.oldloc = get_step(oldposition,EAST) + //src.oldloc = get_step(oldloc, SOUTH) + if(SOUTH) // More difficult, offset to the north! + src.oldposition = get_step(holder,NORTH) + src.oldposition = get_step(oldposition,NORTH) + src.oldloc = get_step(oldposition,EAST) + //src.oldloc = get_step(oldloc,NORTH) + if(EAST) // Just one to the north should suffice + src.oldposition = T + src.oldposition = get_step(oldposition, WEST) + src.oldloc = get_step(oldposition,NORTH) + //src.oldloc = get_step(oldloc,WEST) + if(WEST) // One to the east and north from there + src.oldposition = get_step(holder,EAST) + src.oldposition = get_step(oldposition,EAST) + src.oldloc = get_step(oldposition,NORTH) + //src.oldloc = get_step(oldloc,EAST) + if(istype(T, /turf/space)) + var/obj/effect/effect/trails/ion/I = getFromPool(/obj/effect/effect/trails/ion,src.oldposition) + var/obj/effect/effect/trails/ion/II = getFromPool(/obj/effect/effect/trails/ion,src.oldloc) + //src.oldposition = T + I.dir = src.holder.dir + II.dir = src.holder.dir + flick("ion_fade", I) + flick("ion_fade", II) + I.icon_state = "blank" + II.icon_state = "blank" + spawn( 20 ) + if(I) returnToPool(I) + if(II) returnToPool(II) + + spawn(2) + if(src.on) + src.processing = 1 + src.start() + currloc = T + + +///////////////////////////////////////////// +//////// Attach a steam trail to an object (eg. a reacting beaker) that will follow it +// even if it's carried of thrown. +///////////////////////////////////////////// + +/datum/effect/effect/system/steam_trail_follow + var/turf/oldposition + var/processing = 1 + var/on = 1 + + set_up(atom/atom) + attach(atom) + oldposition = get_turf(atom) + + start() + if(!src.on) + src.on = 1 + src.processing = 1 + if(src.processing) + src.processing = 0 + spawn(0) + if(src.number < 3) + var/obj/effect/effect/steam/I = new /obj/effect/effect/steam(src.oldposition) + src.number++ + src.oldposition = get_turf(holder) + I.dir = src.holder.dir + spawn(10) + if(I) qdel(I) + src.number-- + spawn(2) + if(src.on) + src.processing = 1 + src.start() + else + spawn(2) + if(src.on) + src.processing = 1 + src.start() + + proc/stop() + src.processing = 0 + src.on = 0 + + + +// Foam +// Similar to smoke, but spreads out more +// metal foams leave behind a foamed metal wall + +/obj/effect/effect/foam + name = "foam" + icon_state = "foam" + opacity = 0 + anchored = 1 + density = 0 + layer = OBJ_LAYER + 0.9 + var/amount = 3 + var/expand = 1 + animate_movement = 0 + var/metal = 0 + +/obj/effect/effect/foam/fire + name = "fire supression foam" + icon_state = "mfoam" + +/obj/effect/effect/foam/New(loc, var/ismetal=0) + . = ..(loc) + icon_state = "[ismetal ? "m":""]foam" + metal = ismetal + playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) + spawn(3 + metal*3) + process() + spawn(120) + processing_objects.Remove(src) + sleep(30) + + if(metal) + var/obj/structure/foamedmetal/M = new(src.loc) + M.metal = metal + M.updateicon() + + flick("[icon_state]-disolve", src) + sleep(5) + qdel(src) + +/obj/effect/effect/foam/fire/New(loc, datum/reagents/R) + reagents = R + reagents.my_atom = src + var/ccolor = mix_color_from_reagents(reagents.reagent_list) + if(ccolor) + icon += ccolor + //playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) + if(reagents.has_reagent("water")) + var/turf/simulated/T = get_turf(src) + if(istype(T)) + var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) + lowertemp.temperature = max( min(lowertemp.temperature-500,lowertemp.temperature / 2) ,0) + lowertemp.react() + T.assume_air(lowertemp) + spawn(3) + process() + spawn(120) + processing_objects.Remove(src) + sleep(30) + flick("[icon_state]-disolve", src) + sleep(5) + qdel(src) + AddToProfiler() + +/obj/effect/effect/foam/fire/process() + if(--amount < 0) + return + +// on delete, transfer any reagents to the floor +/obj/effect/effect/foam/Destroy() + if(!metal && reagents && !istype(src, /obj/effect/effect/foam/fire)) + for(var/atom/A in oview(0,src)) + if(A == src) + continue + reagents.reaction(A, 1, 1) + ..() + + +/obj/effect/effect/foam/process() + if(--amount < 0) + return + + + for(var/direction in cardinal) + + + var/turf/T = get_step(src,direction) + if(!T) + continue + + if(!T.Enter(src)) + continue + + var/obj/effect/effect/foam/F = locate() in T + if(F) + continue + + F = new(T, metal) + F.amount = amount + if(!metal) + F.create_reagents(10) + if (reagents) + for(var/datum/reagent/R in reagents.reagent_list) + F.reagents.add_reagent(R.id,1) + +// foam disolves when heated +// except metal foams +/obj/effect/effect/foam/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(!metal && prob(max(0, exposed_temperature - 475))) + flick("[icon_state]-disolve", src) + + spawn(5) + qdel(src) + + +/obj/effect/effect/foam/Crossed(var/atom/movable/AM) + if(metal) + return + if(istype(src, /obj/effect/effect/foam/fire)) + if(isliving(AM)) + var/mob/living/M = AM + reagents.reaction(M) + return + + if (istype(AM, /mob/living/carbon)) + var/mob/living/carbon/M = AM + if (M.Slip(5, 2, 1)) + to_chat(M, "You slipped on the foam!") + + +/datum/effect/effect/system/foam_spread + var/amount = 5 // the size of the foam spread. + var/list/carried_reagents // the IDs of reagents present when the foam was mixed + var/metal = 0 // 0=foam, 1=metalfoam, 2=ironfoam + + + + + set_up(amt=5, loca, var/datum/reagents/carry = null, var/metalfoam = 0) + amount = round(sqrt(amt / 3), 1) + if(istype(loca, /turf/)) + location = loca + else + location = get_turf(loca) + + carried_reagents = list() + metal = metalfoam + + + // bit of a hack here. Foam carries along any reagent also present in the glass it is mixed + // with (defaults to water if none is present). Rather than actually transfer the reagents, + // this makes a list of the reagent ids and spawns 1 unit of that reagent when the foam disolves. + + + if(carry && !metal) + for(var/datum/reagent/R in carry.reagent_list) + carried_reagents += R.id + + start() + spawn(0) + var/obj/effect/effect/foam/F = locate() in location + if(F) + F.amount += amount + return + + F = new(src.location, metal) + F.amount = amount + + if(!metal) // don't carry other chemicals if a metal foam + F.create_reagents(10) + + if(carried_reagents) + for(var/id in carried_reagents) + F.reagents.add_reagent(id,1) + else + F.reagents.add_reagent("water", 1) + +// wall formed by metal foams +// dense and opaque, but easy to break + +/obj/structure/foamedmetal + icon = 'icons/effects/effects.dmi' + icon_state = "metalfoam" + density = 1 + opacity = 1 // changed in New() + anchored = 1 + name = "foamed metal" + desc = "A lightweight foamed metal wall." + var/metal = 1 // 1=aluminum, 2=iron + +/obj/structure/foamedmetal/proc/updateicon() + + if(metal == 1) + icon_state = "metalfoam" + else + icon_state = "ironfoam" + + +/obj/structure/foamedmetal/ex_act(severity) + qdel(src) + +/obj/structure/foamedmetal/blob_act() + qdel(src) + +/obj/structure/foamedmetal/bullet_act() + if(metal==1 || prob(50)) + qdel(src) + +/obj/structure/foamedmetal/attack_paw(var/mob/user) + attack_hand(user) + return + +/obj/structure/foamedmetal/attack_hand(var/mob/user) + user.delayNextAttack(10) + if ((M_HULK in user.mutations) || (prob(75 - metal*25))) + to_chat(user, "You smash through the metal foam wall.") + for(var/mob/O in oviewers(user)) + if ((O.client && !( O.blinded ))) + to_chat(O, "[user] smashes through the foamed metal.") + qdel(src) + else + to_chat(user, "You hit the metal foam but bounce off it.") + return + + +/obj/structure/foamedmetal/attackby(var/obj/item/I, var/mob/user) + user.delayNextAttack(10) + if (istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + G.affecting.loc = src.loc + for(var/mob/O in viewers(src)) + if (O.client) + to_chat(O, "[G.assailant] smashes [G.affecting] through the foamed metal wall.") + returnToPool(I) + qdel(src) + return + + if(prob(I.force*20 - metal*25)) + to_chat(user, "You smash through the foamed metal with \the [I].") + for(var/mob/O in oviewers(user)) + if ((O.client && !( O.blinded ))) + to_chat(O, "[user] smashes through the foamed metal.") + qdel(src) + else + to_chat(user, "You hit the metal foam to no effect.") + +/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group) return 0 + return !density + + +/obj/structure/foamedmetal/proc/update_nearby_tiles() + + if (isnull(air_master)) + return 0 + + var/T = loc + + if (isturf(T)) + air_master.mark_for_update(T) + + return 1 + +/obj/structure/foamedmetal/New() + . = ..() + update_nearby_tiles() + +/obj/structure/foamedmetal/Destroy() + update_nearby_tiles() + ..() + +/datum/effect/effect/system/reagents_explosion + var/amount // TNT equivalent + var/flashing = 0 // does explosion creates flash effect? + var/flashing_factor = 0 // factor of how powerful the flash effect relatively to the explosion + + set_up (amt, loc, flash = 0, flash_fact = 0) + amount = amt + if(istype(loc, /turf/)) + location = loc + else + location = get_turf(loc) + + flashing = flash + flashing_factor = flash_fact + + return + + start() + if (amount <= 2) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, location) + s.start() + + for(var/mob/M in viewers(5, location)) + to_chat(M, "The solution violently explodes.") + for(var/mob/M in viewers(1, location)) + if (prob (50 * amount)) + to_chat(M, "The explosion knocks you down.") + M.Weaken(rand(1,5)) + return + else + var/devastation = -1 + var/heavy = -1 + var/light = -1 + var/flash = -1 + var/range = 0 + // Clamp all values to MAX_EXPLOSION_RANGE + range = min (MAX_EXPLOSION_RANGE, light + round(amount/3)) + devastation = round(min(1, range * 0.25)) // clamps to 1 devestation for grenades + heavy = round(min(3, range * 0.5)) // clamps to 3 heavy range for grenades + light = min(6, range) // clamps to 6 light range for grenades + flash = range * 1.5 + /* + if (round(amount/12) > 0) + devastation = min (MAX_EXPLOSION_RANGE, devastation + round(amount/12)) + + if (round(amount/6) > 0) + heavy = min (MAX_EXPLOSION_RANGE, heavy + round(amount/6)) + + if (round(amount/3) > 0) + light = min (MAX_EXPLOSION_RANGE, light + round(amount/3)) + + if (flash && flashing_factor) + flash += (round(amount/4) * flashing_factor) + */ + + for(var/mob/M in viewers(8, location)) + to_chat(M, "The solution violently explodes.") + + explosion(location, devastation, heavy, light, flash) + + proc/holder_damage(var/atom/holder) + if(holder) + var/dmglevel = 4 + + if (round(amount/8) > 0) + dmglevel = 1 + else if (round(amount/4) > 0) + dmglevel = 2 + else if (round(amount/2) > 0) + dmglevel = 3 + + if(dmglevel<4) holder.ex_act(dmglevel) diff --git a/code/game/objects/effects/gibs.dm b/code/game/objects/effects/gibs.dm index a0d458622f3..11dffb47179 100644 --- a/code/game/objects/effects/gibs.dm +++ b/code/game/objects/effects/gibs.dm @@ -1,81 +1,81 @@ -/proc/gibs(atom/location, var/list/viruses, var/datum/dna/MobDNA) //CARN MARKER - new /obj/effect/gibspawner/generic(get_turf(location),viruses,MobDNA) - -/proc/hgibs(atom/location, var/list/viruses, var/datum/dna/MobDNA, var/fleshcolor, var/bloodcolor) - new /obj/effect/gibspawner/human(get_turf(location),viruses,MobDNA,fleshcolor,bloodcolor) - -/proc/xgibs(atom/location, var/list/viruses) - new /obj/effect/gibspawner/xeno(get_turf(location),viruses) - -/proc/robogibs(atom/location, var/list/viruses) - new /obj/effect/gibspawner/robot(get_turf(location),viruses) - -/obj/effect/gibspawner - var/sparks = 0 //whether sparks spread on Gib() - var/virusProb = 20 //the chance for viruses to spread on the gibs - var/list/gibtypes = list() - var/list/gibamounts = list() - var/list/gibdirections = list() //of lists - var/fleshcolor //Used for gibbed humans. - var/bloodcolor //Used for gibbed humans. - -/obj/effect/gibspawner/New(location, var/list/viruses, var/datum/dna/MobDNA, var/fleshcolor, var/bloodcolor) - ..() - - if(fleshcolor) src.fleshcolor = fleshcolor - if(bloodcolor) src.bloodcolor = bloodcolor - - if(istype(loc,/turf)) //basically if a badmin spawns it - Gib(loc,viruses,MobDNA) - -/obj/effect/gibspawner/proc/Gib(atom/location, var/list/viruses = list(), var/datum/dna/MobDNA = null) - if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len) +/proc/gibs(atom/location, var/list/viruses, var/datum/dna/MobDNA) //CARN MARKER + new /obj/effect/gibspawner/generic(get_turf(location),viruses,MobDNA) + +/proc/hgibs(atom/location, var/list/viruses, var/datum/dna/MobDNA, var/fleshcolor, var/bloodcolor) + new /obj/effect/gibspawner/human(get_turf(location),viruses,MobDNA,fleshcolor,bloodcolor) + +/proc/xgibs(atom/location, var/list/viruses) + new /obj/effect/gibspawner/xeno(get_turf(location),viruses) + +/proc/robogibs(atom/location, var/list/viruses) + new /obj/effect/gibspawner/robot(get_turf(location),viruses) + +/obj/effect/gibspawner + var/sparks = 0 //whether sparks spread on Gib() + var/virusProb = 20 //the chance for viruses to spread on the gibs + var/list/gibtypes = list() + var/list/gibamounts = list() + var/list/gibdirections = list() //of lists + var/fleshcolor //Used for gibbed humans. + var/bloodcolor //Used for gibbed humans. + +/obj/effect/gibspawner/New(location, var/list/viruses, var/datum/dna/MobDNA, var/fleshcolor, var/bloodcolor) + ..() + + if(fleshcolor) src.fleshcolor = fleshcolor + if(bloodcolor) src.bloodcolor = bloodcolor + + if(istype(loc,/turf)) //basically if a badmin spawns it + Gib(loc,viruses,MobDNA) + +/obj/effect/gibspawner/proc/Gib(atom/location, var/list/viruses = list(), var/datum/dna/MobDNA = null) + if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len) to_chat(world, "Gib list length mismatch!") - return - - var/obj/effect/decal/cleanable/blood/gibs/gib = null - for(var/datum/disease/D in viruses) - if(D.spread_type == SPECIAL) - D.cure(1) - qdel(D) - D = null - - if(sparks) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, location) - s.start() - - for(var/i = 1, i<= gibtypes.len, i++) - if(gibamounts[i]) - for(var/j = 1, j<= gibamounts[i], j++) - var/gibType = gibtypes[i] - gib = getFromPool(gibType,location)//new gibType(location) - gib.New(location) - - // Apply human species colouration to masks. - if(fleshcolor) - gib.fleshcolor = fleshcolor - if(bloodcolor) - gib.basecolor = bloodcolor - - gib.update_icon() - - if(viruses.len > 0) - for(var/datum/disease/D in viruses) - if(prob(virusProb)) - var/datum/disease/viruus = D.Copy(1) - gib.viruses += viruus - viruus.holder = gib - - gib.blood_DNA = list() - if(MobDNA) - gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.b_type - else if(istype(src, /obj/effect/gibspawner/xeno)) - gib.blood_DNA["UNKNOWN DNA"] = "X*" - else if(istype(src, /obj/effect/gibspawner/human)) // Probably a monkey - gib.blood_DNA["Non-human DNA"] = "A+" - var/list/directions = gibdirections[i] - if(directions.len) - gib.streak(directions) - - qdel(src) + return + + var/obj/effect/decal/cleanable/blood/gibs/gib = null + for(var/datum/disease/D in viruses) + if(D.spread_type == SPECIAL) + D.cure(1) + qdel(D) + D = null + + if(sparks) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, location) + s.start() + + for(var/i = 1, i<= gibtypes.len, i++) + if(gibamounts[i]) + for(var/j = 1, j<= gibamounts[i], j++) + var/gibType = gibtypes[i] + gib = getFromPool(gibType,location)//new gibType(location) + gib.New(location) + + // Apply human species colouration to masks. + if(fleshcolor) + gib.fleshcolor = fleshcolor + if(bloodcolor) + gib.basecolor = bloodcolor + + gib.update_icon() + + if(viruses.len > 0) + for(var/datum/disease/D in viruses) + if(prob(virusProb)) + var/datum/disease/viruus = D.Copy(1) + gib.viruses += viruus + viruus.holder = gib + + gib.blood_DNA = list() + if(MobDNA) + gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.b_type + else if(istype(src, /obj/effect/gibspawner/xeno)) + gib.blood_DNA["UNKNOWN DNA"] = "X*" + else if(istype(src, /obj/effect/gibspawner/human)) // Probably a monkey + gib.blood_DNA["Non-human DNA"] = "A+" + var/list/directions = gibdirections[i] + if(directions.len) + gib.streak(directions) + + qdel(src) diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm index 5d80fdaea82..46f0beb54eb 100644 --- a/code/game/objects/effects/glowshroom.dm +++ b/code/game/objects/effects/glowshroom.dm @@ -1,157 +1,157 @@ -//separate dm since hydro is getting bloated already - -/obj/effect/glowshroom - name = "glowshroom" - anchored = 1 - opacity = 0 - density = 0 - icon = 'icons/obj/lighting.dmi' - icon_state = "glowshroomf" - layer = 2.1 - var/endurance = 30 - var/potency = 30 - var/delay = 1200 - var/floor = 0 - var/yield = 3 - var/spreadChance = 40 - var/spreadIntoAdjacentChance = 60 - var/evolveChance = 2 - w_type=NOT_RECYCLABLE - -/obj/effect/glowshroom/single - spreadChance = 0 - -/obj/effect/glowshroom/New() - ..() - dir = CalcDir() - - if(!floor) - switch(dir) //offset to make it be on the wall rather than on the floor - if(NORTH) - pixel_y = 32 - if(SOUTH) - pixel_y = -32 - if(EAST) - pixel_x = 32 - if(WEST) - pixel_x = -32 - icon_state = "glowshroom[rand(1,3)]" - else //if on the floor, glowshroom on-floor sprite - icon_state = "glowshroomf" - - spawn(delay) - set_light(round(potency/10)) - // Spread() - Methinks this is broken - N3X - -/obj/effect/glowshroom/proc/Spread() - //set background = 1 - var/spreaded = 1 - - while(spreaded) - spreaded = 0 - - for(var/i=1,i<=yield,i++) - if(prob(spreadChance)) - var/list/possibleLocs = list() - var/spreadsIntoAdjacent = 0 - - if(prob(spreadIntoAdjacentChance)) - spreadsIntoAdjacent = 1 - - for(var/turf/unsimulated/floor/asteroid/earth in view(3,src)) - if(spreadsIntoAdjacent || !locate(/obj/effect/glowshroom) in view(1,earth)) - possibleLocs += earth - - if(!possibleLocs.len) - break - - var/turf/newLoc = pick(possibleLocs) - - var/shroomCount = 0 //hacky - var/placeCount = 1 - for(var/obj/effect/glowshroom/shroom in newLoc) - shroomCount++ - for(var/wallDir in cardinal) - var/turf/isWall = get_step(newLoc,wallDir) - if(isWall.density) - placeCount++ - if(shroomCount >= placeCount) - continue - - var/obj/effect/glowshroom/child = new /obj/effect/glowshroom(newLoc) - child.potency = potency - child.yield = yield - child.delay = delay - child.endurance = endurance - - spreaded++ - - if(prob(evolveChance)) //very low chance to evolve on its own - potency += rand(4,6) - - sleep(delay) - -/obj/effect/glowshroom/proc/CalcDir(turf/location = loc) - //set background = 1 - var/direction = 16 - - for(var/wallDir in cardinal) - var/turf/newTurf = get_step(location,wallDir) - if(newTurf.density) - direction |= wallDir - - for(var/obj/effect/glowshroom/shroom in location) - if(shroom == src) - continue - if(shroom.floor) //special - direction &= ~16 - else - direction &= ~shroom.dir - - var/list/dirList = list() - - for(var/i=1,i<=16,i <<= 1) - if(direction & i) - dirList += i - - if(dirList.len) - var/newDir = pick(dirList) - if(newDir == 16) - floor = 1 - newDir = 1 - return newDir - - floor = 1 - return 1 - -/obj/effect/glowshroom/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - - endurance -= W.force - - CheckEndurance() - -/obj/effect/glowshroom/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(5)) - qdel(src) - return - else - return - -/obj/effect/glowshroom/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - endurance -= 5 - CheckEndurance() - -/obj/effect/glowshroom/proc/CheckEndurance() - if(endurance <= 0) - qdel(src) +//separate dm since hydro is getting bloated already + +/obj/effect/glowshroom + name = "glowshroom" + anchored = 1 + opacity = 0 + density = 0 + icon = 'icons/obj/lighting.dmi' + icon_state = "glowshroomf" + layer = 2.1 + var/endurance = 30 + var/potency = 30 + var/delay = 1200 + var/floor = 0 + var/yield = 3 + var/spreadChance = 40 + var/spreadIntoAdjacentChance = 60 + var/evolveChance = 2 + w_type=NOT_RECYCLABLE + +/obj/effect/glowshroom/single + spreadChance = 0 + +/obj/effect/glowshroom/New() + ..() + dir = CalcDir() + + if(!floor) + switch(dir) //offset to make it be on the wall rather than on the floor + if(NORTH) + pixel_y = 32 + if(SOUTH) + pixel_y = -32 + if(EAST) + pixel_x = 32 + if(WEST) + pixel_x = -32 + icon_state = "glowshroom[rand(1,3)]" + else //if on the floor, glowshroom on-floor sprite + icon_state = "glowshroomf" + + spawn(delay) + set_light(round(potency/10)) + // Spread() - Methinks this is broken - N3X + +/obj/effect/glowshroom/proc/Spread() + //set background = 1 + var/spreaded = 1 + + while(spreaded) + spreaded = 0 + + for(var/i=1,i<=yield,i++) + if(prob(spreadChance)) + var/list/possibleLocs = list() + var/spreadsIntoAdjacent = 0 + + if(prob(spreadIntoAdjacentChance)) + spreadsIntoAdjacent = 1 + + for(var/turf/unsimulated/floor/asteroid/earth in view(3,src)) + if(spreadsIntoAdjacent || !locate(/obj/effect/glowshroom) in view(1,earth)) + possibleLocs += earth + + if(!possibleLocs.len) + break + + var/turf/newLoc = pick(possibleLocs) + + var/shroomCount = 0 //hacky + var/placeCount = 1 + for(var/obj/effect/glowshroom/shroom in newLoc) + shroomCount++ + for(var/wallDir in cardinal) + var/turf/isWall = get_step(newLoc,wallDir) + if(isWall.density) + placeCount++ + if(shroomCount >= placeCount) + continue + + var/obj/effect/glowshroom/child = new /obj/effect/glowshroom(newLoc) + child.potency = potency + child.yield = yield + child.delay = delay + child.endurance = endurance + + spreaded++ + + if(prob(evolveChance)) //very low chance to evolve on its own + potency += rand(4,6) + + sleep(delay) + +/obj/effect/glowshroom/proc/CalcDir(turf/location = loc) + //set background = 1 + var/direction = 16 + + for(var/wallDir in cardinal) + var/turf/newTurf = get_step(location,wallDir) + if(newTurf.density) + direction |= wallDir + + for(var/obj/effect/glowshroom/shroom in location) + if(shroom == src) + continue + if(shroom.floor) //special + direction &= ~16 + else + direction &= ~shroom.dir + + var/list/dirList = list() + + for(var/i=1,i<=16,i <<= 1) + if(direction & i) + dirList += i + + if(dirList.len) + var/newDir = pick(dirList) + if(newDir == 16) + floor = 1 + newDir = 1 + return newDir + + floor = 1 + return 1 + +/obj/effect/glowshroom/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + + endurance -= W.force + + CheckEndurance() + +/obj/effect/glowshroom/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(5)) + qdel(src) + return + else + return + +/obj/effect/glowshroom/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + endurance -= 5 + CheckEndurance() + +/obj/effect/glowshroom/proc/CheckEndurance() + if(endurance <= 0) + qdel(src) diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 83665c0b603..3e5a8b7cb14 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -1,100 +1,100 @@ -/obj/effect/landmark - name = "landmark" - icon = 'icons/mob/screen1.dmi' - icon_state = "x2" - anchored = 1 - unacidable = 1 - w_type=NOT_RECYCLABLE - -/obj/effect/landmark/New() - . = ..() - tag = text("landmark*[]", name) - invisibility = 101 - - switch(name) //some of these are probably obsolete - if("shuttle") - shuttle_z = z - qdel(src) - - if("airtunnel_stop") - airtunnel_stop = x - - if("airtunnel_start") - airtunnel_start = x - - if("airtunnel_bottom") - airtunnel_bottom = y - - if("monkey") - monkeystart += loc - qdel(src) - if("start") - newplayer_start += loc - qdel(src) - - if("wizard") - wizardstart += loc - qdel(src) - - if("JoinLate") - latejoin += loc - qdel(src) - if("AssetJoinLate") - assistant_latejoin += loc - qdel(src) - - //prisoners - if("prisonwarp") - prisonwarp += loc - qdel(src) - // if("mazewarp") - // mazewarp += loc - if("Holding Facility") - holdingfacility += loc - if("tdome1") - tdome1 += loc - if("tdome2") - tdome2 += loc - if("tdomeadmin") - tdomeadmin += loc - if("tdomeobserve") - tdomeobserve += loc - //not prisoners - if("prisonsecuritywarp") - prisonsecuritywarp += loc - qdel(src) - - if("blobstart") - blobstart += loc - qdel(src) - - if("xeno_spawn") - xeno_spawn += loc - qdel(src) - - if("endgame_exit") - endgame_safespawns += loc - qdel(src) - if("bluespacerift") - endgame_exits += loc - qdel(src) - - landmarks_list += src - return 1 - -/obj/effect/landmark/Destroy() - landmarks_list -= src - ..() - -/obj/effect/landmark/start - name = "start" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - anchored = 1.0 - -/obj/effect/landmark/start/New() - ..() - tag = "start*[name]" - invisibility = 101 - - return 1 +/obj/effect/landmark + name = "landmark" + icon = 'icons/mob/screen1.dmi' + icon_state = "x2" + anchored = 1 + unacidable = 1 + w_type=NOT_RECYCLABLE + +/obj/effect/landmark/New() + . = ..() + tag = text("landmark*[]", name) + invisibility = 101 + + switch(name) //some of these are probably obsolete + if("shuttle") + shuttle_z = z + qdel(src) + + if("airtunnel_stop") + airtunnel_stop = x + + if("airtunnel_start") + airtunnel_start = x + + if("airtunnel_bottom") + airtunnel_bottom = y + + if("monkey") + monkeystart += loc + qdel(src) + if("start") + newplayer_start += loc + qdel(src) + + if("wizard") + wizardstart += loc + qdel(src) + + if("JoinLate") + latejoin += loc + qdel(src) + if("AssetJoinLate") + assistant_latejoin += loc + qdel(src) + + //prisoners + if("prisonwarp") + prisonwarp += loc + qdel(src) + // if("mazewarp") + // mazewarp += loc + if("Holding Facility") + holdingfacility += loc + if("tdome1") + tdome1 += loc + if("tdome2") + tdome2 += loc + if("tdomeadmin") + tdomeadmin += loc + if("tdomeobserve") + tdomeobserve += loc + //not prisoners + if("prisonsecuritywarp") + prisonsecuritywarp += loc + qdel(src) + + if("blobstart") + blobstart += loc + qdel(src) + + if("xeno_spawn") + xeno_spawn += loc + qdel(src) + + if("endgame_exit") + endgame_safespawns += loc + qdel(src) + if("bluespacerift") + endgame_exits += loc + qdel(src) + + landmarks_list += src + return 1 + +/obj/effect/landmark/Destroy() + landmarks_list -= src + ..() + +/obj/effect/landmark/start + name = "start" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + anchored = 1.0 + +/obj/effect/landmark/start/New() + ..() + tag = "start*[name]" + invisibility = 101 + + return 1 diff --git a/code/game/objects/effects/manifest.dm b/code/game/objects/effects/manifest.dm index 7cd727f70c6..2d07ddbda36 100644 --- a/code/game/objects/effects/manifest.dm +++ b/code/game/objects/effects/manifest.dm @@ -1,22 +1,22 @@ -/obj/effect/manifest - name = "manifest" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - unacidable = 1//Just to be sure. - w_type=NOT_RECYCLABLE - -/obj/effect/manifest/New() - - src.invisibility = 101 - return - -/obj/effect/manifest/proc/manifest() - var/dat = "Crew Manifest:
                      " - for(var/mob/living/carbon/human/M in mob_list) - dat += text(" [] - []
                      ", M.name, M.get_assignment()) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc ) - P.info = dat - P.name = "paper- 'Crew Manifest'" - //SN src = null - qdel(src) - return +/obj/effect/manifest + name = "manifest" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + unacidable = 1//Just to be sure. + w_type=NOT_RECYCLABLE + +/obj/effect/manifest/New() + + src.invisibility = 101 + return + +/obj/effect/manifest/proc/manifest() + var/dat = "Crew Manifest:
                      " + for(var/mob/living/carbon/human/M in mob_list) + dat += text(" [] - []
                      ", M.name, M.get_assignment()) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc ) + P.info = dat + P.name = "paper- 'Crew Manifest'" + //SN src = null + qdel(src) + return diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 0746bcd888a..740da9dc040 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -1,118 +1,118 @@ -/obj/effect/mine - name = "Mine" - desc = "I better stay away from that thing." - density = 1 - anchored = 1 - w_type=NOT_RECYCLABLE - layer = 3 - icon = 'icons/obj/weapons.dmi' - icon_state = "uglymine" - var/triggerproc = "explode" //name of the proc thats called when the mine is triggered - var/triggered = 0 - -/obj/effect/mine/New() - icon_state = "uglyminearmed" - -/obj/effect/mine/Crossed(AM as mob|obj) - Bumped(AM) - -/obj/effect/mine/Bumped(mob/M as mob|obj) - - if(triggered) return - - if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey)) - for(var/mob/O in viewers(world.view, src.loc)) +/obj/effect/mine + name = "Mine" + desc = "I better stay away from that thing." + density = 1 + anchored = 1 + w_type=NOT_RECYCLABLE + layer = 3 + icon = 'icons/obj/weapons.dmi' + icon_state = "uglymine" + var/triggerproc = "explode" //name of the proc thats called when the mine is triggered + var/triggered = 0 + +/obj/effect/mine/New() + icon_state = "uglyminearmed" + +/obj/effect/mine/Crossed(AM as mob|obj) + Bumped(AM) + +/obj/effect/mine/Bumped(mob/M as mob|obj) + + if(triggered) return + + if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey)) + for(var/mob/O in viewers(world.view, src.loc)) to_chat(O, "[M] triggered the \icon[src] [src]") - triggered = 1 - call(src,triggerproc)(M) - -/obj/effect/mine/proc/triggerrad(obj) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - obj:radiation += 50 - randmutb(obj) - domutcheck(obj,null) - spawn(0) - qdel(src) - -/obj/effect/mine/proc/triggerstun(obj) - if(ismob(obj)) - var/mob/M = obj - M.Stun(30) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - spawn(0) - qdel(src) - -/obj/effect/mine/proc/triggern2o(obj) - //example: n2o triggerproc - //note: im lazy - - for (var/turf/simulated/floor/target in range(1,src)) - if(!target.blocks_air) - - var/datum/gas_mixture/payload = new - var/datum/gas/sleeping_agent/trace_gas = new - - trace_gas.moles = 30 - payload += trace_gas - - target.zone.air.merge(payload) - - spawn(0) - qdel(src) - -/obj/effect/mine/proc/triggerplasma(obj) - for (var/turf/simulated/floor/target in range(1,src)) - if(!target.blocks_air) - - var/datum/gas_mixture/payload = new - - payload.toxins = 30 - - target.zone.air.merge(payload) - - target.hotspot_expose(1000, CELL_VOLUME) - - spawn(0) - qdel(src) - -/obj/effect/mine/proc/triggerkick(obj) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - qdel(obj:client) - spawn(0) - qdel(src) - -/obj/effect/mine/proc/explode(obj) - explosion(loc, 0, 1, 2, 3) - spawn(0) - qdel(src) - -/obj/effect/mine/dnascramble - name = "Radiation Mine" - icon_state = "uglymine" - triggerproc = "triggerrad" - -/obj/effect/mine/plasma - name = "Plasma Mine" - icon_state = "uglymine" - triggerproc = "triggerplasma" - -/obj/effect/mine/kick - name = "Kick Mine" - icon_state = "uglymine" - triggerproc = "triggerkick" - -/obj/effect/mine/n2o - name = "N2O Mine" - icon_state = "uglymine" - triggerproc = "triggern2o" - -/obj/effect/mine/stun - name = "Stun Mine" - icon_state = "uglymine" - triggerproc = "triggerstun" + triggered = 1 + call(src,triggerproc)(M) + +/obj/effect/mine/proc/triggerrad(obj) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + obj:radiation += 50 + randmutb(obj) + domutcheck(obj,null) + spawn(0) + qdel(src) + +/obj/effect/mine/proc/triggerstun(obj) + if(ismob(obj)) + var/mob/M = obj + M.Stun(30) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + spawn(0) + qdel(src) + +/obj/effect/mine/proc/triggern2o(obj) + //example: n2o triggerproc + //note: im lazy + + for (var/turf/simulated/floor/target in range(1,src)) + if(!target.blocks_air) + + var/datum/gas_mixture/payload = new + var/datum/gas/sleeping_agent/trace_gas = new + + trace_gas.moles = 30 + payload += trace_gas + + target.zone.air.merge(payload) + + spawn(0) + qdel(src) + +/obj/effect/mine/proc/triggerplasma(obj) + for (var/turf/simulated/floor/target in range(1,src)) + if(!target.blocks_air) + + var/datum/gas_mixture/payload = new + + payload.toxins = 30 + + target.zone.air.merge(payload) + + target.hotspot_expose(1000, CELL_VOLUME) + + spawn(0) + qdel(src) + +/obj/effect/mine/proc/triggerkick(obj) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + qdel(obj:client) + spawn(0) + qdel(src) + +/obj/effect/mine/proc/explode(obj) + explosion(loc, 0, 1, 2, 3) + spawn(0) + qdel(src) + +/obj/effect/mine/dnascramble + name = "Radiation Mine" + icon_state = "uglymine" + triggerproc = "triggerrad" + +/obj/effect/mine/plasma + name = "Plasma Mine" + icon_state = "uglymine" + triggerproc = "triggerplasma" + +/obj/effect/mine/kick + name = "Kick Mine" + icon_state = "uglymine" + triggerproc = "triggerkick" + +/obj/effect/mine/n2o + name = "N2O Mine" + icon_state = "uglymine" + triggerproc = "triggern2o" + +/obj/effect/mine/stun + name = "Stun Mine" + icon_state = "uglymine" + triggerproc = "triggerstun" diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index f27d8d3e787..1d6bfbbe206 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -1,65 +1,65 @@ - -/obj/effect/overlay - name = "overlay" - unacidable = 1 - w_type=NOT_RECYCLABLE - var/i_attached//Added for possible image attachments to objects. For hallucinations and the like. - -/obj/effect/overlay/cultify() - return - -/obj/effect/overlay/singuloCanEat() - return 0 - -/obj/effect/overlay/singularity_act() - return - -/obj/effect/overlay/singularity_pull() - return - -/obj/effect/overlay/beam//Not actually a projectile, just an effect. - name="beam" - icon='icons/effects/beam.dmi' - icon_state="b_beam" - layer = 13 - mouse_opacity = 0 - var/tmp/atom/BeamSource - -/obj/effect/overlay/beam/New(turf/loc, var/lifetime = 10, var/fade = 0, var/src_icon = 'icons/effects/beam.dmi') - ..() - icon = src_icon - spawn if(fade) - animate(src, alpha=0, time=lifetime) - spawn(lifetime) - returnToPool(src) - -/obj/effect/overlay/beam/persist/New() - return - -/obj/effect/overlay/palmtree_r - name = "Palm tree" - icon = 'icons/misc/beach2.dmi' - icon_state = "palm1" - density = 1 - layer = 5 - anchored = 1 - -/obj/effect/overlay/palmtree_l - name = "Palm tree" - icon = 'icons/misc/beach2.dmi' - icon_state = "palm2" - density = 1 - layer = 5 - anchored = 1 - -/obj/effect/overlay/coconut - name = "Coconuts" - icon = 'icons/misc/beach.dmi' - icon_state = "coconuts" - - -/obj/effect/overlay/bluespacify - name = "Bluespace" - icon = 'icons/turf/space.dmi' - icon_state = "bluespacify" + +/obj/effect/overlay + name = "overlay" + unacidable = 1 + w_type=NOT_RECYCLABLE + var/i_attached//Added for possible image attachments to objects. For hallucinations and the like. + +/obj/effect/overlay/cultify() + return + +/obj/effect/overlay/singuloCanEat() + return 0 + +/obj/effect/overlay/singularity_act() + return + +/obj/effect/overlay/singularity_pull() + return + +/obj/effect/overlay/beam//Not actually a projectile, just an effect. + name="beam" + icon='icons/effects/beam.dmi' + icon_state="b_beam" + layer = 13 + mouse_opacity = 0 + var/tmp/atom/BeamSource + +/obj/effect/overlay/beam/New(turf/loc, var/lifetime = 10, var/fade = 0, var/src_icon = 'icons/effects/beam.dmi') + ..() + icon = src_icon + spawn if(fade) + animate(src, alpha=0, time=lifetime) + spawn(lifetime) + returnToPool(src) + +/obj/effect/overlay/beam/persist/New() + return + +/obj/effect/overlay/palmtree_r + name = "Palm tree" + icon = 'icons/misc/beach2.dmi' + icon_state = "palm1" + density = 1 + layer = 5 + anchored = 1 + +/obj/effect/overlay/palmtree_l + name = "Palm tree" + icon = 'icons/misc/beach2.dmi' + icon_state = "palm2" + density = 1 + layer = 5 + anchored = 1 + +/obj/effect/overlay/coconut + name = "Coconuts" + icon = 'icons/misc/beach.dmi' + icon_state = "coconuts" + + +/obj/effect/overlay/bluespacify + name = "Bluespace" + icon = 'icons/turf/space.dmi' + icon_state = "bluespacify" layer = LIGHTING_LAYER \ No newline at end of file diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 5cabcfaf3a4..32d38c5f764 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -1,168 +1,168 @@ -/obj/effect/portal - name = "portal" - desc = "Looks stable, but still, best to test it with the clown first." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "portal0" - density = 0 - unacidable = 1//Can't destroy energy portals. - var/obj/target = null - var/obj/item/weapon/creator = null - anchored = 1.0 - w_type=NOT_RECYCLABLE - var/undergoing_deletion = 0 - - var/list/exit_beams = list() - -/obj/effect/portal/attack_hand(var/mob/user) - spawn() - src.teleport(user) - -/obj/effect/portal/attackby(obj/item/weapon/O as obj, mob/user as mob) - if(O == creator) +/obj/effect/portal + name = "portal" + desc = "Looks stable, but still, best to test it with the clown first." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "portal0" + density = 0 + unacidable = 1//Can't destroy energy portals. + var/obj/target = null + var/obj/item/weapon/creator = null + anchored = 1.0 + w_type=NOT_RECYCLABLE + var/undergoing_deletion = 0 + + var/list/exit_beams = list() + +/obj/effect/portal/attack_hand(var/mob/user) + spawn() + src.teleport(user) + +/obj/effect/portal/attackby(obj/item/weapon/O as obj, mob/user as mob) + if(O == creator) to_chat(user, "You close the portal prematurely.") - qdel(src) - else - spawn() - src.teleport(user) -/* -/obj/effect/portal/Bumped(mob/M as mob|obj) - spawn() - src.teleport(M) -*/ -/obj/effect/portal/Crossed(AM as mob|obj,var/no_tp=0) - if(no_tp) - return - if(istype(AM,/obj/item/projectile/beam)) - var/obj/item/projectile/beam/B = AM - B.wait = 1 - spawn() - src.teleport(AM) - -/obj/effect/portal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover,/obj/effect/beam)) - return 0 - else - return ..() - -/obj/effect/portal/New(turf/loc,var/lifespan=300) - ..() - playsound(loc,'sound/effects/portal_open.ogg',60,1) - spawn(lifespan) - qdel(src) - -/obj/effect/portal/Destroy() - if(undergoing_deletion) - return - undergoing_deletion = 1 - playsound(loc,'sound/effects/portal_close.ogg',60,1) - - purge_beams() - - if(target) - if(istype(target,/obj/effect/portal) && !istype(creator,/obj/item/weapon/gun/portalgun)) - qdel(target) - target = null - if(creator) - if(istype(creator,/obj/item/weapon/hand_tele)) - var/obj/item/weapon/hand_tele/H = creator - H.portals -= src - creator = null - else if(istype(creator,/obj/item/weapon/gun/portalgun)) - var/obj/item/weapon/gun/portalgun/P = creator - if(src == P.blue_portal) - P.blue_portal = null - P.sync_portals() - else if(src == P.red_portal) - P.red_portal = null - P.sync_portals() - - var/datum/effect/effect/system/spark_spread/aeffect = new - aeffect.set_up(5, 1, loc) - aeffect.start() - ..() - -/obj/effect/portal/cultify() - return - -/obj/effect/portal/singuloCanEat() - return 0 - -/obj/effect/portal/singularity_act() - return - -/obj/effect/portal/singularity_pull() - return - -var/list/portal_cache = list() - - -/obj/effect/portal/proc/blend_icon(var/obj/effect/portal/P) - var/turf/T = P.loc - - if(!("icon[initial(T.icon)]_iconstate[T.icon_state]" in portal_cache))//If the icon has not been added yet - var/icon/I1 = icon(icon,"portal_mask")//Generate it. - var/icon/I2 = icon(initial(T.icon),T.icon_state) - I1.Blend(I2,ICON_MULTIPLY) - portal_cache["icon[initial(T.icon)]_iconstate[T.icon_state]"] = I1 //And cache it! - - overlays += portal_cache["icon[initial(T.icon)]_iconstate[T.icon_state]"] - -/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj) - if(istype(M, /obj/effect)) //sparks don't teleport - return - if (M.anchored&&istype(M, /obj/mecha)) - return - if (!target) - visible_message("The portal fails to find a destination and dissipates into thin air.") - qdel(src) - return - if (istype(M, /atom/movable)) - var/area/A = get_area(target) - if(A && A.anti_ethereal) - visible_message("A dark form vaguely ressembling a hand reaches through the portal and tears it apart before anything can go through.") - qdel(src) - else - do_teleport(M, target, 0, 1, 1, 1, 'sound/effects/portal_enter.ogg', 'sound/effects/portal_exit.ogg') - - -/obj/effect/portal/beam_connect(var/obj/effect/beam/B) - if(istype(B)) - if(B.HasSource(src)) - return // Prevent infinite loops. - ..() - handle_beams() - -/obj/effect/portal/beam_disconnect(var/obj/effect/beam/B) - if(istype(B)) - if(B.HasSource(src)) - return // Prevent infinite loops. - ..() - handle_beams() - -/obj/effect/portal/handle_beams() - if(target && istype(target,/obj/effect/portal)) - var/obj/effect/portal/PE = target - PE.purge_beams() - - add_beams() - -/obj/effect/portal/proc/purge_beams() - for(var/obj/effect/beam/BE in exit_beams) - exit_beams -= BE - qdel(BE) - -/obj/effect/portal/proc/add_beams() - if((!beams) || (!beams.len) || !target || !istype(target,/obj/effect/portal)) - return - - var/obj/effect/portal/PE = target - - for(var/obj/effect/beam/emitter/BE in beams) - var/list/spawners = list(src) - spawners |= BE.sources - var/obj/effect/beam/emitter/beam = new(PE.loc) - beam.dir = BE.dir - beam.power = BE.power - beam.steps = BE.steps+1 - beam.emit(spawn_by=spawners) - PE.exit_beams += beam + qdel(src) + else + spawn() + src.teleport(user) +/* +/obj/effect/portal/Bumped(mob/M as mob|obj) + spawn() + src.teleport(M) +*/ +/obj/effect/portal/Crossed(AM as mob|obj,var/no_tp=0) + if(no_tp) + return + if(istype(AM,/obj/item/projectile/beam)) + var/obj/item/projectile/beam/B = AM + B.wait = 1 + spawn() + src.teleport(AM) + +/obj/effect/portal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover,/obj/effect/beam)) + return 0 + else + return ..() + +/obj/effect/portal/New(turf/loc,var/lifespan=300) + ..() + playsound(loc,'sound/effects/portal_open.ogg',60,1) + spawn(lifespan) + qdel(src) + +/obj/effect/portal/Destroy() + if(undergoing_deletion) + return + undergoing_deletion = 1 + playsound(loc,'sound/effects/portal_close.ogg',60,1) + + purge_beams() + + if(target) + if(istype(target,/obj/effect/portal) && !istype(creator,/obj/item/weapon/gun/portalgun)) + qdel(target) + target = null + if(creator) + if(istype(creator,/obj/item/weapon/hand_tele)) + var/obj/item/weapon/hand_tele/H = creator + H.portals -= src + creator = null + else if(istype(creator,/obj/item/weapon/gun/portalgun)) + var/obj/item/weapon/gun/portalgun/P = creator + if(src == P.blue_portal) + P.blue_portal = null + P.sync_portals() + else if(src == P.red_portal) + P.red_portal = null + P.sync_portals() + + var/datum/effect/effect/system/spark_spread/aeffect = new + aeffect.set_up(5, 1, loc) + aeffect.start() + ..() + +/obj/effect/portal/cultify() + return + +/obj/effect/portal/singuloCanEat() + return 0 + +/obj/effect/portal/singularity_act() + return + +/obj/effect/portal/singularity_pull() + return + +var/list/portal_cache = list() + + +/obj/effect/portal/proc/blend_icon(var/obj/effect/portal/P) + var/turf/T = P.loc + + if(!("icon[initial(T.icon)]_iconstate[T.icon_state]" in portal_cache))//If the icon has not been added yet + var/icon/I1 = icon(icon,"portal_mask")//Generate it. + var/icon/I2 = icon(initial(T.icon),T.icon_state) + I1.Blend(I2,ICON_MULTIPLY) + portal_cache["icon[initial(T.icon)]_iconstate[T.icon_state]"] = I1 //And cache it! + + overlays += portal_cache["icon[initial(T.icon)]_iconstate[T.icon_state]"] + +/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj) + if(istype(M, /obj/effect)) //sparks don't teleport + return + if (M.anchored&&istype(M, /obj/mecha)) + return + if (!target) + visible_message("The portal fails to find a destination and dissipates into thin air.") + qdel(src) + return + if (istype(M, /atom/movable)) + var/area/A = get_area(target) + if(A && A.anti_ethereal) + visible_message("A dark form vaguely ressembling a hand reaches through the portal and tears it apart before anything can go through.") + qdel(src) + else + do_teleport(M, target, 0, 1, 1, 1, 'sound/effects/portal_enter.ogg', 'sound/effects/portal_exit.ogg') + + +/obj/effect/portal/beam_connect(var/obj/effect/beam/B) + if(istype(B)) + if(B.HasSource(src)) + return // Prevent infinite loops. + ..() + handle_beams() + +/obj/effect/portal/beam_disconnect(var/obj/effect/beam/B) + if(istype(B)) + if(B.HasSource(src)) + return // Prevent infinite loops. + ..() + handle_beams() + +/obj/effect/portal/handle_beams() + if(target && istype(target,/obj/effect/portal)) + var/obj/effect/portal/PE = target + PE.purge_beams() + + add_beams() + +/obj/effect/portal/proc/purge_beams() + for(var/obj/effect/beam/BE in exit_beams) + exit_beams -= BE + qdel(BE) + +/obj/effect/portal/proc/add_beams() + if((!beams) || (!beams.len) || !target || !istype(target,/obj/effect/portal)) + return + + var/obj/effect/portal/PE = target + + for(var/obj/effect/beam/emitter/BE in beams) + var/list/spawners = list(src) + spawners |= BE.sources + var/obj/effect/beam/emitter/beam = new(PE.loc) + beam.dir = BE.dir + beam.power = BE.power + beam.steps = BE.steps+1 + beam.emit(spawn_by=spawners) + PE.exit_beams += beam diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index c7fd3fb5c5e..e4ea6a0133c 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -1,174 +1,174 @@ -/* The old single tank bombs that dont really work anymore -/obj/effect/spawner/bomb - name = "bomb" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - var/btype = 0 //0 = radio, 1= prox, 2=time - var/explosive = 1 // 0= firebomb - var/btemp = 500 // bomb temperature (degC) - var/active = 0 - -/obj/effect/spawner/bomb/radio - btype = 0 - -/obj/effect/spawner/bomb/proximity - btype = 1 - -/obj/effect/spawner/bomb/timer - btype = 2 - -/obj/effect/spawner/bomb/timer/syndicate - btemp = 450 - -/obj/effect/spawner/bomb/suicide - btype = 3 - -/obj/effect/spawner/bomb/New() - ..() - - switch (src.btype) - // radio - if (0) - var/obj/item/assembly/r_i_ptank/R = new /obj/item/assembly/r_i_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/radio/signaler/p1 = new /obj/item/device/radio/signaler(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - p1.master = R - p2.master = R - p3.master = R - R.status = explosive - p1.b_stat = 0 - p2.secured = 1 - p3.air_contents.temperature = btemp + T0C - - // proximity - if (1) - var/obj/item/assembly/m_i_ptank/R = new /obj/item/assembly/m_i_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/prox_sensor/p1 = new /obj/item/device/prox_sensor(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - p1.master = R - p2.master = R - p3.master = R - R.status = explosive - - p3.air_contents.temperature = btemp + T0C - p2.secured = 1 - - if(src.active) - R.part1.secured = 1 - R.part1.icon_state = text("motion[]", 1) - R.c_state(1, src) - - // timer - if (2) - var/obj/item/assembly/t_i_ptank/R = new /obj/item/assembly/t_i_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/timer/p1 = new /obj/item/device/timer(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - p1.master = R - p2.master = R - p3.master = R - R.status = explosive - - p3.air_contents.temperature = btemp + T0C - p2.secured = 1 - //bombvest - if(3) - var/obj/item/clothing/suit/armor/a_i_a_ptank/R = new /obj/item/clothing/suit/armor/a_i_a_ptank(src.loc) - var/obj/item/weapon/tank/plasma/p4 = new /obj/item/weapon/tank/plasma(R) - var/obj/item/device/healthanalyzer/p1 = new /obj/item/device/healthanalyzer(R) - var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) - var/obj/item/clothing/suit/armor/vest/p3 = new /obj/item/clothing/suit/armor/vest(R) - R.part1 = p1 - R.part2 = p2 - R.part3 = p3 - R.part4 = p4 - p1.master = R - p2.master = R - p3.master = R - p4.master = R - R.status = explosive - - p4.air_contents.temperature = btemp + T0C - p2.secured = 1 - - del(src) -*/ - -/obj/effect/spawner/newbomb - name = "bomb" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - var/btype = 0 // 0=radio, 1=prox, 2=time - - timer - btype = 2 - - syndicate - - proximity - btype = 1 - - radio - btype = 0 - - -/obj/effect/spawner/newbomb/New() - ..() - - var/obj/item/device/transfer_valve/V = new(src.loc) - var/obj/item/weapon/tank/plasma/PT = new(V) - var/obj/item/weapon/tank/oxygen/OT = new(V) - - V.tank_one = PT - V.tank_two = OT - - PT.master = V - OT.master = V - - PT.air_contents.temperature = PLASMA_FLASHPOINT - PT.air_contents.toxins = 15 - PT.air_contents.carbon_dioxide = 33 - PT.air_contents.update_values() - - OT.air_contents.temperature = PLASMA_FLASHPOINT - OT.air_contents.oxygen = 48 - OT.air_contents.update_values() - - var/obj/item/device/assembly/S - - switch (src.btype) - // radio - if (0) - - S = new/obj/item/device/assembly/signaler(V) - - // proximity - if (1) - - S = new/obj/item/device/assembly/prox_sensor(V) - - // timer - if (2) - - S = new/obj/item/device/assembly/timer(V) - - - V.attached_device = S - - S.holder = V - S.toggle_secure() - - V.update_icon() - - qdel(src) +/* The old single tank bombs that dont really work anymore +/obj/effect/spawner/bomb + name = "bomb" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + var/btype = 0 //0 = radio, 1= prox, 2=time + var/explosive = 1 // 0= firebomb + var/btemp = 500 // bomb temperature (degC) + var/active = 0 + +/obj/effect/spawner/bomb/radio + btype = 0 + +/obj/effect/spawner/bomb/proximity + btype = 1 + +/obj/effect/spawner/bomb/timer + btype = 2 + +/obj/effect/spawner/bomb/timer/syndicate + btemp = 450 + +/obj/effect/spawner/bomb/suicide + btype = 3 + +/obj/effect/spawner/bomb/New() + ..() + + switch (src.btype) + // radio + if (0) + var/obj/item/assembly/r_i_ptank/R = new /obj/item/assembly/r_i_ptank(src.loc) + var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) + var/obj/item/device/radio/signaler/p1 = new /obj/item/device/radio/signaler(R) + var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) + R.part1 = p1 + R.part2 = p2 + R.part3 = p3 + p1.master = R + p2.master = R + p3.master = R + R.status = explosive + p1.b_stat = 0 + p2.secured = 1 + p3.air_contents.temperature = btemp + T0C + + // proximity + if (1) + var/obj/item/assembly/m_i_ptank/R = new /obj/item/assembly/m_i_ptank(src.loc) + var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) + var/obj/item/device/prox_sensor/p1 = new /obj/item/device/prox_sensor(R) + var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) + R.part1 = p1 + R.part2 = p2 + R.part3 = p3 + p1.master = R + p2.master = R + p3.master = R + R.status = explosive + + p3.air_contents.temperature = btemp + T0C + p2.secured = 1 + + if(src.active) + R.part1.secured = 1 + R.part1.icon_state = text("motion[]", 1) + R.c_state(1, src) + + // timer + if (2) + var/obj/item/assembly/t_i_ptank/R = new /obj/item/assembly/t_i_ptank(src.loc) + var/obj/item/weapon/tank/plasma/p3 = new /obj/item/weapon/tank/plasma(R) + var/obj/item/device/timer/p1 = new /obj/item/device/timer(R) + var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) + R.part1 = p1 + R.part2 = p2 + R.part3 = p3 + p1.master = R + p2.master = R + p3.master = R + R.status = explosive + + p3.air_contents.temperature = btemp + T0C + p2.secured = 1 + //bombvest + if(3) + var/obj/item/clothing/suit/armor/a_i_a_ptank/R = new /obj/item/clothing/suit/armor/a_i_a_ptank(src.loc) + var/obj/item/weapon/tank/plasma/p4 = new /obj/item/weapon/tank/plasma(R) + var/obj/item/device/healthanalyzer/p1 = new /obj/item/device/healthanalyzer(R) + var/obj/item/device/igniter/p2 = new /obj/item/device/igniter(R) + var/obj/item/clothing/suit/armor/vest/p3 = new /obj/item/clothing/suit/armor/vest(R) + R.part1 = p1 + R.part2 = p2 + R.part3 = p3 + R.part4 = p4 + p1.master = R + p2.master = R + p3.master = R + p4.master = R + R.status = explosive + + p4.air_contents.temperature = btemp + T0C + p2.secured = 1 + + del(src) +*/ + +/obj/effect/spawner/newbomb + name = "bomb" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + var/btype = 0 // 0=radio, 1=prox, 2=time + + timer + btype = 2 + + syndicate + + proximity + btype = 1 + + radio + btype = 0 + + +/obj/effect/spawner/newbomb/New() + ..() + + var/obj/item/device/transfer_valve/V = new(src.loc) + var/obj/item/weapon/tank/plasma/PT = new(V) + var/obj/item/weapon/tank/oxygen/OT = new(V) + + V.tank_one = PT + V.tank_two = OT + + PT.master = V + OT.master = V + + PT.air_contents.temperature = PLASMA_FLASHPOINT + PT.air_contents.toxins = 15 + PT.air_contents.carbon_dioxide = 33 + PT.air_contents.update_values() + + OT.air_contents.temperature = PLASMA_FLASHPOINT + OT.air_contents.oxygen = 48 + OT.air_contents.update_values() + + var/obj/item/device/assembly/S + + switch (src.btype) + // radio + if (0) + + S = new/obj/item/device/assembly/signaler(V) + + // proximity + if (1) + + S = new/obj/item/device/assembly/prox_sensor(V) + + // timer + if (2) + + S = new/obj/item/device/assembly/timer(V) + + + V.attached_device = S + + S.holder = V + S.toggle_secure() + + V.update_icon() + + qdel(src) diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index 00311c73ba4..13352067463 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -1,37 +1,37 @@ -/obj/effect/gibspawner - -/obj/effect/gibspawner/generic - gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core) - gibamounts = list(2,2,1) - -/obj/effect/gibspawner/generic/New() - gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list()) - ..() - -/obj/effect/gibspawner/human - gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/down,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core) - gibamounts = list(1,1,1,1,1,1,1) - -/obj/effect/gibspawner/human/New() - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) - gibamounts[6] = pick(0,1,2) - ..() - -/obj/effect/gibspawner/xeno - gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/up,/obj/effect/decal/cleanable/blood/gibs/xeno/down,/obj/effect/decal/cleanable/blood/gibs/xeno,/obj/effect/decal/cleanable/blood/gibs/xeno,/obj/effect/decal/cleanable/blood/gibs/xeno/body,/obj/effect/decal/cleanable/blood/gibs/xeno/limb,/obj/effect/decal/cleanable/blood/gibs/xeno/core) - gibamounts = list(1,1,1,1,1,1,1) - -/obj/effect/gibspawner/xeno/New() - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) - gibamounts[6] = pick(0,1,2) - ..() - -/obj/effect/gibspawner/robot - sparks = 1 - gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/robot/up,/obj/effect/decal/cleanable/blood/gibs/robot/down,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot/limb) - gibamounts = list(1,1,1,1,1,1) - -/obj/effect/gibspawner/robot/New() - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs) - gibamounts[6] = pick(0,1,2) - ..() +/obj/effect/gibspawner + +/obj/effect/gibspawner/generic + gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core) + gibamounts = list(2,2,1) + +/obj/effect/gibspawner/generic/New() + gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list()) + ..() + +/obj/effect/gibspawner/human + gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/down,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core) + gibamounts = list(1,1,1,1,1,1,1) + +/obj/effect/gibspawner/human/New() + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) + gibamounts[6] = pick(0,1,2) + ..() + +/obj/effect/gibspawner/xeno + gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/up,/obj/effect/decal/cleanable/blood/gibs/xeno/down,/obj/effect/decal/cleanable/blood/gibs/xeno,/obj/effect/decal/cleanable/blood/gibs/xeno,/obj/effect/decal/cleanable/blood/gibs/xeno/body,/obj/effect/decal/cleanable/blood/gibs/xeno/limb,/obj/effect/decal/cleanable/blood/gibs/xeno/core) + gibamounts = list(1,1,1,1,1,1,1) + +/obj/effect/gibspawner/xeno/New() + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) + gibamounts[6] = pick(0,1,2) + ..() + +/obj/effect/gibspawner/robot + sparks = 1 + gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/robot/up,/obj/effect/decal/cleanable/blood/gibs/robot/down,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot/limb) + gibamounts = list(1,1,1,1,1,1) + +/obj/effect/gibspawner/robot/New() + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs) + gibamounts[6] = pick(0,1,2) + ..() diff --git a/code/game/objects/effects/spawners/vaultspawner.dm b/code/game/objects/effects/spawners/vaultspawner.dm index c4b9203cefc..0d882cc9bd2 100644 --- a/code/game/objects/effects/spawners/vaultspawner.dm +++ b/code/game/objects/effects/spawners/vaultspawner.dm @@ -1,26 +1,26 @@ -/obj/effect/vaultspawner - var/maxX = 6 - var/maxY = 6 - var/minX = 2 - var/minY = 2 - -/obj/effect/vaultspawner/New(turf/location as turf,lX = minX,uX = maxX,lY = minY,uY = maxY,var/type = null) - if(!type) - type = pick("sandstone","rock","alien") - - var/lowBoundX = location.x - var/lowBoundY = location.y - - var/hiBoundX = location.x + rand(lX,uX) - var/hiBoundY = location.y + rand(lY,uY) - - var/z = location.z - - for(var/i = lowBoundX,i<=hiBoundX,i++) - for(var/j = lowBoundY,j<=hiBoundY,j++) - if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY) - new /turf/simulated/wall/vault(locate(i,j,z),type) - else - new /turf/simulated/floor/vault(locate(i,j,z),type) - - qdel(src) +/obj/effect/vaultspawner + var/maxX = 6 + var/maxY = 6 + var/minX = 2 + var/minY = 2 + +/obj/effect/vaultspawner/New(turf/location as turf,lX = minX,uX = maxX,lY = minY,uY = maxY,var/type = null) + if(!type) + type = pick("sandstone","rock","alien") + + var/lowBoundX = location.x + var/lowBoundY = location.y + + var/hiBoundX = location.x + rand(lX,uX) + var/hiBoundY = location.y + rand(lY,uY) + + var/z = location.z + + for(var/i = lowBoundX,i<=hiBoundX,i++) + for(var/j = lowBoundY,j<=hiBoundY,j++) + if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY) + new /turf/simulated/wall/vault(locate(i,j,z),type) + else + new /turf/simulated/floor/vault(locate(i,j,z),type) + + qdel(src) diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index 12279bf5d24..f42fe6d1a47 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -1,49 +1,49 @@ -proc/empulse(turf/epicenter, heavy_range, light_range, log=0) - if(!epicenter) return - - if(!istype(epicenter, /turf)) - epicenter = get_turf(epicenter.loc) - - if(heavy_range > 1) - var/obj/effect/overlay/pulse = new/obj/effect/overlay ( epicenter ) - pulse.icon = 'icons/effects/effects.dmi' - pulse.icon_state = "emppulse" - pulse.name = "emp pulse" - pulse.anchored = 1 - spawn(20) - qdel(pulse) - - if(heavy_range > light_range) - light_range = heavy_range - - var/max_range = max(heavy_range, light_range) - - var/x0 = epicenter.x - var/y0 = epicenter.y - var/z0 = epicenter.z - - if(log) - message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ([x0],[y0],[z0]) (JMP).") - log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name].") - - spawn() - 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 = cheap_pythag(M_turf.x - x0, M_turf.y - y0) - if(dist <= round(heavy_range + world.view - 2, 1)) +proc/empulse(turf/epicenter, heavy_range, light_range, log=0) + if(!epicenter) return + + if(!istype(epicenter, /turf)) + epicenter = get_turf(epicenter.loc) + + if(heavy_range > 1) + var/obj/effect/overlay/pulse = new/obj/effect/overlay ( epicenter ) + pulse.icon = 'icons/effects/effects.dmi' + pulse.icon_state = "emppulse" + pulse.name = "emp pulse" + pulse.anchored = 1 + spawn(20) + qdel(pulse) + + if(heavy_range > light_range) + light_range = heavy_range + + var/max_range = max(heavy_range, light_range) + + var/x0 = epicenter.x + var/y0 = epicenter.y + var/z0 = epicenter.z + + if(log) + message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ([x0],[y0],[z0]) (JMP).") + log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name].") + + spawn() + 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 = cheap_pythag(M_turf.x - x0, M_turf.y - y0) + if(dist <= round(heavy_range + world.view - 2, 1)) to_chat(M, 'sound/effects/EMPulse.ogg') - - for(var/turf/T in spiral_block(epicenter,max_range)) - var/dist = cheap_pythag(T.x - x0, T.y - y0) - if(dist > max_range) - continue - var/act = 2 - if(dist <= heavy_range) - act = 1 - - for(var/atom/movable/A in T.contents) - A.emp_act(act) + + for(var/turf/T in spiral_block(epicenter,max_range)) + var/dist = cheap_pythag(T.x - x0, T.y - y0) + if(dist > max_range) + continue + var/act = 2 + if(dist <= heavy_range) + act = 1 + + for(var/atom/movable/A in T.contents) + A.emp_act(act) return \ No newline at end of file diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 43ae3b7669c..ec9dbd667b6 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -1,158 +1,158 @@ -//TODO: Flash range does nothing currently - -/proc/trange(var/Dist = 0, var/turf/Center = null)//alternative to range (ONLY processes turfs and thus less intensive) - if (isnull(Center)) - return - - //var/x1 = ((Center.x-Dist) < 1 ? 1 : Center.x - Dist) - //var/y1 = ((Center.y-Dist) < 1 ? 1 : Center.y - Dist) - //var/x2 = ((Center.x+Dist) > world.maxx ? world.maxx : Center.x + Dist) - //var/y2 = ((Center.y+Dist) > world.maxy ? world.maxy : Center.y + Dist) - - var/turf/x1y1 = locate(((Center.x - Dist) < 1 ? 1 : Center.x - Dist), ((Center.y - Dist) < 1 ? 1 : Center.y - Dist), Center.z) - var/turf/x2y2 = locate(((Center.x + Dist) > world.maxx ? world.maxx : Center.x + Dist), ((Center.y + Dist) > world.maxy ? world.maxy : Center.y + Dist), Center.z) - return block(x1y1, x2y2) - -/** - * Make boom - * - * @param epicenter Where explosion is centered - * @param devastation_range - * @param heavy_impact_range - * @param light_impact_range - * @param flash_range Unused - * @param adminlog Log to admins - * @param ignored Do not notify explosion listeners - * @param verbose Explosion listeners will treat as an important explosion worth reporting on radio - */ -/proc/explosion(turf/epicenter, const/devastation_range, const/heavy_impact_range, const/light_impact_range, const/flash_range, adminlog = 1, ignored = 0, verbose = 1) - src = null //so we don't abort once src is deleted - - spawn() - if(config.use_recursive_explosions) - var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power. - explosion_rec(epicenter, power) - return - - var/start = world.timeofday - epicenter = get_turf(epicenter) - if(!epicenter) - return - - score["explosions"]++ //For the scoreboard - - var/max_range = max(devastation_range, heavy_impact_range, light_impact_range) - stat_collection.add_explosion_stat(epicenter, devastation_range, heavy_impact_range, light_impact_range, max_range) -// 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 = (devastation_range * 20) + (heavy_impact_range * 5) - 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)) - if(devastation_range > 0) - M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound - shake_camera(M, 10, 2) - else - M.playsound_local(epicenter, get_sfx("explosion_small"), 100, 1, frequency, falloff = 5) - shake_camera(M, 4, 1) - - //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 - if(devastation_range > 0) - M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5) +//TODO: Flash range does nothing currently + +/proc/trange(var/Dist = 0, var/turf/Center = null)//alternative to range (ONLY processes turfs and thus less intensive) + if (isnull(Center)) + return + + //var/x1 = ((Center.x-Dist) < 1 ? 1 : Center.x - Dist) + //var/y1 = ((Center.y-Dist) < 1 ? 1 : Center.y - Dist) + //var/x2 = ((Center.x+Dist) > world.maxx ? world.maxx : Center.x + Dist) + //var/y2 = ((Center.y+Dist) > world.maxy ? world.maxy : Center.y + Dist) + + var/turf/x1y1 = locate(((Center.x - Dist) < 1 ? 1 : Center.x - Dist), ((Center.y - Dist) < 1 ? 1 : Center.y - Dist), Center.z) + var/turf/x2y2 = locate(((Center.x + Dist) > world.maxx ? world.maxx : Center.x + Dist), ((Center.y + Dist) > world.maxy ? world.maxy : Center.y + Dist), Center.z) + return block(x1y1, x2y2) + +/** + * Make boom + * + * @param epicenter Where explosion is centered + * @param devastation_range + * @param heavy_impact_range + * @param light_impact_range + * @param flash_range Unused + * @param adminlog Log to admins + * @param ignored Do not notify explosion listeners + * @param verbose Explosion listeners will treat as an important explosion worth reporting on radio + */ +/proc/explosion(turf/epicenter, const/devastation_range, const/heavy_impact_range, const/light_impact_range, const/flash_range, adminlog = 1, ignored = 0, verbose = 1) + src = null //so we don't abort once src is deleted + + spawn() + if(config.use_recursive_explosions) + var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power. + explosion_rec(epicenter, power) + return + + var/start = world.timeofday + epicenter = get_turf(epicenter) + if(!epicenter) + return + + score["explosions"]++ //For the scoreboard + + var/max_range = max(devastation_range, heavy_impact_range, light_impact_range) + stat_collection.add_explosion_stat(epicenter, devastation_range, heavy_impact_range, light_impact_range, max_range) +// 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 = (devastation_range * 20) + (heavy_impact_range * 5) + 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)) + if(devastation_range > 0) + M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound + shake_camera(M, 10, 2) + else + M.playsound_local(epicenter, get_sfx("explosion_small"), 100, 1, frequency, falloff = 5) + shake_camera(M, 4, 1) + + //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 + if(devastation_range > 0) + M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5) to_chat(M, "You feel something shake the structure...") - shake_camera(M, 4, 1) - else - M.playsound_local(epicenter, 'sound/effects/explosionsmallfar.ogg', far_volume, 1, frequency, falloff = 5) - - var/close = trange(world.view+round(devastation_range,1), epicenter) - //To all distanced mobs play a different sound - for(var/mob/M in mob_list) if(M.z == epicenter.z) if(!(M in close)) - //Check if the mob can hear - if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space)) + shake_camera(M, 4, 1) + else + M.playsound_local(epicenter, 'sound/effects/explosionsmallfar.ogg', far_volume, 1, frequency, falloff = 5) + + var/close = trange(world.view+round(devastation_range,1), epicenter) + //To all distanced mobs play a different sound + for(var/mob/M in mob_list) if(M.z == epicenter.z) if(!(M in close)) + //Check if the mob can hear + if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space)) to_chat(M, 'sound/effects/explosionfar.ogg') - if(adminlog) - message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)") - log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") - - //Pause the lighting updates for a bit. - var/datum/controller/process/lighting = processScheduler.getProcess("lighting") - lighting.disable() - - if(heavy_impact_range > 1) - var/datum/effect/system/explosion/E = new/datum/effect/system/explosion() - E.set_up(epicenter) - E.start() - else - epicenter.turf_animation('icons/effects/96x96.dmi',"explosion_small",-32, -32, 13) - - var/x0 = epicenter.x - var/y0 = epicenter.y - var/z0 = epicenter.z - - for(var/turf/T in spiral_block(epicenter,max_range,1)) - var/dist = cheap_pythag(T.x - x0, T.y - y0) - - if(explosion_newmethod) //Realistic explosions that take obstacles into account - var/turf/Trajectory = T - while(Trajectory != epicenter) - Trajectory = get_step_towards(Trajectory,epicenter) - if(Trajectory.density && Trajectory.explosion_block) - dist += Trajectory.explosion_block - - for (var/obj/machinery/door/D in Trajectory.contents) - if(D.density && D.explosion_block) - dist += D.explosion_block - - if(dist < devastation_range) - dist = 1 - else if(dist < heavy_impact_range) - dist = 2 - else if(dist < light_impact_range) - dist = 3 - else - continue - - for(var/atom/movable/A in T.contents) - A.ex_act(dist) - - T.ex_act(dist) - - var/took = (world.timeofday-start)/10 - //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare - if(Debug2) - world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds." - - //Machines which report explosions. - if(!ignored) - for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) - if(bhangmeter && !bhangmeter.stat) - bhangmeter.sense_explosion(x0, y0, z0, devastation_range, heavy_impact_range, light_impact_range, took, 0, verbose) - - sleep(8) - - lighting.enable() - - return 1 - - - -proc/secondaryexplosion(turf/epicenter, range) - for(var/turf/tile in trange(range, epicenter)) - tile.ex_act(2) + if(adminlog) + message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)") + log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") + + //Pause the lighting updates for a bit. + var/datum/controller/process/lighting = processScheduler.getProcess("lighting") + lighting.disable() + + if(heavy_impact_range > 1) + var/datum/effect/system/explosion/E = new/datum/effect/system/explosion() + E.set_up(epicenter) + E.start() + else + epicenter.turf_animation('icons/effects/96x96.dmi',"explosion_small",-32, -32, 13) + + var/x0 = epicenter.x + var/y0 = epicenter.y + var/z0 = epicenter.z + + for(var/turf/T in spiral_block(epicenter,max_range,1)) + var/dist = cheap_pythag(T.x - x0, T.y - y0) + + if(explosion_newmethod) //Realistic explosions that take obstacles into account + var/turf/Trajectory = T + while(Trajectory != epicenter) + Trajectory = get_step_towards(Trajectory,epicenter) + if(Trajectory.density && Trajectory.explosion_block) + dist += Trajectory.explosion_block + + for (var/obj/machinery/door/D in Trajectory.contents) + if(D.density && D.explosion_block) + dist += D.explosion_block + + if(dist < devastation_range) + dist = 1 + else if(dist < heavy_impact_range) + dist = 2 + else if(dist < light_impact_range) + dist = 3 + else + continue + + for(var/atom/movable/A in T.contents) + A.ex_act(dist) + + T.ex_act(dist) + + var/took = (world.timeofday-start)/10 + //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare + if(Debug2) + world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds." + + //Machines which report explosions. + if(!ignored) + for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) + if(bhangmeter && !bhangmeter.stat) + bhangmeter.sense_explosion(x0, y0, z0, devastation_range, heavy_impact_range, light_impact_range, took, 0, verbose) + + sleep(8) + + lighting.enable() + + return 1 + + + +proc/secondaryexplosion(turf/epicenter, range) + for(var/turf/tile in trange(range, epicenter)) + tile.ex_act(2) diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm index 8385d45dc2f..b21514ad720 100644 --- a/code/game/objects/explosion_recursive.dm +++ b/code/game/objects/explosion_recursive.dm @@ -1,158 +1,158 @@ -/client/proc/kaboom() - set category = "Debug" - - var/power = input(src, "power?", "power?") as num - var/turf/T = get_turf(src.mob) - explosion_rec(T, power) - -/obj - var/explosion_resistance - -/datum/explosion_turf - var/turf/turf //The turf which will get ex_act called on it - var/max_power //The largest amount of power the turf sustained - - New() - ..() - max_power = 0 - - proc/save_power_if_larger(power) - if(power > max_power) - max_power = power - return 1 - return 0 - -var/list/datum/explosion_turf/explosion_turfs = list() -var/explosion_in_progress = 0 - -proc/get_explosion_turf(var/turf/T) - for( var/datum/explosion_turf/ET in explosion_turfs ) - if( T == ET.turf ) - return ET - var/datum/explosion_turf/ET = new() - ET.turf = T - explosion_turfs += ET - return ET - -proc/explosion_rec(turf/epicenter, power) - - - var/loopbreak = 0 - while(explosion_in_progress) - if(loopbreak >= 15) return - sleep(10) - loopbreak++ - - if(power <= 0) return - epicenter = get_turf(epicenter) - if(!epicenter) return - - message_admins("Explosion with size ([power]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)") - log_game("Explosion with size ([power]) in area [epicenter.loc.name] ") - - playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(power*2,1) ) - playsound(epicenter, "explosion", 100, 1, round(power,1) ) - - explosion_in_progress = 1 - explosion_turfs = list() - var/datum/explosion_turf/ETE = get_explosion_turf() - ETE.turf = epicenter - ETE.max_power = power - - //This steap handles the gathering of turfs which will be ex_act() -ed in the next step. It also ensures each turf gets the maximum possible amount of power dealt to it. - for(var/direction in cardinal) - var/turf/T = get_step(epicenter, direction) - T.explosion_spread(power - epicenter.explosion_resistance, direction) - - //This step applies the ex_act effects for the explosion, as planned in the previous step. - for( var/datum/explosion_turf/ET in explosion_turfs ) - if(ET.max_power <= 0) continue - if(!ET.turf) continue - - //Wow severity looks confusing to calculate... Fret not, I didn't leave you with any additional instructions or help. (just kidding, see the line under the calculation) - var/severity = 4 - round(max(min( 3, ((ET.max_power - ET.turf.explosion_resistance) / (max(3,(power/3)))) ) ,1), 1) - //sanity effective power on tile divided by either 3 or one third the total explosion power - // One third because there are three power levels and I - // want each one to take up a third of the crater - var/x = ET.turf.x - var/y = ET.turf.y - var/z = ET.turf.z - ET.turf.ex_act(severity) - if(!ET.turf) - ET.turf = locate(x,y,z) - for( var/atom/A in ET.turf ) - A.ex_act(severity) - - explosion_in_progress = 0 - -/turf - var/explosion_resistance - -/turf/space - explosion_resistance = 10 - -/turf/simulated/floor - explosion_resistance = 1 - -/turf/unsimulated/mineral - explosion_resistance = 2 - -/turf/simulated/shuttle/floor - explosion_resistance = 1 - -/turf/simulated/shuttle/floor4 - explosion_resistance = 1 - -/turf/simulated/shuttle/plating - explosion_resistance = 1 - -/turf/simulated/shuttle/wall - explosion_resistance = 5 - -/turf/simulated/wall - explosion_resistance = 5 - -/turf/simulated/wall/r_wall - explosion_resistance = 25 - -/turf/simulated/wall/invulnerable - - -//Code-wise, a safe value for power is something up to ~25 or ~30.. This does quite a bit of damage to the station. -//direction is the direction that the spread took to come to this tile. So it is pointing in the main blast direction - meaning where this tile should spread most of it's force. -/turf/proc/explosion_spread(power, direction) - if(power <= 0) - return - - /* - sleep(2) - new/obj/effect/debugging/marker(src) - */ - - var/datum/explosion_turf/ET = get_explosion_turf(src) - if(ET.max_power >= power) - return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again. - ET.max_power = power - - var/spread_power = power - src.explosion_resistance //This is the amount of power that will be spread to the tile in the direction of the blast - var/side_spread_power = power - 2 * src.explosion_resistance //This is the amount of power that will be spread to the side tiles - for(var/obj/O in src) - if(O.explosion_resistance) - spread_power -= O.explosion_resistance - side_spread_power -= O.explosion_resistance - - var/turf/T = get_step(src, direction) - T.explosion_spread(spread_power, direction) - T = get_step(src, turn(direction,90)) - T.explosion_spread(side_spread_power, turn(direction,90)) - T = get_step(src, turn(direction,-90)) - T.explosion_spread(side_spread_power, turn(direction,90)) - - /* - for(var/direction in cardinal) - var/turf/T = get_step(src, direction) - T.explosion_spread(spread_power) - */ - -/turf/unsimulated/explosion_spread(power) +/client/proc/kaboom() + set category = "Debug" + + var/power = input(src, "power?", "power?") as num + var/turf/T = get_turf(src.mob) + explosion_rec(T, power) + +/obj + var/explosion_resistance + +/datum/explosion_turf + var/turf/turf //The turf which will get ex_act called on it + var/max_power //The largest amount of power the turf sustained + + New() + ..() + max_power = 0 + + proc/save_power_if_larger(power) + if(power > max_power) + max_power = power + return 1 + return 0 + +var/list/datum/explosion_turf/explosion_turfs = list() +var/explosion_in_progress = 0 + +proc/get_explosion_turf(var/turf/T) + for( var/datum/explosion_turf/ET in explosion_turfs ) + if( T == ET.turf ) + return ET + var/datum/explosion_turf/ET = new() + ET.turf = T + explosion_turfs += ET + return ET + +proc/explosion_rec(turf/epicenter, power) + + + var/loopbreak = 0 + while(explosion_in_progress) + if(loopbreak >= 15) return + sleep(10) + loopbreak++ + + if(power <= 0) return + epicenter = get_turf(epicenter) + if(!epicenter) return + + message_admins("Explosion with size ([power]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)") + log_game("Explosion with size ([power]) in area [epicenter.loc.name] ") + + playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(power*2,1) ) + playsound(epicenter, "explosion", 100, 1, round(power,1) ) + + explosion_in_progress = 1 + explosion_turfs = list() + var/datum/explosion_turf/ETE = get_explosion_turf() + ETE.turf = epicenter + ETE.max_power = power + + //This steap handles the gathering of turfs which will be ex_act() -ed in the next step. It also ensures each turf gets the maximum possible amount of power dealt to it. + for(var/direction in cardinal) + var/turf/T = get_step(epicenter, direction) + T.explosion_spread(power - epicenter.explosion_resistance, direction) + + //This step applies the ex_act effects for the explosion, as planned in the previous step. + for( var/datum/explosion_turf/ET in explosion_turfs ) + if(ET.max_power <= 0) continue + if(!ET.turf) continue + + //Wow severity looks confusing to calculate... Fret not, I didn't leave you with any additional instructions or help. (just kidding, see the line under the calculation) + var/severity = 4 - round(max(min( 3, ((ET.max_power - ET.turf.explosion_resistance) / (max(3,(power/3)))) ) ,1), 1) + //sanity effective power on tile divided by either 3 or one third the total explosion power + // One third because there are three power levels and I + // want each one to take up a third of the crater + var/x = ET.turf.x + var/y = ET.turf.y + var/z = ET.turf.z + ET.turf.ex_act(severity) + if(!ET.turf) + ET.turf = locate(x,y,z) + for( var/atom/A in ET.turf ) + A.ex_act(severity) + + explosion_in_progress = 0 + +/turf + var/explosion_resistance + +/turf/space + explosion_resistance = 10 + +/turf/simulated/floor + explosion_resistance = 1 + +/turf/unsimulated/mineral + explosion_resistance = 2 + +/turf/simulated/shuttle/floor + explosion_resistance = 1 + +/turf/simulated/shuttle/floor4 + explosion_resistance = 1 + +/turf/simulated/shuttle/plating + explosion_resistance = 1 + +/turf/simulated/shuttle/wall + explosion_resistance = 5 + +/turf/simulated/wall + explosion_resistance = 5 + +/turf/simulated/wall/r_wall + explosion_resistance = 25 + +/turf/simulated/wall/invulnerable + + +//Code-wise, a safe value for power is something up to ~25 or ~30.. This does quite a bit of damage to the station. +//direction is the direction that the spread took to come to this tile. So it is pointing in the main blast direction - meaning where this tile should spread most of it's force. +/turf/proc/explosion_spread(power, direction) + if(power <= 0) + return + + /* + sleep(2) + new/obj/effect/debugging/marker(src) + */ + + var/datum/explosion_turf/ET = get_explosion_turf(src) + if(ET.max_power >= power) + return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again. + ET.max_power = power + + var/spread_power = power - src.explosion_resistance //This is the amount of power that will be spread to the tile in the direction of the blast + var/side_spread_power = power - 2 * src.explosion_resistance //This is the amount of power that will be spread to the side tiles + for(var/obj/O in src) + if(O.explosion_resistance) + spread_power -= O.explosion_resistance + side_spread_power -= O.explosion_resistance + + var/turf/T = get_step(src, direction) + T.explosion_spread(spread_power, direction) + T = get_step(src, turn(direction,90)) + T.explosion_spread(side_spread_power, turn(direction,90)) + T = get_step(src, turn(direction,-90)) + T.explosion_spread(side_spread_power, turn(direction,90)) + + /* + for(var/direction in cardinal) + var/turf/T = get_step(src, direction) + T.explosion_spread(spread_power) + */ + +/turf/unsimulated/explosion_spread(power) return //So it doesn't get to the parent proc, which simulates explosions \ No newline at end of file diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 757753756e3..065fc4cc827 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -1,133 +1,133 @@ -//Also contains /obj/structure/closet/body_bag because I doubt anyone would think to look for bodybags in /object/structures - -/obj/item/bodybag - name = "body bag" - desc = "A folded bag designed for the storage and transportation of cadavers." - icon = 'icons/obj/bodybag.dmi' - icon_state = "bodybag_folded" - -/obj/item/bodybag/attack_self(mob/user) - var/obj/structure/closet/body_bag/R = new /obj/structure/closet/body_bag(user.loc) - R.add_fingerprint(user) - qdel(src) - - -/obj/item/weapon/storage/box/bodybags - name = "body bag kit" - desc = "A kit specifically designed to fit bodybags." - icon_state = "bodybags" //Consider respriting this to a kit some day - max_w_class = 3 - max_combined_w_class = 21 - can_hold = list("/obj/item/bodybag") //Needed due to the last two variables, figures - -/obj/item/weapon/storage/box/bodybags/New() - ..() - new /obj/item/bodybag(src) - new /obj/item/bodybag(src) - new /obj/item/bodybag(src) - new /obj/item/bodybag(src) - new /obj/item/bodybag(src) - new /obj/item/bodybag(src) - new /obj/item/bodybag(src) - - -/obj/structure/closet/body_bag - name = "body bag" - desc = "A plastic bag designed for the storage and transportation of cadavers." - icon = 'icons/obj/bodybag.dmi' - icon_state = "bodybag_closed" - icon_closed = "bodybag_closed" - icon_opened = "bodybag_open" - density = 0 - - -/obj/structure/closet/body_bag/attackby(W as obj, mob/user as mob) - if(istype(W,/obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/S = W - if(S.amount<5) return - S.use(5) - new /obj/structure/morgue(src.loc) - qdel(src) - if(istype(W, /obj/item/weapon/pen)) - var/t = copytext(sanitize(input(user, "What would you like the label to be?", text("[]", src.name), null) as text|null), 1, MAX_NAME_LEN) - if(user.get_active_hand() != W) - return - if (!Adjacent(user) || user.stat) - return - t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - src.name = "body bag" - if(t) - src.name += " ([t])" - src.overlays += image(src.icon, "bodybag_label") - return - else if(istype(W, /obj/item/weapon/wirecutters)) +//Also contains /obj/structure/closet/body_bag because I doubt anyone would think to look for bodybags in /object/structures + +/obj/item/bodybag + name = "body bag" + desc = "A folded bag designed for the storage and transportation of cadavers." + icon = 'icons/obj/bodybag.dmi' + icon_state = "bodybag_folded" + +/obj/item/bodybag/attack_self(mob/user) + var/obj/structure/closet/body_bag/R = new /obj/structure/closet/body_bag(user.loc) + R.add_fingerprint(user) + qdel(src) + + +/obj/item/weapon/storage/box/bodybags + name = "body bag kit" + desc = "A kit specifically designed to fit bodybags." + icon_state = "bodybags" //Consider respriting this to a kit some day + max_w_class = 3 + max_combined_w_class = 21 + can_hold = list("/obj/item/bodybag") //Needed due to the last two variables, figures + +/obj/item/weapon/storage/box/bodybags/New() + ..() + new /obj/item/bodybag(src) + new /obj/item/bodybag(src) + new /obj/item/bodybag(src) + new /obj/item/bodybag(src) + new /obj/item/bodybag(src) + new /obj/item/bodybag(src) + new /obj/item/bodybag(src) + + +/obj/structure/closet/body_bag + name = "body bag" + desc = "A plastic bag designed for the storage and transportation of cadavers." + icon = 'icons/obj/bodybag.dmi' + icon_state = "bodybag_closed" + icon_closed = "bodybag_closed" + icon_opened = "bodybag_open" + density = 0 + + +/obj/structure/closet/body_bag/attackby(W as obj, mob/user as mob) + if(istype(W,/obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/S = W + if(S.amount<5) return + S.use(5) + new /obj/structure/morgue(src.loc) + qdel(src) + if(istype(W, /obj/item/weapon/pen)) + var/t = copytext(sanitize(input(user, "What would you like the label to be?", text("[]", src.name), null) as text|null), 1, MAX_NAME_LEN) + if(user.get_active_hand() != W) + return + if (!Adjacent(user) || user.stat) + return + t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + src.name = "body bag" + if(t) + src.name += " ([t])" + src.overlays += image(src.icon, "bodybag_label") + return + else if(istype(W, /obj/item/weapon/wirecutters)) to_chat(user, "You cut the tag off the bodybag") - src.name = "body bag" - src.overlays.len = 0 - return - - -/obj/structure/closet/body_bag/close() - if(..()) - density = 0 - return 1 - return 0 - - -/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location) - ..() - if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) - if(!ishuman(usr)) return - if(opened) return 0 - if(contents.len) return 0 - visible_message("[usr] folds up the [src.name]") - new/obj/item/bodybag(get_turf(src)) - spawn(0) - qdel(src) - return - -/obj/structure/closet/body_bag/update_icon() - if(!opened) - icon_state = icon_closed - else - icon_state = icon_opened - -//Cryobag (statis bag) below, not currently functional it seems - -/obj/item/bodybag/cryobag - name = "stasis bag" - desc = "A folded, non-reusable bag designed for the preservation of an occupant's brain by stasis." - icon = 'icons/obj/cryobag.dmi' - icon_state = "bodybag_folded" - -/obj/item/bodybag/cryobag/attack_self(mob/user) - var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc) - R.add_fingerprint(user) - qdel(src) - -/obj/structure/closet/body_bag/cryobag - name = "stasis bag" - desc = "A non-reusable plastic bag designed for the preservation of an occupant's brain by stasis." - icon = 'icons/obj/cryobag.dmi' - icon_state = "bodybag_closed" - icon_closed = "bodybag_closed" - icon_opened = "bodybag_open" - density = 0 - - var/used = 0 - -/obj/structure/closet/body_bag/cryobag/open() - . = ..() - if(used) - var/obj/item/O = new/obj/item(src.loc) - O.name = "used stasis bag" - O.icon = src.icon - O.icon_state = "bodybag_used" - O.desc = "Pretty useless now.." - qdel(src) - -/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location) - if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) - if(!ishuman(usr)) return + src.name = "body bag" + src.overlays.len = 0 + return + + +/obj/structure/closet/body_bag/close() + if(..()) + density = 0 + return 1 + return 0 + + +/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location) + ..() + if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) + if(!ishuman(usr)) return + if(opened) return 0 + if(contents.len) return 0 + visible_message("[usr] folds up the [src.name]") + new/obj/item/bodybag(get_turf(src)) + spawn(0) + qdel(src) + return + +/obj/structure/closet/body_bag/update_icon() + if(!opened) + icon_state = icon_closed + else + icon_state = icon_opened + +//Cryobag (statis bag) below, not currently functional it seems + +/obj/item/bodybag/cryobag + name = "stasis bag" + desc = "A folded, non-reusable bag designed for the preservation of an occupant's brain by stasis." + icon = 'icons/obj/cryobag.dmi' + icon_state = "bodybag_folded" + +/obj/item/bodybag/cryobag/attack_self(mob/user) + var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc) + R.add_fingerprint(user) + qdel(src) + +/obj/structure/closet/body_bag/cryobag + name = "stasis bag" + desc = "A non-reusable plastic bag designed for the preservation of an occupant's brain by stasis." + icon = 'icons/obj/cryobag.dmi' + icon_state = "bodybag_closed" + icon_closed = "bodybag_closed" + icon_opened = "bodybag_open" + density = 0 + + var/used = 0 + +/obj/structure/closet/body_bag/cryobag/open() + . = ..() + if(used) + var/obj/item/O = new/obj/item(src.loc) + O.name = "used stasis bag" + O.icon = src.icon + O.icon_state = "bodybag_used" + O.desc = "Pretty useless now.." + qdel(src) + +/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location) + if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) + if(!ishuman(usr)) return to_chat(usr, "You can't fold that up anymore..") ..() diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm index 39d7dcb65d4..93c66d15ef4 100644 --- a/code/game/objects/items/candle.dm +++ b/code/game/objects/items/candle.dm @@ -1,65 +1,65 @@ -/obj/item/candle - name = "red candle" - desc = "A candle made out of wax, used for moody lighting and solar flares" - icon = 'icons/obj/candle.dmi' - icon_state = "candle1" - item_state = "candle1" - w_class = 1 - heat_production = 1000 - light_color = LIGHT_COLOR_FIRE - - var/wax = 200 - var/lit = 0 - var/flavor_text - -/obj/item/candle/update_icon() - var/i - if(wax > 150) - i = 1 - else if(wax > 80) - i = 2 - else i = 3 - icon_state = "candle[i][lit ? "_lit" : ""]" - -/obj/item/candle/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(W.is_hot()) - light("[user] lights [src] with [W].") - -/obj/item/candle/proc/light(var/flavor_text = "[usr] lights [src].") - if(!src.lit) - src.lit = 1 - visible_message(flavor_text) - set_light(CANDLE_LUM) - processing_objects.Add(src) - -/obj/item/candle/process() - if(!lit) - return - wax-- - if(!wax) - new/obj/item/trash/candle(src.loc) - if(istype(src.loc, /mob)) - src.dropped() - qdel(src) - return - update_icon() - if(istype(loc, /turf)) //Start a fire if possible - var/turf/T = loc - T.hotspot_expose(700, 5, surfaces = 0) - -/obj/item/candle/attack_self(mob/user as mob) - if(lit) - lit = 0 - update_icon() - set_light(0) - -/obj/item/candle/is_hot() - if(lit) - return heat_production - return 0 - -/obj/item/weapon/match/is_hot() - if(lit) - return heat_production - return 0 +/obj/item/candle + name = "red candle" + desc = "A candle made out of wax, used for moody lighting and solar flares" + icon = 'icons/obj/candle.dmi' + icon_state = "candle1" + item_state = "candle1" + w_class = 1 + heat_production = 1000 + light_color = LIGHT_COLOR_FIRE + + var/wax = 200 + var/lit = 0 + var/flavor_text + +/obj/item/candle/update_icon() + var/i + if(wax > 150) + i = 1 + else if(wax > 80) + i = 2 + else i = 3 + icon_state = "candle[i][lit ? "_lit" : ""]" + +/obj/item/candle/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(W.is_hot()) + light("[user] lights [src] with [W].") + +/obj/item/candle/proc/light(var/flavor_text = "[usr] lights [src].") + if(!src.lit) + src.lit = 1 + visible_message(flavor_text) + set_light(CANDLE_LUM) + processing_objects.Add(src) + +/obj/item/candle/process() + if(!lit) + return + wax-- + if(!wax) + new/obj/item/trash/candle(src.loc) + if(istype(src.loc, /mob)) + src.dropped() + qdel(src) + return + update_icon() + if(istype(loc, /turf)) //Start a fire if possible + var/turf/T = loc + T.hotspot_expose(700, 5, surfaces = 0) + +/obj/item/candle/attack_self(mob/user as mob) + if(lit) + lit = 0 + update_icon() + set_light(0) + +/obj/item/candle/is_hot() + if(lit) + return heat_production + return 0 + +/obj/item/weapon/match/is_hot() + if(lit) + return heat_production + return 0 diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 2ff46709939..58d8b95f688 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1,2403 +1,2403 @@ -#define MAX_DESIGNS 10 - -//The advanced pea-green monochrome lcd of tomorrow. - -var/global/list/obj/item/device/pda/PDAs = list() - - -/obj/item/device/pda - name = "\improper PDA" - desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge. Can download additional applications from PDA terminals." - icon = 'icons/obj/pda.dmi' - icon_state = "pda" - item_state = "electronic" - w_class = 1.0 - flags = FPRINT - slot_flags = SLOT_ID | SLOT_BELT - - //Main variables - var/owner = null - var/default_cartridge = 0 // Access level defined by cartridge - var/obj/item/weapon/cartridge/cartridge = null //current cartridge - var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge. - - //Secondary variables - var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner, 4 is halogen counter, 5 is gas scanner, 6 is device analyser -- keep this list updated if you add one - var/fon = 0 //Is the flashlight function on? - var/f_lum = 2 //Luminosity for the flashlight function - var/silent = 0 //To beep or not to beep, that is the question - var/toff = 0 //If 1, messenger disabled - var/tnote = null //Current Texts - var/last_text //No text spamming - var/last_honk //Also no honk spamming that's bad too - var/ttone = "beep" //The ringtone! - var/lock_code = "" // Lockcode to unlock uplink - var/honkamt = 0 //How many honks left when infected with honk.exe - var/mimeamt = 0 //How many silence left when infected with mime.exe - var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant!" //Current note in the notepad function - var/notehtml = "" - var/cart = "" //A place to stick cartridge menu information - var/detonate = 1 // Can the PDA be blown up? - var/hidden = 0 // Is the PDA hidden from the PDA list? - - var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both. - var/ownjob = null //related to above - - var/obj/item/device/paicard/pai = null // A slot for a personal AI device - var/obj/item/device/analyzer/atmos_analys = new - var/obj/item/device/device_analyser/dev_analys = null - - var/MM = null - var/DD = null - - var/list/applications = list() - - var/list/incoming_transactions = list() - - var/list/currentevents1 = list("The Prime Minister of Space Australia has announced today a new policy to hand out fake dollar bills to the poor.", - "The President of Space America issued a press release today stating that he is not in fact, a Tajaran in disguise.", - "The Prime Minister of Space England is in hot water today after he announced that space tea would now be made with 20% more nuclear waste.", - "The Czar of the Space Soviet Union has issued a press release stating 'Spess Amerikans suck cocks!' we're working on a translation.", - "Space Israel has not gotten into trouble for bombing dirty Space Palestine again today. Don't be so anti-semitic.", - "Our sources tell us that the Earth country Poland has issued a press release stating that 'they didn't want to go to space anyway' and that 'space sucks'. More at eleven.", - "Sources are saying that the Earth country Poland has issued another press release saying they were sorry and would very much like to be in space. The Intergalactic Empire responded with the word 'No'.", - "The President of Space America has come under fire recently for stating that god was a chicken.", - "The Intergalactic Empire is in hot water this week after proposing to rename Space-Milk to Milk. The newsroom would like to apologize to any readers offended by this news.", - "The Prime Minister of Space Scotland has announced that 'Freedom Day' did not go as planned. Our sources report that over 2000 human heads are now being returned to their loved ones.", - "The Prime Minister of Space Australia has come under fire for stating 'Women are in the kitchen, men are on the sofa, jews are in the oven. My country is doing well.", - "Dirty Space Palestine just declared Jihad on Mighty Space Israel. For shame, Space Palestine.", - "The President of Space America was questioned today about his reaction to the Space Superstorm Baldman disaster, he replied 'I didn't send anybody since I figured it would quit about three quarters through.", - "The President of Space America was photographed today kicking a dog to death while muttering about how he liked cats better.", - "The President of Space America was photographed today with a fairly obvious tail protruding out of his pants, he denies the photo is real, saying 'I, president T'jkar Aw'krejn, am no Tajaran-- I mean catbeast.", - "The votes have come in, and the new Prime Minister of Space Uzbekistan is Kthchichikachi Breekikikiki. When questioned about his landslide victory, he replied 'SQAAAAAAAK'. His only opponent, Er'p Fh'goot, was the first openly gay catbeast to run for office.", - "The President of Space America has issued a press release asking for more chips in his office.", - "The Prime Minister of Space Uzbekistan has issued a press release, stating that 'SQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK BAWWK BAAWWWWKK'. We would like to say that Faux News does not condone or support the words of Mr. Breekikikiki.", - "The Prime Minister of Space Australia has come under fire for stating he was very upset with how many black people there was in his country.", - "The Czar of Space Russia has accused the President of Space America of being a dirty catbeast. The President wiggled his trademark ears and said that if he was a Tajaran, the Czar was a space shark. The President is being treated for bite wounds.", - "The 'Universes Largest Oven' has been completed today in Space Germany. Prime Minister Adole Himmler has invited Space Isreal to see the oven first at its grand opening." - ) - var/list/currentevents2 = list("CEO Discount Dan has been sued. Again.", - "NanoTrasen has inducted a new policy wherein clowns will be spanked for stealing milk.", - "Discount Dan's has created a new line of Discountu Danu food product for Space Japan. The food is comprised of Space Carp on rice. More at ten.", - "Discount Dan's has come under fire for their new 'Horsemeat Lasagna'", - "NanoTrasen's official website has been hacked this morning. The site read 'NT SUXZ, GO SYNDIEKATTZ!!1!1!!' for 48 hours until the site was fixed.", - "Read the all new book by a former unnamed syndicate, 'NanoTrasen sucks but the dental is good so whatever.'", - "NanoTrasen has released a new study that has been made useless by the internet.", - "Discount Dan's 'Spooky Dan' line of product has come under fire for being unintentionally racist toward ghosts.", - "Discount Dan's 'Discounto Danito' line of product has come out with a new 'fiesta size' burrito. CEO Discount Dan has been quoted as saying, 'A big 'ol clot for a big 'ol family!'", - "The Syndicate has issued a press release stating that 'NanoTrasen sucks dicks.'", - "NanoTrasen CEO Johnson Lovelocker has been photographed kicking a Tajaran to death. This shameful publicity stunt is part of the new 'NT Hates Catbeasts, do you?' campaign.", - "NanoTrasen CEO Johnson Lovelocker has been photographed kicking a Vox in the cloaca. He commented that, 'BIRDS BELONG IN MY FUCKING MEALS DAMN IT'.", - "NanoTrasen CEO Johnson Lovelocker is in hot water for an alleged sex scandal with a confused syndicate woman that took the motto 'Fuck NT' too seriously.", - "NanoTrasen CEO Johnson Lovelocker issued a press release stating, 'Anybody who's fucking impersonating me is going to get fucking bluespaced unto a spike.'. We do not condone Lovelocker's use of foul language in the newsroom.", - "NanoTrasen CEO Johnson Lovelocker and Discount Dan's CEO Discount Dan have been photographed buying a new friend necklace. The Syndicate issued a statement that 'That's totally gay.'", - "Discount Dan has been photographed this evening hunting the endangered albino space panda. When questioned, he replied that the endangered animal was 'Good eats'.", - "NanoTrasen's head programmer quit this evening when people did not respond well to his new features on NTOS. Said features included the ability to instantly transmit pictures of your butt to people by blinking.", - "NanoTrasen CEO Johnson Lovelocker was photographed this morning celebrating his birthday will well deserved hookers and blow.", - "Discount Dan's stock has risen 20 points today after CEO Discount Dan promised to include a free toy in every 'Happy Dan' meal. In other news, we have over 300 confirmed reports of broken teeth and lead poisoning in children 6 and under.", - "Discount Dan has come under fire today after trying to hug a plasmaman whilst smoking a cigar. He is being treated for 3rd degree burns at the moment, and we at the newsroom wish him luck.", - "NanoTrasen's treasurer Shlomo Goldburginstein died today in a tragic cooking incident with NT Officer Gass Judenraigh." - ) - var/list/currentevents3 = list("Border patrol around Space America has tightened today after a wave of Tajarans yiffed their way across. We have reports of over 2000 molested Space Americans. More to come at seven.", - "Tajarans continue to protest in their 'Trillion Fur March' today. We have reports that the Space American army is giving a KOS order on all non-humans in the area.", - "Read the all new book by known Plasmaman rights activist Spookler Boney, 'AGHGHHGHGH KILL ME IT BURNS AGHHHHHHH'", - "Read the all new book by the worlds most renown skeleton Johnny Hips, 'It aint easy, being bony.'", - "Scientists in Space Austria have found a chicken with the ability to warp space-time. More at ten.", - "Scientists working on at the Bluespace Portal Research Facility (BPRF), have looked into the fabric of reality. They report that all it is out there is a bunch of fat nerds and a chicken.", - "Scientists working at the Large Hadron Collider have discovered nothing today. A sceptical scientist was quoted as saying, 'It could be nothing, but it's probably just something again.'", - "Johnny Hips has released a new album today, 'Tibia Blues'. The songs include classics such as 'I aint got money for milk.', 'Skeleton Rock', and a new song named, 'Bone Marrow'.", - "Doctors have discovered that clowns indeed do have a funny bone.", - "Renowned mime scientist Free Shrugs has discovered a new element today. He has named it ' ', he also says that it has the properties of ' '.", - "Archaeologists have discovered god's final message to his creation today. The message reads, 'bawk'.", - "Scientists have discovered a new type of elementary particle today. Our sources say it has a bad atitude, and enjoys the color blue.", - "Today, a man was discovered to be living with a 20 year old ghost in his house. When the ghost was questioned who killed him, he responded 'A FAGGOT!'. More at four.", - "Scientists report that ghosts do in fact exist, however, they are huge assholes.", - "Supermatter researchers today have reported that the substance is highly volatile and could possibly rip apart the universe in large quantities. Discount Dan has been reported as ordering over 1000 pounds of supermatter shards.", - "Scientists working at the BPRF have discovered a pocket universe comprised fully of dead clown souls today. 40 scientists are being treated for madness." - ) - var/list/history = list("Adolf Hitler's cyborg body was lain to rest after the ending of WW4.", - "World War Buttbot began, the following war claimed the asses of over 500000 young gentlemen.", - "The 54th President of the United States of Space America was shot in the dick. He succumbed to his injuries after medbay threw him in cryo for an entire day.", - "The first great zombie apocalypse began on Venus.", - "The first man to step on Pluto slipped and was impaled on an ice spike shortly after landing.", - "North Korea became the first country to land a rocket on the sun.", - "Kim Jong Long Dong Silver, 58th generation leader of North Korea, died after being shot seventy two times in the chest.", - "NanoTrasen's new 'Space Station 13' project was announced.", - "Jupiter and Neptune became sentient for a period of 78 hours, Jupiter was heard screaming 'WHY AM I ALIVE DEAR GOD.', whilst curiously, Neptune only said 'Well here we go again.'.", - "The first furry in space was thrown out an airlock, along with his fursuit.", - "The 89th President of Space America read Woody's Got Wood aloud in his first State of the Union, and was beaten to death shortly after.", - "Space France surrendered for the 10124th time, making it the most invaded country in the galaxy.", - "Our glorious leader Karl Pilkington the 24th was crowned emperor of the Intergalactic Human Empire.", - "Everyone in the universe said 'Dave sucks.' at the same time. The cause of this event was unknown, but over 200000 men named Dave were murdered.", - "A cult religion following the belief god was a chicken was created.", - ) - var/list/facts = list("If you have 3 quarters, 4 dimes, and 4 pennies, you have $1.19. You also have the largest amount of money in coins without being able to make change for a dollar.", - "The numbers '172' can be found on the back of the U.S. $5 dollar bill in the bushes at the base of the Lincoln Memorial.", - "President Kennedy was the fastest random speaker in the world with upwards of 350 words per minute.", - "In the average lifetime, a person will walk the equivalent of 5 times around the equator.", - "Odontophobia is the fear of teeth.", - "The surface area of an average-sized brick is 79 cm squared.", - "According to suicide statistics, Monday is the favoured day for self-destruction.", - "The Neanderthal's brain was bigger than yours is.", - "The pancreas produces Insulin.", - "The word 'lethologica' describes the state of not being able to remember the word you want.", - "Every year about 98% of the atoms in your body are replaced.", - "The international telephone dialing code for Antarctica is 672.", - "Women are 37% more likely to go to a psychiatrist than men are.", - "The human heart creates enough pressure to squirt blood 30 feet (9 m).", - "When snakes are born with two heads, they fight each other for food.", - "Stressed is Desserts spelled backwards.", - "The word 'nerd' was first coined by Dr. Seuss in 'If I Ran the Zoo.'", - "Revolvers cannot be silenced because of all the noisy gasses which escape the cylinder gap at the rear of the barrel.", - "Every human spent about half an hour as a single cell.", - "7.5 million toothpicks can be created from a cord of wood.", - "If the Earth's sun were just inch in diameter, the nearest star would be 445 miles away.", - "There is no word in the English language that rhymes with month, orange, silver or purple.", - "Starfish have no brains.", - "2 and 5 are the only prime numbers that end in 2 or 5.", - "'Pronunciation' is the word which is mispronounced the most in the English language.", - "Women blink nearly twice as much as men.", - "Owls are the only birds who can see the color blue.", - "A pizza that has radius 'z' and height 'a' has volume Pi × z × z × a.", - "Months that begin on a Sunday will always have a 'Friday the 13th.'", - "Zero is an even number.", - "The longest English word that can be spelled without repeating any letters is 'uncopyrightable'.", - "10! (Ten factorial) seconds equals exactly six Earth weeks.", - "Want to remember the first digits of Pi easily? You can do it by counting each word's letters in 'May I have a large container of plasma?'" - ) - var/currentevent1 = null - var/currentevent2 = null - var/currentevent3 = null - var/onthisday = null - var/didyouknow = null - - -/obj/item/device/pda/New() - ..() - var/datum/pda_app/balance_check/app = new /datum/pda_app/balance_check() - app.onInstall(src) - -/obj/item/device/pda/medical - name = "Medical PDA" - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-m" - -/obj/item/device/pda/medical/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_medbay - -/obj/item/device/pda/viro - name = "Virology PDA" - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-v" - -/obj/item/device/pda/viro/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_medbay - -/obj/item/device/pda/engineering - name = "Engineering PDA" - default_cartridge = /obj/item/weapon/cartridge/engineering - icon_state = "pda-e" - -/obj/item/device/pda/security - name = "Security PDA" - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-s" - -/obj/item/device/pda/security/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_brig - -/obj/item/device/pda/detective - name = "Detective PDA" - default_cartridge = /obj/item/weapon/cartridge/detective - icon_state = "pda-det" - -/obj/item/device/pda/detective/New() - ..() - var/datum/pda_app/light_upgrade/app = new /datum/pda_app/light_upgrade() - app.onInstall(src) - -/obj/item/device/pda/warden - name = "Warden PDA" - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-warden" - -/obj/item/device/pda/warden/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_brig - -/obj/item/device/pda/janitor - name = "Janitor PDA" - default_cartridge = /obj/item/weapon/cartridge/janitor - icon_state = "pda-j" - ttone = "slip" - -/obj/item/device/pda/toxins - name = "Science PDA" - default_cartridge = /obj/item/weapon/cartridge/signal/toxins - icon_state = "pda-tox" - ttone = "boom" - -/obj/item/device/pda/toxins/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_rnd - -/obj/item/device/pda/clown - name = "Clown PDA" - default_cartridge = /obj/item/weapon/cartridge/clown - icon_state = "pda-clown" - desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings." - ttone = "honk" - -/obj/item/device/pda/mime - name = "Mime PDA" - default_cartridge = /obj/item/weapon/cartridge/mime - icon_state = "pda-mime" - silent = 1 - ttone = "silence" - -/obj/item/device/pda/heads - name = "Head of department PDA" - default_cartridge = /obj/item/weapon/cartridge/head - icon_state = "pda-h" - -/obj/item/device/pda/heads/hop - name = "Head of Personnel PDA" - default_cartridge = /obj/item/weapon/cartridge/hop - icon_state = "pda-hop" - -/obj/item/device/pda/heads/hop/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_hop - -/obj/item/device/pda/heads/hos - name = "Head of Security PDA" - default_cartridge = /obj/item/weapon/cartridge/hos - icon_state = "pda-hos" - -/obj/item/device/pda/heads/hos/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_brig - -/obj/item/device/pda/heads/ce - name = "Chief Engineer PDA" - default_cartridge = /obj/item/weapon/cartridge/ce - icon_state = "pda-ce" - -/obj/item/device/pda/heads/cmo - name = "Chief Medical Officer PDA" - default_cartridge = /obj/item/weapon/cartridge/cmo - icon_state = "pda-cmo" - -/obj/item/device/pda/heads/cmo/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_medbay - -/obj/item/device/pda/heads/rd - name = "Research Director PDA" - default_cartridge = /obj/item/weapon/cartridge/rd - icon_state = "pda-rd" - -/obj/item/device/pda/heads/rd/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_rnd - -/obj/item/device/pda/captain - name = "Captain PDA" - default_cartridge = /obj/item/weapon/cartridge/captain - icon_state = "pda-c" - detonate = 0 - //toff = 1 - -/obj/item/device/pda/captain/New() - ..() - for(var/app_type in (typesof(/datum/pda_app) - /datum/pda_app)) //yes, the captain is such a baller that his PDA has all the apps by default. - var/datum/pda_app/app = new app_type() //will have to edit that when emagged/hidden apps get added. - app.onInstall(src) - -/obj/item/device/pda/cargo - name = "Cargo PDA" - default_cartridge = /obj/item/weapon/cartridge/quartermaster - icon_state = "pda-cargo" - -/obj/item/device/pda/cargo/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_cargo - -/obj/item/device/pda/quartermaster - name = "Quartermaster PDA" - default_cartridge = /obj/item/weapon/cartridge/quartermaster - icon_state = "pda-q" - -/obj/item/device/pda/quartermaster/New() - ..() - var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() - app.onInstall(src) - app.frequency = deskbell_freq_cargo - -/obj/item/device/pda/shaftminer - name = "Mining PDA" - icon_state = "pda-miner" - -/obj/item/device/pda/syndicate - default_cartridge = /obj/item/weapon/cartridge/syndicate - icon_state = "pda-syn" - name = "Military PDA" - owner = "John Doe" - hidden = 1 - -/obj/item/device/pda/chaplain - name = "Chaplain PDA" - icon_state = "pda-holy" - ttone = "holy" - -/obj/item/device/pda/lawyer - name = "Lawyer PDA" - default_cartridge = /obj/item/weapon/cartridge/lawyer - icon_state = "pda-lawyer" - ttone = "..." - -/obj/item/device/pda/botanist - name = "Botany PDA" - //default_cartridge = /obj/item/weapon/cartridge/botanist - icon_state = "pda-hydro" - -/obj/item/device/pda/roboticist - name = "Robotics PDA" - icon_state = "pda-robot" - -/obj/item/device/pda/librarian - name = "Librarian PDA" - icon_state = "pda-libb" - desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader." - note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!" - silent = 1 //Quiet in the library! - -/obj/item/device/pda/clear - icon_state = "pda-transp" - desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case." - note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!" - -/obj/item/device/pda/chef - name = "Chef PDA" - default_cartridge = /obj/item/weapon/cartridge/chef - icon_state = "pda-chef" - -/obj/item/device/pda/bar - name = "Bartender PDA" - icon_state = "pda-bar" - -/obj/item/device/pda/atmos - name = "Atmospherics PDA" - default_cartridge = /obj/item/weapon/cartridge/atmos - icon_state = "pda-atmo" - -/obj/item/device/pda/mechanic - name = "Mechanic PDA" - default_cartridge = /obj/item/weapon/cartridge/mechanic - icon_state = "pda-atmo" - -/obj/item/device/pda/chemist - name = "Chemistry PDA" - default_cartridge = /obj/item/weapon/cartridge/chemistry - icon_state = "pda-chem" - -/obj/item/device/pda/geneticist - name = "Genetics PDA" - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-gene" - - -// Special AI/pAI PDAs that cannot explode. -/obj/item/device/pda/ai - icon_state = "NONE" - ttone = "data" - detonate = 0 - -/obj/item/device/pda/ai/New() - ..() - var/datum/pda_app/spam_filter/app = new /datum/pda_app/spam_filter() - app.onInstall(src) - - -/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text) - owner = newname - ownjob = newjob - name = newname + " (" + ownjob + ")" - - -//AI verb and proc for sending PDA messages. -/mob/living/silicon/ai/proc/cmd_send_pdamesg() - var/list/names = list() - var/list/plist = list() - var/list/namecounts = list() - - if(usr.stat == 2) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - - if(src.aiPDA.toff) - to_chat(usr, "Turn on your receiver in order to send messages.") - return - - for (var/obj/item/device/pda/P in get_viewable_pdas()) - if (P == src) - continue - else if (P == src.aiPDA) - continue - - var/name = P.owner - if (name in names) - namecounts[name]++ - name = text("[name] ([namecounts[name]])") - else - names.Add(name) - namecounts[name] = 1 - - plist[text("[name]")] = P - - var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) - - if (!c) - return - - var/selected = plist[c] - src.aiPDA.create_message(src, selected) - -//AI verb and proc for sending PDA messages. -/obj/item/device/pda/ai/verb/cmd_send_pdamesg() - set category = "AI Commands" - set name = "Send Message" - set src in usr - if(usr.isDead()) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - var/list/plist = available_pdas() - if (plist) - var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) - if (!c) // if the user hasn't selected a PDA file we can't send a message - return - var/selected = plist[c] - create_message(usr, selected) - - -/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver() - set category = "AI Commands" - set name = "Toggle Sender/Receiver" - set src in usr - if(usr.isDead()) - to_chat(usr, "You can't do that because you are dead!") - return - toff = !toff - to_chat(usr, "PDA sender/receiver toggled [(toff ? "Off" : "On")]!") - - -/obj/item/device/pda/ai/verb/cmd_toggle_pda_silent() - set category = "AI Commands" - set name = "Toggle Ringer" - set src in usr - if(usr.isDead()) - to_chat(usr, "You can't do that because you are dead!") - return - silent=!silent - to_chat(usr, "PDA ringer toggled [(silent ? "Off" : "On")]!") - - -/obj/item/device/pda/ai/verb/cmd_show_message_log() - set category = "AI Commands" - set name = "Show Message Log" - set src in usr - if(usr.isDead()) - to_chat(usr, "You can't do that because you are dead!") - return - var/HTML = "AI PDA Message Log[tnote]" - usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") - -/mob/living/silicon/ai/proc/cmd_show_message_log() - if(usr.isDead()) - to_chat(usr, "You can't do that because you are dead!") - return - if(!isnull(aiPDA)) - var/HTML = "AI PDA Message Log[aiPDA.tnote]" - usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") - else - to_chat(usr, "You do not have a PDA. You should make an issue report about this.") - -/obj/item/device/pda/ai/attack_self(mob/user as mob) - if ((honkamt > 0) && (prob(60)))//For clown virus. - honkamt-- - playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - return - - -/obj/item/device/pda/ai/pai - ttone = "assist" - - -/* - * The Actual PDA - */ - -/obj/item/device/pda/New() - ..() - PDAs += src - if(default_cartridge) - cartridge = new default_cartridge(src) - new /obj/item/weapon/pen(src) - MM = text2num(time2text(world.timeofday, "MM")) // get the current month - DD = text2num(time2text(world.timeofday, "DD")) // get the day - currentevent1 = pick(currentevents1) - currentevent2 = pick(currentevents2) - currentevent3 = pick(currentevents3) - onthisday = pick(history) - didyouknow = pick(facts) - -/obj/item/device/pda/proc/can_use(mob/user) - if(user && ismob(user)) - if(user.stat || user.restrained() || user.paralysis || user.stunned || user.weakened) - return 0 - if(loc == user) - return 1 - return 0 - -/obj/item/device/pda/GetAccess() - if(id) - return id.GetAccess() - else - return ..() - -/obj/item/device/pda/GetID() - return id - -/obj/item/device/pda/MouseDrop(obj/over_object as obj, src_location, over_location) - var/mob/M = usr - if((!istype(over_object, /obj/screen)) && can_use(M)) - return attack_self(M) - return - -//NOTE: graphic resources are loaded on client login -/obj/item/device/pda/attack_self(mob/user as mob) - - user.set_machine(src) - - if(active_uplink_check(user)) - return - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:313: var/dat = "Personal Data Assistant" - var/dat = {"Personal Data Assistant - Close"} - // END AUTOFIX - if ((!isnull(cartridge)) && (mode == 0)) - dat += " | Eject [cartridge]" - if (mode) - dat += " | Return" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:321: dat += " | Refresh" - dat += {"| Refresh -
                      "} - // END AUTOFIX - if (!owner) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:326: dat += "Warning: No owner information entered. Please swipe card.

                      " - dat += {"Warning: No owner information entered. Please swipe card.

                      - Retry"} - // END AUTOFIX - else - switch (mode) - if (0) - - if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. - var/datum/asset/simple/C = new/datum/asset/simple/pda() - send_asset_list(user.client, C.assets) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:331: dat += "

                      PERSONAL DATA ASSISTANT v.1.3

                      " - dat += {"

                      PERSONAL DATA ASSISTANT v.1.3

                      - Owner: [owner], [ownjob]
                      "} - // END AUTOFIX - dat += text("ID: [id ? "[id.registered_name], [id.assignment]" : "----------"]") - dat += text("
                      [id ? "Update PDA Info" : ""]

                      ") - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:336: dat += "Station Time: [worldtime2text()]"//:[world.time / 100 % 6][world.time / 100 % 10]" - dat += {"Station Time: [worldtime2text()] -

                      -

                      General Functions

                      - " - dat += {"

                      Applications

                      "} - - if(applications.len == 0) - dat += {"No application currently installed."} - else - dat += {"
                        "} - for(var/datum/pda_app/app in applications) - if(app.menu) - dat += {"
                      • [app.icon ? " " : ""][app.name]
                      • "} - else - dat += {"
                      • [app.icon ? " " : ""][app.name]
                      • "} - dat += {"
                      "} - - if (cartridge) - if (cartridge.access_engine || cartridge.access_atmos) - dat += {"

                      Engineering Functions

                      - "} - - if (cartridge.access_mechanic) - dat += {"

                      Mechanic Functions

                      - "} - - if (cartridge.access_medical) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:360: dat += "

                      Medical Functions

                      " - dat += {"

                      Medical Functions

                      - "} - // END AUTOFIX - if (cartridge.access_security) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:366: dat += "

                      Security Functions

                      " - dat += {"

                      Security Functions

                      -
                        -
                      • Security Records
                      • "} - // END AUTOFIX - if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:370: dat += "
                      • Security Bot Access
                      • " - dat += {"
                      • Security Bot Access
                      • -
                      "} - // END AUTOFIX - else dat += "
                    " - if(cartridge.access_quartermaster) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:374: dat += "

                    Quartermaster Functions:

                    " - dat += {"

                    Quartermaster Functions:

                    - "} - // END AUTOFIX - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:379: dat += "
                  " - dat += {"
                -

                Utilities

                - " - - if (1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:407: dat += "

                Notekeeper V2.1

                " - dat += {"

                Notekeeper V2.1

                - Edit
                "} - // END AUTOFIX - dat += note - - if (2) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:412: dat += "

                SpaceMessenger V3.9.4

                " - dat += {"

                SpaceMessenger V3.9.4

                - Ringer: [silent == 1 ? "Off" : "On"] | - Send / Receive: [toff == 1 ? "Off" : "On"] | - Set Ringtone | - Messages
                "} - // END AUTOFIX - if (istype(cartridge, /obj/item/weapon/cartridge/syndicate)) - dat += "[cartridge:shock_charges] detonation charges left.
                " - if (istype(cartridge, /obj/item/weapon/cartridge/clown)) - dat += "[cartridge:honk_charges] viral files left.
                " - if (istype(cartridge, /obj/item/weapon/cartridge/mime)) - dat += "[cartridge:mime_charges] viral files left.
                " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:425: dat += "

                Detected PDAs

                " - dat += {"

                Detected PDAs

                -
                  "} - // END AUTOFIX - var/count = 0 - - if (!toff) - for (var/obj/item/device/pda/P in sortNames(get_viewable_pdas())) - if (P == src) continue - if(P.hidden) continue - dat += "
                • [P]" - if (id && !istype(P,/obj/item/device/pda/ai)) - dat += " (*Send Money*)" - if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate) - dat += " (*Detonate*)" - if (istype(cartridge, /obj/item/weapon/cartridge/clown)) - dat += " (*Send Virus*)" - if (istype(cartridge, /obj/item/weapon/cartridge/mime)) - dat += " (*Send Virus*)" - dat += "
                • " - count++ - dat += "
                " - if (count == 0) - dat += "None detected.
                " - - if(21) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:448: dat += "

                SpaceMessenger V3.9.4

                " - dat += {"

                SpaceMessenger V3.9.4

                - Clear Messages -

                Messages

                "} - // END AUTOFIX - dat += tnote - dat += "
                " - - if (3) - dat += "

                Atmospheric Readings

                " - - var/turf/T = get_turf(user.loc) - if (isnull(T)) - dat += "Unable to obtain a reading.
                " - else - var/datum/gas_mixture/environment = T.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() - - dat += "Air Pressure: [round(pressure,0.1)] kPa
                " - - if (total_moles) - var/o2_level = environment.oxygen/total_moles - var/n2_level = environment.nitrogen/total_moles - var/co2_level = environment.carbon_dioxide/total_moles - var/plasma_level = environment.toxins/total_moles - var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:476: dat += "Nitrogen: [round(n2_level*100)]%
                " - dat += {"Nitrogen: [round(n2_level*100)]%
                - Oxygen: [round(o2_level*100)]%
                - Carbon Dioxide: [round(co2_level*100)]%
                - Plasma: [round(plasma_level*100)]%
                "} - // END AUTOFIX - if(unknown_level > 0.01) - dat += "OTHER: [round(unknown_level)]%
                " - dat += "Temperature: [round(environment.temperature-T0C)]°C
                " - dat += "
                " - - if (5) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:486: dat += "

                Nanotrasen Relay Chat

                " - dat += {"

                Nanotrasen Relay Chat

                -

                Detected Channels

                :
              • "} - // END AUTOFIX - for(var/datum/chatroom/C in chatrooms) - dat += "#[html_encode(lowertext(C.name))]" - if(C.password != "") - dat += " " - dat += "
              • " - - if (41) //Allows everyone to access crew - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:281: menu = "

                Crew Manifest

                " - dat += {"

                Crew Manifest

                - Entries cannot be modified from this terminal.

                "} - // END AUTOFIX - if(data_core) - dat += data_core.get_manifest(1) // make it monochrome - dat += "
                " - - if (50) //Current events. - dat += {"

                Current Events

                - Station Time: [worldtime2text()].
                - Empire Date: [MM]/[DD]/[game_year].

                - Current Events,
                -
              • [currentevent1] -
              • [currentevent2]

              • -
              • [currentevent3]


              • - On this day,
                -
              • [onthisday]


              • - Did you know...
                -
              • [didyouknow]

              • "} - - if (PDA_APP_RINGER) - var/datum/pda_app/ringer/app = locate(/datum/pda_app/ringer) in applications - dat += {"

                Ringer Application

                "} - if(app) - dat += {" - Status:
                [app.status ? "On" : "Off"]
                - Frequency: - - - - - [format_frequency(app.frequency)] - + - +
                -
                - "} - - if (PDA_APP_SPAMFILTER) - var/datum/pda_app/spam_filter/app = locate(/datum/pda_app/spam_filter) in applications - dat += {"

                Spam Filtering Application

                "} - if(app) - dat += {" - - "} - - if (PDA_APP_BALANCECHECK) - var/datum/pda_app/balance_check/app = locate(/datum/pda_app/balance_check) in applications - dat += {"

                Virtual Wallet and Balance Check Application

                "} - if(app) - if(!id) - dat += {"Insert an ID card in the PDA to use this application."} - else - if(!id.virtual_wallet) - id.update_virtual_wallet() - dat += {"
                -
                Virtual Wallet
                - Owner: [id.virtual_wallet.owner_name]
                - Balance: [id.virtual_wallet.money]$ Print Currency -
                Transaction History
                - On [MM]/[DD]/[game_year]: -
                  - "} - var/list/v_log = list() - for(var/e in id.virtual_wallet.transaction_log) - v_log += e - for(var/datum/transaction/T in reverseRange(v_log)) - dat += {"
                • \[[T.time]\] [T.amount]$, [T.purpose] at [T.source_terminal]
                • "} - dat += {"

                "} - if(!(app.linked_db)) - app.reconnect_database() - if(app.linked_db) - if(app.linked_db.activated) - var/datum/money_account/D = app.linked_db.attempt_account_access(id.associated_account_number, 0, 2, 0) - if(D) - dat += {" -
                Bank Account
                - Owner: [D.owner_name]
                - Balance: [D.money]$ -
                Transaction History
                - On [MM]/[DD]/[game_year]: -
                  - "} - var/list/t_log = list() - for(var/e in D.transaction_log) - t_log += e - for(var/datum/transaction/T in reverseRange(t_log)) - if(T.purpose == "Account creation")//always the last element of the reverse transaction_log - dat += {"
                - On [(DD == 1) ? "[((MM-2)%12)+1]" : "[MM]"]/[((DD-2)%30)+1]/[(DD == MM == 1) ? "[game_year - 1]" : "[game_year]"]: -
                  -
                • \[[T.time]\] [T.amount]$, [T.purpose] at [T.source_terminal]
                • -
                "} - else - dat += {"
              • \[[T.time]\] [T.amount]$, [T.purpose] at [T.source_terminal]
              • "} - if(!D.transaction_log.len) - dat += {"
              "} - else - dat += {" -
              Bank Account
              - Unable to access bank account. Either its security settings don't allow remote checking or the account is nonexistent. - "} - else - dat += {" -
              Bank Account
              - Unfortunately your station's Accounts Database doesn't allow remote access. Negociate with your HoP or Captain to solve this issue. - "} - else - dat += {" -
              Bank Account
              - Unable to connect to accounts database. The database is either nonexistent, inoperative, or too far away. - "} - - if (PDA_APP_STATIONMAP) - var/datum/pda_app/station_map/app = locate(/datum/pda_app/station_map) in applications - dat += {"

              Station Map Application

              "} - if(app) - var/turf/T = get_turf(src.loc) - - if(!fexists("icons/pda_icons/pda_minimap_[map.nameShort].png")) - dat += {"It appears that our services have yet to produce a minimap of this station. We apologize for the inconvenience."} - - if(T.z == map.zMainStation) - dat += {"Current Location: [T.loc.name] ([T.x-WORLD_X_OFFSET[map.zMainStation]],[T.y-WORLD_Y_OFFSET[map.zMainStation]],1)
              "} //it's a "Station Map" app, so it only gives information reguarding - else //the station's z-level - dat += {"Current Location: Unknown
              "} - - if(fexists("icons/pda_icons/pda_minimap_[map.nameShort].png")) - dat += {" -
              - - "} - if(T.z == map.zMainStation) - dat += {""} - for(var/datum/minimap_marker/mkr in app.markers) - dat += {""} - dat += {"
              "} - - else - dat += {" -
              - - "} - if(T.z == map.zMainStation) - dat += {""} - for(var/datum/minimap_marker/mkr in app.markers) - dat += {""} - dat += {"
              "} - -/* - dat += {" -
              - - "} - if(T.z == map.zMainStation) - dat += {""} - for(var/datum/minimap_marker/mkr in app.markers) - dat += {""} - - dat += {"
              "} -*/ - dat += {"
              Markers
              - X=[app.markx]; - Y=[app.marky]; - Add New Marker - "} - - if(!(app.markers.len)) - dat += {"
              no markers"} - else - dat +={"
                "} - for(var/datum/minimap_marker/mkr in app.markers) - dat += {"
              • [mkr.name] ([mkr.x]/[mkr.y]) remove
              • "} - dat += {"
              "} - - if (PDA_APP_SNAKEII) - if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. - var/datum/asset/simple/C = new/datum/asset/simple/pda_snake() - send_asset_list(user.client, C.assets) - - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - dat += {"

              Snake II -+

              "} - if(app) - dat += {"
              -
              - - "} - if(!app.ingame) - dat += {""} - dat += {""} - var/list/templist = app.highscores[app.snake_game.level] - var/list/winnerlist = snake_station_highscores[app.snake_game.level] - dat += {""} - dat += {""} - dat += {""} - dat += {""} - dat += {""} - dat += {""} - dat += {""} - dat += {""} - dat += {""} - var/list/snakebestlist = snake_best_players[app.snake_game.level] - dat += "
              (Station Highscore held by [snakebestlist[app.labyrinth+1]])" - dat += "
              Set speed: " - for(var/x=1;x<=9;x++) - if(x == app.snake_game.level) - dat += "[x], " - else - dat += "[x], " - dat += "
              Set labyrinth: [!app.labyrinth ? "None" : "None"], " - for(var/x=1;x<=7;x++) - if(x == app.labyrinth) - dat += "[x], " - else - dat += "[x], " - dat += "
              Gyroscope (orient yourself to control): " - if(app.snake_game.gyroscope) - dat += "ON" - else - dat +="OFF" - else - if(app.labyrinth) - dat += {""} - for(var/datum/snake/body/B in app.snake_game.snakeparts) - var/body_dir = "" - if(B.life == 1) - switch(B.dir) - if(EAST) - body_dir = "pda_snake_bodytail_east" - if(WEST) - body_dir = "pda_snake_bodytail_west" - if(NORTH) - body_dir = "pda_snake_bodytail_north" - if(SOUTH) - body_dir = "pda_snake_bodytail_south" - else if(B.life > 1) - if(B.corner) - switch(B.dir) - if(EAST) - switch(B.corner) - if(SOUTH) - body_dir = "pda_snake_bodycorner_eastsouth2" - if(NORTH) - body_dir = "pda_snake_bodycorner_eastnorth2" - if(WEST) - switch(B.corner) - if(SOUTH) - body_dir = "pda_snake_bodycorner_westsouth2" - if(NORTH) - body_dir = "pda_snake_bodycorner_westnorth2" - if(NORTH) - switch(B.corner) - if(EAST) - body_dir = "pda_snake_bodycorner_eastnorth" - if(WEST) - body_dir = "pda_snake_bodycorner_westnorth" - if(SOUTH) - switch(B.corner) - if(EAST) - body_dir = "pda_snake_bodycorner_eastsouth" - if(WEST) - body_dir = "pda_snake_bodycorner_westsouth" - else - switch(B.dir) - if(EAST) - body_dir = "pda_snake_body_east" - if(WEST) - body_dir = "pda_snake_body_west" - if(NORTH) - body_dir = "pda_snake_body_north" - if(SOUTH) - body_dir = "pda_snake_body_south" - - if(B.isfull) - body_dir += "_full" - if(!B.flicking) - dat += {""} - - dat += {""} - - if(app.snake_game.next_bonus.life > 0) - dat += {""} - dat += {""} - dat += {""} - dat += {""} - - dat += {""} - dat += {""} - dat += {""} - dat += {""} - - var/head_dir = "" - switch(app.snake_game.head.dir) - if(EAST) - head_dir = "pda_snake_head_east" - if(WEST) - head_dir = "pda_snake_head_west" - if(NORTH) - head_dir = "pda_snake_head_north" - if(SOUTH) - head_dir = "pda_snake_head_south" - if(app.snake_game.head.open_mouth) - head_dir += "_open" - if(!app.snake_game.head.flicking) - dat += {""} - if(app.paused) - dat += {""} - dat += {"
              "} - - dat += {"
              Controls
              - -
              - -
              - "} - - if (PDA_APP_MINESWEEPER) - if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. - var/datum/asset/simple/C = new/datum/asset/simple/pda_mine() - send_asset_list(user.client, C.assets) - - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - dat += {"

              Minesweeper

              "} - if(app) - dat += {"
              -
              - - "} - if(!app.ingame) - for(var/datum/mine_tile/T in app.minesweeper_game.tiles) - dat += {""} - else - for(var/datum/mine_tile/T in app.minesweeper_game.tiles) - var/mine_icon = "" - if(T.dug) - if(T.mined) - mine_icon = "minesweeper_tile_mine_splode" - else if(T.num) - mine_icon = "minesweeper_tile_[T.num]" - else - mine_icon = "minesweeper_tile_empty" - - else - if(T.mined && app.minesweeper_game.gameover) - if(T.flagged == 1) - mine_icon = "minesweeper_tile_flag" - else - mine_icon = "minesweeper_tile_mine_unsplode" - else if(T.flagged == 1) - if(app.minesweeper_game.gameover) - mine_icon = "minesweeper_tile_mine_wrong" - else - mine_icon = "minesweeper_tile_flag" - else if(T.flagged == 2) - mine_icon = "minesweeper_tile_question" - else - mine_icon = "minesweeper_tile_full" - if(T.selected && !app.minesweeper_game.gameover) - mine_icon += "_selected" - dat += {""} - dat += {""} - dat += {""} - dat += {""} - - dat += {""} - dat += {""} - - dat += {""} - var/mine_counter = app.minesweeper_game.initial_mines - for(var/datum/mine_tile/T in app.minesweeper_game.tiles) - if(T.flagged == 1) - mine_counter-- - dat += {""} - dat += {""} - dat += {""} - - dat += {""} - var/time_counter = round((world.time - app.minesweeper_game.timer)/10) - time_counter = min(999,time_counter) - if(!app.ingame || app.minesweeper_game.gameover) - time_counter = app.minesweeper_game.end_timer - dat += {""} - dat += {""} - dat += {""} - - dat += {""} - dat += {""} - dat += {""} - dat += {""} - for(var/x=1;x<=app.minesweeper_game.columns;x++) - dat += {""} - for(var/x=1;x<=app.minesweeper_game.columns;x++) - dat += {""} - for(var/y=0;y"} - for(var/y=0;y"} - - - dat += {"
              "} - if(app.minesweeper_game.current_difficulty != "custom") - dat += {"
              [app.minesweeper_game.current_difficulty] difficulty highscore held by [minesweeper_best_players[app.minesweeper_game.current_difficulty]] (in [minesweeper_station_highscores[app.minesweeper_game.current_difficulty]] seconds)"} - - - if (PDA_APP_SPESSPETS) - if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. - var/datum/asset/simple/C = new/datum/asset/simple/pda_spesspets() - send_asset_list(user.client, C.assets) - - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - dat += {"

              Spess Pets

              "} - if(app) - dat += {"
              Name = [app.petname]
              Level = [app.level]
              -
              - - "} - switch(app.game_state) - if(0) //First Statup - dat += {"
              "} - - dat += {""} - dat += {"
              "} - if(1) //Hatching - var/eggstate = 0 - if(app.hatching > 1200) - eggstate = 3 - else if(app.hatching > 600) - eggstate = 2 - else if(app.hatching > 300) - eggstate = 1 - dat += {""} - if(eggstate >= 2) - dat += {""} - - if(2) //Normal - if(app.ishungry) - dat += {""} - if(app.isdirty) - dat += {""} - if(app.ishurt) - dat += {""} - if(app.isatwork) - dat += {""} - else - dat += {""} - if(app.issleeping) - dat += {""} - else - dat += {""} - dat += {""} - if(app.ishungry) - dat += {""} - if(app.isdirty) - dat += {""} - if(app.ishurt) - dat += {""} - dat += {""} - dat += {""} - if(app.level >= 16) - dat += {""} - if(app.total_coins) - dat += {""} - if(app.total_coins) - dat += {""} - - dat += {""} - if(3) //Dead - dat += {""} - if(app.last_spoken != "") - dat += {"



              [app.last_spoken]"} - if(app.total_coins) - dat += {"
              nanocoins: [app.total_coins]"} - - else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub. - dat += cart - - dat += "" - user << browse(dat, "window=pda;size=400x444;border=1;can_resize=1;can_close=0;can_minimize=0") - onclose(user, "pda", src) - -/obj/item/device/pda/Topic(href, href_list) - ..() - var/mob/living/U = usr - //Looking for master was kind of pointless since PDAs don't appear to have one. - //if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) ) ) - - if(can_use(U)) //Why reinvent the wheel? There's a proc that does exactly that. - add_fingerprint(U) - U.set_machine(src) - - switch(href_list["choice"]) - -//BASIC FUNCTIONS=================================== - - if("Close")//Self explanatory - U.unset_machine() - U << browse(null, "window=pda") - return - if("Refresh")//Refresh, goes to the end of the proc. - if("Return")//Return - if((mode<=9) || (locate(mode) in pda_app_menus)) - mode = 0 - else - mode = round(mode/10)//TODO: fix this shit up - if((mode==4) || (mode==5))//Fix for cartridges. Redirects to hub. - mode = 0 - else if(mode >= 40 && mode <= 53)//Fix for cartridges. Redirects to refresh the menu. - cartridge.mode = mode - cartridge.unlock() - if ("Authenticate")//Checks for ID - id_check(U, 1) - if("UpdateInfo") - ownjob = id.assignment - name = "PDA-[owner] ([ownjob])" - if("Eject")//Ejects the cart, only done from hub. - if (!isnull(cartridge)) - var/turf/T = loc - if(ismob(T)) - T = T.loc - cartridge.loc = T - scanmode = 0 - if (cartridge.radio) - cartridge.radio.hostpda = null - cartridge = null - -//MENU FUNCTIONS=================================== - - if("0")//Hub - mode = 0 - if("1")//Notes - mode = 1 - if("2")//Messenger - mode = 2 - if("21")//Read messeges - mode = 21 - if("3")//Atmos scan - mode = 3 - if("4")//Redirects to hub - mode = 0 - if("41") - mode = 41 - if("chatroom") // chatroom hub - mode = 5 - -//APPLICATIONS FUNCTIONS=========================== - - if(PDA_APP_RINGER) - mode = PDA_APP_RINGER - if("toggleDeskRinger") - var/datum/pda_app/ringer/app = locate(/datum/pda_app/ringer) in applications - if(app) - app.status = !(app.status) - if("ringerFrequency") - var/datum/pda_app/ringer/app = locate(/datum/pda_app/ringer) in applications - if(app) - var/i = app.frequency + text2num(href_list["rfreq"]) - if(i < MINIMUM_FREQUENCY) - i = 1201 - if(i > MAXIMUM_FREQUENCY) - i = 1599 - app.frequency = i - if(PDA_APP_SPAMFILTER) - mode = PDA_APP_SPAMFILTER - if("setFilter") - var/datum/pda_app/spam_filter/app = locate(/datum/pda_app/spam_filter) in applications - if(app) - app.function = text2num(href_list["filter"]) - if(PDA_APP_BALANCECHECK) - mode = PDA_APP_BALANCECHECK - if("printCurrency") - var/mob/user = usr - var/amount = round(input("How much money do you wish to print?", "Currency Printer", 0) as num) - if(!amount || (amount < 0) || (id.virtual_wallet.money <= 0)) - to_chat(user, "\icon[src]The PDA's screen flashes, 'Invalid value.'") - return - if(amount > id.virtual_wallet.money) - amount = id.virtual_wallet.money - if(amount > 10000) // prevent crashes - to_chat(user, "\icon[src]The PDA's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 10,000.'") - amount = 10000 - - id.virtual_wallet.money -= amount - withdraw_arbitrary_sum(user,amount) - if(prob(50)) - playsound(get_turf(src), 'sound/items/polaroid1.ogg', 50, 1) - else - playsound(get_turf(src), 'sound/items/polaroid2.ogg', 50, 1) - - var/datum/transaction/T = new() - T.target_name = user.name - T.purpose = "Currency printed" - T.amount = "-[amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - id.virtual_wallet.transaction_log.Add(T) - - if(PDA_APP_STATIONMAP) - mode = PDA_APP_STATIONMAP - - if("minimapMarker") - var/datum/pda_app/station_map/app = locate(/datum/pda_app/station_map) in applications - switch(href_list["mMark"]) - if("x") - var/new_x = input("Please input desired X coordinate.", "Station Map App", app.markx) as num - var/x_validate=new_x+WORLD_X_OFFSET[map.zMainStation] - if(x_validate < 1 || x_validate > 255) - to_chat(usr, "Error: Invalid X coordinate.") - else - app.markx = new_x - if("y") - var/new_y = input("Please input desired Y coordinate.", "Station Map App", app.marky) as num - var/y_validate=new_y+WORLD_Y_OFFSET[map.zMainStation] - if(y_validate < 1 || y_validate > 255) - to_chat(usr, "Error: Invalid Y coordinate.") - else - app.marky = new_y - if("add") - var/marker_name = copytext(sanitize(input("Give a name to your marker", "Station Map App", "default marker") as null|text),1,MAX_NAME_LEN) - var/datum/minimap_marker/mkr = new/datum/minimap_marker() - mkr.x = app.markx - mkr.y = app.marky - mkr.name = marker_name - app.markers += mkr - mkr.num = app.markers.len - - if("removeMarker") - var/datum/pda_app/station_map/app = locate(/datum/pda_app/station_map) in applications - var/to_remove = text2num(href_list["rMark"]) - var/datum/minimap_marker/mkr = app.markers[to_remove] - qdel(mkr) - mkr = null - -//GAME FUNCTIONS==================================== - - if(PDA_APP_SNAKEII) - mode = PDA_APP_SNAKEII - - if("snakeNewGame") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.ingame = 1 - app.snake_game.game_start() - app.game_tick(usr) - - if("snakeUp") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.snake_game.lastinput = NORTH - - if("snakeLeft") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.snake_game.lastinput = WEST - - if("snakeRight") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.snake_game.lastinput = EAST - - if("snakeDown") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.snake_game.lastinput = SOUTH - - if("snakeUnPause") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.pause(usr) - - if("snakeLabyrinth") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.labyrinth = text2num(href_list["lType"]) - app.snake_game.set_labyrinth(text2num(href_list["lType"])) - - if("snakeLevel") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.snake_game.level = text2num(href_list["sLevel"]) - - if("snakeGyro") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.snake_game.gyroscope = text2num(href_list["gSet"]) - - if("snakeVolume") - var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications - app.volume += text2num(href_list["vChange"]) - app.volume = max(0,app.volume) - app.volume = min(6,app.volume) - - if(PDA_APP_MINESWEEPER) - mode = PDA_APP_MINESWEEPER - - if("mineNewGame") - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - var/datum/mine_tile/T = locate(href_list["mTile"]) - app.ingame = 1 - app.minesweeper_game.game_start(T) - app.game_tick(usr) - - if("mineDig") - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - var/datum/mine_tile/T = locate(href_list["mTile"]) - app.minesweeper_game.dig_tile(T) - app.game_tick(usr) - - if("mineFlag") - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - if(!app.minesweeper_game.gameover) - for(var/datum/mine_tile/T in app.minesweeper_game.tiles) - if(!T.dug && T.selected) - if(!T.flagged) - T.flagged = 1 - else if(T.flagged == 2) - T.flagged = 1 - else - T.flagged = 0 - - if("mineQuestion") - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - if(!app.minesweeper_game.gameover) - for(var/datum/mine_tile/T in app.minesweeper_game.tiles) - if(!T.dug && T.selected) - if(!T.flagged) - T.flagged = 2 - else if(T.flagged == 1) - T.flagged = 2 - else - T.flagged = 0 - - if("mineSettings") - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - if(alert(usr, "Changing the settings will reset the game, are you sure?", "Minesweeper Settings", "Yes", "No") != "Yes") - return - var/list/difficulties = list( - "beginner", - "intermediate", - "expert", - "custom", - ) - var/choice = input("What Difficulty?", "Minesweeper Settings") in difficulties - app.minesweeper_game.set_difficulty(choice) - app.ingame = 0 - - if("mineReset") - var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications - app.minesweeper_game.face = "press" - app.game_update(usr) - sleep(5) - app.minesweeper_game.reset_game() - app.ingame = 0 - - if(PDA_APP_SPESSPETS) - mode = PDA_APP_SPESSPETS - - if("eggPrev") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.previous_egg() - - if("eggNext") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.next_egg() - - if("eggChose") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.game_state = 1 - app.game_tick(usr) - app.petname = copytext(sanitize(input(usr, "What name for your new pet?", "Name your new pet", "[app.petname]") as null|text),1,MAX_NAME_LEN) - app.last_spoken = "" - - if("eggHatch") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_hatch() - - if("eggTalk") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_talk() - - if("eggWalk") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_walk() - - if("eggFeed") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_feed() - - if("eggClean") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_clean() - - if("eggHeal") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_heal() - - if("eggFight") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_fight() - - if("eggVisit") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_visit() - - if("eggWork") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_work() - - if("eggRate") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_rates() - - if("eggCash") - var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications - app.button_cash() - - - -//MAIN FUNCTIONS=================================== - - if("Light") - if(fon) - fon = 0 - set_light(0) - else - fon = 1 - set_light(f_lum) - if("Medical Scan") - if(scanmode == 1) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_medical)) - scanmode = 1 - if("Reagent Scan") - if(scanmode == 3) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner)) - scanmode = 3 - if("Halogen Counter") - if(scanmode == 4) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_engine)) - scanmode = 4 - if("Honk") - if ( !(last_honk && world.time < last_honk + 20) ) - playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) - last_honk = world.time - if("Gas Scan") - if(scanmode == 5) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_atmos)) - scanmode = 5 - if("Device Analyser") - if(scanmode == 6) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_mechanic)) - if(!dev_analys) - dev_analys = new(src) //let's create that device analyser - dev_analys.max_designs = 5 - scanmode = 6 - -//MESSENGER/NOTE FUNCTIONS=================================== - - if ("Edit") - var/n = input(U, "Please enter message", name, notehtml) as message - if (in_range(src, U) && loc == U) - n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) - if (mode == 1) - note = replacetext(n, "\n", "
              ") - notehtml = n - else - U << browse(null, "window=pda") - return - if("Toggle Messenger") - toff = !toff - if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status - silent = !silent - if("Clear")//Clears messages - tnote = null - if("Ringtone") - var/t = input(U, "Please enter new ringtone", name, ttone) as text - if (in_range(src, U) && loc == U) - if (t) - if(src.hidden_uplink && hidden_uplink.check_trigger(U, trim(lowertext(t)), trim(lowertext(lock_code)))) - to_chat(U, "The PDA softly beeps.") - U << browse(null, "window=pda") - src.mode = 0 - else - t = copytext(sanitize(t), 1, 20) - ttone = t - else - U << browse(null, "window=pda") - return - if("Message") - var/obj/item/device/pda/P = locate(href_list["target"]) - src.create_message(U, P) - - if("transferFunds") - if(!id) - return - var/obj/item/device/pda/P = locate(href_list["target"]) - var/amount = round(input("How much money do you wish to transfer to [P.owner]?", "Money Transfer", 0) as num) - if(!amount || (amount < 0) || (id.virtual_wallet.money <= 0)) - to_chat(usr, "\icon[src]The PDA's screen flashes, 'Invalid value.'") - return - if(amount > id.virtual_wallet.money) - amount = id.virtual_wallet.money - - switch(P.receive_funds(owner,amount,name)) - if(1) - to_chat(usr, "\icon[src]The PDA's screen flashes, 'Transaction complete!'") - if(2) - to_chat(usr, "\icon[src]The PDA's screen flashes, 'Transaction complete! The recipient will earn the funds once he enters his ID in his PDA.'") - else - to_chat(usr, "\icon[src]The PDA's screen flashes, 'Error, transaction canceled'") - return - - id.virtual_wallet.money -= amount - var/datum/transaction/T = new() - T.target_name = P.owner - T.purpose = "Money transfer" - T.amount = "-[amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - id.virtual_wallet.transaction_log.Add(T) - - if("Send Honk")//Honk virus - if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch. - var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess. - if(!isnull(P)) - if (!P.toff && cartridge:honk_charges > 0) - cartridge:honk_charges-- - U.show_message("Virus sent!", 1) - P.honkamt = (rand(15,20)) - else - to_chat(U, "PDA not found.") - else - U << browse(null, "window=pda") - return - if("Send Silence")//Silent virus - if(istype(cartridge, /obj/item/weapon/cartridge/mime)) - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge:mime_charges > 0) - cartridge:mime_charges-- - U.show_message("Virus sent!", 1) - P.silent = 1 - P.ttone = "silence" - else - to_chat(U, "PDA not found.") - else - U << browse(null, "window=pda") - return - - -//SYNDICATE FUNCTIONS=================================== - - if("Toggle Door") - if(cartridge && cartridge.access_remote_door) - for(var/obj/machinery/door/poddoor/M in poddoors) - if(M.id_tag == cartridge.remote_door_id) - if(M.density) - M.open() - else - M.close() - - if("Detonate")//Detonate PDA - if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge:shock_charges > 0) - cartridge:shock_charges-- - - var/difficulty = 0 - - if(P.cartridge) - difficulty += P.cartridge.access_medical - difficulty += P.cartridge.access_security - difficulty += P.cartridge.access_engine - difficulty += P.cartridge.access_clown - difficulty += P.cartridge.access_janitor - difficulty += P.cartridge.access_manifest * 2 - else - difficulty += 2 - - if(prob(difficulty * 12) || (P.hidden_uplink)) - U.show_message("An error flashes on your [src].", 1) - else if (prob(difficulty * 3)) - U.show_message("Energy feeds back into your [src]!", 1) - U << browse(null, "window=pda") - explode() - log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up") - message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up", 1) - else - U.show_message("Success!", 1) - log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge and succeded") - message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge and succeded", 1) - P.explode() - else - to_chat(U, "PDA not found.") - else - U.unset_machine() - U << browse(null, "window=pda") - return - -//pAI FUNCTIONS=================================== - if("pai") - switch(href_list["option"]) - if("1") // Configure pAI device - pai.attack_self(U) - if("2") // Eject pAI device - var/turf/T = get_turf(src.loc) - if(T) - pai.loc = T - -//LINK FUNCTIONS=================================== - - else//Cartridge menu linking - mode = text2num(href_list["choice"]) - if(cartridge) - cartridge.mode = mode - cartridge.unlock() - else//If not in range, can't interact or not using the pda. - U.unset_machine() - U << browse(null, "window=pda") - return - -//EXTRA FUNCTIONS=================================== - - if (mode == 2||mode == 21)//To clear message overlays. - overlays.len = 0 - - if ((honkamt > 0) && (prob(60)))//For clown virus. - honkamt-- - playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - - if(U.machine == src && href_list["skiprefresh"]!="1")//Final safety. - attack_self(U)//It auto-closes the menu prior if the user is not in range and so on. - else - U.unset_machine() - U << browse(null, "window=pda") - return - -//Convert money from the virtual wallet into physical bills -/obj/item/device/pda/proc/withdraw_arbitrary_sum(var/mob/user,var/arbitrary_sum) - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(istype(H.wear_id,/obj/item/weapon/storage/wallet)) - dispense_cash(arbitrary_sum,H.wear_id) - to_chat(usr, "\icon[src]Funds were transferred into your physical wallet!") - return - dispense_cash(arbitrary_sum,get_turf(src)) - -//Receive money transferred from another PDA -/obj/item/device/pda/proc/receive_funds(var/creditor_name,var/arbitrary_sum,var/other_pda) - var/turf/U = get_turf(src) - if(!silent) - playsound(U, 'sound/machines/twobeep.ogg', 50, 1) - - for (var/mob/O in hearers(3, U)) - if(!silent) O.show_message(text("\icon[src] *[src.ttone]*")) - - var/mob/living/L = null - if(src.loc && isliving(src.loc)) - L = src.loc - else - L = get(src, /mob/living/silicon) - - if(L) - to_chat(L, "\icon[src] Money transfer from [creditor_name] ([arbitrary_sum]$) [id ? "" : "Insert your ID in the PDA to receive the funds."]") - - tnote += "← Money transfer from [creditor_name] ([arbitrary_sum]$)
              " - - if(id) - if(!id.virtual_wallet) - id.update_virtual_wallet() - id.virtual_wallet.money += arbitrary_sum - var/datum/transaction/T = new() - T.target_name = creditor_name - T.purpose = "Money transfer" - T.amount = arbitrary_sum - T.source_terminal = other_pda - T.date = current_date_string - T.time = worldtime2text() - id.virtual_wallet.transaction_log.Add(T) - return 1 - else - incoming_transactions |= list(list(creditor_name,arbitrary_sum,other_pda)) - return 2 - -//Receive money transferred from another PDA -/obj/item/device/pda/proc/receive_incoming_transactions(var/obj/item/weapon/card/id/ID_card) - for(var/transac in incoming_transactions) - if(!id.virtual_wallet) - id.update_virtual_wallet() - id.virtual_wallet.money += transac[2] - var/datum/transaction/T = new() - T.target_name = transac[1] - T.purpose = "Money transfer" - T.amount = transac[2] - T.source_terminal = transac[3] - T.date = current_date_string - T.time = worldtime2text() - id.virtual_wallet.transaction_log.Add(T) - - incoming_transactions = list() - - var/mob/living/L = null - if(src.loc && isliving(src.loc)) - L = src.loc - to_chat(L, "\icon[src] Transactions successfully received! ") - - -/obj/item/device/pda/proc/remove_id() - if (id) - if (ismob(loc)) - var/mob/M = loc - M.put_in_hands(id) - to_chat(usr, "You remove the ID from the [name].") - else - id.loc = get_turf(src) - id = null - -/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P) - - - var/t = input(U, "Please enter message", name, null) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t || !istype(P)) - return - if (!in_range(src, U) && loc != U) - return - - if (isnull(P)||P.toff || toff) - return - - if (last_text && world.time < last_text + 5) - return - - if(!can_use(U)) - return - - last_text = world.time - // check if telecomms I/O route 1459 is stable - //var/telecomms_intact = telecomms_process(P.owner, owner, t) - 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. - if(MS.active) - useMS = MS - break - - var/datum/signal/signal = src.telecomms_process() - - var/useTC = 0 - if(signal) - if(signal.data["done"]) - useTC = 1 - var/turf/pos = get_turf(P) - if(pos.z in signal.data["level"]) - useTC = 2 - //Let's make this barely readable - if(signal.data["compression"] > 0) - 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? - to_chat(U, "ERROR: Cannot reach recepient.") - return - useMS.send_pda_message("[P.owner]","[owner]","[t]") - - tnote += "→ To [P.owner]:
              [t]
              " - P.tnote += "← From [owner] ([ownjob]):
              [t]
              " - for(var/mob/dead/observer/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA)) // src.client is so that ghosts don't have to listen to mice - M.show_message("PDA Message - [owner] -> [P.owner]: [t]") - - - if (prob(15)) //Give the AI a chance of intercepting the message - var/who = src.owner - if(prob(50)) - who = P:owner - for(var/mob/living/silicon/ai/ai in mob_list) - // Allows other AIs to intercept the message but the AI won't intercept their own message. - if(ai.aiPDA != P && ai.aiPDA != src) - ai.show_message("Intercepted message from [who]: [t]") - - if (!P.silent) - playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, P.loc)) - if(!P.silent) O.show_message(text("\icon[P] *[P.ttone]*")) - //Search for holder of the PDA. - var/mob/living/L = null - if(P.loc && isliving(P.loc)) - L = P.loc - //Maybe they are a pAI! - else - L = get(P, /mob/living/silicon) - - if(L) - L.show_message("\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)", 2) - - log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") - P.overlays.len = 0 - P.overlays += image('icons/obj/pda.dmi', "pda-r") - else - to_chat(U, "ERROR: Messaging server is not responding.") - - -/obj/item/device/pda/verb/verb_remove_id() - set category = "Object" - set name = "Remove id" - set src in usr - - if(issilicon(usr)) - return - - if ( can_use(usr) ) - if(id) - remove_id() - else - to_chat(usr, "This PDA does not have an ID in it.") - else - to_chat(usr, "You cannot do this while restrained.") - -obj/item/device/pda/CtrlClick() - if ( can_use(usr) ) // Checks that the PDA is in our inventory. This will be checked by the proc anyways, but we don't want to generate an error message if not. - verb_remove_id(usr) - return - return ..() - -/obj/item/device/pda/verb/verb_remove_pen() - set category = "Object" - set name = "Remove pen" - set src in usr - - if(issilicon(usr)) - return - - if ( can_use(usr) ) - var/obj/item/weapon/pen/O = locate() in src - if(O) - if (istype(loc, /mob)) - var/mob/M = loc - if(M.get_active_hand() == null) - M.put_in_hands(O) - to_chat(usr, "You remove \the [O] from \the [src].") - return - O.loc = get_turf(src) - else - to_chat(usr, "This PDA does not have a pen in it.") - else - to_chat(usr, "You cannot do this while restrained.") - -obj/item/device/pda/AltClick() - if ( can_use(usr) ) // Checks that the PDA is in our inventory. This will be checked by the proc anyways, but we don't want to generate an error message if not. - verb_remove_pen(usr) - return - return ..() - -/obj/item/device/pda/proc/id_check(mob/user as mob, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use. - if(choice == 1) - if (id) - remove_id() - else - var/obj/item/I = user.get_active_hand() - if (istype(I, /obj/item/weapon/card/id)) - if(user.drop_item(I, src)) - id = I - else - var/obj/item/weapon/card/I = user.get_active_hand() - if (istype(I, /obj/item/weapon/card/id) && I:registered_name) - var/obj/old_id = id - if(user.drop_item(I, src)) - id = I - user.put_in_hands(old_id) - if(id && incoming_transactions.len) - receive_incoming_transactions(id) - return - -// access to status display signals -/obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob) - ..() - if(istype(C, /obj/item/weapon/cartridge) && !cartridge) - if(user.drop_item(C, src)) - cartridge = C - to_chat(user, "You insert [cartridge] into [src].") - if(cartridge.radio) - cartridge.radio.hostpda = src - - else if(istype(C, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/idcard = C - if(!idcard.registered_name) - to_chat(user, "\The [src] rejects the ID.") - return - if(!owner) - owner = idcard.registered_name - ownjob = idcard.assignment - name = "PDA-[owner] ([ownjob])" - to_chat(user, "Card scanned.") - else - //Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand. - if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) ) - if( can_use(user) )//If they can still act. - id_check(user, 2) - to_chat(user, "You put the ID into \the [src]'s slot.") - if(incoming_transactions.len) - receive_incoming_transactions(id) - updateSelfDialog()//Update self dialog on success. - return //Return in case of failed check or when successful. - updateSelfDialog()//For the non-input related code. - else if(istype(C, /obj/item/device/paicard) && !src.pai) - if(user.drop_item(C, src)) - pai = C - to_chat(user, "You slot \the [C] into [src].") - updateUsrDialog() - else if(istype(C, /obj/item/weapon/pen)) - var/obj/item/weapon/pen/O = locate() in src - if(O) - to_chat(user, "There is already a pen in \the [src].") - else - if(user.drop_item(C, src)) - to_chat(user, "You slide \the [C] into \the [src].") - else if(istype(C,/obj/item/weapon/spacecash)) - if(!id) - to_chat(user, "\icon[src]There is no ID in the PDA!") - return - var/obj/item/weapon/spacecash/dosh = C - id.virtual_wallet.money += dosh.worth * dosh.amount - if(prob(50)) - playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) - else - playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) - - var/datum/transaction/T = new() - T.target_name = user.name - T.purpose = "Currency deposit" - T.amount = dosh.worth * dosh.amount - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - id.virtual_wallet.transaction_log.Add(T) - - to_chat(user, "You insert [dosh] into the PDA.") - qdel(dosh) - updateUsrDialog() - - return - -/obj/item/device/pda/attack(mob/living/carbon/C, mob/living/user as mob) - if(istype(C)) - switch(scanmode) - - if(1) - healthanalyze(C,user,0) - - if(2) - if (!istype(C:dna, /datum/dna)) - to_chat(user, "No fingerprints found on [C]") - else if(!istype(C, /mob/living/carbon/monkey)) - if(!isnull(C:gloves)) - to_chat(user, "No fingerprints found on [C]") - else - to_chat(user, text("[C]'s Fingerprints: [md5(C:dna.uni_identity)]")) - if ( !(C:blood_DNA) ) - to_chat(user, "No blood found on [C]") - if(C:blood_DNA) - qdel(C:blood_DNA) - C:blood_DNA = null - else - to_chat(user, "Blood found on [C]. Analysing...") - spawn(15) - for(var/blood in C:blood_DNA) - to_chat(user, "Blood type: [C:blood_DNA[blood]]\nDNA: [blood]") - - if(4) - for (var/mob/O in viewers(C, null)) - O.show_message("[user] has analyzed [C]'s radiation levels!", 1) - - user.show_message("Analyzing Results for [C]:") - if(C.radiation) - user.show_message("Radiation Level: [C.radiation]") - else - user.show_message("No radiation detected.") - -/obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob) - if(scanmode == 5) - if(atmos_analys) - if(A.Adjacent(user)) - if(!A.attackby(atmos_analys, user)) - atmos_analys.afterattack(A, user, 1) - - if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) - note = A:info - to_chat(user, "Paper scanned.")//concept of scanning paper copyright brainoblivion 2009 - - -/obj/item/device/pda/preattack(atom/A as mob|obj|turf|area, mob/user as mob) - switch(scanmode) - if(3) - if(!A.Adjacent(user)) - return - if(!isnull(A.reagents)) - if(A.reagents.reagent_list.len > 0) - var/reagents_length = A.reagents.reagent_list.len - to_chat(user, "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.") - for (var/datum/reagent/re in A.reagents.reagent_list) - to_chat(user, "\t [re]: [re.volume] units") - else - to_chat(user, "No active chemical agents found in [A].") - else - to_chat(user, "No significant chemical agents found in [A].") - . = 1 - - if (6) - if(dev_analys) //let's use this instead. Much neater - if(A.Adjacent(user)) - return dev_analys.preattack(A, user, 1) - -/obj/item/device/pda/proc/explode() //This needs tuning. - if(!src.detonate) return - var/turf/T = get_turf(src.loc) - - if (ismob(loc)) - var/mob/M = loc - M.show_message("Your [src] explodes!", 1) - - if(T) - T.hotspot_expose(700,125,surfaces=istype(loc,/turf)) - - explosion(T, -1, -1, 2, 3) - - qdel(src) - return - -/obj/item/device/pda/Destroy() - PDAs -= src - if (src.id) - src.id.loc = get_turf(src.loc) - if(src.pai) - src.pai.loc = get_turf(src.loc) - ..() - -/obj/item/device/pda/Del() - var/loop_count = 0 - while(null in PDAs) - PDAs.Remove(null) - if(loop_count > 10) break - loop_count++ - PDAs -= src - ..() - -/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery. - if (istype(AM, /mob/living/carbon)) - var/mob/living/carbon/M = AM - if (M.Slip(8, 5)) - to_chat(M, "You slipped on the PDA!") - - if ((istype(M, /mob/living/carbon/human) && (M.real_name != src.owner) && (istype(src.cartridge, /obj/item/weapon/cartridge/clown)))) - var/obj/item/weapon/cartridge/clown/honkcartridge = src.cartridge - if (honkcartridge.honk_charges < 5) - honkcartridge.honk_charges++ - -/obj/item/device/pda/proc/available_pdas() - var/list/names = list() - var/list/plist = list() - var/list/namecounts = list() - - if (toff) - to_chat(usr, "Turn on your receiver in order to send messages.") - return - - for (var/obj/item/device/pda/P in PDAs) - if (!P.owner) - continue - else if(P.hidden) - continue - else if (P == src) - continue - else if (P.toff) - continue - - var/name = P.owner - if (name in names) - namecounts[name]++ - name = text("[name] ([namecounts[name]])") - else - names.Add(name) - namecounts[name] = 1 - - plist[text("[name]")] = P - return plist - - -//Some spare PDAs in a box -/obj/item/weapon/storage/box/PDAs - name = "spare PDAs" - desc = "A box of spare PDA microcomputers." - icon = 'icons/obj/pda.dmi' - icon_state = "pdabox" - - New() - ..() - new /obj/item/device/pda(src) - new /obj/item/device/pda(src) - new /obj/item/device/pda(src) - new /obj/item/device/pda(src) - new /obj/item/weapon/cartridge/head(src) - - 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/quartermaster) - new newcart(src) - -// Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP -/obj/item/device/pda/emp_act(severity) - for(var/atom/A in src) - A.emp_act(severity) - -/proc/get_viewable_pdas() - . = list() - // Returns a list of PDAs which can be viewed from another PDA/message monitor. - for(var/obj/item/device/pda/P in PDAs) - if(!P.owner || P.toff || P.hidden) continue - . += P - return . +#define MAX_DESIGNS 10 + +//The advanced pea-green monochrome lcd of tomorrow. + +var/global/list/obj/item/device/pda/PDAs = list() + + +/obj/item/device/pda + name = "\improper PDA" + desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge. Can download additional applications from PDA terminals." + icon = 'icons/obj/pda.dmi' + icon_state = "pda" + item_state = "electronic" + w_class = 1.0 + flags = FPRINT + slot_flags = SLOT_ID | SLOT_BELT + + //Main variables + var/owner = null + var/default_cartridge = 0 // Access level defined by cartridge + var/obj/item/weapon/cartridge/cartridge = null //current cartridge + var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge. + + //Secondary variables + var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner, 4 is halogen counter, 5 is gas scanner, 6 is device analyser -- keep this list updated if you add one + var/fon = 0 //Is the flashlight function on? + var/f_lum = 2 //Luminosity for the flashlight function + var/silent = 0 //To beep or not to beep, that is the question + var/toff = 0 //If 1, messenger disabled + var/tnote = null //Current Texts + var/last_text //No text spamming + var/last_honk //Also no honk spamming that's bad too + var/ttone = "beep" //The ringtone! + var/lock_code = "" // Lockcode to unlock uplink + var/honkamt = 0 //How many honks left when infected with honk.exe + var/mimeamt = 0 //How many silence left when infected with mime.exe + var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant!" //Current note in the notepad function + var/notehtml = "" + var/cart = "" //A place to stick cartridge menu information + var/detonate = 1 // Can the PDA be blown up? + var/hidden = 0 // Is the PDA hidden from the PDA list? + + var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both. + var/ownjob = null //related to above + + var/obj/item/device/paicard/pai = null // A slot for a personal AI device + var/obj/item/device/analyzer/atmos_analys = new + var/obj/item/device/device_analyser/dev_analys = null + + var/MM = null + var/DD = null + + var/list/applications = list() + + var/list/incoming_transactions = list() + + var/list/currentevents1 = list("The Prime Minister of Space Australia has announced today a new policy to hand out fake dollar bills to the poor.", + "The President of Space America issued a press release today stating that he is not in fact, a Tajaran in disguise.", + "The Prime Minister of Space England is in hot water today after he announced that space tea would now be made with 20% more nuclear waste.", + "The Czar of the Space Soviet Union has issued a press release stating 'Spess Amerikans suck cocks!' we're working on a translation.", + "Space Israel has not gotten into trouble for bombing dirty Space Palestine again today. Don't be so anti-semitic.", + "Our sources tell us that the Earth country Poland has issued a press release stating that 'they didn't want to go to space anyway' and that 'space sucks'. More at eleven.", + "Sources are saying that the Earth country Poland has issued another press release saying they were sorry and would very much like to be in space. The Intergalactic Empire responded with the word 'No'.", + "The President of Space America has come under fire recently for stating that god was a chicken.", + "The Intergalactic Empire is in hot water this week after proposing to rename Space-Milk to Milk. The newsroom would like to apologize to any readers offended by this news.", + "The Prime Minister of Space Scotland has announced that 'Freedom Day' did not go as planned. Our sources report that over 2000 human heads are now being returned to their loved ones.", + "The Prime Minister of Space Australia has come under fire for stating 'Women are in the kitchen, men are on the sofa, jews are in the oven. My country is doing well.", + "Dirty Space Palestine just declared Jihad on Mighty Space Israel. For shame, Space Palestine.", + "The President of Space America was questioned today about his reaction to the Space Superstorm Baldman disaster, he replied 'I didn't send anybody since I figured it would quit about three quarters through.", + "The President of Space America was photographed today kicking a dog to death while muttering about how he liked cats better.", + "The President of Space America was photographed today with a fairly obvious tail protruding out of his pants, he denies the photo is real, saying 'I, president T'jkar Aw'krejn, am no Tajaran-- I mean catbeast.", + "The votes have come in, and the new Prime Minister of Space Uzbekistan is Kthchichikachi Breekikikiki. When questioned about his landslide victory, he replied 'SQAAAAAAAK'. His only opponent, Er'p Fh'goot, was the first openly gay catbeast to run for office.", + "The President of Space America has issued a press release asking for more chips in his office.", + "The Prime Minister of Space Uzbekistan has issued a press release, stating that 'SQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK BAWWK BAAWWWWKK'. We would like to say that Faux News does not condone or support the words of Mr. Breekikikiki.", + "The Prime Minister of Space Australia has come under fire for stating he was very upset with how many black people there was in his country.", + "The Czar of Space Russia has accused the President of Space America of being a dirty catbeast. The President wiggled his trademark ears and said that if he was a Tajaran, the Czar was a space shark. The President is being treated for bite wounds.", + "The 'Universes Largest Oven' has been completed today in Space Germany. Prime Minister Adole Himmler has invited Space Isreal to see the oven first at its grand opening." + ) + var/list/currentevents2 = list("CEO Discount Dan has been sued. Again.", + "NanoTrasen has inducted a new policy wherein clowns will be spanked for stealing milk.", + "Discount Dan's has created a new line of Discountu Danu food product for Space Japan. The food is comprised of Space Carp on rice. More at ten.", + "Discount Dan's has come under fire for their new 'Horsemeat Lasagna'", + "NanoTrasen's official website has been hacked this morning. The site read 'NT SUXZ, GO SYNDIEKATTZ!!1!1!!' for 48 hours until the site was fixed.", + "Read the all new book by a former unnamed syndicate, 'NanoTrasen sucks but the dental is good so whatever.'", + "NanoTrasen has released a new study that has been made useless by the internet.", + "Discount Dan's 'Spooky Dan' line of product has come under fire for being unintentionally racist toward ghosts.", + "Discount Dan's 'Discounto Danito' line of product has come out with a new 'fiesta size' burrito. CEO Discount Dan has been quoted as saying, 'A big 'ol clot for a big 'ol family!'", + "The Syndicate has issued a press release stating that 'NanoTrasen sucks dicks.'", + "NanoTrasen CEO Johnson Lovelocker has been photographed kicking a Tajaran to death. This shameful publicity stunt is part of the new 'NT Hates Catbeasts, do you?' campaign.", + "NanoTrasen CEO Johnson Lovelocker has been photographed kicking a Vox in the cloaca. He commented that, 'BIRDS BELONG IN MY FUCKING MEALS DAMN IT'.", + "NanoTrasen CEO Johnson Lovelocker is in hot water for an alleged sex scandal with a confused syndicate woman that took the motto 'Fuck NT' too seriously.", + "NanoTrasen CEO Johnson Lovelocker issued a press release stating, 'Anybody who's fucking impersonating me is going to get fucking bluespaced unto a spike.'. We do not condone Lovelocker's use of foul language in the newsroom.", + "NanoTrasen CEO Johnson Lovelocker and Discount Dan's CEO Discount Dan have been photographed buying a new friend necklace. The Syndicate issued a statement that 'That's totally gay.'", + "Discount Dan has been photographed this evening hunting the endangered albino space panda. When questioned, he replied that the endangered animal was 'Good eats'.", + "NanoTrasen's head programmer quit this evening when people did not respond well to his new features on NTOS. Said features included the ability to instantly transmit pictures of your butt to people by blinking.", + "NanoTrasen CEO Johnson Lovelocker was photographed this morning celebrating his birthday will well deserved hookers and blow.", + "Discount Dan's stock has risen 20 points today after CEO Discount Dan promised to include a free toy in every 'Happy Dan' meal. In other news, we have over 300 confirmed reports of broken teeth and lead poisoning in children 6 and under.", + "Discount Dan has come under fire today after trying to hug a plasmaman whilst smoking a cigar. He is being treated for 3rd degree burns at the moment, and we at the newsroom wish him luck.", + "NanoTrasen's treasurer Shlomo Goldburginstein died today in a tragic cooking incident with NT Officer Gass Judenraigh." + ) + var/list/currentevents3 = list("Border patrol around Space America has tightened today after a wave of Tajarans yiffed their way across. We have reports of over 2000 molested Space Americans. More to come at seven.", + "Tajarans continue to protest in their 'Trillion Fur March' today. We have reports that the Space American army is giving a KOS order on all non-humans in the area.", + "Read the all new book by known Plasmaman rights activist Spookler Boney, 'AGHGHHGHGH KILL ME IT BURNS AGHHHHHHH'", + "Read the all new book by the worlds most renown skeleton Johnny Hips, 'It aint easy, being bony.'", + "Scientists in Space Austria have found a chicken with the ability to warp space-time. More at ten.", + "Scientists working on at the Bluespace Portal Research Facility (BPRF), have looked into the fabric of reality. They report that all it is out there is a bunch of fat nerds and a chicken.", + "Scientists working at the Large Hadron Collider have discovered nothing today. A sceptical scientist was quoted as saying, 'It could be nothing, but it's probably just something again.'", + "Johnny Hips has released a new album today, 'Tibia Blues'. The songs include classics such as 'I aint got money for milk.', 'Skeleton Rock', and a new song named, 'Bone Marrow'.", + "Doctors have discovered that clowns indeed do have a funny bone.", + "Renowned mime scientist Free Shrugs has discovered a new element today. He has named it ' ', he also says that it has the properties of ' '.", + "Archaeologists have discovered god's final message to his creation today. The message reads, 'bawk'.", + "Scientists have discovered a new type of elementary particle today. Our sources say it has a bad atitude, and enjoys the color blue.", + "Today, a man was discovered to be living with a 20 year old ghost in his house. When the ghost was questioned who killed him, he responded 'A FAGGOT!'. More at four.", + "Scientists report that ghosts do in fact exist, however, they are huge assholes.", + "Supermatter researchers today have reported that the substance is highly volatile and could possibly rip apart the universe in large quantities. Discount Dan has been reported as ordering over 1000 pounds of supermatter shards.", + "Scientists working at the BPRF have discovered a pocket universe comprised fully of dead clown souls today. 40 scientists are being treated for madness." + ) + var/list/history = list("Adolf Hitler's cyborg body was lain to rest after the ending of WW4.", + "World War Buttbot began, the following war claimed the asses of over 500000 young gentlemen.", + "The 54th President of the United States of Space America was shot in the dick. He succumbed to his injuries after medbay threw him in cryo for an entire day.", + "The first great zombie apocalypse began on Venus.", + "The first man to step on Pluto slipped and was impaled on an ice spike shortly after landing.", + "North Korea became the first country to land a rocket on the sun.", + "Kim Jong Long Dong Silver, 58th generation leader of North Korea, died after being shot seventy two times in the chest.", + "NanoTrasen's new 'Space Station 13' project was announced.", + "Jupiter and Neptune became sentient for a period of 78 hours, Jupiter was heard screaming 'WHY AM I ALIVE DEAR GOD.', whilst curiously, Neptune only said 'Well here we go again.'.", + "The first furry in space was thrown out an airlock, along with his fursuit.", + "The 89th President of Space America read Woody's Got Wood aloud in his first State of the Union, and was beaten to death shortly after.", + "Space France surrendered for the 10124th time, making it the most invaded country in the galaxy.", + "Our glorious leader Karl Pilkington the 24th was crowned emperor of the Intergalactic Human Empire.", + "Everyone in the universe said 'Dave sucks.' at the same time. The cause of this event was unknown, but over 200000 men named Dave were murdered.", + "A cult religion following the belief god was a chicken was created.", + ) + var/list/facts = list("If you have 3 quarters, 4 dimes, and 4 pennies, you have $1.19. You also have the largest amount of money in coins without being able to make change for a dollar.", + "The numbers '172' can be found on the back of the U.S. $5 dollar bill in the bushes at the base of the Lincoln Memorial.", + "President Kennedy was the fastest random speaker in the world with upwards of 350 words per minute.", + "In the average lifetime, a person will walk the equivalent of 5 times around the equator.", + "Odontophobia is the fear of teeth.", + "The surface area of an average-sized brick is 79 cm squared.", + "According to suicide statistics, Monday is the favoured day for self-destruction.", + "The Neanderthal's brain was bigger than yours is.", + "The pancreas produces Insulin.", + "The word 'lethologica' describes the state of not being able to remember the word you want.", + "Every year about 98% of the atoms in your body are replaced.", + "The international telephone dialing code for Antarctica is 672.", + "Women are 37% more likely to go to a psychiatrist than men are.", + "The human heart creates enough pressure to squirt blood 30 feet (9 m).", + "When snakes are born with two heads, they fight each other for food.", + "Stressed is Desserts spelled backwards.", + "The word 'nerd' was first coined by Dr. Seuss in 'If I Ran the Zoo.'", + "Revolvers cannot be silenced because of all the noisy gasses which escape the cylinder gap at the rear of the barrel.", + "Every human spent about half an hour as a single cell.", + "7.5 million toothpicks can be created from a cord of wood.", + "If the Earth's sun were just inch in diameter, the nearest star would be 445 miles away.", + "There is no word in the English language that rhymes with month, orange, silver or purple.", + "Starfish have no brains.", + "2 and 5 are the only prime numbers that end in 2 or 5.", + "'Pronunciation' is the word which is mispronounced the most in the English language.", + "Women blink nearly twice as much as men.", + "Owls are the only birds who can see the color blue.", + "A pizza that has radius 'z' and height 'a' has volume Pi × z × z × a.", + "Months that begin on a Sunday will always have a 'Friday the 13th.'", + "Zero is an even number.", + "The longest English word that can be spelled without repeating any letters is 'uncopyrightable'.", + "10! (Ten factorial) seconds equals exactly six Earth weeks.", + "Want to remember the first digits of Pi easily? You can do it by counting each word's letters in 'May I have a large container of plasma?'" + ) + var/currentevent1 = null + var/currentevent2 = null + var/currentevent3 = null + var/onthisday = null + var/didyouknow = null + + +/obj/item/device/pda/New() + ..() + var/datum/pda_app/balance_check/app = new /datum/pda_app/balance_check() + app.onInstall(src) + +/obj/item/device/pda/medical + name = "Medical PDA" + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-m" + +/obj/item/device/pda/medical/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_medbay + +/obj/item/device/pda/viro + name = "Virology PDA" + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-v" + +/obj/item/device/pda/viro/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_medbay + +/obj/item/device/pda/engineering + name = "Engineering PDA" + default_cartridge = /obj/item/weapon/cartridge/engineering + icon_state = "pda-e" + +/obj/item/device/pda/security + name = "Security PDA" + default_cartridge = /obj/item/weapon/cartridge/security + icon_state = "pda-s" + +/obj/item/device/pda/security/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_brig + +/obj/item/device/pda/detective + name = "Detective PDA" + default_cartridge = /obj/item/weapon/cartridge/detective + icon_state = "pda-det" + +/obj/item/device/pda/detective/New() + ..() + var/datum/pda_app/light_upgrade/app = new /datum/pda_app/light_upgrade() + app.onInstall(src) + +/obj/item/device/pda/warden + name = "Warden PDA" + default_cartridge = /obj/item/weapon/cartridge/security + icon_state = "pda-warden" + +/obj/item/device/pda/warden/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_brig + +/obj/item/device/pda/janitor + name = "Janitor PDA" + default_cartridge = /obj/item/weapon/cartridge/janitor + icon_state = "pda-j" + ttone = "slip" + +/obj/item/device/pda/toxins + name = "Science PDA" + default_cartridge = /obj/item/weapon/cartridge/signal/toxins + icon_state = "pda-tox" + ttone = "boom" + +/obj/item/device/pda/toxins/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_rnd + +/obj/item/device/pda/clown + name = "Clown PDA" + default_cartridge = /obj/item/weapon/cartridge/clown + icon_state = "pda-clown" + desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings." + ttone = "honk" + +/obj/item/device/pda/mime + name = "Mime PDA" + default_cartridge = /obj/item/weapon/cartridge/mime + icon_state = "pda-mime" + silent = 1 + ttone = "silence" + +/obj/item/device/pda/heads + name = "Head of department PDA" + default_cartridge = /obj/item/weapon/cartridge/head + icon_state = "pda-h" + +/obj/item/device/pda/heads/hop + name = "Head of Personnel PDA" + default_cartridge = /obj/item/weapon/cartridge/hop + icon_state = "pda-hop" + +/obj/item/device/pda/heads/hop/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_hop + +/obj/item/device/pda/heads/hos + name = "Head of Security PDA" + default_cartridge = /obj/item/weapon/cartridge/hos + icon_state = "pda-hos" + +/obj/item/device/pda/heads/hos/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_brig + +/obj/item/device/pda/heads/ce + name = "Chief Engineer PDA" + default_cartridge = /obj/item/weapon/cartridge/ce + icon_state = "pda-ce" + +/obj/item/device/pda/heads/cmo + name = "Chief Medical Officer PDA" + default_cartridge = /obj/item/weapon/cartridge/cmo + icon_state = "pda-cmo" + +/obj/item/device/pda/heads/cmo/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_medbay + +/obj/item/device/pda/heads/rd + name = "Research Director PDA" + default_cartridge = /obj/item/weapon/cartridge/rd + icon_state = "pda-rd" + +/obj/item/device/pda/heads/rd/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_rnd + +/obj/item/device/pda/captain + name = "Captain PDA" + default_cartridge = /obj/item/weapon/cartridge/captain + icon_state = "pda-c" + detonate = 0 + //toff = 1 + +/obj/item/device/pda/captain/New() + ..() + for(var/app_type in (typesof(/datum/pda_app) - /datum/pda_app)) //yes, the captain is such a baller that his PDA has all the apps by default. + var/datum/pda_app/app = new app_type() //will have to edit that when emagged/hidden apps get added. + app.onInstall(src) + +/obj/item/device/pda/cargo + name = "Cargo PDA" + default_cartridge = /obj/item/weapon/cartridge/quartermaster + icon_state = "pda-cargo" + +/obj/item/device/pda/cargo/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_cargo + +/obj/item/device/pda/quartermaster + name = "Quartermaster PDA" + default_cartridge = /obj/item/weapon/cartridge/quartermaster + icon_state = "pda-q" + +/obj/item/device/pda/quartermaster/New() + ..() + var/datum/pda_app/ringer/app = new /datum/pda_app/ringer() + app.onInstall(src) + app.frequency = deskbell_freq_cargo + +/obj/item/device/pda/shaftminer + name = "Mining PDA" + icon_state = "pda-miner" + +/obj/item/device/pda/syndicate + default_cartridge = /obj/item/weapon/cartridge/syndicate + icon_state = "pda-syn" + name = "Military PDA" + owner = "John Doe" + hidden = 1 + +/obj/item/device/pda/chaplain + name = "Chaplain PDA" + icon_state = "pda-holy" + ttone = "holy" + +/obj/item/device/pda/lawyer + name = "Lawyer PDA" + default_cartridge = /obj/item/weapon/cartridge/lawyer + icon_state = "pda-lawyer" + ttone = "..." + +/obj/item/device/pda/botanist + name = "Botany PDA" + //default_cartridge = /obj/item/weapon/cartridge/botanist + icon_state = "pda-hydro" + +/obj/item/device/pda/roboticist + name = "Robotics PDA" + icon_state = "pda-robot" + +/obj/item/device/pda/librarian + name = "Librarian PDA" + icon_state = "pda-libb" + desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader." + note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!" + silent = 1 //Quiet in the library! + +/obj/item/device/pda/clear + icon_state = "pda-transp" + desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case." + note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!" + +/obj/item/device/pda/chef + name = "Chef PDA" + default_cartridge = /obj/item/weapon/cartridge/chef + icon_state = "pda-chef" + +/obj/item/device/pda/bar + name = "Bartender PDA" + icon_state = "pda-bar" + +/obj/item/device/pda/atmos + name = "Atmospherics PDA" + default_cartridge = /obj/item/weapon/cartridge/atmos + icon_state = "pda-atmo" + +/obj/item/device/pda/mechanic + name = "Mechanic PDA" + default_cartridge = /obj/item/weapon/cartridge/mechanic + icon_state = "pda-atmo" + +/obj/item/device/pda/chemist + name = "Chemistry PDA" + default_cartridge = /obj/item/weapon/cartridge/chemistry + icon_state = "pda-chem" + +/obj/item/device/pda/geneticist + name = "Genetics PDA" + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-gene" + + +// Special AI/pAI PDAs that cannot explode. +/obj/item/device/pda/ai + icon_state = "NONE" + ttone = "data" + detonate = 0 + +/obj/item/device/pda/ai/New() + ..() + var/datum/pda_app/spam_filter/app = new /datum/pda_app/spam_filter() + app.onInstall(src) + + +/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text) + owner = newname + ownjob = newjob + name = newname + " (" + ownjob + ")" + + +//AI verb and proc for sending PDA messages. +/mob/living/silicon/ai/proc/cmd_send_pdamesg() + var/list/names = list() + var/list/plist = list() + var/list/namecounts = list() + + if(usr.stat == 2) + to_chat(usr, "You can't send PDA messages because you are dead!") + return + + if(src.aiPDA.toff) + to_chat(usr, "Turn on your receiver in order to send messages.") + return + + for (var/obj/item/device/pda/P in get_viewable_pdas()) + if (P == src) + continue + else if (P == src.aiPDA) + continue + + var/name = P.owner + if (name in names) + namecounts[name]++ + name = text("[name] ([namecounts[name]])") + else + names.Add(name) + namecounts[name] = 1 + + plist[text("[name]")] = P + + var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) + + if (!c) + return + + var/selected = plist[c] + src.aiPDA.create_message(src, selected) + +//AI verb and proc for sending PDA messages. +/obj/item/device/pda/ai/verb/cmd_send_pdamesg() + set category = "AI Commands" + set name = "Send Message" + set src in usr + if(usr.isDead()) + to_chat(usr, "You can't send PDA messages because you are dead!") + return + var/list/plist = available_pdas() + if (plist) + var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) + if (!c) // if the user hasn't selected a PDA file we can't send a message + return + var/selected = plist[c] + create_message(usr, selected) + + +/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver() + set category = "AI Commands" + set name = "Toggle Sender/Receiver" + set src in usr + if(usr.isDead()) + to_chat(usr, "You can't do that because you are dead!") + return + toff = !toff + to_chat(usr, "PDA sender/receiver toggled [(toff ? "Off" : "On")]!") + + +/obj/item/device/pda/ai/verb/cmd_toggle_pda_silent() + set category = "AI Commands" + set name = "Toggle Ringer" + set src in usr + if(usr.isDead()) + to_chat(usr, "You can't do that because you are dead!") + return + silent=!silent + to_chat(usr, "PDA ringer toggled [(silent ? "Off" : "On")]!") + + +/obj/item/device/pda/ai/verb/cmd_show_message_log() + set category = "AI Commands" + set name = "Show Message Log" + set src in usr + if(usr.isDead()) + to_chat(usr, "You can't do that because you are dead!") + return + var/HTML = "AI PDA Message Log[tnote]" + usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") + +/mob/living/silicon/ai/proc/cmd_show_message_log() + if(usr.isDead()) + to_chat(usr, "You can't do that because you are dead!") + return + if(!isnull(aiPDA)) + var/HTML = "AI PDA Message Log[aiPDA.tnote]" + usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") + else + to_chat(usr, "You do not have a PDA. You should make an issue report about this.") + +/obj/item/device/pda/ai/attack_self(mob/user as mob) + if ((honkamt > 0) && (prob(60)))//For clown virus. + honkamt-- + playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) + return + + +/obj/item/device/pda/ai/pai + ttone = "assist" + + +/* + * The Actual PDA + */ + +/obj/item/device/pda/New() + ..() + PDAs += src + if(default_cartridge) + cartridge = new default_cartridge(src) + new /obj/item/weapon/pen(src) + MM = text2num(time2text(world.timeofday, "MM")) // get the current month + DD = text2num(time2text(world.timeofday, "DD")) // get the day + currentevent1 = pick(currentevents1) + currentevent2 = pick(currentevents2) + currentevent3 = pick(currentevents3) + onthisday = pick(history) + didyouknow = pick(facts) + +/obj/item/device/pda/proc/can_use(mob/user) + if(user && ismob(user)) + if(user.stat || user.restrained() || user.paralysis || user.stunned || user.weakened) + return 0 + if(loc == user) + return 1 + return 0 + +/obj/item/device/pda/GetAccess() + if(id) + return id.GetAccess() + else + return ..() + +/obj/item/device/pda/GetID() + return id + +/obj/item/device/pda/MouseDrop(obj/over_object as obj, src_location, over_location) + var/mob/M = usr + if((!istype(over_object, /obj/screen)) && can_use(M)) + return attack_self(M) + return + +//NOTE: graphic resources are loaded on client login +/obj/item/device/pda/attack_self(mob/user as mob) + + user.set_machine(src) + + if(active_uplink_check(user)) + return + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:313: var/dat = "Personal Data Assistant" + var/dat = {"Personal Data Assistant + Close"} + // END AUTOFIX + if ((!isnull(cartridge)) && (mode == 0)) + dat += " | Eject [cartridge]" + if (mode) + dat += " | Return" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:321: dat += " | Refresh" + dat += {"| Refresh +
              "} + // END AUTOFIX + if (!owner) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:326: dat += "Warning: No owner information entered. Please swipe card.

              " + dat += {"Warning: No owner information entered. Please swipe card.

              + Retry"} + // END AUTOFIX + else + switch (mode) + if (0) + + if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. + var/datum/asset/simple/C = new/datum/asset/simple/pda() + send_asset_list(user.client, C.assets) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:331: dat += "

              PERSONAL DATA ASSISTANT v.1.3

              " + dat += {"

              PERSONAL DATA ASSISTANT v.1.3

              + Owner: [owner], [ownjob]
              "} + // END AUTOFIX + dat += text("ID: [id ? "[id.registered_name], [id.assignment]" : "----------"]") + dat += text("
              [id ? "Update PDA Info" : ""]

              ") + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:336: dat += "Station Time: [worldtime2text()]"//:[world.time / 100 % 6][world.time / 100 % 10]" + dat += {"Station Time: [worldtime2text()] +

              +

              General Functions

              + " + dat += {"

              Applications

              "} + + if(applications.len == 0) + dat += {"No application currently installed."} + else + dat += {"
                "} + for(var/datum/pda_app/app in applications) + if(app.menu) + dat += {"
              • [app.icon ? " " : ""][app.name]
              • "} + else + dat += {"
              • [app.icon ? " " : ""][app.name]
              • "} + dat += {"
              "} + + if (cartridge) + if (cartridge.access_engine || cartridge.access_atmos) + dat += {"

              Engineering Functions

              + "} + + if (cartridge.access_mechanic) + dat += {"

              Mechanic Functions

              + "} + + if (cartridge.access_medical) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:360: dat += "

              Medical Functions

              " + dat += {"

              Medical Functions

              + "} + // END AUTOFIX + if (cartridge.access_security) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:366: dat += "

              Security Functions

              " + dat += {"

              Security Functions

              +
                +
              • Security Records
              • "} + // END AUTOFIX + if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:370: dat += "
              • Security Bot Access
              • " + dat += {"
              • Security Bot Access
              • +
              "} + // END AUTOFIX + else dat += "
            " + if(cartridge.access_quartermaster) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:374: dat += "

            Quartermaster Functions:

            " + dat += {"

            Quartermaster Functions:

            + "} + // END AUTOFIX + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:379: dat += "
          " + dat += {"
        +

        Utilities

        + " + + if (1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:407: dat += "

        Notekeeper V2.1

        " + dat += {"

        Notekeeper V2.1

        + Edit
        "} + // END AUTOFIX + dat += note + + if (2) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:412: dat += "

        SpaceMessenger V3.9.4

        " + dat += {"

        SpaceMessenger V3.9.4

        + Ringer: [silent == 1 ? "Off" : "On"] | + Send / Receive: [toff == 1 ? "Off" : "On"] | + Set Ringtone | + Messages
        "} + // END AUTOFIX + if (istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + dat += "[cartridge:shock_charges] detonation charges left.
        " + if (istype(cartridge, /obj/item/weapon/cartridge/clown)) + dat += "[cartridge:honk_charges] viral files left.
        " + if (istype(cartridge, /obj/item/weapon/cartridge/mime)) + dat += "[cartridge:mime_charges] viral files left.
        " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:425: dat += "

        Detected PDAs

        " + dat += {"

        Detected PDAs

        +
          "} + // END AUTOFIX + var/count = 0 + + if (!toff) + for (var/obj/item/device/pda/P in sortNames(get_viewable_pdas())) + if (P == src) continue + if(P.hidden) continue + dat += "
        • [P]" + if (id && !istype(P,/obj/item/device/pda/ai)) + dat += " (*Send Money*)" + if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate) + dat += " (*Detonate*)" + if (istype(cartridge, /obj/item/weapon/cartridge/clown)) + dat += " (*Send Virus*)" + if (istype(cartridge, /obj/item/weapon/cartridge/mime)) + dat += " (*Send Virus*)" + dat += "
        • " + count++ + dat += "
        " + if (count == 0) + dat += "None detected.
        " + + if(21) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:448: dat += "

        SpaceMessenger V3.9.4

        " + dat += {"

        SpaceMessenger V3.9.4

        + Clear Messages +

        Messages

        "} + // END AUTOFIX + dat += tnote + dat += "
        " + + if (3) + dat += "

        Atmospheric Readings

        " + + var/turf/T = get_turf(user.loc) + if (isnull(T)) + dat += "Unable to obtain a reading.
        " + else + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + + dat += "Air Pressure: [round(pressure,0.1)] kPa
        " + + if (total_moles) + var/o2_level = environment.oxygen/total_moles + var/n2_level = environment.nitrogen/total_moles + var/co2_level = environment.carbon_dioxide/total_moles + var/plasma_level = environment.toxins/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:476: dat += "Nitrogen: [round(n2_level*100)]%
        " + dat += {"Nitrogen: [round(n2_level*100)]%
        + Oxygen: [round(o2_level*100)]%
        + Carbon Dioxide: [round(co2_level*100)]%
        + Plasma: [round(plasma_level*100)]%
        "} + // END AUTOFIX + if(unknown_level > 0.01) + dat += "OTHER: [round(unknown_level)]%
        " + dat += "Temperature: [round(environment.temperature-T0C)]°C
        " + dat += "
        " + + if (5) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\\\pDA.dm:486: dat += "

        Nanotrasen Relay Chat

        " + dat += {"

        Nanotrasen Relay Chat

        +

        Detected Channels

        :
      • "} + // END AUTOFIX + for(var/datum/chatroom/C in chatrooms) + dat += "#[html_encode(lowertext(C.name))]" + if(C.password != "") + dat += " " + dat += "
      • " + + if (41) //Allows everyone to access crew + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:281: menu = "

        Crew Manifest

        " + dat += {"

        Crew Manifest

        + Entries cannot be modified from this terminal.

        "} + // END AUTOFIX + if(data_core) + dat += data_core.get_manifest(1) // make it monochrome + dat += "
        " + + if (50) //Current events. + dat += {"

        Current Events

        + Station Time: [worldtime2text()].
        + Empire Date: [MM]/[DD]/[game_year].

        + Current Events,
        +
      • [currentevent1] +
      • [currentevent2]

      • +
      • [currentevent3]


      • + On this day,
        +
      • [onthisday]


      • + Did you know...
        +
      • [didyouknow]

      • "} + + if (PDA_APP_RINGER) + var/datum/pda_app/ringer/app = locate(/datum/pda_app/ringer) in applications + dat += {"

        Ringer Application

        "} + if(app) + dat += {" + Status:
        [app.status ? "On" : "Off"]
        + Frequency: + - + - + [format_frequency(app.frequency)] + + + +
        +
        + "} + + if (PDA_APP_SPAMFILTER) + var/datum/pda_app/spam_filter/app = locate(/datum/pda_app/spam_filter) in applications + dat += {"

        Spam Filtering Application

        "} + if(app) + dat += {" + + "} + + if (PDA_APP_BALANCECHECK) + var/datum/pda_app/balance_check/app = locate(/datum/pda_app/balance_check) in applications + dat += {"

        Virtual Wallet and Balance Check Application

        "} + if(app) + if(!id) + dat += {"Insert an ID card in the PDA to use this application."} + else + if(!id.virtual_wallet) + id.update_virtual_wallet() + dat += {"
        +
        Virtual Wallet
        + Owner: [id.virtual_wallet.owner_name]
        + Balance: [id.virtual_wallet.money]$ Print Currency +
        Transaction History
        + On [MM]/[DD]/[game_year]: +
          + "} + var/list/v_log = list() + for(var/e in id.virtual_wallet.transaction_log) + v_log += e + for(var/datum/transaction/T in reverseRange(v_log)) + dat += {"
        • \[[T.time]\] [T.amount]$, [T.purpose] at [T.source_terminal]
        • "} + dat += {"

        "} + if(!(app.linked_db)) + app.reconnect_database() + if(app.linked_db) + if(app.linked_db.activated) + var/datum/money_account/D = app.linked_db.attempt_account_access(id.associated_account_number, 0, 2, 0) + if(D) + dat += {" +
        Bank Account
        + Owner: [D.owner_name]
        + Balance: [D.money]$ +
        Transaction History
        + On [MM]/[DD]/[game_year]: +
          + "} + var/list/t_log = list() + for(var/e in D.transaction_log) + t_log += e + for(var/datum/transaction/T in reverseRange(t_log)) + if(T.purpose == "Account creation")//always the last element of the reverse transaction_log + dat += {"
        + On [(DD == 1) ? "[((MM-2)%12)+1]" : "[MM]"]/[((DD-2)%30)+1]/[(DD == MM == 1) ? "[game_year - 1]" : "[game_year]"]: +
          +
        • \[[T.time]\] [T.amount]$, [T.purpose] at [T.source_terminal]
        • +
        "} + else + dat += {"
      • \[[T.time]\] [T.amount]$, [T.purpose] at [T.source_terminal]
      • "} + if(!D.transaction_log.len) + dat += {"
      "} + else + dat += {" +
      Bank Account
      + Unable to access bank account. Either its security settings don't allow remote checking or the account is nonexistent. + "} + else + dat += {" +
      Bank Account
      + Unfortunately your station's Accounts Database doesn't allow remote access. Negociate with your HoP or Captain to solve this issue. + "} + else + dat += {" +
      Bank Account
      + Unable to connect to accounts database. The database is either nonexistent, inoperative, or too far away. + "} + + if (PDA_APP_STATIONMAP) + var/datum/pda_app/station_map/app = locate(/datum/pda_app/station_map) in applications + dat += {"

      Station Map Application

      "} + if(app) + var/turf/T = get_turf(src.loc) + + if(!fexists("icons/pda_icons/pda_minimap_[map.nameShort].png")) + dat += {"It appears that our services have yet to produce a minimap of this station. We apologize for the inconvenience."} + + if(T.z == map.zMainStation) + dat += {"Current Location: [T.loc.name] ([T.x-WORLD_X_OFFSET[map.zMainStation]],[T.y-WORLD_Y_OFFSET[map.zMainStation]],1)
      "} //it's a "Station Map" app, so it only gives information reguarding + else //the station's z-level + dat += {"Current Location: Unknown
      "} + + if(fexists("icons/pda_icons/pda_minimap_[map.nameShort].png")) + dat += {" +
      + + "} + if(T.z == map.zMainStation) + dat += {""} + for(var/datum/minimap_marker/mkr in app.markers) + dat += {""} + dat += {"
      "} + + else + dat += {" +
      + + "} + if(T.z == map.zMainStation) + dat += {""} + for(var/datum/minimap_marker/mkr in app.markers) + dat += {""} + dat += {"
      "} + +/* + dat += {" +
      + + "} + if(T.z == map.zMainStation) + dat += {""} + for(var/datum/minimap_marker/mkr in app.markers) + dat += {""} + + dat += {"
      "} +*/ + dat += {"
      Markers
      + X=[app.markx]; + Y=[app.marky]; + Add New Marker + "} + + if(!(app.markers.len)) + dat += {"
      no markers"} + else + dat +={"
        "} + for(var/datum/minimap_marker/mkr in app.markers) + dat += {"
      • [mkr.name] ([mkr.x]/[mkr.y]) remove
      • "} + dat += {"
      "} + + if (PDA_APP_SNAKEII) + if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. + var/datum/asset/simple/C = new/datum/asset/simple/pda_snake() + send_asset_list(user.client, C.assets) + + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + dat += {"

      Snake II -+

      "} + if(app) + dat += {"
      +
      + + "} + if(!app.ingame) + dat += {""} + dat += {""} + var/list/templist = app.highscores[app.snake_game.level] + var/list/winnerlist = snake_station_highscores[app.snake_game.level] + dat += {""} + dat += {""} + dat += {""} + dat += {""} + dat += {""} + dat += {""} + dat += {""} + dat += {""} + dat += {""} + var/list/snakebestlist = snake_best_players[app.snake_game.level] + dat += "
      (Station Highscore held by [snakebestlist[app.labyrinth+1]])" + dat += "
      Set speed: " + for(var/x=1;x<=9;x++) + if(x == app.snake_game.level) + dat += "[x], " + else + dat += "[x], " + dat += "
      Set labyrinth: [!app.labyrinth ? "None" : "None"], " + for(var/x=1;x<=7;x++) + if(x == app.labyrinth) + dat += "[x], " + else + dat += "[x], " + dat += "
      Gyroscope (orient yourself to control): " + if(app.snake_game.gyroscope) + dat += "ON" + else + dat +="OFF" + else + if(app.labyrinth) + dat += {""} + for(var/datum/snake/body/B in app.snake_game.snakeparts) + var/body_dir = "" + if(B.life == 1) + switch(B.dir) + if(EAST) + body_dir = "pda_snake_bodytail_east" + if(WEST) + body_dir = "pda_snake_bodytail_west" + if(NORTH) + body_dir = "pda_snake_bodytail_north" + if(SOUTH) + body_dir = "pda_snake_bodytail_south" + else if(B.life > 1) + if(B.corner) + switch(B.dir) + if(EAST) + switch(B.corner) + if(SOUTH) + body_dir = "pda_snake_bodycorner_eastsouth2" + if(NORTH) + body_dir = "pda_snake_bodycorner_eastnorth2" + if(WEST) + switch(B.corner) + if(SOUTH) + body_dir = "pda_snake_bodycorner_westsouth2" + if(NORTH) + body_dir = "pda_snake_bodycorner_westnorth2" + if(NORTH) + switch(B.corner) + if(EAST) + body_dir = "pda_snake_bodycorner_eastnorth" + if(WEST) + body_dir = "pda_snake_bodycorner_westnorth" + if(SOUTH) + switch(B.corner) + if(EAST) + body_dir = "pda_snake_bodycorner_eastsouth" + if(WEST) + body_dir = "pda_snake_bodycorner_westsouth" + else + switch(B.dir) + if(EAST) + body_dir = "pda_snake_body_east" + if(WEST) + body_dir = "pda_snake_body_west" + if(NORTH) + body_dir = "pda_snake_body_north" + if(SOUTH) + body_dir = "pda_snake_body_south" + + if(B.isfull) + body_dir += "_full" + if(!B.flicking) + dat += {""} + + dat += {""} + + if(app.snake_game.next_bonus.life > 0) + dat += {""} + dat += {""} + dat += {""} + dat += {""} + + dat += {""} + dat += {""} + dat += {""} + dat += {""} + + var/head_dir = "" + switch(app.snake_game.head.dir) + if(EAST) + head_dir = "pda_snake_head_east" + if(WEST) + head_dir = "pda_snake_head_west" + if(NORTH) + head_dir = "pda_snake_head_north" + if(SOUTH) + head_dir = "pda_snake_head_south" + if(app.snake_game.head.open_mouth) + head_dir += "_open" + if(!app.snake_game.head.flicking) + dat += {""} + if(app.paused) + dat += {""} + dat += {"
      "} + + dat += {"
      Controls
      + +
      + +
      + "} + + if (PDA_APP_MINESWEEPER) + if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. + var/datum/asset/simple/C = new/datum/asset/simple/pda_mine() + send_asset_list(user.client, C.assets) + + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + dat += {"

      Minesweeper

      "} + if(app) + dat += {"
      +
      + + "} + if(!app.ingame) + for(var/datum/mine_tile/T in app.minesweeper_game.tiles) + dat += {""} + else + for(var/datum/mine_tile/T in app.minesweeper_game.tiles) + var/mine_icon = "" + if(T.dug) + if(T.mined) + mine_icon = "minesweeper_tile_mine_splode" + else if(T.num) + mine_icon = "minesweeper_tile_[T.num]" + else + mine_icon = "minesweeper_tile_empty" + + else + if(T.mined && app.minesweeper_game.gameover) + if(T.flagged == 1) + mine_icon = "minesweeper_tile_flag" + else + mine_icon = "minesweeper_tile_mine_unsplode" + else if(T.flagged == 1) + if(app.minesweeper_game.gameover) + mine_icon = "minesweeper_tile_mine_wrong" + else + mine_icon = "minesweeper_tile_flag" + else if(T.flagged == 2) + mine_icon = "minesweeper_tile_question" + else + mine_icon = "minesweeper_tile_full" + if(T.selected && !app.minesweeper_game.gameover) + mine_icon += "_selected" + dat += {""} + dat += {""} + dat += {""} + dat += {""} + + dat += {""} + dat += {""} + + dat += {""} + var/mine_counter = app.minesweeper_game.initial_mines + for(var/datum/mine_tile/T in app.minesweeper_game.tiles) + if(T.flagged == 1) + mine_counter-- + dat += {""} + dat += {""} + dat += {""} + + dat += {""} + var/time_counter = round((world.time - app.minesweeper_game.timer)/10) + time_counter = min(999,time_counter) + if(!app.ingame || app.minesweeper_game.gameover) + time_counter = app.minesweeper_game.end_timer + dat += {""} + dat += {""} + dat += {""} + + dat += {""} + dat += {""} + dat += {""} + dat += {""} + for(var/x=1;x<=app.minesweeper_game.columns;x++) + dat += {""} + for(var/x=1;x<=app.minesweeper_game.columns;x++) + dat += {""} + for(var/y=0;y"} + for(var/y=0;y"} + + + dat += {"
      "} + if(app.minesweeper_game.current_difficulty != "custom") + dat += {"
      [app.minesweeper_game.current_difficulty] difficulty highscore held by [minesweeper_best_players[app.minesweeper_game.current_difficulty]] (in [minesweeper_station_highscores[app.minesweeper_game.current_difficulty]] seconds)"} + + + if (PDA_APP_SPESSPETS) + if(user.client) //If we have a client to send to, in reality none of this proc is needed in that case but eh I don't care. + var/datum/asset/simple/C = new/datum/asset/simple/pda_spesspets() + send_asset_list(user.client, C.assets) + + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + dat += {"

      Spess Pets

      "} + if(app) + dat += {"
      Name = [app.petname]
      Level = [app.level]
      +
      + + "} + switch(app.game_state) + if(0) //First Statup + dat += {"
      "} + + dat += {""} + dat += {"
      "} + if(1) //Hatching + var/eggstate = 0 + if(app.hatching > 1200) + eggstate = 3 + else if(app.hatching > 600) + eggstate = 2 + else if(app.hatching > 300) + eggstate = 1 + dat += {""} + if(eggstate >= 2) + dat += {""} + + if(2) //Normal + if(app.ishungry) + dat += {""} + if(app.isdirty) + dat += {""} + if(app.ishurt) + dat += {""} + if(app.isatwork) + dat += {""} + else + dat += {""} + if(app.issleeping) + dat += {""} + else + dat += {""} + dat += {""} + if(app.ishungry) + dat += {""} + if(app.isdirty) + dat += {""} + if(app.ishurt) + dat += {""} + dat += {""} + dat += {""} + if(app.level >= 16) + dat += {""} + if(app.total_coins) + dat += {""} + if(app.total_coins) + dat += {""} + + dat += {""} + if(3) //Dead + dat += {""} + if(app.last_spoken != "") + dat += {"



      [app.last_spoken]"} + if(app.total_coins) + dat += {"
      nanocoins: [app.total_coins]"} + + else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub. + dat += cart + + dat += "" + user << browse(dat, "window=pda;size=400x444;border=1;can_resize=1;can_close=0;can_minimize=0") + onclose(user, "pda", src) + +/obj/item/device/pda/Topic(href, href_list) + ..() + var/mob/living/U = usr + //Looking for master was kind of pointless since PDAs don't appear to have one. + //if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) ) ) + + if(can_use(U)) //Why reinvent the wheel? There's a proc that does exactly that. + add_fingerprint(U) + U.set_machine(src) + + switch(href_list["choice"]) + +//BASIC FUNCTIONS=================================== + + if("Close")//Self explanatory + U.unset_machine() + U << browse(null, "window=pda") + return + if("Refresh")//Refresh, goes to the end of the proc. + if("Return")//Return + if((mode<=9) || (locate(mode) in pda_app_menus)) + mode = 0 + else + mode = round(mode/10)//TODO: fix this shit up + if((mode==4) || (mode==5))//Fix for cartridges. Redirects to hub. + mode = 0 + else if(mode >= 40 && mode <= 53)//Fix for cartridges. Redirects to refresh the menu. + cartridge.mode = mode + cartridge.unlock() + if ("Authenticate")//Checks for ID + id_check(U, 1) + if("UpdateInfo") + ownjob = id.assignment + name = "PDA-[owner] ([ownjob])" + if("Eject")//Ejects the cart, only done from hub. + if (!isnull(cartridge)) + var/turf/T = loc + if(ismob(T)) + T = T.loc + cartridge.loc = T + scanmode = 0 + if (cartridge.radio) + cartridge.radio.hostpda = null + cartridge = null + +//MENU FUNCTIONS=================================== + + if("0")//Hub + mode = 0 + if("1")//Notes + mode = 1 + if("2")//Messenger + mode = 2 + if("21")//Read messeges + mode = 21 + if("3")//Atmos scan + mode = 3 + if("4")//Redirects to hub + mode = 0 + if("41") + mode = 41 + if("chatroom") // chatroom hub + mode = 5 + +//APPLICATIONS FUNCTIONS=========================== + + if(PDA_APP_RINGER) + mode = PDA_APP_RINGER + if("toggleDeskRinger") + var/datum/pda_app/ringer/app = locate(/datum/pda_app/ringer) in applications + if(app) + app.status = !(app.status) + if("ringerFrequency") + var/datum/pda_app/ringer/app = locate(/datum/pda_app/ringer) in applications + if(app) + var/i = app.frequency + text2num(href_list["rfreq"]) + if(i < MINIMUM_FREQUENCY) + i = 1201 + if(i > MAXIMUM_FREQUENCY) + i = 1599 + app.frequency = i + if(PDA_APP_SPAMFILTER) + mode = PDA_APP_SPAMFILTER + if("setFilter") + var/datum/pda_app/spam_filter/app = locate(/datum/pda_app/spam_filter) in applications + if(app) + app.function = text2num(href_list["filter"]) + if(PDA_APP_BALANCECHECK) + mode = PDA_APP_BALANCECHECK + if("printCurrency") + var/mob/user = usr + var/amount = round(input("How much money do you wish to print?", "Currency Printer", 0) as num) + if(!amount || (amount < 0) || (id.virtual_wallet.money <= 0)) + to_chat(user, "\icon[src]The PDA's screen flashes, 'Invalid value.'") + return + if(amount > id.virtual_wallet.money) + amount = id.virtual_wallet.money + if(amount > 10000) // prevent crashes + to_chat(user, "\icon[src]The PDA's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 10,000.'") + amount = 10000 + + id.virtual_wallet.money -= amount + withdraw_arbitrary_sum(user,amount) + if(prob(50)) + playsound(get_turf(src), 'sound/items/polaroid1.ogg', 50, 1) + else + playsound(get_turf(src), 'sound/items/polaroid2.ogg', 50, 1) + + var/datum/transaction/T = new() + T.target_name = user.name + T.purpose = "Currency printed" + T.amount = "-[amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + id.virtual_wallet.transaction_log.Add(T) + + if(PDA_APP_STATIONMAP) + mode = PDA_APP_STATIONMAP + + if("minimapMarker") + var/datum/pda_app/station_map/app = locate(/datum/pda_app/station_map) in applications + switch(href_list["mMark"]) + if("x") + var/new_x = input("Please input desired X coordinate.", "Station Map App", app.markx) as num + var/x_validate=new_x+WORLD_X_OFFSET[map.zMainStation] + if(x_validate < 1 || x_validate > 255) + to_chat(usr, "Error: Invalid X coordinate.") + else + app.markx = new_x + if("y") + var/new_y = input("Please input desired Y coordinate.", "Station Map App", app.marky) as num + var/y_validate=new_y+WORLD_Y_OFFSET[map.zMainStation] + if(y_validate < 1 || y_validate > 255) + to_chat(usr, "Error: Invalid Y coordinate.") + else + app.marky = new_y + if("add") + var/marker_name = copytext(sanitize(input("Give a name to your marker", "Station Map App", "default marker") as null|text),1,MAX_NAME_LEN) + var/datum/minimap_marker/mkr = new/datum/minimap_marker() + mkr.x = app.markx + mkr.y = app.marky + mkr.name = marker_name + app.markers += mkr + mkr.num = app.markers.len + + if("removeMarker") + var/datum/pda_app/station_map/app = locate(/datum/pda_app/station_map) in applications + var/to_remove = text2num(href_list["rMark"]) + var/datum/minimap_marker/mkr = app.markers[to_remove] + qdel(mkr) + mkr = null + +//GAME FUNCTIONS==================================== + + if(PDA_APP_SNAKEII) + mode = PDA_APP_SNAKEII + + if("snakeNewGame") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.ingame = 1 + app.snake_game.game_start() + app.game_tick(usr) + + if("snakeUp") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.snake_game.lastinput = NORTH + + if("snakeLeft") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.snake_game.lastinput = WEST + + if("snakeRight") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.snake_game.lastinput = EAST + + if("snakeDown") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.snake_game.lastinput = SOUTH + + if("snakeUnPause") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.pause(usr) + + if("snakeLabyrinth") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.labyrinth = text2num(href_list["lType"]) + app.snake_game.set_labyrinth(text2num(href_list["lType"])) + + if("snakeLevel") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.snake_game.level = text2num(href_list["sLevel"]) + + if("snakeGyro") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.snake_game.gyroscope = text2num(href_list["gSet"]) + + if("snakeVolume") + var/datum/pda_app/snake/app = locate(/datum/pda_app/snake) in applications + app.volume += text2num(href_list["vChange"]) + app.volume = max(0,app.volume) + app.volume = min(6,app.volume) + + if(PDA_APP_MINESWEEPER) + mode = PDA_APP_MINESWEEPER + + if("mineNewGame") + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + var/datum/mine_tile/T = locate(href_list["mTile"]) + app.ingame = 1 + app.minesweeper_game.game_start(T) + app.game_tick(usr) + + if("mineDig") + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + var/datum/mine_tile/T = locate(href_list["mTile"]) + app.minesweeper_game.dig_tile(T) + app.game_tick(usr) + + if("mineFlag") + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + if(!app.minesweeper_game.gameover) + for(var/datum/mine_tile/T in app.minesweeper_game.tiles) + if(!T.dug && T.selected) + if(!T.flagged) + T.flagged = 1 + else if(T.flagged == 2) + T.flagged = 1 + else + T.flagged = 0 + + if("mineQuestion") + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + if(!app.minesweeper_game.gameover) + for(var/datum/mine_tile/T in app.minesweeper_game.tiles) + if(!T.dug && T.selected) + if(!T.flagged) + T.flagged = 2 + else if(T.flagged == 1) + T.flagged = 2 + else + T.flagged = 0 + + if("mineSettings") + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + if(alert(usr, "Changing the settings will reset the game, are you sure?", "Minesweeper Settings", "Yes", "No") != "Yes") + return + var/list/difficulties = list( + "beginner", + "intermediate", + "expert", + "custom", + ) + var/choice = input("What Difficulty?", "Minesweeper Settings") in difficulties + app.minesweeper_game.set_difficulty(choice) + app.ingame = 0 + + if("mineReset") + var/datum/pda_app/minesweeper/app = locate(/datum/pda_app/minesweeper) in applications + app.minesweeper_game.face = "press" + app.game_update(usr) + sleep(5) + app.minesweeper_game.reset_game() + app.ingame = 0 + + if(PDA_APP_SPESSPETS) + mode = PDA_APP_SPESSPETS + + if("eggPrev") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.previous_egg() + + if("eggNext") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.next_egg() + + if("eggChose") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.game_state = 1 + app.game_tick(usr) + app.petname = copytext(sanitize(input(usr, "What name for your new pet?", "Name your new pet", "[app.petname]") as null|text),1,MAX_NAME_LEN) + app.last_spoken = "" + + if("eggHatch") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_hatch() + + if("eggTalk") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_talk() + + if("eggWalk") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_walk() + + if("eggFeed") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_feed() + + if("eggClean") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_clean() + + if("eggHeal") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_heal() + + if("eggFight") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_fight() + + if("eggVisit") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_visit() + + if("eggWork") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_work() + + if("eggRate") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_rates() + + if("eggCash") + var/datum/pda_app/spesspets/app = locate(/datum/pda_app/spesspets) in applications + app.button_cash() + + + +//MAIN FUNCTIONS=================================== + + if("Light") + if(fon) + fon = 0 + set_light(0) + else + fon = 1 + set_light(f_lum) + if("Medical Scan") + if(scanmode == 1) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_medical)) + scanmode = 1 + if("Reagent Scan") + if(scanmode == 3) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner)) + scanmode = 3 + if("Halogen Counter") + if(scanmode == 4) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_engine)) + scanmode = 4 + if("Honk") + if ( !(last_honk && world.time < last_honk + 20) ) + playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) + last_honk = world.time + if("Gas Scan") + if(scanmode == 5) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_atmos)) + scanmode = 5 + if("Device Analyser") + if(scanmode == 6) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_mechanic)) + if(!dev_analys) + dev_analys = new(src) //let's create that device analyser + dev_analys.max_designs = 5 + scanmode = 6 + +//MESSENGER/NOTE FUNCTIONS=================================== + + if ("Edit") + var/n = input(U, "Please enter message", name, notehtml) as message + if (in_range(src, U) && loc == U) + n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) + if (mode == 1) + note = replacetext(n, "\n", "
      ") + notehtml = n + else + U << browse(null, "window=pda") + return + if("Toggle Messenger") + toff = !toff + if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status + silent = !silent + if("Clear")//Clears messages + tnote = null + if("Ringtone") + var/t = input(U, "Please enter new ringtone", name, ttone) as text + if (in_range(src, U) && loc == U) + if (t) + if(src.hidden_uplink && hidden_uplink.check_trigger(U, trim(lowertext(t)), trim(lowertext(lock_code)))) + to_chat(U, "The PDA softly beeps.") + U << browse(null, "window=pda") + src.mode = 0 + else + t = copytext(sanitize(t), 1, 20) + ttone = t + else + U << browse(null, "window=pda") + return + if("Message") + var/obj/item/device/pda/P = locate(href_list["target"]) + src.create_message(U, P) + + if("transferFunds") + if(!id) + return + var/obj/item/device/pda/P = locate(href_list["target"]) + var/amount = round(input("How much money do you wish to transfer to [P.owner]?", "Money Transfer", 0) as num) + if(!amount || (amount < 0) || (id.virtual_wallet.money <= 0)) + to_chat(usr, "\icon[src]The PDA's screen flashes, 'Invalid value.'") + return + if(amount > id.virtual_wallet.money) + amount = id.virtual_wallet.money + + switch(P.receive_funds(owner,amount,name)) + if(1) + to_chat(usr, "\icon[src]The PDA's screen flashes, 'Transaction complete!'") + if(2) + to_chat(usr, "\icon[src]The PDA's screen flashes, 'Transaction complete! The recipient will earn the funds once he enters his ID in his PDA.'") + else + to_chat(usr, "\icon[src]The PDA's screen flashes, 'Error, transaction canceled'") + return + + id.virtual_wallet.money -= amount + var/datum/transaction/T = new() + T.target_name = P.owner + T.purpose = "Money transfer" + T.amount = "-[amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + id.virtual_wallet.transaction_log.Add(T) + + if("Send Honk")//Honk virus + if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch. + var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess. + if(!isnull(P)) + if (!P.toff && cartridge:honk_charges > 0) + cartridge:honk_charges-- + U.show_message("Virus sent!", 1) + P.honkamt = (rand(15,20)) + else + to_chat(U, "PDA not found.") + else + U << browse(null, "window=pda") + return + if("Send Silence")//Silent virus + if(istype(cartridge, /obj/item/weapon/cartridge/mime)) + var/obj/item/device/pda/P = locate(href_list["target"]) + if(!isnull(P)) + if (!P.toff && cartridge:mime_charges > 0) + cartridge:mime_charges-- + U.show_message("Virus sent!", 1) + P.silent = 1 + P.ttone = "silence" + else + to_chat(U, "PDA not found.") + else + U << browse(null, "window=pda") + return + + +//SYNDICATE FUNCTIONS=================================== + + if("Toggle Door") + if(cartridge && cartridge.access_remote_door) + for(var/obj/machinery/door/poddoor/M in poddoors) + if(M.id_tag == cartridge.remote_door_id) + if(M.density) + M.open() + else + M.close() + + if("Detonate")//Detonate PDA + if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + var/obj/item/device/pda/P = locate(href_list["target"]) + if(!isnull(P)) + if (!P.toff && cartridge:shock_charges > 0) + cartridge:shock_charges-- + + var/difficulty = 0 + + if(P.cartridge) + difficulty += P.cartridge.access_medical + difficulty += P.cartridge.access_security + difficulty += P.cartridge.access_engine + difficulty += P.cartridge.access_clown + difficulty += P.cartridge.access_janitor + difficulty += P.cartridge.access_manifest * 2 + else + difficulty += 2 + + if(prob(difficulty * 12) || (P.hidden_uplink)) + U.show_message("An error flashes on your [src].", 1) + else if (prob(difficulty * 3)) + U.show_message("Energy feeds back into your [src]!", 1) + U << browse(null, "window=pda") + explode() + log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up") + message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up", 1) + else + U.show_message("Success!", 1) + log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge and succeded") + message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge and succeded", 1) + P.explode() + else + to_chat(U, "PDA not found.") + else + U.unset_machine() + U << browse(null, "window=pda") + return + +//pAI FUNCTIONS=================================== + if("pai") + switch(href_list["option"]) + if("1") // Configure pAI device + pai.attack_self(U) + if("2") // Eject pAI device + var/turf/T = get_turf(src.loc) + if(T) + pai.loc = T + +//LINK FUNCTIONS=================================== + + else//Cartridge menu linking + mode = text2num(href_list["choice"]) + if(cartridge) + cartridge.mode = mode + cartridge.unlock() + else//If not in range, can't interact or not using the pda. + U.unset_machine() + U << browse(null, "window=pda") + return + +//EXTRA FUNCTIONS=================================== + + if (mode == 2||mode == 21)//To clear message overlays. + overlays.len = 0 + + if ((honkamt > 0) && (prob(60)))//For clown virus. + honkamt-- + playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) + + if(U.machine == src && href_list["skiprefresh"]!="1")//Final safety. + attack_self(U)//It auto-closes the menu prior if the user is not in range and so on. + else + U.unset_machine() + U << browse(null, "window=pda") + return + +//Convert money from the virtual wallet into physical bills +/obj/item/device/pda/proc/withdraw_arbitrary_sum(var/mob/user,var/arbitrary_sum) + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(istype(H.wear_id,/obj/item/weapon/storage/wallet)) + dispense_cash(arbitrary_sum,H.wear_id) + to_chat(usr, "\icon[src]Funds were transferred into your physical wallet!") + return + dispense_cash(arbitrary_sum,get_turf(src)) + +//Receive money transferred from another PDA +/obj/item/device/pda/proc/receive_funds(var/creditor_name,var/arbitrary_sum,var/other_pda) + var/turf/U = get_turf(src) + if(!silent) + playsound(U, 'sound/machines/twobeep.ogg', 50, 1) + + for (var/mob/O in hearers(3, U)) + if(!silent) O.show_message(text("\icon[src] *[src.ttone]*")) + + var/mob/living/L = null + if(src.loc && isliving(src.loc)) + L = src.loc + else + L = get(src, /mob/living/silicon) + + if(L) + to_chat(L, "\icon[src] Money transfer from [creditor_name] ([arbitrary_sum]$) [id ? "" : "Insert your ID in the PDA to receive the funds."]") + + tnote += "← Money transfer from [creditor_name] ([arbitrary_sum]$)
      " + + if(id) + if(!id.virtual_wallet) + id.update_virtual_wallet() + id.virtual_wallet.money += arbitrary_sum + var/datum/transaction/T = new() + T.target_name = creditor_name + T.purpose = "Money transfer" + T.amount = arbitrary_sum + T.source_terminal = other_pda + T.date = current_date_string + T.time = worldtime2text() + id.virtual_wallet.transaction_log.Add(T) + return 1 + else + incoming_transactions |= list(list(creditor_name,arbitrary_sum,other_pda)) + return 2 + +//Receive money transferred from another PDA +/obj/item/device/pda/proc/receive_incoming_transactions(var/obj/item/weapon/card/id/ID_card) + for(var/transac in incoming_transactions) + if(!id.virtual_wallet) + id.update_virtual_wallet() + id.virtual_wallet.money += transac[2] + var/datum/transaction/T = new() + T.target_name = transac[1] + T.purpose = "Money transfer" + T.amount = transac[2] + T.source_terminal = transac[3] + T.date = current_date_string + T.time = worldtime2text() + id.virtual_wallet.transaction_log.Add(T) + + incoming_transactions = list() + + var/mob/living/L = null + if(src.loc && isliving(src.loc)) + L = src.loc + to_chat(L, "\icon[src] Transactions successfully received! ") + + +/obj/item/device/pda/proc/remove_id() + if (id) + if (ismob(loc)) + var/mob/M = loc + M.put_in_hands(id) + to_chat(usr, "You remove the ID from the [name].") + else + id.loc = get_turf(src) + id = null + +/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P) + + + var/t = input(U, "Please enter message", name, null) as text + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t || !istype(P)) + return + if (!in_range(src, U) && loc != U) + return + + if (isnull(P)||P.toff || toff) + return + + if (last_text && world.time < last_text + 5) + return + + if(!can_use(U)) + return + + last_text = world.time + // check if telecomms I/O route 1459 is stable + //var/telecomms_intact = telecomms_process(P.owner, owner, t) + 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. + if(MS.active) + useMS = MS + break + + var/datum/signal/signal = src.telecomms_process() + + var/useTC = 0 + if(signal) + if(signal.data["done"]) + useTC = 1 + var/turf/pos = get_turf(P) + if(pos.z in signal.data["level"]) + useTC = 2 + //Let's make this barely readable + if(signal.data["compression"] > 0) + 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? + to_chat(U, "ERROR: Cannot reach recepient.") + return + useMS.send_pda_message("[P.owner]","[owner]","[t]") + + tnote += "→ To [P.owner]:
      [t]
      " + P.tnote += "← From [owner] ([ownjob]):
      [t]
      " + for(var/mob/dead/observer/M in player_list) + if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA)) // src.client is so that ghosts don't have to listen to mice + M.show_message("PDA Message - [owner] -> [P.owner]: [t]") + + + if (prob(15)) //Give the AI a chance of intercepting the message + var/who = src.owner + if(prob(50)) + who = P:owner + for(var/mob/living/silicon/ai/ai in mob_list) + // Allows other AIs to intercept the message but the AI won't intercept their own message. + if(ai.aiPDA != P && ai.aiPDA != src) + ai.show_message("Intercepted message from [who]: [t]") + + if (!P.silent) + playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1) + for (var/mob/O in hearers(3, P.loc)) + if(!P.silent) O.show_message(text("\icon[P] *[P.ttone]*")) + //Search for holder of the PDA. + var/mob/living/L = null + if(P.loc && isliving(P.loc)) + L = P.loc + //Maybe they are a pAI! + else + L = get(P, /mob/living/silicon) + + if(L) + L.show_message("\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)", 2) + + log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") + P.overlays.len = 0 + P.overlays += image('icons/obj/pda.dmi', "pda-r") + else + to_chat(U, "ERROR: Messaging server is not responding.") + + +/obj/item/device/pda/verb/verb_remove_id() + set category = "Object" + set name = "Remove id" + set src in usr + + if(issilicon(usr)) + return + + if ( can_use(usr) ) + if(id) + remove_id() + else + to_chat(usr, "This PDA does not have an ID in it.") + else + to_chat(usr, "You cannot do this while restrained.") + +obj/item/device/pda/CtrlClick() + if ( can_use(usr) ) // Checks that the PDA is in our inventory. This will be checked by the proc anyways, but we don't want to generate an error message if not. + verb_remove_id(usr) + return + return ..() + +/obj/item/device/pda/verb/verb_remove_pen() + set category = "Object" + set name = "Remove pen" + set src in usr + + if(issilicon(usr)) + return + + if ( can_use(usr) ) + var/obj/item/weapon/pen/O = locate() in src + if(O) + if (istype(loc, /mob)) + var/mob/M = loc + if(M.get_active_hand() == null) + M.put_in_hands(O) + to_chat(usr, "You remove \the [O] from \the [src].") + return + O.loc = get_turf(src) + else + to_chat(usr, "This PDA does not have a pen in it.") + else + to_chat(usr, "You cannot do this while restrained.") + +obj/item/device/pda/AltClick() + if ( can_use(usr) ) // Checks that the PDA is in our inventory. This will be checked by the proc anyways, but we don't want to generate an error message if not. + verb_remove_pen(usr) + return + return ..() + +/obj/item/device/pda/proc/id_check(mob/user as mob, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use. + if(choice == 1) + if (id) + remove_id() + else + var/obj/item/I = user.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + if(user.drop_item(I, src)) + id = I + else + var/obj/item/weapon/card/I = user.get_active_hand() + if (istype(I, /obj/item/weapon/card/id) && I:registered_name) + var/obj/old_id = id + if(user.drop_item(I, src)) + id = I + user.put_in_hands(old_id) + if(id && incoming_transactions.len) + receive_incoming_transactions(id) + return + +// access to status display signals +/obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob) + ..() + if(istype(C, /obj/item/weapon/cartridge) && !cartridge) + if(user.drop_item(C, src)) + cartridge = C + to_chat(user, "You insert [cartridge] into [src].") + if(cartridge.radio) + cartridge.radio.hostpda = src + + else if(istype(C, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/idcard = C + if(!idcard.registered_name) + to_chat(user, "\The [src] rejects the ID.") + return + if(!owner) + owner = idcard.registered_name + ownjob = idcard.assignment + name = "PDA-[owner] ([ownjob])" + to_chat(user, "Card scanned.") + else + //Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand. + if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) ) + if( can_use(user) )//If they can still act. + id_check(user, 2) + to_chat(user, "You put the ID into \the [src]'s slot.") + if(incoming_transactions.len) + receive_incoming_transactions(id) + updateSelfDialog()//Update self dialog on success. + return //Return in case of failed check or when successful. + updateSelfDialog()//For the non-input related code. + else if(istype(C, /obj/item/device/paicard) && !src.pai) + if(user.drop_item(C, src)) + pai = C + to_chat(user, "You slot \the [C] into [src].") + updateUsrDialog() + else if(istype(C, /obj/item/weapon/pen)) + var/obj/item/weapon/pen/O = locate() in src + if(O) + to_chat(user, "There is already a pen in \the [src].") + else + if(user.drop_item(C, src)) + to_chat(user, "You slide \the [C] into \the [src].") + else if(istype(C,/obj/item/weapon/spacecash)) + if(!id) + to_chat(user, "\icon[src]There is no ID in the PDA!") + return + var/obj/item/weapon/spacecash/dosh = C + id.virtual_wallet.money += dosh.worth * dosh.amount + if(prob(50)) + playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) + else + playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) + + var/datum/transaction/T = new() + T.target_name = user.name + T.purpose = "Currency deposit" + T.amount = dosh.worth * dosh.amount + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + id.virtual_wallet.transaction_log.Add(T) + + to_chat(user, "You insert [dosh] into the PDA.") + qdel(dosh) + updateUsrDialog() + + return + +/obj/item/device/pda/attack(mob/living/carbon/C, mob/living/user as mob) + if(istype(C)) + switch(scanmode) + + if(1) + healthanalyze(C,user,0) + + if(2) + if (!istype(C:dna, /datum/dna)) + to_chat(user, "No fingerprints found on [C]") + else if(!istype(C, /mob/living/carbon/monkey)) + if(!isnull(C:gloves)) + to_chat(user, "No fingerprints found on [C]") + else + to_chat(user, text("[C]'s Fingerprints: [md5(C:dna.uni_identity)]")) + if ( !(C:blood_DNA) ) + to_chat(user, "No blood found on [C]") + if(C:blood_DNA) + qdel(C:blood_DNA) + C:blood_DNA = null + else + to_chat(user, "Blood found on [C]. Analysing...") + spawn(15) + for(var/blood in C:blood_DNA) + to_chat(user, "Blood type: [C:blood_DNA[blood]]\nDNA: [blood]") + + if(4) + for (var/mob/O in viewers(C, null)) + O.show_message("[user] has analyzed [C]'s radiation levels!", 1) + + user.show_message("Analyzing Results for [C]:") + if(C.radiation) + user.show_message("Radiation Level: [C.radiation]") + else + user.show_message("No radiation detected.") + +/obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob) + if(scanmode == 5) + if(atmos_analys) + if(A.Adjacent(user)) + if(!A.attackby(atmos_analys, user)) + atmos_analys.afterattack(A, user, 1) + + if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) + note = A:info + to_chat(user, "Paper scanned.")//concept of scanning paper copyright brainoblivion 2009 + + +/obj/item/device/pda/preattack(atom/A as mob|obj|turf|area, mob/user as mob) + switch(scanmode) + if(3) + if(!A.Adjacent(user)) + return + if(!isnull(A.reagents)) + if(A.reagents.reagent_list.len > 0) + var/reagents_length = A.reagents.reagent_list.len + to_chat(user, "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.") + for (var/datum/reagent/re in A.reagents.reagent_list) + to_chat(user, "\t [re]: [re.volume] units") + else + to_chat(user, "No active chemical agents found in [A].") + else + to_chat(user, "No significant chemical agents found in [A].") + . = 1 + + if (6) + if(dev_analys) //let's use this instead. Much neater + if(A.Adjacent(user)) + return dev_analys.preattack(A, user, 1) + +/obj/item/device/pda/proc/explode() //This needs tuning. + if(!src.detonate) return + var/turf/T = get_turf(src.loc) + + if (ismob(loc)) + var/mob/M = loc + M.show_message("Your [src] explodes!", 1) + + if(T) + T.hotspot_expose(700,125,surfaces=istype(loc,/turf)) + + explosion(T, -1, -1, 2, 3) + + qdel(src) + return + +/obj/item/device/pda/Destroy() + PDAs -= src + if (src.id) + src.id.loc = get_turf(src.loc) + if(src.pai) + src.pai.loc = get_turf(src.loc) + ..() + +/obj/item/device/pda/Del() + var/loop_count = 0 + while(null in PDAs) + PDAs.Remove(null) + if(loop_count > 10) break + loop_count++ + PDAs -= src + ..() + +/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery. + if (istype(AM, /mob/living/carbon)) + var/mob/living/carbon/M = AM + if (M.Slip(8, 5)) + to_chat(M, "You slipped on the PDA!") + + if ((istype(M, /mob/living/carbon/human) && (M.real_name != src.owner) && (istype(src.cartridge, /obj/item/weapon/cartridge/clown)))) + var/obj/item/weapon/cartridge/clown/honkcartridge = src.cartridge + if (honkcartridge.honk_charges < 5) + honkcartridge.honk_charges++ + +/obj/item/device/pda/proc/available_pdas() + var/list/names = list() + var/list/plist = list() + var/list/namecounts = list() + + if (toff) + to_chat(usr, "Turn on your receiver in order to send messages.") + return + + for (var/obj/item/device/pda/P in PDAs) + if (!P.owner) + continue + else if(P.hidden) + continue + else if (P == src) + continue + else if (P.toff) + continue + + var/name = P.owner + if (name in names) + namecounts[name]++ + name = text("[name] ([namecounts[name]])") + else + names.Add(name) + namecounts[name] = 1 + + plist[text("[name]")] = P + return plist + + +//Some spare PDAs in a box +/obj/item/weapon/storage/box/PDAs + name = "spare PDAs" + desc = "A box of spare PDA microcomputers." + icon = 'icons/obj/pda.dmi' + icon_state = "pdabox" + + New() + ..() + new /obj/item/device/pda(src) + new /obj/item/device/pda(src) + new /obj/item/device/pda(src) + new /obj/item/device/pda(src) + new /obj/item/weapon/cartridge/head(src) + + 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/quartermaster) + new newcart(src) + +// Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP +/obj/item/device/pda/emp_act(severity) + for(var/atom/A in src) + A.emp_act(severity) + +/proc/get_viewable_pdas() + . = list() + // Returns a list of PDAs which can be viewed from another PDA/message monitor. + for(var/obj/item/device/pda/P in PDAs) + if(!P.owner || P.toff || P.hidden) continue + . += P + return . diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index c4e7a1d04d6..8db95e803a2 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -1,808 +1,808 @@ -/obj/item/weapon/cartridge - name = "generic cartridge" - desc = "A data cartridge for portable microcomputers." - icon = 'icons/obj/pda.dmi' - icon_state = "cart" - item_state = "electronic" - origin_tech = "programming=2" - w_class = 1 - - var/obj/item/radio/integrated/radio = null - var/access_security = 0 - var/access_engine = 0 - var/access_atmos = 0 - var/access_mechanic = 0 - var/access_medical = 0 - var/access_manifest = 1 // Make all jobs able to access the manifest - var/access_clown = 0 - var/access_mime = 0 - var/access_janitor = 0 -// var/access_flora = 0 - var/access_reagent_scanner = 0 - var/access_remote_door = 0 //Control some blast doors remotely!! - var/remote_door_id = "" - var/access_status_display = 0 - var/access_quartermaster = 0 - var/access_hydroponics = 0 - var/mode = null - var/menu - var/datum/data/record/active1 = null //General - var/datum/data/record/active2 = null //Medical - var/datum/data/record/active3 = null //Security - var/obj/machinery/power/monitor/powmonitor = null // Power Monitor - var/list/powermonitors = list() - var/obj/machinery/computer/station_alert/alertmonitor = null // Alert Monitor - var/list/alertmonitors = list() - var/message1 // used for status_displays - var/message2 - var/list/stored_data = list() - -/obj/item/weapon/cartridge/engineering - name = "Power-ON Cartridge" - icon_state = "cart-e" - access_engine = 1 - -/obj/item/weapon/cartridge/atmos - name = "BreatheDeep Cartridge" - icon_state = "cart-a" - access_atmos = 1 - -/obj/item/weapon/cartridge/mechanic - name = "Screw-E Cartridge" - icon_state = "cart-mech" - access_mechanic = 1 - access_engine = 1 //for the power monitor, but may remove later - -/obj/item/weapon/cartridge/medical - name = "Med-U Cartridge" - icon_state = "cart-m" - access_medical = 1 - -/obj/item/weapon/cartridge/chemistry - name = "ChemWhiz Cartridge" - icon_state = "cart-chem" - access_reagent_scanner = 1 - -/obj/item/weapon/cartridge/chef - name = "ChefBuddy Cartridge" - icon_state = "cart-chef" - access_reagent_scanner = 1 - -/obj/item/weapon/cartridge/security - name = "R.O.B.U.S.T. Cartridge" - icon_state = "cart-s" - access_security = 1 - -/obj/item/weapon/cartridge/security/New() - ..() - spawn(5)//giving time for the radio_controller to initialize - radio = new /obj/item/radio/integrated/beepsky(src) - -/obj/item/weapon/cartridge/detective - name = "D.E.T.E.C.T. Cartridge" - icon_state = "cart-s" - access_security = 1 - access_medical = 1 - access_manifest = 1 - - -/obj/item/weapon/cartridge/janitor - name = "CustodiPRO Cartridge" - desc = "The ultimate in clean-room design." - icon_state = "cart-j" - access_janitor = 1 - -/obj/item/weapon/cartridge/lawyer - name = "P.R.O.V.E. Cartridge" - icon_state = "cart-s" - access_security = 1 - -/obj/item/weapon/cartridge/clown - name = "Honkworks 5.0" - icon_state = "cart-clown" - access_clown = 1 - var/honk_charges = 5 - -/obj/item/weapon/cartridge/mime - name = "Gestur-O 1000" - icon_state = "cart-mi" - access_mime = 1 - var/mime_charges = 5 -/* -/obj/item/weapon/cartridge/botanist - name = "Green Thumb v4.20" - icon_state = "cart-b" - access_flora = 1 -*/ - -/obj/item/weapon/cartridge/signal - name = "generic signaler cartridge" - desc = "A data cartridge with an integrated radio signaler module." - -/obj/item/weapon/cartridge/signal/toxins - name = "Signal Ace 2" - desc = "Complete with integrated radio signaler!" - icon_state = "cart-tox" - access_reagent_scanner = 1 - access_atmos = 1 - -/obj/item/weapon/cartridge/signal/New() - ..() - spawn(5)//giving time for the radio_controller to initialize - radio = new /obj/item/radio/integrated/signal(src) - -/obj/item/weapon/cartridge/quartermaster - name = "Space Parts & Space Vendors Cartridge" - desc = "Perfect for the Quartermaster on the go!" - icon_state = "cart-q" - access_quartermaster = 1 - -/obj/item/weapon/cartridge/quartermaster/New() - ..() - spawn(5)//giving time for the radio_controller to initialize - radio = new /obj/item/radio/integrated/mule(src) - -/obj/item/weapon/cartridge/head - name = "Easy-Record DELUXE" - icon_state = "cart-h" - access_manifest = 1 - access_status_display = 1 - -/obj/item/weapon/cartridge/hop - name = "HumanResources9001" - icon_state = "cart-h" - access_manifest = 1 - access_status_display = 1 - access_quartermaster = 1 - access_janitor = 1 - access_security = 1 - -/obj/item/weapon/cartridge/hop/New() - ..() - spawn(5)//giving time for the radio_controller to initialize - radio = new /obj/item/radio/integrated/mule(src) - -/obj/item/weapon/cartridge/hos - name = "R.O.B.U.S.T. DELUXE" - icon_state = "cart-hos" - access_manifest = 1 - access_status_display = 1 - access_security = 1 - -/obj/item/weapon/cartridge/hos/New() - ..() - spawn(5)//giving time for the radio_controller to initialize - radio = new /obj/item/radio/integrated/beepsky(src) - -/obj/item/weapon/cartridge/ce - name = "Power-On DELUXE" - icon_state = "cart-ce" - access_manifest = 1 - access_mechanic = 1 - access_status_display = 1 - access_engine = 1 - access_atmos = 1 - -/obj/item/weapon/cartridge/cmo - name = "Med-U DELUXE" - icon_state = "cart-cmo" - access_manifest = 1 - access_status_display = 1 - access_reagent_scanner = 1 - access_medical = 1 - -/obj/item/weapon/cartridge/rd - name = "Signal Ace DELUXE" - icon_state = "cart-rd" - access_manifest = 1 - access_status_display = 1 - access_reagent_scanner = 1 - access_atmos = 1 - -/obj/item/weapon/cartridge/rd/New() - ..() - spawn(5)//giving time for the radio_controller to initialize - radio = new /obj/item/radio/integrated/signal(src) - -/obj/item/weapon/cartridge/captain - name = "Value-PAK Cartridge" - desc = "Now with 200% more value!" - icon_state = "cart-c" - access_manifest = 1 - access_engine = 1 - access_mechanic = 1 - access_security = 1 - access_medical = 1 - access_reagent_scanner = 1 - access_status_display = 1 - access_atmos = 1 - -/obj/item/weapon/cartridge/syndicate - name = "Detomatix Cartridge" - icon_state = "cart" - access_remote_door = 1 - remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. - origin_tech = "programming=2;syndicate=2" - mech_flags = MECH_SCAN_ILLEGAL - var/shock_charges = 4 - -/obj/item/weapon/cartridge/proc/unlock() - if (!istype(loc, /obj/item/device/pda)) - return - - generate_menu() - print_to_host(menu) - return - -/obj/item/weapon/cartridge/proc/print_to_host(var/text) - if (!istype(loc, /obj/item/device/pda)) - return - - var/obj/item/device/pda/pda_device = loc - - pda_device.cart = text - - for (var/mob/M in viewers(1, pda_device.loc)) - if (M.client && M.machine == pda_device) - pda_device.attack_self(M) - - return - -/obj/item/weapon/cartridge/proc/post_status(var/command, var/data1, var/data2) - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) - - if(!frequency) return - - var/datum/signal/status_signal = getFromPool(/datum/signal) - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - - switch(command) - if("message") - status_signal.data["msg1"] = data1 - status_signal.data["msg2"] = data2 - if(loc) - var/obj/item/PDA = loc - var/mob/user = PDA.fingerprintslast - if(istype(PDA.loc,/mob/living)) - name = PDA.loc - log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") - message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") - - if("alert") - status_signal.data["picture_state"] = data1 - - frequency.post_signal(src, status_signal) - -/obj/item/weapon/cartridge/proc/generate_menu() - switch(mode) - if(40) //signaller - menu = "

      Remote Signaling System

      " - - menu += {" -Send Signal
      -Frequency: -- -- -[format_frequency(radio:frequency)] -+ -+
      -
      -Code: -- -- -[radio:code] -+ -+
      "} - /*if (41) //crew manifest - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:281: menu = "

      Crew Manifest

      " - menu = {"

      Crew Manifest

      - Entries cannot be modified from this terminal.

      "} - // END AUTOFIX - if(data_core) - menu += data_core.get_manifest(1) // make it monochrome - menu += "
      "*/ - - - if (42) //status displays - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:289: menu = "

      Station Status Display Interlink

      " - menu = {"

      Station Status Display Interlink

      - \[ Clear \]
      - \[ Shuttle ETA \]
      - \[ Message \] -
      - \[ Alert: None | - Red Alert | - Lockdown | - Biohazard \]
      "} - // END AUTOFIX - if (43) //Muskets' and Rockdtben's power monitor :D - menu = "

      Please select a Power Monitoring Computer


      No Power Monitoring Computer detected in the vicinity.
      " - var/powercount = 0 - var/found = 0 - - for(var/obj/machinery/power/monitor/pMon in power_machines) - if(!(pMon.stat & (NOPOWER|BROKEN))) - var/turf/T = get_turf(src) - if(T.z == pMon.z)//the application may only detect power monitoring computers on its Z-level. - if(!found) - menu = "

      Please select a Power Monitoring Computer


      " - found = 1 - menu += "" - powercount++ - menu += " [pMon]
      " - powermonitors += "\ref[pMon]" - if(found) - menu += "
      " - - if (433) //Muskets' and Rockdtben's power monitor :D - if(!powmonitor) - menu = "

      Power Monitor


      " - menu += "No connection
      " - else - menu = "

      [powmonitor]


      " - var/list/L = list() - for(var/obj/machinery/power/terminal/term in powmonitor.powernet.nodes) - if(istype(term.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = term.master - L += A - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:338: menu += "
      Total power: [powmonitor.powernet.avail] W
      Total load: [num2text(powmonitor.powernet.viewload,10)] W
      " - menu += {"
      Total power: [powmonitor.powernet.avail] W
      Total load: [num2text(powmonitor.powernet.viewload,10)] W
      - "} - // END AUTOFIX - if(L.len > 0) - menu += "Area Eqp./Lgt./Env. Load Cell
      " - - var/list/S = list(" Off","AOff"," On", " AOn") - var/list/chg = list("N","C","F") - - for(var/obj/machinery/power/apc/A in L) - menu += copytext(add_tspace(A.areaMaster.name, 30), 1, 30) - menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]
      " - - menu += "
      " - - if (53) - menu = "

      Please select an Alert Computer


      No Alert Computer detected in the vicinity.
      " - alertmonitor = null - alertmonitors = list() - - var/alertcount = 0 - var/found = 0 - - for(var/obj/machinery/computer/station_alert/aMon in machines) - if(!(aMon.stat & (NOPOWER|BROKEN))) - var/turf/T = get_turf(src) - if(T.z == aMon.z)//the application may only detect station alert computers on its Z-level. - if(!found) - menu = "

      Please select an Alert Computer


      " - found = 1 - menu += "" - alertcount++ - menu += " [aMon]
      " - alertmonitors += "\ref[aMon]" - if(found) - menu += "
      " - - if (533) - if(!alertmonitor) - menu = "

      Alert Monitor


      " - menu += "No connection
      " - else - menu = "

      [alertmonitor]


      " - for (var/cat in alertmonitor.alarms) - menu += text("[]
      \n", cat) - var/list/L = alertmonitor.alarms[cat] - if (L.len) - for (var/alarm in L) - var/list/alm = L[alarm] - var/area/A = alm[1] - var/list/sources = alm[3] - - menu += {" - • - [A.name]"} - - if (sources.len > 1) - menu += text(" - [] sources", sources.len) - menu += "
      \n" - else - menu += "-- All Systems Nominal
      \n" - menu += "
      \n" - - menu += "
      " - - if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working. - menu = "

      Medical Record List

      " - if(!isnull(data_core.general)) - for (var/datum/data/record/R in sortRecord(data_core.general)) - menu += "[R.fields["id"]]: [R.fields["name"]]
      " - menu += "
      " - if(441) - menu = "

      Medical Record

      " - - if (istype(active1, /datum/data/record) && (active1 in data_core.general)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:364: menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]
      " - menu += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
      - Sex: [active1.fields["sex"]]
      - Age: [active1.fields["age"]]
      - Rank: [active1.fields["rank"]]
      - Fingerprint: [active1.fields["fingerprint"]]
      - Physical Status: [active1.fields["p_stat"]]
      - Mental Status: [active1.fields["m_stat"]]
      "} - // END AUTOFIX - else - menu += "Record Lost!
      " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:374: menu += "
      " - menu += {"
      -

      Medical Data

      "} - // END AUTOFIX - if (istype(active2, /datum/data/record) && (active2 in data_core.medical)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:378: menu += "Blood Type: [active2.fields["b_type"]]

      " - menu += {"Blood Type: [active2.fields["b_type"]]

      - Minor Disabilities: [active2.fields["mi_dis"]]
      - Details: [active2.fields["mi_dis_d"]]

      - Major Disabilities: [active2.fields["ma_dis"]]
      - Details: [active2.fields["ma_dis_d"]]

      - Allergies: [active2.fields["alg"]]
      - Details: [active2.fields["alg_d"]]

      - Current Diseases: [active2.fields["cdi"]]
      - Details: [active2.fields["cdi_d"]]

      - Important Notes: [active2.fields["notes"]]
      "} - // END AUTOFIX - else - menu += "Record Lost!
      " - - menu += "
      " - if (45) //security records - menu = "

      Security Record List

      " - if(!isnull(data_core.general)) - for (var/datum/data/record/R in sortRecord(data_core.general)) - menu += "
      [R.fields["id"]]: [R.fields["name"]]
      " - - menu += "
      " - if(451) - menu = "

      Security Record

      " - - if (istype(active1, /datum/data/record) && (active1 in data_core.general)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:408: menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]
      " - menu += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
      - Sex: [active1.fields["sex"]]
      - Age: [active1.fields["age"]]
      - Rank: [active1.fields["rank"]]
      - Fingerprint: [active1.fields["fingerprint"]]
      - Physical Status: [active1.fields["p_stat"]]
      - Mental Status: [active1.fields["m_stat"]]
      "} - // END AUTOFIX - else - menu += "Record Lost!
      " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:418: menu += "
      " - menu += {"
      -

      Security Data

      "} - // END AUTOFIX - if (istype(active3, /datum/data/record) && (active3 in data_core.security)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:422: menu += "Criminal Status: [active3.fields["criminal"]]
      " - menu += {"Criminal Status: [active3.fields["criminal"]]
      - Minor Crimes: [active3.fields["mi_crim"]]
      - Details: [active3.fields["mi_crim"]]

      - Major Crimes: [active3.fields["ma_crim"]]
      - Details: [active3.fields["ma_crim_d"]]

      - Important Notes:
      - [active3.fields["notes"]]"} - // END AUTOFIX - else - menu += "Record Lost!
      " - - menu += "
      " - if (46) //beepsky control - var/obj/item/radio/integrated/beepsky/SC = radio - if(!SC) - menu = "Interlink Error - Please reinsert cartridge." - return - - menu = "

      Securitron Interlink

      " - - if(!SC.active) - // list of bots - if(!SC.botlist || (SC.botlist && SC.botlist.len==0)) - menu += "No bots found.
      " - - else - for(var/obj/machinery/bot/B in SC.botlist) - if (B) - menu += "
      [B] at [B.loc.loc]
      " - - menu += "
      Scan for active bots
      " - - else // bot selected, control it - - menu += "[SC.active]
      Status: (refresh)
      " - - if(!SC.botstatus) - menu += "Waiting for response...
      " - else - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:464: menu += "Location: [SC.botstatus["loca"] ]
      " - menu += {"Location: [SC.botstatus["loca"] ]
      - Mode: "} - // END AUTOFIX - switch(SC.botstatus["mode"]) - if(0) - menu += "Ready" - if(1) - menu += "Apprehending target" - if(2,3) - menu += "Arresting target" - if(4) - menu += "Starting patrol" - if(5) - menu += "On patrol" - if(6) - menu += "Responding to summons" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:481: menu += "
      \[Stop Patrol\] " - menu += {"
      \[Stop Patrol\] - \[Start Patrol\] - \[Summon Bot\]
      -
      Return to bot list"} - // END AUTOFIX - if (47) //quartermaster order records - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:487: menu = "

      Supply Record Interlink

      " - menu = {"

      Supply Record Interlink

      -
      Supply shuttle
      - Location: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Dock"]
      - Current approved orders:
        "} - // END AUTOFIX - for(var/S in supply_shuttle.shoppinglist) - var/datum/supply_order/SO = S - menu += "
      1. #[SO.ordernum] - [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
      2. " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:495: menu += "
      " - menu += {"
    - Current requests:
      "} - // END AUTOFIX - for(var/S in supply_shuttle.requestlist) - var/datum/supply_order/SO = S - menu += "
    1. #[SO.ordernum] - [SO.object.name] requested by [SO.orderedby]
    2. " - menu += "
    Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." - - if (48) //mulebot control - var/obj/item/radio/integrated/mule/QC = radio - if(!QC) - menu = "Interlink Error - Please reinsert cartridge." - return - - menu = "

    M.U.L.E. bot Interlink V0.8

    " - - if(!QC.active) - // list of bots - if(!QC.botlist || (QC.botlist && QC.botlist.len==0)) - menu += "No bots found.
    " - - else - for(var/obj/machinery/bot/mulebot/B in QC.botlist) - menu += "[B] at [get_area(B)]
    " - menu += "
    Scan for active bots
    " - - else // bot selected, control it - - menu += "[QC.active]
    Status: (refresh)
    " - - if(!QC.botstatus) - menu += "Waiting for response...
    " - else - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:529: menu += "Location: [QC.botstatus["loca"] ]
    " - menu += {"Location: [QC.botstatus["loca"] ]
    - Mode: "} - // END AUTOFIX - switch(QC.botstatus["mode"]) - if(0) - menu += "Ready" - if(1) - menu += "Loading/Unloading" - if(2) - menu += "Navigating to Delivery Location" - if(3) - menu += "Navigating to Home" - if(4) - menu += "Waiting for clear path" - if(5,6) - menu += "Calculating navigation path" - if(7) - menu += "Unable to locate destination" - var/obj/structure/closet/crate/C = QC.botstatus["load"] - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:548: menu += "
    Current Load: [ !C ? "none" : "[C.name] (unload)" ]
    " - menu += {"
    Current Load: [ !C ? "none" : "[C.name] (unload)" ]
    - Destination: [!QC.botstatus["dest"] ? "none" : QC.botstatus["dest"] ] (set)
    - Power: [QC.botstatus["powr"]]%
    - Home: [!QC.botstatus["home"] ? "none" : QC.botstatus["home"] ]
    - Auto Return Home: [QC.botstatus["retn"] ? "On Off" : "(On) Off"]
    - Auto Pickup Crate: [QC.botstatus["pick"] ? "On Off" : "(On) Off"]

    - \[Stop\] - \[Proceed\] - \[Return Home\]
    -
    Return to bot list"} - // END AUTOFIX - if (49) //janitorial locator - menu = "

    Persistent Custodial Object Locator

    " - - var/turf/cl = get_turf(src) - if (cl) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:565: menu += "Current Orbital Location: \[[cl.x],[cl.y]\]" - menu += {"Current Orbital Location: \[[cl.x-WORLD_X_OFFSET[cl.z]],[cl.y-WORLD_Y_OFFSET[cl.z]]\] -

    Located Mops:

    "} - // END AUTOFIX - var/ldat - for (var/obj/item/weapon/mop/M in world) - var/turf/ml = get_turf(M) - - if(ml) - if (ml.z != cl.z) - continue - var/direction = get_dir(src, M) - ldat += "Mop - \[[ml.x-WORLD_X_OFFSET[ml.z]],[ml.y-WORLD_Y_OFFSET[ml.z]] ([uppertext(dir2text(direction))])\] - [M.reagents.total_volume ? "Wet" : "Dry"]
    " - - if (!ldat) - menu += "None" - else - menu += "[ldat]" - - menu += "

    Located Mop Buckets:

    " - - ldat = null - for (var/obj/structure/mopbucket/B in world) - var/turf/bl = get_turf(B) - - if(bl) - if (bl.z != cl.z) - continue - var/direction = get_dir(src, B) - ldat += "Bucket - \[[bl.x-WORLD_X_OFFSET[bl.z]],[bl.y-WORLD_Y_OFFSET[bl.z]] ([uppertext(dir2text(direction))])\] - Water level: [B.reagents.total_volume]/100
    " - - if (!ldat) - menu += "None" - else - menu += "[ldat]" - - menu += "

    Located Cleanbots:

    " - - ldat = null - for (var/obj/machinery/bot/cleanbot/B in world) - var/turf/bl = get_turf(B) - - if(bl) - if (bl.z != cl.z) - continue - var/direction = get_dir(src, B) - ldat += "Cleanbot - \[[bl.x-WORLD_X_OFFSET[bl.z]],[bl.y-WORLD_Y_OFFSET[bl.z]] ([uppertext(dir2text(direction))])\] - [B.on ? "Online" : "Offline"]
    " - - if (!ldat) - menu += "None" - else - menu += "[ldat]" - - else - menu += "ERROR: Unable to determine current location." - menu += "

    Refresh GPS Locator" - - -/obj/item/weapon/cartridge/Topic(href, href_list) - ..() - - if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr.unset_machine() - usr << browse(null, "window=pda") - return - - switch(href_list["choice"]) - if("Medical Records") - var/datum/data/record/R = locate(href_list["target"]) - var/datum/data/record/M = locate(href_list["target"]) - loc:mode = 441 - mode = 441 - if (R in data_core.general) - for (var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - break - active1 = R - active2 = M - - if("Security Records") - var/datum/data/record/R = locate(href_list["target"]) - var/datum/data/record/S = locate(href_list["target"]) - loc:mode = 451 - mode = 451 - if (R in data_core.general) - for (var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - S = E - break - active1 = R - active3 = S - - if("Send Signal") - spawn( 0 ) - radio:send_signal("ACTIVATE") - return - - if("Signal Frequency") - var/new_frequency = sanitize_frequency(radio:frequency + text2num(href_list["sfreq"])) - radio:set_frequency(new_frequency) - - if("Signal Code") - radio:code += text2num(href_list["scode"]) - radio:code = round(radio:code) - radio:code = min(100, radio:code) - radio:code = max(1, radio:code) - - if("Status") - switch(href_list["statdisp"]) - if("message") - post_status("message", message1, message2) - if("alert") - post_status("alert", href_list["alert"]) - if("setmsg1") - message1 = reject_bad_text(trim(copytext(sanitize(input("Line 1", "Enter Message Text", message1) as text|null), 1, 40)), 40) - updateSelfDialog() - if("setmsg2") - message2 = reject_bad_text(trim(copytext(sanitize(input("Line 2", "Enter Message Text", message2) as text|null), 1, 40)), 40) - updateSelfDialog() - else - post_status(href_list["statdisp"]) - if("Power Select") - var/pnum = text2num(href_list["target"]) - powmonitor = locate(powermonitors[pnum]) - if(istype(powmonitor)) - loc:mode = 433 - mode = 433 - - if("Alert Select") - var/pnum = text2num(href_list["target"]) - alertmonitor = locate(alertmonitors[pnum]) - if(istype(alertmonitor)) - loc:mode = 533 - mode = 533 - - generate_menu() - print_to_host(menu) +/obj/item/weapon/cartridge + name = "generic cartridge" + desc = "A data cartridge for portable microcomputers." + icon = 'icons/obj/pda.dmi' + icon_state = "cart" + item_state = "electronic" + origin_tech = "programming=2" + w_class = 1 + + var/obj/item/radio/integrated/radio = null + var/access_security = 0 + var/access_engine = 0 + var/access_atmos = 0 + var/access_mechanic = 0 + var/access_medical = 0 + var/access_manifest = 1 // Make all jobs able to access the manifest + var/access_clown = 0 + var/access_mime = 0 + var/access_janitor = 0 +// var/access_flora = 0 + var/access_reagent_scanner = 0 + var/access_remote_door = 0 //Control some blast doors remotely!! + var/remote_door_id = "" + var/access_status_display = 0 + var/access_quartermaster = 0 + var/access_hydroponics = 0 + var/mode = null + var/menu + var/datum/data/record/active1 = null //General + var/datum/data/record/active2 = null //Medical + var/datum/data/record/active3 = null //Security + var/obj/machinery/power/monitor/powmonitor = null // Power Monitor + var/list/powermonitors = list() + var/obj/machinery/computer/station_alert/alertmonitor = null // Alert Monitor + var/list/alertmonitors = list() + var/message1 // used for status_displays + var/message2 + var/list/stored_data = list() + +/obj/item/weapon/cartridge/engineering + name = "Power-ON Cartridge" + icon_state = "cart-e" + access_engine = 1 + +/obj/item/weapon/cartridge/atmos + name = "BreatheDeep Cartridge" + icon_state = "cart-a" + access_atmos = 1 + +/obj/item/weapon/cartridge/mechanic + name = "Screw-E Cartridge" + icon_state = "cart-mech" + access_mechanic = 1 + access_engine = 1 //for the power monitor, but may remove later + +/obj/item/weapon/cartridge/medical + name = "Med-U Cartridge" + icon_state = "cart-m" + access_medical = 1 + +/obj/item/weapon/cartridge/chemistry + name = "ChemWhiz Cartridge" + icon_state = "cart-chem" + access_reagent_scanner = 1 + +/obj/item/weapon/cartridge/chef + name = "ChefBuddy Cartridge" + icon_state = "cart-chef" + access_reagent_scanner = 1 + +/obj/item/weapon/cartridge/security + name = "R.O.B.U.S.T. Cartridge" + icon_state = "cart-s" + access_security = 1 + +/obj/item/weapon/cartridge/security/New() + ..() + spawn(5)//giving time for the radio_controller to initialize + radio = new /obj/item/radio/integrated/beepsky(src) + +/obj/item/weapon/cartridge/detective + name = "D.E.T.E.C.T. Cartridge" + icon_state = "cart-s" + access_security = 1 + access_medical = 1 + access_manifest = 1 + + +/obj/item/weapon/cartridge/janitor + name = "CustodiPRO Cartridge" + desc = "The ultimate in clean-room design." + icon_state = "cart-j" + access_janitor = 1 + +/obj/item/weapon/cartridge/lawyer + name = "P.R.O.V.E. Cartridge" + icon_state = "cart-s" + access_security = 1 + +/obj/item/weapon/cartridge/clown + name = "Honkworks 5.0" + icon_state = "cart-clown" + access_clown = 1 + var/honk_charges = 5 + +/obj/item/weapon/cartridge/mime + name = "Gestur-O 1000" + icon_state = "cart-mi" + access_mime = 1 + var/mime_charges = 5 +/* +/obj/item/weapon/cartridge/botanist + name = "Green Thumb v4.20" + icon_state = "cart-b" + access_flora = 1 +*/ + +/obj/item/weapon/cartridge/signal + name = "generic signaler cartridge" + desc = "A data cartridge with an integrated radio signaler module." + +/obj/item/weapon/cartridge/signal/toxins + name = "Signal Ace 2" + desc = "Complete with integrated radio signaler!" + icon_state = "cart-tox" + access_reagent_scanner = 1 + access_atmos = 1 + +/obj/item/weapon/cartridge/signal/New() + ..() + spawn(5)//giving time for the radio_controller to initialize + radio = new /obj/item/radio/integrated/signal(src) + +/obj/item/weapon/cartridge/quartermaster + name = "Space Parts & Space Vendors Cartridge" + desc = "Perfect for the Quartermaster on the go!" + icon_state = "cart-q" + access_quartermaster = 1 + +/obj/item/weapon/cartridge/quartermaster/New() + ..() + spawn(5)//giving time for the radio_controller to initialize + radio = new /obj/item/radio/integrated/mule(src) + +/obj/item/weapon/cartridge/head + name = "Easy-Record DELUXE" + icon_state = "cart-h" + access_manifest = 1 + access_status_display = 1 + +/obj/item/weapon/cartridge/hop + name = "HumanResources9001" + icon_state = "cart-h" + access_manifest = 1 + access_status_display = 1 + access_quartermaster = 1 + access_janitor = 1 + access_security = 1 + +/obj/item/weapon/cartridge/hop/New() + ..() + spawn(5)//giving time for the radio_controller to initialize + radio = new /obj/item/radio/integrated/mule(src) + +/obj/item/weapon/cartridge/hos + name = "R.O.B.U.S.T. DELUXE" + icon_state = "cart-hos" + access_manifest = 1 + access_status_display = 1 + access_security = 1 + +/obj/item/weapon/cartridge/hos/New() + ..() + spawn(5)//giving time for the radio_controller to initialize + radio = new /obj/item/radio/integrated/beepsky(src) + +/obj/item/weapon/cartridge/ce + name = "Power-On DELUXE" + icon_state = "cart-ce" + access_manifest = 1 + access_mechanic = 1 + access_status_display = 1 + access_engine = 1 + access_atmos = 1 + +/obj/item/weapon/cartridge/cmo + name = "Med-U DELUXE" + icon_state = "cart-cmo" + access_manifest = 1 + access_status_display = 1 + access_reagent_scanner = 1 + access_medical = 1 + +/obj/item/weapon/cartridge/rd + name = "Signal Ace DELUXE" + icon_state = "cart-rd" + access_manifest = 1 + access_status_display = 1 + access_reagent_scanner = 1 + access_atmos = 1 + +/obj/item/weapon/cartridge/rd/New() + ..() + spawn(5)//giving time for the radio_controller to initialize + radio = new /obj/item/radio/integrated/signal(src) + +/obj/item/weapon/cartridge/captain + name = "Value-PAK Cartridge" + desc = "Now with 200% more value!" + icon_state = "cart-c" + access_manifest = 1 + access_engine = 1 + access_mechanic = 1 + access_security = 1 + access_medical = 1 + access_reagent_scanner = 1 + access_status_display = 1 + access_atmos = 1 + +/obj/item/weapon/cartridge/syndicate + name = "Detomatix Cartridge" + icon_state = "cart" + access_remote_door = 1 + remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. + origin_tech = "programming=2;syndicate=2" + mech_flags = MECH_SCAN_ILLEGAL + var/shock_charges = 4 + +/obj/item/weapon/cartridge/proc/unlock() + if (!istype(loc, /obj/item/device/pda)) + return + + generate_menu() + print_to_host(menu) + return + +/obj/item/weapon/cartridge/proc/print_to_host(var/text) + if (!istype(loc, /obj/item/device/pda)) + return + + var/obj/item/device/pda/pda_device = loc + + pda_device.cart = text + + for (var/mob/M in viewers(1, pda_device.loc)) + if (M.client && M.machine == pda_device) + pda_device.attack_self(M) + + return + +/obj/item/weapon/cartridge/proc/post_status(var/command, var/data1, var/data2) + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + + if(!frequency) return + + var/datum/signal/status_signal = getFromPool(/datum/signal) + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + + switch(command) + if("message") + status_signal.data["msg1"] = data1 + status_signal.data["msg2"] = data2 + if(loc) + var/obj/item/PDA = loc + var/mob/user = PDA.fingerprintslast + if(istype(PDA.loc,/mob/living)) + name = PDA.loc + log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") + message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") + + if("alert") + status_signal.data["picture_state"] = data1 + + frequency.post_signal(src, status_signal) + +/obj/item/weapon/cartridge/proc/generate_menu() + switch(mode) + if(40) //signaller + menu = "

    Remote Signaling System

    " + + menu += {" +Send Signal
    +Frequency: +- +- +[format_frequency(radio:frequency)] ++ ++
    +
    +Code: +- +- +[radio:code] ++ ++
    "} + /*if (41) //crew manifest + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:281: menu = "

    Crew Manifest

    " + menu = {"

    Crew Manifest

    + Entries cannot be modified from this terminal.

    "} + // END AUTOFIX + if(data_core) + menu += data_core.get_manifest(1) // make it monochrome + menu += "
    "*/ + + + if (42) //status displays + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:289: menu = "

    Station Status Display Interlink

    " + menu = {"

    Station Status Display Interlink

    + \[ Clear \]
    + \[ Shuttle ETA \]
    + \[ Message \] +
    + \[ Alert: None | + Red Alert | + Lockdown | + Biohazard \]
    "} + // END AUTOFIX + if (43) //Muskets' and Rockdtben's power monitor :D + menu = "

    Please select a Power Monitoring Computer


    No Power Monitoring Computer detected in the vicinity.
    " + var/powercount = 0 + var/found = 0 + + for(var/obj/machinery/power/monitor/pMon in power_machines) + if(!(pMon.stat & (NOPOWER|BROKEN))) + var/turf/T = get_turf(src) + if(T.z == pMon.z)//the application may only detect power monitoring computers on its Z-level. + if(!found) + menu = "

    Please select a Power Monitoring Computer


    " + found = 1 + menu += "" + powercount++ + menu += " [pMon]
    " + powermonitors += "\ref[pMon]" + if(found) + menu += "
    " + + if (433) //Muskets' and Rockdtben's power monitor :D + if(!powmonitor) + menu = "

    Power Monitor


    " + menu += "No connection
    " + else + menu = "

    [powmonitor]


    " + var/list/L = list() + for(var/obj/machinery/power/terminal/term in powmonitor.powernet.nodes) + if(istype(term.master, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = term.master + L += A + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:338: menu += "
    Total power: [powmonitor.powernet.avail] W
    Total load: [num2text(powmonitor.powernet.viewload,10)] W
    " + menu += {"
    Total power: [powmonitor.powernet.avail] W
    Total load: [num2text(powmonitor.powernet.viewload,10)] W
    + "} + // END AUTOFIX + if(L.len > 0) + menu += "Area Eqp./Lgt./Env. Load Cell
    " + + var/list/S = list(" Off","AOff"," On", " AOn") + var/list/chg = list("N","C","F") + + for(var/obj/machinery/power/apc/A in L) + menu += copytext(add_tspace(A.areaMaster.name, 30), 1, 30) + menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]
    " + + menu += "
    " + + if (53) + menu = "

    Please select an Alert Computer


    No Alert Computer detected in the vicinity.
    " + alertmonitor = null + alertmonitors = list() + + var/alertcount = 0 + var/found = 0 + + for(var/obj/machinery/computer/station_alert/aMon in machines) + if(!(aMon.stat & (NOPOWER|BROKEN))) + var/turf/T = get_turf(src) + if(T.z == aMon.z)//the application may only detect station alert computers on its Z-level. + if(!found) + menu = "

    Please select an Alert Computer


    " + found = 1 + menu += "" + alertcount++ + menu += " [aMon]
    " + alertmonitors += "\ref[aMon]" + if(found) + menu += "
    " + + if (533) + if(!alertmonitor) + menu = "

    Alert Monitor


    " + menu += "No connection
    " + else + menu = "

    [alertmonitor]


    " + for (var/cat in alertmonitor.alarms) + menu += text("[]
    \n", cat) + var/list/L = alertmonitor.alarms[cat] + if (L.len) + for (var/alarm in L) + var/list/alm = L[alarm] + var/area/A = alm[1] + var/list/sources = alm[3] + + menu += {" + • + [A.name]"} + + if (sources.len > 1) + menu += text(" - [] sources", sources.len) + menu += "
    \n" + else + menu += "-- All Systems Nominal
    \n" + menu += "
    \n" + + menu += "
    " + + if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working. + menu = "

    Medical Record List

    " + if(!isnull(data_core.general)) + for (var/datum/data/record/R in sortRecord(data_core.general)) + menu += "[R.fields["id"]]: [R.fields["name"]]
    " + menu += "
    " + if(441) + menu = "

    Medical Record

    " + + if (istype(active1, /datum/data/record) && (active1 in data_core.general)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:364: menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    " + menu += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    + Sex: [active1.fields["sex"]]
    + Age: [active1.fields["age"]]
    + Rank: [active1.fields["rank"]]
    + Fingerprint: [active1.fields["fingerprint"]]
    + Physical Status: [active1.fields["p_stat"]]
    + Mental Status: [active1.fields["m_stat"]]
    "} + // END AUTOFIX + else + menu += "Record Lost!
    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:374: menu += "
    " + menu += {"
    +

    Medical Data

    "} + // END AUTOFIX + if (istype(active2, /datum/data/record) && (active2 in data_core.medical)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:378: menu += "Blood Type: [active2.fields["b_type"]]

    " + menu += {"Blood Type: [active2.fields["b_type"]]

    + Minor Disabilities: [active2.fields["mi_dis"]]
    + Details: [active2.fields["mi_dis_d"]]

    + Major Disabilities: [active2.fields["ma_dis"]]
    + Details: [active2.fields["ma_dis_d"]]

    + Allergies: [active2.fields["alg"]]
    + Details: [active2.fields["alg_d"]]

    + Current Diseases: [active2.fields["cdi"]]
    + Details: [active2.fields["cdi_d"]]

    + Important Notes: [active2.fields["notes"]]
    "} + // END AUTOFIX + else + menu += "Record Lost!
    " + + menu += "
    " + if (45) //security records + menu = "

    Security Record List

    " + if(!isnull(data_core.general)) + for (var/datum/data/record/R in sortRecord(data_core.general)) + menu += "
    [R.fields["id"]]: [R.fields["name"]]
    " + + menu += "
    " + if(451) + menu = "

    Security Record

    " + + if (istype(active1, /datum/data/record) && (active1 in data_core.general)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:408: menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    " + menu += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    + Sex: [active1.fields["sex"]]
    + Age: [active1.fields["age"]]
    + Rank: [active1.fields["rank"]]
    + Fingerprint: [active1.fields["fingerprint"]]
    + Physical Status: [active1.fields["p_stat"]]
    + Mental Status: [active1.fields["m_stat"]]
    "} + // END AUTOFIX + else + menu += "Record Lost!
    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:418: menu += "
    " + menu += {"
    +

    Security Data

    "} + // END AUTOFIX + if (istype(active3, /datum/data/record) && (active3 in data_core.security)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:422: menu += "Criminal Status: [active3.fields["criminal"]]
    " + menu += {"Criminal Status: [active3.fields["criminal"]]
    + Minor Crimes: [active3.fields["mi_crim"]]
    + Details: [active3.fields["mi_crim"]]

    + Major Crimes: [active3.fields["ma_crim"]]
    + Details: [active3.fields["ma_crim_d"]]

    + Important Notes:
    + [active3.fields["notes"]]"} + // END AUTOFIX + else + menu += "Record Lost!
    " + + menu += "
    " + if (46) //beepsky control + var/obj/item/radio/integrated/beepsky/SC = radio + if(!SC) + menu = "Interlink Error - Please reinsert cartridge." + return + + menu = "

    Securitron Interlink

    " + + if(!SC.active) + // list of bots + if(!SC.botlist || (SC.botlist && SC.botlist.len==0)) + menu += "No bots found.
    " + + else + for(var/obj/machinery/bot/B in SC.botlist) + if (B) + menu += "
    [B] at [B.loc.loc]
    " + + menu += "
    Scan for active bots
    " + + else // bot selected, control it + + menu += "[SC.active]
    Status: (refresh)
    " + + if(!SC.botstatus) + menu += "Waiting for response...
    " + else + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:464: menu += "Location: [SC.botstatus["loca"] ]
    " + menu += {"Location: [SC.botstatus["loca"] ]
    + Mode: "} + // END AUTOFIX + switch(SC.botstatus["mode"]) + if(0) + menu += "Ready" + if(1) + menu += "Apprehending target" + if(2,3) + menu += "Arresting target" + if(4) + menu += "Starting patrol" + if(5) + menu += "On patrol" + if(6) + menu += "Responding to summons" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:481: menu += "
    \[Stop Patrol\] " + menu += {"
    \[Stop Patrol\] + \[Start Patrol\] + \[Summon Bot\]
    +
    Return to bot list"} + // END AUTOFIX + if (47) //quartermaster order records + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:487: menu = "

    Supply Record Interlink

    " + menu = {"

    Supply Record Interlink

    +
    Supply shuttle
    + Location: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Dock"]
    + Current approved orders:
      "} + // END AUTOFIX + for(var/S in supply_shuttle.shoppinglist) + var/datum/supply_order/SO = S + menu += "
    1. #[SO.ordernum] - [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    2. " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:495: menu += "
    " + menu += {" + Current requests:
      "} + // END AUTOFIX + for(var/S in supply_shuttle.requestlist) + var/datum/supply_order/SO = S + menu += "
    1. #[SO.ordernum] - [SO.object.name] requested by [SO.orderedby]
    2. " + menu += "
    Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." + + if (48) //mulebot control + var/obj/item/radio/integrated/mule/QC = radio + if(!QC) + menu = "Interlink Error - Please reinsert cartridge." + return + + menu = "

    M.U.L.E. bot Interlink V0.8

    " + + if(!QC.active) + // list of bots + if(!QC.botlist || (QC.botlist && QC.botlist.len==0)) + menu += "No bots found.
    " + + else + for(var/obj/machinery/bot/mulebot/B in QC.botlist) + menu += "[B] at [get_area(B)]
    " + menu += "
    Scan for active bots
    " + + else // bot selected, control it + + menu += "[QC.active]
    Status: (refresh)
    " + + if(!QC.botstatus) + menu += "Waiting for response...
    " + else + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:529: menu += "Location: [QC.botstatus["loca"] ]
    " + menu += {"Location: [QC.botstatus["loca"] ]
    + Mode: "} + // END AUTOFIX + switch(QC.botstatus["mode"]) + if(0) + menu += "Ready" + if(1) + menu += "Loading/Unloading" + if(2) + menu += "Navigating to Delivery Location" + if(3) + menu += "Navigating to Home" + if(4) + menu += "Waiting for clear path" + if(5,6) + menu += "Calculating navigation path" + if(7) + menu += "Unable to locate destination" + var/obj/structure/closet/crate/C = QC.botstatus["load"] + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:548: menu += "
    Current Load: [ !C ? "none" : "[C.name] (unload)" ]
    " + menu += {"
    Current Load: [ !C ? "none" : "[C.name] (unload)" ]
    + Destination: [!QC.botstatus["dest"] ? "none" : QC.botstatus["dest"] ] (set)
    + Power: [QC.botstatus["powr"]]%
    + Home: [!QC.botstatus["home"] ? "none" : QC.botstatus["home"] ]
    + Auto Return Home: [QC.botstatus["retn"] ? "On Off" : "(On) Off"]
    + Auto Pickup Crate: [QC.botstatus["pick"] ? "On Off" : "(On) Off"]

    + \[Stop\] + \[Proceed\] + \[Return Home\]
    +
    Return to bot list"} + // END AUTOFIX + if (49) //janitorial locator + menu = "

    Persistent Custodial Object Locator

    " + + var/turf/cl = get_turf(src) + if (cl) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\\\pDA\cart.dm:565: menu += "Current Orbital Location: \[[cl.x],[cl.y]\]" + menu += {"Current Orbital Location: \[[cl.x-WORLD_X_OFFSET[cl.z]],[cl.y-WORLD_Y_OFFSET[cl.z]]\] +

    Located Mops:

    "} + // END AUTOFIX + var/ldat + for (var/obj/item/weapon/mop/M in world) + var/turf/ml = get_turf(M) + + if(ml) + if (ml.z != cl.z) + continue + var/direction = get_dir(src, M) + ldat += "Mop - \[[ml.x-WORLD_X_OFFSET[ml.z]],[ml.y-WORLD_Y_OFFSET[ml.z]] ([uppertext(dir2text(direction))])\] - [M.reagents.total_volume ? "Wet" : "Dry"]
    " + + if (!ldat) + menu += "None" + else + menu += "[ldat]" + + menu += "

    Located Mop Buckets:

    " + + ldat = null + for (var/obj/structure/mopbucket/B in world) + var/turf/bl = get_turf(B) + + if(bl) + if (bl.z != cl.z) + continue + var/direction = get_dir(src, B) + ldat += "Bucket - \[[bl.x-WORLD_X_OFFSET[bl.z]],[bl.y-WORLD_Y_OFFSET[bl.z]] ([uppertext(dir2text(direction))])\] - Water level: [B.reagents.total_volume]/100
    " + + if (!ldat) + menu += "None" + else + menu += "[ldat]" + + menu += "

    Located Cleanbots:

    " + + ldat = null + for (var/obj/machinery/bot/cleanbot/B in world) + var/turf/bl = get_turf(B) + + if(bl) + if (bl.z != cl.z) + continue + var/direction = get_dir(src, B) + ldat += "Cleanbot - \[[bl.x-WORLD_X_OFFSET[bl.z]],[bl.y-WORLD_Y_OFFSET[bl.z]] ([uppertext(dir2text(direction))])\] - [B.on ? "Online" : "Offline"]
    " + + if (!ldat) + menu += "None" + else + menu += "[ldat]" + + else + menu += "ERROR: Unable to determine current location." + menu += "

    Refresh GPS Locator" + + +/obj/item/weapon/cartridge/Topic(href, href_list) + ..() + + if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr.unset_machine() + usr << browse(null, "window=pda") + return + + switch(href_list["choice"]) + if("Medical Records") + var/datum/data/record/R = locate(href_list["target"]) + var/datum/data/record/M = locate(href_list["target"]) + loc:mode = 441 + mode = 441 + if (R in data_core.general) + for (var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + break + active1 = R + active2 = M + + if("Security Records") + var/datum/data/record/R = locate(href_list["target"]) + var/datum/data/record/S = locate(href_list["target"]) + loc:mode = 451 + mode = 451 + if (R in data_core.general) + for (var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + S = E + break + active1 = R + active3 = S + + if("Send Signal") + spawn( 0 ) + radio:send_signal("ACTIVATE") + return + + if("Signal Frequency") + var/new_frequency = sanitize_frequency(radio:frequency + text2num(href_list["sfreq"])) + radio:set_frequency(new_frequency) + + if("Signal Code") + radio:code += text2num(href_list["scode"]) + radio:code = round(radio:code) + radio:code = min(100, radio:code) + radio:code = max(1, radio:code) + + if("Status") + switch(href_list["statdisp"]) + if("message") + post_status("message", message1, message2) + if("alert") + post_status("alert", href_list["alert"]) + if("setmsg1") + message1 = reject_bad_text(trim(copytext(sanitize(input("Line 1", "Enter Message Text", message1) as text|null), 1, 40)), 40) + updateSelfDialog() + if("setmsg2") + message2 = reject_bad_text(trim(copytext(sanitize(input("Line 2", "Enter Message Text", message2) as text|null), 1, 40)), 40) + updateSelfDialog() + else + post_status(href_list["statdisp"]) + if("Power Select") + var/pnum = text2num(href_list["target"]) + powmonitor = locate(powermonitors[pnum]) + if(istype(powmonitor)) + loc:mode = 433 + mode = 433 + + if("Alert Select") + var/pnum = text2num(href_list["target"]) + alertmonitor = locate(alertmonitors[pnum]) + if(istype(alertmonitor)) + loc:mode = 533 + mode = 533 + + generate_menu() + print_to_host(menu) diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm index 7ecf798d5bc..28551524a53 100644 --- a/code/game/objects/items/devices/PDA/radio.dm +++ b/code/game/objects/items/devices/PDA/radio.dm @@ -1,270 +1,270 @@ -/obj/item/radio/integrated - name = "PDA radio module" - desc = "An electronic radio system of nanotrasen origin." - icon = 'icons/obj/module.dmi' - icon_state = "power_mod" - var/obj/item/device/pda/hostpda = null - - var/on = 0 //Are we currently active? - var/menu_message = "" - -/obj/item/radio/integrated/New() - ..() - if (istype(loc.loc, /obj/item/device/pda)) - hostpda = loc.loc - -/obj/item/radio/integrated/proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3, s_filter) - - +/obj/item/radio/integrated + name = "PDA radio module" + desc = "An electronic radio system of nanotrasen origin." + icon = 'icons/obj/module.dmi' + icon_state = "power_mod" + var/obj/item/device/pda/hostpda = null + + var/on = 0 //Are we currently active? + var/menu_message = "" + +/obj/item/radio/integrated/New() + ..() + if (istype(loc.loc, /obj/item/device/pda)) + hostpda = loc.loc + +/obj/item/radio/integrated/proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3, s_filter) + + // to_chat(world, "Post: [freq]: [key]=[value], [key2]=[value2]") - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.transmission_method = 1 - signal.data[key] = value - if(key2) - signal.data[key2] = value2 - if(key3) - signal.data[key3] = value3 - - frequency.post_signal(src, signal, filter = s_filter) - -/obj/item/radio/integrated/proc/print_to_host(var/text) - if (isnull(src.hostpda)) - return - src.hostpda.cart = text - - for (var/mob/M in viewers(1, src.hostpda.loc)) - if (M.client && M.machine == src.hostpda) - src.hostpda.cartridge.unlock() - - return - -/obj/item/radio/integrated/proc/generate_menu() - -/obj/item/radio/integrated/beepsky - var/list/botlist = null // list of bots - var/obj/machinery/bot/secbot/active // the active bot; if null, show bot list - var/list/botstatus // the status signal sent by the bot - - var/control_freq = 1447 - -// create a new QM cartridge, and register to receive bot control & beacon message -/obj/item/radio/integrated/beepsky/New() - ..() - spawn(5) - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) -/obj/item/radio/integrated/beepsky/Destroy() - if(radio_controller) - radio_controller.remove_object(src, control_freq) - ..() -// receive radio signals -// can detect bot status signals -// create/populate list as they are recvd - -/obj/item/radio/integrated/beepsky/receive_signal(datum/signal/signal) -// var/obj/item/device/pda/P = src.loc - - /* + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.transmission_method = 1 + signal.data[key] = value + if(key2) + signal.data[key2] = value2 + if(key3) + signal.data[key3] = value3 + + frequency.post_signal(src, signal, filter = s_filter) + +/obj/item/radio/integrated/proc/print_to_host(var/text) + if (isnull(src.hostpda)) + return + src.hostpda.cart = text + + for (var/mob/M in viewers(1, src.hostpda.loc)) + if (M.client && M.machine == src.hostpda) + src.hostpda.cartridge.unlock() + + return + +/obj/item/radio/integrated/proc/generate_menu() + +/obj/item/radio/integrated/beepsky + var/list/botlist = null // list of bots + var/obj/machinery/bot/secbot/active // the active bot; if null, show bot list + var/list/botstatus // the status signal sent by the bot + + var/control_freq = 1447 + +// create a new QM cartridge, and register to receive bot control & beacon message +/obj/item/radio/integrated/beepsky/New() + ..() + spawn(5) + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) +/obj/item/radio/integrated/beepsky/Destroy() + if(radio_controller) + radio_controller.remove_object(src, control_freq) + ..() +// receive radio signals +// can detect bot status signals +// create/populate list as they are recvd + +/obj/item/radio/integrated/beepsky/receive_signal(datum/signal/signal) +// var/obj/item/device/pda/P = src.loc + + /* to_chat(world, "recvd:[P] : [signal.source]") - for(var/d in signal.data) + for(var/d in signal.data) to_chat(world, "- [d] = [signal.data[d]]") - */ - if (signal.data["type"] == "secbot") - if(!botlist) - botlist = new() - - if(!(signal.source in botlist)) - botlist += signal.source - - if(active == signal.source) - var/list/b = signal.data - botstatus = b.Copy() - -// if (istype(P)) P.updateSelfDialog() - -/obj/item/radio/integrated/beepsky/Topic(href, href_list) - ..() - var/obj/item/device/pda/PDA = src.hostpda - - switch(href_list["op"]) - - if("control") - active = locate(href_list["bot"]) - post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) - - if("scanbots") // find all bots - botlist = null - post_signal(control_freq, "command", "bot_status", s_filter = RADIO_SECBOT) - - if("botlist") - active = null - - if("stop", "go") - post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = RADIO_SECBOT) - post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) - - if("summon") - post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , s_filter = RADIO_SECBOT) - post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) - PDA.cartridge.unlock() - -/obj/item/radio/integrated/mule - var/list/botlist = null // list of bots - var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list - var/list/botstatus // the status signal sent by the bot - var/list/beacons - - var/beacon_freq = 1400 - var/control_freq = 1447 - -// create a new QM cartridge, and register to receive bot control & beacon message -/obj/item/radio/integrated/mule/New() - ..() - spawn(5) - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - spawn(10) - post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS) - -/obj/item/radio/integrated/mule/Destroy() - if(radio_controller) - radio_controller.remove_object(src, control_freq) - radio_controller.remove_object(src, beacon_freq) - ..() - -// receive radio signals -// can detect bot status signals -// and beacon locations -// create/populate lists as they are recvd - -/obj/item/radio/integrated/mule/receive_signal(datum/signal/signal) -// var/obj/item/device/pda/P = src.loc - - /* + */ + if (signal.data["type"] == "secbot") + if(!botlist) + botlist = new() + + if(!(signal.source in botlist)) + botlist += signal.source + + if(active == signal.source) + var/list/b = signal.data + botstatus = b.Copy() + +// if (istype(P)) P.updateSelfDialog() + +/obj/item/radio/integrated/beepsky/Topic(href, href_list) + ..() + var/obj/item/device/pda/PDA = src.hostpda + + switch(href_list["op"]) + + if("control") + active = locate(href_list["bot"]) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) + + if("scanbots") // find all bots + botlist = null + post_signal(control_freq, "command", "bot_status", s_filter = RADIO_SECBOT) + + if("botlist") + active = null + + if("stop", "go") + post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = RADIO_SECBOT) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) + + if("summon") + post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , s_filter = RADIO_SECBOT) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) + PDA.cartridge.unlock() + +/obj/item/radio/integrated/mule + var/list/botlist = null // list of bots + var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list + var/list/botstatus // the status signal sent by the bot + var/list/beacons + + var/beacon_freq = 1400 + var/control_freq = 1447 + +// create a new QM cartridge, and register to receive bot control & beacon message +/obj/item/radio/integrated/mule/New() + ..() + spawn(5) + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + spawn(10) + post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS) + +/obj/item/radio/integrated/mule/Destroy() + if(radio_controller) + radio_controller.remove_object(src, control_freq) + radio_controller.remove_object(src, beacon_freq) + ..() + +// receive radio signals +// can detect bot status signals +// and beacon locations +// create/populate lists as they are recvd + +/obj/item/radio/integrated/mule/receive_signal(datum/signal/signal) +// var/obj/item/device/pda/P = src.loc + + /* to_chat(world, "recvd:[P] : [signal.source]") - for(var/d in signal.data) + for(var/d in signal.data) to_chat(world, "- [d] = [signal.data[d]]") - */ - if(signal.data["type"] == "mulebot") - if(!botlist) - botlist = new() - - if(!(signal.source in botlist)) - botlist += signal.source - - if(active == signal.source) - var/list/b = signal.data - botstatus = b.Copy() - - else if(signal.data["beacon"]) - if(!beacons) - beacons = new() - - beacons[signal.data["beacon"] ] = signal.source - - -// if(istype(P)) P.updateSelfDialog() - -/obj/item/radio/integrated/mule/Topic(href, href_list) - ..() - var/obj/item/device/pda/PDA = src.hostpda - var/cmd = "command" - if(active) cmd = "command [active.suffix]" - - switch(href_list["op"]) - - if("control") - active = locate(href_list["bot"]) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("scanbots") // find all bots - botlist = null - post_signal(control_freq, "command", "bot_status", s_filter = RADIO_MULEBOT) - - if("botlist") - active = null - - - if("unload") - post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - if("setdest") - if(beacons) - var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons - if(dest) - post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("retoff") - post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - if("reton") - post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("pickoff") - post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - if("pickon") - post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - - if("stop", "go", "home") - post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) - PDA.cartridge.unlock() - - - -/* - * Radio Cartridge, essentially a signaler. - */ - - -/obj/item/radio/integrated/signal - var/frequency = 1457 - var/code = 30.0 - var/last_transmission - var/datum/radio_frequency/radio_connection - -/obj/item/radio/integrated/signal/New() - ..() - if(radio_controller) - initialize() - -/obj/item/radio/integrated/signal/initialize() - if (src.frequency < 1441 || src.frequency > 1489) - src.frequency = sanitize_frequency(src.frequency) - - set_frequency(frequency) - -/obj/item/radio/integrated/signal/proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency) - -/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE") - - - if(last_transmission && world.time < (last_transmission + 5)) - return - last_transmission = world.time - - var/time = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.encryption = code - signal.data["message"] = message - - radio_connection.post_signal(src, signal) - - return + */ + if(signal.data["type"] == "mulebot") + if(!botlist) + botlist = new() + + if(!(signal.source in botlist)) + botlist += signal.source + + if(active == signal.source) + var/list/b = signal.data + botstatus = b.Copy() + + else if(signal.data["beacon"]) + if(!beacons) + beacons = new() + + beacons[signal.data["beacon"] ] = signal.source + + +// if(istype(P)) P.updateSelfDialog() + +/obj/item/radio/integrated/mule/Topic(href, href_list) + ..() + var/obj/item/device/pda/PDA = src.hostpda + var/cmd = "command" + if(active) cmd = "command [active.suffix]" + + switch(href_list["op"]) + + if("control") + active = locate(href_list["bot"]) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + + if("scanbots") // find all bots + botlist = null + post_signal(control_freq, "command", "bot_status", s_filter = RADIO_MULEBOT) + + if("botlist") + active = null + + + if("unload") + post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + if("setdest") + if(beacons) + var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons + if(dest) + post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + + if("retoff") + post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + if("reton") + post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + + if("pickoff") + post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + if("pickon") + post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + + if("stop", "go", "home") + post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + PDA.cartridge.unlock() + + + +/* + * Radio Cartridge, essentially a signaler. + */ + + +/obj/item/radio/integrated/signal + var/frequency = 1457 + var/code = 30.0 + var/last_transmission + var/datum/radio_frequency/radio_connection + +/obj/item/radio/integrated/signal/New() + ..() + if(radio_controller) + initialize() + +/obj/item/radio/integrated/signal/initialize() + if (src.frequency < 1441 || src.frequency > 1489) + src.frequency = sanitize_frequency(src.frequency) + + set_frequency(frequency) + +/obj/item/radio/integrated/signal/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency) + +/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE") + + + if(last_transmission && world.time < (last_transmission + 5)) + return + last_transmission = world.time + + var/time = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.encryption = code + signal.data["message"] = message + + radio_connection.post_signal(src, signal) + + return diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 42b028908af..827f72d8665 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -1,132 +1,132 @@ -/obj/item/device/aicard - name = "inteliCard" - icon = 'icons/obj/pda.dmi' - icon_state = "aicard" // aicard-full - item_state = "electronic" - w_class = 2.0 - flags = FPRINT - slot_flags = SLOT_BELT - var/flush = null - origin_tech = "programming=4;materials=4" - - - attack(mob/living/silicon/ai/M as mob, mob/user as mob) - if(!istype(M, /mob/living/silicon/ai))//If target is not an AI. - return ..() - - M.attack_log += text("\[[time_stamp()]\] Has been carded with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to card [M.name] ([M.ckey])") - - log_attack("[user.name] ([user.ckey]) used the [src.name] to card [M.name] ([M.ckey])") - - transfer_ai("AICORE", "AICARD", M, user) - - playsound(get_turf(src), 'sound/machines/paistartup.ogg', 50, 1) - return - - attack_self(mob/user) - if (!in_range(src, user)) - return - user.set_machine(src) - var/dat = "Intelicard
    " - var/laws - for(var/mob/living/silicon/ai/A in src) - dat += "Stored AI: [A.name]
    System integrity: [A.system_integrity()]%
    " - - //AI DIDN'T KILL SOMEONE FOR ME, CARD HER TO CHECK HER LAWS - - //for (var/index = 1, index <= A.laws.ion.len, index++) - //var/law = A.laws.ion[index] - //if (length(law) > 0) - //var/num = ionnum() - //laws += "[num]. [law]" - - //if (A.laws.zeroth) - //laws += "0: [A.laws.zeroth]
    " - - var/number = 1 - for (var/index = 1, index <= A.laws.inherent.len, index++) - var/law = A.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
    " - number++ - - for (var/index = 1, index <= A.laws.supplied.len, index++) - var/law = A.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
    " - number++ - - dat += "Laws:
    [laws]
    " - - if (A.stat == 2) - dat += "AI nonfunctional" - else - if (!src.flush) - dat += {"Wipe AI"} - else - dat += "Wipe in progress" - dat += "
    " - dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"} - dat += "
    " - dat += {" Close"} - user << browse(dat, "window=aicard") - onclose(user, "aicard") - return - - Topic(href, href_list) - var/mob/living/U = usr - if (!in_range(src, U)||U.machine!=src)//If they are not in range of 1 or less or their machine is not the card (ie, clicked on something else). - U << browse(null, "window=aicard") - U.unset_machine() - return - - add_fingerprint(U) - U.set_machine(src) - - switch(href_list["choice"])//Now we switch based on choice. - if ("Close") - U << browse(null, "window=aicard") - U.unset_machine() - return - - if ("Wipe") - var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") - if(confirm == "Yes") - if(isnull(src)||!in_range(src, U)||U.machine!=src) - U << browse(null, "window=aicard") - U.unset_machine() - return - else - flush = 1 - for(var/mob/living/silicon/ai/A in src) - A.suiciding = 1 +/obj/item/device/aicard + name = "inteliCard" + icon = 'icons/obj/pda.dmi' + icon_state = "aicard" // aicard-full + item_state = "electronic" + w_class = 2.0 + flags = FPRINT + slot_flags = SLOT_BELT + var/flush = null + origin_tech = "programming=4;materials=4" + + + attack(mob/living/silicon/ai/M as mob, mob/user as mob) + if(!istype(M, /mob/living/silicon/ai))//If target is not an AI. + return ..() + + M.attack_log += text("\[[time_stamp()]\] Has been carded with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to card [M.name] ([M.ckey])") + + log_attack("[user.name] ([user.ckey]) used the [src.name] to card [M.name] ([M.ckey])") + + transfer_ai("AICORE", "AICARD", M, user) + + playsound(get_turf(src), 'sound/machines/paistartup.ogg', 50, 1) + return + + attack_self(mob/user) + if (!in_range(src, user)) + return + user.set_machine(src) + var/dat = "Intelicard
    " + var/laws + for(var/mob/living/silicon/ai/A in src) + dat += "Stored AI: [A.name]
    System integrity: [A.system_integrity()]%
    " + + //AI DIDN'T KILL SOMEONE FOR ME, CARD HER TO CHECK HER LAWS + + //for (var/index = 1, index <= A.laws.ion.len, index++) + //var/law = A.laws.ion[index] + //if (length(law) > 0) + //var/num = ionnum() + //laws += "[num]. [law]" + + //if (A.laws.zeroth) + //laws += "0: [A.laws.zeroth]
    " + + var/number = 1 + for (var/index = 1, index <= A.laws.inherent.len, index++) + var/law = A.laws.inherent[index] + if (length(law) > 0) + laws += "[number]: [law]
    " + number++ + + for (var/index = 1, index <= A.laws.supplied.len, index++) + var/law = A.laws.supplied[index] + if (length(law) > 0) + laws += "[number]: [law]
    " + number++ + + dat += "Laws:
    [laws]
    " + + if (A.stat == 2) + dat += "AI nonfunctional" + else + if (!src.flush) + dat += {"Wipe AI"} + else + dat += "Wipe in progress" + dat += "
    " + dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"} + dat += "
    " + dat += {" Close"} + user << browse(dat, "window=aicard") + onclose(user, "aicard") + return + + Topic(href, href_list) + var/mob/living/U = usr + if (!in_range(src, U)||U.machine!=src)//If they are not in range of 1 or less or their machine is not the card (ie, clicked on something else). + U << browse(null, "window=aicard") + U.unset_machine() + return + + add_fingerprint(U) + U.set_machine(src) + + switch(href_list["choice"])//Now we switch based on choice. + if ("Close") + U << browse(null, "window=aicard") + U.unset_machine() + return + + if ("Wipe") + var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") + if(confirm == "Yes") + if(isnull(src)||!in_range(src, U)||U.machine!=src) + U << browse(null, "window=aicard") + U.unset_machine() + return + else + flush = 1 + for(var/mob/living/silicon/ai/A in src) + A.suiciding = 1 to_chat(A, "Your core files are being wiped!") - A.attack_log += text("\[[time_stamp()]\] Has been wiped with an [src.name] by [U.name] ([U.ckey])") - U.attack_log += text("\[[time_stamp()]\] Used an [src.name] to wipe [A.name] ([A.ckey])") - log_attack("[key_name(U)] Used an [src.name] to wipe [key_name(A)]") - - while (A.stat != 2) - A.adjustOxyLoss(2) - A.updatehealth() - sleep(10) - flush = 0 - - if ("Wireless") - for(var/mob/living/silicon/ai/A in src) - A.control_disabled = !A.control_disabled + A.attack_log += text("\[[time_stamp()]\] Has been wiped with an [src.name] by [U.name] ([U.ckey])") + U.attack_log += text("\[[time_stamp()]\] Used an [src.name] to wipe [A.name] ([A.ckey])") + log_attack("[key_name(U)] Used an [src.name] to wipe [key_name(A)]") + + while (A.stat != 2) + A.adjustOxyLoss(2) + A.updatehealth() + sleep(10) + flush = 0 + + if ("Wireless") + for(var/mob/living/silicon/ai/A in src) + A.control_disabled = !A.control_disabled to_chat(A, "The intelicard's wireless port has been [A.control_disabled ? "disabled" : "enabled"]!") - if (A.control_disabled) - overlays -= image('icons/obj/pda.dmi', "aicard-on") - else - overlays += image('icons/obj/pda.dmi', "aicard-on") - attack_self(U) - -/obj/item/device/aicard/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - if(prob(50)) qdel(src) - if(3.0) - if(prob(25)) qdel(src) + if (A.control_disabled) + overlays -= image('icons/obj/pda.dmi', "aicard-on") + else + overlays += image('icons/obj/pda.dmi', "aicard-on") + attack_self(U) + +/obj/item/device/aicard/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + if(prob(50)) qdel(src) + if(3.0) + if(prob(25)) qdel(src) diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index b0d5773694f..c4d151c81a1 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -1,181 +1,181 @@ -/obj/item/device/chameleon - name = "chameleon-projector" - icon_state = "shield0" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - item_state = "electronic" - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - origin_tech = "syndicate=4;magnets=4" - var/cham_proj_scan = 1 //Scanning function starts on - var/can_use = 1 - var/obj/effect/dummy/chameleon/active_dummy = null - var/saved_item = /obj/item/weapon/cigbutt - var/saved_icon = 'icons/obj/clothing/masks.dmi' - var/saved_icon_state = "cigbutt" - var/saved_overlays - -/obj/item/device/chameleon/dropped() - spawn() //So the chammy project is dropped into the dummy before the dummy empties itself out - disrupt() - -/obj/item/device/chameleon/equipped() - disrupt() - -/obj/item/device/chameleon/attack_self() - toggle() - -/obj/item/device/chameleon/verb/toggle_scaning() - set name = "Toggle Chameleon Projector Scanning" - set category = "Object" - - if(usr.isUnconscious()) - return - - cham_proj_scan = !cham_proj_scan - to_chat(usr, "You [cham_proj_scan ? "activate":"deactivate"] [src]'s scanning function") - -/obj/item/device/chameleon/preattack(atom/target, mob/user , proximity) - if(!proximity) - return - if(!cham_proj_scan) //Is scanning disabled ? - return - if(!active_dummy) - if(istype(target, /obj/item) && !istype(target, /obj/item/weapon/disk/nuclear) || istype(target, /mob)) - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6) - to_chat(user, "Scanned [target].") - saved_item = target.type - saved_icon = target.icon - saved_icon_state = target.icon_state - saved_overlays = target.overlays - return 1 - -/obj/item/device/chameleon/proc/toggle() - if(!can_use || !saved_item) - return - if(active_dummy) - eject_all() - //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) - del(active_dummy) - active_dummy = null - to_chat(usr, "You deactivate [src].") - var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src)) - T.icon = 'icons/effects/effects.dmi' - flick("emppulse",T) - spawn(8) - qdel(T) - can_use = 0 - spawn(20) //Stop spamming this shit - can_use = 1 - else - //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) - var/obj/O = new saved_item(src) - if(!O) - return - var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(usr.loc) - C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src) - qdel(O) - O = null - to_chat(usr, "You activate [src].") - var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src)) - T.icon = 'icons/effects/effects.dmi' - flick("emppulse",T) - spawn(8) - qdel(T) - can_use = 0 - spawn(20) //Stop spamming this shit - can_use = 1 - -/obj/item/device/chameleon/proc/disrupt(var/delete_dummy = 1) - if(active_dummy) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread - spark_system.set_up(5, 0, src) - spark_system.attach(src) - spark_system.start() - eject_all() - if(delete_dummy) - qdel(active_dummy) - active_dummy = null - can_use = 0 - spawn(50) - can_use = 1 - -/obj/item/device/chameleon/proc/eject_all() - for(var/atom/movable/A in active_dummy) - A.loc = active_dummy.loc - if(ismob(A)) - var/mob/M = A - M.reset_view(null) - M.layer = MOB_LAYER //Reset the mob's layer - -/obj/effect/dummy/chameleon - name = "" - desc = "" - density = 0 - anchored = 0 - var/can_move = 1 - var/obj/item/device/chameleon/master = null - -/obj/effect/dummy/chameleon/proc/activate(var/obj/O, var/mob/M, new_icon, new_iconstate, new_overlays, var/obj/item/device/chameleon/C) - name = O.name - desc = O.desc - icon = new_icon - icon_state = new_iconstate - overlays = new_overlays - dir = O.dir - M.loc = src - M.layer = OBJ_LAYER //Needed for some things, notably lockers - master = C - master.active_dummy = src - -/obj/effect/dummy/chameleon/attackby() - for(var/mob/M in src) - to_chat(M, "Your chameleon-projector deactivates.") - master.disrupt() - -/obj/effect/dummy/chameleon/attack_hand() - for(var/mob/M in src) - to_chat(M, "Your chameleon-projector deactivates.") - master.disrupt() - -/obj/effect/dummy/chameleon/ex_act() - for(var/mob/M in src) - to_chat(M, "Your chameleon-projector deactivates.") - master.disrupt() - -/obj/effect/dummy/chameleon/bullet_act() - for(var/mob/M in src) - to_chat(M, "Your chameleon-projector deactivates.") - ..() - master.disrupt() - -/obj/effect/dummy/chameleon/relaymove(var/mob/user, direction) - if(istype(loc, /turf/space)) return //No magical space movement! - - if(can_move) - can_move = 0 - switch(user.bodytemperature) - if(300 to INFINITY) - spawn(8) - can_move = 1 - if(295 to 300) - spawn(11) - can_move = 1 - if(280 to 295) - spawn(14) - can_move = 1 - if(260 to 280) - spawn(18) - can_move = 1 - else - spawn(23) - can_move = 1 - step(src, direction) - return - -/obj/effect/dummy/chameleon/Destroy() - master.disrupt(0) - ..() +/obj/item/device/chameleon + name = "chameleon-projector" + icon_state = "shield0" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + item_state = "electronic" + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + origin_tech = "syndicate=4;magnets=4" + var/cham_proj_scan = 1 //Scanning function starts on + var/can_use = 1 + var/obj/effect/dummy/chameleon/active_dummy = null + var/saved_item = /obj/item/weapon/cigbutt + var/saved_icon = 'icons/obj/clothing/masks.dmi' + var/saved_icon_state = "cigbutt" + var/saved_overlays + +/obj/item/device/chameleon/dropped() + spawn() //So the chammy project is dropped into the dummy before the dummy empties itself out + disrupt() + +/obj/item/device/chameleon/equipped() + disrupt() + +/obj/item/device/chameleon/attack_self() + toggle() + +/obj/item/device/chameleon/verb/toggle_scaning() + set name = "Toggle Chameleon Projector Scanning" + set category = "Object" + + if(usr.isUnconscious()) + return + + cham_proj_scan = !cham_proj_scan + to_chat(usr, "You [cham_proj_scan ? "activate":"deactivate"] [src]'s scanning function") + +/obj/item/device/chameleon/preattack(atom/target, mob/user , proximity) + if(!proximity) + return + if(!cham_proj_scan) //Is scanning disabled ? + return + if(!active_dummy) + if(istype(target, /obj/item) && !istype(target, /obj/item/weapon/disk/nuclear) || istype(target, /mob)) + playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6) + to_chat(user, "Scanned [target].") + saved_item = target.type + saved_icon = target.icon + saved_icon_state = target.icon_state + saved_overlays = target.overlays + return 1 + +/obj/item/device/chameleon/proc/toggle() + if(!can_use || !saved_item) + return + if(active_dummy) + eject_all() + //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) + del(active_dummy) + active_dummy = null + to_chat(usr, "You deactivate [src].") + var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src)) + T.icon = 'icons/effects/effects.dmi' + flick("emppulse",T) + spawn(8) + qdel(T) + can_use = 0 + spawn(20) //Stop spamming this shit + can_use = 1 + else + //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) + var/obj/O = new saved_item(src) + if(!O) + return + var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(usr.loc) + C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src) + qdel(O) + O = null + to_chat(usr, "You activate [src].") + var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src)) + T.icon = 'icons/effects/effects.dmi' + flick("emppulse",T) + spawn(8) + qdel(T) + can_use = 0 + spawn(20) //Stop spamming this shit + can_use = 1 + +/obj/item/device/chameleon/proc/disrupt(var/delete_dummy = 1) + if(active_dummy) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread + spark_system.set_up(5, 0, src) + spark_system.attach(src) + spark_system.start() + eject_all() + if(delete_dummy) + qdel(active_dummy) + active_dummy = null + can_use = 0 + spawn(50) + can_use = 1 + +/obj/item/device/chameleon/proc/eject_all() + for(var/atom/movable/A in active_dummy) + A.loc = active_dummy.loc + if(ismob(A)) + var/mob/M = A + M.reset_view(null) + M.layer = MOB_LAYER //Reset the mob's layer + +/obj/effect/dummy/chameleon + name = "" + desc = "" + density = 0 + anchored = 0 + var/can_move = 1 + var/obj/item/device/chameleon/master = null + +/obj/effect/dummy/chameleon/proc/activate(var/obj/O, var/mob/M, new_icon, new_iconstate, new_overlays, var/obj/item/device/chameleon/C) + name = O.name + desc = O.desc + icon = new_icon + icon_state = new_iconstate + overlays = new_overlays + dir = O.dir + M.loc = src + M.layer = OBJ_LAYER //Needed for some things, notably lockers + master = C + master.active_dummy = src + +/obj/effect/dummy/chameleon/attackby() + for(var/mob/M in src) + to_chat(M, "Your chameleon-projector deactivates.") + master.disrupt() + +/obj/effect/dummy/chameleon/attack_hand() + for(var/mob/M in src) + to_chat(M, "Your chameleon-projector deactivates.") + master.disrupt() + +/obj/effect/dummy/chameleon/ex_act() + for(var/mob/M in src) + to_chat(M, "Your chameleon-projector deactivates.") + master.disrupt() + +/obj/effect/dummy/chameleon/bullet_act() + for(var/mob/M in src) + to_chat(M, "Your chameleon-projector deactivates.") + ..() + master.disrupt() + +/obj/effect/dummy/chameleon/relaymove(var/mob/user, direction) + if(istype(loc, /turf/space)) return //No magical space movement! + + if(can_move) + can_move = 0 + switch(user.bodytemperature) + if(300 to INFINITY) + spawn(8) + can_move = 1 + if(295 to 300) + spawn(11) + can_move = 1 + if(280 to 295) + spawn(14) + can_move = 1 + if(260 to 280) + spawn(18) + can_move = 1 + else + spawn(23) + can_move = 1 + step(src, direction) + return + +/obj/effect/dummy/chameleon/Destroy() + master.disrupt(0) + ..() diff --git a/code/game/objects/items/devices/debugger.dm b/code/game/objects/items/devices/debugger.dm index e0cef929f6b..293747f105f 100644 --- a/code/game/objects/items/devices/debugger.dm +++ b/code/game/objects/items/devices/debugger.dm @@ -1,47 +1,47 @@ -/** - * Multitool -- A multitool is used for hacking electronic devices. - * TO-DO -- Using it as a power measurement tool for cables etc. Nannek. - * - */ - -/obj/item/device/debugger - icon = 'icons/obj/hacktool.dmi' - name = "debugger" - desc = "Used to debug electronic equipment." - icon_state = "hacktool-g" - flags = FPRINT - siemens_coefficient = 1 - force = 5.0 - w_class = 2.0 - throwforce = 5.0 - throw_range = 15 - throw_speed = 3 - desc = "You can use this on airlocks or APCs to try to hack them without cutting wires." - starting_materials = list(MAT_IRON = 50, MAT_GLASS = 20) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_SILICON - origin_tech = "magnets=1;engineering=1" - var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage - -/obj/item/device/debugger/is_used_on(obj/O, mob/user) - if(istype(O, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = O - if(A.emagged || A.malfhack) +/** + * Multitool -- A multitool is used for hacking electronic devices. + * TO-DO -- Using it as a power measurement tool for cables etc. Nannek. + * + */ + +/obj/item/device/debugger + icon = 'icons/obj/hacktool.dmi' + name = "debugger" + desc = "Used to debug electronic equipment." + icon_state = "hacktool-g" + flags = FPRINT + siemens_coefficient = 1 + force = 5.0 + w_class = 2.0 + throwforce = 5.0 + throw_range = 15 + throw_speed = 3 + desc = "You can use this on airlocks or APCs to try to hack them without cutting wires." + starting_materials = list(MAT_IRON = 50, MAT_GLASS = 20) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_SILICON + origin_tech = "magnets=1;engineering=1" + var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage + +/obj/item/device/debugger/is_used_on(obj/O, mob/user) + if(istype(O, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = O + if(A.emagged || A.malfhack) to_chat(user, "There is a software error with the device.") - else + else to_chat(user, "The device's software appears to be fine.") - return 1 - if(istype(O, /obj/machinery/door)) - var/obj/machinery/door/D = O - if(D.operating == -1) + return 1 + if(istype(O, /obj/machinery/door)) + var/obj/machinery/door/D = O + if(D.operating == -1) to_chat(user, "There is a software error with the device.") - else + else to_chat(user, "The device's software appears to be fine.") - return 1 - else if(istype(O, /obj/machinery)) - var/obj/machinery/A = O - if(A.emagged) + return 1 + else if(istype(O, /obj/machinery)) + var/obj/machinery/A = O + if(A.emagged) to_chat(user, "There is a software error with the device.") - else + else to_chat(user, "The device's software appears to be fine.") return 1 \ No newline at end of file diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index d415c75a5fb..794e837f596 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -1,229 +1,229 @@ -/obj/item/device/flash - name = "flash" - desc = "Used for blinding and being an asshole." - icon_state = "flash" - item_state = "flash" - throwforce = 5 - w_class = 1.0 - throw_speed = 4 - throw_range = 10 - flags = FPRINT - siemens_coefficient = 1 - origin_tech = "magnets=2;combat=1" - min_harm_label = 15 //Multiple layers? - harm_label_examine = list("A label is on the bulb, but doesn't cover it.", "A label covers the bulb!") - - var/times_used = 0 //Number of times it's been used. - var/broken = 0 //Is the flash burnt out? - var/last_used = 0 //last world.time it was used. - -/obj/item/device/flash/proc/clown_check(var/mob/user) - if(user && (M_CLUMSY in user.mutations) && prob(50)) +/obj/item/device/flash + name = "flash" + desc = "Used for blinding and being an asshole." + icon_state = "flash" + item_state = "flash" + throwforce = 5 + w_class = 1.0 + throw_speed = 4 + throw_range = 10 + flags = FPRINT + siemens_coefficient = 1 + origin_tech = "magnets=2;combat=1" + min_harm_label = 15 //Multiple layers? + harm_label_examine = list("A label is on the bulb, but doesn't cover it.", "A label covers the bulb!") + + var/times_used = 0 //Number of times it's been used. + var/broken = 0 //Is the flash burnt out? + var/last_used = 0 //last world.time it was used. + +/obj/item/device/flash/proc/clown_check(var/mob/user) + if(user && (M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "\The [src] slips out of your hand.") - user.drop_item() - return 0 - return 1 - -/obj/item/device/flash/proc/flash_recharge() - //capacitor recharges over time - for(var/i=0, i<3, i++) - if(last_used+600 > world.time) - break - last_used += 600 - times_used -= 2 - last_used = world.time - times_used = max(0,round(times_used)) //sanity - - -/obj/item/device/flash/attack(mob/living/M as mob, mob/user as mob) - if(!user || !M) //sanity - return - - M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [key_name(user)]") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [key_name(M)]") - - log_attack("[key_name(user)] Used the [src.name] to flash [key_name(M)]") - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - if(!clown_check(user)) - return - - if(broken) + user.drop_item() + return 0 + return 1 + +/obj/item/device/flash/proc/flash_recharge() + //capacitor recharges over time + for(var/i=0, i<3, i++) + if(last_used+600 > world.time) + break + last_used += 600 + times_used -= 2 + last_used = world.time + times_used = max(0,round(times_used)) //sanity + + +/obj/item/device/flash/attack(mob/living/M as mob, mob/user as mob) + if(!user || !M) //sanity + return + + M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [key_name(user)]") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [key_name(M)]") + + log_attack("[key_name(user)] Used the [src.name] to flash [key_name(M)]") + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + if(!clown_check(user)) + return + + if(broken) to_chat(user, "\The [src] is broken.") - return - - flash_recharge() - - //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking - //It will never break on the first use. - switch(times_used) - if(0 to 5) - last_used = world.time - if(prob(times_used)) //if you use it 5 times in a minute it has a 10% chance to break! - broken = 1 + return + + flash_recharge() + + //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking + //It will never break on the first use. + switch(times_used) + if(0 to 5) + last_used = world.time + if(prob(times_used)) //if you use it 5 times in a minute it has a 10% chance to break! + broken = 1 to_chat(user, "The bulb has burnt out!") - icon_state = "flashburnt" - return - times_used++ - else //can only use it 5 times a minute + icon_state = "flashburnt" + return + times_used++ + else //can only use it 5 times a minute to_chat(user, "*click* *click*") - return - - playsound(get_turf(user), 'sound/weapons/flash.ogg', 100, 1) - - var/flashfail = (harm_labeled >= min_harm_label) //Flashfail is always true if the device has been successfully harm-labeled. - - if(iscarbon(M)) - var/mob/living/carbon/Subject = M - var/safe = Subject.eyecheck() - - if(safe <= 0) - Subject.Weaken(10) - flick("e_flash", Subject.flash) - - if(user.mind && isrevhead(user)) // alien revhead when? - if(ishuman(Subject)) - if(Subject.stat != DEAD) - Subject.mind_initialize() // give them a mind datum if they don't have one - - var/result = ticker.mode.add_revolutionary(Subject.mind) - - if(result == 1) - log_admin("[key_name(user)] has converted [key_name(Subject)] to the revolution at [formatLocation(Subject.loc)]") - Subject.mind.has_been_rev = TRUE - else if(result == -1 || Subject.mind.has_been_rev) // command positions or has been rev before (according to old code you cannot attempt to rev people that has been deconverted, can be remove) + return + + playsound(get_turf(user), 'sound/weapons/flash.ogg', 100, 1) + + var/flashfail = (harm_labeled >= min_harm_label) //Flashfail is always true if the device has been successfully harm-labeled. + + if(iscarbon(M)) + var/mob/living/carbon/Subject = M + var/safe = Subject.eyecheck() + + if(safe <= 0) + Subject.Weaken(10) + flick("e_flash", Subject.flash) + + if(user.mind && isrevhead(user)) // alien revhead when? + if(ishuman(Subject)) + if(Subject.stat != DEAD) + Subject.mind_initialize() // give them a mind datum if they don't have one + + var/result = ticker.mode.add_revolutionary(Subject.mind) + + if(result == 1) + log_admin("[key_name(user)] has converted [key_name(Subject)] to the revolution at [formatLocation(Subject.loc)]") + Subject.mind.has_been_rev = TRUE + else if(result == -1 || Subject.mind.has_been_rev) // command positions or has been rev before (according to old code you cannot attempt to rev people that has been deconverted, can be remove) to_chat(user, "This mind seems resistant to the flash!") - else if(result == -2) // rev jobbanned + else if(result == -2) // rev jobbanned to_chat(user, "This mind seems resistant to the flash! (OOC INFO: REVOLUTIONARY JOBBANNED)") - else if(result == -3) // loyalty implanted + else if(result == -3) // loyalty implanted to_chat(user, "Something seems to be blocking the flash!") - else + else to_chat(user, "This mind is so vacant that it is not susceptible to influence!") - else - flashfail = TRUE - else if(issilicon(M)) - M.Weaken(rand(5, 10)) - else - flashfail = TRUE - - if(isrobot(user)) - spawn(0) - var/atom/movable/overlay/animation = new(get_turf(user)) - animation.layer = user.layer + 1 - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = user - flick("blspell", animation) - sleep(5) - qdel(animation) - - if(!flashfail) - flick("flash2", src) - - if(!issilicon(M)) - user.visible_message("[user] blinds [M] with the flash!") - else - user.visible_message("[user] overloads [M]'s sensors with the flash!") - else - user.visible_message("[user] fails to blind [M] with the flash!") - -/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) - if(!user || !clown_check(user)) return - if(broken) - user.show_message("The [src.name] is broken", 2) - return - - flash_recharge() - - //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking - //It will never break on the first use. - switch(times_used) - if(0 to 5) - if(prob(2*times_used)) //if you use it 5 times in a minute it has a 10% chance to break! - broken = 1 + else + flashfail = TRUE + else if(issilicon(M)) + M.Weaken(rand(5, 10)) + else + flashfail = TRUE + + if(isrobot(user)) + spawn(0) + var/atom/movable/overlay/animation = new(get_turf(user)) + animation.layer = user.layer + 1 + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = user + flick("blspell", animation) + sleep(5) + qdel(animation) + + if(!flashfail) + flick("flash2", src) + + if(!issilicon(M)) + user.visible_message("[user] blinds [M] with the flash!") + else + user.visible_message("[user] overloads [M]'s sensors with the flash!") + else + user.visible_message("[user] fails to blind [M] with the flash!") + +/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) + if(!user || !clown_check(user)) return + if(broken) + user.show_message("The [src.name] is broken", 2) + return + + flash_recharge() + + //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking + //It will never break on the first use. + switch(times_used) + if(0 to 5) + if(prob(2*times_used)) //if you use it 5 times in a minute it has a 10% chance to break! + broken = 1 to_chat(user, "The bulb has burnt out!") - icon_state = "flashburnt" - return - times_used++ - else //can only use it 5 times a minute - user.show_message("*click* *click*", 2) - return - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) - if(harm_labeled >= min_harm_label) return //Act as if the flash was activated except the useful part. - flick("flash2", src) - if(user && isrobot(user)) - spawn(0) - var/atom/movable/overlay/animation = new(user.loc) - animation.layer = user.layer + 1 - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = user - flick("blspell", animation) - sleep(5) - qdel(animation) - animation = null - - for(var/mob/living/carbon/M in oviewers(3, null)) - if(prob(50)) - if (locate(/obj/item/weapon/cloaking_device, M)) - for(var/obj/item/weapon/cloaking_device/S in M) - S.active = 0 - S.icon_state = "shield0" - if(M.alpha < 255) - var/oldalpha = M.alpha - if(prob(80)) - M.alpha = 255 - M.visible_message("[M] suddenly becomes fully visible!",\ - "You see a bright flash of light and are suddenly fully visible again.") - spawn(50) - M.alpha = oldalpha - var/safety = M:eyecheck() - if(!safety) - if(!M.blinded) - flick("flash", M.flash) - - return - -/obj/item/device/flash/emp_act(severity) - if(broken) return - flash_recharge() - switch(times_used) - if(0 to 5) - if(prob(2*times_used)) - broken = 1 - icon_state = "flashburnt" - return - times_used++ - if(istype(loc, /mob/living/carbon) && harm_labeled < min_harm_label) - var/mob/living/carbon/M = loc - var/safety = M.eyecheck() - if(safety <= 0) - M.Weaken(10) - flick("e_flash", M.flash) - for(var/mob/O in viewers(M, null)) - O.show_message("[M] is blinded by the flash!") - ..() - -/obj/item/device/flash/synthetic - name = "synthetic flash" - desc = "When a problem arises, SCIENCE is the solution." - icon_state = "sflash" - origin_tech = "magnets=2;combat=1" - -/obj/item/device/flash/synthetic/attack(mob/living/M as mob, mob/user as mob) - ..() - if(!broken) - broken = 1 + icon_state = "flashburnt" + return + times_used++ + else //can only use it 5 times a minute + user.show_message("*click* *click*", 2) + return + playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) + if(harm_labeled >= min_harm_label) return //Act as if the flash was activated except the useful part. + flick("flash2", src) + if(user && isrobot(user)) + spawn(0) + var/atom/movable/overlay/animation = new(user.loc) + animation.layer = user.layer + 1 + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = user + flick("blspell", animation) + sleep(5) + qdel(animation) + animation = null + + for(var/mob/living/carbon/M in oviewers(3, null)) + if(prob(50)) + if (locate(/obj/item/weapon/cloaking_device, M)) + for(var/obj/item/weapon/cloaking_device/S in M) + S.active = 0 + S.icon_state = "shield0" + if(M.alpha < 255) + var/oldalpha = M.alpha + if(prob(80)) + M.alpha = 255 + M.visible_message("[M] suddenly becomes fully visible!",\ + "You see a bright flash of light and are suddenly fully visible again.") + spawn(50) + M.alpha = oldalpha + var/safety = M:eyecheck() + if(!safety) + if(!M.blinded) + flick("flash", M.flash) + + return + +/obj/item/device/flash/emp_act(severity) + if(broken) return + flash_recharge() + switch(times_used) + if(0 to 5) + if(prob(2*times_used)) + broken = 1 + icon_state = "flashburnt" + return + times_used++ + if(istype(loc, /mob/living/carbon) && harm_labeled < min_harm_label) + var/mob/living/carbon/M = loc + var/safety = M.eyecheck() + if(safety <= 0) + M.Weaken(10) + flick("e_flash", M.flash) + for(var/mob/O in viewers(M, null)) + O.show_message("[M] is blinded by the flash!") + ..() + +/obj/item/device/flash/synthetic + name = "synthetic flash" + desc = "When a problem arises, SCIENCE is the solution." + icon_state = "sflash" + origin_tech = "magnets=2;combat=1" + +/obj/item/device/flash/synthetic/attack(mob/living/M as mob, mob/user as mob) + ..() + if(!broken) + broken = 1 to_chat(user, "The bulb has burnt out!") - icon_state = "flashburnt" - -/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) - ..() - if(!broken) - broken = 1 + icon_state = "flashburnt" + +/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) + ..() + if(!broken) + broken = 1 to_chat(user, "The bulb has burnt out!") - icon_state = "flashburnt" + icon_state = "flashburnt" diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 9630f43a7a2..ae3503a95ac 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -1,244 +1,244 @@ -/obj/item/device/flashlight - name = "flashlight" - desc = "A hand-held emergency light." - icon = 'icons/obj/lighting.dmi' - icon_state = "flashlight" - item_state = "flashlight" - origin_tech = "engineering=1" - w_class = 2 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - starting_materials = list(MAT_IRON = 50, MAT_GLASS = 20) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_STEEL // Assuming big beefy fucking maglite. - action_button_name = "Toggle Light" - var/on = 0 - var/brightness_on = 4 //luminosity when on - -/obj/item/device/flashlight/initialize() - ..() - if(on) - icon_state = "[initial(icon_state)]-on" - set_light(brightness_on) - else - icon_state = initial(icon_state) - set_light(0) - -/obj/item/device/flashlight/proc/update_brightness(var/mob/user = null) - if(on) - icon_state = "[initial(icon_state)]-on" - set_light(brightness_on) - else - icon_state = initial(icon_state) - set_light(0) - -/obj/item/device/flashlight/attack_self(mob/user) - if(!isturf(user.loc)) - to_chat(user, "You cannot turn the light on while in this [user.loc].")//To prevent some lighting anomalities. +/obj/item/device/flashlight + name = "flashlight" + desc = "A hand-held emergency light." + icon = 'icons/obj/lighting.dmi' + icon_state = "flashlight" + item_state = "flashlight" + origin_tech = "engineering=1" + w_class = 2 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + starting_materials = list(MAT_IRON = 50, MAT_GLASS = 20) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_STEEL // Assuming big beefy fucking maglite. + action_button_name = "Toggle Light" + var/on = 0 + var/brightness_on = 4 //luminosity when on - return 0 - on = !on - update_brightness(user) - return 1 - - -/obj/item/device/flashlight/attack(mob/living/M as mob, mob/living/user as mob) - add_fingerprint(user) - if(on && user.zone_sel.selecting == "eyes") - - if(((M_CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly - return ..() //just hit them in the head - - if (!user.dexterity_check()) +/obj/item/device/flashlight/initialize() + ..() + if(on) + icon_state = "[initial(icon_state)]-on" + set_light(brightness_on) + else + icon_state = initial(icon_state) + set_light(0) + +/obj/item/device/flashlight/proc/update_brightness(var/mob/user = null) + if(on) + icon_state = "[initial(icon_state)]-on" + set_light(brightness_on) + else + icon_state = initial(icon_state) + set_light(0) + +/obj/item/device/flashlight/attack_self(mob/user) + if(!isturf(user.loc)) + to_chat(user, "You cannot turn the light on while in this [user.loc].")//To prevent some lighting anomalities. + + return 0 + on = !on + update_brightness(user) + return 1 + + +/obj/item/device/flashlight/attack(mob/living/M as mob, mob/living/user as mob) + add_fingerprint(user) + if(on && user.zone_sel.selecting == "eyes") + + if(((M_CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly + return ..() //just hit them in the head + + if (!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") - return - - var/mob/living/carbon/human/H = M //mob has protective eyewear - if(istype(M, /mob/living/carbon/human)) - var/obj/item/eye_protection = H.get_body_part_coverage(EYES) - if(eye_protection) - to_chat(user, "You're going to need to remove their [eye_protection] first.") - return - - if(M == user) //they're using it on themselves - if(!M.blinded) - flick("flash", M.flash) - M.visible_message("[M] directs [src] to \his eyes.", \ - "You wave the light in front of your eyes! Trippy!") - else - M.visible_message("[M] directs [src] to \his eyes.", \ - "You wave the light in front of your eyes.") - return - - user.visible_message("[user] directs [src] to [M]'s eyes.", \ - "You direct [src] to [M]'s eyes.") - - if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey)) //robots and aliens are unaffected - if(M.stat == DEAD || M.sdisabilities & BLIND) //mob is dead or fully blind - to_chat(user, "[M] pupils does not react to the light!") - else if(M_XRAY in M.mutations) //mob has X-RAY vision - flick("flash", M.flash) //Yes, you can still get flashed wit X-Ray. - to_chat(user, "[M] pupils give an eerie glow!") - else //they're okay! - if(!M.blinded) - flick("flash", M.flash) //flash the affected mob - to_chat(user, "[M]'s pupils narrow.") - else - return ..() - -/obj/item/device/flashlight/pen - name = "penlight" - desc = "A pen-sized light, used by medical staff." - icon_state = "penlight" - item_state = "" - flags = FPRINT - siemens_coefficient = 1 - brightness_on = 2 - - -// the desk lamps are a bit special -/obj/item/device/flashlight/lamp - name = "desk lamp" - desc = "A desk lamp with an adjustable mount." - icon_state = "lamp" - item_state = "lamp" - brightness_on = 5 - w_class = 4 - flags = FPRINT - siemens_coefficient = 1 - starting_materials = null - on = 1 - -/obj/item/device/flashlight/lamp/cultify() - new /obj/structure/cult/pylon(loc) - qdel(src) - -// green-shaded desk lamp -/obj/item/device/flashlight/lamp/green - desc = "A classic green-shaded desk lamp." - icon_state = "lampgreen" - item_state = "lampgreen" - brightness_on = 5 - - -/obj/item/device/flashlight/lamp/verb/toggle_light() - set name = "Toggle light" - set category = "Object" - set src in oview(1) - - if(!usr.stat) - attack_self(usr) - -// FLARES - -/obj/item/device/flashlight/flare - name = "flare" - desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'." - w_class = 2.0 - brightness_on = 4 // Pretty bright. - light_power = 2.5 - icon_state = "flare" - item_state = "flare" - action_button_name = null //just pull it manually, neckbeard. - var/fuel = 0 - var/on_damage = 7 - var/produce_heat = 1500 - var/H_color = "" - - light_color = LIGHT_COLOR_FLARE - -/obj/item/device/flashlight/flare/New() - fuel = rand(300, 500) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds. - ..() - -/obj/item/device/flashlight/flare/process() - var/turf/pos = get_turf(src) - if(pos) - pos.hotspot_expose(produce_heat, 5,surfaces=istype(loc,/turf)) - fuel = max(fuel - 1, 0) - if(!fuel || !on) - turn_off() - if(!fuel) - src.icon_state = "[initial(icon_state)]-empty" - processing_objects -= src - -/obj/item/device/flashlight/flare/proc/turn_off() - on = 0 - src.force = initial(src.force) - src.damtype = initial(src.damtype) - if(ismob(loc)) - var/mob/U = loc - update_brightness(U) - else - update_brightness() - -/obj/item/device/flashlight/flare/attack_self(mob/user) - - // Usual checks - if(!fuel) - to_chat(user, "It's out of fuel.") - return - if(on) - return - // All good, turn it on. - user.visible_message("[user] activates the flare.", "You pull the cord on the flare, activating it!") - Light(user) - -/obj/item/device/flashlight/flare/proc/Light(var/mob/user as mob) - if(user) - if(!isturf(user.loc)) - to_chat(user, "You cannot turn the light on while in this [user.loc].")//To prevent some lighting anomalities. + return - return 0 - on = 1 - src.force = on_damage - src.damtype = "fire" - processing_objects += src - if(user) - update_brightness(user) - else - update_brightness() - -/obj/item/device/flashlight/flare/ever_bright/New() - . = ..() - fuel = INFINITY - Light() - -// SLIME LAMP -/obj/item/device/flashlight/lamp/slime - name = "slime lamp" - desc = "A lamp powered by a slime core. You can adjust its brightness by touching it." - icon_state = "slimelamp" - item_state = "" - origin_tech = "biotech=3" - light_color = LIGHT_COLOR_SLIME_LAMP - on = 0 - luminosity = 2 - var/brightness_max = 6 - var/brightness_min = 2 - -/obj/item/device/flashlight/lamp/slime/initialize() - ..() - if(on) - icon_state = "[initial(icon_state)]-on" - set_light(brightness_max) - else - icon_state = initial(icon_state) - set_light(brightness_min) - -/obj/item/device/flashlight/lamp/slime/proc/slime_brightness(var/mob/user = null) - if(on) - icon_state = "[initial(icon_state)]-on" - set_light(brightness_max) - else - icon_state = initial(icon_state) - set_light(brightness_min) - -/obj/item/device/flashlight/lamp/slime/attack_self(mob/user) - if(!isturf(user.loc)) + var/mob/living/carbon/human/H = M //mob has protective eyewear + if(istype(M, /mob/living/carbon/human)) + var/obj/item/eye_protection = H.get_body_part_coverage(EYES) + if(eye_protection) + to_chat(user, "You're going to need to remove their [eye_protection] first.") + return + + if(M == user) //they're using it on themselves + if(!M.blinded) + flick("flash", M.flash) + M.visible_message("[M] directs [src] to \his eyes.", \ + "You wave the light in front of your eyes! Trippy!") + else + M.visible_message("[M] directs [src] to \his eyes.", \ + "You wave the light in front of your eyes.") + return + + user.visible_message("[user] directs [src] to [M]'s eyes.", \ + "You direct [src] to [M]'s eyes.") + + if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey)) //robots and aliens are unaffected + if(M.stat == DEAD || M.sdisabilities & BLIND) //mob is dead or fully blind + to_chat(user, "[M] pupils does not react to the light!") + else if(M_XRAY in M.mutations) //mob has X-RAY vision + flick("flash", M.flash) //Yes, you can still get flashed wit X-Ray. + to_chat(user, "[M] pupils give an eerie glow!") + else //they're okay! + if(!M.blinded) + flick("flash", M.flash) //flash the affected mob + to_chat(user, "[M]'s pupils narrow.") + else + return ..() + +/obj/item/device/flashlight/pen + name = "penlight" + desc = "A pen-sized light, used by medical staff." + icon_state = "penlight" + item_state = "" + flags = FPRINT + siemens_coefficient = 1 + brightness_on = 2 + + +// the desk lamps are a bit special +/obj/item/device/flashlight/lamp + name = "desk lamp" + desc = "A desk lamp with an adjustable mount." + icon_state = "lamp" + item_state = "lamp" + brightness_on = 5 + w_class = 4 + flags = FPRINT + siemens_coefficient = 1 + starting_materials = null + on = 1 + +/obj/item/device/flashlight/lamp/cultify() + new /obj/structure/cult/pylon(loc) + qdel(src) + +// green-shaded desk lamp +/obj/item/device/flashlight/lamp/green + desc = "A classic green-shaded desk lamp." + icon_state = "lampgreen" + item_state = "lampgreen" + brightness_on = 5 + + +/obj/item/device/flashlight/lamp/verb/toggle_light() + set name = "Toggle light" + set category = "Object" + set src in oview(1) + + if(!usr.stat) + attack_self(usr) + +// FLARES + +/obj/item/device/flashlight/flare + name = "flare" + desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'." + w_class = 2.0 + brightness_on = 4 // Pretty bright. + light_power = 2.5 + icon_state = "flare" + item_state = "flare" + action_button_name = null //just pull it manually, neckbeard. + var/fuel = 0 + var/on_damage = 7 + var/produce_heat = 1500 + var/H_color = "" + + light_color = LIGHT_COLOR_FLARE + +/obj/item/device/flashlight/flare/New() + fuel = rand(300, 500) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds. + ..() + +/obj/item/device/flashlight/flare/process() + var/turf/pos = get_turf(src) + if(pos) + pos.hotspot_expose(produce_heat, 5,surfaces=istype(loc,/turf)) + fuel = max(fuel - 1, 0) + if(!fuel || !on) + turn_off() + if(!fuel) + src.icon_state = "[initial(icon_state)]-empty" + processing_objects -= src + +/obj/item/device/flashlight/flare/proc/turn_off() + on = 0 + src.force = initial(src.force) + src.damtype = initial(src.damtype) + if(ismob(loc)) + var/mob/U = loc + update_brightness(U) + else + update_brightness() + +/obj/item/device/flashlight/flare/attack_self(mob/user) + + // Usual checks + if(!fuel) + to_chat(user, "It's out of fuel.") + return + if(on) + return + // All good, turn it on. + user.visible_message("[user] activates the flare.", "You pull the cord on the flare, activating it!") + Light(user) + +/obj/item/device/flashlight/flare/proc/Light(var/mob/user as mob) + if(user) + if(!isturf(user.loc)) + to_chat(user, "You cannot turn the light on while in this [user.loc].")//To prevent some lighting anomalities. + + return 0 + on = 1 + src.force = on_damage + src.damtype = "fire" + processing_objects += src + if(user) + update_brightness(user) + else + update_brightness() + +/obj/item/device/flashlight/flare/ever_bright/New() + . = ..() + fuel = INFINITY + Light() + +// SLIME LAMP +/obj/item/device/flashlight/lamp/slime + name = "slime lamp" + desc = "A lamp powered by a slime core. You can adjust its brightness by touching it." + icon_state = "slimelamp" + item_state = "" + origin_tech = "biotech=3" + light_color = LIGHT_COLOR_SLIME_LAMP + on = 0 + luminosity = 2 + var/brightness_max = 6 + var/brightness_min = 2 + +/obj/item/device/flashlight/lamp/slime/initialize() + ..() + if(on) + icon_state = "[initial(icon_state)]-on" + set_light(brightness_max) + else + icon_state = initial(icon_state) + set_light(brightness_min) + +/obj/item/device/flashlight/lamp/slime/proc/slime_brightness(var/mob/user = null) + if(on) + icon_state = "[initial(icon_state)]-on" + set_light(brightness_max) + else + icon_state = initial(icon_state) + set_light(brightness_min) + +/obj/item/device/flashlight/lamp/slime/attack_self(mob/user) + if(!isturf(user.loc)) to_chat(user, "You cannot turn the light on while in this [user.loc].") - return 0 - on = !on - slime_brightness(user) - return 1 + return 0 + on = !on + slime_brightness(user) + return 1 diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 996073b93bc..652dd673d5f 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -1,593 +1,593 @@ - -// Light Replacer (LR) -// -// ABOUT THE DEVICE -// -// This is a device supposedly to be used by Janitors and Janitor Cyborgs which will -// allow them to easily replace lights. This was mostly designed for Janitor Cyborgs since -// they don't have hands or a way to replace lightbulbs. -// -// HOW IT WORKS -// -// You attack a light fixture with it. If the light fixture is broken, it will replace the -// light fixture with a working light. The broken light is then placed into the device's waste box. -// If the fixture is empty then it will just place a light in the fixture. -// -// HOW TO REFILL THE DEVICE -// -// The supply box can be removed and replaced to refill the whole thing at once or lights can be inserted into the device. -// Additionally, it can process glass into any type of light, though it uses much more than other methods of making lights -// and lights made this way start out with a high switchcount. -// -// EMAGGED FEATURES -// -// NOTICE: The Cyborg cannot use the emagged Light Replacer and the light's explosion was nerfed. It cannot create holes in the station anymore. -// -// I'm not sure everyone will react the emag's features so please say what your opinions are of it. -// -// When emagged it will rig every light it replaces, which will explode when the light is on. -// This is VERY noticable, even the device's name changes when you emag it so if anyone -// examines you when you're holding it in your hand, you will be discovered. -// It will also be very obvious who is setting all these lights off, since only Janitor Borgs and Janitors have easy -// access to them, and only one of them can emag their device. -// -// The explosion cannot insta-kill anyone with 30% or more health. - -#define LIGHT_OK 0 -#define LIGHT_EMPTY 1 -#define LIGHT_BROKEN 2 -#define LIGHT_BURNED 3 - - -/obj/item/device/lightreplacer - - name = "light replacer" - desc = "A device to automatically replace lights. Takes lights from a supply box and puts the spent ones in a waste box. It is slotted to accept specifically light bulb/tube boxes." - - icon = 'icons/obj/janitor.dmi' - icon_state = "lightreplacer0" - item_state = "electronic" - - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - origin_tech = "magnets=3;materials=2" - - var/obj/item/weapon/storage/box/lights/supply = null //Takes bulbs from here to replace - var/obj/item/weapon/storage/box/lights/waste = null //Places replaced bulbs here - var/glass_stor = 0 //How much glass it contains for producing lights - var/glass_stor_max = 5 * CC_PER_SHEET_GLASS //Max glass it can hold - var/prod_quality = 30 //Starting switchcount for lights this builds out of glass - var/prod_eff = 10 //How many times more glass it uses to build lights than would an autolathe - var/cardboard_stor //How many sheets of cardboard it contains for quick-assembling boxes - var/cardboard_stor_max = 5 - var/emagged = 0 - var/light_types_glass = list() //An associative list with the starting glass amount for each type of light that is fabricated. - //Populated with a new entry each time a new type of light is made by the replacer for the first time in a given round. - //The key is the part of the typepath after /obj/item/weapon/light/ in string form. The value is its starting glass amount. - -/obj/item/device/lightreplacer/borg //Since it will mainly be loaded by processing glass, it is MUCH better at it than the standard version. - desc = "A device to automatically replace lights. Takes lights from a supply container and puts the spent ones in a waste container. It is fitted with a rudimentary recycling system to recover some glass from the waste lights." - glass_stor_max = 10 * CC_PER_SHEET_GLASS //Twice the capacity of the standard version. It also starts full, but this is done in New(). - prod_quality = 0 //Just as good as lights from a box/autolathe - prod_eff = 5 //Half the glass per light as the standard version - cardboard_stor_max = 0 //No removing or building new boxes for borgs. - var/recycle_eff_broken = 0.5 //Proportion of glass returned by the built-in recycler. - var/recycle_eff_burned = 0.9 //Proportion of glass returned by the built-in recycler. - var/recycle_eff_ok = 1 //Proportion of glass returned by the built-in recycler. Note that this does not allow infinite fabrication and recycling due to production losses. - var/glass_per_charge = 500 //Note: Adjust if the default borg light replacer efficiency is changed. - -/obj/item/device/lightreplacer/loaded/New() //Contains only a waste box. Exists mainly just as a parent of the other loaded ones, but I guess you can use it. - ..() - waste = new(src) - cardboard_stor = cardboard_stor_max //Might as well. - -/obj/item/device/lightreplacer/loaded/mixed/New() //Contains a box of normal mixed lights plus a waste box. - ..() - supply = new /obj/item/weapon/storage/box/lights/mixed(src) - -/obj/item/device/lightreplacer/loaded/he/New() //Contains a box of high-efficiency mixed lights plus a waste box. - ..() - supply = new /obj/item/weapon/storage/box/lights/he(src) - -/obj/item/device/lightreplacer/borg/New() //Contains a box of mixed lights and a waste box and starts full of glass. - ..() - supply = new /obj/item/weapon/storage/box/lights/mixed(src) - waste = new /obj/item/weapon/storage/box/lights(src) - add_glass(glass_stor_max, force_fill = 2) - -/obj/item/device/lightreplacer/examine(mob/user) - ..() - if(supply) - if(supply.contents.len) - to_chat(user, "It has [supply.contents.len] light[supply.contents.len == 1 ? "" : "s"] remaining. Check its interface to see what type[supply.contents.len == 1 ? "" : "s"].") - else - to_chat(user, "Its supply container is empty.") - else - to_chat(user, "It has no supply container.") - - if(waste) - to_chat(user, "Its waste container has [waste.contents.len] slot[waste.contents.len == 1 ? "" : "s"] full.") - else - to_chat(user, "It has no waste container.") - - to_chat(user, "Its glass storage contains [glass_stor] unit[waste.contents.len == 1 ? "" : "s"].") - - -/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/card/emag) && emagged == 0) - Emag() - return - - if(istype(W, /obj/item/stack/sheet/glass/glass)) - if(!add_glass(CC_PER_SHEET_GLASS, force_fill = 1)) - to_chat(user, "\The [src] can't hold any more glass!") - return - var/obj/item/stack/sheet/glass/glass/G = W - G.use(1) - to_chat(user, "You insert \the [G] into \the [src].") - return - - if(istype(W, /obj/item/weapon/light)) - var/obj/item/weapon/light/L = W - switch(insert_if_possible(L)) - if(0) - if(L.status ? istype(waste) : istype(supply)) //The expression returns true if the correct box for the light is valid, which implies that it is full because the insertion failed. - to_chat(user, "\The [src]'s [L.status ? "waste" : "supply"] container is full!") - else - to_chat(user, "\The [src] has no [L.status ? "waste" : "supply"] container!") - if(1) - user.visible_message("[user] inserts \a [L] into \the [src]", "You insert \the [L] into \the [src]'s [L.status ? "waste" : "supply"] container.") - else - to_chat(user, "Something very strange has happened. Please adminhelp and ask someone to view the variables of that light, especially status.") - return - - if(istype(W, /obj/item/weapon/storage/box/lights)) - if(!supply) - if(user.drop_item(W, src)) - user.visible_message("[user] inserts \a [W] into \the [src]", "You insert \the [W] into \the [src] to be used as the supply container.") - supply = W - return - else if(!waste) - if(user.drop_item(W, src)) - user.visible_message("[user] inserts \a [W] into \the [src]", "You insert \the [W] into \the [src] to be used as the waste container.") - waste = W - return - else - var/obj/item/weapon/storage/box/lights/lsource = W - if(!lsource.contents.len) - to_chat(user, "\The [src] has both a supply box and a waste box and this box is empty. Remove one first if you want to insert a new one or use a light box with lights in it to insert them.") - return - var/hasinserted = 0 - for(var/obj/item/weapon/light/L in lsource) - if(insert_if_possible(L)) - hasinserted = 1 - if(hasinserted) - to_chat(user, "\The [src] accepts the lights in \the [lsource].") - else - to_chat(user, "\The [src] cannot accept any of the lights in \the [lsource]!") - return - - if(istype(W, /obj/item/stack/sheet/cardboard)) - if(cardboard_stor >= cardboard_stor_max) - to_chat(user, "\The [src] cannot hold any more cardboard!") - return - var/obj/item/stack/sheet/cardboard/C = W - cardboard_stor++ - C.use(1) - to_chat(user, "You insert a cardboard sheet into \the [src].") - return - -/obj/item/device/lightreplacer/attack_self(mob/user) - var/dat = {"Light Replacer Interface - - Glass storage: [glass_stor]/[glass_stor_max]
    Cardboard Sheets: [cardboard_stor]/[cardboard_stor_max]
    "} - - if(supply) - dat += {"Fabricate Tube - Fabricate Bulb - - - -

    Supply Container:

    "} //It's not clear here, but the argument to build is the part of the typepath after /obj/item/weapon/light/ - var/list/light_types = new() - var/lightname - for(var/obj/item/weapon/light/L in supply) - lightname = "" - if(L.status == LIGHT_BROKEN) - lightname += "broken " - else if(L.status == LIGHT_BURNED) - lightname += "burned-out " - lightname += L.name - if(!light_types[lightname]) - light_types[lightname] = list() - light_types[lightname] += L - - var/list/light_type_cur - var/list/to_dump_5 //I guess I could do this without this variable, but it would involve more string concatenation, and nobody wants that. - var/list/to_dump_all//This too - - for(var/T in light_types) - light_type_cur = light_types[T] //The way you'd expect to be the good way to do this doesn't work. This is dumb, but necessary. - to_dump_5 = list() - to_dump_all = list() - for(var/light_to_ref in light_type_cur) - to_dump_all += "\ref[light_to_ref]" - to_dump_5 = to_dump_all.Copy(1, min(6, to_dump_all.len + 1)) - dat += "
    [T]: [light_type_cur.len] | Dump to Waste: 15All" - - dat += "
    Eject Supply Container" - - else - dat += "

    No supply container inserted


    Construct Supply Box" - - if(supply || waste) - dat += "

    Swap Supply and Waste Containers" - - if(waste) - dat += {"


    Waste Container:

    - - Filled: [waste.contents.len]/[waste.storage_slots]
    - Eject Waste Container - "} - else - dat += "


    No waste container inserted


    Construct Waste Box" - - var/datum/browser/popup = new(user, "lightreplacer", "", nref = src) - popup.set_content(dat) - popup.open() - -/obj/item/device/lightreplacer/borg/attack_self(mob/user) //The menu must be different to accomodate the differences necessary for the borg version. - /* // This would probably be a bit OP. If you want it though, uncomment the code. - if(isrobot(user)) - var/mob/living/silicon/robot/R = user - if(R.emagged) - src.Emag() - to_chat(usr, "You shortcircuit the [src].") - return - */ - - var/dat = {"Light Replacer Interface - - Glass storage: [glass_stor]/[glass_stor_max]
    "} - - if(supply) - dat += {"Fabricate Tube - Fabricate Bulb - Fabricate High Efficiency Tube - Fabricate High Efficiency Bulb - - - -

    Supply Container:

    "} - var/list/light_types = new() - var/lightname - for(var/obj/item/weapon/light/L in supply) - lightname = "" - if(L.status == LIGHT_BROKEN) - lightname += "broken " - else if(L.status == LIGHT_BURNED) - lightname += "burned-out " - lightname += L.name - if(!light_types[lightname]) - light_types[lightname] = list() - light_types[lightname] += L - - var/list/light_type_cur - var/list/to_dump_5//I guess I could do this without this variable, but it would include more string concatenation, and nobody wants that. - var/list/to_dump_all //This too - - for(var/T in light_types) - to_dump_5 = list() - to_dump_all = list() - light_type_cur = light_types[T] //The way you'd expect to be the good way to do this doesn't work. This is dumb, but necessary. - for(var/light_to_ref in light_type_cur) - to_dump_all += "\ref[light_to_ref]" - to_dump_5 = to_dump_all.Copy(1, min(6, to_dump_all.len + 1)) - dat += "
    [T]: [light_type_cur.len] | Dump to Waste: 15All" - - else - dat += "

    No supply container inserted. This should be impossible. Please ahelp this.

    " - - if(supply || waste) - dat += "

    Swap Supply and Waste Containers" - - if(waste) - dat += {"


    Waste Container:

    - - Filled: [waste.contents.len]/[waste.storage_slots]
    - Recycle Contents - "} - else - dat += "


    No waste container inserted. This should be impossible. Please ahelp this.

    " - - var/datum/browser/popup = new(user, "lightreplacer", "", nref = src) - popup.set_content(dat) - popup.open() - -/obj/item/device/lightreplacer/update_icon() - icon_state = "lightreplacer[emagged]" - - -/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/user) - var/obj/item/weapon/light/best_light = get_best_light(target) - if(best_light == 0) - to_chat(user, "\The [src] has no supply container!") - return - else if(!best_light) - to_chat(user, "\The [src] has no compatible light!") - return - if(!is_light_better(best_light, target)) - to_chat(user, "\The [src] has no light better than the one already in \the [target].") - return - - - to_chat(user, "You replace the [target.fitting] with \the [src].") - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) - - supply.remove_from_storage(best_light) - - if(target.status != LIGHT_EMPTY) - var/obj/item/weapon/light/L1 = new target.light_type(target.loc) - L1.status = target.status - L1.rigged = target.rigged - L1.brightness_range = target.brightness_range - L1.brightness_power = target.brightness_power - L1.brightness_color = target.brightness_color - L1.cost = target.cost - L1.base_state = target.base_state - L1.switchcount = target.switchcount - target.switchcount = 0 - L1.update() - target.status = LIGHT_EMPTY - target.update() - if(!insert_if_possible(L1)) - if(istype(waste)) - to_chat(user, "\The [src]'s waste container is full and it drops the removed light on the floor!") - else - to_chat(user, "\The [src] has no waste container and it drops the removed light on the floor!") - - target.status = best_light.status - target.switchcount = best_light.switchcount - target.rigged = emagged || best_light.rigged - target.brightness_range = best_light.brightness_range - target.brightness_power = best_light.brightness_power - target.brightness_color = best_light.brightness_color - target.cost = best_light.cost - target.base_state = best_light.base_state - target.light_type = best_light.type - target.on = target.has_power() - target.update() - qdel(best_light) - best_light = null - if(target.on && target.rigged) - target.explode() - - -/obj/item/device/lightreplacer/proc/Emag() - emagged = !emagged - playsound(get_turf(src), "sparks", 100, 1) - if(emagged) - name = "Shortcircuited [initial(name)]" - else - name = initial(name) - update_icon() - - -//Attempts to insert a light into the light replacer's storage. -//If the light works, attempts to place it in the supply box. Otherwise, attempts to place it in the waste box. -//Fails if the light cannot be placed into the correct box for any reason. -//Returns 1 if the light is successfully inserted into the correct box, 0 if the insertion fails, and null if the item to be inserted is not a light or something very strange happens. -/obj/item/device/lightreplacer/proc/insert_if_possible(var/obj/item/weapon/light/L) - if(!istype(L)) - return - if(L.status == LIGHT_OK) - if(supply && supply.can_be_inserted(L, TRUE)) - if(istype(L.loc, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/lsource = L.loc - lsource.remove_from_storage(L, supply) - else - supply.handle_item_insertion(L, TRUE) - return 1 - else - return 0 - else if(L.status == LIGHT_BROKEN || L.status == LIGHT_BURNED) - if(waste && waste.can_be_inserted(L, TRUE)) - if(istype(L.loc, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/lsource = L.loc - lsource.remove_from_storage(L, waste) - else - waste.handle_item_insertion(L, TRUE) - return 1 - else - return 0 - -//Returns the best light currently in the supply container that is compatible with target. -//For the standard light replacer, it just prioritizes HE lights over standard lights. I may add an advanced replacer with better light selection later. -//Returns null if no compatible bulb is found and 0 if the light replacer has no (valid) supply box. -/obj/item/device/lightreplacer/proc/get_best_light(var/obj/machinery/light/target) - if(!istype(supply)) - return 0 - var/best_light - switch(target.fitting) - if("bulb") - best_light = (locate(/obj/item/weapon/light/bulb/he) in supply) || (locate(/obj/item/weapon/light/bulb) in supply) - if("tube") - best_light = (locate(/obj/item/weapon/light/tube/he) in supply) || (locate(/obj/item/weapon/light/tube) in supply) - if("large tube") - best_light = locate(/obj/item/weapon/light/tube/large) in supply - return best_light - -//Returns 1 if the first argument is considered better, 0 if the second is better or they are equal, and null if either argument is invalid. -//To be valid, each argument must be an instance of either /obj/item/weapon/light or /obj/machinery/light. -//Again, standard replacer just checks as follows: -//HE light < standard light < no light < broken light = burned-out light -//In normal operation, tested should never be no light and very rarely be a broken light. -/obj/item/device/lightreplacer/proc/is_light_better(var/obj/tested, var/obj/comparison) - if(!(istype(tested, /obj/item/weapon/light) || istype(tested, /obj/machinery/light)) || !(istype(comparison, /obj/item/weapon/light) || istype(comparison, /obj/machinery/light))) - return - if(tested:status >= LIGHT_BROKEN) //Is tested broken or burnt out? If so, it cannot win. - return 0 - if(tested:status < comparison:status) //Is tested closer to functional than comparison? If so, it wins. - return 1 - if(tested:status) //Is tested empty? If so, either it must be a tie or comparison wins, so tested cannot win. - return 0 - - //Now we know both work, so all that is left is to test if tested wins by being HE. - if(findtextEx(tested:base_state, "he", 1, 3) && !findtextEx(comparison:base_state, "he", 1, 3)) - return 1 - else - return 0 - -//Can you use it? -//This used to actually check if it wasn't empty, but that's handled in ReplaceLight() now. - -/obj/item/device/lightreplacer/proc/CanUse(var/mob/living/user) - src.add_fingerprint(user) - //Not sure what else to check for. Maybe if clumsy? - return 1 - -/obj/item/device/lightreplacer/borg/proc/Charge(var/mob/user) - add_glass(glass_per_charge, force_fill = 2) - -//Adds amt glass to the glass storage if possible. -//If force_fill is 0, fails if there is not enough room for all of amt. -//If force_fill is 1, fails only if amt is totally full. -//If force_fill is 2, never fails. -//Returns 1 on success and 0 on fail. -/obj/item/device/lightreplacer/proc/add_glass(var/amt, var/force_fill = 0) - if(!force_fill) - if(glass_stor + amt > glass_stor_max) - return 0 - else if(force_fill == 1) - if(glass_stor >= glass_stor_max) - return 0 - glass_stor = min(glass_stor_max, glass_stor + amt) - return 1 - -//Attempts to use amt glass from storage. Returns 1 on success and 0 on failure. -/obj/item/device/lightreplacer/proc/use_glass(var/amt) - if(amt > glass_stor) - return 0 - glass_stor -= amt - return 1 - -/obj/item/device/lightreplacer/Topic(href, href_list) - if(..()) return 1 - - if(href_list["eject"]) - switch(href_list["eject"]) - - if("supply") - if(usr) - usr.put_in_hands(supply) - usr.visible_message("[usr] removes \the [supply] from \the [src].", "You remove \the [src]'s supply container, \the [supply].") - else - supply.loc = get_turf(src) - supply = null - if(usr) attack_self(usr) - return 1 - - if("waste") - if(usr) - usr.put_in_hands(waste) - usr.visible_message("[usr] removes \the [waste] from \the [src].", "You remove \the [src]'s waste container, \the [waste].") - else - waste.loc = get_turf(src) - waste = null - if(usr) attack_self(usr) - return 1 - - if(href_list["build"]) - var/light_type = href_list["build"] - var/light_path = text2path("/obj/item/weapon/light/[light_type]") - var/obj/item/weapon/light/L - if(!light_types_glass[light_type]) - L = new light_path - light_types_glass[light_type] = L.starting_materials[MAT_GLASS] - if(!use_glass(light_types_glass[light_type] * prod_eff)) - if(usr) to_chat(usr, "\The [src] doesn't have enough glass to make that!") - if(L) - qdel(L) - L = null - return 1 - if(!L) - L = new light_path - L.switchcount = prod_quality - if(!insert_if_possible(L)) - L.loc = get_turf(src) - if(usr) to_chat(usr, "\The [src] successfully fabricates \a [L], but it drops it on the floor.") - else if(usr) to_chat(usr, "\The [src] successfully fabricates \a [L].") - if(usr) attack_self(usr) - return 1 - - if(href_list["dump"]) - if(!supply) - if(usr) to_chat(usr, "\The [src] doesn't have a supply container!") - return 1 - if(!waste) - if(usr) to_chat(usr, "\The [src] doesn't have a waste container!") - return 1 - var/list/dumplist = text2list(href_list["dump"], ", ") - for(var/lightref in dumplist) - var/obj/item/weapon/light/L = locate(lightref) - if(L.loc == supply) - supply.remove_from_storage(L, waste) - if(usr) attack_self(usr) - return 1 - - if(href_list["swap"]) - var/swapholder = waste - waste = supply - supply = swapholder - if(usr) attack_self(usr) - return 1 - - if(href_list["fold"]) - if(cardboard_stor <= 0) - if(usr) to_chat(usr, "\The [src] is out of cardboard!") - return 1 - switch(href_list["fold"]) - if("supply") - if(!supply) //Topic is technically asynchronous, I believe, so this sanity is a good idea - supply = new(src) - cardboard_stor-- - if(usr) - to_chat(usr, "\The [src] constructs a new supply container.") - attack_self(usr) - return 1 - if("waste") - if(!waste) //Topic is technically asynchronous, I believe, so this sanity is a good idea - waste = new(src) - cardboard_stor-- - if(usr) - to_chat(usr, "\The [src] constructs a new waste container.") - attack_self(usr) - return 1 - -/obj/item/device/lightreplacer/borg/Topic(href, href_list) - if(..()) return 1 - - if(href_list["recycle"]) - if(waste) - var/recycledglass = 0 //How much glass is successfully recycled - for(var/obj/item/weapon/light/L in waste) - if(istype(L)) - switch(L.status) - if(LIGHT_OK) - recycledglass += (L.materials.storage[MAT_GLASS] * recycle_eff_ok) - if(LIGHT_BROKEN) - recycledglass += (L.materials.storage[MAT_GLASS] * recycle_eff_broken) - if(LIGHT_BURNED) - recycledglass += (L.materials.storage[MAT_GLASS] * recycle_eff_burned) - qdel(L) - L = null - add_glass(recycledglass, force_fill = 2) - if(usr) attack_self(usr) - return 1 - - -#undef LIGHT_OK -#undef LIGHT_EMPTY -#undef LIGHT_BROKEN -#undef LIGHT_BURNED + +// Light Replacer (LR) +// +// ABOUT THE DEVICE +// +// This is a device supposedly to be used by Janitors and Janitor Cyborgs which will +// allow them to easily replace lights. This was mostly designed for Janitor Cyborgs since +// they don't have hands or a way to replace lightbulbs. +// +// HOW IT WORKS +// +// You attack a light fixture with it. If the light fixture is broken, it will replace the +// light fixture with a working light. The broken light is then placed into the device's waste box. +// If the fixture is empty then it will just place a light in the fixture. +// +// HOW TO REFILL THE DEVICE +// +// The supply box can be removed and replaced to refill the whole thing at once or lights can be inserted into the device. +// Additionally, it can process glass into any type of light, though it uses much more than other methods of making lights +// and lights made this way start out with a high switchcount. +// +// EMAGGED FEATURES +// +// NOTICE: The Cyborg cannot use the emagged Light Replacer and the light's explosion was nerfed. It cannot create holes in the station anymore. +// +// I'm not sure everyone will react the emag's features so please say what your opinions are of it. +// +// When emagged it will rig every light it replaces, which will explode when the light is on. +// This is VERY noticable, even the device's name changes when you emag it so if anyone +// examines you when you're holding it in your hand, you will be discovered. +// It will also be very obvious who is setting all these lights off, since only Janitor Borgs and Janitors have easy +// access to them, and only one of them can emag their device. +// +// The explosion cannot insta-kill anyone with 30% or more health. + +#define LIGHT_OK 0 +#define LIGHT_EMPTY 1 +#define LIGHT_BROKEN 2 +#define LIGHT_BURNED 3 + + +/obj/item/device/lightreplacer + + name = "light replacer" + desc = "A device to automatically replace lights. Takes lights from a supply box and puts the spent ones in a waste box. It is slotted to accept specifically light bulb/tube boxes." + + icon = 'icons/obj/janitor.dmi' + icon_state = "lightreplacer0" + item_state = "electronic" + + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + origin_tech = "magnets=3;materials=2" + + var/obj/item/weapon/storage/box/lights/supply = null //Takes bulbs from here to replace + var/obj/item/weapon/storage/box/lights/waste = null //Places replaced bulbs here + var/glass_stor = 0 //How much glass it contains for producing lights + var/glass_stor_max = 5 * CC_PER_SHEET_GLASS //Max glass it can hold + var/prod_quality = 30 //Starting switchcount for lights this builds out of glass + var/prod_eff = 10 //How many times more glass it uses to build lights than would an autolathe + var/cardboard_stor //How many sheets of cardboard it contains for quick-assembling boxes + var/cardboard_stor_max = 5 + var/emagged = 0 + var/light_types_glass = list() //An associative list with the starting glass amount for each type of light that is fabricated. + //Populated with a new entry each time a new type of light is made by the replacer for the first time in a given round. + //The key is the part of the typepath after /obj/item/weapon/light/ in string form. The value is its starting glass amount. + +/obj/item/device/lightreplacer/borg //Since it will mainly be loaded by processing glass, it is MUCH better at it than the standard version. + desc = "A device to automatically replace lights. Takes lights from a supply container and puts the spent ones in a waste container. It is fitted with a rudimentary recycling system to recover some glass from the waste lights." + glass_stor_max = 10 * CC_PER_SHEET_GLASS //Twice the capacity of the standard version. It also starts full, but this is done in New(). + prod_quality = 0 //Just as good as lights from a box/autolathe + prod_eff = 5 //Half the glass per light as the standard version + cardboard_stor_max = 0 //No removing or building new boxes for borgs. + var/recycle_eff_broken = 0.5 //Proportion of glass returned by the built-in recycler. + var/recycle_eff_burned = 0.9 //Proportion of glass returned by the built-in recycler. + var/recycle_eff_ok = 1 //Proportion of glass returned by the built-in recycler. Note that this does not allow infinite fabrication and recycling due to production losses. + var/glass_per_charge = 500 //Note: Adjust if the default borg light replacer efficiency is changed. + +/obj/item/device/lightreplacer/loaded/New() //Contains only a waste box. Exists mainly just as a parent of the other loaded ones, but I guess you can use it. + ..() + waste = new(src) + cardboard_stor = cardboard_stor_max //Might as well. + +/obj/item/device/lightreplacer/loaded/mixed/New() //Contains a box of normal mixed lights plus a waste box. + ..() + supply = new /obj/item/weapon/storage/box/lights/mixed(src) + +/obj/item/device/lightreplacer/loaded/he/New() //Contains a box of high-efficiency mixed lights plus a waste box. + ..() + supply = new /obj/item/weapon/storage/box/lights/he(src) + +/obj/item/device/lightreplacer/borg/New() //Contains a box of mixed lights and a waste box and starts full of glass. + ..() + supply = new /obj/item/weapon/storage/box/lights/mixed(src) + waste = new /obj/item/weapon/storage/box/lights(src) + add_glass(glass_stor_max, force_fill = 2) + +/obj/item/device/lightreplacer/examine(mob/user) + ..() + if(supply) + if(supply.contents.len) + to_chat(user, "It has [supply.contents.len] light[supply.contents.len == 1 ? "" : "s"] remaining. Check its interface to see what type[supply.contents.len == 1 ? "" : "s"].") + else + to_chat(user, "Its supply container is empty.") + else + to_chat(user, "It has no supply container.") + + if(waste) + to_chat(user, "Its waste container has [waste.contents.len] slot[waste.contents.len == 1 ? "" : "s"] full.") + else + to_chat(user, "It has no waste container.") + + to_chat(user, "Its glass storage contains [glass_stor] unit[waste.contents.len == 1 ? "" : "s"].") + + +/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/card/emag) && emagged == 0) + Emag() + return + + if(istype(W, /obj/item/stack/sheet/glass/glass)) + if(!add_glass(CC_PER_SHEET_GLASS, force_fill = 1)) + to_chat(user, "\The [src] can't hold any more glass!") + return + var/obj/item/stack/sheet/glass/glass/G = W + G.use(1) + to_chat(user, "You insert \the [G] into \the [src].") + return + + if(istype(W, /obj/item/weapon/light)) + var/obj/item/weapon/light/L = W + switch(insert_if_possible(L)) + if(0) + if(L.status ? istype(waste) : istype(supply)) //The expression returns true if the correct box for the light is valid, which implies that it is full because the insertion failed. + to_chat(user, "\The [src]'s [L.status ? "waste" : "supply"] container is full!") + else + to_chat(user, "\The [src] has no [L.status ? "waste" : "supply"] container!") + if(1) + user.visible_message("[user] inserts \a [L] into \the [src]", "You insert \the [L] into \the [src]'s [L.status ? "waste" : "supply"] container.") + else + to_chat(user, "Something very strange has happened. Please adminhelp and ask someone to view the variables of that light, especially status.") + return + + if(istype(W, /obj/item/weapon/storage/box/lights)) + if(!supply) + if(user.drop_item(W, src)) + user.visible_message("[user] inserts \a [W] into \the [src]", "You insert \the [W] into \the [src] to be used as the supply container.") + supply = W + return + else if(!waste) + if(user.drop_item(W, src)) + user.visible_message("[user] inserts \a [W] into \the [src]", "You insert \the [W] into \the [src] to be used as the waste container.") + waste = W + return + else + var/obj/item/weapon/storage/box/lights/lsource = W + if(!lsource.contents.len) + to_chat(user, "\The [src] has both a supply box and a waste box and this box is empty. Remove one first if you want to insert a new one or use a light box with lights in it to insert them.") + return + var/hasinserted = 0 + for(var/obj/item/weapon/light/L in lsource) + if(insert_if_possible(L)) + hasinserted = 1 + if(hasinserted) + to_chat(user, "\The [src] accepts the lights in \the [lsource].") + else + to_chat(user, "\The [src] cannot accept any of the lights in \the [lsource]!") + return + + if(istype(W, /obj/item/stack/sheet/cardboard)) + if(cardboard_stor >= cardboard_stor_max) + to_chat(user, "\The [src] cannot hold any more cardboard!") + return + var/obj/item/stack/sheet/cardboard/C = W + cardboard_stor++ + C.use(1) + to_chat(user, "You insert a cardboard sheet into \the [src].") + return + +/obj/item/device/lightreplacer/attack_self(mob/user) + var/dat = {"Light Replacer Interface + + Glass storage: [glass_stor]/[glass_stor_max]
    Cardboard Sheets: [cardboard_stor]/[cardboard_stor_max]
    "} + + if(supply) + dat += {"Fabricate Tube + Fabricate Bulb + + + +

    Supply Container:

    "} //It's not clear here, but the argument to build is the part of the typepath after /obj/item/weapon/light/ + var/list/light_types = new() + var/lightname + for(var/obj/item/weapon/light/L in supply) + lightname = "" + if(L.status == LIGHT_BROKEN) + lightname += "broken " + else if(L.status == LIGHT_BURNED) + lightname += "burned-out " + lightname += L.name + if(!light_types[lightname]) + light_types[lightname] = list() + light_types[lightname] += L + + var/list/light_type_cur + var/list/to_dump_5 //I guess I could do this without this variable, but it would involve more string concatenation, and nobody wants that. + var/list/to_dump_all//This too + + for(var/T in light_types) + light_type_cur = light_types[T] //The way you'd expect to be the good way to do this doesn't work. This is dumb, but necessary. + to_dump_5 = list() + to_dump_all = list() + for(var/light_to_ref in light_type_cur) + to_dump_all += "\ref[light_to_ref]" + to_dump_5 = to_dump_all.Copy(1, min(6, to_dump_all.len + 1)) + dat += "
    [T]: [light_type_cur.len] | Dump to Waste: 15All" + + dat += "
    Eject Supply Container" + + else + dat += "

    No supply container inserted


    Construct Supply Box" + + if(supply || waste) + dat += "

    Swap Supply and Waste Containers" + + if(waste) + dat += {"


    Waste Container:

    + + Filled: [waste.contents.len]/[waste.storage_slots]
    + Eject Waste Container + "} + else + dat += "


    No waste container inserted


    Construct Waste Box" + + var/datum/browser/popup = new(user, "lightreplacer", "", nref = src) + popup.set_content(dat) + popup.open() + +/obj/item/device/lightreplacer/borg/attack_self(mob/user) //The menu must be different to accomodate the differences necessary for the borg version. + /* // This would probably be a bit OP. If you want it though, uncomment the code. + if(isrobot(user)) + var/mob/living/silicon/robot/R = user + if(R.emagged) + src.Emag() + to_chat(usr, "You shortcircuit the [src].") + return + */ + + var/dat = {"Light Replacer Interface + + Glass storage: [glass_stor]/[glass_stor_max]
    "} + + if(supply) + dat += {"Fabricate Tube + Fabricate Bulb + Fabricate High Efficiency Tube + Fabricate High Efficiency Bulb + + + +

    Supply Container:

    "} + var/list/light_types = new() + var/lightname + for(var/obj/item/weapon/light/L in supply) + lightname = "" + if(L.status == LIGHT_BROKEN) + lightname += "broken " + else if(L.status == LIGHT_BURNED) + lightname += "burned-out " + lightname += L.name + if(!light_types[lightname]) + light_types[lightname] = list() + light_types[lightname] += L + + var/list/light_type_cur + var/list/to_dump_5//I guess I could do this without this variable, but it would include more string concatenation, and nobody wants that. + var/list/to_dump_all //This too + + for(var/T in light_types) + to_dump_5 = list() + to_dump_all = list() + light_type_cur = light_types[T] //The way you'd expect to be the good way to do this doesn't work. This is dumb, but necessary. + for(var/light_to_ref in light_type_cur) + to_dump_all += "\ref[light_to_ref]" + to_dump_5 = to_dump_all.Copy(1, min(6, to_dump_all.len + 1)) + dat += "
    [T]: [light_type_cur.len] | Dump to Waste: 15All" + + else + dat += "

    No supply container inserted. This should be impossible. Please ahelp this.

    " + + if(supply || waste) + dat += "

    Swap Supply and Waste Containers" + + if(waste) + dat += {"


    Waste Container:

    + + Filled: [waste.contents.len]/[waste.storage_slots]
    + Recycle Contents + "} + else + dat += "


    No waste container inserted. This should be impossible. Please ahelp this.

    " + + var/datum/browser/popup = new(user, "lightreplacer", "", nref = src) + popup.set_content(dat) + popup.open() + +/obj/item/device/lightreplacer/update_icon() + icon_state = "lightreplacer[emagged]" + + +/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/user) + var/obj/item/weapon/light/best_light = get_best_light(target) + if(best_light == 0) + to_chat(user, "\The [src] has no supply container!") + return + else if(!best_light) + to_chat(user, "\The [src] has no compatible light!") + return + if(!is_light_better(best_light, target)) + to_chat(user, "\The [src] has no light better than the one already in \the [target].") + return + + + to_chat(user, "You replace the [target.fitting] with \the [src].") + playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + + supply.remove_from_storage(best_light) + + if(target.status != LIGHT_EMPTY) + var/obj/item/weapon/light/L1 = new target.light_type(target.loc) + L1.status = target.status + L1.rigged = target.rigged + L1.brightness_range = target.brightness_range + L1.brightness_power = target.brightness_power + L1.brightness_color = target.brightness_color + L1.cost = target.cost + L1.base_state = target.base_state + L1.switchcount = target.switchcount + target.switchcount = 0 + L1.update() + target.status = LIGHT_EMPTY + target.update() + if(!insert_if_possible(L1)) + if(istype(waste)) + to_chat(user, "\The [src]'s waste container is full and it drops the removed light on the floor!") + else + to_chat(user, "\The [src] has no waste container and it drops the removed light on the floor!") + + target.status = best_light.status + target.switchcount = best_light.switchcount + target.rigged = emagged || best_light.rigged + target.brightness_range = best_light.brightness_range + target.brightness_power = best_light.brightness_power + target.brightness_color = best_light.brightness_color + target.cost = best_light.cost + target.base_state = best_light.base_state + target.light_type = best_light.type + target.on = target.has_power() + target.update() + qdel(best_light) + best_light = null + if(target.on && target.rigged) + target.explode() + + +/obj/item/device/lightreplacer/proc/Emag() + emagged = !emagged + playsound(get_turf(src), "sparks", 100, 1) + if(emagged) + name = "Shortcircuited [initial(name)]" + else + name = initial(name) + update_icon() + + +//Attempts to insert a light into the light replacer's storage. +//If the light works, attempts to place it in the supply box. Otherwise, attempts to place it in the waste box. +//Fails if the light cannot be placed into the correct box for any reason. +//Returns 1 if the light is successfully inserted into the correct box, 0 if the insertion fails, and null if the item to be inserted is not a light or something very strange happens. +/obj/item/device/lightreplacer/proc/insert_if_possible(var/obj/item/weapon/light/L) + if(!istype(L)) + return + if(L.status == LIGHT_OK) + if(supply && supply.can_be_inserted(L, TRUE)) + if(istype(L.loc, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/lsource = L.loc + lsource.remove_from_storage(L, supply) + else + supply.handle_item_insertion(L, TRUE) + return 1 + else + return 0 + else if(L.status == LIGHT_BROKEN || L.status == LIGHT_BURNED) + if(waste && waste.can_be_inserted(L, TRUE)) + if(istype(L.loc, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/lsource = L.loc + lsource.remove_from_storage(L, waste) + else + waste.handle_item_insertion(L, TRUE) + return 1 + else + return 0 + +//Returns the best light currently in the supply container that is compatible with target. +//For the standard light replacer, it just prioritizes HE lights over standard lights. I may add an advanced replacer with better light selection later. +//Returns null if no compatible bulb is found and 0 if the light replacer has no (valid) supply box. +/obj/item/device/lightreplacer/proc/get_best_light(var/obj/machinery/light/target) + if(!istype(supply)) + return 0 + var/best_light + switch(target.fitting) + if("bulb") + best_light = (locate(/obj/item/weapon/light/bulb/he) in supply) || (locate(/obj/item/weapon/light/bulb) in supply) + if("tube") + best_light = (locate(/obj/item/weapon/light/tube/he) in supply) || (locate(/obj/item/weapon/light/tube) in supply) + if("large tube") + best_light = locate(/obj/item/weapon/light/tube/large) in supply + return best_light + +//Returns 1 if the first argument is considered better, 0 if the second is better or they are equal, and null if either argument is invalid. +//To be valid, each argument must be an instance of either /obj/item/weapon/light or /obj/machinery/light. +//Again, standard replacer just checks as follows: +//HE light < standard light < no light < broken light = burned-out light +//In normal operation, tested should never be no light and very rarely be a broken light. +/obj/item/device/lightreplacer/proc/is_light_better(var/obj/tested, var/obj/comparison) + if(!(istype(tested, /obj/item/weapon/light) || istype(tested, /obj/machinery/light)) || !(istype(comparison, /obj/item/weapon/light) || istype(comparison, /obj/machinery/light))) + return + if(tested:status >= LIGHT_BROKEN) //Is tested broken or burnt out? If so, it cannot win. + return 0 + if(tested:status < comparison:status) //Is tested closer to functional than comparison? If so, it wins. + return 1 + if(tested:status) //Is tested empty? If so, either it must be a tie or comparison wins, so tested cannot win. + return 0 + + //Now we know both work, so all that is left is to test if tested wins by being HE. + if(findtextEx(tested:base_state, "he", 1, 3) && !findtextEx(comparison:base_state, "he", 1, 3)) + return 1 + else + return 0 + +//Can you use it? +//This used to actually check if it wasn't empty, but that's handled in ReplaceLight() now. + +/obj/item/device/lightreplacer/proc/CanUse(var/mob/living/user) + src.add_fingerprint(user) + //Not sure what else to check for. Maybe if clumsy? + return 1 + +/obj/item/device/lightreplacer/borg/proc/Charge(var/mob/user) + add_glass(glass_per_charge, force_fill = 2) + +//Adds amt glass to the glass storage if possible. +//If force_fill is 0, fails if there is not enough room for all of amt. +//If force_fill is 1, fails only if amt is totally full. +//If force_fill is 2, never fails. +//Returns 1 on success and 0 on fail. +/obj/item/device/lightreplacer/proc/add_glass(var/amt, var/force_fill = 0) + if(!force_fill) + if(glass_stor + amt > glass_stor_max) + return 0 + else if(force_fill == 1) + if(glass_stor >= glass_stor_max) + return 0 + glass_stor = min(glass_stor_max, glass_stor + amt) + return 1 + +//Attempts to use amt glass from storage. Returns 1 on success and 0 on failure. +/obj/item/device/lightreplacer/proc/use_glass(var/amt) + if(amt > glass_stor) + return 0 + glass_stor -= amt + return 1 + +/obj/item/device/lightreplacer/Topic(href, href_list) + if(..()) return 1 + + if(href_list["eject"]) + switch(href_list["eject"]) + + if("supply") + if(usr) + usr.put_in_hands(supply) + usr.visible_message("[usr] removes \the [supply] from \the [src].", "You remove \the [src]'s supply container, \the [supply].") + else + supply.loc = get_turf(src) + supply = null + if(usr) attack_self(usr) + return 1 + + if("waste") + if(usr) + usr.put_in_hands(waste) + usr.visible_message("[usr] removes \the [waste] from \the [src].", "You remove \the [src]'s waste container, \the [waste].") + else + waste.loc = get_turf(src) + waste = null + if(usr) attack_self(usr) + return 1 + + if(href_list["build"]) + var/light_type = href_list["build"] + var/light_path = text2path("/obj/item/weapon/light/[light_type]") + var/obj/item/weapon/light/L + if(!light_types_glass[light_type]) + L = new light_path + light_types_glass[light_type] = L.starting_materials[MAT_GLASS] + if(!use_glass(light_types_glass[light_type] * prod_eff)) + if(usr) to_chat(usr, "\The [src] doesn't have enough glass to make that!") + if(L) + qdel(L) + L = null + return 1 + if(!L) + L = new light_path + L.switchcount = prod_quality + if(!insert_if_possible(L)) + L.loc = get_turf(src) + if(usr) to_chat(usr, "\The [src] successfully fabricates \a [L], but it drops it on the floor.") + else if(usr) to_chat(usr, "\The [src] successfully fabricates \a [L].") + if(usr) attack_self(usr) + return 1 + + if(href_list["dump"]) + if(!supply) + if(usr) to_chat(usr, "\The [src] doesn't have a supply container!") + return 1 + if(!waste) + if(usr) to_chat(usr, "\The [src] doesn't have a waste container!") + return 1 + var/list/dumplist = text2list(href_list["dump"], ", ") + for(var/lightref in dumplist) + var/obj/item/weapon/light/L = locate(lightref) + if(L.loc == supply) + supply.remove_from_storage(L, waste) + if(usr) attack_self(usr) + return 1 + + if(href_list["swap"]) + var/swapholder = waste + waste = supply + supply = swapholder + if(usr) attack_self(usr) + return 1 + + if(href_list["fold"]) + if(cardboard_stor <= 0) + if(usr) to_chat(usr, "\The [src] is out of cardboard!") + return 1 + switch(href_list["fold"]) + if("supply") + if(!supply) //Topic is technically asynchronous, I believe, so this sanity is a good idea + supply = new(src) + cardboard_stor-- + if(usr) + to_chat(usr, "\The [src] constructs a new supply container.") + attack_self(usr) + return 1 + if("waste") + if(!waste) //Topic is technically asynchronous, I believe, so this sanity is a good idea + waste = new(src) + cardboard_stor-- + if(usr) + to_chat(usr, "\The [src] constructs a new waste container.") + attack_self(usr) + return 1 + +/obj/item/device/lightreplacer/borg/Topic(href, href_list) + if(..()) return 1 + + if(href_list["recycle"]) + if(waste) + var/recycledglass = 0 //How much glass is successfully recycled + for(var/obj/item/weapon/light/L in waste) + if(istype(L)) + switch(L.status) + if(LIGHT_OK) + recycledglass += (L.materials.storage[MAT_GLASS] * recycle_eff_ok) + if(LIGHT_BROKEN) + recycledglass += (L.materials.storage[MAT_GLASS] * recycle_eff_broken) + if(LIGHT_BURNED) + recycledglass += (L.materials.storage[MAT_GLASS] * recycle_eff_burned) + qdel(L) + L = null + add_glass(recycledglass, force_fill = 2) + if(usr) attack_self(usr) + return 1 + + +#undef LIGHT_OK +#undef LIGHT_EMPTY +#undef LIGHT_BROKEN +#undef LIGHT_BURNED diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 52aa2780246..c9b6144f2ec 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -1,140 +1,140 @@ -// Multitool -- A multitool is used for hacking electronic devices. - -#define DETECT_TICKER_PERIOD 10 //in deciseconds -#define DETECT_AI 1 -#define DETECT_PAI 2 -#define DETECT_RECORDER 4 -#define DETECT_ANALYZER 8 - - ////////////////////////////////////////////////////////// - -/obj/item/device/multitool - name = "multitool" - desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." - icon_state = "multitool" - flags = FPRINT - siemens_coefficient = 1 - force = 5.0 - w_class = 2.0 - throwforce = 5.0 - throw_range = 15 - throw_speed = 3 - starting_materials = list(MAT_IRON = 50, MAT_GLASS = 20) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_SILICON - origin_tech = "magnets=1;engineering=1" - // VG: We dun changed dis so we can link simple machines. - N3X - var/obj/machinery/buffer // simple machine buffer for device linkage - var/clone = 0 // If this is on cloning will happen, this is handled in machinery code. - -/obj/item/device/multitool/proc/IsBufferA(var/typepath) - if(!buffer) - return 0 - return istype(buffer,typepath) - -/obj/item/device/multitool/attack_self(var/mob/user) - if(!buffer && !clone) // Can't enable cloning without buffer. - return - - clone = !clone - if(clone) +// Multitool -- A multitool is used for hacking electronic devices. + +#define DETECT_TICKER_PERIOD 10 //in deciseconds +#define DETECT_AI 1 +#define DETECT_PAI 2 +#define DETECT_RECORDER 4 +#define DETECT_ANALYZER 8 + + ////////////////////////////////////////////////////////// + +/obj/item/device/multitool + name = "multitool" + desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." + icon_state = "multitool" + flags = FPRINT + siemens_coefficient = 1 + force = 5.0 + w_class = 2.0 + throwforce = 5.0 + throw_range = 15 + throw_speed = 3 + starting_materials = list(MAT_IRON = 50, MAT_GLASS = 20) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_SILICON + origin_tech = "magnets=1;engineering=1" + // VG: We dun changed dis so we can link simple machines. - N3X + var/obj/machinery/buffer // simple machine buffer for device linkage + var/clone = 0 // If this is on cloning will happen, this is handled in machinery code. + +/obj/item/device/multitool/proc/IsBufferA(var/typepath) + if(!buffer) + return 0 + return istype(buffer,typepath) + +/obj/item/device/multitool/attack_self(var/mob/user) + if(!buffer && !clone) // Can't enable cloning without buffer. + return + + clone = !clone + if(clone) to_chat(user, "You enable cloning on \the [src].") - else + else to_chat(user, "You disable cloning on \the [src].") - -/obj/item/device/multitool/examine(var/mob/user) - . = ..() + +/obj/item/device/multitool/examine(var/mob/user) + . = ..() to_chat(user, "Cloning is [clone ? "enabled" : "disabled"].") - -///////////////////////// -//Disguised AI detector// - changes color based on proximity to various surveillance devices -///////////////////////// - -/obj/item/device/multitool/ai_detect - var/detected = 0 //bitflags - -/obj/item/device/multitool/ai_detect/New() - spawn() src.ticker() - -/obj/item/device/multitool/ai_detect/proc/ticker() - var/mob/M - var/range - var/turf/our_turf - var/turf/T - while(src && !src.gcDestroyed) - detected = 0 - our_turf = get_turf(src) - range = range(8,our_turf) - - //Search for AIs and people looking through sec cams - if(cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) - var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) - if(chunk && chunk.seenby.len) - for(M in chunk.seenby) - if(get_dist(src,M) < 8) - src.detected |= DETECT_AI - break - - for(T in range) //Search for pAIs - if(src.findItem(/mob/living/silicon/pai,T)) - src.detected |= DETECT_PAI - break - - for(T in range) //Search for recorders - if(src.findItem(/obj/item/device/taperecorder,T)) - src.detected |= DETECT_RECORDER - break - - for(T in range) //Search for analyzers - if(src.findComponent(/obj/item/device/assembly/voice,T)) - src.detected |= DETECT_ANALYZER - break - - src.update_icon() - sleep(DETECT_TICKER_PERIOD) - return - -/obj/item/device/multitool/ai_detect/proc/findItem(pathToFind,atom/thingToSearch) - if(locate(pathToFind) in thingToSearch.contents) return 1 - for(var/mob/living/carbon/mob in thingToSearch) - if(.(pathToFind,mob)) return 1 - return 0 - -/obj/item/device/multitool/ai_detect/proc/findComponent(pathToFind,atom/thingToSearch) - if(locate(pathToFind) in thingToSearch.contents) return 1 - for(var/obj/item/device/assembly_holder/assembly in thingToSearch) - if(.(pathToFind,assembly)) return 1 - for(var/obj/item/device/transfer_valve/valve in thingToSearch) - if(.(pathToFind,valve)) return 1 - for(var/mob/living/carbon/mob in thingToSearch) - if(.(pathToFind,mob)) return 1 - return 0 - -obj/item/device/multitool/ai_detect/update_icon() - if(src.detected) - if(src.detected & DETECT_AI) - src.icon_state = "[initial(src.icon_state)]_red" - else if(src.detected & DETECT_PAI) - src.icon_state = "[initial(src.icon_state)]_orange" - else if(src.detected & DETECT_RECORDER) - src.icon_state = "[initial(src.icon_state)]_yellow" - else if(src.detected & DETECT_ANALYZER) - src.icon_state = "[initial(src.icon_state)]_blue" - else src.icon_state = initial(src.icon_state) - return - -obj/item/device/multitool/ai_detect/examine(mob/user) - ..() - if(src.detected) - user << "The screen displays:" - if(DETECT_AI) to_chat(user, "AI detected") - if(DETECT_PAI) to_chat(user, "pAI detected>") - if(DETECT_RECORDER) to_chat(user, "Tape recorder detected") - if(DETECT_ANALYZER) to_chat(user, "Voice analyzer detected") - -//////////////////////////////////////////////////////////////////////// -#undef DETECT_TICKER_PERIOD -#undef DETECT_AI -#undef DETECT_PAI -#undef DETECT_RECORDER -#undef DETECT_ANALYZER + +///////////////////////// +//Disguised AI detector// - changes color based on proximity to various surveillance devices +///////////////////////// + +/obj/item/device/multitool/ai_detect + var/detected = 0 //bitflags + +/obj/item/device/multitool/ai_detect/New() + spawn() src.ticker() + +/obj/item/device/multitool/ai_detect/proc/ticker() + var/mob/M + var/range + var/turf/our_turf + var/turf/T + while(src && !src.gcDestroyed) + detected = 0 + our_turf = get_turf(src) + range = range(8,our_turf) + + //Search for AIs and people looking through sec cams + if(cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) + var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) + if(chunk && chunk.seenby.len) + for(M in chunk.seenby) + if(get_dist(src,M) < 8) + src.detected |= DETECT_AI + break + + for(T in range) //Search for pAIs + if(src.findItem(/mob/living/silicon/pai,T)) + src.detected |= DETECT_PAI + break + + for(T in range) //Search for recorders + if(src.findItem(/obj/item/device/taperecorder,T)) + src.detected |= DETECT_RECORDER + break + + for(T in range) //Search for analyzers + if(src.findComponent(/obj/item/device/assembly/voice,T)) + src.detected |= DETECT_ANALYZER + break + + src.update_icon() + sleep(DETECT_TICKER_PERIOD) + return + +/obj/item/device/multitool/ai_detect/proc/findItem(pathToFind,atom/thingToSearch) + if(locate(pathToFind) in thingToSearch.contents) return 1 + for(var/mob/living/carbon/mob in thingToSearch) + if(.(pathToFind,mob)) return 1 + return 0 + +/obj/item/device/multitool/ai_detect/proc/findComponent(pathToFind,atom/thingToSearch) + if(locate(pathToFind) in thingToSearch.contents) return 1 + for(var/obj/item/device/assembly_holder/assembly in thingToSearch) + if(.(pathToFind,assembly)) return 1 + for(var/obj/item/device/transfer_valve/valve in thingToSearch) + if(.(pathToFind,valve)) return 1 + for(var/mob/living/carbon/mob in thingToSearch) + if(.(pathToFind,mob)) return 1 + return 0 + +obj/item/device/multitool/ai_detect/update_icon() + if(src.detected) + if(src.detected & DETECT_AI) + src.icon_state = "[initial(src.icon_state)]_red" + else if(src.detected & DETECT_PAI) + src.icon_state = "[initial(src.icon_state)]_orange" + else if(src.detected & DETECT_RECORDER) + src.icon_state = "[initial(src.icon_state)]_yellow" + else if(src.detected & DETECT_ANALYZER) + src.icon_state = "[initial(src.icon_state)]_blue" + else src.icon_state = initial(src.icon_state) + return + +obj/item/device/multitool/ai_detect/examine(mob/user) + ..() + if(src.detected) + user << "The screen displays:" + if(DETECT_AI) to_chat(user, "AI detected") + if(DETECT_PAI) to_chat(user, "pAI detected>") + if(DETECT_RECORDER) to_chat(user, "Tape recorder detected") + if(DETECT_ANALYZER) to_chat(user, "Voice analyzer detected") + +//////////////////////////////////////////////////////////////////////// +#undef DETECT_TICKER_PERIOD +#undef DETECT_AI +#undef DETECT_PAI +#undef DETECT_RECORDER +#undef DETECT_ANALYZER diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index c3747f99691..1bad5722ba9 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -1,164 +1,164 @@ -/obj/item/device/paicard - name = "personal AI device" - icon = 'icons/obj/pda.dmi' - icon_state = "pai" - item_state = "electronic" - w_class = 2.0 - flags = FPRINT - slot_flags = SLOT_BELT - origin_tech = "programming=2" - var/looking_for_personality = 0 - var/mob/living/silicon/pai/pai - -/obj/item/device/paicard/New() - ..() - overlays += "pai-off" - -#ifdef DEBUG_ROLESELECT -/obj/item/device/paicard/test/New() - src.looking_for_personality = 1 - paiController.findPAI(src, usr) -#endif - -/obj/item/device/paicard/Destroy() - //Will stop people throwing friend pAIs into the singularity so they can respawn - if(!isnull(pai)) - pai.death(0) - ..() - -/obj/item/device/paicard/attack_self(mob/user) - 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
    " - if(pai) - - dat += {"Installed Personality: [pai.name]
    - Prime directive:
    [pai.pai_law0]
    - Additional directives:
    [pai.pai_laws]
    - Configure Directives
    -
    -

    Device Settings


    "} - if(pai.radio) - dat += "Radio Uplink
    " - dat += "Transmit: [(pai.radio.wires.IsIndexCut(WIRE_TRANSMIT)) ? "Disabled" : "Enabled"]
    " - dat += "Receive: [(pai.radio.wires.IsIndexCut(WIRE_RECEIVE)) ? "Disabled" : "Enabled"]
    " - else - - dat += {"Radio Uplink
    - Radio firmware not loaded. Please install a pAI personality to load firmware.
    "} - dat += "\[Wipe current pAI personality\]
    " - else - if(looking_for_personality) - - dat += {"Searching for a personality... - \[View available personalities\]
    "} - else - - dat += {"No personality is installed.
    - \[Request personal AI personality\]
    - 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."} - user << browse(dat, "window=paicard") - onclose(user, "paicard") - return - -/obj/item/device/paicard/attack_ghost(var/mob/dead/observer/O) - if(looking_for_personality&&paiController.check_recruit(O)) - paiController.recruitWindow(O) - else - visible_message("\The [src] pings softly.") - -/obj/item/device/paicard/Topic(href, href_list) - - if(!usr || usr.stat) - return - - if(href_list["setdna"]) - if(pai.master_dna) - return - var/mob/M = usr - if(!istype(M, /mob/living/carbon)) - to_chat(usr, "You don't have any DNA, or your DNA is incompatible with this device.") - else - var/datum/dna/dna = usr.dna - pai.master = M.real_name - pai.master_dna = dna.unique_enzymes - to_chat(pai, "

    You have been bound to a new master.

    ") - if(href_list["request"]) - src.looking_for_personality = 1 - paiController.findPAI(src, usr) - if(href_list["wipe"]) - var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No") - if(confirm == "Yes") - for(var/mob/M in src) - to_chat(M, "

    You feel yourself slipping away from reality.

    ") - to_chat(M, "

    Byte by byte you lose your sense of self.

    ") - to_chat(M, "

    Your mental faculties leave you.

    ") - to_chat(M, "
    oblivion...
    ") - M.death(0) - removePersonality() - if(href_list["wires"]) - var/t1 = text2num(href_list["wires"]) - if(pai.radio) - pai.radio.wires.CutWireIndex(t1) - if(href_list["setlaws"]) - var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.pai_laws) as message),1,MAX_MESSAGE_LEN) - if(newlaws) - pai.pai_laws = newlaws - to_chat(pai, "Your supplemental directives have been updated. Your new directives are:") - to_chat(pai, "Prime Directive :
    [pai.pai_law0]") - to_chat(pai, "Supplemental Directives:
    [pai.pai_laws]") - attack_self(usr) - -// WIRE_SIGNAL = 1 -// WIRE_RECEIVE = 2 -// WIRE_TRANSMIT = 4 - -/obj/item/device/paicard/proc/setPersonality(mob/living/silicon/pai/personality) - src.pai = personality - src.overlays += "pai-happy" - -/obj/item/device/paicard/proc/removePersonality() - src.pai = null - src.overlays.len = 0 - src.overlays += "pai-off" - -/obj/item/device/paicard/proc/setEmotion(var/emotion) - if(pai) - var/face = "pai-happy" - src.overlays.len = 0 - pai.overlays.len = 0 - switch(emotion) - if(1) face = "pai-happy" - if(2) face = "pai-cat" - if(3) face = "pai-extremely-happy" - if(4) face = "pai-face" - if(5) face = "pai-laugh" - if(6) face = "pai-off" - if(7) face = "pai-sad" - if(8) face = "pai-angry" - if(9) face = "pai-what" - if(10) face = "pai-longface" - if(11) face = "pai-sick" - if(12) face = "pai-high" - if(13) face = "pai-love" - if(14) face = "pai-electric" - if(15) face = "pai-pissed" - if(16) face = "pai-nose" - if(17) face = "pai-kawaii" - if(18) face = "pai-cry" - src.overlays += "[face]" - pai.overlays += "[face]"//we also update the mob's overlay so it appears properly on the scoreboard. - -/obj/item/device/paicard/proc/alertUpdate() - var/turf/T = get_turf(src.loc) - for (var/mob/M in viewers(T)) - M.show_message("[src] flashes a message across its screen, \"Additional personalities available for download.\"", 1, "[src] bleeps electronically.", 2) - playsound(loc, 'sound/machines/paistartup.ogg', 50, 1) - -/obj/item/device/paicard/emp_act(severity) - for(var/mob/M in src) - M.emp_act(severity) - ..() +/obj/item/device/paicard + name = "personal AI device" + icon = 'icons/obj/pda.dmi' + icon_state = "pai" + item_state = "electronic" + w_class = 2.0 + flags = FPRINT + slot_flags = SLOT_BELT + origin_tech = "programming=2" + var/looking_for_personality = 0 + var/mob/living/silicon/pai/pai + +/obj/item/device/paicard/New() + ..() + overlays += "pai-off" + +#ifdef DEBUG_ROLESELECT +/obj/item/device/paicard/test/New() + src.looking_for_personality = 1 + paiController.findPAI(src, usr) +#endif + +/obj/item/device/paicard/Destroy() + //Will stop people throwing friend pAIs into the singularity so they can respawn + if(!isnull(pai)) + pai.death(0) + ..() + +/obj/item/device/paicard/attack_self(mob/user) + 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
    " + if(pai) + + dat += {"Installed Personality: [pai.name]
    + Prime directive:
    [pai.pai_law0]
    + Additional directives:
    [pai.pai_laws]
    + Configure Directives
    +
    +

    Device Settings


    "} + if(pai.radio) + dat += "Radio Uplink
    " + dat += "Transmit: [(pai.radio.wires.IsIndexCut(WIRE_TRANSMIT)) ? "Disabled" : "Enabled"]
    " + dat += "Receive: [(pai.radio.wires.IsIndexCut(WIRE_RECEIVE)) ? "Disabled" : "Enabled"]
    " + else + + dat += {"Radio Uplink
    + Radio firmware not loaded. Please install a pAI personality to load firmware.
    "} + dat += "\[Wipe current pAI personality\]
    " + else + if(looking_for_personality) + + dat += {"Searching for a personality... + \[View available personalities\]
    "} + else + + dat += {"No personality is installed.
    + \[Request personal AI personality\]
    + 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."} + user << browse(dat, "window=paicard") + onclose(user, "paicard") + return + +/obj/item/device/paicard/attack_ghost(var/mob/dead/observer/O) + if(looking_for_personality&&paiController.check_recruit(O)) + paiController.recruitWindow(O) + else + visible_message("\The [src] pings softly.") + +/obj/item/device/paicard/Topic(href, href_list) + + if(!usr || usr.stat) + return + + if(href_list["setdna"]) + if(pai.master_dna) + return + var/mob/M = usr + if(!istype(M, /mob/living/carbon)) + to_chat(usr, "You don't have any DNA, or your DNA is incompatible with this device.") + else + var/datum/dna/dna = usr.dna + pai.master = M.real_name + pai.master_dna = dna.unique_enzymes + to_chat(pai, "

    You have been bound to a new master.

    ") + if(href_list["request"]) + src.looking_for_personality = 1 + paiController.findPAI(src, usr) + if(href_list["wipe"]) + var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No") + if(confirm == "Yes") + for(var/mob/M in src) + to_chat(M, "

    You feel yourself slipping away from reality.

    ") + to_chat(M, "

    Byte by byte you lose your sense of self.

    ") + to_chat(M, "

    Your mental faculties leave you.

    ") + to_chat(M, "
    oblivion...
    ") + M.death(0) + removePersonality() + if(href_list["wires"]) + var/t1 = text2num(href_list["wires"]) + if(pai.radio) + pai.radio.wires.CutWireIndex(t1) + if(href_list["setlaws"]) + var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.pai_laws) as message),1,MAX_MESSAGE_LEN) + if(newlaws) + pai.pai_laws = newlaws + to_chat(pai, "Your supplemental directives have been updated. Your new directives are:") + to_chat(pai, "Prime Directive :
    [pai.pai_law0]") + to_chat(pai, "Supplemental Directives:
    [pai.pai_laws]") + attack_self(usr) + +// WIRE_SIGNAL = 1 +// WIRE_RECEIVE = 2 +// WIRE_TRANSMIT = 4 + +/obj/item/device/paicard/proc/setPersonality(mob/living/silicon/pai/personality) + src.pai = personality + src.overlays += "pai-happy" + +/obj/item/device/paicard/proc/removePersonality() + src.pai = null + src.overlays.len = 0 + src.overlays += "pai-off" + +/obj/item/device/paicard/proc/setEmotion(var/emotion) + if(pai) + var/face = "pai-happy" + src.overlays.len = 0 + pai.overlays.len = 0 + switch(emotion) + if(1) face = "pai-happy" + if(2) face = "pai-cat" + if(3) face = "pai-extremely-happy" + if(4) face = "pai-face" + if(5) face = "pai-laugh" + if(6) face = "pai-off" + if(7) face = "pai-sad" + if(8) face = "pai-angry" + if(9) face = "pai-what" + if(10) face = "pai-longface" + if(11) face = "pai-sick" + if(12) face = "pai-high" + if(13) face = "pai-love" + if(14) face = "pai-electric" + if(15) face = "pai-pissed" + if(16) face = "pai-nose" + if(17) face = "pai-kawaii" + if(18) face = "pai-cry" + src.overlays += "[face]" + pai.overlays += "[face]"//we also update the mob's overlay so it appears properly on the scoreboard. + +/obj/item/device/paicard/proc/alertUpdate() + var/turf/T = get_turf(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("[src] flashes a message across its screen, \"Additional personalities available for download.\"", 1, "[src] bleeps electronically.", 2) + playsound(loc, 'sound/machines/paistartup.ogg', 50, 1) + +/obj/item/device/paicard/emp_act(severity) + for(var/mob/M in src) + M.emp_act(severity) + ..() diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index fb974204bbe..c5ba2b1fe97 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -1,134 +1,134 @@ -// Powersink - used to drain station power - -/obj/item/device/powersink - desc = "A nulling power sink which drains energy from electrical systems." - name = "power sink" - icon_state = "powersink0" - item_state = "electronic" - w_class = 4.0 - flags = FPRINT - siemens_coefficient = 1 - throwforce = 5 - throw_speed = 1 - throw_range = 2 - starting_materials = list(MAT_IRON = 750) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_STEEL - origin_tech = "powerstorage=3;syndicate=5" - var/drain_rate = 600000 // amount of power to drain per tick - var/power_drained = 0 // has drained this much power - var/max_power = 1e8 // maximum power that can be drained before exploding - var/mode = 0 // 0 = off, 1=clamped (off), 2=operating - - - var/obj/structure/cable/attached // the attached cable - - attackby(var/obj/item/I, var/mob/user) - if(istype(I, /obj/item/weapon/screwdriver)) - if(mode == 0) - var/turf/T = loc - if(isturf(T) && !T.intact) - attached = locate() in T - if(!attached) +// Powersink - used to drain station power + +/obj/item/device/powersink + desc = "A nulling power sink which drains energy from electrical systems." + name = "power sink" + icon_state = "powersink0" + item_state = "electronic" + w_class = 4.0 + flags = FPRINT + siemens_coefficient = 1 + throwforce = 5 + throw_speed = 1 + throw_range = 2 + starting_materials = list(MAT_IRON = 750) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_STEEL + origin_tech = "powerstorage=3;syndicate=5" + var/drain_rate = 600000 // amount of power to drain per tick + var/power_drained = 0 // has drained this much power + var/max_power = 1e8 // maximum power that can be drained before exploding + var/mode = 0 // 0 = off, 1=clamped (off), 2=operating + + + var/obj/structure/cable/attached // the attached cable + + attackby(var/obj/item/I, var/mob/user) + if(istype(I, /obj/item/weapon/screwdriver)) + if(mode == 0) + var/turf/T = loc + if(isturf(T) && !T.intact) + attached = locate() in T + if(!attached) to_chat(user, "No exposed cable here to attach to.") - return - else - attached.attached = src - anchored = 1 - mode = 1 + return + else + attached.attached = src + anchored = 1 + mode = 1 to_chat(user, "You attach the device to the cable.") - for(var/mob/M in viewers(user)) - if(M == user) continue + for(var/mob/M in viewers(user)) + if(M == user) continue to_chat(M, "[user] attaches the power sink to the cable.") - return - else + return + else to_chat(user, "Device must be placed over an exposed cable to attach to it.") - return - else - if (mode == 2) - processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite - anchored = 0 - mode = 0 + return + else + if (mode == 2) + processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite + anchored = 0 + mode = 0 to_chat(user, "You detach the device from the cable.") - attached.attached = null - attached = null - for(var/mob/M in viewers(user)) - if(M == user) continue + attached.attached = null + attached = null + for(var/mob/M in viewers(user)) + if(M == user) continue to_chat(M, "[user] detaches the power sink from the cable.") - set_light(0) - icon_state = "powersink0" - - return - else - ..() - - Destroy() - set_light(0) - processing_objects.Remove(src) - attached.attached = null - attached = null - ..() - - attack_paw() - return - - attack_ai() - return - - attack_hand(var/mob/user) - switch(mode) - if(0) - ..() - - if(1) + set_light(0) + icon_state = "powersink0" + + return + else + ..() + + Destroy() + set_light(0) + processing_objects.Remove(src) + attached.attached = null + attached = null + ..() + + attack_paw() + return + + attack_ai() + return + + attack_hand(var/mob/user) + switch(mode) + if(0) + ..() + + if(1) to_chat(user, "You activate the device!") - for(var/mob/M in viewers(user)) - if(M == user) continue + for(var/mob/M in viewers(user)) + if(M == user) continue to_chat(M, "[user] activates the power sink!") - mode = 2 - icon_state = "powersink1" - playsound(get_turf(src), 'sound/effects/phasein.ogg', 30, 1) - processing_objects.Add(src) - - if(2) //This switch option wasn't originally included. It exists now. --NeoFite + mode = 2 + icon_state = "powersink1" + playsound(get_turf(src), 'sound/effects/phasein.ogg', 30, 1) + processing_objects.Add(src) + + if(2) //This switch option wasn't originally included. It exists now. --NeoFite to_chat(user, "You deactivate the device!") - for(var/mob/M in viewers(user)) - if(M == user) continue + for(var/mob/M in viewers(user)) + if(M == user) continue to_chat(M, "[user] deactivates the power sink!") - mode = 1 - set_light(0) - icon_state = "powersink0" - playsound(get_turf(src), 'sound/effects/teleport.ogg', 50, 1) - processing_objects.Remove(src) - - process() - if(attached) - var/datum/powernet/PN = attached.get_powernet() - if(PN) - set_light(12) - - // found a powernet, so drain up to max power from it - - var/drained = min ( drain_rate, PN.avail ) - PN.load += drained - power_drained += drained - - // if tried to drain more than available on powernet - // now look for APCs and drain their cells - if(drained < drain_rate) - for(var/obj/machinery/power/terminal/T in PN.nodes) - if(istype(T.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = T.master - if(A.operating && A.cell) - A.cell.charge = max(0, A.cell.charge - 50) - power_drained += 50 - if(A.charging == 2) - A.charging = 1 - - - if(power_drained > max_power * 0.95) - playsound(src, 'sound/effects/screech.ogg', 100, 1, 1) - if(power_drained >= max_power) - processing_objects.Remove(src) - explosion(src.loc, 3,6,9,12) - qdel(src) + mode = 1 + set_light(0) + icon_state = "powersink0" + playsound(get_turf(src), 'sound/effects/teleport.ogg', 50, 1) + processing_objects.Remove(src) + + process() + if(attached) + var/datum/powernet/PN = attached.get_powernet() + if(PN) + set_light(12) + + // found a powernet, so drain up to max power from it + + var/drained = min ( drain_rate, PN.avail ) + PN.load += drained + power_drained += drained + + // if tried to drain more than available on powernet + // now look for APCs and drain their cells + if(drained < drain_rate) + for(var/obj/machinery/power/terminal/T in PN.nodes) + if(istype(T.master, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = T.master + if(A.operating && A.cell) + A.cell.charge = max(0, A.cell.charge - 50) + power_drained += 50 + if(A.charging == 2) + A.charging = 1 + + + if(power_drained > max_power * 0.95) + playsound(src, 'sound/effects/screech.ogg', 100, 1, 1) + if(power_drained >= max_power) + processing_objects.Remove(src) + explosion(src.loc, 3,6,9,12) + qdel(src) diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index 8eff448ab1b..e8120c9c914 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -1,165 +1,165 @@ -/obj/item/device/radio/electropack - name = "electropack" - desc = "Dance my monkeys! DANCE!!!" - icon_state = "electropack0" - item_state = "electropack" - origin_tech = "materials=1;powerstorage=2" - frequency = 1449 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - w_class = 5.0 - starting_materials = list(MAT_IRON = 10000, MAT_GLASS = 2500) - w_type = RECYK_ELECTRONIC - var/code = 2 - var/datum/radio_frequency/radio_connection - -/obj/item/device/radio/electropack/New() - ..() - if(radio_controller) - initialize() - else - spawn(50) - if(radio_controller) initialize() - -/obj/item/device/radio/electropack/initialize() - if(frequency < MINIMUM_FREQUENCY || frequency > MAXIMUM_FREQUENCY) - src.frequency = sanitize_frequency(src.frequency) - - set_frequency(frequency) - -/obj/item/device/radio/electropack/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency) - -/obj/item/device/radio/electropack/attack_hand(mob/user as mob) - if(src == user.back) +/obj/item/device/radio/electropack + name = "electropack" + desc = "Dance my monkeys! DANCE!!!" + icon_state = "electropack0" + item_state = "electropack" + origin_tech = "materials=1;powerstorage=2" + frequency = 1449 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + w_class = 5.0 + starting_materials = list(MAT_IRON = 10000, MAT_GLASS = 2500) + w_type = RECYK_ELECTRONIC + var/code = 2 + var/datum/radio_frequency/radio_connection + +/obj/item/device/radio/electropack/New() + ..() + if(radio_controller) + initialize() + else + spawn(50) + if(radio_controller) initialize() + +/obj/item/device/radio/electropack/initialize() + if(frequency < MINIMUM_FREQUENCY || frequency > MAXIMUM_FREQUENCY) + src.frequency = sanitize_frequency(src.frequency) + + set_frequency(frequency) + +/obj/item/device/radio/electropack/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency) + +/obj/item/device/radio/electropack/attack_hand(mob/user as mob) + if(src == user.back) to_chat(user, "You need help taking this off!") - return - ..() - -/obj/item/device/radio/electropack/Destroy() - if(istype(src.loc, /obj/item/assembly/shock_kit)) - var/obj/item/assembly/shock_kit/S = src.loc - if(S.part1 == src) - S.part1 = null - else if(S.part2 == src) - S.part2 = null - master = null - if(radio_controller) - radio_controller.remove_object(src, frequency) - ..() - -/obj/item/device/radio/electropack/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(istype(W, /obj/item/clothing/head/helmet)) - if(!b_stat) + return + ..() + +/obj/item/device/radio/electropack/Destroy() + if(istype(src.loc, /obj/item/assembly/shock_kit)) + var/obj/item/assembly/shock_kit/S = src.loc + if(S.part1 == src) + S.part1 = null + else if(S.part2 == src) + S.part2 = null + master = null + if(radio_controller) + radio_controller.remove_object(src, frequency) + ..() + +/obj/item/device/radio/electropack/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(istype(W, /obj/item/clothing/head/helmet)) + if(!b_stat) to_chat(user, "[src] is not ready to be attached!") - return - var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user ) - A.icon = 'icons/obj/assemblies.dmi' - - user.drop_from_inventory(W) - W.loc = A - W.master = A - A.part1 = W - - user.drop_from_inventory(src) - loc = A - master = A - A.part2 = src - - user.put_in_hands(A) - A.add_fingerprint(user) - -/obj/item/device/radio/electropack/Topic(href, href_list) - //..() - if(usr.stat || usr.restrained()) - return - if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf))))) - usr.set_machine(src) - if(href_list["freq"]) - var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"])) - set_frequency(new_frequency) - else - if(href_list["code"]) - code += text2num(href_list["code"]) - code = round(code) - code = min(100, code) - code = max(1, code) - else - if(href_list["power"]) - on = !( on ) - icon_state = "electropack[on]" - if(!( master )) - if(istype(loc, /mob)) - attack_self(loc) - else - for(var/mob/M in viewers(1, src)) - if(M.client) - attack_self(M) - else - if(istype(master.loc, /mob)) - attack_self(master.loc) - else - for(var/mob/M in viewers(1, master)) - if(M.client) - attack_self(M) - else - usr << browse(null, "window=radio") - return - return - -/obj/item/device/radio/electropack/receive_signal(datum/signal/signal) - if(!signal || signal.encryption != code) - return - - if(istype(src.loc, /obj/mecha) && on) - var/obj/mecha/R = src.loc //R is for GIANT ROBOT - R.shock_n_boot() - - else if(ismob(loc) && on) - var/mob/M = loc - var/turf/T = M.loc - if(istype(T, /turf)) - if(!M.moved_recently && M.last_move) - M.moved_recently = 1 - step(M, M.last_move) - spawn(50) - if(M) - M.moved_recently = 0 + return + var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user ) + A.icon = 'icons/obj/assemblies.dmi' + + user.drop_from_inventory(W) + W.loc = A + W.master = A + A.part1 = W + + user.drop_from_inventory(src) + loc = A + master = A + A.part2 = src + + user.put_in_hands(A) + A.add_fingerprint(user) + +/obj/item/device/radio/electropack/Topic(href, href_list) + //..() + if(usr.stat || usr.restrained()) + return + if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf))))) + usr.set_machine(src) + if(href_list["freq"]) + var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"])) + set_frequency(new_frequency) + else + if(href_list["code"]) + code += text2num(href_list["code"]) + code = round(code) + code = min(100, code) + code = max(1, code) + else + if(href_list["power"]) + on = !( on ) + icon_state = "electropack[on]" + if(!( master )) + if(istype(loc, /mob)) + attack_self(loc) + else + for(var/mob/M in viewers(1, src)) + if(M.client) + attack_self(M) + else + if(istype(master.loc, /mob)) + attack_self(master.loc) + else + for(var/mob/M in viewers(1, master)) + if(M.client) + attack_self(M) + else + usr << browse(null, "window=radio") + return + return + +/obj/item/device/radio/electropack/receive_signal(datum/signal/signal) + if(!signal || signal.encryption != code) + return + + if(istype(src.loc, /obj/mecha) && on) + var/obj/mecha/R = src.loc //R is for GIANT ROBOT + R.shock_n_boot() + + else if(ismob(loc) && on) + var/mob/M = loc + var/turf/T = M.loc + if(istype(T, /turf)) + if(!M.moved_recently && M.last_move) + M.moved_recently = 1 + step(M, M.last_move) + spawn(50) + if(M) + M.moved_recently = 0 to_chat(M, "You feel a sharp shock!") - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, M) - s.start() - - M.Weaken(10) - - if(master && isWireCut(1)) - master.receive_signal() - return - -/obj/item/device/radio/electropack/attack_self(mob/user as mob, flag1) - - if(!istype(user, /mob/living/carbon/human)) - return - user.set_machine(src) - var/dat = {" -Turn [on ? "Off" : "On"]
    -Frequency/Code for electropack:
    -Frequency: -- -- [format_frequency(frequency)] -+ -+
    - -Code: -- -- [code] -+ -+
    -
    "} - user << browse(dat, "window=radio") - onclose(user, "radio") - return + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, M) + s.start() + + M.Weaken(10) + + if(master && isWireCut(1)) + master.receive_signal() + return + +/obj/item/device/radio/electropack/attack_self(mob/user as mob, flag1) + + if(!istype(user, /mob/living/carbon/human)) + return + user.set_machine(src) + var/dat = {" +Turn [on ? "Off" : "On"]
    +Frequency/Code for electropack:
    +Frequency: +- +- [format_frequency(frequency)] ++ ++
    + +Code: +- +- [code] ++ ++
    +
    "} + user << browse(dat, "window=radio") + onclose(user, "radio") + return diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 1039c071535..4220747e237 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -1,365 +1,365 @@ -/obj/item/device/radio/headset - name = "radio headset" - desc = "An updated, modular intercom that fits over the head. Takes encryption keys" - icon_state = "headset" - item_state = "headset" - starting_materials = list(MAT_IRON = 75) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - subspace_transmission = 1 - canhear_range = 0 // can't hear headsets from very far away - - slot_flags = SLOT_EARS - var/translate_binary = 0 - var/translate_hive = 0 - var/obj/item/device/encryptionkey/keyslot1 = null - var/obj/item/device/encryptionkey/keyslot2 = null - maxf = 1489 - -/obj/item/device/radio/headset/New() - ..() - keyslot1 = new /obj/item/device/encryptionkey/ - recalculateChannels() - -/obj/item/device/radio/headset/receive_range(freq, level) - if(ishuman(src.loc)) - var/mob/living/carbon/human/H = src.loc - if(H.ears == src) - return ..(freq, level) - return -1 - -/obj/item/device/radio/headset/syndicate - origin_tech = "syndicate=3" -/obj/item/device/radio/headset/syndicate/New() - ..() - qdel(keyslot1) - keyslot1 = new /obj/item/device/encryptionkey/syndicate - syndie = 1 - recalculateChannels() - -/obj/item/device/radio/headset/binary - origin_tech = "syndicate=3" -/obj/item/device/radio/headset/binary/New() - ..() - qdel(keyslot1) - keyslot1 = new /obj/item/device/encryptionkey/binary - recalculateChannels() - -/obj/item/device/radio/headset/headset_sec - name = "security radio headset" - desc = "This is used by your elite security force. To access the security channel, use :s." - icon_state = "sec_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_sec(src) - ..() - -/obj/item/device/radio/headset/headset_eng - name = "engineering radio headset" - desc = "When the engineers wish to chat like girls. To access the engineering channel, use :e. " - icon_state = "eng_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_eng - ..() - -/obj/item/device/radio/headset/headset_rob - name = "robotics radio headset" - desc = "Made specifically for the roboticists who cannot decide between departments. To access the engineering channel, use :e. For research, use :n." - icon_state = "rob_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_rob - ..() - -/obj/item/device/radio/headset/headset_med - name = "medical radio headset" - desc = "A headset for the trained staff of the medbay. To access the medical channel, use :m." - icon_state = "med_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_med - ..() - -/obj/item/device/radio/headset/headset_sci - name = "science radio headset" - desc = "A sciency headset. Like usual. To access the science channel, use :n." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_sci - ..() - -/obj/item/device/radio/headset/headset_medsci - name = "medical research radio headset" - desc = "A headset that is a result of the mating between medical and science. To access the medical channel, use :m. For science, use :n." - icon_state = "med_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_medsci - ..() - -/obj/item/device/radio/headset/headset_com - name = "command radio headset" - desc = "A headset with a commanding channel. To access the command channel, use :c." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_com - ..() - -/obj/item/device/radio/headset/heads/captain - name = "captain's headset" - desc = "The headset of the boss. Channels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :d - service, :m - medical, :n - science." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/heads/captain - ..() - -/obj/item/device/radio/headset/heads/rd - name = "Research Director's headset" - desc = "Headset of the researching God. To access the science channel, use :n. For command, use :c." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/heads/rd - ..() - -/obj/item/device/radio/headset/heads/hos - name = "head of security's headset" - desc = "The headset of the man who protects your worthless lifes. To access the security channel, use :s. For command, use :c." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/heads/hos - ..() - -/obj/item/device/radio/headset/heads/ce - name = "chief engineer's headset" - desc = "The headset of the guy who is in charge of morons. To access the engineering channel, use :e. For command, use :c." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/heads/ce - ..() - -/obj/item/device/radio/headset/heads/cmo - name = "chief medical officer's headset" - desc = "The headset of the highly trained medical chief. To access the medical channel, use :m. For command, use :c." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/heads/cmo - ..() - -/obj/item/device/radio/headset/heads/hop - name = "head of personnel's headset" - desc = "The headset of the guy who will one day be captain. Channels are as follows: :u - supply, :d - service, :c - command, :s - security" - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/heads/hop - ..() - -/obj/item/device/radio/headset/headset_cargo - name = "supply radio headset" - desc = "A headset used by the QM and his slaves. To access the supply channel, use :u." - icon_state = "cargo_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_cargo - ..() - -/obj/item/device/radio/headset/headset_mining - name = "supply radio headset" - desc = "A headset used by the shaft miners to be yelled at from the QM and R&D at the same time. Channels are as follows: :u - supply, :n - science" - icon_state = "mine_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_mining - ..() - -/obj/item/device/radio/headset/headset_service - name = "service radio headset" - desc = "A headset used by the chef, the bartender and the botanists to plan their poisoning of the entire crew. To access the service channel, use :d." - icon_state = "service_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_service - ..() - -/obj/item/device/radio/headset/headset_engsci - name = "research engineering radio headset" - desc = "A headset used to gossip about engineering to the science crew, and about science to the engineering crew. To access the engineering channel, use :e. For science, use :n." - icon_state = "eng_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_engsci - ..() - -/obj/item/device/radio/headset/headset_servsci - name = "research service radio headset" - desc = "A headset used to talk to botanists and scientists. To access the science channel, use :n. For service, use :d." - icon_state = "com_headset" - item_state = "headset" - - New() - keyslot2 = new /obj/item/device/encryptionkey/headset_servsci - ..() - -/obj/item/device/radio/headset/headset_earmuffs - name = "headset earmuffs" - desc = "Protective earmuffs for sound technicians that allow one to speak on radio channels. To access service, use :d. For engineering, use :e." - icon = 'icons/obj/items.dmi' - icon_state = "headset_earmuffs" - item_state = "earmuffs" - - New() - //keyslot2 = new /obj/item/device/encryptionkey/headset_serveng - ..() - -/obj/item/device/radio/headset/deathsquad - name = "Deathsquad headset" - desc = "A headset used by the dark side of Nanotrasen's Spec Ops. Channels are as follows: :0 - Deathsquad :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science." - icon_state = "deathsquad_headset" - item_state = "headset" - freerange = 1 - - New() - keyslot2 = new /obj/item/device/encryptionkey/deathsquad - ..() - -/obj/item/device/radio/headset/ert - name = "CentCom Response Team headset" - desc = "The headset of the boss's boss. Channels are as follows: :r - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science." - icon_state = "ert_headset" - item_state = "headset" - freerange = 1 - - New() - keyslot2 = new /obj/item/device/encryptionkey/ert - ..() - -/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob) -// ..() - user.set_machine(src) - if (!( istype(W, /obj/item/weapon/screwdriver) || (istype(W, /obj/item/device/encryptionkey/ )))) - return - - if(istype(W, /obj/item/weapon/screwdriver)) - if(keyslot1 || keyslot2) - - - for(var/ch_name in channels) - radio_controller.remove_object(src, radiochannels[ch_name]) - secure_radio_connections[ch_name] = null - - - if(keyslot1) - var/turf/T = get_turf(user) - if(T) - keyslot1.loc = T - keyslot1 = null - - - - if(keyslot2) - var/turf/T = get_turf(user) - if(T) - keyslot2.loc = T - keyslot2 = null - - recalculateChannels() +/obj/item/device/radio/headset + name = "radio headset" + desc = "An updated, modular intercom that fits over the head. Takes encryption keys" + icon_state = "headset" + item_state = "headset" + starting_materials = list(MAT_IRON = 75) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + subspace_transmission = 1 + canhear_range = 0 // can't hear headsets from very far away + + slot_flags = SLOT_EARS + var/translate_binary = 0 + var/translate_hive = 0 + var/obj/item/device/encryptionkey/keyslot1 = null + var/obj/item/device/encryptionkey/keyslot2 = null + maxf = 1489 + +/obj/item/device/radio/headset/New() + ..() + keyslot1 = new /obj/item/device/encryptionkey/ + recalculateChannels() + +/obj/item/device/radio/headset/receive_range(freq, level) + if(ishuman(src.loc)) + var/mob/living/carbon/human/H = src.loc + if(H.ears == src) + return ..(freq, level) + return -1 + +/obj/item/device/radio/headset/syndicate + origin_tech = "syndicate=3" +/obj/item/device/radio/headset/syndicate/New() + ..() + qdel(keyslot1) + keyslot1 = new /obj/item/device/encryptionkey/syndicate + syndie = 1 + recalculateChannels() + +/obj/item/device/radio/headset/binary + origin_tech = "syndicate=3" +/obj/item/device/radio/headset/binary/New() + ..() + qdel(keyslot1) + keyslot1 = new /obj/item/device/encryptionkey/binary + recalculateChannels() + +/obj/item/device/radio/headset/headset_sec + name = "security radio headset" + desc = "This is used by your elite security force. To access the security channel, use :s." + icon_state = "sec_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_sec(src) + ..() + +/obj/item/device/radio/headset/headset_eng + name = "engineering radio headset" + desc = "When the engineers wish to chat like girls. To access the engineering channel, use :e. " + icon_state = "eng_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_eng + ..() + +/obj/item/device/radio/headset/headset_rob + name = "robotics radio headset" + desc = "Made specifically for the roboticists who cannot decide between departments. To access the engineering channel, use :e. For research, use :n." + icon_state = "rob_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_rob + ..() + +/obj/item/device/radio/headset/headset_med + name = "medical radio headset" + desc = "A headset for the trained staff of the medbay. To access the medical channel, use :m." + icon_state = "med_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_med + ..() + +/obj/item/device/radio/headset/headset_sci + name = "science radio headset" + desc = "A sciency headset. Like usual. To access the science channel, use :n." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_sci + ..() + +/obj/item/device/radio/headset/headset_medsci + name = "medical research radio headset" + desc = "A headset that is a result of the mating between medical and science. To access the medical channel, use :m. For science, use :n." + icon_state = "med_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_medsci + ..() + +/obj/item/device/radio/headset/headset_com + name = "command radio headset" + desc = "A headset with a commanding channel. To access the command channel, use :c." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_com + ..() + +/obj/item/device/radio/headset/heads/captain + name = "captain's headset" + desc = "The headset of the boss. Channels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :d - service, :m - medical, :n - science." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/heads/captain + ..() + +/obj/item/device/radio/headset/heads/rd + name = "Research Director's headset" + desc = "Headset of the researching God. To access the science channel, use :n. For command, use :c." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/heads/rd + ..() + +/obj/item/device/radio/headset/heads/hos + name = "head of security's headset" + desc = "The headset of the man who protects your worthless lifes. To access the security channel, use :s. For command, use :c." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/heads/hos + ..() + +/obj/item/device/radio/headset/heads/ce + name = "chief engineer's headset" + desc = "The headset of the guy who is in charge of morons. To access the engineering channel, use :e. For command, use :c." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/heads/ce + ..() + +/obj/item/device/radio/headset/heads/cmo + name = "chief medical officer's headset" + desc = "The headset of the highly trained medical chief. To access the medical channel, use :m. For command, use :c." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/heads/cmo + ..() + +/obj/item/device/radio/headset/heads/hop + name = "head of personnel's headset" + desc = "The headset of the guy who will one day be captain. Channels are as follows: :u - supply, :d - service, :c - command, :s - security" + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/heads/hop + ..() + +/obj/item/device/radio/headset/headset_cargo + name = "supply radio headset" + desc = "A headset used by the QM and his slaves. To access the supply channel, use :u." + icon_state = "cargo_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_cargo + ..() + +/obj/item/device/radio/headset/headset_mining + name = "supply radio headset" + desc = "A headset used by the shaft miners to be yelled at from the QM and R&D at the same time. Channels are as follows: :u - supply, :n - science" + icon_state = "mine_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_mining + ..() + +/obj/item/device/radio/headset/headset_service + name = "service radio headset" + desc = "A headset used by the chef, the bartender and the botanists to plan their poisoning of the entire crew. To access the service channel, use :d." + icon_state = "service_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_service + ..() + +/obj/item/device/radio/headset/headset_engsci + name = "research engineering radio headset" + desc = "A headset used to gossip about engineering to the science crew, and about science to the engineering crew. To access the engineering channel, use :e. For science, use :n." + icon_state = "eng_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_engsci + ..() + +/obj/item/device/radio/headset/headset_servsci + name = "research service radio headset" + desc = "A headset used to talk to botanists and scientists. To access the science channel, use :n. For service, use :d." + icon_state = "com_headset" + item_state = "headset" + + New() + keyslot2 = new /obj/item/device/encryptionkey/headset_servsci + ..() + +/obj/item/device/radio/headset/headset_earmuffs + name = "headset earmuffs" + desc = "Protective earmuffs for sound technicians that allow one to speak on radio channels. To access service, use :d. For engineering, use :e." + icon = 'icons/obj/items.dmi' + icon_state = "headset_earmuffs" + item_state = "earmuffs" + + New() + //keyslot2 = new /obj/item/device/encryptionkey/headset_serveng + ..() + +/obj/item/device/radio/headset/deathsquad + name = "Deathsquad headset" + desc = "A headset used by the dark side of Nanotrasen's Spec Ops. Channels are as follows: :0 - Deathsquad :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science." + icon_state = "deathsquad_headset" + item_state = "headset" + freerange = 1 + + New() + keyslot2 = new /obj/item/device/encryptionkey/deathsquad + ..() + +/obj/item/device/radio/headset/ert + name = "CentCom Response Team headset" + desc = "The headset of the boss's boss. Channels are as follows: :r - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science." + icon_state = "ert_headset" + item_state = "headset" + freerange = 1 + + New() + keyslot2 = new /obj/item/device/encryptionkey/ert + ..() + +/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob) +// ..() + user.set_machine(src) + if (!( istype(W, /obj/item/weapon/screwdriver) || (istype(W, /obj/item/device/encryptionkey/ )))) + return + + if(istype(W, /obj/item/weapon/screwdriver)) + if(keyslot1 || keyslot2) + + + for(var/ch_name in channels) + radio_controller.remove_object(src, radiochannels[ch_name]) + secure_radio_connections[ch_name] = null + + + if(keyslot1) + var/turf/T = get_turf(user) + if(T) + keyslot1.loc = T + keyslot1 = null + + + + if(keyslot2) + var/turf/T = get_turf(user) + if(T) + keyslot2.loc = T + keyslot2 = null + + recalculateChannels() to_chat(user, "You pop out the encryption keys in the headset!") - - else + + else to_chat(user, "This headset doesn't have any encryption keys! How useless...") - - if(istype(W, /obj/item/device/encryptionkey/)) - if(keyslot1 && keyslot2) + + if(istype(W, /obj/item/device/encryptionkey/)) + if(keyslot1 && keyslot2) to_chat(user, "The headset can't hold another key!") - return - - if(!keyslot1) - if(user.drop_item(W, src)) - keyslot1 = W - - else - if(user.drop_item(W, src)) - keyslot2 = W - - - recalculateChannels() - - return - - -/obj/item/device/radio/headset/proc/recalculateChannels() - src.channels = list() - src.translate_binary = 0 - src.translate_hive = 0 - src.syndie = 0 - - if(keyslot1) - for(var/ch_name in keyslot1.channels) - if(ch_name in src.channels) - continue - src.channels += ch_name - src.channels[ch_name] = keyslot1.channels[ch_name] - - if(keyslot1.translate_binary) - src.translate_binary = 1 - - if(keyslot1.translate_hive) - src.translate_hive = 1 - - if(keyslot1.syndie) - src.syndie = 1 - - if(keyslot2) - for(var/ch_name in keyslot2.channels) - if(ch_name in src.channels) - continue - src.channels += ch_name - src.channels[ch_name] = keyslot2.channels[ch_name] - - if(keyslot2.translate_binary) - src.translate_binary = 1 - - if(keyslot2.translate_hive) - src.translate_hive = 1 - - if(keyslot2.syndie) - src.syndie = 1 - - - for (var/ch_name in channels) - //this is the most hilarious piece of code i have seen this week, so im not going to remove it - /* - if(!radio_controller) - sleep(30) // Waiting for the radio_controller to be created. - if(!radio_controller) - src.name = "broken radio headset" - return - */ - secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name]) - - return + return + + if(!keyslot1) + if(user.drop_item(W, src)) + keyslot1 = W + + else + if(user.drop_item(W, src)) + keyslot2 = W + + + recalculateChannels() + + return + + +/obj/item/device/radio/headset/proc/recalculateChannels() + src.channels = list() + src.translate_binary = 0 + src.translate_hive = 0 + src.syndie = 0 + + if(keyslot1) + for(var/ch_name in keyslot1.channels) + if(ch_name in src.channels) + continue + src.channels += ch_name + src.channels[ch_name] = keyslot1.channels[ch_name] + + if(keyslot1.translate_binary) + src.translate_binary = 1 + + if(keyslot1.translate_hive) + src.translate_hive = 1 + + if(keyslot1.syndie) + src.syndie = 1 + + if(keyslot2) + for(var/ch_name in keyslot2.channels) + if(ch_name in src.channels) + continue + src.channels += ch_name + src.channels[ch_name] = keyslot2.channels[ch_name] + + if(keyslot2.translate_binary) + src.translate_binary = 1 + + if(keyslot2.translate_hive) + src.translate_hive = 1 + + if(keyslot2.syndie) + src.syndie = 1 + + + for (var/ch_name in channels) + //this is the most hilarious piece of code i have seen this week, so im not going to remove it + /* + if(!radio_controller) + sleep(30) // Waiting for the radio_controller to be created. + if(!radio_controller) + src.name = "broken radio headset" + return + */ + secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name]) + + return diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index e2beb7c2211..daacbbaa689 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -1,163 +1,163 @@ -/obj/item/device/radio/intercom - name = "station intercom" - desc = "Talk through this." - icon_state = "intercom" - anchored = 1 - w_class = 4.0 - canhear_range = 2 - var/number = 0 - var/anyai = 1 - var/circuitry_installed=1 - var/mob/living/silicon/ai/ai = list() - var/last_tick //used to delay the powercheck - var/buildstage = 0 - -/obj/item/device/radio/intercom/universe/New() - tag = "UNIVERSE" - return ..() - -/obj/item/device/radio/intercom/New(turf/loc, var/ndir = 0, var/building = 3) - ..() - buildstage = building - if(buildstage) - processing_objects.Add(src) - else - pixel_x = (ndir & 3)? 0 : (ndir == 4 ? 28 : -28) - pixel_y = (ndir & 3)? (ndir ==1 ? 28 : -28) : 0 - dir=ndir - b_stat=1 - on = 0 - update_icon() - -/obj/item/device/radio/intercom/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/device/radio/intercom/attack_ai(mob/user as mob) - add_hiddenprint(user) - add_fingerprint(user) - spawn (0) - attack_self(user) - -/obj/item/device/radio/intercom/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/item/device/radio/intercom/attack_hand(mob/user as mob) - add_fingerprint(user) - spawn (0) - attack_self(user) - -/obj/item/device/radio/intercom/receive_range(freq, level) - if (!on || b_stat || isWireCut(WIRE_RECEIVE)) - return -1 - if(!(0 in level)) - var/turf/position = get_turf(src) - if(isnull(position) || !(position.z in level)) - return -1 - if (!src.listening) - return -1 - if(freq == SYND_FREQ) - if(!(src.syndie)) - return -1//Prevents broadcast of messages over devices lacking the encryption - - return canhear_range - - -/obj/item/device/radio/intercom/Hear(var/datum/speech/speech, var/rendered_speech="") - if(speech.speaker && !src.anyai && !(speech.speaker in src.ai)) - return - ..() - -/obj/item/device/radio/intercom/attackby(obj/item/weapon/W as obj, mob/user as mob) - switch(buildstage) - if(3) - if(iswirecutter(W) && b_stat && wires.IsAllCut()) +/obj/item/device/radio/intercom + name = "station intercom" + desc = "Talk through this." + icon_state = "intercom" + anchored = 1 + w_class = 4.0 + canhear_range = 2 + var/number = 0 + var/anyai = 1 + var/circuitry_installed=1 + var/mob/living/silicon/ai/ai = list() + var/last_tick //used to delay the powercheck + var/buildstage = 0 + +/obj/item/device/radio/intercom/universe/New() + tag = "UNIVERSE" + return ..() + +/obj/item/device/radio/intercom/New(turf/loc, var/ndir = 0, var/building = 3) + ..() + buildstage = building + if(buildstage) + processing_objects.Add(src) + else + pixel_x = (ndir & 3)? 0 : (ndir == 4 ? 28 : -28) + pixel_y = (ndir & 3)? (ndir ==1 ? 28 : -28) : 0 + dir=ndir + b_stat=1 + on = 0 + update_icon() + +/obj/item/device/radio/intercom/Destroy() + processing_objects.Remove(src) + ..() + +/obj/item/device/radio/intercom/attack_ai(mob/user as mob) + add_hiddenprint(user) + add_fingerprint(user) + spawn (0) + attack_self(user) + +/obj/item/device/radio/intercom/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/item/device/radio/intercom/attack_hand(mob/user as mob) + add_fingerprint(user) + spawn (0) + attack_self(user) + +/obj/item/device/radio/intercom/receive_range(freq, level) + if (!on || b_stat || isWireCut(WIRE_RECEIVE)) + return -1 + if(!(0 in level)) + var/turf/position = get_turf(src) + if(isnull(position) || !(position.z in level)) + return -1 + if (!src.listening) + return -1 + if(freq == SYND_FREQ) + if(!(src.syndie)) + return -1//Prevents broadcast of messages over devices lacking the encryption + + return canhear_range + + +/obj/item/device/radio/intercom/Hear(var/datum/speech/speech, var/rendered_speech="") + if(speech.speaker && !src.anyai && !(speech.speaker in src.ai)) + return + ..() + +/obj/item/device/radio/intercom/attackby(obj/item/weapon/W as obj, mob/user as mob) + switch(buildstage) + if(3) + if(iswirecutter(W) && b_stat && wires.IsAllCut()) to_chat(user, "You cut out the intercoms wiring and disconnect its electronics.") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) - if(do_after(user, src, 10)) - new /obj/item/stack/cable_coil(get_turf(src),5) - on = 0 - b_stat = 1 - buildstage = 1 - update_icon() - processing_objects.Remove(src) - return 1 - else return ..() - if(2) - if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 10)) - update_icon() - on = 1 - b_stat = 0 - buildstage = 3 + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + if(do_after(user, src, 10)) + new /obj/item/stack/cable_coil(get_turf(src),5) + on = 0 + b_stat = 1 + buildstage = 1 + update_icon() + processing_objects.Remove(src) + return 1 + else return ..() + if(2) + if(isscrewdriver(W)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 10)) + update_icon() + on = 1 + b_stat = 0 + buildstage = 3 to_chat(user, "You secure the electronics!") - update_icon() - processing_objects.Add(src) - for(var/i, i<= 5, i++) - wires.UpdateCut(i,1) - return 1 - if(1) - if(iscoil(W)) - var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 5) + update_icon() + processing_objects.Add(src) + for(var/i, i<= 5, i++) + wires.UpdateCut(i,1) + return 1 + if(1) + if(iscoil(W)) + var/obj/item/stack/cable_coil/coil = W + if(coil.amount < 5) to_chat(user, "You need more cable for this!") - return - if(do_after(user, src, 10)) - coil.use(5) + return + if(do_after(user, src, 10)) + coil.use(5) to_chat(user, "You wire \the [src]!") - buildstage = 2 - return 1 - if(iscrowbar(W)) + buildstage = 2 + return 1 + if(iscrowbar(W)) to_chat(user, "You begin removing the electronics...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 10)) - new /obj/item/weapon/intercom_electronics(get_turf(src)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 10)) + new /obj/item/weapon/intercom_electronics(get_turf(src)) to_chat(user, "The circuitboard pops out!") - buildstage = 0 - return 1 - if(0) - if(istype(W,/obj/item/weapon/intercom_electronics)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 10)) - qdel(W) + buildstage = 0 + return 1 + if(0) + if(istype(W,/obj/item/weapon/intercom_electronics)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 10)) + qdel(W) to_chat(user, "You insert \the [W] into \the [src]!") - buildstage = 1 - return 1 - if(iswelder(W)) - var/obj/item/weapon/weldingtool/WT=W - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - if(!WT.remove_fuel(3, user)) + buildstage = 1 + return 1 + if(iswelder(W)) + var/obj/item/weapon/weldingtool/WT=W + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + if(!WT.remove_fuel(3, user)) to_chat(user, "You're out of welding fuel.") - return 1 - if(do_after(user, src, 10)) + return 1 + if(do_after(user, src, 10)) to_chat(user, "You cut the intercom frame from the wall!") - new /obj/item/mounted/frame/intercom(get_turf(src)) - qdel(src) - return 1 - -/obj/item/device/radio/intercom/update_icon() - if(!circuitry_installed) - icon_state="intercom-frame" - return - icon_state = "intercom[!on?"-p":""][b_stat ? "-open":""]" - -/obj/item/device/radio/intercom/process() - if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) - last_tick = world.timeofday - if(!areaMaster) - on = 0 - update_icon() - return - on = areaMaster.powered(EQUIP) // set "on" to the power status - update_icon() - -/obj/item/weapon/intercom_electronics - name = "intercom electronics" - icon = 'icons/obj/doors/door_assembly.dmi' - icon_state = "door_electronics" - desc = "Looks like a circuit. Probably is." - w_class = 2.0 - starting_materials = list(MAT_IRON = 50, MAT_GLASS = 50) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_SILICON + new /obj/item/mounted/frame/intercom(get_turf(src)) + qdel(src) + return 1 + +/obj/item/device/radio/intercom/update_icon() + if(!circuitry_installed) + icon_state="intercom-frame" + return + icon_state = "intercom[!on?"-p":""][b_stat ? "-open":""]" + +/obj/item/device/radio/intercom/process() + if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) + last_tick = world.timeofday + if(!areaMaster) + on = 0 + update_icon() + return + on = areaMaster.powered(EQUIP) // set "on" to the power status + update_icon() + +/obj/item/weapon/intercom_electronics + name = "intercom electronics" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + desc = "Looks like a circuit. Probably is." + w_class = 2.0 + starting_materials = list(MAT_IRON = 50, MAT_GLASS = 50) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_SILICON diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 19d13d11499..428bc632a86 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -1,551 +1,551 @@ -/obj/item/device/radio - icon = 'icons/obj/radio.dmi' - name = "station bounced radio" - suffix = "\[3\]" - icon_state = "walkietalkie" - item_state = "walkietalkie" - var/on = 1 // 0 for off - var/last_transmission - var/frequency = 1459 //common chat - var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies - var/canhear_range = 3 // the range which mobs can hear this radio from - var/obj/item/device/radio/patch_link = null - var/datum/wires/radio/wires = null - var/list/secure_radio_connections - var/prison_radio = 0 - var/b_stat = 0 - var/broadcasting = 0 - var/listening = 1 - var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range - var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h - var/subspace_transmission = 0 - var/syndie = 0//Holder to see if it's a syndicate encrpyed radio - var/maxf = 1499 -// "Example" = FREQ_LISTENING|FREQ_BROADCASTING - flags = FPRINT | HEAR - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throw_speed = 2 - throw_range = 9 - w_class = 2 - starting_materials = list(MAT_IRON = 75, MAT_GLASS = 25) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - - var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio - var/const/FREQ_LISTENING = 1 - //FREQ_BROADCASTING = 2 - - var/always_talk=0 // ALWAYS catch signals. Useful for covert listening devices. - -/obj/item/device/radio/proc/set_frequency(new_frequency) - remove_radio(src, frequency) - frequency = add_radio(src, new_frequency) - -/obj/item/device/radio/New() - wires = new(src) - - if(prison_radio) - wires.CutWireIndex(WIRE_TRANSMIT) - - secure_radio_connections = new - ..(loc) - if(radio_controller) - initialize() - -/obj/item/device/radio/Destroy() - wires = null - remove_radio_all(src) //Just to be sure - ..() - - -/obj/item/device/radio/initialize() - - if(freerange) - if(frequency < 1200 || frequency > 1600) - frequency = sanitize_frequency(frequency, maxf) - // The max freq is higher than a regular headset to decrease the chance of people listening in, if you use the higher channels. - else if (frequency < 1441 || frequency > maxf) - //world.log << "[src] ([type]) has a frequency of [frequency], sanitizing." - frequency = sanitize_frequency(frequency, maxf) - - set_frequency(frequency) - - for (var/channel_name in channels) - secure_radio_connections[channel_name] = add_radio(src, radiochannels[channel_name]) - -/obj/item/device/radio/attack_self(mob/user as mob) - user.set_machine(src) - interact(user) - -/obj/item/device/radio/interact(mob/user as mob) - if(!on) - return - - if(active_uplink_check(user)) - return - - var/dat = "[src]" - - if(!istype(src, /obj/item/device/radio/headset)) //Headsets dont get a mic button - dat += "Microphone: [broadcasting ? "Engaged" : "Disengaged"]
    " - - dat += {" - Speaker: [listening ? "Engaged" : "Disengaged"]
    - Frequency: - - - - - [format_frequency(frequency)] - + - +
    - "} - - for (var/ch_name in channels) - dat+=text_sec_channel(ch_name, channels[ch_name]) - dat+={"[text_wires()]
    "} - user << browse(dat, "window=radio") - onclose(user, "radio") - return - -/obj/item/device/radio/proc/text_wires() - if (b_stat) - return wires.GetInteractWindow() - return - - -/obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat) - var/list = !!(chan_stat&FREQ_LISTENING)!=0 - return {" - [chan_name]: [list ? "Engaged" : "Disengaged"]
    - "} - -/obj/item/device/radio/Topic(href, href_list) - //..() - if (usr.stat || !on) - return - - if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) )))) - usr << browse(null, "window=radio") - return - usr.set_machine(src) - if (href_list["open"]) - var/mob/target = locate(href_list["open"]) - var/mob/living/silicon/ai/A = locate(href_list["open2"]) - if(A && target) - A.open_nearest_door(target) - return - - if (href_list["track"]) - var/mob/target = locate(href_list["track"]) - var/mob/living/silicon/ai/A = locate(href_list["track2"]) - if(A && target) - A.ai_actual_track(target) - return - - else if (href_list["faketrack"]) - var/mob/target = locate(href_list["track"]) - var/mob/living/silicon/ai/A = locate(href_list["track2"]) - if(A && target) - - A:cameraFollow = target +/obj/item/device/radio + icon = 'icons/obj/radio.dmi' + name = "station bounced radio" + suffix = "\[3\]" + icon_state = "walkietalkie" + item_state = "walkietalkie" + var/on = 1 // 0 for off + var/last_transmission + var/frequency = 1459 //common chat + var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies + var/canhear_range = 3 // the range which mobs can hear this radio from + var/obj/item/device/radio/patch_link = null + var/datum/wires/radio/wires = null + var/list/secure_radio_connections + var/prison_radio = 0 + var/b_stat = 0 + var/broadcasting = 0 + var/listening = 1 + var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range + var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h + var/subspace_transmission = 0 + var/syndie = 0//Holder to see if it's a syndicate encrpyed radio + var/maxf = 1499 +// "Example" = FREQ_LISTENING|FREQ_BROADCASTING + flags = FPRINT | HEAR + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throw_speed = 2 + throw_range = 9 + w_class = 2 + starting_materials = list(MAT_IRON = 75, MAT_GLASS = 25) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + + var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio + var/const/FREQ_LISTENING = 1 + //FREQ_BROADCASTING = 2 + + var/always_talk=0 // ALWAYS catch signals. Useful for covert listening devices. + +/obj/item/device/radio/proc/set_frequency(new_frequency) + remove_radio(src, frequency) + frequency = add_radio(src, new_frequency) + +/obj/item/device/radio/New() + wires = new(src) + + if(prison_radio) + wires.CutWireIndex(WIRE_TRANSMIT) + + secure_radio_connections = new + ..(loc) + if(radio_controller) + initialize() + +/obj/item/device/radio/Destroy() + wires = null + remove_radio_all(src) //Just to be sure + ..() + + +/obj/item/device/radio/initialize() + + if(freerange) + if(frequency < 1200 || frequency > 1600) + frequency = sanitize_frequency(frequency, maxf) + // The max freq is higher than a regular headset to decrease the chance of people listening in, if you use the higher channels. + else if (frequency < 1441 || frequency > maxf) + //world.log << "[src] ([type]) has a frequency of [frequency], sanitizing." + frequency = sanitize_frequency(frequency, maxf) + + set_frequency(frequency) + + for (var/channel_name in channels) + secure_radio_connections[channel_name] = add_radio(src, radiochannels[channel_name]) + +/obj/item/device/radio/attack_self(mob/user as mob) + user.set_machine(src) + interact(user) + +/obj/item/device/radio/interact(mob/user as mob) + if(!on) + return + + if(active_uplink_check(user)) + return + + var/dat = "[src]" + + if(!istype(src, /obj/item/device/radio/headset)) //Headsets dont get a mic button + dat += "Microphone: [broadcasting ? "Engaged" : "Disengaged"]
    " + + dat += {" + Speaker: [listening ? "Engaged" : "Disengaged"]
    + Frequency: + - + - + [format_frequency(frequency)] + + + +
    + "} + + for (var/ch_name in channels) + dat+=text_sec_channel(ch_name, channels[ch_name]) + dat+={"[text_wires()]
    "} + user << browse(dat, "window=radio") + onclose(user, "radio") + return + +/obj/item/device/radio/proc/text_wires() + if (b_stat) + return wires.GetInteractWindow() + return + + +/obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat) + var/list = !!(chan_stat&FREQ_LISTENING)!=0 + return {" + [chan_name]: [list ? "Engaged" : "Disengaged"]
    + "} + +/obj/item/device/radio/Topic(href, href_list) + //..() + if (usr.stat || !on) + return + + if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) )))) + usr << browse(null, "window=radio") + return + usr.set_machine(src) + if (href_list["open"]) + var/mob/target = locate(href_list["open"]) + var/mob/living/silicon/ai/A = locate(href_list["open2"]) + if(A && target) + A.open_nearest_door(target) + return + + if (href_list["track"]) + var/mob/target = locate(href_list["track"]) + var/mob/living/silicon/ai/A = locate(href_list["track2"]) + if(A && target) + A.ai_actual_track(target) + return + + else if (href_list["faketrack"]) + var/mob/target = locate(href_list["track"]) + var/mob/living/silicon/ai/A = locate(href_list["track2"]) + if(A && target) + + A:cameraFollow = target to_chat(A, text("Now tracking [] on camera.", target.name)) - if (usr.machine == null) - usr.machine = usr - - while (usr:cameraFollow == target) + if (usr.machine == null) + usr.machine = usr + + while (usr:cameraFollow == target) to_chat(usr, "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb).") - sleep(40) - continue - - return - - else if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if (!freerange || (frequency < 1200 || frequency > 1600)) - new_frequency = sanitize_frequency(new_frequency, maxf) - set_frequency(new_frequency) - if(hidden_uplink) - if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) - usr << browse(null, "window=radio") - return - - else if (href_list["talk"]) - broadcasting = text2num(href_list["talk"]) - else if (href_list["listen"]) - var/chan_name = href_list["ch_name"] - if (!chan_name) - listening = text2num(href_list["listen"]) - else - if (channels[chan_name] & FREQ_LISTENING) - channels[chan_name] &= ~FREQ_LISTENING - else - channels[chan_name] |= FREQ_LISTENING - if (!( master )) - if (istype(loc, /mob)) - interact(loc) - else - updateDialog() - else - if (istype(master.loc, /mob)) - interact(master.loc) - else - updateDialog() - add_fingerprint(usr) - -/obj/item/device/radio/proc/isWireCut(var/index) - return wires.IsIndexCut(index) -/* -/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT - var/datum/radio_frequency/connection = null - if(channel && channels && channels.len > 0) - if (channel == "department") + sleep(40) + continue + + return + + else if (href_list["freq"]) + var/new_frequency = (frequency + text2num(href_list["freq"])) + if (!freerange || (frequency < 1200 || frequency > 1600)) + new_frequency = sanitize_frequency(new_frequency, maxf) + set_frequency(new_frequency) + if(hidden_uplink) + if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) + usr << browse(null, "window=radio") + return + + else if (href_list["talk"]) + broadcasting = text2num(href_list["talk"]) + else if (href_list["listen"]) + var/chan_name = href_list["ch_name"] + if (!chan_name) + listening = text2num(href_list["listen"]) + else + if (channels[chan_name] & FREQ_LISTENING) + channels[chan_name] &= ~FREQ_LISTENING + else + channels[chan_name] |= FREQ_LISTENING + if (!( master )) + if (istype(loc, /mob)) + interact(loc) + else + updateDialog() + else + if (istype(master.loc, /mob)) + interact(master.loc) + else + updateDialog() + add_fingerprint(usr) + +/obj/item/device/radio/proc/isWireCut(var/index) + return wires.IsIndexCut(index) +/* +/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT + var/datum/radio_frequency/connection = null + if(channel && channels && channels.len > 0) + if (channel == "department") // to_chat(world, "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"") - channel = channels[1] - connection = secure_radio_connections[channel] - else - connection = radio_connection - channel = null - if (!istype(connection)) - return - if (!connection) - return - - var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(src, null, null, 1) - Broadcast_Message(connection, all_languages["Sol Common"], A, - 0, "*garbled automated announcement*", src, - message, from, "Automated Announcement", from, "synthesized voice", - 4, 0, list(1), 1459) - del(A) - return - -*/ - -/obj/item/device/radio/talk_into(var/datum/speech/speech_orig, var/channel=null) - say_testing(loc, "\[Radio\] - Got radio/talk_into([html_encode(speech_orig.message)], [channel!=null ? channel : "null"]).") - if(!on) - say_testing(loc, "\[Radio\] - Not on.") - return // the device has to be on - // Fix for permacell radios, but kinda eh about actually fixing them. - if(!speech_orig.speaker || !speech_orig.message) - say_testing(loc, "\[Radio\] - speech.speaker or speech.message are null. [speech_orig.speaker], [html_encode(speech_orig.message)]") - return - - // Uncommenting this. To the above comment: - // The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom - if(isWireCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact - say_testing(loc, "\[Radio\] - TRANSMIT wire cut.") - return - - if(!speech_orig.speaker.IsVocal()) - say_testing(loc, "\[Radio\] - Speaker not vocal.") - return - - /* Quick introduction: - This new radio system uses a very robust FTL signaling technology unoriginally - dubbed "subspace" which is somewhat similar to 'blue-space' but can't - actually transmit large mass. Headsets are the only radio devices capable - of sending subspace transmissions to the Communications Satellite. - A headset sends a signal to a subspace listener/reciever elsewhere in space, - the signal gets processed and logged, and an audible transmission gets sent - to each individual headset. - */ - - /* - be prepared to disregard any comments in all of tcomms code. i tried my best to keep them somewhat up-to-date, but eh - */ - var/datum/speech/speech=speech_orig.clone() - speech.radio=src - #ifdef SAY_DEBUG - var/msgclasses = speech.render_message_classes(", ") - var/wrapclasses = speech.render_wrapper_classes(", ") - say_testing(loc, "\[Radio\] - Cloned speech - language=[speech.language], message_classes={[msgclasses]}, wrapper_classes={[wrapclasses]}") - #endif - - var/skip_freq_search=0 - switch(channel) - if(MODE_HEADSET,null) // Used for ";" prefix, which always sends to src.frequency. - say_testing(loc, "\[Radio\] - channel=[channel]; Forcing frequency to be [frequency].") - speech.frequency = src.frequency - channel = null - skip_freq_search=1 - if(MODE_SECURE_HEADSET) // Secure headset (?) - channel = 1 // Always pick the first channel...? - - - if(!skip_freq_search) - if(channel && channels && channels.len > 0) - if(channel == "department") - channel = channels[1] - speech.frequency = secure_radio_connections[channel] - if(!channels[channel]) - say_testing(loc, "\[Radio\] - Unable to find channel \"[channel]\".") - returnToPool(speech) - return - else - speech.frequency = frequency - channel = null - - say_testing(loc, "talk_into(): frequency set to [speech.frequency]") - - var/turf/position = get_turf(src) - - //#### Tagging the signal with all appropriate identity values ####// - - // ||-- The mob's name identity --|| - var/real_name = speech.name // mob's real name - var/mobkey = "none" // player key associated with mob - var/voicemask = 0 // the speaker is wearing a voice mask - var/voice = speech.speaker.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already - if(ismob(speech.speaker)) - var/mob/speaker = speech.speaker - real_name = speaker.real_name - if(speaker.client) - mobkey = speaker.key // assign the mob's key - - // --- Human: use their actual job --- - if (ishuman(speech.speaker)) - if(voice != real_name) - voicemask = 1 - speech.job = speech.speaker:get_assignment() - - // --- Carbon Nonhuman --- - else if (iscarbon(speech.speaker)) // Nonhuman carbon mob - speech.job = "No id" - - // --- AI --- - else if (isAI(speech.speaker)) - speech.job = "AI" - - // --- Cyborg --- - else if (isrobot(speech.speaker)) - speech.job = "Cyborg" - - // --- Personal AI (pAI) --- - else if (istype(speech.speaker, /mob/living/silicon/pai)) - speech.job = "Personal AI" - - // --- Cold, emotionless machines. --- - else if(isobj(speech.speaker)) - speech.job = "Machine" - - // --- Unidentifiable mob --- - else - speech.job = "Unknown" - -/* - // --- Modifications to the mob's identity --- - - // The mob is disguising their identity: - if (ishuman(M) && M.GetVoice() != real_name) - displayname = M.GetVoice() - jobname = "Unknown" - voicemask = 1 -*/ - - - /* ###### Radio headsets can only broadcast through subspace ###### */ - - if(subspace_transmission) - // First, we want to generate a new radio signal - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 2 // 2 would be a subspace transmission. - // transmission_method could probably be enumerated through #define. Would be neater. - - // --- Finally, tag the actual signal with the appropriate values --- - signal.data = list( - // Identity-associated tags: - "mob" = speech.speaker, // store a reference to the mob - "mobtype" = speech.speaker.type, // the mob's type - "realname" = real_name, // the mob's real name - "name" = voice, // the mob's voice name - "job" = speech.job, // the mob's job - "key" = mobkey, // the mob's key - "vmask" = voicemask, // 1 if the mob is using a voice gas mask - - // We store things that would otherwise be kept in the actual mob - // so that they can be logged even AFTER the mob is deleted or something - - // Other tags: - "compression" = rand(45,50), // compressed radio signal - "message" = speech.message, // the actual sent message - "radio" = src, // stores the radio used for transmission - "slow" = 0, // how much to sleep() before broadcasting - simulates net lag - "traffic" = 0, // dictates the total traffic sum that the signal went through - "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 - "language" = speech.language, //The language M is talking in. - - "r_quote" = speech.rquote, - "l_quote" = speech.lquote, - - "message_classes" = speech.message_classes.Copy(), - "wrapper_classes" = speech.wrapper_classes.Copy() - ) - signal.frequency = speech.frequency // Quick frequency set - - say_testing(loc, "talk_into(): subspace signal frequency set to [signal.frequency]") - - //#### Sending the signal to all subspace receivers ####// - - for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) - - // Allinone can act as receivers. - for(var/obj/machinery/telecomms/allinone/R in telecomms_list) - R.receive_signal(signal) - - // Receiving code can be located in Telecommunications.dm - returnToPool(speech) - return - - - /* ###### Intercoms and station-bounced radios ###### */ - - var/filter_type = 2 - - /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */ - if(istype(src, /obj/item/device/radio/intercom)) - filter_type = 1 - - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.transmission_method = 2 - - - /* --- Try to send a normal subspace broadcast first */ - - signal.data = list( - - "mob" = speech.speaker, // store a reference to the mob - "mobtype" = speech.speaker.type, // the mob's type - "realname" = real_name, // the mob's real name - "name" = voice, // the mob's display name - "job" = speech.job, // the mob's job - "key" = mobkey, // the mob's key - "vmask" = voicemask, // 1 if the mob is using a voice gas mas - - "compression" = 0, // uncompressed radio signal - "message" = speech.message, // the actual sent message - "radio" = src, // stores the radio used for transmission - "slow" = 0, - "traffic" = 0, - "type" = 0, - "server" = null, - "reject" = 0, - "level" = position.z, - "language" = speech.language, - - "r_quote" = speech.rquote, - "l_quote" = speech.lquote, - - "message_classes" = speech.message_classes.Copy(), - "wrapper_classes" = speech.wrapper_classes.Copy(), - ) - signal.frequency = speech.frequency // Quick frequency set - - say_testing(loc, "talk_into(): subspace signal frequency set to [signal.frequency]") - - for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) - - spawn(rand(10,25)) // wait a little... - - if(signal.data["done"] && position.z in signal.data["level"]) - // we're done here. - returnToPool(speech) - return - - // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level. - // Send a mundane broadcast with limited targets: - Broadcast_Message(speech, voicemask, filter_type, signal.data["compression"], list(position.z)) - returnToPool(speech) - -/obj/item/device/radio/Hear(var/datum/speech/speech, var/rendered_speech="") - if(!speech.speaker || speech.frequency) - return - if (broadcasting) - if(get_dist(src, speech.speaker) <= canhear_range) - talk_into(speech) -/* -/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message) - - - if ((R.frequency == frequency && message)) - return 1 - else if - - else - return null - return -*/ - - -/obj/item/device/radio/proc/receive_range(freq, level) - // check if this radio can receive on the given frequency, and if so, - // what the range is in which mobs will hear the radio - // returns: -1 if can't receive, range otherwise - - if (isWireCut(WIRE_RECEIVE)) - return -1 - if(!listening) - return -1 - if(!(0 in level)) - var/turf/position = get_turf(src) - if(!position || !(position.z in level)) - return -1 - if(freq == SYND_FREQ) - if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys - return -1 - if (!on) - return -1 - if (!freq) //recieved on main frequency - if (!listening) - return -1 - else - var/accept = (freq==frequency && listening) - if (!accept) - for (var/ch_name in channels) - if(channels[ch_name] & FREQ_LISTENING) - if(radiochannels[ch_name] == text2num(freq) || syndie) - accept = 1 - break - if (!accept) - return -1 - return canhear_range - -/obj/item/device/radio/proc/send_hear(freq, level) - - - var/range = receive_range(freq, level) - if(range > -1) - return get_hearers_in_view(canhear_range, src) - - -/obj/item/device/radio/examine(mob/user) - ..() - if (b_stat) - user.show_message("\The [src] can be attached and modified!") - else - user.show_message("\The [src] can not be modified or attached!") - -/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - user.set_machine(src) - if (!( istype(W, /obj/item/weapon/screwdriver) )) - return - b_stat = !( b_stat ) - if (b_stat) - user.show_message("\The [src] can now be attached and modified!") - else - user.show_message("\The [src] can no longer be modified or attached!") - updateDialog() - add_fingerprint(user) - -/obj/item/device/radio/emp_act(severity) - broadcasting = 0 - listening = 0 - for (var/ch_name in channels) - channels[ch_name] = 0 - ..() + channel = channels[1] + connection = secure_radio_connections[channel] + else + connection = radio_connection + channel = null + if (!istype(connection)) + return + if (!connection) + return + + var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(src, null, null, 1) + Broadcast_Message(connection, all_languages["Sol Common"], A, + 0, "*garbled automated announcement*", src, + message, from, "Automated Announcement", from, "synthesized voice", + 4, 0, list(1), 1459) + del(A) + return + +*/ + +/obj/item/device/radio/talk_into(var/datum/speech/speech_orig, var/channel=null) + say_testing(loc, "\[Radio\] - Got radio/talk_into([html_encode(speech_orig.message)], [channel!=null ? channel : "null"]).") + if(!on) + say_testing(loc, "\[Radio\] - Not on.") + return // the device has to be on + // Fix for permacell radios, but kinda eh about actually fixing them. + if(!speech_orig.speaker || !speech_orig.message) + say_testing(loc, "\[Radio\] - speech.speaker or speech.message are null. [speech_orig.speaker], [html_encode(speech_orig.message)]") + return + + // Uncommenting this. To the above comment: + // The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom + if(isWireCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact + say_testing(loc, "\[Radio\] - TRANSMIT wire cut.") + return + + if(!speech_orig.speaker.IsVocal()) + say_testing(loc, "\[Radio\] - Speaker not vocal.") + return + + /* Quick introduction: + This new radio system uses a very robust FTL signaling technology unoriginally + dubbed "subspace" which is somewhat similar to 'blue-space' but can't + actually transmit large mass. Headsets are the only radio devices capable + of sending subspace transmissions to the Communications Satellite. + A headset sends a signal to a subspace listener/reciever elsewhere in space, + the signal gets processed and logged, and an audible transmission gets sent + to each individual headset. + */ + + /* + be prepared to disregard any comments in all of tcomms code. i tried my best to keep them somewhat up-to-date, but eh + */ + var/datum/speech/speech=speech_orig.clone() + speech.radio=src + #ifdef SAY_DEBUG + var/msgclasses = speech.render_message_classes(", ") + var/wrapclasses = speech.render_wrapper_classes(", ") + say_testing(loc, "\[Radio\] - Cloned speech - language=[speech.language], message_classes={[msgclasses]}, wrapper_classes={[wrapclasses]}") + #endif + + var/skip_freq_search=0 + switch(channel) + if(MODE_HEADSET,null) // Used for ";" prefix, which always sends to src.frequency. + say_testing(loc, "\[Radio\] - channel=[channel]; Forcing frequency to be [frequency].") + speech.frequency = src.frequency + channel = null + skip_freq_search=1 + if(MODE_SECURE_HEADSET) // Secure headset (?) + channel = 1 // Always pick the first channel...? + + + if(!skip_freq_search) + if(channel && channels && channels.len > 0) + if(channel == "department") + channel = channels[1] + speech.frequency = secure_radio_connections[channel] + if(!channels[channel]) + say_testing(loc, "\[Radio\] - Unable to find channel \"[channel]\".") + returnToPool(speech) + return + else + speech.frequency = frequency + channel = null + + say_testing(loc, "talk_into(): frequency set to [speech.frequency]") + + var/turf/position = get_turf(src) + + //#### Tagging the signal with all appropriate identity values ####// + + // ||-- The mob's name identity --|| + var/real_name = speech.name // mob's real name + var/mobkey = "none" // player key associated with mob + var/voicemask = 0 // the speaker is wearing a voice mask + var/voice = speech.speaker.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already + if(ismob(speech.speaker)) + var/mob/speaker = speech.speaker + real_name = speaker.real_name + if(speaker.client) + mobkey = speaker.key // assign the mob's key + + // --- Human: use their actual job --- + if (ishuman(speech.speaker)) + if(voice != real_name) + voicemask = 1 + speech.job = speech.speaker:get_assignment() + + // --- Carbon Nonhuman --- + else if (iscarbon(speech.speaker)) // Nonhuman carbon mob + speech.job = "No id" + + // --- AI --- + else if (isAI(speech.speaker)) + speech.job = "AI" + + // --- Cyborg --- + else if (isrobot(speech.speaker)) + speech.job = "Cyborg" + + // --- Personal AI (pAI) --- + else if (istype(speech.speaker, /mob/living/silicon/pai)) + speech.job = "Personal AI" + + // --- Cold, emotionless machines. --- + else if(isobj(speech.speaker)) + speech.job = "Machine" + + // --- Unidentifiable mob --- + else + speech.job = "Unknown" + +/* + // --- Modifications to the mob's identity --- + + // The mob is disguising their identity: + if (ishuman(M) && M.GetVoice() != real_name) + displayname = M.GetVoice() + jobname = "Unknown" + voicemask = 1 +*/ + + + /* ###### Radio headsets can only broadcast through subspace ###### */ + + if(subspace_transmission) + // First, we want to generate a new radio signal + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 2 // 2 would be a subspace transmission. + // transmission_method could probably be enumerated through #define. Would be neater. + + // --- Finally, tag the actual signal with the appropriate values --- + signal.data = list( + // Identity-associated tags: + "mob" = speech.speaker, // store a reference to the mob + "mobtype" = speech.speaker.type, // the mob's type + "realname" = real_name, // the mob's real name + "name" = voice, // the mob's voice name + "job" = speech.job, // the mob's job + "key" = mobkey, // the mob's key + "vmask" = voicemask, // 1 if the mob is using a voice gas mask + + // We store things that would otherwise be kept in the actual mob + // so that they can be logged even AFTER the mob is deleted or something + + // Other tags: + "compression" = rand(45,50), // compressed radio signal + "message" = speech.message, // the actual sent message + "radio" = src, // stores the radio used for transmission + "slow" = 0, // how much to sleep() before broadcasting - simulates net lag + "traffic" = 0, // dictates the total traffic sum that the signal went through + "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 + "language" = speech.language, //The language M is talking in. + + "r_quote" = speech.rquote, + "l_quote" = speech.lquote, + + "message_classes" = speech.message_classes.Copy(), + "wrapper_classes" = speech.wrapper_classes.Copy() + ) + signal.frequency = speech.frequency // Quick frequency set + + say_testing(loc, "talk_into(): subspace signal frequency set to [signal.frequency]") + + //#### Sending the signal to all subspace receivers ####// + + for(var/obj/machinery/telecomms/receiver/R in telecomms_list) + R.receive_signal(signal) + + // Allinone can act as receivers. + for(var/obj/machinery/telecomms/allinone/R in telecomms_list) + R.receive_signal(signal) + + // Receiving code can be located in Telecommunications.dm + returnToPool(speech) + return + + + /* ###### Intercoms and station-bounced radios ###### */ + + var/filter_type = 2 + + /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */ + if(istype(src, /obj/item/device/radio/intercom)) + filter_type = 1 + + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.transmission_method = 2 + + + /* --- Try to send a normal subspace broadcast first */ + + signal.data = list( + + "mob" = speech.speaker, // store a reference to the mob + "mobtype" = speech.speaker.type, // the mob's type + "realname" = real_name, // the mob's real name + "name" = voice, // the mob's display name + "job" = speech.job, // the mob's job + "key" = mobkey, // the mob's key + "vmask" = voicemask, // 1 if the mob is using a voice gas mas + + "compression" = 0, // uncompressed radio signal + "message" = speech.message, // the actual sent message + "radio" = src, // stores the radio used for transmission + "slow" = 0, + "traffic" = 0, + "type" = 0, + "server" = null, + "reject" = 0, + "level" = position.z, + "language" = speech.language, + + "r_quote" = speech.rquote, + "l_quote" = speech.lquote, + + "message_classes" = speech.message_classes.Copy(), + "wrapper_classes" = speech.wrapper_classes.Copy(), + ) + signal.frequency = speech.frequency // Quick frequency set + + say_testing(loc, "talk_into(): subspace signal frequency set to [signal.frequency]") + + for(var/obj/machinery/telecomms/receiver/R in telecomms_list) + R.receive_signal(signal) + + spawn(rand(10,25)) // wait a little... + + if(signal.data["done"] && position.z in signal.data["level"]) + // we're done here. + returnToPool(speech) + return + + // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level. + // Send a mundane broadcast with limited targets: + Broadcast_Message(speech, voicemask, filter_type, signal.data["compression"], list(position.z)) + returnToPool(speech) + +/obj/item/device/radio/Hear(var/datum/speech/speech, var/rendered_speech="") + if(!speech.speaker || speech.frequency) + return + if (broadcasting) + if(get_dist(src, speech.speaker) <= canhear_range) + talk_into(speech) +/* +/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message) + + + if ((R.frequency == frequency && message)) + return 1 + else if + + else + return null + return +*/ + + +/obj/item/device/radio/proc/receive_range(freq, level) + // check if this radio can receive on the given frequency, and if so, + // what the range is in which mobs will hear the radio + // returns: -1 if can't receive, range otherwise + + if (isWireCut(WIRE_RECEIVE)) + return -1 + if(!listening) + return -1 + if(!(0 in level)) + var/turf/position = get_turf(src) + if(!position || !(position.z in level)) + return -1 + if(freq == SYND_FREQ) + if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys + return -1 + if (!on) + return -1 + if (!freq) //recieved on main frequency + if (!listening) + return -1 + else + var/accept = (freq==frequency && listening) + if (!accept) + for (var/ch_name in channels) + if(channels[ch_name] & FREQ_LISTENING) + if(radiochannels[ch_name] == text2num(freq) || syndie) + accept = 1 + break + if (!accept) + return -1 + return canhear_range + +/obj/item/device/radio/proc/send_hear(freq, level) + + + var/range = receive_range(freq, level) + if(range > -1) + return get_hearers_in_view(canhear_range, src) + + +/obj/item/device/radio/examine(mob/user) + ..() + if (b_stat) + user.show_message("\The [src] can be attached and modified!") + else + user.show_message("\The [src] can not be modified or attached!") + +/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + user.set_machine(src) + if (!( istype(W, /obj/item/weapon/screwdriver) )) + return + b_stat = !( b_stat ) + if (b_stat) + user.show_message("\The [src] can now be attached and modified!") + else + user.show_message("\The [src] can no longer be modified or attached!") + updateDialog() + add_fingerprint(user) + +/obj/item/device/radio/emp_act(severity) + broadcasting = 0 + listening = 0 + for (var/ch_name in channels) + channels[ch_name] = 0 + ..() diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 8c568ae27e4..6c3de14581d 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -1,475 +1,475 @@ -/* -CONTAINS: -T-RAY -HEALTH ANALYZER -GAS ANALYZER -MASS SPECTROMETER -REAGENT SCANNER -*/ - -/obj/item/device/t_scanner - name = "T-ray scanner" - desc = "A terahertz-ray emitter and scanner that can pick up the faintest traces of energy, used to detect the invisible." - icon_state = "t-ray0" - flags = FPRINT - slot_flags = SLOT_BELT - w_class = 2 - item_state = "electronic" - starting_materials = list(MAT_IRON = 150, MAT_GLASS = 50) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - origin_tech = "magnets=1;engineering=1" - - var/on = 0 - var/base_state = "t-ray" - var/ray_range = 1 - -/obj/item/device/t_scanner/Destroy() - if(on) - processing_objects.Remove(src) - ..() - -/obj/item/device/t_scanner/attack_self(mob/user) - - on = !on - icon_state = "[base_state][on]" - - if(on) - processing_objects.Add(src) - - -/obj/item/device/t_scanner/process() - if(!on) - processing_objects.Remove(src) - return null - - for(var/turf/T in trange(ray_range, get_turf(src))) - - if(!T.intact) - continue - - for(var/obj/O in T.contents) - - if(O.level != 1) - continue - - if(O.invisibility == 101) - O.invisibility = 0 - spawn(10) - if(O) - var/turf/U = O.loc - if(U && U.intact) - O.invisibility = 101 - for(var/mob/living/M in T.contents) - var/oldalpha = M.alpha - if(M.alpha < 255 && istype(M)) - M.alpha = 255 - spawn(10) - if(M) - M.alpha = oldalpha - - var/mob/living/M = locate() in T - if(M && M.invisibility == 2) - M.invisibility = 0 - spawn(10) - if(M) - M.invisibility = INVISIBILITY_LEVEL_TWO - -/obj/item/device/healthanalyzer - name = "health analyzer" - icon_state = "health" - item_state = "analyzer" - desc = "A hand-held body scanner able to distinguish vital signs of the subject." - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throwforce = 3 - w_class = 1.0 - throw_speed = 5 - starting_materials = list(MAT_IRON = 200) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - origin_tech = "magnets=1;biotech=1" - var/last_reading = null - var/mode = 1 - -/obj/item/device/healthanalyzer/attack(mob/living/M as mob, mob/living/user as mob) - if(!user.hallucinating()) - last_reading = healthanalyze(M, user, mode) - else - if(M.isDead()) - user.show_message("\The [src] beeps, \"It's dead, Jim.\"", MESSAGE_HEAR ,"\The [src] glows black.") - else - to_chat(user, "\The [src] glows [pick("red", "green", "blue", "pink")]! You wonder what that would mean.") - src.add_fingerprint(user) - -/obj/item/device/healthanalyzer/attack_self(mob/living/user as mob) - . = ..() - if(.) - return - if(!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - if(last_reading) - to_chat(user, "Accessing Prior Scan Result") - to_chat(user, last_reading) - -//Note : Used directly by other objects. Could benefit of OOP, maybe ? -proc/healthanalyze(mob/living/M as mob, mob/living/user as mob, var/mode = 0, var/skip_checks = 0, var/silent = 0) - var/message = "" - if(!skip_checks) - if(((M_CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) - user.visible_message("[user] analyzes the floor's vitals!", \ - "You analyze the floor's vitals!") - playsound(user, 'sound/items/healthanalyzer.ogg', 50, 1) - to_chat(user, {"Analyzing Results for the floor:
    Overall Status: Healthy
    -Key: Suffocation/Toxin/Burns/Brute -Damage Specifics: 0 - 0 - 0 - 0 -Body Temperature: ???°C (???°F) -Localized Damage, Brute/Burn: -No limb damage detected. -Subject bloodstream oxygen level normal | Subject bloodstream toxin level normal | Subject burn injury status clear | Subject brute injury status clear -Blood Level Unknown: ???% ???cl -Subject's pulse: ??? BPM"}) - return - if(!silent) - user.visible_message("[user] analyzes [M]'s vitals.", \ - "You analyze [M]'s vitals.") - playsound(user, 'sound/items/healthanalyzer.ogg', 50, 1) - var/fake_oxy = max(rand(1, 40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss()))) - var/OX = M.getOxyLoss() > 50 ? "[M.getOxyLoss()]" : M.getOxyLoss() - var/TX = M.getToxLoss() > 50 ? "[M.getToxLoss()]" : M.getToxLoss() - var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss() - var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss() - if(M.status_flags & FAKEDEATH) - OX = fake_oxy > 50 ? "[fake_oxy]" : fake_oxy - message += "Analyzing Results for [M]:
    Overall Status: Dead

    " - else - message += "
    Analyzing Results for [M]:
    Overall Status: [M.stat > 1 ? "Dead" : "[M.health - M.halloss]% Healthy"]
    " - message += "
    Key: Suffocation/Toxin/Burns/Brute" - message += "
    Damage Specifics: [OX] - [TX] - [BU] - [BR]" - message += "
    Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)" - if(M.tod && M.isDead()) - message += "
    Time of Death: [M.tod]" - if(istype(M, /mob/living/carbon/human) && mode) - var/mob/living/carbon/human/H = M - var/list/damaged = H.get_damaged_organs(1, 1) - message += "
    Localized Damage, Brute/Burn:" - if(length(damaged)) - for(var/datum/organ/external/org in damaged) - var/organ_msg = "
    " - organ_msg += capitalize(org.display_name) - organ_msg += ": " - organ_msg += "[org.brute_dam ? org.brute_dam : 0]" - organ_msg += "/[org.burn_dam ? org.burn_dam : 0]" - if(org.status & ORGAN_BLEEDING) - organ_msg += "\[BLEEDING\]" - if(org.status & org.is_peg()) - organ_msg += "\[WOOD DETECTED?\]" - if(org.status & org.is_robotic()) - organ_msg += "\[METAL DETECTED?\]" - message += organ_msg - else - message += "
    No limb damage detected." - - OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" - TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level normal" - BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status clear" - BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute injury status clear" - if(M.status_flags & FAKEDEATH) - OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" - message += ("
    [OX] | [TX] | [BU] | [BR]") - - if(M.reagents.total_volume) - message += "
    Warning: Unknown substance detected in subject's blood." - if(hardcore_mode_on && ishuman(M) && eligible_for_hardcore_mode(M)) - var/mob/living/carbon/human/H = M - if(H.nutrition < STARVATION_MIN) - message += "
    Warning: Severe lack of essential nutriments detected in subject's blood." - - if(iscarbon(M)) - var/mob/living/carbon/C = M - if(C.virus2.len) - for(var/ID in C.virus2) - if(ID in virusDB) - var/datum/data/record/V = virusDB[ID] - message += "
    Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]" - //Canned out to make viruses much harder to notice, I suppose. Too bad we can't port a single functional virus code with visibility stats already - //else - //user.show_message(text("Warning: Unknown pathogen detected in subject's blood.")) - - if(M.getCloneLoss()) - message += "
    Subject appears to have been imperfectly cloned." - for(var/datum/disease/D in M.viruses) - if(!D.hidden[SCANNER]) - message += "
    Warning: [D.form] Detected
    Name: [D.name].
    Type: [D.spread].
    Stage: [D.stage]/[D.max_stages].
    Possible Cure: [D.cure]
    " - if(M.reagents && M.reagents.get_reagent_amount("inaprovaline")) - message += "
    Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals." - if(M.has_brain_worms()) - message += "
    Strange MRI readout. Subject needs further scanning." - else if(M.getBrainLoss() >= 100 || !M.has_brain()) - message += "
    No brain activity has been detected. Subject is braindead." - else if(M.getBrainLoss() >= 60) - message += "
    Severe brain damage detected. Subject likely to have mental retardation." - else if(M.getBrainLoss() >= 10) - message += "
    Significant brain damage detected. Subject may have had a concussion." - if(ishuman(M)) - var/mob/living/carbon/human/H = M - for(var/name in H.organs_by_name) - var/datum/organ/external/e = H.organs_by_name[name] - var/limb = e.display_name - /* - * Doesn't belong here, only the advanced scanner can locate fractures - if(e.is_broken()) - if((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) //Only these limbs can be splinted - message += "
    Unsecured fracture in subject's [limb]. Splinting recommended for transport." - */ - if(e.has_infected_wound()) - message += "
    Infected wound detected in subject's [limb]. Disinfection recommended." - - for(var/name in H.organs_by_name) - var/datum/organ/external/e = H.organs_by_name[name] - if(e.is_broken()) - message += text("
    Bone fractures detected. Advanced scan required for location.") - break - for(var/datum/organ/external/e in H.organs) - for(var/datum/wound/W in e.wounds) - if(W.internal) - message += text("
    Internal bleeding detected. Advanced scan required for location.") - break - if(H.vessel) - var/blood_volume = round(H.vessel.get_reagent_amount("blood")) - var/blood_percent = round((blood_volume / 560) * 100) - switch(blood_volume) - if(BLOOD_VOLUME_SAFE to 1000000000) - message += "
    Blood Level Normal: [blood_percent]% ([blood_volume]cl)" - if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) - message += "
    Warning: Blood Level Low: [blood_percent]% [blood_volume]cl" //Still about fine - if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) - message += "
    Danger: Blood Level Serious: [blood_percent]% [blood_volume]cl" - if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) - message += "
    Danger: Blood Level Critical: [blood_percent]% [blood_volume]cl" - if(-1000000000 to BLOOD_VOLUME_SURVIVE) - message += "
    Danger: Blood Level Fatal: [blood_percent]% [blood_volume]cl" - message += "
    Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] BPM" - to_chat(user, message)//Here goes - - return message //To read last scan - -/obj/item/device/healthanalyzer/verb/toggle_mode() - set name = "Switch mode" - set category = "Object" - - mode = !mode - to_chat(usr, "The scanner will [mode ? "now show specific limb damage" : "no longer show specific limb damage"].") - -/obj/item/device/analyzer - desc = "A hand-held environment scanner which reports data about gas mixtures." - name = "atmospheric analyzer" - icon_state = "atmos" - item_state = "analyzer" - w_class = 2.0 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - starting_materials = list(MAT_IRON = 30, MAT_GLASS = 20) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - origin_tech = "magnets=1;engineering=1" - -/obj/item/device/analyzer/attack_self(mob/user as mob) - - . = ..() - if(.) - return - - if(!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - - var/turf/location = get_turf(user) - - if(!location) //Somehow - return - - var/datum/gas_mixture/environment = location.return_air() - - user << output_gas_scan(environment, location, 1) - - src.add_fingerprint(user) - return - -//If human_standard is enabled, the message will be formatted to show which values are dangerous -/obj/item/device/analyzer/proc/output_gas_scan(var/datum/gas_mixture/scanned, var/atom/container, human_standard = 1) - if(!scanned) - return "No gas mixture found." - scanned.update_values() - var/pressure = scanned.return_pressure() - var/total_moles = scanned.total_moles() - var/message = "" - if(!container || istype(container, /turf)) - message += "Results:" - else - message += "\icon [container] Results of [container] scan:" - if(total_moles) - message += "
    [human_standard && abs(pressure - ONE_ATMOSPHERE) > 10 ? "" : ""] Pressure: [round(pressure, 0.1)] kPa" - var/o2_concentration = scanned.oxygen/total_moles - var/n2_concentration = scanned.nitrogen/total_moles - var/co2_concentration = scanned.carbon_dioxide/total_moles - var/plasma_concentration = scanned.toxins/total_moles - - var/unknown_concentration = 1 - (o2_concentration + n2_concentration + co2_concentration + plasma_concentration) - - if(n2_concentration > 0.01) - message += "
    [human_standard && abs(n2_concentration - N2STANDARD) > 20 ? "" : ""] Nitrogen: [round(scanned.nitrogen, 0.1)] mol, [round(n2_concentration*100)]%" - if(o2_concentration > 0.01) - message += "
    [human_standard && abs(o2_concentration - O2STANDARD) > 2 ? "" : ""] Oxygen: [round(scanned.oxygen, 0.1)] mol, [round(o2_concentration*100)]%" - if(co2_concentration > 0.01) - message += "
    [human_standard ? "" : ""] CO2: [round(scanned.carbon_dioxide, 0.1)] mol, [round(co2_concentration*100)]%" - if(plasma_concentration > 0.01) - message += "
    [human_standard ? "" : ""] Plasma: [round(scanned.toxins, 0.1)] mol, [round(plasma_concentration*100)]%" - if(unknown_concentration > 0.01) - message += "
    Unknown: [round(unknown_concentration*100)]%" - - message += "
    [human_standard && !(scanned.temperature in range(BODYTEMP_COLD_DAMAGE_LIMIT, BODYTEMP_HEAT_DAMAGE_LIMIT)) ? "" : ""] Temperature: [round(scanned.temperature-T0C)]°C" - else - message += "
    No gasses detected[container && !istype(container, /turf) ? " in \the [container]." : ""]!" - return message - -/obj/item/device/mass_spectrometer - desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample." - name = "mass-spectrometer" - icon_state = "spectrometer" - item_state = "analyzer" - w_class = 2.0 - flags = FPRINT | OPENCONTAINER - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - starting_materials = list(MAT_IRON = 30, MAT_GLASS = 20) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=2;biotech=2" - var/details = 0 - -/obj/item/device/mass_spectrometer/New() - . = ..() - create_reagents(5) - -/obj/item/device/mass_spectrometer/on_reagent_change() - if(reagents.total_volume) - icon_state = initial(icon_state) + "_s" - else - icon_state = initial(icon_state) - -/obj/item/device/mass_spectrometer/attack(mob/living/M as mob, mob/living/user as mob) - if(!M.reagents) - return - if(iscarbon(M)) - var/mob/living/carbon/C = M - if(reagents.total_volume) - to_chat(user, "This device already has a blood sample!") - return - if(!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - if(!C.dna) - return - if(M_NOCLONE in C.mutations) - return - - var/datum/reagent/B = C.take_blood(src, src.reagents.maximum_volume) - if(B) - src.reagents.reagent_list |= B - src.reagents.update_total() - src.on_reagent_change() - src.reagents.handle_reactions() - update_icon() - user.visible_message("[user] takes a blood sample from [C].", \ - "You take a blood sample from [C]") - playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) //It uses the same thing as the hypospray, in reverse. SCIENCE! - -/obj/item/device/mass_spectrometer/attack_self(mob/user as mob) - . = ..() - if(.) - return - - if(!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - if(reagents.total_volume) - var/list/blood_traces = list() - for(var/datum/reagent/R in reagents.reagent_list) - if(R.id != "blood") - reagents.clear_reagents() - to_chat(user, "The sample was contaminated! Please insert another sample.") - return - else - blood_traces = params2list(R.data["trace_chem"]) - break - var/dat - if(blood_traces.len) - dat = "Trace Chemicals Found:" - for(var/R in blood_traces) - dat += "
    [R] [details ? "([blood_traces[R]] units)":""]" - else - dat = "No trace chemicals found in the sample." - to_chat(user, "[dat]") - reagents.clear_reagents() - return - -/obj/item/device/mass_spectrometer/adv - name = "advanced mass-spectrometer" - icon_state = "adv_spectrometer" - details = 1 - origin_tech = "magnets=4;biotech=2" - -/obj/item/device/reagent_scanner - name = "reagent scanner" - desc = "A hand-held reagent scanner which identifies chemical agents." - icon_state = "spectrometer" - item_state = "analyzer" - w_class = 2.0 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - starting_materials = list(MAT_IRON = 30, MAT_GLASS = 20) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=2;biotech=2" - var/details = 0 - var/recent_fail = 0 - -/obj/item/device/reagent_scanner/afterattack(obj/O, mob/user as mob) - . = ..() - if(.) - return - if(!istype(O)) //Wrong type sent - return - if(!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - if(O.reagents) - var/dat = "" - if(O.reagents.reagent_list.len) - for(var/datum/reagent/R in O.reagents.reagent_list) - var/reagent_percent = (R.volume/O.reagents.total_volume)*100 - dat += "
    [R] [details ? "([R.volume] units, [reagent_percent]%)" : ""]" - if(dat) - to_chat(user, "Chemicals found in \the [O]:[dat]") - else - to_chat(user, "No active chemical agents found in \the [O].") - - return - -/obj/item/device/reagent_scanner/adv - name = "advanced reagent scanner" - icon_state = "adv_spectrometer" - details = 1 - origin_tech = "magnets=4;biotech=2" +/* +CONTAINS: +T-RAY +HEALTH ANALYZER +GAS ANALYZER +MASS SPECTROMETER +REAGENT SCANNER +*/ + +/obj/item/device/t_scanner + name = "T-ray scanner" + desc = "A terahertz-ray emitter and scanner that can pick up the faintest traces of energy, used to detect the invisible." + icon_state = "t-ray0" + flags = FPRINT + slot_flags = SLOT_BELT + w_class = 2 + item_state = "electronic" + starting_materials = list(MAT_IRON = 150, MAT_GLASS = 50) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + origin_tech = "magnets=1;engineering=1" + + var/on = 0 + var/base_state = "t-ray" + var/ray_range = 1 + +/obj/item/device/t_scanner/Destroy() + if(on) + processing_objects.Remove(src) + ..() + +/obj/item/device/t_scanner/attack_self(mob/user) + + on = !on + icon_state = "[base_state][on]" + + if(on) + processing_objects.Add(src) + + +/obj/item/device/t_scanner/process() + if(!on) + processing_objects.Remove(src) + return null + + for(var/turf/T in trange(ray_range, get_turf(src))) + + if(!T.intact) + continue + + for(var/obj/O in T.contents) + + if(O.level != 1) + continue + + if(O.invisibility == 101) + O.invisibility = 0 + spawn(10) + if(O) + var/turf/U = O.loc + if(U && U.intact) + O.invisibility = 101 + for(var/mob/living/M in T.contents) + var/oldalpha = M.alpha + if(M.alpha < 255 && istype(M)) + M.alpha = 255 + spawn(10) + if(M) + M.alpha = oldalpha + + var/mob/living/M = locate() in T + if(M && M.invisibility == 2) + M.invisibility = 0 + spawn(10) + if(M) + M.invisibility = INVISIBILITY_LEVEL_TWO + +/obj/item/device/healthanalyzer + name = "health analyzer" + icon_state = "health" + item_state = "analyzer" + desc = "A hand-held body scanner able to distinguish vital signs of the subject." + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 3 + w_class = 1.0 + throw_speed = 5 + starting_materials = list(MAT_IRON = 200) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + origin_tech = "magnets=1;biotech=1" + var/last_reading = null + var/mode = 1 + +/obj/item/device/healthanalyzer/attack(mob/living/M as mob, mob/living/user as mob) + if(!user.hallucinating()) + last_reading = healthanalyze(M, user, mode) + else + if(M.isDead()) + user.show_message("\The [src] beeps, \"It's dead, Jim.\"", MESSAGE_HEAR ,"\The [src] glows black.") + else + to_chat(user, "\The [src] glows [pick("red", "green", "blue", "pink")]! You wonder what that would mean.") + src.add_fingerprint(user) + +/obj/item/device/healthanalyzer/attack_self(mob/living/user as mob) + . = ..() + if(.) + return + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + if(last_reading) + to_chat(user, "Accessing Prior Scan Result") + to_chat(user, last_reading) + +//Note : Used directly by other objects. Could benefit of OOP, maybe ? +proc/healthanalyze(mob/living/M as mob, mob/living/user as mob, var/mode = 0, var/skip_checks = 0, var/silent = 0) + var/message = "" + if(!skip_checks) + if(((M_CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) + user.visible_message("[user] analyzes the floor's vitals!", \ + "You analyze the floor's vitals!") + playsound(user, 'sound/items/healthanalyzer.ogg', 50, 1) + to_chat(user, {"Analyzing Results for the floor:
    Overall Status: Healthy
    +Key: Suffocation/Toxin/Burns/Brute +Damage Specifics: 0 - 0 - 0 - 0 +Body Temperature: ???°C (???°F) +Localized Damage, Brute/Burn: +No limb damage detected. +Subject bloodstream oxygen level normal | Subject bloodstream toxin level normal | Subject burn injury status clear | Subject brute injury status clear +Blood Level Unknown: ???% ???cl +Subject's pulse: ??? BPM"}) + return + if(!silent) + user.visible_message("[user] analyzes [M]'s vitals.", \ + "You analyze [M]'s vitals.") + playsound(user, 'sound/items/healthanalyzer.ogg', 50, 1) + var/fake_oxy = max(rand(1, 40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss()))) + var/OX = M.getOxyLoss() > 50 ? "[M.getOxyLoss()]" : M.getOxyLoss() + var/TX = M.getToxLoss() > 50 ? "[M.getToxLoss()]" : M.getToxLoss() + var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss() + var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss() + if(M.status_flags & FAKEDEATH) + OX = fake_oxy > 50 ? "[fake_oxy]" : fake_oxy + message += "Analyzing Results for [M]:
    Overall Status: Dead

    " + else + message += "
    Analyzing Results for [M]:
    Overall Status: [M.stat > 1 ? "Dead" : "[M.health - M.halloss]% Healthy"]
    " + message += "
    Key: Suffocation/Toxin/Burns/Brute" + message += "
    Damage Specifics: [OX] - [TX] - [BU] - [BR]" + message += "
    Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)" + if(M.tod && M.isDead()) + message += "
    Time of Death: [M.tod]" + if(istype(M, /mob/living/carbon/human) && mode) + var/mob/living/carbon/human/H = M + var/list/damaged = H.get_damaged_organs(1, 1) + message += "
    Localized Damage, Brute/Burn:" + if(length(damaged)) + for(var/datum/organ/external/org in damaged) + var/organ_msg = "
    " + organ_msg += capitalize(org.display_name) + organ_msg += ": " + organ_msg += "[org.brute_dam ? org.brute_dam : 0]" + organ_msg += "/[org.burn_dam ? org.burn_dam : 0]" + if(org.status & ORGAN_BLEEDING) + organ_msg += "\[BLEEDING\]" + if(org.status & org.is_peg()) + organ_msg += "\[WOOD DETECTED?\]" + if(org.status & org.is_robotic()) + organ_msg += "\[METAL DETECTED?\]" + message += organ_msg + else + message += "
    No limb damage detected." + + OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" + TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level normal" + BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status clear" + BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute injury status clear" + if(M.status_flags & FAKEDEATH) + OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" + message += ("
    [OX] | [TX] | [BU] | [BR]") + + if(M.reagents.total_volume) + message += "
    Warning: Unknown substance detected in subject's blood." + if(hardcore_mode_on && ishuman(M) && eligible_for_hardcore_mode(M)) + var/mob/living/carbon/human/H = M + if(H.nutrition < STARVATION_MIN) + message += "
    Warning: Severe lack of essential nutriments detected in subject's blood." + + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(C.virus2.len) + for(var/ID in C.virus2) + if(ID in virusDB) + var/datum/data/record/V = virusDB[ID] + message += "
    Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]" + //Canned out to make viruses much harder to notice, I suppose. Too bad we can't port a single functional virus code with visibility stats already + //else + //user.show_message(text("Warning: Unknown pathogen detected in subject's blood.")) + + if(M.getCloneLoss()) + message += "
    Subject appears to have been imperfectly cloned." + for(var/datum/disease/D in M.viruses) + if(!D.hidden[SCANNER]) + message += "
    Warning: [D.form] Detected
    Name: [D.name].
    Type: [D.spread].
    Stage: [D.stage]/[D.max_stages].
    Possible Cure: [D.cure]
    " + if(M.reagents && M.reagents.get_reagent_amount("inaprovaline")) + message += "
    Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals." + if(M.has_brain_worms()) + message += "
    Strange MRI readout. Subject needs further scanning." + else if(M.getBrainLoss() >= 100 || !M.has_brain()) + message += "
    No brain activity has been detected. Subject is braindead." + else if(M.getBrainLoss() >= 60) + message += "
    Severe brain damage detected. Subject likely to have mental retardation." + else if(M.getBrainLoss() >= 10) + message += "
    Significant brain damage detected. Subject may have had a concussion." + if(ishuman(M)) + var/mob/living/carbon/human/H = M + for(var/name in H.organs_by_name) + var/datum/organ/external/e = H.organs_by_name[name] + var/limb = e.display_name + /* + * Doesn't belong here, only the advanced scanner can locate fractures + if(e.is_broken()) + if((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) //Only these limbs can be splinted + message += "
    Unsecured fracture in subject's [limb]. Splinting recommended for transport." + */ + if(e.has_infected_wound()) + message += "
    Infected wound detected in subject's [limb]. Disinfection recommended." + + for(var/name in H.organs_by_name) + var/datum/organ/external/e = H.organs_by_name[name] + if(e.is_broken()) + message += text("
    Bone fractures detected. Advanced scan required for location.") + break + for(var/datum/organ/external/e in H.organs) + for(var/datum/wound/W in e.wounds) + if(W.internal) + message += text("
    Internal bleeding detected. Advanced scan required for location.") + break + if(H.vessel) + var/blood_volume = round(H.vessel.get_reagent_amount("blood")) + var/blood_percent = round((blood_volume / 560) * 100) + switch(blood_volume) + if(BLOOD_VOLUME_SAFE to 1000000000) + message += "
    Blood Level Normal: [blood_percent]% ([blood_volume]cl)" + if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) + message += "
    Warning: Blood Level Low: [blood_percent]% [blood_volume]cl" //Still about fine + if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) + message += "
    Danger: Blood Level Serious: [blood_percent]% [blood_volume]cl" + if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) + message += "
    Danger: Blood Level Critical: [blood_percent]% [blood_volume]cl" + if(-1000000000 to BLOOD_VOLUME_SURVIVE) + message += "
    Danger: Blood Level Fatal: [blood_percent]% [blood_volume]cl" + message += "
    Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] BPM" + to_chat(user, message)//Here goes + + return message //To read last scan + +/obj/item/device/healthanalyzer/verb/toggle_mode() + set name = "Switch mode" + set category = "Object" + + mode = !mode + to_chat(usr, "The scanner will [mode ? "now show specific limb damage" : "no longer show specific limb damage"].") + +/obj/item/device/analyzer + desc = "A hand-held environment scanner which reports data about gas mixtures." + name = "atmospheric analyzer" + icon_state = "atmos" + item_state = "analyzer" + w_class = 2.0 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 5 + throw_speed = 4 + throw_range = 20 + starting_materials = list(MAT_IRON = 30, MAT_GLASS = 20) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + origin_tech = "magnets=1;engineering=1" + +/obj/item/device/analyzer/attack_self(mob/user as mob) + + . = ..() + if(.) + return + + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + + var/turf/location = get_turf(user) + + if(!location) //Somehow + return + + var/datum/gas_mixture/environment = location.return_air() + + user << output_gas_scan(environment, location, 1) + + src.add_fingerprint(user) + return + +//If human_standard is enabled, the message will be formatted to show which values are dangerous +/obj/item/device/analyzer/proc/output_gas_scan(var/datum/gas_mixture/scanned, var/atom/container, human_standard = 1) + if(!scanned) + return "No gas mixture found." + scanned.update_values() + var/pressure = scanned.return_pressure() + var/total_moles = scanned.total_moles() + var/message = "" + if(!container || istype(container, /turf)) + message += "Results:" + else + message += "\icon [container] Results of [container] scan:" + if(total_moles) + message += "
    [human_standard && abs(pressure - ONE_ATMOSPHERE) > 10 ? "" : ""] Pressure: [round(pressure, 0.1)] kPa" + var/o2_concentration = scanned.oxygen/total_moles + var/n2_concentration = scanned.nitrogen/total_moles + var/co2_concentration = scanned.carbon_dioxide/total_moles + var/plasma_concentration = scanned.toxins/total_moles + + var/unknown_concentration = 1 - (o2_concentration + n2_concentration + co2_concentration + plasma_concentration) + + if(n2_concentration > 0.01) + message += "
    [human_standard && abs(n2_concentration - N2STANDARD) > 20 ? "" : ""] Nitrogen: [round(scanned.nitrogen, 0.1)] mol, [round(n2_concentration*100)]%" + if(o2_concentration > 0.01) + message += "
    [human_standard && abs(o2_concentration - O2STANDARD) > 2 ? "" : ""] Oxygen: [round(scanned.oxygen, 0.1)] mol, [round(o2_concentration*100)]%" + if(co2_concentration > 0.01) + message += "
    [human_standard ? "" : ""] CO2: [round(scanned.carbon_dioxide, 0.1)] mol, [round(co2_concentration*100)]%" + if(plasma_concentration > 0.01) + message += "
    [human_standard ? "" : ""] Plasma: [round(scanned.toxins, 0.1)] mol, [round(plasma_concentration*100)]%" + if(unknown_concentration > 0.01) + message += "
    Unknown: [round(unknown_concentration*100)]%" + + message += "
    [human_standard && !(scanned.temperature in range(BODYTEMP_COLD_DAMAGE_LIMIT, BODYTEMP_HEAT_DAMAGE_LIMIT)) ? "" : ""] Temperature: [round(scanned.temperature-T0C)]°C" + else + message += "
    No gasses detected[container && !istype(container, /turf) ? " in \the [container]." : ""]!" + return message + +/obj/item/device/mass_spectrometer + desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample." + name = "mass-spectrometer" + icon_state = "spectrometer" + item_state = "analyzer" + w_class = 2.0 + flags = FPRINT | OPENCONTAINER + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 5 + throw_speed = 4 + throw_range = 20 + starting_materials = list(MAT_IRON = 30, MAT_GLASS = 20) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=2;biotech=2" + var/details = 0 + +/obj/item/device/mass_spectrometer/New() + . = ..() + create_reagents(5) + +/obj/item/device/mass_spectrometer/on_reagent_change() + if(reagents.total_volume) + icon_state = initial(icon_state) + "_s" + else + icon_state = initial(icon_state) + +/obj/item/device/mass_spectrometer/attack(mob/living/M as mob, mob/living/user as mob) + if(!M.reagents) + return + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(reagents.total_volume) + to_chat(user, "This device already has a blood sample!") + return + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + if(!C.dna) + return + if(M_NOCLONE in C.mutations) + return + + var/datum/reagent/B = C.take_blood(src, src.reagents.maximum_volume) + if(B) + src.reagents.reagent_list |= B + src.reagents.update_total() + src.on_reagent_change() + src.reagents.handle_reactions() + update_icon() + user.visible_message("[user] takes a blood sample from [C].", \ + "You take a blood sample from [C]") + playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) //It uses the same thing as the hypospray, in reverse. SCIENCE! + +/obj/item/device/mass_spectrometer/attack_self(mob/user as mob) + . = ..() + if(.) + return + + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + if(reagents.total_volume) + var/list/blood_traces = list() + for(var/datum/reagent/R in reagents.reagent_list) + if(R.id != "blood") + reagents.clear_reagents() + to_chat(user, "The sample was contaminated! Please insert another sample.") + return + else + blood_traces = params2list(R.data["trace_chem"]) + break + var/dat + if(blood_traces.len) + dat = "Trace Chemicals Found:" + for(var/R in blood_traces) + dat += "
    [R] [details ? "([blood_traces[R]] units)":""]" + else + dat = "No trace chemicals found in the sample." + to_chat(user, "[dat]") + reagents.clear_reagents() + return + +/obj/item/device/mass_spectrometer/adv + name = "advanced mass-spectrometer" + icon_state = "adv_spectrometer" + details = 1 + origin_tech = "magnets=4;biotech=2" + +/obj/item/device/reagent_scanner + name = "reagent scanner" + desc = "A hand-held reagent scanner which identifies chemical agents." + icon_state = "spectrometer" + item_state = "analyzer" + w_class = 2.0 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 5 + throw_speed = 4 + throw_range = 20 + starting_materials = list(MAT_IRON = 30, MAT_GLASS = 20) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=2;biotech=2" + var/details = 0 + var/recent_fail = 0 + +/obj/item/device/reagent_scanner/afterattack(obj/O, mob/user as mob) + . = ..() + if(.) + return + if(!istype(O)) //Wrong type sent + return + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + if(O.reagents) + var/dat = "" + if(O.reagents.reagent_list.len) + for(var/datum/reagent/R in O.reagents.reagent_list) + var/reagent_percent = (R.volume/O.reagents.total_volume)*100 + dat += "
    [R] [details ? "([R.volume] units, [reagent_percent]%)" : ""]" + if(dat) + to_chat(user, "Chemicals found in \the [O]:[dat]") + else + to_chat(user, "No active chemical agents found in \the [O].") + + return + +/obj/item/device/reagent_scanner/adv + name = "advanced reagent scanner" + icon_state = "adv_spectrometer" + details = 1 + origin_tech = "magnets=4;biotech=2" diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 9866566f6a3..c746ca2023f 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -1,244 +1,244 @@ -/obj/item/device/taperecorder - desc = "A device that can record up to an hour of dialogue and play it back. It automatically translates the content in playback." - name = "universal recorder" - icon_state = "taperecorderidle" - item_state = "analyzer" - origin_tech = "magnets=1;programming=1" - w_class = 1.0 - starting_materials = list(MAT_IRON = 60, MAT_GLASS = 30) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - var/emagged = 0.0 - var/recording = 0.0 - var/playing = 0.0 - var/timerecorded = 0.0 - var/playsleepseconds = 0.0 - var/list/storedinfo = new/list() - var/list/timestamp = new/list() - var/canprint = 1 - flags = FPRINT | HEAR - siemens_coefficient = 1 - throwforce = 2 - throw_speed = 4 - throw_range = 20 - -/obj/item/device/taperecorder/Hear(var/datum/speech/speech, var/rendered_speech="") - if(recording) - timestamp += timerecorded - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] \"[html_encode(speech.message)]\"" - -/obj/item/device/taperecorder/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(istype(W, /obj/item/weapon/card/emag)) - if(emagged == 0) - emagged = 1 - recording = 0 - to_chat(user, "PZZTTPFFFT") - icon_state = "taperecorderidle" - else - to_chat(user, "It is already emagged!") - -/obj/item/device/taperecorder/proc/explode() - var/turf/T = get_turf(loc) - if(ismob(loc)) - var/mob/M = loc - to_chat(M, "\The [src] explodes!") - if(T) - T.hotspot_expose(700,125,surfaces=istype(loc,/turf)) - explosion(T, -1, -1, 0, 4) - qdel(src) - return - -/obj/item/device/taperecorder/verb/record() - set name = "Start Recording" - set category = "Object" - - if(usr.isUnconscious()) - return - if(emagged == 1) - to_chat(usr, "The tape recorder makes a scratchy noise.") - return - icon_state = "taperecorderrecording" - if(timerecorded < 3600 && playing == 0) - to_chat(usr, "Recording started.") - recording = 1 - timestamp+= timerecorded - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording started." - for(timerecorded, timerecorded<3600) - if(recording == 0) - break - timerecorded++ - sleep(10) - recording = 0 - icon_state = "taperecorderidle" - return - else - to_chat(usr, "Either your tape recorder's memory is full, or it is currently playing back its memory.") - - -/obj/item/device/taperecorder/verb/stop() - set name = "Stop" - set category = "Object" - - if(usr.isUnconscious()) - return - if(emagged == 1) - to_chat(usr, "The tape recorder makes a scratchy noise.") - return - if(recording == 1) - recording = 0 - timestamp+= timerecorded - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording stopped." - to_chat(usr, "Recording stopped.") - icon_state = "taperecorderidle" - return - else if(playing == 1) - playing = 0 - recorder_message("Playback stopped.") - icon_state = "taperecorderidle" - return - - -/obj/item/device/taperecorder/verb/clear_memory() - set name = "Clear Memory" - set category = "Object" - - if(usr.isUnconscious()) - return - if(emagged == 1) - to_chat(usr, "The tape recorder makes a scratchy noise.") - return - if(recording == 1 || playing == 1) - to_chat(usr, "You can't clear the memory while playing or recording!") - return - else - if(storedinfo) storedinfo.Cut() - if(timestamp) timestamp.Cut() - timerecorded = 0 - to_chat(usr, "Memory cleared.") - return - - -/obj/item/device/taperecorder/verb/playback_memory() - set name = "Playback Memory" - set category = "Object" - - if(usr.isUnconscious()) - return - if(emagged == 1) - to_chat(usr, "The tape recorder makes a scratchy noise.") - return - if(recording == 1) - to_chat(usr, "You can't playback when recording!") - return - if(playing == 1) - to_chat(usr, "You're already playing!") - return - playing = 1 - icon_state = "taperecorderplaying" - to_chat(usr, "Playing started.") - for(var/i=1,timerecorded<3600,sleep(10 * (playsleepseconds) )) - if(playing == 0) - break - if(storedinfo.len < i) - break - recorder_message("[storedinfo[i]]") - if(storedinfo.len < i+1) - playsleepseconds = 1 - sleep(10) - recorder_message("End of recording.") - else - playsleepseconds = timestamp[i+1] - timestamp[i] - if(playsleepseconds > 14) - sleep(10) - recorder_message("Skipping [playsleepseconds] seconds of silence") - playsleepseconds = 1 - i++ - icon_state = "taperecorderidle" - playing = 0 - if(emagged == 1.0) - recorder_message("This tape recorder will self-destruct in... Five.") - sleep(10) - recorder_message("Four.") - sleep(10) - recorder_message("Three.") - sleep(10) - recorder_message("Two.") - sleep(10) - recorder_message("One.") - sleep(10) - explode() - - -/obj/item/device/taperecorder/verb/print_transcript() - set name = "Print Transcript" - set category = "Object" - - if(usr.isUnconscious()) - return - if(emagged == 1) - to_chat(usr, "The tape recorder makes a scratchy noise.") - return - if(!canprint) - to_chat(usr, "The recorder can't print that fast!") - return - if(recording == 1 || playing == 1) - to_chat(usr, "You can't print the transcript while playing or recording!") - return - to_chat(usr, "Transcript printed.") - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src)) - var/t1 = "Transcript:

    " - for(var/i=1,storedinfo.len >= i,i++) - t1 += "[storedinfo[i]]
    " - P.info = t1 - P.name = "paper- 'Transcript'" - canprint = 0 - sleep(300) - canprint = 1 - - -/obj/item/device/taperecorder/attack_self(mob/user) - if(recording == 0 && playing == 0) - if(usr.stat) - return - if(emagged == 1) - to_chat(usr, "The tape recorder makes a scratchy noise.") - return - icon_state = "taperecorderrecording" - if(timerecorded < 3600 && playing == 0) - to_chat(usr, "Recording started.") - recording = 1 - timestamp+= timerecorded - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording started." - for(timerecorded, timerecorded<3600) - if(recording == 0) - break - timerecorded++ - sleep(10) - recording = 0 - icon_state = "taperecorderidle" - return - else - to_chat(usr, "Either your tape recorder's memory is full, or it is currently playing back its memory.") - else - if(usr.stat) - to_chat(usr, "Not when you're incapacitated.") - return - if(recording == 1) - recording = 0 - timestamp+= timerecorded - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording stopped." - to_chat(usr, "Recording stopped.") - icon_state = "taperecorderidle" - return - else if(playing == 1) - playing = 0 - recorder_message("Playback stopped") - icon_state = "taperecorderidle" - return - else - to_chat(usr, "Stop what?") - return - -/obj/item/device/taperecorder/proc/recorder_message(var/msg) - visible_message("Tape Recorder: [msg]") +/obj/item/device/taperecorder + desc = "A device that can record up to an hour of dialogue and play it back. It automatically translates the content in playback." + name = "universal recorder" + icon_state = "taperecorderidle" + item_state = "analyzer" + origin_tech = "magnets=1;programming=1" + w_class = 1.0 + starting_materials = list(MAT_IRON = 60, MAT_GLASS = 30) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + var/emagged = 0.0 + var/recording = 0.0 + var/playing = 0.0 + var/timerecorded = 0.0 + var/playsleepseconds = 0.0 + var/list/storedinfo = new/list() + var/list/timestamp = new/list() + var/canprint = 1 + flags = FPRINT | HEAR + siemens_coefficient = 1 + throwforce = 2 + throw_speed = 4 + throw_range = 20 + +/obj/item/device/taperecorder/Hear(var/datum/speech/speech, var/rendered_speech="") + if(recording) + timestamp += timerecorded + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] \"[html_encode(speech.message)]\"" + +/obj/item/device/taperecorder/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(istype(W, /obj/item/weapon/card/emag)) + if(emagged == 0) + emagged = 1 + recording = 0 + to_chat(user, "PZZTTPFFFT") + icon_state = "taperecorderidle" + else + to_chat(user, "It is already emagged!") + +/obj/item/device/taperecorder/proc/explode() + var/turf/T = get_turf(loc) + if(ismob(loc)) + var/mob/M = loc + to_chat(M, "\The [src] explodes!") + if(T) + T.hotspot_expose(700,125,surfaces=istype(loc,/turf)) + explosion(T, -1, -1, 0, 4) + qdel(src) + return + +/obj/item/device/taperecorder/verb/record() + set name = "Start Recording" + set category = "Object" + + if(usr.isUnconscious()) + return + if(emagged == 1) + to_chat(usr, "The tape recorder makes a scratchy noise.") + return + icon_state = "taperecorderrecording" + if(timerecorded < 3600 && playing == 0) + to_chat(usr, "Recording started.") + recording = 1 + timestamp+= timerecorded + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording started." + for(timerecorded, timerecorded<3600) + if(recording == 0) + break + timerecorded++ + sleep(10) + recording = 0 + icon_state = "taperecorderidle" + return + else + to_chat(usr, "Either your tape recorder's memory is full, or it is currently playing back its memory.") + + +/obj/item/device/taperecorder/verb/stop() + set name = "Stop" + set category = "Object" + + if(usr.isUnconscious()) + return + if(emagged == 1) + to_chat(usr, "The tape recorder makes a scratchy noise.") + return + if(recording == 1) + recording = 0 + timestamp+= timerecorded + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording stopped." + to_chat(usr, "Recording stopped.") + icon_state = "taperecorderidle" + return + else if(playing == 1) + playing = 0 + recorder_message("Playback stopped.") + icon_state = "taperecorderidle" + return + + +/obj/item/device/taperecorder/verb/clear_memory() + set name = "Clear Memory" + set category = "Object" + + if(usr.isUnconscious()) + return + if(emagged == 1) + to_chat(usr, "The tape recorder makes a scratchy noise.") + return + if(recording == 1 || playing == 1) + to_chat(usr, "You can't clear the memory while playing or recording!") + return + else + if(storedinfo) storedinfo.Cut() + if(timestamp) timestamp.Cut() + timerecorded = 0 + to_chat(usr, "Memory cleared.") + return + + +/obj/item/device/taperecorder/verb/playback_memory() + set name = "Playback Memory" + set category = "Object" + + if(usr.isUnconscious()) + return + if(emagged == 1) + to_chat(usr, "The tape recorder makes a scratchy noise.") + return + if(recording == 1) + to_chat(usr, "You can't playback when recording!") + return + if(playing == 1) + to_chat(usr, "You're already playing!") + return + playing = 1 + icon_state = "taperecorderplaying" + to_chat(usr, "Playing started.") + for(var/i=1,timerecorded<3600,sleep(10 * (playsleepseconds) )) + if(playing == 0) + break + if(storedinfo.len < i) + break + recorder_message("[storedinfo[i]]") + if(storedinfo.len < i+1) + playsleepseconds = 1 + sleep(10) + recorder_message("End of recording.") + else + playsleepseconds = timestamp[i+1] - timestamp[i] + if(playsleepseconds > 14) + sleep(10) + recorder_message("Skipping [playsleepseconds] seconds of silence") + playsleepseconds = 1 + i++ + icon_state = "taperecorderidle" + playing = 0 + if(emagged == 1.0) + recorder_message("This tape recorder will self-destruct in... Five.") + sleep(10) + recorder_message("Four.") + sleep(10) + recorder_message("Three.") + sleep(10) + recorder_message("Two.") + sleep(10) + recorder_message("One.") + sleep(10) + explode() + + +/obj/item/device/taperecorder/verb/print_transcript() + set name = "Print Transcript" + set category = "Object" + + if(usr.isUnconscious()) + return + if(emagged == 1) + to_chat(usr, "The tape recorder makes a scratchy noise.") + return + if(!canprint) + to_chat(usr, "The recorder can't print that fast!") + return + if(recording == 1 || playing == 1) + to_chat(usr, "You can't print the transcript while playing or recording!") + return + to_chat(usr, "Transcript printed.") + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src)) + var/t1 = "Transcript:

    " + for(var/i=1,storedinfo.len >= i,i++) + t1 += "[storedinfo[i]]
    " + P.info = t1 + P.name = "paper- 'Transcript'" + canprint = 0 + sleep(300) + canprint = 1 + + +/obj/item/device/taperecorder/attack_self(mob/user) + if(recording == 0 && playing == 0) + if(usr.stat) + return + if(emagged == 1) + to_chat(usr, "The tape recorder makes a scratchy noise.") + return + icon_state = "taperecorderrecording" + if(timerecorded < 3600 && playing == 0) + to_chat(usr, "Recording started.") + recording = 1 + timestamp+= timerecorded + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording started." + for(timerecorded, timerecorded<3600) + if(recording == 0) + break + timerecorded++ + sleep(10) + recording = 0 + icon_state = "taperecorderidle" + return + else + to_chat(usr, "Either your tape recorder's memory is full, or it is currently playing back its memory.") + else + if(usr.stat) + to_chat(usr, "Not when you're incapacitated.") + return + if(recording == 1) + recording = 0 + timestamp+= timerecorded + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] Recording stopped." + to_chat(usr, "Recording stopped.") + icon_state = "taperecorderidle" + return + else if(playing == 1) + playing = 0 + recorder_message("Playback stopped") + icon_state = "taperecorderidle" + return + else + to_chat(usr, "Stop what?") + return + +/obj/item/device/taperecorder/proc/recorder_message(var/msg) + visible_message("Tape Recorder: [msg]") diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index f2cf76b4b59..e8cb1f87e66 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -1,226 +1,226 @@ -/obj/item/device/transfer_valve - icon = 'icons/obj/assemblies.dmi' - name = "tank transfer valve" - icon_state = "valve_1" - desc = "Regulates the transfer of air between two tanks" - var/obj/item/weapon/tank/tank_one - var/obj/item/weapon/tank/tank_two - var/obj/item/device/attached_device - var/mob/attacher = null - var/valve_open = 0 - var/toggle = 1 - - flags = FPRINT | PROXMOVE - -/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D) - -/obj/item/device/transfer_valve/IsAssemblyHolder() - return 1 - -/obj/item/device/transfer_valve/Crossed(AM as mob|obj) - if(attached_device) - attached_device.Crossed(AM) - ..() - -/obj/item/device/transfer_valve/on_found(AM as mob|obj) - if(attached_device) - attached_device.on_found(AM) - ..() - -/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user) - if(istype(item, /obj/item/weapon/tank)) - if(tank_one && tank_two) - to_chat(user, "There are already two tanks attached, remove one first.") - return - - if(!tank_one) - if(user.drop_item(item, src)) - tank_one = item - to_chat(user, "You attach the tank to the transfer valve.") - else if(!tank_two) - if(user.drop_item(item, src)) - tank_two = item - to_chat(user, "You attach the tank to the transfer valve.") - - update_icon() - //TODO: Have this take an assemblyholder - else if(isassembly(item)) - var/obj/item/device/assembly/A = item - if(A.secured) - to_chat(user, "The device is secured.") - return - if(attached_device) - to_chat(user, "There is already a device attached to the valve, remove it first.") - return - user.remove_from_mob(item) - attached_device = A - A.loc = src - to_chat(user, "You attach the [item] to the valve controls and secure it.") - A.holder = src - A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb). - - bombers += "[key_name(user)] attached a [item] to a transfer valve." - message_admins("[key_name_admin(user)] attached a [item] to a transfer valve.") - log_game("[key_name_admin(user)] attached a [item] to a transfer valve.") - attacher = user - return - - -/obj/item/device/transfer_valve/HasProximity(atom/movable/AM as mob|obj) - if(!attached_device) return - attached_device.HasProximity(AM) - return - - -/obj/item/device/transfer_valve/attack_self(mob/user as mob) - user.set_machine(src) - var/dat = {" Valve properties: -
    Attachment one: [tank_one] [tank_one ? "Remove" : ""] -
    Attachment two: [tank_two] [tank_two ? "Remove" : ""] -
    Valve attachment: [attached_device ? "[attached_device]" : "None"] [attached_device ? "Remove" : ""] -
    Valve status: [ valve_open ? "Closed Open" : "Closed Open"]"} - - user << browse(dat, "window=trans_valve;size=600x300") - onclose(user, "trans_valve") - return - -/obj/item/device/transfer_valve/Topic(href, href_list) - ..() - if ( usr.stat || usr.restrained() ) - return - if (src.loc == usr) - if(tank_one && href_list["tankone"]) - split_gases() - valve_open = 0 - tank_one.loc = get_turf(src) - tank_one = null - update_icon() - else if(tank_two && href_list["tanktwo"]) - split_gases() - valve_open = 0 - tank_two.loc = get_turf(src) - tank_two = null - update_icon() - else if(href_list["open"]) - toggle_valve() - else if(attached_device) - if(href_list["rem_device"]) - attached_device.loc = get_turf(src) - attached_device:holder = null - attached_device = null - update_icon() - if(href_list["device"]) - attached_device.attack_self(usr) - - src.attack_self(usr) - src.add_fingerprint(usr) - return - return - -/obj/item/device/transfer_valve/process_activation(var/obj/item/device/D) - if(toggle) - toggle = 0 - toggle_valve() - spawn(50) // To stop a signal being spammed from a proxy sensor constantly going off or whatever - toggle = 1 - -/obj/item/device/transfer_valve/update_icon() - overlays.len = 0 - underlays = null - - if(!tank_one && !tank_two && !attached_device) - icon_state = "valve_1" - return - icon_state = "valve" - - if(tank_one) - overlays += "[tank_one.icon_state]" - if(tank_two) - var/icon/J = new(icon, icon_state = "[tank_two.icon_state]") - J.Shift(WEST, 13) - underlays += J - if(attached_device) - overlays += "device" - -/obj/item/device/transfer_valve/proc/merge_gases() - tank_two.air_contents.volume += tank_one.air_contents.volume - var/datum/gas_mixture/temp - temp = tank_one.air_contents.remove_ratio(1) - tank_two.air_contents.merge(temp) - -/obj/item/device/transfer_valve/proc/split_gases() - if (!valve_open || !tank_one || !tank_two) - return - var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume - var/datum/gas_mixture/temp - temp = tank_two.air_contents.remove_ratio(ratio1) - tank_one.air_contents.merge(temp) - tank_two.air_contents.volume -= tank_one.air_contents.volume - - /* - Exadv1: I know this isn't how it's going to work, but this was just to check - it explodes properly when it gets a signal (and it does). - */ - -/obj/item/device/transfer_valve/proc/toggle_valve() - if(valve_open==0 && (tank_one && tank_two)) - valve_open = 1 - var/turf/bombturf = get_turf(src) - var/area/A = get_area(bombturf) - - var/attacher_name = "" - if(!attacher) - attacher_name = "Unknown" - else - attacher_name = "[attacher.name]([attacher.ckey])" - - var/log_str = "Bomb valve opened in [A.name] " - log_str += "with [attached_device ? attached_device : "no device"] attacher: [attacher_name]" - - if(attacher) - log_str += "(?)" - - var/mob/mob = get_mob_by_key(src.fingerprintslast) - var/last_touch_info = "" - if(mob) - last_touch_info = "(?)" - - log_str += " Last touched by: [src.fingerprintslast][last_touch_info]" - bombers += log_str - message_admins(log_str, 0, 1) - log_game(log_str) - merge_gases() - else if(valve_open==1 && (tank_one && tank_two)) - split_gases() - valve_open = 0 - src.update_icon() - -/** - * Handles child tanks exploding. - * - * Previously handled by a stupid fucking spawn() and sleep(10) loop. - * - * We destroy any item we're inside of - */ -/obj/item/device/transfer_valve/proc/child_ruptured(var/obj/item/weapon/tank/tank, var/range) - // Old behavior. - if(tank_one == tank) - tank_one=null - if(tank_two == tank) - tank_two=null - update_icon() - - // New behavior: Ensure deletion of valve assembly, send damage info up the chain. - if(range > 4) // Extreme damage is range/4, so any extreme damage will trip this. - // Send explosion up chain of custody. - if(src.loc && istype(src.loc,/obj)) - src.loc.ex_act(1,src) - - // Delete ourselves. - qdel(src) - - -// this doesn't do anything but the timer etc. expects it to be here -// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs -/obj/item/device/transfer_valve/proc/c_state() - return +/obj/item/device/transfer_valve + icon = 'icons/obj/assemblies.dmi' + name = "tank transfer valve" + icon_state = "valve_1" + desc = "Regulates the transfer of air between two tanks" + var/obj/item/weapon/tank/tank_one + var/obj/item/weapon/tank/tank_two + var/obj/item/device/attached_device + var/mob/attacher = null + var/valve_open = 0 + var/toggle = 1 + + flags = FPRINT | PROXMOVE + +/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D) + +/obj/item/device/transfer_valve/IsAssemblyHolder() + return 1 + +/obj/item/device/transfer_valve/Crossed(AM as mob|obj) + if(attached_device) + attached_device.Crossed(AM) + ..() + +/obj/item/device/transfer_valve/on_found(AM as mob|obj) + if(attached_device) + attached_device.on_found(AM) + ..() + +/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user) + if(istype(item, /obj/item/weapon/tank)) + if(tank_one && tank_two) + to_chat(user, "There are already two tanks attached, remove one first.") + return + + if(!tank_one) + if(user.drop_item(item, src)) + tank_one = item + to_chat(user, "You attach the tank to the transfer valve.") + else if(!tank_two) + if(user.drop_item(item, src)) + tank_two = item + to_chat(user, "You attach the tank to the transfer valve.") + + update_icon() + //TODO: Have this take an assemblyholder + else if(isassembly(item)) + var/obj/item/device/assembly/A = item + if(A.secured) + to_chat(user, "The device is secured.") + return + if(attached_device) + to_chat(user, "There is already a device attached to the valve, remove it first.") + return + user.remove_from_mob(item) + attached_device = A + A.loc = src + to_chat(user, "You attach the [item] to the valve controls and secure it.") + A.holder = src + A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb). + + bombers += "[key_name(user)] attached a [item] to a transfer valve." + message_admins("[key_name_admin(user)] attached a [item] to a transfer valve.") + log_game("[key_name_admin(user)] attached a [item] to a transfer valve.") + attacher = user + return + + +/obj/item/device/transfer_valve/HasProximity(atom/movable/AM as mob|obj) + if(!attached_device) return + attached_device.HasProximity(AM) + return + + +/obj/item/device/transfer_valve/attack_self(mob/user as mob) + user.set_machine(src) + var/dat = {" Valve properties: +
    Attachment one: [tank_one] [tank_one ? "Remove" : ""] +
    Attachment two: [tank_two] [tank_two ? "Remove" : ""] +
    Valve attachment: [attached_device ? "[attached_device]" : "None"] [attached_device ? "Remove" : ""] +
    Valve status: [ valve_open ? "Closed Open" : "Closed Open"]"} + + user << browse(dat, "window=trans_valve;size=600x300") + onclose(user, "trans_valve") + return + +/obj/item/device/transfer_valve/Topic(href, href_list) + ..() + if ( usr.stat || usr.restrained() ) + return + if (src.loc == usr) + if(tank_one && href_list["tankone"]) + split_gases() + valve_open = 0 + tank_one.loc = get_turf(src) + tank_one = null + update_icon() + else if(tank_two && href_list["tanktwo"]) + split_gases() + valve_open = 0 + tank_two.loc = get_turf(src) + tank_two = null + update_icon() + else if(href_list["open"]) + toggle_valve() + else if(attached_device) + if(href_list["rem_device"]) + attached_device.loc = get_turf(src) + attached_device:holder = null + attached_device = null + update_icon() + if(href_list["device"]) + attached_device.attack_self(usr) + + src.attack_self(usr) + src.add_fingerprint(usr) + return + return + +/obj/item/device/transfer_valve/process_activation(var/obj/item/device/D) + if(toggle) + toggle = 0 + toggle_valve() + spawn(50) // To stop a signal being spammed from a proxy sensor constantly going off or whatever + toggle = 1 + +/obj/item/device/transfer_valve/update_icon() + overlays.len = 0 + underlays = null + + if(!tank_one && !tank_two && !attached_device) + icon_state = "valve_1" + return + icon_state = "valve" + + if(tank_one) + overlays += "[tank_one.icon_state]" + if(tank_two) + var/icon/J = new(icon, icon_state = "[tank_two.icon_state]") + J.Shift(WEST, 13) + underlays += J + if(attached_device) + overlays += "device" + +/obj/item/device/transfer_valve/proc/merge_gases() + tank_two.air_contents.volume += tank_one.air_contents.volume + var/datum/gas_mixture/temp + temp = tank_one.air_contents.remove_ratio(1) + tank_two.air_contents.merge(temp) + +/obj/item/device/transfer_valve/proc/split_gases() + if (!valve_open || !tank_one || !tank_two) + return + var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume + var/datum/gas_mixture/temp + temp = tank_two.air_contents.remove_ratio(ratio1) + tank_one.air_contents.merge(temp) + tank_two.air_contents.volume -= tank_one.air_contents.volume + + /* + Exadv1: I know this isn't how it's going to work, but this was just to check + it explodes properly when it gets a signal (and it does). + */ + +/obj/item/device/transfer_valve/proc/toggle_valve() + if(valve_open==0 && (tank_one && tank_two)) + valve_open = 1 + var/turf/bombturf = get_turf(src) + var/area/A = get_area(bombturf) + + var/attacher_name = "" + if(!attacher) + attacher_name = "Unknown" + else + attacher_name = "[attacher.name]([attacher.ckey])" + + var/log_str = "Bomb valve opened in [A.name] " + log_str += "with [attached_device ? attached_device : "no device"] attacher: [attacher_name]" + + if(attacher) + log_str += "(?)" + + var/mob/mob = get_mob_by_key(src.fingerprintslast) + var/last_touch_info = "" + if(mob) + last_touch_info = "(?)" + + log_str += " Last touched by: [src.fingerprintslast][last_touch_info]" + bombers += log_str + message_admins(log_str, 0, 1) + log_game(log_str) + merge_gases() + else if(valve_open==1 && (tank_one && tank_two)) + split_gases() + valve_open = 0 + src.update_icon() + +/** + * Handles child tanks exploding. + * + * Previously handled by a stupid fucking spawn() and sleep(10) loop. + * + * We destroy any item we're inside of + */ +/obj/item/device/transfer_valve/proc/child_ruptured(var/obj/item/weapon/tank/tank, var/range) + // Old behavior. + if(tank_one == tank) + tank_one=null + if(tank_two == tank) + tank_two=null + update_icon() + + // New behavior: Ensure deletion of valve assembly, send damage info up the chain. + if(range > 4) // Extreme damage is range/4, so any extreme damage will trip this. + // Send explosion up chain of custody. + if(src.loc && istype(src.loc,/obj)) + src.loc.ex_act(1,src) + + // Delete ourselves. + qdel(src) + + +// this doesn't do anything but the timer etc. expects it to be here +// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs +/obj/item/device/transfer_valve/proc/c_state() + return diff --git a/code/game/objects/items/devices/violin.dm b/code/game/objects/items/devices/violin.dm index 0bfbd6a0bac..8c8ef12f2a7 100644 --- a/code/game/objects/items/devices/violin.dm +++ b/code/game/objects/items/devices/violin.dm @@ -1,405 +1,405 @@ -//copy pasta of the space piano, don't hurt me -Pete - -/obj/item/device/violin - name = "space violin" - desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\"" - icon = 'icons/obj/musician.dmi' - icon_state = "violin" - item_state = "violin" - force = 10 - var/datum/song/song - var/playing = 0 - var/help = 0 - var/edit = 1 - var/repeat = 0 - -/obj/item/device/violin/proc/playnote(var/note as text) +//copy pasta of the space piano, don't hurt me -Pete + +/obj/item/device/violin + name = "space violin" + desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\"" + icon = 'icons/obj/musician.dmi' + icon_state = "violin" + item_state = "violin" + force = 10 + var/datum/song/song + var/playing = 0 + var/help = 0 + var/edit = 1 + var/repeat = 0 + +/obj/item/device/violin/proc/playnote(var/note as text) // to_chat(world, "Note: [note]") - var/soundfile - /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically. - Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/ - switch(note) - if("Cn1") soundfile = 'sound/violin/Cn1.mid' - if("C#1") soundfile = 'sound/violin/C#1.mid' - if("Db1") soundfile = 'sound/violin/Db1.mid' - if("Dn1") soundfile = 'sound/violin/Dn1.mid' - if("D#1") soundfile = 'sound/violin/D#1.mid' - if("Eb1") soundfile = 'sound/violin/Eb1.mid' - if("En1") soundfile = 'sound/violin/En1.mid' - if("E#1") soundfile = 'sound/violin/E#1.mid' - if("Fb1") soundfile = 'sound/violin/Fb1.mid' - if("Fn1") soundfile = 'sound/violin/Fn1.mid' - if("F#1") soundfile = 'sound/violin/F#1.mid' - if("Gb1") soundfile = 'sound/violin/Gb1.mid' - if("Gn1") soundfile = 'sound/violin/Gn1.mid' - if("G#1") soundfile = 'sound/violin/G#1.mid' - if("Ab1") soundfile = 'sound/violin/Ab1.mid' - if("An1") soundfile = 'sound/violin/An1.mid' - if("A#1") soundfile = 'sound/violin/A#1.mid' - if("Bb1") soundfile = 'sound/violin/Bb1.mid' - if("Bn1") soundfile = 'sound/violin/Bn1.mid' - if("B#1") soundfile = 'sound/violin/B#1.mid' - if("Cb2") soundfile = 'sound/violin/Cb2.mid' - if("Cn2") soundfile = 'sound/violin/Cn2.mid' - if("C#2") soundfile = 'sound/violin/C#2.mid' - if("Db2") soundfile = 'sound/violin/Db2.mid' - if("Dn2") soundfile = 'sound/violin/Dn2.mid' - if("D#2") soundfile = 'sound/violin/D#2.mid' - if("Eb2") soundfile = 'sound/violin/Eb2.mid' - if("En2") soundfile = 'sound/violin/En2.mid' - if("E#2") soundfile = 'sound/violin/E#2.mid' - if("Fb2") soundfile = 'sound/violin/Fb2.mid' - if("Fn2") soundfile = 'sound/violin/Fn2.mid' - if("F#2") soundfile = 'sound/violin/F#2.mid' - if("Gb2") soundfile = 'sound/violin/Gb2.mid' - if("Gn2") soundfile = 'sound/violin/Gn2.mid' - if("G#2") soundfile = 'sound/violin/G#2.mid' - if("Ab2") soundfile = 'sound/violin/Ab2.mid' - if("An2") soundfile = 'sound/violin/An2.mid' - if("A#2") soundfile = 'sound/violin/A#2.mid' - if("Bb2") soundfile = 'sound/violin/Bb2.mid' - if("Bn2") soundfile = 'sound/violin/Bn2.mid' - if("B#2") soundfile = 'sound/violin/B#2.mid' - if("Cb3") soundfile = 'sound/violin/Cb3.mid' - if("Cn3") soundfile = 'sound/violin/Cn3.mid' - if("C#3") soundfile = 'sound/violin/C#3.mid' - if("Db3") soundfile = 'sound/violin/Db3.mid' - if("Dn3") soundfile = 'sound/violin/Dn3.mid' - if("D#3") soundfile = 'sound/violin/D#3.mid' - if("Eb3") soundfile = 'sound/violin/Eb3.mid' - if("En3") soundfile = 'sound/violin/En3.mid' - if("E#3") soundfile = 'sound/violin/E#3.mid' - if("Fb3") soundfile = 'sound/violin/Fb3.mid' - if("Fn3") soundfile = 'sound/violin/Fn3.mid' - if("F#3") soundfile = 'sound/violin/F#3.mid' - if("Gb3") soundfile = 'sound/violin/Gb3.mid' - if("Gn3") soundfile = 'sound/violin/Gn3.mid' - if("G#3") soundfile = 'sound/violin/G#3.mid' - if("Ab3") soundfile = 'sound/violin/Ab3.mid' - if("An3") soundfile = 'sound/violin/An3.mid' - if("A#3") soundfile = 'sound/violin/A#3.mid' - if("Bb3") soundfile = 'sound/violin/Bb3.mid' - if("Bn3") soundfile = 'sound/violin/Bn3.mid' - if("B#3") soundfile = 'sound/violin/B#3.mid' - if("Cb4") soundfile = 'sound/violin/Cb4.mid' - if("Cn4") soundfile = 'sound/violin/Cn4.mid' - if("C#4") soundfile = 'sound/violin/C#4.mid' - if("Db4") soundfile = 'sound/violin/Db4.mid' - if("Dn4") soundfile = 'sound/violin/Dn4.mid' - if("D#4") soundfile = 'sound/violin/D#4.mid' - if("Eb4") soundfile = 'sound/violin/Eb4.mid' - if("En4") soundfile = 'sound/violin/En4.mid' - if("E#4") soundfile = 'sound/violin/E#4.mid' - if("Fb4") soundfile = 'sound/violin/Fb4.mid' - if("Fn4") soundfile = 'sound/violin/Fn4.mid' - if("F#4") soundfile = 'sound/violin/F#4.mid' - if("Gb4") soundfile = 'sound/violin/Gb4.mid' - if("Gn4") soundfile = 'sound/violin/Gn4.mid' - if("G#4") soundfile = 'sound/violin/G#4.mid' - if("Ab4") soundfile = 'sound/violin/Ab4.mid' - if("An4") soundfile = 'sound/violin/An4.mid' - if("A#4") soundfile = 'sound/violin/A#4.mid' - if("Bb4") soundfile = 'sound/violin/Bb4.mid' - if("Bn4") soundfile = 'sound/violin/Bn4.mid' - if("B#4") soundfile = 'sound/violin/B#4.mid' - if("Cb5") soundfile = 'sound/violin/Cb5.mid' - if("Cn5") soundfile = 'sound/violin/Cn5.mid' - if("C#5") soundfile = 'sound/violin/C#5.mid' - if("Db5") soundfile = 'sound/violin/Db5.mid' - if("Dn5") soundfile = 'sound/violin/Dn5.mid' - if("D#5") soundfile = 'sound/violin/D#5.mid' - if("Eb5") soundfile = 'sound/violin/Eb5.mid' - if("En5") soundfile = 'sound/violin/En5.mid' - if("E#5") soundfile = 'sound/violin/E#5.mid' - if("Fb5") soundfile = 'sound/violin/Fb5.mid' - if("Fn5") soundfile = 'sound/violin/Fn5.mid' - if("F#5") soundfile = 'sound/violin/F#5.mid' - if("Gb5") soundfile = 'sound/violin/Gb5.mid' - if("Gn5") soundfile = 'sound/violin/Gn5.mid' - if("G#5") soundfile = 'sound/violin/G#5.mid' - if("Ab5") soundfile = 'sound/violin/Ab5.mid' - if("An5") soundfile = 'sound/violin/An5.mid' - if("A#5") soundfile = 'sound/violin/A#5.mid' - if("Bb5") soundfile = 'sound/violin/Bb5.mid' - if("Bn5") soundfile = 'sound/violin/Bn5.mid' - if("B#5") soundfile = 'sound/violin/B#5.mid' - if("Cb6") soundfile = 'sound/violin/Cb6.mid' - if("Cn6") soundfile = 'sound/violin/Cn6.mid' - if("C#6") soundfile = 'sound/violin/C#6.mid' - if("Db6") soundfile = 'sound/violin/Db6.mid' - if("Dn6") soundfile = 'sound/violin/Dn6.mid' - if("D#6") soundfile = 'sound/violin/D#6.mid' - if("Eb6") soundfile = 'sound/violin/Eb6.mid' - if("En6") soundfile = 'sound/violin/En6.mid' - if("E#6") soundfile = 'sound/violin/E#6.mid' - if("Fb6") soundfile = 'sound/violin/Fb6.mid' - if("Fn6") soundfile = 'sound/violin/Fn6.mid' - if("F#6") soundfile = 'sound/violin/F#6.mid' - if("Gb6") soundfile = 'sound/violin/Gb6.mid' - if("Gn6") soundfile = 'sound/violin/Gn6.mid' - if("G#6") soundfile = 'sound/violin/G#6.mid' - if("Ab6") soundfile = 'sound/violin/Ab6.mid' - if("An6") soundfile = 'sound/violin/An6.mid' - if("A#6") soundfile = 'sound/violin/A#6.mid' - if("Bb6") soundfile = 'sound/violin/Bb6.mid' - if("Bn6") soundfile = 'sound/violin/Bn6.mid' - if("B#6") soundfile = 'sound/violin/B#6.mid' - if("Cb7") soundfile = 'sound/violin/Cb7.mid' - if("Cn7") soundfile = 'sound/violin/Cn7.mid' - if("C#7") soundfile = 'sound/violin/C#7.mid' - if("Db7") soundfile = 'sound/violin/Db7.mid' - if("Dn7") soundfile = 'sound/violin/Dn7.mid' - if("D#7") soundfile = 'sound/violin/D#7.mid' - if("Eb7") soundfile = 'sound/violin/Eb7.mid' - if("En7") soundfile = 'sound/violin/En7.mid' - if("E#7") soundfile = 'sound/violin/E#7.mid' - if("Fb7") soundfile = 'sound/violin/Fb7.mid' - if("Fn7") soundfile = 'sound/violin/Fn7.mid' - if("F#7") soundfile = 'sound/violin/F#7.mid' - if("Gb7") soundfile = 'sound/violin/Gb7.mid' - if("Gn7") soundfile = 'sound/violin/Gn7.mid' - if("G#7") soundfile = 'sound/violin/G#7.mid' - if("Ab7") soundfile = 'sound/violin/Ab7.mid' - if("An7") soundfile = 'sound/violin/An7.mid' - if("A#7") soundfile = 'sound/violin/A#7.mid' - if("Bb7") soundfile = 'sound/violin/Bb7.mid' - if("Bn7") soundfile = 'sound/violin/Bn7.mid' - if("B#7") soundfile = 'sound/violin/B#7.mid' - if("Cb8") soundfile = 'sound/violin/Cb8.mid' - if("Cn8") soundfile = 'sound/violin/Cn8.mid' - if("C#8") soundfile = 'sound/violin/C#8.mid' - if("Db8") soundfile = 'sound/violin/Db8.mid' - if("Dn8") soundfile = 'sound/violin/Dn8.mid' - if("D#8") soundfile = 'sound/violin/D#8.mid' - if("Eb8") soundfile = 'sound/violin/Eb8.mid' - if("En8") soundfile = 'sound/violin/En8.mid' - if("E#8") soundfile = 'sound/violin/E#8.mid' - if("Fb8") soundfile = 'sound/violin/Fb8.mid' - if("Fn8") soundfile = 'sound/violin/Fn8.mid' - if("F#8") soundfile = 'sound/violin/F#8.mid' - if("Gb8") soundfile = 'sound/violin/Gb8.mid' - if("Gn8") soundfile = 'sound/violin/Gn8.mid' - if("G#8") soundfile = 'sound/violin/G#8.mid' - if("Ab8") soundfile = 'sound/violin/Ab8.mid' - if("An8") soundfile = 'sound/violin/An8.mid' - if("A#8") soundfile = 'sound/violin/A#8.mid' - if("Bb8") soundfile = 'sound/violin/Bb8.mid' - if("Bn8") soundfile = 'sound/violin/Bn8.mid' - if("B#8") soundfile = 'sound/violin/B#8.mid' - if("Cb9") soundfile = 'sound/violin/Cb9.mid' - if("Cn9") soundfile = 'sound/violin/Cn9.mid' - else return - + var/soundfile + /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically. + Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/ + switch(note) + if("Cn1") soundfile = 'sound/violin/Cn1.mid' + if("C#1") soundfile = 'sound/violin/C#1.mid' + if("Db1") soundfile = 'sound/violin/Db1.mid' + if("Dn1") soundfile = 'sound/violin/Dn1.mid' + if("D#1") soundfile = 'sound/violin/D#1.mid' + if("Eb1") soundfile = 'sound/violin/Eb1.mid' + if("En1") soundfile = 'sound/violin/En1.mid' + if("E#1") soundfile = 'sound/violin/E#1.mid' + if("Fb1") soundfile = 'sound/violin/Fb1.mid' + if("Fn1") soundfile = 'sound/violin/Fn1.mid' + if("F#1") soundfile = 'sound/violin/F#1.mid' + if("Gb1") soundfile = 'sound/violin/Gb1.mid' + if("Gn1") soundfile = 'sound/violin/Gn1.mid' + if("G#1") soundfile = 'sound/violin/G#1.mid' + if("Ab1") soundfile = 'sound/violin/Ab1.mid' + if("An1") soundfile = 'sound/violin/An1.mid' + if("A#1") soundfile = 'sound/violin/A#1.mid' + if("Bb1") soundfile = 'sound/violin/Bb1.mid' + if("Bn1") soundfile = 'sound/violin/Bn1.mid' + if("B#1") soundfile = 'sound/violin/B#1.mid' + if("Cb2") soundfile = 'sound/violin/Cb2.mid' + if("Cn2") soundfile = 'sound/violin/Cn2.mid' + if("C#2") soundfile = 'sound/violin/C#2.mid' + if("Db2") soundfile = 'sound/violin/Db2.mid' + if("Dn2") soundfile = 'sound/violin/Dn2.mid' + if("D#2") soundfile = 'sound/violin/D#2.mid' + if("Eb2") soundfile = 'sound/violin/Eb2.mid' + if("En2") soundfile = 'sound/violin/En2.mid' + if("E#2") soundfile = 'sound/violin/E#2.mid' + if("Fb2") soundfile = 'sound/violin/Fb2.mid' + if("Fn2") soundfile = 'sound/violin/Fn2.mid' + if("F#2") soundfile = 'sound/violin/F#2.mid' + if("Gb2") soundfile = 'sound/violin/Gb2.mid' + if("Gn2") soundfile = 'sound/violin/Gn2.mid' + if("G#2") soundfile = 'sound/violin/G#2.mid' + if("Ab2") soundfile = 'sound/violin/Ab2.mid' + if("An2") soundfile = 'sound/violin/An2.mid' + if("A#2") soundfile = 'sound/violin/A#2.mid' + if("Bb2") soundfile = 'sound/violin/Bb2.mid' + if("Bn2") soundfile = 'sound/violin/Bn2.mid' + if("B#2") soundfile = 'sound/violin/B#2.mid' + if("Cb3") soundfile = 'sound/violin/Cb3.mid' + if("Cn3") soundfile = 'sound/violin/Cn3.mid' + if("C#3") soundfile = 'sound/violin/C#3.mid' + if("Db3") soundfile = 'sound/violin/Db3.mid' + if("Dn3") soundfile = 'sound/violin/Dn3.mid' + if("D#3") soundfile = 'sound/violin/D#3.mid' + if("Eb3") soundfile = 'sound/violin/Eb3.mid' + if("En3") soundfile = 'sound/violin/En3.mid' + if("E#3") soundfile = 'sound/violin/E#3.mid' + if("Fb3") soundfile = 'sound/violin/Fb3.mid' + if("Fn3") soundfile = 'sound/violin/Fn3.mid' + if("F#3") soundfile = 'sound/violin/F#3.mid' + if("Gb3") soundfile = 'sound/violin/Gb3.mid' + if("Gn3") soundfile = 'sound/violin/Gn3.mid' + if("G#3") soundfile = 'sound/violin/G#3.mid' + if("Ab3") soundfile = 'sound/violin/Ab3.mid' + if("An3") soundfile = 'sound/violin/An3.mid' + if("A#3") soundfile = 'sound/violin/A#3.mid' + if("Bb3") soundfile = 'sound/violin/Bb3.mid' + if("Bn3") soundfile = 'sound/violin/Bn3.mid' + if("B#3") soundfile = 'sound/violin/B#3.mid' + if("Cb4") soundfile = 'sound/violin/Cb4.mid' + if("Cn4") soundfile = 'sound/violin/Cn4.mid' + if("C#4") soundfile = 'sound/violin/C#4.mid' + if("Db4") soundfile = 'sound/violin/Db4.mid' + if("Dn4") soundfile = 'sound/violin/Dn4.mid' + if("D#4") soundfile = 'sound/violin/D#4.mid' + if("Eb4") soundfile = 'sound/violin/Eb4.mid' + if("En4") soundfile = 'sound/violin/En4.mid' + if("E#4") soundfile = 'sound/violin/E#4.mid' + if("Fb4") soundfile = 'sound/violin/Fb4.mid' + if("Fn4") soundfile = 'sound/violin/Fn4.mid' + if("F#4") soundfile = 'sound/violin/F#4.mid' + if("Gb4") soundfile = 'sound/violin/Gb4.mid' + if("Gn4") soundfile = 'sound/violin/Gn4.mid' + if("G#4") soundfile = 'sound/violin/G#4.mid' + if("Ab4") soundfile = 'sound/violin/Ab4.mid' + if("An4") soundfile = 'sound/violin/An4.mid' + if("A#4") soundfile = 'sound/violin/A#4.mid' + if("Bb4") soundfile = 'sound/violin/Bb4.mid' + if("Bn4") soundfile = 'sound/violin/Bn4.mid' + if("B#4") soundfile = 'sound/violin/B#4.mid' + if("Cb5") soundfile = 'sound/violin/Cb5.mid' + if("Cn5") soundfile = 'sound/violin/Cn5.mid' + if("C#5") soundfile = 'sound/violin/C#5.mid' + if("Db5") soundfile = 'sound/violin/Db5.mid' + if("Dn5") soundfile = 'sound/violin/Dn5.mid' + if("D#5") soundfile = 'sound/violin/D#5.mid' + if("Eb5") soundfile = 'sound/violin/Eb5.mid' + if("En5") soundfile = 'sound/violin/En5.mid' + if("E#5") soundfile = 'sound/violin/E#5.mid' + if("Fb5") soundfile = 'sound/violin/Fb5.mid' + if("Fn5") soundfile = 'sound/violin/Fn5.mid' + if("F#5") soundfile = 'sound/violin/F#5.mid' + if("Gb5") soundfile = 'sound/violin/Gb5.mid' + if("Gn5") soundfile = 'sound/violin/Gn5.mid' + if("G#5") soundfile = 'sound/violin/G#5.mid' + if("Ab5") soundfile = 'sound/violin/Ab5.mid' + if("An5") soundfile = 'sound/violin/An5.mid' + if("A#5") soundfile = 'sound/violin/A#5.mid' + if("Bb5") soundfile = 'sound/violin/Bb5.mid' + if("Bn5") soundfile = 'sound/violin/Bn5.mid' + if("B#5") soundfile = 'sound/violin/B#5.mid' + if("Cb6") soundfile = 'sound/violin/Cb6.mid' + if("Cn6") soundfile = 'sound/violin/Cn6.mid' + if("C#6") soundfile = 'sound/violin/C#6.mid' + if("Db6") soundfile = 'sound/violin/Db6.mid' + if("Dn6") soundfile = 'sound/violin/Dn6.mid' + if("D#6") soundfile = 'sound/violin/D#6.mid' + if("Eb6") soundfile = 'sound/violin/Eb6.mid' + if("En6") soundfile = 'sound/violin/En6.mid' + if("E#6") soundfile = 'sound/violin/E#6.mid' + if("Fb6") soundfile = 'sound/violin/Fb6.mid' + if("Fn6") soundfile = 'sound/violin/Fn6.mid' + if("F#6") soundfile = 'sound/violin/F#6.mid' + if("Gb6") soundfile = 'sound/violin/Gb6.mid' + if("Gn6") soundfile = 'sound/violin/Gn6.mid' + if("G#6") soundfile = 'sound/violin/G#6.mid' + if("Ab6") soundfile = 'sound/violin/Ab6.mid' + if("An6") soundfile = 'sound/violin/An6.mid' + if("A#6") soundfile = 'sound/violin/A#6.mid' + if("Bb6") soundfile = 'sound/violin/Bb6.mid' + if("Bn6") soundfile = 'sound/violin/Bn6.mid' + if("B#6") soundfile = 'sound/violin/B#6.mid' + if("Cb7") soundfile = 'sound/violin/Cb7.mid' + if("Cn7") soundfile = 'sound/violin/Cn7.mid' + if("C#7") soundfile = 'sound/violin/C#7.mid' + if("Db7") soundfile = 'sound/violin/Db7.mid' + if("Dn7") soundfile = 'sound/violin/Dn7.mid' + if("D#7") soundfile = 'sound/violin/D#7.mid' + if("Eb7") soundfile = 'sound/violin/Eb7.mid' + if("En7") soundfile = 'sound/violin/En7.mid' + if("E#7") soundfile = 'sound/violin/E#7.mid' + if("Fb7") soundfile = 'sound/violin/Fb7.mid' + if("Fn7") soundfile = 'sound/violin/Fn7.mid' + if("F#7") soundfile = 'sound/violin/F#7.mid' + if("Gb7") soundfile = 'sound/violin/Gb7.mid' + if("Gn7") soundfile = 'sound/violin/Gn7.mid' + if("G#7") soundfile = 'sound/violin/G#7.mid' + if("Ab7") soundfile = 'sound/violin/Ab7.mid' + if("An7") soundfile = 'sound/violin/An7.mid' + if("A#7") soundfile = 'sound/violin/A#7.mid' + if("Bb7") soundfile = 'sound/violin/Bb7.mid' + if("Bn7") soundfile = 'sound/violin/Bn7.mid' + if("B#7") soundfile = 'sound/violin/B#7.mid' + if("Cb8") soundfile = 'sound/violin/Cb8.mid' + if("Cn8") soundfile = 'sound/violin/Cn8.mid' + if("C#8") soundfile = 'sound/violin/C#8.mid' + if("Db8") soundfile = 'sound/violin/Db8.mid' + if("Dn8") soundfile = 'sound/violin/Dn8.mid' + if("D#8") soundfile = 'sound/violin/D#8.mid' + if("Eb8") soundfile = 'sound/violin/Eb8.mid' + if("En8") soundfile = 'sound/violin/En8.mid' + if("E#8") soundfile = 'sound/violin/E#8.mid' + if("Fb8") soundfile = 'sound/violin/Fb8.mid' + if("Fn8") soundfile = 'sound/violin/Fn8.mid' + if("F#8") soundfile = 'sound/violin/F#8.mid' + if("Gb8") soundfile = 'sound/violin/Gb8.mid' + if("Gn8") soundfile = 'sound/violin/Gn8.mid' + if("G#8") soundfile = 'sound/violin/G#8.mid' + if("Ab8") soundfile = 'sound/violin/Ab8.mid' + if("An8") soundfile = 'sound/violin/An8.mid' + if("A#8") soundfile = 'sound/violin/A#8.mid' + if("Bb8") soundfile = 'sound/violin/Bb8.mid' + if("Bn8") soundfile = 'sound/violin/Bn8.mid' + if("B#8") soundfile = 'sound/violin/B#8.mid' + if("Cb9") soundfile = 'sound/violin/Cb9.mid' + if("Cn9") soundfile = 'sound/violin/Cn9.mid' + else return + to_chat(hearers(15, get_turf(src)), sound(soundfile)) - -/obj/item/device/violin/proc/playsong() - do - var/cur_oct[7] - var/cur_acc[7] - for(var/i = 1 to 7) - cur_oct[i] = "3" - cur_acc[i] = "n" - - for(var/line in song.lines) + +/obj/item/device/violin/proc/playsong() + do + var/cur_oct[7] + var/cur_acc[7] + for(var/i = 1 to 7) + cur_oct[i] = "3" + cur_acc[i] = "n" + + for(var/line in song.lines) // to_chat(world, line) - for(var/beat in text2list(lowertext(line), ",")) + for(var/beat in text2list(lowertext(line), ",")) // to_chat(world, "beat: [beat]") - var/list/notes = text2list(beat, "/") - for(var/note in text2list(notes[1], "-")) + var/list/notes = text2list(beat, "/") + for(var/note in text2list(notes[1], "-")) // to_chat(world, "note: [note]") - if(!playing || !isliving(loc))//If the violin is playing, or isn't held by a person - playing = 0 - return - if(length(note) == 0) - continue + if(!playing || !isliving(loc))//If the violin is playing, or isn't held by a person + playing = 0 + return + if(length(note) == 0) + continue // to_chat(world, "Parse: [copytext(note,1,2)]") - var/cur_note = text2ascii(note) - 96 - if(cur_note < 1 || cur_note > 7) - continue - for(var/i=2 to length(note)) - var/ni = copytext(note,i,i+1) - if(!text2num(ni)) - if(ni == "#" || ni == "b" || ni == "n") - cur_acc[cur_note] = ni - else if(ni == "s") - cur_acc[cur_note] = "#" // so shift is never required - else - cur_oct[cur_note] = ni - playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note]) - if(notes.len >= 2 && text2num(notes[2])) - sleep(song.tempo / text2num(notes[2])) - else - sleep(song.tempo) - if(repeat > 0) - repeat-- //Infinite loops are baaaad. - while(repeat > 0) - playing = 0 - -/obj/item/device/violin/attack_self(mob/user as mob) - if(!isliving(user) || user.stat || user.restrained() || user.lying) return - user.set_machine(src) - - var/dat = "Violin" - - if(song) - if(song.lines.len > 0 && !(playing)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\violin.dm:246: dat += "Play Song

    " - dat += {"Play Song

    - Repeat Song: [repeat] times.

    "} - // END AUTOFIX - if(playing) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\violin.dm:249: dat += "Stop Playing
    " - dat += {"Stop Playing
    - Repeats left: [repeat].

    "} - // END AUTOFIX - if(!edit) - dat += "Show Editor

    " - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\violin.dm:254: dat += "Hide Editor
    " - dat += {"Hide Editor
    - Start a New Song
    - Import a Song

    "} - // END AUTOFIX - if(song) - var/calctempo = (10/song.tempo)*60 - dat += "Tempo : -- [calctempo] BPM ++

    " - var/linecount = 0 - for(var/line in song.lines) - linecount += 1 - dat += "Line [linecount]: [line] Delete Line Modify Line
    " - dat += "Add Line

    " - if(help) - dat += "Hide Help
    " - dat += {" - Lines are a series of chords, separated by commas (,), each with notes seperated by hyphens (-).
    - Every note in a chord will play together, with chord timed by the tempo.
    -
    - Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
    - By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
    - Example: C,D,E,F,G,A,B will play a C major scale.
    - After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3

    - Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
    - A pause may be denoted by an empty chord: C,E,,C,G
    - To make a chord be a different time, end it with /x, where the chord length will be length
    - defined by tempo / x: C,G/2,E/4
    - Combined, an example is: E-E4/4,/2,G#/8,B/8,E3-E4/4 -
    - Lines may be up to 50 characters.
    - A song may only contain up to 50 lines.
    - "} - else - dat += "Show Help
    " - dat += "" - user << browse(dat, "window=violin;size=700x300") - onclose(user, "violin") - -/obj/item/device/violin/Topic(href, href_list) - if(..()) - return - - usr.set_machine(src) - - if(href_list["newsong"]) - song = new() - else if(song) - if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. - if(playing) return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. - var/tempnum = input("How many times do you want to repeat this piece? (max:10)") as num|null - if(tempnum > 10) - tempnum = 10 - if(tempnum < 0) - tempnum = 0 - repeat = round(tempnum) - - else if(href_list["tempo"]) - song.tempo += round(text2num(href_list["tempo"])) - if(song.tempo < 1) - song.tempo = 1 - - else if(href_list["play"]) - if(song) - playing = 1 - spawn() playsong() - - else if(href_list["newline"]) - var/newline = html_encode(input("Enter your line: ", "violin") as text|null) - if(!newline) - return - if(song.lines.len > 50) - return - if(length(newline) > 50) - newline = copytext(newline, 1, 50) - song.lines.Add(newline) - - else if(href_list["deleteline"]) - var/num = round(text2num(href_list["deleteline"])) - if(num > song.lines.len || num < 1) - return - song.lines.Cut(num, num+1) - - else if(href_list["modifyline"]) - var/num = round(text2num(href_list["modifyline"]),1) - var/content = html_encode(input("Enter your line: ", "violin", song.lines[num]) as text|null) - if(!content) - return - if(length(content) > 50) - content = copytext(content, 1, 50) - if(num > song.lines.len || num < 1) - return - song.lines[num] = content - - else if(href_list["stop"]) - playing = 0 - - else if(href_list["help"]) - help = text2num(href_list["help"]) - 1 - - else if(href_list["edit"]) - edit = text2num(href_list["edit"]) - 1 - - else if(href_list["import"]) - var/t = "" - do - t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) - if(!in_range(src, usr)) - return - - if(length(t) >= 3072) - var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") - if(cont == "no") - break - while(length(t) > 3072) - - //split into lines - spawn() - var/list/lines = text2list(t, "\n") - var/tempo = 5 - if(copytext(lines[1],1,6) == "BPM: ") - tempo = 600 / text2num(copytext(lines[1],6)) - lines.Cut(1,2) - if(lines.len > 50) + var/cur_note = text2ascii(note) - 96 + if(cur_note < 1 || cur_note > 7) + continue + for(var/i=2 to length(note)) + var/ni = copytext(note,i,i+1) + if(!text2num(ni)) + if(ni == "#" || ni == "b" || ni == "n") + cur_acc[cur_note] = ni + else if(ni == "s") + cur_acc[cur_note] = "#" // so shift is never required + else + cur_oct[cur_note] = ni + playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note]) + if(notes.len >= 2 && text2num(notes[2])) + sleep(song.tempo / text2num(notes[2])) + else + sleep(song.tempo) + if(repeat > 0) + repeat-- //Infinite loops are baaaad. + while(repeat > 0) + playing = 0 + +/obj/item/device/violin/attack_self(mob/user as mob) + if(!isliving(user) || user.stat || user.restrained() || user.lying) return + user.set_machine(src) + + var/dat = "Violin" + + if(song) + if(song.lines.len > 0 && !(playing)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\violin.dm:246: dat += "Play Song

    " + dat += {"Play Song

    + Repeat Song: [repeat] times.

    "} + // END AUTOFIX + if(playing) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\violin.dm:249: dat += "Stop Playing
    " + dat += {"Stop Playing
    + Repeats left: [repeat].

    "} + // END AUTOFIX + if(!edit) + dat += "Show Editor

    " + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\\devices\violin.dm:254: dat += "Hide Editor
    " + dat += {"Hide Editor
    + Start a New Song
    + Import a Song

    "} + // END AUTOFIX + if(song) + var/calctempo = (10/song.tempo)*60 + dat += "Tempo : -- [calctempo] BPM ++

    " + var/linecount = 0 + for(var/line in song.lines) + linecount += 1 + dat += "Line [linecount]: [line] Delete Line Modify Line
    " + dat += "Add Line

    " + if(help) + dat += "Hide Help
    " + dat += {" + Lines are a series of chords, separated by commas (,), each with notes seperated by hyphens (-).
    + Every note in a chord will play together, with chord timed by the tempo.
    +
    + Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
    + By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
    + Example: C,D,E,F,G,A,B will play a C major scale.
    + After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
    + Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
    + A pause may be denoted by an empty chord: C,E,,C,G
    + To make a chord be a different time, end it with /x, where the chord length will be length
    + defined by tempo / x: C,G/2,E/4
    + Combined, an example is: E-E4/4,/2,G#/8,B/8,E3-E4/4 +
    + Lines may be up to 50 characters.
    + A song may only contain up to 50 lines.
    + "} + else + dat += "Show Help
    " + dat += "" + user << browse(dat, "window=violin;size=700x300") + onclose(user, "violin") + +/obj/item/device/violin/Topic(href, href_list) + if(..()) + return + + usr.set_machine(src) + + if(href_list["newsong"]) + song = new() + else if(song) + if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. + if(playing) return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. + var/tempnum = input("How many times do you want to repeat this piece? (max:10)") as num|null + if(tempnum > 10) + tempnum = 10 + if(tempnum < 0) + tempnum = 0 + repeat = round(tempnum) + + else if(href_list["tempo"]) + song.tempo += round(text2num(href_list["tempo"])) + if(song.tempo < 1) + song.tempo = 1 + + else if(href_list["play"]) + if(song) + playing = 1 + spawn() playsong() + + else if(href_list["newline"]) + var/newline = html_encode(input("Enter your line: ", "violin") as text|null) + if(!newline) + return + if(song.lines.len > 50) + return + if(length(newline) > 50) + newline = copytext(newline, 1, 50) + song.lines.Add(newline) + + else if(href_list["deleteline"]) + var/num = round(text2num(href_list["deleteline"])) + if(num > song.lines.len || num < 1) + return + song.lines.Cut(num, num+1) + + else if(href_list["modifyline"]) + var/num = round(text2num(href_list["modifyline"]),1) + var/content = html_encode(input("Enter your line: ", "violin", song.lines[num]) as text|null) + if(!content) + return + if(length(content) > 50) + content = copytext(content, 1, 50) + if(num > song.lines.len || num < 1) + return + song.lines[num] = content + + else if(href_list["stop"]) + playing = 0 + + else if(href_list["help"]) + help = text2num(href_list["help"]) - 1 + + else if(href_list["edit"]) + edit = text2num(href_list["edit"]) - 1 + + else if(href_list["import"]) + var/t = "" + do + t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) + if(!in_range(src, usr)) + return + + if(length(t) >= 3072) + var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") + if(cont == "no") + break + while(length(t) > 3072) + + //split into lines + spawn() + var/list/lines = text2list(t, "\n") + var/tempo = 5 + if(copytext(lines[1],1,6) == "BPM: ") + tempo = 600 / text2num(copytext(lines[1],6)) + lines.Cut(1,2) + if(lines.len > 50) to_chat(usr, "Too many lines!") - lines.Cut(51) - var/linenum = 1 - for(var/l in lines) - if(length(l) > 50) + lines.Cut(51) + var/linenum = 1 + for(var/l in lines) + if(length(l) > 50) to_chat(usr, "Line [linenum] too long!") - lines.Remove(l) - else - linenum++ - song = new() - song.lines = lines - song.tempo = tempo - - add_fingerprint(usr) - src.updateUsrDialog() - //for(var/mob/M in viewers(1, loc)) - // if((M.client && M.machine == src)) - // attack_self(M) + lines.Remove(l) + else + linenum++ + song = new() + song.lines = lines + song.tempo = tempo + + add_fingerprint(usr) + src.updateUsrDialog() + //for(var/mob/M in viewers(1, loc)) + // if((M.client && M.machine == src)) + // attack_self(M) return \ No newline at end of file diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index ea32af49ba5..bb15959bf83 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -1,48 +1,48 @@ -/obj/item/latexballon - name = "Latex glove" - desc = "" //todo - icon_state = "latexballon" - item_state = "lgloves" - force = 0 - throwforce = 0 - w_class = 1.0 - throw_speed = 1 - throw_range = 15 - var/state - var/datum/gas_mixture/air_contents = null - -/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank) - if (icon_state == "latexballon_bursted") - return - src.air_contents = tank.remove_air_volume(3) - icon_state = "latexballon_blow" - item_state = "latexballon" - -/obj/item/latexballon/proc/burst() - if (!air_contents) - return - playsound(src, 'sound/weapons/Gunshot.ogg', 100, 1) - icon_state = "latexballon_bursted" - item_state = "lgloves" - loc.assume_air(air_contents) - -/obj/item/latexballon/ex_act(severity) - burst() - switch(severity) - if (1) - qdel(src) - if (2) - if (prob(50)) - qdel(src) - -/obj/item/latexballon/bullet_act() - burst() - -/obj/item/latexballon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C+100) - burst() - return - -/obj/item/latexballon/attackby(obj/item/W as obj, mob/user as mob) - if (is_sharp(W)) +/obj/item/latexballon + name = "Latex glove" + desc = "" //todo + icon_state = "latexballon" + item_state = "lgloves" + force = 0 + throwforce = 0 + w_class = 1.0 + throw_speed = 1 + throw_range = 15 + var/state + var/datum/gas_mixture/air_contents = null + +/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank) + if (icon_state == "latexballon_bursted") + return + src.air_contents = tank.remove_air_volume(3) + icon_state = "latexballon_blow" + item_state = "latexballon" + +/obj/item/latexballon/proc/burst() + if (!air_contents) + return + playsound(src, 'sound/weapons/Gunshot.ogg', 100, 1) + icon_state = "latexballon_bursted" + item_state = "lgloves" + loc.assume_air(air_contents) + +/obj/item/latexballon/ex_act(severity) + burst() + switch(severity) + if (1) + qdel(src) + if (2) + if (prob(50)) + qdel(src) + +/obj/item/latexballon/bullet_act() + burst() + +/obj/item/latexballon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > T0C+100) + burst() + return + +/obj/item/latexballon/attackby(obj/item/W as obj, mob/user as mob) + if (is_sharp(W)) burst() \ No newline at end of file diff --git a/code/game/objects/items/mountable_frames/newscaster.dm b/code/game/objects/items/mountable_frames/newscaster.dm index ef3ab171cb2..51228500407 100644 --- a/code/game/objects/items/mountable_frames/newscaster.dm +++ b/code/game/objects/items/mountable_frames/newscaster.dm @@ -1,12 +1,12 @@ -/obj/item/mounted/frame/newscaster - name = "Unhinged Newscaster" - desc = "The difference between an unhinged newscaster and a journalist is that one of them is actually crazy." - icon = 'icons/obj/terminals.dmi' - icon_state = "newscaster_assembly" - flags = FPRINT - w_type=2*RECYK_METAL - mount_reqs = list("nospace", "simfloor") - -/obj/item/mounted/frame/newscaster/do_build(turf/on_wall, mob/user) - new /obj/machinery/newscaster(get_turf(src), get_dir(user, on_wall), 0) - qdel(src) +/obj/item/mounted/frame/newscaster + name = "Unhinged Newscaster" + desc = "The difference between an unhinged newscaster and a journalist is that one of them is actually crazy." + icon = 'icons/obj/terminals.dmi' + icon_state = "newscaster_assembly" + flags = FPRINT + w_type=2*RECYK_METAL + mount_reqs = list("nospace", "simfloor") + +/obj/item/mounted/frame/newscaster/do_build(turf/on_wall, mob/user) + new /obj/machinery/newscaster(get_turf(src), get_dir(user, on_wall), 0) + qdel(src) diff --git a/code/game/objects/items/mountable_frames/sound_system.dm b/code/game/objects/items/mountable_frames/sound_system.dm index 7ebb5937943..9782f337e43 100644 --- a/code/game/objects/items/mountable_frames/sound_system.dm +++ b/code/game/objects/items/mountable_frames/sound_system.dm @@ -1,12 +1,12 @@ -/obj/item/mounted/frame/soundsystem - name = "sound system frame" - desc = "Used for repairing or building sound systems" - icon = 'icons/obj/radio.dmi' - icon_state = "wallradio" - flags = FPRINT - w_type=2*RECYK_METAL - mount_reqs = list("nospace", "simfloor") - -/obj/item/mounted/frame/soundsystem/do_build(turf/on_wall, mob/user) - new /obj/machinery/media/receiver/boombox/wallmount(get_turf(src), get_dir(user, on_wall), 0) - qdel(src) +/obj/item/mounted/frame/soundsystem + name = "sound system frame" + desc = "Used for repairing or building sound systems" + icon = 'icons/obj/radio.dmi' + icon_state = "wallradio" + flags = FPRINT + w_type=2*RECYK_METAL + mount_reqs = list("nospace", "simfloor") + +/obj/item/mounted/frame/soundsystem/do_build(turf/on_wall, mob/user) + new /obj/machinery/media/receiver/boombox/wallmount(get_turf(src), get_dir(user, on_wall), 0) + qdel(src) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 0a5f1afde72..03159093364 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -1,37 +1,37 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/********************************************************************** - Cyborg Spec Items -***********************************************************************/ -//Might want to move this into several files later but for now it works here -/obj/item/borg/stun - name = "electrified arm" - icon = 'icons/obj/decals.dmi' - icon_state = "shock" - - attack(mob/M as mob, mob/living/silicon/robot/user as mob) - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") - - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - user.cell.charge -= 30 - - M.Weaken(5) - if (M.stuttering < 5) - M.stuttering = 5 - M.Stun(5) - - for(var/mob/O in viewers(M, null)) - if (O.client) - O.show_message("[user] has prodded [M] with an electrically-charged arm!", 1, "You hear someone fall", 2) - -/obj/item/borg/overdrive - name = "overdrive" - icon = 'icons/obj/decals.dmi' - icon_state = "shock" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/********************************************************************** + Cyborg Spec Items +***********************************************************************/ +//Might want to move this into several files later but for now it works here +/obj/item/borg/stun + name = "electrified arm" + icon = 'icons/obj/decals.dmi' + icon_state = "shock" + + attack(mob/M as mob, mob/living/silicon/robot/user as mob) + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") + + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + user.cell.charge -= 30 + + M.Weaken(5) + if (M.stuttering < 5) + M.stuttering = 5 + M.Stun(5) + + for(var/mob/O in viewers(M, null)) + if (O.client) + O.show_message("[user] has prodded [M] with an electrically-charged arm!", 1, "You hear someone fall", 2) + +/obj/item/borg/overdrive + name = "overdrive" + icon = 'icons/obj/decals.dmi' + icon_state = "shock" diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index cb1d694e91f..5a47e6f4e2c 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -1,181 +1,181 @@ -// Targets, the things that actually get shot! -/obj/item/target - name = "shooting target" - desc = "A shooting target." - icon = 'icons/obj/objects.dmi' - icon_state = "target_h" - density = 0 - var/hp = 1800 - var/icon/virtualIcon - var/list/bulletholes = list() - - Destroy() - // if a target is deleted and associated with a stake, force stake to forget - for(var/obj/structure/target_stake/T in view(3,src)) - if(T.pinned_target == src) - T.pinned_target = null - T.density = 1 - break - ..() // delete target - - Move() - ..() - // After target moves, check for nearby stakes. If associated, move to target - for(var/obj/structure/target_stake/M in view(3,src)) - if(M.density == 0 && M.pinned_target == src) - M.loc = loc - - // This may seem a little counter-intuitive but I assure you that's for a purpose. - // Stakes are the ones that carry targets, yes, but in the stake code we set - // a stake's density to 0 meaning it can't be pushed anymore. Instead of pushing - // the stake now, we have to push the target. - - - - attackby(obj/item/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - overlays.len = 0 +// Targets, the things that actually get shot! +/obj/item/target + name = "shooting target" + desc = "A shooting target." + icon = 'icons/obj/objects.dmi' + icon_state = "target_h" + density = 0 + var/hp = 1800 + var/icon/virtualIcon + var/list/bulletholes = list() + + Destroy() + // if a target is deleted and associated with a stake, force stake to forget + for(var/obj/structure/target_stake/T in view(3,src)) + if(T.pinned_target == src) + T.pinned_target = null + T.density = 1 + break + ..() // delete target + + Move() + ..() + // After target moves, check for nearby stakes. If associated, move to target + for(var/obj/structure/target_stake/M in view(3,src)) + if(M.density == 0 && M.pinned_target == src) + M.loc = loc + + // This may seem a little counter-intuitive but I assure you that's for a purpose. + // Stakes are the ones that carry targets, yes, but in the stake code we set + // a stake's density to 0 meaning it can't be pushed anymore. Instead of pushing + // the stake now, we have to push the target. + + + + attackby(obj/item/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + overlays.len = 0 to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") - return - - - attack_hand(mob/user as mob) - // taking pinned targets off! - var/obj/structure/target_stake/stake - for(var/obj/structure/target_stake/T in view(3,src)) - if(T.pinned_target == src) - stake = T - break - - if(stake) - if(stake.pinned_target) - stake.density = 1 - density = 0 - layer = OBJ_LAYER - - loc = user.loc - if(ishuman(user)) - if(!user.get_active_hand()) - user.put_in_hands(src) + return + + + attack_hand(mob/user as mob) + // taking pinned targets off! + var/obj/structure/target_stake/stake + for(var/obj/structure/target_stake/T in view(3,src)) + if(T.pinned_target == src) + stake = T + break + + if(stake) + if(stake.pinned_target) + stake.density = 1 + density = 0 + layer = OBJ_LAYER + + loc = user.loc + if(ishuman(user)) + if(!user.get_active_hand()) + user.put_in_hands(src) to_chat(user, "You take the target out of the stake.") - else - src.loc = get_turf(user) + else + src.loc = get_turf(user) to_chat(user, "You take the target out of the stake.") - - stake.pinned_target = null - return - - else - ..() - - syndicate - icon_state = "target_s" - desc = "A shooting target that looks like a syndicate scum." - hp = 2600 // i guess syndie targets are sturdier? - alien - icon_state = "target_q" - desc = "A shooting target that looks like a xenomorphic alien." - hp = 2350 // alium onest too kinda - -/obj/item/target/bullet_act(var/obj/item/projectile/Proj) - var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!" - var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1) - var/decaltype = 1 // 1 - scorch, 2 - bullet - - if(istype(/obj/item/projectile/bullet, Proj)) - decaltype = 2 - - - virtualIcon = new(icon, icon_state) - - if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null) - - hp -= Proj.damage - if(hp <= 0) - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) + + stake.pinned_target = null + return + + else + ..() + + syndicate + icon_state = "target_s" + desc = "A shooting target that looks like a syndicate scum." + hp = 2600 // i guess syndie targets are sturdier? + alien + icon_state = "target_q" + desc = "A shooting target that looks like a xenomorphic alien." + hp = 2350 // alium onest too kinda + +/obj/item/target/bullet_act(var/obj/item/projectile/Proj) + var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!" + var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1) + var/decaltype = 1 // 1 - scorch, 2 - bullet + + if(istype(/obj/item/projectile/bullet, Proj)) + decaltype = 2 + + + virtualIcon = new(icon, icon_state) + + if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null) + + hp -= Proj.damage + if(hp <= 0) + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) to_chat(O, "[src] breaks into tiny pieces and collapses!") - qdel(src) - - // Create a temporary object to represent the damage - var/obj/bmark = new - bmark.pixel_x = p_x - bmark.pixel_y = p_y - bmark.icon = 'icons/effects/effects.dmi' - bmark.layer = 3.5 - bmark.icon_state = "scorch" - - if(decaltype == 1) - // Energy weapons are hot. they scorch! - - // offset correction - bmark.pixel_x-- - bmark.pixel_y-- - - if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice)) - bmark.icon_state = "scorch" - bmark.dir = pick(NORTH,SOUTH,EAST,WEST) // random scorch design - - - else - bmark.icon_state = "light_scorch" - else - - // Bullets are hard. They make dents! - bmark.icon_state = "dent" - - if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes - if(decaltype == 2) // bullet - if(prob(Proj.damage+30)) // bullets make holes more commonly! - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole - else // Lasers! - if(prob(Proj.damage-10)) // lasers make holes less commonly - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole - - // draw bullet holes - for(var/datum/bullethole/B in bulletholes) - - virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right - virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom - - overlays += bmark // add the decal - - icon = virtualIcon // apply bulletholes over decals - - return - - return -1 // the bullet/projectile goes through the target! Ie, you missed - - -// Small memory holder entity for transparent bullet holes -/datum/bullethole - // First box - var/b1x1 = 0 - var/b1x2 = 0 - var/b1y = 0 - - // Second box - var/b2x = 0 - var/b2y1 = 0 - var/b2y2 = 0 - - New(var/obj/item/target/Target, var/pixel_x = 0, var/pixel_y = 0) - if(!Target) return - - // Randomize the first box - b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4) - b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4) - b1y = pixel_y - if(prob(35)) - b1y += rand(-4,4) - - // Randomize the second box - b2x = pixel_x - if(prob(35)) - b2x += rand(-4,4) - b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) - b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) - - Target.bulletholes.Add(src) + qdel(src) + + // Create a temporary object to represent the damage + var/obj/bmark = new + bmark.pixel_x = p_x + bmark.pixel_y = p_y + bmark.icon = 'icons/effects/effects.dmi' + bmark.layer = 3.5 + bmark.icon_state = "scorch" + + if(decaltype == 1) + // Energy weapons are hot. they scorch! + + // offset correction + bmark.pixel_x-- + bmark.pixel_y-- + + if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice)) + bmark.icon_state = "scorch" + bmark.dir = pick(NORTH,SOUTH,EAST,WEST) // random scorch design + + + else + bmark.icon_state = "light_scorch" + else + + // Bullets are hard. They make dents! + bmark.icon_state = "dent" + + if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes + if(decaltype == 2) // bullet + if(prob(Proj.damage+30)) // bullets make holes more commonly! + new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole + else // Lasers! + if(prob(Proj.damage-10)) // lasers make holes less commonly + new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole + + // draw bullet holes + for(var/datum/bullethole/B in bulletholes) + + virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right + virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom + + overlays += bmark // add the decal + + icon = virtualIcon // apply bulletholes over decals + + return + + return -1 // the bullet/projectile goes through the target! Ie, you missed + + +// Small memory holder entity for transparent bullet holes +/datum/bullethole + // First box + var/b1x1 = 0 + var/b1x2 = 0 + var/b1y = 0 + + // Second box + var/b2x = 0 + var/b2y1 = 0 + var/b2y2 = 0 + + New(var/obj/item/target/Target, var/pixel_x = 0, var/pixel_y = 0) + if(!Target) return + + // Randomize the first box + b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4) + b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4) + b1y = pixel_y + if(prob(35)) + b1y += rand(-4,4) + + // Randomize the second box + b2x = pixel_x + if(prob(35)) + b2x += rand(-4,4) + b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) + b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) + + Target.bulletholes.Add(src) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index a37c891fead..baaef8b7260 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -1,270 +1,270 @@ -/obj/item/stack/medical - name = "medical pack" - singular_name = "medical pack" - icon = 'icons/obj/items.dmi' - amount = 5 - max_amount = 5 - w_class = 1 - throw_speed = 4 - throw_range = 10 - var/heal_brute = 0 - var/heal_burn = 0 - -/obj/item/stack/medical/attack(mob/living/carbon/M as mob, mob/user as mob) - - if(!istype(M)) +/obj/item/stack/medical + name = "medical pack" + singular_name = "medical pack" + icon = 'icons/obj/items.dmi' + amount = 5 + max_amount = 5 + w_class = 1 + throw_speed = 4 + throw_range = 10 + var/heal_brute = 0 + var/heal_burn = 0 + +/obj/item/stack/medical/attack(mob/living/carbon/M as mob, mob/user as mob) + + if(!istype(M)) to_chat(user, "\The [src] cannot be applied to [M]!") - return 1 - - if (!user.dexterity_check()) + return 1 + + if (!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") - return 1 - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - - if(affecting.display_name == "head") - if(H.head && istype(H.head,/obj/item/clothing/head/helmet/space)) + return 1 + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(affecting.display_name == "head") + if(H.head && istype(H.head,/obj/item/clothing/head/helmet/space)) to_chat(user, "You can't apply \the [src] through \the [H.head]!") - return 1 - else - if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) + return 1 + else + if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) to_chat(user, "You can't apply \the [src] through \the [H.wear_suit]!") - return 1 - - if(affecting.status & ORGAN_ROBOT) + return 1 + + if(affecting.status & ORGAN_ROBOT) to_chat(user, "This isn't useful at all on a robotic limb.") - return 1 - - if(affecting.status & ORGAN_PEG) + return 1 + + if(affecting.status & ORGAN_PEG) to_chat(user, "This isn't useful at all on a peg limb.") - return 1 - - H.UpdateDamageIcon() - - else - - M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2)) - user.visible_message( \ - "[user] applies \the [src] to [M].", \ - "You apply \the [src] to [M]." \ - ) - use(1) - - M.updatehealth() -/obj/item/stack/medical/bruise_pack - name = "roll of gauze" - singular_name = "gauze length" - desc = "Some sterile gauze to wrap around bloody stumps." - icon_state = "brutepack" - origin_tech = "biotech=1" - -/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) - if(..()) - return 1 - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - - if(affecting.open == 0) - if(!affecting.bandage()) + return 1 + + H.UpdateDamageIcon() + + else + + M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2)) + user.visible_message( \ + "[user] applies \the [src] to [M].", \ + "You apply \the [src] to [M]." \ + ) + use(1) + + M.updatehealth() +/obj/item/stack/medical/bruise_pack + name = "roll of gauze" + singular_name = "gauze length" + desc = "Some sterile gauze to wrap around bloody stumps." + icon_state = "brutepack" + origin_tech = "biotech=1" + +/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(affecting.open == 0) + if(!affecting.bandage()) to_chat(user, "The wounds on [M]'s [affecting.display_name] have already been bandaged.") - return 1 - else - for(var/datum/wound/W in affecting.wounds) - if(W.internal) - continue - if(W.current_stage <= W.max_bleeding_stage) - user.visible_message("[user] bandages \the [W.desc] on [M]'s [affecting.display_name].", \ - "You bandage \the [W.desc] on [M]'s [affecting.display_name].") - //H.add_side_effect("Itch") - else if(istype(W,/datum/wound/bruise)) - user.visible_message("[user] places a bruise patch over \the [W.desc] on [M]'s [affecting.display_name].", \ - "You place a bruise patch over \the [W.desc] on [M]'s [affecting.display_name].") - else - user.visible_message("[user] places a bandaid over \the [W.desc] on [M]'s [affecting.display_name].", \ - "You place a bandaid over \the [W.desc] on [M]'s [affecting.display_name].") - use(1) - else - if(can_operate(H)) //Checks if mob is lying down on table for surgery - if(do_surgery(H,user,src)) - return - else + return 1 + else + for(var/datum/wound/W in affecting.wounds) + if(W.internal) + continue + if(W.current_stage <= W.max_bleeding_stage) + user.visible_message("[user] bandages \the [W.desc] on [M]'s [affecting.display_name].", \ + "You bandage \the [W.desc] on [M]'s [affecting.display_name].") + //H.add_side_effect("Itch") + else if(istype(W,/datum/wound/bruise)) + user.visible_message("[user] places a bruise patch over \the [W.desc] on [M]'s [affecting.display_name].", \ + "You place a bruise patch over \the [W.desc] on [M]'s [affecting.display_name].") + else + user.visible_message("[user] places a bandaid over \the [W.desc] on [M]'s [affecting.display_name].", \ + "You place a bandaid over \the [W.desc] on [M]'s [affecting.display_name].") + use(1) + else + if(can_operate(H)) //Checks if mob is lying down on table for surgery + if(do_surgery(H,user,src)) + return + else to_chat(user, "[H]'s [affecting.display_name] is cut wide open, you'll need more than a bandage!") - -/obj/item/stack/medical/ointment - name = "ointment" - desc = "Used to treat those nasty burns." - gender = PLURAL - singular_name = "ointment" - icon_state = "ointment" - origin_tech = "biotech=1" - -/obj/item/stack/medical/ointment/attack(mob/living/carbon/M as mob, mob/user as mob) - if(..()) - return 1 - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - - if(affecting.open == 0) - if(!affecting.salve()) + +/obj/item/stack/medical/ointment + name = "ointment" + desc = "Used to treat those nasty burns." + gender = PLURAL + singular_name = "ointment" + icon_state = "ointment" + origin_tech = "biotech=1" + +/obj/item/stack/medical/ointment/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(affecting.open == 0) + if(!affecting.salve()) to_chat(user, "The wounds on [M]'s [affecting.display_name] have already been salved.") - return 1 - else - user.visible_message("[user] salves the wounds on [M]'s [affecting.display_name].", \ - "You salve the wounds on [M]'s [affecting.display_name]." ) - use(1) - else - if(can_operate(H)) //Checks if mob is lying down on table for surgery - if(do_surgery(H,user,src)) - return - else + return 1 + else + user.visible_message("[user] salves the wounds on [M]'s [affecting.display_name].", \ + "You salve the wounds on [M]'s [affecting.display_name]." ) + use(1) + else + if(can_operate(H)) //Checks if mob is lying down on table for surgery + if(do_surgery(H,user,src)) + return + else to_chat(user, "[H]'s [affecting.display_name] is cut wide open, you'll need more than some ointment!") - -/obj/item/stack/medical/bruise_pack/tajaran - name = "\improper S'rendarr's Hand leaf" - singular_name = "S'rendarr's Hand leaf" - desc = "A poultice made of soft leaves that is rubbed on bruises." - icon = 'icons/obj/harvest.dmi' - icon_state = "cabbage" - heal_brute = 5 - -/obj/item/stack/medical/ointment/tajaran - name = "\improper Messa's Tear petals" - singular_name = "Messa's Tear petals" - desc = "A poultice made of cold, blue petals that is rubbed on burns." - icon = 'icons/obj/harvest.dmi' - icon_state = "ambrosiavulgaris" - heal_burn = 5 - - -/obj/item/stack/medical/advanced/bruise_pack - name = "advanced trauma kit" - singular_name = "advanced trauma kit" - desc = "An advanced trauma kit for severe injuries." - icon_state = "traumakit" - heal_brute = 10 - origin_tech = "biotech=2" - -/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) - if(..()) - return 1 - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - - if(affecting.open == 0) - if(!affecting.bandage()) + +/obj/item/stack/medical/bruise_pack/tajaran + name = "\improper S'rendarr's Hand leaf" + singular_name = "S'rendarr's Hand leaf" + desc = "A poultice made of soft leaves that is rubbed on bruises." + icon = 'icons/obj/harvest.dmi' + icon_state = "cabbage" + heal_brute = 5 + +/obj/item/stack/medical/ointment/tajaran + name = "\improper Messa's Tear petals" + singular_name = "Messa's Tear petals" + desc = "A poultice made of cold, blue petals that is rubbed on burns." + icon = 'icons/obj/harvest.dmi' + icon_state = "ambrosiavulgaris" + heal_burn = 5 + + +/obj/item/stack/medical/advanced/bruise_pack + name = "advanced trauma kit" + singular_name = "advanced trauma kit" + desc = "An advanced trauma kit for severe injuries." + icon_state = "traumakit" + heal_brute = 10 + origin_tech = "biotech=2" + +/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(affecting.open == 0) + if(!affecting.bandage()) to_chat(user, "The wounds on [M]'s [affecting.display_name] have already been treated.") - return 1 - else - for(var/datum/wound/W in affecting.wounds) - if(W.internal) - continue - if(W.current_stage <= W.max_bleeding_stage) - user.visible_message("[user] cleans \the [W.desc] on [M]'s [affecting.display_name] and seals the edges with bioglue.", \ - "You clean \the [W.desc] on [M]'s [affecting.display_name] and seal the edges with bioglue .") - //H.add_side_effect("Itch") - else if(istype(W,/datum/wound/bruise)) - user.visible_message("[user] disinfects and places a medicine patch over \the [W.desc] on [M]'s [affecting.display_name].", \ - "You disinfect and place a medicine patch over \the [W.desc] on [M]'s [affecting.display_name].") - else - user.visible_message("[user] smears some bioglue over \the [W.desc] on [M]'s [affecting.display_name].", \ - "You smear some bioglue over \the [W.desc] on [M]'s [affecting.display_name].") - affecting.heal_damage(rand(heal_brute, heal_brute + 5), 0) - use(1) - else - if(can_operate(H)) //Checks if mob is lying down on table for surgery - if(do_surgery(H,user,src)) - return - else + return 1 + else + for(var/datum/wound/W in affecting.wounds) + if(W.internal) + continue + if(W.current_stage <= W.max_bleeding_stage) + user.visible_message("[user] cleans \the [W.desc] on [M]'s [affecting.display_name] and seals the edges with bioglue.", \ + "You clean \the [W.desc] on [M]'s [affecting.display_name] and seal the edges with bioglue .") + //H.add_side_effect("Itch") + else if(istype(W,/datum/wound/bruise)) + user.visible_message("[user] disinfects and places a medicine patch over \the [W.desc] on [M]'s [affecting.display_name].", \ + "You disinfect and place a medicine patch over \the [W.desc] on [M]'s [affecting.display_name].") + else + user.visible_message("[user] smears some bioglue over \the [W.desc] on [M]'s [affecting.display_name].", \ + "You smear some bioglue over \the [W.desc] on [M]'s [affecting.display_name].") + affecting.heal_damage(rand(heal_brute, heal_brute + 5), 0) + use(1) + else + if(can_operate(H)) //Checks if mob is lying down on table for surgery + if(do_surgery(H,user,src)) + return + else to_chat(user, "[H]'s [affecting.display_name] is cut wide open, even bioglue won't do!") - -/obj/item/stack/medical/advanced/ointment - name = "advanced burn kit" - singular_name = "advanced burn kit" - desc = "An advanced treatment kit for severe burns." - icon_state = "burnkit" - heal_burn = 10 - origin_tech = "biotech=2" - - -/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M as mob, mob/user as mob) - if(..()) - return 1 - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - - if(affecting.open == 0) - if(!affecting.salve()) + +/obj/item/stack/medical/advanced/ointment + name = "advanced burn kit" + singular_name = "advanced burn kit" + desc = "An advanced treatment kit for severe burns." + icon_state = "burnkit" + heal_burn = 10 + origin_tech = "biotech=2" + + +/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(affecting.open == 0) + if(!affecting.salve()) to_chat(user, "The wounds on [M]'s [affecting.display_name] have already been salved.") - return 1 - else - user.visible_message("[user] disinfects the wounds on [M]'s [affecting.display_name] and covers them with a regenerative membrane.", \ - "You disinfect the wounds on [M]'s [affecting.display_name] and cover them with a regenerative membrane.") - affecting.heal_damage(0, rand(heal_burn, heal_burn + 5)) - use(1) - else - if(can_operate(H)) //Checks if mob is lying down on table for surgery - if(do_surgery(H,user,src)) - return - else + return 1 + else + user.visible_message("[user] disinfects the wounds on [M]'s [affecting.display_name] and covers them with a regenerative membrane.", \ + "You disinfect the wounds on [M]'s [affecting.display_name] and cover them with a regenerative membrane.") + affecting.heal_damage(0, rand(heal_burn, heal_burn + 5)) + use(1) + else + if(can_operate(H)) //Checks if mob is lying down on table for surgery + if(do_surgery(H,user,src)) + return + else to_chat(user, "[H]'s [affecting.display_name] is cut wide open, even a regenerative membrane won't do!") - -/obj/item/stack/medical/splint - name = "medical splints" - singular_name = "medical splint" - icon_state = "splint" - amount = 5 - max_amount = 5 - -/obj/item/stack/medical/splint/attack(mob/living/carbon/M as mob, mob/user as mob) - if(..()) - return 1 - - if (istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - var/limb = affecting.display_name - if(!((affecting.name == "l_arm") || (affecting.name == "r_arm") || (affecting.name == "l_leg") || (affecting.name == "r_leg"))) + +/obj/item/stack/medical/splint + name = "medical splints" + singular_name = "medical splint" + icon_state = "splint" + amount = 5 + max_amount = 5 + +/obj/item/stack/medical/splint/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + var/limb = affecting.display_name + if(!((affecting.name == "l_arm") || (affecting.name == "r_arm") || (affecting.name == "l_leg") || (affecting.name == "r_leg"))) to_chat(user, "You can only apply splints on limbs!") - return - if(affecting.status & ORGAN_SPLINTED) + return + if(affecting.status & ORGAN_SPLINTED) to_chat(user, "[M]'s [limb] is already splinted!") - return - if (M != user) - user.visible_message("[user] starts to apply \the [src] to [M]'s [limb].", \ - "You start to apply \the [src] to [M]'s [limb].", \ - "You hear something being wrapped.") - else - if((!user.hand && affecting.name == "r_arm") || (user.hand && affecting.name == "l_arm")) + return + if (M != user) + user.visible_message("[user] starts to apply \the [src] to [M]'s [limb].", \ + "You start to apply \the [src] to [M]'s [limb].", \ + "You hear something being wrapped.") + else + if((!user.hand && affecting.name == "r_arm") || (user.hand && affecting.name == "l_arm")) to_chat(user, "You can't apply a splint to the arm you're using!") - return - user.visible_message("[user] starts to apply \the [src] to their [limb].", \ - "You start to apply \the [src] to your [limb].", \ - "You hear something being wrapped.") - if(do_mob(user, M, 50)) - if (M != user) - user.visible_message("[user] finishes applying \the [src] to [M]'s [limb].", \ - "You finish applying \the [src] to [M]'s [limb].", \ - "You hear something being wrapped.") - else - if(prob(25)) - user.visible_message("[user] successfully applies \the [src] to their [limb].", \ - "You successfully apply \the [src] to your [limb].", \ - "You hear something being wrapped.") - else - user.visible_message("[user] fumbles \the [src].", \ - "You fumble \the [src].", \ - "You hear something being wrapped.") - return - affecting.status |= ORGAN_SPLINTED - use(1) - return + return + user.visible_message("[user] starts to apply \the [src] to their [limb].", \ + "You start to apply \the [src] to your [limb].", \ + "You hear something being wrapped.") + if(do_mob(user, M, 50)) + if (M != user) + user.visible_message("[user] finishes applying \the [src] to [M]'s [limb].", \ + "You finish applying \the [src] to [M]'s [limb].", \ + "You hear something being wrapped.") + else + if(prob(25)) + user.visible_message("[user] successfully applies \the [src] to their [limb].", \ + "You successfully apply \the [src] to your [limb].", \ + "You hear something being wrapped.") + else + user.visible_message("[user] fumbles \the [src].", \ + "You fumble \the [src].", \ + "You hear something being wrapped.") + return + affecting.status |= ORGAN_SPLINTED + use(1) + return diff --git a/code/game/objects/items/stacks/packagewrap.dm b/code/game/objects/items/stacks/packagewrap.dm index 693e7e2b7af..bd91cf5c834 100644 --- a/code/game/objects/items/stacks/packagewrap.dm +++ b/code/game/objects/items/stacks/packagewrap.dm @@ -1,183 +1,183 @@ -/obj/item/stack/package_wrap - name = "package wrap" - desc = "Wrapping paper designed to help goods safely navigate the mail system." - icon = 'icons/obj/items.dmi' - icon_state = "deliveryPaper" - singular_name = "paper sheet" - w_class = 2 - amount = 24 - max_amount = 24 - //If it's null, it can't wrap that type. - var/smallpath = /obj/item/delivery //We use this for items - var/bigpath = /obj/item/delivery/large //We use this for structures (crates, closets, recharge packs, etc.) - var/manpath = null //We use this for people. - var/human_wrap_speed = 100 //Handcuffs are 30 - - var/list/cannot_wrap = list( - /obj/structure/table, - /obj/structure/rack, - /obj/item/delivery, - /obj/item/weapon/gift, - /obj/item/weapon/winter_gift, - /obj/item/weapon/evidencebag, - /obj/item/weapon/legcuffs/bolas, - /obj/item/weapon/storage - ) - - var/list/wrappable_big_stuff = list( - /obj/structure/closet, - /obj/structure/vendomatpack, - /obj/structure/stackopacks - ) - -/obj/item/stack/package_wrap/afterattack(var/attacked, mob/user as mob, var/proximity_flag) - if(ishuman(attacked)) return try_wrap_human(attacked,user) - if(!istype(attacked,/obj)) return - var/obj/target = attacked - if(is_type_in_list(target, cannot_wrap)) return - if(target.anchored) return - if(target in user) return - if(!proximity_flag) return - - user.attack_log += "\[[time_stamp()]\] Has used [src.name] on \ref[target]" - target.add_fingerprint(user) - src.add_fingerprint(user) - - if(istype(target, /obj/item) && smallpath) - if (amount >= 1) - var/obj/item/I = target - var/obj/item/P = new smallpath(get_turf(target.loc),target,round(I.w_class)) - if(!istype(target.loc, /turf)) - if(user.client) - user.client.screen -= target - target.forceMove(P) - P.add_fingerprint(user) - use(1) - else - to_chat(user, "You need more paper!") - else if(is_type_in_list(target,wrappable_big_stuff) && bigpath) - if(istype(target,/obj/structure/closet)) - var/obj/structure/closet/C = target - if(C.opened) return - if(amount >= 3) - var/obj/item/P = new bigpath(get_turf(target.loc),target) - target.forceMove(P) - P.add_fingerprint(user) - use(3) - else - to_chat(user, "You need more paper!") - else - to_chat(user, "[src] isn't useful for wrapping [target].") - return 1 - -/obj/item/stack/package_wrap/proc/try_wrap_human(var/mob/living/carbon/human/H, mob/user as mob) - if(!manpath) return 0 - if(amount >= 2) - H.visible_message("[user] is trying to wrap up [H]!") - if(do_mob(user,H,human_wrap_speed)) - var/obj/present = new manpath(get_turf(H),H) - if (H.client) - H.client.perspective = EYE_PERSPECTIVE - H.client.eye = present - H.forceMove(present) - H.attack_log += text("\[[time_stamp()]\] Has been wrapped with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to wrap [H.name] ([H.ckey])") - if(!iscarbon(user)) - H.LAssailant = null - else - H.LAssailant = user - log_attack("[user.name] ([user.ckey]) used the [src.name] to wrap [H.name] ([H.ckey])") - use(2) - return 1 - else - to_chat(user, "You need more paper!") - return 0 - -/obj/item/stack/package_wrap/gift //For more details, see gift_wrappaper.dm - name = "gift wrap" - desc = "A festive wrap for hand-delivered presents. Not compatible with mail." - icon_state = "wrap_paper" - smallpath = /obj/item/weapon/gift - bigpath = null - manpath = /obj/structure/strange_present - -/obj/item/stack/package_wrap/syndie - //Looks just like normal paper, with a slight description change - desc = "Wrapping paper designed to help goods safely navigate the mail system. It has extra-strong adhesive for tight packaging." - manpath = /obj/item/delivery/large - human_wrap_speed = 30 //same as cuffs - -/obj/item/delivery - desc = "A small wrapped package." - name = "small parcel" - icon = 'icons/obj/storage.dmi' - icon_state = "deliverycrateSmall" - var/sortTag - var/atom/movable/wrapped - flags = FPRINT - -/obj/item/delivery/New(turf/loc, var/obj/item/target = null, var/size = 2) - ..() - wrapped = target - icon_state = "deliverycrate[size]" - -/obj/item/delivery/Destroy() - ..() - if(wrapped) - wrapped.forceMove(get_turf(src.loc)) - -/obj/item/delivery/attack_self(mob/user as mob) - if(wrapped) - if(ishuman(user)) - user.put_in_hands(wrapped) - else - wrapped.forceMove(get_turf(src)) - qdel(src) - -/obj/item/delivery/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/device/destTagger)) - var/obj/item/device/destTagger/O = W - - if(src.sortTag != O.currTag) - var/tag = uppertext(O.destinations[O.currTag]) - to_chat(user, "*[tag]*") - sortTag = tag - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) - overlays = 0 - overlays += "deliverytag" - src.desc = "A small wrapped package. It has a label reading [tag]" - - else if(istype(W, /obj/item/weapon/pen)) - var/str = copytext(sanitize(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN) - if (!Adjacent(user) || user.stat) return - if(!str || !length(str)) - to_chat(user, "Invalid text.") - return - for(var/mob/M in viewers()) - to_chat(M, "[user] labels [src] as [str].") - src.name = "[src.name] ([str])" //also needs updating - -/obj/item/delivery/large - desc = "A big wrapped package." - name = "large parcel" - density = 1 - flags = FPRINT - mouse_drag_pointer = MOUSE_ACTIVE_POINTER - -/obj/item/delivery/large/New(turf/loc, atom/movable/target) - ..() - wrapped = target - if(istype(wrapped,/obj/structure/closet/crate) || ishuman(target)) icon_state = "deliverycrate" - else if(istype(wrapped,/obj/structure/vendomatpack)) icon_state = "deliverypack" - else if(istype(wrapped,/obj/structure/stackopacks)) icon_state = "deliverystack" - else if(istype(wrapped,/obj/structure/closet)) icon_state = "deliverycloset" //Only IF it isn't a crate-type - -/obj/item/delivery/large/attack_hand(mob/user as mob) - if(wrapped) - wrapped.forceMove(get_turf(src.loc)) - qdel(src) - -/obj/item/delivery/large/attack_robot(mob/user) - if(!Adjacent(user)) - return - attack_hand(user) +/obj/item/stack/package_wrap + name = "package wrap" + desc = "Wrapping paper designed to help goods safely navigate the mail system." + icon = 'icons/obj/items.dmi' + icon_state = "deliveryPaper" + singular_name = "paper sheet" + w_class = 2 + amount = 24 + max_amount = 24 + //If it's null, it can't wrap that type. + var/smallpath = /obj/item/delivery //We use this for items + var/bigpath = /obj/item/delivery/large //We use this for structures (crates, closets, recharge packs, etc.) + var/manpath = null //We use this for people. + var/human_wrap_speed = 100 //Handcuffs are 30 + + var/list/cannot_wrap = list( + /obj/structure/table, + /obj/structure/rack, + /obj/item/delivery, + /obj/item/weapon/gift, + /obj/item/weapon/winter_gift, + /obj/item/weapon/evidencebag, + /obj/item/weapon/legcuffs/bolas, + /obj/item/weapon/storage + ) + + var/list/wrappable_big_stuff = list( + /obj/structure/closet, + /obj/structure/vendomatpack, + /obj/structure/stackopacks + ) + +/obj/item/stack/package_wrap/afterattack(var/attacked, mob/user as mob, var/proximity_flag) + if(ishuman(attacked)) return try_wrap_human(attacked,user) + if(!istype(attacked,/obj)) return + var/obj/target = attacked + if(is_type_in_list(target, cannot_wrap)) return + if(target.anchored) return + if(target in user) return + if(!proximity_flag) return + + user.attack_log += "\[[time_stamp()]\] Has used [src.name] on \ref[target]" + target.add_fingerprint(user) + src.add_fingerprint(user) + + if(istype(target, /obj/item) && smallpath) + if (amount >= 1) + var/obj/item/I = target + var/obj/item/P = new smallpath(get_turf(target.loc),target,round(I.w_class)) + if(!istype(target.loc, /turf)) + if(user.client) + user.client.screen -= target + target.forceMove(P) + P.add_fingerprint(user) + use(1) + else + to_chat(user, "You need more paper!") + else if(is_type_in_list(target,wrappable_big_stuff) && bigpath) + if(istype(target,/obj/structure/closet)) + var/obj/structure/closet/C = target + if(C.opened) return + if(amount >= 3) + var/obj/item/P = new bigpath(get_turf(target.loc),target) + target.forceMove(P) + P.add_fingerprint(user) + use(3) + else + to_chat(user, "You need more paper!") + else + to_chat(user, "[src] isn't useful for wrapping [target].") + return 1 + +/obj/item/stack/package_wrap/proc/try_wrap_human(var/mob/living/carbon/human/H, mob/user as mob) + if(!manpath) return 0 + if(amount >= 2) + H.visible_message("[user] is trying to wrap up [H]!") + if(do_mob(user,H,human_wrap_speed)) + var/obj/present = new manpath(get_turf(H),H) + if (H.client) + H.client.perspective = EYE_PERSPECTIVE + H.client.eye = present + H.forceMove(present) + H.attack_log += text("\[[time_stamp()]\] Has been wrapped with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to wrap [H.name] ([H.ckey])") + if(!iscarbon(user)) + H.LAssailant = null + else + H.LAssailant = user + log_attack("[user.name] ([user.ckey]) used the [src.name] to wrap [H.name] ([H.ckey])") + use(2) + return 1 + else + to_chat(user, "You need more paper!") + return 0 + +/obj/item/stack/package_wrap/gift //For more details, see gift_wrappaper.dm + name = "gift wrap" + desc = "A festive wrap for hand-delivered presents. Not compatible with mail." + icon_state = "wrap_paper" + smallpath = /obj/item/weapon/gift + bigpath = null + manpath = /obj/structure/strange_present + +/obj/item/stack/package_wrap/syndie + //Looks just like normal paper, with a slight description change + desc = "Wrapping paper designed to help goods safely navigate the mail system. It has extra-strong adhesive for tight packaging." + manpath = /obj/item/delivery/large + human_wrap_speed = 30 //same as cuffs + +/obj/item/delivery + desc = "A small wrapped package." + name = "small parcel" + icon = 'icons/obj/storage.dmi' + icon_state = "deliverycrateSmall" + var/sortTag + var/atom/movable/wrapped + flags = FPRINT + +/obj/item/delivery/New(turf/loc, var/obj/item/target = null, var/size = 2) + ..() + wrapped = target + icon_state = "deliverycrate[size]" + +/obj/item/delivery/Destroy() + ..() + if(wrapped) + wrapped.forceMove(get_turf(src.loc)) + +/obj/item/delivery/attack_self(mob/user as mob) + if(wrapped) + if(ishuman(user)) + user.put_in_hands(wrapped) + else + wrapped.forceMove(get_turf(src)) + qdel(src) + +/obj/item/delivery/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/device/destTagger)) + var/obj/item/device/destTagger/O = W + + if(src.sortTag != O.currTag) + var/tag = uppertext(O.destinations[O.currTag]) + to_chat(user, "*[tag]*") + sortTag = tag + playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) + overlays = 0 + overlays += "deliverytag" + src.desc = "A small wrapped package. It has a label reading [tag]" + + else if(istype(W, /obj/item/weapon/pen)) + var/str = copytext(sanitize(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN) + if (!Adjacent(user) || user.stat) return + if(!str || !length(str)) + to_chat(user, "Invalid text.") + return + for(var/mob/M in viewers()) + to_chat(M, "[user] labels [src] as [str].") + src.name = "[src.name] ([str])" //also needs updating + +/obj/item/delivery/large + desc = "A big wrapped package." + name = "large parcel" + density = 1 + flags = FPRINT + mouse_drag_pointer = MOUSE_ACTIVE_POINTER + +/obj/item/delivery/large/New(turf/loc, atom/movable/target) + ..() + wrapped = target + if(istype(wrapped,/obj/structure/closet/crate) || ishuman(target)) icon_state = "deliverycrate" + else if(istype(wrapped,/obj/structure/vendomatpack)) icon_state = "deliverypack" + else if(istype(wrapped,/obj/structure/stackopacks)) icon_state = "deliverystack" + else if(istype(wrapped,/obj/structure/closet)) icon_state = "deliverycloset" //Only IF it isn't a crate-type + +/obj/item/delivery/large/attack_hand(mob/user as mob) + if(wrapped) + wrapped.forceMove(get_turf(src.loc)) + qdel(src) + +/obj/item/delivery/large/attack_robot(mob/user) + if(!Adjacent(user)) + return + attack_hand(user) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 4e34e8cdc08..308560e55de 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -1,115 +1,115 @@ -/obj/item/stack/rods - name = "metal rod" - desc = "Some rods. Can be used for building, or something." - singular_name = "metal rod" - icon_state = "rods" - flags = FPRINT - siemens_coefficient = 1 - w_class = 3.0 - force = 9.0 - throwforce = 15.0 - throw_speed = 5 - throw_range = 20 - starting_materials = list(MAT_IRON = 1875) - max_amount = 60 - attack_verb = list("hit", "bludgeoned", "whacked") - w_type=RECYK_METAL - melt_temperature = MELTPOINT_STEEL - -/obj/item/stack/rods/recycle(var/datum/materials/rec) - rec.addAmount("iron",amount/2) - return RECYK_METAL - -/obj/item/stack/rods/afterattack(atom/Target, mob/user, adjacent, params) - var/busy = 0 - if(adjacent) - if(isturf(Target) || istype(Target, /obj/structure/lattice)) - var/turf/T = get_turf(Target) - var/obj/item/stack/rods/R = src - var/obj/structure/lattice/L = T.canBuildCatwalk(R) - if(istype(L)) - if(R.amount < 2) - to_chat(user, "You need atleast 2 rods to build a catwalk!") - return - if(busy) //We are already building a catwalk, avoids stacking catwalks - return - to_chat(user, "You begin to build a catwalk.") - busy = 1 - if(do_after(user, Target, 30)) - busy = 0 - if(R.amount < 2) - to_chat(user, "You ran out of rods!") - return - if(!istype(L) || L.loc != T) - to_chat(user, "You need a lattice first!") - return - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - to_chat(user, "You build a catwalk!") - R.use(2) - new /obj/structure/catwalk(T) - qdel(L) - return - - if(T.canBuildLattice(R)) - to_chat(user, "Constructing support lattice ...") - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) - new /obj/structure/lattice(T) - R.use(1) - return - -/obj/item/stack/rods/attackby(obj/item/W as obj, mob/user as mob) - if(iswelder(W)) - var/obj/item/weapon/weldingtool/WT = W - - if(amount < 2) - to_chat(user, "You need at least two rods to do this.") - return - - if(WT.remove_fuel(0,user)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 1 - M.add_to_stacks(usr) - user.visible_message("[src] is shaped into metal by [user.name] with the weldingtool.", \ - "You shape the [src] into metal with the weldingtool.", \ - "You hear welding.") - var/obj/item/stack/rods/R = src - src = null - var/replace = (user.get_inactive_hand()==R) - R.use(2) - if (!R && replace) - user.put_in_hands(M) - return 1 - return ..() - - -/obj/item/stack/rods/attack_self(mob/user as mob) - src.add_fingerprint(user) - - if(!istype(user.loc, /turf)) return 0 - - if(locate(/obj/structure/grille, user.loc)) - for(var/obj/structure/grille/G in user.loc) - if(G.broken) - G.health = initial(G.health) - G.density = 1 - G.broken = 0 - G.icon_state = "[initial(G.icon_state)]" - use(1) - else - return 1 - else - if(amount < 2) - to_chat(user, "You need at least two rods to do this.") - return - - to_chat(user, "Assembling grille...") - - if(!do_after(user, get_turf(src), 10)) - return - - var/obj/structure/grille/Grille = getFromPool(/obj/structure/grille, user.loc) - if(!Grille) - Grille = new(user.loc) - to_chat(user, "You assembled a grille!") - Grille.add_fingerprint(user) - use(2) +/obj/item/stack/rods + name = "metal rod" + desc = "Some rods. Can be used for building, or something." + singular_name = "metal rod" + icon_state = "rods" + flags = FPRINT + siemens_coefficient = 1 + w_class = 3.0 + force = 9.0 + throwforce = 15.0 + throw_speed = 5 + throw_range = 20 + starting_materials = list(MAT_IRON = 1875) + max_amount = 60 + attack_verb = list("hit", "bludgeoned", "whacked") + w_type=RECYK_METAL + melt_temperature = MELTPOINT_STEEL + +/obj/item/stack/rods/recycle(var/datum/materials/rec) + rec.addAmount("iron",amount/2) + return RECYK_METAL + +/obj/item/stack/rods/afterattack(atom/Target, mob/user, adjacent, params) + var/busy = 0 + if(adjacent) + if(isturf(Target) || istype(Target, /obj/structure/lattice)) + var/turf/T = get_turf(Target) + var/obj/item/stack/rods/R = src + var/obj/structure/lattice/L = T.canBuildCatwalk(R) + if(istype(L)) + if(R.amount < 2) + to_chat(user, "You need atleast 2 rods to build a catwalk!") + return + if(busy) //We are already building a catwalk, avoids stacking catwalks + return + to_chat(user, "You begin to build a catwalk.") + busy = 1 + if(do_after(user, Target, 30)) + busy = 0 + if(R.amount < 2) + to_chat(user, "You ran out of rods!") + return + if(!istype(L) || L.loc != T) + to_chat(user, "You need a lattice first!") + return + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + to_chat(user, "You build a catwalk!") + R.use(2) + new /obj/structure/catwalk(T) + qdel(L) + return + + if(T.canBuildLattice(R)) + to_chat(user, "Constructing support lattice ...") + playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + new /obj/structure/lattice(T) + R.use(1) + return + +/obj/item/stack/rods/attackby(obj/item/W as obj, mob/user as mob) + if(iswelder(W)) + var/obj/item/weapon/weldingtool/WT = W + + if(amount < 2) + to_chat(user, "You need at least two rods to do this.") + return + + if(WT.remove_fuel(0,user)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 1 + M.add_to_stacks(usr) + user.visible_message("[src] is shaped into metal by [user.name] with the weldingtool.", \ + "You shape the [src] into metal with the weldingtool.", \ + "You hear welding.") + var/obj/item/stack/rods/R = src + src = null + var/replace = (user.get_inactive_hand()==R) + R.use(2) + if (!R && replace) + user.put_in_hands(M) + return 1 + return ..() + + +/obj/item/stack/rods/attack_self(mob/user as mob) + src.add_fingerprint(user) + + if(!istype(user.loc, /turf)) return 0 + + if(locate(/obj/structure/grille, user.loc)) + for(var/obj/structure/grille/G in user.loc) + if(G.broken) + G.health = initial(G.health) + G.density = 1 + G.broken = 0 + G.icon_state = "[initial(G.icon_state)]" + use(1) + else + return 1 + else + if(amount < 2) + to_chat(user, "You need at least two rods to do this.") + return + + to_chat(user, "Assembling grille...") + + if(!do_after(user, get_turf(src), 10)) + return + + var/obj/structure/grille/Grille = getFromPool(/obj/structure/grille, user.loc) + if(!Grille) + Grille = new(user.loc) + to_chat(user, "You assembled a grille!") + Grille.add_fingerprint(user) + use(2) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 6ca61c80122..7cb1c7d46ad 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -1,304 +1,304 @@ -/* Glass stack types - * Contains: - * Glass sheets - * Reinforced glass sheets - * Plasma Glass Sheets - * Reinforced Plasma Glass Sheets (AKA Holy fuck strong windows) - */ - -/obj/item/stack/sheet/glass - w_type = RECYK_GLASS - melt_temperature = MELTPOINT_GLASS - var/created_window = /obj/structure/window - var/full_window = /obj/structure/window/full - var/windoor = null - var/reinforced = 0 - var/rglass = 0 - //For solars created from this glass type - var/glass_quality = 0.5 //Quality of a solar made from this - var/shealth = 5 //Health of a solar made from this - var/sname = "glass" - var/shard_type = /obj/item/weapon/shard - - siemens_coefficient = 0 //does not conduct - -/obj/item/stack/sheet/glass/attack_self(mob/user as mob) - construct_window(user) - -/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user) - if(issolder(W)) - src.use(1) - new /obj/item/weapon/circuitboard/blank(user.loc) - to_chat(user, "You fashion a blank circuitboard out of the glass.") - playsound(src.loc, 'sound/items/Welder.ogg', 35, 1) - if(istype(W, /obj/item/stack/rods) && !reinforced) - var/obj/item/stack/rods/V = W - var/obj/item/stack/sheet/glass/RG = new rglass(user.loc) - RG.add_fingerprint(user) - RG.add_to_stacks(user) - V.use(1) - var/obj/item/stack/sheet/glass/G = src - src = null - var/replace = (user.get_inactive_hand()==G) - G.use(1) - if (!G && !RG && replace) - if(isMoMMI(user)) - RG.loc=get_turf(user) - else - user.put_in_hands(RG) - else - return ..() - -/obj/item/stack/sheet/glass/proc/construct_window(mob/user as mob) - if(!user || !src) return 0 - if(!istype(user.loc,/turf)) return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return 0 - var/title = "[src.name] Sheets" - title += " ([src.amount] sheet\s left)" - if(windoor) //TODO: Find way to merge this if-else clause and lower duplication - switch(input(title, "Would you like full tile glass a one direction glass pane or a windoor?") in list("One Direction", "Full Window", "Windoor", "Cancel")) - if("One Direction") - if(!src) return 1 - if(src.loc != user) return 1 - var/list/directions = new/list(cardinal) - var/i = 0 - for (var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - to_chat(user, "There are too many windows in this location.") - return 1 - directions-=win.dir - if(win.is_fulltile()) - to_chat(user, "Can't let you do that.") - return 1 - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - var/obj/structure/window/W = new created_window(user.loc, 0) - W.d_state = 0 - W.dir = dir_to_set - W.ini_dir = W.dir - W.anchored = 0 - src.use(1) - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - to_chat(user, "You need more glass to do that.") - return 1 - if(locate(/obj/structure/window/full) in user.loc) - to_chat(user, "There is a window in the way.") - return 1 - var/obj/structure/window/W = new full_window( user.loc, 0 ) - W.d_state = 0 - W.dir = SOUTHWEST - W.ini_dir = SOUTHWEST - W.anchored = 0 - src.use(2) - if("Windoor") - if(!src || src.loc != user) - return 1 - if(isturf(user.loc) && locate(/obj/structure/windoor_assembly/, user.loc)) - to_chat(user, "There is already a windoor assembly in that location.") - return 1 - if(isturf(user.loc) && locate(/obj/machinery/door/window/, user.loc)) - to_chat(user, "There is already a windoor in that location.") - return 1 - if(src.amount < 5) - to_chat(user, "You need more glass to do that.") - return 1 - var/obj/structure/windoor_assembly/WD = new windoor(user.loc, 0 ) - WD.state = "01" - WD.anchored = 0 - WD.dir = user.dir - WD.ini_dir = WD.dir - src.use(5) - switch(user.dir) - if(SOUTH) - WD.dir = SOUTH - WD.ini_dir = SOUTH - if(EAST) - WD.dir = EAST - WD.ini_dir = EAST - if(WEST) - WD.dir = WEST - WD.ini_dir = WEST - else//If the user is facing northeast. northwest, southeast, southwest or north, default to north - WD.dir = NORTH - WD.ini_dir = NORTH - else - return 1 - else - switch(alert(title, "Would you like full tile glass or one direction?", "One Direction", "Full Window", "Cancel", null)) - if("One Direction") - if(!src) return 1 - if(src.loc != user) return 1 - var/list/directions = new/list(cardinal) - var/i = 0 - for (var/obj/structure/window/win in user.loc) - i++ - if(i >= 4) - to_chat(user, "There are too many windows in this location.") - return 1 - directions-=win.dir - if(win.is_fulltile()) - to_chat(user, "Can't let you do that.") - return 1 - //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. - var/dir_to_set = 2 - for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) - var/found = 0 - for(var/obj/structure/window/WT in user.loc) - if(WT.dir == direction) - found = 1 - if(!found) - dir_to_set = direction - break - var/obj/structure/window/W = new created_window( user.loc, 0 ) - W.d_state = 0 - W.dir = dir_to_set - W.ini_dir = W.dir - W.anchored = 0 - src.use(1) - if("Full Window") - if(!src) return 1 - if(src.loc != user) return 1 - if(src.amount < 2) - to_chat(user, "You need more glass to do that.") - return 1 - if(locate(/obj/structure/window/full) in user.loc) - to_chat(user, "There is a window in the way.") - return 1 - var/obj/structure/window/W = new full_window( user.loc, 0 ) - W.d_state = 0 - W.dir = SOUTHWEST - W.ini_dir = SOUTHWEST - W.anchored = 0 - src.use(2) - return 0 - - -/* - * Glass sheets - */ - -/obj/item/stack/sheet/glass/glass - name = "glass" - desc = "HOLY SHEET! That is a lot of glass." - singular_name = "glass sheet" - icon_state = "sheet-glass" - starting_materials = list(MAT_GLASS = 3750) - origin_tech = "materials=1" - rglass = /obj/item/stack/sheet/glass/rglass - -/obj/item/stack/sheet/glass/glass/cyborg - starting_materials = null - -/obj/item/stack/sheet/glass/glass/recycle(var/datum/materials/rec) - rec.addAmount(MAT_GLASS, amount) - return 1 - -/obj/item/stack/sheet/glass/glass/attackby(obj/item/W, mob/user) - if(istype(W,/obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CC = W - if(CC.amount < 2) //Cost changed from 5 to 2, so that you get 15 tiles from a cable coil instead of only 6 (!) - to_chat(user, "There is not enough wire in this coil. You need at least two lengths.") - return - CC.use(2) - src.use(1) - - to_chat(user, "You attach some wires to the [name].")//the dreaded dubblespan - - drop_stack(/obj/item/stack/light_w, get_turf(user), 1, user) - else - return ..() - - -/* - * Reinforced glass sheets - */ - -/obj/item/stack/sheet/glass/rglass - name = "reinforced glass" - desc = "Glass which seems to have rods or something stuck in them." - singular_name = "reinforced glass sheet" - sname = "glass_ref" - icon_state = "sheet-rglass" - starting_materials = list(MAT_IRON = 1875, MAT_GLASS = 3750) - created_window = /obj/structure/window/reinforced - full_window = /obj/structure/window/full/reinforced - windoor = /obj/structure/windoor_assembly/ - origin_tech = "materials=2" - reinforced = 1 - glass_quality = 1 - shealth = 10 - -/obj/item/stack/sheet/glass/rglass/cyborg - starting_materials = null - -/obj/item/stack/sheet/glass/rglass/recycle(var/datum/materials/rec) - rec.addAmount(MAT_GLASS, amount) - rec.addAmount(MAT_IRON, 0.5 * amount) - return 1 - -/* - * Plasma Glass sheets - */ - -/obj/item/stack/sheet/glass/plasmaglass - name = "plasma glass" - desc = "A very strong and very resistant sheet of a plasma-glass alloy." - singular_name = "glass sheet" - icon_state = "sheet-plasmaglass" - sname = "plasma" - starting_materials = list(MAT_GLASS = CC_PER_SHEET_GLASS) - origin_tech = "materials=3;plasmatech=2" - created_window = /obj/structure/window/plasma - full_window = /obj/structure/window/full/plasma - rglass = /obj/item/stack/sheet/glass/plasmarglass - perunit = 2875 //average of plasma and glass - melt_temperature = MELTPOINT_STEEL + 500 - glass_quality = 1.15 //Can you imagine a world in which plasmaglass is worse than rglass - shealth = 20 - shard_type = /obj/item/weapon/shard/plasma - -/obj/item/stack/sheet/glass/plasmaglass/recycle(var/datum/materials/rec) - rec.addAmount(MAT_PLASMA, amount) - rec.addAmount(MAT_GLASS, amount) - return RECYK_GLASS - -/* - * Reinforced plasma glass sheets - */ -/obj/item/stack/sheet/glass/plasmarglass - name = "reinforced plasma glass" - desc = "Plasma glass which seems to have rods or something stuck in them." - singular_name = "reinforced plasma glass sheet" - icon_state = "sheet-plasmarglass" - sname = "plasma_ref" - starting_materials = list(MAT_IRON = 1875, MAT_GLASS = CC_PER_SHEET_GLASS) - melt_temperature = MELTPOINT_STEEL+500 // I guess...? - origin_tech = "materials=4;plasmatech=2" - created_window = /obj/structure/window/reinforced/plasma - full_window = /obj/structure/window/full/reinforced/plasma - windoor = /obj/structure/windoor_assembly/plasma - perunit = 2875 - reinforced = 1 - glass_quality = 1.3 - shealth = 30 - shard_type = /obj/item/weapon/shard/plasma - -/obj/item/stack/sheet/glass/plasmarglass/recycle(var/datum/materials/rec) - rec.addAmount(MAT_PLASMA, amount) - rec.addAmount(MAT_GLASS, amount) - rec.addAmount(MAT_IRON, 0.5 * amount) - return 1 +/* Glass stack types + * Contains: + * Glass sheets + * Reinforced glass sheets + * Plasma Glass Sheets + * Reinforced Plasma Glass Sheets (AKA Holy fuck strong windows) + */ + +/obj/item/stack/sheet/glass + w_type = RECYK_GLASS + melt_temperature = MELTPOINT_GLASS + var/created_window = /obj/structure/window + var/full_window = /obj/structure/window/full + var/windoor = null + var/reinforced = 0 + var/rglass = 0 + //For solars created from this glass type + var/glass_quality = 0.5 //Quality of a solar made from this + var/shealth = 5 //Health of a solar made from this + var/sname = "glass" + var/shard_type = /obj/item/weapon/shard + + siemens_coefficient = 0 //does not conduct + +/obj/item/stack/sheet/glass/attack_self(mob/user as mob) + construct_window(user) + +/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user) + if(issolder(W)) + src.use(1) + new /obj/item/weapon/circuitboard/blank(user.loc) + to_chat(user, "You fashion a blank circuitboard out of the glass.") + playsound(src.loc, 'sound/items/Welder.ogg', 35, 1) + if(istype(W, /obj/item/stack/rods) && !reinforced) + var/obj/item/stack/rods/V = W + var/obj/item/stack/sheet/glass/RG = new rglass(user.loc) + RG.add_fingerprint(user) + RG.add_to_stacks(user) + V.use(1) + var/obj/item/stack/sheet/glass/G = src + src = null + var/replace = (user.get_inactive_hand()==G) + G.use(1) + if (!G && !RG && replace) + if(isMoMMI(user)) + RG.loc=get_turf(user) + else + user.put_in_hands(RG) + else + return ..() + +/obj/item/stack/sheet/glass/proc/construct_window(mob/user as mob) + if(!user || !src) return 0 + if(!istype(user.loc,/turf)) return 0 + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + return 0 + var/title = "[src.name] Sheets" + title += " ([src.amount] sheet\s left)" + if(windoor) //TODO: Find way to merge this if-else clause and lower duplication + switch(input(title, "Would you like full tile glass a one direction glass pane or a windoor?") in list("One Direction", "Full Window", "Windoor", "Cancel")) + if("One Direction") + if(!src) return 1 + if(src.loc != user) return 1 + var/list/directions = new/list(cardinal) + var/i = 0 + for (var/obj/structure/window/win in user.loc) + i++ + if(i >= 4) + to_chat(user, "There are too many windows in this location.") + return 1 + directions-=win.dir + if(win.is_fulltile()) + to_chat(user, "Can't let you do that.") + return 1 + //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. + var/dir_to_set = 2 + for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) + var/found = 0 + for(var/obj/structure/window/WT in user.loc) + if(WT.dir == direction) + found = 1 + if(!found) + dir_to_set = direction + break + var/obj/structure/window/W = new created_window(user.loc, 0) + W.d_state = 0 + W.dir = dir_to_set + W.ini_dir = W.dir + W.anchored = 0 + src.use(1) + if("Full Window") + if(!src) return 1 + if(src.loc != user) return 1 + if(src.amount < 2) + to_chat(user, "You need more glass to do that.") + return 1 + if(locate(/obj/structure/window/full) in user.loc) + to_chat(user, "There is a window in the way.") + return 1 + var/obj/structure/window/W = new full_window( user.loc, 0 ) + W.d_state = 0 + W.dir = SOUTHWEST + W.ini_dir = SOUTHWEST + W.anchored = 0 + src.use(2) + if("Windoor") + if(!src || src.loc != user) + return 1 + if(isturf(user.loc) && locate(/obj/structure/windoor_assembly/, user.loc)) + to_chat(user, "There is already a windoor assembly in that location.") + return 1 + if(isturf(user.loc) && locate(/obj/machinery/door/window/, user.loc)) + to_chat(user, "There is already a windoor in that location.") + return 1 + if(src.amount < 5) + to_chat(user, "You need more glass to do that.") + return 1 + var/obj/structure/windoor_assembly/WD = new windoor(user.loc, 0 ) + WD.state = "01" + WD.anchored = 0 + WD.dir = user.dir + WD.ini_dir = WD.dir + src.use(5) + switch(user.dir) + if(SOUTH) + WD.dir = SOUTH + WD.ini_dir = SOUTH + if(EAST) + WD.dir = EAST + WD.ini_dir = EAST + if(WEST) + WD.dir = WEST + WD.ini_dir = WEST + else//If the user is facing northeast. northwest, southeast, southwest or north, default to north + WD.dir = NORTH + WD.ini_dir = NORTH + else + return 1 + else + switch(alert(title, "Would you like full tile glass or one direction?", "One Direction", "Full Window", "Cancel", null)) + if("One Direction") + if(!src) return 1 + if(src.loc != user) return 1 + var/list/directions = new/list(cardinal) + var/i = 0 + for (var/obj/structure/window/win in user.loc) + i++ + if(i >= 4) + to_chat(user, "There are too many windows in this location.") + return 1 + directions-=win.dir + if(win.is_fulltile()) + to_chat(user, "Can't let you do that.") + return 1 + //Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc. + var/dir_to_set = 2 + for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) )) + var/found = 0 + for(var/obj/structure/window/WT in user.loc) + if(WT.dir == direction) + found = 1 + if(!found) + dir_to_set = direction + break + var/obj/structure/window/W = new created_window( user.loc, 0 ) + W.d_state = 0 + W.dir = dir_to_set + W.ini_dir = W.dir + W.anchored = 0 + src.use(1) + if("Full Window") + if(!src) return 1 + if(src.loc != user) return 1 + if(src.amount < 2) + to_chat(user, "You need more glass to do that.") + return 1 + if(locate(/obj/structure/window/full) in user.loc) + to_chat(user, "There is a window in the way.") + return 1 + var/obj/structure/window/W = new full_window( user.loc, 0 ) + W.d_state = 0 + W.dir = SOUTHWEST + W.ini_dir = SOUTHWEST + W.anchored = 0 + src.use(2) + return 0 + + +/* + * Glass sheets + */ + +/obj/item/stack/sheet/glass/glass + name = "glass" + desc = "HOLY SHEET! That is a lot of glass." + singular_name = "glass sheet" + icon_state = "sheet-glass" + starting_materials = list(MAT_GLASS = 3750) + origin_tech = "materials=1" + rglass = /obj/item/stack/sheet/glass/rglass + +/obj/item/stack/sheet/glass/glass/cyborg + starting_materials = null + +/obj/item/stack/sheet/glass/glass/recycle(var/datum/materials/rec) + rec.addAmount(MAT_GLASS, amount) + return 1 + +/obj/item/stack/sheet/glass/glass/attackby(obj/item/W, mob/user) + if(istype(W,/obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/CC = W + if(CC.amount < 2) //Cost changed from 5 to 2, so that you get 15 tiles from a cable coil instead of only 6 (!) + to_chat(user, "There is not enough wire in this coil. You need at least two lengths.") + return + CC.use(2) + src.use(1) + + to_chat(user, "You attach some wires to the [name].")//the dreaded dubblespan + + drop_stack(/obj/item/stack/light_w, get_turf(user), 1, user) + else + return ..() + + +/* + * Reinforced glass sheets + */ + +/obj/item/stack/sheet/glass/rglass + name = "reinforced glass" + desc = "Glass which seems to have rods or something stuck in them." + singular_name = "reinforced glass sheet" + sname = "glass_ref" + icon_state = "sheet-rglass" + starting_materials = list(MAT_IRON = 1875, MAT_GLASS = 3750) + created_window = /obj/structure/window/reinforced + full_window = /obj/structure/window/full/reinforced + windoor = /obj/structure/windoor_assembly/ + origin_tech = "materials=2" + reinforced = 1 + glass_quality = 1 + shealth = 10 + +/obj/item/stack/sheet/glass/rglass/cyborg + starting_materials = null + +/obj/item/stack/sheet/glass/rglass/recycle(var/datum/materials/rec) + rec.addAmount(MAT_GLASS, amount) + rec.addAmount(MAT_IRON, 0.5 * amount) + return 1 + +/* + * Plasma Glass sheets + */ + +/obj/item/stack/sheet/glass/plasmaglass + name = "plasma glass" + desc = "A very strong and very resistant sheet of a plasma-glass alloy." + singular_name = "glass sheet" + icon_state = "sheet-plasmaglass" + sname = "plasma" + starting_materials = list(MAT_GLASS = CC_PER_SHEET_GLASS) + origin_tech = "materials=3;plasmatech=2" + created_window = /obj/structure/window/plasma + full_window = /obj/structure/window/full/plasma + rglass = /obj/item/stack/sheet/glass/plasmarglass + perunit = 2875 //average of plasma and glass + melt_temperature = MELTPOINT_STEEL + 500 + glass_quality = 1.15 //Can you imagine a world in which plasmaglass is worse than rglass + shealth = 20 + shard_type = /obj/item/weapon/shard/plasma + +/obj/item/stack/sheet/glass/plasmaglass/recycle(var/datum/materials/rec) + rec.addAmount(MAT_PLASMA, amount) + rec.addAmount(MAT_GLASS, amount) + return RECYK_GLASS + +/* + * Reinforced plasma glass sheets + */ +/obj/item/stack/sheet/glass/plasmarglass + name = "reinforced plasma glass" + desc = "Plasma glass which seems to have rods or something stuck in them." + singular_name = "reinforced plasma glass sheet" + icon_state = "sheet-plasmarglass" + sname = "plasma_ref" + starting_materials = list(MAT_IRON = 1875, MAT_GLASS = CC_PER_SHEET_GLASS) + melt_temperature = MELTPOINT_STEEL+500 // I guess...? + origin_tech = "materials=4;plasmatech=2" + created_window = /obj/structure/window/reinforced/plasma + full_window = /obj/structure/window/full/reinforced/plasma + windoor = /obj/structure/windoor_assembly/plasma + perunit = 2875 + reinforced = 1 + glass_quality = 1.3 + shealth = 30 + shard_type = /obj/item/weapon/shard/plasma + +/obj/item/stack/sheet/glass/plasmarglass/recycle(var/datum/materials/rec) + rec.addAmount(MAT_PLASMA, amount) + rec.addAmount(MAT_GLASS, amount) + rec.addAmount(MAT_IRON, 0.5 * amount) + return 1 diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index f176a5ea7a2..8f8057e3b8c 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -1,144 +1,144 @@ -/obj/item/stack/sheet/animalhide - icon = 'icons/obj/butchering_products.dmi' - -/obj/item/stack/sheet/animalhide/human - name = "human skin" - desc = "The by-product of human farming." - singular_name = "human skin piece" - icon_state = "sheet-hide" - origin_tech = "" - -/obj/item/stack/sheet/animalhide/corgi - name = "corgi hide" - desc = "The by-product of corgi farming." - singular_name = "corgi hide piece" - icon_state = "sheet-corgi" - origin_tech = "" - -/obj/item/stack/sheet/animalhide/cat - name = "cat hide" - desc = "The by-product of cat farming." - singular_name = "cat hide piece" - icon_state = "sheet-cat" - origin_tech = "" - -/obj/item/stack/sheet/animalhide/monkey - name = "monkey hide" - desc = "The by-product of monkey farming." - singular_name = "monkey hide piece" - icon_state = "sheet-monkey" - origin_tech = "" - -/obj/item/stack/sheet/animalhide/lizard - name = "lizard skin" - desc = "Sssssss..." - singular_name = "lizard skin piece" - icon_state = "sheet-lizard" - origin_tech = "" - -/obj/item/stack/sheet/animalhide/xeno - name = "alien hide" - desc = "The skin of a terrible creature." - singular_name = "alien hide piece" - icon_state = "sheet-xeno" - origin_tech = "" - -//don't see anywhere else to put these, maybe together they could be used to make the xenos suit? -/obj/item/stack/sheet/xenochitin - name = "alien chitin" - desc = "A piece of the hide of a terrible creature." - singular_name = "alien hide piece" - icon = 'icons/obj/butchering_products.dmi' - icon_state = "chitin" - origin_tech = "" - -/obj/item/xenos_claw - name = "alien claw" - desc = "The claw of a terrible creature." - icon = 'icons/obj/butchering_products.dmi' - icon_state = "claw" - origin_tech = "" - -/obj/item/xenos_claw/attackby(obj/item/W, mob/user) - .=..() - - if(istype(W,/obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = W - - if(C.use(5)) - user.drop_item(src, force_drop = 1) - - var/obj/item/clothing/mask/necklace/xeno_claw/X = new(get_turf(src)) - user.put_in_active_hand(X) - to_chat(user, "You create a necklace out of \the [src] and \the [C].") - - qdel(src) - else - to_chat(user, "You need at least 5 lengths of cable to do this!") - -/obj/item/weed_extract - name = "weed extract" - desc = "A piece of slimy, purplish weed." - icon = 'icons/mob/alien.dmi' - icon_state = "weed_extract" - origin_tech = "" - -/obj/item/stack/sheet/hairlesshide - name = "hairless hide" - desc = "This hide was stripped of it's hair, but still needs tanning." - singular_name = "hairless hide piece" - icon = 'icons/obj/butchering_products.dmi' - icon_state = "sheet-hairlesshide" - origin_tech = "" - -/obj/item/stack/sheet/wetleather - name = "wet leather" - desc = "This leather has been cleaned but still needs to be dried." - singular_name = "wet leather piece" - icon = 'icons/obj/butchering_products.dmi' - icon_state = "sheet-wetleather" - origin_tech = "" - var/wetness = 30 //Reduced when exposed to high temperautres - var/drying_threshold_temperature = 500 //Kelvin to start drying - -/obj/item/stack/sheet/leather - name = "leather" - desc = "The by-product of mob grinding." - singular_name = "leather piece" - icon = 'icons/obj/butchering_products.dmi' - icon_state = "sheet-leather" - origin_tech = "materials=2" - - - -//Step one - dehairing. - -/obj/item/stack/sheet/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob) - if( W.is_sharp() >= 1.2 ) - - //visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message) - user.visible_message("\the [usr] starts cutting hair off \the [src]", "You start cutting the hair off \the [src]", "You hear the sound of a knife rubbing against flesh") - - spawn() - if(do_after(user, src, 50)) - to_chat(user, "You cut the hair from this [src.singular_name]") - - if(src.use(1)) - drop_stack(/obj/item/stack/sheet/hairlesshide, user.loc, 1, user) - return 1 - else - ..() - - -//Step two - washing..... it's actually in washing machine code. - -//Step three - drying -/obj/item/stack/sheet/wetleather/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - ..() - if(exposed_temperature >= drying_threshold_temperature) - wetness-- - if(wetness == 0) - - if(src.use(1)) - drop_stack(/obj/item/stack/sheet/leather, src.loc, 1) - wetness = initial(wetness) +/obj/item/stack/sheet/animalhide + icon = 'icons/obj/butchering_products.dmi' + +/obj/item/stack/sheet/animalhide/human + name = "human skin" + desc = "The by-product of human farming." + singular_name = "human skin piece" + icon_state = "sheet-hide" + origin_tech = "" + +/obj/item/stack/sheet/animalhide/corgi + name = "corgi hide" + desc = "The by-product of corgi farming." + singular_name = "corgi hide piece" + icon_state = "sheet-corgi" + origin_tech = "" + +/obj/item/stack/sheet/animalhide/cat + name = "cat hide" + desc = "The by-product of cat farming." + singular_name = "cat hide piece" + icon_state = "sheet-cat" + origin_tech = "" + +/obj/item/stack/sheet/animalhide/monkey + name = "monkey hide" + desc = "The by-product of monkey farming." + singular_name = "monkey hide piece" + icon_state = "sheet-monkey" + origin_tech = "" + +/obj/item/stack/sheet/animalhide/lizard + name = "lizard skin" + desc = "Sssssss..." + singular_name = "lizard skin piece" + icon_state = "sheet-lizard" + origin_tech = "" + +/obj/item/stack/sheet/animalhide/xeno + name = "alien hide" + desc = "The skin of a terrible creature." + singular_name = "alien hide piece" + icon_state = "sheet-xeno" + origin_tech = "" + +//don't see anywhere else to put these, maybe together they could be used to make the xenos suit? +/obj/item/stack/sheet/xenochitin + name = "alien chitin" + desc = "A piece of the hide of a terrible creature." + singular_name = "alien hide piece" + icon = 'icons/obj/butchering_products.dmi' + icon_state = "chitin" + origin_tech = "" + +/obj/item/xenos_claw + name = "alien claw" + desc = "The claw of a terrible creature." + icon = 'icons/obj/butchering_products.dmi' + icon_state = "claw" + origin_tech = "" + +/obj/item/xenos_claw/attackby(obj/item/W, mob/user) + .=..() + + if(istype(W,/obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = W + + if(C.use(5)) + user.drop_item(src, force_drop = 1) + + var/obj/item/clothing/mask/necklace/xeno_claw/X = new(get_turf(src)) + user.put_in_active_hand(X) + to_chat(user, "You create a necklace out of \the [src] and \the [C].") + + qdel(src) + else + to_chat(user, "You need at least 5 lengths of cable to do this!") + +/obj/item/weed_extract + name = "weed extract" + desc = "A piece of slimy, purplish weed." + icon = 'icons/mob/alien.dmi' + icon_state = "weed_extract" + origin_tech = "" + +/obj/item/stack/sheet/hairlesshide + name = "hairless hide" + desc = "This hide was stripped of it's hair, but still needs tanning." + singular_name = "hairless hide piece" + icon = 'icons/obj/butchering_products.dmi' + icon_state = "sheet-hairlesshide" + origin_tech = "" + +/obj/item/stack/sheet/wetleather + name = "wet leather" + desc = "This leather has been cleaned but still needs to be dried." + singular_name = "wet leather piece" + icon = 'icons/obj/butchering_products.dmi' + icon_state = "sheet-wetleather" + origin_tech = "" + var/wetness = 30 //Reduced when exposed to high temperautres + var/drying_threshold_temperature = 500 //Kelvin to start drying + +/obj/item/stack/sheet/leather + name = "leather" + desc = "The by-product of mob grinding." + singular_name = "leather piece" + icon = 'icons/obj/butchering_products.dmi' + icon_state = "sheet-leather" + origin_tech = "materials=2" + + + +//Step one - dehairing. + +/obj/item/stack/sheet/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob) + if( W.is_sharp() >= 1.2 ) + + //visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message) + user.visible_message("\the [usr] starts cutting hair off \the [src]", "You start cutting the hair off \the [src]", "You hear the sound of a knife rubbing against flesh") + + spawn() + if(do_after(user, src, 50)) + to_chat(user, "You cut the hair from this [src.singular_name]") + + if(src.use(1)) + drop_stack(/obj/item/stack/sheet/hairlesshide, user.loc, 1, user) + return 1 + else + ..() + + +//Step two - washing..... it's actually in washing machine code. + +//Step three - drying +/obj/item/stack/sheet/wetleather/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + ..() + if(exposed_temperature >= drying_threshold_temperature) + wetness-- + if(wetness == 0) + + if(src.use(1)) + drop_stack(/obj/item/stack/sheet/leather, src.loc, 1) + wetness = initial(wetness) diff --git a/code/game/objects/items/stacks/sheets/light.dm b/code/game/objects/items/stacks/sheets/light.dm index b360622ca50..6d2700df316 100644 --- a/code/game/objects/items/stacks/sheets/light.dm +++ b/code/game/objects/items/stacks/sheets/light.dm @@ -1,34 +1,34 @@ -/obj/item/stack/light_w - name = "wired glass tiles" - singular_name = "wired glass floor tile" - desc = "A glass tile, which is wired, somehow." - icon_state = "glass_wire" - w_class = 3.0 - force = 3.0 - throwforce = 5.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - -/obj/item/stack/light_w/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O,/obj/item/weapon/wirecutters)) - var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) - CC.amount = 5 - amount-- - new/obj/item/stack/sheet/glass/glass(user.loc) - if(amount <= 0) - user.drop_from_inventory(src) - qdel(src) - return - - if(istype(O,/obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/M = O - M.use(1) - src.use(1) - - drop_stack(/obj/item/stack/tile/light, get_turf(user), 1, user) - - return - return ..() +/obj/item/stack/light_w + name = "wired glass tiles" + singular_name = "wired glass floor tile" + desc = "A glass tile, which is wired, somehow." + icon_state = "glass_wire" + w_class = 3.0 + force = 3.0 + throwforce = 5.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + +/obj/item/stack/light_w/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O,/obj/item/weapon/wirecutters)) + var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) + CC.amount = 5 + amount-- + new/obj/item/stack/sheet/glass/glass(user.loc) + if(amount <= 0) + user.drop_from_inventory(src) + qdel(src) + return + + if(istype(O,/obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = O + M.use(1) + src.use(1) + + drop_stack(/obj/item/stack/tile/light, get_turf(user), 1, user) + + return + return ..() diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index c8292858017..a3299ddefec 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -1,471 +1,471 @@ -/* -Mineral Sheets - Contains: - - Sandstone - - Diamond - - Uranium - - Plasma - - Gold - - Silver - - Clown - - Plastic - Others: - - Adamantine - - Mythril - - Enriched Uranium -*/ - -/obj/item/stack/sheet/mineral - w_type = RECYK_METAL - var/recyck_mat - -/obj/item/stack/sheet/mineral/recycle(var/datum/materials/rec) - if(!recyck_mat) - return 0 - - rec.addAmount(recyck_mat, amount) - . = 1 - -/* - * Sandstone - */ -/obj/item/stack/sheet/mineral/sandstone - name = "sandstone bricks" - desc = "This appears to be a combination of both sand and stone." - singular_name = "sandstone brick" - icon_state = "sheet-sandstone" - throw_speed = 4 - throw_range = 5 - origin_tech = "materials=1" - sheettype = "sandstone" - melt_temperature = MELTPOINT_GLASS - recyck_mat = MAT_GLASS - -var/global/list/datum/stack_recipe/sandstone_recipes = list ( \ - new/datum/stack_recipe("pile of dirt", /obj/machinery/portable_atmospherics/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("sandstone door", /obj/machinery/door/mineral/sandstone, 10, one_per_turf = 1, on_floor = 1), \ -/* new/datum/stack_recipe("sandstone wall", ???), \ - new/datum/stack_recipe("sandstone floor", ???),\ */ - ) - -/obj/item/stack/sheet/mineral/sandstone/New(var/loc, var/amount=null) - recipes = sandstone_recipes - ..() - -/* - * Diamond - */ -/obj/item/stack/sheet/mineral/diamond - name = "diamond" - singular_name = "diamond sheet" - icon_state = "sheet-diamond" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_range = 3 - origin_tech = "materials=6" - perunit = 1750 - sheettype = "diamond" - melt_temperature = 3820 // In a vacuum, but fuck dat - recyck_mat = MAT_DIAMOND - -var/global/list/datum/stack_recipe/diamond_recipes = list ( \ - new/datum/stack_recipe("diamond floor tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \ - new/datum/stack_recipe("diamond door", /obj/machinery/door/mineral/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \ - ) - -/obj/item/stack/sheet/mineral/diamond/New(var/loc, var/amount=null) - recipes = diamond_recipes - ..() - -/* - * Uranium - */ -/obj/item/stack/sheet/mineral/uranium - name = "uranium" - singular_name = "uranium sheet" - icon_state = "sheet-uranium" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 2000 - sheettype = "uranium" - melt_temperature = 1132+T0C - recyck_mat = MAT_URANIUM - -var/global/list/datum/stack_recipe/uranium_recipes = list ( \ - new/datum/stack_recipe("uranium floor tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \ - new/datum/stack_recipe("uranium door", /obj/machinery/door/mineral/uranium, 10, one_per_turf = 1, on_floor = 1), \ - ) - -/obj/item/stack/sheet/mineral/uranium/New(var/loc, var/amount=null) - recipes = uranium_recipes - ..() - -/* - * Plasma - */ -/obj/item/stack/sheet/mineral/plasma - name = "solid plasma" - singular_name = "plasma sheet" - icon_state = "sheet-plasma" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "plasmatech=2;materials=2" - perunit = 2000 - sheettype = "plasma" - melt_temperature = MELTPOINT_STEEL + 500 - recyck_mat = MAT_PLASMA - -var/global/list/datum/stack_recipe/plasma_recipes = list ( \ - new/datum/stack_recipe("plasma floor tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \ - new/datum/stack_recipe("plasma door", /obj/machinery/door/mineral/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \ - ) - -/obj/item/stack/sheet/mineral/plasma/New(var/loc, var/amount=null) - recipes = plasma_recipes - - ..() - -/obj/item/stack/sheet/mineral/plastic - name = "plastic" - singular_name = "plastic sheet" - icon_state = "sheet-plastic" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=3" - perunit = 2000 - melt_temperature = MELTPOINT_PLASTIC - sheettype = "plastic" - recyck_mat = MAT_PLASTIC - -var/global/list/datum/stack_recipe/plastic_recipes = list ( \ - new/datum/stack_recipe("plastic floor tile", /obj/item/stack/tile/mineral/plastic, 1, 4, 20), \ - new/datum/stack_recipe("plastic crate", /obj/structure/closet/pcrate, 10, one_per_turf = 1, on_floor = 1, one_per_turf = 1), \ - new/datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 2, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("plastic fork", /obj/item/weapon/kitchen/utensil/fork/plastic, 1, on_floor = 1), \ - new/datum/stack_recipe("plastic spoon", /obj/item/weapon/kitchen/utensil/spoon/plastic, 1, on_floor = 1), \ - new/datum/stack_recipe("plastic knife", /obj/item/weapon/kitchen/utensil/knife/plastic, 1, on_floor = 1), \ - new/datum/stack_recipe("plastic bag", /obj/item/weapon/storage/bag/plasticbag, 3, on_floor = 1), \ - new/datum/stack_recipe("blood bag", /obj/item/weapon/reagent_containers/blood/empty, 3, on_floor = 1), \ - new/datum/stack_recipe("plastic coat", /obj/item/clothing/suit/raincoat, 5), \ - new/datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 10, one_per_turf = 1, on_floor = 1, start_unanchored = 1), \ - new/datum/stack_recipe("water-cooler", /obj/structure/reagent_dispensers/water_cooler, 4, one_per_turf = 1, on_floor = 1), \ - ) - -/obj/item/stack/sheet/mineral/plastic/New(var/loc, var/amount=null) - recipes = plastic_recipes - ..() - -/* - * Gold - */ -/obj/item/stack/sheet/mineral/gold - name = "gold" - singular_name = "gold sheet" - icon_state = "sheet-gold" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=4" - perunit = 2000 - melt_temperature = 1064+T0C - sheettype = "gold" - recyck_mat = MAT_GOLD - -var/global/list/datum/stack_recipe/gold_recipes = list ( \ - new/datum/stack_recipe("golden floor tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \ - new/datum/stack_recipe("golden door", /obj/machinery/door/mineral/gold, 10, one_per_turf = 1, on_floor = 1), \ - ) - -/obj/item/stack/sheet/mineral/gold/New(var/loc, var/amount=null) - recipes = gold_recipes - ..() - -/* - * Phazon - */ -var/global/list/datum/stack_recipe/phazon_recipes = list( \ - new/datum/stack_recipe("phazon floor tile", /obj/item/stack/tile/mineral/phazon, 1, 4, 20), \ - ) - -/obj/item/stack/sheet/mineral/phazon - name = "phazon" - singular_name = "phazon sheet" - desc = "Holy christ what is this?" - icon_state = "sheet-phazon" - item_state = "sheet-phazon" - sheettype = "phazon" - perunit = 1500 - melt_temperature = MELTPOINT_PLASTIC - throwforce = 15.0 - flags = FPRINT - siemens_coefficient = 1 - origin_tech = "materials=9" - recyck_mat = MAT_PHAZON - -/obj/item/stack/sheet/mineral/phazon/New(var/loc, var/amount=null) - recipes = phazon_recipes - return ..() - -/* - * Silver - */ -/obj/item/stack/sheet/mineral/silver - name = "silver" - singular_name = "silver sheet" - icon_state = "sheet-silver" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=3" - perunit = 2000 - sheettype = "silver" - recyck_mat = MAT_SILVER - -var/global/list/datum/stack_recipe/silver_recipes = list ( \ - new/datum/stack_recipe("silver floor tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \ - new/datum/stack_recipe("silver door", /obj/machinery/door/mineral/silver, 10, one_per_turf = 1, on_floor = 1), \ - ) - -/obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null) - recipes = silver_recipes - ..() - -/* - * Clown - */ -/obj/item/stack/sheet/mineral/clown - name = "bananium" - singular_name = "bananium sheet" - icon_state = "sheet-clown" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=4" - perunit = 2000 - sheettype = "clown" - recyck_mat = MAT_CLOWN - -var/global/list/datum/stack_recipe/clown_recipes = list ( \ - new/datum/stack_recipe("bananium floor tile", /obj/item/stack/tile/mineral/clown, 1, 4, 20), \ - ) - -/obj/item/stack/sheet/mineral/clown/New(var/loc, var/amount=null) - recipes = clown_recipes - ..() - -/****************************** Others ****************************/ - -/* - * Enriched Uranium - */ -/obj/item/stack/sheet/mineral/enruranium - name = "enriched uranium" - icon_state = "sheet-enruranium" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 1000 - -/* - * Adamantine - */ -/obj/item/stack/sheet/mineral/adamantine - name = "adamantine" - icon_state = "sheet-adamantine" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=4" - perunit = 2000 - -/* - * Mythril - */ -/obj/item/stack/sheet/mineral/mythril - name = "mythril" - icon_state = "sheet-mythril" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=4" - perunit = 2000 - -/* -/obj/item/stack/sheet/mineral/pharosium - name = "pharosium" - icon_state = "sheet-pharosium" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - -/obj/item/stack/sheet/mineral/char - name = "char" - icon_state = "sheet-char" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/claretine - name = "claretine" - icon_state = "sheet-claretine" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/cobryl - name = "cobryl" - icon_state = "sheet-cobryl" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/bohrum - name = "bohrum" - icon_state = "sheet-bohrum" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/syreline - name = "syreline" - icon_state = "sheet-syreline" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/erebite - name = "erebite" - icon_state = "sheet-erebite" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/cerenkite - name = "cerenkite" - icon_state = "sheet-cerenkite" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/cytine - name = "cytine" - icon_state = "sheet-cytine" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/uqill - name = "uqill" - icon_state = "sheet-uqill" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/telecrystal - name = "telecrystal" - icon_state = "sheet-telecrystal" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/mauxite - name = "mauxite" - icon_state = "sheet-mauxite" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 - - -/obj/item/stack/sheet/mineral/molitz - name = "molitz" - icon_state = "sheet-molitz" - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=5" - perunit = 3750 -*/ +/* +Mineral Sheets + Contains: + - Sandstone + - Diamond + - Uranium + - Plasma + - Gold + - Silver + - Clown + - Plastic + Others: + - Adamantine + - Mythril + - Enriched Uranium +*/ + +/obj/item/stack/sheet/mineral + w_type = RECYK_METAL + var/recyck_mat + +/obj/item/stack/sheet/mineral/recycle(var/datum/materials/rec) + if(!recyck_mat) + return 0 + + rec.addAmount(recyck_mat, amount) + . = 1 + +/* + * Sandstone + */ +/obj/item/stack/sheet/mineral/sandstone + name = "sandstone bricks" + desc = "This appears to be a combination of both sand and stone." + singular_name = "sandstone brick" + icon_state = "sheet-sandstone" + throw_speed = 4 + throw_range = 5 + origin_tech = "materials=1" + sheettype = "sandstone" + melt_temperature = MELTPOINT_GLASS + recyck_mat = MAT_GLASS + +var/global/list/datum/stack_recipe/sandstone_recipes = list ( \ + new/datum/stack_recipe("pile of dirt", /obj/machinery/portable_atmospherics/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("sandstone door", /obj/machinery/door/mineral/sandstone, 10, one_per_turf = 1, on_floor = 1), \ +/* new/datum/stack_recipe("sandstone wall", ???), \ + new/datum/stack_recipe("sandstone floor", ???),\ */ + ) + +/obj/item/stack/sheet/mineral/sandstone/New(var/loc, var/amount=null) + recipes = sandstone_recipes + ..() + +/* + * Diamond + */ +/obj/item/stack/sheet/mineral/diamond + name = "diamond" + singular_name = "diamond sheet" + icon_state = "sheet-diamond" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_range = 3 + origin_tech = "materials=6" + perunit = 1750 + sheettype = "diamond" + melt_temperature = 3820 // In a vacuum, but fuck dat + recyck_mat = MAT_DIAMOND + +var/global/list/datum/stack_recipe/diamond_recipes = list ( \ + new/datum/stack_recipe("diamond floor tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \ + new/datum/stack_recipe("diamond door", /obj/machinery/door/mineral/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \ + ) + +/obj/item/stack/sheet/mineral/diamond/New(var/loc, var/amount=null) + recipes = diamond_recipes + ..() + +/* + * Uranium + */ +/obj/item/stack/sheet/mineral/uranium + name = "uranium" + singular_name = "uranium sheet" + icon_state = "sheet-uranium" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 2000 + sheettype = "uranium" + melt_temperature = 1132+T0C + recyck_mat = MAT_URANIUM + +var/global/list/datum/stack_recipe/uranium_recipes = list ( \ + new/datum/stack_recipe("uranium floor tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \ + new/datum/stack_recipe("uranium door", /obj/machinery/door/mineral/uranium, 10, one_per_turf = 1, on_floor = 1), \ + ) + +/obj/item/stack/sheet/mineral/uranium/New(var/loc, var/amount=null) + recipes = uranium_recipes + ..() + +/* + * Plasma + */ +/obj/item/stack/sheet/mineral/plasma + name = "solid plasma" + singular_name = "plasma sheet" + icon_state = "sheet-plasma" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "plasmatech=2;materials=2" + perunit = 2000 + sheettype = "plasma" + melt_temperature = MELTPOINT_STEEL + 500 + recyck_mat = MAT_PLASMA + +var/global/list/datum/stack_recipe/plasma_recipes = list ( \ + new/datum/stack_recipe("plasma floor tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \ + new/datum/stack_recipe("plasma door", /obj/machinery/door/mineral/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \ + ) + +/obj/item/stack/sheet/mineral/plasma/New(var/loc, var/amount=null) + recipes = plasma_recipes + + ..() + +/obj/item/stack/sheet/mineral/plastic + name = "plastic" + singular_name = "plastic sheet" + icon_state = "sheet-plastic" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=3" + perunit = 2000 + melt_temperature = MELTPOINT_PLASTIC + sheettype = "plastic" + recyck_mat = MAT_PLASTIC + +var/global/list/datum/stack_recipe/plastic_recipes = list ( \ + new/datum/stack_recipe("plastic floor tile", /obj/item/stack/tile/mineral/plastic, 1, 4, 20), \ + new/datum/stack_recipe("plastic crate", /obj/structure/closet/pcrate, 10, one_per_turf = 1, on_floor = 1, one_per_turf = 1), \ + new/datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 2, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("plastic fork", /obj/item/weapon/kitchen/utensil/fork/plastic, 1, on_floor = 1), \ + new/datum/stack_recipe("plastic spoon", /obj/item/weapon/kitchen/utensil/spoon/plastic, 1, on_floor = 1), \ + new/datum/stack_recipe("plastic knife", /obj/item/weapon/kitchen/utensil/knife/plastic, 1, on_floor = 1), \ + new/datum/stack_recipe("plastic bag", /obj/item/weapon/storage/bag/plasticbag, 3, on_floor = 1), \ + new/datum/stack_recipe("blood bag", /obj/item/weapon/reagent_containers/blood/empty, 3, on_floor = 1), \ + new/datum/stack_recipe("plastic coat", /obj/item/clothing/suit/raincoat, 5), \ + new/datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 10, one_per_turf = 1, on_floor = 1, start_unanchored = 1), \ + new/datum/stack_recipe("water-cooler", /obj/structure/reagent_dispensers/water_cooler, 4, one_per_turf = 1, on_floor = 1), \ + ) + +/obj/item/stack/sheet/mineral/plastic/New(var/loc, var/amount=null) + recipes = plastic_recipes + ..() + +/* + * Gold + */ +/obj/item/stack/sheet/mineral/gold + name = "gold" + singular_name = "gold sheet" + icon_state = "sheet-gold" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=4" + perunit = 2000 + melt_temperature = 1064+T0C + sheettype = "gold" + recyck_mat = MAT_GOLD + +var/global/list/datum/stack_recipe/gold_recipes = list ( \ + new/datum/stack_recipe("golden floor tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \ + new/datum/stack_recipe("golden door", /obj/machinery/door/mineral/gold, 10, one_per_turf = 1, on_floor = 1), \ + ) + +/obj/item/stack/sheet/mineral/gold/New(var/loc, var/amount=null) + recipes = gold_recipes + ..() + +/* + * Phazon + */ +var/global/list/datum/stack_recipe/phazon_recipes = list( \ + new/datum/stack_recipe("phazon floor tile", /obj/item/stack/tile/mineral/phazon, 1, 4, 20), \ + ) + +/obj/item/stack/sheet/mineral/phazon + name = "phazon" + singular_name = "phazon sheet" + desc = "Holy christ what is this?" + icon_state = "sheet-phazon" + item_state = "sheet-phazon" + sheettype = "phazon" + perunit = 1500 + melt_temperature = MELTPOINT_PLASTIC + throwforce = 15.0 + flags = FPRINT + siemens_coefficient = 1 + origin_tech = "materials=9" + recyck_mat = MAT_PHAZON + +/obj/item/stack/sheet/mineral/phazon/New(var/loc, var/amount=null) + recipes = phazon_recipes + return ..() + +/* + * Silver + */ +/obj/item/stack/sheet/mineral/silver + name = "silver" + singular_name = "silver sheet" + icon_state = "sheet-silver" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=3" + perunit = 2000 + sheettype = "silver" + recyck_mat = MAT_SILVER + +var/global/list/datum/stack_recipe/silver_recipes = list ( \ + new/datum/stack_recipe("silver floor tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \ + new/datum/stack_recipe("silver door", /obj/machinery/door/mineral/silver, 10, one_per_turf = 1, on_floor = 1), \ + ) + +/obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null) + recipes = silver_recipes + ..() + +/* + * Clown + */ +/obj/item/stack/sheet/mineral/clown + name = "bananium" + singular_name = "bananium sheet" + icon_state = "sheet-clown" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=4" + perunit = 2000 + sheettype = "clown" + recyck_mat = MAT_CLOWN + +var/global/list/datum/stack_recipe/clown_recipes = list ( \ + new/datum/stack_recipe("bananium floor tile", /obj/item/stack/tile/mineral/clown, 1, 4, 20), \ + ) + +/obj/item/stack/sheet/mineral/clown/New(var/loc, var/amount=null) + recipes = clown_recipes + ..() + +/****************************** Others ****************************/ + +/* + * Enriched Uranium + */ +/obj/item/stack/sheet/mineral/enruranium + name = "enriched uranium" + icon_state = "sheet-enruranium" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 1000 + +/* + * Adamantine + */ +/obj/item/stack/sheet/mineral/adamantine + name = "adamantine" + icon_state = "sheet-adamantine" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=4" + perunit = 2000 + +/* + * Mythril + */ +/obj/item/stack/sheet/mineral/mythril + name = "mythril" + icon_state = "sheet-mythril" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=4" + perunit = 2000 + +/* +/obj/item/stack/sheet/mineral/pharosium + name = "pharosium" + icon_state = "sheet-pharosium" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + +/obj/item/stack/sheet/mineral/char + name = "char" + icon_state = "sheet-char" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/claretine + name = "claretine" + icon_state = "sheet-claretine" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/cobryl + name = "cobryl" + icon_state = "sheet-cobryl" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/bohrum + name = "bohrum" + icon_state = "sheet-bohrum" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/syreline + name = "syreline" + icon_state = "sheet-syreline" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/erebite + name = "erebite" + icon_state = "sheet-erebite" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/cerenkite + name = "cerenkite" + icon_state = "sheet-cerenkite" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/cytine + name = "cytine" + icon_state = "sheet-cytine" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/uqill + name = "uqill" + icon_state = "sheet-uqill" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/telecrystal + name = "telecrystal" + icon_state = "sheet-telecrystal" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/mauxite + name = "mauxite" + icon_state = "sheet-mauxite" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 + + +/obj/item/stack/sheet/mineral/molitz + name = "molitz" + icon_state = "sheet-molitz" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + origin_tech = "materials=5" + perunit = 3750 +*/ diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index 7533d38203b..8776c9c2c0b 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -1,33 +1,33 @@ -/obj/item/stack/sheet - name = "sheet" - flags = FPRINT - w_class = 3.0 - force = 5 - throwforce = 5 - max_amount = 50 - throw_speed = 3 - throw_range = 3 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") - perunit=3750 - var/sheettype = null //this is used for girders in the creation of walls/false walls - - mech_flags = MECH_SCAN_FAIL - -/obj/item/stack/sheet/New(var/newloc, var/amount = null) - pixel_x = rand(0,4)-4 - pixel_y = rand(0,4)-4 - ..() - - -// Since the sheetsnatcher was consolidated into weapon/storage/bag we now use -// item/attackby() properly, making this unnecessary - -/*/obj/item/stack/sheet/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/storage/bag/sheetsnatcher)) - var/obj/item/weapon/storage/bag/sheetsnatcher/S = W - if(!S.mode) - S.add(src,user) - else - for (var/obj/item/stack/sheet/stack in locate(src.x,src.y,src.z)) - S.add(stack,user) +/obj/item/stack/sheet + name = "sheet" + flags = FPRINT + w_class = 3.0 + force = 5 + throwforce = 5 + max_amount = 50 + throw_speed = 3 + throw_range = 3 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") + perunit=3750 + var/sheettype = null //this is used for girders in the creation of walls/false walls + + mech_flags = MECH_SCAN_FAIL + +/obj/item/stack/sheet/New(var/newloc, var/amount = null) + pixel_x = rand(0,4)-4 + pixel_y = rand(0,4)-4 + ..() + + +// Since the sheetsnatcher was consolidated into weapon/storage/bag we now use +// item/attackby() properly, making this unnecessary + +/*/obj/item/stack/sheet/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/storage/bag/sheetsnatcher)) + var/obj/item/weapon/storage/bag/sheetsnatcher/S = W + if(!S.mode) + S.add(src,user) + else + for (var/obj/item/stack/sheet/stack in locate(src.x,src.y,src.z)) + S.add(stack,user) ..()*/ \ No newline at end of file diff --git a/code/game/objects/items/stacks/tiles/light.dm b/code/game/objects/items/stacks/tiles/light.dm index 40fad866bb2..aa8967b798c 100644 --- a/code/game/objects/items/stacks/tiles/light.dm +++ b/code/game/objects/items/stacks/tiles/light.dm @@ -1,91 +1,91 @@ -var/global/list/lightfloor_colors = list( - "white" = rgb(255,255,255), \ - "red" = rgb(255,0,0), \ - "orange" = rgb(255,106,0), \ - "yellow" = rgb(255,216,0), \ - "green" = rgb(0,255,0), \ - "dark green" = rgb(60,215,0), \ - "teal" = rgb(0,234,234), \ - "light blue" = rgb(0,148,255), \ - "dark blue" = rgb(0,38,255), \ - "purple" = rgb(178,0,255), \ - "pink" = rgb(255,135,255), \ - ) - -#define LIGHTFLOOR_OPTION_CUSTOM "Custom" - -/obj/item/stack/tile/light - name = "light tile" - singular_name = "light floor tile" - desc = "A floor tile made out of glass. Use a multitool on it to change its color." - icon_state = "light_tile_broken" - w_class = 3.0 - force = 3.0 - throwforce = 5.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") - - material = "glass" - - var/on = 1 - - var/color_r = 255 - var/color_g = 255 - var/color_b = 255 - - var/image/color_overlay - -/obj/item/stack/tile/light/New() - .=..() - update_icon() - overlays += color_overlay - -/obj/item/stack/tile/light/update_icon(var/new_color) - .=..() - overlays = list() - color_overlay = image('icons/obj/items.dmi', icon_state = "light_tile_overlay") - color_overlay.color = rgb(color_r,color_g,color_b) - overlays += color_overlay - -/obj/item/stack/tile/light/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O,/obj/item/weapon/crowbar)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 1 - amount-- - new/obj/item/stack/light_w(user.loc) - if(amount <= 0) - user.drop_from_inventory(src) - qdel(src) - return 1 - else if(istype(O,/obj/item/device/multitool)) - var/list/choice_list = list(LIGHTFLOOR_OPTION_CUSTOM) + lightfloor_colors - - var/choice = input(user,"Select a colour to set [src] to.","[src]") in choice_list - if(!Adjacent(user)) return - - var/new_color - if(choice == LIGHTFLOOR_OPTION_CUSTOM) - new_color = input("Please select a color for the tile.", "[src]",rgb(color_r,color_g,color_b)) as color - if(new_color) - color_r = hex2num(copytext(new_color, 2, 4)) - color_g = hex2num(copytext(new_color, 4, 6)) - color_b = hex2num(copytext(new_color, 6, 8)) - else - new_color = choice_list[choice] - color_r = hex2num(copytext(new_color, 2, 4)) - color_g = hex2num(copytext(new_color, 4, 6)) - color_b = hex2num(copytext(new_color, 6, 8)) - - update_icon() - - return ..() - -/obj/item/stack/tile/light/proc/get_turf_image() - - var/image/I = image('icons/turf/floors.dmi',icon_state = "light_overlay") - I.color = rgb(color_r,color_g,color_b) - return I +var/global/list/lightfloor_colors = list( + "white" = rgb(255,255,255), \ + "red" = rgb(255,0,0), \ + "orange" = rgb(255,106,0), \ + "yellow" = rgb(255,216,0), \ + "green" = rgb(0,255,0), \ + "dark green" = rgb(60,215,0), \ + "teal" = rgb(0,234,234), \ + "light blue" = rgb(0,148,255), \ + "dark blue" = rgb(0,38,255), \ + "purple" = rgb(178,0,255), \ + "pink" = rgb(255,135,255), \ + ) + +#define LIGHTFLOOR_OPTION_CUSTOM "Custom" + +/obj/item/stack/tile/light + name = "light tile" + singular_name = "light floor tile" + desc = "A floor tile made out of glass. Use a multitool on it to change its color." + icon_state = "light_tile_broken" + w_class = 3.0 + force = 3.0 + throwforce = 5.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") + + material = "glass" + + var/on = 1 + + var/color_r = 255 + var/color_g = 255 + var/color_b = 255 + + var/image/color_overlay + +/obj/item/stack/tile/light/New() + .=..() + update_icon() + overlays += color_overlay + +/obj/item/stack/tile/light/update_icon(var/new_color) + .=..() + overlays = list() + color_overlay = image('icons/obj/items.dmi', icon_state = "light_tile_overlay") + color_overlay.color = rgb(color_r,color_g,color_b) + overlays += color_overlay + +/obj/item/stack/tile/light/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O,/obj/item/weapon/crowbar)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 1 + amount-- + new/obj/item/stack/light_w(user.loc) + if(amount <= 0) + user.drop_from_inventory(src) + qdel(src) + return 1 + else if(istype(O,/obj/item/device/multitool)) + var/list/choice_list = list(LIGHTFLOOR_OPTION_CUSTOM) + lightfloor_colors + + var/choice = input(user,"Select a colour to set [src] to.","[src]") in choice_list + if(!Adjacent(user)) return + + var/new_color + if(choice == LIGHTFLOOR_OPTION_CUSTOM) + new_color = input("Please select a color for the tile.", "[src]",rgb(color_r,color_g,color_b)) as color + if(new_color) + color_r = hex2num(copytext(new_color, 2, 4)) + color_g = hex2num(copytext(new_color, 4, 6)) + color_b = hex2num(copytext(new_color, 6, 8)) + else + new_color = choice_list[choice] + color_r = hex2num(copytext(new_color, 2, 4)) + color_g = hex2num(copytext(new_color, 4, 6)) + color_b = hex2num(copytext(new_color, 6, 8)) + + update_icon() + + return ..() + +/obj/item/stack/tile/light/proc/get_turf_image() + + var/image/I = image('icons/turf/floors.dmi',icon_state = "light_overlay") + I.color = rgb(color_r,color_g,color_b) + return I diff --git a/code/game/objects/items/stacks/tiles/plasteel.dm b/code/game/objects/items/stacks/tiles/plasteel.dm index cf77ffa3b6f..8af306ed89b 100644 --- a/code/game/objects/items/stacks/tiles/plasteel.dm +++ b/code/game/objects/items/stacks/tiles/plasteel.dm @@ -1,100 +1,100 @@ -/obj/item/stack/tile/plasteel - name = "floor tile" - singular_name = "floor tile" - desc = "Those could work as a pretty decent throwing weapon" - icon_state = "tile" - w_class = 3.0 - force = 6.0 - starting_materials = list(MAT_IRON = 937.5) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - throwforce = 15.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - - material = "metal" - -/obj/item/stack/tile/plasteel/New(var/loc, var/amount=null) - . = ..() - pixel_x = rand(1, 14) - pixel_y = rand(1, 14) - -/obj/item/stack/tile/plasteel/recycle(var/datum/materials/rec) - rec.addAmount("iron",amount/4) - return 1 - -/* -/obj/item/stack/tile/plasteel/attack_self(mob/user as mob) - if (usr.stat) - return - var/T = user.loc - if (!( istype(T, /turf) )) - to_chat(user, "You must be on the ground!") - return - if (!( istype(T, /turf/space) )) - to_chat(user, "You cannot build on or repair this turf!") - return - src.build(T) - src.add_fingerprint(user) - use(1) - return -*/ - -/obj/item/stack/tile/plasteel/proc/build(turf/S as turf) - - - if(istype(S,/turf/space) || istype(S,/turf/unsimulated)) - S.ChangeTurf(/turf/simulated/floor/plating/airless) - else - S.ChangeTurf(/turf/simulated/floor/plating) - return - -/obj/item/stack/tile/plasteel/attackby(obj/item/W as obj, mob/user as mob) - if(iswelder(W)) - var/obj/item/weapon/weldingtool/WT = W - if(amount < 4) - to_chat(user, "You need at least four tiles to do this.") - return - - if(WT.remove_fuel(0,user)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(usr)) - M.amount = 1 - M.add_to_stacks(usr) - user.visible_message("[src] is shaped into metal by [user.name] with the weldingtool.", \ - "You shape the [src] into metal with the weldingtool.", \ - "You hear welding.") - var/obj/item/stack/tile/plasteel/R = src - src = null - var/replace = (user.get_inactive_hand()==R) - R.use(4) - if (!R && replace) - user.put_in_hands(M) - return 1 - return ..() - -/obj/item/stack/tile/plasteel/afterattack(atom/target, mob/user, adjacent, params) - if(adjacent) - if(isturf(target) || istype(target, /obj/structure/lattice)) - var/turf/T = get_turf(target) - var/obj/structure/lattice/L - var/obj/item/stack/tile/plasteel/S = src - switch(T.canBuildPlating()) - if(BUILD_SUCCESS) - L = locate(/obj/structure/lattice) in T - if(!istype(L)) - return - qdel(L) - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) - S.build(T) - S.use(1) - return - if(BUILD_IGNORE) - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) - S.build(T) - S.use(1) - if(BUILD_FAILURE) - to_chat(user, "The plating is going to need some support.") - return +/obj/item/stack/tile/plasteel + name = "floor tile" + singular_name = "floor tile" + desc = "Those could work as a pretty decent throwing weapon" + icon_state = "tile" + w_class = 3.0 + force = 6.0 + starting_materials = list(MAT_IRON = 937.5) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + throwforce = 15.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + + material = "metal" + +/obj/item/stack/tile/plasteel/New(var/loc, var/amount=null) + . = ..() + pixel_x = rand(1, 14) + pixel_y = rand(1, 14) + +/obj/item/stack/tile/plasteel/recycle(var/datum/materials/rec) + rec.addAmount("iron",amount/4) + return 1 + +/* +/obj/item/stack/tile/plasteel/attack_self(mob/user as mob) + if (usr.stat) + return + var/T = user.loc + if (!( istype(T, /turf) )) + to_chat(user, "You must be on the ground!") + return + if (!( istype(T, /turf/space) )) + to_chat(user, "You cannot build on or repair this turf!") + return + src.build(T) + src.add_fingerprint(user) + use(1) + return +*/ + +/obj/item/stack/tile/plasteel/proc/build(turf/S as turf) + + + if(istype(S,/turf/space) || istype(S,/turf/unsimulated)) + S.ChangeTurf(/turf/simulated/floor/plating/airless) + else + S.ChangeTurf(/turf/simulated/floor/plating) + return + +/obj/item/stack/tile/plasteel/attackby(obj/item/W as obj, mob/user as mob) + if(iswelder(W)) + var/obj/item/weapon/weldingtool/WT = W + if(amount < 4) + to_chat(user, "You need at least four tiles to do this.") + return + + if(WT.remove_fuel(0,user)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(usr)) + M.amount = 1 + M.add_to_stacks(usr) + user.visible_message("[src] is shaped into metal by [user.name] with the weldingtool.", \ + "You shape the [src] into metal with the weldingtool.", \ + "You hear welding.") + var/obj/item/stack/tile/plasteel/R = src + src = null + var/replace = (user.get_inactive_hand()==R) + R.use(4) + if (!R && replace) + user.put_in_hands(M) + return 1 + return ..() + +/obj/item/stack/tile/plasteel/afterattack(atom/target, mob/user, adjacent, params) + if(adjacent) + if(isturf(target) || istype(target, /obj/structure/lattice)) + var/turf/T = get_turf(target) + var/obj/structure/lattice/L + var/obj/item/stack/tile/plasteel/S = src + switch(T.canBuildPlating()) + if(BUILD_SUCCESS) + L = locate(/obj/structure/lattice) in T + if(!istype(L)) + return + qdel(L) + playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + S.build(T) + S.use(1) + return + if(BUILD_IGNORE) + playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + S.build(T) + S.use(1) + if(BUILD_FAILURE) + to_chat(user, "The plating is going to need some support.") + return diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 2a1d510648d..6ceba6c2593 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -1,130 +1,130 @@ -/* Diffrent misc types of tiles - * Contains: - * Grass - * Wood - * Carpet - */ - -/obj/item/stack/tile - var/material - -/obj/item/stack/tile/ex_act(severity) - switch(severity) - if(1.0) - returnToPool(src) - return - if(2.0) - if (prob(50)) - returnToPool(src) - return - if(3.0) - if (prob(5)) - returnToPool(src) - return - else - return - -/obj/item/stack/tile/blob_act() - returnToPool(src) - -/obj/item/stack/tile/singularity_act() - returnToPool(src) - return 2 - -/* - * Grass - */ -/obj/item/stack/tile/grass - name = "grass tile" - singular_name = "grass floor tile" - desc = "A patch of grass like they often use on golf courses" - icon_state = "tile_grass" - w_class = 3.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - origin_tech = "biotech=1" - - material = "grass" - -/* - * Wood - */ -/obj/item/stack/tile/wood - name = "wood floor tile" - singular_name = "wood floor tile" - desc = "an easy to fit wood floor tile" - icon_state = "tile-wood" - w_class = 3.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - - material = "wood" - -/obj/item/stack/tile/wood/proc/build(turf/S as turf) - if(istype(S,/turf/unsimulated/floor/asteroid)) - S.ChangeTurf(/turf/simulated/floor/plating/deck/airless) - else - S.ChangeTurf(/turf/simulated/floor/plating/deck) - -/obj/item/stack/tile/wood/afterattack(atom/target, mob/user, adjacent, params) - if(adjacent) - if(isturf(target) || istype(target, /obj/structure/lattice/wood)) - var/turf/T = get_turf(target) - var/obj/structure/lattice/L - L = locate(/obj/structure/lattice/wood) in T - if(!istype(L)) - return - var/obj/item/stack/tile/wood/S = src - if(!(T.canBuildPlating(S))) - to_chat(user, "You can't get that deck up without some support!") - return - if(S.use(1)) - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) - S.build(T) - if(T.canBuildPlating(S) == BUILD_SUCCESS) - qdel(L) - -/* - * Carpets - */ -/obj/item/stack/tile/carpet - name = "length of carpet" - singular_name = "length of carpet" - desc = "A piece of carpet. It is the same size as a floor tile" - icon_state = "tile-carpet" - w_class = 3.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - - material = "fabric" - -/obj/item/stack/tile/arcade - name = "length of arcade carpet" - singular_name = "length of arcade carpet" - desc = "A piece of arcade carpet. It has a snazzy space theme." - icon_state = "tile-arcade" - w_class = 3.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 5 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - max_amount = 60 - +/* Diffrent misc types of tiles + * Contains: + * Grass + * Wood + * Carpet + */ + +/obj/item/stack/tile + var/material + +/obj/item/stack/tile/ex_act(severity) + switch(severity) + if(1.0) + returnToPool(src) + return + if(2.0) + if (prob(50)) + returnToPool(src) + return + if(3.0) + if (prob(5)) + returnToPool(src) + return + else + return + +/obj/item/stack/tile/blob_act() + returnToPool(src) + +/obj/item/stack/tile/singularity_act() + returnToPool(src) + return 2 + +/* + * Grass + */ +/obj/item/stack/tile/grass + name = "grass tile" + singular_name = "grass floor tile" + desc = "A patch of grass like they often use on golf courses" + icon_state = "tile_grass" + w_class = 3.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + origin_tech = "biotech=1" + + material = "grass" + +/* + * Wood + */ +/obj/item/stack/tile/wood + name = "wood floor tile" + singular_name = "wood floor tile" + desc = "an easy to fit wood floor tile" + icon_state = "tile-wood" + w_class = 3.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + + material = "wood" + +/obj/item/stack/tile/wood/proc/build(turf/S as turf) + if(istype(S,/turf/unsimulated/floor/asteroid)) + S.ChangeTurf(/turf/simulated/floor/plating/deck/airless) + else + S.ChangeTurf(/turf/simulated/floor/plating/deck) + +/obj/item/stack/tile/wood/afterattack(atom/target, mob/user, adjacent, params) + if(adjacent) + if(isturf(target) || istype(target, /obj/structure/lattice/wood)) + var/turf/T = get_turf(target) + var/obj/structure/lattice/L + L = locate(/obj/structure/lattice/wood) in T + if(!istype(L)) + return + var/obj/item/stack/tile/wood/S = src + if(!(T.canBuildPlating(S))) + to_chat(user, "You can't get that deck up without some support!") + return + if(S.use(1)) + playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + S.build(T) + if(T.canBuildPlating(S) == BUILD_SUCCESS) + qdel(L) + +/* + * Carpets + */ +/obj/item/stack/tile/carpet + name = "length of carpet" + singular_name = "length of carpet" + desc = "A piece of carpet. It is the same size as a floor tile" + icon_state = "tile-carpet" + w_class = 3.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + + material = "fabric" + +/obj/item/stack/tile/arcade + name = "length of arcade carpet" + singular_name = "length of arcade carpet" + desc = "A piece of arcade carpet. It has a snazzy space theme." + icon_state = "tile-arcade" + w_class = 3.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 5 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + max_amount = 60 + material = "fabric" \ No newline at end of file diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 59846218ef7..6fbddb85208 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -1,127 +1,127 @@ -//Items labled as 'trash' for the trash bag. -//TODO: Make this an item var or something... - -//Added by Jack Rost -/obj/item/trash - icon = 'icons/obj/trash.dmi' - w_class = 1.0 - desc = "This is rubbish." - w_type=NOT_RECYCLABLE - autoignition_temperature = AUTOIGNITION_PAPER - fire_fuel = 1 - //var/global/list/trash_items = list() - -/obj/item/trash/New() - ..() - trash_items += src - -/obj/item/trash/bustanuts - name = "\improper Busta-Nuts" - icon_state = "busta_nut" - starting_materials = list(MAT_CARDBOARD = 370) - w_type=RECYK_MISC - -/obj/item/trash/raisins - name = "4no raisins" - icon_state= "4no_raisins" - starting_materials = list(MAT_CARDBOARD = 370) - w_type=RECYK_MISC - -/obj/item/trash/candy - name = "candy" - icon_state= "candy" - -/obj/item/trash/cheesie - name = "\improper Cheesie honkers" - icon_state = "cheesie_honkers" - -/obj/item/trash/chips - name = "chips" - icon_state = "chips" - - -/obj/item/trash/popcorn - name = "popcorn" - icon_state = "popcorn" - starting_materials = list(MAT_CARDBOARD = 370) - w_type=RECYK_MISC - -/obj/item/trash/sosjerky - name = "\improper Scaredy's Private Reserve Beef Jerky" - icon_state = "sosjerky" - starting_materials = list(MAT_CARDBOARD = 370) - w_type=RECYK_MISC - -/obj/item/trash/syndi_cakes - name = "\improper Syndi cakes" - icon_state = "syndi_cakes" - starting_materials = list(MAT_CARDBOARD = 370) - w_type=RECYK_MISC - -/obj/item/trash/discountchocolate - name = "\improper Discount Dan's Chocolate Bar" - icon_state = "danbar" - -/obj/item/trash/danitos - name = "\improper Danitos" - icon_state = "danitos" - -/obj/item/trash/waffles - name = "waffles" - icon_state = "waffles" - -/obj/item/trash/plate - name = "plate" - icon_state = "plate" - -/obj/item/trash/pietin - name = "pie tin" - icon_state = "pietin" - autoignition_temperature = 0 - siemens_coefficient = 2 //Do not touch live wires - melt_temperature = MELTPOINT_SILICON //Not as high as steel - -/obj/item/trash/pietin/attackby(obj/item/W, mob/user) - if(istype(W,/obj/item/trash/pietin)) - var/obj/item/I = new /obj/item/clothing/head/tinfoil(get_turf(src)) - qdel(W) - qdel(src) - user.put_in_hands(I) - -/obj/item/trash/snack_bowl - name = "snack bowl" - icon_state = "snack_bowl" - -/obj/item/trash/pistachios - name = "pistachios pack" - icon_state = "pistachios_pack" - -/obj/item/trash/semki - name = "pemki pack" - icon_state = "semki_pack" - -/obj/item/trash/tray - name = "tray" - icon_state = "tray" - -/obj/item/trash/candle - name = "candle" - icon = 'icons/obj/candle.dmi' - icon_state = "candle4" - -/obj/item/trash/liquidfood - name = "\improper \"LiquidFood\" ration" - icon_state = "liquidfood" - -/obj/item/trash/chicken_bucket - name = "chicken bucket" - icon_state = "kfc_bucket" - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - -/obj/item/trash/attack(mob/M as mob, mob/living/user as mob) - return - -/obj/item/trash/Destroy() - trash_items -= src - ..() +//Items labled as 'trash' for the trash bag. +//TODO: Make this an item var or something... + +//Added by Jack Rost +/obj/item/trash + icon = 'icons/obj/trash.dmi' + w_class = 1.0 + desc = "This is rubbish." + w_type=NOT_RECYCLABLE + autoignition_temperature = AUTOIGNITION_PAPER + fire_fuel = 1 + //var/global/list/trash_items = list() + +/obj/item/trash/New() + ..() + trash_items += src + +/obj/item/trash/bustanuts + name = "\improper Busta-Nuts" + icon_state = "busta_nut" + starting_materials = list(MAT_CARDBOARD = 370) + w_type=RECYK_MISC + +/obj/item/trash/raisins + name = "4no raisins" + icon_state= "4no_raisins" + starting_materials = list(MAT_CARDBOARD = 370) + w_type=RECYK_MISC + +/obj/item/trash/candy + name = "candy" + icon_state= "candy" + +/obj/item/trash/cheesie + name = "\improper Cheesie honkers" + icon_state = "cheesie_honkers" + +/obj/item/trash/chips + name = "chips" + icon_state = "chips" + + +/obj/item/trash/popcorn + name = "popcorn" + icon_state = "popcorn" + starting_materials = list(MAT_CARDBOARD = 370) + w_type=RECYK_MISC + +/obj/item/trash/sosjerky + name = "\improper Scaredy's Private Reserve Beef Jerky" + icon_state = "sosjerky" + starting_materials = list(MAT_CARDBOARD = 370) + w_type=RECYK_MISC + +/obj/item/trash/syndi_cakes + name = "\improper Syndi cakes" + icon_state = "syndi_cakes" + starting_materials = list(MAT_CARDBOARD = 370) + w_type=RECYK_MISC + +/obj/item/trash/discountchocolate + name = "\improper Discount Dan's Chocolate Bar" + icon_state = "danbar" + +/obj/item/trash/danitos + name = "\improper Danitos" + icon_state = "danitos" + +/obj/item/trash/waffles + name = "waffles" + icon_state = "waffles" + +/obj/item/trash/plate + name = "plate" + icon_state = "plate" + +/obj/item/trash/pietin + name = "pie tin" + icon_state = "pietin" + autoignition_temperature = 0 + siemens_coefficient = 2 //Do not touch live wires + melt_temperature = MELTPOINT_SILICON //Not as high as steel + +/obj/item/trash/pietin/attackby(obj/item/W, mob/user) + if(istype(W,/obj/item/trash/pietin)) + var/obj/item/I = new /obj/item/clothing/head/tinfoil(get_turf(src)) + qdel(W) + qdel(src) + user.put_in_hands(I) + +/obj/item/trash/snack_bowl + name = "snack bowl" + icon_state = "snack_bowl" + +/obj/item/trash/pistachios + name = "pistachios pack" + icon_state = "pistachios_pack" + +/obj/item/trash/semki + name = "pemki pack" + icon_state = "semki_pack" + +/obj/item/trash/tray + name = "tray" + icon_state = "tray" + +/obj/item/trash/candle + name = "candle" + icon = 'icons/obj/candle.dmi' + icon_state = "candle4" + +/obj/item/trash/liquidfood + name = "\improper \"LiquidFood\" ration" + icon_state = "liquidfood" + +/obj/item/trash/chicken_bucket + name = "chicken bucket" + icon_state = "kfc_bucket" + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + +/obj/item/trash/attack(mob/M as mob, mob/living/user as mob) + return + +/obj/item/trash/Destroy() + trash_items -= src + ..() diff --git a/code/game/objects/items/weapons/RCL.dm b/code/game/objects/items/weapons/RCL.dm index a70f649ca96..977df68c540 100644 --- a/code/game/objects/items/weapons/RCL.dm +++ b/code/game/objects/items/weapons/RCL.dm @@ -1,119 +1,119 @@ -/obj/item/weapon/rcl - name = "rapid cable layer (RCL)" - desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables." - icon = 'icons/obj/items.dmi' - icon_state = "rcl-0" - item_state = "rcl-0" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/electronics.dmi', "right_hand" = 'icons/mob/in-hand/right/electronics.dmi') - opacity = 0 - flags = FPRINT - siemens_coefficient = 1 //Not quite as conductive as working with cables themselves - force = 5.0 //Plastic is soft - throwforce = 5.0 - throw_speed = 1 - throw_range = 10 - w_class = 3.0 - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_PLASTIC - origin_tech = "engineering=2;materials=4" - var/max_amount = 90 - var/active = 0 - var/obj/structure/cable/last = null - var/obj/item/stack/cable_coil/loaded = null - -/obj/item/weapon/rcl/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/stack/cable_coil)) - if(!loaded) - if(user.drop_item(W,src)) - loaded = W - loaded.max_amount = max_amount //We store a lot. - else - loaded.preattack(W,user,1) - update_icon() +/obj/item/weapon/rcl + name = "rapid cable layer (RCL)" + desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables." + icon = 'icons/obj/items.dmi' + icon_state = "rcl-0" + item_state = "rcl-0" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/electronics.dmi', "right_hand" = 'icons/mob/in-hand/right/electronics.dmi') + opacity = 0 + flags = FPRINT + siemens_coefficient = 1 //Not quite as conductive as working with cables themselves + force = 5.0 //Plastic is soft + throwforce = 5.0 + throw_speed = 1 + throw_range = 10 + w_class = 3.0 + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + origin_tech = "engineering=2;materials=4" + var/max_amount = 90 + var/active = 0 + var/obj/structure/cable/last = null + var/obj/item/stack/cable_coil/loaded = null + +/obj/item/weapon/rcl/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/stack/cable_coil)) + if(!loaded) + if(user.drop_item(W,src)) + loaded = W + loaded.max_amount = max_amount //We store a lot. + else + loaded.preattack(W,user,1) + update_icon() to_chat(user, "You add the cables to the [src]. It now contains [loaded.amount].") - else if(isscrewdriver(W)) - if(!loaded) return + else if(isscrewdriver(W)) + if(!loaded) return to_chat(user, "You loosen the securing screws on the side, allowing you to lower the guiding edge and retrieve the wires.") - while(loaded.amount>30) //There are only two kinds of situations: "nodiff" (60,90), or "diff" (31-59, 61-89) - var/diff = loaded.amount % 30 - if(diff) - loaded.use(diff) - getFromPool(/obj/item/stack/cable_coil,user.loc,diff) - else - loaded.use(30) - getFromPool(/obj/item/stack/cable_coil,user.loc,30) - loaded.max_amount = initial(loaded.max_amount) - loaded.loc = user.loc - user.put_in_hands(loaded) - loaded = null - update_icon() - else - ..() - -/obj/item/weapon/rcl/examine(mob/user) - ..() - if(loaded) + while(loaded.amount>30) //There are only two kinds of situations: "nodiff" (60,90), or "diff" (31-59, 61-89) + var/diff = loaded.amount % 30 + if(diff) + loaded.use(diff) + getFromPool(/obj/item/stack/cable_coil,user.loc,diff) + else + loaded.use(30) + getFromPool(/obj/item/stack/cable_coil,user.loc,30) + loaded.max_amount = initial(loaded.max_amount) + loaded.loc = user.loc + user.put_in_hands(loaded) + loaded = null + update_icon() + else + ..() + +/obj/item/weapon/rcl/examine(mob/user) + ..() + if(loaded) to_chat(user, "It contains [loaded.amount]/90 cables.") - -/obj/item/weapon/rcl/Destroy() - qdel(loaded) - loaded = null - last = null - ..() - -/obj/item/weapon/rcl/update_icon() - if(!loaded) - icon_state = "rcl-0" - item_state = "rcl-0" - return - switch(loaded.amount) - if(61 to INFINITY) - icon_state = "rcl-30" - item_state = "rcl" - if(31 to 60) - icon_state = "rcl-20" - item_state = "rcl" - if(1 to 30) - icon_state = "rcl-10" - item_state = "rcl" - else - icon_state = "rcl-0" - item_state = "rcl-0" - -/obj/item/weapon/rcl/proc/is_empty(mob/user) - update_icon() - if(!loaded.amount) + +/obj/item/weapon/rcl/Destroy() + qdel(loaded) + loaded = null + last = null + ..() + +/obj/item/weapon/rcl/update_icon() + if(!loaded) + icon_state = "rcl-0" + item_state = "rcl-0" + return + switch(loaded.amount) + if(61 to INFINITY) + icon_state = "rcl-30" + item_state = "rcl" + if(31 to 60) + icon_state = "rcl-20" + item_state = "rcl" + if(1 to 30) + icon_state = "rcl-10" + item_state = "rcl" + else + icon_state = "rcl-0" + item_state = "rcl-0" + +/obj/item/weapon/rcl/proc/is_empty(mob/user) + update_icon() + if(!loaded.amount) to_chat(user, "The last of the cables unreel from \the [src].") - returnToPool(loaded) - loaded = null - return 1 - return 0 - -/obj/item/weapon/rcl/dropped(mob/wearer as mob) - ..() - active = 0 - -/obj/item/weapon/rcl/attack_self(mob/user as mob) - active = !active + returnToPool(loaded) + loaded = null + return 1 + return 0 + +/obj/item/weapon/rcl/dropped(mob/wearer as mob) + ..() + active = 0 + +/obj/item/weapon/rcl/attack_self(mob/user as mob) + active = !active to_chat(user, "You turn the [src] [active ? "on" : "off"].") - if(active) - trigger(user) - -/obj/item/weapon/rcl/proc/trigger(mob/user as mob) - if(!loaded) + if(active) + trigger(user) + +/obj/item/weapon/rcl/proc/trigger(mob/user as mob) + if(!loaded) to_chat(user, "\The [src] is empty!") - return - if(last) - if(get_dist(last, user) == 0) //hacky, but it works - last = null - else if(get_dist(last, user) == 1) - if(get_dir(last, user)==last.d2) - //Did we just walk backwards? Well, that's the one direction we CAN'T complete a stub. - last = null - return - loaded.cable_join(last,user) - if(is_empty(user)) return //If we've run out, display message and exit - else - last = null - last = loaded.turf_place(get_turf(src.loc),user,turn(user.dir,180)) - is_empty(user) //If we've run out, display message + return + if(last) + if(get_dist(last, user) == 0) //hacky, but it works + last = null + else if(get_dist(last, user) == 1) + if(get_dir(last, user)==last.d2) + //Did we just walk backwards? Well, that's the one direction we CAN'T complete a stub. + last = null + return + loaded.cable_join(last,user) + if(is_empty(user)) return //If we've run out, display message and exit + else + last = null + last = loaded.turf_place(get_turf(src.loc),user,turn(user.dir,180)) + is_empty(user) //If we've run out, display message diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index c14a56cc481..b5e9e80c4e9 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -1,590 +1,590 @@ -/* Cards - * Contains: - * DATA CARD - * ID CARD - * FINGERPRINT CARD HOLDER - * FINGERPRINT CARD - */ - - - -/* - * DATA CARDS - Used for the teleporter - */ -/obj/item/weapon/card - name = "card" - desc = "Does card things." - icon = 'icons/obj/card.dmi' - w_class = 1.0 - var/associated_account_number = 0 - - var/list/files = list( ) - -/obj/item/weapon/card/data - name = "data disk" - desc = "A disk of data." - icon_state = "data" - var/function = "storage" - var/data = "null" - var/special = null - item_state = "card-id" - -/obj/item/weapon/card/data/verb/label(t as text) - set name = "Label Disk" - set category = "Object" - set src in usr - - if (t) - src.name = text("Data Disk- '[]'", t) - else - src.name = "Data Disk" - src.add_fingerprint(usr) - return - -/obj/item/weapon/card/data/clown - name = "Coordinates to Clown Planet" - icon_state = "data" - item_state = "card-id" - layer = 3 - level = 2 - desc = "This card contains coordinates to the fabled Clown Planet. Handle with care." - function = "teleporter" - data = "Clown Planet" - -/* - * ID CARDS - */ -/obj/item/weapon/card/emag - desc = "It's a card with a magnetic strip attached to some circuitry." - name = "cryptographic sequencer" - icon_state = "emag" - item_state = "card-id" - origin_tech = "magnets=2;syndicate=2" - - /** - * Number of uses left. -1 = infinite - * (Note: Some devices can use more than 1 use, so this is just called "energy") - * @since 10-28-2014 - */ - var/energy = -1 - - /** - * Max energy per emag. -1 = infinite - * @since 10-28-2014 - */ - var/max_energy = -1 - - /** - * Every X ticks, add [recharge_rate] energy. - * @since 10-28-2014 - */ - var/recharge_ticks = 0 - - /** - * Every [recharge_ticks] ticks, add X energy. - * @since 10-28-2014 - */ - var/recharge_rate = 0 - - var/nticks=0 - -/obj/item/weapon/card/emag/New(var/loc, var/disable_tuning=0) - ..(loc) - - // For standardized subtypes, once they're established. - if(disable_tuning) - return - - // Tuning tools. - ////////////////// - if(config.emag_energy != -1) - max_energy = config.emag_energy - - if(config.emag_starts_charged) - energy = max_energy - - if(config.emag_recharge_rate != 0) - recharge_rate = config.emag_recharge_rate - - if(config.emag_recharge_ticks > 0) - recharge_ticks = config.emag_recharge_ticks - -/obj/item/weapon/card/emag/process() - if(loc && loc:timestopped) return - if(energy < max_energy) - // Specified number of ticks has passed? Add charge. - if(nticks >= recharge_ticks) - nticks = 0 - energy = min(energy + recharge_rate, max_energy) - nticks ++ - else - nticks = 0 - processing_objects.Remove(src) - -/obj/item/weapon/card/emag/proc/canUse(var/mob/user, var/obj/machinery/M) - // We've already checked for emaggability. All we do here is check cost. - - // Infinite uses? Just return true. - if(energy < 0) - return 1 - - var/cost=M.getEmagCost(user,src) - - // Free to emag? Return true every time. - if(cost == 0) - return 1 - - if(energy >= cost) - energy -= cost - - // Start recharging, if we're supposed to. - if(energy < max_energy && recharge_rate && recharge_ticks) - if(!(src in processing_objects)) - processing_objects.Add(src) - - return 1 - - return 0 - -/obj/item/weapon/card/emag/examine(mob/user) - ..() - if(energy==-1) +/* Cards + * Contains: + * DATA CARD + * ID CARD + * FINGERPRINT CARD HOLDER + * FINGERPRINT CARD + */ + + + +/* + * DATA CARDS - Used for the teleporter + */ +/obj/item/weapon/card + name = "card" + desc = "Does card things." + icon = 'icons/obj/card.dmi' + w_class = 1.0 + var/associated_account_number = 0 + + var/list/files = list( ) + +/obj/item/weapon/card/data + name = "data disk" + desc = "A disk of data." + icon_state = "data" + var/function = "storage" + var/data = "null" + var/special = null + item_state = "card-id" + +/obj/item/weapon/card/data/verb/label(t as text) + set name = "Label Disk" + set category = "Object" + set src in usr + + if (t) + src.name = text("Data Disk- '[]'", t) + else + src.name = "Data Disk" + src.add_fingerprint(usr) + return + +/obj/item/weapon/card/data/clown + name = "Coordinates to Clown Planet" + icon_state = "data" + item_state = "card-id" + layer = 3 + level = 2 + desc = "This card contains coordinates to the fabled Clown Planet. Handle with care." + function = "teleporter" + data = "Clown Planet" + +/* + * ID CARDS + */ +/obj/item/weapon/card/emag + desc = "It's a card with a magnetic strip attached to some circuitry." + name = "cryptographic sequencer" + icon_state = "emag" + item_state = "card-id" + origin_tech = "magnets=2;syndicate=2" + + /** + * Number of uses left. -1 = infinite + * (Note: Some devices can use more than 1 use, so this is just called "energy") + * @since 10-28-2014 + */ + var/energy = -1 + + /** + * Max energy per emag. -1 = infinite + * @since 10-28-2014 + */ + var/max_energy = -1 + + /** + * Every X ticks, add [recharge_rate] energy. + * @since 10-28-2014 + */ + var/recharge_ticks = 0 + + /** + * Every [recharge_ticks] ticks, add X energy. + * @since 10-28-2014 + */ + var/recharge_rate = 0 + + var/nticks=0 + +/obj/item/weapon/card/emag/New(var/loc, var/disable_tuning=0) + ..(loc) + + // For standardized subtypes, once they're established. + if(disable_tuning) + return + + // Tuning tools. + ////////////////// + if(config.emag_energy != -1) + max_energy = config.emag_energy + + if(config.emag_starts_charged) + energy = max_energy + + if(config.emag_recharge_rate != 0) + recharge_rate = config.emag_recharge_rate + + if(config.emag_recharge_ticks > 0) + recharge_ticks = config.emag_recharge_ticks + +/obj/item/weapon/card/emag/process() + if(loc && loc:timestopped) return + if(energy < max_energy) + // Specified number of ticks has passed? Add charge. + if(nticks >= recharge_ticks) + nticks = 0 + energy = min(energy + recharge_rate, max_energy) + nticks ++ + else + nticks = 0 + processing_objects.Remove(src) + +/obj/item/weapon/card/emag/proc/canUse(var/mob/user, var/obj/machinery/M) + // We've already checked for emaggability. All we do here is check cost. + + // Infinite uses? Just return true. + if(energy < 0) + return 1 + + var/cost=M.getEmagCost(user,src) + + // Free to emag? Return true every time. + if(cost == 0) + return 1 + + if(energy >= cost) + energy -= cost + + // Start recharging, if we're supposed to. + if(energy < max_energy && recharge_rate && recharge_ticks) + if(!(src in processing_objects)) + processing_objects.Add(src) + + return 1 + + return 0 + +/obj/item/weapon/card/emag/examine(mob/user) + ..() + if(energy==-1) to_chat(user, "\The [name] has a tiny fusion generator for power.") - else - var/class="info" - if(energy/max_energy < 0.1 /* 10% energy left */) - class="warning" + else + var/class="info" + if(energy/max_energy < 0.1 /* 10% energy left */) + class="warning" to_chat(user, "This [name] has [energy]MJ left in its capacitor ([max_energy]MJ capacity).") - if(recharge_rate && recharge_ticks) + if(recharge_rate && recharge_ticks) to_chat(user, "A small label on a thermocouple notes that it recharges at a rate of [recharge_rate]MJ for every [recharge_ticks<=1?"":"[recharge_ticks] "]oscillator tick[recharge_ticks>1?"s":""].") - -/obj/item/weapon/card/emag/attack() - return - -/obj/item/weapon/card/emag/afterattack(atom/target, mob/user, proximity) - var/atom/A = target - if(!proximity) return - A.emag_act(user) - -/obj/item/weapon/card/id - name = "identification card" - desc = "A card used to provide ID and determine access across the station. Features a virtual wallet accessible by PDA." - icon_state = "id" - item_state = "card-id" - var/list/access = list() - var/registered_name = "Unknown" // The name registered_name on the card - slot_flags = SLOT_ID - - var/blood_type = "\[UNSET\]" - var/dna_hash = "\[UNSET\]" - var/fingerprint_hash = "\[UNSET\]" - var/bans = null - //alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system - var/assignment = null //can be alt title or the actual job - var/rank = null //actual job - var/dorm = 0 // determines if this ID has claimed a dorm already - - var/datum/money_account/virtual_wallet = null //money! - -/obj/item/weapon/card/id/New() - ..() - update_virtual_wallet() - spawn(30) //AWFULNESS AHOY - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - SetOwnerInfo(H) - update_virtual_wallet() - -/obj/item/weapon/card/id/examine(mob/user) - ..() - - if(Adjacent(user)) - user.show_message(text("The current assignment on the card is [src.assignment]."),1) - user.show_message("The blood type on the card is [blood_type].",1) - user.show_message("The DNA hash on the card is [dna_hash].",1) - user.show_message("The fingerprint hash on the card is [fingerprint_hash].",1) - -/obj/item/weapon/card/id/attack_self(mob/user as mob) - user.visible_message("[user] shows you: \icon[src] [src.name]: assignment: [src.assignment]",\ - "You flash your ID card: \icon[src] [src.name]: assignment: [src.assignment]") - src.add_fingerprint(user) - return - -/obj/item/weapon/card/id/GetAccess() - return access - -/obj/item/weapon/card/id/GetID() - return src - -/obj/item/weapon/card/id/proc/update_virtual_wallet(var/new_funds=0) - if(!virtual_wallet) - virtual_wallet = new() - virtual_wallet.virtual = 1 - - virtual_wallet.owner_name = registered_name - - if(new_funds) - virtual_wallet.money = new_funds - - //Virtual wallet accounts are tied to an ID card, not an account database, thus they don't need an acount number. - //For now using the virtual wallet doesn't require a PIN either. - - if(!virtual_wallet.account_number) - virtual_wallet.account_number = next_account_number - next_account_number += rand(1,25) - -/obj/item/weapon/card/id/proc/UpdateName() - name = "[src.registered_name]'s ID Card ([src.assignment])" - -/obj/item/weapon/card/id/proc/SetOwnerInfo(var/mob/living/carbon/human/H) - if(!H || !H.dna) return - - blood_type = H.dna.b_type - dna_hash = H.dna.unique_enzymes - fingerprint_hash = md5(H.dna.uni_identity) - -/obj/item/weapon/card/id/proc/GetBalance(var/format=0) - var/amt = 0 - var/datum/money_account/acct = get_card_account(src) - if(acct) - amt = acct.money - if(format) - amt = "$[num2septext(amt)]" - return amt - -/obj/item/weapon/card/id/proc/GetJobName() - var/jobName = src.assignment //what the card's job is called - var/alt_jobName = src.rank //what the card's job ACTUALLY IS: determines access, etc. - - if(jobName in get_all_job_icons()) //Check if the job name has a hud icon - return jobName - if(alt_jobName in get_all_job_icons()) //Check if the base job has a hud icon - return alt_jobName - if(jobName in get_all_centcom_jobs() || alt_jobName in get_all_centcom_jobs()) //Return with the NT logo if it is a Centcom job - return "Centcom" - return "Unknown" //Return unknown if none of the above apply - -/obj/item/weapon/card/id/proc/GetJobRealName() - if( rank in get_all_jobs() ) - return rank - - if( assignment in get_all_jobs() ) - return assignment - - return "Unknown" - -// vgedit: We have different wallets. -/* -/obj/item/weapon/card/id/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(istype(W,/obj/item/weapon/id_wallet)) + +/obj/item/weapon/card/emag/attack() + return + +/obj/item/weapon/card/emag/afterattack(atom/target, mob/user, proximity) + var/atom/A = target + if(!proximity) return + A.emag_act(user) + +/obj/item/weapon/card/id + name = "identification card" + desc = "A card used to provide ID and determine access across the station. Features a virtual wallet accessible by PDA." + icon_state = "id" + item_state = "card-id" + var/list/access = list() + var/registered_name = "Unknown" // The name registered_name on the card + slot_flags = SLOT_ID + + var/blood_type = "\[UNSET\]" + var/dna_hash = "\[UNSET\]" + var/fingerprint_hash = "\[UNSET\]" + var/bans = null + //alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system + var/assignment = null //can be alt title or the actual job + var/rank = null //actual job + var/dorm = 0 // determines if this ID has claimed a dorm already + + var/datum/money_account/virtual_wallet = null //money! + +/obj/item/weapon/card/id/New() + ..() + update_virtual_wallet() + spawn(30) //AWFULNESS AHOY + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + SetOwnerInfo(H) + update_virtual_wallet() + +/obj/item/weapon/card/id/examine(mob/user) + ..() + + if(Adjacent(user)) + user.show_message(text("The current assignment on the card is [src.assignment]."),1) + user.show_message("The blood type on the card is [blood_type].",1) + user.show_message("The DNA hash on the card is [dna_hash].",1) + user.show_message("The fingerprint hash on the card is [fingerprint_hash].",1) + +/obj/item/weapon/card/id/attack_self(mob/user as mob) + user.visible_message("[user] shows you: \icon[src] [src.name]: assignment: [src.assignment]",\ + "You flash your ID card: \icon[src] [src.name]: assignment: [src.assignment]") + src.add_fingerprint(user) + return + +/obj/item/weapon/card/id/GetAccess() + return access + +/obj/item/weapon/card/id/GetID() + return src + +/obj/item/weapon/card/id/proc/update_virtual_wallet(var/new_funds=0) + if(!virtual_wallet) + virtual_wallet = new() + virtual_wallet.virtual = 1 + + virtual_wallet.owner_name = registered_name + + if(new_funds) + virtual_wallet.money = new_funds + + //Virtual wallet accounts are tied to an ID card, not an account database, thus they don't need an acount number. + //For now using the virtual wallet doesn't require a PIN either. + + if(!virtual_wallet.account_number) + virtual_wallet.account_number = next_account_number + next_account_number += rand(1,25) + +/obj/item/weapon/card/id/proc/UpdateName() + name = "[src.registered_name]'s ID Card ([src.assignment])" + +/obj/item/weapon/card/id/proc/SetOwnerInfo(var/mob/living/carbon/human/H) + if(!H || !H.dna) return + + blood_type = H.dna.b_type + dna_hash = H.dna.unique_enzymes + fingerprint_hash = md5(H.dna.uni_identity) + +/obj/item/weapon/card/id/proc/GetBalance(var/format=0) + var/amt = 0 + var/datum/money_account/acct = get_card_account(src) + if(acct) + amt = acct.money + if(format) + amt = "$[num2septext(amt)]" + return amt + +/obj/item/weapon/card/id/proc/GetJobName() + var/jobName = src.assignment //what the card's job is called + var/alt_jobName = src.rank //what the card's job ACTUALLY IS: determines access, etc. + + if(jobName in get_all_job_icons()) //Check if the job name has a hud icon + return jobName + if(alt_jobName in get_all_job_icons()) //Check if the base job has a hud icon + return alt_jobName + if(jobName in get_all_centcom_jobs() || alt_jobName in get_all_centcom_jobs()) //Return with the NT logo if it is a Centcom job + return "Centcom" + return "Unknown" //Return unknown if none of the above apply + +/obj/item/weapon/card/id/proc/GetJobRealName() + if( rank in get_all_jobs() ) + return rank + + if( assignment in get_all_jobs() ) + return assignment + + return "Unknown" + +// vgedit: We have different wallets. +/* +/obj/item/weapon/card/id/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(istype(W,/obj/item/weapon/id_wallet)) to_chat(user, "You slip [src] into [W].") - src.name = "[src.registered_name]'s [W.name] ([src.assignment])" - src.desc = W.desc - src.icon = W.icon - src.icon_state = W.icon_state - del(W) - return -*/ - -/obj/item/weapon/card/id/silver - name = "identification card" - desc = "A silver card which shows honour and dedication." - icon_state = "silver" - item_state = "silver_id" - -/obj/item/weapon/card/id/gold - name = "identification card" - desc = "A golden card which shows power and might." - icon_state = "gold" - item_state = "gold_id" - -/obj/item/weapon/card/id/syndicate - name = "agent card" - access = list(access_maint_tunnels, access_syndicate, access_external_airlocks) - origin_tech = "syndicate=3" - var/registered_user=null - -/obj/item/weapon/card/id/syndicate/afterattack(var/obj/item/weapon/O as obj, mob/user as mob) - if(istype(O, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/I = O + src.name = "[src.registered_name]'s [W.name] ([src.assignment])" + src.desc = W.desc + src.icon = W.icon + src.icon_state = W.icon_state + del(W) + return +*/ + +/obj/item/weapon/card/id/silver + name = "identification card" + desc = "A silver card which shows honour and dedication." + icon_state = "silver" + item_state = "silver_id" + +/obj/item/weapon/card/id/gold + name = "identification card" + desc = "A golden card which shows power and might." + icon_state = "gold" + item_state = "gold_id" + +/obj/item/weapon/card/id/syndicate + name = "agent card" + access = list(access_maint_tunnels, access_syndicate, access_external_airlocks) + origin_tech = "syndicate=3" + var/registered_user=null + +/obj/item/weapon/card/id/syndicate/afterattack(var/obj/item/weapon/O as obj, mob/user as mob) + if(istype(O, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I = O to_chat(user, "The [src]'s microscanners activate as you pass it over \the [I], copying its access.") - access |= I.access - -/obj/item/weapon/card/id/syndicate/attack_self(mob/user as mob) - if(!src.registered_name) - //Stop giving the players unsanitized unputs! You are giving ways for players to intentionally crash clients! -Nodrak - var t = reject_bad_name(input(user, "What name would you like to put on this card?", "Agent card name", ishuman(user) ? user.real_name : user.name)) - if(!t) //Same as mob/new_player/prefrences.dm - alert("Invalid name.") - return - src.registered_name = t - - var u = sanitize(stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Agent", MAX_MESSAGE_LEN)) - if(!u) - alert("Invalid assignment.") - src.registered_name = "" - return - src.assignment = u - src.name = "[src.registered_name]'s ID Card ([src.assignment])" + access |= I.access + +/obj/item/weapon/card/id/syndicate/attack_self(mob/user as mob) + if(!src.registered_name) + //Stop giving the players unsanitized unputs! You are giving ways for players to intentionally crash clients! -Nodrak + var t = reject_bad_name(input(user, "What name would you like to put on this card?", "Agent card name", ishuman(user) ? user.real_name : user.name)) + if(!t) //Same as mob/new_player/prefrences.dm + alert("Invalid name.") + return + src.registered_name = t + + var u = sanitize(stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Agent", MAX_MESSAGE_LEN)) + if(!u) + alert("Invalid assignment.") + src.registered_name = "" + return + src.assignment = u + src.name = "[src.registered_name]'s ID Card ([src.assignment])" to_chat(user, "You successfully forge the ID card.") - registered_user = user - else if(!registered_user || registered_user == user) - - if(!registered_user) registered_user = user // - - switch(alert(user,"Would you like to display \the [src] or edit it?","Choose.","Show","Edit")) - if("Show") - return ..() - if("Edit") - switch(input(user,"What would you like to edit on \the [src]?") in list("Name","Appearance","Occupation","Money account","Blood type","DNA hash","Fingerprint hash","Reset card")) - if("Name") - var/new_name = reject_bad_name(input(user,"What name would you like to put on this card?","Agent card name", ishuman(user) ? user.real_name : user.name)) - if(!Adjacent(user)) return - - src.registered_name = new_name - UpdateName() + registered_user = user + else if(!registered_user || registered_user == user) + + if(!registered_user) registered_user = user // + + switch(alert(user,"Would you like to display \the [src] or edit it?","Choose.","Show","Edit")) + if("Show") + return ..() + if("Edit") + switch(input(user,"What would you like to edit on \the [src]?") in list("Name","Appearance","Occupation","Money account","Blood type","DNA hash","Fingerprint hash","Reset card")) + if("Name") + var/new_name = reject_bad_name(input(user,"What name would you like to put on this card?","Agent card name", ishuman(user) ? user.real_name : user.name)) + if(!Adjacent(user)) return + + src.registered_name = new_name + UpdateName() to_chat(user, "Name changed to [new_name].") - - if("Appearance") - var/list/appearances = list( - "data", - "id", - "gold", - "silver", - "centcom_old", - "centcom", - "security", - "medical", - "HoS", - "research", - "engineering", - "CMO", - "RD", - "CE", - "clown", - "mime", - "syndie", - "deathsquad", - "creed", - "ERT_leader", - "ERT_security", - "ERT_engineering", - "ERT_medical", - ) - var/choice = input(user, "Select the appearance for this card.", "Choose.") in appearances - if(!Adjacent(user)) - return - if(!choice) - return - src.icon_state = choice + + if("Appearance") + var/list/appearances = list( + "data", + "id", + "gold", + "silver", + "centcom_old", + "centcom", + "security", + "medical", + "HoS", + "research", + "engineering", + "CMO", + "RD", + "CE", + "clown", + "mime", + "syndie", + "deathsquad", + "creed", + "ERT_leader", + "ERT_security", + "ERT_engineering", + "ERT_medical", + ) + var/choice = input(user, "Select the appearance for this card.", "Choose.") in appearances + if(!Adjacent(user)) + return + if(!choice) + return + src.icon_state = choice to_chat(usr, "Appearance changed to [choice].") - - if("Occupation") - var/new_job = sanitize(stripped_input(user,"What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent card occupation", "Assistant", MAX_MESSAGE_LEN)) - if(!Adjacent(user)) return - src.assignment = new_job + + if("Occupation") + var/new_job = sanitize(stripped_input(user,"What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent card occupation", "Assistant", MAX_MESSAGE_LEN)) + if(!Adjacent(user)) return + src.assignment = new_job to_chat(user, "Occupation changed to [new_job].") - UpdateName() - - if("Money account") - var/new_account = input(user,"What money account would you like to link to this card?","Agent card account",11111) as num - if(!Adjacent(user)) return - associated_account_number = new_account + UpdateName() + + if("Money account") + var/new_account = input(user,"What money account would you like to link to this card?","Agent card account",11111) as num + if(!Adjacent(user)) return + associated_account_number = new_account to_chat(user, "Linked money account changed to [new_account].") - - if("Blood type") - var/default = "\[UNSET\]" - if(ishuman(user)) - var/mob/living/carbon/human/H = user - - if(H.dna) - default = H.dna.b_type - - var/new_blood_type = sanitize(input(user,"What blood type would you like to be written on this card?","Agent card blood type",default) as text) - if(!Adjacent(user)) return - src.blood_type = new_blood_type + + if("Blood type") + var/default = "\[UNSET\]" + if(ishuman(user)) + var/mob/living/carbon/human/H = user + + if(H.dna) + default = H.dna.b_type + + var/new_blood_type = sanitize(input(user,"What blood type would you like to be written on this card?","Agent card blood type",default) as text) + if(!Adjacent(user)) return + src.blood_type = new_blood_type to_chat(user, "Blood type changed to [new_blood_type].") - - if("DNA hash") - var/default = "\[UNSET\]" - if(ishuman(user)) - var/mob/living/carbon/human/H = user - - if(H.dna) - default = H.dna.unique_enzymes - - var/new_dna_hash = sanitize(input(user,"What DNA hash would you like to be written on this card?","Agent card DNA hash",default) as text) - if(!Adjacent(user)) return - src.dna_hash = new_dna_hash + + if("DNA hash") + var/default = "\[UNSET\]" + if(ishuman(user)) + var/mob/living/carbon/human/H = user + + if(H.dna) + default = H.dna.unique_enzymes + + var/new_dna_hash = sanitize(input(user,"What DNA hash would you like to be written on this card?","Agent card DNA hash",default) as text) + if(!Adjacent(user)) return + src.dna_hash = new_dna_hash to_chat(user, "DNA hash changed to [new_dna_hash].") - - if("Fingerprint hash") - var/default = "\[UNSET\]" - if(ishuman(user)) - var/mob/living/carbon/human/H = user - - if(H.dna) - default = md5(H.dna.uni_identity) - - var/new_fingerprint_hash = sanitize(input(user,"What fingerprint hash would you like to be written on this card?","Agent card fingerprint hash",default) as text) - if(!Adjacent(user)) return - src.fingerprint_hash = new_fingerprint_hash + + if("Fingerprint hash") + var/default = "\[UNSET\]" + if(ishuman(user)) + var/mob/living/carbon/human/H = user + + if(H.dna) + default = md5(H.dna.uni_identity) + + var/new_fingerprint_hash = sanitize(input(user,"What fingerprint hash would you like to be written on this card?","Agent card fingerprint hash",default) as text) + if(!Adjacent(user)) return + src.fingerprint_hash = new_fingerprint_hash to_chat(user, "Fingerprint hash changed to [new_fingerprint_hash].") - - if("Reset card") - name = initial(name) - registered_name = initial(registered_name) - icon_state = initial(icon_state) - assignment = initial(assignment) - associated_account_number = initial(associated_account_number) - blood_type = initial(blood_type) - dna_hash = initial(dna_hash) - fingerprint_hash = initial(fingerprint_hash) - access = initial(access) - registered_user = null - + + if("Reset card") + name = initial(name) + registered_name = initial(registered_name) + icon_state = initial(icon_state) + assignment = initial(assignment) + associated_account_number = initial(associated_account_number) + blood_type = initial(blood_type) + dna_hash = initial(dna_hash) + fingerprint_hash = initial(fingerprint_hash) + access = initial(access) + registered_user = null + to_chat(user, "All information has been deleted from \the [src].") - else - ..() - -/obj/item/weapon/card/id/syndicate_command - name = "syndicate ID card" - desc = "An ID straight from the Syndicate." - registered_name = "Syndicate" - icon_state = "syndie" - assignment = "Syndicate Overlord" - access = list(access_syndicate, access_external_airlocks) - -/obj/item/weapon/card/id/captains_spare - name = "captain's spare ID" - desc = "The spare ID of the High Lord himself." - icon_state = "gold" - item_state = "gold_id" - registered_name = "Captain" - assignment = "Captain" - -/obj/item/weapon/card/id/captains_spare/New() - var/datum/job/captain/J = new/datum/job/captain - access = J.get_access() - ..() - -/obj/item/weapon/card/id/admin - name = "Admin ID" - icon_state = "admin" - item_state = "gold_id" - registered_name = "Admin" - assignment = "Testing Shit" - -/obj/item/weapon/card/id/admin/New() - access = get_absolutely_all_accesses() - ..() - -/obj/item/weapon/card/id/centcom - name = "\improper CentCom. ID" - desc = "An ID awarded only to the best brown nosers." - icon_state = "centcom" - registered_name = "Central Command" - assignment = "General" - -/obj/item/weapon/card/id/centcom/New() - access = get_all_centcom_access() - ..() - -/obj/item/weapon/card/id/salvage_captain - name = "Captain's ID" - registered_name = "Captain" - icon_state = "centcom" - desc = "Finders, keepers." - access = list(access_salvage_captain) - -/obj/item/weapon/card/id/medical - name = "Medical ID" - registered_name = "Medic" - icon_state = "medical" - desc = "A card covered in the blood stains of the wild ride." - access = list(access_medical, access_genetics, access_morgue, access_chemistry, access_paramedic, access_virology, access_surgery, access_cmo) - -/obj/item/weapon/card/id/security - name = "Security ID" - registered_name = "Officer" - icon_state = "security" - desc = "Some say these cards are drowned in the tears of assistants, forged in the burning bodies of clowns." - access = list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos) - -/obj/item/weapon/card/id/research - name = "Research ID" - registered_name = "Scientist" - icon_state = "research" - desc = "Pinnacle of name technology." - access = list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_rd) - -/obj/item/weapon/card/id/supply - name = "Supply ID" - registered_name = "Cargonian" - icon_state = "cargo" - desc = "ROH ROH! HEIL THE QUARTERMASTER!" - access = list(access_mailsorting, access_mining, access_mining_station, access_cargo, access_qm, access_taxi) - -/obj/item/weapon/card/id/engineering - name = "Engineering ID" - registered_name = "Engineer" - icon_state = "engineering" - desc = "Shame it's going to be lost in the void of a black hole." - access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_construction) - -/obj/item/weapon/card/id/hos - name = "Head of Security ID" - registered_name = "HoS" - icon_state = "HoS" - desc = "An ID awarded to only the most robust shits in the buisness." - access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway) - -/obj/item/weapon/card/id/cmo - name = "Chief Medical Officer ID" - registered_name = "CMO" - icon_state = "CMO" - desc = "It gives off the faint smell of chloral, mixed with a backdraft of shittery." - access = list(access_medical, access_morgue, access_genetics, access_heads, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_keycard_auth, access_sec_doors, access_paramedic, access_maint_tunnels) - -/obj/item/weapon/card/id/rd - name = "Research Director ID" - registered_name = "RD" - icon_state = "RD" - desc = "If you put your ear to the card, you can faintly hear screaming, glomping, and mechs. What the fuck." - access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway) - -/obj/item/weapon/card/id/ce - name = "Chief Engineer ID" - registered_name = "CE" - icon_state = "CE" - desc = "The card has a faint aroma of autism." - access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_heads, access_construction, access_sec_doors, access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) - -/obj/item/weapon/card/id/clown - name = "Pink ID" - registered_name = "HONK!" - icon_state = "clown" - desc = "Even looking at the card strikes you with deep fear." - access = list(access_clown, access_theatre, access_maint_tunnels) - -/obj/item/weapon/card/id/mime - name = "Black and White ID" - registered_name = "..." - icon_state = "mime" - desc = "..." - access = list(access_clown, access_theatre, access_maint_tunnels) - -/obj/item/weapon/card/id/thunderdome/red - name = "Thunderdome Red ID" - registered_name = "Red Team Fighter" - assignment = "Red Team Fighter" - icon_state = "TDred" - desc = "This ID card is given to those who fought inside the thunderdome for the Red Team. Not many have lived to see one of those, even fewer lived to keep it." - -/obj/item/weapon/card/id/thunderdome/green - name = "Thunderdome Green ID" - registered_name = "Green Team Fighter" - assignment = "Green Team Fighter" - icon_state = "TDgreen" - desc = "This ID card is given to those who fought inside the thunderdome for the Green Team. Not many have lived to see one of those, even fewer lived to keep it." + else + ..() + +/obj/item/weapon/card/id/syndicate_command + name = "syndicate ID card" + desc = "An ID straight from the Syndicate." + registered_name = "Syndicate" + icon_state = "syndie" + assignment = "Syndicate Overlord" + access = list(access_syndicate, access_external_airlocks) + +/obj/item/weapon/card/id/captains_spare + name = "captain's spare ID" + desc = "The spare ID of the High Lord himself." + icon_state = "gold" + item_state = "gold_id" + registered_name = "Captain" + assignment = "Captain" + +/obj/item/weapon/card/id/captains_spare/New() + var/datum/job/captain/J = new/datum/job/captain + access = J.get_access() + ..() + +/obj/item/weapon/card/id/admin + name = "Admin ID" + icon_state = "admin" + item_state = "gold_id" + registered_name = "Admin" + assignment = "Testing Shit" + +/obj/item/weapon/card/id/admin/New() + access = get_absolutely_all_accesses() + ..() + +/obj/item/weapon/card/id/centcom + name = "\improper CentCom. ID" + desc = "An ID awarded only to the best brown nosers." + icon_state = "centcom" + registered_name = "Central Command" + assignment = "General" + +/obj/item/weapon/card/id/centcom/New() + access = get_all_centcom_access() + ..() + +/obj/item/weapon/card/id/salvage_captain + name = "Captain's ID" + registered_name = "Captain" + icon_state = "centcom" + desc = "Finders, keepers." + access = list(access_salvage_captain) + +/obj/item/weapon/card/id/medical + name = "Medical ID" + registered_name = "Medic" + icon_state = "medical" + desc = "A card covered in the blood stains of the wild ride." + access = list(access_medical, access_genetics, access_morgue, access_chemistry, access_paramedic, access_virology, access_surgery, access_cmo) + +/obj/item/weapon/card/id/security + name = "Security ID" + registered_name = "Officer" + icon_state = "security" + desc = "Some say these cards are drowned in the tears of assistants, forged in the burning bodies of clowns." + access = list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos) + +/obj/item/weapon/card/id/research + name = "Research ID" + registered_name = "Scientist" + icon_state = "research" + desc = "Pinnacle of name technology." + access = list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_rd) + +/obj/item/weapon/card/id/supply + name = "Supply ID" + registered_name = "Cargonian" + icon_state = "cargo" + desc = "ROH ROH! HEIL THE QUARTERMASTER!" + access = list(access_mailsorting, access_mining, access_mining_station, access_cargo, access_qm, access_taxi) + +/obj/item/weapon/card/id/engineering + name = "Engineering ID" + registered_name = "Engineer" + icon_state = "engineering" + desc = "Shame it's going to be lost in the void of a black hole." + access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_construction) + +/obj/item/weapon/card/id/hos + name = "Head of Security ID" + registered_name = "HoS" + icon_state = "HoS" + desc = "An ID awarded to only the most robust shits in the buisness." + access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway) + +/obj/item/weapon/card/id/cmo + name = "Chief Medical Officer ID" + registered_name = "CMO" + icon_state = "CMO" + desc = "It gives off the faint smell of chloral, mixed with a backdraft of shittery." + access = list(access_medical, access_morgue, access_genetics, access_heads, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_keycard_auth, access_sec_doors, access_paramedic, access_maint_tunnels) + +/obj/item/weapon/card/id/rd + name = "Research Director ID" + registered_name = "RD" + icon_state = "RD" + desc = "If you put your ear to the card, you can faintly hear screaming, glomping, and mechs. What the fuck." + access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway) + +/obj/item/weapon/card/id/ce + name = "Chief Engineer ID" + registered_name = "CE" + icon_state = "CE" + desc = "The card has a faint aroma of autism." + access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_heads, access_construction, access_sec_doors, access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) + +/obj/item/weapon/card/id/clown + name = "Pink ID" + registered_name = "HONK!" + icon_state = "clown" + desc = "Even looking at the card strikes you with deep fear." + access = list(access_clown, access_theatre, access_maint_tunnels) + +/obj/item/weapon/card/id/mime + name = "Black and White ID" + registered_name = "..." + icon_state = "mime" + desc = "..." + access = list(access_clown, access_theatre, access_maint_tunnels) + +/obj/item/weapon/card/id/thunderdome/red + name = "Thunderdome Red ID" + registered_name = "Red Team Fighter" + assignment = "Red Team Fighter" + icon_state = "TDred" + desc = "This ID card is given to those who fought inside the thunderdome for the Red Team. Not many have lived to see one of those, even fewer lived to keep it." + +/obj/item/weapon/card/id/thunderdome/green + name = "Thunderdome Green ID" + registered_name = "Green Team Fighter" + assignment = "Green Team Fighter" + icon_state = "TDgreen" + desc = "This ID card is given to those who fought inside the thunderdome for the Green Team. Not many have lived to see one of those, even fewer lived to keep it." diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index ada303fb902..29967438c93 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -1,724 +1,724 @@ -//cleansed 9/15/2012 17:48 - -/* -CONTAINS: -MATCHES -CIGARETTES -CIGARS -SMOKING PIPES -CHEAP LIGHTERS -ZIPPO - -CIGARETTE PACKETS ARE IN FANCY.DM -MATCHBOXES ARE ALSO IN FANCY.DM -*/ - -/////////// -//MATCHES// -/////////// - -/obj/item/weapon/match - name = "match" - desc = "A budget match stick, used to start fires easily, preferably at the end of a smoke." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "match" - item_state = "cig" - var/lit = 0 - var/smoketime = 10 - var/brightness_on = 1 //Barely enough to see where you're standing, it's a shitty discount match - heat_production = 1000 - w_class = 1.0 - origin_tech = "materials=1" - attack_verb = list("burnt", "singed") - light_color = LIGHT_COLOR_FIRE - -/obj/item/weapon/match/New() - - ..() - update_brightness() //Useful if you want to spawn burnt matches, or burning ones you maniac - -/obj/item/weapon/match/examine(mob/user) - - ..() - switch(lit) - if(1) - to_chat(user, "The match is lit.") - if(0) - to_chat(user, "The match is unlit and ready to be used.") - if(-1) - to_chat(user, "The match is burnt.") - -//Also updates the name, the damage and item_state for good measure -/obj/item/weapon/match/update_icon() - - switch(lit) - if(1) - name = "lit [initial(name)]" - item_state = "[initial(item_state)]on" - icon_state = "[initial(icon_state)]_lit" - damtype = BURN - if(0) - name = "[initial(name)]" - item_state = "[initial(item_state)]off" - icon_state = "[initial(icon_state)]_unlit" - damtype = BRUTE - if(-1) - name = "burnt [initial(name)]" - item_state = "[initial(item_state)]off" - icon_state = "[initial(icon_state)]_burnt" - damtype = BRUTE - -/obj/item/weapon/match/proc/update_brightness() - - - if(lit == 1) //I wish I didn't need the == 1 part, but Dreamkamer is a dumb puppy - processing_objects.Add(src) - set_light(brightness_on) - else - processing_objects.Remove(src) - set_light(0) - update_icon() - -/obj/item/weapon/match/process() - var/turf/location = get_turf(src) - smoketime-- - if(smoketime <= 0) - lit = -1 - update_brightness() - return - if(location) - location.hotspot_expose(heat_production, 5, surfaces = istype(loc, /turf)) - return - -/obj/item/weapon/match/is_hot() - if(lit == 1) - return heat_production - return 0 - -/obj/item/weapon/match/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && user.zone_sel.selecting == "mouth" && lit == 1) - var/obj/item/clothing/mask/cigarette/cig = M.wear_mask - if(M == user) - cig.attackby(src, user) - else - cig.light("[user] holds \the [name] out for [M], and lights \his [cig.name].") - else - return ..() - -/* -/obj/item/weapon/match/attackby(obj/item/weapon/W as obj, mob/user as mob) - - if(W.is_hot()) - lit = 1 - update_brightness() - user.visible_message("[user] lights \the [src] with \the [W].", \ - "You light \the [src] with \the [W].") - ..() -*/ - -/obj/item/weapon/match/strike_anywhere - name = "strike-anywhere match" - desc = "An improved match stick, used to start fires easily, preferably at the end of a smoke. Can be lit against any surface" - -/obj/item/weapon/match/strike_anywhere/afterattack(atom/target, mob/user, prox_flags) - if(!prox_flags == 1) - return - - if(!(get_turf(src) == get_turf(user))) - return - - if(lit) - return - - if(istype(target, /obj) || istype(target, /turf)) - lit = 1 - update_brightness() - user.visible_message("[user] strikes \the [src] on \the [target].", \ - "You strike \the [src] on \the [target].") - -////////////////// -//FINE SMOKABLES// -////////////////// - -//Doubles as a mask entity, aka can be put to your mouth like a real cigarette -/obj/item/clothing/mask/cigarette - name = "cigarette" - desc = "A roll of tobacco and nicotine. Not the best thing to have on your face in the event of a plasma flood." - icon_state = "cig" - item_state = "cig" - w_class = 1 - body_parts_covered = null - attack_verb = list("burnt", "singed") - heat_production = 1000 - light_color = LIGHT_COLOR_FIRE - var/lit = 0 - var/overlay_on = "ciglit" //Apparently not used - var/type_butt = /obj/item/weapon/cigbutt - var/lastHolder = null - var/brightness_on = 1 //Barely enough to see where you're standing, it's a boring old cigarette - var/smoketime = 300 - var/chem_volume = 15 - -/obj/item/clothing/mask/cigarette/New() - ..() - flags |= NOREACT // so it doesn't react until you light it - create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15 - update_brightness() - -/obj/item/clothing/mask/cigarette/examine(mob/user) - - ..() - to_chat(user, "\The [src] is [lit ? "":"un"]lit.")//Shared with all cigarette sub-types - - -//Also updates the name, the damage and item_state for good measure -/obj/item/clothing/mask/cigarette/update_icon() - - switch(lit) - if(1) - name = "lit [initial(name)]" - item_state = "[initial(item_state)]on" - icon_state = "[initial(icon_state)]on" - damtype = BURN - if(0) - name = "[initial(name)]" - item_state = "[initial(item_state)]off" - icon_state = "[initial(icon_state)]off" - damtype = BRUTE - -/obj/item/clothing/mask/cigarette/proc/update_brightness() - - - if(lit) - processing_objects.Add(src) - set_light(brightness_on) - else - processing_objects.Remove(src) - set_light(0) - update_icon() - -/obj/item/clothing/mask/cigarette/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(lit) - return - light("The raging fire sets \the [src] alight.") - -/obj/item/clothing/mask/cigarette/is_hot() - if(lit) - return heat_production - return 0 - -/obj/item/clothing/mask/cigarette/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - - if(lit) //The cigarette is already lit - to_chat(user, "\The [src] is already lit.") - return //Don't bother - - //Items with special messages go first - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.is_hot()) //Badasses dont get blinded while lighting their cig with a welding tool - light("[user] casually lights \his [name] with \the [W], what a badass.") - - else if(istype(W, /obj/item/weapon/lighter/zippo)) - var/obj/item/weapon/lighter/zippo/Z = W - if(Z.is_hot()) - light("With a single flick of their wrist, [user] smoothly lights \his [name] with \the [W]. Damn, that's cool.") - - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.is_hot()) - light("After some fiddling, [user] manages to light \his [name] with \the [W].") - - else if(istype(W, /obj/item/weapon/melee/energy/sword)) - var/obj/item/weapon/melee/energy/sword/S = W - if(S.is_hot()) - light("[user] raises \his [W.name], lighting \the [src]. Holy fucking shit.") - - else if(istype(W, /obj/item/device/assembly/igniter)) - var/obj/item/device/assembly/igniter/I = W - if(I.is_hot()) - light("[user] fiddles with \his [W.name], and manages to light their [name].") - - //All other items are included here, any item that is hot can light the cigarette - else if(W.is_hot()) - light("[user] lights \his [name] with \the [W].") - return - - -/obj/item/clothing/mask/cigarette/afterattack(obj/item/weapon/reagent_containers/glass/glass, mob/user as mob) - ..() - if(istype(glass)) //You can dip cigarettes into beakers and beaker subtypes - if(glass.reagents.has_reagent("sacid") || glass.reagents.has_reagent("pacid")) //Dumping into acid, a dumb idea - new type_butt(get_turf(glass)) - processing_objects.Remove(src) - to_chat(user, "Half of \the [src] dissolves with a nasty fizzle as you dip it into \the [glass].") - user.drop_item(src, force_drop = 1) - qdel(src) - return - if(glass.reagents.has_reagent("water") && lit) //Dumping a lit cigarette into water, the result is obvious - new type_butt(get_turf(glass)) - processing_objects.Remove(src) - to_chat(user, "\The [src] fizzles as you dip it into \the [glass].") - user.drop_item(src, force_drop = 1) - qdel(src) - return - var/transfered = glass.reagents.trans_to(src, chem_volume) - if(transfered) //If reagents were transfered, show the message - to_chat(user, "You dip \the [src] into \the [glass].") - else //If not, either the beaker was empty, or the cigarette was full - if(!glass.reagents.total_volume) //Only show an explicit message if the beaker was empty, you can't tell a cigarette is "full" - to_chat(user, "\The [glass] is empty.") - return - -/obj/item/clothing/mask/cigarette/proc/light(var/flavor_text = "[usr] lights \the [src].") - if(lit) //Failsafe - return //"Normal" situations were already handled in attackby, don't show a message - - if(reagents.get_reagent_amount("water")) //The cigarette was dipped into water, it's useless now - to_chat(usr, "You fail to light \the [src]. It appears to be wet.") - return - - if(reagents.get_reagent_amount("plasma")) //Plasma explodes when exposed to fire - var/datum/effect/effect/system/reagents_explosion/e = new() - e.set_up(round(reagents.get_reagent_amount("plasma")/2.5, 1), get_turf(src), 0, 0) - e.start() - if(ismob(loc)) - var/mob/M = loc - M.drop_from_inventory(src) - qdel(src) - return - - if(reagents.get_reagent_amount("fuel")) //Fuel explodes, too, but much less violently - var/datum/effect/effect/system/reagents_explosion/e = new() - e.set_up(round(reagents.get_reagent_amount("fuel")/5, 1), get_turf(src), 0, 0) - e.start() - if(ismob(loc)) - var/mob/M = loc - M.drop_from_inventory(src) - qdel(src) - return - - lit = 1 //All checks that could have stopped the cigarette are done, let us begin - - flags &= ~NOREACT //Allow reagents to react after being lit - flags |= (MASKINTERNALS | BLOCK_GAS_SMOKE_EFFECT) - - reagents.handle_reactions() - //This ain't ready yet. - //overlays.len = 0 - //overlays += image('icons/mob/mask.dmi', overlay_on, LIGHTING_LAYER+1) - var/turf/T = get_turf(src) - T.visible_message(flavor_text) - - update_brightness() - - //can't think of any other way to update the overlays :< //Gee, thanks - if(ismob(loc)) - var/mob/M = loc - M.update_inv_wear_mask(0) - M.update_inv_l_hand(0) - M.update_inv_r_hand(1) - -/obj/item/clothing/mask/cigarette/process() - var/turf/location = get_turf(src) - var/mob/living/M = loc - if(isliving(loc)) - M.IgniteMob() - smoketime-- - if(smoketime <= 0) - new type_butt(location) //Spawn the cigarette butt - lit = 0 //Actually unlight the cigarette so that the lighting can update correctly - update_brightness() - if(ismob(loc)) - to_chat(M, "Your [name] goes out.") - M.u_equip(src, 0) //Un-equip it so the overlays can update - qdel(src) - return - if(location) - location.hotspot_expose(700, 5, surfaces = istype(loc, /turf)) - //Oddly specific and snowflakey reagent transfer system below - if(reagents && reagents.total_volume) //Check if it has any reagents at all - if(iscarbon(M) && (src == M.wear_mask)) //If it's in the human/monkey mouth, transfer reagents to the mob - if(M.reagents.has_reagent("lexorin") || M_NO_BREATH in M.mutations || istype(M.loc, /obj/machinery/atmospherics/unary/cryo_cell)) - reagents.remove_any(REAGENTS_METABOLISM) - else - if(prob(25)) //So it's not an instarape in case of acid - reagents.reaction(M, INGEST) - reagents.trans_to(M, 1) - else //Else just remove some of the reagents - reagents.remove_any(REAGENTS_METABOLISM) - return - -/obj/item/clothing/mask/cigarette/attack_self(mob/user as mob) - if(lit) - user.visible_message("[user] calmly drops and treads on the lit [name], putting it out.") - var/turf/T = get_turf(src) - new type_butt(T) - lit = 0 //Needed for proper update - update_brightness() - qdel(src) - return ..() - -/obj/item/clothing/mask/cigarette/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!istype(M)) - return ..() - - if(!lit && M.on_fire) //Hit burning mobs with cigarettes to light it up. - if(M == user) - light("[user] uses \his burning body to light \the [src]. Smooth.") - return - else - light("[user] uses the flames on [M] to light \the [src]. How rude.") - return - - //Using another cigarette to light yours - if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && user.zone_sel && user.zone_sel.selecting == "mouth" && lit) - var/obj/item/clothing/mask/cigarette/cig = M.wear_mask - if(M == user) - cig.attackby(src, user) - else - cig.light("[user] holds \his [name] out for [M], and lights \the [cig].") - - else - return ..() - -//////////// -// CIGARS // -//////////// - -/obj/item/clothing/mask/cigarette/cigar - name = "Premium Cigar" - desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!" - icon_state = "cigar" - overlay_on = "cigarlit" - flags = FPRINT - type_butt = /obj/item/weapon/cigbutt/cigarbutt - item_state = "cigar" - smoketime = 1500 - chem_volume = 20 - -/obj/item/clothing/mask/cigarette/cigar/cohiba - name = "Cohiba Robusto Cigar" - desc = "There's little more you could want from a cigar." - icon_state = "cigar2" - overlay_on = "cigar2lit" - -/obj/item/clothing/mask/cigarette/cigar/havana - name = "Premium Havanian Cigar" - desc = "A cigar fit for only the best for the best." - icon_state = "cigar2" - overlay_on = "cigar2lit" - smoketime = 7200 - chem_volume = 30 - -/obj/item/weapon/cigbutt - name = "cigarette butt" - desc = "A manky old cigarette butt." - icon = 'icons/obj/clothing/masks.dmi' - icon_state = "cigbutt" - w_class = 1 - throwforce = 1 - -/obj/item/weapon/cigbutt/cigarbutt - name = "cigar butt" - desc = "A manky old cigar butt." - icon_state = "cigarbutt" - -/* -//I'll light my cigar with an energy sword if I want to, thanks -/obj/item/clothing/mask/cigarette/cigar/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/match)) - ..() - else - to_chat(user, "\The [src] straight out REFUSES to be lit by such uncivilized means.") -*/ - -/////////////////// -//AMBROSIA BLUNTS// -/////////////////// - -/obj/item/clothing/mask/cigarette/blunt - name = "blunt" - desc = "A special homemade cigar. Light it up and pass it around." - icon_state = "blunt" - overlay_on = "bluntlit" - type_butt = /obj/item/weapon/cigbutt/bluntbutt - item_state = "blunt" - attack_verb = list("burnt", "singed", "blunted") - smoketime = 420 - chem_volume = 50 //It's a fat blunt, a really fat blunt - -/obj/item/clothing/mask/cigarette/blunt/rolled //grown.dm handles reagents for these - -/obj/item/clothing/mask/cigarette/blunt/cruciatus - -/*/obj/item/clothing/mask/cigarette/blunt/cruciatus/New() - . = ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("space_drugs", 7) - reagents.add_reagent("kelotane", 7) - reagents.add_reagent("bicaridine", 5) - reagents.add_reagent("toxin", 5) - reagents.add_reagent("spiritbreaker", 10) - update_brightness()*/ - -/obj/item/clothing/mask/cigarette/blunt/cruciatus/rolled - -/obj/item/clothing/mask/cigarette/blunt/deus - name = "godblunt" - desc = "A fat ambrosia deus cigar. Smoke weed every day." - icon_state = "dblunt" - overlay_on = "dbluntlit" - -/*/obj/item/clothing/mask/cigarette/blunt/deus/New() - . = ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("bicaridine", 7) - reagents.add_reagent("synaptizine", 7) - reagents.add_reagent("hyperzine", 5) - reagents.add_reagent("space_drugs", 5) - update_brightness()*/ - -/obj/item/clothing/mask/cigarette/blunt/deus/rolled - -/obj/item/weapon/cigbutt/bluntbutt - name = "blunt butt" - desc = "A manky old blunt butt." - icon = 'icons/obj/clothing/masks.dmi' - icon_state = "bluntbutt" - w_class = 1 - throwforce = 1 - -///////////////// -//SMOKING PIPES// -///////////////// - -/obj/item/clothing/mask/cigarette/pipe - name = "smoking pipe" - desc = "A pipe, for smoking. Probably made of meershaum or something." - flags = FPRINT - icon_state = "pipe" - item_state = "pipe" - overlay_on = "pipelit" - smoketime = 100 - -/obj/item/clothing/mask/cigarette/pipe/light(var/flavor_text = "[usr] lights the [name].") - if(!src.lit) - lit = 1 - damtype = BURN - update_brightness() - var/turf/T = get_turf(src) - T.visible_message(flavor_text) - if(istype(loc,/mob)) - var/mob/M = loc - if(M.wear_mask == src) - M.update_inv_wear_mask(0) - -/obj/item/clothing/mask/cigarette/pipe/process() - var/turf/location = get_turf(src) - smoketime-- - if(smoketime <= 0) - new /obj/effect/decal/cleanable/ash(location) - lit = 0 - if(ismob(loc)) - var/mob/living/M = loc - M.visible_message("[M]'s [name] goes out.", \ - "Your [name] goes out, and you empty the ash.") - if(M.wear_mask == src) - M.update_inv_wear_mask(0) - update_brightness() - return - if(location) - location.hotspot_expose(700, 5, surfaces = istype(loc, /turf)) - return - -/obj/item/clothing/mask/cigarette/pipe/attack_self(mob/user as mob) //Refills the pipe. Can be changed to an attackby later, if loose tobacco is added to vendors or something. //Later meaning never - if(lit) - user.visible_message("[user] puts out \the [src].", \ - "You put out \the [src].") - lit = 0 - update_brightness() - return - if(smoketime < initial(smoketime)) //Warrants a refill - user.visible_message("[user] refills \the [src].", \ - "You refill \the [src].") - smoketime = initial(smoketime) - return - -/* -//Ditto above, only a ruffian would refuse to light his pipe with an energy sword -/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/match)) - ..() - else - to_chat(user, "\The [src] straight out REFUSES to be lit by such means.") -*/ - -/obj/item/clothing/mask/cigarette/pipe/cobpipe - name = "corn cob pipe" - desc = "A nicotine delivery system popularized by folksy backwoodsmen and kept popular in the modern age and beyond by space hipsters." - icon_state = "cobpipe" - item_state = "cobpipe" - smoketime = 400 - -///////// -//ZIPPO// -///////// - -/obj/item/weapon/lighter - name = "cheap lighter" - desc = "A budget lighter. More likely lit more fingers than it did light smokes." - icon = 'icons/obj/items.dmi' - icon_state = "lighter-g" - item_state = "lighter-g" - w_class = 1 - throwforce = 4 - flags = null - siemens_coefficient = 1 - var/brightness_on = 2 //Sensibly better than a match or a cigarette - var/lightersound = list('sound/items/lighter1.ogg','sound/items/lighter2.ogg') - var/fuel = 20 - var/fueltime - heat_production = 1500 - slot_flags = SLOT_BELT - attack_verb = list("burnt", "singed") - light_color = LIGHT_COLOR_FIRE - var/lit = 0 - -/obj/item/weapon/lighter/zippo - name = "Zippo lighter" - desc = "The Zippo lighter. Need to light a smoke ? Zippo !" - icon_state = "zippo" - item_state = "zippo" - var/open_sound = list('sound/items/zippo_open.ogg') - var/close_sound = list('sound/items/zippo_close.ogg') - fuel = 100 //Zippos da bes - -/obj/item/weapon/lighter/random/New() - . = ..() - var/color = pick("r","c","y","g") - icon_state = "lighter-[color]" - update_brightness() - -/obj/item/weapon/lighter/examine(mob/user) - - ..() - to_chat(user, "The lighter is [lit ? "":"un"]lit") - -//Also updates the name, the damage and item_state for good measure -/obj/item/weapon/lighter/update_icon() - - switch(lit) - if(1) - name = "lit [initial(name)]" - item_state = "[initial(item_state)]on" - icon_state = "[initial(icon_state)]-on" - damtype = BURN - if(0) - name = "[initial(name)]" - item_state = "[initial(item_state)]off" - icon_state = "[initial(icon_state)]" - damtype = BRUTE - -/obj/item/weapon/lighter/proc/update_brightness() - - - if(lit) - processing_objects.Add(src) - set_light(brightness_on) - else - processing_objects.Remove(src) - set_light(0) - update_icon() - -/obj/item/weapon/lighter/afterattack(obj/O, mob/user, proximity) - if(!proximity) - return 0 - if(istype(O, /obj/structure/reagent_dispensers/fueltank)) - fuel += O.reagents.remove_any(initial(fuel) - fuel) - user.visible_message("[user] refuels \the [src].", \ - "You refuel \the [src].") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) - return -/obj/item/weapon/lighter/attack_self(mob/living/user) - - user.delayNextAttack(5) //Hold on there cowboy - if(!fuel) - user.visible_message("[user] attempts to light \the [src] to no avail.", \ - "\The [src] doesn't have enough fuel to ignite") - return - if(!lit) //Lighting the lighter - playsound(get_turf(src), pick(lightersound), 50, 1) - if(fuel >= initial(fuel) - 5 || prob(100 * (fuel/initial(fuel)))) //Strike, but fail to light it - user.visible_message("[user] manages to light \the [src].", \ - "You manage to light \the [src].") - lit = !lit - update_brightness() - --fuel - return - else //Failure - user.visible_message("[user] tries to light \the [src].", \ - "You try to light \the [src].") - return - else - fueltime = null - lit = !lit - user.visible_message("[user] quietly shuts off \the [src].", \ - "You quietly shut off \the [src].") - update_brightness() - -/obj/item/weapon/lighter/zippo/attack_self(mob/living/user) - user.delayNextAttack(5) //Hold on there cowboy - if(!fuel) - user.visible_message("[user] attempts to light \the [src] to no avail.", \ - "\The [src] doesn't have enough fuel to ignite") - return - lit = !lit - if(lit) //Was lit - playsound(get_turf(src), pick(open_sound), 50, 1) - user.visible_message("Without even breaking stride, [user] flips open and lights \the [src] in one smooth movement.", \ - "Without even breaking stride, you flip open and light \the [src] in one smooth movement.") - --fuel - else //Was shut off - fueltime = null - playsound(get_turf(src), pick(close_sound), 50, 1) - user.visible_message("You hear a quiet click as [user] shuts off \the [src] without even looking at what they're doing. Wow.", \ - "You hear a quiet click as you shut off \the [src] without even looking at what you are doing.") - update_brightness() - -/obj/item/weapon/lighter/is_hot() - if(lit) - return heat_production - return 0 - -/obj/item/weapon/lighter/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && user.zone_sel.selecting == "mouth" && lit) - var/obj/item/clothing/mask/cigarette/cig = M.wear_mask - if(M == user) - cig.attackby(src, user) - else - if(istype(src, /obj/item/weapon/lighter/zippo)) - cig.light("[user] whips \his [name] out and holds it for [M]. Their arm is as steady as the unflickering flame they light \the [cig] with.") - else - cig.light("[user] holds \his [name] out for [M] and lights \the [cig].") - else - return ..() - -/obj/item/weapon/lighter/process() - var/turf/location = get_turf(src) - if(location) - location.hotspot_expose(700, 5, surfaces = istype(loc, /turf)) - if(!fueltime) - fueltime = world.time + 100 - if(world.time > fueltime) - fueltime = world.time + 100 - --fuel - if(!fuel) - lit = 0 - update_brightness() - visible_message("Without warning, \the [src] suddenly shuts off.") - fueltime = null - return +//cleansed 9/15/2012 17:48 + +/* +CONTAINS: +MATCHES +CIGARETTES +CIGARS +SMOKING PIPES +CHEAP LIGHTERS +ZIPPO + +CIGARETTE PACKETS ARE IN FANCY.DM +MATCHBOXES ARE ALSO IN FANCY.DM +*/ + +/////////// +//MATCHES// +/////////// + +/obj/item/weapon/match + name = "match" + desc = "A budget match stick, used to start fires easily, preferably at the end of a smoke." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "match" + item_state = "cig" + var/lit = 0 + var/smoketime = 10 + var/brightness_on = 1 //Barely enough to see where you're standing, it's a shitty discount match + heat_production = 1000 + w_class = 1.0 + origin_tech = "materials=1" + attack_verb = list("burnt", "singed") + light_color = LIGHT_COLOR_FIRE + +/obj/item/weapon/match/New() + + ..() + update_brightness() //Useful if you want to spawn burnt matches, or burning ones you maniac + +/obj/item/weapon/match/examine(mob/user) + + ..() + switch(lit) + if(1) + to_chat(user, "The match is lit.") + if(0) + to_chat(user, "The match is unlit and ready to be used.") + if(-1) + to_chat(user, "The match is burnt.") + +//Also updates the name, the damage and item_state for good measure +/obj/item/weapon/match/update_icon() + + switch(lit) + if(1) + name = "lit [initial(name)]" + item_state = "[initial(item_state)]on" + icon_state = "[initial(icon_state)]_lit" + damtype = BURN + if(0) + name = "[initial(name)]" + item_state = "[initial(item_state)]off" + icon_state = "[initial(icon_state)]_unlit" + damtype = BRUTE + if(-1) + name = "burnt [initial(name)]" + item_state = "[initial(item_state)]off" + icon_state = "[initial(icon_state)]_burnt" + damtype = BRUTE + +/obj/item/weapon/match/proc/update_brightness() + + + if(lit == 1) //I wish I didn't need the == 1 part, but Dreamkamer is a dumb puppy + processing_objects.Add(src) + set_light(brightness_on) + else + processing_objects.Remove(src) + set_light(0) + update_icon() + +/obj/item/weapon/match/process() + var/turf/location = get_turf(src) + smoketime-- + if(smoketime <= 0) + lit = -1 + update_brightness() + return + if(location) + location.hotspot_expose(heat_production, 5, surfaces = istype(loc, /turf)) + return + +/obj/item/weapon/match/is_hot() + if(lit == 1) + return heat_production + return 0 + +/obj/item/weapon/match/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && user.zone_sel.selecting == "mouth" && lit == 1) + var/obj/item/clothing/mask/cigarette/cig = M.wear_mask + if(M == user) + cig.attackby(src, user) + else + cig.light("[user] holds \the [name] out for [M], and lights \his [cig.name].") + else + return ..() + +/* +/obj/item/weapon/match/attackby(obj/item/weapon/W as obj, mob/user as mob) + + if(W.is_hot()) + lit = 1 + update_brightness() + user.visible_message("[user] lights \the [src] with \the [W].", \ + "You light \the [src] with \the [W].") + ..() +*/ + +/obj/item/weapon/match/strike_anywhere + name = "strike-anywhere match" + desc = "An improved match stick, used to start fires easily, preferably at the end of a smoke. Can be lit against any surface" + +/obj/item/weapon/match/strike_anywhere/afterattack(atom/target, mob/user, prox_flags) + if(!prox_flags == 1) + return + + if(!(get_turf(src) == get_turf(user))) + return + + if(lit) + return + + if(istype(target, /obj) || istype(target, /turf)) + lit = 1 + update_brightness() + user.visible_message("[user] strikes \the [src] on \the [target].", \ + "You strike \the [src] on \the [target].") + +////////////////// +//FINE SMOKABLES// +////////////////// + +//Doubles as a mask entity, aka can be put to your mouth like a real cigarette +/obj/item/clothing/mask/cigarette + name = "cigarette" + desc = "A roll of tobacco and nicotine. Not the best thing to have on your face in the event of a plasma flood." + icon_state = "cig" + item_state = "cig" + w_class = 1 + body_parts_covered = null + attack_verb = list("burnt", "singed") + heat_production = 1000 + light_color = LIGHT_COLOR_FIRE + var/lit = 0 + var/overlay_on = "ciglit" //Apparently not used + var/type_butt = /obj/item/weapon/cigbutt + var/lastHolder = null + var/brightness_on = 1 //Barely enough to see where you're standing, it's a boring old cigarette + var/smoketime = 300 + var/chem_volume = 15 + +/obj/item/clothing/mask/cigarette/New() + ..() + flags |= NOREACT // so it doesn't react until you light it + create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15 + update_brightness() + +/obj/item/clothing/mask/cigarette/examine(mob/user) + + ..() + to_chat(user, "\The [src] is [lit ? "":"un"]lit.")//Shared with all cigarette sub-types + + +//Also updates the name, the damage and item_state for good measure +/obj/item/clothing/mask/cigarette/update_icon() + + switch(lit) + if(1) + name = "lit [initial(name)]" + item_state = "[initial(item_state)]on" + icon_state = "[initial(icon_state)]on" + damtype = BURN + if(0) + name = "[initial(name)]" + item_state = "[initial(item_state)]off" + icon_state = "[initial(icon_state)]off" + damtype = BRUTE + +/obj/item/clothing/mask/cigarette/proc/update_brightness() + + + if(lit) + processing_objects.Add(src) + set_light(brightness_on) + else + processing_objects.Remove(src) + set_light(0) + update_icon() + +/obj/item/clothing/mask/cigarette/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(lit) + return + light("The raging fire sets \the [src] alight.") + +/obj/item/clothing/mask/cigarette/is_hot() + if(lit) + return heat_production + return 0 + +/obj/item/clothing/mask/cigarette/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + + if(lit) //The cigarette is already lit + to_chat(user, "\The [src] is already lit.") + return //Don't bother + + //Items with special messages go first + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.is_hot()) //Badasses dont get blinded while lighting their cig with a welding tool + light("[user] casually lights \his [name] with \the [W], what a badass.") + + else if(istype(W, /obj/item/weapon/lighter/zippo)) + var/obj/item/weapon/lighter/zippo/Z = W + if(Z.is_hot()) + light("With a single flick of their wrist, [user] smoothly lights \his [name] with \the [W]. Damn, that's cool.") + + else if(istype(W, /obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/L = W + if(L.is_hot()) + light("After some fiddling, [user] manages to light \his [name] with \the [W].") + + else if(istype(W, /obj/item/weapon/melee/energy/sword)) + var/obj/item/weapon/melee/energy/sword/S = W + if(S.is_hot()) + light("[user] raises \his [W.name], lighting \the [src]. Holy fucking shit.") + + else if(istype(W, /obj/item/device/assembly/igniter)) + var/obj/item/device/assembly/igniter/I = W + if(I.is_hot()) + light("[user] fiddles with \his [W.name], and manages to light their [name].") + + //All other items are included here, any item that is hot can light the cigarette + else if(W.is_hot()) + light("[user] lights \his [name] with \the [W].") + return + + +/obj/item/clothing/mask/cigarette/afterattack(obj/item/weapon/reagent_containers/glass/glass, mob/user as mob) + ..() + if(istype(glass)) //You can dip cigarettes into beakers and beaker subtypes + if(glass.reagents.has_reagent("sacid") || glass.reagents.has_reagent("pacid")) //Dumping into acid, a dumb idea + new type_butt(get_turf(glass)) + processing_objects.Remove(src) + to_chat(user, "Half of \the [src] dissolves with a nasty fizzle as you dip it into \the [glass].") + user.drop_item(src, force_drop = 1) + qdel(src) + return + if(glass.reagents.has_reagent("water") && lit) //Dumping a lit cigarette into water, the result is obvious + new type_butt(get_turf(glass)) + processing_objects.Remove(src) + to_chat(user, "\The [src] fizzles as you dip it into \the [glass].") + user.drop_item(src, force_drop = 1) + qdel(src) + return + var/transfered = glass.reagents.trans_to(src, chem_volume) + if(transfered) //If reagents were transfered, show the message + to_chat(user, "You dip \the [src] into \the [glass].") + else //If not, either the beaker was empty, or the cigarette was full + if(!glass.reagents.total_volume) //Only show an explicit message if the beaker was empty, you can't tell a cigarette is "full" + to_chat(user, "\The [glass] is empty.") + return + +/obj/item/clothing/mask/cigarette/proc/light(var/flavor_text = "[usr] lights \the [src].") + if(lit) //Failsafe + return //"Normal" situations were already handled in attackby, don't show a message + + if(reagents.get_reagent_amount("water")) //The cigarette was dipped into water, it's useless now + to_chat(usr, "You fail to light \the [src]. It appears to be wet.") + return + + if(reagents.get_reagent_amount("plasma")) //Plasma explodes when exposed to fire + var/datum/effect/effect/system/reagents_explosion/e = new() + e.set_up(round(reagents.get_reagent_amount("plasma")/2.5, 1), get_turf(src), 0, 0) + e.start() + if(ismob(loc)) + var/mob/M = loc + M.drop_from_inventory(src) + qdel(src) + return + + if(reagents.get_reagent_amount("fuel")) //Fuel explodes, too, but much less violently + var/datum/effect/effect/system/reagents_explosion/e = new() + e.set_up(round(reagents.get_reagent_amount("fuel")/5, 1), get_turf(src), 0, 0) + e.start() + if(ismob(loc)) + var/mob/M = loc + M.drop_from_inventory(src) + qdel(src) + return + + lit = 1 //All checks that could have stopped the cigarette are done, let us begin + + flags &= ~NOREACT //Allow reagents to react after being lit + flags |= (MASKINTERNALS | BLOCK_GAS_SMOKE_EFFECT) + + reagents.handle_reactions() + //This ain't ready yet. + //overlays.len = 0 + //overlays += image('icons/mob/mask.dmi', overlay_on, LIGHTING_LAYER+1) + var/turf/T = get_turf(src) + T.visible_message(flavor_text) + + update_brightness() + + //can't think of any other way to update the overlays :< //Gee, thanks + if(ismob(loc)) + var/mob/M = loc + M.update_inv_wear_mask(0) + M.update_inv_l_hand(0) + M.update_inv_r_hand(1) + +/obj/item/clothing/mask/cigarette/process() + var/turf/location = get_turf(src) + var/mob/living/M = loc + if(isliving(loc)) + M.IgniteMob() + smoketime-- + if(smoketime <= 0) + new type_butt(location) //Spawn the cigarette butt + lit = 0 //Actually unlight the cigarette so that the lighting can update correctly + update_brightness() + if(ismob(loc)) + to_chat(M, "Your [name] goes out.") + M.u_equip(src, 0) //Un-equip it so the overlays can update + qdel(src) + return + if(location) + location.hotspot_expose(700, 5, surfaces = istype(loc, /turf)) + //Oddly specific and snowflakey reagent transfer system below + if(reagents && reagents.total_volume) //Check if it has any reagents at all + if(iscarbon(M) && (src == M.wear_mask)) //If it's in the human/monkey mouth, transfer reagents to the mob + if(M.reagents.has_reagent("lexorin") || M_NO_BREATH in M.mutations || istype(M.loc, /obj/machinery/atmospherics/unary/cryo_cell)) + reagents.remove_any(REAGENTS_METABOLISM) + else + if(prob(25)) //So it's not an instarape in case of acid + reagents.reaction(M, INGEST) + reagents.trans_to(M, 1) + else //Else just remove some of the reagents + reagents.remove_any(REAGENTS_METABOLISM) + return + +/obj/item/clothing/mask/cigarette/attack_self(mob/user as mob) + if(lit) + user.visible_message("[user] calmly drops and treads on the lit [name], putting it out.") + var/turf/T = get_turf(src) + new type_butt(T) + lit = 0 //Needed for proper update + update_brightness() + qdel(src) + return ..() + +/obj/item/clothing/mask/cigarette/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M)) + return ..() + + if(!lit && M.on_fire) //Hit burning mobs with cigarettes to light it up. + if(M == user) + light("[user] uses \his burning body to light \the [src]. Smooth.") + return + else + light("[user] uses the flames on [M] to light \the [src]. How rude.") + return + + //Using another cigarette to light yours + if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && user.zone_sel && user.zone_sel.selecting == "mouth" && lit) + var/obj/item/clothing/mask/cigarette/cig = M.wear_mask + if(M == user) + cig.attackby(src, user) + else + cig.light("[user] holds \his [name] out for [M], and lights \the [cig].") + + else + return ..() + +//////////// +// CIGARS // +//////////// + +/obj/item/clothing/mask/cigarette/cigar + name = "Premium Cigar" + desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!" + icon_state = "cigar" + overlay_on = "cigarlit" + flags = FPRINT + type_butt = /obj/item/weapon/cigbutt/cigarbutt + item_state = "cigar" + smoketime = 1500 + chem_volume = 20 + +/obj/item/clothing/mask/cigarette/cigar/cohiba + name = "Cohiba Robusto Cigar" + desc = "There's little more you could want from a cigar." + icon_state = "cigar2" + overlay_on = "cigar2lit" + +/obj/item/clothing/mask/cigarette/cigar/havana + name = "Premium Havanian Cigar" + desc = "A cigar fit for only the best for the best." + icon_state = "cigar2" + overlay_on = "cigar2lit" + smoketime = 7200 + chem_volume = 30 + +/obj/item/weapon/cigbutt + name = "cigarette butt" + desc = "A manky old cigarette butt." + icon = 'icons/obj/clothing/masks.dmi' + icon_state = "cigbutt" + w_class = 1 + throwforce = 1 + +/obj/item/weapon/cigbutt/cigarbutt + name = "cigar butt" + desc = "A manky old cigar butt." + icon_state = "cigarbutt" + +/* +//I'll light my cigar with an energy sword if I want to, thanks +/obj/item/clothing/mask/cigarette/cigar/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/match)) + ..() + else + to_chat(user, "\The [src] straight out REFUSES to be lit by such uncivilized means.") +*/ + +/////////////////// +//AMBROSIA BLUNTS// +/////////////////// + +/obj/item/clothing/mask/cigarette/blunt + name = "blunt" + desc = "A special homemade cigar. Light it up and pass it around." + icon_state = "blunt" + overlay_on = "bluntlit" + type_butt = /obj/item/weapon/cigbutt/bluntbutt + item_state = "blunt" + attack_verb = list("burnt", "singed", "blunted") + smoketime = 420 + chem_volume = 50 //It's a fat blunt, a really fat blunt + +/obj/item/clothing/mask/cigarette/blunt/rolled //grown.dm handles reagents for these + +/obj/item/clothing/mask/cigarette/blunt/cruciatus + +/*/obj/item/clothing/mask/cigarette/blunt/cruciatus/New() + . = ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("space_drugs", 7) + reagents.add_reagent("kelotane", 7) + reagents.add_reagent("bicaridine", 5) + reagents.add_reagent("toxin", 5) + reagents.add_reagent("spiritbreaker", 10) + update_brightness()*/ + +/obj/item/clothing/mask/cigarette/blunt/cruciatus/rolled + +/obj/item/clothing/mask/cigarette/blunt/deus + name = "godblunt" + desc = "A fat ambrosia deus cigar. Smoke weed every day." + icon_state = "dblunt" + overlay_on = "dbluntlit" + +/*/obj/item/clothing/mask/cigarette/blunt/deus/New() + . = ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("bicaridine", 7) + reagents.add_reagent("synaptizine", 7) + reagents.add_reagent("hyperzine", 5) + reagents.add_reagent("space_drugs", 5) + update_brightness()*/ + +/obj/item/clothing/mask/cigarette/blunt/deus/rolled + +/obj/item/weapon/cigbutt/bluntbutt + name = "blunt butt" + desc = "A manky old blunt butt." + icon = 'icons/obj/clothing/masks.dmi' + icon_state = "bluntbutt" + w_class = 1 + throwforce = 1 + +///////////////// +//SMOKING PIPES// +///////////////// + +/obj/item/clothing/mask/cigarette/pipe + name = "smoking pipe" + desc = "A pipe, for smoking. Probably made of meershaum or something." + flags = FPRINT + icon_state = "pipe" + item_state = "pipe" + overlay_on = "pipelit" + smoketime = 100 + +/obj/item/clothing/mask/cigarette/pipe/light(var/flavor_text = "[usr] lights the [name].") + if(!src.lit) + lit = 1 + damtype = BURN + update_brightness() + var/turf/T = get_turf(src) + T.visible_message(flavor_text) + if(istype(loc,/mob)) + var/mob/M = loc + if(M.wear_mask == src) + M.update_inv_wear_mask(0) + +/obj/item/clothing/mask/cigarette/pipe/process() + var/turf/location = get_turf(src) + smoketime-- + if(smoketime <= 0) + new /obj/effect/decal/cleanable/ash(location) + lit = 0 + if(ismob(loc)) + var/mob/living/M = loc + M.visible_message("[M]'s [name] goes out.", \ + "Your [name] goes out, and you empty the ash.") + if(M.wear_mask == src) + M.update_inv_wear_mask(0) + update_brightness() + return + if(location) + location.hotspot_expose(700, 5, surfaces = istype(loc, /turf)) + return + +/obj/item/clothing/mask/cigarette/pipe/attack_self(mob/user as mob) //Refills the pipe. Can be changed to an attackby later, if loose tobacco is added to vendors or something. //Later meaning never + if(lit) + user.visible_message("[user] puts out \the [src].", \ + "You put out \the [src].") + lit = 0 + update_brightness() + return + if(smoketime < initial(smoketime)) //Warrants a refill + user.visible_message("[user] refills \the [src].", \ + "You refill \the [src].") + smoketime = initial(smoketime) + return + +/* +//Ditto above, only a ruffian would refuse to light his pipe with an energy sword +/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/match)) + ..() + else + to_chat(user, "\The [src] straight out REFUSES to be lit by such means.") +*/ + +/obj/item/clothing/mask/cigarette/pipe/cobpipe + name = "corn cob pipe" + desc = "A nicotine delivery system popularized by folksy backwoodsmen and kept popular in the modern age and beyond by space hipsters." + icon_state = "cobpipe" + item_state = "cobpipe" + smoketime = 400 + +///////// +//ZIPPO// +///////// + +/obj/item/weapon/lighter + name = "cheap lighter" + desc = "A budget lighter. More likely lit more fingers than it did light smokes." + icon = 'icons/obj/items.dmi' + icon_state = "lighter-g" + item_state = "lighter-g" + w_class = 1 + throwforce = 4 + flags = null + siemens_coefficient = 1 + var/brightness_on = 2 //Sensibly better than a match or a cigarette + var/lightersound = list('sound/items/lighter1.ogg','sound/items/lighter2.ogg') + var/fuel = 20 + var/fueltime + heat_production = 1500 + slot_flags = SLOT_BELT + attack_verb = list("burnt", "singed") + light_color = LIGHT_COLOR_FIRE + var/lit = 0 + +/obj/item/weapon/lighter/zippo + name = "Zippo lighter" + desc = "The Zippo lighter. Need to light a smoke ? Zippo !" + icon_state = "zippo" + item_state = "zippo" + var/open_sound = list('sound/items/zippo_open.ogg') + var/close_sound = list('sound/items/zippo_close.ogg') + fuel = 100 //Zippos da bes + +/obj/item/weapon/lighter/random/New() + . = ..() + var/color = pick("r","c","y","g") + icon_state = "lighter-[color]" + update_brightness() + +/obj/item/weapon/lighter/examine(mob/user) + + ..() + to_chat(user, "The lighter is [lit ? "":"un"]lit") + +//Also updates the name, the damage and item_state for good measure +/obj/item/weapon/lighter/update_icon() + + switch(lit) + if(1) + name = "lit [initial(name)]" + item_state = "[initial(item_state)]on" + icon_state = "[initial(icon_state)]-on" + damtype = BURN + if(0) + name = "[initial(name)]" + item_state = "[initial(item_state)]off" + icon_state = "[initial(icon_state)]" + damtype = BRUTE + +/obj/item/weapon/lighter/proc/update_brightness() + + + if(lit) + processing_objects.Add(src) + set_light(brightness_on) + else + processing_objects.Remove(src) + set_light(0) + update_icon() + +/obj/item/weapon/lighter/afterattack(obj/O, mob/user, proximity) + if(!proximity) + return 0 + if(istype(O, /obj/structure/reagent_dispensers/fueltank)) + fuel += O.reagents.remove_any(initial(fuel) - fuel) + user.visible_message("[user] refuels \the [src].", \ + "You refuel \the [src].") + playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + return +/obj/item/weapon/lighter/attack_self(mob/living/user) + + user.delayNextAttack(5) //Hold on there cowboy + if(!fuel) + user.visible_message("[user] attempts to light \the [src] to no avail.", \ + "\The [src] doesn't have enough fuel to ignite") + return + if(!lit) //Lighting the lighter + playsound(get_turf(src), pick(lightersound), 50, 1) + if(fuel >= initial(fuel) - 5 || prob(100 * (fuel/initial(fuel)))) //Strike, but fail to light it + user.visible_message("[user] manages to light \the [src].", \ + "You manage to light \the [src].") + lit = !lit + update_brightness() + --fuel + return + else //Failure + user.visible_message("[user] tries to light \the [src].", \ + "You try to light \the [src].") + return + else + fueltime = null + lit = !lit + user.visible_message("[user] quietly shuts off \the [src].", \ + "You quietly shut off \the [src].") + update_brightness() + +/obj/item/weapon/lighter/zippo/attack_self(mob/living/user) + user.delayNextAttack(5) //Hold on there cowboy + if(!fuel) + user.visible_message("[user] attempts to light \the [src] to no avail.", \ + "\The [src] doesn't have enough fuel to ignite") + return + lit = !lit + if(lit) //Was lit + playsound(get_turf(src), pick(open_sound), 50, 1) + user.visible_message("Without even breaking stride, [user] flips open and lights \the [src] in one smooth movement.", \ + "Without even breaking stride, you flip open and light \the [src] in one smooth movement.") + --fuel + else //Was shut off + fueltime = null + playsound(get_turf(src), pick(close_sound), 50, 1) + user.visible_message("You hear a quiet click as [user] shuts off \the [src] without even looking at what they're doing. Wow.", \ + "You hear a quiet click as you shut off \the [src] without even looking at what you are doing.") + update_brightness() + +/obj/item/weapon/lighter/is_hot() + if(lit) + return heat_production + return 0 + +/obj/item/weapon/lighter/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && user.zone_sel.selecting == "mouth" && lit) + var/obj/item/clothing/mask/cigarette/cig = M.wear_mask + if(M == user) + cig.attackby(src, user) + else + if(istype(src, /obj/item/weapon/lighter/zippo)) + cig.light("[user] whips \his [name] out and holds it for [M]. Their arm is as steady as the unflickering flame they light \the [cig] with.") + else + cig.light("[user] holds \his [name] out for [M] and lights \the [cig].") + else + return ..() + +/obj/item/weapon/lighter/process() + var/turf/location = get_turf(src) + if(location) + location.hotspot_expose(700, 5, surfaces = istype(loc, /turf)) + if(!fueltime) + fueltime = world.time + 100 + if(world.time > fueltime) + fueltime = world.time + 100 + --fuel + if(!fuel) + lit = 0 + update_brightness() + visible_message("Without warning, \the [src] suddenly shuts off.") + fueltime = null + return diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 717d50f563c..1b84ac529b6 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -1,88 +1,88 @@ -/obj/item/weapon/lipstick - name = "red lipstick" - desc = "A generic brand of lipstick." - icon = 'icons/obj/items.dmi' - icon_state = "lipstick" - flags = FPRINT - w_class = 1.0 - var/colour = "red" - var/open = 0 - - -/obj/item/weapon/lipstick/purple - name = "purple lipstick" - colour = "purple" - -/obj/item/weapon/lipstick/jade - name = "jade lipstick" - colour = "jade" - -/obj/item/weapon/lipstick/black - name = "black lipstick" - colour = "black" - - -/obj/item/weapon/lipstick/random - name = "lipstick" - -/obj/item/weapon/lipstick/random/New() - colour = pick("red","purple","jade","black") - name = "[colour] lipstick" - ..() - - -/obj/item/weapon/lipstick/attack_self(mob/user as mob) +/obj/item/weapon/lipstick + name = "red lipstick" + desc = "A generic brand of lipstick." + icon = 'icons/obj/items.dmi' + icon_state = "lipstick" + flags = FPRINT + w_class = 1.0 + var/colour = "red" + var/open = 0 + + +/obj/item/weapon/lipstick/purple + name = "purple lipstick" + colour = "purple" + +/obj/item/weapon/lipstick/jade + name = "jade lipstick" + colour = "jade" + +/obj/item/weapon/lipstick/black + name = "black lipstick" + colour = "black" + + +/obj/item/weapon/lipstick/random + name = "lipstick" + +/obj/item/weapon/lipstick/random/New() + colour = pick("red","purple","jade","black") + name = "[colour] lipstick" + ..() + + +/obj/item/weapon/lipstick/attack_self(mob/user as mob) to_chat(user, "You twist \the [src] [open ? "closed" : "open"].") - open = !open - if(open) - icon_state = "[initial(icon_state)]_[colour]" - else - icon_state = initial(icon_state) - -/obj/item/weapon/lipstick/attack(mob/M as mob, mob/user as mob) - if(!open) return - - if(!istype(M, /mob)) return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.lip_style) //if they already have lipstick on + open = !open + if(open) + icon_state = "[initial(icon_state)]_[colour]" + else + icon_state = initial(icon_state) + +/obj/item/weapon/lipstick/attack(mob/M as mob, mob/user as mob) + if(!open) return + + if(!istype(M, /mob)) return + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.lip_style) //if they already have lipstick on to_chat(user, "You need to wipe off the old lipstick first!") - return - if(H == user) - user.visible_message("[user] does their lips with \the [src].", \ - "You take a moment to apply \the [src]. Perfect!") - H.lip_style = colour - H.update_body() - else - user.visible_message("[user] begins to do [H]'s lips with \the [src].", \ - "You begin to apply \the [src].") - if(do_after(user,H, 20) && do_after(H,null, 20, 5, 0)) //user needs to keep their active hand, H does not. - user.visible_message("[user] does [H]'s lips with \the [src].", \ - "You apply \the [src].") - H.lip_style = colour - H.update_body() - else + return + if(H == user) + user.visible_message("[user] does their lips with \the [src].", \ + "You take a moment to apply \the [src]. Perfect!") + H.lip_style = colour + H.update_body() + else + user.visible_message("[user] begins to do [H]'s lips with \the [src].", \ + "You begin to apply \the [src].") + if(do_after(user,H, 20) && do_after(H,null, 20, 5, 0)) //user needs to keep their active hand, H does not. + user.visible_message("[user] does [H]'s lips with \the [src].", \ + "You apply \the [src].") + H.lip_style = colour + H.update_body() + else to_chat(user, "Where are the lips on that?") - -//you can wipe off lipstick with paper! -/obj/item/weapon/paper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(user.zone_sel.selecting == "mouth") - if(!istype(M, /mob)) return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H == user) + +//you can wipe off lipstick with paper! +/obj/item/weapon/paper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(user.zone_sel.selecting == "mouth") + if(!istype(M, /mob)) return + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H == user) to_chat(user, "You wipe off the lipstick with [src].") - H.lip_style = null - H.update_body() - else - user.visible_message("[user] begins to wipe [H]'s lipstick off with \the [src].", \ - "You begin to wipe off [H]'s lipstick.") - if(do_after(user, H, 10) && do_after(H, null, 10, 5, 0)) //user needs to keep their active hand, H does not. - user.visible_message("[user] wipes [H]'s lipstick off with \the [src].", \ - "You wipe off [H]'s lipstick.") - H.lip_style = null - H.update_body() - else + H.lip_style = null + H.update_body() + else + user.visible_message("[user] begins to wipe [H]'s lipstick off with \the [src].", \ + "You begin to wipe off [H]'s lipstick.") + if(do_after(user, H, 10) && do_after(H, null, 10, 5, 0)) //user needs to keep their active hand, H does not. + user.visible_message("[user] wipes [H]'s lipstick off with \the [src].", \ + "You wipe off [H]'s lipstick.") + H.lip_style = null + H.update_body() + else ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index c6a36899de0..97cae8c5bad 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -1,292 +1,292 @@ -/obj/item/weapon/dice - name = "d6" - desc = "A die with six sides. Basic and servicable." - icon = 'icons/obj/dice.dmi' - icon_state = "d6" - w_class = 1 - var/sides = 6 - var/minsides = 1 - var/result = null - -/obj/item/weapon/dice/New() - ..() - result = rand(minsides, sides) - update_icon() - -/obj/item/weapon/dice/d2 - name = "d2" - desc = "A die with two sides. Coins are undignified!" - icon_state = "d2" - sides = 2 - -/obj/item/weapon/dice/d4 - name = "d4" - desc = "A die with four sides. The nerd's caltrop." - icon_state = "d4" - sides = 4 - -/obj/item/weapon/dice/d8 - name = "d8" - desc = "A die with eight sides. It feels... lucky." - icon_state = "d8" - sides = 8 - -/obj/item/weapon/dice/d10 - name = "d10" - desc = "A die with ten sides. Useful for percentages." - icon_state = "d10" - sides = 10 - -/obj/item/weapon/dice/d00 - name = "d00" - desc = "A die with ten sides. Works better for d100 rolls than a golfball." - icon_state = "d00" - sides = 10 - -/obj/item/weapon/dice/d12 - name = "d12" - desc = "A die with twelve sides. There's an air of neglect about it." - icon_state = "d12" - sides = 12 - -/obj/item/weapon/dice/d20 - name = "d20" - desc = "A die with twenty sides. The prefered die to throw at the GM." - icon_state = "d20" - sides = 20 - -/obj/item/weapon/dice/d20/e20 - var/triggered = 0 - -/obj/item/weapon/dice/attack_self(mob/user as mob) - diceroll(user, 0) - -/obj/item/weapon/dice/throw_impact(atom/hit_atom, speed, user) - ..() - diceroll(user, 1) - -/obj/item/weapon/dice/proc/diceroll(mob/user as mob, thrown) - result = rand(minsides, sides) - var/comment = "" - if(sides == 20 && result == 20) - comment = "Nat 20!" - else if(sides == 20 && result == 1) - comment = "Ouch, bad luck." - update_icon() - if(initial(icon_state) == "d00") - result = (result - 1)*10 - if(!thrown) //Dice was rolled in someone's hand - user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \ - "You throw [src]. It lands on [result]. [comment]", \ - "You hear [src] landing on [result]. [comment]") - else if(src.throwing == 0) //Dice was thrown and is coming to rest - visible_message("[src] rolls to a stop, landing on [result]. [comment]") - -/obj/item/weapon/dice/d4/Crossed(var/mob/living/carbon/human/H) - if(istype(H) && !H.shoes) - to_chat(H, "You step on the D4!") - H.apply_damage(4,BRUTE,(pick("l_leg", "r_leg"))) - H.Weaken(3) - -/obj/item/weapon/dice/update_icon() - overlays.len = 0 - overlays += "[src.icon_state][src.result]" - -/obj/item/weapon/dice/d20/e20/diceroll(mob/user as mob, thrown) - if(!istype(user)) return 0 - if(triggered) return - ..() - message_admins("[key_name(user)] has [thrown? "used" : "thrown"] an explosive dice and rolled a [result]") - log_game("[key_name(user)] has [thrown? "used" : "thrown"] an explosive dice and rolled a [result]") - if(result == 1) - to_chat(user, "Rocks fall, you die.") - user.gib() - user.drop_item(src, force_drop = 1) - else - triggered = 1 - visible_message("You hear a quiet click.") - spawn(40) - var/cap = 0 - var/uncapped = result - if(result > MAX_EXPLOSION_RANGE && result != 20) - cap = 1 - result = min(result, MAX_EXPLOSION_RANGE) //Apply the bombcap - if(result > 14) - sleep(20) - else if(result == 20) //Roll a nat 20, screw the bombcap - result = 24 - sleep(40) - var/turf/epicenter = get_turf(src) - explosion(epicenter, round(result*0.25), round(result*0.5), round(result), round(result*1.5), 1, cap) - if(cap) - for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) - if(bhangmeter) - bhangmeter.sense_explosion(epicenter.x,epicenter.y,epicenter.z,round(uncapped*0.25), round(uncapped*0.5), round(uncapped),"???", cap) - - -/obj/item/weapon/dice/d20/cursed - desc = "Something about this dice seems wrong" - name = "\improper Mysterious d20" - var/deactivated = 0 //Eventually the dice runs out of power - -/obj/item/weapon/dice/d20/cursed/pickup(mob/user as mob) - ..() - if(deactivated == 0) - to_chat(user, "Are you feeling lucky?") - -/obj/item/weapon/dice/d20/cursed/diceroll(mob/user as mob, thrown) - ..() - if(deactivated == 0) //If the dice has power then something will happen - message_admins("[key_name(user)] has [thrown? "used" : "thrown"] a cursed dice and rolled a [result]") - log_game("[key_name(user)] has [thrown? "used" : "thrown"] a cursed dice and rolled a [result]") - if(istype(user,/mob/living/carbon/human)) //check that a humanoid is rolling the dice; Xenomorphs / Sillicons need not apply. - var/mob/living/carbon/human/h = user - switch(result) - if(1) - to_chat(user, "A natural failure, your poor roll has cursed you. Better luck next time! ") - flick("e_flash", user.flash) - h.Cluwneize() - if(2 to 5) - to_chat(user, "It could be worse, but not much worse! Enjoy your curse! ") - flick("e_flash", user.flash) - switch(pick(1,2,3)) - if(1) - if(h.species.name != "Tajaran") - if(h.set_species("Tajaran")) - h.regenerate_icons() - to_chat(user, "You have been turned into a disgusting catbeast! ") - else - for(var/datum/organ/external/E in h.organs) //Being a catbeast doesn't exempt you from getting a curse just because you cannot turn into a catbeast again. - E.droplimb(1) - if(2) - for(var/datum/organ/external/E in h.organs) - E.droplimb(1) - if(3) - user.reagents.add_reagent("amutationtoxin", 1) - to_chat(user, "You've been turned into a slime! ") - if(6 to 9) - to_chat(user, "
    You have rolled low and shall recieve a curse! It could be a lot worse however!
    ") - flick("e_flash", user.flash) - switch(pick(1,2,3,4)) - if(1) - user.dna.SetSEState(DEAFBLOCK,1) - user.dna.SetSEState(MUTEBLOCK,1) - user.dna.SetSEState(BLINDBLOCK,1) - genemutcheck(user,DEAFBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,MUTEBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,BLINDBLOCK,null,MUTCHK_FORCED) - user.update_mutations() - to_chat(user, "You've gone blind, deaf and mute! ") - if(2) - for(var/datum/organ/external/l_arm/E in h.organs) - E.droplimb(1) - for(var/datum/organ/external/r_arm/E in h.organs) - E.droplimb(2) - if(3) - if(h.species.name != "Tajaran") //someone who was made a catbeast by the dice can't become a different species by getting lucky - switch(pick(1,2,3)) - if(1) - if(h.species.name != "Unathi") - if(h.set_species("Unathi")) - h.regenerate_icons() - to_chat(user, "You have been turned into a disgusting lizard! ") - else - for(var/datum/organ/external/l_arm/E in h.organs) //Someone who has already become a lizard can't get out of recieving a curse and so they lose their arms instead - E.droplimb(1) - for(var/datum/organ/external/r_arm/E in h.organs) - E.droplimb(1) - if(2) - if(h.species.name != "Skrell") - if(h.set_species("Skrell")) - h.regenerate_icons() - to_chat(user, "You have been turned into a disgusting squidman! ") - else - for(var/datum/organ/external/l_arm/E in h.organs) //Someone who has already become a squid can't get out of recieving a curse and so they lose their arms instead - E.droplimb(1) - for(var/datum/organ/external/r_arm/E in h.organs) - E.droplimb(1) - if(3) - if(h.species.name != "Vox") - if(h.set_species("Vox")) - h.regenerate_icons() - to_chat(user, "You have been turned into a dumb, diseased bird! ") - else - for(var/datum/organ/external/l_arm/E in h.organs) //Someone who is a vox can't get out of recieving a curse and so they lose their arms instead - E.droplimb(1) - for(var/datum/organ/external/r_arm/E in h.organs) - E.droplimb(1) - if(4) - h.adjustBrainLoss(200) - user.reagents.add_reagent("nutriment", 1000) - user.overeatduration = 1000 - - to_chat(user, "In this moment you feel euphoric! ") - if(10 to 12) - to_chat(user, "You get nothing. No curse or reward! ") - if(13) - to_chat(user, "You've rolled 13! The cursed dice is broken! ") - explosion(get_turf(src), 0, 0, 4, 7) - to_chat(user, "The dice explosively shatters! ") - qdel(src) - - if(14 to 19) - to_chat(user, "You've rolled well and shall be rewarded! ") - switch(pick(1,2,3,4,5)) - if(1) - user.dna.SetSEState(INCREASERUNBLOCK,1) - user.dna.SetSEState(SMALLSIZEBLOCK,1) - genemutcheck(user,INCREASERUNBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,SMALLSIZEBLOCK,null,MUTCHK_FORCED) - user.update_mutations() - to_chat(user, "You have been made faster! ") - if(2) - user.dna.SetSEState(XRAYBLOCK,1) - user.dna.SetSEState(TELEBLOCK,1) - genemutcheck(user, XRAYBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,TELEBLOCK,null,MUTCHK_FORCED) - user.update_mutations() - to_chat(user, "You have been granted vision! ") - if(3) - user.dna.SetSEState(COLDBLOCK,1) - user.dna.SetSEState(FIREBLOCK,1) - user.dna.SetSEState(NOBREATHBLOCK,1) - genemutcheck(user,COLDBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,FIREBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,NOBREATHBLOCK,null,MUTCHK_FORCED) - user.update_mutations() - to_chat(user, "You have been granted protection! ") - if(4) - getFromPool(/obj/item/stack/sheet/mineral/gold,user.loc,50) - to_chat(user, "You have been reward in gold! ") - if(5) - getFromPool(/obj/item/stack/sheet/mineral/silver,user.loc,50) - to_chat(user, "You have been rewarded in silver! ") - if(20) - to_chat(user, "A perfect roll! enjoy your reward! ") - getFromPool(/obj/item/stack/sheet/mineral/phazon,user.loc,50) - getFromPool(/obj/item/stack/sheet/mineral/diamond,user.loc,50) - getFromPool(/obj/item/stack/sheet/mineral/clown,user.loc,50) - user.dna.SetSEState(XRAYBLOCK,1) - user.dna.SetSEState(TELEBLOCK,1) - user.dna.SetSEState(INCREASERUNBLOCK,1) - user.dna.SetSEState(SMALLSIZEBLOCK,1) - user.dna.SetSEState(COLDBLOCK,1) - user.dna.SetSEState(NOBREATHBLOCK,1) - user.dna.SetSEState(FIREBLOCK,1) - genemutcheck(user,XRAYBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,TELEBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,INCREASERUNBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,SMALLSIZEBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,COLDBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,NOBREATHBLOCK,null,MUTCHK_FORCED) - genemutcheck(user,FIREBLOCK,null,MUTCHK_FORCED) - user.update_mutations() - to_chat(user, "You have been rewarded hanesomely with rare minerals and powers! ") - - if(prob(15)) - deactivated = 1 - user.visible_message("The dice shudders and loses its power! ") - name = "d20" - desc = "A die with twenty sides. The prefered die to throw at the GM." - else +/obj/item/weapon/dice + name = "d6" + desc = "A die with six sides. Basic and servicable." + icon = 'icons/obj/dice.dmi' + icon_state = "d6" + w_class = 1 + var/sides = 6 + var/minsides = 1 + var/result = null + +/obj/item/weapon/dice/New() + ..() + result = rand(minsides, sides) + update_icon() + +/obj/item/weapon/dice/d2 + name = "d2" + desc = "A die with two sides. Coins are undignified!" + icon_state = "d2" + sides = 2 + +/obj/item/weapon/dice/d4 + name = "d4" + desc = "A die with four sides. The nerd's caltrop." + icon_state = "d4" + sides = 4 + +/obj/item/weapon/dice/d8 + name = "d8" + desc = "A die with eight sides. It feels... lucky." + icon_state = "d8" + sides = 8 + +/obj/item/weapon/dice/d10 + name = "d10" + desc = "A die with ten sides. Useful for percentages." + icon_state = "d10" + sides = 10 + +/obj/item/weapon/dice/d00 + name = "d00" + desc = "A die with ten sides. Works better for d100 rolls than a golfball." + icon_state = "d00" + sides = 10 + +/obj/item/weapon/dice/d12 + name = "d12" + desc = "A die with twelve sides. There's an air of neglect about it." + icon_state = "d12" + sides = 12 + +/obj/item/weapon/dice/d20 + name = "d20" + desc = "A die with twenty sides. The prefered die to throw at the GM." + icon_state = "d20" + sides = 20 + +/obj/item/weapon/dice/d20/e20 + var/triggered = 0 + +/obj/item/weapon/dice/attack_self(mob/user as mob) + diceroll(user, 0) + +/obj/item/weapon/dice/throw_impact(atom/hit_atom, speed, user) + ..() + diceroll(user, 1) + +/obj/item/weapon/dice/proc/diceroll(mob/user as mob, thrown) + result = rand(minsides, sides) + var/comment = "" + if(sides == 20 && result == 20) + comment = "Nat 20!" + else if(sides == 20 && result == 1) + comment = "Ouch, bad luck." + update_icon() + if(initial(icon_state) == "d00") + result = (result - 1)*10 + if(!thrown) //Dice was rolled in someone's hand + user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \ + "You throw [src]. It lands on [result]. [comment]", \ + "You hear [src] landing on [result]. [comment]") + else if(src.throwing == 0) //Dice was thrown and is coming to rest + visible_message("[src] rolls to a stop, landing on [result]. [comment]") + +/obj/item/weapon/dice/d4/Crossed(var/mob/living/carbon/human/H) + if(istype(H) && !H.shoes) + to_chat(H, "You step on the D4!") + H.apply_damage(4,BRUTE,(pick("l_leg", "r_leg"))) + H.Weaken(3) + +/obj/item/weapon/dice/update_icon() + overlays.len = 0 + overlays += "[src.icon_state][src.result]" + +/obj/item/weapon/dice/d20/e20/diceroll(mob/user as mob, thrown) + if(!istype(user)) return 0 + if(triggered) return + ..() + message_admins("[key_name(user)] has [thrown? "used" : "thrown"] an explosive dice and rolled a [result]") + log_game("[key_name(user)] has [thrown? "used" : "thrown"] an explosive dice and rolled a [result]") + if(result == 1) + to_chat(user, "Rocks fall, you die.") + user.gib() + user.drop_item(src, force_drop = 1) + else + triggered = 1 + visible_message("You hear a quiet click.") + spawn(40) + var/cap = 0 + var/uncapped = result + if(result > MAX_EXPLOSION_RANGE && result != 20) + cap = 1 + result = min(result, MAX_EXPLOSION_RANGE) //Apply the bombcap + if(result > 14) + sleep(20) + else if(result == 20) //Roll a nat 20, screw the bombcap + result = 24 + sleep(40) + var/turf/epicenter = get_turf(src) + explosion(epicenter, round(result*0.25), round(result*0.5), round(result), round(result*1.5), 1, cap) + if(cap) + for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) + if(bhangmeter) + bhangmeter.sense_explosion(epicenter.x,epicenter.y,epicenter.z,round(uncapped*0.25), round(uncapped*0.5), round(uncapped),"???", cap) + + +/obj/item/weapon/dice/d20/cursed + desc = "Something about this dice seems wrong" + name = "\improper Mysterious d20" + var/deactivated = 0 //Eventually the dice runs out of power + +/obj/item/weapon/dice/d20/cursed/pickup(mob/user as mob) + ..() + if(deactivated == 0) + to_chat(user, "Are you feeling lucky?") + +/obj/item/weapon/dice/d20/cursed/diceroll(mob/user as mob, thrown) + ..() + if(deactivated == 0) //If the dice has power then something will happen + message_admins("[key_name(user)] has [thrown? "used" : "thrown"] a cursed dice and rolled a [result]") + log_game("[key_name(user)] has [thrown? "used" : "thrown"] a cursed dice and rolled a [result]") + if(istype(user,/mob/living/carbon/human)) //check that a humanoid is rolling the dice; Xenomorphs / Sillicons need not apply. + var/mob/living/carbon/human/h = user + switch(result) + if(1) + to_chat(user, "A natural failure, your poor roll has cursed you. Better luck next time! ") + flick("e_flash", user.flash) + h.Cluwneize() + if(2 to 5) + to_chat(user, "It could be worse, but not much worse! Enjoy your curse! ") + flick("e_flash", user.flash) + switch(pick(1,2,3)) + if(1) + if(h.species.name != "Tajaran") + if(h.set_species("Tajaran")) + h.regenerate_icons() + to_chat(user, "You have been turned into a disgusting catbeast! ") + else + for(var/datum/organ/external/E in h.organs) //Being a catbeast doesn't exempt you from getting a curse just because you cannot turn into a catbeast again. + E.droplimb(1) + if(2) + for(var/datum/organ/external/E in h.organs) + E.droplimb(1) + if(3) + user.reagents.add_reagent("amutationtoxin", 1) + to_chat(user, "You've been turned into a slime! ") + if(6 to 9) + to_chat(user, "You have rolled low and shall recieve a curse! It could be a lot worse however! ") + flick("e_flash", user.flash) + switch(pick(1,2,3,4)) + if(1) + user.dna.SetSEState(DEAFBLOCK,1) + user.dna.SetSEState(MUTEBLOCK,1) + user.dna.SetSEState(BLINDBLOCK,1) + genemutcheck(user,DEAFBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,MUTEBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,BLINDBLOCK,null,MUTCHK_FORCED) + user.update_mutations() + to_chat(user, "You've gone blind, deaf and mute! ") + if(2) + for(var/datum/organ/external/l_arm/E in h.organs) + E.droplimb(1) + for(var/datum/organ/external/r_arm/E in h.organs) + E.droplimb(2) + if(3) + if(h.species.name != "Tajaran") //someone who was made a catbeast by the dice can't become a different species by getting lucky + switch(pick(1,2,3)) + if(1) + if(h.species.name != "Unathi") + if(h.set_species("Unathi")) + h.regenerate_icons() + to_chat(user, "You have been turned into a disgusting lizard! ") + else + for(var/datum/organ/external/l_arm/E in h.organs) //Someone who has already become a lizard can't get out of recieving a curse and so they lose their arms instead + E.droplimb(1) + for(var/datum/organ/external/r_arm/E in h.organs) + E.droplimb(1) + if(2) + if(h.species.name != "Skrell") + if(h.set_species("Skrell")) + h.regenerate_icons() + to_chat(user, "You have been turned into a disgusting squidman! ") + else + for(var/datum/organ/external/l_arm/E in h.organs) //Someone who has already become a squid can't get out of recieving a curse and so they lose their arms instead + E.droplimb(1) + for(var/datum/organ/external/r_arm/E in h.organs) + E.droplimb(1) + if(3) + if(h.species.name != "Vox") + if(h.set_species("Vox")) + h.regenerate_icons() + to_chat(user, "You have been turned into a dumb, diseased bird! ") + else + for(var/datum/organ/external/l_arm/E in h.organs) //Someone who is a vox can't get out of recieving a curse and so they lose their arms instead + E.droplimb(1) + for(var/datum/organ/external/r_arm/E in h.organs) + E.droplimb(1) + if(4) + h.adjustBrainLoss(200) + user.reagents.add_reagent("nutriment", 1000) + user.overeatduration = 1000 + + to_chat(user, "In this moment you feel euphoric! ") + if(10 to 12) + to_chat(user, "You get nothing. No curse or reward! ") + if(13) + to_chat(user, "You've rolled 13! The cursed dice is broken! ") + explosion(get_turf(src), 0, 0, 4, 7) + to_chat(user, "The dice explosively shatters! ") + qdel(src) + + if(14 to 19) + to_chat(user, "You've rolled well and shall be rewarded! ") + switch(pick(1,2,3,4,5)) + if(1) + user.dna.SetSEState(INCREASERUNBLOCK,1) + user.dna.SetSEState(SMALLSIZEBLOCK,1) + genemutcheck(user,INCREASERUNBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,SMALLSIZEBLOCK,null,MUTCHK_FORCED) + user.update_mutations() + to_chat(user, "You have been made faster! ") + if(2) + user.dna.SetSEState(XRAYBLOCK,1) + user.dna.SetSEState(TELEBLOCK,1) + genemutcheck(user, XRAYBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,TELEBLOCK,null,MUTCHK_FORCED) + user.update_mutations() + to_chat(user, "You have been granted vision! ") + if(3) + user.dna.SetSEState(COLDBLOCK,1) + user.dna.SetSEState(FIREBLOCK,1) + user.dna.SetSEState(NOBREATHBLOCK,1) + genemutcheck(user,COLDBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,FIREBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,NOBREATHBLOCK,null,MUTCHK_FORCED) + user.update_mutations() + to_chat(user, "You have been granted protection! ") + if(4) + getFromPool(/obj/item/stack/sheet/mineral/gold,user.loc,50) + to_chat(user, "You have been reward in gold! ") + if(5) + getFromPool(/obj/item/stack/sheet/mineral/silver,user.loc,50) + to_chat(user, "You have been rewarded in silver! ") + if(20) + to_chat(user, "A perfect roll! enjoy your reward! ") + getFromPool(/obj/item/stack/sheet/mineral/phazon,user.loc,50) + getFromPool(/obj/item/stack/sheet/mineral/diamond,user.loc,50) + getFromPool(/obj/item/stack/sheet/mineral/clown,user.loc,50) + user.dna.SetSEState(XRAYBLOCK,1) + user.dna.SetSEState(TELEBLOCK,1) + user.dna.SetSEState(INCREASERUNBLOCK,1) + user.dna.SetSEState(SMALLSIZEBLOCK,1) + user.dna.SetSEState(COLDBLOCK,1) + user.dna.SetSEState(NOBREATHBLOCK,1) + user.dna.SetSEState(FIREBLOCK,1) + genemutcheck(user,XRAYBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,TELEBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,INCREASERUNBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,SMALLSIZEBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,COLDBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,NOBREATHBLOCK,null,MUTCHK_FORCED) + genemutcheck(user,FIREBLOCK,null,MUTCHK_FORCED) + user.update_mutations() + to_chat(user, "You have been rewarded hanesomely with rare minerals and powers! ") + + if(prob(15)) + deactivated = 1 + user.visible_message("The dice shudders and loses its power! ") + name = "d20" + desc = "A die with twenty sides. The prefered die to throw at the GM." + else return 0 \ No newline at end of file diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index ac369c78877..d3acc06c57b 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -1,1238 +1,1238 @@ -/obj/item/weapon/dnainjector - name = "DNA-Injector" - desc = "This injects the person with DNA." - icon = 'icons/obj/items.dmi' - icon_state = "dnainjector" - var/block=0 - var/datum/dna2/record/buf=null - var/s_time = 10.0 - throw_speed = 1 - throw_range = 5 - w_class = 1.0 - var/uses = 1 - var/nofail = 0 - var/is_bullet = 0 - var/inuse = 0 - - // USE ONLY IN PREMADE SYRINGES. WILL NOT WORK OTHERWISE. - var/datatype=0 - var/value=0 - -/obj/item/weapon/dnainjector/New() - . = ..() - - if(datatype && block) - buf=new - buf.dna=new - buf.types = datatype - buf.dna.ResetSE() - //testing("[name]: DNA2 SE blocks prior to SetValue: [english_list(buf.dna.SE)]") - SetValue(src.value) - //testing("[name]: DNA2 SE blocks after SetValue: [english_list(buf.dna.SE)]") - -/obj/item/weapon/dnainjector/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/item/weapon/dnainjector/proc/GetRealBlock(var/selblock) - if(selblock==0) - return block - else - return selblock - -/obj/item/weapon/dnainjector/proc/GetState(var/selblock=0) - var/real_block=GetRealBlock(selblock) - if(buf.types&DNA2_BUF_SE) - return buf.dna.GetSEState(real_block) - else - return buf.dna.GetUIState(real_block) - -/obj/item/weapon/dnainjector/proc/SetState(var/on, var/selblock=0) - var/real_block=GetRealBlock(selblock) - if(buf.types&DNA2_BUF_SE) - return buf.dna.SetSEState(real_block,on) - else - return buf.dna.SetUIState(real_block,on) - -/obj/item/weapon/dnainjector/proc/GetValue(var/selblock=0) - var/real_block=GetRealBlock(selblock) - if(buf.types&DNA2_BUF_SE) - return buf.dna.GetSEValue(real_block) - else - return buf.dna.GetUIValue(real_block) - -/obj/item/weapon/dnainjector/proc/SetValue(var/val,var/selblock=0) - var/real_block=GetRealBlock(selblock) - if(buf.types&DNA2_BUF_SE) - return buf.dna.SetSEValue(real_block,val) - else - return buf.dna.SetUIValue(real_block,val) - -/obj/item/weapon/dnainjector/proc/inject(mob/M as mob, mob/user as mob) - if(istype(M,/mob/living/carbon/human/manifested)) +/obj/item/weapon/dnainjector + name = "DNA-Injector" + desc = "This injects the person with DNA." + icon = 'icons/obj/items.dmi' + icon_state = "dnainjector" + var/block=0 + var/datum/dna2/record/buf=null + var/s_time = 10.0 + throw_speed = 1 + throw_range = 5 + w_class = 1.0 + var/uses = 1 + var/nofail = 0 + var/is_bullet = 0 + var/inuse = 0 + + // USE ONLY IN PREMADE SYRINGES. WILL NOT WORK OTHERWISE. + var/datatype=0 + var/value=0 + +/obj/item/weapon/dnainjector/New() + . = ..() + + if(datatype && block) + buf=new + buf.dna=new + buf.types = datatype + buf.dna.ResetSE() + //testing("[name]: DNA2 SE blocks prior to SetValue: [english_list(buf.dna.SE)]") + SetValue(src.value) + //testing("[name]: DNA2 SE blocks after SetValue: [english_list(buf.dna.SE)]") + +/obj/item/weapon/dnainjector/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/item/weapon/dnainjector/proc/GetRealBlock(var/selblock) + if(selblock==0) + return block + else + return selblock + +/obj/item/weapon/dnainjector/proc/GetState(var/selblock=0) + var/real_block=GetRealBlock(selblock) + if(buf.types&DNA2_BUF_SE) + return buf.dna.GetSEState(real_block) + else + return buf.dna.GetUIState(real_block) + +/obj/item/weapon/dnainjector/proc/SetState(var/on, var/selblock=0) + var/real_block=GetRealBlock(selblock) + if(buf.types&DNA2_BUF_SE) + return buf.dna.SetSEState(real_block,on) + else + return buf.dna.SetUIState(real_block,on) + +/obj/item/weapon/dnainjector/proc/GetValue(var/selblock=0) + var/real_block=GetRealBlock(selblock) + if(buf.types&DNA2_BUF_SE) + return buf.dna.GetSEValue(real_block) + else + return buf.dna.GetUIValue(real_block) + +/obj/item/weapon/dnainjector/proc/SetValue(var/val,var/selblock=0) + var/real_block=GetRealBlock(selblock) + if(buf.types&DNA2_BUF_SE) + return buf.dna.SetSEValue(real_block,val) + else + return buf.dna.SetUIValue(real_block,val) + +/obj/item/weapon/dnainjector/proc/inject(mob/M as mob, mob/user as mob) + if(istype(M,/mob/living/carbon/human/manifested)) to_chat(M, " Apparently it didn't work.") - if(M != user) + if(M != user) to_chat(user, " Apparently it didn't work.") - else - if(istype(M,/mob/living)) - M.radiation += rand(5,20) - - if(!(M_NOCLONE in M.mutations)) // prevents drained people from having their DNA changed - // UI in syringe. - if(buf.types & DNA2_BUF_UI) - if(!block) //isolated block? - M.UpdateAppearance(buf.dna.UI.Copy()) - if (buf.types & DNA2_BUF_UE) //unique enzymes? yes - M.real_name = buf.dna.real_name - M.name = buf.dna.real_name - uses-- - else - M.dna.SetUIValue(block,src.GetValue()) - M.UpdateAppearance() - uses-- - if(buf.types & DNA2_BUF_SE) - if(!block) //isolated block? - M.dna.SE = buf.dna.SE.Copy() - M.dna.UpdateSE() - else - M.dna.SetSEValue(block,src.GetValue()) - domutcheck(M, null, nofail) - uses-- - //if(prob(5)) - //trigger_side_effect(M) - - spawn(0)//this prevents the collapse of space-time continuum - if(user) - user.drop_from_inventory(src) - if(!uses) - qdel(src) - return uses - -/obj/item/weapon/dnainjector/attack(mob/M as mob, mob/user as mob) - if (!istype(M, /mob)) - return - if (!user.dexterity_check()) + else + if(istype(M,/mob/living)) + M.radiation += rand(5,20) + + if(!(M_NOCLONE in M.mutations)) // prevents drained people from having their DNA changed + // UI in syringe. + if(buf.types & DNA2_BUF_UI) + if(!block) //isolated block? + M.UpdateAppearance(buf.dna.UI.Copy()) + if (buf.types & DNA2_BUF_UE) //unique enzymes? yes + M.real_name = buf.dna.real_name + M.name = buf.dna.real_name + uses-- + else + M.dna.SetUIValue(block,src.GetValue()) + M.UpdateAppearance() + uses-- + if(buf.types & DNA2_BUF_SE) + if(!block) //isolated block? + M.dna.SE = buf.dna.SE.Copy() + M.dna.UpdateSE() + else + M.dna.SetSEValue(block,src.GetValue()) + domutcheck(M, null, nofail) + uses-- + //if(prob(5)) + //trigger_side_effect(M) + + spawn(0)//this prevents the collapse of space-time continuum + if(user) + user.drop_from_inventory(src) + if(!uses) + qdel(src) + return uses + +/obj/item/weapon/dnainjector/attack(mob/M as mob, mob/user as mob) + if (!istype(M, /mob)) + return + if (!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") - return - - M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.ckey])") - log_attack("[user.name] ([user.ckey]) used the [name] to inject [M.name] ([M.ckey])") - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - if (user) - if (istype(M, /mob/living/carbon/human)) - if(!inuse) - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = user - O.target = M - O.item = src - O.s_loc = user.loc - O.t_loc = M.loc - O.place = "dnainjector" - src.inuse = 1 - spawn(50) // Not the best fix. There should be an failure proc, for /effect/equip_e/, which is called when the first initital checks fail - inuse = 0 - M.requests += O - if (buf.types & DNA2_BUF_SE) - if(block)// Isolated injector - //testing("Isolated block [block] injector with contents: [GetValue()]") - if (GetState() && block == MONKEYBLOCK && istype(M, /mob/living/carbon/human) ) - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name] (MONKEY)") - log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - else - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name]") - else - //testing("DNA injector with contents: [english_list(buf.dna.SE)]") - if (GetState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human) ) - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)") - log_attack("[key_name(user)] injected [key_name(M)] with the [name] (MONKEY)") - log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)") - else - // message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") - log_attack("[key_name(user)] injected [key_name(M)] with the [name]") - else - // message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") - log_attack("[key_name(user)] injected [key_name(M)] with the [name]") - - spawn( 0 ) - O.process() - return - else - if(!inuse) - - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] has been injected with [] by [].", M, src, user), 1) - //Foreach goto(192) - if (!(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))) + return + + M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.ckey])") + log_attack("[user.name] ([user.ckey]) used the [name] to inject [M.name] ([M.ckey])") + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + if (user) + if (istype(M, /mob/living/carbon/human)) + if(!inuse) + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = user + O.target = M + O.item = src + O.s_loc = user.loc + O.t_loc = M.loc + O.place = "dnainjector" + src.inuse = 1 + spawn(50) // Not the best fix. There should be an failure proc, for /effect/equip_e/, which is called when the first initital checks fail + inuse = 0 + M.requests += O + if (buf.types & DNA2_BUF_SE) + if(block)// Isolated injector + //testing("Isolated block [block] injector with contents: [GetValue()]") + if (GetState() && block == MONKEYBLOCK && istype(M, /mob/living/carbon/human) ) + message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") + log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name] (MONKEY)") + log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") + else + log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name]") + else + //testing("DNA injector with contents: [english_list(buf.dna.SE)]") + if (GetState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human) ) + message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)") + log_attack("[key_name(user)] injected [key_name(M)] with the [name] (MONKEY)") + log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)") + else + // message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") + log_attack("[key_name(user)] injected [key_name(M)] with the [name]") + else + // message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") + log_attack("[key_name(user)] injected [key_name(M)] with the [name]") + + spawn( 0 ) + O.process() + return + else + if(!inuse) + + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] has been injected with [] by [].", M, src, user), 1) + //Foreach goto(192) + if (!(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey))) to_chat(user, "Apparently it didn't work.") - return - - if (buf.types & DNA2_BUF_SE) - if(block)// Isolated injector - //testing("Isolated block [block] injector with contents: [GetValue()]") - if (GetState() && block == MONKEYBLOCK && istype(M, /mob/living/carbon/human) ) - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name] (MONKEY)") - log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") - else - log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name]") - else - //testing("DNA injector with contents: [english_list(buf.dna.SE)]") - if (GetState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human)) - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)") - log_game("[key_name(user)] injected [key_name(M)] with the [name] (MONKEY)") - else - // message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") - log_game("[key_name(user)] injected [key_name(M)] with the [name]") - else -// message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") - log_game("[key_name(user)] injected [key_name(M)] with the [name]") - inuse = 1 - inject(M, user)//Now we actually do the heavy lifting. - spawn(50) - inuse = 0 - /* - A user injecting themselves could mean their own transformation and deletion of mob. - I don't have the time to figure out how this code works so this will do for now. - I did rearrange things a bit. - */ - if(user)//If the user still exists. Their mob may not. - if(M)//Runtime fix: If the mob doesn't exist, mob.name doesnt work. - Nodrak - user.show_message(text("You inject [M.name].")) - else - user.show_message(text("You finish the injection.")) - return - -/obj/item/weapon/dnainjector/nofail - nofail = MUTCHK_FORCED - -/obj/item/weapon/dnainjector/nofail/hulkmut - name = "DNA-Injector (Hulk)" - desc = "This will make you big and strong, but give you a bad skin condition." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = HULKBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antihulk - name = "DNA-Injector (Anti-Hulk)" - desc = "Cures green skin." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = HULKBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/xraymut - name = "DNA-Injector (Xray)" - desc = "Finally you can see what the Captain does." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 8 - New() - block = XRAYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antixray - name = "DNA-Injector (Anti-Xray)" - desc = "It will make you see harder." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 8 - New() - block = XRAYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/firemut - name = "DNA-Injector (Fire)" - desc = "Gives you fire." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 10 - New() - block = FIREBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antifire - name = "DNA-Injector (Anti-Fire)" - desc = "Cures fire." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 10 - New() - block = FIREBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/telemut - name = "DNA-Injector (Tele.)" - desc = "Super brain man!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 12 - New() - block = TELEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antitele - name = "DNA-Injector (Anti-Tele.)" - desc = "Will make you not able to control your mind." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 12 - New() - block = TELEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/nobreath - name = "DNA-Injector (No Breath)" - desc = "Hold your breath and count to infinity." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = NOBREATHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antinobreath - name = "DNA-Injector (Anti-No Breath)" - desc = "Hold your breath and count to 100." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = NOBREATHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/remoteview - name = "DNA-Injector (Remote View)" - desc = "Stare into the distance for a reason." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = REMOTEVIEWBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiremoteview - name = "DNA-Injector (Anti-Remote View)" - desc = "Cures green skin." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = REMOTEVIEWBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/regenerate - name = "DNA-Injector (Regeneration)" - desc = "Healthy but hungry." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = REGENERATEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiregenerate - name = "DNA-Injector (Anti-Regeneration)" - desc = "Sickly but sated." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = REGENERATEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/runfast - name = "DNA-Injector (Increase Run)" - desc = "Running Man." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = INCREASERUNBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antirunfast - name = "DNA-Injector (Anti-Increase Run)" - desc = "Walking Man." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = INCREASERUNBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/morph - name = "DNA-Injector (Morph)" - desc = "A total makeover." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = MORPHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antimorph - name = "DNA-Injector (Anti-Morph)" - desc = "Cures identity crisis." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = MORPHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/cold - name = "DNA-Injector (Cold)" - desc = "Feels a bit chilly." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = COLDBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/anticold - name = "DNA-Injector (Anti-Cold)" - desc = "Feels room-temperature." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = COLDBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/noprints - name = "DNA-Injector (No Prints)" - desc = "Better than a pair of budget insulated gloves." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = NOPRINTSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antinoprints - name = "DNA-Injector (Anti-No Prints)" - desc = "Not quite as good as a pair of budget insulated gloves." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = NOPRINTSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/insulation - name = "DNA-Injector (Shock Immunity)" - desc = "Better than a pair of real insulated gloves." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = SHOCKIMMUNITYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiinsulation - name = "DNA-Injector (Anti-Shock Immunity)" - desc = "Not quite as good as a pair of real insulated gloves." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = SHOCKIMMUNITYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/midgit - name = "DNA-Injector (Small Size)" - desc = "Makes you shrink." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = SMALLSIZEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antimidgit - name = "DNA-Injector (Anti-Small Size)" - desc = "Makes you grow. But not too much." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = SMALLSIZEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/sober - name = "DNA-Injector (Sober)" - desc = "Makes you not fun." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = SOBERBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antisober - name = "DNA-Injector (Anti-Sober)" - desc = "Makes you fun as hell." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = SOBERBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/psychic_resist - name = "DNA-Injector (Psychic Resist)" - desc = "Not today, mind hippies." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = PSYRESISTBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/antipsychic_resist - name = "DNA-Injector (Anti-Psychic Resist)" - desc = "Im thinking about furry porn 24/7. Come at me, faggots." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = PSYRESISTBLOCK - ..() - -/*/obj/item/weapon/dnainjector/nofail/darkcloak - name = "DNA-Injector (Dark Cloak)" - desc = "BLEH BLEH, I AM HERE TO SUCK YOUR BLOOD!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = SHADOWBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antidarkcloak - name = "DNA-Injector (Anti-Dark Cloak)" - desc = "THE LIGHT, IT BUUURNS!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = SHADOWBLOCK - ..() -*/ -/obj/item/weapon/dnainjector/nofail/chameleon - name = "DNA-Injector (Chameleon)" - desc = "You cant see me." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = CHAMELEONBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antichameleon - name = "DNA-Injector (Anti-Chameleon)" - desc = "OH GOD EVERYONE CAN SEE ME!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = CHAMELEONBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/cryo - name = "DNA-Injector (Cryokinesis)" - desc = "Its about to get chilly." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = CRYOBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/anticryo - name = "DNA-Injector (Anti-Cryokinesis)" - desc = "Fuck, its hot in here!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = CRYOBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/mattereater - name = "DNA-Injector (Matter Eater)" - desc = "OM NOM NOM." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = EATBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antimattereater - name = "DNA-Injector (Anti-Matter Eater)" - desc = "Oh god I'm gonna puke." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = EATBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/jumpy - name = "DNA-Injector (Jumpy)" - desc = "WEEEEEEEEEEEE!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = JUMPBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antijumpy - name = "DNA-Injector (Anti-Jumpy)" - desc = "Awwe.." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = JUMPBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/polymorph - name = "DNA-Injector (Polymorph)" - desc = "A clone of myself? Now neither of us will be virgins!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = POLYMORPHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antipolymorph - name = "DNA-Injector (Anti-Polymorph)" - desc = "Damn, friendzoned by my own clone." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = POLYMORPHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/empath - name = "DNA-Injector (Empathic Thought)" - desc = "What will I have for dinner?" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = EMPATHBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/antiempath - name = "DNA-Injector (Anti-Empathic Thought)" - desc = "Damn tin foil hats." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = EMPATHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/superfart - name = "DNA-Injector (Super Fart)" - desc = "Really?" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = SUPERFARTBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antisuperfart - name = "DNA-Injector (Anti-Super Fart)" - desc = "No, really!?" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = SUPERFARTBLOCK - ..() - -///////////////////////////////////// -/obj/item/weapon/dnainjector/nofail/antiglasses - name = "DNA-Injector (Anti-Glasses)" - desc = "Toss away those glasses!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 1 - New() - block = GLASSESBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/glassesmut - name = "DNA-Injector (Glasses)" - desc = "Will make you need dorkish glasses." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 1 - New() - block = GLASSESBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/epimut - name = "DNA-Injector (Epi.)" - desc = "Shake shake shake the room!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 3 - New() - block = HEADACHEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiepi - name = "DNA-Injector (Anti-Epi.)" - desc = "Will fix you up from shaking the room." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 3 - New() - block = HEADACHEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/anticough - name = "DNA-Injector (Anti-Cough)" - desc = "Will stop that awful noise." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 5 - New() - block = COUGHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/coughmut - name = "DNA-Injector (Cough)" - desc = "Will bring forth a sound of horror from your throat." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 5 - New() - block = COUGHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/clumsymut - name = "DNA-Injector (Clumsy)" - desc = "Makes clumsy minions." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 6 - New() - block = CLUMSYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/anticlumsy - name = "DNA-Injector (Anti-Clumy)" - desc = "Cleans up confusion." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 6 - New() - block = CLUMSYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antitour - name = "DNA-Injector (Anti-Tour.)" - desc = "Will cure tourrets." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 7 - New() - block = TWITCHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/tourmut - name = "DNA-Injector (Tour.)" - desc = "Gives you a nasty case off tourrets." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 7 - New() - block = TWITCHBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/stuttmut - name = "DNA-Injector (Stutt.)" - desc = "Makes you s-s-stuttterrr" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 9 - New() - block = NERVOUSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antistutt - name = "DNA-Injector (Anti-Stutt.)" - desc = "Fixes that speaking impairment." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 9 - New() - block = NERVOUSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/blindmut - name = "DNA-Injector (Blind)" - desc = "Makes you not see anything." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 11 - New() - block = BLINDBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiblind - name = "DNA-Injector (Anti-Blind)" - desc = "ITS A MIRACLE!!!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 11 - New() - block = BLINDBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/deafmut - name = "DNA-Injector (Deaf)" - desc = "Sorry, what did you say?" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 13 - New() - block = DEAFBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antideaf - name = "DNA-Injector (Anti-Deaf)" - desc = "Will make you hear once more." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 13 - New() - block = DEAFBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/hallucination - name = "DNA-Injector (Halluctination)" - desc = "What you see isn't always what you get." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = HALLUCINATIONBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antihallucination - name = "DNA-Injector (Anti-Hallucination)" - desc = "What you see is what you get." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = HALLUCINATIONBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/h2m - name = "DNA-Injector (Human > Monkey)" - desc = "Will make you a flea bag." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = MONKEYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/m2h - name = "DNA-Injector (Monkey > Human)" - desc = "Will make you...less hairy." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = MONKEYBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/mute - name = "DNA-Injector (Mute)" - desc = "Hell." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = MUTEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antimute - name = "DNA-Injector (Anti-Mute)" - desc = "Shut up." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = MUTEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/radioactive - name = "DNA-Injector (Radioactive)" - desc = "Welcome to the new age." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = RADBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiradioactive - name = "DNA-Injector (Anti-Radioactive)" - desc = "All systems go." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = RADBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/fat - name = "DNA-Injector (Fat)" - desc = "Gives you big bones." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = FATBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antifat - name = "DNA-Injector (Anti-Fat)" - desc = "Feeds you subway." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = FATBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/chav - name = "DNA-Injector (Chav)" - desc = "Makes you a real arsehole." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = CHAVBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antichav - name = "DNA-Injector (Anti-Chav)" - desc = "Put it back, I liked you better that way." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = CHAVBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/sweedish - name = "DNA-Injector (Sweedish)" - desc = "BORK! BORK! BORK!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = SWEDEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antisweedish - name = "DNA-Injector (Anti-Sweedish)" - desc = "You're no fun." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = SWEDEBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/unintelligable - name = "DNA-Injector (Unintelligable)" - desc = "At?wh" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = SCRAMBLEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiunintelligable - name = "DNA-Injector (Anti-Unintelligable)" - desc = "What?" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = SCRAMBLEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/strong - name = "DNA-Injector (Strong)" - desc = "HEY BRO, WANNA HIT THE GYM?" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = STRONGBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antistrong - name = "DNA-Injector (Anti-Strong)" - desc = "Spot me!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = STRONGBLOCK - ..() - - -/obj/item/weapon/dnainjector/nofail/horns - name = "DNA-Injector (Horns)" - desc = "Feelin' horny?" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = HORNSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antihorns - name = "DNA-Injector (Anti-Horns)" - desc = "Right, lets just watch Law & Order." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = HORNSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/immolate - name = "DNA-Injector (Immolate)" - desc = "We didn't start the fire." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = IMMOLATEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiimmolate - name = "DNA-Injector (Anti-Immolate)" - desc = "It was always burnin' since the world was turnin'" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = IMMOLATEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/melt - name = "DNA-Injector (Dissolve)" - desc = "Win the game." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = MELTBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antimelt - name = "DNA-Injector (Dissolve)" - desc = "You just lost the game." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = MELTBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/smile - name = "DNA-Injector (Smile)" - desc = ":)" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = SMILEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antismile - name = "DNA-Injector (Anti-Smile)" - desc = ":(" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = SMILEBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/elvis - name = "DNA-Injector (Elvis)" - desc = "Tell the folks back home this is the promised land calling" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = ELVISBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antielvis - name = "DNA-Injector (Anti-Elvis)" - desc = "And the poor boy is on the line." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = ELVISBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/loud - name = "DNA-Injector (Loud)" - desc = "CAPS LOCK IS CRUISE CONRTOL FOR COOL!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = LOUDBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiloud - name = "DNA-Injector (Anti-Loud)" - desc = "EVEN WITH CRUISE CONTROL, YOU STILL HAVE TO STEER!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = LOUDBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/whisper - name = "DNA-Injector (Quiet)" - desc = "Shhh..." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = WHISPERBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiwhisper - name = "DNA-Injector (Anti-Quiet)" - desc = "WOOOO HOOOO!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = WHISPERBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/dizzy - name = "DNA-Injector (Dizzy)" - desc = "Touch fuzzy," - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = DIZZYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antidizzy - name = "DNA-Injector (Anti-Dizzy)" - desc = "Get dizzy." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = DIZZYBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/sans - name = "DNA-Injector (Wacky)" - desc = "#wow #woah" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - New() - block = SANSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antisans - name = "DNA-Injector (Anti-Wacky)" - desc = "Worst font." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - New() - block = SANSBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/farsightmut - name = "DNA-Injector (Farsight)" - desc = "This will allow you to focus your eyes better." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - New() - block = FARSIGHTBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antifarsight - name = "DNA-Injector (Anti-Farsight)" - desc = "No fun allowed" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - New() - block = FARSIGHTBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/remotesay - name = "DNA-Injector (Remote Say)" - desc = "Share it with the world." - datatype = DNA2_BUF_SE - value = 0xFFF - New() - block = REMOTETALKBLOCK - ..() - -/obj/item/weapon/dnainjector/nofail/antiremotesay - name = "DNA-Injector (Remote Say)" - desc = "Keep it to yourself." - datatype = DNA2_BUF_SE - value = 0x001 - New() - block = REMOTETALKBLOCK - ..() + return + + if (buf.types & DNA2_BUF_SE) + if(block)// Isolated injector + //testing("Isolated block [block] injector with contents: [GetValue()]") + if (GetState() && block == MONKEYBLOCK && istype(M, /mob/living/carbon/human) ) + message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") + log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name] (MONKEY)") + log_game("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") + else + log_attack("[key_name(user)] injected [key_name(M)] with the Isolated [name]") + else + //testing("DNA injector with contents: [english_list(buf.dna.SE)]") + if (GetState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human)) + message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] (MONKEY)") + log_game("[key_name(user)] injected [key_name(M)] with the [name] (MONKEY)") + else + // message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") + log_game("[key_name(user)] injected [key_name(M)] with the [name]") + else +// message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name]") + log_game("[key_name(user)] injected [key_name(M)] with the [name]") + inuse = 1 + inject(M, user)//Now we actually do the heavy lifting. + spawn(50) + inuse = 0 + /* + A user injecting themselves could mean their own transformation and deletion of mob. + I don't have the time to figure out how this code works so this will do for now. + I did rearrange things a bit. + */ + if(user)//If the user still exists. Their mob may not. + if(M)//Runtime fix: If the mob doesn't exist, mob.name doesnt work. - Nodrak + user.show_message(text("You inject [M.name].")) + else + user.show_message(text("You finish the injection.")) + return + +/obj/item/weapon/dnainjector/nofail + nofail = MUTCHK_FORCED + +/obj/item/weapon/dnainjector/nofail/hulkmut + name = "DNA-Injector (Hulk)" + desc = "This will make you big and strong, but give you a bad skin condition." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = HULKBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antihulk + name = "DNA-Injector (Anti-Hulk)" + desc = "Cures green skin." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = HULKBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/xraymut + name = "DNA-Injector (Xray)" + desc = "Finally you can see what the Captain does." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 8 + New() + block = XRAYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antixray + name = "DNA-Injector (Anti-Xray)" + desc = "It will make you see harder." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 8 + New() + block = XRAYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/firemut + name = "DNA-Injector (Fire)" + desc = "Gives you fire." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 10 + New() + block = FIREBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antifire + name = "DNA-Injector (Anti-Fire)" + desc = "Cures fire." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 10 + New() + block = FIREBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/telemut + name = "DNA-Injector (Tele.)" + desc = "Super brain man!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 12 + New() + block = TELEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antitele + name = "DNA-Injector (Anti-Tele.)" + desc = "Will make you not able to control your mind." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 12 + New() + block = TELEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/nobreath + name = "DNA-Injector (No Breath)" + desc = "Hold your breath and count to infinity." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = NOBREATHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antinobreath + name = "DNA-Injector (Anti-No Breath)" + desc = "Hold your breath and count to 100." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = NOBREATHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/remoteview + name = "DNA-Injector (Remote View)" + desc = "Stare into the distance for a reason." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = REMOTEVIEWBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiremoteview + name = "DNA-Injector (Anti-Remote View)" + desc = "Cures green skin." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = REMOTEVIEWBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/regenerate + name = "DNA-Injector (Regeneration)" + desc = "Healthy but hungry." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = REGENERATEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiregenerate + name = "DNA-Injector (Anti-Regeneration)" + desc = "Sickly but sated." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = REGENERATEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/runfast + name = "DNA-Injector (Increase Run)" + desc = "Running Man." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = INCREASERUNBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antirunfast + name = "DNA-Injector (Anti-Increase Run)" + desc = "Walking Man." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = INCREASERUNBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/morph + name = "DNA-Injector (Morph)" + desc = "A total makeover." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = MORPHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antimorph + name = "DNA-Injector (Anti-Morph)" + desc = "Cures identity crisis." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = MORPHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/cold + name = "DNA-Injector (Cold)" + desc = "Feels a bit chilly." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = COLDBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/anticold + name = "DNA-Injector (Anti-Cold)" + desc = "Feels room-temperature." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = COLDBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/noprints + name = "DNA-Injector (No Prints)" + desc = "Better than a pair of budget insulated gloves." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = NOPRINTSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antinoprints + name = "DNA-Injector (Anti-No Prints)" + desc = "Not quite as good as a pair of budget insulated gloves." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = NOPRINTSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/insulation + name = "DNA-Injector (Shock Immunity)" + desc = "Better than a pair of real insulated gloves." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = SHOCKIMMUNITYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiinsulation + name = "DNA-Injector (Anti-Shock Immunity)" + desc = "Not quite as good as a pair of real insulated gloves." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = SHOCKIMMUNITYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/midgit + name = "DNA-Injector (Small Size)" + desc = "Makes you shrink." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = SMALLSIZEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antimidgit + name = "DNA-Injector (Anti-Small Size)" + desc = "Makes you grow. But not too much." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = SMALLSIZEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/sober + name = "DNA-Injector (Sober)" + desc = "Makes you not fun." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = SOBERBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antisober + name = "DNA-Injector (Anti-Sober)" + desc = "Makes you fun as hell." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = SOBERBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/psychic_resist + name = "DNA-Injector (Psychic Resist)" + desc = "Not today, mind hippies." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = PSYRESISTBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/antipsychic_resist + name = "DNA-Injector (Anti-Psychic Resist)" + desc = "Im thinking about furry porn 24/7. Come at me, faggots." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = PSYRESISTBLOCK + ..() + +/*/obj/item/weapon/dnainjector/nofail/darkcloak + name = "DNA-Injector (Dark Cloak)" + desc = "BLEH BLEH, I AM HERE TO SUCK YOUR BLOOD!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = SHADOWBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antidarkcloak + name = "DNA-Injector (Anti-Dark Cloak)" + desc = "THE LIGHT, IT BUUURNS!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = SHADOWBLOCK + ..() +*/ +/obj/item/weapon/dnainjector/nofail/chameleon + name = "DNA-Injector (Chameleon)" + desc = "You cant see me." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = CHAMELEONBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antichameleon + name = "DNA-Injector (Anti-Chameleon)" + desc = "OH GOD EVERYONE CAN SEE ME!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = CHAMELEONBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/cryo + name = "DNA-Injector (Cryokinesis)" + desc = "Its about to get chilly." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = CRYOBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/anticryo + name = "DNA-Injector (Anti-Cryokinesis)" + desc = "Fuck, its hot in here!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = CRYOBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/mattereater + name = "DNA-Injector (Matter Eater)" + desc = "OM NOM NOM." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = EATBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antimattereater + name = "DNA-Injector (Anti-Matter Eater)" + desc = "Oh god I'm gonna puke." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = EATBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/jumpy + name = "DNA-Injector (Jumpy)" + desc = "WEEEEEEEEEEEE!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = JUMPBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antijumpy + name = "DNA-Injector (Anti-Jumpy)" + desc = "Awwe.." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = JUMPBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/polymorph + name = "DNA-Injector (Polymorph)" + desc = "A clone of myself? Now neither of us will be virgins!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = POLYMORPHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antipolymorph + name = "DNA-Injector (Anti-Polymorph)" + desc = "Damn, friendzoned by my own clone." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = POLYMORPHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/empath + name = "DNA-Injector (Empathic Thought)" + desc = "What will I have for dinner?" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = EMPATHBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/antiempath + name = "DNA-Injector (Anti-Empathic Thought)" + desc = "Damn tin foil hats." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = EMPATHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/superfart + name = "DNA-Injector (Super Fart)" + desc = "Really?" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = SUPERFARTBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antisuperfart + name = "DNA-Injector (Anti-Super Fart)" + desc = "No, really!?" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = SUPERFARTBLOCK + ..() + +///////////////////////////////////// +/obj/item/weapon/dnainjector/nofail/antiglasses + name = "DNA-Injector (Anti-Glasses)" + desc = "Toss away those glasses!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 1 + New() + block = GLASSESBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/glassesmut + name = "DNA-Injector (Glasses)" + desc = "Will make you need dorkish glasses." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 1 + New() + block = GLASSESBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/epimut + name = "DNA-Injector (Epi.)" + desc = "Shake shake shake the room!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 3 + New() + block = HEADACHEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiepi + name = "DNA-Injector (Anti-Epi.)" + desc = "Will fix you up from shaking the room." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 3 + New() + block = HEADACHEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/anticough + name = "DNA-Injector (Anti-Cough)" + desc = "Will stop that awful noise." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 5 + New() + block = COUGHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/coughmut + name = "DNA-Injector (Cough)" + desc = "Will bring forth a sound of horror from your throat." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 5 + New() + block = COUGHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/clumsymut + name = "DNA-Injector (Clumsy)" + desc = "Makes clumsy minions." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 6 + New() + block = CLUMSYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/anticlumsy + name = "DNA-Injector (Anti-Clumy)" + desc = "Cleans up confusion." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 6 + New() + block = CLUMSYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antitour + name = "DNA-Injector (Anti-Tour.)" + desc = "Will cure tourrets." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 7 + New() + block = TWITCHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/tourmut + name = "DNA-Injector (Tour.)" + desc = "Gives you a nasty case off tourrets." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 7 + New() + block = TWITCHBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/stuttmut + name = "DNA-Injector (Stutt.)" + desc = "Makes you s-s-stuttterrr" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 9 + New() + block = NERVOUSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antistutt + name = "DNA-Injector (Anti-Stutt.)" + desc = "Fixes that speaking impairment." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 9 + New() + block = NERVOUSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/blindmut + name = "DNA-Injector (Blind)" + desc = "Makes you not see anything." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 11 + New() + block = BLINDBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiblind + name = "DNA-Injector (Anti-Blind)" + desc = "ITS A MIRACLE!!!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 11 + New() + block = BLINDBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/deafmut + name = "DNA-Injector (Deaf)" + desc = "Sorry, what did you say?" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 13 + New() + block = DEAFBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antideaf + name = "DNA-Injector (Anti-Deaf)" + desc = "Will make you hear once more." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 13 + New() + block = DEAFBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/hallucination + name = "DNA-Injector (Halluctination)" + desc = "What you see isn't always what you get." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = HALLUCINATIONBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antihallucination + name = "DNA-Injector (Anti-Hallucination)" + desc = "What you see is what you get." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = HALLUCINATIONBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/h2m + name = "DNA-Injector (Human > Monkey)" + desc = "Will make you a flea bag." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = MONKEYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/m2h + name = "DNA-Injector (Monkey > Human)" + desc = "Will make you...less hairy." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = MONKEYBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/mute + name = "DNA-Injector (Mute)" + desc = "Hell." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = MUTEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antimute + name = "DNA-Injector (Anti-Mute)" + desc = "Shut up." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = MUTEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/radioactive + name = "DNA-Injector (Radioactive)" + desc = "Welcome to the new age." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = RADBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiradioactive + name = "DNA-Injector (Anti-Radioactive)" + desc = "All systems go." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = RADBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/fat + name = "DNA-Injector (Fat)" + desc = "Gives you big bones." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = FATBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antifat + name = "DNA-Injector (Anti-Fat)" + desc = "Feeds you subway." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = FATBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/chav + name = "DNA-Injector (Chav)" + desc = "Makes you a real arsehole." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = CHAVBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antichav + name = "DNA-Injector (Anti-Chav)" + desc = "Put it back, I liked you better that way." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = CHAVBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/sweedish + name = "DNA-Injector (Sweedish)" + desc = "BORK! BORK! BORK!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = SWEDEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antisweedish + name = "DNA-Injector (Anti-Sweedish)" + desc = "You're no fun." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = SWEDEBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/unintelligable + name = "DNA-Injector (Unintelligable)" + desc = "At?wh" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = SCRAMBLEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiunintelligable + name = "DNA-Injector (Anti-Unintelligable)" + desc = "What?" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = SCRAMBLEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/strong + name = "DNA-Injector (Strong)" + desc = "HEY BRO, WANNA HIT THE GYM?" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = STRONGBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antistrong + name = "DNA-Injector (Anti-Strong)" + desc = "Spot me!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = STRONGBLOCK + ..() + + +/obj/item/weapon/dnainjector/nofail/horns + name = "DNA-Injector (Horns)" + desc = "Feelin' horny?" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = HORNSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antihorns + name = "DNA-Injector (Anti-Horns)" + desc = "Right, lets just watch Law & Order." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = HORNSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/immolate + name = "DNA-Injector (Immolate)" + desc = "We didn't start the fire." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = IMMOLATEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiimmolate + name = "DNA-Injector (Anti-Immolate)" + desc = "It was always burnin' since the world was turnin'" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = IMMOLATEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/melt + name = "DNA-Injector (Dissolve)" + desc = "Win the game." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = MELTBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antimelt + name = "DNA-Injector (Dissolve)" + desc = "You just lost the game." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = MELTBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/smile + name = "DNA-Injector (Smile)" + desc = ":)" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = SMILEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antismile + name = "DNA-Injector (Anti-Smile)" + desc = ":(" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = SMILEBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/elvis + name = "DNA-Injector (Elvis)" + desc = "Tell the folks back home this is the promised land calling" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = ELVISBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antielvis + name = "DNA-Injector (Anti-Elvis)" + desc = "And the poor boy is on the line." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = ELVISBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/loud + name = "DNA-Injector (Loud)" + desc = "CAPS LOCK IS CRUISE CONRTOL FOR COOL!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = LOUDBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiloud + name = "DNA-Injector (Anti-Loud)" + desc = "EVEN WITH CRUISE CONTROL, YOU STILL HAVE TO STEER!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = LOUDBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/whisper + name = "DNA-Injector (Quiet)" + desc = "Shhh..." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = WHISPERBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiwhisper + name = "DNA-Injector (Anti-Quiet)" + desc = "WOOOO HOOOO!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = WHISPERBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/dizzy + name = "DNA-Injector (Dizzy)" + desc = "Touch fuzzy," + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = DIZZYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antidizzy + name = "DNA-Injector (Anti-Dizzy)" + desc = "Get dizzy." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = DIZZYBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/sans + name = "DNA-Injector (Wacky)" + desc = "#wow #woah" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + New() + block = SANSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antisans + name = "DNA-Injector (Anti-Wacky)" + desc = "Worst font." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + New() + block = SANSBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/farsightmut + name = "DNA-Injector (Farsight)" + desc = "This will allow you to focus your eyes better." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + New() + block = FARSIGHTBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antifarsight + name = "DNA-Injector (Anti-Farsight)" + desc = "No fun allowed" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + New() + block = FARSIGHTBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/remotesay + name = "DNA-Injector (Remote Say)" + desc = "Share it with the world." + datatype = DNA2_BUF_SE + value = 0xFFF + New() + block = REMOTETALKBLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiremotesay + name = "DNA-Injector (Remote Say)" + desc = "Keep it to yourself." + datatype = DNA2_BUF_SE + value = 0x001 + New() + block = REMOTETALKBLOCK + ..() diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 06f055c65a0..a89412f8fd8 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -1,135 +1,135 @@ - - -/obj/item/weapon/plastique - name = "plastic explosives" - desc = "Used to put holes in specific areas without too much extra hole." - gender = PLURAL - icon = 'icons/obj/assemblies.dmi' - icon_state = "plastic-explosive0" - item_state = "plasticx" - flags = FPRINT - w_class = 2.0 - origin_tech = "syndicate=2" - var/datum/wires/explosive/plastic/wires = null - var/timer = 10 - var/atom/target = null - var/open_panel = 0 - -/obj/item/weapon/plastique/New() - . = ..() - wires = new(src) - -/obj/item/weapon/plastique/Destroy() - if(wires) - qdel(wires) - wires = null - - ..() - -/obj/item/weapon/plastique/suicide_act(var/mob/user) - . = (BRUTELOSS) - to_chat(viewers(user), "[user] activates the C4 and holds it above his head! It looks like \he's going out with a bang!") - var/message_say = "FOR NO RAISIN!" - if(user.mind) - if(user.mind.special_role) - var/role = lowertext(user.mind.special_role) - if(role == "traitor" || role == "syndicate") - message_say = "FOR THE SYNDICATE!" - else if(role == "changeling") - message_say = "FOR THE HIVE!" - else if(role == "cultist") - message_say = "FOR NARSIE!" - user.say(message_say) - target = user - explode(get_turf(user)) - return . - -/obj/item/weapon/plastique/attackby(var/obj/item/I, var/mob/user) - if(istype(I, /obj/item/weapon/screwdriver)) - open_panel = !open_panel - to_chat(user, "You [open_panel ? "open" : "close"] the wire panel.") - else if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler )) - wires.Interact(user) - else - ..() - -/obj/item/weapon/plastique/attack_self(mob/user as mob) - var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(newtime > 60000) - newtime = 60000 - timer = newtime - to_chat(user, "Timer set for [timer] seconds.") - -/obj/item/weapon/plastique/afterattack(atom/target as obj|turf, mob/user as mob, flag) - if (!flag) - return - if (istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/)) - return - to_chat(user, "Planting explosives...") - if(ismob(target)) - - user.attack_log += "\[[time_stamp()]\] [user.real_name] tried planting [name] on [target:real_name] ([target:ckey])" - msg_admin_attack("[user.real_name] ([user.ckey]) tried planting [name] on [target:real_name] ([target:ckey]) (JMP)") - - user.visible_message("[user.name] is trying to plant some kind of explosive on [target.name]!") - - if(do_after(user, target, 50) && user.Adjacent(target)) - var/glue_act = 0 //If 1, the C4 is superglued to the guy's hands - produce a funny message - - if(user.drop_item(src)) - src.target = target - else //User can't drop this normally -> stick it to him (but drop it anyways, to prevent unintended features) - to_chat(user, "\The [src] are glued to your hands!") //Honk - src.target = user - target = user - glue_act = 1 - user.drop_item(src, force_drop = 1) - - loc = null - - if (ismob(target)) - var/mob/M=target - target:attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" - - if(!glue_act) - user.visible_message("[user.name] finished planting an explosive on [target.name]!") - else - user.visible_message("[user] found \himself unable to drop \the [src] after setting the timer on them!") - - playsound(get_turf(target), 'sound/weapons/c4armed.ogg', 60, 1) - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - target.overlays += image('icons/obj/assemblies.dmi', "plastic-explosive2") - to_chat(user, "Bomb has been planted. Timer counting down from [timer].") - spawn(timer*10) - explode(get_turf(target)) - -/obj/item/weapon/plastique/proc/explode(var/location) - - - if(!target) - target = get_atom_on_turf(src) - if(!target) - target = src - if(location) - explosion(location, -1, -1, 2, 3) - - if(target) - target.overlays -= image('icons/obj/assemblies.dmi', "plastic-explosive2") - if(!(target.singuloCanEat()))//mostly adminbus objects. It'd make sense though that C4 can't destroy what even a singulo can't eat. - qdel(src) - return - if (istype(target, /turf/simulated/wall)) - target:dismantle_wall(1) - else - target.ex_act(1) - if (isobj(target)) - if (target) - qdel(target) - target = null - qdel(src) - -/obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone) - return + + +/obj/item/weapon/plastique + name = "plastic explosives" + desc = "Used to put holes in specific areas without too much extra hole." + gender = PLURAL + icon = 'icons/obj/assemblies.dmi' + icon_state = "plastic-explosive0" + item_state = "plasticx" + flags = FPRINT + w_class = 2.0 + origin_tech = "syndicate=2" + var/datum/wires/explosive/plastic/wires = null + var/timer = 10 + var/atom/target = null + var/open_panel = 0 + +/obj/item/weapon/plastique/New() + . = ..() + wires = new(src) + +/obj/item/weapon/plastique/Destroy() + if(wires) + qdel(wires) + wires = null + + ..() + +/obj/item/weapon/plastique/suicide_act(var/mob/user) + . = (BRUTELOSS) + to_chat(viewers(user), "[user] activates the C4 and holds it above his head! It looks like \he's going out with a bang!") + var/message_say = "FOR NO RAISIN!" + if(user.mind) + if(user.mind.special_role) + var/role = lowertext(user.mind.special_role) + if(role == "traitor" || role == "syndicate") + message_say = "FOR THE SYNDICATE!" + else if(role == "changeling") + message_say = "FOR THE HIVE!" + else if(role == "cultist") + message_say = "FOR NARSIE!" + user.say(message_say) + target = user + explode(get_turf(user)) + return . + +/obj/item/weapon/plastique/attackby(var/obj/item/I, var/mob/user) + if(istype(I, /obj/item/weapon/screwdriver)) + open_panel = !open_panel + to_chat(user, "You [open_panel ? "open" : "close"] the wire panel.") + else if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler )) + wires.Interact(user) + else + ..() + +/obj/item/weapon/plastique/attack_self(mob/user as mob) + var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num + if(newtime > 60000) + newtime = 60000 + timer = newtime + to_chat(user, "Timer set for [timer] seconds.") + +/obj/item/weapon/plastique/afterattack(atom/target as obj|turf, mob/user as mob, flag) + if (!flag) + return + if (istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/)) + return + to_chat(user, "Planting explosives...") + if(ismob(target)) + + user.attack_log += "\[[time_stamp()]\] [user.real_name] tried planting [name] on [target:real_name] ([target:ckey])" + msg_admin_attack("[user.real_name] ([user.ckey]) tried planting [name] on [target:real_name] ([target:ckey]) (JMP)") + + user.visible_message("[user.name] is trying to plant some kind of explosive on [target.name]!") + + if(do_after(user, target, 50) && user.Adjacent(target)) + var/glue_act = 0 //If 1, the C4 is superglued to the guy's hands - produce a funny message + + if(user.drop_item(src)) + src.target = target + else //User can't drop this normally -> stick it to him (but drop it anyways, to prevent unintended features) + to_chat(user, "\The [src] are glued to your hands!") //Honk + src.target = user + target = user + glue_act = 1 + user.drop_item(src, force_drop = 1) + + loc = null + + if (ismob(target)) + var/mob/M=target + target:attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" + + if(!glue_act) + user.visible_message("[user.name] finished planting an explosive on [target.name]!") + else + user.visible_message("[user] found \himself unable to drop \the [src] after setting the timer on them!") + + playsound(get_turf(target), 'sound/weapons/c4armed.ogg', 60, 1) + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + target.overlays += image('icons/obj/assemblies.dmi', "plastic-explosive2") + to_chat(user, "Bomb has been planted. Timer counting down from [timer].") + spawn(timer*10) + explode(get_turf(target)) + +/obj/item/weapon/plastique/proc/explode(var/location) + + + if(!target) + target = get_atom_on_turf(src) + if(!target) + target = src + if(location) + explosion(location, -1, -1, 2, 3) + + if(target) + target.overlays -= image('icons/obj/assemblies.dmi', "plastic-explosive2") + if(!(target.singuloCanEat()))//mostly adminbus objects. It'd make sense though that C4 can't destroy what even a singulo can't eat. + qdel(src) + return + if (istype(target, /turf/simulated/wall)) + target:dismantle_wall(1) + else + target.ex_act(1) + if (isobj(target)) + if (target) + qdel(target) + target = null + qdel(src) + +/obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone) + return diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 73720e3188e..f8bc37701f3 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -1,344 +1,344 @@ - -/obj/item/weapon/extinguisher - name = "fire extinguisher" - desc = "A traditional red fire extinguisher." - icon = 'icons/obj/items.dmi' - icon_state = "fire_extinguisher0" - item_state = "fire_extinguisher" - hitsound = 'sound/weapons/smash.ogg' - flags = FPRINT - siemens_coefficient = 1 - throwforce = 10 - w_class = 3.0 - throw_speed = 2 - throw_range = 10 - force = 10.0 - starting_materials = list(MAT_IRON = 90) // TODO: Check against autolathe. - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed") - var/max_water = 50 - var/last_use = 1.0 - var/safety = 1 - var/sprite_name = "fire_extinguisher" - -/obj/item/weapon/extinguisher/New() - . = ..() - create_reagents(max_water) - reagents.add_reagent("water", max_water) - -/obj/item/weapon/extinguisher/mini - name = "fire extinguisher" - desc = "A light and compact fibreglass-framed model fire extinguisher." - icon_state = "miniFE0" - item_state = "miniFE" - hitsound = null //it is much lighter, after all. - flags = FPRINT - throwforce = 2 - w_class = 2.0 - force = 3.0 - starting_materials = null - max_water = 30 - sprite_name = "miniFE" - -/obj/item/weapon/extinguisher/foam - name = "foam fire extinguisher" - desc = "A modern foam fire supression system." - icon_state = "foam_extinguisher0" - item_state = "foam_extinguisher" - sprite_name = "foam_extinguisher" - -/proc/pack_check(mob/user, var/obj/item/weapon/extinguisher/E) //Checks the user for a nonempty chempack. - var/mob/living/M = user - if (M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack)) - var/obj/item/weapon/reagent_containers/chempack/P = M.back - if (!P.safety) - if (!P.is_empty()) - transfer_sub(P, E, 5, user) - return 2 - else - to_chat(user, "\The [P] is empty!") - return 1 - else - return 0 - -/obj/item/weapon/extinguisher/examine(mob/user) - ..() - if(!is_open_container()) - to_chat(user, "It contains:") - if(reagents && reagents.reagent_list.len) - for(var/datum/reagent/R in reagents.reagent_list) - to_chat(user, "[R.volume] units of [R.name]") - else - to_chat(user, "Nothing") - for(var/thing in src) - to_chat(user, "\A [thing] is jammed into the nozzle!") - -/obj/item/weapon/extinguisher/attack_self(mob/user as mob) - safety = !safety - src.icon_state = "[sprite_name][!safety]" - src.desc = "The safety is [safety ? "on" : "off"]." - to_chat(user, "The safety is [safety ? "on" : "off"].") - return - -/obj/item/weapon/extinguisher/attackby(obj/item/W, mob/user) - if(user.stat || user.restrained() || user.lying) return - if (istype(W, /obj/item/weapon/wrench)) - if(!is_open_container()) - user.visible_message("[user] begins to unwrench the fill cap on \the [src].","You begin to unwrench the fill cap on \the [src].") - if(do_after(user, src, 25)) - user.visible_message("[user] removes the fill cap on \the [src].","You remove the fill cap on \the [src].") - playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) - flags |= OPENCONTAINER - else - user.visible_message("[user] begins to seal the fill cap on \the [src].","You begin to seal the fill cap on \the [src].") - if(do_after(user, src, 25)) - user.visible_message("[user] fastens the fill cap on \the [src].","You fasten the fill cap on \the [src].") - playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) - flags &= ~OPENCONTAINER - return - - if (istype(W, /obj/item) && !is_open_container() && !istype(src, /obj/item/weapon/extinguisher/foam) && !istype(W, /obj/item/weapon/evidencebag)) - if(W.is_open_container()) return //We're probably trying to fill it - if(W.w_class>1) - to_chat(user, "\The [W] won't fit into the nozzle!") - return - if(locate(/obj) in src) - to_chat(user, "There's already something crammed into the nozzle.") - return - if(isrobot(user) && !isMoMMI(user)) // MoMMI's can but borgs can't - to_chat(user, "You're a robot. No.") - return - if(user.drop_item(W, src)) - to_chat(user, "You cram \the [W] into the nozzle of \the [src].") - message_admins("[user]/[user.ckey] has crammed \a [W] into a [src].") - -/obj/item/weapon/extinguisher/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(proximity_flag) - if((istype(target, /obj/structure/reagent_dispensers))) - var/obj/o = target - var/list/badshit=list() - for(var/bad_reagent in reagents_to_log) - if(o.reagents.has_reagent(bad_reagent)) - badshit += reagents_to_log[bad_reagent] - if(badshit.len) - var/hl="([english_list(badshit)])" - // message_admins("[user.name] ([user.ckey]) filled \a [src] with [o.reagents.get_reagent_ids()] [hl]. (JMP)") - log_game("[user.name] ([user.ckey]) filled \a [src] with [o.reagents.get_reagent_ids()] [hl]. (JMP)") - o.reagents.trans_to(src, 50) - to_chat(user, "\The [src] is now refilled") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) - return - - if(is_open_container() && reagents.total_volume) - to_chat(user, "You empty \the [src] onto [target].") - if(reagents.has_reagent("fuel")) - message_admins("[user.name] ([user.ckey]) poured Welder Fuel onto [target]. (JMP)") - log_game("[user.name] ([user.ckey]) poured Welder Fuel onto [target]. (JMP)") - src.reagents.reaction(target, TOUCH) - spawn(5) src.reagents.clear_reagents() - return - if (!safety && !is_open_container()) - if (src.reagents.total_volume < 1) - var/pack = pack_check(user, src) - if (!pack) //Only display the "extinguisher empty" warning if the user is not wearing a chempack, since chempacks are designed to be used with empty items. - to_chat(user, "\The [src] is empty!") - return - else if (pack == 1) - return - - if (world.time < src.last_use + 20) - return - user.delayNextAttack(5, 1) - var/list/badshit=list() - for(var/bad_reagent in reagents_to_log) - if(reagents.has_reagent(bad_reagent)) - badshit += reagents_to_log[bad_reagent] - if(badshit.len) - var/hl="([english_list(badshit)])" - message_admins("[user.name] ([user.ckey]) used \a [src] filled with [reagents.get_reagent_ids(1)] [hl]. (JMP)") - log_game("[user.name] ([user.ckey]) used \a [src] filled with [reagents.get_reagent_ids(1)] [hl]. (JMP)") - - src.last_use = world.time - - playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3) - - var/direction = get_dir(src,target) - - if(user.locked_to && isobj(user.locked_to) && !user.locked_to.anchored ) - spawn() - var/obj/B = user.locked_to - var/movementdirection = turn(direction,180) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - - if(locate(/obj) in src) - for(var/obj/thing in src) - thing.loc = get_turf(src) - thing.throw_at(target,10,thing.throw_speed*3) - user.visible_message( - "[user] fires [src] and launches [thing] at [target]!", - "You fire [src] and launch [thing] at [target]!") - break - - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - - var/list/the_targets = list(T,T1,T2) - - for(var/a=0, a<5, a++) - spawn(0) - var/datum/reagents/R = new/datum/reagents(5) - R.my_atom = src - reagents.trans_to_holder(R,1) - var/obj/effect/effect/water/spray/W = new /obj/effect/effect/water/spray/( get_turf(src)) - var/ccolor = mix_color_from_reagents(R.reagent_list) - if(ccolor) - W.color = ccolor - var/turf/my_target = pick(the_targets) - if(!W) return - W.reagents = R - R.my_atom = W - if(!W || !src) return - for(var/b=0, b<5, b++) - step_towards(W,my_target) - if(!W || !W.reagents) return - W.reagents.reaction(get_turf(W), TOUCH) - for(var/atom/atm in get_turf(W)) - if(!W) return - W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. - if(W.reagents.has_reagent("water")) - if(istype(atm,/obj/machinery/space_heater/campfire)) - var/obj/machinery/space_heater/campfire/campfire = atm - campfire.cell.charge = 0 - campfire.process() - if(isliving(atm)) // For extinguishing mobs on fire - var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X - M.ExtinguishMob() - if(atm.on_fire) // For extinguishing objects on fire - atm.extinguish() - if(atm.molten) // Molten shit. - atm.molten=0 - atm.solidify() - if(W.loc == my_target) break - sleep(2) - - if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) - user.inertia_dir = get_dir(target, user) - step(user, user.inertia_dir) - else - return ..() - return - - - - -/obj/item/weapon/extinguisher/foam/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(proximity_flag) - if((istype(target, /obj/structure/reagent_dispensers/watertank))) - var/obj/o = target - o.reagents.trans_to(src, 50) - to_chat(user, "\The [src] is now refilled") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) - return - - if (!safety && !is_open_container()) - if (src.reagents.total_volume < 1) - var/pack = pack_check(user, src) - if (!pack) - to_chat(user, "\The [src] is empty!") - return - else if (pack == 1) - return - - if (world.time < src.last_use + 20) - return - user.delayNextAttack(5, 1) - src.last_use = world.time - - playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3) - - var/direction = get_dir(src,target) - - if(usr.locked_to && isobj(usr.locked_to) && !usr.locked_to.anchored ) - spawn(0) - var/obj/B = usr.locked_to - var/movementdirection = turn(direction,180) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(usr,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(usr,movementdirection), movementdirection) - - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - - var/list/the_targets = list(T,T1,T2) - - for(var/a=0, a<5, a++) - spawn(0) - var/datum/reagents/R = new/datum/reagents(5) - R.my_atom = src - reagents.trans_to_holder(R,1) - var/obj/effect/effect/foam/fire/W = new /obj/effect/effect/foam/fire( get_turf(src) , R) - var/turf/my_target = pick(the_targets) - if(!W || !src) return - for(var/b=0, b<5, b++) - var/turf/oldturf = get_turf(W) - step_towards(W,my_target) - if(!W || !W.reagents) return - W.reagents.reaction(get_turf(W), TOUCH) - for(var/atom/atm in get_turf(W)) - if(!W) return - W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. - if(W.reagents.has_reagent("water")) - if(isliving(atm)) // For extinguishing mobs on fire - var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X - M.ExtinguishMob() - if(atm.on_fire) // For extinguishing objects on fire - atm.extinguish() - if(atm.molten) // Molten shit. - atm.molten=0 - atm.solidify() - - var/obj/effect/effect/foam/fire/F = locate() in oldturf - if(!istype(F) && oldturf != get_turf(src)) - F = new /obj/effect/effect/foam/fire( get_turf(oldturf) , W.reagents) - if(W.loc == my_target) break - sleep(2) - - if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) - user.inertia_dir = get_dir(target, user) - step(user, user.inertia_dir) - else - return ..() - return + +/obj/item/weapon/extinguisher + name = "fire extinguisher" + desc = "A traditional red fire extinguisher." + icon = 'icons/obj/items.dmi' + icon_state = "fire_extinguisher0" + item_state = "fire_extinguisher" + hitsound = 'sound/weapons/smash.ogg' + flags = FPRINT + siemens_coefficient = 1 + throwforce = 10 + w_class = 3.0 + throw_speed = 2 + throw_range = 10 + force = 10.0 + starting_materials = list(MAT_IRON = 90) // TODO: Check against autolathe. + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed") + var/max_water = 50 + var/last_use = 1.0 + var/safety = 1 + var/sprite_name = "fire_extinguisher" + +/obj/item/weapon/extinguisher/New() + . = ..() + create_reagents(max_water) + reagents.add_reagent("water", max_water) + +/obj/item/weapon/extinguisher/mini + name = "fire extinguisher" + desc = "A light and compact fibreglass-framed model fire extinguisher." + icon_state = "miniFE0" + item_state = "miniFE" + hitsound = null //it is much lighter, after all. + flags = FPRINT + throwforce = 2 + w_class = 2.0 + force = 3.0 + starting_materials = null + max_water = 30 + sprite_name = "miniFE" + +/obj/item/weapon/extinguisher/foam + name = "foam fire extinguisher" + desc = "A modern foam fire supression system." + icon_state = "foam_extinguisher0" + item_state = "foam_extinguisher" + sprite_name = "foam_extinguisher" + +/proc/pack_check(mob/user, var/obj/item/weapon/extinguisher/E) //Checks the user for a nonempty chempack. + var/mob/living/M = user + if (M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack)) + var/obj/item/weapon/reagent_containers/chempack/P = M.back + if (!P.safety) + if (!P.is_empty()) + transfer_sub(P, E, 5, user) + return 2 + else + to_chat(user, "\The [P] is empty!") + return 1 + else + return 0 + +/obj/item/weapon/extinguisher/examine(mob/user) + ..() + if(!is_open_container()) + to_chat(user, "It contains:") + if(reagents && reagents.reagent_list.len) + for(var/datum/reagent/R in reagents.reagent_list) + to_chat(user, "[R.volume] units of [R.name]") + else + to_chat(user, "Nothing") + for(var/thing in src) + to_chat(user, "\A [thing] is jammed into the nozzle!") + +/obj/item/weapon/extinguisher/attack_self(mob/user as mob) + safety = !safety + src.icon_state = "[sprite_name][!safety]" + src.desc = "The safety is [safety ? "on" : "off"]." + to_chat(user, "The safety is [safety ? "on" : "off"].") + return + +/obj/item/weapon/extinguisher/attackby(obj/item/W, mob/user) + if(user.stat || user.restrained() || user.lying) return + if (istype(W, /obj/item/weapon/wrench)) + if(!is_open_container()) + user.visible_message("[user] begins to unwrench the fill cap on \the [src].","You begin to unwrench the fill cap on \the [src].") + if(do_after(user, src, 25)) + user.visible_message("[user] removes the fill cap on \the [src].","You remove the fill cap on \the [src].") + playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) + flags |= OPENCONTAINER + else + user.visible_message("[user] begins to seal the fill cap on \the [src].","You begin to seal the fill cap on \the [src].") + if(do_after(user, src, 25)) + user.visible_message("[user] fastens the fill cap on \the [src].","You fasten the fill cap on \the [src].") + playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) + flags &= ~OPENCONTAINER + return + + if (istype(W, /obj/item) && !is_open_container() && !istype(src, /obj/item/weapon/extinguisher/foam) && !istype(W, /obj/item/weapon/evidencebag)) + if(W.is_open_container()) return //We're probably trying to fill it + if(W.w_class>1) + to_chat(user, "\The [W] won't fit into the nozzle!") + return + if(locate(/obj) in src) + to_chat(user, "There's already something crammed into the nozzle.") + return + if(isrobot(user) && !isMoMMI(user)) // MoMMI's can but borgs can't + to_chat(user, "You're a robot. No.") + return + if(user.drop_item(W, src)) + to_chat(user, "You cram \the [W] into the nozzle of \the [src].") + message_admins("[user]/[user.ckey] has crammed \a [W] into a [src].") + +/obj/item/weapon/extinguisher/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(proximity_flag) + if((istype(target, /obj/structure/reagent_dispensers))) + var/obj/o = target + var/list/badshit=list() + for(var/bad_reagent in reagents_to_log) + if(o.reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="([english_list(badshit)])" + // message_admins("[user.name] ([user.ckey]) filled \a [src] with [o.reagents.get_reagent_ids()] [hl]. (JMP)") + log_game("[user.name] ([user.ckey]) filled \a [src] with [o.reagents.get_reagent_ids()] [hl]. (JMP)") + o.reagents.trans_to(src, 50) + to_chat(user, "\The [src] is now refilled") + playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + return + + if(is_open_container() && reagents.total_volume) + to_chat(user, "You empty \the [src] onto [target].") + if(reagents.has_reagent("fuel")) + message_admins("[user.name] ([user.ckey]) poured Welder Fuel onto [target]. (JMP)") + log_game("[user.name] ([user.ckey]) poured Welder Fuel onto [target]. (JMP)") + src.reagents.reaction(target, TOUCH) + spawn(5) src.reagents.clear_reagents() + return + if (!safety && !is_open_container()) + if (src.reagents.total_volume < 1) + var/pack = pack_check(user, src) + if (!pack) //Only display the "extinguisher empty" warning if the user is not wearing a chempack, since chempacks are designed to be used with empty items. + to_chat(user, "\The [src] is empty!") + return + else if (pack == 1) + return + + if (world.time < src.last_use + 20) + return + user.delayNextAttack(5, 1) + var/list/badshit=list() + for(var/bad_reagent in reagents_to_log) + if(reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="([english_list(badshit)])" + message_admins("[user.name] ([user.ckey]) used \a [src] filled with [reagents.get_reagent_ids(1)] [hl]. (JMP)") + log_game("[user.name] ([user.ckey]) used \a [src] filled with [reagents.get_reagent_ids(1)] [hl]. (JMP)") + + src.last_use = world.time + + playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3) + + var/direction = get_dir(src,target) + + if(user.locked_to && isobj(user.locked_to) && !user.locked_to.anchored ) + spawn() + var/obj/B = user.locked_to + var/movementdirection = turn(direction,180) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + + if(locate(/obj) in src) + for(var/obj/thing in src) + thing.loc = get_turf(src) + thing.throw_at(target,10,thing.throw_speed*3) + user.visible_message( + "[user] fires [src] and launches [thing] at [target]!", + "You fire [src] and launch [thing] at [target]!") + break + + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T,turn(direction, 90)) + var/turf/T2 = get_step(T,turn(direction, -90)) + + var/list/the_targets = list(T,T1,T2) + + for(var/a=0, a<5, a++) + spawn(0) + var/datum/reagents/R = new/datum/reagents(5) + R.my_atom = src + reagents.trans_to_holder(R,1) + var/obj/effect/effect/water/spray/W = new /obj/effect/effect/water/spray/( get_turf(src)) + var/ccolor = mix_color_from_reagents(R.reagent_list) + if(ccolor) + W.color = ccolor + var/turf/my_target = pick(the_targets) + if(!W) return + W.reagents = R + R.my_atom = W + if(!W || !src) return + for(var/b=0, b<5, b++) + step_towards(W,my_target) + if(!W || !W.reagents) return + W.reagents.reaction(get_turf(W), TOUCH) + for(var/atom/atm in get_turf(W)) + if(!W) return + W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. + if(W.reagents.has_reagent("water")) + if(istype(atm,/obj/machinery/space_heater/campfire)) + var/obj/machinery/space_heater/campfire/campfire = atm + campfire.cell.charge = 0 + campfire.process() + if(isliving(atm)) // For extinguishing mobs on fire + var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X + M.ExtinguishMob() + if(atm.on_fire) // For extinguishing objects on fire + atm.extinguish() + if(atm.molten) // Molten shit. + atm.molten=0 + atm.solidify() + if(W.loc == my_target) break + sleep(2) + + if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) + user.inertia_dir = get_dir(target, user) + step(user, user.inertia_dir) + else + return ..() + return + + + + +/obj/item/weapon/extinguisher/foam/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(proximity_flag) + if((istype(target, /obj/structure/reagent_dispensers/watertank))) + var/obj/o = target + o.reagents.trans_to(src, 50) + to_chat(user, "\The [src] is now refilled") + playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + return + + if (!safety && !is_open_container()) + if (src.reagents.total_volume < 1) + var/pack = pack_check(user, src) + if (!pack) + to_chat(user, "\The [src] is empty!") + return + else if (pack == 1) + return + + if (world.time < src.last_use + 20) + return + user.delayNextAttack(5, 1) + src.last_use = world.time + + playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3) + + var/direction = get_dir(src,target) + + if(usr.locked_to && isobj(usr.locked_to) && !usr.locked_to.anchored ) + spawn(0) + var/obj/B = usr.locked_to + var/movementdirection = turn(direction,180) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(usr,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(usr,movementdirection), movementdirection) + + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T,turn(direction, 90)) + var/turf/T2 = get_step(T,turn(direction, -90)) + + var/list/the_targets = list(T,T1,T2) + + for(var/a=0, a<5, a++) + spawn(0) + var/datum/reagents/R = new/datum/reagents(5) + R.my_atom = src + reagents.trans_to_holder(R,1) + var/obj/effect/effect/foam/fire/W = new /obj/effect/effect/foam/fire( get_turf(src) , R) + var/turf/my_target = pick(the_targets) + if(!W || !src) return + for(var/b=0, b<5, b++) + var/turf/oldturf = get_turf(W) + step_towards(W,my_target) + if(!W || !W.reagents) return + W.reagents.reaction(get_turf(W), TOUCH) + for(var/atom/atm in get_turf(W)) + if(!W) return + W.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. + if(W.reagents.has_reagent("water")) + if(isliving(atm)) // For extinguishing mobs on fire + var/mob/living/M = atm // Why isn't this handled by the reagent? - N3X + M.ExtinguishMob() + if(atm.on_fire) // For extinguishing objects on fire + atm.extinguish() + if(atm.molten) // Molten shit. + atm.molten=0 + atm.solidify() + + var/obj/effect/effect/foam/fire/F = locate() in oldturf + if(!istype(F) && oldturf != get_turf(src)) + F = new /obj/effect/effect/foam/fire( get_turf(oldturf) , W.reagents) + if(W.loc == my_target) break + sleep(2) + + if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) + user.inertia_dir = get_dir(target, user) + step(user, user.inertia_dir) + else + return ..() + return diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index e59b7cb43b7..d5eef49fe29 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -1,216 +1,216 @@ -/obj/item/weapon/flamethrower - name = "flamethrower" - desc = "You are a firestarter!" - icon = 'icons/obj/flamethrower.dmi' - icon_state = "flamethrowerbase" - item_state = "flamethrower_0" - flags = FPRINT - siemens_coefficient = 1 - force = 3.0 - throwforce = 10.0 - throw_speed = 1 - throw_range = 5 - w_class = 3.0 - starting_materials = list(MAT_IRON = 500) - w_type = RECYK_MISC - melt_temperature = MELTPOINT_STEEL - origin_tech = "combat=1;plasmatech=1" - var/status = 0 - var/throw_amount = 100 - var/lit = 0 //on or off - var/operating = 0//cooldown - var/turf/previousturf = null - var/obj/item/weapon/weldingtool/weldtool = null - var/obj/item/device/assembly/igniter/igniter = null - var/obj/item/weapon/tank/plasma/ptank = null - - -/obj/item/weapon/flamethrower/Destroy() - if(weldtool) - qdel(weldtool) - weldtool = null - if(igniter) - qdel(igniter) - igniter = null - if(ptank) - qdel(ptank) - ptank = null - ..() - return - - -/obj/item/weapon/flamethrower/process() - if(!lit) - processing_objects.Remove(src) - return null - var/turf/location = loc - if(istype(location, /mob/)) - var/mob/M = location - if(M.l_hand == src || M.r_hand == src) - location = M.loc - if(isturf(location)) //start a fire if possible - location.hotspot_expose(700, 2,surfaces=istype(loc,/turf)) - return - - -/obj/item/weapon/flamethrower/update_icon() - overlays.len = 0 - if(igniter) - overlays += "+igniter[status]" - if(ptank) - overlays += "+ptank" - if(lit) - overlays += "+lit" - item_state = "flamethrower_1" - else - item_state = "flamethrower_0" - return - -/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, flag) - // Make sure our user is still holding us - user.delayNextAttack(8) - if(user && user.get_active_hand() == src) - var/turf/target_turf = get_turf(target) - if(target_turf) - var/turflist = getline(user, target_turf) - flame_turf(turflist) - -/obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob) - if(user.stat || user.restrained() || user.lying) return - if(iswrench(W) && !status)//Taking this apart - var/turf/T = get_turf(src) - if(weldtool) - weldtool.loc = T - weldtool = null - if(igniter) - igniter.loc = T - igniter = null - if(ptank) - ptank.loc = T - ptank = null - getFromPool(/obj/item/stack/rods, T) - qdel(src) - return - - if(isscrewdriver(W) && igniter && !lit) - status = !status +/obj/item/weapon/flamethrower + name = "flamethrower" + desc = "You are a firestarter!" + icon = 'icons/obj/flamethrower.dmi' + icon_state = "flamethrowerbase" + item_state = "flamethrower_0" + flags = FPRINT + siemens_coefficient = 1 + force = 3.0 + throwforce = 10.0 + throw_speed = 1 + throw_range = 5 + w_class = 3.0 + starting_materials = list(MAT_IRON = 500) + w_type = RECYK_MISC + melt_temperature = MELTPOINT_STEEL + origin_tech = "combat=1;plasmatech=1" + var/status = 0 + var/throw_amount = 100 + var/lit = 0 //on or off + var/operating = 0//cooldown + var/turf/previousturf = null + var/obj/item/weapon/weldingtool/weldtool = null + var/obj/item/device/assembly/igniter/igniter = null + var/obj/item/weapon/tank/plasma/ptank = null + + +/obj/item/weapon/flamethrower/Destroy() + if(weldtool) + qdel(weldtool) + weldtool = null + if(igniter) + qdel(igniter) + igniter = null + if(ptank) + qdel(ptank) + ptank = null + ..() + return + + +/obj/item/weapon/flamethrower/process() + if(!lit) + processing_objects.Remove(src) + return null + var/turf/location = loc + if(istype(location, /mob/)) + var/mob/M = location + if(M.l_hand == src || M.r_hand == src) + location = M.loc + if(isturf(location)) //start a fire if possible + location.hotspot_expose(700, 2,surfaces=istype(loc,/turf)) + return + + +/obj/item/weapon/flamethrower/update_icon() + overlays.len = 0 + if(igniter) + overlays += "+igniter[status]" + if(ptank) + overlays += "+ptank" + if(lit) + overlays += "+lit" + item_state = "flamethrower_1" + else + item_state = "flamethrower_0" + return + +/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, flag) + // Make sure our user is still holding us + user.delayNextAttack(8) + if(user && user.get_active_hand() == src) + var/turf/target_turf = get_turf(target) + if(target_turf) + var/turflist = getline(user, target_turf) + flame_turf(turflist) + +/obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob) + if(user.stat || user.restrained() || user.lying) return + if(iswrench(W) && !status)//Taking this apart + var/turf/T = get_turf(src) + if(weldtool) + weldtool.loc = T + weldtool = null + if(igniter) + igniter.loc = T + igniter = null + if(ptank) + ptank.loc = T + ptank = null + getFromPool(/obj/item/stack/rods, T) + qdel(src) + return + + if(isscrewdriver(W) && igniter && !lit) + status = !status to_chat(user, "[igniter] is now [status ? "secured" : "unsecured"]!") - update_icon() - return - - if(isigniter(W)) - var/obj/item/device/assembly/igniter/I = W - if(I.secured) return - if(igniter) return - if(user.drop_item(I, src)) - igniter = I - update_icon() - return - - if(istype(W,/obj/item/weapon/tank/plasma)) - if(ptank) + update_icon() + return + + if(isigniter(W)) + var/obj/item/device/assembly/igniter/I = W + if(I.secured) return + if(igniter) return + if(user.drop_item(I, src)) + igniter = I + update_icon() + return + + if(istype(W,/obj/item/weapon/tank/plasma)) + if(ptank) to_chat(user, "There appears to already be a plasma tank loaded in [src]!") - return - if(user.drop_item(W, src)) - ptank = W - update_icon() - return - - if(istype(W, /obj/item/device/analyzer) && ptank) - var/obj/item/device/analyzer/analyzer = W - user.visible_message("[user] has used the analyzer on \icon[icon]") - user.show_message(analyzer.output_gas_scan(ptank.air_contents, src, 0), 1) - return - ..() - return - - -/obj/item/weapon/flamethrower/attack_self(mob/user as mob) - if(user.stat || user.restrained() || user.lying) return - user.set_machine(src) - if(!ptank) + return + if(user.drop_item(W, src)) + ptank = W + update_icon() + return + + if(istype(W, /obj/item/device/analyzer) && ptank) + var/obj/item/device/analyzer/analyzer = W + user.visible_message("[user] has used the analyzer on \icon[icon]") + user.show_message(analyzer.output_gas_scan(ptank.air_contents, src, 0), 1) + return + ..() + return + + +/obj/item/weapon/flamethrower/attack_self(mob/user as mob) + if(user.stat || user.restrained() || user.lying) return + user.set_machine(src) + if(!ptank) to_chat(user, "Attach a plasma tank first!") - return - var/dat = text("Flamethrower ([lit ? "Lit" : "Unlit"])
    \n Tank Pressure: [ptank.air_contents.return_pressure()]
    \nAmount to throw: - - - [throw_amount] + + +
    \nRemove plasmatank - Close
    ") - user << browse(dat, "window=flamethrower;size=600x300") - onclose(user, "flamethrower") - return - - -/obj/item/weapon/flamethrower/Topic(href,href_list[]) - if(href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=flamethrower") - return - if(usr.stat || usr.restrained() || usr.lying) return - usr.set_machine(src) - if(href_list["light"]) - if(!ptank) return - if(ptank.air_contents.toxins < 1) return - if(!status) return - lit = !lit - if(lit) - processing_objects.Add(src) - if(href_list["amount"]) - throw_amount = throw_amount + text2num(href_list["amount"]) - throw_amount = max(50, min(5000, throw_amount)) - if(href_list["remove"]) - if(!ptank) return - usr.put_in_hands(ptank) - ptank = null - lit = 0 - usr.unset_machine() - usr << browse(null, "window=flamethrower") - for(var/mob/M in viewers(1, loc)) - if((M.client && M.machine == src)) - attack_self(M) - update_icon() - return - - -//Called from turf.dm turf/dblclick -/obj/item/weapon/flamethrower/proc/flame_turf(turflist) - if(!lit || operating) return - operating = 1 - for(var/turf/T in turflist) - if(T.density || istype(T, /turf/space)) - break - if(!previousturf && length(turflist)>1) - previousturf = get_turf(src) - continue //so we don't burn the tile we be standin on - if(previousturf && LinkBlocked(previousturf, T)) - break - ignite_turf(T) - sleep(1) - previousturf = null - operating = 0 - for(var/mob/M in viewers(1, loc)) - if((M.client && M.machine == src)) - attack_self(M) - return - - -/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target) - //TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this... - //Transfer 5% of current tank air contents to turf - var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(0.02*(throw_amount/100)) - //air_transfer.toxins = air_transfer.toxins * 5 // This is me not comprehending the air system. I realize this is retarded and I could probably make it work without fucking it up like this, but there you have it. -- TLE - var/plasma_moles = air_transfer.toxins - getFromPool(/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel, target, plasma_moles*10, get_dir(loc, target)) - air_transfer.toxins = 0 - target.assume_air(air_transfer) - //Burn it based on transfered gas - //target.hotspot_expose(part4.air_contents.temperature*2,300) - target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500) // -- More of my "how do I shot fire?" dickery. -- TLE - //location.hotspot_expose(1000,500,1) - return - -/obj/item/weapon/flamethrower/full/New(var/loc) - ..() - weldtool = new /obj/item/weapon/weldingtool(src) - weldtool.status = 0 - igniter = new /obj/item/device/assembly/igniter(src) - igniter.secured = 0 - status = 1 - update_icon() - return + return + var/dat = text("Flamethrower ([lit ? "Lit" : "Unlit"])
    \n Tank Pressure: [ptank.air_contents.return_pressure()]
    \nAmount to throw: - - - [throw_amount] + + +
    \nRemove plasmatank - Close
    ") + user << browse(dat, "window=flamethrower;size=600x300") + onclose(user, "flamethrower") + return + + +/obj/item/weapon/flamethrower/Topic(href,href_list[]) + if(href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=flamethrower") + return + if(usr.stat || usr.restrained() || usr.lying) return + usr.set_machine(src) + if(href_list["light"]) + if(!ptank) return + if(ptank.air_contents.toxins < 1) return + if(!status) return + lit = !lit + if(lit) + processing_objects.Add(src) + if(href_list["amount"]) + throw_amount = throw_amount + text2num(href_list["amount"]) + throw_amount = max(50, min(5000, throw_amount)) + if(href_list["remove"]) + if(!ptank) return + usr.put_in_hands(ptank) + ptank = null + lit = 0 + usr.unset_machine() + usr << browse(null, "window=flamethrower") + for(var/mob/M in viewers(1, loc)) + if((M.client && M.machine == src)) + attack_self(M) + update_icon() + return + + +//Called from turf.dm turf/dblclick +/obj/item/weapon/flamethrower/proc/flame_turf(turflist) + if(!lit || operating) return + operating = 1 + for(var/turf/T in turflist) + if(T.density || istype(T, /turf/space)) + break + if(!previousturf && length(turflist)>1) + previousturf = get_turf(src) + continue //so we don't burn the tile we be standin on + if(previousturf && LinkBlocked(previousturf, T)) + break + ignite_turf(T) + sleep(1) + previousturf = null + operating = 0 + for(var/mob/M in viewers(1, loc)) + if((M.client && M.machine == src)) + attack_self(M) + return + + +/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target) + //TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this... + //Transfer 5% of current tank air contents to turf + var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(0.02*(throw_amount/100)) + //air_transfer.toxins = air_transfer.toxins * 5 // This is me not comprehending the air system. I realize this is retarded and I could probably make it work without fucking it up like this, but there you have it. -- TLE + var/plasma_moles = air_transfer.toxins + getFromPool(/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel, target, plasma_moles*10, get_dir(loc, target)) + air_transfer.toxins = 0 + target.assume_air(air_transfer) + //Burn it based on transfered gas + //target.hotspot_expose(part4.air_contents.temperature*2,300) + target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500) // -- More of my "how do I shot fire?" dickery. -- TLE + //location.hotspot_expose(1000,500,1) + return + +/obj/item/weapon/flamethrower/full/New(var/loc) + ..() + weldtool = new /obj/item/weapon/weldingtool(src) + weldtool.status = 0 + igniter = new /obj/item/device/assembly/igniter(src) + igniter.secured = 0 + status = 1 + update_icon() + return diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 0bd0f2fd35f..46803d908b6 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -1,422 +1,422 @@ -/obj/item/weapon/grenade/chem_grenade - name = "Grenade Casing" - icon_state = "chemg" - item_state = "flashbang" - desc = "A hand made chemical grenade." - w_class = 2.0 - force = 2.0 - var/stage = 0 - var/state = 0 - var/path = 0 - var/obj/item/device/assembly_holder/detonator = null - var/list/beakers = new/list() - var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle) - var/affected_area = 3 - var/inserted_cores = 0 - var/obj/item/slime_extract/E = null //for large and Ex grenades - var/obj/item/slime_extract/C = null //for Ex grenades - var/obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade/reservoir = null - var/extract_uses = 0 - -/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user as mob) - if(!stage || stage==1) - if(detonator) -// detonator.loc=src.loc - detonator.detached() - usr.put_in_hands(detonator) - detonator=null - stage=0 - icon_state = initial(icon_state) - else if(beakers.len) - for(var/obj/B in beakers) - if(istype(B)) - beakers -= B - user.put_in_hands(B) - E = null - C = null - inserted_cores = 0 - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - if(stage > 1 && !active && clown_check(user)) - to_chat(user, "You prime \the [name]!") - - log_attack("[user.name] ([user.ckey]) primed \a [src].") - log_admin("ATTACK: [user] ([user.ckey]) primed \a [src].") - message_admins("ATTACK: [user] ([user.ckey]) primed \a [src].") - - activate() - add_fingerprint(user) - if(iscarbon(user)) - var/mob/living/carbon/C = user - C.throw_mode_on() - -/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && path != 2) - var/obj/item/device/assembly_holder/det = W - if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right))) - to_chat(user, " Assembly must contain one igniter.") - return - if(!det.secured) - to_chat(user, " Assembly must be secured with screwdriver.") - return - path = 1 - to_chat(user, "You add [W] to the metal casing.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) - user.remove_from_mob(det) - det.loc = src - detonator = det - icon_state = initial(icon_state) +"_ass" - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - stage = 1 - else if(istype(W,/obj/item/stack/cable_coil/) && !beakers.len) - var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 2) return - coil.use(2) - var/obj/item/weapon/electrolyzer/E = new /obj/item/weapon/electrolyzer - to_chat(user, "You tightly coil the wire around the metal casing.") - playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) - user.before_take_item(src) - user.put_in_hands(E) - qdel(src) - else if(istype(W,/obj/item/weapon/screwdriver) && path != 2) - if(stage == 1) - path = 1 - if(beakers.len) - to_chat(user, "You lock the assembly.") - name = "grenade" - else -// to_chat(user, "You need to add at least one beaker before locking the assembly.") - to_chat(user, "You lock the empty assembly.") - name = "fake grenade" - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) - icon_state = initial(icon_state) +"_locked" - stage = 2 - else if(stage == 2) - if(active && prob(95)) - to_chat(user, "You trigger the assembly!") - prime() - return - else - to_chat(user, "You unlock the assembly.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - icon_state = initial(icon_state) + (detonator?"_ass":"") - stage = 1 - active = 0 - else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2) - path = 1 - if(beakers.len == 2) - to_chat(user, " The grenade can not hold more containers.") - return - else - if (istype(W,/obj/item/slime_extract)) - if (inserted_cores > 0) - to_chat(user, " This type of grenade cannot hold more than one slime core.") - else - if(user.drop_item(W, src)) - to_chat(user, "You add \the [W] to the assembly.") - beakers += W - stage = 1 - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - else if(W.reagents.total_volume) - if(user.drop_item(W, src)) - to_chat(user, "You add \the [W] to the assembly.") - beakers += W - stage = 1 - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - else - to_chat(user, " \the [W] is empty.") - else if (istype(W,/obj/item/slime_extract)) - to_chat(user, " This grenade case is too small for a slime core to fit in it.") - -/obj/item/weapon/grenade/chem_grenade/examine(mob/user) - ..() - if(detonator) - to_chat(user, "With an attached [detonator.name]") - -/obj/item/weapon/grenade/chem_grenade/Crossed(AM as mob|obj) - if(detonator) - detonator.Crossed(AM) - ..() - -/obj/item/weapon/grenade/chem_grenade/on_found(AM as mob|obj) - if(detonator) - detonator.on_found(AM) - ..() - -/obj/item/weapon/grenade/chem_grenade/activate(mob/user as mob) - if(active) return - - if(detonator) - if(!isigniter(detonator.a_left)) - detonator.a_left.activate() - active = 1 - if(!isigniter(detonator.a_right)) - detonator.a_right.activate() - active = 1 - if(active) - icon_state = initial(icon_state) + "_active" - - if(user) - log_attack("[user.name] ([user.ckey]) primed \a [src]") - log_admin("ATTACK: [user] ([user.ckey]) primed \a [src]") - message_admins("ATTACK: [user] ([user.ckey]) primed \a [src]") - - return - -/obj/item/weapon/grenade/chem_grenade/proc/primed(var/primed = 1) - if(active) - icon_state = initial(icon_state) + (primed?"_primed":"_active") - -/obj/item/weapon/grenade/chem_grenade/prime() - if(!stage || stage<2) return - - //if(prob(reliability)) - var/has_reagents = 0 - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - if(G.reagents.total_volume) has_reagents = 1 - - active = 0 - if(!has_reagents) - icon_state = initial(icon_state) +"_locked" - playsound(get_turf(src), 'sound/items/Screwdriver2.ogg', 50, 1) - return - - playsound(get_turf(src), 'sound/effects/bamfgas.ogg', 50, 1) - - visible_message("\icon[src] \The [src] bursts open.") - - reservoir = new /obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade() //acts like a stasis beaker, so the chemical reactions don't occur before all the slime reactions have occured - - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - G.reagents.trans_to(reservoir, G.reagents.total_volume) - for(var/obj/item/slime_extract/S in beakers) //checking for reagents inside the slime extracts - S.reagents.trans_to(reservoir, S.reagents.total_volume) - if (E != null) - extract_uses = E.Uses - for(var/i=1,i<=extract_uses,i++)//<-------//exception for slime extracts injected with steroids. The grenade will repeat its checks untill all its remaining uses are gone - if (reservoir.reagents.has_reagent("plasma", 5)) - reservoir.reagents.trans_id_to(E, "plasma", 5) //If the grenade contains a slime extract, the grenade will check in this order - else if (reservoir.reagents.has_reagent("blood", 5)) //for any Plasma -> Blood ->or Water among the reagents of the other containers - reservoir.reagents.trans_id_to(E, "blood", 5) //and inject 5u of it into the slime extract. - else if (reservoir.reagents.has_reagent("water", 5)) - reservoir.reagents.trans_id_to(E, "water", 5) - else if (reservoir.reagents.has_reagent("sugar", 5)) - reservoir.reagents.trans_id_to(E, "sugar", 5) - if(E.reagents.total_volume) //<-------//exception for slime reactions that produce new reagents. The grenade checks if any - E.reagents.trans_to(reservoir, E.reagents.total_volume) //reagents are left in the slime extracts after the slime reactions occured - if (C != null) - extract_uses = C.Uses - for(var/j=1,j<=extract_uses,j++) //why don't anyone ever uses "while" directives anyway? - if (reservoir.reagents.has_reagent("plasma", 5)) - reservoir.reagents.trans_id_to(C, "plasma", 5) //since the order in which slime extracts are inserted matters (in the case of an Ex grenade) - else if (reservoir.reagents.has_reagent("blood", 5))//this allow users to plannify which reagent will get into which extract. - reservoir.reagents.trans_id_to(C, "blood", 5) - else if (reservoir.reagents.has_reagent("water", 5)) - reservoir.reagents.trans_id_to(C, "water", 5) - else if (reservoir.reagents.has_reagent("sugar", 5)) - reservoir.reagents.trans_id_to(C, "sugar", 5) - if(C.reagents.total_volume) - C.reagents.trans_to(reservoir, C.reagents.total_volume) - - reservoir.reagents.update_total() - - reservoir.reagents.trans_to(src, reservoir.reagents.total_volume) - - if(src.reagents.total_volume) //The possible reactions didnt use up all reagents. - var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() - steam.set_up(10, 0, get_turf(src)) - steam.attach(src) - steam.start() - - for(var/atom/A in view(affected_area, get_turf(src))) - if( A == src ) continue - src.reagents.reaction(A, 1, 10) - - invisibility = INVISIBILITY_MAXIMUM //Why am i doing this? - spawn(50) //To make sure all reagents can work - qdel(src) //correctly before deleting the grenade. - /*else - icon_state = initial(icon_state) + "_locked" - crit_fail = 1 - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - G.loc = get_turf(src.loc)*/ - -/obj/item/weapon/grenade/chem_grenade/New() - . = ..() - create_reagents(1000) - -/obj/item/weapon/grenade/chem_grenade/large - name = "Large Chem Grenade" - desc = "An oversized grenade that affects a larger area." - icon_state = "large_grenade" - allowed_containers = list(/obj/item/weapon/reagent_containers/glass, /obj/item/slime_extract) - origin_tech = "combat=3;materials=3" - affected_area = 4 - -obj/item/weapon/grenade/chem_grenade/exgrenade - name = "EX Chem Grenade" - desc = "A specially designed large grenade that can hold three containers." - icon_state = "ex_grenade" - allowed_containers = list(/obj/item/weapon/reagent_containers/glass, /obj/item/slime_extract) - origin_tech = "combat=4;materials=3;engineering=2" - affected_area = 4 - -obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && path != 2) - var/obj/item/device/assembly_holder/det = W - if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right))) - to_chat(user, " Assembly must contain one igniter.") - return - if(!det.secured) - to_chat(user, " Assembly must be secured with screwdriver.") - return - path = 1 - to_chat(user, "You insert [W] into the grenade.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) - user.remove_from_mob(det) - det.loc = src - detonator = det - icon_state = initial(icon_state) +"_ass" - name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" - stage = 1 - else if(istype(W,/obj/item/weapon/screwdriver) && path != 2) - if(stage == 1) - path = 1 - if(beakers.len) - to_chat(user, "You lock the assembly.") - name = "EX Grenade" - else - to_chat(user, "You lock the empty assembly.") - name = "fake grenade" - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) - icon_state = initial(icon_state) +"_locked" - stage = 2 - else if(stage == 2) - if(active && prob(95)) - to_chat(user, "You trigger the assembly!") - prime() - return - else - to_chat(user, "You unlock the assembly.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) - name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" - icon_state = initial(icon_state) + (detonator?"_ass":"") - stage = 1 - active = 0 - else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2) - path = 1 - if(beakers.len == 3) - to_chat(user, " The grenade can not hold more containers.") - return - else - if (istype(W,/obj/item/slime_extract)) - if (inserted_cores > 1) - to_chat(user, "You cannot fit more than two slime cores in this grenade.") - else - if(user.drop_item(W, src)) - to_chat(user, "You add \the [W] to the assembly.") - beakers += W - stage = 1 - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - else if(W.reagents.total_volume) - if(user.drop_item(W, src)) - to_chat(user, "You add \the [W] to the assembly.") - beakers += W - stage = 1 - name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" - else - to_chat(user, " \the [W] is empty.") - -/obj/item/weapon/grenade/chem_grenade/metalfoam - name = "Metal-Foam Grenade" - desc = "Used for emergency sealing of air breaches." - path = 1 - stage = 2 - -/obj/item/weapon/grenade/chem_grenade/metalfoam/New() - ..() - var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - - B1.reagents.add_reagent("aluminum", 30) - B2.reagents.add_reagent("foaming_agent", 10) - B2.reagents.add_reagent("pacid", 10) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - - beakers += B1 - beakers += B2 - icon_state = initial(icon_state) +"_locked" - -/obj/item/weapon/grenade/chem_grenade/incendiary - name = "Incendiary Grenade" - desc = "Used for clearing rooms of living things." - path = 1 - stage = 2 - -/obj/item/weapon/grenade/chem_grenade/incendiary/New() - ..() - var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - - B1.reagents.add_reagent("aluminum", 15) - //B1.reagents.add_reagent("fuel",20) - B2.reagents.add_reagent("plasma", 15) - B2.reagents.add_reagent("sacid", 15) - //B1.reagents.add_reagent("fuel",20) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - - beakers += B1 - beakers += B2 - icon_state = initial(icon_state) +"_locked" - -/obj/item/weapon/grenade/chem_grenade/antiweed - name = "weedkiller grenade" - desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents." - path = 1 - stage = 2 - -/obj/item/weapon/grenade/chem_grenade/antiweed/New() - ..() - var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - - B1.reagents.add_reagent("plantbgone", 25) - B1.reagents.add_reagent("potassium", 25) - B2.reagents.add_reagent("phosphorus", 25) - B2.reagents.add_reagent("sugar", 25) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - - beakers += B1 - beakers += B2 - icon_state = "grenade" - -/obj/item/weapon/grenade/chem_grenade/cleaner - name = "Cleaner Grenade" - desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas." - stage = 2 - path = 1 - -/obj/item/weapon/grenade/chem_grenade/cleaner/New() - ..() - var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - - B1.reagents.add_reagent("fluorosurfactant", 40) - B2.reagents.add_reagent("water", 40) - B2.reagents.add_reagent("cleaner", 10) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - - beakers += B1 - beakers += B2 - icon_state = initial(icon_state) +"_locked" - -/obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade - name = "grenade reservoir" - desc = "..." - icon_state = null - volume = 1000 - flags = FPRINT | OPENCONTAINER | NOREACT +/obj/item/weapon/grenade/chem_grenade + name = "Grenade Casing" + icon_state = "chemg" + item_state = "flashbang" + desc = "A hand made chemical grenade." + w_class = 2.0 + force = 2.0 + var/stage = 0 + var/state = 0 + var/path = 0 + var/obj/item/device/assembly_holder/detonator = null + var/list/beakers = new/list() + var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle) + var/affected_area = 3 + var/inserted_cores = 0 + var/obj/item/slime_extract/E = null //for large and Ex grenades + var/obj/item/slime_extract/C = null //for Ex grenades + var/obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade/reservoir = null + var/extract_uses = 0 + +/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user as mob) + if(!stage || stage==1) + if(detonator) +// detonator.loc=src.loc + detonator.detached() + usr.put_in_hands(detonator) + detonator=null + stage=0 + icon_state = initial(icon_state) + else if(beakers.len) + for(var/obj/B in beakers) + if(istype(B)) + beakers -= B + user.put_in_hands(B) + E = null + C = null + inserted_cores = 0 + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + if(stage > 1 && !active && clown_check(user)) + to_chat(user, "You prime \the [name]!") + + log_attack("[user.name] ([user.ckey]) primed \a [src].") + log_admin("ATTACK: [user] ([user.ckey]) primed \a [src].") + message_admins("ATTACK: [user] ([user.ckey]) primed \a [src].") + + activate() + add_fingerprint(user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + C.throw_mode_on() + +/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && path != 2) + var/obj/item/device/assembly_holder/det = W + if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right))) + to_chat(user, " Assembly must contain one igniter.") + return + if(!det.secured) + to_chat(user, " Assembly must be secured with screwdriver.") + return + path = 1 + to_chat(user, "You add [W] to the metal casing.") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + user.remove_from_mob(det) + det.loc = src + detonator = det + icon_state = initial(icon_state) +"_ass" + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + stage = 1 + else if(istype(W,/obj/item/stack/cable_coil/) && !beakers.len) + var/obj/item/stack/cable_coil/coil = W + if(coil.amount < 2) return + coil.use(2) + var/obj/item/weapon/electrolyzer/E = new /obj/item/weapon/electrolyzer + to_chat(user, "You tightly coil the wire around the metal casing.") + playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) + user.before_take_item(src) + user.put_in_hands(E) + qdel(src) + else if(istype(W,/obj/item/weapon/screwdriver) && path != 2) + if(stage == 1) + path = 1 + if(beakers.len) + to_chat(user, "You lock the assembly.") + name = "grenade" + else +// to_chat(user, "You need to add at least one beaker before locking the assembly.") + to_chat(user, "You lock the empty assembly.") + name = "fake grenade" + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + icon_state = initial(icon_state) +"_locked" + stage = 2 + else if(stage == 2) + if(active && prob(95)) + to_chat(user, "You trigger the assembly!") + prime() + return + else + to_chat(user, "You unlock the assembly.") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + icon_state = initial(icon_state) + (detonator?"_ass":"") + stage = 1 + active = 0 + else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2) + path = 1 + if(beakers.len == 2) + to_chat(user, " The grenade can not hold more containers.") + return + else + if (istype(W,/obj/item/slime_extract)) + if (inserted_cores > 0) + to_chat(user, " This type of grenade cannot hold more than one slime core.") + else + if(user.drop_item(W, src)) + to_chat(user, "You add \the [W] to the assembly.") + beakers += W + stage = 1 + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + else if(W.reagents.total_volume) + if(user.drop_item(W, src)) + to_chat(user, "You add \the [W] to the assembly.") + beakers += W + stage = 1 + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + else + to_chat(user, " \the [W] is empty.") + else if (istype(W,/obj/item/slime_extract)) + to_chat(user, " This grenade case is too small for a slime core to fit in it.") + +/obj/item/weapon/grenade/chem_grenade/examine(mob/user) + ..() + if(detonator) + to_chat(user, "With an attached [detonator.name]") + +/obj/item/weapon/grenade/chem_grenade/Crossed(AM as mob|obj) + if(detonator) + detonator.Crossed(AM) + ..() + +/obj/item/weapon/grenade/chem_grenade/on_found(AM as mob|obj) + if(detonator) + detonator.on_found(AM) + ..() + +/obj/item/weapon/grenade/chem_grenade/activate(mob/user as mob) + if(active) return + + if(detonator) + if(!isigniter(detonator.a_left)) + detonator.a_left.activate() + active = 1 + if(!isigniter(detonator.a_right)) + detonator.a_right.activate() + active = 1 + if(active) + icon_state = initial(icon_state) + "_active" + + if(user) + log_attack("[user.name] ([user.ckey]) primed \a [src]") + log_admin("ATTACK: [user] ([user.ckey]) primed \a [src]") + message_admins("ATTACK: [user] ([user.ckey]) primed \a [src]") + + return + +/obj/item/weapon/grenade/chem_grenade/proc/primed(var/primed = 1) + if(active) + icon_state = initial(icon_state) + (primed?"_primed":"_active") + +/obj/item/weapon/grenade/chem_grenade/prime() + if(!stage || stage<2) return + + //if(prob(reliability)) + var/has_reagents = 0 + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + if(G.reagents.total_volume) has_reagents = 1 + + active = 0 + if(!has_reagents) + icon_state = initial(icon_state) +"_locked" + playsound(get_turf(src), 'sound/items/Screwdriver2.ogg', 50, 1) + return + + playsound(get_turf(src), 'sound/effects/bamfgas.ogg', 50, 1) + + visible_message("\icon[src] \The [src] bursts open.") + + reservoir = new /obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade() //acts like a stasis beaker, so the chemical reactions don't occur before all the slime reactions have occured + + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + G.reagents.trans_to(reservoir, G.reagents.total_volume) + for(var/obj/item/slime_extract/S in beakers) //checking for reagents inside the slime extracts + S.reagents.trans_to(reservoir, S.reagents.total_volume) + if (E != null) + extract_uses = E.Uses + for(var/i=1,i<=extract_uses,i++)//<-------//exception for slime extracts injected with steroids. The grenade will repeat its checks untill all its remaining uses are gone + if (reservoir.reagents.has_reagent("plasma", 5)) + reservoir.reagents.trans_id_to(E, "plasma", 5) //If the grenade contains a slime extract, the grenade will check in this order + else if (reservoir.reagents.has_reagent("blood", 5)) //for any Plasma -> Blood ->or Water among the reagents of the other containers + reservoir.reagents.trans_id_to(E, "blood", 5) //and inject 5u of it into the slime extract. + else if (reservoir.reagents.has_reagent("water", 5)) + reservoir.reagents.trans_id_to(E, "water", 5) + else if (reservoir.reagents.has_reagent("sugar", 5)) + reservoir.reagents.trans_id_to(E, "sugar", 5) + if(E.reagents.total_volume) //<-------//exception for slime reactions that produce new reagents. The grenade checks if any + E.reagents.trans_to(reservoir, E.reagents.total_volume) //reagents are left in the slime extracts after the slime reactions occured + if (C != null) + extract_uses = C.Uses + for(var/j=1,j<=extract_uses,j++) //why don't anyone ever uses "while" directives anyway? + if (reservoir.reagents.has_reagent("plasma", 5)) + reservoir.reagents.trans_id_to(C, "plasma", 5) //since the order in which slime extracts are inserted matters (in the case of an Ex grenade) + else if (reservoir.reagents.has_reagent("blood", 5))//this allow users to plannify which reagent will get into which extract. + reservoir.reagents.trans_id_to(C, "blood", 5) + else if (reservoir.reagents.has_reagent("water", 5)) + reservoir.reagents.trans_id_to(C, "water", 5) + else if (reservoir.reagents.has_reagent("sugar", 5)) + reservoir.reagents.trans_id_to(C, "sugar", 5) + if(C.reagents.total_volume) + C.reagents.trans_to(reservoir, C.reagents.total_volume) + + reservoir.reagents.update_total() + + reservoir.reagents.trans_to(src, reservoir.reagents.total_volume) + + if(src.reagents.total_volume) //The possible reactions didnt use up all reagents. + var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() + steam.set_up(10, 0, get_turf(src)) + steam.attach(src) + steam.start() + + for(var/atom/A in view(affected_area, get_turf(src))) + if( A == src ) continue + src.reagents.reaction(A, 1, 10) + + invisibility = INVISIBILITY_MAXIMUM //Why am i doing this? + spawn(50) //To make sure all reagents can work + qdel(src) //correctly before deleting the grenade. + /*else + icon_state = initial(icon_state) + "_locked" + crit_fail = 1 + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + G.loc = get_turf(src.loc)*/ + +/obj/item/weapon/grenade/chem_grenade/New() + . = ..() + create_reagents(1000) + +/obj/item/weapon/grenade/chem_grenade/large + name = "Large Chem Grenade" + desc = "An oversized grenade that affects a larger area." + icon_state = "large_grenade" + allowed_containers = list(/obj/item/weapon/reagent_containers/glass, /obj/item/slime_extract) + origin_tech = "combat=3;materials=3" + affected_area = 4 + +obj/item/weapon/grenade/chem_grenade/exgrenade + name = "EX Chem Grenade" + desc = "A specially designed large grenade that can hold three containers." + icon_state = "ex_grenade" + allowed_containers = list(/obj/item/weapon/reagent_containers/glass, /obj/item/slime_extract) + origin_tech = "combat=4;materials=3;engineering=2" + affected_area = 4 + +obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && path != 2) + var/obj/item/device/assembly_holder/det = W + if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right))) + to_chat(user, " Assembly must contain one igniter.") + return + if(!det.secured) + to_chat(user, " Assembly must be secured with screwdriver.") + return + path = 1 + to_chat(user, "You insert [W] into the grenade.") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + user.remove_from_mob(det) + det.loc = src + detonator = det + icon_state = initial(icon_state) +"_ass" + name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" + stage = 1 + else if(istype(W,/obj/item/weapon/screwdriver) && path != 2) + if(stage == 1) + path = 1 + if(beakers.len) + to_chat(user, "You lock the assembly.") + name = "EX Grenade" + else + to_chat(user, "You lock the empty assembly.") + name = "fake grenade" + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + icon_state = initial(icon_state) +"_locked" + stage = 2 + else if(stage == 2) + if(active && prob(95)) + to_chat(user, "You trigger the assembly!") + prime() + return + else + to_chat(user, "You unlock the assembly.") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" + icon_state = initial(icon_state) + (detonator?"_ass":"") + stage = 1 + active = 0 + else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2) + path = 1 + if(beakers.len == 3) + to_chat(user, " The grenade can not hold more containers.") + return + else + if (istype(W,/obj/item/slime_extract)) + if (inserted_cores > 1) + to_chat(user, "You cannot fit more than two slime cores in this grenade.") + else + if(user.drop_item(W, src)) + to_chat(user, "You add \the [W] to the assembly.") + beakers += W + stage = 1 + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + else if(W.reagents.total_volume) + if(user.drop_item(W, src)) + to_chat(user, "You add \the [W] to the assembly.") + beakers += W + stage = 1 + name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" + else + to_chat(user, " \the [W] is empty.") + +/obj/item/weapon/grenade/chem_grenade/metalfoam + name = "Metal-Foam Grenade" + desc = "Used for emergency sealing of air breaches." + path = 1 + stage = 2 + +/obj/item/weapon/grenade/chem_grenade/metalfoam/New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent("aluminum", 30) + B2.reagents.add_reagent("foaming_agent", 10) + B2.reagents.add_reagent("pacid", 10) + + detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + + beakers += B1 + beakers += B2 + icon_state = initial(icon_state) +"_locked" + +/obj/item/weapon/grenade/chem_grenade/incendiary + name = "Incendiary Grenade" + desc = "Used for clearing rooms of living things." + path = 1 + stage = 2 + +/obj/item/weapon/grenade/chem_grenade/incendiary/New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent("aluminum", 15) + //B1.reagents.add_reagent("fuel",20) + B2.reagents.add_reagent("plasma", 15) + B2.reagents.add_reagent("sacid", 15) + //B1.reagents.add_reagent("fuel",20) + + detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + + beakers += B1 + beakers += B2 + icon_state = initial(icon_state) +"_locked" + +/obj/item/weapon/grenade/chem_grenade/antiweed + name = "weedkiller grenade" + desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents." + path = 1 + stage = 2 + +/obj/item/weapon/grenade/chem_grenade/antiweed/New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent("plantbgone", 25) + B1.reagents.add_reagent("potassium", 25) + B2.reagents.add_reagent("phosphorus", 25) + B2.reagents.add_reagent("sugar", 25) + + detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + + beakers += B1 + beakers += B2 + icon_state = "grenade" + +/obj/item/weapon/grenade/chem_grenade/cleaner + name = "Cleaner Grenade" + desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas." + stage = 2 + path = 1 + +/obj/item/weapon/grenade/chem_grenade/cleaner/New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent("fluorosurfactant", 40) + B2.reagents.add_reagent("water", 40) + B2.reagents.add_reagent("cleaner", 10) + + detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + + beakers += B1 + beakers += B2 + icon_state = initial(icon_state) +"_locked" + +/obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade + name = "grenade reservoir" + desc = "..." + icon_state = null + volume = 1000 + flags = FPRINT | OPENCONTAINER | NOREACT diff --git a/code/game/objects/items/weapons/grenades/emgrenade.dm b/code/game/objects/items/weapons/grenades/emgrenade.dm index a3614adc5ec..b4d5706f150 100644 --- a/code/game/objects/items/weapons/grenades/emgrenade.dm +++ b/code/game/objects/items/weapons/grenades/emgrenade.dm @@ -1,12 +1,12 @@ -/obj/item/weapon/grenade/empgrenade - name = "emp grenade" - icon_state = "emp" - item_state = "emp" - origin_tech = "materials=2;magnets=3" - - prime() - ..() - if(empulse(src, 4, 10)) - del(src) - return - +/obj/item/weapon/grenade/empgrenade + name = "emp grenade" + icon_state = "emp" + item_state = "emp" + origin_tech = "materials=2;magnets=3" + + prime() + ..() + if(empulse(src, 4, 10)) + del(src) + return + diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 3c2de64663f..1b5423a2d2b 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -1,180 +1,180 @@ -/obj/item/weapon/grenade/flashbang - name = "flashbang" - icon_state = "flashbang" - item_state = "flashbang" - origin_tech = "materials=2;combat=1" - var/banglet = 0 - -/obj/item/weapon/grenade/flashbang/prime() - update_mob() - var/flashbang_turf = get_turf(src) - if(!flashbang_turf) - return - for(var/mob/living/carbon/M in get_hearers_in_view(7, flashbang_turf)) - if(isbrain(M) || !istype(M)) - continue - bang(get_turf(M), M) - - for(var/obj/effect/blob/B in get_hear(8,flashbang_turf)) //Blob damage here - var/damage = round(15/(get_dist(B,get_turf(src))+1)) - B.health -= damage - B.update_icon() - qdel(src) - -/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged. - if (locate(/obj/item/weapon/cloaking_device, M)) // Called during the loop that bangs people in lockers/containers and when banging - for(var/obj/item/weapon/cloaking_device/S in M) // people in normal view. Could theroetically be called during other explosions. - S.active = 0 // -- Polymorph - S.icon_state = "shield0" - +/obj/item/weapon/grenade/flashbang + name = "flashbang" + icon_state = "flashbang" + item_state = "flashbang" + origin_tech = "materials=2;combat=1" + var/banglet = 0 + +/obj/item/weapon/grenade/flashbang/prime() + update_mob() + var/flashbang_turf = get_turf(src) + if(!flashbang_turf) + return + for(var/mob/living/carbon/M in get_hearers_in_view(7, flashbang_turf)) + if(isbrain(M) || !istype(M)) + continue + bang(get_turf(M), M) + + for(var/obj/effect/blob/B in get_hear(8,flashbang_turf)) //Blob damage here + var/damage = round(15/(get_dist(B,get_turf(src))+1)) + B.health -= damage + B.update_icon() + qdel(src) + +/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged. + if (locate(/obj/item/weapon/cloaking_device, M)) // Called during the loop that bangs people in lockers/containers and when banging + for(var/obj/item/weapon/cloaking_device/S in M) // people in normal view. Could theroetically be called during other explosions. + S.active = 0 // -- Polymorph + S.icon_state = "shield0" + to_chat(M, "BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) - -//Checking for protections - var/eye_safety = 0 - var/ear_safety = 0 - if(iscarbon(M)) - eye_safety = M.eyecheck() - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.earprot()) - ear_safety += 2 - if(M_HULK in M.mutations) - ear_safety += 1 - if(istype(M:head, /obj/item/clothing/head/helmet)) - ear_safety += 1 - -//Flashing everyone - if(eye_safety < 1) - flick("e_flash", M.flash) - M.Stun(2) - M.Weaken(10) - - - -//Now applying sound - if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M)) - if(ear_safety > 0) - M.Stun(2) - M.Weaken(1) - else - M.Stun(10) - M.Weaken(3) - if ((prob(14) || (M == src.loc && prob(70)))) - M.ear_damage += rand(1, 10) - else - M.ear_damage += rand(0, 5) - M.ear_deaf = max(M.ear_deaf,15) - - else if(get_dist(M, T) <= 5) - if(!ear_safety) - M.Stun(8) - M.ear_damage += rand(0, 3) - M.ear_deaf = max(M.ear_deaf,10) - - else if(!ear_safety) - M.Stun(4) - M.ear_damage += rand(0, 1) - M.ear_deaf = max(M.ear_deaf,5) - -//This really should be in mob not every check - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if (E && E.damage >= E.min_bruised_damage) + playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + +//Checking for protections + var/eye_safety = 0 + var/ear_safety = 0 + if(iscarbon(M)) + eye_safety = M.eyecheck() + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.earprot()) + ear_safety += 2 + if(M_HULK in M.mutations) + ear_safety += 1 + if(istype(M:head, /obj/item/clothing/head/helmet)) + ear_safety += 1 + +//Flashing everyone + if(eye_safety < 1) + flick("e_flash", M.flash) + M.Stun(2) + M.Weaken(10) + + + +//Now applying sound + if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M)) + if(ear_safety > 0) + M.Stun(2) + M.Weaken(1) + else + M.Stun(10) + M.Weaken(3) + if ((prob(14) || (M == src.loc && prob(70)))) + M.ear_damage += rand(1, 10) + else + M.ear_damage += rand(0, 5) + M.ear_deaf = max(M.ear_deaf,15) + + else if(get_dist(M, T) <= 5) + if(!ear_safety) + M.Stun(8) + M.ear_damage += rand(0, 3) + M.ear_deaf = max(M.ear_deaf,10) + + else if(!ear_safety) + M.Stun(4) + M.ear_damage += rand(0, 1) + M.ear_deaf = max(M.ear_deaf,5) + +//This really should be in mob not every check + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] + if (E && E.damage >= E.min_bruised_damage) to_chat(M, "Your eyes start to burn badly!") - if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang))) - if (E.damage >= E.min_broken_damage) + if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang))) + if (E.damage >= E.min_broken_damage) to_chat(M, "You can't see anything!") - if (M.ear_damage >= 15) + if (M.ear_damage >= 15) to_chat(M, "Your ears start to ring badly!") - if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang))) - if (prob(M.ear_damage - 10 + 5)) + if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang))) + if (prob(M.ear_damage - 10 + 5)) to_chat(M, "You can't hear anything!") - M.sdisabilities |= DEAF - else - if (M.ear_damage >= 5) + M.sdisabilities |= DEAF + else + if (M.ear_damage >= 5) to_chat(M, "Your ears start to ring!") - M.update_icons() - -/obj/effect/effect/smoke/flashbang - name = "illumination" - time_to_live = 10 - opacity = 0 - icon_state = "sparks" - -/obj/effect/effect/smoke/flashbang/New() - ..() - set_light(15) - -/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve - desc = "Use of this weapon may constiute a war crime in your area, consult your local captain." - name = "clusterbang" - icon = 'icons/obj/grenade.dmi' - icon_state = "clusterbang" - -/obj/item/weapon/grenade/flashbang/clusterbang/prime() - var/numspawned = rand(4,8) - var/again = 0 - for(var/more = numspawned,more > 0,more--) - if(prob(35)) - again++ - numspawned -- - - for(,numspawned > 0, numspawned--) - spawn(0) - new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs - playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) - - for(,again > 0, again--) - spawn(0) - new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs - playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) - spawn(0) - qdel(src) - return - -/obj/item/weapon/grenade/flashbang/clusterbang/segment - desc = "A smaller segment of a clusterbang. Better run." - name = "clusterbang segment" - icon = 'icons/obj/grenade.dmi' - icon_state = "clusterbang_segment" - -/obj/item/weapon/grenade/flashbang/clusterbang/segment/New()//Segments should never exist except part of the clusterbang, since these immediately 'do their thing' and asplode - icon_state = "clusterbang_segment_active" - active = 1 - banglet = 1 - var/stepdist = rand(1,4)//How far to step - var/temploc = src.loc//Saves the current location to know where to step away from - walk_away(src,temploc,stepdist)//I must go, my people need me - var/dettime = rand(15,60) - spawn(dettime) - prime() - ..() - -/obj/item/weapon/grenade/flashbang/clusterbang/segment/prime() - var/numspawned = rand(4,8) - for(var/more = numspawned,more > 0,more--) - if(prob(35)) - numspawned -- - - for(,numspawned > 0, numspawned--) - spawn(0) - new /obj/item/weapon/grenade/flashbang/cluster(src.loc) - playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) - spawn(0) - qdel(src) - return - -/obj/item/weapon/grenade/flashbang/cluster/New()//Same concept as the segments, so that all of the parts don't become reliant on the clusterbang - spawn(0) - icon_state = "flashbang_active" - active = 1 - banglet = 1 - var/stepdist = rand(1,3) - var/temploc = src.loc - walk_away(src,temploc,stepdist) - var/dettime = rand(15,60) - spawn(dettime) - prime() - ..() + M.update_icons() + +/obj/effect/effect/smoke/flashbang + name = "illumination" + time_to_live = 10 + opacity = 0 + icon_state = "sparks" + +/obj/effect/effect/smoke/flashbang/New() + ..() + set_light(15) + +/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve + desc = "Use of this weapon may constiute a war crime in your area, consult your local captain." + name = "clusterbang" + icon = 'icons/obj/grenade.dmi' + icon_state = "clusterbang" + +/obj/item/weapon/grenade/flashbang/clusterbang/prime() + var/numspawned = rand(4,8) + var/again = 0 + for(var/more = numspawned,more > 0,more--) + if(prob(35)) + again++ + numspawned -- + + for(,numspawned > 0, numspawned--) + spawn(0) + new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs + playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) + + for(,again > 0, again--) + spawn(0) + new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs + playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) + spawn(0) + qdel(src) + return + +/obj/item/weapon/grenade/flashbang/clusterbang/segment + desc = "A smaller segment of a clusterbang. Better run." + name = "clusterbang segment" + icon = 'icons/obj/grenade.dmi' + icon_state = "clusterbang_segment" + +/obj/item/weapon/grenade/flashbang/clusterbang/segment/New()//Segments should never exist except part of the clusterbang, since these immediately 'do their thing' and asplode + icon_state = "clusterbang_segment_active" + active = 1 + banglet = 1 + var/stepdist = rand(1,4)//How far to step + var/temploc = src.loc//Saves the current location to know where to step away from + walk_away(src,temploc,stepdist)//I must go, my people need me + var/dettime = rand(15,60) + spawn(dettime) + prime() + ..() + +/obj/item/weapon/grenade/flashbang/clusterbang/segment/prime() + var/numspawned = rand(4,8) + for(var/more = numspawned,more > 0,more--) + if(prob(35)) + numspawned -- + + for(,numspawned > 0, numspawned--) + spawn(0) + new /obj/item/weapon/grenade/flashbang/cluster(src.loc) + playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) + spawn(0) + qdel(src) + return + +/obj/item/weapon/grenade/flashbang/cluster/New()//Same concept as the segments, so that all of the parts don't become reliant on the clusterbang + spawn(0) + icon_state = "flashbang_active" + active = 1 + banglet = 1 + var/stepdist = rand(1,3) + var/temploc = src.loc + walk_away(src,temploc,stepdist) + var/dettime = rand(15,60) + spawn(dettime) + prime() + ..() diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index cf45a056ef7..bdc1a134c07 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -1,122 +1,122 @@ -/obj/item/weapon/grenade - name = "grenade" - desc = "A hand held grenade, with an adjustable timer." - w_class = 2.0 - icon = 'icons/obj/grenade.dmi' - icon_state = "grenade" - item_state = "flashbang" - throw_speed = 4 - throw_range = 20 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - var/active = 0 - var/det_time = 50 - -/obj/item/weapon/grenade/proc/clown_check(var/mob/living/user) - if((M_CLUMSY in user.mutations) && prob(50)) +/obj/item/weapon/grenade + name = "grenade" + desc = "A hand held grenade, with an adjustable timer." + w_class = 2.0 + icon = 'icons/obj/grenade.dmi' + icon_state = "grenade" + item_state = "flashbang" + throw_speed = 4 + throw_range = 20 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + var/active = 0 + var/det_time = 50 + +/obj/item/weapon/grenade/proc/clown_check(var/mob/living/user) + if((M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "Huh? How does this thing work?") - - activate(user) - add_fingerprint(user) - spawn(5) - prime(user) - return 0 - return 1 - - -/*/obj/item/weapon/grenade/afterattack(atom/target as mob|obj|turf|area, mob/user as mob) - if (istype(target, /obj/item/weapon/storage)) return ..() // Trying to put it in a full container - if (istype(target, /obj/item/weapon/gun/grenadelauncher)) return ..() - if((user.get_active_hand() == src) && (!active) && (clown_check(user)) && target.loc != src.loc) + + activate(user) + add_fingerprint(user) + spawn(5) + prime(user) + return 0 + return 1 + + +/*/obj/item/weapon/grenade/afterattack(atom/target as mob|obj|turf|area, mob/user as mob) + if (istype(target, /obj/item/weapon/storage)) return ..() // Trying to put it in a full container + if (istype(target, /obj/item/weapon/gun/grenadelauncher)) return ..() + if((user.get_active_hand() == src) && (!active) && (clown_check(user)) && target.loc != src.loc) to_chat(user, "You prime the [name]! [det_time/10] seconds!") - active = 1 - icon_state = initial(icon_state) + "_active" - playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - spawn(det_time) - prime() - return - user.dir = get_dir(user, target) - user.drop_item(null, ) - var/t = (isturf(target) ? target : target.loc) - walk_towards(src, t, 3) - return*/ - - -/obj/item/weapon/grenade/examine(mob/user) - ..() - if(det_time > 1) + active = 1 + icon_state = initial(icon_state) + "_active" + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + spawn(det_time) + prime() + return + user.dir = get_dir(user, target) + user.drop_item(null, ) + var/t = (isturf(target) ? target : target.loc) + walk_towards(src, t, 3) + return*/ + + +/obj/item/weapon/grenade/examine(mob/user) + ..() + if(det_time > 1) to_chat(user, "The timer is set to [det_time/10] seconds.") - return + return to_chat(user, "\The [src] is set for instant detonation.") - - -/obj/item/weapon/grenade/attack_self(mob/user as mob) - if(!active) - if(clown_check(user)) + + +/obj/item/weapon/grenade/attack_self(mob/user as mob) + if(!active) + if(clown_check(user)) to_chat(user, "You prime \the [name]! [det_time/10] seconds!") - - activate(user) - add_fingerprint(user) - if(iscarbon(user)) - var/mob/living/carbon/C = user - C.throw_mode_on() - return - - -/obj/item/weapon/grenade/proc/activate(mob/user as mob) - if(active) - return - - if(user) - log_attack("[user.name] ([user.ckey]) primed \a [src]") - log_admin("ATTACK: [user] ([user.ckey]) primed \a [src]") - message_admins("ATTACK: [user] ([user.ckey]) primed \a [src]") - - icon_state = initial(icon_state) + "_active" - active = 1 - playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - - spawn(det_time) - prime(user) - return - - -/obj/item/weapon/grenade/proc/prime() -// playsound(loc, 'sound/items/Welder2.ogg', 25, 1) - var/turf/T = get_turf(src) - if(T) - T.hotspot_expose(700,125,surfaces=istype(loc,/turf)) - -/obj/item/weapon/grenade/proc/update_mob() - if(ismob(loc)) - var/mob/M = loc - M.drop_from_inventory(src) - - -/obj/item/weapon/grenade/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isscrewdriver(W)) - switch(det_time) - if ("1") - det_time = 10 + + activate(user) + add_fingerprint(user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + C.throw_mode_on() + return + + +/obj/item/weapon/grenade/proc/activate(mob/user as mob) + if(active) + return + + if(user) + log_attack("[user.name] ([user.ckey]) primed \a [src]") + log_admin("ATTACK: [user] ([user.ckey]) primed \a [src]") + message_admins("ATTACK: [user] ([user.ckey]) primed \a [src]") + + icon_state = initial(icon_state) + "_active" + active = 1 + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + + spawn(det_time) + prime(user) + return + + +/obj/item/weapon/grenade/proc/prime() +// playsound(loc, 'sound/items/Welder2.ogg', 25, 1) + var/turf/T = get_turf(src) + if(T) + T.hotspot_expose(700,125,surfaces=istype(loc,/turf)) + +/obj/item/weapon/grenade/proc/update_mob() + if(ismob(loc)) + var/mob/M = loc + M.drop_from_inventory(src) + + +/obj/item/weapon/grenade/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isscrewdriver(W)) + switch(det_time) + if ("1") + det_time = 10 to_chat(user, "You set the [name] for 1 second detonation time.") - if ("10") - det_time = 30 + if ("10") + det_time = 30 to_chat(user, "You set the [name] for 3 second detonation time.") - if ("30") - det_time = 50 + if ("30") + det_time = 50 to_chat(user, "You set the [name] for 5 second detonation time.") - if ("50") - det_time = 1 + if ("50") + det_time = 1 to_chat(user, "You set the [name] for instant detonation.") - add_fingerprint(user) - ..() - return - -/obj/item/weapon/grenade/attack_hand() - walk(src, null, null) - ..() - return - -/obj/item/weapon/grenade/attack_paw(mob/user as mob) - return attack_hand(user) + add_fingerprint(user) + ..() + return + +/obj/item/weapon/grenade/attack_hand() + walk(src, null, null) + ..() + return + +/obj/item/weapon/grenade/attack_paw(mob/user as mob) + return attack_hand(user) diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index f2c24da208c..5db81e4a87a 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -1,35 +1,35 @@ -/obj/item/weapon/grenade/smokebomb - desc = "It is set to detonate in 2 seconds." - name = "smoke bomb" - icon = 'icons/obj/grenade.dmi' - icon_state = "flashbang" - det_time = 20 - item_state = "flashbang" - flags = FPRINT - slot_flags = SLOT_BELT - var/datum/effect/effect/system/smoke_spread/bad/smoke - - New() - ..() - src.smoke = new /datum/effect/effect/system/smoke_spread/bad - src.smoke.attach(src) - - prime() - playsound(get_turf(src), 'sound/effects/smoke.ogg', 50, 1, -3) - src.smoke.set_up(10, 0, usr.loc) - spawn(0) - src.smoke.start() - sleep(10) - src.smoke.start() - sleep(10) - src.smoke.start() - sleep(10) - src.smoke.start() - - for(var/obj/effect/blob/B in view(8,src)) - var/damage = round(30/(get_dist(B,src)+1)) - B.health -= damage - B.update_icon() - sleep(80) - qdel(src) - return +/obj/item/weapon/grenade/smokebomb + desc = "It is set to detonate in 2 seconds." + name = "smoke bomb" + icon = 'icons/obj/grenade.dmi' + icon_state = "flashbang" + det_time = 20 + item_state = "flashbang" + flags = FPRINT + slot_flags = SLOT_BELT + var/datum/effect/effect/system/smoke_spread/bad/smoke + + New() + ..() + src.smoke = new /datum/effect/effect/system/smoke_spread/bad + src.smoke.attach(src) + + prime() + playsound(get_turf(src), 'sound/effects/smoke.ogg', 50, 1, -3) + src.smoke.set_up(10, 0, usr.loc) + spawn(0) + src.smoke.start() + sleep(10) + src.smoke.start() + sleep(10) + src.smoke.start() + sleep(10) + src.smoke.start() + + for(var/obj/effect/blob/B in view(8,src)) + var/damage = round(30/(get_dist(B,src)+1)) + B.health -= damage + B.update_icon() + sleep(80) + qdel(src) + return diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 753da0059dc..6e23cd9e5d6 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -1,99 +1,99 @@ -/obj/item/weapon/grenade/spawnergrenade - desc = "It is set to detonate in 5 seconds. It will unleash unleash an unspecified anomaly into the vicinity." - name = "delivery grenade" - icon = 'icons/obj/grenade.dmi' - icon_state = "delivery" - item_state = "flashbang" - origin_tech = "materials=3;magnets=4" - var/banglet = 0 - var/spawner_type = null // must be an object path - var/deliveryamt = 1 // amount of type to deliver - var/mob/living/owner = null - var/mob_faction = "" - -/obj/item/weapon/grenade/spawnergrenade/prime(var/mob/living/L = null) - // Prime now just handles the two loops that query for people in lockers and people who can see it. - if(spawner_type && deliveryamt) - // Make a quick flash - var/turf/T = get_turf(src) - playsound(T, 'sound/effects/phasein.ogg', 100, 1) - for(var/mob/living/carbon/human/M in viewers(T, null)) - if(M:eyecheck() <= 0) - flick("e_flash", M.flash) // flash dose faggots - - var/list/spawned_atoms = list() - for(var/i=1, i<=deliveryamt, i++) - var/atom/movable/x = new spawner_type - spawned_atoms += x - x.loc = T - if(prob(50)) - for(var/j = 1, j <= rand(1, 3), j++) - step(x, pick(NORTH,SOUTH,EAST,WEST)) - if(L && istype(L)) - handle_faction(x,L) - // Spawn some hostile critters - postPrime(spawned_atoms) - qdel(src) - return - -/obj/item/weapon/grenade/spawnergrenade/proc/handle_faction(var/mob/living/spawned, var/mob/living/L) - return - -/obj/item/weapon/grenade/spawnergrenade/proc/postPrime(var/list/spawned_atoms) - return - -/obj/item/weapon/grenade/spawnergrenade/manhacks - name = "manhack delivery grenade" - spawner_type = /mob/living/simple_animal/hostile/viscerator - deliveryamt = 5 - origin_tech = "materials=3;magnets=4;syndicate=4" - -/obj/item/weapon/grenade/spawnergrenade/manhacks/handle_faction(var/mob/living/spawned, var/mob/living/L) - if(!spawned || !L) - return - - spawned.faction = "\ref[L]" - -/obj/item/weapon/grenade/spawnergrenade/manhacks/syndicate - desc = "It is set to detonate in 5 seconds. It will unleash a pair of hostile visceratorrs that will hack at any nearby targets indiscriminately." - name = "viscerator grenade" - spawner_type = /mob/living/simple_animal/hostile/viscerator - deliveryamt = 2 - origin_tech = "materials=3;magnets=4;syndicate=4" - mob_faction = "syndicate" - -/obj/item/weapon/grenade/spawnergrenade/manhacks/syndicate/handle_faction(var/mob/living/spawned, var/mob/living/L) - if(!spawned || !L) - return - - if(!isnukeop(L))//"syndicate" faction mobs don't attack nuke ops by default - spawned.faction = "\ref[L]" - -/obj/item/weapon/grenade/spawnergrenade/spesscarp - name = "carp delivery grenade" - spawner_type = /mob/living/simple_animal/hostile/carp - deliveryamt = 5 - origin_tech = "materials=3;magnets=4;syndicate=4" - -/obj/item/weapon/grenade/spawnergrenade/beenade - name = "bee-nade" - icon_state = "beenade" - spawner_type = /mob/living/simple_animal/bee - deliveryamt = 15 - origin_tech = "materials=3;magnets=4;biotech=4" - - -/obj/item/weapon/grenade/spawnergrenade/beenade/postPrime(var/list/spawned_atoms) - if(!spawned_atoms || !spawned_atoms.len) - return - playsound(get_turf(src), 'sound/effects/bees.ogg', 100, 1) - for(var/A in spawned_atoms) - var/mob/living/simple_animal/bee/BEE = A - if(!istype(BEE)) - continue - BEE.strength = 1 - BEE.toxic = 5 - BEE.mut = 2 - BEE.feral = 25 - BEE.icon_state = "bees1-feral" - BEE.newTarget() +/obj/item/weapon/grenade/spawnergrenade + desc = "It is set to detonate in 5 seconds. It will unleash unleash an unspecified anomaly into the vicinity." + name = "delivery grenade" + icon = 'icons/obj/grenade.dmi' + icon_state = "delivery" + item_state = "flashbang" + origin_tech = "materials=3;magnets=4" + var/banglet = 0 + var/spawner_type = null // must be an object path + var/deliveryamt = 1 // amount of type to deliver + var/mob/living/owner = null + var/mob_faction = "" + +/obj/item/weapon/grenade/spawnergrenade/prime(var/mob/living/L = null) + // Prime now just handles the two loops that query for people in lockers and people who can see it. + if(spawner_type && deliveryamt) + // Make a quick flash + var/turf/T = get_turf(src) + playsound(T, 'sound/effects/phasein.ogg', 100, 1) + for(var/mob/living/carbon/human/M in viewers(T, null)) + if(M:eyecheck() <= 0) + flick("e_flash", M.flash) // flash dose faggots + + var/list/spawned_atoms = list() + for(var/i=1, i<=deliveryamt, i++) + var/atom/movable/x = new spawner_type + spawned_atoms += x + x.loc = T + if(prob(50)) + for(var/j = 1, j <= rand(1, 3), j++) + step(x, pick(NORTH,SOUTH,EAST,WEST)) + if(L && istype(L)) + handle_faction(x,L) + // Spawn some hostile critters + postPrime(spawned_atoms) + qdel(src) + return + +/obj/item/weapon/grenade/spawnergrenade/proc/handle_faction(var/mob/living/spawned, var/mob/living/L) + return + +/obj/item/weapon/grenade/spawnergrenade/proc/postPrime(var/list/spawned_atoms) + return + +/obj/item/weapon/grenade/spawnergrenade/manhacks + name = "manhack delivery grenade" + spawner_type = /mob/living/simple_animal/hostile/viscerator + deliveryamt = 5 + origin_tech = "materials=3;magnets=4;syndicate=4" + +/obj/item/weapon/grenade/spawnergrenade/manhacks/handle_faction(var/mob/living/spawned, var/mob/living/L) + if(!spawned || !L) + return + + spawned.faction = "\ref[L]" + +/obj/item/weapon/grenade/spawnergrenade/manhacks/syndicate + desc = "It is set to detonate in 5 seconds. It will unleash a pair of hostile visceratorrs that will hack at any nearby targets indiscriminately." + name = "viscerator grenade" + spawner_type = /mob/living/simple_animal/hostile/viscerator + deliveryamt = 2 + origin_tech = "materials=3;magnets=4;syndicate=4" + mob_faction = "syndicate" + +/obj/item/weapon/grenade/spawnergrenade/manhacks/syndicate/handle_faction(var/mob/living/spawned, var/mob/living/L) + if(!spawned || !L) + return + + if(!isnukeop(L))//"syndicate" faction mobs don't attack nuke ops by default + spawned.faction = "\ref[L]" + +/obj/item/weapon/grenade/spawnergrenade/spesscarp + name = "carp delivery grenade" + spawner_type = /mob/living/simple_animal/hostile/carp + deliveryamt = 5 + origin_tech = "materials=3;magnets=4;syndicate=4" + +/obj/item/weapon/grenade/spawnergrenade/beenade + name = "bee-nade" + icon_state = "beenade" + spawner_type = /mob/living/simple_animal/bee + deliveryamt = 15 + origin_tech = "materials=3;magnets=4;biotech=4" + + +/obj/item/weapon/grenade/spawnergrenade/beenade/postPrime(var/list/spawned_atoms) + if(!spawned_atoms || !spawned_atoms.len) + return + playsound(get_turf(src), 'sound/effects/bees.ogg', 100, 1) + for(var/A in spawned_atoms) + var/mob/living/simple_animal/bee/BEE = A + if(!istype(BEE)) + continue + BEE.strength = 1 + BEE.toxic = 5 + BEE.mut = 2 + BEE.feral = 25 + BEE.icon_state = "bees1-feral" + BEE.newTarget() diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index f2e713e9092..b4465dcb273 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -1,177 +1,177 @@ -/obj/item/weapon/handcuffs - name = "handcuffs" - desc = "Use this to keep prisoners in line." - setGender(PLURAL) - icon = 'icons/obj/items.dmi' - icon_state = "handcuff" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throwforce = 5 - w_class = 2.0 - throw_speed = 2 - throw_range = 5 - starting_materials = list(MAT_IRON = 500) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - origin_tech = "materials=1" - var/dispenser = 0 - var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes - -/obj/item/weapon/handcuffs/attack(mob/living/carbon/C as mob, mob/user as mob) - if(!istype(C)) return - if(istype(src, /obj/item/weapon/handcuffs/cyborg) && isrobot(user)) - if(!C.handcuffed) - var/turf/p_loc = user.loc - var/turf/p_loc_m = C.loc - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) - for(var/mob/O in viewers(user, null)) - O.show_message("[user] is trying to put handcuffs on [C]!", 1) - spawn(30) - if(!C) return - if(p_loc == user.loc && p_loc_m == C.loc) - C.handcuffed = new /obj/item/weapon/handcuffs(C) - C.update_inv_handcuffed() - - else - if ((M_CLUMSY in usr.mutations) && prob(50)) +/obj/item/weapon/handcuffs + name = "handcuffs" + desc = "Use this to keep prisoners in line." + setGender(PLURAL) + icon = 'icons/obj/items.dmi' + icon_state = "handcuff" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 5 + w_class = 2.0 + throw_speed = 2 + throw_range = 5 + starting_materials = list(MAT_IRON = 500) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + origin_tech = "materials=1" + var/dispenser = 0 + var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes + +/obj/item/weapon/handcuffs/attack(mob/living/carbon/C as mob, mob/user as mob) + if(!istype(C)) return + if(istype(src, /obj/item/weapon/handcuffs/cyborg) && isrobot(user)) + if(!C.handcuffed) + var/turf/p_loc = user.loc + var/turf/p_loc_m = C.loc + playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + for(var/mob/O in viewers(user, null)) + O.show_message("[user] is trying to put handcuffs on [C]!", 1) + spawn(30) + if(!C) return + if(p_loc == user.loc && p_loc_m == C.loc) + C.handcuffed = new /obj/item/weapon/handcuffs(C) + C.update_inv_handcuffed() + + else + if ((M_CLUMSY in usr.mutations) && prob(50)) to_chat(usr, "Uh ... how do those things work?!") - if (istype(C, /mob/living/carbon/human)) - if(!C.handcuffed) - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = user - O.target = user - O.item = user.get_active_hand() - O.s_loc = user.loc - O.t_loc = user.loc - O.place = "handcuff" - C.requests += O - spawn( 0 ) - O.process() - return - return - if (!usr.dexterity_check()) + if (istype(C, /mob/living/carbon/human)) + if(!C.handcuffed) + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = user + O.target = user + O.item = user.get_active_hand() + O.s_loc = user.loc + O.t_loc = user.loc + O.place = "handcuff" + C.requests += O + spawn( 0 ) + O.process() + return + return + if (!usr.dexterity_check()) to_chat(usr, "You don't have the dexterity to do this!") - return - if (istype(C, /mob/living/carbon/human)) - if(!C.handcuffed) - C.attack_log += text("\[[time_stamp()]\] Has been handcuffed (attempt) by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Attempted to handcuff [C.name] ([C.ckey])") - if(!iscarbon(user)) - C.LAssailant = null - else - C.LAssailant = user - - log_attack("[user.name] ([user.ckey]) Attempted to handcuff [C.name] ([C.ckey])") - - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = user - O.target = C - O.item = user.get_active_hand() - O.s_loc = user.loc - O.t_loc = C.loc - O.place = "handcuff" - C.requests += O - spawn( 0 ) - if(istype(src, /obj/item/weapon/handcuffs/cable)) - feedback_add_details("handcuffs","C") - playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) - else - feedback_add_details("handcuffs","H") - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) - O.process() - return - else - if(!C.handcuffed) - var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) - O.source = user - O.target = C - O.item = user.get_active_hand() - O.s_loc = user.loc - O.t_loc = C.loc - O.place = "handcuff" - C.requests += O - spawn( 0 ) - if(istype(src, /obj/item/weapon/handcuffs/cable)) - playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) - else - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) - O.process() - return - return - -/obj/item/weapon/handcuffs/cable - name = "cable restraints" - desc = "Looks like some cables tied together. Could be used to tie something up." - icon_state = "cuff_red" - _color = "red" - breakouttime = 300 //Deciseconds = 30s - -/obj/item/weapon/handcuffs/cable/red - icon_state = "cuff_red" - -/obj/item/weapon/handcuffs/cable/yellow - icon_state = "cuff_yellow" - _color = "yellow" - -/obj/item/weapon/handcuffs/cable/blue - icon_state = "cuff_blue" - _color = "blue" - -/obj/item/weapon/handcuffs/cable/green - icon_state = "cuff_green" - _color = "green" - -/obj/item/weapon/handcuffs/cable/pink - icon_state = "cuff_pink" - _color = "pink" - -/obj/item/weapon/handcuffs/cable/orange - icon_state = "cuff_orange" - _color = "orange" - -/obj/item/weapon/handcuffs/cable/cyan - icon_state = "cuff_cyan" - _color = "cyan" - -/obj/item/weapon/handcuffs/cable/white - icon_state = "cuff_white" - _color = "white" - -/obj/item/weapon/handcuffs/cable/update_icon() - if(_color) - icon_state = "cuff_[_color]" - -/obj/item/weapon/handcuffs/cyborg - dispenser = 1 - -/obj/item/weapon/handcuffs/cable/attackby(var/obj/item/I, mob/user as mob) - ..() - if(istype(I, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = I - var/obj/item/weapon/wirerod/W = new /obj/item/weapon/wirerod - R.use(1) - - user.before_take_item(src) - - user.put_in_hands(W) + return + if (istype(C, /mob/living/carbon/human)) + if(!C.handcuffed) + C.attack_log += text("\[[time_stamp()]\] Has been handcuffed (attempt) by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Attempted to handcuff [C.name] ([C.ckey])") + if(!iscarbon(user)) + C.LAssailant = null + else + C.LAssailant = user + + log_attack("[user.name] ([user.ckey]) Attempted to handcuff [C.name] ([C.ckey])") + + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = user + O.target = C + O.item = user.get_active_hand() + O.s_loc = user.loc + O.t_loc = C.loc + O.place = "handcuff" + C.requests += O + spawn( 0 ) + if(istype(src, /obj/item/weapon/handcuffs/cable)) + feedback_add_details("handcuffs","C") + playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) + else + feedback_add_details("handcuffs","H") + playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + O.process() + return + else + if(!C.handcuffed) + var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) + O.source = user + O.target = C + O.item = user.get_active_hand() + O.s_loc = user.loc + O.t_loc = C.loc + O.place = "handcuff" + C.requests += O + spawn( 0 ) + if(istype(src, /obj/item/weapon/handcuffs/cable)) + playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) + else + playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + O.process() + return + return + +/obj/item/weapon/handcuffs/cable + name = "cable restraints" + desc = "Looks like some cables tied together. Could be used to tie something up." + icon_state = "cuff_red" + _color = "red" + breakouttime = 300 //Deciseconds = 30s + +/obj/item/weapon/handcuffs/cable/red + icon_state = "cuff_red" + +/obj/item/weapon/handcuffs/cable/yellow + icon_state = "cuff_yellow" + _color = "yellow" + +/obj/item/weapon/handcuffs/cable/blue + icon_state = "cuff_blue" + _color = "blue" + +/obj/item/weapon/handcuffs/cable/green + icon_state = "cuff_green" + _color = "green" + +/obj/item/weapon/handcuffs/cable/pink + icon_state = "cuff_pink" + _color = "pink" + +/obj/item/weapon/handcuffs/cable/orange + icon_state = "cuff_orange" + _color = "orange" + +/obj/item/weapon/handcuffs/cable/cyan + icon_state = "cuff_cyan" + _color = "cyan" + +/obj/item/weapon/handcuffs/cable/white + icon_state = "cuff_white" + _color = "white" + +/obj/item/weapon/handcuffs/cable/update_icon() + if(_color) + icon_state = "cuff_[_color]" + +/obj/item/weapon/handcuffs/cyborg + dispenser = 1 + +/obj/item/weapon/handcuffs/cable/attackby(var/obj/item/I, mob/user as mob) + ..() + if(istype(I, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = I + var/obj/item/weapon/wirerod/W = new /obj/item/weapon/wirerod + R.use(1) + + user.before_take_item(src) + + user.put_in_hands(W) to_chat(user, "You wrap the cable restraint around the top of the rod.") - - qdel(src) - -/* mite b cool - N3X -/obj/item/weapon/handcuffs/cyborg/attack(mob/living/carbon/C, mob/user) - if(isrobot(user)) - if(!C.handcuffed) - var/turf/user_loc = user.loc - var/turf/C_loc = C.loc - playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) - C.visible_message("[user] is trying to put handcuffs on [C]!", \ - "[user] is trying to put handcuffs on [C]!") - if(do_after(user, C, 30)) - if(!C || C.handcuffed) - return - if(user_loc == user.loc && C_loc == C.loc) - C.handcuffed = new /obj/item/weapon/handcuffs(C) - C.update_inv_handcuffed(0) -*/ + + qdel(src) + +/* mite b cool - N3X +/obj/item/weapon/handcuffs/cyborg/attack(mob/living/carbon/C, mob/user) + if(isrobot(user)) + if(!C.handcuffed) + var/turf/user_loc = user.loc + var/turf/C_loc = C.loc + playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) + C.visible_message("[user] is trying to put handcuffs on [C]!", \ + "[user] is trying to put handcuffs on [C]!") + if(do_after(user, C, 30)) + if(!C || C.handcuffed) + return + if(user_loc == user.loc && C_loc == C.loc) + C.handcuffed = new /obj/item/weapon/handcuffs(C) + C.update_inv_handcuffed(0) +*/ diff --git a/code/game/objects/items/weapons/hydroponics.dm b/code/game/objects/items/weapons/hydroponics.dm index 0eae9036421..91abaea728a 100644 --- a/code/game/objects/items/weapons/hydroponics.dm +++ b/code/game/objects/items/weapons/hydroponics.dm @@ -1,238 +1,238 @@ -/* Hydroponic stuff - * Contains: - * Sunflowers - * Nettle - * Deathnettle - * Corbcob - */ - - - -/* - * SeedBag - */ -//uncomment when this is updated to match storage update -/* -/obj/item/weapon/seedbag - icon = 'icons/obj/hydroponics.dmi' - icon_state = "seedbag" - name = "Seed Bag" - desc = "A small satchel made for organizing seeds." - var/mode = 1; //0 = pick one at a time, 1 = pick all on tile - var/capacity = 500; //the number of seeds it can carry. - flags = FPRINT - slot_flags = SLOT_BELT - w_class = 1 - var/list/item_quants = list() - -/obj/item/weapon/seedbag/attack_self(mob/user as mob) - user.machine = src - interact(user) - -/obj/item/weapon/seedbag/verb/toggle_mode() - set name = "Switch Bagging Method" - set category = "Object" - - mode = !mode - switch (mode) - if(1) +/* Hydroponic stuff + * Contains: + * Sunflowers + * Nettle + * Deathnettle + * Corbcob + */ + + + +/* + * SeedBag + */ +//uncomment when this is updated to match storage update +/* +/obj/item/weapon/seedbag + icon = 'icons/obj/hydroponics.dmi' + icon_state = "seedbag" + name = "Seed Bag" + desc = "A small satchel made for organizing seeds." + var/mode = 1; //0 = pick one at a time, 1 = pick all on tile + var/capacity = 500; //the number of seeds it can carry. + flags = FPRINT + slot_flags = SLOT_BELT + w_class = 1 + var/list/item_quants = list() + +/obj/item/weapon/seedbag/attack_self(mob/user as mob) + user.machine = src + interact(user) + +/obj/item/weapon/seedbag/verb/toggle_mode() + set name = "Switch Bagging Method" + set category = "Object" + + mode = !mode + switch (mode) + if(1) to_chat(usr, "The bag now picks up all seeds in a tile at once.") - if(0) + if(0) to_chat(usr, "The bag now picks up one seed pouch at a time.") - -/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob) - ..() - if (istype(O, /obj/item/weapon/seedbag)) - var/obj/item/weapon/seedbag/S = O - if (S.mode == 1) - for (var/obj/item/seeds/G in locate(src.x,src.y,src.z)) - if (S.contents.len < S.capacity) - S.contents += G; - if(S.item_quants[G.name]) - S.item_quants[G.name]++ - else - S.item_quants[G.name] = 1 - else + +/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob) + ..() + if (istype(O, /obj/item/weapon/seedbag)) + var/obj/item/weapon/seedbag/S = O + if (S.mode == 1) + for (var/obj/item/seeds/G in locate(src.x,src.y,src.z)) + if (S.contents.len < S.capacity) + S.contents += G; + if(S.item_quants[G.name]) + S.item_quants[G.name]++ + else + S.item_quants[G.name] = 1 + else to_chat(user, "The seed bag is full.") - S.updateUsrDialog() - return + S.updateUsrDialog() + return to_chat(user, "You pick up all the seeds.") - else - if (S.contents.len < S.capacity) - S.contents += src; - if(S.item_quants[name]) - S.item_quants[name]++ - else - S.item_quants[name] = 1 - else + else + if (S.contents.len < S.capacity) + S.contents += src; + if(S.item_quants[name]) + S.item_quants[name]++ + else + S.item_quants[name] = 1 + else to_chat(user, "The seed bag is full.") - S.updateUsrDialog() - return - -/obj/item/weapon/seedbag/interact(mob/user as mob) - - var/dat = "Select an item:
    " - - if (contents.len == 0) - dat += "No seeds loaded!" - else - for (var/O in item_quants) - if(item_quants[O] > 0) - var/N = item_quants[O] - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\weapons\hydroponics.dm:82: dat += "[capitalize(O)]:" - dat += {"[capitalize(O)]: - [N] - Vend -
    "} - // END AUTOFIX - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\weapons\hydroponics.dm:87: dat += "
    Unload All" - dat += {"
    Unload All -
    "} - // END AUTOFIX - user << browse("Seedbag Supplies[dat]", "window=seedbag") - onclose(user, "seedbag") - return - -/obj/item/weapon/seedbag/Topic(href, href_list) - if(..()) - return - - usr.machine = src - if ( href_list["vend"] ) - var/N = href_list["vend"] - - if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. - return - - item_quants[N] -= 1 - for(var/obj/O in contents) - if(O.name == N) - O.loc = get_turf(src) - usr.put_in_hands(O) - break - - else if ( href_list["unload"] ) - item_quants.len = 0 - for(var/obj/O in contents ) - O.loc = get_turf(src) - - src.updateUsrDialog() - return - -/obj/item/weapon/seedbag/updateUsrDialog() - var/list/nearby = range(1, src) - for(var/mob/M in nearby) - if ((M.client && M.machine == src)) - src.attack_self(M) -*/ -/* - * Sunflower & NovaFlower - */ - -/*/obj/item/weapon/grown/sunflower/attack(mob/M as mob, mob/user as mob) + S.updateUsrDialog() + return + +/obj/item/weapon/seedbag/interact(mob/user as mob) + + var/dat = "Select an item:
    " + + if (contents.len == 0) + dat += "No seeds loaded!" + else + for (var/O in item_quants) + if(item_quants[O] > 0) + var/N = item_quants[O] + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\weapons\hydroponics.dm:82: dat += "[capitalize(O)]:" + dat += {"[capitalize(O)]: + [N] + Vend +
    "} + // END AUTOFIX + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\weapons\hydroponics.dm:87: dat += "
    Unload All" + dat += {"
    Unload All +
    "} + // END AUTOFIX + user << browse("Seedbag Supplies[dat]", "window=seedbag") + onclose(user, "seedbag") + return + +/obj/item/weapon/seedbag/Topic(href, href_list) + if(..()) + return + + usr.machine = src + if ( href_list["vend"] ) + var/N = href_list["vend"] + + if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. + return + + item_quants[N] -= 1 + for(var/obj/O in contents) + if(O.name == N) + O.loc = get_turf(src) + usr.put_in_hands(O) + break + + else if ( href_list["unload"] ) + item_quants.len = 0 + for(var/obj/O in contents ) + O.loc = get_turf(src) + + src.updateUsrDialog() + return + +/obj/item/weapon/seedbag/updateUsrDialog() + var/list/nearby = range(1, src) + for(var/mob/M in nearby) + if ((M.client && M.machine == src)) + src.attack_self(M) +*/ +/* + * Sunflower & NovaFlower + */ + +/*/obj/item/weapon/grown/sunflower/attack(mob/M as mob, mob/user as mob) to_chat(M, " [user] smacks you with a sunflower!FLOWER POWER") to_chat(user, "Your sunflower's FLOWER POWER strikes [M]")*/ - -/*/obj/item/weapon/grown/novaflower - name = "novaflower" - desc = "These beautiful flowers have a crisp smokey scent, like a summer bonfire." - icon = 'icons/obj/harvest.dmi' - icon_state = "novaflower" - damtype = "fire" - force = 0 - flags = 0 - slot_flags = SLOT_HEAD - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - attack_verb = list("seared", "heated", "whacked", "steamed")*/ - -/*/obj/item/weapon/grown/novaflower/attack(mob/living/carbon/M as mob, mob/user as mob) - if(!..()) return - if(istype(M, /mob/living)) + +/*/obj/item/weapon/grown/novaflower + name = "novaflower" + desc = "These beautiful flowers have a crisp smokey scent, like a summer bonfire." + icon = 'icons/obj/harvest.dmi' + icon_state = "novaflower" + damtype = "fire" + force = 0 + flags = 0 + slot_flags = SLOT_HEAD + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + attack_verb = list("seared", "heated", "whacked", "steamed")*/ + +/*/obj/item/weapon/grown/novaflower/attack(mob/living/carbon/M as mob, mob/user as mob) + if(!..()) return + if(istype(M, /mob/living)) to_chat(M, "You are heated by the warmth of the of the [name]!") - M.bodytemperature += potency/2 * TEMPERATURE_DAMAGE_COEFFICIENT*/ - -/* -/obj/item/weapon/grown/novaflower/pickup(mob/living/carbon/human/user as mob) - if(!user.gloves) + M.bodytemperature += potency/2 * TEMPERATURE_DAMAGE_COEFFICIENT*/ + +/* +/obj/item/weapon/grown/novaflower/pickup(mob/living/carbon/human/user as mob) + if(!user.gloves) to_chat(user, "The [name] burns your bare hand!") - user.adjustFireLoss(rand(1,5))*/ - -/* - * Nettle - */ -/*/obj/item/weapon/grown/nettle/pickup(mob/living/carbon/human/user as mob) - if(!user.gloves) + user.adjustFireLoss(rand(1,5))*/ + +/* + * Nettle + */ +/*/obj/item/weapon/grown/nettle/pickup(mob/living/carbon/human/user as mob) + if(!user.gloves) to_chat(user, "The nettle burns your bare hand!") - if(istype(user, /mob/living/carbon/human)) - var/organ = ((user.hand ? "l_":"r_") + "arm") - var/datum/organ/external/affecting = user.get_organ(organ) - if(affecting.take_damage(0,force)) - user.UpdateDamageIcon() - else - user.take_organ_damage(0,force) - -/obj/item/weapon/grown/nettle/changePotency(newValue) //-QualityVan - potency = newValue - force = round((5+potency/5), 1)*/ - -/* - * Deathnettle - */ - -/*/obj/item/weapon/grown/deathnettle/pickup(mob/living/carbon/human/user as mob) //todo this - if(!user.gloves) - if(istype(user, /mob/living/carbon/human)) - var/organ = ((user.hand ? "l_":"r_") + "arm") - var/datum/organ/external/affecting = user.get_organ(organ) - if(affecting.take_damage(0,force)) - user.UpdateDamageIcon() - else - user.take_organ_damage(0,force) - if(prob(50)) - user.Paralyse(5) + if(istype(user, /mob/living/carbon/human)) + var/organ = ((user.hand ? "l_":"r_") + "arm") + var/datum/organ/external/affecting = user.get_organ(organ) + if(affecting.take_damage(0,force)) + user.UpdateDamageIcon() + else + user.take_organ_damage(0,force) + +/obj/item/weapon/grown/nettle/changePotency(newValue) //-QualityVan + potency = newValue + force = round((5+potency/5), 1)*/ + +/* + * Deathnettle + */ + +/*/obj/item/weapon/grown/deathnettle/pickup(mob/living/carbon/human/user as mob) //todo this + if(!user.gloves) + if(istype(user, /mob/living/carbon/human)) + var/organ = ((user.hand ? "l_":"r_") + "arm") + var/datum/organ/external/affecting = user.get_organ(organ) + if(affecting.take_damage(0,force)) + user.UpdateDamageIcon() + else + user.take_organ_damage(0,force) + if(prob(50)) + user.Paralyse(5) to_chat(user, "You are stunned by the Deathnettle when you try picking it up!") - -/obj/item/weapon/grown/deathnettle/attack(mob/living/carbon/M as mob, mob/user as mob) - if(!..()) return - if(istype(M, /mob/living)) + +/obj/item/weapon/grown/deathnettle/attack(mob/living/carbon/M as mob, mob/user as mob) + if(!..()) return + if(istype(M, /mob/living)) to_chat(M, "You are stunned by the powerful acid of the Deathnettle!") - M.attack_log += text("\[[time_stamp()]\] Had the [src.name] used on them by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] on [M.name] ([M.ckey])") - - log_attack(" [user.name] ([user.ckey]) used the [src.name] on [M.name] ([M.ckey])") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - - M.eye_blurry += force/7 - if(prob(20)) - M.Paralyse(force/6) - M.Weaken(force/15) - M.drop_item() - - -/obj/item/weapon/grown/deathnettle/changePotency(newValue) //-QualityVan - potency = newValue - force = round((5+potency/2.5), 1)*/ - - -/* - * Corncob - */ -/*/obj/item/weapon/corncob/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || istype(W, /obj/item/weapon/kitchen/utensil/knife) || istype(W, /obj/item/weapon/kitchen/utensil/knife/large) || istype(W, /obj/item/weapon/kitchen/utensil/knife/large/ritual)) + M.attack_log += text("\[[time_stamp()]\] Had the [src.name] used on them by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] on [M.name] ([M.ckey])") + + log_attack(" [user.name] ([user.ckey]) used the [src.name] on [M.name] ([M.ckey])") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + + M.eye_blurry += force/7 + if(prob(20)) + M.Paralyse(force/6) + M.Weaken(force/15) + M.drop_item() + + +/obj/item/weapon/grown/deathnettle/changePotency(newValue) //-QualityVan + potency = newValue + force = round((5+potency/2.5), 1)*/ + + +/* + * Corncob + */ +/*/obj/item/weapon/corncob/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || istype(W, /obj/item/weapon/kitchen/utensil/knife) || istype(W, /obj/item/weapon/kitchen/utensil/knife/large) || istype(W, /obj/item/weapon/kitchen/utensil/knife/large/ritual)) to_chat(user, "You use [W] to fashion a pipe out of the corn cob!") - new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc) - qdel(src) - return*/ + new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc) + qdel(src) + return*/ diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index c4df37f81f7..92e43300241 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -1,513 +1,513 @@ -#define MALFUNCTION_TEMPORARY 1 -#define MALFUNCTION_PERMANENT 2 -/obj/item/weapon/implant - name = "implant" - icon = 'icons/obj/device.dmi' - icon_state = "implant" - var/implanted = null - var/mob/imp_in = null - var/datum/organ/external/part = null - _color = "b" - var/allow_reagents = 0 - var/malfunction = 0 - -/obj/item/weapon/implant/proc/trigger(emote, source as mob) - return - -/obj/item/weapon/implant/proc/activate() - return - - -// What does the implant do upon injection? -// return 0 if the implant fails (ex. Revhead and loyalty implant.) -// return 1 if the implant succeeds (ex. Nonrevhead and loyalty implant.) -/obj/item/weapon/implant/proc/implanted(var/mob/source) - return 1 - -/obj/item/weapon/implant/proc/get_data() - return "No information available" - -/obj/item/weapon/implant/proc/hear(message, source as mob) - return - -/obj/item/weapon/implant/proc/islegal() - return 0 - -/obj/item/weapon/implant/proc/meltdown() //breaks it down, making implant unrecongizible - to_chat(imp_in, "You feel something melting inside [part ? "your [part.display_name]" : "you"]!") - if (part) - part.take_damage(burn = 15, used_weapon = "Electronics meltdown") - else - var/mob/living/M = imp_in - M.apply_damage(15,BURN) - name = "melted implant" - desc = "Charred circuit in melted plastic case. Wonder what that used to be..." - icon_state = "implant_melted" - malfunction = MALFUNCTION_PERMANENT - -/obj/item/weapon/implant/Destroy() - if(part) - part.implants.Remove(src) - imp_in = null - if(reagents) - qdel(reagents) - ..() - -var/global/tracking_implants = list() //fuck me - -/obj/item/weapon/implant/tracking - name = "tracking" - desc = "Track with this." - var/id = 1.0 - -/obj/item/weapon/implant/tracking/New() - ..() - tracking_implants += src - -/obj/item/weapon/implant/tracking/Destroy() - ..() - tracking_implants -= src - -/obj/item/weapon/implant/tracking/get_data() - var/dat = {"Implant Specifications:
    -Name: Tracking Beacon
    -Life: 10 minutes after death of host
    -Important Notes: None
    -
    -Implant Details:
    -Function: Continuously transmits low power signal. Useful for tracking.
    -Special Features:
    -Neuro-Safe- Specialized shell absorbs excess voltages self-destructing the chip if -a malfunction occurs thereby securing safety of subject. The implant will melt and -disintegrate into bio-safe elements.
    -Integrity: Gradient creates slight risk of being overcharged and frying the -circuitry. As a result neurotoxins can cause massive damage.
    -Implant Specifics:
    "} - return dat - -/obj/item/weapon/implant/tracking/emp_act(severity) - if (malfunction) //no, dawg, you can't malfunction while you are malfunctioning - return - malfunction = MALFUNCTION_TEMPORARY - - var/delay = 20 - switch(severity) - if(1) - if(prob(60)) - meltdown() - if(2) - delay = rand(5 MINUTES, 15 MINUTES) - - spawn(delay) - malfunction-- - -//BS12 Explosive -/obj/item/weapon/implant/explosive - name = "explosive implant" - desc = "A military grade micro bio-explosive. Highly dangerous." - var/phrase = "supercalifragilisticexpialidocious" - icon_state = "implant_evil" - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Robust Corp RX-78 Intimidation Class Implant
    -Life: Activates upon codephrase or detected death.
    -Important Notes: Explodes
    -
    -Implant Details:
    -Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
    -Special Features: Explodes
    -Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - return dat - -/obj/item/weapon/implant/explosive/Hear(var/datum/speech/speech, var/rendered_speech="") - hear(speech.message) - return - -/obj/item/weapon/implant/explosive/hear(var/msg) - var/list/replacechars = list("'" = "", "\"" = "", ">" = "", "<" = "", "(" = "", ")" = "") - msg = sanitize_simple(msg, replacechars) - if(findtext(msg, phrase)) - activate() - -/obj/item/weapon/implant/explosive/trigger(emote, source as mob) - if(emote == "deathgasp") - activate() - -/obj/item/weapon/implant/explosive/activate() - if(malfunction == MALFUNCTION_PERMANENT) - return - if(iscarbon(imp_in)) - var/mob/M = imp_in - - message_admins("Explosive implant triggered in [M] ([M.key]). (JMP) ") - log_game("Explosive implant triggered in [M] ([M.key]).") - - var/turf/T = get_turf(M) - - explosion(T, 1, 3, 4, 6) - T.hotspot_expose(3500, 125, surfaces = 1) - - qdel(src) - -/obj/item/weapon/implant/explosive/implanted(mob/source as mob) - phrase = input("Choose activation phrase:") as text - var/list/replacechars = list("'" = "", "\"" = "", ">" = "", "<" = "", "(" = "", ")" = "") - phrase = sanitize_simple(phrase, replacechars) - usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0) - to_chat(usr, "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.") - addHear() - return 1 - -/obj/item/weapon/implant/explosive/emp_act(severity) - if(malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - switch (severity) - if(2.0) //Weak EMP will make implant tear limbs off. - if(prob(50)) - small_boom() - if(1.0) //Strong EMP will melt implant either making it go off, or disarming it - if(prob(70)) - if(prob(50)) - small_boom() - else - if(prob(50)) - activate() //50% chance of bye bye - else - meltdown() //50% chance of implant disarming - spawn(20) - malfunction-- - -/obj/item/weapon/implant/explosive/islegal() - return 0 - -/obj/item/weapon/implant/explosive/proc/small_boom() - if(iscarbon(imp_in)) - imp_in.visible_message("Something beeps inside [imp_in][part ? "'s [part.display_name]" : ""]!") - playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3) - spawn(25) - if(ishuman(imp_in) && part) - //No tearing off these parts since it's pretty much killing - //and you can't replace groins - if(istype(part, /datum/organ/external/chest) || istype(part, /datum/organ/external/groin) || istype(part, /datum/organ/external/head)) - part.createwound(BRUISE, 60) //Mangle them instead - else - part.droplimb(1) - explosion(get_turf(imp_in), -1, -1, 2, 3, 3) - qdel(src) - -/obj/item/weapon/implant/chem - name = "chem" - desc = "Injects things." - allow_reagents = 1 - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Robust Corp MJ-420 Prisoner Management Implant
    -Life: Deactivates upon death but remains within the body.
    -Important Notes: Due to the system functioning off of nutrients in the implanted subject's body, the subject
    -will suffer from an increased appetite.

    -
    -Implant Details:
    -Function: Contains a small capsule that can contain various chemicals. Upon receiving a specially encoded signal
    -the implant releases the chemicals directly into the blood stream.
    -Special Features: -Micro-Capsule- Can be loaded with any sort of chemical agent via the common syringe and can hold 50 units.
    -Can only be loaded while still in its original case.
    -Integrity: Implant will last so long as the subject is alive. However, if the subject suffers from malnutrition,
    -the implant may become unstable and either pre-maturely inject the subject or simply break."} - return dat - -/obj/item/weapon/implant/chem/trigger(emote, source as mob) - if(emote == "deathgasp") - src.activate(src.reagents.total_volume) - return - - -/obj/item/weapon/implant/chem/activate(var/cause) - if((!cause) || (!src.imp_in)) return 0 - var/mob/living/carbon/R = src.imp_in - src.reagents.trans_to(R, cause) - to_chat(R, "You hear a faint *beep*.") - if(!src.reagents.total_volume) - to_chat(R, "You hear a faint click from your chest.") - spawn(0) - qdel(src) - return - -/obj/item/weapon/implant/chem/emp_act(severity) - if (malfunction) - return - malfunction = MALFUNCTION_TEMPORARY - - switch(severity) - if(1) - if(prob(60)) - activate(20) - if(2) - if(prob(30)) - activate(5) - - spawn(20) - malfunction-- - -/obj/item/weapon/implant/chem/New() - . = ..() - create_reagents(50) - -/obj/item/weapon/implant/loyalty - name = "loyalty" - desc = "Makes you loyal or such." - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Nanotrasen Employee Management Implant
    -Life: Ten years.
    -Important Notes: Personnel injected with this device tend to be much more loyal to the company.
    -
    -Implant Details:
    -Function: Contains a small pod of nanobots that manipulate the host's mental functions.
    -Special Features: Will prevent and cure most forms of brainwashing.
    -Integrity: Implant will last so long as the nanobots are inside the bloodstream."} - return dat - - -/obj/item/weapon/implant/loyalty/implanted(mob/M) - if(!iscarbon(M)) return 0 - var/mob/living/carbon/H = M - if(H.mind in ticker.mode.head_revolutionaries) - H.visible_message("[H] seems to resist the implant!", "You feel the corporate tendrils of Nanotrasen try to invade your mind!") - return 0 - else if(H.mind in ticker.mode:revolutionaries) - ticker.mode:remove_revolutionary(H.mind) - to_chat(H, "You feel a surge of loyalty towards Nanotrasen.") - return 1 - -/obj/item/weapon/implant/traitor - name = "Greytide Implant" - desc = "Greytide Station wide" - icon_state = "implant_evil" - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Greytide Mind-Slave Implant
    -Life: ???
    -Important Notes: Any humanoid injected with this implant will become loyal to the injector and the greytide, unless of course the host is already loyal to someone else.
    -
    -Implant Details:
    -Function: Contains a small pod of nanobots that manipulate the host's mental functions.
    -Special Features: Glory to the Greytide!
    -Integrity: Implant will last so long as the nanobots are inside the bloodstream."} - return dat - -/obj/item/weapon/implant/traitor/implanted(mob/M, mob/user) - var/list/implanters - var/ref = "\ref[user.mind]" - if(!iscarbon(M)) return 0 - if(!M.mind) return 0 - var/mob/living/carbon/H = M - if(M == user) - to_chat(user, "You feel quite stupid for doing that.") - if(isliving(user)) - user:brainloss += 10 - return - if(locate(/obj/item/weapon/implant/traitor) in H.contents || locate(/obj/item/weapon/implant/loyalty) in H.contents) - H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") - return 0 - else if(H.mind in ticker.mode.traitors) - H.visible_message("[H] seems to resist the implant!", "You feel a familiar sensation in your head that quickly dissipates.") - return 0 - H.implanting = 1 - to_chat(H, "You feel a surge of loyalty towards [user.name].") - if(!(user.mind in ticker.mode:implanter)) - ticker.mode:implanter[ref] = list() - implanters = ticker.mode:implanter[ref] - implanters.Add(H.mind) - ticker.mode.implanted.Add(H.mind) - ticker.mode.implanted[H.mind] = user.mind - //ticker.mode:implanter[user.mind] += H.mind - ticker.mode:implanter[ref] = implanters - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - to_chat(H, "You've been shown the Greytide by [user.name]! You now must lay down your life to protect them and assist in their goals at any cost.
    ") - var/datum/objective/protect/p = new - p.owner = H.mind - p.target = user:mind - p.explanation_text = "Protect [user:real_name], the [user:mind:assigned_role=="MODE" ? (user:mind:special_role) : (user:mind:assigned_role)]." - H.mind.objectives += p - for(var/datum/objective/objective in H.mind.objectives) - to_chat(H, "Objective #1: [objective.explanation_text]") - ticker.mode.update_traitor_icons_added(H.mind) - ticker.mode.update_traitor_icons_added(user.mind) - log_admin("[ckey(user.key)] has mind-slaved [ckey(H.key)].") - return 1 -/obj/item/weapon/implant/adrenalin - name = "adrenalin" - desc = "Removes all stuns and knockdowns." - var/uses - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Cybersun Industries Adrenalin Implant
    -Life: Five days.
    -Important Notes: Illegal
    -
    -Implant Details: Subjects injected with implant can activate a massive injection of adrenalin.
    -Function: Contains nanobots to stimulate body to mass-produce Adrenalin.
    -Special Features: Will prevent and cure most forms of brainwashing.
    -Integrity: Implant can only be used three times before the nanobots are depleted."} - return dat - - -/obj/item/weapon/implant/adrenalin/trigger(emote, mob/source as mob) - if (src.uses < 1) return 0 - if (emote == "pale") - src.uses-- - to_chat(source, "You feel a sudden surge of energy!") - source.SetStunned(0) - source.SetWeakened(0) - source.SetParalysis(0) - - return - - -/obj/item/weapon/implant/adrenalin/implanted(mob/source) - source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0) - to_chat(source, "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate.") - return 1 - - -/obj/item/weapon/implant/death_alarm - name = "death alarm implant" - desc = "An alarm which monitors host vital signs and transmits a radio message upon death." - var/mobname = "Will Robinson" - - get_data() - var/dat = {" -Implant Specifications:
    -Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
    -Life: Activates upon death.
    -Important Notes: Alerts crew to crewmember death.
    -
    -Implant Details:
    -Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
    -Special Features: Alerts crew to crewmember death.
    -Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - return dat - -/obj/item/weapon/implant/death_alarm/process() - if (!implanted || timestopped) return - var/mob/M = imp_in - - if(isnull(M)) // If the mob got gibbed - if(loc) - if(loc:timestopped) return - activate() - else if(M.stat == 2) - if(M.timestopped) return - activate("death") - -/obj/item/weapon/implant/death_alarm/activate(var/cause) - var/mob/M = imp_in - var/area/t = get_area(M) - src.name = "\improper [mobname]'s Death Alarm" - var/datum/speech/speech = create_speech("[mobname] has died in",1459,src) - speech.name="[mobname]'s Death Alarm" - speech.job="Death Alarm" - speech.set_language(LANGUAGE_SOL_COMMON) - switch (cause) - if("death") - if(!announcement_intercom || !istype(announcement_intercom)) - announcement_intercom = new(null) - - if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) ) - //give the syndies a bit of stealth - speech.message="[mobname] has died in Space!" - else - speech.message="[mobname] has died in [t.name]!" - processing_objects.Remove(src) - if ("emp") - var/name = prob(50) ? t.name : pick(teleportlocs) - speech.message="[mobname] has died in [name]!" - else - speech.message="[mobname] has died-zzzzt in-in-in..." - processing_objects.Remove(src) - Broadcast_Message(speech, vmask=0, data=0, compression=0, level=list(0,1)) - returnToPool(speech) - -/obj/item/weapon/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this - if (malfunction) //so I'm just going to add a meltdown chance here - return - malfunction = MALFUNCTION_TEMPORARY - - activate("emp") //let's shout that this dude is dead - if(severity == 1) - if(prob(40)) //small chance of obvious meltdown - meltdown() - else if (prob(60)) //but more likely it will just quietly die - malfunction = MALFUNCTION_PERMANENT - processing_objects.Remove(src) - - spawn(20) - malfunction-- - -/obj/item/weapon/implant/death_alarm/implanted(mob/source as mob) - mobname = source.real_name - processing_objects.Add(src) - return 1 - -/obj/item/weapon/implant/compressed - name = "compressed matter implant" - desc = "Based on compressed matter technology, can store a single item." - icon_state = "implant_evil" - var/activation_emote = "sigh" - var/obj/item/scanned = null - - get_data() - var/dat = {" -Implant Specifications:
    -Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
    -Life: Activates upon death.
    -Important Notes: Alerts crew to crewmember death.
    -
    -Implant Details:
    -Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
    -Special Features: Alerts crew to crewmember death.
    -Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} - return dat - -/obj/item/weapon/implant/compressed/trigger(emote, mob/source as mob) - if (src.scanned == null) - return 0 - - if (emote == src.activation_emote) - to_chat(source, "The air glows as \the [src.scanned.name] uncompresses.") - activate() - -/obj/item/weapon/implant/compressed/activate() - var/turf/t = get_turf(src) - if (imp_in) - imp_in.put_in_hands(scanned) - else - scanned.loc = t - qdel (src) - -/obj/item/weapon/implant/compressed/implanted(mob/source as mob) - src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - if (source.mind) - source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) - to_chat(source, "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.") - return 1 - -/obj/item/weapon/implant/compressed/islegal() - return 0 - -/obj/item/weapon/implant/cortical - name = "cortical stack" - desc = "A fist-sized mass of biocircuits and chips." +#define MALFUNCTION_TEMPORARY 1 +#define MALFUNCTION_PERMANENT 2 +/obj/item/weapon/implant + name = "implant" + icon = 'icons/obj/device.dmi' + icon_state = "implant" + var/implanted = null + var/mob/imp_in = null + var/datum/organ/external/part = null + _color = "b" + var/allow_reagents = 0 + var/malfunction = 0 + +/obj/item/weapon/implant/proc/trigger(emote, source as mob) + return + +/obj/item/weapon/implant/proc/activate() + return + + +// What does the implant do upon injection? +// return 0 if the implant fails (ex. Revhead and loyalty implant.) +// return 1 if the implant succeeds (ex. Nonrevhead and loyalty implant.) +/obj/item/weapon/implant/proc/implanted(var/mob/source) + return 1 + +/obj/item/weapon/implant/proc/get_data() + return "No information available" + +/obj/item/weapon/implant/proc/hear(message, source as mob) + return + +/obj/item/weapon/implant/proc/islegal() + return 0 + +/obj/item/weapon/implant/proc/meltdown() //breaks it down, making implant unrecongizible + to_chat(imp_in, "You feel something melting inside [part ? "your [part.display_name]" : "you"]!") + if (part) + part.take_damage(burn = 15, used_weapon = "Electronics meltdown") + else + var/mob/living/M = imp_in + M.apply_damage(15,BURN) + name = "melted implant" + desc = "Charred circuit in melted plastic case. Wonder what that used to be..." + icon_state = "implant_melted" + malfunction = MALFUNCTION_PERMANENT + +/obj/item/weapon/implant/Destroy() + if(part) + part.implants.Remove(src) + imp_in = null + if(reagents) + qdel(reagents) + ..() + +var/global/tracking_implants = list() //fuck me + +/obj/item/weapon/implant/tracking + name = "tracking" + desc = "Track with this." + var/id = 1.0 + +/obj/item/weapon/implant/tracking/New() + ..() + tracking_implants += src + +/obj/item/weapon/implant/tracking/Destroy() + ..() + tracking_implants -= src + +/obj/item/weapon/implant/tracking/get_data() + var/dat = {"Implant Specifications:
    +Name: Tracking Beacon
    +Life: 10 minutes after death of host
    +Important Notes: None
    +
    +Implant Details:
    +Function: Continuously transmits low power signal. Useful for tracking.
    +Special Features:
    +Neuro-Safe- Specialized shell absorbs excess voltages self-destructing the chip if +a malfunction occurs thereby securing safety of subject. The implant will melt and +disintegrate into bio-safe elements.
    +Integrity: Gradient creates slight risk of being overcharged and frying the +circuitry. As a result neurotoxins can cause massive damage.
    +Implant Specifics:
    "} + return dat + +/obj/item/weapon/implant/tracking/emp_act(severity) + if (malfunction) //no, dawg, you can't malfunction while you are malfunctioning + return + malfunction = MALFUNCTION_TEMPORARY + + var/delay = 20 + switch(severity) + if(1) + if(prob(60)) + meltdown() + if(2) + delay = rand(5 MINUTES, 15 MINUTES) + + spawn(delay) + malfunction-- + +//BS12 Explosive +/obj/item/weapon/implant/explosive + name = "explosive implant" + desc = "A military grade micro bio-explosive. Highly dangerous." + var/phrase = "supercalifragilisticexpialidocious" + icon_state = "implant_evil" + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Robust Corp RX-78 Intimidation Class Implant
    +Life: Activates upon codephrase or detected death.
    +Important Notes: Explodes
    +
    +Implant Details:
    +Function: Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death.
    +Special Features: Explodes
    +Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + return dat + +/obj/item/weapon/implant/explosive/Hear(var/datum/speech/speech, var/rendered_speech="") + hear(speech.message) + return + +/obj/item/weapon/implant/explosive/hear(var/msg) + var/list/replacechars = list("'" = "", "\"" = "", ">" = "", "<" = "", "(" = "", ")" = "") + msg = sanitize_simple(msg, replacechars) + if(findtext(msg, phrase)) + activate() + +/obj/item/weapon/implant/explosive/trigger(emote, source as mob) + if(emote == "deathgasp") + activate() + +/obj/item/weapon/implant/explosive/activate() + if(malfunction == MALFUNCTION_PERMANENT) + return + if(iscarbon(imp_in)) + var/mob/M = imp_in + + message_admins("Explosive implant triggered in [M] ([M.key]). (JMP) ") + log_game("Explosive implant triggered in [M] ([M.key]).") + + var/turf/T = get_turf(M) + + explosion(T, 1, 3, 4, 6) + T.hotspot_expose(3500, 125, surfaces = 1) + + qdel(src) + +/obj/item/weapon/implant/explosive/implanted(mob/source as mob) + phrase = input("Choose activation phrase:") as text + var/list/replacechars = list("'" = "", "\"" = "", ">" = "", "<" = "", "(" = "", ")" = "") + phrase = sanitize_simple(phrase, replacechars) + usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0) + to_chat(usr, "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.") + addHear() + return 1 + +/obj/item/weapon/implant/explosive/emp_act(severity) + if(malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + switch (severity) + if(2.0) //Weak EMP will make implant tear limbs off. + if(prob(50)) + small_boom() + if(1.0) //Strong EMP will melt implant either making it go off, or disarming it + if(prob(70)) + if(prob(50)) + small_boom() + else + if(prob(50)) + activate() //50% chance of bye bye + else + meltdown() //50% chance of implant disarming + spawn(20) + malfunction-- + +/obj/item/weapon/implant/explosive/islegal() + return 0 + +/obj/item/weapon/implant/explosive/proc/small_boom() + if(iscarbon(imp_in)) + imp_in.visible_message("Something beeps inside [imp_in][part ? "'s [part.display_name]" : ""]!") + playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3) + spawn(25) + if(ishuman(imp_in) && part) + //No tearing off these parts since it's pretty much killing + //and you can't replace groins + if(istype(part, /datum/organ/external/chest) || istype(part, /datum/organ/external/groin) || istype(part, /datum/organ/external/head)) + part.createwound(BRUISE, 60) //Mangle them instead + else + part.droplimb(1) + explosion(get_turf(imp_in), -1, -1, 2, 3, 3) + qdel(src) + +/obj/item/weapon/implant/chem + name = "chem" + desc = "Injects things." + allow_reagents = 1 + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Robust Corp MJ-420 Prisoner Management Implant
    +Life: Deactivates upon death but remains within the body.
    +Important Notes: Due to the system functioning off of nutrients in the implanted subject's body, the subject
    +will suffer from an increased appetite.

    +
    +Implant Details:
    +Function: Contains a small capsule that can contain various chemicals. Upon receiving a specially encoded signal
    +the implant releases the chemicals directly into the blood stream.
    +Special Features: +Micro-Capsule- Can be loaded with any sort of chemical agent via the common syringe and can hold 50 units.
    +Can only be loaded while still in its original case.
    +Integrity: Implant will last so long as the subject is alive. However, if the subject suffers from malnutrition,
    +the implant may become unstable and either pre-maturely inject the subject or simply break."} + return dat + +/obj/item/weapon/implant/chem/trigger(emote, source as mob) + if(emote == "deathgasp") + src.activate(src.reagents.total_volume) + return + + +/obj/item/weapon/implant/chem/activate(var/cause) + if((!cause) || (!src.imp_in)) return 0 + var/mob/living/carbon/R = src.imp_in + src.reagents.trans_to(R, cause) + to_chat(R, "You hear a faint *beep*.") + if(!src.reagents.total_volume) + to_chat(R, "You hear a faint click from your chest.") + spawn(0) + qdel(src) + return + +/obj/item/weapon/implant/chem/emp_act(severity) + if (malfunction) + return + malfunction = MALFUNCTION_TEMPORARY + + switch(severity) + if(1) + if(prob(60)) + activate(20) + if(2) + if(prob(30)) + activate(5) + + spawn(20) + malfunction-- + +/obj/item/weapon/implant/chem/New() + . = ..() + create_reagents(50) + +/obj/item/weapon/implant/loyalty + name = "loyalty" + desc = "Makes you loyal or such." + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Nanotrasen Employee Management Implant
    +Life: Ten years.
    +Important Notes: Personnel injected with this device tend to be much more loyal to the company.
    +
    +Implant Details:
    +Function: Contains a small pod of nanobots that manipulate the host's mental functions.
    +Special Features: Will prevent and cure most forms of brainwashing.
    +Integrity: Implant will last so long as the nanobots are inside the bloodstream."} + return dat + + +/obj/item/weapon/implant/loyalty/implanted(mob/M) + if(!iscarbon(M)) return 0 + var/mob/living/carbon/H = M + if(H.mind in ticker.mode.head_revolutionaries) + H.visible_message("[H] seems to resist the implant!", "You feel the corporate tendrils of Nanotrasen try to invade your mind!") + return 0 + else if(H.mind in ticker.mode:revolutionaries) + ticker.mode:remove_revolutionary(H.mind) + to_chat(H, "You feel a surge of loyalty towards Nanotrasen.") + return 1 + +/obj/item/weapon/implant/traitor + name = "Greytide Implant" + desc = "Greytide Station wide" + icon_state = "implant_evil" + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Greytide Mind-Slave Implant
    +Life: ???
    +Important Notes: Any humanoid injected with this implant will become loyal to the injector and the greytide, unless of course the host is already loyal to someone else.
    +
    +Implant Details:
    +Function: Contains a small pod of nanobots that manipulate the host's mental functions.
    +Special Features: Glory to the Greytide!
    +Integrity: Implant will last so long as the nanobots are inside the bloodstream."} + return dat + +/obj/item/weapon/implant/traitor/implanted(mob/M, mob/user) + var/list/implanters + var/ref = "\ref[user.mind]" + if(!iscarbon(M)) return 0 + if(!M.mind) return 0 + var/mob/living/carbon/H = M + if(M == user) + to_chat(user, "You feel quite stupid for doing that.") + if(isliving(user)) + user:brainloss += 10 + return + if(locate(/obj/item/weapon/implant/traitor) in H.contents || locate(/obj/item/weapon/implant/loyalty) in H.contents) + H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") + return 0 + else if(H.mind in ticker.mode.traitors) + H.visible_message("[H] seems to resist the implant!", "You feel a familiar sensation in your head that quickly dissipates.") + return 0 + H.implanting = 1 + to_chat(H, "You feel a surge of loyalty towards [user.name].") + if(!(user.mind in ticker.mode:implanter)) + ticker.mode:implanter[ref] = list() + implanters = ticker.mode:implanter[ref] + implanters.Add(H.mind) + ticker.mode.implanted.Add(H.mind) + ticker.mode.implanted[H.mind] = user.mind + //ticker.mode:implanter[user.mind] += H.mind + ticker.mode:implanter[ref] = implanters + ticker.mode.traitors += H.mind + H.mind.special_role = "traitor" + to_chat(H, "You've been shown the Greytide by [user.name]! You now must lay down your life to protect them and assist in their goals at any cost.
    ") + var/datum/objective/protect/p = new + p.owner = H.mind + p.target = user:mind + p.explanation_text = "Protect [user:real_name], the [user:mind:assigned_role=="MODE" ? (user:mind:special_role) : (user:mind:assigned_role)]." + H.mind.objectives += p + for(var/datum/objective/objective in H.mind.objectives) + to_chat(H, "Objective #1: [objective.explanation_text]") + ticker.mode.update_traitor_icons_added(H.mind) + ticker.mode.update_traitor_icons_added(user.mind) + log_admin("[ckey(user.key)] has mind-slaved [ckey(H.key)].") + return 1 +/obj/item/weapon/implant/adrenalin + name = "adrenalin" + desc = "Removes all stuns and knockdowns." + var/uses + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Cybersun Industries Adrenalin Implant
    +Life: Five days.
    +Important Notes: Illegal
    +
    +Implant Details: Subjects injected with implant can activate a massive injection of adrenalin.
    +Function: Contains nanobots to stimulate body to mass-produce Adrenalin.
    +Special Features: Will prevent and cure most forms of brainwashing.
    +Integrity: Implant can only be used three times before the nanobots are depleted."} + return dat + + +/obj/item/weapon/implant/adrenalin/trigger(emote, mob/source as mob) + if (src.uses < 1) return 0 + if (emote == "pale") + src.uses-- + to_chat(source, "You feel a sudden surge of energy!") + source.SetStunned(0) + source.SetWeakened(0) + source.SetParalysis(0) + + return + + +/obj/item/weapon/implant/adrenalin/implanted(mob/source) + source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0) + to_chat(source, "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate.") + return 1 + + +/obj/item/weapon/implant/death_alarm + name = "death alarm implant" + desc = "An alarm which monitors host vital signs and transmits a radio message upon death." + var/mobname = "Will Robinson" + + get_data() + var/dat = {" +Implant Specifications:
    +Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
    +Life: Activates upon death.
    +Important Notes: Alerts crew to crewmember death.
    +
    +Implant Details:
    +Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
    +Special Features: Alerts crew to crewmember death.
    +Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + return dat + +/obj/item/weapon/implant/death_alarm/process() + if (!implanted || timestopped) return + var/mob/M = imp_in + + if(isnull(M)) // If the mob got gibbed + if(loc) + if(loc:timestopped) return + activate() + else if(M.stat == 2) + if(M.timestopped) return + activate("death") + +/obj/item/weapon/implant/death_alarm/activate(var/cause) + var/mob/M = imp_in + var/area/t = get_area(M) + src.name = "\improper [mobname]'s Death Alarm" + var/datum/speech/speech = create_speech("[mobname] has died in",1459,src) + speech.name="[mobname]'s Death Alarm" + speech.job="Death Alarm" + speech.set_language(LANGUAGE_SOL_COMMON) + switch (cause) + if("death") + if(!announcement_intercom || !istype(announcement_intercom)) + announcement_intercom = new(null) + + if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) ) + //give the syndies a bit of stealth + speech.message="[mobname] has died in Space!" + else + speech.message="[mobname] has died in [t.name]!" + processing_objects.Remove(src) + if ("emp") + var/name = prob(50) ? t.name : pick(teleportlocs) + speech.message="[mobname] has died in [name]!" + else + speech.message="[mobname] has died-zzzzt in-in-in..." + processing_objects.Remove(src) + Broadcast_Message(speech, vmask=0, data=0, compression=0, level=list(0,1)) + returnToPool(speech) + +/obj/item/weapon/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this + if (malfunction) //so I'm just going to add a meltdown chance here + return + malfunction = MALFUNCTION_TEMPORARY + + activate("emp") //let's shout that this dude is dead + if(severity == 1) + if(prob(40)) //small chance of obvious meltdown + meltdown() + else if (prob(60)) //but more likely it will just quietly die + malfunction = MALFUNCTION_PERMANENT + processing_objects.Remove(src) + + spawn(20) + malfunction-- + +/obj/item/weapon/implant/death_alarm/implanted(mob/source as mob) + mobname = source.real_name + processing_objects.Add(src) + return 1 + +/obj/item/weapon/implant/compressed + name = "compressed matter implant" + desc = "Based on compressed matter technology, can store a single item." + icon_state = "implant_evil" + var/activation_emote = "sigh" + var/obj/item/scanned = null + + get_data() + var/dat = {" +Implant Specifications:
    +Name: NanoTrasen \"Profit Margin\" Class Employee Lifesign Sensor
    +Life: Activates upon death.
    +Important Notes: Alerts crew to crewmember death.
    +
    +Implant Details:
    +Function: Contains a compact radio signaler that triggers when the host's lifesigns cease.
    +Special Features: Alerts crew to crewmember death.
    +Integrity: Implant will occasionally be degraded by the body's immune system and thus will occasionally malfunction."} + return dat + +/obj/item/weapon/implant/compressed/trigger(emote, mob/source as mob) + if (src.scanned == null) + return 0 + + if (emote == src.activation_emote) + to_chat(source, "The air glows as \the [src.scanned.name] uncompresses.") + activate() + +/obj/item/weapon/implant/compressed/activate() + var/turf/t = get_turf(src) + if (imp_in) + imp_in.put_in_hands(scanned) + else + scanned.loc = t + qdel (src) + +/obj/item/weapon/implant/compressed/implanted(mob/source as mob) + src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") + if (source.mind) + source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) + to_chat(source, "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.") + return 1 + +/obj/item/weapon/implant/compressed/islegal() + return 0 + +/obj/item/weapon/implant/cortical + name = "cortical stack" + desc = "A fist-sized mass of biocircuits and chips." diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index d4ad1cdf84b..d127a7b13ea 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -1,130 +1,130 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/weapon/implantcase - name = "Glass Case" - desc = "A case containing an implant." - icon_state = "implantcase-0" - item_state = "implantcase" - throw_speed = 1 - throw_range = 5 - w_class = 1.0 - var/obj/item/weapon/implant/imp = null - proc - update() - - - update() - if (src.imp) - src.icon_state = text("implantcase-[]", src.imp._color) - else - src.icon_state = "implantcase-0" - return - - - attackby(obj/item/weapon/I as obj, mob/user as mob) - ..() - if (istype(I, /obj/item/weapon/pen)) - var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text - if (user.get_active_hand() != I) - return - if (!Adjacent(user) || user.stat) - return - t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - if(t) - src.name = text("Glass Case- '[]'", t) - else - src.name = "Glass Case" - else if(istype(I, /obj/item/weapon/reagent_containers/syringe)) - if(!src.imp) return - if(!src.imp.allow_reagents) return - if(src.imp.reagents.total_volume >= src.imp.reagents.maximum_volume) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/weapon/implantcase + name = "Glass Case" + desc = "A case containing an implant." + icon_state = "implantcase-0" + item_state = "implantcase" + throw_speed = 1 + throw_range = 5 + w_class = 1.0 + var/obj/item/weapon/implant/imp = null + proc + update() + + + update() + if (src.imp) + src.icon_state = text("implantcase-[]", src.imp._color) + else + src.icon_state = "implantcase-0" + return + + + attackby(obj/item/weapon/I as obj, mob/user as mob) + ..() + if (istype(I, /obj/item/weapon/pen)) + var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text + if (user.get_active_hand() != I) + return + if (!Adjacent(user) || user.stat) + return + t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + if(t) + src.name = text("Glass Case- '[]'", t) + else + src.name = "Glass Case" + else if(istype(I, /obj/item/weapon/reagent_containers/syringe)) + if(!src.imp) return + if(!src.imp.allow_reagents) return + if(src.imp.reagents.total_volume >= src.imp.reagents.maximum_volume) to_chat(user, "[src] is full.") - else - spawn(5) - I.reagents.trans_to(src.imp, 5) + else + spawn(5) + I.reagents.trans_to(src.imp, 5) to_chat(user, "You inject 5 units of the solution. The syringe now contains [I.reagents.total_volume] units.") - else if (istype(I, /obj/item/weapon/implanter)) - if (I:imp) - if ((src.imp || I:imp.implanted)) - return - I:imp.loc = src - src.imp = I:imp - I:imp = null - src.update() - I:update() - else - if (src.imp) - if (I:imp) - return - src.imp.loc = I - I:imp = src.imp - src.imp = null - update() - I:update() - return - - - -/obj/item/weapon/implantcase/tracking - name = "Glass Case- 'Tracking'" - desc = "A case containing a tracking implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-b" - - - New() - src.imp = new /obj/item/weapon/implant/tracking( src ) - ..() - return - - - -/obj/item/weapon/implantcase/explosive - name = "Glass Case- 'Explosive'" - desc = "A case containing an explosive implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-r" - - - New() - src.imp = new /obj/item/weapon/implant/explosive( src ) - ..() - return - - - -/obj/item/weapon/implantcase/chem - name = "Glass Case- 'Chem'" - desc = "A case containing a chemical implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-b" -/obj/item/weapon/implantcase/chem/New() - - src.imp = new /obj/item/weapon/implant/chem( src ) - ..() - return - - -/obj/item/weapon/implantcase/loyalty - name = "Glass Case- 'Loyalty'" - desc = "A case containing a loyalty implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-r" - - - New() - src.imp = new /obj/item/weapon/implant/loyalty( src ) - ..() - return - - -/obj/item/weapon/implantcase/death_alarm - name = "Glass Case- 'Death Alarm'" - desc = "A case containing a death alarm implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-b" - - New() - src.imp = new /obj/item/weapon/implant/death_alarm( src ) - ..() - return + else if (istype(I, /obj/item/weapon/implanter)) + if (I:imp) + if ((src.imp || I:imp.implanted)) + return + I:imp.loc = src + src.imp = I:imp + I:imp = null + src.update() + I:update() + else + if (src.imp) + if (I:imp) + return + src.imp.loc = I + I:imp = src.imp + src.imp = null + update() + I:update() + return + + + +/obj/item/weapon/implantcase/tracking + name = "Glass Case- 'Tracking'" + desc = "A case containing a tracking implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-b" + + + New() + src.imp = new /obj/item/weapon/implant/tracking( src ) + ..() + return + + + +/obj/item/weapon/implantcase/explosive + name = "Glass Case- 'Explosive'" + desc = "A case containing an explosive implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-r" + + + New() + src.imp = new /obj/item/weapon/implant/explosive( src ) + ..() + return + + + +/obj/item/weapon/implantcase/chem + name = "Glass Case- 'Chem'" + desc = "A case containing a chemical implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-b" +/obj/item/weapon/implantcase/chem/New() + + src.imp = new /obj/item/weapon/implant/chem( src ) + ..() + return + + +/obj/item/weapon/implantcase/loyalty + name = "Glass Case- 'Loyalty'" + desc = "A case containing a loyalty implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-r" + + + New() + src.imp = new /obj/item/weapon/implant/loyalty( src ) + ..() + return + + +/obj/item/weapon/implantcase/death_alarm + name = "Glass Case- 'Death Alarm'" + desc = "A case containing a death alarm implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-b" + + New() + src.imp = new /obj/item/weapon/implant/death_alarm( src ) + ..() + return diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index 28b6765ab41..1403b3b04da 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -1,175 +1,175 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/machinery/implantchair - name = "Loyalty Implanter" - desc = "Used to implant occupants with loyalty implants." - icon = 'icons/obj/machines/implantchair.dmi' - icon_state = "implantchair" - density = 1 - opacity = 0 - anchored = 1 - - var/ready = 1 - var/malfunction = 0 - var/list/obj/item/weapon/implant/loyalty/implant_list = list() - var/max_implants = 5 - var/injection_cooldown = 600 - var/replenish_cooldown = 6000 - var/replenishing = 0 - var/mob/living/carbon/occupant = null - var/injecting = 0 - - proc - go_out() - put_mob(mob/living/carbon/M as mob) - implant(var/mob/M) - add_implants() - - - New() - ..() - add_implants() - - - attack_hand(mob/user as mob) - user.set_machine(src) - var/health_text = "" - if(src.occupant) - if(src.occupant.health <= -100) - health_text = "Dead" - else if(src.occupant.health < 0) - health_text = "[round(src.occupant.health,0.1)]" - else - health_text = "[round(src.occupant.health,0.1)]" - - var/dat ="Implanter Status
    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\items\weapons\implants\implantchair.dm:47: dat +="Current occupant: [src.occupant ? "
    Name: [src.occupant]
    Health: [health_text]
    " : "None"]
    " - dat += {"Current occupant: [src.occupant ? "
    Name: [src.occupant]
    Health: [health_text]
    " : "None"]
    - Implants: [src.implant_list.len ? "[implant_list.len]" : "Replenish"]
    "} - // END AUTOFIX - if(src.occupant) - dat += "[src.ready ? "Implant" : "Recharging"]
    " - user.set_machine(src) - user << browse(dat, "window=implant") - onclose(user, "implant") - - - Topic(href, href_list) - if((get_dist(src, usr) <= 1) || istype(usr, /mob/living/silicon/ai)) - if(href_list["implant"]) - if(src.occupant) - injecting = 1 - go_out() - ready = 0 - spawn(injection_cooldown) - ready = 1 - - if(href_list["replenish"]) - ready = 0 - spawn(replenish_cooldown) - add_implants() - ready = 1 - - src.updateUsrDialog() - src.add_fingerprint(usr) - return - - - attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) - if(istype(G, /obj/item/weapon/grab)) - if(!ismob(G:affecting)) - return - for(var/mob/living/carbon/slime/M in range(1,G:affecting)) - if(M.Victim == G:affecting) - to_chat(usr, "[G:affecting:name] will not fit into the [src.name] because they have a slime latched onto their head.") - return - var/mob/M = G:affecting - if(put_mob(M)) - returnToPool(G) - src.updateUsrDialog() - return - - - go_out(var/mob/M) - if(!( src.occupant )) - return - if(M == occupant) // so that the guy inside can't eject himself -Agouri - return - if (src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE - src.occupant.loc = src.loc - if(injecting) - implant(src.occupant) - injecting = 0 - src.occupant = null - icon_state = "implantchair" - return - - - put_mob(mob/living/carbon/M as mob) - if(!iscarbon(M)) - to_chat(usr, "The [src.name] cannot hold this!") - return - if(src.occupant) - to_chat(usr, "The [src.name] is already occupied!") - return - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - M.stop_pulling() - M.loc = src - src.occupant = M - src.add_fingerprint(usr) - icon_state = "implantchair_on" - return 1 - - - implant(var/mob/M) - if (!istype(M, /mob/living/carbon)) - return - if(!implant_list.len) return - for(var/obj/item/weapon/implant/loyalty/imp in implant_list) - if(!imp) continue - if(istype(imp, /obj/item/weapon/implant/loyalty)) - for (var/mob/O in viewers(M, null)) - O.show_message("[M] has been implanted by the [src.name].", 1) - - if(imp.implanted(M)) - imp.loc = M - imp.imp_in = M - imp.implanted = 1 - implant_list -= imp - break - return - - - add_implants() - for(var/i=0, iName: [src.occupant]
    Health: [health_text]
    " : "None"]
    " + dat += {"Current occupant: [src.occupant ? "
    Name: [src.occupant]
    Health: [health_text]
    " : "None"]
    + Implants: [src.implant_list.len ? "[implant_list.len]" : "Replenish"]
    "} + // END AUTOFIX + if(src.occupant) + dat += "[src.ready ? "Implant" : "Recharging"]
    " + user.set_machine(src) + user << browse(dat, "window=implant") + onclose(user, "implant") + + + Topic(href, href_list) + if((get_dist(src, usr) <= 1) || istype(usr, /mob/living/silicon/ai)) + if(href_list["implant"]) + if(src.occupant) + injecting = 1 + go_out() + ready = 0 + spawn(injection_cooldown) + ready = 1 + + if(href_list["replenish"]) + ready = 0 + spawn(replenish_cooldown) + add_implants() + ready = 1 + + src.updateUsrDialog() + src.add_fingerprint(usr) + return + + + attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) + if(istype(G, /obj/item/weapon/grab)) + if(!ismob(G:affecting)) + return + for(var/mob/living/carbon/slime/M in range(1,G:affecting)) + if(M.Victim == G:affecting) + to_chat(usr, "[G:affecting:name] will not fit into the [src.name] because they have a slime latched onto their head.") + return + var/mob/M = G:affecting + if(put_mob(M)) + returnToPool(G) + src.updateUsrDialog() + return + + + go_out(var/mob/M) + if(!( src.occupant )) + return + if(M == occupant) // so that the guy inside can't eject himself -Agouri + return + if (src.occupant.client) + src.occupant.client.eye = src.occupant.client.mob + src.occupant.client.perspective = MOB_PERSPECTIVE + src.occupant.loc = src.loc + if(injecting) + implant(src.occupant) + injecting = 0 + src.occupant = null + icon_state = "implantchair" + return + + + put_mob(mob/living/carbon/M as mob) + if(!iscarbon(M)) + to_chat(usr, "The [src.name] cannot hold this!") + return + if(src.occupant) + to_chat(usr, "The [src.name] is already occupied!") + return + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.stop_pulling() + M.loc = src + src.occupant = M + src.add_fingerprint(usr) + icon_state = "implantchair_on" + return 1 + + + implant(var/mob/M) + if (!istype(M, /mob/living/carbon)) + return + if(!implant_list.len) return + for(var/obj/item/weapon/implant/loyalty/imp in implant_list) + if(!imp) continue + if(istype(imp, /obj/item/weapon/implant/loyalty)) + for (var/mob/O in viewers(M, null)) + O.show_message("[M] has been implanted by the [src.name].", 1) + + if(imp.implanted(M)) + imp.loc = M + imp.imp_in = M + imp.implanted = 1 + implant_list -= imp + break + return + + + add_implants() + for(var/i=0, i[user] is attempting to implant [M].", 1) - - var/turf/T1 = get_turf(M) - if (T1 && ((M == user) || do_after(user,M, 50))) - if(user && M && (get_turf(M) == T1) && src && src.imp) - for (var/mob/O in viewers(M, null)) - O.show_message("[M] has been implanted by [user].", 1) - - M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.imp.name]) by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.imp.name]) to implant [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") - - user.show_message("You implanted the implant into [M].") - if(src.imp.implanted(M, user)) - src.imp.loc = M - src.imp.imp_in = M - src.imp.implanted = 1 - if (ishuman(M)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/affected = H.get_organ(user.zone_sel.selecting) - affected.implants += src.imp - imp.part = affected - M:implanting = 0 - src.imp = null - update() - return - - -/obj/item/weapon/implanter/traitor - name = "implanter-greytide" - desc = "Greytide Stationwide." - -/obj/item/weapon/implanter/traitor/New() - src.imp = new /obj/item/weapon/implant/traitor(src) - ..() - update() - return - -/obj/item/weapon/implanter/loyalty - name = "implanter-loyalty" - -/obj/item/weapon/implanter/loyalty/New() - src.imp = new /obj/item/weapon/implant/loyalty( src ) - ..() - update() - return - - - -/obj/item/weapon/implanter/explosive - name = "implanter (E)" - -/obj/item/weapon/implanter/explosive/New() - src.imp = new /obj/item/weapon/implant/explosive( src ) - ..() - update() - return - -/obj/item/weapon/implanter/adrenalin - name = "implanter-adrenalin" - -/obj/item/weapon/implanter/adrenalin/New() - src.imp = new /obj/item/weapon/implant/adrenalin(src) - ..() - update() - return - -/obj/item/weapon/implanter/compressed - name = "implanter (C)" - icon_state = "cimplanter1" - - var/list/forbidden_types=list( - // /obj/item/weapon/storage/bible // VG #11 - Recursion. - ) - -/obj/item/weapon/implanter/compressed/New() - imp = new /obj/item/weapon/implant/compressed( src ) - ..() - update() - return - -/obj/item/weapon/implanter/compressed/update() - if (imp) - var/obj/item/weapon/implant/compressed/c = imp - if(!c.scanned) - icon_state = "cimplanter1" - else - icon_state = "cimplanter2" - else - icon_state = "cimplanter0" - return - -/obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob) - // Attacking things in your hands tends to make this fuck up. - if(!istype(M)) - return - var/obj/item/weapon/implant/compressed/c = imp - if (!c) return - if (c.scanned == null) +/obj/item/weapon/implanter + name = "implanter" + icon = 'icons/obj/items.dmi' + icon_state = "implanter0" + item_state = "syringe_0" + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + var/obj/item/weapon/implant/imp = null + +/obj/item/weapon/implanter/proc/update() + + + +/obj/item/weapon/implanter/update() + if (src.imp) + src.icon_state = "implanter1" + else + src.icon_state = "implanter0" + return + + +/obj/item/weapon/implanter/attack(mob/M as mob, mob/user as mob) + if (!istype(M, /mob/living/carbon)) + return + if (user && src.imp) + for (var/mob/O in viewers(M, null)) + O.show_message("[user] is attempting to implant [M].", 1) + + var/turf/T1 = get_turf(M) + if (T1 && ((M == user) || do_after(user,M, 50))) + if(user && M && (get_turf(M) == T1) && src && src.imp) + for (var/mob/O in viewers(M, null)) + O.show_message("[M] has been implanted by [user].", 1) + + M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.imp.name]) by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.imp.name]) to implant [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") + + user.show_message("You implanted the implant into [M].") + if(src.imp.implanted(M, user)) + src.imp.loc = M + src.imp.imp_in = M + src.imp.implanted = 1 + if (ishuman(M)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affected = H.get_organ(user.zone_sel.selecting) + affected.implants += src.imp + imp.part = affected + M:implanting = 0 + src.imp = null + update() + return + + +/obj/item/weapon/implanter/traitor + name = "implanter-greytide" + desc = "Greytide Stationwide." + +/obj/item/weapon/implanter/traitor/New() + src.imp = new /obj/item/weapon/implant/traitor(src) + ..() + update() + return + +/obj/item/weapon/implanter/loyalty + name = "implanter-loyalty" + +/obj/item/weapon/implanter/loyalty/New() + src.imp = new /obj/item/weapon/implant/loyalty( src ) + ..() + update() + return + + + +/obj/item/weapon/implanter/explosive + name = "implanter (E)" + +/obj/item/weapon/implanter/explosive/New() + src.imp = new /obj/item/weapon/implant/explosive( src ) + ..() + update() + return + +/obj/item/weapon/implanter/adrenalin + name = "implanter-adrenalin" + +/obj/item/weapon/implanter/adrenalin/New() + src.imp = new /obj/item/weapon/implant/adrenalin(src) + ..() + update() + return + +/obj/item/weapon/implanter/compressed + name = "implanter (C)" + icon_state = "cimplanter1" + + var/list/forbidden_types=list( + // /obj/item/weapon/storage/bible // VG #11 - Recursion. + ) + +/obj/item/weapon/implanter/compressed/New() + imp = new /obj/item/weapon/implant/compressed( src ) + ..() + update() + return + +/obj/item/weapon/implanter/compressed/update() + if (imp) + var/obj/item/weapon/implant/compressed/c = imp + if(!c.scanned) + icon_state = "cimplanter1" + else + icon_state = "cimplanter2" + else + icon_state = "cimplanter0" + return + +/obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob) + // Attacking things in your hands tends to make this fuck up. + if(!istype(M)) + return + var/obj/item/weapon/implant/compressed/c = imp + if (!c) return + if (c.scanned == null) to_chat(user, "Please scan an object with the implanter first.") - return - ..() - -/obj/item/weapon/implanter/compressed/afterattack(var/obj/item/I, mob/user as mob) - if(is_type_in_list(I,forbidden_types)) + return + ..() + +/obj/item/weapon/implanter/compressed/afterattack(var/obj/item/I, mob/user as mob) + if(is_type_in_list(I,forbidden_types)) to_chat(user, "A red light flickers on the implanter.") - return - if(istype(I) && imp) - var/obj/item/weapon/implant/compressed/c = imp - if (c.scanned) - if(istype(I,/obj/item/weapon/storage)) - ..() - return + return + if(istype(I) && imp) + var/obj/item/weapon/implant/compressed/c = imp + if (c.scanned) + if(istype(I,/obj/item/weapon/storage)) + ..() + return to_chat(user, "Something is already scanned inside the implant!") - return - if(user) - user.u_equip(I,0) - user.update_icons() //update our overlays - c.scanned = I - c.scanned.loc = c - update() + return + if(user) + user.u_equip(I,0) + user.update_icons() //update our overlays + c.scanned = I + c.scanned.loc = c + update() diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm index 387d166386b..2670d856022 100644 --- a/code/game/objects/items/weapons/implants/implantfreedom.dm +++ b/code/game/objects/items/weapons/implants/implantfreedom.dm @@ -1,71 +1,71 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/weapon/implant/freedom - name = "freedom" - desc = "Use this to escape from those evil Red Shirts." - _color = "r" - var/activation_emote = "chuckle" - var/uses = 1.0 - - - New() - src.activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - src.uses = rand(1, 5) - ..() - return - - - trigger(emote, mob/living/carbon/source as mob) - if (src.uses < 1) return 0 - if (emote == src.activation_emote) - src.uses-- +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/weapon/implant/freedom + name = "freedom" + desc = "Use this to escape from those evil Red Shirts." + _color = "r" + var/activation_emote = "chuckle" + var/uses = 1.0 + + + New() + src.activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") + src.uses = rand(1, 5) + ..() + return + + + trigger(emote, mob/living/carbon/source as mob) + if (src.uses < 1) return 0 + if (emote == src.activation_emote) + src.uses-- to_chat(source, "You feel a faint click.") - if (source.handcuffed) - var/obj/item/weapon/W = source.handcuffed - source.handcuffed = null - source.update_inv_handcuffed() - if (source.client) - source.client.screen -= W - if (W) - W.loc = source.loc - dropped(source) - if (W) - W.layer = initial(W.layer) - if (source.legcuffed) - var/obj/item/weapon/W = source.legcuffed - source.legcuffed = null - source.update_inv_legcuffed() - if (source.client) - source.client.screen -= W - if (W) - W.loc = source.loc - dropped(source) - if (W) - W.layer = initial(W.layer) - return - - - implanted(mob/living/carbon/source) - source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) + if (source.handcuffed) + var/obj/item/weapon/W = source.handcuffed + source.handcuffed = null + source.update_inv_handcuffed() + if (source.client) + source.client.screen -= W + if (W) + W.loc = source.loc + dropped(source) + if (W) + W.layer = initial(W.layer) + if (source.legcuffed) + var/obj/item/weapon/W = source.legcuffed + source.legcuffed = null + source.update_inv_legcuffed() + if (source.client) + source.client.screen -= W + if (W) + W.loc = source.loc + dropped(source) + if (W) + W.layer = initial(W.layer) + return + + + implanted(mob/living/carbon/source) + source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) to_chat(source, "The implanted freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.") - return 1 - - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Freedom Beacon
    -Life: optimum 5 uses
    -Important Notes: Illegal
    -
    -Implant Details:
    -Function: Transmits a specialized cluster of signals to override handcuff locking -mechanisms
    -Special Features:
    -Neuro-Scan- Analyzes certain shadow signals in the nervous system
    -Integrity: The battery is extremely weak and commonly after injection its -life can drive down to only 1 use.
    -No Implant Specifics"} - return dat - - + return 1 + + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Freedom Beacon
    +Life: optimum 5 uses
    +Important Notes: Illegal
    +
    +Implant Details:
    +Function: Transmits a specialized cluster of signals to override handcuff locking +mechanisms
    +Special Features:
    +Neuro-Scan- Analyzes certain shadow signals in the nervous system
    +Integrity: The battery is extremely weak and commonly after injection its +life can drive down to only 1 use.
    +No Implant Specifics"} + return dat + + diff --git a/code/game/objects/items/weapons/implants/implantpad.dm b/code/game/objects/items/weapons/implants/implantpad.dm index eda5b4cee04..ca5bdb4ab38 100644 --- a/code/game/objects/items/weapons/implants/implantpad.dm +++ b/code/game/objects/items/weapons/implants/implantpad.dm @@ -1,97 +1,97 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/weapon/implantpad - name = "implantpad" - desc = "Used to modify implants." - icon = 'icons/obj/items.dmi' - icon_state = "implantpad-0" - item_state = "electronic" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - var/obj/item/weapon/implantcase/case = null - var/broadcasting = null - var/listening = 1.0 - proc - update() - - - update() - if (src.case) - src.icon_state = "implantpad-1" - else - src.icon_state = "implantpad-0" - return - - - attack_hand(mob/user as mob) - if ((src.case && (user.l_hand == src || user.r_hand == src))) - user.put_in_active_hand(case) - - src.case.add_fingerprint(user) - src.case = null - - src.add_fingerprint(user) - update() - else - return ..() - return - - - attackby(obj/item/weapon/implantcase/C as obj, mob/user as mob) - ..() - if(istype(C, /obj/item/weapon/implantcase)) - if(!( src.case )) - if(user.drop_item(C, src)) - src.case = C - else - return - src.update() - return - - - attack_self(mob/user as mob) - user.set_machine(src) - var/dat = "Implant Mini-Computer:
    " - if (src.case) - if(src.case.imp) - if(istype(src.case.imp, /obj/item/weapon/implant)) - dat += src.case.imp.get_data() - if(istype(src.case.imp, /obj/item/weapon/implant/tracking)) - dat += {"ID (1-100): - - - - [case.imp:id] - + - +
    "} - else - dat += "The implant casing is empty." - else - dat += "Please insert an implant casing!" - user << browse(dat, "window=implantpad") - onclose(user, "implantpad") - return - - - Topic(href, href_list) - ..() - if (usr.stat) - return - if ((usr.contents.Find(src)) || ((in_range(src, usr) && istype(src.loc, /turf)))) - usr.set_machine(src) - if (href_list["tracking_id"]) - var/obj/item/weapon/implant/tracking/T = src.case.imp - T.id += text2num(href_list["tracking_id"]) - T.id = min(100, T.id) - T.id = max(1, T.id) - - if (istype(src.loc, /mob)) - attack_self(src.loc) - else - for(var/mob/M in viewers(1, src)) - if (M.client) - src.attack_self(M) - src.add_fingerprint(usr) - else - usr << browse(null, "window=implantpad") - return - return +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/weapon/implantpad + name = "implantpad" + desc = "Used to modify implants." + icon = 'icons/obj/items.dmi' + icon_state = "implantpad-0" + item_state = "electronic" + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + var/obj/item/weapon/implantcase/case = null + var/broadcasting = null + var/listening = 1.0 + proc + update() + + + update() + if (src.case) + src.icon_state = "implantpad-1" + else + src.icon_state = "implantpad-0" + return + + + attack_hand(mob/user as mob) + if ((src.case && (user.l_hand == src || user.r_hand == src))) + user.put_in_active_hand(case) + + src.case.add_fingerprint(user) + src.case = null + + src.add_fingerprint(user) + update() + else + return ..() + return + + + attackby(obj/item/weapon/implantcase/C as obj, mob/user as mob) + ..() + if(istype(C, /obj/item/weapon/implantcase)) + if(!( src.case )) + if(user.drop_item(C, src)) + src.case = C + else + return + src.update() + return + + + attack_self(mob/user as mob) + user.set_machine(src) + var/dat = "Implant Mini-Computer:
    " + if (src.case) + if(src.case.imp) + if(istype(src.case.imp, /obj/item/weapon/implant)) + dat += src.case.imp.get_data() + if(istype(src.case.imp, /obj/item/weapon/implant/tracking)) + dat += {"ID (1-100): + - + - [case.imp:id] + + + +
    "} + else + dat += "The implant casing is empty." + else + dat += "Please insert an implant casing!" + user << browse(dat, "window=implantpad") + onclose(user, "implantpad") + return + + + Topic(href, href_list) + ..() + if (usr.stat) + return + if ((usr.contents.Find(src)) || ((in_range(src, usr) && istype(src.loc, /turf)))) + usr.set_machine(src) + if (href_list["tracking_id"]) + var/obj/item/weapon/implant/tracking/T = src.case.imp + T.id += text2num(href_list["tracking_id"]) + T.id = min(100, T.id) + T.id = max(1, T.id) + + if (istype(src.loc, /mob)) + attack_self(src.loc) + else + for(var/mob/M in viewers(1, src)) + if (M.client) + src.attack_self(M) + src.add_fingerprint(usr) + else + usr << browse(null, "window=implantpad") + return + return diff --git a/code/game/objects/items/weapons/implants/implantuplink.dm b/code/game/objects/items/weapons/implants/implantuplink.dm index fd80eb0618f..69d4a58adf2 100644 --- a/code/game/objects/items/weapons/implants/implantuplink.dm +++ b/code/game/objects/items/weapons/implants/implantuplink.dm @@ -1,23 +1,23 @@ -/obj/item/weapon/implant/uplink - name = "uplink" - desc = "Summon things." - var/activation_emote = "chuckle" - -/obj/item/weapon/implant/uplink/New() - activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - hidden_uplink = new(src) - hidden_uplink.uses = 5 - ..() - return - -/obj/item/weapon/implant/uplink/implanted(mob/source) - activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) +/obj/item/weapon/implant/uplink + name = "uplink" + desc = "Summon things." + var/activation_emote = "chuckle" + +/obj/item/weapon/implant/uplink/New() + activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") + hidden_uplink = new(src) + hidden_uplink.uses = 5 + ..() + return + +/obj/item/weapon/implant/uplink/implanted(mob/source) + activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") + source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) to_chat(source, "The implanted uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.") - return 1 - - -/obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob) - if(hidden_uplink && usr == source) // Let's not have another people activate our uplink - hidden_uplink.check_trigger(source, emote, activation_emote) + return 1 + + +/obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob) + if(hidden_uplink && usr == source) // Let's not have another people activate our uplink + hidden_uplink.check_trigger(source, emote, activation_emote) return \ No newline at end of file diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index e2b05094379..b9e61565bed 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -1,563 +1,563 @@ -/* Kitchen tools - * Contains: - * Utensils - * Spoons - * Forks - * Knives - * Kitchen knives - * Butcher's cleaver - * Rolling Pins - * Trays - */ - -/obj/item/weapon/kitchen - icon = 'icons/obj/kitchen.dmi' - -/* - * Utensils - */ -/obj/item/weapon/kitchen/utensil - force = 5.0 - w_class = 1.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - flags = FPRINT - siemens_coefficient = 1 - origin_tech = "materials=1" - attack_verb = list("attacked", "stabbed", "poked") - -/obj/item/weapon/kitchen/utensil/New() - . = ..() - - if (prob(60)) - src.pixel_y = rand(0, 4) - -/* - * Spoons - */ -/obj/item/weapon/kitchen/utensil/spoon - name = "spoon" - desc = "SPOON!" - icon_state = "spoon" - attack_verb = list("attacked", "poked") - melt_temperature = MELTPOINT_STEEL - -/obj/item/weapon/kitchen/utensil/spoon/plastic - name = "plastic spoon" - desc = "Super dull action!" - icon_state = "pspoon" - melt_temperature = MELTPOINT_PLASTIC - -/* - * Forks - */ -/obj/item/weapon/kitchen/utensil/fork - name = "fork" - desc = "Pointy." - icon_state = "fork" - sharpness = 0.6 - var/loaded_food_name - var/image/loaded_food - melt_temperature = MELTPOINT_STEEL - -/obj/item/weapon/kitchen/utensil/fork/New() - ..() - reagents = new(10) - reagents.my_atom = src - -/obj/item/weapon/kitchen/utensil/fork/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M) || !istype(user)) - return ..() - - if(user.zone_sel.selecting != "eyes" && user.zone_sel.selecting != "head" && M != user && !loaded_food) - return ..() - - if (src.loaded_food) - reagents.update_total() - if(M == user) - user.visible_message("[user] eats a delicious forkful of [loaded_food_name]!") - else - user.visible_message("[user] feeds [M] a delicious forkful of [loaded_food_name]!") - reagents.reaction(M, INGEST) - reagents.trans_to(M.reagents, reagents.total_volume) - overlays -= loaded_food - del(loaded_food) - loaded_food_name = null - return - else - if((M_CLUMSY in user.mutations) && prob(50)) - return eyestab(user,user) - else - return eyestab(M, user) - -/obj/item/weapon/kitchen/utensil/fork/examine(mob/user) - ..() - if(loaded_food) - user.show_message("It has a forkful of [loaded_food_name] on it.") - -/obj/item/weapon/kitchen/utensil/fork/proc/load_food(obj/item/weapon/reagent_containers/food/snacks/snack, mob/user) - if(!snack || !user || !istype(snack) || !istype(user)) - return - - if(loaded_food) +/* Kitchen tools + * Contains: + * Utensils + * Spoons + * Forks + * Knives + * Kitchen knives + * Butcher's cleaver + * Rolling Pins + * Trays + */ + +/obj/item/weapon/kitchen + icon = 'icons/obj/kitchen.dmi' + +/* + * Utensils + */ +/obj/item/weapon/kitchen/utensil + force = 5.0 + w_class = 1.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + flags = FPRINT + siemens_coefficient = 1 + origin_tech = "materials=1" + attack_verb = list("attacked", "stabbed", "poked") + +/obj/item/weapon/kitchen/utensil/New() + . = ..() + + if (prob(60)) + src.pixel_y = rand(0, 4) + +/* + * Spoons + */ +/obj/item/weapon/kitchen/utensil/spoon + name = "spoon" + desc = "SPOON!" + icon_state = "spoon" + attack_verb = list("attacked", "poked") + melt_temperature = MELTPOINT_STEEL + +/obj/item/weapon/kitchen/utensil/spoon/plastic + name = "plastic spoon" + desc = "Super dull action!" + icon_state = "pspoon" + melt_temperature = MELTPOINT_PLASTIC + +/* + * Forks + */ +/obj/item/weapon/kitchen/utensil/fork + name = "fork" + desc = "Pointy." + icon_state = "fork" + sharpness = 0.6 + var/loaded_food_name + var/image/loaded_food + melt_temperature = MELTPOINT_STEEL + +/obj/item/weapon/kitchen/utensil/fork/New() + ..() + reagents = new(10) + reagents.my_atom = src + +/obj/item/weapon/kitchen/utensil/fork/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M) || !istype(user)) + return ..() + + if(user.zone_sel.selecting != "eyes" && user.zone_sel.selecting != "head" && M != user && !loaded_food) + return ..() + + if (src.loaded_food) + reagents.update_total() + if(M == user) + user.visible_message("[user] eats a delicious forkful of [loaded_food_name]!") + else + user.visible_message("[user] feeds [M] a delicious forkful of [loaded_food_name]!") + reagents.reaction(M, INGEST) + reagents.trans_to(M.reagents, reagents.total_volume) + overlays -= loaded_food + del(loaded_food) + loaded_food_name = null + return + else + if((M_CLUMSY in user.mutations) && prob(50)) + return eyestab(user,user) + else + return eyestab(M, user) + +/obj/item/weapon/kitchen/utensil/fork/examine(mob/user) + ..() + if(loaded_food) + user.show_message("It has a forkful of [loaded_food_name] on it.") + +/obj/item/weapon/kitchen/utensil/fork/proc/load_food(obj/item/weapon/reagent_containers/food/snacks/snack, mob/user) + if(!snack || !user || !istype(snack) || !istype(user)) + return + + if(loaded_food) to_chat(user, "You already have food on \the [src].") - return - - if(snack.wrapped) + return + + if(snack.wrapped) to_chat(user, "You can't eat packaging!") - return - - if(snack.reagents.total_volume) - loaded_food_name = snack.name - var/icon/food_to_load = getFlatIcon(snack) - food_to_load.Scale(16,16) - loaded_food = image(food_to_load) - loaded_food.pixel_x = 8 + src.pixel_x - loaded_food.pixel_y = 15 + src.pixel_y - src.overlays += loaded_food - if(snack.reagents.total_volume > snack.bitesize) - snack.reagents.trans_to(src, snack.bitesize) - else - snack.reagents.trans_to(src, snack.reagents.total_volume) - snack.bitecount++ - snack.On_Consume(user) - return 1 - -/obj/item/weapon/kitchen/utensil/fork/plastic - name = "plastic fork" - desc = "Yay, no washing up to do." - icon_state = "pfork" - melt_temperature = MELTPOINT_PLASTIC - -/* - * Knives - */ -/obj/item/weapon/kitchen/utensil/knife - name = "knife" - desc = "Can cut through any food." - icon_state = "knife" - force = 10.0 - throwforce = 10.0 - sharpness = 1.2 - melt_temperature = MELTPOINT_STEEL - -/obj/item/weapon/kitchen/utensil/knife/suicide_act(mob/user) + return + + if(snack.reagents.total_volume) + loaded_food_name = snack.name + var/icon/food_to_load = getFlatIcon(snack) + food_to_load.Scale(16,16) + loaded_food = image(food_to_load) + loaded_food.pixel_x = 8 + src.pixel_x + loaded_food.pixel_y = 15 + src.pixel_y + src.overlays += loaded_food + if(snack.reagents.total_volume > snack.bitesize) + snack.reagents.trans_to(src, snack.bitesize) + else + snack.reagents.trans_to(src, snack.reagents.total_volume) + snack.bitecount++ + snack.On_Consume(user) + return 1 + +/obj/item/weapon/kitchen/utensil/fork/plastic + name = "plastic fork" + desc = "Yay, no washing up to do." + icon_state = "pfork" + melt_temperature = MELTPOINT_PLASTIC + +/* + * Knives + */ +/obj/item/weapon/kitchen/utensil/knife + name = "knife" + desc = "Can cut through any food." + icon_state = "knife" + force = 10.0 + throwforce = 10.0 + sharpness = 1.2 + melt_temperature = MELTPOINT_STEEL + +/obj/item/weapon/kitchen/utensil/knife/suicide_act(mob/user) to_chat(viewers(user), pick("[user] is slitting \his wrists with the [src.name]! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) - return (BRUTELOSS) - -/obj/item/weapon/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) - if ((M_CLUMSY in user.mutations) && prob(50)) + "[user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ + "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) + return (BRUTELOSS) + +/obj/item/weapon/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) + if ((M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "You accidentally cut yourself with the [src].") - user.take_organ_damage(20) - return - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/kitchen/utensil/knife/plastic - name = "plastic knife" - desc = "The bluntest of blades." - icon_state = "pknife" - force = 2 - throwforce = 1 - sharpness = 0.8 - melt_temperature = MELTPOINT_PLASTIC - -/* - * Kitchen knives - */ -/obj/item/weapon/kitchen/utensil/knife/large - name = "kitchen knife" - icon = 'icons/obj/kitchen.dmi' - icon_state = "knife" - desc = "A general purpose Chef's Knife made by SpaceCook Incorporated. Guaranteed to stay sharp for years to come." - flags = FPRINT - siemens_coefficient = 1 - sharpness = 1.5 - force = 10.0 - w_class = 3.0 - throwforce = 6.0 - throw_speed = 3 - throw_range = 6 - starting_materials = list(MAT_IRON = 12000) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - origin_tech = "materials=1" - attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/weapon/kitchen/utensil/knife/large/suicide_act(mob/user) + user.take_organ_damage(20) + return + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/kitchen/utensil/knife/plastic + name = "plastic knife" + desc = "The bluntest of blades." + icon_state = "pknife" + force = 2 + throwforce = 1 + sharpness = 0.8 + melt_temperature = MELTPOINT_PLASTIC + +/* + * Kitchen knives + */ +/obj/item/weapon/kitchen/utensil/knife/large + name = "kitchen knife" + icon = 'icons/obj/kitchen.dmi' + icon_state = "knife" + desc = "A general purpose Chef's Knife made by SpaceCook Incorporated. Guaranteed to stay sharp for years to come." + flags = FPRINT + siemens_coefficient = 1 + sharpness = 1.5 + force = 10.0 + w_class = 3.0 + throwforce = 6.0 + throw_speed = 3 + throw_range = 6 + starting_materials = list(MAT_IRON = 12000) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + origin_tech = "materials=1" + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/kitchen/utensil/knife/large/suicide_act(mob/user) to_chat(viewers(user), pick("[user] is slitting \his wrists with the [src.name]! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) - return (BRUTELOSS) - -/obj/item/weapon/kitchen/utensil/knife/large/ritual - name = "ritual knife" - desc = "The unearthly energies that once powered this blade are now dormant." - icon = 'icons/obj/wizard.dmi' - icon_state = "render" - -/* - * Butcher's cleaver - */ -/obj/item/weapon/kitchen/utensil/knife/large/butch - name = "butcher's cleaver" - icon = 'icons/obj/kitchen.dmi' - icon_state = "butch" - hitsound = "sound/weapons/rapidslice.ogg" - desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." - flags = FPRINT - siemens_coefficient = 1 - sharpness = 1.2 - force = 15.0 - w_class = 2.0 - throwforce = 8.0 - throw_speed = 3 - throw_range = 6 - starting_materials = list(MAT_IRON = 12000) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - origin_tech = "materials=1" - attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver - name = "meat cleaver" - icon_state = "mcleaver" - desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." - force = 25.0 - throwforce = 15.0 - -/obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver/throw_impact(atom/hit_atom) - if(istype(hit_atom, /mob/living) && prob(85)) - var/mob/living/L = hit_atom - L.Stun(5) - L.Weaken(5) - return ..() - -/* - * Rolling Pins - */ - -/obj/item/weapon/kitchen/rollingpin - name = "rolling pin" - desc = "Used to knock out the Bartender." - icon_state = "rolling_pin" - hitsound = "sound/weapons/smash.ogg" - force = 8.0 - throwforce = 10.0 - throw_speed = 2 - throw_range = 7 - w_class = 3.0 - autoignition_temperature=AUTOIGNITION_WOOD - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") //I think the rollingpin attackby will end up ignoring this anyway. - -/obj/item/weapon/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob) - if ((M_CLUMSY in user.mutations) && prob(50)) + "[user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ + "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) + return (BRUTELOSS) + +/obj/item/weapon/kitchen/utensil/knife/large/ritual + name = "ritual knife" + desc = "The unearthly energies that once powered this blade are now dormant." + icon = 'icons/obj/wizard.dmi' + icon_state = "render" + +/* + * Butcher's cleaver + */ +/obj/item/weapon/kitchen/utensil/knife/large/butch + name = "butcher's cleaver" + icon = 'icons/obj/kitchen.dmi' + icon_state = "butch" + hitsound = "sound/weapons/rapidslice.ogg" + desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." + flags = FPRINT + siemens_coefficient = 1 + sharpness = 1.2 + force = 15.0 + w_class = 2.0 + throwforce = 8.0 + throw_speed = 3 + throw_range = 6 + starting_materials = list(MAT_IRON = 12000) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + origin_tech = "materials=1" + attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver + name = "meat cleaver" + icon_state = "mcleaver" + desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." + force = 25.0 + throwforce = 15.0 + +/obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver/throw_impact(atom/hit_atom) + if(istype(hit_atom, /mob/living) && prob(85)) + var/mob/living/L = hit_atom + L.Stun(5) + L.Weaken(5) + return ..() + +/* + * Rolling Pins + */ + +/obj/item/weapon/kitchen/rollingpin + name = "rolling pin" + desc = "Used to knock out the Bartender." + icon_state = "rolling_pin" + hitsound = "sound/weapons/smash.ogg" + force = 8.0 + throwforce = 10.0 + throw_speed = 2 + throw_range = 7 + w_class = 3.0 + autoignition_temperature=AUTOIGNITION_WOOD + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") //I think the rollingpin attackby will end up ignoring this anyway. + +/obj/item/weapon/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob) + if ((M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "The [src] slips out of your hand and hits your head.") - user.take_organ_damage(10) - user.Paralyse(2) - return - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - - log_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey])") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - var/t = user:zone_sel.selecting - if (t == "head") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if (H.stat < 2 && H.health < 50 && prob(90)) - // ******* Check - if (istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80)) + user.take_organ_damage(10) + user.Paralyse(2) + return + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + + log_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey])") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + var/t = user:zone_sel.selecting + if (t == "head") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if (H.stat < 2 && H.health < 50 && prob(90)) + // ******* Check + if (istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80)) to_chat(H, "The helmet protects you from being hit hard in the head!") - return - var/time = rand(2, 6) - if (prob(75)) - H.Paralyse(time) - else - H.Stun(time) - if(H.stat != 2) H.stat = 1 - user.visible_message("[H] has been knocked unconscious!", "You knock [H] unconscious!") - return - else - H.visible_message("[user] tried to knock [H] unconscious!", "[user] tried to knock you unconscious!") - H.eye_blurry += 3 - return ..() - -/* - * Trays - Agouri - */ -/obj/item/weapon/tray - name = "tray" - icon = 'icons/obj/food.dmi' - icon_state = "tray" - desc = "A metal tray to lay food on." - throwforce = 12.0 - throwforce = 10.0 - throw_speed = 1 - throw_range = 5 - w_class = 3.0 - flags = FPRINT - siemens_coefficient = 1 - starting_materials = list(MAT_IRON = 3000) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - var/list/carrying = list() // List of things on the tray. - Doohl - var/max_carry = 10 // w_class = 1 -- takes up 1 - // w_class = 2 -- takes up 3 - // w_class = 3 -- takes up 5 - -/obj/item/weapon/tray/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - - // Drop all the things. All of them. - overlays.len = 0 - for(var/obj/item/I in carrying) - I.loc = M.loc - carrying.Remove(I) - if(isturf(I.loc)) - spawn() - for(var/i = 1, i <= rand(1,2), i++) - if(I) - step(I, pick(NORTH,SOUTH,EAST,WEST)) - sleep(rand(2,4)) - - - if((M_CLUMSY in user.mutations) && prob(50)) //What if he's a clown? + return + var/time = rand(2, 6) + if (prob(75)) + H.Paralyse(time) + else + H.Stun(time) + if(H.stat != 2) H.stat = 1 + user.visible_message("[H] has been knocked unconscious!", "You knock [H] unconscious!") + return + else + H.visible_message("[user] tried to knock [H] unconscious!", "[user] tried to knock you unconscious!") + H.eye_blurry += 3 + return ..() + +/* + * Trays - Agouri + */ +/obj/item/weapon/tray + name = "tray" + icon = 'icons/obj/food.dmi' + icon_state = "tray" + desc = "A metal tray to lay food on." + throwforce = 12.0 + throwforce = 10.0 + throw_speed = 1 + throw_range = 5 + w_class = 3.0 + flags = FPRINT + siemens_coefficient = 1 + starting_materials = list(MAT_IRON = 3000) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + var/list/carrying = list() // List of things on the tray. - Doohl + var/max_carry = 10 // w_class = 1 -- takes up 1 + // w_class = 2 -- takes up 3 + // w_class = 3 -- takes up 5 + +/obj/item/weapon/tray/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + + // Drop all the things. All of them. + overlays.len = 0 + for(var/obj/item/I in carrying) + I.loc = M.loc + carrying.Remove(I) + if(isturf(I.loc)) + spawn() + for(var/i = 1, i <= rand(1,2), i++) + if(I) + step(I, pick(NORTH,SOUTH,EAST,WEST)) + sleep(rand(2,4)) + + + if((M_CLUMSY in user.mutations) && prob(50)) //What if he's a clown? to_chat(M, "You accidentally slam yourself with the [src]!") - M.Weaken(1) - user.take_organ_damage(2) - if(prob(50)) - playsound(M, 'sound/items/trayhit1.ogg', 50, 1) - return - else - playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' - return //it always returns, but I feel like adding an extra return just for safety's sakes. EDIT; Oh well I won't :3 - - var/mob/living/carbon/human/H = M ///////////////////////////////////// /Let's have this ready for later. - - - if(!(user.zone_sel.selecting == ("eyes" || "head"))) //////////////hitting anything else other than the eyes - if(prob(33)) - src.add_blood(H) - var/turf/location = H.loc - if (istype(location, /turf/simulated)) - location.add_blood(H) ///Plik plik, the sound of blood - - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - - log_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey])") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - if(prob(15)) - M.Weaken(3) - M.take_organ_damage(3) - else - M.take_organ_damage(5) - if(prob(50)) - playsound(M, 'sound/items/trayhit1.ogg', 50, 1) - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] slams [] with the tray!", user, M), 1) - return - else - playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //we applied the damage, we played the sound, we showed the appropriate messages. Time to return and stop the proc - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] slams [] with the tray!", user, M), 1) - return - - - - - if(istype(M, /mob/living/carbon/human) && H.check_body_part_coverage(EYES)) + M.Weaken(1) + user.take_organ_damage(2) + if(prob(50)) + playsound(M, 'sound/items/trayhit1.ogg', 50, 1) + return + else + playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' + return //it always returns, but I feel like adding an extra return just for safety's sakes. EDIT; Oh well I won't :3 + + var/mob/living/carbon/human/H = M ///////////////////////////////////// /Let's have this ready for later. + + + if(!(user.zone_sel.selecting == ("eyes" || "head"))) //////////////hitting anything else other than the eyes + if(prob(33)) + src.add_blood(H) + var/turf/location = H.loc + if (istype(location, /turf/simulated)) + location.add_blood(H) ///Plik plik, the sound of blood + + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + + log_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey])") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + if(prob(15)) + M.Weaken(3) + M.take_organ_damage(3) + else + M.take_organ_damage(5) + if(prob(50)) + playsound(M, 'sound/items/trayhit1.ogg', 50, 1) + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] slams [] with the tray!", user, M), 1) + return + else + playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //we applied the damage, we played the sound, we showed the appropriate messages. Time to return and stop the proc + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] slams [] with the tray!", user, M), 1) + return + + + + + if(istype(M, /mob/living/carbon/human) && H.check_body_part_coverage(EYES)) to_chat(H, "You get slammed in the face with the tray, against your mask!") - if(prob(33)) - src.add_blood(H) - if (H.wear_mask) - H.wear_mask.add_blood(H) - if (H.head) - H.head.add_blood(H) - if (H.glasses && prob(33)) - H.glasses.add_blood(H) - var/turf/location = H.loc - if (istype(location, /turf/simulated)) //Addin' blood! At least on the floor and item :v - location.add_blood(H) - - if(prob(50)) - playsound(M, 'sound/items/trayhit1.ogg', 50, 1) - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] slams [] with the tray!", user, M), 1) - else - playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] slams [] with the tray!", user, M), 1) - if(prob(10)) - M.Stun(rand(1,3)) - M.take_organ_damage(3) - return - else - M.take_organ_damage(5) - return - - else //No eye or head protection, tough luck! + if(prob(33)) + src.add_blood(H) + if (H.wear_mask) + H.wear_mask.add_blood(H) + if (H.head) + H.head.add_blood(H) + if (H.glasses && prob(33)) + H.glasses.add_blood(H) + var/turf/location = H.loc + if (istype(location, /turf/simulated)) //Addin' blood! At least on the floor and item :v + location.add_blood(H) + + if(prob(50)) + playsound(M, 'sound/items/trayhit1.ogg', 50, 1) + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] slams [] with the tray!", user, M), 1) + else + playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] slams [] with the tray!", user, M), 1) + if(prob(10)) + M.Stun(rand(1,3)) + M.take_organ_damage(3) + return + else + M.take_organ_damage(5) + return + + else //No eye or head protection, tough luck! to_chat(M, "You get slammed in the face with the tray!") - if(prob(33)) - src.add_blood(M) - var/turf/location = H.loc - if (istype(location, /turf/simulated)) - location.add_blood(H) - - if(prob(50)) - playsound(M, 'sound/items/trayhit1.ogg', 50, 1) - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] slams [] in the face with the tray!", user, M), 1) - else - playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' again - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] slams [] in the face with the tray!", user, M), 1) - if(prob(30)) - M.Stun(rand(2,4)) - M.take_organ_damage(4) - return - else - M.take_organ_damage(8) - if(prob(30)) - M.Weaken(2) - return - return - -/obj/item/weapon/tray/var/cooldown = 0 //shield bash cooldown. based on world.time - -/obj/item/weapon/tray/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/kitchen/rollingpin)) - if(cooldown < world.time - 25) - user.visible_message("[user] bashes [src] with [W]!") - playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - cooldown = world.time - else - ..() - -/* -===============~~~~~================================~~~~~==================== -= = -= Code for trays carrying things. By Doohl for Doohl erryday Doohl Doohl~ = -= = -===============~~~~~================================~~~~~==================== -*/ -/obj/item/weapon/tray/proc/calc_carry() - // calculate the weight of the items on the tray - var/val = 0 // value to return - - for(var/obj/item/I in carrying) - if(I.w_class == 1.0) - val ++ - else if(I.w_class == 2.0) - val += 3 - else - val += 5 - - return val - -/obj/item/weapon/tray/pickup(mob/user) - - if(!isturf(loc)) - return - - for(var/obj/item/I in loc) - if( I != src && !I.anchored && !istype(I, /obj/item/clothing/under) && !istype(I, /obj/item/clothing/suit) && !istype(I, /obj/item/projectile) ) - var/add = 0 - if(I.w_class == 1.0) - add = 1 - else if(I.w_class == 2.0) - add = 3 - else - add = 5 - if(calc_carry() + add >= max_carry) - break - - I.loc = src - carrying.Add(I) - - var/image/image = image(icon = null) //image(appearance = ...) doesn't work, and neither does image(). - image.appearance = I.appearance - image.layer = I.layer + 30 - - overlays += image - //overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = 30 + I.layer) - -/obj/item/weapon/tray/dropped(mob/user) - - var/mob/living/M - for(M in src.loc) //to handle hand switching - return - - var/foundtable = 0 - for(var/obj/structure/table/T in loc) - foundtable = 1 - break - - overlays.len = 0 - - for(var/obj/item/I in carrying) - I.loc = loc - carrying.Remove(I) - if(!foundtable && isturf(loc)) - // if no table, presume that the person just shittily dropped the tray on the ground and made a mess everywhere! - spawn() - for(var/i = 1, i <= rand(1,2), i++) - if(I) - step(I, pick(NORTH,SOUTH,EAST,WEST)) - sleep(rand(2,4)) - - - - - -///////////////////////////////////////////////////////////////////////////////////////// -//Enough with the violent stuff, here's what happens if you try putting food on it -///////////////////////////////////////////////////////////////////////////////////////////// - - - -/*/obj/item/weapon/tray/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/kitchen/utensil/fork)) - if (W.icon_state == "forkloaded") + if(prob(33)) + src.add_blood(M) + var/turf/location = H.loc + if (istype(location, /turf/simulated)) + location.add_blood(H) + + if(prob(50)) + playsound(M, 'sound/items/trayhit1.ogg', 50, 1) + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] slams [] in the face with the tray!", user, M), 1) + else + playsound(M, 'sound/items/trayhit2.ogg', 50, 1) //sound playin' again + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] slams [] in the face with the tray!", user, M), 1) + if(prob(30)) + M.Stun(rand(2,4)) + M.take_organ_damage(4) + return + else + M.take_organ_damage(8) + if(prob(30)) + M.Weaken(2) + return + return + +/obj/item/weapon/tray/var/cooldown = 0 //shield bash cooldown. based on world.time + +/obj/item/weapon/tray/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/kitchen/rollingpin)) + if(cooldown < world.time - 25) + user.visible_message("[user] bashes [src] with [W]!") + playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) + cooldown = world.time + else + ..() + +/* +===============~~~~~================================~~~~~==================== += = += Code for trays carrying things. By Doohl for Doohl erryday Doohl Doohl~ = += = +===============~~~~~================================~~~~~==================== +*/ +/obj/item/weapon/tray/proc/calc_carry() + // calculate the weight of the items on the tray + var/val = 0 // value to return + + for(var/obj/item/I in carrying) + if(I.w_class == 1.0) + val ++ + else if(I.w_class == 2.0) + val += 3 + else + val += 5 + + return val + +/obj/item/weapon/tray/pickup(mob/user) + + if(!isturf(loc)) + return + + for(var/obj/item/I in loc) + if( I != src && !I.anchored && !istype(I, /obj/item/clothing/under) && !istype(I, /obj/item/clothing/suit) && !istype(I, /obj/item/projectile) ) + var/add = 0 + if(I.w_class == 1.0) + add = 1 + else if(I.w_class == 2.0) + add = 3 + else + add = 5 + if(calc_carry() + add >= max_carry) + break + + I.loc = src + carrying.Add(I) + + var/image/image = image(icon = null) //image(appearance = ...) doesn't work, and neither does image(). + image.appearance = I.appearance + image.layer = I.layer + 30 + + overlays += image + //overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = 30 + I.layer) + +/obj/item/weapon/tray/dropped(mob/user) + + var/mob/living/M + for(M in src.loc) //to handle hand switching + return + + var/foundtable = 0 + for(var/obj/structure/table/T in loc) + foundtable = 1 + break + + overlays.len = 0 + + for(var/obj/item/I in carrying) + I.loc = loc + carrying.Remove(I) + if(!foundtable && isturf(loc)) + // if no table, presume that the person just shittily dropped the tray on the ground and made a mess everywhere! + spawn() + for(var/i = 1, i <= rand(1,2), i++) + if(I) + step(I, pick(NORTH,SOUTH,EAST,WEST)) + sleep(rand(2,4)) + + + + + +///////////////////////////////////////////////////////////////////////////////////////// +//Enough with the violent stuff, here's what happens if you try putting food on it +///////////////////////////////////////////////////////////////////////////////////////////// + + + +/*/obj/item/weapon/tray/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W,/obj/item/weapon/kitchen/utensil/fork)) + if (W.icon_state == "forkloaded") to_chat(user, "You already have omelette on your fork.") - return - W.icon = 'icons/obj/kitchen.dmi' - W.icon_state = "forkloaded" + return + W.icon = 'icons/obj/kitchen.dmi' + W.icon_state = "forkloaded" to_chat(viewers(3,user), "[user] takes a piece of omelette with his fork!") - reagents.remove_reagent("nutriment", 1) - if (reagents.total_volume <= 0) - del(src)*/ - - -/* if (prob(33)) - var/turf/location = H.loc - if (istype(location, /turf/simulated)) - location.add_blood(H) - if (H.wear_mask) - H.wear_mask.add_blood(H) - if (H.head) - H.head.add_blood(H) - if (H.glasses && prob(33)) - H.glasses.add_blood(H) - if (istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/user2 = user - if (user2.gloves) - user2.gloves.add_blood(H) - else - user2.add_blood(H) - if (prob(15)) - if (user2.wear_suit) - user2.wear_suit.add_blood(H) - else if (user2.w_uniform) - user2.w_uniform.add_blood(H)*/ + reagents.remove_reagent("nutriment", 1) + if (reagents.total_volume <= 0) + del(src)*/ + + +/* if (prob(33)) + var/turf/location = H.loc + if (istype(location, /turf/simulated)) + location.add_blood(H) + if (H.wear_mask) + H.wear_mask.add_blood(H) + if (H.head) + H.head.add_blood(H) + if (H.glasses && prob(33)) + H.glasses.add_blood(H) + if (istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/user2 = user + if (user2.gloves) + user2.gloves.add_blood(H) + else + user2.add_blood(H) + if (prob(15)) + if (user2.wear_suit) + user2.wear_suit.add_blood(H) + else if (user2.w_uniform) + user2.w_uniform.add_blood(H)*/ diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index fe38661e969..cedf5d99c4e 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -1,605 +1,605 @@ -/*********************MANUALS (BOOKS)***********************/ - -//Oh god what the fuck I am not good at computer -/obj/item/weapon/book/manual - icon = 'icons/obj/library.dmi' - due_date = 0 // Game time in 1/10th seconds - unique = 1 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified - -/obj/item/weapon/book/manual/engineering_construction - name = "Station Repairs and Construction" - icon_state ="bookEngineering" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Station Repairs and Construction" - wiki_page = "Guide_to_Construction" - -/obj/item/weapon/book/manual/engineering_particle_accelerator - name = "Particle Accelerator User's Guide" - icon_state ="bookParticleAccelerator" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Particle Accelerator User's Guide" -//big pile of shit below. - - dat = {" - - - - - -

    Experienced user's guide

    - -

    Setting up

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

    Use

    - -
      -
    1. Open the control panel
    2. -
    3. Set the speed to 2
    4. -
    5. Start firing at the singularity generator
    6. -
    7. When the singularity reaches a large enough size so it starts moving on it's own set the speed down to 0, but don't shut it off
    8. -
    9. Remember to wear a radiation suit when working with this machine... we did tell you that at the start, right?
    10. -
    - - - "} - - -/obj/item/weapon/book/manual/engineering_hacking - name = "Hacking" - icon_state ="bookHacking" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Hacking" - wiki_page = "Hacking" - -/obj/item/weapon/book/manual/engineering_singularity_safety - name = "Singularity Safety in Special Circumstances" - icon_state ="bookEngineeringSingularitySafety" - author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Singularity Safety in Special Circumstances" -//big pile of shit below. - - dat = {" - - - - -

    Singularity Safety in Special Circumstances

    - -

    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!!!
    -

    - -

    Shields get damaged

    - - Step one: GET THE FUCK OUT OF THERE!!! FORGET THE WOMEN AND CHILDREN, SAVE YOURSELF!!!
    - - - "} - -/obj/item/weapon/book/manual/hydroponics_pod_people - name = "The Human Harvest - From seed to market" - icon_state ="bookHydroponicsPodPeople" - author = "Farmer John" - title = "The Human Harvest - From seed to market" - /*dat = {" - - - - -

    Growing Humans

    - - Why would you want to grow humans? Well I'm expecting most readers to be in the slave trade, but a few might actually - want to revive fallen comrades. Growing pod people is easy, but prone to disaster. -

    -

      -
    1. Find a dead person who is in need of cloning.
    2. -
    3. Take a blood sample with a syringe.
    4. -
    5. Inject a seed pack with the blood sample.
    6. -
    7. Plant the seeds.
    8. -
    9. Tend to the plants water and nutrition levels until it is time to harvest the cloned human.
    10. -
    -

    - It really is that easy! Good luck! - - - - "}*/ - -/obj/item/weapon/book/manual/medical_cloning - 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" -//big pile of shit below. - - 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. - -
      -
    1. Acquire body
    2. -
    3. Strip body
    4. -
    5. Put body in cloning machine
    6. -
    7. Scan body
    8. -
    9. Clone body
    10. -
    11. Get clean Structurel Enzymes for the body
    12. -
    13. Put body in morgue
    14. -
    15. Await cloned body
    16. -
    17. Use the clean SW injector
    18. -
    19. Give person clothes back
    20. -
    21. Send person on their way
    22. -
    - -

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

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

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

    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: Use the clean SE injector on person

    - Has your body been cloned yet? Great! As soon as the guy pops out, grab your 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 11: Send person on their way

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

    If you’ve gotten this far, congratulations! You have mastered the art of cloning. Now, the real problem is how to resurrect yourself after that traitor had his way with you for cloning his target. - - - - - - "} - -/obj/item/weapon/book/manual/chemistry_manual - name = "Chemistry 101" - icon_state ="bookChemistry" - author = "SpaceChem Inc." - title = "Chemistry 101" - wiki_page = "Chemistry_101" - - -/obj/item/weapon/book/manual/ripley_build_and_repair - name = "APLU \"Ripley\" Construction and Operation Manual" - icon_state ="book" - author = "Weyland-Yutani Corp" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "APLU \"Ripley\" Construction and Operation Manual" -//big pile of shit below. - - /*dat = {" - - - - -

    - Weyland-Yutani - Building Better Worlds -

    Autonomous Power Loader Unit \"Ripley\"

    -
    -

    Specifications:

    -
      -
    • Class: Autonomous Power Loader
    • -
    • Scope: Logistics and Construction
    • -
    • Weight: 820kg (without operator and with empty cargo compartment)
    • -
    • Height: 2.5m
    • -
    • Width: 1.8m
    • -
    • Top speed: 5km/hour
    • -
    • Operation in vacuum/hostile environment: Possible -
    • Airtank Volume: 500liters
    • -
    • Devices: -
        -
      • Hydraulic Clamp
      • -
      • High-speed Drill
      • -
      -
    • -
    • Propulsion Device: Powercell-powered electro-hydraulic system.
    • -
    • Powercell capacity: Varies.
    • -
    - -

    Construction:

    -
      -
    1. Connect all exosuit parts to the chassis frame
    2. -
    3. Connect all hydraulic fittings and tighten them up with a wrench
    4. -
    5. Adjust the servohydraulics with a screwdriver
    6. -
    7. Wire the chassis. (Cable is not included.)
    8. -
    9. Use the wirecutters to remove the excess cable if needed.
    10. -
    11. Install the central control module (Not included. Use supplied datadisk to create one).
    12. -
    13. Secure the mainboard with a screwdriver.
    14. -
    15. Install the peripherals control module (Not included. Use supplied datadisk to create one).
    16. -
    17. Secure the peripherals control module with a screwdriver
    18. -
    19. Install the internal armor plating (Not included due to Nanotrasen regulations. Can be made using 5 metal sheets.)
    20. -
    21. Secure the internal armor plating with a wrench
    22. -
    23. Weld the internal armor plating to the chassis
    24. -
    25. Install the external reinforced armor plating (Not included due to Nanotrasen regulations. Can be made using 5 reinforced metal sheets.)
    26. -
    27. Secure the external reinforced armor plating with a wrench
    28. -
    29. Weld the external reinforced armor plating to the chassis
    30. -
    31. -
    32. Additional Information:
    33. -
    34. The firefighting variation is made in a similar fashion.
    35. -
    36. A firesuit must be connected to the Firefighter chassis for heat shielding.
    37. -
    38. Internal armor is plasteel for additional strength.
    39. -
    40. External armor must be installed in 2 parts, totaling 10 sheets.
    41. -
    42. Completed mech is more resiliant against fire, and is a bit more durable overall
    43. -
    44. Nanotrasen is determined to the safety of its investments employees.
    45. -
    - - - -

    Operation

    - Coming soon... - "}*/ - - -/obj/item/weapon/book/manual/research_and_development - name = "Research and Development 101" - icon_state = "rdbook" - author = "Dr. L. Ight" - title = "Research and Development 101" - dat = {" - - - - - -

    Science For Dummies

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

    The R&D Console

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

    Destructive Analyzer

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

    Circuit Imprinter

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

    Protolathe

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

    Reliability and You

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

    Building a Better Machine

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

    Cyborgs for Dummies

    - -

    Chapters

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

    Cyborg Related Equipment

    - -

    Exosuit Fabricator

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

    Cyborg Recharging Station

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

    Robotics Control Console

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

    Cyborg Modules

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

    Standard Cyborg

    - The standard cyborg module is a multi-purpose cyborg. It is equipped with various modules, allowing it to do basic tasks.
    A Standard Cyborg comes with: -
      -
    • Crowbar
    • -
    • Stun Baton
    • -
    • Health Analyzer
    • -
    • Fire Extinguisher
    • -
    - -

    Engineering Cyborg

    - The Engineering cyborg module comes equipped with various engineering-related tools to help with engineering-related tasks.
    An Engineering Cyborg comes with: -
      -
    • A basic set of engineering tools
    • -
    • Metal Synthesizer
    • -
    • Reinforced Glass Synthesizer
    • -
    • An RCD
    • -
    • Wire Synthesizer
    • -
    • Fire Extinguisher
    • -
    • Built-in Optical Meson Scanners
    • -
    - -

    Mining Cyborg

    - The Mining Cyborg module comes equipped with the latest in mining equipment. They are efficient at mining due to no need for oxygen, but their power cells limit their time in the mines.
    A Mining Cyborg comes with: -
      -
    • Jackhammer
    • -
    • Shovel
    • -
    • Mining Satchel
    • -
    • Built-in Optical Meson Scanners
    • -
    - -

    Security Cyborg

    - The Security Cyborg module is equipped with effective security measures used to apprehend and arrest criminals without harming them a bit.
    A Security Cyborg comes with: -
      -
    • Stun Baton
    • -
    • Handcuffs
    • -
    • Taser
    • -
    - -

    Janitor Cyborg

    - The Janitor Cyborg module is equipped with various cleaning-facilitating devices.
    A Janitor Cyborg comes with: -
      -
    • Mop
    • -
    • Hand Bucket
    • -
    • Cleaning Spray Synthesizer and Spray Nozzle
    • -
    - -

    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: -
      -
    • Shaker
    • -
    • Industrial Dropper
    • -
    • Platter
    • -
    • Beer Synthesizer
    • -
    • Zippo Lighter
    • -
    • Rapid-Service-Fabricator (Produces various entertainment and refreshment objects)
    • -
    • Pen
    • -
    - -

    Cyborg Construction

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

    Cyborg Maintenance

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

    Replacing a Power Cell

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

    Exposing the Internal Wiring

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

    Cyborg Repairs

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

    Dents

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

    Excessive Heat Damage

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

    In Case of Emergency

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

    "Rogue" Cyborgs

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

    As a last resort

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

    WARNING:

    Do not detonate a borg without an explicit reason for doing so. Cyborgs are expensive pieces of Nanotrasen equipment, and you may be punished for detonating them without reason. - - - - "} - -/obj/item/weapon/book/manual/security_space_law - name = "Space Law" - desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." - icon_state = "bookSpaceLaw" - author = "Nanotrasen" - title = "Space Law" - wiki_page = "Space_Law" - -/obj/item/weapon/book/manual/engineering_guide - name = "Engineering Textbook" - icon_state ="bookEngineering2" - author = "Engineering Encyclopedia" - title = "Engineering Textbook" - wiki_page = "Guide_to_Engineering" - - -/obj/item/weapon/book/manual/chef_recipes - name = "Chef Recipes" - icon_state = "cooked_book" - author = "Lord Frenrir Cageth" - title = "Chef Recipes" - wiki_page = "Chef_recipes" - -/obj/item/weapon/book/manual/barman_recipes - name = "Barman Recipes" - icon_state = "barbook" - author = "Sir John Rose" - title = "Barman Recipes" - wiki_page = "Barman_recipes" - -/obj/item/weapon/book/manual/detective - name = "The Film Noir: proper Procedures for Investigations" - icon_state ="bookDetective" - author = "Nanotrasen" - title = "The Film Noir: proper Procedures for Investigations" - wiki_page = "Guide_to_Forensics" - -/obj/item/weapon/book/manual/nuclear - name = "Fission Mailed: Nuclear Sabotage 101" - icon_state ="bookNuclear" - author = "Syndicate" - title = "Fission Mailed: Nuclear Sabotage 101" - wiki_page = "Nuclear_Agent" - forbidden = 2 // Only available to emagged terminals. +/*********************MANUALS (BOOKS)***********************/ + +//Oh god what the fuck I am not good at computer +/obj/item/weapon/book/manual + icon = 'icons/obj/library.dmi' + due_date = 0 // Game time in 1/10th seconds + unique = 1 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified + +/obj/item/weapon/book/manual/engineering_construction + name = "Station Repairs and Construction" + icon_state ="bookEngineering" + author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + title = "Station Repairs and Construction" + wiki_page = "Guide_to_Construction" + +/obj/item/weapon/book/manual/engineering_particle_accelerator + name = "Particle Accelerator User's Guide" + icon_state ="bookParticleAccelerator" + author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + title = "Particle Accelerator User's Guide" +//big pile of shit below. + + dat = {" + + + + + +

    Experienced user's guide

    + +

    Setting up

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

    Use

    + +
      +
    1. Open the control panel
    2. +
    3. Set the speed to 2
    4. +
    5. Start firing at the singularity generator
    6. +
    7. When the singularity reaches a large enough size so it starts moving on it's own set the speed down to 0, but don't shut it off
    8. +
    9. Remember to wear a radiation suit when working with this machine... we did tell you that at the start, right?
    10. +
    + + + "} + + +/obj/item/weapon/book/manual/engineering_hacking + name = "Hacking" + icon_state ="bookHacking" + author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + title = "Hacking" + wiki_page = "Hacking" + +/obj/item/weapon/book/manual/engineering_singularity_safety + name = "Singularity Safety in Special Circumstances" + icon_state ="bookEngineeringSingularitySafety" + author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + title = "Singularity Safety in Special Circumstances" +//big pile of shit below. + + dat = {" + + + + +

    Singularity Safety in Special Circumstances

    + +

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

    + +

    Shields get damaged

    + + Step one: GET THE FUCK OUT OF THERE!!! FORGET THE WOMEN AND CHILDREN, SAVE YOURSELF!!!
    + + + "} + +/obj/item/weapon/book/manual/hydroponics_pod_people + name = "The Human Harvest - From seed to market" + icon_state ="bookHydroponicsPodPeople" + author = "Farmer John" + title = "The Human Harvest - From seed to market" + /*dat = {" + + + + +

    Growing Humans

    + + Why would you want to grow humans? Well I'm expecting most readers to be in the slave trade, but a few might actually + want to revive fallen comrades. Growing pod people is easy, but prone to disaster. +

    +

      +
    1. Find a dead person who is in need of cloning.
    2. +
    3. Take a blood sample with a syringe.
    4. +
    5. Inject a seed pack with the blood sample.
    6. +
    7. Plant the seeds.
    8. +
    9. Tend to the plants water and nutrition levels until it is time to harvest the cloned human.
    10. +
    +

    + It really is that easy! Good luck! + + + + "}*/ + +/obj/item/weapon/book/manual/medical_cloning + 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" +//big pile of shit below. + + 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. + +
      +
    1. Acquire body
    2. +
    3. Strip body
    4. +
    5. Put body in cloning machine
    6. +
    7. Scan body
    8. +
    9. Clone body
    10. +
    11. Get clean Structurel Enzymes for the body
    12. +
    13. Put body in morgue
    14. +
    15. Await cloned body
    16. +
    17. Use the clean SW injector
    18. +
    19. Give person clothes back
    20. +
    21. Send person on their way
    22. +
    + +

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

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

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

    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: Use the clean SE injector on person

    + Has your body been cloned yet? Great! As soon as the guy pops out, grab your 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 11: Send person on their way

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

    If you’ve gotten this far, congratulations! You have mastered the art of cloning. Now, the real problem is how to resurrect yourself after that traitor had his way with you for cloning his target. + + + + + + "} + +/obj/item/weapon/book/manual/chemistry_manual + name = "Chemistry 101" + icon_state ="bookChemistry" + author = "SpaceChem Inc." + title = "Chemistry 101" + wiki_page = "Chemistry_101" + + +/obj/item/weapon/book/manual/ripley_build_and_repair + name = "APLU \"Ripley\" Construction and Operation Manual" + icon_state ="book" + author = "Weyland-Yutani Corp" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + title = "APLU \"Ripley\" Construction and Operation Manual" +//big pile of shit below. + + /*dat = {" + + + + +

    + Weyland-Yutani - Building Better Worlds +

    Autonomous Power Loader Unit \"Ripley\"

    +
    +

    Specifications:

    +
      +
    • Class: Autonomous Power Loader
    • +
    • Scope: Logistics and Construction
    • +
    • Weight: 820kg (without operator and with empty cargo compartment)
    • +
    • Height: 2.5m
    • +
    • Width: 1.8m
    • +
    • Top speed: 5km/hour
    • +
    • Operation in vacuum/hostile environment: Possible +
    • Airtank Volume: 500liters
    • +
    • Devices: +
        +
      • Hydraulic Clamp
      • +
      • High-speed Drill
      • +
      +
    • +
    • Propulsion Device: Powercell-powered electro-hydraulic system.
    • +
    • Powercell capacity: Varies.
    • +
    + +

    Construction:

    +
      +
    1. Connect all exosuit parts to the chassis frame
    2. +
    3. Connect all hydraulic fittings and tighten them up with a wrench
    4. +
    5. Adjust the servohydraulics with a screwdriver
    6. +
    7. Wire the chassis. (Cable is not included.)
    8. +
    9. Use the wirecutters to remove the excess cable if needed.
    10. +
    11. Install the central control module (Not included. Use supplied datadisk to create one).
    12. +
    13. Secure the mainboard with a screwdriver.
    14. +
    15. Install the peripherals control module (Not included. Use supplied datadisk to create one).
    16. +
    17. Secure the peripherals control module with a screwdriver
    18. +
    19. Install the internal armor plating (Not included due to Nanotrasen regulations. Can be made using 5 metal sheets.)
    20. +
    21. Secure the internal armor plating with a wrench
    22. +
    23. Weld the internal armor plating to the chassis
    24. +
    25. Install the external reinforced armor plating (Not included due to Nanotrasen regulations. Can be made using 5 reinforced metal sheets.)
    26. +
    27. Secure the external reinforced armor plating with a wrench
    28. +
    29. Weld the external reinforced armor plating to the chassis
    30. +
    31. +
    32. Additional Information:
    33. +
    34. The firefighting variation is made in a similar fashion.
    35. +
    36. A firesuit must be connected to the Firefighter chassis for heat shielding.
    37. +
    38. Internal armor is plasteel for additional strength.
    39. +
    40. External armor must be installed in 2 parts, totaling 10 sheets.
    41. +
    42. Completed mech is more resiliant against fire, and is a bit more durable overall
    43. +
    44. Nanotrasen is determined to the safety of its investments employees.
    45. +
    + + + +

    Operation

    + Coming soon... + "}*/ + + +/obj/item/weapon/book/manual/research_and_development + name = "Research and Development 101" + icon_state = "rdbook" + author = "Dr. L. Ight" + title = "Research and Development 101" + dat = {" + + + + + +

    Science For Dummies

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

    The R&D Console

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

    Destructive Analyzer

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

    Circuit Imprinter

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

    Protolathe

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

    Reliability and You

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

    Building a Better Machine

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

    Cyborgs for Dummies

    + +

    Chapters

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

    Cyborg Related Equipment

    + +

    Exosuit Fabricator

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

    Cyborg Recharging Station

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

    Robotics Control Console

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

    Cyborg Modules

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

    Standard Cyborg

    + The standard cyborg module is a multi-purpose cyborg. It is equipped with various modules, allowing it to do basic tasks.
    A Standard Cyborg comes with: +
      +
    • Crowbar
    • +
    • Stun Baton
    • +
    • Health Analyzer
    • +
    • Fire Extinguisher
    • +
    + +

    Engineering Cyborg

    + The Engineering cyborg module comes equipped with various engineering-related tools to help with engineering-related tasks.
    An Engineering Cyborg comes with: +
      +
    • A basic set of engineering tools
    • +
    • Metal Synthesizer
    • +
    • Reinforced Glass Synthesizer
    • +
    • An RCD
    • +
    • Wire Synthesizer
    • +
    • Fire Extinguisher
    • +
    • Built-in Optical Meson Scanners
    • +
    + +

    Mining Cyborg

    + The Mining Cyborg module comes equipped with the latest in mining equipment. They are efficient at mining due to no need for oxygen, but their power cells limit their time in the mines.
    A Mining Cyborg comes with: +
      +
    • Jackhammer
    • +
    • Shovel
    • +
    • Mining Satchel
    • +
    • Built-in Optical Meson Scanners
    • +
    + +

    Security Cyborg

    + The Security Cyborg module is equipped with effective security measures used to apprehend and arrest criminals without harming them a bit.
    A Security Cyborg comes with: +
      +
    • Stun Baton
    • +
    • Handcuffs
    • +
    • Taser
    • +
    + +

    Janitor Cyborg

    + The Janitor Cyborg module is equipped with various cleaning-facilitating devices.
    A Janitor Cyborg comes with: +
      +
    • Mop
    • +
    • Hand Bucket
    • +
    • Cleaning Spray Synthesizer and Spray Nozzle
    • +
    + +

    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: +
      +
    • Shaker
    • +
    • Industrial Dropper
    • +
    • Platter
    • +
    • Beer Synthesizer
    • +
    • Zippo Lighter
    • +
    • Rapid-Service-Fabricator (Produces various entertainment and refreshment objects)
    • +
    • Pen
    • +
    + +

    Cyborg Construction

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

    Cyborg Maintenance

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

    Replacing a Power Cell

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

    Exposing the Internal Wiring

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

    Cyborg Repairs

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

    Dents

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

    Excessive Heat Damage

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

    In Case of Emergency

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

    "Rogue" Cyborgs

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

    As a last resort

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

    WARNING:

    Do not detonate a borg without an explicit reason for doing so. Cyborgs are expensive pieces of Nanotrasen equipment, and you may be punished for detonating them without reason. + + + + "} + +/obj/item/weapon/book/manual/security_space_law + name = "Space Law" + desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." + icon_state = "bookSpaceLaw" + author = "Nanotrasen" + title = "Space Law" + wiki_page = "Space_Law" + +/obj/item/weapon/book/manual/engineering_guide + name = "Engineering Textbook" + icon_state ="bookEngineering2" + author = "Engineering Encyclopedia" + title = "Engineering Textbook" + wiki_page = "Guide_to_Engineering" + + +/obj/item/weapon/book/manual/chef_recipes + name = "Chef Recipes" + icon_state = "cooked_book" + author = "Lord Frenrir Cageth" + title = "Chef Recipes" + wiki_page = "Chef_recipes" + +/obj/item/weapon/book/manual/barman_recipes + name = "Barman Recipes" + icon_state = "barbook" + author = "Sir John Rose" + title = "Barman Recipes" + wiki_page = "Barman_recipes" + +/obj/item/weapon/book/manual/detective + name = "The Film Noir: proper Procedures for Investigations" + icon_state ="bookDetective" + author = "Nanotrasen" + title = "The Film Noir: proper Procedures for Investigations" + wiki_page = "Guide_to_Forensics" + +/obj/item/weapon/book/manual/nuclear + name = "Fission Mailed: Nuclear Sabotage 101" + icon_state ="bookNuclear" + author = "Syndicate" + title = "Fission Mailed: Nuclear Sabotage 101" + wiki_page = "Nuclear_Agent" + forbidden = 2 // Only available to emagged terminals. diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 66341e0f165..0fc1200719f 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -1,130 +1,130 @@ -/obj/item/weapon/melee/energy - var/active = 0 - sharpness = 1.5 //very very sharp - heat_production = 3500 - -/obj/item/weapon/melee/energy/suicide_act(mob/user) - to_chat(viewers(user), pick("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.", \ - "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")) - return (BRUTELOSS|FIRELOSS) - -/obj/item/weapon/melee/energy/is_hot() - if(active) - return heat_production - return 0 - -/obj/item/weapon/melee/energy/is_sharp() - if(active) - return sharpness - return 0 - -/obj/item/weapon/melee/energy/axe - name = "energy axe" - desc = "An energised battle axe." - icon_state = "axe0" - force = 40.0 - throwforce = 25.0 - throw_speed = 1 - throw_range = 5 - w_class = 3.0 - flags = FPRINT - siemens_coefficient = 1 - origin_tech = "combat=3" - attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") - - - suicide_act(mob/user) - to_chat(viewers(user), "[user] swings the [src.name] towards /his head! It looks like \he's trying to commit suicide.") - return (BRUTELOSS|FIRELOSS) - -/obj/item/weapon/melee/energy/sword - name = "energy sword" - desc = "May the force be within you." - icon_state = "sword0" - var/base_state = "sword" - var/active_state = "" - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - flags = FPRINT - origin_tech = "magnets=3;syndicate=4" - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - -/obj/item/weapon/melee/energy/sword/IsShield() - if(active) - return 1 - return 0 - -/obj/item/weapon/melee/energy/sword/New() - ..() - _color = pick("red","blue","green","purple") - if(!active_state) - active_state = base_state + _color - update_icon() - -/obj/item/weapon/melee/energy/sword/attack_self(mob/living/user as mob) - if ((M_CLUMSY in user.mutations) && prob(50) && active) //only an on blade can cut - to_chat(user, "You accidentally cut yourself with [src].") - user.take_organ_damage(5,5) - return - toggleActive(user) - add_fingerprint(user) - return - -/obj/item/weapon/melee/energy/sword/proc/toggleActive(mob/user, var/togglestate = "") //you can use togglestate to manually set the sword on or off - switch(togglestate) - if("on") - active = 1 - if("off") - active = 0 - else - active = !active - if (active) - force = 30 - w_class = 4 - sharpness = 1.5 - hitsound = "sound/weapons/blade1.ogg" - playsound(user, 'sound/weapons/saberon.ogg', 50, 1) - to_chat(user, " [src] is now active.") - else - force = 3 - w_class = 2 - sharpness = 0 - playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) - hitsound = "sound/weapons/empty.ogg" - to_chat(user, " [src] can now be concealed.") - update_icon() - -/obj/item/weapon/melee/energy/sword/update_icon() - if(active && _color) - icon_state = active_state - else - icon_state = "[base_state][active]" - -/obj/item/weapon/melee/energy/sword/attackby(obj/item/weapon/W, mob/living/user) - ..() - if(istype(W, /obj/item/weapon/melee/energy/sword)) - if(W == src) - to_chat(user, "You try to attach the end of the energy sword to... itself. You're not very smart, are you?") - if(ishuman(user)) - user.adjustBrainLoss(10) - else - to_chat(user, "You attach the ends of the two energy swords, making a single double-bladed weapon! You're cool.") - new /obj/item/weapon/dualsaber(user.loc) - qdel(W) - W = null - qdel(src) - -/obj/item/weapon/melee/energy/sword/pirate - name = "energy cutlass" - desc = "Arrrr matey." - icon_state = "cutlass0" - base_state = "cutlass" - -/obj/item/weapon/melee/energy/sword/pirate/New() - ..() - _color = null - update_icon() +/obj/item/weapon/melee/energy + var/active = 0 + sharpness = 1.5 //very very sharp + heat_production = 3500 + +/obj/item/weapon/melee/energy/suicide_act(mob/user) + to_chat(viewers(user), pick("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.", \ + "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")) + return (BRUTELOSS|FIRELOSS) + +/obj/item/weapon/melee/energy/is_hot() + if(active) + return heat_production + return 0 + +/obj/item/weapon/melee/energy/is_sharp() + if(active) + return sharpness + return 0 + +/obj/item/weapon/melee/energy/axe + name = "energy axe" + desc = "An energised battle axe." + icon_state = "axe0" + force = 40.0 + throwforce = 25.0 + throw_speed = 1 + throw_range = 5 + w_class = 3.0 + flags = FPRINT + siemens_coefficient = 1 + origin_tech = "combat=3" + attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") + + + suicide_act(mob/user) + to_chat(viewers(user), "[user] swings the [src.name] towards /his head! It looks like \he's trying to commit suicide.") + return (BRUTELOSS|FIRELOSS) + +/obj/item/weapon/melee/energy/sword + name = "energy sword" + desc = "May the force be within you." + icon_state = "sword0" + var/base_state = "sword" + var/active_state = "" + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + flags = FPRINT + origin_tech = "magnets=3;syndicate=4" + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + +/obj/item/weapon/melee/energy/sword/IsShield() + if(active) + return 1 + return 0 + +/obj/item/weapon/melee/energy/sword/New() + ..() + _color = pick("red","blue","green","purple") + if(!active_state) + active_state = base_state + _color + update_icon() + +/obj/item/weapon/melee/energy/sword/attack_self(mob/living/user as mob) + if ((M_CLUMSY in user.mutations) && prob(50) && active) //only an on blade can cut + to_chat(user, "You accidentally cut yourself with [src].") + user.take_organ_damage(5,5) + return + toggleActive(user) + add_fingerprint(user) + return + +/obj/item/weapon/melee/energy/sword/proc/toggleActive(mob/user, var/togglestate = "") //you can use togglestate to manually set the sword on or off + switch(togglestate) + if("on") + active = 1 + if("off") + active = 0 + else + active = !active + if (active) + force = 30 + w_class = 4 + sharpness = 1.5 + hitsound = "sound/weapons/blade1.ogg" + playsound(user, 'sound/weapons/saberon.ogg', 50, 1) + to_chat(user, " [src] is now active.") + else + force = 3 + w_class = 2 + sharpness = 0 + playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) + hitsound = "sound/weapons/empty.ogg" + to_chat(user, " [src] can now be concealed.") + update_icon() + +/obj/item/weapon/melee/energy/sword/update_icon() + if(active && _color) + icon_state = active_state + else + icon_state = "[base_state][active]" + +/obj/item/weapon/melee/energy/sword/attackby(obj/item/weapon/W, mob/living/user) + ..() + if(istype(W, /obj/item/weapon/melee/energy/sword)) + if(W == src) + to_chat(user, "You try to attach the end of the energy sword to... itself. You're not very smart, are you?") + if(ishuman(user)) + user.adjustBrainLoss(10) + else + to_chat(user, "You attach the ends of the two energy swords, making a single double-bladed weapon! You're cool.") + new /obj/item/weapon/dualsaber(user.loc) + qdel(W) + W = null + qdel(src) + +/obj/item/weapon/melee/energy/sword/pirate + name = "energy cutlass" + desc = "Arrrr matey." + icon_state = "cutlass0" + base_state = "cutlass" + +/obj/item/weapon/melee/energy/sword/pirate/New() + ..() + _color = null + update_icon() diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm index 3774640fa3d..cb94e23e867 100644 --- a/code/game/objects/items/weapons/melee/misc.dm +++ b/code/game/objects/items/weapons/melee/misc.dm @@ -1,18 +1,18 @@ -/obj/item/weapon/melee/chainofcommand - name = "chain of command" - desc = "A tool used by great men to placate the frothing masses." - icon_state = "chain" - item_state = "chain" - hitsound = "sound/weapons/whip.ogg" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - force = 10 - throwforce = 7 - w_class = 3 - origin_tech = "combat=4" - attack_verb = list("flogged", "whipped", "lashed", "disciplined") - - suicide_act(mob/user) +/obj/item/weapon/melee/chainofcommand + name = "chain of command" + desc = "A tool used by great men to placate the frothing masses." + icon_state = "chain" + item_state = "chain" + hitsound = "sound/weapons/whip.ogg" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + force = 10 + throwforce = 7 + w_class = 3 + origin_tech = "combat=4" + attack_verb = list("flogged", "whipped", "lashed", "disciplined") + + suicide_act(mob/user) to_chat(viewers(user), "[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.") return (OXYLOSS) \ No newline at end of file diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 5cc63e2fb47..9407a7be121 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -1,51 +1,51 @@ -/obj/item/weapon/mop - desc = "The world of janitalia wouldn't be complete without a mop." - name = "mop" - icon = 'icons/obj/janitor.dmi' - icon_state = "mop" - hitsound = "sound/weapons/whip.ogg" - force = 3.0 - throwforce = 10.0 - throw_speed = 5 - throw_range = 3 - w_class = 3.0 - flags = FPRINT - attack_verb = list("mopped", "bashed", "bludgeoned", "whacked", "slapped", "whipped") - -/obj/item/weapon/mop/New() - . = ..() - create_reagents(50) - -/obj/item/weapon/mop/proc/clean(turf/simulated/A as turf) - reagents.reaction(A,1,10) //Mops magically make chems ten times more efficient than usual, aka equivalent of 50 units of whatever you're using - A.clean_blood() - for(var/obj/effect/O in A) - if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay)) - qdel(O) - -/obj/effect/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/mop)) - return - ..() - -/obj/item/weapon/mop/afterattack(atom/A, mob/user as mob) - if(!user.Adjacent(A)) - return - if(A.mop_act(src, user)) - return - if(istype(A, /mob/living)) - if(!(reagents.total_volume < 1)) //Slap slap slap - A.visible_message("[user] covers [A] in the mop's contents") - reagents.reaction(A,1,10) //I hope you like my polyacid cleaner mix - reagents.clear_reagents() - - if(istype(A, /turf/simulated) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay) || istype(A, /obj/effect/rune)) - if(reagents.total_volume < 1) +/obj/item/weapon/mop + desc = "The world of janitalia wouldn't be complete without a mop." + name = "mop" + icon = 'icons/obj/janitor.dmi' + icon_state = "mop" + hitsound = "sound/weapons/whip.ogg" + force = 3.0 + throwforce = 10.0 + throw_speed = 5 + throw_range = 3 + w_class = 3.0 + flags = FPRINT + attack_verb = list("mopped", "bashed", "bludgeoned", "whacked", "slapped", "whipped") + +/obj/item/weapon/mop/New() + . = ..() + create_reagents(50) + +/obj/item/weapon/mop/proc/clean(turf/simulated/A as turf) + reagents.reaction(A,1,10) //Mops magically make chems ten times more efficient than usual, aka equivalent of 50 units of whatever you're using + A.clean_blood() + for(var/obj/effect/O in A) + if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay)) + qdel(O) + +/obj/effect/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/mop)) + return + ..() + +/obj/item/weapon/mop/afterattack(atom/A, mob/user as mob) + if(!user.Adjacent(A)) + return + if(A.mop_act(src, user)) + return + if(istype(A, /mob/living)) + if(!(reagents.total_volume < 1)) //Slap slap slap + A.visible_message("[user] covers [A] in the mop's contents") + reagents.reaction(A,1,10) //I hope you like my polyacid cleaner mix + reagents.clear_reagents() + + if(istype(A, /turf/simulated) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay) || istype(A, /obj/effect/rune)) + if(reagents.total_volume < 1) to_chat(user, "Your mop is dry!") - return - user.visible_message("[user] begins to clean \the [get_turf(A)].") - if(do_after(user,A, 30)) - if(A) - clean(get_turf(A)) - reagents.remove_any(1) //Might be a tad wonky with "special mop mixes", but fuck it + return + user.visible_message("[user] begins to clean \the [get_turf(A)].") + if(do_after(user,A, 30)) + if(A) + clean(get_turf(A)) + reagents.remove_any(1) //Might be a tad wonky with "special mop mixes", but fuck it to_chat(user, "You have finished mopping \the [get_turf(A)]!") diff --git a/code/game/objects/items/weapons/paint.dm b/code/game/objects/items/weapons/paint.dm index c54280d6dc0..b7229e092b6 100644 --- a/code/game/objects/items/weapons/paint.dm +++ b/code/game/objects/items/weapons/paint.dm @@ -1,240 +1,240 @@ -//NEVER USE THIS IT SUX -PETETHEGOAT - -var/global/list/cached_icons = list() - -/obj/item/weapon/reagent_containers/glass/paint - desc = "It's a paint bucket." - name = "paint bucket" - icon = 'icons/obj/items.dmi' - icon_state = "paint_neutral" - item_state = "paintcan" - starting_materials = list(MAT_IRON = 200) - w_type = RECYK_METAL - w_class = 3.0 - melt_temperature = MELTPOINT_STEEL - amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(10,20,30,50,70) - volume = 70 - flags = FPRINT | OPENCONTAINER - var/paint_type = "" - -/obj/item/weapon/reagent_containers/glass/paint/suicide_act(mob/user) +//NEVER USE THIS IT SUX -PETETHEGOAT + +var/global/list/cached_icons = list() + +/obj/item/weapon/reagent_containers/glass/paint + desc = "It's a paint bucket." + name = "paint bucket" + icon = 'icons/obj/items.dmi' + icon_state = "paint_neutral" + item_state = "paintcan" + starting_materials = list(MAT_IRON = 200) + w_type = RECYK_METAL + w_class = 3.0 + melt_temperature = MELTPOINT_STEEL + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(10,20,30,50,70) + volume = 70 + flags = FPRINT | OPENCONTAINER + var/paint_type = "" + +/obj/item/weapon/reagent_containers/glass/paint/suicide_act(mob/user) to_chat(viewers(user), "[user] is taking \his hand and eating the [src.name]! It looks like \he's trying to commit suicide!") - return (TOXLOSS|OXYLOSS) - -/obj/item/weapon/reagent_containers/glass/paint/mop_act(obj/item/weapon/mop/M, mob/user) - return 0 - -/obj/item/weapon/reagent_containers/glass/paint/afterattack(turf/simulated/target, mob/user , flag) - if(istype(target) && reagents.total_volume > 5) - for(var/mob/O in viewers(user)) - O.show_message("\The [target] has been splashed with something by [user]!", 1) - spawn(5) - reagents.reaction(target, TOUCH) - reagents.remove_any(5) - else - return ..() - -/obj/item/weapon/reagent_containers/glass/paint/New() - if(paint_type == "remover") - name = "paint remover bucket" - else if(paint_type && length(paint_type) > 0) - name = paint_type + " " + name - ..() - reagents.add_reagent("paint_[paint_type]", volume) - -/obj/item/weapon/reagent_containers/glass/paint/red - icon_state = "paint_red" - paint_type = "red" - -/obj/item/weapon/reagent_containers/glass/paint/green - icon_state = "paint_green" - paint_type = "green" - -/obj/item/weapon/reagent_containers/glass/paint/blue - icon_state = "paint_blue" - paint_type = "blue" - -/obj/item/weapon/reagent_containers/glass/paint/yellow - icon_state = "paint_yellow" - paint_type = "yellow" - -/obj/item/weapon/reagent_containers/glass/paint/violet - icon_state = "paint_violet" - paint_type = "violet" - -/obj/item/weapon/reagent_containers/glass/paint/black - icon_state = "paint_black" - paint_type = "black" - -/obj/item/weapon/reagent_containers/glass/paint/white - icon_state = "paint_white" - paint_type = "white" - -/obj/item/weapon/reagent_containers/glass/paint/remover - paint_type = "remover" -/* -/obj/item/weapon/paint - name = "Paint Can" - desc = "Used to recolor floors and walls. Can not be removed by the janitor." - icon = 'icons/obj/items.dmi' - icon_state = "paint_neutral" - color = "FFFFFF" - item_state = "paintcan" - w_class = 3.0 - -/obj/item/weapon/paint/red - name = "Red paint" - color = "FF0000" - icon_state = "paint_red" - -/obj/item/weapon/paint/green - name = "Green paint" - color = "00FF00" - icon_state = "paint_green" - -/obj/item/weapon/paint/blue - name = "Blue paint" - color = "0000FF" - icon_state = "paint_blue" - -/obj/item/weapon/paint/yellow - name = "Yellow paint" - color = "FFFF00" - icon_state = "paint_yellow" - -/obj/item/weapon/paint/violet - name = "Violet paint" - color = "FF00FF" - icon_state = "paint_violet" - -/obj/item/weapon/paint/black - name = "Black paint" - color = "333333" - icon_state = "paint_black" - -/obj/item/weapon/paint/white - name = "White paint" - color = "FFFFFF" - icon_state = "paint_white" - - -/obj/item/weapon/paint/anycolor - name = "Any color" - icon_state = "paint_neutral" - - attack_self(mob/user as mob) - var/t1 = input(user, "Please select a color:", "Locking Computer", null) in list( "red", "blue", "green", "yellow", "black", "white") - if ((user.get_active_hand() != src || user.stat || user.restrained())) - return - switch(t1) - if("red") - color = "FF0000" - if("blue") - color = "0000FF" - if("green") - color = "00FF00" - if("yellow") - color = "FFFF00" - if("violet") - color = "FF00FF" - if("white") - color = "FFFFFF" - if("black") - color = "333333" - icon_state = "paint_[t1]" - add_fingerprint(user) - return - - -/obj/item/weapon/paint/afterattack(turf/target, mob/user as mob) - if(!istype(target) || istype(target, /turf/space)) - return - var/ind = "[initial(target.icon)][color]" - if(!cached_icons[ind]) - var/icon/overlay = new/icon(initial(target.icon)) - overlay.Blend("#[color]",ICON_MULTIPLY) - overlay.SetIntensity(1.4) - target.icon = overlay - cached_icons[ind] = target.icon - else - target.icon = cached_icons[ind] - return - -/obj/item/weapon/paint/paint_remover - name = "Paint remover" - icon_state = "paint_neutral" - - afterattack(turf/target, mob/user as mob) - if(istype(target) && target.icon != initial(target.icon)) - target.icon = initial(target.icon) - return -*/ - -datum/reagent/paint - name = "Paint" - id = "paint_" - description = "Floor paint is used to color floor tiles." - reagent_state = 2 - color = "#808080" - - reaction_turf(var/turf/T, var/volume) - if(!istype(T) || istype(T, /turf/space)) - return - var/ind = "[initial(T.icon)][color]" - if(!cached_icons[ind]) - var/icon/overlay = new/icon(initial(T.icon)) - overlay.Blend(color,ICON_MULTIPLY) - overlay.SetIntensity(1.4) - T.icon = overlay - cached_icons[ind] = T.icon - else - T.icon = cached_icons[ind] - return - - red - name = "Red Paint" - id = "paint_red" - color = "#FF0000" - - green - name = "Green Paint" - color = "#00FF00" - id = "paint_green" - - blue - name = "Blue Paint" - color = "#0000FF" - id = "paint_blue" - - yellow - name = "Yellow Paint" - color = "#FFFF00" - id = "paint_yellow" - - violet - name = "Violet Paint" - color = "#FF00FF" - id = "paint_violet" - - black - name = "Black Paint" - color = "#333333" - id = "paint_black" - - white - name = "White Paint" - color = "#FFFFFF" - id = "paint_white" - -datum/reagent/paint_remover - name = "Paint Remover" - id = "paint_remover" - description = "Paint remover is used to remove floor paint from floor tiles." - reagent_state = 2 - color = "#808080" - - reaction_turf(var/turf/T, var/volume) - if(istype(T) && T.icon != initial(T.icon)) - T.icon = initial(T.icon) - return + return (TOXLOSS|OXYLOSS) + +/obj/item/weapon/reagent_containers/glass/paint/mop_act(obj/item/weapon/mop/M, mob/user) + return 0 + +/obj/item/weapon/reagent_containers/glass/paint/afterattack(turf/simulated/target, mob/user , flag) + if(istype(target) && reagents.total_volume > 5) + for(var/mob/O in viewers(user)) + O.show_message("\The [target] has been splashed with something by [user]!", 1) + spawn(5) + reagents.reaction(target, TOUCH) + reagents.remove_any(5) + else + return ..() + +/obj/item/weapon/reagent_containers/glass/paint/New() + if(paint_type == "remover") + name = "paint remover bucket" + else if(paint_type && length(paint_type) > 0) + name = paint_type + " " + name + ..() + reagents.add_reagent("paint_[paint_type]", volume) + +/obj/item/weapon/reagent_containers/glass/paint/red + icon_state = "paint_red" + paint_type = "red" + +/obj/item/weapon/reagent_containers/glass/paint/green + icon_state = "paint_green" + paint_type = "green" + +/obj/item/weapon/reagent_containers/glass/paint/blue + icon_state = "paint_blue" + paint_type = "blue" + +/obj/item/weapon/reagent_containers/glass/paint/yellow + icon_state = "paint_yellow" + paint_type = "yellow" + +/obj/item/weapon/reagent_containers/glass/paint/violet + icon_state = "paint_violet" + paint_type = "violet" + +/obj/item/weapon/reagent_containers/glass/paint/black + icon_state = "paint_black" + paint_type = "black" + +/obj/item/weapon/reagent_containers/glass/paint/white + icon_state = "paint_white" + paint_type = "white" + +/obj/item/weapon/reagent_containers/glass/paint/remover + paint_type = "remover" +/* +/obj/item/weapon/paint + name = "Paint Can" + desc = "Used to recolor floors and walls. Can not be removed by the janitor." + icon = 'icons/obj/items.dmi' + icon_state = "paint_neutral" + color = "FFFFFF" + item_state = "paintcan" + w_class = 3.0 + +/obj/item/weapon/paint/red + name = "Red paint" + color = "FF0000" + icon_state = "paint_red" + +/obj/item/weapon/paint/green + name = "Green paint" + color = "00FF00" + icon_state = "paint_green" + +/obj/item/weapon/paint/blue + name = "Blue paint" + color = "0000FF" + icon_state = "paint_blue" + +/obj/item/weapon/paint/yellow + name = "Yellow paint" + color = "FFFF00" + icon_state = "paint_yellow" + +/obj/item/weapon/paint/violet + name = "Violet paint" + color = "FF00FF" + icon_state = "paint_violet" + +/obj/item/weapon/paint/black + name = "Black paint" + color = "333333" + icon_state = "paint_black" + +/obj/item/weapon/paint/white + name = "White paint" + color = "FFFFFF" + icon_state = "paint_white" + + +/obj/item/weapon/paint/anycolor + name = "Any color" + icon_state = "paint_neutral" + + attack_self(mob/user as mob) + var/t1 = input(user, "Please select a color:", "Locking Computer", null) in list( "red", "blue", "green", "yellow", "black", "white") + if ((user.get_active_hand() != src || user.stat || user.restrained())) + return + switch(t1) + if("red") + color = "FF0000" + if("blue") + color = "0000FF" + if("green") + color = "00FF00" + if("yellow") + color = "FFFF00" + if("violet") + color = "FF00FF" + if("white") + color = "FFFFFF" + if("black") + color = "333333" + icon_state = "paint_[t1]" + add_fingerprint(user) + return + + +/obj/item/weapon/paint/afterattack(turf/target, mob/user as mob) + if(!istype(target) || istype(target, /turf/space)) + return + var/ind = "[initial(target.icon)][color]" + if(!cached_icons[ind]) + var/icon/overlay = new/icon(initial(target.icon)) + overlay.Blend("#[color]",ICON_MULTIPLY) + overlay.SetIntensity(1.4) + target.icon = overlay + cached_icons[ind] = target.icon + else + target.icon = cached_icons[ind] + return + +/obj/item/weapon/paint/paint_remover + name = "Paint remover" + icon_state = "paint_neutral" + + afterattack(turf/target, mob/user as mob) + if(istype(target) && target.icon != initial(target.icon)) + target.icon = initial(target.icon) + return +*/ + +datum/reagent/paint + name = "Paint" + id = "paint_" + description = "Floor paint is used to color floor tiles." + reagent_state = 2 + color = "#808080" + + reaction_turf(var/turf/T, var/volume) + if(!istype(T) || istype(T, /turf/space)) + return + var/ind = "[initial(T.icon)][color]" + if(!cached_icons[ind]) + var/icon/overlay = new/icon(initial(T.icon)) + overlay.Blend(color,ICON_MULTIPLY) + overlay.SetIntensity(1.4) + T.icon = overlay + cached_icons[ind] = T.icon + else + T.icon = cached_icons[ind] + return + + red + name = "Red Paint" + id = "paint_red" + color = "#FF0000" + + green + name = "Green Paint" + color = "#00FF00" + id = "paint_green" + + blue + name = "Blue Paint" + color = "#0000FF" + id = "paint_blue" + + yellow + name = "Yellow Paint" + color = "#FFFF00" + id = "paint_yellow" + + violet + name = "Violet Paint" + color = "#FF00FF" + id = "paint_violet" + + black + name = "Black Paint" + color = "#333333" + id = "paint_black" + + white + name = "White Paint" + color = "#FFFFFF" + id = "paint_white" + +datum/reagent/paint_remover + name = "Paint Remover" + id = "paint_remover" + description = "Paint remover is used to remove floor paint from floor tiles." + reagent_state = 2 + color = "#808080" + + reaction_turf(var/turf/T, var/volume) + if(istype(T) && T.icon != initial(T.icon)) + T.icon = initial(T.icon) + return diff --git a/code/game/objects/items/weapons/paiwire.dm b/code/game/objects/items/weapons/paiwire.dm index 2dc2e485f09..130f36259e2 100644 --- a/code/game/objects/items/weapons/paiwire.dm +++ b/code/game/objects/items/weapons/paiwire.dm @@ -1,11 +1,11 @@ -/obj/item/weapon/pai_cable/proc/plugin(obj/machinery/M as obj, mob/user as mob) - if(istype(M, /obj/machinery/door) || istype(M, /obj/machinery/camera)) - user.visible_message("[user] inserts [src] into a data port on [M].", "You insert [src] into a data port on [M].", "You hear the satisfying click of a wire jack fastening into place.") - if(user && user.get_active_hand() == src) - user.drop_item(src, M, force_drop = 1) - src.machine = M - else - user.visible_message("[user] dumbly fumbles to find a place on [M] to plug in [src].", "There aren't any ports on [M] that match the jack belonging to [src].") - -/obj/item/weapon/pai_cable/attack(obj/machinery/M as obj, mob/user as mob) +/obj/item/weapon/pai_cable/proc/plugin(obj/machinery/M as obj, mob/user as mob) + if(istype(M, /obj/machinery/door) || istype(M, /obj/machinery/camera)) + user.visible_message("[user] inserts [src] into a data port on [M].", "You insert [src] into a data port on [M].", "You hear the satisfying click of a wire jack fastening into place.") + if(user && user.get_active_hand() == src) + user.drop_item(src, M, force_drop = 1) + src.machine = M + else + user.visible_message("[user] dumbly fumbles to find a place on [M] to plug in [src].", "There aren't any ports on [M] that match the jack belonging to [src].") + +/obj/item/weapon/pai_cable/attack(obj/machinery/M as obj, mob/user as mob) src.plugin(M, user) \ No newline at end of file diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index fda18aafa20..931cc481789 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -1,129 +1,129 @@ -/obj/item/weapon/cell - name = "power cell" - desc = "A rechargeable electrochemical power cell." - icon = 'icons/obj/power.dmi' - icon_state = "cell" - item_state = "cell" - origin_tech = "powerstorage=1" - flags = FPRINT - force = 5.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - w_class = 3.0 - var/charge = 0 // note %age conveted to actual charge in New - var/maxcharge = 1000 - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 50) - w_type = RECYK_ELECTRONIC - melt_temperature = MELTPOINT_STEEL // Rugged - var/rigged = 0 // true if rigged to explode - var/minor_fault = 0 //If not 100% reliable, it will build up faults. - - suicide_act(mob/user) +/obj/item/weapon/cell + name = "power cell" + desc = "A rechargeable electrochemical power cell." + icon = 'icons/obj/power.dmi' + icon_state = "cell" + item_state = "cell" + origin_tech = "powerstorage=1" + flags = FPRINT + force = 5.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + w_class = 3.0 + var/charge = 0 // note %age conveted to actual charge in New + var/maxcharge = 1000 + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 50) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_STEEL // Rugged + var/rigged = 0 // true if rigged to explode + var/minor_fault = 0 //If not 100% reliable, it will build up faults. + + suicide_act(mob/user) to_chat(viewers(user), "[user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide.") - return (FIRELOSS) - -/obj/item/weapon/cell/crap - name = "\improper Nanotrasen brand rechargeable AA battery" - desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT - origin_tech = "powerstorage=0" - maxcharge = 500 - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 40) - -/obj/item/weapon/cell/crap/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/secborg - name = "\improper Security borg rechargeable D battery" - origin_tech = "powerstorage=0" - maxcharge = 600 //600 max charge / 100 charge per shot = six shots - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 40) - - -/obj/item/weapon/cell/secborg/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/miningborg - name = "\improper Mining borg rechargeable D battery" - origin_tech = "powerstorage=0" - maxcharge = 600 //600 max charge / 100 charge per shot = six shots - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 40) - - -/obj/item/weapon/cell/miningborg/empty/New() - ..() - charge = 0 - - -/obj/item/weapon/cell/high - name = "high-capacity power cell" - origin_tech = "powerstorage=2" - icon_state = "hcell" - maxcharge = 10000 - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 60) - -/obj/item/weapon/cell/high/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/super - name = "super-capacity power cell" - origin_tech = "powerstorage=5" - icon_state = "scell" - maxcharge = 20000 - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 70) -/obj/item/weapon/cell/super/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/hyper - name = "hyper-capacity power cell" - origin_tech = "powerstorage=6" - icon_state = "hpcell" - maxcharge = 30000 - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 80) - -/obj/item/weapon/cell/hyper/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/infinite - name = "infinite-capacity power cell!" - icon_state = "icell" - origin_tech = null - maxcharge = 30000 - starting_materials = list(MAT_IRON = 700, MAT_GLASS = 80) - use() - return 1 - -/obj/item/weapon/cell/potato - name = "potato battery" - desc = "A rechargeable starch based power cell." - origin_tech = "powerstorage=1" - icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' - icon_state = "potato_cell" //"potato_battery" - charge = 100 - maxcharge = 300 - starting_materials = null - w_type = RECYK_BIOLOGICAL - minor_fault = 1 - - -/obj/item/weapon/cell/slime - name = "charged slime core" - desc = "A yellow slime core infused with plasma, it crackles with power." - origin_tech = "powerstorage=2;biotech=4" - icon = 'icons/mob/slimes.dmi' //'icons/obj/harvest.dmi' - icon_state = "yellow slime extract" //"potato_battery" - maxcharge = 10000 - starting_materials = null - w_type = RECYK_BIOLOGICAL - - -/obj/item/weapon/cell/temperaturegun - name = "temperature gun cell" - desc = "A specially designed power cell for heating and cooling projectiles" - icon_state = "icell" + return (FIRELOSS) + +/obj/item/weapon/cell/crap + name = "\improper Nanotrasen brand rechargeable AA battery" + desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT + origin_tech = "powerstorage=0" + maxcharge = 500 + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 40) + +/obj/item/weapon/cell/crap/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/secborg + name = "\improper Security borg rechargeable D battery" + origin_tech = "powerstorage=0" + maxcharge = 600 //600 max charge / 100 charge per shot = six shots + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 40) + + +/obj/item/weapon/cell/secborg/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/miningborg + name = "\improper Mining borg rechargeable D battery" + origin_tech = "powerstorage=0" + maxcharge = 600 //600 max charge / 100 charge per shot = six shots + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 40) + + +/obj/item/weapon/cell/miningborg/empty/New() + ..() + charge = 0 + + +/obj/item/weapon/cell/high + name = "high-capacity power cell" + origin_tech = "powerstorage=2" + icon_state = "hcell" + maxcharge = 10000 + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 60) + +/obj/item/weapon/cell/high/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/super + name = "super-capacity power cell" + origin_tech = "powerstorage=5" + icon_state = "scell" + maxcharge = 20000 + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 70) +/obj/item/weapon/cell/super/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/hyper + name = "hyper-capacity power cell" + origin_tech = "powerstorage=6" + icon_state = "hpcell" + maxcharge = 30000 + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 80) + +/obj/item/weapon/cell/hyper/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/infinite + name = "infinite-capacity power cell!" + icon_state = "icell" + origin_tech = null + maxcharge = 30000 + starting_materials = list(MAT_IRON = 700, MAT_GLASS = 80) + use() + return 1 + +/obj/item/weapon/cell/potato + name = "potato battery" + desc = "A rechargeable starch based power cell." + origin_tech = "powerstorage=1" + icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' + icon_state = "potato_cell" //"potato_battery" + charge = 100 + maxcharge = 300 + starting_materials = null + w_type = RECYK_BIOLOGICAL + minor_fault = 1 + + +/obj/item/weapon/cell/slime + name = "charged slime core" + desc = "A yellow slime core infused with plasma, it crackles with power." + origin_tech = "powerstorage=2;biotech=4" + icon = 'icons/mob/slimes.dmi' //'icons/obj/harvest.dmi' + icon_state = "yellow slime extract" //"potato_battery" + maxcharge = 10000 + starting_materials = null + w_type = RECYK_BIOLOGICAL + + +/obj/item/weapon/cell/temperaturegun + name = "temperature gun cell" + desc = "A specially designed power cell for heating and cooling projectiles" + icon_state = "icell" maxcharge = 900 \ No newline at end of file diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm index 9b18a806e01..89d3dc7ddd1 100644 --- a/code/game/objects/items/weapons/scrolls.dm +++ b/code/game/objects/items/weapons/scrolls.dm @@ -1,99 +1,99 @@ -/obj/item/weapon/teleportation_scroll - name = "scroll of teleportation" - desc = "A scroll for moving around." - icon = 'icons/obj/wizard.dmi' - icon_state = "scroll" - var/uses = 4.0 - flags = FPRINT - w_class = 2.0 - item_state = "paper" - throw_speed = 4 - throw_range = 20 - origin_tech = "bluespace=4" - -/obj/item/weapon/teleportation_scroll/apprentice - name = "lesser scroll of teleportation" - uses = 1 - origin_tech = "bluespace=2" - - - -/obj/item/weapon/teleportation_scroll/attack_self(mob/user as mob) - user.set_machine(src) - var/dat = "Teleportation Scroll:
    " - dat += "Number of uses: [src.uses]
    " - dat += "
    " - dat += "Four uses, use them wisely:
    " - dat += "
    Teleport
    " - dat += "Kind regards,
    Wizards Federation

    P.S. Don't forget to bring your gear, you'll need it to cast most spells.
    " - user << browse(dat, "window=scroll") - onclose(user, "scroll") - return - -/obj/item/weapon/teleportation_scroll/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained() || src.loc != usr) - return - var/mob/living/carbon/human/H = usr - if (!( istype(H, /mob/living/carbon/human))) - return 1 - if ((usr == src.loc || (in_range(src, usr) && istype(src.loc, /turf)))) - usr.set_machine(src) - if (href_list["spell_teleport"]) - if (src.uses >= 1) - teleportscroll(H) - if(H) - attack_self(H) - return - -/obj/item/weapon/teleportation_scroll/proc/teleportscroll(var/mob/user) - - - var/A - - A = input(user, "Area to jump to", "BOOYEA", A) in teleportlocs - var/area/thearea = teleportlocs[A] - - if (!user || user.stat || user.restrained()) - return - if(!((user == loc || (in_range(src, user) && istype(src.loc, /turf))))) - return - - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(5, 0, user.loc) - smoke.attach(user) - smoke.start() - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(!T.density) - var/clear = 1 - for(var/obj/O in T) - if(O.density) - clear = 0 - break - if(clear) - L+=T - - if(!L.len) +/obj/item/weapon/teleportation_scroll + name = "scroll of teleportation" + desc = "A scroll for moving around." + icon = 'icons/obj/wizard.dmi' + icon_state = "scroll" + var/uses = 4.0 + flags = FPRINT + w_class = 2.0 + item_state = "paper" + throw_speed = 4 + throw_range = 20 + origin_tech = "bluespace=4" + +/obj/item/weapon/teleportation_scroll/apprentice + name = "lesser scroll of teleportation" + uses = 1 + origin_tech = "bluespace=2" + + + +/obj/item/weapon/teleportation_scroll/attack_self(mob/user as mob) + user.set_machine(src) + var/dat = "Teleportation Scroll:
    " + dat += "Number of uses: [src.uses]
    " + dat += "
    " + dat += "Four uses, use them wisely:
    " + dat += "Teleport
    " + dat += "Kind regards,
    Wizards Federation

    P.S. Don't forget to bring your gear, you'll need it to cast most spells.
    " + user << browse(dat, "window=scroll") + onclose(user, "scroll") + return + +/obj/item/weapon/teleportation_scroll/Topic(href, href_list) + ..() + if (usr.stat || usr.restrained() || src.loc != usr) + return + var/mob/living/carbon/human/H = usr + if (!( istype(H, /mob/living/carbon/human))) + return 1 + if ((usr == src.loc || (in_range(src, usr) && istype(src.loc, /turf)))) + usr.set_machine(src) + if (href_list["spell_teleport"]) + if (src.uses >= 1) + teleportscroll(H) + if(H) + attack_self(H) + return + +/obj/item/weapon/teleportation_scroll/proc/teleportscroll(var/mob/user) + + + var/A + + A = input(user, "Area to jump to", "BOOYEA", A) in teleportlocs + var/area/thearea = teleportlocs[A] + + if (!user || user.stat || user.restrained()) + return + if(!((user == loc || (in_range(src, user) && istype(src.loc, /turf))))) + return + + var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() + smoke.set_up(5, 0, user.loc) + smoke.attach(user) + smoke.start() + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + + if(!L.len) to_chat(user, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.") - return - - if(user && user.locked_to) - user.locked_to.unlock_atom(user) - - var/list/tempL = L - var/attempt = null - var/success = 0 - while(tempL.len) - attempt = pick(tempL) - success = user.Move(attempt) - if(!success) - tempL.Remove(attempt) - else - break - - if(!success) - user.loc = pick(L) - - smoke.start() + return + + if(user && user.locked_to) + user.locked_to.unlock_atom(user) + + var/list/tempL = L + var/attempt = null + var/success = 0 + while(tempL.len) + attempt = pick(tempL) + success = user.Move(attempt) + if(!success) + tempL.Remove(attempt) + else + break + + if(!success) + user.loc = pick(L) + + smoke.start() src.uses -= 1 \ No newline at end of file diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 3e4084ed9e3..e85ba72c768 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -1,174 +1,174 @@ -/obj/item/weapon/shield - name = "shield" - -/obj/item/weapon/shield/riot - name = "riot shield" - desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder." - icon = 'icons/obj/weapons.dmi' - icon_state = "riot" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - force = 5.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 4 - w_class = 4.0 - starting_materials = list(MAT_IRON = 1000, MAT_GLASS = 7500) - melt_temperature = MELTPOINT_GLASS - origin_tech = "materials=2" - attack_verb = list("shoved", "bashed") - var/cooldown = 0 //shield bash cooldown. based on world.time - - suicide_act(mob/user) +/obj/item/weapon/shield + name = "shield" + +/obj/item/weapon/shield/riot + name = "riot shield" + desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder." + icon = 'icons/obj/weapons.dmi' + icon_state = "riot" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + force = 5.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 4 + w_class = 4.0 + starting_materials = list(MAT_IRON = 1000, MAT_GLASS = 7500) + melt_temperature = MELTPOINT_GLASS + origin_tech = "materials=2" + attack_verb = list("shoved", "bashed") + var/cooldown = 0 //shield bash cooldown. based on world.time + + suicide_act(mob/user) to_chat(viewers(user), "[user] is smashing \his face into the [src.name]! It looks like \he's trying to commit suicide!") - return (BRUTELOSS) - - IsShield() - return 1 - - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/melee/baton)) - if(cooldown < world.time - 25) - user.visible_message("[user] bashes [src] with [W]!") - playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - cooldown = world.time - else - ..() - -/obj/item/weapon/shield/riot/roman - name = "roman shield" - desc = "Bears an inscription on the inside: \"Romanes venio domus\"." - icon_state = "roman_shield" - - IsShield() - return 1 - - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/spear)) - if(cooldown < world.time - 25) - user.visible_message("[user] bashes [src] with [W]!") - playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - cooldown = world.time - else - ..() - - - -/obj/item/weapon/shield/energy - name = "energy combat shield" - desc = "A shield capable of stopping most projectile and melee attacks. It can be retracted, expanded, and stored anywhere." - icon = 'icons/obj/weapons.dmi' - icon_state = "eshield0" // eshield1 for expanded - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shields.dmi', "right_hand" = 'icons/mob/in-hand/right/shields.dmi') - flags = FPRINT - siemens_coefficient = 1 - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 4 - w_class = 1 - origin_tech = "materials=4;magnets=3;syndicate=4" - attack_verb = list("shoved", "bashed") - var/active = 0 - -/obj/item/weapon/shield/energy/suicide_act(mob/user) + return (BRUTELOSS) + + IsShield() + return 1 + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/melee/baton)) + if(cooldown < world.time - 25) + user.visible_message("[user] bashes [src] with [W]!") + playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) + cooldown = world.time + else + ..() + +/obj/item/weapon/shield/riot/roman + name = "roman shield" + desc = "Bears an inscription on the inside: \"Romanes venio domus\"." + icon_state = "roman_shield" + + IsShield() + return 1 + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/spear)) + if(cooldown < world.time - 25) + user.visible_message("[user] bashes [src] with [W]!") + playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) + cooldown = world.time + else + ..() + + + +/obj/item/weapon/shield/energy + name = "energy combat shield" + desc = "A shield capable of stopping most projectile and melee attacks. It can be retracted, expanded, and stored anywhere." + icon = 'icons/obj/weapons.dmi' + icon_state = "eshield0" // eshield1 for expanded + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shields.dmi', "right_hand" = 'icons/mob/in-hand/right/shields.dmi') + flags = FPRINT + siemens_coefficient = 1 + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 4 + w_class = 1 + origin_tech = "materials=4;magnets=3;syndicate=4" + attack_verb = list("shoved", "bashed") + var/active = 0 + +/obj/item/weapon/shield/energy/suicide_act(mob/user) to_chat(viewers(user), "[user] is putting the [src.name] to their head and activating it! It looks like \he's trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/weapon/shield/energy/IsShield() - if(active) - return 1 - else - return 0 - -/obj/item/weapon/shield/energy/attack_self(mob/living/user as mob) - if ((M_CLUMSY in user.mutations) && prob(50)) + return (BRUTELOSS) + +/obj/item/weapon/shield/energy/IsShield() + if(active) + return 1 + else + return 0 + +/obj/item/weapon/shield/energy/attack_self(mob/living/user as mob) + if ((M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "You beat yourself in the head with [src].") - user.take_organ_damage(5) - active = !active - if (active) - force = 10 - w_class = 4 - playsound(user, 'sound/weapons/saberon.ogg', 50, 1) + user.take_organ_damage(5) + active = !active + if (active) + force = 10 + w_class = 4 + playsound(user, 'sound/weapons/saberon.ogg', 50, 1) to_chat(user, "[src] is now active.") - else - force = 3 - w_class = 1 - playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) + else + force = 3 + w_class = 1 + playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) to_chat(user, "[src] can now be concealed.") - icon_state = "eshield[active]" - item_state = "eshield[active]" - user.regenerate_icons() - add_fingerprint(user) - return - - -/obj/item/weapon/cloaking_device - name = "cloaking device" - desc = "Use this to become invisible to the human eyesocket." - icon = 'icons/obj/device.dmi' - icon_state = "shield0" - var/active = 0.0 - flags = FPRINT - siemens_coefficient = 1 - item_state = "electronic" - throwforce = 10.0 - throw_speed = 2 - throw_range = 10 - w_class = 2.0 - origin_tech = "magnets=3;syndicate=4" - - -/obj/item/weapon/cloaking_device/attack_self(mob/user as mob) - src.active = !( src.active ) - if (src.active) + icon_state = "eshield[active]" + item_state = "eshield[active]" + user.regenerate_icons() + add_fingerprint(user) + return + + +/obj/item/weapon/cloaking_device + name = "cloaking device" + desc = "Use this to become invisible to the human eyesocket." + icon = 'icons/obj/device.dmi' + icon_state = "shield0" + var/active = 0.0 + flags = FPRINT + siemens_coefficient = 1 + item_state = "electronic" + throwforce = 10.0 + throw_speed = 2 + throw_range = 10 + w_class = 2.0 + origin_tech = "magnets=3;syndicate=4" + + +/obj/item/weapon/cloaking_device/attack_self(mob/user as mob) + src.active = !( src.active ) + if (src.active) to_chat(user, "The cloaking device is now active.") - src.icon_state = "shield1" - else + src.icon_state = "shield1" + else to_chat(user, "The cloaking device is now inactive.") - src.icon_state = "shield0" - src.add_fingerprint(user) - return - -/obj/item/weapon/cloaking_device/emp_act(severity) - active = 0 - icon_state = "shield0" - if(ismob(loc)) - loc:update_icons() - ..() - -/obj/item/weapon/shield/riot/proto - name = "Prototype Shield" - desc = "Doubles as a sled!" - icon_state = "protoshield" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shields.dmi', "right_hand" = 'icons/mob/in-hand/right/shields.dmi') - IsShield() - return 1 - - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/spear)) - if(cooldown < world.time - 25) - user.visible_message("[user] bashes [src] with [W]!") - playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - cooldown = world.time - else - ..() - - -/obj/item/weapon/shield/riot/joe - name = "Sniper Shield" - desc = "Very useful for close-quarters sniping, regardless of how stupid that idea is." - icon_state = "joeshield" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shields.dmi', "right_hand" = 'icons/mob/in-hand/right/shields.dmi') - IsShield() - return 1 - - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/spear)) - if(cooldown < world.time - 25) - user.visible_message("[user] bashes [src] with [W]!") - playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - cooldown = world.time - else + src.icon_state = "shield0" + src.add_fingerprint(user) + return + +/obj/item/weapon/cloaking_device/emp_act(severity) + active = 0 + icon_state = "shield0" + if(ismob(loc)) + loc:update_icons() + ..() + +/obj/item/weapon/shield/riot/proto + name = "Prototype Shield" + desc = "Doubles as a sled!" + icon_state = "protoshield" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shields.dmi', "right_hand" = 'icons/mob/in-hand/right/shields.dmi') + IsShield() + return 1 + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/spear)) + if(cooldown < world.time - 25) + user.visible_message("[user] bashes [src] with [W]!") + playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) + cooldown = world.time + else + ..() + + +/obj/item/weapon/shield/riot/joe + name = "Sniper Shield" + desc = "Very useful for close-quarters sniping, regardless of how stupid that idea is." + icon_state = "joeshield" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shields.dmi', "right_hand" = 'icons/mob/in-hand/right/shields.dmi') + IsShield() + return 1 + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/spear)) + if(cooldown < world.time - 25) + user.visible_message("[user] bashes [src] with [W]!") + playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) + cooldown = world.time + else ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 7e4a9cd6770..ba2a66d43a7 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -1,224 +1,224 @@ - -/* - * Backpack - */ - -/obj/item/weapon/storage/backpack - name = "backpack" - desc = "You wear this on your back and put items into it." - icon_state = "backpack" - item_state = "backpack" - w_class = 4.0 - flags = FPRINT - slot_flags = SLOT_BACK //ERROOOOO - max_w_class = 3 - max_combined_w_class = 21 - -/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob) - playsound(get_turf(src), "rustle", 50, 1, -5) - . = ..() - -/* - * Backpack Types - */ - - - - -/obj/item/weapon/storage/backpack/holding - name = "Bag of Holding" - desc = "A backpack that opens into a localized pocket of Blue Space." - origin_tech = "bluespace=4" - item_state = "holdingpack" - icon_state = "holdingpack" - max_w_class = 4 - max_combined_w_class = 28 - -/obj/item/weapon/storage/backpack/holding/suicide_act(mob/user) - to_chat(viewers(user), "[user] puts the [src.name] on \his head and stretches the bag around \himself. With a sudden snapping sound, the bag shrinks to it's original size, leaving no trace of [user] ") - loc = get_turf(user) - qdel(user) - -/obj/item/weapon/storage/backpack/holding/New() - ..() - return - -/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(W == src) - return // HOLY FUCKING SHIT WHY STORAGE CODE, WHY - pomf - if(crit_fail) - to_chat(user, "The Bluespace generator isn't working.") - return - //BoH+BoH=Singularity, WAS commented out - if(istype(W, /obj/item/weapon/storage/backpack/holding) && !W.crit_fail) - investigation_log(I_SINGULO,"has become a singularity. Caused by [user.key]") - message_admins("[src] has become a singularity. Caused by [user.key]") - to_chat(user, "The Bluespace interfaces of the two devices catastrophically malfunction!") - qdel(W) - W = null - new /obj/machinery/singularity (get_turf(src)) - message_admins("[key_name_admin(user)] detonated a bag of holding") - log_game("[key_name(user)] detonated a bag of holding") - to_chat(user, "FUCK") - user.throw_at(get_turf(src), 10, 5) - qdel(src) - return - . = ..() - -/obj/item/weapon/storage/backpack/holding/proc/failcheck(mob/user as mob) - if (prob(src.reliability)) return 1 //No failure - if (prob(src.reliability)) - to_chat(user, "The Bluespace portal resists your attempt to add another item.")//light failure - - else - to_chat(user, "The Bluespace generator malfunctions!") - for (var/obj/O in src.contents) //it broke, delete what was in it - qdel(O) - crit_fail = 1 - icon_state = "brokenpack" - -/obj/item/weapon/storage/backpack/holding/singularity_act(var/current_size,var/obj/machinery/singularity/S) - var/dist = max(current_size, 1) - empulse(S.loc,(dist*2),(dist*4)) - if(S.current_size <= 3) - investigation_log(I_SINGULO, "has been destroyed by a bag of holding.") - qdel(S) - else - investigation_log(I_SINGULO, "has been weakened by a bag of holding.") - S.energy -= (S.energy/3)*2 - S.check_energy() - qdel(src) - return - - -/obj/item/weapon/storage/backpack/santabag - name = "Santa's Gift Bag" - desc = "Space Santa uses this to deliver toys to all the nice children in space in Christmas! Wow, it's pretty big!" - icon_state = "giftbag0" - item_state = "giftbag" - w_class = 4.0 - storage_slots = 7 - max_w_class = 4 - max_combined_w_class = 400 // can store a ton of shit! - -/obj/item/weapon/storage/backpack/santabag/attack_hand(user) - if(contents.len < storage_slots) - var/empty_slots = Clamp((storage_slots - contents.len),0,storage_slots) - to_chat(user,"You look into the bag, and find it filled with [empty_slots] new presents!") - for(var/i = 1,i <= empty_slots,i++) - var/gift = pick(/obj/item/weapon/winter_gift/cloth,/obj/item/weapon/winter_gift/regular,/obj/item/weapon/winter_gift/food) - if(prob(1)) - gift = /obj/item/weapon/winter_gift/special - new gift(src) - . = ..() - -/obj/item/weapon/storage/backpack/cultpack - name = "trophy rack" - desc = "It's useful for both carrying extra gear and proudly declaring your insanity." - icon_state = "cultpack" - item_state = "cultpacknew" - -/obj/item/weapon/storage/backpack/cultify() - new /obj/item/weapon/storage/backpack/cultpack(loc) - ..() - -/obj/item/weapon/storage/backpack/cultpack/cultify() - return - -/obj/item/weapon/storage/backpack/clown - name = "Giggles Von Honkerton" - desc = "It's a backpack made by Honk! Co." - icon_state = "clownpack" - item_state = "clownpack" - -/obj/item/weapon/storage/backpack/medic - name = "medical backpack" - desc = "It's a backpack especially designed for use in a sterile environment." - icon_state = "medicalpack" - item_state = "medicalpack" - -/obj/item/weapon/storage/backpack/security - name = "security backpack" - desc = "It's a very robust backpack." - icon_state = "securitypack" - item_state = "securitypack" - -/obj/item/weapon/storage/backpack/captain - name = "captain's backpack" - desc = "It's a special backpack made exclusively for Nanotrasen officers." - icon_state = "captainpack" - item_state = "captainpack" - -/obj/item/weapon/storage/backpack/industrial - name = "industrial backpack" - desc = "It's a tough backpack for the daily grind of station life." - icon_state = "engiepack" - item_state = "engiepack" - -/* - * Satchel Types - */ - -/obj/item/weapon/storage/backpack/satchel - name = "leather satchel" - desc = "It's a very fancy satchel made with fine leather." - icon_state = "satchel" - -/obj/item/weapon/storage/backpack/satchel/withwallet - New() - ..() - new /obj/item/weapon/storage/wallet/random( src ) - -/obj/item/weapon/storage/backpack/satchel_norm - name = "satchel" - desc = "A trendy looking satchel." - icon_state = "satchel-norm" - -/obj/item/weapon/storage/backpack/satchel_eng - name = "industrial satchel" - desc = "A tough satchel with extra pockets." - icon_state = "satchel-eng" - item_state = "engiepack" - -/obj/item/weapon/storage/backpack/satchel_med - name = "medical satchel" - desc = "A sterile satchel used in medical departments." - icon_state = "satchel-med" - item_state = "medicalpack" - -/obj/item/weapon/storage/backpack/satchel_vir - name = "virologist satchel" - desc = "A sterile satchel with virologist colours." - icon_state = "satchel-vir" - -/obj/item/weapon/storage/backpack/satchel_chem - name = "chemist satchel" - desc = "A sterile satchel with chemist colours." - icon_state = "satchel-chem" - -/obj/item/weapon/storage/backpack/satchel_gen - name = "geneticist satchel" - desc = "A sterile satchel with geneticist colours." - icon_state = "satchel-gen" - -/obj/item/weapon/storage/backpack/satchel_tox - name = "scientist satchel" - desc = "Useful for holding research materials." - icon_state = "satchel-tox" - -/obj/item/weapon/storage/backpack/satchel_sec - name = "security satchel" - desc = "A robust satchel for security related needs." - icon_state = "satchel-sec" - item_state = "securitypack" - -/obj/item/weapon/storage/backpack/satchel_hyd - name = "hydroponics satchel" - desc = "A green satchel for plant related work." - icon_state = "satchel_hyd" - -/obj/item/weapon/storage/backpack/satchel_cap - name = "captain's satchel" - desc = "An exclusive satchel for Nanotrasen officers." - icon_state = "satchel-cap" - item_state = "captainpack" + +/* + * Backpack + */ + +/obj/item/weapon/storage/backpack + name = "backpack" + desc = "You wear this on your back and put items into it." + icon_state = "backpack" + item_state = "backpack" + w_class = 4.0 + flags = FPRINT + slot_flags = SLOT_BACK //ERROOOOO + max_w_class = 3 + max_combined_w_class = 21 + +/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob) + playsound(get_turf(src), "rustle", 50, 1, -5) + . = ..() + +/* + * Backpack Types + */ + + + + +/obj/item/weapon/storage/backpack/holding + name = "Bag of Holding" + desc = "A backpack that opens into a localized pocket of Blue Space." + origin_tech = "bluespace=4" + item_state = "holdingpack" + icon_state = "holdingpack" + max_w_class = 4 + max_combined_w_class = 28 + +/obj/item/weapon/storage/backpack/holding/suicide_act(mob/user) + to_chat(viewers(user), "[user] puts the [src.name] on \his head and stretches the bag around \himself. With a sudden snapping sound, the bag shrinks to it's original size, leaving no trace of [user] ") + loc = get_turf(user) + qdel(user) + +/obj/item/weapon/storage/backpack/holding/New() + ..() + return + +/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(W == src) + return // HOLY FUCKING SHIT WHY STORAGE CODE, WHY - pomf + if(crit_fail) + to_chat(user, "The Bluespace generator isn't working.") + return + //BoH+BoH=Singularity, WAS commented out + if(istype(W, /obj/item/weapon/storage/backpack/holding) && !W.crit_fail) + investigation_log(I_SINGULO,"has become a singularity. Caused by [user.key]") + message_admins("[src] has become a singularity. Caused by [user.key]") + to_chat(user, "The Bluespace interfaces of the two devices catastrophically malfunction!") + qdel(W) + W = null + new /obj/machinery/singularity (get_turf(src)) + message_admins("[key_name_admin(user)] detonated a bag of holding") + log_game("[key_name(user)] detonated a bag of holding") + to_chat(user, "FUCK") + user.throw_at(get_turf(src), 10, 5) + qdel(src) + return + . = ..() + +/obj/item/weapon/storage/backpack/holding/proc/failcheck(mob/user as mob) + if (prob(src.reliability)) return 1 //No failure + if (prob(src.reliability)) + to_chat(user, "The Bluespace portal resists your attempt to add another item.")//light failure + + else + to_chat(user, "The Bluespace generator malfunctions!") + for (var/obj/O in src.contents) //it broke, delete what was in it + qdel(O) + crit_fail = 1 + icon_state = "brokenpack" + +/obj/item/weapon/storage/backpack/holding/singularity_act(var/current_size,var/obj/machinery/singularity/S) + var/dist = max(current_size, 1) + empulse(S.loc,(dist*2),(dist*4)) + if(S.current_size <= 3) + investigation_log(I_SINGULO, "has been destroyed by a bag of holding.") + qdel(S) + else + investigation_log(I_SINGULO, "has been weakened by a bag of holding.") + S.energy -= (S.energy/3)*2 + S.check_energy() + qdel(src) + return + + +/obj/item/weapon/storage/backpack/santabag + name = "Santa's Gift Bag" + desc = "Space Santa uses this to deliver toys to all the nice children in space in Christmas! Wow, it's pretty big!" + icon_state = "giftbag0" + item_state = "giftbag" + w_class = 4.0 + storage_slots = 7 + max_w_class = 4 + max_combined_w_class = 400 // can store a ton of shit! + +/obj/item/weapon/storage/backpack/santabag/attack_hand(user) + if(contents.len < storage_slots) + var/empty_slots = Clamp((storage_slots - contents.len),0,storage_slots) + to_chat(user,"You look into the bag, and find it filled with [empty_slots] new presents!") + for(var/i = 1,i <= empty_slots,i++) + var/gift = pick(/obj/item/weapon/winter_gift/cloth,/obj/item/weapon/winter_gift/regular,/obj/item/weapon/winter_gift/food) + if(prob(1)) + gift = /obj/item/weapon/winter_gift/special + new gift(src) + . = ..() + +/obj/item/weapon/storage/backpack/cultpack + name = "trophy rack" + desc = "It's useful for both carrying extra gear and proudly declaring your insanity." + icon_state = "cultpack" + item_state = "cultpacknew" + +/obj/item/weapon/storage/backpack/cultify() + new /obj/item/weapon/storage/backpack/cultpack(loc) + ..() + +/obj/item/weapon/storage/backpack/cultpack/cultify() + return + +/obj/item/weapon/storage/backpack/clown + name = "Giggles Von Honkerton" + desc = "It's a backpack made by Honk! Co." + icon_state = "clownpack" + item_state = "clownpack" + +/obj/item/weapon/storage/backpack/medic + name = "medical backpack" + desc = "It's a backpack especially designed for use in a sterile environment." + icon_state = "medicalpack" + item_state = "medicalpack" + +/obj/item/weapon/storage/backpack/security + name = "security backpack" + desc = "It's a very robust backpack." + icon_state = "securitypack" + item_state = "securitypack" + +/obj/item/weapon/storage/backpack/captain + name = "captain's backpack" + desc = "It's a special backpack made exclusively for Nanotrasen officers." + icon_state = "captainpack" + item_state = "captainpack" + +/obj/item/weapon/storage/backpack/industrial + name = "industrial backpack" + desc = "It's a tough backpack for the daily grind of station life." + icon_state = "engiepack" + item_state = "engiepack" + +/* + * Satchel Types + */ + +/obj/item/weapon/storage/backpack/satchel + name = "leather satchel" + desc = "It's a very fancy satchel made with fine leather." + icon_state = "satchel" + +/obj/item/weapon/storage/backpack/satchel/withwallet + New() + ..() + new /obj/item/weapon/storage/wallet/random( src ) + +/obj/item/weapon/storage/backpack/satchel_norm + name = "satchel" + desc = "A trendy looking satchel." + icon_state = "satchel-norm" + +/obj/item/weapon/storage/backpack/satchel_eng + name = "industrial satchel" + desc = "A tough satchel with extra pockets." + icon_state = "satchel-eng" + item_state = "engiepack" + +/obj/item/weapon/storage/backpack/satchel_med + name = "medical satchel" + desc = "A sterile satchel used in medical departments." + icon_state = "satchel-med" + item_state = "medicalpack" + +/obj/item/weapon/storage/backpack/satchel_vir + name = "virologist satchel" + desc = "A sterile satchel with virologist colours." + icon_state = "satchel-vir" + +/obj/item/weapon/storage/backpack/satchel_chem + name = "chemist satchel" + desc = "A sterile satchel with chemist colours." + icon_state = "satchel-chem" + +/obj/item/weapon/storage/backpack/satchel_gen + name = "geneticist satchel" + desc = "A sterile satchel with geneticist colours." + icon_state = "satchel-gen" + +/obj/item/weapon/storage/backpack/satchel_tox + name = "scientist satchel" + desc = "Useful for holding research materials." + icon_state = "satchel-tox" + +/obj/item/weapon/storage/backpack/satchel_sec + name = "security satchel" + desc = "A robust satchel for security related needs." + icon_state = "satchel-sec" + item_state = "securitypack" + +/obj/item/weapon/storage/backpack/satchel_hyd + name = "hydroponics satchel" + desc = "A green satchel for plant related work." + icon_state = "satchel_hyd" + +/obj/item/weapon/storage/backpack/satchel_cap + name = "captain's satchel" + desc = "An exclusive satchel for Nanotrasen officers." + icon_state = "satchel-cap" + item_state = "captainpack" diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index f8ef5f4a016..00d4ead4508 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -1,348 +1,348 @@ -/* - * These absorb the functionality of the plant bag, ore satchel, etc. - * They use the use_to_pickup, quick_gather, and quick_empty functions - * that were already defined in weapon/storage, but which had been - * re-implemented in other classes. - * - * Contains: - * Trash Bag - * Mining Satchel - * Plant Bag - * Sheet Snatcher - * - * -Sayu - */ - -// Generic non-item -/obj/item/weapon/storage/bag - allow_quick_gather = 1 - allow_quick_empty = 1 - display_contents_with_number = 0 // UNStABLE AS FuCK, turn on when it stops crashing clients - use_to_pickup = 1 - slot_flags = SLOT_BELT - flags = FPRINT - - -// ----------------------------- -// Trash bag -// ----------------------------- -/obj/item/weapon/storage/bag/trash - name = "trash bag" - desc = "It's the heavy-duty black polymer kind. Time to take out the trash!" - icon = 'icons/obj/trash.dmi' - icon_state = "trashbag0" - item_state = "trashbag" - - w_class = 4 - max_w_class = 2 - storage_slots = 21 - can_hold = list() // any - cant_hold = list("/obj/item/weapon/disk/nuclear") - -/obj/item/weapon/storage/bag/trash/update_icon() - if(contents.len == 0) - icon_state = "trashbag0" - else if(contents.len < 12) - icon_state = "trashbag1" - else if(contents.len < 21) - icon_state = "trashbag2" - else icon_state = "trashbag3" - - -// ----------------------------- -// Plastic Bag -// ----------------------------- - -/obj/item/weapon/storage/bag/plasticbag - name = "plastic bag" - desc = "It's a very flimsy, very noisy alternative to a bag." - icon = 'icons/obj/trash.dmi' - icon_state = "plasticbag" - item_state = "plasticbag" - - w_class = 4 - max_w_class = 2 - storage_slots = 21 - can_hold = list() // any - cant_hold = list("/obj/item/weapon/disk/nuclear") - - slot_flags = SLOT_BELT | SLOT_HEAD - flags = FPRINT | BLOCK_BREATHING | BLOCK_GAS_SMOKE_EFFECT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR - -/obj/item/weapon/storage/bag/plasticbag/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0) - //Forbid wearing bags with something inside! - .=..() - if(contents.len && (slot == slot_head)) - return 0 - -/obj/item/weapon/storage/bag/plasticbag/can_be_inserted() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - if(H.head == src) //If worn - return 0 - return ..() - -/obj/item/weapon/storage/bag/plasticbag/suicide_act(mob/user) - user.visible_message("[user] puts the [src.name] over \his head and tightens the handles around \his neck! It looks like \he's trying to commit suicide.") - return(OXYLOSS) - -// ----------------------------- -// Mining Satchel -// ----------------------------- - -/obj/item/weapon/storage/bag/ore - name = "\improper Mining Satchel" //need the improper for the - desc = "This little bugger can be used to store and transport ores." - icon = 'icons/obj/mining.dmi' - icon_state = "satchel" - slot_flags = SLOT_BELT | SLOT_POCKET - w_class = 3 - storage_slots = 50 - max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class - max_w_class = 3 - can_hold = list("/obj/item/weapon/ore") - - -// ----------------------------- -// Plant bag -// ----------------------------- - -/obj/item/weapon/storage/bag/plants - icon = 'icons/obj/hydroponics.dmi' - icon_state = "plantbag" - name = "Plant Bag" - 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 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown", "/obj/item/weapon/reagent_containers/food/snacks/meat", "/obj/item/weapon/reagent_containers/food/snacks/egg", "/obj/item/weapon/reagent_containers/food/snacks/honeycomb") - -// ----------------------------- -// Food bag -// ----------------------------- - -/obj/item/weapon/storage/bag/food - icon = 'icons/obj/kitchen.dmi' - icon_state = "foodbag0" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/backpacks_n_bags.dmi', "right_hand" = 'icons/mob/in-hand/right/backpacks_n_bags.dmi') - name = "Food Delivery Bag" - storage_slots = 14; //the number of food items it can carry. - max_combined_w_class = 28 //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 = 3 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks") - -/obj/item/weapon/storage/bag/food/update_icon() - if(contents.len < 1) - icon_state = "foodbag0" - else icon_state = "foodbag1" - -/obj/item/weapon/storage/bag/food/menu1/New() - ..() - new/obj/item/weapon/reagent_containers/food/snacks/monkeyburger(src)//6 nutriments - new/obj/item/weapon/reagent_containers/food/snacks/fries(src)//4 nutriments - new/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola(src)//-3 drowsy - update_icon() - -/obj/item/weapon/storage/bag/food/menu2/New() - ..() - new/obj/item/weapon/reagent_containers/food/snacks/bigbiteburger(src)//14 nutriments - new/obj/item/weapon/reagent_containers/food/snacks/cheesyfries(src)//6 nutriments - new/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind(src)//-7 drowsy, -1 sleepy - update_icon() - -// ----------------------------- -// Borg Food bag -// ----------------------------- - -/obj/item/weapon/storage/bag/food/borg - name = "Food Transport Bag" - desc = "Useful for manipulating food items in the kitchen." - -// ----------------------------- -// Pill Collector -// ----------------------------- - -/obj/item/weapon/storage/bag/chem - icon = 'icons/obj/chemical.dmi' - icon_state = "pcollector" - name = "Pill Collector" - item_state = "pcollector" - origin_tech = "biotech=2;materials=1" - 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 - can_hold = list("/obj/item/weapon/reagent_containers/glass/bottle","/obj/item/weapon/reagent_containers/pill","/obj/item/weapon/reagent_containers/syringe") - -// ----------------------------- -// Sheet Snatcher -// ----------------------------- -// Because it stacks stacks, this doesn't operate normally. -// However, making it a storage/bag allows us to reuse existing code in some places. -Sayu - -/obj/item/weapon/storage/bag/sheetsnatcher - icon = 'icons/obj/mining.dmi' - icon_state = "sheetsnatcher" - name = "Sheet Snatcher" - desc = "A patented Nanotrasen storage system designed for any kind of mineral sheet." - - var/capacity = 300; //the number of sheets it can carry. - w_class = 3 - - allow_quick_empty = 1 // this function is superceded - New() - ..() - //verbs -= /obj/item/weapon/storage/verb/quick_empty - //verbs += /obj/item/weapon/storage/bag/sheetsnatcher/quick_empty - - can_be_inserted(obj/item/W as obj, stop_messages = 0) - if(!istype(W,/obj/item/stack/sheet) || istype(W,/obj/item/stack/sheet/mineral/sandstone) || istype(W,/obj/item/stack/sheet/wood)) - if(!stop_messages) +/* + * These absorb the functionality of the plant bag, ore satchel, etc. + * They use the use_to_pickup, quick_gather, and quick_empty functions + * that were already defined in weapon/storage, but which had been + * re-implemented in other classes. + * + * Contains: + * Trash Bag + * Mining Satchel + * Plant Bag + * Sheet Snatcher + * + * -Sayu + */ + +// Generic non-item +/obj/item/weapon/storage/bag + allow_quick_gather = 1 + allow_quick_empty = 1 + display_contents_with_number = 0 // UNStABLE AS FuCK, turn on when it stops crashing clients + use_to_pickup = 1 + slot_flags = SLOT_BELT + flags = FPRINT + + +// ----------------------------- +// Trash bag +// ----------------------------- +/obj/item/weapon/storage/bag/trash + name = "trash bag" + desc = "It's the heavy-duty black polymer kind. Time to take out the trash!" + icon = 'icons/obj/trash.dmi' + icon_state = "trashbag0" + item_state = "trashbag" + + w_class = 4 + max_w_class = 2 + storage_slots = 21 + can_hold = list() // any + cant_hold = list("/obj/item/weapon/disk/nuclear") + +/obj/item/weapon/storage/bag/trash/update_icon() + if(contents.len == 0) + icon_state = "trashbag0" + else if(contents.len < 12) + icon_state = "trashbag1" + else if(contents.len < 21) + icon_state = "trashbag2" + else icon_state = "trashbag3" + + +// ----------------------------- +// Plastic Bag +// ----------------------------- + +/obj/item/weapon/storage/bag/plasticbag + name = "plastic bag" + desc = "It's a very flimsy, very noisy alternative to a bag." + icon = 'icons/obj/trash.dmi' + icon_state = "plasticbag" + item_state = "plasticbag" + + w_class = 4 + max_w_class = 2 + storage_slots = 21 + can_hold = list() // any + cant_hold = list("/obj/item/weapon/disk/nuclear") + + slot_flags = SLOT_BELT | SLOT_HEAD + flags = FPRINT | BLOCK_BREATHING | BLOCK_GAS_SMOKE_EFFECT + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR + +/obj/item/weapon/storage/bag/plasticbag/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0) + //Forbid wearing bags with something inside! + .=..() + if(contents.len && (slot == slot_head)) + return 0 + +/obj/item/weapon/storage/bag/plasticbag/can_be_inserted() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.head == src) //If worn + return 0 + return ..() + +/obj/item/weapon/storage/bag/plasticbag/suicide_act(mob/user) + user.visible_message("[user] puts the [src.name] over \his head and tightens the handles around \his neck! It looks like \he's trying to commit suicide.") + return(OXYLOSS) + +// ----------------------------- +// Mining Satchel +// ----------------------------- + +/obj/item/weapon/storage/bag/ore + name = "\improper Mining Satchel" //need the improper for the + desc = "This little bugger can be used to store and transport ores." + icon = 'icons/obj/mining.dmi' + icon_state = "satchel" + slot_flags = SLOT_BELT | SLOT_POCKET + w_class = 3 + storage_slots = 50 + max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class + max_w_class = 3 + can_hold = list("/obj/item/weapon/ore") + + +// ----------------------------- +// Plant bag +// ----------------------------- + +/obj/item/weapon/storage/bag/plants + icon = 'icons/obj/hydroponics.dmi' + icon_state = "plantbag" + name = "Plant Bag" + 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 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown", "/obj/item/weapon/reagent_containers/food/snacks/meat", "/obj/item/weapon/reagent_containers/food/snacks/egg", "/obj/item/weapon/reagent_containers/food/snacks/honeycomb") + +// ----------------------------- +// Food bag +// ----------------------------- + +/obj/item/weapon/storage/bag/food + icon = 'icons/obj/kitchen.dmi' + icon_state = "foodbag0" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/backpacks_n_bags.dmi', "right_hand" = 'icons/mob/in-hand/right/backpacks_n_bags.dmi') + name = "Food Delivery Bag" + storage_slots = 14; //the number of food items it can carry. + max_combined_w_class = 28 //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 = 3 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks") + +/obj/item/weapon/storage/bag/food/update_icon() + if(contents.len < 1) + icon_state = "foodbag0" + else icon_state = "foodbag1" + +/obj/item/weapon/storage/bag/food/menu1/New() + ..() + new/obj/item/weapon/reagent_containers/food/snacks/monkeyburger(src)//6 nutriments + new/obj/item/weapon/reagent_containers/food/snacks/fries(src)//4 nutriments + new/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola(src)//-3 drowsy + update_icon() + +/obj/item/weapon/storage/bag/food/menu2/New() + ..() + new/obj/item/weapon/reagent_containers/food/snacks/bigbiteburger(src)//14 nutriments + new/obj/item/weapon/reagent_containers/food/snacks/cheesyfries(src)//6 nutriments + new/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind(src)//-7 drowsy, -1 sleepy + update_icon() + +// ----------------------------- +// Borg Food bag +// ----------------------------- + +/obj/item/weapon/storage/bag/food/borg + name = "Food Transport Bag" + desc = "Useful for manipulating food items in the kitchen." + +// ----------------------------- +// Pill Collector +// ----------------------------- + +/obj/item/weapon/storage/bag/chem + icon = 'icons/obj/chemical.dmi' + icon_state = "pcollector" + name = "Pill Collector" + item_state = "pcollector" + origin_tech = "biotech=2;materials=1" + 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 + can_hold = list("/obj/item/weapon/reagent_containers/glass/bottle","/obj/item/weapon/reagent_containers/pill","/obj/item/weapon/reagent_containers/syringe") + +// ----------------------------- +// Sheet Snatcher +// ----------------------------- +// Because it stacks stacks, this doesn't operate normally. +// However, making it a storage/bag allows us to reuse existing code in some places. -Sayu + +/obj/item/weapon/storage/bag/sheetsnatcher + icon = 'icons/obj/mining.dmi' + icon_state = "sheetsnatcher" + name = "Sheet Snatcher" + desc = "A patented Nanotrasen storage system designed for any kind of mineral sheet." + + var/capacity = 300; //the number of sheets it can carry. + w_class = 3 + + allow_quick_empty = 1 // this function is superceded + New() + ..() + //verbs -= /obj/item/weapon/storage/verb/quick_empty + //verbs += /obj/item/weapon/storage/bag/sheetsnatcher/quick_empty + + can_be_inserted(obj/item/W as obj, stop_messages = 0) + if(!istype(W,/obj/item/stack/sheet) || istype(W,/obj/item/stack/sheet/mineral/sandstone) || istype(W,/obj/item/stack/sheet/wood)) + if(!stop_messages) to_chat(usr, "The snatcher does not accept [W].") - return 0 //I don't care, but the existing code rejects them for not being "sheets" *shrug* -Sayu - var/current = 0 - for(var/obj/item/stack/sheet/S in contents) - current += S.amount - if(capacity == current)//If it's full, you're done - if(!stop_messages) + return 0 //I don't care, but the existing code rejects them for not being "sheets" *shrug* -Sayu + var/current = 0 + for(var/obj/item/stack/sheet/S in contents) + current += S.amount + if(capacity == current)//If it's full, you're done + if(!stop_messages) to_chat(usr, "The snatcher is full.") - return 0 - return 1 - - -// Modified handle_item_insertion. Would prefer not to, but... - handle_item_insertion(obj/item/W as obj, prevent_warning = 0) - var/obj/item/stack/sheet/S = W - if(!istype(S)) return 0 - - var/amount - var/inserted = 0 - var/current = 0 - for(var/obj/item/stack/sheet/S2 in contents) - current += S2.amount - if(capacity < current + S.amount)//If the stack will fill it up - amount = capacity - current - else - amount = S.amount - - for(var/obj/item/stack/sheet/sheet in contents) - if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects - sheet.amount += amount // they should only be removed through procs in this file, which split them up. - S.amount -= amount - inserted = 1 - break - - if(!inserted || !S.amount) - usr.u_equip(S,1) - usr.update_icons() //update our overlays - if (usr.client && usr.s_active != src) - usr.client.screen -= S - //S.dropped(usr) - if(!S.amount) - qdel (S) - S = null - else - S.loc = src - - orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - update_icon() - return 1 - - -// Sets up numbered display to show the stack size of each stored mineral -// NOTE: numbered display is turned off currently because it's broken - orient2hud(mob/user as mob) - var/adjusted_contents = contents.len - - //Numbered contents display - var/list/datum/numbered_display/numbered_contents - if(display_contents_with_number) - numbered_contents = list() - adjusted_contents = 0 - for(var/obj/item/stack/sheet/I in contents) - adjusted_contents++ - var/datum/numbered_display/D = new/datum/numbered_display(I) - D.number = I.amount - numbered_contents.Add( D ) - - var/row_num = 0 - var/col_count = min(7,storage_slots) -1 - if (adjusted_contents > 7) - row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width. - src.standard_orient_objs(row_num, col_count, numbered_contents) - return - - -// Modified quick_empty verb drops appropriate sized stacks - quick_empty() - var/location = get_turf(src) - for(var/obj/item/stack/sheet/S in contents) - while(S.amount) - var/obj/item/stack/sheet/N = new S.type(location) - var/stacksize = min(S.amount,N.max_amount) - N.amount = stacksize - S.amount -= stacksize - if(!S.amount) - qdel (S) // todo: there's probably something missing here - S = null - orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - update_icon() - -// Instead of removing - remove_from_storage(obj/item/W as obj, atom/new_location) - var/obj/item/stack/sheet/S = W - if(!istype(S)) return 0 - - //I would prefer to drop a new stack, but the item/attack_hand code - // that calls this can't recieve a different object than you clicked on. - //Therefore, make a new stack internally that has the remainder. - // -Sayu - - if(S.amount > S.max_amount) - var/obj/item/stack/sheet/temp = new S.type(src) - temp.amount = S.amount - S.max_amount - S.amount = S.max_amount - - return ..(S,new_location) - -// ----------------------------- -// Sheet Snatcher (Cyborg) -// ----------------------------- - -/obj/item/weapon/storage/bag/sheetsnatcher/borg - name = "Sheet Snatcher 9000" - desc = "" - capacity = 500//Borgs get more because >specialization - -// ----------------------------- -// Gadget Bag -// ----------------------------- - -/obj/item/weapon/storage/bag/gadgets - icon = 'icons/obj/storage.dmi' - icon_state = "gadget_bag" - slot_flags = SLOT_BELT - name = "gadget bag" - desc = "This bag can be used to store many machine components." - storage_slots = 25; - max_combined_w_class = 200 - max_w_class = 3 - w_class = 1 - can_hold = list("/obj/item/weapon/stock_parts", "/obj/item/weapon/reagent_containers/glass/beaker", "/obj/item/weapon/cell") - -/obj/item/weapon/storage/bag/gadgets/mass_remove(atom/A) - var/lowest_rating = INFINITY //Get the lowest rating, so only mass drop the lowest parts. - for(var/obj/item/B in contents) - if(B.get_rating() < lowest_rating) - lowest_rating = B.get_rating() - - for(var/obj/item/B in contents) //Now that we have the lowest rating we can dump only parts at the lowest rating. - if(B.get_rating() > lowest_rating) - continue - remove_from_storage(B, A) + return 0 + return 1 + + +// Modified handle_item_insertion. Would prefer not to, but... + handle_item_insertion(obj/item/W as obj, prevent_warning = 0) + var/obj/item/stack/sheet/S = W + if(!istype(S)) return 0 + + var/amount + var/inserted = 0 + var/current = 0 + for(var/obj/item/stack/sheet/S2 in contents) + current += S2.amount + if(capacity < current + S.amount)//If the stack will fill it up + amount = capacity - current + else + amount = S.amount + + for(var/obj/item/stack/sheet/sheet in contents) + if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects + sheet.amount += amount // they should only be removed through procs in this file, which split them up. + S.amount -= amount + inserted = 1 + break + + if(!inserted || !S.amount) + usr.u_equip(S,1) + usr.update_icons() //update our overlays + if (usr.client && usr.s_active != src) + usr.client.screen -= S + //S.dropped(usr) + if(!S.amount) + qdel (S) + S = null + else + S.loc = src + + orient2hud(usr) + if(usr.s_active) + usr.s_active.show_to(usr) + update_icon() + return 1 + + +// Sets up numbered display to show the stack size of each stored mineral +// NOTE: numbered display is turned off currently because it's broken + orient2hud(mob/user as mob) + var/adjusted_contents = contents.len + + //Numbered contents display + var/list/datum/numbered_display/numbered_contents + if(display_contents_with_number) + numbered_contents = list() + adjusted_contents = 0 + for(var/obj/item/stack/sheet/I in contents) + adjusted_contents++ + var/datum/numbered_display/D = new/datum/numbered_display(I) + D.number = I.amount + numbered_contents.Add( D ) + + var/row_num = 0 + var/col_count = min(7,storage_slots) -1 + if (adjusted_contents > 7) + row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width. + src.standard_orient_objs(row_num, col_count, numbered_contents) + return + + +// Modified quick_empty verb drops appropriate sized stacks + quick_empty() + var/location = get_turf(src) + for(var/obj/item/stack/sheet/S in contents) + while(S.amount) + var/obj/item/stack/sheet/N = new S.type(location) + var/stacksize = min(S.amount,N.max_amount) + N.amount = stacksize + S.amount -= stacksize + if(!S.amount) + qdel (S) // todo: there's probably something missing here + S = null + orient2hud(usr) + if(usr.s_active) + usr.s_active.show_to(usr) + update_icon() + +// Instead of removing + remove_from_storage(obj/item/W as obj, atom/new_location) + var/obj/item/stack/sheet/S = W + if(!istype(S)) return 0 + + //I would prefer to drop a new stack, but the item/attack_hand code + // that calls this can't recieve a different object than you clicked on. + //Therefore, make a new stack internally that has the remainder. + // -Sayu + + if(S.amount > S.max_amount) + var/obj/item/stack/sheet/temp = new S.type(src) + temp.amount = S.amount - S.max_amount + S.amount = S.max_amount + + return ..(S,new_location) + +// ----------------------------- +// Sheet Snatcher (Cyborg) +// ----------------------------- + +/obj/item/weapon/storage/bag/sheetsnatcher/borg + name = "Sheet Snatcher 9000" + desc = "" + capacity = 500//Borgs get more because >specialization + +// ----------------------------- +// Gadget Bag +// ----------------------------- + +/obj/item/weapon/storage/bag/gadgets + icon = 'icons/obj/storage.dmi' + icon_state = "gadget_bag" + slot_flags = SLOT_BELT + name = "gadget bag" + desc = "This bag can be used to store many machine components." + storage_slots = 25; + max_combined_w_class = 200 + max_w_class = 3 + w_class = 1 + can_hold = list("/obj/item/weapon/stock_parts", "/obj/item/weapon/reagent_containers/glass/beaker", "/obj/item/weapon/cell") + +/obj/item/weapon/storage/bag/gadgets/mass_remove(atom/A) + var/lowest_rating = INFINITY //Get the lowest rating, so only mass drop the lowest parts. + for(var/obj/item/B in contents) + if(B.get_rating() < lowest_rating) + lowest_rating = B.get_rating() + + for(var/obj/item/B in contents) //Now that we have the lowest rating we can dump only parts at the lowest rating. + if(B.get_rating() > lowest_rating) + continue + remove_from_storage(B, A) diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 50c4ed09ac2..713f0b9c748 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -1,171 +1,171 @@ -/obj/item/weapon/storage/bible - name = "bible" - desc = "Apply to head repeatedly." - icon_state = "bible" - throw_speed = 1 - throw_range = 5 - w_class = 3.0 - force = 2.5 //A big book, solely used for non-Chaplains trying to use it on people - flags = FPRINT - attack_verb = list("whack", "slap", "slam") - var/mob/affecting = null - var/deity_name = "Christ" - - autoignition_temperature = 522 // Kelvin - fire_fuel = 2 - -/obj/item/weapon/storage/bible/suicide_act(mob/living/user) - user.visible_message("[user] is farting on \the [src]! It looks like \he's trying to commit suicide!") - user.emote("fart") - spawn(10) //Wait for it - user.fire_stacks += 5 - user.IgniteMob() - user.emote("scream",,, 1) - return FIRELOSS //Set ablaze and burned to crisps - -//"Special" Bible with a little gift on introduction -/obj/item/weapon/storage/bible/booze - - autoignition_temperature = 0 //Not actually paper - fire_fuel = 0 - -/obj/item/weapon/storage/bible/booze/New() - . = ..() - new /obj/item/weapon/reagent_containers/food/drinks/beer(src) - new /obj/item/weapon/reagent_containers/food/drinks/beer(src) - new /obj/item/weapon/spacecash(src) - new /obj/item/weapon/spacecash(src) - new /obj/item/weapon/spacecash(src) - -//What happens when you slap things with the Bible in general -/obj/item/weapon/storage/bible/attack(mob/living/M as mob, mob/living/user as mob) - - var/chaplain = 0 //Are we the Chaplain ? Used for simplification - if(user.mind && (user.mind.assigned_role == "Chaplain")) - chaplain = 1 //Indeed we are - - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - - if(!user.dexterity_check()) +/obj/item/weapon/storage/bible + name = "bible" + desc = "Apply to head repeatedly." + icon_state = "bible" + throw_speed = 1 + throw_range = 5 + w_class = 3.0 + force = 2.5 //A big book, solely used for non-Chaplains trying to use it on people + flags = FPRINT + attack_verb = list("whack", "slap", "slam") + var/mob/affecting = null + var/deity_name = "Christ" + + autoignition_temperature = 522 // Kelvin + fire_fuel = 2 + +/obj/item/weapon/storage/bible/suicide_act(mob/living/user) + user.visible_message("[user] is farting on \the [src]! It looks like \he's trying to commit suicide!") + user.emote("fart") + spawn(10) //Wait for it + user.fire_stacks += 5 + user.IgniteMob() + user.emote("scream",,, 1) + return FIRELOSS //Set ablaze and burned to crisps + +//"Special" Bible with a little gift on introduction +/obj/item/weapon/storage/bible/booze + + autoignition_temperature = 0 //Not actually paper + fire_fuel = 0 + +/obj/item/weapon/storage/bible/booze/New() + . = ..() + new /obj/item/weapon/reagent_containers/food/drinks/beer(src) + new /obj/item/weapon/reagent_containers/food/drinks/beer(src) + new /obj/item/weapon/spacecash(src) + new /obj/item/weapon/spacecash(src) + new /obj/item/weapon/spacecash(src) + +//What happens when you slap things with the Bible in general +/obj/item/weapon/storage/bible/attack(mob/living/M as mob, mob/living/user as mob) + + var/chaplain = 0 //Are we the Chaplain ? Used for simplification + if(user.mind && (user.mind.assigned_role == "Chaplain")) + chaplain = 1 //Indeed we are + + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") + + if(!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") - return - - if(!chaplain) //The user is not a Chaplain. BLASPHEMY ! - //Using the Bible as a member of the occult will get you smithed, aka holy cleansing fire. You'd have to be stupid to remotely consider it - if(isvampire(user)) //Vampire trying to use it + return + + if(!chaplain) //The user is not a Chaplain. BLASPHEMY ! + //Using the Bible as a member of the occult will get you smithed, aka holy cleansing fire. You'd have to be stupid to remotely consider it + if(isvampire(user)) //Vampire trying to use it to_chat(user, "[deity_name] channels through \the [src] and sets you ablaze for your blasphemy!") - user.fire_stacks += 5 - user.IgniteMob() - user.emote("scream",,, 1) - M.mind.vampire.smitecounter += 50 //Once we are extinguished, we will be quite vulnerable regardless - else if(iscult(user)) //Cultist trying to use it + user.fire_stacks += 5 + user.IgniteMob() + user.emote("scream",,, 1) + M.mind.vampire.smitecounter += 50 //Once we are extinguished, we will be quite vulnerable regardless + else if(iscult(user)) //Cultist trying to use it to_chat(user, "[deity_name] channels through \the [src] and sets you ablaze for your blasphemy!") - user.fire_stacks += 5 - user.IgniteMob() - user.emote("scream",,, 1) - else //Literally anyone else than a Cultist using it, at this point it's just a big book - ..() //WHACK - return //Non-chaplains can't use the holy book, at least not properly - - if((M_CLUMSY in user.mutations) && prob(50)) //Using it while clumsy, let's have some fun - user.visible_message("\The [src] slips out of [user]'s hands and hits \his head.", - "\The [src] slips out of your hands and hits your head.") - user.apply_damage(10, BRUTE, "head") - user.Stun(5) - return - - //From this point onwards we are done with the user, let's check whoever is on the receiving end - //Let us also note that if we made it this far, the user IS a Chaplain. No need to check - //Worthy of note, blessings are done on craniums. I guess this is the best way to send the message across - - if(M == user) //We are trying to smack ourselves - return //That's dumb, don't do it - - if(ishuman(M)) //We're forced to do two ishuman() code paragraphs because this one blocks the others - var/mob/living/carbon/human/H = M - if(istype(H.head, /obj/item/clothing/head/helmet) || istype(H.head, /obj/item/clothing/head/hardhat) || istype(H.head, /obj/item/clothing/head/fedora) || istype(H.head, /obj/item/clothing/head/culthood)) //Blessing blocked - user.visible_message("[user] [pick(attack_verb)]s [H]'s head with \the [src], but their headgear blocks the hit.", - "You [pick(attack_verb)] [H]'s head with \the [src], but their headgear blocks the blessing. Blasphemy!") - return //That's it. Helmets are very haram - - if(M.stat == DEAD) //Our target is dead. RIP in peace - user.visible_message("[user] [pick(attack_verb)]s [M]'s lifeless body with \the [src].", - "You [pick(attack_verb)] [M]'s lifeless body with \the [src], trying to conjure [deity_name]'s mercy on them.") - playsound(get_turf(src), "punch", 25, 1, -1) - - //TODO : Way to bring people back from death if they are your followers - return //Otherwise, there's so little we can do - - //Our target is alive, prepare the blessing - user.visible_message("[user] [pick(attack_verb)]s [M]'s head with \the [src].", - "You [pick(attack_verb)] [M]'s head with \the [src]. In the name of [deity_name], bless thee!") - playsound(get_turf(src), "punch", 25, 1, -1) - - if(ishuman(M)) //Only humans can be vampires or cultists - var/mob/living/carbon/human/H = M - if(isvampire(H) && !(VAMP_MATURE in H.mind.vampire.powers)) //The user is a "young" Vampire, fuck up his vampiric powers and hurt his head + user.fire_stacks += 5 + user.IgniteMob() + user.emote("scream",,, 1) + else //Literally anyone else than a Cultist using it, at this point it's just a big book + ..() //WHACK + return //Non-chaplains can't use the holy book, at least not properly + + if((M_CLUMSY in user.mutations) && prob(50)) //Using it while clumsy, let's have some fun + user.visible_message("\The [src] slips out of [user]'s hands and hits \his head.", + "\The [src] slips out of your hands and hits your head.") + user.apply_damage(10, BRUTE, "head") + user.Stun(5) + return + + //From this point onwards we are done with the user, let's check whoever is on the receiving end + //Let us also note that if we made it this far, the user IS a Chaplain. No need to check + //Worthy of note, blessings are done on craniums. I guess this is the best way to send the message across + + if(M == user) //We are trying to smack ourselves + return //That's dumb, don't do it + + if(ishuman(M)) //We're forced to do two ishuman() code paragraphs because this one blocks the others + var/mob/living/carbon/human/H = M + if(istype(H.head, /obj/item/clothing/head/helmet) || istype(H.head, /obj/item/clothing/head/hardhat) || istype(H.head, /obj/item/clothing/head/fedora) || istype(H.head, /obj/item/clothing/head/culthood)) //Blessing blocked + user.visible_message("[user] [pick(attack_verb)]s [H]'s head with \the [src], but their headgear blocks the hit.", + "You [pick(attack_verb)] [H]'s head with \the [src], but their headgear blocks the blessing. Blasphemy!") + return //That's it. Helmets are very haram + + if(M.stat == DEAD) //Our target is dead. RIP in peace + user.visible_message("[user] [pick(attack_verb)]s [M]'s lifeless body with \the [src].", + "You [pick(attack_verb)] [M]'s lifeless body with \the [src], trying to conjure [deity_name]'s mercy on them.") + playsound(get_turf(src), "punch", 25, 1, -1) + + //TODO : Way to bring people back from death if they are your followers + return //Otherwise, there's so little we can do + + //Our target is alive, prepare the blessing + user.visible_message("[user] [pick(attack_verb)]s [M]'s head with \the [src].", + "You [pick(attack_verb)] [M]'s head with \the [src]. In the name of [deity_name], bless thee!") + playsound(get_turf(src), "punch", 25, 1, -1) + + if(ishuman(M)) //Only humans can be vampires or cultists + var/mob/living/carbon/human/H = M + if(isvampire(H) && !(VAMP_MATURE in H.mind.vampire.powers)) //The user is a "young" Vampire, fuck up his vampiric powers and hurt his head to_chat(H, "[deity_name]'s power nullifies your own!") - if(H.mind.vampire.nullified < 5) //Don't actually reduce their debuff if it's over 5 - H.mind.vampire.nullified = max(5, H.mind.vampire.nullified + 2) - H.mind.vampire.smitecounter += 10 //Better get out of here quickly before the problem shows. Ten hits and you are literal toast - - if(iscult(H)) //The user is a Cultist. We are thus deconverting him - if(prob(20)) + if(H.mind.vampire.nullified < 5) //Don't actually reduce their debuff if it's over 5 + H.mind.vampire.nullified = max(5, H.mind.vampire.nullified + 2) + H.mind.vampire.smitecounter += 10 //Better get out of here quickly before the problem shows. Ten hits and you are literal toast + + if(iscult(H)) //The user is a Cultist. We are thus deconverting him + if(prob(20)) to_chat(H, "The power of [deity_name] suddenly clears your mind of heresy. Your allegiance to Nar'Sie wanes!") to_chat(user, "You see [H]'s eyes become clear. Nar'Sie no longer controls his mind, [deity_name] saved him!") - ticker.mode.remove_cultist(H.mind) - else //We aren't deconverting him this time, give the Cultist a fair warning + ticker.mode.remove_cultist(H.mind) + else //We aren't deconverting him this time, give the Cultist a fair warning to_chat(H, "The power of [deity_name] is overwhelming you. Your mind feverishly questions Nar'Sie's teachings!") - - - bless_mob(user, H) //Let's outsource the healing code, because we can - -//Bless thee. Heals followers fairly, potentially heals everyone a bit (or gives them brain damage) -/obj/item/weapon/storage/bible/proc/bless_mob(mob/living/carbon/human/user, mob/living/carbon/human/H) - var/datum/organ/internal/brain/sponge = H.internal_organs_by_name["brain"] - if(sponge && sponge.damage >= 60) //Massive brain damage + + + bless_mob(user, H) //Let's outsource the healing code, because we can + +//Bless thee. Heals followers fairly, potentially heals everyone a bit (or gives them brain damage) +/obj/item/weapon/storage/bible/proc/bless_mob(mob/living/carbon/human/user, mob/living/carbon/human/H) + var/datum/organ/internal/brain/sponge = H.internal_organs_by_name["brain"] + if(sponge && sponge.damage >= 60) //Massive brain damage to_chat(user, "[H] responds to \the [src]'s blessing with drooling and an empty stare. [deity_name]'s teachings appear to be lost on this poor soul.") - return //Brainfart - //TODO: Put code for followers right here - if(prob(20)) //1/5 chance of adding some brain damage. You can't just heal people for free - H.adjustBrainLoss(5) - if(prob(50)) //1/2 chance of healing at all - for(var/datum/organ/external/affecting in H.organs) - if(affecting.heal_damage(5, 5)) //5 brute and burn healed per bash. Not wonderful, but it can help if someone has Alkyzine handy - H.UpdateDamageIcon() - return //Nothing else to add - -//We're done working on mobs, let's check if we're blessing something else -/obj/item/weapon/storage/bible/afterattack(atom/A, mob/user as mob) - user.delayNextAttack(5) //Extra delay - if(user.mind && (user.mind.assigned_role == "Chaplain")) //Make sure we still are a Chaplain, just in case - if(A.reagents && A.reagents.has_reagent("water")) //Blesses all the water in the holder - user.visible_message("[user] blesses \the [A].", - "You bless \the [A].") - //Ugly but functional conversion proc - var/water2holy = A.reagents.get_reagent_amount("water") - A.reagents.del_reagent("water") - A.reagents.add_reagent("holywater", water2holy) - -/obj/item/weapon/storage/bible/attackby(obj/item/weapon/W as obj, mob/user as mob) - playsound(get_turf(src), "rustle", 50, 1, -5) - . = ..() - -/obj/item/weapon/storage/bible/pickup(mob/living/user as mob) - if(user.mind && user.mind.assigned_role == "Chaplain") //We are the Chaplain, yes we are + return //Brainfart + //TODO: Put code for followers right here + if(prob(20)) //1/5 chance of adding some brain damage. You can't just heal people for free + H.adjustBrainLoss(5) + if(prob(50)) //1/2 chance of healing at all + for(var/datum/organ/external/affecting in H.organs) + if(affecting.heal_damage(5, 5)) //5 brute and burn healed per bash. Not wonderful, but it can help if someone has Alkyzine handy + H.UpdateDamageIcon() + return //Nothing else to add + +//We're done working on mobs, let's check if we're blessing something else +/obj/item/weapon/storage/bible/afterattack(atom/A, mob/user as mob) + user.delayNextAttack(5) //Extra delay + if(user.mind && (user.mind.assigned_role == "Chaplain")) //Make sure we still are a Chaplain, just in case + if(A.reagents && A.reagents.has_reagent("water")) //Blesses all the water in the holder + user.visible_message("[user] blesses \the [A].", + "You bless \the [A].") + //Ugly but functional conversion proc + var/water2holy = A.reagents.get_reagent_amount("water") + A.reagents.del_reagent("water") + A.reagents.add_reagent("holywater", water2holy) + +/obj/item/weapon/storage/bible/attackby(obj/item/weapon/W as obj, mob/user as mob) + playsound(get_turf(src), "rustle", 50, 1, -5) + . = ..() + +/obj/item/weapon/storage/bible/pickup(mob/living/user as mob) + if(user.mind && user.mind.assigned_role == "Chaplain") //We are the Chaplain, yes we are to_chat(user, "You feel [deity_name]'s holy presence as you pick up \the [src].") - if(ishuman(user)) //We are checking for antagonists, only humans can be antagonists - var/mob/living/carbon/human/H = user - if(isvampire(H) && (!VAMP_UNDYING in H.mind.vampire.powers)) //We are a Vampire, we aren't very smart + if(ishuman(user)) //We are checking for antagonists, only humans can be antagonists + var/mob/living/carbon/human/H = user + if(isvampire(H) && (!VAMP_UNDYING in H.mind.vampire.powers)) //We are a Vampire, we aren't very smart to_chat(H, "[deity_name]'s power channels through \the [src]. You feel extremely uneasy as you grab it!") - H.mind.vampire.smitecounter += 10 - if(iscult(H)) //We are a Cultist, we aren't very smart either, but at least there will be no consequences for us + H.mind.vampire.smitecounter += 10 + if(iscult(H)) //We are a Cultist, we aren't very smart either, but at least there will be no consequences for us to_chat(H, "[deity_name]'s power channels through \the [src]. You feel uneasy as you grab it, but Nar'Sie protects you from its influence!") diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 4cee1ef7242..cedb1080519 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -1,536 +1,536 @@ -/* - * Everything derived from the common cardboard box. - * Basically everything except the original is a kit (starts full). - * - * Contains: - * Empty box, starter boxes (survival/engineer), - * Latex glove and sterile mask boxes, - * Syringe, beaker, dna injector boxes, - * Blanks, flashbangs, and EMP grenade boxes, - * Tracking and chemical implant boxes, - * Prescription glasses and drinking glass boxes, - * Condiment bottle and silly cup boxes, - * Donkpocket and monkeycube boxes, - * ID and security PDA cart boxes, - * Handcuff, mousetrap, and pillbottle boxes, - * Snap-pops and matchboxes, - * Replacement light boxes. - * - * For syndicate call-ins see uplink_kits.dm - */ - -/obj/item/weapon/storage/box - name = "box" - desc = "It's just an ordinary box." - icon_state = "box" - item_state = "syringe_kit" - foldable = /obj/item/stack/sheet/cardboard //BubbleWrap - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - - autoignition_temperature = 522 // Kelvin - fire_fuel = 2 - -/obj/item/weapon/storage/box/large - name = "large box" - desc = "You could build a fort with this." - icon_state = "largebox" - item_state = "largebox" - w_class = 42 // Big, bulky. - foldable = /obj/item/stack/sheet/cardboard - foldable_amount = 4 // Takes 4 to make. - N3X - starting_materials = list(MAT_CARDBOARD = 15000) - storage_slots = 21 - max_combined_w_class = 42 // 21*2 - - autoignition_temperature = 530 // Kelvin - fire_fuel = 3 - -/obj/item/weapon/storage/box/surveillance - name = "\improper DromedaryCo packet" - desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" - icon = 'icons/obj/cigarettes.dmi' - icon_state = "Dpacket" - item_state = "Dpacket" - w_class = 1 - foldable = null - New() - ..() - contents = list() - sleep(1) - for(var/i = 1 to 5) - new /obj/item/device/camera_bug(src) - -/obj/item/weapon/storage/box/survival - New() - ..() - contents = list() - sleep(1) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/tank/emergency_oxygen(src) - return - -/obj/item/weapon/storage/box/survival/vox - New() - ..() - contents = list() - sleep(1) - new /obj/item/clothing/mask/breath/vox(src) - new /obj/item/weapon/tank/emergency_nitrogen(src) - return - -/obj/item/weapon/storage/box/engineer/ - New() - ..() - contents = list() - sleep(1) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - return - - -/obj/item/weapon/storage/box/gloves - name = "box of latex gloves" - desc = "Contains white gloves." - icon_state = "latex" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/clothing/gloves/latex(src) - -/obj/item/weapon/storage/box/bgloves - name = "box of black gloves" - desc = "Contains black gloves." - icon_state = "bgloves" - - New() - ..() - for(var/i = 0, i < 7, i++) - new /obj/item/clothing/gloves/black(src) - -/obj/item/weapon/storage/box/sunglasses - name = "box of sunglasses" - desc = "Contains sunglasses." - icon_state = "sunglass" - - New() - ..() - for(var/i = 0, i < 7, i++) - new /obj/item/clothing/glasses/sunglasses(src) - -/obj/item/weapon/storage/box/masks - name = "sterile masks" - desc = "This box contains masks of sterility." - icon_state = "sterile" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/clothing/mask/surgical(src) - - -/obj/item/weapon/storage/box/syringes - name = "syringes" - desc = "A biohazard alert warning is printed on the box" - icon_state = "syringe" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/reagent_containers/syringe(src) - -/obj/item/weapon/storage/box/beakers - name = "beaker box" - icon_state = "beaker" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/reagent_containers/glass/beaker(src) - -/obj/item/weapon/storage/box/injectors - name = "\improper DNA injectors" - desc = "This box contains injectors it seems." - - New() - ..() - for(var/i=0,i<3,i++) - new /obj/item/weapon/dnainjector/nofail/h2m(src) - for(var/i=0,i<3,i++) - new /obj/item/weapon/dnainjector/nofail/m2h(src) - - -/obj/item/weapon/storage/box/blanks - name = "box of blank shells" - desc = "It has a picture of a gun and several warning symbols on the front." - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/ammo_casing/shotgun/blank(src) - - - -/obj/item/weapon/storage/box/flashbangs - name = "box of flashbangs (WARNING)" - desc = "WARNING: These devices are extremely dangerous and can cause blindness or deafness in repeated use." - icon_state = "flashbang" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/grenade/flashbang(src) - -/obj/item/weapon/storage/box/smokebombs - name = "box of smokebombs" - icon_state = "smokebomb" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/grenade/smokebomb(src) - -/obj/item/weapon/storage/box/stickybombs - name = "box of stickybombs" - icon_state = "stickybomb" - - New() - ..() - for(var/i=0,i<24,i++) - new /obj/item/stickybomb(src) - -/obj/item/weapon/storage/box/emps - name = "emp grenades" - desc = "A box with 5 emp grenades." - icon_state = "flashbang" - - New() - ..() - for(var/i=0,i<5,i++) - new /obj/item/weapon/grenade/empgrenade(src) - -/obj/item/weapon/storage/box/foam - name = "metal foam grenades" - desc = "A box containing 7 metal foam grenades" - icon_state = "metalfoam" - - New() - ..() - for(var/i = 0, i < 7, i++) - new /obj/item/weapon/grenade/chem_grenade/metalfoam(src) - -/obj/item/weapon/storage/box/trackimp - name = "tracking implant kit" - desc = "Box full of scum-bag tracking utensils." - icon_state = "implant" - - New() - ..() - for(var/i=0,i<4,i++) - new /obj/item/weapon/implantcase/tracking(src) - new /obj/item/weapon/implanter(src) - new /obj/item/weapon/implantpad(src) - new /obj/item/weapon/locator(src) - -/obj/item/weapon/storage/box/chemimp - name = "chemical implant kit" - desc = "Box of stuff used to implant chemicals." - icon_state = "implant" - - New() - ..() - for(var/i=0,i<5,i++) - new /obj/item/weapon/implantcase/chem(src) - new /obj/item/weapon/implanter(src) - new /obj/item/weapon/implantpad(src) - -/obj/item/weapon/storage/box/bolas - name = "bolas box" - desc = "Box of bolases. Make sure to take them out before throwing them." - icon_state = "bolas" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/legcuffs/bolas(src) - - -/obj/item/weapon/storage/box/rxglasses - name = "prescription glasses" - desc = "This box contains nerd glasses." - icon_state = "glasses" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/clothing/glasses/regular(src) - -/obj/item/weapon/storage/box/drinkingglasses - name = "box of drinking glasses" - desc = "It has a picture of drinking glasses on it." - - New() - ..() - for(var/i=0,i<6,i++) - new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass(src) - -/obj/item/weapon/storage/box/cdeathalarm_kit - name = "Death Alarm Kit" - desc = "Box of stuff used to implant death alarms." - icon_state = "implant" - item_state = "syringe_kit" - - New() - ..() - new /obj/item/weapon/implanter(src) - for(var/i=0,i<6,i++) - new /obj/item/weapon/implantcase/death_alarm(src) - -/obj/item/weapon/storage/box/condimentbottles - name = "box of condiment bottles" - desc = "It has a large ketchup smear on it." - - New() - ..() - for(var/i=0,i<6,i++) - new /obj/item/weapon/reagent_containers/food/condiment(src) - - - -/obj/item/weapon/storage/box/cups - name = "box of paper cups" - desc = "It has pictures of paper cups on the front." - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src) - - -/obj/item/weapon/storage/box/donkpockets - name = "box of donk-pockets" - desc = "Instructions: Heat in microwave. Product will cool if not eaten within seven minutes." - icon_state = "donk_kit" - - New() - ..() - for(var/i=0,i<6,i++) - new /obj/item/weapon/reagent_containers/food/snacks/donkpocket(src) - -/obj/item/weapon/storage/box/monkeycubes - name = "monkey cube box" - desc = "Drymate brand monkey cubes. Just add water!" - icon = 'icons/obj/food.dmi' - icon_state = "monkeycubebox" - storage_slots = 7 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/monkeycube") - New() - ..() - if(src.type == /obj/item/weapon/storage/box/monkeycubes) - for(var/i = 1; i <= 5; i++) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src) - -/obj/item/weapon/storage/box/monkeycubes/farwacubes - name = "farwa cube box" - desc = "Drymate brand farwa cubes, shipped from Ahdomai. Just add water!" - New() - ..() - for(var/i = 1; i <= 5; i++) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube(src) - -/obj/item/weapon/storage/box/monkeycubes/stokcubes - name = "stok cube box" - desc = "Drymate brand stok cubes, shipped from Moghes. Just add water!" - New() - ..() - for(var/i = 1; i <= 5; i++) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube(src) - -/obj/item/weapon/storage/box/monkeycubes/neaeracubes - name = "neaera cube box" - desc = "Drymate brand neaera cubes, shipped from Jargon 4. Just add water!" - New() - ..() - for(var/i = 1; i <= 5; i++) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube(src) - -/obj/item/weapon/storage/box/ids - name = "spare IDs" - desc = "Has so many empty IDs." - icon_state = "id" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/card/id(src) - -/obj/item/weapon/storage/box/seccarts - name = "Spare R.O.B.U.S.T. Cartridges" - desc = "A box full of R.O.B.U.S.T. Cartridges, used by Security." - icon_state = "pda" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/cartridge/security(src) - - -/obj/item/weapon/storage/box/handcuffs - name = "spare handcuffs" - desc = "A box full of handcuffs." - icon_state = "handcuff" - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/handcuffs(src) - -/obj/item/weapon/storage/box/mousetraps - name = "box of Pest-B-Gon Mousetraps" - desc = "WARNING: Keep out of reach of children." - icon_state = "mousetraps" - - New() - ..() - for(var/i=0,i<6,i++) - new /obj/item/device/assembly/mousetrap(src) - -/obj/item/weapon/storage/box/pillbottles - name = "box of pill bottles" - desc = "It has pictures of pill bottles on its front." - - New() - ..() - for(var/i=0,i<7,i++) - new /obj/item/weapon/storage/pill_bottle(src) - -/obj/item/weapon/storage/box/lethalshells - name = "lethal shells" - icon_state = "lethal shells" - - New() - ..() - for(var/i=0,i<15,i++) - new /obj/item/ammo_casing/shotgun(src) - -/obj/item/weapon/storage/box/beanbagshells - name = "bean bag shells" - icon_state = "bean bag shells" - - New() - ..() - for(var/i=0,i<15,i++) - new /obj/item/ammo_casing/shotgun/beanbag(src) - -/obj/item/weapon/storage/box/stunshells - name = "stun shells" - icon_state = "stun shells" - - New() - ..() - for(var/i=0,i<15,i++) - new /obj/item/ammo_casing/shotgun/stunshell(src) - -/obj/item/weapon/storage/box/dartshells - name = "shotgun darts" - icon_state = "dart shells" - - New() - ..() - for(var/i=0,i<15,i++) - new /obj/item/ammo_casing/shotgun/dart(src) - -/obj/item/weapon/storage/box/labels - name = "label roll box" - desc = "A box of refill rolls for a hand labeler." - icon_state = "labels" - - New() - ..() - for(var/i=1; i <= storage_slots; i++) - new /obj/item/device/label_roll(src) - -/obj/item/weapon/storage/box/snappops - name = "snap pop box" - desc = "Eight wrappers of fun! Ages 8 and up. Not suitable for children." - icon = 'icons/obj/toy.dmi' - icon_state = "spbox" - storage_slots = 8 - can_hold = list("/obj/item/toy/snappop") - New() - ..() - for(var/i=1; i <= storage_slots; i++) - new /obj/item/toy/snappop(src) - -/obj/item/weapon/storage/box/autoinjectors - name = "box of injectors" - desc = "Contains autoinjectors." - icon_state = "syringe" - New() - ..() - for (var/i; i < storage_slots; i++) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) - -/obj/item/weapon/storage/box/mugs - name = "box of mugs" - desc = "It's a box of mugs." - icon_state = "box" - - New() - ..() - for(var/i=0,i<6,i++) - new /obj/item/weapon/reagent_containers/food/drinks/mug(src) - -// TODO Change this to a box/large. - N3X -/obj/item/weapon/storage/box/lights - name = "replacement bulbs" - icon = 'icons/obj/storage.dmi' - icon_state = "light" - desc = "This box is shaped on the inside so that only light tubes and bulbs fit." - item_state = "syringe_kit" - 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 - use_to_pickup = 1 // for picking up broken bulbs, not that most people will try - -/obj/item/weapon/storage/box/lights/bulbs/New() - ..() - for(var/i = 0; i < 21; i++) - new /obj/item/weapon/light/bulb(src) - -/obj/item/weapon/storage/box/lights/tubes - name = "replacement tubes" - icon_state = "lighttube" - -/obj/item/weapon/storage/box/lights/tubes/New() - ..() - for(var/i = 0; i < 21; i++) - new /obj/item/weapon/light/tube(src) - -/obj/item/weapon/storage/box/lights/mixed - name = "replacement lights" - icon_state = "lightmixed" - -/obj/item/weapon/storage/box/lights/mixed/New() - ..() - for(var/i = 0; i < 14; i++) - new /obj/item/weapon/light/tube(src) - for(var/i = 0; i < 7; i++) - new /obj/item/weapon/light/bulb(src) - -/obj/item/weapon/storage/box/lights/tubes/New() - ..() - for(var/i = 0; i < 21; i++) - new /obj/item/weapon/light/tube(src) - -/obj/item/weapon/storage/box/lights/he - name = "high efficiency lights" - icon_state = "lightmixed" - -/obj/item/weapon/storage/box/lights/he/New() - ..() - for(var/i = 0; i < 14; i++) - new /obj/item/weapon/light/tube/he(src) - for(var/i = 0; i < 7; i++) - new /obj/item/weapon/light/bulb/he(src) +/* + * Everything derived from the common cardboard box. + * Basically everything except the original is a kit (starts full). + * + * Contains: + * Empty box, starter boxes (survival/engineer), + * Latex glove and sterile mask boxes, + * Syringe, beaker, dna injector boxes, + * Blanks, flashbangs, and EMP grenade boxes, + * Tracking and chemical implant boxes, + * Prescription glasses and drinking glass boxes, + * Condiment bottle and silly cup boxes, + * Donkpocket and monkeycube boxes, + * ID and security PDA cart boxes, + * Handcuff, mousetrap, and pillbottle boxes, + * Snap-pops and matchboxes, + * Replacement light boxes. + * + * For syndicate call-ins see uplink_kits.dm + */ + +/obj/item/weapon/storage/box + name = "box" + desc = "It's just an ordinary box." + icon_state = "box" + item_state = "syringe_kit" + foldable = /obj/item/stack/sheet/cardboard //BubbleWrap + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + + autoignition_temperature = 522 // Kelvin + fire_fuel = 2 + +/obj/item/weapon/storage/box/large + name = "large box" + desc = "You could build a fort with this." + icon_state = "largebox" + item_state = "largebox" + w_class = 42 // Big, bulky. + foldable = /obj/item/stack/sheet/cardboard + foldable_amount = 4 // Takes 4 to make. - N3X + starting_materials = list(MAT_CARDBOARD = 15000) + storage_slots = 21 + max_combined_w_class = 42 // 21*2 + + autoignition_temperature = 530 // Kelvin + fire_fuel = 3 + +/obj/item/weapon/storage/box/surveillance + name = "\improper DromedaryCo packet" + desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" + icon = 'icons/obj/cigarettes.dmi' + icon_state = "Dpacket" + item_state = "Dpacket" + w_class = 1 + foldable = null + New() + ..() + contents = list() + sleep(1) + for(var/i = 1 to 5) + new /obj/item/device/camera_bug(src) + +/obj/item/weapon/storage/box/survival + New() + ..() + contents = list() + sleep(1) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/tank/emergency_oxygen(src) + return + +/obj/item/weapon/storage/box/survival/vox + New() + ..() + contents = list() + sleep(1) + new /obj/item/clothing/mask/breath/vox(src) + new /obj/item/weapon/tank/emergency_nitrogen(src) + return + +/obj/item/weapon/storage/box/engineer/ + New() + ..() + contents = list() + sleep(1) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + return + + +/obj/item/weapon/storage/box/gloves + name = "box of latex gloves" + desc = "Contains white gloves." + icon_state = "latex" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/clothing/gloves/latex(src) + +/obj/item/weapon/storage/box/bgloves + name = "box of black gloves" + desc = "Contains black gloves." + icon_state = "bgloves" + + New() + ..() + for(var/i = 0, i < 7, i++) + new /obj/item/clothing/gloves/black(src) + +/obj/item/weapon/storage/box/sunglasses + name = "box of sunglasses" + desc = "Contains sunglasses." + icon_state = "sunglass" + + New() + ..() + for(var/i = 0, i < 7, i++) + new /obj/item/clothing/glasses/sunglasses(src) + +/obj/item/weapon/storage/box/masks + name = "sterile masks" + desc = "This box contains masks of sterility." + icon_state = "sterile" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/clothing/mask/surgical(src) + + +/obj/item/weapon/storage/box/syringes + name = "syringes" + desc = "A biohazard alert warning is printed on the box" + icon_state = "syringe" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/reagent_containers/syringe(src) + +/obj/item/weapon/storage/box/beakers + name = "beaker box" + icon_state = "beaker" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/reagent_containers/glass/beaker(src) + +/obj/item/weapon/storage/box/injectors + name = "\improper DNA injectors" + desc = "This box contains injectors it seems." + + New() + ..() + for(var/i=0,i<3,i++) + new /obj/item/weapon/dnainjector/nofail/h2m(src) + for(var/i=0,i<3,i++) + new /obj/item/weapon/dnainjector/nofail/m2h(src) + + +/obj/item/weapon/storage/box/blanks + name = "box of blank shells" + desc = "It has a picture of a gun and several warning symbols on the front." + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/ammo_casing/shotgun/blank(src) + + + +/obj/item/weapon/storage/box/flashbangs + name = "box of flashbangs (WARNING)" + desc = "WARNING: These devices are extremely dangerous and can cause blindness or deafness in repeated use." + icon_state = "flashbang" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/grenade/flashbang(src) + +/obj/item/weapon/storage/box/smokebombs + name = "box of smokebombs" + icon_state = "smokebomb" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/grenade/smokebomb(src) + +/obj/item/weapon/storage/box/stickybombs + name = "box of stickybombs" + icon_state = "stickybomb" + + New() + ..() + for(var/i=0,i<24,i++) + new /obj/item/stickybomb(src) + +/obj/item/weapon/storage/box/emps + name = "emp grenades" + desc = "A box with 5 emp grenades." + icon_state = "flashbang" + + New() + ..() + for(var/i=0,i<5,i++) + new /obj/item/weapon/grenade/empgrenade(src) + +/obj/item/weapon/storage/box/foam + name = "metal foam grenades" + desc = "A box containing 7 metal foam grenades" + icon_state = "metalfoam" + + New() + ..() + for(var/i = 0, i < 7, i++) + new /obj/item/weapon/grenade/chem_grenade/metalfoam(src) + +/obj/item/weapon/storage/box/trackimp + name = "tracking implant kit" + desc = "Box full of scum-bag tracking utensils." + icon_state = "implant" + + New() + ..() + for(var/i=0,i<4,i++) + new /obj/item/weapon/implantcase/tracking(src) + new /obj/item/weapon/implanter(src) + new /obj/item/weapon/implantpad(src) + new /obj/item/weapon/locator(src) + +/obj/item/weapon/storage/box/chemimp + name = "chemical implant kit" + desc = "Box of stuff used to implant chemicals." + icon_state = "implant" + + New() + ..() + for(var/i=0,i<5,i++) + new /obj/item/weapon/implantcase/chem(src) + new /obj/item/weapon/implanter(src) + new /obj/item/weapon/implantpad(src) + +/obj/item/weapon/storage/box/bolas + name = "bolas box" + desc = "Box of bolases. Make sure to take them out before throwing them." + icon_state = "bolas" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/legcuffs/bolas(src) + + +/obj/item/weapon/storage/box/rxglasses + name = "prescription glasses" + desc = "This box contains nerd glasses." + icon_state = "glasses" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/clothing/glasses/regular(src) + +/obj/item/weapon/storage/box/drinkingglasses + name = "box of drinking glasses" + desc = "It has a picture of drinking glasses on it." + + New() + ..() + for(var/i=0,i<6,i++) + new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass(src) + +/obj/item/weapon/storage/box/cdeathalarm_kit + name = "Death Alarm Kit" + desc = "Box of stuff used to implant death alarms." + icon_state = "implant" + item_state = "syringe_kit" + + New() + ..() + new /obj/item/weapon/implanter(src) + for(var/i=0,i<6,i++) + new /obj/item/weapon/implantcase/death_alarm(src) + +/obj/item/weapon/storage/box/condimentbottles + name = "box of condiment bottles" + desc = "It has a large ketchup smear on it." + + New() + ..() + for(var/i=0,i<6,i++) + new /obj/item/weapon/reagent_containers/food/condiment(src) + + + +/obj/item/weapon/storage/box/cups + name = "box of paper cups" + desc = "It has pictures of paper cups on the front." + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src) + + +/obj/item/weapon/storage/box/donkpockets + name = "box of donk-pockets" + desc = "Instructions: Heat in microwave. Product will cool if not eaten within seven minutes." + icon_state = "donk_kit" + + New() + ..() + for(var/i=0,i<6,i++) + new /obj/item/weapon/reagent_containers/food/snacks/donkpocket(src) + +/obj/item/weapon/storage/box/monkeycubes + name = "monkey cube box" + desc = "Drymate brand monkey cubes. Just add water!" + icon = 'icons/obj/food.dmi' + icon_state = "monkeycubebox" + storage_slots = 7 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/monkeycube") + New() + ..() + if(src.type == /obj/item/weapon/storage/box/monkeycubes) + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src) + +/obj/item/weapon/storage/box/monkeycubes/farwacubes + name = "farwa cube box" + desc = "Drymate brand farwa cubes, shipped from Ahdomai. Just add water!" + New() + ..() + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube(src) + +/obj/item/weapon/storage/box/monkeycubes/stokcubes + name = "stok cube box" + desc = "Drymate brand stok cubes, shipped from Moghes. Just add water!" + New() + ..() + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube(src) + +/obj/item/weapon/storage/box/monkeycubes/neaeracubes + name = "neaera cube box" + desc = "Drymate brand neaera cubes, shipped from Jargon 4. Just add water!" + New() + ..() + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube(src) + +/obj/item/weapon/storage/box/ids + name = "spare IDs" + desc = "Has so many empty IDs." + icon_state = "id" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/card/id(src) + +/obj/item/weapon/storage/box/seccarts + name = "Spare R.O.B.U.S.T. Cartridges" + desc = "A box full of R.O.B.U.S.T. Cartridges, used by Security." + icon_state = "pda" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/cartridge/security(src) + + +/obj/item/weapon/storage/box/handcuffs + name = "spare handcuffs" + desc = "A box full of handcuffs." + icon_state = "handcuff" + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/handcuffs(src) + +/obj/item/weapon/storage/box/mousetraps + name = "box of Pest-B-Gon Mousetraps" + desc = "WARNING: Keep out of reach of children." + icon_state = "mousetraps" + + New() + ..() + for(var/i=0,i<6,i++) + new /obj/item/device/assembly/mousetrap(src) + +/obj/item/weapon/storage/box/pillbottles + name = "box of pill bottles" + desc = "It has pictures of pill bottles on its front." + + New() + ..() + for(var/i=0,i<7,i++) + new /obj/item/weapon/storage/pill_bottle(src) + +/obj/item/weapon/storage/box/lethalshells + name = "lethal shells" + icon_state = "lethal shells" + + New() + ..() + for(var/i=0,i<15,i++) + new /obj/item/ammo_casing/shotgun(src) + +/obj/item/weapon/storage/box/beanbagshells + name = "bean bag shells" + icon_state = "bean bag shells" + + New() + ..() + for(var/i=0,i<15,i++) + new /obj/item/ammo_casing/shotgun/beanbag(src) + +/obj/item/weapon/storage/box/stunshells + name = "stun shells" + icon_state = "stun shells" + + New() + ..() + for(var/i=0,i<15,i++) + new /obj/item/ammo_casing/shotgun/stunshell(src) + +/obj/item/weapon/storage/box/dartshells + name = "shotgun darts" + icon_state = "dart shells" + + New() + ..() + for(var/i=0,i<15,i++) + new /obj/item/ammo_casing/shotgun/dart(src) + +/obj/item/weapon/storage/box/labels + name = "label roll box" + desc = "A box of refill rolls for a hand labeler." + icon_state = "labels" + + New() + ..() + for(var/i=1; i <= storage_slots; i++) + new /obj/item/device/label_roll(src) + +/obj/item/weapon/storage/box/snappops + name = "snap pop box" + desc = "Eight wrappers of fun! Ages 8 and up. Not suitable for children." + icon = 'icons/obj/toy.dmi' + icon_state = "spbox" + storage_slots = 8 + can_hold = list("/obj/item/toy/snappop") + New() + ..() + for(var/i=1; i <= storage_slots; i++) + new /obj/item/toy/snappop(src) + +/obj/item/weapon/storage/box/autoinjectors + name = "box of injectors" + desc = "Contains autoinjectors." + icon_state = "syringe" + New() + ..() + for (var/i; i < storage_slots; i++) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) + +/obj/item/weapon/storage/box/mugs + name = "box of mugs" + desc = "It's a box of mugs." + icon_state = "box" + + New() + ..() + for(var/i=0,i<6,i++) + new /obj/item/weapon/reagent_containers/food/drinks/mug(src) + +// TODO Change this to a box/large. - N3X +/obj/item/weapon/storage/box/lights + name = "replacement bulbs" + icon = 'icons/obj/storage.dmi' + icon_state = "light" + desc = "This box is shaped on the inside so that only light tubes and bulbs fit." + item_state = "syringe_kit" + 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 + use_to_pickup = 1 // for picking up broken bulbs, not that most people will try + +/obj/item/weapon/storage/box/lights/bulbs/New() + ..() + for(var/i = 0; i < 21; i++) + new /obj/item/weapon/light/bulb(src) + +/obj/item/weapon/storage/box/lights/tubes + name = "replacement tubes" + icon_state = "lighttube" + +/obj/item/weapon/storage/box/lights/tubes/New() + ..() + for(var/i = 0; i < 21; i++) + new /obj/item/weapon/light/tube(src) + +/obj/item/weapon/storage/box/lights/mixed + name = "replacement lights" + icon_state = "lightmixed" + +/obj/item/weapon/storage/box/lights/mixed/New() + ..() + for(var/i = 0; i < 14; i++) + new /obj/item/weapon/light/tube(src) + for(var/i = 0; i < 7; i++) + new /obj/item/weapon/light/bulb(src) + +/obj/item/weapon/storage/box/lights/tubes/New() + ..() + for(var/i = 0; i < 21; i++) + new /obj/item/weapon/light/tube(src) + +/obj/item/weapon/storage/box/lights/he + name = "high efficiency lights" + icon_state = "lightmixed" + +/obj/item/weapon/storage/box/lights/he/New() + ..() + for(var/i = 0; i < 14; i++) + new /obj/item/weapon/light/tube/he(src) + for(var/i = 0; i < 7; i++) + new /obj/item/weapon/light/bulb/he(src) diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index 58f057d6722..27d4be99083 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -1,146 +1,146 @@ -/obj/item/weapon/storage/briefcase - 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" - flags = FPRINT - siemens_coefficient = 1 - force = 8.0 - throw_speed = 1 - throw_range = 4 - w_class = 4.0 - max_w_class = 3 - max_combined_w_class = 16 - var/empty = 0 - -/obj/item/weapon/storage/briefcase/empty - empty = 1 - -/obj/item/weapon/storage/briefcase/biogen - empty = 1 - desc = "Smells faintly of potato." - -/obj/item/weapon/storage/briefcase/suicide_act(mob/user) +/obj/item/weapon/storage/briefcase + 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" + flags = FPRINT + siemens_coefficient = 1 + force = 8.0 + throw_speed = 1 + throw_range = 4 + w_class = 4.0 + max_w_class = 3 + max_combined_w_class = 16 + var/empty = 0 + +/obj/item/weapon/storage/briefcase/empty + empty = 1 + +/obj/item/weapon/storage/briefcase/biogen + empty = 1 + desc = "Smells faintly of potato." + +/obj/item/weapon/storage/briefcase/suicide_act(mob/user) to_chat(viewers(user), "[user] is smashing \his head inside the [src.name]! It looks like \he's trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/weapon/storage/briefcase/New() - ..() - if (empty) return - new /obj/item/weapon/paper/demotion_key(src) - new /obj/item/weapon/paper/commendation_key(src) - -/obj/item/weapon/storage/briefcase/attack(mob/living/M as mob, mob/living/user as mob) - //..() - - if ((M_CLUMSY in user.mutations) && prob(50)) + return (BRUTELOSS) + +/obj/item/weapon/storage/briefcase/New() + ..() + if (empty) return + new /obj/item/weapon/paper/demotion_key(src) + new /obj/item/weapon/paper/commendation_key(src) + +/obj/item/weapon/storage/briefcase/attack(mob/living/M as mob, mob/living/user as mob) + //..() + + if ((M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "The [src] slips out of your hand and hits your head.") - user.take_organ_damage(10) - user.Paralyse(2) - return - - - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (?)") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - if (M.stat < 2 && M.health < 50 && prob(90)) - var/mob/H = M - // ******* Check - if ((istype(H, /mob/living/carbon/human) && istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80))) + user.take_organ_damage(10) + user.Paralyse(2) + return + + + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (?)") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + if (M.stat < 2 && M.health < 50 && prob(90)) + var/mob/H = M + // ******* Check + if ((istype(H, /mob/living/carbon/human) && istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80))) to_chat(M, "The helmet protects you from being hit hard in the head!") - return - var/time = rand(2, 6) - if (prob(75)) - M.Paralyse(time) - else - M.Stun(time) - if(M.stat != 2) M.stat = 1 - for(var/mob/O in viewers(M, null)) - O.show_message(text("[] has been knocked unconscious!", M), 1, "You hear someone fall.", 2) - else + return + var/time = rand(2, 6) + if (prob(75)) + M.Paralyse(time) + else + M.Stun(time) + if(M.stat != 2) M.stat = 1 + for(var/mob/O in viewers(M, null)) + O.show_message(text("[] has been knocked unconscious!", M), 1, "You hear someone fall.", 2) + else to_chat(M, text("[] tried to knock you unconcious!",user)) - M.eye_blurry += 3 - - return - -/obj/item/weapon/storage/briefcase/false_bottomed - name = "briefcase" - desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. This one feels a bit heavier than normal for how much fits in it." - icon_state = "briefcase" - force = 8.0 - throw_speed = 1 - throw_range = 3 - w_class = 4.0 - max_w_class = 2 - max_combined_w_class = 10 - - var/busy_hunting = 0 - var/bottom_open = 0 //is the false bottom open? - var/obj/item/stored_item = null //what's in the false bottom. If it's a gun, we can fire it - -/obj/item/weapon/storage/briefcase/false_bottomed/Destroy() - if(stored_item)//since the stored_item isn't in the briefcase' contents we gotta remind the game to delete it here. - qdel(stored_item) - stored_item = null - ..() - -/obj/item/weapon/storage/briefcase/false_bottomed/afterattack(var/atom/A, mob/user) - ..() - if(stored_item && istype(stored_item, /obj/item/weapon/gun) && get_dist(A, user) > 1) - var/obj/item/weapon/gun/stored_gun = stored_item - stored_gun.Fire(A, user) - return - -/obj/item/weapon/storage/briefcase/false_bottomed/attackby(var/obj/item/item, mob/user) - if(istype(item, /obj/item/weapon/screwdriver)) - if(!bottom_open && !busy_hunting) + M.eye_blurry += 3 + + return + +/obj/item/weapon/storage/briefcase/false_bottomed + name = "briefcase" + desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. This one feels a bit heavier than normal for how much fits in it." + icon_state = "briefcase" + force = 8.0 + throw_speed = 1 + throw_range = 3 + w_class = 4.0 + max_w_class = 2 + max_combined_w_class = 10 + + var/busy_hunting = 0 + var/bottom_open = 0 //is the false bottom open? + var/obj/item/stored_item = null //what's in the false bottom. If it's a gun, we can fire it + +/obj/item/weapon/storage/briefcase/false_bottomed/Destroy() + if(stored_item)//since the stored_item isn't in the briefcase' contents we gotta remind the game to delete it here. + qdel(stored_item) + stored_item = null + ..() + +/obj/item/weapon/storage/briefcase/false_bottomed/afterattack(var/atom/A, mob/user) + ..() + if(stored_item && istype(stored_item, /obj/item/weapon/gun) && get_dist(A, user) > 1) + var/obj/item/weapon/gun/stored_gun = stored_item + stored_gun.Fire(A, user) + return + +/obj/item/weapon/storage/briefcase/false_bottomed/attackby(var/obj/item/item, mob/user) + if(istype(item, /obj/item/weapon/screwdriver)) + if(!bottom_open && !busy_hunting) to_chat(user, "You begin to hunt around the rim of \the [src]...") - busy_hunting = 1 - if(do_after(user, src, 20)) - if(user) + busy_hunting = 1 + if(do_after(user, src, 20)) + if(user) to_chat(user, "You pry open the false bottom!") - bottom_open = 1 - busy_hunting = 0 - else if(bottom_open) + bottom_open = 1 + busy_hunting = 0 + else if(bottom_open) to_chat(user, "You push the false bottom down and close it with a click[stored_item ? ", with \the [stored_item] snugly inside." : "."]") - bottom_open = 0 - else if(bottom_open) - if(stored_item) + bottom_open = 0 + else if(bottom_open) + if(stored_item) to_chat(user, "There's already something in the false bottom!") - return - if(item.w_class > 3.0) + return + if(item.w_class > 3.0) to_chat(user, "\The [item] is too big to fit in the false bottom!") - return - if(!user.drop_item(item)) - user << "\The [item] is stuck to your hands!" - return - - stored_item = item - max_w_class = 3.0 - stored_item.w_class - item.loc = null //null space here we go - to stop it showing up in the briefcase + return + if(!user.drop_item(item)) + user << "\The [item] is stuck to your hands!" + return + + stored_item = item + max_w_class = 3.0 - stored_item.w_class + item.loc = null //null space here we go - to stop it showing up in the briefcase to_chat(user, "You place \the [item] into the false bottom of the briefcase.") - else - return ..() - -/obj/item/weapon/storage/briefcase/false_bottomed/attack_hand(mob/user) - if(bottom_open && stored_item) - user.put_in_hands(stored_item) + else + return ..() + +/obj/item/weapon/storage/briefcase/false_bottomed/attack_hand(mob/user) + if(bottom_open && stored_item) + user.put_in_hands(stored_item) to_chat(user, "You pull out \the [stored_item] from \the [src]'s false bottom.") - stored_item = null - max_w_class = initial(max_w_class) - else - return ..() - - -/obj/item/weapon/storage/briefcase/false_bottomed/smg - - -/obj/item/weapon/storage/briefcase/false_bottomed/smg/New() - ..() - var/obj/item/weapon/gun/projectile/automatic/SMG = new - SMG.gun_flags &= ~AUTOMAGDROP //dont want to drop mags in null space, do we? - stored_item = SMG + stored_item = null + max_w_class = initial(max_w_class) + else + return ..() + + +/obj/item/weapon/storage/briefcase/false_bottomed/smg + + +/obj/item/weapon/storage/briefcase/false_bottomed/smg/New() + ..() + var/obj/item/weapon/gun/projectile/automatic/SMG = new + SMG.gun_flags &= ~AUTOMAGDROP //dont want to drop mags in null space, do we? + stored_item = SMG diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index bc36dbcc1da..729de4fa324 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -1,521 +1,521 @@ -/* - * The 'fancy' path is for objects like donut boxes that show how many items are in the storage item on the sprite itself - * .. Sorry for the shitty path name, I couldnt think of a better one. - * - * WARNING: var/icon_type is used for both examine text and sprite name. Please look at the procs below and adjust your sprite names accordingly - * TODO: Cigarette boxes should be ported to this standard - * - * Contains: - * Donut Box - * Egg Box - * Candle Box - * Crayon Box - * Cigarette Box - * Food Box - * Chicken Bucket - * Slider Box - */ - -/obj/item/weapon/storage/fancy/ - icon = 'icons/obj/food.dmi' - icon_state = "donutbox6" - name = "donut box" - var/icon_type = "donut" - var/plural_type = "s" //Why does the english language have to be so complicated to work with ? - var/empty = 0 - - foldable = /obj/item/stack/sheet/cardboard - - //Note : Fancy storages generally collect one specific type of objects only due to their properties - //As such, it would make sense that one click on a stack of the corresponding objects should shove everything in here - - allow_quick_gather = 1 - use_to_pickup = 1 - allow_quick_empty = 1 - -/obj/item/weapon/storage/fancy/update_icon(var/itemremoved = 0) - var/total_contents = src.contents.len - itemremoved - src.icon_state = "[src.icon_type]box[total_contents]" - return - -/obj/item/weapon/storage/fancy/examine(mob/user) - ..() - if(contents.len <= 0) +/* + * The 'fancy' path is for objects like donut boxes that show how many items are in the storage item on the sprite itself + * .. Sorry for the shitty path name, I couldnt think of a better one. + * + * WARNING: var/icon_type is used for both examine text and sprite name. Please look at the procs below and adjust your sprite names accordingly + * TODO: Cigarette boxes should be ported to this standard + * + * Contains: + * Donut Box + * Egg Box + * Candle Box + * Crayon Box + * Cigarette Box + * Food Box + * Chicken Bucket + * Slider Box + */ + +/obj/item/weapon/storage/fancy/ + icon = 'icons/obj/food.dmi' + icon_state = "donutbox6" + name = "donut box" + var/icon_type = "donut" + var/plural_type = "s" //Why does the english language have to be so complicated to work with ? + var/empty = 0 + + foldable = /obj/item/stack/sheet/cardboard + + //Note : Fancy storages generally collect one specific type of objects only due to their properties + //As such, it would make sense that one click on a stack of the corresponding objects should shove everything in here + + allow_quick_gather = 1 + use_to_pickup = 1 + allow_quick_empty = 1 + +/obj/item/weapon/storage/fancy/update_icon(var/itemremoved = 0) + var/total_contents = src.contents.len - itemremoved + src.icon_state = "[src.icon_type]box[total_contents]" + return + +/obj/item/weapon/storage/fancy/examine(mob/user) + ..() + if(contents.len <= 0) to_chat(user, "There are no [src.icon_type][plural_type] left in the box.") - else if(contents.len == 1) + else if(contents.len == 1) to_chat(user, "There is one [src.icon_type] left in the box.") - else + else to_chat(user, "There are [src.contents.len] [src.icon_type][plural_type] in the box.") - - -/* - * Donut Box - */ - -/obj/item/weapon/storage/fancy/donut_box - icon = 'icons/obj/food.dmi' - icon_state = "donutbox6" - icon_type = "donut" - name = "donut box" - storage_slots = 6 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/donut", \ - "/obj/item/weapon/reagent_containers/food/snacks/customizable/candy/donut") - - foldable = /obj/item/stack/sheet/cardboard - starting_materials = list(MAT_CARDBOARD = 3750) - w_type = RECYK_MISC - -/obj/item/weapon/storage/fancy/donut_box/empty - empty = 1 - icon_state = "donutbox0" - -/obj/item/weapon/storage/fancy/donut_box/New() - ..() - if(empty) - update_icon() //Make it look actually empty - return - for(var/i = 1; i <= storage_slots; i++) - new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(src) - return - -/* - * Egg Box - */ - -/obj/item/weapon/storage/fancy/egg_box - icon = 'icons/obj/food.dmi' - icon_state = "eggbox" - icon_type = "egg" - name = "egg box" - storage_slots = 12 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/egg") - - foldable = /obj/item/stack/sheet/cardboard - starting_materials = list(MAT_CARDBOARD = 3750) - w_type = RECYK_MISC - -/obj/item/weapon/storage/fancy/egg_box/empty - empty = 1 - icon_state = "eggbox0" - -/obj/item/weapon/storage/fancy/egg_box/New() - ..() - if(empty) - update_icon() //Make it look actually empty - return - for(var/i = 1; i <= storage_slots; i++) - new /obj/item/weapon/reagent_containers/food/snacks/egg(src) - return - -/* - * Candle Box - */ - -/obj/item/weapon/storage/fancy/candle_box - name = "Candle pack" - desc = "A pack of red candles." - icon = 'icons/obj/candle.dmi' - icon_state = "candlebox5" - icon_type = "candle" - item_state = "candlebox5" - foldable = /obj/item/stack/sheet/cardboard - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - storage_slots = 5 - throwforce = 2 - flags = 0 - slot_flags = SLOT_BELT - -/obj/item/weapon/storage/fancy/candle_box/empty - empty = 1 - icon_state = "candlebox0" - item_state = "candlebox0" //i don't know what this does but it seems like this should go here - -/obj/item/weapon/storage/fancy/candle_box/New() - ..() - if (empty) return - for(var/i=1; i <= storage_slots; i++) - new /obj/item/candle(src) - return - -/* - * Crayon Box - */ - -/obj/item/weapon/storage/fancy/crayons - name = "box of crayons" - desc = "A box of crayons for all your rune drawing needs." - icon = 'icons/obj/crayons.dmi' - icon_state = "crayonbox" - foldable = /obj/item/stack/sheet/cardboard - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - w_class = 2.0 - storage_slots = 6 - icon_type = "crayon" - can_hold = list( - "/obj/item/toy/crayon" - ) - -/obj/item/weapon/storage/fancy/crayons/empty - empty = 1 - -/obj/item/weapon/storage/fancy/crayons/New() - ..() - if (empty) return - new /obj/item/toy/crayon/red(src) - new /obj/item/toy/crayon/orange(src) - new /obj/item/toy/crayon/yellow(src) - new /obj/item/toy/crayon/green(src) - new /obj/item/toy/crayon/blue(src) - new /obj/item/toy/crayon/purple(src) - update_icon() - -/obj/item/weapon/storage/fancy/crayons/update_icon() - overlays = list() //resets list - overlays += image('icons/obj/crayons.dmi',"crayonbox") - for(var/obj/item/toy/crayon/crayon in contents) - overlays += image('icons/obj/crayons.dmi',crayon.colourName) - -/obj/item/weapon/storage/fancy/crayons/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W,/obj/item/toy/crayon)) - switch(W:colourName) - if("mime") + + +/* + * Donut Box + */ + +/obj/item/weapon/storage/fancy/donut_box + icon = 'icons/obj/food.dmi' + icon_state = "donutbox6" + icon_type = "donut" + name = "donut box" + storage_slots = 6 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/donut", \ + "/obj/item/weapon/reagent_containers/food/snacks/customizable/candy/donut") + + foldable = /obj/item/stack/sheet/cardboard + starting_materials = list(MAT_CARDBOARD = 3750) + w_type = RECYK_MISC + +/obj/item/weapon/storage/fancy/donut_box/empty + empty = 1 + icon_state = "donutbox0" + +/obj/item/weapon/storage/fancy/donut_box/New() + ..() + if(empty) + update_icon() //Make it look actually empty + return + for(var/i = 1; i <= storage_slots; i++) + new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(src) + return + +/* + * Egg Box + */ + +/obj/item/weapon/storage/fancy/egg_box + icon = 'icons/obj/food.dmi' + icon_state = "eggbox" + icon_type = "egg" + name = "egg box" + storage_slots = 12 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/egg") + + foldable = /obj/item/stack/sheet/cardboard + starting_materials = list(MAT_CARDBOARD = 3750) + w_type = RECYK_MISC + +/obj/item/weapon/storage/fancy/egg_box/empty + empty = 1 + icon_state = "eggbox0" + +/obj/item/weapon/storage/fancy/egg_box/New() + ..() + if(empty) + update_icon() //Make it look actually empty + return + for(var/i = 1; i <= storage_slots; i++) + new /obj/item/weapon/reagent_containers/food/snacks/egg(src) + return + +/* + * Candle Box + */ + +/obj/item/weapon/storage/fancy/candle_box + name = "Candle pack" + desc = "A pack of red candles." + icon = 'icons/obj/candle.dmi' + icon_state = "candlebox5" + icon_type = "candle" + item_state = "candlebox5" + foldable = /obj/item/stack/sheet/cardboard + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + storage_slots = 5 + throwforce = 2 + flags = 0 + slot_flags = SLOT_BELT + +/obj/item/weapon/storage/fancy/candle_box/empty + empty = 1 + icon_state = "candlebox0" + item_state = "candlebox0" //i don't know what this does but it seems like this should go here + +/obj/item/weapon/storage/fancy/candle_box/New() + ..() + if (empty) return + for(var/i=1; i <= storage_slots; i++) + new /obj/item/candle(src) + return + +/* + * Crayon Box + */ + +/obj/item/weapon/storage/fancy/crayons + name = "box of crayons" + desc = "A box of crayons for all your rune drawing needs." + icon = 'icons/obj/crayons.dmi' + icon_state = "crayonbox" + foldable = /obj/item/stack/sheet/cardboard + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + w_class = 2.0 + storage_slots = 6 + icon_type = "crayon" + can_hold = list( + "/obj/item/toy/crayon" + ) + +/obj/item/weapon/storage/fancy/crayons/empty + empty = 1 + +/obj/item/weapon/storage/fancy/crayons/New() + ..() + if (empty) return + new /obj/item/toy/crayon/red(src) + new /obj/item/toy/crayon/orange(src) + new /obj/item/toy/crayon/yellow(src) + new /obj/item/toy/crayon/green(src) + new /obj/item/toy/crayon/blue(src) + new /obj/item/toy/crayon/purple(src) + update_icon() + +/obj/item/weapon/storage/fancy/crayons/update_icon() + overlays = list() //resets list + overlays += image('icons/obj/crayons.dmi',"crayonbox") + for(var/obj/item/toy/crayon/crayon in contents) + overlays += image('icons/obj/crayons.dmi',crayon.colourName) + +/obj/item/weapon/storage/fancy/crayons/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W,/obj/item/toy/crayon)) + switch(W:colourName) + if("mime") to_chat(usr, "This crayon is too sad to be contained in this box.") - return - if("rainbow") + return + if("rainbow") to_chat(usr, "This crayon is too powerful to be contained in this box.") - return - . = ..() - -/* - * Match Box - */ - -/obj/item/weapon/storage/fancy/matchbox - name = "matchbox" - desc = "A box of matches. Critical element of a survival kit and equally needed by chain smokers and pyromaniacs." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "matchbox" - item_state = "zippo" - icon_type = "match" - plural_type = "es" - storage_slots = 21 //3 rows of 7 items - w_class = 1 - flags = 0 - var/matchtype = /obj/item/weapon/match - can_hold = list("/obj/item/weapon/match") // Strict type check. - slot_flags = SLOT_BELT - -/obj/item/weapon/storage/fancy/matchbox/empty - empty = 1 - icon_state = "matchbox_e" - -/obj/item/weapon/storage/fancy/matchbox/New() - ..() - if(empty) - update_icon() //Make it look actually empty - return - for(var/i = 1; i <= storage_slots; i++) - new matchtype(src) - update_icon() - -/obj/item/weapon/storage/fancy/matchbox/update_icon() - - var/contentpercent = (contents.len/storage_slots)*100 - if(contentpercent < 33) //Looks empty, actually not a single row full because logic - icon_state = "[initial(icon_state)]_e" - return - else if(contentpercent < 65) //1 row full, 1 row almost full - icon_state = "[initial(icon_state)]_almostempty" - return - else if(contentpercent < 100) //At least one of the first row removed - icon_state = "[initial(icon_state)]_almostfull" - return - else if(contentpercent == 100) - icon_state = "[initial(icon_state)]" - return - -/obj/item/weapon/storage/fancy/matchbox/attackby(obj/item/weapon/match/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/match) && !W.lit) - W.lit = 1 - W.update_brightness() - return - -/obj/item/weapon/storage/fancy/matchbox/strike_anywhere - name = "strike-anywhere matchbox" - desc = "A box of strike-anywhere matches. Critical element of a survival kit and equally needed by chain smokers and pyromaniacs. These ones can be lit against any surface." - icon_type = "strike-anywhere match" - matchtype = /obj/item/weapon/match/strike_anywhere - -/obj/item/weapon/storage/fancy/matchbox/strike_anywhere/empty - empty = 1 - -//////////// -//CIG PACK// -//////////// -/obj/item/weapon/storage/fancy/cigarettes - name = "cigarette packet" - desc = "The most popular brand of Space Cigarettes, sponsors of the Space Olympics." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "cigpacket" - item_state = "cigpacket" - w_class = 1 - throwforce = 2 - flags = 0 - slot_flags = SLOT_BELT - storage_slots = 6 - can_hold = list("=/obj/item/clothing/mask/cigarette", "/obj/item/weapon/lighter") // Strict type check. - icon_type = "cigarette" - starting_materials = list(MAT_CARDBOARD = 370) - w_type=RECYK_MISC - -/obj/item/weapon/storage/fancy/cigarettes/New() - ..() - flags |= NOREACT - for(var/i = 1 to storage_slots) - new /obj/item/clothing/mask/cigarette(src) - create_reagents(15 * storage_slots)//so people can inject cigarettes without opening a packet, now with being able to inject the whole one - -/obj/item/weapon/storage/fancy/cigarettes/Destroy() - qdel(reagents) - reagents = null - ..() - - -/obj/item/weapon/storage/fancy/cigarettes/update_icon() - icon_state = "[initial(icon_state)][contents.len]" - desc = "There are [contents.len] cig\s left!" - return - -/obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W as obj, atom/new_location) - var/obj/item/clothing/mask/cigarette/C = W - if(!istype(C)) return // what - reagents.trans_to(C, (reagents.total_volume/contents.len)) - ..() - -/obj/item/weapon/storage/fancy/cigarettes/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M, /mob)) - return - - if(M == user && user.zone_sel.selecting == "mouth" && contents.len > 0 && !user.wear_mask) - var/obj/item/clothing/mask/cigarette/W = new /obj/item/clothing/mask/cigarette(user) - reagents.trans_to(W, (reagents.total_volume/contents.len)) - user.equip_to_slot_if_possible(W, slot_wear_mask) - reagents.maximum_volume = 15 * contents.len - contents.len-- + return + . = ..() + +/* + * Match Box + */ + +/obj/item/weapon/storage/fancy/matchbox + name = "matchbox" + desc = "A box of matches. Critical element of a survival kit and equally needed by chain smokers and pyromaniacs." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "matchbox" + item_state = "zippo" + icon_type = "match" + plural_type = "es" + storage_slots = 21 //3 rows of 7 items + w_class = 1 + flags = 0 + var/matchtype = /obj/item/weapon/match + can_hold = list("/obj/item/weapon/match") // Strict type check. + slot_flags = SLOT_BELT + +/obj/item/weapon/storage/fancy/matchbox/empty + empty = 1 + icon_state = "matchbox_e" + +/obj/item/weapon/storage/fancy/matchbox/New() + ..() + if(empty) + update_icon() //Make it look actually empty + return + for(var/i = 1; i <= storage_slots; i++) + new matchtype(src) + update_icon() + +/obj/item/weapon/storage/fancy/matchbox/update_icon() + + var/contentpercent = (contents.len/storage_slots)*100 + if(contentpercent < 33) //Looks empty, actually not a single row full because logic + icon_state = "[initial(icon_state)]_e" + return + else if(contentpercent < 65) //1 row full, 1 row almost full + icon_state = "[initial(icon_state)]_almostempty" + return + else if(contentpercent < 100) //At least one of the first row removed + icon_state = "[initial(icon_state)]_almostfull" + return + else if(contentpercent == 100) + icon_state = "[initial(icon_state)]" + return + +/obj/item/weapon/storage/fancy/matchbox/attackby(obj/item/weapon/match/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/match) && !W.lit) + W.lit = 1 + W.update_brightness() + return + +/obj/item/weapon/storage/fancy/matchbox/strike_anywhere + name = "strike-anywhere matchbox" + desc = "A box of strike-anywhere matches. Critical element of a survival kit and equally needed by chain smokers and pyromaniacs. These ones can be lit against any surface." + icon_type = "strike-anywhere match" + matchtype = /obj/item/weapon/match/strike_anywhere + +/obj/item/weapon/storage/fancy/matchbox/strike_anywhere/empty + empty = 1 + +//////////// +//CIG PACK// +//////////// +/obj/item/weapon/storage/fancy/cigarettes + name = "cigarette packet" + desc = "The most popular brand of Space Cigarettes, sponsors of the Space Olympics." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "cigpacket" + item_state = "cigpacket" + w_class = 1 + throwforce = 2 + flags = 0 + slot_flags = SLOT_BELT + storage_slots = 6 + can_hold = list("=/obj/item/clothing/mask/cigarette", "/obj/item/weapon/lighter") // Strict type check. + icon_type = "cigarette" + starting_materials = list(MAT_CARDBOARD = 370) + w_type=RECYK_MISC + +/obj/item/weapon/storage/fancy/cigarettes/New() + ..() + flags |= NOREACT + for(var/i = 1 to storage_slots) + new /obj/item/clothing/mask/cigarette(src) + create_reagents(15 * storage_slots)//so people can inject cigarettes without opening a packet, now with being able to inject the whole one + +/obj/item/weapon/storage/fancy/cigarettes/Destroy() + qdel(reagents) + reagents = null + ..() + + +/obj/item/weapon/storage/fancy/cigarettes/update_icon() + icon_state = "[initial(icon_state)][contents.len]" + desc = "There are [contents.len] cig\s left!" + return + +/obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W as obj, atom/new_location) + var/obj/item/clothing/mask/cigarette/C = W + if(!istype(C)) return // what + reagents.trans_to(C, (reagents.total_volume/contents.len)) + ..() + +/obj/item/weapon/storage/fancy/cigarettes/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M, /mob)) + return + + if(M == user && user.zone_sel.selecting == "mouth" && contents.len > 0 && !user.wear_mask) + var/obj/item/clothing/mask/cigarette/W = new /obj/item/clothing/mask/cigarette(user) + reagents.trans_to(W, (reagents.total_volume/contents.len)) + user.equip_to_slot_if_possible(W, slot_wear_mask) + reagents.maximum_volume = 15 * contents.len + contents.len-- to_chat(user, "You take a cigarette out of the pack.") - update_icon() - else - ..() - -/obj/item/weapon/storage/fancy/cigarettes/dromedaryco - name = "\improper DromedaryCo packet" - desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" - icon_state = "Dpacket" - item_state = "Dpacket" - - -/* - * Vial Box - */ - -/obj/item/weapon/storage/fancy/vials - icon = 'icons/obj/vialbox.dmi' - icon_state = "vialbox6" - icon_type = "vial" - name = "vial storage box" - storage_slots = 6 - can_hold = list("/obj/item/weapon/reagent_containers/glass/beaker/vial") - - foldable = null - - -/obj/item/weapon/storage/fancy/vials/New() - ..() - for(var/i=1; i <= storage_slots; i++) - new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) - return - -//I know vial storage is just above, but it really shouldn't be there -//Furthermore, this can lead to confusion with fancy items now having quick gather and quick empty -/obj/item/weapon/storage/lockbox/vials - name = "secure vial storage box" - desc = "A locked box for keeping things away from children." - icon = 'icons/obj/vialbox.dmi' - icon_state = "vialbox0" - item_state = "syringe_kit" - max_w_class = 3 - can_hold = list("/obj/item/weapon/reagent_containers/glass/beaker/vial") - max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. - storage_slots = 6 - req_access = list(access_virology) - -/obj/item/weapon/storage/lockbox/vials/New() - ..() - update_icon() - -/obj/item/weapon/storage/lockbox/vials/update_icon(var/itemremoved = 0) - var/total_contents = src.contents.len - itemremoved - src.icon_state = "vialbox[total_contents]" - src.overlays.len = 0 - if (!broken) - overlays += image(icon, src, "led[locked]") - if(locked) - overlays += image(icon, src, "cover") - else - overlays += image(icon, src, "ledb") - return - -/obj/item/weapon/storage/lockbox/vials/attackby(obj/item/weapon/W as obj, mob/user as mob) - . = ..() - update_icon() - -//FLARE BOX -//Useful for lots of things, this box has 6 flares in it. Only takes unused and unlight flares. -//Great for emergency crates/closets etc. - -/obj/item/weapon/storage/fancy/flares - icon = 'icons/obj/lighting.dmi' - icon_state = "flarebox6" - icon_type = "flare" - name = "box of flares" - storage_slots = 6 - can_hold = list("/obj/item/device/flashlight/flare") - - foldable = /obj/item/stack/sheet/cardboard - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - -/obj/item/weapon/storage/fancy/flares/empty - empty = 1 - icon_state = "flarebox0" - -/obj/item/weapon/storage/fancy/flares/New() - ..() - if(empty) - update_icon() //Make it look actually empty - return - for(var/i=1; i <= storage_slots; i++) - new /obj/item/device/flashlight/flare(src) - return - -/obj/item/weapon/storage/fancy/flares/attackby(var/obj/item/device/flashlight/flare/F, var/user as mob) //if it's on or empty, we don't want it - if(!istype(F)) - return - if(F.on) + update_icon() + else + ..() + +/obj/item/weapon/storage/fancy/cigarettes/dromedaryco + name = "\improper DromedaryCo packet" + desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" + icon_state = "Dpacket" + item_state = "Dpacket" + + +/* + * Vial Box + */ + +/obj/item/weapon/storage/fancy/vials + icon = 'icons/obj/vialbox.dmi' + icon_state = "vialbox6" + icon_type = "vial" + name = "vial storage box" + storage_slots = 6 + can_hold = list("/obj/item/weapon/reagent_containers/glass/beaker/vial") + + foldable = null + + +/obj/item/weapon/storage/fancy/vials/New() + ..() + for(var/i=1; i <= storage_slots; i++) + new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) + return + +//I know vial storage is just above, but it really shouldn't be there +//Furthermore, this can lead to confusion with fancy items now having quick gather and quick empty +/obj/item/weapon/storage/lockbox/vials + name = "secure vial storage box" + desc = "A locked box for keeping things away from children." + icon = 'icons/obj/vialbox.dmi' + icon_state = "vialbox0" + item_state = "syringe_kit" + max_w_class = 3 + can_hold = list("/obj/item/weapon/reagent_containers/glass/beaker/vial") + max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. + storage_slots = 6 + req_access = list(access_virology) + +/obj/item/weapon/storage/lockbox/vials/New() + ..() + update_icon() + +/obj/item/weapon/storage/lockbox/vials/update_icon(var/itemremoved = 0) + var/total_contents = src.contents.len - itemremoved + src.icon_state = "vialbox[total_contents]" + src.overlays.len = 0 + if (!broken) + overlays += image(icon, src, "led[locked]") + if(locked) + overlays += image(icon, src, "cover") + else + overlays += image(icon, src, "ledb") + return + +/obj/item/weapon/storage/lockbox/vials/attackby(obj/item/weapon/W as obj, mob/user as mob) + . = ..() + update_icon() + +//FLARE BOX +//Useful for lots of things, this box has 6 flares in it. Only takes unused and unlight flares. +//Great for emergency crates/closets etc. + +/obj/item/weapon/storage/fancy/flares + icon = 'icons/obj/lighting.dmi' + icon_state = "flarebox6" + icon_type = "flare" + name = "box of flares" + storage_slots = 6 + can_hold = list("/obj/item/device/flashlight/flare") + + foldable = /obj/item/stack/sheet/cardboard + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + +/obj/item/weapon/storage/fancy/flares/empty + empty = 1 + icon_state = "flarebox0" + +/obj/item/weapon/storage/fancy/flares/New() + ..() + if(empty) + update_icon() //Make it look actually empty + return + for(var/i=1; i <= storage_slots; i++) + new /obj/item/device/flashlight/flare(src) + return + +/obj/item/weapon/storage/fancy/flares/attackby(var/obj/item/device/flashlight/flare/F, var/user as mob) //if it's on or empty, we don't want it + if(!istype(F)) + return + if(F.on) to_chat(user, "You can't put a lit flare in the box!") - return - if(!F.fuel) + return + if(!F.fuel) to_chat(user, "This flare is empty!") - return - . = ..() - -/obj/item/weapon/storage/fancy/flares/update_icon() - ..() - -/obj/item/weapon/storage/fancy/food_box/chicken_bucket - name = "chicken bucket" - desc = "Now we're doing it!" - icon_state = "kfc_drumsticks" - item_state = "kfc_bucket" - icon_type = "drumstick" - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick") - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - -/obj/item/weapon/storage/fancy/food_box/chicken_bucket/New() - ..() - for(var/i=1; i <= storage_slots; i++) - new /obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick(src) - return - -/obj/item/weapon/storage/fancy/food_box/chicken_bucket/remove_from_storage(obj/item/W as obj, atom/new_location) - ..() - if(!contents.len) - new/obj/item/trash/chicken_bucket(get_turf(src.loc)) - if(istype(src.loc,/mob/living/carbon)) - var/mob/living/carbon/C = src.loc - C.u_equip(src, 0) - qdel(src) - -/obj/item/weapon/storage/fancy/food_box/chicken_bucket/update_icon(var/itemremoved = 0) - return - -/obj/item/weapon/storage/fancy/food_box - name = "food box" - desc = "Holds food." - icon = 'icons/obj/food.dmi' - icon_state = "slider_box" - storage_slots = 6 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks") - -/obj/item/weapon/storage/fancy/food_box/update_icon(var/itemremoved = 0) //this is so that your box doesn't turn into a donut box, see line 29 - return - -//SLIDER BOXES - -/obj/item/weapon/storage/fancy/food_box/slider_box - name = "slider box" - desc = "I wonder what's inside." - icon_type = "slider" - storage_slots = 4 - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/slider") - var/slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider//set this as the spawn path of your slider - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - -/obj/item/weapon/storage/fancy/food_box/slider_box/New() - ..() - for(var/i=1, i <= storage_slots; i++) - new slider_type(src) - -/obj/item/weapon/storage/fancy/food_box/slider_box/synth - name = "synth slider box" - icon_type = "synth slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/synth - -/obj/item/weapon/storage/fancy/food_box/slider_box/xeno - name = "xeno slider box" - icon_type = "xeno slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/xeno - -/obj/item/weapon/storage/fancy/food_box/slider_box/chicken - name = "chicken slider box" - icon_type = "chicken slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/chicken - -/obj/item/weapon/storage/fancy/food_box/slider_box/toxiccarp - name = "carp slider box" - icon_type = "carp slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/toxiccarp - storage_slots = 2 - -/obj/item/weapon/storage/fancy/food_box/slider_box/carp - name = "carp slider box" - icon_type = "carp slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/carp - storage_slots = 2 - -/obj/item/weapon/storage/fancy/food_box/slider_box/spider - name = "spidey slidey box" - icon_type = "spider slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/carp/spider - -/obj/item/weapon/storage/fancy/food_box/slider_box/clown - name = "honky slider box" - icon_type = "honky slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/clown - -/obj/item/weapon/storage/fancy/food_box/slider_box/mime - name = "quiet slider box" - icon_type = "quiet slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/mime - -/obj/item/weapon/storage/fancy/food_box/slider_box/slippery - name = "slippery slider box" - icon_type = "slippery slider" - slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/slippery - storage_slots = 2 - -//SLIDER BOXES END + return + . = ..() + +/obj/item/weapon/storage/fancy/flares/update_icon() + ..() + +/obj/item/weapon/storage/fancy/food_box/chicken_bucket + name = "chicken bucket" + desc = "Now we're doing it!" + icon_state = "kfc_drumsticks" + item_state = "kfc_bucket" + icon_type = "drumstick" + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick") + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + +/obj/item/weapon/storage/fancy/food_box/chicken_bucket/New() + ..() + for(var/i=1; i <= storage_slots; i++) + new /obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick(src) + return + +/obj/item/weapon/storage/fancy/food_box/chicken_bucket/remove_from_storage(obj/item/W as obj, atom/new_location) + ..() + if(!contents.len) + new/obj/item/trash/chicken_bucket(get_turf(src.loc)) + if(istype(src.loc,/mob/living/carbon)) + var/mob/living/carbon/C = src.loc + C.u_equip(src, 0) + qdel(src) + +/obj/item/weapon/storage/fancy/food_box/chicken_bucket/update_icon(var/itemremoved = 0) + return + +/obj/item/weapon/storage/fancy/food_box + name = "food box" + desc = "Holds food." + icon = 'icons/obj/food.dmi' + icon_state = "slider_box" + storage_slots = 6 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks") + +/obj/item/weapon/storage/fancy/food_box/update_icon(var/itemremoved = 0) //this is so that your box doesn't turn into a donut box, see line 29 + return + +//SLIDER BOXES + +/obj/item/weapon/storage/fancy/food_box/slider_box + name = "slider box" + desc = "I wonder what's inside." + icon_type = "slider" + storage_slots = 4 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/slider") + var/slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider//set this as the spawn path of your slider + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + +/obj/item/weapon/storage/fancy/food_box/slider_box/New() + ..() + for(var/i=1, i <= storage_slots; i++) + new slider_type(src) + +/obj/item/weapon/storage/fancy/food_box/slider_box/synth + name = "synth slider box" + icon_type = "synth slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/synth + +/obj/item/weapon/storage/fancy/food_box/slider_box/xeno + name = "xeno slider box" + icon_type = "xeno slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/xeno + +/obj/item/weapon/storage/fancy/food_box/slider_box/chicken + name = "chicken slider box" + icon_type = "chicken slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/chicken + +/obj/item/weapon/storage/fancy/food_box/slider_box/toxiccarp + name = "carp slider box" + icon_type = "carp slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/toxiccarp + storage_slots = 2 + +/obj/item/weapon/storage/fancy/food_box/slider_box/carp + name = "carp slider box" + icon_type = "carp slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/carp + storage_slots = 2 + +/obj/item/weapon/storage/fancy/food_box/slider_box/spider + name = "spidey slidey box" + icon_type = "spider slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/carp/spider + +/obj/item/weapon/storage/fancy/food_box/slider_box/clown + name = "honky slider box" + icon_type = "honky slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/clown + +/obj/item/weapon/storage/fancy/food_box/slider_box/mime + name = "quiet slider box" + icon_type = "quiet slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/mime + +/obj/item/weapon/storage/fancy/food_box/slider_box/slippery + name = "slippery slider box" + icon_type = "slippery slider" + slider_type = /obj/item/weapon/reagent_containers/food/snacks/slider/slippery + storage_slots = 2 + +//SLIDER BOXES END diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index c0b1e393b25..8de8072db11 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -1,262 +1,262 @@ -/* First aid storage - * Contains: - * First Aid Kits - * Pill Bottles - * Dice Pack (in a pill bottle) - */ - -/* - * First Aid Kits - */ -/obj/item/weapon/storage/firstaid - name = "first-aid kit" - desc = "It's an emergency medical kit for those serious boo-boos." - icon_state = "firstaid" - throw_speed = 2 - throw_range = 8 - var/empty = 0 - - -/obj/item/weapon/storage/firstaid/fire - name = "fire first-aid kit" - desc = "It's an emergency medical kit for when the toxins lab -spontaneously- burns down." - icon_state = "ointment" - item_state = "firstaid-ointment" - - New() - ..() - if (empty) return - - icon_state = pick("ointment","firefirstaid") - - new /obj/item/device/healthanalyzer( src ) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - new /obj/item/stack/medical/ointment( src ) - new /obj/item/stack/medical/ointment( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) //Replaced ointment with these since they actually work --Errorage - return - - -/obj/item/weapon/storage/firstaid/regular - icon_state = "firstaid" - - New() - ..() - if (empty) return - new /obj/item/stack/medical/bruise_pack(src) - new /obj/item/stack/medical/bruise_pack(src) - new /obj/item/stack/medical/bruise_pack(src) - new /obj/item/stack/medical/ointment(src) - new /obj/item/stack/medical/ointment(src) - new /obj/item/device/healthanalyzer(src) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - return - -/obj/item/weapon/storage/firstaid/toxin - name = "toxin first aid" - desc = "Used to treat when you have a high amount of toxins in your body." - icon_state = "antitoxin" - item_state = "firstaid-toxin" - - New() - ..() - if (empty) return - - icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3") - - new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) - new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) - new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/device/healthanalyzer( src ) - return - -/obj/item/weapon/storage/firstaid/o2 - name = "oxygen deprivation first aid" - desc = "A box full of oxygen goodies." - icon_state = "o2" - item_state = "firstaid-oxy" - - New() - ..() - if (empty) return - new /obj/item/weapon/reagent_containers/pill/dexalin( src ) - new /obj/item/weapon/reagent_containers/pill/dexalin( src ) - new /obj/item/weapon/reagent_containers/pill/dexalin( src ) - new /obj/item/weapon/reagent_containers/pill/dexalin( src ) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - new /obj/item/weapon/reagent_containers/syringe/inaprovaline( src ) - new /obj/item/device/healthanalyzer( src ) - return - -/obj/item/weapon/storage/firstaid/adv - name = "advanced first-aid kit" - desc = "Contains advanced medical treatments." - icon_state = "advfirstaid" - item_state = "firstaid-advanced" - -/obj/item/weapon/storage/firstaid/adv/New() - ..() - if (empty) return - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - new /obj/item/stack/medical/advanced/bruise_pack(src) - new /obj/item/stack/medical/advanced/bruise_pack(src) - new /obj/item/stack/medical/advanced/bruise_pack(src) - new /obj/item/stack/medical/advanced/ointment(src) - new /obj/item/stack/medical/advanced/ointment(src) - new /obj/item/stack/medical/splint(src) - return -/* - * Pill Bottles - */ -/obj/item/weapon/storage/pill_bottle - name = "pill bottle" - desc = "It's an airtight container for storing medication." - icon_state = "pill_canister" - icon = 'icons/obj/chemical.dmi' - item_state = "contsolid" - w_class = 2.0 - can_hold = list("/obj/item/weapon/reagent_containers/pill","/obj/item/weapon/dice","/obj/item/weapon/paper") - allow_quick_gather = 1 - use_to_pickup = 1 - storage_slots = 14 - starting_materials = list(MAT_IRON = 10, MAT_GLASS = 60) - var/image/colour_overlay - -/obj/item/weapon/storage/pill_bottle/New() - ..() - colour_overlay = image('icons/obj/chemical.dmi',"bottle_colour") - overlays += colour_overlay - - -/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,0) - M.put_in_r_hand(src) - if("l_hand") - M.u_equip(src,0) - 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 - -/obj/item/weapon/storage/pill_bottle/attackby(var/obj/item/I, var/mob/user) - if(!I) return - if(istype(I, /obj/item/weapon/storage/bag/chem)) - var/obj/item/weapon/storage/bag/chem/C = I +/* First aid storage + * Contains: + * First Aid Kits + * Pill Bottles + * Dice Pack (in a pill bottle) + */ + +/* + * First Aid Kits + */ +/obj/item/weapon/storage/firstaid + name = "first-aid kit" + desc = "It's an emergency medical kit for those serious boo-boos." + icon_state = "firstaid" + throw_speed = 2 + throw_range = 8 + var/empty = 0 + + +/obj/item/weapon/storage/firstaid/fire + name = "fire first-aid kit" + desc = "It's an emergency medical kit for when the toxins lab -spontaneously- burns down." + icon_state = "ointment" + item_state = "firstaid-ointment" + + New() + ..() + if (empty) return + + icon_state = pick("ointment","firefirstaid") + + new /obj/item/device/healthanalyzer( src ) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) + new /obj/item/stack/medical/ointment( src ) + new /obj/item/stack/medical/ointment( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) //Replaced ointment with these since they actually work --Errorage + return + + +/obj/item/weapon/storage/firstaid/regular + icon_state = "firstaid" + + New() + ..() + if (empty) return + new /obj/item/stack/medical/bruise_pack(src) + new /obj/item/stack/medical/bruise_pack(src) + new /obj/item/stack/medical/bruise_pack(src) + new /obj/item/stack/medical/ointment(src) + new /obj/item/stack/medical/ointment(src) + new /obj/item/device/healthanalyzer(src) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) + return + +/obj/item/weapon/storage/firstaid/toxin + name = "toxin first aid" + desc = "Used to treat when you have a high amount of toxins in your body." + icon_state = "antitoxin" + item_state = "firstaid-toxin" + + New() + ..() + if (empty) return + + icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3") + + new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) + new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) + new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/device/healthanalyzer( src ) + return + +/obj/item/weapon/storage/firstaid/o2 + name = "oxygen deprivation first aid" + desc = "A box full of oxygen goodies." + icon_state = "o2" + item_state = "firstaid-oxy" + + New() + ..() + if (empty) return + new /obj/item/weapon/reagent_containers/pill/dexalin( src ) + new /obj/item/weapon/reagent_containers/pill/dexalin( src ) + new /obj/item/weapon/reagent_containers/pill/dexalin( src ) + new /obj/item/weapon/reagent_containers/pill/dexalin( src ) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) + new /obj/item/weapon/reagent_containers/syringe/inaprovaline( src ) + new /obj/item/device/healthanalyzer( src ) + return + +/obj/item/weapon/storage/firstaid/adv + name = "advanced first-aid kit" + desc = "Contains advanced medical treatments." + icon_state = "advfirstaid" + item_state = "firstaid-advanced" + +/obj/item/weapon/storage/firstaid/adv/New() + ..() + if (empty) return + new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) + new /obj/item/stack/medical/advanced/bruise_pack(src) + new /obj/item/stack/medical/advanced/bruise_pack(src) + new /obj/item/stack/medical/advanced/bruise_pack(src) + new /obj/item/stack/medical/advanced/ointment(src) + new /obj/item/stack/medical/advanced/ointment(src) + new /obj/item/stack/medical/splint(src) + return +/* + * Pill Bottles + */ +/obj/item/weapon/storage/pill_bottle + name = "pill bottle" + desc = "It's an airtight container for storing medication." + icon_state = "pill_canister" + icon = 'icons/obj/chemical.dmi' + item_state = "contsolid" + w_class = 2.0 + can_hold = list("/obj/item/weapon/reagent_containers/pill","/obj/item/weapon/dice","/obj/item/weapon/paper") + allow_quick_gather = 1 + use_to_pickup = 1 + storage_slots = 14 + starting_materials = list(MAT_IRON = 10, MAT_GLASS = 60) + var/image/colour_overlay + +/obj/item/weapon/storage/pill_bottle/New() + ..() + colour_overlay = image('icons/obj/chemical.dmi',"bottle_colour") + overlays += colour_overlay + + +/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,0) + M.put_in_r_hand(src) + if("l_hand") + M.u_equip(src,0) + 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 + +/obj/item/weapon/storage/pill_bottle/attackby(var/obj/item/I, var/mob/user) + if(!I) return + if(istype(I, /obj/item/weapon/storage/bag/chem)) + var/obj/item/weapon/storage/bag/chem/C = I to_chat(user, "You transfer the contents of [C].") - for(var/obj/item/O in C.contents) - if(can_be_inserted(O)) - handle_item_insertion(O, 1) - return 1 - . = ..() -var/global/list/bottle_colour_choices = list("Blue" = "#0094FF","Dark Blue" = "#00137F","Green" = "#129E0A","Orange" = "#FF6A00","Purple" = "#A17FFF","Red" = "#BE0000","Yellow" = "#FFD800","Grey" = "#9F9F9F","White" = "#FFFFFF","Custom" = "#FFFFFF",) -/obj/item/weapon/storage/pill_bottle/verb/change() - set name = "Add Coloured Label" - set category = "Object" - set src in usr - if(!colour_overlay) - return - var/bottle_colour - bottle_colour = input("Select Colour to change it to", "Pill Bottle Colour", bottle_colour) as null|anything in bottle_colour_choices - if(!bottle_colour||(usr.stat)) - return - if(bottle_colour == "Custom") - bottle_colour = input("Select Colour to change it to", "Pill Bottle Colour", bottle_colour) as color - else - bottle_colour = bottle_colour_choices[bottle_colour] - overlays -= colour_overlay - colour_overlay.color = "[bottle_colour]" - overlays += colour_overlay - - -/obj/item/weapon/storage/pill_bottle/kelotane - name = "Pill bottle (kelotane)" - desc = "Contains pills used to treat burns." - - New() - ..() - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - new /obj/item/weapon/reagent_containers/pill/kelotane( src ) - -/obj/item/weapon/storage/pill_bottle/antitox - name = "Pill bottle (Anti-toxin)" - desc = "Contains pills used to counter toxins." - - New() - ..() - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - new /obj/item/weapon/reagent_containers/pill/antitox( src ) - -/obj/item/weapon/storage/pill_bottle/inaprovaline - name = "Pill bottle (inaprovaline)" - desc = "Contains pills used to stabilize patients." - - New() - ..() - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) - - -/obj/item/weapon/storage/pill_bottle/dice - name = "bag of dice" - desc = "Contains all the luck you'll ever need." - icon = 'icons/obj/dice.dmi' - icon_state = "dicebag" - - -/obj/item/weapon/storage/pill_bottle/dice/New() - ..() - overlays -= colour_overlay - colour_overlay = null - new /obj/item/weapon/dice/d4( src ) - new /obj/item/weapon/dice( src ) - new /obj/item/weapon/dice/d8( src ) - new /obj/item/weapon/dice/d10( src ) - new /obj/item/weapon/dice/d00( src ) - new /obj/item/weapon/dice/d12( src ) - new /obj/item/weapon/dice/d20( src ) - -/obj/item/weapon/storage/pill_bottle/hyperzine - name = "Pill bottle (hyperzine)" - desc = "Contains pills used to keep you active." - - New() - ..() - new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) - new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) - new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) - new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) - new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) - new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) + for(var/obj/item/O in C.contents) + if(can_be_inserted(O)) + handle_item_insertion(O, 1) + return 1 + . = ..() +var/global/list/bottle_colour_choices = list("Blue" = "#0094FF","Dark Blue" = "#00137F","Green" = "#129E0A","Orange" = "#FF6A00","Purple" = "#A17FFF","Red" = "#BE0000","Yellow" = "#FFD800","Grey" = "#9F9F9F","White" = "#FFFFFF","Custom" = "#FFFFFF",) +/obj/item/weapon/storage/pill_bottle/verb/change() + set name = "Add Coloured Label" + set category = "Object" + set src in usr + if(!colour_overlay) + return + var/bottle_colour + bottle_colour = input("Select Colour to change it to", "Pill Bottle Colour", bottle_colour) as null|anything in bottle_colour_choices + if(!bottle_colour||(usr.stat)) + return + if(bottle_colour == "Custom") + bottle_colour = input("Select Colour to change it to", "Pill Bottle Colour", bottle_colour) as color + else + bottle_colour = bottle_colour_choices[bottle_colour] + overlays -= colour_overlay + colour_overlay.color = "[bottle_colour]" + overlays += colour_overlay + + +/obj/item/weapon/storage/pill_bottle/kelotane + name = "Pill bottle (kelotane)" + desc = "Contains pills used to treat burns." + + New() + ..() + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + new /obj/item/weapon/reagent_containers/pill/kelotane( src ) + +/obj/item/weapon/storage/pill_bottle/antitox + name = "Pill bottle (Anti-toxin)" + desc = "Contains pills used to counter toxins." + + New() + ..() + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + new /obj/item/weapon/reagent_containers/pill/antitox( src ) + +/obj/item/weapon/storage/pill_bottle/inaprovaline + name = "Pill bottle (inaprovaline)" + desc = "Contains pills used to stabilize patients." + + New() + ..() + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + new /obj/item/weapon/reagent_containers/pill/inaprovaline( src ) + + +/obj/item/weapon/storage/pill_bottle/dice + name = "bag of dice" + desc = "Contains all the luck you'll ever need." + icon = 'icons/obj/dice.dmi' + icon_state = "dicebag" + + +/obj/item/weapon/storage/pill_bottle/dice/New() + ..() + overlays -= colour_overlay + colour_overlay = null + new /obj/item/weapon/dice/d4( src ) + new /obj/item/weapon/dice( src ) + new /obj/item/weapon/dice/d8( src ) + new /obj/item/weapon/dice/d10( src ) + new /obj/item/weapon/dice/d00( src ) + new /obj/item/weapon/dice/d12( src ) + new /obj/item/weapon/dice/d20( src ) + +/obj/item/weapon/storage/pill_bottle/hyperzine + name = "Pill bottle (hyperzine)" + desc = "Contains pills used to keep you active." + + New() + ..() + new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) + new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) + new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) + new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) + new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) + new /obj/item/weapon/reagent_containers/pill/hyperzine( src ) diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index 1f4f7652e9a..08587ed928a 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -1,204 +1,204 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/weapon/storage/lockbox - name = "lockbox" - desc = "A locked box." - icon_state = "lockbox+l" - item_state = "syringe_kit" - w_class = 4 - max_w_class = 3 - max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. - storage_slots = 4 - req_access = list(access_armory) - var/locked = 1 - var/broken = 0 - var/icon_locked = "lockbox+l" - var/icon_closed = "lockbox" - var/icon_broken = "lockbox+b" - var/tracked_access = "It doesn't look like it's ever been used." - health = 50 - - - -/obj/item/weapon/storage/lockbox/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/ID = W - if(src.broken) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/weapon/storage/lockbox + name = "lockbox" + desc = "A locked box." + icon_state = "lockbox+l" + item_state = "syringe_kit" + w_class = 4 + max_w_class = 3 + max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. + storage_slots = 4 + req_access = list(access_armory) + var/locked = 1 + var/broken = 0 + var/icon_locked = "lockbox+l" + var/icon_closed = "lockbox" + var/icon_broken = "lockbox+b" + var/tracked_access = "It doesn't look like it's ever been used." + health = 50 + + + +/obj/item/weapon/storage/lockbox/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/ID = W + if(src.broken) to_chat(user, "It appears to be broken.") - return - if(src.allowed(user)) - src.locked = !( src.locked ) - if(src.locked) - src.icon_state = src.icon_locked + return + if(src.allowed(user)) + src.locked = !( src.locked ) + if(src.locked) + src.icon_state = src.icon_locked to_chat(user, "You lock the [src.name]!") - tracked_access = "The tracker reads: 'Last locked by [ID.registered_name].'" - return - else - src.icon_state = src.icon_closed + tracked_access = "The tracker reads: 'Last locked by [ID.registered_name].'" + return + else + src.icon_state = src.icon_closed to_chat(user, "You unlock the [src.name]!") - tracked_access = "The tracker reads: 'Last unlocked by [ID.registered_name].'" - return - else + tracked_access = "The tracker reads: 'Last unlocked by [ID.registered_name].'" + return + else to_chat(user, "Access Denied.") - else if(istype(W, /obj/item/weapon/card/emag) && !src.broken) - broken = 1 - locked = 0 - desc = "It appears to be broken." - icon_state = src.icon_broken - for(var/mob/O in viewers(user, 3)) - O.show_message(text("The locker has been broken by [] with an electromagnetic card!", user), 1, text("You hear a faint electrical spark."), 2) - - if(!locked) - . = ..() - else + else if(istype(W, /obj/item/weapon/card/emag) && !src.broken) + broken = 1 + locked = 0 + desc = "It appears to be broken." + icon_state = src.icon_broken + for(var/mob/O in viewers(user, 3)) + O.show_message(text("The locker has been broken by [] with an electromagnetic card!", user), 1, text("You hear a faint electrical spark."), 2) + + if(!locked) + . = ..() + else to_chat(user, "It's locked!") - return - - -/obj/item/weapon/storage/lockbox/show_to(mob/user as mob) - if(locked) + return + + +/obj/item/weapon/storage/lockbox/show_to(mob/user as mob) + if(locked) to_chat(user, "It's locked!") - else - ..() - return - -/obj/item/weapon/storage/lockbox/bullet_act(var/obj/item/projectile/Proj) - // WHY MUST WE DO THIS - // WHY - if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)) - if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) && !Proj.nodamage) - health -= Proj.damage - ..() - if(health <= 0) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - qdel(src) - return - -/obj/item/weapon/storage/lockbox/ex_act(severity) - var/newsev = max(3,severity+1) - for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion - A.loc = src.loc - A.ex_act(newsev) - newsev=4-severity - if(prob(newsev*25)+25) // 1=100, 2=75, 3=50 - qdel(src) - -/obj/item/weapon/storage/lockbox/emp_act(severity) - ..() - if(!broken) - switch(severity) - if(1) - if(prob(80)) - locked = !locked - src.update_icon() - if(2) - if(prob(50)) - locked = !locked - src.update_icon() - if(3) - if(prob(25)) - locked = !locked - src.update_icon() - -/obj/item/weapon/storage/lockbox/update_icon() - ..() - if (broken) - icon_state = src.icon_broken - else if(locked) - icon_state = src.icon_locked - else - icon_state = src.icon_closed - return - -/obj/item/weapon/storage/lockbox/loyalty - name = "Lockbox (Loyalty Implants)" - req_access = list(access_security) - -/obj/item/weapon/storage/lockbox/loyalty/New() - ..() - new /obj/item/weapon/implantcase/loyalty(src) - new /obj/item/weapon/implantcase/loyalty(src) - new /obj/item/weapon/implantcase/loyalty(src) - new /obj/item/weapon/implanter/loyalty(src) - -/obj/item/weapon/storage/lockbox/tracking - name = "Lockbox (Tracking Implants)" - req_access = list(access_security) - -/obj/item/weapon/storage/lockbox/tracking/New() - ..() - new /obj/item/weapon/implantcase/tracking(src) - new /obj/item/weapon/implantcase/tracking(src) - new /obj/item/weapon/implantcase/tracking(src) - new /obj/item/weapon/implantpad(src) - new /obj/item/weapon/implanter(src) - -/obj/item/weapon/storage/lockbox/chem - name = "Lockbox (Chemical Implants)" - req_access = list(access_security) - -/obj/item/weapon/storage/lockbox/chem/New() - ..() - new /obj/item/weapon/implantcase/chem(src) - new /obj/item/weapon/implantcase/chem(src) - new /obj/item/weapon/implantcase/chem(src) - new /obj/item/weapon/reagent_containers/syringe(src) - new /obj/item/weapon/implanter(src) - -/obj/item/weapon/storage/lockbox/clusterbang - name = "lockbox (clusterbang)" - desc = "You have a bad feeling about opening this." - req_access = list(access_security) - -/obj/item/weapon/storage/lockbox/clusterbang/New() - ..() - new /obj/item/weapon/grenade/flashbang/clusterbang(src) - -/obj/item/weapon/storage/lockbox/unlockable - name = "semi-secure lockbox" - desc = "A securable locked box. Can't lock anything, but can track whoever used it." - req_access = list() - -/obj/item/weapon/storage/lockbox/examine(mob/user) - ..() + else + ..() + return + +/obj/item/weapon/storage/lockbox/bullet_act(var/obj/item/projectile/Proj) + // WHY MUST WE DO THIS + // WHY + if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)) + if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) && !Proj.nodamage) + health -= Proj.damage + ..() + if(health <= 0) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + qdel(src) + return + +/obj/item/weapon/storage/lockbox/ex_act(severity) + var/newsev = max(3,severity+1) + for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion + A.loc = src.loc + A.ex_act(newsev) + newsev=4-severity + if(prob(newsev*25)+25) // 1=100, 2=75, 3=50 + qdel(src) + +/obj/item/weapon/storage/lockbox/emp_act(severity) + ..() + if(!broken) + switch(severity) + if(1) + if(prob(80)) + locked = !locked + src.update_icon() + if(2) + if(prob(50)) + locked = !locked + src.update_icon() + if(3) + if(prob(25)) + locked = !locked + src.update_icon() + +/obj/item/weapon/storage/lockbox/update_icon() + ..() + if (broken) + icon_state = src.icon_broken + else if(locked) + icon_state = src.icon_locked + else + icon_state = src.icon_closed + return + +/obj/item/weapon/storage/lockbox/loyalty + name = "Lockbox (Loyalty Implants)" + req_access = list(access_security) + +/obj/item/weapon/storage/lockbox/loyalty/New() + ..() + new /obj/item/weapon/implantcase/loyalty(src) + new /obj/item/weapon/implantcase/loyalty(src) + new /obj/item/weapon/implantcase/loyalty(src) + new /obj/item/weapon/implanter/loyalty(src) + +/obj/item/weapon/storage/lockbox/tracking + name = "Lockbox (Tracking Implants)" + req_access = list(access_security) + +/obj/item/weapon/storage/lockbox/tracking/New() + ..() + new /obj/item/weapon/implantcase/tracking(src) + new /obj/item/weapon/implantcase/tracking(src) + new /obj/item/weapon/implantcase/tracking(src) + new /obj/item/weapon/implantpad(src) + new /obj/item/weapon/implanter(src) + +/obj/item/weapon/storage/lockbox/chem + name = "Lockbox (Chemical Implants)" + req_access = list(access_security) + +/obj/item/weapon/storage/lockbox/chem/New() + ..() + new /obj/item/weapon/implantcase/chem(src) + new /obj/item/weapon/implantcase/chem(src) + new /obj/item/weapon/implantcase/chem(src) + new /obj/item/weapon/reagent_containers/syringe(src) + new /obj/item/weapon/implanter(src) + +/obj/item/weapon/storage/lockbox/clusterbang + name = "lockbox (clusterbang)" + desc = "You have a bad feeling about opening this." + req_access = list(access_security) + +/obj/item/weapon/storage/lockbox/clusterbang/New() + ..() + new /obj/item/weapon/grenade/flashbang/clusterbang(src) + +/obj/item/weapon/storage/lockbox/unlockable + name = "semi-secure lockbox" + desc = "A securable locked box. Can't lock anything, but can track whoever used it." + req_access = list() + +/obj/item/weapon/storage/lockbox/examine(mob/user) + ..() to_chat(user, "[tracked_access]") - -/obj/item/weapon/storage/lockbox/unlockable/attackby(obj/O as obj, mob/user as mob) - if (istype(O, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/ID = O - if(src.broken) + +/obj/item/weapon/storage/lockbox/unlockable/attackby(obj/O as obj, mob/user as mob) + if (istype(O, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/ID = O + if(src.broken) to_chat(user, "It appears to be broken.") - return - else - src.locked = !( src.locked ) - if(src.locked) - src.icon_state = src.icon_locked + return + else + src.locked = !( src.locked ) + if(src.locked) + src.icon_state = src.icon_locked to_chat(user, "You lock the [src.name]!") - tracked_access = "The tracker reads: 'Last locked by [ID.registered_name]'." - return - else - src.icon_state = src.icon_closed + tracked_access = "The tracker reads: 'Last locked by [ID.registered_name]'." + return + else + src.icon_state = src.icon_closed to_chat(user, "You unlock the [src.name]!") - tracked_access = "The tracker reads: 'Last unlocked by [ID.registered_name].'" - return - else - . = ..() - -/obj/item/weapon/storage/lockbox/coinbox - name = "coinbox" - desc = "A secure container for the profits of a vending machine." - icon_state = "coinbox+l" - w_class = 2 - max_w_class = 1 - can_hold = list("/obj/item/voucher","/obj/item/weapon/coin","/obj/item/weapon/reagent_containers/food/snacks/customizable/candy/coin","/obj/item/weapon/reagent_containers/food/snacks/chococoin") - max_combined_w_class = 30 - force = 8 - throwforce = 10 - storage_slots = 20 - req_access = list(access_qm) - locked = 1 - broken = 0 - icon_locked = "coinbox+l" - icon_closed = "coinbox" - icon_broken = "coinbox+b" + tracked_access = "The tracker reads: 'Last unlocked by [ID.registered_name].'" + return + else + . = ..() + +/obj/item/weapon/storage/lockbox/coinbox + name = "coinbox" + desc = "A secure container for the profits of a vending machine." + icon_state = "coinbox+l" + w_class = 2 + max_w_class = 1 + can_hold = list("/obj/item/voucher","/obj/item/weapon/coin","/obj/item/weapon/reagent_containers/food/snacks/customizable/candy/coin","/obj/item/weapon/reagent_containers/food/snacks/chococoin") + max_combined_w_class = 30 + force = 8 + throwforce = 10 + storage_slots = 20 + req_access = list(access_qm) + locked = 1 + broken = 0 + icon_locked = "coinbox+l" + icon_closed = "coinbox" + icon_broken = "coinbox+b" diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index a6e259fee16..35ec81365e0 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -1,242 +1,242 @@ -/* - * Absorbs /obj/item/weapon/secstorage. - * Reimplements it only slightly to use existing storage functionality. - * - * Contains: - * Secure Briefcase - * Wall Safe - */ - -// ----------------------------- -// Generic Item -// ----------------------------- -/obj/item/weapon/storage/secure - name = "secstorage" - var/icon_locking = "secureb" - var/icon_sparking = "securespark" - var/icon_opened = "secure0" - var/locked = 1 - var/code = "" - var/l_code = null - var/l_set = 0 - var/l_setshort = 0 - var/l_hacking = 0 - var/emagged = 0 - var/open = 0 - w_class = 3.0 - max_w_class = 2 - max_combined_w_class = 14 - -/obj/item/weapon/storage/secure/examine(mob/user) - ..() +/* + * Absorbs /obj/item/weapon/secstorage. + * Reimplements it only slightly to use existing storage functionality. + * + * Contains: + * Secure Briefcase + * Wall Safe + */ + +// ----------------------------- +// Generic Item +// ----------------------------- +/obj/item/weapon/storage/secure + name = "secstorage" + var/icon_locking = "secureb" + var/icon_sparking = "securespark" + var/icon_opened = "secure0" + var/locked = 1 + var/code = "" + var/l_code = null + var/l_set = 0 + var/l_setshort = 0 + var/l_hacking = 0 + var/emagged = 0 + var/open = 0 + w_class = 3.0 + max_w_class = 2 + max_combined_w_class = 14 + +/obj/item/weapon/storage/secure/examine(mob/user) + ..() to_chat(user, "The service panel is [src.open ? "open" : "closed"].") - -/obj/item/weapon/storage/secure/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(locked) - if ( istype(W, /obj/item/weapon/card/emag) && (!src.emagged)) - emagged = 1 - src.overlays += image('icons/obj/storage.dmi', icon_sparking) - sleep(6) - src.overlays = null - overlays += image('icons/obj/storage.dmi', icon_locking) - locked = 0 + +/obj/item/weapon/storage/secure/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(locked) + if ( istype(W, /obj/item/weapon/card/emag) && (!src.emagged)) + emagged = 1 + src.overlays += image('icons/obj/storage.dmi', icon_sparking) + sleep(6) + src.overlays = null + overlays += image('icons/obj/storage.dmi', icon_locking) + locked = 0 to_chat(user, "You short out the lock on [src].") - return - - if (istype(W, /obj/item/weapon/screwdriver)) - if (do_after(user, src, 20)) - src.open =! src.open - user.show_message(text("You [] the service panel.", (src.open ? "open" : "close"))) - return - if ((istype(W, /obj/item/device/multitool)) && (src.open == 1)&& (!src.l_hacking)) - user.show_message(text("Now attempting to reset internal memory, please hold."), 1) - src.l_hacking = 1 - if (do_after(usr, src, 100)) - if (prob(40)) - src.l_setshort = 1 - src.l_set = 0 - user.show_message(text("Internal memory reset. Please give it a few seconds to reinitialize."), 1) - sleep(80) - src.l_setshort = 0 - src.l_hacking = 0 - else - user.show_message(text("Unable to reset internal memory."), 1) - src.l_hacking = 0 - else src.l_hacking = 0 - return - //At this point you have exhausted all the special things to do when locked - // ... but it's still locked. - return - - // -> storage/attackby() what with handle insertion, etc - . = ..() - - -/obj/item/weapon/storage/secure/MouseDrop(over_object, src_location, over_location) - if (locked) - src.add_fingerprint(usr) - return - ..() - - -/obj/item/weapon/storage/secure/attack_self(mob/user as mob) - user.set_machine(src) - var/dat = text("[]
    \n\nLock Status: []",src, (src.locked ? "LOCKED" : "UNLOCKED")) - var/message = "Code" - if ((src.l_set == 0) && (!src.emagged) && (!src.l_setshort)) - dat += text("

    \n5-DIGIT PASSCODE NOT SET.
    ENTER NEW PASSCODE.
    ") - if (src.emagged) - dat += text("

    \nLOCKING SYSTEM ERROR - 1701") - if (src.l_setshort) - dat += text("

    \nALERT: MEMORY SYSTEM ERROR - 6040 201") - message = text("[]", src.code) - if (!src.locked) - message = "*****" - dat += text("


    \n>[]
    \n1-2-3
    \n4-5-6
    \n7-8-9
    \nR-0-E
    \n
    ", message, src, src, src, src, src, src, src, src, src, src, src, src) - user << browse(dat, "window=caselock;size=300x280") - -/obj/item/weapon/storage/secure/Topic(href, href_list) - ..() - if ((usr.stat || usr.restrained()) || (get_dist(src, usr) > 1)) - return - if (href_list["type"]) - if (href_list["type"] == "E") - if ((src.l_set == 0) && (length(src.code) == 5) && (!src.l_setshort) && (src.code != "ERROR")) - src.l_code = src.code - src.l_set = 1 - else if ((src.code == src.l_code) && (src.emagged == 0) && (src.l_set == 1)) - src.locked = 0 - src.overlays = null - overlays += image('icons/obj/storage.dmi', icon_opened) - src.code = null - else - src.code = "ERROR" - else - if ((href_list["type"] == "R") && (src.emagged == 0) && (!src.l_setshort)) - src.locked = 1 - src.overlays = null - src.code = null - src.close(usr) - else - src.code += text("[]", href_list["type"]) - if (length(src.code) > 5) - src.code = "ERROR" - src.add_fingerprint(usr) - for(var/mob/M in viewers(1, src.loc)) - if ((M.client && M.machine == src)) - src.attack_self(M) - return - return - -// ----------------------------- -// Secure Briefcase -// ----------------------------- -/obj/item/weapon/storage/secure/briefcase - name = "secure briefcase" - icon = 'icons/obj/storage.dmi' - icon_state = "secure" - item_state = "sec-case" - desc = "A large briefcase with a digital locking system." - origin_tech = "materials=2;magnets=2;programming=1" - flags = FPRINT - force = 8.0 - throw_speed = 1 - throw_range = 4 - w_class = 4.0 - -/obj/item/weapon/storage/secure/briefcase/New() - ..() - new /obj/item/weapon/paper(src) - new /obj/item/weapon/pen(src) - -/obj/item/weapon/storage/secure/briefcase/attack_hand(mob/user as mob) - if ((src.loc == user) && (src.locked == 1)) + return + + if (istype(W, /obj/item/weapon/screwdriver)) + if (do_after(user, src, 20)) + src.open =! src.open + user.show_message(text("You [] the service panel.", (src.open ? "open" : "close"))) + return + if ((istype(W, /obj/item/device/multitool)) && (src.open == 1)&& (!src.l_hacking)) + user.show_message(text("Now attempting to reset internal memory, please hold."), 1) + src.l_hacking = 1 + if (do_after(usr, src, 100)) + if (prob(40)) + src.l_setshort = 1 + src.l_set = 0 + user.show_message(text("Internal memory reset. Please give it a few seconds to reinitialize."), 1) + sleep(80) + src.l_setshort = 0 + src.l_hacking = 0 + else + user.show_message(text("Unable to reset internal memory."), 1) + src.l_hacking = 0 + else src.l_hacking = 0 + return + //At this point you have exhausted all the special things to do when locked + // ... but it's still locked. + return + + // -> storage/attackby() what with handle insertion, etc + . = ..() + + +/obj/item/weapon/storage/secure/MouseDrop(over_object, src_location, over_location) + if (locked) + src.add_fingerprint(usr) + return + ..() + + +/obj/item/weapon/storage/secure/attack_self(mob/user as mob) + user.set_machine(src) + var/dat = text("[]
    \n\nLock Status: []",src, (src.locked ? "LOCKED" : "UNLOCKED")) + var/message = "Code" + if ((src.l_set == 0) && (!src.emagged) && (!src.l_setshort)) + dat += text("

    \n5-DIGIT PASSCODE NOT SET.
    ENTER NEW PASSCODE.
    ") + if (src.emagged) + dat += text("

    \nLOCKING SYSTEM ERROR - 1701") + if (src.l_setshort) + dat += text("

    \nALERT: MEMORY SYSTEM ERROR - 6040 201") + message = text("[]", src.code) + if (!src.locked) + message = "*****" + dat += text("


    \n>[]
    \n1-2-3
    \n4-5-6
    \n7-8-9
    \nR-0-E
    \n
    ", message, src, src, src, src, src, src, src, src, src, src, src, src) + user << browse(dat, "window=caselock;size=300x280") + +/obj/item/weapon/storage/secure/Topic(href, href_list) + ..() + if ((usr.stat || usr.restrained()) || (get_dist(src, usr) > 1)) + return + if (href_list["type"]) + if (href_list["type"] == "E") + if ((src.l_set == 0) && (length(src.code) == 5) && (!src.l_setshort) && (src.code != "ERROR")) + src.l_code = src.code + src.l_set = 1 + else if ((src.code == src.l_code) && (src.emagged == 0) && (src.l_set == 1)) + src.locked = 0 + src.overlays = null + overlays += image('icons/obj/storage.dmi', icon_opened) + src.code = null + else + src.code = "ERROR" + else + if ((href_list["type"] == "R") && (src.emagged == 0) && (!src.l_setshort)) + src.locked = 1 + src.overlays = null + src.code = null + src.close(usr) + else + src.code += text("[]", href_list["type"]) + if (length(src.code) > 5) + src.code = "ERROR" + src.add_fingerprint(usr) + for(var/mob/M in viewers(1, src.loc)) + if ((M.client && M.machine == src)) + src.attack_self(M) + return + return + +// ----------------------------- +// Secure Briefcase +// ----------------------------- +/obj/item/weapon/storage/secure/briefcase + name = "secure briefcase" + icon = 'icons/obj/storage.dmi' + icon_state = "secure" + item_state = "sec-case" + desc = "A large briefcase with a digital locking system." + origin_tech = "materials=2;magnets=2;programming=1" + flags = FPRINT + force = 8.0 + throw_speed = 1 + throw_range = 4 + w_class = 4.0 + +/obj/item/weapon/storage/secure/briefcase/New() + ..() + new /obj/item/weapon/paper(src) + new /obj/item/weapon/pen(src) + +/obj/item/weapon/storage/secure/briefcase/attack_hand(mob/user as mob) + if ((src.loc == user) && (src.locked == 1)) to_chat(usr, "[src] is locked and cannot be opened!") - else if ((src.loc == user) && (!src.locked)) - playsound(get_turf(src), "rustle", 50, 1, -5) - if (user.s_active) - user.s_active.close(user) //Close and re-open - src.show_to(user) - else - ..() - for(var/mob/M in range(1)) - if (M.s_active == src) - src.close(M) - src.orient2hud(user) - src.add_fingerprint(user) - return - - //I consider this worthless but it isn't my code so whatever. Remove or uncomment. - /*attack(mob/M as mob, mob/living/user as mob) - if ((M_CLUMSY in user.mutations) && prob(50)) + else if ((src.loc == user) && (!src.locked)) + playsound(get_turf(src), "rustle", 50, 1, -5) + if (user.s_active) + user.s_active.close(user) //Close and re-open + src.show_to(user) + else + ..() + for(var/mob/M in range(1)) + if (M.s_active == src) + src.close(M) + src.orient2hud(user) + src.add_fingerprint(user) + return + + //I consider this worthless but it isn't my code so whatever. Remove or uncomment. + /*attack(mob/M as mob, mob/living/user as mob) + if ((M_CLUMSY in user.mutations) && prob(50)) to_chat(user, "The [src] slips out of your hand and hits your head.") - user.take_organ_damage(10) - user.Paralyse(2) - return - - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - - log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - - var/t = user:zone_sel.selecting - if (t == "head") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if (H.stat < 2 && H.health < 50 && prob(90)) - // ******* Check - if (istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80)) + user.take_organ_damage(10) + user.Paralyse(2) + return + + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + + log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") + + var/t = user:zone_sel.selecting + if (t == "head") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if (H.stat < 2 && H.health < 50 && prob(90)) + // ******* Check + if (istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80)) to_chat(H, "The helmet protects you from being hit hard in the head!") - return - var/time = rand(2, 6) - if (prob(75)) - H.Paralyse(time) - else - H.Stun(time) - if(H.stat != 2) H.stat = 1 - for(var/mob/O in viewers(H, null)) - O.show_message(text("[] has been knocked unconscious!", H), 1, "You hear someone fall.", 2) - else + return + var/time = rand(2, 6) + if (prob(75)) + H.Paralyse(time) + else + H.Stun(time) + if(H.stat != 2) H.stat = 1 + for(var/mob/O in viewers(H, null)) + O.show_message(text("[] has been knocked unconscious!", H), 1, "You hear someone fall.", 2) + else to_chat(H, text("[] tried to knock you unconcious!",user)) - H.eye_blurry += 3 - - return*/ - -// ----------------------------- -// Secure Safe -// ----------------------------- - -/obj/item/weapon/storage/secure/safe - name = "secure safe" - icon = 'icons/obj/storage.dmi' - icon_state = "safe" - icon_opened = "safe0" - icon_locking = "safeb" - icon_sparking = "safespark" - flags = FPRINT - force = 8.0 - w_class = 8.0 - max_w_class = 8 - anchored = 1.0 - density = 0 - cant_hold = list("/obj/item/weapon/storage/secure/briefcase") - -/obj/item/weapon/storage/secure/safe/New() - ..() - new /obj/item/weapon/paper(src) - new /obj/item/weapon/pen(src) - -/obj/item/weapon/storage/secure/safe/attack_hand(mob/user as mob) - return attack_self(user) - -// Clown planet WMD storage -/obj/item/weapon/storage/secure/safe/clown - name="WMD Storage" - -/obj/item/weapon/storage/secure/safe/clown/New() - for(var/i=0;i<10;i++) - new /obj/item/weapon/reagent_containers/food/snacks/pie(src) - -/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) + H.eye_blurry += 3 + + return*/ + +// ----------------------------- +// Secure Safe +// ----------------------------- + +/obj/item/weapon/storage/secure/safe + name = "secure safe" + icon = 'icons/obj/storage.dmi' + icon_state = "safe" + icon_opened = "safe0" + icon_locking = "safeb" + icon_sparking = "safespark" + flags = FPRINT + force = 8.0 + w_class = 8.0 + max_w_class = 8 + anchored = 1.0 + density = 0 + cant_hold = list("/obj/item/weapon/storage/secure/briefcase") + +/obj/item/weapon/storage/secure/safe/New() + ..() + new /obj/item/weapon/paper(src) + new /obj/item/weapon/pen(src) + +/obj/item/weapon/storage/secure/safe/attack_hand(mob/user as mob) + return attack_self(user) + +// Clown planet WMD storage +/obj/item/weapon/storage/secure/safe/clown + name="WMD Storage" + +/obj/item/weapon/storage/secure/safe/clown/New() + for(var/i=0;i<10;i++) + new /obj/item/weapon/reagent_containers/food/snacks/pie(src) + +/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) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 9f667cc518e..a34cc38fd23 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -1,621 +1,621 @@ -// To clarify: -// For use_to_pickup and allow_quick_gather functionality, -// see item/attackby() (/game/objects/items.dm) -// Do not remove this functionality without good reason, cough reagent_containers cough. -// -Sayu - - -/obj/item/weapon/storage - name = "storage" - icon = 'icons/obj/storage.dmi' - w_class = 3.0 - - // These two accept a string containing the type path and the following optional prefixes: - // = - Strict type matching. Will NOT check for subtypes. - var/list/can_hold = new/list() //List of objects which this item can store (if set, it can't store anything else) - var/list/cant_hold = new/list() //List of objects which this item can't store (in effect only if can_hold isn't set) - var/list/is_seeing = new/list() //List of mobs which are currently seeing the contents of this item's storage - var/max_w_class = 2 //Max size of objects that this object can store (in effect only if can_hold isn't set) - var/max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. - var/storage_slots = 7 //The number of storage slots in this container. - var/obj/screen/storage/boxes = null - var/obj/screen/close/closer = null - var/use_to_pickup //Set this to make it possible to use this item in an inverse way, so you can have the item in your hand and click items on the floor to pick them up. - var/display_contents_with_number //Set this to make the storage item group contents of the same type and display them as a number. - var/allow_quick_empty //Set this variable to allow the object to have the 'empty' verb, which dumps all the contents on the floor. - 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/foldable_amount = 1 // Number of foldables to produce, if any - N3X - var/internal_store = 0 - -/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(over_object, /obj/structure/table) && M.Adjacent(over_object)) - var/mob/living/L = usr - if(istype(L) && !(L.restrained() || L.stat || L.weakened || L.stunned || L.paralysis || L.resting)) - empty_contents_to(over_object) - if(!( istype(over_object, /obj/screen) )) - return ..() - if(!(src.loc == usr) || (src.loc && src.loc.loc == usr)) - return - playsound(get_turf(src), "rustle", 50, 1, -5) - if(!( M.restrained() ) && !( M.stat )) - switch(over_object.name) - if("r_hand") - M.u_equip(src,0) - M.put_in_r_hand(src) - if("l_hand") - M.u_equip(src,0) - 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 - -/obj/item/weapon/storage/proc/empty_contents_to(var/atom/place) - var/turf = get_turf(place) - for(var/obj/objects in contents) - remove_from_storage(objects, turf) - objects.pixel_x = rand(-6,6) - objects.pixel_y = rand(-6,6) - -/obj/item/weapon/storage/proc/return_inv() - - - var/list/L = list( ) - - L += src.contents - - for(var/obj/item/weapon/storage/S in src) - L += S.return_inv() - for(var/obj/item/weapon/gift/G in src) - L += G.gift - if (istype(G.gift, /obj/item/weapon/storage)) - L += G.gift:return_inv() - return L - -/obj/item/weapon/storage/proc/show_to(mob/user as mob) - if(isliving(user)) - if(user.s_active != src) - for(var/obj/item/I in src) - if(I.on_found(user)) - return - if(user.s_active) - user.s_active.hide_from(user) - user.client.screen -= src.boxes - user.client.screen -= src.closer - user.client.screen -= src.contents - user.client.screen += src.boxes - user.client.screen += src.closer - user.client.screen += src.contents - user.s_active = src - is_seeing |= user - return - -/obj/item/weapon/storage/proc/hide_from(mob/user as mob) - - - if(!user.client) - return - user.client.screen -= src.boxes - user.client.screen -= src.closer - user.client.screen -= src.contents - if(user.s_active == src) - user.s_active = null - is_seeing -= user - return - -/obj/item/weapon/storage/proc/close(mob/user as mob) - - - src.hide_from(user) - user.s_active = null - return - -//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right. -//The numbers are calculated from the bottom-left The bottom-left slot being 1,1. -/obj/item/weapon/storage/proc/orient_objs(tx, ty, mx, my) - var/cx = tx - var/cy = ty - src.boxes.screen_loc = "[tx]:,[ty] to [mx],[my]" - for(var/obj/O in src.contents) - O.screen_loc = "[cx],[cy]" - O.layer = 20 - cx++ - if (cx > mx) - cx = tx - cy-- - src.closer.screen_loc = "[mx+1],[my]" - return - -//This proc draws out the inventory and places the items on it. It uses the standard position. -/obj/item/weapon/storage/proc/standard_orient_objs(var/rows, var/cols, var/list/obj/item/display_contents) - var/cx = 4 - var/cy = 2+rows - src.boxes.screen_loc = "4:16,2:16 to [4+cols]:16,[2+rows]:16" - - if(display_contents_with_number) - for(var/datum/numbered_display/ND in display_contents) - ND.sample_object.screen_loc = "[cx]:16,[cy]:16" - ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" - ND.sample_object.layer = 20 - cx++ - if (cx > (4+cols)) - cx = 4 - cy-- - else - for(var/obj/O in contents) - O.screen_loc = "[cx]:16,[cy]:16" - O.maptext = "" - O.layer = 20 - cx++ - if (cx > (4+cols)) - cx = 4 - cy-- - src.closer.screen_loc = "[4+cols+1]:16,2:16" - return - -/datum/numbered_display - var/obj/item/sample_object - var/number - - New(obj/item/sample as obj) - if(!istype(sample)) - qdel(src) - return - sample_object = sample - number = 1 - -//This proc determins the size of the inventory to be displayed. Please touch it only if you know what you're doing. -/obj/item/weapon/storage/proc/orient2hud(mob/user as mob) - - - var/adjusted_contents = contents.len - - //Numbered contents display - var/list/datum/numbered_display/numbered_contents - if(display_contents_with_number) - numbered_contents = list() - adjusted_contents = 0 - for(var/obj/item/I in contents) - var/found = 0 - for(var/datum/numbered_display/ND in numbered_contents) - if(ND.sample_object.type == I.type) - ND.number++ - found = 1 - break - if(!found) - adjusted_contents++ - numbered_contents.Add( new/datum/numbered_display(I) ) - - //var/mob/living/carbon/human/H = user - var/row_num = 0 - var/col_count = min(7,storage_slots) -1 - if (adjusted_contents > 7) - row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width. - src.standard_orient_objs(row_num, col_count, numbered_contents) - return - -//This proc return 1 if the item can be picked up and 0 if it can't. -//Set the stop_messages to stop it from printing messages -/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0) - if(!istype(W)) return //Not an item - - if(src.loc == W) - return 0 //Means the item is already in the storage item - if(contents.len >= storage_slots) - if(!stop_messages) - to_chat(usr, "\The [src] is full, make some space.") - return 0 //Storage item is full - if(usr && (W.cant_drop > 0)) - if(!stop_messages) - usr << "You can't let go of \the [W]!" - return 0 //Item is stuck to our hands - - if(W.wielded || istype(W, /obj/item/offhand)) - var/obj/item/offhand/offhand = W - var/obj/item/ref_name = W - if(istype(offhand)) - ref_name = offhand.wielding - to_chat(usr, "Unwield \the [ref_name] first.") - return - - if(can_hold.len) - var/ok = 0 - for(var/A in can_hold) - if(dd_hasprefix(A,"=")) - // Force strict matching of type. - // No subtypes allowed. - if("[W.type]"==copytext(A,2)) - ok = 1 - break - else if(istype(W, text2path(A) )) - ok = 1 - break - if(!ok) - if(!stop_messages) - if (istype(W, /obj/item/weapon/hand_labeler)) - return 0 - to_chat(usr, "\The [src] cannot hold \the [W].") - return 0 - - for(var/A in cant_hold) //Check for specific items which this container can't hold. - var/nope=0 - if(dd_hasprefix(A,"=")) - // Force strict matching of type. - // No subtypes allowed. - if("[W.type]"==copytext(A,2)) - nope = 1 - break - else if(istype(W, text2path(A) )) - nope = 1 - break - if(nope) - if(!stop_messages) - to_chat(usr, "\The [src] cannot hold \the [W].") - return 0 - - if (W.w_class > max_w_class) - if(!stop_messages) - to_chat(usr, "\The [W] is too big for \the [src].") - return 0 - - var/sum_w_class = W.w_class - for(var/obj/item/I in contents) - sum_w_class += I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. - - if(sum_w_class > max_combined_w_class) - if(!stop_messages) - to_chat(usr, "\The [src] is full, make some space.") - return 0 - - if(W.w_class >= src.w_class && (istype(W, /obj/item/weapon/storage))) - if(!istype(src, /obj/item/weapon/storage/backpack/holding)) //bohs should be able to hold backpacks again. The override for putting a boh in a boh is in backpack.dm. - if(!stop_messages) - to_chat(usr, "\The [src] cannot hold \the [W] as it's a storage item of the same size.") - return 0 //To prevent the stacking of same sized storage items. - - return 1 - -//This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted() -//The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, -//such as when picking up all the items on a tile with one click. -/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0) - if(!istype(W)) return 0 - if(usr) - usr.u_equip(W,1) - usr.update_icons() //update our overlays - W.forceMove(src) - W.on_enter_storage(src) - if(usr) - if (usr.client && usr.s_active != src) - usr.client.screen -= W - //W.dropped(usr) - add_fingerprint(usr) - - if(!prevent_warning && !istype(W, /obj/item/weapon/gun/energy/crossbow)) - for(var/mob/M in viewers(usr, null)) - if (M == usr) - to_chat(usr, "You put \the [W] into \the [src].") - else if (M in range(1)) //If someone is standing close enough, they can tell what it is... - M.show_message("[usr] puts \the [W] into \the [src].") - else if (W && W.w_class >= 3.0) //Otherwise they can only see large or normal items from a distance... - M.show_message("[usr] puts \the [W] into \the [src].") - - src.orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - update_icon() - return 1 - -//Call this proc to handle the removal of an item from the storage item. The item will be moved to the atom sent as new_target -//force needs to be 1 if you want to override the can_be_inserted() if the target's a storage item. -/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location, var/force = 0) - if(!istype(W)) return 0 - - if(!force && istype(new_location, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/A = new_location - if(!A.can_be_inserted(W, 1)) - return 0 - - if(istype(src, /obj/item/weapon/storage/fancy)) - var/obj/item/weapon/storage/fancy/F = src - F.update_icon(1) - - for(var/mob/M in range(1, get_turf(src))) - if (M.s_active == src) - if (M.client) - M.client.screen -= W - - if(new_location) - var/mob/M - if(ismob(loc)) - M = loc - W.dropped(M) - if(ismob(new_location)) - M = new_location - M.put_in_active_hand(W) - else - if(istype(new_location, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/A = new_location - A.handle_item_insertion(W, 1) - else - W.forceMove(new_location) - else - W.forceMove(get_turf(src)) - - if(usr) - src.orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - if(W.maptext) - W.maptext = "" - W.on_exit_storage(src) - update_icon() - return 1 - -//This proc is called when you want to place an item into the storage item. -/obj/item/weapon/storage/attackby(obj/item/W as obj, mob/user as mob) - if(!Adjacent(user,MAX_ITEM_DEPTH)) - return - ..() - - // /vg/ #11: Recursion. - /*if(istype(W,/obj/item/weapon/implanter/compressed)) - return*/ - - if(isrobot(user)) - if(isMoMMI(user)) - var/mob/living/silicon/robot/mommi/M = user - if(M.is_in_modules(W)) - to_chat(user, "You can't throw away something built into you.") - return //Mommis cant give away their modules but can place other items - else - to_chat(user, "You're a robot. No.") - return //Robots can't interact with storage items. - - - if(!can_be_inserted(W)) - return - - if(istype(W, /obj/item/weapon/tray)) - var/obj/item/weapon/tray/T = W - if(T.calc_carry() > 0) - if(prob(85)) - to_chat(user, "The tray won't fit in \the [src].") - return - else - W.loc = user.loc - if ((user.client && user.s_active != src)) - user.client.screen -= W - W.dropped(user) - to_chat(user, "God damnit!") - - return handle_item_insertion(W) - -/obj/item/weapon/storage/dropped(mob/user as mob) - ..() - -/obj/item/weapon/storage/MouseDrop(over_object, src_location, over_location) - ..() - orient2hud(usr) - 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 - -/obj/item/weapon/storage/attack_hand(mob/user as mob) - playsound(get_turf(src), "rustle", 50, 1, -5) - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if((H.l_store == src || H.r_store == src) && !H.get_active_hand()) //Prevents opening if it's in a pocket. - return ..() - - src.orient2hud(user) - var/atom/maxloc = src.loc - if(src.internal_store) - for(var/i = 1; i++ <= internal_store) - if(maxloc == user) - break - if(maxloc.loc) - maxloc = maxloc.loc - if (maxloc == user) - if (user.s_active) - user.s_active.close(user) - src.show_to(user) - else - ..() - for(var/mob/M in range(1)) - if (M.s_active == src) - src.close(M) - src.add_fingerprint(user) - return - -/obj/item/weapon/storage/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/item/weapon/storage/throw_at() - close_all() //How are you going to see whats inside this thing while throwing it - ..() - -/obj/item/weapon/storage/recycle(var/datum/materials/rec) - if(contents) - mass_remove(get_turf(src)) - return ..() - -/obj/item/weapon/storage/verb/toggle_gathering_mode() - set name = "Switch Gathering Method" - set category = "Object" - - collection_mode = !collection_mode - switch (collection_mode) - if(1) - to_chat(usr, "\The [src] will now pick up all items on a tile at once.") - if(0) - to_chat(usr, "\The [src] will now pick up one item at a time.") - - -/obj/item/weapon/storage/verb/quick_empty() - set name = "Empty Contents" - set category = "Object" - - if((!ishuman(usr) && (src.loc != usr)) || usr.isUnconscious() || usr.restrained()) - return - - var/turf/T = get_turf(src) - hide_from(usr) - mass_remove(T) - -/obj/item/weapon/storage/New() - . = ..() - - if(allow_quick_empty) - verbs += /obj/item/weapon/storage/verb/quick_empty - else - verbs -= /obj/item/weapon/storage/verb/quick_empty - - if(allow_quick_gather) - verbs += /obj/item/weapon/storage/verb/toggle_gathering_mode - else - verbs -= /obj/item/weapon/storage/verb/toggle_gathering_mode - - src.boxes = getFromPool(/obj/screen/storage) - src.boxes.name = "storage" - src.boxes.master = src - src.boxes.icon_state = "block" - src.boxes.screen_loc = "7,7 to 10,8" - src.boxes.layer = 19 - src.closer = getFromPool(/obj/screen/close) - src.closer.master = src - src.closer.icon_state = "x" - src.closer.layer = 20 - orient2hud() - -/obj/item/weapon/storage/emp_act(severity) - if(!istype(src.loc, /mob/living)) - for(var/obj/O in contents) - O.emp_act(severity) - ..() - -/obj/item/weapon/storage/ex_act(var/severity,var/child=null) - if(!istype(src.loc, /mob/living)) - for(var/obj/O in contents) - O.ex_act(severity) - ..() - -// BubbleWrap - A box can be folded up to make card -/obj/item/weapon/storage/attack_self(mob/user as mob) - - //Clicking on itself will empty it, if it has the verb to do that. - if(user.get_active_hand() == src) - if(src.verbs.Find(/obj/item/weapon/storage/verb/quick_empty)) - src.quick_empty() - return - - //Otherwise we'll try to fold it. - if ( contents.len ) - return - - if ( !ispath(src.foldable) ) - return - var/found = 0 - // Close any open UI windows first - for(var/mob/M in range(1)) - if (M.s_active == src) - src.close(M) - if ( M == user ) - found = 1 - if ( !found ) // User is too far away - return - // Now make the cardboard - to_chat(user, "You fold \the [src] flat.") - new src.foldable(get_turf(src),foldable_amount) - qdel(src) -//BubbleWrap END -/obj/item/weapon/storage/proc/can_see_contents() - var/list/cansee = list() - for(var/mob/M in is_seeing) - if(M.s_active == src && M.client) - cansee |= M - else - is_seeing -= M - return cansee - -/obj/item/weapon/storage/proc/close_all() - for(var/mob/M in is_seeing) - close(M) - . = 1 //returns 1 if any mobs actually got a close(M) call - -/obj/item/weapon/storage/Destroy() - ..() - close_all() - returnToPool(boxes) - returnToPool(closer) - boxes = null - closer = null - for(var/atom/movable/AM in contents) - qdel(AM) - contents = null - -/obj/item/weapon/storage/preattack(atom/target, mob/user, adjacent, params) - if(!adjacent) return 0 - if(use_to_pickup) - if(collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one. - var/turf/gather_location - if(isturf(target.loc)) - if(!can_be_inserted(target)) - return 0 //letting the click process continue - gather_location = target.loc - else if(isturf(target)) - gather_location = target - else - return 0 - var/list/rejections = list() - var/success = 0 - var/failure = 0 - - for(var/obj/item/I in gather_location) - if(I.type in rejections) // To limit bag spamming: any given type only complains once - continue - if(I.anchored) - continue - if(!can_be_inserted(I)) // Note can_be_inserted still makes noise when the answer is no - rejections += I.type // therefore full bags are still a little spammy - failure = 1 - continue - success = 1 - handle_item_insertion(I, 1) //The 1 stops the "You put the [target] into [src]" insertion message from being displayed. - if(success && !failure) - to_chat(user, "You put everything into \the [src].") - return 1 - else if(success) - to_chat(user, "You put some things into \the [src].") - return 1 - else - to_chat(user, "You fail to pick anything up with \the [src].") - return 0 - - else if(can_be_inserted(target)) - handle_item_insertion(target) - return 1 - return 0 - -/obj/item/weapon/storage/OnMobDeath(mob/wearer as mob) - for(var/obj/item/I in contents) - I.OnMobDeath(wearer) - -/obj/item/weapon/storage/stripped(mob/wearer as mob, mob/stripper as mob) - for(var/obj/item/I in contents) - I.stripped(wearer,stripper) - -/obj/item/weapon/storage/proc/mass_remove(var/atom/A) - for(var/obj/item/O in contents) - remove_from_storage(O, A) +// To clarify: +// For use_to_pickup and allow_quick_gather functionality, +// see item/attackby() (/game/objects/items.dm) +// Do not remove this functionality without good reason, cough reagent_containers cough. +// -Sayu + + +/obj/item/weapon/storage + name = "storage" + icon = 'icons/obj/storage.dmi' + w_class = 3.0 + + // These two accept a string containing the type path and the following optional prefixes: + // = - Strict type matching. Will NOT check for subtypes. + var/list/can_hold = new/list() //List of objects which this item can store (if set, it can't store anything else) + var/list/cant_hold = new/list() //List of objects which this item can't store (in effect only if can_hold isn't set) + var/list/is_seeing = new/list() //List of mobs which are currently seeing the contents of this item's storage + var/max_w_class = 2 //Max size of objects that this object can store (in effect only if can_hold isn't set) + var/max_combined_w_class = 14 //The sum of the w_classes of all the items in this storage item. + var/storage_slots = 7 //The number of storage slots in this container. + var/obj/screen/storage/boxes = null + var/obj/screen/close/closer = null + var/use_to_pickup //Set this to make it possible to use this item in an inverse way, so you can have the item in your hand and click items on the floor to pick them up. + var/display_contents_with_number //Set this to make the storage item group contents of the same type and display them as a number. + var/allow_quick_empty //Set this variable to allow the object to have the 'empty' verb, which dumps all the contents on the floor. + 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/foldable_amount = 1 // Number of foldables to produce, if any - N3X + var/internal_store = 0 + +/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(over_object, /obj/structure/table) && M.Adjacent(over_object)) + var/mob/living/L = usr + if(istype(L) && !(L.restrained() || L.stat || L.weakened || L.stunned || L.paralysis || L.resting)) + empty_contents_to(over_object) + if(!( istype(over_object, /obj/screen) )) + return ..() + if(!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + playsound(get_turf(src), "rustle", 50, 1, -5) + if(!( M.restrained() ) && !( M.stat )) + switch(over_object.name) + if("r_hand") + M.u_equip(src,0) + M.put_in_r_hand(src) + if("l_hand") + M.u_equip(src,0) + 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 + +/obj/item/weapon/storage/proc/empty_contents_to(var/atom/place) + var/turf = get_turf(place) + for(var/obj/objects in contents) + remove_from_storage(objects, turf) + objects.pixel_x = rand(-6,6) + objects.pixel_y = rand(-6,6) + +/obj/item/weapon/storage/proc/return_inv() + + + var/list/L = list( ) + + L += src.contents + + for(var/obj/item/weapon/storage/S in src) + L += S.return_inv() + for(var/obj/item/weapon/gift/G in src) + L += G.gift + if (istype(G.gift, /obj/item/weapon/storage)) + L += G.gift:return_inv() + return L + +/obj/item/weapon/storage/proc/show_to(mob/user as mob) + if(isliving(user)) + if(user.s_active != src) + for(var/obj/item/I in src) + if(I.on_found(user)) + return + if(user.s_active) + user.s_active.hide_from(user) + user.client.screen -= src.boxes + user.client.screen -= src.closer + user.client.screen -= src.contents + user.client.screen += src.boxes + user.client.screen += src.closer + user.client.screen += src.contents + user.s_active = src + is_seeing |= user + return + +/obj/item/weapon/storage/proc/hide_from(mob/user as mob) + + + if(!user.client) + return + user.client.screen -= src.boxes + user.client.screen -= src.closer + user.client.screen -= src.contents + if(user.s_active == src) + user.s_active = null + is_seeing -= user + return + +/obj/item/weapon/storage/proc/close(mob/user as mob) + + + src.hide_from(user) + user.s_active = null + return + +//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right. +//The numbers are calculated from the bottom-left The bottom-left slot being 1,1. +/obj/item/weapon/storage/proc/orient_objs(tx, ty, mx, my) + var/cx = tx + var/cy = ty + src.boxes.screen_loc = "[tx]:,[ty] to [mx],[my]" + for(var/obj/O in src.contents) + O.screen_loc = "[cx],[cy]" + O.layer = 20 + cx++ + if (cx > mx) + cx = tx + cy-- + src.closer.screen_loc = "[mx+1],[my]" + return + +//This proc draws out the inventory and places the items on it. It uses the standard position. +/obj/item/weapon/storage/proc/standard_orient_objs(var/rows, var/cols, var/list/obj/item/display_contents) + var/cx = 4 + var/cy = 2+rows + src.boxes.screen_loc = "4:16,2:16 to [4+cols]:16,[2+rows]:16" + + if(display_contents_with_number) + for(var/datum/numbered_display/ND in display_contents) + ND.sample_object.screen_loc = "[cx]:16,[cy]:16" + ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" + ND.sample_object.layer = 20 + cx++ + if (cx > (4+cols)) + cx = 4 + cy-- + else + for(var/obj/O in contents) + O.screen_loc = "[cx]:16,[cy]:16" + O.maptext = "" + O.layer = 20 + cx++ + if (cx > (4+cols)) + cx = 4 + cy-- + src.closer.screen_loc = "[4+cols+1]:16,2:16" + return + +/datum/numbered_display + var/obj/item/sample_object + var/number + + New(obj/item/sample as obj) + if(!istype(sample)) + qdel(src) + return + sample_object = sample + number = 1 + +//This proc determins the size of the inventory to be displayed. Please touch it only if you know what you're doing. +/obj/item/weapon/storage/proc/orient2hud(mob/user as mob) + + + var/adjusted_contents = contents.len + + //Numbered contents display + var/list/datum/numbered_display/numbered_contents + if(display_contents_with_number) + numbered_contents = list() + adjusted_contents = 0 + for(var/obj/item/I in contents) + var/found = 0 + for(var/datum/numbered_display/ND in numbered_contents) + if(ND.sample_object.type == I.type) + ND.number++ + found = 1 + break + if(!found) + adjusted_contents++ + numbered_contents.Add( new/datum/numbered_display(I) ) + + //var/mob/living/carbon/human/H = user + var/row_num = 0 + var/col_count = min(7,storage_slots) -1 + if (adjusted_contents > 7) + row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width. + src.standard_orient_objs(row_num, col_count, numbered_contents) + return + +//This proc return 1 if the item can be picked up and 0 if it can't. +//Set the stop_messages to stop it from printing messages +/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0) + if(!istype(W)) return //Not an item + + if(src.loc == W) + return 0 //Means the item is already in the storage item + if(contents.len >= storage_slots) + if(!stop_messages) + to_chat(usr, "\The [src] is full, make some space.") + return 0 //Storage item is full + if(usr && (W.cant_drop > 0)) + if(!stop_messages) + usr << "You can't let go of \the [W]!" + return 0 //Item is stuck to our hands + + if(W.wielded || istype(W, /obj/item/offhand)) + var/obj/item/offhand/offhand = W + var/obj/item/ref_name = W + if(istype(offhand)) + ref_name = offhand.wielding + to_chat(usr, "Unwield \the [ref_name] first.") + return + + if(can_hold.len) + var/ok = 0 + for(var/A in can_hold) + if(dd_hasprefix(A,"=")) + // Force strict matching of type. + // No subtypes allowed. + if("[W.type]"==copytext(A,2)) + ok = 1 + break + else if(istype(W, text2path(A) )) + ok = 1 + break + if(!ok) + if(!stop_messages) + if (istype(W, /obj/item/weapon/hand_labeler)) + return 0 + to_chat(usr, "\The [src] cannot hold \the [W].") + return 0 + + for(var/A in cant_hold) //Check for specific items which this container can't hold. + var/nope=0 + if(dd_hasprefix(A,"=")) + // Force strict matching of type. + // No subtypes allowed. + if("[W.type]"==copytext(A,2)) + nope = 1 + break + else if(istype(W, text2path(A) )) + nope = 1 + break + if(nope) + if(!stop_messages) + to_chat(usr, "\The [src] cannot hold \the [W].") + return 0 + + if (W.w_class > max_w_class) + if(!stop_messages) + to_chat(usr, "\The [W] is too big for \the [src].") + return 0 + + var/sum_w_class = W.w_class + for(var/obj/item/I in contents) + sum_w_class += I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. + + if(sum_w_class > max_combined_w_class) + if(!stop_messages) + to_chat(usr, "\The [src] is full, make some space.") + return 0 + + if(W.w_class >= src.w_class && (istype(W, /obj/item/weapon/storage))) + if(!istype(src, /obj/item/weapon/storage/backpack/holding)) //bohs should be able to hold backpacks again. The override for putting a boh in a boh is in backpack.dm. + if(!stop_messages) + to_chat(usr, "\The [src] cannot hold \the [W] as it's a storage item of the same size.") + return 0 //To prevent the stacking of same sized storage items. + + return 1 + +//This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted() +//The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, +//such as when picking up all the items on a tile with one click. +/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0) + if(!istype(W)) return 0 + if(usr) + usr.u_equip(W,1) + usr.update_icons() //update our overlays + W.forceMove(src) + W.on_enter_storage(src) + if(usr) + if (usr.client && usr.s_active != src) + usr.client.screen -= W + //W.dropped(usr) + add_fingerprint(usr) + + if(!prevent_warning && !istype(W, /obj/item/weapon/gun/energy/crossbow)) + for(var/mob/M in viewers(usr, null)) + if (M == usr) + to_chat(usr, "You put \the [W] into \the [src].") + else if (M in range(1)) //If someone is standing close enough, they can tell what it is... + M.show_message("[usr] puts \the [W] into \the [src].") + else if (W && W.w_class >= 3.0) //Otherwise they can only see large or normal items from a distance... + M.show_message("[usr] puts \the [W] into \the [src].") + + src.orient2hud(usr) + if(usr.s_active) + usr.s_active.show_to(usr) + update_icon() + return 1 + +//Call this proc to handle the removal of an item from the storage item. The item will be moved to the atom sent as new_target +//force needs to be 1 if you want to override the can_be_inserted() if the target's a storage item. +/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location, var/force = 0) + if(!istype(W)) return 0 + + if(!force && istype(new_location, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/A = new_location + if(!A.can_be_inserted(W, 1)) + return 0 + + if(istype(src, /obj/item/weapon/storage/fancy)) + var/obj/item/weapon/storage/fancy/F = src + F.update_icon(1) + + for(var/mob/M in range(1, get_turf(src))) + if (M.s_active == src) + if (M.client) + M.client.screen -= W + + if(new_location) + var/mob/M + if(ismob(loc)) + M = loc + W.dropped(M) + if(ismob(new_location)) + M = new_location + M.put_in_active_hand(W) + else + if(istype(new_location, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/A = new_location + A.handle_item_insertion(W, 1) + else + W.forceMove(new_location) + else + W.forceMove(get_turf(src)) + + if(usr) + src.orient2hud(usr) + if(usr.s_active) + usr.s_active.show_to(usr) + if(W.maptext) + W.maptext = "" + W.on_exit_storage(src) + update_icon() + return 1 + +//This proc is called when you want to place an item into the storage item. +/obj/item/weapon/storage/attackby(obj/item/W as obj, mob/user as mob) + if(!Adjacent(user,MAX_ITEM_DEPTH)) + return + ..() + + // /vg/ #11: Recursion. + /*if(istype(W,/obj/item/weapon/implanter/compressed)) + return*/ + + if(isrobot(user)) + if(isMoMMI(user)) + var/mob/living/silicon/robot/mommi/M = user + if(M.is_in_modules(W)) + to_chat(user, "You can't throw away something built into you.") + return //Mommis cant give away their modules but can place other items + else + to_chat(user, "You're a robot. No.") + return //Robots can't interact with storage items. + + + if(!can_be_inserted(W)) + return + + if(istype(W, /obj/item/weapon/tray)) + var/obj/item/weapon/tray/T = W + if(T.calc_carry() > 0) + if(prob(85)) + to_chat(user, "The tray won't fit in \the [src].") + return + else + W.loc = user.loc + if ((user.client && user.s_active != src)) + user.client.screen -= W + W.dropped(user) + to_chat(user, "God damnit!") + + return handle_item_insertion(W) + +/obj/item/weapon/storage/dropped(mob/user as mob) + ..() + +/obj/item/weapon/storage/MouseDrop(over_object, src_location, over_location) + ..() + orient2hud(usr) + 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 + +/obj/item/weapon/storage/attack_hand(mob/user as mob) + playsound(get_turf(src), "rustle", 50, 1, -5) + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if((H.l_store == src || H.r_store == src) && !H.get_active_hand()) //Prevents opening if it's in a pocket. + return ..() + + src.orient2hud(user) + var/atom/maxloc = src.loc + if(src.internal_store) + for(var/i = 1; i++ <= internal_store) + if(maxloc == user) + break + if(maxloc.loc) + maxloc = maxloc.loc + if (maxloc == user) + if (user.s_active) + user.s_active.close(user) + src.show_to(user) + else + ..() + for(var/mob/M in range(1)) + if (M.s_active == src) + src.close(M) + src.add_fingerprint(user) + return + +/obj/item/weapon/storage/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/item/weapon/storage/throw_at() + close_all() //How are you going to see whats inside this thing while throwing it + ..() + +/obj/item/weapon/storage/recycle(var/datum/materials/rec) + if(contents) + mass_remove(get_turf(src)) + return ..() + +/obj/item/weapon/storage/verb/toggle_gathering_mode() + set name = "Switch Gathering Method" + set category = "Object" + + collection_mode = !collection_mode + switch (collection_mode) + if(1) + to_chat(usr, "\The [src] will now pick up all items on a tile at once.") + if(0) + to_chat(usr, "\The [src] will now pick up one item at a time.") + + +/obj/item/weapon/storage/verb/quick_empty() + set name = "Empty Contents" + set category = "Object" + + if((!ishuman(usr) && (src.loc != usr)) || usr.isUnconscious() || usr.restrained()) + return + + var/turf/T = get_turf(src) + hide_from(usr) + mass_remove(T) + +/obj/item/weapon/storage/New() + . = ..() + + if(allow_quick_empty) + verbs += /obj/item/weapon/storage/verb/quick_empty + else + verbs -= /obj/item/weapon/storage/verb/quick_empty + + if(allow_quick_gather) + verbs += /obj/item/weapon/storage/verb/toggle_gathering_mode + else + verbs -= /obj/item/weapon/storage/verb/toggle_gathering_mode + + src.boxes = getFromPool(/obj/screen/storage) + src.boxes.name = "storage" + src.boxes.master = src + src.boxes.icon_state = "block" + src.boxes.screen_loc = "7,7 to 10,8" + src.boxes.layer = 19 + src.closer = getFromPool(/obj/screen/close) + src.closer.master = src + src.closer.icon_state = "x" + src.closer.layer = 20 + orient2hud() + +/obj/item/weapon/storage/emp_act(severity) + if(!istype(src.loc, /mob/living)) + for(var/obj/O in contents) + O.emp_act(severity) + ..() + +/obj/item/weapon/storage/ex_act(var/severity,var/child=null) + if(!istype(src.loc, /mob/living)) + for(var/obj/O in contents) + O.ex_act(severity) + ..() + +// BubbleWrap - A box can be folded up to make card +/obj/item/weapon/storage/attack_self(mob/user as mob) + + //Clicking on itself will empty it, if it has the verb to do that. + if(user.get_active_hand() == src) + if(src.verbs.Find(/obj/item/weapon/storage/verb/quick_empty)) + src.quick_empty() + return + + //Otherwise we'll try to fold it. + if ( contents.len ) + return + + if ( !ispath(src.foldable) ) + return + var/found = 0 + // Close any open UI windows first + for(var/mob/M in range(1)) + if (M.s_active == src) + src.close(M) + if ( M == user ) + found = 1 + if ( !found ) // User is too far away + return + // Now make the cardboard + to_chat(user, "You fold \the [src] flat.") + new src.foldable(get_turf(src),foldable_amount) + qdel(src) +//BubbleWrap END +/obj/item/weapon/storage/proc/can_see_contents() + var/list/cansee = list() + for(var/mob/M in is_seeing) + if(M.s_active == src && M.client) + cansee |= M + else + is_seeing -= M + return cansee + +/obj/item/weapon/storage/proc/close_all() + for(var/mob/M in is_seeing) + close(M) + . = 1 //returns 1 if any mobs actually got a close(M) call + +/obj/item/weapon/storage/Destroy() + ..() + close_all() + returnToPool(boxes) + returnToPool(closer) + boxes = null + closer = null + for(var/atom/movable/AM in contents) + qdel(AM) + contents = null + +/obj/item/weapon/storage/preattack(atom/target, mob/user, adjacent, params) + if(!adjacent) return 0 + if(use_to_pickup) + if(collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one. + var/turf/gather_location + if(isturf(target.loc)) + if(!can_be_inserted(target)) + return 0 //letting the click process continue + gather_location = target.loc + else if(isturf(target)) + gather_location = target + else + return 0 + var/list/rejections = list() + var/success = 0 + var/failure = 0 + + for(var/obj/item/I in gather_location) + if(I.type in rejections) // To limit bag spamming: any given type only complains once + continue + if(I.anchored) + continue + if(!can_be_inserted(I)) // Note can_be_inserted still makes noise when the answer is no + rejections += I.type // therefore full bags are still a little spammy + failure = 1 + continue + success = 1 + handle_item_insertion(I, 1) //The 1 stops the "You put the [target] into [src]" insertion message from being displayed. + if(success && !failure) + to_chat(user, "You put everything into \the [src].") + return 1 + else if(success) + to_chat(user, "You put some things into \the [src].") + return 1 + else + to_chat(user, "You fail to pick anything up with \the [src].") + return 0 + + else if(can_be_inserted(target)) + handle_item_insertion(target) + return 1 + return 0 + +/obj/item/weapon/storage/OnMobDeath(mob/wearer as mob) + for(var/obj/item/I in contents) + I.OnMobDeath(wearer) + +/obj/item/weapon/storage/stripped(mob/wearer as mob, mob/stripper as mob) + for(var/obj/item/I in contents) + I.stripped(wearer,stripper) + +/obj/item/weapon/storage/proc/mass_remove(var/atom/A) + for(var/obj/item/O in contents) + remove_from_storage(O, A) diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 16a9ca61790..a73bc650554 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -1,92 +1,92 @@ -/obj/item/weapon/storage/toolbox - name = "toolbox" - desc = "Danger. Very robust." - icon = 'icons/obj/storage.dmi' - icon_state = "red" - item_state = "toolbox_red" - flags = FPRINT - siemens_coefficient = 1 - force = 12.0 - hitsound = 'sound/weapons/toolbox.ogg' - throwforce = 10.0 - throw_speed = 1 - throw_range = 7 - starting_materials = list(MAT_IRON = 5000) - w_type = RECYK_METAL - w_class = 4.0 - melt_temperature = MELTPOINT_STEEL - origin_tech = "combat=1" - attack_verb = list("robusted", "battered", "staved in") - - -/obj/item/weapon/storage/toolbox/suicide_act(mob/user) +/obj/item/weapon/storage/toolbox + name = "toolbox" + desc = "Danger. Very robust." + icon = 'icons/obj/storage.dmi' + icon_state = "red" + item_state = "toolbox_red" + flags = FPRINT + siemens_coefficient = 1 + force = 12.0 + hitsound = 'sound/weapons/toolbox.ogg' + throwforce = 10.0 + throw_speed = 1 + throw_range = 7 + starting_materials = list(MAT_IRON = 5000) + w_type = RECYK_METAL + w_class = 4.0 + melt_temperature = MELTPOINT_STEEL + origin_tech = "combat=1" + attack_verb = list("robusted", "battered", "staved in") + + +/obj/item/weapon/storage/toolbox/suicide_act(mob/user) to_chat(viewers(user), "[user] is [pick("staving","robusting")] \his head in with the [src.name]! It looks like \he's trying to commit suicide!") - return (BRUTELOSS) - - -/obj/item/weapon/storage/toolbox/emergency - name = "emergency toolbox" - icon_state = "red" - item_state = "toolbox_red" - -/obj/item/weapon/storage/toolbox/emergency/New() - ..() - new /obj/item/weapon/crowbar/red(src) - new /obj/item/weapon/extinguisher/mini(src) - var/lighting = pick( //emergency lighting yay - 20;/obj/item/device/flashlight, - 30;/obj/item/weapon/storage/fancy/flares, - 50;/obj/item/device/flashlight/flare) - new lighting(src) - new /obj/item/device/radio(src) - -/obj/item/weapon/storage/toolbox/mechanical - name = "mechanical toolbox" - icon_state = "blue" - item_state = "toolbox_blue" - -/obj/item/weapon/storage/toolbox/mechanical/New() - ..() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/device/analyzer(src) - new /obj/item/weapon/wirecutters(src) - -/obj/item/weapon/storage/toolbox/electrical - name = "electrical toolbox" - icon_state = "yellow" - item_state = "toolbox_yellow" - -/obj/item/weapon/storage/toolbox/electrical/New() - ..() - var/color = pick("red","yellow","green","blue","pink","orange","cyan","white") - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/t_scanner(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/stack/cable_coil(src,30,color) - new /obj/item/stack/cable_coil(src,30,color) - if(prob(5)) - new /obj/item/clothing/gloves/yellow(src) - else - new /obj/item/stack/cable_coil(src,30,color) - -/obj/item/weapon/storage/toolbox/syndicate - name = "suspicious looking toolbox" - icon_state = "syndicate" - item_state = "toolbox_syndi" - origin_tech = "combat=1;syndicate=1" - force = 15.0 - -/obj/item/weapon/storage/toolbox/syndicate/New() - ..() - var/color = pick("red","yellow","green","blue","pink","orange","cyan","white") - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/stack/cable_coil(src,30,color) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/multitool(src) + return (BRUTELOSS) + + +/obj/item/weapon/storage/toolbox/emergency + name = "emergency toolbox" + icon_state = "red" + item_state = "toolbox_red" + +/obj/item/weapon/storage/toolbox/emergency/New() + ..() + new /obj/item/weapon/crowbar/red(src) + new /obj/item/weapon/extinguisher/mini(src) + var/lighting = pick( //emergency lighting yay + 20;/obj/item/device/flashlight, + 30;/obj/item/weapon/storage/fancy/flares, + 50;/obj/item/device/flashlight/flare) + new lighting(src) + new /obj/item/device/radio(src) + +/obj/item/weapon/storage/toolbox/mechanical + name = "mechanical toolbox" + icon_state = "blue" + item_state = "toolbox_blue" + +/obj/item/weapon/storage/toolbox/mechanical/New() + ..() + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/device/analyzer(src) + new /obj/item/weapon/wirecutters(src) + +/obj/item/weapon/storage/toolbox/electrical + name = "electrical toolbox" + icon_state = "yellow" + item_state = "toolbox_yellow" + +/obj/item/weapon/storage/toolbox/electrical/New() + ..() + var/color = pick("red","yellow","green","blue","pink","orange","cyan","white") + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/device/t_scanner(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/stack/cable_coil(src,30,color) + new /obj/item/stack/cable_coil(src,30,color) + if(prob(5)) + new /obj/item/clothing/gloves/yellow(src) + else + new /obj/item/stack/cable_coil(src,30,color) + +/obj/item/weapon/storage/toolbox/syndicate + name = "suspicious looking toolbox" + icon_state = "syndicate" + item_state = "toolbox_syndi" + origin_tech = "combat=1;syndicate=1" + force = 15.0 + +/obj/item/weapon/storage/toolbox/syndicate/New() + ..() + var/color = pick("red","yellow","green","blue","pink","orange","cyan","white") + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/stack/cable_coil(src,30,color) + new /obj/item/weapon/wirecutters(src) + new /obj/item/device/multitool(src) diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm index 0480042a48a..d0f80b14dda 100644 --- a/code/game/objects/items/weapons/swords_axes_etc.dm +++ b/code/game/objects/items/weapons/swords_axes_etc.dm @@ -1,211 +1,211 @@ -/* Weapons - * Contains: - * Banhammer - * Sword - * Classic Baton - * Energy Blade - * Energy Axe - * Energy Shield - */ - -/* - * Banhammer - */ -/obj/item/weapon/banhammer/attack(mob/M as mob, mob/user as mob) - to_chat(M, "You have been banned FOR NO REISIN by [user]") - to_chat(user, "You have BANNED [M]") - -/* - * Classic Baton - */ -/obj/item/weapon/melee/classic_baton - name = "police baton" - desc = "A wooden truncheon for beating criminal scum." - icon = 'icons/obj/weapons.dmi' - icon_state = "baton" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/misc_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/misc_tools.dmi') - item_state = "classic_baton" - origin_tech = "combat=3" - mech_flags = MECH_SCAN_FAIL - flags = FPRINT - slot_flags = SLOT_BELT - force = 10 - -/obj/item/weapon/melee/classic_baton/attack(mob/M as mob, mob/living/user as mob) - if ((M_CLUMSY in user.mutations) && prob(50)) - to_chat(user, "You club yourself over the head.") - user.Weaken(3 * force) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.apply_damage(2*force, BRUTE, "head") - else - user.take_organ_damage(2*force) - return -/*this is already called in ..() - src.add_fingerprint(user) - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - - log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") -*/ - if (user.a_intent == I_HURT) - if(!..()) return - playsound(get_turf(src), "swing_hit", 50, 1, -1) - if (M.stuttering < 8 && (!(M_HULK in M.mutations)) /*&& (!istype(H:wear_suit, /obj/item/clothing/suit/judgerobe))*/) - M.stuttering = 8 - M.Stun(8) - M.Weaken(8) - for(var/mob/O in viewers(M)) - if (O.client) O.show_message("[M] has been beaten with \the [src] by [user]!", 1, "You hear someone fall", 2) - else - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1) - M.Stun(5) - M.Weaken(5) - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - src.add_fingerprint(user) - - for(var/mob/O in viewers(M)) - if (O.client) O.show_message("[M] has been stunned with \the [src] by [user]!", 1, "You hear someone fall", 2) - -//Telescopic baton -/obj/item/weapon/melee/telebaton - name = "telescopic baton" - desc = "A compact yet robust personal defense weapon. Can be concealed when folded." - icon = 'icons/obj/weapons.dmi' - icon_state = "telebaton_0" - item_state = "telebaton_0" - origin_tech = "combat=2" - flags = FPRINT - slot_flags = SLOT_BELT - w_class = 2 - force = 3 - var/on = 0 - - -/obj/item/weapon/melee/telebaton/attack_self(mob/user as mob) - on = !on - if(on) - user.visible_message("With a flick of their wrist, [user] extends their telescopic baton.",\ - "You extend the baton.",\ - "You hear an ominous click.",\ - "[user] extends their fishing rod.",\ - "You extend the fishing rod.",\ - "You hear a balloon exploding.") - - icon_state = "telebaton_1" - item_state = "telebaton_1" - w_class = 4 - force = 15//quite robust - attack_verb = list("smacked", "struck", "slapped") - else - user.visible_message("[user] collapses their telescopic baton.",\ - "You collapse the baton.",\ - "You hear a click.",\ - "[user] collapses their fishing rod.",\ - "You collapse the fishing rod.",\ - "You hear a balloon exploding.") - - icon_state = "telebaton_0" - item_state = "telebaton_0" - w_class = 2 - force = 3//not so robust now - attack_verb = list("hit", "punched") - playsound(get_turf(src), 'sound/weapons/empty.ogg', 50, 1) - add_fingerprint(user) - - if(!blood_overlays["[type][icon_state]"]) - generate_blood_overlay() - if(blood_overlay) - overlays -= blood_overlay - blood_overlay = blood_overlays["[type][icon_state]"] - blood_overlay.color = blood_color - overlays += blood_overlay - -/obj/item/weapon/melee/telebaton/generate_blood_overlay() - if(blood_overlays["[type][icon_state]"]) //Unless someone makes a wicked typepath this will never cause a problem - return - var/icon/I = new /icon(icon, icon_state) - I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent) - I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant - blood_overlays["[type][icon_state]"] = image(I) - -/obj/item/weapon/melee/telebaton/attack(mob/target as mob, mob/living/user as mob) - if(on) - if ((M_CLUMSY in user.mutations) && prob(50)) - user.simple_message("You club yourself over the head.", - "The fishing rod goes mad!") - - user.Weaken(3 * force) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.apply_damage(2*force, BRUTE, "head") - else - user.take_organ_damage(2*force) - return - if (user.a_intent == I_HURT) - if(!..()) return - if(!isrobot(target)) - playsound(get_turf(src), "swing_hit", 50, 1, -1) - //target.Stun(4) //naaah - target.Weaken(4) - else - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1) - target.Weaken(2) - target.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [target.name] ([target.ckey])") - log_attack("[user.name] ([user.ckey]) attacked [target.name] ([target.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - src.add_fingerprint(user) - - target.visible_message("[target] has been stunned with \the [src] by [user]!",\ - drugged_message="[user] smacks [target] with the fishing rod!") - - if(!iscarbon(user)) - target.LAssailant = null - else - target.LAssailant = user - return - else - return ..() - - -/* - *Energy Blade - */ -//Most of the other special functions are handled in their own files. - -/obj/item/weapon/melee/energy/sword/green/New() - ..() - _color = "green" - -/obj/item/weapon/melee/energy/sword/red/New() - ..() - _color = "red" - -/* - * Energy Axe - */ -/obj/item/weapon/melee/energy/axe/attack(target as mob, mob/user as mob) - ..() - -/obj/item/weapon/melee/energy/axe/attack_self(mob/user as mob) - src.active = !( src.active ) - if (src.active) - to_chat(user, "The axe is now energised.") - src.force = 150 - src.icon_state = "axe1" - src.w_class = 5 - src.sharpness = 1.5 - else - to_chat(user, "The axe can now be concealed.") - src.force = 40 - src.icon_state = "axe0" - src.w_class = 5 - src.sharpness = 1.0 - src.add_fingerprint(user) - return +/* Weapons + * Contains: + * Banhammer + * Sword + * Classic Baton + * Energy Blade + * Energy Axe + * Energy Shield + */ + +/* + * Banhammer + */ +/obj/item/weapon/banhammer/attack(mob/M as mob, mob/user as mob) + to_chat(M, "You have been banned FOR NO REISIN by [user]") + to_chat(user, "You have BANNED [M]") + +/* + * Classic Baton + */ +/obj/item/weapon/melee/classic_baton + name = "police baton" + desc = "A wooden truncheon for beating criminal scum." + icon = 'icons/obj/weapons.dmi' + icon_state = "baton" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/misc_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/misc_tools.dmi') + item_state = "classic_baton" + origin_tech = "combat=3" + mech_flags = MECH_SCAN_FAIL + flags = FPRINT + slot_flags = SLOT_BELT + force = 10 + +/obj/item/weapon/melee/classic_baton/attack(mob/M as mob, mob/living/user as mob) + if ((M_CLUMSY in user.mutations) && prob(50)) + to_chat(user, "You club yourself over the head.") + user.Weaken(3 * force) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.apply_damage(2*force, BRUTE, "head") + else + user.take_organ_damage(2*force) + return +/*this is already called in ..() + src.add_fingerprint(user) + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + + log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") +*/ + if (user.a_intent == I_HURT) + if(!..()) return + playsound(get_turf(src), "swing_hit", 50, 1, -1) + if (M.stuttering < 8 && (!(M_HULK in M.mutations)) /*&& (!istype(H:wear_suit, /obj/item/clothing/suit/judgerobe))*/) + M.stuttering = 8 + M.Stun(8) + M.Weaken(8) + for(var/mob/O in viewers(M)) + if (O.client) O.show_message("[M] has been beaten with \the [src] by [user]!", 1, "You hear someone fall", 2) + else + playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1) + M.Stun(5) + M.Weaken(5) + M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") + log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + src.add_fingerprint(user) + + for(var/mob/O in viewers(M)) + if (O.client) O.show_message("[M] has been stunned with \the [src] by [user]!", 1, "You hear someone fall", 2) + +//Telescopic baton +/obj/item/weapon/melee/telebaton + name = "telescopic baton" + desc = "A compact yet robust personal defense weapon. Can be concealed when folded." + icon = 'icons/obj/weapons.dmi' + icon_state = "telebaton_0" + item_state = "telebaton_0" + origin_tech = "combat=2" + flags = FPRINT + slot_flags = SLOT_BELT + w_class = 2 + force = 3 + var/on = 0 + + +/obj/item/weapon/melee/telebaton/attack_self(mob/user as mob) + on = !on + if(on) + user.visible_message("With a flick of their wrist, [user] extends their telescopic baton.",\ + "You extend the baton.",\ + "You hear an ominous click.",\ + "[user] extends their fishing rod.",\ + "You extend the fishing rod.",\ + "You hear a balloon exploding.") + + icon_state = "telebaton_1" + item_state = "telebaton_1" + w_class = 4 + force = 15//quite robust + attack_verb = list("smacked", "struck", "slapped") + else + user.visible_message("[user] collapses their telescopic baton.",\ + "You collapse the baton.",\ + "You hear a click.",\ + "[user] collapses their fishing rod.",\ + "You collapse the fishing rod.",\ + "You hear a balloon exploding.") + + icon_state = "telebaton_0" + item_state = "telebaton_0" + w_class = 2 + force = 3//not so robust now + attack_verb = list("hit", "punched") + playsound(get_turf(src), 'sound/weapons/empty.ogg', 50, 1) + add_fingerprint(user) + + if(!blood_overlays["[type][icon_state]"]) + generate_blood_overlay() + if(blood_overlay) + overlays -= blood_overlay + blood_overlay = blood_overlays["[type][icon_state]"] + blood_overlay.color = blood_color + overlays += blood_overlay + +/obj/item/weapon/melee/telebaton/generate_blood_overlay() + if(blood_overlays["[type][icon_state]"]) //Unless someone makes a wicked typepath this will never cause a problem + return + var/icon/I = new /icon(icon, icon_state) + I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent) + I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant + blood_overlays["[type][icon_state]"] = image(I) + +/obj/item/weapon/melee/telebaton/attack(mob/target as mob, mob/living/user as mob) + if(on) + if ((M_CLUMSY in user.mutations) && prob(50)) + user.simple_message("You club yourself over the head.", + "The fishing rod goes mad!") + + user.Weaken(3 * force) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.apply_damage(2*force, BRUTE, "head") + else + user.take_organ_damage(2*force) + return + if (user.a_intent == I_HURT) + if(!..()) return + if(!isrobot(target)) + playsound(get_turf(src), "swing_hit", 50, 1, -1) + //target.Stun(4) //naaah + target.Weaken(4) + else + playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1) + target.Weaken(2) + target.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [target.name] ([target.ckey])") + log_attack("[user.name] ([user.ckey]) attacked [target.name] ([target.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") + src.add_fingerprint(user) + + target.visible_message("[target] has been stunned with \the [src] by [user]!",\ + drugged_message="[user] smacks [target] with the fishing rod!") + + if(!iscarbon(user)) + target.LAssailant = null + else + target.LAssailant = user + return + else + return ..() + + +/* + *Energy Blade + */ +//Most of the other special functions are handled in their own files. + +/obj/item/weapon/melee/energy/sword/green/New() + ..() + _color = "green" + +/obj/item/weapon/melee/energy/sword/red/New() + ..() + _color = "red" + +/* + * Energy Axe + */ +/obj/item/weapon/melee/energy/axe/attack(target as mob, mob/user as mob) + ..() + +/obj/item/weapon/melee/energy/axe/attack_self(mob/user as mob) + src.active = !( src.active ) + if (src.active) + to_chat(user, "The axe is now energised.") + src.force = 150 + src.icon_state = "axe1" + src.w_class = 5 + src.sharpness = 1.5 + else + to_chat(user, "The axe can now be concealed.") + src.force = 40 + src.icon_state = "axe0" + src.w_class = 5 + src.sharpness = 1.0 + src.add_fingerprint(user) + return diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index 4309050267b..8b4cfe22975 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -1,103 +1,103 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/weapon/tank/jetpack - name = "Jetpack (Empty)" - desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack" - w_class = 3.0 - item_state = "jetpack" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - var/datum/effect/effect/system/trail/ion_trail - var/on = 0.0 - var/stabilization_on = 0 - var/volume_rate = 500 //Needed for borg jetpack transfer - action_button_name = "Toggle Jetpack" - -/obj/item/weapon/tank/jetpack/verb/toggle_rockets() - set name = "Toggle Jetpack Stabilization" - set category = "Object" - src.stabilization_on = !( src.stabilization_on ) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/weapon/tank/jetpack + name = "Jetpack (Empty)" + desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution." + icon_state = "jetpack" + w_class = 3.0 + item_state = "jetpack" + distribute_pressure = ONE_ATMOSPHERE*O2STANDARD + var/datum/effect/effect/system/trail/ion_trail + var/on = 0.0 + var/stabilization_on = 0 + var/volume_rate = 500 //Needed for borg jetpack transfer + action_button_name = "Toggle Jetpack" + +/obj/item/weapon/tank/jetpack/verb/toggle_rockets() + set name = "Toggle Jetpack Stabilization" + set category = "Object" + src.stabilization_on = !( src.stabilization_on ) to_chat(usr, "You toggle the stabilization [stabilization_on? "on":"off"].") - return - - -/obj/item/weapon/tank/jetpack/verb/toggle() - set name = "Toggle Jetpack" - set category = "Object" - on = !on - if(on) - icon_state = "[icon_state]-on" -// item_state = "[item_state]-on" - ion_trail.start() - else - icon_state = initial(icon_state) -// item_state = initial(item_state) - ion_trail.stop() - return - - -/obj/item/weapon/tank/jetpack/proc/allow_thrust(num, mob/living/user as mob) - if(!(src.on)) - return 0 - if((num < 0.005 || src.air_contents.total_moles() < num)) - src.toggle() - return 0 - - var/datum/gas_mixture/G = src.air_contents.remove(num) - var/allgases = G.total_moles() - - if(allgases >= 0.005) - return 1 - - qdel(G) - G = null - return - -/obj/item/weapon/tank/jetpack/ui_action_click() - toggle() - -/obj/item/weapon/tank/jetpack/New() - . = ..() - ion_trail = new /datum/effect/effect/system/trail() - ion_trail.set_up(src) - -/obj/item/weapon/tank/jetpack/void - name = "Void Jetpack (Oxygen)" - desc = "It works well in a void." - icon_state = "jetpack-void" - item_state = "jetpack-void" - -/obj/item/weapon/tank/jetpack/void/New() - . = ..() - air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/jetpack/oxygen - name = "Jetpack (Oxygen)" - desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack" - item_state = "jetpack" - -/obj/item/weapon/tank/jetpack/oxygen/New() - . = ..() - air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/jetpack/nitrogen - name = "Jetpack (Nitrogen)" - desc = "A tank of compressed nitrogen for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack-red" - item_state = "jetpack-red" - -/obj/item/weapon/tank/jetpack/nitrogen/New() - . = ..() - air_contents.adjust(, , (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/jetpack/carbondioxide - name = "Jetpack (Carbon Dioxide)" - desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals." - distribute_pressure = 0 - icon_state = "jetpack-black" - item_state = "jetpack-black" - -/obj/item/weapon/tank/jetpack/carbondioxide/New() - . = ..() - air_contents.adjust(, (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + return + + +/obj/item/weapon/tank/jetpack/verb/toggle() + set name = "Toggle Jetpack" + set category = "Object" + on = !on + if(on) + icon_state = "[icon_state]-on" +// item_state = "[item_state]-on" + ion_trail.start() + else + icon_state = initial(icon_state) +// item_state = initial(item_state) + ion_trail.stop() + return + + +/obj/item/weapon/tank/jetpack/proc/allow_thrust(num, mob/living/user as mob) + if(!(src.on)) + return 0 + if((num < 0.005 || src.air_contents.total_moles() < num)) + src.toggle() + return 0 + + var/datum/gas_mixture/G = src.air_contents.remove(num) + var/allgases = G.total_moles() + + if(allgases >= 0.005) + return 1 + + qdel(G) + G = null + return + +/obj/item/weapon/tank/jetpack/ui_action_click() + toggle() + +/obj/item/weapon/tank/jetpack/New() + . = ..() + ion_trail = new /datum/effect/effect/system/trail() + ion_trail.set_up(src) + +/obj/item/weapon/tank/jetpack/void + name = "Void Jetpack (Oxygen)" + desc = "It works well in a void." + icon_state = "jetpack-void" + item_state = "jetpack-void" + +/obj/item/weapon/tank/jetpack/void/New() + . = ..() + air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/jetpack/oxygen + name = "Jetpack (Oxygen)" + desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution." + icon_state = "jetpack" + item_state = "jetpack" + +/obj/item/weapon/tank/jetpack/oxygen/New() + . = ..() + air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/jetpack/nitrogen + name = "Jetpack (Nitrogen)" + desc = "A tank of compressed nitrogen for use as propulsion in zero-gravity areas. Use with caution." + icon_state = "jetpack-red" + item_state = "jetpack-red" + +/obj/item/weapon/tank/jetpack/nitrogen/New() + . = ..() + air_contents.adjust(, , (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/jetpack/carbondioxide + name = "Jetpack (Carbon Dioxide)" + desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals." + distribute_pressure = 0 + icon_state = "jetpack-black" + item_state = "jetpack-black" + +/obj/item/weapon/tank/jetpack/carbondioxide/New() + . = ..() + air_contents.adjust(, (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm index d4dd97e13d5..fd0d02ed4b6 100644 --- a/code/game/objects/items/weapons/tanks/tank_types.dm +++ b/code/game/objects/items/weapons/tanks/tank_types.dm @@ -1,140 +1,140 @@ -/* Types of tanks! - * Contains: - * Oxygen - * Anesthetic - * Air - * Plasma - * Emergency Oxygen - */ - -/* - * Oxygen - */ -/obj/item/weapon/tank/oxygen - name = "oxygen tank" - desc = "A tank of oxygen." - icon_state = "oxygen" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - -/obj/item/weapon/tank/oxygen/New() - . = ..() - air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/oxygen/yellow - desc = "A tank of oxygen, this one is yellow." - icon_state = "oxygen_f" - -/obj/item/weapon/tank/oxygen/red - desc = "A tank of oxygen, this one is red." - icon_state = "oxygen_fr" - -/* - * Anesthetic - */ -/obj/item/weapon/tank/anesthetic - name = "anesthetic tank" - desc = "A tank with an N2O/O2 gas mix." - icon_state = "anesthetic" - item_state = "an_tank" - -/obj/item/weapon/tank/anesthetic/New() - . = ..() - var/datum/gas/sleeping_agent/sleeping_agent = new - sleeping_agent.moles = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD - air_contents.adjust((3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD, , , , list(sleeping_agent)) - -/* - * Air - */ -/obj/item/weapon/tank/air - name = "air tank" - desc = "Mixed anyone?" - icon_state = "oxygen" - -/obj/item/weapon/tank/air/New() - . = ..() - air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD, , (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD) - -/* - * Plasma - */ -/obj/item/weapon/tank/plasma - name = "plasma tank" - desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable." - icon_state = "plasma" - flags = FPRINT - slot_flags = null //they have no straps! - -/obj/item/weapon/tank/plasma/New() - . = ..() - air_contents.adjust(, , , (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - - if (istype(W, /obj/item/weapon/flamethrower)) - var/obj/item/weapon/flamethrower/F = W - if ((!F.status)||(F.ptank)) return - src.master = F - F.ptank = src - user.before_take_item(src) - src.loc = F - return - -/obj/item/weapon/tank/plasma/plasmaman - desc = "The lifeblood of plasmamen. Warning: Extremely flammable, do not inhale (unless you're a plasmaman)." - icon_state = "plasma_fr" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - -/* - * Emergency Oxygen - */ -/obj/item/weapon/tank/emergency_oxygen - name = "emergency oxygen tank" - desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it." - icon_state = "emergency" - flags = FPRINT - slot_flags = SLOT_BELT - w_class = 2.0 - force = 4.0 - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - volume = 2 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011) - -/obj/item/weapon/tank/emergency_oxygen/New() - . = ..() - air_contents.adjust((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/emergency_oxygen/engi - name = "extended-capacity emergency oxygen tank" - icon_state = "emergency_engi" - volume = 6 - -/obj/item/weapon/tank/emergency_oxygen/double - name = "double emergency oxygen tank" - icon_state = "emergency_double" - volume = 10 - -/obj/item/weapon/tank/emergency_nitrogen - name = "emergency nitrogen tank" - desc = "Used for emergencies. Not useful unless you only breathe nitrogen." - icon_state = "emergency_nitrogen" - slot_flags = SLOT_BELT - w_class = 2.0 - volume = 2 - -/obj/item/weapon/tank/emergency_nitrogen/New() - . = ..() - air_contents.adjust(, , (3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/* - * Nitrogen - */ -/obj/item/weapon/tank/nitrogen - name = "nitrogen tank" - desc = "A tank of nitrogen." - icon_state = "oxygen_fr" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - -/obj/item/weapon/tank/nitrogen/New() - . = ..() - air_contents.adjust(, , (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) +/* Types of tanks! + * Contains: + * Oxygen + * Anesthetic + * Air + * Plasma + * Emergency Oxygen + */ + +/* + * Oxygen + */ +/obj/item/weapon/tank/oxygen + name = "oxygen tank" + desc = "A tank of oxygen." + icon_state = "oxygen" + distribute_pressure = ONE_ATMOSPHERE*O2STANDARD + +/obj/item/weapon/tank/oxygen/New() + . = ..() + air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/oxygen/yellow + desc = "A tank of oxygen, this one is yellow." + icon_state = "oxygen_f" + +/obj/item/weapon/tank/oxygen/red + desc = "A tank of oxygen, this one is red." + icon_state = "oxygen_fr" + +/* + * Anesthetic + */ +/obj/item/weapon/tank/anesthetic + name = "anesthetic tank" + desc = "A tank with an N2O/O2 gas mix." + icon_state = "anesthetic" + item_state = "an_tank" + +/obj/item/weapon/tank/anesthetic/New() + . = ..() + var/datum/gas/sleeping_agent/sleeping_agent = new + sleeping_agent.moles = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD + air_contents.adjust((3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD, , , , list(sleeping_agent)) + +/* + * Air + */ +/obj/item/weapon/tank/air + name = "air tank" + desc = "Mixed anyone?" + icon_state = "oxygen" + +/obj/item/weapon/tank/air/New() + . = ..() + air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD, , (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD) + +/* + * Plasma + */ +/obj/item/weapon/tank/plasma + name = "plasma tank" + desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable." + icon_state = "plasma" + flags = FPRINT + slot_flags = null //they have no straps! + +/obj/item/weapon/tank/plasma/New() + . = ..() + air_contents.adjust(, , , (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + + if (istype(W, /obj/item/weapon/flamethrower)) + var/obj/item/weapon/flamethrower/F = W + if ((!F.status)||(F.ptank)) return + src.master = F + F.ptank = src + user.before_take_item(src) + src.loc = F + return + +/obj/item/weapon/tank/plasma/plasmaman + desc = "The lifeblood of plasmamen. Warning: Extremely flammable, do not inhale (unless you're a plasmaman)." + icon_state = "plasma_fr" + distribute_pressure = ONE_ATMOSPHERE*O2STANDARD + +/* + * Emergency Oxygen + */ +/obj/item/weapon/tank/emergency_oxygen + name = "emergency oxygen tank" + desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it." + icon_state = "emergency" + flags = FPRINT + slot_flags = SLOT_BELT + w_class = 2.0 + force = 4.0 + distribute_pressure = ONE_ATMOSPHERE*O2STANDARD + volume = 2 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011) + +/obj/item/weapon/tank/emergency_oxygen/New() + . = ..() + air_contents.adjust((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/emergency_oxygen/engi + name = "extended-capacity emergency oxygen tank" + icon_state = "emergency_engi" + volume = 6 + +/obj/item/weapon/tank/emergency_oxygen/double + name = "double emergency oxygen tank" + icon_state = "emergency_double" + volume = 10 + +/obj/item/weapon/tank/emergency_nitrogen + name = "emergency nitrogen tank" + desc = "Used for emergencies. Not useful unless you only breathe nitrogen." + icon_state = "emergency_nitrogen" + slot_flags = SLOT_BELT + w_class = 2.0 + volume = 2 + +/obj/item/weapon/tank/emergency_nitrogen/New() + . = ..() + air_contents.adjust(, , (3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/* + * Nitrogen + */ +/obj/item/weapon/tank/nitrogen + name = "nitrogen tank" + desc = "A tank of nitrogen." + icon_state = "oxygen_fr" + distribute_pressure = ONE_ATMOSPHERE*O2STANDARD + +/obj/item/weapon/tank/nitrogen/New() + . = ..() + air_contents.adjust(, , (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 48f1b7e52d6..1c78be66585 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -1,292 +1,292 @@ -#define TANK_MAX_RELEASE_PRESSURE (3*ONE_ATMOSPHERE) -#define TANK_DEFAULT_RELEASE_PRESSURE 24 - -/obj/item/weapon/tank - name = "tank" - icon = 'icons/obj/tank.dmi' - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - - pressure_resistance = ONE_ATMOSPHERE*5 - - force = 5.0 - throwforce = 10.0 - throw_speed = 1 - throw_range = 4 - - var/datum/gas_mixture/air_contents = null - var/distribute_pressure = ONE_ATMOSPHERE - var/integrity = 3 - var/volume = 70 - var/manipulated_by = null //Used by _onclick/hud/screen_objects.dm internals to determine if someone has messed with our tank or not. - //If they have and we haven't scanned it with the PDA or gas analyzer then we might just breath whatever they put in it. -/obj/item/weapon/tank/New() - ..() - - src.air_contents = new /datum/gas_mixture() - src.air_contents.volume = volume //liters - src.air_contents.temperature = T20C - - processing_objects.Add(src) - return - -/obj/item/weapon/tank/Destroy() - if(air_contents) - qdel(air_contents) - air_contents = null - - if(istype(loc, /obj/machinery/portable_atmospherics)) - var/obj/machinery/portable_atmospherics/holder = loc - holder.holding = null - - processing_objects.Remove(src) - - ..() - -/obj/item/weapon/tank/examine(mob/user) - ..() - var/obj/icon = src - if (istype(src.loc, /obj/item/assembly)) - icon = src.loc - if (!in_range(src, user)) +#define TANK_MAX_RELEASE_PRESSURE (3*ONE_ATMOSPHERE) +#define TANK_DEFAULT_RELEASE_PRESSURE 24 + +/obj/item/weapon/tank + name = "tank" + icon = 'icons/obj/tank.dmi' + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + + pressure_resistance = ONE_ATMOSPHERE*5 + + force = 5.0 + throwforce = 10.0 + throw_speed = 1 + throw_range = 4 + + var/datum/gas_mixture/air_contents = null + var/distribute_pressure = ONE_ATMOSPHERE + var/integrity = 3 + var/volume = 70 + var/manipulated_by = null //Used by _onclick/hud/screen_objects.dm internals to determine if someone has messed with our tank or not. + //If they have and we haven't scanned it with the PDA or gas analyzer then we might just breath whatever they put in it. +/obj/item/weapon/tank/New() + ..() + + src.air_contents = new /datum/gas_mixture() + src.air_contents.volume = volume //liters + src.air_contents.temperature = T20C + + processing_objects.Add(src) + return + +/obj/item/weapon/tank/Destroy() + if(air_contents) + qdel(air_contents) + air_contents = null + + if(istype(loc, /obj/machinery/portable_atmospherics)) + var/obj/machinery/portable_atmospherics/holder = loc + holder.holding = null + + processing_objects.Remove(src) + + ..() + +/obj/item/weapon/tank/examine(mob/user) + ..() + var/obj/icon = src + if (istype(src.loc, /obj/item/assembly)) + icon = src.loc + if (!in_range(src, user)) if (icon == src) to_chat(user, "It's \a \icon[icon][src]! If you want any more information you'll need to get closer.") - return - - var/celsius_temperature = src.air_contents.temperature-T0C - var/descriptive - - if (celsius_temperature < 20) - descriptive = "cold" - else if (celsius_temperature < 40) - descriptive = "room temperature" - else if (celsius_temperature < 80) - descriptive = "lukewarm" - else if (celsius_temperature < 100) - descriptive = "warm" - else if (celsius_temperature < 300) - descriptive = "hot" - else - descriptive = "furiously hot" - + return + + var/celsius_temperature = src.air_contents.temperature-T0C + var/descriptive + + if (celsius_temperature < 20) + descriptive = "cold" + else if (celsius_temperature < 40) + descriptive = "room temperature" + else if (celsius_temperature < 80) + descriptive = "lukewarm" + else if (celsius_temperature < 100) + descriptive = "warm" + else if (celsius_temperature < 300) + descriptive = "hot" + else + descriptive = "furiously hot" + to_chat(user, "\The \icon[icon][src] feels [descriptive]") - - if(air_contents.volume * 10 < volume) + + if(air_contents.volume * 10 < volume) to_chat(user, "The meter on the [src.name] indicates you are almost out of gas!") - playsound(user, 'sound/effects/alert.ogg', 50, 1) - -/obj/item/weapon/tank/blob_act() - if(prob(50)) - var/turf/location = src.loc - if (!( istype(location, /turf) )) - qdel(src) - - if(src.air_contents) - location.assume_air(air_contents) - - qdel(src) - -/obj/item/weapon/tank/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - var/obj/icon = src - - if (istype(src.loc, /obj/item/assembly)) - icon = src.loc - - if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1) - user.visible_message("[user] has used [W] on \icon[icon] [src]", "You use \the [W] on \icon[icon] [src]") - var/obj/item/device/analyzer/analyzer = W - user.show_message(analyzer.output_gas_scan(src.air_contents, src, 0), 1) - src.add_fingerprint(user) - else if (istype(W,/obj/item/latexballon)) - var/obj/item/latexballon/LB = W - LB.blow(src) - src.add_fingerprint(user) - - if(istype(W, /obj/item/device/assembly_holder)) - bomb_assemble(W,user) - -/obj/item/weapon/tank/attack_self(mob/user as mob) - if (!(src.air_contents)) - return - - ui_interact(user) - -/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - - var/using_internal - if(istype(loc,/mob/living/carbon)) - var/mob/living/carbon/location = loc - if(location.internal==src) - using_internal = 1 - - // this is the data which will be sent to the ui - var/data[0] - data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) - data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0) - data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) - data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) - data["valveOpen"] = using_internal ? 1 : 0 - - data["maskConnected"] = 0 - if(istype(loc,/mob/living/carbon)) - var/mob/living/carbon/location = loc - if(location.internal == src || (location.wear_mask && (location.wear_mask.flags & MASKINTERNALS))) - data["maskConnected"] = 1 - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "tanks.tmpl", "Tank", 500, 300) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -/obj/item/weapon/tank/Topic(href, href_list) - ..() - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - if (usr.stat|| usr.restrained()) - return 0 - if (src.loc != usr) - return 0 - - if (href_list["dist_p"]) - if (href_list["dist_p"] == "reset") - src.distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE - else if (href_list["dist_p"] == "max") - src.distribute_pressure = TANK_MAX_RELEASE_PRESSURE - else - var/cp = text2num(href_list["dist_p"]) - src.distribute_pressure += cp - src.distribute_pressure = min(max(round(src.distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE) - if (href_list["stat"]) - if(istype(loc,/mob/living/carbon)) - var/mob/living/carbon/location = loc - if(location.internal == src) - location.internal = null - location.internals.icon_state = "internal0" + playsound(user, 'sound/effects/alert.ogg', 50, 1) + +/obj/item/weapon/tank/blob_act() + if(prob(50)) + var/turf/location = src.loc + if (!( istype(location, /turf) )) + qdel(src) + + if(src.air_contents) + location.assume_air(air_contents) + + qdel(src) + +/obj/item/weapon/tank/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + var/obj/icon = src + + if (istype(src.loc, /obj/item/assembly)) + icon = src.loc + + if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1) + user.visible_message("[user] has used [W] on \icon[icon] [src]", "You use \the [W] on \icon[icon] [src]") + var/obj/item/device/analyzer/analyzer = W + user.show_message(analyzer.output_gas_scan(src.air_contents, src, 0), 1) + src.add_fingerprint(user) + else if (istype(W,/obj/item/latexballon)) + var/obj/item/latexballon/LB = W + LB.blow(src) + src.add_fingerprint(user) + + if(istype(W, /obj/item/device/assembly_holder)) + bomb_assemble(W,user) + +/obj/item/weapon/tank/attack_self(mob/user as mob) + if (!(src.air_contents)) + return + + ui_interact(user) + +/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + + var/using_internal + if(istype(loc,/mob/living/carbon)) + var/mob/living/carbon/location = loc + if(location.internal==src) + using_internal = 1 + + // this is the data which will be sent to the ui + var/data[0] + data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) + data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0) + data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) + data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) + data["valveOpen"] = using_internal ? 1 : 0 + + data["maskConnected"] = 0 + if(istype(loc,/mob/living/carbon)) + var/mob/living/carbon/location = loc + if(location.internal == src || (location.wear_mask && (location.wear_mask.flags & MASKINTERNALS))) + data["maskConnected"] = 1 + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "tanks.tmpl", "Tank", 500, 300) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/item/weapon/tank/Topic(href, href_list) + ..() + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + if (usr.stat|| usr.restrained()) + return 0 + if (src.loc != usr) + return 0 + + if (href_list["dist_p"]) + if (href_list["dist_p"] == "reset") + src.distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE + else if (href_list["dist_p"] == "max") + src.distribute_pressure = TANK_MAX_RELEASE_PRESSURE + else + var/cp = text2num(href_list["dist_p"]) + src.distribute_pressure += cp + src.distribute_pressure = min(max(round(src.distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE) + if (href_list["stat"]) + if(istype(loc,/mob/living/carbon)) + var/mob/living/carbon/location = loc + if(location.internal == src) + location.internal = null + location.internals.icon_state = "internal0" to_chat(usr, "You close the tank release valve.") - if (location.internals) - location.internals.icon_state = "internal0" - else - if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS)) - location.internal = src + if (location.internals) + location.internals.icon_state = "internal0" + else + if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS)) + location.internal = src to_chat(usr, "You open \the [src] valve.") - if (location.internals) - location.internals.icon_state = "internal1" - else + if (location.internals) + location.internals.icon_state = "internal1" + else to_chat(usr, "You need something to connect to \the [src].") - - src.add_fingerprint(usr) - return 1 - - -/obj/item/weapon/tank/remove_air(amount) - return air_contents.remove(amount) - -/obj/item/weapon/tank/return_air() - return air_contents - -/obj/item/weapon/tank/assume_air(datum/gas_mixture/giver) - air_contents.merge(giver) - - check_status() - return 1 - -/obj/item/weapon/tank/proc/remove_air_volume(volume_to_return) - if(!air_contents) - return null - - var/tank_pressure = air_contents.return_pressure() - if(tank_pressure < distribute_pressure) - distribute_pressure = tank_pressure - - var/moles_needed = distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.temperature) - - return remove_air(moles_needed) - -/obj/item/weapon/tank/process() - //Allow for reactions - if(air_contents) - air_contents.react() - check_status() - - -/obj/item/weapon/tank/proc/check_status() - //Handle exploding, leaking, and rupturing of the tank - if(timestopped) return - - var/cap = 0 - var/uncapped = 0 - if(!air_contents) - return 0 - - var/pressure = air_contents.return_pressure() - if(pressure > TANK_FRAGMENT_PRESSURE) - if(!istype(src.loc,/obj/item/device/transfer_valve)) - message_admins("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") - log_game("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") + + src.add_fingerprint(usr) + return 1 + + +/obj/item/weapon/tank/remove_air(amount) + return air_contents.remove(amount) + +/obj/item/weapon/tank/return_air() + return air_contents + +/obj/item/weapon/tank/assume_air(datum/gas_mixture/giver) + air_contents.merge(giver) + + check_status() + return 1 + +/obj/item/weapon/tank/proc/remove_air_volume(volume_to_return) + if(!air_contents) + return null + + var/tank_pressure = air_contents.return_pressure() + if(tank_pressure < distribute_pressure) + distribute_pressure = tank_pressure + + var/moles_needed = distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + + return remove_air(moles_needed) + +/obj/item/weapon/tank/process() + //Allow for reactions + if(air_contents) + air_contents.react() + check_status() + + +/obj/item/weapon/tank/proc/check_status() + //Handle exploding, leaking, and rupturing of the tank + if(timestopped) return + + var/cap = 0 + var/uncapped = 0 + if(!air_contents) + return 0 + + var/pressure = air_contents.return_pressure() + if(pressure > TANK_FRAGMENT_PRESSURE) + if(!istype(src.loc,/obj/item/device/transfer_valve)) + message_admins("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") + log_game("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") // to_chat(world, "[x],[y] tank is exploding: [pressure] kPa") - //Give the gas a chance to build up more pressure through reacting - air_contents.react() - air_contents.react() - air_contents.react() - pressure = air_contents.return_pressure() - var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE - if(range > MAX_EXPLOSION_RANGE) - cap = 1 - uncapped = range - range = min(range, MAX_EXPLOSION_RANGE) // was 8 - - - Changed to a configurable define -- TLE - var/turf/epicenter = get_turf(loc) - + //Give the gas a chance to build up more pressure through reacting + air_contents.react() + air_contents.react() + air_contents.react() + pressure = air_contents.return_pressure() + var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE + if(range > MAX_EXPLOSION_RANGE) + cap = 1 + uncapped = range + range = min(range, MAX_EXPLOSION_RANGE) // was 8 - - - Changed to a configurable define -- TLE + var/turf/epicenter = get_turf(loc) + // to_chat(world, "Exploding Pressure: [pressure] kPa, intensity: [range]") - - explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5), 1, cap) - if(cap) - for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) - if(bhangmeter) - bhangmeter.sense_explosion(epicenter.x,epicenter.y,epicenter.z,round(uncapped*0.25), round(uncapped*0.5), round(uncapped),"???", cap) - - if(istype(src.loc,/obj/item/device/transfer_valve)) - var/obj/item/device/transfer_valve/TV = src.loc - TV.child_ruptured(src, range) - - qdel(src) - - return - - else if(pressure > TANK_RUPTURE_PRESSURE) + + explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5), 1, cap) + if(cap) + for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) + if(bhangmeter) + bhangmeter.sense_explosion(epicenter.x,epicenter.y,epicenter.z,round(uncapped*0.25), round(uncapped*0.5), round(uncapped),"???", cap) + + if(istype(src.loc,/obj/item/device/transfer_valve)) + var/obj/item/device/transfer_valve/TV = src.loc + TV.child_ruptured(src, range) + + qdel(src) + + return + + else if(pressure > TANK_RUPTURE_PRESSURE) // to_chat(world, "[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]") - if(integrity <= 0) - var/turf/simulated/T = get_turf(src) - if(!T) - return - T.assume_air(air_contents) - playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3) - - qdel(src) - - return - else - integrity-- - - else if(pressure > TANK_LEAK_PRESSURE) + if(integrity <= 0) + var/turf/simulated/T = get_turf(src) + if(!T) + return + T.assume_air(air_contents) + playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3) + + qdel(src) + + return + else + integrity-- + + else if(pressure > TANK_LEAK_PRESSURE) // to_chat(world, "[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]") - if(integrity <= 0) - var/turf/simulated/T = get_turf(src) - if(!T) - return - var/datum/gas_mixture/leaked_gas = air_contents.remove_ratio(0.25) - T.assume_air(leaked_gas) - else - integrity-- - - else if(integrity < 3) - integrity++ + if(integrity <= 0) + var/turf/simulated/T = get_turf(src) + if(!T) + return + var/datum/gas_mixture/leaked_gas = air_contents.remove_ratio(0.25) + T.assume_air(leaked_gas) + else + integrity-- + + else if(integrity < 3) + integrity++ diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 25440920b2c..7ebe7bcda75 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -1,217 +1,217 @@ -/* Teleportation devices. - * Contains: - * Locator - * Hand-tele - */ - -/* - * Locator - */ -/obj/item/weapon/locator - name = "locator" - desc = "Used to track those with locater implants." - icon = 'icons/obj/device.dmi' - icon_state = "locator" - var/temp = null - var/frequency = 1451 - var/broadcasting = null - var/listening = 1.0 - flags = FPRINT - siemens_coefficient = 1 - w_class = 2.0 - item_state = "electronic" - throw_speed = 4 - throw_range = 20 - starting_materials = list(MAT_IRON = 400) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=1" - -/obj/item/weapon/locator/attack_self(mob/user as mob) - user.set_machine(src) - var/dat - if (src.temp) - dat = "[src.temp]

    Clear" - else - dat = {" -Persistent Signal Locator
    -Frequency: -- -- [format_frequency(src.frequency)] -+ -+
    - -Refresh"} - user << browse(dat, "window=radio") - onclose(user, "radio") - return - -/obj/item/weapon/locator/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained()) - return - var/turf/current_location = get_turf(usr)//What turf is the user on? - if(!current_location||current_location.z==2)//If turf was not found or they're on z level 2. +/* Teleportation devices. + * Contains: + * Locator + * Hand-tele + */ + +/* + * Locator + */ +/obj/item/weapon/locator + name = "locator" + desc = "Used to track those with locater implants." + icon = 'icons/obj/device.dmi' + icon_state = "locator" + var/temp = null + var/frequency = 1451 + var/broadcasting = null + var/listening = 1.0 + flags = FPRINT + siemens_coefficient = 1 + w_class = 2.0 + item_state = "electronic" + throw_speed = 4 + throw_range = 20 + starting_materials = list(MAT_IRON = 400) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=1" + +/obj/item/weapon/locator/attack_self(mob/user as mob) + user.set_machine(src) + var/dat + if (src.temp) + dat = "[src.temp]

    Clear" + else + dat = {" +Persistent Signal Locator
    +Frequency: +- +- [format_frequency(src.frequency)] ++ ++
    + +Refresh"} + user << browse(dat, "window=radio") + onclose(user, "radio") + return + +/obj/item/weapon/locator/Topic(href, href_list) + ..() + if (usr.stat || usr.restrained()) + return + var/turf/current_location = get_turf(usr)//What turf is the user on? + if(!current_location||current_location.z==2)//If turf was not found or they're on z level 2. to_chat(usr, "The [src] is malfunctioning.") - return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) - usr.set_machine(src) - if (href_list["refresh"]) - src.temp = "Persistent Signal Locator
    " - var/turf/sr = get_turf(src) - - if (sr) - src.temp += "Located Beacons:
    " - - for(var/obj/item/beacon/W in beacons) - if (W.frequency == src.frequency) - var/turf/tr = get_turf(W) - if (tr.z == sr.z && tr) - var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) - if (direct < 5) - direct = "very strong" - else - if (direct < 10) - direct = "strong" - else - if (direct < 20) - direct = "weak" - else - direct = "very weak" - src.temp += "[W.code]-[dir2text(get_dir(sr, tr))]-[direct]
    " - - src.temp += "Extranneous Signals:
    " - for (var/obj/item/weapon/implant/tracking/W in world) - if (!W.implanted || !(istype(W.loc,/datum/organ/external) || ismob(W.loc))) - continue - else - var/mob/M = W.loc - if (M.stat == 2) - if (M.timeofdeath + 6000 < world.time) - continue - - var/turf/tr = get_turf(W) - if (tr.z == sr.z && tr) - var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) - if (direct < 20) - if (direct < 5) - direct = "very strong" - else - if (direct < 10) - direct = "strong" - else - direct = "weak" - src.temp += "[W.id]-[dir2text(get_dir(sr, tr))]-[direct]
    " - - src.temp += "You are at \[[sr.x-WORLD_X_OFFSET[sr.z]],[sr.y-WORLD_Y_OFFSET[sr.z]],[sr.z]\] in orbital coordinates.

    Refresh
    " - else - src.temp += "Processing Error: Unable to locate orbital position.
    " - else - if (href_list["freq"]) - src.frequency += text2num(href_list["freq"]) - src.frequency = sanitize_frequency(src.frequency) - else - if (href_list["temp"]) - src.temp = null - if (istype(src.loc, /mob)) - attack_self(src.loc) - else - for(var/mob/M in viewers(1, src)) - if (M.client) - src.attack_self(M) - return - - -/* - * Hand-tele - */ - #define HANDTELE_MAX_CHARGE 45 - #define HANDTELE_PORTAL_COST 15 -/obj/item/weapon/hand_tele - name = "hand tele" - desc = "A portable item using blue-space technology." - icon = 'icons/obj/device.dmi' - icon_state = "hand_tele" - item_state = "electronic" - throwforce = 5 - w_class = 2.0 - throw_speed = 3 - throw_range = 5 - starting_materials = list(MAT_IRON = 10000, MAT_GOLD = 500, MAT_PHAZON = 50) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=1;bluespace=3" - var/list/portals = list() - var/charge = HANDTELE_MAX_CHARGE//how many pairs of portal can the hand-tele sustain at once. a new charge is added every 30 seconds until the maximum is reached.. - var/recharging = 0 - -/obj/item/weapon/hand_tele/attack_self(mob/user as mob) - var/turf/current_location = get_turf(user)//What turf is the user on? - if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist. + return + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) + usr.set_machine(src) + if (href_list["refresh"]) + src.temp = "Persistent Signal Locator
    " + var/turf/sr = get_turf(src) + + if (sr) + src.temp += "Located Beacons:
    " + + for(var/obj/item/beacon/W in beacons) + if (W.frequency == src.frequency) + var/turf/tr = get_turf(W) + if (tr.z == sr.z && tr) + var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) + if (direct < 5) + direct = "very strong" + else + if (direct < 10) + direct = "strong" + else + if (direct < 20) + direct = "weak" + else + direct = "very weak" + src.temp += "[W.code]-[dir2text(get_dir(sr, tr))]-[direct]
    " + + src.temp += "Extranneous Signals:
    " + for (var/obj/item/weapon/implant/tracking/W in world) + if (!W.implanted || !(istype(W.loc,/datum/organ/external) || ismob(W.loc))) + continue + else + var/mob/M = W.loc + if (M.stat == 2) + if (M.timeofdeath + 6000 < world.time) + continue + + var/turf/tr = get_turf(W) + if (tr.z == sr.z && tr) + var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) + if (direct < 20) + if (direct < 5) + direct = "very strong" + else + if (direct < 10) + direct = "strong" + else + direct = "weak" + src.temp += "[W.id]-[dir2text(get_dir(sr, tr))]-[direct]
    " + + src.temp += "You are at \[[sr.x-WORLD_X_OFFSET[sr.z]],[sr.y-WORLD_Y_OFFSET[sr.z]],[sr.z]\] in orbital coordinates.

    Refresh
    " + else + src.temp += "Processing Error: Unable to locate orbital position.
    " + else + if (href_list["freq"]) + src.frequency += text2num(href_list["freq"]) + src.frequency = sanitize_frequency(src.frequency) + else + if (href_list["temp"]) + src.temp = null + if (istype(src.loc, /mob)) + attack_self(src.loc) + else + for(var/mob/M in viewers(1, src)) + if (M.client) + src.attack_self(M) + return + + +/* + * Hand-tele + */ + #define HANDTELE_MAX_CHARGE 45 + #define HANDTELE_PORTAL_COST 15 +/obj/item/weapon/hand_tele + name = "hand tele" + desc = "A portable item using blue-space technology." + icon = 'icons/obj/device.dmi' + icon_state = "hand_tele" + item_state = "electronic" + throwforce = 5 + w_class = 2.0 + throw_speed = 3 + throw_range = 5 + starting_materials = list(MAT_IRON = 10000, MAT_GOLD = 500, MAT_PHAZON = 50) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=1;bluespace=3" + var/list/portals = list() + var/charge = HANDTELE_MAX_CHARGE//how many pairs of portal can the hand-tele sustain at once. a new charge is added every 30 seconds until the maximum is reached.. + var/recharging = 0 + +/obj/item/weapon/hand_tele/attack_self(mob/user as mob) + var/turf/current_location = get_turf(user)//What turf is the user on? + if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist. to_chat(user, "\The [src] is malfunctioning.") - return - var/list/L = list( ) - for(var/obj/machinery/computer/teleporter/R in machines) - for(var/obj/machinery/teleport/hub/com in locate(R.x + 2, R.y, R.z)) - if(R.locked && !R.one_time_use) - if(com.engaged) - L["[R.id] (Active)"] = R.locked - else - L["[R.id] (Inactive)"] = R.locked - - var/list/turfs = new/list() - - for (var/turf/T in trange(10, user)) - // putting them at the edge is dumb - if (T.x > world.maxx - 8 || T.x < 8) - continue - - if (T.y > world.maxy - 8 || T.y < 8) - continue - - turfs += T - - if (turfs.len) - L["None (Dangerous)"] = pick(turfs) - - turfs = null - - var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L - - if((user.get_active_hand() != src || user.stat || user.restrained())) - return - if(charge < HANDTELE_PORTAL_COST) - user.show_message("\The [src] is recharging!") - return - var/T = L[t1] - - if((t1 == "None (Dangerous)") && prob(5)) - T = locate(rand(7, world.maxx - 7), rand(7, world.maxy -7), map.zTCommSat) - - var/turf/U = get_turf(src) - U.visible_message("Locked In.") - var/obj/effect/portal/P1 = new (U) - var/obj/effect/portal/P2 = new (get_turf(T)) - P1.target = P2 - P2.target = P1 - P2.icon_state = "portal1" - P1.creator = src - P2.creator = src - P1.blend_icon(P2) - P2.blend_icon(P1) - portals += P1 - portals += P2 - src.add_fingerprint(user) - - charge = max(charge - HANDTELE_PORTAL_COST,0) - if(!recharging) - recharging = 1 - processing_objects.Add(src) - -/obj/item/weapon/hand_tele/process() - charge = min(HANDTELE_MAX_CHARGE,charge+1) - if(charge >= HANDTELE_MAX_CHARGE) - processing_objects.Remove(src) - recharging = 0 - return 1 - - #undef HANDTELE_MAX_CHARGE - #undef HANDTELE_PORTAL_COST + return + var/list/L = list( ) + for(var/obj/machinery/computer/teleporter/R in machines) + for(var/obj/machinery/teleport/hub/com in locate(R.x + 2, R.y, R.z)) + if(R.locked && !R.one_time_use) + if(com.engaged) + L["[R.id] (Active)"] = R.locked + else + L["[R.id] (Inactive)"] = R.locked + + var/list/turfs = new/list() + + for (var/turf/T in trange(10, user)) + // putting them at the edge is dumb + if (T.x > world.maxx - 8 || T.x < 8) + continue + + if (T.y > world.maxy - 8 || T.y < 8) + continue + + turfs += T + + if (turfs.len) + L["None (Dangerous)"] = pick(turfs) + + turfs = null + + var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L + + if((user.get_active_hand() != src || user.stat || user.restrained())) + return + if(charge < HANDTELE_PORTAL_COST) + user.show_message("\The [src] is recharging!") + return + var/T = L[t1] + + if((t1 == "None (Dangerous)") && prob(5)) + T = locate(rand(7, world.maxx - 7), rand(7, world.maxy -7), map.zTCommSat) + + var/turf/U = get_turf(src) + U.visible_message("Locked In.") + var/obj/effect/portal/P1 = new (U) + var/obj/effect/portal/P2 = new (get_turf(T)) + P1.target = P2 + P2.target = P1 + P2.icon_state = "portal1" + P1.creator = src + P2.creator = src + P1.blend_icon(P2) + P2.blend_icon(P1) + portals += P1 + portals += P2 + src.add_fingerprint(user) + + charge = max(charge - HANDTELE_PORTAL_COST,0) + if(!recharging) + recharging = 1 + processing_objects.Add(src) + +/obj/item/weapon/hand_tele/process() + charge = min(HANDTELE_MAX_CHARGE,charge+1) + if(charge >= HANDTELE_MAX_CHARGE) + processing_objects.Remove(src) + recharging = 0 + return 1 + + #undef HANDTELE_MAX_CHARGE + #undef HANDTELE_PORTAL_COST diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index e542ddf27e7..7cbebd1f37e 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -1,735 +1,735 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/* Tools! - * Note: Multitools are /obj/item/device - * - * Contains: - * Wrench - * Screwdriver - * Wirecutters - * Welding Tool - * Crowbar - * Revolver Conversion Kit(made sense) - * Soldering Tool - * Fuel Can - */ - -/* Used for fancy tool subtypes that are faster or slower than the standard tool. - * The value for the key "construct" (or Co_CON_SPEED) is the multiplier for construction delay. - * The value for the key "deconstruct" (or Co_DECON_SPEED) is the multiplier for deconstruction delay, in case you hadn't guessed. - * If one is zero, the tool cannot be used in that direction. If you want to adminbus an instant tool, use .0001 or something, not 0. - * Don't set either to a negative number. It will probably break, though I'm not really sure in what way. - * Since this is a variable of /atom, it can technically be applied to any item used in construction, as long as the construction is based on construction datums. - * Yes, this allows for hyperspeed building stacks, but I wouldn't recommend that, as it doesn't carry over too well when stacks are merged or separated. - * Might work for borg stack modules, though. Worth looking into. - */ -/atom - var/list/construction_delay_mult = null - //Formatted as list(Co_CON_SPEED = value, Co_DECON_SPEED = value) - -/* - * Wrench - */ -/obj/item/weapon/wrench - name = "wrench" - desc = "A wrench with common uses. Can be found in your hand." - icon = 'icons/obj/items.dmi' - icon_state = "wrench" - hitsound = "sound/weapons/smash.ogg" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - force = 5.0 - throwforce = 7.0 - w_class = 2.0 - starting_materials = list(MAT_IRON = 150) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - origin_tech = "materials=1;engineering=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - -//we inherit a lot from wrench, so we change very little -/obj/item/weapon/wrench/socket - name = "socket wrench" - desc = "A wrench intended to be wrenchier than other wrenches. It's the wrenchiest." - icon_state = "socket_wrench" - w_class = 4.0 //big shit, to balance its power - -/* - * Screwdriver - */ -/obj/item/weapon/screwdriver - name = "screwdriver" - desc = "You can be totally screwy with this." - icon = 'icons/obj/items.dmi' - icon_state = "screwdriver" - hitsound = 'sound/weapons/toolhit.ogg' - flags = FPRINT - siemens_coefficient = 1 - sharpness = 1 - slot_flags = SLOT_BELT - force = 5.0 - w_class = 1.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - starting_materials = list(MAT_IRON = 75) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - attack_verb = list("stabbed") - -/obj/item/weapon/screwdriver/suicide_act(mob/user) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/* Tools! + * Note: Multitools are /obj/item/device + * + * Contains: + * Wrench + * Screwdriver + * Wirecutters + * Welding Tool + * Crowbar + * Revolver Conversion Kit(made sense) + * Soldering Tool + * Fuel Can + */ + +/* Used for fancy tool subtypes that are faster or slower than the standard tool. + * The value for the key "construct" (or Co_CON_SPEED) is the multiplier for construction delay. + * The value for the key "deconstruct" (or Co_DECON_SPEED) is the multiplier for deconstruction delay, in case you hadn't guessed. + * If one is zero, the tool cannot be used in that direction. If you want to adminbus an instant tool, use .0001 or something, not 0. + * Don't set either to a negative number. It will probably break, though I'm not really sure in what way. + * Since this is a variable of /atom, it can technically be applied to any item used in construction, as long as the construction is based on construction datums. + * Yes, this allows for hyperspeed building stacks, but I wouldn't recommend that, as it doesn't carry over too well when stacks are merged or separated. + * Might work for borg stack modules, though. Worth looking into. + */ +/atom + var/list/construction_delay_mult = null + //Formatted as list(Co_CON_SPEED = value, Co_DECON_SPEED = value) + +/* + * Wrench + */ +/obj/item/weapon/wrench + name = "wrench" + desc = "A wrench with common uses. Can be found in your hand." + icon = 'icons/obj/items.dmi' + icon_state = "wrench" + hitsound = "sound/weapons/smash.ogg" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + force = 5.0 + throwforce = 7.0 + w_class = 2.0 + starting_materials = list(MAT_IRON = 150) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + +//we inherit a lot from wrench, so we change very little +/obj/item/weapon/wrench/socket + name = "socket wrench" + desc = "A wrench intended to be wrenchier than other wrenches. It's the wrenchiest." + icon_state = "socket_wrench" + w_class = 4.0 //big shit, to balance its power + +/* + * Screwdriver + */ +/obj/item/weapon/screwdriver + name = "screwdriver" + desc = "You can be totally screwy with this." + icon = 'icons/obj/items.dmi' + icon_state = "screwdriver" + hitsound = 'sound/weapons/toolhit.ogg' + flags = FPRINT + siemens_coefficient = 1 + sharpness = 1 + slot_flags = SLOT_BELT + force = 5.0 + w_class = 1.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + starting_materials = list(MAT_IRON = 75) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + attack_verb = list("stabbed") + +/obj/item/weapon/screwdriver/suicide_act(mob/user) to_chat(viewers(user), pick("[user] is stabbing the [src.name] into \his temple! It looks like \he's trying to commit suicide.", \ - "[user] is stabbing the [src.name] into \his heart! It looks like \he's trying to commit suicide.")) - return(BRUTELOSS) - -/obj/item/weapon/screwdriver/New() - . = ..() - - switch(pick("red","blue","purple","brown","green","cyan","yellow")) - if ("red") - icon_state = "screwdriver2" - item_state = "screwdriver" - if ("blue") - icon_state = "screwdriver" - item_state = "screwdriver_blue" - if ("purple") - icon_state = "screwdriver3" - item_state = "screwdriver_purple" - if ("brown") - icon_state = "screwdriver4" - item_state = "screwdriver_brown" - if ("green") - icon_state = "screwdriver5" - item_state = "screwdriver_green" - if ("cyan") - icon_state = "screwdriver6" - item_state = "screwdriver_cyan" - if ("yellow") - icon_state = "screwdriver7" - item_state = "screwdriver_yellow" - - if (prob(75)) - src.pixel_y = rand(0, 16) - -/obj/item/weapon/screwdriver/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M)) return ..() - if(user.zone_sel.selecting != "eyes" && user.zone_sel.selecting != "head") - return ..() - if((M_CLUMSY in user.mutations) && prob(50)) - M = user - return eyestab(M,user) - -/obj/item/weapon/screwdriver/attackby(var/obj/O) - if(istype(O, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = O - var/mob/M = usr - if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned) - if(!istype(M.loc,/turf)) return - if(C.amount < 10) + "[user] is stabbing the [src.name] into \his heart! It looks like \he's trying to commit suicide.")) + return(BRUTELOSS) + +/obj/item/weapon/screwdriver/New() + . = ..() + + switch(pick("red","blue","purple","brown","green","cyan","yellow")) + if ("red") + icon_state = "screwdriver2" + item_state = "screwdriver" + if ("blue") + icon_state = "screwdriver" + item_state = "screwdriver_blue" + if ("purple") + icon_state = "screwdriver3" + item_state = "screwdriver_purple" + if ("brown") + icon_state = "screwdriver4" + item_state = "screwdriver_brown" + if ("green") + icon_state = "screwdriver5" + item_state = "screwdriver_green" + if ("cyan") + icon_state = "screwdriver6" + item_state = "screwdriver_cyan" + if ("yellow") + icon_state = "screwdriver7" + item_state = "screwdriver_yellow" + + if (prob(75)) + src.pixel_y = rand(0, 16) + +/obj/item/weapon/screwdriver/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(!istype(M)) return ..() + if(user.zone_sel.selecting != "eyes" && user.zone_sel.selecting != "head") + return ..() + if((M_CLUMSY in user.mutations) && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/weapon/screwdriver/attackby(var/obj/O) + if(istype(O, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = O + var/mob/M = usr + if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned) + if(!istype(M.loc,/turf)) return + if(C.amount < 10) to_chat(usr, "You need at least 10 lengths to make a bolas wire!") - return - var/obj/item/weapon/legcuffs/bolas/cable/B = new /obj/item/weapon/legcuffs/bolas/cable(usr.loc) - qdel(src) - B.icon_state = "cbolas_[C._color]" - B.cable_color = C._color - B.screw_state = item_state - B.screw_istate = icon_state + return + var/obj/item/weapon/legcuffs/bolas/cable/B = new /obj/item/weapon/legcuffs/bolas/cable(usr.loc) + qdel(src) + B.icon_state = "cbolas_[C._color]" + B.cable_color = C._color + B.screw_state = item_state + B.screw_istate = icon_state to_chat(M, "You wind some cable around the screwdriver handle to make a bolas wire.") - C.use(10) - else + C.use(10) + else to_chat(usr, "You cannot do that.") - else - ..() -/* - * Wirecutters - */ -/obj/item/weapon/wirecutters - name = "wirecutters" - desc = "This cuts wires." - icon = 'icons/obj/items.dmi' - icon_state = "cutters" - hitsound = 'sound/weapons/toolhit.ogg' - flags = FPRINT - siemens_coefficient = 1 - sharpness = 1 - slot_flags = SLOT_BELT - force = 6.0 - throw_speed = 2 - throw_range = 9 - w_class = 2.0 - starting_materials = list(MAT_IRON = 80) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - origin_tech = "materials=1;engineering=1" - attack_verb = list("pinched", "nipped") - -/obj/item/weapon/wirecutters/New() - . = ..() - - if(prob(50)) - icon_state = "cutters-y" - item_state = "cutters_yellow" - -/obj/item/weapon/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob) - if((C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable))) - usr.visible_message("\The [usr] cuts \the [C]'s restraints with \the [src]!",\ - "You cut \the [C]'s restraints with \the [src]!",\ - "You hear cable being cut.") - C.handcuffed.loc = null //garbage collector awaaaaay - C.handcuffed = null - C.update_inv_handcuffed() - return - else - ..() -/* - * Welding Tool - */ -/obj/item/weapon/weldingtool - name = "welding tool" - icon = 'icons/obj/items.dmi' - icon_state = "welder" - hitsound = 'sound/weapons/toolhit.ogg' - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - - //Amount of OUCH when it's thrown - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - sharpness = 0.8 - heat_production = 3800 - - //Cost to make in the autolathe - starting_materials = list(MAT_IRON = 70, MAT_GLASS = 30) - w_type = RECYK_MISC - melt_temperature = MELTPOINT_PLASTIC - - //R&D tech level - origin_tech = "engineering=1" - - //Welding tool specific stuff - var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) - var/status = 1 //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) - var/max_fuel = 20 //The max amount of fuel the welder can hold - var/start_fueled = 1 //Explicit, should the welder start with fuel in it ? - -/obj/item/weapon/weldingtool/suicide_act(mob/user) - user.visible_message("[user] is burning \his face off with the [src.name]! It looks like \he's trying to commit suicide!") - return (FIRELOSS|OXYLOSS) - -/obj/item/weapon/weldingtool/New() - . = ..() - create_reagents(max_fuel) - if(start_fueled) - reagents.add_reagent("fuel", max_fuel) - -/obj/item/weapon/weldingtool/examine(mob/user) - ..() + else + ..() +/* + * Wirecutters + */ +/obj/item/weapon/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/items.dmi' + icon_state = "cutters" + hitsound = 'sound/weapons/toolhit.ogg' + flags = FPRINT + siemens_coefficient = 1 + sharpness = 1 + slot_flags = SLOT_BELT + force = 6.0 + throw_speed = 2 + throw_range = 9 + w_class = 2.0 + starting_materials = list(MAT_IRON = 80) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + origin_tech = "materials=1;engineering=1" + attack_verb = list("pinched", "nipped") + +/obj/item/weapon/wirecutters/New() + . = ..() + + if(prob(50)) + icon_state = "cutters-y" + item_state = "cutters_yellow" + +/obj/item/weapon/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob) + if((C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable))) + usr.visible_message("\The [usr] cuts \the [C]'s restraints with \the [src]!",\ + "You cut \the [C]'s restraints with \the [src]!",\ + "You hear cable being cut.") + C.handcuffed.loc = null //garbage collector awaaaaay + C.handcuffed = null + C.update_inv_handcuffed() + return + else + ..() +/* + * Welding Tool + */ +/obj/item/weapon/weldingtool + name = "welding tool" + icon = 'icons/obj/items.dmi' + icon_state = "welder" + hitsound = 'sound/weapons/toolhit.ogg' + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + + //Amount of OUCH when it's thrown + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + sharpness = 0.8 + heat_production = 3800 + + //Cost to make in the autolathe + starting_materials = list(MAT_IRON = 70, MAT_GLASS = 30) + w_type = RECYK_MISC + melt_temperature = MELTPOINT_PLASTIC + + //R&D tech level + origin_tech = "engineering=1" + + //Welding tool specific stuff + var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2) + var/status = 1 //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower) + var/max_fuel = 20 //The max amount of fuel the welder can hold + var/start_fueled = 1 //Explicit, should the welder start with fuel in it ? + +/obj/item/weapon/weldingtool/suicide_act(mob/user) + user.visible_message("[user] is burning \his face off with the [src.name]! It looks like \he's trying to commit suicide!") + return (FIRELOSS|OXYLOSS) + +/obj/item/weapon/weldingtool/New() + . = ..() + create_reagents(max_fuel) + if(start_fueled) + reagents.add_reagent("fuel", max_fuel) + +/obj/item/weapon/weldingtool/examine(mob/user) + ..() to_chat(user, "It contains [get_fuel()]/[src.max_fuel] units of fuel!") - -/obj/item/weapon/weldingtool/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/screwdriver)) - if(welding) + +/obj/item/weapon/weldingtool/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W,/obj/item/weapon/screwdriver)) + if(welding) to_chat(user, "Stop welding first!") - return - status = !status - if(status) + return + status = !status + if(status) to_chat(user, "You resecure the welder.") - else + else to_chat(user, "The welder can now be attached and modified.") - src.add_fingerprint(user) - return - - if((!status) && (istype(W,/obj/item/stack/rods))) - var/obj/item/stack/rods/R = W - R.use(1) - var/obj/item/weapon/flamethrower/F = new/obj/item/weapon/flamethrower(user.loc) - src.loc = F - F.weldtool = src - if (user.client) - user.client.screen -= src - if (user.r_hand == src) - user.u_equip(src,0) - else - user.u_equip(src,0) - src.master = F - src.layer = initial(src.layer) - user.u_equip(src,0) - if (user.client) - user.client.screen -= src - src.loc = F - src.add_fingerprint(user) - return - - ..() - return - - -/obj/item/weapon/weldingtool/process() - switch(welding) - //If off - if(0) - if(src.icon_state != "welder") //Check that the sprite is correct, if it isnt, it means toggle() was not called - src.force = 3 - src.damtype = "brute" - src.icon_state = "welder" - src.hitsound = "sound/weapons/toolhit.ogg" - src.welding = 0 - processing_objects.Remove(src) - return - //Welders left on now use up fuel, but lets not have them run out quite that fast - if(1) - if(src.icon_state != "welder1") //Check that the sprite is correct, if it isnt, it means toggle() was not called - src.force = 15 - src.damtype = "fire" - src.icon_state = "welder1" - src.hitsound = "sound/weapons/welderattack.ogg" - if(prob(5)) - remove_fuel(1) - - //If you're actually actively welding, use fuel faster. - //Is this actually used or set anywhere? - Nodrak - if(2) - if(prob(75)) - remove_fuel(1) - - - //I'm not sure what this does. I assume it has to do with starting fires... - //...but it doesnt check to see if the welder is on or not. - var/turf/location = src.loc - if(istype(location, /mob/)) - var/mob/M = location - if(M.l_hand == src || M.r_hand == src) - location = get_turf(M) - if (istype(location, /turf)) - location.hotspot_expose(700, 5,surfaces=istype(loc,/turf)) - - -/obj/item/weapon/weldingtool/afterattack(obj/O as obj, mob/user as mob, proximity) - if(!proximity) return - if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && !src.welding) - O.reagents.trans_to(src, max_fuel) + src.add_fingerprint(user) + return + + if((!status) && (istype(W,/obj/item/stack/rods))) + var/obj/item/stack/rods/R = W + R.use(1) + var/obj/item/weapon/flamethrower/F = new/obj/item/weapon/flamethrower(user.loc) + src.loc = F + F.weldtool = src + if (user.client) + user.client.screen -= src + if (user.r_hand == src) + user.u_equip(src,0) + else + user.u_equip(src,0) + src.master = F + src.layer = initial(src.layer) + user.u_equip(src,0) + if (user.client) + user.client.screen -= src + src.loc = F + src.add_fingerprint(user) + return + + ..() + return + + +/obj/item/weapon/weldingtool/process() + switch(welding) + //If off + if(0) + if(src.icon_state != "welder") //Check that the sprite is correct, if it isnt, it means toggle() was not called + src.force = 3 + src.damtype = "brute" + src.icon_state = "welder" + src.hitsound = "sound/weapons/toolhit.ogg" + src.welding = 0 + processing_objects.Remove(src) + return + //Welders left on now use up fuel, but lets not have them run out quite that fast + if(1) + if(src.icon_state != "welder1") //Check that the sprite is correct, if it isnt, it means toggle() was not called + src.force = 15 + src.damtype = "fire" + src.icon_state = "welder1" + src.hitsound = "sound/weapons/welderattack.ogg" + if(prob(5)) + remove_fuel(1) + + //If you're actually actively welding, use fuel faster. + //Is this actually used or set anywhere? - Nodrak + if(2) + if(prob(75)) + remove_fuel(1) + + + //I'm not sure what this does. I assume it has to do with starting fires... + //...but it doesnt check to see if the welder is on or not. + var/turf/location = src.loc + if(istype(location, /mob/)) + var/mob/M = location + if(M.l_hand == src || M.r_hand == src) + location = get_turf(M) + if (istype(location, /turf)) + location.hotspot_expose(700, 5,surfaces=istype(loc,/turf)) + + +/obj/item/weapon/weldingtool/afterattack(obj/O as obj, mob/user as mob, proximity) + if(!proximity) return + if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && !src.welding) + O.reagents.trans_to(src, max_fuel) to_chat(user, "Welder refueled") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) - return - else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && src.welding) - message_admins("[key_name_admin(user)] triggered a fueltank explosion.") - log_game("[key_name(user)] triggered a fueltank explosion.") + playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + return + else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && src.welding) + message_admins("[key_name_admin(user)] triggered a fueltank explosion.") + log_game("[key_name(user)] triggered a fueltank explosion.") to_chat(user, "That was stupid of you.") - var/obj/structure/reagent_dispensers/fueltank/tank = O - tank.explode() - return - if (src.welding) - remove_fuel(1) - var/turf/location = get_turf(user) - if (istype(location, /turf)) - location.hotspot_expose(700, 50, 1,surfaces=1) - if(isliving(O)) - var/mob/living/L = O - L.IgniteMob() - return - - -/obj/item/weapon/weldingtool/attack_self(mob/user as mob) - toggle() - return - -//Returns the amount of fuel in the welder -/obj/item/weapon/weldingtool/proc/get_fuel() - return reagents.get_reagent_amount("fuel") - - -//Removes fuel from the welding tool. If a mob is passed, it will perform an eyecheck on the mob. This should probably be renamed to use() -/obj/item/weapon/weldingtool/proc/remove_fuel(var/amount = 1, var/mob/M = null) - if(!welding || !check_fuel()) - return 0 - if(get_fuel() >= amount) - reagents.remove_reagent("fuel", amount) - check_fuel() - if(M) - eyecheck(M) - return 1 - else - if(M) + var/obj/structure/reagent_dispensers/fueltank/tank = O + tank.explode() + return + if (src.welding) + remove_fuel(1) + var/turf/location = get_turf(user) + if (istype(location, /turf)) + location.hotspot_expose(700, 50, 1,surfaces=1) + if(isliving(O)) + var/mob/living/L = O + L.IgniteMob() + return + + +/obj/item/weapon/weldingtool/attack_self(mob/user as mob) + toggle() + return + +//Returns the amount of fuel in the welder +/obj/item/weapon/weldingtool/proc/get_fuel() + return reagents.get_reagent_amount("fuel") + + +//Removes fuel from the welding tool. If a mob is passed, it will perform an eyecheck on the mob. This should probably be renamed to use() +/obj/item/weapon/weldingtool/proc/remove_fuel(var/amount = 1, var/mob/M = null) + if(!welding || !check_fuel()) + return 0 + if(get_fuel() >= amount) + reagents.remove_reagent("fuel", amount) + check_fuel() + if(M) + eyecheck(M) + return 1 + else + if(M) to_chat(M, "You need more welding fuel to complete this task.") - return 0 - -//Returns whether or not the welding tool is currently on. -/obj/item/weapon/weldingtool/proc/isOn() - return src.welding - - -/obj/item/weapon/weldingtool/is_hot() - if(isOn()) - return heat_production - return 0 - - -/obj/item/weapon/weldingtool/is_sharp() - if(isOn()) - return sharpness - return 0 - -//Sets the welding state of the welding tool. If you see W.welding = 1 anywhere, please change it to W.setWelding(1) -//so that the welding tool updates accordingly -/obj/item/weapon/weldingtool/proc/setWelding(var/temp_welding) - //If we're turning it on - if(temp_welding > 0) - if (remove_fuel(1)) + return 0 + +//Returns whether or not the welding tool is currently on. +/obj/item/weapon/weldingtool/proc/isOn() + return src.welding + + +/obj/item/weapon/weldingtool/is_hot() + if(isOn()) + return heat_production + return 0 + + +/obj/item/weapon/weldingtool/is_sharp() + if(isOn()) + return sharpness + return 0 + +//Sets the welding state of the welding tool. If you see W.welding = 1 anywhere, please change it to W.setWelding(1) +//so that the welding tool updates accordingly +/obj/item/weapon/weldingtool/proc/setWelding(var/temp_welding) + //If we're turning it on + if(temp_welding > 0) + if (remove_fuel(1)) to_chat(usr, "\The [src] switches on.") - src.force = 15 - src.damtype = "fire" - src.icon_state = "welder1" - processing_objects.Add(src) - else + src.force = 15 + src.damtype = "fire" + src.icon_state = "welder1" + processing_objects.Add(src) + else to_chat(usr, "Need more fuel!") - src.welding = 0 - return - //Otherwise - else + src.welding = 0 + return + //Otherwise + else to_chat(usr, "\The [src] switches off.") - src.force = 3 - src.damtype = "brute" - src.icon_state = "welder" - src.welding = 0 - -//Turns off the welder if there is no more fuel (does this really need to be its own proc?) -/obj/item/weapon/weldingtool/proc/check_fuel() - if((get_fuel() <= 0) && welding) - toggle(1) - return 0 - return 1 - - -//Toggles the welder off and on -/obj/item/weapon/weldingtool/proc/toggle(var/message = 0) - if(!status) return - src.welding = !( src.welding ) - if (src.welding) - if (remove_fuel(1)) + src.force = 3 + src.damtype = "brute" + src.icon_state = "welder" + src.welding = 0 + +//Turns off the welder if there is no more fuel (does this really need to be its own proc?) +/obj/item/weapon/weldingtool/proc/check_fuel() + if((get_fuel() <= 0) && welding) + toggle(1) + return 0 + return 1 + + +//Toggles the welder off and on +/obj/item/weapon/weldingtool/proc/toggle(var/message = 0) + if(!status) return + src.welding = !( src.welding ) + if (src.welding) + if (remove_fuel(1)) to_chat(usr, "You switch the [src] on.") - src.force = 15 - src.damtype = "fire" - src.icon_state = "welder1" - processing_objects.Add(src) - else + src.force = 15 + src.damtype = "fire" + src.icon_state = "welder1" + processing_objects.Add(src) + else to_chat(usr, "Need more fuel!") - src.welding = 0 - return - else - if(!message) + src.welding = 0 + return + else + if(!message) to_chat(usr, "You switch the [src] off.") - else + else to_chat(usr, "\The [src] shuts off!") - src.force = 3 - src.damtype = "brute" - src.icon_state = "welder" - src.welding = 0 - -//Decides whether or not to damage a player's eyes based on what they're wearing as protection -//Note: This should probably be moved to mob -/obj/item/weapon/weldingtool/proc/eyecheck(mob/user as mob) - if(!iscarbon(user)) return 1 - var/safety = user:eyecheck() - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if(!E) - return - if(H.species.flags & IS_SYNTHETIC) - return - if(safety < 2) - switch(safety) - if(1) - usr.simple_message("Your eyes sting a little.",\ - "You shed a tear.") - E.damage += rand(1, 2) - if(E.damage > 12) - user.eye_blurry += rand(3,6) - if(0) - usr.simple_message("Your eyes burn.",\ - "Some tears fall down from your eyes.") - E.damage += rand(2, 4) - if(E.damage > 10) - E.damage += rand(4,10) - if(-1) - var/obj/item/clothing/to_blame = H.head //blame the hat - if(!to_blame || (istype(to_blame) && H.glasses && H.glasses.eyeprot < to_blame.eyeprot)) //if we don't have a hat, the issue is the glasses. Otherwise, if the glasses are worse, blame the glasses - to_blame = H.glasses - usr.simple_message("Your [to_blame] intensifies the welder's glow. Your eyes itch and burn severely.",\ - "Somebody's cutting onions.") - user.eye_blurry += rand(12,20) - E.damage += rand(12, 16) - if(E.damage > 10 && safety < 2) - user.simple_message("Your eyes are really starting to hurt. This can't be good for you!",\ - "This is too sad! You start to cry.") - if (E.damage >= E.min_broken_damage) - user.simple_message("You go blind!","Somebody turns the lights off.") - user.sdisabilities |= BLIND - else if (E.damage >= E.min_bruised_damage) - user.simple_message("You go blind!","Somebody turns the lights off.") - user.eye_blind = 5 - user.eye_blurry = 5 - user.disabilities |= NEARSIGHTED - spawn(100) - user.disabilities &= ~NEARSIGHTED - return - -/obj/item/weapon/weldingtool/empty - start_fueled = 0 - -/obj/item/weapon/weldingtool/largetank - name = "Industrial Welding Tool" - max_fuel = 40 - starting_materials = list(MAT_IRON = 70, MAT_GLASS = 60) - origin_tech = "engineering=2" - -/obj/item/weapon/weldingtool/largetank/empty - start_fueled = 0 - -/obj/item/weapon/weldingtool/hugetank - name = "Upgraded Welding Tool" - max_fuel = 80 - w_class = 3.0 - starting_materials = list(MAT_IRON = 70, MAT_GLASS = 120) - origin_tech = "engineering=3" - -/obj/item/weapon/weldingtool/hugetank/empty - start_fueled = 0 - -/obj/item/weapon/weldingtool/experimental - name = "Experimental Welding Tool" - max_fuel = 40 - w_class = 3.0 - starting_materials = list(MAT_IRON = 70, MAT_GLASS = 120) - origin_tech = "engineering=4;plasmatech=3" - icon_state = "ewelder" - var/last_gen = 0 - -/obj/item/weapon/weldingtool/experimental/empty - start_fueled = 0 - -/obj/item/weapon/weldingtool/experimental/proc/fuel_gen()//Proc to make the experimental welder generate fuel, optimized as fuck -Sieve - var/gen_amount = ((world.time-last_gen)/25) //Too bad it's not actually implemented - reagents += (gen_amount) - if(reagents > max_fuel) - reagents = max_fuel - -/* - * Crowbar - */ - -/obj/item/weapon/crowbar - name = "crowbar" - desc = "Used to hit floors" - icon = 'icons/obj/items.dmi' - icon_state = "crowbar" - hitsound = "sound/weapons/toolhit.ogg" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - force = 5.0 - throwforce = 7.0 - item_state = "crowbar" - w_class = 2.0 - starting_materials = list(MAT_IRON = 50) - w_type = RECYK_METAL - melt_temperature = MELTPOINT_STEEL - origin_tech = "engineering=1" - attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") - - - suicide_act(mob/user) + src.force = 3 + src.damtype = "brute" + src.icon_state = "welder" + src.welding = 0 + +//Decides whether or not to damage a player's eyes based on what they're wearing as protection +//Note: This should probably be moved to mob +/obj/item/weapon/weldingtool/proc/eyecheck(mob/user as mob) + if(!iscarbon(user)) return 1 + var/safety = user:eyecheck() + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] + if(!E) + return + if(H.species.flags & IS_SYNTHETIC) + return + if(safety < 2) + switch(safety) + if(1) + usr.simple_message("Your eyes sting a little.",\ + "You shed a tear.") + E.damage += rand(1, 2) + if(E.damage > 12) + user.eye_blurry += rand(3,6) + if(0) + usr.simple_message("Your eyes burn.",\ + "Some tears fall down from your eyes.") + E.damage += rand(2, 4) + if(E.damage > 10) + E.damage += rand(4,10) + if(-1) + var/obj/item/clothing/to_blame = H.head //blame the hat + if(!to_blame || (istype(to_blame) && H.glasses && H.glasses.eyeprot < to_blame.eyeprot)) //if we don't have a hat, the issue is the glasses. Otherwise, if the glasses are worse, blame the glasses + to_blame = H.glasses + usr.simple_message("Your [to_blame] intensifies the welder's glow. Your eyes itch and burn severely.",\ + "Somebody's cutting onions.") + user.eye_blurry += rand(12,20) + E.damage += rand(12, 16) + if(E.damage > 10 && safety < 2) + user.simple_message("Your eyes are really starting to hurt. This can't be good for you!",\ + "This is too sad! You start to cry.") + if (E.damage >= E.min_broken_damage) + user.simple_message("You go blind!","Somebody turns the lights off.") + user.sdisabilities |= BLIND + else if (E.damage >= E.min_bruised_damage) + user.simple_message("You go blind!","Somebody turns the lights off.") + user.eye_blind = 5 + user.eye_blurry = 5 + user.disabilities |= NEARSIGHTED + spawn(100) + user.disabilities &= ~NEARSIGHTED + return + +/obj/item/weapon/weldingtool/empty + start_fueled = 0 + +/obj/item/weapon/weldingtool/largetank + name = "Industrial Welding Tool" + max_fuel = 40 + starting_materials = list(MAT_IRON = 70, MAT_GLASS = 60) + origin_tech = "engineering=2" + +/obj/item/weapon/weldingtool/largetank/empty + start_fueled = 0 + +/obj/item/weapon/weldingtool/hugetank + name = "Upgraded Welding Tool" + max_fuel = 80 + w_class = 3.0 + starting_materials = list(MAT_IRON = 70, MAT_GLASS = 120) + origin_tech = "engineering=3" + +/obj/item/weapon/weldingtool/hugetank/empty + start_fueled = 0 + +/obj/item/weapon/weldingtool/experimental + name = "Experimental Welding Tool" + max_fuel = 40 + w_class = 3.0 + starting_materials = list(MAT_IRON = 70, MAT_GLASS = 120) + origin_tech = "engineering=4;plasmatech=3" + icon_state = "ewelder" + var/last_gen = 0 + +/obj/item/weapon/weldingtool/experimental/empty + start_fueled = 0 + +/obj/item/weapon/weldingtool/experimental/proc/fuel_gen()//Proc to make the experimental welder generate fuel, optimized as fuck -Sieve + var/gen_amount = ((world.time-last_gen)/25) //Too bad it's not actually implemented + reagents += (gen_amount) + if(reagents > max_fuel) + reagents = max_fuel + +/* + * Crowbar + */ + +/obj/item/weapon/crowbar + name = "crowbar" + desc = "Used to hit floors" + icon = 'icons/obj/items.dmi' + icon_state = "crowbar" + hitsound = "sound/weapons/toolhit.ogg" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + force = 5.0 + throwforce = 7.0 + item_state = "crowbar" + w_class = 2.0 + starting_materials = list(MAT_IRON = 50) + w_type = RECYK_METAL + melt_temperature = MELTPOINT_STEEL + origin_tech = "engineering=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + + + suicide_act(mob/user) to_chat(viewers(user), "[user] is smashing \his head in with the [src.name]! It looks like \he's trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/weapon/crowbar/red - desc = "Rise and shine." - icon = 'icons/obj/items.dmi' - icon_state = "red_crowbar" - item_state = "crowbar_red" - - suicide_act(mob/user) + return (BRUTELOSS) + +/obj/item/weapon/crowbar/red + desc = "Rise and shine." + icon = 'icons/obj/items.dmi' + icon_state = "red_crowbar" + item_state = "crowbar_red" + + suicide_act(mob/user) to_chat(viewers(user), "[user] is smashing \his head in with the [src.name]! It looks like \he's done waiting for half life three!") - return (BRUTELOSS) - - -/obj/item/weapon/weldingtool/attack(mob/M as mob, mob/user as mob) - if(hasorgans(M)) - if(can_operate(M)) - if(do_surgery(M, user, src)) - return - var/datum/organ/external/S = M:organs_by_name[user.zone_sel.selecting] - if (!S) return - if(!(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP) - return ..() - if(S.brute_dam) - S.heal_damage(15,0,0,1) - if(user != M) - user.visible_message("\The [user] patches some dents on \the [M]'s [S.display_name] with \the [src]",\ - "You patch some dents on \the [M]'s [S.display_name]",\ - "You hear a welder.") - else - user.visible_message("\The [user] patches some dents on their [S.display_name] with \the [src]",\ - "You patch some dents on your [S.display_name]",\ - "You hear a welder.") - else + return (BRUTELOSS) + + +/obj/item/weapon/weldingtool/attack(mob/M as mob, mob/user as mob) + if(hasorgans(M)) + if(can_operate(M)) + if(do_surgery(M, user, src)) + return + var/datum/organ/external/S = M:organs_by_name[user.zone_sel.selecting] + if (!S) return + if(!(S.status & ORGAN_ROBOT) || user.a_intent != I_HELP) + return ..() + if(S.brute_dam) + S.heal_damage(15,0,0,1) + if(user != M) + user.visible_message("\The [user] patches some dents on \the [M]'s [S.display_name] with \the [src]",\ + "You patch some dents on \the [M]'s [S.display_name]",\ + "You hear a welder.") + else + user.visible_message("\The [user] patches some dents on their [S.display_name] with \the [src]",\ + "You patch some dents on your [S.display_name]",\ + "You hear a welder.") + else to_chat(user, "Nothing to fix!") - else - return ..() - -/obj/item/weapon/conversion_kit - name = "\improper Revolver Conversion Kit" - desc = "A professional conversion kit used to convert any knock off revolver into the real deal capable of shooting lethal .357 rounds without the possibility of catastrophic failure" - icon = 'icons/obj/weapons.dmi' - icon_state = "kit" - flags = FPRINT - siemens_coefficient = 1 - w_class = 2.0 - w_type = RECYK_MISC - origin_tech = "combat=2" - var/open = 0 - - New() - ..() - update_icon() - - update_icon() - icon_state = "[initial(icon_state)]_[open]" - - attack_self(mob/user as mob) - open = !open + else + return ..() + +/obj/item/weapon/conversion_kit + name = "\improper Revolver Conversion Kit" + desc = "A professional conversion kit used to convert any knock off revolver into the real deal capable of shooting lethal .357 rounds without the possibility of catastrophic failure" + icon = 'icons/obj/weapons.dmi' + icon_state = "kit" + flags = FPRINT + siemens_coefficient = 1 + w_class = 2.0 + w_type = RECYK_MISC + origin_tech = "combat=2" + var/open = 0 + + New() + ..() + update_icon() + + update_icon() + icon_state = "[initial(icon_state)]_[open]" + + attack_self(mob/user as mob) + open = !open to_chat(user, "You [open?"open" : "close"] the conversion kit.") - update_icon() - -/* - * Soldering Iron - */ -/obj/item/weapon/solder - name = "soldering iron" - icon = 'icons/obj/items.dmi' - icon_state = "solder-0" - hitsound = 'sound/weapons/toolhit.ogg' - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - force = 3.0 - sharpness = 1 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - starting_materials = list(MAT_IRON = 70, MAT_GLASS = 30) - w_type = RECYK_MISC - melt_temperature = MELTPOINT_STEEL - origin_tech = "engineering=1" - var/max_fuel = 20 //The max amount of acid stored - -/obj/item/weapon/solder/New() - . = ..() - create_reagents(max_fuel) - //Does not come fueled up - -/obj/item/weapon/solder/update_icon() - ..() - switch(reagents.get_reagent_amount("sacid")) - if(16 to INFINITY) - icon_state = "solder-20" - if(11 to 15) - icon_state = "solder-15" - if(6 to 10) - icon_state = "solder-10" - if(1 to 5) - icon_state = "solder-5" - if(0) - icon_state = "solder-0" - -/obj/item/weapon/solder/examine(mob/user) - ..() + update_icon() + +/* + * Soldering Iron + */ +/obj/item/weapon/solder + name = "soldering iron" + icon = 'icons/obj/items.dmi' + icon_state = "solder-0" + hitsound = 'sound/weapons/toolhit.ogg' + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + force = 3.0 + sharpness = 1 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + starting_materials = list(MAT_IRON = 70, MAT_GLASS = 30) + w_type = RECYK_MISC + melt_temperature = MELTPOINT_STEEL + origin_tech = "engineering=1" + var/max_fuel = 20 //The max amount of acid stored + +/obj/item/weapon/solder/New() + . = ..() + create_reagents(max_fuel) + //Does not come fueled up + +/obj/item/weapon/solder/update_icon() + ..() + switch(reagents.get_reagent_amount("sacid")) + if(16 to INFINITY) + icon_state = "solder-20" + if(11 to 15) + icon_state = "solder-15" + if(6 to 10) + icon_state = "solder-10" + if(1 to 5) + icon_state = "solder-5" + if(0) + icon_state = "solder-0" + +/obj/item/weapon/solder/examine(mob/user) + ..() to_chat(user, "It contains [reagents.get_reagent_amount("sacid")]/[src.max_fuel] units of fuel!") - -/obj/item/weapon/solder/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/reagent_containers/glass/)) - var/obj/item/weapon/reagent_containers/glass/G = W - if(G.reagents.reagent_list.len>1) - user.simple_message("The mixture is rejected by the tool.", - "The tool isn't THAT thirsty.") - return - if(!G.reagents.has_reagent("sacid", 1)) - user.simple_message("The tool is not compatible with that.", - "The tool won't drink that.") - return - else - var/space = max_fuel - reagents.total_volume - if(!space) - user.simple_message("The tool is full!", - "The tool isn't thirsty.") - return - var/transfer_amount = min(G.amount_per_transfer_from_this,space) - user.simple_message("You transfer [transfer_amount] units to the [src].", - "The tool gulps down your drink!") - G.reagents.trans_id_to(src,"sacid",transfer_amount) - update_icon() - else - return ..() - -/obj/item/weapon/solder/proc/remove_fuel(var/amount, mob/user as mob) - if(reagents.get_reagent_amount("sacid") >= amount) - reagents.remove_reagent("sacid", amount) - update_icon() - return 1 - else - user.simple_message("The tool does not have enough acid!", - "The tool is too thirsty!") - return 0 - -/* -* Fuel Can -* A special, large container that fits on the belt -*/ -/obj/item/weapon/reagent_containers/glass/fuelcan - name = "fuel can" - desc = "A special container named Furst in its class by engineers. It has partitioned containment to allow engineers to separate different chemicals, such as welding fuel, sulphuric acid, or water. It also bears a clip to fit on a standard toolbelt." - icon = 'icons/obj/items.dmi' - icon_state = "fueljar0" - starting_materials = list(MAT_IRON = 500) - volume = 50 - possible_transfer_amounts = list(5,10,20) - var/slot = 0 //This dictates which side is open - var/datum/reagents/slotzero = null - var/datum/reagents/slotone = null - -/obj/item/weapon/reagent_containers/glass/fuelcan/New() - ..() - slotzero = reagents - slotone = new/datum/reagents(volume) - slotone.my_atom = src - reagents.add_reagent("fuel", 50) - -/obj/item/weapon/reagent_containers/glass/fuelcan/attack_self(mob/user as mob) - if(!slot) - slotzero = reagents - reagents = slotone - else - slotone = reagents - reagents = slotzero - slot = !slot - update_icon() + +/obj/item/weapon/solder/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W,/obj/item/weapon/reagent_containers/glass/)) + var/obj/item/weapon/reagent_containers/glass/G = W + if(G.reagents.reagent_list.len>1) + user.simple_message("The mixture is rejected by the tool.", + "The tool isn't THAT thirsty.") + return + if(!G.reagents.has_reagent("sacid", 1)) + user.simple_message("The tool is not compatible with that.", + "The tool won't drink that.") + return + else + var/space = max_fuel - reagents.total_volume + if(!space) + user.simple_message("The tool is full!", + "The tool isn't thirsty.") + return + var/transfer_amount = min(G.amount_per_transfer_from_this,space) + user.simple_message("You transfer [transfer_amount] units to the [src].", + "The tool gulps down your drink!") + G.reagents.trans_id_to(src,"sacid",transfer_amount) + update_icon() + else + return ..() + +/obj/item/weapon/solder/proc/remove_fuel(var/amount, mob/user as mob) + if(reagents.get_reagent_amount("sacid") >= amount) + reagents.remove_reagent("sacid", amount) + update_icon() + return 1 + else + user.simple_message("The tool does not have enough acid!", + "The tool is too thirsty!") + return 0 + +/* +* Fuel Can +* A special, large container that fits on the belt +*/ +/obj/item/weapon/reagent_containers/glass/fuelcan + name = "fuel can" + desc = "A special container named Furst in its class by engineers. It has partitioned containment to allow engineers to separate different chemicals, such as welding fuel, sulphuric acid, or water. It also bears a clip to fit on a standard toolbelt." + icon = 'icons/obj/items.dmi' + icon_state = "fueljar0" + starting_materials = list(MAT_IRON = 500) + volume = 50 + possible_transfer_amounts = list(5,10,20) + var/slot = 0 //This dictates which side is open + var/datum/reagents/slotzero = null + var/datum/reagents/slotone = null + +/obj/item/weapon/reagent_containers/glass/fuelcan/New() + ..() + slotzero = reagents + slotone = new/datum/reagents(volume) + slotone.my_atom = src + reagents.add_reagent("fuel", 50) + +/obj/item/weapon/reagent_containers/glass/fuelcan/attack_self(mob/user as mob) + if(!slot) + slotzero = reagents + reagents = slotone + else + slotone = reagents + reagents = slotzero + slot = !slot + update_icon() to_chat(user, "You switch the stopper to the other side.") - -/obj/item/weapon/reagent_containers/glass/fuelcan/examine(mob/user) - ..() + +/obj/item/weapon/reagent_containers/glass/fuelcan/examine(mob/user) + ..() to_chat(user, "The alternate partition contains:") - var/datum/reagents/alternate = (slot ? slotzero : slotone) - if(alternate.reagent_list.len) //Copied from atom/examine - for(var/datum/reagent/R in alternate.reagent_list) + var/datum/reagents/alternate = (slot ? slotzero : slotone) + if(alternate.reagent_list.len) //Copied from atom/examine + for(var/datum/reagent/R in alternate.reagent_list) to_chat(user, "[R.volume] units of [R.name]") - else + else to_chat(user, "Nothing.") - -/obj/item/weapon/reagent_containers/glass/fuelcan/update_icon() - icon_state = "fueljar[slot]" + +/obj/item/weapon/reagent_containers/glass/fuelcan/update_icon() + icon_state = "fueljar[slot]" diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 511d1413923..f01238f3720 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -1,197 +1,197 @@ -/* Two-handed Weapons - * Contains: - * Twohanded - * Fireaxe - * Double-Bladed Energy Swords - * Spears - * High Energy Frequency Blade - */ - -///////////OFFHAND/////////////// -//what the mob gets when wielding something -/obj/item/offhand - w_class = 5.0 - icon = 'icons/obj/weapons.dmi' - icon_state = "offhand" - name = "offhand" - abstract = 1 - var/obj/item/wielding = null - -/obj/item/offhand/dropped(user) - if(!wielding) - returnToPool(src) - return null - return wielding.unwield(user) - - -/obj/item/offhand/unwield(user) - if(!wielding) - returnToPool(src) - return null - return wielding.unwield(user) - -/obj/item/offhand/preattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) return - if(istype(target, /obj/item/weapon/storage)) //we place automatically - return - if(wielding) - if(!target.attackby(wielding, user)) - wielding.afterattack(target, user, proximity_flag, click_parameters) - return 1 - -/obj/item/offhand/attack_self(mob/user) - if(!wielding) - qdel(src) - return null - return wielding.unwield(user) - -/obj/item/offhand/proc/attach_to(var/obj/item/I) - I.wielded = src - wielding = I - name = wielding.name + " offhand" - desc = "Your second grip on the [I.name]" - -/obj/item/offhand/IsShield()//if the actual twohanded weapon is a shield, we count as a shield too! - return wielding.IsShield() -/* - * Fireaxe - */ -/obj/item/weapon/fireaxe // DEM AXES MAN, marker -Agouri - icon_state = "fireaxe0" - name = "fire axe" - desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" - w_class = 4.0 - sharpness = 1.2 - slot_flags = SLOT_BACK - attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") - flags = FPRINT | TWOHANDABLE - -/obj/item/weapon/fireaxe/update_wield(mob/user) - ..() - item_state = "fireaxe[wielded ? 1 : 0]" - force = wielded ? 40 : 10 - if(user) - user.update_inv_l_hand() - user.update_inv_r_hand() - -/obj/item/weapon/fireaxe/suicide_act(mob/user) +/* Two-handed Weapons + * Contains: + * Twohanded + * Fireaxe + * Double-Bladed Energy Swords + * Spears + * High Energy Frequency Blade + */ + +///////////OFFHAND/////////////// +//what the mob gets when wielding something +/obj/item/offhand + w_class = 5.0 + icon = 'icons/obj/weapons.dmi' + icon_state = "offhand" + name = "offhand" + abstract = 1 + var/obj/item/wielding = null + +/obj/item/offhand/dropped(user) + if(!wielding) + returnToPool(src) + return null + return wielding.unwield(user) + + +/obj/item/offhand/unwield(user) + if(!wielding) + returnToPool(src) + return null + return wielding.unwield(user) + +/obj/item/offhand/preattack(atom/target, mob/user, proximity_flag, click_parameters) + if(!proximity_flag) return + if(istype(target, /obj/item/weapon/storage)) //we place automatically + return + if(wielding) + if(!target.attackby(wielding, user)) + wielding.afterattack(target, user, proximity_flag, click_parameters) + return 1 + +/obj/item/offhand/attack_self(mob/user) + if(!wielding) + qdel(src) + return null + return wielding.unwield(user) + +/obj/item/offhand/proc/attach_to(var/obj/item/I) + I.wielded = src + wielding = I + name = wielding.name + " offhand" + desc = "Your second grip on the [I.name]" + +/obj/item/offhand/IsShield()//if the actual twohanded weapon is a shield, we count as a shield too! + return wielding.IsShield() +/* + * Fireaxe + */ +/obj/item/weapon/fireaxe // DEM AXES MAN, marker -Agouri + icon_state = "fireaxe0" + name = "fire axe" + desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" + w_class = 4.0 + sharpness = 1.2 + slot_flags = SLOT_BACK + attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") + flags = FPRINT | TWOHANDABLE + +/obj/item/weapon/fireaxe/update_wield(mob/user) + ..() + item_state = "fireaxe[wielded ? 1 : 0]" + force = wielded ? 40 : 10 + if(user) + user.update_inv_l_hand() + user.update_inv_r_hand() + +/obj/item/weapon/fireaxe/suicide_act(mob/user) to_chat(viewers(user), "[user] is smashing \himself in the head with the [src.name]! It looks like \he's commit suicide!") - return (BRUTELOSS) - -/obj/item/weapon/fireaxe/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return - ..() - if(A && wielded && (istype(A,/obj/structure/window) || istype(A,/obj/structure/grille))) //destroys windows and grilles in one hit - user.delayNextAttack(8) - if(istype(A,/obj/structure/window)) - var/pdiff=performWallPressureCheck(A.loc) - if(pdiff>0) - message_admins("[A] with pdiff [pdiff] fire-axed by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(A.loc)]!") - log_admin("[A] with pdiff [pdiff] fire-axed by [user.real_name] ([user.ckey]) at [A.loc]!") - var/obj/structure/window/W = A - W.Destroy(brokenup = 1) - else - qdel(A) - A = null - - -/* - * Double-Bladed Energy Swords - Cheridan - */ -/obj/item/weapon/dualsaber - icon_state = "dualsaber0" - name = "double-bladed energy sword" - desc = "Handle with care." - force = 3 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - flags = FPRINT | TWOHANDABLE - origin_tech = "magnets=3;syndicate=4" - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - -/obj/item/weapon/dualsaber/update_wield(mob/user) - ..() - icon_state = "dualsaber[wielded ? 1 : 0]" - item_state = "dualsaber[wielded ? 1 : 0]" - force = wielded ? 30 : 3 - w_class = wielded ? 5 : 2 - if(user) - user.update_inv_l_hand() - user.update_inv_r_hand() - playsound(get_turf(src), wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1) - return - -/obj/item/weapon/dualsaber/attack(target as mob, mob/living/user as mob) - ..() - if((M_CLUMSY in user.mutations) && (wielded) &&prob(40)) + return (BRUTELOSS) + +/obj/item/weapon/fireaxe/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) + if(!proximity) return + ..() + if(A && wielded && (istype(A,/obj/structure/window) || istype(A,/obj/structure/grille))) //destroys windows and grilles in one hit + user.delayNextAttack(8) + if(istype(A,/obj/structure/window)) + var/pdiff=performWallPressureCheck(A.loc) + if(pdiff>0) + message_admins("[A] with pdiff [pdiff] fire-axed by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(A.loc)]!") + log_admin("[A] with pdiff [pdiff] fire-axed by [user.real_name] ([user.ckey]) at [A.loc]!") + var/obj/structure/window/W = A + W.Destroy(brokenup = 1) + else + qdel(A) + A = null + + +/* + * Double-Bladed Energy Swords - Cheridan + */ +/obj/item/weapon/dualsaber + icon_state = "dualsaber0" + name = "double-bladed energy sword" + desc = "Handle with care." + force = 3 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + flags = FPRINT | TWOHANDABLE + origin_tech = "magnets=3;syndicate=4" + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/dualsaber/update_wield(mob/user) + ..() + icon_state = "dualsaber[wielded ? 1 : 0]" + item_state = "dualsaber[wielded ? 1 : 0]" + force = wielded ? 30 : 3 + w_class = wielded ? 5 : 2 + if(user) + user.update_inv_l_hand() + user.update_inv_r_hand() + playsound(get_turf(src), wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1) + return + +/obj/item/weapon/dualsaber/attack(target as mob, mob/living/user as mob) + ..() + if((M_CLUMSY in user.mutations) && (wielded) &&prob(40)) to_chat(user, "You twirl around a bit before losing your balance and impaling yourself on the [src].") - user.take_organ_damage(20,25) - return - if((wielded) && prob(50)) - spawn for(var/i=1, i<=8, i++) - user.dir = turn(user.dir, 45) - sleep(1) - -/obj/item/weapon/dualsaber/IsShield() - if(wielded) - return 1 - else - return 0 - - - -/* - * High-Frequency Blade - */ -/obj/item/weapon/katana/hfrequency - icon_state = "hfrequency0" - item_state = "hfrequency0" - name = "high-frequency blade" - desc = "Keep hands off blade at all times." - slot_flags = SLOT_BACK - throwforce = 35 - throw_speed = 5 - throw_range = 10 - w_class = 4.0 - flags = FPRINT | TWOHANDABLE - origin_tech = "magnets=4;combat=5" - -/obj/item/weapon/katana/hfrequency/update_wield(mob/user) - ..() - item_state = "hfrequency[wielded ? 1 : 0]" - force = wielded ? 200 : 50 - if(user) - user.update_inv_l_hand() - user.update_inv_r_hand() - return - -/obj/item/weapon/katana/hfrequency/IsShield() - if(wielded) - return 1 - else - return 0 - - -//spears -/obj/item/weapon/spear - icon_state = "spearglass0" - name = "spear" - desc = "A haphazardly-constructed yet still deadly weapon of ancient design." - force = 10 - w_class = 4.0 - slot_flags = SLOT_BACK - throwforce = 15 - flags = TWOHANDABLE - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - -/obj/item/weapon/spear/update_wield(mob/user) - icon_state = "spearglass[wielded ? 1 : 0]" - item_state = "spearglass[wielded ? 1 : 0]" - force = wielded ? 18 : 10 - if(user) - user.update_inv_l_hand() - user.update_inv_r_hand() - return + user.take_organ_damage(20,25) + return + if((wielded) && prob(50)) + spawn for(var/i=1, i<=8, i++) + user.dir = turn(user.dir, 45) + sleep(1) + +/obj/item/weapon/dualsaber/IsShield() + if(wielded) + return 1 + else + return 0 + + + +/* + * High-Frequency Blade + */ +/obj/item/weapon/katana/hfrequency + icon_state = "hfrequency0" + item_state = "hfrequency0" + name = "high-frequency blade" + desc = "Keep hands off blade at all times." + slot_flags = SLOT_BACK + throwforce = 35 + throw_speed = 5 + throw_range = 10 + w_class = 4.0 + flags = FPRINT | TWOHANDABLE + origin_tech = "magnets=4;combat=5" + +/obj/item/weapon/katana/hfrequency/update_wield(mob/user) + ..() + item_state = "hfrequency[wielded ? 1 : 0]" + force = wielded ? 200 : 50 + if(user) + user.update_inv_l_hand() + user.update_inv_r_hand() + return + +/obj/item/weapon/katana/hfrequency/IsShield() + if(wielded) + return 1 + else + return 0 + + +//spears +/obj/item/weapon/spear + icon_state = "spearglass0" + name = "spear" + desc = "A haphazardly-constructed yet still deadly weapon of ancient design." + force = 10 + w_class = 4.0 + slot_flags = SLOT_BACK + throwforce = 15 + flags = TWOHANDABLE + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") + +/obj/item/weapon/spear/update_wield(mob/user) + icon_state = "spearglass[wielded ? 1 : 0]" + item_state = "spearglass[wielded ? 1 : 0]" + force = wielded ? 18 : 10 + if(user) + user.update_inv_l_hand() + user.update_inv_r_hand() + return diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index eb2eadca8d1..52150e717a2 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -1,154 +1,154 @@ -/obj/item/weapon/banhammer - desc = "A banhammer" - name = "banhammer" - icon = 'icons/obj/items.dmi' - icon_state = "toyhammer" - flags = FPRINT - slot_flags = SLOT_BELT - throwforce = 0 - w_class = 1.0 - throw_speed = 7 - throw_range = 15 - attack_verb = list("banned") - - - suicide_act(mob/user) - to_chat(viewers(user), "[user] is hitting \himself with the [src.name]! It looks like \he's trying to ban \himself from life.") - return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS) - -/obj/item/weapon/sord - name = "\improper SORD" - desc = "This thing is so unspeakably shitty you are having a hard time even holding it." - icon_state = "sord" - item_state = "sord" - flags = FPRINT - slot_flags = SLOT_BELT - force = 2 - throwforce = 1 - w_class = 3 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - - suicide_act(mob/user) - to_chat(viewers(user), "[user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide.") - return(BRUTELOSS) - -/obj/item/weapon/sord/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - playsound(get_turf(src), 'sound/weapons/bladeslice.ogg', 50, 1, -1) - user.adjustBruteLoss(0.5) - return ..() - -/obj/item/weapon/claymore - name = "claymore" - desc = "What are you standing around staring at this for? Get to killing!" - icon_state = "claymore" - item_state = "claymore" - hitsound = "sound/weapons/bloodyslice.ogg" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - force = 40 - throwforce = 10 - w_class = 3 - sharpness = 1.2 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - - IsShield() - return 1 - - suicide_act(mob/user) - to_chat(viewers(user), "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.") - return(BRUTELOSS) - -/obj/item/weapon/claymore/cultify() - new /obj/item/weapon/melee/cultblade(loc) - ..() - -/obj/item/weapon/claymore/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - playsound(loc, 'sound/weapons/bloodyslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/katana - name = "katana" - desc = "Woefully underpowered in D20" - icon_state = "katana" - item_state = "katana" - hitsound = "sound/weapons/bloodyslice.ogg" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - w_class = 3 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - suicide_act(mob/user) - to_chat(viewers(user), "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") - return(BRUTELOSS) - -/obj/item/weapon/katana/IsShield() - return 1 - -/obj/item/weapon/katana/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - playsound(loc, 'sound/weapons/bloodyslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/harpoon - name = "harpoon" - sharpness = 1.2 - desc = "Tharr she blows!" - icon_state = "harpoon" - item_state = "harpoon" - hitsound = "sound/weapons/bladeslice.ogg" - force = 20 - throwforce = 15 - w_class = 3 - attack_verb = list("jabbed","stabbed","ripped") - -obj/item/weapon/wirerod - name = "Wired rod" - desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." - icon_state = "wiredrod" - item_state = "rods" - flags = FPRINT - siemens_coefficient = 1 - force = 9 - throwforce = 10 - w_class = 3 - starting_materials = list(MAT_IRON = 1875) - w_type = RECYK_METAL - attack_verb = list("hit", "bludgeoned", "whacked", "bonked") - - -obj/item/weapon/wirerod/attackby(var/obj/item/I, mob/user as mob) - ..() - if(istype(I, /obj/item/weapon/shard)) - var/obj/item/weapon/spear/S = new /obj/item/weapon/spear - - user.before_take_item(I) - user.before_take_item(src) - - user.put_in_hands(S) - to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") - qdel(I) - I = null - qdel(src) - - else if(istype(I, /obj/item/weapon/wirecutters)) - var/obj/item/weapon/melee/baton/cattleprod/P = new /obj/item/weapon/melee/baton/cattleprod - - user.before_take_item(I) - user.before_take_item(src) - - user.put_in_hands(P) - to_chat(user, "You fasten the wirecutters to the top of the rod with the cable, prongs outward.") - qdel(I) - I = null - qdel(src) - - -obj/item/weapon/banhammer/admin - desc = "A banhammer specifically reserved for admins. Legends tell of a weapon that destroys the target to the utmost capacity." - throwforce = 999 - force = 999 +/obj/item/weapon/banhammer + desc = "A banhammer" + name = "banhammer" + icon = 'icons/obj/items.dmi' + icon_state = "toyhammer" + flags = FPRINT + slot_flags = SLOT_BELT + throwforce = 0 + w_class = 1.0 + throw_speed = 7 + throw_range = 15 + attack_verb = list("banned") + + + suicide_act(mob/user) + to_chat(viewers(user), "[user] is hitting \himself with the [src.name]! It looks like \he's trying to ban \himself from life.") + return (BRUTELOSS|FIRELOSS|TOXLOSS|OXYLOSS) + +/obj/item/weapon/sord + name = "\improper SORD" + desc = "This thing is so unspeakably shitty you are having a hard time even holding it." + icon_state = "sord" + item_state = "sord" + flags = FPRINT + slot_flags = SLOT_BELT + force = 2 + throwforce = 1 + w_class = 3 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + + suicide_act(mob/user) + to_chat(viewers(user), "[user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide.") + return(BRUTELOSS) + +/obj/item/weapon/sord/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + playsound(get_turf(src), 'sound/weapons/bladeslice.ogg', 50, 1, -1) + user.adjustBruteLoss(0.5) + return ..() + +/obj/item/weapon/claymore + name = "claymore" + desc = "What are you standing around staring at this for? Get to killing!" + icon_state = "claymore" + item_state = "claymore" + hitsound = "sound/weapons/bloodyslice.ogg" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + force = 40 + throwforce = 10 + w_class = 3 + sharpness = 1.2 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + + IsShield() + return 1 + + suicide_act(mob/user) + to_chat(viewers(user), "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.") + return(BRUTELOSS) + +/obj/item/weapon/claymore/cultify() + new /obj/item/weapon/melee/cultblade(loc) + ..() + +/obj/item/weapon/claymore/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + playsound(loc, 'sound/weapons/bloodyslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/katana + name = "katana" + desc = "Woefully underpowered in D20" + icon_state = "katana" + item_state = "katana" + hitsound = "sound/weapons/bloodyslice.ogg" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + w_class = 3 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + suicide_act(mob/user) + to_chat(viewers(user), "[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") + return(BRUTELOSS) + +/obj/item/weapon/katana/IsShield() + return 1 + +/obj/item/weapon/katana/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + playsound(loc, 'sound/weapons/bloodyslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/harpoon + name = "harpoon" + sharpness = 1.2 + desc = "Tharr she blows!" + icon_state = "harpoon" + item_state = "harpoon" + hitsound = "sound/weapons/bladeslice.ogg" + force = 20 + throwforce = 15 + w_class = 3 + attack_verb = list("jabbed","stabbed","ripped") + +obj/item/weapon/wirerod + name = "Wired rod" + desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." + icon_state = "wiredrod" + item_state = "rods" + flags = FPRINT + siemens_coefficient = 1 + force = 9 + throwforce = 10 + w_class = 3 + starting_materials = list(MAT_IRON = 1875) + w_type = RECYK_METAL + attack_verb = list("hit", "bludgeoned", "whacked", "bonked") + + +obj/item/weapon/wirerod/attackby(var/obj/item/I, mob/user as mob) + ..() + if(istype(I, /obj/item/weapon/shard)) + var/obj/item/weapon/spear/S = new /obj/item/weapon/spear + + user.before_take_item(I) + user.before_take_item(src) + + user.put_in_hands(S) + to_chat(user, "You fasten the glass shard to the top of the rod with the cable.") + qdel(I) + I = null + qdel(src) + + else if(istype(I, /obj/item/weapon/wirecutters)) + var/obj/item/weapon/melee/baton/cattleprod/P = new /obj/item/weapon/melee/baton/cattleprod + + user.before_take_item(I) + user.before_take_item(src) + + user.put_in_hands(P) + to_chat(user, "You fasten the wirecutters to the top of the rod with the cable, prongs outward.") + qdel(I) + I = null + qdel(src) + + +obj/item/weapon/banhammer/admin + desc = "A banhammer specifically reserved for admins. Legends tell of a weapon that destroys the target to the utmost capacity." + throwforce = 999 + force = 999 diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 758199fc152..7c90e333604 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -1,322 +1,322 @@ -var/global/list/reagents_to_log = list("fuel" = "welder fuel", "plasma"= "plasma", "pacid" = "polytrinic acid", "sacid" = "sulphuric acid", "amutationtoxin" = "slime mutation toxin") -/obj - var/origin_tech = null //Used by R&D to determine what research bonuses it grants. - var/reliability = 100 //Used by SOME devices to determine how reliable they are. - var/crit_fail = 0 - var/unacidable = 0 //universal "unacidabliness" var, here so you can use it in any obj. - animate_movement = 2 - var/throwforce = 1 - var/siemens_coefficient = 0 // for electrical admittance/conductance (electrocution checks and shit) - 0 is not conductive, 1 is conductive - this is a range, not binary - var/sharpness = 0 //not a binary - rough guide is 0.8 cutting, 1 cutting well, 1.2 specifically sharp (knives, etc) 1.5 really sharp (scalpels, e-weapons) - var/heat_production = 0 - - var/edge = 0 - var/in_use = 0 // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING! - - var/damtype = "brute" - var/force = 0 - - //Should we alert about reagents that should be logged? - var/log_reagents = 1 - - var/list/mob/_using // All mobs dicking with us. - - // Shit for mechanics. (MECH_*) - var/mech_flags=0 - -/obj/Destroy() - for(var/mob/user in _using) - user.unset_machine() - - if(src in processing_objects) - processing_objects -= src - - ..() - -/obj/item/proc/is_used_on(obj/O, mob/user) - -/obj/recycle(var/datum/materials/rec) - if(..()) - return 1 - return w_type - -/* -/obj/melt() - var/obj/effect/decal/slag/slag=locate(/obj/effect/decal/slag) in get_turf(src) - if(!slag) - slag = new(get_turf(src)) - slag.slaggify(src) -*/ - -/obj/proc/is_conductor(var/siemens_min = 0.5) - if(src.siemens_coefficient >= siemens_min) - return 1 - return - -/obj/proc/cultify() - qdel(src) - -/obj/proc/is_sharp() - return sharpness - -/obj/proc/is_hot() - return heat_production - -/obj/proc/process() - processing_objects.Remove(src) - -/obj/assume_air(datum/gas_mixture/giver) - if(loc) - return loc.assume_air(giver) - else - return null - -/obj/remove_air(amount) - if(loc) - return loc.remove_air(amount) - else - return null - -/obj/return_air() - if(loc) - return loc.return_air() - else - return null - -/obj/proc/handle_internal_lifeform(mob/lifeform_inside_me, breath_request) - //Return: (NONSTANDARD) - // null if object handles breathing logic for lifeform - // datum/air_group to tell lifeform to process using that breath return - //DEFAULT: Take air from turf to give to have mob process - if(breath_request>0) - return remove_air(breath_request) - else - return null - -/atom/movable/proc/initialize() - return - -/obj/proc/updateUsrDialog() - if(in_use) - var/is_in_use = 0 - if(_using && _using.len) - var/list/nearby = viewers(1, src) - for(var/mob/M in _using) // Only check things actually messing with us. - if (!M || !M.client || M.machine != src) - _using.Remove(M) - continue - - if(!M in nearby) // NOT NEARBY - // AIs/Robots can do shit from afar. - if (isAI(M) || isrobot(M)) - is_in_use = 1 - src.attack_ai(M) - - // check for TK users - if(M.mutations && M.mutations.len) - if(M_TK in M.mutations) - is_in_use = 1 - src.attack_hand(M, TRUE) // The second param is to make sure brain damage on the user doesn't cause the UI to not update but the action to still happen. - else - // Remove. - _using.Remove(M) - continue - else // EVERYTHING FROM HERE DOWN MUST BE NEARBY - is_in_use = 1 - attack_hand(M, TRUE) - in_use = is_in_use - -/obj/proc/updateDialog() - // Check that people are actually using the machine. If not, don't update anymore. - if(in_use) - var/list/nearby = viewers(1, src) - var/is_in_use = 0 - for(var/mob/M in _using) // Only check things actually messing with us. - // Not actually using the fucking thing? - if (!M || !M.client || M.machine != src) - _using.Remove(M) - continue - // Not robot or AI, and not nearby? - if(!isAI(M) && !isrobot(M) && !(M in nearby)) - _using.Remove(M) - continue - is_in_use = 1 - src.interact(M) - in_use = is_in_use - -/obj/proc/interact(mob/user) - return - -/obj/singularity_act() - ex_act(1) - if(src) - qdel(src) - return 2 - -/obj/shuttle_act(datum/shuttle/S) - return qdel(src) - -/obj/singularity_pull(S, current_size) - if(anchored) - if(current_size >= STAGE_FIVE) - anchored = 0 - step_towards(src, S) - else step_towards(src, S) - -/obj/proc/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - return "NO MULTITOOL_MENU!" - -/obj/proc/linkWith(var/mob/user, var/obj/buffer, var/link/context) - return 0 - -/obj/proc/unlinkFrom(var/mob/user, var/obj/buffer) - return 0 - -/obj/proc/canLink(var/obj/O, var/link/context) - return 0 - -/obj/proc/isLinkedWith(var/obj/O) - return 0 - -/obj/proc/getLink(var/idx) - return null - -/obj/proc/canClone(var/obj/O) - return 0 - -/obj/proc/clone(var/obj/O) - return 0 - -/obj/proc/linkMenu(var/obj/O) - var/dat="" - if(canLink(O, list())) - dat += " \[Link\] " - return dat - -/obj/proc/format_tag(var/label,var/varname, var/act="set_tag") - var/value = vars[varname] - if(!value || value=="") - value="-----" - return "[label]: [value]" - - -/obj/proc/update_multitool_menu(mob/user as mob) - var/obj/item/device/multitool/P = get_multitool(user) - - if(!istype(P)) - return 0 - - // Cloning stuff goes here. - if(P.clone && P.buffer) // Cloning is on. - if(!canClone(P.buffer)) - to_chat(user, "A red light flashes on \the [P]; you cannot clone to this device!") - return - - if(!clone(P.buffer)) - to_chat(user, "A red light flashes on \the [P]; something went wrong when cloning to this device!") - return - - to_chat(user, "A green light flashes on \the [P], confirming the device was cloned to.") - return - - var/dat = {" - - [name] Configuration - - - -

    [name]

    -"} - dat += multitool_menu(user,P) - if(P) - if(P.buffer) - var/id = null - if(istype(P.buffer, /obj/machinery/telecomms)) - var/obj/machinery/telecomms/buffer = P.buffer//Casting is better than using colons - id = buffer.id - else if(P.buffer.vars["id_tag"])//not doing in vars here incase the var is empty, it'd show () - id = P.buffer:id_tag//sadly, : is needed - - dat += "

    MULTITOOL BUFFER: [P.buffer] [id ? "([id])" : ""]"//If you can't into the ? operator, that will make it not display () if there's no ID. - - dat += linkMenu(P.buffer) - - if(P.buffer) - dat += "\[Flush\]" - dat += "

    " - else - dat += "

    MULTITOOL BUFFER: \[Add Machine\]

    " - dat += "" - user << browse(dat, "window=mtcomputer") - user.set_machine(src) - onclose(user, "mtcomputer") - -/obj/update_icon() - return - -/mob/proc/unset_machine() - if(machine) - if(machine._using) - machine._using -= src - - if(!machine._using.len) - machine._using = null - - machine = null - -/mob/proc/set_machine(const/obj/O) - unset_machine() - - if(istype(O)) - machine = O - - if(!machine._using) - machine._using = new - - machine._using += src - machine.in_use = 1 - -/obj/item/proc/updateSelfDialog() - var/mob/M = src.loc - if(istype(M) && M.client && M.machine == src) - src.attack_self(M) - - -/obj/proc/alter_health() - return 1 - -/obj/proc/hide(h) - return - -/obj/proc/container_resist() - return - -/obj/proc/can_pickup(mob/living/user) - return 0 - -/obj/proc/verb_pickup(mob/living/user) - return 0 - -/** - * If a mob logouts/logins in side of an object you can use this proc. - */ -/obj/proc/on_log() - if (isobj(loc)) - var/obj/location = loc - location.on_log() - -// Dummy to give items special techlist for the purposes of the Device Analyser, in case you'd ever need them to give them different tech levels depending on special checks. -/obj/proc/give_tech_list() - return null +var/global/list/reagents_to_log = list("fuel" = "welder fuel", "plasma"= "plasma", "pacid" = "polytrinic acid", "sacid" = "sulphuric acid", "amutationtoxin" = "slime mutation toxin") +/obj + var/origin_tech = null //Used by R&D to determine what research bonuses it grants. + var/reliability = 100 //Used by SOME devices to determine how reliable they are. + var/crit_fail = 0 + var/unacidable = 0 //universal "unacidabliness" var, here so you can use it in any obj. + animate_movement = 2 + var/throwforce = 1 + var/siemens_coefficient = 0 // for electrical admittance/conductance (electrocution checks and shit) - 0 is not conductive, 1 is conductive - this is a range, not binary + var/sharpness = 0 //not a binary - rough guide is 0.8 cutting, 1 cutting well, 1.2 specifically sharp (knives, etc) 1.5 really sharp (scalpels, e-weapons) + var/heat_production = 0 + + var/edge = 0 + var/in_use = 0 // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING! + + var/damtype = "brute" + var/force = 0 + + //Should we alert about reagents that should be logged? + var/log_reagents = 1 + + var/list/mob/_using // All mobs dicking with us. + + // Shit for mechanics. (MECH_*) + var/mech_flags=0 + +/obj/Destroy() + for(var/mob/user in _using) + user.unset_machine() + + if(src in processing_objects) + processing_objects -= src + + ..() + +/obj/item/proc/is_used_on(obj/O, mob/user) + +/obj/recycle(var/datum/materials/rec) + if(..()) + return 1 + return w_type + +/* +/obj/melt() + var/obj/effect/decal/slag/slag=locate(/obj/effect/decal/slag) in get_turf(src) + if(!slag) + slag = new(get_turf(src)) + slag.slaggify(src) +*/ + +/obj/proc/is_conductor(var/siemens_min = 0.5) + if(src.siemens_coefficient >= siemens_min) + return 1 + return + +/obj/proc/cultify() + qdel(src) + +/obj/proc/is_sharp() + return sharpness + +/obj/proc/is_hot() + return heat_production + +/obj/proc/process() + processing_objects.Remove(src) + +/obj/assume_air(datum/gas_mixture/giver) + if(loc) + return loc.assume_air(giver) + else + return null + +/obj/remove_air(amount) + if(loc) + return loc.remove_air(amount) + else + return null + +/obj/return_air() + if(loc) + return loc.return_air() + else + return null + +/obj/proc/handle_internal_lifeform(mob/lifeform_inside_me, breath_request) + //Return: (NONSTANDARD) + // null if object handles breathing logic for lifeform + // datum/air_group to tell lifeform to process using that breath return + //DEFAULT: Take air from turf to give to have mob process + if(breath_request>0) + return remove_air(breath_request) + else + return null + +/atom/movable/proc/initialize() + return + +/obj/proc/updateUsrDialog() + if(in_use) + var/is_in_use = 0 + if(_using && _using.len) + var/list/nearby = viewers(1, src) + for(var/mob/M in _using) // Only check things actually messing with us. + if (!M || !M.client || M.machine != src) + _using.Remove(M) + continue + + if(!M in nearby) // NOT NEARBY + // AIs/Robots can do shit from afar. + if (isAI(M) || isrobot(M)) + is_in_use = 1 + src.attack_ai(M) + + // check for TK users + if(M.mutations && M.mutations.len) + if(M_TK in M.mutations) + is_in_use = 1 + src.attack_hand(M, TRUE) // The second param is to make sure brain damage on the user doesn't cause the UI to not update but the action to still happen. + else + // Remove. + _using.Remove(M) + continue + else // EVERYTHING FROM HERE DOWN MUST BE NEARBY + is_in_use = 1 + attack_hand(M, TRUE) + in_use = is_in_use + +/obj/proc/updateDialog() + // Check that people are actually using the machine. If not, don't update anymore. + if(in_use) + var/list/nearby = viewers(1, src) + var/is_in_use = 0 + for(var/mob/M in _using) // Only check things actually messing with us. + // Not actually using the fucking thing? + if (!M || !M.client || M.machine != src) + _using.Remove(M) + continue + // Not robot or AI, and not nearby? + if(!isAI(M) && !isrobot(M) && !(M in nearby)) + _using.Remove(M) + continue + is_in_use = 1 + src.interact(M) + in_use = is_in_use + +/obj/proc/interact(mob/user) + return + +/obj/singularity_act() + ex_act(1) + if(src) + qdel(src) + return 2 + +/obj/shuttle_act(datum/shuttle/S) + return qdel(src) + +/obj/singularity_pull(S, current_size) + if(anchored) + if(current_size >= STAGE_FIVE) + anchored = 0 + step_towards(src, S) + else step_towards(src, S) + +/obj/proc/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + return "NO MULTITOOL_MENU!" + +/obj/proc/linkWith(var/mob/user, var/obj/buffer, var/link/context) + return 0 + +/obj/proc/unlinkFrom(var/mob/user, var/obj/buffer) + return 0 + +/obj/proc/canLink(var/obj/O, var/link/context) + return 0 + +/obj/proc/isLinkedWith(var/obj/O) + return 0 + +/obj/proc/getLink(var/idx) + return null + +/obj/proc/canClone(var/obj/O) + return 0 + +/obj/proc/clone(var/obj/O) + return 0 + +/obj/proc/linkMenu(var/obj/O) + var/dat="" + if(canLink(O, list())) + dat += " \[Link\] " + return dat + +/obj/proc/format_tag(var/label,var/varname, var/act="set_tag") + var/value = vars[varname] + if(!value || value=="") + value="-----" + return "[label]: [value]" + + +/obj/proc/update_multitool_menu(mob/user as mob) + var/obj/item/device/multitool/P = get_multitool(user) + + if(!istype(P)) + return 0 + + // Cloning stuff goes here. + if(P.clone && P.buffer) // Cloning is on. + if(!canClone(P.buffer)) + to_chat(user, "A red light flashes on \the [P]; you cannot clone to this device!") + return + + if(!clone(P.buffer)) + to_chat(user, "A red light flashes on \the [P]; something went wrong when cloning to this device!") + return + + to_chat(user, "A green light flashes on \the [P], confirming the device was cloned to.") + return + + var/dat = {" + + [name] Configuration + + + +

    [name]

    +"} + dat += multitool_menu(user,P) + if(P) + if(P.buffer) + var/id = null + if(istype(P.buffer, /obj/machinery/telecomms)) + var/obj/machinery/telecomms/buffer = P.buffer//Casting is better than using colons + id = buffer.id + else if(P.buffer.vars["id_tag"])//not doing in vars here incase the var is empty, it'd show () + id = P.buffer:id_tag//sadly, : is needed + + dat += "

    MULTITOOL BUFFER: [P.buffer] [id ? "([id])" : ""]"//If you can't into the ? operator, that will make it not display () if there's no ID. + + dat += linkMenu(P.buffer) + + if(P.buffer) + dat += "\[Flush\]" + dat += "

    " + else + dat += "

    MULTITOOL BUFFER: \[Add Machine\]

    " + dat += "" + user << browse(dat, "window=mtcomputer") + user.set_machine(src) + onclose(user, "mtcomputer") + +/obj/update_icon() + return + +/mob/proc/unset_machine() + if(machine) + if(machine._using) + machine._using -= src + + if(!machine._using.len) + machine._using = null + + machine = null + +/mob/proc/set_machine(const/obj/O) + unset_machine() + + if(istype(O)) + machine = O + + if(!machine._using) + machine._using = new + + machine._using += src + machine.in_use = 1 + +/obj/item/proc/updateSelfDialog() + var/mob/M = src.loc + if(istype(M) && M.client && M.machine == src) + src.attack_self(M) + + +/obj/proc/alter_health() + return 1 + +/obj/proc/hide(h) + return + +/obj/proc/container_resist() + return + +/obj/proc/can_pickup(mob/living/user) + return 0 + +/obj/proc/verb_pickup(mob/living/user) + return 0 + +/** + * If a mob logouts/logins in side of an object you can use this proc. + */ +/obj/proc/on_log() + if (isobj(loc)) + var/obj/location = loc + location.on_log() + +// Dummy to give items special techlist for the purposes of the Device Analyser, in case you'd ever need them to give them different tech levels depending on special checks. +/obj/proc/give_tech_list() + return null diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index f08c1dd63de..b91b95cfc28 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -1,22 +1,22 @@ -obj/structure - icon = 'icons/obj/structures.dmi' - penetration_dampening = 5 - -obj/structure/blob_act() - if(prob(50)) - qdel(src) - -obj/structure/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if(prob(50)) - qdel(src) - return - if(3.0) - return - -/obj/structure/projectile_check() - return PROJREACT_OBJS +obj/structure + icon = 'icons/obj/structures.dmi' + penetration_dampening = 5 + +obj/structure/blob_act() + if(prob(50)) + qdel(src) + +obj/structure/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if(prob(50)) + qdel(src) + return + if(3.0) + return + +/obj/structure/projectile_check() + return PROJREACT_OBJS diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index d111869db80..f55b185f9b3 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -1,219 +1,219 @@ -/* -CONTAINS: -BEDSHEETS -LINEN BINS -*/ - -/obj/item/weapon/bedsheet - name = "bedsheet" - desc = "A surprisingly soft linen bedsheet." - icon = 'icons/obj/items.dmi' - icon_state = "sheet" - item_state = "bedsheet" - layer = 4.0 - throwforce = 1 - throw_speed = 1 - throw_range = 2 - w_class = 1.0 - _color = "white" - -//cutting the bedsheet into rags -/obj/item/weapon/bedsheet/attackby(var/obj/item/I, mob/user as mob) - var/cut_time=0 - if(istype(I, /obj/item/weapon/scalpel)) - cut_time=20 - else if(istype(I, /obj/item/weapon/kitchen/utensil/knife/large) || istype(I, /obj/item/weapon/kitchen/utensil/knife/large/butch)) - cut_time=40 - else if(istype(I, /obj/item/weapon/shard)) - cut_time=80 - else if(istype(I, /obj/item/weapon/kitchen/utensil/knife/plastic)) - cut_time=160 - if(cut_time) - to_chat(user, "You begin cutting the [src].") - if(do_after(user, src, cut_time)) - if(!src) return - to_chat(user, "You have cut the [src] into rags.") - var/turf/location = get_turf(src) - for(var/x=0; x<=8; x++) - var/obj/item/weapon/reagent_containers/glass/rag/S = new/obj/item/weapon/reagent_containers/glass/rag/(location) - S.pixel_x = rand(-5.0, 5) - S.pixel_y = rand(-5.0, 5) - qdel(src) - -//todo: hold one if possible? -//todo: coloring and molotov coloring? -//todo: finger prints? -//todo: more cutting tools? -//todo: sharp thing code/game/objects/objs.dm - -/obj/item/weapon/bedsheet/attack_self(mob/user as mob) - user.drop_item(src, force_drop = 1) - if(layer == initial(layer)) - layer = 5 - else - layer = initial(layer) - add_fingerprint(user) - return - - -/obj/item/weapon/bedsheet/blue - icon_state = "sheetblue" - _color = "blue" - -/obj/item/weapon/bedsheet/green - icon_state = "sheetgreen" - _color = "green" - -/obj/item/weapon/bedsheet/orange - icon_state = "sheetorange" - _color = "orange" - -/obj/item/weapon/bedsheet/purple - icon_state = "sheetpurple" - _color = "purple" - -/obj/item/weapon/bedsheet/rainbow - icon_state = "sheetrainbow" - _color = "rainbow" - -/obj/item/weapon/bedsheet/red - icon_state = "sheetred" - _color = "red" - -/obj/item/weapon/bedsheet/red/redcoat - _color = "redcoat" //for denied stamp - -/obj/item/weapon/bedsheet/yellow - icon_state = "sheetyellow" - _color = "yellow" - -/obj/item/weapon/bedsheet/mime - icon_state = "sheetmime" - _color = "mime" - -/obj/item/weapon/bedsheet/clown - icon_state = "sheetclown" - _color = "clown" - -/obj/item/weapon/bedsheet/captain - icon_state = "sheetcaptain" - _color = "captain" - -/obj/item/weapon/bedsheet/rd - icon_state = "sheetrd" - _color = "director" - -/obj/item/weapon/bedsheet/medical - icon_state = "sheetmedical" - _color = "medical" - -/obj/item/weapon/bedsheet/hos - icon_state = "sheethos" - _color = "hosred" - -/obj/item/weapon/bedsheet/hop - icon_state = "sheethop" - _color = "hop" - -/obj/item/weapon/bedsheet/ce - icon_state = "sheetce" - _color = "chief" - -/obj/item/weapon/bedsheet/brown - icon_state = "sheetbrown" - _color = "brown" - -/obj/item/weapon/bedsheet/brown/cargo - _color = "cargo" //exists for washing machines, is not different from brown bedsheet in any way - - -/obj/structure/bedsheetbin - name = "linen bin" - desc = "A linen bin. It looks rather cosy." - icon = 'icons/obj/structures.dmi' - icon_state = "linenbin-full" - anchored = 1 - var/amount = 20 - var/list/sheets = list() - var/obj/item/hidden = null - - -/obj/structure/bedsheetbin/examine(mob/user) - ..() - if(amount == 0) - to_chat(user, "There are no bed sheets in the bin.") - else if(amount == 1) - to_chat(user, "There is one bed sheet in the bin.") - else - to_chat(user, "There are [amount] bed sheets in the bin.") - - -/obj/structure/bedsheetbin/update_icon() - switch(amount) - if(0) icon_state = "linenbin-empty" - if(1 to amount / 2) icon_state = "linenbin-half" - else icon_state = "linenbin-full" - - -/obj/structure/bedsheetbin/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/weapon/bedsheet)) - if(user.drop_item(I, src)) - sheets.Add(I) - amount++ - to_chat(user, "You put \the [I] in \the [src].") - else if(amount && !hidden && I.w_class < 4) //make sure there's sheets to hide it among, make sure nothing else is hidden in there. - if(user.drop_item(I, src)) - hidden = I - to_chat(user, "You hide [I] among the sheets.") - - -/obj/structure/bedsheetbin/attack_paw(mob/user as mob) - return attack_hand(user) - - -/obj/structure/bedsheetbin/attack_hand(mob/user as mob) - if(amount >= 1) - amount-- - - var/obj/item/weapon/bedsheet/B - if(sheets.len > 0) - B = sheets[sheets.len] - sheets.Remove(B) - - else - B = new /obj/item/weapon/bedsheet(loc) - - B.loc = user.loc - user.put_in_hands(B) - to_chat(user, "You take [B] out of [src].") - - if(hidden) - hidden.loc = user.loc - to_chat(user, "[hidden] falls out of [B]!") - hidden = null - - - add_fingerprint(user) - -/obj/structure/bedsheetbin/attack_tk(mob/user as mob) - if(amount >= 1) - amount-- - - var/obj/item/weapon/bedsheet/B - if(sheets.len > 0) - B = sheets[sheets.len] - sheets.Remove(B) - - else - B = new /obj/item/weapon/bedsheet(loc) - - B.loc = loc - to_chat(user, "You telekinetically remove [B] from [src].") - update_icon() - - if(hidden) - hidden.loc = loc - hidden = null - - - add_fingerprint(user) +/* +CONTAINS: +BEDSHEETS +LINEN BINS +*/ + +/obj/item/weapon/bedsheet + name = "bedsheet" + desc = "A surprisingly soft linen bedsheet." + icon = 'icons/obj/items.dmi' + icon_state = "sheet" + item_state = "bedsheet" + layer = 4.0 + throwforce = 1 + throw_speed = 1 + throw_range = 2 + w_class = 1.0 + _color = "white" + +//cutting the bedsheet into rags +/obj/item/weapon/bedsheet/attackby(var/obj/item/I, mob/user as mob) + var/cut_time=0 + if(istype(I, /obj/item/weapon/scalpel)) + cut_time=20 + else if(istype(I, /obj/item/weapon/kitchen/utensil/knife/large) || istype(I, /obj/item/weapon/kitchen/utensil/knife/large/butch)) + cut_time=40 + else if(istype(I, /obj/item/weapon/shard)) + cut_time=80 + else if(istype(I, /obj/item/weapon/kitchen/utensil/knife/plastic)) + cut_time=160 + if(cut_time) + to_chat(user, "You begin cutting the [src].") + if(do_after(user, src, cut_time)) + if(!src) return + to_chat(user, "You have cut the [src] into rags.") + var/turf/location = get_turf(src) + for(var/x=0; x<=8; x++) + var/obj/item/weapon/reagent_containers/glass/rag/S = new/obj/item/weapon/reagent_containers/glass/rag/(location) + S.pixel_x = rand(-5.0, 5) + S.pixel_y = rand(-5.0, 5) + qdel(src) + +//todo: hold one if possible? +//todo: coloring and molotov coloring? +//todo: finger prints? +//todo: more cutting tools? +//todo: sharp thing code/game/objects/objs.dm + +/obj/item/weapon/bedsheet/attack_self(mob/user as mob) + user.drop_item(src, force_drop = 1) + if(layer == initial(layer)) + layer = 5 + else + layer = initial(layer) + add_fingerprint(user) + return + + +/obj/item/weapon/bedsheet/blue + icon_state = "sheetblue" + _color = "blue" + +/obj/item/weapon/bedsheet/green + icon_state = "sheetgreen" + _color = "green" + +/obj/item/weapon/bedsheet/orange + icon_state = "sheetorange" + _color = "orange" + +/obj/item/weapon/bedsheet/purple + icon_state = "sheetpurple" + _color = "purple" + +/obj/item/weapon/bedsheet/rainbow + icon_state = "sheetrainbow" + _color = "rainbow" + +/obj/item/weapon/bedsheet/red + icon_state = "sheetred" + _color = "red" + +/obj/item/weapon/bedsheet/red/redcoat + _color = "redcoat" //for denied stamp + +/obj/item/weapon/bedsheet/yellow + icon_state = "sheetyellow" + _color = "yellow" + +/obj/item/weapon/bedsheet/mime + icon_state = "sheetmime" + _color = "mime" + +/obj/item/weapon/bedsheet/clown + icon_state = "sheetclown" + _color = "clown" + +/obj/item/weapon/bedsheet/captain + icon_state = "sheetcaptain" + _color = "captain" + +/obj/item/weapon/bedsheet/rd + icon_state = "sheetrd" + _color = "director" + +/obj/item/weapon/bedsheet/medical + icon_state = "sheetmedical" + _color = "medical" + +/obj/item/weapon/bedsheet/hos + icon_state = "sheethos" + _color = "hosred" + +/obj/item/weapon/bedsheet/hop + icon_state = "sheethop" + _color = "hop" + +/obj/item/weapon/bedsheet/ce + icon_state = "sheetce" + _color = "chief" + +/obj/item/weapon/bedsheet/brown + icon_state = "sheetbrown" + _color = "brown" + +/obj/item/weapon/bedsheet/brown/cargo + _color = "cargo" //exists for washing machines, is not different from brown bedsheet in any way + + +/obj/structure/bedsheetbin + name = "linen bin" + desc = "A linen bin. It looks rather cosy." + icon = 'icons/obj/structures.dmi' + icon_state = "linenbin-full" + anchored = 1 + var/amount = 20 + var/list/sheets = list() + var/obj/item/hidden = null + + +/obj/structure/bedsheetbin/examine(mob/user) + ..() + if(amount == 0) + to_chat(user, "There are no bed sheets in the bin.") + else if(amount == 1) + to_chat(user, "There is one bed sheet in the bin.") + else + to_chat(user, "There are [amount] bed sheets in the bin.") + + +/obj/structure/bedsheetbin/update_icon() + switch(amount) + if(0) icon_state = "linenbin-empty" + if(1 to amount / 2) icon_state = "linenbin-half" + else icon_state = "linenbin-full" + + +/obj/structure/bedsheetbin/attackby(obj/item/I as obj, mob/user as mob) + if(istype(I, /obj/item/weapon/bedsheet)) + if(user.drop_item(I, src)) + sheets.Add(I) + amount++ + to_chat(user, "You put \the [I] in \the [src].") + else if(amount && !hidden && I.w_class < 4) //make sure there's sheets to hide it among, make sure nothing else is hidden in there. + if(user.drop_item(I, src)) + hidden = I + to_chat(user, "You hide [I] among the sheets.") + + +/obj/structure/bedsheetbin/attack_paw(mob/user as mob) + return attack_hand(user) + + +/obj/structure/bedsheetbin/attack_hand(mob/user as mob) + if(amount >= 1) + amount-- + + var/obj/item/weapon/bedsheet/B + if(sheets.len > 0) + B = sheets[sheets.len] + sheets.Remove(B) + + else + B = new /obj/item/weapon/bedsheet(loc) + + B.loc = user.loc + user.put_in_hands(B) + to_chat(user, "You take [B] out of [src].") + + if(hidden) + hidden.loc = user.loc + to_chat(user, "[hidden] falls out of [B]!") + hidden = null + + + add_fingerprint(user) + +/obj/structure/bedsheetbin/attack_tk(mob/user as mob) + if(amount >= 1) + amount-- + + var/obj/item/weapon/bedsheet/B + if(sheets.len > 0) + B = sheets[sheets.len] + sheets.Remove(B) + + else + B = new /obj/item/weapon/bedsheet(loc) + + B.loc = loc + to_chat(user, "You telekinetically remove [B] from [src].") + update_icon() + + if(hidden) + hidden.loc = loc + hidden = null + + + add_fingerprint(user) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 6e9dd071d03..605310988ea 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -1,451 +1,451 @@ -/obj/structure/closet - name = "closet" - desc = "It's a basic storage unit." - icon = 'icons/obj/closet.dmi' - icon_state = "closed" - density = 1 - flags = FPRINT - var/icon_closed = "closed" - var/icon_opened = "open" - var/opened = 0 - var/welded = 0 - var/locked = 0 - var/broken = 0 - var/large = 1 - var/pick_up_stuff = 1 // Pick up things that spawn at this location. - var/wall_mounted = 0 //never solid (You can always pass over it) - var/health = 100 - var/lastbang - var/storage_capacity = 30 //This is so that someone can't pack hundreds of items in a locker/crate - //then open it in a populated area to crash clients. - var/breakout_time = 2 //2 minutes by default - - starting_materials = list(MAT_IRON = 2*CC_PER_SHEET_METAL) - w_type = RECYK_METAL - ignoreinvert = 1 - - -/obj/structure/closet/initialize() - ..() - if(!opened) // if closed, any item at the crate's loc is put in the contents - take_contents() - else - density = 0 - -// Fix for #383 - C4 deleting fridges with corpses -/obj/structure/closet/Destroy() - dump_contents() - ..() - -/obj/structure/closet/alter_health() - return get_turf(src) - -/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0 || wall_mounted)) return 1 - return (!density) - -/obj/structure/closet/proc/can_open() - if(src.welded) - return 0 - return 1 - -/obj/structure/closet/proc/can_close() - for(var/obj/structure/closet/closet in get_turf(src)) - if(closet != src) - return 0 - return 1 - -/obj/structure/closet/proc/dump_contents() - if(usr) - var/mob/living/L = usr - var/obj/machinery/power/supermatter/SM = locate() in contents - if(istype(SM)) - message_admins("[L.name] ([L.ckey]) opened \the [src] that contained supermatter (JMP)") - log_game("[L.name] ([L.ckey]) opened \the [src] that contained supermatter (JMP)") - - - //Cham Projector Exception - for(var/obj/effect/dummy/chameleon/AD in src) - AD.loc = src.loc - - for(var/obj/O in src) - O.loc = src.loc - - for(var/mob/M in src) - M.loc = src.loc - if(M.client) - M.client.eye = M.client.mob - M.client.perspective = MOB_PERSPECTIVE - -/obj/structure/closet/proc/take_contents() - for(var/atom/movable/AM in src.loc) - if(insert(AM) == -1) // limit reached - break - INVOKE_EVENT(AM.on_moved,list("loc"=src)) - -/obj/structure/closet/proc/open() - if(src.opened) - return 0 - - if(!src.can_open()) - return 0 - - - src.icon_state = src.icon_opened - src.opened = 1 - src.density = 0 - src.dump_contents() - INVOKE_EVENT(on_destroyed, list()) - if(istype(src, /obj/structure/closet/body_bag)) - playsound(get_turf(src), 'sound/items/zip.ogg', 15, 1, -3) - else - playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) - return 1 - -/obj/structure/closet/proc/insert(var/atom/movable/AM) - - - if(contents.len >= storage_capacity) - return -1 - - // Prevent AIs from being crammed into lockers. /vg/ Redmine #153 - N3X - if(istype(AM, /mob/living/silicon/ai) || istype(AM, /mob/living/simple_animal/sculpture)) - return 0 - - if(istype(AM, /mob/living)) - var/mob/living/L = AM - if(L.locked_to) - return 0 - if(L.client) - L.client.perspective = EYE_PERSPECTIVE - L.client.eye = src - else if(!istype(AM, /obj/item) && !istype(AM, /obj/effect/dummy/chameleon)) - return 0 - else if(AM.density || AM.anchored) - return 0 - AM.loc = src - return 1 - -/obj/structure/closet/proc/close() - if(!src.opened) - return 0 - if(!src.can_close()) - return 0 - - take_contents() - /* /vg/: Delete if there's no code in here we need. - var/itemcount = 0 - - //Cham Projector Exception - for(var/obj/effect/dummy/chameleon/AD in src.loc) - if(itemcount >= storage_capacity) - break - AD.loc = src - itemcount++ - - for(var/obj/item/I in src.loc) - if(itemcount >= storage_capacity) - break - if(!I.anchored) - I.loc = src - itemcount++ - - for(var/mob/M in src.loc) - if(itemcount >= storage_capacity) - break - if(istype (M, /mob/dead/observer)) - continue - if(M.locked_to) - continue - - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - - M.loc = src - itemcount++ - */ - src.icon_state = src.icon_closed - src.opened = 0 - if(istype(src, /obj/structure/closet/body_bag)) - playsound(get_turf(src), 'sound/items/zip.ogg', 15, 1, -3) - else - playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) - density = 1 - for(var/obj/effect/beam/B in loc) - B.Crossed(src) - return 1 - -/obj/structure/closet/proc/toggle() - if(src.opened) - return src.close() - return src.open() - -// this should probably use dump_contents() -/obj/structure/closet/ex_act(severity) - switch(severity) - if(1) - for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion - A.loc = src.loc - A.ex_act(severity++) - qdel(src) - if(2) - if(prob(50)) - for (var/atom/movable/A as mob|obj in src) - A.loc = src.loc - A.ex_act(severity++) - qdel(src) - if(3) - if(prob(5)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - A.ex_act(severity++) - qdel(src) - -/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <= 0) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - qdel(src) - - return - -/obj/structure/closet/beam_connect(var/obj/effect/beam/B) - if(!processing_objects.Find(src)) - processing_objects.Add(src) - testing("Connected [src] with [B]!") - return ..() - -/obj/structure/closet/beam_disconnect(var/obj/effect/beam/B) - ..() - if(beams.len==0) - // I hope to christ this doesn't break shit. - processing_objects.Remove(src) - -/obj/structure/closet/process() - //..() - for(var/obj/effect/beam/B in beams) - health -= B.get_damage() - - if(health <= 0) - dump_contents() - qdel(src) - -// This is broken, see attack_ai. -/obj/structure/closet/attack_robot(mob/living/silicon/robot/user as mob) - if(isMoMMI(user)) - src.add_hiddenprint(user) - add_fingerprint(user) - return src.attack_hand(user) - ..(user) - -/obj/machinery/closet/attack_ai(mob/user as mob) - if(isMoMMI(user)) - src.add_hiddenprint(user) - add_fingerprint(user) - return src.attack_hand(user) - ..(user) - -/obj/structure/closet/attack_animal(mob/living/simple_animal/user as mob) - if(user.environment_smash) - visible_message("[user] destroys the [src]. ") - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - qdel(src) - -// this should probably use dump_contents() -/obj/structure/closet/blob_act() - if(prob(75)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - qdel(src) - -/obj/structure/closet/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(src.opened) - if(istype(W, /obj/item/weapon/grab)) - if(src.large) - var/obj/item/weapon/grab/G = W - src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet - else - to_chat(user, "The locker is too small to stuff [W] into!") - if(istype(W,/obj/item/tk_grab)) - return 0 - - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0,user)) - to_chat(user, "You need more welding fuel to complete this task.") - return - var/obj/item/stack/sheet/metal/Met = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - Met.amount = 2 - for(var/mob/M in viewers(src)) - M.show_message("\The [src] has been cut apart by [user] with \the [WT].", 1, "You hear welding.", 2) - qdel(src) - return - - user.drop_item(W, src.loc) - - else if(istype(W, /obj/item/stack/package_wrap)) - return - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0,user)) - to_chat(user, "You need more welding fuel to complete this task.") - return - src.welded =! src.welded - src.update_icon() - for(var/mob/M in viewers(src)) - M.show_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", 1, "You hear welding.", 2) - else if(!place(user, W)) - src.attack_hand(user) - return - -/obj/structure/closet/proc/place(var/mob/user, var/obj/item/I) - return 0 - -/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob, var/needs_opened = 1, var/show_message = 1, var/move_them = 1) - if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete - return 0 - if(!isturf(O.loc)) - return 0 - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.lying) - return 0 - if((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1)) - return 0 - if(!istype(user.loc, /turf)) // are you in a container/closet/pod/etc? Will also check for null loc - return 0 - if(needs_opened && !src.opened) - return 0 - if(istype(O, /obj/structure/closet)) - return 0 - if(move_them) - step_towards(O, src.loc) - if(show_message && user != O) - user.show_viewers("[user] stuffs [O] into [src]!") - src.add_fingerprint(user) - return 1 - -/obj/structure/closet/relaymove(mob/user as mob) - if(user.stat || !isturf(src.loc)) - return - - if(!src.open()) - to_chat(user, "It won't budge!") - if(!lastbang) - lastbang = 1 - for (var/mob/M in hearers(src, null)) - to_chat(M, text("BANG, bang!", max(0, 5 - get_dist(src, M)))) - spawn(30) - lastbang = 0 - - -/obj/structure/closet/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/closet/attack_hand(mob/user as mob) - if(!Adjacent(user)) - return - src.add_fingerprint(user) - - var/mob/living/L = user - if(src.opened==0 && L && L.client && L.hallucinating()) //If the closet is CLOSED and user is hallucinating - if(prob(10)) - var/client/C = L.client - var/image/temp_overlay = image(src.icon, icon_state=src.icon_opened) //Get the closet's OPEN icon - temp_overlay.override = 1 - temp_overlay.loc = src - - var/image/spooky_overlay - switch(rand(0,5)) - if(0) spooky_overlay = image('icons/mob/animal.dmi',icon_state="hunter",dir=turn(L.dir,180)) - if(1) spooky_overlay = image('icons/mob/animal.dmi',icon_state="zombie",dir=turn(L.dir,180)) - if(2) spooky_overlay = image('icons/mob/horror.dmi',icon_state="horror_[pick("male","female")]",dir=turn(L.dir,180)) - if(3) spooky_overlay = image('icons/mob/animal.dmi',icon_state="faithless",dir=turn(L.dir,180)) - if(4) spooky_overlay = image('icons/mob/animal.dmi',icon_state="carp",dir=turn(L.dir,180)) - if(5) spooky_overlay = image('icons/mob/animal.dmi',icon_state="skelly",dir=turn(L.dir,180)) - - if(!spooky_overlay) return - - temp_overlay.overlays += spooky_overlay - - C.images += temp_overlay - to_chat(L, sound('sound/machines/click.ogg')) - to_chat(L, sound('sound/hallucinations/scary.ogg')) - L.Weaken(5) - - sleep(50) - - if(C) - C.images -= temp_overlay - return - - if(!src.toggle()) - to_chat(usr, "It won't budge!") - -// tk grab then use on self -/obj/structure/closet/attack_self_tk(mob/user as mob) - src.add_fingerprint(user) - - if(!src.toggle()) - to_chat(usr, "It won't budge!") - -/obj/structure/closet/verb/verb_toggleopen() - set src in oview(1) - set category = "Object" - set name = "Toggle Open" - - if(!usr.canmove || usr.isUnconscious() || usr.restrained()) - return - - if(ishuman(usr) || isMoMMI(usr)) - if(isMoMMI(usr)) - src.add_hiddenprint(usr) - add_fingerprint(usr) - src.attack_hand(usr) - else - to_chat(usr, "This mob type can't use this verb.") - -/obj/structure/closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) - overlays.len = 0 - if(!opened) - icon_state = icon_closed - if(welded) - overlays += "welded" - else - icon_state = icon_opened - -// Objects that try to exit a locker by stepping were doing so successfully, -// and due to an oversight in turf/Enter() were going through walls. That -// should be independently resolved, but this is also an interesting twist. -/obj/structure/closet/Exit(atom/movable/AM) - open() - if(AM.loc == src) return 0 - return 1 - -/obj/structure/closet/container_resist() - var/mob/user = usr - var/breakout_time = 2 //2 minutes by default - - if(opened || (!welded && !locked)) - return //Door's open, not locked or welded, no point in resisting. - - //okay, so the closet is either welded or locked... resist!!! - user.delayNext(DELAY_ALL,100) - - to_chat(user, "You lean on the back of [src] and start pushing the door open. (this will take about [breakout_time] minutes.)") - for(var/mob/O in viewers(src)) - to_chat(O, "[src] begins to shake violently!") - var/turf/T = get_turf(src) //Check for moved locker - if(do_after(user, src, (breakout_time*60*10))) //minutes * 60seconds * 10deciseconds - if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) || T != get_turf(src)) - return - //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting - - welded = 0 //applies to all lockers lockers - locked = 0 //applies to critter crates and secure lockers only - broken = 1 //applies to secure lockers only - visible_message("[user] successfully broke out of [src]!") - to_chat(user, "You successfully break out of [src]!") - open() +/obj/structure/closet + name = "closet" + desc = "It's a basic storage unit." + icon = 'icons/obj/closet.dmi' + icon_state = "closed" + density = 1 + flags = FPRINT + var/icon_closed = "closed" + var/icon_opened = "open" + var/opened = 0 + var/welded = 0 + var/locked = 0 + var/broken = 0 + var/large = 1 + var/pick_up_stuff = 1 // Pick up things that spawn at this location. + var/wall_mounted = 0 //never solid (You can always pass over it) + var/health = 100 + var/lastbang + var/storage_capacity = 30 //This is so that someone can't pack hundreds of items in a locker/crate + //then open it in a populated area to crash clients. + var/breakout_time = 2 //2 minutes by default + + starting_materials = list(MAT_IRON = 2*CC_PER_SHEET_METAL) + w_type = RECYK_METAL + ignoreinvert = 1 + + +/obj/structure/closet/initialize() + ..() + if(!opened) // if closed, any item at the crate's loc is put in the contents + take_contents() + else + density = 0 + +// Fix for #383 - C4 deleting fridges with corpses +/obj/structure/closet/Destroy() + dump_contents() + ..() + +/obj/structure/closet/alter_health() + return get_turf(src) + +/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0 || wall_mounted)) return 1 + return (!density) + +/obj/structure/closet/proc/can_open() + if(src.welded) + return 0 + return 1 + +/obj/structure/closet/proc/can_close() + for(var/obj/structure/closet/closet in get_turf(src)) + if(closet != src) + return 0 + return 1 + +/obj/structure/closet/proc/dump_contents() + if(usr) + var/mob/living/L = usr + var/obj/machinery/power/supermatter/SM = locate() in contents + if(istype(SM)) + message_admins("[L.name] ([L.ckey]) opened \the [src] that contained supermatter (JMP)") + log_game("[L.name] ([L.ckey]) opened \the [src] that contained supermatter (JMP)") + + + //Cham Projector Exception + for(var/obj/effect/dummy/chameleon/AD in src) + AD.loc = src.loc + + for(var/obj/O in src) + O.loc = src.loc + + for(var/mob/M in src) + M.loc = src.loc + if(M.client) + M.client.eye = M.client.mob + M.client.perspective = MOB_PERSPECTIVE + +/obj/structure/closet/proc/take_contents() + for(var/atom/movable/AM in src.loc) + if(insert(AM) == -1) // limit reached + break + INVOKE_EVENT(AM.on_moved,list("loc"=src)) + +/obj/structure/closet/proc/open() + if(src.opened) + return 0 + + if(!src.can_open()) + return 0 + + + src.icon_state = src.icon_opened + src.opened = 1 + src.density = 0 + src.dump_contents() + INVOKE_EVENT(on_destroyed, list()) + if(istype(src, /obj/structure/closet/body_bag)) + playsound(get_turf(src), 'sound/items/zip.ogg', 15, 1, -3) + else + playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) + return 1 + +/obj/structure/closet/proc/insert(var/atom/movable/AM) + + + if(contents.len >= storage_capacity) + return -1 + + // Prevent AIs from being crammed into lockers. /vg/ Redmine #153 - N3X + if(istype(AM, /mob/living/silicon/ai) || istype(AM, /mob/living/simple_animal/sculpture)) + return 0 + + if(istype(AM, /mob/living)) + var/mob/living/L = AM + if(L.locked_to) + return 0 + if(L.client) + L.client.perspective = EYE_PERSPECTIVE + L.client.eye = src + else if(!istype(AM, /obj/item) && !istype(AM, /obj/effect/dummy/chameleon)) + return 0 + else if(AM.density || AM.anchored) + return 0 + AM.loc = src + return 1 + +/obj/structure/closet/proc/close() + if(!src.opened) + return 0 + if(!src.can_close()) + return 0 + + take_contents() + /* /vg/: Delete if there's no code in here we need. + var/itemcount = 0 + + //Cham Projector Exception + for(var/obj/effect/dummy/chameleon/AD in src.loc) + if(itemcount >= storage_capacity) + break + AD.loc = src + itemcount++ + + for(var/obj/item/I in src.loc) + if(itemcount >= storage_capacity) + break + if(!I.anchored) + I.loc = src + itemcount++ + + for(var/mob/M in src.loc) + if(itemcount >= storage_capacity) + break + if(istype (M, /mob/dead/observer)) + continue + if(M.locked_to) + continue + + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + + M.loc = src + itemcount++ + */ + src.icon_state = src.icon_closed + src.opened = 0 + if(istype(src, /obj/structure/closet/body_bag)) + playsound(get_turf(src), 'sound/items/zip.ogg', 15, 1, -3) + else + playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) + density = 1 + for(var/obj/effect/beam/B in loc) + B.Crossed(src) + return 1 + +/obj/structure/closet/proc/toggle() + if(src.opened) + return src.close() + return src.open() + +// this should probably use dump_contents() +/obj/structure/closet/ex_act(severity) + switch(severity) + if(1) + for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion + A.loc = src.loc + A.ex_act(severity++) + qdel(src) + if(2) + if(prob(50)) + for (var/atom/movable/A as mob|obj in src) + A.loc = src.loc + A.ex_act(severity++) + qdel(src) + if(3) + if(prob(5)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + A.ex_act(severity++) + qdel(src) + +/obj/structure/closet/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <= 0) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + qdel(src) + + return + +/obj/structure/closet/beam_connect(var/obj/effect/beam/B) + if(!processing_objects.Find(src)) + processing_objects.Add(src) + testing("Connected [src] with [B]!") + return ..() + +/obj/structure/closet/beam_disconnect(var/obj/effect/beam/B) + ..() + if(beams.len==0) + // I hope to christ this doesn't break shit. + processing_objects.Remove(src) + +/obj/structure/closet/process() + //..() + for(var/obj/effect/beam/B in beams) + health -= B.get_damage() + + if(health <= 0) + dump_contents() + qdel(src) + +// This is broken, see attack_ai. +/obj/structure/closet/attack_robot(mob/living/silicon/robot/user as mob) + if(isMoMMI(user)) + src.add_hiddenprint(user) + add_fingerprint(user) + return src.attack_hand(user) + ..(user) + +/obj/machinery/closet/attack_ai(mob/user as mob) + if(isMoMMI(user)) + src.add_hiddenprint(user) + add_fingerprint(user) + return src.attack_hand(user) + ..(user) + +/obj/structure/closet/attack_animal(mob/living/simple_animal/user as mob) + if(user.environment_smash) + visible_message("[user] destroys the [src]. ") + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + qdel(src) + +// this should probably use dump_contents() +/obj/structure/closet/blob_act() + if(prob(75)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + qdel(src) + +/obj/structure/closet/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(src.opened) + if(istype(W, /obj/item/weapon/grab)) + if(src.large) + var/obj/item/weapon/grab/G = W + src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet + else + to_chat(user, "The locker is too small to stuff [W] into!") + if(istype(W,/obj/item/tk_grab)) + return 0 + + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.remove_fuel(0,user)) + to_chat(user, "You need more welding fuel to complete this task.") + return + var/obj/item/stack/sheet/metal/Met = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + Met.amount = 2 + for(var/mob/M in viewers(src)) + M.show_message("\The [src] has been cut apart by [user] with \the [WT].", 1, "You hear welding.", 2) + qdel(src) + return + + user.drop_item(W, src.loc) + + else if(istype(W, /obj/item/stack/package_wrap)) + return + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.remove_fuel(0,user)) + to_chat(user, "You need more welding fuel to complete this task.") + return + src.welded =! src.welded + src.update_icon() + for(var/mob/M in viewers(src)) + M.show_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", 1, "You hear welding.", 2) + else if(!place(user, W)) + src.attack_hand(user) + return + +/obj/structure/closet/proc/place(var/mob/user, var/obj/item/I) + return 0 + +/obj/structure/closet/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob, var/needs_opened = 1, var/show_message = 1, var/move_them = 1) + if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete + return 0 + if(!isturf(O.loc)) + return 0 + if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.lying) + return 0 + if((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1)) + return 0 + if(!istype(user.loc, /turf)) // are you in a container/closet/pod/etc? Will also check for null loc + return 0 + if(needs_opened && !src.opened) + return 0 + if(istype(O, /obj/structure/closet)) + return 0 + if(move_them) + step_towards(O, src.loc) + if(show_message && user != O) + user.show_viewers("[user] stuffs [O] into [src]!") + src.add_fingerprint(user) + return 1 + +/obj/structure/closet/relaymove(mob/user as mob) + if(user.stat || !isturf(src.loc)) + return + + if(!src.open()) + to_chat(user, "It won't budge!") + if(!lastbang) + lastbang = 1 + for (var/mob/M in hearers(src, null)) + to_chat(M, text("BANG, bang!", max(0, 5 - get_dist(src, M)))) + spawn(30) + lastbang = 0 + + +/obj/structure/closet/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/closet/attack_hand(mob/user as mob) + if(!Adjacent(user)) + return + src.add_fingerprint(user) + + var/mob/living/L = user + if(src.opened==0 && L && L.client && L.hallucinating()) //If the closet is CLOSED and user is hallucinating + if(prob(10)) + var/client/C = L.client + var/image/temp_overlay = image(src.icon, icon_state=src.icon_opened) //Get the closet's OPEN icon + temp_overlay.override = 1 + temp_overlay.loc = src + + var/image/spooky_overlay + switch(rand(0,5)) + if(0) spooky_overlay = image('icons/mob/animal.dmi',icon_state="hunter",dir=turn(L.dir,180)) + if(1) spooky_overlay = image('icons/mob/animal.dmi',icon_state="zombie",dir=turn(L.dir,180)) + if(2) spooky_overlay = image('icons/mob/horror.dmi',icon_state="horror_[pick("male","female")]",dir=turn(L.dir,180)) + if(3) spooky_overlay = image('icons/mob/animal.dmi',icon_state="faithless",dir=turn(L.dir,180)) + if(4) spooky_overlay = image('icons/mob/animal.dmi',icon_state="carp",dir=turn(L.dir,180)) + if(5) spooky_overlay = image('icons/mob/animal.dmi',icon_state="skelly",dir=turn(L.dir,180)) + + if(!spooky_overlay) return + + temp_overlay.overlays += spooky_overlay + + C.images += temp_overlay + to_chat(L, sound('sound/machines/click.ogg')) + to_chat(L, sound('sound/hallucinations/scary.ogg')) + L.Weaken(5) + + sleep(50) + + if(C) + C.images -= temp_overlay + return + + if(!src.toggle()) + to_chat(usr, "It won't budge!") + +// tk grab then use on self +/obj/structure/closet/attack_self_tk(mob/user as mob) + src.add_fingerprint(user) + + if(!src.toggle()) + to_chat(usr, "It won't budge!") + +/obj/structure/closet/verb/verb_toggleopen() + set src in oview(1) + set category = "Object" + set name = "Toggle Open" + + if(!usr.canmove || usr.isUnconscious() || usr.restrained()) + return + + if(ishuman(usr) || isMoMMI(usr)) + if(isMoMMI(usr)) + src.add_hiddenprint(usr) + add_fingerprint(usr) + src.attack_hand(usr) + else + to_chat(usr, "This mob type can't use this verb.") + +/obj/structure/closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) + overlays.len = 0 + if(!opened) + icon_state = icon_closed + if(welded) + overlays += "welded" + else + icon_state = icon_opened + +// Objects that try to exit a locker by stepping were doing so successfully, +// and due to an oversight in turf/Enter() were going through walls. That +// should be independently resolved, but this is also an interesting twist. +/obj/structure/closet/Exit(atom/movable/AM) + open() + if(AM.loc == src) return 0 + return 1 + +/obj/structure/closet/container_resist() + var/mob/user = usr + var/breakout_time = 2 //2 minutes by default + + if(opened || (!welded && !locked)) + return //Door's open, not locked or welded, no point in resisting. + + //okay, so the closet is either welded or locked... resist!!! + user.delayNext(DELAY_ALL,100) + + to_chat(user, "You lean on the back of [src] and start pushing the door open. (this will take about [breakout_time] minutes.)") + for(var/mob/O in viewers(src)) + to_chat(O, "[src] begins to shake violently!") + var/turf/T = get_turf(src) //Check for moved locker + if(do_after(user, src, (breakout_time*60*10))) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) || T != get_turf(src)) + return + //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting + + welded = 0 //applies to all lockers lockers + locked = 0 //applies to critter crates and secure lockers only + broken = 1 //applies to secure lockers only + visible_message("[user] successfully broke out of [src]!") + to_chat(user, "You successfully break out of [src]!") + open() diff --git a/code/game/objects/structures/crates_lockers/closets/coffin.dm b/code/game/objects/structures/crates_lockers/closets/coffin.dm index 256f72522e8..689fb5ba3b3 100644 --- a/code/game/objects/structures/crates_lockers/closets/coffin.dm +++ b/code/game/objects/structures/crates_lockers/closets/coffin.dm @@ -1,12 +1,12 @@ -/obj/structure/closet/coffin - name = "coffin" - desc = "It's a burial receptacle for the dearly departed." - icon_state = "coffin" - icon_closed = "coffin" - icon_opened = "coffin_open" - -/obj/structure/closet/coffin/update_icon() - if(!opened) - icon_state = icon_closed - else +/obj/structure/closet/coffin + name = "coffin" + desc = "It's a burial receptacle for the dearly departed." + icon_state = "coffin" + icon_closed = "coffin" + icon_opened = "coffin_open" + +/obj/structure/closet/coffin/update_icon() + if(!opened) + icon_state = icon_closed + else icon_state = icon_opened \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/crittercrate.dm b/code/game/objects/structures/crates_lockers/closets/crittercrate.dm index 230aca6ca06..a9ccd78db7f 100644 --- a/code/game/objects/structures/crates_lockers/closets/crittercrate.dm +++ b/code/game/objects/structures/crates_lockers/closets/crittercrate.dm @@ -1,8 +1,8 @@ -/obj/structure/closet/crate/critter - name = "critter crate" - desc = "A crate which can sustain life for a while." - icon_state = "critter" - icon_opened = "critteropen" - icon_closed = "critter" - +/obj/structure/closet/crate/critter + name = "critter crate" + desc = "A crate which can sustain life for a while." + icon_state = "critter" + icon_opened = "critteropen" + icon_closed = "critter" + breakout_time = 0.75 //45 seconds if it's an unwelded critter crate \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index 9465833b398..f48ebef9cd9 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -1,142 +1,142 @@ -/obj/structure/closet/cabinet - name = "cabinet" - desc = "Old will forever be in fashion." - icon_state = "cabinet_closed" - icon_closed = "cabinet_closed" - icon_opened = "cabinet_open" - -/obj/structure/closet/cabinet/update_icon() - if(!opened) - icon_state = icon_closed - else - icon_state = icon_opened - -/obj/structure/closet/acloset - name = "strange closet" - desc = "It looks alien!" - icon_state = "acloset" - icon_closed = "acloset" - icon_opened = "aclosetopen" - - -/obj/structure/closet/gimmick - name = "administrative supply closet" - desc = "It's a storage unit for things that have no right being here." - icon_state = "syndicate1" - icon_closed = "syndicate1" - icon_opened = "syndicate1open" - anchored = 0 - -/obj/structure/closet/gimmick/russian - name = "russian surplus closet" - desc = "It's a storage unit for Russian standard-issue surplus." - icon_state = "syndicate1" - icon_closed = "syndicate1" - icon_opened = "syndicate1open" - -/obj/structure/closet/gimmick/russian/New() - ..() - sleep(2) - new /obj/item/clothing/head/ushanka(src) - new /obj/item/clothing/head/ushanka(src) - new /obj/item/clothing/head/ushanka(src) - new /obj/item/clothing/head/ushanka(src) - new /obj/item/clothing/head/ushanka(src) - new /obj/item/clothing/under/soviet(src) - new /obj/item/clothing/under/soviet(src) - new /obj/item/clothing/under/soviet(src) - new /obj/item/clothing/under/soviet(src) - new /obj/item/clothing/under/soviet(src) - - -/obj/structure/closet/gimmick/tacticool - name = "tacticool gear closet" - desc = "It's a storage unit for Tacticool gear." - icon_state = "syndicate1" - icon_closed = "syndicate1" - icon_opened = "syndicate1open" - -/obj/structure/closet/gimmick/tacticool/New() - ..() - sleep(2) - new /obj/item/clothing/glasses/eyepatch(src) - new /obj/item/clothing/glasses/sunglasses(src) - new /obj/item/clothing/gloves/swat(src) - new /obj/item/clothing/gloves/swat(src) - new /obj/item/clothing/head/helmet/swat(src) - new /obj/item/clothing/head/helmet/swat(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/clothing/shoes/swat(src) - new /obj/item/clothing/shoes/swat(src) - new /obj/item/clothing/suit/armor/swat(src) - new /obj/item/clothing/suit/armor/swat(src) - new /obj/item/clothing/under/syndicate/tacticool(src) - new /obj/item/clothing/under/syndicate/tacticool(src) - - -/obj/structure/closet/thunderdome - name = "\improper Thunderdome closet" - desc = "Everything you need!" - icon_state = "syndicate" - icon_closed = "syndicate" - icon_opened = "syndicateopen" - anchored = 1 - -/obj/structure/closet/thunderdome/New() - ..() - sleep(2) - -/obj/structure/closet/thunderdome/tdred - name = "red-team Thunderdome closet" - -/obj/structure/closet/thunderdome/tdred/New() - ..() - sleep(2) - new /obj/item/clothing/suit/armor/tdome/red(src) - new /obj/item/clothing/suit/armor/tdome/red(src) - new /obj/item/clothing/suit/armor/tdome/red(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/clothing/head/helmet/thunderdome(src) - new /obj/item/clothing/head/helmet/thunderdome(src) - new /obj/item/clothing/head/helmet/thunderdome(src) - -/obj/structure/closet/thunderdome/tdgreen - name = "green-team Thunderdome closet" - icon_state = "syndicate1" - icon_closed = "syndicate1" - icon_opened = "syndicate1open" - -/obj/structure/closet/thunderdome/tdgreen/New() - ..() - sleep(2) - new /obj/item/clothing/suit/armor/tdome/green(src) - new /obj/item/clothing/suit/armor/tdome/green(src) - new /obj/item/clothing/suit/armor/tdome/green(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/clothing/head/helmet/thunderdome(src) - new /obj/item/clothing/head/helmet/thunderdome(src) - new /obj/item/clothing/head/helmet/thunderdome(src) - +/obj/structure/closet/cabinet + name = "cabinet" + desc = "Old will forever be in fashion." + icon_state = "cabinet_closed" + icon_closed = "cabinet_closed" + icon_opened = "cabinet_open" + +/obj/structure/closet/cabinet/update_icon() + if(!opened) + icon_state = icon_closed + else + icon_state = icon_opened + +/obj/structure/closet/acloset + name = "strange closet" + desc = "It looks alien!" + icon_state = "acloset" + icon_closed = "acloset" + icon_opened = "aclosetopen" + + +/obj/structure/closet/gimmick + name = "administrative supply closet" + desc = "It's a storage unit for things that have no right being here." + icon_state = "syndicate1" + icon_closed = "syndicate1" + icon_opened = "syndicate1open" + anchored = 0 + +/obj/structure/closet/gimmick/russian + name = "russian surplus closet" + desc = "It's a storage unit for Russian standard-issue surplus." + icon_state = "syndicate1" + icon_closed = "syndicate1" + icon_opened = "syndicate1open" + +/obj/structure/closet/gimmick/russian/New() + ..() + sleep(2) + new /obj/item/clothing/head/ushanka(src) + new /obj/item/clothing/head/ushanka(src) + new /obj/item/clothing/head/ushanka(src) + new /obj/item/clothing/head/ushanka(src) + new /obj/item/clothing/head/ushanka(src) + new /obj/item/clothing/under/soviet(src) + new /obj/item/clothing/under/soviet(src) + new /obj/item/clothing/under/soviet(src) + new /obj/item/clothing/under/soviet(src) + new /obj/item/clothing/under/soviet(src) + + +/obj/structure/closet/gimmick/tacticool + name = "tacticool gear closet" + desc = "It's a storage unit for Tacticool gear." + icon_state = "syndicate1" + icon_closed = "syndicate1" + icon_opened = "syndicate1open" + +/obj/structure/closet/gimmick/tacticool/New() + ..() + sleep(2) + new /obj/item/clothing/glasses/eyepatch(src) + new /obj/item/clothing/glasses/sunglasses(src) + new /obj/item/clothing/gloves/swat(src) + new /obj/item/clothing/gloves/swat(src) + new /obj/item/clothing/head/helmet/swat(src) + new /obj/item/clothing/head/helmet/swat(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/clothing/shoes/swat(src) + new /obj/item/clothing/shoes/swat(src) + new /obj/item/clothing/suit/armor/swat(src) + new /obj/item/clothing/suit/armor/swat(src) + new /obj/item/clothing/under/syndicate/tacticool(src) + new /obj/item/clothing/under/syndicate/tacticool(src) + + +/obj/structure/closet/thunderdome + name = "\improper Thunderdome closet" + desc = "Everything you need!" + icon_state = "syndicate" + icon_closed = "syndicate" + icon_opened = "syndicateopen" + anchored = 1 + +/obj/structure/closet/thunderdome/New() + ..() + sleep(2) + +/obj/structure/closet/thunderdome/tdred + name = "red-team Thunderdome closet" + +/obj/structure/closet/thunderdome/tdred/New() + ..() + sleep(2) + new /obj/item/clothing/suit/armor/tdome/red(src) + new /obj/item/clothing/suit/armor/tdome/red(src) + new /obj/item/clothing/suit/armor/tdome/red(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/clothing/head/helmet/thunderdome(src) + new /obj/item/clothing/head/helmet/thunderdome(src) + new /obj/item/clothing/head/helmet/thunderdome(src) + +/obj/structure/closet/thunderdome/tdgreen + name = "green-team Thunderdome closet" + icon_state = "syndicate1" + icon_closed = "syndicate1" + icon_opened = "syndicate1open" + +/obj/structure/closet/thunderdome/tdgreen/New() + ..() + sleep(2) + new /obj/item/clothing/suit/armor/tdome/green(src) + new /obj/item/clothing/suit/armor/tdome/green(src) + new /obj/item/clothing/suit/armor/tdome/green(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/clothing/head/helmet/thunderdome(src) + new /obj/item/clothing/head/helmet/thunderdome(src) + new /obj/item/clothing/head/helmet/thunderdome(src) + diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index 9f32de1cbbd..ec859762551 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -1,119 +1,119 @@ -/* Closets for specific jobs - * Contains: - * Bartender - * Janitor - * Lawyer - */ - -/* - * Bartender - */ -/obj/structure/closet/gmcloset - name = "formal closet" - desc = "It's a storage unit for formal clothing." - icon_state = "black" - icon_closed = "black" - -/obj/structure/closet/gmcloset/New() - ..() - new /obj/item/clothing/head/that(src) - new /obj/item/clothing/head/that(src) - new /obj/item/clothing/head/hairflower - new /obj/item/clothing/under/sl_suit(src) - new /obj/item/clothing/under/sl_suit(src) - new /obj/item/clothing/under/rank/bartender(src) - new /obj/item/clothing/under/rank/bartender(src) - new /obj/item/clothing/under/dress/dress_saloon - new /obj/item/clothing/suit/wcoat(src) - new /obj/item/clothing/suit/wcoat(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/monkeyclothes(src) - new /obj/item/clothing/monkeyclothes(src) - new /obj/item/weapon/reagent_containers/food/drinks/coloring(src) - -/* - * Janitor - */ -/obj/structure/closet/jcloset - name = "custodial closet" - desc = "It's a storage unit for janitorial clothes and gear." - icon_state = "mixed" - icon_closed = "mixed" - -/obj/structure/closet/jcloset/New() - ..() - new /obj/item/clothing/under/rank/janitor(src) - new /obj/item/weapon/cartridge/janitor(src) - new /obj/item/device/flashlight(src) - new /obj/item/clothing/shoes/galoshes(src) - new /obj/item/weapon/caution(src) - new /obj/item/weapon/caution(src) - new /obj/item/weapon/caution(src) - new /obj/item/weapon/caution(src) - new /obj/item/weapon/caution(src) - new /obj/item/weapon/caution(src) - new /obj/item/weapon/storage/bag/trash(src) - new /obj/item/device/lightreplacer/loaded/mixed(src) - new /obj/item/clothing/gloves/black(src) - new /obj/item/clothing/head/soft/purple(src) - new /obj/item/weapon/storage/box/lights/he(src) - new /obj/item/weapon/storage/box/lights/he(src) - -/* - * Lawyer - */ -/obj/structure/closet/lawcloset - name = "legal closet" - desc = "It's a storage unit for courtroom apparel and items." - icon_state = "blue" - icon_closed = "blue" - -/obj/structure/closet/lawcloset/New() - ..() - new /obj/item/clothing/under/cia(src) - new /obj/item/clothing/under/lawyer/female(src) - new /obj/item/clothing/under/lawyer/black(src) - new /obj/item/clothing/under/lawyer/red(src) - new /obj/item/clothing/under/lawyer/bluesuit(src) - new /obj/item/clothing/suit/storage/lawyer/bluejacket(src) - new /obj/item/clothing/under/lawyer/purpsuit(src) - new /obj/item/clothing/suit/storage/lawyer/purpjacket(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/clothing/shoes/black(src) - - //Paramedic - -/obj/structure/closet/paramedic - name = "Paramedic Wardrobe" - desc = "It's a storage unit for paramedic equipment." - icon_state = "blue" - icon_closed = "blue" - - -/obj/structure/closet/paramedic/New() - ..() - new /obj/item/clothing/under/rank/medical/paramedic(src) - new /obj/item/clothing/under/rank/medical/paramedic(src) - new /obj/item/device/radio/headset/headset_med(src) - new /obj/item/device/radio/headset/headset_med(src) - new /obj/item/clothing/head/soft/paramedic(src) - new /obj/item/clothing/head/soft/paramedic(src) - new /obj/item/clothing/head/soft/paramedic(src) - new /obj/item/clothing/head/soft/paramedic(src) - new /obj/item/clothing/gloves/latex(src) - new /obj/item/clothing/gloves/latex(src) - new /obj/item/clothing/gloves/latex(src) - new /obj/item/clothing/gloves/latex(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/suit/storage/paramedic(src) - new /obj/item/clothing/suit/storage/paramedic(src) - new /obj/item/clothing/suit/storage/paramedic(src) - new /obj/item/clothing/suit/storage/paramedic(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/device/gps/paramedic(src) - new /obj/item/device/gps/paramedic(src) +/* Closets for specific jobs + * Contains: + * Bartender + * Janitor + * Lawyer + */ + +/* + * Bartender + */ +/obj/structure/closet/gmcloset + name = "formal closet" + desc = "It's a storage unit for formal clothing." + icon_state = "black" + icon_closed = "black" + +/obj/structure/closet/gmcloset/New() + ..() + new /obj/item/clothing/head/that(src) + new /obj/item/clothing/head/that(src) + new /obj/item/clothing/head/hairflower + new /obj/item/clothing/under/sl_suit(src) + new /obj/item/clothing/under/sl_suit(src) + new /obj/item/clothing/under/rank/bartender(src) + new /obj/item/clothing/under/rank/bartender(src) + new /obj/item/clothing/under/dress/dress_saloon + new /obj/item/clothing/suit/wcoat(src) + new /obj/item/clothing/suit/wcoat(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/monkeyclothes(src) + new /obj/item/clothing/monkeyclothes(src) + new /obj/item/weapon/reagent_containers/food/drinks/coloring(src) + +/* + * Janitor + */ +/obj/structure/closet/jcloset + name = "custodial closet" + desc = "It's a storage unit for janitorial clothes and gear." + icon_state = "mixed" + icon_closed = "mixed" + +/obj/structure/closet/jcloset/New() + ..() + new /obj/item/clothing/under/rank/janitor(src) + new /obj/item/weapon/cartridge/janitor(src) + new /obj/item/device/flashlight(src) + new /obj/item/clothing/shoes/galoshes(src) + new /obj/item/weapon/caution(src) + new /obj/item/weapon/caution(src) + new /obj/item/weapon/caution(src) + new /obj/item/weapon/caution(src) + new /obj/item/weapon/caution(src) + new /obj/item/weapon/caution(src) + new /obj/item/weapon/storage/bag/trash(src) + new /obj/item/device/lightreplacer/loaded/mixed(src) + new /obj/item/clothing/gloves/black(src) + new /obj/item/clothing/head/soft/purple(src) + new /obj/item/weapon/storage/box/lights/he(src) + new /obj/item/weapon/storage/box/lights/he(src) + +/* + * Lawyer + */ +/obj/structure/closet/lawcloset + name = "legal closet" + desc = "It's a storage unit for courtroom apparel and items." + icon_state = "blue" + icon_closed = "blue" + +/obj/structure/closet/lawcloset/New() + ..() + new /obj/item/clothing/under/cia(src) + new /obj/item/clothing/under/lawyer/female(src) + new /obj/item/clothing/under/lawyer/black(src) + new /obj/item/clothing/under/lawyer/red(src) + new /obj/item/clothing/under/lawyer/bluesuit(src) + new /obj/item/clothing/suit/storage/lawyer/bluejacket(src) + new /obj/item/clothing/under/lawyer/purpsuit(src) + new /obj/item/clothing/suit/storage/lawyer/purpjacket(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/clothing/shoes/black(src) + + //Paramedic + +/obj/structure/closet/paramedic + name = "Paramedic Wardrobe" + desc = "It's a storage unit for paramedic equipment." + icon_state = "blue" + icon_closed = "blue" + + +/obj/structure/closet/paramedic/New() + ..() + new /obj/item/clothing/under/rank/medical/paramedic(src) + new /obj/item/clothing/under/rank/medical/paramedic(src) + new /obj/item/device/radio/headset/headset_med(src) + new /obj/item/device/radio/headset/headset_med(src) + new /obj/item/clothing/head/soft/paramedic(src) + new /obj/item/clothing/head/soft/paramedic(src) + new /obj/item/clothing/head/soft/paramedic(src) + new /obj/item/clothing/head/soft/paramedic(src) + new /obj/item/clothing/gloves/latex(src) + new /obj/item/clothing/gloves/latex(src) + new /obj/item/clothing/gloves/latex(src) + new /obj/item/clothing/gloves/latex(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/suit/storage/paramedic(src) + new /obj/item/clothing/suit/storage/paramedic(src) + new /obj/item/clothing/suit/storage/paramedic(src) + new /obj/item/clothing/suit/storage/paramedic(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/device/gps/paramedic(src) + new /obj/item/device/gps/paramedic(src) diff --git a/code/game/objects/structures/crates_lockers/closets/l3closet.dm b/code/game/objects/structures/crates_lockers/closets/l3closet.dm index 6e7591868a3..cf6a8264488 100644 --- a/code/game/objects/structures/crates_lockers/closets/l3closet.dm +++ b/code/game/objects/structures/crates_lockers/closets/l3closet.dm @@ -1,77 +1,77 @@ -/obj/structure/closet/l3closet - name = "level-3 biohazard suit closet" - desc = "It's a storage unit for level-3 biohazard gear." - icon_state = "bio" - icon_closed = "bio" - icon_opened = "bioopen" - -/obj/structure/closet/l3closet/New() - ..() - sleep(2) - new /obj/item/clothing/suit/bio_suit/general( src ) - new /obj/item/clothing/head/bio_hood/general( src ) - - -/obj/structure/closet/l3closet/general - icon_state = "bio_general" - icon_closed = "bio_general" - icon_opened = "bio_generalopen" - -/obj/structure/closet/l3closet/general/New() - ..() - sleep(2) - contents = list() - new /obj/item/clothing/suit/bio_suit/general( src ) - new /obj/item/clothing/head/bio_hood/general( src ) - - -/obj/structure/closet/l3closet/virology - icon_state = "bio_virology" - icon_closed = "bio_virology" - icon_opened = "bio_virologyopen" - -/obj/structure/closet/l3closet/virology/New() - ..() - sleep(2) - contents = list() - new /obj/item/clothing/suit/bio_suit/virology( src ) - new /obj/item/clothing/head/bio_hood/virology( src ) - - -/obj/structure/closet/l3closet/security - icon_state = "bio_security" - icon_closed = "bio_security" - icon_opened = "bio_securityopen" - -/obj/structure/closet/l3closet/security/New() - ..() - sleep(2) - contents = list() - new /obj/item/clothing/suit/bio_suit/security( src ) - new /obj/item/clothing/head/bio_hood/security( src ) - - -/obj/structure/closet/l3closet/janitor - icon_state = "bio_janitor" - icon_closed = "bio_janitor" - icon_opened = "bio_janitoropen" - -/obj/structure/closet/l3closet/janitor/New() - ..() - sleep(2) - contents = list() - new /obj/item/clothing/suit/bio_suit/janitor( src ) - new /obj/item/clothing/head/bio_hood/janitor( src ) - - -/obj/structure/closet/l3closet/scientist - icon_state = "bio_scientist" - icon_closed = "bio_scientist" - icon_opened = "bio_scientistopen" - -/obj/structure/closet/l3closet/scientist/New() - ..() - sleep(2) - contents = list() - new /obj/item/clothing/suit/bio_suit/scientist( src ) +/obj/structure/closet/l3closet + name = "level-3 biohazard suit closet" + desc = "It's a storage unit for level-3 biohazard gear." + icon_state = "bio" + icon_closed = "bio" + icon_opened = "bioopen" + +/obj/structure/closet/l3closet/New() + ..() + sleep(2) + new /obj/item/clothing/suit/bio_suit/general( src ) + new /obj/item/clothing/head/bio_hood/general( src ) + + +/obj/structure/closet/l3closet/general + icon_state = "bio_general" + icon_closed = "bio_general" + icon_opened = "bio_generalopen" + +/obj/structure/closet/l3closet/general/New() + ..() + sleep(2) + contents = list() + new /obj/item/clothing/suit/bio_suit/general( src ) + new /obj/item/clothing/head/bio_hood/general( src ) + + +/obj/structure/closet/l3closet/virology + icon_state = "bio_virology" + icon_closed = "bio_virology" + icon_opened = "bio_virologyopen" + +/obj/structure/closet/l3closet/virology/New() + ..() + sleep(2) + contents = list() + new /obj/item/clothing/suit/bio_suit/virology( src ) + new /obj/item/clothing/head/bio_hood/virology( src ) + + +/obj/structure/closet/l3closet/security + icon_state = "bio_security" + icon_closed = "bio_security" + icon_opened = "bio_securityopen" + +/obj/structure/closet/l3closet/security/New() + ..() + sleep(2) + contents = list() + new /obj/item/clothing/suit/bio_suit/security( src ) + new /obj/item/clothing/head/bio_hood/security( src ) + + +/obj/structure/closet/l3closet/janitor + icon_state = "bio_janitor" + icon_closed = "bio_janitor" + icon_opened = "bio_janitoropen" + +/obj/structure/closet/l3closet/janitor/New() + ..() + sleep(2) + contents = list() + new /obj/item/clothing/suit/bio_suit/janitor( src ) + new /obj/item/clothing/head/bio_hood/janitor( src ) + + +/obj/structure/closet/l3closet/scientist + icon_state = "bio_scientist" + icon_closed = "bio_scientist" + icon_opened = "bio_scientistopen" + +/obj/structure/closet/l3closet/scientist/New() + ..() + sleep(2) + contents = list() + new /obj/item/clothing/suit/bio_suit/scientist( src ) new /obj/item/clothing/head/bio_hood/scientist( src ) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/malfunction.dm b/code/game/objects/structures/crates_lockers/closets/malfunction.dm index 7cfb4f18e2f..6f554a08494 100644 --- a/code/game/objects/structures/crates_lockers/closets/malfunction.dm +++ b/code/game/objects/structures/crates_lockers/closets/malfunction.dm @@ -1,17 +1,17 @@ - -/obj/structure/closet/malf/suits - desc = "It's a storage unit for operational gear." - icon_state = "syndicate" - icon_closed = "syndicate" - icon_opened = "syndicateopen" - -/obj/structure/closet/malf/suits/New() - ..() - sleep(2) - new /obj/item/weapon/tank/jetpack/void(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/clothing/head/helmet/space/nasavoid(src) - new /obj/item/clothing/suit/space/nasavoid(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/cell(src) + +/obj/structure/closet/malf/suits + desc = "It's a storage unit for operational gear." + icon_state = "syndicate" + icon_closed = "syndicate" + icon_opened = "syndicateopen" + +/obj/structure/closet/malf/suits/New() + ..() + sleep(2) + new /obj/item/weapon/tank/jetpack/void(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/clothing/head/helmet/space/nasavoid(src) + new /obj/item/clothing/suit/space/nasavoid(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/cell(src) new /obj/item/device/multitool(src) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 28f07c45b4d..5cab18a6017 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -1,220 +1,220 @@ -/obj/structure/closet/secure_closet/engineering_chief - name = "Chief Engineer's Locker" - req_access = list(access_ce) - icon_state = "securece1" - icon_closed = "securece" - icon_locked = "securece1" - icon_opened = "secureceopen" - icon_broken = "securecebroken" - icon_off = "secureceoff" - - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/industrial(src) - else - new /obj/item/weapon/storage/backpack/satchel_eng(src) - new /obj/item/blueprints(src) - new /obj/item/clothing/under/rank/chief_engineer(src) - new /obj/item/clothing/head/hardhat/white(src) - new /obj/item/clothing/head/welding(src) - new /obj/item/clothing/gloves/yellow(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/weapon/cartridge/ce(src) - new /obj/item/device/radio/headset/heads/ce(src) - new /obj/item/weapon/storage/toolbox/mechanical(src) - new /obj/item/device/device_analyser/advanced(src) - new /obj/item/clothing/suit/storage/hazardvest(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/device/multitool(src) - new /obj/item/device/flash(src) - new /obj/item/device/gps/engineering(src) - new /obj/item/weapon/storage/belt/utility/chief(src) - return - - - -/obj/structure/closet/secure_closet/engineering_electrical - name = "Electrical Supplies" - req_access = list(access_engine_equip) - icon_state = "secureengelec1" - icon_closed = "secureengelec" - icon_locked = "secureengelec1" - icon_opened = "toolclosetopen" - icon_broken = "secureengelecbroken" - icon_off = "secureengelecoff" - - - New() - ..() - sleep(2) - new /obj/item/weapon/storage/toolbox/electrical(src) - new /obj/item/weapon/storage/toolbox/electrical(src) - new /obj/item/weapon/storage/toolbox/electrical(src) - new /obj/item/weapon/rcl(src) - new /obj/item/weapon/circuitboard/power_control(src) - new /obj/item/weapon/circuitboard/power_control(src) - new /obj/item/weapon/circuitboard/power_control(src) - new /obj/item/clothing/gloves/yellow(src) - new /obj/item/clothing/gloves/yellow(src) - new /obj/item/device/multitool(src) - new /obj/item/device/multitool(src) - new /obj/item/device/multitool(src) - return - - - -/obj/structure/closet/secure_closet/engineering_welding - name = "Welding Supplies" - req_access = list(access_engine_equip) - icon_state = "secureengweld1" - icon_closed = "secureengweld" - icon_locked = "secureengweld1" - icon_opened = "toolclosetopen" - icon_broken = "secureengweldbroken" - icon_off = "secureengweldoff" - - - New() - ..() - sleep(2) - new /obj/item/clothing/head/welding(src) - new /obj/item/clothing/head/welding(src) - new /obj/item/clothing/head/welding(src) - new /obj/item/weapon/weldingtool/largetank(src) - new /obj/item/weapon/weldingtool/largetank(src) - new /obj/item/weapon/weldingtool/largetank(src) - return - - - -/obj/structure/closet/secure_closet/engineering_personal - name = "Engineer's Locker" - req_access = list(access_engine_equip) - icon_state = "secureeng1" - icon_closed = "secureeng" - icon_locked = "secureeng1" - icon_opened = "secureengopen" - icon_broken = "secureengbroken" - icon_off = "secureengoff" - - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/industrial(src) - else - new /obj/item/weapon/storage/backpack/satchel_eng(src) - new /obj/item/clothing/under/rank/engineer(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/weapon/storage/toolbox/mechanical(src) -// new /obj/item/weapon/cartridge/engineering(src) - new /obj/item/device/radio/headset/headset_eng(src) - new /obj/item/clothing/suit/storage/hazardvest(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/clothing/glasses/meson(src) - new /obj/item/taperoll/engineering(src) - new /obj/item/taperoll/engineering(src) - new /obj/item/device/gps/engineering(src) - return - -/obj/structure/closet/secure_closet/engineering_atmos - name = "Atmospheric Technician's Locker" - req_access = list(access_atmospherics) - icon_state = "secureatmos1" - icon_closed = "secureatmos" - icon_locked = "secureatmos1" - icon_opened = "secureatmosopen" - icon_broken = "secureatmosbroken" - icon_off = "secureatmosoff" - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack(src) - else - new /obj/item/weapon/storage/backpack/satchel_norm(src) - new /obj/item/clothing/under/rank/atmospheric_technician(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/weapon/storage/toolbox/mechanical(src) - new /obj/item/weapon/extinguisher/foam(src) - // new /obj/item/weapon/cartridge/engineering(src) - new /obj/item/device/radio/headset/headset_eng(src) - new /obj/item/clothing/suit/storage/hazardvest(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/taperoll/atmos(src) - new /obj/item/pipe_planner(src) - new /obj/item/weapon/wrench/socket(src) - new /obj/item/weapon/gun/projectile/flare(src) //yay for emergency lighting - new /obj/item/ammo_storage/box/flare(src) - new /obj/item/device/rcd/rpd(src) - new /obj/item/device/analyzer(src) - return - -/obj/structure/closet/secure_closet/engineering_mechanic - name = "Mechanic's Locker" - req_access = list(access_mechanic) - icon_state = "securemechni1" - icon_closed = "securemechni" - icon_locked = "securemechni1" - icon_opened = "securemechniopen" - icon_broken = "securemechnibroken" - icon_off = "securemechnioff" - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/industrial(src) - else - new /obj/item/weapon/storage/backpack/satchel_eng(src) - new /obj/item/clothing/under/rank/mechanic(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/weapon/storage/toolbox/mechanical(src) - //new /obj/item/device/component_exchanger(src) - new /obj/item/device/radio/headset/headset_engsci(src) - new /obj/item/clothing/suit/storage/hazardvest(src) - new /obj/item/device/device_analyser(src) - new /obj/item/weapon/soap/nanotrasen(src) - new /obj/item/clothing/gloves/black(src) - new /obj/item/device/assembly_frame(src) - new /obj/item/device/assembly_frame(src) - - if(prob(50)) - new /obj/item/clothing/head/welding(src) - else - new /obj/item/clothing/glasses/welding(src) - return - -/obj/structure/closet/secure_closet/engineering_general - name = "Engineering Locker" - req_access = list(access_engine_equip) - icon_state = "secureeng1" - icon_closed = "secureeng" - icon_locked = "secureeng1" - icon_opened = "secureengopen" - icon_broken = "secureengbroken" - icon_off = "secureengoff" - - -/obj/structure/closet/crate/secure/large/reinforced/shard - name = "Supermatter Shard Crate" - New() - ..() - sleep(2) - new /obj/machinery/power/supermatter/shard(src) - -/obj/structure/closet/crate/secure/large/reinforced/shard/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover,/obj/machinery/power/supermatter)) - return 1 - . = ..() - -/obj/structure/closet/crate/secure/large/reinforced/shard/can_close() - for(var/obj/machinery/power/supermatter/S in loc) - if(S.damage) //This is what I like to call predicting the metagame - return 0 +/obj/structure/closet/secure_closet/engineering_chief + name = "Chief Engineer's Locker" + req_access = list(access_ce) + icon_state = "securece1" + icon_closed = "securece" + icon_locked = "securece1" + icon_opened = "secureceopen" + icon_broken = "securecebroken" + icon_off = "secureceoff" + + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/industrial(src) + else + new /obj/item/weapon/storage/backpack/satchel_eng(src) + new /obj/item/blueprints(src) + new /obj/item/clothing/under/rank/chief_engineer(src) + new /obj/item/clothing/head/hardhat/white(src) + new /obj/item/clothing/head/welding(src) + new /obj/item/clothing/gloves/yellow(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/weapon/cartridge/ce(src) + new /obj/item/device/radio/headset/heads/ce(src) + new /obj/item/weapon/storage/toolbox/mechanical(src) + new /obj/item/device/device_analyser/advanced(src) + new /obj/item/clothing/suit/storage/hazardvest(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/device/multitool(src) + new /obj/item/device/flash(src) + new /obj/item/device/gps/engineering(src) + new /obj/item/weapon/storage/belt/utility/chief(src) + return + + + +/obj/structure/closet/secure_closet/engineering_electrical + name = "Electrical Supplies" + req_access = list(access_engine_equip) + icon_state = "secureengelec1" + icon_closed = "secureengelec" + icon_locked = "secureengelec1" + icon_opened = "toolclosetopen" + icon_broken = "secureengelecbroken" + icon_off = "secureengelecoff" + + + New() + ..() + sleep(2) + new /obj/item/weapon/storage/toolbox/electrical(src) + new /obj/item/weapon/storage/toolbox/electrical(src) + new /obj/item/weapon/storage/toolbox/electrical(src) + new /obj/item/weapon/rcl(src) + new /obj/item/weapon/circuitboard/power_control(src) + new /obj/item/weapon/circuitboard/power_control(src) + new /obj/item/weapon/circuitboard/power_control(src) + new /obj/item/clothing/gloves/yellow(src) + new /obj/item/clothing/gloves/yellow(src) + new /obj/item/device/multitool(src) + new /obj/item/device/multitool(src) + new /obj/item/device/multitool(src) + return + + + +/obj/structure/closet/secure_closet/engineering_welding + name = "Welding Supplies" + req_access = list(access_engine_equip) + icon_state = "secureengweld1" + icon_closed = "secureengweld" + icon_locked = "secureengweld1" + icon_opened = "toolclosetopen" + icon_broken = "secureengweldbroken" + icon_off = "secureengweldoff" + + + New() + ..() + sleep(2) + new /obj/item/clothing/head/welding(src) + new /obj/item/clothing/head/welding(src) + new /obj/item/clothing/head/welding(src) + new /obj/item/weapon/weldingtool/largetank(src) + new /obj/item/weapon/weldingtool/largetank(src) + new /obj/item/weapon/weldingtool/largetank(src) + return + + + +/obj/structure/closet/secure_closet/engineering_personal + name = "Engineer's Locker" + req_access = list(access_engine_equip) + icon_state = "secureeng1" + icon_closed = "secureeng" + icon_locked = "secureeng1" + icon_opened = "secureengopen" + icon_broken = "secureengbroken" + icon_off = "secureengoff" + + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/industrial(src) + else + new /obj/item/weapon/storage/backpack/satchel_eng(src) + new /obj/item/clothing/under/rank/engineer(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/weapon/storage/toolbox/mechanical(src) +// new /obj/item/weapon/cartridge/engineering(src) + new /obj/item/device/radio/headset/headset_eng(src) + new /obj/item/clothing/suit/storage/hazardvest(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/clothing/glasses/meson(src) + new /obj/item/taperoll/engineering(src) + new /obj/item/taperoll/engineering(src) + new /obj/item/device/gps/engineering(src) + return + +/obj/structure/closet/secure_closet/engineering_atmos + name = "Atmospheric Technician's Locker" + req_access = list(access_atmospherics) + icon_state = "secureatmos1" + icon_closed = "secureatmos" + icon_locked = "secureatmos1" + icon_opened = "secureatmosopen" + icon_broken = "secureatmosbroken" + icon_off = "secureatmosoff" + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack(src) + else + new /obj/item/weapon/storage/backpack/satchel_norm(src) + new /obj/item/clothing/under/rank/atmospheric_technician(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/weapon/storage/toolbox/mechanical(src) + new /obj/item/weapon/extinguisher/foam(src) + // new /obj/item/weapon/cartridge/engineering(src) + new /obj/item/device/radio/headset/headset_eng(src) + new /obj/item/clothing/suit/storage/hazardvest(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/taperoll/atmos(src) + new /obj/item/pipe_planner(src) + new /obj/item/weapon/wrench/socket(src) + new /obj/item/weapon/gun/projectile/flare(src) //yay for emergency lighting + new /obj/item/ammo_storage/box/flare(src) + new /obj/item/device/rcd/rpd(src) + new /obj/item/device/analyzer(src) + return + +/obj/structure/closet/secure_closet/engineering_mechanic + name = "Mechanic's Locker" + req_access = list(access_mechanic) + icon_state = "securemechni1" + icon_closed = "securemechni" + icon_locked = "securemechni1" + icon_opened = "securemechniopen" + icon_broken = "securemechnibroken" + icon_off = "securemechnioff" + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/industrial(src) + else + new /obj/item/weapon/storage/backpack/satchel_eng(src) + new /obj/item/clothing/under/rank/mechanic(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/weapon/storage/toolbox/mechanical(src) + //new /obj/item/device/component_exchanger(src) + new /obj/item/device/radio/headset/headset_engsci(src) + new /obj/item/clothing/suit/storage/hazardvest(src) + new /obj/item/device/device_analyser(src) + new /obj/item/weapon/soap/nanotrasen(src) + new /obj/item/clothing/gloves/black(src) + new /obj/item/device/assembly_frame(src) + new /obj/item/device/assembly_frame(src) + + if(prob(50)) + new /obj/item/clothing/head/welding(src) + else + new /obj/item/clothing/glasses/welding(src) + return + +/obj/structure/closet/secure_closet/engineering_general + name = "Engineering Locker" + req_access = list(access_engine_equip) + icon_state = "secureeng1" + icon_closed = "secureeng" + icon_locked = "secureeng1" + icon_opened = "secureengopen" + icon_broken = "secureengbroken" + icon_off = "secureengoff" + + +/obj/structure/closet/crate/secure/large/reinforced/shard + name = "Supermatter Shard Crate" + New() + ..() + sleep(2) + new /obj/machinery/power/supermatter/shard(src) + +/obj/structure/closet/crate/secure/large/reinforced/shard/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover,/obj/machinery/power/supermatter)) + return 1 + . = ..() + +/obj/structure/closet/crate/secure/large/reinforced/shard/can_close() + for(var/obj/machinery/power/supermatter/S in loc) + if(S.damage) //This is what I like to call predicting the metagame + return 0 return ..() \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm index c1e5511c078..f316e37b997 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm @@ -1,111 +1,111 @@ -/obj/structure/closet/secure_closet/freezer - -/obj/structure/closet/secure_closet/freezer/update_icon() - overlays.len = 0 - if(broken) - icon_state = icon_broken - else - if(!opened) - if(locked) - icon_state = icon_locked - else - icon_state = icon_closed - if(welded) - overlays += "welded" - else - icon_state = icon_opened - -/obj/structure/closet/secure_closet/freezer/ex_act(var/severity) - // IF INDIANA JONES CAN DO IT SO CAN YOU - - // Bomb in here? (using same search as space transits searching for nuke disk) - var/list/bombs = search_contents_for(/obj/item/device/transfer_valve) - if(!isemptylist(bombs)) // You're fucked. - ..(severity) - - return - -/obj/structure/closet/secure_closet/freezer/kitchen - name = "Kitchen Cabinet" - req_access = list(access_kitchen) - - New() - ..() - sleep(2) - for(var/i = 0, i < 3, i++) - new /obj/item/weapon/reagent_containers/food/drinks/flour(src) - new /obj/item/weapon/reagent_containers/food/condiment/sugar(src) - return - - -/obj/structure/closet/secure_closet/freezer/kitchen/mining - req_access = list() - - - -/obj/structure/closet/secure_closet/freezer/meat - name = "Meat Fridge" - icon_state = "fridge1" - icon_closed = "fridge" - icon_locked = "fridge1" - icon_opened = "fridgeopen" - icon_broken = "fridgebroken" - icon_off = "fridge1" - - - New() - ..() - sleep(2) - for(var/i = 0, i < 4, i++) - new /obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey(src) - return - - - -/obj/structure/closet/secure_closet/freezer/fridge - name = "Refrigerator" - icon_state = "fridge1" - icon_closed = "fridge" - icon_locked = "fridge1" - icon_opened = "fridgeopen" - icon_broken = "fridgebroken" - icon_off = "fridge1" - - - New() - ..() - sleep(2) - for(var/i = 0, i < 5, i++) - new /obj/item/weapon/reagent_containers/food/drinks/milk(src) - for(var/i = 0, i < 5, i++) - new /obj/item/weapon/reagent_containers/food/drinks/soymilk(src) - for(var/i = 0, i < 2, i++) - new /obj/item/weapon/storage/fancy/egg_box(src) - return - - - -/obj/structure/closet/secure_closet/freezer/money - name = "Freezer" - icon_state = "fridge1" - icon_closed = "fridge" - icon_locked = "fridge1" - icon_opened = "fridgeopen" - icon_broken = "fridgebroken" - icon_off = "fridge1" - req_access = list(access_heads_vault) - - - New() - ..() - sleep(2) - dispense_cash(6700,src) - return - - - - - - - - +/obj/structure/closet/secure_closet/freezer + +/obj/structure/closet/secure_closet/freezer/update_icon() + overlays.len = 0 + if(broken) + icon_state = icon_broken + else + if(!opened) + if(locked) + icon_state = icon_locked + else + icon_state = icon_closed + if(welded) + overlays += "welded" + else + icon_state = icon_opened + +/obj/structure/closet/secure_closet/freezer/ex_act(var/severity) + // IF INDIANA JONES CAN DO IT SO CAN YOU + + // Bomb in here? (using same search as space transits searching for nuke disk) + var/list/bombs = search_contents_for(/obj/item/device/transfer_valve) + if(!isemptylist(bombs)) // You're fucked. + ..(severity) + + return + +/obj/structure/closet/secure_closet/freezer/kitchen + name = "Kitchen Cabinet" + req_access = list(access_kitchen) + + New() + ..() + sleep(2) + for(var/i = 0, i < 3, i++) + new /obj/item/weapon/reagent_containers/food/drinks/flour(src) + new /obj/item/weapon/reagent_containers/food/condiment/sugar(src) + return + + +/obj/structure/closet/secure_closet/freezer/kitchen/mining + req_access = list() + + + +/obj/structure/closet/secure_closet/freezer/meat + name = "Meat Fridge" + icon_state = "fridge1" + icon_closed = "fridge" + icon_locked = "fridge1" + icon_opened = "fridgeopen" + icon_broken = "fridgebroken" + icon_off = "fridge1" + + + New() + ..() + sleep(2) + for(var/i = 0, i < 4, i++) + new /obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey(src) + return + + + +/obj/structure/closet/secure_closet/freezer/fridge + name = "Refrigerator" + icon_state = "fridge1" + icon_closed = "fridge" + icon_locked = "fridge1" + icon_opened = "fridgeopen" + icon_broken = "fridgebroken" + icon_off = "fridge1" + + + New() + ..() + sleep(2) + for(var/i = 0, i < 5, i++) + new /obj/item/weapon/reagent_containers/food/drinks/milk(src) + for(var/i = 0, i < 5, i++) + new /obj/item/weapon/reagent_containers/food/drinks/soymilk(src) + for(var/i = 0, i < 2, i++) + new /obj/item/weapon/storage/fancy/egg_box(src) + return + + + +/obj/structure/closet/secure_closet/freezer/money + name = "Freezer" + icon_state = "fridge1" + icon_closed = "fridge" + icon_locked = "fridge1" + icon_opened = "fridgeopen" + icon_broken = "fridgebroken" + icon_off = "fridge1" + req_access = list(access_heads_vault) + + + New() + ..() + sleep(2) + dispense_cash(6700,src) + return + + + + + + + + diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 819310f83b0..4fc9248c94d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -1,230 +1,230 @@ -/obj/structure/closet/secure_closet/medical1 - name = "Medicine Closet" - desc = "Filled with medical junk." - icon_state = "medical1" - icon_closed = "medical" - icon_locked = "medical1" - icon_opened = "medicalopen" - icon_broken = "medicalbroken" - icon_off = "medicaloff" - req_access = list(access_medical) - - - New() - ..() - sleep(2) - new /obj/item/weapon/storage/box/syringes(src) - new /obj/item/weapon/reagent_containers/dropper(src) - new /obj/item/weapon/reagent_containers/dropper(src) - new /obj/item/weapon/reagent_containers/glass/beaker(src) - new /obj/item/weapon/reagent_containers/glass/beaker(src) - new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) - new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) - new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) - new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) - return - - - -/obj/structure/closet/secure_closet/medical2 - name = "Anesthetic" - desc = "Used to knock people out." - icon_state = "medical1" - icon_closed = "medical" - icon_locked = "medical1" - icon_opened = "medicalopen" - icon_broken = "medicalbroken" - icon_off = "medicaloff" - req_access = list(access_surgery) - - - New() - ..() - sleep(2) - new /obj/item/weapon/tank/anesthetic(src) - new /obj/item/weapon/tank/anesthetic(src) - new /obj/item/weapon/tank/anesthetic(src) - new /obj/item/clothing/mask/breath/medical(src) - new /obj/item/clothing/mask/breath/medical(src) - new /obj/item/clothing/mask/breath/medical(src) - return - - - -/obj/structure/closet/secure_closet/medical3 - name = "Medical Doctor's Locker" - req_access = list(access_surgery) - icon_state = "securemed1" - icon_closed = "securemed" - icon_locked = "securemed1" - icon_opened = "securemedopen" - icon_broken = "securemedbroken" - icon_off = "securemedoff" - - New() - ..() - sleep(2) - new /obj/item/clothing/monkeyclothes/doctor (src) - new /obj/item/clothing/monkeyclothes/doctor (src) - if(prob(50)) - new /obj/item/weapon/storage/backpack/medic(src) - else - new /obj/item/weapon/storage/backpack/satchel_med(src) - new /obj/item/clothing/under/rank/nursesuit (src) - new /obj/item/clothing/head/nursehat (src) - switch(pick("blue", "green", "purple")) - if ("blue") - new /obj/item/clothing/under/rank/medical/blue(src) - new /obj/item/clothing/head/surgery/blue(src) - if ("green") - new /obj/item/clothing/under/rank/medical/green(src) - new /obj/item/clothing/head/surgery/green(src) - if ("purple") - new /obj/item/clothing/under/rank/medical/purple(src) - new /obj/item/clothing/head/surgery/purple(src) - switch(pick("blue", "green", "purple")) - if ("blue") - new /obj/item/clothing/under/rank/medical/blue(src) - new /obj/item/clothing/head/surgery/blue(src) - if ("green") - new /obj/item/clothing/under/rank/medical/green(src) - new /obj/item/clothing/head/surgery/green(src) - if ("purple") - new /obj/item/clothing/under/rank/medical/purple(src) - new /obj/item/clothing/head/surgery/purple(src) - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/under/rank/nurse(src) - new /obj/item/clothing/under/rank/orderly(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/suit/storage/fr_jacket(src) - new /obj/item/clothing/shoes/white(src) -// new /obj/item/weapon/cartridge/medical(src) - new /obj/item/device/radio/headset/headset_med(src) - new /obj/item/weapon/storage/belt/medical(src) - return - - - -/obj/structure/closet/secure_closet/CMO - name = "Chief Medical Officer's Locker" - req_access = list(access_cmo) - icon_state = "cmosecure1" - icon_closed = "cmosecure" - icon_locked = "cmosecure1" - icon_opened = "cmosecureopen" - icon_broken = "cmosecurebroken" - icon_off = "cmosecureoff" - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/medic(src) - else - new /obj/item/weapon/storage/backpack/satchel_med(src) - new /obj/item/clothing/suit/bio_suit/cmo(src) - new /obj/item/clothing/head/bio_hood/cmo(src) - new /obj/item/clothing/shoes/white(src) - switch(pick("blue", "green", "purple")) - if ("blue") - new /obj/item/clothing/under/rank/medical/blue(src) - new /obj/item/clothing/head/surgery/blue(src) - if ("green") - new /obj/item/clothing/under/rank/medical/green(src) - new /obj/item/clothing/head/surgery/green(src) - if ("purple") - new /obj/item/clothing/under/rank/medical/purple(src) - new /obj/item/clothing/head/surgery/purple(src) - new /obj/item/clothing/under/rank/chief_medical_officer(src) - new /obj/item/clothing/suit/storage/labcoat/cmo(src) - new /obj/item/weapon/cartridge/cmo(src) - new /obj/item/clothing/gloves/latex(src) - new /obj/item/clothing/shoes/brown (src) - new /obj/item/device/radio/headset/heads/cmo(src) - new /obj/item/weapon/storage/belt/medical(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/hypospray(src) - return - - - -/obj/structure/closet/secure_closet/animal - name = "Animal Control" - req_access = list(access_surgery) - - - New() - ..() - sleep(2) - new /obj/item/device/assembly/signaler(src) - new /obj/item/device/radio/electropack(src) - new /obj/item/device/radio/electropack(src) - new /obj/item/device/radio/electropack(src) - return - - - -/obj/structure/closet/secure_closet/chemical - name = "Chemical Closet" - desc = "Store dangerous chemicals in here." - icon_state = "medical1" - icon_closed = "medical" - icon_locked = "medical1" - icon_opened = "medicalopen" - icon_broken = "medicalbroken" - icon_off = "medicaloff" - req_access = list(access_chemistry) - - - New() - ..() - sleep(2) - new /obj/item/weapon/storage/box/pillbottles(src) - new /obj/item/weapon/storage/box/pillbottles(src) - return - -/obj/structure/closet/secure_closet/medical_wall - name = "First Aid Closet" - desc = "It's a secure wall-mounted storage unit for first aid supplies." - icon_state = "medical_wall_locked" - icon_closed = "medical_wall_unlocked" - icon_locked = "medical_wall_locked" - icon_opened = "medical_wall_open" - icon_broken = "medical_wall_spark" - icon_off = "medical_wall_off" - anchored = 1 - density = 0 - wall_mounted = 1 - req_access = list(access_medical) - -/obj/structure/closet/secure_closet/medical_wall/update_icon() - if(broken) - icon_state = icon_broken - else - if(!opened) - if(locked) - icon_state = icon_locked - else - icon_state = icon_closed - else - icon_state = icon_opened - -/obj/structure/closet/secure_closet/paramedic - name = "Paramedic EVA gear" - desc = "A locker with a Paramedic EVA suit." - icon_state = "medical1" - icon_closed = "medical" - icon_locked = "medical1" - icon_opened = "medicalopen" - icon_broken = "medicalbroken" - icon_off = "medicaloff" - req_access = list(access_paramedic) - - - New() - ..() - sleep(2) - new /obj/item/clothing/suit/space/paramedic(src) - new /obj/item/clothing/head/helmet/space/paramedic(src) - new /obj/item/clothing/shoes/magboots(src) - return +/obj/structure/closet/secure_closet/medical1 + name = "Medicine Closet" + desc = "Filled with medical junk." + icon_state = "medical1" + icon_closed = "medical" + icon_locked = "medical1" + icon_opened = "medicalopen" + icon_broken = "medicalbroken" + icon_off = "medicaloff" + req_access = list(access_medical) + + + New() + ..() + sleep(2) + new /obj/item/weapon/storage/box/syringes(src) + new /obj/item/weapon/reagent_containers/dropper(src) + new /obj/item/weapon/reagent_containers/dropper(src) + new /obj/item/weapon/reagent_containers/glass/beaker(src) + new /obj/item/weapon/reagent_containers/glass/beaker(src) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) + return + + + +/obj/structure/closet/secure_closet/medical2 + name = "Anesthetic" + desc = "Used to knock people out." + icon_state = "medical1" + icon_closed = "medical" + icon_locked = "medical1" + icon_opened = "medicalopen" + icon_broken = "medicalbroken" + icon_off = "medicaloff" + req_access = list(access_surgery) + + + New() + ..() + sleep(2) + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/clothing/mask/breath/medical(src) + new /obj/item/clothing/mask/breath/medical(src) + new /obj/item/clothing/mask/breath/medical(src) + return + + + +/obj/structure/closet/secure_closet/medical3 + name = "Medical Doctor's Locker" + req_access = list(access_surgery) + icon_state = "securemed1" + icon_closed = "securemed" + icon_locked = "securemed1" + icon_opened = "securemedopen" + icon_broken = "securemedbroken" + icon_off = "securemedoff" + + New() + ..() + sleep(2) + new /obj/item/clothing/monkeyclothes/doctor (src) + new /obj/item/clothing/monkeyclothes/doctor (src) + if(prob(50)) + new /obj/item/weapon/storage/backpack/medic(src) + else + new /obj/item/weapon/storage/backpack/satchel_med(src) + new /obj/item/clothing/under/rank/nursesuit (src) + new /obj/item/clothing/head/nursehat (src) + switch(pick("blue", "green", "purple")) + if ("blue") + new /obj/item/clothing/under/rank/medical/blue(src) + new /obj/item/clothing/head/surgery/blue(src) + if ("green") + new /obj/item/clothing/under/rank/medical/green(src) + new /obj/item/clothing/head/surgery/green(src) + if ("purple") + new /obj/item/clothing/under/rank/medical/purple(src) + new /obj/item/clothing/head/surgery/purple(src) + switch(pick("blue", "green", "purple")) + if ("blue") + new /obj/item/clothing/under/rank/medical/blue(src) + new /obj/item/clothing/head/surgery/blue(src) + if ("green") + new /obj/item/clothing/under/rank/medical/green(src) + new /obj/item/clothing/head/surgery/green(src) + if ("purple") + new /obj/item/clothing/under/rank/medical/purple(src) + new /obj/item/clothing/head/surgery/purple(src) + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/under/rank/nurse(src) + new /obj/item/clothing/under/rank/orderly(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/suit/storage/fr_jacket(src) + new /obj/item/clothing/shoes/white(src) +// new /obj/item/weapon/cartridge/medical(src) + new /obj/item/device/radio/headset/headset_med(src) + new /obj/item/weapon/storage/belt/medical(src) + return + + + +/obj/structure/closet/secure_closet/CMO + name = "Chief Medical Officer's Locker" + req_access = list(access_cmo) + icon_state = "cmosecure1" + icon_closed = "cmosecure" + icon_locked = "cmosecure1" + icon_opened = "cmosecureopen" + icon_broken = "cmosecurebroken" + icon_off = "cmosecureoff" + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/medic(src) + else + new /obj/item/weapon/storage/backpack/satchel_med(src) + new /obj/item/clothing/suit/bio_suit/cmo(src) + new /obj/item/clothing/head/bio_hood/cmo(src) + new /obj/item/clothing/shoes/white(src) + switch(pick("blue", "green", "purple")) + if ("blue") + new /obj/item/clothing/under/rank/medical/blue(src) + new /obj/item/clothing/head/surgery/blue(src) + if ("green") + new /obj/item/clothing/under/rank/medical/green(src) + new /obj/item/clothing/head/surgery/green(src) + if ("purple") + new /obj/item/clothing/under/rank/medical/purple(src) + new /obj/item/clothing/head/surgery/purple(src) + new /obj/item/clothing/under/rank/chief_medical_officer(src) + new /obj/item/clothing/suit/storage/labcoat/cmo(src) + new /obj/item/weapon/cartridge/cmo(src) + new /obj/item/clothing/gloves/latex(src) + new /obj/item/clothing/shoes/brown (src) + new /obj/item/device/radio/headset/heads/cmo(src) + new /obj/item/weapon/storage/belt/medical(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/reagent_containers/hypospray(src) + return + + + +/obj/structure/closet/secure_closet/animal + name = "Animal Control" + req_access = list(access_surgery) + + + New() + ..() + sleep(2) + new /obj/item/device/assembly/signaler(src) + new /obj/item/device/radio/electropack(src) + new /obj/item/device/radio/electropack(src) + new /obj/item/device/radio/electropack(src) + return + + + +/obj/structure/closet/secure_closet/chemical + name = "Chemical Closet" + desc = "Store dangerous chemicals in here." + icon_state = "medical1" + icon_closed = "medical" + icon_locked = "medical1" + icon_opened = "medicalopen" + icon_broken = "medicalbroken" + icon_off = "medicaloff" + req_access = list(access_chemistry) + + + New() + ..() + sleep(2) + new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/weapon/storage/box/pillbottles(src) + return + +/obj/structure/closet/secure_closet/medical_wall + name = "First Aid Closet" + desc = "It's a secure wall-mounted storage unit for first aid supplies." + icon_state = "medical_wall_locked" + icon_closed = "medical_wall_unlocked" + icon_locked = "medical_wall_locked" + icon_opened = "medical_wall_open" + icon_broken = "medical_wall_spark" + icon_off = "medical_wall_off" + anchored = 1 + density = 0 + wall_mounted = 1 + req_access = list(access_medical) + +/obj/structure/closet/secure_closet/medical_wall/update_icon() + if(broken) + icon_state = icon_broken + else + if(!opened) + if(locked) + icon_state = icon_locked + else + icon_state = icon_closed + else + icon_state = icon_opened + +/obj/structure/closet/secure_closet/paramedic + name = "Paramedic EVA gear" + desc = "A locker with a Paramedic EVA suit." + icon_state = "medical1" + icon_closed = "medical" + icon_locked = "medical1" + icon_opened = "medicalopen" + icon_broken = "medicalbroken" + icon_off = "medicaloff" + req_access = list(access_paramedic) + + + New() + ..() + sleep(2) + new /obj/item/clothing/suit/space/paramedic(src) + new /obj/item/clothing/head/helmet/space/paramedic(src) + new /obj/item/clothing/shoes/magboots(src) + return 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 6277eea6a30..c906ea78852 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -1,84 +1,84 @@ -/obj/structure/closet/secure_closet/personal - desc = "It's a secure locker for personell. The first card swiped gains control." - name = "personal closet" - req_access = list(access_all_personal_lockers) - var/registered_name = null - -/obj/structure/closet/secure_closet/personal/New() - ..() - spawn(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack(src) - else - new /obj/item/weapon/storage/backpack/satchel_norm(src) - new /obj/item/device/radio/headset( src ) - return - - -/obj/structure/closet/secure_closet/personal/patient - name = "patient's closet" - -/obj/structure/closet/secure_closet/personal/patient/New() - ..() - spawn(4) - contents = list() - new /obj/item/clothing/under/color/white( src ) - new /obj/item/clothing/shoes/white( src ) - return - - - -/obj/structure/closet/secure_closet/personal/cabinet - icon_state = "cabinetdetective_locked" - icon_closed = "cabinetdetective" - icon_locked = "cabinetdetective_locked" - icon_opened = "cabinetdetective_open" - icon_broken = "cabinetdetective_broken" - icon_off = "cabinetdetective_broken" - -/obj/structure/closet/secure_closet/personal/cabinet/update_icon() - if(broken) - icon_state = icon_broken - else - if(!opened) - if(locked) - icon_state = icon_locked - else - icon_state = icon_closed - else - icon_state = icon_opened - -/obj/structure/closet/secure_closet/personal/cabinet/New() - ..() - spawn(4) - contents = list() - new /obj/item/weapon/storage/backpack/satchel/withwallet( src ) - new /obj/item/device/radio/headset( src ) - return - -/obj/structure/closet/secure_closet/personal/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/id)) - if(src.broken) +/obj/structure/closet/secure_closet/personal + desc = "It's a secure locker for personell. The first card swiped gains control." + name = "personal closet" + req_access = list(access_all_personal_lockers) + var/registered_name = null + +/obj/structure/closet/secure_closet/personal/New() + ..() + spawn(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack(src) + else + new /obj/item/weapon/storage/backpack/satchel_norm(src) + new /obj/item/device/radio/headset( src ) + return + + +/obj/structure/closet/secure_closet/personal/patient + name = "patient's closet" + +/obj/structure/closet/secure_closet/personal/patient/New() + ..() + spawn(4) + contents = list() + new /obj/item/clothing/under/color/white( src ) + new /obj/item/clothing/shoes/white( src ) + return + + + +/obj/structure/closet/secure_closet/personal/cabinet + icon_state = "cabinetdetective_locked" + icon_closed = "cabinetdetective" + icon_locked = "cabinetdetective_locked" + icon_opened = "cabinetdetective_open" + icon_broken = "cabinetdetective_broken" + icon_off = "cabinetdetective_broken" + +/obj/structure/closet/secure_closet/personal/cabinet/update_icon() + if(broken) + icon_state = icon_broken + else + if(!opened) + if(locked) + icon_state = icon_locked + else + icon_state = icon_closed + else + icon_state = icon_opened + +/obj/structure/closet/secure_closet/personal/cabinet/New() + ..() + spawn(4) + contents = list() + new /obj/item/weapon/storage/backpack/satchel/withwallet( src ) + new /obj/item/device/radio/headset( src ) + return + +/obj/structure/closet/secure_closet/personal/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/id)) + if(src.broken) to_chat(user, "It appears to be broken.") - return - var/obj/item/weapon/card/id/I = W - if(!I || !I.registered_name) return - togglelock(user, I.registered_name) - else - ..() //get the other stuff to do it - -/obj/structure/closet/secure_closet/personal/togglelock(mob/user as mob, var/given_name = "") - if(src.allowed(user) || !src.registered_name || (src.registered_name == given_name)) //they can open all lockers, or nobody owns this, or they own this locker - src.locked = !src.locked - for(var/mob/O in viewers(user, 3)) - if((O.client && !( O.blinded ))) + return + var/obj/item/weapon/card/id/I = W + if(!I || !I.registered_name) return + togglelock(user, I.registered_name) + else + ..() //get the other stuff to do it + +/obj/structure/closet/secure_closet/personal/togglelock(mob/user as mob, var/given_name = "") + if(src.allowed(user) || !src.registered_name || (src.registered_name == given_name)) //they can open all lockers, or nobody owns this, or they own this locker + src.locked = !src.locked + for(var/mob/O in viewers(user, 3)) + if((O.client && !( O.blinded ))) to_chat(O, "The locker has been [locked ? null : "un"]locked by [user].") - if(src.locked) - src.icon_state = src.icon_locked - else - src.icon_state = src.icon_closed - if(!src.registered_name && given_name) - src.registered_name = given_name - src.desc = "Owned by [given_name]." - else + if(src.locked) + src.icon_state = src.icon_locked + else + src.icon_state = src.icon_closed + if(!src.registered_name && given_name) + src.registered_name = given_name + src.desc = "Owned by [given_name]." + else to_chat(user, "Access Denied.") 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 1dc3ca6f58f..3e314b47f93 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -1,50 +1,50 @@ -/obj/structure/closet/secure_closet/scientist - name = "Scientist's Locker" - req_access = list(access_tox_storage) - icon_state = "secureres1" - icon_closed = "secureres" - icon_locked = "secureres1" - icon_opened = "secureresopen" - icon_broken = "secureresbroken" - icon_off = "secureresoff" - - New() - ..() - sleep(2) - new /obj/item/clothing/under/rank/scientist(src) - //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/device/radio/headset/headset_sci(src) - new /obj/item/weapon/tank/air(src) - new /obj/item/clothing/mask/gas(src) - return - - - -/obj/structure/closet/secure_closet/RD - name = "Research Director's Locker" - req_access = list(access_rd) - icon_state = "rdsecure1" - icon_closed = "rdsecure" - icon_locked = "rdsecure1" - icon_opened = "rdsecureopen" - icon_broken = "rdsecurebroken" - icon_off = "rdsecureoff" - - New() - ..() - sleep(2) - new /obj/item/clothing/suit/bio_suit/scientist(src) - new /obj/item/clothing/head/bio_hood/scientist(src) - new /obj/item/clothing/under/rank/research_director(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/weapon/cartridge/rd(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/gloves/latex(src) - new /obj/item/device/radio/headset/heads/rd(src) - new /obj/item/weapon/tank/air(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/device/flash(src) +/obj/structure/closet/secure_closet/scientist + name = "Scientist's Locker" + req_access = list(access_tox_storage) + icon_state = "secureres1" + icon_closed = "secureres" + icon_locked = "secureres1" + icon_opened = "secureresopen" + icon_broken = "secureresbroken" + icon_off = "secureresoff" + + New() + ..() + sleep(2) + new /obj/item/clothing/under/rank/scientist(src) + //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/device/radio/headset/headset_sci(src) + new /obj/item/weapon/tank/air(src) + new /obj/item/clothing/mask/gas(src) + return + + + +/obj/structure/closet/secure_closet/RD + name = "Research Director's Locker" + req_access = list(access_rd) + icon_state = "rdsecure1" + icon_closed = "rdsecure" + icon_locked = "rdsecure1" + icon_opened = "rdsecureopen" + icon_broken = "rdsecurebroken" + icon_off = "rdsecureoff" + + New() + ..() + sleep(2) + new /obj/item/clothing/suit/bio_suit/scientist(src) + new /obj/item/clothing/head/bio_hood/scientist(src) + new /obj/item/clothing/under/rank/research_director(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/weapon/cartridge/rd(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/gloves/latex(src) + new /obj/item/device/radio/headset/heads/rd(src) + new /obj/item/weapon/tank/air(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/device/flash(src) return \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index 54e352e123e..5a9c4a707ac 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -1,174 +1,174 @@ -/obj/structure/closet/secure_closet - name = "secure locker" - desc = "It's an immobile card-locked storage unit." - icon = 'icons/obj/closet.dmi' - icon_state = "secure1" - density = 1 - opened = 0 - large = 1 - locked = 1 - icon_closed = "secure" - var/icon_locked = "secure1" - icon_opened = "secureopen" - var/icon_broken = "securebroken" - var/icon_off = "secureoff" - wall_mounted = 0 //never solid (You can always pass over it) - health = 200 - -/obj/structure/closet/secure_closet/can_open() - if(!..()) - return 0 - if(src.locked) - return 0 - return 1 - -/obj/structure/closet/secure_closet/close() - ..() - if(broken) - icon_state = src.icon_off - return 1 - -/obj/structure/closet/secure_closet/emp_act(severity) - for(var/obj/O in src) - O.emp_act(severity) - if(!broken) - if(prob(50/severity)) - src.locked = !src.locked - src.update_icon() - if(prob(20/severity) && !opened) - if(!locked) - open() - else - src.req_access = list() - src.req_access += pick(get_all_accesses()) - ..() - -/obj/structure/closet/secure_closet/proc/togglelock(mob/user as mob) - if(src.allowed(user)) - src.locked = !src.locked - for(var/mob/O in viewers(user, 3)) - if((O.client && !( O.blinded ))) - to_chat(O, "The locker has been [locked ? null : "un"]locked by [user].") - if(src.locked) - src.icon_state = src.icon_locked - else - src.icon_state = src.icon_closed - else - to_chat(user, "Access Denied.") - -/obj/structure/closet/secure_closet/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(src.opened) - return ..() - else if(src.broken) - if(issolder(W)) - var/obj/item/weapon/solder/S = W - if(!S.remove_fuel(4,user)) - return - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - if(do_after(user, src,40)) - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - broken = 0 - to_chat(user, "You repair the electronics inside the locking mechanism!") - src.icon_state = src.icon_closed - else - to_chat(user, "The locker appears to be broken.") - return - else if(istype(W, /obj/item/weapon/card/emag) && !src.broken) - broken = 1 - locked = 0 - desc = "It appears to be broken." - icon_state = icon_off - flick(icon_broken, src) - for(var/mob/O in viewers(user, 3)) - O.show_message("The locker has been broken by [user] with an electromagnetic card!", 1, "You hear a faint electrical spark.", 2) - update_icon() - else - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!WT.remove_fuel(0,user)) - to_chat(user, "You need more welding fuel to complete this task.") - return - src.welded =! src.welded - src.update_icon() - for(var/mob/M in viewers(src)) - M.show_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", 1, "You hear welding.", 2) - else - togglelock(user) - -/obj/structure/closet/secure_closet/relaymove(mob/user as mob) - if(user.stat || !isturf(src.loc)) - return - - if(!(src.locked) && !(src.welded)) - for(var/obj/item/I in src) - I.loc = src.loc - for(var/mob/M in src) - M.loc = src.loc - if(M.client) - M.client.eye = M.client.mob - M.client.perspective = MOB_PERSPECTIVE - src.icon_state = src.icon_opened - src.opened = 1 - src.density = 0 - playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) - else - if(!can_open()) - to_chat(user, "It won't budge!") - else - to_chat(user, "The locker is locked!") - if(world.time > lastbang+5) - lastbang = world.time - for(var/mob/M in hearers(src, null)) - to_chat(M, "BANG, bang!") - return - -/obj/structure/closet/secure_closet/attack_hand(mob/user as mob) - if(!Adjacent(user)) - return - src.add_fingerprint(user) - - if(!src.toggle()) - return src.attackby(null, user) - -/obj/structure/closet/secure_closet/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/closet/secure_closet/verb/verb_togglelock() - set src in oview(1) // One square distance - set category = "Object" - set name = "Toggle Lock" - - if(!usr.canmove || usr.isUnconscious() || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain - return - - if(!Adjacent(usr) || usr.loc == src) - return - - if(src.broken) - return - - if (ishuman(usr)) - if (!opened) - togglelock(usr) - return 1 - else - to_chat(usr, "This mob type can't use this verb.") - -/obj/structure/closet/secure_closet/AltClick() - if(verb_togglelock()) - return - return ..() - -/obj/structure/closet/secure_closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) - overlays.len = 0 - if(!opened) - if(locked) - icon_state = icon_locked - else if(broken) - icon_state = icon_off - else - icon_state = icon_closed - if(welded) - overlays += "welded" - else - icon_state = icon_opened +/obj/structure/closet/secure_closet + name = "secure locker" + desc = "It's an immobile card-locked storage unit." + icon = 'icons/obj/closet.dmi' + icon_state = "secure1" + density = 1 + opened = 0 + large = 1 + locked = 1 + icon_closed = "secure" + var/icon_locked = "secure1" + icon_opened = "secureopen" + var/icon_broken = "securebroken" + var/icon_off = "secureoff" + wall_mounted = 0 //never solid (You can always pass over it) + health = 200 + +/obj/structure/closet/secure_closet/can_open() + if(!..()) + return 0 + if(src.locked) + return 0 + return 1 + +/obj/structure/closet/secure_closet/close() + ..() + if(broken) + icon_state = src.icon_off + return 1 + +/obj/structure/closet/secure_closet/emp_act(severity) + for(var/obj/O in src) + O.emp_act(severity) + if(!broken) + if(prob(50/severity)) + src.locked = !src.locked + src.update_icon() + if(prob(20/severity) && !opened) + if(!locked) + open() + else + src.req_access = list() + src.req_access += pick(get_all_accesses()) + ..() + +/obj/structure/closet/secure_closet/proc/togglelock(mob/user as mob) + if(src.allowed(user)) + src.locked = !src.locked + for(var/mob/O in viewers(user, 3)) + if((O.client && !( O.blinded ))) + to_chat(O, "The locker has been [locked ? null : "un"]locked by [user].") + if(src.locked) + src.icon_state = src.icon_locked + else + src.icon_state = src.icon_closed + else + to_chat(user, "Access Denied.") + +/obj/structure/closet/secure_closet/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(src.opened) + return ..() + else if(src.broken) + if(issolder(W)) + var/obj/item/weapon/solder/S = W + if(!S.remove_fuel(4,user)) + return + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + if(do_after(user, src,40)) + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + broken = 0 + to_chat(user, "You repair the electronics inside the locking mechanism!") + src.icon_state = src.icon_closed + else + to_chat(user, "The locker appears to be broken.") + return + else if(istype(W, /obj/item/weapon/card/emag) && !src.broken) + broken = 1 + locked = 0 + desc = "It appears to be broken." + icon_state = icon_off + flick(icon_broken, src) + for(var/mob/O in viewers(user, 3)) + O.show_message("The locker has been broken by [user] with an electromagnetic card!", 1, "You hear a faint electrical spark.", 2) + update_icon() + else + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.remove_fuel(0,user)) + to_chat(user, "You need more welding fuel to complete this task.") + return + src.welded =! src.welded + src.update_icon() + for(var/mob/M in viewers(src)) + M.show_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", 1, "You hear welding.", 2) + else + togglelock(user) + +/obj/structure/closet/secure_closet/relaymove(mob/user as mob) + if(user.stat || !isturf(src.loc)) + return + + if(!(src.locked) && !(src.welded)) + for(var/obj/item/I in src) + I.loc = src.loc + for(var/mob/M in src) + M.loc = src.loc + if(M.client) + M.client.eye = M.client.mob + M.client.perspective = MOB_PERSPECTIVE + src.icon_state = src.icon_opened + src.opened = 1 + src.density = 0 + playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) + else + if(!can_open()) + to_chat(user, "It won't budge!") + else + to_chat(user, "The locker is locked!") + if(world.time > lastbang+5) + lastbang = world.time + for(var/mob/M in hearers(src, null)) + to_chat(M, "BANG, bang!") + return + +/obj/structure/closet/secure_closet/attack_hand(mob/user as mob) + if(!Adjacent(user)) + return + src.add_fingerprint(user) + + if(!src.toggle()) + return src.attackby(null, user) + +/obj/structure/closet/secure_closet/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/closet/secure_closet/verb/verb_togglelock() + set src in oview(1) // One square distance + set category = "Object" + set name = "Toggle Lock" + + if(!usr.canmove || usr.isUnconscious() || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain + return + + if(!Adjacent(usr) || usr.loc == src) + return + + if(src.broken) + return + + if (ishuman(usr)) + if (!opened) + togglelock(usr) + return 1 + else + to_chat(usr, "This mob type can't use this verb.") + +/obj/structure/closet/secure_closet/AltClick() + if(verb_togglelock()) + return + return ..() + +/obj/structure/closet/secure_closet/update_icon()//Putting the welded stuff in updateicon() so it's easy to overwrite for special cases (Fridges, cabinets, and whatnot) + overlays.len = 0 + if(!opened) + if(locked) + icon_state = icon_locked + else if(broken) + icon_state = icon_off + else + icon_state = icon_closed + if(welded) + overlays += "welded" + else + icon_state = icon_opened diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 37b890db44f..c3e630e060c 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -1,348 +1,348 @@ -/obj/structure/closet/secure_closet/captains - name = "Captain's Locker" - req_access = list(access_captain) - icon_state = "capsecure1" - icon_closed = "capsecure" - icon_locked = "capsecure1" - icon_opened = "capsecureopen" - icon_broken = "capsecurebroken" - icon_off = "capsecureoff" - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/captain(src) - else - new /obj/item/weapon/storage/backpack/satchel_cap(src) - new /obj/item/clothing/suit/captunic(src) - new /obj/item/clothing/suit/storage/capjacket(src) - new /obj/item/clothing/head/helmet/cap(src) - new /obj/item/clothing/under/rank/captain(src) - new /obj/item/clothing/suit/armor/vest(src) - new /obj/item/weapon/cartridge/captain(src) - new /obj/item/clothing/head/helmet/swat(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/device/radio/headset/heads/captain(src) - new /obj/item/clothing/gloves/captain(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/clothing/suit/armor/captain(src) - new /obj/item/weapon/melee/telebaton(src) - new /obj/item/clothing/under/dress/dress_cap(src) - new /obj/item/device/gps/secure(src) - return - - - -/obj/structure/closet/secure_closet/hop - name = "Head of Personnel's Locker" - req_access = list(access_hop) - icon_state = "hopsecure1" - icon_closed = "hopsecure" - icon_locked = "hopsecure1" - icon_opened = "hopsecureopen" - icon_broken = "hopsecurebroken" - icon_off = "hopsecureoff" - - New() - ..() - sleep(2) - new /obj/item/clothing/glasses/sunglasses(src) - new /obj/item/clothing/suit/storage/Hop_Coat(src) - new /obj/item/clothing/head/helmet/hopcap(src) - new /obj/item/weapon/cartridge/hop(src) - new /obj/item/device/radio/headset/heads/hop(src) - new /obj/item/weapon/storage/box/ids(src) - new /obj/item/weapon/storage/box/ids(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/device/flash(src) - new /obj/item/device/gps/secure(src) - return - -/obj/structure/closet/secure_closet/hop2 - name = "Head of Personnel's Attire" - req_access = list(access_hop) - icon_state = "hopsecure1" - icon_closed = "hopsecure" - icon_locked = "hopsecure1" - icon_opened = "hopsecureopen" - icon_broken = "hopsecurebroken" - icon_off = "hopsecureoff" - - New() - ..() - sleep(2) - new /obj/item/clothing/under/rank/head_of_personnel(src) - new /obj/item/clothing/under/dress/dress_hop(src) - new /obj/item/clothing/under/dress/dress_hr(src) - new /obj/item/clothing/under/lawyer/female(src) - new /obj/item/clothing/under/lawyer/black(src) - new /obj/item/clothing/under/lawyer/red(src) - new /obj/item/clothing/under/lawyer/oldman(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/leather(src) - new /obj/item/clothing/shoes/white(src) - return - - - -/obj/structure/closet/secure_closet/hos - name = "Head of Security's Locker" - req_access = list(access_hos) - icon_state = "hossecure1" - icon_closed = "hossecure" - icon_locked = "hossecure1" - icon_opened = "hossecureopen" - icon_broken = "hossecurebroken" - icon_off = "hossecureoff" - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/security(src) - else - new /obj/item/weapon/storage/backpack/satchel_sec(src) - new /obj/item/clothing/head/helmet/HoS(src) - new /obj/item/clothing/suit/armor/vest(src) - new /obj/item/clothing/under/rank/head_of_security/jensen(src) - new /obj/item/clothing/suit/armor/hos/jensen(src) - new /obj/item/clothing/head/helmet/HoS/dermal(src) - new /obj/item/weapon/cartridge/hos(src) - new /obj/item/device/detective_scanner(src) - new /obj/item/device/radio/headset/heads/hos(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/weapon/shield/riot(src) - new /obj/item/weapon/storage/lockbox/loyalty(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/clothing/accessory/holster/waist(src) - new /obj/item/weapon/melee/telebaton(src) - new /obj/item/device/gps/secure(src) - return - - - -/obj/structure/closet/secure_closet/warden - name = "Warden's Locker" - req_access = list(access_armory) - icon_state = "wardensecure1" - icon_closed = "wardensecure" - icon_locked = "wardensecure1" - icon_opened = "wardensecureopen" - icon_broken = "wardensecurebroken" - icon_off = "wardensecureoff" - - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/security(src) - else - new /obj/item/weapon/storage/backpack/satchel_sec(src) - new /obj/item/clothing/suit/armor/vest/security(src) - new /obj/item/clothing/under/rank/warden(src) - new /obj/item/clothing/suit/armor/vest/warden(src) - new /obj/item/clothing/head/helmet/warden(src) -// new /obj/item/weapon/cartridge/security(src) - new /obj/item/device/radio/headset/headset_sec(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/taser(src) - new /obj/item/weapon/storage/box/bolas(src) - new /obj/item/weapon/batteringram(src) - new /obj/item/device/gps/secure(src) - return - - - -/obj/structure/closet/secure_closet/security - name = "Security Officer's Locker" - req_access = list(access_security) - icon_state = "sec1" - icon_closed = "sec" - icon_locked = "sec1" - icon_opened = "secopen" - icon_broken = "secbroken" - icon_off = "secoff" - - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/security(src) - else - new /obj/item/weapon/storage/backpack/satchel_sec(src) - new /obj/item/clothing/suit/armor/vest/security(src) - new /obj/item/clothing/head/helmet(src) -// new /obj/item/weapon/cartridge/security(src) - new /obj/item/device/radio/headset/headset_sec(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/grenade/flashbang(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/taser(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/taperoll/police(src) - new /obj/item/device/hailer(src) //wonder if vg would spam this - new /obj/item/clothing/gloves/black(src) - new /obj/item/device/gps/secure(src) - return - - -/obj/structure/closet/secure_closet/security/cargo - - New() - ..() - new /obj/item/clothing/accessory/armband/cargo(src) - new /obj/item/device/encryptionkey/headset_cargo(src) - return - -/obj/structure/closet/secure_closet/security/engine - - New() - ..() - new /obj/item/clothing/accessory/armband/engine(src) - new /obj/item/device/encryptionkey/headset_eng(src) - return - -/obj/structure/closet/secure_closet/security/science - - New() - ..() - new /obj/item/clothing/accessory/armband/science(src) - new /obj/item/device/encryptionkey/headset_sci(src) - return - -/obj/structure/closet/secure_closet/security/med - - New() - ..() - new /obj/item/clothing/accessory/armband/medgreen(src) - new /obj/item/device/encryptionkey/headset_med(src) - return - - -/obj/structure/closet/secure_closet/detective - name = "Detective's Cabinet" - req_access = list(access_forensics_lockers) - icon_state = "cabinetdetective_locked" - icon_closed = "cabinetdetective" - icon_locked = "cabinetdetective_locked" - icon_opened = "cabinetdetective_open" - icon_broken = "cabinetdetective_broken" - icon_off = "cabinetdetective_broken" - - New() - ..() - sleep(2) - new /obj/item/clothing/under/det(src) - new /obj/item/clothing/suit/storage/det_suit(src) - new /obj/item/clothing/suit/storage/forensics/blue(src) - new /obj/item/clothing/suit/storage/forensics/red(src) - new /obj/item/clothing/gloves/black(src) - new /obj/item/clothing/head/det_hat(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/weapon/storage/box/evidence(src) - new /obj/item/device/radio/headset/headset_sec(src) - new /obj/item/device/detective_scanner(src) - new /obj/item/clothing/suit/armor/det_suit(src) - new /obj/item/ammo_storage/speedloader/c38(src) - new /obj/item/ammo_storage/box/c38(src) - new /obj/item/ammo_storage/box/c38(src) - new /obj/item/weapon/gun/projectile/detective(src) - new /obj/item/clothing/accessory/holster/armpit(src) - new /obj/item/device/gps/secure(src) - return - -/obj/structure/closet/secure_closet/detective/update_icon() - if(broken) - icon_state = icon_broken - else - if(!opened) - if(locked) - icon_state = icon_locked - else - icon_state = icon_closed - else - icon_state = icon_opened - -/obj/structure/closet/secure_closet/injection - name = "Lethal Injections" - req_access = list(access_captain) - - - New() - ..() - sleep(2) - new /obj/item/weapon/reagent_containers/syringe/giant/chloral(src) - new /obj/item/weapon/reagent_containers/syringe/giant/chloral(src) - return - - - -/obj/structure/closet/secure_closet/brig - name = "Brig Locker" - req_access = list(access_brig) - anchored = 1 - var/id_tag = null - - New() - ..() - new /obj/item/clothing/under/color/prisoner(src) - new /obj/item/clothing/shoes/orange(src) - return - - - -/obj/structure/closet/secure_closet/courtroom - name = "Courtroom Locker" - req_access = list(access_court) - - New() - ..() - sleep(2) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/weapon/paper/Court(src) - new /obj/item/weapon/paper/Court(src) - new /obj/item/weapon/paper/Court(src) - new /obj/item/weapon/pen (src) - new /obj/item/clothing/suit/judgerobe(src) - new /obj/item/clothing/head/powdered_wig(src) - new /obj/item/weapon/storage/briefcase(src) - return - -/obj/structure/closet/secure_closet/wall - name = "wall locker" - req_access = list(access_security) - icon_state = "wall-locker1" - density = 1 - icon_closed = "wall-locker" - icon_locked = "wall-locker1" - icon_opened = "wall-lockeropen" - icon_broken = "wall-lockerbroken" - icon_off = "wall-lockeroff" - - //too small to put a man in - large = 0 - -/obj/structure/closet/secure_closet/wall/update_icon() - if(broken) - icon_state = icon_broken - else - if(!opened) - if(locked) - icon_state = icon_locked - else - icon_state = icon_closed - else - icon_state = icon_opened +/obj/structure/closet/secure_closet/captains + name = "Captain's Locker" + req_access = list(access_captain) + icon_state = "capsecure1" + icon_closed = "capsecure" + icon_locked = "capsecure1" + icon_opened = "capsecureopen" + icon_broken = "capsecurebroken" + icon_off = "capsecureoff" + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/captain(src) + else + new /obj/item/weapon/storage/backpack/satchel_cap(src) + new /obj/item/clothing/suit/captunic(src) + new /obj/item/clothing/suit/storage/capjacket(src) + new /obj/item/clothing/head/helmet/cap(src) + new /obj/item/clothing/under/rank/captain(src) + new /obj/item/clothing/suit/armor/vest(src) + new /obj/item/weapon/cartridge/captain(src) + new /obj/item/clothing/head/helmet/swat(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/device/radio/headset/heads/captain(src) + new /obj/item/clothing/gloves/captain(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/clothing/suit/armor/captain(src) + new /obj/item/weapon/melee/telebaton(src) + new /obj/item/clothing/under/dress/dress_cap(src) + new /obj/item/device/gps/secure(src) + return + + + +/obj/structure/closet/secure_closet/hop + name = "Head of Personnel's Locker" + req_access = list(access_hop) + icon_state = "hopsecure1" + icon_closed = "hopsecure" + icon_locked = "hopsecure1" + icon_opened = "hopsecureopen" + icon_broken = "hopsecurebroken" + icon_off = "hopsecureoff" + + New() + ..() + sleep(2) + new /obj/item/clothing/glasses/sunglasses(src) + new /obj/item/clothing/suit/storage/Hop_Coat(src) + new /obj/item/clothing/head/helmet/hopcap(src) + new /obj/item/weapon/cartridge/hop(src) + new /obj/item/device/radio/headset/heads/hop(src) + new /obj/item/weapon/storage/box/ids(src) + new /obj/item/weapon/storage/box/ids(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/device/flash(src) + new /obj/item/device/gps/secure(src) + return + +/obj/structure/closet/secure_closet/hop2 + name = "Head of Personnel's Attire" + req_access = list(access_hop) + icon_state = "hopsecure1" + icon_closed = "hopsecure" + icon_locked = "hopsecure1" + icon_opened = "hopsecureopen" + icon_broken = "hopsecurebroken" + icon_off = "hopsecureoff" + + New() + ..() + sleep(2) + new /obj/item/clothing/under/rank/head_of_personnel(src) + new /obj/item/clothing/under/dress/dress_hop(src) + new /obj/item/clothing/under/dress/dress_hr(src) + new /obj/item/clothing/under/lawyer/female(src) + new /obj/item/clothing/under/lawyer/black(src) + new /obj/item/clothing/under/lawyer/red(src) + new /obj/item/clothing/under/lawyer/oldman(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/leather(src) + new /obj/item/clothing/shoes/white(src) + return + + + +/obj/structure/closet/secure_closet/hos + name = "Head of Security's Locker" + req_access = list(access_hos) + icon_state = "hossecure1" + icon_closed = "hossecure" + icon_locked = "hossecure1" + icon_opened = "hossecureopen" + icon_broken = "hossecurebroken" + icon_off = "hossecureoff" + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/security(src) + else + new /obj/item/weapon/storage/backpack/satchel_sec(src) + new /obj/item/clothing/head/helmet/HoS(src) + new /obj/item/clothing/suit/armor/vest(src) + new /obj/item/clothing/under/rank/head_of_security/jensen(src) + new /obj/item/clothing/suit/armor/hos/jensen(src) + new /obj/item/clothing/head/helmet/HoS/dermal(src) + new /obj/item/weapon/cartridge/hos(src) + new /obj/item/device/detective_scanner(src) + new /obj/item/device/radio/headset/heads/hos(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/weapon/shield/riot(src) + new /obj/item/weapon/storage/lockbox/loyalty(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/clothing/accessory/holster/waist(src) + new /obj/item/weapon/melee/telebaton(src) + new /obj/item/device/gps/secure(src) + return + + + +/obj/structure/closet/secure_closet/warden + name = "Warden's Locker" + req_access = list(access_armory) + icon_state = "wardensecure1" + icon_closed = "wardensecure" + icon_locked = "wardensecure1" + icon_opened = "wardensecureopen" + icon_broken = "wardensecurebroken" + icon_off = "wardensecureoff" + + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/security(src) + else + new /obj/item/weapon/storage/backpack/satchel_sec(src) + new /obj/item/clothing/suit/armor/vest/security(src) + new /obj/item/clothing/under/rank/warden(src) + new /obj/item/clothing/suit/armor/vest/warden(src) + new /obj/item/clothing/head/helmet/warden(src) +// new /obj/item/weapon/cartridge/security(src) + new /obj/item/device/radio/headset/headset_sec(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/gun/energy/taser(src) + new /obj/item/weapon/storage/box/bolas(src) + new /obj/item/weapon/batteringram(src) + new /obj/item/device/gps/secure(src) + return + + + +/obj/structure/closet/secure_closet/security + name = "Security Officer's Locker" + req_access = list(access_security) + icon_state = "sec1" + icon_closed = "sec" + icon_locked = "sec1" + icon_opened = "secopen" + icon_broken = "secbroken" + icon_off = "secoff" + + New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/security(src) + else + new /obj/item/weapon/storage/backpack/satchel_sec(src) + new /obj/item/clothing/suit/armor/vest/security(src) + new /obj/item/clothing/head/helmet(src) +// new /obj/item/weapon/cartridge/security(src) + new /obj/item/device/radio/headset/headset_sec(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/grenade/flashbang(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/gun/energy/taser(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/taperoll/police(src) + new /obj/item/device/hailer(src) //wonder if vg would spam this + new /obj/item/clothing/gloves/black(src) + new /obj/item/device/gps/secure(src) + return + + +/obj/structure/closet/secure_closet/security/cargo + + New() + ..() + new /obj/item/clothing/accessory/armband/cargo(src) + new /obj/item/device/encryptionkey/headset_cargo(src) + return + +/obj/structure/closet/secure_closet/security/engine + + New() + ..() + new /obj/item/clothing/accessory/armband/engine(src) + new /obj/item/device/encryptionkey/headset_eng(src) + return + +/obj/structure/closet/secure_closet/security/science + + New() + ..() + new /obj/item/clothing/accessory/armband/science(src) + new /obj/item/device/encryptionkey/headset_sci(src) + return + +/obj/structure/closet/secure_closet/security/med + + New() + ..() + new /obj/item/clothing/accessory/armband/medgreen(src) + new /obj/item/device/encryptionkey/headset_med(src) + return + + +/obj/structure/closet/secure_closet/detective + name = "Detective's Cabinet" + req_access = list(access_forensics_lockers) + icon_state = "cabinetdetective_locked" + icon_closed = "cabinetdetective" + icon_locked = "cabinetdetective_locked" + icon_opened = "cabinetdetective_open" + icon_broken = "cabinetdetective_broken" + icon_off = "cabinetdetective_broken" + + New() + ..() + sleep(2) + new /obj/item/clothing/under/det(src) + new /obj/item/clothing/suit/storage/det_suit(src) + new /obj/item/clothing/suit/storage/forensics/blue(src) + new /obj/item/clothing/suit/storage/forensics/red(src) + new /obj/item/clothing/gloves/black(src) + new /obj/item/clothing/head/det_hat(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/weapon/storage/box/evidence(src) + new /obj/item/device/radio/headset/headset_sec(src) + new /obj/item/device/detective_scanner(src) + new /obj/item/clothing/suit/armor/det_suit(src) + new /obj/item/ammo_storage/speedloader/c38(src) + new /obj/item/ammo_storage/box/c38(src) + new /obj/item/ammo_storage/box/c38(src) + new /obj/item/weapon/gun/projectile/detective(src) + new /obj/item/clothing/accessory/holster/armpit(src) + new /obj/item/device/gps/secure(src) + return + +/obj/structure/closet/secure_closet/detective/update_icon() + if(broken) + icon_state = icon_broken + else + if(!opened) + if(locked) + icon_state = icon_locked + else + icon_state = icon_closed + else + icon_state = icon_opened + +/obj/structure/closet/secure_closet/injection + name = "Lethal Injections" + req_access = list(access_captain) + + + New() + ..() + sleep(2) + new /obj/item/weapon/reagent_containers/syringe/giant/chloral(src) + new /obj/item/weapon/reagent_containers/syringe/giant/chloral(src) + return + + + +/obj/structure/closet/secure_closet/brig + name = "Brig Locker" + req_access = list(access_brig) + anchored = 1 + var/id_tag = null + + New() + ..() + new /obj/item/clothing/under/color/prisoner(src) + new /obj/item/clothing/shoes/orange(src) + return + + + +/obj/structure/closet/secure_closet/courtroom + name = "Courtroom Locker" + req_access = list(access_court) + + New() + ..() + sleep(2) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/weapon/paper/Court(src) + new /obj/item/weapon/paper/Court(src) + new /obj/item/weapon/paper/Court(src) + new /obj/item/weapon/pen (src) + new /obj/item/clothing/suit/judgerobe(src) + new /obj/item/clothing/head/powdered_wig(src) + new /obj/item/weapon/storage/briefcase(src) + return + +/obj/structure/closet/secure_closet/wall + name = "wall locker" + req_access = list(access_security) + icon_state = "wall-locker1" + density = 1 + icon_closed = "wall-locker" + icon_locked = "wall-locker1" + icon_opened = "wall-lockeropen" + icon_broken = "wall-lockerbroken" + icon_off = "wall-lockeroff" + + //too small to put a man in + large = 0 + +/obj/structure/closet/secure_closet/wall/update_icon() + if(broken) + icon_state = icon_broken + else + if(!opened) + if(locked) + icon_state = icon_locked + else + icon_state = icon_closed + else + icon_state = icon_opened diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm index 4e9f1ee505b..da8f0e52cb0 100644 --- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm +++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm @@ -1,157 +1,157 @@ -/obj/structure/closet/syndicate - name = "armoury closet" - desc = "Why is this here?" - icon_state = "syndicate" - icon_closed = "syndicate" - icon_opened = "syndicateopen" - - -/obj/structure/closet/syndicate/personal - desc = "It's a storage unit for operative gear." - -/obj/structure/closet/syndicate/personal/New() - ..() - sleep(2) - new /obj/item/weapon/tank/jetpack/oxygen(src) - new /obj/item/clothing/mask/gas/syndicate(src) - new /obj/item/clothing/under/syndicate(src) - new /obj/item/clothing/head/helmet/space/rig/syndi(src) - new /obj/item/clothing/suit/space/rig/syndi(src) - new /obj/item/weapon/crowbar/red(src) - new /obj/item/weapon/cell/high(src) - new /obj/item/weapon/card/id/syndicate(src) - new /obj/item/device/multitool(src) - new /obj/item/weapon/shield/energy(src) - new /obj/item/clothing/shoes/magboots(src) - - -/obj/structure/closet/syndicate/nuclear - desc = "It's a storage unit for nuclear-operative gear." - -/obj/structure/closet/syndicate/nuclear/New() - ..() - sleep(2) - new /obj/item/ammo_storage/magazine/a12mm(src) - new /obj/item/ammo_storage/magazine/a12mm(src) - new /obj/item/ammo_storage/magazine/a12mm(src) - new /obj/item/ammo_storage/magazine/a12mm(src) - new /obj/item/ammo_storage/magazine/a12mm(src) - new /obj/item/weapon/storage/box/handcuffs(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/box/emps(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/weapon/pinpointer/nukeop(src) - new /obj/item/weapon/pinpointer/nukeop(src) - new /obj/item/weapon/pinpointer/nukeop(src) - new /obj/item/weapon/pinpointer/nukeop(src) - new /obj/item/weapon/pinpointer/nukeop(src) - new /obj/item/device/pda/syndicate(src) - var/obj/item/device/radio/uplink/U = new(src) - U.hidden_uplink.uses = 40 - return - -/obj/structure/closet/syndicate/resources/ - desc = "An old, dusty locker." - - New() - ..() - var/common_min = 30 //Minimum amount of minerals in the stack for common minerals - var/common_max = 50 //Maximum amount of HONK in the stack for HONK common minerals - var/rare_min = 5 //Minimum HONK of HONK in the stack HONK HONK rare minerals - var/rare_max = 20 //Maximum HONK HONK HONK in the HONK for HONK rare HONK - - - sleep(2) - - var/pickednum = rand(1, 50) - - //Sad trombone - if(pickednum == 1) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src) - P.name = "IOU" - P.info = "Sorry man, we needed the money so we sold your stash. It's ok, we'll double our money for sure this time!" - - //Metal (common ore) - if(pickednum >= 2) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = rand(common_min, common_max) - - //Glass (common ore) - if(pickednum >= 5) - new /obj/item/stack/sheet/glass/glass(src, rand(common_min, common_max)) - - //Plasteel (common ore) Because it has a million more uses then plasma - if(pickednum >= 10) - new /obj/item/stack/sheet/plasteel(src, rand(common_min, common_max)) - - //Plasma (rare ore) - if(pickednum >= 15) - new /obj/item/stack/sheet/mineral/plasma(src, rand(rare_min, rare_max)) - - //Silver (rare ore) - if(pickednum >= 20) - new /obj/item/stack/sheet/mineral/silver(src, rand(rare_min, rare_max)) - - //Gold (rare ore) - if(pickednum >= 30) - new /obj/item/stack/sheet/mineral/gold(src, rand(rare_min, rare_max)) - - //Uranium (rare ore) - if(pickednum >= 40) - new /obj/item/stack/sheet/mineral/uranium(src, rand(rare_min, rare_max)) - - //Diamond (rare HONK) - if(pickednum >= 45) - new /obj/item/stack/sheet/mineral/diamond(src, rand(rare_min, rare_max)) - - //Jetpack (You hit the jackpot!) - if(pickednum == 50) - new /obj/item/weapon/tank/jetpack/carbondioxide(src) - - return - -/obj/structure/closet/syndicate/resources/everything - desc = "It's an emergency storage closet for repairs." - - New() - var/list/resources = list( - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/glass/glass, - /obj/item/stack/sheet/mineral/gold, - /obj/item/stack/sheet/mineral/silver, - /obj/item/stack/sheet/mineral/plasma, - /obj/item/stack/sheet/mineral/uranium, - /obj/item/stack/sheet/mineral/diamond, - /obj/item/stack/sheet/mineral/clown, - /obj/item/stack/sheet/plasteel, - /obj/item/stack/rods - ) - - sleep(2) - - for(var/i = 0, i<2, i++) - for(var/res in resources) - var/obj/item/stack/R = new res(src) - R.amount = R.max_amount - - return - -/obj/structure/closet/vox_raiders - name = "vox armoury closet" - desc = "Polly wants a gun." - icon_state = "syndicate" - icon_closed = "syndicate" - icon_opened = "syndicateopen" - - New() - sleep(2) - new /obj/item/clothing/head/helmet/space/vox/pressure(src) - new /obj/item/clothing/mask/breath/vox(src) - new /obj/item/clothing/shoes/magboots/vox(src) - new /obj/item/clothing/suit/space/vox/pressure(src) - new /obj/item/clothing/under/vox/vox_casual(src) +/obj/structure/closet/syndicate + name = "armoury closet" + desc = "Why is this here?" + icon_state = "syndicate" + icon_closed = "syndicate" + icon_opened = "syndicateopen" + + +/obj/structure/closet/syndicate/personal + desc = "It's a storage unit for operative gear." + +/obj/structure/closet/syndicate/personal/New() + ..() + sleep(2) + new /obj/item/weapon/tank/jetpack/oxygen(src) + new /obj/item/clothing/mask/gas/syndicate(src) + new /obj/item/clothing/under/syndicate(src) + new /obj/item/clothing/head/helmet/space/rig/syndi(src) + new /obj/item/clothing/suit/space/rig/syndi(src) + new /obj/item/weapon/crowbar/red(src) + new /obj/item/weapon/cell/high(src) + new /obj/item/weapon/card/id/syndicate(src) + new /obj/item/device/multitool(src) + new /obj/item/weapon/shield/energy(src) + new /obj/item/clothing/shoes/magboots(src) + + +/obj/structure/closet/syndicate/nuclear + desc = "It's a storage unit for nuclear-operative gear." + +/obj/structure/closet/syndicate/nuclear/New() + ..() + sleep(2) + new /obj/item/ammo_storage/magazine/a12mm(src) + new /obj/item/ammo_storage/magazine/a12mm(src) + new /obj/item/ammo_storage/magazine/a12mm(src) + new /obj/item/ammo_storage/magazine/a12mm(src) + new /obj/item/ammo_storage/magazine/a12mm(src) + new /obj/item/weapon/storage/box/handcuffs(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/box/emps(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/weapon/pinpointer/nukeop(src) + new /obj/item/weapon/pinpointer/nukeop(src) + new /obj/item/weapon/pinpointer/nukeop(src) + new /obj/item/weapon/pinpointer/nukeop(src) + new /obj/item/weapon/pinpointer/nukeop(src) + new /obj/item/device/pda/syndicate(src) + var/obj/item/device/radio/uplink/U = new(src) + U.hidden_uplink.uses = 40 + return + +/obj/structure/closet/syndicate/resources/ + desc = "An old, dusty locker." + + New() + ..() + var/common_min = 30 //Minimum amount of minerals in the stack for common minerals + var/common_max = 50 //Maximum amount of HONK in the stack for HONK common minerals + var/rare_min = 5 //Minimum HONK of HONK in the stack HONK HONK rare minerals + var/rare_max = 20 //Maximum HONK HONK HONK in the HONK for HONK rare HONK + + + sleep(2) + + var/pickednum = rand(1, 50) + + //Sad trombone + if(pickednum == 1) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src) + P.name = "IOU" + P.info = "Sorry man, we needed the money so we sold your stash. It's ok, we'll double our money for sure this time!" + + //Metal (common ore) + if(pickednum >= 2) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = rand(common_min, common_max) + + //Glass (common ore) + if(pickednum >= 5) + new /obj/item/stack/sheet/glass/glass(src, rand(common_min, common_max)) + + //Plasteel (common ore) Because it has a million more uses then plasma + if(pickednum >= 10) + new /obj/item/stack/sheet/plasteel(src, rand(common_min, common_max)) + + //Plasma (rare ore) + if(pickednum >= 15) + new /obj/item/stack/sheet/mineral/plasma(src, rand(rare_min, rare_max)) + + //Silver (rare ore) + if(pickednum >= 20) + new /obj/item/stack/sheet/mineral/silver(src, rand(rare_min, rare_max)) + + //Gold (rare ore) + if(pickednum >= 30) + new /obj/item/stack/sheet/mineral/gold(src, rand(rare_min, rare_max)) + + //Uranium (rare ore) + if(pickednum >= 40) + new /obj/item/stack/sheet/mineral/uranium(src, rand(rare_min, rare_max)) + + //Diamond (rare HONK) + if(pickednum >= 45) + new /obj/item/stack/sheet/mineral/diamond(src, rand(rare_min, rare_max)) + + //Jetpack (You hit the jackpot!) + if(pickednum == 50) + new /obj/item/weapon/tank/jetpack/carbondioxide(src) + + return + +/obj/structure/closet/syndicate/resources/everything + desc = "It's an emergency storage closet for repairs." + + New() + var/list/resources = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/glass/glass, + /obj/item/stack/sheet/mineral/gold, + /obj/item/stack/sheet/mineral/silver, + /obj/item/stack/sheet/mineral/plasma, + /obj/item/stack/sheet/mineral/uranium, + /obj/item/stack/sheet/mineral/diamond, + /obj/item/stack/sheet/mineral/clown, + /obj/item/stack/sheet/plasteel, + /obj/item/stack/rods + ) + + sleep(2) + + for(var/i = 0, i<2, i++) + for(var/res in resources) + var/obj/item/stack/R = new res(src) + R.amount = R.max_amount + + return + +/obj/structure/closet/vox_raiders + name = "vox armoury closet" + desc = "Polly wants a gun." + icon_state = "syndicate" + icon_closed = "syndicate" + icon_opened = "syndicateopen" + + New() + sleep(2) + new /obj/item/clothing/head/helmet/space/vox/pressure(src) + new /obj/item/clothing/mask/breath/vox(src) + new /obj/item/clothing/shoes/magboots/vox(src) + new /obj/item/clothing/suit/space/vox/pressure(src) + new /obj/item/clothing/under/vox/vox_casual(src) new /obj/item/weapon/tank/jetpack/nitrogen(src) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index 9659f79ee92..08b19e004c1 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -1,237 +1,237 @@ -/* Utility Closets - * Contains: - * Emergency Closet - * Fire Closet - * Tool Closet - * Radiation Closet - * Bombsuit Closet - * Hydrant - * First Aid - */ - -/* - * Emergency Closet - */ -/obj/structure/closet/emcloset - name = "emergency closet" - desc = "It's a storage unit for emergency breathmasks and o2/n2 tanks." - icon_state = "emergency" - icon_closed = "emergency" - icon_opened = "emergencyopen" - -/obj/structure/closet/emcloset/New() - ..() - new /obj/item/weapon/tank/emergency_nitrogen(src) - switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 0, "delete" = 0))) - if ("small") - new /obj/item/weapon/tank/emergency_oxygen(src) - new /obj/item/weapon/tank/emergency_oxygen(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/storage/toolbox/emergency(src) - if ("aid") - new /obj/item/weapon/tank/emergency_oxygen(src) - new /obj/item/weapon/storage/toolbox/emergency(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/storage/firstaid/o2(src) - if ("tank") - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/storage/toolbox/emergency(src) - if ("both") - new /obj/item/weapon/storage/toolbox/emergency(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/storage/firstaid/o2(src) - if ("nothing") - return - if ("delete") - qdel(src) - return - /*if ("fire") - new /obj/structure/closet/firecloset(src.loc) - del(src) - return*/ - -/obj/structure/closet/emcloset/legacy/New() - ..() - new /obj/item/weapon/tank/oxygen(src) - new /obj/item/clothing/mask/gas(src) - - -/obj/structure/closet/emcloset/vox - name = "vox emergency closet" - desc = "It's full of life-saving equipment. Assuming, that is, that you breathe nitrogen." - -/obj/structure/closet/emcloset/vox/New() - AddToProfiler() - new /obj/item/weapon/tank/nitrogen(src) - new /obj/item/weapon/tank/nitrogen(src) - new /obj/item/clothing/mask/breath/vox(src) - new /obj/item/clothing/mask/breath/vox(src) - -/* - * Fire Closet - */ -/obj/structure/closet/firecloset - name = "fire-safety closet" - desc = "It's a storage unit for fire-fighting supplies." - icon_state = "firecloset" - icon_closed = "firecloset" - icon_opened = "fireclosetopen" - -/obj/structure/closet/firecloset/New() - ..() - - new /obj/item/clothing/suit/fire/firefighter(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/weapon/tank/oxygen/red(src) - new /obj/item/weapon/extinguisher(src) - new /obj/item/clothing/head/hardhat/red(src) - -/obj/structure/closet/firecloset/full/New() - ..() - new /obj/item/device/flashlight(src) - -/obj/structure/closet/firecloset/update_icon() - if(!opened) - icon_state = icon_closed - else - icon_state = icon_opened - - -/* - * Tool Closet - */ -/obj/structure/closet/toolcloset - name = "tool closet" - desc = "It's a storage unit for tools." - icon_state = "toolcloset" - icon_closed = "toolcloset" - icon_opened = "toolclosetopen" - -/obj/structure/closet/toolcloset/New() - . = ..() - if(prob(40)) - new /obj/item/clothing/suit/storage/hazardvest(src) - if(prob(70)) - new /obj/item/device/flashlight(src) - if(prob(70)) - new /obj/item/weapon/screwdriver(src) - if(prob(70)) - new /obj/item/weapon/wrench(src) - if(prob(70)) - new /obj/item/weapon/weldingtool(src) - if(prob(70)) - new /obj/item/weapon/crowbar(src) - if(prob(70)) - new /obj/item/weapon/wirecutters(src) - if(prob(70)) - new /obj/item/device/t_scanner(src) - if(prob(20)) - new /obj/item/weapon/storage/belt/utility(src) - if(prob(30)) - new /obj/item/stack/cable_coil/random(src) - if(prob(30)) - new /obj/item/stack/cable_coil/random(src) - if(prob(30)) - new /obj/item/stack/cable_coil/random(src) - if(prob(20)) - new /obj/item/device/multitool(src) - if(prob(5)) - new /obj/item/clothing/gloves/yellow(src) - if(prob(40)) - new /obj/item/clothing/head/hardhat(src) - - -/* - * Radiation Closet - */ -/obj/structure/closet/radiation - name = "radiation suit closet" - desc = "It's a storage unit for rad-protective suits." - icon_state = "radsuitcloset" - icon_opened = "toolclosetopen" - icon_closed = "radsuitcloset" - -/obj/structure/closet/radiation/New() - ..() - new /obj/item/clothing/suit/radiation(src) - new /obj/item/clothing/head/radiation(src) - -/* - * Bombsuit closet - */ -/obj/structure/closet/bombcloset - name = "\improper EOD closet" - desc = "It's a storage unit for explosion-protective suits." - icon_state = "bombsuit" - icon_closed = "bombsuit" - icon_opened = "bombsuitopen" - -/obj/structure/closet/bombcloset/New() - ..() - new /obj/item/clothing/suit/bomb_suit( src ) - new /obj/item/clothing/under/color/black( src ) - new /obj/item/clothing/shoes/black( src ) - new /obj/item/clothing/head/bomb_hood( src ) - - -/obj/structure/closet/bombclosetsecurity - name = "\improper EOD closet" - desc = "It's a storage unit for explosion-protective suits." - icon_state = "bombsuitsec" - icon_closed = "bombsuitsec" - icon_opened = "bombsuitsecopen" - -/obj/structure/closet/bombclosetsecurity/New() - ..() - new /obj/item/clothing/suit/bomb_suit/security( src ) - new /obj/item/clothing/under/rank/security( src ) - new /obj/item/clothing/shoes/brown( src ) - new /obj/item/clothing/head/bomb_hood/security( src ) - -/* - * Hydrant - */ -/obj/structure/closet/hydrant //wall mounted fire closet - name = "fire-safety closet" - desc = "It's a storage unit for fire-fighting supplies." - icon_state = "hydrant" - icon_closed = "hydrant" - icon_opened = "hydrant_open" - anchored = 1 - density = 0 - wall_mounted = 1 - pick_up_stuff = 0 // #367 - Picks up stuff at src.loc, rather than the offset location. - -/obj/structure/closet/hydrant/New() - ..() - - new /obj/item/clothing/suit/fire/firefighter(src) - new /obj/item/clothing/mask/gas(src) - new /obj/item/weapon/tank/oxygen/red(src) - new /obj/item/weapon/extinguisher(src) - new /obj/item/clothing/head/hardhat/red(src) - -/* - * First Aid - */ -/obj/structure/closet/medical_wall //wall mounted medical closet - name = "first-aid closet" - desc = "It's wall-mounted storage unit for first aid supplies." - icon_state = "medical_wall" - icon_closed = "medical_wall" - icon_opened = "medical_wall_open" - anchored = 1 - density = 0 - wall_mounted = 1 - pick_up_stuff = 0 // #367 - Picks up stuff at src.loc, rather than the offset location. - -/obj/structure/closet/medical_wall/update_icon() - if(!opened) - icon_state = icon_closed - else - icon_state = icon_opened +/* Utility Closets + * Contains: + * Emergency Closet + * Fire Closet + * Tool Closet + * Radiation Closet + * Bombsuit Closet + * Hydrant + * First Aid + */ + +/* + * Emergency Closet + */ +/obj/structure/closet/emcloset + name = "emergency closet" + desc = "It's a storage unit for emergency breathmasks and o2/n2 tanks." + icon_state = "emergency" + icon_closed = "emergency" + icon_opened = "emergencyopen" + +/obj/structure/closet/emcloset/New() + ..() + new /obj/item/weapon/tank/emergency_nitrogen(src) + switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 0, "delete" = 0))) + if ("small") + new /obj/item/weapon/tank/emergency_oxygen(src) + new /obj/item/weapon/tank/emergency_oxygen(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/storage/toolbox/emergency(src) + if ("aid") + new /obj/item/weapon/tank/emergency_oxygen(src) + new /obj/item/weapon/storage/toolbox/emergency(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/storage/firstaid/o2(src) + if ("tank") + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/storage/toolbox/emergency(src) + if ("both") + new /obj/item/weapon/storage/toolbox/emergency(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/storage/firstaid/o2(src) + if ("nothing") + return + if ("delete") + qdel(src) + return + /*if ("fire") + new /obj/structure/closet/firecloset(src.loc) + del(src) + return*/ + +/obj/structure/closet/emcloset/legacy/New() + ..() + new /obj/item/weapon/tank/oxygen(src) + new /obj/item/clothing/mask/gas(src) + + +/obj/structure/closet/emcloset/vox + name = "vox emergency closet" + desc = "It's full of life-saving equipment. Assuming, that is, that you breathe nitrogen." + +/obj/structure/closet/emcloset/vox/New() + AddToProfiler() + new /obj/item/weapon/tank/nitrogen(src) + new /obj/item/weapon/tank/nitrogen(src) + new /obj/item/clothing/mask/breath/vox(src) + new /obj/item/clothing/mask/breath/vox(src) + +/* + * Fire Closet + */ +/obj/structure/closet/firecloset + name = "fire-safety closet" + desc = "It's a storage unit for fire-fighting supplies." + icon_state = "firecloset" + icon_closed = "firecloset" + icon_opened = "fireclosetopen" + +/obj/structure/closet/firecloset/New() + ..() + + new /obj/item/clothing/suit/fire/firefighter(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/weapon/tank/oxygen/red(src) + new /obj/item/weapon/extinguisher(src) + new /obj/item/clothing/head/hardhat/red(src) + +/obj/structure/closet/firecloset/full/New() + ..() + new /obj/item/device/flashlight(src) + +/obj/structure/closet/firecloset/update_icon() + if(!opened) + icon_state = icon_closed + else + icon_state = icon_opened + + +/* + * Tool Closet + */ +/obj/structure/closet/toolcloset + name = "tool closet" + desc = "It's a storage unit for tools." + icon_state = "toolcloset" + icon_closed = "toolcloset" + icon_opened = "toolclosetopen" + +/obj/structure/closet/toolcloset/New() + . = ..() + if(prob(40)) + new /obj/item/clothing/suit/storage/hazardvest(src) + if(prob(70)) + new /obj/item/device/flashlight(src) + if(prob(70)) + new /obj/item/weapon/screwdriver(src) + if(prob(70)) + new /obj/item/weapon/wrench(src) + if(prob(70)) + new /obj/item/weapon/weldingtool(src) + if(prob(70)) + new /obj/item/weapon/crowbar(src) + if(prob(70)) + new /obj/item/weapon/wirecutters(src) + if(prob(70)) + new /obj/item/device/t_scanner(src) + if(prob(20)) + new /obj/item/weapon/storage/belt/utility(src) + if(prob(30)) + new /obj/item/stack/cable_coil/random(src) + if(prob(30)) + new /obj/item/stack/cable_coil/random(src) + if(prob(30)) + new /obj/item/stack/cable_coil/random(src) + if(prob(20)) + new /obj/item/device/multitool(src) + if(prob(5)) + new /obj/item/clothing/gloves/yellow(src) + if(prob(40)) + new /obj/item/clothing/head/hardhat(src) + + +/* + * Radiation Closet + */ +/obj/structure/closet/radiation + name = "radiation suit closet" + desc = "It's a storage unit for rad-protective suits." + icon_state = "radsuitcloset" + icon_opened = "toolclosetopen" + icon_closed = "radsuitcloset" + +/obj/structure/closet/radiation/New() + ..() + new /obj/item/clothing/suit/radiation(src) + new /obj/item/clothing/head/radiation(src) + +/* + * Bombsuit closet + */ +/obj/structure/closet/bombcloset + name = "\improper EOD closet" + desc = "It's a storage unit for explosion-protective suits." + icon_state = "bombsuit" + icon_closed = "bombsuit" + icon_opened = "bombsuitopen" + +/obj/structure/closet/bombcloset/New() + ..() + new /obj/item/clothing/suit/bomb_suit( src ) + new /obj/item/clothing/under/color/black( src ) + new /obj/item/clothing/shoes/black( src ) + new /obj/item/clothing/head/bomb_hood( src ) + + +/obj/structure/closet/bombclosetsecurity + name = "\improper EOD closet" + desc = "It's a storage unit for explosion-protective suits." + icon_state = "bombsuitsec" + icon_closed = "bombsuitsec" + icon_opened = "bombsuitsecopen" + +/obj/structure/closet/bombclosetsecurity/New() + ..() + new /obj/item/clothing/suit/bomb_suit/security( src ) + new /obj/item/clothing/under/rank/security( src ) + new /obj/item/clothing/shoes/brown( src ) + new /obj/item/clothing/head/bomb_hood/security( src ) + +/* + * Hydrant + */ +/obj/structure/closet/hydrant //wall mounted fire closet + name = "fire-safety closet" + desc = "It's a storage unit for fire-fighting supplies." + icon_state = "hydrant" + icon_closed = "hydrant" + icon_opened = "hydrant_open" + anchored = 1 + density = 0 + wall_mounted = 1 + pick_up_stuff = 0 // #367 - Picks up stuff at src.loc, rather than the offset location. + +/obj/structure/closet/hydrant/New() + ..() + + new /obj/item/clothing/suit/fire/firefighter(src) + new /obj/item/clothing/mask/gas(src) + new /obj/item/weapon/tank/oxygen/red(src) + new /obj/item/weapon/extinguisher(src) + new /obj/item/clothing/head/hardhat/red(src) + +/* + * First Aid + */ +/obj/structure/closet/medical_wall //wall mounted medical closet + name = "first-aid closet" + desc = "It's wall-mounted storage unit for first aid supplies." + icon_state = "medical_wall" + icon_closed = "medical_wall" + icon_opened = "medical_wall_open" + anchored = 1 + density = 0 + wall_mounted = 1 + pick_up_stuff = 0 // #367 - Picks up stuff at src.loc, rather than the offset location. + +/obj/structure/closet/medical_wall/update_icon() + if(!opened) + icon_state = icon_closed + else + icon_state = icon_opened diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 26ed7ebdfeb..0387a3628d4 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -1,410 +1,410 @@ -/obj/structure/closet/wardrobe - name = "wardrobe" - desc = "It's a storage unit for standard-issue Nanotrasen attire." - icon_state = "blue" - icon_closed = "blue" - -/obj/structure/closet/wardrobe/New() - . = ..() - new /obj/item/clothing/under/color/blue(src) - new /obj/item/clothing/under/color/blue(src) - new /obj/item/clothing/under/color/blue(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/clothing/shoes/brown(src) - -/obj/structure/closet/wardrobe/red - name = "security wardrobe" - icon_state = "red" - icon_closed = "red" - -/obj/structure/closet/wardrobe/red/New() - new /obj/item/clothing/under/rank/security(src) - new /obj/item/clothing/under/rank/security(src) - new /obj/item/clothing/under/rank/security(src) - new /obj/item/clothing/under/rank/security2(src) - new /obj/item/clothing/under/rank/security2(src) - new /obj/item/clothing/under/rank/security2(src) - new /obj/item/clothing/shoes/jackboots(src) - new /obj/item/clothing/shoes/jackboots(src) - new /obj/item/clothing/shoes/jackboots(src) - new /obj/item/clothing/head/soft/sec(src) - new /obj/item/clothing/head/soft/sec(src) - new /obj/item/clothing/head/soft/sec(src) - new /obj/item/clothing/head/beret/sec(src) - new /obj/item/clothing/head/beret/sec(src) - new /obj/item/clothing/head/beret/sec(src) - new /obj/item/clothing/mask/bandana/red(src) - new /obj/item/clothing/mask/bandana/red(src) - new /obj/item/clothing/mask/bandana/red(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/pink - name = "pink wardrobe" - icon_state = "pink" - icon_closed = "pink" - -/obj/structure/closet/wardrobe/pink/New() - new /obj/item/clothing/under/color/pink(src) - new /obj/item/clothing/under/color/pink(src) - new /obj/item/clothing/under/color/pink(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/clothing/shoes/brown(src) - new /obj/item/clothing/shoes/brown(src) - AddToProfiler() - return - -/obj/structure/closet/wardrobe/black - name = "black wardrobe" - icon_state = "black" - icon_closed = "black" - -/obj/structure/closet/wardrobe/black/New() - new /obj/item/clothing/under/color/black(src) - new /obj/item/clothing/under/color/black(src) - new /obj/item/clothing/under/color/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/head/that(src) - new /obj/item/clothing/head/that(src) - new /obj/item/clothing/head/that(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/chaplain_black - name = "chapel wardrobe" - desc = "It's a storage unit for Nanotrasen-approved religious attire." - icon_state = "black" - icon_closed = "black" - -/obj/structure/closet/wardrobe/chaplain_black/New() - new /obj/item/clothing/under/rank/chaplain(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/suit/nun(src) - new /obj/item/clothing/head/nun_hood(src) - new /obj/item/clothing/suit/chaplain_hoodie(src) - new /obj/item/clothing/head/chaplain_hood(src) - new /obj/item/clothing/suit/holidaypriest(src) - new /obj/item/clothing/under/wedding/bride_white(src) - new /obj/item/weapon/storage/backpack/cultpack (src) - new /obj/item/weapon/storage/fancy/candle_box(src) - new /obj/item/weapon/storage/fancy/candle_box(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/green - name = "green wardrobe" - icon_state = "green" - icon_closed = "green" - -/obj/structure/closet/wardrobe/green/New() - new /obj/item/clothing/under/color/green(src) - new /obj/item/clothing/under/color/green(src) - new /obj/item/clothing/under/color/green(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - AddToProfiler() - return - -/obj/structure/closet/wardrobe/xenos - name = "xenos wardrobe" - icon_state = "green" - icon_closed = "green" - -/obj/structure/closet/wardrobe/xenos/New() - new /obj/item/clothing/suit/unathi/mantle(src) - new /obj/item/clothing/suit/unathi/robe(src) - new /obj/item/clothing/shoes/sandal(src) - new /obj/item/clothing/shoes/sandal(src) - new /obj/item/clothing/shoes/sandal(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/orange - name = "prison wardrobe" - desc = "It's a storage unit for Nanotrasen-regulated prisoner attire." - icon_state = "orange" - icon_closed = "orange" - -/obj/structure/closet/wardrobe/orange/New() - new /obj/item/clothing/under/color/prisoner(src) - new /obj/item/clothing/under/color/prisoner(src) - new /obj/item/clothing/under/color/prisoner(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/orange(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/yellow - name = "yellow wardrobe" - icon_state = "wardrobe-y" - icon_closed = "wardrobe-y" - -/obj/structure/closet/wardrobe/yellow/New() - new /obj/item/clothing/under/color/yellow(src) - new /obj/item/clothing/under/color/yellow(src) - new /obj/item/clothing/under/color/yellow(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/orange(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/atmospherics_yellow - name = "atmospherics wardrobe" - icon_state = "yellow" - icon_closed = "yellow" - -/obj/structure/closet/wardrobe/atmospherics_yellow/New() - new /obj/item/clothing/under/rank/atmospheric_technician(src) - new /obj/item/clothing/under/rank/atmospheric_technician(src) - new /obj/item/clothing/under/rank/atmospheric_technician(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - AddToProfiler() - return - - - -/obj/structure/closet/wardrobe/engineering_yellow - name = "engineering wardrobe" - icon_state = "yellow" - icon_closed = "yellow" - -/obj/structure/closet/wardrobe/engineering_yellow/New() - new /obj/item/clothing/under/rank/engineer(src) - new /obj/item/clothing/under/rank/engineer(src) - new /obj/item/clothing/under/rank/engine_tech(src) - new /obj/item/clothing/under/rank/engine_tech(src) - new /obj/item/clothing/under/rank/maintenance_tech(src) - new /obj/item/clothing/under/rank/maintenance_tech(src) - new /obj/item/clothing/under/rank/electrician(src) - new /obj/item/clothing/under/rank/electrician(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/orange(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/white - name = "white wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/white/New() - new /obj/item/clothing/under/color/white(src) - new /obj/item/clothing/under/color/white(src) - new /obj/item/clothing/under/color/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/pjs - name = "Pajama wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/pjs/New() - new /obj/item/clothing/under/pj/red(src) - new /obj/item/clothing/under/pj/red(src) - new /obj/item/clothing/under/pj/blue(src) - new /obj/item/clothing/under/pj/blue(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/slippers(src) - new /obj/item/clothing/shoes/slippers(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/toxins_white - name = "toxins wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/toxins_white/New() - new /obj/item/clothing/under/rank/scientist(src) - new /obj/item/clothing/under/rank/scientist(src) - new /obj/item/clothing/under/rank/xenoarch(src) - new /obj/item/clothing/under/rank/plasmares(src) - new /obj/item/clothing/under/rank/xenobio(src) - new /obj/item/clothing/under/rank/anomalist(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/slippers - new /obj/item/clothing/shoes/slippers - new /obj/item/clothing/shoes/slippers - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/robotics_black - name = "robotics wardrobe" - icon_state = "black" - icon_closed = "black" - -/obj/structure/closet/wardrobe/robotics_black/New() - new /obj/item/clothing/under/rank/roboticist(src) - new /obj/item/clothing/under/rank/roboticist(src) - new /obj/item/clothing/under/rank/mechatronic(src) - new /obj/item/clothing/under/rank/mechatronic(src) - new /obj/item/clothing/under/rank/biomechanical(src) - new /obj/item/clothing/under/rank/biomechanical(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/gloves/black(src) - new /obj/item/clothing/gloves/black(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/chemistry_white - name = "chemistry wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/chemistry_white/New() - new /obj/item/clothing/under/rank/chemist(src) - new /obj/item/clothing/under/rank/chemist(src) - new /obj/item/clothing/under/rank/pharma(src) - new /obj/item/clothing/under/rank/pharma(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/suit/storage/labcoat/chemist(src) - new /obj/item/clothing/suit/storage/labcoat/chemist(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/oncology_white - name = "oncology wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/oncology_white/New() - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/suit/storage/labcoat/oncologist(src) - new /obj/item/clothing/suit/storage/labcoat/oncologist(src) - AddToProfiler() - return - -/obj/structure/closet/wardrobe/genetics_white - name = "genetics wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/genetics_white/New() - new /obj/item/clothing/under/rank/geneticist(src) - new /obj/item/clothing/under/rank/geneticist(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/suit/storage/labcoat/genetics(src) - new /obj/item/clothing/suit/storage/labcoat/genetics(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/virology_white - name = "virology wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/virology_white/New() - new /obj/item/clothing/under/rank/virologist(src) - new /obj/item/clothing/under/rank/virologist(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/suit/storage/labcoat/virologist(src) - new /obj/item/clothing/suit/storage/labcoat/virologist(src) - new /obj/item/clothing/mask/surgical(src) - new /obj/item/clothing/mask/surgical(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/medic_white - name = "medical wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/medic_white/New() - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/under/rank/medical/blue(src) - new /obj/item/clothing/under/rank/medical/green(src) - new /obj/item/clothing/under/rank/medical/purple(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/suit/storage/labcoat(src) - new /obj/item/clothing/mask/surgical(src) - new /obj/item/clothing/mask/surgical(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/grey - name = "grey wardrobe" - icon_state = "grey" - icon_closed = "grey" - -/obj/structure/closet/wardrobe/grey/New() - new /obj/item/clothing/under/color/grey(src) - new /obj/item/clothing/under/color/grey(src) - new /obj/item/clothing/under/color/grey(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/clothing/head/soft/grey(src) - new /obj/item/clothing/head/soft/grey(src) - new /obj/item/clothing/head/soft/grey(src) - AddToProfiler() - return - - -/obj/structure/closet/wardrobe/mixed - name = "mixed wardrobe" - icon_state = "mixed" - icon_closed = "mixed" - -/obj/structure/closet/wardrobe/mixed/New() - new /obj/item/clothing/under/color/blue(src) - new /obj/item/clothing/under/color/yellow(src) - new /obj/item/clothing/under/color/green(src) - new /obj/item/clothing/under/color/orange(src) - new /obj/item/clothing/under/color/pink(src) - new /obj/item/clothing/under/dress/plaid_blue(src) - new /obj/item/clothing/under/dress/plaid_red(src) - new /obj/item/clothing/under/dress/plaid_purple(src) - new /obj/item/clothing/shoes/blue(src) - new /obj/item/clothing/shoes/yellow(src) - new /obj/item/clothing/shoes/green(src) - new /obj/item/clothing/shoes/orange(src) - new /obj/item/clothing/shoes/purple(src) - new /obj/item/clothing/shoes/leather(src) - AddToProfiler() +/obj/structure/closet/wardrobe + name = "wardrobe" + desc = "It's a storage unit for standard-issue Nanotrasen attire." + icon_state = "blue" + icon_closed = "blue" + +/obj/structure/closet/wardrobe/New() + . = ..() + new /obj/item/clothing/under/color/blue(src) + new /obj/item/clothing/under/color/blue(src) + new /obj/item/clothing/under/color/blue(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/clothing/shoes/brown(src) + +/obj/structure/closet/wardrobe/red + name = "security wardrobe" + icon_state = "red" + icon_closed = "red" + +/obj/structure/closet/wardrobe/red/New() + new /obj/item/clothing/under/rank/security(src) + new /obj/item/clothing/under/rank/security(src) + new /obj/item/clothing/under/rank/security(src) + new /obj/item/clothing/under/rank/security2(src) + new /obj/item/clothing/under/rank/security2(src) + new /obj/item/clothing/under/rank/security2(src) + new /obj/item/clothing/shoes/jackboots(src) + new /obj/item/clothing/shoes/jackboots(src) + new /obj/item/clothing/shoes/jackboots(src) + new /obj/item/clothing/head/soft/sec(src) + new /obj/item/clothing/head/soft/sec(src) + new /obj/item/clothing/head/soft/sec(src) + new /obj/item/clothing/head/beret/sec(src) + new /obj/item/clothing/head/beret/sec(src) + new /obj/item/clothing/head/beret/sec(src) + new /obj/item/clothing/mask/bandana/red(src) + new /obj/item/clothing/mask/bandana/red(src) + new /obj/item/clothing/mask/bandana/red(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/pink + name = "pink wardrobe" + icon_state = "pink" + icon_closed = "pink" + +/obj/structure/closet/wardrobe/pink/New() + new /obj/item/clothing/under/color/pink(src) + new /obj/item/clothing/under/color/pink(src) + new /obj/item/clothing/under/color/pink(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/clothing/shoes/brown(src) + new /obj/item/clothing/shoes/brown(src) + AddToProfiler() + return + +/obj/structure/closet/wardrobe/black + name = "black wardrobe" + icon_state = "black" + icon_closed = "black" + +/obj/structure/closet/wardrobe/black/New() + new /obj/item/clothing/under/color/black(src) + new /obj/item/clothing/under/color/black(src) + new /obj/item/clothing/under/color/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/head/that(src) + new /obj/item/clothing/head/that(src) + new /obj/item/clothing/head/that(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/chaplain_black + name = "chapel wardrobe" + desc = "It's a storage unit for Nanotrasen-approved religious attire." + icon_state = "black" + icon_closed = "black" + +/obj/structure/closet/wardrobe/chaplain_black/New() + new /obj/item/clothing/under/rank/chaplain(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/suit/nun(src) + new /obj/item/clothing/head/nun_hood(src) + new /obj/item/clothing/suit/chaplain_hoodie(src) + new /obj/item/clothing/head/chaplain_hood(src) + new /obj/item/clothing/suit/holidaypriest(src) + new /obj/item/clothing/under/wedding/bride_white(src) + new /obj/item/weapon/storage/backpack/cultpack (src) + new /obj/item/weapon/storage/fancy/candle_box(src) + new /obj/item/weapon/storage/fancy/candle_box(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/green + name = "green wardrobe" + icon_state = "green" + icon_closed = "green" + +/obj/structure/closet/wardrobe/green/New() + new /obj/item/clothing/under/color/green(src) + new /obj/item/clothing/under/color/green(src) + new /obj/item/clothing/under/color/green(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + AddToProfiler() + return + +/obj/structure/closet/wardrobe/xenos + name = "xenos wardrobe" + icon_state = "green" + icon_closed = "green" + +/obj/structure/closet/wardrobe/xenos/New() + new /obj/item/clothing/suit/unathi/mantle(src) + new /obj/item/clothing/suit/unathi/robe(src) + new /obj/item/clothing/shoes/sandal(src) + new /obj/item/clothing/shoes/sandal(src) + new /obj/item/clothing/shoes/sandal(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/orange + name = "prison wardrobe" + desc = "It's a storage unit for Nanotrasen-regulated prisoner attire." + icon_state = "orange" + icon_closed = "orange" + +/obj/structure/closet/wardrobe/orange/New() + new /obj/item/clothing/under/color/prisoner(src) + new /obj/item/clothing/under/color/prisoner(src) + new /obj/item/clothing/under/color/prisoner(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/orange(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/yellow + name = "yellow wardrobe" + icon_state = "wardrobe-y" + icon_closed = "wardrobe-y" + +/obj/structure/closet/wardrobe/yellow/New() + new /obj/item/clothing/under/color/yellow(src) + new /obj/item/clothing/under/color/yellow(src) + new /obj/item/clothing/under/color/yellow(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/orange(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/atmospherics_yellow + name = "atmospherics wardrobe" + icon_state = "yellow" + icon_closed = "yellow" + +/obj/structure/closet/wardrobe/atmospherics_yellow/New() + new /obj/item/clothing/under/rank/atmospheric_technician(src) + new /obj/item/clothing/under/rank/atmospheric_technician(src) + new /obj/item/clothing/under/rank/atmospheric_technician(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + AddToProfiler() + return + + + +/obj/structure/closet/wardrobe/engineering_yellow + name = "engineering wardrobe" + icon_state = "yellow" + icon_closed = "yellow" + +/obj/structure/closet/wardrobe/engineering_yellow/New() + new /obj/item/clothing/under/rank/engineer(src) + new /obj/item/clothing/under/rank/engineer(src) + new /obj/item/clothing/under/rank/engine_tech(src) + new /obj/item/clothing/under/rank/engine_tech(src) + new /obj/item/clothing/under/rank/maintenance_tech(src) + new /obj/item/clothing/under/rank/maintenance_tech(src) + new /obj/item/clothing/under/rank/electrician(src) + new /obj/item/clothing/under/rank/electrician(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/orange(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/white + name = "white wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/white/New() + new /obj/item/clothing/under/color/white(src) + new /obj/item/clothing/under/color/white(src) + new /obj/item/clothing/under/color/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/pjs + name = "Pajama wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/pjs/New() + new /obj/item/clothing/under/pj/red(src) + new /obj/item/clothing/under/pj/red(src) + new /obj/item/clothing/under/pj/blue(src) + new /obj/item/clothing/under/pj/blue(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/slippers(src) + new /obj/item/clothing/shoes/slippers(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/toxins_white + name = "toxins wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/toxins_white/New() + new /obj/item/clothing/under/rank/scientist(src) + new /obj/item/clothing/under/rank/scientist(src) + new /obj/item/clothing/under/rank/xenoarch(src) + new /obj/item/clothing/under/rank/plasmares(src) + new /obj/item/clothing/under/rank/xenobio(src) + new /obj/item/clothing/under/rank/anomalist(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/slippers + new /obj/item/clothing/shoes/slippers + new /obj/item/clothing/shoes/slippers + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/robotics_black + name = "robotics wardrobe" + icon_state = "black" + icon_closed = "black" + +/obj/structure/closet/wardrobe/robotics_black/New() + new /obj/item/clothing/under/rank/roboticist(src) + new /obj/item/clothing/under/rank/roboticist(src) + new /obj/item/clothing/under/rank/mechatronic(src) + new /obj/item/clothing/under/rank/mechatronic(src) + new /obj/item/clothing/under/rank/biomechanical(src) + new /obj/item/clothing/under/rank/biomechanical(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/gloves/black(src) + new /obj/item/clothing/gloves/black(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/chemistry_white + name = "chemistry wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/chemistry_white/New() + new /obj/item/clothing/under/rank/chemist(src) + new /obj/item/clothing/under/rank/chemist(src) + new /obj/item/clothing/under/rank/pharma(src) + new /obj/item/clothing/under/rank/pharma(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/suit/storage/labcoat/chemist(src) + new /obj/item/clothing/suit/storage/labcoat/chemist(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/oncology_white + name = "oncology wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/oncology_white/New() + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/suit/storage/labcoat/oncologist(src) + new /obj/item/clothing/suit/storage/labcoat/oncologist(src) + AddToProfiler() + return + +/obj/structure/closet/wardrobe/genetics_white + name = "genetics wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/genetics_white/New() + new /obj/item/clothing/under/rank/geneticist(src) + new /obj/item/clothing/under/rank/geneticist(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/suit/storage/labcoat/genetics(src) + new /obj/item/clothing/suit/storage/labcoat/genetics(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/virology_white + name = "virology wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/virology_white/New() + new /obj/item/clothing/under/rank/virologist(src) + new /obj/item/clothing/under/rank/virologist(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/suit/storage/labcoat/virologist(src) + new /obj/item/clothing/suit/storage/labcoat/virologist(src) + new /obj/item/clothing/mask/surgical(src) + new /obj/item/clothing/mask/surgical(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/medic_white + name = "medical wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/medic_white/New() + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/under/rank/medical/blue(src) + new /obj/item/clothing/under/rank/medical/green(src) + new /obj/item/clothing/under/rank/medical/purple(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/suit/storage/labcoat(src) + new /obj/item/clothing/mask/surgical(src) + new /obj/item/clothing/mask/surgical(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/grey + name = "grey wardrobe" + icon_state = "grey" + icon_closed = "grey" + +/obj/structure/closet/wardrobe/grey/New() + new /obj/item/clothing/under/color/grey(src) + new /obj/item/clothing/under/color/grey(src) + new /obj/item/clothing/under/color/grey(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/clothing/head/soft/grey(src) + new /obj/item/clothing/head/soft/grey(src) + new /obj/item/clothing/head/soft/grey(src) + AddToProfiler() + return + + +/obj/structure/closet/wardrobe/mixed + name = "mixed wardrobe" + icon_state = "mixed" + icon_closed = "mixed" + +/obj/structure/closet/wardrobe/mixed/New() + new /obj/item/clothing/under/color/blue(src) + new /obj/item/clothing/under/color/yellow(src) + new /obj/item/clothing/under/color/green(src) + new /obj/item/clothing/under/color/orange(src) + new /obj/item/clothing/under/color/pink(src) + new /obj/item/clothing/under/dress/plaid_blue(src) + new /obj/item/clothing/under/dress/plaid_red(src) + new /obj/item/clothing/under/dress/plaid_purple(src) + new /obj/item/clothing/shoes/blue(src) + new /obj/item/clothing/shoes/yellow(src) + new /obj/item/clothing/shoes/green(src) + new /obj/item/clothing/shoes/orange(src) + new /obj/item/clothing/shoes/purple(src) + new /obj/item/clothing/shoes/leather(src) + AddToProfiler() return \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 91ed2b671e7..6c7327755e2 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -1,622 +1,622 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/structure/closet/crate - name = "crate" - desc = "A rectangular steel crate." - icon = 'icons/obj/storage.dmi' - icon_state = "crate" - density = 1 - icon_opened = "crateopen" - icon_closed = "crate" - req_access = null - opened = 0 - flags = FPRINT -// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? - var/rigged = 0 - var/sound_effect_open = 'sound/machines/click.ogg' - var/sound_effect_close = 'sound/machines/click.ogg' - -/obj/structure/closet/pcrate - name = "plastic crate" - desc = "A rectangular plastic crate." - icon = 'icons/obj/storage.dmi' - icon_state = "plasticcrate" - density = 1 - icon_opened = "plasticcrateopen" - icon_closed = "plasticcrate" - req_access = null - opened = 0 - flags = FPRINT -// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? - var/rigged = 0 - var/sound_effect_open = 'sound/machines/click.ogg' - var/sound_effect_close = 'sound/machines/click.ogg' - - starting_materials = list(MAT_PLASTIC = 10*CC_PER_SHEET_METAL) // Recipe calls for 10 sheets. - -/obj/structure/closet/crate/internals - desc = "A internals crate." - name = "Internals crate" - icon = 'icons/obj/storage.dmi' - icon_state = "o2crate" - density = 1 - icon_opened = "o2crateopen" - icon_closed = "o2crate" - -/obj/structure/closet/crate/trashcart - desc = "A heavy, metal trashcart with wheels." - name = "Trash Cart" - icon = 'icons/obj/storage.dmi' - icon_state = "trashcart" - density = 1 - icon_opened = "trashcartopen" - icon_closed = "trashcart" - -/obj/structure/closet/crate/chest - desc = "A heavy wooden chest. Probably filled with gold and treasure!" - name = "chest" - icon = 'icons/obj/storage.dmi' - icon_state = "chest" - density = 1 - icon_opened = "chestopen" - icon_closed = "chest" - -/*these aren't needed anymore -/obj/structure/closet/crate/hat - desc = "A crate filled with Valuable Collector's Hats!." - name = "Hat Crate" - icon = 'icons/obj/storage.dmi' - icon_state = "crate" - density = 1 - icon_opened = "crateopen" - icon_closed = "crate" - -/obj/structure/closet/crate/contraband - name = "Poster crate" - desc = "A random assortment of posters manufactured by providers NOT listed under Nanotrasen's whitelist." - icon = 'icons/obj/storage.dmi' - icon_state = "crate" - density = 1 - icon_opened = "crateopen" - icon_closed = "crate" -*/ - -/obj/structure/closet/crate/medical - desc = "A medical crate." - name = "Medical crate" - icon = 'icons/obj/storage.dmi' - icon_state = "medicalcrate" - density = 1 - icon_opened = "medicalcrateopen" - icon_closed = "medicalcrate" - -/obj/structure/closet/crate/rcd - desc = "A crate for the storage of the RCD." - name = "RCD crate" - icon = 'icons/obj/storage.dmi' - icon_state = "crate" - density = 1 - icon_opened = "crateopen" - icon_closed = "crate" - -/obj/structure/closet/crate/freezer - desc = "A freezer." - name = "Freezer" - icon = 'icons/obj/storage.dmi' - icon_state = "freezer" - density = 1 - icon_opened = "freezeropen" - icon_closed = "freezer" - var/target_temp = T0C - 40 - var/cooling_power = 40 - - return_air() - var/datum/gas_mixture/gas = (..()) - if(!gas) return null - var/datum/gas_mixture/newgas = new/datum/gas_mixture() - newgas.oxygen = gas.oxygen - newgas.carbon_dioxide = gas.carbon_dioxide - newgas.nitrogen = gas.nitrogen - newgas.toxins = gas.toxins - newgas.volume = gas.volume - newgas.temperature = gas.temperature - if(newgas.temperature <= target_temp) return - - if((newgas.temperature - cooling_power) > target_temp) - newgas.temperature -= cooling_power - else - newgas.temperature = target_temp - return newgas - - -/obj/structure/closet/crate/bin - desc = "A large bin." - name = "Large bin" - icon = 'icons/obj/storage.dmi' - icon_state = "largebin" - density = 1 - icon_opened = "largebinopen" - icon_closed = "largebin" - -/obj/structure/closet/crate/radiation - desc = "A crate with a radiation sign on it." - name = "Radioactive gear crate" - icon = 'icons/obj/storage.dmi' - icon_state = "radiation" - density = 1 - icon_opened = "radiationopen" - icon_closed = "radiation" - -/obj/structure/closet/crate/secure/weapon - desc = "A secure weapons crate." - name = "Weapons crate" - icon = 'icons/obj/storage.dmi' - icon_state = "weaponcrate" - density = 1 - icon_opened = "weaponcrateopen" - icon_closed = "weaponcrate" - -/obj/structure/closet/crate/secure/plasma - desc = "A secure plasma crate." - name = "Plasma crate" - icon = 'icons/obj/storage.dmi' - icon_state = "plasmacrate" - density = 1 - icon_opened = "plasmacrateopen" - icon_closed = "plasmacrate" - -/obj/structure/closet/crate/secure/gear - desc = "A secure gear crate." - name = "Gear crate" - icon = 'icons/obj/storage.dmi' - icon_state = "secgearcrate" - density = 1 - icon_opened = "secgearcrateopen" - icon_closed = "secgearcrate" - -/obj/structure/closet/crate/secure/hydrosec - desc = "A crate with a lock on it, painted in the scheme of the station's botanists." - name = "secure hydroponics crate" - icon = 'icons/obj/storage.dmi' - icon_state = "hydrosecurecrate" - density = 1 - icon_opened = "hydrosecurecrateopen" - icon_closed = "hydrosecurecrate" - -/obj/structure/closet/crate/secure/bin - desc = "A secure bin." - name = "Secure bin" - icon_state = "largebins" - icon_opened = "largebinsopen" - icon_closed = "largebins" - redlight = "largebinr" - greenlight = "largebing" - sparks = "largebinsparks" - emag = "largebinemag" - -/obj/structure/closet/crate/secure/large - name = "large crate" - desc = "A hefty metal crate with an electronic locking system." - icon = 'icons/obj/storage.dmi' - icon_state = "largemetal" - icon_opened = "largemetalopen" - icon_closed = "largemetal" - redlight = "largemetalr" - greenlight = "largemetalg" - -/obj/structure/closet/crate/secure/large/close() - //we can hold up to one large item - var/found = 0 - for(var/obj/structure/S in src.loc) - if(S == src) - continue - if(!S.anchored) - found = 1 - S.loc = src - break - if(!found) - for(var/obj/machinery/M in src.loc) - if(!M.anchored) - M.loc = src - break - ..() - -//fluff variant -/obj/structure/closet/crate/secure/large/reinforced - desc = "A hefty, reinforced metal crate with an electronic locking system." - icon_state = "largermetal" - icon_opened = "largermetalopen" - icon_closed = "largermetal" - -/obj/structure/closet/crate/secure - desc = "A secure crate." - name = "Secure crate" - icon_state = "securecrate" - icon_opened = "securecrateopen" - icon_closed = "securecrate" - var/redlight = "securecrater" - var/greenlight = "securecrateg" - var/sparks = "securecratesparks" - var/emag = "securecrateemag" - broken = 0 - locked = 1 - health = 1000 - -/obj/structure/closet/crate/large - name = "large crate" - desc = "A hefty metal crate." - icon = 'icons/obj/storage.dmi' - icon_state = "largemetal" - icon_opened = "largemetalopen" - icon_closed = "largemetal" - -/obj/structure/closet/crate/large/close() - //we can hold up to one large item - var/found = 0 - for(var/obj/structure/S in src.loc) - if(S == src) - continue - if(!S.anchored) - found = 1 - S.loc = src - break - if(!found) - for(var/obj/machinery/M in src.loc) - if(!M.anchored) - M.loc = src - break - ..() - -/obj/structure/closet/crate/hydroponics - name = "Hydroponics crate" - desc = "All you need to destroy those pesky weeds and pests." - icon = 'icons/obj/storage.dmi' - icon_state = "hydrocrate" - icon_opened = "hydrocrateopen" - icon_closed = "hydrocrate" - density = 1 - -/obj/structure/closet/crate/sci - desc = "A science crate." - name = "science crate" - icon = 'icons/obj/storage.dmi' - icon_state = "scicrate" - density = 1 - icon_opened = "scicrateopen" - icon_closed = "scicrate" - -/obj/structure/closet/crate/secure/scisec - desc = "A secure science crate." - name = "secure science crate" - icon = 'icons/obj/storage.dmi' - icon_state = "scisecurecrate" - density = 1 - icon_opened = "scisecurecrateopen" - icon_closed = "scisecurecrate" - -/obj/structure/closet/crate/engi - desc = "An engineering crate." - name = "engineering crate" - icon = 'icons/obj/storage.dmi' - icon_state = "engicrate" - density = 1 - icon_opened = "engicrateopen" - icon_closed = "engicrate" - -/obj/structure/closet/crate/secure/engisec - desc = "A secure engineering crate." - name = "secure engineering crate" - icon = 'icons/obj/storage.dmi' - icon_state = "engisecurecrate" - density = 1 - icon_opened = "engisecurecrateopen" - icon_closed = "engisecurecrate" - -/obj/structure/closet/crate/secure/plasma/prefilled - var/count=10 -/obj/structure/closet/crate/secure/plasma/prefilled/New() - for(var/i=0;i= storage_capacity) - return -1 - - if(include_mobs && isliving(AM)) - var/mob/living/L = AM - if(L.locked_to) - return 0 - else if(isobj(AM)) - if(AM.density || AM.anchored || istype(AM,/obj/structure/closet)) - return 0 - else - return 0 - - if(istype(AM, /obj/structure/bed)) //This is only necessary because of rollerbeds and swivel chairs. - var/obj/structure/bed/B = AM - if(B.locked_atoms.len) - return 0 - - AM.forceMove(src) - return 1 - -/obj/structure/closet/crate/attack_hand(mob/user as mob) - if(!Adjacent(user)) - return - if(opened) - close() - else - if(rigged && locate(/obj/item/device/radio/electropack) in src) - if(isliving(user)) - var/mob/living/L = user - if(L.electrocute_act(17, src)) - //var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - //s.set_up(5, 1, src) - //s.start() - return - open() - return - -/obj/structure/closet/crate/secure/attack_hand(mob/user as mob) - if(!Adjacent(user)) - return - if(locked && !broken) - if (allowed(user)) - to_chat(user, "You unlock [src].") - src.locked = 0 - overlays.len = 0 - overlays += greenlight - return - else - to_chat(user, "[src] is locked.") - return - else - ..() - -/obj/structure/closet/crate/secure/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card) && src.allowed(user) && !locked && !opened && !broken) - to_chat(user, "You lock \the [src].") - src.locked = 1 - overlays.len = 0 - overlays += redlight - return - else if ( istype(W, /obj/item/weapon/card/emag) && locked &&!broken) - overlays.len = 0 - overlays += emag - overlays += sparks - spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* - playsound(get_turf(src), "sparks", 60, 1) - src.locked = 0 - src.broken = 1 - to_chat(user, "You unlock \the [src].") - return - return ..() - -/obj/structure/closet/crate/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/structure/closet/crate/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(opened) - return ..() - else if(istype(W, /obj/item/stack/package_wrap)) - return - else if(istype(W, /obj/item/stack/cable_coil)) - if(rigged) - to_chat(user, "[src] is already rigged!") - return - - if(user.drop_item(W)) - to_chat(user, "You rig [src].") - qdel(W) - W = null - rigged = 1 - return - else if(istype(W, /obj/item/device/radio/electropack)) - if(rigged) - if(user.drop_item(W, src.loc)) - to_chat(user, "You attach [W] to [src].") - return - else if(istype(W, /obj/item/weapon/wirecutters)) - if(rigged) - to_chat(user, "You cut away the wiring.") - playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) - rigged = 0 - return - else if(!place(user, W)) - return attack_hand(user) - -/obj/structure/closet/crate/secure/emp_act(severity) - for(var/obj/O in src) - O.emp_act(severity) - if(!broken && !opened && prob(50/severity)) - if(!locked) - src.locked = 1 - overlays.len = 0 - overlays += redlight - else - overlays.len = 0 - overlays += emag - overlays += sparks - spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) - src.locked = 0 - if(!opened && prob(20/severity)) - if(!locked) - open() - else - src.req_access = list() - src.req_access += pick(get_all_accesses()) - ..() - - -/obj/structure/closet/crate/ex_act(severity) - switch(severity) - if(1.0) - for(var/obj/O in src.contents) - qdel(O) - qdel(src) - return - if(2.0) - for(var/obj/O in src.contents) - if(prob(50)) - qdel(O) - qdel(src) - return - if(3.0) - if (prob(50)) - qdel(src) - return - else - return - -/obj/structure/closet/crate/secure/weapon/experimental - name = "Experimental Weapons Crate" - var/chosen_set = null - -/obj/structure/closet/crate/secure/weapon/experimental/New() - ..() - if(!chosen_set) - chosen_set = pick("ricochet","bison","spur","gatling","stickybomb","nikita","osipr","hecate","gravitywell") - - switch(chosen_set) - if("ricochet") - new/obj/item/clothing/suit/armor/laserproof(src) - new/obj/item/weapon/gun/energy/ricochet(src) - new/obj/item/weapon/gun/energy/ricochet(src) - if("bison") - new/obj/item/clothing/shoes/jackboots(src) - new/obj/item/clothing/suit/hgpirate(src) - new/obj/item/clothing/head/hgpiratecap(src) - new/obj/item/clothing/glasses/eyepatch(src) - new/obj/item/weapon/gun/energy/bison(src) - if("spur") - new/obj/item/clothing/suit/cardborg(src) - new/obj/item/clothing/head/cardborg(src) - new/obj/item/device/modkit/spur_parts(src) - new/obj/item/weapon/gun/energy/polarstar(src) - if("gatling") - new/obj/item/clothing/suit/armor/riot(src) - new/obj/item/clothing/head/helmet/riot(src) - new/obj/item/clothing/shoes/swat(src) - new/obj/item/clothing/gloves/swat(src) - new/obj/item/weapon/gun/gatling(src) - if("stickybomb") - new/obj/item/clothing/suit/bomb_suit/security(src) - new/obj/item/clothing/head/bomb_hood/security(src) - new/obj/item/weapon/gun/stickybomb(src) - new/obj/item/weapon/storage/box/stickybombs(src) - if("nikita") - for(var/i=1;i<=5;i++) - new/obj/item/ammo_casing/rocket_rpg/nikita(src) - new/obj/item/weapon/gun/projectile/rocketlauncher/nikita(src) - if("osipr") - new/obj/item/clothing/suit/space/syndicate/black(src) - new/obj/item/clothing/head/helmet/space/syndicate/black(src) - new/obj/item/weapon/gun/osipr(src) - if("hecate") - new/obj/item/weapon/gun/projectile/hecate(src) - new/obj/item/ammo_storage/box/BMG50(src) - new/obj/item/device/radio/headset/headset_earmuffs(src) - new/obj/item/clothing/glasses/thermal(src) - if("gravitywell") - new/obj/item/clothing/suit/radiation(src) - new/obj/item/clothing/head/radiation(src) - new/obj/item/clothing/shoes/magboots(src) - new/obj/item/weapon/gun/gravitywell(src) - -/obj/structure/closet/crate/secure/weapon/experimental/ricochet - chosen_set = "ricochet" - -/obj/structure/closet/crate/secure/weapon/experimental/bison - chosen_set = "bison" - -/obj/structure/closet/crate/secure/weapon/experimental/spur - chosen_set = "spur" - -/obj/structure/closet/crate/secure/weapon/experimental/gatling - chosen_set = "gatling" - -/obj/structure/closet/crate/secure/weapon/experimental/stickybomb - chosen_set = "stickybomb" - -/obj/structure/closet/crate/secure/weapon/experimental/nikita - chosen_set = "nikita" - -/obj/structure/closet/crate/secure/weapon/experimental/osipr - chosen_set = "osipr" - -/obj/structure/closet/crate/secure/weapon/experimental/hecate - chosen_set = "hecate" - -/obj/structure/closet/crate/secure/weapon/experimental/gravitywell - chosen_set = "gravitywell" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/structure/closet/crate + name = "crate" + desc = "A rectangular steel crate." + icon = 'icons/obj/storage.dmi' + icon_state = "crate" + density = 1 + icon_opened = "crateopen" + icon_closed = "crate" + req_access = null + opened = 0 + flags = FPRINT +// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? + var/rigged = 0 + var/sound_effect_open = 'sound/machines/click.ogg' + var/sound_effect_close = 'sound/machines/click.ogg' + +/obj/structure/closet/pcrate + name = "plastic crate" + desc = "A rectangular plastic crate." + icon = 'icons/obj/storage.dmi' + icon_state = "plasticcrate" + density = 1 + icon_opened = "plasticcrateopen" + icon_closed = "plasticcrate" + req_access = null + opened = 0 + flags = FPRINT +// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? + var/rigged = 0 + var/sound_effect_open = 'sound/machines/click.ogg' + var/sound_effect_close = 'sound/machines/click.ogg' + + starting_materials = list(MAT_PLASTIC = 10*CC_PER_SHEET_METAL) // Recipe calls for 10 sheets. + +/obj/structure/closet/crate/internals + desc = "A internals crate." + name = "Internals crate" + icon = 'icons/obj/storage.dmi' + icon_state = "o2crate" + density = 1 + icon_opened = "o2crateopen" + icon_closed = "o2crate" + +/obj/structure/closet/crate/trashcart + desc = "A heavy, metal trashcart with wheels." + name = "Trash Cart" + icon = 'icons/obj/storage.dmi' + icon_state = "trashcart" + density = 1 + icon_opened = "trashcartopen" + icon_closed = "trashcart" + +/obj/structure/closet/crate/chest + desc = "A heavy wooden chest. Probably filled with gold and treasure!" + name = "chest" + icon = 'icons/obj/storage.dmi' + icon_state = "chest" + density = 1 + icon_opened = "chestopen" + icon_closed = "chest" + +/*these aren't needed anymore +/obj/structure/closet/crate/hat + desc = "A crate filled with Valuable Collector's Hats!." + name = "Hat Crate" + icon = 'icons/obj/storage.dmi' + icon_state = "crate" + density = 1 + icon_opened = "crateopen" + icon_closed = "crate" + +/obj/structure/closet/crate/contraband + name = "Poster crate" + desc = "A random assortment of posters manufactured by providers NOT listed under Nanotrasen's whitelist." + icon = 'icons/obj/storage.dmi' + icon_state = "crate" + density = 1 + icon_opened = "crateopen" + icon_closed = "crate" +*/ + +/obj/structure/closet/crate/medical + desc = "A medical crate." + name = "Medical crate" + icon = 'icons/obj/storage.dmi' + icon_state = "medicalcrate" + density = 1 + icon_opened = "medicalcrateopen" + icon_closed = "medicalcrate" + +/obj/structure/closet/crate/rcd + desc = "A crate for the storage of the RCD." + name = "RCD crate" + icon = 'icons/obj/storage.dmi' + icon_state = "crate" + density = 1 + icon_opened = "crateopen" + icon_closed = "crate" + +/obj/structure/closet/crate/freezer + desc = "A freezer." + name = "Freezer" + icon = 'icons/obj/storage.dmi' + icon_state = "freezer" + density = 1 + icon_opened = "freezeropen" + icon_closed = "freezer" + var/target_temp = T0C - 40 + var/cooling_power = 40 + + return_air() + var/datum/gas_mixture/gas = (..()) + if(!gas) return null + var/datum/gas_mixture/newgas = new/datum/gas_mixture() + newgas.oxygen = gas.oxygen + newgas.carbon_dioxide = gas.carbon_dioxide + newgas.nitrogen = gas.nitrogen + newgas.toxins = gas.toxins + newgas.volume = gas.volume + newgas.temperature = gas.temperature + if(newgas.temperature <= target_temp) return + + if((newgas.temperature - cooling_power) > target_temp) + newgas.temperature -= cooling_power + else + newgas.temperature = target_temp + return newgas + + +/obj/structure/closet/crate/bin + desc = "A large bin." + name = "Large bin" + icon = 'icons/obj/storage.dmi' + icon_state = "largebin" + density = 1 + icon_opened = "largebinopen" + icon_closed = "largebin" + +/obj/structure/closet/crate/radiation + desc = "A crate with a radiation sign on it." + name = "Radioactive gear crate" + icon = 'icons/obj/storage.dmi' + icon_state = "radiation" + density = 1 + icon_opened = "radiationopen" + icon_closed = "radiation" + +/obj/structure/closet/crate/secure/weapon + desc = "A secure weapons crate." + name = "Weapons crate" + icon = 'icons/obj/storage.dmi' + icon_state = "weaponcrate" + density = 1 + icon_opened = "weaponcrateopen" + icon_closed = "weaponcrate" + +/obj/structure/closet/crate/secure/plasma + desc = "A secure plasma crate." + name = "Plasma crate" + icon = 'icons/obj/storage.dmi' + icon_state = "plasmacrate" + density = 1 + icon_opened = "plasmacrateopen" + icon_closed = "plasmacrate" + +/obj/structure/closet/crate/secure/gear + desc = "A secure gear crate." + name = "Gear crate" + icon = 'icons/obj/storage.dmi' + icon_state = "secgearcrate" + density = 1 + icon_opened = "secgearcrateopen" + icon_closed = "secgearcrate" + +/obj/structure/closet/crate/secure/hydrosec + desc = "A crate with a lock on it, painted in the scheme of the station's botanists." + name = "secure hydroponics crate" + icon = 'icons/obj/storage.dmi' + icon_state = "hydrosecurecrate" + density = 1 + icon_opened = "hydrosecurecrateopen" + icon_closed = "hydrosecurecrate" + +/obj/structure/closet/crate/secure/bin + desc = "A secure bin." + name = "Secure bin" + icon_state = "largebins" + icon_opened = "largebinsopen" + icon_closed = "largebins" + redlight = "largebinr" + greenlight = "largebing" + sparks = "largebinsparks" + emag = "largebinemag" + +/obj/structure/closet/crate/secure/large + name = "large crate" + desc = "A hefty metal crate with an electronic locking system." + icon = 'icons/obj/storage.dmi' + icon_state = "largemetal" + icon_opened = "largemetalopen" + icon_closed = "largemetal" + redlight = "largemetalr" + greenlight = "largemetalg" + +/obj/structure/closet/crate/secure/large/close() + //we can hold up to one large item + var/found = 0 + for(var/obj/structure/S in src.loc) + if(S == src) + continue + if(!S.anchored) + found = 1 + S.loc = src + break + if(!found) + for(var/obj/machinery/M in src.loc) + if(!M.anchored) + M.loc = src + break + ..() + +//fluff variant +/obj/structure/closet/crate/secure/large/reinforced + desc = "A hefty, reinforced metal crate with an electronic locking system." + icon_state = "largermetal" + icon_opened = "largermetalopen" + icon_closed = "largermetal" + +/obj/structure/closet/crate/secure + desc = "A secure crate." + name = "Secure crate" + icon_state = "securecrate" + icon_opened = "securecrateopen" + icon_closed = "securecrate" + var/redlight = "securecrater" + var/greenlight = "securecrateg" + var/sparks = "securecratesparks" + var/emag = "securecrateemag" + broken = 0 + locked = 1 + health = 1000 + +/obj/structure/closet/crate/large + name = "large crate" + desc = "A hefty metal crate." + icon = 'icons/obj/storage.dmi' + icon_state = "largemetal" + icon_opened = "largemetalopen" + icon_closed = "largemetal" + +/obj/structure/closet/crate/large/close() + //we can hold up to one large item + var/found = 0 + for(var/obj/structure/S in src.loc) + if(S == src) + continue + if(!S.anchored) + found = 1 + S.loc = src + break + if(!found) + for(var/obj/machinery/M in src.loc) + if(!M.anchored) + M.loc = src + break + ..() + +/obj/structure/closet/crate/hydroponics + name = "Hydroponics crate" + desc = "All you need to destroy those pesky weeds and pests." + icon = 'icons/obj/storage.dmi' + icon_state = "hydrocrate" + icon_opened = "hydrocrateopen" + icon_closed = "hydrocrate" + density = 1 + +/obj/structure/closet/crate/sci + desc = "A science crate." + name = "science crate" + icon = 'icons/obj/storage.dmi' + icon_state = "scicrate" + density = 1 + icon_opened = "scicrateopen" + icon_closed = "scicrate" + +/obj/structure/closet/crate/secure/scisec + desc = "A secure science crate." + name = "secure science crate" + icon = 'icons/obj/storage.dmi' + icon_state = "scisecurecrate" + density = 1 + icon_opened = "scisecurecrateopen" + icon_closed = "scisecurecrate" + +/obj/structure/closet/crate/engi + desc = "An engineering crate." + name = "engineering crate" + icon = 'icons/obj/storage.dmi' + icon_state = "engicrate" + density = 1 + icon_opened = "engicrateopen" + icon_closed = "engicrate" + +/obj/structure/closet/crate/secure/engisec + desc = "A secure engineering crate." + name = "secure engineering crate" + icon = 'icons/obj/storage.dmi' + icon_state = "engisecurecrate" + density = 1 + icon_opened = "engisecurecrateopen" + icon_closed = "engisecurecrate" + +/obj/structure/closet/crate/secure/plasma/prefilled + var/count=10 +/obj/structure/closet/crate/secure/plasma/prefilled/New() + for(var/i=0;i= storage_capacity) + return -1 + + if(include_mobs && isliving(AM)) + var/mob/living/L = AM + if(L.locked_to) + return 0 + else if(isobj(AM)) + if(AM.density || AM.anchored || istype(AM,/obj/structure/closet)) + return 0 + else + return 0 + + if(istype(AM, /obj/structure/bed)) //This is only necessary because of rollerbeds and swivel chairs. + var/obj/structure/bed/B = AM + if(B.locked_atoms.len) + return 0 + + AM.forceMove(src) + return 1 + +/obj/structure/closet/crate/attack_hand(mob/user as mob) + if(!Adjacent(user)) + return + if(opened) + close() + else + if(rigged && locate(/obj/item/device/radio/electropack) in src) + if(isliving(user)) + var/mob/living/L = user + if(L.electrocute_act(17, src)) + //var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + //s.set_up(5, 1, src) + //s.start() + return + open() + return + +/obj/structure/closet/crate/secure/attack_hand(mob/user as mob) + if(!Adjacent(user)) + return + if(locked && !broken) + if (allowed(user)) + to_chat(user, "You unlock [src].") + src.locked = 0 + overlays.len = 0 + overlays += greenlight + return + else + to_chat(user, "[src] is locked.") + return + else + ..() + +/obj/structure/closet/crate/secure/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card) && src.allowed(user) && !locked && !opened && !broken) + to_chat(user, "You lock \the [src].") + src.locked = 1 + overlays.len = 0 + overlays += redlight + return + else if ( istype(W, /obj/item/weapon/card/emag) && locked &&!broken) + overlays.len = 0 + overlays += emag + overlays += sparks + spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* + playsound(get_turf(src), "sparks", 60, 1) + src.locked = 0 + src.broken = 1 + to_chat(user, "You unlock \the [src].") + return + return ..() + +/obj/structure/closet/crate/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/structure/closet/crate/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(opened) + return ..() + else if(istype(W, /obj/item/stack/package_wrap)) + return + else if(istype(W, /obj/item/stack/cable_coil)) + if(rigged) + to_chat(user, "[src] is already rigged!") + return + + if(user.drop_item(W)) + to_chat(user, "You rig [src].") + qdel(W) + W = null + rigged = 1 + return + else if(istype(W, /obj/item/device/radio/electropack)) + if(rigged) + if(user.drop_item(W, src.loc)) + to_chat(user, "You attach [W] to [src].") + return + else if(istype(W, /obj/item/weapon/wirecutters)) + if(rigged) + to_chat(user, "You cut away the wiring.") + playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) + rigged = 0 + return + else if(!place(user, W)) + return attack_hand(user) + +/obj/structure/closet/crate/secure/emp_act(severity) + for(var/obj/O in src) + O.emp_act(severity) + if(!broken && !opened && prob(50/severity)) + if(!locked) + src.locked = 1 + overlays.len = 0 + overlays += redlight + else + overlays.len = 0 + overlays += emag + overlays += sparks + spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* + playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + src.locked = 0 + if(!opened && prob(20/severity)) + if(!locked) + open() + else + src.req_access = list() + src.req_access += pick(get_all_accesses()) + ..() + + +/obj/structure/closet/crate/ex_act(severity) + switch(severity) + if(1.0) + for(var/obj/O in src.contents) + qdel(O) + qdel(src) + return + if(2.0) + for(var/obj/O in src.contents) + if(prob(50)) + qdel(O) + qdel(src) + return + if(3.0) + if (prob(50)) + qdel(src) + return + else + return + +/obj/structure/closet/crate/secure/weapon/experimental + name = "Experimental Weapons Crate" + var/chosen_set = null + +/obj/structure/closet/crate/secure/weapon/experimental/New() + ..() + if(!chosen_set) + chosen_set = pick("ricochet","bison","spur","gatling","stickybomb","nikita","osipr","hecate","gravitywell") + + switch(chosen_set) + if("ricochet") + new/obj/item/clothing/suit/armor/laserproof(src) + new/obj/item/weapon/gun/energy/ricochet(src) + new/obj/item/weapon/gun/energy/ricochet(src) + if("bison") + new/obj/item/clothing/shoes/jackboots(src) + new/obj/item/clothing/suit/hgpirate(src) + new/obj/item/clothing/head/hgpiratecap(src) + new/obj/item/clothing/glasses/eyepatch(src) + new/obj/item/weapon/gun/energy/bison(src) + if("spur") + new/obj/item/clothing/suit/cardborg(src) + new/obj/item/clothing/head/cardborg(src) + new/obj/item/device/modkit/spur_parts(src) + new/obj/item/weapon/gun/energy/polarstar(src) + if("gatling") + new/obj/item/clothing/suit/armor/riot(src) + new/obj/item/clothing/head/helmet/riot(src) + new/obj/item/clothing/shoes/swat(src) + new/obj/item/clothing/gloves/swat(src) + new/obj/item/weapon/gun/gatling(src) + if("stickybomb") + new/obj/item/clothing/suit/bomb_suit/security(src) + new/obj/item/clothing/head/bomb_hood/security(src) + new/obj/item/weapon/gun/stickybomb(src) + new/obj/item/weapon/storage/box/stickybombs(src) + if("nikita") + for(var/i=1;i<=5;i++) + new/obj/item/ammo_casing/rocket_rpg/nikita(src) + new/obj/item/weapon/gun/projectile/rocketlauncher/nikita(src) + if("osipr") + new/obj/item/clothing/suit/space/syndicate/black(src) + new/obj/item/clothing/head/helmet/space/syndicate/black(src) + new/obj/item/weapon/gun/osipr(src) + if("hecate") + new/obj/item/weapon/gun/projectile/hecate(src) + new/obj/item/ammo_storage/box/BMG50(src) + new/obj/item/device/radio/headset/headset_earmuffs(src) + new/obj/item/clothing/glasses/thermal(src) + if("gravitywell") + new/obj/item/clothing/suit/radiation(src) + new/obj/item/clothing/head/radiation(src) + new/obj/item/clothing/shoes/magboots(src) + new/obj/item/weapon/gun/gravitywell(src) + +/obj/structure/closet/crate/secure/weapon/experimental/ricochet + chosen_set = "ricochet" + +/obj/structure/closet/crate/secure/weapon/experimental/bison + chosen_set = "bison" + +/obj/structure/closet/crate/secure/weapon/experimental/spur + chosen_set = "spur" + +/obj/structure/closet/crate/secure/weapon/experimental/gatling + chosen_set = "gatling" + +/obj/structure/closet/crate/secure/weapon/experimental/stickybomb + chosen_set = "stickybomb" + +/obj/structure/closet/crate/secure/weapon/experimental/nikita + chosen_set = "nikita" + +/obj/structure/closet/crate/secure/weapon/experimental/osipr + chosen_set = "osipr" + +/obj/structure/closet/crate/secure/weapon/experimental/hecate + chosen_set = "hecate" + +/obj/structure/closet/crate/secure/weapon/experimental/gravitywell + chosen_set = "gravitywell" diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 804d04a3359..7e05ad937ee 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -1,75 +1,75 @@ -/obj/structure/largecrate - name = "large crate" - desc = "A hefty wooden crate." - icon = 'icons/obj/storage.dmi' - icon_state = "densecrate" - density = 1 - flags = FPRINT - -/obj/structure/largecrate/attack_hand(mob/user as mob) +/obj/structure/largecrate + name = "large crate" + desc = "A hefty wooden crate." + icon = 'icons/obj/storage.dmi' + icon_state = "densecrate" + density = 1 + flags = FPRINT + +/obj/structure/largecrate/attack_hand(mob/user as mob) to_chat(user, "You need a crowbar to pry this open!") - return - -/obj/structure/largecrate/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/crowbar)) - new /obj/item/stack/sheet/wood(src) - var/turf/T = get_turf(src) - for(var/obj/O in contents) - O.loc = T - user.visible_message("[user] pries \the [src] open.", \ - "You pry open \the [src].", \ - "You hear splitting wood.") - qdel(src) - else - return attack_hand(user) - -/obj/structure/largecrate/mule - icon_state = "mulecrate" - -/obj/structure/largecrate/lisa - icon_state = "lisacrate" - -/obj/structure/largecrate/porcelain - ..() - -/obj/structure/largecrate/lisa/attackby(obj/item/weapon/W as obj, mob/user as mob) //ugly but oh well - if(istype(W, /obj/item/weapon/crowbar)) - new /mob/living/simple_animal/corgi/Lisa(loc) - ..() - -/obj/structure/largecrate/cow - name = "cow crate" - icon_state = "lisacrate" - -/obj/structure/largecrate/cow/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/crowbar)) - new /mob/living/simple_animal/cow(loc) - ..() - -/obj/structure/largecrate/goat - name = "goat crate" - icon_state = "lisacrate" - -/obj/structure/largecrate/goat/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/crowbar)) - new /mob/living/simple_animal/hostile/retaliate/goat(loc) - ..() - -/obj/structure/largecrate/chick - name = "chicken crate" - icon_state = "lisacrate" - -/obj/structure/largecrate/chick/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/crowbar)) - var/num = rand(4, 6) - for(var/i = 0, i < num, i++) - new /mob/living/simple_animal/chick(loc) - ..() - -/obj/structure/largecrate/porcelain/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/crowbar)) - var/obj/structure/toilet/T = new (loc) - T.anchored = 0 - var/obj/structure/sink/S = new (loc) - S.anchored = 0 - ..() + return + +/obj/structure/largecrate/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + new /obj/item/stack/sheet/wood(src) + var/turf/T = get_turf(src) + for(var/obj/O in contents) + O.loc = T + user.visible_message("[user] pries \the [src] open.", \ + "You pry open \the [src].", \ + "You hear splitting wood.") + qdel(src) + else + return attack_hand(user) + +/obj/structure/largecrate/mule + icon_state = "mulecrate" + +/obj/structure/largecrate/lisa + icon_state = "lisacrate" + +/obj/structure/largecrate/porcelain + ..() + +/obj/structure/largecrate/lisa/attackby(obj/item/weapon/W as obj, mob/user as mob) //ugly but oh well + if(istype(W, /obj/item/weapon/crowbar)) + new /mob/living/simple_animal/corgi/Lisa(loc) + ..() + +/obj/structure/largecrate/cow + name = "cow crate" + icon_state = "lisacrate" + +/obj/structure/largecrate/cow/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + new /mob/living/simple_animal/cow(loc) + ..() + +/obj/structure/largecrate/goat + name = "goat crate" + icon_state = "lisacrate" + +/obj/structure/largecrate/goat/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + new /mob/living/simple_animal/hostile/retaliate/goat(loc) + ..() + +/obj/structure/largecrate/chick + name = "chicken crate" + icon_state = "lisacrate" + +/obj/structure/largecrate/chick/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + var/num = rand(4, 6) + for(var/i = 0, i < num, i++) + new /mob/living/simple_animal/chick(loc) + ..() + +/obj/structure/largecrate/porcelain/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + var/obj/structure/toilet/T = new (loc) + T.anchored = 0 + var/obj/structure/sink/S = new (loc) + S.anchored = 0 + ..() diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 48f2b6fa049..0482fa318f4 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -1,275 +1,275 @@ -/obj/structure/displaycase_frame - name = "display case frame" - icon = 'icons/obj/stock_parts.dmi' - icon_state="box_glass" - var/obj/item/weapon/circuitboard/airlock/circuit=null - var/state=0 - -/obj/structure/displaycase_frame/Destroy() - ..() - if(circuit) - qdel(circuit) - circuit = null - -/obj/structure/displaycase_frame/attackby(obj/item/weapon/W as obj, mob/user as mob) - var/pstate=state - var/turf/T=get_turf(src) - switch(state) - if(0) - if(istype(W, /obj/item/weapon/circuitboard/airlock) && W:icon_state != "door_electronics_smoked") - if(user.drop_item(W, src)) - circuit=W - state++ - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(istype(W, /obj/item/weapon/crowbar)) - var/obj/machinery/constructable_frame/machine_frame/MF = new /obj/machinery/constructable_frame/machine_frame(T) - MF.state = 1 - MF.set_build_state(2) - new /obj/item/stack/sheet/glass/glass(T) - qdel(src) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - return - - if(1) - if(isscrewdriver(W)) - var/obj/structure/displaycase/C=new(T) - if(circuit.one_access) - C.req_access = null - C.req_one_access = circuit.conf_access - else - C.req_access = circuit.conf_access - C.req_one_access = null - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - qdel(src) - return - if(istype(W, /obj/item/weapon/crowbar)) - circuit.loc=T - circuit=null - state-- - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - if(pstate!=state) - pstate=state - update_icon() - -/obj/structure/displaycase_frame/update_icon() - switch(state) - if(1) - icon_state="box_glass_circuit" - else - icon_state="box_glass" - - -/obj/structure/displaycase - name = "display case" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "glassbox20" - desc = "A display case for prized possessions. It tempts you to kick it." - density = 1 - anchored = 1 - unacidable = 1//Dissolving the case would also delete the gun. - var/health = 30 - var/obj/item/occupant = null - var/destroyed = 0 - var/locked = 0 - var/ue=null - var/image/occupant_overlay=null - var/obj/item/weapon/circuitboard/airlock/circuit - -/obj/structure/displaycase/Destroy() - ..() - if(circuit) - qdel(circuit) - circuit = null - dump() - -/obj/structure/displaycase/captains_laser/New() - ..() - occupant=new /obj/item/weapon/gun/energy/laser/captain(src) - locked=1 - req_access=list(access_captain) - update_icon() - -/obj/structure/displaycase/gooncode/New() - ..() - occupant=new /obj/item/toy/gooncode(src) - locked=1 - req_access=list(access_captain) - update_icon() - -/obj/structure/displaycase/lamarr/New() - ..() - occupant=new /obj/item/clothing/mask/facehugger/lamarr(src) - locked=1 - req_access=list(access_rd) - update_icon() - -/obj/structure/displaycase/examine(mob/user) - ..() - var/msg = "Peering through the glass, you see that it contains:" - if(occupant) - msg+= "\icon[occupant] \A [occupant]" - else - msg+= "Nothing." - to_chat(user, msg) - -/obj/structure/displaycase/proc/dump() - if(occupant) - occupant.loc=get_turf(src) - occupant=null - occupant_overlay=null - -/obj/structure/displaycase/ex_act(severity) - switch(severity) - if (1) - getFromPool(/obj/item/weapon/shard, loc) - if (occupant) - dump() - qdel(src) - if (2) - if (prob(50)) - src.health -= 15 - src.healthcheck() - if (3) - if (prob(50)) - src.health -= 5 - src.healthcheck() - - -/obj/structure/displaycase/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - src.healthcheck() - return - - -/obj/structure/displaycase/blob_act() - if (prob(75)) - getFromPool(/obj/item/weapon/shard, loc) - if(occupant) dump() - qdel(src) - -/obj/structure/displaycase/proc/healthcheck() - if (src.health <= 0) - if (!( src.destroyed )) - src.density = 0 - src.destroyed = 1 - getFromPool(/obj/item/weapon/shard, loc) - playsound(get_turf(src), "shatter", 70, 1) - update_icon() - else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - return - -/obj/structure/displaycase/update_icon() - if(src.destroyed) - src.icon_state = "glassbox2b" - else - src.icon_state = "glassbox2[locked]" - overlays = 0 - if(occupant) - var/icon/occupant_icon=getFlatIcon(occupant) - occupant_icon.Scale(19,19) - occupant_overlay = image(occupant_icon) - occupant_overlay.pixel_x=8 - occupant_overlay.pixel_y=8 - if(locked) - occupant_overlay.alpha=128//ChangeOpacity(0.5) - //underlays += occupant_overlay - overlays += occupant_overlay - return - - -/obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/I=W - if(!check_access(I)) - to_chat(user, "Access denied.") - return - locked = !locked - if(!locked) - to_chat(user, "\icon[src] \The [src] clicks as locks release, and it slowly opens for you.") - else - to_chat(user, "\icon[src] You close \the [src] and swipe your card, locking it.") - update_icon() - else if(istype(W, /obj/item/weapon/crowbar) && (!locked || destroyed)) - user.visible_message("[user.name] pries \the [src] apart.", \ - "You pry \the [src] apart.", \ - "You hear something pop.") - var/turf/T=get_turf(src) - playsound(T, 'sound/items/Crowbar.ogg', 50, 1) - dump() - var/obj/item/weapon/circuitboard/airlock/C=circuit - if(!C) - C=new (src) - C.one_access=!(req_access && req_access.len>0) - if(!C.one_access) - C.conf_access=req_access - else - C.conf_access=req_one_access - if(!destroyed) - var/obj/structure/displaycase_frame/F=new(T) - F.state=1 - F.circuit=C - F.circuit.loc=F - F.update_icon() - else - C.loc=T - circuit=null - new /obj/machinery/constructable_frame/machine_frame(T) - qdel(src) - else if(user.a_intent == I_HURT) - user.delayNextAttack(8) - src.health -= W.force - src.healthcheck() - ..() - else - if(locked) - to_chat(user, "It's locked, you can't put anything into it.") - else if(!occupant) - if(user.drop_item(W, src)) - to_chat(user, "You insert \the [W] into \the [src], and it floats as the hoverfield activates.") - occupant=W - update_icon() - -/obj/structure/displaycase/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/displaycase/proc/getPrint(mob/user as mob) - return md5(user:dna:uni_identity) - -/obj/structure/displaycase/attack_hand(mob/user as mob) - if (destroyed) - if(occupant) - dump() - to_chat(user, "You smash your fist into the delicate electronics at the bottom of the case, and deactivate the hoverfield permanently.") - src.add_fingerprint(user) - update_icon() - else - if(user.a_intent == I_HURT) - user.delayNextAttack(8) - user.visible_message("[user.name] kicks \the [src]!", \ - "You kick \the [src]!", \ - "You hear glass crack.") - src.health -= 2 - healthcheck() - else if(!locked) - if(ishuman(user)) - if(!ue) - to_chat(user, "You press your thumb against the fingerprint scanner, registering your identity with the case.") - ue = getPrint(user) - return - if(ue!=getPrint(user)) - to_chat(user, "Access denied.") - return - - to_chat(user, "You press your thumb against the fingerprint scanner, and deactivate the hoverfield built into the case.") - if(occupant) - dump() - update_icon() - else - to_chat(src, "\icon[src] \The [src] is empty!") - else - user.delayNextAttack(10) // prevent spam - user.visible_message("[user.name] gently runs their hands over \the [src] in appreciation of its contents.", \ - "You gently run your hands over \the [src] in appreciation of its contents.", \ - "You hear someone streaking glass with their greasy hands.") +/obj/structure/displaycase_frame + name = "display case frame" + icon = 'icons/obj/stock_parts.dmi' + icon_state="box_glass" + var/obj/item/weapon/circuitboard/airlock/circuit=null + var/state=0 + +/obj/structure/displaycase_frame/Destroy() + ..() + if(circuit) + qdel(circuit) + circuit = null + +/obj/structure/displaycase_frame/attackby(obj/item/weapon/W as obj, mob/user as mob) + var/pstate=state + var/turf/T=get_turf(src) + switch(state) + if(0) + if(istype(W, /obj/item/weapon/circuitboard/airlock) && W:icon_state != "door_electronics_smoked") + if(user.drop_item(W, src)) + circuit=W + state++ + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(istype(W, /obj/item/weapon/crowbar)) + var/obj/machinery/constructable_frame/machine_frame/MF = new /obj/machinery/constructable_frame/machine_frame(T) + MF.state = 1 + MF.set_build_state(2) + new /obj/item/stack/sheet/glass/glass(T) + qdel(src) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + return + + if(1) + if(isscrewdriver(W)) + var/obj/structure/displaycase/C=new(T) + if(circuit.one_access) + C.req_access = null + C.req_one_access = circuit.conf_access + else + C.req_access = circuit.conf_access + C.req_one_access = null + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + qdel(src) + return + if(istype(W, /obj/item/weapon/crowbar)) + circuit.loc=T + circuit=null + state-- + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + if(pstate!=state) + pstate=state + update_icon() + +/obj/structure/displaycase_frame/update_icon() + switch(state) + if(1) + icon_state="box_glass_circuit" + else + icon_state="box_glass" + + +/obj/structure/displaycase + name = "display case" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "glassbox20" + desc = "A display case for prized possessions. It tempts you to kick it." + density = 1 + anchored = 1 + unacidable = 1//Dissolving the case would also delete the gun. + var/health = 30 + var/obj/item/occupant = null + var/destroyed = 0 + var/locked = 0 + var/ue=null + var/image/occupant_overlay=null + var/obj/item/weapon/circuitboard/airlock/circuit + +/obj/structure/displaycase/Destroy() + ..() + if(circuit) + qdel(circuit) + circuit = null + dump() + +/obj/structure/displaycase/captains_laser/New() + ..() + occupant=new /obj/item/weapon/gun/energy/laser/captain(src) + locked=1 + req_access=list(access_captain) + update_icon() + +/obj/structure/displaycase/gooncode/New() + ..() + occupant=new /obj/item/toy/gooncode(src) + locked=1 + req_access=list(access_captain) + update_icon() + +/obj/structure/displaycase/lamarr/New() + ..() + occupant=new /obj/item/clothing/mask/facehugger/lamarr(src) + locked=1 + req_access=list(access_rd) + update_icon() + +/obj/structure/displaycase/examine(mob/user) + ..() + var/msg = "Peering through the glass, you see that it contains:" + if(occupant) + msg+= "\icon[occupant] \A [occupant]" + else + msg+= "Nothing." + to_chat(user, msg) + +/obj/structure/displaycase/proc/dump() + if(occupant) + occupant.loc=get_turf(src) + occupant=null + occupant_overlay=null + +/obj/structure/displaycase/ex_act(severity) + switch(severity) + if (1) + getFromPool(/obj/item/weapon/shard, loc) + if (occupant) + dump() + qdel(src) + if (2) + if (prob(50)) + src.health -= 15 + src.healthcheck() + if (3) + if (prob(50)) + src.health -= 5 + src.healthcheck() + + +/obj/structure/displaycase/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + src.healthcheck() + return + + +/obj/structure/displaycase/blob_act() + if (prob(75)) + getFromPool(/obj/item/weapon/shard, loc) + if(occupant) dump() + qdel(src) + +/obj/structure/displaycase/proc/healthcheck() + if (src.health <= 0) + if (!( src.destroyed )) + src.density = 0 + src.destroyed = 1 + getFromPool(/obj/item/weapon/shard, loc) + playsound(get_turf(src), "shatter", 70, 1) + update_icon() + else + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + return + +/obj/structure/displaycase/update_icon() + if(src.destroyed) + src.icon_state = "glassbox2b" + else + src.icon_state = "glassbox2[locked]" + overlays = 0 + if(occupant) + var/icon/occupant_icon=getFlatIcon(occupant) + occupant_icon.Scale(19,19) + occupant_overlay = image(occupant_icon) + occupant_overlay.pixel_x=8 + occupant_overlay.pixel_y=8 + if(locked) + occupant_overlay.alpha=128//ChangeOpacity(0.5) + //underlays += occupant_overlay + overlays += occupant_overlay + return + + +/obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I=W + if(!check_access(I)) + to_chat(user, "Access denied.") + return + locked = !locked + if(!locked) + to_chat(user, "\icon[src] \The [src] clicks as locks release, and it slowly opens for you.") + else + to_chat(user, "\icon[src] You close \the [src] and swipe your card, locking it.") + update_icon() + else if(istype(W, /obj/item/weapon/crowbar) && (!locked || destroyed)) + user.visible_message("[user.name] pries \the [src] apart.", \ + "You pry \the [src] apart.", \ + "You hear something pop.") + var/turf/T=get_turf(src) + playsound(T, 'sound/items/Crowbar.ogg', 50, 1) + dump() + var/obj/item/weapon/circuitboard/airlock/C=circuit + if(!C) + C=new (src) + C.one_access=!(req_access && req_access.len>0) + if(!C.one_access) + C.conf_access=req_access + else + C.conf_access=req_one_access + if(!destroyed) + var/obj/structure/displaycase_frame/F=new(T) + F.state=1 + F.circuit=C + F.circuit.loc=F + F.update_icon() + else + C.loc=T + circuit=null + new /obj/machinery/constructable_frame/machine_frame(T) + qdel(src) + else if(user.a_intent == I_HURT) + user.delayNextAttack(8) + src.health -= W.force + src.healthcheck() + ..() + else + if(locked) + to_chat(user, "It's locked, you can't put anything into it.") + else if(!occupant) + if(user.drop_item(W, src)) + to_chat(user, "You insert \the [W] into \the [src], and it floats as the hoverfield activates.") + occupant=W + update_icon() + +/obj/structure/displaycase/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/displaycase/proc/getPrint(mob/user as mob) + return md5(user:dna:uni_identity) + +/obj/structure/displaycase/attack_hand(mob/user as mob) + if (destroyed) + if(occupant) + dump() + to_chat(user, "You smash your fist into the delicate electronics at the bottom of the case, and deactivate the hoverfield permanently.") + src.add_fingerprint(user) + update_icon() + else + if(user.a_intent == I_HURT) + user.delayNextAttack(8) + user.visible_message("[user.name] kicks \the [src]!", \ + "You kick \the [src]!", \ + "You hear glass crack.") + src.health -= 2 + healthcheck() + else if(!locked) + if(ishuman(user)) + if(!ue) + to_chat(user, "You press your thumb against the fingerprint scanner, registering your identity with the case.") + ue = getPrint(user) + return + if(ue!=getPrint(user)) + to_chat(user, "Access denied.") + return + + to_chat(user, "You press your thumb against the fingerprint scanner, and deactivate the hoverfield built into the case.") + if(occupant) + dump() + update_icon() + else + to_chat(src, "\icon[src] \The [src] is empty!") + else + user.delayNextAttack(10) // prevent spam + user.visible_message("[user.name] gently runs their hands over \the [src] in appreciation of its contents.", \ + "You gently run your hands over \the [src] in appreciation of its contents.", \ + "You hear someone streaking glass with their greasy hands.") diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 42dfeaf9cc3..2a7c6454726 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -1,351 +1,351 @@ -/obj/structure/door_assembly - icon = 'icons/obj/doors/door_assembly.dmi' - - name = "Airlock Assembly" - icon_state = "door_as_0" - anchored = 0 - density = 1 - var/state = 0 - var/base_icon_state = "" - var/base_name = "Airlock" - var/obj/item/weapon/circuitboard/airlock/electronics = null - var/airlock_type = "" //the type path of the airlock once completed - var/glass_type = "/glass" - var/glass = 0 // 0 = glass can be installed. -1 = glass can't be installed. 1 = glass is already installed. Text = mineral plating is installed instead. - var/created_name = null - var/busy = 0 - -/obj/structure/door_assembly/New() - ..() - update_state() - -/obj/structure/door_assembly/door_assembly_com - base_icon_state = "com" - base_name = "Command Airlock" - glass_type = "/glass_command" - airlock_type = "/command" - -/obj/structure/door_assembly/door_assembly_sec - base_icon_state = "sec" - base_name = "Security Airlock" - glass_type = "/glass_security" - airlock_type = "/security" - -/obj/structure/door_assembly/door_assembly_eng - base_icon_state = "eng" - base_name = "Engineering Airlock" - glass_type = "/glass_engineering" - airlock_type = "/engineering" - -/obj/structure/door_assembly/door_assembly_min - base_icon_state = "min" - base_name = "Mining Airlock" - glass_type = "/glass_mining" - airlock_type = "/mining" - -/obj/structure/door_assembly/door_assembly_atmo - base_icon_state = "atmo" - base_name = "Atmospherics Airlock" - glass_type = "/glass_atmos" - airlock_type = "/atmos" - -/obj/structure/door_assembly/door_assembly_research - base_icon_state = "res" - base_name = "Research Airlock" - glass_type = "/glass_research" - airlock_type = "/research" - -/obj/structure/door_assembly/door_assembly_science - base_icon_state = "sci" - base_name = "Science Airlock" - glass_type = "/glass_science" - airlock_type = "/science" - -/obj/structure/door_assembly/door_assembly_med - base_icon_state = "med" - base_name = "Medical Airlock" - glass_type = "/glass_medical" - airlock_type = "/medical" - -/obj/structure/door_assembly/door_assembly_mai - base_icon_state = "mai" - base_name = "Maintenance Airlock" - airlock_type = "/maintenance" - glass = -1 - -/obj/structure/door_assembly/door_assembly_ext - base_icon_state = "ext" - base_name = "External Airlock" - airlock_type = "/external" - glass = -1 - -/obj/structure/door_assembly/door_assembly_fre - base_icon_state = "fre" - base_name = "Freezer Airlock" - airlock_type = "/freezer" - glass = -1 - -/obj/structure/door_assembly/door_assembly_hatch - base_icon_state = "hatch" - base_name = "Airtight Hatch" - airlock_type = "/hatch" - glass = -1 - -/obj/structure/door_assembly/door_assembly_mhatch - base_icon_state = "mhatch" - base_name = "Maintenance Hatch" - airlock_type = "/maintenance_hatch" - glass = -1 - -/obj/structure/door_assembly/door_assembly_highsecurity // Borrowing this until WJohnston makes sprites for the assembly - base_icon_state = "highsec" - base_name = "High Security Airlock" - airlock_type = "/highsecurity" - glass = -1 - -/obj/structure/door_assembly/door_assembly_vault - base_icon_state = "vault" - base_name = "Vault" - airlock_type = "/vault" - glass = -1 - -/obj/structure/door_assembly/multi_tile/ - icon = 'icons/obj/doors/door_assembly2x1.dmi' - dir = EAST - var/width = 1 - - /*Temporary until we get sprites. - glass_type = "/multi_tile/glass" - airlock_type = "/multi_tile/maint" - glass = 1*/ - - - base_icon_state = "g" //Remember to delete this line when reverting "glass" var to 1. - airlock_type = "/multi_tile/glass" - glass = -1 //To prevent bugs in deconstruction process. - -/obj/structure/door_assembly/multi_tile/New() - if(dir in list(EAST, WEST)) - bound_width = width * world.icon_size - bound_height = world.icon_size - else - bound_width = world.icon_size - bound_height = width * world.icon_size - ..() - -/obj/structure/door_assembly/multi_tile/Move() - . = ..() - if(dir in list(EAST, WEST)) - bound_width = width * world.icon_size - bound_height = world.icon_size - else - bound_width = world.icon_size - bound_height = width * world.icon_size - - - -/obj/structure/door_assembly/attackby(obj/item/W as obj, mob/user as mob) - if(busy) return - - if(istype(W, /obj/item/weapon/pen)) - var/t = copytext(stripped_input(user, "Enter the name for the door.", src.name, src.created_name),1,MAX_NAME_LEN) - if(!t) return - if(!in_range(src, usr) && src.loc != usr) return - created_name = t - return - - if (istype(W, /obj/item/weapon/weldingtool) && ( (istext(glass)) || (glass == 1) || (!anchored) )) - var/obj/item/weapon/weldingtool/WT = W - - if (WT.remove_fuel(0, user)) - busy = TRUE - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) - - if (istext(glass)) - user.visible_message("[user] welds the [glass] plating off the airlock assembly.", "You start to weld the [glass] plating off the airlock assembly.") - - if (do_after(user, src, 40)) - if (!src || !WT.isOn()) - busy = FALSE - return - +/obj/structure/door_assembly + icon = 'icons/obj/doors/door_assembly.dmi' + + name = "Airlock Assembly" + icon_state = "door_as_0" + anchored = 0 + density = 1 + var/state = 0 + var/base_icon_state = "" + var/base_name = "Airlock" + var/obj/item/weapon/circuitboard/airlock/electronics = null + var/airlock_type = "" //the type path of the airlock once completed + var/glass_type = "/glass" + var/glass = 0 // 0 = glass can be installed. -1 = glass can't be installed. 1 = glass is already installed. Text = mineral plating is installed instead. + var/created_name = null + var/busy = 0 + +/obj/structure/door_assembly/New() + ..() + update_state() + +/obj/structure/door_assembly/door_assembly_com + base_icon_state = "com" + base_name = "Command Airlock" + glass_type = "/glass_command" + airlock_type = "/command" + +/obj/structure/door_assembly/door_assembly_sec + base_icon_state = "sec" + base_name = "Security Airlock" + glass_type = "/glass_security" + airlock_type = "/security" + +/obj/structure/door_assembly/door_assembly_eng + base_icon_state = "eng" + base_name = "Engineering Airlock" + glass_type = "/glass_engineering" + airlock_type = "/engineering" + +/obj/structure/door_assembly/door_assembly_min + base_icon_state = "min" + base_name = "Mining Airlock" + glass_type = "/glass_mining" + airlock_type = "/mining" + +/obj/structure/door_assembly/door_assembly_atmo + base_icon_state = "atmo" + base_name = "Atmospherics Airlock" + glass_type = "/glass_atmos" + airlock_type = "/atmos" + +/obj/structure/door_assembly/door_assembly_research + base_icon_state = "res" + base_name = "Research Airlock" + glass_type = "/glass_research" + airlock_type = "/research" + +/obj/structure/door_assembly/door_assembly_science + base_icon_state = "sci" + base_name = "Science Airlock" + glass_type = "/glass_science" + airlock_type = "/science" + +/obj/structure/door_assembly/door_assembly_med + base_icon_state = "med" + base_name = "Medical Airlock" + glass_type = "/glass_medical" + airlock_type = "/medical" + +/obj/structure/door_assembly/door_assembly_mai + base_icon_state = "mai" + base_name = "Maintenance Airlock" + airlock_type = "/maintenance" + glass = -1 + +/obj/structure/door_assembly/door_assembly_ext + base_icon_state = "ext" + base_name = "External Airlock" + airlock_type = "/external" + glass = -1 + +/obj/structure/door_assembly/door_assembly_fre + base_icon_state = "fre" + base_name = "Freezer Airlock" + airlock_type = "/freezer" + glass = -1 + +/obj/structure/door_assembly/door_assembly_hatch + base_icon_state = "hatch" + base_name = "Airtight Hatch" + airlock_type = "/hatch" + glass = -1 + +/obj/structure/door_assembly/door_assembly_mhatch + base_icon_state = "mhatch" + base_name = "Maintenance Hatch" + airlock_type = "/maintenance_hatch" + glass = -1 + +/obj/structure/door_assembly/door_assembly_highsecurity // Borrowing this until WJohnston makes sprites for the assembly + base_icon_state = "highsec" + base_name = "High Security Airlock" + airlock_type = "/highsecurity" + glass = -1 + +/obj/structure/door_assembly/door_assembly_vault + base_icon_state = "vault" + base_name = "Vault" + airlock_type = "/vault" + glass = -1 + +/obj/structure/door_assembly/multi_tile/ + icon = 'icons/obj/doors/door_assembly2x1.dmi' + dir = EAST + var/width = 1 + + /*Temporary until we get sprites. + glass_type = "/multi_tile/glass" + airlock_type = "/multi_tile/maint" + glass = 1*/ + + + base_icon_state = "g" //Remember to delete this line when reverting "glass" var to 1. + airlock_type = "/multi_tile/glass" + glass = -1 //To prevent bugs in deconstruction process. + +/obj/structure/door_assembly/multi_tile/New() + if(dir in list(EAST, WEST)) + bound_width = width * world.icon_size + bound_height = world.icon_size + else + bound_width = world.icon_size + bound_height = width * world.icon_size + ..() + +/obj/structure/door_assembly/multi_tile/Move() + . = ..() + if(dir in list(EAST, WEST)) + bound_width = width * world.icon_size + bound_height = world.icon_size + else + bound_width = world.icon_size + bound_height = width * world.icon_size + + + +/obj/structure/door_assembly/attackby(obj/item/W as obj, mob/user as mob) + if(busy) return + + if(istype(W, /obj/item/weapon/pen)) + var/t = copytext(stripped_input(user, "Enter the name for the door.", src.name, src.created_name),1,MAX_NAME_LEN) + if(!t) return + if(!in_range(src, usr) && src.loc != usr) return + created_name = t + return + + if (istype(W, /obj/item/weapon/weldingtool) && ( (istext(glass)) || (glass == 1) || (!anchored) )) + var/obj/item/weapon/weldingtool/WT = W + + if (WT.remove_fuel(0, user)) + busy = TRUE + playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + + if (istext(glass)) + user.visible_message("[user] welds the [glass] plating off the airlock assembly.", "You start to weld the [glass] plating off the airlock assembly.") + + if (do_after(user, src, 40)) + if (!src || !WT.isOn()) + busy = FALSE + return + to_chat(user, "You welded the [glass] plating off!") - - var/M = text2path("/obj/item/stack/sheet/mineral/[glass]") - new M(src.loc, 2) - - glass = 0 - else if (glass == 1) - user.visible_message("[user] welds the glass panel out of the airlock assembly.", "You start to weld the glass panel out of the airlock assembly.") - - if (do_after(user, src, 40)) - if (!src || !WT.isOn()) - busy = FALSE - return - + + var/M = text2path("/obj/item/stack/sheet/mineral/[glass]") + new M(src.loc, 2) + + glass = 0 + else if (glass == 1) + user.visible_message("[user] welds the glass panel out of the airlock assembly.", "You start to weld the glass panel out of the airlock assembly.") + + if (do_after(user, src, 40)) + if (!src || !WT.isOn()) + busy = FALSE + return + to_chat(user, "You welded the glass panel out!") - new /obj/item/stack/sheet/glass/rglass(src.loc) - glass = 0 - else if (!anchored) - user.visible_message("[user] dissassembles the airlock assembly.", "You start to dissassemble the airlock assembly.") - - if (do_after(user, src, 40)) - if (!src || !WT.isOn()) - busy = FALSE - return - + new /obj/item/stack/sheet/glass/rglass(src.loc) + glass = 0 + else if (!anchored) + user.visible_message("[user] dissassembles the airlock assembly.", "You start to dissassemble the airlock assembly.") + + if (do_after(user, src, 40)) + if (!src || !WT.isOn()) + busy = FALSE + return + to_chat(user, "You dissasembled the airlock assembly!") - - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 4 - - qdel (src) - - busy = FALSE - else + + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 4 + + qdel (src) + + busy = FALSE + else to_chat(user, "You need more welding fuel.") - return - else if(istype(W, /obj/item/weapon/wrench) && state == 0) - busy = 1 - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - if(anchored) - user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor.") - else - user.visible_message("[user] secures the airlock assembly to the floor.", "You start to secure the airlock assembly to the floor.") - - if(do_after(user, src, 40)) - if(!src) return + return + else if(istype(W, /obj/item/weapon/wrench) && state == 0) + busy = 1 + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + if(anchored) + user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor.") + else + user.visible_message("[user] secures the airlock assembly to the floor.", "You start to secure the airlock assembly to the floor.") + + if(do_after(user, src, 40)) + if(!src) return to_chat(user, "You [anchored? "un" : ""]secured the airlock assembly!") - anchored = !anchored - busy = 0 - - else if(istype(W, /obj/item/stack/cable_coil) && state == 0 && anchored ) - busy = 1 - var/obj/item/stack/cable_coil/coil = W - user.visible_message("[user] wires the airlock assembly.", "You start to wire the airlock assembly.") - if(do_after(user, src, 40)) - if(!src) return - coil.use(1) - src.state = 1 + anchored = !anchored + busy = 0 + + else if(istype(W, /obj/item/stack/cable_coil) && state == 0 && anchored ) + busy = 1 + var/obj/item/stack/cable_coil/coil = W + user.visible_message("[user] wires the airlock assembly.", "You start to wire the airlock assembly.") + if(do_after(user, src, 40)) + if(!src) return + coil.use(1) + src.state = 1 to_chat(user, "You wire the Airlock!") - busy = 0 - - else if(istype(W, /obj/item/weapon/wirecutters) && state == 1 ) - busy = 1 - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) - user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.") - - if(do_after(user, src, 40)) - if(!src) return + busy = 0 + + else if(istype(W, /obj/item/weapon/wirecutters) && state == 1 ) + busy = 1 + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) + user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.") + + if(do_after(user, src, 40)) + if(!src) return to_chat(user, "You cut the airlock wires.!") - new/obj/item/stack/cable_coil(src.loc, 1) - src.state = 0 - busy = 0 - - else if(istype(W, /obj/item/weapon/circuitboard/airlock) && state == 1 && W:icon_state != "door_electronics_smoked") - busy = 1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) - user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.") - user.drop_item(W, src, force_drop = 1) - - if(do_after(user, src, 40)) - if(!src) return + new/obj/item/stack/cable_coil(src.loc, 1) + src.state = 0 + busy = 0 + + else if(istype(W, /obj/item/weapon/circuitboard/airlock) && state == 1 && W:icon_state != "door_electronics_smoked") + busy = 1 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.") + user.drop_item(W, src, force_drop = 1) + + if(do_after(user, src, 40)) + if(!src) return to_chat(user, "You installed the airlock electronics!") - src.state = 2 - src.name = "Near finished Airlock Assembly" - src.electronics = W - else - W.loc = src.loc - busy = 0 - - else if(istype(W, /obj/item/weapon/crowbar) && state == 2 ) - busy = 1 - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to install electronics into the airlock assembly.") - - if(do_after(user, src, 40)) - if(!src) return + src.state = 2 + src.name = "Near finished Airlock Assembly" + src.electronics = W + else + W.loc = src.loc + busy = 0 + + else if(istype(W, /obj/item/weapon/crowbar) && state == 2 ) + busy = 1 + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to install electronics into the airlock assembly.") + + if(do_after(user, src, 40)) + if(!src) return to_chat(user, "You removed the airlock electronics!") - src.state = 1 - src.name = "Wired Airlock Assembly" - var/obj/item/weapon/circuitboard/airlock/ae - if (!electronics) - ae = new/obj/item/weapon/circuitboard/airlock( src.loc ) - else - ae = electronics - electronics = null - ae.loc = src.loc - busy = 0 - - else if(istype(W, /obj/item/stack/sheet) && !glass) - var/obj/item/stack/sheet/S = W - if (S) - if (S.amount>=1) - busy = 1 - if(istype(S, /obj/item/stack/sheet/glass/rglass)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") - if(do_after(user, src, 40)) + src.state = 1 + src.name = "Wired Airlock Assembly" + var/obj/item/weapon/circuitboard/airlock/ae + if (!electronics) + ae = new/obj/item/weapon/circuitboard/airlock( src.loc ) + else + ae = electronics + electronics = null + ae.loc = src.loc + busy = 0 + + else if(istype(W, /obj/item/stack/sheet) && !glass) + var/obj/item/stack/sheet/S = W + if (S) + if (S.amount>=1) + busy = 1 + if(istype(S, /obj/item/stack/sheet/glass/rglass)) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") + if(do_after(user, src, 40)) to_chat(user, "You installed reinforced glass windows into the airlock assembly!") - S.use(1) - glass = 1 - else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype) - var/M = S.sheettype - if(S.amount>=2) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") - if(do_after(user, src, 40)) + S.use(1) + glass = 1 + else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype) + var/M = S.sheettype + if(S.amount>=2) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") + if(do_after(user, src, 40)) to_chat(user, "You installed [M] plating into the airlock assembly!") - S.use(2) - glass = "[M]" - busy = 0 - - else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 ) - busy = 1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + S.use(2) + glass = "[M]" + busy = 0 + + else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 ) + busy = 1 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) to_chat(user, "Now finishing the airlock.") - - if(do_after(user, src, 40)) - if(!src) return + + if(do_after(user, src, 40)) + if(!src) return to_chat(user, "You finish the airlock!") - var/path - if(istext(glass)) - path = text2path("/obj/machinery/door/airlock/[glass]") - else if (glass == 1) - path = text2path("/obj/machinery/door/airlock[glass_type]") - else - path = text2path("/obj/machinery/door/airlock[airlock_type]") - var/obj/machinery/door/airlock/door = new path(src.loc) - door.assembly_type = type - door.electronics = src.electronics - door.fingerprints += src.fingerprints - door.fingerprintshidden += src.fingerprintshidden - door.fingerprintslast = user.ckey - if(src.electronics.one_access) - door.req_access = null - door.req_one_access = src.electronics.conf_access - else - door.req_access = src.electronics.conf_access - if(created_name) - door.name = created_name - else - door.name = "[istext(glass) ? "[glass] airlock" : base_name]" - src.electronics.loc = door - qdel(src) - busy = 0 - else - ..() - update_state() - -/obj/structure/door_assembly/proc/update_state() - icon_state = "door_as_[glass == 1 ? "g" : ""][istext(glass) ? glass : base_icon_state][state]" - name = "" - switch (state) - if(0) - if (anchored) - name = "Secured " - if(1) - name = "Wired " - if(2) - name = "Near Finished " + var/path + if(istext(glass)) + path = text2path("/obj/machinery/door/airlock/[glass]") + else if (glass == 1) + path = text2path("/obj/machinery/door/airlock[glass_type]") + else + path = text2path("/obj/machinery/door/airlock[airlock_type]") + var/obj/machinery/door/airlock/door = new path(src.loc) + door.assembly_type = type + door.electronics = src.electronics + door.fingerprints += src.fingerprints + door.fingerprintshidden += src.fingerprintshidden + door.fingerprintslast = user.ckey + if(src.electronics.one_access) + door.req_access = null + door.req_one_access = src.electronics.conf_access + else + door.req_access = src.electronics.conf_access + if(created_name) + door.name = created_name + else + door.name = "[istext(glass) ? "[glass] airlock" : base_name]" + src.electronics.loc = door + qdel(src) + busy = 0 + else + ..() + update_state() + +/obj/structure/door_assembly/proc/update_state() + icon_state = "door_as_[glass == 1 ? "g" : ""][istext(glass) ? glass : base_icon_state][state]" + name = "" + switch (state) + if(0) + if (anchored) + name = "Secured " + if(1) + name = "Wired " + if(2) + name = "Near Finished " name += "[glass == 1 ? "Window " : ""][istext(glass) ? "[glass] Airlock" : base_name] Assembly" \ No newline at end of file diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 947388f0af2..141dbb4fcbe 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -1,369 +1,369 @@ -/* - * False Walls - */ - -// Minimum pressure difference to fail building falsewalls. -// Also affects admin alerts. -#define FALSEDOOR_MAX_PRESSURE_DIFF 25.0 - -/** -* Gets the highest and lowest pressures from the tiles in cardinal directions -* around us, then checks the difference. -*/ -/proc/getOPressureDifferential(var/turf/loc) - var/minp=16777216; - var/maxp=0; - for(var/dir in cardinal) - var/turf/simulated/T=get_turf(get_step(loc,dir)) - var/cp=0 - if(T && istype(T) && T.zone) - var/datum/gas_mixture/environment = T.return_air() - cp = environment.return_pressure() - else - if(istype(T,/turf/simulated)) - continue - if(cpmaxp)maxp=cp - return abs(minp-maxp) - -// Checks pressure here vs. around us. -/proc/performFalseWallPressureCheck(var/turf/loc) - var/turf/simulated/lT=loc - if(!istype(lT) || !lT.zone) - return 0 - var/datum/gas_mixture/myenv=lT.return_air() - var/pressure=myenv.return_pressure() - - for(var/dir in cardinal) - var/turf/simulated/T=get_turf(get_step(loc,dir)) - if(T && istype(T) && T.zone) - var/datum/gas_mixture/environment = T.return_air() - var/pdiff = abs(pressure - environment.return_pressure()) - if(pdiff > FALSEDOOR_MAX_PRESSURE_DIFF) - return pdiff - return 0 - -/proc/performWallPressureCheck(var/turf/loc) - var/pdiff = getOPressureDifferential(loc) - if(pdiff > FALSEDOOR_MAX_PRESSURE_DIFF) - return pdiff - return 0 - -/client/proc/pdiff() - set name = "Get PDiff" - set category = "Debug" - - if(!mob || !holder) - return - var/turf/T = mob.loc - - if (!( istype(T, /turf) )) - return - - var/pdiff = getOPressureDifferential(T) - var/fwpcheck=performFalseWallPressureCheck(T) - var/wpcheck=performWallPressureCheck(T) - +/* + * False Walls + */ + +// Minimum pressure difference to fail building falsewalls. +// Also affects admin alerts. +#define FALSEDOOR_MAX_PRESSURE_DIFF 25.0 + +/** +* Gets the highest and lowest pressures from the tiles in cardinal directions +* around us, then checks the difference. +*/ +/proc/getOPressureDifferential(var/turf/loc) + var/minp=16777216; + var/maxp=0; + for(var/dir in cardinal) + var/turf/simulated/T=get_turf(get_step(loc,dir)) + var/cp=0 + if(T && istype(T) && T.zone) + var/datum/gas_mixture/environment = T.return_air() + cp = environment.return_pressure() + else + if(istype(T,/turf/simulated)) + continue + if(cpmaxp)maxp=cp + return abs(minp-maxp) + +// Checks pressure here vs. around us. +/proc/performFalseWallPressureCheck(var/turf/loc) + var/turf/simulated/lT=loc + if(!istype(lT) || !lT.zone) + return 0 + var/datum/gas_mixture/myenv=lT.return_air() + var/pressure=myenv.return_pressure() + + for(var/dir in cardinal) + var/turf/simulated/T=get_turf(get_step(loc,dir)) + if(T && istype(T) && T.zone) + var/datum/gas_mixture/environment = T.return_air() + var/pdiff = abs(pressure - environment.return_pressure()) + if(pdiff > FALSEDOOR_MAX_PRESSURE_DIFF) + return pdiff + return 0 + +/proc/performWallPressureCheck(var/turf/loc) + var/pdiff = getOPressureDifferential(loc) + if(pdiff > FALSEDOOR_MAX_PRESSURE_DIFF) + return pdiff + return 0 + +/client/proc/pdiff() + set name = "Get PDiff" + set category = "Debug" + + if(!mob || !holder) + return + var/turf/T = mob.loc + + if (!( istype(T, /turf) )) + return + + var/pdiff = getOPressureDifferential(T) + var/fwpcheck=performFalseWallPressureCheck(T) + var/wpcheck=performWallPressureCheck(T) + to_chat(src, "Pressure Differential (cardinals): [pdiff]") to_chat(src, "FWPCheck: [fwpcheck]") to_chat(src, "WPCheck: [wpcheck]") - -/obj/structure/falsewall - name = "wall" - desc = "A huge chunk of metal used to seperate rooms." - anchored = 1 - icon = 'icons/turf/walls.dmi' - var/mineral = "metal" - var/opening = 0 - - // WHY DO WE SMOOTH WITH FALSE R-WALLS WHEN WE DON'T SMOOTH WITH REAL R-WALLS. - canSmoothWith = "/turf/simulated/wall=0&/obj/structure/falsewall=0&/obj/structure/falserwall=0" - -/obj/structure/falsewall/New() - ..() - relativewall() - relativewall_neighbours() - -/obj/structure/falsewall/Destroy() - - var/temploc = src.loc - - spawn(10) - for(var/turf/simulated/wall/W in range(temploc,1)) - W.relativewall() - - for(var/obj/structure/falsewall/W in range(temploc,1)) - W.relativewall() - - for(var/obj/structure/falserwall/W in range(temploc,1)) - W.relativewall() - ..() - - -/obj/structure/falsewall/relativewall() - - if(!density) - icon_state = "[mineral]fwall_open" - return - - var/junction=findSmoothingNeighbors() - icon_state = "[mineral][junction]" - -/obj/structure/falsewall/attack_ai(mob/user as mob) - if(isMoMMI(user)) - src.add_hiddenprint(user) - attack_hand(user) - -/obj/structure/falsewall/attack_hand(mob/user as mob) - if(opening) - return - - if(density) - opening = 1 - icon_state = "[mineral]fwall_open" - flick("[mineral]fwall_opening", src) - sleep(15) - src.density = 0 - set_opacity(0) - opening = 0 - else - opening = 1 - flick("[mineral]fwall_closing", src) - icon_state = "[mineral]0" - density = 1 - sleep(15) - set_opacity(1) - src.relativewall() - opening = 0 - -/obj/structure/falsewall/update_icon()//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open - ..() - if(density) - icon_state = "[mineral]0" - src.relativewall() - else - icon_state = "[mineral]fwall_open" - -/obj/structure/falsewall/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(opening) + +/obj/structure/falsewall + name = "wall" + desc = "A huge chunk of metal used to seperate rooms." + anchored = 1 + icon = 'icons/turf/walls.dmi' + var/mineral = "metal" + var/opening = 0 + + // WHY DO WE SMOOTH WITH FALSE R-WALLS WHEN WE DON'T SMOOTH WITH REAL R-WALLS. + canSmoothWith = "/turf/simulated/wall=0&/obj/structure/falsewall=0&/obj/structure/falserwall=0" + +/obj/structure/falsewall/New() + ..() + relativewall() + relativewall_neighbours() + +/obj/structure/falsewall/Destroy() + + var/temploc = src.loc + + spawn(10) + for(var/turf/simulated/wall/W in range(temploc,1)) + W.relativewall() + + for(var/obj/structure/falsewall/W in range(temploc,1)) + W.relativewall() + + for(var/obj/structure/falserwall/W in range(temploc,1)) + W.relativewall() + ..() + + +/obj/structure/falsewall/relativewall() + + if(!density) + icon_state = "[mineral]fwall_open" + return + + var/junction=findSmoothingNeighbors() + icon_state = "[mineral][junction]" + +/obj/structure/falsewall/attack_ai(mob/user as mob) + if(isMoMMI(user)) + src.add_hiddenprint(user) + attack_hand(user) + +/obj/structure/falsewall/attack_hand(mob/user as mob) + if(opening) + return + + if(density) + opening = 1 + icon_state = "[mineral]fwall_open" + flick("[mineral]fwall_opening", src) + sleep(15) + src.density = 0 + set_opacity(0) + opening = 0 + else + opening = 1 + flick("[mineral]fwall_closing", src) + icon_state = "[mineral]0" + density = 1 + sleep(15) + set_opacity(1) + src.relativewall() + opening = 0 + +/obj/structure/falsewall/update_icon()//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open + ..() + if(density) + icon_state = "[mineral]0" + src.relativewall() + else + icon_state = "[mineral]fwall_open" + +/obj/structure/falsewall/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(opening) to_chat(user, "You must wait until the door has stopped moving.") - return - - if(density) - var/turf/T = get_turf(src) - if(T.density) + return + + if(density) + var/turf/T = get_turf(src) + if(T.density) to_chat(user, "The wall is blocked!") - return - if(istype(W, /obj/item/weapon/screwdriver)) - user.visible_message("[user] tightens some bolts on the wall.", "You tighten the bolts on the wall.") - if(!mineral || mineral == "metal") - T.ChangeTurf(/turf/simulated/wall) - else - T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) - qdel(src) - - if( istype(W, /obj/item/weapon/weldingtool) ) - var/obj/item/weapon/weldingtool/WT = W - if( WT:welding ) - if(!mineral) - T.ChangeTurf(/turf/simulated/wall) - else - T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) - if(mineral != "plasma")//Stupid shit keeps me from pushing the attackby() to plasma walls -Sieve - T = get_turf(src) - T.attackby(W,user) - qdel(src) - else + return + if(istype(W, /obj/item/weapon/screwdriver)) + user.visible_message("[user] tightens some bolts on the wall.", "You tighten the bolts on the wall.") + if(!mineral || mineral == "metal") + T.ChangeTurf(/turf/simulated/wall) + else + T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) + qdel(src) + + if( istype(W, /obj/item/weapon/weldingtool) ) + var/obj/item/weapon/weldingtool/WT = W + if( WT:welding ) + if(!mineral) + T.ChangeTurf(/turf/simulated/wall) + else + T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) + if(mineral != "plasma")//Stupid shit keeps me from pushing the attackby() to plasma walls -Sieve + T = get_turf(src) + T.attackby(W,user) + qdel(src) + else to_chat(user, "You can't reach, close it first!") - - if( istype(W, /obj/item/weapon/pickaxe) ) - var/obj/item/weapon/pickaxe/used_pick = W - if(!(used_pick.diggables & DIG_WALLS)) - return - var/turf/T = get_turf(src) - if(!mineral) - T.ChangeTurf(/turf/simulated/wall) - else - T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) - if(mineral != "plasma") - T = get_turf(src) - T.attackby(W,user) - qdel(src) - -/obj/structure/falsewall/update_icon()//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open - ..() - if(density) - icon_state = "[mineral]0" - src.relativewall() - else - icon_state = "[mineral]fwall_open" - -/* - * False R-Walls - */ - -/obj/structure/falserwall - name = "reinforced wall" - desc = "A huge chunk of reinforced metal used to seperate rooms." - icon = 'icons/turf/walls.dmi' - icon_state = "r_wall" - density = 1 - opacity = 1 - anchored = 1 - var/mineral = "metal" - var/opening = 0 - - // WHY DO WE SMOOTH WITH FALSE R-WALLS WHEN WE DON'T SMOOTH WITH REAL R-WALLS. - canSmoothWith = "/turf/simulated/wall=0&/obj/structure/falsewall=0&/obj/structure/falserwall=0" - -/obj/structure/falserwall/New() - relativewall_neighbours() - ..() - - -/obj/structure/falserwall/attack_ai(mob/user as mob) - if(isMoMMI(user)) - src.add_hiddenprint(user) - attack_hand(user) - -/obj/structure/falserwall/attack_hand(mob/user as mob) - if(opening) - return - - if(density) - opening = 1 - // Open wall - icon_state = "frwall_open" - flick("frwall_opening", src) - sleep(15) - density = 0 - set_opacity(0) - opening = 0 - else - opening = 1 - icon_state = "r_wall" - flick("frwall_closing", src) - density = 1 - sleep(15) - set_opacity(1) - relativewall() - opening = 0 - -/obj/structure/falserwall/relativewall() - - if(!density) - icon_state = "frwall_open" - return - var/junction=findSmoothingNeighbors() - icon_state = "rwall[junction]" - -/obj/structure/falserwall/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(opening) + + if( istype(W, /obj/item/weapon/pickaxe) ) + var/obj/item/weapon/pickaxe/used_pick = W + if(!(used_pick.diggables & DIG_WALLS)) + return + var/turf/T = get_turf(src) + if(!mineral) + T.ChangeTurf(/turf/simulated/wall) + else + T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) + if(mineral != "plasma") + T = get_turf(src) + T.attackby(W,user) + qdel(src) + +/obj/structure/falsewall/update_icon()//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open + ..() + if(density) + icon_state = "[mineral]0" + src.relativewall() + else + icon_state = "[mineral]fwall_open" + +/* + * False R-Walls + */ + +/obj/structure/falserwall + name = "reinforced wall" + desc = "A huge chunk of reinforced metal used to seperate rooms." + icon = 'icons/turf/walls.dmi' + icon_state = "r_wall" + density = 1 + opacity = 1 + anchored = 1 + var/mineral = "metal" + var/opening = 0 + + // WHY DO WE SMOOTH WITH FALSE R-WALLS WHEN WE DON'T SMOOTH WITH REAL R-WALLS. + canSmoothWith = "/turf/simulated/wall=0&/obj/structure/falsewall=0&/obj/structure/falserwall=0" + +/obj/structure/falserwall/New() + relativewall_neighbours() + ..() + + +/obj/structure/falserwall/attack_ai(mob/user as mob) + if(isMoMMI(user)) + src.add_hiddenprint(user) + attack_hand(user) + +/obj/structure/falserwall/attack_hand(mob/user as mob) + if(opening) + return + + if(density) + opening = 1 + // Open wall + icon_state = "frwall_open" + flick("frwall_opening", src) + sleep(15) + density = 0 + set_opacity(0) + opening = 0 + else + opening = 1 + icon_state = "r_wall" + flick("frwall_closing", src) + density = 1 + sleep(15) + set_opacity(1) + relativewall() + opening = 0 + +/obj/structure/falserwall/relativewall() + + if(!density) + icon_state = "frwall_open" + return + var/junction=findSmoothingNeighbors() + icon_state = "rwall[junction]" + +/obj/structure/falserwall/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(opening) to_chat(user, "You must wait until the door has stopped moving.") - return - - if(istype(W, /obj/item/weapon/screwdriver)) - var/turf/T = get_turf(src) - user.visible_message("[user] tightens some bolts on the r wall.", "You tighten the bolts on the wall.") - T.ChangeTurf(/turf/simulated/wall/r_wall) //Why not make rwall? - qdel(src) - - if( istype(W, /obj/item/weapon/weldingtool) ) - var/obj/item/weapon/weldingtool/WT = W - if( WT.remove_fuel(0,user) ) - var/turf/T = get_turf(src) - T.ChangeTurf(/turf/simulated/wall) - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - else if( istype(W, /obj/item/weapon/pickaxe) ) - var/obj/item/weapon/pickaxe/used_pick = W - if(!(used_pick.diggables & DIG_WALLS)) - return - var/turf/T = get_turf(src) - T.ChangeTurf(/turf/simulated/wall) - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - -/* - * Uranium Falsewalls - */ - -/obj/structure/falsewall/uranium - name = "uranium wall" - desc = "A wall with uranium plating. This is probably a bad idea." - icon_state = "" - mineral = "uranium" - var/active = null - var/last_event = 0 - -/obj/structure/falsewall/uranium/attackby(obj/item/weapon/W as obj, mob/user as mob) - radiate() - ..() - -/obj/structure/falsewall/uranium/attack_hand(mob/user as mob) - radiate() - ..() - -/obj/structure/falsewall/uranium/proc/radiate() - if(!active) - if(world.time > last_event+15) - active = 1 - for(var/mob/living/L in range(3,src)) - L.apply_effect(12,IRRADIATE,0) - for(var/turf/simulated/wall/mineral/uranium/T in range(3,src)) - T.radiate() - last_event = world.time - active = null - return - return -/* - * Other misc falsewall types - */ - -/obj/structure/falsewall/gold - name = "gold wall" - desc = "A wall with gold plating. Swag!" - icon_state = "" - mineral = "gold" - -/obj/structure/falsewall/silver - name = "silver wall" - desc = "A wall with silver plating. Shiny." - icon_state = "" - mineral = "silver" - -/obj/structure/falsewall/diamond - name = "diamond wall" - desc = "A wall with diamond plating. You monster." - icon_state = "" - mineral = "diamond" - -/obj/structure/falsewall/plasma - name = "plasma wall" - desc = "A wall with plasma plating. This is definitely a bad idea." - icon_state = "" - mineral = "plasma" - -/obj/structure/falsewall/plastic - name = "plastic wall" - desc = "A wall made of colorful plastic blocks attached together." - icon_state = "" - mineral = "plastic" - -//-----------wtf?-----------start -/obj/structure/falsewall/clown - name = "bananium wall" - desc = "A wall with bananium plating. Honk!" - icon_state = "" - mineral = "clown" - -/obj/structure/falsewall/sandstone - name = "sandstone wall" - desc = "A wall with sandstone plating." - icon_state = "" - mineral = "sandstone" -//------------wtf?------------end + return + + if(istype(W, /obj/item/weapon/screwdriver)) + var/turf/T = get_turf(src) + user.visible_message("[user] tightens some bolts on the r wall.", "You tighten the bolts on the wall.") + T.ChangeTurf(/turf/simulated/wall/r_wall) //Why not make rwall? + qdel(src) + + if( istype(W, /obj/item/weapon/weldingtool) ) + var/obj/item/weapon/weldingtool/WT = W + if( WT.remove_fuel(0,user) ) + var/turf/T = get_turf(src) + T.ChangeTurf(/turf/simulated/wall) + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + else if( istype(W, /obj/item/weapon/pickaxe) ) + var/obj/item/weapon/pickaxe/used_pick = W + if(!(used_pick.diggables & DIG_WALLS)) + return + var/turf/T = get_turf(src) + T.ChangeTurf(/turf/simulated/wall) + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + +/* + * Uranium Falsewalls + */ + +/obj/structure/falsewall/uranium + name = "uranium wall" + desc = "A wall with uranium plating. This is probably a bad idea." + icon_state = "" + mineral = "uranium" + var/active = null + var/last_event = 0 + +/obj/structure/falsewall/uranium/attackby(obj/item/weapon/W as obj, mob/user as mob) + radiate() + ..() + +/obj/structure/falsewall/uranium/attack_hand(mob/user as mob) + radiate() + ..() + +/obj/structure/falsewall/uranium/proc/radiate() + if(!active) + if(world.time > last_event+15) + active = 1 + for(var/mob/living/L in range(3,src)) + L.apply_effect(12,IRRADIATE,0) + for(var/turf/simulated/wall/mineral/uranium/T in range(3,src)) + T.radiate() + last_event = world.time + active = null + return + return +/* + * Other misc falsewall types + */ + +/obj/structure/falsewall/gold + name = "gold wall" + desc = "A wall with gold plating. Swag!" + icon_state = "" + mineral = "gold" + +/obj/structure/falsewall/silver + name = "silver wall" + desc = "A wall with silver plating. Shiny." + icon_state = "" + mineral = "silver" + +/obj/structure/falsewall/diamond + name = "diamond wall" + desc = "A wall with diamond plating. You monster." + icon_state = "" + mineral = "diamond" + +/obj/structure/falsewall/plasma + name = "plasma wall" + desc = "A wall with plasma plating. This is definitely a bad idea." + icon_state = "" + mineral = "plasma" + +/obj/structure/falsewall/plastic + name = "plastic wall" + desc = "A wall made of colorful plastic blocks attached together." + icon_state = "" + mineral = "plastic" + +//-----------wtf?-----------start +/obj/structure/falsewall/clown + name = "bananium wall" + desc = "A wall with bananium plating. Honk!" + icon_state = "" + mineral = "clown" + +/obj/structure/falsewall/sandstone + name = "sandstone wall" + desc = "A wall with sandstone plating." + icon_state = "" + mineral = "sandstone" +//------------wtf?------------end diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index dfef03160cd..a513147a60b 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -1,360 +1,360 @@ -//trees -/obj/structure/flora/tree - name = "tree" - anchored = 1 - density = 1 - - layer = FLY_LAYER - icon = 'icons/obj/flora/deadtrees.dmi' - icon_state = "tree_1" - - pixel_x = -16 - - var/health = 100 - var/maxHealth = 100 - - var/height = 6 //How many logs are spawned - - - var/falling_dir = 0 //Direction in which spawned logs are thrown. - - var/const/randomize_on_creation = 1 - var/const/log_type = /obj/item/weapon/grown/log/tree - -/obj/structure/flora/tree/New() - ..() - - if(randomize_on_creation) - health = rand(60, 200) - maxHealth = health - - height = rand(3, 8) - - icon_state = pick( - "tree_1", - "tree_2", - "tree_3", - "tree_4", - "tree_5", - "tree_6", - ) - -/obj/structure/flora/tree/examine(mob/user) - .=..() - - //Tell user about the height. Note that normally height ranges from 3 to 8 (with a 5% chance of having 6 to 15 instead) - to_chat(user, "It appears to be about [height*3] feet tall.") - switch(health / maxHealth) - if(1.0) - //It's healthy - if(0.9 to 0.6) - to_chat(user, "It's been partially cut down.") - if(0.6 to 0.2) - to_chat(user, "It's almost cut down, [falling_dir ? "and it's leaning towards the [dir2text(falling_dir)]." : "but it still stands upright."]") - if(0.2 to 0) - to_chat(user, "It's going to fall down any minute now!") - -/obj/structure/flora/tree/attackby(obj/item/W, mob/living/user) - ..() - - if(istype(W, /obj/item/weapon)) - if(W.is_sharp() >= 1.2) //As sharp as a knife - if(W.w_class >= 2) //Big enough to use to cut down trees - health -= (user.get_strength() * W.force) - else - to_chat(user, "\The [W] doesn't appear to be big enough to cut into \the [src]. Try something bigger.") - else - to_chat(user, "\The [W] doesn't appear to be sharp enough to cut into \the [src]. Try something sharper.") - - update_health() - - return 1 - -/obj/structure/flora/tree/proc/fall_down() - if(!falling_dir) - falling_dir = pick(cardinal) - - var/turf/our_turf = get_turf(src) //Turf at which this tree is located - var/turf/current_turf = get_turf(src) //Turf in which to spawn a log. Updated in the loop - - qdel(src) - - spawn() - while(height > 0) - if(!current_turf) break //If the turf in which to spawn a log doesn't exist, stop the thing - - var/obj/item/I = new log_type(our_turf) //Spawn a log and throw it at the "current_turf" - I.throw_at(current_turf, 10, 10) - - current_turf = get_step(current_turf, falling_dir) - - height-- - - sleep(1) - -/obj/structure/flora/tree/proc/update_health() - if(health < 40 && !falling_dir) - falling_dir = pick(cardinal) - visible_message("\The [src] starts leaning to the [dir2text(falling_dir)]!", - drugged_message = "\The [src] is coming to life, man.") - - if(health <= 0) - fall_down() - -/obj/structure/flora/tree/ex_act(severity) - switch(severity) - if(1) //Epicentre - return qdel(src) - if(2) //Major devastation - height -= rand(1,4) //Some logs are lost - fall_down() - if(3) //Minor devastation (IED) - health -= rand(10,30) - update_health() - -/obj/structure/flora/tree/pine - name = "pine tree" - icon = 'icons/obj/flora/pinetrees.dmi' - icon_state = "pine_1" - -/obj/structure/flora/tree/pine/New() - ..() - icon_state = "pine_[rand(1, 3)]" - -/obj/structure/flora/tree/pine/xmas - name = "xmas tree" - icon = 'icons/obj/flora/pinetrees.dmi' - icon_state = "pine_c" - -/obj/structure/flora/tree/pine/xmas/New() - ..() - icon_state = "pine_c" - -/obj/structure/flora/tree/dead - name = "dead tree" - icon = 'icons/obj/flora/deadtrees.dmi' - icon_state = "tree_1" - -/obj/structure/flora/tree/dead/New() - ..() - icon_state = "tree_[rand(1, 6)]" - -/obj/structure/flora/tree_stump - name = "tree stump" - icon = 'icons/obj/flora/pinetrees.dmi' - icon_state = "pine_stump" - -//grass -/obj/structure/flora/grass - name = "grass" - icon = 'icons/obj/flora/snowflora.dmi' - anchored = 1 - -/obj/structure/flora/grass/brown - icon_state = "snowgrass1bb" - -/obj/structure/flora/grass/brown/New() - ..() - icon_state = "snowgrass[rand(1, 3)]bb" - - -/obj/structure/flora/grass/green - icon_state = "snowgrass1gb" - -/obj/structure/flora/grass/green/New() - ..() - icon_state = "snowgrass[rand(1, 3)]gb" - -/obj/structure/flora/grass/both - icon_state = "snowgrassall1" - -/obj/structure/flora/grass/both/New() - ..() - icon_state = "snowgrassall[rand(1, 3)]" - - -//bushes -/obj/structure/flora/bush - name = "bush" - icon = 'icons/obj/flora/snowflora.dmi' - icon_state = "snowbush1" - anchored = 1 - -/obj/structure/flora/bush/New() - ..() - icon_state = "snowbush[rand(1, 6)]" - -/obj/structure/flora/pottedplant - name = "potted plant" - desc = "Oh, no. Not again." - icon = 'icons/obj/plants.dmi' - icon_state = "plant-26" - layer = FLY_LAYER - var/obj/item/full = null - -/obj/structure/flora/pottedplant/attackby(var/obj/item/I, var/mob/user) - if(!I) - return - if(I.w_class>2.0) - to_chat(user, "That item is too big.") - return - if(full) - to_chat(user, "There is already something in the pot.") - else - if(user.drop_item(I, src)) - full = I - - user.visible_message("[user] stuffs something into the pot.","You stuff \the [full] into the [src].") - -/obj/structure/flora/pottedplant/attack_hand(mob/user) - if(full) - user.visible_message("[user] retrieves something from the pot.","You retrieve the [full] from the [src].") - full.forceMove(loc) - user.put_in_active_hand(full) - full = null - else - to_chat(user, "You root around in the roots.") - -// /vg/ -/obj/structure/flora/pottedplant/random/New() - ..() - icon_state = "plant-[rand(1,26)]" - -//newbushes - -/obj/structure/flora/ausbushes - name = "bush" - icon = 'icons/obj/flora/ausflora.dmi' - icon_state = "firstbush_1" - anchored = 1 - -/obj/structure/flora/ausbushes/New() - ..() - icon_state = "firstbush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/reedbush - icon_state = "reedbush_1" - -/obj/structure/flora/ausbushes/reedbush/New() - ..() - icon_state = "reedbush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/leafybush - icon_state = "leafybush_1" - -/obj/structure/flora/ausbushes/leafybush/New() - ..() - icon_state = "leafybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/palebush - icon_state = "palebush_1" - -/obj/structure/flora/ausbushes/palebush/New() - ..() - icon_state = "palebush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/stalkybush - icon_state = "stalkybush_1" - -/obj/structure/flora/ausbushes/stalkybush/New() - ..() - icon_state = "stalkybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/grassybush - icon_state = "grassybush_1" - -/obj/structure/flora/ausbushes/grassybush/New() - ..() - icon_state = "grassybush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/fernybush - icon_state = "fernybush_1" - -/obj/structure/flora/ausbushes/fernybush/New() - ..() - icon_state = "fernybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/sunnybush - icon_state = "sunnybush_1" - -/obj/structure/flora/ausbushes/sunnybush/New() - ..() - icon_state = "sunnybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/genericbush - icon_state = "genericbush_1" - -/obj/structure/flora/ausbushes/genericbush/New() - ..() - icon_state = "genericbush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/pointybush - icon_state = "pointybush_1" - -/obj/structure/flora/ausbushes/pointybush/New() - ..() - icon_state = "pointybush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/lavendergrass - icon_state = "lavendergrass_1" - -/obj/structure/flora/ausbushes/lavendergrass/New() - ..() - icon_state = "lavendergrass_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/ywflowers - icon_state = "ywflowers_1" - -/obj/structure/flora/ausbushes/ywflowers/New() - ..() - icon_state = "ywflowers_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/brflowers - icon_state = "brflowers_1" - -/obj/structure/flora/ausbushes/brflowers/New() - ..() - icon_state = "brflowers_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/ppflowers - icon_state = "ppflowers_1" - -/obj/structure/flora/ausbushes/ppflowers/New() - ..() - icon_state = "ppflowers_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/sparsegrass - icon_state = "sparsegrass_1" - -/obj/structure/flora/ausbushes/sparsegrass/New() - ..() - icon_state = "sparsegrass_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/fullgrass - icon_state = "fullgrass_1" - -/obj/structure/flora/ausbushes/fullgrass/New() - ..() - icon_state = "fullgrass_[rand(1, 3)]" - -//a rock is flora according to where the icon file is -//and now these defines -/obj/structure/flora/rock - name = "rock" - desc = "a rock" - icon_state = "rock1" - icon = 'icons/obj/flora/rocks.dmi' - anchored = 1 - -/obj/structure/flora/rock/New() - ..() - icon_state = "rock[rand(1,5)]" - -/obj/structure/flora/rock/pile - name = "rocks" - desc = "some rocks" - icon_state = "rockpile1" - -/obj/structure/flora/rock/pile/New() - ..() - icon_state = "rockpile[rand(1,5)]" +//trees +/obj/structure/flora/tree + name = "tree" + anchored = 1 + density = 1 + + layer = FLY_LAYER + icon = 'icons/obj/flora/deadtrees.dmi' + icon_state = "tree_1" + + pixel_x = -16 + + var/health = 100 + var/maxHealth = 100 + + var/height = 6 //How many logs are spawned + + + var/falling_dir = 0 //Direction in which spawned logs are thrown. + + var/const/randomize_on_creation = 1 + var/const/log_type = /obj/item/weapon/grown/log/tree + +/obj/structure/flora/tree/New() + ..() + + if(randomize_on_creation) + health = rand(60, 200) + maxHealth = health + + height = rand(3, 8) + + icon_state = pick( + "tree_1", + "tree_2", + "tree_3", + "tree_4", + "tree_5", + "tree_6", + ) + +/obj/structure/flora/tree/examine(mob/user) + .=..() + + //Tell user about the height. Note that normally height ranges from 3 to 8 (with a 5% chance of having 6 to 15 instead) + to_chat(user, "It appears to be about [height*3] feet tall.") + switch(health / maxHealth) + if(1.0) + //It's healthy + if(0.9 to 0.6) + to_chat(user, "It's been partially cut down.") + if(0.6 to 0.2) + to_chat(user, "It's almost cut down, [falling_dir ? "and it's leaning towards the [dir2text(falling_dir)]." : "but it still stands upright."]") + if(0.2 to 0) + to_chat(user, "It's going to fall down any minute now!") + +/obj/structure/flora/tree/attackby(obj/item/W, mob/living/user) + ..() + + if(istype(W, /obj/item/weapon)) + if(W.is_sharp() >= 1.2) //As sharp as a knife + if(W.w_class >= 2) //Big enough to use to cut down trees + health -= (user.get_strength() * W.force) + else + to_chat(user, "\The [W] doesn't appear to be big enough to cut into \the [src]. Try something bigger.") + else + to_chat(user, "\The [W] doesn't appear to be sharp enough to cut into \the [src]. Try something sharper.") + + update_health() + + return 1 + +/obj/structure/flora/tree/proc/fall_down() + if(!falling_dir) + falling_dir = pick(cardinal) + + var/turf/our_turf = get_turf(src) //Turf at which this tree is located + var/turf/current_turf = get_turf(src) //Turf in which to spawn a log. Updated in the loop + + qdel(src) + + spawn() + while(height > 0) + if(!current_turf) break //If the turf in which to spawn a log doesn't exist, stop the thing + + var/obj/item/I = new log_type(our_turf) //Spawn a log and throw it at the "current_turf" + I.throw_at(current_turf, 10, 10) + + current_turf = get_step(current_turf, falling_dir) + + height-- + + sleep(1) + +/obj/structure/flora/tree/proc/update_health() + if(health < 40 && !falling_dir) + falling_dir = pick(cardinal) + visible_message("\The [src] starts leaning to the [dir2text(falling_dir)]!", + drugged_message = "\The [src] is coming to life, man.") + + if(health <= 0) + fall_down() + +/obj/structure/flora/tree/ex_act(severity) + switch(severity) + if(1) //Epicentre + return qdel(src) + if(2) //Major devastation + height -= rand(1,4) //Some logs are lost + fall_down() + if(3) //Minor devastation (IED) + health -= rand(10,30) + update_health() + +/obj/structure/flora/tree/pine + name = "pine tree" + icon = 'icons/obj/flora/pinetrees.dmi' + icon_state = "pine_1" + +/obj/structure/flora/tree/pine/New() + ..() + icon_state = "pine_[rand(1, 3)]" + +/obj/structure/flora/tree/pine/xmas + name = "xmas tree" + icon = 'icons/obj/flora/pinetrees.dmi' + icon_state = "pine_c" + +/obj/structure/flora/tree/pine/xmas/New() + ..() + icon_state = "pine_c" + +/obj/structure/flora/tree/dead + name = "dead tree" + icon = 'icons/obj/flora/deadtrees.dmi' + icon_state = "tree_1" + +/obj/structure/flora/tree/dead/New() + ..() + icon_state = "tree_[rand(1, 6)]" + +/obj/structure/flora/tree_stump + name = "tree stump" + icon = 'icons/obj/flora/pinetrees.dmi' + icon_state = "pine_stump" + +//grass +/obj/structure/flora/grass + name = "grass" + icon = 'icons/obj/flora/snowflora.dmi' + anchored = 1 + +/obj/structure/flora/grass/brown + icon_state = "snowgrass1bb" + +/obj/structure/flora/grass/brown/New() + ..() + icon_state = "snowgrass[rand(1, 3)]bb" + + +/obj/structure/flora/grass/green + icon_state = "snowgrass1gb" + +/obj/structure/flora/grass/green/New() + ..() + icon_state = "snowgrass[rand(1, 3)]gb" + +/obj/structure/flora/grass/both + icon_state = "snowgrassall1" + +/obj/structure/flora/grass/both/New() + ..() + icon_state = "snowgrassall[rand(1, 3)]" + + +//bushes +/obj/structure/flora/bush + name = "bush" + icon = 'icons/obj/flora/snowflora.dmi' + icon_state = "snowbush1" + anchored = 1 + +/obj/structure/flora/bush/New() + ..() + icon_state = "snowbush[rand(1, 6)]" + +/obj/structure/flora/pottedplant + name = "potted plant" + desc = "Oh, no. Not again." + icon = 'icons/obj/plants.dmi' + icon_state = "plant-26" + layer = FLY_LAYER + var/obj/item/full = null + +/obj/structure/flora/pottedplant/attackby(var/obj/item/I, var/mob/user) + if(!I) + return + if(I.w_class>2.0) + to_chat(user, "That item is too big.") + return + if(full) + to_chat(user, "There is already something in the pot.") + else + if(user.drop_item(I, src)) + full = I + + user.visible_message("[user] stuffs something into the pot.","You stuff \the [full] into the [src].") + +/obj/structure/flora/pottedplant/attack_hand(mob/user) + if(full) + user.visible_message("[user] retrieves something from the pot.","You retrieve the [full] from the [src].") + full.forceMove(loc) + user.put_in_active_hand(full) + full = null + else + to_chat(user, "You root around in the roots.") + +// /vg/ +/obj/structure/flora/pottedplant/random/New() + ..() + icon_state = "plant-[rand(1,26)]" + +//newbushes + +/obj/structure/flora/ausbushes + name = "bush" + icon = 'icons/obj/flora/ausflora.dmi' + icon_state = "firstbush_1" + anchored = 1 + +/obj/structure/flora/ausbushes/New() + ..() + icon_state = "firstbush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/reedbush + icon_state = "reedbush_1" + +/obj/structure/flora/ausbushes/reedbush/New() + ..() + icon_state = "reedbush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/leafybush + icon_state = "leafybush_1" + +/obj/structure/flora/ausbushes/leafybush/New() + ..() + icon_state = "leafybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/palebush + icon_state = "palebush_1" + +/obj/structure/flora/ausbushes/palebush/New() + ..() + icon_state = "palebush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/stalkybush + icon_state = "stalkybush_1" + +/obj/structure/flora/ausbushes/stalkybush/New() + ..() + icon_state = "stalkybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/grassybush + icon_state = "grassybush_1" + +/obj/structure/flora/ausbushes/grassybush/New() + ..() + icon_state = "grassybush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/fernybush + icon_state = "fernybush_1" + +/obj/structure/flora/ausbushes/fernybush/New() + ..() + icon_state = "fernybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/sunnybush + icon_state = "sunnybush_1" + +/obj/structure/flora/ausbushes/sunnybush/New() + ..() + icon_state = "sunnybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/genericbush + icon_state = "genericbush_1" + +/obj/structure/flora/ausbushes/genericbush/New() + ..() + icon_state = "genericbush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/pointybush + icon_state = "pointybush_1" + +/obj/structure/flora/ausbushes/pointybush/New() + ..() + icon_state = "pointybush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/lavendergrass + icon_state = "lavendergrass_1" + +/obj/structure/flora/ausbushes/lavendergrass/New() + ..() + icon_state = "lavendergrass_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/ywflowers + icon_state = "ywflowers_1" + +/obj/structure/flora/ausbushes/ywflowers/New() + ..() + icon_state = "ywflowers_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/brflowers + icon_state = "brflowers_1" + +/obj/structure/flora/ausbushes/brflowers/New() + ..() + icon_state = "brflowers_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/ppflowers + icon_state = "ppflowers_1" + +/obj/structure/flora/ausbushes/ppflowers/New() + ..() + icon_state = "ppflowers_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/sparsegrass + icon_state = "sparsegrass_1" + +/obj/structure/flora/ausbushes/sparsegrass/New() + ..() + icon_state = "sparsegrass_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/fullgrass + icon_state = "fullgrass_1" + +/obj/structure/flora/ausbushes/fullgrass/New() + ..() + icon_state = "fullgrass_[rand(1, 3)]" + +//a rock is flora according to where the icon file is +//and now these defines +/obj/structure/flora/rock + name = "rock" + desc = "a rock" + icon_state = "rock1" + icon = 'icons/obj/flora/rocks.dmi' + anchored = 1 + +/obj/structure/flora/rock/New() + ..() + icon_state = "rock[rand(1,5)]" + +/obj/structure/flora/rock/pile + name = "rocks" + desc = "some rocks" + icon_state = "rockpile1" + +/obj/structure/flora/rock/pile/New() + ..() + icon_state = "rockpile[rand(1,5)]" diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 62eb061fb6d..c000304e936 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -1,443 +1,443 @@ -/obj/structure/girder - icon_state = "girder" - anchored = 1 - density = 1 - layer = 2 - var/state = 0 - var/material = /obj/item/stack/sheet/metal - -/obj/structure/girder/wood - icon_state = "girder_wood" - name = "wooden girder" - material = /obj/item/stack/sheet/wood - -/obj/structure/girder/wood/update_icon() - if(anchored) - name = "wooden girder" - icon_state = "girder_wood" - else - name = "displaced wooden girder" - icon_state = "displaced_wood" - -/obj/structure/girder/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - if(state == 0) //Normal girder or wooden girder - if(anchored && !istype(src, /obj/structure/girder/displaced)) //Anchored, destroy it - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - user.visible_message("[user] starts disassembling \the [src].", \ - "You start disassembling \the [src].") - if(do_after(user, src, 40)) - user.visible_message("[user] dissasembles \the [src].", \ - "You dissasemble \the [src].") - getFromPool(material, get_turf(src)) - qdel(src) - else if(!anchored) //Unanchored, anchor it - if(!istype(src.loc, /turf/simulated/floor)) //Prevent from anchoring shit to shuttles / space - to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!") - return - - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - user.visible_message("[user] starts securing \the [src].", \ - "You start securing \the [src].") - if(do_after(user, src, 40)) - user.visible_message("[user] secures \the [src].", \ - "You secure \the [src].") - add_hiddenprint(user) - add_fingerprint(user) - anchored = 1 - update_icon() - else if(state == 1 || state == 2) //Clearly a reinforced girder - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - user.visible_message("[user] starts [anchored ? "un" : ""]securing \the [src].", \ - "You start [anchored ? "un" : ""]securing \the [src].") - if(do_after(user, src, 40)) - anchored = !anchored //Unachor it if anchored, or opposite - user.visible_message("[user] [anchored ? "" : "un"]secures \the [src].", \ - "You [anchored ? "" : "un"]secure \the [src].") - add_hiddenprint(user) - add_fingerprint(user) - update_icon() - - else if(istype(W, /obj/item/weapon/pickaxe)) - var/obj/item/weapon/pickaxe/PK = W - if(!(PK.diggables & DIG_WALLS)) //If we can't dig a wall, we can't dig a girder - return - - user.visible_message("[user] starts [PK.drill_verb] \the [src] with \the [PK]", \ - "You start [PK.drill_verb] \the [src] with \the [PK]") - if(do_after(user, src, 30)) - user.visible_message("[user] destroys \the [src]!", \ - "Your [PK] tears through the last of \the [src]!") - getFromPool(material, get_turf(src)) - qdel(src) - - else if(istype(W, /obj/item/weapon/screwdriver) && state == 2) //Unsecuring support struts, stage 2 to 1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) - user.visible_message("[user] starts unsecuring \the [src]'s internal support struts.", \ - "You start unsecuring \the [src]'s internal support struts.") - if(do_after(user, src, 40)) - user.visible_message("[user] unsecures \the [src]'s internal support struts.", \ - "You unsecure \the [src]'s internal support struts.") - add_hiddenprint(user) - add_fingerprint(user) - state = 1 - update_icon() - - else if(istype(W, /obj/item/weapon/screwdriver) && state == 1) //Securing support struts, stage 1 to 2 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) - user.visible_message("[user] starts securing \the [src]'s internal support struts.", \ - "You start securing \the [src]'s internal support struts.") - if(do_after(user, src, 40)) - user.visible_message("[user] secures \the [src]'s internal support struts.", \ - "You secure \the [src]'s internal support struts.") - add_hiddenprint(user) - add_fingerprint(user) - state = 2 - update_icon() - - else if(istype(W, /obj/item/weapon/wirecutters) && state == 1) //Removing support struts, stage 1 to 0 (normal girder) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) - user.visible_message("[user] starts removing \the [src]'s internal support struts.", \ - "You start removing \the [src]'s internal support struts.") - if(do_after(user, src, 40)) - user.visible_message("[user] removes \the [src]'s internal support struts.", \ - "You remove \the [src]'s internal support struts.") - add_hiddenprint(user) - add_fingerprint(user) - getFromPool(/obj/item/stack/rods, get_turf(src), 2) - state = 0 - update_icon() - - else if(istype(W, /obj/item/stack/rods) && state == 0 && material == /obj/item/stack/sheet/metal) //Inserting support struts, stage 0 to 1 (reinforced girder, replaces plasteel step) - var/obj/item/stack/rods/R = W - if(R.amount < 2) //Do a first check BEFORE the user begins, in case he's using a single rod - to_chat(user, "You need more rods to finish the support struts.") - return - user.visible_message("[user] starts inserting internal support struts into \the [src.]", \ - "You start inserting internal support struts into \the [src].") - if(do_after(user, src,40)) - var/obj/item/stack/rods/O = W - if(O.amount < 2) //In case our user is trying to be tricky - to_chat(user, "You need more rods to finish the support struts.") - return - O.use(2) - user.visible_message("[user] inserts internal support struts into \the [src].", \ - "You insert internal support struts into \the [src].") - add_hiddenprint(user) - add_fingerprint(user) - state = 1 - update_icon() - - else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored) //Turning normal girder into disloged girder - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] starts dislodging \the [src].", \ - "You start dislodging \the [src].") - if(do_after(user, src, 40)) - user.visible_message("[user] dislodges \the [src].", \ - "You dislodge \the [src].") - add_hiddenprint(user) - add_fingerprint(user) - anchored = 0 - update_icon() - - else if(istype(W, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/S = W - switch(S.type) - if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg) - if(state) //We are trying to finish a reinforced girder with regular metal - return - if(!anchored) - if(S.amount < 2) - return - var/pdiff = performWallPressureCheck(src.loc) - if(!pdiff) //Should really not be that precise, 10 kPa is the usual breaking point - S.use(2) - user.visible_message("[user] creates a false wall!", \ - "You create a false wall. Push on it to open or close the passage.") - var/obj/structure/falsewall/FW = new /obj/structure/falsewall (src.loc) - FW.add_hiddenprint(user) - FW.add_fingerprint(user) - qdel(src) - else - to_chat(user, "There is too much air moving through the gap! The door wouldn't stay closed if you built it.") - message_admins("Attempted false wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!") - log_admin("Attempted false wall made by [user.real_name] (user.ckey) at [loc] had a pressure difference of [pdiff]!") - return - else - if(S.amount < 2) - return ..() // ? - user.visible_message("[user] starts installing plating to \the [src].", \ - "You start installing plating to \the [src].") - if(do_after(user, src, 40)) - if(S.amount < 2) //User being tricky - return - S.use(2) - user.visible_message("[user] finishes installing plating to \the [src].", \ - "You finish installing plating to \the [src].") - var/turf/Tsrc = get_turf(src) - if(!istype(Tsrc)) return 0 - var/turf/simulated/wall/X = Tsrc.ChangeTurf(/turf/simulated/wall) - if(X) - X.add_hiddenprint(user) - X.add_fingerprint(user) - qdel(src) - return - - if(/obj/item/stack/sheet/plasteel) - - //Due to the way wall construction works, this uses both plasteel sheets immediately - if(!anchored) - if(S.amount < 2) - return - var/pdiff = performWallPressureCheck(src.loc) - if(!pdiff) - S.use(2) - user.visible_message("[user] creates a false reinforced wall!", \ - "You create a false reinforced wall. Push on it to open or close the passage.") - var/obj/structure/falserwall/FW = new /obj/structure/falserwall(src.loc) - FW.add_hiddenprint(user) - FW.add_fingerprint(user) - qdel(src) - else - to_chat(user, "There is too much air moving through the gap! The door wouldn't stay closed if you built it.") - message_admins("Attempted false rwall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!") - log_admin("Attempted false rwall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!") - return - - //We are ready to turn this reinforced girder into a beautiful reinforced wall - //The other plasteel sheet is used in the rest of the construction steps, see walls_reinforced.dm - - if(state != 2) - return //Coders against indents - user.visible_message("[user] starts installing reinforced plating to \the [src].", \ - "You start installing reinforced plating to \the [src].") - if(do_after(user, src, 50)) - S.use(1) - user.visible_message("[user] finishes installing reinforced plating to \the [src].", \ - "You finish installing reinforced plating to \the [src].") - var/turf/Tsrc = get_turf(src) - var/turf/simulated/wall/r_wall/X = Tsrc.ChangeTurf(/turf/simulated/wall/r_wall) - if(X) - X.add_hiddenprint(user) - X.add_fingerprint(user) - X.d_state = 4 //Reinforced wall not finished yet, but since we're changing to a turf, need to transfer desired variables - X.update_icon() //Tell our reinforced wall to update its icon - qdel(src) - return - - if(S.sheettype) - var/M = S.sheettype - if(!anchored) - if(S.amount < 2) - return - var/F = text2path("/obj/structure/falsewall/[M]") - if(!ispath(F)) - return - var/pdiff = performWallPressureCheck(src.loc) - if(!pdiff) - S.use(2) - user.visible_message("[user] creates a false wall!", \ - "You create a false wall. Push on it to open or close the passage.") - var/obj/structure/falsewall/FW = new F (src.loc) - FW.add_hiddenprint(user) - FW.add_fingerprint(user) - qdel(src) - else - to_chat(user, "There is too much air moving through the gap! The door wouldn't stay closed if you built it.") - message_admins("Attempted false [M] wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!") - log_admin("Attempted false [M] wall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!") - return - else - if(S.amount < 2) - return ..() - var/wallpath = text2path("/turf/simulated/wall/mineral/[M]") - if(!ispath(wallpath)) - return ..() - user.visible_message("[user] starts installing plating to \the [src].", \ - "You start installing plating to \the [src].") - if(do_after(user, src,40)) - if(S.amount < 2) //Don't be tricky now - return - S.use(2) - user.visible_message("[user] finishes installing plating to \the [src].", \ - "You finish installing plating to \the [src].") - var/turf/Tsrc = get_turf(src) - var/turf/simulated/wall/mineral/X = Tsrc.ChangeTurf(wallpath) - if(X) - X.add_hiddenprint(user) - X.add_fingerprint(user) - qdel(src) - return - - add_hiddenprint(usr) - - //Wait, what, WHAT ? - else if(istype(W, /obj/item/pipe)) - var/obj/item/pipe/P = W - if(P.pipe_type in list(0, 1, 5)) //Simple pipes, simple bends, and simple manifolds. - if(user.drop_item(P, src.loc)) - user.visible_message("[user] fits \the [P] into \the [src]", \ - "You fit \the [P] into \the [src]") - else - ..() - -/obj/structure/girder/blob_act() - if(prob(40)) - qdel(src) - -/obj/structure/girder/bullet_act(var/obj/item/projectile/Proj) - if(Proj.destroy) - src.ex_act(2) - ..() - return 0 - -/obj/structure/girder/ex_act(severity) - switch(severity) - if(1.0) - if(prob(25) && state == 2) //Strong enough to have a chance to stand if finished, but not in one piece - getFromPool(/obj/item/stack/rods, get_turf(src)) //Lose one rod - state = 0 - update_icon() - else //Not finished or not lucky - qdel(src) //No scraps - return - if(2.0) - if(prob(30)) - if(state == 2) - state = 1 - update_icon() - if(state == 1) - getFromPool(/obj/item/stack/rods, get_turf(src)) - state = 0 - update_icon() - else - getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - qdel(src) - return - if(3.0) - if((state == 0) && prob(5)) - getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - qdel(src) - else if(prob(15)) - if(state == 2) - state = 1 - update_icon() - if(state == 1) - getFromPool(/obj/item/stack/rods, get_turf(src), 2) - state = 0 - update_icon() - return - return - -/obj/structure/girder/mech_drill_act(severity) - getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - qdel(src) - return - -/obj/structure/girder/update_icon() - //Names really shouldn't be set here, but it's the only proc that checks where needed - if(anchored) - if(state) - name = "reinforced girder" - icon_state = "reinforced" - else - name = "girder" - icon_state = "girder" - else - if(state) - name = "displaced reinforced girder" - icon_state = "r_displaced" - else - name = "displaced girder" - icon_state = "displaced" - -/obj/structure/girder/projectile_check() - return PROJREACT_WALLS - -/obj/structure/girder/displaced - name = "displaced girder" - icon_state = "displaced" - anchored = 0 - -/obj/structure/girder/reinforced - name = "reinforced girder" - icon_state = "reinforced" - state = 2 - -/obj/structure/cultgirder - name = "cult girder" - icon = 'icons/obj/cult.dmi' - icon_state = "cultgirder" - anchored = 1 - density = 1 - layer = 2 - -/obj/structure/cultgirder/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - user.visible_message("[user] starts disassembling \the [src].", \ - "You start disassembling \the [src].") - if(do_after(user, src,40)) - user.visible_message("[src] dissasembles \the [src].", \ - "You dissasemble \the [src].") - //new /obj/effect/decal/remains/human(get_turf(src)) //Commented out until remains are cleanable - qdel(src) - - else if(istype(W, /obj/item/weapon/pickaxe)) - var/obj/item/weapon/pickaxe/PK = W - if(!(PK.diggables & DIG_WALLS)) - return - - user.visible_message("[user] starts [PK.drill_verb] \the [src] with \the [PK].", - "You start [PK.drill_verb] \the [src] with \the [PK].") - if(do_after(user, src,30)) - user.visible_message("[user] destroys \the [src]!", - "Your [PK] tears through the last of \the [src]!") - new /obj/effect/decal/remains/human(loc) - qdel(src) - -/obj/structure/cultgirder/attack_construct(mob/user as mob) - if(istype(user, /mob/living/simple_animal/construct/builder)) - to_chat(user, "You start repairing the girder.") - if(do_after(user,src,30)) - to_chat(user, "Girder repaired.") - var/turf/Tsrc = get_turf(src) - if(!istype(Tsrc)) return 0 - Tsrc.ChangeTurf(/turf/simulated/wall/cult) - qdel(src) - return 1 - return 0 - -/obj/structure/cultgirder/attack_animal(var/mob/living/simple_animal/M) - M.delayNextAttack(8) - if(M.environment_smash >= 2) - new /obj/effect/decal/remains/human(get_turf(src)) - M.visible_message("[M] smashes through \the [src].", \ - "You smash through \the [src].") - qdel(src) - -/obj/structure/cultgirder/blob_act() - if(prob(40)) - qdel(src) - -/obj/structure/cultgirder/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(30)) - new /obj/effect/decal/remains/human(loc) - qdel(src) - return - if(3.0) - if (prob(5)) - new /obj/effect/decal/remains/human(loc) - qdel(src) - return - return - -/obj/structure/cultgirder/mech_drill_act(severity) - new /obj/effect/decal/remains/human(loc) - qdel(src) - return +/obj/structure/girder + icon_state = "girder" + anchored = 1 + density = 1 + layer = 2 + var/state = 0 + var/material = /obj/item/stack/sheet/metal + +/obj/structure/girder/wood + icon_state = "girder_wood" + name = "wooden girder" + material = /obj/item/stack/sheet/wood + +/obj/structure/girder/wood/update_icon() + if(anchored) + name = "wooden girder" + icon_state = "girder_wood" + else + name = "displaced wooden girder" + icon_state = "displaced_wood" + +/obj/structure/girder/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + if(state == 0) //Normal girder or wooden girder + if(anchored && !istype(src, /obj/structure/girder/displaced)) //Anchored, destroy it + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + user.visible_message("[user] starts disassembling \the [src].", \ + "You start disassembling \the [src].") + if(do_after(user, src, 40)) + user.visible_message("[user] dissasembles \the [src].", \ + "You dissasemble \the [src].") + getFromPool(material, get_turf(src)) + qdel(src) + else if(!anchored) //Unanchored, anchor it + if(!istype(src.loc, /turf/simulated/floor)) //Prevent from anchoring shit to shuttles / space + to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!") + return + + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + user.visible_message("[user] starts securing \the [src].", \ + "You start securing \the [src].") + if(do_after(user, src, 40)) + user.visible_message("[user] secures \the [src].", \ + "You secure \the [src].") + add_hiddenprint(user) + add_fingerprint(user) + anchored = 1 + update_icon() + else if(state == 1 || state == 2) //Clearly a reinforced girder + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + user.visible_message("[user] starts [anchored ? "un" : ""]securing \the [src].", \ + "You start [anchored ? "un" : ""]securing \the [src].") + if(do_after(user, src, 40)) + anchored = !anchored //Unachor it if anchored, or opposite + user.visible_message("[user] [anchored ? "" : "un"]secures \the [src].", \ + "You [anchored ? "" : "un"]secure \the [src].") + add_hiddenprint(user) + add_fingerprint(user) + update_icon() + + else if(istype(W, /obj/item/weapon/pickaxe)) + var/obj/item/weapon/pickaxe/PK = W + if(!(PK.diggables & DIG_WALLS)) //If we can't dig a wall, we can't dig a girder + return + + user.visible_message("[user] starts [PK.drill_verb] \the [src] with \the [PK]", \ + "You start [PK.drill_verb] \the [src] with \the [PK]") + if(do_after(user, src, 30)) + user.visible_message("[user] destroys \the [src]!", \ + "Your [PK] tears through the last of \the [src]!") + getFromPool(material, get_turf(src)) + qdel(src) + + else if(istype(W, /obj/item/weapon/screwdriver) && state == 2) //Unsecuring support struts, stage 2 to 1 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + user.visible_message("[user] starts unsecuring \the [src]'s internal support struts.", \ + "You start unsecuring \the [src]'s internal support struts.") + if(do_after(user, src, 40)) + user.visible_message("[user] unsecures \the [src]'s internal support struts.", \ + "You unsecure \the [src]'s internal support struts.") + add_hiddenprint(user) + add_fingerprint(user) + state = 1 + update_icon() + + else if(istype(W, /obj/item/weapon/screwdriver) && state == 1) //Securing support struts, stage 1 to 2 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + user.visible_message("[user] starts securing \the [src]'s internal support struts.", \ + "You start securing \the [src]'s internal support struts.") + if(do_after(user, src, 40)) + user.visible_message("[user] secures \the [src]'s internal support struts.", \ + "You secure \the [src]'s internal support struts.") + add_hiddenprint(user) + add_fingerprint(user) + state = 2 + update_icon() + + else if(istype(W, /obj/item/weapon/wirecutters) && state == 1) //Removing support struts, stage 1 to 0 (normal girder) + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) + user.visible_message("[user] starts removing \the [src]'s internal support struts.", \ + "You start removing \the [src]'s internal support struts.") + if(do_after(user, src, 40)) + user.visible_message("[user] removes \the [src]'s internal support struts.", \ + "You remove \the [src]'s internal support struts.") + add_hiddenprint(user) + add_fingerprint(user) + getFromPool(/obj/item/stack/rods, get_turf(src), 2) + state = 0 + update_icon() + + else if(istype(W, /obj/item/stack/rods) && state == 0 && material == /obj/item/stack/sheet/metal) //Inserting support struts, stage 0 to 1 (reinforced girder, replaces plasteel step) + var/obj/item/stack/rods/R = W + if(R.amount < 2) //Do a first check BEFORE the user begins, in case he's using a single rod + to_chat(user, "You need more rods to finish the support struts.") + return + user.visible_message("[user] starts inserting internal support struts into \the [src.]", \ + "You start inserting internal support struts into \the [src].") + if(do_after(user, src,40)) + var/obj/item/stack/rods/O = W + if(O.amount < 2) //In case our user is trying to be tricky + to_chat(user, "You need more rods to finish the support struts.") + return + O.use(2) + user.visible_message("[user] inserts internal support struts into \the [src].", \ + "You insert internal support struts into \the [src].") + add_hiddenprint(user) + add_fingerprint(user) + state = 1 + update_icon() + + else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored) //Turning normal girder into disloged girder + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] starts dislodging \the [src].", \ + "You start dislodging \the [src].") + if(do_after(user, src, 40)) + user.visible_message("[user] dislodges \the [src].", \ + "You dislodge \the [src].") + add_hiddenprint(user) + add_fingerprint(user) + anchored = 0 + update_icon() + + else if(istype(W, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/S = W + switch(S.type) + if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg) + if(state) //We are trying to finish a reinforced girder with regular metal + return + if(!anchored) + if(S.amount < 2) + return + var/pdiff = performWallPressureCheck(src.loc) + if(!pdiff) //Should really not be that precise, 10 kPa is the usual breaking point + S.use(2) + user.visible_message("[user] creates a false wall!", \ + "You create a false wall. Push on it to open or close the passage.") + var/obj/structure/falsewall/FW = new /obj/structure/falsewall (src.loc) + FW.add_hiddenprint(user) + FW.add_fingerprint(user) + qdel(src) + else + to_chat(user, "There is too much air moving through the gap! The door wouldn't stay closed if you built it.") + message_admins("Attempted false wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!") + log_admin("Attempted false wall made by [user.real_name] (user.ckey) at [loc] had a pressure difference of [pdiff]!") + return + else + if(S.amount < 2) + return ..() // ? + user.visible_message("[user] starts installing plating to \the [src].", \ + "You start installing plating to \the [src].") + if(do_after(user, src, 40)) + if(S.amount < 2) //User being tricky + return + S.use(2) + user.visible_message("[user] finishes installing plating to \the [src].", \ + "You finish installing plating to \the [src].") + var/turf/Tsrc = get_turf(src) + if(!istype(Tsrc)) return 0 + var/turf/simulated/wall/X = Tsrc.ChangeTurf(/turf/simulated/wall) + if(X) + X.add_hiddenprint(user) + X.add_fingerprint(user) + qdel(src) + return + + if(/obj/item/stack/sheet/plasteel) + + //Due to the way wall construction works, this uses both plasteel sheets immediately + if(!anchored) + if(S.amount < 2) + return + var/pdiff = performWallPressureCheck(src.loc) + if(!pdiff) + S.use(2) + user.visible_message("[user] creates a false reinforced wall!", \ + "You create a false reinforced wall. Push on it to open or close the passage.") + var/obj/structure/falserwall/FW = new /obj/structure/falserwall(src.loc) + FW.add_hiddenprint(user) + FW.add_fingerprint(user) + qdel(src) + else + to_chat(user, "There is too much air moving through the gap! The door wouldn't stay closed if you built it.") + message_admins("Attempted false rwall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!") + log_admin("Attempted false rwall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!") + return + + //We are ready to turn this reinforced girder into a beautiful reinforced wall + //The other plasteel sheet is used in the rest of the construction steps, see walls_reinforced.dm + + if(state != 2) + return //Coders against indents + user.visible_message("[user] starts installing reinforced plating to \the [src].", \ + "You start installing reinforced plating to \the [src].") + if(do_after(user, src, 50)) + S.use(1) + user.visible_message("[user] finishes installing reinforced plating to \the [src].", \ + "You finish installing reinforced plating to \the [src].") + var/turf/Tsrc = get_turf(src) + var/turf/simulated/wall/r_wall/X = Tsrc.ChangeTurf(/turf/simulated/wall/r_wall) + if(X) + X.add_hiddenprint(user) + X.add_fingerprint(user) + X.d_state = 4 //Reinforced wall not finished yet, but since we're changing to a turf, need to transfer desired variables + X.update_icon() //Tell our reinforced wall to update its icon + qdel(src) + return + + if(S.sheettype) + var/M = S.sheettype + if(!anchored) + if(S.amount < 2) + return + var/F = text2path("/obj/structure/falsewall/[M]") + if(!ispath(F)) + return + var/pdiff = performWallPressureCheck(src.loc) + if(!pdiff) + S.use(2) + user.visible_message("[user] creates a false wall!", \ + "You create a false wall. Push on it to open or close the passage.") + var/obj/structure/falsewall/FW = new F (src.loc) + FW.add_hiddenprint(user) + FW.add_fingerprint(user) + qdel(src) + else + to_chat(user, "There is too much air moving through the gap! The door wouldn't stay closed if you built it.") + message_admins("Attempted false [M] wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!") + log_admin("Attempted false [M] wall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!") + return + else + if(S.amount < 2) + return ..() + var/wallpath = text2path("/turf/simulated/wall/mineral/[M]") + if(!ispath(wallpath)) + return ..() + user.visible_message("[user] starts installing plating to \the [src].", \ + "You start installing plating to \the [src].") + if(do_after(user, src,40)) + if(S.amount < 2) //Don't be tricky now + return + S.use(2) + user.visible_message("[user] finishes installing plating to \the [src].", \ + "You finish installing plating to \the [src].") + var/turf/Tsrc = get_turf(src) + var/turf/simulated/wall/mineral/X = Tsrc.ChangeTurf(wallpath) + if(X) + X.add_hiddenprint(user) + X.add_fingerprint(user) + qdel(src) + return + + add_hiddenprint(usr) + + //Wait, what, WHAT ? + else if(istype(W, /obj/item/pipe)) + var/obj/item/pipe/P = W + if(P.pipe_type in list(0, 1, 5)) //Simple pipes, simple bends, and simple manifolds. + if(user.drop_item(P, src.loc)) + user.visible_message("[user] fits \the [P] into \the [src]", \ + "You fit \the [P] into \the [src]") + else + ..() + +/obj/structure/girder/blob_act() + if(prob(40)) + qdel(src) + +/obj/structure/girder/bullet_act(var/obj/item/projectile/Proj) + if(Proj.destroy) + src.ex_act(2) + ..() + return 0 + +/obj/structure/girder/ex_act(severity) + switch(severity) + if(1.0) + if(prob(25) && state == 2) //Strong enough to have a chance to stand if finished, but not in one piece + getFromPool(/obj/item/stack/rods, get_turf(src)) //Lose one rod + state = 0 + update_icon() + else //Not finished or not lucky + qdel(src) //No scraps + return + if(2.0) + if(prob(30)) + if(state == 2) + state = 1 + update_icon() + if(state == 1) + getFromPool(/obj/item/stack/rods, get_turf(src)) + state = 0 + update_icon() + else + getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + qdel(src) + return + if(3.0) + if((state == 0) && prob(5)) + getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + qdel(src) + else if(prob(15)) + if(state == 2) + state = 1 + update_icon() + if(state == 1) + getFromPool(/obj/item/stack/rods, get_turf(src), 2) + state = 0 + update_icon() + return + return + +/obj/structure/girder/mech_drill_act(severity) + getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + qdel(src) + return + +/obj/structure/girder/update_icon() + //Names really shouldn't be set here, but it's the only proc that checks where needed + if(anchored) + if(state) + name = "reinforced girder" + icon_state = "reinforced" + else + name = "girder" + icon_state = "girder" + else + if(state) + name = "displaced reinforced girder" + icon_state = "r_displaced" + else + name = "displaced girder" + icon_state = "displaced" + +/obj/structure/girder/projectile_check() + return PROJREACT_WALLS + +/obj/structure/girder/displaced + name = "displaced girder" + icon_state = "displaced" + anchored = 0 + +/obj/structure/girder/reinforced + name = "reinforced girder" + icon_state = "reinforced" + state = 2 + +/obj/structure/cultgirder + name = "cult girder" + icon = 'icons/obj/cult.dmi' + icon_state = "cultgirder" + anchored = 1 + density = 1 + layer = 2 + +/obj/structure/cultgirder/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + user.visible_message("[user] starts disassembling \the [src].", \ + "You start disassembling \the [src].") + if(do_after(user, src,40)) + user.visible_message("[src] dissasembles \the [src].", \ + "You dissasemble \the [src].") + //new /obj/effect/decal/remains/human(get_turf(src)) //Commented out until remains are cleanable + qdel(src) + + else if(istype(W, /obj/item/weapon/pickaxe)) + var/obj/item/weapon/pickaxe/PK = W + if(!(PK.diggables & DIG_WALLS)) + return + + user.visible_message("[user] starts [PK.drill_verb] \the [src] with \the [PK].", + "You start [PK.drill_verb] \the [src] with \the [PK].") + if(do_after(user, src,30)) + user.visible_message("[user] destroys \the [src]!", + "Your [PK] tears through the last of \the [src]!") + new /obj/effect/decal/remains/human(loc) + qdel(src) + +/obj/structure/cultgirder/attack_construct(mob/user as mob) + if(istype(user, /mob/living/simple_animal/construct/builder)) + to_chat(user, "You start repairing the girder.") + if(do_after(user,src,30)) + to_chat(user, "Girder repaired.") + var/turf/Tsrc = get_turf(src) + if(!istype(Tsrc)) return 0 + Tsrc.ChangeTurf(/turf/simulated/wall/cult) + qdel(src) + return 1 + return 0 + +/obj/structure/cultgirder/attack_animal(var/mob/living/simple_animal/M) + M.delayNextAttack(8) + if(M.environment_smash >= 2) + new /obj/effect/decal/remains/human(get_turf(src)) + M.visible_message("[M] smashes through \the [src].", \ + "You smash through \the [src].") + qdel(src) + +/obj/structure/cultgirder/blob_act() + if(prob(40)) + qdel(src) + +/obj/structure/cultgirder/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(30)) + new /obj/effect/decal/remains/human(loc) + qdel(src) + return + if(3.0) + if (prob(5)) + new /obj/effect/decal/remains/human(loc) + qdel(src) + return + return + +/obj/structure/cultgirder/mech_drill_act(severity) + new /obj/effect/decal/remains/human(loc) + qdel(src) + return diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 08ababefaf1..32b6aeaf873 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -1,253 +1,253 @@ -/obj/structure/grille - name = "grille" - desc = "A matrice of metal rods, usually used as a support for window bays, with screws to secure it to the floor." - icon = 'icons/obj/structures.dmi' - icon_state = "grille" - density = 1 - anchored = 1 - flags = FPRINT - siemens_coefficient = 1 - pressure_resistance = 5*ONE_ATMOSPHERE - layer = 2.9 - explosion_resistance = 5 - var/health = 20 //Relatively "strong" since it's hard to dismantle via brute force - var/broken = 0 - -/obj/structure/grille/examine(mob/user) - - ..() - if(!anchored) - to_chat(user, "Its screws are loose.") - if(broken) //We're not going to bother with the damage - to_chat(user, "It has been completely smashed apart, only a few rods are still holding together") - -/obj/structure/grille/cultify() - new /obj/structure/grille/cult(get_turf(src)) - returnToPool(src) - ..() - -/obj/structure/grille/proc/healthcheck(var/hitsound = 0) //Note : Doubles as the destruction proc() - if(hitsound) - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - if(health <= (0.25*initial(health)) && !broken) //Modular, 1/4th of original health. Do make sure the grille isn't broken ! - broken = 1 - icon_state = "[initial(icon_state)]-b" - density = 0 //Not blocking anything anymore - getFromPool(/obj/item/stack/rods, get_turf(src)) //One rod set - if(health <= 0) //Dead - getFromPool(/obj/item/stack/rods, get_turf(src)) //Drop the second set of rods - returnToPool(src) - -/obj/structure/grille/ex_act(severity) - switch(severity) - if(1) - health -= rand(30, 50) - if(2) - health -= rand(15, 30) - if(3) - health -= rand(5, 15) - healthcheck(hitsound = 1) - return - -/obj/structure/grille/blob_act() - health -= rand(initial(health)*0.8, initial(health)*3) //Grille will always be blasted, but chances of leaving things over - healthcheck(hitsound = 1) - -/obj/structure/grille/Bumped(atom/user) - if(ismob(user)) - shock(user, 60) //Give the user the benifit of the doubt - -/obj/structure/grille/attack_paw(mob/user as mob) - attack_hand(user) - -/obj/structure/grille/attack_hand(mob/user as mob) - var/humanverb = pick(list("kick", "slam", "elbow")) //Only verbs with a third person "s", thank you - user.delayNextAttack(8) - user.visible_message("[user] [humanverb]s \the [src].", \ - "You [humanverb] \the [src].", \ - "You hear twisting metal.") - if(M_HULK in user.mutations) - health -= 5 //Fair hit - else - health -= 3 //Do decent damage, still not as good as using a real tool - healthcheck(hitsound = 1) - shock(user, 100) //If there's power running in the grille, allow the attack but grill the user - -/obj/structure/grille/attack_alien(mob/user as mob) - if(istype(user, /mob/living/carbon/alien/larva)) - return - var/alienverb = pick(list("slam", "rip", "claw")) //See above - user.delayNextAttack(8) - user.visible_message("[user] [alienverb]s \the [src].", \ - "You [alienverb] \the [src].", \ - "You hear twisting metal.") - health -= 5 - healthcheck(hitsound = 1) - shock(user, 75) //Ditto above - -/obj/structure/grille/attack_slime(mob/user as mob) - if(!istype(user, /mob/living/carbon/slime/adult)) - return - user.delayNextAttack(8) - user.visible_message("[user] smashes against \the [src].", \ - "You smash against \the [src].", \ - "You hear twisting metal.") - health -= 3 - healthcheck(hitsound = 1) - shock(user, 100) - return - -/obj/structure/grille/attack_animal(var/mob/living/simple_animal/M as mob) - M.delayNextAttack(8) - if(M.melee_damage_upper == 0) - return - M.visible_message("[M] smashes against \the [src].", \ - "You smash against \the [src].", \ - "You hear twisting metal.") - health -= rand(M.melee_damage_lower, M.melee_damage_upper) - healthcheck(hitsound = 1) - shock(M, 100) - return - - -/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0) - if(air_group || (height == 0)) - return 1 - if(istype(mover) && mover.checkpass(PASSGRILLE)) - return 1 - else - if(istype(mover, /obj/item/projectile)) - return prob(66) //Fairly hit chance - else - return !density - -/obj/structure/grille/bullet_act(var/obj/item/projectile/Proj) - if(!Proj) - return - health -= Proj.damage //Just use the projectile damage, it already has high odds of "missing" - healthcheck(hitsound = 1) - return 0 - -/obj/structure/grille/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.delayNextAttack(8) - if(iswirecutter(W)) - if(!shock(user, 100)) //Prevent user from doing it if he gets shocked - playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) - getFromPool(/obj/item/stack/rods, get_turf(src), broken ? 1 : 2) //Drop the rods, taking account on whenever the grille is broken or not ! - returnToPool(src) - return - return //Return in case the user starts cutting and gets shocked, so that it doesn't continue downwards ! - else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored)) - if(!shock(user, 90)) - playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) - anchored = !anchored - user.visible_message("[user] [anchored ? "fastens" : "unfastens"] the grille [anchored ? "to" : "from"] the floor.", \ - "You [anchored ? "fasten" : "unfasten"] the grille [anchored ? "to" : "from"] the floor.") - return - -//Window placement - else if(istype(W, /obj/item/stack/sheet/glass)) - var/dir_to_set - if(loc == user.loc) - dir_to_set = user.dir //Whatever the user is doing, return the "normal" window placement output - else - if((x == user.x) || (y == user.y)) //Only supposed to work for cardinal directions, aka can't lay windows in diagonal directions - if(x == user.x) //User is on the same vertical plane - if(y > user.y) - dir_to_set = 2 //User is laying from the bottom - else - dir_to_set = 1 //User is laying from the top - else if(y == user.y) //User is on the same horizontal plane - if (x > user.x) - dir_to_set = 8 //User is laying from the left - else - dir_to_set = 4 //User is laying from the right - else - to_chat(user, "You can't reach far enough.") - return - for(var/obj/structure/window/P in loc) - if(P.dir == dir_to_set) - to_chat(user, "There's already a window here.")//You idiot +/obj/structure/grille + name = "grille" + desc = "A matrice of metal rods, usually used as a support for window bays, with screws to secure it to the floor." + icon = 'icons/obj/structures.dmi' + icon_state = "grille" + density = 1 + anchored = 1 + flags = FPRINT + siemens_coefficient = 1 + pressure_resistance = 5*ONE_ATMOSPHERE + layer = 2.9 + explosion_resistance = 5 + var/health = 20 //Relatively "strong" since it's hard to dismantle via brute force + var/broken = 0 - return - user.visible_message("[user] starts placing a window on \the [src].", \ - "You start placing a window on \the [src].") - if(do_after(user, src, 20)) - for(var/obj/structure/window/P in loc) - if(P.dir == dir_to_set)//checking this for a 2nd time to check if a window was made while we were waiting. +/obj/structure/grille/examine(mob/user) + + ..() + if(!anchored) + to_chat(user, "Its screws are loose.") + if(broken) //We're not going to bother with the damage + to_chat(user, "It has been completely smashed apart, only a few rods are still holding together") + +/obj/structure/grille/cultify() + new /obj/structure/grille/cult(get_turf(src)) + returnToPool(src) + ..() + +/obj/structure/grille/proc/healthcheck(var/hitsound = 0) //Note : Doubles as the destruction proc() + if(hitsound) + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + if(health <= (0.25*initial(health)) && !broken) //Modular, 1/4th of original health. Do make sure the grille isn't broken ! + broken = 1 + icon_state = "[initial(icon_state)]-b" + density = 0 //Not blocking anything anymore + getFromPool(/obj/item/stack/rods, get_turf(src)) //One rod set + if(health <= 0) //Dead + getFromPool(/obj/item/stack/rods, get_turf(src)) //Drop the second set of rods + returnToPool(src) + +/obj/structure/grille/ex_act(severity) + switch(severity) + if(1) + health -= rand(30, 50) + if(2) + health -= rand(15, 30) + if(3) + health -= rand(5, 15) + healthcheck(hitsound = 1) + return + +/obj/structure/grille/blob_act() + health -= rand(initial(health)*0.8, initial(health)*3) //Grille will always be blasted, but chances of leaving things over + healthcheck(hitsound = 1) + +/obj/structure/grille/Bumped(atom/user) + if(ismob(user)) + shock(user, 60) //Give the user the benifit of the doubt + +/obj/structure/grille/attack_paw(mob/user as mob) + attack_hand(user) + +/obj/structure/grille/attack_hand(mob/user as mob) + var/humanverb = pick(list("kick", "slam", "elbow")) //Only verbs with a third person "s", thank you + user.delayNextAttack(8) + user.visible_message("[user] [humanverb]s \the [src].", \ + "You [humanverb] \the [src].", \ + "You hear twisting metal.") + if(M_HULK in user.mutations) + health -= 5 //Fair hit + else + health -= 3 //Do decent damage, still not as good as using a real tool + healthcheck(hitsound = 1) + shock(user, 100) //If there's power running in the grille, allow the attack but grill the user + +/obj/structure/grille/attack_alien(mob/user as mob) + if(istype(user, /mob/living/carbon/alien/larva)) + return + var/alienverb = pick(list("slam", "rip", "claw")) //See above + user.delayNextAttack(8) + user.visible_message("[user] [alienverb]s \the [src].", \ + "You [alienverb] \the [src].", \ + "You hear twisting metal.") + health -= 5 + healthcheck(hitsound = 1) + shock(user, 75) //Ditto above + +/obj/structure/grille/attack_slime(mob/user as mob) + if(!istype(user, /mob/living/carbon/slime/adult)) + return + user.delayNextAttack(8) + user.visible_message("[user] smashes against \the [src].", \ + "You smash against \the [src].", \ + "You hear twisting metal.") + health -= 3 + healthcheck(hitsound = 1) + shock(user, 100) + return + +/obj/structure/grille/attack_animal(var/mob/living/simple_animal/M as mob) + M.delayNextAttack(8) + if(M.melee_damage_upper == 0) + return + M.visible_message("[M] smashes against \the [src].", \ + "You smash against \the [src].", \ + "You hear twisting metal.") + health -= rand(M.melee_damage_lower, M.melee_damage_upper) + healthcheck(hitsound = 1) + shock(M, 100) + return + + +/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0) + if(air_group || (height == 0)) + return 1 + if(istype(mover) && mover.checkpass(PASSGRILLE)) + return 1 + else + if(istype(mover, /obj/item/projectile)) + return prob(66) //Fairly hit chance + else + return !density + +/obj/structure/grille/bullet_act(var/obj/item/projectile/Proj) + if(!Proj) + return + health -= Proj.damage //Just use the projectile damage, it already has high odds of "missing" + healthcheck(hitsound = 1) + return 0 + +/obj/structure/grille/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.delayNextAttack(8) + if(iswirecutter(W)) + if(!shock(user, 100)) //Prevent user from doing it if he gets shocked + playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) + getFromPool(/obj/item/stack/rods, get_turf(src), broken ? 1 : 2) //Drop the rods, taking account on whenever the grille is broken or not ! + returnToPool(src) + return + return //Return in case the user starts cutting and gets shocked, so that it doesn't continue downwards ! + else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored)) + if(!shock(user, 90)) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) + anchored = !anchored + user.visible_message("[user] [anchored ? "fastens" : "unfastens"] the grille [anchored ? "to" : "from"] the floor.", \ + "You [anchored ? "fasten" : "unfasten"] the grille [anchored ? "to" : "from"] the floor.") + return + +//Window placement + else if(istype(W, /obj/item/stack/sheet/glass)) + var/dir_to_set + if(loc == user.loc) + dir_to_set = user.dir //Whatever the user is doing, return the "normal" window placement output + else + if((x == user.x) || (y == user.y)) //Only supposed to work for cardinal directions, aka can't lay windows in diagonal directions + if(x == user.x) //User is on the same vertical plane + if(y > user.y) + dir_to_set = 2 //User is laying from the bottom + else + dir_to_set = 1 //User is laying from the top + else if(y == user.y) //User is on the same horizontal plane + if (x > user.x) + dir_to_set = 8 //User is laying from the left + else + dir_to_set = 4 //User is laying from the right + else + to_chat(user, "You can't reach far enough.") + return + for(var/obj/structure/window/P in loc) + if(P.dir == dir_to_set) + to_chat(user, "There's already a window here.")//You idiot + + return + user.visible_message("[user] starts placing a window on \the [src].", \ + "You start placing a window on \the [src].") + if(do_after(user, src, 20)) + for(var/obj/structure/window/P in loc) + if(P.dir == dir_to_set)//checking this for a 2nd time to check if a window was made while we were waiting. to_chat(user, "There's already a window here.") - return - var/obj/item/stack/sheet/glass/glass/G = W //This fucking stacks code holy shit - var/obj/structure/window/WD = new G.created_window(loc, 0) - WD.dir = dir_to_set - WD.ini_dir = dir_to_set - WD.anchored = 0 - WD.d_state = 0 - var/obj/item/stack/ST = W //HOLY FUCKING SHIT ! - ST.use(1) - user.visible_message("[user] places \a [WD] on \the [src].", \ - "You place \a [WD] on \the [src].") - return - - switch(W.damtype) - if("fire") - health -= W.force //Fire-based tools like welding tools are ideal to work through small metal rods ! - if("brute") - health -= W.force * 0.5 //Rod matrices have an innate resistance to brute damage - shock(user, 100 * W.siemens_coefficient) //Chance of getting shocked is proportional to conductivity - healthcheck(hitsound = 1) - ..() - return - -//Shock user with probability prb (if all connections & power are working) -//Returns 1 if shocked, 0 otherwise - -/obj/structure/grille/proc/shock(mob/user as mob, prb) - if(!anchored || broken) //De-anchored and destroyed grilles are never connected to the powernet ! - return 0 - if(!prob(prb)) //If the probability roll failed, don't go further - return 0 - if(!in_range(src, user)) //To prevent TK and mech users from getting shocked - return 0 - //Process the shocking via powernet, our job is done here - var/turf/T = get_turf(src) - var/obj/structure/cable/C = T.get_cable_node() - if(C) - if(electrocute_mob(user, C, src)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - return 1 - else - return 0 - return 0 - -/obj/structure/grille/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 1500) - health -= 1 - healthcheck() //Note : This healthcheck is silent, and it's going to stay that way - ..() - -//Mapping entities and alternatives ! - -/obj/structure/grille/broken //THIS IS ONLY TO BE USED FOR MAPPING, THANK YOU FOR YOUR UNDERSTANDING - - //We need to set all variables for broken grilles manually, notably to have those show up nicely in mapmaker - broken = 1 - icon_state = "grille-b" - density = 0 //Not blocking anything anymore - New() - health -= rand(initial(health)*0.8, initial(health)*0.9) //Largely under broken threshold, this is used to adjust the health, NOT to break it - healthcheck() //Send this to healthcheck just in case we want to do something else with it - -/obj/structure/grille/cult //Used to get rid of those ugly fucking walls everywhere while still blocking air - - name = "cult grille" - desc = "A matrice built out of an unknown material, with some sort of force field blocking air around it" - icon_state = "grillecult" - health = 40 //Make it strong enough to avoid people breaking in too easily - -/obj/structure/grille/cult/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0) - if(air_group || !broken) - return 0 //Make sure air doesn't drain - ..() + return + var/obj/item/stack/sheet/glass/glass/G = W //This fucking stacks code holy shit + var/obj/structure/window/WD = new G.created_window(loc, 0) + WD.dir = dir_to_set + WD.ini_dir = dir_to_set + WD.anchored = 0 + WD.d_state = 0 + var/obj/item/stack/ST = W //HOLY FUCKING SHIT ! + ST.use(1) + user.visible_message("[user] places \a [WD] on \the [src].", \ + "You place \a [WD] on \the [src].") + return + + switch(W.damtype) + if("fire") + health -= W.force //Fire-based tools like welding tools are ideal to work through small metal rods ! + if("brute") + health -= W.force * 0.5 //Rod matrices have an innate resistance to brute damage + shock(user, 100 * W.siemens_coefficient) //Chance of getting shocked is proportional to conductivity + healthcheck(hitsound = 1) + ..() + return + +//Shock user with probability prb (if all connections & power are working) +//Returns 1 if shocked, 0 otherwise + +/obj/structure/grille/proc/shock(mob/user as mob, prb) + if(!anchored || broken) //De-anchored and destroyed grilles are never connected to the powernet ! + return 0 + if(!prob(prb)) //If the probability roll failed, don't go further + return 0 + if(!in_range(src, user)) //To prevent TK and mech users from getting shocked + return 0 + //Process the shocking via powernet, our job is done here + var/turf/T = get_turf(src) + var/obj/structure/cable/C = T.get_cable_node() + if(C) + if(electrocute_mob(user, C, src)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + return 1 + else + return 0 + return 0 + +/obj/structure/grille/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > T0C + 1500) + health -= 1 + healthcheck() //Note : This healthcheck is silent, and it's going to stay that way + ..() + +//Mapping entities and alternatives ! + +/obj/structure/grille/broken //THIS IS ONLY TO BE USED FOR MAPPING, THANK YOU FOR YOUR UNDERSTANDING + + //We need to set all variables for broken grilles manually, notably to have those show up nicely in mapmaker + broken = 1 + icon_state = "grille-b" + density = 0 //Not blocking anything anymore + New() + health -= rand(initial(health)*0.8, initial(health)*0.9) //Largely under broken threshold, this is used to adjust the health, NOT to break it + healthcheck() //Send this to healthcheck just in case we want to do something else with it + +/obj/structure/grille/cult //Used to get rid of those ugly fucking walls everywhere while still blocking air + + name = "cult grille" + desc = "A matrice built out of an unknown material, with some sort of force field blocking air around it" + icon_state = "grillecult" + health = 40 //Make it strong enough to avoid people breaking in too easily + +/obj/structure/grille/cult/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0) + if(air_group || !broken) + return 0 //Make sure air doesn't drain + ..() diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 82f41a42ce3..4db5868b402 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -1,124 +1,124 @@ -/obj/item/key/janicart - name = "janicart key" - desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." - icon_state = "jani_keys" - -/obj/item/mecha_parts/janicart_upgrade - name = "Janicart Cleaner Upgrade" - desc = "This device upgrades the janicart to automatically clean surfaces when driving." - icon = 'icons/obj/module.dmi' - icon_state = "cyborg_upgrade" - -/obj/structure/bed/chair/vehicle/janicart - name = "janicart" - icon_state = "pussywagon" - nick = "pimpin' ride" - keytype = /obj/item/key/janicart - flags = OPENCONTAINER - var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite - var/obj/item/weapon/storage/bag/trash/mybag = null - - var/upgraded = 0 - -/obj/structure/bed/chair/vehicle/janicart/New() - . = ..() - create_reagents(100) - -/obj/structure/bed/chair/vehicle/janicart/examine(mob/user) - ..() - if(in_range(src, user) && reagents.has_reagent("lube")) - to_chat(user, " Something is very off about this water.") - switch(health) - if(75 to 99) - to_chat(user, "It appears slightly dented.") - if(40 to 74) - to_chat(user, "It appears heavily dented.") - if(1 to 39) - to_chat(user, "It appears severely dented.") - if((INFINITY * -1) to 0) - to_chat(user, "It appears completely unsalvageable.") - if(mybag) - to_chat(user, "\A [mybag] is hanging on \the [nick].") - -/obj/structure/bed/chair/vehicle/janicart/attackby(obj/item/W, mob/user) - ..() - if(istype(W, /obj/item/mecha_parts/janicart_upgrade) && !upgraded && !destroyed) - if(user.drop_item(W)) - qdel(W) - to_chat(user, "You upgrade \the [nick].") - upgraded = 1 - name = "upgraded [name]" - icon_state = "pussywagon_upgraded" - else if(istype(W, /obj/item/weapon/storage/bag/trash)) - if(mybag) - to_chat(user, "There's already a [W.name] on \the [nick]!") - return - if(user.drop_item(W, src)) - to_chat(user, "You hook \the [W] onto \the [nick].") - mybag = W - -/obj/structure/bed/chair/vehicle/janicart/mop_act(obj/item/weapon/mop/M, mob/user) - if(istype(M)) - if(reagents.total_volume >= 2) - reagents.trans_to(M, 3) - to_chat(user, "You wet the mop in \the [nick].") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - if(reagents.total_volume < 1) - to_chat(user, "\The [nick] is out of water!") - return 1 - -/obj/structure/bed/chair/vehicle/janicart/verb/remove_trashbag() - set name = "Remove Trash Bag" - set category = "Object" - set src in oview(1) - - if((usr.canmove || occupant == usr) && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && usr.dexterity_check()) - mybag.forceMove(get_turf(usr)) - usr.put_in_hands(mybag) - mybag = null - -/obj/structure/bed/chair/vehicle/janicart/attack_hand(mob/user) - if(occupant && occupant == user) - return ..() - if(mybag) - remove_trashbag() - else - ..() - -/obj/structure/bed/chair/vehicle/janicart/AltClick() - if(mybag) - remove_trashbag() - return - ..() - -/obj/structure/bed/chair/vehicle/janicart/Move() - ..() - if(upgraded) - var/turf/tile = loc - if(isturf(tile)) - tile.clean_blood() - for(var/A in tile) - if(istype(A, /obj/effect)) - if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay)) - qdel(A) - else if(istype(A, /obj/item)) - var/obj/item/cleaned_item = A - cleaned_item.clean_blood() - else if(istype(A, /mob/living/carbon/human)) - var/mob/living/carbon/human/cleaned_human = A - if(cleaned_human.lying) - if(cleaned_human.head) - cleaned_human.head.clean_blood() - cleaned_human.update_inv_head(0) - if(cleaned_human.wear_suit) - cleaned_human.wear_suit.clean_blood() - cleaned_human.update_inv_wear_suit(0) - else if(cleaned_human.w_uniform) - cleaned_human.w_uniform.clean_blood() - cleaned_human.update_inv_w_uniform(0) - if(cleaned_human.shoes) - cleaned_human.shoes.clean_blood() - cleaned_human.update_inv_shoes(0) - cleaned_human.clean_blood() - to_chat(cleaned_human, "[src] cleans your face!") - return +/obj/item/key/janicart + name = "janicart key" + desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." + icon_state = "jani_keys" + +/obj/item/mecha_parts/janicart_upgrade + name = "Janicart Cleaner Upgrade" + desc = "This device upgrades the janicart to automatically clean surfaces when driving." + icon = 'icons/obj/module.dmi' + icon_state = "cyborg_upgrade" + +/obj/structure/bed/chair/vehicle/janicart + name = "janicart" + icon_state = "pussywagon" + nick = "pimpin' ride" + keytype = /obj/item/key/janicart + flags = OPENCONTAINER + var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite + var/obj/item/weapon/storage/bag/trash/mybag = null + + var/upgraded = 0 + +/obj/structure/bed/chair/vehicle/janicart/New() + . = ..() + create_reagents(100) + +/obj/structure/bed/chair/vehicle/janicart/examine(mob/user) + ..() + if(in_range(src, user) && reagents.has_reagent("lube")) + to_chat(user, " Something is very off about this water.") + switch(health) + if(75 to 99) + to_chat(user, "It appears slightly dented.") + if(40 to 74) + to_chat(user, "It appears heavily dented.") + if(1 to 39) + to_chat(user, "It appears severely dented.") + if((INFINITY * -1) to 0) + to_chat(user, "It appears completely unsalvageable.") + if(mybag) + to_chat(user, "\A [mybag] is hanging on \the [nick].") + +/obj/structure/bed/chair/vehicle/janicart/attackby(obj/item/W, mob/user) + ..() + if(istype(W, /obj/item/mecha_parts/janicart_upgrade) && !upgraded && !destroyed) + if(user.drop_item(W)) + qdel(W) + to_chat(user, "You upgrade \the [nick].") + upgraded = 1 + name = "upgraded [name]" + icon_state = "pussywagon_upgraded" + else if(istype(W, /obj/item/weapon/storage/bag/trash)) + if(mybag) + to_chat(user, "There's already a [W.name] on \the [nick]!") + return + if(user.drop_item(W, src)) + to_chat(user, "You hook \the [W] onto \the [nick].") + mybag = W + +/obj/structure/bed/chair/vehicle/janicart/mop_act(obj/item/weapon/mop/M, mob/user) + if(istype(M)) + if(reagents.total_volume >= 2) + reagents.trans_to(M, 3) + to_chat(user, "You wet the mop in \the [nick].") + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + if(reagents.total_volume < 1) + to_chat(user, "\The [nick] is out of water!") + return 1 + +/obj/structure/bed/chair/vehicle/janicart/verb/remove_trashbag() + set name = "Remove Trash Bag" + set category = "Object" + set src in oview(1) + + if((usr.canmove || occupant == usr) && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && usr.dexterity_check()) + mybag.forceMove(get_turf(usr)) + usr.put_in_hands(mybag) + mybag = null + +/obj/structure/bed/chair/vehicle/janicart/attack_hand(mob/user) + if(occupant && occupant == user) + return ..() + if(mybag) + remove_trashbag() + else + ..() + +/obj/structure/bed/chair/vehicle/janicart/AltClick() + if(mybag) + remove_trashbag() + return + ..() + +/obj/structure/bed/chair/vehicle/janicart/Move() + ..() + if(upgraded) + var/turf/tile = loc + if(isturf(tile)) + tile.clean_blood() + for(var/A in tile) + if(istype(A, /obj/effect)) + if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay)) + qdel(A) + else if(istype(A, /obj/item)) + var/obj/item/cleaned_item = A + cleaned_item.clean_blood() + else if(istype(A, /mob/living/carbon/human)) + var/mob/living/carbon/human/cleaned_human = A + if(cleaned_human.lying) + if(cleaned_human.head) + cleaned_human.head.clean_blood() + cleaned_human.update_inv_head(0) + if(cleaned_human.wear_suit) + cleaned_human.wear_suit.clean_blood() + cleaned_human.update_inv_wear_suit(0) + else if(cleaned_human.w_uniform) + cleaned_human.w_uniform.clean_blood() + cleaned_human.update_inv_w_uniform(0) + if(cleaned_human.shoes) + cleaned_human.shoes.clean_blood() + cleaned_human.update_inv_shoes(0) + cleaned_human.clean_blood() + to_chat(cleaned_human, "[src] cleans your face!") + return diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index e35e6850b4b..77217bdf31e 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -1,96 +1,96 @@ -//////Kitchen Spike - -/obj/structure/kitchenspike - name = "meat spike" - icon = 'icons/obj/kitchen.dmi' - icon_state = "spike" - desc = "A spike for collecting meat from animals" - density = 1 - anchored = 1 - - var/mob/living/occupant = null - var/meat_remaining = 0 - - var/list/allowed_mobs = list( - /mob/living/carbon/monkey/diona = "spikebloodynymph", - /mob/living/carbon/monkey = "spikebloody", - /mob/living/carbon/alien = "spikebloodygreen", - /mob/living/simple_animal/hostile/alien = "spikebloodygreen" - ) //Associated with icon states - -/obj/structure/kitchenspike/attack_paw(mob/user as mob) - return src.attack_hand(usr) - -/obj/structure/kitchenspike/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if (istype(W, /obj/item/weapon/wrench)) - if(occupant) +//////Kitchen Spike + +/obj/structure/kitchenspike + name = "meat spike" + icon = 'icons/obj/kitchen.dmi' + icon_state = "spike" + desc = "A spike for collecting meat from animals" + density = 1 + anchored = 1 + + var/mob/living/occupant = null + var/meat_remaining = 0 + + var/list/allowed_mobs = list( + /mob/living/carbon/monkey/diona = "spikebloodynymph", + /mob/living/carbon/monkey = "spikebloody", + /mob/living/carbon/alien = "spikebloodygreen", + /mob/living/simple_animal/hostile/alien = "spikebloodygreen" + ) //Associated with icon states + +/obj/structure/kitchenspike/attack_paw(mob/user as mob) + return src.attack_hand(usr) + +/obj/structure/kitchenspike/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if (istype(W, /obj/item/weapon/wrench)) + if(occupant) to_chat(user, "You can't disassemble [src] with meat and gore all over it.") - return - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 2 - qdel(src) - return - - if(istype(W,/obj/item/weapon/grab)) - return handleGrab(W,user) - -/obj/structure/kitchenspike/proc/handleGrab(obj/item/weapon/grab/G as obj, mob/user as mob) - if(!istype(G)) - return - - var/mob/living/our_mob = G.affecting - if(!istype(our_mob)) return - - if(occupant) + return + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 2 + qdel(src) + return + + if(istype(W,/obj/item/weapon/grab)) + return handleGrab(W,user) + +/obj/structure/kitchenspike/proc/handleGrab(obj/item/weapon/grab/G as obj, mob/user as mob) + if(!istype(G)) + return + + var/mob/living/our_mob = G.affecting + if(!istype(our_mob)) return + + if(occupant) to_chat(user, "[occupant.name] is already hanging from \the [src], finish collecting its meat first!") - return - - for(var/T in allowed_mobs) - if(istype(our_mob, T)) - if(our_mob.abiotic()) + return + + for(var/T in allowed_mobs) + if(istype(our_mob, T)) + if(our_mob.abiotic()) to_chat(user, "Subject may not have abiotic items on.") - return - else - src.occupant = our_mob - - if(allowed_mobs[T]) - src.icon_state = allowed_mobs[T] - else - src.icon_state = "spikebloody" - - src.meat_remaining = 1 + our_mob.size - our_mob.meat_taken - - user.visible_message("[user] has forced [our_mob] onto the spike, killing it instantly!") - - our_mob.death(0) - our_mob.ghostize() - - our_mob.forceMove(src) - - returnToPool(G) - return - -/obj/structure/kitchenspike/attack_hand(mob/user as mob) - if(..()) - return - - if(src.occupant) - if(src.meat_remaining > 0) - src.meat_remaining-- - src.occupant.drop_meat(get_turf(src)) - - if(src.meat_remaining) + return + else + src.occupant = our_mob + + if(allowed_mobs[T]) + src.icon_state = allowed_mobs[T] + else + src.icon_state = "spikebloody" + + src.meat_remaining = 1 + our_mob.size - our_mob.meat_taken + + user.visible_message("[user] has forced [our_mob] onto the spike, killing it instantly!") + + our_mob.death(0) + our_mob.ghostize() + + our_mob.forceMove(src) + + returnToPool(G) + return + +/obj/structure/kitchenspike/attack_hand(mob/user as mob) + if(..()) + return + + if(src.occupant) + if(src.meat_remaining > 0) + src.meat_remaining-- + src.occupant.drop_meat(get_turf(src)) + + if(src.meat_remaining) to_chat(user, "You remove some meat from \the [src.occupant].") - else + else to_chat(user, "You remove the last piece of meat from \the [src]!") - src.clean() - else - src.clean() - -/obj/structure/kitchenspike/proc/clean() - icon_state = initial(icon_state) - if(occupant) - qdel(occupant) - occupant = null + src.clean() + else + src.clean() + +/obj/structure/kitchenspike/proc/clean() + icon_state = initial(icon_state) + if(occupant) + qdel(occupant) + occupant = null meat_remaining = 0 \ No newline at end of file diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index a10448cfcc4..a4208220cfe 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -1,73 +1,73 @@ -/obj/structure/ladder - name = "ladder" - desc = "A sturdy metal ladder." - icon = 'icons/obj/structures.dmi' - icon_state = "ladder11" - var/id = null - var/height = 0 //the 'height' of the ladder. higher numbers are considered physically higher - var/obj/structure/ladder/down = null //the ladder below this one - var/obj/structure/ladder/up = null //the ladder above this one - -/obj/structure/ladder/New() - spawn(8) - for(var/obj/structure/ladder/L in world) - if(L.id == id) - if(L.height == (height - 1)) - down = L - continue - if(L.height == (height + 1)) - up = L - continue - - if(up && down) //if both our connections are filled - break - update_icon() - -/obj/structure/ladder/update_icon() - if(up && down) - icon_state = "ladder11" - - else if(up) - icon_state = "ladder10" - - else if(down) - icon_state = "ladder01" - - else //wtf make your ladders properly assholes - icon_state = "ladder00" - -/obj/structure/ladder/attack_hand(mob/user as mob) - if(up && down) - switch( alert("Go up or down the ladder?", "Ladder", "Up", "Down", "Cancel") ) - if("Up") - user.visible_message("[user] climbs up \the [src]!", \ - "You climb up \the [src]!") - user.loc = get_turf(up) - up.add_fingerprint(user) - if("Down") - user.visible_message("[user] climbs down \the [src]!", \ - "You climb down \the [src]!") - user.loc = get_turf(down) - down.add_fingerprint(user) - if("Cancel") - return - - else if(up) - user.visible_message("[user] climbs up \the [src]!", \ - "You climb up \the [src]!") - user.loc = get_turf(up) - up.add_fingerprint(user) - - else if(down) - user.visible_message("[user] climbs down \the [src]!", \ - "You climb down \the [src]!") - user.loc = get_turf(down) - down.add_fingerprint(user) - - add_fingerprint(user) - -/obj/structure/ladder/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/structure/ladder/attackby(obj/item/weapon/W, mob/user as mob) +/obj/structure/ladder + name = "ladder" + desc = "A sturdy metal ladder." + icon = 'icons/obj/structures.dmi' + icon_state = "ladder11" + var/id = null + var/height = 0 //the 'height' of the ladder. higher numbers are considered physically higher + var/obj/structure/ladder/down = null //the ladder below this one + var/obj/structure/ladder/up = null //the ladder above this one + +/obj/structure/ladder/New() + spawn(8) + for(var/obj/structure/ladder/L in world) + if(L.id == id) + if(L.height == (height - 1)) + down = L + continue + if(L.height == (height + 1)) + up = L + continue + + if(up && down) //if both our connections are filled + break + update_icon() + +/obj/structure/ladder/update_icon() + if(up && down) + icon_state = "ladder11" + + else if(up) + icon_state = "ladder10" + + else if(down) + icon_state = "ladder01" + + else //wtf make your ladders properly assholes + icon_state = "ladder00" + +/obj/structure/ladder/attack_hand(mob/user as mob) + if(up && down) + switch( alert("Go up or down the ladder?", "Ladder", "Up", "Down", "Cancel") ) + if("Up") + user.visible_message("[user] climbs up \the [src]!", \ + "You climb up \the [src]!") + user.loc = get_turf(up) + up.add_fingerprint(user) + if("Down") + user.visible_message("[user] climbs down \the [src]!", \ + "You climb down \the [src]!") + user.loc = get_turf(down) + down.add_fingerprint(user) + if("Cancel") + return + + else if(up) + user.visible_message("[user] climbs up \the [src]!", \ + "You climb up \the [src]!") + user.loc = get_turf(up) + up.add_fingerprint(user) + + else if(down) + user.visible_message("[user] climbs down \the [src]!", \ + "You climb down \the [src]!") + user.loc = get_turf(down) + down.add_fingerprint(user) + + add_fingerprint(user) + +/obj/structure/ladder/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/structure/ladder/attackby(obj/item/weapon/W, mob/user as mob) return attack_hand(user) \ No newline at end of file diff --git a/code/game/objects/structures/lamarr_cage.dm b/code/game/objects/structures/lamarr_cage.dm index b572ae5450f..e7b87df5b2d 100644 --- a/code/game/objects/structures/lamarr_cage.dm +++ b/code/game/objects/structures/lamarr_cage.dm @@ -1,97 +1,97 @@ -/obj/structure/lamarr - name = "Lab Cage" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "labcage1" - desc = "A glass lab container for storing interesting creatures." - density = 1 - anchored = 1 - unacidable = 1//Dissolving the case would also delete Lamarr - var/health = 30 - var/occupied = 1 - var/destroyed = 0 - -/obj/structure/lamarr/ex_act(severity) - switch(severity) - if (1) - getFromPool(/obj/item/weapon/shard, loc) - Break() - qdel(src) - if (2) - if (prob(50)) - src.health -= 15 - src.healthcheck() - if (3) - if (prob(50)) - src.health -= 5 - src.healthcheck() - - -/obj/structure/lamarr/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - src.healthcheck() - return - - -/obj/structure/lamarr/blob_act() - if (prob(75)) - getFromPool(/obj/item/weapon/shard, loc) - Break() - qdel(src) - -/obj/structure/lamarr/proc/healthcheck() - if (src.health <= 0) - if (!( src.destroyed )) - src.density = 0 - src.destroyed = 1 - getFromPool(/obj/item/weapon/shard, loc) - playsound(src, "shatter", 70, 1) - Break() - else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - return - -/obj/structure/lamarr/update_icon() - if(src.destroyed) - src.icon_state = "labcageb[src.occupied]" - else - src.icon_state = "labcage[src.occupied]" - return - - -/obj/structure/lamarr/attackby(obj/item/weapon/W as obj, mob/user as mob) - src.health -= W.force - src.healthcheck() - ..() - return - -/obj/structure/lamarr/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/lamarr/attack_hand(mob/user as mob) - if (src.destroyed) - return - else +/obj/structure/lamarr + name = "Lab Cage" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "labcage1" + desc = "A glass lab container for storing interesting creatures." + density = 1 + anchored = 1 + unacidable = 1//Dissolving the case would also delete Lamarr + var/health = 30 + var/occupied = 1 + var/destroyed = 0 + +/obj/structure/lamarr/ex_act(severity) + switch(severity) + if (1) + getFromPool(/obj/item/weapon/shard, loc) + Break() + qdel(src) + if (2) + if (prob(50)) + src.health -= 15 + src.healthcheck() + if (3) + if (prob(50)) + src.health -= 5 + src.healthcheck() + + +/obj/structure/lamarr/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + src.healthcheck() + return + + +/obj/structure/lamarr/blob_act() + if (prob(75)) + getFromPool(/obj/item/weapon/shard, loc) + Break() + qdel(src) + +/obj/structure/lamarr/proc/healthcheck() + if (src.health <= 0) + if (!( src.destroyed )) + src.density = 0 + src.destroyed = 1 + getFromPool(/obj/item/weapon/shard, loc) + playsound(src, "shatter", 70, 1) + Break() + else + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + return + +/obj/structure/lamarr/update_icon() + if(src.destroyed) + src.icon_state = "labcageb[src.occupied]" + else + src.icon_state = "labcage[src.occupied]" + return + + +/obj/structure/lamarr/attackby(obj/item/weapon/W as obj, mob/user as mob) + src.health -= W.force + src.healthcheck() + ..() + return + +/obj/structure/lamarr/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/lamarr/attack_hand(mob/user as mob) + if (src.destroyed) + return + else to_chat(usr, text("You kick the lab cage.")) - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) to_chat(O, text("[] kicks the lab cage.", usr)) - src.health -= 2 - healthcheck() - return - -/obj/structure/lamarr/proc/Break() - if(occupied) - new /obj/item/clothing/mask/facehugger/lamarr(src.loc) - occupied = 0 - update_icon() - return - -/obj/item/clothing/mask/facehugger/lamarr - name = "Lamarr" - desc = "The worst she might do is attempt to... couple with your head."//hope we don't get sued over a harmless reference, rite? - sterile = 1 - setGender(FEMALE) - -/obj/item/clothing/mask/facehugger/lamarr/New()//to prevent deleting it if aliums are disabled + src.health -= 2 + healthcheck() + return + +/obj/structure/lamarr/proc/Break() + if(occupied) + new /obj/item/clothing/mask/facehugger/lamarr(src.loc) + occupied = 0 + update_icon() + return + +/obj/item/clothing/mask/facehugger/lamarr + name = "Lamarr" + desc = "The worst she might do is attempt to... couple with your head."//hope we don't get sued over a harmless reference, rite? + sterile = 1 + setGender(FEMALE) + +/obj/item/clothing/mask/facehugger/lamarr/New()//to prevent deleting it if aliums are disabled return \ No newline at end of file diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 98a2e0b4093..66fe3ff0a68 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -1,69 +1,69 @@ -/obj/structure/lattice - desc = "A lightweight support lattice." - name = "lattice" - icon = 'icons/obj/structures.dmi' - icon_state = "latticefull" - density = 0 - anchored = 1.0 - layer = 2.3 //under pipes - // flags = CONDUCT - - canSmoothWith = "/obj/structure/lattice=0&/obj/structure/catwalk=0&/turf=0" - -/obj/structure/lattice/New(loc) - ..(loc) - - icon = 'icons/obj/smoothlattice.dmi' - - relativewall() - - relativewall_neighbours() - -/obj/structure/lattice/relativewall() - var/junction = findSmoothingNeighbors() - icon_state = "lattice[junction]" - -/obj/structure/lattice/isSmoothableNeighbor(atom/A) - if (istype(A, /turf/space)) - return 0 - - return ..() - -/obj/structure/lattice/blob_act() - qdel(src) - -/obj/structure/lattice/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - qdel(src) - -/obj/structure/lattice/attackby(obj/item/C as obj, mob/user as mob) - if(iswelder(C)) - var/obj/item/weapon/weldingtool/WeldingTool = C - if(WeldingTool.remove_fuel(0, user)) - to_chat(user, "Slicing [src] joints...") - new/obj/item/stack/rods(loc) - qdel(src) - else - var/turf/T = get_turf(src) - T.attackby(C, user) //Attacking to the lattice will attack to the space turf - -/obj/structure/lattice/wood/attackby(obj/item/C as obj, mob/user as mob) - if((C.is_sharp() >= 1.2) && (C.w_class >= 2)) // If C is able to cut down a tree - new/obj/item/stack/sheet/wood(loc) - to_chat(user, "You chop the [src] apart!") - qdel(src) - else - var/turf/T = get_turf(src) - T.attackby(C, user) //Attacking the wood will attack the turf underneath - -/obj/structure/lattice/wood - name = "wood foundations" - desc = "It's a foundation, for building on." - icon_state = "lattice-wood" - canSmoothWith = null - -/obj/structure/lattice/wood/New() +/obj/structure/lattice + desc = "A lightweight support lattice." + name = "lattice" + icon = 'icons/obj/structures.dmi' + icon_state = "latticefull" + density = 0 + anchored = 1.0 + layer = 2.3 //under pipes + // flags = CONDUCT + + canSmoothWith = "/obj/structure/lattice=0&/obj/structure/catwalk=0&/turf=0" + +/obj/structure/lattice/New(loc) + ..(loc) + + icon = 'icons/obj/smoothlattice.dmi' + + relativewall() + + relativewall_neighbours() + +/obj/structure/lattice/relativewall() + var/junction = findSmoothingNeighbors() + icon_state = "lattice[junction]" + +/obj/structure/lattice/isSmoothableNeighbor(atom/A) + if (istype(A, /turf/space)) + return 0 + + return ..() + +/obj/structure/lattice/blob_act() + qdel(src) + +/obj/structure/lattice/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + qdel(src) + +/obj/structure/lattice/attackby(obj/item/C as obj, mob/user as mob) + if(iswelder(C)) + var/obj/item/weapon/weldingtool/WeldingTool = C + if(WeldingTool.remove_fuel(0, user)) + to_chat(user, "Slicing [src] joints...") + new/obj/item/stack/rods(loc) + qdel(src) + else + var/turf/T = get_turf(src) + T.attackby(C, user) //Attacking to the lattice will attack to the space turf + +/obj/structure/lattice/wood/attackby(obj/item/C as obj, mob/user as mob) + if((C.is_sharp() >= 1.2) && (C.w_class >= 2)) // If C is able to cut down a tree + new/obj/item/stack/sheet/wood(loc) + to_chat(user, "You chop the [src] apart!") + qdel(src) + else + var/turf/T = get_turf(src) + T.attackby(C, user) //Attacking the wood will attack the turf underneath + +/obj/structure/lattice/wood + name = "wood foundations" + desc = "It's a foundation, for building on." + icon_state = "lattice-wood" + canSmoothWith = null + +/obj/structure/lattice/wood/New() return \ No newline at end of file diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index e350df67682..d1e970c6eb1 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -1,140 +1,140 @@ -//wip wip wup -/obj/structure/mirror - name = "mirror" - desc = "Mirror mirror on the wall, who's the most robust of them all?" - icon = 'icons/obj/watercloset.dmi' - icon_state = "mirror" - density = 0 - anchored = 1 - var/shattered = 0 - - -/obj/structure/mirror/attack_hand(mob/user as mob) - if(shattered) return - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(isvampire(H)) - if(!(VAMP_MATURE in H.mind.vampire.powers)) +//wip wip wup +/obj/structure/mirror + name = "mirror" + desc = "Mirror mirror on the wall, who's the most robust of them all?" + icon = 'icons/obj/watercloset.dmi' + icon_state = "mirror" + density = 0 + anchored = 1 + var/shattered = 0 + + +/obj/structure/mirror/attack_hand(mob/user as mob) + if(shattered) return + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(isvampire(H)) + if(!(VAMP_MATURE in H.mind.vampire.powers)) to_chat(H, "You don't see anything.") - return - if(user.hallucinating()) - switch(rand(1,100)) - if(1 to 20) + return + if(user.hallucinating()) + switch(rand(1,100)) + if(1 to 20) to_chat(H, "You look like [pick("a monster","a goliath","a catbeast","a ghost","a chicken","the mailman","a demon")]! Your heart skips a beat.") - H.Weaken(4) - return - if(21 to 40) + H.Weaken(4) + return + if(21 to 40) to_chat(H, "There's [pick("somebody","a monster","a little girl","a zombie","a ghost","a catbeast","a demon")] standing behind you!") - H.emote("scream",,, 1) - H.dir = turn(H.dir, 180) - return - if(41 to 50) + H.emote("scream",,, 1) + H.dir = turn(H.dir, 180) + return + if(41 to 50) to_chat(H, "You don't see anything.") - return - var/userloc = H.loc - - //see code/modules/mob/new_player/preferences.dm at approx line 545 for comments! - //this is largely copypasted from there. - - //handle facial hair (if necessary) - if(H.gender == MALE) - var/list/species_facial_hair = list() - if(H.species) - for(var/i in facial_hair_styles_list) - var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i] - if(H.species.name in tmp_facial.species_allowed) - species_facial_hair += i - else - species_facial_hair = facial_hair_styles_list - - var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair - if(userloc != H.loc) return //no tele-grooming - if(new_style) - H.f_style = new_style - - //handle normal hair - var/list/species_hair = list() - if(H.species) - for(var/i in hair_styles_list) - var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] - if(H.species.name in tmp_hair.species_allowed) - species_hair += i - else - species_hair = hair_styles_list - - var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in species_hair - if(userloc != H.loc) return //no tele-grooming - if(new_style) - H.h_style = new_style - - H.update_hair() - - -/obj/structure/mirror/proc/shatter() - if(shattered) return - shattered = 1 - icon_state = "mirror_broke" - playsound(src, "shatter", 70, 1) - desc = "Oh no, seven years of bad luck!" - - -/obj/structure/mirror/bullet_act(var/obj/item/projectile/Proj) - if(prob(Proj.damage * 2)) - if(!shattered) - shatter() - else - playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - ..() - - -/obj/structure/mirror/attackby(obj/item/I as obj, mob/user as mob) - if ((shattered) && (istype(I, /obj/item/stack/sheet/glass/glass))) - var/obj/item/stack/sheet/glass/glass/stack = I - if ((stack.amount - 2) < 0) + return + var/userloc = H.loc + + //see code/modules/mob/new_player/preferences.dm at approx line 545 for comments! + //this is largely copypasted from there. + + //handle facial hair (if necessary) + if(H.gender == MALE) + var/list/species_facial_hair = list() + if(H.species) + for(var/i in facial_hair_styles_list) + var/datum/sprite_accessory/facial_hair/tmp_facial = facial_hair_styles_list[i] + if(H.species.name in tmp_facial.species_allowed) + species_facial_hair += i + else + species_facial_hair = facial_hair_styles_list + + var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in species_facial_hair + if(userloc != H.loc) return //no tele-grooming + if(new_style) + H.f_style = new_style + + //handle normal hair + var/list/species_hair = list() + if(H.species) + for(var/i in hair_styles_list) + var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i] + if(H.species.name in tmp_hair.species_allowed) + species_hair += i + else + species_hair = hair_styles_list + + var/new_style = input(user, "Select a hair style", "Grooming") as null|anything in species_hair + if(userloc != H.loc) return //no tele-grooming + if(new_style) + H.h_style = new_style + + H.update_hair() + + +/obj/structure/mirror/proc/shatter() + if(shattered) return + shattered = 1 + icon_state = "mirror_broke" + playsound(src, "shatter", 70, 1) + desc = "Oh no, seven years of bad luck!" + + +/obj/structure/mirror/bullet_act(var/obj/item/projectile/Proj) + if(prob(Proj.damage * 2)) + if(!shattered) + shatter() + else + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + ..() + + +/obj/structure/mirror/attackby(obj/item/I as obj, mob/user as mob) + if ((shattered) && (istype(I, /obj/item/stack/sheet/glass/glass))) + var/obj/item/stack/sheet/glass/glass/stack = I + if ((stack.amount - 2) < 0) to_chat(user, "You need more glass to do that.") - else - stack.use(2) - shattered = 0 - icon_state = "mirror" - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 80, 1) - - else if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - - else if(prob(I.force * 2)) - visible_message("[user] smashes [src] with [I]!") - shatter() - else - visible_message("[user] hits [src] with [I]!") - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 70, 1) - - -/obj/structure/mirror/attack_alien(mob/user as mob) - if(islarva(user)) return - if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") - shatter() - - -/obj/structure/mirror/attack_animal(mob/user as mob) - if(!isanimal(user)) return - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) return - if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") - shatter() - - -/obj/structure/mirror/attack_slime(mob/user as mob) - if(!isslimeadult(user)) return - if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") + else + stack.use(2) + shattered = 0 + icon_state = "mirror" + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 80, 1) + + else if(shattered) + playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + + else if(prob(I.force * 2)) + visible_message("[user] smashes [src] with [I]!") + shatter() + else + visible_message("[user] hits [src] with [I]!") + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 70, 1) + + +/obj/structure/mirror/attack_alien(mob/user as mob) + if(islarva(user)) return + if(shattered) + playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + user.visible_message("[user] smashes [src]!") + shatter() + + +/obj/structure/mirror/attack_animal(mob/user as mob) + if(!isanimal(user)) return + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) return + if(shattered) + playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + user.visible_message("[user] smashes [src]!") + shatter() + + +/obj/structure/mirror/attack_slime(mob/user as mob) + if(!isslimeadult(user)) return + if(shattered) + playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + user.visible_message("[user] smashes [src]!") shatter() \ No newline at end of file diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index 7b853cc509b..517425d5c4c 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -1,57 +1,57 @@ -/obj/structure/mopbucket - name = "mop bucket" - desc = "Fill it with water, but don't forget a mop!" - icon = 'icons/obj/janitor.dmi' - icon_state = "mopbucket" - density = 1 - anchored = 0 - var/lockedby = "" - pressure_resistance = 5 - flags = FPRINT | OPENCONTAINER - var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite - -/obj/structure/mopbucket/New() - ..() - create_reagents(100) - -/obj/structure/mopbucket/attack_hand(mob/user as mob) - ..() - if(!anchored) - anchored = 1 - user.visible_message("[user] locks [src]'s wheels!") - lockedby += "\[[time_stamp()]\] [usr] ([usr.ckey]) - locked [src]" - else - anchored = 0 - user.visible_message("[user] unlocks [src]'s wheels!") - lockedby += "\[[time_stamp()]\] [usr] ([usr.ckey]) - unlocked [src]" - -/obj/structure/mopbucket/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/mop)) - return 0 - return ..() -/obj/structure/mopbucket/mop_act(obj/item/weapon/mop/M, mob/user as mob) - if (istype(M)) - if (src.reagents.total_volume >= 1) - if(M.reagents.total_volume >= 25) - return 1 - else - src.reagents.trans_to(M, 3) +/obj/structure/mopbucket + name = "mop bucket" + desc = "Fill it with water, but don't forget a mop!" + icon = 'icons/obj/janitor.dmi' + icon_state = "mopbucket" + density = 1 + anchored = 0 + var/lockedby = "" + pressure_resistance = 5 + flags = FPRINT | OPENCONTAINER + var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite + +/obj/structure/mopbucket/New() + ..() + create_reagents(100) + +/obj/structure/mopbucket/attack_hand(mob/user as mob) + ..() + if(!anchored) + anchored = 1 + user.visible_message("[user] locks [src]'s wheels!") + lockedby += "\[[time_stamp()]\] [usr] ([usr.ckey]) - locked [src]" + else + anchored = 0 + user.visible_message("[user] unlocks [src]'s wheels!") + lockedby += "\[[time_stamp()]\] [usr] ([usr.ckey]) - unlocked [src]" + +/obj/structure/mopbucket/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/mop)) + return 0 + return ..() +/obj/structure/mopbucket/mop_act(obj/item/weapon/mop/M, mob/user as mob) + if (istype(M)) + if (src.reagents.total_volume >= 1) + if(M.reagents.total_volume >= 25) + return 1 + else + src.reagents.trans_to(M, 3) to_chat(user, "You wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - else + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + else to_chat(user, "Nothing left to wet [M] with!") - return 1 - -/obj/structure/mopbucket/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(5)) - qdel(src) - return + return 1 + +/obj/structure/mopbucket/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(5)) + qdel(src) + return diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 4d6fa3fa2c5..803b234be64 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -1,434 +1,434 @@ -/* Morgue stuff - * Contains: - * Morgue - * Morgue trays - * Creamatorium - * Creamatorium trays - */ - -/* - * Morgue - */ - -/obj/structure/morgue - name = "morgue" - desc = "Used to keep bodies in until someone fetches them." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "morgue1" - dir = EAST - density = 1 - var/obj/structure/m_tray/connected = null - anchored = 1.0 - -/obj/structure/morgue/proc/update() - if (connected) - icon_state = "morgue0" - else - if (contents.len > 0) - var/list/inside = recursive_type_check(src, /mob) - if (!inside.len) - icon_state = "morgue3" // no mobs at all, but objects inside - else - for (var/mob/body in inside) - if (body && body.client) - icon_state = "morgue4" // clone that mofo - return - icon_state = "morgue2" // dead no-client mob - else - icon_state = "morgue1" - -/obj/structure/morgue/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - if(2.0) - if (prob(50)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - if(3.0) - if (prob(5)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - return - -/obj/structure/morgue/alter_health() - return src.loc - -/obj/structure/morgue/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/morgue/attack_hand(mob/user as mob) - if (src.connected) - for(var/atom/movable/A as mob|obj in src.connected.loc) - if (!( A.anchored )) - A.loc = src - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - //src.connected = null - qdel(src.connected) - src.connected = null - else - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/m_tray( src.loc ) - step(src.connected, src.dir) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, src.dir) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "morgue0" - for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc - src.connected.icon_state = "morguet" - src.connected.dir = src.dir - else - qdel(src.connected) - src.connected = null - src.add_fingerprint(user) - update() - return - -/obj/structure/morgue/attackby(P as obj, mob/user as mob) - if(iscrowbar(P)&&!contents.len) - if(do_after(user, src,50)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - new /obj/structure/closet/body_bag(src.loc) - new /obj/item/stack/sheet/metal(src.loc,5) - qdel(src) - if(iswrench(P)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(dir==4) - dir=8 - else - dir=4 - if (istype(P, /obj/item/weapon/pen)) - var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text - if (user.get_active_hand() != P) - return - if (!Adjacent(user) || user.stat) - return - t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - if (t) - src.name = text("Morgue- '[]'", t) - else - src.name = "Morgue" - src.add_fingerprint(user) - return - -/obj/structure/morgue/relaymove(mob/user as mob) - if (user.stat) - return - src.connected = new /obj/structure/m_tray( src.loc ) - step(src.connected, EAST) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, EAST) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "morgue0" - for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc - //Foreach goto(106) - src.connected.icon_state = "morguet" - else - //src.connected = null - qdel(src.connected) - return - -/obj/structure/morgue/on_log() - update() - -/* - * Morgue tray - */ -/obj/structure/m_tray - name = "morgue tray" - desc = "Apply corpse before closing." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "morguet" - density = 1 - layer = 2.0 - var/obj/structure/morgue/connected = null - anchored = 1.0 - -/obj/structure/m_tray/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if (istype(mover, /obj/item/weapon/dummy)) - return 1 - else - return ..() - -/obj/structure/m_tray/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/m_tray/attack_hand(mob/user as mob) - if (src.connected) - for(var/atom/movable/A as mob|obj in src.loc) - if (!( A.anchored )) - A.loc = src.connected - //Foreach goto(26) - src.connected.connected = null - src.connected.update() - add_fingerprint(user) - //SN src = null - qdel(src) - return - return - -/obj/structure/m_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) - return - if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) - return - O.loc = src.loc - if (user != O) - for(var/mob/B in viewers(user, 3)) - if ((B.client && !( B.blinded ))) +/* Morgue stuff + * Contains: + * Morgue + * Morgue trays + * Creamatorium + * Creamatorium trays + */ + +/* + * Morgue + */ + +/obj/structure/morgue + name = "morgue" + desc = "Used to keep bodies in until someone fetches them." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "morgue1" + dir = EAST + density = 1 + var/obj/structure/m_tray/connected = null + anchored = 1.0 + +/obj/structure/morgue/proc/update() + if (connected) + icon_state = "morgue0" + else + if (contents.len > 0) + var/list/inside = recursive_type_check(src, /mob) + if (!inside.len) + icon_state = "morgue3" // no mobs at all, but objects inside + else + for (var/mob/body in inside) + if (body && body.client) + icon_state = "morgue4" // clone that mofo + return + icon_state = "morgue2" // dead no-client mob + else + icon_state = "morgue1" + +/obj/structure/morgue/ex_act(severity) + switch(severity) + if(1.0) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + if(2.0) + if (prob(50)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + if(3.0) + if (prob(5)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + return + +/obj/structure/morgue/alter_health() + return src.loc + +/obj/structure/morgue/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/morgue/attack_hand(mob/user as mob) + if (src.connected) + for(var/atom/movable/A as mob|obj in src.connected.loc) + if (!( A.anchored )) + A.loc = src + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + //src.connected = null + qdel(src.connected) + src.connected = null + else + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + src.connected = new /obj/structure/m_tray( src.loc ) + step(src.connected, src.dir) + src.connected.layer = OBJ_LAYER + var/turf/T = get_step(src, src.dir) + if (T.contents.Find(src.connected)) + src.connected.connected = src + src.icon_state = "morgue0" + for(var/atom/movable/A as mob|obj in src) + A.loc = src.connected.loc + src.connected.icon_state = "morguet" + src.connected.dir = src.dir + else + qdel(src.connected) + src.connected = null + src.add_fingerprint(user) + update() + return + +/obj/structure/morgue/attackby(P as obj, mob/user as mob) + if(iscrowbar(P)&&!contents.len) + if(do_after(user, src,50)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + new /obj/structure/closet/body_bag(src.loc) + new /obj/item/stack/sheet/metal(src.loc,5) + qdel(src) + if(iswrench(P)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(dir==4) + dir=8 + else + dir=4 + if (istype(P, /obj/item/weapon/pen)) + var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text + if (user.get_active_hand() != P) + return + if (!Adjacent(user) || user.stat) + return + t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + if (t) + src.name = text("Morgue- '[]'", t) + else + src.name = "Morgue" + src.add_fingerprint(user) + return + +/obj/structure/morgue/relaymove(mob/user as mob) + if (user.stat) + return + src.connected = new /obj/structure/m_tray( src.loc ) + step(src.connected, EAST) + src.connected.layer = OBJ_LAYER + var/turf/T = get_step(src, EAST) + if (T.contents.Find(src.connected)) + src.connected.connected = src + src.icon_state = "morgue0" + for(var/atom/movable/A as mob|obj in src) + A.loc = src.connected.loc + //Foreach goto(106) + src.connected.icon_state = "morguet" + else + //src.connected = null + qdel(src.connected) + return + +/obj/structure/morgue/on_log() + update() + +/* + * Morgue tray + */ +/obj/structure/m_tray + name = "morgue tray" + desc = "Apply corpse before closing." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "morguet" + density = 1 + layer = 2.0 + var/obj/structure/morgue/connected = null + anchored = 1.0 + +/obj/structure/m_tray/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if (istype(mover, /obj/item/weapon/dummy)) + return 1 + else + return ..() + +/obj/structure/m_tray/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/m_tray/attack_hand(mob/user as mob) + if (src.connected) + for(var/atom/movable/A as mob|obj in src.loc) + if (!( A.anchored )) + A.loc = src.connected + //Foreach goto(26) + src.connected.connected = null + src.connected.update() + add_fingerprint(user) + //SN src = null + qdel(src) + return + return + +/obj/structure/m_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) + return + if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) + return + O.loc = src.loc + if (user != O) + for(var/mob/B in viewers(user, 3)) + if ((B.client && !( B.blinded ))) to_chat(B, text("[] stuffs [] into []!", user, O, src)) - return - - -/* - * Crematorium - */ - -/obj/structure/crematorium - name = "crematorium" - desc = "A human incinerator. Works well on barbeque nights." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "crema1" - density = 1 - var/obj/structure/c_tray/connected = null - anchored = 1.0 - var/cremating = 0 - var/id = 1 - var/locked = 0 - -/obj/structure/crematorium/proc/update() - if (cremating) - icon_state = "crema_active" - return - - if (contents.len > 0) - icon_state = "crema2" - else - icon_state = "crema1" - -/obj/structure/crematorium/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - if(2.0) - if (prob(50)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - if(3.0) - if (prob(5)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - qdel(src) - return - return - -/obj/structure/crematorium/alter_health() - return src.loc - -/obj/structure/crematorium/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/crematorium/attack_hand(mob/user as mob) -// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH -// user.show_message("Uh-oh, that was a bad idea.", 1) + return + + +/* + * Crematorium + */ + +/obj/structure/crematorium + name = "crematorium" + desc = "A human incinerator. Works well on barbeque nights." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "crema1" + density = 1 + var/obj/structure/c_tray/connected = null + anchored = 1.0 + var/cremating = 0 + var/id = 1 + var/locked = 0 + +/obj/structure/crematorium/proc/update() + if (cremating) + icon_state = "crema_active" + return + + if (contents.len > 0) + icon_state = "crema2" + else + icon_state = "crema1" + +/obj/structure/crematorium/ex_act(severity) + switch(severity) + if(1.0) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + if(2.0) + if (prob(50)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + if(3.0) + if (prob(5)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + qdel(src) + return + return + +/obj/structure/crematorium/alter_health() + return src.loc + +/obj/structure/crematorium/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/crematorium/attack_hand(mob/user as mob) +// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH +// user.show_message("Uh-oh, that was a bad idea.", 1) // to_chat(usr, "Uh-oh, that was a bad idea.") -// src:loc:poison += 20000000 -// src:loc:firelevel = src:loc:poison -// return - if (cremating) +// src:loc:poison += 20000000 +// src:loc:firelevel = src:loc:poison +// return + if (cremating) to_chat(usr, "It's locked.") - return - if ((src.connected) && (src.locked == 0)) - for(var/atom/movable/A as mob|obj in src.connected.loc) - if (!( A.anchored )) - A.loc = src - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src.connected) - src.connected = null - else if (src.locked == 0) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, SOUTH) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "crema0" - for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc - src.connected.icon_state = "cremat" - else - qdel(src.connected) - src.connected = null - src.add_fingerprint(user) - update() - -/obj/structure/crematorium/attackby(P as obj, mob/user as mob) - if (istype(P, /obj/item/weapon/pen)) - var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text - if (user.get_active_hand() != P) - return - if (!Adjacent(user) || user.stat) - return - t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - if (t) - src.name = text("Crematorium- '[]'", t) - else - src.name = "Crematorium" - src.add_fingerprint(user) - return - -/obj/structure/crematorium/relaymove(mob/user as mob) - if (user.stat || locked) - return - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) - src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, SOUTH) - if (T.contents.Find(src.connected)) - src.connected.connected = src - src.icon_state = "crema0" - for(var/atom/movable/A as mob|obj in src) - A.loc = src.connected.loc - //Foreach goto(106) - src.connected.icon_state = "cremat" - else - qdel(src.connected) - src.connected = null - return - -/obj/structure/crematorium/proc/cremate(mob/user) -// for(var/obj/machinery/crema_switch/O in src) //trying to figure a way to call the switch, too drunk to sort it out atm -// if(var/on == 1) -// return - if(cremating) - return //don't let you cremate something twice or w/e - - if(contents.len <= 0) - for (var/mob/M in viewers(src)) - M.show_message("You hear a hollow crackle.", 1) - return - - else - var/inside = get_contents_in_object(src) - - if (locate(/obj/item/weapon/disk/nuclear) in inside) + return + if ((src.connected) && (src.locked == 0)) + for(var/atom/movable/A as mob|obj in src.connected.loc) + if (!( A.anchored )) + A.loc = src + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + qdel(src.connected) + src.connected = null + else if (src.locked == 0) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + src.connected = new /obj/structure/c_tray( src.loc ) + step(src.connected, SOUTH) + src.connected.layer = OBJ_LAYER + var/turf/T = get_step(src, SOUTH) + if (T.contents.Find(src.connected)) + src.connected.connected = src + src.icon_state = "crema0" + for(var/atom/movable/A as mob|obj in src) + A.loc = src.connected.loc + src.connected.icon_state = "cremat" + else + qdel(src.connected) + src.connected = null + src.add_fingerprint(user) + update() + +/obj/structure/crematorium/attackby(P as obj, mob/user as mob) + if (istype(P, /obj/item/weapon/pen)) + var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text + if (user.get_active_hand() != P) + return + if (!Adjacent(user) || user.stat) + return + t = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + if (t) + src.name = text("Crematorium- '[]'", t) + else + src.name = "Crematorium" + src.add_fingerprint(user) + return + +/obj/structure/crematorium/relaymove(mob/user as mob) + if (user.stat || locked) + return + src.connected = new /obj/structure/c_tray( src.loc ) + step(src.connected, SOUTH) + src.connected.layer = OBJ_LAYER + var/turf/T = get_step(src, SOUTH) + if (T.contents.Find(src.connected)) + src.connected.connected = src + src.icon_state = "crema0" + for(var/atom/movable/A as mob|obj in src) + A.loc = src.connected.loc + //Foreach goto(106) + src.connected.icon_state = "cremat" + else + qdel(src.connected) + src.connected = null + return + +/obj/structure/crematorium/proc/cremate(mob/user) +// for(var/obj/machinery/crema_switch/O in src) //trying to figure a way to call the switch, too drunk to sort it out atm +// if(var/on == 1) +// return + if(cremating) + return //don't let you cremate something twice or w/e + + if(contents.len <= 0) + for (var/mob/M in viewers(src)) + M.show_message("You hear a hollow crackle.", 1) + return + + else + var/inside = get_contents_in_object(src) + + if (locate(/obj/item/weapon/disk/nuclear) in inside) to_chat(user, "You get the feeling that you shouldn't cremate one of the items in the cremator.") - return - - for (var/mob/M in viewers(src)) - if(!M.hallucinating()) - M.show_message("You hear a roar as the crematorium activates.", 1) - else - M.show_message("You hear chewing as the crematorium consumes its meal.", 1) + return + + for (var/mob/M in viewers(src)) + if(!M.hallucinating()) + M.show_message("You hear a roar as the crematorium activates.", 1) + else + M.show_message("You hear chewing as the crematorium consumes its meal.", 1) to_chat(M, 'sound/items/eatfood.ogg') - - locked = 1 - cremating = 1 - update() - - for (var/mob/living/M in inside) - if (M.stat!=2) - M.emote("scream",,, 1) - //Logging for this causes runtimes resulting in the cremator locking up. Commenting it out until that's figured out. - //M.attack_log += "\[[time_stamp()]\] Has been cremated by [user]/[user.ckey]" //No point in this when the mob's about to be qdeleted - //user.attack_log +="\[[time_stamp()]\] Cremated [M]/[M.ckey]" - //log_attack("\[[time_stamp()]\] [user]/[user.ckey] cremated [M]/[M.ckey]") - M.death(1) - M.ghostize() - qdel(M) - M = null - - for (var/obj/O in inside) //obj instead of obj/item so that bodybags and ashes get destroyed. We dont want tons and tons of ash piling up - qdel(O) - - inside = null - - new /obj/effect/decal/cleanable/ash(src) - sleep(30) - cremating = 0 - update() - locked = 0 - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) - return - - -/* - * Crematorium tray - */ -/obj/structure/c_tray - name = "crematorium tray" - desc = "Apply body before burning." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "cremat" - density = 1 - layer = 2.0 - var/obj/structure/crematorium/connected = null - anchored = 1.0 - -/obj/structure/c_tray/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if (istype(mover, /obj/item/weapon/dummy)) - return 1 - else - return ..() - -/obj/structure/c_tray/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/c_tray/attack_hand(mob/user as mob) - if (src.connected) - for(var/atom/movable/A as mob|obj in src.loc) - if (!( A.anchored )) - A.loc = src.connected - //Foreach goto(26) - src.connected.connected = null - src.connected.update() - add_fingerprint(user) - //SN src = null - qdel(src) - return - return - -/obj/structure/c_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) - return - if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) - return - O.loc = src.loc - if (user != O) - for(var/mob/B in viewers(user, 3)) - if ((B.client && !( B.blinded ))) + + locked = 1 + cremating = 1 + update() + + for (var/mob/living/M in inside) + if (M.stat!=2) + M.emote("scream",,, 1) + //Logging for this causes runtimes resulting in the cremator locking up. Commenting it out until that's figured out. + //M.attack_log += "\[[time_stamp()]\] Has been cremated by [user]/[user.ckey]" //No point in this when the mob's about to be qdeleted + //user.attack_log +="\[[time_stamp()]\] Cremated [M]/[M.ckey]" + //log_attack("\[[time_stamp()]\] [user]/[user.ckey] cremated [M]/[M.ckey]") + M.death(1) + M.ghostize() + qdel(M) + M = null + + for (var/obj/O in inside) //obj instead of obj/item so that bodybags and ashes get destroyed. We dont want tons and tons of ash piling up + qdel(O) + + inside = null + + new /obj/effect/decal/cleanable/ash(src) + sleep(30) + cremating = 0 + update() + locked = 0 + playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + return + + +/* + * Crematorium tray + */ +/obj/structure/c_tray + name = "crematorium tray" + desc = "Apply body before burning." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "cremat" + density = 1 + layer = 2.0 + var/obj/structure/crematorium/connected = null + anchored = 1.0 + +/obj/structure/c_tray/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if (istype(mover, /obj/item/weapon/dummy)) + return 1 + else + return ..() + +/obj/structure/c_tray/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/structure/c_tray/attack_hand(mob/user as mob) + if (src.connected) + for(var/atom/movable/A as mob|obj in src.loc) + if (!( A.anchored )) + A.loc = src.connected + //Foreach goto(26) + src.connected.connected = null + src.connected.update() + add_fingerprint(user) + //SN src = null + qdel(src) + return + return + +/obj/structure/c_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) + if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) + return + if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) + return + O.loc = src.loc + if (user != O) + for(var/mob/B in viewers(user, 3)) + if ((B.client && !( B.blinded ))) to_chat(B, text("[] stuffs [] into []!", user, O, src)) - //Foreach goto(99) - return - -/obj/machinery/crema_switch/attack_hand(mob/user as mob) - if (allowed(user)) - for (var/obj/structure/crematorium/C in world) - if (C.id == id) - C.cremate(user) - else + //Foreach goto(99) + return + +/obj/machinery/crema_switch/attack_hand(mob/user as mob) + if (allowed(user)) + for (var/obj/structure/crematorium/C in world) + if (C.id == id) + C.cremate(user) + else to_chat(user, "Access denied.") - return + return diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index fb73c2a456a..3f7d778e4bc 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -1,455 +1,455 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/datum/song - var/name = "Untitled" - var/list/lines = new() - var/tempo = 5 - -/obj/structure/device/piano - name = "space minimoog" - icon = 'icons/obj/musician.dmi' - icon_state = "minimoog" - anchored = 1 - density = 1 - var/datum/song/song - var/playing = 0 - var/help = 0 - var/edit = 1 - var/repeat = 0 - -/obj/structure/device/piano/New() - ..() - if(prob(50)) - name = "space minimoog" - desc = "This is a minimoog, like a space piano, but more spacey!" - icon_state = "minimoog" - else - name = "space piano" - desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." - icon_state = "piano" - -/obj/structure/device/piano/proc/playnote(var/note as text) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/datum/song + var/name = "Untitled" + var/list/lines = new() + var/tempo = 5 + +/obj/structure/device/piano + name = "space minimoog" + icon = 'icons/obj/musician.dmi' + icon_state = "minimoog" + anchored = 1 + density = 1 + var/datum/song/song + var/playing = 0 + var/help = 0 + var/edit = 1 + var/repeat = 0 + +/obj/structure/device/piano/New() + ..() + if(prob(50)) + name = "space minimoog" + desc = "This is a minimoog, like a space piano, but more spacey!" + icon_state = "minimoog" + else + name = "space piano" + desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." + icon_state = "piano" + +/obj/structure/device/piano/proc/playnote(var/note as text) // to_chat(world, "Note: [note]") - var/soundfile - /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically. - Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/ - switch(note) - if("Cn1") soundfile = 'sound/piano/Cn1.ogg' - if("C#1") soundfile = 'sound/piano/C#1.ogg' - if("Db1") soundfile = 'sound/piano/Db1.ogg' - if("Dn1") soundfile = 'sound/piano/Dn1.ogg' - if("D#1") soundfile = 'sound/piano/D#1.ogg' - if("Eb1") soundfile = 'sound/piano/Eb1.ogg' - if("En1") soundfile = 'sound/piano/En1.ogg' - if("E#1") soundfile = 'sound/piano/E#1.ogg' - if("Fb1") soundfile = 'sound/piano/Fb1.ogg' - if("Fn1") soundfile = 'sound/piano/Fn1.ogg' - if("F#1") soundfile = 'sound/piano/F#1.ogg' - if("Gb1") soundfile = 'sound/piano/Gb1.ogg' - if("Gn1") soundfile = 'sound/piano/Gn1.ogg' - if("G#1") soundfile = 'sound/piano/G#1.ogg' - if("Ab1") soundfile = 'sound/piano/Ab1.ogg' - if("An1") soundfile = 'sound/piano/An1.ogg' - if("A#1") soundfile = 'sound/piano/A#1.ogg' - if("Bb1") soundfile = 'sound/piano/Bb1.ogg' - if("Bn1") soundfile = 'sound/piano/Bn1.ogg' - if("B#1") soundfile = 'sound/piano/B#1.ogg' - if("Cb2") soundfile = 'sound/piano/Cb2.ogg' - if("Cn2") soundfile = 'sound/piano/Cn2.ogg' - if("C#2") soundfile = 'sound/piano/C#2.ogg' - if("Db2") soundfile = 'sound/piano/Db2.ogg' - if("Dn2") soundfile = 'sound/piano/Dn2.ogg' - if("D#2") soundfile = 'sound/piano/D#2.ogg' - if("Eb2") soundfile = 'sound/piano/Eb2.ogg' - if("En2") soundfile = 'sound/piano/En2.ogg' - if("E#2") soundfile = 'sound/piano/E#2.ogg' - if("Fb2") soundfile = 'sound/piano/Fb2.ogg' - if("Fn2") soundfile = 'sound/piano/Fn2.ogg' - if("F#2") soundfile = 'sound/piano/F#2.ogg' - if("Gb2") soundfile = 'sound/piano/Gb2.ogg' - if("Gn2") soundfile = 'sound/piano/Gn2.ogg' - if("G#2") soundfile = 'sound/piano/G#2.ogg' - if("Ab2") soundfile = 'sound/piano/Ab2.ogg' - if("An2") soundfile = 'sound/piano/An2.ogg' - if("A#2") soundfile = 'sound/piano/A#2.ogg' - if("Bb2") soundfile = 'sound/piano/Bb2.ogg' - if("Bn2") soundfile = 'sound/piano/Bn2.ogg' - if("B#2") soundfile = 'sound/piano/B#2.ogg' - if("Cb3") soundfile = 'sound/piano/Cb3.ogg' - if("Cn3") soundfile = 'sound/piano/Cn3.ogg' - if("C#3") soundfile = 'sound/piano/C#3.ogg' - if("Db3") soundfile = 'sound/piano/Db3.ogg' - if("Dn3") soundfile = 'sound/piano/Dn3.ogg' - if("D#3") soundfile = 'sound/piano/D#3.ogg' - if("Eb3") soundfile = 'sound/piano/Eb3.ogg' - if("En3") soundfile = 'sound/piano/En3.ogg' - if("E#3") soundfile = 'sound/piano/E#3.ogg' - if("Fb3") soundfile = 'sound/piano/Fb3.ogg' - if("Fn3") soundfile = 'sound/piano/Fn3.ogg' - if("F#3") soundfile = 'sound/piano/F#3.ogg' - if("Gb3") soundfile = 'sound/piano/Gb3.ogg' - if("Gn3") soundfile = 'sound/piano/Gn3.ogg' - if("G#3") soundfile = 'sound/piano/G#3.ogg' - if("Ab3") soundfile = 'sound/piano/Ab3.ogg' - if("An3") soundfile = 'sound/piano/An3.ogg' - if("A#3") soundfile = 'sound/piano/A#3.ogg' - if("Bb3") soundfile = 'sound/piano/Bb3.ogg' - if("Bn3") soundfile = 'sound/piano/Bn3.ogg' - if("B#3") soundfile = 'sound/piano/B#3.ogg' - if("Cb4") soundfile = 'sound/piano/Cb4.ogg' - if("Cn4") soundfile = 'sound/piano/Cn4.ogg' - if("C#4") soundfile = 'sound/piano/C#4.ogg' - if("Db4") soundfile = 'sound/piano/Db4.ogg' - if("Dn4") soundfile = 'sound/piano/Dn4.ogg' - if("D#4") soundfile = 'sound/piano/D#4.ogg' - if("Eb4") soundfile = 'sound/piano/Eb4.ogg' - if("En4") soundfile = 'sound/piano/En4.ogg' - if("E#4") soundfile = 'sound/piano/E#4.ogg' - if("Fb4") soundfile = 'sound/piano/Fb4.ogg' - if("Fn4") soundfile = 'sound/piano/Fn4.ogg' - if("F#4") soundfile = 'sound/piano/F#4.ogg' - if("Gb4") soundfile = 'sound/piano/Gb4.ogg' - if("Gn4") soundfile = 'sound/piano/Gn4.ogg' - if("G#4") soundfile = 'sound/piano/G#4.ogg' - if("Ab4") soundfile = 'sound/piano/Ab4.ogg' - if("An4") soundfile = 'sound/piano/An4.ogg' - if("A#4") soundfile = 'sound/piano/A#4.ogg' - if("Bb4") soundfile = 'sound/piano/Bb4.ogg' - if("Bn4") soundfile = 'sound/piano/Bn4.ogg' - if("B#4") soundfile = 'sound/piano/B#4.ogg' - if("Cb5") soundfile = 'sound/piano/Cb5.ogg' - if("Cn5") soundfile = 'sound/piano/Cn5.ogg' - if("C#5") soundfile = 'sound/piano/C#5.ogg' - if("Db5") soundfile = 'sound/piano/Db5.ogg' - if("Dn5") soundfile = 'sound/piano/Dn5.ogg' - if("D#5") soundfile = 'sound/piano/D#5.ogg' - if("Eb5") soundfile = 'sound/piano/Eb5.ogg' - if("En5") soundfile = 'sound/piano/En5.ogg' - if("E#5") soundfile = 'sound/piano/E#5.ogg' - if("Fb5") soundfile = 'sound/piano/Fb5.ogg' - if("Fn5") soundfile = 'sound/piano/Fn5.ogg' - if("F#5") soundfile = 'sound/piano/F#5.ogg' - if("Gb5") soundfile = 'sound/piano/Gb5.ogg' - if("Gn5") soundfile = 'sound/piano/Gn5.ogg' - if("G#5") soundfile = 'sound/piano/G#5.ogg' - if("Ab5") soundfile = 'sound/piano/Ab5.ogg' - if("An5") soundfile = 'sound/piano/An5.ogg' - if("A#5") soundfile = 'sound/piano/A#5.ogg' - if("Bb5") soundfile = 'sound/piano/Bb5.ogg' - if("Bn5") soundfile = 'sound/piano/Bn5.ogg' - if("B#5") soundfile = 'sound/piano/B#5.ogg' - if("Cb6") soundfile = 'sound/piano/Cb6.ogg' - if("Cn6") soundfile = 'sound/piano/Cn6.ogg' - if("C#6") soundfile = 'sound/piano/C#6.ogg' - if("Db6") soundfile = 'sound/piano/Db6.ogg' - if("Dn6") soundfile = 'sound/piano/Dn6.ogg' - if("D#6") soundfile = 'sound/piano/D#6.ogg' - if("Eb6") soundfile = 'sound/piano/Eb6.ogg' - if("En6") soundfile = 'sound/piano/En6.ogg' - if("E#6") soundfile = 'sound/piano/E#6.ogg' - if("Fb6") soundfile = 'sound/piano/Fb6.ogg' - if("Fn6") soundfile = 'sound/piano/Fn6.ogg' - if("F#6") soundfile = 'sound/piano/F#6.ogg' - if("Gb6") soundfile = 'sound/piano/Gb6.ogg' - if("Gn6") soundfile = 'sound/piano/Gn6.ogg' - if("G#6") soundfile = 'sound/piano/G#6.ogg' - if("Ab6") soundfile = 'sound/piano/Ab6.ogg' - if("An6") soundfile = 'sound/piano/An6.ogg' - if("A#6") soundfile = 'sound/piano/A#6.ogg' - if("Bb6") soundfile = 'sound/piano/Bb6.ogg' - if("Bn6") soundfile = 'sound/piano/Bn6.ogg' - if("B#6") soundfile = 'sound/piano/B#6.ogg' - if("Cb7") soundfile = 'sound/piano/Cb7.ogg' - if("Cn7") soundfile = 'sound/piano/Cn7.ogg' - if("C#7") soundfile = 'sound/piano/C#7.ogg' - if("Db7") soundfile = 'sound/piano/Db7.ogg' - if("Dn7") soundfile = 'sound/piano/Dn7.ogg' - if("D#7") soundfile = 'sound/piano/D#7.ogg' - if("Eb7") soundfile = 'sound/piano/Eb7.ogg' - if("En7") soundfile = 'sound/piano/En7.ogg' - if("E#7") soundfile = 'sound/piano/E#7.ogg' - if("Fb7") soundfile = 'sound/piano/Fb7.ogg' - if("Fn7") soundfile = 'sound/piano/Fn7.ogg' - if("F#7") soundfile = 'sound/piano/F#7.ogg' - if("Gb7") soundfile = 'sound/piano/Gb7.ogg' - if("Gn7") soundfile = 'sound/piano/Gn7.ogg' - if("G#7") soundfile = 'sound/piano/G#7.ogg' - if("Ab7") soundfile = 'sound/piano/Ab7.ogg' - if("An7") soundfile = 'sound/piano/An7.ogg' - if("A#7") soundfile = 'sound/piano/A#7.ogg' - if("Bb7") soundfile = 'sound/piano/Bb7.ogg' - if("Bn7") soundfile = 'sound/piano/Bn7.ogg' - if("B#7") soundfile = 'sound/piano/B#7.ogg' - if("Cb8") soundfile = 'sound/piano/Cb8.ogg' - if("Cn8") soundfile = 'sound/piano/Cn8.ogg' - if("C#8") soundfile = 'sound/piano/C#8.ogg' - if("Db8") soundfile = 'sound/piano/Db8.ogg' - if("Dn8") soundfile = 'sound/piano/Dn8.ogg' - if("D#8") soundfile = 'sound/piano/D#8.ogg' - if("Eb8") soundfile = 'sound/piano/Eb8.ogg' - if("En8") soundfile = 'sound/piano/En8.ogg' - if("E#8") soundfile = 'sound/piano/E#8.ogg' - if("Fb8") soundfile = 'sound/piano/Fb8.ogg' - if("Fn8") soundfile = 'sound/piano/Fn8.ogg' - if("F#8") soundfile = 'sound/piano/F#8.ogg' - if("Gb8") soundfile = 'sound/piano/Gb8.ogg' - if("Gn8") soundfile = 'sound/piano/Gn8.ogg' - if("G#8") soundfile = 'sound/piano/G#8.ogg' - if("Ab8") soundfile = 'sound/piano/Ab8.ogg' - if("An8") soundfile = 'sound/piano/An8.ogg' - if("A#8") soundfile = 'sound/piano/A#8.ogg' - if("Bb8") soundfile = 'sound/piano/Bb8.ogg' - if("Bn8") soundfile = 'sound/piano/Bn8.ogg' - if("B#8") soundfile = 'sound/piano/B#8.ogg' - if("Cb9") soundfile = 'sound/piano/Cb9.ogg' - if("Cn9") soundfile = 'sound/piano/Cn9.ogg' - else return - + var/soundfile + /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically. + Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/ + switch(note) + if("Cn1") soundfile = 'sound/piano/Cn1.ogg' + if("C#1") soundfile = 'sound/piano/C#1.ogg' + if("Db1") soundfile = 'sound/piano/Db1.ogg' + if("Dn1") soundfile = 'sound/piano/Dn1.ogg' + if("D#1") soundfile = 'sound/piano/D#1.ogg' + if("Eb1") soundfile = 'sound/piano/Eb1.ogg' + if("En1") soundfile = 'sound/piano/En1.ogg' + if("E#1") soundfile = 'sound/piano/E#1.ogg' + if("Fb1") soundfile = 'sound/piano/Fb1.ogg' + if("Fn1") soundfile = 'sound/piano/Fn1.ogg' + if("F#1") soundfile = 'sound/piano/F#1.ogg' + if("Gb1") soundfile = 'sound/piano/Gb1.ogg' + if("Gn1") soundfile = 'sound/piano/Gn1.ogg' + if("G#1") soundfile = 'sound/piano/G#1.ogg' + if("Ab1") soundfile = 'sound/piano/Ab1.ogg' + if("An1") soundfile = 'sound/piano/An1.ogg' + if("A#1") soundfile = 'sound/piano/A#1.ogg' + if("Bb1") soundfile = 'sound/piano/Bb1.ogg' + if("Bn1") soundfile = 'sound/piano/Bn1.ogg' + if("B#1") soundfile = 'sound/piano/B#1.ogg' + if("Cb2") soundfile = 'sound/piano/Cb2.ogg' + if("Cn2") soundfile = 'sound/piano/Cn2.ogg' + if("C#2") soundfile = 'sound/piano/C#2.ogg' + if("Db2") soundfile = 'sound/piano/Db2.ogg' + if("Dn2") soundfile = 'sound/piano/Dn2.ogg' + if("D#2") soundfile = 'sound/piano/D#2.ogg' + if("Eb2") soundfile = 'sound/piano/Eb2.ogg' + if("En2") soundfile = 'sound/piano/En2.ogg' + if("E#2") soundfile = 'sound/piano/E#2.ogg' + if("Fb2") soundfile = 'sound/piano/Fb2.ogg' + if("Fn2") soundfile = 'sound/piano/Fn2.ogg' + if("F#2") soundfile = 'sound/piano/F#2.ogg' + if("Gb2") soundfile = 'sound/piano/Gb2.ogg' + if("Gn2") soundfile = 'sound/piano/Gn2.ogg' + if("G#2") soundfile = 'sound/piano/G#2.ogg' + if("Ab2") soundfile = 'sound/piano/Ab2.ogg' + if("An2") soundfile = 'sound/piano/An2.ogg' + if("A#2") soundfile = 'sound/piano/A#2.ogg' + if("Bb2") soundfile = 'sound/piano/Bb2.ogg' + if("Bn2") soundfile = 'sound/piano/Bn2.ogg' + if("B#2") soundfile = 'sound/piano/B#2.ogg' + if("Cb3") soundfile = 'sound/piano/Cb3.ogg' + if("Cn3") soundfile = 'sound/piano/Cn3.ogg' + if("C#3") soundfile = 'sound/piano/C#3.ogg' + if("Db3") soundfile = 'sound/piano/Db3.ogg' + if("Dn3") soundfile = 'sound/piano/Dn3.ogg' + if("D#3") soundfile = 'sound/piano/D#3.ogg' + if("Eb3") soundfile = 'sound/piano/Eb3.ogg' + if("En3") soundfile = 'sound/piano/En3.ogg' + if("E#3") soundfile = 'sound/piano/E#3.ogg' + if("Fb3") soundfile = 'sound/piano/Fb3.ogg' + if("Fn3") soundfile = 'sound/piano/Fn3.ogg' + if("F#3") soundfile = 'sound/piano/F#3.ogg' + if("Gb3") soundfile = 'sound/piano/Gb3.ogg' + if("Gn3") soundfile = 'sound/piano/Gn3.ogg' + if("G#3") soundfile = 'sound/piano/G#3.ogg' + if("Ab3") soundfile = 'sound/piano/Ab3.ogg' + if("An3") soundfile = 'sound/piano/An3.ogg' + if("A#3") soundfile = 'sound/piano/A#3.ogg' + if("Bb3") soundfile = 'sound/piano/Bb3.ogg' + if("Bn3") soundfile = 'sound/piano/Bn3.ogg' + if("B#3") soundfile = 'sound/piano/B#3.ogg' + if("Cb4") soundfile = 'sound/piano/Cb4.ogg' + if("Cn4") soundfile = 'sound/piano/Cn4.ogg' + if("C#4") soundfile = 'sound/piano/C#4.ogg' + if("Db4") soundfile = 'sound/piano/Db4.ogg' + if("Dn4") soundfile = 'sound/piano/Dn4.ogg' + if("D#4") soundfile = 'sound/piano/D#4.ogg' + if("Eb4") soundfile = 'sound/piano/Eb4.ogg' + if("En4") soundfile = 'sound/piano/En4.ogg' + if("E#4") soundfile = 'sound/piano/E#4.ogg' + if("Fb4") soundfile = 'sound/piano/Fb4.ogg' + if("Fn4") soundfile = 'sound/piano/Fn4.ogg' + if("F#4") soundfile = 'sound/piano/F#4.ogg' + if("Gb4") soundfile = 'sound/piano/Gb4.ogg' + if("Gn4") soundfile = 'sound/piano/Gn4.ogg' + if("G#4") soundfile = 'sound/piano/G#4.ogg' + if("Ab4") soundfile = 'sound/piano/Ab4.ogg' + if("An4") soundfile = 'sound/piano/An4.ogg' + if("A#4") soundfile = 'sound/piano/A#4.ogg' + if("Bb4") soundfile = 'sound/piano/Bb4.ogg' + if("Bn4") soundfile = 'sound/piano/Bn4.ogg' + if("B#4") soundfile = 'sound/piano/B#4.ogg' + if("Cb5") soundfile = 'sound/piano/Cb5.ogg' + if("Cn5") soundfile = 'sound/piano/Cn5.ogg' + if("C#5") soundfile = 'sound/piano/C#5.ogg' + if("Db5") soundfile = 'sound/piano/Db5.ogg' + if("Dn5") soundfile = 'sound/piano/Dn5.ogg' + if("D#5") soundfile = 'sound/piano/D#5.ogg' + if("Eb5") soundfile = 'sound/piano/Eb5.ogg' + if("En5") soundfile = 'sound/piano/En5.ogg' + if("E#5") soundfile = 'sound/piano/E#5.ogg' + if("Fb5") soundfile = 'sound/piano/Fb5.ogg' + if("Fn5") soundfile = 'sound/piano/Fn5.ogg' + if("F#5") soundfile = 'sound/piano/F#5.ogg' + if("Gb5") soundfile = 'sound/piano/Gb5.ogg' + if("Gn5") soundfile = 'sound/piano/Gn5.ogg' + if("G#5") soundfile = 'sound/piano/G#5.ogg' + if("Ab5") soundfile = 'sound/piano/Ab5.ogg' + if("An5") soundfile = 'sound/piano/An5.ogg' + if("A#5") soundfile = 'sound/piano/A#5.ogg' + if("Bb5") soundfile = 'sound/piano/Bb5.ogg' + if("Bn5") soundfile = 'sound/piano/Bn5.ogg' + if("B#5") soundfile = 'sound/piano/B#5.ogg' + if("Cb6") soundfile = 'sound/piano/Cb6.ogg' + if("Cn6") soundfile = 'sound/piano/Cn6.ogg' + if("C#6") soundfile = 'sound/piano/C#6.ogg' + if("Db6") soundfile = 'sound/piano/Db6.ogg' + if("Dn6") soundfile = 'sound/piano/Dn6.ogg' + if("D#6") soundfile = 'sound/piano/D#6.ogg' + if("Eb6") soundfile = 'sound/piano/Eb6.ogg' + if("En6") soundfile = 'sound/piano/En6.ogg' + if("E#6") soundfile = 'sound/piano/E#6.ogg' + if("Fb6") soundfile = 'sound/piano/Fb6.ogg' + if("Fn6") soundfile = 'sound/piano/Fn6.ogg' + if("F#6") soundfile = 'sound/piano/F#6.ogg' + if("Gb6") soundfile = 'sound/piano/Gb6.ogg' + if("Gn6") soundfile = 'sound/piano/Gn6.ogg' + if("G#6") soundfile = 'sound/piano/G#6.ogg' + if("Ab6") soundfile = 'sound/piano/Ab6.ogg' + if("An6") soundfile = 'sound/piano/An6.ogg' + if("A#6") soundfile = 'sound/piano/A#6.ogg' + if("Bb6") soundfile = 'sound/piano/Bb6.ogg' + if("Bn6") soundfile = 'sound/piano/Bn6.ogg' + if("B#6") soundfile = 'sound/piano/B#6.ogg' + if("Cb7") soundfile = 'sound/piano/Cb7.ogg' + if("Cn7") soundfile = 'sound/piano/Cn7.ogg' + if("C#7") soundfile = 'sound/piano/C#7.ogg' + if("Db7") soundfile = 'sound/piano/Db7.ogg' + if("Dn7") soundfile = 'sound/piano/Dn7.ogg' + if("D#7") soundfile = 'sound/piano/D#7.ogg' + if("Eb7") soundfile = 'sound/piano/Eb7.ogg' + if("En7") soundfile = 'sound/piano/En7.ogg' + if("E#7") soundfile = 'sound/piano/E#7.ogg' + if("Fb7") soundfile = 'sound/piano/Fb7.ogg' + if("Fn7") soundfile = 'sound/piano/Fn7.ogg' + if("F#7") soundfile = 'sound/piano/F#7.ogg' + if("Gb7") soundfile = 'sound/piano/Gb7.ogg' + if("Gn7") soundfile = 'sound/piano/Gn7.ogg' + if("G#7") soundfile = 'sound/piano/G#7.ogg' + if("Ab7") soundfile = 'sound/piano/Ab7.ogg' + if("An7") soundfile = 'sound/piano/An7.ogg' + if("A#7") soundfile = 'sound/piano/A#7.ogg' + if("Bb7") soundfile = 'sound/piano/Bb7.ogg' + if("Bn7") soundfile = 'sound/piano/Bn7.ogg' + if("B#7") soundfile = 'sound/piano/B#7.ogg' + if("Cb8") soundfile = 'sound/piano/Cb8.ogg' + if("Cn8") soundfile = 'sound/piano/Cn8.ogg' + if("C#8") soundfile = 'sound/piano/C#8.ogg' + if("Db8") soundfile = 'sound/piano/Db8.ogg' + if("Dn8") soundfile = 'sound/piano/Dn8.ogg' + if("D#8") soundfile = 'sound/piano/D#8.ogg' + if("Eb8") soundfile = 'sound/piano/Eb8.ogg' + if("En8") soundfile = 'sound/piano/En8.ogg' + if("E#8") soundfile = 'sound/piano/E#8.ogg' + if("Fb8") soundfile = 'sound/piano/Fb8.ogg' + if("Fn8") soundfile = 'sound/piano/Fn8.ogg' + if("F#8") soundfile = 'sound/piano/F#8.ogg' + if("Gb8") soundfile = 'sound/piano/Gb8.ogg' + if("Gn8") soundfile = 'sound/piano/Gn8.ogg' + if("G#8") soundfile = 'sound/piano/G#8.ogg' + if("Ab8") soundfile = 'sound/piano/Ab8.ogg' + if("An8") soundfile = 'sound/piano/An8.ogg' + if("A#8") soundfile = 'sound/piano/A#8.ogg' + if("Bb8") soundfile = 'sound/piano/Bb8.ogg' + if("Bn8") soundfile = 'sound/piano/Bn8.ogg' + if("B#8") soundfile = 'sound/piano/B#8.ogg' + if("Cb9") soundfile = 'sound/piano/Cb9.ogg' + if("Cn9") soundfile = 'sound/piano/Cn9.ogg' + else return + // to_chat(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 - var/cur_oct[7] - var/cur_acc[7] - for(var/i = 1 to 7) - cur_oct[i] = "3" - cur_acc[i] = "n" - - for(var/line in song.lines) + 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 + var/cur_oct[7] + var/cur_acc[7] + for(var/i = 1 to 7) + cur_oct[i] = "3" + cur_acc[i] = "n" + + for(var/line in song.lines) // to_chat(world, line) - for(var/beat in text2list(lowertext(line), ",")) + for(var/beat in text2list(lowertext(line), ",")) // to_chat(world, "beat: [beat]") - var/list/notes = text2list(beat, "/") - for(var/note in text2list(notes[1], "-")) + var/list/notes = text2list(beat, "/") + for(var/note in text2list(notes[1], "-")) // to_chat(world, "note: [note]") - if(!playing || !anchored)//If the piano is playing, or is loose - playing = 0 - return - if(length(note) == 0) - continue + if(!playing || !anchored)//If the piano is playing, or is loose + playing = 0 + return + if(length(note) == 0) + continue // to_chat(world, "Parse: [copytext(note,1,2)]") - var/cur_note = text2ascii(note) - 96 - if(cur_note < 1 || cur_note > 7) - continue - for(var/i=2 to length(note)) - var/ni = copytext(note,i,i+1) - if(!text2num(ni)) - if(ni == "#" || ni == "b" || ni == "n") - cur_acc[cur_note] = ni - else if(ni == "s") - cur_acc[cur_note] = "#" // so shift is never required - else - cur_oct[cur_note] = ni - playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note]) - if(notes.len >= 2 && text2num(notes[2])) - sleep(song.tempo / text2num(notes[2])) - else - sleep(song.tempo) - if(repeat > 0) - repeat-- //Infinite loops are baaaad. - while(repeat > 0) - playing = 0 - updateUsrDialog() - -/obj/structure/device/piano/attack_paw(var/mob/user) - if (!user.dexterity_check()) + var/cur_note = text2ascii(note) - 96 + if(cur_note < 1 || cur_note > 7) + continue + for(var/i=2 to length(note)) + var/ni = copytext(note,i,i+1) + if(!text2num(ni)) + if(ni == "#" || ni == "b" || ni == "n") + cur_acc[cur_note] = ni + else if(ni == "s") + cur_acc[cur_note] = "#" // so shift is never required + else + cur_oct[cur_note] = ni + playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note]) + if(notes.len >= 2 && text2num(notes[2])) + sleep(song.tempo / text2num(notes[2])) + else + sleep(song.tempo) + if(repeat > 0) + repeat-- //Infinite loops are baaaad. + while(repeat > 0) + playing = 0 + updateUsrDialog() + +/obj/structure/device/piano/attack_paw(var/mob/user) + if (!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") - return - attack_hand(user) - -/obj/structure/device/piano/attack_hand(var/mob/user as mob) - if(!anchored) - return - - usr.machine = src - var/dat = "Piano" - - if(song) - if(song.lines.len > 0 && !(playing)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\\musician.dm:262: dat += "Play Song

    " - dat += {"Play Song

    - Repeat Song: [repeat] times.

    "} - // END AUTOFIX - if(playing) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\\musician.dm:265: dat += "Stop Playing
    " - dat += {"Stop Playing
    - Repeats left: [repeat].

    "} - // END AUTOFIX - if(!edit) - dat += "Show Editor

    " - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\\musician.dm:270: dat += "Hide Editor
    " - dat += {"Hide Editor
    - Start a New Song
    - Import a Song

    "} - // END AUTOFIX - if(song) - var/calctempo = (10/song.tempo)*60 - dat += "Tempo : -- [calctempo] BPM ++

    " - var/linecount = 0 - for(var/line in song.lines) - linecount += 1 - dat += "Line [linecount]: [line] Delete Line Modify Line
    " - dat += "Add Line

    " - if(help) - dat += "Hide Help
    " - dat += {" - Lines are a series of chords, separated by commas (,), each with notes seperated by hyphens (-).
    - Every note in a chord will play together, with chord timed by the tempo.
    -
    - Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
    - By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
    - Example: C,D,E,F,G,A,B will play a C major scale.
    - After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
    - Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
    - A pause may be denoted by an empty chord: C,E,,C,G
    - To make a chord be a different time, end it with /x, where the chord length will be length
    - defined by tempo / x: C,G/2,E/4
    - Combined, an example is: E-E4/4,/2,G#/8,B/8,E3-E4/4 -
    - Lines may be up to 50 characters.
    - A song may only contain up to 50 lines.
    - "} - else - dat += "Show Help
    " - dat += "" - user << browse(dat, "window=piano;size=700x300") - onclose(user, "piano") - -/obj/structure/device/piano/Topic(href, href_list) - if(..()) - return - if(issilicon(usr) || !anchored || !usr.canmove) - return - - usr.set_machine(src) - - if(href_list["newsong"]) - song = new() - else if(song) - if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. - if(playing) return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. - var/tempnum = input("How many times do you want to repeat this piece? (max:10)") as num|null - if(tempnum > 10) - tempnum = 10 - if(tempnum < 0) - tempnum = 0 - repeat = round(tempnum) - - else if(href_list["tempo"]) - song.tempo += round(text2num(href_list["tempo"])) - if(song.tempo < 1) - song.tempo = 1 - - else if(href_list["play"]) - if(song) - playing = 1 - spawn() playsong() - - else if(href_list["newline"]) - var/newline = html_encode(input("Enter your line: ", "Piano") as text|null) - if(!newline) - return - if(song.lines.len > 50) - return - if(length(newline) > 50) - newline = copytext(newline, 1, 50) - song.lines.Add(newline) - - else if(href_list["deleteline"]) - var/num = round(text2num(href_list["deleteline"])) - if(num > song.lines.len || num < 1) - return - song.lines.Cut(num, num+1) - - else if(href_list["modifyline"]) - var/num = round(text2num(href_list["modifyline"]),1) - var/content = html_encode(input("Enter your line: ", "Piano", song.lines[num]) as text|null) - if(!content) - return - if(length(content) > 50) - content = copytext(content, 1, 50) - if(num > song.lines.len || num < 1) - return - song.lines[num] = content - - else if(href_list["stop"]) - playing = 0 - - else if(href_list["help"]) - help = text2num(href_list["help"]) - 1 - - else if(href_list["edit"]) - edit = text2num(href_list["edit"]) - 1 - - else if(href_list["import"]) - var/t = "" - do - t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", src.name), t) as message) - if (!in_range(src, usr)) - return - - if(length(t) >= 3072) - var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") - if(cont == "no") - break - while(length(t) > 3072) - - //split into lines - spawn() - var/list/lines = text2list(t, "\n") - var/tempo = 5 - if(copytext(lines[1],1,6) == "BPM: ") - tempo = 600 / text2num(copytext(lines[1],6)) - lines.Cut(1,2) - if(lines.len > 50) + return + attack_hand(user) + +/obj/structure/device/piano/attack_hand(var/mob/user as mob) + if(!anchored) + return + + usr.machine = src + var/dat = "Piano" + + if(song) + if(song.lines.len > 0 && !(playing)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\\musician.dm:262: dat += "Play Song

    " + dat += {"Play Song

    + Repeat Song: [repeat] times.

    "} + // END AUTOFIX + if(playing) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\\musician.dm:265: dat += "Stop Playing
    " + dat += {"Stop Playing
    + Repeats left: [repeat].

    "} + // END AUTOFIX + if(!edit) + dat += "Show Editor

    " + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\\musician.dm:270: dat += "Hide Editor
    " + dat += {"Hide Editor
    + Start a New Song
    + Import a Song

    "} + // END AUTOFIX + if(song) + var/calctempo = (10/song.tempo)*60 + dat += "Tempo : -- [calctempo] BPM ++

    " + var/linecount = 0 + for(var/line in song.lines) + linecount += 1 + dat += "Line [linecount]: [line] Delete Line Modify Line
    " + dat += "Add Line

    " + if(help) + dat += "Hide Help
    " + dat += {" + Lines are a series of chords, separated by commas (,), each with notes seperated by hyphens (-).
    + Every note in a chord will play together, with chord timed by the tempo.
    +
    + Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
    + By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
    + Example: C,D,E,F,G,A,B will play a C major scale.
    + After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
    + Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
    + A pause may be denoted by an empty chord: C,E,,C,G
    + To make a chord be a different time, end it with /x, where the chord length will be length
    + defined by tempo / x: C,G/2,E/4
    + Combined, an example is: E-E4/4,/2,G#/8,B/8,E3-E4/4 +
    + Lines may be up to 50 characters.
    + A song may only contain up to 50 lines.
    + "} + else + dat += "Show Help
    " + dat += "" + user << browse(dat, "window=piano;size=700x300") + onclose(user, "piano") + +/obj/structure/device/piano/Topic(href, href_list) + if(..()) + return + if(issilicon(usr) || !anchored || !usr.canmove) + return + + usr.set_machine(src) + + if(href_list["newsong"]) + song = new() + else if(song) + if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. + if(playing) return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. + var/tempnum = input("How many times do you want to repeat this piece? (max:10)") as num|null + if(tempnum > 10) + tempnum = 10 + if(tempnum < 0) + tempnum = 0 + repeat = round(tempnum) + + else if(href_list["tempo"]) + song.tempo += round(text2num(href_list["tempo"])) + if(song.tempo < 1) + song.tempo = 1 + + else if(href_list["play"]) + if(song) + playing = 1 + spawn() playsong() + + else if(href_list["newline"]) + var/newline = html_encode(input("Enter your line: ", "Piano") as text|null) + if(!newline) + return + if(song.lines.len > 50) + return + if(length(newline) > 50) + newline = copytext(newline, 1, 50) + song.lines.Add(newline) + + else if(href_list["deleteline"]) + var/num = round(text2num(href_list["deleteline"])) + if(num > song.lines.len || num < 1) + return + song.lines.Cut(num, num+1) + + else if(href_list["modifyline"]) + var/num = round(text2num(href_list["modifyline"]),1) + var/content = html_encode(input("Enter your line: ", "Piano", song.lines[num]) as text|null) + if(!content) + return + if(length(content) > 50) + content = copytext(content, 1, 50) + if(num > song.lines.len || num < 1) + return + song.lines[num] = content + + else if(href_list["stop"]) + playing = 0 + + else if(href_list["help"]) + help = text2num(href_list["help"]) - 1 + + else if(href_list["edit"]) + edit = text2num(href_list["edit"]) - 1 + + else if(href_list["import"]) + var/t = "" + do + t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", src.name), t) as message) + if (!in_range(src, usr)) + return + + if(length(t) >= 3072) + var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") + if(cont == "no") + break + while(length(t) > 3072) + + //split into lines + spawn() + var/list/lines = text2list(t, "\n") + var/tempo = 5 + if(copytext(lines[1],1,6) == "BPM: ") + tempo = 600 / text2num(copytext(lines[1],6)) + lines.Cut(1,2) + if(lines.len > 50) to_chat(usr, "Too many lines!") - lines.Cut(51) - var/linenum = 1 - for(var/l in lines) - if(length(l) > 50) + lines.Cut(51) + var/linenum = 1 + for(var/l in lines) + if(length(l) > 50) to_chat(usr, "Line [linenum] too long!") - lines.Remove(l) - else - linenum++ - song = new() - song.lines = lines - song.tempo = tempo - src.updateUsrDialog() - - add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/structure/device/piano/attackby(obj/item/O as obj, mob/user as mob) - if (istype(O, /obj/item/weapon/wrench)) - if (anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + lines.Remove(l) + else + linenum++ + song = new() + song.lines = lines + song.tempo = tempo + src.updateUsrDialog() + + add_fingerprint(usr) + src.updateUsrDialog() + return + +/obj/structure/device/piano/attackby(obj/item/O as obj, mob/user as mob) + if (istype(O, /obj/item/weapon/wrench)) + if (anchored) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You begin to loosen \the [src]'s casters...") - if (do_after(user, src, 40)) - user.visible_message( \ - "[user] loosens \the [src]'s casters.", \ - "You have loosened \the [src]. Now it can be pulled somewhere else.", \ - "You hear ratchet.") - src.anchored = 0 - else - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if (do_after(user, src, 40)) + user.visible_message( \ + "[user] loosens \the [src]'s casters.", \ + "You have loosened \the [src]. Now it can be pulled somewhere else.", \ + "You hear ratchet.") + src.anchored = 0 + else + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You begin to tighten \the [src] to the floor...") - if (do_after(user, src, 20)) - user.visible_message( \ - "[user] tightens \the [src]'s casters.", \ - "You have tightened \the [src]'s casters. Now it can be played again.", \ - "You hear ratchet.") - src.anchored = 1 - else - ..() + if (do_after(user, src, 20)) + user.visible_message( \ + "[user] tightens \the [src]'s casters.", \ + "You have tightened \the [src]'s casters. Now it can be played again.", \ + "You hear ratchet.") + src.anchored = 1 + else + ..() diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index 503db81a49a..0b46c228a5f 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -1,84 +1,84 @@ -/obj/structure/noticeboard - name = "notice board" - desc = "A board for pinning important notices upon." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "nboard00" - flags = FPRINT - density = 0 - anchored = 1 - var/notices = 0 - -/obj/structure/noticeboard/initialize() - for(var/obj/item/I in loc) - if(notices > 4) break - if(istype(I, /obj/item/weapon/paper)) - I.loc = src - notices++ - icon_state = "nboard0[notices]" - -//attaching papers!! -/obj/structure/noticeboard/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) - if(iswrench(O)) +/obj/structure/noticeboard + name = "notice board" + desc = "A board for pinning important notices upon." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "nboard00" + flags = FPRINT + density = 0 + anchored = 1 + var/notices = 0 + +/obj/structure/noticeboard/initialize() + for(var/obj/item/I in loc) + if(notices > 4) break + if(istype(I, /obj/item/weapon/paper)) + I.loc = src + notices++ + icon_state = "nboard0[notices]" + +//attaching papers!! +/obj/structure/noticeboard/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) + if(iswrench(O)) to_chat(user, "You disassemble \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - new /obj/item/stack/sheet/wood (src.loc,2) - qdel(src) - if(istype(O, /obj/item/weapon/paper)) - if(notices < 5) - O.add_fingerprint(user) - add_fingerprint(user) - user.drop_item(O,src, force_drop = 1) - notices++ - icon_state = "nboard0[notices]" //update sprite + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + new /obj/item/stack/sheet/wood (src.loc,2) + qdel(src) + if(istype(O, /obj/item/weapon/paper)) + if(notices < 5) + O.add_fingerprint(user) + add_fingerprint(user) + user.drop_item(O,src, force_drop = 1) + notices++ + icon_state = "nboard0[notices]" //update sprite to_chat(user, "You pin the paper to the noticeboard.") - else + else to_chat(user, "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.") - -/obj/structure/noticeboard/attack_hand(user as mob) - var/dat = "Noticeboard
    " - for(var/obj/item/weapon/paper/P in src) - dat += "[P.name] Write Remove
    " - user << browse("Notices[dat]","window=noticeboard") - onclose(user, "noticeboard") - - -/obj/structure/noticeboard/Topic(href, href_list) - ..() - usr.set_machine(src) - if(href_list["remove"]) - if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open - return - var/obj/item/P = locate(href_list["remove"]) - if((P && P.loc == src)) - P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck - P.add_fingerprint(usr) - add_fingerprint(usr) - notices-- - icon_state = "nboard0[notices]" - - if(href_list["write"]) - if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open - return - var/obj/item/P = locate(href_list["write"]) - - if((P && P.loc == src)) //ifthe paper's on the board - if(istype(usr.r_hand, /obj/item/weapon/pen)) //and you're holding a pen - add_fingerprint(usr) - P.attackby(usr.r_hand, usr) //then do ittttt - else - if(istype(usr.l_hand, /obj/item/weapon/pen)) //check other hand for pen - add_fingerprint(usr) - P.attackby(usr.l_hand, usr) - else + +/obj/structure/noticeboard/attack_hand(user as mob) + var/dat = "Noticeboard
    " + for(var/obj/item/weapon/paper/P in src) + dat += "[P.name] Write Remove
    " + user << browse("Notices[dat]","window=noticeboard") + onclose(user, "noticeboard") + + +/obj/structure/noticeboard/Topic(href, href_list) + ..() + usr.set_machine(src) + if(href_list["remove"]) + if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open + return + var/obj/item/P = locate(href_list["remove"]) + if((P && P.loc == src)) + P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck + P.add_fingerprint(usr) + add_fingerprint(usr) + notices-- + icon_state = "nboard0[notices]" + + if(href_list["write"]) + if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open + return + var/obj/item/P = locate(href_list["write"]) + + if((P && P.loc == src)) //ifthe paper's on the board + if(istype(usr.r_hand, /obj/item/weapon/pen)) //and you're holding a pen + add_fingerprint(usr) + P.attackby(usr.r_hand, usr) //then do ittttt + else + if(istype(usr.l_hand, /obj/item/weapon/pen)) //check other hand for pen + add_fingerprint(usr) + P.attackby(usr.l_hand, usr) + else to_chat(usr, "You'll need something to write with!") - - if(href_list["read"]) - var/obj/item/weapon/paper/P = locate(href_list["read"]) - if((P && P.loc == src)) - if(!( istype(usr, /mob/living/carbon/human) )) - usr << browse("[P.name][stars(P.info)]", "window=[P.name]") - onclose(usr, "[P.name]") - else - usr << browse("[P.name][P.info]", "window=[P.name]") - onclose(usr, "[P.name]") - return + + if(href_list["read"]) + var/obj/item/weapon/paper/P = locate(href_list["read"]) + if((P && P.loc == src)) + if(!( istype(usr, /mob/living/carbon/human) )) + usr << browse("[P.name][stars(P.info)]", "window=[P.name]") + onclose(usr, "[P.name]") + else + usr << browse("[P.name][P.info]", "window=[P.name]") + onclose(usr, "[P.name]") + return diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 107f2b706a3..80261f342df 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -1,190 +1,190 @@ -/* -CONTAINS: -SAFES -FLOOR SAFES -*/ - -//SAFES -/obj/structure/safe - name = "safe" - desc = "A huge chunk of metal with a dial embedded in it. Fine print on the dial reads \"Scarborough Arms - 2 tumbler safe, guaranteed thermite resistant, explosion resistant, and assistant resistant.\"" - icon = 'icons/obj/structures.dmi' - icon_state = "safe" - anchored = 1 - density = 1 - var/open = 0 //is the safe open? - var/tumbler_1_pos //the tumbler position- from 0 to 72 - var/tumbler_1_open //the tumbler position to open at- 0 to 72 - var/tumbler_2_pos - var/tumbler_2_open - var/dial = 0 //where is the dial pointing? - var/space = 0 //the combined w_class of everything in the safe - var/maxspace = 24 //the maximum combined w_class of stuff in the safe - - -/obj/structure/safe/New() - tumbler_1_pos = rand(0, 72) - tumbler_1_open = rand(0, 72) - - tumbler_2_pos = rand(0, 72) - tumbler_2_open = rand(0, 72) - - -/obj/structure/safe/initialize() - for(var/obj/item/I in loc) - if(space >= maxspace) - return - if(I.w_class + space <= maxspace) - space += I.w_class - I.loc = src - - -/obj/structure/safe/proc/check_unlocked(mob/user as mob, canhear) - if(user && canhear) - if(tumbler_1_pos == tumbler_1_open) - to_chat(user, "You hear a [pick("tonk", "krunk", "plunk")] from [src].") - if(tumbler_2_pos == tumbler_2_open) - to_chat(user, "You hear a [pick("tink", "krink", "plink")] from [src].") - if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open) - if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") - return 1 - return 0 - - -/obj/structure/safe/proc/decrement(num) - num -= 1 - if(num < 0) - num = 71 - return num - - -/obj/structure/safe/proc/increment(num) - num += 1 - if(num > 71) - num = 0 - return num - - -/obj/structure/safe/update_icon() - if(open) - icon_state = "[initial(icon_state)]-open" - else - icon_state = initial(icon_state) - - -/obj/structure/safe/attack_hand(mob/user as mob) - user.set_machine(src) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\safe.dm:77: var/dat = "
    " - var/dat = {"
    -[open ? "Close" : "Open"] [src] | - [dial * 5] +"} - // END AUTOFIX - if(open) - dat += "" - for(var/i = contents.len, i>=1, i--) - var/obj/item/P = contents[i] - dat += "" - dat += "
    [P.name]
    " - user << browse("[name][dat]", "window=safe;size=350x300") - onclose(user, "safe") - - -/obj/structure/safe/Topic(href, href_list) - if(!ishuman(usr)) return - var/mob/living/carbon/human/user = usr - - var/canhear = 0 - if(istype(user.l_hand, /obj/item/clothing/accessory/stethoscope) || istype(user.r_hand, /obj/item/clothing/accessory/stethoscope)) - canhear = 1 - - if(href_list["open"]) - if(check_unlocked()) - to_chat(user, "You [open ? "close" : "open"] [src].") - open = !open - update_icon() - updateUsrDialog() - return - else - to_chat(user, "You can't [open ? "close" : "open"] [src], the lock is engaged!") - return - - if(href_list["decrement"]) - dial = decrement(dial) - if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71) - tumbler_1_pos = decrement(tumbler_1_pos) - if(canhear) - to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") - if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35) - tumbler_2_pos = decrement(tumbler_2_pos) - if(canhear) - to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") - check_unlocked(user, canhear) - updateUsrDialog() - return - - if(href_list["increment"]) - dial = increment(dial) - if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71) - tumbler_1_pos = increment(tumbler_1_pos) - if(canhear) - to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") - if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35) - tumbler_2_pos = increment(tumbler_2_pos) - if(canhear) - to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") - check_unlocked(user, canhear) - updateUsrDialog() - return - - if(href_list["retrieve"]) - user << browse("", "window=safe") // Close the menu - - var/obj/item/P = locate(href_list["retrieve"]) in src - if(open) - if(P && in_range(src, user)) - user.put_in_hands(P) - updateUsrDialog() - - -/obj/structure/safe/attackby(obj/item/I as obj, mob/user as mob) - if(open) - if(I.w_class + space <= maxspace) - if(user.drop_item(I, src)) - space += I.w_class - to_chat(user, "You put [I] in [src].") - updateUsrDialog() - return - else - to_chat(user, "[I] won't fit in [src].") - return - else - if(istype(I, /obj/item/clothing/accessory/stethoscope)) - to_chat(user, "Hold [I] in one of your hands while you manipulate the dial.") - return - - -obj/structure/safe/blob_act() - return - - -obj/structure/safe/ex_act(severity) - return - -//FLOOR SAFES -/obj/structure/safe/floor - name = "floor safe" - icon_state = "floorsafe" - density = 0 - level = 1 //underfloor - layer = 2.5 - - -/obj/structure/safe/floor/initialize() - ..() - var/turf/T = loc - hide(T.intact) - - -/obj/structure/safe/floor/hide(var/intact) +/* +CONTAINS: +SAFES +FLOOR SAFES +*/ + +//SAFES +/obj/structure/safe + name = "safe" + desc = "A huge chunk of metal with a dial embedded in it. Fine print on the dial reads \"Scarborough Arms - 2 tumbler safe, guaranteed thermite resistant, explosion resistant, and assistant resistant.\"" + icon = 'icons/obj/structures.dmi' + icon_state = "safe" + anchored = 1 + density = 1 + var/open = 0 //is the safe open? + var/tumbler_1_pos //the tumbler position- from 0 to 72 + var/tumbler_1_open //the tumbler position to open at- 0 to 72 + var/tumbler_2_pos + var/tumbler_2_open + var/dial = 0 //where is the dial pointing? + var/space = 0 //the combined w_class of everything in the safe + var/maxspace = 24 //the maximum combined w_class of stuff in the safe + + +/obj/structure/safe/New() + tumbler_1_pos = rand(0, 72) + tumbler_1_open = rand(0, 72) + + tumbler_2_pos = rand(0, 72) + tumbler_2_open = rand(0, 72) + + +/obj/structure/safe/initialize() + for(var/obj/item/I in loc) + if(space >= maxspace) + return + if(I.w_class + space <= maxspace) + space += I.w_class + I.loc = src + + +/obj/structure/safe/proc/check_unlocked(mob/user as mob, canhear) + if(user && canhear) + if(tumbler_1_pos == tumbler_1_open) + to_chat(user, "You hear a [pick("tonk", "krunk", "plunk")] from [src].") + if(tumbler_2_pos == tumbler_2_open) + to_chat(user, "You hear a [pick("tink", "krink", "plink")] from [src].") + if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open) + if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!") + return 1 + return 0 + + +/obj/structure/safe/proc/decrement(num) + num -= 1 + if(num < 0) + num = 71 + return num + + +/obj/structure/safe/proc/increment(num) + num += 1 + if(num > 71) + num = 0 + return num + + +/obj/structure/safe/update_icon() + if(open) + icon_state = "[initial(icon_state)]-open" + else + icon_state = initial(icon_state) + + +/obj/structure/safe/attack_hand(mob/user as mob) + user.set_machine(src) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\safe.dm:77: var/dat = "
    " + var/dat = {"
    +[open ? "Close" : "Open"] [src] | - [dial * 5] +"} + // END AUTOFIX + if(open) + dat += "" + for(var/i = contents.len, i>=1, i--) + var/obj/item/P = contents[i] + dat += "" + dat += "
    [P.name]
    " + user << browse("[name][dat]", "window=safe;size=350x300") + onclose(user, "safe") + + +/obj/structure/safe/Topic(href, href_list) + if(!ishuman(usr)) return + var/mob/living/carbon/human/user = usr + + var/canhear = 0 + if(istype(user.l_hand, /obj/item/clothing/accessory/stethoscope) || istype(user.r_hand, /obj/item/clothing/accessory/stethoscope)) + canhear = 1 + + if(href_list["open"]) + if(check_unlocked()) + to_chat(user, "You [open ? "close" : "open"] [src].") + open = !open + update_icon() + updateUsrDialog() + return + else + to_chat(user, "You can't [open ? "close" : "open"] [src], the lock is engaged!") + return + + if(href_list["decrement"]) + dial = decrement(dial) + if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71) + tumbler_1_pos = decrement(tumbler_1_pos) + if(canhear) + to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") + if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35) + tumbler_2_pos = decrement(tumbler_2_pos) + if(canhear) + to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") + check_unlocked(user, canhear) + updateUsrDialog() + return + + if(href_list["increment"]) + dial = increment(dial) + if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71) + tumbler_1_pos = increment(tumbler_1_pos) + if(canhear) + to_chat(user, "You hear a [pick("clack", "scrape", "clank")] from [src].") + if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35) + tumbler_2_pos = increment(tumbler_2_pos) + if(canhear) + to_chat(user, "You hear a [pick("click", "chink", "clink")] from [src].") + check_unlocked(user, canhear) + updateUsrDialog() + return + + if(href_list["retrieve"]) + user << browse("", "window=safe") // Close the menu + + var/obj/item/P = locate(href_list["retrieve"]) in src + if(open) + if(P && in_range(src, user)) + user.put_in_hands(P) + updateUsrDialog() + + +/obj/structure/safe/attackby(obj/item/I as obj, mob/user as mob) + if(open) + if(I.w_class + space <= maxspace) + if(user.drop_item(I, src)) + space += I.w_class + to_chat(user, "You put [I] in [src].") + updateUsrDialog() + return + else + to_chat(user, "[I] won't fit in [src].") + return + else + if(istype(I, /obj/item/clothing/accessory/stethoscope)) + to_chat(user, "Hold [I] in one of your hands while you manipulate the dial.") + return + + +obj/structure/safe/blob_act() + return + + +obj/structure/safe/ex_act(severity) + return + +//FLOOR SAFES +/obj/structure/safe/floor + name = "floor safe" + icon_state = "floorsafe" + density = 0 + level = 1 //underfloor + layer = 2.5 + + +/obj/structure/safe/floor/initialize() + ..() + var/turf/T = loc + hide(T.intact) + + +/obj/structure/safe/floor/hide(var/intact) invisibility = intact ? 101 : 0 \ No newline at end of file diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index f4cdde6ae5b..c9be014984a 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -1,226 +1,226 @@ -/*////////////////////////////////////////// -// WARNING! ACHTUNG! // -// WHEN YOU'RE MAKING A SIGN: // -// REMEMBER TO USE \improper // -// ONLY IF NAME IS CAPITALIZED AND // -//ACTUALLY NOT PROPER; FAILURE TO DO THIS // -// WILL RESULT IN MESSAGES LIKE "The The // -// Periodic Table has been hit..." // -// PLEASE REMEMBER THAT AND THANKS. // -// HAVE A NICE DAY! // -*/////////////////////////////////////////// - -/obj/structure/sign - icon = 'icons/obj/decals.dmi' - anchored = 1 - opacity = 0 - density = 0 - layer = 3.5 - -/obj/structure/sign/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - qdel(src) - return - if(3.0) - qdel(src) - return - else - return - -/obj/structure/sign/blob_act() - qdel(src) - return - -/obj/structure/sign/attackby(obj/item/tool as obj, mob/user as mob) //deconstruction - if(istype(tool, /obj/item/weapon/screwdriver) && !istype(src, /obj/structure/sign/double)) - to_chat(user, "You unfasten the sign with your [tool].") - var/obj/item/sign/S = new(src.loc) - S.name = name - S.desc = desc - S.icon_state = icon_state - //var/icon/I = icon('icons/obj/decals.dmi', icon_state) - //S.icon = I.Scale(24, 24) - S.sign_state = icon_state - qdel(src) - return - else ..() - -/obj/item/sign - name = "sign" - desc = "" - icon = 'icons/obj/decals.dmi' - w_class = 3 //big - var/sign_state = "" - -/obj/item/sign/attackby(obj/item/tool as obj, mob/user as mob) //construction - if(istype(tool, /obj/item/weapon/screwdriver) && isturf(user.loc)) - var/direction = input("In which direction?", "Select direction.") in list("North", "East", "South", "West", "Cancel") - if(direction == "Cancel") return - var/obj/structure/sign/S = new(user.loc) - switch(direction) - if("North") - S.pixel_y = 32 - if("East") - S.pixel_x = 32 - if("South") - S.pixel_y = -32 - if("West") - S.pixel_x = -32 - else return - S.name = name - S.desc = desc - S.icon_state = sign_state - to_chat(user, "You fasten \the [S] with your [tool].") - qdel(src) - return - else ..() - -/obj/structure/sign/double/map - name = "station map" - desc = "A framed picture of the station." - -/obj/structure/sign/double/map/left - icon_state = "map-left" - -/obj/structure/sign/double/map/right - icon_state = "map-right" - -//For efficiency station -/obj/structure/sign/map/efficiency - name = "station map" - desc = "A framed picture of the station." - icon_state = "map_efficiency" - -/obj/structure/sign/map/meta/left - name = "station map" - desc = "A framed picture of the station." - icon_state = "map-left-MS" - -/obj/structure/sign/map/meta/right - name = "station map" - desc = "A framed picture of the station." - icon_state = "map-right-MS" - -/obj/structure/sign/securearea - name = "SECURE AREA" - desc = "A warning sign which reads 'SECURE AREA'." - icon_state = "securearea" - -/obj/structure/sign/biohazard - name = "BIOHAZARD" - desc = "A warning sign which reads 'BIOHAZARD'" - icon_state = "bio" - -/obj/structure/sign/electricshock - name = "HIGH VOLTAGE" - desc = "A warning sign which reads 'HIGH VOLTAGE'" - icon_state = "shock" - -/obj/structure/sign/examroom - name = "EXAM" - desc = "A guidance sign which reads 'EXAM ROOM'" - icon_state = "examroom" - -/obj/structure/sign/vacuum - name = "HARD VACUUM AHEAD" - desc = "A warning sign which reads 'HARD VACUUM AHEAD'" - icon_state = "space" - -/obj/structure/sign/deathsposal - name = "DISPOSAL LEADS TO SPACE" - desc = "A warning sign which reads 'DISPOSAL LEADS TO SPACE'" - icon_state = "deathsposal" - -/obj/structure/sign/pods - name = "ESCAPE PODS" - desc = "A warning sign which reads 'ESCAPE PODS'" - icon_state = "pods" - -/obj/structure/sign/fire - name = "DANGER: FIRE" - desc = "A warning sign which reads 'DANGER: FIRE'" - icon_state = "fire" - -/obj/structure/sign/nosmoking_1 - name = "NO SMOKING" - desc = "A warning sign which reads 'NO SMOKING'" - icon_state = "nosmoking" - -/obj/structure/sign/nosmoking_2 - name = "NO SMOKING" - desc = "A warning sign which reads 'NO SMOKING'" - icon_state = "nosmoking2" - -/obj/structure/sign/redcross - name = "Medbay" - desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here.'" - icon_state = "redcross" - -/obj/structure/sign/greencross - name = "Medbay" - desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here.'" - icon_state = "greencross" - -/obj/structure/sign/goldenplaque - name = "The Most Robust Men Award for Robustness" - desc = "To be Robust is not an action or a way of life, but a mental state. Only those with the force of Will strong enough to act during a crisis, saving friend from foe, are truly Robust. Stay Robust my friends." - icon_state = "goldenplaque" - -/obj/structure/sign/kiddieplaque - name = "\improper AI developer's plaque" - desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"" - icon_state = "kiddieplaque" - -/obj/structure/sign/atmosplaque - name = "\improper FEA Atmospherics Division plaque" - desc = "This plaque commemorates the fall of the Atmos FEA division. For all the charred, dizzy, and brittle men who have died in its hands." - icon_state = "atmosplaque" - -/obj/structure/sign/science //These 3 have multiple types, just var-edit the icon_state to whatever one you want on the map - name = "SCIENCE!" - desc = "A warning sign which reads 'SCIENCE!'" - icon_state = "science1" - -/obj/structure/sign/chemistry - name = "CHEMISTRY" - desc = "A warning sign which reads 'CHEMISTRY'" - icon_state = "chemistry1" - -/obj/structure/sign/chemtable - name = "The Periodic Table" - desc = "A very colorful and detailed table of all the chemical elements you could blow up or burn down a chemistry laboratory with, titled 'The Space Periodic Table - To be continued'. Just the mere sight of it makes you feel smarter." - icon_state = "periodic" - -/obj/structure/sign/botany - name = "HYDROPONICS" - desc = "A warning sign which reads 'HYDROPONICS'" - icon_state = "hydro1" - -/obj/structure/sign/directions/science - name = "Science department" - desc = "A direction sign, pointing out which way Science department is." - icon_state = "direction_sci" - -/obj/structure/sign/directions/engineering - name = "Engineering department" - desc = "A direction sign, pointing out which way Engineering department is." - icon_state = "direction_eng" - -/obj/structure/sign/directions/security - name = "Security department" - desc = "A direction sign, pointing out which way Security department is." - icon_state = "direction_sec" - -/obj/structure/sign/directions/medical - name = "Medical Bay" - desc = "A direction sign, pointing out which way Meducal Bay is." - icon_state = "direction_med" - -/obj/structure/sign/directions/evac - name = "Escape Arm" - desc = "A direction sign, pointing out which way escape shuttle dock is." - icon_state = "direction_evac" +/*////////////////////////////////////////// +// WARNING! ACHTUNG! // +// WHEN YOU'RE MAKING A SIGN: // +// REMEMBER TO USE \improper // +// ONLY IF NAME IS CAPITALIZED AND // +//ACTUALLY NOT PROPER; FAILURE TO DO THIS // +// WILL RESULT IN MESSAGES LIKE "The The // +// Periodic Table has been hit..." // +// PLEASE REMEMBER THAT AND THANKS. // +// HAVE A NICE DAY! // +*/////////////////////////////////////////// + +/obj/structure/sign + icon = 'icons/obj/decals.dmi' + anchored = 1 + opacity = 0 + density = 0 + layer = 3.5 + +/obj/structure/sign/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + qdel(src) + return + if(3.0) + qdel(src) + return + else + return + +/obj/structure/sign/blob_act() + qdel(src) + return + +/obj/structure/sign/attackby(obj/item/tool as obj, mob/user as mob) //deconstruction + if(istype(tool, /obj/item/weapon/screwdriver) && !istype(src, /obj/structure/sign/double)) + to_chat(user, "You unfasten the sign with your [tool].") + var/obj/item/sign/S = new(src.loc) + S.name = name + S.desc = desc + S.icon_state = icon_state + //var/icon/I = icon('icons/obj/decals.dmi', icon_state) + //S.icon = I.Scale(24, 24) + S.sign_state = icon_state + qdel(src) + return + else ..() + +/obj/item/sign + name = "sign" + desc = "" + icon = 'icons/obj/decals.dmi' + w_class = 3 //big + var/sign_state = "" + +/obj/item/sign/attackby(obj/item/tool as obj, mob/user as mob) //construction + if(istype(tool, /obj/item/weapon/screwdriver) && isturf(user.loc)) + var/direction = input("In which direction?", "Select direction.") in list("North", "East", "South", "West", "Cancel") + if(direction == "Cancel") return + var/obj/structure/sign/S = new(user.loc) + switch(direction) + if("North") + S.pixel_y = 32 + if("East") + S.pixel_x = 32 + if("South") + S.pixel_y = -32 + if("West") + S.pixel_x = -32 + else return + S.name = name + S.desc = desc + S.icon_state = sign_state + to_chat(user, "You fasten \the [S] with your [tool].") + qdel(src) + return + else ..() + +/obj/structure/sign/double/map + name = "station map" + desc = "A framed picture of the station." + +/obj/structure/sign/double/map/left + icon_state = "map-left" + +/obj/structure/sign/double/map/right + icon_state = "map-right" + +//For efficiency station +/obj/structure/sign/map/efficiency + name = "station map" + desc = "A framed picture of the station." + icon_state = "map_efficiency" + +/obj/structure/sign/map/meta/left + name = "station map" + desc = "A framed picture of the station." + icon_state = "map-left-MS" + +/obj/structure/sign/map/meta/right + name = "station map" + desc = "A framed picture of the station." + icon_state = "map-right-MS" + +/obj/structure/sign/securearea + name = "SECURE AREA" + desc = "A warning sign which reads 'SECURE AREA'." + icon_state = "securearea" + +/obj/structure/sign/biohazard + name = "BIOHAZARD" + desc = "A warning sign which reads 'BIOHAZARD'" + icon_state = "bio" + +/obj/structure/sign/electricshock + name = "HIGH VOLTAGE" + desc = "A warning sign which reads 'HIGH VOLTAGE'" + icon_state = "shock" + +/obj/structure/sign/examroom + name = "EXAM" + desc = "A guidance sign which reads 'EXAM ROOM'" + icon_state = "examroom" + +/obj/structure/sign/vacuum + name = "HARD VACUUM AHEAD" + desc = "A warning sign which reads 'HARD VACUUM AHEAD'" + icon_state = "space" + +/obj/structure/sign/deathsposal + name = "DISPOSAL LEADS TO SPACE" + desc = "A warning sign which reads 'DISPOSAL LEADS TO SPACE'" + icon_state = "deathsposal" + +/obj/structure/sign/pods + name = "ESCAPE PODS" + desc = "A warning sign which reads 'ESCAPE PODS'" + icon_state = "pods" + +/obj/structure/sign/fire + name = "DANGER: FIRE" + desc = "A warning sign which reads 'DANGER: FIRE'" + icon_state = "fire" + +/obj/structure/sign/nosmoking_1 + name = "NO SMOKING" + desc = "A warning sign which reads 'NO SMOKING'" + icon_state = "nosmoking" + +/obj/structure/sign/nosmoking_2 + name = "NO SMOKING" + desc = "A warning sign which reads 'NO SMOKING'" + icon_state = "nosmoking2" + +/obj/structure/sign/redcross + name = "Medbay" + desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here.'" + icon_state = "redcross" + +/obj/structure/sign/greencross + name = "Medbay" + desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here.'" + icon_state = "greencross" + +/obj/structure/sign/goldenplaque + name = "The Most Robust Men Award for Robustness" + desc = "To be Robust is not an action or a way of life, but a mental state. Only those with the force of Will strong enough to act during a crisis, saving friend from foe, are truly Robust. Stay Robust my friends." + icon_state = "goldenplaque" + +/obj/structure/sign/kiddieplaque + name = "\improper AI developer's plaque" + desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"" + icon_state = "kiddieplaque" + +/obj/structure/sign/atmosplaque + name = "\improper FEA Atmospherics Division plaque" + desc = "This plaque commemorates the fall of the Atmos FEA division. For all the charred, dizzy, and brittle men who have died in its hands." + icon_state = "atmosplaque" + +/obj/structure/sign/science //These 3 have multiple types, just var-edit the icon_state to whatever one you want on the map + name = "SCIENCE!" + desc = "A warning sign which reads 'SCIENCE!'" + icon_state = "science1" + +/obj/structure/sign/chemistry + name = "CHEMISTRY" + desc = "A warning sign which reads 'CHEMISTRY'" + icon_state = "chemistry1" + +/obj/structure/sign/chemtable + name = "The Periodic Table" + desc = "A very colorful and detailed table of all the chemical elements you could blow up or burn down a chemistry laboratory with, titled 'The Space Periodic Table - To be continued'. Just the mere sight of it makes you feel smarter." + icon_state = "periodic" + +/obj/structure/sign/botany + name = "HYDROPONICS" + desc = "A warning sign which reads 'HYDROPONICS'" + icon_state = "hydro1" + +/obj/structure/sign/directions/science + name = "Science department" + desc = "A direction sign, pointing out which way Science department is." + icon_state = "direction_sci" + +/obj/structure/sign/directions/engineering + name = "Engineering department" + desc = "A direction sign, pointing out which way Engineering department is." + icon_state = "direction_eng" + +/obj/structure/sign/directions/security + name = "Security department" + desc = "A direction sign, pointing out which way Security department is." + icon_state = "direction_sec" + +/obj/structure/sign/directions/medical + name = "Medical Bay" + desc = "A direction sign, pointing out which way Meducal Bay is." + icon_state = "direction_med" + +/obj/structure/sign/directions/evac + name = "Escape Arm" + desc = "A direction sign, pointing out which way escape shuttle dock is." + icon_state = "direction_evac" diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm index 7c2fa10d608..8e142897a80 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm @@ -1,78 +1,78 @@ -#define ALIEN_NEST_LOCKED_Y_OFFSET 6 -//Alium nests. Essentially beds with an unbuckle delay that only aliums can buckle mobs to. - -/obj/structure/bed/nest - name = "alien nest" - desc = "It's a gruesome pile of thick, sticky resin shaped like a nest." - icon = 'icons/mob/alien.dmi' - icon_state = "nest" - var/health = 100 - -/obj/structure/bed/nest/manual_unbuckle(mob/user as mob) - if(locked_atoms.len) - var/mob/M = locked_atoms[1] - if(M != user) - M.visible_message(\ - "[user.name] pulls [M.name] free from the sticky nest!",\ - "[user.name] pulls you free from the gelatinous resin.",\ - "You hear squelching...") - unlock_atom(M) - else - M.visible_message(\ - "[M.name] struggles to break free of the gelatinous resin...",\ - "You struggle to break free from the gelatinous resin...",\ - "You hear squelching...") - spawn(1200) - if(user && M && user.locked_to == src) - unlock_atom(M) - src.add_fingerprint(user) - -/obj/structure/bed/nest/buckle_mob(mob/M as mob, mob/user as mob) - if (locked_atoms.len || !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || usr.stat || M.locked_to || istype(user, /mob/living/silicon/pai) ) - return - - if(istype(M,/mob/living/carbon/alien)) - return - if(!istype(user,/mob/living/carbon/alien/humanoid)) - return - - if(M == usr) - return - else - M.visible_message(\ - "[user.name] secretes a thick vile goo, securing [M.name] into \the [src]!",\ - "[user.name] drenches you in a foul-smelling resin, trapping you in \the [src]!",\ - "You hear squelching...") - lock_atom(M) - M.pixel_y = 6 - src.add_fingerprint(user) - -/obj/structure/bed/nest/attackby(obj/item/weapon/W as obj, mob/user as mob) - var/aforce = W.force - health = max(0, health - aforce) - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - user.visible_message("[user] hits \the [src] with \the [W]!", \ - "You hit \the [src] with \the [W]!") - user.delayNextAttack(10) - healthcheck() - -/obj/structure/bed/nest/proc/healthcheck() - if(health <= 0) - density = 0 - qdel(src) - -/obj/structure/bed/nest/lock_atom(var/atom/movable/AM) - . = ..() - if(!.) - return - - AM.pixel_y += ALIEN_NEST_LOCKED_Y_OFFSET - -/obj/structure/bed/nest/unlock_atom(var/atom/movable/AM) - . = ..() - if(!.) - return - - AM.pixel_y -= ALIEN_NEST_LOCKED_Y_OFFSET - -#undef ALIEN_NEST_LOCKED_Y_OFFSET +#define ALIEN_NEST_LOCKED_Y_OFFSET 6 +//Alium nests. Essentially beds with an unbuckle delay that only aliums can buckle mobs to. + +/obj/structure/bed/nest + name = "alien nest" + desc = "It's a gruesome pile of thick, sticky resin shaped like a nest." + icon = 'icons/mob/alien.dmi' + icon_state = "nest" + var/health = 100 + +/obj/structure/bed/nest/manual_unbuckle(mob/user as mob) + if(locked_atoms.len) + var/mob/M = locked_atoms[1] + if(M != user) + M.visible_message(\ + "[user.name] pulls [M.name] free from the sticky nest!",\ + "[user.name] pulls you free from the gelatinous resin.",\ + "You hear squelching...") + unlock_atom(M) + else + M.visible_message(\ + "[M.name] struggles to break free of the gelatinous resin...",\ + "You struggle to break free from the gelatinous resin...",\ + "You hear squelching...") + spawn(1200) + if(user && M && user.locked_to == src) + unlock_atom(M) + src.add_fingerprint(user) + +/obj/structure/bed/nest/buckle_mob(mob/M as mob, mob/user as mob) + if (locked_atoms.len || !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || usr.stat || M.locked_to || istype(user, /mob/living/silicon/pai) ) + return + + if(istype(M,/mob/living/carbon/alien)) + return + if(!istype(user,/mob/living/carbon/alien/humanoid)) + return + + if(M == usr) + return + else + M.visible_message(\ + "[user.name] secretes a thick vile goo, securing [M.name] into \the [src]!",\ + "[user.name] drenches you in a foul-smelling resin, trapping you in \the [src]!",\ + "You hear squelching...") + lock_atom(M) + M.pixel_y = 6 + src.add_fingerprint(user) + +/obj/structure/bed/nest/attackby(obj/item/weapon/W as obj, mob/user as mob) + var/aforce = W.force + health = max(0, health - aforce) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + user.visible_message("[user] hits \the [src] with \the [W]!", \ + "You hit \the [src] with \the [W]!") + user.delayNextAttack(10) + healthcheck() + +/obj/structure/bed/nest/proc/healthcheck() + if(health <= 0) + density = 0 + qdel(src) + +/obj/structure/bed/nest/lock_atom(var/atom/movable/AM) + . = ..() + if(!.) + return + + AM.pixel_y += ALIEN_NEST_LOCKED_Y_OFFSET + +/obj/structure/bed/nest/unlock_atom(var/atom/movable/AM) + . = ..() + if(!.) + return + + AM.pixel_y -= ALIEN_NEST_LOCKED_Y_OFFSET + +#undef ALIEN_NEST_LOCKED_Y_OFFSET diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index ac24df5a103..4bdc019b356 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -1,169 +1,169 @@ -/* Beds... get your mind out of the gutter, they're for sleeping! - * Contains: - * Beds - * Roller beds - */ - -/* - * Beds - */ -/obj/structure/bed - name = "bed" - desc = "This is used to lie in, sleep in or strap on." - icon_state = "bed" - icon = 'icons/obj/stools-chairs-beds.dmi' - - locked_should_lie = 1 - dense_when_locking = 0 - anchored = 1 - var/sheet_type = /obj/item/stack/sheet/metal - var/sheet_amt = 1 - -/obj/structure/bed/alien - name = "resting contraption" - desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" - icon_state = "abed" - -/obj/structure/bed/cultify() - var/obj/structure/bed/chair/wood/wings/I = new /obj/structure/bed/chair/wood/wings(loc) - I.dir = dir - . = ..() - -/obj/structure/bed/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/structure/bed/attack_hand(mob/user as mob) - manual_unbuckle(user) - -/obj/structure/bed/attack_animal(mob/user as mob) - manual_unbuckle(user) - -/obj/structure/bed/attack_robot(mob/user as mob) - if(Adjacent(user)) - manual_unbuckle(user) - -/obj/structure/bed/MouseDrop(atom/over_object) - return - -/obj/structure/bed/MouseDrop_T(mob/M as mob, mob/user as mob) - if(!istype(M)) - return - - buckle_mob(M, user) - -/obj/structure/bed/proc/manual_unbuckle(mob/user as mob) - if(!locked_atoms.len) - return - - var/mob/M = locked_atoms[1] - if(M != user) - M.visible_message(\ - "[M] was unbuckled by [user]!",\ - "You were unbuckled from \the [src] by [user].",\ - "You hear metal clanking.") - else - M.visible_message(\ - "[M] unbuckled \himself!",\ - "You unbuckle yourself from \the [src].",\ - "You hear metal clanking.") - - unlock_atom(M) - - add_fingerprint(user) - -/obj/structure/bed/proc/buckle_mob(mob/M as mob, mob/user as mob) - if(!ismob(M) || !Adjacent(user) || (M.loc != src.loc) || user.restrained() || user.lying || user.stat || M.locked_to || istype(user, /mob/living/silicon/pai) ) - return - - if(isanimal(M)) - if(M.size <= SIZE_TINY) //Fuck off mice +/* Beds... get your mind out of the gutter, they're for sleeping! + * Contains: + * Beds + * Roller beds + */ + +/* + * Beds + */ +/obj/structure/bed + name = "bed" + desc = "This is used to lie in, sleep in or strap on." + icon_state = "bed" + icon = 'icons/obj/stools-chairs-beds.dmi' + + locked_should_lie = 1 + dense_when_locking = 0 + anchored = 1 + var/sheet_type = /obj/item/stack/sheet/metal + var/sheet_amt = 1 + +/obj/structure/bed/alien + name = "resting contraption" + desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" + icon_state = "abed" + +/obj/structure/bed/cultify() + var/obj/structure/bed/chair/wood/wings/I = new /obj/structure/bed/chair/wood/wings(loc) + I.dir = dir + . = ..() + +/obj/structure/bed/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/structure/bed/attack_hand(mob/user as mob) + manual_unbuckle(user) + +/obj/structure/bed/attack_animal(mob/user as mob) + manual_unbuckle(user) + +/obj/structure/bed/attack_robot(mob/user as mob) + if(Adjacent(user)) + manual_unbuckle(user) + +/obj/structure/bed/MouseDrop(atom/over_object) + return + +/obj/structure/bed/MouseDrop_T(mob/M as mob, mob/user as mob) + if(!istype(M)) + return + + buckle_mob(M, user) + +/obj/structure/bed/proc/manual_unbuckle(mob/user as mob) + if(!locked_atoms.len) + return + + var/mob/M = locked_atoms[1] + if(M != user) + M.visible_message(\ + "[M] was unbuckled by [user]!",\ + "You were unbuckled from \the [src] by [user].",\ + "You hear metal clanking.") + else + M.visible_message(\ + "[M] unbuckled \himself!",\ + "You unbuckle yourself from \the [src].",\ + "You hear metal clanking.") + + unlock_atom(M) + + add_fingerprint(user) + +/obj/structure/bed/proc/buckle_mob(mob/M as mob, mob/user as mob) + if(!ismob(M) || !Adjacent(user) || (M.loc != src.loc) || user.restrained() || user.lying || user.stat || M.locked_to || istype(user, /mob/living/silicon/pai) ) + return + + if(isanimal(M)) + if(M.size <= SIZE_TINY) //Fuck off mice to_chat(user, "The [M] is too small to buckle in.") - return - - if(istype(M, /mob/living/carbon/slime)) + return + + if(istype(M, /mob/living/carbon/slime)) to_chat(user, "The [M] is too squishy to buckle in.") - return - - if(locked_atoms.len) + return + + if(locked_atoms.len) to_chat(user, "Somebody else is already buckled into \the [src]!") - - if(M == usr) - M.visible_message(\ - "[M.name] buckles in!",\ - "You buckle yourself to [src].",\ - "You hear metal clanking.") - else - M.visible_message(\ - "[M.name] is buckled in to [src] by [user.name]!",\ - "You are buckled in to [src] by [user.name].",\ - "You hear metal clanking.") - - add_fingerprint(user) - - lock_atom(M) - -/* - * Roller beds - */ - -#define ROLLERBED_Y_OFFSET 6 - -/obj/structure/bed/roller - name = "roller bed" - icon = 'icons/obj/rollerbed.dmi' - icon_state = "down" - anchored = 0 - dense_when_locking = 1 - -/obj/item/roller - name = "roller bed" - desc = "A collapsed roller bed that can be carried around." - icon = 'icons/obj/rollerbed.dmi' - icon_state = "folded" - w_class = 4 // Can't be put in backpacks. Oh well. - -/obj/item/roller/attack_self(mob/user) - var/obj/structure/bed/roller/R = new /obj/structure/bed/roller(user.loc) - R.add_fingerprint(user) - qdel(src) - -/obj/structure/bed/roller/lock_atom(var/atom/movable/AM) - ..() - AM.pixel_y += ROLLERBED_Y_OFFSET - density = 1 - icon_state = "up" - -/obj/structure/bed/roller/unlock_atom(var/atom/movable/AM) - . = ..() - if(!.) - return - - AM.pixel_y -= ROLLERBED_Y_OFFSET - icon_state = "down" - -/obj/structure/bed/roller/MouseDrop(over_object, src_location, over_location) - ..() - if(over_object == usr && Adjacent(usr)) - if(!ishuman(usr)) - return - - if(locked_atoms.len) - return 0 - - visible_message("[usr] collapses \the [src.name]") - - new/obj/item/roller(get_turf(src)) - - qdel(src) - -/obj/structure/bed/attackby(obj/item/weapon/W as obj, mob/user as mob) - - if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - getFromPool(sheet_type, get_turf(src), 2) - qdel(src) - return - - . = ..() - -#undef ROLLERBED_Y_OFFSET + + if(M == usr) + M.visible_message(\ + "[M.name] buckles in!",\ + "You buckle yourself to [src].",\ + "You hear metal clanking.") + else + M.visible_message(\ + "[M.name] is buckled in to [src] by [user.name]!",\ + "You are buckled in to [src] by [user.name].",\ + "You hear metal clanking.") + + add_fingerprint(user) + + lock_atom(M) + +/* + * Roller beds + */ + +#define ROLLERBED_Y_OFFSET 6 + +/obj/structure/bed/roller + name = "roller bed" + icon = 'icons/obj/rollerbed.dmi' + icon_state = "down" + anchored = 0 + dense_when_locking = 1 + +/obj/item/roller + name = "roller bed" + desc = "A collapsed roller bed that can be carried around." + icon = 'icons/obj/rollerbed.dmi' + icon_state = "folded" + w_class = 4 // Can't be put in backpacks. Oh well. + +/obj/item/roller/attack_self(mob/user) + var/obj/structure/bed/roller/R = new /obj/structure/bed/roller(user.loc) + R.add_fingerprint(user) + qdel(src) + +/obj/structure/bed/roller/lock_atom(var/atom/movable/AM) + ..() + AM.pixel_y += ROLLERBED_Y_OFFSET + density = 1 + icon_state = "up" + +/obj/structure/bed/roller/unlock_atom(var/atom/movable/AM) + . = ..() + if(!.) + return + + AM.pixel_y -= ROLLERBED_Y_OFFSET + icon_state = "down" + +/obj/structure/bed/roller/MouseDrop(over_object, src_location, over_location) + ..() + if(over_object == usr && Adjacent(usr)) + if(!ishuman(usr)) + return + + if(locked_atoms.len) + return 0 + + visible_message("[usr] collapses \the [src.name]") + + new/obj/item/roller(get_turf(src)) + + qdel(src) + +/obj/structure/bed/attackby(obj/item/weapon/W as obj, mob/user as mob) + + if(iswrench(W)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + getFromPool(sheet_type, get_turf(src), 2) + qdel(src) + return + + . = ..() + +#undef ROLLERBED_Y_OFFSET diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 71e64bd1d91..8782f70124b 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -1,204 +1,204 @@ -/obj/structure/bed/chair - name = "chair" - desc = "You sit in this. Either by will or force." - icon_state = "chair" - locked_should_lie = 0 - dense_when_locking = 0 - - sheet_amt = 1 - -/obj/structure/bed/chair/New() - ..() - spawn(3) - handle_layer() - -/obj/structure/bed/chair/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/assembly/shock_kit)) - var/obj/item/assembly/shock_kit/SK = W - if(!SK.status) - to_chat(user, "[SK] is not ready to be attached!") - return - if(user.drop_item(W)) - var/obj/structure/bed/chair/e_chair/E = new /obj/structure/bed/chair/e_chair(src.loc) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - E.dir = dir - E.part = SK - SK.forceMove(E) - SK.master = E - qdel(src) - return - - if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - getFromPool(sheet_type, get_turf(src), 2) - qdel(src) - return - - . = ..() - -/obj/structure/bed/chair/update_dir() - ..() - - handle_layer() - -/obj/structure/bed/chair/proc/handle_layer() - if(dir == NORTH) - src.layer = FLY_LAYER - else - src.layer = OBJ_LAYER - -/obj/structure/bed/chair/proc/spin() - change_dir(turn(dir, 90)) - -/obj/structure/bed/chair/verb/rotate() - set name = "Rotate Chair" - set category = "Object" - set src in oview(1) - - if(!usr || !isturf(usr.loc)) - return - - if(!config.ghost_interaction && !blessed) - if(usr.isUnconscious() || usr.restrained()) - return - - spin() - -/obj/structure/bed/chair/MouseDrop_T(mob/M as mob, mob/user as mob) - if(!istype(M)) return - var/mob/living/carbon/human/target = null - if(ishuman(M)) - target = M - if((target) && (target.op_stage.butt == 4)) //Butt surgery is at stage 4 - if(!M.weakened) //Spam prevention - if(M == usr) - M.visible_message(\ - "[M.name] has no butt, and slides right out of [src]!",\ - "Having no butt, you slide right out of the [src]",\ - "You hear metal clanking.") - - else - M.visible_message(\ - "[M.name] has no butt, and slides right out of [src]!",\ - "Having no butt, you slide right out of the [src]",\ - "You hear metal clanking.") - - M.Weaken(5) - else - to_chat(user, "You can't buckle [M.name] to [src], They just fell out!") - - else - buckle_mob(M, user) - -// Chair types -/obj/structure/bed/chair/wood - autoignition_temperature = AUTOIGNITION_WOOD - fire_fuel = 3 - // TODO: Special ash subtype that looks like charred chair legs - - sheet_type = /obj/item/stack/sheet/wood - -/obj/structure/bed/chair/wood/normal - icon_state = "wooden_chair" - name = "wooden chair" - desc = "Old is never too old to not be in fashion." - -/obj/structure/bed/chair/wood/wings - icon_state = "wooden_chair_wings" - name = "wooden chair" - desc = "Old is never too old to not be in fashion." - -/obj/structure/bed/chair/wood/wings/cultify() - return - -/obj/structure/bed/chair/holowood/normal - icon_state = "wooden_chair" - name = "wooden chair" - desc = "Old is never too old to not be in fashion." - -/obj/structure/bed/chair/holowood/wings - icon_state = "wooden_chair_wings" - name = "wooden chair" - desc = "Old is never too old to not be in fashion." - -/obj/structure/bed/chair/holowood/attackby(obj/item/weapon/W as obj, mob/user as mob) - return - -//Comfy chairs - -/obj/structure/bed/chair/comfy - name = "comfy chair" - desc = "It looks comfy." - icon_state = "comfychair_black" - - var/image/armrest - -/obj/structure/bed/chair/comfy/New() - ..() - armrest = image("icons/obj/objects.dmi", "[icon_state]_armrest", MOB_LAYER + 0.1) - -/obj/structure/bed/chair/comfy/lock_atom(var/atom/movable/AM) - ..() - update_icon() - -/obj/structure/bed/chair/comfy/unlock_atom(var/atom/movable/AM) - ..() - update_icon() - -/obj/structure/bed/chair/comfy/update_icon() - ..() - if(locked_atoms.len) - overlays += armrest - else - overlays -= armrest - -/obj/structure/bed/chair/comfy/brown - icon_state = "comfychair_brown" - -/obj/structure/bed/chair/comfy/beige - icon_state = "comfychair_beige" - -/obj/structure/bed/chair/comfy/teal - icon_state = "comfychair_teal" - -/obj/structure/bed/chair/comfy/black - icon_state = "comfychair_black" - -/obj/structure/bed/chair/comfy/lime - icon_state = "comfychair_lime" - -//Office chairs - -/obj/structure/bed/chair/office - icon_state = "officechair_white" - var/image/back - - sheet_amt = 5 - - anchored = 0 - -/obj/structure/bed/chair/office/New() - ..() - back = image("icons/obj/objects.dmi", "[icon_state]-overlay", MOB_LAYER + 0.1) - -/obj/structure/bed/chair/office/lock_atom(var/atom/movable/AM) - . = ..() - update_icon() - -/obj/structure/bed/chair/office/unlock_atom(var/atom/movable/AM) - ..() - update_icon() - -/obj/structure/bed/chair/office/update_icon() - ..() - if(locked_atoms.len) - overlays += back - else - overlays -= back - -/obj/structure/bed/chair/office/light - icon_state = "officechair_white" - -/obj/structure/bed/chair/office/dark - icon_state = "officechair_dark" - +/obj/structure/bed/chair + name = "chair" + desc = "You sit in this. Either by will or force." + icon_state = "chair" + locked_should_lie = 0 + dense_when_locking = 0 + + sheet_amt = 1 + +/obj/structure/bed/chair/New() + ..() + spawn(3) + handle_layer() + +/obj/structure/bed/chair/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/assembly/shock_kit)) + var/obj/item/assembly/shock_kit/SK = W + if(!SK.status) + to_chat(user, "[SK] is not ready to be attached!") + return + if(user.drop_item(W)) + var/obj/structure/bed/chair/e_chair/E = new /obj/structure/bed/chair/e_chair(src.loc) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + E.dir = dir + E.part = SK + SK.forceMove(E) + SK.master = E + qdel(src) + return + + if(iswrench(W)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + getFromPool(sheet_type, get_turf(src), 2) + qdel(src) + return + + . = ..() + +/obj/structure/bed/chair/update_dir() + ..() + + handle_layer() + +/obj/structure/bed/chair/proc/handle_layer() + if(dir == NORTH) + src.layer = FLY_LAYER + else + src.layer = OBJ_LAYER + +/obj/structure/bed/chair/proc/spin() + change_dir(turn(dir, 90)) + +/obj/structure/bed/chair/verb/rotate() + set name = "Rotate Chair" + set category = "Object" + set src in oview(1) + + if(!usr || !isturf(usr.loc)) + return + + if(!config.ghost_interaction && !blessed) + if(usr.isUnconscious() || usr.restrained()) + return + + spin() + +/obj/structure/bed/chair/MouseDrop_T(mob/M as mob, mob/user as mob) + if(!istype(M)) return + var/mob/living/carbon/human/target = null + if(ishuman(M)) + target = M + if((target) && (target.op_stage.butt == 4)) //Butt surgery is at stage 4 + if(!M.weakened) //Spam prevention + if(M == usr) + M.visible_message(\ + "[M.name] has no butt, and slides right out of [src]!",\ + "Having no butt, you slide right out of the [src]",\ + "You hear metal clanking.") + + else + M.visible_message(\ + "[M.name] has no butt, and slides right out of [src]!",\ + "Having no butt, you slide right out of the [src]",\ + "You hear metal clanking.") + + M.Weaken(5) + else + to_chat(user, "You can't buckle [M.name] to [src], They just fell out!") + + else + buckle_mob(M, user) + +// Chair types +/obj/structure/bed/chair/wood + autoignition_temperature = AUTOIGNITION_WOOD + fire_fuel = 3 + // TODO: Special ash subtype that looks like charred chair legs + + sheet_type = /obj/item/stack/sheet/wood + +/obj/structure/bed/chair/wood/normal + icon_state = "wooden_chair" + name = "wooden chair" + desc = "Old is never too old to not be in fashion." + +/obj/structure/bed/chair/wood/wings + icon_state = "wooden_chair_wings" + name = "wooden chair" + desc = "Old is never too old to not be in fashion." + +/obj/structure/bed/chair/wood/wings/cultify() + return + +/obj/structure/bed/chair/holowood/normal + icon_state = "wooden_chair" + name = "wooden chair" + desc = "Old is never too old to not be in fashion." + +/obj/structure/bed/chair/holowood/wings + icon_state = "wooden_chair_wings" + name = "wooden chair" + desc = "Old is never too old to not be in fashion." + +/obj/structure/bed/chair/holowood/attackby(obj/item/weapon/W as obj, mob/user as mob) + return + +//Comfy chairs + +/obj/structure/bed/chair/comfy + name = "comfy chair" + desc = "It looks comfy." + icon_state = "comfychair_black" + + var/image/armrest + +/obj/structure/bed/chair/comfy/New() + ..() + armrest = image("icons/obj/objects.dmi", "[icon_state]_armrest", MOB_LAYER + 0.1) + +/obj/structure/bed/chair/comfy/lock_atom(var/atom/movable/AM) + ..() + update_icon() + +/obj/structure/bed/chair/comfy/unlock_atom(var/atom/movable/AM) + ..() + update_icon() + +/obj/structure/bed/chair/comfy/update_icon() + ..() + if(locked_atoms.len) + overlays += armrest + else + overlays -= armrest + +/obj/structure/bed/chair/comfy/brown + icon_state = "comfychair_brown" + +/obj/structure/bed/chair/comfy/beige + icon_state = "comfychair_beige" + +/obj/structure/bed/chair/comfy/teal + icon_state = "comfychair_teal" + +/obj/structure/bed/chair/comfy/black + icon_state = "comfychair_black" + +/obj/structure/bed/chair/comfy/lime + icon_state = "comfychair_lime" + +//Office chairs + +/obj/structure/bed/chair/office + icon_state = "officechair_white" + var/image/back + + sheet_amt = 5 + + anchored = 0 + +/obj/structure/bed/chair/office/New() + ..() + back = image("icons/obj/objects.dmi", "[icon_state]-overlay", MOB_LAYER + 0.1) + +/obj/structure/bed/chair/office/lock_atom(var/atom/movable/AM) + . = ..() + update_icon() + +/obj/structure/bed/chair/office/unlock_atom(var/atom/movable/AM) + ..() + update_icon() + +/obj/structure/bed/chair/office/update_icon() + ..() + if(locked_atoms.len) + overlays += back + else + overlays -= back + +/obj/structure/bed/chair/office/light + icon_state = "officechair_white" + +/obj/structure/bed/chair/office/dark + icon_state = "officechair_dark" + diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm index 76032c08a1d..3b32d796128 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -1,52 +1,52 @@ -/obj/item/weapon/stool - name = "stool" - desc = "Apply butt." - icon = 'icons/obj/stools-chairs-beds.dmi' - icon_state = "stool" - force = 10 - throwforce = 10 - w_class = 5.0 - var/sheet_path = /obj/item/stack/sheet/metal - -/obj/item/weapon/stool/hologram - sheet_path = null - -/obj/item/weapon/stool/piano - name = "piano stool" - desc = "Apply butt. Become Mozart." - icon_state = "stool_piano" - autoignition_temperature = AUTOIGNITION_WOOD - fire_fuel = 3 - sheet_path = /obj/item/stack/sheet/wood - -//So they don't get picked up. -/obj/item/weapon/stool/piano/attack_hand() - return - -/obj/item/weapon/stool/attackby(var/obj/item/weapon/W, var/mob/user) - if(iswrench(W) && sheet_path) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - getFromPool(sheet_path, get_turf(src), 1) - qdel(src) - - . = ..() - -/obj/item/weapon/stool/cultify() - var/obj/structure/bed/chair/wood/wings/I = new /obj/structure/bed/chair/wood/wings(loc) - I.dir = dir - . = ..() - -/obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob) - if(prob(5) && istype(M, /mob/living) && sheet_path) - user.visible_message("[user] breaks \the [src] over [M]'s back!.") - user.u_equip(src, 0) - - getFromPool(sheet_path, get_turf(src), 1) - qdel(src) - - var/mob/living/T = M - T.Weaken(10) - T.apply_damage(20) - return - - . = ..() +/obj/item/weapon/stool + name = "stool" + desc = "Apply butt." + icon = 'icons/obj/stools-chairs-beds.dmi' + icon_state = "stool" + force = 10 + throwforce = 10 + w_class = 5.0 + var/sheet_path = /obj/item/stack/sheet/metal + +/obj/item/weapon/stool/hologram + sheet_path = null + +/obj/item/weapon/stool/piano + name = "piano stool" + desc = "Apply butt. Become Mozart." + icon_state = "stool_piano" + autoignition_temperature = AUTOIGNITION_WOOD + fire_fuel = 3 + sheet_path = /obj/item/stack/sheet/wood + +//So they don't get picked up. +/obj/item/weapon/stool/piano/attack_hand() + return + +/obj/item/weapon/stool/attackby(var/obj/item/weapon/W, var/mob/user) + if(iswrench(W) && sheet_path) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + getFromPool(sheet_path, get_turf(src), 1) + qdel(src) + + . = ..() + +/obj/item/weapon/stool/cultify() + var/obj/structure/bed/chair/wood/wings/I = new /obj/structure/bed/chair/wood/wings(loc) + I.dir = dir + . = ..() + +/obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob) + if(prob(5) && istype(M, /mob/living) && sheet_path) + user.visible_message("[user] breaks \the [src] over [M]'s back!.") + user.u_equip(src, 0) + + getFromPool(sheet_path, get_turf(src), 1) + qdel(src) + + var/mob/living/T = M + T.Weaken(10) + T.apply_damage(20) + return + + . = ..() diff --git a/code/game/objects/structures/support_rail.dm b/code/game/objects/structures/support_rail.dm index c727617691f..dcae688dd80 100644 --- a/code/game/objects/structures/support_rail.dm +++ b/code/game/objects/structures/support_rail.dm @@ -1,53 +1,53 @@ -/obj/structure/support_rail - desc = "A metal bar used to secure one's self. It has a label on the side that reads: 'Maximum Safe Capacity: 1, Enforceable by Space Law'. It looks pretty serious." - name = "support rail" - icon = 'icons/obj/objects.dmi' - icon_state = "rail" - density = 0 - anchored = 1 - flags = FPRINT - siemens_coefficient = 1 - pressure_resistance = 5*ONE_ATMOSPHERE - layer = 2.1 - explosion_resistance = 5 - var/health = 10 - var/destroyed = 0 - var/mob/living/carbon/human/supported_mob - -/obj/structure/support_rail/attackby(obj/item/weapon/W, mob/living/carbon/human/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 1 - qdel(src) - else - return ..() - - -/obj/structure/support_rail/Destroy() - letgo() - ..() - return - -/obj/structure/support_rail/proc/letgo() - supported_mob.update_canmove() - supported_mob.anchored = 0 - supported_mob.visible_message( - "[supported_mob.name] let go.") - src.supported_mob = null - return - -/obj/structure/support_rail/attack_hand(mob/user as mob) - if(supported_mob) //Anyone can force you to let go - letgo() - add_fingerprint(user) - else - supported_mob = user - user.visible_message( - "[supported_mob.name] grabbed the rail.") - user.anchored = 1 - user.loc = src.loc - user.dir = src.dir - user.update_canmove() - add_fingerprint(user) - return +/obj/structure/support_rail + desc = "A metal bar used to secure one's self. It has a label on the side that reads: 'Maximum Safe Capacity: 1, Enforceable by Space Law'. It looks pretty serious." + name = "support rail" + icon = 'icons/obj/objects.dmi' + icon_state = "rail" + density = 0 + anchored = 1 + flags = FPRINT + siemens_coefficient = 1 + pressure_resistance = 5*ONE_ATMOSPHERE + layer = 2.1 + explosion_resistance = 5 + var/health = 10 + var/destroyed = 0 + var/mob/living/carbon/human/supported_mob + +/obj/structure/support_rail/attackby(obj/item/weapon/W, mob/living/carbon/human/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 1 + qdel(src) + else + return ..() + + +/obj/structure/support_rail/Destroy() + letgo() + ..() + return + +/obj/structure/support_rail/proc/letgo() + supported_mob.update_canmove() + supported_mob.anchored = 0 + supported_mob.visible_message( + "[supported_mob.name] let go.") + src.supported_mob = null + return + +/obj/structure/support_rail/attack_hand(mob/user as mob) + if(supported_mob) //Anyone can force you to let go + letgo() + add_fingerprint(user) + else + supported_mob = user + user.visible_message( + "[supported_mob.name] grabbed the rail.") + user.anchored = 1 + user.loc = src.loc + user.dir = src.dir + user.update_canmove() + add_fingerprint(user) + return diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index c79b45c6010..3cba75bf78b 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -1,690 +1,690 @@ -/* Tables and Racks - * Contains: - * Tables - * Wooden tables - * Reinforced tables - * Racks - */ - - -/* - * Tables - */ -/obj/structure/table - name = "table" - desc = "A square piece of metal standing on four metal legs. It can not move." - icon = 'icons/obj/structures.dmi' - icon_state = "table" - density = 1 - anchored = 1.0 - layer = 2.8 - throwpass = 1 //You can throw objects over this, despite it's density.") - var/parts = /obj/item/weapon/table_parts - var/icon/clicked - var/flipped = 0 - var/health = 100 - -/obj/structure/table/proc/update_adjacent() - for(var/direction in alldirs) - if(locate(/obj/structure/table, get_step(src, direction))) - var/obj/structure/table/T = locate(/obj/structure/table, get_step(src, direction)) - T.update_icon() - -/obj/structure/table/cultify() - new /obj/structure/table/woodentable(loc) //See New() for qdel - -/obj/structure/table/New() - ..() - for(var/obj/structure/table/T in src.loc) - if(T != src) - qdel(T) - update_icon() - update_adjacent() - -/obj/structure/table/Destroy() - update_adjacent() - ..() - -/obj/structure/table/bullet_act(var/obj/item/projectile/Proj) - if(Proj.destroy) - src.ex_act(1) - ..() - return 0 - -/obj/structure/table/proc/destroy() - new parts(loc) - density = 0 - qdel(src) - -/obj/structure/rack/proc/destroy() - new parts(loc) - density = 0 - qdel(src) - -/obj/structure/table/proc/can_disassemble() - return 1 - -/obj/structure/table/update_icon() - spawn(2) //So it properly updates when deleting - - if(flipped) - var/type = 0 - var/tabledirs = 0 - for(var/direction in list(turn(dir,90), turn(dir,-90)) ) - var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,direction)) - if (T && T.flipped && T.dir == src.dir) - type++ - tabledirs |= direction - var/base = "table" - if (istype(src, /obj/structure/table/woodentable)) - base = "wood" - if (istype(src, /obj/structure/table/reinforced)) - base = "rtable" - - icon_state = "[base]flip[type]" - if (type==1) - if (tabledirs & turn(dir,90)) - icon_state = icon_state+"-" - if (tabledirs & turn(dir,-90)) - icon_state = icon_state+"+" - return 1 - - var/dir_sum = 0 - for(var/direction in alldirs) - var/skip_sum = 0 - for(var/obj/structure/window/W in src.loc) - if(W.dir == direction) //So smooth tables don't go smooth through windows - skip_sum = 1 - continue - var/inv_direction //inverse direction - switch(direction) - if(1) - inv_direction = 2 - if(2) - inv_direction = 1 - if(4) - inv_direction = 8 - if(8) - inv_direction = 4 - if(5) - inv_direction = 10 - if(6) - inv_direction = 9 - if(9) - inv_direction = 6 - if(10) - inv_direction = 5 - for(var/obj/structure/window/W in get_step(src,direction)) - if(W.dir == inv_direction) //So smooth tables don't go smooth through windows when the window is on the other table's tile - skip_sum = 1 - continue - if(!skip_sum) //means there is a window between the two tiles in this direction - var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,direction)) - if(T && !T.flipped) - if(direction <5) - dir_sum += direction - else - if(direction == 5) //This permits the use of all table directions. (Set up so clockwise around the central table is a higher value, from north) - dir_sum += 16 - if(direction == 6) - dir_sum += 32 - if(direction == 8) //Aherp and Aderp. Jezes I am stupid. -- SkyMarshal - dir_sum += 8 - if(direction == 10) - dir_sum += 64 - if(direction == 9) - dir_sum += 128 - - var/table_type = 0 //stand_alone table - if(dir_sum%16 in cardinal) - table_type = 1 //endtable - dir_sum %= 16 - if(dir_sum%16 in list(3,12)) - table_type = 2 //1 tile thick, streight table - if(dir_sum%16 == 3) //3 doesn't exist as a dir - dir_sum = 2 - if(dir_sum%16 == 12) //12 doesn't exist as a dir. - dir_sum = 4 - if(dir_sum%16 in list(5,6,9,10)) - if(locate(/obj/structure/table,get_step(src.loc,dir_sum%16))) - table_type = 3 //full table (not the 1 tile thick one, but one of the 'tabledir' tables) - else - table_type = 2 //1 tile thick, corner table (treated the same as streight tables in code later on) - dir_sum %= 16 - if(dir_sum%16 in list(13,14,7,11)) //Three-way intersection - table_type = 5 //full table as three-way intersections are not sprited, would require 64 sprites to handle all combinations. TOO BAD -- SkyMarshal - switch(dir_sum%16) //Begin computation of the special type tables. --SkyMarshal - if(7) - if(dir_sum == 23) - table_type = 6 - dir_sum = 8 - else if(dir_sum == 39) - dir_sum = 4 - table_type = 6 - else if(dir_sum == 55 || dir_sum == 119 || dir_sum == 247 || dir_sum == 183) - dir_sum = 4 - table_type = 3 - else - dir_sum = 4 - if(11) - if(dir_sum == 75) - dir_sum = 5 - table_type = 6 - else if(dir_sum == 139) - dir_sum = 9 - table_type = 6 - else if(dir_sum == 203 || dir_sum == 219 || dir_sum == 251 || dir_sum == 235) - dir_sum = 8 - table_type = 3 - else - dir_sum = 8 - if(13) - if(dir_sum == 29) - dir_sum = 10 - table_type = 6 - else if(dir_sum == 141) - dir_sum = 6 - table_type = 6 - else if(dir_sum == 189 || dir_sum == 221 || dir_sum == 253 || dir_sum == 157) - dir_sum = 1 - table_type = 3 - else - dir_sum = 1 - if(14) - if(dir_sum == 46) - dir_sum = 1 - table_type = 6 - else if(dir_sum == 78) - dir_sum = 2 - table_type = 6 - else if(dir_sum == 110 || dir_sum == 254 || dir_sum == 238 || dir_sum == 126) - dir_sum = 2 - table_type = 3 - else - dir_sum = 2 //These translate the dir_sum to the correct dirs from the 'tabledir' icon_state. - if(dir_sum%16 == 15) - table_type = 4 //4-way intersection, the 'middle' table sprites will be used. - switch(table_type) - if(0) - icon_state = "[initial(icon_state)]" - if(1) - icon_state = "[initial(icon_state)]_1tileendtable" - if(2) - icon_state = "[initial(icon_state)]_1tilethick" - if(3) - icon_state = "[initial(icon_state)]_dir" - if(4) - icon_state = "[initial(icon_state)]_middle" - if(5) - icon_state = "[initial(icon_state)]_dir2" - if(6) - icon_state = "[initial(icon_state)]_dir3" - if (dir_sum in alldirs) - dir = dir_sum - else - dir = 2 - - clicked = new/icon(src.icon, src.icon_state, src.dir) //giving you runtime icon access is too byond Byond - -/obj/structure/table/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(25)) - destroy() - else - return - - -/obj/structure/table/blob_act() - if(prob(75)) - destroy() - -/obj/structure/table/attack_paw(mob/user) - if(M_HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - visible_message("[user] smashes the [src] apart!") - user.delayNextAttack(8) - destroy() - - -/obj/structure/table/attack_alien(mob/user) - visible_message("[user] slices [src] apart!") - destroy() - -/obj/structure/table/attack_animal(mob/living/simple_animal/user) - if(user.environment_smash>0) - visible_message("[user] smashes [src] apart!") - destroy() - - - -/obj/structure/table/attack_hand(mob/user) - if(M_HULK in user.mutations) - visible_message("[user] smashes [src] apart!") - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - destroy() - -/obj/structure/table/attack_tk() // no telehulk sorry - return - -/obj/structure/table/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - if(istype(mover,/obj/item/projectile)) - return (check_cover(mover,target)) - if(ismob(mover)) - var/mob/M = mover - if(M.flying) - return 1 - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - if (flipped) - if (get_dir(loc, target) == dir) - return !density - else - return 1 - return 0 - -/obj/structure/table/Bumped(atom/AM) - if (istype(AM, /obj/structure/bed/chair/vehicle/wizmobile)) - destroy() - return ..() - -//checks if projectile 'P' from turf 'from' can hit whatever is behind the table. Returns 1 if it can, 0 if bullet stops. -/obj/structure/table/proc/check_cover(obj/item/projectile/P, turf/from) - var/turf/cover = flipped ? get_turf(src) : get_step(loc, get_dir(from, loc)) - if (get_dist(P.starting, loc) <= 1) //Tables won't help you if people are THIS close - return 1 - if (get_turf(P.original) == cover) - var/chance = 20 - if (ismob(P.original)) - var/mob/M = P.original - if (M.lying) - chance += 20 //Lying down lets you catch less bullets - if(flipped) - if(get_dir(loc, from) == dir) //Flipped tables catch mroe bullets - chance += 20 - else - return 1 //But only from one side - if(prob(chance)) - health -= P.damage/2 - if (health > 0) - visible_message("[P] hits \the [src]!") - return 0 - else - visible_message("[src] breaks down!") - destroy() - return 1 - return 1 - -/obj/structure/table/CheckExit(atom/movable/O as mob|obj, target as turf) - if(istype(O) && O.checkpass(PASSTABLE)) - return 1 - if (flipped) - if (get_dir(loc, target) == dir) - return !density - else - return 1 - return 1 - -/obj/structure/table/MouseDrop_T(obj/O as obj, mob/user as mob) - if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) - return - if(user.drop_item()) - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return - - -/obj/structure/table/attackby(obj/item/W as obj, mob/user as mob, params) - if (!W) return - - var/list/params_list = params2list(params) - - if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) - var/obj/item/weapon/grab/G = W - if (istype(G.affecting, /mob/living)) - var/mob/living/M = G.affecting - if (G.state < 2) - if(user.a_intent == I_HURT) - if (prob(15)) M.Weaken(5) - M.apply_damage(8,def_zone = "head") - visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") - playsound(get_turf(src), 'sound/weapons/tablehit1.ogg', 50, 1) - else +/* Tables and Racks + * Contains: + * Tables + * Wooden tables + * Reinforced tables + * Racks + */ + + +/* + * Tables + */ +/obj/structure/table + name = "table" + desc = "A square piece of metal standing on four metal legs. It can not move." + icon = 'icons/obj/structures.dmi' + icon_state = "table" + density = 1 + anchored = 1.0 + layer = 2.8 + throwpass = 1 //You can throw objects over this, despite it's density.") + var/parts = /obj/item/weapon/table_parts + var/icon/clicked + var/flipped = 0 + var/health = 100 + +/obj/structure/table/proc/update_adjacent() + for(var/direction in alldirs) + if(locate(/obj/structure/table, get_step(src, direction))) + var/obj/structure/table/T = locate(/obj/structure/table, get_step(src, direction)) + T.update_icon() + +/obj/structure/table/cultify() + new /obj/structure/table/woodentable(loc) //See New() for qdel + +/obj/structure/table/New() + ..() + for(var/obj/structure/table/T in src.loc) + if(T != src) + qdel(T) + update_icon() + update_adjacent() + +/obj/structure/table/Destroy() + update_adjacent() + ..() + +/obj/structure/table/bullet_act(var/obj/item/projectile/Proj) + if(Proj.destroy) + src.ex_act(1) + ..() + return 0 + +/obj/structure/table/proc/destroy() + new parts(loc) + density = 0 + qdel(src) + +/obj/structure/rack/proc/destroy() + new parts(loc) + density = 0 + qdel(src) + +/obj/structure/table/proc/can_disassemble() + return 1 + +/obj/structure/table/update_icon() + spawn(2) //So it properly updates when deleting + + if(flipped) + var/type = 0 + var/tabledirs = 0 + for(var/direction in list(turn(dir,90), turn(dir,-90)) ) + var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,direction)) + if (T && T.flipped && T.dir == src.dir) + type++ + tabledirs |= direction + var/base = "table" + if (istype(src, /obj/structure/table/woodentable)) + base = "wood" + if (istype(src, /obj/structure/table/reinforced)) + base = "rtable" + + icon_state = "[base]flip[type]" + if (type==1) + if (tabledirs & turn(dir,90)) + icon_state = icon_state+"-" + if (tabledirs & turn(dir,-90)) + icon_state = icon_state+"+" + return 1 + + var/dir_sum = 0 + for(var/direction in alldirs) + var/skip_sum = 0 + for(var/obj/structure/window/W in src.loc) + if(W.dir == direction) //So smooth tables don't go smooth through windows + skip_sum = 1 + continue + var/inv_direction //inverse direction + switch(direction) + if(1) + inv_direction = 2 + if(2) + inv_direction = 1 + if(4) + inv_direction = 8 + if(8) + inv_direction = 4 + if(5) + inv_direction = 10 + if(6) + inv_direction = 9 + if(9) + inv_direction = 6 + if(10) + inv_direction = 5 + for(var/obj/structure/window/W in get_step(src,direction)) + if(W.dir == inv_direction) //So smooth tables don't go smooth through windows when the window is on the other table's tile + skip_sum = 1 + continue + if(!skip_sum) //means there is a window between the two tiles in this direction + var/obj/structure/table/T = locate(/obj/structure/table,get_step(src,direction)) + if(T && !T.flipped) + if(direction <5) + dir_sum += direction + else + if(direction == 5) //This permits the use of all table directions. (Set up so clockwise around the central table is a higher value, from north) + dir_sum += 16 + if(direction == 6) + dir_sum += 32 + if(direction == 8) //Aherp and Aderp. Jezes I am stupid. -- SkyMarshal + dir_sum += 8 + if(direction == 10) + dir_sum += 64 + if(direction == 9) + dir_sum += 128 + + var/table_type = 0 //stand_alone table + if(dir_sum%16 in cardinal) + table_type = 1 //endtable + dir_sum %= 16 + if(dir_sum%16 in list(3,12)) + table_type = 2 //1 tile thick, streight table + if(dir_sum%16 == 3) //3 doesn't exist as a dir + dir_sum = 2 + if(dir_sum%16 == 12) //12 doesn't exist as a dir. + dir_sum = 4 + if(dir_sum%16 in list(5,6,9,10)) + if(locate(/obj/structure/table,get_step(src.loc,dir_sum%16))) + table_type = 3 //full table (not the 1 tile thick one, but one of the 'tabledir' tables) + else + table_type = 2 //1 tile thick, corner table (treated the same as streight tables in code later on) + dir_sum %= 16 + if(dir_sum%16 in list(13,14,7,11)) //Three-way intersection + table_type = 5 //full table as three-way intersections are not sprited, would require 64 sprites to handle all combinations. TOO BAD -- SkyMarshal + switch(dir_sum%16) //Begin computation of the special type tables. --SkyMarshal + if(7) + if(dir_sum == 23) + table_type = 6 + dir_sum = 8 + else if(dir_sum == 39) + dir_sum = 4 + table_type = 6 + else if(dir_sum == 55 || dir_sum == 119 || dir_sum == 247 || dir_sum == 183) + dir_sum = 4 + table_type = 3 + else + dir_sum = 4 + if(11) + if(dir_sum == 75) + dir_sum = 5 + table_type = 6 + else if(dir_sum == 139) + dir_sum = 9 + table_type = 6 + else if(dir_sum == 203 || dir_sum == 219 || dir_sum == 251 || dir_sum == 235) + dir_sum = 8 + table_type = 3 + else + dir_sum = 8 + if(13) + if(dir_sum == 29) + dir_sum = 10 + table_type = 6 + else if(dir_sum == 141) + dir_sum = 6 + table_type = 6 + else if(dir_sum == 189 || dir_sum == 221 || dir_sum == 253 || dir_sum == 157) + dir_sum = 1 + table_type = 3 + else + dir_sum = 1 + if(14) + if(dir_sum == 46) + dir_sum = 1 + table_type = 6 + else if(dir_sum == 78) + dir_sum = 2 + table_type = 6 + else if(dir_sum == 110 || dir_sum == 254 || dir_sum == 238 || dir_sum == 126) + dir_sum = 2 + table_type = 3 + else + dir_sum = 2 //These translate the dir_sum to the correct dirs from the 'tabledir' icon_state. + if(dir_sum%16 == 15) + table_type = 4 //4-way intersection, the 'middle' table sprites will be used. + switch(table_type) + if(0) + icon_state = "[initial(icon_state)]" + if(1) + icon_state = "[initial(icon_state)]_1tileendtable" + if(2) + icon_state = "[initial(icon_state)]_1tilethick" + if(3) + icon_state = "[initial(icon_state)]_dir" + if(4) + icon_state = "[initial(icon_state)]_middle" + if(5) + icon_state = "[initial(icon_state)]_dir2" + if(6) + icon_state = "[initial(icon_state)]_dir3" + if (dir_sum in alldirs) + dir = dir_sum + else + dir = 2 + + clicked = new/icon(src.icon, src.icon_state, src.dir) //giving you runtime icon access is too byond Byond + +/obj/structure/table/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(25)) + destroy() + else + return + + +/obj/structure/table/blob_act() + if(prob(75)) + destroy() + +/obj/structure/table/attack_paw(mob/user) + if(M_HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes the [src] apart!") + user.delayNextAttack(8) + destroy() + + +/obj/structure/table/attack_alien(mob/user) + visible_message("[user] slices [src] apart!") + destroy() + +/obj/structure/table/attack_animal(mob/living/simple_animal/user) + if(user.environment_smash>0) + visible_message("[user] smashes [src] apart!") + destroy() + + + +/obj/structure/table/attack_hand(mob/user) + if(M_HULK in user.mutations) + visible_message("[user] smashes [src] apart!") + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + destroy() + +/obj/structure/table/attack_tk() // no telehulk sorry + return + +/obj/structure/table/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + if(istype(mover,/obj/item/projectile)) + return (check_cover(mover,target)) + if(ismob(mover)) + var/mob/M = mover + if(M.flying) + return 1 + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + if (flipped) + if (get_dir(loc, target) == dir) + return !density + else + return 1 + return 0 + +/obj/structure/table/Bumped(atom/AM) + if (istype(AM, /obj/structure/bed/chair/vehicle/wizmobile)) + destroy() + return ..() + +//checks if projectile 'P' from turf 'from' can hit whatever is behind the table. Returns 1 if it can, 0 if bullet stops. +/obj/structure/table/proc/check_cover(obj/item/projectile/P, turf/from) + var/turf/cover = flipped ? get_turf(src) : get_step(loc, get_dir(from, loc)) + if (get_dist(P.starting, loc) <= 1) //Tables won't help you if people are THIS close + return 1 + if (get_turf(P.original) == cover) + var/chance = 20 + if (ismob(P.original)) + var/mob/M = P.original + if (M.lying) + chance += 20 //Lying down lets you catch less bullets + if(flipped) + if(get_dir(loc, from) == dir) //Flipped tables catch mroe bullets + chance += 20 + else + return 1 //But only from one side + if(prob(chance)) + health -= P.damage/2 + if (health > 0) + visible_message("[P] hits \the [src]!") + return 0 + else + visible_message("[src] breaks down!") + destroy() + return 1 + return 1 + +/obj/structure/table/CheckExit(atom/movable/O as mob|obj, target as turf) + if(istype(O) && O.checkpass(PASSTABLE)) + return 1 + if (flipped) + if (get_dir(loc, target) == dir) + return !density + else + return 1 + return 1 + +/obj/structure/table/MouseDrop_T(obj/O as obj, mob/user as mob) + if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) + return + if(user.drop_item()) + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return + + +/obj/structure/table/attackby(obj/item/W as obj, mob/user as mob, params) + if (!W) return + + var/list/params_list = params2list(params) + + if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) + var/obj/item/weapon/grab/G = W + if (istype(G.affecting, /mob/living)) + var/mob/living/M = G.affecting + if (G.state < 2) + if(user.a_intent == I_HURT) + if (prob(15)) M.Weaken(5) + M.apply_damage(8,def_zone = "head") + visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") + playsound(get_turf(src), 'sound/weapons/tablehit1.ogg', 50, 1) + else to_chat(user, "You need a better grip to do that!") - return - else - G.affecting.loc = src.loc - G.affecting.Weaken(5) - visible_message("[G.assailant] puts [G.affecting] on \the [src].") - returnToPool(W) - return - - if (istype(W, /obj/item/weapon/wrench) && can_disassemble()) - //if(!params_list.len || text2num(params_list["icon-y"]) < 8) //8 above the bottom of the icon + return + else + G.affecting.loc = src.loc + G.affecting.Weaken(5) + visible_message("[G.assailant] puts [G.affecting] on \the [src].") + returnToPool(W) + return + + if (istype(W, /obj/item/weapon/wrench) && can_disassemble()) + //if(!params_list.len || text2num(params_list["icon-y"]) < 8) //8 above the bottom of the icon to_chat(user, "Now disassembling table") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src,50)) - destroy() - return - - if(user.drop_item(W, src.loc)) - if(W.loc == src.loc && params_list.len) - var/clamp_x = clicked.Width() / 2 - var/clamp_y = clicked.Height() / 2 - W.pixel_x = Clamp(text2num(params_list["icon-x"]) - clamp_x, -clamp_x, clamp_x) - W.pixel_y = Clamp(text2num(params_list["icon-y"]) - clamp_y, -clamp_y, clamp_y) - return - -/obj/structure/table/proc/straight_table_check(var/direction) - var/obj/structure/table/T - for(var/angle in list(-90,90)) - T = locate() in get_step(src.loc,turn(direction,angle)) - if(T && !T.flipped) - return 0 - T = locate() in get_step(src.loc,direction) - if (!T || T.flipped) - return 1 - if (istype(T,/obj/structure/table/reinforced/)) - var/obj/structure/table/reinforced/R = T - if (R.status == 2) - return 0 - return T.straight_table_check(direction) - -/obj/structure/table/verb/can_touch(var/mob/user) - if (!user) - return 0 - if (user.stat) //zombie goasts go away - return 0 - if (issilicon(user)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src,50)) + destroy() + return + + if(user.drop_item(W, src.loc)) + if(W.loc == src.loc && params_list.len) + var/clamp_x = clicked.Width() / 2 + var/clamp_y = clicked.Height() / 2 + W.pixel_x = Clamp(text2num(params_list["icon-x"]) - clamp_x, -clamp_x, clamp_x) + W.pixel_y = Clamp(text2num(params_list["icon-y"]) - clamp_y, -clamp_y, clamp_y) + return + +/obj/structure/table/proc/straight_table_check(var/direction) + var/obj/structure/table/T + for(var/angle in list(-90,90)) + T = locate() in get_step(src.loc,turn(direction,angle)) + if(T && !T.flipped) + return 0 + T = locate() in get_step(src.loc,direction) + if (!T || T.flipped) + return 1 + if (istype(T,/obj/structure/table/reinforced/)) + var/obj/structure/table/reinforced/R = T + if (R.status == 2) + return 0 + return T.straight_table_check(direction) + +/obj/structure/table/verb/can_touch(var/mob/user) + if (!user) + return 0 + if (user.stat) //zombie goasts go away + return 0 + if (issilicon(user)) to_chat(user, "You need hands for this.") - return 0 - return 1 - -/obj/structure/table/verb/do_flip() - set name = "Flip table" - set desc = "Flips a non-reinforced table" - set category = "Object" - set src in oview(1) - if(ismouse(usr)) - return - if (!can_touch(usr)) - return - if(!flip(get_cardinal_dir(usr,src))) + return 0 + return 1 + +/obj/structure/table/verb/do_flip() + set name = "Flip table" + set desc = "Flips a non-reinforced table" + set category = "Object" + set src in oview(1) + if(ismouse(usr)) + return + if (!can_touch(usr)) + return + if(!flip(get_cardinal_dir(usr,src))) to_chat(usr, "It won't budge.") - else - usr.visible_message("[usr] flips \the [src]!") - return - -/obj/structure/table/proc/unflipping_check(var/direction) - for(var/mob/M in oview(src,0)) - return 0 - - var/list/L = list() - if(direction) - L.Add(direction) - else - L.Add(turn(src.dir,-90)) - L.Add(turn(src.dir,90)) - for(var/new_dir in L) - var/obj/structure/table/T = locate() in get_step(src.loc,new_dir) - if(T) - if(T.flipped && T.dir == src.dir && !T.unflipping_check(new_dir)) - return 0 - return 1 - -/obj/structure/table/proc/do_put() - set name = "Put table back" - set desc = "Puts flipped table back" - set category = "Object" - set src in oview(1) - - if (!can_touch(usr)) - return - - if (!unflipping_check()) + else + usr.visible_message("[usr] flips \the [src]!") + return + +/obj/structure/table/proc/unflipping_check(var/direction) + for(var/mob/M in oview(src,0)) + return 0 + + var/list/L = list() + if(direction) + L.Add(direction) + else + L.Add(turn(src.dir,-90)) + L.Add(turn(src.dir,90)) + for(var/new_dir in L) + var/obj/structure/table/T = locate() in get_step(src.loc,new_dir) + if(T) + if(T.flipped && T.dir == src.dir && !T.unflipping_check(new_dir)) + return 0 + return 1 + +/obj/structure/table/proc/do_put() + set name = "Put table back" + set desc = "Puts flipped table back" + set category = "Object" + set src in oview(1) + + if (!can_touch(usr)) + return + + if (!unflipping_check()) to_chat(usr, "It won't budge.") - return - unflip() - -/obj/structure/table/proc/flip(var/direction) - if( !straight_table_check(turn(direction,90)) || !straight_table_check(turn(direction,-90)) ) - return 0 - - verbs -=/obj/structure/table/verb/do_flip - verbs +=/obj/structure/table/proc/do_put - - var/list/targets = list(get_step(src,dir),get_step(src,turn(dir, 45)),get_step(src,turn(dir, -45))) - for (var/atom/movable/A in get_turf(src)) - if (!A.anchored) - spawn(0) - A.throw_at(pick(targets),1,1) - - dir = direction - if(dir != NORTH) - layer = 5 - flipped = 1 - flags |= ON_BORDER - for(var/D in list(turn(direction, 90), turn(direction, -90))) - var/obj/structure/table/T = locate() in get_step(src,D) - if(T && !T.flipped) - T.flip(direction) - update_icon() - update_adjacent() - - return 1 - -/obj/structure/table/proc/unflip() - verbs -=/obj/structure/table/proc/do_put - verbs +=/obj/structure/table/verb/do_flip - - layer = initial(layer) - flipped = 0 - flags &= ~ON_BORDER - for(var/D in list(turn(dir, 90), turn(dir, -90))) - var/obj/structure/table/T = locate() in get_step(src.loc,D) - if(T && T.flipped && T.dir == src.dir) - T.unflip() - update_icon() - update_adjacent() - - return 1 - -/* - * Wooden tables - */ -/obj/structure/table/woodentable - name = "wooden table" - desc = "Do not apply fire to this. Rumour says it burns easily." - icon_state = "woodtable" - parts = /obj/item/weapon/table_parts/wood - health = 50 - autoignition_temperature = AUTOIGNITION_WOOD // TODO: Special ash subtype that looks like charred table legs. - fire_fuel = 5 - -/obj/structure/table/woodentable/cultify() - return - -/obj/structure/table/woodentable/poker //No specialties, Just a mapping object. - name = "gambling table" - desc = "A seedy table for seedy dealings in seedy places." - icon_state = "pokertable" - parts = /obj/item/weapon/table_parts/wood/poker - -/* - * Reinforced tables - */ -/obj/structure/table/reinforced - name = "reinforced table" - desc = "A version of the four legged table. It is stronger." - icon_state = "reinftable" - parts = /obj/item/weapon/table_parts/reinforced - var/status = 2 - -/obj/structure/table/reinforced/can_disassemble() - return status != 2 - -/obj/structure/table/reinforced/flip(var/direction) - if (status == 2) - return 0 - else - return ..() - -/obj/structure/table/reinforced/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(istype(W,/obj/item/weapon/stock_parts/scanning_module)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 40)) - if(user.drop_item(W)) - var/obj/machinery/optable/OPT = new /obj/machinery/optable(src.loc) - var/obj/item/weapon/stock_parts/scanning_module/SM = W - OPT.rating = SM.rating - - qdel(W) - qdel(src) - - return - else - user << "\The [W] is stuck to your hands!" - return - - else if (istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(!(WT.welding)/* || (params_list.len && text2num(params_list["icon-y"]) > 8)*/) //8 above the bottom of the icon - return ..() - if(WT.remove_fuel(0, user)) - if(src.status == 2) + return + unflip() + +/obj/structure/table/proc/flip(var/direction) + if( !straight_table_check(turn(direction,90)) || !straight_table_check(turn(direction,-90)) ) + return 0 + + verbs -=/obj/structure/table/verb/do_flip + verbs +=/obj/structure/table/proc/do_put + + var/list/targets = list(get_step(src,dir),get_step(src,turn(dir, 45)),get_step(src,turn(dir, -45))) + for (var/atom/movable/A in get_turf(src)) + if (!A.anchored) + spawn(0) + A.throw_at(pick(targets),1,1) + + dir = direction + if(dir != NORTH) + layer = 5 + flipped = 1 + flags |= ON_BORDER + for(var/D in list(turn(direction, 90), turn(direction, -90))) + var/obj/structure/table/T = locate() in get_step(src,D) + if(T && !T.flipped) + T.flip(direction) + update_icon() + update_adjacent() + + return 1 + +/obj/structure/table/proc/unflip() + verbs -=/obj/structure/table/proc/do_put + verbs +=/obj/structure/table/verb/do_flip + + layer = initial(layer) + flipped = 0 + flags &= ~ON_BORDER + for(var/D in list(turn(dir, 90), turn(dir, -90))) + var/obj/structure/table/T = locate() in get_step(src.loc,D) + if(T && T.flipped && T.dir == src.dir) + T.unflip() + update_icon() + update_adjacent() + + return 1 + +/* + * Wooden tables + */ +/obj/structure/table/woodentable + name = "wooden table" + desc = "Do not apply fire to this. Rumour says it burns easily." + icon_state = "woodtable" + parts = /obj/item/weapon/table_parts/wood + health = 50 + autoignition_temperature = AUTOIGNITION_WOOD // TODO: Special ash subtype that looks like charred table legs. + fire_fuel = 5 + +/obj/structure/table/woodentable/cultify() + return + +/obj/structure/table/woodentable/poker //No specialties, Just a mapping object. + name = "gambling table" + desc = "A seedy table for seedy dealings in seedy places." + icon_state = "pokertable" + parts = /obj/item/weapon/table_parts/wood/poker + +/* + * Reinforced tables + */ +/obj/structure/table/reinforced + name = "reinforced table" + desc = "A version of the four legged table. It is stronger." + icon_state = "reinftable" + parts = /obj/item/weapon/table_parts/reinforced + var/status = 2 + +/obj/structure/table/reinforced/can_disassemble() + return status != 2 + +/obj/structure/table/reinforced/flip(var/direction) + if (status == 2) + return 0 + else + return ..() + +/obj/structure/table/reinforced/attackby(obj/item/weapon/W as obj, mob/user as mob, params) + if(istype(W,/obj/item/weapon/stock_parts/scanning_module)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 40)) + if(user.drop_item(W)) + var/obj/machinery/optable/OPT = new /obj/machinery/optable(src.loc) + var/obj/item/weapon/stock_parts/scanning_module/SM = W + OPT.rating = SM.rating + + qdel(W) + qdel(src) + + return + else + user << "\The [W] is stuck to your hands!" + return + + else if (istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(!(WT.welding)/* || (params_list.len && text2num(params_list["icon-y"]) > 8)*/) //8 above the bottom of the icon + return ..() + if(WT.remove_fuel(0, user)) + if(src.status == 2) to_chat(user, "Now weakening the reinforced table.") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - if (do_after(user, src, 50)) - if(!src || !WT.isOn()) return + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + if (do_after(user, src, 50)) + if(!src || !WT.isOn()) return to_chat(user, "Table weakened.") - src.status = 1 - else + src.status = 1 + else to_chat(user, "Now strengthening the reinforced table.") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - if (do_after(user, src, 50)) - if(!src || !WT.isOn()) return + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + if (do_after(user, src, 50)) + if(!src || !WT.isOn()) return to_chat(user, "Table strengthened.") - src.status = 2 - return - return - return ..() - -/* - * Racks - */ -/obj/structure/rack - name = "rack" - desc = "Different from the Middle Ages version." - icon = 'icons/obj/objects.dmi' - icon_state = "rack" - density = 1 - flags = FPRINT - anchored = 1.0 - throwpass = 1 //You can throw objects over this, despite it's density. - var/parts = /obj/item/weapon/rack_parts - var/offset_step = 0 - -/obj/structure/rack/bullet_act(var/obj/item/projectile/Proj) - if(Proj.destroy) - src.ex_act(1) - ..() - return 0 - -/obj/structure/rack/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - if(2.0) - qdel(src) - if(prob(50)) - new /obj/item/weapon/rack_parts(src.loc) - if(3.0) - if(prob(25)) - qdel(src) - new /obj/item/weapon/rack_parts(src.loc) - -/obj/structure/rack/blob_act() - if(prob(75)) - del(src) - return - else if(prob(50)) - new /obj/item/weapon/rack_parts(src.loc) - del(src) - return - -/obj/structure/rack/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - if(src.density == 0) //Because broken racks -Agouri |TODO: SPRITE!| - return 1 - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - else - return 0 - -/obj/structure/rack/Bumped(atom/AM) - if (istype(AM, /obj/structure/bed/chair/vehicle/wizmobile)) - destroy() - return ..() - -/obj/structure/rack/MouseDrop_T(obj/O as obj, mob/user as mob) - if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) - return - if(user.drop_item(O)) - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return - -/obj/structure/rack/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/weapon/rack_parts( src.loc ) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - del(src) - return - - if(user.drop_item(W, src.loc)) - if(W.loc == src.loc) - switch(offset_step) - if(1) - W.pixel_x = -3 - W.pixel_y = 3 - if(2) - W.pixel_x = 0 - W.pixel_y = 0 - if(3) - W.pixel_x = 3 - W.pixel_y = -3 - offset_step = 0 - offset_step++ - return 1 - -/obj/structure/table/attack_hand(mob/user) - if(M_HULK in user.mutations) - visible_message("[user] smashes [src] apart!") - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - destroy() - -/obj/structure/rack/attack_paw(mob/user) - if(M_HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - visible_message("[user] smashes [src] apart!") - destroy() - -/obj/structure/rack/attack_alien(mob/user) - visible_message("[user] slices [src] apart!") - destroy() - -/obj/structure/rack/attack_animal(mob/living/simple_animal/user) - if(user.environment_smash>0) - visible_message("[user] smashes [src] apart!") - destroy() - -/obj/structure/rack/attack_tk() // no telehulk sorry - return + src.status = 2 + return + return + return ..() + +/* + * Racks + */ +/obj/structure/rack + name = "rack" + desc = "Different from the Middle Ages version." + icon = 'icons/obj/objects.dmi' + icon_state = "rack" + density = 1 + flags = FPRINT + anchored = 1.0 + throwpass = 1 //You can throw objects over this, despite it's density. + var/parts = /obj/item/weapon/rack_parts + var/offset_step = 0 + +/obj/structure/rack/bullet_act(var/obj/item/projectile/Proj) + if(Proj.destroy) + src.ex_act(1) + ..() + return 0 + +/obj/structure/rack/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + if(2.0) + qdel(src) + if(prob(50)) + new /obj/item/weapon/rack_parts(src.loc) + if(3.0) + if(prob(25)) + qdel(src) + new /obj/item/weapon/rack_parts(src.loc) + +/obj/structure/rack/blob_act() + if(prob(75)) + del(src) + return + else if(prob(50)) + new /obj/item/weapon/rack_parts(src.loc) + del(src) + return + +/obj/structure/rack/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + if(src.density == 0) //Because broken racks -Agouri |TODO: SPRITE!| + return 1 + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + else + return 0 + +/obj/structure/rack/Bumped(atom/AM) + if (istype(AM, /obj/structure/bed/chair/vehicle/wizmobile)) + destroy() + return ..() + +/obj/structure/rack/MouseDrop_T(obj/O as obj, mob/user as mob) + if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) + return + if(user.drop_item(O)) + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return + +/obj/structure/rack/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/weapon/rack_parts( src.loc ) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + del(src) + return + + if(user.drop_item(W, src.loc)) + if(W.loc == src.loc) + switch(offset_step) + if(1) + W.pixel_x = -3 + W.pixel_y = 3 + if(2) + W.pixel_x = 0 + W.pixel_y = 0 + if(3) + W.pixel_x = 3 + W.pixel_y = -3 + offset_step = 0 + offset_step++ + return 1 + +/obj/structure/table/attack_hand(mob/user) + if(M_HULK in user.mutations) + visible_message("[user] smashes [src] apart!") + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + destroy() + +/obj/structure/rack/attack_paw(mob/user) + if(M_HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes [src] apart!") + destroy() + +/obj/structure/rack/attack_alien(mob/user) + visible_message("[user] slices [src] apart!") + destroy() + +/obj/structure/rack/attack_animal(mob/living/simple_animal/user) + if(user.environment_smash>0) + visible_message("[user] smashes [src] apart!") + destroy() + +/obj/structure/rack/attack_tk() // no telehulk sorry + return diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 6d2739a6d67..e5a7d81686e 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -1,123 +1,123 @@ -/obj/structure/dispenser - name = "tank storage unit" - desc = "A simple yet bulky storage device for gas tanks. Has room for up to ten oxygen tanks, and ten plasma tanks." - icon = 'icons/obj/objects.dmi' - icon_state = "dispenser" - density = 1 - anchored = 1.0 - var/oxygentanks = 10 - var/plasmatanks = 10 - var/list/oxytanks = list() //sorry for the similar var names - var/list/platanks = list() - - -/obj/structure/dispenser/oxygen - plasmatanks = 0 - -/obj/structure/dispenser/plasma - oxygentanks = 0 - -/obj/structure/dispenser/empty - plasmatanks = 0 - oxygentanks = 0 - - -/obj/structure/dispenser/New() - . = ..() - update_icon() - - -/obj/structure/dispenser/update_icon() - overlays.len = 0 - switch(oxygentanks) - if(1 to 3) overlays += "oxygen-[oxygentanks]" - if(4 to INFINITY) overlays += "oxygen-4" - switch(plasmatanks) - if(1 to 4) overlays += "plasma-[plasmatanks]" - if(5 to INFINITY) overlays += "plasma-5" - - -/obj/structure/dispenser/attack_robot(mob/user as mob) - if(isMoMMI(user)) - return attack_hand(user) - return ..() - -/obj/structure/dispenser/attack_hand(mob/user as mob) - user.set_machine(src) - var/dat = "[src]

    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\tank_dispenser.dm:38: dat += "Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
    " - dat += {"Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
    - Plasma tanks: [plasmatanks] - [plasmatanks ? "Dispense" : "empty"]"} - // END AUTOFIX - user << browse(dat, "window=dispenser") - onclose(user, "dispenser") - return - - -/obj/structure/dispenser/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/weapon/tank/oxygen) || istype(I, /obj/item/weapon/tank/air) || istype(I, /obj/item/weapon/tank/anesthetic)) - if(oxygentanks < 10) - if(user.drop_item(I, src)) - oxytanks.Add(I) - oxygentanks++ - to_chat(user, "You put [I] in [src].") - else - to_chat(user, "[src] is full.") - updateUsrDialog() - return - if(istype(I, /obj/item/weapon/tank/plasma)) - if(plasmatanks < 10) - if(user.drop_item(I, src)) - platanks.Add(I) - plasmatanks++ - to_chat(user, "You put [I] in [src].") - else - to_chat(user, "[src] is full.") - updateUsrDialog() - return - if(istype(I, /obj/item/weapon/wrench)) - if(anchored) - to_chat(user, "You lean down and unwrench [src].") - anchored = 0 - else - to_chat(user, "You wrench [src] into place.") - anchored = 1 - return - -/obj/structure/dispenser/Topic(href, href_list) - if(usr.stat || usr.restrained()) - return - if(Adjacent(usr)) - usr.set_machine(src) - if(href_list["oxygen"]) - if(oxygentanks > 0) - var/obj/item/weapon/tank/oxygen/O - if(oxytanks.len == oxygentanks) - O = oxytanks[1] - oxytanks.Remove(O) - else - O = new /obj/item/weapon/tank/oxygen(loc) - O.loc = loc - to_chat(usr, "You take [O] out of [src].") - oxygentanks-- - update_icon() - if(href_list["plasma"]) - if(plasmatanks > 0) - var/obj/item/weapon/tank/plasma/P - if(platanks.len == plasmatanks) - P = platanks[1] - platanks.Remove(P) - else - P = new /obj/item/weapon/tank/plasma(loc) - P.loc = loc - to_chat(usr, "You take [P] out of [src].") - plasmatanks-- - update_icon() - add_fingerprint(usr) - updateUsrDialog() - else - usr << browse(null, "window=dispenser") - return +/obj/structure/dispenser + name = "tank storage unit" + desc = "A simple yet bulky storage device for gas tanks. Has room for up to ten oxygen tanks, and ten plasma tanks." + icon = 'icons/obj/objects.dmi' + icon_state = "dispenser" + density = 1 + anchored = 1.0 + var/oxygentanks = 10 + var/plasmatanks = 10 + var/list/oxytanks = list() //sorry for the similar var names + var/list/platanks = list() + + +/obj/structure/dispenser/oxygen + plasmatanks = 0 + +/obj/structure/dispenser/plasma + oxygentanks = 0 + +/obj/structure/dispenser/empty + plasmatanks = 0 + oxygentanks = 0 + + +/obj/structure/dispenser/New() + . = ..() + update_icon() + + +/obj/structure/dispenser/update_icon() + overlays.len = 0 + switch(oxygentanks) + if(1 to 3) overlays += "oxygen-[oxygentanks]" + if(4 to INFINITY) overlays += "oxygen-4" + switch(plasmatanks) + if(1 to 4) overlays += "plasma-[plasmatanks]" + if(5 to INFINITY) overlays += "plasma-5" + + +/obj/structure/dispenser/attack_robot(mob/user as mob) + if(isMoMMI(user)) + return attack_hand(user) + return ..() + +/obj/structure/dispenser/attack_hand(mob/user as mob) + user.set_machine(src) + var/dat = "[src]

    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\objects\structures\tank_dispenser.dm:38: dat += "Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
    " + dat += {"Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
    + Plasma tanks: [plasmatanks] - [plasmatanks ? "Dispense" : "empty"]"} + // END AUTOFIX + user << browse(dat, "window=dispenser") + onclose(user, "dispenser") + return + + +/obj/structure/dispenser/attackby(obj/item/I as obj, mob/user as mob) + if(istype(I, /obj/item/weapon/tank/oxygen) || istype(I, /obj/item/weapon/tank/air) || istype(I, /obj/item/weapon/tank/anesthetic)) + if(oxygentanks < 10) + if(user.drop_item(I, src)) + oxytanks.Add(I) + oxygentanks++ + to_chat(user, "You put [I] in [src].") + else + to_chat(user, "[src] is full.") + updateUsrDialog() + return + if(istype(I, /obj/item/weapon/tank/plasma)) + if(plasmatanks < 10) + if(user.drop_item(I, src)) + platanks.Add(I) + plasmatanks++ + to_chat(user, "You put [I] in [src].") + else + to_chat(user, "[src] is full.") + updateUsrDialog() + return + if(istype(I, /obj/item/weapon/wrench)) + if(anchored) + to_chat(user, "You lean down and unwrench [src].") + anchored = 0 + else + to_chat(user, "You wrench [src] into place.") + anchored = 1 + return + +/obj/structure/dispenser/Topic(href, href_list) + if(usr.stat || usr.restrained()) + return + if(Adjacent(usr)) + usr.set_machine(src) + if(href_list["oxygen"]) + if(oxygentanks > 0) + var/obj/item/weapon/tank/oxygen/O + if(oxytanks.len == oxygentanks) + O = oxytanks[1] + oxytanks.Remove(O) + else + O = new /obj/item/weapon/tank/oxygen(loc) + O.loc = loc + to_chat(usr, "You take [O] out of [src].") + oxygentanks-- + update_icon() + if(href_list["plasma"]) + if(plasmatanks > 0) + var/obj/item/weapon/tank/plasma/P + if(platanks.len == plasmatanks) + P = platanks[1] + platanks.Remove(P) + else + P = new /obj/item/weapon/tank/plasma(loc) + P.loc = loc + to_chat(usr, "You take [P] out of [src].") + plasmatanks-- + update_icon() + add_fingerprint(usr) + updateUsrDialog() + else + usr << browse(null, "window=dispenser") + return return \ No newline at end of file diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index c59123449f8..6e0863d40ca 100644 --- a/code/game/objects/structures/target_stake.dm +++ b/code/game/objects/structures/target_stake.dm @@ -1,52 +1,52 @@ -// Basically they are for the firing range -/obj/structure/target_stake - name = "target stake" - desc = "A thin platform with negatively-magnetized wheels." - icon = 'icons/obj/objects.dmi' - icon_state = "target_stake" - density = 1 - flags = 0 - siemens_coefficient = 1 - var/obj/item/target/pinned_target // the current pinned target - - Move() - ..() - // Move the pinned target along with the stake - if(pinned_target in view(3, src)) - pinned_target.loc = loc - - else // Sanity check: if the pinned target can't be found in immediate view - pinned_target = null - density = 1 - - attackby(obj/item/W as obj, mob/user as mob) - // Putting objects on the stake. Most importantly, targets - if(pinned_target) - return // get rid of that pinned target first! - - if(istype(W, /obj/item/target)) - if(user.drop_item(W, src.loc)) - density = 0 - W.density = 1 - W.layer = 3.1 - pinned_target = W - to_chat(user, "You slide the target into the stake.") - return - - attack_hand(mob/user as mob) - // taking pinned targets off! - if(pinned_target) - density = 1 - pinned_target.density = 0 - pinned_target.layer = OBJ_LAYER - - pinned_target.loc = user.loc - if(ishuman(user)) - if(!user.get_active_hand()) - user.put_in_hands(pinned_target) - to_chat(user, "You take the target out of the stake.") - else - pinned_target.loc = get_turf(user) - to_chat(user, "You take the target out of the stake.") - +// Basically they are for the firing range +/obj/structure/target_stake + name = "target stake" + desc = "A thin platform with negatively-magnetized wheels." + icon = 'icons/obj/objects.dmi' + icon_state = "target_stake" + density = 1 + flags = 0 + siemens_coefficient = 1 + var/obj/item/target/pinned_target // the current pinned target + + Move() + ..() + // Move the pinned target along with the stake + if(pinned_target in view(3, src)) + pinned_target.loc = loc + + else // Sanity check: if the pinned target can't be found in immediate view + pinned_target = null + density = 1 + + attackby(obj/item/W as obj, mob/user as mob) + // Putting objects on the stake. Most importantly, targets + if(pinned_target) + return // get rid of that pinned target first! + + if(istype(W, /obj/item/target)) + if(user.drop_item(W, src.loc)) + density = 0 + W.density = 1 + W.layer = 3.1 + pinned_target = W + to_chat(user, "You slide the target into the stake.") + return + + attack_hand(mob/user as mob) + // taking pinned targets off! + if(pinned_target) + density = 1 + pinned_target.density = 0 + pinned_target.layer = OBJ_LAYER + + pinned_target.loc = user.loc + if(ishuman(user)) + if(!user.get_active_hand()) + user.put_in_hands(pinned_target) + to_chat(user, "You take the target out of the stake.") + else + pinned_target.loc = get_turf(user) + to_chat(user, "You take the target out of the stake.") + pinned_target = null \ No newline at end of file diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 89466053358..0a47ee9defe 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -1,546 +1,546 @@ -//Windows, one of the oldest pieces of code -//Note : You might wonder where full windows are. Full windows are in fullwindow.dm. Now you know -//And knowing is half the battle - -#define WINDOWLOOSE 0 -#define WINDOWLOOSEFRAME 1 -#define WINDOWUNSECUREFRAME 2 -#define WINDOWSECURE 3 - -/obj/structure/window - name = "window" - desc = "A silicate barrier, used to keep things out and in sight. Fragile." - icon = 'icons/obj/structures.dmi' - icon_state = "window" - density = 1 - layer = 3.2 //Just above airlocks //For some reason I guess - pressure_resistance = 4*ONE_ATMOSPHERE - anchored = 1 - var/health = 10 //This window is so bad blowing on it would break it, sucks for it - var/ini_dir = null //This really shouldn't exist, but it does and I don't want to risk deleting it because it's likely mapping-related - var/d_state = WINDOWLOOSEFRAME //Normal windows have one step (unanchor), reinforced windows have three - var/shardtype = /obj/item/weapon/shard - var/sheettype = /obj/item/stack/sheet/glass/glass //Used for deconstruction - var/sheetamount = 1 //Number of sheets needed to build this window (determines how much shit is spawned via Destroy()) - var/reinforced = 0 //Used for deconstruction steps - penetration_dampening = 1 - - var/obj/Overlays/damage_overlay - var/cracked_base = "crack" - - var/fire_temp_threshold = 800 - var/fire_volume_mod = 100 - -/obj/structure/window/New(loc) - - ..(loc) - flags |= ON_BORDER - ini_dir = dir - - update_nearby_tiles() - update_nearby_icons() - update_icon() - -/obj/structure/window/projectile_check() - return PROJREACT_WINDOWS - -/obj/structure/window/examine(mob/user) - - ..() - if(!anchored) +//Windows, one of the oldest pieces of code +//Note : You might wonder where full windows are. Full windows are in fullwindow.dm. Now you know +//And knowing is half the battle + +#define WINDOWLOOSE 0 +#define WINDOWLOOSEFRAME 1 +#define WINDOWUNSECUREFRAME 2 +#define WINDOWSECURE 3 + +/obj/structure/window + name = "window" + desc = "A silicate barrier, used to keep things out and in sight. Fragile." + icon = 'icons/obj/structures.dmi' + icon_state = "window" + density = 1 + layer = 3.2 //Just above airlocks //For some reason I guess + pressure_resistance = 4*ONE_ATMOSPHERE + anchored = 1 + var/health = 10 //This window is so bad blowing on it would break it, sucks for it + var/ini_dir = null //This really shouldn't exist, but it does and I don't want to risk deleting it because it's likely mapping-related + var/d_state = WINDOWLOOSEFRAME //Normal windows have one step (unanchor), reinforced windows have three + var/shardtype = /obj/item/weapon/shard + var/sheettype = /obj/item/stack/sheet/glass/glass //Used for deconstruction + var/sheetamount = 1 //Number of sheets needed to build this window (determines how much shit is spawned via Destroy()) + var/reinforced = 0 //Used for deconstruction steps + penetration_dampening = 1 + + var/obj/Overlays/damage_overlay + var/cracked_base = "crack" + + var/fire_temp_threshold = 800 + var/fire_volume_mod = 100 + +/obj/structure/window/New(loc) + + ..(loc) + flags |= ON_BORDER + ini_dir = dir + + update_nearby_tiles() + update_nearby_icons() + update_icon() + +/obj/structure/window/projectile_check() + return PROJREACT_WINDOWS + +/obj/structure/window/examine(mob/user) + + ..() + if(!anchored) to_chat(user, "It appears to be completely loose and movable.") - //switch most likely can't take inequalities, so here's that if block - if(health >= initial(health)) //Sanity + //switch most likely can't take inequalities, so here's that if block + if(health >= initial(health)) //Sanity to_chat(user, "It's in perfect shape, not even a scratch.") - else if(health >= 0.8*initial(health)) + else if(health >= 0.8*initial(health)) to_chat(user, "It has a few scratches and a small impact.") - else if(health >= 0.5*initial(health)) + else if(health >= 0.5*initial(health)) to_chat(user, "It has a few impacts and some cracks running from them.") - else if(health >= 0.2*initial(health)) + else if(health >= 0.2*initial(health)) to_chat(user, "It's covered in impact marks and most of the outer sheet is crackled.") - else + else to_chat(user, "It's completely crackled over multiple layers, it's a miracle it's even standing.") - if(reinforced) //Normal windows can be loose or not, reinforced windows are more complex - switch(d_state) - if(WINDOWSECURE) + if(reinforced) //Normal windows can be loose or not, reinforced windows are more complex + switch(d_state) + if(WINDOWSECURE) to_chat(user, "It is firmly secured.") - if(WINDOWUNSECUREFRAME) + if(WINDOWUNSECUREFRAME) to_chat(user, "It appears it was unfastened from its frame.") - if(WINDOWLOOSEFRAME) + if(WINDOWLOOSEFRAME) to_chat(user, "It appears to be loose from its frame.") - -//Allows us to quickly check if we should break the window, can handle not having an user -/obj/structure/window/proc/healthcheck(var/mob/M, var/sound = 1) - - - if(health <= 0) - if(M) //Did someone pass a mob ? If so, perform a pressure check - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff > 0) - message_admins("Window with pdiff [pdiff] at [formatJumpTo(loc)] destroyed by [M.real_name] ([formatPlayerPanel(M,M.ckey)])!") - log_admin("Window with pdiff [pdiff] at [loc] destroyed by [M.real_name] ([M.ckey])!") - Destroy(brokenup = 1) - else - if(sound) - playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) - if(!damage_overlay) - damage_overlay = new(src) - damage_overlay.icon = icon('icons/obj/structures.dmi') - damage_overlay.dir = src.dir - - overlays.Cut() - - if(health < initial(health)) - var/damage_fraction = Clamp(round((initial(health) - health) / initial(health) * 5) + 1, 1, 5) //gives a number, 1-5, based on damagedness - damage_overlay.icon_state = "[cracked_base][damage_fraction]" - overlays += damage_overlay - -/obj/structure/window/bullet_act(var/obj/item/projectile/Proj) - - health -= Proj.damage - ..() - healthcheck(Proj.firer) - return - -/obj/structure/window/proc/is_fulltile() - - - return 0 - -//This ex_act just removes health to be fully modular with "bomb-proof" windows -/obj/structure/window/ex_act(severity) - - switch(severity) - if(1.0) - health -= rand(100, 150) - healthcheck() - return - if(2.0) - health -= rand(20, 50) - healthcheck() - return - if(3.0) - health -= rand(5, 15) - healthcheck() - return - -/obj/structure/window/blob_act() - - health -= rand(30, 50) - healthcheck() - -/obj/structure/window/CheckExit(var/atom/movable/O, var/turf/target) - - if(istype(O) && O.checkpass(PASSGLASS)) - return 1 - if(get_dir(O.loc, target) == dir) - return !density - return 1 - -/obj/structure/window/CanPass(atom/movable/mover, turf/target, height = 0) - - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) - return !density - return 1 - -//Someone threw something at us, please advise -/obj/structure/window/hitby(AM as mob|obj) - - ..() - if(ismob(AM)) - var/mob/M = AM //Duh - health -= 10 //We estimate just above a slam but under a crush, since mobs can't carry a throwforce variable - healthcheck(M) - visible_message("\The [M] slams into \the [src].", \ - "You slam into \the [src].") - else if(isobj(AM)) - var/obj/item/I = AM - health -= I.throwforce - healthcheck() - visible_message("\The [I] slams into \the [src].") - -/obj/structure/window/attack_hand(mob/user as mob) - - if(M_HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) - user.visible_message("[user] smashes \the [src]!") - health -= 25 - healthcheck() - user.delayNextAttack(8) - - //Bang against the window - else if(usr.a_intent == I_HURT) - user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) - user.visible_message("[user] bangs against \the [src]!", \ - "You bang against \the [src]!", \ - "You hear banging.") - - //Knock against it - else - user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1) - user.visible_message("[user] knocks on \the [src].", \ - "You knock on \the [src].", \ - "You hear knocking.") - return - -/obj/structure/window/attack_paw(mob/user as mob) - - return attack_hand(user) - -/obj/structure/window/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime - - - user.delayNextAttack(10) - health -= damage - user.visible_message("\The [user] smashes into \the [src]!", \ - "You smash into \the [src]!") - healthcheck(user) - -/obj/structure/window/attack_alien(mob/user as mob) - - if(islarva(user)) - return - attack_generic(user, 15) - -/obj/structure/window/attack_animal(mob/user as mob) - - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) - return - attack_generic(M, M.melee_damage_upper) - -/obj/structure/window/attack_slime(mob/user as mob) - - if(!isslimeadult(user)) - return - attack_generic(user, rand(10, 15)) - -/obj/structure/window/attackby(obj/item/weapon/W as obj, mob/user as mob) - - if(istype(W, /obj/item/weapon/grab) && Adjacent(user)) - var/obj/item/weapon/grab/G = W - if(istype(G.affecting, /mob/living)) - var/mob/living/M = G.affecting - var/gstate = G.state - returnToPool(W) //Gotta delete it here because if window breaks, it won't get deleted - switch(gstate) - if(GRAB_PASSIVE) - M.apply_damage(5) //Meh, bit of pain, window is fine, just a shove - visible_message("\The [user] shoves \the [M] into \the [src]!", \ - "You shove \the [M] into \the [src]!") - if(GRAB_AGGRESSIVE) - M.apply_damage(10) //Nasty, but dazed and concussed at worst - health -= 5 - visible_message("\The [user] slams \the [M] into \the [src]!", \ - "You slam \the [M] into \the [src]!") - if(GRAB_NECK to GRAB_KILL) - M.Weaken(3) //Almost certainly shoved head or face-first, you're going to need a bit for the lights to come back on - M.apply_damage(20) //That got to fucking hurt, you were basically flung into a window, most likely a shattered one at that - health -= 20 //Window won't like that - visible_message("\The [user] crushes \the [M] into \the [src]!", \ - "You crush \the [M] into \the [src]!") - healthcheck(user) - M.attack_log += text("\[[time_stamp()]\] Has been window slammed by [user.name] ([user.ckey]) ([gstate]).") - user.attack_log += text("\[[time_stamp()]\] Window slammed [M.name] ([gstate]).") - msg_admin_attack("[user.name] ([user.ckey]) window slammed [M.name] ([M.ckey]) ([gstate]) (JMP)") - log_attack("[user.name] ([user.ckey]) window slammed [M.name] ([M.ckey]) ([gstate]) (JMP)") - return - - //Start construction and deconstruction, absolute priority over the other object interactions to avoid hitting the window - - if(reinforced) //Steps for all reinforced window types - - switch(d_state) - - if(WINDOWSECURE) //Reinforced, fully secured - - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - user.visible_message("[user] unfastens \the [src] from its frame.", \ - "You unfasten \the [src] from its frame.") - d_state = WINDOWUNSECUREFRAME - return - - if(WINDOWUNSECUREFRAME) - - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - user.visible_message("[user] fastens \the [src] to its frame.", \ - "You fasten \the [src] to its frame.") - d_state = WINDOWSECURE - return - - if(istype(W, /obj/item/weapon/crowbar)) - playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) - user.visible_message("[user] pries \the [src] from its frame.", \ - "You pry \the [src] from its frame.") - d_state = WINDOWLOOSEFRAME - return - - if(WINDOWLOOSEFRAME) - - if(istype(W, /obj/item/weapon/crowbar)) - playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) - user.visible_message("[user] pries \the [src] into its frame.", \ - "You pry \the [src] into its frame.") - d_state = WINDOWUNSECUREFRAME - return - - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - user.visible_message("[user] unfastens \the [src]'s frame from the floor.", \ - "You unfasten \the [src]'s frame from the floor.") - d_state = WINDOWLOOSE - anchored = 0 - update_nearby_tiles() //Needed if it's a full window, since unanchored windows don't link - update_nearby_icons() - update_icon() - //Perform pressure check since window no longer blocks air - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff > 0) - message_admins("Window with pdiff [pdiff] deanchored by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)]!") - log_admin("Window with pdiff [pdiff] deanchored by [user.real_name] ([user.ckey]) at [loc]!") - return - - if(WINDOWLOOSE) - - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - user.visible_message("[user] fastens \the [src]'s frame to the floor.", \ - "You fasten \the [src]'s frame to the floor.") - d_state = WINDOWLOOSEFRAME - anchored = 1 - update_nearby_tiles() //Ditto above, but in reverse - update_nearby_icons() - update_icon() - return - - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0)) - playsound(src, 'sound/items/Welder.ogg', 100, 1) - user.visible_message("[user] starts disassembling \the [src].", \ - "You start disassembling \the [src].") - if(do_after(user, src, 40) && d_state == WINDOWLOOSE) //Extra condition needed to avoid cheesing - playsound(src, 'sound/items/Welder.ogg', 100, 1) - user.visible_message("[user] disassembles \the [src].", \ - "You disassemble \the [src].") - getFromPool(sheettype, get_turf(src), sheetamount) - qdel(src) - return - else + +//Allows us to quickly check if we should break the window, can handle not having an user +/obj/structure/window/proc/healthcheck(var/mob/M, var/sound = 1) + + + if(health <= 0) + if(M) //Did someone pass a mob ? If so, perform a pressure check + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff > 0) + message_admins("Window with pdiff [pdiff] at [formatJumpTo(loc)] destroyed by [M.real_name] ([formatPlayerPanel(M,M.ckey)])!") + log_admin("Window with pdiff [pdiff] at [loc] destroyed by [M.real_name] ([M.ckey])!") + Destroy(brokenup = 1) + else + if(sound) + playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) + if(!damage_overlay) + damage_overlay = new(src) + damage_overlay.icon = icon('icons/obj/structures.dmi') + damage_overlay.dir = src.dir + + overlays.Cut() + + if(health < initial(health)) + var/damage_fraction = Clamp(round((initial(health) - health) / initial(health) * 5) + 1, 1, 5) //gives a number, 1-5, based on damagedness + damage_overlay.icon_state = "[cracked_base][damage_fraction]" + overlays += damage_overlay + +/obj/structure/window/bullet_act(var/obj/item/projectile/Proj) + + health -= Proj.damage + ..() + healthcheck(Proj.firer) + return + +/obj/structure/window/proc/is_fulltile() + + + return 0 + +//This ex_act just removes health to be fully modular with "bomb-proof" windows +/obj/structure/window/ex_act(severity) + + switch(severity) + if(1.0) + health -= rand(100, 150) + healthcheck() + return + if(2.0) + health -= rand(20, 50) + healthcheck() + return + if(3.0) + health -= rand(5, 15) + healthcheck() + return + +/obj/structure/window/blob_act() + + health -= rand(30, 50) + healthcheck() + +/obj/structure/window/CheckExit(var/atom/movable/O, var/turf/target) + + if(istype(O) && O.checkpass(PASSGLASS)) + return 1 + if(get_dir(O.loc, target) == dir) + return !density + return 1 + +/obj/structure/window/CanPass(atom/movable/mover, turf/target, height = 0) + + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) + return !density + return 1 + +//Someone threw something at us, please advise +/obj/structure/window/hitby(AM as mob|obj) + + ..() + if(ismob(AM)) + var/mob/M = AM //Duh + health -= 10 //We estimate just above a slam but under a crush, since mobs can't carry a throwforce variable + healthcheck(M) + visible_message("\The [M] slams into \the [src].", \ + "You slam into \the [src].") + else if(isobj(AM)) + var/obj/item/I = AM + health -= I.throwforce + healthcheck() + visible_message("\The [I] slams into \the [src].") + +/obj/structure/window/attack_hand(mob/user as mob) + + if(M_HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) + user.visible_message("[user] smashes \the [src]!") + health -= 25 + healthcheck() + user.delayNextAttack(8) + + //Bang against the window + else if(usr.a_intent == I_HURT) + user.delayNextAttack(10) + playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) + user.visible_message("[user] bangs against \the [src]!", \ + "You bang against \the [src]!", \ + "You hear banging.") + + //Knock against it + else + user.delayNextAttack(10) + playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1) + user.visible_message("[user] knocks on \the [src].", \ + "You knock on \the [src].", \ + "You hear knocking.") + return + +/obj/structure/window/attack_paw(mob/user as mob) + + return attack_hand(user) + +/obj/structure/window/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime + + + user.delayNextAttack(10) + health -= damage + user.visible_message("\The [user] smashes into \the [src]!", \ + "You smash into \the [src]!") + healthcheck(user) + +/obj/structure/window/attack_alien(mob/user as mob) + + if(islarva(user)) + return + attack_generic(user, 15) + +/obj/structure/window/attack_animal(mob/user as mob) + + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) + return + attack_generic(M, M.melee_damage_upper) + +/obj/structure/window/attack_slime(mob/user as mob) + + if(!isslimeadult(user)) + return + attack_generic(user, rand(10, 15)) + +/obj/structure/window/attackby(obj/item/weapon/W as obj, mob/user as mob) + + if(istype(W, /obj/item/weapon/grab) && Adjacent(user)) + var/obj/item/weapon/grab/G = W + if(istype(G.affecting, /mob/living)) + var/mob/living/M = G.affecting + var/gstate = G.state + returnToPool(W) //Gotta delete it here because if window breaks, it won't get deleted + switch(gstate) + if(GRAB_PASSIVE) + M.apply_damage(5) //Meh, bit of pain, window is fine, just a shove + visible_message("\The [user] shoves \the [M] into \the [src]!", \ + "You shove \the [M] into \the [src]!") + if(GRAB_AGGRESSIVE) + M.apply_damage(10) //Nasty, but dazed and concussed at worst + health -= 5 + visible_message("\The [user] slams \the [M] into \the [src]!", \ + "You slam \the [M] into \the [src]!") + if(GRAB_NECK to GRAB_KILL) + M.Weaken(3) //Almost certainly shoved head or face-first, you're going to need a bit for the lights to come back on + M.apply_damage(20) //That got to fucking hurt, you were basically flung into a window, most likely a shattered one at that + health -= 20 //Window won't like that + visible_message("\The [user] crushes \the [M] into \the [src]!", \ + "You crush \the [M] into \the [src]!") + healthcheck(user) + M.attack_log += text("\[[time_stamp()]\] Has been window slammed by [user.name] ([user.ckey]) ([gstate]).") + user.attack_log += text("\[[time_stamp()]\] Window slammed [M.name] ([gstate]).") + msg_admin_attack("[user.name] ([user.ckey]) window slammed [M.name] ([M.ckey]) ([gstate]) (JMP)") + log_attack("[user.name] ([user.ckey]) window slammed [M.name] ([M.ckey]) ([gstate]) (JMP)") + return + + //Start construction and deconstruction, absolute priority over the other object interactions to avoid hitting the window + + if(reinforced) //Steps for all reinforced window types + + switch(d_state) + + if(WINDOWSECURE) //Reinforced, fully secured + + if(istype(W, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + user.visible_message("[user] unfastens \the [src] from its frame.", \ + "You unfasten \the [src] from its frame.") + d_state = WINDOWUNSECUREFRAME + return + + if(WINDOWUNSECUREFRAME) + + if(istype(W, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + user.visible_message("[user] fastens \the [src] to its frame.", \ + "You fasten \the [src] to its frame.") + d_state = WINDOWSECURE + return + + if(istype(W, /obj/item/weapon/crowbar)) + playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) + user.visible_message("[user] pries \the [src] from its frame.", \ + "You pry \the [src] from its frame.") + d_state = WINDOWLOOSEFRAME + return + + if(WINDOWLOOSEFRAME) + + if(istype(W, /obj/item/weapon/crowbar)) + playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) + user.visible_message("[user] pries \the [src] into its frame.", \ + "You pry \the [src] into its frame.") + d_state = WINDOWUNSECUREFRAME + return + + if(istype(W, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + user.visible_message("[user] unfastens \the [src]'s frame from the floor.", \ + "You unfasten \the [src]'s frame from the floor.") + d_state = WINDOWLOOSE + anchored = 0 + update_nearby_tiles() //Needed if it's a full window, since unanchored windows don't link + update_nearby_icons() + update_icon() + //Perform pressure check since window no longer blocks air + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff > 0) + message_admins("Window with pdiff [pdiff] deanchored by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)]!") + log_admin("Window with pdiff [pdiff] deanchored by [user.real_name] ([user.ckey]) at [loc]!") + return + + if(WINDOWLOOSE) + + if(istype(W, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + user.visible_message("[user] fastens \the [src]'s frame to the floor.", \ + "You fasten \the [src]'s frame to the floor.") + d_state = WINDOWLOOSEFRAME + anchored = 1 + update_nearby_tiles() //Ditto above, but in reverse + update_nearby_icons() + update_icon() + return + + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0)) + playsound(src, 'sound/items/Welder.ogg', 100, 1) + user.visible_message("[user] starts disassembling \the [src].", \ + "You start disassembling \the [src].") + if(do_after(user, src, 40) && d_state == WINDOWLOOSE) //Extra condition needed to avoid cheesing + playsound(src, 'sound/items/Welder.ogg', 100, 1) + user.visible_message("[user] disassembles \the [src].", \ + "You disassemble \the [src].") + getFromPool(sheettype, get_turf(src), sheetamount) + qdel(src) + return + else to_chat(user, "You need more welding fuel to complete this task.") - return - - else if(!reinforced) //Normal window steps - - if(istype(W, /obj/item/weapon/screwdriver)) - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - user.visible_message("[user] [d_state ? "un":""]fastens \the [src].", \ - "You [d_state ? "un":""]fasten \the [src].") - d_state = !d_state - anchored = !anchored - update_nearby_tiles() //Ditto above - update_nearby_icons() - update_icon() - return - - if(istype(W, /obj/item/weapon/weldingtool) && !d_state) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0)) - playsound(src, 'sound/items/Welder.ogg', 100, 1) - user.visible_message("[user] starts disassembling \the [src].", \ - "You start disassembling \the [src].") - if(do_after(user, src, 40) && d_state == WINDOWLOOSE) //Ditto above - playsound(src, 'sound/items/Welder.ogg', 100, 1) - user.visible_message("[user] disassembles \the [src].", \ - "You disassemble \the [src].") - getFromPool(sheettype, get_turf(src), sheetamount) - Destroy() - return - else + return + + else if(!reinforced) //Normal window steps + + if(istype(W, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + user.visible_message("[user] [d_state ? "un":""]fastens \the [src].", \ + "You [d_state ? "un":""]fasten \the [src].") + d_state = !d_state + anchored = !anchored + update_nearby_tiles() //Ditto above + update_nearby_icons() + update_icon() + return + + if(istype(W, /obj/item/weapon/weldingtool) && !d_state) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0)) + playsound(src, 'sound/items/Welder.ogg', 100, 1) + user.visible_message("[user] starts disassembling \the [src].", \ + "You start disassembling \the [src].") + if(do_after(user, src, 40) && d_state == WINDOWLOOSE) //Ditto above + playsound(src, 'sound/items/Welder.ogg', 100, 1) + user.visible_message("[user] disassembles \the [src].", \ + "You disassemble \the [src].") + getFromPool(sheettype, get_turf(src), sheetamount) + Destroy() + return + else to_chat(user, "You need more welding fuel to complete this task.") - return - - if(W.damtype == BRUTE || W.damtype == BURN) - user.delayNextAttack(10) - health -= W.force - user.visible_message("\The [user] hits \the [src] with \the [W].", \ - "You hit \the [src] with \the [W].") - healthcheck(user) - return - else - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - ..() - - return - -/obj/structure/window/proc/can_be_reached(mob/user) - - - if(!is_fulltile()) - if(get_dir(user, src) & dir) - for(var/obj/O in loc) - if(!O.CanPass(user, user.loc, 1, 0)) - return 0 - return 1 - -/obj/structure/window/verb/rotate() - set name = "Rotate Window Counter-Clockwise" - set category = "Object" - set src in oview(1) - - if(anchored) + return + + if(W.damtype == BRUTE || W.damtype == BURN) + user.delayNextAttack(10) + health -= W.force + user.visible_message("\The [user] hits \the [src] with \the [W].", \ + "You hit \the [src] with \the [W].") + healthcheck(user) + return + else + playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) + ..() + + return + +/obj/structure/window/proc/can_be_reached(mob/user) + + + if(!is_fulltile()) + if(get_dir(user, src) & dir) + for(var/obj/O in loc) + if(!O.CanPass(user, user.loc, 1, 0)) + return 0 + return 1 + +/obj/structure/window/verb/rotate() + set name = "Rotate Window Counter-Clockwise" + set category = "Object" + set src in oview(1) + + if(anchored) to_chat(usr, "\The [src] is fastened to the floor, therefore you can't rotate it!") - return 0 - - update_nearby_tiles() //Compel updates before - dir = turn(dir, 90) - update_nearby_tiles() - ini_dir = dir - return - -/obj/structure/window/verb/revrotate() - set name = "Rotate Window Clockwise" - set category = "Object" - set src in oview(1) - - if(anchored) + return 0 + + update_nearby_tiles() //Compel updates before + dir = turn(dir, 90) + update_nearby_tiles() + ini_dir = dir + return + +/obj/structure/window/verb/revrotate() + set name = "Rotate Window Clockwise" + set category = "Object" + set src in oview(1) + + if(anchored) to_chat(usr, "\The [src] is fastened to the floor, therefore you can't rotate it!") - return 0 - - update_nearby_tiles() //Compel updates before - dir = turn(dir, 270) - update_nearby_tiles() - ini_dir = dir - return - -/obj/structure/window/Destroy(var/brokenup = 0) - - density = 0 //Sanity while we do the rest - update_nearby_tiles() - update_nearby_icons() - if(brokenup) //If the instruction we were sent clearly states we're breaking the window, not deleting it ! - if(loc) - playsound(get_turf(src), "shatter", 70, 1) - getFromPool(shardtype, loc, sheetamount) - if(reinforced) - getFromPool(/obj/item/stack/rods, loc, sheetamount) - ..() - -/obj/structure/window/Move() - - update_nearby_tiles() - ..() - dir = ini_dir - update_nearby_tiles() - -//This proc has to do with airgroups and atmos, it has nothing to do with smoothwindows, that's update_nearby_tiles(). -/obj/structure/window/proc/update_nearby_tiles(var/turf/T) - - - if(isnull(air_master)) - return 0 - - if(!T) - T = get_turf(src) - - if(isturf(T)) - air_master.mark_for_update(T) - - return 1 - -//This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc! -/obj/structure/window/proc/update_nearby_icons(var/turf/T) - - - if(!loc) - return 0 - if(!T) - T = get_turf(src) - - update_icon() - - for(var/direction in cardinal) - for(var/obj/structure/window/W in get_step(T,direction)) - W.update_icon() - -/obj/structure/window/forceMove(var/atom/A) - var/turf/T = loc - ..() - update_nearby_icons(T) - update_nearby_icons() - update_nearby_tiles(T) - update_nearby_tiles() - -/obj/structure/window/update_icon() - - return - -/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - - if(exposed_temperature > T0C + fire_temp_threshold) - health -= round(exposed_volume/fire_volume_mod) - healthcheck(sound = 0) - ..() - -/obj/structure/window/reinforced - name = "reinforced window" - desc = "A window with a rod matrice. It looks more solid than the average window." - icon_state = "rwindow" - sheettype = /obj/item/stack/sheet/glass/rglass - health = 40 - d_state = WINDOWSECURE - reinforced = 1 - penetration_dampening = 3 - -/obj/structure/window/plasma - - name = "plasma window" - desc = "A window made out of a plasma-silicate alloy. It looks insanely tough to break and burn through." - icon_state = "plasmawindow" - shardtype = /obj/item/weapon/shard/plasma - sheettype = /obj/item/stack/sheet/glass/plasmaglass - health = 120 - penetration_dampening = 5 - - fire_temp_threshold = 32000 - fire_volume_mod = 1000 - -/obj/structure/window/reinforced/plasma - - name = "reinforced plasma window" - desc = "A window made out of a plasma-silicate alloy and a rod matrice. It looks hopelessly tough to break and is most likely nigh fireproof." - icon_state = "plasmarwindow" - shardtype = /obj/item/weapon/shard/plasma - sheettype = /obj/item/stack/sheet/glass/plasmarglass - health = 160 - penetration_dampening = 7 - -/obj/structure/window/reinforced/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/structure/window/reinforced/tinted - - name = "tinted window" - desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque. Why not a wall ?" - icon_state = "twindow" - opacity = 1 - sheettype = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you - -/obj/structure/window/reinforced/tinted/frosted - - name = "frosted window" - desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque, and it's frosty. Why not an ice wall ?" - icon_state = "fwindow" - health = 30 - sheettype = /obj/item/stack/sheet/glass/rglass //Ditto above - -#undef WINDOWLOOSE -#undef WINDOWLOOSEFRAME -#undef WINDOWUNSECUREFRAME -#undef WINDOWSECURE + return 0 + + update_nearby_tiles() //Compel updates before + dir = turn(dir, 270) + update_nearby_tiles() + ini_dir = dir + return + +/obj/structure/window/Destroy(var/brokenup = 0) + + density = 0 //Sanity while we do the rest + update_nearby_tiles() + update_nearby_icons() + if(brokenup) //If the instruction we were sent clearly states we're breaking the window, not deleting it ! + if(loc) + playsound(get_turf(src), "shatter", 70, 1) + getFromPool(shardtype, loc, sheetamount) + if(reinforced) + getFromPool(/obj/item/stack/rods, loc, sheetamount) + ..() + +/obj/structure/window/Move() + + update_nearby_tiles() + ..() + dir = ini_dir + update_nearby_tiles() + +//This proc has to do with airgroups and atmos, it has nothing to do with smoothwindows, that's update_nearby_tiles(). +/obj/structure/window/proc/update_nearby_tiles(var/turf/T) + + + if(isnull(air_master)) + return 0 + + if(!T) + T = get_turf(src) + + if(isturf(T)) + air_master.mark_for_update(T) + + return 1 + +//This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc! +/obj/structure/window/proc/update_nearby_icons(var/turf/T) + + + if(!loc) + return 0 + if(!T) + T = get_turf(src) + + update_icon() + + for(var/direction in cardinal) + for(var/obj/structure/window/W in get_step(T,direction)) + W.update_icon() + +/obj/structure/window/forceMove(var/atom/A) + var/turf/T = loc + ..() + update_nearby_icons(T) + update_nearby_icons() + update_nearby_tiles(T) + update_nearby_tiles() + +/obj/structure/window/update_icon() + + return + +/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + + if(exposed_temperature > T0C + fire_temp_threshold) + health -= round(exposed_volume/fire_volume_mod) + healthcheck(sound = 0) + ..() + +/obj/structure/window/reinforced + name = "reinforced window" + desc = "A window with a rod matrice. It looks more solid than the average window." + icon_state = "rwindow" + sheettype = /obj/item/stack/sheet/glass/rglass + health = 40 + d_state = WINDOWSECURE + reinforced = 1 + penetration_dampening = 3 + +/obj/structure/window/plasma + + name = "plasma window" + desc = "A window made out of a plasma-silicate alloy. It looks insanely tough to break and burn through." + icon_state = "plasmawindow" + shardtype = /obj/item/weapon/shard/plasma + sheettype = /obj/item/stack/sheet/glass/plasmaglass + health = 120 + penetration_dampening = 5 + + fire_temp_threshold = 32000 + fire_volume_mod = 1000 + +/obj/structure/window/reinforced/plasma + + name = "reinforced plasma window" + desc = "A window made out of a plasma-silicate alloy and a rod matrice. It looks hopelessly tough to break and is most likely nigh fireproof." + icon_state = "plasmarwindow" + shardtype = /obj/item/weapon/shard/plasma + sheettype = /obj/item/stack/sheet/glass/plasmarglass + health = 160 + penetration_dampening = 7 + +/obj/structure/window/reinforced/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/structure/window/reinforced/tinted + + name = "tinted window" + desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque. Why not a wall ?" + icon_state = "twindow" + opacity = 1 + sheettype = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you + +/obj/structure/window/reinforced/tinted/frosted + + name = "frosted window" + desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque, and it's frosty. Why not an ice wall ?" + icon_state = "fwindow" + health = 30 + sheettype = /obj/item/stack/sheet/glass/rglass //Ditto above + +#undef WINDOWLOOSE +#undef WINDOWLOOSEFRAME +#undef WINDOWUNSECUREFRAME +#undef WINDOWSECURE diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index 3d7fe8e5540..aad4f22dd40 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -1,64 +1,64 @@ -/obj/structure/shuttle - name = "shuttle" - icon = 'icons/turf/shuttle.dmi' - -/obj/structure/shuttle/window - name = "shuttle window" - icon = 'icons/obj/podwindows.dmi' - icon_state = "1" - density = 1 - opacity = 0 - anchored = 1 - -/obj/structure/shuttle/window/shuttle_rotate(angle) //WOW - src.transform = turn(src.transform, angle) - -/obj/structure/shuttle/window/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(!height || air_group) - return 0 - else - return ..() - -/obj/structure/shuttle/engine - name = "engine" - density = 1 - anchored = 1.0 - -/obj/structure/shuttle/engine/heater - name = "heater" - icon_state = "heater" - -/obj/structure/shuttle/engine/heater/cultify() - new /obj/structure/cult/pylon(loc) - ..() - -/obj/structure/shuttle/engine/platform - name = "platform" - icon_state = "platform" - -/obj/structure/shuttle/engine/propulsion - name = "propulsion" - icon_state = "propulsion" - opacity = 1 - - -/obj/structure/shuttle/engine/propulsion/cultify() - var/turf/T = get_turf(src) - if(T) - T.ChangeTurf(/turf/simulated/wall/cult) - ..() - -/obj/structure/shuttle/engine/propulsion/burst - name = "burst" - -/obj/structure/shuttle/engine/propulsion/burst/left - name = "left" - icon_state = "burst_l" - -/obj/structure/shuttle/engine/propulsion/burst/right - name = "right" - icon_state = "burst_r" - -/obj/structure/shuttle/engine/router - name = "router" - icon_state = "router" +/obj/structure/shuttle + name = "shuttle" + icon = 'icons/turf/shuttle.dmi' + +/obj/structure/shuttle/window + name = "shuttle window" + icon = 'icons/obj/podwindows.dmi' + icon_state = "1" + density = 1 + opacity = 0 + anchored = 1 + +/obj/structure/shuttle/window/shuttle_rotate(angle) //WOW + src.transform = turn(src.transform, angle) + +/obj/structure/shuttle/window/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(!height || air_group) + return 0 + else + return ..() + +/obj/structure/shuttle/engine + name = "engine" + density = 1 + anchored = 1.0 + +/obj/structure/shuttle/engine/heater + name = "heater" + icon_state = "heater" + +/obj/structure/shuttle/engine/heater/cultify() + new /obj/structure/cult/pylon(loc) + ..() + +/obj/structure/shuttle/engine/platform + name = "platform" + icon_state = "platform" + +/obj/structure/shuttle/engine/propulsion + name = "propulsion" + icon_state = "propulsion" + opacity = 1 + + +/obj/structure/shuttle/engine/propulsion/cultify() + var/turf/T = get_turf(src) + if(T) + T.ChangeTurf(/turf/simulated/wall/cult) + ..() + +/obj/structure/shuttle/engine/propulsion/burst + name = "burst" + +/obj/structure/shuttle/engine/propulsion/burst/left + name = "left" + icon_state = "burst_l" + +/obj/structure/shuttle/engine/propulsion/burst/right + name = "right" + icon_state = "burst_r" + +/obj/structure/shuttle/engine/router + name = "router" + icon_state = "router" diff --git a/code/game/skincmd.dm b/code/game/skincmd.dm index fd9131538e4..f8aa4c4b74b 100644 --- a/code/game/skincmd.dm +++ b/code/game/skincmd.dm @@ -1,13 +1,13 @@ -/mob/var/skincmds = list() -/obj/proc/SkinCmd(mob/user as mob, var/data as text) - -/proc/SkinCmdRegister(var/mob/user, var/name as text, var/O as obj) - user.skincmds[name] = O - -/mob/verb/skincmd(data as text) - set hidden = 1 - - var/ref = copytext(data, 1, findtext(data, ";")) - if (src.skincmds[ref] != null) - var/obj/a = src.skincmds[ref] +/mob/var/skincmds = list() +/obj/proc/SkinCmd(mob/user as mob, var/data as text) + +/proc/SkinCmdRegister(var/mob/user, var/name as text, var/O as obj) + user.skincmds[name] = O + +/mob/verb/skincmd(data as text) + set hidden = 1 + + var/ref = copytext(data, 1, findtext(data, ";")) + if (src.skincmds[ref] != null) + var/obj/a = src.skincmds[ref] a.SkinCmd(src, copytext(data, findtext(data, ";") + 1)) \ No newline at end of file diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm index 4a829f3270c..940e537751a 100644 --- a/code/game/smoothwall.dm +++ b/code/game/smoothwall.dm @@ -1,124 +1,124 @@ -// OKAY I DON'T KNOW WHO THE FUCK ORIGINALLY CODED THIS BUT THEY ARE OFFICIALLY FIRED FOR BEING DRUNK AND STUPID -// FUCK YOU MYSTERY CODERS -// FOR THIS SHIT I'M GOING TO MAKE ALL MY COMMENTS IN CAPS - -/atom - var/canSmoothWith // TYPE PATHS I CAN SMOOTH WITH~~~~~ - -// MOVED INTO UTILITY FUNCTION FOR LESS DUPLICATED CODE. -/atom/proc/findSmoothingNeighbors() - // THIS IS A BITMAP BECAUSE NORTH/SOUTH/ETC ARE ALL BITFLAGS BECAUSE BYOND IS DUMB AND - // DOESN'T FUCKING MAKE SENSE, BUT IT WORKS TO OUR ADVANTAGE - var/junction = 0 - for(var/cdir in cardinal) - var/turf/T = get_step(src,cdir) - if(isSmoothableNeighbor(T)) - junction |= cdir - continue // NO NEED FOR FURTHER SEARCHING IN THIS TILE - for(var/atom/A in T) - if(isSmoothableNeighbor(A)) - junction |= cdir - break // NO NEED FOR FURTHER SEARCHING IN THIS TILE - - return junction - -/atom/proc/isSmoothableNeighbor(atom/A) - if(!A) - WARNING("[__FILE__]L[__LINE__]: atom/isSmoothableNeighbor given bad atom") - return 0 - return isInTypes(A, canSmoothWith) - -/turf/simulated/wall/isSmoothableNeighbor(atom/A) - if(!A) - WARNING("[__FILE__]L[__LINE__]: turf/isSmoothableNeighbor given bad atom") - return 0 - if(isInTypes(A, canSmoothWith)) - // COLON OPERATORS ARE TERRIBLE BUT I HAVE NO CHOICE - if(src.mineral == A:mineral) - return 1 - - return 0 - -/** - * WALL SMOOTHING SHIT - * - * IN /ATOM BECAUSE /TURFS ARE /ATOMS AND SO ARE /OBJ/STRUCTURE/FALSEWALLS - * THIS IS STUPID BUT IS FAIRLY ELEGANT FOR BYOND - * - * HOWEVER, INSTEAD OF MAKING ONE BIG GODDAMN MONOLITHIC PROC LIKE A FUCKING - * SHITTY FUNCTIONAL PROGRAMMER, WE WILL BE COOL AND MODERN AND USE INHERITANCE. - */ -/atom/proc/relativewall() - return // DOES JACK SHIT BY DEFAULT. OLD BEHAVIOR WAS TO SPAM LOOPS ANYWAY. - -/* - * SEE? NOW WE ONLY HAVE TO PROGRAM THIS SHIT INTO WHAT WE WANT TO SMOOTH - * INSTEAD OF BEING DUMB AND HAVING A BIG FUCKING IFTREE WITH TYPECHECKS - * MY GOD, WE COULD EVEN MOVE THE CODE TO BE WITH THE REST OF THE WALL'S CODE! - * HOW FUCKING INNOVATIVE. ISN'T INHERITANCE NICE? - * - * WE COULD STANDARDIZE THIS BUT EVERYONE'S A FUCKING SNOWFLAKE - */ -/turf/simulated/wall/relativewall() - var/junction=findSmoothingNeighbors() - icon_state = "[walltype][junction]" // WHY ISN'T THIS IN UPDATE_ICON OR SIMILAR - -// AND NOW WE HAVE TO YELL AT THE NEIGHBORS FOR BEING LOUD AND NOT PAINTING WITH HOA-APPROVED COLORS -/atom/proc/relativewall_neighbours(var/at=null) - if(!at) - at = get_turf(src) - // OPTIMIZE BY NOT CHECKING FOR NEIGHBORS IF WE DON'T FUCKING SMOOTH - if(canSmoothWith) - for(var/cdir in cardinal) - var/turf/T = get_step(src,cdir) - if(isSmoothableNeighbor(T)) - T.relativewall() - for(var/atom/A in T) - if(isSmoothableNeighbor(A)) - A.relativewall() - -/turf/simulated/wall/New() - ..() - - // SMOOTH US WITH OUR NEIGHBORS - relativewall() - - // WE NEED TO TELL ALL OUR FRIENDS ABOUT THIS SCANDAL - relativewall_neighbours() - -/turf/simulated/wall/Destroy() - - var/temploc = src.loc - - if(!del_suppress_resmoothing) - spawn(10) - relativewall_neighbours(at=temploc) - - // JESUS WHY - for(var/direction in cardinal) - for(var/obj/effect/glowshroom/shroom in get_step(src,direction)) - if(!shroom.floor) //shrooms drop to the floor - shroom.floor = 1 - shroom.icon_state = "glowshroomf" - shroom.pixel_x = 0 - shroom.pixel_y = 0 - - ..() - -// DE-HACK -/turf/simulated/wall/vault/relativewall() - return - -var/list/smoothable_unsims = list( - "riveted", - ) - -/turf/unsimulated/wall/New() - ..() - if(icon_state in smoothable_unsims) - relativewall() - relativewall_neighbours() - -/turf/unsimulated/wall/relativewall() - var/junction=findSmoothingNeighbors() - icon_state = "[walltype][junction]" +// OKAY I DON'T KNOW WHO THE FUCK ORIGINALLY CODED THIS BUT THEY ARE OFFICIALLY FIRED FOR BEING DRUNK AND STUPID +// FUCK YOU MYSTERY CODERS +// FOR THIS SHIT I'M GOING TO MAKE ALL MY COMMENTS IN CAPS + +/atom + var/canSmoothWith // TYPE PATHS I CAN SMOOTH WITH~~~~~ + +// MOVED INTO UTILITY FUNCTION FOR LESS DUPLICATED CODE. +/atom/proc/findSmoothingNeighbors() + // THIS IS A BITMAP BECAUSE NORTH/SOUTH/ETC ARE ALL BITFLAGS BECAUSE BYOND IS DUMB AND + // DOESN'T FUCKING MAKE SENSE, BUT IT WORKS TO OUR ADVANTAGE + var/junction = 0 + for(var/cdir in cardinal) + var/turf/T = get_step(src,cdir) + if(isSmoothableNeighbor(T)) + junction |= cdir + continue // NO NEED FOR FURTHER SEARCHING IN THIS TILE + for(var/atom/A in T) + if(isSmoothableNeighbor(A)) + junction |= cdir + break // NO NEED FOR FURTHER SEARCHING IN THIS TILE + + return junction + +/atom/proc/isSmoothableNeighbor(atom/A) + if(!A) + WARNING("[__FILE__]L[__LINE__]: atom/isSmoothableNeighbor given bad atom") + return 0 + return isInTypes(A, canSmoothWith) + +/turf/simulated/wall/isSmoothableNeighbor(atom/A) + if(!A) + WARNING("[__FILE__]L[__LINE__]: turf/isSmoothableNeighbor given bad atom") + return 0 + if(isInTypes(A, canSmoothWith)) + // COLON OPERATORS ARE TERRIBLE BUT I HAVE NO CHOICE + if(src.mineral == A:mineral) + return 1 + + return 0 + +/** + * WALL SMOOTHING SHIT + * + * IN /ATOM BECAUSE /TURFS ARE /ATOMS AND SO ARE /OBJ/STRUCTURE/FALSEWALLS + * THIS IS STUPID BUT IS FAIRLY ELEGANT FOR BYOND + * + * HOWEVER, INSTEAD OF MAKING ONE BIG GODDAMN MONOLITHIC PROC LIKE A FUCKING + * SHITTY FUNCTIONAL PROGRAMMER, WE WILL BE COOL AND MODERN AND USE INHERITANCE. + */ +/atom/proc/relativewall() + return // DOES JACK SHIT BY DEFAULT. OLD BEHAVIOR WAS TO SPAM LOOPS ANYWAY. + +/* + * SEE? NOW WE ONLY HAVE TO PROGRAM THIS SHIT INTO WHAT WE WANT TO SMOOTH + * INSTEAD OF BEING DUMB AND HAVING A BIG FUCKING IFTREE WITH TYPECHECKS + * MY GOD, WE COULD EVEN MOVE THE CODE TO BE WITH THE REST OF THE WALL'S CODE! + * HOW FUCKING INNOVATIVE. ISN'T INHERITANCE NICE? + * + * WE COULD STANDARDIZE THIS BUT EVERYONE'S A FUCKING SNOWFLAKE + */ +/turf/simulated/wall/relativewall() + var/junction=findSmoothingNeighbors() + icon_state = "[walltype][junction]" // WHY ISN'T THIS IN UPDATE_ICON OR SIMILAR + +// AND NOW WE HAVE TO YELL AT THE NEIGHBORS FOR BEING LOUD AND NOT PAINTING WITH HOA-APPROVED COLORS +/atom/proc/relativewall_neighbours(var/at=null) + if(!at) + at = get_turf(src) + // OPTIMIZE BY NOT CHECKING FOR NEIGHBORS IF WE DON'T FUCKING SMOOTH + if(canSmoothWith) + for(var/cdir in cardinal) + var/turf/T = get_step(src,cdir) + if(isSmoothableNeighbor(T)) + T.relativewall() + for(var/atom/A in T) + if(isSmoothableNeighbor(A)) + A.relativewall() + +/turf/simulated/wall/New() + ..() + + // SMOOTH US WITH OUR NEIGHBORS + relativewall() + + // WE NEED TO TELL ALL OUR FRIENDS ABOUT THIS SCANDAL + relativewall_neighbours() + +/turf/simulated/wall/Destroy() + + var/temploc = src.loc + + if(!del_suppress_resmoothing) + spawn(10) + relativewall_neighbours(at=temploc) + + // JESUS WHY + for(var/direction in cardinal) + for(var/obj/effect/glowshroom/shroom in get_step(src,direction)) + if(!shroom.floor) //shrooms drop to the floor + shroom.floor = 1 + shroom.icon_state = "glowshroomf" + shroom.pixel_x = 0 + shroom.pixel_y = 0 + + ..() + +// DE-HACK +/turf/simulated/wall/vault/relativewall() + return + +var/list/smoothable_unsims = list( + "riveted", + ) + +/turf/unsimulated/wall/New() + ..() + if(icon_state in smoothable_unsims) + relativewall() + relativewall_neighbours() + +/turf/unsimulated/wall/relativewall() + var/junction=findSmoothingNeighbors() + icon_state = "[walltype][junction]" diff --git a/code/game/sound.dm b/code/game/sound.dm index e9334687bb3..b1925cf5a72 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -1,157 +1,157 @@ -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','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg') -var/list/small_explosion_sound = list('sound/effects/Explosion_Small1.ogg','sound/effects/Explosion_Small2.ogg','sound/effects/Explosion_Small3.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/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') -var/list/gib_sound = list('sound/effects/gib1.ogg', 'sound/effects/gib2.ogg', 'sound/effects/gib3.ogg') -var/list/mommicomment_sound = list('sound/voice/mommi_comment1.ogg', 'sound/voice/mommi_comment2.ogg', 'sound/voice/mommi_comment3.ogg', 'sound/voice/mommi_comment5.ogg', 'sound/voice/mommi_comment6.ogg', 'sound/voice/mommi_comment7.ogg', 'sound/voice/mommi_comment8.ogg') -var/list/polaroid_sound = list('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg') -var/list/male_scream_sound = list('sound/misc/malescream1.ogg', 'sound/misc/malescream2.ogg', 'sound/misc/malescream3.ogg', 'sound/misc/malescream4.ogg', 'sound/misc/malescream5.ogg') -var/list/female_scream_sound = list('sound/misc/femalescream1.ogg', 'sound/misc/femalescream2.ogg', 'sound/misc/femalescream3.ogg', 'sound/misc/femalescream4.ogg', 'sound/misc/femalescream5.ogg') -var/list/lightning_sound = list('sound/effects/lightning/chainlightning1.ogg', 'sound/effects/lightning/chainlightning2.ogg', 'sound/effects/lightning/chainlightning3.ogg', 'sound/effects/lightning/chainlightning4.ogg', 'sound/effects/lightning/chainlightning5.ogg', 'sound/effects/lightning/chainlightning6.ogg', 'sound/effects/lightning/chainlightning7.ogg') - -//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') - -//gas_modified controls if a sound is affected by how much gas there is in the atmosphere of the source -//space sounds have no gas modification, for example. Though >space sounds -/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/gas_modified = 1, var/channel = 0) - var/turf/turf_source = get_turf(source) - - ASSERT(!isnull(turf_source)) - - var/frequency = get_rand_frequency() // Same frequency for everybody - -/* What's going on in this block? - If the proc isn't set to not be modified by air, the following steps occur: - - The atmospheric pressure of the turf where the sound is played is determined - - A calculation is made as to the fraction of one atmosphere that the pressure is at, in tenths e.g. 0.1, 0.3, 0.7, never exceeding 1 - - If the proc has extrarange, the fraction of this extrarange that applies is equal to that of the pressure of the tile - - If the proc has NO extrarange, the fraction of the 7 range is used, so a sound only trasmits to those in the screen at regular pressure - - This means that at low or 0 pressure, sound doesn't trasmit from the tile at all! How cool is that? -*/ - if(!extrarange) - extrarange = 0 - if(!vol) //don't do that - return - - if(gas_modified && turf_source && !turf_source.c_airblock(turf_source)) //if the sound is modified by air, and we are on an airflowing tile - var/atmosphere = 0 - var/datum/gas_mixture/current_air = turf_source.return_air() - if(current_air) - atmosphere = current_air.return_pressure() - else - atmosphere = 0 //no air - - //message_admins("We're starting off with [atmosphere], [extrarange], and [vol]") - var/atmos_modifier = round(atmosphere/ONE_ATMOSPHERE, 0.1) - var/total_range = world.view + extrarange //this must be positive. - total_range = min ( round( (total_range) * sqrt(atmos_modifier), 1 ), (total_range * 2) ) //upper range of twice the original range. Range technically falls off with the root of pressure (see Newtonian sound) - extrarange = total_range - world.view - vol = min( round( (vol) * atmos_modifier, 1 ), vol * 2) //upper range of twice the volume. Trust me, otherwise you get 10000 volume in a plasmafire - //message_admins("We've adjusted the sound of [source] at [turf_source.loc] to have a range of [7 + extrarange] and a volume of [vol]") - - var/Dist = world.view + extrarange - - // Looping through the player list has the added bonus of working for mobs inside containers - for (var/mob/player in player_list) - if(!player || !player.client) - continue - - var/turf/player_turf = get_turf(player) - - if (player_turf && turf_source && player_turf.z == turf_source.z) - if(get_dist(player_turf, turf_source) <= Dist) - player.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, gas_modified, channel) - -var/const/FALLOFF_SOUNDS = 1 -var/const/SURROUND_CAP = 7 - -#define MIN_SOUND_PRESSURE 2 //2 kPa of pressure required to at least hear sound -/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, gas_modified, var/channel = 0) - if(!src.client) - return - - if(ear_deaf > 0) - vol = vol / (1 + ear_deaf) - - if(gas_modified) - var/turf/current_turf = get_turf(src) - if(!current_turf) - return - - var/datum/gas_mixture/environment = current_turf.return_air() - var/atmosphere = 0 - if(environment) - atmosphere = environment.return_pressure() - - /// Local sound modifications /// - if(atmosphere < MIN_SOUND_PRESSURE) //no sound reception in space, boyos - vol = 0 - else - vol = min( vol * atmosphere / ONE_ATMOSPHERE, vol) //sound can't be amplified from low to high pressure, but can be reduced - /// end /// - - soundin = get_sfx(soundin) - - var/sound/S = sound(soundin, 0, 0, channel, vol) - - if (vary) - 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(Clamp(dx, -SURROUND_CAP, SURROUND_CAP), 1) - - var/dz = turf_source.y - T.y // Hearing from infront/behind - S.z = round(Clamp(dz, -SURROUND_CAP, SURROUND_CAP), 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) - if(istype(src)) - 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 ("explosion_small") soundin = pick(small_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 ("mechstep") soundin = pick(mechstep_sound) - if ("gib") soundin = pick(gib_sound) - if ("mommicomment") soundin = pick(mommicomment_sound) - if ("polaroid") soundin = pick(polaroid_sound) - if ("malescream") soundin = pick(male_scream_sound) - if ("femalescream") soundin = pick(female_scream_sound) - //if ("gunshot") soundin = pick(gun_sound) - return soundin +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','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg') +var/list/small_explosion_sound = list('sound/effects/Explosion_Small1.ogg','sound/effects/Explosion_Small2.ogg','sound/effects/Explosion_Small3.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/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') +var/list/gib_sound = list('sound/effects/gib1.ogg', 'sound/effects/gib2.ogg', 'sound/effects/gib3.ogg') +var/list/mommicomment_sound = list('sound/voice/mommi_comment1.ogg', 'sound/voice/mommi_comment2.ogg', 'sound/voice/mommi_comment3.ogg', 'sound/voice/mommi_comment5.ogg', 'sound/voice/mommi_comment6.ogg', 'sound/voice/mommi_comment7.ogg', 'sound/voice/mommi_comment8.ogg') +var/list/polaroid_sound = list('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg') +var/list/male_scream_sound = list('sound/misc/malescream1.ogg', 'sound/misc/malescream2.ogg', 'sound/misc/malescream3.ogg', 'sound/misc/malescream4.ogg', 'sound/misc/malescream5.ogg') +var/list/female_scream_sound = list('sound/misc/femalescream1.ogg', 'sound/misc/femalescream2.ogg', 'sound/misc/femalescream3.ogg', 'sound/misc/femalescream4.ogg', 'sound/misc/femalescream5.ogg') +var/list/lightning_sound = list('sound/effects/lightning/chainlightning1.ogg', 'sound/effects/lightning/chainlightning2.ogg', 'sound/effects/lightning/chainlightning3.ogg', 'sound/effects/lightning/chainlightning4.ogg', 'sound/effects/lightning/chainlightning5.ogg', 'sound/effects/lightning/chainlightning6.ogg', 'sound/effects/lightning/chainlightning7.ogg') + +//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') + +//gas_modified controls if a sound is affected by how much gas there is in the atmosphere of the source +//space sounds have no gas modification, for example. Though >space sounds +/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/gas_modified = 1, var/channel = 0) + var/turf/turf_source = get_turf(source) + + ASSERT(!isnull(turf_source)) + + var/frequency = get_rand_frequency() // Same frequency for everybody + +/* What's going on in this block? + If the proc isn't set to not be modified by air, the following steps occur: + - The atmospheric pressure of the turf where the sound is played is determined + - A calculation is made as to the fraction of one atmosphere that the pressure is at, in tenths e.g. 0.1, 0.3, 0.7, never exceeding 1 + - If the proc has extrarange, the fraction of this extrarange that applies is equal to that of the pressure of the tile + - If the proc has NO extrarange, the fraction of the 7 range is used, so a sound only trasmits to those in the screen at regular pressure + - This means that at low or 0 pressure, sound doesn't trasmit from the tile at all! How cool is that? +*/ + if(!extrarange) + extrarange = 0 + if(!vol) //don't do that + return + + if(gas_modified && turf_source && !turf_source.c_airblock(turf_source)) //if the sound is modified by air, and we are on an airflowing tile + var/atmosphere = 0 + var/datum/gas_mixture/current_air = turf_source.return_air() + if(current_air) + atmosphere = current_air.return_pressure() + else + atmosphere = 0 //no air + + //message_admins("We're starting off with [atmosphere], [extrarange], and [vol]") + var/atmos_modifier = round(atmosphere/ONE_ATMOSPHERE, 0.1) + var/total_range = world.view + extrarange //this must be positive. + total_range = min ( round( (total_range) * sqrt(atmos_modifier), 1 ), (total_range * 2) ) //upper range of twice the original range. Range technically falls off with the root of pressure (see Newtonian sound) + extrarange = total_range - world.view + vol = min( round( (vol) * atmos_modifier, 1 ), vol * 2) //upper range of twice the volume. Trust me, otherwise you get 10000 volume in a plasmafire + //message_admins("We've adjusted the sound of [source] at [turf_source.loc] to have a range of [7 + extrarange] and a volume of [vol]") + + var/Dist = world.view + extrarange + + // Looping through the player list has the added bonus of working for mobs inside containers + for (var/mob/player in player_list) + if(!player || !player.client) + continue + + var/turf/player_turf = get_turf(player) + + if (player_turf && turf_source && player_turf.z == turf_source.z) + if(get_dist(player_turf, turf_source) <= Dist) + player.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, gas_modified, channel) + +var/const/FALLOFF_SOUNDS = 1 +var/const/SURROUND_CAP = 7 + +#define MIN_SOUND_PRESSURE 2 //2 kPa of pressure required to at least hear sound +/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, gas_modified, var/channel = 0) + if(!src.client) + return + + if(ear_deaf > 0) + vol = vol / (1 + ear_deaf) + + if(gas_modified) + var/turf/current_turf = get_turf(src) + if(!current_turf) + return + + var/datum/gas_mixture/environment = current_turf.return_air() + var/atmosphere = 0 + if(environment) + atmosphere = environment.return_pressure() + + /// Local sound modifications /// + if(atmosphere < MIN_SOUND_PRESSURE) //no sound reception in space, boyos + vol = 0 + else + vol = min( vol * atmosphere / ONE_ATMOSPHERE, vol) //sound can't be amplified from low to high pressure, but can be reduced + /// end /// + + soundin = get_sfx(soundin) + + var/sound/S = sound(soundin, 0, 0, channel, vol) + + if (vary) + 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(Clamp(dx, -SURROUND_CAP, SURROUND_CAP), 1) + + var/dz = turf_source.y - T.y // Hearing from infront/behind + S.z = round(Clamp(dz, -SURROUND_CAP, SURROUND_CAP), 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) + if(istype(src)) + 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 ("explosion_small") soundin = pick(small_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 ("mechstep") soundin = pick(mechstep_sound) + if ("gib") soundin = pick(gib_sound) + if ("mommicomment") soundin = pick(mommicomment_sound) + if ("polaroid") soundin = pick(polaroid_sound) + if ("malescream") soundin = pick(male_scream_sound) + if ("femalescream") soundin = pick(female_scream_sound) + //if ("gunshot") soundin = pick(gun_sound) + return soundin diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 6b73a192f35..6648680e1ec 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -1,841 +1,841 @@ -//Config stuff -#define SUPPLY_DOCKZ 2 //Z-level of the Dock. -#define SUPPLY_STATIONZ 1 //Z-level of the Station. - -#define SUPPLY_TAX 10 // Credits to charge per order. -var/datum/controller/supply_shuttle/supply_shuttle = new - -var/list/mechtoys = list( - /obj/item/toy/prize/ripley, - /obj/item/toy/prize/fireripley, - /obj/item/toy/prize/deathripley, - /obj/item/toy/prize/gygax, - /obj/item/toy/prize/durand, - /obj/item/toy/prize/honk, - /obj/item/toy/prize/marauder, - /obj/item/toy/prize/seraph, - /obj/item/toy/prize/mauler, - /obj/item/toy/prize/odysseus, - /obj/item/toy/prize/phazon -) -//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 can't get past those. No way." - icon = 'icons/obj/stationobjs.dmi' //Change this. - icon_state = "plasticflaps" - density = 0 - anchored = 1 - layer = 4 - explosion_resistance = 5 - var/airtight = 0 - -/obj/structure/plasticflaps/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/weapon/crowbar) && anchored == 1) - if(airtight == 0) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - else - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - user.visible_message("[user] [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.", "You [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.") - airtight = !airtight - name = "\improper [airtight? "Airtight p" : "P"]lastic flaps" - desc = "[airtight? "Heavy duty, airtight, plastic flaps." : "I definitely can't get past those. No way."]" - return 1 - if(istype(I, /obj/item/weapon/wrench) && airtight != 1) - if(anchored == 0) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - else - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - user.visible_message("[user] [anchored? "loosens" : "tightens"] the flap from its anchoring.", "You [anchored? "loosen" : "tighten"] the flap from its anchoring.") - anchored = !anchored - return 1 - else if (iswelder(I) && anchored == 0) - var/obj/item/weapon/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - new /obj/item/stack/sheet/mineral/plastic (src.loc,10) - qdel(src) - return - return ..() - -/obj/structure/plasticflaps/examine(mob/user as mob) - ..() - to_chat(user, "It appears to be [anchored? "anchored to" : "unachored from"] the floor, [airtight? "and it seems to be airtight as well." : "but it does not seem to be airtight."]") - -/obj/structure/plasticflaps/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return prob(60) - - var/obj/structure/bed/B = mover - if (istype(mover, /obj/structure/bed) && B.locked_atoms.len)//if it's a bed/chair and someone is locked_to, it will not pass - return 0 - - else if(isliving(mover)) // You Shall Not Pass! - var/mob/living/M = mover - 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. - return 0 - if(!istype(mover)) // Aircheck! - return !airtight - return 1 - -/obj/structure/plasticflaps/ex_act(severity) - switch(severity) - if (1) - qdel(src) - if (2) - if (prob(50)) - qdel(src) - if (3) - if (prob(5)) - qdel(src) - -/obj/structure/plasticflaps/mining - name = "\improper Airtight plastic flaps" - desc = "Heavy duty, airtight, plastic flaps." - airtight = 1 - -/obj/structure/plasticflaps/cultify() - new /obj/structure/grille/cult(get_turf(src)) - ..() - -/obj/machinery/computer/supplycomp - name = "Supply shuttle console" - icon = 'icons/obj/computer.dmi' - icon_state = "supply" - req_access = list(access_cargo) - circuit = "/obj/item/weapon/circuitboard/supplycomp" - var/temp = null - var/reqtime = 0 //Cooldown for requisitions - Quarxink - var/hacked = 0 - var/can_order_contraband = 0 - var/last_viewed_group = "categories" - var/datum/money_account/current_acct - - light_color = LIGHT_COLOR_BROWN - -/obj/machinery/computer/ordercomp - name = "Supply ordering console" - icon = 'icons/obj/computer.dmi' - icon_state = "request" - circuit = "/obj/item/weapon/circuitboard/ordercomp" - var/temp = null - var/reqtime = 0 //Cooldown for requisitions - Quarxink - var/last_viewed_group = "categories" - var/datum/money_account/current_acct - - light_color = LIGHT_COLOR_BROWN - -/* -/obj/effect/marker/supplymarker - icon_state = "X" - icon = 'icons/misc/mark.dmi' - name = "X" - invisibility = 101 - anchored = 1 - opacity = 0 -*/ - -/datum/supply_order - var/ordernum - var/datum/supply_packs/object = null - var/datum/money_account/account = null - var/orderedby = null - var/comment = null - -/datum/controller/supply_shuttle - processing = 1 - processing_interval = 300 - //supply points have been replaced with MONEY MONEY MONEY - N3X - var/credits_per_slip = 2 - var/credits_per_crate = 5 - //var/credits_per_plasma = 0.5 // 2 plasma for 1 point - //control - var/ordernum - var/list/centcomm_orders = list() - var/list/shoppinglist = list() - var/list/requestlist = list() - var/list/supply_packs = list() - //shuttle movement - var/at_station = 0 - var/movetime = 1200 - var/moving = 0 - var/eta_timeofday - var/eta - var/datum/materials/materials_list = new - -/datum/controller/supply_shuttle/New() - ordernum = rand(1,9000) - - //Supply shuttle ticker - handles supply point regenertion and shuttle travelling between centcomm and the station -/datum/controller/supply_shuttle/proc/process() - for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs)) - var/datum/supply_packs/P = new typepath() - supply_packs[P.name] = P - - spawn(0) - //set background = 1 - while(1) - if(processing) - iteration++ - - if(moving == 1) - var/ticksleft = (eta_timeofday - world.timeofday) - if(ticksleft > 0) - eta = round(ticksleft/600,1) - else - eta = 0 - send() - - - sleep(processing_interval) - -/datum/controller/supply_shuttle/proc/send() - - var/obj/structure/docking_port/destination - - if(!at_station) //not at station - destination = cargo_shuttle.dock_station - - at_station = 1 - - if(!destination) - message_admins("WARNING: Cargo shuttle unable to find the station!") - warning("Cargo shuttle can't find centcomm") - else //at station - destination = cargo_shuttle.dock_centcom - - at_station = 0 - - if(!destination) - message_admins("WARNING: Cargo shuttle unable to find centcomm!") - warning("Cargo shuttle can't find centcomm") - - cargo_shuttle.move_to_dock(destination) - moving = 0 - - //Check whether the shuttle is allowed to move -/datum/controller/supply_shuttle/proc/can_move() - if(moving) return 0 - - if(forbidden_atoms_check(cargo_shuttle.linked_area)) - return 0 - - return 1 - -/datum/controller/supply_shuttle/proc/SellObjToOrders(var/atom/A,var/in_crate) - - - // Per-unit orders run last so they don't steal shit. - var/list/deferred_order_checks=list() - var/order_idx=0 - for(var/datum/centcomm_order/O in centcomm_orders) - order_idx++ - if(istype(O,/datum/centcomm_order/per_unit)) - deferred_order_checks += order_idx - if(O.CheckShuttleObject(A,in_crate)) - return - for(var/oid in deferred_order_checks) - var/datum/centcomm_order/O = centcomm_orders[oid] - if(O.CheckShuttleObject(A,in_crate)) - return - //Sellin - -/datum/controller/supply_shuttle/proc/sell() - - var/area/shuttle = cargo_shuttle.linked_area - if(!shuttle) return - - var/datum/money_account/cargo_acct = department_accounts["Cargo"] - - for(var/atom/movable/MA in shuttle) - if(MA.anchored) continue - - if(istype(MA, /obj/item/stack/sheet/mineral/plasma)) - var/obj/item/stack/sheet/mineral/plasma/P = MA - if(P.redeemed) continue - var/datum/material/mat = materials_list.getMaterial(P.sheettype) - cargo_acct.money += (mat.value * 2) * P.amount // Central Command pays double for plasma they receive that hasn't been redeemed already. - - // Must be in a crate! - else if(istype(MA,/obj/structure/closet/crate)) - cargo_acct.money += credits_per_crate - var/find_slip = 1 - - for(var/atom/A in MA) - if(istype(A, /obj/item/stack/sheet/mineral/plasma)) - var/obj/item/stack/sheet/mineral/plasma/P = A - if(P.redeemed) continue - var/datum/material/mat = materials_list.getMaterial(P.sheettype) - cargo_acct.money += (mat.value * 2) * P.amount // Central Command pays double for plasma they receive that hasn't been redeemed already. - continue - if(find_slip && istype(A,/obj/item/weapon/paper/manifest)) - var/obj/item/weapon/paper/slip = A - if(slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense - cargo_acct.money += credits_per_slip - find_slip = 0 - continue - - SellObjToOrders(A,0) - - // Delete it. (Fixes github #473) - if(A) qdel(A) - else - SellObjToOrders(MA,1) - - // PAY UP BITCHES - for(var/datum/centcomm_order/O in centcomm_orders) - if(O.CheckFulfilled()) - O.Pay() - centcomm_orders -= O -// to_chat(world, "deleting [MA]/[MA.type] it was [!MA.anchored ? "not ": ""] anchored") - qdel(MA) - - //Buyin -/datum/controller/supply_shuttle/proc/buy() - if(!shoppinglist.len) return - - var/area/shuttle = cargo_shuttle.linked_area - if(!shuttle) return - - var/list/clear_turfs = list() - - for(var/turf/T in shuttle) - if(T.density) continue - var/contcount - for(var/atom/A in T.contents) - if(islightingoverlay(A)) - continue - contcount++ - if(contcount) - continue - clear_turfs += T - - for(var/S in shoppinglist) - if(!clear_turfs.len) break - var/i = rand(1,clear_turfs.len) - var/turf/pickedloc = clear_turfs[i] - clear_turfs.Cut(i,i+1) - - var/datum/supply_order/SO = S - var/datum/supply_packs/SP = SO.object - - var/atom/A = new SP.containertype(pickedloc) - A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]" - - //supply manifest generation begin - - var/obj/item/weapon/paper/manifest/slip = new /obj/item/weapon/paper/manifest(A) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:298: slip.info = "

    [command_name()] Shipping Manifest



    " - slip.name = "Shipping Manifest for [SO.orderedby]'s Order" - slip.info = {"

    [command_name()] Shipping Manifest for [SO.orderedby]'s Order



    - Order #[SO.ordernum]
    - Destination: [station_name]
    - [supply_shuttle.shoppinglist.len] PACKAGES IN THIS SHIPMENT
    - CONTENTS:
      "} - // END AUTOFIX - //spawn the stuff, finish generating the manifest while you're at it - if(SP.access) - A:req_access = list() - A:req_access += text2num(SP.access) - - var/list/contains - if(istype(SP,/datum/supply_packs/randomised)) - var/datum/supply_packs/randomised/SPR = SP - contains = list() - if(SPR.contains.len) - for(var/j=1,j<=SPR.num_contained,j++) - contains += pick(SPR.contains) - else - contains = SP.contains - - for(var/typepath in contains) - if(!typepath) continue - var/atom/B2 = new typepath(A) - if(SP.amount && B2:amount) B2:amount = SP.amount - slip.info += "
    • [B2.name]
    • " //add the item to the manifest - - //manifest finalisation - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:326: slip.info += "

    " - slip.info += {"
    - CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
    "} - // END AUTOFIX - if (SP.contraband) slip.loc = null //we are out of blanks for Form #44-D Ordering Illicit Drugs. - - supply_shuttle.shoppinglist.len = 0 - return - -/datum/controller/supply_shuttle/proc/forbidden_atoms_check(atom/A) - var/contents = get_contents_in_object(A) - - if (locate(/mob/living) in contents) - . = TRUE - else if (locate(/obj/item/weapon/disk/nuclear) in contents) - . = TRUE - else if (locate(/obj/machinery/nuclearbomb) in contents) - . = TRUE - else if (locate(/obj/item/beacon) in contents) - . = TRUE - else if (locate(/obj/effect/portal) in contents)//you crafty fuckers - . = TRUE - else - . = FALSE - -/obj/item/weapon/paper/manifest - name = "Supply Manifest" - - -/obj/machinery/computer/ordercomp/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/computer/ordercomp/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/supplycomp/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return attack_hand(user) - -/obj/machinery/computer/supplycomp/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/ordercomp/attack_hand(var/mob/user as mob) - if(..()) - return - current_acct = user.get_worn_id_account() - user.set_machine(src) - var/dat - if(temp) - dat = temp - else - dat += {"
    Supply shuttle
    - Location: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Dock"]
    -
    Bank account credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    -
    \nRequest items

    - View approved orders

    - View requests

    - Close"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/ordercomp/Topic(href, href_list) - if(..()) - return - - if( isturf(loc) && (in_range(src, usr) || istype(usr, /mob/living/silicon)) ) - usr.set_machine(src) - - if(href_list["order"]) - if(href_list["order"] == "categories") - //all_supply_groups - //Request what? - last_viewed_group = "categories" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:383: temp = "Supply points: [supply_shuttle.points]
    " - temp = {"Bank account credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    - Main Menu


    - Select a category

    "} - // END AUTOFIX - for(var/supply_group_name in all_supply_groups ) - temp += "[supply_group_name]
    " - else - last_viewed_group = href_list["order"] - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:390: temp = "Supply points: [supply_shuttle.points]
    " - temp = {"Bank account credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    - Back to all categories


    - Request from: [last_viewed_group]

    "} - // END AUTOFIX - for(var/supply_name in supply_shuttle.supply_packs ) - var/datum/supply_packs/N = supply_shuttle.supply_packs[supply_name] - if(N.hidden || N.contraband || N.group != last_viewed_group) continue //Have to send the type instead of a reference to - temp += "[supply_name] Cost: $[num2septext(N.cost)]
    " //the obj because it would get caught by the garbage - - else if (href_list["doorder"]) - if(world.time < reqtime) - for(var/mob/V in hearers(src)) - V.show_message("[src]'s monitor flashes, \"[world.time - reqtime] seconds remaining until another requisition form may be printed.\"") - return - - //Find the correct supply_pack datum - var/datum/supply_packs/P = supply_shuttle.supply_packs[href_list["doorder"]] - if(!istype(P)) return - - var/timeout = world.time + 600 - var/reason = copytext(sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text),1,MAX_MESSAGE_LEN) - if(world.time > timeout) return - if(!reason) return - - var/idname = "*None Provided*" - var/idrank = "*None Provided*" - var/datum/money_account/account - if(ishuman(usr)) - var/obj/item/weapon/card/id/I = usr.get_id_card() - if(I) - idname = I.registered_name - idrank = I.GetJobName() - account = get_card_account(I) - else - to_chat(usr, "Please wear an ID with an associated bank account.") - return - to_chat(usr, "\icon[src]Your request has been saved. The transaction will be performed to your bank account when it has been accepted by cargo staff.") - if(account && (account.money < P.cost)) - to_chat(usr, "\icon[src]Your bank account doesn't have enough funds to order this pack. Your request will be on hold until you provide your bank account with the necessary funds.") - else if(issilicon(usr)) - idname = usr.real_name - account = station_account - - supply_shuttle.ordernum++ - var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc) - reqform.name = "[P.name] Requisition Form - [idname], [idrank]" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:425: reqform.info += "

    [station_name] Supply Requisition Form


    " - reqform.info += {"

    [station_name] Supply Requisition Form


    - INDEX: #[supply_shuttle.ordernum]
    - REQUESTED BY: [idname]
    - RANK: [idrank]
    - REASON: [reason]
    - SUPPLY CRATE TYPE: [P.name]
    - ACCESS RESTRICTION: [replacetext(get_access_desc(P.access))]
    - CONTENTS:
    "} - // END AUTOFIX - reqform.info += P.manifest - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:434: reqform.info += "
    " - reqform.info += {"
    - STAMP BELOW TO APPROVE THIS REQUISITION:
    "} - // END AUTOFIX - reqform.update_icon() //Fix for appearing blank when printed. - reqtime = (world.time + 5) % 1e5 - - //make our supply_order datum - var/datum/supply_order/O = new /datum/supply_order() - O.ordernum = supply_shuttle.ordernum - O.object = P - O.orderedby = idname - O.account = account - supply_shuttle.requestlist += O - stat_collection.crates_ordered++ - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:447: temp = "Thanks for your request. The cargo team will process it as soon as possible.
    " - temp = {"Thanks for your request. The cargo team will process it as soon as possible.
    -
    Back Main Menu"} - // END AUTOFIX - else if (href_list["vieworders"]) - temp = "Current approved orders:

    " - for(var/S in supply_shuttle.shoppinglist) - var/datum/supply_order/SO = S - temp += "[SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    " - temp += "
    OK" - - else if (href_list["viewrequests"]) - temp = "Current requests:

    " - for(var/S in supply_shuttle.requestlist) - var/datum/supply_order/SO = S - temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby]
    " - temp += "
    OK" - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/supplycomp/attack_hand(var/mob/user as mob) - if(!allowed(user)) - to_chat(user, "Access Denied.") - return - - if(..()) - return - - current_acct = user.get_worn_id_account() - - user.set_machine(src) - post_signal("supply") - - var/dat - if (temp) - dat = temp - else - dat += {"
    Supply shuttle
    - \nLocation: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Away"]
    -
    \nAvailable Credits: [current_acct ? current_acct.fmtBalance() : "N/A"]
    \n
    - [supply_shuttle.moving ? "\n*Must be away to order items*
    \n
    ":supply_shuttle.at_station ? "\n*Must be away to order items*
    \n
    ":"\nOrder items
    \n
    "] - [supply_shuttle.moving ? "\n*Shuttle already called*
    \n
    ":supply_shuttle.at_station ? "\nSend away
    \n
    ":"\nSend to station
    \n
    "] - \nView requests
    \n
    - \nView orders
    \n
    - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/supplycomp/attackby(I as obj, user as mob) - if(istype(I,/obj/item/weapon/card/emag) && !hacked) - to_chat(user, "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, src, 20)) - if (stat & BROKEN) - to_chat(user, "The broken glass falls out.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc ) - getFromPool(/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 - qdel(src) - else - to_chat(user, "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 - qdel(src) - else - return ..() - -/obj/machinery/computer/supplycomp/Topic(href, href_list) - - if(!supply_shuttle) - world.log << "## ERROR: Eek. The supply_shuttle controller datum is missing somehow." - return - if(..()) - return 1 - //Calling the shuttle - if(href_list["send"]) - if(!supply_shuttle.can_move()) - temp = "For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.

    OK" - else if(supply_shuttle.at_station) - supply_shuttle.moving = -1 - supply_shuttle.sell() - supply_shuttle.send() - temp = "The supply shuttle has departed.

    OK" - else - supply_shuttle.moving = 1 - supply_shuttle.buy() - supply_shuttle.eta_timeofday = (world.timeofday + supply_shuttle.movetime) % 864000 - temp = "The supply shuttle has been called and will arrive in [round(supply_shuttle.movetime/600,1)] minutes.

    OK" - post_signal("supply") - else if (href_list["order"]) - if(supply_shuttle.moving) return - if(href_list["order"] == "categories") - //all_supply_groups - //Request what? - last_viewed_group = "categories" - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:567: temp = "Supply points: [supply_shuttle.points]
    " - temp = {"Available credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    - Main Menu


    - Select a category

    "} - // END AUTOFIX - for(var/supply_group_name in all_supply_groups ) - temp += "[supply_group_name]
    " - else - last_viewed_group = href_list["order"] - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:574: temp = "Supply points: [supply_shuttle.points]
    " - temp = {"Available credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    - Back to all categories


    - Request from: [last_viewed_group]

    "} - // END AUTOFIX - for(var/supply_name in supply_shuttle.supply_packs ) - var/datum/supply_packs/N = supply_shuttle.supply_packs[supply_name] - if((N.hidden && !hacked) || (N.contraband && !can_order_contraband) || N.group != last_viewed_group) continue //Have to send the type instead of a reference to - temp += "[supply_name] Cost: [N.cost]
    " //the obj because it would get caught by the garbage - /*temp = "Supply points: [supply_shuttle.points]


    Request what?

    " - for(var/supply_name in supply_shuttle.supply_packs ) - var/datum/supply_packs/N = supply_shuttle.supply_packs[supply_name] - if(N.hidden && !hacked) continue - if(N.contraband && !can_order_contraband) continue - temp += "[supply_name] Cost: [N.cost]
    " //the obj because it would get caught by the garbage - temp += "
    OK"*/ - else if (href_list["doorder"]) - if(world.time < reqtime) - for(var/mob/V in hearers(src)) - V.show_message("[src]'s monitor flashes, \"[world.time - reqtime] seconds remaining until another requisition form may be printed.\"") - return - //Find the correct supply_pack datum - var/datum/supply_packs/P = supply_shuttle.supply_packs[href_list["doorder"]] - if(!istype(P)) return - var/timeout = world.time + 600 - var/reason = copytext(sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text),1,MAX_MESSAGE_LEN) - if(world.time > timeout) return - if(!reason) return - var/idname = "*None Provided*" - var/idrank = "*None Provided*" - var/datum/money_account/account - if(ishuman(usr)) - var/obj/item/weapon/card/id/I = usr.get_id_card() - if(I) - idname = I.registered_name - idrank = I.GetJobName() - account = get_card_account(I) - else - to_chat(usr, "\icon[src]Please wear an ID with an associated bank account.") - return - to_chat(usr, "\icon[src]Your request has been saved. The transaction will be performed to your bank account when it has been accepted by cargo staff.") - if(account && (account.money < P.cost)) - to_chat(usr, "\icon[src]Your bank account doesn't have enough funds to order this pack. Your request will be on hold until you provide your bank account with the necessary funds.") - else if(issilicon(usr)) - idname = usr.real_name - account = station_account - supply_shuttle.ordernum++ - var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc) - reqform.name = "[P.name] Requisition Form - [idname], [idrank]" - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:618: reqform.info += "

    [station_name] Supply Requisition Form


    " - reqform.info += {"

    [station_name] Supply Requisition Form


    - INDEX: #[supply_shuttle.ordernum]
    - REQUESTED BY: [idname]
    - RANK: [idrank]
    - REASON: [reason]
    - SUPPLY CRATE TYPE: [P.name]
    - ACCESS RESTRICTION: [replacetext(get_access_desc(P.access))]
    - CONTENTS:
    "} - // END AUTOFIX - reqform.info += P.manifest - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:627: reqform.info += "
    " - reqform.info += {"
    - STAMP BELOW TO APPROVE THIS REQUISITION:
    "} - // END AUTOFIX - reqform.update_icon() //Fix for appearing blank when printed. - reqtime = (world.time + 5) % 1e5 - //make our supply_order datum - var/datum/supply_order/O = new /datum/supply_order() - O.ordernum = supply_shuttle.ordernum - O.object = P - O.orderedby = idname - O.account = account - supply_shuttle.requestlist += O - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:640: temp = "Order request placed.
    " - temp = {"Order request placed.
    -
    Back | Main Menu | Authorize Order"} - // END AUTOFIX - else if(href_list["confirmorder"]) - //Find the correct supply_order datum - var/ordernum = text2num(href_list["confirmorder"]) - var/datum/supply_order/O - var/datum/supply_packs/P - var/datum/money_account/A - var/datum/money_account/cargo_acct = department_accounts["Cargo"] - temp = "Invalid Request.
    Main Menu" - for(var/i=1, i<=supply_shuttle.requestlist.len, i++) - var/datum/supply_order/SO = supply_shuttle.requestlist[i] - if(SO.ordernum == ordernum) - O = SO - P = O.object - A = SO.account - if(A && A.money >= P.cost) - supply_shuttle.requestlist.Cut(i,i+1) - var/cargo_share = round((P.cost/100)*20) - var/centcom_share = P.cost-cargo_share - A.charge(centcom_share,null,"Supply Order #[SO.ordernum] ([P.name])",src.name,dest_name = "CentComm") - A.charge(cargo_share,cargo_acct,"Order Tax",src.name) - supply_shuttle.shoppinglist += O - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:658: temp = "Thanks for your order.
    " - temp = {"Thanks for your order.
    -
    Back Main Menu"} - // END AUTOFIX - else - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:661: temp = "Not enough supply points.
    " - temp = {"Not enough credit.
    -
    Back Main Menu"} - // END AUTOFIX - break - else if (href_list["vieworders"]) - temp = "Current approved orders:

    " - for(var/S in supply_shuttle.shoppinglist) - var/datum/supply_order/SO = S - temp += "#[SO.ordernum] - [SO.object.name] approved by [SO.orderedby][SO.comment ? " ([SO.comment])":""]
    "// (Cancel)
    " - temp += "
    OK" -/* - else if (href_list["cancelorder"]) - var/datum/supply_order/remove_supply = href_list["cancelorder"] - supply_shuttle_shoppinglist -= remove_supply - supply_shuttle_points += remove_supply.object.cost - temp += "Canceled: [remove_supply.object.name]


    " - for(var/S in supply_shuttle_shoppinglist) - var/datum/supply_order/SO = S - temp += "[SO.object.name] approved by [SO.orderedby][SO.comment ? " ([SO.comment])":""] (Cancel)
    " - temp += "
    OK" -*/ - else if (href_list["viewrequests"]) - temp = "Current requests:

    " - for(var/S in supply_shuttle.requestlist) - var/datum/supply_order/SO = S - temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby] [supply_shuttle.moving ? "":supply_shuttle.at_station ? "":"Approve Remove"]
    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:689: temp += "
    Clear list" - temp += {"
    Clear list -
    OK"} - // END AUTOFIX - else if (href_list["rreq"]) - var/ordernum = text2num(href_list["rreq"]) - temp = "Invalid Request.
    " - for(var/i=1, i<=supply_shuttle.requestlist.len, i++) - var/datum/supply_order/SO = supply_shuttle.requestlist[i] - if(SO.ordernum == ordernum) - supply_shuttle.requestlist.Cut(i,i+1) - temp = "Request removed.
    " - break - temp += "
    Back Main Menu" - - else if (href_list["clearreq"]) - supply_shuttle.requestlist.len = 0 - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:705: temp = "List cleared.
    " - temp = {"List cleared.
    -
    OK"} - // END AUTOFIX - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/supplycomp/proc/post_signal(var/command) - - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) - - if(!frequency) return - - var/datum/signal/status_signal = getFromPool(/datum/signal) - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - - frequency.post_signal(src, status_signal) +//Config stuff +#define SUPPLY_DOCKZ 2 //Z-level of the Dock. +#define SUPPLY_STATIONZ 1 //Z-level of the Station. + +#define SUPPLY_TAX 10 // Credits to charge per order. +var/datum/controller/supply_shuttle/supply_shuttle = new + +var/list/mechtoys = list( + /obj/item/toy/prize/ripley, + /obj/item/toy/prize/fireripley, + /obj/item/toy/prize/deathripley, + /obj/item/toy/prize/gygax, + /obj/item/toy/prize/durand, + /obj/item/toy/prize/honk, + /obj/item/toy/prize/marauder, + /obj/item/toy/prize/seraph, + /obj/item/toy/prize/mauler, + /obj/item/toy/prize/odysseus, + /obj/item/toy/prize/phazon +) +//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 can't get past those. No way." + icon = 'icons/obj/stationobjs.dmi' //Change this. + icon_state = "plasticflaps" + density = 0 + anchored = 1 + layer = 4 + explosion_resistance = 5 + var/airtight = 0 + +/obj/structure/plasticflaps/attackby(obj/item/I as obj, mob/user as mob) + if(istype(I, /obj/item/weapon/crowbar) && anchored == 1) + if(airtight == 0) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + else + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + user.visible_message("[user] [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.", "You [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.") + airtight = !airtight + name = "\improper [airtight? "Airtight p" : "P"]lastic flaps" + desc = "[airtight? "Heavy duty, airtight, plastic flaps." : "I definitely can't get past those. No way."]" + return 1 + if(istype(I, /obj/item/weapon/wrench) && airtight != 1) + if(anchored == 0) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + else + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + user.visible_message("[user] [anchored? "loosens" : "tightens"] the flap from its anchoring.", "You [anchored? "loosen" : "tighten"] the flap from its anchoring.") + anchored = !anchored + return 1 + else if (iswelder(I) && anchored == 0) + var/obj/item/weapon/weldingtool/WT = I + if(WT.remove_fuel(0, user)) + new /obj/item/stack/sheet/mineral/plastic (src.loc,10) + qdel(src) + return + return ..() + +/obj/structure/plasticflaps/examine(mob/user as mob) + ..() + to_chat(user, "It appears to be [anchored? "anchored to" : "unachored from"] the floor, [airtight? "and it seems to be airtight as well." : "but it does not seem to be airtight."]") + +/obj/structure/plasticflaps/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return prob(60) + + var/obj/structure/bed/B = mover + if (istype(mover, /obj/structure/bed) && B.locked_atoms.len)//if it's a bed/chair and someone is locked_to, it will not pass + return 0 + + else if(isliving(mover)) // You Shall Not Pass! + var/mob/living/M = mover + 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. + return 0 + if(!istype(mover)) // Aircheck! + return !airtight + return 1 + +/obj/structure/plasticflaps/ex_act(severity) + switch(severity) + if (1) + qdel(src) + if (2) + if (prob(50)) + qdel(src) + if (3) + if (prob(5)) + qdel(src) + +/obj/structure/plasticflaps/mining + name = "\improper Airtight plastic flaps" + desc = "Heavy duty, airtight, plastic flaps." + airtight = 1 + +/obj/structure/plasticflaps/cultify() + new /obj/structure/grille/cult(get_turf(src)) + ..() + +/obj/machinery/computer/supplycomp + name = "Supply shuttle console" + icon = 'icons/obj/computer.dmi' + icon_state = "supply" + req_access = list(access_cargo) + circuit = "/obj/item/weapon/circuitboard/supplycomp" + var/temp = null + var/reqtime = 0 //Cooldown for requisitions - Quarxink + var/hacked = 0 + var/can_order_contraband = 0 + var/last_viewed_group = "categories" + var/datum/money_account/current_acct + + light_color = LIGHT_COLOR_BROWN + +/obj/machinery/computer/ordercomp + name = "Supply ordering console" + icon = 'icons/obj/computer.dmi' + icon_state = "request" + circuit = "/obj/item/weapon/circuitboard/ordercomp" + var/temp = null + var/reqtime = 0 //Cooldown for requisitions - Quarxink + var/last_viewed_group = "categories" + var/datum/money_account/current_acct + + light_color = LIGHT_COLOR_BROWN + +/* +/obj/effect/marker/supplymarker + icon_state = "X" + icon = 'icons/misc/mark.dmi' + name = "X" + invisibility = 101 + anchored = 1 + opacity = 0 +*/ + +/datum/supply_order + var/ordernum + var/datum/supply_packs/object = null + var/datum/money_account/account = null + var/orderedby = null + var/comment = null + +/datum/controller/supply_shuttle + processing = 1 + processing_interval = 300 + //supply points have been replaced with MONEY MONEY MONEY - N3X + var/credits_per_slip = 2 + var/credits_per_crate = 5 + //var/credits_per_plasma = 0.5 // 2 plasma for 1 point + //control + var/ordernum + var/list/centcomm_orders = list() + var/list/shoppinglist = list() + var/list/requestlist = list() + var/list/supply_packs = list() + //shuttle movement + var/at_station = 0 + var/movetime = 1200 + var/moving = 0 + var/eta_timeofday + var/eta + var/datum/materials/materials_list = new + +/datum/controller/supply_shuttle/New() + ordernum = rand(1,9000) + + //Supply shuttle ticker - handles supply point regenertion and shuttle travelling between centcomm and the station +/datum/controller/supply_shuttle/proc/process() + for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs)) + var/datum/supply_packs/P = new typepath() + supply_packs[P.name] = P + + spawn(0) + //set background = 1 + while(1) + if(processing) + iteration++ + + if(moving == 1) + var/ticksleft = (eta_timeofday - world.timeofday) + if(ticksleft > 0) + eta = round(ticksleft/600,1) + else + eta = 0 + send() + + + sleep(processing_interval) + +/datum/controller/supply_shuttle/proc/send() + + var/obj/structure/docking_port/destination + + if(!at_station) //not at station + destination = cargo_shuttle.dock_station + + at_station = 1 + + if(!destination) + message_admins("WARNING: Cargo shuttle unable to find the station!") + warning("Cargo shuttle can't find centcomm") + else //at station + destination = cargo_shuttle.dock_centcom + + at_station = 0 + + if(!destination) + message_admins("WARNING: Cargo shuttle unable to find centcomm!") + warning("Cargo shuttle can't find centcomm") + + cargo_shuttle.move_to_dock(destination) + moving = 0 + + //Check whether the shuttle is allowed to move +/datum/controller/supply_shuttle/proc/can_move() + if(moving) return 0 + + if(forbidden_atoms_check(cargo_shuttle.linked_area)) + return 0 + + return 1 + +/datum/controller/supply_shuttle/proc/SellObjToOrders(var/atom/A,var/in_crate) + + + // Per-unit orders run last so they don't steal shit. + var/list/deferred_order_checks=list() + var/order_idx=0 + for(var/datum/centcomm_order/O in centcomm_orders) + order_idx++ + if(istype(O,/datum/centcomm_order/per_unit)) + deferred_order_checks += order_idx + if(O.CheckShuttleObject(A,in_crate)) + return + for(var/oid in deferred_order_checks) + var/datum/centcomm_order/O = centcomm_orders[oid] + if(O.CheckShuttleObject(A,in_crate)) + return + //Sellin + +/datum/controller/supply_shuttle/proc/sell() + + var/area/shuttle = cargo_shuttle.linked_area + if(!shuttle) return + + var/datum/money_account/cargo_acct = department_accounts["Cargo"] + + for(var/atom/movable/MA in shuttle) + if(MA.anchored) continue + + if(istype(MA, /obj/item/stack/sheet/mineral/plasma)) + var/obj/item/stack/sheet/mineral/plasma/P = MA + if(P.redeemed) continue + var/datum/material/mat = materials_list.getMaterial(P.sheettype) + cargo_acct.money += (mat.value * 2) * P.amount // Central Command pays double for plasma they receive that hasn't been redeemed already. + + // Must be in a crate! + else if(istype(MA,/obj/structure/closet/crate)) + cargo_acct.money += credits_per_crate + var/find_slip = 1 + + for(var/atom/A in MA) + if(istype(A, /obj/item/stack/sheet/mineral/plasma)) + var/obj/item/stack/sheet/mineral/plasma/P = A + if(P.redeemed) continue + var/datum/material/mat = materials_list.getMaterial(P.sheettype) + cargo_acct.money += (mat.value * 2) * P.amount // Central Command pays double for plasma they receive that hasn't been redeemed already. + continue + if(find_slip && istype(A,/obj/item/weapon/paper/manifest)) + var/obj/item/weapon/paper/slip = A + if(slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense + cargo_acct.money += credits_per_slip + find_slip = 0 + continue + + SellObjToOrders(A,0) + + // Delete it. (Fixes github #473) + if(A) qdel(A) + else + SellObjToOrders(MA,1) + + // PAY UP BITCHES + for(var/datum/centcomm_order/O in centcomm_orders) + if(O.CheckFulfilled()) + O.Pay() + centcomm_orders -= O +// to_chat(world, "deleting [MA]/[MA.type] it was [!MA.anchored ? "not ": ""] anchored") + qdel(MA) + + //Buyin +/datum/controller/supply_shuttle/proc/buy() + if(!shoppinglist.len) return + + var/area/shuttle = cargo_shuttle.linked_area + if(!shuttle) return + + var/list/clear_turfs = list() + + for(var/turf/T in shuttle) + if(T.density) continue + var/contcount + for(var/atom/A in T.contents) + if(islightingoverlay(A)) + continue + contcount++ + if(contcount) + continue + clear_turfs += T + + for(var/S in shoppinglist) + if(!clear_turfs.len) break + var/i = rand(1,clear_turfs.len) + var/turf/pickedloc = clear_turfs[i] + clear_turfs.Cut(i,i+1) + + var/datum/supply_order/SO = S + var/datum/supply_packs/SP = SO.object + + var/atom/A = new SP.containertype(pickedloc) + A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]" + + //supply manifest generation begin + + var/obj/item/weapon/paper/manifest/slip = new /obj/item/weapon/paper/manifest(A) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:298: slip.info = "

    [command_name()] Shipping Manifest



    " + slip.name = "Shipping Manifest for [SO.orderedby]'s Order" + slip.info = {"

    [command_name()] Shipping Manifest for [SO.orderedby]'s Order



    + Order #[SO.ordernum]
    + Destination: [station_name]
    + [supply_shuttle.shoppinglist.len] PACKAGES IN THIS SHIPMENT
    + CONTENTS:
      "} + // END AUTOFIX + //spawn the stuff, finish generating the manifest while you're at it + if(SP.access) + A:req_access = list() + A:req_access += text2num(SP.access) + + var/list/contains + if(istype(SP,/datum/supply_packs/randomised)) + var/datum/supply_packs/randomised/SPR = SP + contains = list() + if(SPR.contains.len) + for(var/j=1,j<=SPR.num_contained,j++) + contains += pick(SPR.contains) + else + contains = SP.contains + + for(var/typepath in contains) + if(!typepath) continue + var/atom/B2 = new typepath(A) + if(SP.amount && B2:amount) B2:amount = SP.amount + slip.info += "
    • [B2.name]
    • " //add the item to the manifest + + //manifest finalisation + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:326: slip.info += "

    " + slip.info += {"
    + CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
    "} + // END AUTOFIX + if (SP.contraband) slip.loc = null //we are out of blanks for Form #44-D Ordering Illicit Drugs. + + supply_shuttle.shoppinglist.len = 0 + return + +/datum/controller/supply_shuttle/proc/forbidden_atoms_check(atom/A) + var/contents = get_contents_in_object(A) + + if (locate(/mob/living) in contents) + . = TRUE + else if (locate(/obj/item/weapon/disk/nuclear) in contents) + . = TRUE + else if (locate(/obj/machinery/nuclearbomb) in contents) + . = TRUE + else if (locate(/obj/item/beacon) in contents) + . = TRUE + else if (locate(/obj/effect/portal) in contents)//you crafty fuckers + . = TRUE + else + . = FALSE + +/obj/item/weapon/paper/manifest + name = "Supply Manifest" + + +/obj/machinery/computer/ordercomp/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/computer/ordercomp/attack_paw(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/supplycomp/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return attack_hand(user) + +/obj/machinery/computer/supplycomp/attack_paw(var/mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/ordercomp/attack_hand(var/mob/user as mob) + if(..()) + return + current_acct = user.get_worn_id_account() + user.set_machine(src) + var/dat + if(temp) + dat = temp + else + dat += {"
    Supply shuttle
    + Location: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Dock"]
    +
    Bank account credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    +
    \nRequest items

    + View approved orders

    + View requests

    + Close"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + +/obj/machinery/computer/ordercomp/Topic(href, href_list) + if(..()) + return + + if( isturf(loc) && (in_range(src, usr) || istype(usr, /mob/living/silicon)) ) + usr.set_machine(src) + + if(href_list["order"]) + if(href_list["order"] == "categories") + //all_supply_groups + //Request what? + last_viewed_group = "categories" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:383: temp = "Supply points: [supply_shuttle.points]
    " + temp = {"Bank account credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    + Main Menu


    + Select a category

    "} + // END AUTOFIX + for(var/supply_group_name in all_supply_groups ) + temp += "[supply_group_name]
    " + else + last_viewed_group = href_list["order"] + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:390: temp = "Supply points: [supply_shuttle.points]
    " + temp = {"Bank account credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    + Back to all categories


    + Request from: [last_viewed_group]

    "} + // END AUTOFIX + for(var/supply_name in supply_shuttle.supply_packs ) + var/datum/supply_packs/N = supply_shuttle.supply_packs[supply_name] + if(N.hidden || N.contraband || N.group != last_viewed_group) continue //Have to send the type instead of a reference to + temp += "[supply_name] Cost: $[num2septext(N.cost)]
    " //the obj because it would get caught by the garbage + + else if (href_list["doorder"]) + if(world.time < reqtime) + for(var/mob/V in hearers(src)) + V.show_message("[src]'s monitor flashes, \"[world.time - reqtime] seconds remaining until another requisition form may be printed.\"") + return + + //Find the correct supply_pack datum + var/datum/supply_packs/P = supply_shuttle.supply_packs[href_list["doorder"]] + if(!istype(P)) return + + var/timeout = world.time + 600 + var/reason = copytext(sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text),1,MAX_MESSAGE_LEN) + if(world.time > timeout) return + if(!reason) return + + var/idname = "*None Provided*" + var/idrank = "*None Provided*" + var/datum/money_account/account + if(ishuman(usr)) + var/obj/item/weapon/card/id/I = usr.get_id_card() + if(I) + idname = I.registered_name + idrank = I.GetJobName() + account = get_card_account(I) + else + to_chat(usr, "Please wear an ID with an associated bank account.") + return + to_chat(usr, "\icon[src]Your request has been saved. The transaction will be performed to your bank account when it has been accepted by cargo staff.") + if(account && (account.money < P.cost)) + to_chat(usr, "\icon[src]Your bank account doesn't have enough funds to order this pack. Your request will be on hold until you provide your bank account with the necessary funds.") + else if(issilicon(usr)) + idname = usr.real_name + account = station_account + + supply_shuttle.ordernum++ + var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc) + reqform.name = "[P.name] Requisition Form - [idname], [idrank]" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:425: reqform.info += "

    [station_name] Supply Requisition Form


    " + reqform.info += {"

    [station_name] Supply Requisition Form


    + INDEX: #[supply_shuttle.ordernum]
    + REQUESTED BY: [idname]
    + RANK: [idrank]
    + REASON: [reason]
    + SUPPLY CRATE TYPE: [P.name]
    + ACCESS RESTRICTION: [replacetext(get_access_desc(P.access))]
    + CONTENTS:
    "} + // END AUTOFIX + reqform.info += P.manifest + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:434: reqform.info += "
    " + reqform.info += {"
    + STAMP BELOW TO APPROVE THIS REQUISITION:
    "} + // END AUTOFIX + reqform.update_icon() //Fix for appearing blank when printed. + reqtime = (world.time + 5) % 1e5 + + //make our supply_order datum + var/datum/supply_order/O = new /datum/supply_order() + O.ordernum = supply_shuttle.ordernum + O.object = P + O.orderedby = idname + O.account = account + supply_shuttle.requestlist += O + stat_collection.crates_ordered++ + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:447: temp = "Thanks for your request. The cargo team will process it as soon as possible.
    " + temp = {"Thanks for your request. The cargo team will process it as soon as possible.
    +
    Back Main Menu"} + // END AUTOFIX + else if (href_list["vieworders"]) + temp = "Current approved orders:

    " + for(var/S in supply_shuttle.shoppinglist) + var/datum/supply_order/SO = S + temp += "[SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    " + temp += "
    OK" + + else if (href_list["viewrequests"]) + temp = "Current requests:

    " + for(var/S in supply_shuttle.requestlist) + var/datum/supply_order/SO = S + temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby]
    " + temp += "
    OK" + + else if (href_list["mainmenu"]) + temp = null + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/supplycomp/attack_hand(var/mob/user as mob) + if(!allowed(user)) + to_chat(user, "Access Denied.") + return + + if(..()) + return + + current_acct = user.get_worn_id_account() + + user.set_machine(src) + post_signal("supply") + + var/dat + if (temp) + dat = temp + else + dat += {"
    Supply shuttle
    + \nLocation: [supply_shuttle.moving ? "Moving to station ([supply_shuttle.eta] Mins.)":supply_shuttle.at_station ? "Station":"Away"]
    +
    \nAvailable Credits: [current_acct ? current_acct.fmtBalance() : "N/A"]
    \n
    + [supply_shuttle.moving ? "\n*Must be away to order items*
    \n
    ":supply_shuttle.at_station ? "\n*Must be away to order items*
    \n
    ":"\nOrder items
    \n
    "] + [supply_shuttle.moving ? "\n*Shuttle already called*
    \n
    ":supply_shuttle.at_station ? "\nSend away
    \n
    ":"\nSend to station
    \n
    "] + \nView requests
    \n
    + \nView orders
    \n
    + \nClose"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + +/obj/machinery/computer/supplycomp/attackby(I as obj, user as mob) + if(istype(I,/obj/item/weapon/card/emag) && !hacked) + to_chat(user, "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, src, 20)) + if (stat & BROKEN) + to_chat(user, "The broken glass falls out.") + var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc ) + getFromPool(/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 + qdel(src) + else + to_chat(user, "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 + qdel(src) + else + return ..() + +/obj/machinery/computer/supplycomp/Topic(href, href_list) + + if(!supply_shuttle) + world.log << "## ERROR: Eek. The supply_shuttle controller datum is missing somehow." + return + if(..()) + return 1 + //Calling the shuttle + if(href_list["send"]) + if(!supply_shuttle.can_move()) + temp = "For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.

    OK" + else if(supply_shuttle.at_station) + supply_shuttle.moving = -1 + supply_shuttle.sell() + supply_shuttle.send() + temp = "The supply shuttle has departed.

    OK" + else + supply_shuttle.moving = 1 + supply_shuttle.buy() + supply_shuttle.eta_timeofday = (world.timeofday + supply_shuttle.movetime) % 864000 + temp = "The supply shuttle has been called and will arrive in [round(supply_shuttle.movetime/600,1)] minutes.

    OK" + post_signal("supply") + else if (href_list["order"]) + if(supply_shuttle.moving) return + if(href_list["order"] == "categories") + //all_supply_groups + //Request what? + last_viewed_group = "categories" + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:567: temp = "Supply points: [supply_shuttle.points]
    " + temp = {"Available credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    + Main Menu


    + Select a category

    "} + // END AUTOFIX + for(var/supply_group_name in all_supply_groups ) + temp += "[supply_group_name]
    " + else + last_viewed_group = href_list["order"] + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:574: temp = "Supply points: [supply_shuttle.points]
    " + temp = {"Available credits: [current_acct ? current_acct.fmtBalance() : "PANIC"]
    + Back to all categories


    + Request from: [last_viewed_group]

    "} + // END AUTOFIX + for(var/supply_name in supply_shuttle.supply_packs ) + var/datum/supply_packs/N = supply_shuttle.supply_packs[supply_name] + if((N.hidden && !hacked) || (N.contraband && !can_order_contraband) || N.group != last_viewed_group) continue //Have to send the type instead of a reference to + temp += "[supply_name] Cost: [N.cost]
    " //the obj because it would get caught by the garbage + /*temp = "Supply points: [supply_shuttle.points]


    Request what?

    " + for(var/supply_name in supply_shuttle.supply_packs ) + var/datum/supply_packs/N = supply_shuttle.supply_packs[supply_name] + if(N.hidden && !hacked) continue + if(N.contraband && !can_order_contraband) continue + temp += "[supply_name] Cost: [N.cost]
    " //the obj because it would get caught by the garbage + temp += "
    OK"*/ + else if (href_list["doorder"]) + if(world.time < reqtime) + for(var/mob/V in hearers(src)) + V.show_message("[src]'s monitor flashes, \"[world.time - reqtime] seconds remaining until another requisition form may be printed.\"") + return + //Find the correct supply_pack datum + var/datum/supply_packs/P = supply_shuttle.supply_packs[href_list["doorder"]] + if(!istype(P)) return + var/timeout = world.time + 600 + var/reason = copytext(sanitize(input(usr,"Reason:","Why do you require this item?","") as null|text),1,MAX_MESSAGE_LEN) + if(world.time > timeout) return + if(!reason) return + var/idname = "*None Provided*" + var/idrank = "*None Provided*" + var/datum/money_account/account + if(ishuman(usr)) + var/obj/item/weapon/card/id/I = usr.get_id_card() + if(I) + idname = I.registered_name + idrank = I.GetJobName() + account = get_card_account(I) + else + to_chat(usr, "\icon[src]Please wear an ID with an associated bank account.") + return + to_chat(usr, "\icon[src]Your request has been saved. The transaction will be performed to your bank account when it has been accepted by cargo staff.") + if(account && (account.money < P.cost)) + to_chat(usr, "\icon[src]Your bank account doesn't have enough funds to order this pack. Your request will be on hold until you provide your bank account with the necessary funds.") + else if(issilicon(usr)) + idname = usr.real_name + account = station_account + supply_shuttle.ordernum++ + var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc) + reqform.name = "[P.name] Requisition Form - [idname], [idrank]" + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:618: reqform.info += "

    [station_name] Supply Requisition Form


    " + reqform.info += {"

    [station_name] Supply Requisition Form


    + INDEX: #[supply_shuttle.ordernum]
    + REQUESTED BY: [idname]
    + RANK: [idrank]
    + REASON: [reason]
    + SUPPLY CRATE TYPE: [P.name]
    + ACCESS RESTRICTION: [replacetext(get_access_desc(P.access))]
    + CONTENTS:
    "} + // END AUTOFIX + reqform.info += P.manifest + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:627: reqform.info += "
    " + reqform.info += {"
    + STAMP BELOW TO APPROVE THIS REQUISITION:
    "} + // END AUTOFIX + reqform.update_icon() //Fix for appearing blank when printed. + reqtime = (world.time + 5) % 1e5 + //make our supply_order datum + var/datum/supply_order/O = new /datum/supply_order() + O.ordernum = supply_shuttle.ordernum + O.object = P + O.orderedby = idname + O.account = account + supply_shuttle.requestlist += O + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:640: temp = "Order request placed.
    " + temp = {"Order request placed.
    +
    Back | Main Menu | Authorize Order"} + // END AUTOFIX + else if(href_list["confirmorder"]) + //Find the correct supply_order datum + var/ordernum = text2num(href_list["confirmorder"]) + var/datum/supply_order/O + var/datum/supply_packs/P + var/datum/money_account/A + var/datum/money_account/cargo_acct = department_accounts["Cargo"] + temp = "Invalid Request.
    Main Menu" + for(var/i=1, i<=supply_shuttle.requestlist.len, i++) + var/datum/supply_order/SO = supply_shuttle.requestlist[i] + if(SO.ordernum == ordernum) + O = SO + P = O.object + A = SO.account + if(A && A.money >= P.cost) + supply_shuttle.requestlist.Cut(i,i+1) + var/cargo_share = round((P.cost/100)*20) + var/centcom_share = P.cost-cargo_share + A.charge(centcom_share,null,"Supply Order #[SO.ordernum] ([P.name])",src.name,dest_name = "CentComm") + A.charge(cargo_share,cargo_acct,"Order Tax",src.name) + supply_shuttle.shoppinglist += O + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:658: temp = "Thanks for your order.
    " + temp = {"Thanks for your order.
    +
    Back Main Menu"} + // END AUTOFIX + else + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:661: temp = "Not enough supply points.
    " + temp = {"Not enough credit.
    +
    Back Main Menu"} + // END AUTOFIX + break + else if (href_list["vieworders"]) + temp = "Current approved orders:

    " + for(var/S in supply_shuttle.shoppinglist) + var/datum/supply_order/SO = S + temp += "#[SO.ordernum] - [SO.object.name] approved by [SO.orderedby][SO.comment ? " ([SO.comment])":""]
    "// (Cancel)
    " + temp += "
    OK" +/* + else if (href_list["cancelorder"]) + var/datum/supply_order/remove_supply = href_list["cancelorder"] + supply_shuttle_shoppinglist -= remove_supply + supply_shuttle_points += remove_supply.object.cost + temp += "Canceled: [remove_supply.object.name]


    " + for(var/S in supply_shuttle_shoppinglist) + var/datum/supply_order/SO = S + temp += "[SO.object.name] approved by [SO.orderedby][SO.comment ? " ([SO.comment])":""] (Cancel)
    " + temp += "
    OK" +*/ + else if (href_list["viewrequests"]) + temp = "Current requests:

    " + for(var/S in supply_shuttle.requestlist) + var/datum/supply_order/SO = S + temp += "#[SO.ordernum] - [SO.object.name] requested by [SO.orderedby] [supply_shuttle.moving ? "":supply_shuttle.at_station ? "":"Approve Remove"]
    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:689: temp += "
    Clear list" + temp += {"
    Clear list +
    OK"} + // END AUTOFIX + else if (href_list["rreq"]) + var/ordernum = text2num(href_list["rreq"]) + temp = "Invalid Request.
    " + for(var/i=1, i<=supply_shuttle.requestlist.len, i++) + var/datum/supply_order/SO = supply_shuttle.requestlist[i] + if(SO.ordernum == ordernum) + supply_shuttle.requestlist.Cut(i,i+1) + temp = "Request removed.
    " + break + temp += "
    Back Main Menu" + + else if (href_list["clearreq"]) + supply_shuttle.requestlist.len = 0 + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\game\supplyshuttle.dm:705: temp = "List cleared.
    " + temp = {"List cleared.
    +
    OK"} + // END AUTOFIX + else if (href_list["mainmenu"]) + temp = null + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/supplycomp/proc/post_signal(var/command) + + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + + if(!frequency) return + + var/datum/signal/status_signal = getFromPool(/datum/signal) + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + + frequency.post_signal(src, status_signal) diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 39e8d84708f..fa03c12546c 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -1,142 +1,142 @@ -/turf/simulated - name = "station" - var/wet = 0 - var/image/wet_overlay = null - - var/thermite = 0 - var/can_thermite = 1 - oxygen = MOLES_O2STANDARD - nitrogen = MOLES_N2STANDARD - var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed - var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to - var/drying = 0 // tracking if something is currently drying -/turf/simulated/New() - ..() - - if(istype(loc, /area/chapel)) - holy = 1 - levelupdate() - -/turf/simulated/proc/AddTracks(var/typepath,var/bloodDNA,var/comingdir,var/goingdir,var/bloodcolor="#A10808") - var/obj/effect/decal/cleanable/blood/tracks/tracks = locate(typepath) in src - if(!tracks) - tracks = getFromPool(typepath, src) - tracks.AddTracks(bloodDNA,comingdir,goingdir,bloodcolor) - -/turf/simulated/Entered(atom/A, atom/OL) - if(movement_disabled && usr.ckey != movement_disabled_exception) - to_chat(usr, "Movement is admin-disabled.")//This is to identify lag problems - - return - - if (istype(A,/mob/living/carbon)) - var/mob/living/carbon/M = A - if(M.lying) return - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - - // Tracking blood - var/list/bloodDNA = null - var/bloodcolor="" - - // Do we have shoes? - if(H.shoes) - var/obj/item/clothing/shoes/S = H.shoes - if(S.track_blood && S.blood_DNA) - bloodDNA = S.blood_DNA - bloodcolor = S.blood_color - S.track_blood = max(round(S.track_blood - 1, 1),0) - else - if(H.track_blood && H.feet_blood_DNA) - bloodDNA = H.feet_blood_DNA - bloodcolor = H.feet_blood_color - H.track_blood = max(round(H.track_blood - 1, 1),0) - - if (bloodDNA) - if(istype(M,/mob/living/carbon/human/vox)) - src.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/vox,bloodDNA,H.dir,0,bloodcolor) // Coming - else - src.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints,bloodDNA,H.dir,0,bloodcolor) // Coming - var/turf/simulated/from = get_step(H,reverse_direction(H.dir)) - if(istype(from) && from) - if(istype(M,/mob/living/carbon/human/vox)) - from.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/vox,bloodDNA,0,H.dir,bloodcolor) // Going - else - from.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints,bloodDNA,0,H.dir,bloodcolor) // Going - - bloodDNA = null - - // Floorlength braids? Enjoy your tripping. - if(H.h_style && !H.check_hidden_head_flags(HIDEHEADHAIR)) - var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] - if(hair_style && (hair_style.flags & HAIRSTYLE_CANTRIP)) - if(H.m_intent == "run" && prob(5)) - if (H.Slip(4, 5)) - step(H, H.dir) - to_chat(H, "You tripped over your hair!") - - //Anything beyond that point will not fire if the mob isn't physically walking here - if(!M.on_foot()) //Checks lying, flying and locked.to - return ..() - - //And anything beyond that point will not fire for slimes - if(isslime(M)) //Slimes just don't slip, end of story - return ..() - - switch(src.wet) - if(1) //Water - if (M.Slip(5, 3)) - step(M, M.dir) - M.visible_message("[M] slips on the wet floor!", \ - "You slip on the wet floor!") - - if(2) //Lube - M.stop_pulling() - step(M, M.dir) - spawn(1) - step(M, M.dir) - spawn(2) - step(M, M.dir) - spawn(3) - step(M, M.dir) - spawn(4) - step(M, M.dir) - M.take_organ_damage(2) // Was 5 -- TLE - M.visible_message("[M] slips on the floor!", \ - "You slip on the floor!") - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) - M.Weaken(10) - - if(3) // Ice - if(prob(30) && M.Slip(4, 3)) - step(M, M.dir) - M.visible_message("[M] slips on the icy floor!", \ - "You slip on the icy floor!") - ..() - -//returns 1 if made bloody, returns 0 otherwise -/turf/simulated/add_blood(mob/living/carbon/human/M as mob) - if (!..()) - return 0 - - for(var/obj/effect/decal/cleanable/blood/B in contents) - if(!B.blood_DNA[M.dna.unique_enzymes]) - B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - B.virus2 = virus_copylist(M.virus2) - return 1 //we bloodied the floor - - blood_splatter(src,M,1) - return 1 //we bloodied the floor - - -// Only adds blood on the floor -- Skie -/turf/simulated/proc/add_blood_floor(mob/living/carbon/M as mob) - if(istype(M, /mob/living/carbon/monkey)) - blood_splatter(src,M,1) - else if( istype(M, /mob/living/carbon/alien )) - var/obj/effect/decal/cleanable/blood/xeno/this = getFromPool(/obj/effect/decal/cleanable/blood/xeno, src) - this.New(src) - this.blood_DNA["UNKNOWN BLOOD"] = "X*" - else if( istype(M, /mob/living/silicon/robot )) - var/obj/effect/decal/cleanable/blood/oil/B = getFromPool(/obj/effect/decal/cleanable/blood/oil,src) - B.New(src) +/turf/simulated + name = "station" + var/wet = 0 + var/image/wet_overlay = null + + var/thermite = 0 + var/can_thermite = 1 + oxygen = MOLES_O2STANDARD + nitrogen = MOLES_N2STANDARD + var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed + var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to + var/drying = 0 // tracking if something is currently drying +/turf/simulated/New() + ..() + + if(istype(loc, /area/chapel)) + holy = 1 + levelupdate() + +/turf/simulated/proc/AddTracks(var/typepath,var/bloodDNA,var/comingdir,var/goingdir,var/bloodcolor="#A10808") + var/obj/effect/decal/cleanable/blood/tracks/tracks = locate(typepath) in src + if(!tracks) + tracks = getFromPool(typepath, src) + tracks.AddTracks(bloodDNA,comingdir,goingdir,bloodcolor) + +/turf/simulated/Entered(atom/A, atom/OL) + if(movement_disabled && usr.ckey != movement_disabled_exception) + to_chat(usr, "Movement is admin-disabled.")//This is to identify lag problems + + return + + if (istype(A,/mob/living/carbon)) + var/mob/living/carbon/M = A + if(M.lying) return + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + + // Tracking blood + var/list/bloodDNA = null + var/bloodcolor="" + + // Do we have shoes? + if(H.shoes) + var/obj/item/clothing/shoes/S = H.shoes + if(S.track_blood && S.blood_DNA) + bloodDNA = S.blood_DNA + bloodcolor = S.blood_color + S.track_blood = max(round(S.track_blood - 1, 1),0) + else + if(H.track_blood && H.feet_blood_DNA) + bloodDNA = H.feet_blood_DNA + bloodcolor = H.feet_blood_color + H.track_blood = max(round(H.track_blood - 1, 1),0) + + if (bloodDNA) + if(istype(M,/mob/living/carbon/human/vox)) + src.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/vox,bloodDNA,H.dir,0,bloodcolor) // Coming + else + src.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints,bloodDNA,H.dir,0,bloodcolor) // Coming + var/turf/simulated/from = get_step(H,reverse_direction(H.dir)) + if(istype(from) && from) + if(istype(M,/mob/living/carbon/human/vox)) + from.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints/vox,bloodDNA,0,H.dir,bloodcolor) // Going + else + from.AddTracks(/obj/effect/decal/cleanable/blood/tracks/footprints,bloodDNA,0,H.dir,bloodcolor) // Going + + bloodDNA = null + + // Floorlength braids? Enjoy your tripping. + if(H.h_style && !H.check_hidden_head_flags(HIDEHEADHAIR)) + var/datum/sprite_accessory/hair_style = hair_styles_list[H.h_style] + if(hair_style && (hair_style.flags & HAIRSTYLE_CANTRIP)) + if(H.m_intent == "run" && prob(5)) + if (H.Slip(4, 5)) + step(H, H.dir) + to_chat(H, "You tripped over your hair!") + + //Anything beyond that point will not fire if the mob isn't physically walking here + if(!M.on_foot()) //Checks lying, flying and locked.to + return ..() + + //And anything beyond that point will not fire for slimes + if(isslime(M)) //Slimes just don't slip, end of story + return ..() + + switch(src.wet) + if(1) //Water + if (M.Slip(5, 3)) + step(M, M.dir) + M.visible_message("[M] slips on the wet floor!", \ + "You slip on the wet floor!") + + if(2) //Lube + M.stop_pulling() + step(M, M.dir) + spawn(1) + step(M, M.dir) + spawn(2) + step(M, M.dir) + spawn(3) + step(M, M.dir) + spawn(4) + step(M, M.dir) + M.take_organ_damage(2) // Was 5 -- TLE + M.visible_message("[M] slips on the floor!", \ + "You slip on the floor!") + playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) + M.Weaken(10) + + if(3) // Ice + if(prob(30) && M.Slip(4, 3)) + step(M, M.dir) + M.visible_message("[M] slips on the icy floor!", \ + "You slip on the icy floor!") + ..() + +//returns 1 if made bloody, returns 0 otherwise +/turf/simulated/add_blood(mob/living/carbon/human/M as mob) + if (!..()) + return 0 + + for(var/obj/effect/decal/cleanable/blood/B in contents) + if(!B.blood_DNA[M.dna.unique_enzymes]) + B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type + B.virus2 = virus_copylist(M.virus2) + return 1 //we bloodied the floor + + blood_splatter(src,M,1) + return 1 //we bloodied the floor + + +// Only adds blood on the floor -- Skie +/turf/simulated/proc/add_blood_floor(mob/living/carbon/M as mob) + if(istype(M, /mob/living/carbon/monkey)) + blood_splatter(src,M,1) + else if( istype(M, /mob/living/carbon/alien )) + var/obj/effect/decal/cleanable/blood/xeno/this = getFromPool(/obj/effect/decal/cleanable/blood/xeno, src) + this.New(src) + this.blood_DNA["UNKNOWN BLOOD"] = "X*" + else if( istype(M, /mob/living/silicon/robot )) + var/obj/effect/decal/cleanable/blood/oil/B = getFromPool(/obj/effect/decal/cleanable/blood/oil,src) + B.New(src) diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index cb7f84cb2a2..daa2f1670a8 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -1,650 +1,650 @@ -//This is so damaged or burnt tiles or platings don't get remembered as the default tile -var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","damaged4", - "damaged5","panelscorched","floorscorched1","floorscorched2","platingdmg1","platingdmg2", - "platingdmg3","plating","light_on","light_on_flicker1","light_on_flicker2", - "light_on_clicker3","light_on_clicker4","light_on_clicker5","light_broken", - "light_on_broken","light_off","wall_thermite","grass1","grass2","grass3","grass4", - "asteroid","asteroid_dug", - "asteroid0","asteroid1","asteroid2","asteroid3","asteroid4", - "asteroid5","asteroid6","asteroid7","asteroid8","asteroid9","asteroid10","asteroid11","asteroid12", - "oldburning","light-on-r","light-on-y","light-on-g","light-on-b", "wood", "wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7", "carpet", - "carpetcorner", "carpetside", "carpet", "arcade", "ironsand1", "ironsand2", "ironsand3", "ironsand4", "ironsand5", - "ironsand6", "ironsand7", "ironsand8", "ironsand9", "ironsand10", "ironsand11", - "ironsand12", "ironsand13", "ironsand14", "ironsand15") - -var/list/plating_icons = list("plating","platingdmg1","platingdmg2","platingdmg3","asteroid","asteroid_dug", - "ironsand1", "ironsand2", "ironsand3", "ironsand4", "ironsand5", "ironsand6", "ironsand7", - "ironsand8", "ironsand9", "ironsand10", "ironsand11", - "ironsand12", "ironsand13", "ironsand14", "ironsand15") -var/list/wood_icons = list("wood","wood-broken") -var/image/list/w_overlays = list("wet" = image('icons/effects/water.dmi',icon_state = "wet_floor")) -/turf/simulated/floor - - //Note to coders, the 'intact' var can no longer be used to determine if the floor is a plating or not. - //Use the is_plating(), is_plasteel_floor() and is_light_floor() procs instead. --Errorage - name = "floor" - icon = 'icons/turf/floors.dmi' - icon_state = "floor" - - var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default - var/icon_plating = "plating" - thermal_conductivity = 0.040 - heat_capacity = 10000 - var/lava = 0 - var/broken = 0 - var/burnt = 0 - var/material = "metal" - var/spam_flag = 0 //For certain interactions, like bananium floors honking when stepped on - var/obj/item/stack/tile/floor_tile - var/image/floor_overlay - - melt_temperature = 1643.15 // Melting point of steel - -/turf/simulated/floor/New() - ..() - if(!floor_tile) - floor_tile = getFromPool(/obj/item/stack/tile/plasteel, null) - floor_tile.amount = 1 - if(icon_state in icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default - icon_regular_floor = "floor" - else - icon_regular_floor = icon_state - -/turf/simulated/floor/ashify() - burn_tile() - -/turf/simulated/floor/melt() // Melting is different. - burn_tile() - -//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) -// if ((istype(mover, /obj/machinery/vehicle) && !(src.burnt))) -// if (!( locate(/obj/machinery/mass_driver, src) )) -// return 0 -// return ..() - -/turf/simulated/floor/ex_act(severity) - //set src in oview(1) - switch(severity) - if(1.0) - src.ChangeTurf(get_base_turf(src.z)) - if(2.0) - switch(pick(1,2;75,3)) - if (1) - src.ReplaceWithLattice() - if(prob(33)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 1 - if(2) - src.ChangeTurf(get_base_turf(src.z)) - if(3) - if(prob(80)) - src.break_tile_to_plating() - else - src.break_tile() - src.hotspot_expose(1000,CELL_VOLUME,surfaces=1) - if(prob(33)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 1 - if(3.0) - if (prob(50)) - src.break_tile() - src.hotspot_expose(1000,CELL_VOLUME,surfaces=1) - return - -/turf/simulated/floor/blob_act() - return - -turf/simulated/floor/update_icon() - overlays -= floor_overlay - - if(lava) - return - else if(is_plasteel_floor()) - if(!broken && !burnt) - icon_state = icon_regular_floor - else if(is_plating()) - if(!broken && !burnt) - icon_state = icon_plating //Because asteroids are 'platings' too. - else if(is_light_floor()) - var/obj/item/stack/tile/light/T = floor_tile - if(T.on) - set_light(5) - floor_overlay = T.get_turf_image() - icon_state = "light_base" - overlays += floor_overlay - light_color = floor_overlay.color - else - set_light(0) - icon_state = "light_off" - else if(is_grass_floor()) - if(!broken && !burnt) - if(!(icon_state in list("grass1","grass2","grass3","grass4"))) - icon_state = "grass[pick("1","2","3","4")]" - else if(is_carpet_floor()) - if(!broken && !burnt) - var/connectdir = 0 - for(var/direction in cardinal) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - if(FF.is_carpet_floor()) - connectdir |= direction - - //Check the diagonal connections for corners, where you have, for example, connections both north and east. In this case it checks for a north-east connection to determine whether to add a corner marker or not. - var/diagonalconnect = 0 //1 = NE; 2 = SE; 4 = NW; 8 = SW - - //Northeast - if(connectdir & NORTH && connectdir & EAST) - if(istype(get_step(src,NORTHEAST),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,NORTHEAST) - if(FF.is_carpet_floor()) - diagonalconnect |= 1 - - //Southeast - if(connectdir & SOUTH && connectdir & EAST) - if(istype(get_step(src,SOUTHEAST),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,SOUTHEAST) - if(FF.is_carpet_floor()) - diagonalconnect |= 2 - - //Northwest - if(connectdir & NORTH && connectdir & WEST) - if(istype(get_step(src,NORTHWEST),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,NORTHWEST) - if(FF.is_carpet_floor()) - diagonalconnect |= 4 - - //Southwest - if(connectdir & SOUTH && connectdir & WEST) - if(istype(get_step(src,SOUTHWEST),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,SOUTHWEST) - if(FF.is_carpet_floor()) - diagonalconnect |= 8 - - icon_state = "carpet[connectdir]-[diagonalconnect]" - - else if(is_arcade_floor()) - if(!broken && !burnt) - icon_state = "arcade" - - else if(is_wood_floor()) - if(!broken && !burnt) - if( !(icon_state in wood_icons) ) - icon_state = "wood" -// to_chat(world, "[icon_state]y's got [icon_state]") - else if(is_mineral_floor()) - if(!broken && !burnt) - icon_state = floor_tile.material - /*spawn(1) - if(istype(src,/turf/simulated/floor)) //Was throwing runtime errors due to a chance of it changing to space halfway through. - if(air) - update_visuals(air)*/ - -/turf/simulated/floor/return_siding_icon_state() - ..() - if(is_grass_floor()) - var/dir_sum = 0 - for(var/direction in cardinal) - var/turf/T = get_step(src,direction) - if(!(T.is_grass_floor())) - dir_sum += direction - if(dir_sum) - return "wood_siding[dir_sum]" - else - return 0 - - -/turf/simulated/floor/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/turf/simulated/floor/attack_hand(mob/user as mob) - if (is_light_floor()) - var/obj/item/stack/tile/light/T = floor_tile - T.on = !T.on - update_icon() - - switch(material) - if("bananium") - if(!spam_flag) - spam_flag = 1 - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1) - spawn(20) - spam_flag = 0 - ..() - -/turf/simulated/floor/proc/gets_drilled() - return - -/turf/simulated/floor/proc/break_tile_to_plating() - if(!is_plating()) - make_plating() - break_tile() - -/turf/simulated/floor/is_plasteel_floor() - if(istype(floor_tile,/obj/item/stack/tile/plasteel)) - return 1 - else - return 0 - -/turf/simulated/floor/is_light_floor() - if(istype(floor_tile,/obj/item/stack/tile/light)) - return 1 - else - return 0 - -/turf/simulated/floor/is_grass_floor() - if(istype(floor_tile,/obj/item/stack/tile/grass)) - return 1 - else - return 0 - -/turf/simulated/floor/is_wood_floor() - if(istype(floor_tile,/obj/item/stack/tile/wood)) - return 1 - else - return 0 - -/turf/simulated/floor/is_carpet_floor() - if(istype(floor_tile,/obj/item/stack/tile/carpet)) - return 1 - else - return 0 - -/turf/simulated/floor/is_arcade_floor() - if(istype(floor_tile,/obj/item/stack/tile/arcade)) - return 1 - return 0 - -/turf/simulated/floor/is_plating() - if(!floor_tile) - return 1 - return 0 - -/turf/simulated/floor/is_mineral_floor() - if(istype(floor_tile,/obj/item/stack/tile/mineral)) - return 1 - return 0 - -/turf/simulated/floor/proc/break_tile() - if(istype(src,/turf/simulated/floor/engine)) return - if(broken) return - if(is_plasteel_floor()) - src.icon_state = "damaged[pick(1,2,3,4,5)]" - broken = 1 - else if(is_light_floor()) - src.icon_state = "light_broken" - broken = 1 - else if(is_plating()) - src.icon_state = "platingdmg[pick(1,2,3)]" - broken = 1 - else if(is_wood_floor()) - src.icon_state = "wood-broken" - broken = 1 - else if((is_carpet_floor()) || (is_arcade_floor())) - src.icon_state = "carpet-broken" - broken = 1 - else if(is_grass_floor()) - src.icon_state = "sand[pick("1","2","3")]" - broken = 1 - else if(is_mineral_floor()) - if(material=="diamond") return //diamond doesn't break - if(material=="plastic") return //you can't break legos - if(material=="phazon") //Phazon shatters - spawn(rand(2,10)) - playsound(get_turf(src), "shatter", 70, 1) - make_plating() - return - - src.icon_state = "[material]_broken" - -/turf/simulated/floor/proc/burn_tile() - if(istype(src,/turf/simulated/floor/engine)) return - if(istype(src,/turf/unsimulated/floor/asteroid)) return//Asteroid tiles don't burn - if(is_plasteel_floor()) - src.icon_state = "damaged[pick(1,2,3,4,5)]" - burnt = 1 - else if(is_plasteel_floor()) - src.icon_state = "floorscorched[pick(1,2)]" - burnt = 1 - else if(is_plating()) - src.icon_state = "panelscorched" - burnt = 1 - else if(is_wood_floor()) - src.icon_state = "wood-broken" - burnt = 1 - else if((is_carpet_floor()) || (is_arcade_floor())) - src.icon_state = "carpet-broken" - burnt = 1 - else if(is_grass_floor()) - src.icon_state = "sand[pick("1","2","3")]" - burnt = 1 - else if(is_mineral_floor()) - burnt = 1 - -//This proc will delete the floor_tile and the update_iocn() proc will then change the icon_state of the turf -//This proc auto corrects the grass tiles' siding. -/turf/simulated/floor/proc/make_plating() - if(istype(src,/turf/simulated/floor/engine)) return - - if(is_grass_floor()) - for(var/direction in cardinal) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - FF.update_icon() //so siding get updated properly - else if(is_carpet_floor()) - spawn(5) - if(src) - for(var/direction in alldirs) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - FF.update_icon() //so siding get updated properly - - if(floor_tile) - //qdel(floor_tile) - returnToPool(floor_tile) - icon_plating = "plating" - set_light(0) - floor_tile = null - intact = 0 - broken = 0 - burnt = 0 - material = "metal" - - update_icon() - levelupdate() - -//This proc will make the turf a plasteel floor tile. The expected argument is the tile to make the turf with -//If none is given it will make a new object. dropping or unequipping must be handled before or after calling -//this proc. -/turf/simulated/floor/proc/make_plasteel_floor(var/obj/item/stack/tile/plasteel/T = null) - broken = 0 - burnt = 0 - intact = 1 - set_light(0) - if(floor_tile) returnToPool(floor_tile) - floor_tile = null - if(T) - if(istype(T,/obj/item/stack/tile/plasteel)) - floor_tile = T - if (icon_regular_floor) - icon_state = icon_regular_floor - else - icon_state = "floor" - icon_regular_floor = icon_state - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_tile = getFromPool(/obj/item/stack/tile/plasteel, null) - icon_state = "floor" - icon_regular_floor = icon_state - - update_icon() - levelupdate() - -//This proc will make the turf a light floor tile. The expected argument is the tile to make the turf with -//If none is given it will make a new object. dropping or unequipping must be handled before or after calling -//this proc. -/turf/simulated/floor/proc/make_light_floor(var/obj/item/stack/tile/light/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(floor_tile) returnToPool(floor_tile) - floor_tile = null - if(T) - if(istype(T,/obj/item/stack/tile/light)) - floor_tile = T - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_tile = getFromPool(/obj/item/stack/tile/light, null) - - update_icon() - levelupdate() - -//This proc will make a turf into a grass patch. Fun eh? Insert the grass tile to be used as the argument -//If no argument is given a new one will be made. -/turf/simulated/floor/proc/make_grass_floor(var/obj/item/stack/tile/grass/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(floor_tile) returnToPool(floor_tile) - floor_tile = null - if(T) - if(istype(T,/obj/item/stack/tile/grass)) - floor_tile = T - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_tile = getFromPool(/obj/item/stack/tile/wood, null) - update_icon() - levelupdate() - -//This proc will make a turf into a wood floor. Fun eh? Insert the wood tile to be used as the argument -//If no argument is given a new one will be made. -/turf/simulated/floor/proc/make_wood_floor(var/obj/item/stack/tile/wood/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(floor_tile) returnToPool(floor_tile) - floor_tile = null - if(T) - if(istype(T,/obj/item/stack/tile/wood)) - floor_tile = T - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_tile = getFromPool(/obj/item/stack/tile/wood, null) - update_icon() - levelupdate() - -//This proc will make a turf into a carpet floor. Fun eh? Insert the carpet tile to be used as the argument -//If no argument is given a new one will be made. -/turf/simulated/floor/proc/make_carpet_floor(var/obj/item/stack/tile/carpet/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(floor_tile) returnToPool(floor_tile) - floor_tile = null - if(T) - if(istype(T,/obj/item/stack/tile/carpet)) - floor_tile = T - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_tile = getFromPool(/obj/item/stack/tile/carpet, null) - - update_icon() - levelupdate() - - -/turf/simulated/floor/singularity_pull(S, current_size) - if(current_size >= STAGE_FIVE) - if(prob(75)) - if(floor_tile && !broken && !burnt) - floor_tile.loc = src - floor_tile = null - make_plating() - return - if(current_size == STAGE_FOUR) - if(prob(30)) - if(floor_tile && !broken && !burnt) - floor_tile.loc = src - floor_tile = null - make_plating() - -/turf/simulated/floor/attackby(obj/item/C as obj, mob/user as mob) - if(!C || !user) - return 0 - - if(istype(C, /obj/item/weapon/crowbar) && (!(is_plating()))) - if(broken || burnt) - to_chat(user, "You remove the broken plating.") - else - if(is_wood_floor()) - to_chat(user, "You forcefully pry off the planks, destroying them in the process.") - else - to_chat(user, "You remove the [floor_tile.name].") - floor_tile.loc = src - floor_tile = null - - make_plating() - // Can't play sounds from areas. - N3X - playsound(src, 'sound/items/Crowbar.ogg', 80, 1) - - return - else if(istype(C, /obj/item/weapon/screwdriver)) - if(is_wood_floor()) - if(broken || burnt) - return - else - if(is_wood_floor()) - to_chat(user, "You unscrew the planks.") - new floor_tile.type(src) - - make_plating() - playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) - return - else if(istype(C, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = C - if (is_plating()) - if (R.amount >= 2) - to_chat(user, "Reinforcing the floor...") - if(do_after(user, src, 30) && R && R.amount >= 2 && is_plating()) - ChangeTurf(/turf/simulated/floor/engine) - playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) - R.use(2) - return - else - to_chat(user, "You need more rods.") - else - to_chat(user, "You must remove the plating first.") - return - else if(istype(C, /obj/item/stack/tile)) - if(is_plating()) - if(!broken && !burnt) - var/obj/item/stack/tile/T = C - if(T.use(1)) - if(floor_tile) returnToPool(floor_tile) - floor_tile = null - floor_tile = getFromPool(T.type, null) - material = floor_tile.material - intact = 1 - if(istype(T,/obj/item/stack/tile/light)) - var/obj/item/stack/tile/light/L = T - var/obj/item/stack/tile/light/F = floor_tile - F.color_r = L.color_r - F.color_g = L.color_g - F.color_b = L.color_b - F.on = L.on - if(istype(T,/obj/item/stack/tile/grass)) - for(var/direction in cardinal) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - FF.update_icon() //so siding gets updated properly - else if(istype(T,/obj/item/stack/tile/carpet)) - for(var/direction in alldirs) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - FF.update_icon() //so siding gets updated properly - update_icon() - levelupdate() - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - else - to_chat(user, "This section is too damaged to support a tile. Use a welder to fix the damage.") - else if(istype(C, /obj/item/stack/cable_coil)) - if(is_plating()) - var/obj/item/stack/cable_coil/coil = C - coil.turf_place(src, user) - else - to_chat(user, "You must remove the plating first.") - else if(istype(C, /obj/item/weapon/pickaxe/shovel)) - if(is_grass_floor()) - playsound(src, 'sound/items/shovel.ogg', 50, 1) - new /obj/item/weapon/ore/glass(src) - new /obj/item/weapon/ore/glass(src) //Make some sand if you shovel grass - to_chat(user, "You shovel the grass.") - make_plating() - else - to_chat(user, "You cannot shovel this.") - else if(istype(C, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/welder = C - if(welder.isOn() && (is_plating())) - if(broken || burnt) - if(welder.remove_fuel(0,user)) - to_chat(user, "You fix some dents on the broken plating.") - playsound(src, 'sound/items/Welder.ogg', 80, 1) - icon_state = "plating" - burnt = 0 - broken = 0 - else - to_chat(user, "You need more welding fuel to complete this task.") - -/turf/simulated/floor/Enter(mob/AM) - .=..() - - if(AM && istype(AM,/mob/living)) - switch(material) - if("bananium") - if(!spam_flag) - spam_flag = 1 - playsound(get_turf(src), "clownstep", 50, 1) - spawn(20) - spam_flag = 0 - if("uranium") - if(!spam_flag) - spam_flag = 1 - set_light(3) - icon_state = "uranium_inactive" - for(var/mob/living/L in range(2,src)) //Weak radiation - L.apply_effect(3,IRRADIATE,0) - flick("uranium_active",src) - spawn(20) - set_light(0) - spawn(200) - spam_flag = 0 - update_icon() - -/turf/simulated/proc/wet(delay = 800) - if(wet >= 1) return - wet = 1 - if(wet_overlay) - overlays -= wet_overlay - wet_overlay = null - wet_overlay = w_overlays["wet"] - overlays += wet_overlay - spawn() dry(delay) - -/turf/simulated/proc/dry(delay = 800) - if(drying || wet >= 2) - return - drying = 1 - spawn(delay) - if (!istype(src)) return - if(wet >= 2) return - wet = 0 - drying = 0 - if(wet_overlay) - overlays -= wet_overlay - wet_overlay = null - -/turf/simulated/floor/attack_construct(mob/user as mob) - if(istype(src,/turf/simulated/floor/carpet)) return//carpets are cool - if(istype(user,/mob/living/simple_animal/construct/builder) && (get_dist(src,user) <= 3)) - if((icon_state != "cult")&&(icon_state != "cult-narsie")) - var/spell/aoe_turf/conjure/floor/S = locate() in user.spell_list - S.perform(user,0,src) - var/obj/screen/spell/SS = S.connected_button - SS.update_charge(1) - return 1 - return 0 - -/turf/simulated/floor/cultify() - if((icon_state != "cult")&&(icon_state != "cult-narsie")) - name = "engraved floor" - icon_state = "cult" - turf_animation('icons/effects/effects.dmi',"cultfloor",0,0,MOB_LAYER-1) - return +//This is so damaged or burnt tiles or platings don't get remembered as the default tile +var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","damaged4", + "damaged5","panelscorched","floorscorched1","floorscorched2","platingdmg1","platingdmg2", + "platingdmg3","plating","light_on","light_on_flicker1","light_on_flicker2", + "light_on_clicker3","light_on_clicker4","light_on_clicker5","light_broken", + "light_on_broken","light_off","wall_thermite","grass1","grass2","grass3","grass4", + "asteroid","asteroid_dug", + "asteroid0","asteroid1","asteroid2","asteroid3","asteroid4", + "asteroid5","asteroid6","asteroid7","asteroid8","asteroid9","asteroid10","asteroid11","asteroid12", + "oldburning","light-on-r","light-on-y","light-on-g","light-on-b", "wood", "wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7", "carpet", + "carpetcorner", "carpetside", "carpet", "arcade", "ironsand1", "ironsand2", "ironsand3", "ironsand4", "ironsand5", + "ironsand6", "ironsand7", "ironsand8", "ironsand9", "ironsand10", "ironsand11", + "ironsand12", "ironsand13", "ironsand14", "ironsand15") + +var/list/plating_icons = list("plating","platingdmg1","platingdmg2","platingdmg3","asteroid","asteroid_dug", + "ironsand1", "ironsand2", "ironsand3", "ironsand4", "ironsand5", "ironsand6", "ironsand7", + "ironsand8", "ironsand9", "ironsand10", "ironsand11", + "ironsand12", "ironsand13", "ironsand14", "ironsand15") +var/list/wood_icons = list("wood","wood-broken") +var/image/list/w_overlays = list("wet" = image('icons/effects/water.dmi',icon_state = "wet_floor")) +/turf/simulated/floor + + //Note to coders, the 'intact' var can no longer be used to determine if the floor is a plating or not. + //Use the is_plating(), is_plasteel_floor() and is_light_floor() procs instead. --Errorage + name = "floor" + icon = 'icons/turf/floors.dmi' + icon_state = "floor" + + var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default + var/icon_plating = "plating" + thermal_conductivity = 0.040 + heat_capacity = 10000 + var/lava = 0 + var/broken = 0 + var/burnt = 0 + var/material = "metal" + var/spam_flag = 0 //For certain interactions, like bananium floors honking when stepped on + var/obj/item/stack/tile/floor_tile + var/image/floor_overlay + + melt_temperature = 1643.15 // Melting point of steel + +/turf/simulated/floor/New() + ..() + if(!floor_tile) + floor_tile = getFromPool(/obj/item/stack/tile/plasteel, null) + floor_tile.amount = 1 + if(icon_state in icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default + icon_regular_floor = "floor" + else + icon_regular_floor = icon_state + +/turf/simulated/floor/ashify() + burn_tile() + +/turf/simulated/floor/melt() // Melting is different. + burn_tile() + +//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) +// if ((istype(mover, /obj/machinery/vehicle) && !(src.burnt))) +// if (!( locate(/obj/machinery/mass_driver, src) )) +// return 0 +// return ..() + +/turf/simulated/floor/ex_act(severity) + //set src in oview(1) + switch(severity) + if(1.0) + src.ChangeTurf(get_base_turf(src.z)) + if(2.0) + switch(pick(1,2;75,3)) + if (1) + src.ReplaceWithLattice() + if(prob(33)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 1 + if(2) + src.ChangeTurf(get_base_turf(src.z)) + if(3) + if(prob(80)) + src.break_tile_to_plating() + else + src.break_tile() + src.hotspot_expose(1000,CELL_VOLUME,surfaces=1) + if(prob(33)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 1 + if(3.0) + if (prob(50)) + src.break_tile() + src.hotspot_expose(1000,CELL_VOLUME,surfaces=1) + return + +/turf/simulated/floor/blob_act() + return + +turf/simulated/floor/update_icon() + overlays -= floor_overlay + + if(lava) + return + else if(is_plasteel_floor()) + if(!broken && !burnt) + icon_state = icon_regular_floor + else if(is_plating()) + if(!broken && !burnt) + icon_state = icon_plating //Because asteroids are 'platings' too. + else if(is_light_floor()) + var/obj/item/stack/tile/light/T = floor_tile + if(T.on) + set_light(5) + floor_overlay = T.get_turf_image() + icon_state = "light_base" + overlays += floor_overlay + light_color = floor_overlay.color + else + set_light(0) + icon_state = "light_off" + else if(is_grass_floor()) + if(!broken && !burnt) + if(!(icon_state in list("grass1","grass2","grass3","grass4"))) + icon_state = "grass[pick("1","2","3","4")]" + else if(is_carpet_floor()) + if(!broken && !burnt) + var/connectdir = 0 + for(var/direction in cardinal) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + if(FF.is_carpet_floor()) + connectdir |= direction + + //Check the diagonal connections for corners, where you have, for example, connections both north and east. In this case it checks for a north-east connection to determine whether to add a corner marker or not. + var/diagonalconnect = 0 //1 = NE; 2 = SE; 4 = NW; 8 = SW + + //Northeast + if(connectdir & NORTH && connectdir & EAST) + if(istype(get_step(src,NORTHEAST),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,NORTHEAST) + if(FF.is_carpet_floor()) + diagonalconnect |= 1 + + //Southeast + if(connectdir & SOUTH && connectdir & EAST) + if(istype(get_step(src,SOUTHEAST),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,SOUTHEAST) + if(FF.is_carpet_floor()) + diagonalconnect |= 2 + + //Northwest + if(connectdir & NORTH && connectdir & WEST) + if(istype(get_step(src,NORTHWEST),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,NORTHWEST) + if(FF.is_carpet_floor()) + diagonalconnect |= 4 + + //Southwest + if(connectdir & SOUTH && connectdir & WEST) + if(istype(get_step(src,SOUTHWEST),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,SOUTHWEST) + if(FF.is_carpet_floor()) + diagonalconnect |= 8 + + icon_state = "carpet[connectdir]-[diagonalconnect]" + + else if(is_arcade_floor()) + if(!broken && !burnt) + icon_state = "arcade" + + else if(is_wood_floor()) + if(!broken && !burnt) + if( !(icon_state in wood_icons) ) + icon_state = "wood" +// to_chat(world, "[icon_state]y's got [icon_state]") + else if(is_mineral_floor()) + if(!broken && !burnt) + icon_state = floor_tile.material + /*spawn(1) + if(istype(src,/turf/simulated/floor)) //Was throwing runtime errors due to a chance of it changing to space halfway through. + if(air) + update_visuals(air)*/ + +/turf/simulated/floor/return_siding_icon_state() + ..() + if(is_grass_floor()) + var/dir_sum = 0 + for(var/direction in cardinal) + var/turf/T = get_step(src,direction) + if(!(T.is_grass_floor())) + dir_sum += direction + if(dir_sum) + return "wood_siding[dir_sum]" + else + return 0 + + +/turf/simulated/floor/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/turf/simulated/floor/attack_hand(mob/user as mob) + if (is_light_floor()) + var/obj/item/stack/tile/light/T = floor_tile + T.on = !T.on + update_icon() + + switch(material) + if("bananium") + if(!spam_flag) + spam_flag = 1 + playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1) + spawn(20) + spam_flag = 0 + ..() + +/turf/simulated/floor/proc/gets_drilled() + return + +/turf/simulated/floor/proc/break_tile_to_plating() + if(!is_plating()) + make_plating() + break_tile() + +/turf/simulated/floor/is_plasteel_floor() + if(istype(floor_tile,/obj/item/stack/tile/plasteel)) + return 1 + else + return 0 + +/turf/simulated/floor/is_light_floor() + if(istype(floor_tile,/obj/item/stack/tile/light)) + return 1 + else + return 0 + +/turf/simulated/floor/is_grass_floor() + if(istype(floor_tile,/obj/item/stack/tile/grass)) + return 1 + else + return 0 + +/turf/simulated/floor/is_wood_floor() + if(istype(floor_tile,/obj/item/stack/tile/wood)) + return 1 + else + return 0 + +/turf/simulated/floor/is_carpet_floor() + if(istype(floor_tile,/obj/item/stack/tile/carpet)) + return 1 + else + return 0 + +/turf/simulated/floor/is_arcade_floor() + if(istype(floor_tile,/obj/item/stack/tile/arcade)) + return 1 + return 0 + +/turf/simulated/floor/is_plating() + if(!floor_tile) + return 1 + return 0 + +/turf/simulated/floor/is_mineral_floor() + if(istype(floor_tile,/obj/item/stack/tile/mineral)) + return 1 + return 0 + +/turf/simulated/floor/proc/break_tile() + if(istype(src,/turf/simulated/floor/engine)) return + if(broken) return + if(is_plasteel_floor()) + src.icon_state = "damaged[pick(1,2,3,4,5)]" + broken = 1 + else if(is_light_floor()) + src.icon_state = "light_broken" + broken = 1 + else if(is_plating()) + src.icon_state = "platingdmg[pick(1,2,3)]" + broken = 1 + else if(is_wood_floor()) + src.icon_state = "wood-broken" + broken = 1 + else if((is_carpet_floor()) || (is_arcade_floor())) + src.icon_state = "carpet-broken" + broken = 1 + else if(is_grass_floor()) + src.icon_state = "sand[pick("1","2","3")]" + broken = 1 + else if(is_mineral_floor()) + if(material=="diamond") return //diamond doesn't break + if(material=="plastic") return //you can't break legos + if(material=="phazon") //Phazon shatters + spawn(rand(2,10)) + playsound(get_turf(src), "shatter", 70, 1) + make_plating() + return + + src.icon_state = "[material]_broken" + +/turf/simulated/floor/proc/burn_tile() + if(istype(src,/turf/simulated/floor/engine)) return + if(istype(src,/turf/unsimulated/floor/asteroid)) return//Asteroid tiles don't burn + if(is_plasteel_floor()) + src.icon_state = "damaged[pick(1,2,3,4,5)]" + burnt = 1 + else if(is_plasteel_floor()) + src.icon_state = "floorscorched[pick(1,2)]" + burnt = 1 + else if(is_plating()) + src.icon_state = "panelscorched" + burnt = 1 + else if(is_wood_floor()) + src.icon_state = "wood-broken" + burnt = 1 + else if((is_carpet_floor()) || (is_arcade_floor())) + src.icon_state = "carpet-broken" + burnt = 1 + else if(is_grass_floor()) + src.icon_state = "sand[pick("1","2","3")]" + burnt = 1 + else if(is_mineral_floor()) + burnt = 1 + +//This proc will delete the floor_tile and the update_iocn() proc will then change the icon_state of the turf +//This proc auto corrects the grass tiles' siding. +/turf/simulated/floor/proc/make_plating() + if(istype(src,/turf/simulated/floor/engine)) return + + if(is_grass_floor()) + for(var/direction in cardinal) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + FF.update_icon() //so siding get updated properly + else if(is_carpet_floor()) + spawn(5) + if(src) + for(var/direction in alldirs) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + FF.update_icon() //so siding get updated properly + + if(floor_tile) + //qdel(floor_tile) + returnToPool(floor_tile) + icon_plating = "plating" + set_light(0) + floor_tile = null + intact = 0 + broken = 0 + burnt = 0 + material = "metal" + + update_icon() + levelupdate() + +//This proc will make the turf a plasteel floor tile. The expected argument is the tile to make the turf with +//If none is given it will make a new object. dropping or unequipping must be handled before or after calling +//this proc. +/turf/simulated/floor/proc/make_plasteel_floor(var/obj/item/stack/tile/plasteel/T = null) + broken = 0 + burnt = 0 + intact = 1 + set_light(0) + if(floor_tile) returnToPool(floor_tile) + floor_tile = null + if(T) + if(istype(T,/obj/item/stack/tile/plasteel)) + floor_tile = T + if (icon_regular_floor) + icon_state = icon_regular_floor + else + icon_state = "floor" + icon_regular_floor = icon_state + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_tile = getFromPool(/obj/item/stack/tile/plasteel, null) + icon_state = "floor" + icon_regular_floor = icon_state + + update_icon() + levelupdate() + +//This proc will make the turf a light floor tile. The expected argument is the tile to make the turf with +//If none is given it will make a new object. dropping or unequipping must be handled before or after calling +//this proc. +/turf/simulated/floor/proc/make_light_floor(var/obj/item/stack/tile/light/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(floor_tile) returnToPool(floor_tile) + floor_tile = null + if(T) + if(istype(T,/obj/item/stack/tile/light)) + floor_tile = T + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_tile = getFromPool(/obj/item/stack/tile/light, null) + + update_icon() + levelupdate() + +//This proc will make a turf into a grass patch. Fun eh? Insert the grass tile to be used as the argument +//If no argument is given a new one will be made. +/turf/simulated/floor/proc/make_grass_floor(var/obj/item/stack/tile/grass/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(floor_tile) returnToPool(floor_tile) + floor_tile = null + if(T) + if(istype(T,/obj/item/stack/tile/grass)) + floor_tile = T + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_tile = getFromPool(/obj/item/stack/tile/wood, null) + update_icon() + levelupdate() + +//This proc will make a turf into a wood floor. Fun eh? Insert the wood tile to be used as the argument +//If no argument is given a new one will be made. +/turf/simulated/floor/proc/make_wood_floor(var/obj/item/stack/tile/wood/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(floor_tile) returnToPool(floor_tile) + floor_tile = null + if(T) + if(istype(T,/obj/item/stack/tile/wood)) + floor_tile = T + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_tile = getFromPool(/obj/item/stack/tile/wood, null) + update_icon() + levelupdate() + +//This proc will make a turf into a carpet floor. Fun eh? Insert the carpet tile to be used as the argument +//If no argument is given a new one will be made. +/turf/simulated/floor/proc/make_carpet_floor(var/obj/item/stack/tile/carpet/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(floor_tile) returnToPool(floor_tile) + floor_tile = null + if(T) + if(istype(T,/obj/item/stack/tile/carpet)) + floor_tile = T + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_tile = getFromPool(/obj/item/stack/tile/carpet, null) + + update_icon() + levelupdate() + + +/turf/simulated/floor/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(75)) + if(floor_tile && !broken && !burnt) + floor_tile.loc = src + floor_tile = null + make_plating() + return + if(current_size == STAGE_FOUR) + if(prob(30)) + if(floor_tile && !broken && !burnt) + floor_tile.loc = src + floor_tile = null + make_plating() + +/turf/simulated/floor/attackby(obj/item/C as obj, mob/user as mob) + if(!C || !user) + return 0 + + if(istype(C, /obj/item/weapon/crowbar) && (!(is_plating()))) + if(broken || burnt) + to_chat(user, "You remove the broken plating.") + else + if(is_wood_floor()) + to_chat(user, "You forcefully pry off the planks, destroying them in the process.") + else + to_chat(user, "You remove the [floor_tile.name].") + floor_tile.loc = src + floor_tile = null + + make_plating() + // Can't play sounds from areas. - N3X + playsound(src, 'sound/items/Crowbar.ogg', 80, 1) + + return + else if(istype(C, /obj/item/weapon/screwdriver)) + if(is_wood_floor()) + if(broken || burnt) + return + else + if(is_wood_floor()) + to_chat(user, "You unscrew the planks.") + new floor_tile.type(src) + + make_plating() + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) + return + else if(istype(C, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = C + if (is_plating()) + if (R.amount >= 2) + to_chat(user, "Reinforcing the floor...") + if(do_after(user, src, 30) && R && R.amount >= 2 && is_plating()) + ChangeTurf(/turf/simulated/floor/engine) + playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) + R.use(2) + return + else + to_chat(user, "You need more rods.") + else + to_chat(user, "You must remove the plating first.") + return + else if(istype(C, /obj/item/stack/tile)) + if(is_plating()) + if(!broken && !burnt) + var/obj/item/stack/tile/T = C + if(T.use(1)) + if(floor_tile) returnToPool(floor_tile) + floor_tile = null + floor_tile = getFromPool(T.type, null) + material = floor_tile.material + intact = 1 + if(istype(T,/obj/item/stack/tile/light)) + var/obj/item/stack/tile/light/L = T + var/obj/item/stack/tile/light/F = floor_tile + F.color_r = L.color_r + F.color_g = L.color_g + F.color_b = L.color_b + F.on = L.on + if(istype(T,/obj/item/stack/tile/grass)) + for(var/direction in cardinal) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + FF.update_icon() //so siding gets updated properly + else if(istype(T,/obj/item/stack/tile/carpet)) + for(var/direction in alldirs) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + FF.update_icon() //so siding gets updated properly + update_icon() + levelupdate() + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + else + to_chat(user, "This section is too damaged to support a tile. Use a welder to fix the damage.") + else if(istype(C, /obj/item/stack/cable_coil)) + if(is_plating()) + var/obj/item/stack/cable_coil/coil = C + coil.turf_place(src, user) + else + to_chat(user, "You must remove the plating first.") + else if(istype(C, /obj/item/weapon/pickaxe/shovel)) + if(is_grass_floor()) + playsound(src, 'sound/items/shovel.ogg', 50, 1) + new /obj/item/weapon/ore/glass(src) + new /obj/item/weapon/ore/glass(src) //Make some sand if you shovel grass + to_chat(user, "You shovel the grass.") + make_plating() + else + to_chat(user, "You cannot shovel this.") + else if(istype(C, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/welder = C + if(welder.isOn() && (is_plating())) + if(broken || burnt) + if(welder.remove_fuel(0,user)) + to_chat(user, "You fix some dents on the broken plating.") + playsound(src, 'sound/items/Welder.ogg', 80, 1) + icon_state = "plating" + burnt = 0 + broken = 0 + else + to_chat(user, "You need more welding fuel to complete this task.") + +/turf/simulated/floor/Enter(mob/AM) + .=..() + + if(AM && istype(AM,/mob/living)) + switch(material) + if("bananium") + if(!spam_flag) + spam_flag = 1 + playsound(get_turf(src), "clownstep", 50, 1) + spawn(20) + spam_flag = 0 + if("uranium") + if(!spam_flag) + spam_flag = 1 + set_light(3) + icon_state = "uranium_inactive" + for(var/mob/living/L in range(2,src)) //Weak radiation + L.apply_effect(3,IRRADIATE,0) + flick("uranium_active",src) + spawn(20) + set_light(0) + spawn(200) + spam_flag = 0 + update_icon() + +/turf/simulated/proc/wet(delay = 800) + if(wet >= 1) return + wet = 1 + if(wet_overlay) + overlays -= wet_overlay + wet_overlay = null + wet_overlay = w_overlays["wet"] + overlays += wet_overlay + spawn() dry(delay) + +/turf/simulated/proc/dry(delay = 800) + if(drying || wet >= 2) + return + drying = 1 + spawn(delay) + if (!istype(src)) return + if(wet >= 2) return + wet = 0 + drying = 0 + if(wet_overlay) + overlays -= wet_overlay + wet_overlay = null + +/turf/simulated/floor/attack_construct(mob/user as mob) + if(istype(src,/turf/simulated/floor/carpet)) return//carpets are cool + if(istype(user,/mob/living/simple_animal/construct/builder) && (get_dist(src,user) <= 3)) + if((icon_state != "cult")&&(icon_state != "cult-narsie")) + var/spell/aoe_turf/conjure/floor/S = locate() in user.spell_list + S.perform(user,0,src) + var/obj/screen/spell/SS = S.connected_button + SS.update_charge(1) + return 1 + return 0 + +/turf/simulated/floor/cultify() + if((icon_state != "cult")&&(icon_state != "cult-narsie")) + name = "engraved floor" + icon_state = "cult" + turf_animation('icons/effects/effects.dmi',"cultfloor",0,0,MOB_LAYER-1) + return diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index c51a154d1dd..1baa25b8f62 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -1,354 +1,354 @@ -/turf/simulated/floor/airless - icon_state = "floor" - name = "airless floor" - oxygen = 0.01 - nitrogen = 0.01 - temperature = TCMB - -/turf/simulated/floor/airless/New() - ..() - name = "floor" - - -/turf/simulated/floor/plating/vox - icon_state = "plating" - name = "vox plating" - //icon = 'icons/turf/shuttle-debug.dmi' - oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON - nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure - -/turf/simulated/floor/plating/vox/New() - ..() - name = "plating" - -/turf/simulated/floor/vox - icon_state = "floor" - name = "vox floor" - //icon = 'icons/turf/shuttle-debug.dmi' - oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON - nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure - -/turf/simulated/floor/vox/New() - ..() - name = "floor" - -/turf/simulated/floor/vox/wood - name = "floor" - icon_state = "wood" - floor_tile - - autoignition_temperature = AUTOIGNITION_WOOD - fire_fuel = 10 - soot_type = null - melt_temperature = 0 // Doesn't melt. - -/turf/simulated/floor/vox/wood/New() - if(floor_tile) - returnToPool(floor_tile) - floor_tile = null - floor_tile = getFromPool(/obj/item/stack/tile/wood, null) - ..() - -/turf/simulated/floor/light - name = "Light floor" - luminosity = 5 - icon_state = "light_on" - floor_tile - -/turf/simulated/floor/light/New() - if(floor_tile) - returnToPool(floor_tile) - floor_tile = null - floor_tile = getFromPool(/obj/item/stack/tile/light, null) - floor_tile.New() //I guess New() isn't run on objects spawned without the definition of a turf to house them, ah well. - var/n = name //just in case commands rename it in the ..() call - ..() - spawn(4) - if(src) - update_icon() - name = n - -/turf/simulated/floor/wood - name = "floor" - icon_state = "wood" - floor_tile - - autoignition_temperature = AUTOIGNITION_WOOD - fire_fuel = 10 - soot_type = null - melt_temperature = 0 // Doesn't melt. - -/turf/simulated/floor/wood/New() - floor_tile = getFromPool(/obj/item/stack/tile/wood,null) - ..() - -/turf/simulated/floor/vault - icon_state = "rockvault" - -/turf/simulated/floor/vault/New(location,type) - ..() - icon_state = "[type]vault" - -/turf/simulated/wall/vault - icon_state = "rockvault" - -/turf/simulated/wall/vault/New(location,type) - ..() - icon_state = "[type]vault" - -/turf/simulated/floor/engine - name = "reinforced floor" - icon_state = "engine" - thermal_conductivity = 0.025 - heat_capacity = 325000 - - soot_type = null - melt_temperature = 0 // Doesn't melt. - -/turf/simulated/floor/engine/attackby(obj/item/weapon/C as obj, mob/user as mob) - if(!C) - return - if(!user) - return - if(istype(C, /obj/item/weapon/wrench)) - to_chat(user, "Removing rods...") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 80, 1) - if(do_after(user, src, 30) && istype(src, /turf/simulated/floor/engine)) // Somehow changing the turf does NOT kill the current running proc. - new /obj/item/stack/rods(src, 2) - ChangeTurf(/turf/simulated/floor) - var/turf/simulated/floor/F = src - F.make_plating() - return - -/turf/simulated/floor/engine/ex_act(severity) - switch(severity) - if(1.0) - if(prob(80)) - src.ReplaceWithLattice() - else if(prob(50)) - src.ChangeTurf(get_base_turf(src.z)) - else - var/turf/simulated/floor/F = src - F.make_plating() - if(2.0) - if(prob(50)) - var/turf/simulated/floor/F = src - F.make_plating() - else - return - if(3.0) - return - return - -/turf/simulated/floor/engine/cult - name = "engraved floor" - icon_state = "cult" - -/turf/simulated/floor/engine/cult/attack_construct(mob/user as mob) - return 0 - -/turf/simulated/floor/engine/cult/cultify() - return - -/turf/simulated/floor/engine/airless - oxygen = 0.01 - nitrogen = 0.01 - -/turf/simulated/floor/engine/n20 - -/turf/simulated/floor/engine/n20/New() - ..() - if(src.air) - // EXACTLY the same code as fucking roomfillers. If this doesn't work, something's fucked. - var/datum/gas/sleeping_agent/trace_gas = new - air.trace_gases += trace_gas - trace_gas.moles = 9*4000 - air.update_values() - -/turf/simulated/floor/engine/nitrogen - name = "nitrogen floor" - icon_state = "engine" - oxygen=0 - nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure - temperature = TCMB - -/turf/simulated/floor/engine/vacuum - name = "vacuum floor" - icon_state = "engine" - oxygen = 0 - nitrogen = 0.001 - temperature = TCMB - -/turf/simulated/floor/plating - name = "plating" - icon_state = "plating" - intact = 0 - -/turf/simulated/floor/plating/deck - name = "deck" - icon_plating = "deck" - desc = "Children love to play on this deck." - -/turf/simulated/floor/plating/deck/New() - ..() - icon_state = "deck" - -/turf/simulated/floor/plating/deck/update_icon() - icon_plating = "deck" - ..() - if(!floor_tile) - name = "deck" - icon_state = "deck" - desc = "Children love to play on this deck." - else - name = "floor" - desc = null - -/turf/simulated/floor/plating/deck/airless - name = "airless deck" - oxygen = 0.01 - nitrogen = 0.01 - temperature = TCMB - -/turf/simulated/floor/plating/deck/airless/New() - ..() - name = "deck" - -/turf/simulated/floor/plating/New() - ..() - if(floor_tile) - returnToPool(floor_tile) - floor_tile = null - - -/turf/simulated/floor/plating/airless - icon_state = "plating" - name = "airless plating" - oxygen = 0.01 - nitrogen = 0.01 - temperature = TCMB - -/turf/simulated/floor/plating/airless/New() - ..() - name = "plating" - -/turf/simulated/floor/bluegrid - icon = 'icons/turf/floors.dmi' - icon_state = "bcircuit" - -/turf/simulated/floor/greengrid - icon = 'icons/turf/floors.dmi' - icon_state = "gcircuit" - -/turf/simulated/floor/beach - name = "Beach" - icon = 'icons/misc/beach.dmi' - soot_type = null - melt_temperature = 0 // Doesn't melt. - -/turf/simulated/floor/beach/sand - name = "Sand" - icon_state = "sand" - -/turf/simulated/floor/beach/coastline - name = "Coastline" - icon = 'icons/misc/beach2.dmi' - icon_state = "sandwater" - -/turf/simulated/floor/beach/water - name = "Water" - icon_state = "water" - -/turf/simulated/floor/beach/water/New() - ..() - overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1) - -/turf/simulated/floor/grass - name = "Grass patch" - icon_state = "grass1" - floor_tile - -/turf/simulated/floor/grass/New() - if(floor_tile) - returnToPool(floor_tile) - floor_tile = null - floor_tile = getFromPool(/obj/item/stack/tile/grass, null) - floor_tile.New() //I guess New() isn't ran on objects spawned without the definition of a turf to house them, ah well. - icon_state = "grass[pick("1","2","3","4")]" - ..() - spawn(4) - if(src) - update_icon() - for(var/direction in cardinal) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - FF.update_icon() //so siding get updated properly - -/turf/simulated/floor/carpet - name = "Carpet" - icon_state = "carpet" - floor_tile - var/has_siding=1 - -/turf/simulated/floor/carpet/New() - if(floor_tile) - returnToPool(floor_tile) - floor_tile = null - floor_tile = getFromPool(/obj/item/stack/tile/carpet, null) - floor_tile.New() //I guess New() isn't ran on objects spawned without the definition of a turf to house them, ah well. - if(!icon_state) - icon_state = initial(icon_state) - ..() - if(has_siding) - spawn(4) - if(src) - update_icon() - for(var/direction in alldirs) - if(istype(get_step(src,direction),/turf/simulated/floor)) - var/turf/simulated/floor/FF = get_step(src,direction) - FF.update_icon() //so siding get updated properly - -/turf/simulated/floor/carpet/cultify() - return - -/turf/simulated/floor/arcade - name = "Arcade Carpet" - icon_state = "arcade" - floor_tile - -/turf/simulated/floor/arcade/New() - if(floor_tile) - returnToPool(floor_tile) - floor_tile = null - floor_tile = getFromPool(/obj/item/stack/tile/arcade, null) - ..() - -/turf/simulated/floor/plating/ironsand/New() - ..() - name = "Iron Sand" - icon_state = "ironsand[rand(1,15)]" - -/turf/simulated/floor/plating/snow - name = "snow" - icon = 'icons/turf/snow.dmi' - icon_state = "snow" - gender = PLURAL - -/turf/simulated/floor/plating/snow/concrete - name = "concrete" - icon = 'icons/turf/floors.dmi' - icon_state = "concrete" - -/turf/simulated/floor/plating/snow/ex_act(severity) - return - -// VOX SHUTTLE SHIT -/turf/simulated/shuttle/floor/vox - oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON - nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure - //icon = 'icons/turf/shuttle-debug.dmi' - -/turf/simulated/shuttle/plating/vox - oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON - nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure - //icon = 'icons/turf/shuttle-debug.dmi' +/turf/simulated/floor/airless + icon_state = "floor" + name = "airless floor" + oxygen = 0.01 + nitrogen = 0.01 + temperature = TCMB + +/turf/simulated/floor/airless/New() + ..() + name = "floor" + + +/turf/simulated/floor/plating/vox + icon_state = "plating" + name = "vox plating" + //icon = 'icons/turf/shuttle-debug.dmi' + oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON + nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure + +/turf/simulated/floor/plating/vox/New() + ..() + name = "plating" + +/turf/simulated/floor/vox + icon_state = "floor" + name = "vox floor" + //icon = 'icons/turf/shuttle-debug.dmi' + oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON + nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure + +/turf/simulated/floor/vox/New() + ..() + name = "floor" + +/turf/simulated/floor/vox/wood + name = "floor" + icon_state = "wood" + floor_tile + + autoignition_temperature = AUTOIGNITION_WOOD + fire_fuel = 10 + soot_type = null + melt_temperature = 0 // Doesn't melt. + +/turf/simulated/floor/vox/wood/New() + if(floor_tile) + returnToPool(floor_tile) + floor_tile = null + floor_tile = getFromPool(/obj/item/stack/tile/wood, null) + ..() + +/turf/simulated/floor/light + name = "Light floor" + luminosity = 5 + icon_state = "light_on" + floor_tile + +/turf/simulated/floor/light/New() + if(floor_tile) + returnToPool(floor_tile) + floor_tile = null + floor_tile = getFromPool(/obj/item/stack/tile/light, null) + floor_tile.New() //I guess New() isn't run on objects spawned without the definition of a turf to house them, ah well. + var/n = name //just in case commands rename it in the ..() call + ..() + spawn(4) + if(src) + update_icon() + name = n + +/turf/simulated/floor/wood + name = "floor" + icon_state = "wood" + floor_tile + + autoignition_temperature = AUTOIGNITION_WOOD + fire_fuel = 10 + soot_type = null + melt_temperature = 0 // Doesn't melt. + +/turf/simulated/floor/wood/New() + floor_tile = getFromPool(/obj/item/stack/tile/wood,null) + ..() + +/turf/simulated/floor/vault + icon_state = "rockvault" + +/turf/simulated/floor/vault/New(location,type) + ..() + icon_state = "[type]vault" + +/turf/simulated/wall/vault + icon_state = "rockvault" + +/turf/simulated/wall/vault/New(location,type) + ..() + icon_state = "[type]vault" + +/turf/simulated/floor/engine + name = "reinforced floor" + icon_state = "engine" + thermal_conductivity = 0.025 + heat_capacity = 325000 + + soot_type = null + melt_temperature = 0 // Doesn't melt. + +/turf/simulated/floor/engine/attackby(obj/item/weapon/C as obj, mob/user as mob) + if(!C) + return + if(!user) + return + if(istype(C, /obj/item/weapon/wrench)) + to_chat(user, "Removing rods...") + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 80, 1) + if(do_after(user, src, 30) && istype(src, /turf/simulated/floor/engine)) // Somehow changing the turf does NOT kill the current running proc. + new /obj/item/stack/rods(src, 2) + ChangeTurf(/turf/simulated/floor) + var/turf/simulated/floor/F = src + F.make_plating() + return + +/turf/simulated/floor/engine/ex_act(severity) + switch(severity) + if(1.0) + if(prob(80)) + src.ReplaceWithLattice() + else if(prob(50)) + src.ChangeTurf(get_base_turf(src.z)) + else + var/turf/simulated/floor/F = src + F.make_plating() + if(2.0) + if(prob(50)) + var/turf/simulated/floor/F = src + F.make_plating() + else + return + if(3.0) + return + return + +/turf/simulated/floor/engine/cult + name = "engraved floor" + icon_state = "cult" + +/turf/simulated/floor/engine/cult/attack_construct(mob/user as mob) + return 0 + +/turf/simulated/floor/engine/cult/cultify() + return + +/turf/simulated/floor/engine/airless + oxygen = 0.01 + nitrogen = 0.01 + +/turf/simulated/floor/engine/n20 + +/turf/simulated/floor/engine/n20/New() + ..() + if(src.air) + // EXACTLY the same code as fucking roomfillers. If this doesn't work, something's fucked. + var/datum/gas/sleeping_agent/trace_gas = new + air.trace_gases += trace_gas + trace_gas.moles = 9*4000 + air.update_values() + +/turf/simulated/floor/engine/nitrogen + name = "nitrogen floor" + icon_state = "engine" + oxygen=0 + nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure + temperature = TCMB + +/turf/simulated/floor/engine/vacuum + name = "vacuum floor" + icon_state = "engine" + oxygen = 0 + nitrogen = 0.001 + temperature = TCMB + +/turf/simulated/floor/plating + name = "plating" + icon_state = "plating" + intact = 0 + +/turf/simulated/floor/plating/deck + name = "deck" + icon_plating = "deck" + desc = "Children love to play on this deck." + +/turf/simulated/floor/plating/deck/New() + ..() + icon_state = "deck" + +/turf/simulated/floor/plating/deck/update_icon() + icon_plating = "deck" + ..() + if(!floor_tile) + name = "deck" + icon_state = "deck" + desc = "Children love to play on this deck." + else + name = "floor" + desc = null + +/turf/simulated/floor/plating/deck/airless + name = "airless deck" + oxygen = 0.01 + nitrogen = 0.01 + temperature = TCMB + +/turf/simulated/floor/plating/deck/airless/New() + ..() + name = "deck" + +/turf/simulated/floor/plating/New() + ..() + if(floor_tile) + returnToPool(floor_tile) + floor_tile = null + + +/turf/simulated/floor/plating/airless + icon_state = "plating" + name = "airless plating" + oxygen = 0.01 + nitrogen = 0.01 + temperature = TCMB + +/turf/simulated/floor/plating/airless/New() + ..() + name = "plating" + +/turf/simulated/floor/bluegrid + icon = 'icons/turf/floors.dmi' + icon_state = "bcircuit" + +/turf/simulated/floor/greengrid + icon = 'icons/turf/floors.dmi' + icon_state = "gcircuit" + +/turf/simulated/floor/beach + name = "Beach" + icon = 'icons/misc/beach.dmi' + soot_type = null + melt_temperature = 0 // Doesn't melt. + +/turf/simulated/floor/beach/sand + name = "Sand" + icon_state = "sand" + +/turf/simulated/floor/beach/coastline + name = "Coastline" + icon = 'icons/misc/beach2.dmi' + icon_state = "sandwater" + +/turf/simulated/floor/beach/water + name = "Water" + icon_state = "water" + +/turf/simulated/floor/beach/water/New() + ..() + overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1) + +/turf/simulated/floor/grass + name = "Grass patch" + icon_state = "grass1" + floor_tile + +/turf/simulated/floor/grass/New() + if(floor_tile) + returnToPool(floor_tile) + floor_tile = null + floor_tile = getFromPool(/obj/item/stack/tile/grass, null) + floor_tile.New() //I guess New() isn't ran on objects spawned without the definition of a turf to house them, ah well. + icon_state = "grass[pick("1","2","3","4")]" + ..() + spawn(4) + if(src) + update_icon() + for(var/direction in cardinal) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + FF.update_icon() //so siding get updated properly + +/turf/simulated/floor/carpet + name = "Carpet" + icon_state = "carpet" + floor_tile + var/has_siding=1 + +/turf/simulated/floor/carpet/New() + if(floor_tile) + returnToPool(floor_tile) + floor_tile = null + floor_tile = getFromPool(/obj/item/stack/tile/carpet, null) + floor_tile.New() //I guess New() isn't ran on objects spawned without the definition of a turf to house them, ah well. + if(!icon_state) + icon_state = initial(icon_state) + ..() + if(has_siding) + spawn(4) + if(src) + update_icon() + for(var/direction in alldirs) + if(istype(get_step(src,direction),/turf/simulated/floor)) + var/turf/simulated/floor/FF = get_step(src,direction) + FF.update_icon() //so siding get updated properly + +/turf/simulated/floor/carpet/cultify() + return + +/turf/simulated/floor/arcade + name = "Arcade Carpet" + icon_state = "arcade" + floor_tile + +/turf/simulated/floor/arcade/New() + if(floor_tile) + returnToPool(floor_tile) + floor_tile = null + floor_tile = getFromPool(/obj/item/stack/tile/arcade, null) + ..() + +/turf/simulated/floor/plating/ironsand/New() + ..() + name = "Iron Sand" + icon_state = "ironsand[rand(1,15)]" + +/turf/simulated/floor/plating/snow + name = "snow" + icon = 'icons/turf/snow.dmi' + icon_state = "snow" + gender = PLURAL + +/turf/simulated/floor/plating/snow/concrete + name = "concrete" + icon = 'icons/turf/floors.dmi' + icon_state = "concrete" + +/turf/simulated/floor/plating/snow/ex_act(severity) + return + +// VOX SHUTTLE SHIT +/turf/simulated/shuttle/floor/vox + oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON + nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure + //icon = 'icons/turf/shuttle-debug.dmi' + +/turf/simulated/shuttle/plating/vox + oxygen=0 // BIRDS HATE OXYGEN FOR SOME REASON + nitrogen = MOLES_O2STANDARD+MOLES_N2STANDARD // So it totals to the same pressure + //icon = 'icons/turf/shuttle-debug.dmi' diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 7eb5c7aee8a..2028ae075f5 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -1,366 +1,366 @@ -/turf/simulated/wall - name = "wall" - desc = "A huge chunk of metal used to separate rooms." - icon = 'icons/turf/walls.dmi' - var/mineral = "metal" - var/rotting = 0 - opacity = 1 - density = 1 - blocks_air = 1 - - thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT - heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall - - var/walltype = "metal" - var/hardness = 60 //Higher numbers are harder (so that it actually makes sense). Walls are 60 hardness, reinforced walls are 90 hardness. No hardness over 100, PLEASE - var/engraving, engraving_quality //engraving on the wall - var/del_suppress_resmoothing = 0 // Do not resmooth neighbors on Destroy. (smoothwall.dm) - - var/dismantle_type = /turf/simulated/floor/plating - var/girder_type = /obj/structure/girder - - canSmoothWith = "/turf/simulated/wall=0&/obj/structure/falsewall=0&/obj/structure/rfalsewall=0" - - soot_type = null - - explosion_block = 1 - -/turf/simulated/wall/examine(mob/user) - ..() - if(rotting) - to_chat(user, "It is covered in wallrot and looks weakened") - if(thermite) - to_chat(user, "It's doused in thermite!") - if(src.engraving) - to_chat(user, src.engraving) - -/turf/simulated/wall/dismantle_wall(devastated = 0, explode = 0) - if(mineral == "metal") - getFromPool(/obj/item/stack/sheet/metal, src, 2) - else if(mineral == "wood") - getFromPool(/obj/item/stack/sheet/wood, src, 2) - else - var/M = text2path("/obj/item/stack/sheet/mineral/[mineral]") - if(M) - getFromPool(M, src, 2) - - if(devastated) - getFromPool(/obj/item/stack/sheet/metal, src) - else - new girder_type(src) - - for(var/obj/O in src.contents) //Eject contents! - if(istype(O,/obj/structure/sign/poster)) - var/obj/structure/sign/poster/P = O - P.roll_and_drop(src) - - ChangeTurf(dismantle_type) - -/turf/simulated/wall/ex_act(severity) - if(rotting) - severity = 1.0 - switch(severity) - if(1.0) - src.ChangeTurf(get_base_turf(src.z)) //You get NOTHING, you LOSE - return - if(2.0) - if(prob(50)) - dismantle_wall(0,1) - else - dismantle_wall(1,1) - return - if(3.0) - if(prob(40)) - dismantle_wall(0,1) - return - return - -/turf/simulated/wall/mech_drill_act(severity) - return dismantle_wall() - -/turf/simulated/wall/blob_act() - if(prob(50) || rotting) - dismantle_wall() - -/turf/simulated/wall/attack_animal(var/mob/living/simple_animal/M) - M.delayNextAttack(8) - if(M.environment_smash >= 2) - if(istype(src, /turf/simulated/wall/r_wall)) - if(M.environment_smash == 3) - dismantle_wall(1) - M.visible_message("[M] smashes through \the [src].", \ - "You smash through \the [src].") - else - to_chat(M, "This [src] is far too strong for you to destroy.") - else - dismantle_wall(1) - M.visible_message("[M] smashes through \the [src].", \ - "You smash through \the [src].") - return - -/turf/simulated/wall/attack_paw(mob/user as mob) - - return src.attack_hand(user) - -/turf/simulated/wall/attack_hand(mob/user as mob) - user.delayNextAttack(8) - if(M_HULK in user.mutations) - if(prob(100 - hardness) || rotting) - dismantle_wall(1) - user.visible_message("[user] smashes through \the [src].", \ - "You smash through \the [src].") - usr.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - return - else - user.visible_message("[user] punches \the [src].", \ - "You punch \the [src].") - return - - if(rotting) - return src.attack_rotting(user) //Stop there, we aren't slamming our hands on a dirty rotten wall - - user.visible_message("[user] pushes \the [src].", \ - "You push \the [src] but nothing happens!") - playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) - src.add_fingerprint(user) - return ..() - -/turf/simulated/wall/proc/attack_rotting(mob/user as mob) - if(istype(src, /turf/simulated/wall/r_wall)) //I wish I didn't have to do typechecks - to_chat(user, "This [src] feels rather unstable.") - return - else - //Should be a normal wall or a mineral wall, SHOULD - user.visible_message("\The [src] crumbles under [user]'s touch.", \ - "\The [src] crumbles under your touch.") - dismantle_wall() - return - -/turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.delayNextAttack(8) - if (!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - - if(istype(W,/obj/item/weapon/solder) && bullet_marks) - var/obj/item/weapon/solder/S = W - if(!S.remove_fuel(bullet_marks*2,user)) - return - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - to_chat(user, "You remove the bullet marks with \the [W].") - bullet_marks = 0 - icon = initial(icon) - return - - //Get the user's location - if(!istype(user.loc, /turf)) - return //Can't do this stuff whilst inside objects and such - - if(rotting) - if(W.is_hot()) - user.visible_message("[user] burns the fungi away with \the [W].", \ - "You burn the fungi away with \the [W].") - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - rotting = 0 - return - if(istype(W,/obj/item/weapon/soap)) - user.visible_message("[user] forcefully scrubs the fungi away with \the [W].", \ - "You forcefully scrub the fungi away with \the [W].") - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - rotting = 0 - return - else if(!W.is_sharp() && W.force >= 10 || W.force >= 20) - user.visible_message("With one strong swing, [user] destroys the rotting [src] with \the [W].", \ - "With one strong swing, the rotting [src] crumbles away under \the [W].") - src.dismantle_wall(1) - - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff) - message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) broke a rotting wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") - return - - //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects - if(thermite && can_thermite) - if(W.is_hot()) //HEY CAN THIS SET THE THERMITE ON FIRE ? - user.visible_message("[user] applies \the [W] to the thermite coating \the [src] and waits", \ - "You apply \the [W] to the thermite coating \the [src] and wait") - if(do_after(user, src, 100) && W.is_hot()) //Thermite is hard to light up - thermitemelt(user) //There, I just saved you fifty lines of redundant typechecks and awful snowflake coding - user.visible_message("[user] sets \the [src] ablaze with \the [W]", \ - "You set \the [src] ablaze with \the [W]") - return - - //Deconstruction - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - if(engraving) - to_chat(user, "You deform the wall back into its original shape") - engraving = null - engraving_quality = null - playsound(src, 'sound/items/Welder.ogg', 100, 1) - overlays.Cut() - return - user.visible_message("[user] begins slicing through \the [src]'s outer plating.", \ - "You begin slicing through \the [src]'s outer plating.", \ - "You hear welding noises.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 100)) - if(!istype(src)) return - playsound(src, 'sound/items/Welder.ogg', 100, 1) - user.visible_message("[user] slices through \the [src]'s outer plating.", \ - "You slice through \the [src]'s outer plating.", \ - "You hear welding noises.") - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff) - message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) dismanted a wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") - log_admin("[user.real_name] ([user.ckey]) dismanted a wall with a pdiff of [pdiff] at [loc]!") - dismantle_wall() - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - else if(istype(W, /obj/item/weapon/pickaxe)) - var/obj/item/weapon/pickaxe/PK = W - if(!(PK.diggables & DIG_WALLS)) - return - if(mineral == "diamond") //Nigger it's a one meter thick wall made out of diamonds - return - - user.visible_message("[user] begins [PK.drill_verb] straight into \the [src].", \ - "You begin [PK.drill_verb] straight into \the [src].") - playsound(src, PK.drill_sound, 100, 1) - if(do_after(user, src, PK.digspeed * 10)) - user.visible_message("[user]'s [PK] tears though the last of \the [src], leaving nothing but a girder.", \ - "Your [PK] tears though the last of \the [src], leaving nothing but a girder.") - dismantle_wall() - - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff) - message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) dismantled with a pdiff of [pdiff] at [formatJumpTo(loc)]!") - log_admin("[user.real_name] ([user.ckey]) dismantled with a pdiff of [pdiff] at [loc]!") - return - - else if(istype(W, /obj/item/mounted)) //If we place it, we don't want to have a silly message - return - - else - return attack_hand(user) - return - -//Wall-rot effect, a nasty fungus that destroys walls. -//Side effect : Also rots the code of any .dm it's referenced in, until now -/turf/simulated/wall/proc/rot() - if(rotting) //The fuck are you doing ? - return - else - rotting = 1 - var/number_rots = rand(2,3) - for(var/i=0, i < number_rots, i++) - var/obj/effect/overlay/O = new/obj/effect/overlay(src) - O.name = "Wallrot" - O.desc = "Ick..." - O.icon = 'icons/effects/wallrot.dmi' - O.pixel_x += rand(-10, 10) - O.pixel_y += rand(-10, 10) - O.anchored = 1 - O.density = 1 - O.layer = 5 - O.mouse_opacity = 0 - -/turf/simulated/wall/proc/thermitemelt(var/mob/user) - if(mineral == "diamond") - return - var/obj/effect/overlay/O = new/obj/effect/overlay(src) - O.name = "thermite" - O.desc = "Nothing is going to stop it from burning now." - O.icon = 'icons/effects/fire.dmi' - O.icon_state = "2" - O.anchored = 1 - O.density = 1 - O.layer = 5 - - var/cultwall = 0 - if(istype(src, /turf/simulated/wall/cult)) - cultwall = 1 - - if(cultwall) - src.ChangeTurf(/turf/simulated/floor/engine/cult) - else - src.ChangeTurf(/turf/simulated/floor/plating) - - var/turf/simulated/floor/F = src - if(!F) - if(O) - message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) thermited a wall into space at [formatJumpTo(loc)]!") - visible_message("The thermite melts right through \the [src] and the underlying plating, leaving a gaping hole into deep space.") //Good job you big damn hero - qdel(O) - return - F.burn_tile() - F.icon_state = "[cultwall ? "cultwall_thermite" : "wall_thermite"]" - - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff) - message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) thermited a wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") - - hotspot_expose(3000, 125, surfaces = 1) //Only works once when the thermite is created, but else it would need to not be an effect to work - spawn(100) - if(O) - visible_message("\The [O] melts right through \the [src].") - qdel(O) - return - -//Generic wall melting proc. -/turf/simulated/wall/melt() - if(mineral == "diamond") - return - - src.ChangeTurf(/turf/simulated/floor/plating) - - var/turf/simulated/floor/F = src - if(!F) - return - F.burn_tile() - F.icon_state = "wall_thermite" - visible_message("\The [src] spontaenously combusts!.") //!!OH SHIT!! - return - -/turf/simulated/wall/Destroy() - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - ..() - -/turf/simulated/wall/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 1) - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - ..() - -/turf/simulated/wall/cultify() - ChangeTurf(/turf/simulated/wall/cult) - turf_animation('icons/effects/effects.dmi',"cultwall", 0, 0, MOB_LAYER-1) - return - -/turf/simulated/wall/attack_construct(mob/user as mob) - if(istype(user,/mob/living/simple_animal/construct/builder) && (get_dist(src,user) <= 3)) - var/spell/aoe_turf/conjure/wall/S = locate() in user.spell_list - S.perform(user,0,src) - var/obj/screen/spell/SS = S.connected_button - SS.update_charge(1) - return 1 - return 0 - -/turf/simulated/wall/singularity_pull(S, current_size) - if(current_size >= STAGE_FIVE) - if(prob(75)) - dismantle_wall() - return - if(current_size == STAGE_FOUR) - if(prob(30)) - dismantle_wall() +/turf/simulated/wall + name = "wall" + desc = "A huge chunk of metal used to separate rooms." + icon = 'icons/turf/walls.dmi' + var/mineral = "metal" + var/rotting = 0 + opacity = 1 + density = 1 + blocks_air = 1 + + thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT + heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall + + var/walltype = "metal" + var/hardness = 60 //Higher numbers are harder (so that it actually makes sense). Walls are 60 hardness, reinforced walls are 90 hardness. No hardness over 100, PLEASE + var/engraving, engraving_quality //engraving on the wall + var/del_suppress_resmoothing = 0 // Do not resmooth neighbors on Destroy. (smoothwall.dm) + + var/dismantle_type = /turf/simulated/floor/plating + var/girder_type = /obj/structure/girder + + canSmoothWith = "/turf/simulated/wall=0&/obj/structure/falsewall=0&/obj/structure/rfalsewall=0" + + soot_type = null + + explosion_block = 1 + +/turf/simulated/wall/examine(mob/user) + ..() + if(rotting) + to_chat(user, "It is covered in wallrot and looks weakened") + if(thermite) + to_chat(user, "It's doused in thermite!") + if(src.engraving) + to_chat(user, src.engraving) + +/turf/simulated/wall/dismantle_wall(devastated = 0, explode = 0) + if(mineral == "metal") + getFromPool(/obj/item/stack/sheet/metal, src, 2) + else if(mineral == "wood") + getFromPool(/obj/item/stack/sheet/wood, src, 2) + else + var/M = text2path("/obj/item/stack/sheet/mineral/[mineral]") + if(M) + getFromPool(M, src, 2) + + if(devastated) + getFromPool(/obj/item/stack/sheet/metal, src) + else + new girder_type(src) + + for(var/obj/O in src.contents) //Eject contents! + if(istype(O,/obj/structure/sign/poster)) + var/obj/structure/sign/poster/P = O + P.roll_and_drop(src) + + ChangeTurf(dismantle_type) + +/turf/simulated/wall/ex_act(severity) + if(rotting) + severity = 1.0 + switch(severity) + if(1.0) + src.ChangeTurf(get_base_turf(src.z)) //You get NOTHING, you LOSE + return + if(2.0) + if(prob(50)) + dismantle_wall(0,1) + else + dismantle_wall(1,1) + return + if(3.0) + if(prob(40)) + dismantle_wall(0,1) + return + return + +/turf/simulated/wall/mech_drill_act(severity) + return dismantle_wall() + +/turf/simulated/wall/blob_act() + if(prob(50) || rotting) + dismantle_wall() + +/turf/simulated/wall/attack_animal(var/mob/living/simple_animal/M) + M.delayNextAttack(8) + if(M.environment_smash >= 2) + if(istype(src, /turf/simulated/wall/r_wall)) + if(M.environment_smash == 3) + dismantle_wall(1) + M.visible_message("[M] smashes through \the [src].", \ + "You smash through \the [src].") + else + to_chat(M, "This [src] is far too strong for you to destroy.") + else + dismantle_wall(1) + M.visible_message("[M] smashes through \the [src].", \ + "You smash through \the [src].") + return + +/turf/simulated/wall/attack_paw(mob/user as mob) + + return src.attack_hand(user) + +/turf/simulated/wall/attack_hand(mob/user as mob) + user.delayNextAttack(8) + if(M_HULK in user.mutations) + if(prob(100 - hardness) || rotting) + dismantle_wall(1) + user.visible_message("[user] smashes through \the [src].", \ + "You smash through \the [src].") + usr.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + return + else + user.visible_message("[user] punches \the [src].", \ + "You punch \the [src].") + return + + if(rotting) + return src.attack_rotting(user) //Stop there, we aren't slamming our hands on a dirty rotten wall + + user.visible_message("[user] pushes \the [src].", \ + "You push \the [src] but nothing happens!") + playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) + src.add_fingerprint(user) + return ..() + +/turf/simulated/wall/proc/attack_rotting(mob/user as mob) + if(istype(src, /turf/simulated/wall/r_wall)) //I wish I didn't have to do typechecks + to_chat(user, "This [src] feels rather unstable.") + return + else + //Should be a normal wall or a mineral wall, SHOULD + user.visible_message("\The [src] crumbles under [user]'s touch.", \ + "\The [src] crumbles under your touch.") + dismantle_wall() + return + +/turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.delayNextAttack(8) + if (!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + + if(istype(W,/obj/item/weapon/solder) && bullet_marks) + var/obj/item/weapon/solder/S = W + if(!S.remove_fuel(bullet_marks*2,user)) + return + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + to_chat(user, "You remove the bullet marks with \the [W].") + bullet_marks = 0 + icon = initial(icon) + return + + //Get the user's location + if(!istype(user.loc, /turf)) + return //Can't do this stuff whilst inside objects and such + + if(rotting) + if(W.is_hot()) + user.visible_message("[user] burns the fungi away with \the [W].", \ + "You burn the fungi away with \the [W].") + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + rotting = 0 + return + if(istype(W,/obj/item/weapon/soap)) + user.visible_message("[user] forcefully scrubs the fungi away with \the [W].", \ + "You forcefully scrub the fungi away with \the [W].") + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + rotting = 0 + return + else if(!W.is_sharp() && W.force >= 10 || W.force >= 20) + user.visible_message("With one strong swing, [user] destroys the rotting [src] with \the [W].", \ + "With one strong swing, the rotting [src] crumbles away under \the [W].") + src.dismantle_wall(1) + + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff) + message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) broke a rotting wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") + return + + //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects + if(thermite && can_thermite) + if(W.is_hot()) //HEY CAN THIS SET THE THERMITE ON FIRE ? + user.visible_message("[user] applies \the [W] to the thermite coating \the [src] and waits", \ + "You apply \the [W] to the thermite coating \the [src] and wait") + if(do_after(user, src, 100) && W.is_hot()) //Thermite is hard to light up + thermitemelt(user) //There, I just saved you fifty lines of redundant typechecks and awful snowflake coding + user.visible_message("[user] sets \the [src] ablaze with \the [W]", \ + "You set \the [src] ablaze with \the [W]") + return + + //Deconstruction + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + if(engraving) + to_chat(user, "You deform the wall back into its original shape") + engraving = null + engraving_quality = null + playsound(src, 'sound/items/Welder.ogg', 100, 1) + overlays.Cut() + return + user.visible_message("[user] begins slicing through \the [src]'s outer plating.", \ + "You begin slicing through \the [src]'s outer plating.", \ + "You hear welding noises.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 100)) + if(!istype(src)) return + playsound(src, 'sound/items/Welder.ogg', 100, 1) + user.visible_message("[user] slices through \the [src]'s outer plating.", \ + "You slice through \the [src]'s outer plating.", \ + "You hear welding noises.") + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff) + message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) dismanted a wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") + log_admin("[user.real_name] ([user.ckey]) dismanted a wall with a pdiff of [pdiff] at [loc]!") + dismantle_wall() + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + else if(istype(W, /obj/item/weapon/pickaxe)) + var/obj/item/weapon/pickaxe/PK = W + if(!(PK.diggables & DIG_WALLS)) + return + if(mineral == "diamond") //Nigger it's a one meter thick wall made out of diamonds + return + + user.visible_message("[user] begins [PK.drill_verb] straight into \the [src].", \ + "You begin [PK.drill_verb] straight into \the [src].") + playsound(src, PK.drill_sound, 100, 1) + if(do_after(user, src, PK.digspeed * 10)) + user.visible_message("[user]'s [PK] tears though the last of \the [src], leaving nothing but a girder.", \ + "Your [PK] tears though the last of \the [src], leaving nothing but a girder.") + dismantle_wall() + + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff) + message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) dismantled with a pdiff of [pdiff] at [formatJumpTo(loc)]!") + log_admin("[user.real_name] ([user.ckey]) dismantled with a pdiff of [pdiff] at [loc]!") + return + + else if(istype(W, /obj/item/mounted)) //If we place it, we don't want to have a silly message + return + + else + return attack_hand(user) + return + +//Wall-rot effect, a nasty fungus that destroys walls. +//Side effect : Also rots the code of any .dm it's referenced in, until now +/turf/simulated/wall/proc/rot() + if(rotting) //The fuck are you doing ? + return + else + rotting = 1 + var/number_rots = rand(2,3) + for(var/i=0, i < number_rots, i++) + var/obj/effect/overlay/O = new/obj/effect/overlay(src) + O.name = "Wallrot" + O.desc = "Ick..." + O.icon = 'icons/effects/wallrot.dmi' + O.pixel_x += rand(-10, 10) + O.pixel_y += rand(-10, 10) + O.anchored = 1 + O.density = 1 + O.layer = 5 + O.mouse_opacity = 0 + +/turf/simulated/wall/proc/thermitemelt(var/mob/user) + if(mineral == "diamond") + return + var/obj/effect/overlay/O = new/obj/effect/overlay(src) + O.name = "thermite" + O.desc = "Nothing is going to stop it from burning now." + O.icon = 'icons/effects/fire.dmi' + O.icon_state = "2" + O.anchored = 1 + O.density = 1 + O.layer = 5 + + var/cultwall = 0 + if(istype(src, /turf/simulated/wall/cult)) + cultwall = 1 + + if(cultwall) + src.ChangeTurf(/turf/simulated/floor/engine/cult) + else + src.ChangeTurf(/turf/simulated/floor/plating) + + var/turf/simulated/floor/F = src + if(!F) + if(O) + message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) thermited a wall into space at [formatJumpTo(loc)]!") + visible_message("The thermite melts right through \the [src] and the underlying plating, leaving a gaping hole into deep space.") //Good job you big damn hero + qdel(O) + return + F.burn_tile() + F.icon_state = "[cultwall ? "cultwall_thermite" : "wall_thermite"]" + + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff) + message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) thermited a wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") + + hotspot_expose(3000, 125, surfaces = 1) //Only works once when the thermite is created, but else it would need to not be an effect to work + spawn(100) + if(O) + visible_message("\The [O] melts right through \the [src].") + qdel(O) + return + +//Generic wall melting proc. +/turf/simulated/wall/melt() + if(mineral == "diamond") + return + + src.ChangeTurf(/turf/simulated/floor/plating) + + var/turf/simulated/floor/F = src + if(!F) + return + F.burn_tile() + F.icon_state = "wall_thermite" + visible_message("\The [src] spontaenously combusts!.") //!!OH SHIT!! + return + +/turf/simulated/wall/Destroy() + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + ..() + +/turf/simulated/wall/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 1) + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + ..() + +/turf/simulated/wall/cultify() + ChangeTurf(/turf/simulated/wall/cult) + turf_animation('icons/effects/effects.dmi',"cultwall", 0, 0, MOB_LAYER-1) + return + +/turf/simulated/wall/attack_construct(mob/user as mob) + if(istype(user,/mob/living/simple_animal/construct/builder) && (get_dist(src,user) <= 3)) + var/spell/aoe_turf/conjure/wall/S = locate() in user.spell_list + S.perform(user,0,src) + var/obj/screen/spell/SS = S.connected_button + SS.update_charge(1) + return 1 + return 0 + +/turf/simulated/wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(75)) + dismantle_wall() + return + if(current_size == STAGE_FOUR) + if(prob(30)) + dismantle_wall() diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index 14ac32747b2..57d8238080e 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -1,167 +1,167 @@ -/turf/simulated/wall/mineral - name = "mineral wall" - desc = "This shouldn't exist" - icon_state = "" - explosion_block = 1 - var/last_event = 0 - var/active = null - -/turf/simulated/wall/mineral/wood - name = "wooden wall" - desc = "A wall with wooden plating." - icon_state = "wood0" - walltype = "wood" - mineral = "wood" - -/turf/simulated/wall/mineral/gold - name = "gold wall" - desc = "A wall with gold plating. Swag!" - icon_state = "gold0" - walltype = "gold" - mineral = "gold" - //var/electro = 1 - //var/shocked = null - -/turf/simulated/wall/mineral/silver - name = "silver wall" - desc = "A wall with silver plating. Shiny!" - icon_state = "silver0" - walltype = "silver" - mineral = "silver" - //var/electro = 0.75 - //var/shocked = null - -/turf/simulated/wall/mineral/diamond - name = "diamond wall" - desc = "A wall with diamond plating. You monster." - icon_state = "diamond0" - walltype = "diamond" - mineral = "diamond" - explosion_block = 3 - -/turf/simulated/wall/mineral/clown - name = "bananium wall" - desc = "A wall with bananium plating. Honk!" - icon_state = "clown0" - walltype = "clown" - mineral = "clown" - -/turf/simulated/wall/mineral/sandstone - name = "sandstone wall" - desc = "A wall with sandstone plating." - icon_state = "sandstone0" - walltype = "sandstone" - mineral = "sandstone" - explosion_block = 0 - -/turf/simulated/wall/mineral/plastic - name = "plastic wall" - desc = "A wall made of colorful plastic blocks attached together." - icon_state = "plastic0" - walltype = "plastic" - mineral = "plastic" - opacity = 0 - explosion_block = 0 - -/turf/simulated/wall/mineral/uranium - name = "uranium wall" - desc = "A wall with uranium plating. This is probably a bad idea." - icon_state = "uranium0" - walltype = "uranium" - mineral = "uranium" - explosion_block = 2 - -/turf/simulated/wall/mineral/uranium/proc/radiate() - if(!active) - if(world.time > last_event+15) - active = 1 - for(var/mob/living/L in range(3,src)) - L.apply_effect(12,IRRADIATE,0) - for(var/turf/simulated/wall/mineral/uranium/T in range(3,src)) - T.radiate() - last_event = world.time - active = null - return - return - -/turf/simulated/wall/mineral/uranium/attack_hand(mob/user as mob) - radiate() - ..() - -/turf/simulated/wall/mineral/uranium/attackby(obj/item/weapon/W as obj, mob/user as mob) - radiate() - ..() - -/turf/simulated/wall/mineral/uranium/Bumped(AM as mob|obj) - radiate() - ..() - -/turf/simulated/wall/mineral/plasma - name = "plasma wall" - desc = "A wall with plasma plating. This is definately a bad idea." - icon_state = "plasma0" - walltype = "plasma" - mineral = "plasma" - -/turf/simulated/wall/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite - ignite(W.is_hot()) - return - ..() - -/turf/simulated/wall/mineral/plasma/proc/PlasmaBurn(temperature) - var/pdiff=performWallPressureCheck(src.loc) - if(pdiff>0) - message_admins("Plasma wall with pdiff [pdiff] at [formatJumpTo(loc)] just caught fire!") - spawn(2) - new /obj/structure/girder(src) - src.ChangeTurf(/turf/simulated/floor) - for(var/turf/simulated/floor/target_tile in range(0,src)) - /*if(target_tile.parent && target_tile.parent.group_processing) - target_tile.parent.suspend_group_processing()*/ - var/datum/gas_mixture/napalm = new - var/toxinsToDeduce = 20 - napalm.toxins = toxinsToDeduce - napalm.temperature = 400+T0C - target_tile.assume_air(napalm) - spawn (0) target_tile.hotspot_expose(temperature, 400,surfaces=1) - for(var/obj/structure/falsewall/plasma/F in range(3,src))//Hackish as fuck, but until fire_act works, there is nothing I can do -Sieve - var/turf/T = get_turf(F) - T.ChangeTurf(/turf/simulated/wall/mineral/plasma/) - qdel (F) - F = null - for(var/turf/simulated/wall/mineral/plasma/W in range(3,src)) - W.ignite((temperature/4))//Added so that you can't set off a massive chain reaction with a small flame - for(var/obj/machinery/door/airlock/plasma/D in range(3,src)) - D.ignite(temperature/4) - -/turf/simulated/wall/mineral/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)//Doesn't fucking work because walls don't interact with air :( - if(exposed_temperature > 300) - PlasmaBurn(exposed_temperature) - -/turf/simulated/wall/mineral/plasma/ignite(exposed_temperature) - if(exposed_temperature > 300) - PlasmaBurn(exposed_temperature) - -/turf/simulated/wall/mineral/plasma/bullet_act(var/obj/item/projectile/Proj) - if(istype(Proj,/obj/item/projectile/beam)) - PlasmaBurn(2500) - else if(istype(Proj,/obj/item/projectile/ion)) - PlasmaBurn(500) - ..() - -/* -/turf/simulated/wall/mineral/proc/shock() - if (electrocute_mob(user, C, src)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - return 1 - else - return 0 - -/turf/simulated/wall/mineral/proc/attackby(obj/item/weapon/W as obj, mob/user as mob) - if((mineral == "gold") || (mineral == "silver")) - if(shocked) - shock() -*/ +/turf/simulated/wall/mineral + name = "mineral wall" + desc = "This shouldn't exist" + icon_state = "" + explosion_block = 1 + var/last_event = 0 + var/active = null + +/turf/simulated/wall/mineral/wood + name = "wooden wall" + desc = "A wall with wooden plating." + icon_state = "wood0" + walltype = "wood" + mineral = "wood" + +/turf/simulated/wall/mineral/gold + name = "gold wall" + desc = "A wall with gold plating. Swag!" + icon_state = "gold0" + walltype = "gold" + mineral = "gold" + //var/electro = 1 + //var/shocked = null + +/turf/simulated/wall/mineral/silver + name = "silver wall" + desc = "A wall with silver plating. Shiny!" + icon_state = "silver0" + walltype = "silver" + mineral = "silver" + //var/electro = 0.75 + //var/shocked = null + +/turf/simulated/wall/mineral/diamond + name = "diamond wall" + desc = "A wall with diamond plating. You monster." + icon_state = "diamond0" + walltype = "diamond" + mineral = "diamond" + explosion_block = 3 + +/turf/simulated/wall/mineral/clown + name = "bananium wall" + desc = "A wall with bananium plating. Honk!" + icon_state = "clown0" + walltype = "clown" + mineral = "clown" + +/turf/simulated/wall/mineral/sandstone + name = "sandstone wall" + desc = "A wall with sandstone plating." + icon_state = "sandstone0" + walltype = "sandstone" + mineral = "sandstone" + explosion_block = 0 + +/turf/simulated/wall/mineral/plastic + name = "plastic wall" + desc = "A wall made of colorful plastic blocks attached together." + icon_state = "plastic0" + walltype = "plastic" + mineral = "plastic" + opacity = 0 + explosion_block = 0 + +/turf/simulated/wall/mineral/uranium + name = "uranium wall" + desc = "A wall with uranium plating. This is probably a bad idea." + icon_state = "uranium0" + walltype = "uranium" + mineral = "uranium" + explosion_block = 2 + +/turf/simulated/wall/mineral/uranium/proc/radiate() + if(!active) + if(world.time > last_event+15) + active = 1 + for(var/mob/living/L in range(3,src)) + L.apply_effect(12,IRRADIATE,0) + for(var/turf/simulated/wall/mineral/uranium/T in range(3,src)) + T.radiate() + last_event = world.time + active = null + return + return + +/turf/simulated/wall/mineral/uranium/attack_hand(mob/user as mob) + radiate() + ..() + +/turf/simulated/wall/mineral/uranium/attackby(obj/item/weapon/W as obj, mob/user as mob) + radiate() + ..() + +/turf/simulated/wall/mineral/uranium/Bumped(AM as mob|obj) + radiate() + ..() + +/turf/simulated/wall/mineral/plasma + name = "plasma wall" + desc = "A wall with plasma plating. This is definately a bad idea." + icon_state = "plasma0" + walltype = "plasma" + mineral = "plasma" + +/turf/simulated/wall/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite + ignite(W.is_hot()) + return + ..() + +/turf/simulated/wall/mineral/plasma/proc/PlasmaBurn(temperature) + var/pdiff=performWallPressureCheck(src.loc) + if(pdiff>0) + message_admins("Plasma wall with pdiff [pdiff] at [formatJumpTo(loc)] just caught fire!") + spawn(2) + new /obj/structure/girder(src) + src.ChangeTurf(/turf/simulated/floor) + for(var/turf/simulated/floor/target_tile in range(0,src)) + /*if(target_tile.parent && target_tile.parent.group_processing) + target_tile.parent.suspend_group_processing()*/ + var/datum/gas_mixture/napalm = new + var/toxinsToDeduce = 20 + napalm.toxins = toxinsToDeduce + napalm.temperature = 400+T0C + target_tile.assume_air(napalm) + spawn (0) target_tile.hotspot_expose(temperature, 400,surfaces=1) + for(var/obj/structure/falsewall/plasma/F in range(3,src))//Hackish as fuck, but until fire_act works, there is nothing I can do -Sieve + var/turf/T = get_turf(F) + T.ChangeTurf(/turf/simulated/wall/mineral/plasma/) + qdel (F) + F = null + for(var/turf/simulated/wall/mineral/plasma/W in range(3,src)) + W.ignite((temperature/4))//Added so that you can't set off a massive chain reaction with a small flame + for(var/obj/machinery/door/airlock/plasma/D in range(3,src)) + D.ignite(temperature/4) + +/turf/simulated/wall/mineral/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)//Doesn't fucking work because walls don't interact with air :( + if(exposed_temperature > 300) + PlasmaBurn(exposed_temperature) + +/turf/simulated/wall/mineral/plasma/ignite(exposed_temperature) + if(exposed_temperature > 300) + PlasmaBurn(exposed_temperature) + +/turf/simulated/wall/mineral/plasma/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj,/obj/item/projectile/beam)) + PlasmaBurn(2500) + else if(istype(Proj,/obj/item/projectile/ion)) + PlasmaBurn(500) + ..() + +/* +/turf/simulated/wall/mineral/proc/shock() + if (electrocute_mob(user, C, src)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return 1 + else + return 0 + +/turf/simulated/wall/mineral/proc/attackby(obj/item/weapon/W as obj, mob/user as mob) + if((mineral == "gold") || (mineral == "silver")) + if(shocked) + shock() +*/ diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm index ad8e8b018aa..125b227fce4 100644 --- a/code/game/turfs/simulated/walls_misc.dm +++ b/code/game/turfs/simulated/walls_misc.dm @@ -1,32 +1,32 @@ -/turf/simulated/wall/cult - name = "wall" - desc = "The patterns engraved on the wall seem to shift as you try to focus on them. You feel sick" - icon_state = "cult" - walltype = "cult" - dismantle_type = /turf/simulated/floor/engine/cult - girder_type = /obj/structure/cultgirder - -/turf/simulated/wall/cult/cultify() - return - -/turf/simulated/wall/cult/dismantle_wall(devastated = 0, explode = 0) - if(!devastated) - getFromPool(/obj/effect/decal/cleanable/blood, src) - new girder_type(src) - else - if(prob(10)) - getFromPool(/obj/effect/decal/cleanable/blood, src) - // new /obj/effect/decal/remains/human(src) //Commented out until remains are cleanable - - for(var/obj/O in src.contents) //Eject contents! - if(istype(O,/obj/structure/sign/poster)) - var/obj/structure/sign/poster/P = O - P.roll_and_drop(src) - - ChangeTurf(dismantle_type) - -/turf/simulated/wall/cult/attack_construct(mob/user as mob) - if(istype(user,/mob/living/simple_animal/construct/builder) && user.Adjacent(src)) - dismantle_wall(1) - return 1 - return 0 +/turf/simulated/wall/cult + name = "wall" + desc = "The patterns engraved on the wall seem to shift as you try to focus on them. You feel sick" + icon_state = "cult" + walltype = "cult" + dismantle_type = /turf/simulated/floor/engine/cult + girder_type = /obj/structure/cultgirder + +/turf/simulated/wall/cult/cultify() + return + +/turf/simulated/wall/cult/dismantle_wall(devastated = 0, explode = 0) + if(!devastated) + getFromPool(/obj/effect/decal/cleanable/blood, src) + new girder_type(src) + else + if(prob(10)) + getFromPool(/obj/effect/decal/cleanable/blood, src) + // new /obj/effect/decal/remains/human(src) //Commented out until remains are cleanable + + for(var/obj/O in src.contents) //Eject contents! + if(istype(O,/obj/structure/sign/poster)) + var/obj/structure/sign/poster/P = O + P.roll_and_drop(src) + + ChangeTurf(dismantle_type) + +/turf/simulated/wall/cult/attack_construct(mob/user as mob) + if(istype(user,/mob/living/simple_animal/construct/builder) && user.Adjacent(src)) + dismantle_wall(1) + return 1 + return 0 diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index 68e85261294..23e9184823e 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -1,436 +1,436 @@ -#define WALLCOMPLETED 0 -#define WALLCOVEREXPOSED 1 -#define WALLCOVERUNSECURED 2 -#define WALLCOVERWEAKENED 3 -#define WALLCOVERREMOVED 4 -#define WALLRODSUNSECURED 5 -#define WALLRODSCUT 6 -/turf/simulated/wall/r_wall - name = "reinforced wall" - desc = "A huge chunk of reinforced metal and anchored rods used to seperate rooms and keep all but the most equipped crewmen out." - icon_state = "r_wall" - opacity = 1 - density = 1 - - walltype = "rwall" - hardness = 90 - - explosion_block = 2 - girder_type = /obj/structure/girder/reinforced - - penetration_dampening = 20 - - var/d_state = WALLCOMPLETED - -/turf/simulated/wall/r_wall/examine(mob/user) - ..() - if(d_state) - switch(d_state) //How fucked or unfinished is our wall - if(WALLCOVEREXPOSED) - to_chat(user, "It has no outer grille") - if(WALLCOVERUNSECURED) - to_chat(user, "It has no outer grille and the external reinforced cover is exposed") - if(WALLCOVERWEAKENED) - to_chat(user, "It has no outer grille and the external reinforced cover has been welded into") - if(WALLCOVERREMOVED) - to_chat(user, "It has no outer grille or external reinforced cover and the external support rods are exposed") - if(WALLRODSUNSECURED) - to_chat(user, "It has no outer grille or external reinforced cover and the external support rods are loose") - if(WALLRODSCUT) - to_chat(user, "It has no outer grille, external reinforced cover or external support rods and the inner reinforced cover is exposed")//And that's terrible - - -//We need to export this here because we want to handle it differently -//This took me longer to find this than it should havle -/turf/simulated/wall/r_wall/relativewall() - if(d_state) //We are fucking building - return //Fuck off - ..() - -/turf/simulated/wall/r_wall/update_icon() - if(!d_state) //Are we under construction or deconstruction ? - relativewall() //Well isn't that odd, let's pass this to smoothwall.dm - relativewall_neighbours() //Let's make sure the other walls know about this travesty - return //Now fuck off - icon_state = "r_wall-[d_state]" //You can thank me later - -/turf/simulated/wall/r_wall/attackby(obj/item/W as obj, mob/user as mob) - - if (!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to do this!") - return - - if(istype(W,/obj/item/weapon/solder) && bullet_marks) - var/obj/item/weapon/solder/S = W - if(!S.remove_fuel(bullet_marks*2,user)) - return - playsound(loc, 'sound/items/Welder.ogg', 100, 1) - to_chat(user, "You remove the bullet marks with \the [W].") - bullet_marks = 0 - icon = initial(icon) - return - - //Get the user's location - if(!istype(user.loc, /turf)) - return //Can't do this stuff whilst inside objects and such //Thanks BYOND - - if(rotting) - if(W.is_hot()) //Yes, you can do it with a welding tool, or a lighter, or a candle, or an energy sword - user.visible_message("[user] burns the fungi away with \the [W].", \ - "You burn the fungi away with \the [W].") - playsound(src, 'sound/items/Welder.ogg', 10, 1) - for(var/obj/effect/E in src) //WHYYYY - if(E.name == "Wallrot") //WHYYYYYYYYY - qdel(E) - rotting = 0 - return - if(istype(W,/obj/item/weapon/soap)) - user.visible_message("[user] forcefully scrubs the fungi away with \the [W].", \ - "You forcefully scrub the fungi away with \the [W].") - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - rotting = 0 - return - else if(!W.is_sharp() && W.force >= 10 || W.force >= 20) - user.visible_message("With one strong swing, [user] destroys the rotting [src] with \the [W].", \ - "With one strong swing, the rotting [src] crumbles away under \the [W].") - src.dismantle_wall() - - var/pdiff = performWallPressureCheck(src.loc) - if(pdiff) - message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) broke a rotting reinforced wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") - return - - //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects - if(thermite && can_thermite) - if(W.is_hot()) //HEY CAN THIS SET THE THERMITE ON FIRE ? - user.visible_message("[user] applies \the [W] to the thermite coating \the [src] and waits.", \ - "You apply \the [W] to the thermite coating \the [src] and wait...") - if(do_after(user, src, 100) && W.is_hot()) //Thermite is hard to light up - thermitemelt(user) //There, I just saved you fifty lines of redundant typechecks and awful snowflake coding - user.visible_message("[user] sets \the [src] ablaze with \the [W]!", \ - "You set \the [src] ablaze with \the [W]!") - return - - //Deconstruction and reconstruction - switch(d_state) - if(WALLCOMPLETED) - if(istype(W, /obj/item/weapon/wirecutters)) - playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) - src.d_state = WALLCOVEREXPOSED - update_icon() - user.visible_message("[user] cuts out \the [src]'s outer grille.", \ - "You cut out \the [src]'s outer grille, exposing the external cover.") - return - - if(WALLCOVEREXPOSED) - if(istype(W, /obj/item/weapon/screwdriver)) - user.visible_message("[user] begins unsecuring \the [src]'s external cover.", \ - "You begin unsecuring \the [src]'s external cover.") - playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) - - if(do_after(user, src, 40) && d_state == WALLCOVEREXPOSED) - src.d_state = WALLCOVERUNSECURED - update_icon() - user.visible_message("[user] unsecures \the [src]'s external cover.", \ - "You unsecure \the [src]'s external cover.") - return - - //Repairing outer grille, use welding tool - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - user.visible_message("[user] begins mending the damage on \the [src]'s outer grille.", \ - "You begin mending the damage on \the [src]'s outer grille.", \ - "You hear welding noises.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - if(do_after(user, src, 40) && d_state == WALLCOVEREXPOSED) - playsound(src, 'sound/items/Welder.ogg', 100, 1) - src.d_state = WALLCOMPLETED - update_icon() - user.visible_message("[user] mends the damage on \the [src]'s outer grille.", \ - "You mend the damage on \the [src]'s outer grille.", \ - "You hear welding noises.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(WALLCOVERUNSECURED) - if(istype(W, /obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - user.visible_message("[user] begins slicing through \the [src]'s external cover.", \ - "You begin slicing through \the [src]'s external cover.", \ - "You hear welding noises.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 60) && d_state == WALLCOVERUNSECURED) - playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again - src.d_state = WALLCOVERWEAKENED - update_icon() - user.visible_message("[user] finishes weakening \the [src]'s external cover.", \ - "You finish weakening \the [src]'s external cover.", \ - "You hear welding noises.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) //Ah, snowflake coding, my favorite - - user.visible_message("[user] begins slicing through \the [src]'s external cover.", \ - "You begin slicing through \the [src]'s external cover.", \ - "You hear welding noises.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 40) && d_state == WALLCOVERUNSECURED) - playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again - src.d_state = WALLCOVERWEAKENED - update_icon() - user.visible_message("[user] finishes weakening \the [src]'s external cover.", \ - "You finish weakening \the [src]'s external cover.", \ - "You hear welding noises.") - return - - //Re-secure external cover, unsurprisingly exact same step as above - else if(istype(W, /obj/item/weapon/screwdriver)) - user.visible_message("[user] begins securing \the [src]'s external cover.", \ - "You begin securing \the [src]'s external cover.") - playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) - - if(do_after(user, src, 40) && d_state == WALLCOVERUNSECURED) - src.d_state = WALLCOVEREXPOSED - update_icon() - user.visible_message("[user] secures \the [src]'s external cover.", \ - "You secure \the [src]'s external cover.") - return - - if(WALLCOVERWEAKENED) - if(istype(W, /obj/item/weapon/crowbar)) - - user.visible_message("[user] starts prying off \the [src]'s external cover.", \ - "You struggle to pry off \the [src]'s external cover.", \ - "You hear a crowbar.") - playsound(src, 'sound/items/Crowbar.ogg', 100, 1) - - if(do_after(user, src, 100) && d_state == WALLCOVERWEAKENED) - playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) //SLAM - src.d_state = WALLCOVERREMOVED - update_icon() - getFromPool(/obj/item/stack/sheet/plasteel, get_turf(src)) - user.visible_message("[user] pries off \the [src]'s external cover.", \ - "You pry off \the [src]'s external cover.") - return - - //Fix welding damage caused above, by welding shit into place again - else if(istype(W, /obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - user.visible_message("[user] begins fixing the welding damage on \the [src]'s external cover.", \ - "You begin fixing the welding damage on \the [src]'s external cover.", \ - "You hear welding noises.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 60) && d_state == WALLCOVERWEAKENED) - playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again - src.d_state = WALLCOVERUNSECURED - update_icon() - user.visible_message("[user] fixes the welding damage on \the [src]'s external cover.", \ - "You fix the welding damage on \the [src]'s external cover.", \ - "You hear welding noises.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(WALLCOVERREMOVED) - if(istype(W, /obj/item/weapon/wrench)) - - user.visible_message("[user] starts loosening the bolts anchoring \the [src]'s external support rods.", \ - "You start loosening the bolts anchoring \the [src]'s external support rods.") - playsound(src, 'sound/items/Ratchet.ogg', 100, 1) - - if(do_after(user, src, 40) && d_state == WALLCOVERREMOVED) - src.d_state = WALLRODSUNSECURED - update_icon() - user.visible_message("[user] loosens the bolts anchoring \the [src]'s external support rods.", \ - "You loosen the bolts anchoring \the [src]'s external support rods.") - return - - //Only construction step after reinforced girder, add the second plasteel sheet - //Acts as a super repair step, incidentally, if there's clearly more than cover damage - else if(istype(W, /obj/item/stack/sheet/plasteel)) - var/obj/item/stack/sheet/plasteel/P = W - user.visible_message("[user] starts installing an external cover to \the [src].", \ - "You start installing an external cover to \the [src].") - playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) - - if(do_after(user, src, 50) && d_state == WALLCOVERREMOVED) - P.use(1) - src.d_state = WALLCOMPLETED //A new pristine reinforced cover, we are done here - update_icon() - user.visible_message("[user] finishes installing an external cover to \the [src].", \ - "You finish installing an external cover to \the [src].") - return - - if(WALLRODSUNSECURED) - if(istype(W, /obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - user.visible_message("[user] begins slicing through \the [src]'s external support rods.", \ - "You begin slicing through \the [src]'s external support rods.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 100) && d_state == WALLRODSUNSECURED) - playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again - src.d_state = WALLRODSCUT - update_icon() - user.visible_message("[user] slices through \the [src]'s external support rods.", \ - "You slice through \the [src]'s external support rods, exposing its internal cover.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - - user.visible_message("[user] begins slicing through \the [src]'s external support rods.", \ - "You begin slicing through \the [src]'s external support rods.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 70)) - playsound(src, 'sound/items/Welder.ogg', 100, 1) - src.d_state = WALLRODSCUT - update_icon() - user.visible_message("[user] slices through \the [src]'s external support rods.", \ - "You slice through \the [src]'s external support rods, exposing its internal cover.") - return - - //Repair step, tighten the anchoring bolts - else if(istype(W, /obj/item/weapon/wrench)) - - user.visible_message("[user] starts tightening the bolts anchoring \the [src]'s external support rods.", \ - "You start tightening the bolts anchoring \the [src]'s external support rods.") - playsound(src, 'sound/items/Ratchet.ogg', 100, 1) - - if(do_after(user, src, 40) && d_state == WALLRODSUNSECURED) - src.d_state = WALLCOVERREMOVED - update_icon() - user.visible_message("[user] tightens the bolts anchoring \the [src]'s external support rods.", \ - "You tighten the bolts anchoring \the [src]'s external support rods.") - return - - if(WALLRODSCUT) - if(istype(W, /obj/item/weapon/crowbar)) - - user.visible_message("[user] starts prying off [src]'s internal cover.", \ - "You struggle to pry off [src]'s internal cover.") - playsound(src, 'sound/items/Crowbar.ogg', 100, 1) - - if(do_after(user, src, 100) && d_state == WALLRODSCUT) - user.visible_message("[user] pries off [src]'s internal cover.", \ - "You pry off [src]'s internal cover.") - dismantle_wall() //Mr. Engineer, break down that reinforced wall - playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) - return - - //Repair the external support rods welded through in the previous step, with a welding tool. Naturally - else if(istype(W, /obj/item/weapon/weldingtool)) - - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - user.visible_message("[user] begins mending \the [src]'s external support rods.", \ - "You begin mending \the [src]'s external support rods.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user, src, 100) && d_state == WALLRODSCUT) - playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again - src.d_state = WALLRODSUNSECURED - update_icon() - user.visible_message("[user] mends \the [src]'s external support rods.", \ - "You mend \the [src]'s external support rods.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - -//This is where we perform actions that aren't deconstructing, constructing or thermiting the reinforced wall - - //Drilling - //Needs a diamond drill or equivalent - if(istype(W, /obj/item/weapon/pickaxe)) - - var/obj/item/weapon/pickaxe/PK = W - if(!(PK.diggables & DIG_RWALLS)) - return - - user.visible_message("[user] begins [PK.drill_verb] straight into \the [src].", \ - "You begin [PK.drill_verb] straight into \the [src].") - playsound(src, PK.drill_sound, 100, 1) - if(do_after(user, src, PK.digspeed * 50)) - user.visible_message("[user]'s [PK] tears though the last of \the [src], leaving nothing but a girder.", \ - "Your [PK] tears though the last of \the [src], leaving nothing but a girder.") - dismantle_wall() - return - - else if(istype(W, /obj/item/mounted)) - return - - //Finally, CHECKING FOR FALSE WALLS if it isn't damaged - //This is obsolete since reinforced false walls were commented out, but gotta slap the wall with my hand anyways ! - else if(!d_state) - return attack_hand(user) - return - -/turf/simulated/wall/r_wall/attack_construct(mob/user as mob) - return 0 - -/turf/simulated/wall/r_wall/singularity_pull(S, current_size) - if(current_size >= STAGE_FIVE) - if(prob(30)) - dismantle_wall() - -/turf/simulated/wall/r_wall/dismantle_wall(devastated = 0, explode = 0) - if(!devastated) - getFromPool(/obj/item/stack/sheet/plasteel, src)//Reinforced girder has deconstruction steps too. If no girder, drop ONE plasteel sheet AND rods - else - getFromPool(/obj/item/stack/rods, src, 2) - getFromPool(/obj/item/stack/sheet/plasteel, src) - - for(var/obj/O in src.contents) //Eject contents! - if(istype(O,/obj/structure/sign/poster)) - var/obj/structure/sign/poster/P = O - P.roll_and_drop(src) - - ChangeTurf(dismantle_type) - -/turf/simulated/wall/r_wall/ex_act(severity) - if(rotting) - severity = 1.0 - switch(severity) - if(1.0) - if(prob(66)) //It's "bomb-proof" - dismantle_wall(0,1) //So it isn't completely destroyed, nice uh ? - else - dismantle_wall(1,1) //Fuck it up nicely - if(2.0) - if(prob(75) && (d_state == WALLCOMPLETED))//No more infinite plasteel generation! - src.d_state = WALLCOVERREMOVED - update_icon() - getFromPool(/obj/item/stack/sheet/plasteel, get_turf(src)) //Lose the plasteel needed to get there - else - dismantle_wall(0,1) - if(3.0) - if(prob(15)) - dismantle_wall(0,1) - else //If prob fails, break the outer safety grille to look like scrap damage - src.d_state = WALLCOVEREXPOSED - update_icon() - return -#undef WALLCOMPLETED -#undef WALLCOVEREXPOSED -#undef WALLCOVERUNSECURED -#undef WALLCOVERWEAKENED -#undef WALLCOVERREMOVED -#undef WALLRODSUNSECURED -#undef WALLRODSCUT +#define WALLCOMPLETED 0 +#define WALLCOVEREXPOSED 1 +#define WALLCOVERUNSECURED 2 +#define WALLCOVERWEAKENED 3 +#define WALLCOVERREMOVED 4 +#define WALLRODSUNSECURED 5 +#define WALLRODSCUT 6 +/turf/simulated/wall/r_wall + name = "reinforced wall" + desc = "A huge chunk of reinforced metal and anchored rods used to seperate rooms and keep all but the most equipped crewmen out." + icon_state = "r_wall" + opacity = 1 + density = 1 + + walltype = "rwall" + hardness = 90 + + explosion_block = 2 + girder_type = /obj/structure/girder/reinforced + + penetration_dampening = 20 + + var/d_state = WALLCOMPLETED + +/turf/simulated/wall/r_wall/examine(mob/user) + ..() + if(d_state) + switch(d_state) //How fucked or unfinished is our wall + if(WALLCOVEREXPOSED) + to_chat(user, "It has no outer grille") + if(WALLCOVERUNSECURED) + to_chat(user, "It has no outer grille and the external reinforced cover is exposed") + if(WALLCOVERWEAKENED) + to_chat(user, "It has no outer grille and the external reinforced cover has been welded into") + if(WALLCOVERREMOVED) + to_chat(user, "It has no outer grille or external reinforced cover and the external support rods are exposed") + if(WALLRODSUNSECURED) + to_chat(user, "It has no outer grille or external reinforced cover and the external support rods are loose") + if(WALLRODSCUT) + to_chat(user, "It has no outer grille, external reinforced cover or external support rods and the inner reinforced cover is exposed")//And that's terrible + + +//We need to export this here because we want to handle it differently +//This took me longer to find this than it should havle +/turf/simulated/wall/r_wall/relativewall() + if(d_state) //We are fucking building + return //Fuck off + ..() + +/turf/simulated/wall/r_wall/update_icon() + if(!d_state) //Are we under construction or deconstruction ? + relativewall() //Well isn't that odd, let's pass this to smoothwall.dm + relativewall_neighbours() //Let's make sure the other walls know about this travesty + return //Now fuck off + icon_state = "r_wall-[d_state]" //You can thank me later + +/turf/simulated/wall/r_wall/attackby(obj/item/W as obj, mob/user as mob) + + if (!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + + if(istype(W,/obj/item/weapon/solder) && bullet_marks) + var/obj/item/weapon/solder/S = W + if(!S.remove_fuel(bullet_marks*2,user)) + return + playsound(loc, 'sound/items/Welder.ogg', 100, 1) + to_chat(user, "You remove the bullet marks with \the [W].") + bullet_marks = 0 + icon = initial(icon) + return + + //Get the user's location + if(!istype(user.loc, /turf)) + return //Can't do this stuff whilst inside objects and such //Thanks BYOND + + if(rotting) + if(W.is_hot()) //Yes, you can do it with a welding tool, or a lighter, or a candle, or an energy sword + user.visible_message("[user] burns the fungi away with \the [W].", \ + "You burn the fungi away with \the [W].") + playsound(src, 'sound/items/Welder.ogg', 10, 1) + for(var/obj/effect/E in src) //WHYYYY + if(E.name == "Wallrot") //WHYYYYYYYYY + qdel(E) + rotting = 0 + return + if(istype(W,/obj/item/weapon/soap)) + user.visible_message("[user] forcefully scrubs the fungi away with \the [W].", \ + "You forcefully scrub the fungi away with \the [W].") + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + rotting = 0 + return + else if(!W.is_sharp() && W.force >= 10 || W.force >= 20) + user.visible_message("With one strong swing, [user] destroys the rotting [src] with \the [W].", \ + "With one strong swing, the rotting [src] crumbles away under \the [W].") + src.dismantle_wall() + + var/pdiff = performWallPressureCheck(src.loc) + if(pdiff) + message_admins("[user.real_name] ([formatPlayerPanel(user,user.ckey)]) broke a rotting reinforced wall with a pdiff of [pdiff] at [formatJumpTo(loc)]!") + return + + //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects + if(thermite && can_thermite) + if(W.is_hot()) //HEY CAN THIS SET THE THERMITE ON FIRE ? + user.visible_message("[user] applies \the [W] to the thermite coating \the [src] and waits.", \ + "You apply \the [W] to the thermite coating \the [src] and wait...") + if(do_after(user, src, 100) && W.is_hot()) //Thermite is hard to light up + thermitemelt(user) //There, I just saved you fifty lines of redundant typechecks and awful snowflake coding + user.visible_message("[user] sets \the [src] ablaze with \the [W]!", \ + "You set \the [src] ablaze with \the [W]!") + return + + //Deconstruction and reconstruction + switch(d_state) + if(WALLCOMPLETED) + if(istype(W, /obj/item/weapon/wirecutters)) + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) + src.d_state = WALLCOVEREXPOSED + update_icon() + user.visible_message("[user] cuts out \the [src]'s outer grille.", \ + "You cut out \the [src]'s outer grille, exposing the external cover.") + return + + if(WALLCOVEREXPOSED) + if(istype(W, /obj/item/weapon/screwdriver)) + user.visible_message("[user] begins unsecuring \the [src]'s external cover.", \ + "You begin unsecuring \the [src]'s external cover.") + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) + + if(do_after(user, src, 40) && d_state == WALLCOVEREXPOSED) + src.d_state = WALLCOVERUNSECURED + update_icon() + user.visible_message("[user] unsecures \the [src]'s external cover.", \ + "You unsecure \the [src]'s external cover.") + return + + //Repairing outer grille, use welding tool + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + user.visible_message("[user] begins mending the damage on \the [src]'s outer grille.", \ + "You begin mending the damage on \the [src]'s outer grille.", \ + "You hear welding noises.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + if(do_after(user, src, 40) && d_state == WALLCOVEREXPOSED) + playsound(src, 'sound/items/Welder.ogg', 100, 1) + src.d_state = WALLCOMPLETED + update_icon() + user.visible_message("[user] mends the damage on \the [src]'s outer grille.", \ + "You mend the damage on \the [src]'s outer grille.", \ + "You hear welding noises.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(WALLCOVERUNSECURED) + if(istype(W, /obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + user.visible_message("[user] begins slicing through \the [src]'s external cover.", \ + "You begin slicing through \the [src]'s external cover.", \ + "You hear welding noises.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 60) && d_state == WALLCOVERUNSECURED) + playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again + src.d_state = WALLCOVERWEAKENED + update_icon() + user.visible_message("[user] finishes weakening \the [src]'s external cover.", \ + "You finish weakening \the [src]'s external cover.", \ + "You hear welding noises.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) //Ah, snowflake coding, my favorite + + user.visible_message("[user] begins slicing through \the [src]'s external cover.", \ + "You begin slicing through \the [src]'s external cover.", \ + "You hear welding noises.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 40) && d_state == WALLCOVERUNSECURED) + playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again + src.d_state = WALLCOVERWEAKENED + update_icon() + user.visible_message("[user] finishes weakening \the [src]'s external cover.", \ + "You finish weakening \the [src]'s external cover.", \ + "You hear welding noises.") + return + + //Re-secure external cover, unsurprisingly exact same step as above + else if(istype(W, /obj/item/weapon/screwdriver)) + user.visible_message("[user] begins securing \the [src]'s external cover.", \ + "You begin securing \the [src]'s external cover.") + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) + + if(do_after(user, src, 40) && d_state == WALLCOVERUNSECURED) + src.d_state = WALLCOVEREXPOSED + update_icon() + user.visible_message("[user] secures \the [src]'s external cover.", \ + "You secure \the [src]'s external cover.") + return + + if(WALLCOVERWEAKENED) + if(istype(W, /obj/item/weapon/crowbar)) + + user.visible_message("[user] starts prying off \the [src]'s external cover.", \ + "You struggle to pry off \the [src]'s external cover.", \ + "You hear a crowbar.") + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) + + if(do_after(user, src, 100) && d_state == WALLCOVERWEAKENED) + playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) //SLAM + src.d_state = WALLCOVERREMOVED + update_icon() + getFromPool(/obj/item/stack/sheet/plasteel, get_turf(src)) + user.visible_message("[user] pries off \the [src]'s external cover.", \ + "You pry off \the [src]'s external cover.") + return + + //Fix welding damage caused above, by welding shit into place again + else if(istype(W, /obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + user.visible_message("[user] begins fixing the welding damage on \the [src]'s external cover.", \ + "You begin fixing the welding damage on \the [src]'s external cover.", \ + "You hear welding noises.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 60) && d_state == WALLCOVERWEAKENED) + playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again + src.d_state = WALLCOVERUNSECURED + update_icon() + user.visible_message("[user] fixes the welding damage on \the [src]'s external cover.", \ + "You fix the welding damage on \the [src]'s external cover.", \ + "You hear welding noises.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(WALLCOVERREMOVED) + if(istype(W, /obj/item/weapon/wrench)) + + user.visible_message("[user] starts loosening the bolts anchoring \the [src]'s external support rods.", \ + "You start loosening the bolts anchoring \the [src]'s external support rods.") + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) + + if(do_after(user, src, 40) && d_state == WALLCOVERREMOVED) + src.d_state = WALLRODSUNSECURED + update_icon() + user.visible_message("[user] loosens the bolts anchoring \the [src]'s external support rods.", \ + "You loosen the bolts anchoring \the [src]'s external support rods.") + return + + //Only construction step after reinforced girder, add the second plasteel sheet + //Acts as a super repair step, incidentally, if there's clearly more than cover damage + else if(istype(W, /obj/item/stack/sheet/plasteel)) + var/obj/item/stack/sheet/plasteel/P = W + user.visible_message("[user] starts installing an external cover to \the [src].", \ + "You start installing an external cover to \the [src].") + playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) + + if(do_after(user, src, 50) && d_state == WALLCOVERREMOVED) + P.use(1) + src.d_state = WALLCOMPLETED //A new pristine reinforced cover, we are done here + update_icon() + user.visible_message("[user] finishes installing an external cover to \the [src].", \ + "You finish installing an external cover to \the [src].") + return + + if(WALLRODSUNSECURED) + if(istype(W, /obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + user.visible_message("[user] begins slicing through \the [src]'s external support rods.", \ + "You begin slicing through \the [src]'s external support rods.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 100) && d_state == WALLRODSUNSECURED) + playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again + src.d_state = WALLRODSCUT + update_icon() + user.visible_message("[user] slices through \the [src]'s external support rods.", \ + "You slice through \the [src]'s external support rods, exposing its internal cover.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + + user.visible_message("[user] begins slicing through \the [src]'s external support rods.", \ + "You begin slicing through \the [src]'s external support rods.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 70)) + playsound(src, 'sound/items/Welder.ogg', 100, 1) + src.d_state = WALLRODSCUT + update_icon() + user.visible_message("[user] slices through \the [src]'s external support rods.", \ + "You slice through \the [src]'s external support rods, exposing its internal cover.") + return + + //Repair step, tighten the anchoring bolts + else if(istype(W, /obj/item/weapon/wrench)) + + user.visible_message("[user] starts tightening the bolts anchoring \the [src]'s external support rods.", \ + "You start tightening the bolts anchoring \the [src]'s external support rods.") + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) + + if(do_after(user, src, 40) && d_state == WALLRODSUNSECURED) + src.d_state = WALLCOVERREMOVED + update_icon() + user.visible_message("[user] tightens the bolts anchoring \the [src]'s external support rods.", \ + "You tighten the bolts anchoring \the [src]'s external support rods.") + return + + if(WALLRODSCUT) + if(istype(W, /obj/item/weapon/crowbar)) + + user.visible_message("[user] starts prying off [src]'s internal cover.", \ + "You struggle to pry off [src]'s internal cover.") + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) + + if(do_after(user, src, 100) && d_state == WALLRODSCUT) + user.visible_message("[user] pries off [src]'s internal cover.", \ + "You pry off [src]'s internal cover.") + dismantle_wall() //Mr. Engineer, break down that reinforced wall + playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) + return + + //Repair the external support rods welded through in the previous step, with a welding tool. Naturally + else if(istype(W, /obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + user.visible_message("[user] begins mending \the [src]'s external support rods.", \ + "You begin mending \the [src]'s external support rods.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user, src, 100) && d_state == WALLRODSCUT) + playsound(src, 'sound/items/Welder.ogg', 100, 1) //Not an error, play welder sound again + src.d_state = WALLRODSUNSECURED + update_icon() + user.visible_message("[user] mends \the [src]'s external support rods.", \ + "You mend \the [src]'s external support rods.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + +//This is where we perform actions that aren't deconstructing, constructing or thermiting the reinforced wall + + //Drilling + //Needs a diamond drill or equivalent + if(istype(W, /obj/item/weapon/pickaxe)) + + var/obj/item/weapon/pickaxe/PK = W + if(!(PK.diggables & DIG_RWALLS)) + return + + user.visible_message("[user] begins [PK.drill_verb] straight into \the [src].", \ + "You begin [PK.drill_verb] straight into \the [src].") + playsound(src, PK.drill_sound, 100, 1) + if(do_after(user, src, PK.digspeed * 50)) + user.visible_message("[user]'s [PK] tears though the last of \the [src], leaving nothing but a girder.", \ + "Your [PK] tears though the last of \the [src], leaving nothing but a girder.") + dismantle_wall() + return + + else if(istype(W, /obj/item/mounted)) + return + + //Finally, CHECKING FOR FALSE WALLS if it isn't damaged + //This is obsolete since reinforced false walls were commented out, but gotta slap the wall with my hand anyways ! + else if(!d_state) + return attack_hand(user) + return + +/turf/simulated/wall/r_wall/attack_construct(mob/user as mob) + return 0 + +/turf/simulated/wall/r_wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(30)) + dismantle_wall() + +/turf/simulated/wall/r_wall/dismantle_wall(devastated = 0, explode = 0) + if(!devastated) + getFromPool(/obj/item/stack/sheet/plasteel, src)//Reinforced girder has deconstruction steps too. If no girder, drop ONE plasteel sheet AND rods + else + getFromPool(/obj/item/stack/rods, src, 2) + getFromPool(/obj/item/stack/sheet/plasteel, src) + + for(var/obj/O in src.contents) //Eject contents! + if(istype(O,/obj/structure/sign/poster)) + var/obj/structure/sign/poster/P = O + P.roll_and_drop(src) + + ChangeTurf(dismantle_type) + +/turf/simulated/wall/r_wall/ex_act(severity) + if(rotting) + severity = 1.0 + switch(severity) + if(1.0) + if(prob(66)) //It's "bomb-proof" + dismantle_wall(0,1) //So it isn't completely destroyed, nice uh ? + else + dismantle_wall(1,1) //Fuck it up nicely + if(2.0) + if(prob(75) && (d_state == WALLCOMPLETED))//No more infinite plasteel generation! + src.d_state = WALLCOVERREMOVED + update_icon() + getFromPool(/obj/item/stack/sheet/plasteel, get_turf(src)) //Lose the plasteel needed to get there + else + dismantle_wall(0,1) + if(3.0) + if(prob(15)) + dismantle_wall(0,1) + else //If prob fails, break the outer safety grille to look like scrap damage + src.d_state = WALLCOVEREXPOSED + update_icon() + return +#undef WALLCOMPLETED +#undef WALLCOVEREXPOSED +#undef WALLCOVERUNSECURED +#undef WALLCOVERWEAKENED +#undef WALLCOVERREMOVED +#undef WALLRODSUNSECURED +#undef WALLRODSCUT diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index ecef0582f9e..78fdc6ff20e 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -1,173 +1,173 @@ -/turf/space - icon = 'icons/turf/space.dmi' - name = "\proper space" - desc = "The final frontier." - icon_state = "0" - - temperature = TCMB - thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT - heat_capacity = 700000 - intact = 0 //No seriously, that's not a joke. Allows cable to be laid properLY on catwalks - dynamic_lighting = 0 - luminosity = 1 - can_border_transition = 1 - -/turf/space/New() - turfs |= src - if(!istype(src, /turf/space/transit)) - icon_state = "[((x + y) ^ ~(x * y) + z) % 25]" - -/turf/space/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/turf/space/canBuildCatwalk() - if(locate(/obj/structure/catwalk) in contents) - return BUILD_FAILURE - return locate(/obj/structure/lattice) in contents - - -/turf/space/canBuildLattice(var/material) - if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) - return BUILD_FAILURE - else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) - return BUILD_FAILURE - else if(!(locate(/obj/structure/lattice) in contents) && !(istype(material,/obj/item/stack/sheet/wood))) - return 1 - return BUILD_FAILURE - -/turf/space/canBuildPlating(var/material) - if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) - return BUILD_FAILURE - else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) - return BUILD_FAILURE - else if((locate(/obj/structure/lattice) in contents) && !(istype(material,/obj/item/stack/tile/wood))) - return 1 - return BUILD_FAILURE - -// Ported from unstable r355 - -/turf/space/Entered(atom/movable/A as mob|obj) - ..() - inertial_drift(A) - -/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj) - var/cur_x - var/cur_y - var/next_x - var/next_y - var/target_z - var/list/y_arr - - if(src.x <= 1) - if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) - qdel(A) - A = null - return - - var/list/cur_pos = src.get_global_map_pos() - if(!cur_pos) return - cur_x = cur_pos["x"] - cur_y = cur_pos["y"] - next_x = (--cur_x||global_map.len) - y_arr = global_map[next_x] - target_z = y_arr[cur_y] -/* - //debug - to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") - to_chat(world, "Target Z = [target_z]") - to_chat(world, "Next X = [next_x]") - //debug -*/ - if(target_z) - A.z = target_z - A.x = world.maxx - 2 - spawn (0) - if ((A && A.loc)) - A.loc.Entered(A) - else if (src.x >= world.maxx) - if(istype(A, /obj/effect/meteor)) - qdel(A) - A = null - return - - var/list/cur_pos = src.get_global_map_pos() - if(!cur_pos) return - cur_x = cur_pos["x"] - cur_y = cur_pos["y"] - next_x = (++cur_x > global_map.len ? 1 : cur_x) - y_arr = global_map[next_x] - target_z = y_arr[cur_y] -/* - //debug - to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") - to_chat(world, "Target Z = [target_z]") - to_chat(world, "Next X = [next_x]") - //debug -*/ - if(target_z) - A.z = target_z - A.x = 3 - spawn (0) - if ((A && A.loc)) - A.loc.Entered(A) - else if (src.y <= 1) - if(istype(A, /obj/effect/meteor)) - qdel(A) - A = null - return - var/list/cur_pos = src.get_global_map_pos() - if(!cur_pos) return - cur_x = cur_pos["x"] - cur_y = cur_pos["y"] - y_arr = global_map[cur_x] - next_y = (--cur_y||y_arr.len) - target_z = y_arr[next_y] -/* - //debug - to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") - to_chat(world, "Next Y = [next_y]") - to_chat(world, "Target Z = [target_z]") - //debug -*/ - if(target_z) - A.z = target_z - A.y = world.maxy - 2 - spawn (0) - if ((A && A.loc)) - A.loc.Entered(A) - - else if (src.y >= world.maxy) - if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) - qdel(A) - A = null - return - var/list/cur_pos = src.get_global_map_pos() - if(!cur_pos) return - cur_x = cur_pos["x"] - cur_y = cur_pos["y"] - y_arr = global_map[cur_x] - next_y = (++cur_y > y_arr.len ? 1 : cur_y) - target_z = y_arr[next_y] -/* - //debug - to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") - to_chat(world, "Next Y = [next_y]") - to_chat(world, "Target Z = [target_z]") - //debug -*/ - if(target_z) - A.z = target_z - A.y = 3 - spawn (0) - if ((A && A.loc)) - A.loc.Entered(A) - return - -/turf/space/singularity_act() - return - -/turf/space/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 1) - return ..(N, tell_universe, 1, allow) - -/turf/space/lighting_build_overlays() - return +/turf/space + icon = 'icons/turf/space.dmi' + name = "\proper space" + desc = "The final frontier." + icon_state = "0" + + temperature = TCMB + thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT + heat_capacity = 700000 + intact = 0 //No seriously, that's not a joke. Allows cable to be laid properLY on catwalks + dynamic_lighting = 0 + luminosity = 1 + can_border_transition = 1 + +/turf/space/New() + turfs |= src + if(!istype(src, /turf/space/transit)) + icon_state = "[((x + y) ^ ~(x * y) + z) % 25]" + +/turf/space/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/turf/space/canBuildCatwalk() + if(locate(/obj/structure/catwalk) in contents) + return BUILD_FAILURE + return locate(/obj/structure/lattice) in contents + + +/turf/space/canBuildLattice(var/material) + if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) + return BUILD_FAILURE + else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) + return BUILD_FAILURE + else if(!(locate(/obj/structure/lattice) in contents) && !(istype(material,/obj/item/stack/sheet/wood))) + return 1 + return BUILD_FAILURE + +/turf/space/canBuildPlating(var/material) + if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) + return BUILD_FAILURE + else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) + return BUILD_FAILURE + else if((locate(/obj/structure/lattice) in contents) && !(istype(material,/obj/item/stack/tile/wood))) + return 1 + return BUILD_FAILURE + +// Ported from unstable r355 + +/turf/space/Entered(atom/movable/A as mob|obj) + ..() + inertial_drift(A) + +/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj) + var/cur_x + var/cur_y + var/next_x + var/next_y + var/target_z + var/list/y_arr + + if(src.x <= 1) + if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) + qdel(A) + A = null + return + + var/list/cur_pos = src.get_global_map_pos() + if(!cur_pos) return + cur_x = cur_pos["x"] + cur_y = cur_pos["y"] + next_x = (--cur_x||global_map.len) + y_arr = global_map[next_x] + target_z = y_arr[cur_y] +/* + //debug + to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") + to_chat(world, "Target Z = [target_z]") + to_chat(world, "Next X = [next_x]") + //debug +*/ + if(target_z) + A.z = target_z + A.x = world.maxx - 2 + spawn (0) + if ((A && A.loc)) + A.loc.Entered(A) + else if (src.x >= world.maxx) + if(istype(A, /obj/effect/meteor)) + qdel(A) + A = null + return + + var/list/cur_pos = src.get_global_map_pos() + if(!cur_pos) return + cur_x = cur_pos["x"] + cur_y = cur_pos["y"] + next_x = (++cur_x > global_map.len ? 1 : cur_x) + y_arr = global_map[next_x] + target_z = y_arr[cur_y] +/* + //debug + to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") + to_chat(world, "Target Z = [target_z]") + to_chat(world, "Next X = [next_x]") + //debug +*/ + if(target_z) + A.z = target_z + A.x = 3 + spawn (0) + if ((A && A.loc)) + A.loc.Entered(A) + else if (src.y <= 1) + if(istype(A, /obj/effect/meteor)) + qdel(A) + A = null + return + var/list/cur_pos = src.get_global_map_pos() + if(!cur_pos) return + cur_x = cur_pos["x"] + cur_y = cur_pos["y"] + y_arr = global_map[cur_x] + next_y = (--cur_y||y_arr.len) + target_z = y_arr[next_y] +/* + //debug + to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") + to_chat(world, "Next Y = [next_y]") + to_chat(world, "Target Z = [target_z]") + //debug +*/ + if(target_z) + A.z = target_z + A.y = world.maxy - 2 + spawn (0) + if ((A && A.loc)) + A.loc.Entered(A) + + else if (src.y >= world.maxy) + if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) + qdel(A) + A = null + return + var/list/cur_pos = src.get_global_map_pos() + if(!cur_pos) return + cur_x = cur_pos["x"] + cur_y = cur_pos["y"] + y_arr = global_map[cur_x] + next_y = (++cur_y > y_arr.len ? 1 : cur_y) + target_z = y_arr[next_y] +/* + //debug + to_chat(world, "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]") + to_chat(world, "Next Y = [next_y]") + to_chat(world, "Target Z = [target_z]") + //debug +*/ + if(target_z) + A.z = target_z + A.y = 3 + spawn (0) + if ((A && A.loc)) + A.loc.Entered(A) + return + +/turf/space/singularity_act() + return + +/turf/space/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 1) + return ..(N, tell_universe, 1, allow) + +/turf/space/lighting_build_overlays() + return diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index 68e6ce3ddb9..de8e6682823 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -1,55 +1,55 @@ -/turf/space/transit - var/pushdirection // push things that get caught in the transit tile this direction - -/turf/space/transit/New() - turfs |= src - var/dira="" - var/i=0 - switch(pushdirection) - if(SOUTH) // North to south - dira="ns" - i=1+(abs((x^2)-y)%15) // Vary widely across X, but just decrement across Y - - if(WEST) // East to west - dira="ew" - i=1+(((y^2)+x)%15) // Vary widely across Y, but just increment across X - /* - if(NORTH) // South to north (SPRITES DO NOT EXIST!) - dira="sn" - i=1+(((x^2)+y)%15) // Vary widely across X, but just increment across Y - - if(EAST) // West to east (SPRITES DO NOT EXIST!) - dira="we" - i=1+(abs((y^2)-x)%15) // Vary widely across X, but just increment across Y - */ - - else - icon_state="black" - if(icon_state != "black") - icon_state = "speedspace_[dira]_[i]" - -/turf/space/transit/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 0) - return ..(N, tell_universe, 1, allow) - -//Overwrite because we dont want people building rods in space. -/turf/space/transit/attackby(obj/O as obj, mob/user as mob) - return - -/turf/space/transit/canBuildCatwalk() - return BUILD_FAILURE - -/turf/space/transit/canBuildLattice() - return BUILD_FAILURE - -/turf/space/transit/canBuildPlating() - return BUILD_SILENT_FAILURE - -/turf/space/transit/north // moving to the north - - pushdirection = SOUTH // south because the space tile is scrolling south - icon_state="debug-north" - -/turf/space/transit/east // moving to the east - - pushdirection = WEST +/turf/space/transit + var/pushdirection // push things that get caught in the transit tile this direction + +/turf/space/transit/New() + turfs |= src + var/dira="" + var/i=0 + switch(pushdirection) + if(SOUTH) // North to south + dira="ns" + i=1+(abs((x^2)-y)%15) // Vary widely across X, but just decrement across Y + + if(WEST) // East to west + dira="ew" + i=1+(((y^2)+x)%15) // Vary widely across Y, but just increment across X + /* + if(NORTH) // South to north (SPRITES DO NOT EXIST!) + dira="sn" + i=1+(((x^2)+y)%15) // Vary widely across X, but just increment across Y + + if(EAST) // West to east (SPRITES DO NOT EXIST!) + dira="we" + i=1+(abs((y^2)-x)%15) // Vary widely across X, but just increment across Y + */ + + else + icon_state="black" + if(icon_state != "black") + icon_state = "speedspace_[dira]_[i]" + +/turf/space/transit/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 0) + return ..(N, tell_universe, 1, allow) + +//Overwrite because we dont want people building rods in space. +/turf/space/transit/attackby(obj/O as obj, mob/user as mob) + return + +/turf/space/transit/canBuildCatwalk() + return BUILD_FAILURE + +/turf/space/transit/canBuildLattice() + return BUILD_FAILURE + +/turf/space/transit/canBuildPlating() + return BUILD_SILENT_FAILURE + +/turf/space/transit/north // moving to the north + + pushdirection = SOUTH // south because the space tile is scrolling south + icon_state="debug-north" + +/turf/space/transit/east // moving to the east + + pushdirection = WEST icon_state="debug-east" \ No newline at end of file diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm index 178b69b2868..a50794a76d4 100644 --- a/code/game/turfs/unsimulated.dm +++ b/code/game/turfs/unsimulated.dm @@ -1,5 +1,5 @@ -/turf/unsimulated - intact = 1 - name = "command" - oxygen = MOLES_O2STANDARD +/turf/unsimulated + intact = 1 + name = "command" + oxygen = MOLES_O2STANDARD nitrogen = MOLES_N2STANDARD \ No newline at end of file diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm index 05678e13e4e..4f6b2f0874e 100644 --- a/code/game/turfs/unsimulated/beach.dm +++ b/code/game/turfs/unsimulated/beach.dm @@ -1,23 +1,23 @@ -/turf/unsimulated/beach - name = "Beach" - icon = 'icons/misc/beach.dmi' - -/turf/unsimulated/beach/sand - name = "Sand" - icon_state = "sand" - -/turf/unsimulated/beach/coastline - name = "Coastline" - icon = 'icons/misc/beach2.dmi' - icon_state = "sandwater" - -/turf/unsimulated/beach/water - name = "Water" - icon_state = "water" - -/turf/unsimulated/beach/water/New() - ..() - overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1) - -/turf/unsimulated/beach/cultify() +/turf/unsimulated/beach + name = "Beach" + icon = 'icons/misc/beach.dmi' + +/turf/unsimulated/beach/sand + name = "Sand" + icon_state = "sand" + +/turf/unsimulated/beach/coastline + name = "Coastline" + icon = 'icons/misc/beach2.dmi' + icon_state = "sandwater" + +/turf/unsimulated/beach/water + name = "Water" + icon_state = "water" + +/turf/unsimulated/beach/water/New() + ..() + overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1) + +/turf/unsimulated/beach/cultify() return \ No newline at end of file diff --git a/code/game/turfs/unsimulated/floor.dm b/code/game/turfs/unsimulated/floor.dm index b4ce2a862db..0f8c9443a85 100644 --- a/code/game/turfs/unsimulated/floor.dm +++ b/code/game/turfs/unsimulated/floor.dm @@ -1,221 +1,221 @@ -/turf/unsimulated/floor - name = "floor" - icon = 'icons/turf/floors.dmi' - icon_state = "Floor3" - -/turf/unsimulated/floor/ex_act(severity) - switch(severity) - if(1.0) - new/obj/effect/decal/cleanable/soot(src) - if(2.0) - if(prob(65)) - new/obj/effect/decal/cleanable/soot(src) - if(3.0) - if(prob(20)) - new/obj/effect/decal/cleanable/soot(src) - return - return - -/turf/unsimulated/floor/attack_paw(user as mob) - return src.attack_hand(user) - -/turf/unsimulated/floor/cultify() - if((icon_state != "cult")&&(icon_state != "cult-narsie")) - name = "engraved floor" - icon_state = "cult" - turf_animation('icons/effects/effects.dmi',"cultfloor",0,0,MOB_LAYER-1) - return - -/turf/unsimulated/floor/grass - icon_state = "grass1" - -/turf/unsimulated/floor/grass/New() - ..() - icon_state = "grass[rand(1,4)]" - -/turf/unsimulated/floor/snow - ..() - temperature = 233.15 // -40C in K - oxygen = MOLES_O2STANDARD*1.25 // 100kpa - nitrogen = MOLES_N2STANDARD*1.25 // 100kpa - name = "snow" - icon = 'icons/turf/newsnow.dmi' - icon_state = "snow0" - var/snowballs = 0 - var/global/list/snowlayers = list() - var/global/list/dirtlayers = list() - light_color = "#e5ffff" - can_border_transition = 1 - dynamic_lighting = 0 - luminosity = 1 - -/turf/unsimulated/floor/snow/New() - ..() - icon_state = "snow[rand(0,6)]" - relativewall_neighbours() - snowballs = rand(30,50) - src.update_icon() - if(prob(5) && !(src.contents.len)) - new/obj/structure/flora/tree/pine(src) - -/turf/unsimulated/floor/snow/relativewall_neighbours() - for(var/direction in alldirs) - var/turf/adj_tile = get_step(src, direction) - if(istype(adj_tile,/turf/unsimulated/floor/snow)) - adj_tile.update_icon() - -/turf/unsimulated/floor/snow/undersnow/New() - ..() - snowballs = 0 - -/turf/unsimulated/floor/snow/undersnow/update_icon() - ..() - var/junction = findSmoothingNeighbors() - var/dircount = 0 - for(var/direction in diagonal) - if (istype(get_step(src, direction),/turf/unsimulated/floor/snow/undersnow)) - if((direction & junction) == direction) - overlays += dirtlayers["diag[direction]"] - dircount += 1 - if(dircount == 4) - overlays.Cut() - icon_state = "snowpath-Full" - overlays += snowlayers["1"] - overlays += snowlayers["2"] - else if(junction) - overlays += dirtlayers["snow[junction]"] - else overlays += dirtlayers["snow0"] - - -/turf/unsimulated/floor/snow/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(snowballs >= 0) - if(istype(W,/obj/item/weapon/pickaxe/shovel)) - user.delayNextAttack(15) - if(do_after(user,src,25)) - for(var/i = 0; i < min(snowballs,10), i++) - var/obj/item/stack/sheet/snow/snowball = new /obj/item/stack/sheet/snow(user.loc) - snowball.pixel_x = rand(-16,16) - snowball.pixel_y = rand(-16,16) - snowballs = min(snowballs-10,0) - if(snowballs <= 0) - src.ChangeTurf(/turf/unsimulated/floor/snow/undersnow) - -/turf/unsimulated/floor/snow/undersnow/canBuildCatwalk() - return BUILD_FAILURE - -/turf/unsimulated/floor/snow/undersnow/canBuildLattice() - if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) - return BUILD_FAILURE - else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) - return BUILD_FAILURE - else if(!(locate(/obj/structure/lattice) in contents)) - return BUILD_SUCCESS - return BUILD_FAILURE - -/turf/unsimulated/floor/snow/undersnow/canBuildPlating() - if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) - return BUILD_FAILURE - else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) - return BUILD_FAILURE - else if(locate(/obj/structure/lattice) in contents) - return BUILD_SUCCESS - return BUILD_FAILURE - -/turf/unsimulated/floor/snow/attack_hand(mob/user as mob) - if(snowballs > 0) - user.delayNextAttack(15) - if(do_after(user,src,15)) - snowballs -= 1 - var/obj/item/stack/sheet/snow/snowball = new /obj/item/stack/sheet/snow - user.put_in_hands(snowball) - if(snowballs <= 0) - src.ChangeTurf(/turf/unsimulated/floor/snow/undersnow) - src.relativewall_neighbours() - ..() - -/turf/unsimulated/floor/snow/Entered(mob/user) - ..() - if(istype(user,/mob/living/carbon)&&!(user.stat)) - var/list/snowsound = list('sound/misc/snow1.ogg','sound/misc/snow2.ogg','sound/misc/snow3.ogg','sound/misc/snow4.ogg','sound/misc/snow5.ogg','sound/misc/snow6.ogg') - playsound(get_turf(src), pick(snowsound), 10, 1, -1,channel = 123) - -/turf/unsimulated/floor/snow/update_icon() - if (overlays.len > 2) - overlays.Cut() - if(!(snowlayers.len)) - snowlayers["1"] = image('icons/turf/snowfx.dmi',"snowlayer1",17) - snowlayers["2"] = image('icons/turf/snowfx.dmi',"snowlayer2",17) - if(!(dirtlayers.len)) - for(var/dirtdir in alldirs) - dirtlayers["side[dirtdir]"] = image('icons/turf/newsnow.dmi',"snowpath-Side",dir = dirtdir) - for(var/diagdir in diagonal) - dirtlayers["diag[diagdir]"] = image('icons/turf/newsnow.dmi',"dirtquarter",dir = diagdir,layer=2.1) - dirtlayers["snow[diagdir]"] = image('icons/turf/newsnow.dmi',"snowpath",dir = diagdir) - for(var/dirtdir in cardinal) - dirtlayers["snow[dirtdir]"] = image('icons/turf/newsnow.dmi',"snowpath-half",dir = dirtdir) - var/realdir = null - switch(dirtdir) - if(NORTH) - realdir = EAST|SOUTH|WEST - if(SOUTH) - realdir = WEST|NORTH|EAST - if(EAST) - realdir = SOUTH|WEST|NORTH - if(WEST) - realdir = NORTH|EAST|SOUTH - dirtlayers["snow[realdir]"] = image('icons/turf/newsnow.dmi',"snowpath-TJunction",dir = dirtdir) - dirtlayers["snow15"] = image('icons/turf/newsnow.dmi',"snowpath-Crossroads") - dirtlayers["snow0"] = image('icons/turf/newsnow.dmi',"snowpath-circle") - dirtlayers["snow3"] = image('icons/turf/newsnow.dmi',"snowpath",dir = 1) - dirtlayers["snow12"] = image('icons/turf/newsnow.dmi',"snowpath",dir = 8) - var/lightson = 0 - for(var/direction in alldirs) - if(!istype(get_step(src, direction),/turf/unsimulated/floor/snow)) - if(istype(get_step(src, direction),/turf/simulated/floor)) - lightson = 1 - // var/turf/tilebehind = get_step(tile, tile_dir) - // if(tilebehind.temperature > 273.15) - src.overlays += dirtlayers["side[direction]"] - var/image/snow1 = snowlayers["1"] - var/image/snow2 = snowlayers["2"] - snow1.alpha = 255 - snow2.alpha = 255 - switch(direction) - if(1) - snow1.pixel_y = 32 - overlays += snow1 - snow2.pixel_y = 32 - overlays += snow2 - if(2) - snow1.pixel_y = -32 - overlays += snow1 - snow2.pixel_y = -32 - overlays += snow2 - if(4) - snow1.pixel_x = 32 - overlays += snow1 - snow2.pixel_x = 32 - overlays += snow2 - if(8) - snow1.pixel_x = -32 - overlays += snow1 - snow2.pixel_x = -32 - overlays += snow2 - snow1.alpha = 64 - snow2.alpha = 64 - snow1.pixel_x = 0 - snow2.pixel_x = 0 - snow1.pixel_y = 0 - snow2.pixel_y = 0 - if(lightson) - set_light(5, 0.5) - else - set_light(0,0) - overlays += snowlayers["1"] - overlays += snowlayers["2"] - -/turf/unsimulated/floor/snow/undersnow - ..() - name = "dirt" +/turf/unsimulated/floor + name = "floor" + icon = 'icons/turf/floors.dmi' + icon_state = "Floor3" + +/turf/unsimulated/floor/ex_act(severity) + switch(severity) + if(1.0) + new/obj/effect/decal/cleanable/soot(src) + if(2.0) + if(prob(65)) + new/obj/effect/decal/cleanable/soot(src) + if(3.0) + if(prob(20)) + new/obj/effect/decal/cleanable/soot(src) + return + return + +/turf/unsimulated/floor/attack_paw(user as mob) + return src.attack_hand(user) + +/turf/unsimulated/floor/cultify() + if((icon_state != "cult")&&(icon_state != "cult-narsie")) + name = "engraved floor" + icon_state = "cult" + turf_animation('icons/effects/effects.dmi',"cultfloor",0,0,MOB_LAYER-1) + return + +/turf/unsimulated/floor/grass + icon_state = "grass1" + +/turf/unsimulated/floor/grass/New() + ..() + icon_state = "grass[rand(1,4)]" + +/turf/unsimulated/floor/snow + ..() + temperature = 233.15 // -40C in K + oxygen = MOLES_O2STANDARD*1.25 // 100kpa + nitrogen = MOLES_N2STANDARD*1.25 // 100kpa + name = "snow" + icon = 'icons/turf/newsnow.dmi' + icon_state = "snow0" + var/snowballs = 0 + var/global/list/snowlayers = list() + var/global/list/dirtlayers = list() + light_color = "#e5ffff" + can_border_transition = 1 + dynamic_lighting = 0 + luminosity = 1 + +/turf/unsimulated/floor/snow/New() + ..() + icon_state = "snow[rand(0,6)]" + relativewall_neighbours() + snowballs = rand(30,50) + src.update_icon() + if(prob(5) && !(src.contents.len)) + new/obj/structure/flora/tree/pine(src) + +/turf/unsimulated/floor/snow/relativewall_neighbours() + for(var/direction in alldirs) + var/turf/adj_tile = get_step(src, direction) + if(istype(adj_tile,/turf/unsimulated/floor/snow)) + adj_tile.update_icon() + +/turf/unsimulated/floor/snow/undersnow/New() + ..() + snowballs = 0 + +/turf/unsimulated/floor/snow/undersnow/update_icon() + ..() + var/junction = findSmoothingNeighbors() + var/dircount = 0 + for(var/direction in diagonal) + if (istype(get_step(src, direction),/turf/unsimulated/floor/snow/undersnow)) + if((direction & junction) == direction) + overlays += dirtlayers["diag[direction]"] + dircount += 1 + if(dircount == 4) + overlays.Cut() + icon_state = "snowpath-Full" + overlays += snowlayers["1"] + overlays += snowlayers["2"] + else if(junction) + overlays += dirtlayers["snow[junction]"] + else overlays += dirtlayers["snow0"] + + +/turf/unsimulated/floor/snow/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(snowballs >= 0) + if(istype(W,/obj/item/weapon/pickaxe/shovel)) + user.delayNextAttack(15) + if(do_after(user,src,25)) + for(var/i = 0; i < min(snowballs,10), i++) + var/obj/item/stack/sheet/snow/snowball = new /obj/item/stack/sheet/snow(user.loc) + snowball.pixel_x = rand(-16,16) + snowball.pixel_y = rand(-16,16) + snowballs = min(snowballs-10,0) + if(snowballs <= 0) + src.ChangeTurf(/turf/unsimulated/floor/snow/undersnow) + +/turf/unsimulated/floor/snow/undersnow/canBuildCatwalk() + return BUILD_FAILURE + +/turf/unsimulated/floor/snow/undersnow/canBuildLattice() + if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) + return BUILD_FAILURE + else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) + return BUILD_FAILURE + else if(!(locate(/obj/structure/lattice) in contents)) + return BUILD_SUCCESS + return BUILD_FAILURE + +/turf/unsimulated/floor/snow/undersnow/canBuildPlating() + if(src.x >= (world.maxx - TRANSITIONEDGE) || src.x <= TRANSITIONEDGE) + return BUILD_FAILURE + else if (src.y >= (world.maxy - TRANSITIONEDGE || src.y <= TRANSITIONEDGE )) + return BUILD_FAILURE + else if(locate(/obj/structure/lattice) in contents) + return BUILD_SUCCESS + return BUILD_FAILURE + +/turf/unsimulated/floor/snow/attack_hand(mob/user as mob) + if(snowballs > 0) + user.delayNextAttack(15) + if(do_after(user,src,15)) + snowballs -= 1 + var/obj/item/stack/sheet/snow/snowball = new /obj/item/stack/sheet/snow + user.put_in_hands(snowball) + if(snowballs <= 0) + src.ChangeTurf(/turf/unsimulated/floor/snow/undersnow) + src.relativewall_neighbours() + ..() + +/turf/unsimulated/floor/snow/Entered(mob/user) + ..() + if(istype(user,/mob/living/carbon)&&!(user.stat)) + var/list/snowsound = list('sound/misc/snow1.ogg','sound/misc/snow2.ogg','sound/misc/snow3.ogg','sound/misc/snow4.ogg','sound/misc/snow5.ogg','sound/misc/snow6.ogg') + playsound(get_turf(src), pick(snowsound), 10, 1, -1,channel = 123) + +/turf/unsimulated/floor/snow/update_icon() + if (overlays.len > 2) + overlays.Cut() + if(!(snowlayers.len)) + snowlayers["1"] = image('icons/turf/snowfx.dmi',"snowlayer1",17) + snowlayers["2"] = image('icons/turf/snowfx.dmi',"snowlayer2",17) + if(!(dirtlayers.len)) + for(var/dirtdir in alldirs) + dirtlayers["side[dirtdir]"] = image('icons/turf/newsnow.dmi',"snowpath-Side",dir = dirtdir) + for(var/diagdir in diagonal) + dirtlayers["diag[diagdir]"] = image('icons/turf/newsnow.dmi',"dirtquarter",dir = diagdir,layer=2.1) + dirtlayers["snow[diagdir]"] = image('icons/turf/newsnow.dmi',"snowpath",dir = diagdir) + for(var/dirtdir in cardinal) + dirtlayers["snow[dirtdir]"] = image('icons/turf/newsnow.dmi',"snowpath-half",dir = dirtdir) + var/realdir = null + switch(dirtdir) + if(NORTH) + realdir = EAST|SOUTH|WEST + if(SOUTH) + realdir = WEST|NORTH|EAST + if(EAST) + realdir = SOUTH|WEST|NORTH + if(WEST) + realdir = NORTH|EAST|SOUTH + dirtlayers["snow[realdir]"] = image('icons/turf/newsnow.dmi',"snowpath-TJunction",dir = dirtdir) + dirtlayers["snow15"] = image('icons/turf/newsnow.dmi',"snowpath-Crossroads") + dirtlayers["snow0"] = image('icons/turf/newsnow.dmi',"snowpath-circle") + dirtlayers["snow3"] = image('icons/turf/newsnow.dmi',"snowpath",dir = 1) + dirtlayers["snow12"] = image('icons/turf/newsnow.dmi',"snowpath",dir = 8) + var/lightson = 0 + for(var/direction in alldirs) + if(!istype(get_step(src, direction),/turf/unsimulated/floor/snow)) + if(istype(get_step(src, direction),/turf/simulated/floor)) + lightson = 1 + // var/turf/tilebehind = get_step(tile, tile_dir) + // if(tilebehind.temperature > 273.15) + src.overlays += dirtlayers["side[direction]"] + var/image/snow1 = snowlayers["1"] + var/image/snow2 = snowlayers["2"] + snow1.alpha = 255 + snow2.alpha = 255 + switch(direction) + if(1) + snow1.pixel_y = 32 + overlays += snow1 + snow2.pixel_y = 32 + overlays += snow2 + if(2) + snow1.pixel_y = -32 + overlays += snow1 + snow2.pixel_y = -32 + overlays += snow2 + if(4) + snow1.pixel_x = 32 + overlays += snow1 + snow2.pixel_x = 32 + overlays += snow2 + if(8) + snow1.pixel_x = -32 + overlays += snow1 + snow2.pixel_x = -32 + overlays += snow2 + snow1.alpha = 64 + snow2.alpha = 64 + snow1.pixel_x = 0 + snow2.pixel_x = 0 + snow1.pixel_y = 0 + snow2.pixel_y = 0 + if(lightson) + set_light(5, 0.5) + else + set_light(0,0) + overlays += snowlayers["1"] + overlays += snowlayers["2"] + +/turf/unsimulated/floor/snow/undersnow + ..() + name = "dirt" canSmoothWith = "/turf/unsimulated/floor/snow/undersnow" \ No newline at end of file diff --git a/code/game/turfs/unsimulated/walls.dm b/code/game/turfs/unsimulated/walls.dm index 3b62d6a6346..93507cf1bb0 100644 --- a/code/game/turfs/unsimulated/walls.dm +++ b/code/game/turfs/unsimulated/walls.dm @@ -1,65 +1,65 @@ -/turf/unsimulated/wall - name = "riveted wall" - icon = 'icons/turf/walls.dmi' - icon_state = "riveted" - opacity = 1 - density = 1 - explosion_block = 2 - canSmoothWith = "/turf/unsimulated/wall=0" - - var/walltype = "riveted" - -/turf/unsimulated/wall/fakeglass - name = "window" - icon_state = "fakewindows" - opacity = 0 - canSmoothWith = null - -/turf/unsimulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.delayNextAttack(8) - if (!user.dexterity_check()) +/turf/unsimulated/wall + name = "riveted wall" + icon = 'icons/turf/walls.dmi' + icon_state = "riveted" + opacity = 1 + density = 1 + explosion_block = 2 + canSmoothWith = "/turf/unsimulated/wall=0" + + var/walltype = "riveted" + +/turf/unsimulated/wall/fakeglass + name = "window" + icon_state = "fakewindows" + opacity = 0 + canSmoothWith = null + +/turf/unsimulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.delayNextAttack(8) + if (!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") - return - if(istype(W,/obj/item/weapon/solder) && bullet_marks) - var/obj/item/weapon/solder/S = W - if(!S.remove_fuel(bullet_marks*2,user)) - return - playsound(loc, 'sound/items/Welder.ogg', 100, 1) + return + if(istype(W,/obj/item/weapon/solder) && bullet_marks) + var/obj/item/weapon/solder/S = W + if(!S.remove_fuel(bullet_marks*2,user)) + return + playsound(loc, 'sound/items/Welder.ogg', 100, 1) to_chat(user, "You remove the bullet marks with \the [W].") - bullet_marks = 0 - icon = initial(icon) - -turf/unsimulated/wall/splashscreen - name = "Space Station 13" - icon = null - icon_state = null - layer = FLY_LAYER - canSmoothWith = null - - New() - var/path = "icons/splashworks/" - var/list/filenames = flist(path) - for(var/filename in filenames) - if(copytext(filename, length(filename)) == "/") - filenames -= filename - icon = file("[path][pick(filenames)]") - -/turf/unsimulated/wall/other - icon_state = "r_wall" - canSmoothWith = null - -/turf/unsimulated/wall/cult - name = "wall" - desc = "The patterns engraved on the wall seem to shift as you try to focus on them. You feel sick" - icon_state = "cult0" - opacity = 1 - density = 1 - canSmoothWith = null - -/turf/unsimulated/wall/cultify() - ChangeTurf(/turf/unsimulated/wall/cult) - turf_animation('icons/effects/effects.dmi',"cultwall",0,0,MOB_LAYER-1) - return - -/turf/unsimulated/wall/cult/cultify() + bullet_marks = 0 + icon = initial(icon) + +turf/unsimulated/wall/splashscreen + name = "Space Station 13" + icon = null + icon_state = null + layer = FLY_LAYER + canSmoothWith = null + + New() + var/path = "icons/splashworks/" + var/list/filenames = flist(path) + for(var/filename in filenames) + if(copytext(filename, length(filename)) == "/") + filenames -= filename + icon = file("[path][pick(filenames)]") + +/turf/unsimulated/wall/other + icon_state = "r_wall" + canSmoothWith = null + +/turf/unsimulated/wall/cult + name = "wall" + desc = "The patterns engraved on the wall seem to shift as you try to focus on them. You feel sick" + icon_state = "cult0" + opacity = 1 + density = 1 + canSmoothWith = null + +/turf/unsimulated/wall/cultify() + ChangeTurf(/turf/unsimulated/wall/cult) + turf_animation('icons/effects/effects.dmi',"cultwall",0,0,MOB_LAYER-1) + return + +/turf/unsimulated/wall/cult/cultify() return \ No newline at end of file diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 7fb7c7bd477..2ee80a8454b 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -1,181 +1,181 @@ -/client/verb/ooc(msg as text) - set name = "OOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite - set category = "OOC" - - if(say_disabled) //This is here to try to identify lag problems +/client/verb/ooc(msg as text) + set name = "OOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite + set category = "OOC" + + if(say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") - return - - if(!mob) return - if(IsGuestKey(key)) + return + + if(!mob) return + if(IsGuestKey(key)) to_chat(src, "Guests may not use OOC.") - return - - msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) - if(!msg) return - - if(!(prefs.toggles & CHAT_OOC)) + return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + if(!msg) return + + if(!(prefs.toggles & CHAT_OOC)) to_chat(src, "You have OOC muted.") - return - - if(!holder) - if(!ooc_allowed) + return + + if(!holder) + if(!ooc_allowed) to_chat(src, "OOC is globally muted") - return - if(!dooc_allowed && (mob.stat == DEAD)) + return + if(!dooc_allowed && (mob.stat == DEAD)) to_chat(usr, "OOC for dead mobs has been turned off.") - return - if(prefs.muted & MUTE_OOC) + return + if(prefs.muted & MUTE_OOC) to_chat(src, "You cannot use OOC (muted).") - return - if(oocban_isbanned(ckey)) + return + if(oocban_isbanned(ckey)) to_chat(src, "You cannot use OOC (banned).") - return - if(handle_spam_prevention(msg,MUTE_OOC)) - return - /*if(findtext(msg, "byond://")) + return + if(handle_spam_prevention(msg,MUTE_OOC)) + return + /*if(findtext(msg, "byond://")) to_chat(src, "Advertising other servers is not allowed.") - log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]") - message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") - return - */ - log_ooc("[mob.name]/[key] (@[mob.x],[mob.y],[mob.z]): [msg]") - - var/display_colour = config.default_ooc_color - if(holder && !holder.fakekey) - display_colour = "#0099cc" //light blue - if(holder.rights & R_MOD && !(holder.rights & R_ADMIN)) - display_colour = "#184880" //dark blue - if(holder.rights & R_DEBUG && !(holder.rights & R_ADMIN)) - display_colour = "#1b521f" //dark green - else if(holder.rights & R_ADMIN) - if(config.allow_admin_ooccolor) - display_colour = src.prefs.ooccolor - else - display_colour = "#b82e00" //orange - - for(var/client/C in clients) - if(C.prefs.toggles & CHAT_OOC) - var/display_name = src.key - if(holder) - if(holder.fakekey) - if(C.holder) - display_name = "[holder.fakekey]/([src.key])" - else - display_name = holder.fakekey + log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]") + message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") + return + */ + log_ooc("[mob.name]/[key] (@[mob.x],[mob.y],[mob.z]): [msg]") + + var/display_colour = config.default_ooc_color + if(holder && !holder.fakekey) + display_colour = "#0099cc" //light blue + if(holder.rights & R_MOD && !(holder.rights & R_ADMIN)) + display_colour = "#184880" //dark blue + if(holder.rights & R_DEBUG && !(holder.rights & R_ADMIN)) + display_colour = "#1b521f" //dark green + else if(holder.rights & R_ADMIN) + if(config.allow_admin_ooccolor) + display_colour = src.prefs.ooccolor + else + display_colour = "#b82e00" //orange + + for(var/client/C in clients) + if(C.prefs.toggles & CHAT_OOC) + var/display_name = src.key + if(holder) + if(holder.fakekey) + if(C.holder) + display_name = "[holder.fakekey]/([src.key])" + else + display_name = holder.fakekey to_chat(C, "OOC: [display_name]: [msg]") - /* - if(holder) - if(!holder.fakekey || C.holder) - if(holder.rights & R_ADMIN) + /* + if(holder) + if(!holder.fakekey || C.holder) + if(holder.rights & R_ADMIN) to_chat(C, "OOC: [key][holder.fakekey ? "/([holder.fakekey])" : ""]: [msg]") - else if(holder.rights & R_MOD) + else if(holder.rights & R_MOD) to_chat(C, "OOC: [src.key][holder.fakekey ? "/([holder.fakekey])" : ""]: [msg]") - else + else to_chat(C, "OOC: [src.key]: [msg]") - - else + + else to_chat(C, "OOC: [holder.fakekey ? holder.fakekey : src.key]: [msg]") - else + else to_chat(C, "OOC: [src.key]: [msg]") - */ - -/client/proc/set_ooc(newColor as color) - set name = "Set Player OOC Colour" - set desc = "Set to yellow for eye burning goodness." - set category = "Fun" - - config.default_ooc_color = newColor - -// Stealing it back :3c -Nexypoo -/client/verb/looc(msg as text) - set name = "LOOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite - set desc = "Local OOC, seen only by those in view." - set category = "OOC" - - if(say_disabled) //This is here to try to identify lag problems + */ + +/client/proc/set_ooc(newColor as color) + set name = "Set Player OOC Colour" + set desc = "Set to yellow for eye burning goodness." + set category = "Fun" + + config.default_ooc_color = newColor + +// Stealing it back :3c -Nexypoo +/client/verb/looc(msg as text) + set name = "LOOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite + set desc = "Local OOC, seen only by those in view." + set category = "OOC" + + if(say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") - return - - if(!mob) return - if(IsGuestKey(key)) + return + + if(!mob) return + if(IsGuestKey(key)) to_chat(src, "Guests may not use OOC.") - return - - msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) - if(!msg) return - - if(!(prefs.toggles & CHAT_LOOC)) + return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + if(!msg) return + + if(!(prefs.toggles & CHAT_LOOC)) to_chat(src, "You have LOOC muted.") - return - - if(!holder) - if(!ooc_allowed) + return + + if(!holder) + if(!ooc_allowed) to_chat(src, "LOOC is globally muted") - return - if(!dooc_allowed && (mob.stat == DEAD)) + return + if(!dooc_allowed && (mob.stat == DEAD)) to_chat(usr, "LOOC for dead mobs has been turned off.") - return - if(prefs.muted & MUTE_OOC) + return + if(prefs.muted & MUTE_OOC) to_chat(src, "You cannot use LOOC (muted).") - return - if(oocban_isbanned(ckey)) + return + if(oocban_isbanned(ckey)) to_chat(src, "You cannot use LOOC (banned).") - return - if(handle_spam_prevention(msg,MUTE_OOC)) - return - /*if(findtext(msg, "byond://")) + return + if(handle_spam_prevention(msg,MUTE_OOC)) + return + /*if(findtext(msg, "byond://")) to_chat(src, "Advertising other servers is not allowed.") - log_admin("[key_name(src)] has attempted to advertise in LOOC: [msg]") - message_admins("[key_name_admin(src)] has attempted to advertise in LOOC: [msg]") - return - */ - log_ooc("(LOCAL) [mob.name]/[key] (@[mob.x],[mob.y],[mob.z]): [msg]") - var/list/heard - var/mob/living/silicon/ai/AI - if(!isAI(src.mob)) - heard = get_hearers_in_view(7, src.mob) - else - AI = src.mob - heard = get_hearers_in_view(7, (istype(AI.eyeobj) ? AI.eyeobj : AI)) //if it doesn't have an eye somehow give it just the AI mob itself - for(var/mob/M in heard) - if(AI == M) continue - if(!M.client) - continue - var/client/C = M.client - if (C in admins) - continue //they are handled after that - if(isAIEye(M)) - var/mob/camera/aiEye/E = M - if(E.ai) - C = E.ai.client - if(C.prefs.toggles & CHAT_LOOC) - var/display_name = src.key - if(holder) - if(holder.fakekey) - if(C.holder) - display_name = "[holder.fakekey]/([src.key])" - else - display_name = holder.fakekey + log_admin("[key_name(src)] has attempted to advertise in LOOC: [msg]") + message_admins("[key_name_admin(src)] has attempted to advertise in LOOC: [msg]") + return + */ + log_ooc("(LOCAL) [mob.name]/[key] (@[mob.x],[mob.y],[mob.z]): [msg]") + var/list/heard + var/mob/living/silicon/ai/AI + if(!isAI(src.mob)) + heard = get_hearers_in_view(7, src.mob) + else + AI = src.mob + heard = get_hearers_in_view(7, (istype(AI.eyeobj) ? AI.eyeobj : AI)) //if it doesn't have an eye somehow give it just the AI mob itself + for(var/mob/M in heard) + if(AI == M) continue + if(!M.client) + continue + var/client/C = M.client + if (C in admins) + continue //they are handled after that + if(isAIEye(M)) + var/mob/camera/aiEye/E = M + if(E.ai) + C = E.ai.client + if(C.prefs.toggles & CHAT_LOOC) + var/display_name = src.key + if(holder) + if(holder.fakekey) + if(C.holder) + display_name = "[holder.fakekey]/([src.key])" + else + display_name = holder.fakekey to_chat(C, "LOOC: [display_name]: [msg]") - - for(var/client/C in admins) - if(C.prefs.toggles & CHAT_LOOC) - var/prefix = "(R)LOOC" - if (C.mob in heard) - prefix = "LOOC" + + for(var/client/C in admins) + if(C.prefs.toggles & CHAT_LOOC) + var/prefix = "(R)LOOC" + if (C.mob in heard) + prefix = "LOOC" to_chat(C, "[prefix]: [src.key]: [msg]") - if(istype(AI)) - var/client/C = AI.client - if (C in admins) - return //already been handled - - if(C.prefs.toggles & CHAT_LOOC) - var/display_name = src.key - if(holder) - if(holder.fakekey) - if(C.holder) - display_name = "[holder.fakekey]/([src.key])" - else - display_name = holder.fakekey + if(istype(AI)) + var/client/C = AI.client + if (C in admins) + return //already been handled + + if(C.prefs.toggles & CHAT_LOOC) + var/display_name = src.key + if(holder) + if(holder.fakekey) + if(C.holder) + display_name = "[holder.fakekey]/([src.key])" + else + display_name = holder.fakekey to_chat(C, "LOOC: [display_name]: [msg]") diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index ede8a16a8b1..37f49d2b2ba 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -1,295 +1,295 @@ -/mob/var/suiciding = 0 - -/mob/living/carbon/human/verb/suicide() - set hidden = 1 - if(!ticker) - to_chat(src, "You can't commit suicide before the game starts!") - return - - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(istype(wear_mask, /obj/item/clothing/mask/happy)) - to_chat(src, "BUT WHY? I'M SO HAPPY!") - return - - var/mob/living/simple_animal/borer/B = has_brain_worms() - if(B && B.controlling) //Borer - to_chat(src, "You cannot commit suicide, your host is clinging to life enough to resist it.") - return - - var/permitted = 1 - var/list/allowed = list("Syndicate", "traitor", "Wizard", "Head Revolutionary", "Cultist", "Changeling") - for(var/T in allowed) - if(mind.special_role == T) - permitted = 1 - break - - if(!permitted) - message_admins("[ckey] has tried to suicide, but they were not permitted to due to being an antagonist.", 1) //Fairly urgent - to_chat(src, "Your masters and the gods won't let you do that without a proper reason.") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - if(!canmove || restrained()) //Just while I finish up the new 'fun' suiciding verb. This is to prevent metagaming via suicide - to_chat(src, "You can't commit suicide whilst restrained!") - return - suiciding = 1 - var/obj/item/held_item = get_active_hand() - if(held_item) - var/damagetype = held_item.suicide_act(src) - if(damagetype) - var/damage_mod = 1 - switch(damagetype) //Sorry about the magic numbers. - //brute = 1, burn = 2, tox = 4, oxy = 8 - if(15) //4 damage types - damage_mod = 4 - - if(6, 11, 13, 14) //3 damage types - damage_mod = 3 - - if(3, 5, 7, 9, 10, 12) //2 damage types - damage_mod = 2 - - if(1, 2, 4, 8) //1 damage type - damage_mod = 1 - - else //This should not happen, but if it does, everything should still work - damage_mod = 1 - - //Do 175 damage divided by the number of damage types applied. - if(damagetype & BRUTELOSS) - adjustBruteLoss(175/damage_mod) - - if(damagetype & FIRELOSS) - adjustFireLoss(175/damage_mod) - - if(damagetype & TOXLOSS) - adjustToxLoss(175/damage_mod) - - if(damagetype & OXYLOSS) - adjustOxyLoss(175/damage_mod) - - //If something went wrong, just do normal oxyloss - if(!(damagetype | BRUTELOSS) && !(damagetype | FIRELOSS) && !(damagetype | TOXLOSS) && !(damagetype | OXYLOSS)) - adjustOxyLoss(max(175 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - - updatehealth() - return - - - visible_message(pick("[src] is attempting to bite \his tongue off! It looks like \he's trying to commit suicide.", \ - "[src] is jamming \his thumbs into \his eye sockets! It looks like \he's trying to commit suicide.", \ - "[src] is twisting \his own neck! It looks like \he's trying to commit suicide.", \ - "[src] is holding \his breath! It looks like \he's trying to commit suicide.")) - adjustOxyLoss(max(175 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - updatehealth() - -/mob/living/carbon/brain/verb/suicide() - set hidden = 1 - if(!ticker) - to_chat(src, "You can't commit suicide before the game starts!") - return - - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - if(!container) - visible_message("[src]'s brain is growing dull and lifeless. It looks like it has lost the will to live.") - spawn(50) - death(0) - suiciding = 0 - -/mob/living/carbon/monkey/verb/suicide() - set hidden = 1 - if(!ticker) - to_chat(src, "You can't commit suicide before the game starts!") - return - - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/mob/living/simple_animal/borer/B=has_brain_worms() - if (B && B.controlling) // Borer - to_chat(src, "Your can't suicide while controlling your host, you dick.") - return - - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - if(!canmove || restrained()) - to_chat(src, "You can't commit suicide whilst restrained! ((You can type Ghost instead however.))") - return - suiciding = 1 - //instead of killing them instantly, just put them at -175 health and let 'em gasp for a while - visible_message("\The [src] is attempting to bite \his tongue off. It looks like \he's trying to commit suicide.") - adjustOxyLoss(max(175 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - updatehealth() - -/mob/living/silicon/ai/verb/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] is powering down. It looks like \he's trying to commit suicide.") - //put em at -175 - adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - updatehealth() - -/mob/living/silicon/robot/verb/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] is powering down. It looks like \he's trying to commit suicide.") - //put em at -175 - adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - stat = DEAD //new robot shit doesnt care about oxyloss - updatehealth() - -/mob/living/silicon/pai/verb/suicide() - set category = "pAI Commands" - set desc = "Kill yourself and become a ghost (You will receive a confirmation prompt)" - set name = "pAI Suicide" - var/answer = input("REALLY kill yourself? This action can't be undone.", "Suicide", "No") in list ("Yes", "No") - if(answer == "Yes") - var/obj/item/device/paicard/card = loc - card.removePersonality() - var/turf/T = get_turf(card.loc) - for (var/mob/M in viewers(T)) - visible_message("[src] flashes a message across its screen, \"Wiping core files. Please acquire a new personality to continue using pAI device functions.\"") - death(0) - -/mob/living/carbon/alien/humanoid/verb/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] is thrashing around wildly! It looks like \he's trying to commit suicide.") - //put em at -175 - adjustOxyLoss(max(175 - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - updatehealth() - -/mob/living/carbon/slime/verb/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] starts vibrating uncontrollably! It looks like \he's trying to commit suicide.") - setOxyLoss(100) - adjustBruteLoss(100 - getBruteLoss()) - setToxLoss(100) - setCloneLoss(100) - - updatehealth() - -//Default for all simple animals, using the Die() proc. Custom cases below -/mob/living/simple_animal/verb/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] suddenly starts thrashing around! It looks like \he's trying to commit suicide.") - Die() - -/mob/living/simple_animal/spiderbot/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] suddenly topples over and starts thrashing around! It looks like \he's trying to commit suicide.") - Die() //Handles death properly enough - -/mob/living/simple_animal/borer/suicide() - set hidden = 1 - if(stat == DEAD) - to_chat(src, "You're already dead!") - return - - if(suiciding) - to_chat(src, "You're already committing suicide! Be patient!") - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - visible_message("[src] suddenly starts trashing around [host ? "[host]'s head":""]! It looks like \he's trying to commit suicide.") - detach() - Die() +/mob/var/suiciding = 0 + +/mob/living/carbon/human/verb/suicide() + set hidden = 1 + if(!ticker) + to_chat(src, "You can't commit suicide before the game starts!") + return + + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(istype(wear_mask, /obj/item/clothing/mask/happy)) + to_chat(src, "BUT WHY? I'M SO HAPPY!") + return + + var/mob/living/simple_animal/borer/B = has_brain_worms() + if(B && B.controlling) //Borer + to_chat(src, "You cannot commit suicide, your host is clinging to life enough to resist it.") + return + + var/permitted = 1 + var/list/allowed = list("Syndicate", "traitor", "Wizard", "Head Revolutionary", "Cultist", "Changeling") + for(var/T in allowed) + if(mind.special_role == T) + permitted = 1 + break + + if(!permitted) + message_admins("[ckey] has tried to suicide, but they were not permitted to due to being an antagonist.", 1) //Fairly urgent + to_chat(src, "Your masters and the gods won't let you do that without a proper reason.") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + if(!canmove || restrained()) //Just while I finish up the new 'fun' suiciding verb. This is to prevent metagaming via suicide + to_chat(src, "You can't commit suicide whilst restrained!") + return + suiciding = 1 + var/obj/item/held_item = get_active_hand() + if(held_item) + var/damagetype = held_item.suicide_act(src) + if(damagetype) + var/damage_mod = 1 + switch(damagetype) //Sorry about the magic numbers. + //brute = 1, burn = 2, tox = 4, oxy = 8 + if(15) //4 damage types + damage_mod = 4 + + if(6, 11, 13, 14) //3 damage types + damage_mod = 3 + + if(3, 5, 7, 9, 10, 12) //2 damage types + damage_mod = 2 + + if(1, 2, 4, 8) //1 damage type + damage_mod = 1 + + else //This should not happen, but if it does, everything should still work + damage_mod = 1 + + //Do 175 damage divided by the number of damage types applied. + if(damagetype & BRUTELOSS) + adjustBruteLoss(175/damage_mod) + + if(damagetype & FIRELOSS) + adjustFireLoss(175/damage_mod) + + if(damagetype & TOXLOSS) + adjustToxLoss(175/damage_mod) + + if(damagetype & OXYLOSS) + adjustOxyLoss(175/damage_mod) + + //If something went wrong, just do normal oxyloss + if(!(damagetype | BRUTELOSS) && !(damagetype | FIRELOSS) && !(damagetype | TOXLOSS) && !(damagetype | OXYLOSS)) + adjustOxyLoss(max(175 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + + updatehealth() + return + + + visible_message(pick("[src] is attempting to bite \his tongue off! It looks like \he's trying to commit suicide.", \ + "[src] is jamming \his thumbs into \his eye sockets! It looks like \he's trying to commit suicide.", \ + "[src] is twisting \his own neck! It looks like \he's trying to commit suicide.", \ + "[src] is holding \his breath! It looks like \he's trying to commit suicide.")) + adjustOxyLoss(max(175 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + updatehealth() + +/mob/living/carbon/brain/verb/suicide() + set hidden = 1 + if(!ticker) + to_chat(src, "You can't commit suicide before the game starts!") + return + + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + if(!container) + visible_message("[src]'s brain is growing dull and lifeless. It looks like it has lost the will to live.") + spawn(50) + death(0) + suiciding = 0 + +/mob/living/carbon/monkey/verb/suicide() + set hidden = 1 + if(!ticker) + to_chat(src, "You can't commit suicide before the game starts!") + return + + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/mob/living/simple_animal/borer/B=has_brain_worms() + if (B && B.controlling) // Borer + to_chat(src, "Your can't suicide while controlling your host, you dick.") + return + + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + if(!canmove || restrained()) + to_chat(src, "You can't commit suicide whilst restrained! ((You can type Ghost instead however.))") + return + suiciding = 1 + //instead of killing them instantly, just put them at -175 health and let 'em gasp for a while + visible_message("\The [src] is attempting to bite \his tongue off. It looks like \he's trying to commit suicide.") + adjustOxyLoss(max(175 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + updatehealth() + +/mob/living/silicon/ai/verb/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] is powering down. It looks like \he's trying to commit suicide.") + //put em at -175 + adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + updatehealth() + +/mob/living/silicon/robot/verb/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] is powering down. It looks like \he's trying to commit suicide.") + //put em at -175 + adjustOxyLoss(max(maxHealth * 2 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + stat = DEAD //new robot shit doesnt care about oxyloss + updatehealth() + +/mob/living/silicon/pai/verb/suicide() + set category = "pAI Commands" + set desc = "Kill yourself and become a ghost (You will receive a confirmation prompt)" + set name = "pAI Suicide" + var/answer = input("REALLY kill yourself? This action can't be undone.", "Suicide", "No") in list ("Yes", "No") + if(answer == "Yes") + var/obj/item/device/paicard/card = loc + card.removePersonality() + var/turf/T = get_turf(card.loc) + for (var/mob/M in viewers(T)) + visible_message("[src] flashes a message across its screen, \"Wiping core files. Please acquire a new personality to continue using pAI device functions.\"") + death(0) + +/mob/living/carbon/alien/humanoid/verb/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] is thrashing around wildly! It looks like \he's trying to commit suicide.") + //put em at -175 + adjustOxyLoss(max(175 - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) + updatehealth() + +/mob/living/carbon/slime/verb/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] starts vibrating uncontrollably! It looks like \he's trying to commit suicide.") + setOxyLoss(100) + adjustBruteLoss(100 - getBruteLoss()) + setToxLoss(100) + setCloneLoss(100) + + updatehealth() + +//Default for all simple animals, using the Die() proc. Custom cases below +/mob/living/simple_animal/verb/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] suddenly starts thrashing around! It looks like \he's trying to commit suicide.") + Die() + +/mob/living/simple_animal/spiderbot/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] suddenly topples over and starts thrashing around! It looks like \he's trying to commit suicide.") + Die() //Handles death properly enough + +/mob/living/simple_animal/borer/suicide() + set hidden = 1 + if(stat == DEAD) + to_chat(src, "You're already dead!") + return + + if(suiciding) + to_chat(src, "You're already committing suicide! Be patient!") + return + + var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") + + if(confirm == "Yes") + suiciding = 1 + visible_message("[src] suddenly starts trashing around [host ? "[host]'s head":""]! It looks like \he's trying to commit suicide.") + detach() + Die() diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index a38dac973dd..fda243fa423 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -1,114 +1,114 @@ -/client/verb/who() - set name = "Who" - set category = "OOC" - - var/msg = "\nCurrent Players:\n" - - var/list/Lines = list() - - if (holder) - for (var/client/C in clients) - var/entry = "\t[C.key]" - - if (C.holder && C.holder.fakekey) - entry += " (as [C.holder.fakekey])" - - if(C.mob.real_name) - entry += " - Playing as [C.mob.real_name]" - - switch (C.mob.stat) - if (UNCONSCIOUS) - entry += " - Unconscious" - - if (DEAD) - if (isobserver(C.mob)) - var/mob/dead/observer/O = C.mob - - if (O.started_as_observer) - entry += " - Observing" - else - entry += " - DEAD" - else if (isnewplayer(C.mob)) - entry += " - Lobby" - else - entry += " - DEAD" - - if (is_special_character(C.mob)) - entry += " - Antagonist" - - entry += " (?)" - Lines += entry - - log_admin("[key_name(usr)] used who verb advanced (shows OOC key - IC name, status and if antagonist)") - else - for (var/client/C in clients) - if (C.holder && C.holder.fakekey) - Lines += C.holder.fakekey - else - Lines += C.key - - for (var/line in sortList(Lines)) - msg += "[line]\n" - - msg += "Total Players: [length(Lines)]\n" +/client/verb/who() + set name = "Who" + set category = "OOC" + + var/msg = "\nCurrent Players:\n" + + var/list/Lines = list() + + if (holder) + for (var/client/C in clients) + var/entry = "\t[C.key]" + + if (C.holder && C.holder.fakekey) + entry += " (as [C.holder.fakekey])" + + if(C.mob.real_name) + entry += " - Playing as [C.mob.real_name]" + + switch (C.mob.stat) + if (UNCONSCIOUS) + entry += " - Unconscious" + + if (DEAD) + if (isobserver(C.mob)) + var/mob/dead/observer/O = C.mob + + if (O.started_as_observer) + entry += " - Observing" + else + entry += " - DEAD" + else if (isnewplayer(C.mob)) + entry += " - Lobby" + else + entry += " - DEAD" + + if (is_special_character(C.mob)) + entry += " - Antagonist" + + entry += " (?)" + Lines += entry + + log_admin("[key_name(usr)] used who verb advanced (shows OOC key - IC name, status and if antagonist)") + else + for (var/client/C in clients) + if (C.holder && C.holder.fakekey) + Lines += C.holder.fakekey + else + Lines += C.key + + for (var/line in sortList(Lines)) + msg += "[line]\n" + + msg += "Total Players: [length(Lines)]\n" to_chat(src, msg) - -/client/verb/adminwho() - set category = "Admin" - set name = "Adminwho" - - var/aNames = "" - var/mNames = "" - var/numAdminsOnline = 0 - var/numModsOnline = 0 - - if (holder) - for (var/client/C in admins) - if (R_ADMIN & C.holder.rights || !(R_MOD & C.holder.rights)) - aNames += "\t[C] is a [C.holder.rank]" - - if (C.holder.fakekey) - aNames += " (as [C.holder.fakekey])" - - if (isobserver(C.mob)) - aNames += " - Observing" - else if (istype(C.mob,/mob/new_player)) - aNames += " - Lobby" - else - aNames += " - Playing" - - if (C.is_afk()) - aNames += " (AFK)" - - aNames += "\n" - numAdminsOnline++ - else - mNames += "\t[C] is a [C.holder.rank]" - - if (C.holder.fakekey) - mNames += " (as [C.holder.fakekey])" - - if (isobserver(C.mob)) - mNames += " - Observing" - else if (istype(C.mob,/mob/new_player)) - mNames += " - Lobby" - else - mNames += " - Playing" - - if (C.is_afk()) - mNames += " (AFK)" - - mNames += "\n" - numModsOnline++ - else - for (var/client/C in admins) - if (R_ADMIN & C.holder.rights || !(R_MOD & C.holder.rights)) - if (!C.holder.fakekey) - aNames += "\t[C] is a [C.holder.rank]\n" - numAdminsOnline++ - else - if (!C.holder.fakekey) - mNames += "\t[C] is a [C.holder.rank]\n" - numModsOnline++ - + +/client/verb/adminwho() + set category = "Admin" + set name = "Adminwho" + + var/aNames = "" + var/mNames = "" + var/numAdminsOnline = 0 + var/numModsOnline = 0 + + if (holder) + for (var/client/C in admins) + if (R_ADMIN & C.holder.rights || !(R_MOD & C.holder.rights)) + aNames += "\t[C] is a [C.holder.rank]" + + if (C.holder.fakekey) + aNames += " (as [C.holder.fakekey])" + + if (isobserver(C.mob)) + aNames += " - Observing" + else if (istype(C.mob,/mob/new_player)) + aNames += " - Lobby" + else + aNames += " - Playing" + + if (C.is_afk()) + aNames += " (AFK)" + + aNames += "\n" + numAdminsOnline++ + else + mNames += "\t[C] is a [C.holder.rank]" + + if (C.holder.fakekey) + mNames += " (as [C.holder.fakekey])" + + if (isobserver(C.mob)) + mNames += " - Observing" + else if (istype(C.mob,/mob/new_player)) + mNames += " - Lobby" + else + mNames += " - Playing" + + if (C.is_afk()) + mNames += " (AFK)" + + mNames += "\n" + numModsOnline++ + else + for (var/client/C in admins) + if (R_ADMIN & C.holder.rights || !(R_MOD & C.holder.rights)) + if (!C.holder.fakekey) + aNames += "\t[C] is a [C.holder.rank]\n" + numAdminsOnline++ + else + if (!C.holder.fakekey) + mNames += "\t[C] is a [C.holder.rank]\n" + numModsOnline++ + to_chat(src, "\nCurrent Admins ([numAdminsOnline]):\n" + aNames + "\nCurrent Moderators ([numModsOnline]):\n" + mNames + "\n") diff --git a/code/global.dm b/code/global.dm index 1502dbf8659..ea7437b00f7 100644 --- a/code/global.dm +++ b/code/global.dm @@ -1,395 +1,395 @@ -//Content of the Round End Information window -var/round_end_info = "" - -//List of ckeys that have de-adminned themselves during this round -var/global/list/deadmins = list() - -// List of types and how many instances of each type there are. -var/global/list/type_instances[0] - -/var/global/datum/map/active/map = new() //Current loaded map -//Defined in its .dm, see maps/_map.dm for more info. - -var/global/obj/effect/datacore/data_core = null -var/global/obj/effect/overlay/plmaster = null -var/global/obj/effect/overlay/slmaster = null - -var/global/list/account_DBs = list() - -// Used only by space turfs. TODO: Remove. -// The comment below is no longer accurate. -var/global/list/global_map = null - - //list/global_map = list(list(1,5),list(4,3))//an array of map Z levels. - //Resulting sector map looks like - //|_1_|_4_| - //|_5_|_3_| - // - //1 - SS13 - //4 - Derelict - //3 - AI satellite - //5 - empty space - -var/global/datum/universal_state/universe = new - -var/list/paper_tag_whitelist = list("center","p","div","span","h1","h2","h3","h4","h5","h6","hr","pre", \ - "big","small","font","i","u","b","s","sub","sup","tt","br","hr","ol","ul","li","caption","col", \ - "table","td","th","tr") -var/list/paper_blacklist = list("java","onblur","onchange","onclick","ondblclick","onfocus","onkeydown", \ - "onkeypress","onkeyup","onload","onmousedown","onmousemove","onmouseout","onmouseover", \ - "onmouseup","onreset","onselect","onsubmit","onunload") - -var/BLINDBLOCK = 0 -var/DEAFBLOCK = 0 -var/HULKBLOCK = 0 -var/TELEBLOCK = 0 -var/FIREBLOCK = 0 -var/XRAYBLOCK = 0 -var/CLUMSYBLOCK = 0 -var/FAKEBLOCK = 0 -var/COUGHBLOCK = 0 -var/GLASSESBLOCK = 0 -var/EPILEPSYBLOCK = 0 -var/TWITCHBLOCK = 0 -var/NERVOUSBLOCK = 0 -var/MONKEYBLOCK = 54 // Monkey block will always be the DNA_SE_LENGTH - -var/BLOCKADD = 0 -var/DIFFMUT = 0 - -var/HEADACHEBLOCK = 0 -var/NOBREATHBLOCK = 0 -var/REMOTEVIEWBLOCK = 0 -var/REGENERATEBLOCK = 0 -var/INCREASERUNBLOCK = 0 -var/REMOTETALKBLOCK = 0 -var/MORPHBLOCK = 0 -var/COLDBLOCK = 0 -var/HALLUCINATIONBLOCK = 0 -var/NOPRINTSBLOCK = 0 -var/SHOCKIMMUNITYBLOCK = 0 -var/SMALLSIZEBLOCK = 0 - -/////////////////////////////// -// Goon Stuff -/////////////////////////////// -// Disabilities -var/LISPBLOCK = 0 -var/MUTEBLOCK = 0 -var/RADBLOCK = 0 -var/FATBLOCK = 0 -var/CHAVBLOCK = 0 -var/SWEDEBLOCK = 0 -var/SCRAMBLEBLOCK = 0 -var/TOXICFARTBLOCK = 0 -var/STRONGBLOCK = 0 -var/HORNSBLOCK = 0 -var/SMILEBLOCK = 0 -var/ELVISBLOCK = 0 - -// Powers -var/SOBERBLOCK = 0 -var/PSYRESISTBLOCK = 0 -//var/SHADOWBLOCK = 0 -var/FARSIGHTBLOCK = 0 -var/CHAMELEONBLOCK = 0 -var/CRYOBLOCK = 0 -var/EATBLOCK = 0 -var/JUMPBLOCK = 0 -var/MELTBLOCK = 0 -var/EMPATHBLOCK = 0 -var/SUPERFARTBLOCK = 0 -var/IMMOLATEBLOCK = 0 -var/POLYMORPHBLOCK = 0 - -/////////////////////////////// -// /vg/ Mutations -/////////////////////////////// -var/LOUDBLOCK = 0 -var/WHISPERBLOCK = 0 -var/DIZZYBLOCK = 0 -var/SANSBLOCK = 0 - - - - -var/skipupdate = 0 - /////////////// -var/eventchance = 10 //% per 5 mins -var/event = 0 -var/hadevent = 0 -var/blobevent = 0 - /////////////// -var/starticon = null -var/midicon = null -var/endicon = null -var/diary = null -var/diaryofmeanpeople = null -var/admin_diary = null -var/href_logfile = null -var/station_name = null -var/game_version = "veegee" -var/changelog_hash = "" -var/game_year = (text2num(time2text(world.realtime, "YYYY")) + 544) - -var/datum/air_tunnel/air_tunnel1/SS13_airtunnel = null -var/going = 1.0 -var/master_mode = "extended"//"extended" -var/secret_force_mode = "secret" // if this is anything but "secret", the secret rotation will forceably choose this mode - -var/datum/engine_eject/engine_eject_control = null -var/host = null -var/aliens_allowed = 1 -var/ooc_allowed = 1 -var/dooc_allowed = 1 -var/traitor_scaling = 1 -//var/goonsay_allowed = 0 -var/dna_ident = 1 -var/abandon_allowed = 1 -var/enter_allowed = 1 -var/guests_allowed = 1 -var/shuttle_frozen = 0 -var/shuttle_left = 0 -var/tinted_weldhelh = 1 - -var/list/jobMax = list() -var/list/bombers = list( ) -var/list/admin_log = list ( ) -var/list/lastsignalers = list( ) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]" -var/list/lawchanges = list( ) //Stores who uploaded laws to which silicon-based lifeform, and what the law was -var/list/shuttles = list( ) -var/list/reg_dna = list( ) -// list/traitobj = list( ) - -var/CELLRATE = 0.002 // multiplier for watts per tick <> cell storage (eg: .002 means if there is a load of 1000 watts, 20 units will be taken from a cell per second) -var/CHARGELEVEL = 0.001 // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second) - -// COORDINATE OFFSETS -// Used for telescience. Only apply to GPSes and other things that display coordinates to players. -// The idea is that coordinates given will be entirely different from those displayed on the map in DreamMaker, -// while still making it very simple to lock onto someone who is drifting in space. -var/list/WORLD_X_OFFSET = list() -var/list/WORLD_Y_OFFSET = list() - -var/shuttle_z = 2 //default -var/airtunnel_start = 68 // default -var/airtunnel_stop = 68 // default -var/airtunnel_bottom = 72 // default -var/list/monkeystart = list() -var/list/wizardstart = list() -var/list/newplayer_start = list() -var/list/latejoin = list() -var/list/assistant_latejoin = list() -var/list/prisonwarp = list() //prisoners go to these -var/list/holdingfacility = list() //captured people go here -var/list/xeno_spawn = list()//Aliens spawn at these. -var/list/endgame_safespawns = list() -var/list/endgame_exits = list() -var/list/tdome1 = list() -var/list/tdome2 = list() -var/list/tdomeobserve = list() -var/list/tdomeadmin = list() -var/list/prisonsecuritywarp = list() //prison security goes to these -var/list/prisonwarped = list() //list of players already warped -var/list/blobstart = list() -var/list/ninjastart = list() -// list/traitors = list() //traitor list -var/list/cardinal = list( NORTH, SOUTH, EAST, WEST ) -var/list/diagonal = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) -var/list/alldirs = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) - -var/global/universal_cult_chat = 0 //if set to 1, even human cultists can use cultchat - -var/datum/station_state/start_state = null -var/datum/configuration/config = null - -var/list/combatlog = list() -var/list/IClog = list() -var/list/OOClog = list() -var/list/adminlog = list() - -var/suspend_alert = 0 - -var/Debug = 0 // global debug switch -var/Debug2 = 0 - -var/datum/debug/debugobj - -var/datum/moduletypes/mods = new() - -var/wavesecret = 0 -var/gravity_is_on = 1 - -var/shuttlecoming = 0 - -var/join_motd = null -var/forceblob = 0 - -var/polarstar = 0 //1 means that the polar star has been found, 2 means that the spur modification kit has been found - -// nanomanager, the manager for Nano UIs -var/datum/nanomanager/nanomanager = new() - -#define SPEED_OF_LIGHT 3e8 //not exact but hey! -#define SPEED_OF_LIGHT_SQ 9e+16 -#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215) -#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage. (default 2.025) -#define INFINITY 1e31 //closer then enough - - //Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam -#define MAX_MESSAGE_LEN 1024 -#define MAX_PAPER_MESSAGE_LEN 3072 -#define MAX_BOOK_MESSAGE_LEN 9216 -#define MAX_NAME_LEN 26 -#define MAX_BROADCAST_LEN 512 - -#define shuttle_time_in_station 1800 // 3 minutes in the station -#define shuttle_time_to_arrive 6000 // 10 minutes to arrive - - //away missions -var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to - - // MySQL configuration - -var/sqladdress = "localhost" -var/sqlport = "3306" -var/sqldb = "tgstation" -var/sqllogin = "root" -var/sqlpass = "" - - // Feedback gathering sql connection - -var/sqlfdbkdb = "test" -var/sqlfdbklogin = "root" -var/sqlfdbkpass = "" - -var/sqllogging = 0 // Should we log deaths, population stats, etc? - - - - // Forum MySQL configuration (for use with forum account/key authentication) - // These are all default values that will load should the forumdbconfig.txt - // file fail to read for whatever reason. - -var/forumsqladdress = "localhost" -var/forumsqlport = "3306" -var/forumsqldb = "tgstation" -var/forumsqllogin = "root" -var/forumsqlpass = "" -var/forum_activated_group = "2" -var/forum_authenticated_group = "10" - - // For FTP requests. (i.e. downloading runtime logs.) - // However it'd be ok to use for accessing attack logs and such too, which are even laggier. -var/fileaccess_timer = 0 -var/custom_event_msg = null - -//Database connections -//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.). -var/DBConnection/dbcon = new() //Feedback database (New database) -var/DBConnection/dbcon_old = new() //Tgstation database (Old database) - See the files in the SQL folder for information what goes where. - -#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day - -//Recall time limit: 2 hours -var/recall_time_limit = 72000 - -//Goonstyle scoreboard -//NOW AN ASSOCIATIVE LIST -//NO FUCKING EXCUSE FOR THE ATROCITY THAT WAS -var/list/score=list( - "crewscore" = 0, //This is the overall var/score for the whole round - "stuffshipped" = 0, //How many useful items have cargo shipped out? Currently broken - "stuffharvested" = 0, //How many harvests have hydroponics done (per crop)? - "oremined" = 0, //How many chunks of ore were smelted - "eventsendured" = 0, //How many random events did the station endure? - "powerloss" = 0, //How many APCs have alarms (under 30 %)? - "escapees" = 0, //How many people got out alive? - "deadcrew" = 0, //Humans who died during the round - "deadsilicon" = 0, //Silicons who died during the round - "mess" = 0, //How much messes on the floor went uncleaned - "litter" = 0, //How much trash is laying on the station floor - "meals" = 0, //How much food was actively cooked that day - "disease" = 0, //How many disease vectors in the world (one disease on one person is one) - - //These ones are mainly for the stat panel - "powerbonus" = 0, //If all APCs on the station are running optimally, big bonus - "messbonus" = 0, //If there are no messes on the station anywhere, huge bonus - "deadaipenalty" = 0, //AIs who died during the round - "foodeaten" = 0, //How much food was consumed - "clownabuse" = 0, //How many times a clown was punched, struck or otherwise maligned - "richestname" = null, //This is all stuff to show who was the richest alive on the shuttle - "richestjob" = null, //Kinda pointless if you dont have a money system i guess - "richestcash" = 0, - "richestkey" = null, - "dmgestname" = null, //Who had the most damage on the shuttle (but was still alive) - "dmgestjob" = null, - "dmgestdamage" = 0, - "dmgestkey" = null, - "explosions" = 0, //How many explosions happened total - - "arenafights" = 0, - "arenabest" = null, -) - -var/list/trash_items = list() -var/list/decals = list() - -// Mostly used for ban systems. -// Initialized on world/New() -var/global/event/on_login -var/global/event/on_ban -var/global/event/on_unban - -// List of /plugins -var/global/list/plugins = list() - -// Space get this to return for things i guess? -var/global/datum/gas_mixture/space_gas = new - -//Announcement intercom -var/global/obj/item/device/radio/intercom/universe/announcement_intercom = new - -//used by jump-to-area etc. Updated by area/updateName() -var/list/sortedAreas = list() - -var/global/bomberman_mode = 0 -var/global/bomberman_hurt = 0 -var/global/bomberman_destroy = 0 - -var/global/list/volunteer_gladiators = list() -var/global/list/ready_gladiators = list() -var/global/list/never_gladiators = list() - -var/global/list/achievements = list() - -//icons that appear on the Round End pop-up browser -var/global/list/end_icons = list() - -var/global/list/arena_leaderboard = list() -var/arena_rounds = 0 -var/arena_top_score = 0 - -var/endgame_info_logged = 0 - -var/explosion_newmethod = 1 // 1 = explosions take walls and obstacles into account; 0 = explosions pass through walls and obstacles without any impediments; - -//PDA games vars -//Snake II leaderboard -var/global/list/snake_station_highscores = list() -var/global/list/snake_best_players = list() - -//Minesweeper leaderboard -var/global/list/minesweeper_station_highscores = list() -var/global/list/minesweeper_best_players = list() - -var/nanocoins_rates = 1 -var/nanocoins_lastchange = 0 - -var/minimapinit = 0 - -var/datum/stat_collector/stat_collection = new - -//Hardcore mode -//When enabled, starvation kills -var/global/hardcore_mode = 0 +//Content of the Round End Information window +var/round_end_info = "" + +//List of ckeys that have de-adminned themselves during this round +var/global/list/deadmins = list() + +// List of types and how many instances of each type there are. +var/global/list/type_instances[0] + +/var/global/datum/map/active/map = new() //Current loaded map +//Defined in its .dm, see maps/_map.dm for more info. + +var/global/obj/effect/datacore/data_core = null +var/global/obj/effect/overlay/plmaster = null +var/global/obj/effect/overlay/slmaster = null + +var/global/list/account_DBs = list() + +// Used only by space turfs. TODO: Remove. +// The comment below is no longer accurate. +var/global/list/global_map = null + + //list/global_map = list(list(1,5),list(4,3))//an array of map Z levels. + //Resulting sector map looks like + //|_1_|_4_| + //|_5_|_3_| + // + //1 - SS13 + //4 - Derelict + //3 - AI satellite + //5 - empty space + +var/global/datum/universal_state/universe = new + +var/list/paper_tag_whitelist = list("center","p","div","span","h1","h2","h3","h4","h5","h6","hr","pre", \ + "big","small","font","i","u","b","s","sub","sup","tt","br","hr","ol","ul","li","caption","col", \ + "table","td","th","tr") +var/list/paper_blacklist = list("java","onblur","onchange","onclick","ondblclick","onfocus","onkeydown", \ + "onkeypress","onkeyup","onload","onmousedown","onmousemove","onmouseout","onmouseover", \ + "onmouseup","onreset","onselect","onsubmit","onunload") + +var/BLINDBLOCK = 0 +var/DEAFBLOCK = 0 +var/HULKBLOCK = 0 +var/TELEBLOCK = 0 +var/FIREBLOCK = 0 +var/XRAYBLOCK = 0 +var/CLUMSYBLOCK = 0 +var/FAKEBLOCK = 0 +var/COUGHBLOCK = 0 +var/GLASSESBLOCK = 0 +var/EPILEPSYBLOCK = 0 +var/TWITCHBLOCK = 0 +var/NERVOUSBLOCK = 0 +var/MONKEYBLOCK = 54 // Monkey block will always be the DNA_SE_LENGTH + +var/BLOCKADD = 0 +var/DIFFMUT = 0 + +var/HEADACHEBLOCK = 0 +var/NOBREATHBLOCK = 0 +var/REMOTEVIEWBLOCK = 0 +var/REGENERATEBLOCK = 0 +var/INCREASERUNBLOCK = 0 +var/REMOTETALKBLOCK = 0 +var/MORPHBLOCK = 0 +var/COLDBLOCK = 0 +var/HALLUCINATIONBLOCK = 0 +var/NOPRINTSBLOCK = 0 +var/SHOCKIMMUNITYBLOCK = 0 +var/SMALLSIZEBLOCK = 0 + +/////////////////////////////// +// Goon Stuff +/////////////////////////////// +// Disabilities +var/LISPBLOCK = 0 +var/MUTEBLOCK = 0 +var/RADBLOCK = 0 +var/FATBLOCK = 0 +var/CHAVBLOCK = 0 +var/SWEDEBLOCK = 0 +var/SCRAMBLEBLOCK = 0 +var/TOXICFARTBLOCK = 0 +var/STRONGBLOCK = 0 +var/HORNSBLOCK = 0 +var/SMILEBLOCK = 0 +var/ELVISBLOCK = 0 + +// Powers +var/SOBERBLOCK = 0 +var/PSYRESISTBLOCK = 0 +//var/SHADOWBLOCK = 0 +var/FARSIGHTBLOCK = 0 +var/CHAMELEONBLOCK = 0 +var/CRYOBLOCK = 0 +var/EATBLOCK = 0 +var/JUMPBLOCK = 0 +var/MELTBLOCK = 0 +var/EMPATHBLOCK = 0 +var/SUPERFARTBLOCK = 0 +var/IMMOLATEBLOCK = 0 +var/POLYMORPHBLOCK = 0 + +/////////////////////////////// +// /vg/ Mutations +/////////////////////////////// +var/LOUDBLOCK = 0 +var/WHISPERBLOCK = 0 +var/DIZZYBLOCK = 0 +var/SANSBLOCK = 0 + + + + +var/skipupdate = 0 + /////////////// +var/eventchance = 10 //% per 5 mins +var/event = 0 +var/hadevent = 0 +var/blobevent = 0 + /////////////// +var/starticon = null +var/midicon = null +var/endicon = null +var/diary = null +var/diaryofmeanpeople = null +var/admin_diary = null +var/href_logfile = null +var/station_name = null +var/game_version = "veegee" +var/changelog_hash = "" +var/game_year = (text2num(time2text(world.realtime, "YYYY")) + 544) + +var/datum/air_tunnel/air_tunnel1/SS13_airtunnel = null +var/going = 1.0 +var/master_mode = "extended"//"extended" +var/secret_force_mode = "secret" // if this is anything but "secret", the secret rotation will forceably choose this mode + +var/datum/engine_eject/engine_eject_control = null +var/host = null +var/aliens_allowed = 1 +var/ooc_allowed = 1 +var/dooc_allowed = 1 +var/traitor_scaling = 1 +//var/goonsay_allowed = 0 +var/dna_ident = 1 +var/abandon_allowed = 1 +var/enter_allowed = 1 +var/guests_allowed = 1 +var/shuttle_frozen = 0 +var/shuttle_left = 0 +var/tinted_weldhelh = 1 + +var/list/jobMax = list() +var/list/bombers = list( ) +var/list/admin_log = list ( ) +var/list/lastsignalers = list( ) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]" +var/list/lawchanges = list( ) //Stores who uploaded laws to which silicon-based lifeform, and what the law was +var/list/shuttles = list( ) +var/list/reg_dna = list( ) +// list/traitobj = list( ) + +var/CELLRATE = 0.002 // multiplier for watts per tick <> cell storage (eg: .002 means if there is a load of 1000 watts, 20 units will be taken from a cell per second) +var/CHARGELEVEL = 0.001 // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second) + +// COORDINATE OFFSETS +// Used for telescience. Only apply to GPSes and other things that display coordinates to players. +// The idea is that coordinates given will be entirely different from those displayed on the map in DreamMaker, +// while still making it very simple to lock onto someone who is drifting in space. +var/list/WORLD_X_OFFSET = list() +var/list/WORLD_Y_OFFSET = list() + +var/shuttle_z = 2 //default +var/airtunnel_start = 68 // default +var/airtunnel_stop = 68 // default +var/airtunnel_bottom = 72 // default +var/list/monkeystart = list() +var/list/wizardstart = list() +var/list/newplayer_start = list() +var/list/latejoin = list() +var/list/assistant_latejoin = list() +var/list/prisonwarp = list() //prisoners go to these +var/list/holdingfacility = list() //captured people go here +var/list/xeno_spawn = list()//Aliens spawn at these. +var/list/endgame_safespawns = list() +var/list/endgame_exits = list() +var/list/tdome1 = list() +var/list/tdome2 = list() +var/list/tdomeobserve = list() +var/list/tdomeadmin = list() +var/list/prisonsecuritywarp = list() //prison security goes to these +var/list/prisonwarped = list() //list of players already warped +var/list/blobstart = list() +var/list/ninjastart = list() +// list/traitors = list() //traitor list +var/list/cardinal = list( NORTH, SOUTH, EAST, WEST ) +var/list/diagonal = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) +var/list/alldirs = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) + +var/global/universal_cult_chat = 0 //if set to 1, even human cultists can use cultchat + +var/datum/station_state/start_state = null +var/datum/configuration/config = null + +var/list/combatlog = list() +var/list/IClog = list() +var/list/OOClog = list() +var/list/adminlog = list() + +var/suspend_alert = 0 + +var/Debug = 0 // global debug switch +var/Debug2 = 0 + +var/datum/debug/debugobj + +var/datum/moduletypes/mods = new() + +var/wavesecret = 0 +var/gravity_is_on = 1 + +var/shuttlecoming = 0 + +var/join_motd = null +var/forceblob = 0 + +var/polarstar = 0 //1 means that the polar star has been found, 2 means that the spur modification kit has been found + +// nanomanager, the manager for Nano UIs +var/datum/nanomanager/nanomanager = new() + +#define SPEED_OF_LIGHT 3e8 //not exact but hey! +#define SPEED_OF_LIGHT_SQ 9e+16 +#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215) +#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage. (default 2.025) +#define INFINITY 1e31 //closer then enough + + //Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam +#define MAX_MESSAGE_LEN 1024 +#define MAX_PAPER_MESSAGE_LEN 3072 +#define MAX_BOOK_MESSAGE_LEN 9216 +#define MAX_NAME_LEN 26 +#define MAX_BROADCAST_LEN 512 + +#define shuttle_time_in_station 1800 // 3 minutes in the station +#define shuttle_time_to_arrive 6000 // 10 minutes to arrive + + //away missions +var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to + + // MySQL configuration + +var/sqladdress = "localhost" +var/sqlport = "3306" +var/sqldb = "tgstation" +var/sqllogin = "root" +var/sqlpass = "" + + // Feedback gathering sql connection + +var/sqlfdbkdb = "test" +var/sqlfdbklogin = "root" +var/sqlfdbkpass = "" + +var/sqllogging = 0 // Should we log deaths, population stats, etc? + + + + // Forum MySQL configuration (for use with forum account/key authentication) + // These are all default values that will load should the forumdbconfig.txt + // file fail to read for whatever reason. + +var/forumsqladdress = "localhost" +var/forumsqlport = "3306" +var/forumsqldb = "tgstation" +var/forumsqllogin = "root" +var/forumsqlpass = "" +var/forum_activated_group = "2" +var/forum_authenticated_group = "10" + + // For FTP requests. (i.e. downloading runtime logs.) + // However it'd be ok to use for accessing attack logs and such too, which are even laggier. +var/fileaccess_timer = 0 +var/custom_event_msg = null + +//Database connections +//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.). +var/DBConnection/dbcon = new() //Feedback database (New database) +var/DBConnection/dbcon_old = new() //Tgstation database (Old database) - See the files in the SQL folder for information what goes where. + +#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day + +//Recall time limit: 2 hours +var/recall_time_limit = 72000 + +//Goonstyle scoreboard +//NOW AN ASSOCIATIVE LIST +//NO FUCKING EXCUSE FOR THE ATROCITY THAT WAS +var/list/score=list( + "crewscore" = 0, //This is the overall var/score for the whole round + "stuffshipped" = 0, //How many useful items have cargo shipped out? Currently broken + "stuffharvested" = 0, //How many harvests have hydroponics done (per crop)? + "oremined" = 0, //How many chunks of ore were smelted + "eventsendured" = 0, //How many random events did the station endure? + "powerloss" = 0, //How many APCs have alarms (under 30 %)? + "escapees" = 0, //How many people got out alive? + "deadcrew" = 0, //Humans who died during the round + "deadsilicon" = 0, //Silicons who died during the round + "mess" = 0, //How much messes on the floor went uncleaned + "litter" = 0, //How much trash is laying on the station floor + "meals" = 0, //How much food was actively cooked that day + "disease" = 0, //How many disease vectors in the world (one disease on one person is one) + + //These ones are mainly for the stat panel + "powerbonus" = 0, //If all APCs on the station are running optimally, big bonus + "messbonus" = 0, //If there are no messes on the station anywhere, huge bonus + "deadaipenalty" = 0, //AIs who died during the round + "foodeaten" = 0, //How much food was consumed + "clownabuse" = 0, //How many times a clown was punched, struck or otherwise maligned + "richestname" = null, //This is all stuff to show who was the richest alive on the shuttle + "richestjob" = null, //Kinda pointless if you dont have a money system i guess + "richestcash" = 0, + "richestkey" = null, + "dmgestname" = null, //Who had the most damage on the shuttle (but was still alive) + "dmgestjob" = null, + "dmgestdamage" = 0, + "dmgestkey" = null, + "explosions" = 0, //How many explosions happened total + + "arenafights" = 0, + "arenabest" = null, +) + +var/list/trash_items = list() +var/list/decals = list() + +// Mostly used for ban systems. +// Initialized on world/New() +var/global/event/on_login +var/global/event/on_ban +var/global/event/on_unban + +// List of /plugins +var/global/list/plugins = list() + +// Space get this to return for things i guess? +var/global/datum/gas_mixture/space_gas = new + +//Announcement intercom +var/global/obj/item/device/radio/intercom/universe/announcement_intercom = new + +//used by jump-to-area etc. Updated by area/updateName() +var/list/sortedAreas = list() + +var/global/bomberman_mode = 0 +var/global/bomberman_hurt = 0 +var/global/bomberman_destroy = 0 + +var/global/list/volunteer_gladiators = list() +var/global/list/ready_gladiators = list() +var/global/list/never_gladiators = list() + +var/global/list/achievements = list() + +//icons that appear on the Round End pop-up browser +var/global/list/end_icons = list() + +var/global/list/arena_leaderboard = list() +var/arena_rounds = 0 +var/arena_top_score = 0 + +var/endgame_info_logged = 0 + +var/explosion_newmethod = 1 // 1 = explosions take walls and obstacles into account; 0 = explosions pass through walls and obstacles without any impediments; + +//PDA games vars +//Snake II leaderboard +var/global/list/snake_station_highscores = list() +var/global/list/snake_best_players = list() + +//Minesweeper leaderboard +var/global/list/minesweeper_station_highscores = list() +var/global/list/minesweeper_best_players = list() + +var/nanocoins_rates = 1 +var/nanocoins_lastchange = 0 + +var/minimapinit = 0 + +var/datum/stat_collector/stat_collection = new + +//Hardcore mode +//When enabled, starvation kills +var/global/hardcore_mode = 0 diff --git a/code/hub.dm b/code/hub.dm index 24422099b74..204068fbe5a 100644 --- a/code/hub.dm +++ b/code/hub.dm @@ -1,13 +1,13 @@ -/world - - hub = "Exadv1.spacestation13" - hub_password = "SORRYNOPASSWORD" - name = "Baystation12" -/* This is for any host that would like their server to appear on the main SS13 hub. -To use it, simply replace the password above, with the password found below, and it should work. -If not, let us know on the main tgstation IRC channel of irc.rizon.net #tgstation13 we can help you there. - - hub = "Exadv1.spacestation13" - hub_password = "kMZy3U5jJHSiBQjr" - name = "Space Station 13" +/world + + hub = "Exadv1.spacestation13" + hub_password = "SORRYNOPASSWORD" + name = "Baystation12" +/* This is for any host that would like their server to appear on the main SS13 hub. +To use it, simply replace the password above, with the password found below, and it should work. +If not, let us know on the main tgstation IRC channel of irc.rizon.net #tgstation13 we can help you there. + + hub = "Exadv1.spacestation13" + hub_password = "kMZy3U5jJHSiBQjr" + name = "Space Station 13" */ \ No newline at end of file diff --git a/code/js/byjax.dm b/code/js/byjax.dm index c776b8ac776..6f855a705cd 100644 --- a/code/js/byjax.dm +++ b/code/js/byjax.dm @@ -1,50 +1,50 @@ -//this function places received data into element with specified id. -var/const/js_byjax = {" - -function replaceContent() { - var args = Array.prototype.slice.call(arguments); - var id = args\[0\]; - var content = args\[1\]; - var callback = null; - if(args\[2\]){ - callback = args\[2\]; - if(args\[3\]){ - args = args.slice(3); - } - } - var parent = document.getElementById(id); - if(typeof(parent)!=='undefined' && parent!=null){ - parent.innerHTML = content?content:''; - } - if(callback && window\[callback\]){ - window\[callback\].apply(null,args); - } -} -"} - -/* -sends data to control_id:replaceContent - -receiver - mob -control_id - window id (for windows opened with browse(), it'll be "windowname.browser") -target_element - HTML element id -new_content - HTML content -callback - js function that will be called after the data is sent -callback_args - arguments for callback function - -Be sure to include required js functions in your page, or it'll raise an exception. -*/ -proc/send_byjax(receiver, control_id, target_element, new_content=null, callback=null, list/callback_args=null) - if(receiver && target_element && control_id) // && winexists(receiver, control_id)) - var/list/argums = list(target_element, new_content) - if(callback) - argums += callback - if(callback_args) - argums += callback_args - argums = list2params(argums) -/* if(callback_args) - argums += "&[list2params(callback_args)]" -*/ - receiver << output(argums,"[control_id]:replaceContent") - return - +//this function places received data into element with specified id. +var/const/js_byjax = {" + +function replaceContent() { + var args = Array.prototype.slice.call(arguments); + var id = args\[0\]; + var content = args\[1\]; + var callback = null; + if(args\[2\]){ + callback = args\[2\]; + if(args\[3\]){ + args = args.slice(3); + } + } + var parent = document.getElementById(id); + if(typeof(parent)!=='undefined' && parent!=null){ + parent.innerHTML = content?content:''; + } + if(callback && window\[callback\]){ + window\[callback\].apply(null,args); + } +} +"} + +/* +sends data to control_id:replaceContent + +receiver - mob +control_id - window id (for windows opened with browse(), it'll be "windowname.browser") +target_element - HTML element id +new_content - HTML content +callback - js function that will be called after the data is sent +callback_args - arguments for callback function + +Be sure to include required js functions in your page, or it'll raise an exception. +*/ +proc/send_byjax(receiver, control_id, target_element, new_content=null, callback=null, list/callback_args=null) + if(receiver && target_element && control_id) // && winexists(receiver, control_id)) + var/list/argums = list(target_element, new_content) + if(callback) + argums += callback + if(callback_args) + argums += callback_args + argums = list2params(argums) +/* if(callback_args) + argums += "&[list2params(callback_args)]" +*/ + receiver << output(argums,"[control_id]:replaceContent") + return + diff --git a/code/js/menus.dm b/code/js/menus.dm index 69ff900db67..01137ce9630 100644 --- a/code/js/menus.dm +++ b/code/js/menus.dm @@ -1,37 +1,37 @@ -var/const/js_dropdowns = {" -function dropdowns() { - var divs = document.getElementsByTagName('div'); - var headers = new Array(); - var links = new Array(); - for(var i=0;i=0) { - elem.className = elem.className.replace('visible','hidden'); - this.className = this.className.replace('open','closed'); - this.innerHTML = this.innerHTML.replace('-','+'); - } - else { - elem.className = elem.className.replace('hidden','visible'); - this.className = this.className.replace('closed','open'); - this.innerHTML = this.innerHTML.replace('+','-'); - } - return false; - } - })(links\[i\]); - } - } -} +var/const/js_dropdowns = {" +function dropdowns() { + var divs = document.getElementsByTagName('div'); + var headers = new Array(); + var links = new Array(); + for(var i=0;i=0) { + elem.className = elem.className.replace('visible','hidden'); + this.className = this.className.replace('open','closed'); + this.innerHTML = this.innerHTML.replace('-','+'); + } + else { + elem.className = elem.className.replace('hidden','visible'); + this.className = this.className.replace('closed','open'); + this.innerHTML = this.innerHTML.replace('+','-'); + } + return false; + } + })(links\[i\]); + } + } +} "} \ No newline at end of file diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 74e144fb64b..c838853ddde 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -1,469 +1,469 @@ - -/datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null) - - - if(!check_rights(R_BAN)) return - - establish_db_connection() - if(!dbcon.IsConnected()) - return - - var/serverip = "[world.internet_address]:[world.port]" - var/bantype_pass = 0 - var/bantype_str - switch(bantype) - if(BANTYPE_PERMA) - bantype_str = "PERMABAN" - duration = -1 - bantype_pass = 1 - if(BANTYPE_TEMP) - bantype_str = "TEMPBAN" - bantype_pass = 1 - if(BANTYPE_JOB_PERMA) - bantype_str = "JOB_PERMABAN" - duration = -1 - bantype_pass = 1 - if(BANTYPE_JOB_TEMP) - bantype_str = "JOB_TEMPBAN" - bantype_pass = 1 - if(BANTYPE_APPEARANCE) - bantype_str = "APPEARANCE_PERMABAN" - bantype_pass = 1 - if(BANTYPE_OOC_PERMA) - bantype_str = "OOC_PERMABAN" - duration = -1 - bantype_pass = 1 - if(BANTYPE_OOC_TEMP) - bantype_str = "OOC_TEMPBAN" - bantype_pass = 1 - if( !bantype_pass ) return - if( !istext(reason) ) return - if( !isnum(duration) ) return - - var/ckey - var/computerid - var/ip - - if(ismob(banned_mob)) - ckey = banned_mob.ckey - if(banned_mob.client) - computerid = banned_mob.client.computer_id - ip = banned_mob.client.address - else if(banckey) - ckey = ckey(banckey) - - var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'") - query.Execute() - var/validckey = 0 - if(query.NextRow()) - validckey = 1 - if(!validckey) - if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key))) - message_admins("[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.",1) - return - - var/a_ckey - var/a_computerid - var/a_ip - - if(src.owner && istype(src.owner, /client)) - a_ckey = src.owner:ckey - a_computerid = src.owner:computer_id - a_ip = src.owner:address - - var/who - for(var/client/C in clients) - if(!who) - who = "[C]" - else - who += ", [C]" - - var/adminwho - for(var/client/C in admins) - if(!adminwho) - adminwho = "[C]" - else - adminwho += ", [C]" - - reason = sql_sanitize_text(reason) - - var/sql = "INSERT INTO erro_ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)" - var/DBQuery/query_insert = dbcon.NewQuery(sql) - query_insert.Execute() + +/datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null) + + + if(!check_rights(R_BAN)) return + + establish_db_connection() + if(!dbcon.IsConnected()) + return + + var/serverip = "[world.internet_address]:[world.port]" + var/bantype_pass = 0 + var/bantype_str + switch(bantype) + if(BANTYPE_PERMA) + bantype_str = "PERMABAN" + duration = -1 + bantype_pass = 1 + if(BANTYPE_TEMP) + bantype_str = "TEMPBAN" + bantype_pass = 1 + if(BANTYPE_JOB_PERMA) + bantype_str = "JOB_PERMABAN" + duration = -1 + bantype_pass = 1 + if(BANTYPE_JOB_TEMP) + bantype_str = "JOB_TEMPBAN" + bantype_pass = 1 + if(BANTYPE_APPEARANCE) + bantype_str = "APPEARANCE_PERMABAN" + bantype_pass = 1 + if(BANTYPE_OOC_PERMA) + bantype_str = "OOC_PERMABAN" + duration = -1 + bantype_pass = 1 + if(BANTYPE_OOC_TEMP) + bantype_str = "OOC_TEMPBAN" + bantype_pass = 1 + if( !bantype_pass ) return + if( !istext(reason) ) return + if( !isnum(duration) ) return + + var/ckey + var/computerid + var/ip + + if(ismob(banned_mob)) + ckey = banned_mob.ckey + if(banned_mob.client) + computerid = banned_mob.client.computer_id + ip = banned_mob.client.address + else if(banckey) + ckey = ckey(banckey) + + var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'") + query.Execute() + var/validckey = 0 + if(query.NextRow()) + validckey = 1 + if(!validckey) + if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key))) + message_admins("[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.",1) + return + + var/a_ckey + var/a_computerid + var/a_ip + + if(src.owner && istype(src.owner, /client)) + a_ckey = src.owner:ckey + a_computerid = src.owner:computer_id + a_ip = src.owner:address + + var/who + for(var/client/C in clients) + if(!who) + who = "[C]" + else + who += ", [C]" + + var/adminwho + for(var/client/C in admins) + if(!adminwho) + adminwho = "[C]" + else + adminwho += ", [C]" + + reason = sql_sanitize_text(reason) + + var/sql = "INSERT INTO erro_ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)" + var/DBQuery/query_insert = dbcon.NewQuery(sql) + query_insert.Execute() to_chat(usr, "Ban saved to database.") - message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1) - - INVOKE_EVENT(on_ban,list( - "ckey"=ckey, - "computer_id"=computerid, - "reason"=reason, - "duration"=duration, - "ip"=ip, - "type"=bantype, - "job"=job, - "admin"=usr - )) - - - -datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") - - - if(!check_rights(R_BAN)) return - - var/bantype_str - if(bantype) - var/bantype_pass = 0 - switch(bantype) - if(BANTYPE_PERMA) - bantype_str = "PERMABAN" - bantype_pass = 1 - if(BANTYPE_TEMP) - bantype_str = "TEMPBAN" - bantype_pass = 1 - if(BANTYPE_JOB_PERMA) - bantype_str = "JOB_PERMABAN" - bantype_pass = 1 - if(BANTYPE_JOB_TEMP) - bantype_str = "JOB_TEMPBAN" - bantype_pass = 1 - if(BANTYPE_APPEARANCE) - bantype_str = "APPEARANCE_PERMABAN" - bantype_pass = 1 - if(BANTYPE_ANY_FULLBAN) - bantype_str = "ANY" - bantype_pass = 1 - if( !bantype_pass ) return - - var/bantype_sql - if(bantype_str == "ANY") - bantype_sql = "(bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now() ) )" - else - bantype_sql = "bantype = '[bantype_str]'" - - var/sql = "SELECT id FROM erro_ban WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)" - if(job) - sql += " AND job = '[job]'" - - establish_db_connection() - if(!dbcon.IsConnected()) - return - - var/ban_id - var/ban_number = 0 //failsafe - - var/DBQuery/query = dbcon.NewQuery(sql) - query.Execute() - while(query.NextRow()) - ban_id = query.item[1] - ban_number++; - - if(ban_number == 0) + message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1) + + INVOKE_EVENT(on_ban,list( + "ckey"=ckey, + "computer_id"=computerid, + "reason"=reason, + "duration"=duration, + "ip"=ip, + "type"=bantype, + "job"=job, + "admin"=usr + )) + + + +datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") + + + if(!check_rights(R_BAN)) return + + var/bantype_str + if(bantype) + var/bantype_pass = 0 + switch(bantype) + if(BANTYPE_PERMA) + bantype_str = "PERMABAN" + bantype_pass = 1 + if(BANTYPE_TEMP) + bantype_str = "TEMPBAN" + bantype_pass = 1 + if(BANTYPE_JOB_PERMA) + bantype_str = "JOB_PERMABAN" + bantype_pass = 1 + if(BANTYPE_JOB_TEMP) + bantype_str = "JOB_TEMPBAN" + bantype_pass = 1 + if(BANTYPE_APPEARANCE) + bantype_str = "APPEARANCE_PERMABAN" + bantype_pass = 1 + if(BANTYPE_ANY_FULLBAN) + bantype_str = "ANY" + bantype_pass = 1 + if( !bantype_pass ) return + + var/bantype_sql + if(bantype_str == "ANY") + bantype_sql = "(bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now() ) )" + else + bantype_sql = "bantype = '[bantype_str]'" + + var/sql = "SELECT id FROM erro_ban WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)" + if(job) + sql += " AND job = '[job]'" + + establish_db_connection() + if(!dbcon.IsConnected()) + return + + var/ban_id + var/ban_number = 0 //failsafe + + var/DBQuery/query = dbcon.NewQuery(sql) + query.Execute() + while(query.NextRow()) + ban_id = query.item[1] + ban_number++; + + if(ban_number == 0) to_chat(usr, "Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin.") - return - - if(ban_number > 1) + return + + if(ban_number > 1) to_chat(usr, "Database update failed due to multiple bans fitting the search criteria. Note down the ckey, job and current time and contact the database admin.") - return - - if(istext(ban_id)) - ban_id = text2num(ban_id) - if(!isnum(ban_id)) + return + + if(istext(ban_id)) + ban_id = text2num(ban_id) + if(!isnum(ban_id)) to_chat(usr, "Database update failed due to a ban ID mismatch. Contact the database admin.") - return - - DB_ban_unban_by_id(ban_id) - -datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null) - - - if(!check_rights(R_BAN)) return - - if(!isnum(banid) || !istext(param)) + return + + DB_ban_unban_by_id(ban_id) + +datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null) + + + if(!check_rights(R_BAN)) return + + if(!isnum(banid) || !istext(param)) to_chat(usr, "Cancelled") - return - - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]") - query.Execute() - - var/eckey = usr.ckey //Editing admin ckey - var/pckey //(banned) Player ckey - var/duration //Old duration - var/reason //Old reason - - if(query.NextRow()) - pckey = query.item[1] - duration = query.item[2] - reason = query.item[3] - else + return + + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]") + query.Execute() + + var/eckey = usr.ckey //Editing admin ckey + var/pckey //(banned) Player ckey + var/duration //Old duration + var/reason //Old reason + + if(query.NextRow()) + pckey = query.item[1] + duration = query.item[2] + reason = query.item[3] + else to_chat(usr, "Invalid ban id. Contact the database admin") - return - - reason = sql_sanitize_text(reason) - var/value - - switch(param) - if("reason") - if(!value) - value = input("Insert the new reason for [pckey]'s ban", "New Reason", "[reason]", null) as null|text - value = sql_sanitize_text(value) - if(!value) + return + + reason = sql_sanitize_text(reason) + var/value + + switch(param) + if("reason") + if(!value) + value = input("Insert the new reason for [pckey]'s ban", "New Reason", "[reason]", null) as null|text + value = sql_sanitize_text(value) + if(!value) to_chat(usr, "Cancelled") - return - - var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
    ') WHERE id = [banid]") - update_query.Execute() - message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1) - if("duration") - if(!value) - value = input("Insert the new duration (in minutes) for [pckey]'s ban", "New Duration", "[duration]", null) as null|num - if(!isnum(value) || !value) + return + + var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
    ') WHERE id = [banid]") + update_query.Execute() + message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1) + if("duration") + if(!value) + value = input("Insert the new duration (in minutes) for [pckey]'s ban", "New Duration", "[duration]", null) as null|num + if(!isnum(value) || !value) to_chat(usr, "Cancelled") - return - - var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
    '), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") - message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1) - update_query.Execute() - if("unban") - if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes") - DB_ban_unban_by_id(banid) - return - else + return + + var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
    '), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") + message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1) + update_query.Execute() + if("unban") + if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes") + DB_ban_unban_by_id(banid) + return + else to_chat(usr, "Cancelled") - return - else + return + else to_chat(usr, "Cancelled") - return - -datum/admins/proc/DB_ban_unban_by_id(var/id) - - - if(!check_rights(R_BAN)) return - - var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]" - - establish_db_connection() - if(!dbcon.IsConnected()) - return - - var/ban_number = 0 //failsafe - - var/pckey - var/DBQuery/query = dbcon.NewQuery(sql) - query.Execute() - while(query.NextRow()) - pckey = query.item[1] - ban_number++; - - if(ban_number == 0) + return + +datum/admins/proc/DB_ban_unban_by_id(var/id) + + + if(!check_rights(R_BAN)) return + + var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]" + + establish_db_connection() + if(!dbcon.IsConnected()) + return + + var/ban_number = 0 //failsafe + + var/pckey + var/DBQuery/query = dbcon.NewQuery(sql) + query.Execute() + while(query.NextRow()) + pckey = query.item[1] + ban_number++; + + if(ban_number == 0) to_chat(usr, "Database update failed due to a ban id not being present in the database.") - return - - if(ban_number > 1) + return + + if(ban_number > 1) to_chat(usr, "Database update failed due to multiple bans having the same ID. Contact the database admin.") - return - - if(!src.owner || !istype(src.owner, /client)) - return - - var/unban_ckey = src.owner:ckey - var/unban_computerid = src.owner:computer_id - var/unban_ip = src.owner:address - - var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]" - message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1) - - var/DBQuery/query_update = dbcon.NewQuery(sql_update) - query_update.Execute() - - INVOKE_EVENT(on_unban,list( - "id"=id, - "ckey"=pckey, - - "admin"=src.owner - )) - -/client/proc/DB_ban_panel() - set category = "Admin" - set name = "Banning Panel" - set desc = "Edit admin permissions" - - if(!holder) - return - - holder.DB_ban_panel() - -/datum/admins/proc/DB_ban_panel(var/playerckey = null, var/adminckey = null) - if(!usr.client) - return - - if(!check_rights(R_BAN)) return - - establish_db_connection() - if(!dbcon.IsConnected()) + return + + if(!src.owner || !istype(src.owner, /client)) + return + + var/unban_ckey = src.owner:ckey + var/unban_computerid = src.owner:computer_id + var/unban_ip = src.owner:address + + var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]" + message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1) + + var/DBQuery/query_update = dbcon.NewQuery(sql_update) + query_update.Execute() + + INVOKE_EVENT(on_unban,list( + "id"=id, + "ckey"=pckey, + + "admin"=src.owner + )) + +/client/proc/DB_ban_panel() + set category = "Admin" + set name = "Banning Panel" + set desc = "Edit admin permissions" + + if(!holder) + return + + holder.DB_ban_panel() + +/datum/admins/proc/DB_ban_panel(var/playerckey = null, var/adminckey = null) + if(!usr.client) + return + + if(!check_rights(R_BAN)) return + + establish_db_connection() + if(!dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection") - return - - var/output = "
    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:282: output += " -
    " - output += {" -

    Banning panel

    -
    -
    Add custom ban: (ONLY use this if you can't ban through any other method) - - - - - -
    Ban type:Ckey:
    Duration: Job:
    " - output += {"
    - Reason:

    - - - - - -
    Search: - - Ckey: - Admin ckey: - -
    - Please note that all jobban bans or unbans are in-effect the following round."} - // END AUTOFIX - if(adminckey || playerckey) - - var/blcolor = "#ffeeee" //banned light - var/bdcolor = "#ffdddd" //banned dark - var/ulcolor = "#eeffee" //unbanned light - var/udcolor = "#ddffdd" //unbanned dark - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:333: output += "" - output += {"
    - - - - - - - "} - // END AUTOFIX - adminckey = ckey(adminckey) - playerckey = ckey(playerckey) - var/adminsearch = "" - var/playersearch = "" - if(adminckey) - adminsearch = "AND a_ckey = '[adminckey]' " - if(playerckey) - playersearch = "AND ckey = '[playerckey]' " - - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC") - select_query.Execute() - - while(select_query.NextRow()) - var/banid = select_query.item[1] - var/bantime = select_query.item[2] - var/bantype = select_query.item[3] - var/reason = select_query.item[4] - var/job = select_query.item[5] - var/duration = select_query.item[6] - var/expiration = select_query.item[7] - var/ckey = select_query.item[8] - var/ackey = select_query.item[9] - var/unbanned = select_query.item[10] - var/unbanckey = select_query.item[11] - var/unbantime = select_query.item[12] - var/edits = select_query.item[13] - - var/lcolor = blcolor - var/dcolor = bdcolor - if(unbanned) - lcolor = ulcolor - dcolor = udcolor - - var/typedesc ="" - switch(bantype) - if("PERMABAN") - typedesc = "PERMABAN" - if("TEMPBAN") - typedesc = "TEMPBAN
    ([duration] minutes [(unbanned) ? "" : "(Edit))"]
    Expires [expiration]
    " - if("JOB_PERMABAN") - typedesc = "JOBBAN
    ([job])" - if("JOB_TEMPBAN") - typedesc = "TEMP JOBBAN
    ([job])
    ([duration] minutes
    Expires [expiration]" - if("APPEARANCE_PERMABAN") - typedesc = "APPEARANCE/NAME BAN" - if("OOC_PERMABAN") - typedesc = "PERMA OOCBAN" - if("OOC_TEMPBAN") - typedesc = "TEMP OOCBAN" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:388: output += "
    " - output += {" - - - - - - - - - "} - // END AUTOFIX - if(edits) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:399: output += "" - output += {" - - - - - "} - // END AUTOFIX - if(unbanned) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:406: output += "" - output += {" - - "} - // END AUTOFIX - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:409: output += "" - output += {" - - "} - // END AUTOFIX - - output += "
    TYPECKEYTIME APPLIEDADMINOPTIONS
    [typedesc][ckey][bantime][ackey][(unbanned) ? "" : "Unban"]
    Reason: [(unbanned) ? "" : "(Edit)"] \"[reason]\"
    EDITS
    [edits]
    UNBANNED by admin [unbanckey] on [unbantime]
     
    " - + return + + var/output = "
    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:282: output += " +
    " + output += {" +

    Banning panel

    +
    +
    Add custom ban: (ONLY use this if you can't ban through any other method) + + + + + +
    Ban type:Ckey:
    Duration: Job:
    " + output += {"
    + Reason:

    + + + + + +
    Search: + + Ckey: + Admin ckey: + +
    + Please note that all jobban bans or unbans are in-effect the following round."} + // END AUTOFIX + if(adminckey || playerckey) + + var/blcolor = "#ffeeee" //banned light + var/bdcolor = "#ffdddd" //banned dark + var/ulcolor = "#eeffee" //unbanned light + var/udcolor = "#ddffdd" //unbanned dark + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:333: output += "" + output += {"
    + + + + + + + "} + // END AUTOFIX + adminckey = ckey(adminckey) + playerckey = ckey(playerckey) + var/adminsearch = "" + var/playersearch = "" + if(adminckey) + adminsearch = "AND a_ckey = '[adminckey]' " + if(playerckey) + playersearch = "AND ckey = '[playerckey]' " + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC") + select_query.Execute() + + while(select_query.NextRow()) + var/banid = select_query.item[1] + var/bantime = select_query.item[2] + var/bantype = select_query.item[3] + var/reason = select_query.item[4] + var/job = select_query.item[5] + var/duration = select_query.item[6] + var/expiration = select_query.item[7] + var/ckey = select_query.item[8] + var/ackey = select_query.item[9] + var/unbanned = select_query.item[10] + var/unbanckey = select_query.item[11] + var/unbantime = select_query.item[12] + var/edits = select_query.item[13] + + var/lcolor = blcolor + var/dcolor = bdcolor + if(unbanned) + lcolor = ulcolor + dcolor = udcolor + + var/typedesc ="" + switch(bantype) + if("PERMABAN") + typedesc = "PERMABAN" + if("TEMPBAN") + typedesc = "TEMPBAN
    ([duration] minutes [(unbanned) ? "" : "(Edit))"]
    Expires [expiration]
    " + if("JOB_PERMABAN") + typedesc = "JOBBAN
    ([job])" + if("JOB_TEMPBAN") + typedesc = "TEMP JOBBAN
    ([job])
    ([duration] minutes
    Expires [expiration]" + if("APPEARANCE_PERMABAN") + typedesc = "APPEARANCE/NAME BAN" + if("OOC_PERMABAN") + typedesc = "PERMA OOCBAN" + if("OOC_TEMPBAN") + typedesc = "TEMP OOCBAN" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:388: output += "
    " + output += {" + + + + + + + + + "} + // END AUTOFIX + if(edits) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:399: output += "" + output += {" + + + + + "} + // END AUTOFIX + if(unbanned) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:406: output += "" + output += {" + + "} + // END AUTOFIX + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\dB ban\functions.dm:409: output += "" + output += {" + + "} + // END AUTOFIX + + output += "
    TYPECKEYTIME APPLIEDADMINOPTIONS
    [typedesc][ckey][bantime][ackey][(unbanned) ? "" : "Unban"]
    Reason: [(unbanned) ? "" : "(Edit)"] \"[reason]\"
    EDITS
    [edits]
    UNBANNED by admin [unbanckey] on [unbantime]
     
    " + usr << browse(output,"window=lookupbans;size=900x500") \ No newline at end of file diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm index 433befa87ee..53f28268c57 100644 --- a/code/modules/admin/NewBan.dm +++ b/code/modules/admin/NewBan.dm @@ -1,232 +1,232 @@ -var/CMinutes = null -var/savefile/Banlist - - -/proc/CheckBan(var/ckey, var/id, var/address) - if(!Banlist) // if Banlist cannot be located for some reason - LoadBans() // try to load the bans - if(!Banlist) // uh oh, can't find bans! - return 0 // ABORT ABORT ABORT - - . = list() - var/appeal - if(config && config.banappeals) - appeal = "\nFor more information on your ban, or to appeal, head to [config.banappeals]" - Banlist.cd = "/base" - if( "[ckey][id]" in Banlist.dir ) - Banlist.cd = "[ckey][id]" - if (Banlist["temp"]) - if (!GetExp(Banlist["minutes"])) - ClearTempbans() - return 0 - else - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]" - else - Banlist.cd = "/base/[ckey][id]" - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: PERMENANT\nBy: [Banlist["bannedby"]][appeal]" - .["reason"] = "ckey/id" - return . - else - for (var/A in Banlist.dir) - Banlist.cd = "/base/[A]" - var/matches - if( ckey == Banlist["key"] ) - matches += "ckey" - if( id == Banlist["id"] ) - if(matches) - matches += "/" - matches += "id" - if( address == Banlist["ip"] ) - if(matches) - matches += "/" - matches += "ip" - - if(matches) - if(Banlist["temp"]) - if (!GetExp(Banlist["minutes"])) - ClearTempbans() - return 0 - else - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]" - else - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: PERMENANT\nBy: [Banlist["bannedby"]][appeal]" - .["reason"] = matches - return . - return 0 - -/proc/UpdateTime() //No idea why i made this a proc. - CMinutes = (world.realtime / 10) / 60 - return 1 - -/proc/LoadBans() - - - Banlist = new("data/banlist.bdb") - log_admin("Loading Banlist") - - if (!length(Banlist.dir)) log_admin("Banlist is empty.") - - if (!Banlist.dir.Find("base")) - log_admin("Banlist missing base dir.") - Banlist.dir.Add("base") - Banlist.cd = "/base" - else if (Banlist.dir.Find("base")) - Banlist.cd = "/base" - - ClearTempbans() - return 1 - -/proc/ClearTempbans() - UpdateTime() - - Banlist.cd = "/base" - for (var/A in Banlist.dir) - Banlist.cd = "/base/[A]" - if (!Banlist["key"] || !Banlist["id"]) - RemoveBan(A) - log_admin("Invalid Ban.") - message_admins("Invalid Ban.") - continue - - if (!Banlist["temp"]) continue - if (CMinutes >= Banlist["minutes"]) RemoveBan(A) - - return 1 - - -/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes, address) - - - var/bantimestamp - - if (temp) - UpdateTime() - bantimestamp = CMinutes + minutes - - Banlist.cd = "/base" - if ( Banlist.dir.Find("[ckey][computerid]") ) +var/CMinutes = null +var/savefile/Banlist + + +/proc/CheckBan(var/ckey, var/id, var/address) + if(!Banlist) // if Banlist cannot be located for some reason + LoadBans() // try to load the bans + if(!Banlist) // uh oh, can't find bans! + return 0 // ABORT ABORT ABORT + + . = list() + var/appeal + if(config && config.banappeals) + appeal = "\nFor more information on your ban, or to appeal, head to [config.banappeals]" + Banlist.cd = "/base" + if( "[ckey][id]" in Banlist.dir ) + Banlist.cd = "[ckey][id]" + if (Banlist["temp"]) + if (!GetExp(Banlist["minutes"])) + ClearTempbans() + return 0 + else + .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]" + else + Banlist.cd = "/base/[ckey][id]" + .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: PERMENANT\nBy: [Banlist["bannedby"]][appeal]" + .["reason"] = "ckey/id" + return . + else + for (var/A in Banlist.dir) + Banlist.cd = "/base/[A]" + var/matches + if( ckey == Banlist["key"] ) + matches += "ckey" + if( id == Banlist["id"] ) + if(matches) + matches += "/" + matches += "id" + if( address == Banlist["ip"] ) + if(matches) + matches += "/" + matches += "ip" + + if(matches) + if(Banlist["temp"]) + if (!GetExp(Banlist["minutes"])) + ClearTempbans() + return 0 + else + .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]" + else + .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: PERMENANT\nBy: [Banlist["bannedby"]][appeal]" + .["reason"] = matches + return . + return 0 + +/proc/UpdateTime() //No idea why i made this a proc. + CMinutes = (world.realtime / 10) / 60 + return 1 + +/proc/LoadBans() + + + Banlist = new("data/banlist.bdb") + log_admin("Loading Banlist") + + if (!length(Banlist.dir)) log_admin("Banlist is empty.") + + if (!Banlist.dir.Find("base")) + log_admin("Banlist missing base dir.") + Banlist.dir.Add("base") + Banlist.cd = "/base" + else if (Banlist.dir.Find("base")) + Banlist.cd = "/base" + + ClearTempbans() + return 1 + +/proc/ClearTempbans() + UpdateTime() + + Banlist.cd = "/base" + for (var/A in Banlist.dir) + Banlist.cd = "/base/[A]" + if (!Banlist["key"] || !Banlist["id"]) + RemoveBan(A) + log_admin("Invalid Ban.") + message_admins("Invalid Ban.") + continue + + if (!Banlist["temp"]) continue + if (CMinutes >= Banlist["minutes"]) RemoveBan(A) + + return 1 + + +/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes, address) + + + var/bantimestamp + + if (temp) + UpdateTime() + bantimestamp = CMinutes + minutes + + Banlist.cd = "/base" + if ( Banlist.dir.Find("[ckey][computerid]") ) to_chat(usr, text("Ban already exists.")) - return 0 - else - Banlist.dir.Add("[ckey][computerid]") - Banlist.cd = "/base/[ckey][computerid]" + return 0 + else + Banlist.dir.Add("[ckey][computerid]") + Banlist.cd = "/base/[ckey][computerid]" Banlist["key"] << ckey Banlist["id"] << computerid Banlist["ip"] << address Banlist["reason"] << reason Banlist["bannedby"] << bannedby Banlist["temp"] << temp - if (temp) + if (temp) Banlist["minutes"] << bantimestamp - return 1 - -/proc/RemoveBan(foldername) - var/key - var/id - - Banlist.cd = "/base/[foldername]" - Banlist["key"] >> key - Banlist["id"] >> id - Banlist.cd = "/base" - - if (!Banlist.dir.Remove(foldername)) return 0 - - if(!usr) - log_admin("Ban Expired: [key]") - message_admins("Ban Expired: [key]") - else - ban_unban_log_save("[key_name_admin(usr)] unbanned [key]") - log_admin("[key_name_admin(usr)] unbanned [key]") - message_admins("[key_name_admin(usr)] unbanned: [key]") - feedback_inc("ban_unban",1) - usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN) - for (var/A in Banlist.dir) - Banlist.cd = "/base/[A]" - if (key == Banlist["key"] /*|| id == Banlist["id"]*/) - Banlist.cd = "/base" - Banlist.dir.Remove(A) - continue - - return 1 - -/proc/GetExp(minutes as num) - UpdateTime() - var/exp = minutes - CMinutes - if (exp <= 0) - return 0 - else - var/timeleftstring - if (exp >= 1440) //1440 = 1 day in minutes - timeleftstring = "[round(exp / 1440, 0.1)] Days" - else if (exp >= 60) //60 = 1 hour in minutes - timeleftstring = "[round(exp / 60, 0.1)] Hours" - else - timeleftstring = "[exp] Minutes" - return timeleftstring - -/datum/admins/proc/unbanpanel() - var/count = 0 - var/dat - //var/dat = "
    Unban Player: (U) = Unban , (E) = Edit Ban(Total
    " - Banlist.cd = "/base" - for (var/A in Banlist.dir) - count++ - Banlist.cd = "/base/[A]" - var/ref = "\ref[src]" - var/key = Banlist["key"] - var/id = Banlist["id"] - var/ip = Banlist["ip"] - var/reason = Banlist["reason"] - var/by = Banlist["bannedby"] - var/expiry - if(Banlist["temp"]) - expiry = GetExp(Banlist["minutes"]) - if(!expiry) expiry = "Removal Pending" - else expiry = "Permaban" - - dat += text("") - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\NewBan.dm:187: dat += "
    (U)(E) Key: [key]ComputerID: [id]IP: [ip] [expiry](By: [by])(Reason: [reason])
    " - dat += {" -
    Bans: (U) = Unban , (E) = Edit Ban - ([count] Bans)
    [dat]"} - // END AUTOFIX - usr << browse(dat, "window=unbanp;size=875x400") - -//////////////////////////////////// DEBUG //////////////////////////////////// - -/proc/CreateBans() - - - UpdateTime() - - var/i - var/last - - for(i=0, i<1001, i++) - var/a = pick(1,0) - var/b = pick(1,0) - if(b) - Banlist.cd = "/base" - Banlist.dir.Add("trash[i]trashid[i]") - Banlist.cd = "/base/trash[i]trashid[i]" + return 1 + +/proc/RemoveBan(foldername) + var/key + var/id + + Banlist.cd = "/base/[foldername]" + Banlist["key"] >> key + Banlist["id"] >> id + Banlist.cd = "/base" + + if (!Banlist.dir.Remove(foldername)) return 0 + + if(!usr) + log_admin("Ban Expired: [key]") + message_admins("Ban Expired: [key]") + else + ban_unban_log_save("[key_name_admin(usr)] unbanned [key]") + log_admin("[key_name_admin(usr)] unbanned [key]") + message_admins("[key_name_admin(usr)] unbanned: [key]") + feedback_inc("ban_unban",1) + usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN) + for (var/A in Banlist.dir) + Banlist.cd = "/base/[A]" + if (key == Banlist["key"] /*|| id == Banlist["id"]*/) + Banlist.cd = "/base" + Banlist.dir.Remove(A) + continue + + return 1 + +/proc/GetExp(minutes as num) + UpdateTime() + var/exp = minutes - CMinutes + if (exp <= 0) + return 0 + else + var/timeleftstring + if (exp >= 1440) //1440 = 1 day in minutes + timeleftstring = "[round(exp / 1440, 0.1)] Days" + else if (exp >= 60) //60 = 1 hour in minutes + timeleftstring = "[round(exp / 60, 0.1)] Hours" + else + timeleftstring = "[exp] Minutes" + return timeleftstring + +/datum/admins/proc/unbanpanel() + var/count = 0 + var/dat + //var/dat = "
    Unban Player:(U) = Unban , (E) = Edit Ban(Total
    " + Banlist.cd = "/base" + for (var/A in Banlist.dir) + count++ + Banlist.cd = "/base/[A]" + var/ref = "\ref[src]" + var/key = Banlist["key"] + var/id = Banlist["id"] + var/ip = Banlist["ip"] + var/reason = Banlist["reason"] + var/by = Banlist["bannedby"] + var/expiry + if(Banlist["temp"]) + expiry = GetExp(Banlist["minutes"]) + if(!expiry) expiry = "Removal Pending" + else expiry = "Permaban" + + dat += text("") + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\NewBan.dm:187: dat += "
    (U)(E) Key: [key]ComputerID: [id]IP: [ip] [expiry](By: [by])(Reason: [reason])
    " + dat += {" +
    Bans: (U) = Unban , (E) = Edit Ban - ([count] Bans)
    [dat]"} + // END AUTOFIX + usr << browse(dat, "window=unbanp;size=875x400") + +//////////////////////////////////// DEBUG //////////////////////////////////// + +/proc/CreateBans() + + + UpdateTime() + + var/i + var/last + + for(i=0, i<1001, i++) + var/a = pick(1,0) + var/b = pick(1,0) + if(b) + Banlist.cd = "/base" + Banlist.dir.Add("trash[i]trashid[i]") + Banlist.cd = "/base/trash[i]trashid[i]" Banlist["key"] << "trash[i]" - else - Banlist.cd = "/base" - Banlist.dir.Add("[last]trashid[i]") - Banlist.cd = "/base/[last]trashid[i]" + else + Banlist.cd = "/base" + Banlist.dir.Add("[last]trashid[i]") + Banlist.cd = "/base/[last]trashid[i]" Banlist["key"] << last Banlist["id"] << "trashid[i]" Banlist["reason"] << "Trashban[i]." Banlist["temp"] << a Banlist["minutes"] << CMinutes + rand(1,2000) Banlist["bannedby"] << "trashmin" - last = "trash[i]" - - Banlist.cd = "/base" - -/proc/ClearAllBans() - Banlist.cd = "/base" - for (var/A in Banlist.dir) - RemoveBan(A) + last = "trash[i]" + + Banlist.cd = "/base" + +/proc/ClearAllBans() + Banlist.cd = "/base" + for (var/A in Banlist.dir) + RemoveBan(A) diff --git a/code/modules/admin/ToRban.dm b/code/modules/admin/ToRban.dm index 9c4fe3994a0..c5951638aa8 100644 --- a/code/modules/admin/ToRban.dm +++ b/code/modules/admin/ToRban.dm @@ -1,88 +1,88 @@ -//By Carnwennan -//fetches an external list and processes it into a list of ip addresses. -//It then stores the processed list into a savefile for later use -#define TORFILE "data/ToR_ban.bdb" -#define TOR_UPDATE_INTERVAL 216000 //~6 hours - -/proc/ToRban_isbanned(var/ip_address) - var/savefile/F = new(TORFILE) - if(F) - if( ip_address in F.dir ) - return 1 - return 0 - -/proc/ToRban_autoupdate() - var/savefile/F = new(TORFILE) - if(F) - var/last_update - F["last_update"] >> last_update - if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while - ToRban_update() - return - -/proc/ToRban_update() - spawn(0) - diary << "Downloading updated ToR data..." - var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses") - - var/list/rawlist = file2list(http["CONTENT"]) - if(rawlist.len) - fdel(TORFILE) - var/savefile/F = new(TORFILE) - for( var/line in rawlist ) - if(!line) continue - if( copytext(line,1,12) == "ExitAddress" ) - var/cleaned = copytext(line,13,length(line)-19) - if(!cleaned) continue - F[cleaned] << 1 +//By Carnwennan +//fetches an external list and processes it into a list of ip addresses. +//It then stores the processed list into a savefile for later use +#define TORFILE "data/ToR_ban.bdb" +#define TOR_UPDATE_INTERVAL 216000 //~6 hours + +/proc/ToRban_isbanned(var/ip_address) + var/savefile/F = new(TORFILE) + if(F) + if( ip_address in F.dir ) + return 1 + return 0 + +/proc/ToRban_autoupdate() + var/savefile/F = new(TORFILE) + if(F) + var/last_update + F["last_update"] >> last_update + if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while + ToRban_update() + return + +/proc/ToRban_update() + spawn(0) + diary << "Downloading updated ToR data..." + var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses") + + var/list/rawlist = file2list(http["CONTENT"]) + if(rawlist.len) + fdel(TORFILE) + var/savefile/F = new(TORFILE) + for( var/line in rawlist ) + if(!line) continue + if( copytext(line,1,12) == "ExitAddress" ) + var/cleaned = copytext(line,13,length(line)-19) + if(!cleaned) continue + F[cleaned] << 1 F["last_update"] << world.realtime - diary << "ToR data updated!" + diary << "ToR data updated!" if(usr) to_chat(usr, "ToRban updated.") - return 1 - diary << "ToR data update aborted: no data." - return 0 - -/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find")) - set name = "ToRban" - set category = "Server" - if(!holder) return - switch(task) - if("update") - ToRban_update() - if("toggle") - if(config) - if(config.ToRban) - config.ToRban = 0 - message_admins("ToR banning disabled.") - else - config.ToRban = 1 - message_admins("ToR banning enabled.") - if("show") - var/savefile/F = new(TORFILE) - var/dat - if( length(F.dir) ) - for( var/i=1, i<=length(F.dir), i++ ) - dat += "" - dat = "
    #[i] [F.dir[i]]
    [dat]
    " - else - dat = "No addresses in list." - src << browse(dat,"window=ToRban_show") - if("remove") - var/savefile/F = new(TORFILE) - var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir - if(choice) - F.dir.Remove(choice) + return 1 + diary << "ToR data update aborted: no data." + return 0 + +/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find")) + set name = "ToRban" + set category = "Server" + if(!holder) return + switch(task) + if("update") + ToRban_update() + if("toggle") + if(config) + if(config.ToRban) + config.ToRban = 0 + message_admins("ToR banning disabled.") + else + config.ToRban = 1 + message_admins("ToR banning enabled.") + if("show") + var/savefile/F = new(TORFILE) + var/dat + if( length(F.dir) ) + for( var/i=1, i<=length(F.dir), i++ ) + dat += "#[i] [F.dir[i]]" + dat = "[dat]
    " + else + dat = "No addresses in list." + src << browse(dat,"window=ToRban_show") + if("remove") + var/savefile/F = new(TORFILE) + var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir + if(choice) + F.dir.Remove(choice) to_chat(src, "Address removed") - if("remove all") + if("remove all") to_chat(src, "[TORFILE] was [fdel(TORFILE)?"":"not "]removed.") - if("find") - var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text - if(input) - if(ToRban_isbanned(input)) + if("find") + var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text + if(input) + if(ToRban_isbanned(input)) to_chat(src, "Address is a known ToR address") - else + else to_chat(src, "Address is not a known ToR address") - return - -#undef TORFILE -#undef TOR_UPDATE_INTERVAL + return + +#undef TORFILE +#undef TOR_UPDATE_INTERVAL diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 1c19c09345c..a9edbca5137 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1,1421 +1,1421 @@ - -var/global/BSACooldown = 0 -var/global/floorIsLava = 0 - - -//////////////////////////////// -/proc/message_admins(var/msg) - msg = "ADMIN LOG: [msg]" - log_adminwarn(msg) - for(var/client/C in admins) - if(R_ADMIN & C.holder.rights) - to_chat(C, msg) - -/proc/msg_admin_attack(var/text) //Toggleable Attack Messages - var/rendered = "ADMIN LOG: [text]" - log_adminwarn(rendered) - for(var/client/C in admins) - if(R_ADMIN & C.holder.rights) - if(C.prefs.toggles & CHAT_ATTACKLOGS) - var/msg = rendered - to_chat(C, msg) - -// Not happening. -// Yes I could do a +PERMISSIONS check but I'm both too lazy and worried admins might do it on accident. -/datum/admins/SDQL_update(var/const/var_name, var/new_value) - return 0 - -///////////////////////////////////////////////////////////////////////////////////////////////Panels - -/datum/admins/proc/show_player_panel(var/mob/M in mob_list) - set category = "Admin" - set name = "Show Player Panel" - set desc="Edit player (respawn, ban, heal, etc)" - - if(!M) - to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.") - return - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - - checkSessionKey() - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\admin.dm:40: var/body = "Options for [M.key]" - var/body = {"Options for [M.key] -Options panel for [M]"} - // END AUTOFIX - var/species_description - if(M.client) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\admin.dm:43: body += " played by [M.client] " - body += {"played by [M.client] - \[[M.client.holder ? M.client.holder.rank : "Player"]\]"} - // END AUTOFIX - if(istype(M, /mob/new_player)) - body += " Hasn't Entered Game " - else - body += " \[Heal\] " - if(ishuman(M)) - var/mob/living/carbon/human/H = M - species_description = "[H.species ? H.species.name : "No Species"]" - body += {" -

    \[ - VV - - TP - - Bans - - PM - - SM - - JMP\]

    - Mob type = [M.type][species_description ? " - Species = [species_description]" : ""]

    - Kick | - Warn | - UNWarn | - Ban | - Jobban | - OOC Ban | - Identity Ban | - Notes - "} - - if(M.client) - body += "| Prison | " - var/muted = M.client.prefs.muted - body += {"
    Mute: - \[IC | - OOC | - PRAY | - ADMINHELP | - DEADCHAT\] - (toggle all) - "} - - body += {"

    - Jump to | - Get | - Send To -

    - Traitor panel | - Narrate to | - Subtle message - "} - - // Mob-specific controls. - body += M.player_panel_controls(usr) - - if (M.client) - if(!istype(M, /mob/new_player)) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\admin.dm:90: body += "

    " - body += {"

    - Transformation: -
    "} - // END AUTOFIX - //Monkey - if(ismonkey(M)) - body += "Monkeyized | " - else - body += "Monkeyize | " - - //Corgi - if(iscorgi(M)) - body += "Corgized | " - else - body += "Corgize | " - - //AI / Cyborg - if(isAI(M)) - body += "Is an AI " - else if(ishuman(M)) - body += {"Make AI | - Make Robot | - Make MoMMI | - Make Alien | - Make slime | - Make Cluwne | - "} - - //Simple Animals - if(isanimal(M)) - body += "Re-Animalize | " - else - body += "Animalize | " - - // DNA2 - Admin Hax - if(iscarbon(M) && !isbrain(M) && !isalien(M)) - body += "

    " - body += "DNA Blocks:
    " - var/bname - for(var/block=1;block<=DNA_SE_LENGTH;block++) - if(((block-1)%5)==0) - body += "" - bname = assigned_blocks[block] - body += "" - body += "
     12345
    [block-1]" - if(bname) - var/bstate=M.dna.GetSEState(block) - var/bcolor="[(bstate)?"#006600":"#ff0000"]" - body += "[bname][block]" - else - body += "[block]" - body+="
    " - - // Law Admin Hax - if(issilicon(M) && M:laws) - body += "

    " - body += "Laws:
    " - var/datum/ai_laws/L = M:laws - body += L.display_admin_tools(M) - body += "
    Add Law" - body += " | Clear Laws" - body += " | Reset Lawset" - body += "
    Send Laws - User is not notified of changes until this button pushed!
    " - - body += {"

    - Rudimentary transformation:
    These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

    - Observer | - \[ Alien: Drone, - Hunter, - Queen, - Sentinel, - Larva \] - Human - \[ slime: Baby, - Adult \] - Monkey | - Cyborg | - Cat | - Runtime | - Corgi | - Ian | - Crab | - Coffee | - \[ Construct: Armoured , - Builder , - Wraith \] - Shade -
    - "} - - if (M.client) - body += {"

    - Other actions: -
    - Forcesay | - Thunderdome Green | - Thunderdome Red | - Thunderdome Admin | - Thunderdome Observer | - "} - - // language toggles - body += "

    Languages:
    " - var/f = 1 - for(var/k in all_languages) - var/datum/language/L = all_languages[k] - if(!f) body += " | " - else f = 0 - if(L in M.languages) - body += "[k]" - else - body += "[k]" - - body += {"
    - - "} - - usr << browse(body, "window=adminplayeropts-\ref[M];size=550x515") - feedback_add_details("admin_verb","SPP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/player_info/var/author // admin who authored the information -/datum/player_info/var/rank //rank of admin who made the notes -/datum/player_info/var/content // text content of the information -/datum/player_info/var/timestamp // Because this is bloody annoying - -#define PLAYER_NOTES_ENTRIES_PER_PAGE 50 -/datum/admins/proc/PlayerNotes() - set category = "Admin" - set name = "Player Notes" - - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - PlayerNotesPage(1) - -/datum/admins/proc/checkCID() - set category = "Admin" - set name = "Lookup bans on Computer ID" - - if(!usr) - return - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - checkSessionKey() - var/cid = input("Type computer ID", "CID", 0) as num | null - if(cid) - usr << link(getVGPanel("rapsheet", admin = 1, query = list("cid" = cid))) -// to_chat(usr, link("[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]&cid=[cid]")) - return - -/datum/admins/proc/checkCKEY() - set category = "Admin" - set name = "Lookup bans on CKEY" - - if(!usr) - return - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - checkSessionKey() - var/ckey = lowertext(input("Type player ckey", "ckey", null) as text | null) - usr << link(getVGPanel("rapsheet", admin = 1, query = list("ckey" = ckey))) -// usr << link("[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]&ckey=[ckey]") - return - -/datum/admins/proc/PlayerNotesPage(page) - var/dat = "Player notes
    " - var/savefile/S=new("data/player_notes.sav") - var/list/note_keys - S >> note_keys - if(!note_keys) - dat += "No notes found." - else - dat += "" - note_keys = sortList(note_keys) - - // Display the notes on the current page - var/number_pages = note_keys.len / PLAYER_NOTES_ENTRIES_PER_PAGE - // Emulate ceil(why does BYOND not have ceil) - if(number_pages != round(number_pages)) - number_pages = round(number_pages) + 1 - var/page_index = page - 1 - if(page_index < 0 || page_index >= number_pages) - return - - var/lower_bound = page_index * PLAYER_NOTES_ENTRIES_PER_PAGE + 1 - var/upper_bound = (page_index + 1) * PLAYER_NOTES_ENTRIES_PER_PAGE - upper_bound = min(upper_bound, note_keys.len) - for(var/index = lower_bound, index <= upper_bound, index++) - var/t = note_keys[index] - dat += "" - - dat += "
    [t]

    " - - // Display a footer to select different pages - for(var/index = 1, index <= number_pages, index++) - if(index == page) - dat += "" - dat += "[index] " - if(index == page) - dat += "" - - usr << browse(dat, "window=player_notes;size=400x400") - - -/datum/admins/proc/player_has_info(var/key as text) - var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") - var/list/infos - info >> infos - if(!infos || !infos.len) return 0 - else return 1 - -/proc/exportnotes(var/key as text) - var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") - var/list/infos - info >> infos - var/list/noteslist = list() - if(!infos) - return list("1" = "No notes found for [key]") - else - var/i = 0 - - for(var/datum/player_info/I in infos) - i += 1 - if(!I.timestamp) - I.timestamp = "Pre-4/3/2012" - if(!I.rank) - I.rank = "N/A" - /*noteslist["note:[i]"] = "[I.content]" - noteslist["author:[i]"] = "[I.author]" - noteslist["rank:[i]"] = "[I.rank]" - noteslist["timestamp:[i]"] = "[I.timestamp]"*/ - noteslist["[i]"] = "[I.content] by [I.author] ([I.rank]) on [I.timestamp]" - if(!noteslist.len) - noteslist["1"] = "No notes found for [key]" - return noteslist -/datum/admins/proc/show_player_info(var/key as text) - set category = "Admin" - set name = "Show Player Info" - - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - - var/dat = {"Info on [key] -"} - - 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 - var/update_file = 0 - var/i = 0 - for(var/datum/player_info/I in infos) - i += 1 - if(!I.timestamp) - I.timestamp = "Pre-4/3/2012" - update_file = 1 - if(!I.rank) - I.rank = "N/A" - update_file = 1 - dat += "[I.content] by [I.author] ([I.rank]) on [I.timestamp] " - if(I.author == usr.key || check_rights(R_PERMISSIONS, show_msg = 0)) - dat += "Remove" - dat += "

    " - if(update_file) - info << infos - - dat += {"
    - Add Comment
    - "} - - usr << browse(dat, "window=adminplayerinfo;size=480x480") - -/datum/admins/proc/access_news_network() //MARKER - set category = "Fun" - set name = "Access Newscaster Network" - set desc = "Allows you to view, add and edit news feeds." - - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - var/dat - dat = text("Admin Newscaster

    Admin Newscaster Unit

    ") - - switch(admincaster_screen) - if(0) - dat += {"Welcome to the admin newscaster.
    Here you can add, edit and censor every newspiece on the network. -
    Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units. -
    Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!
    - "} - if(news_network.wanted_issue) - dat+= "
    Read Wanted Issue" - - dat+= {"

    Create Feed Channel -
    View Feed Channels -
    Submit new Feed story -

    Exit - "} - - var/wanted_already = 0 - if(news_network.wanted_issue) - wanted_already = 1 - - dat+={"
    Feed Security functions:
    -
    [(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue -
    Censor Feed Stories -
    Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel. -

    The newscaster recognises you as:
    [src.admincaster_signature]
    - "} - if(1) - dat+= "Station Feed Channels
    " - if( isemptylist(news_network.network_channels) ) - dat+="No active channels found..." - else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) - if(CHANNEL.is_admin_channel) - dat+="[CHANNEL.channel_name]
    " - else - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
    " - dat+={"

    Refresh -
    Back - "} - - if(2) - dat+={" - Creating new Feed Channel... -
    Channel Name: [src.admincaster_feed_channel.channel_name]
    - Channel Author: [src.admincaster_signature]
    - Will Accept Public Feeds: [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]

    -
    Submit

    Cancel
    - "} - if(3) - dat+={" - Creating new Feed Message... -
    Receiving Channel: [src.admincaster_feed_channel.channel_name]
    " //MARK - Message Author: [src.admincaster_signature]
    - Message Body: [src.admincaster_feed_message.body]
    -
    Submit

    Cancel
    - "} - if(4) - dat+={" - Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].

    -
    Return
    - "} - if(5) - dat+={" - Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.

    -
    Return
    - "} - if(6) - dat+="ERROR: Could not submit Feed story to Network.

    " - if(src.admincaster_feed_channel.channel_name=="") - dat+="�Invalid receiving channel name.
    " - if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]") - dat+="�Invalid message body.
    " - dat+="
    Return
    " - if(7) - dat+="ERROR: Could not submit Feed Channel to Network.

    " - if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") - dat+="�Invalid channel name.
    " - var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.admincaster_feed_channel.channel_name) - check = 1 - break - if(check) - dat+="�Channel name already in use.
    " - dat+="
    Return
    " - if(9) - dat+="[src.admincaster_feed_channel.channel_name]: \[created by: [src.admincaster_feed_channel.author]\]
    " - if(src.admincaster_feed_channel.censored) - dat+={" - ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
    - No further feed story additions are allowed while the D-Notice is in effect.


    - "} - else - if( isemptylist(src.admincaster_feed_channel.messages) ) - dat+="No feed messages found in channel...
    " - else - var/i = 0 - for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages) - i++ - dat+="-[MESSAGE.body]
    " - if(MESSAGE.img) - usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") - dat+="

    " - dat+="\[Story by [MESSAGE.author]\]
    " - dat+={" -

    Refresh -
    Back - "} - if(10) - dat+={" - Nanotrasen Feed Censorship Tool
    - NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
    - Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
    -
    Select Feed channel to get Stories from:
    - "} - if(isemptylist(news_network.network_channels)) - dat+="No feed channels found active...
    " - else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
    " - dat+="
    Cancel" - if(11) - dat+={" - Nanotrasen D-Notice Handler
    - A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's - morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed - stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
    - "} - if(isemptylist(news_network.network_channels)) - dat+="No feed channels found active...
    " - else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
    " - - dat+="
    Back" - if(12) - dat+={" - [src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.author] \]
    - [(src.admincaster_feed_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
    - "} - if( isemptylist(src.admincaster_feed_channel.messages) ) - dat+="No feed messages found in channel...
    " - else - for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages) - dat+={" - -[MESSAGE.body]
    \[Story by [MESSAGE.author]\]
    - [(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
    - "} - dat+="
    Back" - if(13) - dat+={" - [src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.author] \]
    - Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
    - "} - if(src.admincaster_feed_channel.censored) - dat+={" - ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
    - No further feed story additions are allowed while the D-Notice is in effect.


    - "} - else - if( isemptylist(src.admincaster_feed_channel.messages) ) - dat+="No feed messages found in channel...
    " - else - for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages) - dat+="-[MESSAGE.body]
    \[Story by [MESSAGE.author]\]
    " - - dat+="
    Back" - if(14) - dat+="Wanted Issue Handler:" - var/wanted_already = 0 - var/end_param = 1 - if(news_network.wanted_issue) - wanted_already = 1 - end_param = 2 - if(wanted_already) - dat+="
    A wanted issue is already in Feed Circulation. You can edit or cancel it below.
    " - dat+={" -
    - Criminal Name: [src.admincaster_feed_message.author]
    - Description: [src.admincaster_feed_message.body]
    - "} - if(wanted_already) - dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
    " - else - dat+="Wanted Issue will be created under prosecutor: [src.admincaster_signature]
    " - dat+="
    [(wanted_already) ? ("Edit Issue") : ("Submit")]" - if(wanted_already) - dat+="
    Take down Issue" - dat+="
    Cancel" - if(15) - dat+={" - Wanted issue for [src.admincaster_feed_message.author] is now in Network Circulation.

    -
    Return
    - "} - if(16) - dat+="ERROR: Wanted Issue rejected by Network.

    " - if(src.admincaster_feed_message.author =="" || src.admincaster_feed_message.author == "\[REDACTED\]") - dat+="�Invalid name for person wanted.
    " - if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]") - dat+="�Invalid description.
    " - dat+="
    Return
    " - if(17) - dat+={" - Wanted Issue successfully deleted from Circulation
    -
    Return
    - "} - if(18) - dat+={" - -- STATIONWIDE WANTED ISSUE --
    \[Submitted by: [news_network.wanted_issue.backup_author]\]
    - Criminal: [news_network.wanted_issue.author]
    - Description: [news_network.wanted_issue.body]
    - Photo:: - "} - if(news_network.wanted_issue.img) - usr << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png") - dat+="
    " - else - dat+="None" - dat+="
    Back
    " - if(19) - dat+={" - Wanted issue for [src.admincaster_feed_message.author] successfully edited.

    -
    Return
    - "} - else - dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" - -// to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]") -// to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]") - usr << browse(dat, "window=admincaster_main;size=400x600") - onclose(usr, "admincaster_main") - - - -/datum/admins/proc/Jobbans() - if(!check_rights(R_BAN)) return - - var/dat = "Job Bans!
    " - for(var/t in jobban_keylist) - var/r = t - if( findtext(r,"##") ) - r = copytext( r, 1, findtext(r,"##") )//removes the description - dat += text("") - dat += "
    [t] (unban)
    " - usr << browse(dat, "window=ban;size=400x400") - -/datum/admins/proc/Game() - if(!check_rights(0)) return - - var/dat = {" -
    Game Panel

    \n - Change Game Mode
    - "} - if(master_mode == "secret") - dat += "(Force Secret Mode)
    " - - dat += {" -
    - -
    - Create Object
    - Quick Create Object
    - Create Turf
    - Create Mob
    -
    - Edit ZAS Settings
    - Choose a default ZAS setting
    - "} - - usr << browse(dat, "window=admin2;size=280x370") - return - -/datum/admins/proc/Secrets() - if(!check_rights(0)) return - - var/dat = "The first rule of adminbuse is: you don't talk about the adminbuse.
    " - - if(check_rights(R_FUN,0) || check_rights(R_ADMINBUS,0)) - dat += {" - Fourth-Wall Demolition
    -
    - "} - if(check_rights(R_ADMINBUS,0)) - dat += {" - Spawn an Adminbus
    - "} - if(check_rights(R_FUN,0)) - dat += {" - Spawn yourself as a Test Dummy
    -
    - "} - - if(check_rights(R_ADMIN,0)) - dat += {" - Admin Secrets
    -
    - Remove all bombs currently in existence
    - Bombing List
    - Show current traitors and objectives
    - Show last [length(lastsignalers)] signalers
    - Show last [length(lawchanges)] law changes
    - Show AI Laws
    - Show Game Mode
    - Show Crew Manifest
    - List DNA (Blood)
    - List Fingerprints

    -
    - "} - - if(check_rights(R_FUN,0)) - dat += {" - 'Random' Events
    -
    - Toggle station artificial gravity
    - Spawn a wave of meteors (aka lagocolyptic shower)
    - Spawn a gravitational anomaly (aka lagitational anomolag)
    - Spawn wormholes
    - Spawn blob
    - Trigger an Alien infestation
    - Spawn an Alien silently
    - Trigger a Spider infestation
    - Send in a strike team
    - Trigger a Carp migration
    - Irradiate the station
    - Trigger a Prison Break
    - Trigger a Virus Outbreak
    - Spawn an Immovable Rod
    - Toggle a "lights out" event
    - Spawn an Ion Storm
    - Spawn Space-Vines
    - Trigger a communication blackout
    - Trigger a wave of PDA spams
    -
    - Fun Secrets
    -
    - [ticker&&ticker.hardcore_mode ? "Disable" : "Enable"] hardcore mode (makes starvation kill!)
    - Remove 'internal' clothing
    - Remove ALL clothing
    - Turn all humans into monkeys
    - Remove firesuits, grilles, and pods
    - Make all areas powered
    - Make all areas unpowered
    - Power all SMES
    - Toggle Prison Shuttle Status(Use with S/R)
    - Send Prison Shuttle
    - Return Prison Shuttle
    - Warp all Players to Prison
    - Triple AI mode (needs to be used in the lobby)
    - Everyone is the traitor
    - There can only be one!
    - Ghost Mode
    - Make all players retarded
    - Make all items look like guns
    - Distribute experimental guns to the crew
    - Japanese Animes Mode
    - Egalitarian Station Mode
    - Move Alien Dinghy
    - Break all lights
    - Fix all lights
    - Unleash THE BEES onto the crew
    - The floor is lava! (DANGEROUS: extremely lame)
    - Toggle Nar-Sie's behaviour
    - Trigger a fake alert
    - Adds in some Micheal Bay to the shift without major destruction
    - Turn every players into Bomberman
    - Make Bomberman Bombs actually hurt players
    - Make Bomberman Bombs actually destroy stuff
    - Make Bomberman Bombs harmless to players(default)
    - Make Bomberman Bombs harmless to the environnement(default)
    - Create a turret
    -
    - Final Solutions
    - (Warning, these will end the round!)
    -
    - Summon Nar-Sie
    - Start a Supermatter Cascade
    - "} - - if(check_rights(R_SERVER,0)) - - dat += {" -
    - Server
    -
    - Toggle bomb cap
    - Toggle explosion method
    - "} - - dat += "
    " - - if(check_rights(R_DEBUG,0)) - dat += {" - Security Level Elevated
    -
    - Change all maintenance doors to engie/brig access only
    - Change all maintenance doors to brig access only
    - Remove cap on security officers
    - Custom Virus Outbreak
    -
    - Coder Secrets
    -
    - Show Job Debug
    - Admin Log
    -
    - "} - - usr << browse(dat, "window=secrets") - return - -/datum/admins/var/datum/shuttle/selected_shuttle -/datum/admins/proc/shuttle_magic() - var/dat = "WARNING: server may explode!

    " - - if(!istype(selected_shuttle)) - dat += "Select a shuttle
    " - else - dat += {"Selected shuttle: [selected_shuttle.name] ([selected_shuttle.type])
    - view variables | teleport to | select another shuttle
    - cooldown: [selected_shuttle.cooldown] | pre-flight delay: [selected_shuttle.pre_flight_delay] | transit delay: [selected_shuttle.transit_delay]
    - rotation [selected_shuttle.can_rotate ? "ENABLED" : "DISABLED"] | transit [selected_shuttle.use_transit ? "ENABLED" : "DISABLED"]
    - - Create a destination docking port
    - Add a destination docking port
    - Modify transit area
    - Get control console
    - Modify parameters[selected_shuttle.is_special() ? " and pre-defined areas" : ""] -
    - Send
    - Teleport
    - Make movement instant
    - Draw outline -
    - [selected_shuttle.lockdown ? "Lift lockdown" : "Lock down"]
    - Reset
    - Delete -
    - "} - - //The following commands don't need a selected shuttle - dat += {" - Turn current area into a shuttle
    - Create a shuttle docking port
    - Lock down all shuttles
    - "} - usr << browse(dat, "window=shuttlemagic") - - -/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge -//i.e. buttons/verbs - - -/datum/admins/proc/restart() - set category = "Server" - set name = "Restart" - set desc="Restarts the world" - - if (!usr.client.holder) - return - var/confirm = alert("Restart the game world?", "Restart", "Yes", "Cancel") - if(confirm == "Cancel") - return - if(confirm == "Yes") - to_chat(world, "Restarting world! Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!") - log_admin("[key_name(usr)] initiated a reboot.") - - feedback_set_details("end_error","admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]") - feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - if(blackbox) - blackbox.save_all_data_to_sql() - - CallHook("Reboot",list()) - - if (watchdog.waiting) - to_chat(world, "Server will shut down for an automatic update in a few seconds.") - watchdog.signal_ready() - return - - sleep(50) - world.Reboot() - - -/datum/admins/proc/announce() - set category = "Special Verbs" - set name = "Announce" - set desc="Announce your desires to the world" - - if(!check_rights(0)) return - - var/message = input("Global message to send:", "Admin Announce", null, null) as message - if(message) - if(!check_rights(R_SERVER,0)) - message = adminscrub(message,500) - to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]") - log_admin("Announce: [key_name(usr)] : [message]") - feedback_add_details("admin_verb","A") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleooc() - set category = "Server" - set desc="Globally Toggles OOC" - set name="Toggle OOC" - - ooc_allowed = !( ooc_allowed ) - if (ooc_allowed) - to_chat(world, "The OOC channel has been globally enabled!") - else - to_chat(world, "The OOC channel has been globally disabled!") - log_admin("[key_name(usr)] toggled OOC.") - message_admins("[key_name_admin(usr)] toggled OOC.", 1) - feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/admins/proc/toggleoocdead() - set category = "Server" - set desc="Toggle dis bitch" - set name="Toggle Dead OOC" - dooc_allowed = !( dooc_allowed ) - - log_admin("[key_name(usr)] toggled OOC.") - message_admins("[key_name_admin(usr)] toggled Dead OOC.", 1) - feedback_add_details("admin_verb","TDOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggletraitorscaling() - set category = "Server" - set desc="Toggle traitor scaling" - set name="Toggle Traitor Scaling" - - traitor_scaling = !traitor_scaling - log_admin("[key_name(usr)] toggled Traitor Scaling to [traitor_scaling].") - message_admins("[key_name_admin(usr)] toggled Traitor Scaling [traitor_scaling ? "on" : "off"].", 1) - feedback_add_details("admin_verb","TTS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/startnow() - set category = "Server" - set desc="Start the round RIGHT NOW" - set name="Start Now" - - if(!ticker) - alert("Unable to start the game as it is not set up.") - return - if(ticker.current_state == GAME_STATE_PREGAME) - ticker.current_state = GAME_STATE_SETTING_UP - log_admin("[usr.key] has started the game.") - message_admins("[usr.key] has started the game.") - feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return 1 - else - to_chat(usr, "Error: Start Now: Game has already started.") - return 0 - -/datum/admins/proc/toggleenter() - set category = "Server" - set desc="People can't enter" - set name="Toggle Entering" - - enter_allowed = !( enter_allowed ) - if (!( enter_allowed )) - to_chat(world, "New players may no longer enter the game.") - else - to_chat(world, "New players may now enter the game.") - log_admin("[key_name(usr)] toggled new player game entering.") - message_admins("[key_name_admin(usr)] toggled new player game entering.", 1) - world.update_status() - feedback_add_details("admin_verb","TE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleAI() - set category = "Server" - set desc="People can't be AI" - set name="Toggle AI" - - config.allow_ai = !( config.allow_ai ) - if (!( config.allow_ai )) - to_chat(world, "The AI job is no longer chooseable.") - else - to_chat(world, "The AI job is chooseable now.") - log_admin("[key_name(usr)] toggled AI allowed.") - world.update_status() - feedback_add_details("admin_verb","TAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleaban() - set category = "Server" - set desc="Respawn basically" - set name="Toggle Respawn" - - abandon_allowed = !( abandon_allowed ) - if (abandon_allowed) - to_chat(world, "You may now respawn.") - else - to_chat(world, "You may no longer respawn :(") - message_admins("[key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].", 1) - log_admin("[key_name(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].") - world.update_status() - feedback_add_details("admin_verb","TR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggle_aliens() - set category = "Server" - set desc="Toggle alien mobs" - set name="Toggle Aliens" - - aliens_allowed = !aliens_allowed - log_admin("[key_name(usr)] toggled Aliens to [aliens_allowed].") - message_admins("[key_name_admin(usr)] toggled Aliens [aliens_allowed ? "on" : "off"].", 1) - feedback_add_details("admin_verb","TA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -#define LOBBY_TICKING_STOPPED 0 -#define LOBBY_TICKING_RESTARTED 2 -/datum/admins/proc/delay() - set category = "Server" - set desc="Delay the game start/end" - set name="Delay" - - if(!check_rights(R_ADMIN)) return - if (!ticker || ticker.current_state != GAME_STATE_PREGAME) - if(ticker.delay_end == 2) - to_chat(world, "World Reboot triggered by [key_name(usr)]!") - log_admin("World Reboot triggered by [key_name(usr)]!") - if(watchdog.waiting) - watchdog.signal_ready() - else - world.Reboot() - ticker.delay_end = !ticker.delay_end - log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") - message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) - - return //alert("Round end delayed", null, null, null, null, null) - if (!( going )) - going = LOBBY_TICKING_RESTARTED - ticker.pregame_timeleft = world.timeofday + ticker.remaining_time - to_chat(world, "The game will start soon.") - log_admin("[key_name(usr)] removed the delay.") - else - going = LOBBY_TICKING_STOPPED - to_chat(world, "The game start has been delayed.") - log_admin("[key_name(usr)] delayed the game.") - feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -#undef LOBBY_TICKING_STOPPED -#undef LOBBY_TICKING_RESTARTED -/datum/admins/proc/adjump() - set category = "Server" - set desc="Toggle admin jumping" - set name="Toggle Jump" - - config.allow_admin_jump = !(config.allow_admin_jump) - message_admins("Toggled admin jumping to [config.allow_admin_jump].") - feedback_add_details("admin_verb","TJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/adspawn() - set category = "Server" - set desc="Toggle admin spawning" - set name="Toggle Spawn" - - config.allow_admin_spawning = !(config.allow_admin_spawning) - message_admins("Toggled admin item spawning to [config.allow_admin_spawning].") - feedback_add_details("admin_verb","TAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/adrev() - set category = "Server" - set desc="Toggle admin revives" - set name="Toggle Revive" - - config.allow_admin_rev = !(config.allow_admin_rev) - message_admins("Toggled reviving to [config.allow_admin_rev].") - feedback_add_details("admin_verb","TAR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/immreboot() - set category = "Server" - set desc="Reboots the server post haste" - set name="Immediate Reboot" - - if(!usr.client.holder) return - if( alert("Reboot server?",,"Yes","No") == "No") - return - to_chat(world, "Rebooting world! Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!") - log_admin("[key_name(usr)] initiated an immediate reboot.") - - feedback_set_details("end_error","immediate admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]") - feedback_add_details("admin_verb","IR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - if(blackbox) - blackbox.save_all_data_to_sql() - - CallHook("Reboot",list()) - - if (watchdog.waiting) - to_chat(world, "Server will shut down for an automatic update in a few seconds.") - watchdog.signal_ready() - return - - world.Reboot() - -/datum/admins/proc/unprison(var/mob/M in mob_list) - set category = "Admin" - set name = "Unprison" - - if (M.z == 2) - if (config.allow_admin_jump) - M.loc = pick(latejoin) - message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]", 1) - log_admin("[key_name(usr)] has unprisoned [key_name(M)]") - else - alert("Admin jumping disabled") - else - alert("[M.name] is not prisoned.") - feedback_add_details("admin_verb","UP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS - -/proc/is_special_character(mob/M as mob) // returns 1 for specail characters and 2 for heroes of gamemode - if(!ticker || !ticker.mode) - return 0 - if (!istype(M)) - return 0 - if(isrev(M) || isrevhead(M)) - if (ticker.mode.config_tag == "revolution") - return 2 - return 1 - if(iscult(M)) - if (ticker.mode.config_tag == "cult") - return 2 - return 1 - if(ismalf(M)) - if (ticker.mode.config_tag == "malfunction") - return 2 - return 1 - if(isnukeop(M)) - if (ticker.mode.config_tag == "nuclear") - return 2 - return 1 - if(iswizard(M)) - if (ticker.mode.config_tag == "wizard") - return 2 - return 1 - if(ischangeling(M)) - if (ticker.mode.config_tag == "changeling") - return 2 - return 1 - if(isborer(M)) - if (ticker.mode.config_tag == "borer") - return 2 - return 1 - if(isbadmonkey(M)) - if (ticker.mode.config_tag == "monkey") - return 2 - return 1 - if(isrobot(M)) - var/mob/living/silicon/robot/R = M - if(R.emagged) - return 1 - if(M.mind&&M.mind.special_role)//If they have a mind and special role, they are some type of traitor or antagonist. - return 1 - - return 0 - -/* -/datum/admins/proc/get_sab_desc(var/target) - switch(target) - if(1) - return "Destroy at least 70% of the plasma canisters on the station" - if(2) - return "Destroy the AI" - if(3) - var/count = 0 - for(var/mob/living/carbon/monkey/Monkey in world) - if(Monkey.z == 1) - count++ - return "Kill all [count] of the monkeys on the station" - if(4) - return "Cut power to at least 80% of the station" - else - return "Error: Invalid sabotage target: [target]" -*/ -/datum/admins/proc/spawn_atom(var/object as text) - set category = "Debug" - set desc = "(atom path) Spawn an atom" - set name = "Spawn" - - if(!check_rights(R_SPAWN)) return - - var/list/matches = new() - - for(var/path in typesof(/atom)) - if(findtext("[path]", object)) - matches += path - - if(matches.len==0) - return - - var/chosen - if(matches.len==1) - chosen = matches[1] - else - chosen = input("Select an atom type", "Spawn Atom", matches[1]) as null|anything in matches - if(!chosen) - return - - if(ispath(chosen,/turf)) - var/turf/T = get_turf(usr.loc) - T.ChangeTurf(chosen) - else - new chosen(usr.loc) - - log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") - feedback_add_details("admin_verb","SA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/show_traitor_panel(var/mob/M in mob_list) - set category = "Admin" - set desc = "Edit mobs's memory and role" - set name = "Show Traitor Panel" - - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(!M.mind) - to_chat(usr, "This mob has no mind!") - return - - M.mind.edit_memory() - feedback_add_details("admin_verb","STP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/datum/admins/proc/toggletintedweldhelmets() - set category = "Debug" - set desc="Reduces view range when wearing welding helmets" - set name="Toggle tinted welding helmes" - - tinted_weldhelh = !( tinted_weldhelh ) - if (tinted_weldhelh) - to_chat(world, "The tinted_weldhelh has been enabled!") - else - to_chat(world, "The tinted_weldhelh has been disabled!") - log_admin("[key_name(usr)] toggled tinted_weldhelh.") - message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.", 1) - feedback_add_details("admin_verb","TTWH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggleguests() - set category = "Server" - set desc="Guests can't enter" - set name="Toggle guests" - - guests_allowed = !( guests_allowed ) - if (!( guests_allowed )) - to_chat(world, "Guests may no longer enter the game.") - else - to_chat(world, "Guests may now enter the game.") - log_admin("[key_name(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.") - message_admins("[key_name_admin(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.", 1) - feedback_add_details("admin_verb","TGU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/unjobban_panel() - set name = "Unjobban Panel" - set category = "Admin" - if (src.holder) - src.holder.unjobbanpanel() - feedback_add_details("admin_verb","UJBP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/datum/admins/proc/output_ai_laws() - var/ai_number = 0 - for(var/mob/living/silicon/S in mob_list) - ai_number++ - if(isAI(S)) - to_chat(usr, "AI [key_name(S, usr)]'s laws:") - else if(isrobot(S)) - var/mob/living/silicon/robot/R = S - to_chat(usr, "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independant)"]: laws:") - else if (ispAI(S)) - var/mob/living/silicon/pai/pAI = S - to_chat(usr, "pAI [key_name(S, usr)]'s laws (master: [pAI.master] ):") - else - to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") - - if(ispAI(S)) - var/mob/living/silicon/pai/pAI = S - pAI.show_directives(usr) - else if (S.laws == null) - to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.") - else - S.laws.show_laws(usr) - - if(!ai_number) - to_chat(usr, "No AIs located")//Just so you know the thing is actually working and not just ignoring you. - - -/client/proc/update_mob_sprite(mob/living/carbon/human/H as mob in mob_list) - set category = "Admin" - set name = "Update Mob Sprite" - set desc = "Should fix any mob sprite update errors." - - if (!holder) - to_chat(src, "Only administrators may use this command.") - return - - if(istype(H)) - H.regenerate_icons() - -// -// -//ALL DONE -//********************************************************************************************************* -//TO-DO: -// -// - - -/**********************Administration Shuttle**************************/ - -var/admin_shuttle_location = 0 // 0 = centcom 13, 1 = station - -proc/move_admin_shuttle() - var/area/fromArea - var/area/toArea - if (admin_shuttle_location == 1) - fromArea = locate(/area/shuttle/administration/station) - toArea = locate(/area/shuttle/administration/centcom) - else - fromArea = locate(/area/shuttle/administration/centcom) - toArea = locate(/area/shuttle/administration/station) - fromArea.move_contents_to(toArea) - if (admin_shuttle_location) - admin_shuttle_location = 0 - else - admin_shuttle_location = 1 - return - -/**********************Alien ship**************************/ - -var/alien_ship_location = 1 // 0 = base , 1 = mine - -proc/move_alien_ship() - var/area/fromArea - var/area/toArea - if (alien_ship_location == 1) - fromArea = locate(/area/shuttle/alien/mine) - toArea = locate(/area/shuttle/alien/base) - else - fromArea = locate(/area/shuttle/alien/base) - toArea = locate(/area/shuttle/alien/mine) - fromArea.move_contents_to(toArea) - if (alien_ship_location) - alien_ship_location = 0 - else - alien_ship_location = 1 - return - -proc/formatJumpTo(location, where = "") - var/turf/loc - - if (isturf(location)) - loc = location - else - loc = get_turf(location) - - if (where == "") - where = formatLocation(loc) - - return "[where]" - -proc/formatLocation(location) - var/turf/loc - - if (isturf(location)) - loc = location - else - loc = get_turf(location) - - var/area/A = get_area(location) - var/answer = "[istype(A) ? "[A.name]" : "UNKNOWN"] - [istype(loc) ? "[loc.x],[loc.y],[loc.z]" : "UNKNOWN"]" - return answer - -proc/formatPlayerPanel(var/mob/U,var/text="PP") - return "[text]" - -//Credit to MrStonedOne from TG for this QoL improvement -//returns 1 to let the dragdrop code know we are trapping this event -//returns 0 if we don't plan to trap the event -/datum/admins/proc/cmd_ghost_drag(var/mob/dead/observer/frommob, var/mob/living/tomob) - - - //if we couldn't do it manually, we can't do it here - the 0 means no message is displayed for failure - if (!check_rights(R_VAREDIT, 0)) - return 0 - - if (!frommob.ckey) - return 0 - - var/question = "" - if (tomob.ckey) - question = "This mob already has a user ([tomob.key]) in control of it! " - question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?" - if(alert(question, "Place ghost in control of mob?", "Yes", "No") != "Yes") - return 1 - - if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response - return 1 - - tomob.ghostize(0) //boot the old mob out - - message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].") - log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].") - feedback_add_details("admin_verb","CGD") - tomob.ckey = frommob.ckey - qdel(frommob) - return 1 + +var/global/BSACooldown = 0 +var/global/floorIsLava = 0 + + +//////////////////////////////// +/proc/message_admins(var/msg) + msg = "ADMIN LOG: [msg]" + log_adminwarn(msg) + for(var/client/C in admins) + if(R_ADMIN & C.holder.rights) + to_chat(C, msg) + +/proc/msg_admin_attack(var/text) //Toggleable Attack Messages + var/rendered = "ADMIN LOG: [text]" + log_adminwarn(rendered) + for(var/client/C in admins) + if(R_ADMIN & C.holder.rights) + if(C.prefs.toggles & CHAT_ATTACKLOGS) + var/msg = rendered + to_chat(C, msg) + +// Not happening. +// Yes I could do a +PERMISSIONS check but I'm both too lazy and worried admins might do it on accident. +/datum/admins/SDQL_update(var/const/var_name, var/new_value) + return 0 + +///////////////////////////////////////////////////////////////////////////////////////////////Panels + +/datum/admins/proc/show_player_panel(var/mob/M in mob_list) + set category = "Admin" + set name = "Show Player Panel" + set desc="Edit player (respawn, ban, heal, etc)" + + if(!M) + to_chat(usr, "You seem to be selecting a mob that doesn't exist anymore.") + return + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + + checkSessionKey() + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\admin.dm:40: var/body = "Options for [M.key]" + var/body = {"Options for [M.key] +Options panel for [M]"} + // END AUTOFIX + var/species_description + if(M.client) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\admin.dm:43: body += " played by [M.client] " + body += {"played by [M.client] + \[[M.client.holder ? M.client.holder.rank : "Player"]\]"} + // END AUTOFIX + if(istype(M, /mob/new_player)) + body += " Hasn't Entered Game " + else + body += " \[Heal\] " + if(ishuman(M)) + var/mob/living/carbon/human/H = M + species_description = "[H.species ? H.species.name : "No Species"]" + body += {" +

    \[ + VV - + TP - + Bans - + PM - + SM - + JMP\]

    + Mob type = [M.type][species_description ? " - Species = [species_description]" : ""]

    + Kick | + Warn | + UNWarn | + Ban | + Jobban | + OOC Ban | + Identity Ban | + Notes + "} + + if(M.client) + body += "| Prison | " + var/muted = M.client.prefs.muted + body += {"
    Mute: + \[IC | + OOC | + PRAY | + ADMINHELP | + DEADCHAT\] + (toggle all) + "} + + body += {"

    + Jump to | + Get | + Send To +

    + Traitor panel | + Narrate to | + Subtle message + "} + + // Mob-specific controls. + body += M.player_panel_controls(usr) + + if (M.client) + if(!istype(M, /mob/new_player)) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\admin.dm:90: body += "

    " + body += {"

    + Transformation: +
    "} + // END AUTOFIX + //Monkey + if(ismonkey(M)) + body += "Monkeyized | " + else + body += "Monkeyize | " + + //Corgi + if(iscorgi(M)) + body += "Corgized | " + else + body += "Corgize | " + + //AI / Cyborg + if(isAI(M)) + body += "Is an AI " + else if(ishuman(M)) + body += {"Make AI | + Make Robot | + Make MoMMI | + Make Alien | + Make slime | + Make Cluwne | + "} + + //Simple Animals + if(isanimal(M)) + body += "Re-Animalize | " + else + body += "Animalize | " + + // DNA2 - Admin Hax + if(iscarbon(M) && !isbrain(M) && !isalien(M)) + body += "

    " + body += "DNA Blocks:
    " + var/bname + for(var/block=1;block<=DNA_SE_LENGTH;block++) + if(((block-1)%5)==0) + body += "" + bname = assigned_blocks[block] + body += "" + body += "
     12345
    [block-1]" + if(bname) + var/bstate=M.dna.GetSEState(block) + var/bcolor="[(bstate)?"#006600":"#ff0000"]" + body += "[bname][block]" + else + body += "[block]" + body+="
    " + + // Law Admin Hax + if(issilicon(M) && M:laws) + body += "

    " + body += "Laws:
    " + var/datum/ai_laws/L = M:laws + body += L.display_admin_tools(M) + body += "
    Add Law" + body += " | Clear Laws" + body += " | Reset Lawset" + body += "
    Send Laws - User is not notified of changes until this button pushed!
    " + + body += {"

    + Rudimentary transformation:
    These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

    + Observer | + \[ Alien: Drone, + Hunter, + Queen, + Sentinel, + Larva \] + Human + \[ slime: Baby, + Adult \] + Monkey | + Cyborg | + Cat | + Runtime | + Corgi | + Ian | + Crab | + Coffee | + \[ Construct: Armoured , + Builder , + Wraith \] + Shade +
    + "} + + if (M.client) + body += {"

    + Other actions: +
    + Forcesay | + Thunderdome Green | + Thunderdome Red | + Thunderdome Admin | + Thunderdome Observer | + "} + + // language toggles + body += "

    Languages:
    " + var/f = 1 + for(var/k in all_languages) + var/datum/language/L = all_languages[k] + if(!f) body += " | " + else f = 0 + if(L in M.languages) + body += "[k]" + else + body += "[k]" + + body += {"
    + + "} + + usr << browse(body, "window=adminplayeropts-\ref[M];size=550x515") + feedback_add_details("admin_verb","SPP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/player_info/var/author // admin who authored the information +/datum/player_info/var/rank //rank of admin who made the notes +/datum/player_info/var/content // text content of the information +/datum/player_info/var/timestamp // Because this is bloody annoying + +#define PLAYER_NOTES_ENTRIES_PER_PAGE 50 +/datum/admins/proc/PlayerNotes() + set category = "Admin" + set name = "Player Notes" + + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + PlayerNotesPage(1) + +/datum/admins/proc/checkCID() + set category = "Admin" + set name = "Lookup bans on Computer ID" + + if(!usr) + return + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + checkSessionKey() + var/cid = input("Type computer ID", "CID", 0) as num | null + if(cid) + usr << link(getVGPanel("rapsheet", admin = 1, query = list("cid" = cid))) +// to_chat(usr, link("[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]&cid=[cid]")) + return + +/datum/admins/proc/checkCKEY() + set category = "Admin" + set name = "Lookup bans on CKEY" + + if(!usr) + return + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + checkSessionKey() + var/ckey = lowertext(input("Type player ckey", "ckey", null) as text | null) + usr << link(getVGPanel("rapsheet", admin = 1, query = list("ckey" = ckey))) +// usr << link("[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]&ckey=[ckey]") + return + +/datum/admins/proc/PlayerNotesPage(page) + var/dat = "Player notes
    " + var/savefile/S=new("data/player_notes.sav") + var/list/note_keys + S >> note_keys + if(!note_keys) + dat += "No notes found." + else + dat += "" + note_keys = sortList(note_keys) + + // Display the notes on the current page + var/number_pages = note_keys.len / PLAYER_NOTES_ENTRIES_PER_PAGE + // Emulate ceil(why does BYOND not have ceil) + if(number_pages != round(number_pages)) + number_pages = round(number_pages) + 1 + var/page_index = page - 1 + if(page_index < 0 || page_index >= number_pages) + return + + var/lower_bound = page_index * PLAYER_NOTES_ENTRIES_PER_PAGE + 1 + var/upper_bound = (page_index + 1) * PLAYER_NOTES_ENTRIES_PER_PAGE + upper_bound = min(upper_bound, note_keys.len) + for(var/index = lower_bound, index <= upper_bound, index++) + var/t = note_keys[index] + dat += "" + + dat += "
    [t]

    " + + // Display a footer to select different pages + for(var/index = 1, index <= number_pages, index++) + if(index == page) + dat += "" + dat += "[index] " + if(index == page) + dat += "" + + usr << browse(dat, "window=player_notes;size=400x400") + + +/datum/admins/proc/player_has_info(var/key as text) + var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") + var/list/infos + info >> infos + if(!infos || !infos.len) return 0 + else return 1 + +/proc/exportnotes(var/key as text) + var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") + var/list/infos + info >> infos + var/list/noteslist = list() + if(!infos) + return list("1" = "No notes found for [key]") + else + var/i = 0 + + for(var/datum/player_info/I in infos) + i += 1 + if(!I.timestamp) + I.timestamp = "Pre-4/3/2012" + if(!I.rank) + I.rank = "N/A" + /*noteslist["note:[i]"] = "[I.content]" + noteslist["author:[i]"] = "[I.author]" + noteslist["rank:[i]"] = "[I.rank]" + noteslist["timestamp:[i]"] = "[I.timestamp]"*/ + noteslist["[i]"] = "[I.content] by [I.author] ([I.rank]) on [I.timestamp]" + if(!noteslist.len) + noteslist["1"] = "No notes found for [key]" + return noteslist +/datum/admins/proc/show_player_info(var/key as text) + set category = "Admin" + set name = "Show Player Info" + + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + + var/dat = {"Info on [key] +"} + + 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 + var/update_file = 0 + var/i = 0 + for(var/datum/player_info/I in infos) + i += 1 + if(!I.timestamp) + I.timestamp = "Pre-4/3/2012" + update_file = 1 + if(!I.rank) + I.rank = "N/A" + update_file = 1 + dat += "[I.content] by [I.author] ([I.rank]) on [I.timestamp] " + if(I.author == usr.key || check_rights(R_PERMISSIONS, show_msg = 0)) + dat += "Remove" + dat += "

    " + if(update_file) + info << infos + + dat += {"
    + Add Comment
    + "} + + usr << browse(dat, "window=adminplayerinfo;size=480x480") + +/datum/admins/proc/access_news_network() //MARKER + set category = "Fun" + set name = "Access Newscaster Network" + set desc = "Allows you to view, add and edit news feeds." + + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + var/dat + dat = text("Admin Newscaster

    Admin Newscaster Unit

    ") + + switch(admincaster_screen) + if(0) + dat += {"Welcome to the admin newscaster.
    Here you can add, edit and censor every newspiece on the network. +
    Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units. +
    Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!
    + "} + if(news_network.wanted_issue) + dat+= "
    Read Wanted Issue" + + dat+= {"

    Create Feed Channel +
    View Feed Channels +
    Submit new Feed story +

    Exit + "} + + var/wanted_already = 0 + if(news_network.wanted_issue) + wanted_already = 1 + + dat+={"
    Feed Security functions:
    +
    [(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue +
    Censor Feed Stories +
    Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel. +

    The newscaster recognises you as:
    [src.admincaster_signature]
    + "} + if(1) + dat+= "Station Feed Channels
    " + if( isemptylist(news_network.network_channels) ) + dat+="No active channels found..." + else + for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + if(CHANNEL.is_admin_channel) + dat+="[CHANNEL.channel_name]
    " + else + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
    " + dat+={"

    Refresh +
    Back + "} + + if(2) + dat+={" + Creating new Feed Channel... +
    Channel Name: [src.admincaster_feed_channel.channel_name]
    + Channel Author: [src.admincaster_signature]
    + Will Accept Public Feeds: [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]

    +
    Submit

    Cancel
    + "} + if(3) + dat+={" + Creating new Feed Message... +
    Receiving Channel: [src.admincaster_feed_channel.channel_name]
    " //MARK + Message Author: [src.admincaster_signature]
    + Message Body: [src.admincaster_feed_message.body]
    +
    Submit

    Cancel
    + "} + if(4) + dat+={" + Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].

    +
    Return
    + "} + if(5) + dat+={" + Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.

    +
    Return
    + "} + if(6) + dat+="ERROR: Could not submit Feed story to Network.

    " + if(src.admincaster_feed_channel.channel_name=="") + dat+="�Invalid receiving channel name.
    " + if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]") + dat+="�Invalid message body.
    " + dat+="
    Return
    " + if(7) + dat+="ERROR: Could not submit Feed Channel to Network.

    " + if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") + dat+="�Invalid channel name.
    " + var/check = 0 + for(var/datum/feed_channel/FC in news_network.network_channels) + if(FC.channel_name == src.admincaster_feed_channel.channel_name) + check = 1 + break + if(check) + dat+="�Channel name already in use.
    " + dat+="
    Return
    " + if(9) + dat+="[src.admincaster_feed_channel.channel_name]: \[created by: [src.admincaster_feed_channel.author]\]
    " + if(src.admincaster_feed_channel.censored) + dat+={" + ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
    + No further feed story additions are allowed while the D-Notice is in effect.


    + "} + else + if( isemptylist(src.admincaster_feed_channel.messages) ) + dat+="No feed messages found in channel...
    " + else + var/i = 0 + for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + i++ + dat+="-[MESSAGE.body]
    " + if(MESSAGE.img) + usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") + dat+="

    " + dat+="\[Story by [MESSAGE.author]\]
    " + dat+={" +

    Refresh +
    Back + "} + if(10) + dat+={" + Nanotrasen Feed Censorship Tool
    + NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
    + Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
    +
    Select Feed channel to get Stories from:
    + "} + if(isemptylist(news_network.network_channels)) + dat+="No feed channels found active...
    " + else + for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
    " + dat+="
    Cancel" + if(11) + dat+={" + Nanotrasen D-Notice Handler
    + A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's + morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed + stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
    + "} + if(isemptylist(news_network.network_channels)) + dat+="No feed channels found active...
    " + else + for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
    " + + dat+="
    Back" + if(12) + dat+={" + [src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.author] \]
    + [(src.admincaster_feed_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
    + "} + if( isemptylist(src.admincaster_feed_channel.messages) ) + dat+="No feed messages found in channel...
    " + else + for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + dat+={" + -[MESSAGE.body]
    \[Story by [MESSAGE.author]\]
    + [(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
    + "} + dat+="
    Back" + if(13) + dat+={" + [src.admincaster_feed_channel.channel_name]: \[ created by: [src.admincaster_feed_channel.author] \]
    + Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
    + "} + if(src.admincaster_feed_channel.censored) + dat+={" + ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
    + No further feed story additions are allowed while the D-Notice is in effect.


    + "} + else + if( isemptylist(src.admincaster_feed_channel.messages) ) + dat+="No feed messages found in channel...
    " + else + for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + dat+="-[MESSAGE.body]
    \[Story by [MESSAGE.author]\]
    " + + dat+="
    Back" + if(14) + dat+="Wanted Issue Handler:" + var/wanted_already = 0 + var/end_param = 1 + if(news_network.wanted_issue) + wanted_already = 1 + end_param = 2 + if(wanted_already) + dat+="
    A wanted issue is already in Feed Circulation. You can edit or cancel it below.
    " + dat+={" +
    + Criminal Name: [src.admincaster_feed_message.author]
    + Description: [src.admincaster_feed_message.body]
    + "} + if(wanted_already) + dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
    " + else + dat+="Wanted Issue will be created under prosecutor: [src.admincaster_signature]
    " + dat+="
    [(wanted_already) ? ("Edit Issue") : ("Submit")]" + if(wanted_already) + dat+="
    Take down Issue" + dat+="
    Cancel" + if(15) + dat+={" + Wanted issue for [src.admincaster_feed_message.author] is now in Network Circulation.

    +
    Return
    + "} + if(16) + dat+="ERROR: Wanted Issue rejected by Network.

    " + if(src.admincaster_feed_message.author =="" || src.admincaster_feed_message.author == "\[REDACTED\]") + dat+="�Invalid name for person wanted.
    " + if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]") + dat+="�Invalid description.
    " + dat+="
    Return
    " + if(17) + dat+={" + Wanted Issue successfully deleted from Circulation
    +
    Return
    + "} + if(18) + dat+={" + -- STATIONWIDE WANTED ISSUE --
    \[Submitted by: [news_network.wanted_issue.backup_author]\]
    + Criminal: [news_network.wanted_issue.author]
    + Description: [news_network.wanted_issue.body]
    + Photo:: + "} + if(news_network.wanted_issue.img) + usr << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png") + dat+="
    " + else + dat+="None" + dat+="
    Back
    " + if(19) + dat+={" + Wanted issue for [src.admincaster_feed_message.author] successfully edited.

    +
    Return
    + "} + else + dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" + +// to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]") +// to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]") + usr << browse(dat, "window=admincaster_main;size=400x600") + onclose(usr, "admincaster_main") + + + +/datum/admins/proc/Jobbans() + if(!check_rights(R_BAN)) return + + var/dat = "Job Bans!
    " + for(var/t in jobban_keylist) + var/r = t + if( findtext(r,"##") ) + r = copytext( r, 1, findtext(r,"##") )//removes the description + dat += text("") + dat += "
    [t] (unban)
    " + usr << browse(dat, "window=ban;size=400x400") + +/datum/admins/proc/Game() + if(!check_rights(0)) return + + var/dat = {" +
    Game Panel

    \n + Change Game Mode
    + "} + if(master_mode == "secret") + dat += "(Force Secret Mode)
    " + + dat += {" +
    + +
    + Create Object
    + Quick Create Object
    + Create Turf
    + Create Mob
    +
    + Edit ZAS Settings
    + Choose a default ZAS setting
    + "} + + usr << browse(dat, "window=admin2;size=280x370") + return + +/datum/admins/proc/Secrets() + if(!check_rights(0)) return + + var/dat = "The first rule of adminbuse is: you don't talk about the adminbuse.
    " + + if(check_rights(R_FUN,0) || check_rights(R_ADMINBUS,0)) + dat += {" + Fourth-Wall Demolition
    +
    + "} + if(check_rights(R_ADMINBUS,0)) + dat += {" + Spawn an Adminbus
    + "} + if(check_rights(R_FUN,0)) + dat += {" + Spawn yourself as a Test Dummy
    +
    + "} + + if(check_rights(R_ADMIN,0)) + dat += {" + Admin Secrets
    +
    + Remove all bombs currently in existence
    + Bombing List
    + Show current traitors and objectives
    + Show last [length(lastsignalers)] signalers
    + Show last [length(lawchanges)] law changes
    + Show AI Laws
    + Show Game Mode
    + Show Crew Manifest
    + List DNA (Blood)
    + List Fingerprints

    +
    + "} + + if(check_rights(R_FUN,0)) + dat += {" + 'Random' Events
    +
    + Toggle station artificial gravity
    + Spawn a wave of meteors (aka lagocolyptic shower)
    + Spawn a gravitational anomaly (aka lagitational anomolag)
    + Spawn wormholes
    + Spawn blob
    + Trigger an Alien infestation
    + Spawn an Alien silently
    + Trigger a Spider infestation
    + Send in a strike team
    + Trigger a Carp migration
    + Irradiate the station
    + Trigger a Prison Break
    + Trigger a Virus Outbreak
    + Spawn an Immovable Rod
    + Toggle a "lights out" event
    + Spawn an Ion Storm
    + Spawn Space-Vines
    + Trigger a communication blackout
    + Trigger a wave of PDA spams
    +
    + Fun Secrets
    +
    + [ticker&&ticker.hardcore_mode ? "Disable" : "Enable"] hardcore mode (makes starvation kill!)
    + Remove 'internal' clothing
    + Remove ALL clothing
    + Turn all humans into monkeys
    + Remove firesuits, grilles, and pods
    + Make all areas powered
    + Make all areas unpowered
    + Power all SMES
    + Toggle Prison Shuttle Status(Use with S/R)
    + Send Prison Shuttle
    + Return Prison Shuttle
    + Warp all Players to Prison
    + Triple AI mode (needs to be used in the lobby)
    + Everyone is the traitor
    + There can only be one!
    + Ghost Mode
    + Make all players retarded
    + Make all items look like guns
    + Distribute experimental guns to the crew
    + Japanese Animes Mode
    + Egalitarian Station Mode
    + Move Alien Dinghy
    + Break all lights
    + Fix all lights
    + Unleash THE BEES onto the crew
    + The floor is lava! (DANGEROUS: extremely lame)
    + Toggle Nar-Sie's behaviour
    + Trigger a fake alert
    + Adds in some Micheal Bay to the shift without major destruction
    + Turn every players into Bomberman
    + Make Bomberman Bombs actually hurt players
    + Make Bomberman Bombs actually destroy stuff
    + Make Bomberman Bombs harmless to players(default)
    + Make Bomberman Bombs harmless to the environnement(default)
    + Create a turret
    +
    + Final Solutions
    + (Warning, these will end the round!)
    +
    + Summon Nar-Sie
    + Start a Supermatter Cascade
    + "} + + if(check_rights(R_SERVER,0)) + + dat += {" +
    + Server
    +
    + Toggle bomb cap
    + Toggle explosion method
    + "} + + dat += "
    " + + if(check_rights(R_DEBUG,0)) + dat += {" + Security Level Elevated
    +
    + Change all maintenance doors to engie/brig access only
    + Change all maintenance doors to brig access only
    + Remove cap on security officers
    + Custom Virus Outbreak
    +
    + Coder Secrets
    +
    + Show Job Debug
    + Admin Log
    +
    + "} + + usr << browse(dat, "window=secrets") + return + +/datum/admins/var/datum/shuttle/selected_shuttle +/datum/admins/proc/shuttle_magic() + var/dat = "WARNING: server may explode!

    " + + if(!istype(selected_shuttle)) + dat += "Select a shuttle
    " + else + dat += {"Selected shuttle: [selected_shuttle.name] ([selected_shuttle.type])
    + view variables | teleport to | select another shuttle
    + cooldown: [selected_shuttle.cooldown] | pre-flight delay: [selected_shuttle.pre_flight_delay] | transit delay: [selected_shuttle.transit_delay]
    + rotation [selected_shuttle.can_rotate ? "ENABLED" : "DISABLED"] | transit [selected_shuttle.use_transit ? "ENABLED" : "DISABLED"]
    + + Create a destination docking port
    + Add a destination docking port
    + Modify transit area
    + Get control console
    + Modify parameters[selected_shuttle.is_special() ? " and pre-defined areas" : ""] +
    + Send
    + Teleport
    + Make movement instant
    + Draw outline +
    + [selected_shuttle.lockdown ? "Lift lockdown" : "Lock down"]
    + Reset
    + Delete +
    + "} + + //The following commands don't need a selected shuttle + dat += {" + Turn current area into a shuttle
    + Create a shuttle docking port
    + Lock down all shuttles
    + "} + usr << browse(dat, "window=shuttlemagic") + + +/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge +//i.e. buttons/verbs + + +/datum/admins/proc/restart() + set category = "Server" + set name = "Restart" + set desc="Restarts the world" + + if (!usr.client.holder) + return + var/confirm = alert("Restart the game world?", "Restart", "Yes", "Cancel") + if(confirm == "Cancel") + return + if(confirm == "Yes") + to_chat(world, "Restarting world! Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!") + log_admin("[key_name(usr)] initiated a reboot.") + + feedback_set_details("end_error","admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]") + feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + if(blackbox) + blackbox.save_all_data_to_sql() + + CallHook("Reboot",list()) + + if (watchdog.waiting) + to_chat(world, "Server will shut down for an automatic update in a few seconds.") + watchdog.signal_ready() + return + + sleep(50) + world.Reboot() + + +/datum/admins/proc/announce() + set category = "Special Verbs" + set name = "Announce" + set desc="Announce your desires to the world" + + if(!check_rights(0)) return + + var/message = input("Global message to send:", "Admin Announce", null, null) as message + if(message) + if(!check_rights(R_SERVER,0)) + message = adminscrub(message,500) + to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n \t [message]") + log_admin("Announce: [key_name(usr)] : [message]") + feedback_add_details("admin_verb","A") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleooc() + set category = "Server" + set desc="Globally Toggles OOC" + set name="Toggle OOC" + + ooc_allowed = !( ooc_allowed ) + if (ooc_allowed) + to_chat(world, "The OOC channel has been globally enabled!") + else + to_chat(world, "The OOC channel has been globally disabled!") + log_admin("[key_name(usr)] toggled OOC.") + message_admins("[key_name_admin(usr)] toggled OOC.", 1) + feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/admins/proc/toggleoocdead() + set category = "Server" + set desc="Toggle dis bitch" + set name="Toggle Dead OOC" + dooc_allowed = !( dooc_allowed ) + + log_admin("[key_name(usr)] toggled OOC.") + message_admins("[key_name_admin(usr)] toggled Dead OOC.", 1) + feedback_add_details("admin_verb","TDOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggletraitorscaling() + set category = "Server" + set desc="Toggle traitor scaling" + set name="Toggle Traitor Scaling" + + traitor_scaling = !traitor_scaling + log_admin("[key_name(usr)] toggled Traitor Scaling to [traitor_scaling].") + message_admins("[key_name_admin(usr)] toggled Traitor Scaling [traitor_scaling ? "on" : "off"].", 1) + feedback_add_details("admin_verb","TTS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/startnow() + set category = "Server" + set desc="Start the round RIGHT NOW" + set name="Start Now" + + if(!ticker) + alert("Unable to start the game as it is not set up.") + return + if(ticker.current_state == GAME_STATE_PREGAME) + ticker.current_state = GAME_STATE_SETTING_UP + log_admin("[usr.key] has started the game.") + message_admins("[usr.key] has started the game.") + feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return 1 + else + to_chat(usr, "Error: Start Now: Game has already started.") + return 0 + +/datum/admins/proc/toggleenter() + set category = "Server" + set desc="People can't enter" + set name="Toggle Entering" + + enter_allowed = !( enter_allowed ) + if (!( enter_allowed )) + to_chat(world, "New players may no longer enter the game.") + else + to_chat(world, "New players may now enter the game.") + log_admin("[key_name(usr)] toggled new player game entering.") + message_admins("[key_name_admin(usr)] toggled new player game entering.", 1) + world.update_status() + feedback_add_details("admin_verb","TE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleAI() + set category = "Server" + set desc="People can't be AI" + set name="Toggle AI" + + config.allow_ai = !( config.allow_ai ) + if (!( config.allow_ai )) + to_chat(world, "The AI job is no longer chooseable.") + else + to_chat(world, "The AI job is chooseable now.") + log_admin("[key_name(usr)] toggled AI allowed.") + world.update_status() + feedback_add_details("admin_verb","TAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleaban() + set category = "Server" + set desc="Respawn basically" + set name="Toggle Respawn" + + abandon_allowed = !( abandon_allowed ) + if (abandon_allowed) + to_chat(world, "You may now respawn.") + else + to_chat(world, "You may no longer respawn :(") + message_admins("[key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].", 1) + log_admin("[key_name(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].") + world.update_status() + feedback_add_details("admin_verb","TR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggle_aliens() + set category = "Server" + set desc="Toggle alien mobs" + set name="Toggle Aliens" + + aliens_allowed = !aliens_allowed + log_admin("[key_name(usr)] toggled Aliens to [aliens_allowed].") + message_admins("[key_name_admin(usr)] toggled Aliens [aliens_allowed ? "on" : "off"].", 1) + feedback_add_details("admin_verb","TA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +#define LOBBY_TICKING_STOPPED 0 +#define LOBBY_TICKING_RESTARTED 2 +/datum/admins/proc/delay() + set category = "Server" + set desc="Delay the game start/end" + set name="Delay" + + if(!check_rights(R_ADMIN)) return + if (!ticker || ticker.current_state != GAME_STATE_PREGAME) + if(ticker.delay_end == 2) + to_chat(world, "World Reboot triggered by [key_name(usr)]!") + log_admin("World Reboot triggered by [key_name(usr)]!") + if(watchdog.waiting) + watchdog.signal_ready() + else + world.Reboot() + ticker.delay_end = !ticker.delay_end + log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") + message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) + + return //alert("Round end delayed", null, null, null, null, null) + if (!( going )) + going = LOBBY_TICKING_RESTARTED + ticker.pregame_timeleft = world.timeofday + ticker.remaining_time + to_chat(world, "The game will start soon.") + log_admin("[key_name(usr)] removed the delay.") + else + going = LOBBY_TICKING_STOPPED + to_chat(world, "The game start has been delayed.") + log_admin("[key_name(usr)] delayed the game.") + feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +#undef LOBBY_TICKING_STOPPED +#undef LOBBY_TICKING_RESTARTED +/datum/admins/proc/adjump() + set category = "Server" + set desc="Toggle admin jumping" + set name="Toggle Jump" + + config.allow_admin_jump = !(config.allow_admin_jump) + message_admins("Toggled admin jumping to [config.allow_admin_jump].") + feedback_add_details("admin_verb","TJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/adspawn() + set category = "Server" + set desc="Toggle admin spawning" + set name="Toggle Spawn" + + config.allow_admin_spawning = !(config.allow_admin_spawning) + message_admins("Toggled admin item spawning to [config.allow_admin_spawning].") + feedback_add_details("admin_verb","TAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/adrev() + set category = "Server" + set desc="Toggle admin revives" + set name="Toggle Revive" + + config.allow_admin_rev = !(config.allow_admin_rev) + message_admins("Toggled reviving to [config.allow_admin_rev].") + feedback_add_details("admin_verb","TAR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/immreboot() + set category = "Server" + set desc="Reboots the server post haste" + set name="Immediate Reboot" + + if(!usr.client.holder) return + if( alert("Reboot server?",,"Yes","No") == "No") + return + to_chat(world, "Rebooting world! Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]!") + log_admin("[key_name(usr)] initiated an immediate reboot.") + + feedback_set_details("end_error","immediate admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]") + feedback_add_details("admin_verb","IR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + if(blackbox) + blackbox.save_all_data_to_sql() + + CallHook("Reboot",list()) + + if (watchdog.waiting) + to_chat(world, "Server will shut down for an automatic update in a few seconds.") + watchdog.signal_ready() + return + + world.Reboot() + +/datum/admins/proc/unprison(var/mob/M in mob_list) + set category = "Admin" + set name = "Unprison" + + if (M.z == 2) + if (config.allow_admin_jump) + M.loc = pick(latejoin) + message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]", 1) + log_admin("[key_name(usr)] has unprisoned [key_name(M)]") + else + alert("Admin jumping disabled") + else + alert("[M.name] is not prisoned.") + feedback_add_details("admin_verb","UP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS + +/proc/is_special_character(mob/M as mob) // returns 1 for specail characters and 2 for heroes of gamemode + if(!ticker || !ticker.mode) + return 0 + if (!istype(M)) + return 0 + if(isrev(M) || isrevhead(M)) + if (ticker.mode.config_tag == "revolution") + return 2 + return 1 + if(iscult(M)) + if (ticker.mode.config_tag == "cult") + return 2 + return 1 + if(ismalf(M)) + if (ticker.mode.config_tag == "malfunction") + return 2 + return 1 + if(isnukeop(M)) + if (ticker.mode.config_tag == "nuclear") + return 2 + return 1 + if(iswizard(M)) + if (ticker.mode.config_tag == "wizard") + return 2 + return 1 + if(ischangeling(M)) + if (ticker.mode.config_tag == "changeling") + return 2 + return 1 + if(isborer(M)) + if (ticker.mode.config_tag == "borer") + return 2 + return 1 + if(isbadmonkey(M)) + if (ticker.mode.config_tag == "monkey") + return 2 + return 1 + if(isrobot(M)) + var/mob/living/silicon/robot/R = M + if(R.emagged) + return 1 + if(M.mind&&M.mind.special_role)//If they have a mind and special role, they are some type of traitor or antagonist. + return 1 + + return 0 + +/* +/datum/admins/proc/get_sab_desc(var/target) + switch(target) + if(1) + return "Destroy at least 70% of the plasma canisters on the station" + if(2) + return "Destroy the AI" + if(3) + var/count = 0 + for(var/mob/living/carbon/monkey/Monkey in world) + if(Monkey.z == 1) + count++ + return "Kill all [count] of the monkeys on the station" + if(4) + return "Cut power to at least 80% of the station" + else + return "Error: Invalid sabotage target: [target]" +*/ +/datum/admins/proc/spawn_atom(var/object as text) + set category = "Debug" + set desc = "(atom path) Spawn an atom" + set name = "Spawn" + + if(!check_rights(R_SPAWN)) return + + var/list/matches = new() + + for(var/path in typesof(/atom)) + if(findtext("[path]", object)) + matches += path + + if(matches.len==0) + return + + var/chosen + if(matches.len==1) + chosen = matches[1] + else + chosen = input("Select an atom type", "Spawn Atom", matches[1]) as null|anything in matches + if(!chosen) + return + + if(ispath(chosen,/turf)) + var/turf/T = get_turf(usr.loc) + T.ChangeTurf(chosen) + else + new chosen(usr.loc) + + log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") + feedback_add_details("admin_verb","SA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/show_traitor_panel(var/mob/M in mob_list) + set category = "Admin" + set desc = "Edit mobs's memory and role" + set name = "Show Traitor Panel" + + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(!M.mind) + to_chat(usr, "This mob has no mind!") + return + + M.mind.edit_memory() + feedback_add_details("admin_verb","STP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/datum/admins/proc/toggletintedweldhelmets() + set category = "Debug" + set desc="Reduces view range when wearing welding helmets" + set name="Toggle tinted welding helmes" + + tinted_weldhelh = !( tinted_weldhelh ) + if (tinted_weldhelh) + to_chat(world, "The tinted_weldhelh has been enabled!") + else + to_chat(world, "The tinted_weldhelh has been disabled!") + log_admin("[key_name(usr)] toggled tinted_weldhelh.") + message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.", 1) + feedback_add_details("admin_verb","TTWH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggleguests() + set category = "Server" + set desc="Guests can't enter" + set name="Toggle guests" + + guests_allowed = !( guests_allowed ) + if (!( guests_allowed )) + to_chat(world, "Guests may no longer enter the game.") + else + to_chat(world, "Guests may now enter the game.") + log_admin("[key_name(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.") + message_admins("[key_name_admin(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.", 1) + feedback_add_details("admin_verb","TGU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/unjobban_panel() + set name = "Unjobban Panel" + set category = "Admin" + if (src.holder) + src.holder.unjobbanpanel() + feedback_add_details("admin_verb","UJBP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/datum/admins/proc/output_ai_laws() + var/ai_number = 0 + for(var/mob/living/silicon/S in mob_list) + ai_number++ + if(isAI(S)) + to_chat(usr, "AI [key_name(S, usr)]'s laws:") + else if(isrobot(S)) + var/mob/living/silicon/robot/R = S + to_chat(usr, "CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independant)"]: laws:") + else if (ispAI(S)) + var/mob/living/silicon/pai/pAI = S + to_chat(usr, "pAI [key_name(S, usr)]'s laws (master: [pAI.master] ):") + else + to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") + + if(ispAI(S)) + var/mob/living/silicon/pai/pAI = S + pAI.show_directives(usr) + else if (S.laws == null) + to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.") + else + S.laws.show_laws(usr) + + if(!ai_number) + to_chat(usr, "No AIs located")//Just so you know the thing is actually working and not just ignoring you. + + +/client/proc/update_mob_sprite(mob/living/carbon/human/H as mob in mob_list) + set category = "Admin" + set name = "Update Mob Sprite" + set desc = "Should fix any mob sprite update errors." + + if (!holder) + to_chat(src, "Only administrators may use this command.") + return + + if(istype(H)) + H.regenerate_icons() + +// +// +//ALL DONE +//********************************************************************************************************* +//TO-DO: +// +// + + +/**********************Administration Shuttle**************************/ + +var/admin_shuttle_location = 0 // 0 = centcom 13, 1 = station + +proc/move_admin_shuttle() + var/area/fromArea + var/area/toArea + if (admin_shuttle_location == 1) + fromArea = locate(/area/shuttle/administration/station) + toArea = locate(/area/shuttle/administration/centcom) + else + fromArea = locate(/area/shuttle/administration/centcom) + toArea = locate(/area/shuttle/administration/station) + fromArea.move_contents_to(toArea) + if (admin_shuttle_location) + admin_shuttle_location = 0 + else + admin_shuttle_location = 1 + return + +/**********************Alien ship**************************/ + +var/alien_ship_location = 1 // 0 = base , 1 = mine + +proc/move_alien_ship() + var/area/fromArea + var/area/toArea + if (alien_ship_location == 1) + fromArea = locate(/area/shuttle/alien/mine) + toArea = locate(/area/shuttle/alien/base) + else + fromArea = locate(/area/shuttle/alien/base) + toArea = locate(/area/shuttle/alien/mine) + fromArea.move_contents_to(toArea) + if (alien_ship_location) + alien_ship_location = 0 + else + alien_ship_location = 1 + return + +proc/formatJumpTo(location, where = "") + var/turf/loc + + if (isturf(location)) + loc = location + else + loc = get_turf(location) + + if (where == "") + where = formatLocation(loc) + + return "[where]" + +proc/formatLocation(location) + var/turf/loc + + if (isturf(location)) + loc = location + else + loc = get_turf(location) + + var/area/A = get_area(location) + var/answer = "[istype(A) ? "[A.name]" : "UNKNOWN"] - [istype(loc) ? "[loc.x],[loc.y],[loc.z]" : "UNKNOWN"]" + return answer + +proc/formatPlayerPanel(var/mob/U,var/text="PP") + return "[text]" + +//Credit to MrStonedOne from TG for this QoL improvement +//returns 1 to let the dragdrop code know we are trapping this event +//returns 0 if we don't plan to trap the event +/datum/admins/proc/cmd_ghost_drag(var/mob/dead/observer/frommob, var/mob/living/tomob) + + + //if we couldn't do it manually, we can't do it here - the 0 means no message is displayed for failure + if (!check_rights(R_VAREDIT, 0)) + return 0 + + if (!frommob.ckey) + return 0 + + var/question = "" + if (tomob.ckey) + question = "This mob already has a user ([tomob.key]) in control of it! " + question += "Are you sure you want to place [frommob.name]([frommob.key]) in control of [tomob.name]?" + if(alert(question, "Place ghost in control of mob?", "Yes", "No") != "Yes") + return 1 + + if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response + return 1 + + tomob.ghostize(0) //boot the old mob out + + message_admins("[key_name_admin(usr)] has put [frommob.ckey] in control of [tomob.name].") + log_admin("[key_name(usr)] stuffed [frommob.ckey] into [tomob.name].") + feedback_add_details("admin_verb","CGD") + tomob.ckey = frommob.ckey + qdel(frommob) + return 1 diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 862e797bc54..c9c274f5c9d 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -1,158 +1,158 @@ -var/list/admin_ranks = list() //list of all ranks with associated rights - -//load our rank - > rights associations -/proc/load_admin_ranks() - admin_ranks.len = 0 - - var/previous_rights = 0 - - //load text from file - var/list/Lines = file2list("config/admin_ranks.txt") - - //process each line seperately - for(var/line in Lines) - if(!length(line)) continue - if(copytext(line,1,2) == "#") continue - - var/list/List = text2list(line,"+") - if(!List.len) continue - - var/rank = ckeyEx(List[1]) - switch(rank) - if(null,"") continue - if("Removed") continue //Reserved - - var/rights = 0 - for(var/i=2, i<=List.len, i++) - switch(ckey(List[i])) - if("@","prev") rights |= previous_rights - if("buildmode","build") rights |= R_BUILDMODE - if("admin") rights |= R_ADMIN - if("ban") rights |= R_BAN - if("fun") rights |= R_FUN - if("server") rights |= R_SERVER - if("debug") rights |= R_DEBUG - if("permissions","rights") rights |= R_PERMISSIONS - if("possess") rights |= R_POSSESS - if("stealth") rights |= R_STEALTH - if("rejuv","rejuvinate") rights |= R_REJUVINATE - if("varedit") rights |= R_VAREDIT - if("everything","host","all") rights |= R_HOST - if("sound","sounds") rights |= R_SOUNDS - if("spawn","create") rights |= R_SPAWN - if("mod") rights |= R_MOD - if("adminbus","bus") rights |= R_ADMINBUS - - admin_ranks[rank] = rights - previous_rights = rights - - #ifdef TESTING - var/msg = "Permission Sets Built:\n" - for(var/rank in admin_ranks) - msg += "\t[rank] - [admin_ranks[rank]]\n" - testing(msg) - #endif - - -/proc/load_admins() - //clear the datums references - admin_datums.len = 0 - for(var/client/C in admins) - C.remove_admin_verbs() - C.holder = null - admins.len = 0 - - if(config.admin_legacy_system) - load_admin_ranks() - - //load text from file - var/list/Lines = file2list("config/admins.txt") - - //process each line seperately - for(var/line in Lines) - if(!length(line)) continue - if(copytext(line,1,2) == "#") continue - - //Split the line at every "-" - var/list/List = text2list(line, "-") - if(!List.len) continue - - //ckey is before the first "-" - var/ckey = ckey(List[1]) - if(!ckey) continue - - //rank follows the first "-" - var/rank = "" - if(List.len >= 2) - rank = ckeyEx(List[2]) - - //load permissions associated with this rank - var/rights = admin_ranks[rank] - - //create the admin datum and store it for later use - var/datum/admins/D = new /datum/admins(rank, rights, ckey) - - //find the client for a ckey if they are connected and associate them with the new admin datum - D.associate(directory[ckey]) - - else - //The current admin system uses SQL - - establish_db_connection() - if(!dbcon.IsConnected()) - world.log << "Failed to connect to database in load_admins(). Reverting to legacy system." - diary << "Failed to connect to database in load_admins(). Reverting to legacy system." - config.admin_legacy_system = 1 - load_admins() - return - - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin") - query.Execute() - while(query.NextRow()) - var/ckey = query.item[1] - var/rank = query.item[2] - if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes. - - var/rights = query.item[4] - if(istext(rights)) rights = text2num(rights) - var/datum/admins/D = new /datum/admins(rank, rights, ckey) - - //find the client for a ckey if they are connected and associate them with the new admin datum - D.associate(directory[ckey]) - if(!admin_datums) - world.log << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." - diary << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." - config.admin_legacy_system = 1 - load_admins() - return - - #ifdef TESTING - var/msg = "Admins Built:\n" - for(var/ckey in admin_datums) - var/rank - var/datum/admins/D = admin_datums[ckey] - if(D) rank = D.rank - msg += "\t[ckey] - [rank]\n" - testing(msg) - #endif - - -#ifdef TESTING -/client/verb/changerank(newrank in admin_ranks) - if(holder) - holder.rank = newrank - holder.rights = admin_ranks[newrank] - else - holder = new /datum/admins(newrank,admin_ranks[newrank],ckey) - remove_admin_verbs() - holder.associate(src) - -/client/verb/changerights(newrights as num) - if(holder) - holder.rights = newrights - else - holder = new /datum/admins("testing",newrights,ckey) - remove_admin_verbs() - holder.associate(src) - -#endif +var/list/admin_ranks = list() //list of all ranks with associated rights + +//load our rank - > rights associations +/proc/load_admin_ranks() + admin_ranks.len = 0 + + var/previous_rights = 0 + + //load text from file + var/list/Lines = file2list("config/admin_ranks.txt") + + //process each line seperately + for(var/line in Lines) + if(!length(line)) continue + if(copytext(line,1,2) == "#") continue + + var/list/List = text2list(line,"+") + if(!List.len) continue + + var/rank = ckeyEx(List[1]) + switch(rank) + if(null,"") continue + if("Removed") continue //Reserved + + var/rights = 0 + for(var/i=2, i<=List.len, i++) + switch(ckey(List[i])) + if("@","prev") rights |= previous_rights + if("buildmode","build") rights |= R_BUILDMODE + if("admin") rights |= R_ADMIN + if("ban") rights |= R_BAN + if("fun") rights |= R_FUN + if("server") rights |= R_SERVER + if("debug") rights |= R_DEBUG + if("permissions","rights") rights |= R_PERMISSIONS + if("possess") rights |= R_POSSESS + if("stealth") rights |= R_STEALTH + if("rejuv","rejuvinate") rights |= R_REJUVINATE + if("varedit") rights |= R_VAREDIT + if("everything","host","all") rights |= R_HOST + if("sound","sounds") rights |= R_SOUNDS + if("spawn","create") rights |= R_SPAWN + if("mod") rights |= R_MOD + if("adminbus","bus") rights |= R_ADMINBUS + + admin_ranks[rank] = rights + previous_rights = rights + + #ifdef TESTING + var/msg = "Permission Sets Built:\n" + for(var/rank in admin_ranks) + msg += "\t[rank] - [admin_ranks[rank]]\n" + testing(msg) + #endif + + +/proc/load_admins() + //clear the datums references + admin_datums.len = 0 + for(var/client/C in admins) + C.remove_admin_verbs() + C.holder = null + admins.len = 0 + + if(config.admin_legacy_system) + load_admin_ranks() + + //load text from file + var/list/Lines = file2list("config/admins.txt") + + //process each line seperately + for(var/line in Lines) + if(!length(line)) continue + if(copytext(line,1,2) == "#") continue + + //Split the line at every "-" + var/list/List = text2list(line, "-") + if(!List.len) continue + + //ckey is before the first "-" + var/ckey = ckey(List[1]) + if(!ckey) continue + + //rank follows the first "-" + var/rank = "" + if(List.len >= 2) + rank = ckeyEx(List[2]) + + //load permissions associated with this rank + var/rights = admin_ranks[rank] + + //create the admin datum and store it for later use + var/datum/admins/D = new /datum/admins(rank, rights, ckey) + + //find the client for a ckey if they are connected and associate them with the new admin datum + D.associate(directory[ckey]) + + else + //The current admin system uses SQL + + establish_db_connection() + if(!dbcon.IsConnected()) + world.log << "Failed to connect to database in load_admins(). Reverting to legacy system." + diary << "Failed to connect to database in load_admins(). Reverting to legacy system." + config.admin_legacy_system = 1 + load_admins() + return + + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin") + query.Execute() + while(query.NextRow()) + var/ckey = query.item[1] + var/rank = query.item[2] + if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes. + + var/rights = query.item[4] + if(istext(rights)) rights = text2num(rights) + var/datum/admins/D = new /datum/admins(rank, rights, ckey) + + //find the client for a ckey if they are connected and associate them with the new admin datum + D.associate(directory[ckey]) + if(!admin_datums) + world.log << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." + diary << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system." + config.admin_legacy_system = 1 + load_admins() + return + + #ifdef TESTING + var/msg = "Admins Built:\n" + for(var/ckey in admin_datums) + var/rank + var/datum/admins/D = admin_datums[ckey] + if(D) rank = D.rank + msg += "\t[ckey] - [rank]\n" + testing(msg) + #endif + + +#ifdef TESTING +/client/verb/changerank(newrank in admin_ranks) + if(holder) + holder.rank = newrank + holder.rights = admin_ranks[newrank] + else + holder = new /datum/admins(newrank,admin_ranks[newrank],ckey) + remove_admin_verbs() + holder.associate(src) + +/client/verb/changerights(newrights as num) + if(holder) + holder.rights = newrights + else + holder = new /datum/admins("testing",newrights,ckey) + remove_admin_verbs() + holder.associate(src) + +#endif diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 9cde7c38913..e4db3c032ba 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1,1060 +1,1060 @@ -//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless -var/list/admin_verbs_default = list( - /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ - /client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/ - /client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/ - /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*/ - /datum/admins/proc/checkCID, - /datum/admins/proc/checkCKEY -// /client/proc/deadchat /*toggles deadchat on/off*/ - ) -var/list/admin_verbs_admin = list( - /client/proc/set_base_turf, - /datum/admins/proc/delay, - /client/proc/SendCentcommFax, /*sends a fax to all fax machines*/ - /client/proc/player_panel, /*shows an interface for all players, with links to various panels (old style)*/ - /client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/ - /client/proc/invisimin, /*allows our mob to go invisible/visible*/ -// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage - /datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/ - /datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/ - /datum/admins/proc/announce, /*priority announce something to all clients.*/ - /client/proc/colorooc, /*allows us to set a custom colour for everythign we say in ooc*/ - /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ - /client/proc/toggle_view_range, /*changes how far we can see*/ - /datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/ - /datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/ - /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ - /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ - /client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/ - /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ - /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ - /datum/admins/proc/access_news_network, /*allows access of newscasters*/ - /client/proc/giveruntimelog, /*allows us to give access to runtime logs to somebody*/ - /client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/ - /client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/ - /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/ - /client/proc/Getmob, /*teleports a mob to our location*/ - /client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/ -// /client/proc/sendmob, /*sends a mob somewhere*/ -Removed due to it needing two sorting procs to work, which were executed every time an admin right-clicked. ~Errorage - /client/proc/Jump, - /client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/ - /client/proc/jumptomob, /*allows us to jump to a specific mob*/ - /client/proc/jumptoturf, /*allows us to jump to a specific turf*/ - /client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/ - /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/ - /client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/ - /client/proc/cmd_admin_local_narrate, /*send text locally to all players in view, similar to direct narrate*/ - /client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/ - /client/proc/cmd_admin_create_centcom_report, - /client/proc/check_words, /*displays cult-words*/ - /client/proc/check_ai_laws, /*shows AI and borg laws*/ - /client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/ - /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/ - /client/proc/toggleprayers, /*toggles prayers on/off*/ -// /client/proc/toggle_hear_deadcast, /*toggles whether we hear deadchat*/ - /client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/ - /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/ - /client/proc/secrets, - /client/proc/shuttle_magic, - /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ - /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/ - /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ - /client/proc/cmd_admin_say, /*admin-only ooc chat*/ - /datum/admins/proc/PlayerNotes, - /client/proc/cmd_mod_say, - /client/proc/cmd_mod_window, - /datum/admins/proc/show_player_info, - /client/proc/free_slot, /*frees slot for chosen job*/ - /client/proc/cmd_admin_change_custom_event, - /client/proc/cmd_admin_rejuvenate, - /client/proc/toggleattacklogs, - /client/proc/toggledebuglogs, - /client/proc/check_customitem_activity, - // /client/proc/man_up, - // /client/proc/global_man_up, - /client/proc/response_team, // Response Teams admin verb - /client/proc/toggle_antagHUD_use, - /client/proc/toggle_antagHUD_restrictions, - /client/proc/allow_character_respawn /* Allows a ghost to respawn */ -) -var/list/admin_verbs_ban = list( - /client/proc/unban_panel, - /client/proc/jobbans, - /client/proc/unjobban_panel - // /client/proc/DB_ban_panel - ) -var/list/admin_verbs_sounds = list( - /client/proc/play_local_sound, - /client/proc/play_sound - ) -var/list/admin_verbs_fun = list( - /datum/admins/proc/media_stop_all, - /client/proc/object_talk, - /client/proc/cmd_admin_dress, - /client/proc/cmd_admin_gib_self, - /client/proc/drop_bomb, - /client/proc/drop_emp, - /client/proc/cinematic, - /client/proc/one_click_antag, - /client/proc/antag_madness, - /datum/admins/proc/toggle_aliens, - // FUUUUCKED /client/proc/zombie_event, // ZOMBB-B-BIES - /client/proc/cmd_admin_add_freeform_ai_law, - /client/proc/cmd_admin_add_random_ai_law, - /client/proc/make_sound, - /client/proc/toggle_random_events, - /client/proc/set_ooc, - /client/proc/editappear, - /client/proc/commandname, - /client/proc/delete_all_adminbus, - /client/proc/delete_all_bomberman, - /client/proc/create_bomberman_arena, - /client/proc/control_bomberman_arena, - /client/proc/gib_money, // /vg/ - /client/proc/smissmas, - /client/proc/achievement, - /client/proc/mommi_static, - /client/proc/makepAI - ) -var/list/admin_verbs_spawn = list( - /datum/admins/proc/spawn_atom, /* Allows us to spawn instances. */ - /client/proc/spawn_datum, /* Allows us to spawn datums to the marked datum buffer. */ - /client/proc/respawn_character - ) -var/list/admin_verbs_server = list( - /client/proc/Set_Holiday, - /client/proc/ToRban, - /datum/admins/proc/startnow, - /datum/admins/proc/restart, - /datum/admins/proc/toggleaban, - /client/proc/toggle_log_hrefs, - /datum/admins/proc/immreboot, - /client/proc/everyone_random, - /datum/admins/proc/toggleAI, - /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ - /client/proc/cmd_debug_del_all, - /datum/admins/proc/adrev, - /datum/admins/proc/adspawn, - /datum/admins/proc/adjump, - /datum/admins/proc/toggle_aliens, - /client/proc/toggle_random_events, - /client/proc/check_customitem_activity, - /client/proc/dump_chemreactions, - ) -var/list/admin_verbs_debug = list( - /client/proc/gc_dump_hdl, - /client/proc/getSchedulerContext, - /client/proc/cmd_admin_list_open_jobs, - /proc/getbrokeninhands, - /client/proc/Debug2, - /client/proc/kill_air, - /client/proc/cmd_debug_make_powernets, - /client/proc/kill_airgroup, - /client/proc/debug_controller, - /client/proc/cmd_debug_mob_lists, - /client/proc/cmd_admin_delete, - /client/proc/cmd_debug_del_all, - /client/proc/cmd_debug_tog_aliens, - /client/proc/air_report, - /client/proc/reload_admins, - /client/proc/restart_controller, - /client/proc/enable_debug_verbs, - /client/proc/callproc, - /client/proc/toggledebuglogs, - /client/proc/qdel_toggle, // /vg/ - /client/proc/cmd_admin_dump_instances, // /vg/ - /client/proc/cmd_admin_dump_machine_type_list, // /vg/ - /client/proc/disable_bloodvirii, // /vg - /client/proc/handle_paperwork, //this is completely experimental - /client/proc/reload_style_sheet, - /client/proc/reset_style_sheet, - /client/proc/test_movable_UI, - /client/proc/test_snap_UI, - /client/proc/configFood, - /client/proc/debug_reagents, - /client/proc/make_invulnerable, - /client/proc/cmd_admin_dump_delprofile, - /client/proc/mob_list, - /client/proc/cure_disease, - /client/proc/check_bomb, - /client/proc/set_teleport_pref, - /client/proc/check_convertables, - /client/proc/check_spiral, - /client/proc/cmd_admin_find_bad_blood_tracks, -#ifdef PROFILE_MACHINES - /client/proc/cmd_admin_dump_macprofile, -#endif - /client/proc/debugNatureMapGenerator, - /client/proc/callatomproc - ) -var/list/admin_verbs_possess = list( - /proc/possess, - /proc/release - ) -var/list/admin_verbs_permissions = list( - /client/proc/edit_admin_permissions - ) -var/list/admin_verbs_rejuv = list( - /client/proc/respawn_character - ) - -//verbs which can be hidden - needs work -var/list/admin_verbs_hideable = list( - /client/proc/set_ooc, - /client/proc/deadmin_self, -// /client/proc/deadchat, - /client/proc/toggleprayers, - /client/proc/toggle_hear_radio, - /datum/admins/proc/show_traitor_panel, - /datum/admins/proc/toggleenter, - /datum/admins/proc/toggleguests, - /datum/admins/proc/announce, - /client/proc/colorooc, - /client/proc/admin_ghost, - /client/proc/toggle_view_range, - /datum/admins/proc/view_txt_log, - /datum/admins/proc/view_atk_log, - /client/proc/cmd_admin_subtle_message, - /client/proc/cmd_admin_check_contents, - /datum/admins/proc/access_news_network, - /client/proc/admin_call_shuttle, - /client/proc/admin_cancel_shuttle, - /client/proc/cmd_admin_direct_narrate, - /client/proc/cmd_admin_world_narrate, - /client/proc/check_words, - /client/proc/play_local_sound, - /client/proc/play_sound, - /client/proc/object_talk, - /client/proc/cmd_admin_dress, - /client/proc/cmd_admin_gib_self, - /client/proc/drop_bomb, - /client/proc/drop_emp, - /client/proc/cinematic, - /datum/admins/proc/toggle_aliens, - /client/proc/cmd_admin_add_freeform_ai_law, - /client/proc/cmd_admin_add_random_ai_law, - /client/proc/cmd_admin_create_centcom_report, - /client/proc/make_sound, - /client/proc/toggle_random_events, - /client/proc/cmd_admin_add_random_ai_law, - /client/proc/Set_Holiday, - /client/proc/ToRban, - /datum/admins/proc/startnow, - /datum/admins/proc/restart, - /datum/admins/proc/delay, - /datum/admins/proc/toggleaban, - /client/proc/toggle_log_hrefs, - /datum/admins/proc/immreboot, - /client/proc/everyone_random, - /client/proc/shuttle_magic, - /datum/admins/proc/toggleAI, - /datum/admins/proc/adrev, - /datum/admins/proc/adspawn, - /datum/admins/proc/adjump, - /client/proc/restart_controller, - /client/proc/cmd_admin_list_open_jobs, - /client/proc/callproc, - /client/proc/Debug2, - /client/proc/reload_admins, - /client/proc/kill_air, - /client/proc/cmd_debug_make_powernets, - /client/proc/kill_airgroup, - /client/proc/debug_controller, - /client/proc/startSinglo, - /client/proc/cheat_power, - /client/proc/setup_atmos, - /client/proc/cmd_debug_mob_lists, - /client/proc/cmd_debug_del_all, - /client/proc/cmd_debug_tog_aliens, - /client/proc/air_report, - /client/proc/enable_debug_verbs, - /client/proc/mob_list, - /proc/possess, - /proc/release, - /client/proc/gc_dump_hdl - ) -var/list/admin_verbs_mod = list( - /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ - /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ - /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game.*/ - /client/proc/toggledebuglogs, - /datum/admins/proc/PlayerNotes, - /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ - /client/proc/cmd_mod_say, - /client/proc/cmd_mod_window, - /datum/admins/proc/show_player_info, - /client/proc/player_panel_new, - /client/proc/vv_marked_datum, - /datum/admins/proc/view_mob_attack_log /* Allow you to view attack logs since doing it in VV sucks */ -) -/client/proc/add_admin_verbs() - if(holder) - verbs += admin_verbs_default - if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself - if(holder.rights & R_ADMIN) verbs += admin_verbs_admin - if(holder.rights & R_BAN) verbs += admin_verbs_ban - if(holder.rights & R_FUN) verbs += admin_verbs_fun - if(holder.rights & R_SERVER) verbs += admin_verbs_server - if(holder.rights & R_DEBUG) verbs += admin_verbs_debug - if(holder.rights & R_POSSESS) verbs += admin_verbs_possess - if(holder.rights & R_PERMISSIONS) verbs += admin_verbs_permissions - if(holder.rights & R_STEALTH) verbs += /client/proc/stealth - if(holder.rights & R_REJUVINATE) verbs += admin_verbs_rejuv - if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds - if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn - if(holder.rights & R_MOD) verbs += admin_verbs_mod - if(holder.rights & R_ADMINBUS) verbs += /client/proc/secrets - -/client/proc/remove_admin_verbs() - verbs.Remove( - admin_verbs_default, - /client/proc/togglebuildmodeself, - admin_verbs_admin, - admin_verbs_ban, - admin_verbs_fun, - admin_verbs_server, - admin_verbs_debug, - admin_verbs_possess, - admin_verbs_permissions, - /client/proc/stealth, - admin_verbs_rejuv, - admin_verbs_sounds, - admin_verbs_spawn, - admin_verbs_mod, - /*Debug verbs added by "show debug verbs"*/ - /client/proc/Cell, - /client/proc/pdiff, - /client/proc/do_not_use_these, - /client/proc/camera_view, - /client/proc/sec_camera_report, - /client/proc/intercom_view, - /client/proc/air_status, - /client/proc/atmosscan, - /client/proc/powerdebug, - /client/proc/count_objects_on_z_level, - /client/proc/count_objects_all, - /client/proc/cmd_assume_direct_control, - /client/proc/jump_to_dead_group, - /client/proc/startSinglo, - /client/proc/cheat_power, - /client/proc/setup_atmos, - /client/proc/ticklag, - /client/proc/cmd_admin_grantfullaccess, - /client/proc/kaboom, - /client/proc/splash, - /client/proc/cmd_admin_areatest, - /client/proc/readmin, - /client/proc/nanomapgen_DumpImage, - /client/proc/nanomapgen_DumpImageAll - ) - -/client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs - set name = "Adminverbs - Hide Most" - set category = "Admin" - verbs.Remove(/client/proc/hide_most_verbs, admin_verbs_hideable) - verbs += /client/proc/show_verbs - - to_chat(src, "Most of your adminverbs have been hidden.") - feedback_add_details("admin_verb","HMV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/hide_verbs() - set name = "Adminverbs - Hide All" - set category = "Admin" - remove_admin_verbs() - verbs += /client/proc/show_verbs - to_chat(src, "Almost all of your adminverbs have been hidden.") - feedback_add_details("admin_verb","TAVVH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/show_verbs() - set name = "Adminverbs - Show" - set category = "Admin" - - verbs -= /client/proc/show_verbs - add_admin_verbs() - to_chat(src, "All of your adminverbs are now visible.") - feedback_add_details("admin_verb","TAVVS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - - - -/client/proc/admin_ghost() - set category = "Admin" - set name = "Aghost" - if(!holder) return - if(istype(mob,/mob/dead/observer)) - //re-enter - var/mob/dead/observer/ghost = mob - ghost.can_reenter_corpse = 1 //just in-case. - ghost.reenter_corpse() - feedback_add_details("admin_verb","P") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else if(istype(mob,/mob/new_player)) - to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.") - else - //ghostize - var/mob/body = mob - if(body.mind) body.mind.isScrying = 1 - body.ghostize(1) - - if(body && !body.key) - body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus - feedback_add_details("admin_verb","O") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/invisimin() - set name = "Invisimin" - set category = "Admin" - set desc = "Toggles ghost-like invisibility (Don't abuse this)" - if(holder && mob) - if(mob.invisibility == INVISIBILITY_OBSERVER) - mob.invisibility = initial(mob.invisibility) - to_chat(mob, "Invisimin off. Invisibility reset.") - mob.icon_state = "ghost" - mob.icon = 'icons/mob/human.dmi' - mob.update_icons() - else - mob.invisibility = INVISIBILITY_OBSERVER - to_chat(mob, "Invisimin on. You are now as invisible as a ghost.") - mob.icon_state = "ghost" - mob.icon = 'icons/mob/mob.dmi' - - -/client/proc/player_panel() - set name = "Player Panel" - set category = "Admin" - if(holder) - holder.player_panel_old() - feedback_add_details("admin_verb","PP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/player_panel_new() - set name = "Player Panel New" - set category = "Admin" - if(holder) - holder.player_panel_new() - feedback_add_details("admin_verb","PPN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/check_antagonists() - set name = "Check Antagonists" - set category = "Admin" - if(holder) - holder.check_antagonists() - log_admin("[key_name(usr)] checked antagonists.") //for tsar~ - feedback_add_details("admin_verb","CHA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/jobbans() - set name = "Display Job bans" - set category = "Admin" - if(holder) - if(config.ban_legacy_system) - holder.Jobbans() - else - holder.DB_ban_panel() - feedback_add_details("admin_verb","VJB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/unban_panel() - set name = "Unban Panel" - set category = "Admin" - if(holder) - if(config.ban_legacy_system) - holder.unbanpanel() - else - holder.DB_ban_panel() - feedback_add_details("admin_verb","UBP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/game_panel() - set name = "Game Panel" - set category = "Admin" - if(holder) - holder.Game() - feedback_add_details("admin_verb","GP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/secrets() - set name = "Secrets" - set category = "Admin" - if (holder) - holder.Secrets() - feedback_add_details("admin_verb","S") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/colorooc() - set category = "Fun" - set name = "OOC Text Color" - if(!holder) return - var/new_ooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null - if(new_ooccolor) - prefs.ooccolor = new_ooccolor - prefs.save_preferences_sqlite(src, ckey) - feedback_add_details("admin_verb","OC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/stealth() - set category = "Admin" - set name = "Stealth Mode" - if(holder) - if(holder.fakekey) - holder.fakekey = null - else - var/new_key = ckeyEx(input("Enter your desired display name.", "Fake Key", key) as text|null) - if(!new_key) return - if(length(new_key) >= 26) - new_key = copytext(new_key, 1, 26) - holder.fakekey = new_key - log_admin("[key_name(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]") - message_admins("[key_name_admin(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]", 1) - feedback_add_details("admin_verb","SM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -#define MAX_WARNS 3 -#define AUTOBANTIME 90 - -/client/proc/warn(warned_ckey) - var/reason = "Autobanning due to too many formal warnings" - if(!check_rights(R_ADMIN)) return - - if(!warned_ckey || !istext(warned_ckey)) return - - - var/datum/preferences/D - var/client/C = directory[warned_ckey] - if(C) D = C.prefs - else D = preferences_datums[warned_ckey] - - if(!D) - to_chat(src, "Error: warn(): No such ckey found.") - return - - var/warn_reason = input("Reason for warning?", "Admin abuuuuuuuse") as null|text - if(!warn_reason) - return - notes_add(warned_ckey,warn_reason,src.mob) - if(++D.warns >= MAX_WARNS) //uh ohhhh...you'reee iiiiin trouuuubble O:) - var/bantime = AUTOBANTIME//= (++D.warnbans * AUTOBANTIME) - D.warns = 0 - ++D.warnbans - for(var/i = 1; i < D.warnbans; i++) - bantime *= 2 - ban_unban_log_save("[ckey] warned [warned_ckey] - [warn_reason], resulting in a [bantime] minute autoban.") - if(C) - message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] - [warn_reason], resulting in a [bantime] minute ban.") - to_chat(C, "You have been autobanned due to a warning by [ckey] - Reason: [warn_reason].
    This is a temporary ban, it will be removed in [bantime] minutes.") - else - message_admins("[key_name_admin(src)] has warned [warned_ckey] - [warn_reason], resulting in a [bantime] minute ban.") - AddBan(warned_ckey, D.last_id, "Autobanning due to too many formal warnings - [warn_reason]", ckey, 1, bantime) - holder.DB_ban_record(BANTYPE_TEMP, null, bantime, "[reason] - [warn_reason]", , ,warned_ckey) - feedback_inc("ban_warn",1) - D.save_preferences_sqlite(C, C.ckey) - del(C) - else - if(C) - to_chat(C, "You have been formally warned by an administrator - Reason: [warn_reason].
    Further warnings will result in an autoban.
    ") - message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] - [warn_reason]. They have [MAX_WARNS-D.warns] strikes remaining. And have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") - else - message_admins("[key_name_admin(src)] has warned [warned_ckey] (DC) - [warn_reason]. They have [MAX_WARNS-D.warns] strikes remaining. And have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") - D.save_preferences_sqlite(C, C.ckey) - feedback_add_details("admin_verb","WARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/unwarn(warned_ckey) - if(!check_rights(R_ADMIN)) return - - if(!warned_ckey || !istext(warned_ckey)) return - /*if(warned_ckey in admin_datums) - to_chat(usr, "Error: warn(): You can't warn admins.") - return*/ - - var/datum/preferences/D - var/client/C = directory[warned_ckey] - if(C) D = C.prefs - else D = preferences_datums[warned_ckey] - - if(!D) - to_chat(src, "Error: unwarn(): No such ckey found.") - return - - if(D.warns == 0) - to_chat(src, "Error: unwarn(): You can't unwarn someone with 0 warnings, you big dummy.") - return - - D.warns-=1 - var/strikesleft = MAX_WARNS-D.warns - if(C) - to_chat(C, "One of your warnings has been removed.
    You currently have [strikesleft] strike\s left
    ") - message_admins("[key_name_admin(src)] has unwarned [key_name_admin(C)]. They have [strikesleft] strike(s) remaining, and have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") - else - message_admins("[key_name_admin(src)] has unwarned [warned_ckey] (DC). They have [strikesleft] strike(s) remaining, and have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") - D.save_preferences_sqlite(C, C.ckey) - feedback_add_details("admin_verb","UNWARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -#undef MAX_WARNS -#undef AUTOBANTIME - -/client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE - set category = "Special Verbs" - set name = "Drop Bomb" - set desc = "Cause an explosion of varying strength at your location." - - var/turf/epicenter = mob.loc - var/list/choices = list("Small Bomb (1,2,3)", "Medium Bomb (2,3,4)", "Big Bomb (3,5,7)", "Custom Bomb") - var/choice = input("What size explosion would you like to produce?") in choices - switch(choice) - if(null) - return 0 - if("Small Bomb (1,2,3)") - explosion(epicenter, 1, 2, 3, 3) - if("Medium Bomb (2,3,4)") - explosion(epicenter, 2, 3, 4, 4) - if("Big Bomb (3,5,7)") - explosion(epicenter, 3, 5, 7, 5) - if("Custom Bomb") - var/devastation_range = input("Devastation range (in tiles):") as num - var/heavy_impact_range = input("Heavy impact range (in tiles):") as num - var/light_impact_range = input("Light impact range (in tiles):") as num - var/flash_range = input("Flash range (in tiles):") as num - explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range) - log_admin("[key_name(usr)] creating an admin explosion at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]).") - message_admins("[key_name_admin(src)] creating an admin explosion at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP).") - feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/drop_emp() - set category = "Special Verbs" - set name = "Drop EMP" - set desc = "Cause an EMP of varying strength at your location." - - var/turf/epicenter = mob.loc - var/list/choices = list("Small EMP (1,2)", "Medium EMP (2,4)", "Big EMP (4,8)", "Custom EMP") - var/choice = input("What size EMP would you like to produce?") in choices - switch(choice) - if(null) - return 0 - if("Small EMP (1,2)") - empulse(epicenter, 1, 2) - if("Medium EMP (2,4)") - empulse(epicenter, 2, 4) - if("Big EMP (4,8)") - empulse(epicenter, 4, 8) - if("Custom EMP") - var/heavy_impact_range = input("Heavy impact range (in tiles):") as num - var/light_impact_range = input("Light impact range (in tiles):") as num - empulse(epicenter, heavy_impact_range, light_impact_range) - log_admin("[key_name(usr)] creating an admin EMP at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]).") - message_admins("[key_name_admin(src)] creating an admin EMP at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP).") - feedback_add_details("admin_verb","DE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/give_spell(mob/T as mob in mob_list) // -- Urist - set category = "Fun" - set name = "Give Spell" - set desc = "Gives a spell to a mob." - - var/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells - if(!S) return - T.add_spell(new S) - 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("[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 - if(!D) return - T.contract_disease(new D, 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("[key_name_admin(usr)] gave [key_name(T)] the disease [D].", 1) - -/client/proc/make_sound(var/obj/O in world) // -- TLE - set category = "Special Verbs" - set name = "Make Sound" - set desc = "Display a message to everyone who can hear the target" - if(istype(O)) - var/message = input("What do you want the message to be?", "Make Sound") as text|null - if(!message) - return - var/mob/living/M - var/olduniv - if(ismob(O)) - M = O - olduniv = M.universal_speak - M.universal_speak = 1 - O.say(message) - if(M) - M.universal_speak = olduniv - log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound") - message_admins("[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound", 1) - feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/togglebuildmodeself() - set name = "Toggle Build Mode Self" - set category = "Special Verbs" - if(src.mob) - togglebuildmode(src.mob) - feedback_add_details("admin_verb","TBMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/object_talk(var/obj/O in world) // -- TLE - set category = "Special Verbs" - set name = "OSay" - set desc = "Make an object say something" - var/message = input(usr, "What do you want the message to be?", "Make Sound") as text | null - if(!message) - return - var/mob/living/M - var/olduniv - if(ismob(O)) - M = O - olduniv = M.universal_speak - M.universal_speak = 1 - O.say(message) - if(M) - M.universal_speak = olduniv - log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z] say \"[message]\"") - message_admins("[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. say \"[message]\"", 1) - feedback_add_details("admin_verb","OT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/kill_air() // -- TLE - set category = "Debug" - set name = "Kill Air" - set desc = "Toggle Air Processing" - if(air_processing_killed) - air_processing_killed = 0 - to_chat(usr, "Enabled air processing.") - else - air_processing_killed = 1 - to_chat(usr, "Disabled air processing.") - feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] used 'kill air'.") - message_admins("[key_name_admin(usr)] used 'kill air'.", 1) - -/client/proc/deadmin_self() - set name = "De-admin self" - set category = "Admin" - - if(holder) - if(alert("Are you sure you want to deadmin?","Deadmin","Yes","No")=="No") - return - log_admin("[src] deadminned themself.") - message_admins("[src] deadminned themself.") - deadmin() - verbs += /client/proc/readmin - deadmins += ckey - to_chat(src, "You are now a normal player.") - feedback_add_details("admin_verb","DAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/toggle_log_hrefs() - set name = "Toggle href logging" - set category = "Server" - if(!holder) return - if(config) - if(config.log_hrefs) - config.log_hrefs = 0 - to_chat(src, "Stopped logging hrefs") - else - config.log_hrefs = 1 - to_chat(src, "Started logging hrefs") - -/client/proc/check_ai_laws() - set name = "Check AI Laws" - set category = "Admin" - if(holder) - src.holder.output_ai_laws() - - -//---- bs12 verbs ---- - -/client/proc/mod_panel() - set name = "Moderator Panel" - set category = "Admin" - -/* if(holder) - holder.mod_panel()*/ -// feedback_add_details("admin_verb","MP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/client/proc/editappear(mob/living/carbon/human/M as mob in mob_list) - set name = "Edit Appearance" - set category = "Fun" - - if(!check_rights(R_FUN)) return - - if(!istype(M, /mob/living/carbon/human)) - to_chat(usr, "You can only do this to humans!") - return - switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Vox and Tajaran can result in unintended consequences.",,"Yes","No")) - if("No") - return - var/new_facial = input("Please select facial hair color.", "Character Generation") as color - if(new_facial) - M.r_facial = hex2num(copytext(new_facial, 2, 4)) - M.g_facial = hex2num(copytext(new_facial, 4, 6)) - M.b_facial = hex2num(copytext(new_facial, 6, 8)) - - var/new_hair = input("Please select hair color.", "Character Generation") as color - if(new_facial) - M.r_hair = hex2num(copytext(new_hair, 2, 4)) - M.g_hair = hex2num(copytext(new_hair, 4, 6)) - M.b_hair = hex2num(copytext(new_hair, 6, 8)) - - var/new_eyes = input("Please select eye color.", "Character Generation") as color - if(new_eyes) - M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) - M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) - M.b_eyes = hex2num(copytext(new_eyes, 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) - M.s_tone = max(min(round(text2num(new_tone)), 220), 1) - M.s_tone = -M.s_tone + 35 - - // hair - var/new_hstyle = input(usr, "Select a hair style", "Grooming") as null|anything in hair_styles_list - if(new_hstyle) - M.h_style = new_hstyle - - // facial hair - var/new_fstyle = input(usr, "Select a facial hair style", "Grooming") as null|anything in facial_hair_styles_list - if(new_fstyle) - M.f_style = new_fstyle - - var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") - if (new_gender) - if(new_gender == "Male") - M.setGender(MALE) - else - M.setGender(FEMALE) - M.update_hair() - M.update_body() - M.check_dna(M) - -/client/proc/playernotes() - set name = "Show Player Info" - set category = "Admin" - if(holder) - holder.PlayerNotes() - return - -/client/proc/free_slot() - set name = "Free Job Slot" - set category = "Admin" - if(holder) - var/list/jobs = list() - for (var/datum/job/J in job_master.occupations) - if (J.current_positions >= J.total_positions && J.total_positions != -1) - jobs += J.title - if (!jobs.len) - to_chat(usr, "There are no fully staffed jobs.") - return - var/job = input("Please select job slot to free", "Free job slot") as null|anything in jobs - if (job) - job_master.FreeRole(job) - return - -/client/proc/toggleattacklogs() - set name = "Toggle Attack Log Messages" - set category = "Preferences" - - prefs.toggles ^= CHAT_ATTACKLOGS - prefs.save_preferences_sqlite(src, ckey) - if (prefs.toggles & CHAT_ATTACKLOGS) - to_chat(usr, "You now will get attack log messages") - else - to_chat(usr, "You now won't get attack log messages") - -/client/proc/commandname() - set name = "Set Command Name" - set category = "Fun" - - var/text = input(usr,"Please select a new Central Command name.", null)as text|null - if(text) - change_command_name(text) - -/client/proc/toggledebuglogs() - set name = "Toggle Debug Log Messages" - set category = "Preferences" - - prefs.toggles ^= CHAT_DEBUGLOGS - prefs.save_preferences_sqlite(src, ckey) - if (prefs.toggles & CHAT_DEBUGLOGS) - to_chat(usr, "You now will get debug log messages") - else - to_chat(usr, "You now won't get debug log messages") - - -/client/proc/man_up(mob/T as mob in mob_list) - set category = "Fun" - set name = "Man Up" - set desc = "Tells mob to man up and deal with it." - - to_chat(T, "Man up and deal with it.") - to_chat(T, "Move on.") - - log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.") - message_admins("[key_name_admin(usr)] told [key_name(T)] to man up and deal with it.", 1) - -/client/proc/global_man_up() - set category = "Fun" - set name = "Man Up Global" - set desc = "Tells everyone to man up and deal with it." - - for (var/mob/T as mob in mob_list) - to_chat(T, "
    Man up.
    Deal with it.

    Move on.

    ") - to_chat(T, 'sound/voice/ManUp1.ogg') - - log_admin("[key_name(usr)] told everyone to man up and deal with it.") - message_admins("[key_name_admin(usr)] told everyone to man up and deal with it.", 1) - - -/client/proc/readmin() - set name = "Re-admin self" - set category = "Admin" - set desc = "Regain your admin powers." - var/datum/admins/D = admin_datums[ckey] - if(config.admin_legacy_system) - to_chat(src, "Legacy admins is not supported yet") - return - else - if(!dbcon.IsConnected()) - message_admins("Warning, mysql database is not connected.") - to_chat(src, "Warning, mysql database is not connected.") - return - if(D) - to_chat(src, "You are already an admin.") - verbs -= /client/proc/readmin - return - var/sql_ckey = sanitizeSQL(ckey(ckey)) - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin WHERE ckey = '[sql_ckey]'") - query.Execute() - while(query.NextRow()) - var/dckey = query.item[1] - var/rank = query.item[2] - if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes. - - var/rights = query.item[4] - if(istext(rights)) rights = text2num(rights) - D = new /datum/admins(rank, rights, dckey) - - //find the client for a ckey if they are connected and associate them with the new admin datum - D.associate(src) - message_admins("[src] re-adminned themselves.") - log_admin("[src] re-adminned themselves.") - feedback_add_details("admin_verb","RAS") - verbs -= /client/proc/readmin - return - -/client/proc/achievement() - set name = "Give Achievement" - set category = "Fun" - - if(!check_rights(R_FUN)) return - - var/achoice = "Cancel" - - if(!player_list.len) - to_chat(usr, "player list is empty!") - return - - var/mob/winner = input("Who's a winner?", "Achievement Winner", null) as null|anything in player_list - if(!winner) return - - var/name = input("What will you call your achievement?", "Achievement Winner", "New Achievement", null) as null|text - if(!name) return - - var/desc = input("What description will you give it?", "Achievement Description", "You Win", null) as null|text - if(!desc) return - - if(istype(winner, /mob/living)) - achoice = alert("Give our winner his own trophy?","Achievement Trophy", "Confirm", "Cancel") - if(achoice == "Cancel") return - - var/glob = alert("Announce the achievement globally? (Beware! Ruins immersion!)", "Last Question", "No!","Yes!") - - if(achoice == "Confirm") - var/obj/item/weapon/reagent_containers/food/drinks/golden_cup/C = new(get_turf(winner)) - C.name = name - C.desc = desc - if(iscarbon(winner) && (winner.stat == CONSCIOUS)) - winner.put_in_hands(C) - else - to_chat(winner, "You win [name]! [desc]") - - var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") - - if(glob == "No!") - to_chat(winner.client, sound('sound/misc/achievement.ogg')) - for(var/mob/dead/observer/O in player_list) - to_chat(O, "\icon[cup] [winner.name] wins \"[name]\"!") - else - to_chat(world, sound('sound/misc/achievement.ogg')) - to_chat(world, "\icon[cup] [winner.name] wins \"[name]\"!") - - to_chat(winner, "Congratulations!") - - achievements += "[winner.key] as [winner.name] won \"[name]\"! \"[desc]\"" - - message_admins("[key_name_admin(usr)] has awarded [winner.key]([winner.name]) with the achievement \"[name]\"! \"[desc]\".", 1) - -/client/proc/mommi_static() - set name = "Toggle MoMMI Static" - set desc = "Toggle whether MoMMIs can see mobs or if the mobs are cloaked in static" - set category = "Fun" - - if(!holder || !config) - return - - config.mommi_static = !config.mommi_static - log_admin("[key_name(src)] turned MoMMI static [config.mommi_static ? "on" : "off"].") - message_admins("[key_name(src)] turned MoMMI static [config.mommi_static ? "on" : "off"].") - for(var/mob/living/silicon/robot/mommi/M in player_list) - if(M.can_see_static()) - M.add_static_overlays() - else - M.remove_static_overlays() - -/client/proc/shuttle_magic() - set name = "Shuttle Magic" - set desc = "Open a menu with magic" - set category = "Admin" - - if(!holder || !config) - return - - holder.shuttle_magic() - - -/datum/admins/proc/media_stop_all() - set name = "Stop All Media" - set desc = "Stops all music and video." - set category = "Fun" - - if(!check_rights(R_FUN)) - return - - message_admins("[key_name_admin(usr)] has stopped all media.", 1) - - stop_all_media() - -/client/proc/SendCentcommFax() - set category = "Fun" - set name = "Send Fax" - set desc = "Sends a fax to all fax machines." - - var/sent = input(src, "Please enter a message send via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
    for line breaks.", "Outgoing message from Centcomm", "") as message|null - if(!sent) return - - var/sentname = input(src, "Pick a title for the report", "Title") as text|null - - SendFax(sent, sentname, centcomm = 1) - - log_admin("[key_name(src)] sent a fax to all machines.: [sent]") +//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless +var/list/admin_verbs_default = list( + /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ + /client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/ + /client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/ + /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*/ + /datum/admins/proc/checkCID, + /datum/admins/proc/checkCKEY +// /client/proc/deadchat /*toggles deadchat on/off*/ + ) +var/list/admin_verbs_admin = list( + /client/proc/set_base_turf, + /datum/admins/proc/delay, + /client/proc/SendCentcommFax, /*sends a fax to all fax machines*/ + /client/proc/player_panel, /*shows an interface for all players, with links to various panels (old style)*/ + /client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/ + /client/proc/invisimin, /*allows our mob to go invisible/visible*/ +// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage + /datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/ + /datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/ + /datum/admins/proc/announce, /*priority announce something to all clients.*/ + /client/proc/colorooc, /*allows us to set a custom colour for everythign we say in ooc*/ + /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ + /client/proc/toggle_view_range, /*changes how far we can see*/ + /datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/ + /datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/ + /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ + /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ + /client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/ + /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ + /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ + /datum/admins/proc/access_news_network, /*allows access of newscasters*/ + /client/proc/giveruntimelog, /*allows us to give access to runtime logs to somebody*/ + /client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/ + /client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/ + /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/ + /client/proc/Getmob, /*teleports a mob to our location*/ + /client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/ +// /client/proc/sendmob, /*sends a mob somewhere*/ -Removed due to it needing two sorting procs to work, which were executed every time an admin right-clicked. ~Errorage + /client/proc/Jump, + /client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/ + /client/proc/jumptomob, /*allows us to jump to a specific mob*/ + /client/proc/jumptoturf, /*allows us to jump to a specific turf*/ + /client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/ + /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/ + /client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/ + /client/proc/cmd_admin_local_narrate, /*send text locally to all players in view, similar to direct narrate*/ + /client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/ + /client/proc/cmd_admin_create_centcom_report, + /client/proc/check_words, /*displays cult-words*/ + /client/proc/check_ai_laws, /*shows AI and borg laws*/ + /client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/ + /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/ + /client/proc/toggleprayers, /*toggles prayers on/off*/ +// /client/proc/toggle_hear_deadcast, /*toggles whether we hear deadchat*/ + /client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/ + /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/ + /client/proc/secrets, + /client/proc/shuttle_magic, + /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ + /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/ + /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ + /client/proc/cmd_admin_say, /*admin-only ooc chat*/ + /datum/admins/proc/PlayerNotes, + /client/proc/cmd_mod_say, + /client/proc/cmd_mod_window, + /datum/admins/proc/show_player_info, + /client/proc/free_slot, /*frees slot for chosen job*/ + /client/proc/cmd_admin_change_custom_event, + /client/proc/cmd_admin_rejuvenate, + /client/proc/toggleattacklogs, + /client/proc/toggledebuglogs, + /client/proc/check_customitem_activity, + // /client/proc/man_up, + // /client/proc/global_man_up, + /client/proc/response_team, // Response Teams admin verb + /client/proc/toggle_antagHUD_use, + /client/proc/toggle_antagHUD_restrictions, + /client/proc/allow_character_respawn /* Allows a ghost to respawn */ +) +var/list/admin_verbs_ban = list( + /client/proc/unban_panel, + /client/proc/jobbans, + /client/proc/unjobban_panel + // /client/proc/DB_ban_panel + ) +var/list/admin_verbs_sounds = list( + /client/proc/play_local_sound, + /client/proc/play_sound + ) +var/list/admin_verbs_fun = list( + /datum/admins/proc/media_stop_all, + /client/proc/object_talk, + /client/proc/cmd_admin_dress, + /client/proc/cmd_admin_gib_self, + /client/proc/drop_bomb, + /client/proc/drop_emp, + /client/proc/cinematic, + /client/proc/one_click_antag, + /client/proc/antag_madness, + /datum/admins/proc/toggle_aliens, + // FUUUUCKED /client/proc/zombie_event, // ZOMBB-B-BIES + /client/proc/cmd_admin_add_freeform_ai_law, + /client/proc/cmd_admin_add_random_ai_law, + /client/proc/make_sound, + /client/proc/toggle_random_events, + /client/proc/set_ooc, + /client/proc/editappear, + /client/proc/commandname, + /client/proc/delete_all_adminbus, + /client/proc/delete_all_bomberman, + /client/proc/create_bomberman_arena, + /client/proc/control_bomberman_arena, + /client/proc/gib_money, // /vg/ + /client/proc/smissmas, + /client/proc/achievement, + /client/proc/mommi_static, + /client/proc/makepAI + ) +var/list/admin_verbs_spawn = list( + /datum/admins/proc/spawn_atom, /* Allows us to spawn instances. */ + /client/proc/spawn_datum, /* Allows us to spawn datums to the marked datum buffer. */ + /client/proc/respawn_character + ) +var/list/admin_verbs_server = list( + /client/proc/Set_Holiday, + /client/proc/ToRban, + /datum/admins/proc/startnow, + /datum/admins/proc/restart, + /datum/admins/proc/toggleaban, + /client/proc/toggle_log_hrefs, + /datum/admins/proc/immreboot, + /client/proc/everyone_random, + /datum/admins/proc/toggleAI, + /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ + /client/proc/cmd_debug_del_all, + /datum/admins/proc/adrev, + /datum/admins/proc/adspawn, + /datum/admins/proc/adjump, + /datum/admins/proc/toggle_aliens, + /client/proc/toggle_random_events, + /client/proc/check_customitem_activity, + /client/proc/dump_chemreactions, + ) +var/list/admin_verbs_debug = list( + /client/proc/gc_dump_hdl, + /client/proc/getSchedulerContext, + /client/proc/cmd_admin_list_open_jobs, + /proc/getbrokeninhands, + /client/proc/Debug2, + /client/proc/kill_air, + /client/proc/cmd_debug_make_powernets, + /client/proc/kill_airgroup, + /client/proc/debug_controller, + /client/proc/cmd_debug_mob_lists, + /client/proc/cmd_admin_delete, + /client/proc/cmd_debug_del_all, + /client/proc/cmd_debug_tog_aliens, + /client/proc/air_report, + /client/proc/reload_admins, + /client/proc/restart_controller, + /client/proc/enable_debug_verbs, + /client/proc/callproc, + /client/proc/toggledebuglogs, + /client/proc/qdel_toggle, // /vg/ + /client/proc/cmd_admin_dump_instances, // /vg/ + /client/proc/cmd_admin_dump_machine_type_list, // /vg/ + /client/proc/disable_bloodvirii, // /vg + /client/proc/handle_paperwork, //this is completely experimental + /client/proc/reload_style_sheet, + /client/proc/reset_style_sheet, + /client/proc/test_movable_UI, + /client/proc/test_snap_UI, + /client/proc/configFood, + /client/proc/debug_reagents, + /client/proc/make_invulnerable, + /client/proc/cmd_admin_dump_delprofile, + /client/proc/mob_list, + /client/proc/cure_disease, + /client/proc/check_bomb, + /client/proc/set_teleport_pref, + /client/proc/check_convertables, + /client/proc/check_spiral, + /client/proc/cmd_admin_find_bad_blood_tracks, +#ifdef PROFILE_MACHINES + /client/proc/cmd_admin_dump_macprofile, +#endif + /client/proc/debugNatureMapGenerator, + /client/proc/callatomproc + ) +var/list/admin_verbs_possess = list( + /proc/possess, + /proc/release + ) +var/list/admin_verbs_permissions = list( + /client/proc/edit_admin_permissions + ) +var/list/admin_verbs_rejuv = list( + /client/proc/respawn_character + ) + +//verbs which can be hidden - needs work +var/list/admin_verbs_hideable = list( + /client/proc/set_ooc, + /client/proc/deadmin_self, +// /client/proc/deadchat, + /client/proc/toggleprayers, + /client/proc/toggle_hear_radio, + /datum/admins/proc/show_traitor_panel, + /datum/admins/proc/toggleenter, + /datum/admins/proc/toggleguests, + /datum/admins/proc/announce, + /client/proc/colorooc, + /client/proc/admin_ghost, + /client/proc/toggle_view_range, + /datum/admins/proc/view_txt_log, + /datum/admins/proc/view_atk_log, + /client/proc/cmd_admin_subtle_message, + /client/proc/cmd_admin_check_contents, + /datum/admins/proc/access_news_network, + /client/proc/admin_call_shuttle, + /client/proc/admin_cancel_shuttle, + /client/proc/cmd_admin_direct_narrate, + /client/proc/cmd_admin_world_narrate, + /client/proc/check_words, + /client/proc/play_local_sound, + /client/proc/play_sound, + /client/proc/object_talk, + /client/proc/cmd_admin_dress, + /client/proc/cmd_admin_gib_self, + /client/proc/drop_bomb, + /client/proc/drop_emp, + /client/proc/cinematic, + /datum/admins/proc/toggle_aliens, + /client/proc/cmd_admin_add_freeform_ai_law, + /client/proc/cmd_admin_add_random_ai_law, + /client/proc/cmd_admin_create_centcom_report, + /client/proc/make_sound, + /client/proc/toggle_random_events, + /client/proc/cmd_admin_add_random_ai_law, + /client/proc/Set_Holiday, + /client/proc/ToRban, + /datum/admins/proc/startnow, + /datum/admins/proc/restart, + /datum/admins/proc/delay, + /datum/admins/proc/toggleaban, + /client/proc/toggle_log_hrefs, + /datum/admins/proc/immreboot, + /client/proc/everyone_random, + /client/proc/shuttle_magic, + /datum/admins/proc/toggleAI, + /datum/admins/proc/adrev, + /datum/admins/proc/adspawn, + /datum/admins/proc/adjump, + /client/proc/restart_controller, + /client/proc/cmd_admin_list_open_jobs, + /client/proc/callproc, + /client/proc/Debug2, + /client/proc/reload_admins, + /client/proc/kill_air, + /client/proc/cmd_debug_make_powernets, + /client/proc/kill_airgroup, + /client/proc/debug_controller, + /client/proc/startSinglo, + /client/proc/cheat_power, + /client/proc/setup_atmos, + /client/proc/cmd_debug_mob_lists, + /client/proc/cmd_debug_del_all, + /client/proc/cmd_debug_tog_aliens, + /client/proc/air_report, + /client/proc/enable_debug_verbs, + /client/proc/mob_list, + /proc/possess, + /proc/release, + /client/proc/gc_dump_hdl + ) +var/list/admin_verbs_mod = list( + /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ + /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ + /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game.*/ + /client/proc/toggledebuglogs, + /datum/admins/proc/PlayerNotes, + /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ + /client/proc/cmd_mod_say, + /client/proc/cmd_mod_window, + /datum/admins/proc/show_player_info, + /client/proc/player_panel_new, + /client/proc/vv_marked_datum, + /datum/admins/proc/view_mob_attack_log /* Allow you to view attack logs since doing it in VV sucks */ +) +/client/proc/add_admin_verbs() + if(holder) + verbs += admin_verbs_default + if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself + if(holder.rights & R_ADMIN) verbs += admin_verbs_admin + if(holder.rights & R_BAN) verbs += admin_verbs_ban + if(holder.rights & R_FUN) verbs += admin_verbs_fun + if(holder.rights & R_SERVER) verbs += admin_verbs_server + if(holder.rights & R_DEBUG) verbs += admin_verbs_debug + if(holder.rights & R_POSSESS) verbs += admin_verbs_possess + if(holder.rights & R_PERMISSIONS) verbs += admin_verbs_permissions + if(holder.rights & R_STEALTH) verbs += /client/proc/stealth + if(holder.rights & R_REJUVINATE) verbs += admin_verbs_rejuv + if(holder.rights & R_SOUNDS) verbs += admin_verbs_sounds + if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn + if(holder.rights & R_MOD) verbs += admin_verbs_mod + if(holder.rights & R_ADMINBUS) verbs += /client/proc/secrets + +/client/proc/remove_admin_verbs() + verbs.Remove( + admin_verbs_default, + /client/proc/togglebuildmodeself, + admin_verbs_admin, + admin_verbs_ban, + admin_verbs_fun, + admin_verbs_server, + admin_verbs_debug, + admin_verbs_possess, + admin_verbs_permissions, + /client/proc/stealth, + admin_verbs_rejuv, + admin_verbs_sounds, + admin_verbs_spawn, + admin_verbs_mod, + /*Debug verbs added by "show debug verbs"*/ + /client/proc/Cell, + /client/proc/pdiff, + /client/proc/do_not_use_these, + /client/proc/camera_view, + /client/proc/sec_camera_report, + /client/proc/intercom_view, + /client/proc/air_status, + /client/proc/atmosscan, + /client/proc/powerdebug, + /client/proc/count_objects_on_z_level, + /client/proc/count_objects_all, + /client/proc/cmd_assume_direct_control, + /client/proc/jump_to_dead_group, + /client/proc/startSinglo, + /client/proc/cheat_power, + /client/proc/setup_atmos, + /client/proc/ticklag, + /client/proc/cmd_admin_grantfullaccess, + /client/proc/kaboom, + /client/proc/splash, + /client/proc/cmd_admin_areatest, + /client/proc/readmin, + /client/proc/nanomapgen_DumpImage, + /client/proc/nanomapgen_DumpImageAll + ) + +/client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs + set name = "Adminverbs - Hide Most" + set category = "Admin" + verbs.Remove(/client/proc/hide_most_verbs, admin_verbs_hideable) + verbs += /client/proc/show_verbs + + to_chat(src, "Most of your adminverbs have been hidden.") + feedback_add_details("admin_verb","HMV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/hide_verbs() + set name = "Adminverbs - Hide All" + set category = "Admin" + remove_admin_verbs() + verbs += /client/proc/show_verbs + to_chat(src, "Almost all of your adminverbs have been hidden.") + feedback_add_details("admin_verb","TAVVH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/show_verbs() + set name = "Adminverbs - Show" + set category = "Admin" + + verbs -= /client/proc/show_verbs + add_admin_verbs() + to_chat(src, "All of your adminverbs are now visible.") + feedback_add_details("admin_verb","TAVVS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + + + +/client/proc/admin_ghost() + set category = "Admin" + set name = "Aghost" + if(!holder) return + if(istype(mob,/mob/dead/observer)) + //re-enter + var/mob/dead/observer/ghost = mob + ghost.can_reenter_corpse = 1 //just in-case. + ghost.reenter_corpse() + feedback_add_details("admin_verb","P") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else if(istype(mob,/mob/new_player)) + to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.") + else + //ghostize + var/mob/body = mob + if(body.mind) body.mind.isScrying = 1 + body.ghostize(1) + + if(body && !body.key) + body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus + feedback_add_details("admin_verb","O") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/invisimin() + set name = "Invisimin" + set category = "Admin" + set desc = "Toggles ghost-like invisibility (Don't abuse this)" + if(holder && mob) + if(mob.invisibility == INVISIBILITY_OBSERVER) + mob.invisibility = initial(mob.invisibility) + to_chat(mob, "Invisimin off. Invisibility reset.") + mob.icon_state = "ghost" + mob.icon = 'icons/mob/human.dmi' + mob.update_icons() + else + mob.invisibility = INVISIBILITY_OBSERVER + to_chat(mob, "Invisimin on. You are now as invisible as a ghost.") + mob.icon_state = "ghost" + mob.icon = 'icons/mob/mob.dmi' + + +/client/proc/player_panel() + set name = "Player Panel" + set category = "Admin" + if(holder) + holder.player_panel_old() + feedback_add_details("admin_verb","PP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/player_panel_new() + set name = "Player Panel New" + set category = "Admin" + if(holder) + holder.player_panel_new() + feedback_add_details("admin_verb","PPN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/check_antagonists() + set name = "Check Antagonists" + set category = "Admin" + if(holder) + holder.check_antagonists() + log_admin("[key_name(usr)] checked antagonists.") //for tsar~ + feedback_add_details("admin_verb","CHA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/jobbans() + set name = "Display Job bans" + set category = "Admin" + if(holder) + if(config.ban_legacy_system) + holder.Jobbans() + else + holder.DB_ban_panel() + feedback_add_details("admin_verb","VJB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/unban_panel() + set name = "Unban Panel" + set category = "Admin" + if(holder) + if(config.ban_legacy_system) + holder.unbanpanel() + else + holder.DB_ban_panel() + feedback_add_details("admin_verb","UBP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/game_panel() + set name = "Game Panel" + set category = "Admin" + if(holder) + holder.Game() + feedback_add_details("admin_verb","GP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/secrets() + set name = "Secrets" + set category = "Admin" + if (holder) + holder.Secrets() + feedback_add_details("admin_verb","S") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/colorooc() + set category = "Fun" + set name = "OOC Text Color" + if(!holder) return + var/new_ooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null + if(new_ooccolor) + prefs.ooccolor = new_ooccolor + prefs.save_preferences_sqlite(src, ckey) + feedback_add_details("admin_verb","OC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/stealth() + set category = "Admin" + set name = "Stealth Mode" + if(holder) + if(holder.fakekey) + holder.fakekey = null + else + var/new_key = ckeyEx(input("Enter your desired display name.", "Fake Key", key) as text|null) + if(!new_key) return + if(length(new_key) >= 26) + new_key = copytext(new_key, 1, 26) + holder.fakekey = new_key + log_admin("[key_name(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]") + message_admins("[key_name_admin(usr)] has turned stealth mode [holder.fakekey ? "ON" : "OFF"]", 1) + feedback_add_details("admin_verb","SM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +#define MAX_WARNS 3 +#define AUTOBANTIME 90 + +/client/proc/warn(warned_ckey) + var/reason = "Autobanning due to too many formal warnings" + if(!check_rights(R_ADMIN)) return + + if(!warned_ckey || !istext(warned_ckey)) return + + + var/datum/preferences/D + var/client/C = directory[warned_ckey] + if(C) D = C.prefs + else D = preferences_datums[warned_ckey] + + if(!D) + to_chat(src, "Error: warn(): No such ckey found.") + return + + var/warn_reason = input("Reason for warning?", "Admin abuuuuuuuse") as null|text + if(!warn_reason) + return + notes_add(warned_ckey,warn_reason,src.mob) + if(++D.warns >= MAX_WARNS) //uh ohhhh...you'reee iiiiin trouuuubble O:) + var/bantime = AUTOBANTIME//= (++D.warnbans * AUTOBANTIME) + D.warns = 0 + ++D.warnbans + for(var/i = 1; i < D.warnbans; i++) + bantime *= 2 + ban_unban_log_save("[ckey] warned [warned_ckey] - [warn_reason], resulting in a [bantime] minute autoban.") + if(C) + message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] - [warn_reason], resulting in a [bantime] minute ban.") + to_chat(C, "You have been autobanned due to a warning by [ckey] - Reason: [warn_reason].
    This is a temporary ban, it will be removed in [bantime] minutes.") + else + message_admins("[key_name_admin(src)] has warned [warned_ckey] - [warn_reason], resulting in a [bantime] minute ban.") + AddBan(warned_ckey, D.last_id, "Autobanning due to too many formal warnings - [warn_reason]", ckey, 1, bantime) + holder.DB_ban_record(BANTYPE_TEMP, null, bantime, "[reason] - [warn_reason]", , ,warned_ckey) + feedback_inc("ban_warn",1) + D.save_preferences_sqlite(C, C.ckey) + del(C) + else + if(C) + to_chat(C, "You have been formally warned by an administrator - Reason: [warn_reason].
    Further warnings will result in an autoban.") + message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] - [warn_reason]. They have [MAX_WARNS-D.warns] strikes remaining. And have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") + else + message_admins("[key_name_admin(src)] has warned [warned_ckey] (DC) - [warn_reason]. They have [MAX_WARNS-D.warns] strikes remaining. And have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") + D.save_preferences_sqlite(C, C.ckey) + feedback_add_details("admin_verb","WARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/unwarn(warned_ckey) + if(!check_rights(R_ADMIN)) return + + if(!warned_ckey || !istext(warned_ckey)) return + /*if(warned_ckey in admin_datums) + to_chat(usr, "Error: warn(): You can't warn admins.") + return*/ + + var/datum/preferences/D + var/client/C = directory[warned_ckey] + if(C) D = C.prefs + else D = preferences_datums[warned_ckey] + + if(!D) + to_chat(src, "Error: unwarn(): No such ckey found.") + return + + if(D.warns == 0) + to_chat(src, "Error: unwarn(): You can't unwarn someone with 0 warnings, you big dummy.") + return + + D.warns-=1 + var/strikesleft = MAX_WARNS-D.warns + if(C) + to_chat(C, "One of your warnings has been removed.
    You currently have [strikesleft] strike\s left
    ") + message_admins("[key_name_admin(src)] has unwarned [key_name_admin(C)]. They have [strikesleft] strike(s) remaining, and have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") + else + message_admins("[key_name_admin(src)] has unwarned [warned_ckey] (DC). They have [strikesleft] strike(s) remaining, and have been warn banned [D.warnbans] [D.warnbans == 1 ? "time" : "times"]") + D.save_preferences_sqlite(C, C.ckey) + feedback_add_details("admin_verb","UNWARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +#undef MAX_WARNS +#undef AUTOBANTIME + +/client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE + set category = "Special Verbs" + set name = "Drop Bomb" + set desc = "Cause an explosion of varying strength at your location." + + var/turf/epicenter = mob.loc + var/list/choices = list("Small Bomb (1,2,3)", "Medium Bomb (2,3,4)", "Big Bomb (3,5,7)", "Custom Bomb") + var/choice = input("What size explosion would you like to produce?") in choices + switch(choice) + if(null) + return 0 + if("Small Bomb (1,2,3)") + explosion(epicenter, 1, 2, 3, 3) + if("Medium Bomb (2,3,4)") + explosion(epicenter, 2, 3, 4, 4) + if("Big Bomb (3,5,7)") + explosion(epicenter, 3, 5, 7, 5) + if("Custom Bomb") + var/devastation_range = input("Devastation range (in tiles):") as num + var/heavy_impact_range = input("Heavy impact range (in tiles):") as num + var/light_impact_range = input("Light impact range (in tiles):") as num + var/flash_range = input("Flash range (in tiles):") as num + explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range) + log_admin("[key_name(usr)] creating an admin explosion at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]).") + message_admins("[key_name_admin(src)] creating an admin explosion at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP).") + feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/drop_emp() + set category = "Special Verbs" + set name = "Drop EMP" + set desc = "Cause an EMP of varying strength at your location." + + var/turf/epicenter = mob.loc + var/list/choices = list("Small EMP (1,2)", "Medium EMP (2,4)", "Big EMP (4,8)", "Custom EMP") + var/choice = input("What size EMP would you like to produce?") in choices + switch(choice) + if(null) + return 0 + if("Small EMP (1,2)") + empulse(epicenter, 1, 2) + if("Medium EMP (2,4)") + empulse(epicenter, 2, 4) + if("Big EMP (4,8)") + empulse(epicenter, 4, 8) + if("Custom EMP") + var/heavy_impact_range = input("Heavy impact range (in tiles):") as num + var/light_impact_range = input("Light impact range (in tiles):") as num + empulse(epicenter, heavy_impact_range, light_impact_range) + log_admin("[key_name(usr)] creating an admin EMP at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]).") + message_admins("[key_name_admin(src)] creating an admin EMP at [epicenter.loc] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP).") + feedback_add_details("admin_verb","DE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/give_spell(mob/T as mob in mob_list) // -- Urist + set category = "Fun" + set name = "Give Spell" + set desc = "Gives a spell to a mob." + + var/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells + if(!S) return + T.add_spell(new S) + 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("[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 + if(!D) return + T.contract_disease(new D, 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("[key_name_admin(usr)] gave [key_name(T)] the disease [D].", 1) + +/client/proc/make_sound(var/obj/O in world) // -- TLE + set category = "Special Verbs" + set name = "Make Sound" + set desc = "Display a message to everyone who can hear the target" + if(istype(O)) + var/message = input("What do you want the message to be?", "Make Sound") as text|null + if(!message) + return + var/mob/living/M + var/olduniv + if(ismob(O)) + M = O + olduniv = M.universal_speak + M.universal_speak = 1 + O.say(message) + if(M) + M.universal_speak = olduniv + log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound") + message_admins("[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound", 1) + feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/togglebuildmodeself() + set name = "Toggle Build Mode Self" + set category = "Special Verbs" + if(src.mob) + togglebuildmode(src.mob) + feedback_add_details("admin_verb","TBMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/object_talk(var/obj/O in world) // -- TLE + set category = "Special Verbs" + set name = "OSay" + set desc = "Make an object say something" + var/message = input(usr, "What do you want the message to be?", "Make Sound") as text | null + if(!message) + return + var/mob/living/M + var/olduniv + if(ismob(O)) + M = O + olduniv = M.universal_speak + M.universal_speak = 1 + O.say(message) + if(M) + M.universal_speak = olduniv + log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z] say \"[message]\"") + message_admins("[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. say \"[message]\"", 1) + feedback_add_details("admin_verb","OT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/kill_air() // -- TLE + set category = "Debug" + set name = "Kill Air" + set desc = "Toggle Air Processing" + if(air_processing_killed) + air_processing_killed = 0 + to_chat(usr, "Enabled air processing.") + else + air_processing_killed = 1 + to_chat(usr, "Disabled air processing.") + feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] used 'kill air'.") + message_admins("[key_name_admin(usr)] used 'kill air'.", 1) + +/client/proc/deadmin_self() + set name = "De-admin self" + set category = "Admin" + + if(holder) + if(alert("Are you sure you want to deadmin?","Deadmin","Yes","No")=="No") + return + log_admin("[src] deadminned themself.") + message_admins("[src] deadminned themself.") + deadmin() + verbs += /client/proc/readmin + deadmins += ckey + to_chat(src, "You are now a normal player.") + feedback_add_details("admin_verb","DAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/toggle_log_hrefs() + set name = "Toggle href logging" + set category = "Server" + if(!holder) return + if(config) + if(config.log_hrefs) + config.log_hrefs = 0 + to_chat(src, "Stopped logging hrefs") + else + config.log_hrefs = 1 + to_chat(src, "Started logging hrefs") + +/client/proc/check_ai_laws() + set name = "Check AI Laws" + set category = "Admin" + if(holder) + src.holder.output_ai_laws() + + +//---- bs12 verbs ---- + +/client/proc/mod_panel() + set name = "Moderator Panel" + set category = "Admin" + +/* if(holder) + holder.mod_panel()*/ +// feedback_add_details("admin_verb","MP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/client/proc/editappear(mob/living/carbon/human/M as mob in mob_list) + set name = "Edit Appearance" + set category = "Fun" + + if(!check_rights(R_FUN)) return + + if(!istype(M, /mob/living/carbon/human)) + to_chat(usr, "You can only do this to humans!") + return + switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Vox and Tajaran can result in unintended consequences.",,"Yes","No")) + if("No") + return + var/new_facial = input("Please select facial hair color.", "Character Generation") as color + if(new_facial) + M.r_facial = hex2num(copytext(new_facial, 2, 4)) + M.g_facial = hex2num(copytext(new_facial, 4, 6)) + M.b_facial = hex2num(copytext(new_facial, 6, 8)) + + var/new_hair = input("Please select hair color.", "Character Generation") as color + if(new_facial) + M.r_hair = hex2num(copytext(new_hair, 2, 4)) + M.g_hair = hex2num(copytext(new_hair, 4, 6)) + M.b_hair = hex2num(copytext(new_hair, 6, 8)) + + var/new_eyes = input("Please select eye color.", "Character Generation") as color + if(new_eyes) + M.r_eyes = hex2num(copytext(new_eyes, 2, 4)) + M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) + M.b_eyes = hex2num(copytext(new_eyes, 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) + M.s_tone = max(min(round(text2num(new_tone)), 220), 1) + M.s_tone = -M.s_tone + 35 + + // hair + var/new_hstyle = input(usr, "Select a hair style", "Grooming") as null|anything in hair_styles_list + if(new_hstyle) + M.h_style = new_hstyle + + // facial hair + var/new_fstyle = input(usr, "Select a facial hair style", "Grooming") as null|anything in facial_hair_styles_list + if(new_fstyle) + M.f_style = new_fstyle + + var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") + if (new_gender) + if(new_gender == "Male") + M.setGender(MALE) + else + M.setGender(FEMALE) + M.update_hair() + M.update_body() + M.check_dna(M) + +/client/proc/playernotes() + set name = "Show Player Info" + set category = "Admin" + if(holder) + holder.PlayerNotes() + return + +/client/proc/free_slot() + set name = "Free Job Slot" + set category = "Admin" + if(holder) + var/list/jobs = list() + for (var/datum/job/J in job_master.occupations) + if (J.current_positions >= J.total_positions && J.total_positions != -1) + jobs += J.title + if (!jobs.len) + to_chat(usr, "There are no fully staffed jobs.") + return + var/job = input("Please select job slot to free", "Free job slot") as null|anything in jobs + if (job) + job_master.FreeRole(job) + return + +/client/proc/toggleattacklogs() + set name = "Toggle Attack Log Messages" + set category = "Preferences" + + prefs.toggles ^= CHAT_ATTACKLOGS + prefs.save_preferences_sqlite(src, ckey) + if (prefs.toggles & CHAT_ATTACKLOGS) + to_chat(usr, "You now will get attack log messages") + else + to_chat(usr, "You now won't get attack log messages") + +/client/proc/commandname() + set name = "Set Command Name" + set category = "Fun" + + var/text = input(usr,"Please select a new Central Command name.", null)as text|null + if(text) + change_command_name(text) + +/client/proc/toggledebuglogs() + set name = "Toggle Debug Log Messages" + set category = "Preferences" + + prefs.toggles ^= CHAT_DEBUGLOGS + prefs.save_preferences_sqlite(src, ckey) + if (prefs.toggles & CHAT_DEBUGLOGS) + to_chat(usr, "You now will get debug log messages") + else + to_chat(usr, "You now won't get debug log messages") + + +/client/proc/man_up(mob/T as mob in mob_list) + set category = "Fun" + set name = "Man Up" + set desc = "Tells mob to man up and deal with it." + + to_chat(T, "Man up and deal with it.") + to_chat(T, "Move on.") + + log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.") + message_admins("[key_name_admin(usr)] told [key_name(T)] to man up and deal with it.", 1) + +/client/proc/global_man_up() + set category = "Fun" + set name = "Man Up Global" + set desc = "Tells everyone to man up and deal with it." + + for (var/mob/T as mob in mob_list) + to_chat(T, "
    Man up.
    Deal with it.

    Move on.

    ") + to_chat(T, 'sound/voice/ManUp1.ogg') + + log_admin("[key_name(usr)] told everyone to man up and deal with it.") + message_admins("[key_name_admin(usr)] told everyone to man up and deal with it.", 1) + + +/client/proc/readmin() + set name = "Re-admin self" + set category = "Admin" + set desc = "Regain your admin powers." + var/datum/admins/D = admin_datums[ckey] + if(config.admin_legacy_system) + to_chat(src, "Legacy admins is not supported yet") + return + else + if(!dbcon.IsConnected()) + message_admins("Warning, mysql database is not connected.") + to_chat(src, "Warning, mysql database is not connected.") + return + if(D) + to_chat(src, "You are already an admin.") + verbs -= /client/proc/readmin + return + var/sql_ckey = sanitizeSQL(ckey(ckey)) + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin WHERE ckey = '[sql_ckey]'") + query.Execute() + while(query.NextRow()) + var/dckey = query.item[1] + var/rank = query.item[2] + if(rank == "Removed") continue //This person was de-adminned. They are only in the admin list for archive purposes. + + var/rights = query.item[4] + if(istext(rights)) rights = text2num(rights) + D = new /datum/admins(rank, rights, dckey) + + //find the client for a ckey if they are connected and associate them with the new admin datum + D.associate(src) + message_admins("[src] re-adminned themselves.") + log_admin("[src] re-adminned themselves.") + feedback_add_details("admin_verb","RAS") + verbs -= /client/proc/readmin + return + +/client/proc/achievement() + set name = "Give Achievement" + set category = "Fun" + + if(!check_rights(R_FUN)) return + + var/achoice = "Cancel" + + if(!player_list.len) + to_chat(usr, "player list is empty!") + return + + var/mob/winner = input("Who's a winner?", "Achievement Winner", null) as null|anything in player_list + if(!winner) return + + var/name = input("What will you call your achievement?", "Achievement Winner", "New Achievement", null) as null|text + if(!name) return + + var/desc = input("What description will you give it?", "Achievement Description", "You Win", null) as null|text + if(!desc) return + + if(istype(winner, /mob/living)) + achoice = alert("Give our winner his own trophy?","Achievement Trophy", "Confirm", "Cancel") + if(achoice == "Cancel") return + + var/glob = alert("Announce the achievement globally? (Beware! Ruins immersion!)", "Last Question", "No!","Yes!") + + if(achoice == "Confirm") + var/obj/item/weapon/reagent_containers/food/drinks/golden_cup/C = new(get_turf(winner)) + C.name = name + C.desc = desc + if(iscarbon(winner) && (winner.stat == CONSCIOUS)) + winner.put_in_hands(C) + else + to_chat(winner, "You win [name]! [desc]") + + var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") + + if(glob == "No!") + to_chat(winner.client, sound('sound/misc/achievement.ogg')) + for(var/mob/dead/observer/O in player_list) + to_chat(O, "\icon[cup] [winner.name] wins \"[name]\"!") + else + to_chat(world, sound('sound/misc/achievement.ogg')) + to_chat(world, "\icon[cup] [winner.name] wins \"[name]\"!") + + to_chat(winner, "Congratulations!") + + achievements += "[winner.key] as [winner.name] won \"[name]\"! \"[desc]\"" + + message_admins("[key_name_admin(usr)] has awarded [winner.key]([winner.name]) with the achievement \"[name]\"! \"[desc]\".", 1) + +/client/proc/mommi_static() + set name = "Toggle MoMMI Static" + set desc = "Toggle whether MoMMIs can see mobs or if the mobs are cloaked in static" + set category = "Fun" + + if(!holder || !config) + return + + config.mommi_static = !config.mommi_static + log_admin("[key_name(src)] turned MoMMI static [config.mommi_static ? "on" : "off"].") + message_admins("[key_name(src)] turned MoMMI static [config.mommi_static ? "on" : "off"].") + for(var/mob/living/silicon/robot/mommi/M in player_list) + if(M.can_see_static()) + M.add_static_overlays() + else + M.remove_static_overlays() + +/client/proc/shuttle_magic() + set name = "Shuttle Magic" + set desc = "Open a menu with magic" + set category = "Admin" + + if(!holder || !config) + return + + holder.shuttle_magic() + + +/datum/admins/proc/media_stop_all() + set name = "Stop All Media" + set desc = "Stops all music and video." + set category = "Fun" + + if(!check_rights(R_FUN)) + return + + message_admins("[key_name_admin(usr)] has stopped all media.", 1) + + stop_all_media() + +/client/proc/SendCentcommFax() + set category = "Fun" + set name = "Send Fax" + set desc = "Sends a fax to all fax machines." + + var/sent = input(src, "Please enter a message send via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
    for line breaks.", "Outgoing message from Centcomm", "") as message|null + if(!sent) return + + var/sentname = input(src, "Pick a title for the report", "Title") as text|null + + SendFax(sent, sentname, centcomm = 1) + + log_admin("[key_name(src)] sent a fax to all machines.: [sent]") message_admins("[key_name_admin(src)] sent a fax to all machines.", 1) \ No newline at end of file diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index b4f86dcb399..b641b2dc334 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -1,117 +1,117 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -var/jobban_runonce // Updates legacy bans with new info -var/jobban_keylist[0] //to store the keys & ranks - -/proc/jobban_fullban(mob/M, rank, reason) - if (!M || !M.key) return - jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]")) - jobban_savebanfile() - -/proc/jobban_client_fullban(ckey, rank) - if (!ckey || !rank) return - jobban_keylist.Add(text("[ckey] - [rank]")) - jobban_savebanfile() - -//returns a reason if M is banned from rank, returns 0 otherwise -/proc/jobban_isbanned(mob/M, rank) - if(M && rank) - /* - if(_jobban_isbanned(M, rank)) return "Reason Unspecified" //for old jobban - if (guest_jobbans(rank)) - if(config.guest_jobban && IsGuestKey(M.key)) - return "Guest Job-ban" - if(config.usewhitelist && !check_whitelist(M)) - return "Whitelisted Job" - */ - for (var/s in jobban_keylist) - if( findtext(s,"[M.ckey] - [rank]") == 1 ) - var/startpos = findtext(s, "## ")+3 - if(startpos && startpos> jobban_keylist - log_admin("Loading jobban_rank") - S["runonce"] >> jobban_runonce - - if (!length(jobban_keylist)) - jobban_keylist=list() - log_admin("jobban_keylist was empty") - else - if(!establish_db_connection()) - world.log << "Database connection failed. Reverting to the legacy ban system." - diary << "Database connection failed. Reverting to the legacy ban system." - config.ban_legacy_system = 1 - jobban_loadbanfile() - return - - //Job permabans - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)") - query.Execute() - - while(query.NextRow()) - var/ckey = query.item[1] - var/job = query.item[2] - - jobban_keylist.Add("[ckey] - [job]") - - //Job tempbans - var/DBQuery/query1 = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()") - query1.Execute() - - while(query1.NextRow()) - var/ckey = query1.item[1] - var/job = query1.item[2] - - jobban_keylist.Add("[ckey] - [job]") - -/proc/jobban_savebanfile() - var/savefile/S = new("data/job_full.ban") + +/mob/verb/reload_jobbans() + set name = "reload jobbans" + + jobban_loadbanfile() +*/ + +/proc/jobban_loadbanfile() + if(config.ban_legacy_system) + var/savefile/S=new("data/job_full.ban") + S["keys[0]"] >> jobban_keylist + log_admin("Loading jobban_rank") + S["runonce"] >> jobban_runonce + + if (!length(jobban_keylist)) + jobban_keylist=list() + log_admin("jobban_keylist was empty") + else + if(!establish_db_connection()) + world.log << "Database connection failed. Reverting to the legacy ban system." + diary << "Database connection failed. Reverting to the legacy ban system." + config.ban_legacy_system = 1 + jobban_loadbanfile() + return + + //Job permabans + var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)") + query.Execute() + + while(query.NextRow()) + var/ckey = query.item[1] + var/job = query.item[2] + + jobban_keylist.Add("[ckey] - [job]") + + //Job tempbans + var/DBQuery/query1 = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()") + query1.Execute() + + while(query1.NextRow()) + var/ckey = query1.item[1] + var/job = query1.item[2] + + jobban_keylist.Add("[ckey] - [job]") + +/proc/jobban_savebanfile() + var/savefile/S = new("data/job_full.ban") S["keys[0]"] << jobban_keylist - -/proc/jobban_unban(mob/M, rank) - jobban_remove("[M.ckey] - [rank]") - jobban_savebanfile() - - -/proc/ban_unban_log_save(var/formatted_log) - text2file(formatted_log,"data/ban_unban_log.txt") - - -/proc/jobban_updatelegacybans() - if(!jobban_runonce) - log_admin("Updating jobbanfile!") - // Updates bans.. Or fixes them. Either way. - for(var/T in jobban_keylist) - if(!T) continue - jobban_runonce++ //don't run this update again - - -/proc/jobban_remove(X) - for (var/i = 1; i <= length(jobban_keylist); i++) - if( findtext(jobban_keylist[i], "[X]") ) - jobban_keylist.Remove(jobban_keylist[i]) - jobban_savebanfile() - return 1 - return 0 + +/proc/jobban_unban(mob/M, rank) + jobban_remove("[M.ckey] - [rank]") + jobban_savebanfile() + + +/proc/ban_unban_log_save(var/formatted_log) + text2file(formatted_log,"data/ban_unban_log.txt") + + +/proc/jobban_updatelegacybans() + if(!jobban_runonce) + log_admin("Updating jobbanfile!") + // Updates bans.. Or fixes them. Either way. + for(var/T in jobban_keylist) + if(!T) continue + jobban_runonce++ //don't run this update again + + +/proc/jobban_remove(X) + for (var/i = 1; i <= length(jobban_keylist); i++) + if( findtext(jobban_keylist[i], "[X]") ) + jobban_keylist.Remove(jobban_keylist[i]) + jobban_savebanfile() + return 1 + return 0 diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 3f022d6675d..153cd581383 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -1,9 +1,9 @@ -/var/create_mob_html = null -/datum/admins/proc/create_mob(var/mob/user) - if (!create_mob_html) - var/mobjs = null - mobjs = list2text(typesof(/mob), ";") - create_mob_html = file2text('html/create_object.html') - create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"") - - user << browse(replacetext(create_mob_html, "/* ref src */", "\ref[src]"), "window=create_mob;size=425x520") +/var/create_mob_html = null +/datum/admins/proc/create_mob(var/mob/user) + if (!create_mob_html) + var/mobjs = null + mobjs = list2text(typesof(/mob), ";") + create_mob_html = file2text('html/create_object.html') + create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"") + + user << browse(replacetext(create_mob_html, "/* ref src */", "\ref[src]"), "window=create_mob;size=425x520") diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm index a2cd48e252f..db17426b829 100644 --- a/code/modules/admin/create_object.dm +++ b/code/modules/admin/create_object.dm @@ -1,29 +1,29 @@ -/var/create_object_html = null - -/datum/admins/proc/create_object(var/mob/user) - if (!create_object_html) - var/objectjs = null - objectjs = list2text(typesof(/obj), ";") - create_object_html = file2text('html/create_object.html') - create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"") - - user << browse(replacetext(create_object_html, "/* ref src */", "\ref[src]"), "window=create_object;size=425x475") - - -/datum/admins/proc/quick_create_object(var/mob/user) - - - 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") - - var path = text2path(pathtext) - - if (!quick_create_object_html) - var/objectjs = null - objectjs = list2text(typesof(path), ";") - quick_create_object_html = file2text('html/create_object.html') - quick_create_object_html = replacetext(quick_create_object_html, "null /* object types */", "\"[objectjs]\"") - +/var/create_object_html = null + +/datum/admins/proc/create_object(var/mob/user) + if (!create_object_html) + var/objectjs = null + objectjs = list2text(typesof(/obj), ";") + create_object_html = file2text('html/create_object.html') + create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"") + + user << browse(replacetext(create_object_html, "/* ref src */", "\ref[src]"), "window=create_object;size=425x475") + + +/datum/admins/proc/quick_create_object(var/mob/user) + + + 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") + + var path = text2path(pathtext) + + if (!quick_create_object_html) + var/objectjs = null + objectjs = list2text(typesof(path), ";") + quick_create_object_html = file2text('html/create_object.html') + quick_create_object_html = replacetext(quick_create_object_html, "null /* object types */", "\"[objectjs]\"") + user << browse(replacetext(quick_create_object_html, "/* ref src */", "\ref[src]"), "window=quick_create_object;size=425x475") \ No newline at end of file diff --git a/code/modules/admin/create_turf.dm b/code/modules/admin/create_turf.dm index 0938b7bd33d..94071ecca69 100644 --- a/code/modules/admin/create_turf.dm +++ b/code/modules/admin/create_turf.dm @@ -1,9 +1,9 @@ -/var/create_turf_html = null -/datum/admins/proc/create_turf(var/mob/user) - if (!create_turf_html) - var/turfjs = null - turfjs = list2text(typesof(/turf), ";") - create_turf_html = file2text('html/create_object.html') - create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"") - - user << browse(replacetext(create_turf_html, "/* ref src */", "\ref[src]"), "window=create_turf;size=425x475") +/var/create_turf_html = null +/datum/admins/proc/create_turf(var/mob/user) + if (!create_turf_html) + var/turfjs = null + turfjs = list2text(typesof(/turf), ";") + create_turf_html = file2text('html/create_object.html') + create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"") + + user << browse(replacetext(create_turf_html, "/* ref src */", "\ref[src]"), "window=create_turf;size=425x475") diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 39ba8324784..99b6cf172df 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -1,124 +1,124 @@ -var/list/admin_datums = list() - -/datum/admins - var/rank = "Temporary Admin" - var/client/owner = null - var/rights = 0 - var/fakekey = null - - var/datum/marked_datum - - var/admincaster_screen = 0 //See newscaster.dm under machinery for a full description - var/datum/feed_message/admincaster_feed_message = new /datum/feed_message //These two will act as holders. - var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel - var/admincaster_signature //What you'll sign the newsfeeds as - var/sessKey = 0 - -/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey) - if(!ckey) - error("Admin datum created without a ckey argument. Datum has been deleted") - del(src) - return - admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" - rank = initial_rank - rights = initial_rights - admin_datums[ckey] = src - -/datum/admins/proc/associate(client/C) - if(istype(C)) - owner = C - owner.holder = src - owner.add_admin_verbs() //TODO - admins |= C - owner.verbs -= /client/proc/readmin - -/datum/admins/proc/disassociate() - if(owner) - admins -= owner - owner.remove_admin_verbs() - owner.holder = null - owner = null - -/* -checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags) -if rights_required == 0, then it simply checks if they are an admin. -if it doesn't return 1 and show_msg=1 it will prints a message explaining why the check has failed -generally it would be used like so: - -proc/admin_proc() - if(!check_rights(R_ADMIN)) return +var/list/admin_datums = list() + +/datum/admins + var/rank = "Temporary Admin" + var/client/owner = null + var/rights = 0 + var/fakekey = null + + var/datum/marked_datum + + var/admincaster_screen = 0 //See newscaster.dm under machinery for a full description + var/datum/feed_message/admincaster_feed_message = new /datum/feed_message //These two will act as holders. + var/datum/feed_channel/admincaster_feed_channel = new /datum/feed_channel + var/admincaster_signature //What you'll sign the newsfeeds as + var/sessKey = 0 + +/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey) + if(!ckey) + error("Admin datum created without a ckey argument. Datum has been deleted") + del(src) + return + admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" + rank = initial_rank + rights = initial_rights + admin_datums[ckey] = src + +/datum/admins/proc/associate(client/C) + if(istype(C)) + owner = C + owner.holder = src + owner.add_admin_verbs() //TODO + admins |= C + owner.verbs -= /client/proc/readmin + +/datum/admins/proc/disassociate() + if(owner) + admins -= owner + owner.remove_admin_verbs() + owner.holder = null + owner = null + +/* +checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags) +if rights_required == 0, then it simply checks if they are an admin. +if it doesn't return 1 and show_msg=1 it will prints a message explaining why the check has failed +generally it would be used like so: + +proc/admin_proc() + if(!check_rights(R_ADMIN)) return to_chat(world, "you have enough rights!") - -NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call -you will have to do something like if(client.rights & R_ADMIN) yourself. -*/ -/proc/check_rights(rights_required, show_msg=1) - if(usr && usr.client) - if(rights_required) - if(usr.client.holder) - if(rights_required & usr.client.holder.rights) - return 1 - else - if(show_msg) + +NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call +you will have to do something like if(client.rights & R_ADMIN) yourself. +*/ +/proc/check_rights(rights_required, show_msg=1) + if(usr && usr.client) + if(rights_required) + if(usr.client.holder) + if(rights_required & usr.client.holder.rights) + return 1 + else + if(show_msg) to_chat(usr, "Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].") - else - if(usr.client.holder) - return 1 - else - if(show_msg) + else + if(usr.client.holder) + return 1 + else + if(show_msg) to_chat(usr, "Error: You are not an admin.") - return 0 - -// Making this a bit less of a roaring asspain. - N3X -/mob/proc/check_rights(rights_required) - if(src && src.client) - if(rights_required) - if(src.client.holder) - if(rights_required & src.client.holder.rights) - return 1 - else - if(src.client.holder) - return 1 - return 0 - -//probably a bit iffy - will hopefully figure out a better solution -/proc/check_if_greater_rights_than(client/other) - if(usr && usr.client) - if(usr.client.holder) - if(!other || !other.holder) - return 1 - if(usr.client.holder.rights != other.holder.rights) - if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights ) - return 1 //we have all the rights they have and more + return 0 + +// Making this a bit less of a roaring asspain. - N3X +/mob/proc/check_rights(rights_required) + if(src && src.client) + if(rights_required) + if(src.client.holder) + if(rights_required & src.client.holder.rights) + return 1 + else + if(src.client.holder) + return 1 + return 0 + +//probably a bit iffy - will hopefully figure out a better solution +/proc/check_if_greater_rights_than(client/other) + if(usr && usr.client) + if(usr.client.holder) + if(!other || !other.holder) + return 1 + if(usr.client.holder.rights != other.holder.rights) + if( (usr.client.holder.rights & other.holder.rights) == other.holder.rights ) + return 1 //we have all the rights they have and more to_chat(usr, "Error: Cannot proceed. They have more or equal rights to us.") - return 0 - - - -/client/proc/deadmin() - admin_datums -= ckey - if(holder) - holder.disassociate() - del(holder) - return 1 - -/datum/admins/proc/checkSessionKey(var/recurse=0) - if(recurse==5) - return "\[BROKEN\]"; - recurse++ - var/DBQuery/query = dbcon.NewQuery("DELETE FROM admin_sessions WHERE expires < Now()") - query.Execute() - - query = dbcon.NewQuery("SELECT sessID FROM admin_sessions WHERE ckey = '[owner.ckey]' AND expires > Now()") - query.Execute() - - sessKey=0 - while(query.NextRow()) - sessKey = query.item[1] - query=dbcon.NewQuery("UPDATE admin_sessions SET expires=DATE_ADD(NOW(), INTERVAL 24 HOUR), IP='[owner.address]' WHERE ckey = '[owner.ckey]") - query.Execute() - return sessKey - - query=dbcon.NewQuery("INSERT INTO admin_sessions (sessID,ckey,expires, IP) VALUES (UUID(), '[owner.ckey]', DATE_ADD(NOW(), INTERVAL 24 HOUR), '[owner.address]')") - query.Execute() + return 0 + + + +/client/proc/deadmin() + admin_datums -= ckey + if(holder) + holder.disassociate() + del(holder) + return 1 + +/datum/admins/proc/checkSessionKey(var/recurse=0) + if(recurse==5) + return "\[BROKEN\]"; + recurse++ + var/DBQuery/query = dbcon.NewQuery("DELETE FROM admin_sessions WHERE expires < Now()") + query.Execute() + + query = dbcon.NewQuery("SELECT sessID FROM admin_sessions WHERE ckey = '[owner.ckey]' AND expires > Now()") + query.Execute() + + sessKey=0 + while(query.NextRow()) + sessKey = query.item[1] + query=dbcon.NewQuery("UPDATE admin_sessions SET expires=DATE_ADD(NOW(), INTERVAL 24 HOUR), IP='[owner.address]' WHERE ckey = '[owner.ckey]") + query.Execute() + return sessKey + + query=dbcon.NewQuery("INSERT INTO admin_sessions (sessID,ckey,expires, IP) VALUES (UUID(), '[owner.ckey]', DATE_ADD(NOW(), INTERVAL 24 HOUR), '[owner.address]')") + query.Execute() return checkSessionKey(recurse) \ No newline at end of file diff --git a/code/modules/admin/newbanjob.dm b/code/modules/admin/newbanjob.dm index 27f803ea6fd..29d817f3152 100644 --- a/code/modules/admin/newbanjob.dm +++ b/code/modules/admin/newbanjob.dm @@ -1,280 +1,280 @@ -var/savefile/Banlistjob - - -/proc/_jobban_isbanned(var/client/clientvar, var/rank) - if(!clientvar) return 1 - ClearTempbansjob() - var/id = clientvar.computer_id - var/key = clientvar.ckey - if (guest_jobbans(rank)) - if(config.guest_jobban && IsGuestKey(key)) - return 1 - Banlistjob.cd = "/base" - if (Banlistjob.dir.Find("[key][id][rank]")) - return 1 - - Banlistjob.cd = "/base" - for (var/A in Banlistjob.dir) - Banlistjob.cd = "/base/[A]" - if ((id == Banlistjob["id"] || key == Banlistjob["key"]) && rank == Banlistjob["rank"]) - return 1 - return 0 - -/proc/LoadBansjob() - - - Banlistjob = new("data/job_fullnew.bdb") - log_admin("Loading Banlistjob") - - if (!length(Banlistjob.dir)) log_admin("Banlistjob is empty.") - - if (!Banlistjob.dir.Find("base")) - log_admin("Banlistjob missing base dir.") - Banlistjob.dir.Add("base") - Banlistjob.cd = "/base" - else if (Banlistjob.dir.Find("base")) - Banlistjob.cd = "/base" - - ClearTempbansjob() - return 1 - -/proc/ClearTempbansjob() - UpdateTime() - - Banlistjob.cd = "/base" - for (var/A in Banlistjob.dir) - Banlistjob.cd = "/base/[A]" - //if (!Banlistjob["key"] || !Banlistjob["id"]) - // RemoveBanjob(A, "full") - // log_admin("Invalid Ban.") - // message_admins("Invalid Ban.") - // continue - - if (!Banlistjob["temp"]) continue - if (CMinutes >= Banlistjob["minutes"]) RemoveBanjob(A) - - return 1 - - -/proc/AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, rank) - UpdateTime() - var/bantimestamp - if (temp) - UpdateTime() - bantimestamp = CMinutes + minutes - if(rank == "Heads") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Personnel") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Captain") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - return 1 - if(rank == "Security") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Warden") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Detective") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Security Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") - return 1 - if(rank == "Engineering") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Station Engineer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Atmospheric Technician") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") - return 1 - if(rank == "Research") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Scientist") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") - return 1 - if(rank == "Medical") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Medical Doctor") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chemist") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") - return 1 - if(rank == "CE_Station_Engineer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Station Engineer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") - return 1 - if(rank == "CE_Atmospheric_Tech") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Atmospheric Technician") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") - return 1 - if(rank == "CE_Shaft_Miner") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Shaft Miner") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") - return 1 - if(rank == "Chemist_RD_CMO") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chemist") - return 1 - if(rank == "Geneticist_RD_CMO") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist") - return 1 - if(rank == "MD_CMO") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Medical Doctor") - return 1 - if(rank == "Scientist_RD") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Scientist") - return 1 - if(rank == "AI_Cyborg") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "AI") - return 1 - if(rank == "Detective_HoS") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Detective") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security") - return 1 - if(rank == "Virologist_RD_CMO") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") - AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Virologist") - return 1 - - Banlistjob.cd = "/base" - if ( Banlistjob.dir.Find("[ckey][computerid][rank]") ) +var/savefile/Banlistjob + + +/proc/_jobban_isbanned(var/client/clientvar, var/rank) + if(!clientvar) return 1 + ClearTempbansjob() + var/id = clientvar.computer_id + var/key = clientvar.ckey + if (guest_jobbans(rank)) + if(config.guest_jobban && IsGuestKey(key)) + return 1 + Banlistjob.cd = "/base" + if (Banlistjob.dir.Find("[key][id][rank]")) + return 1 + + Banlistjob.cd = "/base" + for (var/A in Banlistjob.dir) + Banlistjob.cd = "/base/[A]" + if ((id == Banlistjob["id"] || key == Banlistjob["key"]) && rank == Banlistjob["rank"]) + return 1 + return 0 + +/proc/LoadBansjob() + + + Banlistjob = new("data/job_fullnew.bdb") + log_admin("Loading Banlistjob") + + if (!length(Banlistjob.dir)) log_admin("Banlistjob is empty.") + + if (!Banlistjob.dir.Find("base")) + log_admin("Banlistjob missing base dir.") + Banlistjob.dir.Add("base") + Banlistjob.cd = "/base" + else if (Banlistjob.dir.Find("base")) + Banlistjob.cd = "/base" + + ClearTempbansjob() + return 1 + +/proc/ClearTempbansjob() + UpdateTime() + + Banlistjob.cd = "/base" + for (var/A in Banlistjob.dir) + Banlistjob.cd = "/base/[A]" + //if (!Banlistjob["key"] || !Banlistjob["id"]) + // RemoveBanjob(A, "full") + // log_admin("Invalid Ban.") + // message_admins("Invalid Ban.") + // continue + + if (!Banlistjob["temp"]) continue + if (CMinutes >= Banlistjob["minutes"]) RemoveBanjob(A) + + return 1 + + +/proc/AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, rank) + UpdateTime() + var/bantimestamp + if (temp) + UpdateTime() + bantimestamp = CMinutes + minutes + if(rank == "Heads") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Personnel") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Captain") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + return 1 + if(rank == "Security") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Warden") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Detective") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Security Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") + return 1 + if(rank == "Engineering") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Station Engineer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Atmospheric Technician") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") + return 1 + if(rank == "Research") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Scientist") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") + return 1 + if(rank == "Medical") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Medical Doctor") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chemist") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") + return 1 + if(rank == "CE_Station_Engineer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Station Engineer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") + return 1 + if(rank == "CE_Atmospheric_Tech") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Atmospheric Technician") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") + return 1 + if(rank == "CE_Shaft_Miner") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Shaft Miner") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Engineer") + return 1 + if(rank == "Chemist_RD_CMO") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chemist") + return 1 + if(rank == "Geneticist_RD_CMO") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Geneticist") + return 1 + if(rank == "MD_CMO") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Medical Doctor") + return 1 + if(rank == "Scientist_RD") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Scientist") + return 1 + if(rank == "AI_Cyborg") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Cyborg") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "AI") + return 1 + if(rank == "Detective_HoS") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Detective") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Head of Security") + return 1 + if(rank == "Virologist_RD_CMO") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Chief Medical Officer") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Research Director") + AddBanjob(ckey, computerid, reason, bannedby, temp, minutes, "Virologist") + return 1 + + Banlistjob.cd = "/base" + if ( Banlistjob.dir.Find("[ckey][computerid][rank]") ) to_chat(usr, text("Banjob already exists.")) - return 0 - else - Banlistjob.dir.Add("[ckey][computerid][rank]") - Banlistjob.cd = "/base/[ckey][computerid][rank]" + return 0 + else + Banlistjob.dir.Add("[ckey][computerid][rank]") + Banlistjob.cd = "/base/[ckey][computerid][rank]" Banlistjob["key"] << ckey Banlistjob["id"] << computerid Banlistjob["rank"] << rank Banlistjob["reason"] << reason Banlistjob["bannedby"] << bannedby Banlistjob["temp"] << temp - if (temp) + if (temp) Banlistjob["minutes"] << bantimestamp - - return 1 - -/proc/RemoveBanjob(foldername) - var/key - var/id - var/rank - Banlistjob.cd = "/base/[foldername]" - Banlistjob["key"] >> key - Banlistjob["id"] >> id - Banlistjob["rank"] >> rank - Banlistjob.cd = "/base" - - if (!Banlistjob.dir.Remove(foldername)) return 0 - - if(!usr) - log_admin("Banjob Expired: [key]") - message_admins("Banjob Expired: [key]") - else - log_admin("[key_name_admin(usr)] unjobbanned [key] from [rank]") - message_admins("[key_name_admin(usr)] unjobbanned:[key] from [rank]") - ban_unban_log_save("[key_name_admin(usr)] unjobbanned [key] from [rank]") - feedback_inc("ban_job_unban",1) - feedback_add_details("ban_job_unban","- [rank]") - - for (var/A in Banlistjob.dir) - Banlistjob.cd = "/base/[A]" - if ((key == Banlistjob["key"] || id == Banlistjob["id"]) && (rank == Banlistjob["rank"])) - Banlistjob.cd = "/base" - Banlistjob.dir.Remove(A) - continue - - return 1 - -/proc/GetBanExpjob(minutes as num) - UpdateTime() - var/exp = minutes - CMinutes - if (exp <= 0) - return 0 - else - var/timeleftstring - if (exp >= 1440) //1440 = 1 day in minutes - timeleftstring = "[round(exp / 1440, 0.1)] Days" - else if (exp >= 60) //60 = 1 hour in minutes - timeleftstring = "[round(exp / 60, 0.1)] Hours" - else - timeleftstring = "[exp] Minutes" - return timeleftstring - -/datum/admins/proc/unjobbanpanel() - var/count = 0 - var/dat - //var/dat = "
    Unban Player: (U) = Unban , (E) = Edit Ban(Total
    " - Banlistjob.cd = "/base" - for (var/A in Banlistjob.dir) - count++ - Banlistjob.cd = "/base/[A]" - dat += text("") - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\newbanjob.dm:216: dat += "
    (U) Key: [Banlistjob["key"]] Rank: [Banlistjob["rank"]] ([Banlistjob["temp"] ? "[GetBanExpjob(Banlistjob["minutes"]) ? GetBanExpjob(Banlistjob["minutes"]) : "Removal pending" ]" : "Permaban"])(By: [Banlistjob["bannedby"]])(Reason: [Banlistjob["reason"]])
    " - dat += {" -
    Bans: (U) = Unban , - ([count] Bans)
    [dat]"} - // END AUTOFIX - usr << browse(dat, "window=unbanp;size=875x400") - -/*/datum/admins/proc/permjobban(ckey, computerid, reason, bannedby, temp, minutes, rank) - if(AddBanjob(ckey, computerid, reason, usr.ckey, 0, 0, job)) + + return 1 + +/proc/RemoveBanjob(foldername) + var/key + var/id + var/rank + Banlistjob.cd = "/base/[foldername]" + Banlistjob["key"] >> key + Banlistjob["id"] >> id + Banlistjob["rank"] >> rank + Banlistjob.cd = "/base" + + if (!Banlistjob.dir.Remove(foldername)) return 0 + + if(!usr) + log_admin("Banjob Expired: [key]") + message_admins("Banjob Expired: [key]") + else + log_admin("[key_name_admin(usr)] unjobbanned [key] from [rank]") + message_admins("[key_name_admin(usr)] unjobbanned:[key] from [rank]") + ban_unban_log_save("[key_name_admin(usr)] unjobbanned [key] from [rank]") + feedback_inc("ban_job_unban",1) + feedback_add_details("ban_job_unban","- [rank]") + + for (var/A in Banlistjob.dir) + Banlistjob.cd = "/base/[A]" + if ((key == Banlistjob["key"] || id == Banlistjob["id"]) && (rank == Banlistjob["rank"])) + Banlistjob.cd = "/base" + Banlistjob.dir.Remove(A) + continue + + return 1 + +/proc/GetBanExpjob(minutes as num) + UpdateTime() + var/exp = minutes - CMinutes + if (exp <= 0) + return 0 + else + var/timeleftstring + if (exp >= 1440) //1440 = 1 day in minutes + timeleftstring = "[round(exp / 1440, 0.1)] Days" + else if (exp >= 60) //60 = 1 hour in minutes + timeleftstring = "[round(exp / 60, 0.1)] Hours" + else + timeleftstring = "[exp] Minutes" + return timeleftstring + +/datum/admins/proc/unjobbanpanel() + var/count = 0 + var/dat + //var/dat = "
    Unban Player:(U) = Unban , (E) = Edit Ban(Total
    " + Banlistjob.cd = "/base" + for (var/A in Banlistjob.dir) + count++ + Banlistjob.cd = "/base/[A]" + dat += text("") + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\newbanjob.dm:216: dat += "
    (U) Key: [Banlistjob["key"]] Rank: [Banlistjob["rank"]] ([Banlistjob["temp"] ? "[GetBanExpjob(Banlistjob["minutes"]) ? GetBanExpjob(Banlistjob["minutes"]) : "Removal pending" ]" : "Permaban"])(By: [Banlistjob["bannedby"]])(Reason: [Banlistjob["reason"]])
    " + dat += {" +
    Bans: (U) = Unban , - ([count] Bans)
    [dat]"} + // END AUTOFIX + usr << browse(dat, "window=unbanp;size=875x400") + +/*/datum/admins/proc/permjobban(ckey, computerid, reason, bannedby, temp, minutes, rank) + if(AddBanjob(ckey, computerid, reason, usr.ckey, 0, 0, job)) to_chat(M, "You have been banned from [job] by [usr.client.ckey].\nReason: [reason].") to_chat(M, "This is a permanent ban.") - if(config.banappeals) + if(config.banappeals) to_chat(M, "To try to resolve this matter head to [config.banappeals]") - else + else to_chat(M, "No ban appeals URL has been set.") - log_admin("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis is a permanent ban.") - message_admins("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis is a permanent ban.") -/datum/admins/proc/timejobban(ckey, computerid, reason, bannedby, temp, minutes, rank) - if(AddBanjob(ckey, computerid, reason, usr.ckey, 1, mins, job)) + log_admin("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis is a permanent ban.") + message_admins("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis is a permanent ban.") +/datum/admins/proc/timejobban(ckey, computerid, reason, bannedby, temp, minutes, rank) + if(AddBanjob(ckey, computerid, reason, usr.ckey, 1, mins, job)) to_chat(M, "You have been jobbanned from [job] by [usr.client.ckey].\nReason: [reason].") to_chat(M, "This is a temporary ban, it will be removed in [mins] minutes.") - if(config.banappeals) + if(config.banappeals) to_chat(M, "To try to resolve this matter head to [config.banappeals]") - else + else to_chat(M, "No ban appeals URL has been set.") - log_admin("[usr.client.ckey] has jobbanned from [job] [ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - message_admins("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")*/ -//////////////////////////////////// DEBUG //////////////////////////////////// - -/proc/CreateBansjob() - - - UpdateTime() - - var/i - var/last - - for(i=0, i<1001, i++) - var/a = pick(1,0) - var/b = pick(1,0) - if(b) - Banlistjob.cd = "/base" - Banlistjob.dir.Add("trash[i]trashid[i]") - Banlistjob.cd = "/base/trash[i]trashid[i]" + log_admin("[usr.client.ckey] has jobbanned from [job] [ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + message_admins("[usr.client.ckey] has banned from [job] [ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")*/ +//////////////////////////////////// DEBUG //////////////////////////////////// + +/proc/CreateBansjob() + + + UpdateTime() + + var/i + var/last + + for(i=0, i<1001, i++) + var/a = pick(1,0) + var/b = pick(1,0) + if(b) + Banlistjob.cd = "/base" + Banlistjob.dir.Add("trash[i]trashid[i]") + Banlistjob.cd = "/base/trash[i]trashid[i]" Banlistjob["key"] << "trash[i]" - else - Banlistjob.cd = "/base" - Banlistjob.dir.Add("[last]trashid[i]") - Banlistjob.cd = "/base/[last]trashid[i]" + else + Banlistjob.cd = "/base" + Banlistjob.dir.Add("[last]trashid[i]") + Banlistjob.cd = "/base/[last]trashid[i]" Banlistjob["key"] << last Banlistjob["id"] << "trashid[i]" Banlistjob["reason"] << "Trashban[i]." Banlistjob["temp"] << a Banlistjob["minutes"] << CMinutes + rand(1,2000) Banlistjob["bannedby"] << "trashmin" - last = "trash[i]" - - Banlistjob.cd = "/base" - -/proc/ClearAllBansjob() - Banlistjob.cd = "/base" - for (var/A in Banlistjob.dir) - RemoveBanjob(A, "full") + last = "trash[i]" + + Banlistjob.cd = "/base" + +/proc/ClearAllBansjob() + Banlistjob.cd = "/base" + for (var/A in Banlistjob.dir) + RemoveBanjob(A, "full") diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index 9a32287f0f1..7292adbf129 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -1,158 +1,158 @@ -/client/proc/edit_admin_permissions() - set category = "Admin" - set name = "Permissions Panel" - set desc = "Edit admin permissions" - if(!check_rights(R_PERMISSIONS)) return - usr.client.holder.edit_admin_permissions() - -/datum/admins/proc/edit_admin_permissions() - if(!check_rights(R_PERMISSIONS)) return - - var/output = {" - - -Permissions Panel - - - - -
    - - - - -"} - - for(var/adm_ckey in admin_datums) - var/datum/admins/D = admin_datums[adm_ckey] - if(!D) continue - var/rank = D.rank ? D.rank : "*none*" - var/rights = rights2text(D.rights," ") - if(!rights) rights = "*none*" - output += {" - - - -"} - - /*output += "" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\\permissionverbs\\\permissionedit.dm:39: output += "" - output += {" - -"} - // END AUTOFIX - output += ""*/ - - output += {" -
    CKEY \[+\]RANKPERMISSIONS
    [adm_ckey] \[-\][rank][rights]
    [adm_ckey] \[-\][adm_ckey] \[-\][rank][rights]
    -
    Search:
    - -"} - - usr << browse(output,"window=editrights;size=600x500") - -/datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank) - if(config.admin_legacy_system) return - - if(!usr.client) - return - - if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS)) +/client/proc/edit_admin_permissions() + set category = "Admin" + set name = "Permissions Panel" + set desc = "Edit admin permissions" + if(!check_rights(R_PERMISSIONS)) return + usr.client.holder.edit_admin_permissions() + +/datum/admins/proc/edit_admin_permissions() + if(!check_rights(R_PERMISSIONS)) return + + var/output = {" + + +Permissions Panel + + + + +
    + + + + +"} + + for(var/adm_ckey in admin_datums) + var/datum/admins/D = admin_datums[adm_ckey] + if(!D) continue + var/rank = D.rank ? D.rank : "*none*" + var/rights = rights2text(D.rights," ") + if(!rights) rights = "*none*" + output += {" + + + +"} + + /*output += "" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\admin\\\permissionverbs\\\permissionedit.dm:39: output += "" + output += {" + +"} + // END AUTOFIX + output += ""*/ + + output += {" +
    CKEY \[+\]RANKPERMISSIONS
    [adm_ckey] \[-\][rank][rights]
    [adm_ckey] \[-\][adm_ckey] \[-\][rank][rights]
    +
    Search:
    + +"} + + usr << browse(output,"window=editrights;size=600x500") + +/datum/admins/proc/log_admin_rank_modification(var/adm_ckey, var/new_rank) + if(config.admin_legacy_system) return + + if(!usr.client) + return + + if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS)) to_chat(usr, "You do not have permission to do this!") - return - - establish_db_connection() - - if(!dbcon.IsConnected()) + return + + establish_db_connection() + + if(!dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection") - return - - if(!adm_ckey || !new_rank) - return - - adm_ckey = ckey(adm_ckey) - - if(!adm_ckey) - return - - if(!istext(adm_ckey) || !istext(new_rank)) - return - - var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'") - select_query.Execute() - - var/new_admin = 1 - var/admin_id - while(select_query.NextRow()) - new_admin = 0 - admin_id = text2num(select_query.item[1]) - - if(new_admin) - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)") - insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');") - log_query.Execute() + return + + if(!adm_ckey || !new_rank) + return + + adm_ckey = ckey(adm_ckey) + + if(!adm_ckey) + return + + if(!istext(adm_ckey) || !istext(new_rank)) + return + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'") + select_query.Execute() + + var/new_admin = 1 + var/admin_id + while(select_query.NextRow()) + new_admin = 0 + admin_id = text2num(select_query.item[1]) + + if(new_admin) + var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)") + insert_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');") + log_query.Execute() to_chat(usr, "New admin added.") - else - if(!isnull(admin_id) && isnum(admin_id)) - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]") - insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');") - log_query.Execute() + else + if(!isnull(admin_id) && isnum(admin_id)) + var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]") + insert_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');") + log_query.Execute() to_chat(usr, "Admin rank changed.") - -/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission) - if(config.admin_legacy_system) return - - if(!usr.client) - return - - if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS)) + +/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission) + if(config.admin_legacy_system) return + + if(!usr.client) + return + + if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS)) to_chat(usr, "You do not have permission to do this!") - return - - establish_db_connection() - if(!dbcon.IsConnected()) + return + + establish_db_connection() + if(!dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection") - return - - if(!adm_ckey || !new_permission) - return - - adm_ckey = ckey(adm_ckey) - - if(!adm_ckey) - return - - if(istext(new_permission)) - new_permission = text2num(new_permission) - - if(!istext(adm_ckey) || !isnum(new_permission)) - return - - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'") - select_query.Execute() - - var/admin_id - var/admin_rights - while(select_query.NextRow()) - admin_id = text2num(select_query.item[1]) - admin_rights = text2num(select_query.item[2]) - - if(!admin_id) - return - - if(admin_rights & new_permission) //This admin already has this permission, so we are removing it. - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]") - insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") - log_query.Execute() + return + + if(!adm_ckey || !new_permission) + return + + adm_ckey = ckey(adm_ckey) + + if(!adm_ckey) + return + + if(istext(new_permission)) + new_permission = text2num(new_permission) + + if(!istext(adm_ckey) || !isnum(new_permission)) + return + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'") + select_query.Execute() + + var/admin_id + var/admin_rights + while(select_query.NextRow()) + admin_id = text2num(select_query.item[1]) + admin_rights = text2num(select_query.item[2]) + + if(!admin_id) + return + + if(admin_rights & new_permission) //This admin already has this permission, so we are removing it. + var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]") + insert_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") + log_query.Execute() to_chat(usr, "Permission removed.") - else //This admin doesn't have this permission, so we are adding it. - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]") - insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") - log_query.Execute() + else //This admin doesn't have this permission, so we are adding it. + var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]") + insert_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") + log_query.Execute() to_chat(usr, "Permission added.") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index efc9fa28760..3fbef09cc52 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1,3904 +1,3904 @@ -/datum/admins/Topic(href, href_list) - ..() - - if(usr.client != src.owner || !check_rights(0)) - log_admin("[key_name(usr)] tried to use the admin panel without authorization.") - message_admins("[usr.key] has attempted to override the admin panel!") - return - - var/client/CLIENT = usr.client - if(href_list["makeAntag"]) - switch(href_list["makeAntag"]) - if("1") - log_admin("[key_name(usr)] has spawned a traitor.") - if(!src.makeTraitors()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("2") - log_admin("[key_name(usr)] has spawned a changeling.") - if(!src.makeChanglings()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("3") - log_admin("[key_name(usr)] has spawned revolutionaries.") - if(!src.makeRevs()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("4") - log_admin("[key_name(usr)] has spawned a cultists.") - if(!src.makeCult()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("5") - log_admin("[key_name(usr)] has spawned a malf AI.") - if(!src.makeMalfAImode()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("6") - log_admin("[key_name(usr)] has spawned a wizard.") - if(!src.makeWizard()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("7") - log_admin("[key_name(usr)] has spawned a nuke team.") - if(!src.makeNukeTeam()) - to_chat(usr, "Unfortunately there weren't enough candidates available.") - if("9") - log_admin("[key_name(usr)] has spawned aliens.") - src.makeAliens() - if("10") - log_admin("[key_name(usr)] has spawned a death squad.") - if(!makeDeathsquad()) - to_chat(usr, "Unfortunately, there were no candidates available") - if("11") - log_admin("[key_name(usr)] has spawned vox raiders.") - if(!src.makeVoxRaiders()) - to_chat(usr, "Unfortunately, there weren't enough candidates available.") - - else if("announce_laws" in href_list) - var/mob/living/silicon/S = locate(href_list["mob"]) - - log_admin("[key_name(usr)] has notified [key_name(S)] of a change to their laws.") - message_admins("[usr.key] has notified [key_name(S)] of a change to their laws.") - - to_chat(S, "____________________________________") - to_chat(S, "LAW CHANGE NOTICE") - if(S.laws) - to_chat(S, "Your new laws are as follows:") - S.laws.show_laws(S) - else - to_chat(S, "Your laws are null. Contact a coder immediately.") - to_chat(S, "____________________________________") - if(isAI(S)) - var/mob/living/silicon/ai/AI=S - AI.notify_slaved(force_sync=1) - - else if("add_law" in href_list) - var/mob/living/silicon/S = locate(href_list["mob"]) - var/lawtypes = list( - "Law Zero"= LAW_ZERO, - "Ion" = LAW_IONIC, - "Core" = LAW_INHERENT, - "Standard"= 1 - ) - var/lawtype = input("Select a law type.","Law Type",1) as anything in lawtypes - lawtype=lawtypes[lawtype] - if(lawtype == null) - return - testing("Lawtype: [lawtype]") - if(lawtype==1) - lawtype=text2num(input("Enter desired law priority. (15-50)","Priority", 15) as num) - lawtype=Clamp(lawtype,15,50) - var/newlaw = copytext(sanitize(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry", "")),1,MAX_MESSAGE_LEN) - if(newlaw=="") - return - S.laws.add_law(lawtype,newlaw) - - log_admin("[key_name(usr)] has added a law to [key_name(S)]: \"[newlaw]\"") - message_admins("[usr.key] has added a law to [key_name(S)]: \"[newlaw]\"") - lawchanges.Add("[key_name(usr)] has added a law to [key_name(S)]: \"[newlaw]\"") - - else if("reset_laws" in href_list) - var/mob/living/silicon/S = locate(href_list["mob"]) - var/lawtypes = typesof(/datum/ai_laws) - /datum/ai_laws - var/lawtype = input("Select a lawset.","Law Type",1) as null|anything in lawtypes - if(lawtype == null) - return - testing("Lawtype: [lawtype]") - - var/law_zeroth=null - var/law_zeroth_borg=null - if(S.laws.zeroth || S.laws.zeroth_borg) - if(alert(src,"Do you also wish to clear law zero?","Yes","No") == "No") - law_zeroth=S.laws.zeroth - law_zeroth_borg=S.laws.zeroth - - S.laws = new lawtype - S.laws.zeroth=law_zeroth - S.laws.zeroth_borg=law_zeroth_borg - - log_admin("[key_name(usr)] has reset [key_name(S)]: [lawtype]") - message_admins("[usr.key] has reset [key_name(S)]: [lawtype]") - lawchanges.Add("[key_name(usr)] has reset [key_name(S)]: [lawtype]") - - else if("clear_laws" in href_list) - var/mob/living/silicon/S = locate(href_list["mob"]) - S.laws.clear_inherent_laws() - S.laws.clear_supplied_laws() - S.laws.clear_ion_laws() - - if(S.laws.zeroth || S.laws.zeroth_borg) - if(alert(src,"Do you also wish to clear law zero?","Yes","No") == "Yes") - S.laws.set_zeroth_law("","") - - log_admin("[key_name(usr)] has purged [key_name(S)]") - message_admins("[usr.key] has purged [key_name(S)]") - lawchanges.Add("[key_name(usr)] has purged [key_name(S)]") - - else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"]) - var/adminckey = href_list["dbsearchadmin"] - var/playerckey = href_list["dbsearchckey"] - - DB_ban_panel(playerckey, adminckey) - return - - else if(href_list["dbbanedit"]) - var/banedit = href_list["dbbanedit"] - var/banid = text2num(href_list["dbbanid"]) - if(!banedit || !banid) - return - - DB_ban_edit(banid, banedit) - return - - else if(href_list["dbbanaddtype"]) - - var/bantype = text2num(href_list["dbbanaddtype"]) - var/banckey = href_list["dbbanaddckey"] - var/banduration = text2num(href_list["dbbaddduration"]) - var/banjob = href_list["dbbanaddjob"] - var/banreason = href_list["dbbanreason"] - - banckey = ckey(banckey) - - switch(bantype) - if(BANTYPE_PERMA) - if(!banckey || !banreason) - to_chat(usr, "Not enough parameters (Requires ckey and reason)") - return - banduration = null - banjob = null - if(BANTYPE_TEMP) - if(!banckey || !banreason || !banduration) - to_chat(usr, "Not enough parameters (Requires ckey, reason and duration)") - return - banjob = null - if(BANTYPE_JOB_PERMA) - if(!banckey || !banreason || !banjob) - to_chat(usr, "Not enough parameters (Requires ckey, reason and job)") - return - banduration = null - if(BANTYPE_JOB_TEMP) - if(!banckey || !banreason || !banjob || !banduration) - to_chat(usr, "Not enough parameters (Requires ckey, reason and job)") - return - if(BANTYPE_APPEARANCE) - if(!banckey || !banreason) - to_chat(usr, "Not enough parameters (Requires ckey and reason)") - return - banduration = null - banjob = null - if(BANTYPE_OOC_PERMA) - if(!banckey || !banreason) - to_chat(usr, "Not enough parameters (Requires ckey and reason)") - return - banduration = null - if(BANTYPE_OOC_TEMP) - if(!banckey || !banreason || !banduration) - to_chat(usr, "Not enough parameters (Requires ckey, reason, and duration)") - return - - var/mob/playermob - - for(var/mob/M in player_list) - if(M.ckey == banckey) - playermob = M - break - - banreason = "(MANUAL BAN) "+banreason - - DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey) - - else if(href_list["editrights"]) - if(!check_rights(R_PERMISSIONS)) - message_admins("[key_name_admin(usr)] attempted to edit the admin permissions without sufficient rights.") - log_admin("[key_name(usr)] attempted to edit the admin permissions without sufficient rights.") - return - - var/adm_ckey - - var/task = href_list["editrights"] - if(task == "add") - var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null) - if(!new_ckey) return - if(new_ckey in admin_datums) - to_chat(usr, "Error: Topic 'editrights': [new_ckey] is already an admin") - return - adm_ckey = new_ckey - task = "rank" - else if(task != "show") - adm_ckey = ckey(href_list["ckey"]) - if(!adm_ckey) - to_chat(usr, "Error: Topic 'editrights': No valid ckey") - return - - var/datum/admins/D = admin_datums[adm_ckey] - - if(task == "remove") - if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes") - if(!D) return - admin_datums -= adm_ckey - D.disassociate() - - message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list") - log_admin("[key_name(usr)] removed [adm_ckey] from the admins list") - log_admin_rank_modification(adm_ckey, "Removed") - - else if(task == "rank") - var/new_rank - if(admin_ranks.len) - new_rank = input("Please select a rank", "New rank", null, null) as null|anything in (admin_ranks|"*New Rank*") - else - new_rank = input("Please select a rank", "New rank", null, null) as null|anything in list("Game Master","Game Admin", "Trial Admin", "Admin Observer","*New Rank*") - - var/rights = 0 - if(D) - rights = D.rights - switch(new_rank) - if(null,"") return - if("*New Rank*") - new_rank = input("Please input a new rank", "New custom rank", null, null) as null|text - if(config.admin_legacy_system) - new_rank = ckeyEx(new_rank) - if(!new_rank) - to_chat(usr, "Error: Topic 'editrights': Invalid rank") - return - if(config.admin_legacy_system) - if(admin_ranks.len) - if(new_rank in admin_ranks) - rights = admin_ranks[new_rank] //we typed a rank which already exists, use its rights - else - admin_ranks[new_rank] = 0 //add the new rank to admin_ranks - else - if(config.admin_legacy_system) - new_rank = ckeyEx(new_rank) - rights = admin_ranks[new_rank] //we input an existing rank, use its rights - - if(D) - D.disassociate() //remove adminverbs and unlink from client - D.rank = new_rank //update the rank - D.rights = rights //update the rights based on admin_ranks (default: 0) - else - D = new /datum/admins(new_rank, rights, adm_ckey) - - var/client/C = directory[adm_ckey] //find the client with the specified ckey (if they are logged in) - D.associate(C) //link up with the client and add verbs - - message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]") - log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]") - log_admin_rank_modification(adm_ckey, new_rank) - - else if(task == "permissions") - if(!D) return - var/list/permissionlist = list() - for(var/i=1, i<=R_MAXPERMISSION, i<<=1) //that <<= is shorthand for i = i << 1. Which is a left bitshift - permissionlist[rights2text(i)] = i - var/new_permission = input("Select a permission to turn on/off", "Permission toggle", null, null) as null|anything in permissionlist - if(!new_permission) return - D.rights ^= permissionlist[new_permission] - - message_admins("[key_name_admin(usr)] toggled the [new_permission] permission of [adm_ckey]") - log_admin("[key_name(usr)] toggled the [new_permission] permission of [adm_ckey]") - log_admin_permission_modification(adm_ckey, permissionlist[new_permission]) - - edit_admin_permissions() - - else if(href_list["call_shuttle"]) - if(!check_rights(R_ADMIN)) return - - if( ticker.mode.name == "blob" ) - alert("You can't call the shuttle during blob!") - return - - switch(href_list["call_shuttle"]) - if("1") - if ((!( ticker ) || emergency_shuttle.location)) - return - emergency_shuttle.incall() - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") - log_admin("[key_name(usr)] called the Emergency Shuttle") - message_admins("[key_name_admin(usr)] called the Emergency Shuttle to the station", 1) - - if("2") - if ((!( ticker ) || emergency_shuttle.location || emergency_shuttle.direction == 0)) - return - switch(emergency_shuttle.direction) - if(-1) - emergency_shuttle.incall() - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") - log_admin("[key_name(usr)] called the Emergency Shuttle") - message_admins("[key_name_admin(usr)] called the Emergency Shuttle to the station", 1) - if(1) - emergency_shuttle.recall() - log_admin("[key_name(usr)] sent the Emergency Shuttle back") - message_admins("[key_name_admin(usr)] sent the Emergency Shuttle back", 1) - - href_list["secretsadmin"] = "check_antagonist" - - else if(href_list["edit_shuttle_time"]) - if(!check_rights(R_SERVER)) return - - emergency_shuttle.settimeleft( input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", emergency_shuttle.timeleft() ) as num ) - log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [emergency_shuttle.timeleft()]") - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") - message_admins("[key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [emergency_shuttle.timeleft()]", 1) - href_list["secretsadmin"] = "check_antagonist" - - else if(href_list["delay_round_end"]) - if(!check_rights(R_SERVER)) return - - ticker.delay_end = !ticker.delay_end - log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") - message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) - href_list["secretsadmin"] = "check_antagonist" - - else if(href_list["simplemake"]) - if(!check_rights(R_SPAWN)) return - - var/mob/M = locate(href_list["mob"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - var/delmob = 0 - switch(alert("Delete old mob?","Message","Yes","No","Cancel")) - if("Cancel") return - if("Yes") delmob = 1 - - log_admin("[key_name(usr)] has used rudimentary transformation on [key_name(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]") - message_admins("[key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]", 1) - var/mob/new_mob - switch(href_list["simplemake"]) - if("observer") new_mob = M.change_mob_type( /mob/dead/observer , null, null, delmob ) - if("drone") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/drone , null, null, delmob ) - if("hunter") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/hunter , null, null, delmob ) - if("queen") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/queen , null, null, delmob ) - if("sentinel") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob ) - if("larva") new_mob = M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob ) - if("human") new_mob = M.change_mob_type( /mob/living/carbon/human , null, null, delmob ) - if("slime") new_mob = M.change_mob_type( /mob/living/carbon/slime , null, null, delmob ) - if("adultslime") new_mob = M.change_mob_type( /mob/living/carbon/slime/adult , null, null, delmob ) - if("monkey") new_mob = M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob ) - if("robot") new_mob = M.change_mob_type( /mob/living/silicon/robot , null, null, delmob ) - if("cat") new_mob = M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob ) - if("runtime") new_mob = M.change_mob_type( /mob/living/simple_animal/cat/Runtime , null, null, delmob ) - if("corgi") new_mob = M.change_mob_type( /mob/living/simple_animal/corgi , null, null, delmob ) - if("ian") new_mob = M.change_mob_type( /mob/living/simple_animal/corgi/Ian , null, null, delmob ) - if("crab") new_mob = M.change_mob_type( /mob/living/simple_animal/crab , null, null, delmob ) - if("coffee") new_mob = M.change_mob_type( /mob/living/simple_animal/crab/Coffee , null, null, delmob ) - if("parrot") new_mob = M.change_mob_type( /mob/living/simple_animal/parrot , null, null, delmob ) - if("polyparrot") new_mob = M.change_mob_type( /mob/living/simple_animal/parrot/Poly , null, null, delmob ) - if("constructarmoured") new_mob = M.change_mob_type( /mob/living/simple_animal/construct/armoured , null, null, delmob ) - if("constructbuilder") new_mob = M.change_mob_type( /mob/living/simple_animal/construct/builder , null, null, delmob ) - if("constructwraith") new_mob = M.change_mob_type( /mob/living/simple_animal/construct/wraith , null, null, delmob ) - if("shade") new_mob = M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob ) -// to_chat(world, "Made a [new_mob] [usr ? "usr still exists" : "usr does not exist"]") - if(new_mob && new_mob != M) -// to_chat(world, "[new_mob.client] vs [CLIENT] they [new_mob.client == CLIENT ? "match" : "don't match"]") - if(new_mob.client == CLIENT) -// to_chat(world, "setting usr to new_mob") - usr = new_mob //We probably transformed ourselves - show_player_panel(new_mob) - - - /////////////////////////////////////new ban stuff - else if(href_list["unbanf"]) - if(!check_rights(R_BAN)) return - - var/banfolder = href_list["unbanf"] - Banlist.cd = "/base/[banfolder]" - var/key = Banlist["key"] - if(alert(usr, "Are you sure you want to unban [key]?", "Confirmation", "Yes", "No") == "Yes") - if(RemoveBan(banfolder)) - unbanpanel() - else - alert(usr, "This ban has already been lifted / does not exist.", "Error", "Ok") - unbanpanel() - - else if(href_list["warn"]) - usr.client.warn(href_list["warn"]) - - else if(href_list["unwarn"]) - usr.client.unwarn(href_list["unwarn"]) - - else if(href_list["unbane"]) - if(!check_rights(R_BAN)) return - - UpdateTime() - var/reason - - var/banfolder = href_list["unbane"] - Banlist.cd = "/base/[banfolder]" - var/reason2 = Banlist["reason"] - var/temp = Banlist["temp"] - - var/minutes = Banlist["minutes"] - - var/banned_key = Banlist["key"] - Banlist.cd = "/base" - - var/duration - - switch(alert("Temporary Ban?",,"Yes","No")) - if("Yes") - temp = 1 - var/mins = 0 - if(minutes > CMinutes) - mins = minutes - CMinutes - mins = input(usr,"How long (in minutes)? (Default: 1440)","Ban time",mins ? mins : 1440) as num|null - if(!mins) return - mins = min(525599,mins) - minutes = CMinutes + mins - duration = GetExp(minutes) - reason = input(usr,"Reason?","reason",reason2) as text|null - if(!reason) return - if("No") - temp = 0 - duration = "Perma" - reason = input(usr,"Reason?","reason",reason2) as text|null - if(!reason) return - - log_admin("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") - ban_unban_log_save("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") - message_admins("[key_name_admin(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]", 1) - Banlist.cd = "/base/[banfolder]" - to_chat(Banlist["reason"], reason) - to_chat(Banlist["temp"], temp) - to_chat(Banlist["minutes"], minutes) - to_chat(Banlist["bannedby"], usr.ckey) - Banlist.cd = "/base" - feedback_inc("ban_edit",1) - unbanpanel() - - /////////////////////////////////////new ban stuff - else if(href_list["oocban"]) - if(!check_rights(R_BAN)) - return - var/mob/M = locate(href_list["oocban"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(!M.ckey) //sanity - to_chat(usr, "This mob has no ckey") - return - var/oocbanned = oocban_isbanned("[M.ckey]") - if(oocbanned) - switch(alert("Reason: Remove OOC ban?","Please Confirm","Yes","No")) - if("Yes") - ban_unban_log_save("[key_name(usr)] removed [key_name(M)]'s OOC ban") - log_admin("[key_name(usr)] removed [key_name(M)]'s OOC ban") - feedback_inc("ban_ooc_unban", 1) - DB_ban_unban(M.ckey, BANTYPE_OOC_PERMA) - ooc_unban(M) - message_admins("[key_name_admin(usr)] removed [key_name_admin(M)]'s OOC ban", 1) - to_chat(M, "[usr.client.ckey] has removed your OOC ban.") - else switch(alert("OOC ban [M.ckey]?",,"Yes","No")) - if("Yes") - switch(alert("Temporary Ban?",,"Yes","No", "Cancel")) - if("Yes") - var/mins = input(usr,"How long (in minutes)?","OOC Ban time",1440) as num|null - if(!mins) - return - if(mins >= 525600) mins = 525599 - var/reason = input(usr,"Reason?","reason","Shinposting") as text|null - if(!reason) - return - ban_unban_log_save("[usr.client.ckey] has banned [M.ckey]. - Reason: [reason] - This will be removed in [mins] minutes.") - to_chat(M, "You have been OOC banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "This is a temporary ooc ban, it will be removed in [mins] minutes.") - feedback_inc("ban_ooc_tmp",1) - DB_ban_record(BANTYPE_OOC_TEMP, M, mins, reason) - feedback_inc("ban_ooc_tmp_mins",mins) - if(config.banappeals) - to_chat(M, "To try to resolve this matter head to [config.banappeals] or consider not being a shithead in OOC") - else - to_chat(M, "No ban appeals URL has been set.") - log_admin("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - message_admins("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - - if("No") - var/reason = input(usr,"Reason?","reason","Shinposting") as text|null - if(!reason) - return - to_chat(M, "You have been ooc banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "This is a permanent ooc ban.") - if(config.banappeals) - to_chat(M, "To try to resolve this matter head to [config.banappeals] or consider not being a shithead in OOC") - else - to_chat(M, "No ban appeals URL has been set.") - ban_unban_log_save("[usr.client.ckey] has perma-ooc-banned [M.ckey]. - Reason: [reason] - This is a permanent ooc ban.") - log_admin("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis is a permanent ooc ban.") - message_admins("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis is a permanent ooc ban.") - feedback_inc("ban_ooc_perma",1) - DB_ban_record(BANTYPE_OOC_PERMA, M, -1, reason) - - if("Cancel") - return - ooc_ban(M) - return - if("No") - return - else - return - - else if(href_list["appearanceban"]) - if(!check_rights(R_BAN)) - return - var/mob/M = locate(href_list["appearanceban"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(!M.ckey) //sanity - to_chat(usr, "This mob has no ckey") - return - - var/banreason = appearance_isbanned(M) - if(banreason) - /* if(!config.ban_legacy_system) - to_chat(usr, "Unfortunately, database based unbanning cannot be done through this panel") - DB_ban_panel(M.ckey) - return */ - switch(alert("Reason: '[banreason]' Remove appearance ban?","Please Confirm","Yes","No")) - if("Yes") - ban_unban_log_save("[key_name(usr)] removed [key_name(M)]'s appearance ban") - log_admin("[key_name(usr)] removed [key_name(M)]'s appearance ban") - feedback_inc("ban_appearance_unban", 1) - DB_ban_unban(M.ckey, BANTYPE_APPEARANCE) - appearance_unban(M) - message_admins("[key_name_admin(usr)] removed [key_name_admin(M)]'s appearance ban", 1) - to_chat(M, "[usr.client.ckey] has removed your appearance ban.") - - else switch(alert("Appearance ban [M.ckey]?",,"Yes","No", "Cancel")) - if("Yes") - var/reason = input(usr,"Reason?","reason","Metafriender") as text|null - if(!reason) - return - ban_unban_log_save("[key_name(usr)] appearance banned [key_name(M)]. reason: [reason]") - log_admin("[key_name(usr)] appearance banned [key_name(M)]. \nReason: [reason]") - feedback_inc("ban_appearance",1) - DB_ban_record(BANTYPE_APPEARANCE, M, -1, reason) - appearance_fullban(M, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") - notes_add(M.ckey, "Appearance banned - [reason]") - message_admins("[key_name_admin(usr)] appearance banned [key_name_admin(M)]", 1) - to_chat(M, "You have been appearance banned by [usr.client.ckey].") - to_chat(M, "The reason is: [reason]") - to_chat(M, "Appearance ban can be lifted only upon request.") - if(config.banappeals) - to_chat(M, "To try to resolve this matter head to [config.banappeals]") - else - to_chat(M, "No ban appeals URL has been set.") - if("No") - return - - else if(href_list["jobban2"]) -// if(!check_rights(R_BAN)) return - - var/mob/M = locate(href_list["jobban2"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(!M.ckey) //sanity - to_chat(usr, "This mob has no ckey") - return - if(!job_master) - to_chat(usr, "Job Master has not been setup!") - return - - var/dat = "" - var/header = "Job-Ban Panel: [M.name]" - var/body - var/jobs = "" - - /***********************************WARNING!************************************ - The jobban stuff looks mangled and disgusting - But it looks beautiful in-game - -Nodrak - ************************************WARNING!***********************************/ - var/counter = 0 -//Regular jobs - //Command (Blue) - jobs += "" - jobs += "" - for(var/jobPos in command_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 6) //So things dont get squiiiiished! - jobs += "" - counter = 0 - jobs += "
    Command Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " - - //Security (Red) - counter = 0 - jobs += "" - jobs += "" - for(var/jobPos in security_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 5) //So things dont get squiiiiished! - jobs += "" - counter = 0 - jobs += "
    Security Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " - - //Engineering (Yellow) - counter = 0 - jobs += "" - jobs += "" - for(var/jobPos in engineering_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 5) //So things dont get squiiiiished! - jobs += "" - counter = 0 - jobs += "
    Engineering Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " - - //Medical (White) - counter = 0 - jobs += "" - jobs += "" - for(var/jobPos in medical_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 5) //So things dont get squiiiiished! - jobs += "" - counter = 0 - jobs += "
    Medical Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " - - //Science (Purple) - counter = 0 - jobs += "" - jobs += "" - for(var/jobPos in science_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 5) //So things dont get squiiiiished! - jobs += "" - counter = 0 - jobs += "
    Science Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " - - //Civilian (Grey) - counter = 0 - jobs += "" - jobs += "" - for(var/jobPos in civilian_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 5) //So things dont get squiiiiished! - jobs += "" - counter = 0 - - if(jobban_isbanned(M, "Internal Affairs Agent")) - jobs += "" - else - jobs += "" - - jobs += "
    Civilian Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    Internal Affairs AgentInternal Affairs Agent
    " - - //Non-Human (Green) - counter = 0 - jobs += "" - jobs += "" - for(var/jobPos in nonhuman_positions) - if(!jobPos) continue - var/datum/job/job = job_master.GetJob(jobPos) - if(!job) continue - - if(jobban_isbanned(M, job.title)) - jobs += "" - counter++ - else - jobs += "" - counter++ - - if(counter >= 5) //So things dont get squiiiiished! - jobs += "" - counter = 0 - - //pAI isn't technically a job, but it goes in here. - - if(jobban_isbanned(M, "pAI")) - jobs += "" - else - jobs += "" - if(jobban_isbanned(M, "AntagHUD")) - jobs += "" - else - jobs += "" - jobs += "
    Non-human Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    pAIpAIAntagHUDAntagHUD
    " - - //Antagonist (Orange) - var/isbanned_dept = jobban_isbanned(M, "Syndicate") - jobs += "" - jobs += "" - - //Traitor - if(jobban_isbanned(M, "traitor") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Changeling - if(jobban_isbanned(M, "changeling") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Nuke Operative - if(jobban_isbanned(M, "operative") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Revolutionary - if(jobban_isbanned(M, "revolutionary") || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries - - //Cultist - if(jobban_isbanned(M, "cultist") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Wizard - if(jobban_isbanned(M, "wizard") || isbanned_dept) - jobs += "" - else - jobs += "" - - //ERT - if(jobban_isbanned(M, "Emergency Response Team") || isbanned_dept) - jobs += "" - else - jobs += "" - - - //Vox Raider - if(jobban_isbanned(M, "Vox Raider") || isbanned_dept) - jobs += "" - else - jobs += "" - -/* //Malfunctioning AI //Removed Malf-bans because they're a pain to impliment - if(jobban_isbanned(M, "malf AI") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Alien - if(jobban_isbanned(M, "alien candidate") || isbanned_dept) - jobs += "" - else - jobs += "" - - //Infested Monkey - if(jobban_isbanned(M, "infested monkey") || isbanned_dept) - jobs += "" - else - jobs += "" -*/ - - jobs += "
    Antagonist Positions
    [replacetext("Traitor", " ", " ")][replacetext("Traitor", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Nuke Operative", " ", " ")][replacetext("Nuke Operative", " ", " ")][replacetext("Revolutionary", " ", " ")][replacetext("Revolutionary", " ", " ")]
    [replacetext("Cultist", " ", " ")][replacetext("Cultist", " ", " ")][replacetext("Wizard", " ", " ")][replacetext("Wizard", " ", " ")]Emergency Response TeamEmergency Response TeamVox RaiderVox Raider[replacetext("Malf AI", " ", " ")][replacetext("Malf AI", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Infested Monkey", " ", " ")][replacetext("Infested Monkey", " ", " ")]
    " - - //Other races (BLUE, because I have no idea what other color to make this) - jobs += "" - jobs += "" - - if(jobban_isbanned(M, "Dionaea")) - jobs += "" - else - jobs += "" - - jobs += "
    Other Races
    DionaeaDionaea
    " - - - body = "[jobs]" - dat = "[header][body]" - usr << browse(dat, "window=jobban2;size=800x490") - return - - //JOBBAN'S INNARDS - else if(href_list["jobban3"]) - if(!check_rights(R_BAN)) return - - var/mob/M = locate(href_list["jobban4"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(M != usr) //we can jobban ourselves - if(M.client && M.client.holder && (M.client.holder.rights & R_BAN)) //they can ban too. So we can't ban them - alert("You cannot perform this action. You must be of a higher administrative rank!") - return - - if(!job_master) - to_chat(usr, "Job Master has not been setup!") - return - - //get jobs for department if specified, otherwise just returnt he one job in a list. - var/list/joblist = list() - switch(href_list["jobban3"]) - if("commanddept") - for(var/jobPos in command_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("securitydept") - for(var/jobPos in security_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("engineeringdept") - for(var/jobPos in engineering_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("medicaldept") - for(var/jobPos in medical_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("sciencedept") - for(var/jobPos in science_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("civiliandept") - for(var/jobPos in civilian_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("nonhumandept") - joblist += "pAI" - for(var/jobPos in nonhuman_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - else - joblist += href_list["jobban3"] - - //Create a list of unbanned jobs within joblist - var/list/notbannedlist = list() - for(var/job in joblist) - if(!jobban_isbanned(M, job)) - notbannedlist += job - - //Banning comes first - if(notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban. - switch(alert("Temporary Ban?",,"Yes","No", "Cancel")) - if("Yes") - if(config.ban_legacy_system) - to_chat(usr, "Your server is using the legacy banning system, which does not support temporary job bans. Consider upgrading. Aborting ban.") - return - var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null - if(!mins) - return - var/reason = input(usr,"Reason?","Please State Reason","") as text|null - if(!reason) - return - - var/msg - for(var/job in notbannedlist) - ban_unban_log_save("[key_name(usr)] temp-jobbanned [key_name(M)] from [job] for [mins] minutes. reason: [reason]") - log_admin("[key_name(usr)] temp-jobbanned [key_name(M)] from [job] for [mins] minutes") - feedback_inc("ban_job_tmp",1) - DB_ban_record(BANTYPE_JOB_TEMP, M, mins, reason, job) - feedback_add_details("ban_job_tmp","- [job]") - jobban_fullban(M, job, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") //Legacy banning does not support temporary jobbans. - if(!msg) - msg = job - else - msg += ", [job]" - notes_add(M.ckey, "Banned from [msg] - [reason]") - message_admins("[key_name_admin(usr)] banned [key_name_admin(M)] from [msg] for [mins] minutes", 1) - to_chat(M, "You have been jobbanned by [usr.client.ckey] from: [msg].") - to_chat(M, "The reason is: [reason]") - to_chat(M, "This jobban will be lifted in [mins] minutes.") - href_list["jobban2"] = 1 // lets it fall through and refresh - return 1 - if("No") - var/reason = input(usr,"Reason?","Please State Reason","") as text|null - if(reason) - var/msg - for(var/job in notbannedlist) - ban_unban_log_save("[key_name(usr)] perma-jobbanned [key_name(M)] from [job]. reason: [reason]") - log_admin("[key_name(usr)] perma-banned [key_name(M)] from [job]") - feedback_inc("ban_job",1) - DB_ban_record(BANTYPE_JOB_PERMA, M, -1, reason, job) - feedback_add_details("ban_job","- [job]") - jobban_fullban(M, job, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") - if(!msg) msg = job - else msg += ", [job]" - notes_add(M.ckey, "Banned from [msg] - [reason]") - message_admins("[key_name_admin(usr)] banned [key_name_admin(M)] from [msg]", 1) - to_chat(M, "You have been jobbanned by [usr.client.ckey] from: [msg].") - to_chat(M, "The reason is: [reason]") - to_chat(M, "Jobban can be lifted only upon request.") - href_list["jobban2"] = 1 // lets it fall through and refresh - return 1 - if("Cancel") - return - - //Unbanning joblist - //all jobs in joblist are banned already OR we didn't give a reason (implying they shouldn't be banned) - if(joblist.len) //at least 1 banned job exists in joblist so we have stuff to unban. - if(!config.ban_legacy_system) - to_chat(usr, "Unfortunately, database based unbanning cannot be done through this panel") - DB_ban_panel(M.ckey) - return - var/msg - for(var/job in joblist) - var/reason = jobban_isbanned(M, job) - if(!reason) continue //skip if it isn't jobbanned anyway - switch(alert("Job: '[job]' Reason: '[reason]' Un-jobban?","Please Confirm","Yes","No")) - if("Yes") - ban_unban_log_save("[key_name(usr)] unjobbanned [key_name(M)] from [job]") - log_admin("[key_name(usr)] unbanned [key_name(M)] from [job]") - DB_ban_unban(M.ckey, BANTYPE_JOB_PERMA, job) - feedback_inc("ban_job_unban",1) - feedback_add_details("ban_job_unban","- [job]") - jobban_unban(M, job) - if(!msg) msg = job - else msg += ", [job]" - else - continue - if(msg) - message_admins("[key_name_admin(usr)] unbanned [key_name_admin(M)] from [msg]", 1) - to_chat(M, "You have been un-jobbanned by [usr.client.ckey] from [msg].") - href_list["jobban2"] = 1 // lets it fall through and refresh - return 1 - return 0 //we didn't do anything! - - else if(href_list["boot2"]) - var/mob/M = locate(href_list["boot2"]) - if (ismob(M)) - if(!check_if_greater_rights_than(M.client)) - return - to_chat(M, "You have been kicked from the server") - log_admin("[key_name(usr)] booted [key_name(M)].") - message_admins("[key_name_admin(usr)] booted [key_name_admin(M)].", 1) - //M.client = null - del(M.client) -/* - //Player Notes - else if(href_list["notes"]) - var/ckey = href_list["ckey"] - if(!ckey) - var/mob/M = locate(href_list["mob"]) - if(ismob(M)) - ckey = M.ckey - - switch(href_list["notes"]) - if("show") - notes_show(ckey) - if("add") - notes_add(ckey,href_list["text"]) - notes_show(ckey) - if("remove") - notes_remove(ckey,text2num(href_list["from"]),text2num(href_list["to"])) - notes_show(ckey) -*/ - else if(href_list["removejobban"]) - if(!check_rights(R_BAN)) return - - var/t = href_list["removejobban"] - if(t) - if((alert("Do you want to unjobban [t]?","Unjobban confirmation", "Yes", "No") == "Yes") && t) //No more misclicks! Unless you do it twice. - log_admin("[key_name(usr)] removed [t]") - message_admins("[key_name_admin(usr)] removed [t]", 1) - jobban_remove(t) - href_list["ban"] = 1 // lets it fall through and refresh - var/t_split = text2list(t, " - ") - var/key = t_split[1] - var/job = t_split[2] - DB_ban_unban(ckey(key), BANTYPE_JOB_PERMA, job) - - else if(href_list["newban"]) - if(!check_rights(R_BAN)) return - - var/mob/M = locate(href_list["newban"]) - if(!ismob(M)) return - - // now you can! if(M.client && M.client.holder) return //admins cannot be banned. Even if they could, the ban doesn't affect them anyway - - switch(alert("Temporary Ban?",,"Yes","No", "Cancel")) - if("Yes") - var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null - if(!mins) - return - if(mins >= 525600) mins = 525599 - var/reason = input(usr,"Reason?","reason","Griefer") as text|null - if(!reason) - return - AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins) - ban_unban_log_save("[usr.client.ckey] has banned [M.ckey]. - Reason: [reason] - This will be removed in [mins] minutes.") - to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "This is a temporary ban, it will be removed in [mins] minutes.") - feedback_inc("ban_tmp",1) - DB_ban_record(BANTYPE_TEMP, M, mins, reason) - feedback_inc("ban_tmp_mins",mins) - if(config.banappeals) - to_chat(M, "To try to resolve this matter head to [config.banappeals]") - else - to_chat(M, "No ban appeals URL has been set.") - log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - - del(M.client) - //del(M) // See no reason why to delete mob. Important stuff can be lost. And ban can be lifted before round ends. - if("No") - var/reason = input(usr,"Reason?","reason","Griefer") as text|null - if(!reason) - return - switch(alert(usr,"IP ban?",,"Yes","No","Cancel")) - if("Cancel") return - if("Yes") - AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0, M.lastKnownIP) - if("No") - AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0) - var/sticky = alert(usr,"Sticky Ban [M.ckey]? Use this only if you never intend to unban the player.","Sticky Icky","Yes", "No") == "Yes" - if(sticky) - world.SetConfig("keyban",M.ckey,"type=sticky&reason=[reason]&message=[reason]&admin=[ckey(usr.key)]") - message_admins("[key_name_admin(usr)] has sticky banned [key_name(M)].") - log_admin("[key_name(usr)] has sticky banned [key_name(M)].") - to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "This is a permanent ban.") - if(config.banappeals) - to_chat(M, "To try to resolve this matter head to [config.banappeals]") - else - to_chat(M, "No ban appeals URL has been set.") - ban_unban_log_save("[usr.client.ckey] has permabanned [M.ckey]. - Reason: [reason] - This is a permanent ban.") - log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") - message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") - feedback_inc("ban_perma",1) - DB_ban_record(BANTYPE_PERMA, M, -1, reason) - - del(M.client) - //del(M) - if("Cancel") - return - - else if(href_list["unjobbanf"]) - if(!check_rights(R_BAN)) return - - var/banfolder = href_list["unjobbanf"] - Banlist.cd = "/base/[banfolder]" - var/key = Banlist["key"] - if(alert(usr, "Are you sure you want to unban [key]?", "Confirmation", "Yes", "No") == "Yes") - if (RemoveBanjob(banfolder)) - unjobbanpanel() - else - alert(usr,"This ban has already been lifted / does not exist.","Error","Ok") - unjobbanpanel() - - else if(href_list["mute"]) - if(!check_rights(R_ADMIN)) return - - var/mob/M = locate(href_list["mute"]) - if(!ismob(M)) return - if(!M.client) return - - var/mute_type = href_list["mute_type"] - if(istext(mute_type)) mute_type = text2num(mute_type) - if(!isnum(mute_type)) return - - cmd_admin_mute(M, mute_type) - - else if(href_list["c_mode"]) - if(!check_rights(R_ADMIN)) return - - if(ticker && ticker.mode) - return alert(usr, "The game has already started.", null, null, null, null) - var/dat = {"What mode do you wish to play?
    "} - for(var/mode in config.modes) - dat += {"[config.mode_names[mode]]
    "} - dat += {"Secret
    "} - dat += {"Random
    "} - dat += {"Now: [master_mode]"} - usr << browse(dat, "window=c_mode") - - else if(href_list["f_secret"]) - if(!check_rights(R_ADMIN)) return - - if(ticker && ticker.mode) - return alert(usr, "The game has already started.", null, null, null, null) - if(master_mode != "secret") - return alert(usr, "The game mode has to be secret!", null, null, null, null) - var/dat = {"What game mode do you want to force secret to be? Use this if you want to change the game mode, but want the players to believe it's secret. This will only work if the current game mode is secret.
    "} - for(var/mode in config.modes) - dat += {"[config.mode_names[mode]]
    "} - dat += {"Random (default)
    "} - dat += {"Now: [secret_force_mode]"} - usr << browse(dat, "window=f_secret") - - else if(href_list["c_mode2"]) - if(!check_rights(R_ADMIN|R_SERVER)) return - - if (ticker && ticker.mode) - return alert(usr, "The game has already started.", null, null, null, null) - master_mode = href_list["c_mode2"] - log_admin("[key_name(usr)] set the mode as [master_mode].") - message_admins("[key_name_admin(usr)] set the mode as [master_mode].", 1) - to_chat(world, "The mode is now: [master_mode]") - Game() // updates the main game menu - world.save_mode(master_mode) - .(href, list("c_mode"=1)) - - else if(href_list["f_secret2"]) - if(!check_rights(R_ADMIN|R_SERVER)) return - - if(ticker && ticker.mode) - return alert(usr, "The game has already started.", null, null, null, null) - if(master_mode != "secret") - return alert(usr, "The game mode has to be secret!", null, null, null, null) - secret_force_mode = href_list["f_secret2"] - log_admin("[key_name(usr)] set the forced secret mode as [secret_force_mode].") - message_admins("[key_name_admin(usr)] set the forced secret mode as [secret_force_mode].", 1) - Game() // updates the main game menu - .(href, list("f_secret"=1)) - - else if(href_list["monkeyone"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["monkeyone"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - log_admin("[key_name(usr)] attempting to monkeyize [key_name(H)]") - message_admins("[key_name_admin(usr)] attempting to monkeyize [key_name_admin(H)]", 1) - var/mob/M = H.monkeyize() - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["corgione"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["corgione"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - log_admin("[key_name(usr)] attempting to corgize [key_name(H)]") - message_admins("[key_name_admin(usr)] attempting to corgize [key_name_admin(H)]", 1) - var/mob/M = H.corgize() - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["forcespeech"]) - if(!check_rights(R_FUN)) return - - var/mob/M = locate(href_list["forcespeech"]) - if(!ismob(M)) - to_chat(usr, "this can only be used on instances of type /mob") - - var/speech = input("What will [key_name(M)] say?.", "Force speech", "")// Don't need to sanitize, since it does that in say(), we also trust our admins. - if(!speech) return - M.say(speech) - speech = sanitize(speech) // Nah, we don't trust them - log_admin("[key_name(usr)] forced [key_name(M)] to say: [speech]") - message_admins("[key_name_admin(usr)] forced [key_name_admin(M)] to say: [speech]") - - else if(href_list["sendtoprison"]) - // Reworked to be useful for investigating shit. - if(!check_rights(R_ADMIN)) - return - - if(alert(usr, "Warp to prison?", "Message", "Yes", "No") != "Yes") - return - - var/mob/M = locate(href_list["sendtoprison"]) - - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(istype(M, /mob/living/silicon/ai)) - to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") - return - - var/turf/prison_cell = pick(prisonwarp) - - if(!prison_cell) - return - - /* - var/obj/structure/closet/secure_closet/brig/locker = new /obj/structure/closet/secure_closet/brig(prison_cell) - locker.opened = 0 - locker.locked = 1 - - //strip their stuff and stick it in the crate - for(var/obj/item/I in M) - M.u_equip(I,1) - if(I) - I.loc = locker - I.layer = initial(I.layer) - //I.dropped(M) - - M.update_icons() - */ - - //so they black out before warping - M.Paralyse(5) - M.visible_message( - "You hear the sound of cell doors slamming shut, and [M.name] suddenly vanishes!", - "You hear the sound of cell doors slamming shut!") - - sleep(5) - - if(!M) - return - - // TODO: play sound here. Thinking of using Wolfenstein 3D's cell door closing sound. - - M.loc = prison_cell - - /* - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/prisoner = M - prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(prisoner), slot_w_uniform) - prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes) - */ - - to_chat(M, "You have been sent to the prison station!") - log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") - message_admins("[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1) - - else if(href_list["tdome1"] || href_list["tdome2"]) - if(!check_rights(R_FUN)) return - - if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") - return - - var/mob/M = null - var/team = "" - - if(href_list["tdome1"]) - team = "Green" - M = locate(href_list["tdome1"]) - else if (href_list["tdome2"]) - team = "Red" - M = locate(href_list["tdome2"]) - - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(istype(M, /mob/living/silicon/ai)) - to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") - return - - var/obj/item/packobelongings/pack = null - - switch(team) - if("Green") - pack = new /obj/item/packobelongings/green(M.loc) - pack.x = map.tDomeX+2 - if("Red") - pack = new /obj/item/packobelongings/red(M.loc) - pack.x = map.tDomeX-2 - - pack.z = map.tDomeZ //the players' belongings are stored there, in the Thunderdome Admin lodge. - pack.y = map.tDomeY - - pack.name = "[M.real_name]'s belongings" - - for(var/obj/item/I in M) - if(istype(I,/obj/item/clothing/glasses)) - var/obj/item/clothing/glasses/G = I - if(G.prescription) - continue - M.u_equip(I,1) - if(I) - I.loc = M.loc - I.layer = initial(I.layer) - //I.dropped(M) - I.loc = pack - - var/obj/item/weapon/card/id/thunderdome/ident = null - - switch(team) - if("Green") - ident = new /obj/item/weapon/card/id/thunderdome/green(M) - ident.name = "[M.real_name]'s Thunderdome Green ID" - if("Red") - ident = new /obj/item/weapon/card/id/thunderdome/red(M) - ident.name = "[M.real_name]'s Thunderdome Red ID" - - if(!iscarbon(M)) - qdel(ident) - - switch(team) - if("Green") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/green(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) - H.equip_to_slot_or_del(ident, slot_wear_id) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/green(H), slot_belt) - H.regenerate_icons() - else if(ismonkey(M)) - var/mob/living/carbon/monkey/K = M - var/obj/item/clothing/monkeyclothes/jumpsuit_green/JS = new /obj/item/clothing/monkeyclothes/jumpsuit_green(K) - var/obj/item/clothing/monkeyclothes/olduniform = null - var/obj/item/clothing/monkeyclothes/oldhat = null - if(K.uniform) - olduniform = K.uniform - K.uniform = null - olduniform.loc = pack - K.uniform = JS - K.uniform.loc = K - if(K.hat) - oldhat = K.hat - K.hat = null - oldhat.loc = pack - K.equip_to_slot_or_del(ident, slot_r_hand) - K.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/green(K), slot_l_hand) - K.regenerate_icons() - - if("Red") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/red(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) - H.equip_to_slot_or_del(ident, slot_wear_id) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/red(H), slot_belt) - H.regenerate_icons() - else if(ismonkey(M)) - var/mob/living/carbon/monkey/K = M - var/obj/item/clothing/monkeyclothes/jumpsuit_red/JS = new /obj/item/clothing/monkeyclothes/jumpsuit_red(K) - var/obj/item/clothing/monkeyclothes/olduniform = null - var/obj/item/clothing/monkeyclothes/oldhat = null - if(K.uniform) - olduniform = K.uniform - K.uniform = null - olduniform.loc = pack - K.uniform = JS - K.uniform.loc = K - if(K.hat) - oldhat = K.hat - K.hat = null - oldhat.loc = pack - K.equip_to_slot_or_del(ident, slot_r_hand) - K.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/red(K), slot_l_hand) - K.regenerate_icons() - - if(pack.contents.len == 0) - qdel(pack) - - switch(team) - if("Green") - log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team Green)") - message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team Green)", 1) - M.loc = pick(tdome1) - if("Red") - log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team Red)") - message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team Red)", 1) - M.loc = pick(tdome2) - - to_chat(M, "You have been chosen to fight for the [team] Team. [pick(\ - "The wheel of fate is turning!",\ - "Heaven or Hell!",\ - "Set Spell Card!",\ - "Hologram Summer Again!",\ - "Get ready for the next battle!",\ - "Fight for your life!",\ - )]") - - else if(href_list["tdomeadmin"]) - if(!check_rights(R_FUN)) return - - if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") - return - - var/mob/M = locate(href_list["tdomeadmin"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(istype(M, /mob/living/silicon/ai)) - to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") - return - - M.Paralyse(5) - sleep(5) - M.loc = pick(tdomeadmin) - spawn(50) - to_chat(M, "You have been sent to the Thunderdome.") - log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Admin.)") - message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Admin.)", 1) - - else if(href_list["tdomeobserve"]) - if(!check_rights(R_FUN)) return - - if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") - return - - var/mob/M = locate(href_list["tdomeobserve"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - if(istype(M, /mob/living/silicon/ai)) - to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") - return - - for(var/obj/item/I in M) - M.u_equip(I,1) - if(I) - I.loc = M.loc - I.layer = initial(I.layer) - //I.dropped(M) - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/observer = M - observer.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket(observer), slot_w_uniform) - observer.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(observer), slot_shoes) - M.Paralyse(5) - sleep(5) - M.loc = pick(tdomeobserve) - spawn(50) - to_chat(M, "You have been sent to the Thunderdome.") - log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Observer.)") - message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Observer.)", 1) - - else if(href_list["revive"]) - if(!check_rights(R_REJUVINATE)) return - - var/mob/living/L = locate(href_list["revive"]) - if(!istype(L)) - to_chat(usr, "This can only be used on instances of type /mob/living") - return - - if(config.allow_admin_rev) - L.revive(0) - message_admins("Admin [key_name_admin(usr)] healed / revived [key_name_admin(L)]!", 1) - log_admin("[key_name(usr)] healed / revived [key_name(L)]") - else - to_chat(usr, "Admin Rejuvinates have been disabled") - - else if(href_list["makeai"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makeai"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - message_admins("Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!", 1) - log_admin("[key_name(usr)] AIized [key_name(H)]") - var/mob/M = H.AIize() - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["makealien"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makealien"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - var/mob/M = usr.client.cmd_admin_alienize(H) - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["makeslime"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makeslime"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - var/mob/M = usr.client.cmd_admin_slimeize(H) - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["makecluwne"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makecluwne"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - var/mob/M = usr.client.cmd_admin_cluwneize(H) - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["makerobot"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makerobot"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - var/mob/M = usr.client.cmd_admin_robotize(H) - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["makemommi"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makemommi"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - var/mob/M = usr.client.cmd_admin_mommify(H) - if(M) - if(M.client == CLIENT) usr = M //We probably transformed ourselves - show_player_panel(M) - - else if(href_list["makeanimal"]) - if(!check_rights(R_SPAWN)) return - - var/mob/M = locate(href_list["makeanimal"]) - if(istype(M, /mob/new_player)) - to_chat(usr, "This cannot be used on instances of type /mob/new_player") - return - - var/mob/new_mob = usr.client.cmd_admin_animalize(M) - if(new_mob && new_mob != M) - if(new_mob.client == CLIENT) usr = new_mob //We probably transformed ourselves - show_player_panel(new_mob) - - else if(href_list["togmutate"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["togmutate"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - var/block=text2num(href_list["block"]) - //testing("togmutate([href_list["block"]] -> [block])") - usr.client.cmd_admin_toggle_block(H,block) - show_player_panel(H) - //H.regenerate_icons() - -/***************** BEFORE************** - - if (href_list["l_players"]) - var/dat = "Name/Real Name/Key/IP:
    " - for(var/mob/M in world) - var/foo = "" - if (ismob(M) && M.client) - if(!M.client.authenticated && !M.client.authenticating) - foo += text("\[ Authorize | ", src, M) - else - foo += text("\[ Authorized | ") - if(M.start) - if(!istype(M, /mob/living/carbon/monkey)) - foo += text("Monkeyize | ", src, M) - else - foo += text("Monkeyized | ") - if(istype(M, /mob/living/silicon/ai)) - foo += text("Is an AI | ") - else - foo += text("Make AI | ", src, M) - if(M.z != 2) - foo += text("Prison | ", src, M) - foo += text("Maze | ", src, M) - else - foo += text("On Z = 2 | ") - else - foo += text("Hasn't Entered Game | ") - foo += text("Heal/Revive | ", src, M) - - foo += text("Say \]", src, M) - dat += text("N: [] R: [] (K: []) (IP: []) []
    ", M.name, M.real_name, (M.client ? M.client : "No client"), M.lastKnownIP, foo) - - usr << browse(dat, "window=players;size=900x480") - -*****************AFTER******************/ - -// Now isn't that much better? IT IS NOW A PROC, i.e. kinda like a big panel like unstable - - else if(href_list["adminplayeropts"]) - var/mob/M = locate(href_list["adminplayeropts"]) - show_player_panel(M) - - else if(href_list["adminplayerobservejump"]) - if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN)) return - - var/mob/M = locate(href_list["adminplayerobservejump"]) - - var/client/C = usr.client - if(!isobserver(usr)) C.admin_ghost() - sleep(2) - if(C) C.jumptomob(M) - - else if(href_list["check_antagonist"]) - check_antagonists() - - else if(href_list["cult_nextobj"]) - if(alert(usr, "Validate the current Cult objective and unlock the next one?", "Cult Cheat Code", "Yes", "No") != "Yes") - return - - var/datum/game_mode/cult/mode_ticker = ticker.mode - mode_ticker.bypass_phase() - message_admins("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.") - log_admin("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.") - check_antagonists() - - else if(href_list["cult_mindspeak"]) - var/input = stripped_input(usr, "Communicate to all the cultists with the voice of Nar-Sie", "Voice of Nar-Sie", "") - if(!input) - return - - for(var/datum/mind/H in ticker.mode.cult) - if (H.current) - to_chat(H.current, "Nar-Sie murmurs, [input]") - - for(var/mob/dead/observer/O in player_list) - to_chat(O, "Nar-Sie murmurs, [input]") - - message_admins("Admin [key_name_admin(usr)] has talked with the Voice of Nar-Sie.") - log_narspeak("[key_name(usr)] Voice of Nar-Sie: [input]") - - else if(href_list["cult_privatespeak"]) - var/mob/M = locate(href_list["cult_privatespeak"]) - if(!M) - return - - var/input = stripped_input(usr, "Whisper to [M.real_name] with the voice of Nar-Sie", "Voice of Nar-Sie", "") - if(!input) - return - - to_chat(M, "Nar-Sie whispers to you, [input]") - - for(var/mob/dead/observer/O in player_list) - to_chat(O, "Nar-Sie whispers to [M.real_name], [input]") - - message_admins("Admin [key_name_admin(usr)] has talked with the Voice of Nar-Sie.") - - else if(href_list["adminplayerobservecoodjump"]) - if(!check_rights(R_ADMIN)) return - - var/x = text2num(href_list["X"]) - var/y = text2num(href_list["Y"]) - var/z = text2num(href_list["Z"]) - - var/client/C = usr.client - if(!isobserver(usr)) C.admin_ghost() - sleep(2) - C.jumptocoord(x,y,z) - - else if(href_list["adminchecklaws"]) - output_ai_laws() - - else if(href_list["adminmoreinfo"]) - var/mob/M = locate(href_list["adminmoreinfo"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - var/location_description = "" - var/special_role_description = "" - var/health_description = "" - var/gender_description = "" - var/species_description = "Not A Human" - var/turf/T = get_turf(M) - - //Location - if(isturf(T)) - if(isarea(T.loc)) - location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area [T.loc])" - else - location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])" - - //Job + antagonist - if(M.mind) - special_role_description = "Role: [M.mind.assigned_role]; Antagonist: [M.mind.special_role]; Has been rev: [(M.mind.has_been_rev)?"Yes":"No"]" - else - special_role_description = "Role: Mind datum missing Antagonist: Mind datum missing; Has been rev: Mind datum missing;" - - //Health - if(isliving(M)) - var/mob/living/L = M - var/status - switch (M.stat) - if (0) status = "Alive" - if (1) status = "Unconscious" - if (2) status = "Dead" - health_description = "Status = [status]" - health_description += "
    Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]" - else - health_description = "This mob type has no health to speak of." - - //Gener - switch(M.gender) - if(MALE,FEMALE) gender_description = "[M.gender]" - else gender_description = "[M.gender]" - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - species_description = "[H.species ? H.species.name : "No Species"]" - to_chat(src.owner, "Info about [M.name]: ") - to_chat(src.owner, "Mob type = [M.type]; Species = [species_description]; Gender = [gender_description]; Damage = [health_description];") - to_chat(src.owner, "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];") - to_chat(src.owner, "Location = [location_description];") - to_chat(src.owner, "[special_role_description]") - to_chat(src.owner, "(PM) (PP) (VV) (SM) (JMP) (CA)") - - else if(href_list["adminspawncookie"]) - if(!check_rights(R_ADMIN|R_FUN)) return - - var/mob/living/carbon/human/H = locate(href_list["adminspawncookie"]) - if(!ishuman(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - H.equip_to_slot_or_del( new /obj/item/weapon/reagent_containers/food/snacks/cookie(H), slot_l_hand ) - if(!(istype(H.l_hand,/obj/item/weapon/reagent_containers/food/snacks/cookie))) - H.equip_to_slot_or_del( new /obj/item/weapon/reagent_containers/food/snacks/cookie(H), slot_r_hand ) - if(!(istype(H.r_hand,/obj/item/weapon/reagent_containers/food/snacks/cookie))) - log_admin("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") - message_admins("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") - return - else - H.update_inv_r_hand()//To ensure the icon appears in the HUD - else - H.update_inv_l_hand() - log_admin("[key_name(H)] got their cookie, spawned by [key_name(src.owner)]") - message_admins("[key_name(H)] got their cookie, spawned by [key_name(src.owner)]") - feedback_inc("admin_cookies_spawned",1) - to_chat(H, "Your prayers have been answered!! You received the best cookie!") - - else if(href_list["BlueSpaceArtillery"]) - if(!check_rights(R_ADMIN|R_FUN)) return - - var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) - if(!isliving(M)) - to_chat(usr, "This can only be used on instances of type /mob/living") - return - - if(alert(src.owner, "Are you sure you wish to hit [key_name(M)] with Blue Space Artillery?", "Confirm Firing?" , "Yes" , "No") != "Yes") - return - - if(BSACooldown) - to_chat(src.owner, "Standby! Reload cycle in progress! Gunnary crews ready in five seconds!") - return - - BSACooldown = 1 - spawn(50) - BSACooldown = 0 - - to_chat(M, "You've been hit by bluespace artillery!") - log_admin("[key_name(M)] has been hit by Bluespace Artillery fired by [src.owner]") - message_admins("[key_name(M)] has been hit by Bluespace Artillery fired by [src.owner]") - - var/obj/effect/stop/S - S = new /obj/effect/stop - S.victim = M - S.loc = M.loc - spawn(20) - del(S) - - var/turf/simulated/floor/T = get_turf(M) - if(istype(T)) - if(prob(80)) T.break_tile_to_plating() - else T.break_tile() - - if(M.health == 1) - M.gib() - else - M.adjustBruteLoss( min( 99 , (M.health - 1) ) ) - M.Stun(20) - M.Weaken(20) - M.stuttering = 20 - - else if(href_list["CentcommReply"]) - var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - if(!istype(H.ears, /obj/item/device/radio/headset)) - to_chat(usr, "The person you are trying to contact is not wearing a headset") - return - - var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from Centcomm", "") - if(!input) return - - to_chat(src.owner, "You sent [input] to [H] via a secure channel.") - log_admin("[src.owner] replied to [key_name(H)]'s Centcomm message with the message [input].") - message_admins("[src.owner] replied to [key_name(H)]'s Centcom message with: \"[input]\"") - to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows. \"[input]\" Message ends.\"") - - else if(href_list["SyndicateReply"]) - var/mob/living/carbon/human/H = locate(href_list["SyndicateReply"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - if(!istype(H.ears, /obj/item/device/radio/headset)) - to_chat(usr, "The person you are trying to contact is not wearing a headset") - return - - var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from The Syndicate", "") - if(!input) return - - to_chat(src.owner, "You sent [input] to [H] via a secure channel.") - log_admin("[src.owner] replied to [key_name(H)]'s Syndicate message with the message [input].") - to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from your benefactor. Message as follows, agent. \"[input]\" Message ends.\"") - - else if(href_list["CentcommFaxView"]) - var/obj/item/weapon/paper/P = locate(href_list["CentcommFaxView"]) - var/info_2 = "" - if(P.img) - usr << browse_rsc(P.img.img, "tmp_photo.png") - info_2 = "
    " - usr << browse("Centcomm Fax Message[info_2][P.info][P.stamps]", "window=Centcomm Fax Message") - - else if(href_list["CentcommFaxReply"]) - var/mob/living/carbon/human/H = locate(href_list["CentcommFaxReply"]) - - - var/sent = input(src.owner, "Please enter a message to reply to [key_name(H)] via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
    for line breaks.", "Outgoing message from Centcomm", "") as message|null - if(!sent) return - - var/sentname = input(src.owner, "Pick a title for the report", "Title") as text|null - - SendFax(sent, sentname, centcomm = 1) - - to_chat(src.owner, "Message reply to transmitted successfully.") - log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [sent]") - message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]", 1) - - - else if(href_list["jumpto"]) - if(!check_rights(R_ADMIN)) return - - var/mob/M = locate(href_list["jumpto"]) - usr.client.jumptomob(M) - - else if(href_list["getmob"]) - if(!check_rights(R_ADMIN)) return - - if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") return - var/mob/M = locate(href_list["getmob"]) - usr.client.Getmob(M) - - else if(href_list["sendmob"]) - if(!check_rights(R_ADMIN)) return - - var/mob/M = locate(href_list["sendmob"]) - usr.client.sendmob(M) - - else if(href_list["narrateto"]) - if(!check_rights(R_ADMIN)) return - - var/mob/M = locate(href_list["narrateto"]) - usr.client.cmd_admin_direct_narrate(M) - - else if(href_list["subtlemessage"]) - if(!check_rights(R_ADMIN)) return - - var/mob/M = locate(href_list["subtlemessage"]) - usr.client.cmd_admin_subtle_message(M) - - else if(href_list["rapsheet"]) - checkSessionKey() - // build the link - //var/dat = "[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]" - //if(href_list["rsckey"]) - //. dat += "&ckey=[href_list["rsckey"]]" -// to_chat(usr, link(dat)) - usr << link(getVGPanel("rapsheet", admin = 1, query = list("ckey" = href_list["rsckey"]))) - return - - else if(href_list["bansheet"]) - //checkSessionKey() -// to_chat(usr, link("[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]")) - usr << link(getVGPanel("rapsheet", admin = 1)) - return - - else if(href_list["traitor"]) - if(!check_rights(R_ADMIN|R_MOD)) return - - if(!ticker || !ticker.mode) - alert("The game hasn't started yet!") - return - - var/mob/M = locate(href_list["traitor"]) - if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob.") - return - show_traitor_panel(M) - - // /vg/ - else if(href_list["set_base_laws"]) - if(!check_rights(R_FUN)) - to_chat(usr, "You don't have +FUN. Go away.") - return - var/lawtypes = typesof(/datum/ai_laws) - /datum/ai_laws - var/selected_law = input("Select the default lawset desired.","Lawset Selection",null) as null|anything in lawtypes - if(!selected_law) return - var/subject="Unknown" - switch(href_list["set_base_laws"]) - if("ai") - base_law_type = selected_law - subject = "AIs and Cyborgs" - if("mommi") - mommi_base_law_type = selected_law - subject = "MoMMIs" - to_chat(usr, "New [subject] will spawn with the [selected_law] lawset.") - log_admin("[key_name(src.owner)] set the default laws of [subject] to: [selected_law]") - message_admins("[key_name_admin(src.owner)] set the default laws of [subject] to: [selected_law]", 1) - lawchanges.Add("[key_name_admin(src.owner)] set the default laws of [subject] to: [selected_law]") - - else if(href_list["create_object"]) - if(!check_rights(R_SPAWN)) return - return create_object(usr) - - else if(href_list["quick_create_object"]) - if(!check_rights(R_SPAWN)) return - return quick_create_object(usr) - - else if(href_list["create_turf"]) - if(!check_rights(R_SPAWN)) return - return create_turf(usr) - - else if(href_list["create_mob"]) - if(!check_rights(R_SPAWN)) return - return create_mob(usr) - - else if(href_list["object_list"]) //this is the laggiest thing ever - if(!check_rights(R_SPAWN)) return - - if(!config.allow_admin_spawning) - to_chat(usr, "Spawning of items is not allowed.") - return - - var/atom/loc = usr.loc - - var/dirty_paths - if (istext(href_list["object_list"])) - dirty_paths = list(href_list["object_list"]) - else if (istype(href_list["object_list"], /list)) - dirty_paths = href_list["object_list"] - - var/paths = list() - var/removed_paths = list() - - for(var/dirty_path in dirty_paths) - var/path = text2path(dirty_path) - if(!path) - removed_paths += dirty_path - continue - else if(!ispath(path, /obj) && !ispath(path, /turf) && !ispath(path, /mob)) - removed_paths += dirty_path - continue - else if(ispath(path, /obj/item/weapon/gun/energy/pulse_rifle)) - if(!check_rights(R_FUN,0)) - removed_paths += dirty_path - continue - else if(ispath(path, /obj/effect/bhole)) - if(!check_rights(R_FUN,0)) - removed_paths += dirty_path - continue - paths += path - - if(!paths) - alert("The path list you sent is empty") - return - if(length(paths) > 5) - alert("Select fewer object types, (max 5)") - return - else if(length(removed_paths)) - alert("Removed:\n" + list2text(removed_paths, "\n")) - - var/list/offset = text2list(href_list["offset"],",") - var/number = Clamp(text2num(href_list["object_count"]), 1, 100) - var/X = offset.len > 0 ? text2num(offset[1]) : 0 - var/Y = offset.len > 1 ? text2num(offset[2]) : 0 - var/Z = offset.len > 2 ? text2num(offset[3]) : 0 - var/tmp_dir = href_list["object_dir"] - var/obj_dir = tmp_dir ? text2num(tmp_dir) : 2 - if(!obj_dir || !(obj_dir in alldirs)) - obj_dir = 2 - var/obj_name = sanitize(href_list["object_name"]) - var/where = href_list["object_where"] - if (!( where in list("onfloor","inhand","inmarked") )) - where = "onfloor" - - if( where == "inhand" ) - to_chat(usr, "Support for inhand not available yet. Will spawn on floor.") - where = "onfloor" - - if ( where == "inhand" ) //Can only give when human or monkey - if ( !( ishuman(usr) || ismonkey(usr) ) ) - to_chat(usr, "Can only spawn in hand when you're a human or a monkey.") - where = "onfloor" - else if ( usr.get_active_hand() ) - to_chat(usr, "Your active hand is full. Spawning on floor.") - where = "onfloor" - - if ( where == "inmarked" ) - if ( !marked_datum ) - to_chat(usr, "You don't have any object marked. Abandoning spawn.") - return - else - if ( !istype(marked_datum,/atom) ) - to_chat(usr, "The object you have marked cannot be used as a target. Target must be of type /atom. Abandoning spawn.") - return - - var/atom/target //Where the object will be spawned - switch ( where ) - if ( "onfloor" ) - switch (href_list["offset_type"]) - if ("absolute") - target = locate(0 + X,0 + Y,0 + Z) - if ("relative") - target = locate(loc.x + X,loc.y + Y,loc.z + Z) - if ( "inmarked" ) - target = marked_datum - - if(target) - for (var/path in paths) - for (var/i = 0; i < number; i++) - if(path in typesof(/turf)) - var/turf/O = target - var/turf/N = O.ChangeTurf(path) - if(N) - if(obj_name) - N.name = obj_name - else - var/atom/O = new path(target) - if(O) - O.dir = obj_dir - if(obj_name) - O.name = obj_name - if(istype(O,/mob)) - var/mob/M = O - M.real_name = obj_name - - if (number == 1) - log_admin("[key_name(usr)] created a [english_list(paths)] at [formatJumpTo(get_turf(usr))]") - for(var/path in paths) - if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created a [english_list(paths)] at [formatJumpTo(get_turf(usr))]", 1) - break - else - log_admin("[key_name(usr)] created [number]ea [english_list(paths)] at [formatJumpTo(get_turf(usr))]") - for(var/path in paths) - if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)] at [formatJumpTo(get_turf(usr))]", 1) - break - return - - else if(href_list["secretsfun"]) - if(!check_rights(R_FUN)) return - - var/ok = 0 - switch(href_list["secretsfun"]) - if("sec_clothes") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SC") - for(var/obj/item/clothing/under/O in world) - del(O) - ok = 1 - if("sec_all_clothes") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SAC") - for(var/obj/item/clothing/O in world) - del(O) - ok = 1 - if("sec_classic1") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SC1") - for(var/obj/item/clothing/suit/fire/O in world) - del(O) - for(var/obj/structure/grille/O in world) - del(O) -/* for(var/obj/machinery/vehicle/pod/O in world) - for(var/mob/M in src) - M.loc = src.loc - if (M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = M - del(O) - ok = 1*/ - if("monkey") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","M") - for(var/mob/living/carbon/human/H in mob_list) - spawn(0) - H.monkeyize() - ok = 1 - if("corgi") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","M") - for(var/mob/living/carbon/human/H in mob_list) - spawn(0) - H.corgize() - ok = 1 - if("striketeam") - if(usr.client.strike_team()) - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Strike") - if("tripleAI") - usr.client.triple_ai() - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TriAI") - if("gravity") - if(!(ticker && ticker.mode)) - to_chat(usr, "Please wait until the game starts! Not sure how it will work otherwise.") - return - gravity_is_on = !gravity_is_on - for(var/area/A in areas) - A.gravitychange(gravity_is_on,A) - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Grav") - if(gravity_is_on) - log_admin("[key_name(usr)] toggled gravity on.", 1) - message_admins("[key_name_admin(usr)] toggled gravity on.", 1) - command_alert("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") - else - log_admin("[key_name(usr)] toggled gravity off.", 1) - message_admins("[key_name_admin(usr)] toggled gravity off.", 1) - command_alert("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") - if("wave") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Meteor") - log_admin("[key_name(usr)] spawned a meteor wave", 1) - message_admins("[key_name_admin(usr)] spawned a meteor wave.", 1) - new /datum/event/meteor_wave - if("goblob") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Blob") - log_admin("[key_name(usr)] spawned a blob", 1) - message_admins("[key_name_admin(usr)] spawned a blob.", 1) - new /datum/event/blob - - if("aliens") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Aliens") - log_admin("[key_name(usr)] spawned an alien infestation", 1) - message_admins("[key_name_admin(usr)] attempted an alien infestation", 1) - new /datum/event/alien_infestation - - - if("power") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","P") - log_admin("[key_name(usr)] made all areas powered", 1) - message_admins("[key_name_admin(usr)] made all areas powered", 1) - power_restore() - if("unpower") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","UP") - log_admin("[key_name(usr)] made all areas unpowered", 1) - message_admins("[key_name_admin(usr)] made all areas unpowered", 1) - power_failure() - if("quickpower") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","QP") - log_admin("[key_name(usr)] made all SMESs powered", 1) - message_admins("[key_name_admin(usr)] made all SMESs powered", 1) - power_restore_quick() - if("activateprison") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","AP") - to_chat(world, "Transit signature detected.") - to_chat(world, "Incoming shuttle.") - /* - var/A = locate(/area/shuttle_prison) - for(var/atom/movable/AM as mob|obj in A) - AM.z = 1 - AM.Move() - */ - message_admins("[key_name_admin(usr)] sent the prison shuttle to the station.", 1) - if("deactivateprison") - /* - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","DP") - var/A = locate(/area/shuttle_prison) - for(var/atom/movable/AM as mob|obj in A) - AM.z = 2 - AM.Move() - */ - message_admins("[key_name_admin(usr)] sent the prison shuttle back.", 1) - if("toggleprisonstatus") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TPS") - for(var/obj/machinery/computer/prison_shuttle/PS in machines) - PS.allowedtocall = !(PS.allowedtocall) - message_admins("[key_name_admin(usr)] toggled status of prison shuttle to [PS.allowedtocall].", 1) - if ("prisonwarp") - if (!ticker) - alert("The game hasn't started yet!", null, null, null, null, null) - return - - feedback_inc("admin_secrets_fun_used", 1) - - feedback_add_details("admin_secrets_fun_used", "PW") - - message_admins("[key_name_admin(usr)] teleported all players to the prison station.", 1) - - var/security - - for (var/mob/living/carbon/human/H in mob_list) - if (H) - if (H in prisonwarped) // don't warp them if they aren't ready or are already there - continue - - security = FALSE - - H.Paralyse(5) - - var/obj/item/weapon/card/id/id = H.get_id_card() - - if(id) - if (access_security in id.access) - security = TRUE - - if (!security) - // strip their stuff before they teleport into a cell :downs: - for (var/obj/item/I in H.get_all_slots()) - H.drop_from_inventory(I) - - H.loc = pick(prisonwarp) // teleport person to cell - - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/prisoner(H), slot_w_uniform) - - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) - else - H.loc = pick(prisonsecuritywarp) // teleport security person - - prisonwarped += H - if("traitor_all") - if(!ticker) - alert("The game hasn't started yet!") - return - var/objective = copytext(sanitize(input("Enter an objective")),1,MAX_MESSAGE_LEN) - if(!objective) - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TA([objective])") - for(var/mob/living/carbon/human/H in player_list) - if(H.stat == 2 || !H.client || !H.mind) continue - if(is_special_character(H)) continue - //traitorize(H, objective, 0) - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - var/datum/objective/new_objective = new - new_objective.owner = H - new_objective.explanation_text = objective - H.mind.objectives += new_objective - ticker.mode.greet_traitor(H.mind) - //ticker.mode.forge_traitor_objectives(H.mind) - ticker.mode.finalize_traitor(H.mind) - for(var/mob/living/silicon/A in player_list) - ticker.mode.traitors += A.mind - A.mind.special_role = "traitor" - var/datum/objective/new_objective = new - new_objective.owner = A - new_objective.explanation_text = objective - A.mind.objectives += new_objective - ticker.mode.greet_traitor(A.mind) - ticker.mode.finalize_traitor(A.mind) - message_admins("[key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]", 1) - log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") - if("moveadminshuttle") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShA") - move_admin_shuttle() - message_admins("[key_name_admin(usr)] moved the centcom administration shuttle", 1) - log_admin("[key_name(usr)] moved the centcom administration shuttle") - if("moveferry") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShF") - if(!transport_shuttle || !transport_shuttle.linked_area) - to_chat(usr, "There is no transport shuttle!") - return - - transport_shuttle.move(usr) - - message_admins("[key_name_admin(usr)] moved the centcom ferry", 1) - log_admin("[key_name(usr)] moved the centcom ferry") - if("movealienship") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShX") - move_alien_ship() - message_admins("[key_name_admin(usr)] moved the alien dinghy", 1) - log_admin("[key_name(usr)] moved the alien dinghy") - if("togglebombcap") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BC") - switch(MAX_EXPLOSION_RANGE) - if(14) MAX_EXPLOSION_RANGE = 16 - if(16) MAX_EXPLOSION_RANGE = 20 - if(20) MAX_EXPLOSION_RANGE = 28 - if(28) MAX_EXPLOSION_RANGE = 56 - if(56) MAX_EXPLOSION_RANGE = 128 - else MAX_EXPLOSION_RANGE = 14 - var/range_dev = MAX_EXPLOSION_RANGE *0.25 - var/range_high = MAX_EXPLOSION_RANGE *0.5 - var/range_low = MAX_EXPLOSION_RANGE - message_admins(" [key_name_admin(usr)] changed the bomb cap to [range_dev], [range_high], [range_low]", 1) - log_admin("[key_name_admin(usr)] changed the bomb cap to [MAX_EXPLOSION_RANGE]") - - if("flicklights") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FL") - while(!usr.stat) -//knock yourself out to stop the ghosts - for(var/mob/M in player_list) - if(M.stat != 2 && prob(25)) - var/area/AffectedArea = get_area(M) - if(AffectedArea.name != "Space" && AffectedArea.name != "Engine Walls" && AffectedArea.name != "Chemical Lab Test Chamber" && AffectedArea.name != "Escape Shuttle" && AffectedArea.name != "Arrival Area" && AffectedArea.name != "Arrival Shuttle" && AffectedArea.name != "start area" && AffectedArea.name != "Engine Combustion Chamber") - AffectedArea.power_light = 0 - AffectedArea.power_change() - spawn(rand(55,185)) - AffectedArea.power_light = 1 - AffectedArea.power_change() - var/Message = rand(1,4) - switch(Message) - if(1) - M.show_message(text("You shudder as if cold..."), 1) - if(2) - M.show_message(text("You feel something gliding across your back..."), 1) - if(3) - M.show_message(text("Your eyes twitch, you feel like something you can't see is here..."), 1) - if(4) - M.show_message(text("You notice something moving out of the corner of your eye, but nothing is there..."), 1) - for(var/obj/W in orange(5,M)) - if(prob(25) && !W.anchored) - step_rand(W) - sleep(rand(100,1000)) - for(var/mob/M in player_list) - if(M.stat != 2) - M.show_message(text("The chilling wind suddenly stops..."), 1) -/* if("shockwave") - ok = 1 - to_chat(world, "ALERT: STATION STRESS CRITICAL") - sleep(60) - to_chat(world, "ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!") - sleep(80) - to_chat(world, "ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!") - sleep(40) - for(var/mob/M in world) - shake_camera(M, 400, 1) - for(var/obj/structure/window/W in world) - spawn(0) - sleep(rand(10,400)) - W.ex_act(rand(2,1)) - for(var/obj/structure/grille/G in world) - spawn(0) - sleep(rand(20,400)) - G.ex_act(rand(2,1)) - for(var/obj/machinery/door/D in world) - spawn(0) - sleep(rand(20,400)) - D.ex_act(rand(2,1)) - for(var/turf/station/floor/Floor in world) - spawn(0) - sleep(rand(30,400)) - Floor.ex_act(rand(2,1)) - for(var/obj/structure/cable/Cable in world) - spawn(0) - sleep(rand(30,400)) - Cable.ex_act(rand(2,1)) - for(var/obj/structure/closet/Closet in world) - spawn(0) - sleep(rand(30,400)) - Closet.ex_act(rand(2,1)) - for(var/obj/machinery/Machinery in world) - spawn(0) - sleep(rand(30,400)) - Machinery.ex_act(rand(1,3)) - for(var/turf/station/wall/Wall in world) - spawn(0) - sleep(rand(30,400)) - Wall.ex_act(rand(2,1)) */ - if("wave") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","MW") - new /datum/event/meteor_wave - - if("gravanomalies") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","GA") - command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert") - to_chat(world, sound('sound/AI/granomalies.ogg')) - var/turf/T = pick(blobstart) - var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 ) - spawn(rand(100, 600)) - del(bh) - - if("timeanomalies") //dear god this code was awful :P Still needs further optimisation - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","STA") - //moved to its own dm so I could split it up and prevent the spawns copying variables over and over - //can be found in code\game\game_modes\events\wormholes.dm - wormhole_event() - - if("goblob") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BL") - mini_blob_event() - message_admins("[key_name_admin(usr)] has spawned blob", 1) - if("aliens") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","AL") - if(aliens_allowed) - new /datum/event/alien_infestation - message_admins("[key_name_admin(usr)] has spawned aliens", 1) - if("alien_silent") //replaces the spawn_xeno verb - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ALS") - if(aliens_allowed) - create_xeno() - if("spiders") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SL") - new /datum/event/spider_infestation - message_admins("[key_name_admin(usr)] has spawned spiders", 1) - if("comms_blackout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","CB") - var/answer = alert(usr, "Would you like to alert the crew?", "Alert", "Yes", "No") - if(answer == "Yes") - communications_blackout(0) - else - communications_blackout(1) - message_admins("[key_name_admin(usr)] triggered a communications blackout.", 1) - - if("pda_spam") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","PDA") - new /datum/event/pda_spam - - if("carp") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","C") - var/choice = input("You sure you want to spawn carp?") in list("Badmin", "Cancel") - if(choice == "Badmin") - message_admins("[key_name_admin(usr)] has spawned carp.", 1) - new /datum/event/carp_migration - if("radiation") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","R") - message_admins("[key_name_admin(usr)] has has irradiated the station", 1) - new /datum/event/radiation_storm - if("immovable") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","IR") - message_admins("[key_name_admin(usr)] has sent an immovable rod to the station", 1) - immovablerod() - if("prison_break") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","PB") - message_admins("[key_name_admin(usr)] has allowed a prison break", 1) - prison_break() - if("lightout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","LO") - message_admins("[key_name_admin(usr)] has broke a lot of lights", 1) - lightsout(1,2) - if("blackout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BO") - message_admins("[key_name_admin(usr)] broke all lights", 1) - lightsout(0,0) - if("whiteout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","WO") - for(var/obj/machinery/light/L in alllights) - L.fix() - message_admins("[key_name_admin(usr)] fixed all lights", 1) - if("aliens") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","AL") - message_admins("[key_name_admin(usr)] has spawned aliens", 1) - //makeAliens() - new /datum/event/alien_infestation - if("radiation") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","RAD") - message_admins("[key_name_admin(usr)] has started a radiation event", 1) - //makeAliens() - new /datum/event/radiation_storm - if("floorlava") - if(floorIsLava) - to_chat(usr, "The floor is lava already.") - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","LF") - - //Options - var/length = input(usr, "How long will the lava last? (in seconds)", "Length", 180) as num - length = min(abs(length), 1200) - - var/damage = input(usr, "How deadly will the lava be?", "Damage", 2) as num - damage = min(abs(damage), 100) - - var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "YES!", "Nah") - if(sure == "Nah") - return - floorIsLava = 1 - - message_admins("[key_name_admin(usr)] made the floor LAVA! It'll last [length] seconds and it will deal [damage] damage to everyone.", 1) - - for(var/turf/simulated/floor/F in turfs) - if(F.z == 1) - F.name = "lava" - F.desc = "The floor is LAVA!" - F.overlays += "lava" - F.lava = 1 - - spawn(0) - for(var/i = i, i < length, i++) // 180 = 3 minutes - if(damage) - for(var/mob/living/carbon/L in living_mob_list) - if(istype(L.loc, /turf/simulated/floor)) // Are they on LAVA?! - var/turf/simulated/floor/F = L.loc - if(F.lava) - var/safe = 0 - for(var/obj/structure/O in F.contents) - if(O.level > F.level && !istype(O, /obj/structure/window)) // Something to stand on and it isn't under the floor! - safe = 1 - break - if(!safe) - L.adjustFireLoss(damage) - - - sleep(10) - - for(var/turf/simulated/floor/F in turfs) // Reset everything. - if(F.z == 1) - F.name = initial(F.name) - F.desc = initial(F.desc) - F.overlays.len = 0 - F.lava = 0 - F.update_icon() - floorIsLava = 0 - return - if("thebees") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BEE") - var/answer = alert("What's this? A Space Station woefully underpopulated by bees?",,"Let's fix it!","On second thought, let's not.") - if(answer=="Let's fix it!") - message_admins("[key_name_admin(usr)] unleashed the bees onto the crew.", 1) - to_chat(world, "NOT THE BEES!") - to_chat(world, sound('sound/effects/bees.ogg')) - for(var/mob/living/M in player_list) - var/mob/living/simple_animal/bee/BEE = new(get_turf(M)) - BEE.strength = 16 - BEE.toxic = 5 - BEE.mut = 2 - BEE.feral = 25 - BEE.target = M - BEE.icon_state = "bees_swarm-feral" - - if("virus") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","V") - var/answer = alert("Do you want this to be a greater disease or a lesser one?",,"Greater","Lesser") - if(answer=="Lesser") - virus2_lesser_infection() - message_admins("[key_name_admin(usr)] has triggered a lesser virus outbreak.", 1) - else - virus2_greater_infection() - message_admins("[key_name_admin(usr)] has triggered a greater virus outbreak.", 1) - if("retardify") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","RET") - for(var/mob/living/carbon/human/H in player_list) - to_chat(H, "You suddenly feel stupid.") - H.setBrainLoss(60) - message_admins("[key_name_admin(usr)] made everybody retarded") - if("fakeguns") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FG") - for(var/obj/item/W in world) - if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/weapon/disk) || istype(W, /obj/item/weapon/tank)) - continue - W.icon = 'icons/obj/gun.dmi' - W.icon_state = "revolver" - W.item_state = "gun" - message_admins("[key_name_admin(usr)] made every item look like a gun") - if("experimentalguns") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","GUN") - for(var/mob/living/carbon/C in player_list) - var/list/turflist = list() - for(var/turf/T in orange(src,1)) - turflist += T - if(!turflist.len) - turflist += get_turf(C) - var/turf/U = pick(turflist) - var/obj/structure/closet/crate/secure/weapon/experimental/E = new(U) - to_chat(C, "A crate appears next to you. You think you can read \"[E.chosen_set]\" scribbled on it") - U.turf_animation('icons/effects/96x96.dmi',"beamin",-32,0,MOB_LAYER+1,'sound/weapons/emitter2.ogg') - message_admins("[key_name_admin(usr)] distributed experimental guns to the entire crew") - if("schoolgirl") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SG") - for(var/obj/item/clothing/under/W in world) - W.icon_state = "schoolgirl" - W.item_state = "w_suit" - W._color = "schoolgirl" - message_admins("[key_name_admin(usr)] activated Japanese Animes mode") - to_chat(world, sound('sound/AI/animes.ogg')) - if("eagles")//SCRAW - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","EgL") - for(var/obj/machinery/door/airlock/W in all_doors) - if(W.z == 1 && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) - W.req_access = list() - message_admins("[key_name_admin(usr)] activated Egalitarian Station mode") - command_alert("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.") - to_chat(world, sound('sound/AI/commandreport.ogg')) - if("dorf") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","DF") - for(var/mob/living/carbon/human/B in mob_list) - B.f_style = "Dward Beard" - B.update_hair() - message_admins("[key_name_admin(usr)] activated dorf mode") - if("ionstorm") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","I") - generate_ion_law() - message_admins("[key_name_admin(usr)] triggered an ion storm") - var/show_log = alert(usr, "Show ion message?", "Message", "Yes", "No") - if(show_log == "Yes") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") - to_chat(world, sound('sound/AI/ionstorm.ogg')) - if("spacevines") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","K") - new /datum/event/spacevine - message_admins("[key_name_admin(usr)] has spawned spacevines", 1) - if("onlyone") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","OO") - usr.client.only_one() -// message_admins("[key_name_admin(usr)] has triggered a battle to the death (only one)") - if("togglenarsie") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","NA") - var/choice = input("How do you wish for narsie to interact with her surroundings?") in list("CultStation13", "Nar-Singulo") - if(choice == "CultStation13") - message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"CultStation13\".") - narsie_behaviour = "CultStation13" - if(choice == "Nar-Singulo") - message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"Nar-Singulo\".") - narsie_behaviour = "Nar-Singulo" - if("hellonearth") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","NS") - var/choice = input("You sure you want to end the round and summon narsie at your location? Misuse of this could result in removal of flags or halarity.") in list("PRAISE SATAN", "Cancel") - if(choice == "PRAISE SATAN") - new /obj/machinery/singularity/narsie/large(get_turf(usr)) - message_admins("[key_name_admin(usr)] has summoned narsie and brought about a new realm of suffering.") - if("supermattercascade") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SC") - var/choice = input("You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or halarity.") in list("NO TIME TO EXPLAIN", "Cancel") - if(choice == "NO TIME TO EXPLAIN") - explosion(get_turf(usr), 8, 16, 24, 32, 1) - new /turf/unsimulated/wall/supermatter(get_turf(usr)) - SetUniversalState(/datum/universal_state/supermatter_cascade) - message_admins("[key_name_admin(usr)] has managed to destroy the universe with a supermatter cascade. Good job, [key_name_admin(usr)]") - if("spawnadminbus") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","AB") - var/obj/structure/bed/chair/vehicle/adminbus/A = new /obj/structure/bed/chair/vehicle/adminbus(get_turf(usr)) - A.dir = EAST - A.update_lightsource() - A.busjuke.dir = EAST - message_admins("[key_name_admin(usr)] has spawned an Adminbus. Who gave him the keys?") - log_admin("[key_name_admin(usr)] has spawned an Adminbus.") - if("spawnselfdummy") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TD") - message_admins("[key_name_admin(usr)] spawned himself as a Test Dummy.") - log_admin("[key_name_admin(usr)] spawned himself as a Test Dummy.") - var/turf/T = get_turf(usr) - var/mob/living/carbon/human/dummy/D = new /mob/living/carbon/human/dummy(T) - usr.client.cmd_assume_direct_control(D) - D.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(D), slot_w_uniform) - D.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(D), slot_shoes) - D.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(D), slot_ears) - D.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(D), slot_back) - D.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(D.back), slot_in_backpack) - T.turf_animation('icons/effects/96x96.dmi',"beamin",-32,0,MOB_LAYER+1,'sound/misc/adminspawn.ogg') - D.name = "Admin" - D.real_name = "Admin" - var/newname = "" - newname = copytext(sanitize(input(D, "Before you step out as an embodied god, what name do you wish for?", "Choose your name.", "Admin") as null|text),1,MAX_NAME_LEN) - if (!newname) - newname = "Admin" - D.name = newname - D.real_name = newname - var/obj/item/weapon/card/id/admin/admin_id = new(D) - admin_id.registered_name = newname - D.equip_to_slot_or_del(admin_id, slot_wear_id) - //False flags and bait below. May cause mild hilarity or extreme pain. Now in one button - if("fakealerts") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FAKEA") - var/choice = input("Choose the type of fake alert you wish to trigger","False Flag and Bait Panel") in list("Biohazard", "Lifesigns", "Malfunction", "Ion", "Meteor Wave", "Carp Migration", "Return") - //Big fat lists of effects, not very modular but at least there's less buttons - if(choice == "Return") //Actually fuck this - return //Duh - if(choice == "Biohazard") //GUISE WE HAVE A BLOB - var/levelchoice = input("Set the level of the biohazard alert, or leave at 0 to have a random level (1 to 7 supported only)", "Space FEMA Readiness Program", 0) as num - if(!levelchoice || levelchoice > 7 || levelchoice < 0) - to_chat(usr, "Invalid input range (0 to 7 only)") - return - biohazard_alert(level = levelchoice) - message_admins("[key_name_admin(usr)] triggered a FAKE Biohzard Alert.") - log_admin("[key_name_admin(usr)] triggered a FAKE Biohzard Alert.") - return - if(choice == "Lifesigns") //MUH ALIUMS - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") - to_chat(world, sound('sound/AI/aliens.ogg')) - message_admins("[key_name_admin(usr)] triggered a FAKE Lifesign Alert.") - log_admin("[key_name_admin(usr)] triggered a FAKE Lifesign Alert.") - return - if(choice == "Malfunction") //BLOW EVERYTHING - var/salertchoice = input("Do you wish to include the Hostile Runtimes warning to have an authentic Malfunction Takeover Alert ?", "Nanotrasen Alert Level Monitor") in list("Yes", "No") - if(salertchoice == "Yes") - command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") - to_chat(world, "Attention! Delta security level reached!")//Don't ACTUALLY set station alert to Delta to avoid fucking shit up for real - - to_chat(world, "[config.alert_desc_delta]") - to_chat(world, sound('sound/AI/aimalf.ogg'))//AI got valid - - message_admins("[key_name_admin(usr)] triggered a FAKE Malfunction Takeover Alert (Hostile Runtimes alert [salertchoice == "Yes" ? "included":"excluded"])") - log_admin("[key_name_admin(usr)] triggered a FAKE Malfunction Takeover Alert (Hostile Runtimes alert [salertchoice == "Yes" ? "included":"excluded"])") - return - if(choice == "Ion") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") - to_chat(world, sound('sound/AI/ionstorm.ogg')) - message_admins("[key_name_admin(usr)] triggered a FAKE Ion Alert.") - log_admin("[key_name_admin(usr)] triggered a FAKE Ion Alert.") - return - if(choice == "Meteor Wave") - command_alert("A meteor storm has been detected on collision course with the station. Seek shelter within the core of the station immediately.", "Meteor Alert") - to_chat(world, sound('sound/AI/meteors.ogg')) - message_admins("[key_name_admin(usr)] triggered a FAKE Meteor Alert.") - log_admin("[key_name_admin(usr)] triggered a FAKE Meteor Alert.") - return - if(choice == "Carp Migration") - command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") - message_admins("[key_name_admin(usr)] triggered a FAKE Carp Migration Alert.") - log_admin("[key_name_admin(usr)] triggered a FAKE Carp Migration Alert.") - return - if("fakebooms") //Micheal Bay is in the house ! - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FAKEE") - var/choice = input("How much high-budget explosions do you want ?", "Micheal Bay SFX Systems", 1) as num - if(choice < 1) //No negative or null explosion amounts here math genius - to_chat(usr, "Invalid input range (null or negative)") - return - message_admins("[key_name_admin(usr)] improvised himself as Micheal Bay and triggered [round(choice)] fake explosions.") - log_admin("[key_name_admin(usr)] improvised himself as Micheal Bay and triggered [round(choice)] fake explosions.") - for(var/i = 1 to choice) - to_chat(world, sound('sound/effects/explosionfar.ogg')) - sleep(rand(2, 10)) //Sleep 0.2 to 1 second - if("massbomber") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BBM") - var/choice = alert("Dress every player like Bomberman and give them BBDs?","Bomberman Mode Activation","Confirm","Cancel") - if(choice=="Confirm") - bomberman_mode = 1 - to_chat(world, sound('sound/bomberman/start.ogg')) - for(var/mob/living/carbon/human/M in player_list) - if(M.wear_suit) - var/obj/item/O = M.wear_suit - M.u_equip(O,1) - O.loc = M.loc - //O.dropped(M) - if(M.head) - var/obj/item/O = M.head - M.u_equip(O,1) - O.loc = M.loc - //O.dropped(M) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/bomberman(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/bomberman(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/bomberman/(M), slot_s_store) - M.update_icons() - to_chat(M, "Wait...what?") - spawn(50) - to_chat(M, "Tip: Use the BBD in your suit's pocket to place bombs.") - to_chat(M, "Try to keep your BBD and escape this hell hole alive!") - - message_admins("[key_name_admin(usr)] turned everyone into Bomberman!") - log_admin("[key_name_admin(usr)] turned everyone into Bomberman!") - if("bomberhurt") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BBH") - var/choice = alert("Activate Cuban Pete mode? Note that newly spawned BBD will still have player damage deactivated.","Activating Bomberman Bombs Player Damage","Confirm","Cancel") - if(choice=="Confirm") - bomberman_hurt = 1 - for(var/obj/item/weapon/bomberman/B in bombermangear) - if(!B.arena) - B.hurt_players = 1 - message_admins("[key_name_admin(usr)] enabled the player damage of the Bomberman Bomb Dispensers currently in the world. Cuban Pete approves.") - log_admin("[key_name_admin(usr)] enabled the player damage of the Bomberman Bomb Dispensers currently in the world. Cuban Pete approves.") - if("bomberdestroy") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BBD") - var/choice = alert("Activate Michael Bay mode? Note that newly spawned BBD will still have environnement damage deactivated.","Activating Bomberman Bombs Environnement Damage","Confirm","Cancel") - if(choice=="Confirm") - bomberman_destroy = 1 - for(var/obj/item/weapon/bomberman/B in bombermangear) - if(!B.arena) - B.destroy_environnement = 1 - message_admins("[key_name_admin(usr)] enabled the environnement damage of the Bomberman Bomb Dispensers currently in the world. Michael Bay approves.") - log_admin("[key_name_admin(usr)] enabled the environnement damage of the Bomberman Bomb Dispensers currently in the world. Michael Bay approves.") - if("bombernohurt") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BBNH") - var/choice = alert("Disable Cuban Pete mode.","Disable Bomberman Bombs Player Damage","Confirm","Cancel") - if(choice=="Confirm") - bomberman_hurt = 0 - for(var/obj/item/weapon/bomberman/B in bombermangear) - if(!B.arena) - B.hurt_players = 0 - message_admins("[key_name_admin(usr)] disabled the player damage of the Bomberman Bomb Dispensers currently in the world.") - log_admin("[key_name_admin(usr)] disabled the player damage of the Bomberman Bomb Dispensers currently in the world.") - if("bombernodestroy") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BBND") - var/choice = alert("Disable Michael Bay mode?","Disable Bomberman Bombs Environnement Damage","Confirm","Cancel") - if(choice=="Confirm") - bomberman_destroy = 0 - for(var/obj/item/weapon/bomberman/B in bombermangear) - if(!B.arena) - B.destroy_environnement = 0 - message_admins("[key_name_admin(usr)] disabled the environnement damage of the Bomberman Bomb Dispensers currently in the world.") - log_admin("[key_name_admin(usr)] disabled the environnement damage of the Bomberman Bomb Dispensers currently in the world.") - if("togglebombmethod") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BM") - var/choice = input("Do you wish for explosions to take walls and obstacles into account?") in list("Yes, let's have realistic explosions", "No, let's have perfectly circular explosions") - if(choice == "Yes, let's have realistic explosions") - message_admins("[key_name_admin(usr)] has set explosions to take walls and obstacles into account.") - explosion_newmethod = 1 - if(choice == "No, let's have perfectly circular explosions") - message_admins("[key_name_admin(usr)] has set explosions to completely pass through walls and obstacles.") - explosion_newmethod = 0 - if("placeturret") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TUR") - var/list/possible_guns = list() - for(var/path in typesof(/obj/item/weapon/gun/energy)) - possible_guns += path - var/choice = input("What energy gun do you want inside the turret?") in possible_guns - if(!choice) - return - var/obj/item/weapon/gun/energy/gun = new choice() - var/obj/machinery/porta_turret/Turret = new(get_turf(usr)) - Turret.installation = choice - Turret.gun_charge = gun.power_supply.charge - Turret.update_gun() - qdel(gun) - var/emag = input("Emag the turret?") in list("Yes", "No") - if(emag=="Yes") - Turret.emag(usr) - if("hardcore_mode") - var/choice = input("Are you sure you want to [ticker.hardcore_mode ? "disable" : "enable"] hardcore mode? Starvation will [ticker.hardcore_mode ? "no longer":""]slowly kill player-controlled humans.", "Admin Abuse") in list("Yes", "No!") - - if(choice == "Yes") - if(!hardcore_mode_on) - log_admin("[key_name(usr)] has ENABLED hardcore mode!") - hardcore_mode = 1 - to_chat(world, "
    Hardcore mode has been enabled
    ") - to_chat(world, "Not eating for a prolonged period of time will slowly kill player-controlled characters (braindead and catatonic characters are not affected).") - to_chat(world, "If your hunger indicator starts flashing red and black, your character is starving and may die soon!") - else - log_admin("[key_name(usr)] has DISABLED hardcore mode!") - hardcore_mode = 0 - to_chat(world, "
    Hardcore mode has been disabled
    ") - to_chat(world, "Starvation will no longer kill player-controlled characters.") - if(usr) - log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]") - if(ok) - to_chat(world, text("A secret has been activated by [usr.key]!")) - - else if(href_list["secretsadmin"]) - if(!check_rights(R_ADMIN)) - return - - var/ok = 0 - switch(href_list["secretsadmin"]) - if("clear_bombs") - var/num=0 - for(var/obj/item/device/transfer_valve/TV in world) - if(TV.tank_one||TV.tank_two) - del(TV) - TV++ - message_admins("[key_name_admin(usr)] has removed [num] bombs", 1) - if("detonate_bombs") - var/num=0 - for(var/obj/item/device/transfer_valve/TV in world) - if(TV.tank_one||TV.tank_two) - TV.toggle_valve() - message_admins("[key_name_admin(usr)] has toggled valves on [num] bombs", 1) - - if("list_bombers") - var/dat = "Bombing List
    " - for(var/l in bombers) - dat += text("[l]
    ") - usr << browse(dat, "window=bombers") - if("list_signalers") - var/dat = "Showing last [length(lastsignalers)] signalers.
    " - for(var/sig in lastsignalers) - dat += "[sig]
    " - usr << browse(dat, "window=lastsignalers;size=800x500") - if("list_lawchanges") - var/dat = "Showing last [length(lawchanges)] law changes.
    " - for(var/sig in lawchanges) - dat += "[sig]
    " - usr << browse(dat, "window=lawchanges;size=800x500") - if("list_job_debug") - var/dat = "Job Debug info.
    " - if(job_master) - for(var/line in job_master.job_debug) - dat += "[line]
    " - dat+= "*******

    " - for(var/datum/job/job in job_master.occupations) - if(!job) continue - dat += "job: [job.title], current_positions: [job.current_positions], total_positions: [job.total_positions]
    " - usr << browse(dat, "window=jobdebug;size=600x500") - if("showailaws") - output_ai_laws() - if("showgm") - if(!ticker) - alert("The game hasn't started yet!") - else if (ticker.mode) - alert("The game mode is [ticker.mode.name]") - else alert("For some reason there's a ticker, but not a game mode") - if("manifest") - var/dat = "Showing Crew Manifest.
    " - dat += "" - for(var/mob/living/carbon/human/H in mob_list) - if(H.ckey) - dat += text("", H.name, H.get_assignment()) - dat += "
    NamePosition
    [][]
    " - usr << browse(dat, "window=manifest;size=440x410") - if("check_antagonist") - check_antagonists() - if("DNA") - var/dat = "Showing DNA from blood.
    " - dat += "" - for(var/mob/living/carbon/human/H in mob_list) - if(H.dna && H.ckey) - dat += "" - dat += "
    NameDNABlood Type
    [H][H.dna.unique_enzymes][H.b_type]
    " - usr << browse(dat, "window=DNA;size=440x410") - if("fingerprints") - var/dat = "Showing Fingerprints.
    " - dat += "" - for(var/mob/living/carbon/human/H in mob_list) - if(H.ckey) - if(H.dna && H.dna.uni_identity) - dat += "" - else if(H.dna && !H.dna.uni_identity) - dat += "" - else if(!H.dna) - dat += "" - dat += "
    NameFingerprints
    [H][md5(H.dna.uni_identity)]
    [H]H.dna.uni_identity = null
    [H]H.dna = null
    " - usr << browse(dat, "window=fingerprints;size=440x410") - else - if (usr) - log_admin("[key_name(usr)] used secret [href_list["secretsadmin"]]") - if (ok) - to_chat(world, text("A secret has been activated by []!", usr.key)) - - else if(href_list["secretscoder"]) - if(!check_rights(R_DEBUG)) return - - switch(href_list["secretscoder"]) - if("spawn_objects") - var/dat = "Admin Log
    " - for(var/l in admin_log) - dat += "
  • [l]
  • " - if(!admin_log.len) - dat += "No-one has done anything this round!" - usr << browse(dat, "window=admin_log") - if("maint_access_brig") - for(var/obj/machinery/door/airlock/maintenance/M in all_doors) - if (access_maint_tunnels in M.req_access) - M.req_access = list(access_brig) - message_admins("[key_name_admin(usr)] made all maint doors brig access-only.") - if("maint_access_engiebrig") - for(var/obj/machinery/door/airlock/maintenance/M in all_doors) - if (access_maint_tunnels in M.req_access) - M.req_access = list() - M.req_one_access = list(access_brig,access_engine) - message_admins("[key_name_admin(usr)] made all maint doors engineering and brig access-only.") - if("infinite_sec") - var/datum/job/J = job_master.GetJob("Security Officer") - if(!J) return - J.total_positions = -1 - J.spawn_positions = -1 - message_admins("[key_name_admin(usr)] has removed the cap on security officers.") - if("virus_custom") - if(virus2_make_custom(usr.client)) - feedback_add_details("admin_secrets_fun_used", "V_C") - message_admins("[key_name_admin(usr)] has trigger a custom virus outbreak.", 1) - - else if(href_list["ac_view_wanted"]) //Admin newscaster Topic() stuff be here - src.admincaster_screen = 18 //The ac_ prefix before the hrefs stands for AdminCaster. - src.access_news_network() - - else if(href_list["ac_set_channel_name"]) - src.admincaster_feed_channel.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) - while (findtext(src.admincaster_feed_channel.channel_name," ") == 1) - src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1) - src.access_news_network() - - else if(href_list["ac_set_channel_lock"]) - src.admincaster_feed_channel.locked = !src.admincaster_feed_channel.locked - src.access_news_network() - - else if(href_list["ac_submit_new_channel"]) - var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.admincaster_feed_channel.channel_name) - check = 1 - break - if(src.admincaster_feed_channel.channel_name == "" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]" || check ) - src.admincaster_screen=7 - else - var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel") - if(choice=="Confirm") - var/datum/feed_channel/newChannel = new /datum/feed_channel - newChannel.channel_name = src.admincaster_feed_channel.channel_name - newChannel.author = src.admincaster_signature - newChannel.locked = src.admincaster_feed_channel.locked - newChannel.is_admin_channel = 1 - feedback_inc("newscaster_channels",1) - news_network.network_channels += newChannel //Adding channel to the global network - log_admin("[key_name_admin(usr)] created command feed channel: [src.admincaster_feed_channel.channel_name]!") - src.admincaster_screen=5 - src.access_news_network() - - else if(href_list["ac_set_channel_receiving"]) - var/list/available_channels = list() - for(var/datum/feed_channel/F in news_network.network_channels) - available_channels += F.channel_name - src.admincaster_feed_channel.channel_name = adminscrub(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) - src.access_news_network() - - else if(href_list["ac_set_new_message"]) - src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story", "Network Channel Handler", "")) - while (findtext(src.admincaster_feed_message.body," ") == 1) - src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1) - src.access_news_network() - - else if(href_list["ac_submit_new_message"]) - if(src.admincaster_feed_message.body =="" || src.admincaster_feed_message.body =="\[REDACTED\]" || src.admincaster_feed_channel.channel_name == "" ) - src.admincaster_screen = 6 - else - var/datum/feed_message/newMsg = new /datum/feed_message - newMsg.author = src.admincaster_signature - newMsg.body = src.admincaster_feed_message.body - newMsg.is_admin_message = 1 - feedback_inc("newscaster_stories",1) - for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.admincaster_feed_channel.channel_name) - FC.messages += newMsg //Adding message to the network's appropriate feed_channel - break - src.admincaster_screen=4 - - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.newsAlert(src.admincaster_feed_channel.channel_name) - - log_admin("[key_name_admin(usr)] submitted a feed story to channel: [src.admincaster_feed_channel.channel_name]!") - src.access_news_network() - - else if(href_list["ac_create_channel"]) - src.admincaster_screen=2 - src.access_news_network() - - else if(href_list["ac_create_feed_story"]) - src.admincaster_screen=3 - src.access_news_network() - - else if(href_list["ac_menu_censor_story"]) - src.admincaster_screen=10 - src.access_news_network() - - else if(href_list["ac_menu_censor_channel"]) - src.admincaster_screen=11 - src.access_news_network() - - else if(href_list["ac_menu_wanted"]) - var/already_wanted = 0 - if(news_network.wanted_issue) - already_wanted = 1 - - if(already_wanted) - src.admincaster_feed_message.author = news_network.wanted_issue.author - src.admincaster_feed_message.body = news_network.wanted_issue.body - src.admincaster_screen = 14 - src.access_news_network() - - else if(href_list["ac_set_wanted_name"]) - src.admincaster_feed_message.author = adminscrub(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) - while (findtext(src.admincaster_feed_message.author," ") == 1) - src.admincaster_feed_message.author = copytext(admincaster_feed_message.author,2,length(admincaster_feed_message.author)+1) - src.access_news_network() - - else if(href_list["ac_set_wanted_desc"]) - src.admincaster_feed_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) - while (findtext(src.admincaster_feed_message.body," ") == 1) - src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1) - src.access_news_network() - - else if(href_list["ac_submit_wanted"]) - var/input_param = text2num(href_list["ac_submit_wanted"]) - if(src.admincaster_feed_message.author == "" || src.admincaster_feed_message.body == "") - src.admincaster_screen = 16 - else - var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel") - if(choice=="Confirm") - if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below - var/datum/feed_message/WANTED = new /datum/feed_message - WANTED.author = src.admincaster_feed_message.author //Wanted name - WANTED.body = src.admincaster_feed_message.body //Wanted desc - WANTED.backup_author = src.admincaster_signature //Submitted by - WANTED.is_admin_message = 1 - news_network.wanted_issue = WANTED - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.newsAlert() - NEWSCASTER.update_icon() - src.admincaster_screen = 15 - else - news_network.wanted_issue.author = src.admincaster_feed_message.author - news_network.wanted_issue.body = src.admincaster_feed_message.body - news_network.wanted_issue.backup_author = src.admincaster_feed_message.backup_author - src.admincaster_screen = 19 - log_admin("[key_name_admin(usr)] issued a Station-wide Wanted Notification for [src.admincaster_feed_message.author]!") - src.access_news_network() - - else if(href_list["ac_cancel_wanted"]) - var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel") - if(choice=="Confirm") - news_network.wanted_issue = null - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.update_icon() - src.admincaster_screen=17 - src.access_news_network() - - else if(href_list["ac_censor_channel_author"]) - var/datum/feed_channel/FC = locate(href_list["ac_censor_channel_author"]) - if(FC.author != "\[REDACTED\]") - FC.backup_author = FC.author - FC.author = "\[REDACTED\]" - else - FC.author = FC.backup_author - src.access_news_network() - - else if(href_list["ac_censor_channel_story_author"]) - var/datum/feed_message/MSG = locate(href_list["ac_censor_channel_story_author"]) - if(MSG.author != "\[REDACTED\]") - MSG.backup_author = MSG.author - MSG.author = "\[REDACTED\]" - else - MSG.author = MSG.backup_author - src.access_news_network() - - else if(href_list["ac_censor_channel_story_body"]) - var/datum/feed_message/MSG = locate(href_list["ac_censor_channel_story_body"]) - if(MSG.body != "\[REDACTED\]") - MSG.backup_body = MSG.body - MSG.body = "\[REDACTED\]" - else - MSG.body = MSG.backup_body - src.access_news_network() - - else if(href_list["ac_pick_d_notice"]) - var/datum/feed_channel/FC = locate(href_list["ac_pick_d_notice"]) - src.admincaster_feed_channel = FC - src.admincaster_screen=13 - src.access_news_network() - - else if(href_list["ac_toggle_d_notice"]) - var/datum/feed_channel/FC = locate(href_list["ac_toggle_d_notice"]) - FC.censored = !FC.censored - src.access_news_network() - - else if(href_list["ac_view"]) - src.admincaster_screen=1 - src.access_news_network() - - else if(href_list["ac_setScreen"]) //Brings us to the main menu and resets all fields~ - src.admincaster_screen = text2num(href_list["ac_setScreen"]) - if (src.admincaster_screen == 0) - if(src.admincaster_feed_channel) - src.admincaster_feed_channel = new /datum/feed_channel - if(src.admincaster_feed_message) - src.admincaster_feed_message = new /datum/feed_message - src.access_news_network() - - else if(href_list["ac_show_channel"]) - var/datum/feed_channel/FC = locate(href_list["ac_show_channel"]) - src.admincaster_feed_channel = FC - src.admincaster_screen = 9 - src.access_news_network() - - else if(href_list["ac_pick_censor_channel"]) - var/datum/feed_channel/FC = locate(href_list["ac_pick_censor_channel"]) - src.admincaster_feed_channel = FC - src.admincaster_screen = 12 - src.access_news_network() - - else if(href_list["ac_refresh"]) - src.access_news_network() - - else if(href_list["ac_set_signature"]) - src.admincaster_signature = adminscrub(input(usr, "Provide your desired signature", "Network Identity Handler", "")) - src.access_news_network() - - else if(href_list["populate_inactive_customitems"]) - if(check_rights(R_ADMIN|R_SERVER)) - populate_inactive_customitems_list(src.owner) - - else if(href_list["vsc"]) - if(check_rights(R_ADMIN|R_SERVER)) - if(href_list["vsc"] == "airflow") - zas_settings.ChangeSettingsDialog(usr,zas_settings.settings) - if(href_list["vsc"] == "default") - zas_settings.SetDefault(usr) - - else if(href_list["toglang"]) - if(check_rights(R_SPAWN)) - var/mob/M = locate(href_list["toglang"]) - if(!istype(M)) - to_chat(usr, "[M] is illegal type, must be /mob!") - return - var/lang2toggle = href_list["lang"] - var/datum/language/L = all_languages[lang2toggle] - - if(L in M.languages) - if(!M.remove_language(lang2toggle)) - to_chat(usr, "Failed to remove language '[lang2toggle]' from \the [M]!") - else - if(!M.add_language(lang2toggle)) - to_chat(usr, "Failed to add language '[lang2toggle]' from \the [M]!") - - show_player_panel(M) - - // player info stuff - - if(href_list["add_player_info"]) - var/key = href_list["add_player_info"] - var/add = input("Add Player Info") as null|text - if(!add) return - - notes_add(key,add,usr) - show_player_info(key) - - if(href_list["remove_player_info"]) - var/key = href_list["remove_player_info"] - var/index = text2num(href_list["remove_index"]) - - notes_del(key, index) - show_player_info(key) - - if(href_list["notes"]) - var/ckey = href_list["ckey"] - if(!ckey) - var/mob/M = locate(href_list["mob"]) - if(ismob(M)) - ckey = M.ckey - - switch(href_list["notes"]) - if("show") - show_player_info(ckey) - if("list") - PlayerNotesPage(text2num(href_list["index"])) - return - -//------------------------------------------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------Shuttle stuff----------------------------------------------------------- -//------------------------------------------------------------------------------------------------------------------------------------- - - if(href_list["shuttle_select"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SS") - - var/datum/shuttle/S = select_shuttle_from_all(usr,"Please select a shuttle","Admin abuse") - - if(istype(S)) - selected_shuttle = S - to_chat(usr, "[S] ([S.type]) selected!") - - shuttle_magic() //Update the window! - if(href_list["shuttle_add_docking_port"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","CD") - - var/area/A = get_area(get_turf(usr)) - var/datum/shuttle/shuttle_to_add_to = A.get_shuttle() - - if(istype(shuttle_to_add_to)) - if(alert(usr, "Would you like the new shuttle docking port to be assigned to [shuttle_to_add_to.name]? [shuttle_to_add_to.linked_port ? "NOTE: It already has a shuttle docking port." : ""]", "Admin abuse", "Yes", "No") != "Yes") - shuttle_to_add_to = null - - var/obj/structure/docking_port/shuttle/D = new( get_turf(usr) ) - D.dir = usr.dir - - if(istype(shuttle_to_add_to)) - D.link_to_shuttle(shuttle_to_add_to) - to_chat(usr, "Assigned the [D] to [shuttle_to_add_to.name]") - - message_admins("[key_name_admin(usr)] has created a new shuttle docking port in [get_area(D)] [formatJumpTo(get_turf(D))][shuttle_to_add_to ? " and assigned it to [shuttle_to_add_to.name]" : ""]", 1) - log_admin("[key_name_admin(usr)] has created a new destination docking port ([D.areaname]) at [D.x];[D.y];[D.z][shuttle_to_add_to ? " and assigned it to [shuttle_to_add_to.name]" : ""]") - - if(href_list["shuttle_create_destination"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","DC") - - var/area/A = get_area(get_turf(usr)) - - var/name = input(usr,"What would you like to name this docking port?","Admin abuse","[A ? "[A.name]" : "Space [rand(100,999)]"]") as text|null - if(!name) return - - var/obj/structure/docking_port/destination/D = new( get_turf(usr) ) - D.dir = usr.dir - D.areaname = name - - A = get_area(D) - if(A) - var/datum/shuttle/S = A.get_shuttle() - if(S) - if(alert(usr,"Would you like the new docking port to be a part of [S.name] ([S.type])? Any shuttles docked to it will be moved together with [S.name].","Admin abuse","Yes","No") == "Yes") - if(get_area(D) == A) //If the shuttle moved, abort -- as that would lead to weird shittu - S.docking_ports_aboard |= D - to_chat(usr, "[D] is now considered a part of [S.name] ([S.type]).") - - if(istype(selected_shuttle)) - if(alert(usr,"Would you like to add [D.areaname] to the list of [selected_shuttle.name]'s destinations?","Admin abuse","Yes","No") == "Yes") - selected_shuttle.docking_ports |= D - to_chat(usr, "Added [D] to the list of [selected_shuttle.name]'s destinations") - - message_admins("[key_name_admin(usr)] has created a new destination docking port ([D.areaname]) in [get_area(D)] [formatJumpTo(get_turf(D))]", 1) - log_admin("[key_name_admin(usr)] has created a new destination docking port ([D.areaname]) at [D.x];[D.y];[D.z]") - - if(href_list["shuttle_modify_destination"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","MD") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - var/list/docking_ports_to_pick_from = all_docking_ports.Copy() - var/list/options = list() - for(var/obj/structure/docking_port/destination/D in (docking_ports_to_pick_from - S.docking_ports)) - var/name = D.areaname - options += name - options[name] = D - - var/obj/structure/docking_port/destination/choice = options[(input(usr,"Select a docking port to add to [S.name]","Admin abuse") in options)] - if(!istype(choice)) return - - S.docking_ports |= choice - to_chat(usr, "Added [choice.areaname] to [S.name]!") - - if(href_list["shuttle_set_transit"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","AT") - - var/list/L = list() - for(var/obj/structure/docking_port/destination/D in get_turf(usr) ) - var/name = "[D.name] ([D.areaname])" - L += name - L[name]=D - - if(!L.len) - to_chat(usr, "Please stand on the docking port you wish to make a transit area.") - - var/obj/structure/docking_port/port_to_link = L[ (input(usr,"Select a new transit area for the shuttle","Admin abuse") as null|anything in (L + list("Cancel"))) ] - if(!istype(port_to_link)) return - - var/datum/shuttle/shuttle_to_link = selected_shuttle - if(!istype(shuttle_to_link)) return - - var/choice = input(usr,"Please confirm that you want to make [port_to_link] ([port_to_link.areaname]) a transit area for [shuttle_to_link.name] ([shuttle_to_link.type])?","Admin abuse") in list("Yes","No") - - if(choice == "Yes") - shuttle_to_link.set_transit_dock(port_to_link) - else - return - - message_admins("[key_name_admin(usr)] has set a destination docking port ([port_to_link.areaname]) at [port_to_link.x];[port_to_link.y];[port_to_link.z] to be [shuttle_to_link.name] ([shuttle_to_link.type])'s transit area [formatJumpTo(get_turf(port_to_link))]", 1) - log_admin("[key_name_admin(usr)] has set a destination docking port ([port_to_link.areaname]) at [port_to_link.x];[port_to_link.y];[port_to_link.z] to be [shuttle_to_link.name] ([shuttle_to_link.type])'s transit area") - - if(href_list["shuttle_create_shuttleport"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SC") - - var/obj/structure/docking_port/shuttle/D = new(get_turf(usr.loc)) - D.dir = usr.dir - - var/area/A = get_area(D) - var/datum/shuttle/S = A.get_shuttle() - if(S && !S.linked_port) - if(alert(usr,"Would you like to make [S.name] ([S.type]) use this docking port?","Admin abuse","Yes","No") == "Yes") - if(!S || S.linked_port) - to_chat(usr, "Either the shuttle was deleted, or somebody already linked a shuttle docking port to it. Sorry!") - return - if(!D) return - - S.linked_port = D - to_chat(usr, "The shuttle docking port will now be used by [S.name]!") - - message_admins("[key_name_admin(usr)] has created a new shuttle docking port in [get_area(D)] [formatJumpTo(get_turf(D))]", 1) - log_admin("[key_name_admin(usr)] has created a new shuttle docking port at [D.x];[D.y];[D.z]
    ") - - if(href_list["shuttle_toggle_lockdown"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","LD") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - if(S.lockdown) - S.lockdown = 0 - to_chat(usr, "The lockdown from [S.name] has been lifted.") - message_admins("[key_name_admin(usr)] has lifted [capitalize(S.name)]'s lockdown.", 1) - log_admin("[key_name(usr)] has locked [capitalize(S.name)] down. [(length(S.lockdown)>=1) ? "Reason: [S.lockdown]" : ""]") - else - S.lockdown = 1 - to_chat(usr, "[S.name] has been locked down.") - var/reason = input(usr,"Would you like to provide additional information, which will be shown on [capitalize(S.name)]'s control consoles?","Shuttle lockdown") in list("Yes","No") - if(reason == "Yes") - reason = input(usr,"Please type additional information about the lockdown of [capitalize(S.name)].","Shuttle lockdown") - if(length(reason)>=1) - S.lockdown = reason - message_admins("[key_name_admin(usr)] has locked [capitalize(S.name)] down. [(length(S.lockdown)>=1) ? "Reason: [S.lockdown]" : ""]", 1) - log_admin("[key_name(usr)] has locked [capitalize(S.name)] down. [(length(S.lockdown)>=1) ? "Reason: [S.lockdown]" : ""]") - - if(href_list["shuttle_move_to"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","MV") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - var/list/possible_ports = list() - for(var/obj/structure/docking_port/destination/D in S.docking_ports) - var/name = D.areaname - possible_ports += name - possible_ports[name] = D - - var/choice = input(usr, "Select a docking port for [capitalize(S.name)] to travel to", "Shuttle movement") in (possible_ports + list("Cancel")) - var/obj/structure/docking_port/destination/target_port = possible_ports[choice] - - if(!target_port) - return - - S.travel_to(target_port,,usr) - - message_admins("[key_name_admin(usr)] has moved [capitalize(S.name)] to [target_port.areaname] ([target_port.x];[target_port.y];[target_port.z])") - log_admin("[key_name(usr)] has moved [capitalize(S.name)] to [target_port.areaname] ([target_port.x];[target_port.y];[target_port.z])") - - if(href_list["shuttle_edit"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SE") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - var/list/options = list("Cancel","cooldown","pre-flight delay","transit delay","use transit","can link to computer","innacuracy","name","destroy areas","can rotate") - if(S.is_special()) options += "DEFINED LOCATIONS" - var/choice = input(usr,"What to edit in [capitalize(S.name)]?","Shuttle editing") in options - - var/new_value - switch(choice) - if("cooldown") - new_value = input(usr,"Input new cooldown for [capitalize(S.name)] (in 1/10s of a second)","Shuttle editing",S.cooldown) as num - S.cooldown = new_value - if("pre-flight delay") - new_value = input(usr,"Input new pre-flight delay for [capitalize(S.name)] (in 1/10s of a second)","Shuttle editing",S.pre_flight_delay) as num - S.pre_flight_delay = new_value - if("transit delay") - new_value = input(usr,"Input new transit delay for [capitalize(S.name)] (in 1/10s of a second)","Shuttle editing",S.transit_delay) as num - S.transit_delay = new_value - if("use transit") - new_value = input(usr,"[NO_TRANSIT] - no transit, [TRANSIT_ACROSS_Z_LEVELS] - only across z levels, [TRANSIT_ALWAYS] - always","Shuttle editing ([capitalize(S.name)])",S.use_transit) as num - if(new_value in list(NO_TRANSIT,TRANSIT_ACROSS_Z_LEVELS,TRANSIT_ALWAYS)) - S.use_transit = new_value - else - to_chat(usr, "Not valid!") - return - if("can link to computer") - new_value = input(usr,"[LINK_FREE] - can always link, [LINK_PASSWORD_ONLY] - can only link with password ([S.password]), [LINK_FORBIDDEN] - can't link at all","Shuttle editing ([capitalize(S.name)])",S.can_link_to_computer) as num - S.pre_flight_delay = new_value - if("direction") - new_value = input(usr,"[NORTH] - north, [SOUTH] - south, [WEST] - west, [EAST] - east","Shuttle editing ([capitalize(S.name)])",S.dir) as num - if(new_value in cardinal) - S.dir = new_value - else - to_chat(usr, "Not valid!") - return - if("innacuracy") - new_value = input(usr,"Input new innacuracy value for [capitalize(S.name)] (when a shuttle moves, its final location is randomly offset by this value)","Shuttle editing",S.innacuracy) as num - S.innacuracy = new_value - if("name") - new_value = input(usr,"Input new name for [capitalize(S.name)]","Shuttle editing",S.innacuracy) as text - S.name = new_value - if("can rotate") - new_value = input(usr,"0 - rotation disabled, 1 - rotation enabled","Shuttle editing",S.can_rotate) as num - S.can_rotate = new_value - if("DEFINED LOCATIONS") - to_chat(usr, "To prevent accidental mistakes, you can only set these locations to docking ports in the shuttle's memory (use the \"Add a destination docking port to a shuttle\" command)") - - var/list/locations = list("--Cancel--") - switch(S.type) - if(/datum/shuttle/vox) - locations += list("Vox home (MOVING TO IT WILL END THE ROUND)" = "dock_home") - if(/datum/shuttle/escape) - locations += list("Escape shuttle home" = "dock_station","Escape shuttle centcom" = "dock_centcom") - if(/datum/shuttle/taxi) - locations += list("Taxi medbay silicon" = "dock_medical_silicon","Taxi engineering cargo" = "dock_engineering_cargo","Taxi security science" = "dock_security_science","Taxi abandoned station" = "dock_abandoned") - if(/datum/shuttle/supply) - locations += list("Centcom loading bay" = "dock_centcom", "Station cargo bay" = "dock_station") - - var/choice2 = input(usr,"Select a location to modify","Shuttle editing") in locations - var/variable_to_edit = locations[choice2] - - var/obj/structure/docking_port/destination/D = select_port_from_list(usr,"Select a new [choice2] location for [S.name] ([S.type])","Shuttle editing",S.docking_ports) - if(istype(D)) - S.vars[variable_to_edit] = D - to_chat(usr, "[S.name]'s [variable_to_edit] has been changed to [D.areaname]") - message_admins("[key_name_admin(usr)] has changed [capitalize(S.name)]'s [choice2] to [D.areaname]!", 1) - log_admin("[key_name_admin(usr)] has changed [capitalize(S.name)]'s [choice2] to [D.areaname]!") - else - return - - - message_admins("[key_name_admin(usr)] has set [capitalize(S.name)]'s [choice] to [new_value]!", 1) - log_admin("[key_name_admin(usr)] has set [capitalize(S.name)]'s [choice] to [new_value]!") - - shuttle_magic() //Update the window! - - if(href_list["shuttle_delete"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","DEL") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - var/killed_objs = 0 - - if( (input(usr,"Please type \"Yes\" to confirm that you want to delete [capitalize(S)]. This process can't be reverted!","Shuttle deletion","No") as text) != "Yes" ) - return - - if(S.is_special()) - to_chat(usr, "This shuttle can't be deleted. Use the lockdown function instead.") - return - - var/choice = (input(usr,"Would you like to delete all turfs and objects in the shuttle's current area? Mobs will not be affected.") in list("Yes","No","Cancel") ) - if(choice == "Cancel") - return - else if(choice == "Yes") - killed_objs = 1 - - if(S.linked_area) - if(killed_objs == 1) - for(var/turf/T in S.linked_area) - if(istype(T, /turf/simulated)) - qdel(T) - for(var/obj/O in S.linked_area) - if(istype(O, /obj/item) || istype(O, /obj/machinery) || istype(O, /obj/structure)) - qdel(O) - to_chat(usr, "All turfs and objects deleted from [S.linked_area].") - - message_admins("[key_name_admin(usr)] has deleted [capitalize(S.name)] ([S.type]). Objects and turfs [(killed_objs) ? "deleted" : "not deleted"].") - log_admin("[key_name(usr)] has deleted [capitalize(S.name)]! Objects and turfs [(killed_objs) ? "deleted" : "not deleted"].") - - qdel(S) - selected_shuttle = null - - shuttle_magic() //Update the window! - - if(href_list["shuttle_teleport_to"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","TP") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - if(!S.linked_area || !istype(S.linked_area, /area/)) - to_chat(usr, "The shuttle is in the middle of nowhere! (The 'linked_area' variable is either null or not an area, please report this)") - return - - var/turf/T = locate(/turf/) in S.linked_area - usr.forceMove(T) - to_chat(usr, "You have teleported to [capitalize(S.name)]") - - if(href_list["shuttle_teleport_to_dock"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","TP2") - - var/list/destinations = list() - for(var/obj/structure/docking_port/destination/D in all_docking_ports) - var/name = "[D.areaname][D.docked_with ? " (docked to [D.docked_with.areaname])" : ""]" - destinations += name - destinations[name]=D - - var/choice = input(usr,"Select a docking port to teleport to","Finding a docking port") in destinations - - var/obj/structure/docking_port/destination/target = destinations[choice] - if(!target) return - - usr.forceMove(get_turf(target)) - to_chat(usr, "You have teleported to [choice]") - - if(href_list["shuttle_get_console"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","GC") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - if(!S.control_consoles.len) - - var/choice = input(usr,"There is no control console linked to [capitalize(S.name)]. Would you like to create one at your current location?","Shuttle control access") in list("Yes","No") - if(choice == "Yes") - var/turf/usr_loc = get_turf(usr) - var/obj/machinery/computer/shuttle_control/C = new(usr_loc) - if(C) - C.link_to(S) - to_chat(usr, "A new shuttle control console has been created.") - message_admins("[key_name_admin(usr)] has created a new shuttle control console connected to [capitalize(S.name)] in [get_area(usr_loc)].") - log_admin("[key_name(usr)] has created a new shuttle control console connected to [capitalize(S.name)] in [get_area(usr_loc)].") - else - return - - else - - var/obj/machinery/computer/shuttle_control/C = pick(S.control_consoles) - if(C) - usr.loc = C.loc - - if(href_list["shuttle_shuttlify"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SHH") - - var/area/A = get_area(usr) - if(!A) - to_chat(usr, "You must be standing on an area!") - return - if(isspace(A)) - to_chat(usr, "You can't turn space into a shuttle.") - return - - var/datum/shuttle/conflict = A.get_shuttle() - if(conflict) - var/choice = input(usr,"This area is already used by [conflict]. Type \"Yes\" to continue and bring on the unintended features","Shuttlify","NO") as text - if(choice != "Yes") - return - - if( !(locate(/obj/structure/docking_port/shuttle) in A) ) - to_chat(usr, "Please create a shuttle docking port (/obj/structure/docking_port/shuttle) in this area!") - return - - var/name = input(usr, "Please name the new shuttle", "Shuttlify", A.name) as text|null - - if(!name) - to_chat(usr, "Shuttlifying cancelled.") - return - - var/datum/shuttle/custom/S = new(starting_area = A) - S.initialize() - S.name = name - - to_chat(usr, "Shuttle created!") - - selected_shuttle = S - shuttle_magic() //Update the window! - - message_admins("[key_name_admin(usr)] has turned [A.name] into a shuttle named [S.name]. [formatJumpTo(get_turf(usr))]") - log_admin("[key_name(usr)] has turned [A.name] into a shuttle named [S.name].") - - if(href_list["shuttle_forcemove"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","FM") - - var/list/L = list("Cancel","YOUR CURRENT LOCATION") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - for(var/obj/structure/docking_port/destination/D in S.docking_ports) - var/name = "[D.name] [D.areaname]" - L+=name - L[name]=D - - L += "---other destinations---" - - for(var/obj/structure/docking_port/destination/D in all_docking_ports - S.docking_ports) - var/name = D.areaname - L+=name - L[name]=D - - var/choice = input(usr, "Select a location to teleport [S.name] to!", "Shuttle teleporting") in L - - if(choice == "YOUR CURRENT LOCATION") - var/area/A = get_area(usr) - var/turf/T = get_turf(usr) - if(!A) return - if(!T) return - - var/obj/structure/docking_port/destination/temp = new(T) - temp.invisibility = 101 - temp.areaname = A.name - temp.dir = usr.dir - - S.move_to_dock(temp) - - message_admins("[key_name_admin(usr)] has teleported [capitalize(S.name)] to himself ([A.name], [temp.x];[temp.y];[temp.z])!") - log_admin("[key_name(usr)] has teleported [capitalize(S.name)] to himself by ([A.name], [temp.x];[temp.y];[temp.z])") - - qdel(temp) - return - else - var/obj/structure/docking_port/destination/D = L[choice] - if(!D) return - - S.move_to_dock(D) - - message_admins("[key_name_admin(usr)] has teleported [capitalize(S.name)] to [choice] ([D.x];[D.y];[D.z])") - log_admin("[key_name(usr)] has teleported [capitalize(S.name)] to [choice] ([D.x];[D.y];[D.z])") - - return - - if(href_list["shuttle_reset"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SR") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - if(alert(usr,"ARE YOU SURE YOU WANT TO RESET [S.name] ([S.type])?","HELP","Yes","No")=="No") return - - S.name = initial(S.name) - S.cooldown = initial(S.cooldown) - S.innacuracy = initial(S.innacuracy) - S.transit_delay = initial(S.transit_delay) - S.pre_flight_delay = initial(S.pre_flight_delay) - S.use_transit = initial(S.use_transit) - S.dir = initial(S.dir) - - S.initialize() - - message_admins("[key_name_admin(usr)] has reset [capitalize(S.name)]'s variables") - log_admin("[key_name(usr)] has reset [capitalize(S.name)]'s variables") - - if(href_list["shuttle_supercharge"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SUP") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - S.supercharge() - - if(href_list["shuttle_mass_lockdown"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","ML") - - if( !(input(usr,"Please type \"Yes\" to confirm that you want to lockdown all shuttles.","IS IT LOOSE?","NO") == "Yes") ) - return - - for(var/datum/shuttle/S in shuttles) - S.lockdown = 1 - - to_chat(usr, "All shuttles were locked down.") - - message_admins("[key_name_admin(usr)] has locked all shuttles down!") - log_admin("[key_name(usr)] has locked all shuttles down!") - - if(href_list["shuttle_show_overlay"]) - feedback_inc("admin_shuttle_magic_used",1) - feedback_add_details("admin_shuttle_magic_used","SO") - - var/datum/shuttle/S = selected_shuttle - if(!istype(S)) return - - if(!S.linked_port) - to_chat(usr, "The shuttle must have a shuttle docking port!") - return - - if(usr.dir != S.dir) - to_chat(usr, "WARNING: You're not facing [dir2text(S.dir)]! The result may be slightly innacurate.") - - S.show_outline(usr) - - - //------------------------------------------------------------------Shuttle stuff end--------------------------------- +/datum/admins/Topic(href, href_list) + ..() + + if(usr.client != src.owner || !check_rights(0)) + log_admin("[key_name(usr)] tried to use the admin panel without authorization.") + message_admins("[usr.key] has attempted to override the admin panel!") + return + + var/client/CLIENT = usr.client + if(href_list["makeAntag"]) + switch(href_list["makeAntag"]) + if("1") + log_admin("[key_name(usr)] has spawned a traitor.") + if(!src.makeTraitors()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("2") + log_admin("[key_name(usr)] has spawned a changeling.") + if(!src.makeChanglings()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("3") + log_admin("[key_name(usr)] has spawned revolutionaries.") + if(!src.makeRevs()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("4") + log_admin("[key_name(usr)] has spawned a cultists.") + if(!src.makeCult()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("5") + log_admin("[key_name(usr)] has spawned a malf AI.") + if(!src.makeMalfAImode()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("6") + log_admin("[key_name(usr)] has spawned a wizard.") + if(!src.makeWizard()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("7") + log_admin("[key_name(usr)] has spawned a nuke team.") + if(!src.makeNukeTeam()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("9") + log_admin("[key_name(usr)] has spawned aliens.") + src.makeAliens() + if("10") + log_admin("[key_name(usr)] has spawned a death squad.") + if(!makeDeathsquad()) + to_chat(usr, "Unfortunately, there were no candidates available") + if("11") + log_admin("[key_name(usr)] has spawned vox raiders.") + if(!src.makeVoxRaiders()) + to_chat(usr, "Unfortunately, there weren't enough candidates available.") + + else if("announce_laws" in href_list) + var/mob/living/silicon/S = locate(href_list["mob"]) + + log_admin("[key_name(usr)] has notified [key_name(S)] of a change to their laws.") + message_admins("[usr.key] has notified [key_name(S)] of a change to their laws.") + + to_chat(S, "____________________________________") + to_chat(S, "LAW CHANGE NOTICE") + if(S.laws) + to_chat(S, "Your new laws are as follows:") + S.laws.show_laws(S) + else + to_chat(S, "Your laws are null. Contact a coder immediately.") + to_chat(S, "____________________________________") + if(isAI(S)) + var/mob/living/silicon/ai/AI=S + AI.notify_slaved(force_sync=1) + + else if("add_law" in href_list) + var/mob/living/silicon/S = locate(href_list["mob"]) + var/lawtypes = list( + "Law Zero"= LAW_ZERO, + "Ion" = LAW_IONIC, + "Core" = LAW_INHERENT, + "Standard"= 1 + ) + var/lawtype = input("Select a law type.","Law Type",1) as anything in lawtypes + lawtype=lawtypes[lawtype] + if(lawtype == null) + return + testing("Lawtype: [lawtype]") + if(lawtype==1) + lawtype=text2num(input("Enter desired law priority. (15-50)","Priority", 15) as num) + lawtype=Clamp(lawtype,15,50) + var/newlaw = copytext(sanitize(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry", "")),1,MAX_MESSAGE_LEN) + if(newlaw=="") + return + S.laws.add_law(lawtype,newlaw) + + log_admin("[key_name(usr)] has added a law to [key_name(S)]: \"[newlaw]\"") + message_admins("[usr.key] has added a law to [key_name(S)]: \"[newlaw]\"") + lawchanges.Add("[key_name(usr)] has added a law to [key_name(S)]: \"[newlaw]\"") + + else if("reset_laws" in href_list) + var/mob/living/silicon/S = locate(href_list["mob"]) + var/lawtypes = typesof(/datum/ai_laws) - /datum/ai_laws + var/lawtype = input("Select a lawset.","Law Type",1) as null|anything in lawtypes + if(lawtype == null) + return + testing("Lawtype: [lawtype]") + + var/law_zeroth=null + var/law_zeroth_borg=null + if(S.laws.zeroth || S.laws.zeroth_borg) + if(alert(src,"Do you also wish to clear law zero?","Yes","No") == "No") + law_zeroth=S.laws.zeroth + law_zeroth_borg=S.laws.zeroth + + S.laws = new lawtype + S.laws.zeroth=law_zeroth + S.laws.zeroth_borg=law_zeroth_borg + + log_admin("[key_name(usr)] has reset [key_name(S)]: [lawtype]") + message_admins("[usr.key] has reset [key_name(S)]: [lawtype]") + lawchanges.Add("[key_name(usr)] has reset [key_name(S)]: [lawtype]") + + else if("clear_laws" in href_list) + var/mob/living/silicon/S = locate(href_list["mob"]) + S.laws.clear_inherent_laws() + S.laws.clear_supplied_laws() + S.laws.clear_ion_laws() + + if(S.laws.zeroth || S.laws.zeroth_borg) + if(alert(src,"Do you also wish to clear law zero?","Yes","No") == "Yes") + S.laws.set_zeroth_law("","") + + log_admin("[key_name(usr)] has purged [key_name(S)]") + message_admins("[usr.key] has purged [key_name(S)]") + lawchanges.Add("[key_name(usr)] has purged [key_name(S)]") + + else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"]) + var/adminckey = href_list["dbsearchadmin"] + var/playerckey = href_list["dbsearchckey"] + + DB_ban_panel(playerckey, adminckey) + return + + else if(href_list["dbbanedit"]) + var/banedit = href_list["dbbanedit"] + var/banid = text2num(href_list["dbbanid"]) + if(!banedit || !banid) + return + + DB_ban_edit(banid, banedit) + return + + else if(href_list["dbbanaddtype"]) + + var/bantype = text2num(href_list["dbbanaddtype"]) + var/banckey = href_list["dbbanaddckey"] + var/banduration = text2num(href_list["dbbaddduration"]) + var/banjob = href_list["dbbanaddjob"] + var/banreason = href_list["dbbanreason"] + + banckey = ckey(banckey) + + switch(bantype) + if(BANTYPE_PERMA) + if(!banckey || !banreason) + to_chat(usr, "Not enough parameters (Requires ckey and reason)") + return + banduration = null + banjob = null + if(BANTYPE_TEMP) + if(!banckey || !banreason || !banduration) + to_chat(usr, "Not enough parameters (Requires ckey, reason and duration)") + return + banjob = null + if(BANTYPE_JOB_PERMA) + if(!banckey || !banreason || !banjob) + to_chat(usr, "Not enough parameters (Requires ckey, reason and job)") + return + banduration = null + if(BANTYPE_JOB_TEMP) + if(!banckey || !banreason || !banjob || !banduration) + to_chat(usr, "Not enough parameters (Requires ckey, reason and job)") + return + if(BANTYPE_APPEARANCE) + if(!banckey || !banreason) + to_chat(usr, "Not enough parameters (Requires ckey and reason)") + return + banduration = null + banjob = null + if(BANTYPE_OOC_PERMA) + if(!banckey || !banreason) + to_chat(usr, "Not enough parameters (Requires ckey and reason)") + return + banduration = null + if(BANTYPE_OOC_TEMP) + if(!banckey || !banreason || !banduration) + to_chat(usr, "Not enough parameters (Requires ckey, reason, and duration)") + return + + var/mob/playermob + + for(var/mob/M in player_list) + if(M.ckey == banckey) + playermob = M + break + + banreason = "(MANUAL BAN) "+banreason + + DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey) + + else if(href_list["editrights"]) + if(!check_rights(R_PERMISSIONS)) + message_admins("[key_name_admin(usr)] attempted to edit the admin permissions without sufficient rights.") + log_admin("[key_name(usr)] attempted to edit the admin permissions without sufficient rights.") + return + + var/adm_ckey + + var/task = href_list["editrights"] + if(task == "add") + var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null) + if(!new_ckey) return + if(new_ckey in admin_datums) + to_chat(usr, "Error: Topic 'editrights': [new_ckey] is already an admin") + return + adm_ckey = new_ckey + task = "rank" + else if(task != "show") + adm_ckey = ckey(href_list["ckey"]) + if(!adm_ckey) + to_chat(usr, "Error: Topic 'editrights': No valid ckey") + return + + var/datum/admins/D = admin_datums[adm_ckey] + + if(task == "remove") + if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes") + if(!D) return + admin_datums -= adm_ckey + D.disassociate() + + message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list") + log_admin("[key_name(usr)] removed [adm_ckey] from the admins list") + log_admin_rank_modification(adm_ckey, "Removed") + + else if(task == "rank") + var/new_rank + if(admin_ranks.len) + new_rank = input("Please select a rank", "New rank", null, null) as null|anything in (admin_ranks|"*New Rank*") + else + new_rank = input("Please select a rank", "New rank", null, null) as null|anything in list("Game Master","Game Admin", "Trial Admin", "Admin Observer","*New Rank*") + + var/rights = 0 + if(D) + rights = D.rights + switch(new_rank) + if(null,"") return + if("*New Rank*") + new_rank = input("Please input a new rank", "New custom rank", null, null) as null|text + if(config.admin_legacy_system) + new_rank = ckeyEx(new_rank) + if(!new_rank) + to_chat(usr, "Error: Topic 'editrights': Invalid rank") + return + if(config.admin_legacy_system) + if(admin_ranks.len) + if(new_rank in admin_ranks) + rights = admin_ranks[new_rank] //we typed a rank which already exists, use its rights + else + admin_ranks[new_rank] = 0 //add the new rank to admin_ranks + else + if(config.admin_legacy_system) + new_rank = ckeyEx(new_rank) + rights = admin_ranks[new_rank] //we input an existing rank, use its rights + + if(D) + D.disassociate() //remove adminverbs and unlink from client + D.rank = new_rank //update the rank + D.rights = rights //update the rights based on admin_ranks (default: 0) + else + D = new /datum/admins(new_rank, rights, adm_ckey) + + var/client/C = directory[adm_ckey] //find the client with the specified ckey (if they are logged in) + D.associate(C) //link up with the client and add verbs + + message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]") + log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]") + log_admin_rank_modification(adm_ckey, new_rank) + + else if(task == "permissions") + if(!D) return + var/list/permissionlist = list() + for(var/i=1, i<=R_MAXPERMISSION, i<<=1) //that <<= is shorthand for i = i << 1. Which is a left bitshift + permissionlist[rights2text(i)] = i + var/new_permission = input("Select a permission to turn on/off", "Permission toggle", null, null) as null|anything in permissionlist + if(!new_permission) return + D.rights ^= permissionlist[new_permission] + + message_admins("[key_name_admin(usr)] toggled the [new_permission] permission of [adm_ckey]") + log_admin("[key_name(usr)] toggled the [new_permission] permission of [adm_ckey]") + log_admin_permission_modification(adm_ckey, permissionlist[new_permission]) + + edit_admin_permissions() + + else if(href_list["call_shuttle"]) + if(!check_rights(R_ADMIN)) return + + if( ticker.mode.name == "blob" ) + alert("You can't call the shuttle during blob!") + return + + switch(href_list["call_shuttle"]) + if("1") + if ((!( ticker ) || emergency_shuttle.location)) + return + emergency_shuttle.incall() + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + log_admin("[key_name(usr)] called the Emergency Shuttle") + message_admins("[key_name_admin(usr)] called the Emergency Shuttle to the station", 1) + + if("2") + if ((!( ticker ) || emergency_shuttle.location || emergency_shuttle.direction == 0)) + return + switch(emergency_shuttle.direction) + if(-1) + emergency_shuttle.incall() + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + log_admin("[key_name(usr)] called the Emergency Shuttle") + message_admins("[key_name_admin(usr)] called the Emergency Shuttle to the station", 1) + if(1) + emergency_shuttle.recall() + log_admin("[key_name(usr)] sent the Emergency Shuttle back") + message_admins("[key_name_admin(usr)] sent the Emergency Shuttle back", 1) + + href_list["secretsadmin"] = "check_antagonist" + + else if(href_list["edit_shuttle_time"]) + if(!check_rights(R_SERVER)) return + + emergency_shuttle.settimeleft( input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", emergency_shuttle.timeleft() ) as num ) + log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [emergency_shuttle.timeleft()]") + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + message_admins("[key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [emergency_shuttle.timeleft()]", 1) + href_list["secretsadmin"] = "check_antagonist" + + else if(href_list["delay_round_end"]) + if(!check_rights(R_SERVER)) return + + ticker.delay_end = !ticker.delay_end + log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") + message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) + href_list["secretsadmin"] = "check_antagonist" + + else if(href_list["simplemake"]) + if(!check_rights(R_SPAWN)) return + + var/mob/M = locate(href_list["mob"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + var/delmob = 0 + switch(alert("Delete old mob?","Message","Yes","No","Cancel")) + if("Cancel") return + if("Yes") delmob = 1 + + log_admin("[key_name(usr)] has used rudimentary transformation on [key_name(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]") + message_admins("[key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]", 1) + var/mob/new_mob + switch(href_list["simplemake"]) + if("observer") new_mob = M.change_mob_type( /mob/dead/observer , null, null, delmob ) + if("drone") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/drone , null, null, delmob ) + if("hunter") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/hunter , null, null, delmob ) + if("queen") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/queen , null, null, delmob ) + if("sentinel") new_mob = M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob ) + if("larva") new_mob = M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob ) + if("human") new_mob = M.change_mob_type( /mob/living/carbon/human , null, null, delmob ) + if("slime") new_mob = M.change_mob_type( /mob/living/carbon/slime , null, null, delmob ) + if("adultslime") new_mob = M.change_mob_type( /mob/living/carbon/slime/adult , null, null, delmob ) + if("monkey") new_mob = M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob ) + if("robot") new_mob = M.change_mob_type( /mob/living/silicon/robot , null, null, delmob ) + if("cat") new_mob = M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob ) + if("runtime") new_mob = M.change_mob_type( /mob/living/simple_animal/cat/Runtime , null, null, delmob ) + if("corgi") new_mob = M.change_mob_type( /mob/living/simple_animal/corgi , null, null, delmob ) + if("ian") new_mob = M.change_mob_type( /mob/living/simple_animal/corgi/Ian , null, null, delmob ) + if("crab") new_mob = M.change_mob_type( /mob/living/simple_animal/crab , null, null, delmob ) + if("coffee") new_mob = M.change_mob_type( /mob/living/simple_animal/crab/Coffee , null, null, delmob ) + if("parrot") new_mob = M.change_mob_type( /mob/living/simple_animal/parrot , null, null, delmob ) + if("polyparrot") new_mob = M.change_mob_type( /mob/living/simple_animal/parrot/Poly , null, null, delmob ) + if("constructarmoured") new_mob = M.change_mob_type( /mob/living/simple_animal/construct/armoured , null, null, delmob ) + if("constructbuilder") new_mob = M.change_mob_type( /mob/living/simple_animal/construct/builder , null, null, delmob ) + if("constructwraith") new_mob = M.change_mob_type( /mob/living/simple_animal/construct/wraith , null, null, delmob ) + if("shade") new_mob = M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob ) +// to_chat(world, "Made a [new_mob] [usr ? "usr still exists" : "usr does not exist"]") + if(new_mob && new_mob != M) +// to_chat(world, "[new_mob.client] vs [CLIENT] they [new_mob.client == CLIENT ? "match" : "don't match"]") + if(new_mob.client == CLIENT) +// to_chat(world, "setting usr to new_mob") + usr = new_mob //We probably transformed ourselves + show_player_panel(new_mob) + + + /////////////////////////////////////new ban stuff + else if(href_list["unbanf"]) + if(!check_rights(R_BAN)) return + + var/banfolder = href_list["unbanf"] + Banlist.cd = "/base/[banfolder]" + var/key = Banlist["key"] + if(alert(usr, "Are you sure you want to unban [key]?", "Confirmation", "Yes", "No") == "Yes") + if(RemoveBan(banfolder)) + unbanpanel() + else + alert(usr, "This ban has already been lifted / does not exist.", "Error", "Ok") + unbanpanel() + + else if(href_list["warn"]) + usr.client.warn(href_list["warn"]) + + else if(href_list["unwarn"]) + usr.client.unwarn(href_list["unwarn"]) + + else if(href_list["unbane"]) + if(!check_rights(R_BAN)) return + + UpdateTime() + var/reason + + var/banfolder = href_list["unbane"] + Banlist.cd = "/base/[banfolder]" + var/reason2 = Banlist["reason"] + var/temp = Banlist["temp"] + + var/minutes = Banlist["minutes"] + + var/banned_key = Banlist["key"] + Banlist.cd = "/base" + + var/duration + + switch(alert("Temporary Ban?",,"Yes","No")) + if("Yes") + temp = 1 + var/mins = 0 + if(minutes > CMinutes) + mins = minutes - CMinutes + mins = input(usr,"How long (in minutes)? (Default: 1440)","Ban time",mins ? mins : 1440) as num|null + if(!mins) return + mins = min(525599,mins) + minutes = CMinutes + mins + duration = GetExp(minutes) + reason = input(usr,"Reason?","reason",reason2) as text|null + if(!reason) return + if("No") + temp = 0 + duration = "Perma" + reason = input(usr,"Reason?","reason",reason2) as text|null + if(!reason) return + + log_admin("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") + ban_unban_log_save("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") + message_admins("[key_name_admin(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]", 1) + Banlist.cd = "/base/[banfolder]" + to_chat(Banlist["reason"], reason) + to_chat(Banlist["temp"], temp) + to_chat(Banlist["minutes"], minutes) + to_chat(Banlist["bannedby"], usr.ckey) + Banlist.cd = "/base" + feedback_inc("ban_edit",1) + unbanpanel() + + /////////////////////////////////////new ban stuff + else if(href_list["oocban"]) + if(!check_rights(R_BAN)) + return + var/mob/M = locate(href_list["oocban"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(!M.ckey) //sanity + to_chat(usr, "This mob has no ckey") + return + var/oocbanned = oocban_isbanned("[M.ckey]") + if(oocbanned) + switch(alert("Reason: Remove OOC ban?","Please Confirm","Yes","No")) + if("Yes") + ban_unban_log_save("[key_name(usr)] removed [key_name(M)]'s OOC ban") + log_admin("[key_name(usr)] removed [key_name(M)]'s OOC ban") + feedback_inc("ban_ooc_unban", 1) + DB_ban_unban(M.ckey, BANTYPE_OOC_PERMA) + ooc_unban(M) + message_admins("[key_name_admin(usr)] removed [key_name_admin(M)]'s OOC ban", 1) + to_chat(M, "[usr.client.ckey] has removed your OOC ban.") + else switch(alert("OOC ban [M.ckey]?",,"Yes","No")) + if("Yes") + switch(alert("Temporary Ban?",,"Yes","No", "Cancel")) + if("Yes") + var/mins = input(usr,"How long (in minutes)?","OOC Ban time",1440) as num|null + if(!mins) + return + if(mins >= 525600) mins = 525599 + var/reason = input(usr,"Reason?","reason","Shinposting") as text|null + if(!reason) + return + ban_unban_log_save("[usr.client.ckey] has banned [M.ckey]. - Reason: [reason] - This will be removed in [mins] minutes.") + to_chat(M, "You have been OOC banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "This is a temporary ooc ban, it will be removed in [mins] minutes.") + feedback_inc("ban_ooc_tmp",1) + DB_ban_record(BANTYPE_OOC_TEMP, M, mins, reason) + feedback_inc("ban_ooc_tmp_mins",mins) + if(config.banappeals) + to_chat(M, "To try to resolve this matter head to [config.banappeals] or consider not being a shithead in OOC") + else + to_chat(M, "No ban appeals URL has been set.") + log_admin("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + message_admins("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + + if("No") + var/reason = input(usr,"Reason?","reason","Shinposting") as text|null + if(!reason) + return + to_chat(M, "You have been ooc banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "This is a permanent ooc ban.") + if(config.banappeals) + to_chat(M, "To try to resolve this matter head to [config.banappeals] or consider not being a shithead in OOC") + else + to_chat(M, "No ban appeals URL has been set.") + ban_unban_log_save("[usr.client.ckey] has perma-ooc-banned [M.ckey]. - Reason: [reason] - This is a permanent ooc ban.") + log_admin("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis is a permanent ooc ban.") + message_admins("[usr.client.ckey] has ooc banned [M.ckey].\nReason: [reason]\nThis is a permanent ooc ban.") + feedback_inc("ban_ooc_perma",1) + DB_ban_record(BANTYPE_OOC_PERMA, M, -1, reason) + + if("Cancel") + return + ooc_ban(M) + return + if("No") + return + else + return + + else if(href_list["appearanceban"]) + if(!check_rights(R_BAN)) + return + var/mob/M = locate(href_list["appearanceban"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(!M.ckey) //sanity + to_chat(usr, "This mob has no ckey") + return + + var/banreason = appearance_isbanned(M) + if(banreason) + /* if(!config.ban_legacy_system) + to_chat(usr, "Unfortunately, database based unbanning cannot be done through this panel") + DB_ban_panel(M.ckey) + return */ + switch(alert("Reason: '[banreason]' Remove appearance ban?","Please Confirm","Yes","No")) + if("Yes") + ban_unban_log_save("[key_name(usr)] removed [key_name(M)]'s appearance ban") + log_admin("[key_name(usr)] removed [key_name(M)]'s appearance ban") + feedback_inc("ban_appearance_unban", 1) + DB_ban_unban(M.ckey, BANTYPE_APPEARANCE) + appearance_unban(M) + message_admins("[key_name_admin(usr)] removed [key_name_admin(M)]'s appearance ban", 1) + to_chat(M, "[usr.client.ckey] has removed your appearance ban.") + + else switch(alert("Appearance ban [M.ckey]?",,"Yes","No", "Cancel")) + if("Yes") + var/reason = input(usr,"Reason?","reason","Metafriender") as text|null + if(!reason) + return + ban_unban_log_save("[key_name(usr)] appearance banned [key_name(M)]. reason: [reason]") + log_admin("[key_name(usr)] appearance banned [key_name(M)]. \nReason: [reason]") + feedback_inc("ban_appearance",1) + DB_ban_record(BANTYPE_APPEARANCE, M, -1, reason) + appearance_fullban(M, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") + notes_add(M.ckey, "Appearance banned - [reason]") + message_admins("[key_name_admin(usr)] appearance banned [key_name_admin(M)]", 1) + to_chat(M, "You have been appearance banned by [usr.client.ckey].") + to_chat(M, "The reason is: [reason]") + to_chat(M, "Appearance ban can be lifted only upon request.") + if(config.banappeals) + to_chat(M, "To try to resolve this matter head to [config.banappeals]") + else + to_chat(M, "No ban appeals URL has been set.") + if("No") + return + + else if(href_list["jobban2"]) +// if(!check_rights(R_BAN)) return + + var/mob/M = locate(href_list["jobban2"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(!M.ckey) //sanity + to_chat(usr, "This mob has no ckey") + return + if(!job_master) + to_chat(usr, "Job Master has not been setup!") + return + + var/dat = "" + var/header = "Job-Ban Panel: [M.name]" + var/body + var/jobs = "" + + /***********************************WARNING!************************************ + The jobban stuff looks mangled and disgusting + But it looks beautiful in-game + -Nodrak + ************************************WARNING!***********************************/ + var/counter = 0 +//Regular jobs + //Command (Blue) + jobs += "" + jobs += "" + for(var/jobPos in command_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 6) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
    Command Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " + + //Security (Red) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in security_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
    Security Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " + + //Engineering (Yellow) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in engineering_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
    Engineering Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " + + //Medical (White) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in medical_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
    Medical Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " + + //Science (Purple) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in science_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
    Science Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    " + + //Civilian (Grey) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in civilian_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + + if(jobban_isbanned(M, "Internal Affairs Agent")) + jobs += "" + else + jobs += "" + + jobs += "
    Civilian Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    Internal Affairs AgentInternal Affairs Agent
    " + + //Non-Human (Green) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in nonhuman_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + + //pAI isn't technically a job, but it goes in here. + + if(jobban_isbanned(M, "pAI")) + jobs += "" + else + jobs += "" + if(jobban_isbanned(M, "AntagHUD")) + jobs += "" + else + jobs += "" + jobs += "
    Non-human Positions
    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
    pAIpAIAntagHUDAntagHUD
    " + + //Antagonist (Orange) + var/isbanned_dept = jobban_isbanned(M, "Syndicate") + jobs += "" + jobs += "" + + //Traitor + if(jobban_isbanned(M, "traitor") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Changeling + if(jobban_isbanned(M, "changeling") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Nuke Operative + if(jobban_isbanned(M, "operative") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Revolutionary + if(jobban_isbanned(M, "revolutionary") || isbanned_dept) + jobs += "" + else + jobs += "" + + jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries + + //Cultist + if(jobban_isbanned(M, "cultist") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Wizard + if(jobban_isbanned(M, "wizard") || isbanned_dept) + jobs += "" + else + jobs += "" + + //ERT + if(jobban_isbanned(M, "Emergency Response Team") || isbanned_dept) + jobs += "" + else + jobs += "" + + + //Vox Raider + if(jobban_isbanned(M, "Vox Raider") || isbanned_dept) + jobs += "" + else + jobs += "" + +/* //Malfunctioning AI //Removed Malf-bans because they're a pain to impliment + if(jobban_isbanned(M, "malf AI") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Alien + if(jobban_isbanned(M, "alien candidate") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Infested Monkey + if(jobban_isbanned(M, "infested monkey") || isbanned_dept) + jobs += "" + else + jobs += "" +*/ + + jobs += "
    Antagonist Positions
    [replacetext("Traitor", " ", " ")][replacetext("Traitor", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Changeling", " ", " ")][replacetext("Nuke Operative", " ", " ")][replacetext("Nuke Operative", " ", " ")][replacetext("Revolutionary", " ", " ")][replacetext("Revolutionary", " ", " ")]
    [replacetext("Cultist", " ", " ")][replacetext("Cultist", " ", " ")][replacetext("Wizard", " ", " ")][replacetext("Wizard", " ", " ")]Emergency Response TeamEmergency Response TeamVox RaiderVox Raider[replacetext("Malf AI", " ", " ")][replacetext("Malf AI", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Alien", " ", " ")][replacetext("Infested Monkey", " ", " ")][replacetext("Infested Monkey", " ", " ")]
    " + + //Other races (BLUE, because I have no idea what other color to make this) + jobs += "" + jobs += "" + + if(jobban_isbanned(M, "Dionaea")) + jobs += "" + else + jobs += "" + + jobs += "
    Other Races
    DionaeaDionaea
    " + + + body = "[jobs]" + dat = "[header][body]" + usr << browse(dat, "window=jobban2;size=800x490") + return + + //JOBBAN'S INNARDS + else if(href_list["jobban3"]) + if(!check_rights(R_BAN)) return + + var/mob/M = locate(href_list["jobban4"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(M != usr) //we can jobban ourselves + if(M.client && M.client.holder && (M.client.holder.rights & R_BAN)) //they can ban too. So we can't ban them + alert("You cannot perform this action. You must be of a higher administrative rank!") + return + + if(!job_master) + to_chat(usr, "Job Master has not been setup!") + return + + //get jobs for department if specified, otherwise just returnt he one job in a list. + var/list/joblist = list() + switch(href_list["jobban3"]) + if("commanddept") + for(var/jobPos in command_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("securitydept") + for(var/jobPos in security_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("engineeringdept") + for(var/jobPos in engineering_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("medicaldept") + for(var/jobPos in medical_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("sciencedept") + for(var/jobPos in science_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("civiliandept") + for(var/jobPos in civilian_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("nonhumandept") + joblist += "pAI" + for(var/jobPos in nonhuman_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + else + joblist += href_list["jobban3"] + + //Create a list of unbanned jobs within joblist + var/list/notbannedlist = list() + for(var/job in joblist) + if(!jobban_isbanned(M, job)) + notbannedlist += job + + //Banning comes first + if(notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban. + switch(alert("Temporary Ban?",,"Yes","No", "Cancel")) + if("Yes") + if(config.ban_legacy_system) + to_chat(usr, "Your server is using the legacy banning system, which does not support temporary job bans. Consider upgrading. Aborting ban.") + return + var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null + if(!mins) + return + var/reason = input(usr,"Reason?","Please State Reason","") as text|null + if(!reason) + return + + var/msg + for(var/job in notbannedlist) + ban_unban_log_save("[key_name(usr)] temp-jobbanned [key_name(M)] from [job] for [mins] minutes. reason: [reason]") + log_admin("[key_name(usr)] temp-jobbanned [key_name(M)] from [job] for [mins] minutes") + feedback_inc("ban_job_tmp",1) + DB_ban_record(BANTYPE_JOB_TEMP, M, mins, reason, job) + feedback_add_details("ban_job_tmp","- [job]") + jobban_fullban(M, job, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") //Legacy banning does not support temporary jobbans. + if(!msg) + msg = job + else + msg += ", [job]" + notes_add(M.ckey, "Banned from [msg] - [reason]") + message_admins("[key_name_admin(usr)] banned [key_name_admin(M)] from [msg] for [mins] minutes", 1) + to_chat(M, "You have been jobbanned by [usr.client.ckey] from: [msg].") + to_chat(M, "The reason is: [reason]") + to_chat(M, "This jobban will be lifted in [mins] minutes.") + href_list["jobban2"] = 1 // lets it fall through and refresh + return 1 + if("No") + var/reason = input(usr,"Reason?","Please State Reason","") as text|null + if(reason) + var/msg + for(var/job in notbannedlist) + ban_unban_log_save("[key_name(usr)] perma-jobbanned [key_name(M)] from [job]. reason: [reason]") + log_admin("[key_name(usr)] perma-banned [key_name(M)] from [job]") + feedback_inc("ban_job",1) + DB_ban_record(BANTYPE_JOB_PERMA, M, -1, reason, job) + feedback_add_details("ban_job","- [job]") + jobban_fullban(M, job, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") + if(!msg) msg = job + else msg += ", [job]" + notes_add(M.ckey, "Banned from [msg] - [reason]") + message_admins("[key_name_admin(usr)] banned [key_name_admin(M)] from [msg]", 1) + to_chat(M, "You have been jobbanned by [usr.client.ckey] from: [msg].") + to_chat(M, "The reason is: [reason]") + to_chat(M, "Jobban can be lifted only upon request.") + href_list["jobban2"] = 1 // lets it fall through and refresh + return 1 + if("Cancel") + return + + //Unbanning joblist + //all jobs in joblist are banned already OR we didn't give a reason (implying they shouldn't be banned) + if(joblist.len) //at least 1 banned job exists in joblist so we have stuff to unban. + if(!config.ban_legacy_system) + to_chat(usr, "Unfortunately, database based unbanning cannot be done through this panel") + DB_ban_panel(M.ckey) + return + var/msg + for(var/job in joblist) + var/reason = jobban_isbanned(M, job) + if(!reason) continue //skip if it isn't jobbanned anyway + switch(alert("Job: '[job]' Reason: '[reason]' Un-jobban?","Please Confirm","Yes","No")) + if("Yes") + ban_unban_log_save("[key_name(usr)] unjobbanned [key_name(M)] from [job]") + log_admin("[key_name(usr)] unbanned [key_name(M)] from [job]") + DB_ban_unban(M.ckey, BANTYPE_JOB_PERMA, job) + feedback_inc("ban_job_unban",1) + feedback_add_details("ban_job_unban","- [job]") + jobban_unban(M, job) + if(!msg) msg = job + else msg += ", [job]" + else + continue + if(msg) + message_admins("[key_name_admin(usr)] unbanned [key_name_admin(M)] from [msg]", 1) + to_chat(M, "You have been un-jobbanned by [usr.client.ckey] from [msg].") + href_list["jobban2"] = 1 // lets it fall through and refresh + return 1 + return 0 //we didn't do anything! + + else if(href_list["boot2"]) + var/mob/M = locate(href_list["boot2"]) + if (ismob(M)) + if(!check_if_greater_rights_than(M.client)) + return + to_chat(M, "You have been kicked from the server") + log_admin("[key_name(usr)] booted [key_name(M)].") + message_admins("[key_name_admin(usr)] booted [key_name_admin(M)].", 1) + //M.client = null + del(M.client) +/* + //Player Notes + else if(href_list["notes"]) + var/ckey = href_list["ckey"] + if(!ckey) + var/mob/M = locate(href_list["mob"]) + if(ismob(M)) + ckey = M.ckey + + switch(href_list["notes"]) + if("show") + notes_show(ckey) + if("add") + notes_add(ckey,href_list["text"]) + notes_show(ckey) + if("remove") + notes_remove(ckey,text2num(href_list["from"]),text2num(href_list["to"])) + notes_show(ckey) +*/ + else if(href_list["removejobban"]) + if(!check_rights(R_BAN)) return + + var/t = href_list["removejobban"] + if(t) + if((alert("Do you want to unjobban [t]?","Unjobban confirmation", "Yes", "No") == "Yes") && t) //No more misclicks! Unless you do it twice. + log_admin("[key_name(usr)] removed [t]") + message_admins("[key_name_admin(usr)] removed [t]", 1) + jobban_remove(t) + href_list["ban"] = 1 // lets it fall through and refresh + var/t_split = text2list(t, " - ") + var/key = t_split[1] + var/job = t_split[2] + DB_ban_unban(ckey(key), BANTYPE_JOB_PERMA, job) + + else if(href_list["newban"]) + if(!check_rights(R_BAN)) return + + var/mob/M = locate(href_list["newban"]) + if(!ismob(M)) return + + // now you can! if(M.client && M.client.holder) return //admins cannot be banned. Even if they could, the ban doesn't affect them anyway + + switch(alert("Temporary Ban?",,"Yes","No", "Cancel")) + if("Yes") + var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null + if(!mins) + return + if(mins >= 525600) mins = 525599 + var/reason = input(usr,"Reason?","reason","Griefer") as text|null + if(!reason) + return + AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins) + ban_unban_log_save("[usr.client.ckey] has banned [M.ckey]. - Reason: [reason] - This will be removed in [mins] minutes.") + to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "This is a temporary ban, it will be removed in [mins] minutes.") + feedback_inc("ban_tmp",1) + DB_ban_record(BANTYPE_TEMP, M, mins, reason) + feedback_inc("ban_tmp_mins",mins) + if(config.banappeals) + to_chat(M, "To try to resolve this matter head to [config.banappeals]") + else + to_chat(M, "No ban appeals URL has been set.") + log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + + del(M.client) + //del(M) // See no reason why to delete mob. Important stuff can be lost. And ban can be lifted before round ends. + if("No") + var/reason = input(usr,"Reason?","reason","Griefer") as text|null + if(!reason) + return + switch(alert(usr,"IP ban?",,"Yes","No","Cancel")) + if("Cancel") return + if("Yes") + AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0, M.lastKnownIP) + if("No") + AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0) + var/sticky = alert(usr,"Sticky Ban [M.ckey]? Use this only if you never intend to unban the player.","Sticky Icky","Yes", "No") == "Yes" + if(sticky) + world.SetConfig("keyban",M.ckey,"type=sticky&reason=[reason]&message=[reason]&admin=[ckey(usr.key)]") + message_admins("[key_name_admin(usr)] has sticky banned [key_name(M)].") + log_admin("[key_name(usr)] has sticky banned [key_name(M)].") + to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "This is a permanent ban.") + if(config.banappeals) + to_chat(M, "To try to resolve this matter head to [config.banappeals]") + else + to_chat(M, "No ban appeals URL has been set.") + ban_unban_log_save("[usr.client.ckey] has permabanned [M.ckey]. - Reason: [reason] - This is a permanent ban.") + log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") + message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") + feedback_inc("ban_perma",1) + DB_ban_record(BANTYPE_PERMA, M, -1, reason) + + del(M.client) + //del(M) + if("Cancel") + return + + else if(href_list["unjobbanf"]) + if(!check_rights(R_BAN)) return + + var/banfolder = href_list["unjobbanf"] + Banlist.cd = "/base/[banfolder]" + var/key = Banlist["key"] + if(alert(usr, "Are you sure you want to unban [key]?", "Confirmation", "Yes", "No") == "Yes") + if (RemoveBanjob(banfolder)) + unjobbanpanel() + else + alert(usr,"This ban has already been lifted / does not exist.","Error","Ok") + unjobbanpanel() + + else if(href_list["mute"]) + if(!check_rights(R_ADMIN)) return + + var/mob/M = locate(href_list["mute"]) + if(!ismob(M)) return + if(!M.client) return + + var/mute_type = href_list["mute_type"] + if(istext(mute_type)) mute_type = text2num(mute_type) + if(!isnum(mute_type)) return + + cmd_admin_mute(M, mute_type) + + else if(href_list["c_mode"]) + if(!check_rights(R_ADMIN)) return + + if(ticker && ticker.mode) + return alert(usr, "The game has already started.", null, null, null, null) + var/dat = {"What mode do you wish to play?
    "} + for(var/mode in config.modes) + dat += {"[config.mode_names[mode]]
    "} + dat += {"Secret
    "} + dat += {"Random
    "} + dat += {"Now: [master_mode]"} + usr << browse(dat, "window=c_mode") + + else if(href_list["f_secret"]) + if(!check_rights(R_ADMIN)) return + + if(ticker && ticker.mode) + return alert(usr, "The game has already started.", null, null, null, null) + if(master_mode != "secret") + return alert(usr, "The game mode has to be secret!", null, null, null, null) + var/dat = {"What game mode do you want to force secret to be? Use this if you want to change the game mode, but want the players to believe it's secret. This will only work if the current game mode is secret.
    "} + for(var/mode in config.modes) + dat += {"[config.mode_names[mode]]
    "} + dat += {"Random (default)
    "} + dat += {"Now: [secret_force_mode]"} + usr << browse(dat, "window=f_secret") + + else if(href_list["c_mode2"]) + if(!check_rights(R_ADMIN|R_SERVER)) return + + if (ticker && ticker.mode) + return alert(usr, "The game has already started.", null, null, null, null) + master_mode = href_list["c_mode2"] + log_admin("[key_name(usr)] set the mode as [master_mode].") + message_admins("[key_name_admin(usr)] set the mode as [master_mode].", 1) + to_chat(world, "The mode is now: [master_mode]") + Game() // updates the main game menu + world.save_mode(master_mode) + .(href, list("c_mode"=1)) + + else if(href_list["f_secret2"]) + if(!check_rights(R_ADMIN|R_SERVER)) return + + if(ticker && ticker.mode) + return alert(usr, "The game has already started.", null, null, null, null) + if(master_mode != "secret") + return alert(usr, "The game mode has to be secret!", null, null, null, null) + secret_force_mode = href_list["f_secret2"] + log_admin("[key_name(usr)] set the forced secret mode as [secret_force_mode].") + message_admins("[key_name_admin(usr)] set the forced secret mode as [secret_force_mode].", 1) + Game() // updates the main game menu + .(href, list("f_secret"=1)) + + else if(href_list["monkeyone"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["monkeyone"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + log_admin("[key_name(usr)] attempting to monkeyize [key_name(H)]") + message_admins("[key_name_admin(usr)] attempting to monkeyize [key_name_admin(H)]", 1) + var/mob/M = H.monkeyize() + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["corgione"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["corgione"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + log_admin("[key_name(usr)] attempting to corgize [key_name(H)]") + message_admins("[key_name_admin(usr)] attempting to corgize [key_name_admin(H)]", 1) + var/mob/M = H.corgize() + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["forcespeech"]) + if(!check_rights(R_FUN)) return + + var/mob/M = locate(href_list["forcespeech"]) + if(!ismob(M)) + to_chat(usr, "this can only be used on instances of type /mob") + + var/speech = input("What will [key_name(M)] say?.", "Force speech", "")// Don't need to sanitize, since it does that in say(), we also trust our admins. + if(!speech) return + M.say(speech) + speech = sanitize(speech) // Nah, we don't trust them + log_admin("[key_name(usr)] forced [key_name(M)] to say: [speech]") + message_admins("[key_name_admin(usr)] forced [key_name_admin(M)] to say: [speech]") + + else if(href_list["sendtoprison"]) + // Reworked to be useful for investigating shit. + if(!check_rights(R_ADMIN)) + return + + if(alert(usr, "Warp to prison?", "Message", "Yes", "No") != "Yes") + return + + var/mob/M = locate(href_list["sendtoprison"]) + + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(istype(M, /mob/living/silicon/ai)) + to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") + return + + var/turf/prison_cell = pick(prisonwarp) + + if(!prison_cell) + return + + /* + var/obj/structure/closet/secure_closet/brig/locker = new /obj/structure/closet/secure_closet/brig(prison_cell) + locker.opened = 0 + locker.locked = 1 + + //strip their stuff and stick it in the crate + for(var/obj/item/I in M) + M.u_equip(I,1) + if(I) + I.loc = locker + I.layer = initial(I.layer) + //I.dropped(M) + + M.update_icons() + */ + + //so they black out before warping + M.Paralyse(5) + M.visible_message( + "You hear the sound of cell doors slamming shut, and [M.name] suddenly vanishes!", + "You hear the sound of cell doors slamming shut!") + + sleep(5) + + if(!M) + return + + // TODO: play sound here. Thinking of using Wolfenstein 3D's cell door closing sound. + + M.loc = prison_cell + + /* + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/prisoner = M + prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(prisoner), slot_w_uniform) + prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes) + */ + + to_chat(M, "You have been sent to the prison station!") + log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") + message_admins("[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1) + + else if(href_list["tdome1"] || href_list["tdome2"]) + if(!check_rights(R_FUN)) return + + if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") + return + + var/mob/M = null + var/team = "" + + if(href_list["tdome1"]) + team = "Green" + M = locate(href_list["tdome1"]) + else if (href_list["tdome2"]) + team = "Red" + M = locate(href_list["tdome2"]) + + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(istype(M, /mob/living/silicon/ai)) + to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") + return + + var/obj/item/packobelongings/pack = null + + switch(team) + if("Green") + pack = new /obj/item/packobelongings/green(M.loc) + pack.x = map.tDomeX+2 + if("Red") + pack = new /obj/item/packobelongings/red(M.loc) + pack.x = map.tDomeX-2 + + pack.z = map.tDomeZ //the players' belongings are stored there, in the Thunderdome Admin lodge. + pack.y = map.tDomeY + + pack.name = "[M.real_name]'s belongings" + + for(var/obj/item/I in M) + if(istype(I,/obj/item/clothing/glasses)) + var/obj/item/clothing/glasses/G = I + if(G.prescription) + continue + M.u_equip(I,1) + if(I) + I.loc = M.loc + I.layer = initial(I.layer) + //I.dropped(M) + I.loc = pack + + var/obj/item/weapon/card/id/thunderdome/ident = null + + switch(team) + if("Green") + ident = new /obj/item/weapon/card/id/thunderdome/green(M) + ident.name = "[M.real_name]'s Thunderdome Green ID" + if("Red") + ident = new /obj/item/weapon/card/id/thunderdome/red(M) + ident.name = "[M.real_name]'s Thunderdome Red ID" + + if(!iscarbon(M)) + qdel(ident) + + switch(team) + if("Green") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/green(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_to_slot_or_del(ident, slot_wear_id) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/green(H), slot_belt) + H.regenerate_icons() + else if(ismonkey(M)) + var/mob/living/carbon/monkey/K = M + var/obj/item/clothing/monkeyclothes/jumpsuit_green/JS = new /obj/item/clothing/monkeyclothes/jumpsuit_green(K) + var/obj/item/clothing/monkeyclothes/olduniform = null + var/obj/item/clothing/monkeyclothes/oldhat = null + if(K.uniform) + olduniform = K.uniform + K.uniform = null + olduniform.loc = pack + K.uniform = JS + K.uniform.loc = K + if(K.hat) + oldhat = K.hat + K.hat = null + oldhat.loc = pack + K.equip_to_slot_or_del(ident, slot_r_hand) + K.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/green(K), slot_l_hand) + K.regenerate_icons() + + if("Red") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/red(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_to_slot_or_del(ident, slot_wear_id) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/red(H), slot_belt) + H.regenerate_icons() + else if(ismonkey(M)) + var/mob/living/carbon/monkey/K = M + var/obj/item/clothing/monkeyclothes/jumpsuit_red/JS = new /obj/item/clothing/monkeyclothes/jumpsuit_red(K) + var/obj/item/clothing/monkeyclothes/olduniform = null + var/obj/item/clothing/monkeyclothes/oldhat = null + if(K.uniform) + olduniform = K.uniform + K.uniform = null + olduniform.loc = pack + K.uniform = JS + K.uniform.loc = K + if(K.hat) + oldhat = K.hat + K.hat = null + oldhat.loc = pack + K.equip_to_slot_or_del(ident, slot_r_hand) + K.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/thunderdome/red(K), slot_l_hand) + K.regenerate_icons() + + if(pack.contents.len == 0) + qdel(pack) + + switch(team) + if("Green") + log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team Green)") + message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team Green)", 1) + M.loc = pick(tdome1) + if("Red") + log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team Red)") + message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team Red)", 1) + M.loc = pick(tdome2) + + to_chat(M, "You have been chosen to fight for the [team] Team. [pick(\ + "The wheel of fate is turning!",\ + "Heaven or Hell!",\ + "Set Spell Card!",\ + "Hologram Summer Again!",\ + "Get ready for the next battle!",\ + "Fight for your life!",\ + )]") + + else if(href_list["tdomeadmin"]) + if(!check_rights(R_FUN)) return + + if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") + return + + var/mob/M = locate(href_list["tdomeadmin"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(istype(M, /mob/living/silicon/ai)) + to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") + return + + M.Paralyse(5) + sleep(5) + M.loc = pick(tdomeadmin) + spawn(50) + to_chat(M, "You have been sent to the Thunderdome.") + log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Admin.)") + message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Admin.)", 1) + + else if(href_list["tdomeobserve"]) + if(!check_rights(R_FUN)) return + + if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") + return + + var/mob/M = locate(href_list["tdomeobserve"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + if(istype(M, /mob/living/silicon/ai)) + to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") + return + + for(var/obj/item/I in M) + M.u_equip(I,1) + if(I) + I.loc = M.loc + I.layer = initial(I.layer) + //I.dropped(M) + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/observer = M + observer.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket(observer), slot_w_uniform) + observer.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(observer), slot_shoes) + M.Paralyse(5) + sleep(5) + M.loc = pick(tdomeobserve) + spawn(50) + to_chat(M, "You have been sent to the Thunderdome.") + log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Observer.)") + message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Observer.)", 1) + + else if(href_list["revive"]) + if(!check_rights(R_REJUVINATE)) return + + var/mob/living/L = locate(href_list["revive"]) + if(!istype(L)) + to_chat(usr, "This can only be used on instances of type /mob/living") + return + + if(config.allow_admin_rev) + L.revive(0) + message_admins("Admin [key_name_admin(usr)] healed / revived [key_name_admin(L)]!", 1) + log_admin("[key_name(usr)] healed / revived [key_name(L)]") + else + to_chat(usr, "Admin Rejuvinates have been disabled") + + else if(href_list["makeai"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makeai"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + message_admins("Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!", 1) + log_admin("[key_name(usr)] AIized [key_name(H)]") + var/mob/M = H.AIize() + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["makealien"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makealien"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/mob/M = usr.client.cmd_admin_alienize(H) + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["makeslime"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makeslime"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/mob/M = usr.client.cmd_admin_slimeize(H) + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["makecluwne"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makecluwne"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/mob/M = usr.client.cmd_admin_cluwneize(H) + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["makerobot"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makerobot"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/mob/M = usr.client.cmd_admin_robotize(H) + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["makemommi"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makemommi"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + var/mob/M = usr.client.cmd_admin_mommify(H) + if(M) + if(M.client == CLIENT) usr = M //We probably transformed ourselves + show_player_panel(M) + + else if(href_list["makeanimal"]) + if(!check_rights(R_SPAWN)) return + + var/mob/M = locate(href_list["makeanimal"]) + if(istype(M, /mob/new_player)) + to_chat(usr, "This cannot be used on instances of type /mob/new_player") + return + + var/mob/new_mob = usr.client.cmd_admin_animalize(M) + if(new_mob && new_mob != M) + if(new_mob.client == CLIENT) usr = new_mob //We probably transformed ourselves + show_player_panel(new_mob) + + else if(href_list["togmutate"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["togmutate"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + var/block=text2num(href_list["block"]) + //testing("togmutate([href_list["block"]] -> [block])") + usr.client.cmd_admin_toggle_block(H,block) + show_player_panel(H) + //H.regenerate_icons() + +/***************** BEFORE************** + + if (href_list["l_players"]) + var/dat = "Name/Real Name/Key/IP:
    " + for(var/mob/M in world) + var/foo = "" + if (ismob(M) && M.client) + if(!M.client.authenticated && !M.client.authenticating) + foo += text("\[ Authorize | ", src, M) + else + foo += text("\[ Authorized | ") + if(M.start) + if(!istype(M, /mob/living/carbon/monkey)) + foo += text("Monkeyize | ", src, M) + else + foo += text("Monkeyized | ") + if(istype(M, /mob/living/silicon/ai)) + foo += text("Is an AI | ") + else + foo += text("Make AI | ", src, M) + if(M.z != 2) + foo += text("Prison | ", src, M) + foo += text("Maze | ", src, M) + else + foo += text("On Z = 2 | ") + else + foo += text("Hasn't Entered Game | ") + foo += text("Heal/Revive | ", src, M) + + foo += text("Say \]", src, M) + dat += text("N: [] R: [] (K: []) (IP: []) []
    ", M.name, M.real_name, (M.client ? M.client : "No client"), M.lastKnownIP, foo) + + usr << browse(dat, "window=players;size=900x480") + +*****************AFTER******************/ + +// Now isn't that much better? IT IS NOW A PROC, i.e. kinda like a big panel like unstable + + else if(href_list["adminplayeropts"]) + var/mob/M = locate(href_list["adminplayeropts"]) + show_player_panel(M) + + else if(href_list["adminplayerobservejump"]) + if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN)) return + + var/mob/M = locate(href_list["adminplayerobservejump"]) + + var/client/C = usr.client + if(!isobserver(usr)) C.admin_ghost() + sleep(2) + if(C) C.jumptomob(M) + + else if(href_list["check_antagonist"]) + check_antagonists() + + else if(href_list["cult_nextobj"]) + if(alert(usr, "Validate the current Cult objective and unlock the next one?", "Cult Cheat Code", "Yes", "No") != "Yes") + return + + var/datum/game_mode/cult/mode_ticker = ticker.mode + mode_ticker.bypass_phase() + message_admins("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.") + log_admin("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.") + check_antagonists() + + else if(href_list["cult_mindspeak"]) + var/input = stripped_input(usr, "Communicate to all the cultists with the voice of Nar-Sie", "Voice of Nar-Sie", "") + if(!input) + return + + for(var/datum/mind/H in ticker.mode.cult) + if (H.current) + to_chat(H.current, "Nar-Sie murmurs, [input]") + + for(var/mob/dead/observer/O in player_list) + to_chat(O, "Nar-Sie murmurs, [input]") + + message_admins("Admin [key_name_admin(usr)] has talked with the Voice of Nar-Sie.") + log_narspeak("[key_name(usr)] Voice of Nar-Sie: [input]") + + else if(href_list["cult_privatespeak"]) + var/mob/M = locate(href_list["cult_privatespeak"]) + if(!M) + return + + var/input = stripped_input(usr, "Whisper to [M.real_name] with the voice of Nar-Sie", "Voice of Nar-Sie", "") + if(!input) + return + + to_chat(M, "Nar-Sie whispers to you, [input]") + + for(var/mob/dead/observer/O in player_list) + to_chat(O, "Nar-Sie whispers to [M.real_name], [input]") + + message_admins("Admin [key_name_admin(usr)] has talked with the Voice of Nar-Sie.") + + else if(href_list["adminplayerobservecoodjump"]) + if(!check_rights(R_ADMIN)) return + + var/x = text2num(href_list["X"]) + var/y = text2num(href_list["Y"]) + var/z = text2num(href_list["Z"]) + + var/client/C = usr.client + if(!isobserver(usr)) C.admin_ghost() + sleep(2) + C.jumptocoord(x,y,z) + + else if(href_list["adminchecklaws"]) + output_ai_laws() + + else if(href_list["adminmoreinfo"]) + var/mob/M = locate(href_list["adminmoreinfo"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + var/location_description = "" + var/special_role_description = "" + var/health_description = "" + var/gender_description = "" + var/species_description = "Not A Human" + var/turf/T = get_turf(M) + + //Location + if(isturf(T)) + if(isarea(T.loc)) + location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area [T.loc])" + else + location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])" + + //Job + antagonist + if(M.mind) + special_role_description = "Role: [M.mind.assigned_role]; Antagonist: [M.mind.special_role]; Has been rev: [(M.mind.has_been_rev)?"Yes":"No"]" + else + special_role_description = "Role: Mind datum missing Antagonist: Mind datum missing; Has been rev: Mind datum missing;" + + //Health + if(isliving(M)) + var/mob/living/L = M + var/status + switch (M.stat) + if (0) status = "Alive" + if (1) status = "Unconscious" + if (2) status = "Dead" + health_description = "Status = [status]" + health_description += "
    Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]" + else + health_description = "This mob type has no health to speak of." + + //Gener + switch(M.gender) + if(MALE,FEMALE) gender_description = "[M.gender]" + else gender_description = "[M.gender]" + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + species_description = "[H.species ? H.species.name : "No Species"]" + to_chat(src.owner, "Info about [M.name]: ") + to_chat(src.owner, "Mob type = [M.type]; Species = [species_description]; Gender = [gender_description]; Damage = [health_description];") + to_chat(src.owner, "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];") + to_chat(src.owner, "Location = [location_description];") + to_chat(src.owner, "[special_role_description]") + to_chat(src.owner, "(PM) (PP) (VV) (SM) (JMP) (CA)") + + else if(href_list["adminspawncookie"]) + if(!check_rights(R_ADMIN|R_FUN)) return + + var/mob/living/carbon/human/H = locate(href_list["adminspawncookie"]) + if(!ishuman(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + H.equip_to_slot_or_del( new /obj/item/weapon/reagent_containers/food/snacks/cookie(H), slot_l_hand ) + if(!(istype(H.l_hand,/obj/item/weapon/reagent_containers/food/snacks/cookie))) + H.equip_to_slot_or_del( new /obj/item/weapon/reagent_containers/food/snacks/cookie(H), slot_r_hand ) + if(!(istype(H.r_hand,/obj/item/weapon/reagent_containers/food/snacks/cookie))) + log_admin("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") + message_admins("[key_name(H)] has their hands full, so they did not receive their cookie, spawned by [key_name(src.owner)].") + return + else + H.update_inv_r_hand()//To ensure the icon appears in the HUD + else + H.update_inv_l_hand() + log_admin("[key_name(H)] got their cookie, spawned by [key_name(src.owner)]") + message_admins("[key_name(H)] got their cookie, spawned by [key_name(src.owner)]") + feedback_inc("admin_cookies_spawned",1) + to_chat(H, "Your prayers have been answered!! You received the best cookie!") + + else if(href_list["BlueSpaceArtillery"]) + if(!check_rights(R_ADMIN|R_FUN)) return + + var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) + if(!isliving(M)) + to_chat(usr, "This can only be used on instances of type /mob/living") + return + + if(alert(src.owner, "Are you sure you wish to hit [key_name(M)] with Blue Space Artillery?", "Confirm Firing?" , "Yes" , "No") != "Yes") + return + + if(BSACooldown) + to_chat(src.owner, "Standby! Reload cycle in progress! Gunnary crews ready in five seconds!") + return + + BSACooldown = 1 + spawn(50) + BSACooldown = 0 + + to_chat(M, "You've been hit by bluespace artillery!") + log_admin("[key_name(M)] has been hit by Bluespace Artillery fired by [src.owner]") + message_admins("[key_name(M)] has been hit by Bluespace Artillery fired by [src.owner]") + + var/obj/effect/stop/S + S = new /obj/effect/stop + S.victim = M + S.loc = M.loc + spawn(20) + del(S) + + var/turf/simulated/floor/T = get_turf(M) + if(istype(T)) + if(prob(80)) T.break_tile_to_plating() + else T.break_tile() + + if(M.health == 1) + M.gib() + else + M.adjustBruteLoss( min( 99 , (M.health - 1) ) ) + M.Stun(20) + M.Weaken(20) + M.stuttering = 20 + + else if(href_list["CentcommReply"]) + var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + if(!istype(H.ears, /obj/item/device/radio/headset)) + to_chat(usr, "The person you are trying to contact is not wearing a headset") + return + + var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from Centcomm", "") + if(!input) return + + to_chat(src.owner, "You sent [input] to [H] via a secure channel.") + log_admin("[src.owner] replied to [key_name(H)]'s Centcomm message with the message [input].") + message_admins("[src.owner] replied to [key_name(H)]'s Centcom message with: \"[input]\"") + to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows. \"[input]\" Message ends.\"") + + else if(href_list["SyndicateReply"]) + var/mob/living/carbon/human/H = locate(href_list["SyndicateReply"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + if(!istype(H.ears, /obj/item/device/radio/headset)) + to_chat(usr, "The person you are trying to contact is not wearing a headset") + return + + var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from The Syndicate", "") + if(!input) return + + to_chat(src.owner, "You sent [input] to [H] via a secure channel.") + log_admin("[src.owner] replied to [key_name(H)]'s Syndicate message with the message [input].") + to_chat(H, "You hear something crackle in your headset for a moment before a voice speaks. \"Please stand by for a message from your benefactor. Message as follows, agent. \"[input]\" Message ends.\"") + + else if(href_list["CentcommFaxView"]) + var/obj/item/weapon/paper/P = locate(href_list["CentcommFaxView"]) + var/info_2 = "" + if(P.img) + usr << browse_rsc(P.img.img, "tmp_photo.png") + info_2 = "
    " + usr << browse("Centcomm Fax Message[info_2][P.info][P.stamps]", "window=Centcomm Fax Message") + + else if(href_list["CentcommFaxReply"]) + var/mob/living/carbon/human/H = locate(href_list["CentcommFaxReply"]) + + + var/sent = input(src.owner, "Please enter a message to reply to [key_name(H)] via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
    for line breaks.", "Outgoing message from Centcomm", "") as message|null + if(!sent) return + + var/sentname = input(src.owner, "Pick a title for the report", "Title") as text|null + + SendFax(sent, sentname, centcomm = 1) + + to_chat(src.owner, "Message reply to transmitted successfully.") + log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [sent]") + message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]", 1) + + + else if(href_list["jumpto"]) + if(!check_rights(R_ADMIN)) return + + var/mob/M = locate(href_list["jumpto"]) + usr.client.jumptomob(M) + + else if(href_list["getmob"]) + if(!check_rights(R_ADMIN)) return + + if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") return + var/mob/M = locate(href_list["getmob"]) + usr.client.Getmob(M) + + else if(href_list["sendmob"]) + if(!check_rights(R_ADMIN)) return + + var/mob/M = locate(href_list["sendmob"]) + usr.client.sendmob(M) + + else if(href_list["narrateto"]) + if(!check_rights(R_ADMIN)) return + + var/mob/M = locate(href_list["narrateto"]) + usr.client.cmd_admin_direct_narrate(M) + + else if(href_list["subtlemessage"]) + if(!check_rights(R_ADMIN)) return + + var/mob/M = locate(href_list["subtlemessage"]) + usr.client.cmd_admin_subtle_message(M) + + else if(href_list["rapsheet"]) + checkSessionKey() + // build the link + //var/dat = "[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]" + //if(href_list["rsckey"]) + //. dat += "&ckey=[href_list["rsckey"]]" +// to_chat(usr, link(dat)) + usr << link(getVGPanel("rapsheet", admin = 1, query = list("ckey" = href_list["rsckey"]))) + return + + else if(href_list["bansheet"]) + //checkSessionKey() +// to_chat(usr, link("[config.vgws_base_url]/index.php/rapsheet/?s=[sessKey]")) + usr << link(getVGPanel("rapsheet", admin = 1)) + return + + else if(href_list["traitor"]) + if(!check_rights(R_ADMIN|R_MOD)) return + + if(!ticker || !ticker.mode) + alert("The game hasn't started yet!") + return + + var/mob/M = locate(href_list["traitor"]) + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob.") + return + show_traitor_panel(M) + + // /vg/ + else if(href_list["set_base_laws"]) + if(!check_rights(R_FUN)) + to_chat(usr, "You don't have +FUN. Go away.") + return + var/lawtypes = typesof(/datum/ai_laws) - /datum/ai_laws + var/selected_law = input("Select the default lawset desired.","Lawset Selection",null) as null|anything in lawtypes + if(!selected_law) return + var/subject="Unknown" + switch(href_list["set_base_laws"]) + if("ai") + base_law_type = selected_law + subject = "AIs and Cyborgs" + if("mommi") + mommi_base_law_type = selected_law + subject = "MoMMIs" + to_chat(usr, "New [subject] will spawn with the [selected_law] lawset.") + log_admin("[key_name(src.owner)] set the default laws of [subject] to: [selected_law]") + message_admins("[key_name_admin(src.owner)] set the default laws of [subject] to: [selected_law]", 1) + lawchanges.Add("[key_name_admin(src.owner)] set the default laws of [subject] to: [selected_law]") + + else if(href_list["create_object"]) + if(!check_rights(R_SPAWN)) return + return create_object(usr) + + else if(href_list["quick_create_object"]) + if(!check_rights(R_SPAWN)) return + return quick_create_object(usr) + + else if(href_list["create_turf"]) + if(!check_rights(R_SPAWN)) return + return create_turf(usr) + + else if(href_list["create_mob"]) + if(!check_rights(R_SPAWN)) return + return create_mob(usr) + + else if(href_list["object_list"]) //this is the laggiest thing ever + if(!check_rights(R_SPAWN)) return + + if(!config.allow_admin_spawning) + to_chat(usr, "Spawning of items is not allowed.") + return + + var/atom/loc = usr.loc + + var/dirty_paths + if (istext(href_list["object_list"])) + dirty_paths = list(href_list["object_list"]) + else if (istype(href_list["object_list"], /list)) + dirty_paths = href_list["object_list"] + + var/paths = list() + var/removed_paths = list() + + for(var/dirty_path in dirty_paths) + var/path = text2path(dirty_path) + if(!path) + removed_paths += dirty_path + continue + else if(!ispath(path, /obj) && !ispath(path, /turf) && !ispath(path, /mob)) + removed_paths += dirty_path + continue + else if(ispath(path, /obj/item/weapon/gun/energy/pulse_rifle)) + if(!check_rights(R_FUN,0)) + removed_paths += dirty_path + continue + else if(ispath(path, /obj/effect/bhole)) + if(!check_rights(R_FUN,0)) + removed_paths += dirty_path + continue + paths += path + + if(!paths) + alert("The path list you sent is empty") + return + if(length(paths) > 5) + alert("Select fewer object types, (max 5)") + return + else if(length(removed_paths)) + alert("Removed:\n" + list2text(removed_paths, "\n")) + + var/list/offset = text2list(href_list["offset"],",") + var/number = Clamp(text2num(href_list["object_count"]), 1, 100) + var/X = offset.len > 0 ? text2num(offset[1]) : 0 + var/Y = offset.len > 1 ? text2num(offset[2]) : 0 + var/Z = offset.len > 2 ? text2num(offset[3]) : 0 + var/tmp_dir = href_list["object_dir"] + var/obj_dir = tmp_dir ? text2num(tmp_dir) : 2 + if(!obj_dir || !(obj_dir in alldirs)) + obj_dir = 2 + var/obj_name = sanitize(href_list["object_name"]) + var/where = href_list["object_where"] + if (!( where in list("onfloor","inhand","inmarked") )) + where = "onfloor" + + if( where == "inhand" ) + to_chat(usr, "Support for inhand not available yet. Will spawn on floor.") + where = "onfloor" + + if ( where == "inhand" ) //Can only give when human or monkey + if ( !( ishuman(usr) || ismonkey(usr) ) ) + to_chat(usr, "Can only spawn in hand when you're a human or a monkey.") + where = "onfloor" + else if ( usr.get_active_hand() ) + to_chat(usr, "Your active hand is full. Spawning on floor.") + where = "onfloor" + + if ( where == "inmarked" ) + if ( !marked_datum ) + to_chat(usr, "You don't have any object marked. Abandoning spawn.") + return + else + if ( !istype(marked_datum,/atom) ) + to_chat(usr, "The object you have marked cannot be used as a target. Target must be of type /atom. Abandoning spawn.") + return + + var/atom/target //Where the object will be spawned + switch ( where ) + if ( "onfloor" ) + switch (href_list["offset_type"]) + if ("absolute") + target = locate(0 + X,0 + Y,0 + Z) + if ("relative") + target = locate(loc.x + X,loc.y + Y,loc.z + Z) + if ( "inmarked" ) + target = marked_datum + + if(target) + for (var/path in paths) + for (var/i = 0; i < number; i++) + if(path in typesof(/turf)) + var/turf/O = target + var/turf/N = O.ChangeTurf(path) + if(N) + if(obj_name) + N.name = obj_name + else + var/atom/O = new path(target) + if(O) + O.dir = obj_dir + if(obj_name) + O.name = obj_name + if(istype(O,/mob)) + var/mob/M = O + M.real_name = obj_name + + if (number == 1) + log_admin("[key_name(usr)] created a [english_list(paths)] at [formatJumpTo(get_turf(usr))]") + for(var/path in paths) + if(ispath(path, /mob)) + message_admins("[key_name_admin(usr)] created a [english_list(paths)] at [formatJumpTo(get_turf(usr))]", 1) + break + else + log_admin("[key_name(usr)] created [number]ea [english_list(paths)] at [formatJumpTo(get_turf(usr))]") + for(var/path in paths) + if(ispath(path, /mob)) + message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)] at [formatJumpTo(get_turf(usr))]", 1) + break + return + + else if(href_list["secretsfun"]) + if(!check_rights(R_FUN)) return + + var/ok = 0 + switch(href_list["secretsfun"]) + if("sec_clothes") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SC") + for(var/obj/item/clothing/under/O in world) + del(O) + ok = 1 + if("sec_all_clothes") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SAC") + for(var/obj/item/clothing/O in world) + del(O) + ok = 1 + if("sec_classic1") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SC1") + for(var/obj/item/clothing/suit/fire/O in world) + del(O) + for(var/obj/structure/grille/O in world) + del(O) +/* for(var/obj/machinery/vehicle/pod/O in world) + for(var/mob/M in src) + M.loc = src.loc + if (M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = M + del(O) + ok = 1*/ + if("monkey") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","M") + for(var/mob/living/carbon/human/H in mob_list) + spawn(0) + H.monkeyize() + ok = 1 + if("corgi") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","M") + for(var/mob/living/carbon/human/H in mob_list) + spawn(0) + H.corgize() + ok = 1 + if("striketeam") + if(usr.client.strike_team()) + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Strike") + if("tripleAI") + usr.client.triple_ai() + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","TriAI") + if("gravity") + if(!(ticker && ticker.mode)) + to_chat(usr, "Please wait until the game starts! Not sure how it will work otherwise.") + return + gravity_is_on = !gravity_is_on + for(var/area/A in areas) + A.gravitychange(gravity_is_on,A) + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Grav") + if(gravity_is_on) + log_admin("[key_name(usr)] toggled gravity on.", 1) + message_admins("[key_name_admin(usr)] toggled gravity on.", 1) + command_alert("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") + else + log_admin("[key_name(usr)] toggled gravity off.", 1) + message_admins("[key_name_admin(usr)] toggled gravity off.", 1) + command_alert("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") + if("wave") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Meteor") + log_admin("[key_name(usr)] spawned a meteor wave", 1) + message_admins("[key_name_admin(usr)] spawned a meteor wave.", 1) + new /datum/event/meteor_wave + if("goblob") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Blob") + log_admin("[key_name(usr)] spawned a blob", 1) + message_admins("[key_name_admin(usr)] spawned a blob.", 1) + new /datum/event/blob + + if("aliens") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Aliens") + log_admin("[key_name(usr)] spawned an alien infestation", 1) + message_admins("[key_name_admin(usr)] attempted an alien infestation", 1) + new /datum/event/alien_infestation + + + if("power") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","P") + log_admin("[key_name(usr)] made all areas powered", 1) + message_admins("[key_name_admin(usr)] made all areas powered", 1) + power_restore() + if("unpower") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","UP") + log_admin("[key_name(usr)] made all areas unpowered", 1) + message_admins("[key_name_admin(usr)] made all areas unpowered", 1) + power_failure() + if("quickpower") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","QP") + log_admin("[key_name(usr)] made all SMESs powered", 1) + message_admins("[key_name_admin(usr)] made all SMESs powered", 1) + power_restore_quick() + if("activateprison") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","AP") + to_chat(world, "Transit signature detected.") + to_chat(world, "Incoming shuttle.") + /* + var/A = locate(/area/shuttle_prison) + for(var/atom/movable/AM as mob|obj in A) + AM.z = 1 + AM.Move() + */ + message_admins("[key_name_admin(usr)] sent the prison shuttle to the station.", 1) + if("deactivateprison") + /* + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","DP") + var/A = locate(/area/shuttle_prison) + for(var/atom/movable/AM as mob|obj in A) + AM.z = 2 + AM.Move() + */ + message_admins("[key_name_admin(usr)] sent the prison shuttle back.", 1) + if("toggleprisonstatus") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","TPS") + for(var/obj/machinery/computer/prison_shuttle/PS in machines) + PS.allowedtocall = !(PS.allowedtocall) + message_admins("[key_name_admin(usr)] toggled status of prison shuttle to [PS.allowedtocall].", 1) + if ("prisonwarp") + if (!ticker) + alert("The game hasn't started yet!", null, null, null, null, null) + return + + feedback_inc("admin_secrets_fun_used", 1) + + feedback_add_details("admin_secrets_fun_used", "PW") + + message_admins("[key_name_admin(usr)] teleported all players to the prison station.", 1) + + var/security + + for (var/mob/living/carbon/human/H in mob_list) + if (H) + if (H in prisonwarped) // don't warp them if they aren't ready or are already there + continue + + security = FALSE + + H.Paralyse(5) + + var/obj/item/weapon/card/id/id = H.get_id_card() + + if(id) + if (access_security in id.access) + security = TRUE + + if (!security) + // strip their stuff before they teleport into a cell :downs: + for (var/obj/item/I in H.get_all_slots()) + H.drop_from_inventory(I) + + H.loc = pick(prisonwarp) // teleport person to cell + + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/prisoner(H), slot_w_uniform) + + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) + else + H.loc = pick(prisonsecuritywarp) // teleport security person + + prisonwarped += H + if("traitor_all") + if(!ticker) + alert("The game hasn't started yet!") + return + var/objective = copytext(sanitize(input("Enter an objective")),1,MAX_MESSAGE_LEN) + if(!objective) + return + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","TA([objective])") + for(var/mob/living/carbon/human/H in player_list) + if(H.stat == 2 || !H.client || !H.mind) continue + if(is_special_character(H)) continue + //traitorize(H, objective, 0) + ticker.mode.traitors += H.mind + H.mind.special_role = "traitor" + var/datum/objective/new_objective = new + new_objective.owner = H + new_objective.explanation_text = objective + H.mind.objectives += new_objective + ticker.mode.greet_traitor(H.mind) + //ticker.mode.forge_traitor_objectives(H.mind) + ticker.mode.finalize_traitor(H.mind) + for(var/mob/living/silicon/A in player_list) + ticker.mode.traitors += A.mind + A.mind.special_role = "traitor" + var/datum/objective/new_objective = new + new_objective.owner = A + new_objective.explanation_text = objective + A.mind.objectives += new_objective + ticker.mode.greet_traitor(A.mind) + ticker.mode.finalize_traitor(A.mind) + message_admins("[key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]", 1) + log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") + if("moveadminshuttle") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ShA") + move_admin_shuttle() + message_admins("[key_name_admin(usr)] moved the centcom administration shuttle", 1) + log_admin("[key_name(usr)] moved the centcom administration shuttle") + if("moveferry") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ShF") + if(!transport_shuttle || !transport_shuttle.linked_area) + to_chat(usr, "There is no transport shuttle!") + return + + transport_shuttle.move(usr) + + message_admins("[key_name_admin(usr)] moved the centcom ferry", 1) + log_admin("[key_name(usr)] moved the centcom ferry") + if("movealienship") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ShX") + move_alien_ship() + message_admins("[key_name_admin(usr)] moved the alien dinghy", 1) + log_admin("[key_name(usr)] moved the alien dinghy") + if("togglebombcap") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BC") + switch(MAX_EXPLOSION_RANGE) + if(14) MAX_EXPLOSION_RANGE = 16 + if(16) MAX_EXPLOSION_RANGE = 20 + if(20) MAX_EXPLOSION_RANGE = 28 + if(28) MAX_EXPLOSION_RANGE = 56 + if(56) MAX_EXPLOSION_RANGE = 128 + else MAX_EXPLOSION_RANGE = 14 + var/range_dev = MAX_EXPLOSION_RANGE *0.25 + var/range_high = MAX_EXPLOSION_RANGE *0.5 + var/range_low = MAX_EXPLOSION_RANGE + message_admins(" [key_name_admin(usr)] changed the bomb cap to [range_dev], [range_high], [range_low]", 1) + log_admin("[key_name_admin(usr)] changed the bomb cap to [MAX_EXPLOSION_RANGE]") + + if("flicklights") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FL") + while(!usr.stat) +//knock yourself out to stop the ghosts + for(var/mob/M in player_list) + if(M.stat != 2 && prob(25)) + var/area/AffectedArea = get_area(M) + if(AffectedArea.name != "Space" && AffectedArea.name != "Engine Walls" && AffectedArea.name != "Chemical Lab Test Chamber" && AffectedArea.name != "Escape Shuttle" && AffectedArea.name != "Arrival Area" && AffectedArea.name != "Arrival Shuttle" && AffectedArea.name != "start area" && AffectedArea.name != "Engine Combustion Chamber") + AffectedArea.power_light = 0 + AffectedArea.power_change() + spawn(rand(55,185)) + AffectedArea.power_light = 1 + AffectedArea.power_change() + var/Message = rand(1,4) + switch(Message) + if(1) + M.show_message(text("You shudder as if cold..."), 1) + if(2) + M.show_message(text("You feel something gliding across your back..."), 1) + if(3) + M.show_message(text("Your eyes twitch, you feel like something you can't see is here..."), 1) + if(4) + M.show_message(text("You notice something moving out of the corner of your eye, but nothing is there..."), 1) + for(var/obj/W in orange(5,M)) + if(prob(25) && !W.anchored) + step_rand(W) + sleep(rand(100,1000)) + for(var/mob/M in player_list) + if(M.stat != 2) + M.show_message(text("The chilling wind suddenly stops..."), 1) +/* if("shockwave") + ok = 1 + to_chat(world, "ALERT: STATION STRESS CRITICAL") + sleep(60) + to_chat(world, "ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!") + sleep(80) + to_chat(world, "ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!") + sleep(40) + for(var/mob/M in world) + shake_camera(M, 400, 1) + for(var/obj/structure/window/W in world) + spawn(0) + sleep(rand(10,400)) + W.ex_act(rand(2,1)) + for(var/obj/structure/grille/G in world) + spawn(0) + sleep(rand(20,400)) + G.ex_act(rand(2,1)) + for(var/obj/machinery/door/D in world) + spawn(0) + sleep(rand(20,400)) + D.ex_act(rand(2,1)) + for(var/turf/station/floor/Floor in world) + spawn(0) + sleep(rand(30,400)) + Floor.ex_act(rand(2,1)) + for(var/obj/structure/cable/Cable in world) + spawn(0) + sleep(rand(30,400)) + Cable.ex_act(rand(2,1)) + for(var/obj/structure/closet/Closet in world) + spawn(0) + sleep(rand(30,400)) + Closet.ex_act(rand(2,1)) + for(var/obj/machinery/Machinery in world) + spawn(0) + sleep(rand(30,400)) + Machinery.ex_act(rand(1,3)) + for(var/turf/station/wall/Wall in world) + spawn(0) + sleep(rand(30,400)) + Wall.ex_act(rand(2,1)) */ + if("wave") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","MW") + new /datum/event/meteor_wave + + if("gravanomalies") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","GA") + command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert") + to_chat(world, sound('sound/AI/granomalies.ogg')) + var/turf/T = pick(blobstart) + var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 ) + spawn(rand(100, 600)) + del(bh) + + if("timeanomalies") //dear god this code was awful :P Still needs further optimisation + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","STA") + //moved to its own dm so I could split it up and prevent the spawns copying variables over and over + //can be found in code\game\game_modes\events\wormholes.dm + wormhole_event() + + if("goblob") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BL") + mini_blob_event() + message_admins("[key_name_admin(usr)] has spawned blob", 1) + if("aliens") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","AL") + if(aliens_allowed) + new /datum/event/alien_infestation + message_admins("[key_name_admin(usr)] has spawned aliens", 1) + if("alien_silent") //replaces the spawn_xeno verb + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ALS") + if(aliens_allowed) + create_xeno() + if("spiders") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SL") + new /datum/event/spider_infestation + message_admins("[key_name_admin(usr)] has spawned spiders", 1) + if("comms_blackout") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","CB") + var/answer = alert(usr, "Would you like to alert the crew?", "Alert", "Yes", "No") + if(answer == "Yes") + communications_blackout(0) + else + communications_blackout(1) + message_admins("[key_name_admin(usr)] triggered a communications blackout.", 1) + + if("pda_spam") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","PDA") + new /datum/event/pda_spam + + if("carp") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","C") + var/choice = input("You sure you want to spawn carp?") in list("Badmin", "Cancel") + if(choice == "Badmin") + message_admins("[key_name_admin(usr)] has spawned carp.", 1) + new /datum/event/carp_migration + if("radiation") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","R") + message_admins("[key_name_admin(usr)] has has irradiated the station", 1) + new /datum/event/radiation_storm + if("immovable") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","IR") + message_admins("[key_name_admin(usr)] has sent an immovable rod to the station", 1) + immovablerod() + if("prison_break") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","PB") + message_admins("[key_name_admin(usr)] has allowed a prison break", 1) + prison_break() + if("lightout") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","LO") + message_admins("[key_name_admin(usr)] has broke a lot of lights", 1) + lightsout(1,2) + if("blackout") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BO") + message_admins("[key_name_admin(usr)] broke all lights", 1) + lightsout(0,0) + if("whiteout") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","WO") + for(var/obj/machinery/light/L in alllights) + L.fix() + message_admins("[key_name_admin(usr)] fixed all lights", 1) + if("aliens") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","AL") + message_admins("[key_name_admin(usr)] has spawned aliens", 1) + //makeAliens() + new /datum/event/alien_infestation + if("radiation") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","RAD") + message_admins("[key_name_admin(usr)] has started a radiation event", 1) + //makeAliens() + new /datum/event/radiation_storm + if("floorlava") + if(floorIsLava) + to_chat(usr, "The floor is lava already.") + return + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","LF") + + //Options + var/length = input(usr, "How long will the lava last? (in seconds)", "Length", 180) as num + length = min(abs(length), 1200) + + var/damage = input(usr, "How deadly will the lava be?", "Damage", 2) as num + damage = min(abs(damage), 100) + + var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "YES!", "Nah") + if(sure == "Nah") + return + floorIsLava = 1 + + message_admins("[key_name_admin(usr)] made the floor LAVA! It'll last [length] seconds and it will deal [damage] damage to everyone.", 1) + + for(var/turf/simulated/floor/F in turfs) + if(F.z == 1) + F.name = "lava" + F.desc = "The floor is LAVA!" + F.overlays += "lava" + F.lava = 1 + + spawn(0) + for(var/i = i, i < length, i++) // 180 = 3 minutes + if(damage) + for(var/mob/living/carbon/L in living_mob_list) + if(istype(L.loc, /turf/simulated/floor)) // Are they on LAVA?! + var/turf/simulated/floor/F = L.loc + if(F.lava) + var/safe = 0 + for(var/obj/structure/O in F.contents) + if(O.level > F.level && !istype(O, /obj/structure/window)) // Something to stand on and it isn't under the floor! + safe = 1 + break + if(!safe) + L.adjustFireLoss(damage) + + + sleep(10) + + for(var/turf/simulated/floor/F in turfs) // Reset everything. + if(F.z == 1) + F.name = initial(F.name) + F.desc = initial(F.desc) + F.overlays.len = 0 + F.lava = 0 + F.update_icon() + floorIsLava = 0 + return + if("thebees") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BEE") + var/answer = alert("What's this? A Space Station woefully underpopulated by bees?",,"Let's fix it!","On second thought, let's not.") + if(answer=="Let's fix it!") + message_admins("[key_name_admin(usr)] unleashed the bees onto the crew.", 1) + to_chat(world, "NOT THE BEES!") + to_chat(world, sound('sound/effects/bees.ogg')) + for(var/mob/living/M in player_list) + var/mob/living/simple_animal/bee/BEE = new(get_turf(M)) + BEE.strength = 16 + BEE.toxic = 5 + BEE.mut = 2 + BEE.feral = 25 + BEE.target = M + BEE.icon_state = "bees_swarm-feral" + + if("virus") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","V") + var/answer = alert("Do you want this to be a greater disease or a lesser one?",,"Greater","Lesser") + if(answer=="Lesser") + virus2_lesser_infection() + message_admins("[key_name_admin(usr)] has triggered a lesser virus outbreak.", 1) + else + virus2_greater_infection() + message_admins("[key_name_admin(usr)] has triggered a greater virus outbreak.", 1) + if("retardify") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","RET") + for(var/mob/living/carbon/human/H in player_list) + to_chat(H, "You suddenly feel stupid.") + H.setBrainLoss(60) + message_admins("[key_name_admin(usr)] made everybody retarded") + if("fakeguns") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FG") + for(var/obj/item/W in world) + if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/weapon/disk) || istype(W, /obj/item/weapon/tank)) + continue + W.icon = 'icons/obj/gun.dmi' + W.icon_state = "revolver" + W.item_state = "gun" + message_admins("[key_name_admin(usr)] made every item look like a gun") + if("experimentalguns") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","GUN") + for(var/mob/living/carbon/C in player_list) + var/list/turflist = list() + for(var/turf/T in orange(src,1)) + turflist += T + if(!turflist.len) + turflist += get_turf(C) + var/turf/U = pick(turflist) + var/obj/structure/closet/crate/secure/weapon/experimental/E = new(U) + to_chat(C, "A crate appears next to you. You think you can read \"[E.chosen_set]\" scribbled on it") + U.turf_animation('icons/effects/96x96.dmi',"beamin",-32,0,MOB_LAYER+1,'sound/weapons/emitter2.ogg') + message_admins("[key_name_admin(usr)] distributed experimental guns to the entire crew") + if("schoolgirl") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SG") + for(var/obj/item/clothing/under/W in world) + W.icon_state = "schoolgirl" + W.item_state = "w_suit" + W._color = "schoolgirl" + message_admins("[key_name_admin(usr)] activated Japanese Animes mode") + to_chat(world, sound('sound/AI/animes.ogg')) + if("eagles")//SCRAW + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","EgL") + for(var/obj/machinery/door/airlock/W in all_doors) + if(W.z == 1 && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) + W.req_access = list() + message_admins("[key_name_admin(usr)] activated Egalitarian Station mode") + command_alert("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.") + to_chat(world, sound('sound/AI/commandreport.ogg')) + if("dorf") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","DF") + for(var/mob/living/carbon/human/B in mob_list) + B.f_style = "Dward Beard" + B.update_hair() + message_admins("[key_name_admin(usr)] activated dorf mode") + if("ionstorm") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","I") + generate_ion_law() + message_admins("[key_name_admin(usr)] triggered an ion storm") + var/show_log = alert(usr, "Show ion message?", "Message", "Yes", "No") + if(show_log == "Yes") + command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") + to_chat(world, sound('sound/AI/ionstorm.ogg')) + if("spacevines") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","K") + new /datum/event/spacevine + message_admins("[key_name_admin(usr)] has spawned spacevines", 1) + if("onlyone") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","OO") + usr.client.only_one() +// message_admins("[key_name_admin(usr)] has triggered a battle to the death (only one)") + if("togglenarsie") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","NA") + var/choice = input("How do you wish for narsie to interact with her surroundings?") in list("CultStation13", "Nar-Singulo") + if(choice == "CultStation13") + message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"CultStation13\".") + narsie_behaviour = "CultStation13" + if(choice == "Nar-Singulo") + message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"Nar-Singulo\".") + narsie_behaviour = "Nar-Singulo" + if("hellonearth") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","NS") + var/choice = input("You sure you want to end the round and summon narsie at your location? Misuse of this could result in removal of flags or halarity.") in list("PRAISE SATAN", "Cancel") + if(choice == "PRAISE SATAN") + new /obj/machinery/singularity/narsie/large(get_turf(usr)) + message_admins("[key_name_admin(usr)] has summoned narsie and brought about a new realm of suffering.") + if("supermattercascade") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SC") + var/choice = input("You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or halarity.") in list("NO TIME TO EXPLAIN", "Cancel") + if(choice == "NO TIME TO EXPLAIN") + explosion(get_turf(usr), 8, 16, 24, 32, 1) + new /turf/unsimulated/wall/supermatter(get_turf(usr)) + SetUniversalState(/datum/universal_state/supermatter_cascade) + message_admins("[key_name_admin(usr)] has managed to destroy the universe with a supermatter cascade. Good job, [key_name_admin(usr)]") + if("spawnadminbus") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","AB") + var/obj/structure/bed/chair/vehicle/adminbus/A = new /obj/structure/bed/chair/vehicle/adminbus(get_turf(usr)) + A.dir = EAST + A.update_lightsource() + A.busjuke.dir = EAST + message_admins("[key_name_admin(usr)] has spawned an Adminbus. Who gave him the keys?") + log_admin("[key_name_admin(usr)] has spawned an Adminbus.") + if("spawnselfdummy") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","TD") + message_admins("[key_name_admin(usr)] spawned himself as a Test Dummy.") + log_admin("[key_name_admin(usr)] spawned himself as a Test Dummy.") + var/turf/T = get_turf(usr) + var/mob/living/carbon/human/dummy/D = new /mob/living/carbon/human/dummy(T) + usr.client.cmd_assume_direct_control(D) + D.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(D), slot_w_uniform) + D.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(D), slot_shoes) + D.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(D), slot_ears) + D.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(D), slot_back) + D.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(D.back), slot_in_backpack) + T.turf_animation('icons/effects/96x96.dmi',"beamin",-32,0,MOB_LAYER+1,'sound/misc/adminspawn.ogg') + D.name = "Admin" + D.real_name = "Admin" + var/newname = "" + newname = copytext(sanitize(input(D, "Before you step out as an embodied god, what name do you wish for?", "Choose your name.", "Admin") as null|text),1,MAX_NAME_LEN) + if (!newname) + newname = "Admin" + D.name = newname + D.real_name = newname + var/obj/item/weapon/card/id/admin/admin_id = new(D) + admin_id.registered_name = newname + D.equip_to_slot_or_del(admin_id, slot_wear_id) + //False flags and bait below. May cause mild hilarity or extreme pain. Now in one button + if("fakealerts") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FAKEA") + var/choice = input("Choose the type of fake alert you wish to trigger","False Flag and Bait Panel") in list("Biohazard", "Lifesigns", "Malfunction", "Ion", "Meteor Wave", "Carp Migration", "Return") + //Big fat lists of effects, not very modular but at least there's less buttons + if(choice == "Return") //Actually fuck this + return //Duh + if(choice == "Biohazard") //GUISE WE HAVE A BLOB + var/levelchoice = input("Set the level of the biohazard alert, or leave at 0 to have a random level (1 to 7 supported only)", "Space FEMA Readiness Program", 0) as num + if(!levelchoice || levelchoice > 7 || levelchoice < 0) + to_chat(usr, "Invalid input range (0 to 7 only)") + return + biohazard_alert(level = levelchoice) + message_admins("[key_name_admin(usr)] triggered a FAKE Biohzard Alert.") + log_admin("[key_name_admin(usr)] triggered a FAKE Biohzard Alert.") + return + if(choice == "Lifesigns") //MUH ALIUMS + command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") + to_chat(world, sound('sound/AI/aliens.ogg')) + message_admins("[key_name_admin(usr)] triggered a FAKE Lifesign Alert.") + log_admin("[key_name_admin(usr)] triggered a FAKE Lifesign Alert.") + return + if(choice == "Malfunction") //BLOW EVERYTHING + var/salertchoice = input("Do you wish to include the Hostile Runtimes warning to have an authentic Malfunction Takeover Alert ?", "Nanotrasen Alert Level Monitor") in list("Yes", "No") + if(salertchoice == "Yes") + command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") + to_chat(world, "Attention! Delta security level reached!")//Don't ACTUALLY set station alert to Delta to avoid fucking shit up for real + + to_chat(world, "[config.alert_desc_delta]") + to_chat(world, sound('sound/AI/aimalf.ogg'))//AI got valid + + message_admins("[key_name_admin(usr)] triggered a FAKE Malfunction Takeover Alert (Hostile Runtimes alert [salertchoice == "Yes" ? "included":"excluded"])") + log_admin("[key_name_admin(usr)] triggered a FAKE Malfunction Takeover Alert (Hostile Runtimes alert [salertchoice == "Yes" ? "included":"excluded"])") + return + if(choice == "Ion") + command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") + to_chat(world, sound('sound/AI/ionstorm.ogg')) + message_admins("[key_name_admin(usr)] triggered a FAKE Ion Alert.") + log_admin("[key_name_admin(usr)] triggered a FAKE Ion Alert.") + return + if(choice == "Meteor Wave") + command_alert("A meteor storm has been detected on collision course with the station. Seek shelter within the core of the station immediately.", "Meteor Alert") + to_chat(world, sound('sound/AI/meteors.ogg')) + message_admins("[key_name_admin(usr)] triggered a FAKE Meteor Alert.") + log_admin("[key_name_admin(usr)] triggered a FAKE Meteor Alert.") + return + if(choice == "Carp Migration") + command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") + message_admins("[key_name_admin(usr)] triggered a FAKE Carp Migration Alert.") + log_admin("[key_name_admin(usr)] triggered a FAKE Carp Migration Alert.") + return + if("fakebooms") //Micheal Bay is in the house ! + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FAKEE") + var/choice = input("How much high-budget explosions do you want ?", "Micheal Bay SFX Systems", 1) as num + if(choice < 1) //No negative or null explosion amounts here math genius + to_chat(usr, "Invalid input range (null or negative)") + return + message_admins("[key_name_admin(usr)] improvised himself as Micheal Bay and triggered [round(choice)] fake explosions.") + log_admin("[key_name_admin(usr)] improvised himself as Micheal Bay and triggered [round(choice)] fake explosions.") + for(var/i = 1 to choice) + to_chat(world, sound('sound/effects/explosionfar.ogg')) + sleep(rand(2, 10)) //Sleep 0.2 to 1 second + if("massbomber") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BBM") + var/choice = alert("Dress every player like Bomberman and give them BBDs?","Bomberman Mode Activation","Confirm","Cancel") + if(choice=="Confirm") + bomberman_mode = 1 + to_chat(world, sound('sound/bomberman/start.ogg')) + for(var/mob/living/carbon/human/M in player_list) + if(M.wear_suit) + var/obj/item/O = M.wear_suit + M.u_equip(O,1) + O.loc = M.loc + //O.dropped(M) + if(M.head) + var/obj/item/O = M.head + M.u_equip(O,1) + O.loc = M.loc + //O.dropped(M) + M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/bomberman(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/bomberman(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/bomberman/(M), slot_s_store) + M.update_icons() + to_chat(M, "Wait...what?") + spawn(50) + to_chat(M, "Tip: Use the BBD in your suit's pocket to place bombs.") + to_chat(M, "Try to keep your BBD and escape this hell hole alive!") + + message_admins("[key_name_admin(usr)] turned everyone into Bomberman!") + log_admin("[key_name_admin(usr)] turned everyone into Bomberman!") + if("bomberhurt") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BBH") + var/choice = alert("Activate Cuban Pete mode? Note that newly spawned BBD will still have player damage deactivated.","Activating Bomberman Bombs Player Damage","Confirm","Cancel") + if(choice=="Confirm") + bomberman_hurt = 1 + for(var/obj/item/weapon/bomberman/B in bombermangear) + if(!B.arena) + B.hurt_players = 1 + message_admins("[key_name_admin(usr)] enabled the player damage of the Bomberman Bomb Dispensers currently in the world. Cuban Pete approves.") + log_admin("[key_name_admin(usr)] enabled the player damage of the Bomberman Bomb Dispensers currently in the world. Cuban Pete approves.") + if("bomberdestroy") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BBD") + var/choice = alert("Activate Michael Bay mode? Note that newly spawned BBD will still have environnement damage deactivated.","Activating Bomberman Bombs Environnement Damage","Confirm","Cancel") + if(choice=="Confirm") + bomberman_destroy = 1 + for(var/obj/item/weapon/bomberman/B in bombermangear) + if(!B.arena) + B.destroy_environnement = 1 + message_admins("[key_name_admin(usr)] enabled the environnement damage of the Bomberman Bomb Dispensers currently in the world. Michael Bay approves.") + log_admin("[key_name_admin(usr)] enabled the environnement damage of the Bomberman Bomb Dispensers currently in the world. Michael Bay approves.") + if("bombernohurt") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BBNH") + var/choice = alert("Disable Cuban Pete mode.","Disable Bomberman Bombs Player Damage","Confirm","Cancel") + if(choice=="Confirm") + bomberman_hurt = 0 + for(var/obj/item/weapon/bomberman/B in bombermangear) + if(!B.arena) + B.hurt_players = 0 + message_admins("[key_name_admin(usr)] disabled the player damage of the Bomberman Bomb Dispensers currently in the world.") + log_admin("[key_name_admin(usr)] disabled the player damage of the Bomberman Bomb Dispensers currently in the world.") + if("bombernodestroy") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BBND") + var/choice = alert("Disable Michael Bay mode?","Disable Bomberman Bombs Environnement Damage","Confirm","Cancel") + if(choice=="Confirm") + bomberman_destroy = 0 + for(var/obj/item/weapon/bomberman/B in bombermangear) + if(!B.arena) + B.destroy_environnement = 0 + message_admins("[key_name_admin(usr)] disabled the environnement damage of the Bomberman Bomb Dispensers currently in the world.") + log_admin("[key_name_admin(usr)] disabled the environnement damage of the Bomberman Bomb Dispensers currently in the world.") + if("togglebombmethod") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BM") + var/choice = input("Do you wish for explosions to take walls and obstacles into account?") in list("Yes, let's have realistic explosions", "No, let's have perfectly circular explosions") + if(choice == "Yes, let's have realistic explosions") + message_admins("[key_name_admin(usr)] has set explosions to take walls and obstacles into account.") + explosion_newmethod = 1 + if(choice == "No, let's have perfectly circular explosions") + message_admins("[key_name_admin(usr)] has set explosions to completely pass through walls and obstacles.") + explosion_newmethod = 0 + if("placeturret") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","TUR") + var/list/possible_guns = list() + for(var/path in typesof(/obj/item/weapon/gun/energy)) + possible_guns += path + var/choice = input("What energy gun do you want inside the turret?") in possible_guns + if(!choice) + return + var/obj/item/weapon/gun/energy/gun = new choice() + var/obj/machinery/porta_turret/Turret = new(get_turf(usr)) + Turret.installation = choice + Turret.gun_charge = gun.power_supply.charge + Turret.update_gun() + qdel(gun) + var/emag = input("Emag the turret?") in list("Yes", "No") + if(emag=="Yes") + Turret.emag(usr) + if("hardcore_mode") + var/choice = input("Are you sure you want to [ticker.hardcore_mode ? "disable" : "enable"] hardcore mode? Starvation will [ticker.hardcore_mode ? "no longer":""]slowly kill player-controlled humans.", "Admin Abuse") in list("Yes", "No!") + + if(choice == "Yes") + if(!hardcore_mode_on) + log_admin("[key_name(usr)] has ENABLED hardcore mode!") + hardcore_mode = 1 + to_chat(world, "
    Hardcore mode has been enabled
    ") + to_chat(world, "Not eating for a prolonged period of time will slowly kill player-controlled characters (braindead and catatonic characters are not affected).") + to_chat(world, "If your hunger indicator starts flashing red and black, your character is starving and may die soon!") + else + log_admin("[key_name(usr)] has DISABLED hardcore mode!") + hardcore_mode = 0 + to_chat(world, "
    Hardcore mode has been disabled
    ") + to_chat(world, "Starvation will no longer kill player-controlled characters.") + if(usr) + log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]") + if(ok) + to_chat(world, text("A secret has been activated by [usr.key]!")) + + else if(href_list["secretsadmin"]) + if(!check_rights(R_ADMIN)) + return + + var/ok = 0 + switch(href_list["secretsadmin"]) + if("clear_bombs") + var/num=0 + for(var/obj/item/device/transfer_valve/TV in world) + if(TV.tank_one||TV.tank_two) + del(TV) + TV++ + message_admins("[key_name_admin(usr)] has removed [num] bombs", 1) + if("detonate_bombs") + var/num=0 + for(var/obj/item/device/transfer_valve/TV in world) + if(TV.tank_one||TV.tank_two) + TV.toggle_valve() + message_admins("[key_name_admin(usr)] has toggled valves on [num] bombs", 1) + + if("list_bombers") + var/dat = "Bombing List
    " + for(var/l in bombers) + dat += text("[l]
    ") + usr << browse(dat, "window=bombers") + if("list_signalers") + var/dat = "Showing last [length(lastsignalers)] signalers.
    " + for(var/sig in lastsignalers) + dat += "[sig]
    " + usr << browse(dat, "window=lastsignalers;size=800x500") + if("list_lawchanges") + var/dat = "Showing last [length(lawchanges)] law changes.
    " + for(var/sig in lawchanges) + dat += "[sig]
    " + usr << browse(dat, "window=lawchanges;size=800x500") + if("list_job_debug") + var/dat = "Job Debug info.
    " + if(job_master) + for(var/line in job_master.job_debug) + dat += "[line]
    " + dat+= "*******

    " + for(var/datum/job/job in job_master.occupations) + if(!job) continue + dat += "job: [job.title], current_positions: [job.current_positions], total_positions: [job.total_positions]
    " + usr << browse(dat, "window=jobdebug;size=600x500") + if("showailaws") + output_ai_laws() + if("showgm") + if(!ticker) + alert("The game hasn't started yet!") + else if (ticker.mode) + alert("The game mode is [ticker.mode.name]") + else alert("For some reason there's a ticker, but not a game mode") + if("manifest") + var/dat = "Showing Crew Manifest.
    " + dat += "" + for(var/mob/living/carbon/human/H in mob_list) + if(H.ckey) + dat += text("", H.name, H.get_assignment()) + dat += "
    NamePosition
    [][]
    " + usr << browse(dat, "window=manifest;size=440x410") + if("check_antagonist") + check_antagonists() + if("DNA") + var/dat = "Showing DNA from blood.
    " + dat += "" + for(var/mob/living/carbon/human/H in mob_list) + if(H.dna && H.ckey) + dat += "" + dat += "
    NameDNABlood Type
    [H][H.dna.unique_enzymes][H.b_type]
    " + usr << browse(dat, "window=DNA;size=440x410") + if("fingerprints") + var/dat = "Showing Fingerprints.
    " + dat += "" + for(var/mob/living/carbon/human/H in mob_list) + if(H.ckey) + if(H.dna && H.dna.uni_identity) + dat += "" + else if(H.dna && !H.dna.uni_identity) + dat += "" + else if(!H.dna) + dat += "" + dat += "
    NameFingerprints
    [H][md5(H.dna.uni_identity)]
    [H]H.dna.uni_identity = null
    [H]H.dna = null
    " + usr << browse(dat, "window=fingerprints;size=440x410") + else + if (usr) + log_admin("[key_name(usr)] used secret [href_list["secretsadmin"]]") + if (ok) + to_chat(world, text("A secret has been activated by []!", usr.key)) + + else if(href_list["secretscoder"]) + if(!check_rights(R_DEBUG)) return + + switch(href_list["secretscoder"]) + if("spawn_objects") + var/dat = "Admin Log
    " + for(var/l in admin_log) + dat += "
  • [l]
  • " + if(!admin_log.len) + dat += "No-one has done anything this round!" + usr << browse(dat, "window=admin_log") + if("maint_access_brig") + for(var/obj/machinery/door/airlock/maintenance/M in all_doors) + if (access_maint_tunnels in M.req_access) + M.req_access = list(access_brig) + message_admins("[key_name_admin(usr)] made all maint doors brig access-only.") + if("maint_access_engiebrig") + for(var/obj/machinery/door/airlock/maintenance/M in all_doors) + if (access_maint_tunnels in M.req_access) + M.req_access = list() + M.req_one_access = list(access_brig,access_engine) + message_admins("[key_name_admin(usr)] made all maint doors engineering and brig access-only.") + if("infinite_sec") + var/datum/job/J = job_master.GetJob("Security Officer") + if(!J) return + J.total_positions = -1 + J.spawn_positions = -1 + message_admins("[key_name_admin(usr)] has removed the cap on security officers.") + if("virus_custom") + if(virus2_make_custom(usr.client)) + feedback_add_details("admin_secrets_fun_used", "V_C") + message_admins("[key_name_admin(usr)] has trigger a custom virus outbreak.", 1) + + else if(href_list["ac_view_wanted"]) //Admin newscaster Topic() stuff be here + src.admincaster_screen = 18 //The ac_ prefix before the hrefs stands for AdminCaster. + src.access_news_network() + + else if(href_list["ac_set_channel_name"]) + src.admincaster_feed_channel.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) + while (findtext(src.admincaster_feed_channel.channel_name," ") == 1) + src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1) + src.access_news_network() + + else if(href_list["ac_set_channel_lock"]) + src.admincaster_feed_channel.locked = !src.admincaster_feed_channel.locked + src.access_news_network() + + else if(href_list["ac_submit_new_channel"]) + var/check = 0 + for(var/datum/feed_channel/FC in news_network.network_channels) + if(FC.channel_name == src.admincaster_feed_channel.channel_name) + check = 1 + break + if(src.admincaster_feed_channel.channel_name == "" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]" || check ) + src.admincaster_screen=7 + else + var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel") + if(choice=="Confirm") + var/datum/feed_channel/newChannel = new /datum/feed_channel + newChannel.channel_name = src.admincaster_feed_channel.channel_name + newChannel.author = src.admincaster_signature + newChannel.locked = src.admincaster_feed_channel.locked + newChannel.is_admin_channel = 1 + feedback_inc("newscaster_channels",1) + news_network.network_channels += newChannel //Adding channel to the global network + log_admin("[key_name_admin(usr)] created command feed channel: [src.admincaster_feed_channel.channel_name]!") + src.admincaster_screen=5 + src.access_news_network() + + else if(href_list["ac_set_channel_receiving"]) + var/list/available_channels = list() + for(var/datum/feed_channel/F in news_network.network_channels) + available_channels += F.channel_name + src.admincaster_feed_channel.channel_name = adminscrub(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) + src.access_news_network() + + else if(href_list["ac_set_new_message"]) + src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story", "Network Channel Handler", "")) + while (findtext(src.admincaster_feed_message.body," ") == 1) + src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1) + src.access_news_network() + + else if(href_list["ac_submit_new_message"]) + if(src.admincaster_feed_message.body =="" || src.admincaster_feed_message.body =="\[REDACTED\]" || src.admincaster_feed_channel.channel_name == "" ) + src.admincaster_screen = 6 + else + var/datum/feed_message/newMsg = new /datum/feed_message + newMsg.author = src.admincaster_signature + newMsg.body = src.admincaster_feed_message.body + newMsg.is_admin_message = 1 + feedback_inc("newscaster_stories",1) + for(var/datum/feed_channel/FC in news_network.network_channels) + if(FC.channel_name == src.admincaster_feed_channel.channel_name) + FC.messages += newMsg //Adding message to the network's appropriate feed_channel + break + src.admincaster_screen=4 + + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + NEWSCASTER.newsAlert(src.admincaster_feed_channel.channel_name) + + log_admin("[key_name_admin(usr)] submitted a feed story to channel: [src.admincaster_feed_channel.channel_name]!") + src.access_news_network() + + else if(href_list["ac_create_channel"]) + src.admincaster_screen=2 + src.access_news_network() + + else if(href_list["ac_create_feed_story"]) + src.admincaster_screen=3 + src.access_news_network() + + else if(href_list["ac_menu_censor_story"]) + src.admincaster_screen=10 + src.access_news_network() + + else if(href_list["ac_menu_censor_channel"]) + src.admincaster_screen=11 + src.access_news_network() + + else if(href_list["ac_menu_wanted"]) + var/already_wanted = 0 + if(news_network.wanted_issue) + already_wanted = 1 + + if(already_wanted) + src.admincaster_feed_message.author = news_network.wanted_issue.author + src.admincaster_feed_message.body = news_network.wanted_issue.body + src.admincaster_screen = 14 + src.access_news_network() + + else if(href_list["ac_set_wanted_name"]) + src.admincaster_feed_message.author = adminscrub(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) + while (findtext(src.admincaster_feed_message.author," ") == 1) + src.admincaster_feed_message.author = copytext(admincaster_feed_message.author,2,length(admincaster_feed_message.author)+1) + src.access_news_network() + + else if(href_list["ac_set_wanted_desc"]) + src.admincaster_feed_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) + while (findtext(src.admincaster_feed_message.body," ") == 1) + src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1) + src.access_news_network() + + else if(href_list["ac_submit_wanted"]) + var/input_param = text2num(href_list["ac_submit_wanted"]) + if(src.admincaster_feed_message.author == "" || src.admincaster_feed_message.body == "") + src.admincaster_screen = 16 + else + var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel") + if(choice=="Confirm") + if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below + var/datum/feed_message/WANTED = new /datum/feed_message + WANTED.author = src.admincaster_feed_message.author //Wanted name + WANTED.body = src.admincaster_feed_message.body //Wanted desc + WANTED.backup_author = src.admincaster_signature //Submitted by + WANTED.is_admin_message = 1 + news_network.wanted_issue = WANTED + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + NEWSCASTER.newsAlert() + NEWSCASTER.update_icon() + src.admincaster_screen = 15 + else + news_network.wanted_issue.author = src.admincaster_feed_message.author + news_network.wanted_issue.body = src.admincaster_feed_message.body + news_network.wanted_issue.backup_author = src.admincaster_feed_message.backup_author + src.admincaster_screen = 19 + log_admin("[key_name_admin(usr)] issued a Station-wide Wanted Notification for [src.admincaster_feed_message.author]!") + src.access_news_network() + + else if(href_list["ac_cancel_wanted"]) + var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel") + if(choice=="Confirm") + news_network.wanted_issue = null + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + NEWSCASTER.update_icon() + src.admincaster_screen=17 + src.access_news_network() + + else if(href_list["ac_censor_channel_author"]) + var/datum/feed_channel/FC = locate(href_list["ac_censor_channel_author"]) + if(FC.author != "\[REDACTED\]") + FC.backup_author = FC.author + FC.author = "\[REDACTED\]" + else + FC.author = FC.backup_author + src.access_news_network() + + else if(href_list["ac_censor_channel_story_author"]) + var/datum/feed_message/MSG = locate(href_list["ac_censor_channel_story_author"]) + if(MSG.author != "\[REDACTED\]") + MSG.backup_author = MSG.author + MSG.author = "\[REDACTED\]" + else + MSG.author = MSG.backup_author + src.access_news_network() + + else if(href_list["ac_censor_channel_story_body"]) + var/datum/feed_message/MSG = locate(href_list["ac_censor_channel_story_body"]) + if(MSG.body != "\[REDACTED\]") + MSG.backup_body = MSG.body + MSG.body = "\[REDACTED\]" + else + MSG.body = MSG.backup_body + src.access_news_network() + + else if(href_list["ac_pick_d_notice"]) + var/datum/feed_channel/FC = locate(href_list["ac_pick_d_notice"]) + src.admincaster_feed_channel = FC + src.admincaster_screen=13 + src.access_news_network() + + else if(href_list["ac_toggle_d_notice"]) + var/datum/feed_channel/FC = locate(href_list["ac_toggle_d_notice"]) + FC.censored = !FC.censored + src.access_news_network() + + else if(href_list["ac_view"]) + src.admincaster_screen=1 + src.access_news_network() + + else if(href_list["ac_setScreen"]) //Brings us to the main menu and resets all fields~ + src.admincaster_screen = text2num(href_list["ac_setScreen"]) + if (src.admincaster_screen == 0) + if(src.admincaster_feed_channel) + src.admincaster_feed_channel = new /datum/feed_channel + if(src.admincaster_feed_message) + src.admincaster_feed_message = new /datum/feed_message + src.access_news_network() + + else if(href_list["ac_show_channel"]) + var/datum/feed_channel/FC = locate(href_list["ac_show_channel"]) + src.admincaster_feed_channel = FC + src.admincaster_screen = 9 + src.access_news_network() + + else if(href_list["ac_pick_censor_channel"]) + var/datum/feed_channel/FC = locate(href_list["ac_pick_censor_channel"]) + src.admincaster_feed_channel = FC + src.admincaster_screen = 12 + src.access_news_network() + + else if(href_list["ac_refresh"]) + src.access_news_network() + + else if(href_list["ac_set_signature"]) + src.admincaster_signature = adminscrub(input(usr, "Provide your desired signature", "Network Identity Handler", "")) + src.access_news_network() + + else if(href_list["populate_inactive_customitems"]) + if(check_rights(R_ADMIN|R_SERVER)) + populate_inactive_customitems_list(src.owner) + + else if(href_list["vsc"]) + if(check_rights(R_ADMIN|R_SERVER)) + if(href_list["vsc"] == "airflow") + zas_settings.ChangeSettingsDialog(usr,zas_settings.settings) + if(href_list["vsc"] == "default") + zas_settings.SetDefault(usr) + + else if(href_list["toglang"]) + if(check_rights(R_SPAWN)) + var/mob/M = locate(href_list["toglang"]) + if(!istype(M)) + to_chat(usr, "[M] is illegal type, must be /mob!") + return + var/lang2toggle = href_list["lang"] + var/datum/language/L = all_languages[lang2toggle] + + if(L in M.languages) + if(!M.remove_language(lang2toggle)) + to_chat(usr, "Failed to remove language '[lang2toggle]' from \the [M]!") + else + if(!M.add_language(lang2toggle)) + to_chat(usr, "Failed to add language '[lang2toggle]' from \the [M]!") + + show_player_panel(M) + + // player info stuff + + if(href_list["add_player_info"]) + var/key = href_list["add_player_info"] + var/add = input("Add Player Info") as null|text + if(!add) return + + notes_add(key,add,usr) + show_player_info(key) + + if(href_list["remove_player_info"]) + var/key = href_list["remove_player_info"] + var/index = text2num(href_list["remove_index"]) + + notes_del(key, index) + show_player_info(key) + + if(href_list["notes"]) + var/ckey = href_list["ckey"] + if(!ckey) + var/mob/M = locate(href_list["mob"]) + if(ismob(M)) + ckey = M.ckey + + switch(href_list["notes"]) + if("show") + show_player_info(ckey) + if("list") + PlayerNotesPage(text2num(href_list["index"])) + return + +//------------------------------------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------Shuttle stuff----------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------------------------- + + if(href_list["shuttle_select"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SS") + + var/datum/shuttle/S = select_shuttle_from_all(usr,"Please select a shuttle","Admin abuse") + + if(istype(S)) + selected_shuttle = S + to_chat(usr, "[S] ([S.type]) selected!") + + shuttle_magic() //Update the window! + if(href_list["shuttle_add_docking_port"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","CD") + + var/area/A = get_area(get_turf(usr)) + var/datum/shuttle/shuttle_to_add_to = A.get_shuttle() + + if(istype(shuttle_to_add_to)) + if(alert(usr, "Would you like the new shuttle docking port to be assigned to [shuttle_to_add_to.name]? [shuttle_to_add_to.linked_port ? "NOTE: It already has a shuttle docking port." : ""]", "Admin abuse", "Yes", "No") != "Yes") + shuttle_to_add_to = null + + var/obj/structure/docking_port/shuttle/D = new( get_turf(usr) ) + D.dir = usr.dir + + if(istype(shuttle_to_add_to)) + D.link_to_shuttle(shuttle_to_add_to) + to_chat(usr, "Assigned the [D] to [shuttle_to_add_to.name]") + + message_admins("[key_name_admin(usr)] has created a new shuttle docking port in [get_area(D)] [formatJumpTo(get_turf(D))][shuttle_to_add_to ? " and assigned it to [shuttle_to_add_to.name]" : ""]", 1) + log_admin("[key_name_admin(usr)] has created a new destination docking port ([D.areaname]) at [D.x];[D.y];[D.z][shuttle_to_add_to ? " and assigned it to [shuttle_to_add_to.name]" : ""]") + + if(href_list["shuttle_create_destination"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","DC") + + var/area/A = get_area(get_turf(usr)) + + var/name = input(usr,"What would you like to name this docking port?","Admin abuse","[A ? "[A.name]" : "Space [rand(100,999)]"]") as text|null + if(!name) return + + var/obj/structure/docking_port/destination/D = new( get_turf(usr) ) + D.dir = usr.dir + D.areaname = name + + A = get_area(D) + if(A) + var/datum/shuttle/S = A.get_shuttle() + if(S) + if(alert(usr,"Would you like the new docking port to be a part of [S.name] ([S.type])? Any shuttles docked to it will be moved together with [S.name].","Admin abuse","Yes","No") == "Yes") + if(get_area(D) == A) //If the shuttle moved, abort -- as that would lead to weird shittu + S.docking_ports_aboard |= D + to_chat(usr, "[D] is now considered a part of [S.name] ([S.type]).") + + if(istype(selected_shuttle)) + if(alert(usr,"Would you like to add [D.areaname] to the list of [selected_shuttle.name]'s destinations?","Admin abuse","Yes","No") == "Yes") + selected_shuttle.docking_ports |= D + to_chat(usr, "Added [D] to the list of [selected_shuttle.name]'s destinations") + + message_admins("[key_name_admin(usr)] has created a new destination docking port ([D.areaname]) in [get_area(D)] [formatJumpTo(get_turf(D))]", 1) + log_admin("[key_name_admin(usr)] has created a new destination docking port ([D.areaname]) at [D.x];[D.y];[D.z]") + + if(href_list["shuttle_modify_destination"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","MD") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + var/list/docking_ports_to_pick_from = all_docking_ports.Copy() + var/list/options = list() + for(var/obj/structure/docking_port/destination/D in (docking_ports_to_pick_from - S.docking_ports)) + var/name = D.areaname + options += name + options[name] = D + + var/obj/structure/docking_port/destination/choice = options[(input(usr,"Select a docking port to add to [S.name]","Admin abuse") in options)] + if(!istype(choice)) return + + S.docking_ports |= choice + to_chat(usr, "Added [choice.areaname] to [S.name]!") + + if(href_list["shuttle_set_transit"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","AT") + + var/list/L = list() + for(var/obj/structure/docking_port/destination/D in get_turf(usr) ) + var/name = "[D.name] ([D.areaname])" + L += name + L[name]=D + + if(!L.len) + to_chat(usr, "Please stand on the docking port you wish to make a transit area.") + + var/obj/structure/docking_port/port_to_link = L[ (input(usr,"Select a new transit area for the shuttle","Admin abuse") as null|anything in (L + list("Cancel"))) ] + if(!istype(port_to_link)) return + + var/datum/shuttle/shuttle_to_link = selected_shuttle + if(!istype(shuttle_to_link)) return + + var/choice = input(usr,"Please confirm that you want to make [port_to_link] ([port_to_link.areaname]) a transit area for [shuttle_to_link.name] ([shuttle_to_link.type])?","Admin abuse") in list("Yes","No") + + if(choice == "Yes") + shuttle_to_link.set_transit_dock(port_to_link) + else + return + + message_admins("[key_name_admin(usr)] has set a destination docking port ([port_to_link.areaname]) at [port_to_link.x];[port_to_link.y];[port_to_link.z] to be [shuttle_to_link.name] ([shuttle_to_link.type])'s transit area [formatJumpTo(get_turf(port_to_link))]", 1) + log_admin("[key_name_admin(usr)] has set a destination docking port ([port_to_link.areaname]) at [port_to_link.x];[port_to_link.y];[port_to_link.z] to be [shuttle_to_link.name] ([shuttle_to_link.type])'s transit area") + + if(href_list["shuttle_create_shuttleport"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SC") + + var/obj/structure/docking_port/shuttle/D = new(get_turf(usr.loc)) + D.dir = usr.dir + + var/area/A = get_area(D) + var/datum/shuttle/S = A.get_shuttle() + if(S && !S.linked_port) + if(alert(usr,"Would you like to make [S.name] ([S.type]) use this docking port?","Admin abuse","Yes","No") == "Yes") + if(!S || S.linked_port) + to_chat(usr, "Either the shuttle was deleted, or somebody already linked a shuttle docking port to it. Sorry!") + return + if(!D) return + + S.linked_port = D + to_chat(usr, "The shuttle docking port will now be used by [S.name]!") + + message_admins("[key_name_admin(usr)] has created a new shuttle docking port in [get_area(D)] [formatJumpTo(get_turf(D))]", 1) + log_admin("[key_name_admin(usr)] has created a new shuttle docking port at [D.x];[D.y];[D.z]
    ") + + if(href_list["shuttle_toggle_lockdown"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","LD") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + if(S.lockdown) + S.lockdown = 0 + to_chat(usr, "The lockdown from [S.name] has been lifted.") + message_admins("[key_name_admin(usr)] has lifted [capitalize(S.name)]'s lockdown.", 1) + log_admin("[key_name(usr)] has locked [capitalize(S.name)] down. [(length(S.lockdown)>=1) ? "Reason: [S.lockdown]" : ""]") + else + S.lockdown = 1 + to_chat(usr, "[S.name] has been locked down.") + var/reason = input(usr,"Would you like to provide additional information, which will be shown on [capitalize(S.name)]'s control consoles?","Shuttle lockdown") in list("Yes","No") + if(reason == "Yes") + reason = input(usr,"Please type additional information about the lockdown of [capitalize(S.name)].","Shuttle lockdown") + if(length(reason)>=1) + S.lockdown = reason + message_admins("[key_name_admin(usr)] has locked [capitalize(S.name)] down. [(length(S.lockdown)>=1) ? "Reason: [S.lockdown]" : ""]", 1) + log_admin("[key_name(usr)] has locked [capitalize(S.name)] down. [(length(S.lockdown)>=1) ? "Reason: [S.lockdown]" : ""]") + + if(href_list["shuttle_move_to"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","MV") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + var/list/possible_ports = list() + for(var/obj/structure/docking_port/destination/D in S.docking_ports) + var/name = D.areaname + possible_ports += name + possible_ports[name] = D + + var/choice = input(usr, "Select a docking port for [capitalize(S.name)] to travel to", "Shuttle movement") in (possible_ports + list("Cancel")) + var/obj/structure/docking_port/destination/target_port = possible_ports[choice] + + if(!target_port) + return + + S.travel_to(target_port,,usr) + + message_admins("[key_name_admin(usr)] has moved [capitalize(S.name)] to [target_port.areaname] ([target_port.x];[target_port.y];[target_port.z])") + log_admin("[key_name(usr)] has moved [capitalize(S.name)] to [target_port.areaname] ([target_port.x];[target_port.y];[target_port.z])") + + if(href_list["shuttle_edit"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SE") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + var/list/options = list("Cancel","cooldown","pre-flight delay","transit delay","use transit","can link to computer","innacuracy","name","destroy areas","can rotate") + if(S.is_special()) options += "DEFINED LOCATIONS" + var/choice = input(usr,"What to edit in [capitalize(S.name)]?","Shuttle editing") in options + + var/new_value + switch(choice) + if("cooldown") + new_value = input(usr,"Input new cooldown for [capitalize(S.name)] (in 1/10s of a second)","Shuttle editing",S.cooldown) as num + S.cooldown = new_value + if("pre-flight delay") + new_value = input(usr,"Input new pre-flight delay for [capitalize(S.name)] (in 1/10s of a second)","Shuttle editing",S.pre_flight_delay) as num + S.pre_flight_delay = new_value + if("transit delay") + new_value = input(usr,"Input new transit delay for [capitalize(S.name)] (in 1/10s of a second)","Shuttle editing",S.transit_delay) as num + S.transit_delay = new_value + if("use transit") + new_value = input(usr,"[NO_TRANSIT] - no transit, [TRANSIT_ACROSS_Z_LEVELS] - only across z levels, [TRANSIT_ALWAYS] - always","Shuttle editing ([capitalize(S.name)])",S.use_transit) as num + if(new_value in list(NO_TRANSIT,TRANSIT_ACROSS_Z_LEVELS,TRANSIT_ALWAYS)) + S.use_transit = new_value + else + to_chat(usr, "Not valid!") + return + if("can link to computer") + new_value = input(usr,"[LINK_FREE] - can always link, [LINK_PASSWORD_ONLY] - can only link with password ([S.password]), [LINK_FORBIDDEN] - can't link at all","Shuttle editing ([capitalize(S.name)])",S.can_link_to_computer) as num + S.pre_flight_delay = new_value + if("direction") + new_value = input(usr,"[NORTH] - north, [SOUTH] - south, [WEST] - west, [EAST] - east","Shuttle editing ([capitalize(S.name)])",S.dir) as num + if(new_value in cardinal) + S.dir = new_value + else + to_chat(usr, "Not valid!") + return + if("innacuracy") + new_value = input(usr,"Input new innacuracy value for [capitalize(S.name)] (when a shuttle moves, its final location is randomly offset by this value)","Shuttle editing",S.innacuracy) as num + S.innacuracy = new_value + if("name") + new_value = input(usr,"Input new name for [capitalize(S.name)]","Shuttle editing",S.innacuracy) as text + S.name = new_value + if("can rotate") + new_value = input(usr,"0 - rotation disabled, 1 - rotation enabled","Shuttle editing",S.can_rotate) as num + S.can_rotate = new_value + if("DEFINED LOCATIONS") + to_chat(usr, "To prevent accidental mistakes, you can only set these locations to docking ports in the shuttle's memory (use the \"Add a destination docking port to a shuttle\" command)") + + var/list/locations = list("--Cancel--") + switch(S.type) + if(/datum/shuttle/vox) + locations += list("Vox home (MOVING TO IT WILL END THE ROUND)" = "dock_home") + if(/datum/shuttle/escape) + locations += list("Escape shuttle home" = "dock_station","Escape shuttle centcom" = "dock_centcom") + if(/datum/shuttle/taxi) + locations += list("Taxi medbay silicon" = "dock_medical_silicon","Taxi engineering cargo" = "dock_engineering_cargo","Taxi security science" = "dock_security_science","Taxi abandoned station" = "dock_abandoned") + if(/datum/shuttle/supply) + locations += list("Centcom loading bay" = "dock_centcom", "Station cargo bay" = "dock_station") + + var/choice2 = input(usr,"Select a location to modify","Shuttle editing") in locations + var/variable_to_edit = locations[choice2] + + var/obj/structure/docking_port/destination/D = select_port_from_list(usr,"Select a new [choice2] location for [S.name] ([S.type])","Shuttle editing",S.docking_ports) + if(istype(D)) + S.vars[variable_to_edit] = D + to_chat(usr, "[S.name]'s [variable_to_edit] has been changed to [D.areaname]") + message_admins("[key_name_admin(usr)] has changed [capitalize(S.name)]'s [choice2] to [D.areaname]!", 1) + log_admin("[key_name_admin(usr)] has changed [capitalize(S.name)]'s [choice2] to [D.areaname]!") + else + return + + + message_admins("[key_name_admin(usr)] has set [capitalize(S.name)]'s [choice] to [new_value]!", 1) + log_admin("[key_name_admin(usr)] has set [capitalize(S.name)]'s [choice] to [new_value]!") + + shuttle_magic() //Update the window! + + if(href_list["shuttle_delete"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","DEL") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + var/killed_objs = 0 + + if( (input(usr,"Please type \"Yes\" to confirm that you want to delete [capitalize(S)]. This process can't be reverted!","Shuttle deletion","No") as text) != "Yes" ) + return + + if(S.is_special()) + to_chat(usr, "This shuttle can't be deleted. Use the lockdown function instead.") + return + + var/choice = (input(usr,"Would you like to delete all turfs and objects in the shuttle's current area? Mobs will not be affected.") in list("Yes","No","Cancel") ) + if(choice == "Cancel") + return + else if(choice == "Yes") + killed_objs = 1 + + if(S.linked_area) + if(killed_objs == 1) + for(var/turf/T in S.linked_area) + if(istype(T, /turf/simulated)) + qdel(T) + for(var/obj/O in S.linked_area) + if(istype(O, /obj/item) || istype(O, /obj/machinery) || istype(O, /obj/structure)) + qdel(O) + to_chat(usr, "All turfs and objects deleted from [S.linked_area].") + + message_admins("[key_name_admin(usr)] has deleted [capitalize(S.name)] ([S.type]). Objects and turfs [(killed_objs) ? "deleted" : "not deleted"].") + log_admin("[key_name(usr)] has deleted [capitalize(S.name)]! Objects and turfs [(killed_objs) ? "deleted" : "not deleted"].") + + qdel(S) + selected_shuttle = null + + shuttle_magic() //Update the window! + + if(href_list["shuttle_teleport_to"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","TP") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + if(!S.linked_area || !istype(S.linked_area, /area/)) + to_chat(usr, "The shuttle is in the middle of nowhere! (The 'linked_area' variable is either null or not an area, please report this)") + return + + var/turf/T = locate(/turf/) in S.linked_area + usr.forceMove(T) + to_chat(usr, "You have teleported to [capitalize(S.name)]") + + if(href_list["shuttle_teleport_to_dock"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","TP2") + + var/list/destinations = list() + for(var/obj/structure/docking_port/destination/D in all_docking_ports) + var/name = "[D.areaname][D.docked_with ? " (docked to [D.docked_with.areaname])" : ""]" + destinations += name + destinations[name]=D + + var/choice = input(usr,"Select a docking port to teleport to","Finding a docking port") in destinations + + var/obj/structure/docking_port/destination/target = destinations[choice] + if(!target) return + + usr.forceMove(get_turf(target)) + to_chat(usr, "You have teleported to [choice]") + + if(href_list["shuttle_get_console"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","GC") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + if(!S.control_consoles.len) + + var/choice = input(usr,"There is no control console linked to [capitalize(S.name)]. Would you like to create one at your current location?","Shuttle control access") in list("Yes","No") + if(choice == "Yes") + var/turf/usr_loc = get_turf(usr) + var/obj/machinery/computer/shuttle_control/C = new(usr_loc) + if(C) + C.link_to(S) + to_chat(usr, "A new shuttle control console has been created.") + message_admins("[key_name_admin(usr)] has created a new shuttle control console connected to [capitalize(S.name)] in [get_area(usr_loc)].") + log_admin("[key_name(usr)] has created a new shuttle control console connected to [capitalize(S.name)] in [get_area(usr_loc)].") + else + return + + else + + var/obj/machinery/computer/shuttle_control/C = pick(S.control_consoles) + if(C) + usr.loc = C.loc + + if(href_list["shuttle_shuttlify"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SHH") + + var/area/A = get_area(usr) + if(!A) + to_chat(usr, "You must be standing on an area!") + return + if(isspace(A)) + to_chat(usr, "You can't turn space into a shuttle.") + return + + var/datum/shuttle/conflict = A.get_shuttle() + if(conflict) + var/choice = input(usr,"This area is already used by [conflict]. Type \"Yes\" to continue and bring on the unintended features","Shuttlify","NO") as text + if(choice != "Yes") + return + + if( !(locate(/obj/structure/docking_port/shuttle) in A) ) + to_chat(usr, "Please create a shuttle docking port (/obj/structure/docking_port/shuttle) in this area!") + return + + var/name = input(usr, "Please name the new shuttle", "Shuttlify", A.name) as text|null + + if(!name) + to_chat(usr, "Shuttlifying cancelled.") + return + + var/datum/shuttle/custom/S = new(starting_area = A) + S.initialize() + S.name = name + + to_chat(usr, "Shuttle created!") + + selected_shuttle = S + shuttle_magic() //Update the window! + + message_admins("[key_name_admin(usr)] has turned [A.name] into a shuttle named [S.name]. [formatJumpTo(get_turf(usr))]") + log_admin("[key_name(usr)] has turned [A.name] into a shuttle named [S.name].") + + if(href_list["shuttle_forcemove"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","FM") + + var/list/L = list("Cancel","YOUR CURRENT LOCATION") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + for(var/obj/structure/docking_port/destination/D in S.docking_ports) + var/name = "[D.name] [D.areaname]" + L+=name + L[name]=D + + L += "---other destinations---" + + for(var/obj/structure/docking_port/destination/D in all_docking_ports - S.docking_ports) + var/name = D.areaname + L+=name + L[name]=D + + var/choice = input(usr, "Select a location to teleport [S.name] to!", "Shuttle teleporting") in L + + if(choice == "YOUR CURRENT LOCATION") + var/area/A = get_area(usr) + var/turf/T = get_turf(usr) + if(!A) return + if(!T) return + + var/obj/structure/docking_port/destination/temp = new(T) + temp.invisibility = 101 + temp.areaname = A.name + temp.dir = usr.dir + + S.move_to_dock(temp) + + message_admins("[key_name_admin(usr)] has teleported [capitalize(S.name)] to himself ([A.name], [temp.x];[temp.y];[temp.z])!") + log_admin("[key_name(usr)] has teleported [capitalize(S.name)] to himself by ([A.name], [temp.x];[temp.y];[temp.z])") + + qdel(temp) + return + else + var/obj/structure/docking_port/destination/D = L[choice] + if(!D) return + + S.move_to_dock(D) + + message_admins("[key_name_admin(usr)] has teleported [capitalize(S.name)] to [choice] ([D.x];[D.y];[D.z])") + log_admin("[key_name(usr)] has teleported [capitalize(S.name)] to [choice] ([D.x];[D.y];[D.z])") + + return + + if(href_list["shuttle_reset"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SR") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + if(alert(usr,"ARE YOU SURE YOU WANT TO RESET [S.name] ([S.type])?","HELP","Yes","No")=="No") return + + S.name = initial(S.name) + S.cooldown = initial(S.cooldown) + S.innacuracy = initial(S.innacuracy) + S.transit_delay = initial(S.transit_delay) + S.pre_flight_delay = initial(S.pre_flight_delay) + S.use_transit = initial(S.use_transit) + S.dir = initial(S.dir) + + S.initialize() + + message_admins("[key_name_admin(usr)] has reset [capitalize(S.name)]'s variables") + log_admin("[key_name(usr)] has reset [capitalize(S.name)]'s variables") + + if(href_list["shuttle_supercharge"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SUP") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + S.supercharge() + + if(href_list["shuttle_mass_lockdown"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","ML") + + if( !(input(usr,"Please type \"Yes\" to confirm that you want to lockdown all shuttles.","IS IT LOOSE?","NO") == "Yes") ) + return + + for(var/datum/shuttle/S in shuttles) + S.lockdown = 1 + + to_chat(usr, "All shuttles were locked down.") + + message_admins("[key_name_admin(usr)] has locked all shuttles down!") + log_admin("[key_name(usr)] has locked all shuttles down!") + + if(href_list["shuttle_show_overlay"]) + feedback_inc("admin_shuttle_magic_used",1) + feedback_add_details("admin_shuttle_magic_used","SO") + + var/datum/shuttle/S = selected_shuttle + if(!istype(S)) return + + if(!S.linked_port) + to_chat(usr, "The shuttle must have a shuttle docking port!") + return + + if(usr.dir != S.dir) + to_chat(usr, "WARNING: You're not facing [dir2text(S.dir)]! The result may be slightly innacurate.") + + S.show_outline(usr) + + + //------------------------------------------------------------------Shuttle stuff end--------------------------------- diff --git a/code/modules/admin/verbs/BrokenInhands.dm b/code/modules/admin/verbs/BrokenInhands.dm index 9190a7be822..2a7c8e89247 100644 --- a/code/modules/admin/verbs/BrokenInhands.dm +++ b/code/modules/admin/verbs/BrokenInhands.dm @@ -1,39 +1,39 @@ -/proc/getbrokeninhands() - set name = "Broken Sprite List" - set category = "Debug" - - if(!alert("Are you sure you want to get the broken sprites list?",,"Yes","No") == "Yes") return - var/icon/IL = new('icons/mob/in-hand/left/items_lefthand.dmi') - var/list/Lstates = IL.IconStates() - var/icon/IR = new('icons/mob/in-hand/right/items_righthand.dmi') - var/list/Rstates = IR.IconStates() - - - var/text - for(var/A in typesof(/obj/item)) - var/obj/item/O = new A( locate(1,1,1) ) - if(!O) continue - var/icon/J = new(O.icon) - var/list/istates = J.IconStates() - if(!Lstates.Find(O.icon_state) && !Lstates.Find(O.item_state)) - if(O.icon_state) - text += "[O.type] is missing left hand icon called \"[O.icon_state]\".\n" - if(!Rstates.Find(O.icon_state) && !Rstates.Find(O.item_state)) - if(O.icon_state) - text += "[O.type] is missing right hand icon called \"[O.icon_state]\".\n" - - - if(O.icon_state) - if(!istates.Find(O.icon_state)) - text += "[O.type] is missing normal icon called \"[O.icon_state]\" in \"[O.icon]\".\n" - //if(O.item_state) - // if(!istates.Find(O.item_state)) - // text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.item_state]\" IN \"[O.icon]\"\n" - //text+="\n" - del(O) - if(text) - var/F = file("broken_hand_icons.txt") - fdel(F) +/proc/getbrokeninhands() + set name = "Broken Sprite List" + set category = "Debug" + + if(!alert("Are you sure you want to get the broken sprites list?",,"Yes","No") == "Yes") return + var/icon/IL = new('icons/mob/in-hand/left/items_lefthand.dmi') + var/list/Lstates = IL.IconStates() + var/icon/IR = new('icons/mob/in-hand/right/items_righthand.dmi') + var/list/Rstates = IR.IconStates() + + + var/text + for(var/A in typesof(/obj/item)) + var/obj/item/O = new A( locate(1,1,1) ) + if(!O) continue + var/icon/J = new(O.icon) + var/list/istates = J.IconStates() + if(!Lstates.Find(O.icon_state) && !Lstates.Find(O.item_state)) + if(O.icon_state) + text += "[O.type] is missing left hand icon called \"[O.icon_state]\".\n" + if(!Rstates.Find(O.icon_state) && !Rstates.Find(O.item_state)) + if(O.icon_state) + text += "[O.type] is missing right hand icon called \"[O.icon_state]\".\n" + + + if(O.icon_state) + if(!istates.Find(O.icon_state)) + text += "[O.type] is missing normal icon called \"[O.icon_state]\" in \"[O.icon]\".\n" + //if(O.item_state) + // if(!istates.Find(O.item_state)) + // text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.item_state]\" IN \"[O.icon]\"\n" + //text+="\n" + del(O) + if(text) + var/F = file("broken_hand_icons.txt") + fdel(F) to_chat(F, text) to_chat(world, "Completed and written to [F]") - + diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 9738f0875c4..25e393800bf 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -1,121 +1,121 @@ - - -//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE! -var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as") - -/client/verb/adminhelp(msg as text) - set category = "Admin" - set name = "Adminhelp" - - if(say_disabled) //This is here to try to identify lag problems + + +//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE! +var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as") + +/client/verb/adminhelp(msg as text) + set category = "Admin" + set name = "Adminhelp" + + if(say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") - return - - //handle muting and automuting - if(prefs.muted & MUTE_ADMINHELP) + return + + //handle muting and automuting + if(prefs.muted & MUTE_ADMINHELP) to_chat(src, "Error: Admin-PM: You cannot send adminhelps (Muted).") - return - if(src.handle_spam_prevention(msg,MUTE_ADMINHELP)) - return - - /**src.verbs -= /client/verb/adminhelp - - spawn(1200) - src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps - src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps//Go to hell - **/ - - //clean the input msg - if(!msg) return - msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN)) - if(!msg) return - var/original_msg = msg - - //explode the input msg into a list - var/list/msglist = text2list(msg, " ") - - //generate keywords lookup - var/list/surnames = list() - var/list/forenames = list() - var/list/ckeys = list() - for(var/mob/M in mob_list) - var/list/indexing = list(M.real_name, M.name) - if(M.mind) indexing += M.mind.name - - for(var/string in indexing) - var/list/L = text2list(string, " ") - var/surname_found = 0 - //surnames - for(var/i=L.len, i>=1, i--) - var/word = ckey(L[i]) - if(word) - surnames[word] = M - surname_found = i - break - //forenames - for(var/i=1, iCL)" : ""]: [msg]" - - //send this msg to all admins - var/admin_number_afk = 0 - for(var/client/X in admins) - if((R_ADMIN|R_MOD) & X.holder.rights) - if(X.is_afk()) - admin_number_afk++ - if(X.prefs.toggles & SOUND_ADMINHELP) + return + if(src.handle_spam_prevention(msg,MUTE_ADMINHELP)) + return + + /**src.verbs -= /client/verb/adminhelp + + spawn(1200) + src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps + src.verbs += /client/verb/adminhelp // 2 minute cool-down for adminhelps//Go to hell + **/ + + //clean the input msg + if(!msg) return + msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN)) + if(!msg) return + var/original_msg = msg + + //explode the input msg into a list + var/list/msglist = text2list(msg, " ") + + //generate keywords lookup + var/list/surnames = list() + var/list/forenames = list() + var/list/ckeys = list() + for(var/mob/M in mob_list) + var/list/indexing = list(M.real_name, M.name) + if(M.mind) indexing += M.mind.name + + for(var/string in indexing) + var/list/L = text2list(string, " ") + var/surname_found = 0 + //surnames + for(var/i=L.len, i>=1, i--) + var/word = ckey(L[i]) + if(word) + surnames[word] = M + surname_found = i + break + //forenames + for(var/i=1, iCL)" : ""]: [msg]" + + //send this msg to all admins + var/admin_number_afk = 0 + for(var/client/X in admins) + if((R_ADMIN|R_MOD) & X.holder.rights) + if(X.is_afk()) + admin_number_afk++ + if(X.prefs.toggles & SOUND_ADMINHELP) to_chat(X, 'sound/effects/adminhelp.ogg') - if(X.prefs.special_popup) - X << output(msg, "window1.msay_output") - else + if(X.prefs.special_popup) + X << output(msg, "window1.msay_output") + else to_chat(X, msg) - - //show it to the person adminhelping too - if(src.prefs.special_popup) - src << output("\[[time_stamp()]] PM to - Admins: [original_msg]", "window1.msay_output") - else + + //show it to the person adminhelping too + if(src.prefs.special_popup) + src << output("\[[time_stamp()]] PM to - Admins: [original_msg]", "window1.msay_output") + else to_chat(src, "PM to-Admins: [original_msg]") - - var/admin_number_present = admins.len - admin_number_afk - log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.") - if(admin_number_present <= 0) - if(!admin_number_afk) - send2adminirc("HELP [key_name(src)]: [original_msg] - No admins online") - else - send2adminirc("HELP [key_name(src)]: [original_msg] - All admins AFK ([admin_number_afk])") - else - send2adminirc("HELP [key_name(src)]: [original_msg]") - feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + var/admin_number_present = admins.len - admin_number_afk + log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.") + if(admin_number_present <= 0) + if(!admin_number_afk) + send2adminirc("HELP [key_name(src)]: [original_msg] - No admins online") + else + send2adminirc("HELP [key_name(src)]: [original_msg] - All admins AFK ([admin_number_afk])") + else + send2adminirc("HELP [key_name(src)]: [original_msg]") + feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return \ No newline at end of file diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 37f953a5dce..98870aa0d7c 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -1,171 +1,171 @@ -/client/proc/Jump(var/area/A in sortedAreas) - set name = "Jump to Area" - set desc = "Area to jump to" - set category = "Admin" - if(!src.holder) +/client/proc/Jump(var/area/A in sortedAreas) + set name = "Jump to Area" + set desc = "Area to jump to" + set category = "Admin" + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - - if(config.allow_admin_jump) - if(!A) - return - - var/list/turfs = list() - for(var/turf/T in A) - if(T.density) - continue - turfs.Add(T) - - var/turf/T = pick_n_take(turfs) - if(!T) + return + + if(config.allow_admin_jump) + if(!A) + return + + var/list/turfs = list() + for(var/turf/T in A) + if(T.density) + continue + turfs.Add(T) + + var/turf/T = pick_n_take(turfs) + if(!T) to_chat(src, "Nowhere to jump to!") - return - usr.loc = T - - log_admin("[key_name(usr)] jumped to [A]") - message_admins("[key_name_admin(usr)] jumped to [A]", 1) - feedback_add_details("admin_verb","JA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else - alert("Admin jumping disabled") - -/client/proc/jumptoturf(var/turf/T in world) - set name = "Jump to Turf" - set category = "Admin" - if(!src.holder) + return + usr.loc = T + + log_admin("[key_name(usr)] jumped to [A]") + message_admins("[key_name_admin(usr)] jumped to [A]", 1) + feedback_add_details("admin_verb","JA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + alert("Admin jumping disabled") + +/client/proc/jumptoturf(var/turf/T in world) + set name = "Jump to Turf" + set category = "Admin" + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - if(config.allow_admin_jump) - log_admin("[key_name(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]") - message_admins("[key_name_admin(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]", 1) - usr.loc = T - feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else - alert("Admin jumping disabled") - return - -/client/proc/jumptomob(var/mob/M in mob_list) - set category = "Admin" - set name = "Jump to Mob" - - if(!src.holder) + return + if(config.allow_admin_jump) + log_admin("[key_name(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]") + message_admins("[key_name_admin(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]", 1) + usr.loc = T + feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + alert("Admin jumping disabled") + return + +/client/proc/jumptomob(var/mob/M in mob_list) + set category = "Admin" + set name = "Jump to Mob" + + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - - if(config.allow_admin_jump) - log_admin("[key_name(usr)] jumped to [key_name(M)]") - message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1) - if(src.mob) - var/mob/A = src.mob - var/turf/T = get_turf(M) - if(T && isturf(T)) - feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - A.loc = T - else + return + + if(config.allow_admin_jump) + log_admin("[key_name(usr)] jumped to [key_name(M)]") + message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1) + if(src.mob) + var/mob/A = src.mob + var/turf/T = get_turf(M) + if(T && isturf(T)) + feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + A.loc = T + else to_chat(A, "This mob is not located in the game world.") - else - alert("Admin jumping disabled") - -/client/proc/jumptocoord(tx as num, ty as num, tz as num) - set category = "Admin" - set name = "Jump to Coordinate" - - if (!holder) + else + alert("Admin jumping disabled") + +/client/proc/jumptocoord(tx as num, ty as num, tz as num) + set category = "Admin" + set name = "Jump to Coordinate" + + if (!holder) to_chat(src, "Only administrators may use this command.") - return - - if (config.allow_admin_jump) - if(src.mob) - var/mob/A = src.mob - A.x = tx - A.y = ty - A.z = tz - feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") - - else - alert("Admin jumping disabled") - -/client/proc/jumptokey() - set category = "Admin" - set name = "Jump to Key" - - if(!src.holder) + return + + if (config.allow_admin_jump) + if(src.mob) + var/mob/A = src.mob + A.x = tx + A.y = ty + A.z = tz + feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") + + else + alert("Admin jumping disabled") + +/client/proc/jumptokey() + set category = "Admin" + set name = "Jump to Key" + + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - - if(config.allow_admin_jump) - var/list/keys = list() - for(var/mob/M in player_list) - if(M.ckey) - keys["[M.ckey]"] = M //used to be M.client but GHOSTED PEOPLE WERE PUTTING NULL ENTRIES IN THE FUCKING LIST - var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortList(keys) - if(!selection) + return + + if(config.allow_admin_jump) + var/list/keys = list() + for(var/mob/M in player_list) + if(M.ckey) + keys["[M.ckey]"] = M //used to be M.client but GHOSTED PEOPLE WERE PUTTING NULL ENTRIES IN THE FUCKING LIST + var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortList(keys) + if(!selection) to_chat(src, "No keys found.") - return - var/mob/M = keys[selection] - log_admin("[key_name(usr)] jumped to [key_name(M)]") - message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1) - usr.loc = get_turf(M) - feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else - alert("Admin jumping disabled") - -/client/proc/Getmob(var/mob/M in mob_list) - set category = "Admin" - set name = "Get Mob" - set desc = "Mob to teleport" - if(!src.holder) + return + var/mob/M = keys[selection] + log_admin("[key_name(usr)] jumped to [key_name(M)]") + message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1) + usr.loc = get_turf(M) + feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + alert("Admin jumping disabled") + +/client/proc/Getmob(var/mob/M in mob_list) + set category = "Admin" + set name = "Get Mob" + set desc = "Mob to teleport" + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - if(config.allow_admin_jump) - log_admin("[key_name(usr)] teleported [key_name(M)]") - message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1) - M.teleport_to(usr) - feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else - alert("Admin jumping disabled") - -/client/proc/Getkey() - set category = "Admin" - set name = "Get Key" - set desc = "Key to teleport" - - if(!src.holder) + return + if(config.allow_admin_jump) + log_admin("[key_name(usr)] teleported [key_name(M)]") + message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1) + M.teleport_to(usr) + feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + alert("Admin jumping disabled") + +/client/proc/Getkey() + set category = "Admin" + set name = "Get Key" + set desc = "Key to teleport" + + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - - if(config.allow_admin_jump) - var/list/keys = list() - for(var/mob/M in player_list) - if(M) keys += M //used to be M.key but it was putting FUCKING NULLS IN THE LIST - var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) - if(!selection) - return - var/mob/M = selection - - if(!M) - return - log_admin("[key_name(usr)] teleported [key_name(M)]") - message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1) - if(M) - M.teleport_to(usr) - feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else - alert("Admin jumping disabled") - -/client/proc/sendmob(var/mob/M in sortmobs()) - set category = "Admin" - set name = "Send Mob" - if(!src.holder) + return + + if(config.allow_admin_jump) + var/list/keys = list() + for(var/mob/M in player_list) + if(M) keys += M //used to be M.key but it was putting FUCKING NULLS IN THE LIST + var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) + if(!selection) + return + var/mob/M = selection + + if(!M) + return + log_admin("[key_name(usr)] teleported [key_name(M)]") + message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1) + if(M) + M.teleport_to(usr) + feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + alert("Admin jumping disabled") + +/client/proc/sendmob(var/mob/M in sortmobs()) + set category = "Admin" + set name = "Send Mob" + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - var/area/A = input(usr, "Pick an area.", "Pick an area") in sortedAreas - if(A) - if(config.allow_admin_jump) - M.teleport_to(pick(get_area_turfs(A))) - feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - log_admin("[key_name(usr)] teleported [key_name(M)] to [A]") - message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1) - else + return + var/area/A = input(usr, "Pick an area.", "Pick an area") in sortedAreas + if(A) + if(config.allow_admin_jump) + M.teleport_to(pick(get_area_turfs(A))) + feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + log_admin("[key_name(usr)] teleported [key_name(M)] to [A]") + message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]", 1) + else alert("Admin jumping disabled") \ No newline at end of file diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 9c9b4ec5ef2..41a625c5cdb 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -1,48 +1,48 @@ -/client/proc/cmd_admin_say(msg as text) - set category = "Special Verbs" - set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite - set hidden = 1 - if(!check_rights(R_ADMIN)) return - - msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) - if(!msg) return - - log_admin("[key_name(src)] : [msg]") - - if(check_rights(R_ADMIN,0)) - msg = "ADMIN: [key_name(usr, 1)] (JMP): [msg]" - for(var/client/C in admins) - if(R_ADMIN & C.holder.rights) +/client/proc/cmd_admin_say(msg as text) + set category = "Special Verbs" + set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite + set hidden = 1 + if(!check_rights(R_ADMIN)) return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + if(!msg) return + + log_admin("[key_name(src)] : [msg]") + + if(check_rights(R_ADMIN,0)) + msg = "ADMIN: [key_name(usr, 1)] (JMP): [msg]" + for(var/client/C in admins) + if(R_ADMIN & C.holder.rights) to_chat(C, msg) - - feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_mod_window() - set category = "Special Verbs" - set name = "mWindow" - set hidden = 1 - - if(!check_rights(R_ADMIN|R_MOD)) return - winset(src, "window1", "is-visible=true") - -/client/proc/cmd_mod_say(msg as text) - set category = "Special Verbs" - set name = "Msay" - set hidden = 1 - - if(!check_rights(R_ADMIN|R_MOD)) return - - msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) - log_admin("MOD: [key_name(src)] : [msg]") - - if (!msg) - return - var/color = "mod" - if (check_rights(R_ADMIN,0)) - color = "adminmod" - for(var/client/C in admins) - if((R_ADMIN|R_MOD) & C.holder.rights) - if(C.prefs.special_popup) - C << output("\[[time_stamp()]] [key_name(src,1)] (JMP): [msg]", "window1.msay_output") - else + + feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_mod_window() + set category = "Special Verbs" + set name = "mWindow" + set hidden = 1 + + if(!check_rights(R_ADMIN|R_MOD)) return + winset(src, "window1", "is-visible=true") + +/client/proc/cmd_mod_say(msg as text) + set category = "Special Verbs" + set name = "Msay" + set hidden = 1 + + if(!check_rights(R_ADMIN|R_MOD)) return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + log_admin("MOD: [key_name(src)] : [msg]") + + if (!msg) + return + var/color = "mod" + if (check_rights(R_ADMIN,0)) + color = "adminmod" + for(var/client/C in admins) + if((R_ADMIN|R_MOD) & C.holder.rights) + if(C.prefs.special_popup) + C << output("\[[time_stamp()]] [key_name(src,1)] (JMP): [msg]", "window1.msay_output") + else to_chat(C, "MOD: [key_name(src,1)] (JMP): [msg]") diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm index 15c3d2c571f..697b6b2c810 100644 --- a/code/modules/admin/verbs/atmosdebug.dm +++ b/code/modules/admin/verbs/atmosdebug.dm @@ -1,46 +1,46 @@ -/client/proc/atmosscan() - set category = "Mapping" - set name = "Check Plumbing" - if(!src.holder) +/client/proc/atmosscan() + set category = "Mapping" + set name = "Check Plumbing" + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - //all plumbing - yes, some things might get stated twice, doesn't matter. - for (var/obj/machinery/atmospherics/plumbing in atmos_machines) - if (plumbing.nodealert) + return + feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + //all plumbing - yes, some things might get stated twice, doesn't matter. + for (var/obj/machinery/atmospherics/plumbing in atmos_machines) + if (plumbing.nodealert) to_chat(usr, "Unconnected [plumbing.name] located at [formatJumpTo(plumbing.loc)]") - - //Manifolds - for (var/obj/machinery/atmospherics/pipe/manifold/pipe in atmos_machines) - if (!pipe.node1 || !pipe.node2 || !pipe.node3) + + //Manifolds + for (var/obj/machinery/atmospherics/pipe/manifold/pipe in atmos_machines) + if (!pipe.node1 || !pipe.node2 || !pipe.node3) to_chat(usr, "Unconnected [pipe.name] located at [formatJumpTo(pipe.loc)]") - - //4-way Manifolds - for (var/obj/machinery/atmospherics/pipe/manifold4w/pipe in atmos_machines) - if (!pipe.node1 || !pipe.node2 || !pipe.node3 || !pipe.node4) + + //4-way Manifolds + for (var/obj/machinery/atmospherics/pipe/manifold4w/pipe in atmos_machines) + if (!pipe.node1 || !pipe.node2 || !pipe.node3 || !pipe.node4) to_chat(usr, "Unconnected [pipe.name] located at [formatJumpTo(pipe.loc)]") - - //Pipes - for (var/obj/machinery/atmospherics/pipe/simple/pipe in atmos_machines) - if (!pipe.node1 || !pipe.node2) + + //Pipes + for (var/obj/machinery/atmospherics/pipe/simple/pipe in atmos_machines) + if (!pipe.node1 || !pipe.node2) to_chat(usr, "Unconnected [pipe.name] located at [formatJumpTo(pipe.loc)]") - -/client/proc/powerdebug() - set category = "Mapping" - set name = "Check Power" - if(!src.holder) + +/client/proc/powerdebug() + set category = "Mapping" + set name = "Check Power" + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - feedback_add_details("admin_verb","CPOW") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - for (var/datum/powernet/PN in powernets) - if (!PN.nodes || !PN.nodes.len) - if(PN.cables && (PN.cables.len > 1)) - var/obj/structure/cable/C = PN.cables[1] + return + feedback_add_details("admin_verb","CPOW") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + for (var/datum/powernet/PN in powernets) + if (!PN.nodes || !PN.nodes.len) + if(PN.cables && (PN.cables.len > 1)) + var/obj/structure/cable/C = PN.cables[1] to_chat(usr, "Powernet with no nodes! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [get_area(C.loc)]") - - if (!PN.cables || (PN.cables.len < 10)) - if(PN.cables && (PN.cables.len > 1)) - var/obj/structure/cable/C = PN.cables[1] + + if (!PN.cables || (PN.cables.len < 10)) + if(PN.cables && (PN.cables.len > 1)) + var/obj/structure/cable/C = PN.cables[1] to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [C.x], [C.y], [C.z] in area [get_area(C.loc)]") diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index b0401b781d8..d291d6e9a7e 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -1,39 +1,39 @@ -/client/proc/dsay(msg as text) - set category = "Special Verbs" - set name = "Dsay" //Gave this shit a shorter name so you only have to time out "dsay" rather than "dead say" to use it --NeoFite - set hidden = 1 - if(!src.holder) +/client/proc/dsay(msg as text) + set category = "Special Verbs" + set name = "Dsay" //Gave this shit a shorter name so you only have to time out "dsay" rather than "dead say" to use it --NeoFite + set hidden = 1 + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - if(!src.mob) - return - if(prefs.muted & MUTE_DEADCHAT) + return + if(!src.mob) + return + if(prefs.muted & MUTE_DEADCHAT) to_chat(src, "You cannot send DSAY messages (muted).") - return - - if(!(prefs.toggles & CHAT_DEAD)) + return + + if(!(prefs.toggles & CHAT_DEAD)) to_chat(src, "You have deadchat muted.") - return - - if (src.handle_spam_prevention(msg,MUTE_DEADCHAT)) - return - - msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) - log_admin("[key_name(src)] : [msg]") - - if (!msg) - return - - var/rendered = "DEAD: ADMIN([src.holder.fakekey ? pick("BADMIN", "hornigranny", "TLF", "scaredforshadows", "KSI", "Silnazi", "HerpEs", "BJ69", "SpoofedEdd", "Uhangay", "Wario90900", "Regarity", "MissPhareon", "LastFish", "unMportant", "Deurpyn", "Fatbeaver") : src.key]) says, \"[msg]\"" - - for (var/mob/M in player_list) - if (istype(M, /mob/new_player) || !M.client) - continue - - if(M.client && M.client.holder && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to admins who have deadchat toggled on - M.show_message(rendered, 2) - - else if(M.client && M.stat == DEAD && (M.client) && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to regular ghosts who have deadchat toggled on - M.show_message(rendered, 2) - + return + + if (src.handle_spam_prevention(msg,MUTE_DEADCHAT)) + return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + log_admin("[key_name(src)] : [msg]") + + if (!msg) + return + + var/rendered = "DEAD: ADMIN([src.holder.fakekey ? pick("BADMIN", "hornigranny", "TLF", "scaredforshadows", "KSI", "Silnazi", "HerpEs", "BJ69", "SpoofedEdd", "Uhangay", "Wario90900", "Regarity", "MissPhareon", "LastFish", "unMportant", "Deurpyn", "Fatbeaver") : src.key]) says, \"[msg]\"" + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player) || !M.client) + continue + + if(M.client && M.client.holder && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to admins who have deadchat toggled on + M.show_message(rendered, 2) + + else if(M.client && M.stat == DEAD && (M.client) && (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 diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 5fdfc7d9f63..b23990a5bc9 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -1,247 +1,247 @@ -/client/proc/air_report() - set category = "Debug" - set name = "Show Air Report" - - /*(!master_controller || !air_master) - alert(usr,"Master_controller or air_master not found.","Air Report") - return 0 - - var/active_groups = 0 - var/inactive_groups = 0 - var/active_tiles = 0 - for(var/datum/air_group/group in air_master.air_groups) - if(group.group_processing) - active_groups++ - else - inactive_groups++ - active_tiles += group.members.len - - var/hotspots = 0 - for(var/obj/effect/hotspot/hotspot in world) - hotspots++ - - var/output = {"AIR SYSTEMS REPORT
    -General Processing Data
    -# of Groups: [air_master.air_groups.len]
    ----- Active: [active_groups]
    ----- Inactive: [inactive_groups]
    --------- Tiles: [active_tiles]
    -# of Active Singletons: [air_master.active_singletons.len]
    -
    -Special Processing Data
    -Hotspot Processing: [hotspots]
    -High Temperature Processing: [air_master.active_super_conductivity.len]
    -High Pressure Processing: [air_master.high_pressure_delta.len] (not yet implemented)
    -
    -Geometry Processing Data
    -Group Rebuild: [air_master.groups_to_rebuild.len]
    -Tile Update: [air_master.tiles_to_update.len]
    -"} - - usr << browse(output,"window=airreport") - feedback_add_details("admin_verb","SAR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -*/ -/client/proc/air_status(turf/target as turf) - set category = "Debug" - set name = "Display Air Status" - - /*(!isturf(target)) - return - - var/datum/gas_mixture/GM = target.return_air() - var/burning = 0 - if(istype(target, /turf/simulated)) - var/turf/simulated/T = target - if(T.active_hotspot) - burning = 1 - +/client/proc/air_report() + set category = "Debug" + set name = "Show Air Report" + + /*(!master_controller || !air_master) + alert(usr,"Master_controller or air_master not found.","Air Report") + return 0 + + var/active_groups = 0 + var/inactive_groups = 0 + var/active_tiles = 0 + for(var/datum/air_group/group in air_master.air_groups) + if(group.group_processing) + active_groups++ + else + inactive_groups++ + active_tiles += group.members.len + + var/hotspots = 0 + for(var/obj/effect/hotspot/hotspot in world) + hotspots++ + + var/output = {"AIR SYSTEMS REPORT
    +General Processing Data
    +# of Groups: [air_master.air_groups.len]
    +---- Active: [active_groups]
    +---- Inactive: [inactive_groups]
    +-------- Tiles: [active_tiles]
    +# of Active Singletons: [air_master.active_singletons.len]
    +
    +Special Processing Data
    +Hotspot Processing: [hotspots]
    +High Temperature Processing: [air_master.active_super_conductivity.len]
    +High Pressure Processing: [air_master.high_pressure_delta.len] (not yet implemented)
    +
    +Geometry Processing Data
    +Group Rebuild: [air_master.groups_to_rebuild.len]
    +Tile Update: [air_master.tiles_to_update.len]
    +"} + + usr << browse(output,"window=airreport") + feedback_add_details("admin_verb","SAR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +*/ +/client/proc/air_status(turf/target as turf) + set category = "Debug" + set name = "Display Air Status" + + /*(!isturf(target)) + return + + var/datum/gas_mixture/GM = target.return_air() + var/burning = 0 + if(istype(target, /turf/simulated)) + var/turf/simulated/T = target + if(T.active_hotspot) + burning = 1 + to_chat(usr, "@[target.x],[target.y] ([GM.group_multiplier]): O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("BURNING"):(null)]") - for(var/datum/gas/trace_gas in GM.trace_gases) + for(var/datum/gas/trace_gas in GM.trace_gases) to_chat(usr, "[trace_gas.type]: [trace_gas.moles]") - feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - */ - -/client/proc/_fix_delayers(var/dtype) - var/largest_delay = 0 - var/mob/most_delayed_mob = null - var/delay=0 - for(var/mob/M in mob_list) - if(!M.client) - continue - // Get stats - var/datum/delay_controller/delayer = M.vars["[dtype]_delayer"] - if(delayer.blocked()) - delay = delayer.next_allowed - world.time - if(delay > largest_delay) - most_delayed_mob=M - largest_delay=delay - - // Unfreeze - delayer.next_allowed = 0 - message_admins("[key_name_admin(most_delayed_mob)] had the largest [dtype] delay with [largest_delay] frames / [largest_delay/10] seconds!", 1) - -/client/proc/fix_next_move() - set category = "Debug" - set name = "Unfreeze Everyone" - if(!usr.client.holder) return - - _fix_delayers("move") - _fix_delayers("click") - _fix_delayers("attack") - _fix_delayers("special") - - message_admins("world.time = [world.time]", 1) - feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -#undef GATHER_DELAYER_LOCKUPS - -/client/proc/radio_report() - set category = "Debug" - set name = "Radio report" - - var/filters = list( - "1" = "RADIO_TO_AIRALARM", - "2" = "RADIO_FROM_AIRALARM", - "3" = "RADIO_CHAT", - "4" = "RADIO_ATMOSIA", - "5" = "RADIO_NAVBEACONS", - "6" = "RADIO_AIRLOCK", - "7" = "RADIO_SECBOT", - "8" = "RADIO_MULEBOT", - "_default" = "NO_FILTER" - ) - var/output = "Radio Report
    " - for (var/fq in radio_controller.frequencies) - output += "Freq: [fq]
    " - var/list/datum/radio_frequency/fqs = radio_controller.frequencies[fq] - if (!fqs) - output += "  ERROR
    " - continue - for (var/filter in fqs.devices) - var/list/f = fqs.devices[filter] - if (!f) - output += "  [filters[filter]]: ERROR
    " - continue - output += "  [filters[filter]]: [f.len]
    " - for (var/device in f) - if (isobj(device)) - output += "    [device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])
    " - else - output += "    [device]
    " - - usr << browse(output,"window=radioreport") - feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/reload_admins() - set name = "Reload Admins" - set category = "Debug" - - if(!check_rights(R_SERVER)) return - - message_admins("[usr] manually reloaded admins") - load_admins() - feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -//todo: -/client/proc/jump_to_dead_group() - set name = "Jump to dead group" - set category = "Debug" - - /* - if(!holder) + feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + */ + +/client/proc/_fix_delayers(var/dtype) + var/largest_delay = 0 + var/mob/most_delayed_mob = null + var/delay=0 + for(var/mob/M in mob_list) + if(!M.client) + continue + // Get stats + var/datum/delay_controller/delayer = M.vars["[dtype]_delayer"] + if(delayer.blocked()) + delay = delayer.next_allowed - world.time + if(delay > largest_delay) + most_delayed_mob=M + largest_delay=delay + + // Unfreeze + delayer.next_allowed = 0 + message_admins("[key_name_admin(most_delayed_mob)] had the largest [dtype] delay with [largest_delay] frames / [largest_delay/10] seconds!", 1) + +/client/proc/fix_next_move() + set category = "Debug" + set name = "Unfreeze Everyone" + if(!usr.client.holder) return + + _fix_delayers("move") + _fix_delayers("click") + _fix_delayers("attack") + _fix_delayers("special") + + message_admins("world.time = [world.time]", 1) + feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +#undef GATHER_DELAYER_LOCKUPS + +/client/proc/radio_report() + set category = "Debug" + set name = "Radio report" + + var/filters = list( + "1" = "RADIO_TO_AIRALARM", + "2" = "RADIO_FROM_AIRALARM", + "3" = "RADIO_CHAT", + "4" = "RADIO_ATMOSIA", + "5" = "RADIO_NAVBEACONS", + "6" = "RADIO_AIRLOCK", + "7" = "RADIO_SECBOT", + "8" = "RADIO_MULEBOT", + "_default" = "NO_FILTER" + ) + var/output = "Radio Report
    " + for (var/fq in radio_controller.frequencies) + output += "Freq: [fq]
    " + var/list/datum/radio_frequency/fqs = radio_controller.frequencies[fq] + if (!fqs) + output += "  ERROR
    " + continue + for (var/filter in fqs.devices) + var/list/f = fqs.devices[filter] + if (!f) + output += "  [filters[filter]]: ERROR
    " + continue + output += "  [filters[filter]]: [f.len]
    " + for (var/device in f) + if (isobj(device)) + output += "    [device] ([device:x],[device:y],[device:z] in area [get_area(device:loc)])
    " + else + output += "    [device]
    " + + usr << browse(output,"window=radioreport") + feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/reload_admins() + set name = "Reload Admins" + set category = "Debug" + + if(!check_rights(R_SERVER)) return + + message_admins("[usr] manually reloaded admins") + load_admins() + feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +//todo: +/client/proc/jump_to_dead_group() + set name = "Jump to dead group" + set category = "Debug" + + /* + if(!holder) to_chat(src, "Only administrators may use this command.") - return - - if(!air_master) + return + + if(!air_master) to_chat(usr, "Cannot find air_system") - return - var/datum/air_group/dead_groups = list() - for(var/datum/air_group/group in air_master.air_groups) - if (!group.group_processing) - dead_groups += group - var/datum/air_group/dest_group = pick(dead_groups) - usr.loc = pick(dest_group.members) - feedback_add_details("admin_verb","JDAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - */ - -/client/proc/kill_airgroup() - set name = "Kill Local Airgroup" - set desc = "Use this to allow manual manupliation of atmospherics." - set category = "Debug" - - /* - if(!holder) + return + var/datum/air_group/dead_groups = list() + for(var/datum/air_group/group in air_master.air_groups) + if (!group.group_processing) + dead_groups += group + var/datum/air_group/dest_group = pick(dead_groups) + usr.loc = pick(dest_group.members) + feedback_add_details("admin_verb","JDAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + */ + +/client/proc/kill_airgroup() + set name = "Kill Local Airgroup" + set desc = "Use this to allow manual manupliation of atmospherics." + set category = "Debug" + + /* + if(!holder) to_chat(src, "Only administrators may use this command.") - return - - if(!air_master) + return + + if(!air_master) to_chat(usr, "Cannot find air_system") - return - - var/turf/T = get_turf(usr) - if(istype(T, /turf/simulated)) - var/datum/air_group/AG = T:parent - AG.next_check = 30 - AG.group_processing = 0 - else + return + + var/turf/T = get_turf(usr) + if(istype(T, /turf/simulated)) + var/datum/air_group/AG = T:parent + AG.next_check = 30 + AG.group_processing = 0 + else to_chat(usr, "Local airgroup is unsimulated!") - feedback_add_details("admin_verb","KLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - */ - -/client/proc/print_jobban_old() - set name = "Print Jobban Log" - set desc = "This spams all the active jobban entries for the current round to standard output." - set category = "Debug" - + feedback_add_details("admin_verb","KLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + */ + +/client/proc/print_jobban_old() + set name = "Print Jobban Log" + set desc = "This spams all the active jobban entries for the current round to standard output." + set category = "Debug" + to_chat(usr, "Jobbans active in this round.") - for(var/t in jobban_keylist) + for(var/t in jobban_keylist) to_chat(usr, "[t]") - -/client/proc/print_jobban_old_filter() - set name = "Search Jobban Log" - set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output." - set category = "Debug" - - var/filter = input("Contains what?","Filter") as text|null - if(!filter) - return - + +/client/proc/print_jobban_old_filter() + set name = "Search Jobban Log" + set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output." + set category = "Debug" + + var/filter = input("Contains what?","Filter") as text|null + if(!filter) + return + to_chat(usr, "Jobbans active in this round.") - for(var/t in jobban_keylist) - if(findtext(t, filter)) + for(var/t in jobban_keylist) + if(findtext(t, filter)) to_chat(usr, "[t]") - -// For /vg/ Wiki docs -/client/proc/dump_chemreactions() - set category = "Debug" - set name = "Dump Chemical Reactions" - - var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction - - var/str = {" -{| class="wikitable" -|- -! Name -! Reactants -! Result"} - for(var/path in paths) - var/datum/chemical_reaction/R = new path() - str += {" -|- -! [R.name]"} - if(R.required_reagents) - str += "\n|
      " - for(var/r_id in R.required_reagents) - str += "
    • {{reagent|[R.required_reagents[r_id]]|[r_id]}}
    • " - for(var/r_id in R.required_catalysts) - str += "
    • {{reagent|[R.required_catalysts[r_id]]|[r_id]}}
    • " - str += "
    " - else - str += "\n|''None!''" - if(R.result) - str += "\n|{{reagent|[R.result_amount]|[R.result]}}" - else - str += "\n|''(Check [R.type]/on_reaction()!)''" + +// For /vg/ Wiki docs +/client/proc/dump_chemreactions() + set category = "Debug" + set name = "Dump Chemical Reactions" + + var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction + + var/str = {" +{| class="wikitable" +|- +! Name +! Reactants +! Result"} + for(var/path in paths) + var/datum/chemical_reaction/R = new path() + str += {" +|- +! [R.name]"} + if(R.required_reagents) + str += "\n|
      " + for(var/r_id in R.required_reagents) + str += "
    • {{reagent|[R.required_reagents[r_id]]|[r_id]}}
    • " + for(var/r_id in R.required_catalysts) + str += "
    • {{reagent|[R.required_catalysts[r_id]]|[r_id]}}
    • " + str += "
    " + else + str += "\n|''None!''" + if(R.result) + str += "\n|{{reagent|[R.result_amount]|[R.result]}}" + else + str += "\n|''(Check [R.type]/on_reaction()!)''" text2file(str+"\n|}","chemistry-recipes.wiki") \ No newline at end of file diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index e3562cb18eb..e32fb99807f 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -1,400 +1,400 @@ -//- Are all the floors with or without air, as they should be? (regular or airless) -//- Does the area have an APC? -//- Does the area have an Air Alarm? -//- Does the area have a Request Console? -//- Does the area have lights? -//- Does the area have a light switch? -//- Does the area have enough intercoms? -//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug) -//- Is the area connected to the scrubbers air loop? -//- Is the area connected to the vent air loop? (vent pumps) -//- Is everything wired properly? -//- Does the area have a fire alarm and firedoors? -//- Do all pod doors work properly? -//- Are accesses set properly on doors, pod buttons, etc. -//- Are all items placed properly? (not below vents, scrubbers, tables) -//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room? -//- Check for any misplaced or stacked piece of pipe (air and disposal) -//- Check for any misplaced or stacked piece of wire -//- Identify how hard it is to break into the area and where the weak points are -//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels. - -var/camera_range_display_status = 0 -var/intercom_range_display_status = 0 - -/obj/effect/debugging/camera_range - icon = 'icons/480x480.dmi' - icon_state = "25percent" - - New() - src.pixel_x = -224 - src.pixel_y = -224 - -/obj/effect/debugging/marker - icon = 'icons/turf/areas.dmi' - icon_state = "yellow" - -/obj/effect/debugging/marker/Move() - return 0 - -/client/proc/do_not_use_these() - set category = "Mapping" - set name = "-None of these are for ingame use!!" - - ..() - -/client/proc/camera_view() - set category = "Mapping" - set name = "Camera Range Display" - - if(camera_range_display_status) - camera_range_display_status = 0 - else - camera_range_display_status = 1 - - - - for(var/obj/effect/debugging/camera_range/C in world) - del(C) - - if(camera_range_display_status) - for(var/obj/machinery/camera/C in cameranet.cameras) - new/obj/effect/debugging/camera_range(C.loc) - feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - -/client/proc/sec_camera_report() - set category = "Mapping" - set name = "Camera Report" - - if(!master_controller) - alert(usr,"Master_controller not found.","Sec Camera Report") - return 0 - - var/list/obj/machinery/camera/CL = list() - - for(var/obj/machinery/camera/C in cameranet.cameras) - CL += C - - var/output = {"CAMERA ANOMALIES REPORT
    -The following anomalies have been detected. The ones in red need immediate attention: Some of those in black may be intentional.
      "} - - for(var/obj/machinery/camera/C1 in CL) - for(var/obj/machinery/camera/C2 in CL) - if(C1 != C2) - if(C1.c_tag == C2.c_tag) - output += "
    • c_tag match for sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) and \[[C2.x], [C2.y], [C2.z]\] ([C2.loc.loc]) - c_tag is [C1.c_tag]
    • " - if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y) - output += "
    • FULLY overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]
    • " - if(C1.loc == C2.loc) - output += "
    • overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]
    • " - var/turf/T = get_step(C1,turn(C1.dir,180)) - if(!T || !isturf(T) || !T.density ) - if(!(locate(/obj/structure/grille,T))) - var/window_check = 0 - for(var/obj/structure/window/W in T) - if (W.dir == turn(C1.dir,180) || W.is_fulltile() ) - window_check = 1 - break - if(!window_check) - output += "
    • Camera not connected to wall at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Network: [C1.network]
    • " - - output += "
    " - usr << browse(output,"window=airreport;size=1000x500") - feedback_add_details("admin_verb","mCRP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/intercom_view() - set category = "Mapping" - set name = "Intercom Range Display" - - if (intercom_range_display_status) - intercom_range_display_status = FALSE - else - intercom_range_display_status = TRUE - - for (var/obj/effect/debugging/marker/M in world) - qdel(M) - - if (intercom_range_display_status) - for (var/obj/item/device/radio/intercom/I in world) - for (var/turf/T in view(I.canhear_range, I)) - new /obj/effect/debugging/marker(T) - - feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/enable_debug_verbs() - set category = "Debug" - set name = "Debug verbs" - - if(!check_rights(R_DEBUG)) return - - src.verbs += /client/proc/do_not_use_these //-errorage - src.verbs += /client/proc/camera_view //-errorage - src.verbs += /client/proc/sec_camera_report //-errorage - src.verbs += /client/proc/intercom_view //-errorage - src.verbs += /client/proc/air_status //Air things - src.verbs += /client/proc/Cell //More air things - src.verbs += /client/proc/pdiff //Antigriff testing - N3X - src.verbs += /client/proc/atmosscan //check plumbing - src.verbs += /client/proc/powerdebug //check power - src.verbs += /client/proc/count_objects_on_z_level - src.verbs += /client/proc/count_objects_all - src.verbs += /client/proc/cmd_assume_direct_control //-errorage - src.verbs += /client/proc/jump_to_dead_group - src.verbs += /client/proc/startSinglo - src.verbs += /client/proc/cheat_power // Because the above doesn't work off-station. Or at all, occasionally - N3X - src.verbs += /client/proc/setup_atmos // Laziness during atmos testing - N3X - src.verbs += /client/proc/ticklag //allows you to set the ticklag. - src.verbs += /client/proc/cmd_admin_grantfullaccess - src.verbs += /client/proc/kaboom - src.verbs += /client/proc/splash - src.verbs += /client/proc/cmd_admin_areatest - src.verbs += /client/proc/cmd_admin_rejuvenate - src.verbs += /datum/admins/proc/show_traitor_panel - src.verbs += /client/proc/print_jobban_old - src.verbs += /client/proc/print_jobban_old_filter - src.verbs += /client/proc/forceEvent - //src.verbs += /client/proc/break_all_air_groups - //src.verbs += /client/proc/regroup_all_air_groups - //src.verbs += /client/proc/kill_pipe_processing - //src.verbs += /client/proc/kill_air_processing - //src.verbs += /client/proc/disable_communication - //src.verbs += /client/proc/disable_movement - src.verbs += /client/proc/Zone_Info - src.verbs += /client/proc/Test_ZAS_Connection - src.verbs += /client/proc/SDQL2_query - src.verbs += /client/proc/check_sim_unsim - src.verbs += /client/proc/nanomapgen_DumpImage - src.verbs += /client/proc/nanomapgen_DumpImageAll - //src.verbs += /client/proc/cmd_admin_rejuvenate - - feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/count_objects_on_z_level() - set category = "Mapping" - set name = "Count Objects On Level" - - var/level = input("Which z-level?","Level?") as text - if(!level) return - var/num_level = text2num(level) - if(!num_level) return - if(!isnum(num_level)) return - - var/type_text = input("Which type path?","Path?") as text - if(!type_text) return - var/type_path = text2path(type_text) - if(!type_path) return - - var/count = 0 - - var/list/atom/atom_list = list() - - for(var/atom/A in world) - if(istype(A,type_path)) - var/atom/B = A - while(!(isturf(B.loc))) - if(B && B.loc) - B = B.loc - else - break - if(B) - if(B.z == num_level) - count++ - atom_list += A - /* - var/atom/temp_atom - for(var/i = 0; i <= (atom_list.len/10); i++) - var/line = "" - for(var/j = 1; j <= 10; j++) - if(i*10+j <= atom_list.len) - temp_atom = atom_list[i*10+j] - line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; " - to_chat(world, line)*/ - - to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level]") - feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/count_objects_all() - set background = 1 - set category = "Mapping" - set name = "Count Objects All" - - var/type_text = input("Which type path?","") as text - if(!type_text) return - var/type_path = text2path(type_text) - if(!type_path) return - - var/count = 0 - - for(var/atom/A in world) - if(istype(A,type_path)) - count++ - /* - var/atom/temp_atom - for(var/i = 0; i <= (atom_list.len/10); i++) - var/line = "" - for(var/j = 1; j <= 10; j++) - if(i*10+j <= atom_list.len) - temp_atom = atom_list[i*10+j] - line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; " - to_chat(world, line)*/ - - to_chat(usr, "There are [count] objects of type [type_path] in the game world") - feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/check_sim_unsim() - set category = "Mapping" - set name = "Check Sim/Unsim Bounds" - set background = 1 - - // this/can/be/next/to = list(these) - var/list/acceptable_types=list( - /turf/simulated/wall = list( - /turf/simulated, - // Asteroid shit - /turf/unsimulated/mineral, - /turf/unsimulated/floor/airless, - /turf/unsimulated/floor/asteroid, - // Space is okay for walls - /turf/space - ), - /turf/simulated/shuttle/floor = list( - /turf/simulated/shuttle, - /turf/space - ), - /turf/simulated/shuttle/floor4 = list( - /turf/simulated/shuttle, - /turf/space - ), - /turf/simulated/floor/plating/airless = list( - /turf/simulated/floor/plating/airless, - /turf/simulated/floor/airless, - /turf/simulated/wall, - /turf/space - ), - /turf/simulated/floor/airless = list( - /turf/simulated/floor/airless, - /turf/simulated/floor/plating/airless, - /turf/simulated/wall, - /turf/space - ), - /turf/simulated/floor = list( - /turf/simulated/floor, - /turf/simulated/wall, - /turf/simulated/shuttle/wall - ), - ) - - // Actually a "wall" if we have this shit on the tile: - var/list/wallify=list( - /turf/simulated/wall, - /obj/structure/window, - /obj/structure/shuttle, - /obj/machinery/door - ) - - for(var/turf/T in turfs) - for(var/basetype in acceptable_types) - var/list/badtiles[0] - if(istype(T,basetype)) - for(var/atom/A in T) - if(is_type_in_list(A,wallify)) - basetype = /turf/simulated/wall - break - for(var/D in cardinal) - var/turf/AT = get_step(T,D) - if(!is_type_in_list(AT, acceptable_types[basetype])) - badtiles += AT.type - var/oldcolor = initial(T.color) - var/newcolor = oldcolor - if(badtiles.len>0) - message_admins("Tile [formatJumpTo(T)] (BT: [basetype]) is next to: [list2text(badtiles,", ")]") - newcolor="#ff0000" - if(newcolor!=oldcolor) - T.color=newcolor - break - - feedback_add_details("admin_verb","mSIM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -var/global/prevent_airgroup_regroup = 0 - -/* -/client/proc/break_all_air_groups() - set category = "Mapping" - set name = "Break All Airgroups" - - /*prevent_airgroup_regroup = 1 - for(var/datum/air_group/AG in air_master.air_groups) - AG.suspend_group_processing() - message_admins("[src.ckey] used 'Break All Airgroups'")*/ - -/client/proc/regroup_all_air_groups() - set category = "Mapping" - set name = "Regroup All Airgroups Attempt" - - to_chat(usr, "Proc disabled.") - - /*prevent_airgroup_regroup = 0 - for(var/datum/air_group/AG in air_master.air_groups) - AG.check_regroup() - message_admins("[src.ckey] used 'Regroup All Airgroups Attempt'")*/ - -/client/proc/kill_pipe_processing() - set category = "Mapping" - set name = "Kill pipe processing" - - to_chat(usr, "Proc disabled.") - - /*pipe_processing_killed = !pipe_processing_killed - if(pipe_processing_killed) - message_admins("[src.ckey] used 'kill pipe processing', stopping all pipe processing.") - else - message_admins("[src.ckey] used 'kill pipe processing', restoring all pipe processing.")*/ - -/client/proc/kill_air_processing() - set category = "Mapping" - set name = "Kill air processing" - - to_chat(usr, "Proc disabled.") - - /*air_processing_killed = !air_processing_killed - if(air_processing_killed) - message_admins("[src.ckey] used 'kill air processing', stopping all air processing.") - else - message_admins("[src.ckey] used 'kill air processing', restoring all air processing.")*/ -*/ -//This proc is intended to detect lag problems relating to communication procs -var/global/say_disabled = 0 -/* -/client/proc/disable_communication() - set category = "Mapping" - set name = "Disable all communication verbs" - - to_chat(usr, "Proc disabled.") - - /*say_disabled = !say_disabled - if(say_disabled) - message_admins("[src.ckey] used 'Disable all communication verbs', killing all communication methods.") - else - message_admins("[src.ckey] used 'Disable all communication verbs', restoring all communication methods.")*/ - -//This proc is intended to detect lag problems relating to movement -*/ -var/global/movement_disabled = 0 -var/global/movement_disabled_exception //This is the client that calls the proc, so he can continue to run around to gauge any change to lag. -/* -/client/proc/disable_movement() - set category = "Mapping" - set name = "Disable all movement" - - to_chat(usr, "Proc disabled.") - - /*movement_disabled = !movement_disabled - if(movement_disabled) - message_admins("[src.ckey] used 'Disable all movement', killing all movement.") - movement_disabled_exception = usr.ckey - else - message_admins("[src.ckey] used 'Disable all movement', restoring all movement.")*/ -*/ +//- Are all the floors with or without air, as they should be? (regular or airless) +//- Does the area have an APC? +//- Does the area have an Air Alarm? +//- Does the area have a Request Console? +//- Does the area have lights? +//- Does the area have a light switch? +//- Does the area have enough intercoms? +//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug) +//- Is the area connected to the scrubbers air loop? +//- Is the area connected to the vent air loop? (vent pumps) +//- Is everything wired properly? +//- Does the area have a fire alarm and firedoors? +//- Do all pod doors work properly? +//- Are accesses set properly on doors, pod buttons, etc. +//- Are all items placed properly? (not below vents, scrubbers, tables) +//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room? +//- Check for any misplaced or stacked piece of pipe (air and disposal) +//- Check for any misplaced or stacked piece of wire +//- Identify how hard it is to break into the area and where the weak points are +//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels. + +var/camera_range_display_status = 0 +var/intercom_range_display_status = 0 + +/obj/effect/debugging/camera_range + icon = 'icons/480x480.dmi' + icon_state = "25percent" + + New() + src.pixel_x = -224 + src.pixel_y = -224 + +/obj/effect/debugging/marker + icon = 'icons/turf/areas.dmi' + icon_state = "yellow" + +/obj/effect/debugging/marker/Move() + return 0 + +/client/proc/do_not_use_these() + set category = "Mapping" + set name = "-None of these are for ingame use!!" + + ..() + +/client/proc/camera_view() + set category = "Mapping" + set name = "Camera Range Display" + + if(camera_range_display_status) + camera_range_display_status = 0 + else + camera_range_display_status = 1 + + + + for(var/obj/effect/debugging/camera_range/C in world) + del(C) + + if(camera_range_display_status) + for(var/obj/machinery/camera/C in cameranet.cameras) + new/obj/effect/debugging/camera_range(C.loc) + feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + +/client/proc/sec_camera_report() + set category = "Mapping" + set name = "Camera Report" + + if(!master_controller) + alert(usr,"Master_controller not found.","Sec Camera Report") + return 0 + + var/list/obj/machinery/camera/CL = list() + + for(var/obj/machinery/camera/C in cameranet.cameras) + CL += C + + var/output = {"CAMERA ANOMALIES REPORT
    +The following anomalies have been detected. The ones in red need immediate attention: Some of those in black may be intentional.
      "} + + for(var/obj/machinery/camera/C1 in CL) + for(var/obj/machinery/camera/C2 in CL) + if(C1 != C2) + if(C1.c_tag == C2.c_tag) + output += "
    • c_tag match for sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) and \[[C2.x], [C2.y], [C2.z]\] ([C2.loc.loc]) - c_tag is [C1.c_tag]
    • " + if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y) + output += "
    • FULLY overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]
    • " + if(C1.loc == C2.loc) + output += "
    • overlapping sec. cameras at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Networks: [C1.network] and [C2.network]
    • " + var/turf/T = get_step(C1,turn(C1.dir,180)) + if(!T || !isturf(T) || !T.density ) + if(!(locate(/obj/structure/grille,T))) + var/window_check = 0 + for(var/obj/structure/window/W in T) + if (W.dir == turn(C1.dir,180) || W.is_fulltile() ) + window_check = 1 + break + if(!window_check) + output += "
    • Camera not connected to wall at \[[C1.x], [C1.y], [C1.z]\] ([C1.loc.loc]) Network: [C1.network]
    • " + + output += "
    " + usr << browse(output,"window=airreport;size=1000x500") + feedback_add_details("admin_verb","mCRP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/intercom_view() + set category = "Mapping" + set name = "Intercom Range Display" + + if (intercom_range_display_status) + intercom_range_display_status = FALSE + else + intercom_range_display_status = TRUE + + for (var/obj/effect/debugging/marker/M in world) + qdel(M) + + if (intercom_range_display_status) + for (var/obj/item/device/radio/intercom/I in world) + for (var/turf/T in view(I.canhear_range, I)) + new /obj/effect/debugging/marker(T) + + feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/enable_debug_verbs() + set category = "Debug" + set name = "Debug verbs" + + if(!check_rights(R_DEBUG)) return + + src.verbs += /client/proc/do_not_use_these //-errorage + src.verbs += /client/proc/camera_view //-errorage + src.verbs += /client/proc/sec_camera_report //-errorage + src.verbs += /client/proc/intercom_view //-errorage + src.verbs += /client/proc/air_status //Air things + src.verbs += /client/proc/Cell //More air things + src.verbs += /client/proc/pdiff //Antigriff testing - N3X + src.verbs += /client/proc/atmosscan //check plumbing + src.verbs += /client/proc/powerdebug //check power + src.verbs += /client/proc/count_objects_on_z_level + src.verbs += /client/proc/count_objects_all + src.verbs += /client/proc/cmd_assume_direct_control //-errorage + src.verbs += /client/proc/jump_to_dead_group + src.verbs += /client/proc/startSinglo + src.verbs += /client/proc/cheat_power // Because the above doesn't work off-station. Or at all, occasionally - N3X + src.verbs += /client/proc/setup_atmos // Laziness during atmos testing - N3X + src.verbs += /client/proc/ticklag //allows you to set the ticklag. + src.verbs += /client/proc/cmd_admin_grantfullaccess + src.verbs += /client/proc/kaboom + src.verbs += /client/proc/splash + src.verbs += /client/proc/cmd_admin_areatest + src.verbs += /client/proc/cmd_admin_rejuvenate + src.verbs += /datum/admins/proc/show_traitor_panel + src.verbs += /client/proc/print_jobban_old + src.verbs += /client/proc/print_jobban_old_filter + src.verbs += /client/proc/forceEvent + //src.verbs += /client/proc/break_all_air_groups + //src.verbs += /client/proc/regroup_all_air_groups + //src.verbs += /client/proc/kill_pipe_processing + //src.verbs += /client/proc/kill_air_processing + //src.verbs += /client/proc/disable_communication + //src.verbs += /client/proc/disable_movement + src.verbs += /client/proc/Zone_Info + src.verbs += /client/proc/Test_ZAS_Connection + src.verbs += /client/proc/SDQL2_query + src.verbs += /client/proc/check_sim_unsim + src.verbs += /client/proc/nanomapgen_DumpImage + src.verbs += /client/proc/nanomapgen_DumpImageAll + //src.verbs += /client/proc/cmd_admin_rejuvenate + + feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/count_objects_on_z_level() + set category = "Mapping" + set name = "Count Objects On Level" + + var/level = input("Which z-level?","Level?") as text + if(!level) return + var/num_level = text2num(level) + if(!num_level) return + if(!isnum(num_level)) return + + var/type_text = input("Which type path?","Path?") as text + if(!type_text) return + var/type_path = text2path(type_text) + if(!type_path) return + + var/count = 0 + + var/list/atom/atom_list = list() + + for(var/atom/A in world) + if(istype(A,type_path)) + var/atom/B = A + while(!(isturf(B.loc))) + if(B && B.loc) + B = B.loc + else + break + if(B) + if(B.z == num_level) + count++ + atom_list += A + /* + var/atom/temp_atom + for(var/i = 0; i <= (atom_list.len/10); i++) + var/line = "" + for(var/j = 1; j <= 10; j++) + if(i*10+j <= atom_list.len) + temp_atom = atom_list[i*10+j] + line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; " + to_chat(world, line)*/ + + to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level]") + feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/count_objects_all() + set background = 1 + set category = "Mapping" + set name = "Count Objects All" + + var/type_text = input("Which type path?","") as text + if(!type_text) return + var/type_path = text2path(type_text) + if(!type_path) return + + var/count = 0 + + for(var/atom/A in world) + if(istype(A,type_path)) + count++ + /* + var/atom/temp_atom + for(var/i = 0; i <= (atom_list.len/10); i++) + var/line = "" + for(var/j = 1; j <= 10; j++) + if(i*10+j <= atom_list.len) + temp_atom = atom_list[i*10+j] + line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; " + to_chat(world, line)*/ + + to_chat(usr, "There are [count] objects of type [type_path] in the game world") + feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/check_sim_unsim() + set category = "Mapping" + set name = "Check Sim/Unsim Bounds" + set background = 1 + + // this/can/be/next/to = list(these) + var/list/acceptable_types=list( + /turf/simulated/wall = list( + /turf/simulated, + // Asteroid shit + /turf/unsimulated/mineral, + /turf/unsimulated/floor/airless, + /turf/unsimulated/floor/asteroid, + // Space is okay for walls + /turf/space + ), + /turf/simulated/shuttle/floor = list( + /turf/simulated/shuttle, + /turf/space + ), + /turf/simulated/shuttle/floor4 = list( + /turf/simulated/shuttle, + /turf/space + ), + /turf/simulated/floor/plating/airless = list( + /turf/simulated/floor/plating/airless, + /turf/simulated/floor/airless, + /turf/simulated/wall, + /turf/space + ), + /turf/simulated/floor/airless = list( + /turf/simulated/floor/airless, + /turf/simulated/floor/plating/airless, + /turf/simulated/wall, + /turf/space + ), + /turf/simulated/floor = list( + /turf/simulated/floor, + /turf/simulated/wall, + /turf/simulated/shuttle/wall + ), + ) + + // Actually a "wall" if we have this shit on the tile: + var/list/wallify=list( + /turf/simulated/wall, + /obj/structure/window, + /obj/structure/shuttle, + /obj/machinery/door + ) + + for(var/turf/T in turfs) + for(var/basetype in acceptable_types) + var/list/badtiles[0] + if(istype(T,basetype)) + for(var/atom/A in T) + if(is_type_in_list(A,wallify)) + basetype = /turf/simulated/wall + break + for(var/D in cardinal) + var/turf/AT = get_step(T,D) + if(!is_type_in_list(AT, acceptable_types[basetype])) + badtiles += AT.type + var/oldcolor = initial(T.color) + var/newcolor = oldcolor + if(badtiles.len>0) + message_admins("Tile [formatJumpTo(T)] (BT: [basetype]) is next to: [list2text(badtiles,", ")]") + newcolor="#ff0000" + if(newcolor!=oldcolor) + T.color=newcolor + break + + feedback_add_details("admin_verb","mSIM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +var/global/prevent_airgroup_regroup = 0 + +/* +/client/proc/break_all_air_groups() + set category = "Mapping" + set name = "Break All Airgroups" + + /*prevent_airgroup_regroup = 1 + for(var/datum/air_group/AG in air_master.air_groups) + AG.suspend_group_processing() + message_admins("[src.ckey] used 'Break All Airgroups'")*/ + +/client/proc/regroup_all_air_groups() + set category = "Mapping" + set name = "Regroup All Airgroups Attempt" + + to_chat(usr, "Proc disabled.") + + /*prevent_airgroup_regroup = 0 + for(var/datum/air_group/AG in air_master.air_groups) + AG.check_regroup() + message_admins("[src.ckey] used 'Regroup All Airgroups Attempt'")*/ + +/client/proc/kill_pipe_processing() + set category = "Mapping" + set name = "Kill pipe processing" + + to_chat(usr, "Proc disabled.") + + /*pipe_processing_killed = !pipe_processing_killed + if(pipe_processing_killed) + message_admins("[src.ckey] used 'kill pipe processing', stopping all pipe processing.") + else + message_admins("[src.ckey] used 'kill pipe processing', restoring all pipe processing.")*/ + +/client/proc/kill_air_processing() + set category = "Mapping" + set name = "Kill air processing" + + to_chat(usr, "Proc disabled.") + + /*air_processing_killed = !air_processing_killed + if(air_processing_killed) + message_admins("[src.ckey] used 'kill air processing', stopping all air processing.") + else + message_admins("[src.ckey] used 'kill air processing', restoring all air processing.")*/ +*/ +//This proc is intended to detect lag problems relating to communication procs +var/global/say_disabled = 0 +/* +/client/proc/disable_communication() + set category = "Mapping" + set name = "Disable all communication verbs" + + to_chat(usr, "Proc disabled.") + + /*say_disabled = !say_disabled + if(say_disabled) + message_admins("[src.ckey] used 'Disable all communication verbs', killing all communication methods.") + else + message_admins("[src.ckey] used 'Disable all communication verbs', restoring all communication methods.")*/ + +//This proc is intended to detect lag problems relating to movement +*/ +var/global/movement_disabled = 0 +var/global/movement_disabled_exception //This is the client that calls the proc, so he can continue to run around to gauge any change to lag. +/* +/client/proc/disable_movement() + set category = "Mapping" + set name = "Disable all movement" + + to_chat(usr, "Proc disabled.") + + /*movement_disabled = !movement_disabled + if(movement_disabled) + message_admins("[src.ckey] used 'Disable all movement', killing all movement.") + movement_disabled_exception = usr.ckey + else + message_admins("[src.ckey] used 'Disable all movement', restoring all movement.")*/ +*/ diff --git a/code/modules/admin/verbs/massmodvar.dm b/code/modules/admin/verbs/massmodvar.dm index 943ecbfd1fb..0a3148672c7 100644 --- a/code/modules/admin/verbs/massmodvar.dm +++ b/code/modules/admin/verbs/massmodvar.dm @@ -1,412 +1,412 @@ -/client/proc/cmd_mass_modify_object_variables(atom/A, var/var_name) - set category = "Debug" - set name = "Mass Edit Variables" - set desc="(target) Edit all instances of a target item's variables" - - var/method = 0 //0 means strict type detection while 1 means this type and all subtypes (IE: /obj/item with this set to 1 will set it to ALL itms) - - if(!check_rights(R_VAREDIT)) return - - if(A && A.type) - if(typesof(A.type)) - switch(input("Strict object type detection?") as null|anything in list("Strictly this type","This type and subtypes", "Cancel")) - if("Strictly this type") - method = 0 - if("This type and subtypes") - method = 1 - if("Cancel") - return - if(null) - return - - src.massmodify_variables(A, var_name, method) - feedback_add_details("admin_verb","MEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/massmodify_variables(var/atom/O, var/var_name = "", var/method = 0) - if(!check_rights(R_VAREDIT)) return - - var/list/locked = list("vars", "key", "ckey", "client") - - if(holder && !(holder.rights & (R_PERMISSIONS))) - for(var/p in forbidden_varedit_object_types) - if( istype(O,p) ) +/client/proc/cmd_mass_modify_object_variables(atom/A, var/var_name) + set category = "Debug" + set name = "Mass Edit Variables" + set desc="(target) Edit all instances of a target item's variables" + + var/method = 0 //0 means strict type detection while 1 means this type and all subtypes (IE: /obj/item with this set to 1 will set it to ALL itms) + + if(!check_rights(R_VAREDIT)) return + + if(A && A.type) + if(typesof(A.type)) + switch(input("Strict object type detection?") as null|anything in list("Strictly this type","This type and subtypes", "Cancel")) + if("Strictly this type") + method = 0 + if("This type and subtypes") + method = 1 + if("Cancel") + return + if(null) + return + + src.massmodify_variables(A, var_name, method) + feedback_add_details("admin_verb","MEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/massmodify_variables(var/atom/O, var/var_name = "", var/method = 0) + if(!check_rights(R_VAREDIT)) return + + var/list/locked = list("vars", "key", "ckey", "client") + + if(holder && !(holder.rights & (R_PERMISSIONS))) + for(var/p in forbidden_varedit_object_types) + if( istype(O,p) ) to_chat(usr, "It is forbidden to edit this object's variables.") - return - - var/list/names = list() - for (var/V in O.vars) - names += V - - names = sortList(names) - - var/variable = "" - - if(!var_name) - variable = input("Which var?","Var") as null|anything in names - else - variable = var_name - - if(!variable) return - var/default - var/var_value = O.vars[variable] - var/dir - - if(variable == "holder" || (variable in locked)) - if(!check_rights(R_DEBUG)) return - - if(isnull(var_value)) + return + + var/list/names = list() + for (var/V in O.vars) + names += V + + names = sortList(names) + + var/variable = "" + + if(!var_name) + variable = input("Which var?","Var") as null|anything in names + else + variable = var_name + + if(!variable) return + var/default + var/var_value = O.vars[variable] + var/dir + + if(variable == "holder" || (variable in locked)) + if(!check_rights(R_DEBUG)) return + + if(isnull(var_value)) to_chat(usr, "Unable to determine variable type.") - - else if(isnum(var_value)) + + else if(isnum(var_value)) to_chat(usr, "Variable appears to be NUM.") - default = "num" - dir = 1 - - else if(istext(var_value)) + default = "num" + dir = 1 + + else if(istext(var_value)) to_chat(usr, "Variable appears to be TEXT.") - default = "text" - - else if(isloc(var_value)) + default = "text" + + else if(isloc(var_value)) to_chat(usr, "Variable appears to be REFERENCE.") - default = "reference" - - else if(isicon(var_value)) + default = "reference" + + else if(isicon(var_value)) to_chat(usr, "Variable appears to be ICON.") - var_value = "\icon[var_value]" - default = "icon" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) + var_value = "\icon[var_value]" + default = "icon" + + else if(istype(var_value,/atom) || istype(var_value,/datum)) to_chat(usr, "Variable appears to be TYPE.") - default = "type" - - else if(istype(var_value,/list)) + default = "type" + + else if(istype(var_value,/list)) to_chat(usr, "Variable appears to be LIST.") - default = "list" - - else if(istype(var_value,/client)) + default = "list" + + else if(istype(var_value,/client)) to_chat(usr, "Variable appears to be CLIENT.") - default = "cancel" - - else + default = "cancel" + + else to_chat(usr, "Variable appears to be FILE.") - default = "file" - + default = "file" + to_chat(usr, "Variable contains: [var_value]") - if(dir) - switch(var_value) - if(1) - dir = "NORTH" - if(2) - dir = "SOUTH" - if(4) - dir = "EAST" - if(8) - dir = "WEST" - if(5) - dir = "NORTHEAST" - if(6) - dir = "SOUTHEAST" - if(9) - dir = "NORTHWEST" - if(10) - dir = "SOUTHWEST" - else - dir = null - if(dir) + if(dir) + switch(var_value) + if(1) + dir = "NORTH" + if(2) + dir = "SOUTH" + if(4) + dir = "EAST" + if(8) + dir = "WEST" + if(5) + dir = "NORTHEAST" + if(6) + dir = "SOUTHEAST" + if(9) + dir = "NORTHWEST" + if(10) + dir = "SOUTHWEST" + else + dir = null + if(dir) to_chat(usr, "If a direction, direction is: [dir]") - - var/class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","icon","file","edit referenced object","restore to default") - - if(!class) - return - - var/original_name - - if (!istype(O, /atom)) - original_name = "\ref[O] ([O])" - else - original_name = O:name - - switch(class) - - if("restore to default") - O.vars[variable] = initial(O.vars[variable]) - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - var/new_value = input("Enter new text:","Text",O.vars[variable]) as text|null - if(new_value == null) return - - if(variable == "light_color") - O.set_light(l_color = new_value) - else - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - if(variable == "light_color") - M.set_light(l_color = new_value) - else - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - if(variable == "light_color") - A.set_light(l_color = new_value) - else - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - if(variable == "light_color") - A.set_light(l_color = new_value) - else - A.vars[variable] = O.vars[variable] - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - if(variable == "light_color") - M.set_light(l_color = new_value) - else - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - if(variable == "light_color") - A.set_light(l_color = new_value) - else - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - if(variable == "light_color") - A.set_light(l_color = new_value) - else - A.vars[variable] = O.vars[variable] - - if("num") - var/new_value = input("Enter new number:","Num",\ - O.vars[variable]) as num|null - if(new_value == null) return - - if(variable=="light_range") - O.set_light(new_value) - else if(variable == "light_power") - O.set_light(l_power = new_value) - else - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - if(variable=="light_range") - M.set_light(new_value) - else if(variable == "light_power") - M.set_light(l_power = new_value) - else - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - if(variable=="light_range") - A.set_light(new_value) - else if(variable == "light_power") - A.set_light(l_power = new_value) - else - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - if(variable=="light_range") - A.set_light(new_value) - else if(variable == "light_power") - A.set_light(l_power = new_value) - else - A.vars[variable] = O.vars[variable] - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - if(variable=="light_range") - M.set_light(new_value) - else if(variable == "light_power") - M.set_light(l_power = new_value) - else - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - if(variable=="light_range") - A.set_light(new_value) - else if(variable == "light_power") - A.set_light(l_power = new_value) - else - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - if(variable=="light_range") - A.set_light(new_value) - else if(variable == "light_power") - A.set_light(l_power = new_value) - else - A.vars[variable] = O.vars[variable] - - if("type") - var/new_value - new_value = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) - if(new_value == null) return - O.vars[variable] = new_value - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("file") - var/new_value = input("Pick file:","File",O.vars[variable]) as null|file - if(new_value == null) return - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O.type, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O.type, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O.type, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O.type, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("icon") - var/new_value = input("Pick icon:","Icon",O.vars[variable]) as null|icon - if(new_value == null) return - O.vars[variable] = new_value - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]") + + var/class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", + "num","type","icon","file","edit referenced object","restore to default") + + if(!class) + return + + var/original_name + + if (!istype(O, /atom)) + original_name = "\ref[O] ([O])" + else + original_name = O:name + + switch(class) + + if("restore to default") + O.vars[variable] = initial(O.vars[variable]) + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if ( istype(M , O.type) ) + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in world) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if (M.type == O.type) + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + if("edit referenced object") + return .(O.vars[variable]) + + if("text") + var/new_value = input("Enter new text:","Text",O.vars[variable]) as text|null + if(new_value == null) return + + if(variable == "light_color") + O.set_light(l_color = new_value) + else + O.vars[variable] = new_value + + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if ( istype(M , O.type) ) + if(variable == "light_color") + M.set_light(l_color = new_value) + else + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if ( istype(A , O.type) ) + if(variable == "light_color") + A.set_light(l_color = new_value) + else + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if ( istype(A , O.type) ) + if(variable == "light_color") + A.set_light(l_color = new_value) + else + A.vars[variable] = O.vars[variable] + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if (M.type == O.type) + if(variable == "light_color") + M.set_light(l_color = new_value) + else + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if (A.type == O.type) + if(variable == "light_color") + A.set_light(l_color = new_value) + else + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if (A.type == O.type) + if(variable == "light_color") + A.set_light(l_color = new_value) + else + A.vars[variable] = O.vars[variable] + + if("num") + var/new_value = input("Enter new number:","Num",\ + O.vars[variable]) as num|null + if(new_value == null) return + + if(variable=="light_range") + O.set_light(new_value) + else if(variable == "light_power") + O.set_light(l_power = new_value) + else + O.vars[variable] = new_value + + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if ( istype(M , O.type) ) + if(variable=="light_range") + M.set_light(new_value) + else if(variable == "light_power") + M.set_light(l_power = new_value) + else + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if ( istype(A , O.type) ) + if(variable=="light_range") + A.set_light(new_value) + else if(variable == "light_power") + A.set_light(l_power = new_value) + else + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if ( istype(A , O.type) ) + if(variable=="light_range") + A.set_light(new_value) + else if(variable == "light_power") + A.set_light(l_power = new_value) + else + A.vars[variable] = O.vars[variable] + + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if (M.type == O.type) + if(variable=="light_range") + M.set_light(new_value) + else if(variable == "light_power") + M.set_light(l_power = new_value) + else + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if (A.type == O.type) + if(variable=="light_range") + A.set_light(new_value) + else if(variable == "light_power") + A.set_light(l_power = new_value) + else + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if (A.type == O.type) + if(variable=="light_range") + A.set_light(new_value) + else if(variable == "light_power") + A.set_light(l_power = new_value) + else + A.vars[variable] = O.vars[variable] + + if("type") + var/new_value + new_value = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) + if(new_value == null) return + O.vars[variable] = new_value + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if ( istype(M , O.type) ) + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if (M.type == O.type) + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + if("file") + var/new_value = input("Pick file:","File",O.vars[variable]) as null|file + if(new_value == null) return + O.vars[variable] = new_value + + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if ( istype(M , O.type) ) + M.vars[variable] = O.vars[variable] + + else if(istype(O.type, /obj)) + for(var/obj/A in world) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + + else if(istype(O.type, /turf)) + for(var/turf/A in turfs) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if (M.type == O.type) + M.vars[variable] = O.vars[variable] + + else if(istype(O.type, /obj)) + for(var/obj/A in world) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + else if(istype(O.type, /turf)) + for(var/turf/A in turfs) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + if("icon") + var/new_value = input("Pick icon:","Icon",O.vars[variable]) as null|icon + if(new_value == null) return + O.vars[variable] = new_value + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if ( istype(M , O.type) ) + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if ( istype(A , O.type) ) + A.vars[variable] = O.vars[variable] + + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if (M.type == O.type) + M.vars[variable] = O.vars[variable] + + else if(istype(O, /obj)) + for(var/obj/A in world) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + else if(istype(O, /turf)) + for(var/turf/A in turfs) + if (A.type == O.type) + A.vars[variable] = O.vars[variable] + + log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]") message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]", 1) \ No newline at end of file diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index 8642aa1969c..4a94cff4030 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -1,569 +1,569 @@ -var/list/forbidden_varedit_object_types = list( - /datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea. - /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering - /datum/feedback_variable, //Prevents people messing with feedback gathering - /datum/configuration, //prevents people from fucking with logging. - ) - -/* -/client/proc/cmd_modify_object_variables(obj/O as obj|mob|turf|area in world) - set category = "Debug" - set name = "Edit Variables" - set desc="(target) Edit a target item's variables" - src.modify_variables(O) - feedback_add_details("admin_verb","EDITV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -*/ - -/client/proc/cmd_modify_ticker_variables() - set category = "Debug" - set name = "Edit Ticker Variables" - - if (ticker == null) +var/list/forbidden_varedit_object_types = list( + /datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea. + /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering + /datum/feedback_variable, //Prevents people messing with feedback gathering + /datum/configuration, //prevents people from fucking with logging. + ) + +/* +/client/proc/cmd_modify_object_variables(obj/O as obj|mob|turf|area in world) + set category = "Debug" + set name = "Edit Variables" + set desc="(target) Edit a target item's variables" + src.modify_variables(O) + feedback_add_details("admin_verb","EDITV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +*/ + +/client/proc/cmd_modify_ticker_variables() + set category = "Debug" + set name = "Edit Ticker Variables" + + if (ticker == null) to_chat(src, "Game hasn't started yet.") - else - src.modify_variables(ticker) - feedback_add_details("admin_verb","ETV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/mod_list_add_ass() //haha - - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/var_value = null - - switch(class) - - if("text") - var_value = input("Enter new text:","Text") as null|message - - if("num") - var_value = input("Enter new number:","Num") as null|num - - if("type") - var_value = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - - if("reference") - var_value = input("Select reference:","Reference") as null|mob|obj|turf|area in world - - if("mob reference") - var_value = input("Select reference:","Reference") as null|mob in world - - if("file") - var_value = input("Pick file:","File") as null|file - - if("icon") - var_value = input("Pick icon:","Icon") as null|icon - - if("marked datum") - var_value = holder.marked_datum - - if(!var_value) return - - return var_value - - -/client/proc/mod_list_add(var/list/L) - - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/var_value = null - - switch(class) - - if("text") - var_value = input("Enter new text:","Text") as message - - if("num") - var_value = input("Enter new number:","Num") as num - - if("type") - var_value = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - - if("reference") - var_value = input("Select reference:","Reference") as mob|obj|turf|area in world - - if("mob reference") - var_value = input("Select reference:","Reference") as mob in world - - if("file") - var_value = input("Pick file:","File") as file - - if("icon") - var_value = input("Pick icon:","Icon") as icon - - if("marked datum") - var_value = holder.marked_datum - - if(!var_value) return - - switch(alert("Would you like to associate a var with the list entry?",,"Yes","No")) - if("Yes") - L += var_value - L[var_value] = mod_list_add_ass() //haha - if("No") - L += var_value - -/client/proc/mod_list(var/list/L) - if(!check_rights(R_VAREDIT)) return - - if(!istype(L,/list)) - if(alert("Make a new list?", "Not a List.", "Yes", "No") == "No") - return - else - L = list() - - var/list/locked = list("vars", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine", "poo", "icon", "icon_state") - var/list/names = sortList(L) - - var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" - - if(variable == "(ADD VAR)") - mod_list_add(L) - return - - if(!variable) - return - - var/default - - var/dir - - if(variable in locked) - if(!check_rights(R_DEBUG)) return - - if(isnull(variable)) + else + src.modify_variables(ticker) + feedback_add_details("admin_verb","ETV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/mod_list_add_ass() //haha + + + var/class = "text" + if(src.holder && src.holder.marked_datum) + class = input("What kind of variable?","Variable Type") as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") + else + class = input("What kind of variable?","Variable Type") as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") + + if(!class) + return + + if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") + class = "marked datum" + + var/var_value = null + + switch(class) + + if("text") + var_value = input("Enter new text:","Text") as null|message + + if("num") + var_value = input("Enter new number:","Num") as null|num + + if("type") + var_value = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) + + if("reference") + var_value = input("Select reference:","Reference") as null|mob|obj|turf|area in world + + if("mob reference") + var_value = input("Select reference:","Reference") as null|mob in world + + if("file") + var_value = input("Pick file:","File") as null|file + + if("icon") + var_value = input("Pick icon:","Icon") as null|icon + + if("marked datum") + var_value = holder.marked_datum + + if(!var_value) return + + return var_value + + +/client/proc/mod_list_add(var/list/L) + + + var/class = "text" + if(src.holder && src.holder.marked_datum) + class = input("What kind of variable?","Variable Type") as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") + else + class = input("What kind of variable?","Variable Type") as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") + + if(!class) + return + + if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") + class = "marked datum" + + var/var_value = null + + switch(class) + + if("text") + var_value = input("Enter new text:","Text") as message + + if("num") + var_value = input("Enter new number:","Num") as num + + if("type") + var_value = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) + + if("reference") + var_value = input("Select reference:","Reference") as mob|obj|turf|area in world + + if("mob reference") + var_value = input("Select reference:","Reference") as mob in world + + if("file") + var_value = input("Pick file:","File") as file + + if("icon") + var_value = input("Pick icon:","Icon") as icon + + if("marked datum") + var_value = holder.marked_datum + + if(!var_value) return + + switch(alert("Would you like to associate a var with the list entry?",,"Yes","No")) + if("Yes") + L += var_value + L[var_value] = mod_list_add_ass() //haha + if("No") + L += var_value + +/client/proc/mod_list(var/list/L) + if(!check_rights(R_VAREDIT)) return + + if(!istype(L,/list)) + if(alert("Make a new list?", "Not a List.", "Yes", "No") == "No") + return + else + L = list() + + var/list/locked = list("vars", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "viruses", "cuffed", "ka", "last_eaten", "urine", "poo", "icon", "icon_state") + var/list/names = sortList(L) + + var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" + + if(variable == "(ADD VAR)") + mod_list_add(L) + return + + if(!variable) + return + + var/default + + var/dir + + if(variable in locked) + if(!check_rights(R_DEBUG)) return + + if(isnull(variable)) to_chat(usr, "Unable to determine variable type.") - - else if(isnum(variable)) + + else if(isnum(variable)) to_chat(usr, "Variable appears to be NUM.") - default = "num" - dir = 1 - - else if(istext(variable)) + default = "num" + dir = 1 + + else if(istext(variable)) to_chat(usr, "Variable appears to be TEXT.") - default = "text" - - else if(isloc(variable)) + default = "text" + + else if(isloc(variable)) to_chat(usr, "Variable appears to be REFERENCE.") - default = "reference" - - else if(isicon(variable)) + default = "reference" + + else if(isicon(variable)) to_chat(usr, "Variable appears to be ICON.") - variable = "\icon[variable]" - default = "icon" - - else if(istype(variable,/atom) || istype(variable,/datum)) + variable = "\icon[variable]" + default = "icon" + + else if(istype(variable,/atom) || istype(variable,/datum)) to_chat(usr, "Variable appears to be TYPE.") - default = "type" - - else if(istype(variable,/list)) + default = "type" + + else if(istype(variable,/list)) to_chat(usr, "Variable appears to be LIST.") - default = "list" - - else if(istype(variable,/client)) + default = "list" + + else if(istype(variable,/client)) to_chat(usr, "Variable appears to be CLIENT.") - default = "cancel" - - else + default = "cancel" + + else to_chat(usr, "Variable appears to be FILE.") - default = "file" - + default = "file" + to_chat(usr, "Variable contains: [variable]") - if(dir) - switch(variable) - if(1) - dir = "NORTH" - if(2) - dir = "SOUTH" - if(4) - dir = "EAST" - if(8) - dir = "WEST" - if(5) - dir = "NORTHEAST" - if(6) - dir = "SOUTHEAST" - if(9) - dir = "NORTHWEST" - if(10) - dir = "SOUTHWEST" - else - dir = null - - if(dir) + if(dir) + switch(variable) + if(1) + dir = "NORTH" + if(2) + dir = "SOUTH" + if(4) + dir = "EAST" + if(8) + dir = "WEST" + if(5) + dir = "NORTHEAST" + if(6) + dir = "SOUTHEAST" + if(9) + dir = "NORTHWEST" + if(10) + dir = "SOUTHWEST" + else + dir = null + + if(dir) to_chat(usr, "If a direction, direction is: [dir]") - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST") - else - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "DELETE FROM LIST") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. - - if("list") - mod_list(variable) - - if("restore to default") - L[L.Find(variable)]=initial(variable) - - if("edit referenced object") - modify_variables(variable) - - if("DELETE FROM LIST") - L -= variable - return - - if("text") - var/thing = L["[variable]"] - var/newText = input("Enter new text:","Text") as null|message - if(!newText) - return - if(!isnull(thing)) - L["[variable]"] = newText - else - L[L.Find(variable)] = newText - - if("num") - var/thing = L["[variable]"] - var/newNum = input("Enter new number:","Num") as null|num - if(!newNum) - return - if(!isnull(thing)) - L["[variable]"] = newNum - else - L[L.Find(variable)] = newNum - - if("type") - var/thing = L["[variable]"] - var/newType = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - if(!isnull(thing)) - L["[variable]"] = newType - else - L[L.Find(variable)] = newType - - if("reference") - var/thing = L["[variable]"] - var/newRef = input("Select reference:","Reference") as null|mob|obj|turf|area in world - if(!newRef) - return - if(!isnull(thing)) - L["[variable]"] = newRef - else - L[L.Find(variable)] = newRef - - if("mob reference") - var/thing = L["[variable]"] - var/newMob = input("Select reference:","Reference") as null|mob in world - if(!newMob) - return - if(!isnull(thing)) - L["[variable]"] = newMob - else - L[L.Find(variable)] = newMob - - if("file") - var/thing = L["[variable]"] - var/newFile = input("Pick file:","File") as file - if(!isnull(thing)) - L["[variable]"] = newFile - else - L[L.Find(variable)] = newFile - - if("icon") - var/thing = L["[variable]"] - var/newIcon = input("Pick icon:","Icon") as icon - if(!isnull(thing)) - L["[variable]"] = newIcon - else - L[L.Find(variable)] = newIcon - - if("marked datum") - var/thing = L["[variable]"] - var/newThing = holder.marked_datum - if(!isnull(thing)) - L["[variable]"] = newThing - else - L[L.Find(variable)] = newThing - - -/client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0) - if(!check_rights(R_VAREDIT)) return - - var/list/locked = list("vars", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "cuffed", "ka", "last_eaten", "icon", "icon_state", "mutantrace") - - if(holder && !(holder.rights & (R_PERMISSIONS))) - for(var/p in forbidden_varedit_object_types) - if( istype(O,p) ) + + var/class = "text" + if(src.holder && src.holder.marked_datum) + class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST") + else + class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "DELETE FROM LIST") + + if(!class) + return + + if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") + class = "marked datum" + + switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. + + if("list") + mod_list(variable) + + if("restore to default") + L[L.Find(variable)]=initial(variable) + + if("edit referenced object") + modify_variables(variable) + + if("DELETE FROM LIST") + L -= variable + return + + if("text") + var/thing = L["[variable]"] + var/newText = input("Enter new text:","Text") as null|message + if(!newText) + return + if(!isnull(thing)) + L["[variable]"] = newText + else + L[L.Find(variable)] = newText + + if("num") + var/thing = L["[variable]"] + var/newNum = input("Enter new number:","Num") as null|num + if(!newNum) + return + if(!isnull(thing)) + L["[variable]"] = newNum + else + L[L.Find(variable)] = newNum + + if("type") + var/thing = L["[variable]"] + var/newType = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) + if(!isnull(thing)) + L["[variable]"] = newType + else + L[L.Find(variable)] = newType + + if("reference") + var/thing = L["[variable]"] + var/newRef = input("Select reference:","Reference") as null|mob|obj|turf|area in world + if(!newRef) + return + if(!isnull(thing)) + L["[variable]"] = newRef + else + L[L.Find(variable)] = newRef + + if("mob reference") + var/thing = L["[variable]"] + var/newMob = input("Select reference:","Reference") as null|mob in world + if(!newMob) + return + if(!isnull(thing)) + L["[variable]"] = newMob + else + L[L.Find(variable)] = newMob + + if("file") + var/thing = L["[variable]"] + var/newFile = input("Pick file:","File") as file + if(!isnull(thing)) + L["[variable]"] = newFile + else + L[L.Find(variable)] = newFile + + if("icon") + var/thing = L["[variable]"] + var/newIcon = input("Pick icon:","Icon") as icon + if(!isnull(thing)) + L["[variable]"] = newIcon + else + L[L.Find(variable)] = newIcon + + if("marked datum") + var/thing = L["[variable]"] + var/newThing = holder.marked_datum + if(!isnull(thing)) + L["[variable]"] = newThing + else + L[L.Find(variable)] = newThing + + +/client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0) + if(!check_rights(R_VAREDIT)) return + + var/list/locked = list("vars", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "cuffed", "ka", "last_eaten", "icon", "icon_state", "mutantrace") + + if(holder && !(holder.rights & (R_PERMISSIONS))) + for(var/p in forbidden_varedit_object_types) + if( istype(O,p) ) to_chat(usr, "It is forbidden to edit this object's variables.") - return - - var/class - var/variable - var/var_value - - if(param_var_name) - if(!param_var_name in O.vars) + return + + var/class + var/variable + var/var_value + + if(param_var_name) + if(!param_var_name in O.vars) to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this atom ([O])") - return - - if(param_var_name == "holder" || (param_var_name in locked)) - if(!check_rights(R_DEBUG)) return - - variable = param_var_name - - var_value = O.vars[variable] - - if(autodetect_class) - if(isnull(var_value)) + return + + if(param_var_name == "holder" || (param_var_name in locked)) + if(!check_rights(R_DEBUG)) return + + variable = param_var_name + + var_value = O.vars[variable] + + if(autodetect_class) + if(isnull(var_value)) to_chat(usr, "Unable to determine variable type.") - class = null - autodetect_class = null - else if(isnum(var_value)) + class = null + autodetect_class = null + else if(isnum(var_value)) to_chat(usr, "Variable appears to be NUM.") - class = "num" - dir = 1 - - else if(istext(var_value)) + class = "num" + dir = 1 + + else if(istext(var_value)) to_chat(usr, "Variable appears to be TEXT.") - class = "text" - - else if(isloc(var_value)) + class = "text" + + else if(isloc(var_value)) to_chat(usr, "Variable appears to be REFERENCE.") - class = "reference" - - else if(isicon(var_value)) + class = "reference" + + else if(isicon(var_value)) to_chat(usr, "Variable appears to be ICON.") - var_value = "\icon[var_value]" - class = "icon" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) + var_value = "\icon[var_value]" + class = "icon" + + else if(istype(var_value,/atom) || istype(var_value,/datum)) to_chat(usr, "Variable appears to be TYPE.") - class = "type" - - else if(istype(var_value,/list)) + class = "type" + + else if(istype(var_value,/list)) to_chat(usr, "Variable appears to be LIST.") - class = "list" - - else if(istype(var_value,/client)) + class = "list" + + else if(istype(var_value,/client)) to_chat(usr, "Variable appears to be CLIENT.") - class = "cancel" - - else + class = "cancel" + + else to_chat(usr, "Variable appears to be FILE.") - class = "file" - - else - - var/list/names = list() - for (var/V in O.vars) - names += V - - names = sortList(names) - - variable = input("Which var?","Var") as null|anything in names - if(!variable) return - var_value = O.vars[variable] - - if(variable == "holder" || (variable in locked)) - if(!check_rights(R_DEBUG)) return - - if(!autodetect_class) - - var/dir - var/default - if(isnull(var_value)) + class = "file" + + else + + var/list/names = list() + for (var/V in O.vars) + names += V + + names = sortList(names) + + variable = input("Which var?","Var") as null|anything in names + if(!variable) return + var_value = O.vars[variable] + + if(variable == "holder" || (variable in locked)) + if(!check_rights(R_DEBUG)) return + + if(!autodetect_class) + + var/dir + var/default + if(isnull(var_value)) to_chat(usr, "Unable to determine variable type.") - - else if(isnum(var_value)) + + else if(isnum(var_value)) to_chat(usr, "Variable appears to be NUM.") - default = "num" - dir = 1 - - else if(istext(var_value)) + default = "num" + dir = 1 + + else if(istext(var_value)) to_chat(usr, "Variable appears to be TEXT.") - default = "text" - - else if(isloc(var_value)) + default = "text" + + else if(isloc(var_value)) to_chat(usr, "Variable appears to be REFERENCE.") - default = "reference" - - else if(isicon(var_value)) + default = "reference" + + else if(isicon(var_value)) to_chat(usr, "Variable appears to be ICON.") - var_value = "\icon[var_value]" - default = "icon" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) + var_value = "\icon[var_value]" + default = "icon" + + else if(istype(var_value,/atom) || istype(var_value,/datum)) to_chat(usr, "Variable appears to be TYPE.") - default = "type" - - else if(istype(var_value,/list)) + default = "type" + + else if(istype(var_value,/list)) to_chat(usr, "Variable appears to be LIST.") - default = "list" - - else if(istype(var_value,/client)) + default = "list" + + else if(istype(var_value,/client)) to_chat(usr, "Variable appears to be CLIENT.") - default = "cancel" - - else + default = "cancel" + + else to_chat(usr, "Variable appears to be FILE.") - default = "file" - + default = "file" + to_chat(usr, "Variable contains: [var_value]") - if(dir) - switch(var_value) - if(1) - dir = "NORTH" - if(2) - dir = "SOUTH" - if(4) - dir = "EAST" - if(8) - dir = "WEST" - if(5) - dir = "NORTHEAST" - if(6) - dir = "SOUTHEAST" - if(9) - dir = "NORTHWEST" - if(10) - dir = "SOUTHWEST" - else - dir = null - if(dir) + if(dir) + switch(var_value) + if(1) + dir = "NORTH" + if(2) + dir = "SOUTH" + if(4) + dir = "EAST" + if(8) + dir = "WEST" + if(5) + dir = "NORTHEAST" + if(6) + dir = "SOUTHEAST" + if(9) + dir = "NORTHWEST" + if(10) + dir = "SOUTHWEST" + else + dir = null + if(dir) to_chat(usr, "If a direction, direction is: [dir]") - - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") - - if(!class) - return - - var/original_name - - if (!istype(O, /atom)) - original_name = "\ref[O] ([O])" - else - original_name = O:name - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - switch(class) - - if("list") - mod_list(O.vars[variable]) - return - - if("restore to default") - O.vars[variable] = initial(O.vars[variable]) - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - if(variable == "light_color") - var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|message - if(var_new==null) return - O.set_light(l_color = var_new) - else - var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|message - if(var_new==null) return - O.vars[variable] = var_new - - if("num") - if(variable=="light_range") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - O.set_light(var_new) - - else if(variable=="light_power") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - O.set_light(l_power = var_new) - - else if(variable=="stat") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - if((O.vars[variable] == 2) && (var_new < 2))//Bringing the dead back to life - if(ismob(O)) - var/mob/M = O - M.resurrect() - if((O.vars[variable] < 2) && (var_new == 2))//Kill he - living_mob_list -= O - dead_mob_list += O - O.vars[variable] = var_new - else - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new==null) return - O.vars[variable] = var_new - - if("type") - var/var_new = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) - if(var_new==null) return - O.vars[variable] = var_new - - if("reference") - var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob|obj|turf|area in world - if(var_new==null) return - O.vars[variable] = var_new - - if("mob reference") - var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob in world - if(var_new==null) return - O.vars[variable] = var_new - - if("file") - var/var_new = input("Pick file:","File",O.vars[variable]) as null|file - if(var_new==null) return - O.vars[variable] = var_new - - if("icon") - var/var_new = input("Pick icon:","Icon",O.vars[variable]) as null|icon - if(var_new==null) return - O.vars[variable] = var_new - - if("marked datum") - O.vars[variable] = holder.marked_datum - - world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" - log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]", 1) - + + if(src.holder && src.holder.marked_datum) + class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") + else + class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", + "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") + + if(!class) + return + + var/original_name + + if (!istype(O, /atom)) + original_name = "\ref[O] ([O])" + else + original_name = O:name + + if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") + class = "marked datum" + + switch(class) + + if("list") + mod_list(O.vars[variable]) + return + + if("restore to default") + O.vars[variable] = initial(O.vars[variable]) + + if("edit referenced object") + return .(O.vars[variable]) + + if("text") + if(variable == "light_color") + var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|message + if(var_new==null) return + O.set_light(l_color = var_new) + else + var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|message + if(var_new==null) return + O.vars[variable] = var_new + + if("num") + if(variable=="light_range") + var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num + if(var_new == null) return + O.set_light(var_new) + + else if(variable=="light_power") + var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num + if(var_new == null) return + O.set_light(l_power = var_new) + + else if(variable=="stat") + var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num + if(var_new == null) return + if((O.vars[variable] == 2) && (var_new < 2))//Bringing the dead back to life + if(ismob(O)) + var/mob/M = O + M.resurrect() + if((O.vars[variable] < 2) && (var_new == 2))//Kill he + living_mob_list -= O + dead_mob_list += O + O.vars[variable] = var_new + else + var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num + if(var_new==null) return + O.vars[variable] = var_new + + if("type") + var/var_new = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) + if(var_new==null) return + O.vars[variable] = var_new + + if("reference") + var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob|obj|turf|area in world + if(var_new==null) return + O.vars[variable] = var_new + + if("mob reference") + var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob in world + if(var_new==null) return + O.vars[variable] = var_new + + if("file") + var/var_new = input("Pick file:","File",O.vars[variable]) as null|file + if(var_new==null) return + O.vars[variable] = var_new + + if("icon") + var/var_new = input("Pick icon:","Icon",O.vars[variable]) as null|icon + if(var_new==null) return + O.vars[variable] = var_new + + if("marked datum") + O.vars[variable] = holder.marked_datum + + world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" + log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]") + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]", 1) + diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 621f670d3a2..97ebebec784 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -1,475 +1,475 @@ -client/proc/one_click_antag() - set name = "Create Antagonist" - set desc = "Auto-create an antagonist of your choice" - set category = "Admin" - if(holder) - holder.one_click_antag() - return - - -/datum/admins/proc/one_click_antag() - - - var/dat = {"One-click Antagonist
    - Make Traitors
    - Make Changlings
    - Make Revs
    - Make Cult
    - Make Malf AI
    - Make Wizard (Requires Ghosts)
    - Make Vox Raiders (Requires Ghosts)
    - Make Nuke Team (Requires Ghosts)
    - Make Aliens (Requires Ghosts)
    - Make Deathsquad (Syndicate) (Requires Ghosts)
    - "} - - usr << browse(dat, "window=oneclickantag;size=400x400") - return - - -/datum/admins/proc/makeMalfAImode() - - - var/list/mob/living/silicon/AIs = list() - var/mob/living/silicon/malfAI = null - var/datum/mind/themind = null - - for(var/mob/living/silicon/ai/ai in player_list) - if(ai.client) - AIs += ai - - if(AIs.len) - malfAI = pick(AIs) - - if(malfAI) - themind = malfAI.mind - themind.make_AI_Malf() - return 1 - - return 0 - - -/datum/admins/proc/makeTraitors() - var/datum/game_mode/traitor/temp = new - - if(config.protect_roles_from_antagonist) - temp.restricted_jobs += temp.protected_jobs - - var/list/mob/living/carbon/human/candidates = list() - - for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.desires_role(ROLE_TRAITOR)) - if(!applicant.stat) - if(applicant.mind) - if (!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if (candidates.len) - candidates = shuffle(candidates) - - var/mob/living/carbon/human/candidate - - for (var/i = 1 to min(candidates.len, 3)) - candidate = pick_n_take(candidates) - - if (candidate) - var/datum/mind/candidate_mind = candidate.mind - - if (candidate_mind) - if (candidate_mind.make_traitor()) - log_admin("[key_name(owner)] has traitor'ed [key_name(candidate)] via create antagonist verb.") - - return 1 - - return 0 - - -/datum/admins/proc/makeChanglings() - - - var/datum/game_mode/changeling/temp = new - if(config.protect_roles_from_antagonist) - temp.restricted_jobs += temp.protected_jobs - - var/list/mob/living/carbon/human/candidates = list() - var/mob/living/carbon/human/H = null - - for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.desires_role(ROLE_CHANGELING)) - if(!applicant.stat) - if(applicant.mind) - if (!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "changeling") && !jobban_isbanned(applicant, "Syndicate")) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if(candidates.len) - var/numChanglings = min(candidates.len, 3) - - for(var/i = 0, iOne-click Antagonist
    + Make Traitors
    + Make Changlings
    + Make Revs
    + Make Cult
    + Make Malf AI
    + Make Wizard (Requires Ghosts)
    + Make Vox Raiders (Requires Ghosts)
    + Make Nuke Team (Requires Ghosts)
    + Make Aliens (Requires Ghosts)
    + Make Deathsquad (Syndicate) (Requires Ghosts)
    + "} + + usr << browse(dat, "window=oneclickantag;size=400x400") + return + + +/datum/admins/proc/makeMalfAImode() + + + var/list/mob/living/silicon/AIs = list() + var/mob/living/silicon/malfAI = null + var/datum/mind/themind = null + + for(var/mob/living/silicon/ai/ai in player_list) + if(ai.client) + AIs += ai + + if(AIs.len) + malfAI = pick(AIs) + + if(malfAI) + themind = malfAI.mind + themind.make_AI_Malf() + return 1 + + return 0 + + +/datum/admins/proc/makeTraitors() + var/datum/game_mode/traitor/temp = new + + if(config.protect_roles_from_antagonist) + temp.restricted_jobs += temp.protected_jobs + + var/list/mob/living/carbon/human/candidates = list() + + for(var/mob/living/carbon/human/applicant in player_list) + if(applicant.client.desires_role(ROLE_TRAITOR)) + if(!applicant.stat) + if(applicant.mind) + if (!applicant.mind.special_role) + if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant + + if (candidates.len) + candidates = shuffle(candidates) + + var/mob/living/carbon/human/candidate + + for (var/i = 1 to min(candidates.len, 3)) + candidate = pick_n_take(candidates) + + if (candidate) + var/datum/mind/candidate_mind = candidate.mind + + if (candidate_mind) + if (candidate_mind.make_traitor()) + log_admin("[key_name(owner)] has traitor'ed [key_name(candidate)] via create antagonist verb.") + + return 1 + + return 0 + + +/datum/admins/proc/makeChanglings() + + + var/datum/game_mode/changeling/temp = new + if(config.protect_roles_from_antagonist) + temp.restricted_jobs += temp.protected_jobs + + var/list/mob/living/carbon/human/candidates = list() + var/mob/living/carbon/human/H = null + + for(var/mob/living/carbon/human/applicant in player_list) + if(applicant.client.desires_role(ROLE_CHANGELING)) + if(!applicant.stat) + if(applicant.mind) + if (!applicant.mind.special_role) + if(!jobban_isbanned(applicant, "changeling") && !jobban_isbanned(applicant, "Syndicate")) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant + + if(candidates.len) + var/numChanglings = min(candidates.len, 3) + + for(var/i = 0, iYou are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: [input]") - - numagents-- - if(numagents >= 6) - return 0 - - for (var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) - if (L.name == "Syndicate-Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) - - return 1 - - -/proc/makeBody(var/mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character - if(!G_found || !G_found.key) return - - //First we spawn a dude. - var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. - - new_character.gender = pick(MALE,FEMALE) - - var/datum/preferences/A = new() - A.randomize_appearance_for(new_character) - new_character.generate_name() - new_character.age = rand(17,45) - - new_character.dna.ready_dna(new_character) - new_character.key = G_found.key - - return new_character - -/datum/admins/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) - var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) - var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") - var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") - var/syndicate_commando_name = pick(last_names) - - new_syndicate_commando.gender = pick(MALE, FEMALE) - - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_syndicate_commando) - - new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" - new_syndicate_commando.name = new_syndicate_commando.real_name - new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) - - new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. - - //Creates mind stuff. - new_syndicate_commando.mind_initialize() - new_syndicate_commando.mind.assigned_role = "MODE" - new_syndicate_commando.mind.special_role = "Syndicate Commando" - - //Adds them to current traitor list. Which is really the extra antagonist list. - ticker.mode.traitors += new_syndicate_commando.mind - new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) - - return new_syndicate_commando - -/datum/admins/proc/makeVoxRaiders() - - - var/list/mob/dead/observer/candidates = list() - var/mob/dead/observer/theghost = null - var/input = "Disregard shinies, acquire hardware." - - var/leader_chosen = 0 //when the leader is chosen. The last person spawned. - - //Generates a list of candidates from active ghosts. - for(var/mob/dead/observer/G in get_active_candidates(ROLE_VOXRAIDER, poll="Do you wish to be considered for a vox raiding party arriving on the station?")) - candidates += G - - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) - - if(candidates.len) - var/max_raiders = 1 - var/raiders = max_raiders - //Spawns vox raiders and equips them. - for (var/obj/effect/landmark/L in landmarks_list) - if(L.name == "voxstart") - if(raiders<=0) - break - - var/mob/living/carbon/human/new_vox = create_vox_raider(L, leader_chosen) - - while((!theghost || !theghost.client) && candidates.len) - theghost = pick(candidates) - candidates.Remove(theghost) - - if(!theghost) - del(new_vox) - break - - new_vox.key = theghost.key + + numagents-- + if(numagents >= 6) + return 0 + + for (var/obj/effect/landmark/L in /area/shuttle/syndicate_elite) + if (L.name == "Syndicate-Commando-Bomb") + new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) + + return 1 + + +/proc/makeBody(var/mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character + if(!G_found || !G_found.key) return + + //First we spawn a dude. + var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. + + new_character.gender = pick(MALE,FEMALE) + + var/datum/preferences/A = new() + A.randomize_appearance_for(new_character) + new_character.generate_name() + new_character.age = rand(17,45) + + new_character.dna.ready_dna(new_character) + new_character.key = G_found.key + + return new_character + +/datum/admins/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) + var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) + var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") + var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") + var/syndicate_commando_name = pick(last_names) + + new_syndicate_commando.gender = pick(MALE, FEMALE) + + var/datum/preferences/A = new()//Randomize appearance for the commando. + A.randomize_appearance_for(new_syndicate_commando) + + new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" + new_syndicate_commando.name = new_syndicate_commando.real_name + new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) + + new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. + + //Creates mind stuff. + new_syndicate_commando.mind_initialize() + new_syndicate_commando.mind.assigned_role = "MODE" + new_syndicate_commando.mind.special_role = "Syndicate Commando" + + //Adds them to current traitor list. Which is really the extra antagonist list. + ticker.mode.traitors += new_syndicate_commando.mind + new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) + + return new_syndicate_commando + +/datum/admins/proc/makeVoxRaiders() + + + var/list/mob/dead/observer/candidates = list() + var/mob/dead/observer/theghost = null + var/input = "Disregard shinies, acquire hardware." + + var/leader_chosen = 0 //when the leader is chosen. The last person spawned. + + //Generates a list of candidates from active ghosts. + for(var/mob/dead/observer/G in get_active_candidates(ROLE_VOXRAIDER, poll="Do you wish to be considered for a vox raiding party arriving on the station?")) + candidates += G + + for(var/mob/dead/observer/G in candidates) + if(!G.key) + candidates.Remove(G) + + if(candidates.len) + var/max_raiders = 1 + var/raiders = max_raiders + //Spawns vox raiders and equips them. + for (var/obj/effect/landmark/L in landmarks_list) + if(L.name == "voxstart") + if(raiders<=0) + break + + var/mob/living/carbon/human/new_vox = create_vox_raider(L, leader_chosen) + + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + del(new_vox) + break + + new_vox.key = theghost.key to_chat(new_vox, "You are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at the Tau Ceti system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, but everyong is raring to start pillaging! Your current goal is: [input]") to_chat(new_vox, "Don't forget to turn on your nitrogen internals!") - - raiders-- - if(raiders > max_raiders) - return 0 - else - return 0 - return 1 - -/datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) - - - var/mob/living/carbon/human/new_vox = new(spawn_location.loc) - - new_vox.setGender(pick(MALE, FEMALE)) - new_vox.h_style = "Short Vox Quills" - new_vox.regenerate_icons() - - new_vox.age = rand(12,20) - - new_vox.dna.ready_dna(new_vox) // Creates DNA. - new_vox.dna.mutantrace = "vox" - new_vox.set_species("Vox") // Actually makes the vox! How about that. - new_vox.generate_name() - //new_vox.add_language("Vox-pidgin") - new_vox.mind_initialize() - new_vox.mind.assigned_role = "MODE" - new_vox.mind.special_role = "Vox Raider" - new_vox.mutations |= M_NOCLONE //Stops the station crew from messing around with their DNA. - - ticker.mode.traitors += new_vox.mind - new_vox.equip_vox_raider() - + + raiders-- + if(raiders > max_raiders) + return 0 + else + return 0 + return 1 + +/datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) + + + var/mob/living/carbon/human/new_vox = new(spawn_location.loc) + + new_vox.setGender(pick(MALE, FEMALE)) + new_vox.h_style = "Short Vox Quills" + new_vox.regenerate_icons() + + new_vox.age = rand(12,20) + + new_vox.dna.ready_dna(new_vox) // Creates DNA. + new_vox.dna.mutantrace = "vox" + new_vox.set_species("Vox") // Actually makes the vox! How about that. + new_vox.generate_name() + //new_vox.add_language("Vox-pidgin") + new_vox.mind_initialize() + new_vox.mind.assigned_role = "MODE" + new_vox.mind.special_role = "Vox Raider" + new_vox.mutations |= M_NOCLONE //Stops the station crew from messing around with their DNA. + + ticker.mode.traitors += new_vox.mind + new_vox.equip_vox_raider() + return new_vox \ No newline at end of file diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index ddfc0835a24..aed5f1f5945 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -1,52 +1,52 @@ -/client/proc/only_one() - if(!ticker) - alert("The game hasn't started yet!") - return - - for(var/mob/living/carbon/human/H in player_list) - if(H.stat == 2 || !(H.client)) continue - if(is_special_character(H)) continue - - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - - /* This never worked. - var/datum/objective/steal/steal_objective = new - steal_objective.owner = H.mind - steal_objective.set_target("nuclear authentication disk") - H.mind.objectives += steal_objective - */ - - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = H.mind - H.mind.objectives += hijack_objective - +/client/proc/only_one() + if(!ticker) + alert("The game hasn't started yet!") + return + + for(var/mob/living/carbon/human/H in player_list) + if(H.stat == 2 || !(H.client)) continue + if(is_special_character(H)) continue + + ticker.mode.traitors += H.mind + H.mind.special_role = "traitor" + + /* This never worked. + var/datum/objective/steal/steal_objective = new + steal_objective.owner = H.mind + steal_objective.set_target("nuclear authentication disk") + H.mind.objectives += steal_objective + */ + + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = H.mind + H.mind.objectives += hijack_objective + to_chat(H, "You are the traitor.") - var/obj_count = 1 - for(var/datum/objective/OBJ in H.mind.objectives) + var/obj_count = 1 + for(var/datum/objective/OBJ in H.mind.objectives) to_chat(H, "Objective #[obj_count]: [OBJ.explanation_text]") - obj_count++ - - for (var/obj/item/I in H) - if (istype(I, /obj/item/weapon/implant)) - continue - del(I) - - H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_ears) - H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/weapon/claymore(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(H.loc), slot_l_store) - - var/obj/item/weapon/card/id/W = new(H) - W.name = "[H.real_name]'s ID Card" - W.icon_state = "centcom" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.assignment = "Highlander" - W.registered_name = H.real_name - H.equip_to_slot_or_del(W, slot_wear_id) - - message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1) + obj_count++ + + for (var/obj/item/I in H) + if (istype(I, /obj/item/weapon/implant)) + continue + del(I) + + H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_ears) + H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/weapon/claymore(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(H.loc), slot_l_store) + + var/obj/item/weapon/card/id/W = new(H) + W.name = "[H.real_name]'s ID Card" + W.icon_state = "centcom" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.assignment = "Highlander" + W.registered_name = H.real_name + H.equip_to_slot_or_del(W, slot_wear_id) + + message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1) log_admin("[key_name(usr)] used there can be only one.") \ No newline at end of file diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 90331be67d8..34bdebc15b2 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -1,79 +1,79 @@ -/client/proc/play_sound(var/sound/S as sound) - set category = "Fun" - set name = "Play Global Sound" - if(!check_rights(R_SOUNDS)) return - - var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = 777) - uploaded_sound.status = SOUND_STREAM | SOUND_UPDATE - uploaded_sound.priority = 250 - - log_admin("[key_name(src)] played sound [S]") - message_admins("[key_name_admin(src)] played sound [S]", 1) - for(var/mob/M in player_list) - if(!M.client) continue - if(M.client.prefs.toggles & SOUND_MIDI) +/client/proc/play_sound(var/sound/S as sound) + set category = "Fun" + set name = "Play Global Sound" + if(!check_rights(R_SOUNDS)) return + + var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = 777) + uploaded_sound.status = SOUND_STREAM | SOUND_UPDATE + uploaded_sound.priority = 250 + + log_admin("[key_name(src)] played sound [S]") + message_admins("[key_name_admin(src)] played sound [S]", 1) + for(var/mob/M in player_list) + if(!M.client) continue + if(M.client.prefs.toggles & SOUND_MIDI) to_chat(M, uploaded_sound) - - feedback_add_details("admin_verb","PGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/play_local_sound(var/sound/S as sound) - set category = "Fun" - set name = "Play Local Sound" - if(!check_rights(R_SOUNDS)) return - if(!istype(S)) S = sound(S) - log_admin("[key_name(src)] played a local sound [S]") - message_admins("[key_name_admin(src)] played a local sound [S]", 1) - S.status = SOUND_STREAM | SOUND_UPDATE - playsound(get_turf(src.mob), S, 50, 0, 0) - feedback_add_details("admin_verb","PLS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/* -/client/proc/cuban_pete() - set category = "Fun" - set name = "Cuban Pete Time" - - message_admins("[key_name_admin(usr)] has declared Cuban Pete Time!", 1) - for(var/mob/M in world) - if(M.client) - if(M.client.midis) + + feedback_add_details("admin_verb","PGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/play_local_sound(var/sound/S as sound) + set category = "Fun" + set name = "Play Local Sound" + if(!check_rights(R_SOUNDS)) return + if(!istype(S)) S = sound(S) + log_admin("[key_name(src)] played a local sound [S]") + message_admins("[key_name_admin(src)] played a local sound [S]", 1) + S.status = SOUND_STREAM | SOUND_UPDATE + playsound(get_turf(src.mob), S, 50, 0, 0) + feedback_add_details("admin_verb","PLS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/* +/client/proc/cuban_pete() + set category = "Fun" + set name = "Cuban Pete Time" + + message_admins("[key_name_admin(usr)] has declared Cuban Pete Time!", 1) + for(var/mob/M in world) + if(M.client) + if(M.client.midis) to_chat(M, 'cubanpetetime.ogg') - - for(var/mob/living/carbon/human/CP in world) - if(CP.real_name=="Cuban Pete" && CP.key!="Rosham") + + for(var/mob/living/carbon/human/CP in world) + if(CP.real_name=="Cuban Pete" && CP.key!="Rosham") to_chat(CP, "Your body can't contain the rhumba beat") - CP.gib() - - -/client/proc/bananaphone() - set category = "Fun" - set name = "Banana Phone" - - message_admins("[key_name_admin(usr)] has activated Banana Phone!", 1) - for(var/mob/M in world) - if(M.client) - if(M.client.midis) + CP.gib() + + +/client/proc/bananaphone() + set category = "Fun" + set name = "Banana Phone" + + message_admins("[key_name_admin(usr)] has activated Banana Phone!", 1) + for(var/mob/M in world) + if(M.client) + if(M.client.midis) to_chat(M, 'bananaphone.ogg') - - -client/proc/space_asshole() - set category = "Fun" - set name = "Space Asshole" - - message_admins("[key_name_admin(usr)] has played the Space Asshole Hymn.", 1) - for(var/mob/M in world) - if(M.client) - if(M.client.midis) + + +client/proc/space_asshole() + set category = "Fun" + set name = "Space Asshole" + + message_admins("[key_name_admin(usr)] has played the Space Asshole Hymn.", 1) + for(var/mob/M in world) + if(M.client) + if(M.client.midis) to_chat(M, 'sound/music/space_asshole.ogg') - - -client/proc/honk_theme() - set category = "Fun" - set name = "Honk" - - message_admins("[key_name_admin(usr)] has creeped everyone out with Blackest Honks.", 1) - for(var/mob/M in world) - if(M.client) - if(M.client.midis) + + +client/proc/honk_theme() + set category = "Fun" + set name = "Honk" + + message_admins("[key_name_admin(usr)] has creeped everyone out with Blackest Honks.", 1) + for(var/mob/M in world) + if(M.client) + if(M.client.midis) to_chat(M, 'honk_theme.ogg')*/ diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index c67b5feb55a..72eba530b5d 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -1,49 +1,49 @@ -//The Pray verb. Often known as the IC adminhelp, or the crayon for cool shit trade -/mob/verb/pray(msg as text) - set category = "IC" - set name = "Pray" - - if(say_disabled) //This is here to try to identify lag problems +//The Pray verb. Often known as the IC adminhelp, or the crayon for cool shit trade +/mob/verb/pray(msg as text) + set category = "IC" + set name = "Pray" + + if(say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") - return - - msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) - if(!msg) - return - - if(usr.client) - if(usr.client.prefs.muted & MUTE_PRAY) + return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + if(!msg) + return + + if(usr.client) + if(usr.client.prefs.muted & MUTE_PRAY) to_chat(usr, "You cannot pray (muted).") - return - if(src.client.handle_spam_prevention(msg, MUTE_PRAY)) - return - - var/orig_message = msg - var/image/cross = image('icons/obj/storage.dmi',"bible") - msg = "\icon[cross] PRAY (DEITY:[ticker.Bible_deity_name]): [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (CA) (SC): [msg]" - - for(var/client/C in admins) - if(C.prefs.toggles & CHAT_PRAYER) - if(C.prefs.special_popup) - C << output(msg, "window1.msay_output")//if i get told to make this a proc imma be fuckin mad - else + return + if(src.client.handle_spam_prevention(msg, MUTE_PRAY)) + return + + var/orig_message = msg + var/image/cross = image('icons/obj/storage.dmi',"bible") + msg = "\icon[cross] PRAY (DEITY:[ticker.Bible_deity_name]): [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (CA) (SC): [msg]" + + for(var/client/C in admins) + if(C.prefs.toggles & CHAT_PRAYER) + if(C.prefs.special_popup) + C << output(msg, "window1.msay_output")//if i get told to make this a proc imma be fuckin mad + else to_chat(C, msg) to_chat(C, 'sound/effects/prayer.ogg') - - if(!stat) - usr.whisper(orig_message) + + if(!stat) + usr.whisper(orig_message) to_chat(usr, "Your prayers have been received by the gods.") - - feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/proc/Centcomm_announce(var/text , var/mob/Sender) - var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN) - msg = "CENTCOMM:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [msg]" + + feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/proc/Centcomm_announce(var/text , var/mob/Sender) + var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN) + msg = "CENTCOMM:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [msg]" to_chat(admins, msg) to_chat(admins, 'sound/effects/msn.ogg') - -/proc/Syndicate_announce(var/text , var/mob/Sender) - var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN) - msg = "SYNDICATE:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [msg]" + +/proc/Syndicate_announce(var/text , var/mob/Sender) + var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN) + msg = "SYNDICATE:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [msg]" to_chat(admins, msg) to_chat(admins, 'sound/effects/inception.ogg') diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index a25e1847046..4929f2c09ff 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1,979 +1,979 @@ -/client/proc/cmd_admin_drop_everything(mob/M as mob in mob_list) - set category = null - set name = "Drop Everything" - if(!holder) +/client/proc/cmd_admin_drop_everything(mob/M as mob in mob_list) + set category = null + set name = "Drop Everything" + if(!holder) to_chat(src, "Only administrators may use this command.") - return - - var/confirm = alert(src, "Make [M] drop everything?", "Message", "Yes", "No") - if(confirm != "Yes") - return - - M.drop_all() - - log_admin("[key_name(usr)] made [key_name(M)] drop everything!") - message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!", 1) - feedback_add_details("admin_verb","DEVR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_prison(mob/M as mob in mob_list) - set category = "Admin" - set name = "Prison" - if(!holder) + return + + var/confirm = alert(src, "Make [M] drop everything?", "Message", "Yes", "No") + if(confirm != "Yes") + return + + M.drop_all() + + log_admin("[key_name(usr)] made [key_name(M)] drop everything!") + message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!", 1) + feedback_add_details("admin_verb","DEVR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_prison(mob/M as mob in mob_list) + set category = "Admin" + set name = "Prison" + if(!holder) to_chat(src, "Only administrators may use this command.") - return - if (ismob(M)) - if(istype(M, /mob/living/silicon/ai)) - alert("The AI can't be sent to prison you jerk!", null, null, null, null, null) - return - //strip their stuff before they teleport into a cell :downs: - for(var/obj/item/W in M) - M.drop_from_inventory(W) - //teleport person to cell - M.Paralyse(5) - sleep(5) //so they black out before warping - M.loc = pick(prisonwarp) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/prisoner = M - prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/prisoner(prisoner), slot_w_uniform) - prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes) - spawn(50) + return + if (ismob(M)) + if(istype(M, /mob/living/silicon/ai)) + alert("The AI can't be sent to prison you jerk!", null, null, null, null, null) + return + //strip their stuff before they teleport into a cell :downs: + for(var/obj/item/W in M) + M.drop_from_inventory(W) + //teleport person to cell + M.Paralyse(5) + sleep(5) //so they black out before warping + M.loc = pick(prisonwarp) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/prisoner = M + prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/prisoner(prisoner), slot_w_uniform) + prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes) + spawn(50) to_chat(M, "You have been sent to the prison station!") - log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") - message_admins("[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1) - feedback_add_details("admin_verb","PRISON") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_subtle_message(mob/M as mob in mob_list) - set category = "Special Verbs" - set name = "Subtle Message" - - if(!ismob(M)) return - if (!holder) + log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") + message_admins("[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1) + feedback_add_details("admin_verb","PRISON") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_subtle_message(mob/M as mob in mob_list) + set category = "Special Verbs" + set name = "Subtle Message" + + if(!ismob(M)) return + if (!holder) to_chat(src, "Only administrators may use this command.") - return - - var/msg = input("Message:", text("Subtle PM to [M.key]")) as text - - if (!msg) - return - if(usr) - if (usr.client) - if(usr.client.holder) - M.get_subtle_message(msg) - - log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]") - message_admins("SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]", 1) - feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE - set category = "Special Verbs" - set name = "Global Narrate" - - if (!holder) + return + + var/msg = input("Message:", text("Subtle PM to [M.key]")) as text + + if (!msg) + return + if(usr) + if (usr.client) + if(usr.client.holder) + M.get_subtle_message(msg) + + log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]") + message_admins("SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]", 1) + feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE + set category = "Special Verbs" + set name = "Global Narrate" + + if (!holder) to_chat(src, "Only administrators may use this command.") - return - - var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text - - if (!msg) - return + return + + var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text + + if (!msg) + return to_chat(world, "[msg]") - log_admin("GlobalNarrate: [key_name(usr)] : [msg]") - message_admins("GlobalNarrate: [key_name_admin(usr)] : [msg]
    ", 1) - feedback_add_details("admin_verb","GLN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_direct_narrate(var/mob/M) // Targetted narrate -- TLE - set category = "Special Verbs" - set name = "Direct Narrate" - - if(!holder) + log_admin("GlobalNarrate: [key_name(usr)] : [msg]") + message_admins("GlobalNarrate: [key_name_admin(usr)] : [msg]
    ", 1) + feedback_add_details("admin_verb","GLN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_direct_narrate(var/mob/M) // Targetted narrate -- TLE + set category = "Special Verbs" + set name = "Direct Narrate" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - - if(!M) - M = input("Direct narrate to who?", "Active Players") as null|anything in player_list - - if(!M) - return - - var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text - - if( !msg ) - return - + return + + if(!M) + M = input("Direct narrate to who?", "Active Players") as null|anything in player_list + + if(!M) + return + + var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text + + if( !msg ) + return + to_chat(M, msg) - log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]") - message_admins("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]
    ", 1) - feedback_add_details("admin_verb","DIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_local_narrate() // View targetted narration - set category = "Special Verbs" - set name = "Local Narrate" - - if(!holder) + log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]") + message_admins("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]
    ", 1) + feedback_add_details("admin_verb","DIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_local_narrate() // View targetted narration + set category = "Special Verbs" + set name = "Local Narrate" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - - var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text - - if( !msg ) - return - - for(var/mob/M in view()) - if(M in player_list) + return + + var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text + + if( !msg ) + return + + for(var/mob/M in view()) + if(M in player_list) to_chat(M, msg) - - log_admin("LocalNarrate: [key_name(usr)] at [formatJumpTo(get_turf(usr))]: [msg]") - message_admins("DirectNarrate: [key_name(usr)] at [formatJumpTo(get_turf(usr))]: [msg]
    ", 1) - feedback_add_details("admin_verb","LIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_godmode(mob/M as mob in mob_list) - set category = "Special Verbs" - set name = "Godmode" - - if(!holder) + + log_admin("LocalNarrate: [key_name(usr)] at [formatJumpTo(get_turf(usr))]: [msg]") + message_admins("DirectNarrate: [key_name(usr)] at [formatJumpTo(get_turf(usr))]: [msg]
    ", 1) + feedback_add_details("admin_verb","LIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_godmode(mob/M as mob in mob_list) + set category = "Special Verbs" + set name = "Godmode" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - M.status_flags ^= GODMODE + return + M.status_flags ^= GODMODE to_chat(usr, "Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]") - - log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]") - message_admins("[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]", 1) - feedback_add_details("admin_verb","GOD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0) - if(automute) - if(!config.automute_on) return - else - if(!usr || !usr.client) - return - if(!usr.client.holder) + + log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]") + message_admins("[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]", 1) + feedback_add_details("admin_verb","GOD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0) + if(automute) + if(!config.automute_on) return + else + if(!usr || !usr.client) + return + if(!usr.client.holder) to_chat(usr, "Error: cmd_admin_mute: You don't have permission to do this.") - return - if(!M.client) + return + if(!M.client) to_chat(usr, "Error: cmd_admin_mute: This mob doesn't have a client tied to it.") - if(M.client.holder) + if(M.client.holder) to_chat(usr, "Error: cmd_admin_mute: You cannot mute an admin.") - if(!M.client) return - if(M.client.holder) return - - var/muteunmute - var/mute_string - - switch(mute_type) - if(MUTE_IC) mute_string = "IC (say and emote)" - if(MUTE_OOC) mute_string = "OOC" - if(MUTE_PRAY) mute_string = "pray" - if(MUTE_ADMINHELP) mute_string = "adminhelp, admin PM and ASAY" - if(MUTE_DEADCHAT) mute_string = "deadchat and DSAY" - if(MUTE_ALL) mute_string = "everything" - else return - - if(automute) - muteunmute = "auto-muted" - M.client.prefs.muted |= mute_type - log_admin("SPAM AUTOMUTE: [muteunmute] [key_name(M)] from [mute_string]") - message_admins("SPAM AUTOMUTE: [muteunmute] [key_name_admin(M)] from [mute_string].", 1) + if(!M.client) return + if(M.client.holder) return + + var/muteunmute + var/mute_string + + switch(mute_type) + if(MUTE_IC) mute_string = "IC (say and emote)" + if(MUTE_OOC) mute_string = "OOC" + if(MUTE_PRAY) mute_string = "pray" + if(MUTE_ADMINHELP) mute_string = "adminhelp, admin PM and ASAY" + if(MUTE_DEADCHAT) mute_string = "deadchat and DSAY" + if(MUTE_ALL) mute_string = "everything" + else return + + if(automute) + muteunmute = "auto-muted" + M.client.prefs.muted |= mute_type + log_admin("SPAM AUTOMUTE: [muteunmute] [key_name(M)] from [mute_string]") + message_admins("SPAM AUTOMUTE: [muteunmute] [key_name_admin(M)] from [mute_string].", 1) to_chat(M, "You have been [muteunmute] from [mute_string] by the SPAM AUTOMUTE system. Contact an admin.") - feedback_add_details("admin_verb","AUTOMUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - - if(M.client.prefs.muted & mute_type) - muteunmute = "unmuted" - M.client.prefs.muted &= ~mute_type - else - muteunmute = "muted" - M.client.prefs.muted |= mute_type - - log_admin("[key_name(usr)] has [muteunmute] [key_name(M)] from [mute_string]") - message_admins("[key_name_admin(usr)] has [muteunmute] [key_name_admin(M)] from [mute_string].", 1) + feedback_add_details("admin_verb","AUTOMUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + + if(M.client.prefs.muted & mute_type) + muteunmute = "unmuted" + M.client.prefs.muted &= ~mute_type + else + muteunmute = "muted" + M.client.prefs.muted |= mute_type + + log_admin("[key_name(usr)] has [muteunmute] [key_name(M)] from [mute_string]") + message_admins("[key_name_admin(usr)] has [muteunmute] [key_name_admin(M)] from [mute_string].", 1) to_chat(M, "You have been [muteunmute] from [mute_string].") - feedback_add_details("admin_verb","MUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/cmd_admin_add_random_ai_law() - set category = "Fun" - set name = "Add Random AI Law" - - if(!holder) + feedback_add_details("admin_verb","MUTE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/cmd_admin_add_random_ai_law() + set category = "Fun" + set name = "Add Random AI Law" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") - if(confirm != "Yes") return - log_admin("[key_name(src)] has added a random AI law.") - message_admins("[key_name_admin(src)] has added a random AI law.", 1) - - var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No") - if(show_log == "Yes") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") + return + var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") + if(confirm != "Yes") return + log_admin("[key_name(src)] has added a random AI law.") + message_admins("[key_name_admin(src)] has added a random AI law.", 1) + + var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No") + if(show_log == "Yes") + command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") to_chat(world, sound('sound/AI/ionstorm.ogg')) - - generate_ion_law() - feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -//I use this proc for respawn character too. /N -/proc/create_xeno(ckey) - if(!ckey) - var/list/candidates = list() - for(var/mob/M in get_active_candidates(ROLE_ALIEN)) - if(M.stat != DEAD) continue //we are not dead! - if(M.client.is_afk()) continue //we are afk - candidates += M.ckey - if(candidates.len) - ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates - else + + generate_ion_law() + feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +//I use this proc for respawn character too. /N +/proc/create_xeno(ckey) + if(!ckey) + var/list/candidates = list() + for(var/mob/M in get_active_candidates(ROLE_ALIEN)) + if(M.stat != DEAD) continue //we are not dead! + if(M.client.is_afk()) continue //we are afk + candidates += M.ckey + if(candidates.len) + ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates + else to_chat(usr, "Error: create_xeno(): no suitable candidates.") - if(!istext(ckey)) return 0 - - var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva") - var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin) - var/mob/living/carbon/alien/new_xeno - switch(alien_caste) - if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(spawn_here) - if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here) - if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here) - if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here) - if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here) - else return 0 - - new_xeno.ckey = ckey - message_admins("[key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1) - return 1 - -/* -Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly -Ccomp's first proc. -*/ - -/client/proc/get_ghosts(var/notify = 0,var/what = 2) - // what = 1, return ghosts ass list. - // what = 2, return mob list - - var/list/mobs = list() - var/list/ghosts = list() - var/list/sortmob = sortNames(mob_list) // get the mob list. - /var/any=0 - for(var/mob/dead/observer/M in sortmob) - mobs.Add(M) //filter it where it's only ghosts - any = 1 //if no ghosts show up, any will just be 0 - if(!any) - if(notify) + if(!istext(ckey)) return 0 + + var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva") + var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin) + var/mob/living/carbon/alien/new_xeno + switch(alien_caste) + if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(spawn_here) + if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here) + if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here) + if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here) + if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here) + else return 0 + + new_xeno.ckey = ckey + message_admins("[key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1) + return 1 + +/* +Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly +Ccomp's first proc. +*/ + +/client/proc/get_ghosts(var/notify = 0,var/what = 2) + // what = 1, return ghosts ass list. + // what = 2, return mob list + + var/list/mobs = list() + var/list/ghosts = list() + var/list/sortmob = sortNames(mob_list) // get the mob list. + /var/any=0 + for(var/mob/dead/observer/M in sortmob) + mobs.Add(M) //filter it where it's only ghosts + any = 1 //if no ghosts show up, any will just be 0 + if(!any) + if(notify) to_chat(src, "There doesn't appear to be any ghosts for you to select.") - return - - for(var/mob/M in mobs) - var/name = M.name - ghosts[name] = M //get the name of the mob for the popup list - if(what==1) - return ghosts - else - return mobs - - -/client/proc/allow_character_respawn() - set category = "Special Verbs" - set name = "Allow player to respawn" - set desc = "Let's the player bypass the 30 minute wait to respawn or allow them to re-enter their corpse." - - if(!holder) - to_chat(src, "Only administrators may use this command.") - var/list/ghosts= get_ghosts(1,1) - - var/target = input("Please, select a ghost!", "COME BACK TO LIFE!", null, null) as null|anything in ghosts - if(!target) - to_chat(src, "Hrm, appears you didn't select a ghost") // Sanity check, if no ghosts in the list we don't want to edit a null variable and cause a runtime error. + return - return - - var/mob/dead/observer/G = ghosts[target] - if(G.has_enabled_antagHUD && config.antag_hud_restricted) - var/response = alert(src, "Are you sure you wish to allow this individual to play?","Ghost has used AntagHUD","Yes","No") - if(response == "No") return - G.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb. - timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure - there won't be an autopsy. - */ - G.has_enabled_antagHUD = 2 - G.can_reenter_corpse = 1 - - G:show_message(text("You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead."), 1) - log_admin("[key_name(usr)] allowed [key_name(G)] to bypass the 30 minute respawn limit") - message_admins("Admin [key_name_admin(usr)] allowed [key_name_admin(G)] to bypass the 30 minute respawn limit", 1) - - -/client/proc/toggle_antagHUD_use() - set category = "Server" - set name = "Toggle antagHUD usage" - set desc = "Toggles antagHUD usage for observers" - - if(!holder) + for(var/mob/M in mobs) + var/name = M.name + ghosts[name] = M //get the name of the mob for the popup list + if(what==1) + return ghosts + else + return mobs + + +/client/proc/allow_character_respawn() + set category = "Special Verbs" + set name = "Allow player to respawn" + set desc = "Let's the player bypass the 30 minute wait to respawn or allow them to re-enter their corpse." + + if(!holder) to_chat(src, "Only administrators may use this command.") - var/action="" - if(config.antag_hud_allowed) - for(var/mob/dead/observer/g in get_ghosts()) - if(!g.client.holder) //Remove the verb from non-admin ghosts - g.verbs -= /mob/dead/observer/verb/toggle_antagHUD - if(g.antagHUD) - g.antagHUD = 0 // Disable it on those that have it enabled - g.has_enabled_antagHUD = 2 // We'll allow them to respawn + var/list/ghosts= get_ghosts(1,1) + + var/target = input("Please, select a ghost!", "COME BACK TO LIFE!", null, null) as null|anything in ghosts + if(!target) + to_chat(src, "Hrm, appears you didn't select a ghost") // Sanity check, if no ghosts in the list we don't want to edit a null variable and cause a runtime error. + + return + + var/mob/dead/observer/G = ghosts[target] + if(G.has_enabled_antagHUD && config.antag_hud_restricted) + var/response = alert(src, "Are you sure you wish to allow this individual to play?","Ghost has used AntagHUD","Yes","No") + if(response == "No") return + G.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb. + timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure + there won't be an autopsy. + */ + G.has_enabled_antagHUD = 2 + G.can_reenter_corpse = 1 + + G:show_message(text("You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead."), 1) + log_admin("[key_name(usr)] allowed [key_name(G)] to bypass the 30 minute respawn limit") + message_admins("Admin [key_name_admin(usr)] allowed [key_name_admin(G)] to bypass the 30 minute respawn limit", 1) + + +/client/proc/toggle_antagHUD_use() + set category = "Server" + set name = "Toggle antagHUD usage" + set desc = "Toggles antagHUD usage for observers" + + if(!holder) + to_chat(src, "Only administrators may use this command.") + var/action="" + if(config.antag_hud_allowed) + for(var/mob/dead/observer/g in get_ghosts()) + if(!g.client.holder) //Remove the verb from non-admin ghosts + g.verbs -= /mob/dead/observer/verb/toggle_antagHUD + if(g.antagHUD) + g.antagHUD = 0 // Disable it on those that have it enabled + g.has_enabled_antagHUD = 2 // We'll allow them to respawn to_chat(g, "The Administrator has disabled AntagHUD ") - config.antag_hud_allowed = 0 + config.antag_hud_allowed = 0 to_chat(src, "AntagHUD usage has been disabled") - action = "disabled" - else - for(var/mob/dead/observer/g in get_ghosts()) - if(!g.client.holder) // Add the verb back for all non-admin ghosts - g.verbs += /mob/dead/observer/verb/toggle_antagHUD - to_chat(g, "The Administrator has enabled AntagHUD ")// Notify all observers they can now use AntagHUD + action = "disabled" + else + for(var/mob/dead/observer/g in get_ghosts()) + if(!g.client.holder) // Add the verb back for all non-admin ghosts + g.verbs += /mob/dead/observer/verb/toggle_antagHUD + to_chat(g, "The Administrator has enabled AntagHUD ")// Notify all observers they can now use AntagHUD - config.antag_hud_allowed = 1 - action = "enabled" + config.antag_hud_allowed = 1 + action = "enabled" to_chat(src, "AntagHUD usage has been enabled") - - - log_admin("[key_name(usr)] has [action] antagHUD usage for observers") - message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1) - - - -/client/proc/toggle_antagHUD_restrictions() - set category = "Server" - set name = "Toggle antagHUD Restrictions" - set desc = "Restricts players that have used antagHUD from being able to join this round." - - if(!holder) + + + log_admin("[key_name(usr)] has [action] antagHUD usage for observers") + message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1) + + + +/client/proc/toggle_antagHUD_restrictions() + set category = "Server" + set name = "Toggle antagHUD Restrictions" + set desc = "Restricts players that have used antagHUD from being able to join this round." + + if(!holder) to_chat(src, "Only administrators may use this command.") - var/action="" - if(config.antag_hud_restricted) - for(var/mob/dead/observer/g in get_ghosts()) + var/action="" + if(config.antag_hud_restricted) + for(var/mob/dead/observer/g in get_ghosts()) to_chat(g, "The administrator has lifted restrictions on joining the round if you use AntagHUD") - action = "lifted restrictions" - config.antag_hud_restricted = 0 + action = "lifted restrictions" + config.antag_hud_restricted = 0 to_chat(src, "AntagHUD restrictions have been lifted") - else - for(var/mob/dead/observer/g in get_ghosts()) + else + for(var/mob/dead/observer/g in get_ghosts()) to_chat(g, "The administrator has placed restrictions on joining the round if you use AntagHUD") to_chat(g, "Your AntagHUD has been disabled, you may choose to re-enabled it but will be under restrictions ") - g.antagHUD = 0 - g.has_enabled_antagHUD = 0 - action = "placed restrictions" - config.antag_hud_restricted = 1 + g.antagHUD = 0 + g.has_enabled_antagHUD = 0 + action = "placed restrictions" + config.antag_hud_restricted = 1 to_chat(src, "AntagHUD restrictions have been enabled") - - log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD") - message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1) - - - - -/* -If a guy was gibbed and you want to revive him, this is a good way to do so. -Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one. -Traitors and the like can also be revived with the previous role mostly intact. -/N */ -/client/proc/respawn_character() - set category = "Special Verbs" - set name = "Respawn Character" - set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into." - - if(!holder) + + log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD") + message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1) + + + + +/* +If a guy was gibbed and you want to revive him, this is a good way to do so. +Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one. +Traitors and the like can also be revived with the previous role mostly intact. +/N */ +/client/proc/respawn_character() + set category = "Special Verbs" + set name = "Respawn Character" + set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into." + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", "")) - if(!input) - return - - var/mob/dead/observer/G_found - for(var/mob/dead/observer/G in player_list) - if(G.ckey == input) - G_found = G - break - - if(!G_found)//If a ghost was not found. + return + var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", "")) + if(!input) + return + + var/mob/dead/observer/G_found + for(var/mob/dead/observer/G in player_list) + if(G.ckey == input) + G_found = G + break + + if(!G_found)//If a ghost was not found. to_chat(usr, "There is no active key like that in the game or the person is not currently a ghost.") - return - - if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something - //Check if they were an alien - if(G_found.mind.assigned_role=="Alien") - if(alert("This character appears to have been an alien. Would you like to respawn them as such?",,"Yes","No")=="Yes") - var/turf/T - if(xeno_spawn.len) T = pick(xeno_spawn) - else T = pick(latejoin) - - var/mob/living/carbon/alien/new_xeno - switch(G_found.mind.special_role)//If they have a mind, we can determine which caste they were. - if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(T) - if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(T) - if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(T) - if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(T) - else//If we don't know what special role they have, for whatever reason, or they're a larva. - create_xeno(G_found.ckey) - return - - //Now to give them their mind back. - G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use - new_xeno.key = G_found.key + return + + if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something + //Check if they were an alien + if(G_found.mind.assigned_role=="Alien") + if(alert("This character appears to have been an alien. Would you like to respawn them as such?",,"Yes","No")=="Yes") + var/turf/T + if(xeno_spawn.len) T = pick(xeno_spawn) + else T = pick(latejoin) + + var/mob/living/carbon/alien/new_xeno + switch(G_found.mind.special_role)//If they have a mind, we can determine which caste they were. + if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(T) + if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(T) + if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(T) + if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(T) + else//If we don't know what special role they have, for whatever reason, or they're a larva. + create_xeno(G_found.ckey) + return + + //Now to give them their mind back. + G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use + new_xeno.key = G_found.key to_chat(new_xeno, "You have been fully respawned. Enjoy the game.") - message_admins("[key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.", 1) - return //all done. The ghost is auto-deleted - - //check if they were a monkey - else if(findtext(G_found.real_name,"monkey")) - if(alert("This character appears to have been a monkey. Would you like to respawn them as such?",,"Yes","No")=="Yes") - var/mob/living/carbon/monkey/new_monkey = new(pick(latejoin)) - G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use - new_monkey.key = G_found.key + message_admins("[key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.", 1) + return //all done. The ghost is auto-deleted + + //check if they were a monkey + else if(findtext(G_found.real_name,"monkey")) + if(alert("This character appears to have been a monkey. Would you like to respawn them as such?",,"Yes","No")=="Yes") + var/mob/living/carbon/monkey/new_monkey = new(pick(latejoin)) + G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use + new_monkey.key = G_found.key to_chat(new_monkey, "You have been fully respawned. Enjoy the game.") - message_admins("[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.", 1) - return //all done. The ghost is auto-deleted - - - //Ok, it's not a xeno or a monkey. So, spawn a human. - var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. - - var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character. - if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something - /*Try and locate a record for the person being respawned through data_core. - This isn't an exact science but it does the trick more often than not.*/ - var/id = md5("[G_found.real_name][G_found.mind.assigned_role]") - - record_found = find_record("id", id, data_core.locked) - - if(record_found)//If they have a record we can determine a few things. - new_character.real_name = record_found.fields["name"] - new_character.setGender(record_found.fields["sex"]) - new_character.age = record_found.fields["age"] - new_character.b_type = record_found.fields["b_type"] - else - new_character.setGender(pick(MALE,FEMALE)) - var/datum/preferences/A = new() - A.randomize_appearance_for(new_character) - new_character.real_name = G_found.real_name - - if(!new_character.real_name) - new_character.generate_name() - new_character.name = new_character.real_name - - if(G_found.mind && !G_found.mind.active) - G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use - new_character.mind.special_verbs = list() - else - new_character.mind_initialize() - if(!new_character.mind.assigned_role) new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role. - - //DNA - if(record_found)//Pull up their name from database records if they did have a mind. - new_character.dna = new()//Let's first give them a new DNA. - new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity. - - // I HATE BYOND. HATE. HATE. - N3X - var/list/newSE= record_found.fields["enzymes"] - var/list/newUI = record_found.fields["identity"] - new_character.dna.SE = newSE.Copy() //This is the default of enzymes so I think it's safe to go with. - new_character.dna.UpdateSE() - new_character.UpdateAppearance(newUI.Copy())//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch. - else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile. - new_character.dna.ready_dna(new_character) - - new_character.key = G_found.key - - /* - The code below functions with the assumption that the mob is already a traitor if they have a special role. - So all it does is re-equip the mob with powers and/or items. Or not, if they have no special role. - If they don't have a mind, they obviously don't have a special role. - */ - - //Two variables to properly announce later on. - var/admin = key_name_admin(src) - var/player_key = G_found.key - - //Now for special roles and equipment. - switch(new_character.mind.special_role) - if("traitor") - job_master.EquipRank(new_character, new_character.mind.assigned_role, 1) - ticker.mode.equip_traitor(new_character) - if("Wizard") - new_character.loc = pick(wizardstart) - //ticker.mode.learn_basic_spells(new_character) - ticker.mode.equip_wizard(new_character) - if("Syndicate") - var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") - if(synd_spawn) - new_character.loc = get_turf(synd_spawn) - call(/datum/game_mode/proc/equip_syndicate)(new_character) - if("Death Commando")//Leaves them at late-join spawn. - new_character.equip_death_commando() - new_character.internal = new_character.s_store - new_character.internals.icon_state = "internal1" - else//They may also be a cyborg or AI. - switch(new_character.mind.assigned_role) - if("AI") - new_character = new_character.AIize() - if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/proc/add_law_zero)(new_character) - if("Cyborg")//More rigging to make em' work and check if they're traitor. - new_character = new_character.Robotize() - if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/proc/add_law_zero)(new_character) - //Add aliens. - else - job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them. - - //Announces the character on all the systems, based on the record. - if(!issilicon(new_character))//If they are not a cyborg/AI. - if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway. - //Power to the user! - if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes") - data_core.manifest_inject(new_character) - - if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes") - AnnounceArrival(new_character, new_character.mind.assigned_role) - - - message_admins("[admin] has respawned [player_key] as [new_character.real_name].", 1) - + message_admins("[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.", 1) + return //all done. The ghost is auto-deleted + + + //Ok, it's not a xeno or a monkey. So, spawn a human. + var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. + + var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character. + if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something + /*Try and locate a record for the person being respawned through data_core. + This isn't an exact science but it does the trick more often than not.*/ + var/id = md5("[G_found.real_name][G_found.mind.assigned_role]") + + record_found = find_record("id", id, data_core.locked) + + if(record_found)//If they have a record we can determine a few things. + new_character.real_name = record_found.fields["name"] + new_character.setGender(record_found.fields["sex"]) + new_character.age = record_found.fields["age"] + new_character.b_type = record_found.fields["b_type"] + else + new_character.setGender(pick(MALE,FEMALE)) + var/datum/preferences/A = new() + A.randomize_appearance_for(new_character) + new_character.real_name = G_found.real_name + + if(!new_character.real_name) + new_character.generate_name() + new_character.name = new_character.real_name + + if(G_found.mind && !G_found.mind.active) + G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use + new_character.mind.special_verbs = list() + else + new_character.mind_initialize() + if(!new_character.mind.assigned_role) new_character.mind.assigned_role = "Assistant"//If they somehow got a null assigned role. + + //DNA + if(record_found)//Pull up their name from database records if they did have a mind. + new_character.dna = new()//Let's first give them a new DNA. + new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity. + + // I HATE BYOND. HATE. HATE. - N3X + var/list/newSE= record_found.fields["enzymes"] + var/list/newUI = record_found.fields["identity"] + new_character.dna.SE = newSE.Copy() //This is the default of enzymes so I think it's safe to go with. + new_character.dna.UpdateSE() + new_character.UpdateAppearance(newUI.Copy())//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch. + else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile. + new_character.dna.ready_dna(new_character) + + new_character.key = G_found.key + + /* + The code below functions with the assumption that the mob is already a traitor if they have a special role. + So all it does is re-equip the mob with powers and/or items. Or not, if they have no special role. + If they don't have a mind, they obviously don't have a special role. + */ + + //Two variables to properly announce later on. + var/admin = key_name_admin(src) + var/player_key = G_found.key + + //Now for special roles and equipment. + switch(new_character.mind.special_role) + if("traitor") + job_master.EquipRank(new_character, new_character.mind.assigned_role, 1) + ticker.mode.equip_traitor(new_character) + if("Wizard") + new_character.loc = pick(wizardstart) + //ticker.mode.learn_basic_spells(new_character) + ticker.mode.equip_wizard(new_character) + if("Syndicate") + var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") + if(synd_spawn) + new_character.loc = get_turf(synd_spawn) + call(/datum/game_mode/proc/equip_syndicate)(new_character) + if("Death Commando")//Leaves them at late-join spawn. + new_character.equip_death_commando() + new_character.internal = new_character.s_store + new_character.internals.icon_state = "internal1" + else//They may also be a cyborg or AI. + switch(new_character.mind.assigned_role) + if("AI") + new_character = new_character.AIize() + if(new_character.mind.special_role=="traitor") + call(/datum/game_mode/proc/add_law_zero)(new_character) + if("Cyborg")//More rigging to make em' work and check if they're traitor. + new_character = new_character.Robotize() + if(new_character.mind.special_role=="traitor") + call(/datum/game_mode/proc/add_law_zero)(new_character) + //Add aliens. + else + job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them. + + //Announces the character on all the systems, based on the record. + if(!issilicon(new_character))//If they are not a cyborg/AI. + if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway. + //Power to the user! + if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes") + data_core.manifest_inject(new_character) + + if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes") + AnnounceArrival(new_character, new_character.mind.assigned_role) + + + message_admins("[admin] has respawned [player_key] as [new_character.real_name].", 1) + to_chat(new_character, "You have been fully respawned. Enjoy the game.") - - feedback_add_details("admin_verb","RSPCH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return new_character - -/client/proc/cmd_admin_add_freeform_ai_law() - set category = "Fun" - set name = "Add Custom AI law" - - if(!holder) + + feedback_add_details("admin_verb","RSPCH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return new_character + +/client/proc/cmd_admin_add_freeform_ai_law() + set category = "Fun" + set name = "Add Custom AI law" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null - if(!input) - return - for(var/mob/living/silicon/ai/M in mob_list) - if (M.stat == 2) + return + var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null + if(!input) + return + for(var/mob/living/silicon/ai/M in mob_list) + if (M.stat == 2) to_chat(usr, "Upload failed. No signal is being detected from the AI.") - else if (M.see_in_dark == 0) + else if (M.see_in_dark == 0) to_chat(usr, "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power.") - else - M.add_ion_law(input) - for(var/mob/living/silicon/ai/O in mob_list) + else + M.add_ion_law(input) + for(var/mob/living/silicon/ai/O in mob_list) to_chat(O, "" + input + "...LAWS UPDATED") - - log_admin("Admin [key_name(usr)] has added a new AI law - [input]") - message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]", 1) - - var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No") - if(show_log == "Yes") - command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") + + log_admin("Admin [key_name(usr)] has added a new AI law - [input]") + message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]", 1) + + var/show_log = alert(src, "Show ion message?", "Message", "Yes", "No") + if(show_log == "Yes") + command_alert("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert") to_chat(world, sound('sound/AI/ionstorm.ogg')) - feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list) - set category = "Special Verbs" - set name = "Rejuvenate" - - if(!holder) + feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list) + set category = "Special Verbs" + set name = "Rejuvenate" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - if(!mob) - return - if(!istype(M)) - alert("Cannot revive a ghost") - return - if(config.allow_admin_rev) - M.revive(0) - M.suiciding = 0 - - log_admin("[key_name(usr)] healed / revived [key_name(M)]") - message_admins("Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!", 1) - else - alert("Admin revive disabled") - feedback_add_details("admin_verb","REJU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_create_centcom_report() - set category = "Special Verbs" - set name = "Create Command Report" - - if(!holder) + return + if(!mob) + return + if(!istype(M)) + alert("Cannot revive a ghost") + return + if(config.allow_admin_rev) + M.revive(0) + M.suiciding = 0 + + log_admin("[key_name(usr)] healed / revived [key_name(M)]") + message_admins("Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!", 1) + else + alert("Admin revive disabled") + feedback_add_details("admin_verb","REJU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_create_centcom_report() + set category = "Special Verbs" + set name = "Create Command Report" + + if(!holder) to_chat(src, "Only administrators may use this command.") - return - var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null - var/customname = input(usr, "Pick a title for the report.", "Title") as text|null - if(!input) - return - if(!customname) - customname = "NanoTrasen Update" - for (var/obj/machinery/computer/communications/C in machines) - if(! (C.stat & (BROKEN|NOPOWER) ) ) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc ) - P.name = "'[command_name()] Update.'" - P.info = input - P.update_icon() - C.messagetitle.Add("[command_name()] Update") - C.messagetext.Add(P.info) - - switch(alert("Should this be announced to the general population?",,"Yes","No")) - if("Yes") - command_alert(input, customname); - if("No") + return + var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null + var/customname = input(usr, "Pick a title for the report.", "Title") as text|null + if(!input) + return + if(!customname) + customname = "NanoTrasen Update" + for (var/obj/machinery/computer/communications/C in machines) + if(! (C.stat & (BROKEN|NOPOWER) ) ) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc ) + P.name = "'[command_name()] Update.'" + P.info = input + P.update_icon() + C.messagetitle.Add("[command_name()] Update") + C.messagetext.Add(P.info) + + switch(alert("Should this be announced to the general population?",,"Yes","No")) + if("Yes") + command_alert(input, customname); + if("No") to_chat(world, "New NanoTrasen Update available at all communication consoles.") - + to_chat(world, sound('sound/AI/commandreport.ogg')) - log_admin("[key_name(src)] has created a command report: [input]") - message_admins("[key_name_admin(src)] has created a command report", 1) - feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in world) - set category = "Admin" - set name = "Delete" - - if (!holder) + log_admin("[key_name(src)] has created a command report: [input]") + message_admins("[key_name_admin(src)] has created a command report", 1) + feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in world) + set category = "Admin" + set name = "Delete" + + if (!holder) to_chat(src, "Only administrators may use this command.") - return - - if (alert(src, "Are you sure you want to delete:\n[O]\nat ([O.x], [O.y], [O.z])?", "Confirmation", "Yes", "No") == "Yes") - log_admin("[key_name(usr)] deleted [O] at ([O.x],[O.y],[O.z])") - message_admins("[key_name_admin(usr)] deleted [O] at ([O.x],[O.y],[O.z])", 1) - feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - if(istype(O,/turf)) - var/turf/T=O - T.ChangeTurf(get_base_turf(T.z)) - else - qdel(O) - -/client/proc/cmd_admin_list_open_jobs() - set category = "Admin" - set name = "List free slots" - - if (!holder) + return + + if (alert(src, "Are you sure you want to delete:\n[O]\nat ([O.x], [O.y], [O.z])?", "Confirmation", "Yes", "No") == "Yes") + log_admin("[key_name(usr)] deleted [O] at ([O.x],[O.y],[O.z])") + message_admins("[key_name_admin(usr)] deleted [O] at ([O.x],[O.y],[O.z])", 1) + feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + if(istype(O,/turf)) + var/turf/T=O + T.ChangeTurf(get_base_turf(T.z)) + else + qdel(O) + +/client/proc/cmd_admin_list_open_jobs() + set category = "Admin" + set name = "List free slots" + + if (!holder) to_chat(src, "Only administrators may use this command.") - return - if(job_master) - for(var/datum/job/job in job_master.occupations) + return + if(job_master) + for(var/datum/job/job in job_master.occupations) to_chat(src, "[job.title]: [job.total_positions]") - feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world) - set category = "Special Verbs" - set name = "Explosion" - - if(!check_rights(R_DEBUG|R_FUN)) return - - var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null - if(devastation == null) return - var/heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null - if(heavy == null) return - var/light = input("Range of light impact. -1 to none", text("Input")) as num|null - if(light == null) return - var/flash = input("Range of flash. -1 to none", text("Input")) as num|null - if(flash == null) return - - if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1)) - if ((devastation > 20) || (heavy > 20) || (light > 20)) - if (alert(src, "Are you sure you want to do this? It will laaag.", "Confirmation", "Yes", "No") == "No") - return - - explosion(O, devastation, heavy, light, flash) - log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flash]) at ([O.x],[O.y],[O.z])") - message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flash]) at ([O.x],[O.y],[O.z])", 1) - feedback_add_details("admin_verb","EXPL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - else - return - -/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world) - set category = "Special Verbs" - set name = "EM Pulse" - - if(!check_rights(R_DEBUG|R_FUN)) return - - var/heavy = input("Range of heavy pulse.", text("Input")) as num|null - if(heavy == null) return - var/light = input("Range of light pulse.", text("Input")) as num|null - if(light == null) return - - if (heavy || light) - - empulse(O, heavy, light) - log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])") - message_admins("[key_name_admin(usr)] created an EM PUlse ([heavy],[light]) at ([O.x],[O.y],[O.z])", 1) - feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - return - else - return - -/client/proc/cmd_admin_gib(mob/M as mob in mob_list) - set category = "Special Verbs" - set name = "Gib" - - if(!check_rights(R_ADMIN|R_FUN)) return - - var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") - if(confirm != "Yes") return - //Due to the delay here its easy for something to have happened to the mob - if(!M) return - - log_admin("[key_name(usr)] has gibbed [key_name(M)]") - message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(M)]", 1) - - if(istype(M, /mob/dead/observer)) - gibs(M.loc, M.viruses) - return - - M.gib() - feedback_add_details("admin_verb","GIB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_gib_self() - set name = "Gibself" - set category = "Fun" - - var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") - if(confirm == "Yes") - if (istype(mob, /mob/dead/observer)) // so they don't spam gibs everywhere - return - else - mob.gib() - - log_admin("[key_name(usr)] used gibself.") - message_admins("[key_name_admin(usr)] used gibself.", 1) - feedback_add_details("admin_verb","GIBS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/* -/client/proc/cmd_manual_ban() - set name = "Manual Ban" - set category = "Special Verbs" - if(!authenticated || !holder) + feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world) + set category = "Special Verbs" + set name = "Explosion" + + if(!check_rights(R_DEBUG|R_FUN)) return + + var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null + if(devastation == null) return + var/heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null + if(heavy == null) return + var/light = input("Range of light impact. -1 to none", text("Input")) as num|null + if(light == null) return + var/flash = input("Range of flash. -1 to none", text("Input")) as num|null + if(flash == null) return + + if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1)) + if ((devastation > 20) || (heavy > 20) || (light > 20)) + if (alert(src, "Are you sure you want to do this? It will laaag.", "Confirmation", "Yes", "No") == "No") + return + + explosion(O, devastation, heavy, light, flash) + log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flash]) at ([O.x],[O.y],[O.z])") + message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flash]) at ([O.x],[O.y],[O.z])", 1) + feedback_add_details("admin_verb","EXPL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + else + return + +/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world) + set category = "Special Verbs" + set name = "EM Pulse" + + if(!check_rights(R_DEBUG|R_FUN)) return + + var/heavy = input("Range of heavy pulse.", text("Input")) as num|null + if(heavy == null) return + var/light = input("Range of light pulse.", text("Input")) as num|null + if(light == null) return + + if (heavy || light) + + empulse(O, heavy, light) + log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])") + message_admins("[key_name_admin(usr)] created an EM PUlse ([heavy],[light]) at ([O.x],[O.y],[O.z])", 1) + feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + return + else + return + +/client/proc/cmd_admin_gib(mob/M as mob in mob_list) + set category = "Special Verbs" + set name = "Gib" + + if(!check_rights(R_ADMIN|R_FUN)) return + + var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") + if(confirm != "Yes") return + //Due to the delay here its easy for something to have happened to the mob + if(!M) return + + log_admin("[key_name(usr)] has gibbed [key_name(M)]") + message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(M)]", 1) + + if(istype(M, /mob/dead/observer)) + gibs(M.loc, M.viruses) + return + + M.gib() + feedback_add_details("admin_verb","GIB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_gib_self() + set name = "Gibself" + set category = "Fun" + + var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") + if(confirm == "Yes") + if (istype(mob, /mob/dead/observer)) // so they don't spam gibs everywhere + return + else + mob.gib() + + log_admin("[key_name(usr)] used gibself.") + message_admins("[key_name_admin(usr)] used gibself.", 1) + feedback_add_details("admin_verb","GIBS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/* +/client/proc/cmd_manual_ban() + set name = "Manual Ban" + set category = "Special Verbs" + if(!authenticated || !holder) to_chat(src, "Only administrators may use this command.") - return - var/mob/M = null - switch(alert("How would you like to ban someone today?", "Manual Ban", "Key List", "Enter Manually", "Cancel")) - if("Key List") - var/list/keys = list() - for(var/mob/M in world) - keys += M.client - var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in keys - if(!selection) - return - M = selection:mob - if ((M.client && M.client.holder && (M.client.holder.level >= holder.level))) - alert("You cannot perform this action. You must be of a higher administrative rank!") - return - - switch(alert("Temporary Ban?",,"Yes","No")) - if("Yes") - var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num - if(!mins) - return - if(mins >= 525600) mins = 525599 - var/reason = input(usr,"Reason?","reason","Griefer") as text - if(!reason) - return - if(M) - AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins) + return + var/mob/M = null + switch(alert("How would you like to ban someone today?", "Manual Ban", "Key List", "Enter Manually", "Cancel")) + if("Key List") + var/list/keys = list() + for(var/mob/M in world) + keys += M.client + var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in keys + if(!selection) + return + M = selection:mob + if ((M.client && M.client.holder && (M.client.holder.level >= holder.level))) + alert("You cannot perform this action. You must be of a higher administrative rank!") + return + + switch(alert("Temporary Ban?",,"Yes","No")) + if("Yes") + var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num + if(!mins) + return + if(mins >= 525600) mins = 525599 + var/reason = input(usr,"Reason?","reason","Griefer") as text + if(!reason) + return + if(M) + AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins) to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") to_chat(M, "This is a temporary ban, it will be removed in [mins] minutes.") - to_chat(M, "To try to resolve this matter head to http:)//ss13.donglabs.com/forum/" + to_chat(M, "To try to resolve this matter head to http:)//ss13.donglabs.com/forum/" - log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") - world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=[mins]&server=[replacetext(config.server_name, "#", "")]") - del(M.client) - del(M) - else - - if("No") - var/reason = input(usr,"Reason?","reason","Griefer") as text - if(!reason) - return - AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0) + log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.") + world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=[mins]&server=[replacetext(config.server_name, "#", "")]") + del(M.client) + del(M) + else + + if("No") + var/reason = input(usr,"Reason?","reason","Griefer") as text + if(!reason) + return + AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0) to_chat(M, "You have been banned by [usr.client.ckey].\nReason: [reason].") to_chat(M, "This is a permanent ban.") - to_chat(M, "To try to resolve this matter head to http:)//ss13.donglabs.com/forum/" + to_chat(M, "To try to resolve this matter head to http:)//ss13.donglabs.com/forum/" - log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") - message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") - world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=perma&server=[replacetext(config.server_name, "#", "")]") - del(M.client) - del(M) -*/ - -/client/proc/update_world() - // If I see anyone granting powers to specific keys like the code that was here, - // I will both remove their SVN access and permanently ban them from my servers. - return - -/client/proc/cmd_admin_check_contents(mob/living/L as mob in mob_list) - set category = "Special Verbs" - set name = "Check Mob Contents" - - for (var/content in get_contents_in_object(L)) - if (content) + log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") + message_admins("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.") + world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=perma&server=[replacetext(config.server_name, "#", "")]") + del(M.client) + del(M) +*/ + +/client/proc/update_world() + // If I see anyone granting powers to specific keys like the code that was here, + // I will both remove their SVN access and permanently ban them from my servers. + return + +/client/proc/cmd_admin_check_contents(mob/living/L as mob in mob_list) + set category = "Special Verbs" + set name = "Check Mob Contents" + + for (var/content in get_contents_in_object(L)) + if (content) to_chat(usr, "\icon[content] [content]") - - feedback_add_details("admin_verb","CC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/* This proc is DEFERRED. Does not do anything. -/client/proc/cmd_admin_remove_plasma() - set category = "Debug" - set name = "Stabilize Atmos." - if(!holder) + + feedback_add_details("admin_verb","CC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/* This proc is DEFERRED. Does not do anything. +/client/proc/cmd_admin_remove_plasma() + set category = "Debug" + set name = "Stabilize Atmos." + if(!holder) to_chat(src, "Only administrators may use this command.") - return - feedback_add_details("admin_verb","STATM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -// DEFERRED - spawn(0) - for(var/turf/T in view()) - T.poison = 0 - T.oldpoison = 0 - T.tmppoison = 0 - T.oxygen = 755985 - T.oldoxy = 755985 - T.tmpoxy = 755985 - T.co2 = 14.8176 - T.oldco2 = 14.8176 - T.tmpco2 = 14.8176 - T.n2 = 2.844e+006 - T.on2 = 2.844e+006 - T.tn2 = 2.844e+006 - T.tsl_gas = 0 - T.osl_gas = 0 - T.sl_gas = 0 - T.temp = 293.15 - T.otemp = 293.15 - T.ttemp = 293.15 -*/ - -/client/proc/toggle_view_range() - set category = "Special Verbs" - set name = "Change View Range" - set desc = "switches between 1x and custom views" - - if(view == world.view) - view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128) - else - view = world.view - - log_admin("[key_name(usr)] changed their view range to [view].") - //message_admins("[key_name_admin(usr)] changed their view range to [view].", 1) //why? removed by order of XSI - - feedback_add_details("admin_verb","CVRA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/admin_call_shuttle() - set category = "Admin" - set name = "Call Shuttle" - - if ((!( ticker ) || emergency_shuttle.location)) - return - - if(!check_rights(R_ADMIN)) return - - var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") - if(confirm != "Yes") return - - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "confliction") - var/choice = input("The shuttle will just return if you call it. Call anyway?") in list("Confirm", "Cancel") - if(choice == "Confirm") - emergency_shuttle.fake_recall = rand(300,500) - else - return - - emergency_shuttle.incall() - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") + return + feedback_add_details("admin_verb","STATM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +// DEFERRED + spawn(0) + for(var/turf/T in view()) + T.poison = 0 + T.oldpoison = 0 + T.tmppoison = 0 + T.oxygen = 755985 + T.oldoxy = 755985 + T.tmpoxy = 755985 + T.co2 = 14.8176 + T.oldco2 = 14.8176 + T.tmpco2 = 14.8176 + T.n2 = 2.844e+006 + T.on2 = 2.844e+006 + T.tn2 = 2.844e+006 + T.tsl_gas = 0 + T.osl_gas = 0 + T.sl_gas = 0 + T.temp = 293.15 + T.otemp = 293.15 + T.ttemp = 293.15 +*/ + +/client/proc/toggle_view_range() + set category = "Special Verbs" + set name = "Change View Range" + set desc = "switches between 1x and custom views" + + if(view == world.view) + view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128) + else + view = world.view + + log_admin("[key_name(usr)] changed their view range to [view].") + //message_admins("[key_name_admin(usr)] changed their view range to [view].", 1) //why? removed by order of XSI + + feedback_add_details("admin_verb","CVRA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/admin_call_shuttle() + set category = "Admin" + set name = "Call Shuttle" + + if ((!( ticker ) || emergency_shuttle.location)) + return + + if(!check_rights(R_ADMIN)) return + + var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No") + if(confirm != "Yes") return + + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || ticker.mode.name == "confliction") + var/choice = input("The shuttle will just return if you call it. Call anyway?") in list("Confirm", "Cancel") + if(choice == "Confirm") + emergency_shuttle.fake_recall = rand(300,500) + else + return + + emergency_shuttle.incall() + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") to_chat(world, sound('sound/AI/shuttlecalled.ogg')) - feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] admin-called the emergency shuttle.") - message_admins("[key_name_admin(usr)] admin-called the emergency shuttle.", 1) - return - -/client/proc/admin_cancel_shuttle() - set category = "Admin" - set name = "Cancel Shuttle" - - if(!check_rights(R_ADMIN)) return - - if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return - - if(!ticker || emergency_shuttle.location || emergency_shuttle.direction == 0) - return - - emergency_shuttle.recall() - feedback_add_details("admin_verb","CCSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] admin-recalled the emergency shuttle.") - message_admins("[key_name_admin(usr)] admin-recalled the emergency shuttle.", 1) - - return - -/client/proc/admin_deny_shuttle() - set category = "Admin" - set name = "Toggle Deny Shuttle" - - if (!ticker) - return - - if(!check_rights(R_ADMIN)) return - - emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle - - log_admin("[key_name(src)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.") - message_admins("[key_name_admin(usr)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.") - -/client/proc/cmd_admin_attack_log(mob/M as mob in mob_list) - set category = "Special Verbs" - set name = "Attack Log" - + feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] admin-called the emergency shuttle.") + message_admins("[key_name_admin(usr)] admin-called the emergency shuttle.", 1) + return + +/client/proc/admin_cancel_shuttle() + set category = "Admin" + set name = "Cancel Shuttle" + + if(!check_rights(R_ADMIN)) return + + if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return + + if(!ticker || emergency_shuttle.location || emergency_shuttle.direction == 0) + return + + emergency_shuttle.recall() + feedback_add_details("admin_verb","CCSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] admin-recalled the emergency shuttle.") + message_admins("[key_name_admin(usr)] admin-recalled the emergency shuttle.", 1) + + return + +/client/proc/admin_deny_shuttle() + set category = "Admin" + set name = "Toggle Deny Shuttle" + + if (!ticker) + return + + if(!check_rights(R_ADMIN)) return + + emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle + + log_admin("[key_name(src)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.") + message_admins("[key_name_admin(usr)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.") + +/client/proc/cmd_admin_attack_log(mob/M as mob in mob_list) + set category = "Special Verbs" + set name = "Attack Log" + to_chat(usr, text("Attack Log for []", mob)) - for(var/t in M.attack_log) + for(var/t in M.attack_log) to_chat(usr, t) - feedback_add_details("admin_verb","ATTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/everyone_random() - set category = "Fun" - set name = "Make Everyone Random" - set desc = "Make everyone have a random appearance. You can only use this before rounds!" - - if(!check_rights(R_FUN)) return - - if (ticker && ticker.mode) + feedback_add_details("admin_verb","ATTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/everyone_random() + set category = "Fun" + set name = "Make Everyone Random" + set desc = "Make everyone have a random appearance. You can only use this before rounds!" + + if(!check_rights(R_FUN)) return + + if (ticker && ticker.mode) to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!") - return - - if(ticker.random_players) - ticker.random_players = 0 - message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.", 1) + return + + if(ticker.random_players) + ticker.random_players = 0 + message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.", 1) to_chat(usr, "Disabled.") - return - - - var/notifyplayers = alert(src, "Do you want to notify the players?", "Options", "Yes", "No", "Cancel") - if(notifyplayers == "Cancel") - return - - log_admin("Admin [key_name(src)] has forced the players to have random appearances.") - message_admins("Admin [key_name_admin(usr)] has forced the players to have random appearances.", 1) - - if(notifyplayers == "Yes") + return + + + var/notifyplayers = alert(src, "Do you want to notify the players?", "Options", "Yes", "No", "Cancel") + if(notifyplayers == "Cancel") + return + + log_admin("Admin [key_name(src)] has forced the players to have random appearances.") + message_admins("Admin [key_name_admin(usr)] has forced the players to have random appearances.", 1) + + if(notifyplayers == "Yes") to_chat(world, "Admin [usr.key] has forced the players to have completely random identities!") - + to_chat(usr, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.") - - ticker.random_players = 1 - feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/toggle_random_events() - set category = "Server" - set name = "Toggle random events on/off" - set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off" - - if(!check_rights(R_SERVER)) return - - if(!config.allow_random_events) - config.allow_random_events = 1 + + ticker.random_players = 1 + feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/toggle_random_events() + set category = "Server" + set name = "Toggle random events on/off" + set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off" + + if(!check_rights(R_SERVER)) return + + if(!config.allow_random_events) + config.allow_random_events = 1 to_chat(usr, "Random events enabled") - message_admins("Admin [key_name_admin(usr)] has enabled random events.", 1) - else - config.allow_random_events = 0 + message_admins("Admin [key_name_admin(usr)] has enabled random events.", 1) + else + config.allow_random_events = 0 to_chat(usr, "Random events disabled") - message_admins("Admin [key_name_admin(usr)] has disabled random events.", 1) - feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + message_admins("Admin [key_name_admin(usr)] has disabled random events.", 1) + feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index a4f82ac30f8..f09ed1f4b35 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -1,176 +1,176 @@ -//STRIKE TEAMS - -var/const/commandos_possible = 6 //if more Commandos are needed in the future -var/global/sent_strike_team = 0 - -/client/proc/strike_team() - if(!ticker) +//STRIKE TEAMS + +var/const/commandos_possible = 6 //if more Commandos are needed in the future +var/global/sent_strike_team = 0 + +/client/proc/strike_team() + if(!ticker) to_chat(usr, "The game hasn't started yet!") - return - if(world.time < 6000) + return + if(world.time < 6000) to_chat(usr, "There are [(6000-world.time)/10] seconds remaining before it may be called.") - return - if(sent_strike_team == 1) + return + if(sent_strike_team == 1) to_chat(usr, "CentCom is already sending a team.") - return - if(alert("Do you want to send in the CentCom death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes") - return - alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned commandos have internals cameras which are viewable through a monitor inside the Spec. Ops. Office. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.") - - var/input = null - while(!input) - input = copytext(sanitize(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", "")),1,MAX_MESSAGE_LEN) - if(!input) - if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") - return - - if(sent_strike_team) + return + if(alert("Do you want to send in the CentCom death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes") + return + alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned commandos have internals cameras which are viewable through a monitor inside the Spec. Ops. Office. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.") + + var/input = null + while(!input) + input = copytext(sanitize(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", "")),1,MAX_MESSAGE_LEN) + if(!input) + if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") + return + + if(sent_strike_team) to_chat(usr, "Looks like someone beat you to it.") - return - - sent_strike_team = 1 - - if (emergency_shuttle.direction == 1 && emergency_shuttle.online == 1) - emergency_shuttle.recall() - - var/commando_number = commandos_possible //for selecting a leader - var/leader_selected = 0 //when the leader is chosen. The last person spawned. - -//Code for spawning a nuke auth code. - var/nuke_code - var/temp_code - for(var/obj/machinery/nuclearbomb/N in machines) - temp_code = text2num(N.r_code) - if(temp_code)//if it's actually a number. It won't convert any non-numericals. - nuke_code = N.r_code - break - -//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. - var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world. - var/list/commandos = list() //actual commando ghosts as picked by the user. - for(var/mob/dead/observer/G in player_list) - if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list. - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G.key - for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected. - var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate. - candidates -= candidate //Subtract from candidates. - commandos += candidate//Add their ghost to commandos. - -//Spawns commandos and equips them. - for(var/obj/effect/landmark/L in landmarks_list) - if(commando_number<=0) break - if (L.name == "Commando") - leader_selected = commando_number == 1?1:0 - - var/mob/living/carbon/human/new_commando = create_death_commando(L, leader_selected) - - if(commandos.len) - new_commando.key = pick(commandos) - commandos -= new_commando.key - new_commando.internal = new_commando.s_store - new_commando.internals.icon_state = "internal1" - - //So they don't forget their code or mission. - if(nuke_code) - new_commando.mind.store_memory("Nuke Code: [nuke_code].") - new_commando.mind.store_memory("Mission: [input].") - + return + + sent_strike_team = 1 + + if (emergency_shuttle.direction == 1 && emergency_shuttle.online == 1) + emergency_shuttle.recall() + + var/commando_number = commandos_possible //for selecting a leader + var/leader_selected = 0 //when the leader is chosen. The last person spawned. + +//Code for spawning a nuke auth code. + var/nuke_code + var/temp_code + for(var/obj/machinery/nuclearbomb/N in machines) + temp_code = text2num(N.r_code) + if(temp_code)//if it's actually a number. It won't convert any non-numericals. + nuke_code = N.r_code + break + +//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. + var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world. + var/list/commandos = list() //actual commando ghosts as picked by the user. + for(var/mob/dead/observer/G in player_list) + if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list. + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + candidates += G.key + for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected. + var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate. + candidates -= candidate //Subtract from candidates. + commandos += candidate//Add their ghost to commandos. + +//Spawns commandos and equips them. + for(var/obj/effect/landmark/L in landmarks_list) + if(commando_number<=0) break + if (L.name == "Commando") + leader_selected = commando_number == 1?1:0 + + var/mob/living/carbon/human/new_commando = create_death_commando(L, leader_selected) + + if(commandos.len) + new_commando.key = pick(commandos) + commandos -= new_commando.key + new_commando.internal = new_commando.s_store + new_commando.internals.icon_state = "internal1" + + //So they don't forget their code or mission. + if(nuke_code) + new_commando.mind.store_memory("Nuke Code: [nuke_code].") + new_commando.mind.store_memory("Mission: [input].") + to_chat(new_commando, "You are a Special Ops. [!leader_selected?"commando":"LEADER"] in the service of Central Command. Check the table ahead for detailed instructions.\nYour current mission is: [input]") - - commando_number-- - -//Spawns the rest of the commando gear. - for (var/obj/effect/landmark/L in landmarks_list) - if (L.name == "Commando_Manual") - //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) - var/obj/item/weapon/paper/P = new(L.loc) - P.info = "

    Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
    #1 Work as a team.
    #2 Accomplish your objective at all costs.
    #3 Leave no witnesses.
    You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
    If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

    In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

    Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission 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 device functional:
    #1 Place bomb in designated detonation zone
    #2 Extend and anchor bomb (attack with hand).
    #3 Insert Nuclear Auth. Disk into slot.
    #4 Type numeric code into keypad ([nuke_code]).
    Note: If you make a mistake press R to reset the device.
    #5 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 have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
    Note: Toggle off the SAFETY.
    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.

    The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

    Good luck, soldier!

    " - P.name = "Spec. Ops. Manual" - - for (var/obj/effect/landmark/L in landmarks_list) - if (L.name == "Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) - del(L) - - message_admins("[key_name_admin(usr)] has spawned a CentCom strike squad.", 1) - log_admin("[key_name(usr)] used Spawn Death Squad.") - return 1 - -/client/proc/create_death_commando(obj/spawn_location, leader_selected = 0) - var/mob/living/carbon/human/new_commando = new(spawn_location.loc) - var/commando_leader_rank = pick("Lieutenant", "Captain", "Major") - var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") - var/commando_name = pick(last_names) - - new_commando.gender = pick(MALE, FEMALE) - - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_commando) - - new_commando.real_name = "[!leader_selected ? commando_rank : commando_leader_rank] [commando_name]" - new_commando.age = !leader_selected ? rand(23,35) : rand(35,45) - - new_commando.dna.ready_dna(new_commando)//Creates DNA. - - //Creates mind stuff. - new_commando.mind_initialize() - new_commando.mind.assigned_role = "MODE" - new_commando.mind.special_role = "Death Commando" - ticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list. - new_commando.equip_death_commando(leader_selected) - - ticker.mode.deathsquad += new_commando.mind - return new_commando - -/mob/living/carbon/human/proc/equip_death_commando(leader_selected = 0) - - - equip_to_slot_or_del(new /obj/item/device/radio/headset/deathsquad(src), slot_ears) - - if (leader_selected == 0) - equip_to_slot_or_del(new /obj/item/clothing/under/color/green(src), slot_w_uniform) - else - equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/deathsquad(src), slot_shoes) - equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/deathsquad(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/deathsquad(src), slot_head) - equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask) - equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) - - equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/ammo_storage/box/a357(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/shield/energy(src), slot_in_backpack) - if (!leader_selected) - equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) - else - equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double(src), slot_s_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(src), slot_belt) - - equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) - - - var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)//Here you go Deuryn - L.imp_in = src - L.implanted = 1 - - - - var/obj/item/weapon/card/id/W = new(src) - W.name = "[real_name]'s ID Card" - W.icon_state = "centcom" - W.access = get_centcom_access("Death Commando") - W.icon_state = "deathsquad" - W.assignment = "Death Commando" - W.registered_name = real_name - equip_to_slot_or_del(W, slot_wear_id) - + + commando_number-- + +//Spawns the rest of the commando gear. + for (var/obj/effect/landmark/L in landmarks_list) + if (L.name == "Commando_Manual") + //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) + var/obj/item/weapon/paper/P = new(L.loc) + P.info = "

    Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
    #1 Work as a team.
    #2 Accomplish your objective at all costs.
    #3 Leave no witnesses.
    You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
    If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

    In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

    Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission 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 device functional:
    #1 Place bomb in designated detonation zone
    #2 Extend and anchor bomb (attack with hand).
    #3 Insert Nuclear Auth. Disk into slot.
    #4 Type numeric code into keypad ([nuke_code]).
    Note: If you make a mistake press R to reset the device.
    #5 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 have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
    Note: Toggle off the SAFETY.
    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.

    The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

    Good luck, soldier!

    " + P.name = "Spec. Ops. Manual" + + for (var/obj/effect/landmark/L in landmarks_list) + if (L.name == "Commando-Bomb") + new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) + del(L) + + message_admins("[key_name_admin(usr)] has spawned a CentCom strike squad.", 1) + log_admin("[key_name(usr)] used Spawn Death Squad.") + return 1 + +/client/proc/create_death_commando(obj/spawn_location, leader_selected = 0) + var/mob/living/carbon/human/new_commando = new(spawn_location.loc) + var/commando_leader_rank = pick("Lieutenant", "Captain", "Major") + var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") + var/commando_name = pick(last_names) + + new_commando.gender = pick(MALE, FEMALE) + + var/datum/preferences/A = new()//Randomize appearance for the commando. + A.randomize_appearance_for(new_commando) + + new_commando.real_name = "[!leader_selected ? commando_rank : commando_leader_rank] [commando_name]" + new_commando.age = !leader_selected ? rand(23,35) : rand(35,45) + + new_commando.dna.ready_dna(new_commando)//Creates DNA. + + //Creates mind stuff. + new_commando.mind_initialize() + new_commando.mind.assigned_role = "MODE" + new_commando.mind.special_role = "Death Commando" + ticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list. + new_commando.equip_death_commando(leader_selected) + + ticker.mode.deathsquad += new_commando.mind + return new_commando + +/mob/living/carbon/human/proc/equip_death_commando(leader_selected = 0) + + + equip_to_slot_or_del(new /obj/item/device/radio/headset/deathsquad(src), slot_ears) + + if (leader_selected == 0) + equip_to_slot_or_del(new /obj/item/clothing/under/color/green(src), slot_w_uniform) + else + equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform) + equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/deathsquad(src), slot_shoes) + equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/deathsquad(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/deathsquad(src), slot_head) + equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(src), slot_wear_mask) + equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) + + equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) + equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack) + + equip_to_slot_or_del(new /obj/item/ammo_storage/box/a357(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/shield/energy(src), slot_in_backpack) + if (!leader_selected) + equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) + else + equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack) + + equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store) + equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen/double(src), slot_s_store) + equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(src), slot_belt) + + equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) + + + var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)//Here you go Deuryn + L.imp_in = src + L.implanted = 1 + + + + var/obj/item/weapon/card/id/W = new(src) + W.name = "[real_name]'s ID Card" + W.icon_state = "centcom" + W.access = get_centcom_access("Death Commando") + W.icon_state = "deathsquad" + W.assignment = "Death Commando" + W.registered_name = real_name + equip_to_slot_or_del(W, slot_wear_id) + return 1 \ No newline at end of file diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index b215fd9ab61..81ad54042ae 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -1,180 +1,180 @@ -//STRIKE TEAMS - -var/const/syndicate_commandos_possible = 6 //if more Commandos are needed in the future -var/global/sent_syndicate_strike_team = 0 -/client/proc/syndicate_strike_team() - set category = "Fun" - set name = "Spawn Syndicate Strike Team" - set desc = "Spawns a squad of commandos in the Syndicate Mothership if you want to run an admin event." - - if(!src.holder) +//STRIKE TEAMS + +var/const/syndicate_commandos_possible = 6 //if more Commandos are needed in the future +var/global/sent_syndicate_strike_team = 0 +/client/proc/syndicate_strike_team() + set category = "Fun" + set name = "Spawn Syndicate Strike Team" + set desc = "Spawns a squad of commandos in the Syndicate Mothership if you want to run an admin event." + + if(!src.holder) to_chat(src, "Only administrators may use this command.") - return - if(!ticker) - alert("The game hasn't started yet!") - return -// if(world.time < 6000) -// alert("Not so fast, buddy. Wait a few minutes until the game gets going. There are [(6000-world.time)/10] seconds remaining.") -// return - if(sent_syndicate_strike_team == 1) - alert("The Syndicate are already sending a team, Mr. Dumbass.") - return - if(alert("Do you want to send in the Syndicate Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No") - return - alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned syndicates have internals cameras which are viewable through a monitor inside the Syndicate Mothership Bridge. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.") - - var/input = null - while(!input) - input = copytext(sanitize(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", "")),1,MAX_MESSAGE_LEN) - if(!input) - if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") - return - - if(sent_syndicate_strike_team) + return + if(!ticker) + alert("The game hasn't started yet!") + return +// if(world.time < 6000) +// alert("Not so fast, buddy. Wait a few minutes until the game gets going. There are [(6000-world.time)/10] seconds remaining.") +// return + if(sent_syndicate_strike_team == 1) + alert("The Syndicate are already sending a team, Mr. Dumbass.") + return + if(alert("Do you want to send in the Syndicate Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No") + return + alert("This 'mode' will go on until everyone is dead or the station is destroyed. You may also admin-call the evac shuttle when appropriate. Spawned syndicates have internals cameras which are viewable through a monitor inside the Syndicate Mothership Bridge. Assigning the team's detailed task is recommended from there. While you will be able to manually pick the candidates from active ghosts, their assignment in the squad will be random.") + + var/input = null + while(!input) + input = copytext(sanitize(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", "")),1,MAX_MESSAGE_LEN) + if(!input) + if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") + return + + if(sent_syndicate_strike_team) to_chat(src, "Looks like someone beat you to it.") - return - - sent_syndicate_strike_team = 1 - - if (emergency_shuttle.direction == 1 && emergency_shuttle.online == 1) - emergency_shuttle.recall() - - var/syndicate_commando_number = syndicate_commandos_possible //for selecting a leader - var/syndicate_leader_selected = 0 //when the leader is chosen. The last person spawned. - -//Code for spawning a nuke auth code. - var/nuke_code - var/temp_code - for(var/obj/machinery/nuclearbomb/N in machines) - temp_code = text2num(N.r_code) - if(temp_code)//if it's actually a number. It won't convert any non-numericals. - nuke_code = N.r_code - break - -//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. - var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world. - var/list/commandos = list() //actual commando ghosts as picked by the user. - for(var/mob/dead/observer/G in player_list) - if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list. - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G.key - for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected. - var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate. - candidates -= candidate //Subtract from candidates. - commandos += candidate//Add their ghost to commandos. - -//Spawns commandos and equips them. - for(var/obj/effect/landmark/L in landmarks_list) - if(syndicate_commando_number<=0) break - if (L.name == "Syndicate-Commando") - syndicate_leader_selected = syndicate_commando_number == 1?1:0 - - var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - - if(commandos.len) - new_syndicate_commando.key = pick(commandos) - commandos -= new_syndicate_commando.key - new_syndicate_commando.internal = new_syndicate_commando.s_store - new_syndicate_commando.internals.icon_state = "internal1" - - //So they don't forget their code or mission. - if(nuke_code) - new_syndicate_commando.mind.store_memory("Nuke Code: [nuke_code].") - new_syndicate_commando.mind.store_memory("Mission: [input].") - + return + + sent_syndicate_strike_team = 1 + + if (emergency_shuttle.direction == 1 && emergency_shuttle.online == 1) + emergency_shuttle.recall() + + var/syndicate_commando_number = syndicate_commandos_possible //for selecting a leader + var/syndicate_leader_selected = 0 //when the leader is chosen. The last person spawned. + +//Code for spawning a nuke auth code. + var/nuke_code + var/temp_code + for(var/obj/machinery/nuclearbomb/N in machines) + temp_code = text2num(N.r_code) + if(temp_code)//if it's actually a number. It won't convert any non-numericals. + nuke_code = N.r_code + break + +//Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. + var/list/candidates = list() //candidates for being a commando out of all the active ghosts in world. + var/list/commandos = list() //actual commando ghosts as picked by the user. + for(var/mob/dead/observer/G in player_list) + if(!G.client.holder && !G.client.is_afk()) //Whoever called/has the proc won't be added to the list. + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + candidates += G.key + for(var/i=commandos_possible,(i>0&&candidates.len),i--)//Decrease with every commando selected. + var/candidate = input("Pick characters to spawn as the commandos. This will go on until there either no more ghosts to pick from or the slots are full.", "Active Players") as null|anything in candidates //It will auto-pick a person when there is only one candidate. + candidates -= candidate //Subtract from candidates. + commandos += candidate//Add their ghost to commandos. + +//Spawns commandos and equips them. + for(var/obj/effect/landmark/L in landmarks_list) + if(syndicate_commando_number<=0) break + if (L.name == "Syndicate-Commando") + syndicate_leader_selected = syndicate_commando_number == 1?1:0 + + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) + + if(commandos.len) + new_syndicate_commando.key = pick(commandos) + commandos -= new_syndicate_commando.key + new_syndicate_commando.internal = new_syndicate_commando.s_store + new_syndicate_commando.internals.icon_state = "internal1" + + //So they don't forget their code or mission. + if(nuke_code) + new_syndicate_commando.mind.store_memory("Nuke Code: [nuke_code].") + new_syndicate_commando.mind.store_memory("Mission: [input].") + to_chat(new_syndicate_commando, "You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: [input]") - - syndicate_commando_number-- - -//Spawns the rest of the commando gear. -// for (var/obj/effect/landmark/L) - // if (L.name == "Commando_Manual") - //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) - // var/obj/item/weapon/paper/P = new(L.loc) - // P.info = "

    Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
    #1 Work as a team.
    #2 Accomplish your objective at all costs.
    #3 Leave no witnesses.
    You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
    If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

    In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

    Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission 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 device functional:
    #1 Place bomb in designated detonation zone
    #2 Extend and anchor bomb (attack with hand).
    #3 Insert Nuclear Auth. Disk into slot.
    #4 Type numeric code into keypad ([nuke_code]).
    Note: If you make a mistake press R to reset the device.
    #5 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 have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
    Note: Toggle off the SAFETY.
    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.

    The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

    Good luck, soldier!

    " - // P.name = "Spec. Ops. Manual" - - for (var/obj/effect/landmark/L in landmarks_list) - if (L.name == "Syndicate-Commando-Bomb") - new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) - del(L) - - message_admins("[key_name_admin(usr)] has spawned a Syndicate strike squad.", 1) - log_admin("[key_name(usr)] used Spawn Syndicate Squad.") - feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) - var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) - var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") - var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") - var/syndicate_commando_name = pick(last_names) - - new_syndicate_commando.setGender(pick(MALE, FEMALE)) - - var/datum/preferences/A = new()//Randomize appearance for the commando. - A.randomize_appearance_for(new_syndicate_commando) - - new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" - new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) - - new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. - - //Creates mind stuff. - new_syndicate_commando.mind_initialize() - new_syndicate_commando.mind.assigned_role = "MODE" - new_syndicate_commando.mind.special_role = "Syndicate Commando" - ticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list. - new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) - del(spawn_location) - return new_syndicate_commando - -/mob/living/carbon/human/proc/equip_syndicate_commando(syndicate_leader_selected = 0) - - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src) - R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode. - equip_to_slot_or_del(R, slot_ears) - equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black(src), slot_wear_suit) - else - equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black/red(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black(src), slot_head) - else - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black/red(src), slot_head) - equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(src), slot_wear_mask) - equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) - - equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) - equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/ammo_storage/box/c45(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) - else - equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack) - - equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/grenade/empgrenade(src), slot_r_store) - equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store) - equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/silenced(src), slot_belt) - - equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) //Will change to something different at a later time -- Superxpdude - - var/obj/item/weapon/card/id/syndicate/W = new(src) //Untrackable by AI - W.name = "[real_name]'s ID Card" - W.icon_state = "id" - W.access = get_all_accesses()//They get full station access because obviously the syndicate has HAAAX, and can make special IDs for their most elite members. - W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage, access_syndicate)//Let's add their forged CentCom access and syndicate access. - W.assignment = "Syndicate Commando" - W.registered_name = real_name - equip_to_slot_or_del(W, slot_wear_id) - + + syndicate_commando_number-- + +//Spawns the rest of the commando gear. +// for (var/obj/effect/landmark/L) + // if (L.name == "Commando_Manual") + //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) + // var/obj/item/weapon/paper/P = new(L.loc) + // P.info = "

    Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
    #1 Work as a team.
    #2 Accomplish your objective at all costs.
    #3 Leave no witnesses.
    You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
    If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

    In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

    Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission 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 device functional:
    #1 Place bomb in designated detonation zone
    #2 Extend and anchor bomb (attack with hand).
    #3 Insert Nuclear Auth. Disk into slot.
    #4 Type numeric code into keypad ([nuke_code]).
    Note: If you make a mistake press R to reset the device.
    #5 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 have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
    Note: Toggle off the SAFETY.
    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.

    The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

    Good luck, soldier!

    " + // P.name = "Spec. Ops. Manual" + + for (var/obj/effect/landmark/L in landmarks_list) + if (L.name == "Syndicate-Commando-Bomb") + new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) + del(L) + + message_admins("[key_name_admin(usr)] has spawned a Syndicate strike squad.", 1) + log_admin("[key_name(usr)] used Spawn Syndicate Squad.") + feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) + var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) + var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") + var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") + var/syndicate_commando_name = pick(last_names) + + new_syndicate_commando.setGender(pick(MALE, FEMALE)) + + var/datum/preferences/A = new()//Randomize appearance for the commando. + A.randomize_appearance_for(new_syndicate_commando) + + new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" + new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) + + new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. + + //Creates mind stuff. + new_syndicate_commando.mind_initialize() + new_syndicate_commando.mind.assigned_role = "MODE" + new_syndicate_commando.mind.special_role = "Syndicate Commando" + ticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list. + new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) + del(spawn_location) + return new_syndicate_commando + +/mob/living/carbon/human/proc/equip_syndicate_commando(syndicate_leader_selected = 0) + + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src) + R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode. + equip_to_slot_or_del(R, slot_ears) + equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(src), slot_w_uniform) + equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) + if (!syndicate_leader_selected) + equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black(src), slot_wear_suit) + else + equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/black/red(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) + if (!syndicate_leader_selected) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black(src), slot_head) + else + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/black/red(src), slot_head) + equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(src), slot_wear_mask) + equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(src), slot_glasses) + + equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(src), slot_back) + equip_to_slot_or_del(new /obj/item/weapon/storage/box(src), slot_in_backpack) + + equip_to_slot_or_del(new /obj/item/ammo_storage/box/c45(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack) + if (!syndicate_leader_selected) + equip_to_slot_or_del(new /obj/item/weapon/plastique(src), slot_in_backpack) + else + equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack) + + equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store) + equip_to_slot_or_del(new /obj/item/weapon/grenade/empgrenade(src), slot_r_store) + equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store) + equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/silenced(src), slot_belt) + + equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand) //Will change to something different at a later time -- Superxpdude + + var/obj/item/weapon/card/id/syndicate/W = new(src) //Untrackable by AI + W.name = "[real_name]'s ID Card" + W.icon_state = "id" + W.access = get_all_accesses()//They get full station access because obviously the syndicate has HAAAX, and can make special IDs for their most elite members. + W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage, access_syndicate)//Let's add their forged CentCom access and syndicate access. + W.assignment = "Syndicate Commando" + W.registered_name = real_name + equip_to_slot_or_del(W, slot_wear_id) + return 1 \ No newline at end of file diff --git a/code/modules/admin/verbs/ticklag.dm b/code/modules/admin/verbs/ticklag.dm index 0148d02d099..74454f6ba7d 100644 --- a/code/modules/admin/verbs/ticklag.dm +++ b/code/modules/admin/verbs/ticklag.dm @@ -1,18 +1,18 @@ -/client/proc/ticklag() - set category = "Debug" - set name = "Set Ticklag" - set desc = "Sets a new tick lag. Recommend you don't mess with this too much! The standard value has been .55 for some time" - - if(!check_rights(R_DEBUG)) return - - var/newtick = input("Sets a new tick lag. Please don't mess with this too much! The standard value has been .55 for some time","Lag of Tick", world.tick_lag) as num|null - if(!newtick) - return - //I've used ticks of 2 before to help with serious singulo lags - if(newtick <= 2 && newtick > 0) - log_admin("[key_name(src)] has modified world.tick_lag to [newtick]", 0) - message_admins("[key_name(src)] has modified world.tick_lag to [newtick]", 0) - world.tick_lag = newtick - feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else +/client/proc/ticklag() + set category = "Debug" + set name = "Set Ticklag" + set desc = "Sets a new tick lag. Recommend you don't mess with this too much! The standard value has been .55 for some time" + + if(!check_rights(R_DEBUG)) return + + var/newtick = input("Sets a new tick lag. Please don't mess with this too much! The standard value has been .55 for some time","Lag of Tick", world.tick_lag) as num|null + if(!newtick) + return + //I've used ticks of 2 before to help with serious singulo lags + if(newtick <= 2 && newtick > 0) + log_admin("[key_name(src)] has modified world.tick_lag to [newtick]", 0) + message_admins("[key_name(src)] has modified world.tick_lag to [newtick]", 0) + world.tick_lag = newtick + feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else to_chat(src, "Error: ticklag(): Invalid world.ticklag value. No changes made.") diff --git a/code/modules/admin/verbs/tripAI.dm b/code/modules/admin/verbs/tripAI.dm index c80470ba95f..c49ee6f0deb 100644 --- a/code/modules/admin/verbs/tripAI.dm +++ b/code/modules/admin/verbs/tripAI.dm @@ -1,22 +1,22 @@ -/client/proc/triple_ai() - set category = "Fun" - set name = "Create AI Triumvirate" - - if(ticker.current_state > GAME_STATE_PREGAME) +/client/proc/triple_ai() + set category = "Fun" + set name = "Create AI Triumvirate" + + if(ticker.current_state > GAME_STATE_PREGAME) to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.") - return - - if(job_master && ticker) - var/datum/job/job = job_master.GetJob("AI") - if(!job) + return + + if(job_master && ticker) + var/datum/job/job = job_master.GetJob("AI") + if(!job) to_chat(usr, "Unable to locate the AI job") - return - if(ticker.triai) - ticker.triai = 0 + return + if(ticker.triai) + ticker.triai = 0 to_chat(usr, "Only one AI will be spawned at round start.") - message_admins("[key_name_admin(usr)] has toggled off triple AIs at round start.", 1) - else - ticker.triai = 1 + message_admins("[key_name_admin(usr)] has toggled off triple AIs at round start.", 1) + else + ticker.triai = 1 to_chat(usr, "There will be an AI Triumvirate at round start.") - message_admins("[key_name_admin(usr)] has toggled on triple AIs at round start.", 1) - return + message_admins("[key_name_admin(usr)] has toggled on triple AIs at round start.", 1) + return diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index 0ad86dee61a..e46a3564378 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -1,279 +1,279 @@ -#define VALUE_VARIABLE_NAME 1 //See var/list/accessible_values below! -#define VALUE_VARIABLE_TYPE 2 -#define VALUE_VARIABLE_MIN 3 //Minimum possible number value -#define VALUE_VARIABLE_MAX 4 //Maximum possible number value - -var/global/list/assembly_short_name_to_type = list() //Please, I beg you, don't give two different types of assembly the same short_name - -/obj/item/device/assembly - name = "assembly" - var/short_name //Short name of the assembly. If the name is "remote signalling device", short_name must be something like "signaler" - - desc = "A small electronic device that should never exist." - icon = 'icons/obj/assemblies/new_assemblies.dmi' - icon_state = "" - flags = FPRINT - siemens_coefficient = 1 - w_class = 2.0 - starting_materials = list(MAT_IRON = 100) - w_type = RECYK_ELECTRONIC - throwforce = 2 - throw_speed = 3 - throw_range = 10 - origin_tech = "magnets=1" - - var/show_status = 1 //in order to prevent the signaler button in signaler.dm from saying "... is ready!" when examined - var/secured = 1 - var/list/attached_overlays = null - var/obj/item/device/assembly_holder/holder = null - var/cooldown = 0//To prevent spam - var/wires = WIRE_RECEIVE | WIRE_PULSE - - var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate() - var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder - var/const/WIRE_PULSE_SPECIAL = 4 //Allows Pulse(0) to act on the holders special assembly - var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate() - var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message - - var/connection_text = "sending signals to" //For assembly frames - - var/list/accessible_values = list() - - // List of variables that can be READ / WRITTEN TO by other assemblies. - // Format of the list: - // - // accessible_values = list("Time" = "time;number",\ - // "Frequency" = "freq;number",\ - // "Code" = "code;number") - // - // "Time" - name of this value. Can be anything - // "time;number" - parameters. Convert this to a list using params2list, and access them by doing either list[VALUE_VARIABLE_NAME] or list[VALUE_VARIABLE_TYPE] - - //The example above allows any assembly (connected to an assembly frame) to access this assembly's time, frequency and code, e.g. a math circuit can READ this assembly's time, multiply it by 90 and SET this assembly's time to the result - -/obj/item/device/assembly/New() - ..() - - if(!short_name) - short_name = name - -/obj/item/device/assembly/proc/activate() //What the device does when turned on - return - -/obj/item/device/assembly/proc/pulsed(var/radio = 0) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs - return - -/obj/item/device/assembly/proc/pulse(var/radio = 0) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct - return - -/obj/item/device/assembly/proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here - return - -/obj/item/device/assembly/proc/attach_assembly(var/obj/A, var/mob/user) //Called when an assembly is attacked by another - return - -/obj/item/device/assembly/proc/process_cooldown() //Called via spawn(10) to have it count down the cooldown var - return - -/obj/item/device/assembly/proc/holder_movement() //Called when the holder is moved - return - -/obj/item/device/assembly/interact(mob/user as mob) //Called when attack_self is called - return - -/obj/item/device/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc) - return "The trigger assembly looks broken!" - -/obj/item/device/assembly/proc/send_pulses_to_list(var/list/L) //Send pulse to all assemblies in list. - if(!L || !L.len) return - - for(var/obj/item/device/assembly/A in L) - A.pulsed() - -/obj/item/device/assembly/proc/get_value(var/value) //Get the assembly's value (to be used with various circuits). value = an element from the accessible_values list! - if(!value in accessible_values) return - - var/list/L = params2list(accessible_values[value]) - var/var_to_grab = L[VALUE_VARIABLE_NAME] - - return vars[var_to_grab] - -/obj/item/device/assembly/proc/write_to_value(var/value, var/new_value) //Attempt to write to assembly's value. This handles value's type (num/text), whether writing is possible, etc. - if(!value in accessible_values) return - - var/list/L = params2list(accessible_values[value]) - - if(L[VALUE_VARIABLE_TYPE] == "number") - if(!isnum(new_value)) //Attempted to write a non-number to a number var - abort! - return - - if(L.len >= VALUE_VARIABLE_MAX) - new_value = Clamp(new_value, text2num(L[VALUE_VARIABLE_MIN]), text2num(L[VALUE_VARIABLE_MAX])) - else - if(!istext(new_value)) //Attempted to write a non-string to a string var - convert the non-string into a string and continue - new_value = "[new_value]" - - //text values can accept either numbers or text, so don't check for that - - var/var_to_change = L[VALUE_VARIABLE_NAME] - - set_value(var_to_change, new_value) - - return - -/obj/item/device/assembly/proc/set_value(var/var_name, var/new_value) //Actually change the assembly's var. No sanity or anything - vars[var_name] = new_value - -/obj/item/device/assembly/proc/connected(var/obj/item/device/assembly/A, in_frame = 0) //Called when assembly is connected to another assembly. in_frame is 1 if the connection occured in an assembly frame - return - -/obj/item/device/assembly/proc/disconnected(var/obj/item/device/assembly/A, in_frame = 0) //Called when assembly is disconnected from another assembly - return - -/obj/item/device/assembly/process_cooldown() - cooldown-- - if(cooldown <= 0) return 0 - spawn(10) - process_cooldown() - return 1 - -/obj/item/device/assembly/Destroy() - if(istype(src.loc, /obj/item/device/assembly_holder) || istype(holder)) - var/obj/item/device/assembly_holder/A = src.loc - if(A.a_left == src) - A.a_left = null - else if(A.a_right == src) - A.a_right = null - src.holder = null - else if(istype(src.loc, /obj/item/device/assembly_frame)) - var/obj/item/device/assembly_frame/AF = src.loc - - AF.eject_assembly(src) - - ..() - -/obj/item/device/assembly/pulsed(var/radio = 0) - if(holder && (wires & WIRE_RECEIVE)) - activate() - if(radio && (wires & WIRE_RADIO_RECEIVE)) - activate() - return 1 - - -/obj/item/device/assembly/pulse(var/radio = 0) - if(istype(holder, /obj/item/device/assembly_frame)) - var/obj/item/device/assembly_frame/AB = holder - - AB.receive_pulse(src) - else - if(holder && (wires & WIRE_PULSE)) - holder.process_activation(src, 1, 0) - if(holder && (wires & WIRE_PULSE_SPECIAL)) - holder.process_activation(src, 0, 1) - - if(istype(loc,/obj/item/weapon/grenade)) // This is a hack. Todo: Manage this better -Sayu - var/obj/item/weapon/grenade/G = loc - G.prime() // Adios, muchachos -// if(radio && (wires & WIRE_RADIO_PULSE)) - //Not sure what goes here quite yet send signal? - return 1 - - -/obj/item/device/assembly/activate() - if(!secured || (cooldown > 0)) return 0 - cooldown = 2 - spawn(10) - process_cooldown() - return 1 - - -/obj/item/device/assembly/toggle_secure() - secured = !secured - update_icon() - return secured - - -/obj/item/device/assembly/attach_assembly(var/obj/item/device/assembly/A, var/mob/user) - holder = new/obj/item/device/assembly_holder(get_turf(src)) - if(holder.attach(A,src,user)) - to_chat(user, "You attach \the [A] to \the [src]!") - return 1 - return 0 - - -/obj/item/device/assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isassembly(W)) - var/obj/item/device/assembly/A = W - if((!A.secured) && (!secured)) - attach_assembly(A,user) - return - if(isscrewdriver(W)) - if(toggle_secure()) - to_chat(user, "\The [src] is ready!") - else - to_chat(user, "\The [src] can now be attached!") - return - ..() - return - - -/obj/item/device/assembly/process() - processing_objects.Remove(src) - return - - -/obj/item/device/assembly/examine(mob/user) - ..() - if(show_status) - if(secured) - to_chat(user, "\The [src] is ready!") - else - to_chat(user, "\The [src] can be attached!") - -/obj/item/device/assembly/attack_self(mob/user as mob) - if(!user) return 0 - user.set_machine(src) - interact(user) - return 1 - - -/obj/item/device/assembly/interact(mob/user as mob) - return //HTML MENU FOR WIRES GOES HERE - -/* - var/small_icon_state = null//If this obj will go inside the assembly use this for icons - var/list/small_icon_state_overlays = null//Same here - var/obj/holder = null - var/cooldown = 0//To prevent spam - - proc - Activate()//Called when this assembly is pulsed by another one - Process_cooldown()//Call this via spawn(10) to have it count down the cooldown var - Attach_Holder(var/obj/H, var/mob/user)//Called when an assembly holder attempts to attach, sets src's loc in here - - - Activate() - if(cooldown > 0) - return 0 - cooldown = 2 - spawn(10) - Process_cooldown() - //Rest of code here - return 0 - - - Process_cooldown() - cooldown-- - if(cooldown <= 0) return 0 - spawn(10) - Process_cooldown() - return 1 - - - Attach_Holder(var/obj/H, var/mob/user) - if(!H) return 0 - if(!H.IsAssemblyHolder()) return 0 - //Remember to have it set its loc somewhere in here - - -*/ +#define VALUE_VARIABLE_NAME 1 //See var/list/accessible_values below! +#define VALUE_VARIABLE_TYPE 2 +#define VALUE_VARIABLE_MIN 3 //Minimum possible number value +#define VALUE_VARIABLE_MAX 4 //Maximum possible number value + +var/global/list/assembly_short_name_to_type = list() //Please, I beg you, don't give two different types of assembly the same short_name + +/obj/item/device/assembly + name = "assembly" + var/short_name //Short name of the assembly. If the name is "remote signalling device", short_name must be something like "signaler" + + desc = "A small electronic device that should never exist." + icon = 'icons/obj/assemblies/new_assemblies.dmi' + icon_state = "" + flags = FPRINT + siemens_coefficient = 1 + w_class = 2.0 + starting_materials = list(MAT_IRON = 100) + w_type = RECYK_ELECTRONIC + throwforce = 2 + throw_speed = 3 + throw_range = 10 + origin_tech = "magnets=1" + + var/show_status = 1 //in order to prevent the signaler button in signaler.dm from saying "... is ready!" when examined + var/secured = 1 + var/list/attached_overlays = null + var/obj/item/device/assembly_holder/holder = null + var/cooldown = 0//To prevent spam + var/wires = WIRE_RECEIVE | WIRE_PULSE + + var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate() + var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder + var/const/WIRE_PULSE_SPECIAL = 4 //Allows Pulse(0) to act on the holders special assembly + var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate() + var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message + + var/connection_text = "sending signals to" //For assembly frames + + var/list/accessible_values = list() + + // List of variables that can be READ / WRITTEN TO by other assemblies. + // Format of the list: + // + // accessible_values = list("Time" = "time;number",\ + // "Frequency" = "freq;number",\ + // "Code" = "code;number") + // + // "Time" - name of this value. Can be anything + // "time;number" - parameters. Convert this to a list using params2list, and access them by doing either list[VALUE_VARIABLE_NAME] or list[VALUE_VARIABLE_TYPE] + + //The example above allows any assembly (connected to an assembly frame) to access this assembly's time, frequency and code, e.g. a math circuit can READ this assembly's time, multiply it by 90 and SET this assembly's time to the result + +/obj/item/device/assembly/New() + ..() + + if(!short_name) + short_name = name + +/obj/item/device/assembly/proc/activate() //What the device does when turned on + return + +/obj/item/device/assembly/proc/pulsed(var/radio = 0) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs + return + +/obj/item/device/assembly/proc/pulse(var/radio = 0) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct + return + +/obj/item/device/assembly/proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here + return + +/obj/item/device/assembly/proc/attach_assembly(var/obj/A, var/mob/user) //Called when an assembly is attacked by another + return + +/obj/item/device/assembly/proc/process_cooldown() //Called via spawn(10) to have it count down the cooldown var + return + +/obj/item/device/assembly/proc/holder_movement() //Called when the holder is moved + return + +/obj/item/device/assembly/interact(mob/user as mob) //Called when attack_self is called + return + +/obj/item/device/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc) + return "The trigger assembly looks broken!" + +/obj/item/device/assembly/proc/send_pulses_to_list(var/list/L) //Send pulse to all assemblies in list. + if(!L || !L.len) return + + for(var/obj/item/device/assembly/A in L) + A.pulsed() + +/obj/item/device/assembly/proc/get_value(var/value) //Get the assembly's value (to be used with various circuits). value = an element from the accessible_values list! + if(!value in accessible_values) return + + var/list/L = params2list(accessible_values[value]) + var/var_to_grab = L[VALUE_VARIABLE_NAME] + + return vars[var_to_grab] + +/obj/item/device/assembly/proc/write_to_value(var/value, var/new_value) //Attempt to write to assembly's value. This handles value's type (num/text), whether writing is possible, etc. + if(!value in accessible_values) return + + var/list/L = params2list(accessible_values[value]) + + if(L[VALUE_VARIABLE_TYPE] == "number") + if(!isnum(new_value)) //Attempted to write a non-number to a number var - abort! + return + + if(L.len >= VALUE_VARIABLE_MAX) + new_value = Clamp(new_value, text2num(L[VALUE_VARIABLE_MIN]), text2num(L[VALUE_VARIABLE_MAX])) + else + if(!istext(new_value)) //Attempted to write a non-string to a string var - convert the non-string into a string and continue + new_value = "[new_value]" + + //text values can accept either numbers or text, so don't check for that + + var/var_to_change = L[VALUE_VARIABLE_NAME] + + set_value(var_to_change, new_value) + + return + +/obj/item/device/assembly/proc/set_value(var/var_name, var/new_value) //Actually change the assembly's var. No sanity or anything + vars[var_name] = new_value + +/obj/item/device/assembly/proc/connected(var/obj/item/device/assembly/A, in_frame = 0) //Called when assembly is connected to another assembly. in_frame is 1 if the connection occured in an assembly frame + return + +/obj/item/device/assembly/proc/disconnected(var/obj/item/device/assembly/A, in_frame = 0) //Called when assembly is disconnected from another assembly + return + +/obj/item/device/assembly/process_cooldown() + cooldown-- + if(cooldown <= 0) return 0 + spawn(10) + process_cooldown() + return 1 + +/obj/item/device/assembly/Destroy() + if(istype(src.loc, /obj/item/device/assembly_holder) || istype(holder)) + var/obj/item/device/assembly_holder/A = src.loc + if(A.a_left == src) + A.a_left = null + else if(A.a_right == src) + A.a_right = null + src.holder = null + else if(istype(src.loc, /obj/item/device/assembly_frame)) + var/obj/item/device/assembly_frame/AF = src.loc + + AF.eject_assembly(src) + + ..() + +/obj/item/device/assembly/pulsed(var/radio = 0) + if(holder && (wires & WIRE_RECEIVE)) + activate() + if(radio && (wires & WIRE_RADIO_RECEIVE)) + activate() + return 1 + + +/obj/item/device/assembly/pulse(var/radio = 0) + if(istype(holder, /obj/item/device/assembly_frame)) + var/obj/item/device/assembly_frame/AB = holder + + AB.receive_pulse(src) + else + if(holder && (wires & WIRE_PULSE)) + holder.process_activation(src, 1, 0) + if(holder && (wires & WIRE_PULSE_SPECIAL)) + holder.process_activation(src, 0, 1) + + if(istype(loc,/obj/item/weapon/grenade)) // This is a hack. Todo: Manage this better -Sayu + var/obj/item/weapon/grenade/G = loc + G.prime() // Adios, muchachos +// if(radio && (wires & WIRE_RADIO_PULSE)) + //Not sure what goes here quite yet send signal? + return 1 + + +/obj/item/device/assembly/activate() + if(!secured || (cooldown > 0)) return 0 + cooldown = 2 + spawn(10) + process_cooldown() + return 1 + + +/obj/item/device/assembly/toggle_secure() + secured = !secured + update_icon() + return secured + + +/obj/item/device/assembly/attach_assembly(var/obj/item/device/assembly/A, var/mob/user) + holder = new/obj/item/device/assembly_holder(get_turf(src)) + if(holder.attach(A,src,user)) + to_chat(user, "You attach \the [A] to \the [src]!") + return 1 + return 0 + + +/obj/item/device/assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isassembly(W)) + var/obj/item/device/assembly/A = W + if((!A.secured) && (!secured)) + attach_assembly(A,user) + return + if(isscrewdriver(W)) + if(toggle_secure()) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can now be attached!") + return + ..() + return + + +/obj/item/device/assembly/process() + processing_objects.Remove(src) + return + + +/obj/item/device/assembly/examine(mob/user) + ..() + if(show_status) + if(secured) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can be attached!") + +/obj/item/device/assembly/attack_self(mob/user as mob) + if(!user) return 0 + user.set_machine(src) + interact(user) + return 1 + + +/obj/item/device/assembly/interact(mob/user as mob) + return //HTML MENU FOR WIRES GOES HERE + +/* + var/small_icon_state = null//If this obj will go inside the assembly use this for icons + var/list/small_icon_state_overlays = null//Same here + var/obj/holder = null + var/cooldown = 0//To prevent spam + + proc + Activate()//Called when this assembly is pulsed by another one + Process_cooldown()//Call this via spawn(10) to have it count down the cooldown var + Attach_Holder(var/obj/H, var/mob/user)//Called when an assembly holder attempts to attach, sets src's loc in here + + + Activate() + if(cooldown > 0) + return 0 + cooldown = 2 + spawn(10) + Process_cooldown() + //Rest of code here + return 0 + + + Process_cooldown() + cooldown-- + if(cooldown <= 0) return 0 + spawn(10) + Process_cooldown() + return 1 + + + Attach_Holder(var/obj/H, var/mob/user) + if(!H) return 0 + if(!H.IsAssemblyHolder()) return 0 + //Remember to have it set its loc somewhere in here + + +*/ diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 601ad6b0806..41930e57bb2 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -1,165 +1,165 @@ -/obj/item/device/onetankbomb - name = "bomb" - icon = 'icons/obj/tank.dmi' - item_state = "assembly" - throwforce = 5 - w_class = 3.0 - throw_speed = 2 - throw_range = 4 - flags = FPRINT | PROXMOVE - siemens_coefficient = 1 - var/status = 0 //0 - not readied //1 - bomb finished with welder - var/obj/item/device/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device - var/obj/item/weapon/tank/bombtank = null //the second part of the bomb is a plasma tank - -/obj/item/device/onetankbomb/examine(mob/user) - ..() - user.examination(bombtank) - -/obj/item/device/onetankbomb/update_icon() - if(bombtank) - icon_state = bombtank.icon_state - if(bombassembly) - overlays += bombassembly.icon_state - overlays += bombassembly.overlays - overlays += "bomb_assembly" - -/obj/item/device/onetankbomb/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/device/analyzer)) - bombtank.attackby(W, user) - return - if(istype(W, /obj/item/weapon/wrench) && !status) //This is basically bomb assembly code inverted. apparently it works. - +/obj/item/device/onetankbomb + name = "bomb" + icon = 'icons/obj/tank.dmi' + item_state = "assembly" + throwforce = 5 + w_class = 3.0 + throw_speed = 2 + throw_range = 4 + flags = FPRINT | PROXMOVE + siemens_coefficient = 1 + var/status = 0 //0 - not readied //1 - bomb finished with welder + var/obj/item/device/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device + var/obj/item/weapon/tank/bombtank = null //the second part of the bomb is a plasma tank + +/obj/item/device/onetankbomb/examine(mob/user) + ..() + user.examination(bombtank) + +/obj/item/device/onetankbomb/update_icon() + if(bombtank) + icon_state = bombtank.icon_state + if(bombassembly) + overlays += bombassembly.icon_state + overlays += bombassembly.overlays + overlays += "bomb_assembly" + +/obj/item/device/onetankbomb/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/device/analyzer)) + bombtank.attackby(W, user) + return + if(istype(W, /obj/item/weapon/wrench) && !status) //This is basically bomb assembly code inverted. apparently it works. + to_chat(user, "You disassemble [src].") - - bombassembly.loc = user.loc - bombassembly.master = null - bombassembly = null - - bombtank.loc = user.loc - bombtank.master = null - bombtank = null - - del(src) - return - if((istype(W, /obj/item/weapon/weldingtool) && W:welding)) - if(!status) - status = 1 - bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" - message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]") + + bombassembly.loc = user.loc + bombassembly.master = null + bombassembly = null + + bombtank.loc = user.loc + bombtank.master = null + bombtank = null + + del(src) + return + if((istype(W, /obj/item/weapon/weldingtool) && W:welding)) + if(!status) + status = 1 + bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" + message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]") to_chat(user, "A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.") - else - status = 0 - bombers += "[key_name(user)] unwelded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" + else + status = 0 + bombers += "[key_name(user)] unwelded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" to_chat(user, "The hole has been closed.") - add_fingerprint(user) - ..() - -/obj/item/device/onetankbomb/attack_self(mob/user as mob) //pressing the bomb accesses its assembly - bombassembly.attack_self(user, 1) - add_fingerprint(user) - return - -/obj/item/device/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here. - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - sleep(10) - if(!src) - return - if(status) - bombtank.detonate() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file - else - bombtank.release() - -/obj/item/device/onetankbomb/HasProximity(atom/movable/AM as mob|obj) - if(bombassembly) - bombassembly.HasProximity(AM) - -/obj/item/device/onetankbomb/Crossed(AM as mob|obj) - if(bombassembly) - bombassembly.Crossed(AM) - -/obj/item/device/onetankbomb/on_found(mob/finder as mob) - if(bombassembly) - bombassembly.on_found(finder) - -// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ---------- - -/obj/item/weapon/tank/proc/bomb_assemble(W,user) //Bomb assembly proc. This turns assembly+tank into a bomb - var/obj/item/device/assembly_holder/S = W - var/mob/M = user - if(!S.secured) //Check if the assembly is secured - return - if(isigniter(S.a_left) == isigniter(S.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it - return - - if(!M.drop_item(S)) return //Remove the assembly from your hands - - var/obj/item/device/onetankbomb/R = new /obj/item/device/onetankbomb(loc) - - M.remove_from_mob(src) //Remove the tank from your character,in case you were holding it - M.put_in_hands(R) //Equips the bomb if possible, or puts it on the floor. - - R.bombassembly = S //Tell the bomb about its assembly part - S.master = R //Tell the assembly about its new owner - S.loc = R //Move the assembly out of the fucking way - - R.bombtank = src //Same for tank - master = R - loc = R - R.update_icon() - return - -/obj/item/weapon/tank/proc/detonate() //This happens when a bomb is told to explode - var/fuel_moles = air_contents.toxins + air_contents.oxygen/6 - var/strength = 1 - - var/turf/ground_zero = get_turf(loc) - loc = null - - if(air_contents.temperature > (T0C + 400)) - strength = (fuel_moles/15) - - if(strength >=1) - explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1)) - else if(strength >=0.5) - explosion(ground_zero, 0, 1, 2, 4) - else if(strength >=0.2) - explosion(ground_zero, -1, 0, 1, 2) - else - ground_zero.assume_air(air_contents) - ground_zero.hotspot_expose(1000, 125,surfaces=1) - - else if(air_contents.temperature > (T0C + 250)) - strength = (fuel_moles/20) - - if(strength >=1) - explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1)) - else if (strength >=0.5) - explosion(ground_zero, -1, 0, 1, 2) - else - ground_zero.assume_air(air_contents) - ground_zero.hotspot_expose(1000, 125,surfaces=1) - - else if(air_contents.temperature > (T0C + 100)) - strength = (fuel_moles/25) - - if (strength >=1) - explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1)) - else - ground_zero.assume_air(air_contents) - ground_zero.hotspot_expose(1000, 125,1) - - else - ground_zero.assume_air(air_contents) - ground_zero.hotspot_expose(1000, 125,surfaces=1) - - if(master) - del(master) - del(src) - -/obj/item/weapon/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out. - var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles()) - var/turf/simulated/T = get_turf(src) - if(!T) - return + add_fingerprint(user) + ..() + +/obj/item/device/onetankbomb/attack_self(mob/user as mob) //pressing the bomb accesses its assembly + bombassembly.attack_self(user, 1) + add_fingerprint(user) + return + +/obj/item/device/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here. + visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + sleep(10) + if(!src) + return + if(status) + bombtank.detonate() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file + else + bombtank.release() + +/obj/item/device/onetankbomb/HasProximity(atom/movable/AM as mob|obj) + if(bombassembly) + bombassembly.HasProximity(AM) + +/obj/item/device/onetankbomb/Crossed(AM as mob|obj) + if(bombassembly) + bombassembly.Crossed(AM) + +/obj/item/device/onetankbomb/on_found(mob/finder as mob) + if(bombassembly) + bombassembly.on_found(finder) + +// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ---------- + +/obj/item/weapon/tank/proc/bomb_assemble(W,user) //Bomb assembly proc. This turns assembly+tank into a bomb + var/obj/item/device/assembly_holder/S = W + var/mob/M = user + if(!S.secured) //Check if the assembly is secured + return + if(isigniter(S.a_left) == isigniter(S.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it + return + + if(!M.drop_item(S)) return //Remove the assembly from your hands + + var/obj/item/device/onetankbomb/R = new /obj/item/device/onetankbomb(loc) + + M.remove_from_mob(src) //Remove the tank from your character,in case you were holding it + M.put_in_hands(R) //Equips the bomb if possible, or puts it on the floor. + + R.bombassembly = S //Tell the bomb about its assembly part + S.master = R //Tell the assembly about its new owner + S.loc = R //Move the assembly out of the fucking way + + R.bombtank = src //Same for tank + master = R + loc = R + R.update_icon() + return + +/obj/item/weapon/tank/proc/detonate() //This happens when a bomb is told to explode + var/fuel_moles = air_contents.toxins + air_contents.oxygen/6 + var/strength = 1 + + var/turf/ground_zero = get_turf(loc) + loc = null + + if(air_contents.temperature > (T0C + 400)) + strength = (fuel_moles/15) + + if(strength >=1) + explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1)) + else if(strength >=0.5) + explosion(ground_zero, 0, 1, 2, 4) + else if(strength >=0.2) + explosion(ground_zero, -1, 0, 1, 2) + else + ground_zero.assume_air(air_contents) + ground_zero.hotspot_expose(1000, 125,surfaces=1) + + else if(air_contents.temperature > (T0C + 250)) + strength = (fuel_moles/20) + + if(strength >=1) + explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1)) + else if (strength >=0.5) + explosion(ground_zero, -1, 0, 1, 2) + else + ground_zero.assume_air(air_contents) + ground_zero.hotspot_expose(1000, 125,surfaces=1) + + else if(air_contents.temperature > (T0C + 100)) + strength = (fuel_moles/25) + + if (strength >=1) + explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1)) + else + ground_zero.assume_air(air_contents) + ground_zero.hotspot_expose(1000, 125,1) + + else + ground_zero.assume_air(air_contents) + ground_zero.hotspot_expose(1000, 125,surfaces=1) + + if(master) + del(master) + del(src) + +/obj/item/weapon/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out. + var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles()) + var/turf/simulated/T = get_turf(src) + if(!T) + return T.assume_air(removed) \ No newline at end of file diff --git a/code/modules/assembly/helpers.dm b/code/modules/assembly/helpers.dm index 0c8005ad0bc..88bd5b401aa 100644 --- a/code/modules/assembly/helpers.dm +++ b/code/modules/assembly/helpers.dm @@ -1,44 +1,44 @@ -/proc/isassembly(O) - if(istype(O, /obj/item/device/assembly)) - return 1 - return 0 - -/proc/isigniter(O) - if(istype(O, /obj/item/device/assembly/igniter)) - return 1 - return 0 - -/proc/isinfared(O) - if(istype(O, /obj/item/device/assembly/infra)) - return 1 - return 0 - -/proc/isprox(O) - if(istype(O, /obj/item/device/assembly/prox_sensor)) - return 1 - return 0 - -/proc/issignaler(O) - if(istype(O, /obj/item/device/assembly/signaler)) - return 1 - return 0 - -/proc/istimer(O) - if(istype(O, /obj/item/device/assembly/timer)) - return 1 - return 0 - -/* -Name: IsSpecialAssembly -Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door -*/ - -/obj/proc/IsSpecialAssembly() - return 0 - -/* -Name: IsAssemblyHolder -Desc: If true is an object that can hold an assemblyholder object -*/ -/obj/proc/IsAssemblyHolder() +/proc/isassembly(O) + if(istype(O, /obj/item/device/assembly)) + return 1 + return 0 + +/proc/isigniter(O) + if(istype(O, /obj/item/device/assembly/igniter)) + return 1 + return 0 + +/proc/isinfared(O) + if(istype(O, /obj/item/device/assembly/infra)) + return 1 + return 0 + +/proc/isprox(O) + if(istype(O, /obj/item/device/assembly/prox_sensor)) + return 1 + return 0 + +/proc/issignaler(O) + if(istype(O, /obj/item/device/assembly/signaler)) + return 1 + return 0 + +/proc/istimer(O) + if(istype(O, /obj/item/device/assembly/timer)) + return 1 + return 0 + +/* +Name: IsSpecialAssembly +Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door +*/ + +/obj/proc/IsSpecialAssembly() + return 0 + +/* +Name: IsAssemblyHolder +Desc: If true is an object that can hold an assemblyholder object +*/ +/obj/proc/IsAssemblyHolder() return 0 \ No newline at end of file diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 4aa5e6f0d5f..68391eabfb9 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -1,302 +1,302 @@ -/obj/item/device/assembly_holder - name = "Assembly" - icon = 'icons/obj/assemblies/new_assemblies.dmi' - icon_state = "holder" - item_state = "assembly" - flags = FPRINT | PROXMOVE - siemens_coefficient = 1 - throwforce = 5 - w_class = 2.0 - throw_speed = 3 - throw_range = 10 - - var/secured = 0 - var/obj/item/device/assembly/a_left = null - var/obj/item/device/assembly/a_right = null - var/obj/special_assembly = null - -/obj/item/device/assembly_holder/proc/attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) - return - -/obj/item/device/assembly_holder/proc/attach_special(var/obj/O, var/mob/user) - return - -/obj/item/device/assembly_holder/proc/process_activation(var/obj/item/device/D) - return - -/obj/item/device/assembly_holder/proc/detached() - return - - -/obj/item/device/assembly_holder/IsAssemblyHolder() - return 1 - -/obj/item/device/assembly_holder/Destroy() - if(a_left) - a_left.holder = null - a_left.disconnected(a_right) - if(a_right) - a_right.holder = null - a_right.disconnected(a_left) - - ..() - -/obj/item/device/assembly_holder/attach(var/obj/item/device/assembly/D, var/obj/item/device/assembly/D2, var/mob/user) - if((!D)||(!D2)) return 0 - if((!isassembly(D))||(!isassembly(D2))) return 0 - if((D.secured)||(D2.secured)) return 0 - if(user) - user.remove_from_mob(D) - user.remove_from_mob(D2) - D.holder = src - D2.holder = src - D.loc = src - D2.loc = src - - D.connected(D2) - D2.connected(D) - - a_left = D - a_right = D2 - name = "[D.name]-[D2.name] assembly" - update_icon() - usr.put_in_hands(src) - - return 1 - - -/obj/item/device/assembly_holder/attach_special(var/obj/O, var/mob/user) - if(!O) return - if(!O.IsSpecialAssembly()) return 0 - -/* if(O:Attach_Holder()) - special_assembly = O - update_icon() - src.name = "[a_left.name] [a_right.name] [special_assembly.name] assembly" -*/ - return - - -/obj/item/device/assembly_holder/update_icon() - overlays.len = 0 - if(a_left) - overlays += "[a_left.icon_state]_left" - for(var/O in a_left.attached_overlays) - overlays += "[O]_l" - if(a_right) - src.overlays += "[a_right.icon_state]_right" - for(var/O in a_right.attached_overlays) - overlays += "[O]_r" - if(master) - master.update_icon() - -/* if(special_assembly) - special_assembly.update_icon() - if(special_assembly:small_icon_state) - src.overlays += special_assembly:small_icon_state - for(var/O in special_assembly:small_icon_state_overlays) - src.overlays += O -*/ - -/obj/item/device/assembly_holder/examine(mob/user) - ..() - if (secured) - to_chat(user, "\The [src] is ready!") - else - to_chat(user, "\The [src] can be attached!") - - -/obj/item/device/assembly_holder/HasProximity(atom/movable/AM as mob|obj) - if(a_left) - a_left.HasProximity(AM) - if(a_right) - a_right.HasProximity(AM) - if(special_assembly) - special_assembly.HasProximity(AM) - - -/obj/item/device/assembly_holder/Crossed(atom/movable/AM as mob|obj) - if(a_left) - a_left.Crossed(AM) - if(a_right) - a_right.Crossed(AM) - if(special_assembly) - special_assembly.Crossed(AM) - - -/obj/item/device/assembly_holder/on_found(mob/finder as mob) - if(a_left) - a_left.on_found(finder) - if(a_right) - a_right.on_found(finder) - if(special_assembly) - if(istype(special_assembly, /obj/item)) - var/obj/item/S = special_assembly - S.on_found(finder) - -/obj/item/device/assembly_holder/Move() - ..() - if(a_left && a_right) - a_left.holder_movement() - a_right.holder_movement() -// if(special_assembly) -// special_assembly:holder_movement() - return - -/obj/item/device/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess - if(a_left && a_right) - a_left.holder_movement() - a_right.holder_movement() -// if(special_assembly) -// special_assembly:Holder_Movement() - ..() - return - - -/obj/item/device/assembly_holder/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isscrewdriver(W)) - if(!a_left || !a_right) - to_chat(user, "BUG:Assembly part missing, please report this!") - return - a_left.toggle_secure() - a_right.toggle_secure() - secured = !secured - if(secured) - to_chat(user, "\The [src] is ready!") - else - to_chat(user, "\The [src] can now be taken apart!") - update_icon() - return - else if(W.IsSpecialAssembly()) - attach_special(W, user) - else if(istype(W,/obj/item/weapon/weldingtool)) - if(!a_left || !a_right) - to_chat(user, "BUG:Assembly part missing, please report this!") - return - if(!isigniter(a_left) && !isigniter(a_right)) - to_chat(user, "You can't make an igniter without an igniting component!") - return - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) - to_chat(user, "You begin to weld \the [src] to the floor...") - if (do_after(user, src, 40)) - var/obj/machinery/igniter/igniter=new(src.loc) - igniter.assembly=src - src.loc=igniter - to_chat(user, "You attach the assembly to the floor with a few spot welds.") - else: - to_chat(user, "You need more welder fuel to do that.") - return - - else - ..() - return - - -/obj/item/device/assembly_holder/attack_self(mob/user as mob) - src.add_fingerprint(user) - if(src.secured) - if(!a_left || !a_right) - to_chat(user, "Assembly part missing!") - return - if(istype(a_left,a_right.type))//If they are the same type it causes issues due to window code - switch(alert("Which side would you like to use?",,"Left","Right")) - if("Left") a_left.attack_self(user) - if("Right") a_right.attack_self(user) - return - else - if(!istype(a_left,/obj/item/device/assembly/igniter)) - a_left.attack_self(user) - if(!istype(a_right,/obj/item/device/assembly/igniter)) - a_right.attack_self(user) - else - var/turf/T = get_turf(src) - if(!T) return 0 - if(a_left) - a_left:holder = null - a_left.loc = T - a_left.disconnected(a_right) - if(a_right) - a_right:holder = null - a_right.loc = T - a_right.disconnected(a_left) - spawn(0) - del(src) - return - - -/obj/item/device/assembly_holder/process_activation(var/obj/D, var/normal = 1, var/special = 1) - if(!D) return 0 - if(!secured) - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - if((normal) && (a_right) && (a_left)) - if(istype(src.loc, /obj/machinery/igniter)) - src.loc:toggle_state() - else: - if(a_right != D) - a_right.pulsed(0) - if(a_left != D) - a_left.pulsed(0) - if(master) - master.receive_signal() -// if(special && special_assembly) -// if(!special_assembly == D) -// special_assembly.dothings() - return 1 - -/obj/item/device/assembly_holder/timer_igniter - name = "timer-igniter assembly" - -/obj/item/device/assembly_holder/timer_igniter/New() - ..() - - var/obj/item/device/assembly/igniter/ign = new(src) - ign.secured = 1 - ign.holder = src - var/obj/item/device/assembly/timer/tmr = new(src) - tmr.time=5 - tmr.secured = 1 - tmr.holder = src - processing_objects.Add(tmr) - a_left = tmr - a_right = ign - secured = 1 - update_icon() - name = initial(name) + " ([tmr.time] secs)" - - loc.verbs += /obj/item/device/assembly_holder/timer_igniter/verb/configure - -/obj/item/device/assembly_holder/timer_igniter/detached() - loc.verbs -= /obj/item/device/assembly_holder/timer_igniter/verb/configure - ..() - -/obj/item/device/assembly_holder/timer_igniter/verb/configure() - set name = "Set Timer" - set category = "Object" - set src in usr - - if ( !(usr.isUnconscious() || usr.restrained()) ) - var/obj/item/device/assembly_holder/holder - if(istype(src,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/gren = src - holder=gren.detonator - var/obj/item/device/assembly/timer/tmr = holder.a_left - if(!istype(tmr,/obj/item/device/assembly/timer)) - tmr = holder.a_right - if(!istype(tmr,/obj/item/device/assembly/timer)) - to_chat(usr, "This detonator has no timer.") - return - - if(tmr.timing) - to_chat(usr, "Clock is ticking already.") - else - var/ntime = input("Enter desired time in seconds", "Time", "5") as num - if (ntime>0 && ntime<1000) - tmr.time = ntime - name = initial(name) + "([tmr.time] secs)" - to_chat(usr, "Timer set to [tmr.time] seconds.") - else - to_chat(usr, "Timer can't be [ntime<=0?"negative":"more than 1000 seconds"].") - else - to_chat(usr, "You cannot do this while [usr.stat?"unconscious/dead":"restrained"].") +/obj/item/device/assembly_holder + name = "Assembly" + icon = 'icons/obj/assemblies/new_assemblies.dmi' + icon_state = "holder" + item_state = "assembly" + flags = FPRINT | PROXMOVE + siemens_coefficient = 1 + throwforce = 5 + w_class = 2.0 + throw_speed = 3 + throw_range = 10 + + var/secured = 0 + var/obj/item/device/assembly/a_left = null + var/obj/item/device/assembly/a_right = null + var/obj/special_assembly = null + +/obj/item/device/assembly_holder/proc/attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) + return + +/obj/item/device/assembly_holder/proc/attach_special(var/obj/O, var/mob/user) + return + +/obj/item/device/assembly_holder/proc/process_activation(var/obj/item/device/D) + return + +/obj/item/device/assembly_holder/proc/detached() + return + + +/obj/item/device/assembly_holder/IsAssemblyHolder() + return 1 + +/obj/item/device/assembly_holder/Destroy() + if(a_left) + a_left.holder = null + a_left.disconnected(a_right) + if(a_right) + a_right.holder = null + a_right.disconnected(a_left) + + ..() + +/obj/item/device/assembly_holder/attach(var/obj/item/device/assembly/D, var/obj/item/device/assembly/D2, var/mob/user) + if((!D)||(!D2)) return 0 + if((!isassembly(D))||(!isassembly(D2))) return 0 + if((D.secured)||(D2.secured)) return 0 + if(user) + user.remove_from_mob(D) + user.remove_from_mob(D2) + D.holder = src + D2.holder = src + D.loc = src + D2.loc = src + + D.connected(D2) + D2.connected(D) + + a_left = D + a_right = D2 + name = "[D.name]-[D2.name] assembly" + update_icon() + usr.put_in_hands(src) + + return 1 + + +/obj/item/device/assembly_holder/attach_special(var/obj/O, var/mob/user) + if(!O) return + if(!O.IsSpecialAssembly()) return 0 + +/* if(O:Attach_Holder()) + special_assembly = O + update_icon() + src.name = "[a_left.name] [a_right.name] [special_assembly.name] assembly" +*/ + return + + +/obj/item/device/assembly_holder/update_icon() + overlays.len = 0 + if(a_left) + overlays += "[a_left.icon_state]_left" + for(var/O in a_left.attached_overlays) + overlays += "[O]_l" + if(a_right) + src.overlays += "[a_right.icon_state]_right" + for(var/O in a_right.attached_overlays) + overlays += "[O]_r" + if(master) + master.update_icon() + +/* if(special_assembly) + special_assembly.update_icon() + if(special_assembly:small_icon_state) + src.overlays += special_assembly:small_icon_state + for(var/O in special_assembly:small_icon_state_overlays) + src.overlays += O +*/ + +/obj/item/device/assembly_holder/examine(mob/user) + ..() + if (secured) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can be attached!") + + +/obj/item/device/assembly_holder/HasProximity(atom/movable/AM as mob|obj) + if(a_left) + a_left.HasProximity(AM) + if(a_right) + a_right.HasProximity(AM) + if(special_assembly) + special_assembly.HasProximity(AM) + + +/obj/item/device/assembly_holder/Crossed(atom/movable/AM as mob|obj) + if(a_left) + a_left.Crossed(AM) + if(a_right) + a_right.Crossed(AM) + if(special_assembly) + special_assembly.Crossed(AM) + + +/obj/item/device/assembly_holder/on_found(mob/finder as mob) + if(a_left) + a_left.on_found(finder) + if(a_right) + a_right.on_found(finder) + if(special_assembly) + if(istype(special_assembly, /obj/item)) + var/obj/item/S = special_assembly + S.on_found(finder) + +/obj/item/device/assembly_holder/Move() + ..() + if(a_left && a_right) + a_left.holder_movement() + a_right.holder_movement() +// if(special_assembly) +// special_assembly:holder_movement() + return + +/obj/item/device/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess + if(a_left && a_right) + a_left.holder_movement() + a_right.holder_movement() +// if(special_assembly) +// special_assembly:Holder_Movement() + ..() + return + + +/obj/item/device/assembly_holder/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isscrewdriver(W)) + if(!a_left || !a_right) + to_chat(user, "BUG:Assembly part missing, please report this!") + return + a_left.toggle_secure() + a_right.toggle_secure() + secured = !secured + if(secured) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can now be taken apart!") + update_icon() + return + else if(W.IsSpecialAssembly()) + attach_special(W, user) + else if(istype(W,/obj/item/weapon/weldingtool)) + if(!a_left || !a_right) + to_chat(user, "BUG:Assembly part missing, please report this!") + return + if(!isigniter(a_left) && !isigniter(a_right)) + to_chat(user, "You can't make an igniter without an igniting component!") + return + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + to_chat(user, "You begin to weld \the [src] to the floor...") + if (do_after(user, src, 40)) + var/obj/machinery/igniter/igniter=new(src.loc) + igniter.assembly=src + src.loc=igniter + to_chat(user, "You attach the assembly to the floor with a few spot welds.") + else: + to_chat(user, "You need more welder fuel to do that.") + return + + else + ..() + return + + +/obj/item/device/assembly_holder/attack_self(mob/user as mob) + src.add_fingerprint(user) + if(src.secured) + if(!a_left || !a_right) + to_chat(user, "Assembly part missing!") + return + if(istype(a_left,a_right.type))//If they are the same type it causes issues due to window code + switch(alert("Which side would you like to use?",,"Left","Right")) + if("Left") a_left.attack_self(user) + if("Right") a_right.attack_self(user) + return + else + if(!istype(a_left,/obj/item/device/assembly/igniter)) + a_left.attack_self(user) + if(!istype(a_right,/obj/item/device/assembly/igniter)) + a_right.attack_self(user) + else + var/turf/T = get_turf(src) + if(!T) return 0 + if(a_left) + a_left:holder = null + a_left.loc = T + a_left.disconnected(a_right) + if(a_right) + a_right:holder = null + a_right.loc = T + a_right.disconnected(a_left) + spawn(0) + del(src) + return + + +/obj/item/device/assembly_holder/process_activation(var/obj/D, var/normal = 1, var/special = 1) + if(!D) return 0 + if(!secured) + visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + if((normal) && (a_right) && (a_left)) + if(istype(src.loc, /obj/machinery/igniter)) + src.loc:toggle_state() + else: + if(a_right != D) + a_right.pulsed(0) + if(a_left != D) + a_left.pulsed(0) + if(master) + master.receive_signal() +// if(special && special_assembly) +// if(!special_assembly == D) +// special_assembly.dothings() + return 1 + +/obj/item/device/assembly_holder/timer_igniter + name = "timer-igniter assembly" + +/obj/item/device/assembly_holder/timer_igniter/New() + ..() + + var/obj/item/device/assembly/igniter/ign = new(src) + ign.secured = 1 + ign.holder = src + var/obj/item/device/assembly/timer/tmr = new(src) + tmr.time=5 + tmr.secured = 1 + tmr.holder = src + processing_objects.Add(tmr) + a_left = tmr + a_right = ign + secured = 1 + update_icon() + name = initial(name) + " ([tmr.time] secs)" + + loc.verbs += /obj/item/device/assembly_holder/timer_igniter/verb/configure + +/obj/item/device/assembly_holder/timer_igniter/detached() + loc.verbs -= /obj/item/device/assembly_holder/timer_igniter/verb/configure + ..() + +/obj/item/device/assembly_holder/timer_igniter/verb/configure() + set name = "Set Timer" + set category = "Object" + set src in usr + + if ( !(usr.isUnconscious() || usr.restrained()) ) + var/obj/item/device/assembly_holder/holder + if(istype(src,/obj/item/weapon/grenade/chem_grenade)) + var/obj/item/weapon/grenade/chem_grenade/gren = src + holder=gren.detonator + var/obj/item/device/assembly/timer/tmr = holder.a_left + if(!istype(tmr,/obj/item/device/assembly/timer)) + tmr = holder.a_right + if(!istype(tmr,/obj/item/device/assembly/timer)) + to_chat(usr, "This detonator has no timer.") + return + + if(tmr.timing) + to_chat(usr, "Clock is ticking already.") + else + var/ntime = input("Enter desired time in seconds", "Time", "5") as num + if (ntime>0 && ntime<1000) + tmr.time = ntime + name = initial(name) + "([tmr.time] secs)" + to_chat(usr, "Timer set to [tmr.time] seconds.") + else + to_chat(usr, "Timer can't be [ntime<=0?"negative":"more than 1000 seconds"].") + else + to_chat(usr, "You cannot do this while [usr.stat?"unconscious/dead":"restrained"].") diff --git a/code/modules/assembly/igniter.dm b/code/modules/assembly/igniter.dm index 155c1535554..289c12dd665 100644 --- a/code/modules/assembly/igniter.dm +++ b/code/modules/assembly/igniter.dm @@ -1,38 +1,38 @@ -/obj/item/device/assembly/igniter - name = "igniter" - desc = "A small electronic device able to ignite combustable substances." - icon_state = "igniter" - starting_materials = list(MAT_IRON = 500, MAT_GLASS = 50) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=1" - - secured = 1 - wires = WIRE_RECEIVE - -/obj/item/device/assembly/igniter/activate() - if(!..()) return 0//Cooldown check - - if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc - grenade.prime() - else - var/turf/location = get_turf(loc) - if(location) - location.hotspot_expose(1000,1000,surfaces=istype(loc,/turf)) - if (istype(src.loc,/obj/item/device/assembly_holder)) - if (istype(src.loc.loc, /obj/structure/reagent_dispensers/fueltank/)) - var/obj/structure/reagent_dispensers/fueltank/tank = src.loc.loc - if (tank && tank.modded) - tank.explode() - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - return 1 - - -/obj/item/device/assembly/igniter/attack_self(mob/user as mob) - activate() - add_fingerprint(user) - return +/obj/item/device/assembly/igniter + name = "igniter" + desc = "A small electronic device able to ignite combustable substances." + icon_state = "igniter" + starting_materials = list(MAT_IRON = 500, MAT_GLASS = 50) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=1" + + secured = 1 + wires = WIRE_RECEIVE + +/obj/item/device/assembly/igniter/activate() + if(!..()) return 0//Cooldown check + + if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) + var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc + grenade.prime() + else + var/turf/location = get_turf(loc) + if(location) + location.hotspot_expose(1000,1000,surfaces=istype(loc,/turf)) + if (istype(src.loc,/obj/item/device/assembly_holder)) + if (istype(src.loc.loc, /obj/structure/reagent_dispensers/fueltank/)) + var/obj/structure/reagent_dispensers/fueltank/tank = src.loc.loc + if (tank && tank.modded) + tank.explode() + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + return 1 + + +/obj/item/device/assembly/igniter/attack_self(mob/user as mob) + activate() + add_fingerprint(user) + return diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 16d5e046444..d2c8ca791c2 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -1,209 +1,209 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/device/assembly/infra - name = "infrared emitter" - short_name = "IR emitter" - - desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted." - icon_state = "infrared" - starting_materials = list(MAT_IRON = 1000, MAT_GLASS = 500) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=2" - - wires = WIRE_PULSE - - secured = 0 - - var/on = 0 - var/visible = 0 - var/obj/effect/beam/infrared/beam = null - - accessible_values = list( - "Visible" = "visible;number",\ - "On" = "on;number" - ) - - New() del(src) - - -///obj/item/device/assembly/infra/describe() -// return "The infrared trigger is [on?"on":"off"]." - -/obj/item/device/assembly/infra/activate() - if(!..()) - return 0//Cooldown check - on = !on - update_icon() - return 1 - - -/obj/item/device/assembly/infra/toggle_secure() - secured = !secured - if(secured) - processing_objects.Add(src) - else - on = 0 - if(beam) - qdel(beam) - processing_objects.Remove(src) - update_icon() - return secured - - -/obj/item/device/assembly/infra/update_icon() - overlays.len = 0 - attached_overlays = list() - if(on) - overlays += "infrared_on" - attached_overlays += "infrared_on" - - if(holder) - holder.update_icon() - return - - -/obj/item/device/assembly/infra/process()//Old code - if(1) return PROCESS_KILL - if(!on && beam) - qdel(beam) - return - if(beam || !secured) return - var/turf/T = null - if(isturf(loc)) - T = get_turf(src) - else if (holder) - if (istype(holder.loc,/turf)) - T = holder.loc - else if (isturf(holder.loc.loc)) //for onetankbombs and other tertiary builds with assemblies - T = holder.loc.loc - else if(istype(loc,/obj/item/weapon/grenade) && isturf(loc.loc)) - T = loc.loc - if(T) - if(!beam) - beam = new /obj/effect/beam/infrared(T) - beam.visible=visible - beam.emit(src) - return - - -/obj/item/device/assembly/infra/attack_hand() - qdel(beam) - ..() - return - - -/obj/item/device/assembly/infra/Move() - var/t = dir - ..() - dir = t - qdel(beam) - return - - -/obj/item/device/assembly/infra/holder_movement() - if(!holder) return 0 -// dir = holder.dir - qdel(beam) - return 1 - - -/obj/item/device/assembly/infra/proc/trigger_beam() - if((!secured)||(!on)||(cooldown > 0)) return 0 - pulse(0) - if(!holder) - visible_message("\icon[src] *beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - return - - -/obj/item/device/assembly/infra/interact(mob/user as mob)//TODO: change this this to the wire control panel - if(!secured) return - user.set_machine(src) - var/dat = text("Infrared Laser\nStatus: []
    \nVisibility: []
    \n
    ", (on ? text("On", src) : text("Off", src)), (src.visible ? text("Visible", src) : text("Invisible", src))) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\assembly\infrared.dm:117: dat += "

    Refresh" - dat += {"

    Refresh -

    Close"} - // END AUTOFIX - user << browse(dat, "window=infra") - onclose(user, "infra") - return - - -/obj/item/device/assembly/infra/Topic(href, href_list) - ..() - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=infra") - onclose(usr, "infra") - return - - if(href_list["state"]) - on = !(on) - update_icon() - - if(href_list["visible"]) - visible = !(visible) - - if(beam) - beam.set_visible(visible) - - if(href_list["close"]) - usr << browse(null, "window=infra") - return - - if(usr) - attack_self(usr) - - return - - -/obj/item/device/assembly/infra/verb/rotate()//This could likely be better - set name = "Rotate Infrared Laser" - set category = "Object" - set src in usr - - dir = turn(dir, 90) - return - -/***************************IBeam*********************************/ - -/obj/effect/beam/infrared - name = "i beam" - icon = 'icons/obj/projectiles.dmi' - icon_state = "ibeam" - var/limit = null - var/visible = 0.0 - var/left = null - anchored = 1.0 - flags = 0 - - - var/obj/item/device/assembly/infra/assembly - -/obj/effect/beam/infrared/proc/hit() - if(assembly) - assembly.trigger_beam() - -/obj/effect/beam/infrared/Crossed(atom/movable/O) - ..(O) - if(O && O.density && !istype(O, /obj/effect/beam)) - hit() - -/obj/effect/beam/infrared/proc/set_visible(v) - visible = v - if(next) - var/obj/effect/beam/infrared/B=next - B.set_visible(v) - -/obj/effect/beam/infrared/Bumped() - hit() - ..() - -/obj/effect/beam/infrared/spawn_child() - var/obj/effect/beam/infrared/B = ..() - if(!B) return null - B.visible=visible - return B +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/device/assembly/infra + name = "infrared emitter" + short_name = "IR emitter" + + desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted." + icon_state = "infrared" + starting_materials = list(MAT_IRON = 1000, MAT_GLASS = 500) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=2" + + wires = WIRE_PULSE + + secured = 0 + + var/on = 0 + var/visible = 0 + var/obj/effect/beam/infrared/beam = null + + accessible_values = list( + "Visible" = "visible;number",\ + "On" = "on;number" + ) + + New() del(src) + + +///obj/item/device/assembly/infra/describe() +// return "The infrared trigger is [on?"on":"off"]." + +/obj/item/device/assembly/infra/activate() + if(!..()) + return 0//Cooldown check + on = !on + update_icon() + return 1 + + +/obj/item/device/assembly/infra/toggle_secure() + secured = !secured + if(secured) + processing_objects.Add(src) + else + on = 0 + if(beam) + qdel(beam) + processing_objects.Remove(src) + update_icon() + return secured + + +/obj/item/device/assembly/infra/update_icon() + overlays.len = 0 + attached_overlays = list() + if(on) + overlays += "infrared_on" + attached_overlays += "infrared_on" + + if(holder) + holder.update_icon() + return + + +/obj/item/device/assembly/infra/process()//Old code + if(1) return PROCESS_KILL + if(!on && beam) + qdel(beam) + return + if(beam || !secured) return + var/turf/T = null + if(isturf(loc)) + T = get_turf(src) + else if (holder) + if (istype(holder.loc,/turf)) + T = holder.loc + else if (isturf(holder.loc.loc)) //for onetankbombs and other tertiary builds with assemblies + T = holder.loc.loc + else if(istype(loc,/obj/item/weapon/grenade) && isturf(loc.loc)) + T = loc.loc + if(T) + if(!beam) + beam = new /obj/effect/beam/infrared(T) + beam.visible=visible + beam.emit(src) + return + + +/obj/item/device/assembly/infra/attack_hand() + qdel(beam) + ..() + return + + +/obj/item/device/assembly/infra/Move() + var/t = dir + ..() + dir = t + qdel(beam) + return + + +/obj/item/device/assembly/infra/holder_movement() + if(!holder) return 0 +// dir = holder.dir + qdel(beam) + return 1 + + +/obj/item/device/assembly/infra/proc/trigger_beam() + if((!secured)||(!on)||(cooldown > 0)) return 0 + pulse(0) + if(!holder) + visible_message("\icon[src] *beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + return + + +/obj/item/device/assembly/infra/interact(mob/user as mob)//TODO: change this this to the wire control panel + if(!secured) return + user.set_machine(src) + var/dat = text("Infrared Laser\nStatus: []
    \nVisibility: []
    \n
    ", (on ? text("On", src) : text("Off", src)), (src.visible ? text("Visible", src) : text("Invisible", src))) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\assembly\infrared.dm:117: dat += "

    Refresh" + dat += {"

    Refresh +

    Close"} + // END AUTOFIX + user << browse(dat, "window=infra") + onclose(user, "infra") + return + + +/obj/item/device/assembly/infra/Topic(href, href_list) + ..() + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=infra") + onclose(usr, "infra") + return + + if(href_list["state"]) + on = !(on) + update_icon() + + if(href_list["visible"]) + visible = !(visible) + + if(beam) + beam.set_visible(visible) + + if(href_list["close"]) + usr << browse(null, "window=infra") + return + + if(usr) + attack_self(usr) + + return + + +/obj/item/device/assembly/infra/verb/rotate()//This could likely be better + set name = "Rotate Infrared Laser" + set category = "Object" + set src in usr + + dir = turn(dir, 90) + return + +/***************************IBeam*********************************/ + +/obj/effect/beam/infrared + name = "i beam" + icon = 'icons/obj/projectiles.dmi' + icon_state = "ibeam" + var/limit = null + var/visible = 0.0 + var/left = null + anchored = 1.0 + flags = 0 + + + var/obj/item/device/assembly/infra/assembly + +/obj/effect/beam/infrared/proc/hit() + if(assembly) + assembly.trigger_beam() + +/obj/effect/beam/infrared/Crossed(atom/movable/O) + ..(O) + if(O && O.density && !istype(O, /obj/effect/beam)) + hit() + +/obj/effect/beam/infrared/proc/set_visible(v) + visible = v + if(next) + var/obj/effect/beam/infrared/B=next + B.set_visible(v) + +/obj/effect/beam/infrared/Bumped() + hit() + ..() + +/obj/effect/beam/infrared/spawn_child() + var/obj/effect/beam/infrared/B = ..() + if(!B) return null + B.visible=visible + return B diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index f4be83f27d3..438ccbf116f 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -1,127 +1,127 @@ -/obj/item/device/assembly/mousetrap - name = "mousetrap" - desc = "A handy little spring-loaded trap for catching pesty rodents." - icon_state = "mousetrap" - starting_materials = list(MAT_IRON = 100) - w_type = RECYK_METAL - origin_tech = "combat=1" - var/armed = 0 - wires = WIRE_PULSE - -/obj/item/device/assembly/mousetrap/examine(mob/user) - ..() - if(armed) - to_chat(user, "It looks like it's armed.") - -/obj/item/device/assembly/mousetrap/update_icon() - if(armed) - icon_state = "mousetraparmed" - else - icon_state = "mousetrap" - if(holder) - holder.update_icon() - -/obj/item/device/assembly/mousetrap/proc/triggered(mob/target as mob, var/type = "feet") - if(!armed) - return - var/datum/organ/external/affecting = null - if(ishuman(target)) - var/mob/living/carbon/human/H = target - switch(type) - if("feet") - if(!H.shoes) - affecting = H.get_organ(pick("l_leg", "r_leg")) - H.Weaken(3) - if("l_hand", "r_hand") - if(!H.gloves) - affecting = H.get_organ(type) - H.Stun(3) - if(affecting) - if(affecting.take_damage(1, 0)) - H.UpdateDamageIcon() - H.updatehealth() - else if(ismouse(target)) - var/mob/living/simple_animal/mouse/M = target - visible_message("SPLAT!") - M.splat() - playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) - armed = 0 - update_icon() - pulse(0) - - -/obj/item/device/assembly/mousetrap/attack_self(mob/living/user as mob) - if(!armed) - to_chat(user, "You arm [src].") - else - if(((user.getBrainLoss() >= 60 || (M_CLUMSY in user.mutations)) && prob(50))) - var/which_hand = "l_hand" - if(!user.hand) - which_hand = "r_hand" - triggered(user, which_hand) - user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - return - to_chat(user, "You disarm [src].") - armed = !armed - update_icon() - playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3) - - -/obj/item/device/assembly/mousetrap/attack_hand(mob/living/user as mob) - if(armed) - if(((user.getBrainLoss() >= 60 || M_CLUMSY in user.mutations)) && prob(50)) - var/which_hand = "l_hand" - if(!user.hand) - which_hand = "r_hand" - triggered(user, which_hand) - user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - return - ..() - - -/obj/item/device/assembly/mousetrap/Crossed(AM as mob|obj) - if(armed) - if(ishuman(AM)) - var/mob/living/carbon/H = AM - if(H.m_intent == "run") - triggered(H) - H.visible_message("[H] accidentally steps on [src].", \ - "You accidentally step on [src]") - if(ismouse(AM)) - triggered(AM) - ..() - - -/obj/item/device/assembly/mousetrap/on_found(mob/finder as mob) - if(armed) - finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - triggered(finder, finder.hand ? "l_hand" : "r_hand") - return 1 //end the search! - return 0 - - -/obj/item/device/assembly/mousetrap/hitby(A as mob|obj) - if(!armed) - return ..() - visible_message("[src] is triggered by [A].") - triggered(null) - - -/obj/item/device/assembly/mousetrap/armed - icon_state = "mousetraparmed" - armed = 1 - - -/obj/item/device/assembly/mousetrap/verb/hide_under() - set src in oview(1) - set name = "Hide" - set category = "Object" - - if(usr.isUnconscious()) - return - - layer = TURF_LAYER+0.2 - to_chat(usr, "You hide [src].") +/obj/item/device/assembly/mousetrap + name = "mousetrap" + desc = "A handy little spring-loaded trap for catching pesty rodents." + icon_state = "mousetrap" + starting_materials = list(MAT_IRON = 100) + w_type = RECYK_METAL + origin_tech = "combat=1" + var/armed = 0 + wires = WIRE_PULSE + +/obj/item/device/assembly/mousetrap/examine(mob/user) + ..() + if(armed) + to_chat(user, "It looks like it's armed.") + +/obj/item/device/assembly/mousetrap/update_icon() + if(armed) + icon_state = "mousetraparmed" + else + icon_state = "mousetrap" + if(holder) + holder.update_icon() + +/obj/item/device/assembly/mousetrap/proc/triggered(mob/target as mob, var/type = "feet") + if(!armed) + return + var/datum/organ/external/affecting = null + if(ishuman(target)) + var/mob/living/carbon/human/H = target + switch(type) + if("feet") + if(!H.shoes) + affecting = H.get_organ(pick("l_leg", "r_leg")) + H.Weaken(3) + if("l_hand", "r_hand") + if(!H.gloves) + affecting = H.get_organ(type) + H.Stun(3) + if(affecting) + if(affecting.take_damage(1, 0)) + H.UpdateDamageIcon() + H.updatehealth() + else if(ismouse(target)) + var/mob/living/simple_animal/mouse/M = target + visible_message("SPLAT!") + M.splat() + playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) + armed = 0 + update_icon() + pulse(0) + + +/obj/item/device/assembly/mousetrap/attack_self(mob/living/user as mob) + if(!armed) + to_chat(user, "You arm [src].") + else + if(((user.getBrainLoss() >= 60 || (M_CLUMSY in user.mutations)) && prob(50))) + var/which_hand = "l_hand" + if(!user.hand) + which_hand = "r_hand" + triggered(user, which_hand) + user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") + return + to_chat(user, "You disarm [src].") + armed = !armed + update_icon() + playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3) + + +/obj/item/device/assembly/mousetrap/attack_hand(mob/living/user as mob) + if(armed) + if(((user.getBrainLoss() >= 60 || M_CLUMSY in user.mutations)) && prob(50)) + var/which_hand = "l_hand" + if(!user.hand) + which_hand = "r_hand" + triggered(user, which_hand) + user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") + return + ..() + + +/obj/item/device/assembly/mousetrap/Crossed(AM as mob|obj) + if(armed) + if(ishuman(AM)) + var/mob/living/carbon/H = AM + if(H.m_intent == "run") + triggered(H) + H.visible_message("[H] accidentally steps on [src].", \ + "You accidentally step on [src]") + if(ismouse(AM)) + triggered(AM) + ..() + + +/obj/item/device/assembly/mousetrap/on_found(mob/finder as mob) + if(armed) + finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") + triggered(finder, finder.hand ? "l_hand" : "r_hand") + return 1 //end the search! + return 0 + + +/obj/item/device/assembly/mousetrap/hitby(A as mob|obj) + if(!armed) + return ..() + visible_message("[src] is triggered by [A].") + triggered(null) + + +/obj/item/device/assembly/mousetrap/armed + icon_state = "mousetraparmed" + armed = 1 + + +/obj/item/device/assembly/mousetrap/verb/hide_under() + set src in oview(1) + set name = "Hide" + set category = "Object" + + if(usr.isUnconscious()) + return + + layer = TURF_LAYER+0.2 + to_chat(usr, "You hide [src].") diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm index 221ece8a999..c0dd05d956d 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -1,181 +1,181 @@ -/var/global/list/prox_sensor_ignored_types = list \ -( - /obj/effect/beam -) - -/obj/item/device/assembly/prox_sensor - name = "proximity sensor" - short_name = "prox sensor" - - desc = "Used for scanning and alerting when someone enters a certain proximity." - icon_state = "prox" - starting_materials = list(MAT_IRON = 800, MAT_GLASS = 200) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=1" - - wires = WIRE_PULSE | WIRE_RECEIVE - - flags = FPRINT | PROXMOVE - - secured = 0 - - var/scanning = 0 - var/timing = 0 - var/time = 10 - - var/default_time = 10 - - var/range = 2 - - accessible_values = list("Scanning" = "scanning;number",\ - "Scan range" = "range;number;1;5",\ - "Remaining time" = "time;number",\ - "Default time" = "default_time;number",\ - "Timing" = "timing;number") - -/obj/item/device/assembly/prox_sensor/activate() - if(!..()) return 0//Cooldown check - timing = !timing - update_icon() - return 0 - -/obj/item/device/assembly/prox_sensor/toggle_secure() - secured = !secured - if(secured) - processing_objects.Add(src) - else - scanning = 0 - timing = 0 - processing_objects.Remove(src) - update_icon() - return secured - -/obj/item/device/assembly/prox_sensor/HasProximity(var/atom/movable/AM) - if(timestopped || (loc && loc.timestopped)) - return - - if(is_type_in_list(AM, global.prox_sensor_ignored_types)) - return - - if(AM.move_speed < 12) - sense() - -/obj/item/device/assembly/prox_sensor/proc/sense() - var/turf/mainloc = get_turf(src) -// if(scanning && cooldown <= 0) -// mainloc.visible_message("\icon[src] *boop* *boop*", "*boop* *boop*") - if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 - pulse(0) - if(!holder) - mainloc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - return - -/obj/item/device/assembly/prox_sensor/process() - if(scanning) - var/turf/mainloc = get_turf(src) - for(var/mob/living/A in range(range,mainloc)) - if (A.move_speed < 12) - sense() - - if(timing && (time >= 0)) - time-- - if(timing && time <= 0) - timing = 0 - toggle_scan() - time = default_time - return - -/obj/item/device/assembly/prox_sensor/dropped() - spawn(0) - sense() - return - return - -/obj/item/device/assembly/prox_sensor/proc/toggle_scan() - if(!secured) return 0 - scanning = !scanning - update_icon() - return - -/obj/item/device/assembly/prox_sensor/update_icon() - overlays.len = 0 - attached_overlays = list() - if(timing) - overlays += "prox_timing" - attached_overlays += "prox_timing" - if(scanning) - overlays += "prox_scanning" - attached_overlays += "prox_scanning" - if(holder) - holder.update_icon() - if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc - grenade.primed(scanning) - return - -/obj/item/device/assembly/prox_sensor/Move() - ..() - sense() - return - -/obj/item/device/assembly/prox_sensor/interact(mob/user as mob)//TODO: Change this to the wires thingy - if(!secured) - user.show_message("The [name] is unsecured!") - return 0 - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = text("Proximity Sensor\n[] []:[]\n- - + +\n", (timing ? text("Arming", src) : text("Not Arming", src)), minute, second, src, src, src, src) - dat += text("
    Range: - [] +", src, range, src) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\assembly\\\proximity.dm:125: dat += "
    [scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" - dat += {"
    [scanning?"Armed":"Unarmed"] (Movement sensor active when armed!) -

    After countdown, reset time to [(default_time - default_time%60)/60]:[(default_time % 60)] -

    Refresh -

    Close"} - // END AUTOFIX - user << browse(dat, "window=prox") - onclose(user, "prox") - return - - -/obj/item/device/assembly/prox_sensor/Topic(href, href_list) - ..() - if(usr.stat || usr.restrained() || !in_range(loc, usr) || (!usr.canmove && !usr.locked_to)) - //If the user is handcuffed or out of range, or if they're unable to move, - //but NOT if they're unable to move as a result of being buckled into something, they're unable to use the device. - usr << browse(null, "window=prox") - onclose(usr, "prox") - return - - if(href_list["scanning"]) - toggle_scan() - - if(href_list["time"]) - timing = text2num(href_list["time"]) - update_icon() - - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 600) - - if(href_list["range"]) - var/r = text2num(href_list["range"]) - range += r - range = Clamp(range, 1, 5) - - if(href_list["set_default_time"]) - default_time = time - - if(href_list["close"]) - usr << browse(null, "window=prox") - return - - if(usr) - attack_self(usr) - - return +/var/global/list/prox_sensor_ignored_types = list \ +( + /obj/effect/beam +) + +/obj/item/device/assembly/prox_sensor + name = "proximity sensor" + short_name = "prox sensor" + + desc = "Used for scanning and alerting when someone enters a certain proximity." + icon_state = "prox" + starting_materials = list(MAT_IRON = 800, MAT_GLASS = 200) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=1" + + wires = WIRE_PULSE | WIRE_RECEIVE + + flags = FPRINT | PROXMOVE + + secured = 0 + + var/scanning = 0 + var/timing = 0 + var/time = 10 + + var/default_time = 10 + + var/range = 2 + + accessible_values = list("Scanning" = "scanning;number",\ + "Scan range" = "range;number;1;5",\ + "Remaining time" = "time;number",\ + "Default time" = "default_time;number",\ + "Timing" = "timing;number") + +/obj/item/device/assembly/prox_sensor/activate() + if(!..()) return 0//Cooldown check + timing = !timing + update_icon() + return 0 + +/obj/item/device/assembly/prox_sensor/toggle_secure() + secured = !secured + if(secured) + processing_objects.Add(src) + else + scanning = 0 + timing = 0 + processing_objects.Remove(src) + update_icon() + return secured + +/obj/item/device/assembly/prox_sensor/HasProximity(var/atom/movable/AM) + if(timestopped || (loc && loc.timestopped)) + return + + if(is_type_in_list(AM, global.prox_sensor_ignored_types)) + return + + if(AM.move_speed < 12) + sense() + +/obj/item/device/assembly/prox_sensor/proc/sense() + var/turf/mainloc = get_turf(src) +// if(scanning && cooldown <= 0) +// mainloc.visible_message("\icon[src] *boop* *boop*", "*boop* *boop*") + if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 + pulse(0) + if(!holder) + mainloc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + return + +/obj/item/device/assembly/prox_sensor/process() + if(scanning) + var/turf/mainloc = get_turf(src) + for(var/mob/living/A in range(range,mainloc)) + if (A.move_speed < 12) + sense() + + if(timing && (time >= 0)) + time-- + if(timing && time <= 0) + timing = 0 + toggle_scan() + time = default_time + return + +/obj/item/device/assembly/prox_sensor/dropped() + spawn(0) + sense() + return + return + +/obj/item/device/assembly/prox_sensor/proc/toggle_scan() + if(!secured) return 0 + scanning = !scanning + update_icon() + return + +/obj/item/device/assembly/prox_sensor/update_icon() + overlays.len = 0 + attached_overlays = list() + if(timing) + overlays += "prox_timing" + attached_overlays += "prox_timing" + if(scanning) + overlays += "prox_scanning" + attached_overlays += "prox_scanning" + if(holder) + holder.update_icon() + if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) + var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc + grenade.primed(scanning) + return + +/obj/item/device/assembly/prox_sensor/Move() + ..() + sense() + return + +/obj/item/device/assembly/prox_sensor/interact(mob/user as mob)//TODO: Change this to the wires thingy + if(!secured) + user.show_message("The [name] is unsecured!") + return 0 + var/second = time % 60 + var/minute = (time - second) / 60 + var/dat = text("Proximity Sensor\n[] []:[]\n- - + +\n", (timing ? text("Arming", src) : text("Not Arming", src)), minute, second, src, src, src, src) + dat += text("
    Range: - [] +", src, range, src) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\assembly\\\proximity.dm:125: dat += "
    [scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" + dat += {"
    [scanning?"Armed":"Unarmed"] (Movement sensor active when armed!) +

    After countdown, reset time to [(default_time - default_time%60)/60]:[(default_time % 60)] +

    Refresh +

    Close"} + // END AUTOFIX + user << browse(dat, "window=prox") + onclose(user, "prox") + return + + +/obj/item/device/assembly/prox_sensor/Topic(href, href_list) + ..() + if(usr.stat || usr.restrained() || !in_range(loc, usr) || (!usr.canmove && !usr.locked_to)) + //If the user is handcuffed or out of range, or if they're unable to move, + //but NOT if they're unable to move as a result of being buckled into something, they're unable to use the device. + usr << browse(null, "window=prox") + onclose(usr, "prox") + return + + if(href_list["scanning"]) + toggle_scan() + + if(href_list["time"]) + timing = text2num(href_list["time"]) + update_icon() + + if(href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 600) + + if(href_list["range"]) + var/r = text2num(href_list["range"]) + range += r + range = Clamp(range, 1, 5) + + if(href_list["set_default_time"]) + default_time = time + + if(href_list["close"]) + usr << browse(null, "window=prox") + return + + if(usr) + attack_self(usr) + + return diff --git a/code/modules/assembly/shock_kit.dm b/code/modules/assembly/shock_kit.dm index 13ec792af60..88ba5d4ad97 100644 --- a/code/modules/assembly/shock_kit.dm +++ b/code/modules/assembly/shock_kit.dm @@ -1,47 +1,47 @@ -/obj/item/assembly/shock_kit - name = "electrohelmet assembly" - desc = "This appears to be made from both an electropack and a helmet." - icon_state = "shock_kit" - var/obj/item/clothing/head/helmet/part1 = null - var/obj/item/device/radio/electropack/part2 = null - var/status = 0 - w_class = 5.0 - flags = FPRINT - siemens_coefficient = 1 - -/obj/item/assembly/shock_kit/Destroy() - del(part1) - del(part2) - ..() - return - -/obj/item/assembly/shock_kit/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench) && !status) - var/turf/T = loc - if(ismob(T)) - T = T.loc - part1.loc = T - part2.loc = T - part1.master = null - part2.master = null - part1 = null - part2 = null - del(src) - return - if(istype(W, /obj/item/weapon/screwdriver)) - status = !status - to_chat(user, "[src] is now [status ? "secured" : "unsecured"]!") - add_fingerprint(user) - return - -/obj/item/assembly/shock_kit/attack_self(mob/user as mob) - part1.attack_self(user, status) - part2.attack_self(user, status) - add_fingerprint(user) - return - -/obj/item/assembly/shock_kit/receive_signal() - if(istype(loc, /obj/structure/bed/chair/e_chair)) - var/obj/structure/bed/chair/e_chair/C = loc - C.shock() - return +/obj/item/assembly/shock_kit + name = "electrohelmet assembly" + desc = "This appears to be made from both an electropack and a helmet." + icon_state = "shock_kit" + var/obj/item/clothing/head/helmet/part1 = null + var/obj/item/device/radio/electropack/part2 = null + var/status = 0 + w_class = 5.0 + flags = FPRINT + siemens_coefficient = 1 + +/obj/item/assembly/shock_kit/Destroy() + del(part1) + del(part2) + ..() + return + +/obj/item/assembly/shock_kit/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench) && !status) + var/turf/T = loc + if(ismob(T)) + T = T.loc + part1.loc = T + part2.loc = T + part1.master = null + part2.master = null + part1 = null + part2 = null + del(src) + return + if(istype(W, /obj/item/weapon/screwdriver)) + status = !status + to_chat(user, "[src] is now [status ? "secured" : "unsecured"]!") + add_fingerprint(user) + return + +/obj/item/assembly/shock_kit/attack_self(mob/user as mob) + part1.attack_self(user, status) + part2.attack_self(user, status) + add_fingerprint(user) + return + +/obj/item/assembly/shock_kit/receive_signal() + if(istype(loc, /obj/structure/bed/chair/e_chair)) + var/obj/structure/bed/chair/e_chair/C = loc + C.shock() + return diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 0e7fe7985a1..00bf6e9c73e 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -1,278 +1,278 @@ -/obj/item/device/assembly/signaler - name = "remote signaling device" - short_name = "signaler" - - desc = "Used to remotely activate devices." - icon_state = "signaller" - item_state = "signaler" - starting_materials = list(MAT_IRON = 1000, MAT_GLASS = 200) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=1" - wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE - - secured = 1 - - var/code = 30 - var/frequency = 1457 - var/delay = 0 - var/datum/wires/connected = null - var/datum/radio_frequency/radio_connection - var/deadman = 0 - - accessible_values = list("Code (1 to 100)" = "code;number;1;100",\ - "Frequency" = "frequency;number") - -/obj/item/device/assembly/signaler/New() - ..() - spawn(40)//delay so the radio_controller has time to initialize - set_frequency(frequency) - return - -/obj/item/device/assembly/signaler/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = W - if(R.amount >= 1) - R.use(1) - new /obj/machinery/conveyor_switch(get_turf(src.loc)) - user.u_equip(src,0) - qdel(src) - - if(istype(W, /obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/R = W - if(R.amount >= 1) - R.use(1) - var/obj/item/mounted/frame/driver_button/signaler_button/I = new (get_turf(src.loc)) - I.code = src.code - I.frequency = src.frequency - user.u_equip(src,0) - qdel(src) - -/obj/item/device/assembly/signaler/activate() - if(cooldown > 0) return 0 - cooldown = 2 - spawn(10) - process_cooldown() - - signal() - return 1 - -/obj/item/device/assembly/signaler/update_icon() - if(holder) - holder.update_icon() - return - -/obj/item/device/assembly/signaler/interact(mob/user as mob, flag1) - var/t1 = "-------" -// if ((src.b_stat && !( flag1 ))) -// t1 = text("-------
    \nGreen Wire: []
    \nRed Wire: []
    \nBlue Wire: []
    \n", (src.wires & 4 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 2 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 1 ? text("Cut Wire", src) : text("Mend Wire", src))) -// else -// t1 = "-------" Speaker: [src.listening ? "Engaged" : "Disengaged"]
    - var/dat = {" - - - Send Signal
    - Frequency/Code for signaler:
    - Frequency: - - - - - [format_frequency(src.frequency)] - + - +
    - - Code: - - - - - [src.code] - + - +
    - [t1] -
    "} - user << browse(dat, "window=radio") - onclose(user, "radio") - return - - -/obj/item/device/assembly/signaler/Topic(href, href_list) - ..() - if(usr.stat || usr.restrained() || !in_range(loc, usr) || (!usr.canmove && !usr.locked_to)) - //If the user is handcuffed or out of range, or if they're unable to move, - //but NOT if they're unable to move as a result of being buckled into something, they're unable to use the device. - usr << browse(null, "window=radio") - onclose(usr, "radio") - return - - if(href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if(new_frequency < MINIMUM_FREQUENCY || new_frequency > MAXIMUM_FREQUENCY) - new_frequency = sanitize_frequency(new_frequency) - set_frequency(new_frequency) - - if(href_list["code"]) - src.code += text2num(href_list["code"]) - src.code = round(src.code) - src.code = min(100, src.code) - src.code = max(1, src.code) - - if(href_list["send"]) - spawn( 0 ) - signal() - - if(usr) - attack_self(usr) - -/obj/item/device/assembly/signaler/proc/signal() - if(!radio_connection) return - - if(!(frequency in (MINIMUM_FREQUENCY to MAXIMUM_FREQUENCY))) return - if(!code in (1 to 100)) return - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source = src - signal.encryption = code - signal.data["message"] = "ACTIVATE" - radio_connection.post_signal(src, signal) - - var/time = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - if(usr) - var/mob/user = usr - if(user) - lastsignalers.Add("[time] : [user.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - else - lastsignalers.Add("[time] : (NO USER FOUND) used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - return -/* - for(var/obj/item/device/assembly/signaler/S in world) - if(!S) continue - if(S == src) continue - if((S.frequency == src.frequency) && (S.code == src.code)) - spawn(0) - if(S) S.pulse(0) - return 0*/ - - -/obj/item/device/assembly/signaler/pulse(var/radio = 0) - if(src.connected && src.wires) - connected.Pulse(src) - else - return ..(radio) - - -/obj/item/device/assembly/signaler/receive_signal(datum/signal/signal) - if(!signal) return 0 - if(signal.encryption != code) return 0 - if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 - pulse(1) - - if(!holder) - for(var/mob/O in hearers(1, src.loc)) - O.show_message(text("\icon[] *beep* *beep*", src), 1, "*beep* *beep*", 2) - return - - -/obj/item/device/assembly/signaler/proc/set_frequency(new_frequency) - if(!radio_controller) - spawn(20) - if(!radio_controller) - visible_message("Cannot initialize the radio_controller, this is a bug, tell a coder") - return - else - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) - else - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) - return - -/obj/item/device/assembly/signaler/process() - if(loc) - var/atom/A = loc - if(A.timestopped) return - if(!deadman) - processing_objects.Remove(src) - var/mob/M = src.loc - - if(!M || !ismob(M)) - if(prob(5)) - signal() - deadman = 0 - processing_objects.Remove(src) - else if(prob(5)) - M.visible_message("[M]'s finger twitches a bit over [src]'s signal button!") - return - -/obj/item/device/assembly/signaler/verb/deadman_it() - set src in usr - set name = "Threaten to push the button!" - set desc = "BOOOOM!" - - if(usr) - var/mob/user = usr - deadman = 1 - processing_objects.Add(src) - user.visible_message("[user] moves their finger over [src]'s signal button...") - -///Mounted Signaler Button/// -/obj/item/device/assembly/signaler/signaler_button - name = "signaler button" - icon = 'icons/obj/objects.dmi' - icon_state = "launcherbtt" - desc = "Can be used to send signals to various frequencies." - var/id_tag = "default" - var/active = 0 - anchored = 1.0 - show_status = 0 - var/activated = 0 - - ghost_read = 0 // Deactivate ghost touching. - ghost_write = 0 - -/obj/item/device/assembly/signaler/signaler_button/New(turf/loc, var/w_dir=null) - ..() - switch(w_dir) - if(NORTH) - pixel_y = 25 - if(SOUTH) - pixel_y = -25 - if(EAST) - pixel_x = 25 - if(WEST) - pixel_x = -25 - -/obj/item/device/assembly/signaler/signaler_button/attack_hand(mob/user) - if(!activated) - activated = 1 - icon_state = "launcheract" - activate() - sleep(20) - icon_state = "launcherbtt" - activated = 0 - -/obj/item/device/assembly/signaler/signaler_button/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/pen)) //Naming the button without having to use a labeler - var/n_name = copytext(sanitize(input(user, "What would you like to name this button?", "Button Labeling", null) as text|null), 1, MAX_NAME_LEN*3) - if(n_name && Adjacent(user) && !user.stat) - name = "[n_name]" - return - if(istype(W, /obj/item/weapon/crowbar)) - to_chat(user, "You begin prying \the [src] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src,10)) - to_chat(user, "You pry the button off of the wall.") - var/obj/item/mounted/frame/driver_button/signaler_button/I = new (get_turf(user)) - I.code = src.code - I.frequency = src.frequency - qdel(src) - return - if(istype(W, /obj/item/device/multitool)) - interact(user, null) - return - -/obj/item/device/assembly/signaler/set_value(var/var_name, var/new_value) - if(var_name == "frequency") - new_value = sanitize_frequency(new_value) - - return ..(var_name, new_value) +/obj/item/device/assembly/signaler + name = "remote signaling device" + short_name = "signaler" + + desc = "Used to remotely activate devices." + icon_state = "signaller" + item_state = "signaler" + starting_materials = list(MAT_IRON = 1000, MAT_GLASS = 200) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=1" + wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE + + secured = 1 + + var/code = 30 + var/frequency = 1457 + var/delay = 0 + var/datum/wires/connected = null + var/datum/radio_frequency/radio_connection + var/deadman = 0 + + accessible_values = list("Code (1 to 100)" = "code;number;1;100",\ + "Frequency" = "frequency;number") + +/obj/item/device/assembly/signaler/New() + ..() + spawn(40)//delay so the radio_controller has time to initialize + set_frequency(frequency) + return + +/obj/item/device/assembly/signaler/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = W + if(R.amount >= 1) + R.use(1) + new /obj/machinery/conveyor_switch(get_turf(src.loc)) + user.u_equip(src,0) + qdel(src) + + if(istype(W, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/R = W + if(R.amount >= 1) + R.use(1) + var/obj/item/mounted/frame/driver_button/signaler_button/I = new (get_turf(src.loc)) + I.code = src.code + I.frequency = src.frequency + user.u_equip(src,0) + qdel(src) + +/obj/item/device/assembly/signaler/activate() + if(cooldown > 0) return 0 + cooldown = 2 + spawn(10) + process_cooldown() + + signal() + return 1 + +/obj/item/device/assembly/signaler/update_icon() + if(holder) + holder.update_icon() + return + +/obj/item/device/assembly/signaler/interact(mob/user as mob, flag1) + var/t1 = "-------" +// if ((src.b_stat && !( flag1 ))) +// t1 = text("-------
    \nGreen Wire: []
    \nRed Wire: []
    \nBlue Wire: []
    \n", (src.wires & 4 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 2 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 1 ? text("Cut Wire", src) : text("Mend Wire", src))) +// else +// t1 = "-------" Speaker: [src.listening ? "Engaged" : "Disengaged"]
    + var/dat = {" + + + Send Signal
    + Frequency/Code for signaler:
    + Frequency: + - + - + [format_frequency(src.frequency)] + + + +
    + + Code: + - + - + [src.code] + + + +
    + [t1] +
    "} + user << browse(dat, "window=radio") + onclose(user, "radio") + return + + +/obj/item/device/assembly/signaler/Topic(href, href_list) + ..() + if(usr.stat || usr.restrained() || !in_range(loc, usr) || (!usr.canmove && !usr.locked_to)) + //If the user is handcuffed or out of range, or if they're unable to move, + //but NOT if they're unable to move as a result of being buckled into something, they're unable to use the device. + usr << browse(null, "window=radio") + onclose(usr, "radio") + return + + if(href_list["freq"]) + var/new_frequency = (frequency + text2num(href_list["freq"])) + if(new_frequency < MINIMUM_FREQUENCY || new_frequency > MAXIMUM_FREQUENCY) + new_frequency = sanitize_frequency(new_frequency) + set_frequency(new_frequency) + + if(href_list["code"]) + src.code += text2num(href_list["code"]) + src.code = round(src.code) + src.code = min(100, src.code) + src.code = max(1, src.code) + + if(href_list["send"]) + spawn( 0 ) + signal() + + if(usr) + attack_self(usr) + +/obj/item/device/assembly/signaler/proc/signal() + if(!radio_connection) return + + if(!(frequency in (MINIMUM_FREQUENCY to MAXIMUM_FREQUENCY))) return + if(!code in (1 to 100)) return + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source = src + signal.encryption = code + signal.data["message"] = "ACTIVATE" + radio_connection.post_signal(src, signal) + + var/time = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + if(usr) + var/mob/user = usr + if(user) + lastsignalers.Add("[time] : [user.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + else + lastsignalers.Add("[time] : (NO USER FOUND) used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + return +/* + for(var/obj/item/device/assembly/signaler/S in world) + if(!S) continue + if(S == src) continue + if((S.frequency == src.frequency) && (S.code == src.code)) + spawn(0) + if(S) S.pulse(0) + return 0*/ + + +/obj/item/device/assembly/signaler/pulse(var/radio = 0) + if(src.connected && src.wires) + connected.Pulse(src) + else + return ..(radio) + + +/obj/item/device/assembly/signaler/receive_signal(datum/signal/signal) + if(!signal) return 0 + if(signal.encryption != code) return 0 + if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 + pulse(1) + + if(!holder) + for(var/mob/O in hearers(1, src.loc)) + O.show_message(text("\icon[] *beep* *beep*", src), 1, "*beep* *beep*", 2) + return + + +/obj/item/device/assembly/signaler/proc/set_frequency(new_frequency) + if(!radio_controller) + spawn(20) + if(!radio_controller) + visible_message("Cannot initialize the radio_controller, this is a bug, tell a coder") + return + else + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) + else + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) + return + +/obj/item/device/assembly/signaler/process() + if(loc) + var/atom/A = loc + if(A.timestopped) return + if(!deadman) + processing_objects.Remove(src) + var/mob/M = src.loc + + if(!M || !ismob(M)) + if(prob(5)) + signal() + deadman = 0 + processing_objects.Remove(src) + else if(prob(5)) + M.visible_message("[M]'s finger twitches a bit over [src]'s signal button!") + return + +/obj/item/device/assembly/signaler/verb/deadman_it() + set src in usr + set name = "Threaten to push the button!" + set desc = "BOOOOM!" + + if(usr) + var/mob/user = usr + deadman = 1 + processing_objects.Add(src) + user.visible_message("[user] moves their finger over [src]'s signal button...") + +///Mounted Signaler Button/// +/obj/item/device/assembly/signaler/signaler_button + name = "signaler button" + icon = 'icons/obj/objects.dmi' + icon_state = "launcherbtt" + desc = "Can be used to send signals to various frequencies." + var/id_tag = "default" + var/active = 0 + anchored = 1.0 + show_status = 0 + var/activated = 0 + + ghost_read = 0 // Deactivate ghost touching. + ghost_write = 0 + +/obj/item/device/assembly/signaler/signaler_button/New(turf/loc, var/w_dir=null) + ..() + switch(w_dir) + if(NORTH) + pixel_y = 25 + if(SOUTH) + pixel_y = -25 + if(EAST) + pixel_x = 25 + if(WEST) + pixel_x = -25 + +/obj/item/device/assembly/signaler/signaler_button/attack_hand(mob/user) + if(!activated) + activated = 1 + icon_state = "launcheract" + activate() + sleep(20) + icon_state = "launcherbtt" + activated = 0 + +/obj/item/device/assembly/signaler/signaler_button/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/pen)) //Naming the button without having to use a labeler + var/n_name = copytext(sanitize(input(user, "What would you like to name this button?", "Button Labeling", null) as text|null), 1, MAX_NAME_LEN*3) + if(n_name && Adjacent(user) && !user.stat) + name = "[n_name]" + return + if(istype(W, /obj/item/weapon/crowbar)) + to_chat(user, "You begin prying \the [src] off the wall.") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src,10)) + to_chat(user, "You pry the button off of the wall.") + var/obj/item/mounted/frame/driver_button/signaler_button/I = new (get_turf(user)) + I.code = src.code + I.frequency = src.frequency + qdel(src) + return + if(istype(W, /obj/item/device/multitool)) + interact(user, null) + return + +/obj/item/device/assembly/signaler/set_value(var/var_name, var/new_value) + if(var_name == "frequency") + new_value = sanitize_frequency(new_value) + + return ..(var_name, new_value) diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index bf66be38666..01d1a3d336d 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -1,119 +1,119 @@ -/obj/item/device/assembly/timer - name = "timer" - desc = "Used to time things. Works well with contraptions which have to count down. Tick tock." - icon_state = "timer" - starting_materials = list(MAT_IRON = 500, MAT_GLASS = 50) - w_type = RECYK_ELECTRONIC - origin_tech = "magnets=1" - - wires = WIRE_PULSE | WIRE_RECEIVE - - secured = 0 - - var/timing = 0 - var/time = 10 - - var/default_time = 10 - - accessible_values = list("Remaining time" = "time;number",\ - "Default time" = "default_time;number",\ - "Timing" = "timing;number") - -/obj/item/device/assembly/timer/activate() - if(!..()) return 0//Cooldown check - - timing = !timing - - update_icon() - return 0 - -/obj/item/device/assembly/timer/toggle_secure() - secured = !secured - if(secured) - processing_objects.Add(src) - else - timing = 0 - processing_objects.Remove(src) - update_icon() - return secured - -/obj/item/device/assembly/timer/proc/timer_end() - if(!secured) return 0 - pulse(0) - if(!holder) - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - return - -/obj/item/device/assembly/timer/process() - if(timing && (time > 0)) - time-- - if(timing && time <= 0) - timing = 0 - timer_end() - time = default_time - return - - -/obj/item/device/assembly/timer/update_icon() - overlays.len = 0 - attached_overlays = list() - if(timing) - overlays += "timer_timing" - attached_overlays += "timer_timing" - if(holder) - holder.update_icon() - return - - -/obj/item/device/assembly/timer/interact(mob/user as mob)//TODO: Have this use the wires - if(!secured) - user.show_message("The [name] is unsecured!") - return 0 - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = text("Timing Unit\n[] []:[]\n- - + +\n", (timing ? text("Timing", src) : text("Not Timing", src)), minute, second, src, src, src, src) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\assembly\timer.dm:80: dat += "

    Refresh" - dat += "

    After countdown, reset time to [(default_time - default_time%60)/60]:[(default_time % 60)]" - dat += {"

    Refresh -

    Close"} - // END AUTOFIX - user << browse(dat, "window=timer") - onclose(user, "timer") - return - - -/obj/item/device/assembly/timer/Topic(href, href_list) - ..() - if(usr.stat || usr.restrained() || !in_range(loc, usr) || (!usr.canmove && !usr.locked_to)) - //If the user is handcuffed or out of range, or if they're unable to move, - //but NOT if they're unable to move as a result of being buckled into something, they're unable to use the device. - usr << browse(null, "window=timer") - onclose(usr, "timer") - return - - if(href_list["time"]) - timing = text2num(href_list["time"]) - message_admins("[key_name_admin(usr)] [timing ? "started" : "stopped"] a timer at [formatJumpTo(src)]") - update_icon() - - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 600) - - if(href_list["close"]) - usr << browse(null, "window=timer") - return - - if(href_list["set_default_time"]) - default_time = time - - if(usr) - attack_self(usr) - - return +/obj/item/device/assembly/timer + name = "timer" + desc = "Used to time things. Works well with contraptions which have to count down. Tick tock." + icon_state = "timer" + starting_materials = list(MAT_IRON = 500, MAT_GLASS = 50) + w_type = RECYK_ELECTRONIC + origin_tech = "magnets=1" + + wires = WIRE_PULSE | WIRE_RECEIVE + + secured = 0 + + var/timing = 0 + var/time = 10 + + var/default_time = 10 + + accessible_values = list("Remaining time" = "time;number",\ + "Default time" = "default_time;number",\ + "Timing" = "timing;number") + +/obj/item/device/assembly/timer/activate() + if(!..()) return 0//Cooldown check + + timing = !timing + + update_icon() + return 0 + +/obj/item/device/assembly/timer/toggle_secure() + secured = !secured + if(secured) + processing_objects.Add(src) + else + timing = 0 + processing_objects.Remove(src) + update_icon() + return secured + +/obj/item/device/assembly/timer/proc/timer_end() + if(!secured) return 0 + pulse(0) + if(!holder) + visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + return + +/obj/item/device/assembly/timer/process() + if(timing && (time > 0)) + time-- + if(timing && time <= 0) + timing = 0 + timer_end() + time = default_time + return + + +/obj/item/device/assembly/timer/update_icon() + overlays.len = 0 + attached_overlays = list() + if(timing) + overlays += "timer_timing" + attached_overlays += "timer_timing" + if(holder) + holder.update_icon() + return + + +/obj/item/device/assembly/timer/interact(mob/user as mob)//TODO: Have this use the wires + if(!secured) + user.show_message("The [name] is unsecured!") + return 0 + var/second = time % 60 + var/minute = (time - second) / 60 + var/dat = text("Timing Unit\n[] []:[]\n- - + +\n", (timing ? text("Timing", src) : text("Not Timing", src)), minute, second, src, src, src, src) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\assembly\timer.dm:80: dat += "

    Refresh" + dat += "

    After countdown, reset time to [(default_time - default_time%60)/60]:[(default_time % 60)]" + dat += {"

    Refresh +

    Close"} + // END AUTOFIX + user << browse(dat, "window=timer") + onclose(user, "timer") + return + + +/obj/item/device/assembly/timer/Topic(href, href_list) + ..() + if(usr.stat || usr.restrained() || !in_range(loc, usr) || (!usr.canmove && !usr.locked_to)) + //If the user is handcuffed or out of range, or if they're unable to move, + //but NOT if they're unable to move as a result of being buckled into something, they're unable to use the device. + usr << browse(null, "window=timer") + onclose(usr, "timer") + return + + if(href_list["time"]) + timing = text2num(href_list["time"]) + message_admins("[key_name_admin(usr)] [timing ? "started" : "stopped"] a timer at [formatJumpTo(src)]") + update_icon() + + if(href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 600) + + if(href_list["close"]) + usr << browse(null, "window=timer") + return + + if(href_list["set_default_time"]) + default_time = time + + if(usr) + attack_self(usr) + + return diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm index 6573523a443..24133a9854e 100644 --- a/code/modules/awaymissions/bluespaceartillery.dm +++ b/code/modules/awaymissions/bluespaceartillery.dm @@ -1,67 +1,67 @@ - -/obj/machinery/artillerycontrol - var/reload = 180 - name = "bluespace artillery control" - icon_state = "control_boxp1" - icon = 'icons/obj/machines/particle_accelerator.dmi' - density = 1 - anchored = 1 - -/obj/machinery/artillerycontrol/process() - if(src.reload<180) - src.reload++ - -/obj/structure/artilleryplaceholder - name = "artillery" - icon = 'icons/obj/machines/artillery.dmi' - anchored = 1 - density = 1 - -/obj/structure/artilleryplaceholder/decorative - density = 0 - -/obj/machinery/artillerycontrol/attack_hand(mob/user as mob) - user.set_machine(src) - var/dat = "Bluespace Artillery Control:
    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\awaymissionsspaceartillery.dm:26: dat += "Locked on
    " - dat += {"Locked on
    - Charge progress: [reload]/180:
    - Open Fire
    - Deployment of weapon authorized by
    Nanotrasen Naval Command

    Remember, friendly fire is grounds for termination of your contract and life.
    "} - // END AUTOFIX - user << browse(dat, "window=scroll") - onclose(user, "scroll") - return - -/obj/machinery/artillerycontrol/Topic(href, href_list) - if(..()) return 1 - else - var/A - A = input("Area to jump bombard", "Open Fire", A) in teleportlocs - var/area/thearea = teleportlocs[A] - if (usr.stat || usr.restrained()) return - if(src.reload < 180) return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - command_alert("Bluespace artillery fire detected. Brace for impact.") - message_admins("[key_name_admin(usr)] has launched an artillery strike.", 1) - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - L+=T - var/loc = pick(L) - explosion(loc,2,5,11) - reload = 0 - -/*mob/proc/openfire() - var/A - A = input("Area to jump bombard", "Open Fire", A) in teleportlocs - var/area/thearea = teleportlocs[A] - command_alert("Bluespace artillery fire detected. Brace for impact.") - spawn(30) - var/list/L = list() - - for(var/turf/T in get_area_turfs(thearea.type)) - L+=T - var/loc = pick(L) + +/obj/machinery/artillerycontrol + var/reload = 180 + name = "bluespace artillery control" + icon_state = "control_boxp1" + icon = 'icons/obj/machines/particle_accelerator.dmi' + density = 1 + anchored = 1 + +/obj/machinery/artillerycontrol/process() + if(src.reload<180) + src.reload++ + +/obj/structure/artilleryplaceholder + name = "artillery" + icon = 'icons/obj/machines/artillery.dmi' + anchored = 1 + density = 1 + +/obj/structure/artilleryplaceholder/decorative + density = 0 + +/obj/machinery/artillerycontrol/attack_hand(mob/user as mob) + user.set_machine(src) + var/dat = "Bluespace Artillery Control:
    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\awaymissionsspaceartillery.dm:26: dat += "Locked on
    " + dat += {"Locked on
    + Charge progress: [reload]/180:
    + Open Fire
    + Deployment of weapon authorized by
    Nanotrasen Naval Command

    Remember, friendly fire is grounds for termination of your contract and life.
    "} + // END AUTOFIX + user << browse(dat, "window=scroll") + onclose(user, "scroll") + return + +/obj/machinery/artillerycontrol/Topic(href, href_list) + if(..()) return 1 + else + var/A + A = input("Area to jump bombard", "Open Fire", A) in teleportlocs + var/area/thearea = teleportlocs[A] + if (usr.stat || usr.restrained()) return + if(src.reload < 180) return + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + command_alert("Bluespace artillery fire detected. Brace for impact.") + message_admins("[key_name_admin(usr)] has launched an artillery strike.", 1) + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + L+=T + var/loc = pick(L) + explosion(loc,2,5,11) + reload = 0 + +/*mob/proc/openfire() + var/A + A = input("Area to jump bombard", "Open Fire", A) in teleportlocs + var/area/thearea = teleportlocs[A] + command_alert("Bluespace artillery fire detected. Brace for impact.") + spawn(30) + var/list/L = list() + + for(var/turf/T in get_area_turfs(thearea.type)) + L+=T + var/loc = pick(L) explosion(loc,2,5,11)*/ \ No newline at end of file diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index a9ce0414ff9..77844cd60f0 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -1,275 +1,275 @@ - -/obj/effect/landmark/corpse - name = "Unknown" - var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now - var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse. - var/corpsesuit = null - var/corpseshoes = null - var/corpsegloves = null - var/corpseradio = null - var/corpseglasses = null - var/corpsemask = null - var/corpsehelmet = null - var/corpsebelt = null - var/corpsepocket1 = null - var/corpsepocket2 = null - var/corpseback = null - var/corpseid = 0 //Just set to 1 if you want them to have an ID - var/corpseidjob = null // Needs to be in quotes, such as "Clown" or "Chef." This just determines what the ID reads as, not their access - var/corpseidaccess = null //This is for access. See access.dm for which jobs give what access. Again, put in quotes. Use "Captain" if you want it to be all access. - var/corpseidicon = null //For setting it to be a gold, silver, centcomm etc ID - var/mutantrace = "human" - -/obj/effect/landmark/corpse/New() - if(ticker) - initialize() - -/obj/effect/landmark/corpse/initialize() - createCorpse() - -/obj/effect/landmark/corpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it. - var/mob/living/carbon/human/M = new /mob/living/carbon/human (loc) - M.dna.mutantrace = mutantrace - M.real_name = src.name - M.adjustOxyLoss(200) //Kills the new mob - M.iscorpse = 1 - if(src.corpseuniform) - M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform) - if(src.corpsesuit) - M.equip_to_slot_or_del(new src.corpsesuit(M), slot_wear_suit) - if(src.corpseshoes) - M.equip_to_slot_or_del(new src.corpseshoes(M), slot_shoes) - if(src.corpsegloves) - M.equip_to_slot_or_del(new src.corpsegloves(M), slot_gloves) - if(src.corpseradio) - M.equip_to_slot_or_del(new src.corpseradio(M), slot_ears) - if(src.corpseglasses) - M.equip_to_slot_or_del(new src.corpseglasses(M), slot_glasses) - if(src.corpsemask) - M.equip_to_slot_or_del(new src.corpsemask(M), slot_wear_mask) - if(src.corpsehelmet) - M.equip_to_slot_or_del(new src.corpsehelmet(M), slot_head) - if(src.corpsebelt) - M.equip_to_slot_or_del(new src.corpsebelt(M), slot_belt) - if(src.corpsepocket1) - M.equip_to_slot_or_del(new src.corpsepocket1(M), slot_r_store) - if(src.corpsepocket2) - M.equip_to_slot_or_del(new src.corpsepocket2(M), slot_l_store) - if(src.corpseback) - M.equip_to_slot_or_del(new src.corpseback(M), slot_back) - if(src.corpseid == 1) - var/obj/item/weapon/card/id/W = new(M) - W.name = "[M.real_name]'s ID Card" - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype - if(J.title == corpseidaccess) - jobdatum = J - break - if(src.corpseidicon) - W.icon_state = corpseidicon - if(src.corpseidaccess) - if(jobdatum) - W.access = jobdatum.get_access() - else - W.access = list() - if(corpseidjob) - W.assignment = corpseidjob - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - qdel(src) - - - -// I'll work on making a list of corpses people request for maps, or that I think will be commonly used. Syndicate operatives for example. - - - - - -/obj/effect/landmark/corpse/syndicatesoldier - name = "Syndicate Operative" - corpseuniform = /obj/item/clothing/under/syndicate - corpsesuit = /obj/item/clothing/suit/armor/vest - corpseshoes = /obj/item/clothing/shoes/swat - corpsegloves = /obj/item/clothing/gloves/swat - corpseradio = /obj/item/device/radio/headset - corpsemask = /obj/item/clothing/mask/gas - corpsehelmet = /obj/item/clothing/head/helmet/swat - corpseback = /obj/item/weapon/storage/backpack - corpseid = 1 - corpseidjob = "Operative" - corpseidaccess = "Syndicate" - - - -/obj/effect/landmark/corpse/syndicatecommando - name = "Syndicate Commando" - corpseuniform = /obj/item/clothing/under/syndicate - corpsesuit = /obj/item/clothing/suit/space/rig/syndi - corpseshoes = /obj/item/clothing/shoes/swat - corpsegloves = /obj/item/clothing/gloves/swat - corpseradio = /obj/item/device/radio/headset - corpsemask = /obj/item/clothing/mask/gas/syndicate - corpsehelmet = /obj/item/clothing/head/helmet/space/rig/syndi - corpseback = /obj/item/weapon/tank/jetpack/oxygen - corpsepocket1 = /obj/item/weapon/tank/emergency_oxygen - corpseid = 1 - corpseidjob = "Operative" - corpseidaccess = "Syndicate" - - - -///////////Civilians////////////////////// - -/obj/effect/landmark/corpse/chef - name = "Chef" - corpseuniform = /obj/item/clothing/under/rank/chef - corpsesuit = /obj/item/clothing/suit/chef/classic - corpseshoes = /obj/item/clothing/shoes/black - corpsehelmet = /obj/item/clothing/head/chefhat - corpseback = /obj/item/weapon/storage/backpack - corpseradio = /obj/item/device/radio/headset - corpseid = 1 - corpseidjob = "Chef" - corpseidaccess = "Chef" - - -/obj/effect/landmark/corpse/doctor - name = "Doctor" - corpseradio = /obj/item/device/radio/headset/headset_med - corpseuniform = /obj/item/clothing/under/rank/medical - corpsesuit = /obj/item/clothing/suit/storage/labcoat - corpseback = /obj/item/weapon/storage/backpack/medic - corpsepocket1 = /obj/item/device/flashlight/pen - corpseshoes = /obj/item/clothing/shoes/black - corpseid = 1 - corpseidjob = "Medical Doctor" - corpseidaccess = "Medical Doctor" - -/obj/effect/landmark/corpse/engineer - name = "Engineer" - corpseradio = /obj/item/device/radio/headset/headset_eng - corpseuniform = /obj/item/clothing/under/rank/engineer - corpseback = /obj/item/weapon/storage/backpack/industrial - corpseshoes = /obj/item/clothing/shoes/orange - corpsebelt = /obj/item/weapon/storage/belt/utility/full - corpsegloves = /obj/item/clothing/gloves/yellow - corpsehelmet = /obj/item/clothing/head/hardhat - corpseid = 1 - corpseidjob = "Station Engineer" - corpseidaccess = "Station Engineer" - -/obj/effect/landmark/corpse/engineer/rig - corpsesuit = /obj/item/clothing/suit/space/rig - corpsemask = /obj/item/clothing/mask/breath - corpsehelmet = /obj/item/clothing/head/helmet/space/rig - -/obj/effect/landmark/corpse/clown - name = "Clown" - corpseuniform = /obj/item/clothing/under/rank/clown - corpseshoes = /obj/item/clothing/shoes/clown_shoes - corpseradio = /obj/item/device/radio/headset - corpsemask = /obj/item/clothing/mask/gas/clown_hat - corpsepocket1 = /obj/item/weapon/bikehorn - corpseback = /obj/item/weapon/storage/backpack/clown - corpseid = 1 - corpseidjob = "Clown" - corpseidaccess = "Clown" - -/obj/effect/landmark/corpse/mime - name = "Mime" - corpseuniform = /obj/item/clothing/under/mime - corpseshoes = /obj/item/clothing/shoes/black - corpseradio = /obj/item/device/radio/headset - corpsemask = /obj/item/clothing/mask/gas/mime - corpsegloves = /obj/item/clothing/gloves/white/stunglove // Spawn with empty, crappy batteries. - corpseback = /obj/item/weapon/storage/backpack - corpseid = 1 - corpseidjob = "Mime" - corpseidaccess = "Mime" - -/obj/effect/landmark/corpse/scientist - name = "Scientist" - corpseradio = /obj/item/device/radio/headset/headset_sci - corpseuniform = /obj/item/clothing/under/rank/scientist - corpsesuit = /obj/item/clothing/suit/storage/labcoat/science - corpseback = /obj/item/weapon/storage/backpack - corpseshoes = /obj/item/clothing/shoes/white - corpseid = 1 - corpseidjob = "Scientist" - corpseidaccess = "Scientist" - -/obj/effect/landmark/corpse/miner - corpseradio = /obj/item/device/radio/headset/headset_mining - corpseuniform = /obj/item/clothing/under/rank/miner - corpsegloves = /obj/item/clothing/gloves/black - corpseback = /obj/item/weapon/storage/backpack/industrial - corpseshoes = /obj/item/clothing/shoes/black - corpseid = 1 - corpseidjob = "Shaft Miner" - corpseidaccess = "Shaft Miner" - -/obj/effect/landmark/corpse/miner/rig - corpsesuit = /obj/item/clothing/suit/space/rig/mining - corpsemask = /obj/item/clothing/mask/breath - corpsehelmet = /obj/item/clothing/head/helmet/space/rig/mining - - -/////////////////Officers////////////////////// - -/obj/effect/landmark/corpse/bridgeofficer - name = "Bridge Officer" - corpseradio = /obj/item/device/radio/headset/heads/hop - corpseuniform = /obj/item/clothing/under/rank/centcom_officer - corpsesuit = /obj/item/clothing/suit/armor/bulletproof - corpseshoes = /obj/item/clothing/shoes/black - corpseglasses = /obj/item/clothing/glasses/sunglasses - corpseid = 1 - corpseidjob = "Bridge Officer" - corpseidaccess = "Captain" - -/obj/effect/landmark/corpse/commander - name = "Commander" - corpseuniform = /obj/item/clothing/under/rank/centcom_commander - corpsesuit = /obj/item/clothing/suit/armor/bulletproof - corpseradio = /obj/item/device/radio/headset/heads/captain - corpseglasses = /obj/item/clothing/glasses/eyepatch - corpsemask = /obj/item/clothing/mask/cigarette/cigar/cohiba - corpsehelmet = /obj/item/clothing/head/centhat - corpsegloves = /obj/item/clothing/gloves/swat - corpseshoes = /obj/item/clothing/shoes/swat - corpsepocket1 = /obj/item/weapon/lighter/zippo - corpseid = 1 - corpseidjob = "Commander" - corpseidaccess = "Captain" - -/////////////////Simple-Mob Corpses///////////////////// - -/obj/effect/landmark/corpse/pirate - name = "Pirate" - corpseuniform = /obj/item/clothing/under/pirate - corpseshoes = /obj/item/clothing/shoes/jackboots - corpseglasses = /obj/item/clothing/glasses/eyepatch - corpsehelmet = /obj/item/clothing/head/bandana - -/obj/effect/landmark/corpse/pirate - name = "Pirate" - corpseuniform = /obj/item/clothing/under/pirate - corpseshoes = /obj/item/clothing/shoes/jackboots - corpseglasses = /obj/item/clothing/glasses/eyepatch - corpsehelmet = /obj/item/clothing/head/bandana - -/obj/effect/landmark/corpse/pirate/ranged - name = "Pirate Gunner" - corpsesuit = /obj/item/clothing/suit/pirate - corpsehelmet = /obj/item/clothing/head/pirate - -/obj/effect/landmark/corpse/russian - name = "Russian" - corpseuniform = /obj/item/clothing/under/soviet - corpseshoes = /obj/item/clothing/shoes/jackboots - corpsehelmet = /obj/item/clothing/head/bearpelt/real - -/obj/effect/landmark/corpse/russian/ranged + +/obj/effect/landmark/corpse + name = "Unknown" + var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now + var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse. + var/corpsesuit = null + var/corpseshoes = null + var/corpsegloves = null + var/corpseradio = null + var/corpseglasses = null + var/corpsemask = null + var/corpsehelmet = null + var/corpsebelt = null + var/corpsepocket1 = null + var/corpsepocket2 = null + var/corpseback = null + var/corpseid = 0 //Just set to 1 if you want them to have an ID + var/corpseidjob = null // Needs to be in quotes, such as "Clown" or "Chef." This just determines what the ID reads as, not their access + var/corpseidaccess = null //This is for access. See access.dm for which jobs give what access. Again, put in quotes. Use "Captain" if you want it to be all access. + var/corpseidicon = null //For setting it to be a gold, silver, centcomm etc ID + var/mutantrace = "human" + +/obj/effect/landmark/corpse/New() + if(ticker) + initialize() + +/obj/effect/landmark/corpse/initialize() + createCorpse() + +/obj/effect/landmark/corpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it. + var/mob/living/carbon/human/M = new /mob/living/carbon/human (loc) + M.dna.mutantrace = mutantrace + M.real_name = src.name + M.adjustOxyLoss(200) //Kills the new mob + M.iscorpse = 1 + if(src.corpseuniform) + M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform) + if(src.corpsesuit) + M.equip_to_slot_or_del(new src.corpsesuit(M), slot_wear_suit) + if(src.corpseshoes) + M.equip_to_slot_or_del(new src.corpseshoes(M), slot_shoes) + if(src.corpsegloves) + M.equip_to_slot_or_del(new src.corpsegloves(M), slot_gloves) + if(src.corpseradio) + M.equip_to_slot_or_del(new src.corpseradio(M), slot_ears) + if(src.corpseglasses) + M.equip_to_slot_or_del(new src.corpseglasses(M), slot_glasses) + if(src.corpsemask) + M.equip_to_slot_or_del(new src.corpsemask(M), slot_wear_mask) + if(src.corpsehelmet) + M.equip_to_slot_or_del(new src.corpsehelmet(M), slot_head) + if(src.corpsebelt) + M.equip_to_slot_or_del(new src.corpsebelt(M), slot_belt) + if(src.corpsepocket1) + M.equip_to_slot_or_del(new src.corpsepocket1(M), slot_r_store) + if(src.corpsepocket2) + M.equip_to_slot_or_del(new src.corpsepocket2(M), slot_l_store) + if(src.corpseback) + M.equip_to_slot_or_del(new src.corpseback(M), slot_back) + if(src.corpseid == 1) + var/obj/item/weapon/card/id/W = new(M) + W.name = "[M.real_name]'s ID Card" + var/datum/job/jobdatum + for(var/jobtype in typesof(/datum/job)) + var/datum/job/J = new jobtype + if(J.title == corpseidaccess) + jobdatum = J + break + if(src.corpseidicon) + W.icon_state = corpseidicon + if(src.corpseidaccess) + if(jobdatum) + W.access = jobdatum.get_access() + else + W.access = list() + if(corpseidjob) + W.assignment = corpseidjob + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + qdel(src) + + + +// I'll work on making a list of corpses people request for maps, or that I think will be commonly used. Syndicate operatives for example. + + + + + +/obj/effect/landmark/corpse/syndicatesoldier + name = "Syndicate Operative" + corpseuniform = /obj/item/clothing/under/syndicate + corpsesuit = /obj/item/clothing/suit/armor/vest + corpseshoes = /obj/item/clothing/shoes/swat + corpsegloves = /obj/item/clothing/gloves/swat + corpseradio = /obj/item/device/radio/headset + corpsemask = /obj/item/clothing/mask/gas + corpsehelmet = /obj/item/clothing/head/helmet/swat + corpseback = /obj/item/weapon/storage/backpack + corpseid = 1 + corpseidjob = "Operative" + corpseidaccess = "Syndicate" + + + +/obj/effect/landmark/corpse/syndicatecommando + name = "Syndicate Commando" + corpseuniform = /obj/item/clothing/under/syndicate + corpsesuit = /obj/item/clothing/suit/space/rig/syndi + corpseshoes = /obj/item/clothing/shoes/swat + corpsegloves = /obj/item/clothing/gloves/swat + corpseradio = /obj/item/device/radio/headset + corpsemask = /obj/item/clothing/mask/gas/syndicate + corpsehelmet = /obj/item/clothing/head/helmet/space/rig/syndi + corpseback = /obj/item/weapon/tank/jetpack/oxygen + corpsepocket1 = /obj/item/weapon/tank/emergency_oxygen + corpseid = 1 + corpseidjob = "Operative" + corpseidaccess = "Syndicate" + + + +///////////Civilians////////////////////// + +/obj/effect/landmark/corpse/chef + name = "Chef" + corpseuniform = /obj/item/clothing/under/rank/chef + corpsesuit = /obj/item/clothing/suit/chef/classic + corpseshoes = /obj/item/clothing/shoes/black + corpsehelmet = /obj/item/clothing/head/chefhat + corpseback = /obj/item/weapon/storage/backpack + corpseradio = /obj/item/device/radio/headset + corpseid = 1 + corpseidjob = "Chef" + corpseidaccess = "Chef" + + +/obj/effect/landmark/corpse/doctor + name = "Doctor" + corpseradio = /obj/item/device/radio/headset/headset_med + corpseuniform = /obj/item/clothing/under/rank/medical + corpsesuit = /obj/item/clothing/suit/storage/labcoat + corpseback = /obj/item/weapon/storage/backpack/medic + corpsepocket1 = /obj/item/device/flashlight/pen + corpseshoes = /obj/item/clothing/shoes/black + corpseid = 1 + corpseidjob = "Medical Doctor" + corpseidaccess = "Medical Doctor" + +/obj/effect/landmark/corpse/engineer + name = "Engineer" + corpseradio = /obj/item/device/radio/headset/headset_eng + corpseuniform = /obj/item/clothing/under/rank/engineer + corpseback = /obj/item/weapon/storage/backpack/industrial + corpseshoes = /obj/item/clothing/shoes/orange + corpsebelt = /obj/item/weapon/storage/belt/utility/full + corpsegloves = /obj/item/clothing/gloves/yellow + corpsehelmet = /obj/item/clothing/head/hardhat + corpseid = 1 + corpseidjob = "Station Engineer" + corpseidaccess = "Station Engineer" + +/obj/effect/landmark/corpse/engineer/rig + corpsesuit = /obj/item/clothing/suit/space/rig + corpsemask = /obj/item/clothing/mask/breath + corpsehelmet = /obj/item/clothing/head/helmet/space/rig + +/obj/effect/landmark/corpse/clown + name = "Clown" + corpseuniform = /obj/item/clothing/under/rank/clown + corpseshoes = /obj/item/clothing/shoes/clown_shoes + corpseradio = /obj/item/device/radio/headset + corpsemask = /obj/item/clothing/mask/gas/clown_hat + corpsepocket1 = /obj/item/weapon/bikehorn + corpseback = /obj/item/weapon/storage/backpack/clown + corpseid = 1 + corpseidjob = "Clown" + corpseidaccess = "Clown" + +/obj/effect/landmark/corpse/mime + name = "Mime" + corpseuniform = /obj/item/clothing/under/mime + corpseshoes = /obj/item/clothing/shoes/black + corpseradio = /obj/item/device/radio/headset + corpsemask = /obj/item/clothing/mask/gas/mime + corpsegloves = /obj/item/clothing/gloves/white/stunglove // Spawn with empty, crappy batteries. + corpseback = /obj/item/weapon/storage/backpack + corpseid = 1 + corpseidjob = "Mime" + corpseidaccess = "Mime" + +/obj/effect/landmark/corpse/scientist + name = "Scientist" + corpseradio = /obj/item/device/radio/headset/headset_sci + corpseuniform = /obj/item/clothing/under/rank/scientist + corpsesuit = /obj/item/clothing/suit/storage/labcoat/science + corpseback = /obj/item/weapon/storage/backpack + corpseshoes = /obj/item/clothing/shoes/white + corpseid = 1 + corpseidjob = "Scientist" + corpseidaccess = "Scientist" + +/obj/effect/landmark/corpse/miner + corpseradio = /obj/item/device/radio/headset/headset_mining + corpseuniform = /obj/item/clothing/under/rank/miner + corpsegloves = /obj/item/clothing/gloves/black + corpseback = /obj/item/weapon/storage/backpack/industrial + corpseshoes = /obj/item/clothing/shoes/black + corpseid = 1 + corpseidjob = "Shaft Miner" + corpseidaccess = "Shaft Miner" + +/obj/effect/landmark/corpse/miner/rig + corpsesuit = /obj/item/clothing/suit/space/rig/mining + corpsemask = /obj/item/clothing/mask/breath + corpsehelmet = /obj/item/clothing/head/helmet/space/rig/mining + + +/////////////////Officers////////////////////// + +/obj/effect/landmark/corpse/bridgeofficer + name = "Bridge Officer" + corpseradio = /obj/item/device/radio/headset/heads/hop + corpseuniform = /obj/item/clothing/under/rank/centcom_officer + corpsesuit = /obj/item/clothing/suit/armor/bulletproof + corpseshoes = /obj/item/clothing/shoes/black + corpseglasses = /obj/item/clothing/glasses/sunglasses + corpseid = 1 + corpseidjob = "Bridge Officer" + corpseidaccess = "Captain" + +/obj/effect/landmark/corpse/commander + name = "Commander" + corpseuniform = /obj/item/clothing/under/rank/centcom_commander + corpsesuit = /obj/item/clothing/suit/armor/bulletproof + corpseradio = /obj/item/device/radio/headset/heads/captain + corpseglasses = /obj/item/clothing/glasses/eyepatch + corpsemask = /obj/item/clothing/mask/cigarette/cigar/cohiba + corpsehelmet = /obj/item/clothing/head/centhat + corpsegloves = /obj/item/clothing/gloves/swat + corpseshoes = /obj/item/clothing/shoes/swat + corpsepocket1 = /obj/item/weapon/lighter/zippo + corpseid = 1 + corpseidjob = "Commander" + corpseidaccess = "Captain" + +/////////////////Simple-Mob Corpses///////////////////// + +/obj/effect/landmark/corpse/pirate + name = "Pirate" + corpseuniform = /obj/item/clothing/under/pirate + corpseshoes = /obj/item/clothing/shoes/jackboots + corpseglasses = /obj/item/clothing/glasses/eyepatch + corpsehelmet = /obj/item/clothing/head/bandana + +/obj/effect/landmark/corpse/pirate + name = "Pirate" + corpseuniform = /obj/item/clothing/under/pirate + corpseshoes = /obj/item/clothing/shoes/jackboots + corpseglasses = /obj/item/clothing/glasses/eyepatch + corpsehelmet = /obj/item/clothing/head/bandana + +/obj/effect/landmark/corpse/pirate/ranged + name = "Pirate Gunner" + corpsesuit = /obj/item/clothing/suit/pirate + corpsehelmet = /obj/item/clothing/head/pirate + +/obj/effect/landmark/corpse/russian + name = "Russian" + corpseuniform = /obj/item/clothing/under/soviet + corpseshoes = /obj/item/clothing/shoes/jackboots + corpsehelmet = /obj/item/clothing/head/bearpelt/real + +/obj/effect/landmark/corpse/russian/ranged corpsehelmet = /obj/item/clothing/head/ushanka \ No newline at end of file diff --git a/code/modules/awaymissions/exile.dm b/code/modules/awaymissions/exile.dm index 7699d653833..2dc073d7f24 100644 --- a/code/modules/awaymissions/exile.dm +++ b/code/modules/awaymissions/exile.dm @@ -1,51 +1,51 @@ -//////Exile implants will allow you to use the station gate, but not return home. This will allow security to exile badguys/for badguys to exile their kill targets//////// - - -/obj/item/weapon/implanter/exile - name = "implanter-exile" - -/obj/item/weapon/implanter/exile/New() - src.imp = new /obj/item/weapon/implant/exile( src ) - ..() - update() - return - - -/obj/item/weapon/implant/exile - name = "exile" - desc = "Prevents you from returning from away missions" - - get_data() - var/dat = {" -Implant Specifications:
    -Name: Nanotrasen Employee Exile Implant
    -Implant Details: The onboard gateway system has been modified to reject entry by individuals containing this implant
    "} - return dat - -/obj/item/weapon/implantcase/exile - name = "Glass Case- 'Exile'" - desc = "A case containing an exile implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-r" - - - New() - src.imp = new /obj/item/weapon/implant/exile( src ) - ..() - return - - -/obj/structure/closet/secure_closet/exile - name = "Exile Implants" - req_access = list(access_hos) - - New() - ..() - sleep(2) - new /obj/item/weapon/implanter/exile(src) - new /obj/item/weapon/implantcase/exile(src) - new /obj/item/weapon/implantcase/exile(src) - new /obj/item/weapon/implantcase/exile(src) - new /obj/item/weapon/implantcase/exile(src) - new /obj/item/weapon/implantcase/exile(src) +//////Exile implants will allow you to use the station gate, but not return home. This will allow security to exile badguys/for badguys to exile their kill targets//////// + + +/obj/item/weapon/implanter/exile + name = "implanter-exile" + +/obj/item/weapon/implanter/exile/New() + src.imp = new /obj/item/weapon/implant/exile( src ) + ..() + update() + return + + +/obj/item/weapon/implant/exile + name = "exile" + desc = "Prevents you from returning from away missions" + + get_data() + var/dat = {" +Implant Specifications:
    +Name: Nanotrasen Employee Exile Implant
    +Implant Details: The onboard gateway system has been modified to reject entry by individuals containing this implant
    "} + return dat + +/obj/item/weapon/implantcase/exile + name = "Glass Case- 'Exile'" + desc = "A case containing an exile implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-r" + + + New() + src.imp = new /obj/item/weapon/implant/exile( src ) + ..() + return + + +/obj/structure/closet/secure_closet/exile + name = "Exile Implants" + req_access = list(access_hos) + + New() + ..() + sleep(2) + new /obj/item/weapon/implanter/exile(src) + new /obj/item/weapon/implantcase/exile(src) + new /obj/item/weapon/implantcase/exile(src) + new /obj/item/weapon/implantcase/exile(src) + new /obj/item/weapon/implantcase/exile(src) + new /obj/item/weapon/implantcase/exile(src) return \ No newline at end of file diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 65ae4a761a9..5cc2a326446 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -1,238 +1,238 @@ -/obj/machinery/gateway - name = "gateway" - desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations." - icon = 'icons/obj/machines/gateway.dmi' - icon_state = "off" - density = 1 - anchored = 1 - var/active = 0 - - -/obj/machinery/gateway/initialize() - update_icon() - if(dir == 2) - density = 0 - - -/obj/machinery/gateway/update_icon() - if(active) - icon_state = "on" - return - icon_state = "off" - -/obj/machinery/gateway/shuttle_rotate() - return - - -//this is da important part wot makes things go -/obj/machinery/gateway/centerstation - density = 1 - icon_state = "offcenter" - use_power = 1 - - //warping vars - var/list/linked = list() - var/ready = 0 //have we got all the parts for a gateway? - var/wait = 0 //this just grabs world.time at world start - var/obj/machinery/gateway/centeraway/awaygate = null - -/obj/machinery/gateway/centerstation/initialize() - update_icon() - wait = world.time + config.gateway_delay //+ thirty minutes default - awaygate = locate(/obj/machinery/gateway/centeraway) - - -/obj/machinery/gateway/centerstation/update_icon() - if(active) - icon_state = "oncenter" - return - icon_state = "offcenter" - - - -obj/machinery/gateway/centerstation/process() - if(stat & (NOPOWER)) - if(active) toggleoff() - return - - if(active) - use_power(5000) - - -/obj/machinery/gateway/centerstation/proc/detect() - linked = list() //clear the list - var/turf/T = loc - - for(var/i in alldirs) - T = get_step(loc, i) - var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T - if(G) - linked.Add(G) - continue - - //this is only done if we fail to find a part - ready = 0 - toggleoff() - break - - if(linked.len == 8) - ready = 1 - - -/obj/machinery/gateway/centerstation/proc/toggleon(mob/user as mob) - if(!ready) return - if(linked.len != 8) return - if(!powered()) return - if(!awaygate) +/obj/machinery/gateway + name = "gateway" + desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations." + icon = 'icons/obj/machines/gateway.dmi' + icon_state = "off" + density = 1 + anchored = 1 + var/active = 0 + + +/obj/machinery/gateway/initialize() + update_icon() + if(dir == 2) + density = 0 + + +/obj/machinery/gateway/update_icon() + if(active) + icon_state = "on" + return + icon_state = "off" + +/obj/machinery/gateway/shuttle_rotate() + return + + +//this is da important part wot makes things go +/obj/machinery/gateway/centerstation + density = 1 + icon_state = "offcenter" + use_power = 1 + + //warping vars + var/list/linked = list() + var/ready = 0 //have we got all the parts for a gateway? + var/wait = 0 //this just grabs world.time at world start + var/obj/machinery/gateway/centeraway/awaygate = null + +/obj/machinery/gateway/centerstation/initialize() + update_icon() + wait = world.time + config.gateway_delay //+ thirty minutes default + awaygate = locate(/obj/machinery/gateway/centeraway) + + +/obj/machinery/gateway/centerstation/update_icon() + if(active) + icon_state = "oncenter" + return + icon_state = "offcenter" + + + +obj/machinery/gateway/centerstation/process() + if(stat & (NOPOWER)) + if(active) toggleoff() + return + + if(active) + use_power(5000) + + +/obj/machinery/gateway/centerstation/proc/detect() + linked = list() //clear the list + var/turf/T = loc + + for(var/i in alldirs) + T = get_step(loc, i) + var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T + if(G) + linked.Add(G) + continue + + //this is only done if we fail to find a part + ready = 0 + toggleoff() + break + + if(linked.len == 8) + ready = 1 + + +/obj/machinery/gateway/centerstation/proc/toggleon(mob/user as mob) + if(!ready) return + if(linked.len != 8) return + if(!powered()) return + if(!awaygate) to_chat(user, "Error: No destination found.") - return - if(world.time < wait) + return + if(world.time < wait) to_chat(user, "Error: Warpspace triangulation in progress. Estimated time to completion: [round(((wait - world.time) / 10) / 60)] minutes.") - return - - for(var/obj/machinery/gateway/G in linked) - G.active = 1 - G.update_icon() - active = 1 - update_icon() - - -/obj/machinery/gateway/centerstation/proc/toggleoff() - for(var/obj/machinery/gateway/G in linked) - G.active = 0 - G.update_icon() - active = 0 - update_icon() - - -/obj/machinery/gateway/centerstation/attack_hand(mob/user as mob) - if(!ready) - detect() - return - if(!active) - toggleon(user) - return - toggleoff() - - -//okay, here's the good teleporting stuff -/obj/machinery/gateway/centerstation/Bumped(atom/movable/M as mob|obj) - if(!ready) return - if(!active) return - if(!awaygate) return - if(awaygate.calibrated) - M.loc = get_step(awaygate.loc, SOUTH) - M.dir = SOUTH - return - else - var/obj/effect/landmark/dest = pick(awaydestinations) - if(dest) - M.loc = dest.loc - M.dir = SOUTH - use_power(5000) - return - - -/obj/machinery/gateway/centerstation/attackby(obj/item/device/W as obj, mob/user as mob) - if(istype(W,/obj/item/device/multitool)) + return + + for(var/obj/machinery/gateway/G in linked) + G.active = 1 + G.update_icon() + active = 1 + update_icon() + + +/obj/machinery/gateway/centerstation/proc/toggleoff() + for(var/obj/machinery/gateway/G in linked) + G.active = 0 + G.update_icon() + active = 0 + update_icon() + + +/obj/machinery/gateway/centerstation/attack_hand(mob/user as mob) + if(!ready) + detect() + return + if(!active) + toggleon(user) + return + toggleoff() + + +//okay, here's the good teleporting stuff +/obj/machinery/gateway/centerstation/Bumped(atom/movable/M as mob|obj) + if(!ready) return + if(!active) return + if(!awaygate) return + if(awaygate.calibrated) + M.loc = get_step(awaygate.loc, SOUTH) + M.dir = SOUTH + return + else + var/obj/effect/landmark/dest = pick(awaydestinations) + if(dest) + M.loc = dest.loc + M.dir = SOUTH + use_power(5000) + return + + +/obj/machinery/gateway/centerstation/attackby(obj/item/device/W as obj, mob/user as mob) + if(istype(W,/obj/item/device/multitool)) to_chat(user, "\black The gate is already calibrated, there is no work for you to do here.") - return - -/////////////////////////////////////Away//////////////////////// - - -/obj/machinery/gateway/centeraway - density = 1 - icon_state = "offcenter" - use_power = 0 - var/calibrated = 1 - var/list/linked = list() //a list of the connected gateway chunks - var/ready = 0 - var/obj/machinery/gateway/centeraway/stationgate = null - - -/obj/machinery/gateway/centeraway/initialize() - update_icon() - stationgate = locate(/obj/machinery/gateway/centerstation) - - -/obj/machinery/gateway/centeraway/update_icon() - if(active) - icon_state = "oncenter" - return - icon_state = "offcenter" - - -/obj/machinery/gateway/centeraway/proc/detect() - linked = list() //clear the list - var/turf/T = loc - - for(var/i in alldirs) - T = get_step(loc, i) - var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T - if(G) - linked.Add(G) - continue - - //this is only done if we fail to find a part - ready = 0 - toggleoff() - break - - if(linked.len == 8) - ready = 1 - - -/obj/machinery/gateway/centeraway/proc/toggleon(mob/user as mob) - if(!ready) return - if(linked.len != 8) return - if(!stationgate) + return + +/////////////////////////////////////Away//////////////////////// + + +/obj/machinery/gateway/centeraway + density = 1 + icon_state = "offcenter" + use_power = 0 + var/calibrated = 1 + var/list/linked = list() //a list of the connected gateway chunks + var/ready = 0 + var/obj/machinery/gateway/centeraway/stationgate = null + + +/obj/machinery/gateway/centeraway/initialize() + update_icon() + stationgate = locate(/obj/machinery/gateway/centerstation) + + +/obj/machinery/gateway/centeraway/update_icon() + if(active) + icon_state = "oncenter" + return + icon_state = "offcenter" + + +/obj/machinery/gateway/centeraway/proc/detect() + linked = list() //clear the list + var/turf/T = loc + + for(var/i in alldirs) + T = get_step(loc, i) + var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T + if(G) + linked.Add(G) + continue + + //this is only done if we fail to find a part + ready = 0 + toggleoff() + break + + if(linked.len == 8) + ready = 1 + + +/obj/machinery/gateway/centeraway/proc/toggleon(mob/user as mob) + if(!ready) return + if(linked.len != 8) return + if(!stationgate) to_chat(user, "Error: No destination found.") - return - - for(var/obj/machinery/gateway/G in linked) - G.active = 1 - G.update_icon() - active = 1 - update_icon() - - -/obj/machinery/gateway/centeraway/proc/toggleoff() - for(var/obj/machinery/gateway/G in linked) - G.active = 0 - G.update_icon() - active = 0 - update_icon() - - -/obj/machinery/gateway/centeraway/attack_hand(mob/user as mob) - if(!ready) - detect() - return - if(!active) - toggleon(user) - return - toggleoff() - - -/obj/machinery/gateway/centeraway/Bumped(atom/movable/M as mob|obj) - if(!ready) return - if(!active) return - if(istype(M, /mob/living/carbon)) - for(var/obj/item/weapon/implant/exile/E in M)//Checking that there is an exile implant in the contents - if(E.imp_in == M)//Checking that it's actually implanted vs just in their pocket + return + + for(var/obj/machinery/gateway/G in linked) + G.active = 1 + G.update_icon() + active = 1 + update_icon() + + +/obj/machinery/gateway/centeraway/proc/toggleoff() + for(var/obj/machinery/gateway/G in linked) + G.active = 0 + G.update_icon() + active = 0 + update_icon() + + +/obj/machinery/gateway/centeraway/attack_hand(mob/user as mob) + if(!ready) + detect() + return + if(!active) + toggleon(user) + return + toggleoff() + + +/obj/machinery/gateway/centeraway/Bumped(atom/movable/M as mob|obj) + if(!ready) return + if(!active) return + if(istype(M, /mob/living/carbon)) + for(var/obj/item/weapon/implant/exile/E in M)//Checking that there is an exile implant in the contents + if(E.imp_in == M)//Checking that it's actually implanted vs just in their pocket to_chat(M, "\black The station gate has detected your exile implant and is blocking your entry.") - return - M.loc = get_step(stationgate.loc, SOUTH) - M.dir = SOUTH - - -/obj/machinery/gateway/centeraway/attackby(obj/item/device/W as obj, mob/user as mob) - if(istype(W,/obj/item/device/multitool)) - if(calibrated) + return + M.loc = get_step(stationgate.loc, SOUTH) + M.dir = SOUTH + + +/obj/machinery/gateway/centeraway/attackby(obj/item/device/W as obj, mob/user as mob) + if(istype(W,/obj/item/device/multitool)) + if(calibrated) to_chat(user, "\black The gate is already calibrated, there is no work for you to do here.") - return - else + return + else to_chat(user, "Recalibration successful!: This gate's systems have been fine tuned. Travel to this gate will now be on target.") - calibrated = 1 + calibrated = 1 return \ No newline at end of file diff --git a/code/modules/awaymissions/loot.dm b/code/modules/awaymissions/loot.dm index 5aeb9651d2b..8e323d6c00d 100644 --- a/code/modules/awaymissions/loot.dm +++ b/code/modules/awaymissions/loot.dm @@ -1,24 +1,24 @@ -/obj/effect/spawner/lootdrop - icon = 'icons/mob/screen1.dmi' - icon_state = "x2" - var/lootcount = 1 //how many items will be spawned - var/lootdoubles = 0 //if the same item can be spawned twice - var/loot = "" //a list of possible items to spawn- a string of paths - -/obj/effect/spawner/lootdrop/initialize() - var/list/things = params2list(loot) - - if(things && things.len) - for(var/i = lootcount, i > 0, i--) - if(!things.len) - return - - var/loot_spawn = pick(things) - var/loot_path = text2path(loot_spawn) - - if(!loot_path || !lootdoubles) - things.Remove(loot_spawn) - continue - - new loot_path(get_turf(src)) - qdel(src) +/obj/effect/spawner/lootdrop + icon = 'icons/mob/screen1.dmi' + icon_state = "x2" + var/lootcount = 1 //how many items will be spawned + var/lootdoubles = 0 //if the same item can be spawned twice + var/loot = "" //a list of possible items to spawn- a string of paths + +/obj/effect/spawner/lootdrop/initialize() + var/list/things = params2list(loot) + + if(things && things.len) + for(var/i = lootcount, i > 0, i--) + if(!things.len) + return + + var/loot_spawn = pick(things) + var/loot_path = text2path(loot_spawn) + + if(!loot_path || !lootdoubles) + things.Remove(loot_spawn) + continue + + new loot_path(get_turf(src)) + qdel(src) diff --git a/code/modules/awaymissions/pamphlet.dm b/code/modules/awaymissions/pamphlet.dm index d3d2f3a07b1..d8f8cd33274 100644 --- a/code/modules/awaymissions/pamphlet.dm +++ b/code/modules/awaymissions/pamphlet.dm @@ -1,38 +1,38 @@ -/obj/item/weapon/paper/pamphlet - name = "pamphlet" - icon_state = "pamphlet" - info = "Welcome to the Nanotrasen Gateway project...
    \ - Congratulations! If you're reading this, you and your superiors have decided that you're \ - ready to commit to a life spent colonising the rolling hills of far away worlds. You \ - must be ready for a lifetime of adventure, a little bit of hard work, and an award \ - winning dental plan- but that's not all the Nanotrasen Gateway project has to offer.
    \ -
    Because we care about you, we feel it is only fair to make sure you know the risks \ - before you commit to joining the Nanotrasen Gateway project. All away destinations have \ - been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \ - We've even left a case of space beer along with the basic materials you'll need to expand \ - Nanotrasen's operational area and start your new life.

    \ - Gateway Operation Basics
    \ - All Nanotrasen approved Gateways operate on the same basic principals. They operate off \ - area equipment power as you would expect, but they also require a backup wire with at least \ - 128, 000 Watts of power running through it. Without this supply, it cannot safely function \ - and will reject all attempts at operation.

    \ - Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \ - searching for an output location. The amount of time this takes is variable, but the Gateway \ - interface will give you an estimate accurate to the minute. Power loss will not interrupt the \ - searching process. Influenza will not interrupt the searching process. Temporal anomalies \ - may cause the estimate to be inaccurate, but will not interrupt the searching process.

    \ - Life On The Other Side
    \ - Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \ - This is a normal side effect of travelling vast distances in a short period of time. You should \ - survey the immediate area, and attempt to locate your complimentary case of space beer. Our \ - expeditionary teams have ensured the complete safety of all away locations, but in a small \ - number of cases, the Gateway they have established may not be immediately obvious. \ - Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \ -

    A New World
    \ - As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \ - Though complete safety is assured, participants are advised to prepare for inhospitable \ - environs." - -//we don't want the silly text overlay! -/obj/item/weapon/paper/pamphlet/update_icon() +/obj/item/weapon/paper/pamphlet + name = "pamphlet" + icon_state = "pamphlet" + info = "Welcome to the Nanotrasen Gateway project...
    \ + Congratulations! If you're reading this, you and your superiors have decided that you're \ + ready to commit to a life spent colonising the rolling hills of far away worlds. You \ + must be ready for a lifetime of adventure, a little bit of hard work, and an award \ + winning dental plan- but that's not all the Nanotrasen Gateway project has to offer.
    \ +
    Because we care about you, we feel it is only fair to make sure you know the risks \ + before you commit to joining the Nanotrasen Gateway project. All away destinations have \ + been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \ + We've even left a case of space beer along with the basic materials you'll need to expand \ + Nanotrasen's operational area and start your new life.

    \ + Gateway Operation Basics
    \ + All Nanotrasen approved Gateways operate on the same basic principals. They operate off \ + area equipment power as you would expect, but they also require a backup wire with at least \ + 128, 000 Watts of power running through it. Without this supply, it cannot safely function \ + and will reject all attempts at operation.

    \ + Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \ + searching for an output location. The amount of time this takes is variable, but the Gateway \ + interface will give you an estimate accurate to the minute. Power loss will not interrupt the \ + searching process. Influenza will not interrupt the searching process. Temporal anomalies \ + may cause the estimate to be inaccurate, but will not interrupt the searching process.

    \ + Life On The Other Side
    \ + Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \ + This is a normal side effect of travelling vast distances in a short period of time. You should \ + survey the immediate area, and attempt to locate your complimentary case of space beer. Our \ + expeditionary teams have ensured the complete safety of all away locations, but in a small \ + number of cases, the Gateway they have established may not be immediately obvious. \ + Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \ +

    A New World
    \ + As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \ + Though complete safety is assured, participants are advised to prepare for inhospitable \ + environs." + +//we don't want the silly text overlay! +/obj/item/weapon/paper/pamphlet/update_icon() return \ No newline at end of file diff --git a/code/modules/awaymissions/trigger.dm b/code/modules/awaymissions/trigger.dm index 0706e922369..ec6d3e88187 100644 --- a/code/modules/awaymissions/trigger.dm +++ b/code/modules/awaymissions/trigger.dm @@ -1,44 +1,44 @@ -/obj/effect/step_trigger/message - var/message //the message to give to the mob - var/once = 1 - -/obj/effect/step_trigger/message/Trigger(mob/M as mob) - if(M.client) +/obj/effect/step_trigger/message + var/message //the message to give to the mob + var/once = 1 + +/obj/effect/step_trigger/message/Trigger(mob/M as mob) + if(M.client) to_chat(M, "[message]") - if(once) - qdel(src) - -/obj/effect/step_trigger/teleport_fancy - var/locationx - var/locationy - var/uses = 1 //0 for infinite uses - var/entersparks = 0 - var/exitsparks = 0 - var/entersmoke = 0 - var/exitsmoke = 0 - -/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M as mob) - var/dest = locate(locationx, locationy, z) - M.Move(dest) - - if(entersparks) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(4, 1, src) - s.start() - if(exitsparks) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(4, 1, dest) - s.start() - - if(entersmoke) - var/datum/effect/effect/system/smoke_spread/s = new /datum/effect/effect/system/smoke_spread - s.set_up(4, 1, src, 0) - s.start() - if(exitsmoke) - var/datum/effect/effect/system/smoke_spread/s = new /datum/effect/effect/system/smoke_spread - s.set_up(4, 1, dest, 0) - s.start() - - uses-- - if(uses == 0) - qdel(src) + if(once) + qdel(src) + +/obj/effect/step_trigger/teleport_fancy + var/locationx + var/locationy + var/uses = 1 //0 for infinite uses + var/entersparks = 0 + var/exitsparks = 0 + var/entersmoke = 0 + var/exitsmoke = 0 + +/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M as mob) + var/dest = locate(locationx, locationy, z) + M.Move(dest) + + if(entersparks) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(4, 1, src) + s.start() + if(exitsparks) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(4, 1, dest) + s.start() + + if(entersmoke) + var/datum/effect/effect/system/smoke_spread/s = new /datum/effect/effect/system/smoke_spread + s.set_up(4, 1, src, 0) + s.start() + if(exitsmoke) + var/datum/effect/effect/system/smoke_spread/s = new /datum/effect/effect/system/smoke_spread + s.set_up(4, 1, dest, 0) + s.start() + + uses-- + if(uses == 0) + qdel(src) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index d8696e56e88..607a3e2950d 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1,1467 +1,1467 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -var/list/preferences_datums = list() - -var/global/list/special_roles = list( - ROLE_ALIEN = 1, //always show - ROLE_BLOB = 1, - ROLE_BORER = 1, - ROLE_CHANGELING = IS_MODE_COMPILED("changeling"), - ROLE_CULTIST = IS_MODE_COMPILED("cult"), - ROLE_PLANT = 1, - "infested monkey" = IS_MODE_COMPILED("monkey"), - ROLE_MALF = IS_MODE_COMPILED("malfunction"), - ROLE_NINJA = 1, - ROLE_OPERATIVE = IS_MODE_COMPILED("nuclear"), - ROLE_PAI = 1, // -- TLE - ROLE_POSIBRAIN = 1, - ROLE_REV = IS_MODE_COMPILED("revolution"), - ROLE_TRAITOR = IS_MODE_COMPILED("traitor"), - ROLE_VAMPIRE = IS_MODE_COMPILED("vampire"), - ROLE_VOXRAIDER = IS_MODE_COMPILED("heist"), - ROLE_WIZARD = 1, -) - -var/const/MAX_SAVE_SLOTS = 8 - -//used for alternate_option -#define GET_RANDOM_JOB 0 -#define BE_ASSISTANT 1 -#define RETURN_TO_LOBBY 2 -#define POLLED_LIMIT 300 - -/datum/preferences - //doohickeys for savefiles - var/database/db = ("players2.sqlite") - var/path - var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used - var/slot = 1 - var/list/slot_names = new - var/lastPolled = 0 - - var/savefile_version = 0 - - //non-preference stuff - var/warns = 0 - var/warnbans = 0 - var/muted = 0 - var/last_ip - var/last_id - - //game-preferences - var/lastchangelog = "" //Saved changlog filesize to detect if there was a change - var/ooccolor = "#b82e00" - var/UI_style = "Midnight" - var/toggles = TOGGLES_DEFAULT - var/UI_style_color = "#ffffff" - var/UI_style_alpha = 255 - var/special_popup = 0 - - //character preferences - var/real_name //our character's name - var/be_random_name = 0 //whether we are a random name every round - var/be_random_body = 0 //whether we'll have a random body every round - var/gender = MALE //gender of character (well duh) - var/age = 30 //age of character - var/b_type = "A+" //blood type (not-chooseable) - var/underwear = 1 //underwear type - var/backbag = 2 //backpack type - var/h_style = "Bald" //Hair type - var/r_hair = 0 //Hair color - var/g_hair = 0 //Hair color - var/b_hair = 0 //Hair color - var/f_style = "Shaved" //Face hair type - 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/r_eyes = 0 //Eye color - var/g_eyes = 0 //Eye color - var/b_eyes = 0 //Eye color - var/species = "Human" - var/language = "None" //Secondary language - - //Mob preview - var/icon/preview_icon = null - var/icon/preview_icon_front = null - var/icon/preview_icon_side = null - - //Jobs, uses bitflags - var/job_civilian_high = 0 - var/job_civilian_med = 0 - var/job_civilian_low = 0 - - var/job_medsci_high = 0 - var/job_medsci_med = 0 - var/job_medsci_low = 0 - - var/job_engsec_high = 0 - var/job_engsec_med = 0 - var/job_engsec_low = 0 - - //Keeps track of preferrence for not getting any wanted jobs - var/alternate_option = 0 - - var/used_skillpoints = 0 - var/skill_specialization = null - var/list/skills = list() // skills can range from 0 to 3 - - // maps each organ to either null(intact), "cyborg" or "amputated" - // will probably not be able to do this for head and torso ;) - var/list/organ_data = list() - - var/list/player_alt_titles = new() // the default name of a job like "Medical Doctor" - - var/flavor_text = "" - var/med_record = "" - var/sec_record = "" - var/gen_record = "" - var/disabilities = 0 // NOW A BITFIELD, SEE ABOVE - - var/nanotrasen_relation = "Neutral" - - // 0 = character settings, 1 = game preferences - var/current_tab = 0 - - // OOC Metadata: - var/metadata = "" - var/slot_name = "" - - // Whether or not to use randomized character slots - var/randomslot = 0 - - // jukebox volume - var/volume = 100 - var/usewmp = 0 //whether to use WMP or VLC - - var/list/roles=list() // "role" => ROLEPREF_* - - var/usenanoui = 1 //Whether or not this client will use nanoUI, this doesn't do anything other than objects being able to check this. - - var/progress_bars = 1 //Whether to show progress bars when doing delayed actions. - var/client/client - -/datum/preferences/New(client/C) - b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") - client=C - if(istype(C)) - if(!IsGuestKey(C.key)) - var/load_pref = load_preferences_sqlite(C.ckey) - if(load_pref) - if(load_save_sqlite(C.ckey, src, default_slot)) - return - randomize_appearance_for() - real_name = random_name(gender) - save_character_sqlite(src, C.ckey, default_slot) - -/datum/preferences/proc/setup_character_options(var/dat, var/user) - - - dat += {"

    Occupation Choices

    - Set Occupation Preferences
    -

    Identity

    -
    - Random Name - Always Random Name: [be_random_name ? "Yes" : "No"]
    - Name: [real_name]
    - Gender: [gender == MALE ? "Male" : "Female"]
    - Age: [age] -
    -
    -
    -

    Body

    - Random Body - Always Random Body: [be_random_body ? "Yes" : "No"]
    -
    - Species: [species]
    - Secondary Language: [language]
    - Blood Type: [b_type]
    - Skin Tone: [-s_tone + 35]/220

    - Handicaps: Set
    - Limbs: Set
    - Organs: Set
    - Underwear: [gender == MALE ? "[underwear_m[underwear]]" : "[underwear_f[underwear]]"]
    - Backpack: [backbaglist[backbag]]
    - Nanotrasen Relation:
    [nanotrasen_relation] -
    -

    Hair Style

    - [h_style]
    - < >
    -     Change
    -
    -

    Facial Hair Style

    - [f_style]
    - < >
    -     Change
    -
    -

    Eye Color

    -     Change
    -
    - "} - - return dat - -/datum/preferences/proc/setup_UI(var/dat, var/user) - - - dat += {"UI Style: [UI_style]
    - Custom UI(recommended for White UI):    
    Color: [UI_style_color]
    - Alpha(transparency): [UI_style_alpha]
    - "} - - return dat - -/datum/preferences/proc/setup_special(var/dat, var/user) - dat += {"
    -

    General Settings

    - Play admin midis: [(toggles & SOUND_MIDI) ? "Yes" : "No"]
    - Play lobby music: [(toggles & SOUND_LOBBY) ? "Yes" : "No"]
    - Hear streamed media: [(toggles & SOUND_STREAMING) ? "Yes" : "No"]
    - Use WMP: [(usewmp) ? "Yes" : "No"]
    - Use NanoUI: [(usenanoui) ? "Yes" : "No"]
    - Progress Bars: [(progress_bars) ? "Yes" : "No"]
    - Randomized Character Slot: [randomslot ? "Yes" : "No"]
    - Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearby Speech"]
    - Ghost sight: [(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearby Emotes"]
    - Ghost radio: [(toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearby Speakers"]
    - Ghost PDA: [(toggles & CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]
    - Special Windows: [special_popup ? "Yes" : "No"]
    - Character Records: [jobban_isbanned(user, "Records") ? "Banned" : "Set
    "] - Flavor Text:Set
    - "} - - if(config.allow_Metadata) - dat += "OOC Notes: Edit
    " - - dat += "

    Antagonist Settings

    " - - if(jobban_isbanned(user, "Syndicate")) - dat += "You are banned from antagonist roles." - else - for (var/i in special_roles) - if(special_roles[i]) //if mode is available on the server - if(jobban_isbanned(user, i)) - dat += "Be [i]: \[BANNED]
    " - else if(i == "pai candidate") - if(jobban_isbanned(user, "pAI")) - dat += "Be [i]: \[BANNED]
    " - else - dat += "Be [i]: [roles[i] & ROLEPREF_ENABLE ? "Yes" : "No"]
    " - dat += "
    " - return dat - -/datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer", "AI"), widthPerColumn = 295, height = 620) - if(!job_master) - return - - //limit - The amount of jobs allowed per column. Defaults to 17 to make it look nice. - //splitJobs - Allows you split the table by job. You can make different tables for each department by including their heads. Defaults to CE to make it look nice. - //width - Screen' width. Defaults to 550 to make it look nice. - //height - Screen's height. Defaults to 500 to make it look nice. - var/width = widthPerColumn - - - var/HTML = "" - HTML += "" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:386: HTML += "
    " - HTML += {"
    - Choose occupation chances
    -
    Left-click to raise an occupation preference, right-click to lower it.
    - Done

    -
    - "} - - - // END AUTOFIX - var/index = -1 - - //The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows. - var/datum/job/lastJob - if (!job_master) return - for(var/datum/job/job in job_master.occupations) - index += 1 - if((index >= limit) || (job.title in splitJobs)) - width += widthPerColumn - if((index < limit) && (lastJob != null)) - //If the cells were broken up by a job in the splitJob list then it will fill in the rest of the cells with - //the last job's selection color. Creating a rather nice effect. - for(var/i = 0, i < (limit - index), i += 1) - HTML += "" - HTML += "
      
    " - index = 0 - - HTML += "" - continue - if(!job.player_old_enough(user.client)) - var/available_in_days = job.available_in_days(user.client) - HTML += "[rank]" - continue - if((job_civilian_low & ASSISTANT) && (rank != "Assistant")) - HTML += "[rank]" - continue - if((rank in command_positions) || (rank == "AI"))//Bold head jobs - if(job.alt_titles) - HTML += "[GetPlayerAltTitle(job)]" - else - HTML += "[rank]" - else - if(job.alt_titles) - HTML += "[GetPlayerAltTitle(job)]" - else - HTML += "[rank]" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:426: HTML += "" - continue - //if(job.alt_titles) - //HTML += "" - HTML += "[prefLevelLabel]" - HTML += "" - - - for(var/i = 1, i < (limit - index), i += 1) - HTML += "" - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:450: HTML += "
    " - var/rank = job.title - lastJob = job - if(jobban_isbanned(user, rank)) - HTML += "[rank] \[BANNED]
    \[IN [(available_in_days)] DAYS]
    " - HTML += "" - - - - var/prefLevelLabel = "ERROR" - var/prefLevelColor = "pink" - var/prefUpperLevel = -1 - var/prefLowerLevel = -1 - - if(GetJobDepartment(job, 1) & job.flag) - prefLevelLabel = "High" - prefLevelColor = "slateblue" - prefUpperLevel = 4 - prefLowerLevel = 2 - else if(GetJobDepartment(job, 2) & job.flag) - prefLevelLabel = "Medium" - prefLevelColor = "green" - prefUpperLevel = 1 - prefLowerLevel = 3 - else if(GetJobDepartment(job, 3) & job.flag) - prefLevelLabel = "Low" - prefLevelColor = "orange" - prefUpperLevel = 2 - prefLowerLevel = 4 - else - prefLevelLabel = "NEVER" - prefLevelColor = "red" - prefUpperLevel = 3 - prefLowerLevel = 1 - - HTML += "" - - - if(rank == "Assistant")//Assistant is special - if(job_civilian_low & ASSISTANT) - HTML += " Yes" - else - HTML += " No" - HTML += "
     \[[GetPlayerAltTitle(job)]\]
      
    " - HTML += {"
    -
    "} - // END AUTOFIX - switch(alternate_option) - if(GET_RANDOM_JOB) - HTML += "

    Get random job if preferences unavailable

    " - if(BE_ASSISTANT) - HTML += "

    Be assistant if preference unavailable

    " - if(RETURN_TO_LOBBY) - HTML += "

    Return to lobby if preference unavailable

    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:462: HTML += "
    \[Reset\]
    " - HTML += {"
    Reset
    -
    "} - // END AUTOFIX - user << browse(null, "window=preferences") - //user << browse(HTML, "window=mob_occupation;size=[width]x[height]") - var/datum/browser/popup = new(user, "mob_occupation", "
    Occupation Preferences
    ", width, height) - popup.set_content(HTML) - popup.open(0) - return - -/datum/preferences/proc/ShowChoices(mob/user) - if(!user || !user.client) return - update_preview_icon() - var/preview_front = fcopy_rsc(preview_icon_front) - var/preview_side = fcopy_rsc(preview_icon_side) - user << browse_rsc(preview_front, "previewicon.png") - user << browse_rsc(preview_side, "previewicon2.png") - var/dat = "" - - if(!IsGuestKey(user.key)) - - dat += {"
    - Slot [slot_name] - - Load slot - - Save slot - - Reload slot -

    "} - else - dat += "Please create an account to save your preferences." - - dat += "
    Character Settings | " - dat += "UI Settings | " - dat += "General Settings

    " - - if(appearance_isbanned(user)) - dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
    " - - switch(current_tab) - if(0) - dat = setup_character_options(dat, user) - if(1) - dat = setup_UI(dat, user) - if(2) - dat = setup_special(dat, user) - - dat += "

    " - - if(!IsGuestKey(user.key)) - dat += {"
    Undo | - Save Setup | "} - - dat += {"Reset Setup -
    "} - - //user << browse(dat, "window=preferences;size=560x580") - var/datum/browser/popup = new(user, "preferences", "
    Character Setup
    ", 640, 640) - popup.set_content(dat) - popup.open(0) - -/datum/preferences/proc/ShowDisabilityState(mob/user,flag,label) - if(flag==DISABILITY_FLAG_FAT && species!="Human") - return "
  • [species] cannot be fat.
  • " - return "
  • [label]: [disabilities & flag ? "Yes" : "No"]
  • " - -/datum/preferences/proc/SetDisabilities(mob/user) - var/HTML = "" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:474: HTML += "
    " - HTML += {"
    - Choose disabilities
      "} - // END AUTOFIX - HTML += ShowDisabilityState(user,DISABILITY_FLAG_NEARSIGHTED,"Needs Glasses") - HTML += ShowDisabilityState(user,DISABILITY_FLAG_FAT, "Obese") - HTML += ShowDisabilityState(user,DISABILITY_FLAG_EPILEPTIC, "Seizures") - HTML += ShowDisabilityState(user,DISABILITY_FLAG_DEAF, "Deaf") - /*HTML += ShowDisabilityState(user,DISABILITY_FLAG_COUGHING, "Coughing") - HTML += ShowDisabilityState(user,DISABILITY_FLAG_TOURETTES, "Tourettes") Still working on it! -Angelite*/ - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:481: HTML += "
    " - HTML += {" - \[Done\] - \[Reset\] -
    "} - // END AUTOFIX - user << browse(null, "window=preferences") - user << browse(HTML, "window=disabil;size=350x300") - return - -/datum/preferences/proc/SetRecords(mob/user) - var/HTML = "" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:492: HTML += "
    " - HTML += {"
    - Set Character Records
    - Medical Records
    "} - // END AUTOFIX - if(length(med_record) <= 40) - HTML += "[med_record]" - else - HTML += "[copytext(med_record, 1, 37)]..." - - HTML += "

    Employment Records
    " - - if(length(gen_record) <= 40) - HTML += "[gen_record]" - else - HTML += "[copytext(gen_record, 1, 37)]..." - - HTML += "

    Security Records
    " - - if(length(sec_record) <= 40) - HTML += "[sec_record]
    " - else - HTML += "[copytext(sec_record, 1, 37)]...
    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:516: HTML += "
    " - HTML += {"
    - \[Done\] -
    "} - // END AUTOFIX - user << browse(null, "window=preferences") - user << browse(HTML, "window=records;size=350x300") - return - - -/datum/preferences/proc/GetPlayerAltTitle(datum/job/job) - return player_alt_titles.Find(job.title) > 0 \ - ? player_alt_titles[job.title] \ - : job.title - -/datum/preferences/proc/SetPlayerAltTitle(datum/job/job, new_title) - // remove existing entry - if(player_alt_titles.Find(job.title)) - player_alt_titles -= job.title - // add one if it's not default - if(job.title != new_title) - player_alt_titles[job.title] = new_title - -/datum/preferences/proc/SetJob(mob/user, role) - var/datum/job/job = job_master.GetJob(role) - if(!job) - user << browse(null, "window=mob_occupation") - ShowChoices(user) - return - - if(role == "Assistant") - if(job_civilian_low & job.flag) - job_civilian_low &= ~job.flag - else - job_civilian_low |= job.flag - SetChoices(user) - return 1 - - if(GetJobDepartment(job, 1) & job.flag) - SetJobDepartment(job, 1) - else if(GetJobDepartment(job, 2) & job.flag) - SetJobDepartment(job, 2) - else if(GetJobDepartment(job, 3) & job.flag) - SetJobDepartment(job, 3) - else//job = Never - SetJobDepartment(job, 4) - - SetChoices(user) - return 1 -/datum/preferences/proc/ResetJobs() - job_civilian_high = 0 - job_civilian_med = 0 - job_civilian_low = 0 - - job_medsci_high = 0 - job_medsci_med = 0 - job_medsci_low = 0 - - job_engsec_high = 0 - job_engsec_med = 0 - job_engsec_low = 0 - -/datum/preferences/proc/GetJobDepartment(var/datum/job/job, var/level) - if(!job || !level) return 0 - switch(job.department_flag) - if(CIVILIAN) - switch(level) - if(1) - return job_civilian_high - if(2) - return job_civilian_med - if(3) - return job_civilian_low - if(MEDSCI) - switch(level) - if(1) - return job_medsci_high - if(2) - return job_medsci_med - if(3) - return job_medsci_low - if(ENGSEC) - switch(level) - if(1) - return job_engsec_high - if(2) - return job_engsec_med - if(3) - return job_engsec_low - return 0 - -/datum/preferences/proc/SetJobDepartment(var/datum/job/job, var/level) - if(!job || !level) return 0 - switch(level) - if(1)//Only one of these should ever be active at once so clear them all here - job_civilian_high = 0 - job_medsci_high = 0 - job_engsec_high = 0 - return 1 - if(2)//Set current highs to med, then reset them - job_civilian_med |= job_civilian_high - job_medsci_med |= job_medsci_high - job_engsec_med |= job_engsec_high - job_civilian_high = 0 - job_medsci_high = 0 - job_engsec_high = 0 - - switch(job.department_flag) - if(CIVILIAN) - switch(level) - if(2) - job_civilian_high = job.flag - job_civilian_med &= ~job.flag - if(3) - job_civilian_med |= job.flag - job_civilian_low &= ~job.flag - else - job_civilian_low |= job.flag - if(MEDSCI) - switch(level) - if(2) - job_medsci_high = job.flag - job_medsci_med &= ~job.flag - if(3) - job_medsci_med |= job.flag - job_medsci_low &= ~job.flag - else - job_medsci_low |= job.flag - if(ENGSEC) - switch(level) - if(2) - job_engsec_high = job.flag - job_engsec_med &= ~job.flag - if(3) - job_engsec_med |= job.flag - job_engsec_low &= ~job.flag - else - job_engsec_low |= job.flag - return 1 - - - -/datum/preferences/proc/SetRoles(var/mob/user, var/list/href_list) - // We just grab the role from the POST(?) data. - for(var/role_id in special_roles) - if(!(role_id in href_list)) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +var/list/preferences_datums = list() + +var/global/list/special_roles = list( + ROLE_ALIEN = 1, //always show + ROLE_BLOB = 1, + ROLE_BORER = 1, + ROLE_CHANGELING = IS_MODE_COMPILED("changeling"), + ROLE_CULTIST = IS_MODE_COMPILED("cult"), + ROLE_PLANT = 1, + "infested monkey" = IS_MODE_COMPILED("monkey"), + ROLE_MALF = IS_MODE_COMPILED("malfunction"), + ROLE_NINJA = 1, + ROLE_OPERATIVE = IS_MODE_COMPILED("nuclear"), + ROLE_PAI = 1, // -- TLE + ROLE_POSIBRAIN = 1, + ROLE_REV = IS_MODE_COMPILED("revolution"), + ROLE_TRAITOR = IS_MODE_COMPILED("traitor"), + ROLE_VAMPIRE = IS_MODE_COMPILED("vampire"), + ROLE_VOXRAIDER = IS_MODE_COMPILED("heist"), + ROLE_WIZARD = 1, +) + +var/const/MAX_SAVE_SLOTS = 8 + +//used for alternate_option +#define GET_RANDOM_JOB 0 +#define BE_ASSISTANT 1 +#define RETURN_TO_LOBBY 2 +#define POLLED_LIMIT 300 + +/datum/preferences + //doohickeys for savefiles + var/database/db = ("players2.sqlite") + var/path + var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used + var/slot = 1 + var/list/slot_names = new + var/lastPolled = 0 + + var/savefile_version = 0 + + //non-preference stuff + var/warns = 0 + var/warnbans = 0 + var/muted = 0 + var/last_ip + var/last_id + + //game-preferences + var/lastchangelog = "" //Saved changlog filesize to detect if there was a change + var/ooccolor = "#b82e00" + var/UI_style = "Midnight" + var/toggles = TOGGLES_DEFAULT + var/UI_style_color = "#ffffff" + var/UI_style_alpha = 255 + var/special_popup = 0 + + //character preferences + var/real_name //our character's name + var/be_random_name = 0 //whether we are a random name every round + var/be_random_body = 0 //whether we'll have a random body every round + var/gender = MALE //gender of character (well duh) + var/age = 30 //age of character + var/b_type = "A+" //blood type (not-chooseable) + var/underwear = 1 //underwear type + var/backbag = 2 //backpack type + var/h_style = "Bald" //Hair type + var/r_hair = 0 //Hair color + var/g_hair = 0 //Hair color + var/b_hair = 0 //Hair color + var/f_style = "Shaved" //Face hair type + 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/r_eyes = 0 //Eye color + var/g_eyes = 0 //Eye color + var/b_eyes = 0 //Eye color + var/species = "Human" + var/language = "None" //Secondary language + + //Mob preview + var/icon/preview_icon = null + var/icon/preview_icon_front = null + var/icon/preview_icon_side = null + + //Jobs, uses bitflags + var/job_civilian_high = 0 + var/job_civilian_med = 0 + var/job_civilian_low = 0 + + var/job_medsci_high = 0 + var/job_medsci_med = 0 + var/job_medsci_low = 0 + + var/job_engsec_high = 0 + var/job_engsec_med = 0 + var/job_engsec_low = 0 + + //Keeps track of preferrence for not getting any wanted jobs + var/alternate_option = 0 + + var/used_skillpoints = 0 + var/skill_specialization = null + var/list/skills = list() // skills can range from 0 to 3 + + // maps each organ to either null(intact), "cyborg" or "amputated" + // will probably not be able to do this for head and torso ;) + var/list/organ_data = list() + + var/list/player_alt_titles = new() // the default name of a job like "Medical Doctor" + + var/flavor_text = "" + var/med_record = "" + var/sec_record = "" + var/gen_record = "" + var/disabilities = 0 // NOW A BITFIELD, SEE ABOVE + + var/nanotrasen_relation = "Neutral" + + // 0 = character settings, 1 = game preferences + var/current_tab = 0 + + // OOC Metadata: + var/metadata = "" + var/slot_name = "" + + // Whether or not to use randomized character slots + var/randomslot = 0 + + // jukebox volume + var/volume = 100 + var/usewmp = 0 //whether to use WMP or VLC + + var/list/roles=list() // "role" => ROLEPREF_* + + var/usenanoui = 1 //Whether or not this client will use nanoUI, this doesn't do anything other than objects being able to check this. + + var/progress_bars = 1 //Whether to show progress bars when doing delayed actions. + var/client/client + +/datum/preferences/New(client/C) + b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") + client=C + if(istype(C)) + if(!IsGuestKey(C.key)) + var/load_pref = load_preferences_sqlite(C.ckey) + if(load_pref) + if(load_save_sqlite(C.ckey, src, default_slot)) + return + randomize_appearance_for() + real_name = random_name(gender) + save_character_sqlite(src, C.ckey, default_slot) + +/datum/preferences/proc/setup_character_options(var/dat, var/user) + + + dat += {"

    Occupation Choices

    + Set Occupation Preferences
    +

    Identity

    +
    + Random Name + Always Random Name: [be_random_name ? "Yes" : "No"]
    + Name: [real_name]
    + Gender: [gender == MALE ? "Male" : "Female"]
    + Age: [age] +
    +
    +
    +

    Body

    + Random Body + Always Random Body: [be_random_body ? "Yes" : "No"]
    +
    + Species: [species]
    + Secondary Language: [language]
    + Blood Type: [b_type]
    + Skin Tone: [-s_tone + 35]/220

    + Handicaps: Set
    + Limbs: Set
    + Organs: Set
    + Underwear: [gender == MALE ? "[underwear_m[underwear]]" : "[underwear_f[underwear]]"]
    + Backpack: [backbaglist[backbag]]
    + Nanotrasen Relation:
    [nanotrasen_relation] +
    +

    Hair Style

    + [h_style]
    + < >
    +     Change
    +
    +

    Facial Hair Style

    + [f_style]
    + < >
    +     Change
    +
    +

    Eye Color

    +     Change
    +
    + "} + + return dat + +/datum/preferences/proc/setup_UI(var/dat, var/user) + + + dat += {"UI Style: [UI_style]
    + Custom UI(recommended for White UI):    
    Color: [UI_style_color]
    + Alpha(transparency): [UI_style_alpha]
    + "} + + return dat + +/datum/preferences/proc/setup_special(var/dat, var/user) + dat += {"
    +

    General Settings

    + Play admin midis: [(toggles & SOUND_MIDI) ? "Yes" : "No"]
    + Play lobby music: [(toggles & SOUND_LOBBY) ? "Yes" : "No"]
    + Hear streamed media: [(toggles & SOUND_STREAMING) ? "Yes" : "No"]
    + Use WMP: [(usewmp) ? "Yes" : "No"]
    + Use NanoUI: [(usenanoui) ? "Yes" : "No"]
    + Progress Bars: [(progress_bars) ? "Yes" : "No"]
    + Randomized Character Slot: [randomslot ? "Yes" : "No"]
    + Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearby Speech"]
    + Ghost sight: [(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearby Emotes"]
    + Ghost radio: [(toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearby Speakers"]
    + Ghost PDA: [(toggles & CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]
    + Special Windows: [special_popup ? "Yes" : "No"]
    + Character Records: [jobban_isbanned(user, "Records") ? "Banned" : "Set
    "] + Flavor Text:Set
    + "} + + if(config.allow_Metadata) + dat += "OOC Notes: Edit
    " + + dat += "

    Antagonist Settings

    " + + if(jobban_isbanned(user, "Syndicate")) + dat += "You are banned from antagonist roles." + else + for (var/i in special_roles) + if(special_roles[i]) //if mode is available on the server + if(jobban_isbanned(user, i)) + dat += "Be [i]: \[BANNED]
    " + else if(i == "pai candidate") + if(jobban_isbanned(user, "pAI")) + dat += "Be [i]: \[BANNED]
    " + else + dat += "Be [i]: [roles[i] & ROLEPREF_ENABLE ? "Yes" : "No"]
    " + dat += "
    " + return dat + +/datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer", "AI"), widthPerColumn = 295, height = 620) + if(!job_master) + return + + //limit - The amount of jobs allowed per column. Defaults to 17 to make it look nice. + //splitJobs - Allows you split the table by job. You can make different tables for each department by including their heads. Defaults to CE to make it look nice. + //width - Screen' width. Defaults to 550 to make it look nice. + //height - Screen's height. Defaults to 500 to make it look nice. + var/width = widthPerColumn + + + var/HTML = "" + HTML += "" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:386: HTML += "
    " + HTML += {"
    + Choose occupation chances
    +
    Left-click to raise an occupation preference, right-click to lower it.
    + Done

    +
    + "} + + + // END AUTOFIX + var/index = -1 + + //The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows. + var/datum/job/lastJob + if (!job_master) return + for(var/datum/job/job in job_master.occupations) + index += 1 + if((index >= limit) || (job.title in splitJobs)) + width += widthPerColumn + if((index < limit) && (lastJob != null)) + //If the cells were broken up by a job in the splitJob list then it will fill in the rest of the cells with + //the last job's selection color. Creating a rather nice effect. + for(var/i = 0, i < (limit - index), i += 1) + HTML += "" + HTML += "
      
    " + index = 0 + + HTML += "" + continue + if(!job.player_old_enough(user.client)) + var/available_in_days = job.available_in_days(user.client) + HTML += "[rank]" + continue + if((job_civilian_low & ASSISTANT) && (rank != "Assistant")) + HTML += "[rank]" + continue + if((rank in command_positions) || (rank == "AI"))//Bold head jobs + if(job.alt_titles) + HTML += "[GetPlayerAltTitle(job)]" + else + HTML += "[rank]" + else + if(job.alt_titles) + HTML += "[GetPlayerAltTitle(job)]" + else + HTML += "[rank]" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:426: HTML += "" + continue + //if(job.alt_titles) + //HTML += "" + HTML += "[prefLevelLabel]" + HTML += "" + + + for(var/i = 1, i < (limit - index), i += 1) + HTML += "" + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:450: HTML += "
    " + var/rank = job.title + lastJob = job + if(jobban_isbanned(user, rank)) + HTML += "[rank] \[BANNED]
    \[IN [(available_in_days)] DAYS]
    " + HTML += "" + + + + var/prefLevelLabel = "ERROR" + var/prefLevelColor = "pink" + var/prefUpperLevel = -1 + var/prefLowerLevel = -1 + + if(GetJobDepartment(job, 1) & job.flag) + prefLevelLabel = "High" + prefLevelColor = "slateblue" + prefUpperLevel = 4 + prefLowerLevel = 2 + else if(GetJobDepartment(job, 2) & job.flag) + prefLevelLabel = "Medium" + prefLevelColor = "green" + prefUpperLevel = 1 + prefLowerLevel = 3 + else if(GetJobDepartment(job, 3) & job.flag) + prefLevelLabel = "Low" + prefLevelColor = "orange" + prefUpperLevel = 2 + prefLowerLevel = 4 + else + prefLevelLabel = "NEVER" + prefLevelColor = "red" + prefUpperLevel = 3 + prefLowerLevel = 1 + + HTML += "" + + + if(rank == "Assistant")//Assistant is special + if(job_civilian_low & ASSISTANT) + HTML += " Yes" + else + HTML += " No" + HTML += "
     \[[GetPlayerAltTitle(job)]\]
      
    " + HTML += {"
    +
    "} + // END AUTOFIX + switch(alternate_option) + if(GET_RANDOM_JOB) + HTML += "

    Get random job if preferences unavailable

    " + if(BE_ASSISTANT) + HTML += "

    Be assistant if preference unavailable

    " + if(RETURN_TO_LOBBY) + HTML += "

    Return to lobby if preference unavailable

    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:462: HTML += "
    \[Reset\]
    " + HTML += {"
    Reset
    +
    "} + // END AUTOFIX + user << browse(null, "window=preferences") + //user << browse(HTML, "window=mob_occupation;size=[width]x[height]") + var/datum/browser/popup = new(user, "mob_occupation", "
    Occupation Preferences
    ", width, height) + popup.set_content(HTML) + popup.open(0) + return + +/datum/preferences/proc/ShowChoices(mob/user) + if(!user || !user.client) return + update_preview_icon() + var/preview_front = fcopy_rsc(preview_icon_front) + var/preview_side = fcopy_rsc(preview_icon_side) + user << browse_rsc(preview_front, "previewicon.png") + user << browse_rsc(preview_side, "previewicon2.png") + var/dat = "" + + if(!IsGuestKey(user.key)) + + dat += {"
    + Slot [slot_name] - + Load slot - + Save slot - + Reload slot +

    "} + else + dat += "Please create an account to save your preferences." + + dat += "
    Character Settings | " + dat += "UI Settings | " + dat += "General Settings

    " + + if(appearance_isbanned(user)) + dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game.
    " + + switch(current_tab) + if(0) + dat = setup_character_options(dat, user) + if(1) + dat = setup_UI(dat, user) + if(2) + dat = setup_special(dat, user) + + dat += "

    " + + if(!IsGuestKey(user.key)) + dat += {"
    Undo | + Save Setup | "} + + dat += {"Reset Setup +
    "} + + //user << browse(dat, "window=preferences;size=560x580") + var/datum/browser/popup = new(user, "preferences", "
    Character Setup
    ", 640, 640) + popup.set_content(dat) + popup.open(0) + +/datum/preferences/proc/ShowDisabilityState(mob/user,flag,label) + if(flag==DISABILITY_FLAG_FAT && species!="Human") + return "
  • [species] cannot be fat.
  • " + return "
  • [label]: [disabilities & flag ? "Yes" : "No"]
  • " + +/datum/preferences/proc/SetDisabilities(mob/user) + var/HTML = "" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:474: HTML += "
    " + HTML += {"
    + Choose disabilities
      "} + // END AUTOFIX + HTML += ShowDisabilityState(user,DISABILITY_FLAG_NEARSIGHTED,"Needs Glasses") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_FAT, "Obese") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_EPILEPTIC, "Seizures") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_DEAF, "Deaf") + /*HTML += ShowDisabilityState(user,DISABILITY_FLAG_COUGHING, "Coughing") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_TOURETTES, "Tourettes") Still working on it! -Angelite*/ + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:481: HTML += "
    " + HTML += {" + \[Done\] + \[Reset\] +
    "} + // END AUTOFIX + user << browse(null, "window=preferences") + user << browse(HTML, "window=disabil;size=350x300") + return + +/datum/preferences/proc/SetRecords(mob/user) + var/HTML = "" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:492: HTML += "
    " + HTML += {"
    + Set Character Records
    + Medical Records
    "} + // END AUTOFIX + if(length(med_record) <= 40) + HTML += "[med_record]" + else + HTML += "[copytext(med_record, 1, 37)]..." + + HTML += "

    Employment Records
    " + + if(length(gen_record) <= 40) + HTML += "[gen_record]" + else + HTML += "[copytext(gen_record, 1, 37)]..." + + HTML += "

    Security Records
    " + + if(length(sec_record) <= 40) + HTML += "[sec_record]
    " + else + HTML += "[copytext(sec_record, 1, 37)]...
    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:516: HTML += "
    " + HTML += {"
    + \[Done\] +
    "} + // END AUTOFIX + user << browse(null, "window=preferences") + user << browse(HTML, "window=records;size=350x300") + return + + +/datum/preferences/proc/GetPlayerAltTitle(datum/job/job) + return player_alt_titles.Find(job.title) > 0 \ + ? player_alt_titles[job.title] \ + : job.title + +/datum/preferences/proc/SetPlayerAltTitle(datum/job/job, new_title) + // remove existing entry + if(player_alt_titles.Find(job.title)) + player_alt_titles -= job.title + // add one if it's not default + if(job.title != new_title) + player_alt_titles[job.title] = new_title + +/datum/preferences/proc/SetJob(mob/user, role) + var/datum/job/job = job_master.GetJob(role) + if(!job) + user << browse(null, "window=mob_occupation") + ShowChoices(user) + return + + if(role == "Assistant") + if(job_civilian_low & job.flag) + job_civilian_low &= ~job.flag + else + job_civilian_low |= job.flag + SetChoices(user) + return 1 + + if(GetJobDepartment(job, 1) & job.flag) + SetJobDepartment(job, 1) + else if(GetJobDepartment(job, 2) & job.flag) + SetJobDepartment(job, 2) + else if(GetJobDepartment(job, 3) & job.flag) + SetJobDepartment(job, 3) + else//job = Never + SetJobDepartment(job, 4) + + SetChoices(user) + return 1 +/datum/preferences/proc/ResetJobs() + job_civilian_high = 0 + job_civilian_med = 0 + job_civilian_low = 0 + + job_medsci_high = 0 + job_medsci_med = 0 + job_medsci_low = 0 + + job_engsec_high = 0 + job_engsec_med = 0 + job_engsec_low = 0 + +/datum/preferences/proc/GetJobDepartment(var/datum/job/job, var/level) + if(!job || !level) return 0 + switch(job.department_flag) + if(CIVILIAN) + switch(level) + if(1) + return job_civilian_high + if(2) + return job_civilian_med + if(3) + return job_civilian_low + if(MEDSCI) + switch(level) + if(1) + return job_medsci_high + if(2) + return job_medsci_med + if(3) + return job_medsci_low + if(ENGSEC) + switch(level) + if(1) + return job_engsec_high + if(2) + return job_engsec_med + if(3) + return job_engsec_low + return 0 + +/datum/preferences/proc/SetJobDepartment(var/datum/job/job, var/level) + if(!job || !level) return 0 + switch(level) + if(1)//Only one of these should ever be active at once so clear them all here + job_civilian_high = 0 + job_medsci_high = 0 + job_engsec_high = 0 + return 1 + if(2)//Set current highs to med, then reset them + job_civilian_med |= job_civilian_high + job_medsci_med |= job_medsci_high + job_engsec_med |= job_engsec_high + job_civilian_high = 0 + job_medsci_high = 0 + job_engsec_high = 0 + + switch(job.department_flag) + if(CIVILIAN) + switch(level) + if(2) + job_civilian_high = job.flag + job_civilian_med &= ~job.flag + if(3) + job_civilian_med |= job.flag + job_civilian_low &= ~job.flag + else + job_civilian_low |= job.flag + if(MEDSCI) + switch(level) + if(2) + job_medsci_high = job.flag + job_medsci_med &= ~job.flag + if(3) + job_medsci_med |= job.flag + job_medsci_low &= ~job.flag + else + job_medsci_low |= job.flag + if(ENGSEC) + switch(level) + if(2) + job_engsec_high = job.flag + job_engsec_med &= ~job.flag + if(3) + job_engsec_med |= job.flag + job_engsec_low &= ~job.flag + else + job_engsec_low |= job.flag + return 1 + + + +/datum/preferences/proc/SetRoles(var/mob/user, var/list/href_list) + // We just grab the role from the POST(?) data. + for(var/role_id in special_roles) + if(!(role_id in href_list)) to_chat(user, "BUG: Unable to find role [role_id].") - continue - var/oldval=text2num(roles[role_id]) - roles[role_id] = text2num(href_list[role_id]) - if(oldval!=roles[role_id]) + continue + var/oldval=text2num(roles[role_id]) + roles[role_id] = text2num(href_list[role_id]) + if(oldval!=roles[role_id]) to_chat(user, "Set role [role_id] to [get_role_desire_str(user.client.prefs.roles[role_id])]!") - - save_preferences_sqlite(user, user.ckey) - save_character_sqlite(user.ckey, user, default_slot) - return 1 - -/datum/preferences/proc/ToggleRole(var/mob/user, var/list/href_list) - var/role_id = href_list["role_id"] + + save_preferences_sqlite(user, user.ckey) + save_character_sqlite(user.ckey, user, default_slot) + return 1 + +/datum/preferences/proc/ToggleRole(var/mob/user, var/list/href_list) + var/role_id = href_list["role_id"] // to_chat(user, "Toggling role [role_id] (currently at [roles[role_id]])...") - if(!(role_id in special_roles)) + if(!(role_id in special_roles)) to_chat(user, "BUG: Unable to find role [role_id].") - return 0 - - if(roles[role_id] == null || roles[role_id] == "") - roles[role_id] = 0 - // Always set persist. - roles[role_id] |= ROLEPREF_PERSIST - // Toggle role enable - roles[role_id] ^= ROLEPREF_ENABLE - return 1 - -/datum/preferences/proc/SetRole(var/mob/user, var/list/href_list) - var/role_id = href_list["role_id"] + return 0 + + if(roles[role_id] == null || roles[role_id] == "") + roles[role_id] = 0 + // Always set persist. + roles[role_id] |= ROLEPREF_PERSIST + // Toggle role enable + roles[role_id] ^= ROLEPREF_ENABLE + return 1 + +/datum/preferences/proc/SetRole(var/mob/user, var/list/href_list) + var/role_id = href_list["role_id"] // to_chat(user, "Toggling role [role_id] (currently at [roles[role_id]])...") - if(!(role_id in special_roles)) + if(!(role_id in special_roles)) to_chat(user, "BUG: Unable to find role [role_id].") - return 0 - - if(roles[role_id] == null || roles[role_id] == "") - roles[role_id] = 0 - - var/question={"Would you like to be \a [role_id] this round? - -No/Yes: Only affects this round. -Never/Always: Saved for later rounds. - -NOTE: The change will take effect AFTER any current recruiting periods."} - var/answer = alert(question,"Role Preference", "Never", "No", "Yes", "Always") - var/newval=0 - switch(answer) - if("Never") - newval = ROLEPREF_NEVER - if("No") - newval = ROLEPREF_NO - if("Yes") - newval = ROLEPREF_YES - if("Always") - newval = ROLEPREF_ALWAYS - roles[role_id] = (roles[role_id] & ~ROLEPREF_VALMASK) | newval // We only set the lower 2 bits, leaving polled and friends untouched. - - save_preferences_sqlite(user, user.ckey) - save_character_sqlite(user.ckey, user, default_slot) - - return 1 -/datum/preferences/proc/process_link(mob/user, list/href_list) - if(!user) - return - - if(!istype(user, /mob/new_player)) - return - - if(href_list["preference"] == "job") - switch(href_list["task"]) - if("close") - user << browse(null, "window=mob_occupation") - ShowChoices(user) - if("reset") - ResetJobs() - SetChoices(user) - if("random") - if(alternate_option == GET_RANDOM_JOB || alternate_option == BE_ASSISTANT) - alternate_option += 1 - else if(alternate_option == RETURN_TO_LOBBY) - alternate_option = 0 - else - return 0 - SetChoices(user) - if ("alt_title") - var/datum/job/job = locate(href_list["job"]) - if (job) - var/choices = list(job.title) + job.alt_titles - var/choice = input("Pick a title for [job.title].", "Character Generation", GetPlayerAltTitle(job)) as anything in choices | null - if(choice) - SetPlayerAltTitle(job, choice) - SetChoices(user) - if("input") - SetJob(user, href_list["text"]) - else - SetChoices(user) - return 1 - else if(href_list["preference"] == "disabilities") - - switch(href_list["task"]) - if("close") - user << browse(null, "window=disabil") - ShowChoices(user) - if("reset") - disabilities=0 - SetDisabilities(user) - if("input") - var/dflag=text2num(href_list["disability"]) - if(dflag >= 0) - if(!(dflag==DISABILITY_FLAG_FAT && species!="Human")) - disabilities ^= text2num(href_list["disability"]) //MAGIC - SetDisabilities(user) - else - SetDisabilities(user) - return 1 - - else if(href_list["preference"] == "records") - if(text2num(href_list["record"]) >= 1) - SetRecords(user) - return - else - user << browse(null, "window=records") - if(href_list["task"] == "med_record") - var/medmsg = input(usr,"Set your medical notes here.","Medical Records",html_decode(med_record)) as message - - if(medmsg != null) - medmsg = copytext(medmsg, 1, MAX_PAPER_MESSAGE_LEN) - medmsg = html_encode(medmsg) - - med_record = medmsg - SetRecords(user) - - if(href_list["task"] == "sec_record") - var/secmsg = input(usr,"Set your security notes here.","Security Records",html_decode(sec_record)) as message - - if(secmsg != null) - secmsg = copytext(secmsg, 1, MAX_PAPER_MESSAGE_LEN) - secmsg = html_encode(secmsg) - - sec_record = secmsg - SetRecords(user) - if(href_list["task"] == "gen_record") - var/genmsg = input(usr,"Set your employment notes here.","Employment Records",html_decode(gen_record)) as message - - if(genmsg != null) - genmsg = copytext(genmsg, 1, MAX_PAPER_MESSAGE_LEN) - genmsg = html_encode(genmsg) - - gen_record = genmsg - SetRecords(user) - - else if(href_list["preference"] == "set_roles") - return SetRoles(user,href_list) - - else if(href_list["preference"] == "toggle_role") - ToggleRole(user,href_list) - - switch(href_list["task"]) - if("random") - switch(href_list["preference"]) - if("name") - real_name = random_name(gender,species) - if("age") - age = rand(AGE_MIN, AGE_MAX) - if("hair") - r_hair = rand(0,255) - g_hair = rand(0,255) - b_hair = rand(0,255) - if("h_style") - h_style = random_hair_style(gender, species) - if("facial") - r_facial = rand(0,255) - g_facial = rand(0,255) - b_facial = rand(0,255) - if("f_style") - f_style = random_facial_hair_style(gender, species) - if("underwear") - underwear = rand(1,underwear_m.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("bag") - backbag = rand(1,4) - /*if("skin_style") - h_style = random_skin_style(gender)*/ - if("all") - randomize_appearance_for() //no params needed - if("input") - switch(href_list["preference"]) - if("name") - var/new_name = reject_bad_name( input(user, "Choose your character's name:", "Character Preference") as text|null ) - if(new_name) - real_name = new_name - else + return 0 + + if(roles[role_id] == null || roles[role_id] == "") + roles[role_id] = 0 + + var/question={"Would you like to be \a [role_id] this round? + +No/Yes: Only affects this round. +Never/Always: Saved for later rounds. + +NOTE: The change will take effect AFTER any current recruiting periods."} + var/answer = alert(question,"Role Preference", "Never", "No", "Yes", "Always") + var/newval=0 + switch(answer) + if("Never") + newval = ROLEPREF_NEVER + if("No") + newval = ROLEPREF_NO + if("Yes") + newval = ROLEPREF_YES + if("Always") + newval = ROLEPREF_ALWAYS + roles[role_id] = (roles[role_id] & ~ROLEPREF_VALMASK) | newval // We only set the lower 2 bits, leaving polled and friends untouched. + + save_preferences_sqlite(user, user.ckey) + save_character_sqlite(user.ckey, user, default_slot) + + return 1 +/datum/preferences/proc/process_link(mob/user, list/href_list) + if(!user) + return + + if(!istype(user, /mob/new_player)) + return + + if(href_list["preference"] == "job") + switch(href_list["task"]) + if("close") + user << browse(null, "window=mob_occupation") + ShowChoices(user) + if("reset") + ResetJobs() + SetChoices(user) + if("random") + if(alternate_option == GET_RANDOM_JOB || alternate_option == BE_ASSISTANT) + alternate_option += 1 + else if(alternate_option == RETURN_TO_LOBBY) + alternate_option = 0 + else + return 0 + SetChoices(user) + if ("alt_title") + var/datum/job/job = locate(href_list["job"]) + if (job) + var/choices = list(job.title) + job.alt_titles + var/choice = input("Pick a title for [job.title].", "Character Generation", GetPlayerAltTitle(job)) as anything in choices | null + if(choice) + SetPlayerAltTitle(job, choice) + SetChoices(user) + if("input") + SetJob(user, href_list["text"]) + else + SetChoices(user) + return 1 + else if(href_list["preference"] == "disabilities") + + switch(href_list["task"]) + if("close") + user << browse(null, "window=disabil") + ShowChoices(user) + if("reset") + disabilities=0 + SetDisabilities(user) + if("input") + var/dflag=text2num(href_list["disability"]) + if(dflag >= 0) + if(!(dflag==DISABILITY_FLAG_FAT && species!="Human")) + disabilities ^= text2num(href_list["disability"]) //MAGIC + SetDisabilities(user) + else + SetDisabilities(user) + return 1 + + else if(href_list["preference"] == "records") + if(text2num(href_list["record"]) >= 1) + SetRecords(user) + return + else + user << browse(null, "window=records") + if(href_list["task"] == "med_record") + var/medmsg = input(usr,"Set your medical notes here.","Medical Records",html_decode(med_record)) as message + + if(medmsg != null) + medmsg = copytext(medmsg, 1, MAX_PAPER_MESSAGE_LEN) + medmsg = html_encode(medmsg) + + med_record = medmsg + SetRecords(user) + + if(href_list["task"] == "sec_record") + var/secmsg = input(usr,"Set your security notes here.","Security Records",html_decode(sec_record)) as message + + if(secmsg != null) + secmsg = copytext(secmsg, 1, MAX_PAPER_MESSAGE_LEN) + secmsg = html_encode(secmsg) + + sec_record = secmsg + SetRecords(user) + if(href_list["task"] == "gen_record") + var/genmsg = input(usr,"Set your employment notes here.","Employment Records",html_decode(gen_record)) as message + + if(genmsg != null) + genmsg = copytext(genmsg, 1, MAX_PAPER_MESSAGE_LEN) + genmsg = html_encode(genmsg) + + gen_record = genmsg + SetRecords(user) + + else if(href_list["preference"] == "set_roles") + return SetRoles(user,href_list) + + else if(href_list["preference"] == "toggle_role") + ToggleRole(user,href_list) + + switch(href_list["task"]) + if("random") + switch(href_list["preference"]) + if("name") + real_name = random_name(gender,species) + if("age") + age = rand(AGE_MIN, AGE_MAX) + if("hair") + r_hair = rand(0,255) + g_hair = rand(0,255) + b_hair = rand(0,255) + if("h_style") + h_style = random_hair_style(gender, species) + if("facial") + r_facial = rand(0,255) + g_facial = rand(0,255) + b_facial = rand(0,255) + if("f_style") + f_style = random_facial_hair_style(gender, species) + if("underwear") + underwear = rand(1,underwear_m.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("bag") + backbag = rand(1,4) + /*if("skin_style") + h_style = random_skin_style(gender)*/ + if("all") + randomize_appearance_for() //no params needed + if("input") + switch(href_list["preference"]) + if("name") + var/new_name = reject_bad_name( input(user, "Choose your character's name:", "Character Preference") as text|null ) + if(new_name) + real_name = new_name + else to_chat(user, "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and .") - if("next_hair_style") - if (gender == MALE) - h_style = next_list_item(h_style, hair_styles_male_list) - else - h_style = next_list_item(h_style, hair_styles_female_list) - if("previous_hair_style") - if (gender == MALE) - h_style = previous_list_item(h_style, hair_styles_male_list) - else - h_style = previous_list_item(h_style, hair_styles_female_list) - if("next_facehair_style") - if (gender == MALE) - f_style = next_list_item(f_style, facial_hair_styles_male_list) - else - f_style = next_list_item(f_style, facial_hair_styles_female_list) - if("previous_facehair_style") - if (gender == MALE) - f_style = previous_list_item(f_style, facial_hair_styles_male_list) - else - f_style = previous_list_item(f_style, facial_hair_styles_female_list) - if("age") - var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference") as num|null - if(new_age) - age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN) - if("species") - - var/list/new_species = list("Human") - var/prev_species = species - var/whitelisted = 0 - - if(config.usealienwhitelist) //If we're using the whitelist, make sure to check it! - for(var/S in whitelisted_species) - if(is_alien_whitelisted(user,S)) - new_species += S - whitelisted = 1 - if(!whitelisted) - alert(user, "You cannot change your species as you need to be whitelisted. If you wish to be whitelisted contact an admin in-game, on the forums, or on IRC.") - else //Not using the whitelist? Aliens for everyone! - new_species = whitelisted_species - - species = input("Please select a species", "Character Generation", null) in new_species - - if(prev_species != species) - //grab one of the valid hair styles for the newly chosen species - var/list/valid_hairstyles = list() - for(var/hairstyle in hair_styles_list) - var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue - if( !(species in S.species_allowed)) - continue - valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] - - if(valid_hairstyles.len) - h_style = pick(valid_hairstyles) - else - //this shouldn't happen - h_style = hair_styles_list["Bald"] - - //grab one of the valid facial hair styles for the newly chosen species - var/list/valid_facialhairstyles = list() - for(var/facialhairstyle in facial_hair_styles_list) - var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue - if( !(species in S.species_allowed)) - continue - - valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] - - if(valid_facialhairstyles.len) - f_style = pick(valid_facialhairstyles) - else - //this shouldn't happen - f_style = facial_hair_styles_list["Shaved"] - - //reset hair colour and skin colour - r_hair = 0//hex2num(copytext(new_hair, 2, 4)) - g_hair = 0//hex2num(copytext(new_hair, 4, 6)) - b_hair = 0//hex2num(copytext(new_hair, 6, 8)) - - s_tone = 0 - - if("language") - var/languages_available - var/list/new_languages = list("None") - - if(config.usealienwhitelist) - for(var/L in all_languages) - var/datum/language/lang = all_languages[L] - if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED )))) - new_languages += lang.name - - languages_available = 1 - - if(!(languages_available)) - alert(user, "There are not currently any available secondary languages.") - else - for(var/L in all_languages) - var/datum/language/lang = all_languages[L] - if(!(lang.flags & RESTRICTED)) - new_languages += lang.name - - language = input("Please select a secondary language", "Character Generation", null) in new_languages - - if("metadata") - var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null - if(new_metadata) - metadata = sanitize(copytext(new_metadata,1,MAX_MESSAGE_LEN)) - - if("b_type") - var/new_b_type = input(user, "Choose your character's blood-type:", "Character Preference") as null|anything in list( "A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-" ) - if(new_b_type) - b_type = new_b_type - - if("hair") - if(species == "Human" || species == "Unathi") - 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)) - g_hair = hex2num(copytext(new_hair, 4, 6)) - b_hair = hex2num(copytext(new_hair, 6, 8)) - - if("h_style") - var/list/valid_hairstyles = list() - for(var/hairstyle in hair_styles_list) - var/datum/sprite_accessory/S = hair_styles_list[hairstyle] - if( !(species in S.species_allowed)) - continue - - valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] - - var/new_h_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in valid_hairstyles - if(new_h_style) - h_style = new_h_style - - if("facial") - var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference") as color|null - if(new_facial) - r_facial = hex2num(copytext(new_facial, 2, 4)) - g_facial = hex2num(copytext(new_facial, 4, 6)) - b_facial = hex2num(copytext(new_facial, 6, 8)) - - if("f_style") - var/list/valid_facialhairstyles = list() - for(var/facialhairstyle in facial_hair_styles_list) - var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] - if(gender == MALE && S.gender == FEMALE) - continue - if(gender == FEMALE && S.gender == MALE) - continue - if( !(species in S.species_allowed)) - continue - - valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] - - var/new_f_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in valid_facialhairstyles - if(new_f_style) - f_style = new_f_style - - if("underwear") - var/list/underwear_options - if(gender == MALE) - underwear_options = underwear_m - else - underwear_options = underwear_f - - var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_options - if(new_underwear) - underwear = underwear_options.Find(new_underwear) - ShowChoices(user) - - if("eyes") - var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null - if(new_eyes) - r_eyes = hex2num(copytext(new_eyes, 2, 4)) - g_eyes = hex2num(copytext(new_eyes, 4, 6)) - b_eyes = hex2num(copytext(new_eyes, 6, 8)) - - if("s_tone") - if(species != "Human") - return - var/new_s_tone = input(user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Character Preference") as num|null - if(new_s_tone) - s_tone = 35 - max(min( round(new_s_tone), 220),1) - - if("ooccolor") - var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference") as color|null - if(new_ooccolor) - ooccolor = new_ooccolor - - if("bag") - var/new_backbag = input(user, "Choose your character's style of bag:", "Character Preference") as null|anything in backbaglist - if(new_backbag) - backbag = backbaglist.Find(new_backbag) - - if("nt_relation") - var/new_relation = input(user, "Choose your relation to NT. Note that this represents what others can find out about your character by researching your background, not what your character actually thinks.", "Character Preference") as null|anything in list("Loyal", "Supportive", "Neutral", "Skeptical", "Opposed") - if(new_relation) - nanotrasen_relation = new_relation - - if("flavor_text") - var/msg = input(usr,"Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!","Flavor Text",html_decode(flavor_text)) as message - if(msg != null) - msg = copytext(msg, 1, MAX_MESSAGE_LEN) - msg = html_encode(msg) - - flavor_text = msg - - if("limbs") - var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand") - if(!limb_name) return - - var/limb = null - var/second_limb = null // if you try to change the arm, the hand should also change - var/third_limb = null // if you try to unchange the hand, the arm should also change - var/valid_limb_states=list("Normal","Amputated","Prothesis") - switch(limb_name) - if("Left Leg") - limb = "l_leg" - second_limb = "l_foot" - valid_limb_states += "Peg Leg" - if("Right Leg") - limb = "r_leg" - second_limb = "r_foot" - valid_limb_states += "Peg Leg" - if("Left Arm") - limb = "l_arm" - second_limb = "l_hand" - valid_limb_states += "Wooden Prosthesis" - if("Right Arm") - limb = "r_arm" - second_limb = "r_hand" - valid_limb_states += "Wooden Prosthesis" - if("Left Foot") - limb = "l_foot" - third_limb = "l_leg" - if("Right Foot") - limb = "r_foot" - third_limb = "r_leg" - if("Left Hand") - limb = "l_hand" - third_limb = "l_arm" - valid_limb_states += "Hook Prosthesis" - if("Right Hand") - limb = "r_hand" - third_limb = "r_arm" - valid_limb_states += "Hook Prosthesis" - - var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in valid_limb_states - if(!new_state) return - - switch(new_state) - if("Normal") - organ_data[limb] = null - if(third_limb) - organ_data[third_limb] = null - if("Amputated") - organ_data[limb] = "amputated" - if(second_limb) - organ_data[second_limb] = "amputated" - if("Prothesis") - organ_data[limb] = "cyborg" - if(second_limb) - organ_data[second_limb] = "cyborg" - if("Peg Leg","Wooden Prosthesis","Hook Prosthesis") - organ_data[limb] = "peg" - if(second_limb) - if(limb == "l_arm" || limb == "r_arm") - organ_data[second_limb] = "peg" - else - organ_data[second_limb] = "amputated" - - if("organs") - var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes", "Lungs", "Liver", "Kidneys") - if(!organ_name) return - - var/organ = null - switch(organ_name) - if("Heart") - organ = "heart" - if("Eyes") - organ = "eyes" - if("Lungs") - organ = "lungs" - if("Liver") - organ = "liver" - if("Kidneys") - organ = "kidneys" - - var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in list("Normal","Assisted","Mechanical") - if(!new_state) return - - switch(new_state) - if("Normal") - organ_data[organ] = null - if("Assisted") - organ_data[organ] = "assisted" - if("Mechanical") - organ_data[organ] = "mechanical" - - if("skin_style") - var/skin_style_name = input(user, "Select a new skin style") as null|anything in list("default1", "default2", "default3") - if(!skin_style_name) return - - else - switch(href_list["preference"]) - if("gender") - if(gender == MALE) - gender = FEMALE - else - gender = MALE - f_style = random_facial_hair_style(gender) - h_style = random_hair_style(gender) - - if("hear_adminhelps") - toggles ^= SOUND_ADMINHELP - - if("ui") - switch(UI_style) - if("Midnight") - UI_style = "Orange" - if("Orange") - UI_style = "old" - if("old") - UI_style = "White" - else - UI_style = "Midnight" - - if("UIcolor") - var/UI_style_color_new = input(user, "Choose your UI colour, dark colours are not recommended!") as color|null - if(!UI_style_color_new) return - UI_style_color = UI_style_color_new - - if("UIalpha") - var/UI_style_alpha_new = input(user, "Select a new alpha(transparency) parameter for UI, between 50 and 255") as num - if(!UI_style_alpha_new | !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return - UI_style_alpha = UI_style_alpha_new - - if("name") - be_random_name = !be_random_name - - if("all") - be_random_body = !be_random_body - - if("special_popup") - special_popup = !special_popup - - if("randomslot") - randomslot = !randomslot - - if("hear_midis") - toggles ^= SOUND_MIDI - - if("lobby_music") - toggles ^= SOUND_LOBBY - if(toggles & SOUND_LOBBY) + if("next_hair_style") + if (gender == MALE) + h_style = next_list_item(h_style, hair_styles_male_list) + else + h_style = next_list_item(h_style, hair_styles_female_list) + if("previous_hair_style") + if (gender == MALE) + h_style = previous_list_item(h_style, hair_styles_male_list) + else + h_style = previous_list_item(h_style, hair_styles_female_list) + if("next_facehair_style") + if (gender == MALE) + f_style = next_list_item(f_style, facial_hair_styles_male_list) + else + f_style = next_list_item(f_style, facial_hair_styles_female_list) + if("previous_facehair_style") + if (gender == MALE) + f_style = previous_list_item(f_style, facial_hair_styles_male_list) + else + f_style = previous_list_item(f_style, facial_hair_styles_female_list) + if("age") + var/new_age = input(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference") as num|null + if(new_age) + age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN) + if("species") + + var/list/new_species = list("Human") + var/prev_species = species + var/whitelisted = 0 + + if(config.usealienwhitelist) //If we're using the whitelist, make sure to check it! + for(var/S in whitelisted_species) + if(is_alien_whitelisted(user,S)) + new_species += S + whitelisted = 1 + if(!whitelisted) + alert(user, "You cannot change your species as you need to be whitelisted. If you wish to be whitelisted contact an admin in-game, on the forums, or on IRC.") + else //Not using the whitelist? Aliens for everyone! + new_species = whitelisted_species + + species = input("Please select a species", "Character Generation", null) in new_species + + if(prev_species != species) + //grab one of the valid hair styles for the newly chosen species + var/list/valid_hairstyles = list() + for(var/hairstyle in hair_styles_list) + var/datum/sprite_accessory/S = hair_styles_list[hairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) + continue + valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] + + if(valid_hairstyles.len) + h_style = pick(valid_hairstyles) + else + //this shouldn't happen + h_style = hair_styles_list["Bald"] + + //grab one of the valid facial hair styles for the newly chosen species + var/list/valid_facialhairstyles = list() + for(var/facialhairstyle in facial_hair_styles_list) + var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) + continue + + valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] + + if(valid_facialhairstyles.len) + f_style = pick(valid_facialhairstyles) + else + //this shouldn't happen + f_style = facial_hair_styles_list["Shaved"] + + //reset hair colour and skin colour + r_hair = 0//hex2num(copytext(new_hair, 2, 4)) + g_hair = 0//hex2num(copytext(new_hair, 4, 6)) + b_hair = 0//hex2num(copytext(new_hair, 6, 8)) + + s_tone = 0 + + if("language") + var/languages_available + var/list/new_languages = list("None") + + if(config.usealienwhitelist) + for(var/L in all_languages) + var/datum/language/lang = all_languages[L] + if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED )))) + new_languages += lang.name + + languages_available = 1 + + if(!(languages_available)) + alert(user, "There are not currently any available secondary languages.") + else + for(var/L in all_languages) + var/datum/language/lang = all_languages[L] + if(!(lang.flags & RESTRICTED)) + new_languages += lang.name + + language = input("Please select a secondary language", "Character Generation", null) in new_languages + + if("metadata") + var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null + if(new_metadata) + metadata = sanitize(copytext(new_metadata,1,MAX_MESSAGE_LEN)) + + if("b_type") + var/new_b_type = input(user, "Choose your character's blood-type:", "Character Preference") as null|anything in list( "A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-" ) + if(new_b_type) + b_type = new_b_type + + if("hair") + if(species == "Human" || species == "Unathi") + 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)) + g_hair = hex2num(copytext(new_hair, 4, 6)) + b_hair = hex2num(copytext(new_hair, 6, 8)) + + if("h_style") + var/list/valid_hairstyles = list() + for(var/hairstyle in hair_styles_list) + var/datum/sprite_accessory/S = hair_styles_list[hairstyle] + if( !(species in S.species_allowed)) + continue + + valid_hairstyles[hairstyle] = hair_styles_list[hairstyle] + + var/new_h_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in valid_hairstyles + if(new_h_style) + h_style = new_h_style + + if("facial") + var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference") as color|null + if(new_facial) + r_facial = hex2num(copytext(new_facial, 2, 4)) + g_facial = hex2num(copytext(new_facial, 4, 6)) + b_facial = hex2num(copytext(new_facial, 6, 8)) + + if("f_style") + var/list/valid_facialhairstyles = list() + for(var/facialhairstyle in facial_hair_styles_list) + var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle] + if(gender == MALE && S.gender == FEMALE) + continue + if(gender == FEMALE && S.gender == MALE) + continue + if( !(species in S.species_allowed)) + continue + + valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle] + + var/new_f_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in valid_facialhairstyles + if(new_f_style) + f_style = new_f_style + + if("underwear") + var/list/underwear_options + if(gender == MALE) + underwear_options = underwear_m + else + underwear_options = underwear_f + + var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_options + if(new_underwear) + underwear = underwear_options.Find(new_underwear) + ShowChoices(user) + + if("eyes") + var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null + if(new_eyes) + r_eyes = hex2num(copytext(new_eyes, 2, 4)) + g_eyes = hex2num(copytext(new_eyes, 4, 6)) + b_eyes = hex2num(copytext(new_eyes, 6, 8)) + + if("s_tone") + if(species != "Human") + return + var/new_s_tone = input(user, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Character Preference") as num|null + if(new_s_tone) + s_tone = 35 - max(min( round(new_s_tone), 220),1) + + if("ooccolor") + var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference") as color|null + if(new_ooccolor) + ooccolor = new_ooccolor + + if("bag") + var/new_backbag = input(user, "Choose your character's style of bag:", "Character Preference") as null|anything in backbaglist + if(new_backbag) + backbag = backbaglist.Find(new_backbag) + + if("nt_relation") + var/new_relation = input(user, "Choose your relation to NT. Note that this represents what others can find out about your character by researching your background, not what your character actually thinks.", "Character Preference") as null|anything in list("Loyal", "Supportive", "Neutral", "Skeptical", "Opposed") + if(new_relation) + nanotrasen_relation = new_relation + + if("flavor_text") + var/msg = input(usr,"Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!","Flavor Text",html_decode(flavor_text)) as message + if(msg != null) + msg = copytext(msg, 1, MAX_MESSAGE_LEN) + msg = html_encode(msg) + + flavor_text = msg + + if("limbs") + var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand") + if(!limb_name) return + + var/limb = null + var/second_limb = null // if you try to change the arm, the hand should also change + var/third_limb = null // if you try to unchange the hand, the arm should also change + var/valid_limb_states=list("Normal","Amputated","Prothesis") + switch(limb_name) + if("Left Leg") + limb = "l_leg" + second_limb = "l_foot" + valid_limb_states += "Peg Leg" + if("Right Leg") + limb = "r_leg" + second_limb = "r_foot" + valid_limb_states += "Peg Leg" + if("Left Arm") + limb = "l_arm" + second_limb = "l_hand" + valid_limb_states += "Wooden Prosthesis" + if("Right Arm") + limb = "r_arm" + second_limb = "r_hand" + valid_limb_states += "Wooden Prosthesis" + if("Left Foot") + limb = "l_foot" + third_limb = "l_leg" + if("Right Foot") + limb = "r_foot" + third_limb = "r_leg" + if("Left Hand") + limb = "l_hand" + third_limb = "l_arm" + valid_limb_states += "Hook Prosthesis" + if("Right Hand") + limb = "r_hand" + third_limb = "r_arm" + valid_limb_states += "Hook Prosthesis" + + var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in valid_limb_states + if(!new_state) return + + switch(new_state) + if("Normal") + organ_data[limb] = null + if(third_limb) + organ_data[third_limb] = null + if("Amputated") + organ_data[limb] = "amputated" + if(second_limb) + organ_data[second_limb] = "amputated" + if("Prothesis") + organ_data[limb] = "cyborg" + if(second_limb) + organ_data[second_limb] = "cyborg" + if("Peg Leg","Wooden Prosthesis","Hook Prosthesis") + organ_data[limb] = "peg" + if(second_limb) + if(limb == "l_arm" || limb == "r_arm") + organ_data[second_limb] = "peg" + else + organ_data[second_limb] = "amputated" + + if("organs") + var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes", "Lungs", "Liver", "Kidneys") + if(!organ_name) return + + var/organ = null + switch(organ_name) + if("Heart") + organ = "heart" + if("Eyes") + organ = "eyes" + if("Lungs") + organ = "lungs" + if("Liver") + organ = "liver" + if("Kidneys") + organ = "kidneys" + + var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in list("Normal","Assisted","Mechanical") + if(!new_state) return + + switch(new_state) + if("Normal") + organ_data[organ] = null + if("Assisted") + organ_data[organ] = "assisted" + if("Mechanical") + organ_data[organ] = "mechanical" + + if("skin_style") + var/skin_style_name = input(user, "Select a new skin style") as null|anything in list("default1", "default2", "default3") + if(!skin_style_name) return + + else + switch(href_list["preference"]) + if("gender") + if(gender == MALE) + gender = FEMALE + else + gender = MALE + f_style = random_facial_hair_style(gender) + h_style = random_hair_style(gender) + + if("hear_adminhelps") + toggles ^= SOUND_ADMINHELP + + if("ui") + switch(UI_style) + if("Midnight") + UI_style = "Orange" + if("Orange") + UI_style = "old" + if("old") + UI_style = "White" + else + UI_style = "Midnight" + + if("UIcolor") + var/UI_style_color_new = input(user, "Choose your UI colour, dark colours are not recommended!") as color|null + if(!UI_style_color_new) return + UI_style_color = UI_style_color_new + + if("UIalpha") + var/UI_style_alpha_new = input(user, "Select a new alpha(transparency) parameter for UI, between 50 and 255") as num + if(!UI_style_alpha_new | !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return + UI_style_alpha = UI_style_alpha_new + + if("name") + be_random_name = !be_random_name + + if("all") + be_random_body = !be_random_body + + if("special_popup") + special_popup = !special_popup + + if("randomslot") + randomslot = !randomslot + + if("hear_midis") + toggles ^= SOUND_MIDI + + if("lobby_music") + toggles ^= SOUND_LOBBY + if(toggles & SOUND_LOBBY) to_chat(user, sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1)) - else + else to_chat(user, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1)) - - if("jukebox") - toggles ^= SOUND_STREAMING - - if("wmp") - usewmp = !usewmp - if("nanoui") - usenanoui = !usenanoui - if("progbar") - progress_bars = !progress_bars - if("ghost_ears") - toggles ^= CHAT_GHOSTEARS - - if("ghost_sight") - toggles ^= CHAT_GHOSTSIGHT - - if("ghost_radio") - toggles ^= CHAT_GHOSTRADIO - - if("ghost_pda") - toggles ^= CHAT_GHOSTPDA - - if("save") - if(world.timeofday >= (lastPolled + POLLED_LIMIT)) - save_preferences_sqlite(user, user.ckey) - save_character_sqlite(user.ckey, user, default_slot) - lastPolled = world.timeofday - else + + if("jukebox") + toggles ^= SOUND_STREAMING + + if("wmp") + usewmp = !usewmp + if("nanoui") + usenanoui = !usenanoui + if("progbar") + progress_bars = !progress_bars + if("ghost_ears") + toggles ^= CHAT_GHOSTEARS + + if("ghost_sight") + toggles ^= CHAT_GHOSTSIGHT + + if("ghost_radio") + toggles ^= CHAT_GHOSTRADIO + + if("ghost_pda") + toggles ^= CHAT_GHOSTPDA + + if("save") + if(world.timeofday >= (lastPolled + POLLED_LIMIT)) + save_preferences_sqlite(user, user.ckey) + save_character_sqlite(user.ckey, user, default_slot) + lastPolled = world.timeofday + else to_chat(user, "You need to wait [round((((lastPolled + POLLED_LIMIT) - world.timeofday) / 10))] seconds before you can save again.") - //random_character_sqlite(user, user.ckey) - - if("reload") - load_preferences_sqlite(user, user.ckey) - load_save_sqlite(user.ckey, user, default_slot) - - if("open_load_dialog") - if(!IsGuestKey(user.key)) - open_load_dialog(user) - - if("close_load_dialog") - close_load_dialog(user) - - if("changeslot") - var/num = text2num(href_list["num"]) - load_save_sqlite(user.ckey, user, num) - default_slot = num - close_load_dialog(user) - if("tab") - if(href_list["tab"]) - current_tab = text2num(href_list["tab"]) - ShowChoices(user) - return 1 - -/datum/preferences/proc/copy_to(mob/living/carbon/human/character, safety = 0) - if(be_random_name) - real_name = random_name(gender,species) - - if(config.humans_need_surnames && species == "Human") - var/firstspace = findtext(real_name, " ") - var/name_length = length(real_name) - if(!firstspace) //we need a surname - real_name += " [pick(last_names)]" - else if(firstspace == name_length) - real_name += "[pick(last_names)]" - - character.real_name = real_name - character.name = character.real_name - if(character.dna) - character.dna.real_name = character.real_name - - character.flavor_text = flavor_text - character.med_record = med_record - character.sec_record = sec_record - character.gen_record = gen_record - - character.setGender(gender) - character.age = age - character.b_type = b_type - - character.r_eyes = r_eyes - character.g_eyes = g_eyes - character.b_eyes = b_eyes - - character.r_hair = r_hair - character.g_hair = g_hair - character.b_hair = b_hair - - character.r_facial = r_facial - character.g_facial = g_facial - character.b_facial = b_facial - - character.s_tone = s_tone - - character.h_style = h_style - character.f_style = f_style - - - character.skills = skills - - // Destroy/cyborgize organs - - for(var/name in organ_data) - var/datum/organ/external/O = character.organs_by_name[name] - var/datum/organ/internal/I = character.internal_organs_by_name[name] - var/status = organ_data[name] - - if(status == "amputated") - O.status &= ~ORGAN_ROBOT - O.status &= ~ORGAN_PEG - O.amputated = 1 - O.status |= ORGAN_DESTROYED - O.destspawn = 1 - else if(status == "cyborg") - O.status &= ~ORGAN_PEG - O.status |= ORGAN_ROBOT - else if(status == "peg") - O.status &= ~ORGAN_ROBOT - O.status |= ORGAN_PEG - else if(status == "assisted") - I.mechassist() - else if(status == "mechanical") - I.mechanize() - else continue - var/datum/species/chosen_species = all_species[species] - if( (disabilities & DISABILITY_FLAG_FAT) && (chosen_species.flags & CAN_BE_FAT) ) - character.mutations += M_FAT - character.mutations += M_OBESITY - if(disabilities & DISABILITY_FLAG_NEARSIGHTED) - character.disabilities|=NEARSIGHTED - if(disabilities & DISABILITY_FLAG_EPILEPTIC) - character.disabilities|=EPILEPSY - if(disabilities & DISABILITY_FLAG_DEAF) - character.sdisabilities|=DEAF - /*if(disabilities & DISABILITY_FLAG_COUGHING) - character.sdisabilities|=COUGHING - if(disabilities & DISABILITY_FLAG_TOURETTES) - character.sdisabilities|=TOURETTES Still working on it. - Angelite */ - - if(underwear > underwear_m.len || underwear < 1) - 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(backbag > 4 || backbag < 1) - backbag = 1 //Same as above - character.backbag = backbag - - //Debugging report to track down a bug, which randomly assigned the plural gender to people. - if(character.gender in list(PLURAL, NEUTER)) - if(isliving(src)) //Ghosts get neuter by default - message_admins("[character] ([character.ckey]) has spawned with their gender as plural or neuter. Please notify coders.") - character.setGender(MALE) - -/datum/preferences/proc/open_load_dialog(mob/user) - - - var/database/query/q = new - var/list/name_list[MAX_SAVE_SLOTS] - - q.Add("select real_name, player_slot from players where player_ckey=?", user.ckey) - if(q.Execute(db)) - while(q.NextRow()) - name_list[q.GetColumn(2)] = q.GetColumn(1) - else - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:1283: var/dat = "" - var/dat = {"
    "} - // END AUTOFIX - dat += "Select a character slot to load
    " - var/counter = 1 - while(counter <= MAX_SAVE_SLOTS) - if(counter==default_slot) - dat += "[name_list[counter]]
    " - else - if(!name_list[counter]) - dat += "Character[counter]
    " - else - dat += "[name_list[counter]]
    " - counter++ - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:1228: dat += "
    " - dat += {"
    - Close
    -
    "} - // END AUTOFIX - user << browse(dat, "window=saves;size=300x390") - -/datum/preferences/proc/close_load_dialog(mob/user) - user << browse(null, "window=saves") - -/datum/preferences/proc/configure_special_roles(var/mob/user) - var/html={"
    - - -

    Special Role Preferences

    -

    Please note that this also handles in-round polling for things like Raging Mages and Borers.

    -
    - Legend -
    -
    Never:
    -
    Always answer no to this role.
    -
    No:
    -
    Answer no for this round. (Default)
    -
    Yes:
    -
    Answer yes for this round.
    -
    Always:
    -
    Always answer yes to this role.
    -
    -
    - - - - - - - - - - - "} - for(var/role_id in special_roles) - var/desire = get_role_desire_str(roles[role_id]) - html += {" - - - - - - "} - html += {" -
    RoleNeverNoYesAlways
    [role_id]
    - - -
    "} - var/datum/browser/B = new /datum/browser/clean(user, "roles", "Role Selections", 300, 390) - B.set_content(html) - B.add_stylesheet("specialroles", 'html/browser/config_roles.css') - B.open() - -/datum/preferences/Topic(href, href_list) - if(!usr || !client) - return - if(client.mob!=usr) + //random_character_sqlite(user, user.ckey) + + if("reload") + load_preferences_sqlite(user, user.ckey) + load_save_sqlite(user.ckey, user, default_slot) + + if("open_load_dialog") + if(!IsGuestKey(user.key)) + open_load_dialog(user) + + if("close_load_dialog") + close_load_dialog(user) + + if("changeslot") + var/num = text2num(href_list["num"]) + load_save_sqlite(user.ckey, user, num) + default_slot = num + close_load_dialog(user) + if("tab") + if(href_list["tab"]) + current_tab = text2num(href_list["tab"]) + ShowChoices(user) + return 1 + +/datum/preferences/proc/copy_to(mob/living/carbon/human/character, safety = 0) + if(be_random_name) + real_name = random_name(gender,species) + + if(config.humans_need_surnames && species == "Human") + var/firstspace = findtext(real_name, " ") + var/name_length = length(real_name) + if(!firstspace) //we need a surname + real_name += " [pick(last_names)]" + else if(firstspace == name_length) + real_name += "[pick(last_names)]" + + character.real_name = real_name + character.name = character.real_name + if(character.dna) + character.dna.real_name = character.real_name + + character.flavor_text = flavor_text + character.med_record = med_record + character.sec_record = sec_record + character.gen_record = gen_record + + character.setGender(gender) + character.age = age + character.b_type = b_type + + character.r_eyes = r_eyes + character.g_eyes = g_eyes + character.b_eyes = b_eyes + + character.r_hair = r_hair + character.g_hair = g_hair + character.b_hair = b_hair + + character.r_facial = r_facial + character.g_facial = g_facial + character.b_facial = b_facial + + character.s_tone = s_tone + + character.h_style = h_style + character.f_style = f_style + + + character.skills = skills + + // Destroy/cyborgize organs + + for(var/name in organ_data) + var/datum/organ/external/O = character.organs_by_name[name] + var/datum/organ/internal/I = character.internal_organs_by_name[name] + var/status = organ_data[name] + + if(status == "amputated") + O.status &= ~ORGAN_ROBOT + O.status &= ~ORGAN_PEG + O.amputated = 1 + O.status |= ORGAN_DESTROYED + O.destspawn = 1 + else if(status == "cyborg") + O.status &= ~ORGAN_PEG + O.status |= ORGAN_ROBOT + else if(status == "peg") + O.status &= ~ORGAN_ROBOT + O.status |= ORGAN_PEG + else if(status == "assisted") + I.mechassist() + else if(status == "mechanical") + I.mechanize() + else continue + var/datum/species/chosen_species = all_species[species] + if( (disabilities & DISABILITY_FLAG_FAT) && (chosen_species.flags & CAN_BE_FAT) ) + character.mutations += M_FAT + character.mutations += M_OBESITY + if(disabilities & DISABILITY_FLAG_NEARSIGHTED) + character.disabilities|=NEARSIGHTED + if(disabilities & DISABILITY_FLAG_EPILEPTIC) + character.disabilities|=EPILEPSY + if(disabilities & DISABILITY_FLAG_DEAF) + character.sdisabilities|=DEAF + /*if(disabilities & DISABILITY_FLAG_COUGHING) + character.sdisabilities|=COUGHING + if(disabilities & DISABILITY_FLAG_TOURETTES) + character.sdisabilities|=TOURETTES Still working on it. - Angelite */ + + if(underwear > underwear_m.len || underwear < 1) + 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(backbag > 4 || backbag < 1) + backbag = 1 //Same as above + character.backbag = backbag + + //Debugging report to track down a bug, which randomly assigned the plural gender to people. + if(character.gender in list(PLURAL, NEUTER)) + if(isliving(src)) //Ghosts get neuter by default + message_admins("[character] ([character.ckey]) has spawned with their gender as plural or neuter. Please notify coders.") + character.setGender(MALE) + +/datum/preferences/proc/open_load_dialog(mob/user) + + + var/database/query/q = new + var/list/name_list[MAX_SAVE_SLOTS] + + q.Add("select real_name, player_slot from players where player_ckey=?", user.ckey) + if(q.Execute(db)) + while(q.NextRow()) + name_list[q.GetColumn(2)] = q.GetColumn(1) + else + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:1283: var/dat = "" + var/dat = {"
    "} + // END AUTOFIX + dat += "Select a character slot to load
    " + var/counter = 1 + while(counter <= MAX_SAVE_SLOTS) + if(counter==default_slot) + dat += "[name_list[counter]]
    " + else + if(!name_list[counter]) + dat += "Character[counter]
    " + else + dat += "[name_list[counter]]
    " + counter++ + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\client\\\preferences.dm:1228: dat += "
    " + dat += {"
    + Close
    +
    "} + // END AUTOFIX + user << browse(dat, "window=saves;size=300x390") + +/datum/preferences/proc/close_load_dialog(mob/user) + user << browse(null, "window=saves") + +/datum/preferences/proc/configure_special_roles(var/mob/user) + var/html={"
    + + +

    Special Role Preferences

    +

    Please note that this also handles in-round polling for things like Raging Mages and Borers.

    +
    + Legend +
    +
    Never:
    +
    Always answer no to this role.
    +
    No:
    +
    Answer no for this round. (Default)
    +
    Yes:
    +
    Answer yes for this round.
    +
    Always:
    +
    Always answer yes to this role.
    +
    +
    + + + + + + + + + + + "} + for(var/role_id in special_roles) + var/desire = get_role_desire_str(roles[role_id]) + html += {" + + + + + + "} + html += {" +
    RoleNeverNoYesAlways
    [role_id]
    + + +
    "} + var/datum/browser/B = new /datum/browser/clean(user, "roles", "Role Selections", 300, 390) + B.set_content(html) + B.add_stylesheet("specialroles", 'html/browser/config_roles.css') + B.open() + +/datum/preferences/Topic(href, href_list) + if(!usr || !client) + return + if(client.mob!=usr) to_chat(usr, "YOU AREN'T ME GO AWAY") - return - switch(href_list["preference"]) - if("set_roles") - return SetRoles(usr, href_list) - if("set_role") - return SetRole(usr, href_list) + return + switch(href_list["preference"]) + if("set_roles") + return SetRoles(usr, href_list) + if("set_role") + return SetRole(usr, href_list) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index ce9ee66c394..be2661a94f9 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -1,198 +1,198 @@ -#define SAVEFILE_VERSION_MIN 8 -#define SAVEFILE_VERSION_MAX 11 - -//handles converting savefiles to new formats -//MAKE SURE YOU KEEP THIS UP TO DATE! -//If the sanity checks are capable of handling any issues. Only increase SAVEFILE_VERSION_MAX, -//this will mean that savefile_version will still be over SAVEFILE_VERSION_MIN, meaning -//this savefile update doesn't run everytime we load from the savefile. -//This is mainly for format changes, such as the bitflags in toggles changing order or something. -//if a file can't be updated, return 0 to delete it and start again -//if a file was updated, return 1 - -/// IF YOU NEED A FIELD ADDED TO THE DATABASE, CREATE A MIGRATION SO SHIT GETS UPDATED. -/// SEE code/modules/migrations/SS13_Prefs/ - -/datum/preferences/proc/savefile_update() - // Preseed roles. - for(var/role_id in special_roles) - roles[role_id]=0 - - if(savefile_version < 8) //lazily delete everything + additional files so they can be saved in the new format - for(var/ckey in preferences_datums) - var/datum/preferences/D = preferences_datums[ckey] - if(D == src) - var/delpath = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/" - if(delpath && fexists(delpath)) - fdel(delpath) - break - return 0 - - if(savefile_version == SAVEFILE_VERSION_MAX) //update successful. - save_preferences() - save_character() - return 1 - return 0 - - -/datum/preferences/proc/load_path(ckey,filename="preferences.sav") - if(!ckey) return - path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]" - savefile_version = SAVEFILE_VERSION_MAX - - -/datum/preferences/proc/SetChangelog(ckey,hash) - lastchangelog=hash - var/database/query/q = new - q.Add("UPDATE client SET lastchangelog=? WHERE ckey=?",lastchangelog,ckey) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - -/datum/preferences/proc/load_preferences_sqlite(var/ckey) - var/list/preference_list_client = new - var/database/query/check = new - var/database/query/q = new - check.Add("SELECT ckey FROM client WHERE ckey = ?", ckey) - if(check.Execute(db)) - if(!check.NextRow()) - return 0 - else - message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - q.Add("SELECT * FROM client WHERE ckey = ?", ckey) - if(q.Execute(db)) - while(q.NextRow()) - var/list/row = q.GetRowData() - for(var/a in row) - preference_list_client[a] = row[a] - else - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - ooccolor = preference_list_client["ooc_color"] - lastchangelog = preference_list_client["lastchangelog"] - UI_style = preference_list_client["UI_style"] - default_slot = text2num(preference_list_client["default_slot"]) - toggles = text2num(preference_list_client["toggles"]) - UI_style_color = preference_list_client["UI_style_color"] - UI_style_alpha = text2num(preference_list_client["UI_style_alpha"]) - warns = text2num(preference_list_client["warns"]) - warnbans = text2num(preference_list_client["warnsbans"]) - volume = text2num(preference_list_client["volume"]) - usewmp = text2num(preference_list_client["usewmp"]) - special_popup = text2num(preference_list_client["special"]) - randomslot = text2num(preference_list_client["randomslot"]) - usenanoui = text2num(preference_list_client["usenanoui"]) - progress_bars = text2num(preference_list_client["progress_bars"]) - - ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) - lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) - UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style)) - //be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) - default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) - toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) - UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) - UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) - randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) - volume = sanitize_integer(volume, 0, 100, initial(volume)) - usewmp = sanitize_integer(usewmp, 0, 1, initial(usewmp)) - special_popup = sanitize_integer(special_popup, 0, 1, initial(special_popup)) - usenanoui = sanitize_integer(usenanoui, 0, 1, initial(usenanoui)) - progress_bars = sanitize_integer(progress_bars, 0, 1, initial(progress_bars)) - return 1 - - -/datum/preferences/proc/load_preferences() - if(!path) return 0 - if(!fexists(path)) return 0 - var/savefile/S = new /savefile(path) - if(!S) return 0 - S.cd = "/" - - S["version"] >> savefile_version - //Conversion - if(!savefile_version || !isnum(savefile_version) || savefile_version < SAVEFILE_VERSION_MIN || savefile_version > SAVEFILE_VERSION_MAX) - if(!savefile_update()) //handles updates - savefile_version = SAVEFILE_VERSION_MAX - save_preferences() - save_character() - return 0 - - //general preferences - S["ooccolor"] >> ooccolor - S["lastchangelog"] >> lastchangelog - S["UI_style"] >> UI_style - //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 - S["warns"] >> warns - S["warnbans"] >> warnbans - S["randomslot"] >> randomslot - S["volume"] >> volume - S["special_popup"] >> special_popup - //Sanitize - ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) - lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) - UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style)) - //be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) - default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) - toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) - UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) - UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) - randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) - volume = sanitize_integer(volume, 0, 100, initial(volume)) - special_popup = sanitize_integer(special_popup, 0, 1, initial(special_popup)) - return 1 - - -/datum/preferences/proc/save_preferences_sqlite(var/user, var/ckey) - /* FUCK YOU - if(!(world.timeofday >= (lastPolled + POLLED_LIMIT))) +#define SAVEFILE_VERSION_MIN 8 +#define SAVEFILE_VERSION_MAX 11 + +//handles converting savefiles to new formats +//MAKE SURE YOU KEEP THIS UP TO DATE! +//If the sanity checks are capable of handling any issues. Only increase SAVEFILE_VERSION_MAX, +//this will mean that savefile_version will still be over SAVEFILE_VERSION_MIN, meaning +//this savefile update doesn't run everytime we load from the savefile. +//This is mainly for format changes, such as the bitflags in toggles changing order or something. +//if a file can't be updated, return 0 to delete it and start again +//if a file was updated, return 1 + +/// IF YOU NEED A FIELD ADDED TO THE DATABASE, CREATE A MIGRATION SO SHIT GETS UPDATED. +/// SEE code/modules/migrations/SS13_Prefs/ + +/datum/preferences/proc/savefile_update() + // Preseed roles. + for(var/role_id in special_roles) + roles[role_id]=0 + + if(savefile_version < 8) //lazily delete everything + additional files so they can be saved in the new format + for(var/ckey in preferences_datums) + var/datum/preferences/D = preferences_datums[ckey] + if(D == src) + var/delpath = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/" + if(delpath && fexists(delpath)) + fdel(delpath) + break + return 0 + + if(savefile_version == SAVEFILE_VERSION_MAX) //update successful. + save_preferences() + save_character() + return 1 + return 0 + + +/datum/preferences/proc/load_path(ckey,filename="preferences.sav") + if(!ckey) return + path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]" + savefile_version = SAVEFILE_VERSION_MAX + + +/datum/preferences/proc/SetChangelog(ckey,hash) + lastchangelog=hash + var/database/query/q = new + q.Add("UPDATE client SET lastchangelog=? WHERE ckey=?",lastchangelog,ckey) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + +/datum/preferences/proc/load_preferences_sqlite(var/ckey) + var/list/preference_list_client = new + var/database/query/check = new + var/database/query/q = new + check.Add("SELECT ckey FROM client WHERE ckey = ?", ckey) + if(check.Execute(db)) + if(!check.NextRow()) + return 0 + else + message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + q.Add("SELECT * FROM client WHERE ckey = ?", ckey) + if(q.Execute(db)) + while(q.NextRow()) + var/list/row = q.GetRowData() + for(var/a in row) + preference_list_client[a] = row[a] + else + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + ooccolor = preference_list_client["ooc_color"] + lastchangelog = preference_list_client["lastchangelog"] + UI_style = preference_list_client["UI_style"] + default_slot = text2num(preference_list_client["default_slot"]) + toggles = text2num(preference_list_client["toggles"]) + UI_style_color = preference_list_client["UI_style_color"] + UI_style_alpha = text2num(preference_list_client["UI_style_alpha"]) + warns = text2num(preference_list_client["warns"]) + warnbans = text2num(preference_list_client["warnsbans"]) + volume = text2num(preference_list_client["volume"]) + usewmp = text2num(preference_list_client["usewmp"]) + special_popup = text2num(preference_list_client["special"]) + randomslot = text2num(preference_list_client["randomslot"]) + usenanoui = text2num(preference_list_client["usenanoui"]) + progress_bars = text2num(preference_list_client["progress_bars"]) + + ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) + lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) + UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style)) + //be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) + default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) + toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) + UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) + UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) + randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) + volume = sanitize_integer(volume, 0, 100, initial(volume)) + usewmp = sanitize_integer(usewmp, 0, 1, initial(usewmp)) + special_popup = sanitize_integer(special_popup, 0, 1, initial(special_popup)) + usenanoui = sanitize_integer(usenanoui, 0, 1, initial(usenanoui)) + progress_bars = sanitize_integer(progress_bars, 0, 1, initial(progress_bars)) + return 1 + + +/datum/preferences/proc/load_preferences() + if(!path) return 0 + if(!fexists(path)) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = "/" + + S["version"] >> savefile_version + //Conversion + if(!savefile_version || !isnum(savefile_version) || savefile_version < SAVEFILE_VERSION_MIN || savefile_version > SAVEFILE_VERSION_MAX) + if(!savefile_update()) //handles updates + savefile_version = SAVEFILE_VERSION_MAX + save_preferences() + save_character() + return 0 + + //general preferences + S["ooccolor"] >> ooccolor + S["lastchangelog"] >> lastchangelog + S["UI_style"] >> UI_style + //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 + S["warns"] >> warns + S["warnbans"] >> warnbans + S["randomslot"] >> randomslot + S["volume"] >> volume + S["special_popup"] >> special_popup + //Sanitize + ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) + lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) + UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style)) + //be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) + default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) + toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) + UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) + UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) + randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) + volume = sanitize_integer(volume, 0, 100, initial(volume)) + special_popup = sanitize_integer(special_popup, 0, 1, initial(special_popup)) + return 1 + + +/datum/preferences/proc/save_preferences_sqlite(var/user, var/ckey) + /* FUCK YOU + if(!(world.timeofday >= (lastPolled + POLLED_LIMIT))) to_chat(user, "You need to wait [round((((lastPolled + POLLED_LIMIT) - world.timeofday) / 10))] seconds before you can save again.") - return - */ - - var/database/query/check = new - var/database/query/q = new - check.Add("SELECT ckey FROM client WHERE ckey = ?", ckey) - if(check.Execute(db)) - if(!check.NextRow()) - q.Add("INSERT into client (ckey, ooc_color, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, warns, warnbans, randomslot, volume, usewmp, special, usenanoui, progress_bars) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",\ - ckey, ooccolor, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, warns, warnbans, randomslot, volume, usewmp, special_popup, usenanoui, progress_bars) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - else - q.Add("UPDATE client SET ooc_color=?,lastchangelog=?,UI_style=?,default_slot=?,toggles=?,UI_style_color=?,UI_style_alpha=?,warns=?,warnbans=?,randomslot=?,volume=?,usewmp=?,special=?,usenanoui=?,progress_bars=? WHERE ckey = ?",\ - ooccolor, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, warns, warnbans, randomslot, volume, usewmp, special_popup, usenanoui, progress_bars, ckey) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - else - message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + return + */ + + var/database/query/check = new + var/database/query/q = new + check.Add("SELECT ckey FROM client WHERE ckey = ?", ckey) + if(check.Execute(db)) + if(!check.NextRow()) + q.Add("INSERT into client (ckey, ooc_color, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, warns, warnbans, randomslot, volume, usewmp, special, usenanoui, progress_bars) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",\ + ckey, ooccolor, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, warns, warnbans, randomslot, volume, usewmp, special_popup, usenanoui, progress_bars) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + else + q.Add("UPDATE client SET ooc_color=?,lastchangelog=?,UI_style=?,default_slot=?,toggles=?,UI_style_color=?,UI_style_alpha=?,warns=?,warnbans=?,randomslot=?,volume=?,usewmp=?,special=?,usenanoui=?,progress_bars=? WHERE ckey = ?",\ + ooccolor, lastchangelog, UI_style, default_slot, toggles, UI_style_color, UI_style_alpha, warns, warnbans, randomslot, volume, usewmp, special_popup, usenanoui, progress_bars, ckey) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + else + message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Preferences Updated.") - lastPolled = world.timeofday - return 1 - -/datum/preferences/proc/save_preferences() - if(!path) return 0 - var/savefile/S = new /savefile(path) - if(!S) return 0 - S.cd = "/" - + lastPolled = world.timeofday + return 1 + +/datum/preferences/proc/save_preferences() + if(!path) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = "/" + S["version"] << savefile_version - - //general preferences + + //general preferences S["ooccolor"] << ooccolor S["lastchangelog"] << lastchangelog S["UI_style"] << UI_style @@ -205,565 +205,565 @@ S["warnbans"] << warnbans S["randomslot"] << randomslot S["volume"] << volume - return 1 - -//saving volume changes -/datum/preferences/proc/save_volume() - if(!path) return 0 - var/savefile/S = new /savefile(path) - if(!S) return 0 - S.cd = "/" - + return 1 + +//saving volume changes +/datum/preferences/proc/save_volume() + if(!path) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = "/" + S["volume"] << volume - return 1 - -/datum/preferences/proc/load_save_sqlite(var/ckey, var/user, var/slot) - var/list/preference_list = new - var/database/query/q = new - var/database/query/check = new - - check.Add("SELECT player_ckey FROM players WHERE player_ckey = ? AND player_slot = ?", ckey, slot) - if(check.Execute(db)) - if(!check.NextRow()) + return 1 + +/datum/preferences/proc/load_save_sqlite(var/ckey, var/user, var/slot) + var/list/preference_list = new + var/database/query/q = new + var/database/query/check = new + + check.Add("SELECT player_ckey FROM players WHERE player_ckey = ? AND player_slot = ?", ckey, slot) + if(check.Execute(db)) + if(!check.NextRow()) to_chat(user, "You have no character file to load, please save one first.") - return 0 - else - message_admins("load_save_sqlite Check Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - q.Add({" -SELECT - limbs.player_ckey, - limbs.player_slot, - limbs.l_arm, - limbs.r_arm, - limbs.l_leg, - limbs.r_leg, - limbs.l_foot, - limbs.r_foot, - limbs.l_hand, - limbs.r_hand, - limbs.heart, - limbs.eyes, - limbs.lungs, - limbs.liver, - limbs.kidneys, - players.player_ckey, - players.player_slot, - players.ooc_notes, - players.real_name, - players.random_name, - players.gender, - players.age, - players.species, - players.language, - players.flavor_text, - players.med_record, - players.sec_record, - players.gen_record, - players.player_alt_titles, - players.disabilities, - players.nanotrasen_relation, - jobs.player_ckey, - jobs.player_slot, - jobs.alternate_option, - jobs.job_civilian_high, - jobs.job_civilian_med, - jobs.job_civilian_low, - jobs.job_medsci_high, - jobs.job_medsci_med, - jobs.job_medsci_low, - jobs.job_engsec_high, - jobs.job_engsec_med, - jobs.job_engsec_low, - body.player_ckey, - body.player_slot, - body.hair_red, - body.hair_green, - body.hair_blue, - body.facial_red, - body.facial_green, - body.facial_blue, - body.skin_tone, - body.hair_style_name, - body.facial_style_name, - body.eyes_red, - body.eyes_green, - body.eyes_blue, - body.underwear, - body.backbag, - body.b_type -FROM - players -INNER JOIN - limbs -ON - ( - players.player_ckey = limbs.player_ckey) -AND ( - players.player_slot = limbs.player_slot) -INNER JOIN - jobs -ON - ( - limbs.player_ckey = jobs.player_ckey) -AND ( - limbs.player_slot = jobs.player_slot) -INNER JOIN - body -ON - ( - jobs.player_ckey = body.player_ckey) -AND ( - jobs.player_slot = body.player_slot) -WHERE - players.player_ckey = ? -AND players.player_slot = ? ;"}, ckey, slot) - if(q.Execute(db)) - while(q.NextRow()) - var/list/row = q.GetRowData() - for(var/a in row) - preference_list[a] = row[a] - else - message_admins("load_save_sqlite Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - var/list/player_alt_list1 = new - var/list/player_alt_list2 = new() - player_alt_list1.Add(text2list(preference_list["player_alt_titles"], ";")) // we're getting the first part of the string for each job. - for(var/item in player_alt_list1) // iterating through the list - if(!findtext(item, ":")) - continue - var/delim_location = findtext(item, ":") // getting the second part of the string that will be handled for titles - var/job = copytext(item, 1, delim_location) // getting where the job is, it's in the first slot so we want to get that position. - var/title = copytext(item, delim_location + 1, 0) // getting where the job title is, it's in the second slot so we want to get that position. - player_alt_list2[job] = title // we assign the alt_titles here to specific job titles and hope everything works. - - metadata = preference_list["ooc_notes"] - real_name = preference_list["real_name"] - be_random_name = text2num(preference_list["random_name"]) - gender = preference_list["gender"] - age = text2num(preference_list["age"]) - species = preference_list["species"] - language = preference_list["language"] - flavor_text = preference_list["flavor_text"] - med_record = preference_list["med_record"] - sec_record = preference_list["sec_record"] - gen_record = preference_list["gen_record"] - player_alt_titles = player_alt_list2 - disabilities = text2num(preference_list["disabilities"]) - nanotrasen_relation = preference_list["nanotrasen_relation"] - - r_hair = text2num(preference_list["hair_red"]) - g_hair = text2num(preference_list["hair_green"]) - b_hair = text2num(preference_list["hair_blue"]) - h_style = preference_list["hair_style_name"] - - r_facial = text2num(preference_list["facial_red"]) - g_facial = text2num(preference_list["facial_green"]) - b_facial = text2num(preference_list["facial_blue"]) - f_style = preference_list["facial_style_name"] - - r_eyes = text2num(preference_list["eyes_red"]) - g_eyes = text2num(preference_list["eyes_green"]) - b_eyes = text2num(preference_list["eyes_blue"]) - - s_tone = text2num(preference_list["skin_tone"]) - - underwear = text2num(preference_list["underwear"]) - backbag = text2num(preference_list["backbag"]) - b_type = preference_list["b_type"] - - organ_data["l_arm"] = preference_list["l_arm"] - organ_data["r_arm"] = preference_list["r_arm"] - organ_data["l_leg"] = preference_list["l_leg"] - organ_data["r_leg"] = preference_list["r_leg"] - organ_data["l_foot"]= preference_list["l_foot"] - organ_data["r_foot"]= preference_list["r_foot"] - organ_data["l_hand"]= preference_list["l_hand"] - organ_data["r_hand"]= preference_list["r_hand"] - organ_data["heart"] = preference_list["heart"] - organ_data["eyes"] = preference_list["eyes"] - organ_data["lungs"] = preference_list["lungs"] - organ_data["kidneys"]=preference_list["kidneys"] - organ_data["liver"] = preference_list["liver"] - - alternate_option = text2num(preference_list["alternate_option"]) - job_civilian_high = text2num(preference_list["job_civilian_high"]) - job_civilian_med = text2num(preference_list["job_civilian_med"]) - job_civilian_low = text2num(preference_list["job_civilian_low"]) - job_medsci_high = text2num(preference_list["job_medsci_high"]) - job_medsci_med = text2num(preference_list["job_medsci_med"]) - job_medsci_low = text2num(preference_list["job_medsci_low"]) - job_engsec_high = text2num(preference_list["job_engsec_high"]) - job_engsec_med = text2num(preference_list["job_engsec_med"]) - job_engsec_low = text2num(preference_list["job_engsec_low"]) - - - metadata = sanitize_text(metadata, initial(metadata)) - real_name = reject_bad_name(real_name) - - if(isnull(species)) species = "Human" - if(isnull(language)) language = "None" - if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation) - if(!real_name) real_name = random_name(gender,species) - be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) - gender = sanitize_gender(gender) - age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) - - r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair)) - g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair)) - b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair)) - - r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial)) - 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)) - 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)) - backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) - b_type = sanitize_text(b_type, initial(b_type)) - //be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) - - alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option)) - job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high)) - job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med)) - job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_low)) - job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high)) - job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med)) - job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low)) - job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high)) - job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med)) - job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low)) - - q = new - q.Add("SELECT role, preference FROM client_roles WHERE ckey=? AND slot=?", ckey, slot) - if(q.Execute(db)) - while(q.NextRow()) - var/list/row = q.GetRowData() - roles[row["role"]] = text2num(row["preference"]) | ROLEPREF_PERSIST - else - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - if(!skills) skills = list() - if(!used_skillpoints) used_skillpoints= 0 - if(isnull(disabilities)) disabilities = 0 - if(!player_alt_titles) player_alt_titles = new() - if(!organ_data) src.organ_data = list() - + return 0 + else + message_admins("load_save_sqlite Check Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + q.Add({" +SELECT + limbs.player_ckey, + limbs.player_slot, + limbs.l_arm, + limbs.r_arm, + limbs.l_leg, + limbs.r_leg, + limbs.l_foot, + limbs.r_foot, + limbs.l_hand, + limbs.r_hand, + limbs.heart, + limbs.eyes, + limbs.lungs, + limbs.liver, + limbs.kidneys, + players.player_ckey, + players.player_slot, + players.ooc_notes, + players.real_name, + players.random_name, + players.gender, + players.age, + players.species, + players.language, + players.flavor_text, + players.med_record, + players.sec_record, + players.gen_record, + players.player_alt_titles, + players.disabilities, + players.nanotrasen_relation, + jobs.player_ckey, + jobs.player_slot, + jobs.alternate_option, + jobs.job_civilian_high, + jobs.job_civilian_med, + jobs.job_civilian_low, + jobs.job_medsci_high, + jobs.job_medsci_med, + jobs.job_medsci_low, + jobs.job_engsec_high, + jobs.job_engsec_med, + jobs.job_engsec_low, + body.player_ckey, + body.player_slot, + body.hair_red, + body.hair_green, + body.hair_blue, + body.facial_red, + body.facial_green, + body.facial_blue, + body.skin_tone, + body.hair_style_name, + body.facial_style_name, + body.eyes_red, + body.eyes_green, + body.eyes_blue, + body.underwear, + body.backbag, + body.b_type +FROM + players +INNER JOIN + limbs +ON + ( + players.player_ckey = limbs.player_ckey) +AND ( + players.player_slot = limbs.player_slot) +INNER JOIN + jobs +ON + ( + limbs.player_ckey = jobs.player_ckey) +AND ( + limbs.player_slot = jobs.player_slot) +INNER JOIN + body +ON + ( + jobs.player_ckey = body.player_ckey) +AND ( + jobs.player_slot = body.player_slot) +WHERE + players.player_ckey = ? +AND players.player_slot = ? ;"}, ckey, slot) + if(q.Execute(db)) + while(q.NextRow()) + var/list/row = q.GetRowData() + for(var/a in row) + preference_list[a] = row[a] + else + message_admins("load_save_sqlite Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + var/list/player_alt_list1 = new + var/list/player_alt_list2 = new() + player_alt_list1.Add(text2list(preference_list["player_alt_titles"], ";")) // we're getting the first part of the string for each job. + for(var/item in player_alt_list1) // iterating through the list + if(!findtext(item, ":")) + continue + var/delim_location = findtext(item, ":") // getting the second part of the string that will be handled for titles + var/job = copytext(item, 1, delim_location) // getting where the job is, it's in the first slot so we want to get that position. + var/title = copytext(item, delim_location + 1, 0) // getting where the job title is, it's in the second slot so we want to get that position. + player_alt_list2[job] = title // we assign the alt_titles here to specific job titles and hope everything works. + + metadata = preference_list["ooc_notes"] + real_name = preference_list["real_name"] + be_random_name = text2num(preference_list["random_name"]) + gender = preference_list["gender"] + age = text2num(preference_list["age"]) + species = preference_list["species"] + language = preference_list["language"] + flavor_text = preference_list["flavor_text"] + med_record = preference_list["med_record"] + sec_record = preference_list["sec_record"] + gen_record = preference_list["gen_record"] + player_alt_titles = player_alt_list2 + disabilities = text2num(preference_list["disabilities"]) + nanotrasen_relation = preference_list["nanotrasen_relation"] + + r_hair = text2num(preference_list["hair_red"]) + g_hair = text2num(preference_list["hair_green"]) + b_hair = text2num(preference_list["hair_blue"]) + h_style = preference_list["hair_style_name"] + + r_facial = text2num(preference_list["facial_red"]) + g_facial = text2num(preference_list["facial_green"]) + b_facial = text2num(preference_list["facial_blue"]) + f_style = preference_list["facial_style_name"] + + r_eyes = text2num(preference_list["eyes_red"]) + g_eyes = text2num(preference_list["eyes_green"]) + b_eyes = text2num(preference_list["eyes_blue"]) + + s_tone = text2num(preference_list["skin_tone"]) + + underwear = text2num(preference_list["underwear"]) + backbag = text2num(preference_list["backbag"]) + b_type = preference_list["b_type"] + + organ_data["l_arm"] = preference_list["l_arm"] + organ_data["r_arm"] = preference_list["r_arm"] + organ_data["l_leg"] = preference_list["l_leg"] + organ_data["r_leg"] = preference_list["r_leg"] + organ_data["l_foot"]= preference_list["l_foot"] + organ_data["r_foot"]= preference_list["r_foot"] + organ_data["l_hand"]= preference_list["l_hand"] + organ_data["r_hand"]= preference_list["r_hand"] + organ_data["heart"] = preference_list["heart"] + organ_data["eyes"] = preference_list["eyes"] + organ_data["lungs"] = preference_list["lungs"] + organ_data["kidneys"]=preference_list["kidneys"] + organ_data["liver"] = preference_list["liver"] + + alternate_option = text2num(preference_list["alternate_option"]) + job_civilian_high = text2num(preference_list["job_civilian_high"]) + job_civilian_med = text2num(preference_list["job_civilian_med"]) + job_civilian_low = text2num(preference_list["job_civilian_low"]) + job_medsci_high = text2num(preference_list["job_medsci_high"]) + job_medsci_med = text2num(preference_list["job_medsci_med"]) + job_medsci_low = text2num(preference_list["job_medsci_low"]) + job_engsec_high = text2num(preference_list["job_engsec_high"]) + job_engsec_med = text2num(preference_list["job_engsec_med"]) + job_engsec_low = text2num(preference_list["job_engsec_low"]) + + + metadata = sanitize_text(metadata, initial(metadata)) + real_name = reject_bad_name(real_name) + + if(isnull(species)) species = "Human" + if(isnull(language)) language = "None" + if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation) + if(!real_name) real_name = random_name(gender,species) + be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) + gender = sanitize_gender(gender) + age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) + + r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair)) + g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair)) + b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair)) + + r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial)) + 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)) + 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)) + backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) + b_type = sanitize_text(b_type, initial(b_type)) + //be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) + + alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option)) + job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high)) + job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med)) + job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_low)) + job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high)) + job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med)) + job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low)) + job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high)) + job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med)) + job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low)) + + q = new + q.Add("SELECT role, preference FROM client_roles WHERE ckey=? AND slot=?", ckey, slot) + if(q.Execute(db)) + while(q.NextRow()) + var/list/row = q.GetRowData() + roles[row["role"]] = text2num(row["preference"]) | ROLEPREF_PERSIST + else + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + if(!skills) skills = list() + if(!used_skillpoints) used_skillpoints= 0 + if(isnull(disabilities)) disabilities = 0 + if(!player_alt_titles) player_alt_titles = new() + if(!organ_data) src.organ_data = list() + to_chat(user, "Sucessfully loaded [real_name].") - - return 1 - - -/datum/preferences/proc/load_save(dir) - var/savefile/S = new /savefile(path) - if(!S) return 0 - S.cd = dir - - //Character - S["OOC_Notes"] >> metadata - S["real_name"] >> real_name - S["name_is_always_random"] >> be_random_name - S["gender"] >> gender - S["age"] >> age - S["species"] >> species - S["language"] >> language - - //colors to be consolidated into hex strings (requires some work with dna code) - S["hair_red"] >> r_hair - S["hair_green"] >> g_hair - S["hair_blue"] >> b_hair - S["facial_red"] >> r_facial - S["facial_green"] >> g_facial - S["facial_blue"] >> b_facial - S["skin_tone"] >> s_tone - 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["backbag"] >> backbag - S["b_type"] >> b_type - - //Jobs - S["alternate_option"] >> alternate_option - S["job_civilian_high"] >> job_civilian_high - S["job_civilian_med"] >> job_civilian_med - S["job_civilian_low"] >> job_civilian_low - S["job_medsci_high"] >> job_medsci_high - S["job_medsci_med"] >> job_medsci_med - S["job_medsci_low"] >> job_medsci_low - S["job_engsec_high"] >> job_engsec_high - S["job_engsec_med"] >> job_engsec_med - S["job_engsec_low"] >> job_engsec_low - - //Miscellaneous - S["flavor_text"] >> flavor_text - S["med_record"] >> med_record - S["sec_record"] >> sec_record - S["gen_record"] >> gen_record - //S["be_special"] >> be_special - S["disabilities"] >> disabilities - S["player_alt_titles"] >> player_alt_titles - S["used_skillpoints"] >> used_skillpoints - S["skills"] >> skills - S["skill_specialization"] >> skill_specialization - S["organ_data"] >> organ_data - - S["nanotrasen_relation"] >> nanotrasen_relation - //S["skin_style"] >> skin_style - - //Sanitize - metadata = sanitize_text(metadata, initial(metadata)) - real_name = reject_bad_name(real_name) - if(isnull(species)) species = "Human" - if(isnull(language)) language = "None" - if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation) - if(!real_name) real_name = random_name(gender,species) - be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) - gender = sanitize_gender(gender) - age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) - r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair)) - g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair)) - b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair)) - r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial)) - 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)) - 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)) - backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) - b_type = sanitize_text(b_type, initial(b_type)) - - alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option)) - job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high)) - job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med)) - job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_low)) - job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high)) - job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med)) - job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low)) - job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high)) - job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med)) - job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low)) - - if(!skills) skills = list() - if(!used_skillpoints) used_skillpoints= 0 - if(isnull(disabilities)) disabilities = 0 - if(!player_alt_titles) player_alt_titles = new() - if(!organ_data) src.organ_data = list() - //if(!skin_style) skin_style = "Default" - - -/datum/preferences/proc/random_character_sqlite(var/user, var/ckey) - var/database/query/q = new - var/list/slot_list = new - q.Add("SELECT player_slot FROM players WHERE player_ckey=?", ckey) - if(q.Execute(db)) - while(q.NextRow()) - slot_list.Add(q.GetColumn(1)) - else - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - var/random_slot = pick(slot_list) - load_save_sqlite(ckey, user, random_slot) - return 1 - -/datum/preferences/proc/random_character() - if(!path) return 0 - if(!fexists(path)) return 0 - var/savefile/S = new /savefile(path) - if(!S) return 0 - var/list/saves = list() - var/name - for(var/i=1, i<=MAX_SAVE_SLOTS, i++) - S.cd = "/character[i]" - S["real_name"] >> name - if(!name) continue - saves.Add(S.cd) - - if(!saves.len) - load_character() - return 0 - S.cd = pick(saves) - load_save(S.cd) - return 1 - -/datum/preferences/proc/load_character(slot) - if(!path) return 0 - if(!fexists(path)) return 0 - var/savefile/S = new /savefile(path) - if(!S) return 0 - S.cd = "/" - if(!slot) slot = default_slot - slot = sanitize_integer(slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) - if(slot != default_slot) - default_slot = slot + + return 1 + + +/datum/preferences/proc/load_save(dir) + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = dir + + //Character + S["OOC_Notes"] >> metadata + S["real_name"] >> real_name + S["name_is_always_random"] >> be_random_name + S["gender"] >> gender + S["age"] >> age + S["species"] >> species + S["language"] >> language + + //colors to be consolidated into hex strings (requires some work with dna code) + S["hair_red"] >> r_hair + S["hair_green"] >> g_hair + S["hair_blue"] >> b_hair + S["facial_red"] >> r_facial + S["facial_green"] >> g_facial + S["facial_blue"] >> b_facial + S["skin_tone"] >> s_tone + 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["backbag"] >> backbag + S["b_type"] >> b_type + + //Jobs + S["alternate_option"] >> alternate_option + S["job_civilian_high"] >> job_civilian_high + S["job_civilian_med"] >> job_civilian_med + S["job_civilian_low"] >> job_civilian_low + S["job_medsci_high"] >> job_medsci_high + S["job_medsci_med"] >> job_medsci_med + S["job_medsci_low"] >> job_medsci_low + S["job_engsec_high"] >> job_engsec_high + S["job_engsec_med"] >> job_engsec_med + S["job_engsec_low"] >> job_engsec_low + + //Miscellaneous + S["flavor_text"] >> flavor_text + S["med_record"] >> med_record + S["sec_record"] >> sec_record + S["gen_record"] >> gen_record + //S["be_special"] >> be_special + S["disabilities"] >> disabilities + S["player_alt_titles"] >> player_alt_titles + S["used_skillpoints"] >> used_skillpoints + S["skills"] >> skills + S["skill_specialization"] >> skill_specialization + S["organ_data"] >> organ_data + + S["nanotrasen_relation"] >> nanotrasen_relation + //S["skin_style"] >> skin_style + + //Sanitize + metadata = sanitize_text(metadata, initial(metadata)) + real_name = reject_bad_name(real_name) + if(isnull(species)) species = "Human" + if(isnull(language)) language = "None" + if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation) + if(!real_name) real_name = random_name(gender,species) + be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) + gender = sanitize_gender(gender) + age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) + r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair)) + g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair)) + b_hair = sanitize_integer(b_hair, 0, 255, initial(b_hair)) + r_facial = sanitize_integer(r_facial, 0, 255, initial(r_facial)) + 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)) + 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)) + backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) + b_type = sanitize_text(b_type, initial(b_type)) + + alternate_option = sanitize_integer(alternate_option, 0, 2, initial(alternate_option)) + job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high)) + job_civilian_med = sanitize_integer(job_civilian_med, 0, 65535, initial(job_civilian_med)) + job_civilian_low = sanitize_integer(job_civilian_low, 0, 65535, initial(job_civilian_low)) + job_medsci_high = sanitize_integer(job_medsci_high, 0, 65535, initial(job_medsci_high)) + job_medsci_med = sanitize_integer(job_medsci_med, 0, 65535, initial(job_medsci_med)) + job_medsci_low = sanitize_integer(job_medsci_low, 0, 65535, initial(job_medsci_low)) + job_engsec_high = sanitize_integer(job_engsec_high, 0, 65535, initial(job_engsec_high)) + job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med)) + job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low)) + + if(!skills) skills = list() + if(!used_skillpoints) used_skillpoints= 0 + if(isnull(disabilities)) disabilities = 0 + if(!player_alt_titles) player_alt_titles = new() + if(!organ_data) src.organ_data = list() + //if(!skin_style) skin_style = "Default" + + +/datum/preferences/proc/random_character_sqlite(var/user, var/ckey) + var/database/query/q = new + var/list/slot_list = new + q.Add("SELECT player_slot FROM players WHERE player_ckey=?", ckey) + if(q.Execute(db)) + while(q.NextRow()) + slot_list.Add(q.GetColumn(1)) + else + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + var/random_slot = pick(slot_list) + load_save_sqlite(ckey, user, random_slot) + return 1 + +/datum/preferences/proc/random_character() + if(!path) return 0 + if(!fexists(path)) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + var/list/saves = list() + var/name + for(var/i=1, i<=MAX_SAVE_SLOTS, i++) + S.cd = "/character[i]" + S["real_name"] >> name + if(!name) continue + saves.Add(S.cd) + + if(!saves.len) + load_character() + return 0 + S.cd = pick(saves) + load_save(S.cd) + return 1 + +/datum/preferences/proc/load_character(slot) + if(!path) return 0 + if(!fexists(path)) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = "/" + if(!slot) slot = default_slot + slot = sanitize_integer(slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) + if(slot != default_slot) + default_slot = slot S["default_slot"] << slot - S.cd = "/character[slot]" - load_save(S.cd) - return 1 - -/datum/preferences/proc/save_character_sqlite(var/ckey, var/user, var/slot) - - - if(slot > MAX_SAVE_SLOTS) + S.cd = "/character[slot]" + load_save(S.cd) + return 1 + +/datum/preferences/proc/save_character_sqlite(var/ckey, var/user, var/slot) + + + if(slot > MAX_SAVE_SLOTS) to_chat(user, "You are limited to 8 character slots.") - message_admins("[ckey] attempted to override character slot limit") - return 0 - - var/database/query/q = new - var/database/query/check = new - - var/altTitles - - for(var/a in player_alt_titles) - altTitles += "[a]:[player_alt_titles[a]];" - - check.Add("SELECT player_ckey FROM players WHERE player_ckey = ? AND player_slot = ?", ckey, slot) - if(check.Execute(db)) - if(!check.NextRow()) //1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - q.Add("INSERT INTO players (player_ckey,player_slot,ooc_notes,real_name,random_name,gender,age,species,language,flavor_text,med_record,sec_record,gen_record,player_alt_titles,disabilities,nanotrasen_relation) \ - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", - ckey, slot, metadata, real_name, be_random_name, gender, age, species, language, flavor_text, med_record, sec_record, gen_record, altTitles, disabilities, nanotrasen_relation) - if(!q.Execute(db)) - message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + message_admins("[ckey] attempted to override character slot limit") + return 0 + + var/database/query/q = new + var/database/query/check = new + + var/altTitles + + for(var/a in player_alt_titles) + altTitles += "[a]:[player_alt_titles[a]];" + + check.Add("SELECT player_ckey FROM players WHERE player_ckey = ? AND player_slot = ?", ckey, slot) + if(check.Execute(db)) + if(!check.NextRow()) //1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + q.Add("INSERT INTO players (player_ckey,player_slot,ooc_notes,real_name,random_name,gender,age,species,language,flavor_text,med_record,sec_record,gen_record,player_alt_titles,disabilities,nanotrasen_relation) \ + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + ckey, slot, metadata, real_name, be_random_name, gender, age, species, language, flavor_text, med_record, sec_record, gen_record, altTitles, disabilities, nanotrasen_relation) + if(!q.Execute(db)) + message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Created Character") - else - q.Add("UPDATE players SET ooc_notes=?,real_name=?,random_name=?,gender=?,age=?,species=?,language=?,flavor_text=?,med_record=?,sec_record=?,gen_record=?,player_alt_titles=?,disabilities=?,nanotrasen_relation=? WHERE player_ckey = ? AND player_slot = ?",\ - metadata, real_name, be_random_name, gender, age, species, language, flavor_text, med_record, sec_record, gen_record, altTitles, disabilities, nanotrasen_relation, ckey, slot) - if(!q.Execute(db)) - message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + q.Add("UPDATE players SET ooc_notes=?,real_name=?,random_name=?,gender=?,age=?,species=?,language=?,flavor_text=?,med_record=?,sec_record=?,gen_record=?,player_alt_titles=?,disabilities=?,nanotrasen_relation=? WHERE player_ckey = ? AND player_slot = ?",\ + metadata, real_name, be_random_name, gender, age, species, language, flavor_text, med_record, sec_record, gen_record, altTitles, disabilities, nanotrasen_relation, ckey, slot) + if(!q.Execute(db)) + message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Updated Character") - else - message_admins("Error #:[check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - check.Add("SELECT player_ckey FROM body WHERE player_ckey = ? AND player_slot = ?", ckey, slot) - if(check.Execute(db)) - if(!check.NextRow()) - q.Add("INSERT INTO body (player_ckey,player_slot,hair_red,hair_green,hair_blue,facial_red,facial_green,facial_blue,skin_tone,hair_style_name,facial_style_name,eyes_red,eyes_green,eyes_blue,underwear,backbag,b_type) \ - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ckey, slot, r_hair, g_hair, b_hair, r_facial, g_facial, b_facial, s_tone, h_style, f_style, r_eyes, g_eyes, b_eyes, underwear, backbag, b_type) - if(!q.Execute(db)) - message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + message_admins("Error #:[check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + check.Add("SELECT player_ckey FROM body WHERE player_ckey = ? AND player_slot = ?", ckey, slot) + if(check.Execute(db)) + if(!check.NextRow()) + q.Add("INSERT INTO body (player_ckey,player_slot,hair_red,hair_green,hair_blue,facial_red,facial_green,facial_blue,skin_tone,hair_style_name,facial_style_name,eyes_red,eyes_green,eyes_blue,underwear,backbag,b_type) \ + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ckey, slot, r_hair, g_hair, b_hair, r_facial, g_facial, b_facial, s_tone, h_style, f_style, r_eyes, g_eyes, b_eyes, underwear, backbag, b_type) + if(!q.Execute(db)) + message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Created Body") - else - q.Add("UPDATE body SET hair_red=?,hair_green=?,hair_blue=?,facial_red=?,facial_green=?,facial_blue=?,skin_tone=?,hair_style_name=?,facial_style_name=?,eyes_red=?,eyes_green=?,eyes_blue=?,underwear=?,backbag=?,b_type=? WHERE player_ckey = ? AND player_slot = ?",\ - r_hair, g_hair, b_hair, r_facial, g_facial, b_facial, s_tone, h_style, f_style, r_eyes, g_eyes, b_eyes, underwear, backbag, b_type, ckey, slot) - if(!q.Execute(db)) - message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + q.Add("UPDATE body SET hair_red=?,hair_green=?,hair_blue=?,facial_red=?,facial_green=?,facial_blue=?,skin_tone=?,hair_style_name=?,facial_style_name=?,eyes_red=?,eyes_green=?,eyes_blue=?,underwear=?,backbag=?,b_type=? WHERE player_ckey = ? AND player_slot = ?",\ + r_hair, g_hair, b_hair, r_facial, g_facial, b_facial, s_tone, h_style, f_style, r_eyes, g_eyes, b_eyes, underwear, backbag, b_type, ckey, slot) + if(!q.Execute(db)) + message_admins("Error #:[q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Updated Body") - else - message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - check.Add("SELECT player_ckey FROM jobs WHERE player_ckey = ? AND player_slot = ?", ckey, slot) - if(check.Execute(db)) - if(!check.NextRow()) - q.Add("INSERT INTO jobs (player_ckey,player_slot,alternate_option,job_civilian_high,job_civilian_med,job_civilian_low,job_medsci_high,job_medsci_med,job_medsci_low,job_engsec_high,job_engsec_med,job_engsec_low) \ - VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", ckey, slot, alternate_option, job_civilian_high, job_civilian_med, job_civilian_low, job_medsci_high, job_medsci_med, job_medsci_low, job_engsec_high, job_engsec_med, job_engsec_low) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + check.Add("SELECT player_ckey FROM jobs WHERE player_ckey = ? AND player_slot = ?", ckey, slot) + if(check.Execute(db)) + if(!check.NextRow()) + q.Add("INSERT INTO jobs (player_ckey,player_slot,alternate_option,job_civilian_high,job_civilian_med,job_civilian_low,job_medsci_high,job_medsci_med,job_medsci_low,job_engsec_high,job_engsec_med,job_engsec_low) \ + VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", ckey, slot, alternate_option, job_civilian_high, job_civilian_med, job_civilian_low, job_medsci_high, job_medsci_med, job_medsci_low, job_engsec_high, job_engsec_med, job_engsec_low) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Created Job list") - else - q.Add("UPDATE jobs SET alternate_option=?,job_civilian_high=?,job_civilian_med=?,job_civilian_low=?,job_medsci_high=?,job_medsci_med=?,job_medsci_low=?,job_engsec_high=?,job_engsec_med=?,job_engsec_low=? WHERE player_ckey = ? AND player_slot = ?",\ - alternate_option, job_civilian_high, job_civilian_med, job_civilian_low, job_medsci_high, job_medsci_med, job_medsci_low, job_engsec_high, job_engsec_med, job_engsec_low, ckey, slot) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + q.Add("UPDATE jobs SET alternate_option=?,job_civilian_high=?,job_civilian_med=?,job_civilian_low=?,job_medsci_high=?,job_medsci_med=?,job_medsci_low=?,job_engsec_high=?,job_engsec_med=?,job_engsec_low=? WHERE player_ckey = ? AND player_slot = ?",\ + alternate_option, job_civilian_high, job_civilian_med, job_civilian_low, job_medsci_high, job_medsci_med, job_medsci_low, job_engsec_high, job_engsec_med, job_engsec_low, ckey, slot) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Updated Job List") - else - message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - check.Add("SELECT player_ckey FROM limbs WHERE player_ckey = ? AND player_slot = ?", ckey, slot) - if(check.Execute(db)) - if(!check.NextRow()) - q.Add("INSERT INTO limbs (player_ckey, player_slot) VALUES (?,?)", ckey, slot) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - for(var/stuff in organ_data) - q.Add("UPDATE limbs SET [stuff]=? WHERE player_ckey = ? AND player_slot = ?", organ_data[stuff], ckey, slot) - if(!q.Execute(db)) - message_admins("Error #; [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + check.Add("SELECT player_ckey FROM limbs WHERE player_ckey = ? AND player_slot = ?", ckey, slot) + if(check.Execute(db)) + if(!check.NextRow()) + q.Add("INSERT INTO limbs (player_ckey, player_slot) VALUES (?,?)", ckey, slot) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + for(var/stuff in organ_data) + q.Add("UPDATE limbs SET [stuff]=? WHERE player_ckey = ? AND player_slot = ?", organ_data[stuff], ckey, slot) + if(!q.Execute(db)) + message_admins("Error #; [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Created Limbs") - else - for(var/stuff in organ_data) - q.Add("UPDATE limbs SET [stuff] = ? WHERE player_ckey = ? AND player_slot = ?", organ_data[stuff], ckey, slot) - if(!q.Execute(db)) - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 + else + for(var/stuff in organ_data) + q.Add("UPDATE limbs SET [stuff] = ? WHERE player_ckey = ? AND player_slot = ?", organ_data[stuff], ckey, slot) + if(!q.Execute(db)) + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 to_chat(user, "Updated Limbs") - else - message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - check.Add("DELETE FROM client_roles WHERE ckey=? AND slot=?", ckey, slot) - if(!check.Execute(db)) - message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - for(var/role_id in roles) - if(!(roles[role_id] & ROLEPREF_PERSIST)) - continue - q = new - q.Add("INSERT INTO client_roles (ckey, slot, role, preference) VALUES (?,?,?,?)", ckey, slot, role_id, (roles[role_id] & ROLEPREF_SAVEMASK)) - //testing("INSERT INTO client_roles (ckey, slot, role, preference) VALUES ('[ckey]',[slot],'[role_id]',[roles[role_id] & ROLEPREF_SAVEMASK])") - if(!q.Execute(db)) // This never triggers on error, for some reason. - message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") - warning("Error #:[q.Error()] - [q.ErrorMsg()]") - return 0 - - return 1 - - -/datum/preferences/proc/save_character() - - - if(!path) return 0 - var/savefile/S = new /savefile(path) - if(!S) return 0 - S.cd = "/character[default_slot]" - - //Character + misc + else + message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + check.Add("DELETE FROM client_roles WHERE ckey=? AND slot=?", ckey, slot) + if(!check.Execute(db)) + message_admins("Error #: [check.Error()] - [check.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + for(var/role_id in roles) + if(!(roles[role_id] & ROLEPREF_PERSIST)) + continue + q = new + q.Add("INSERT INTO client_roles (ckey, slot, role, preference) VALUES (?,?,?,?)", ckey, slot, role_id, (roles[role_id] & ROLEPREF_SAVEMASK)) + //testing("INSERT INTO client_roles (ckey, slot, role, preference) VALUES ('[ckey]',[slot],'[role_id]',[roles[role_id] & ROLEPREF_SAVEMASK])") + if(!q.Execute(db)) // This never triggers on error, for some reason. + message_admins("Error #: [q.Error()] - [q.ErrorMsg()]") + warning("Error #:[q.Error()] - [q.ErrorMsg()]") + return 0 + + return 1 + + +/datum/preferences/proc/save_character() + + + if(!path) return 0 + var/savefile/S = new /savefile(path) + if(!S) return 0 + S.cd = "/character[default_slot]" + + //Character + misc S["OOC_Notes"] << metadata S["real_name"] << real_name S["name_is_always_random"] << be_random_name @@ -783,7 +783,7 @@ AND players.player_slot = ? ;"}, ckey, slot) S["skill_specialization"] << skill_specialization S["organ_data"] << organ_data S["nanotrasen_relation"] << nanotrasen_relation - //Body + //Body S["hair_red"] << r_hair S["hair_green"] << g_hair S["hair_blue"] << b_hair @@ -799,8 +799,8 @@ AND players.player_slot = ? ;"}, ckey, slot) S["underwear"] << underwear S["backbag"] << backbag S["b_type"] << b_type - - //Jobs + + //Jobs S["alternate_option"] << alternate_option S["job_civilian_high"] << job_civilian_high S["job_civilian_med"] << job_civilian_med @@ -812,9 +812,9 @@ AND players.player_slot = ? ;"}, ckey, slot) S["job_engsec_med"] << job_engsec_med S["job_engsec_low"] << job_engsec_low // S["skin_style"] << skin_style - - return 1 - - -#undef SAVEFILE_VERSION_MAX -#undef SAVEFILE_VERSION_MIN + + return 1 + + +#undef SAVEFILE_VERSION_MAX +#undef SAVEFILE_VERSION_MIN diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 4b10c525dd0..a4268795240 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -1,246 +1,246 @@ -//toggles -/client/verb/toggle_ghost_ears() - set name = "Show/Hide GhostEars" - set category = "Preferences" - set desc = "Toggle Between seeing all mob speech, and only speech of nearby mobs" - prefs.toggles ^= CHAT_GHOSTEARS +//toggles +/client/verb/toggle_ghost_ears() + set name = "Show/Hide GhostEars" + set category = "Preferences" + set desc = "Toggle Between seeing all mob speech, and only speech of nearby mobs" + prefs.toggles ^= CHAT_GHOSTEARS to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].") - prefs.save_preferences_sqlite(src, ckey) - feedback_add_details("admin_verb","TGE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_ghost_sight() - set name = "Show/Hide GhostSight" - set category = "Preferences" - set desc = "Toggle Between seeing all mob emotes, and only emotes of nearby mobs" - prefs.toggles ^= CHAT_GHOSTSIGHT - to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].") - prefs.save_preferences_sqlite(src, ckey) - feedback_add_details("admin_verb","TGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_ghost_radio() - set name = "Enable/Disable GhostRadio" - set category = "Preferences" - set desc = "Toggle between hearing all radio chatter, or only from nearby speakers" - prefs.toggles ^= CHAT_GHOSTRADIO - to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].") - prefs.save_preferences_sqlite(src, ckey) - feedback_add_details("admin_verb","TGR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_ghost_pda() - set name = "Enable/Disable GhostPDA" - set category = "Preferences" - set desc = "Toggle between hearing all PDA messages, or none" - prefs.toggles ^= CHAT_GHOSTPDA - to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTPDA) ? "hear all PDA messages in the world" : "hear no PDA messages at all"].") - prefs.save_preferences_sqlite(src, ckey) - feedback_add_details("admin_verb","TGP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/toggle_hear_radio() - set name = "Show/Hide RadioChatter" - set category = "Preferences" - set desc = "Toggle seeing radiochatter from radios and speakers" - - if(!holder) return - prefs.toggles ^= CHAT_RADIO - prefs.save_preferences_sqlite(src, ckey) - to_chat(usr, "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers") - feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/toggleadminhelpsound() - set name = "Hear/Silence Adminhelps" - set category = "Preferences" - set desc = "Toggle hearing a notification when admin PMs are recieved" - - if(!holder) return - prefs.toggles ^= SOUND_ADMINHELP - prefs.save_preferences_sqlite(src, ckey) - to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.") - feedback_add_details("admin_verb","AHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/deadchat() // Deadchat toggle is usable by anyone. - set name = "Show/Hide Deadchat" - set category = "Preferences" - set desc ="Toggles seeing deadchat" - prefs.toggles ^= CHAT_DEAD - prefs.save_preferences_sqlite(src, ckey) - - if(src.holder) - to_chat(src, "You will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") - else - to_chat(src, "As a ghost, you will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") - - feedback_add_details("admin_verb","TDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/toggleprayers() - set name = "Show/Hide Prayers" - set category = "Preferences" - set desc = "Toggles seeing prayers" - - prefs.toggles ^= CHAT_PRAYER - prefs.save_preferences_sqlite(src, ckey) - to_chat(src, "You will [(prefs.toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.") - feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggletitlemusic() - set name = "Hear/Silence LobbyMusic" - set category = "Preferences" - set desc = "Toggles hearing the GameLobby music" - prefs.toggles ^= SOUND_LOBBY - prefs.save_preferences_sqlite(src, ckey) - if(prefs.toggles & SOUND_LOBBY) - to_chat(src, "You will now hear music in the game lobby.") - if(istype(mob, /mob/new_player)) - playtitlemusic() - else - to_chat(src, "You will no longer hear music in the game lobby.") - if(istype(mob, /mob/new_player)) - to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// stop the jamsz + prefs.save_preferences_sqlite(src, ckey) + feedback_add_details("admin_verb","TGE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - feedback_add_details("admin_verb","TLobby") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/togglemidis() - set name = "Hear/Silence Midis" - set category = "Preferences" - set desc = "Toggles hearing sounds uploaded by admins" - prefs.toggles ^= SOUND_MIDI - prefs.save_preferences_sqlite(src, ckey) - if(prefs.toggles & SOUND_MIDI) +/client/verb/toggle_ghost_sight() + set name = "Show/Hide GhostSight" + set category = "Preferences" + set desc = "Toggle Between seeing all mob emotes, and only emotes of nearby mobs" + prefs.toggles ^= CHAT_GHOSTSIGHT + to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].") + prefs.save_preferences_sqlite(src, ckey) + feedback_add_details("admin_verb","TGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/toggle_ghost_radio() + set name = "Enable/Disable GhostRadio" + set category = "Preferences" + set desc = "Toggle between hearing all radio chatter, or only from nearby speakers" + prefs.toggles ^= CHAT_GHOSTRADIO + to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].") + prefs.save_preferences_sqlite(src, ckey) + feedback_add_details("admin_verb","TGR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/toggle_ghost_pda() + set name = "Enable/Disable GhostPDA" + set category = "Preferences" + set desc = "Toggle between hearing all PDA messages, or none" + prefs.toggles ^= CHAT_GHOSTPDA + to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTPDA) ? "hear all PDA messages in the world" : "hear no PDA messages at all"].") + prefs.save_preferences_sqlite(src, ckey) + feedback_add_details("admin_verb","TGP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/toggle_hear_radio() + set name = "Show/Hide RadioChatter" + set category = "Preferences" + set desc = "Toggle seeing radiochatter from radios and speakers" + + if(!holder) return + prefs.toggles ^= CHAT_RADIO + prefs.save_preferences_sqlite(src, ckey) + to_chat(usr, "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers") + feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/toggleadminhelpsound() + set name = "Hear/Silence Adminhelps" + set category = "Preferences" + set desc = "Toggle hearing a notification when admin PMs are recieved" + + if(!holder) return + prefs.toggles ^= SOUND_ADMINHELP + prefs.save_preferences_sqlite(src, ckey) + to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.") + feedback_add_details("admin_verb","AHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/deadchat() // Deadchat toggle is usable by anyone. + set name = "Show/Hide Deadchat" + set category = "Preferences" + set desc ="Toggles seeing deadchat" + prefs.toggles ^= CHAT_DEAD + prefs.save_preferences_sqlite(src, ckey) + + if(src.holder) + to_chat(src, "You will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") + else + to_chat(src, "As a ghost, you will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") + + feedback_add_details("admin_verb","TDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/toggleprayers() + set name = "Show/Hide Prayers" + set category = "Preferences" + set desc = "Toggles seeing prayers" + + prefs.toggles ^= CHAT_PRAYER + prefs.save_preferences_sqlite(src, ckey) + to_chat(src, "You will [(prefs.toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.") + feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/toggletitlemusic() + set name = "Hear/Silence LobbyMusic" + set category = "Preferences" + set desc = "Toggles hearing the GameLobby music" + prefs.toggles ^= SOUND_LOBBY + prefs.save_preferences_sqlite(src, ckey) + if(prefs.toggles & SOUND_LOBBY) + to_chat(src, "You will now hear music in the game lobby.") + if(istype(mob, /mob/new_player)) + playtitlemusic() + else + to_chat(src, "You will no longer hear music in the game lobby.") + if(istype(mob, /mob/new_player)) + to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// stop the jamsz + + feedback_add_details("admin_verb","TLobby") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/togglemidis() + set name = "Hear/Silence Midis" + set category = "Preferences" + set desc = "Toggles hearing sounds uploaded by admins" + prefs.toggles ^= SOUND_MIDI + prefs.save_preferences_sqlite(src, ckey) + if(prefs.toggles & SOUND_MIDI) to_chat(src, "You will now hear any sounds uploaded by admins.") - else - var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = 777) - break_sound.priority = 255 - src << break_sound //breaks the client's sound output on channel 777 + else + var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = 777) + break_sound.priority = 255 + src << break_sound //breaks the client's sound output on channel 777 to_chat(src, "You will no longer hear sounds uploaded by admins; any currently playing midis have been disabled.") - feedback_add_details("admin_verb","TMidi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/listen_ooc() - set name = "Show/Hide OOC" - set category = "Preferences" - set desc = "Toggles seeing OutOfCharacter chat" - prefs.toggles ^= CHAT_OOC - prefs.save_preferences_sqlite(src,ckey) + feedback_add_details("admin_verb","TMidi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/listen_ooc() + set name = "Show/Hide OOC" + set category = "Preferences" + set desc = "Toggles seeing OutOfCharacter chat" + prefs.toggles ^= CHAT_OOC + prefs.save_preferences_sqlite(src,ckey) to_chat(src, "You will [(prefs.toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.") - feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/verb/listen_looc() - set name = "Show/Hide LOOC" - set category = "Preferences" - set desc = "Toggles seeing Local OutOfCharacter chat" - prefs.toggles ^= CHAT_LOOC - prefs.save_preferences_sqlite(src, ckey) + feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/verb/listen_looc() + set name = "Show/Hide LOOC" + set category = "Preferences" + set desc = "Toggles seeing Local OutOfCharacter chat" + prefs.toggles ^= CHAT_LOOC + prefs.save_preferences_sqlite(src, ckey) to_chat(src, "You will [(prefs.toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.") - feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/verb/Toggle_Soundscape() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful - set name = "Hear/Silence Ambience" - set category = "Preferences" - set desc = "Toggles hearing ambient sound effects" - prefs.toggles ^= SOUND_AMBIENCE - prefs.save_preferences_sqlite(src, ckey) - if(prefs.toggles & SOUND_AMBIENCE) + feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/verb/Toggle_Soundscape() //All new ambience should be added here so it works with this verb until someone better at things comes up with a fix that isn't awful + set name = "Hear/Silence Ambience" + set category = "Preferences" + set desc = "Toggles hearing ambient sound effects" + prefs.toggles ^= SOUND_AMBIENCE + prefs.save_preferences_sqlite(src, ckey) + if(prefs.toggles & SOUND_AMBIENCE) to_chat(src, "You will now hear ambient sounds.") - else + else to_chat(src, "You will no longer hear ambient sounds.") to_chat(src, sound(null, repeat = 0, wait = 0, volume = 0, channel = 1)) to_chat(src, sound(null, repeat = 0, wait = 0, volume = 0, channel = 2)) - feedback_add_details("admin_verb","TAmbi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/verb/change_ui() - set name = "Change UI" - set category = "Preferences" - set desc = "Configure your user interface" - - if(!ishuman(usr)) + feedback_add_details("admin_verb","TAmbi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/verb/change_ui() + set name = "Change UI" + set category = "Preferences" + set desc = "Configure your user interface" + + if(!ishuman(usr)) to_chat(usr, "This only for human") - return - - var/UI_style_new = input(usr, "Select a style, we recommend White for customization") in list("White", "Midnight", "Orange", "old") - if(!UI_style_new) return - - var/UI_style_alpha_new = input(usr, "Select a new alpha(transparence) parametr for UI, between 50 and 255") as num - if(!UI_style_alpha_new | !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return - - var/UI_style_color_new = input(usr, "Choose your UI color, dark colors are not recommended!") as color|null - if(!UI_style_color_new) return - - //update UI - var/list/icons = usr.hud_used.adding + usr.hud_used.other +usr.hud_used.hotkeybuttons - icons.Add(usr.zone_sel) - - if(alert("Like it? Save changes?",,"Yes", "No") == "Yes") - prefs.UI_style = UI_style_new - prefs.UI_style_alpha = UI_style_alpha_new - prefs.UI_style_color = UI_style_color_new - prefs.save_preferences_sqlite(src, ckey) + return + + var/UI_style_new = input(usr, "Select a style, we recommend White for customization") in list("White", "Midnight", "Orange", "old") + if(!UI_style_new) return + + var/UI_style_alpha_new = input(usr, "Select a new alpha(transparence) parametr for UI, between 50 and 255") as num + if(!UI_style_alpha_new | !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return + + var/UI_style_color_new = input(usr, "Choose your UI color, dark colors are not recommended!") as color|null + if(!UI_style_color_new) return + + //update UI + var/list/icons = usr.hud_used.adding + usr.hud_used.other +usr.hud_used.hotkeybuttons + icons.Add(usr.zone_sel) + + if(alert("Like it? Save changes?",,"Yes", "No") == "Yes") + prefs.UI_style = UI_style_new + prefs.UI_style_alpha = UI_style_alpha_new + prefs.UI_style_color = UI_style_color_new + prefs.save_preferences_sqlite(src, ckey) to_chat(usr, "UI was saved") - for(var/obj/screen/I in icons) - if(I.color && I.alpha) - I.icon = ui_style2icon(UI_style_new) - I.color = UI_style_color_new - I.alpha = UI_style_alpha_new - -/client/verb/toggle_media() - set name = "Hear/Silence Streaming" - set category = "Preferences" - set desc = "Toggle hearing streaming media (radios, jukeboxes, etc)" - - prefs.toggles ^= SOUND_STREAMING - prefs.save_preferences_sqlite(src, ckey) + for(var/obj/screen/I in icons) + if(I.color && I.alpha) + I.icon = ui_style2icon(UI_style_new) + I.color = UI_style_color_new + I.alpha = UI_style_alpha_new + +/client/verb/toggle_media() + set name = "Hear/Silence Streaming" + set category = "Preferences" + set desc = "Toggle hearing streaming media (radios, jukeboxes, etc)" + + prefs.toggles ^= SOUND_STREAMING + prefs.save_preferences_sqlite(src, ckey) to_chat(usr, "You will [(prefs.toggles & SOUND_STREAMING) ? "now" : "no longer"] hear streamed media.") - if(!media) return - if(prefs.toggles & SOUND_STREAMING) - media.update_music() - else - media.stop_music() - -/client/verb/toggle_wmp() - set name = "Change Streaming Program" - set category = "Preferences" - set desc = "Toggle between using VLC and WMP to stream jukebox media" - - prefs.usewmp = !prefs.usewmp - prefs.save_preferences_sqlite(src, ckey) + if(!media) return + if(prefs.toggles & SOUND_STREAMING) + media.update_music() + else + media.stop_music() + +/client/verb/toggle_wmp() + set name = "Change Streaming Program" + set category = "Preferences" + set desc = "Toggle between using VLC and WMP to stream jukebox media" + + prefs.usewmp = !prefs.usewmp + prefs.save_preferences_sqlite(src, ckey) to_chat(usr, "You will use [(prefs.usewmp) ? "WMP" : "VLC"] to hear streamed media.") - if(!media) return - media.stop_music() - media.playerstyle = (prefs.usewmp ? PLAYER_OLD_HTML : PLAYER_HTML) - if(prefs.toggles & SOUND_STREAMING) - media.open() - media.update_music() - -/client/verb/setup_special_roles() - set name = "Setup Special Roles" - set category = "Preferences" - set desc = "Toggle hearing streaming media (radios, jukeboxes, etc)" - - prefs.configure_special_roles(usr) - -/client/verb/toggle_nanoui() - set name = "Toggle nanoUI" - set category = "Preferences" - set desc = "Toggle using nanoUI or retro style UIs for objects that support both." - prefs.usenanoui = !prefs.usenanoui - - prefs.save_preferences_sqlite(src, ckey) - - if(!prefs.usenanoui) + if(!media) return + media.stop_music() + media.playerstyle = (prefs.usewmp ? PLAYER_OLD_HTML : PLAYER_HTML) + if(prefs.toggles & SOUND_STREAMING) + media.open() + media.update_music() + +/client/verb/setup_special_roles() + set name = "Setup Special Roles" + set category = "Preferences" + set desc = "Toggle hearing streaming media (radios, jukeboxes, etc)" + + prefs.configure_special_roles(usr) + +/client/verb/toggle_nanoui() + set name = "Toggle nanoUI" + set category = "Preferences" + set desc = "Toggle using nanoUI or retro style UIs for objects that support both." + prefs.usenanoui = !prefs.usenanoui + + prefs.save_preferences_sqlite(src, ckey) + + if(!prefs.usenanoui) to_chat(usr, "You will no longer use nanoUI on cross compatible UIs.") - else + else to_chat(usr, "You will now use nanoUI on cross compatible UIs.") - -/client/verb/toggle_progress_bars() - set name = "Toggle Progress Bars" - set category = "Preferences" - set desc = "Toggle the display of a progress bar above the target of action." - prefs.progress_bars = !prefs.progress_bars - - prefs.save_preferences_sqlite(src,ckey) - - if(!prefs.progress_bars) + +/client/verb/toggle_progress_bars() + set name = "Toggle Progress Bars" + set category = "Preferences" + set desc = "Toggle the display of a progress bar above the target of action." + prefs.progress_bars = !prefs.progress_bars + + prefs.save_preferences_sqlite(src,ckey) + + if(!prefs.progress_bars) to_chat(usr, "You will no longer see progress bars when doing delayed actions.") - else + else to_chat(usr, "You will now see progress bars when doing delayed actions") diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 0b173018151..195674f3018 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -1,312 +1,312 @@ -/obj/item/clothing/glasses/meson - name = "Optical Meson Scanner" - desc = "Used for seeing walls, floors, and stuff through anything." - icon_state = "meson" - item_state = "glasses" - origin_tech = "magnets=2;engineering=2" - vision_flags = SEE_TURFS - eyeprot = -1 - see_invisible = SEE_INVISIBLE_MINIMUM - species_fit = list("Vox") - action_button_name = "Toggle Meson Scanner" - var/on = 1 - -/obj/item/clothing/glasses/meson/proc/getMask() - return global_hud.darkMask - -/obj/item/clothing/glasses/meson/attack_self() - toggle() - - -/obj/item/clothing/glasses/meson/verb/toggle() //Zth: I'm sure there's a better way of doing this, DON'T LYNCH ME PLEASE, I'M LEARNING - set category = "Object" - set name = "Toggle Optical Meson Scanner" - set src in usr - var/mob/C = usr - if(!usr) - if(!ismob(loc)) - return - C = loc - if(C.canmove && !C.stat && !C.restrained()) - if(!src.on) - src.on = !src.on - eyeprot = 2 - vision_flags |= SEE_TURFS - see_invisible |= SEE_INVISIBLE_MINIMUM - body_parts_covered |= EYES - icon_state = initial(icon_state) +/obj/item/clothing/glasses/meson + name = "Optical Meson Scanner" + desc = "Used for seeing walls, floors, and stuff through anything." + icon_state = "meson" + item_state = "glasses" + origin_tech = "magnets=2;engineering=2" + vision_flags = SEE_TURFS + eyeprot = -1 + see_invisible = SEE_INVISIBLE_MINIMUM + species_fit = list("Vox") + action_button_name = "Toggle Meson Scanner" + var/on = 1 + +/obj/item/clothing/glasses/meson/proc/getMask() + return global_hud.darkMask + +/obj/item/clothing/glasses/meson/attack_self() + toggle() + + +/obj/item/clothing/glasses/meson/verb/toggle() //Zth: I'm sure there's a better way of doing this, DON'T LYNCH ME PLEASE, I'M LEARNING + set category = "Object" + set name = "Toggle Optical Meson Scanner" + set src in usr + var/mob/C = usr + if(!usr) + if(!ismob(loc)) + return + C = loc + if(C.canmove && !C.stat && !C.restrained()) + if(!src.on) + src.on = !src.on + eyeprot = 2 + vision_flags |= SEE_TURFS + see_invisible |= SEE_INVISIBLE_MINIMUM + body_parts_covered |= EYES + icon_state = initial(icon_state) to_chat(C, "You turn [src] on.") - else //Mesons are like cyclops' visons. When off, your eyes are exposed - src.on = !src.on - eyeprot = 0 - body_parts_covered &= ~EYES - vision_flags &= ~SEE_TURFS - see_invisible &= ~SEE_INVISIBLE_MINIMUM - icon_state = "[initial(icon_state)]off" + else //Mesons are like cyclops' visons. When off, your eyes are exposed + src.on = !src.on + eyeprot = 0 + body_parts_covered &= ~EYES + vision_flags &= ~SEE_TURFS + see_invisible &= ~SEE_INVISIBLE_MINIMUM + icon_state = "[initial(icon_state)]off" to_chat(C, "You turn [src] off.") - - C.update_inv_glasses() - -/obj/item/clothing/glasses/meson/prescription - name = "prescription mesons" - desc = "Optical Meson Scanner with prescription lenses." - prescription = 1 - eyeprot = -1 - species_fit = list("Vox") - -/obj/item/clothing/glasses/science - name = "Science Goggles" - desc = "nothing" - icon_state = "purple" - item_state = "glasses" - origin_tech = "materials=1" - -/obj/item/clothing/glasses/night - name = "Night Vision Goggles" - desc = "You can totally see in the dark now!." - icon_state = "night" - item_state = "glasses" - origin_tech = "magnets=2" - see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING - see_in_dark = 8 - species_fit = list("Vox") - eyeprot = -1 - -/obj/item/clothing/glasses/eyepatch - name = "eyepatch" - desc = "Yarr." - icon_state = "eyepatch" - item_state = "eyepatch" - min_harm_label = 0 - -/obj/item/clothing/glasses/monocle - name = "monocle" - desc = "Such a dapper eyepiece!" - icon_state = "monocle" - item_state = "headset" // lol - species_fit = list("Vox") - min_harm_label = 3 - harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") -/obj/item/clothing/glasses/monocle/harm_label_update() - return //Can't exactly blind someone by covering one eye. - -/obj/item/clothing/glasses/material - name = "Optical Material Scanner" - desc = "Very confusing glasses." - icon_state = "material" - item_state = "glasses" - origin_tech = "magnets=3;engineering=3" - vision_flags = SEE_OBJS - see_invisible = SEE_INVISIBLE_MINIMUM - species_fit = list("Vox") - -/obj/item/clothing/glasses/regular - name = "Prescription Glasses" - desc = "Made by Nerd. Co." - icon_state = "glasses" - item_state = "glasses" - prescription = 1 - -/obj/item/clothing/glasses/regular/hipster - name = "Prescription Glasses" - desc = "Made by Uncool. Co." - icon_state = "hipster_glasses" - item_state = "hipster_glasses" - -/obj/item/clothing/glasses/gglasses - name = "Green Glasses" - desc = "Forest green glasses, like the kind you'd wear when hatching a nasty scheme." - icon_state = "gglasses" - item_state = "gglasses" - -/obj/item/clothing/glasses/sunglasses - desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." - name = "sunglasses" - icon_state = "sun" - item_state = "sunglasses" - origin_tech = "combat=2" - darkness_view = -1 - eyeprot = 1 - species_fit = list("Vox") - -/obj/item/clothing/glasses/virussunglasses - desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." - name = "sunglasses" - icon_state = "sun" - item_state = "sunglasses" - origin_tech = "combat=2" - darkness_view = -1 - species_fit = list("Vox") - -/obj/item/clothing/glasses/welding - name = "welding goggles" - desc = "Protects the eyes from welders, approved by the mad scientist association." - icon_state = "welding-g" - item_state = "welding-g" - origin_tech = "engineering=1;materials=2" - action_button_name = "Toggle Welding Goggles" - var/up = 0 - eyeprot = 3 - species_fit = list("Vox") - -/obj/item/clothing/glasses/welding/proc/getMask() - return global_hud.darkMask - -/obj/item/clothing/glasses/welding/attack_self() - toggle() - - -/obj/item/clothing/glasses/welding/verb/toggle() - set category = "Object" - set name = "Adjust welding goggles" - set src in usr - var/mob/C = usr - if(!usr) - if(!ismob(loc)) - return - C = loc - if(C.canmove && !C.stat && !C.restrained()) - if(src.up) - src.up = !src.up - eyeprot = 2 - body_parts_covered |= EYES - icon_state = initial(icon_state) + + C.update_inv_glasses() + +/obj/item/clothing/glasses/meson/prescription + name = "prescription mesons" + desc = "Optical Meson Scanner with prescription lenses." + prescription = 1 + eyeprot = -1 + species_fit = list("Vox") + +/obj/item/clothing/glasses/science + name = "Science Goggles" + desc = "nothing" + icon_state = "purple" + item_state = "glasses" + origin_tech = "materials=1" + +/obj/item/clothing/glasses/night + name = "Night Vision Goggles" + desc = "You can totally see in the dark now!." + icon_state = "night" + item_state = "glasses" + origin_tech = "magnets=2" + see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING + see_in_dark = 8 + species_fit = list("Vox") + eyeprot = -1 + +/obj/item/clothing/glasses/eyepatch + name = "eyepatch" + desc = "Yarr." + icon_state = "eyepatch" + item_state = "eyepatch" + min_harm_label = 0 + +/obj/item/clothing/glasses/monocle + name = "monocle" + desc = "Such a dapper eyepiece!" + icon_state = "monocle" + item_state = "headset" // lol + species_fit = list("Vox") + min_harm_label = 3 + harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") +/obj/item/clothing/glasses/monocle/harm_label_update() + return //Can't exactly blind someone by covering one eye. + +/obj/item/clothing/glasses/material + name = "Optical Material Scanner" + desc = "Very confusing glasses." + icon_state = "material" + item_state = "glasses" + origin_tech = "magnets=3;engineering=3" + vision_flags = SEE_OBJS + see_invisible = SEE_INVISIBLE_MINIMUM + species_fit = list("Vox") + +/obj/item/clothing/glasses/regular + name = "Prescription Glasses" + desc = "Made by Nerd. Co." + icon_state = "glasses" + item_state = "glasses" + prescription = 1 + +/obj/item/clothing/glasses/regular/hipster + name = "Prescription Glasses" + desc = "Made by Uncool. Co." + icon_state = "hipster_glasses" + item_state = "hipster_glasses" + +/obj/item/clothing/glasses/gglasses + name = "Green Glasses" + desc = "Forest green glasses, like the kind you'd wear when hatching a nasty scheme." + icon_state = "gglasses" + item_state = "gglasses" + +/obj/item/clothing/glasses/sunglasses + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." + name = "sunglasses" + icon_state = "sun" + item_state = "sunglasses" + origin_tech = "combat=2" + darkness_view = -1 + eyeprot = 1 + species_fit = list("Vox") + +/obj/item/clothing/glasses/virussunglasses + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." + name = "sunglasses" + icon_state = "sun" + item_state = "sunglasses" + origin_tech = "combat=2" + darkness_view = -1 + species_fit = list("Vox") + +/obj/item/clothing/glasses/welding + name = "welding goggles" + desc = "Protects the eyes from welders, approved by the mad scientist association." + icon_state = "welding-g" + item_state = "welding-g" + origin_tech = "engineering=1;materials=2" + action_button_name = "Toggle Welding Goggles" + var/up = 0 + eyeprot = 3 + species_fit = list("Vox") + +/obj/item/clothing/glasses/welding/proc/getMask() + return global_hud.darkMask + +/obj/item/clothing/glasses/welding/attack_self() + toggle() + + +/obj/item/clothing/glasses/welding/verb/toggle() + set category = "Object" + set name = "Adjust welding goggles" + set src in usr + var/mob/C = usr + if(!usr) + if(!ismob(loc)) + return + C = loc + if(C.canmove && !C.stat && !C.restrained()) + if(src.up) + src.up = !src.up + eyeprot = 2 + body_parts_covered |= EYES + icon_state = initial(icon_state) to_chat(C, "You flip the [src] down to protect your eyes.") - else - src.up = !src.up - eyeprot = 0 - body_parts_covered &= ~EYES - icon_state = "[initial(icon_state)]up" + else + src.up = !src.up + eyeprot = 0 + body_parts_covered &= ~EYES + icon_state = "[initial(icon_state)]up" to_chat(C, "You push the [src] up out of your face.") - - C.update_inv_glasses() - -/obj/item/clothing/glasses/welding/superior - name = "superior welding goggles" - desc = "Welding goggles made from more expensive materials, strangely smells like potatoes. Allows for better vision than normal goggles.." - icon_state = "rwelding-g" - item_state = "rwelding-g" - origin_tech = "engineering=3;materials=3" - -/obj/item/clothing/glasses/welding/superior/getMask() - return null - -/obj/item/clothing/glasses/sunglasses/blindfold - name = "blindfold" - desc = "Covers the eyes, preventing sight." - icon_state = "blindfold" - item_state = "blindfold" - see_invisible = SEE_INVISIBLE_LIVING - vision_flags = BLIND - eyeprot = 4 //What you can't see can't burn your eyes out - species_fit = list("Vox") - min_harm_label = 0 - -/obj/item/clothing/glasses/sunglasses/prescription - name = "prescription sunglasses" - prescription = 1 - species_fit = list("Vox") - -/obj/item/clothing/glasses/sunglasses/big - desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks many flashes." - icon_state = "bigsunglasses" - item_state = "bigsunglasses" - species_fit = list("Vox") - min_harm_label = 15 - -/obj/item/clothing/glasses/sunglasses/sechud - name = "HUDSunglasses" - desc = "Sunglasses with a HUD." - icon_state = "sunhud" - var/obj/item/clothing/glasses/hud/security/hud = null - species_fit = list("Vox") - - New() - ..() - src.hud = new/obj/item/clothing/glasses/hud/security(src) - return - -/obj/item/clothing/glasses/thermal - name = "Optical Thermal Scanner" - desc = "Thermals in the shape of glasses." - icon_state = "thermal" - item_state = "glasses" - origin_tech = "magnets=3" - vision_flags = SEE_MOBS - see_invisible = SEE_INVISIBLE_MINIMUM - invisa_view = 2 - eyeprot = -2 //prepare for your eyes to get shit on - - emp_act(severity) - if(istype(src.loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/M = src.loc + + C.update_inv_glasses() + +/obj/item/clothing/glasses/welding/superior + name = "superior welding goggles" + desc = "Welding goggles made from more expensive materials, strangely smells like potatoes. Allows for better vision than normal goggles.." + icon_state = "rwelding-g" + item_state = "rwelding-g" + origin_tech = "engineering=3;materials=3" + +/obj/item/clothing/glasses/welding/superior/getMask() + return null + +/obj/item/clothing/glasses/sunglasses/blindfold + name = "blindfold" + desc = "Covers the eyes, preventing sight." + icon_state = "blindfold" + item_state = "blindfold" + see_invisible = SEE_INVISIBLE_LIVING + vision_flags = BLIND + eyeprot = 4 //What you can't see can't burn your eyes out + species_fit = list("Vox") + min_harm_label = 0 + +/obj/item/clothing/glasses/sunglasses/prescription + name = "prescription sunglasses" + prescription = 1 + species_fit = list("Vox") + +/obj/item/clothing/glasses/sunglasses/big + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks many flashes." + icon_state = "bigsunglasses" + item_state = "bigsunglasses" + species_fit = list("Vox") + min_harm_label = 15 + +/obj/item/clothing/glasses/sunglasses/sechud + name = "HUDSunglasses" + desc = "Sunglasses with a HUD." + icon_state = "sunhud" + var/obj/item/clothing/glasses/hud/security/hud = null + species_fit = list("Vox") + + New() + ..() + src.hud = new/obj/item/clothing/glasses/hud/security(src) + return + +/obj/item/clothing/glasses/thermal + name = "Optical Thermal Scanner" + desc = "Thermals in the shape of glasses." + icon_state = "thermal" + item_state = "glasses" + origin_tech = "magnets=3" + vision_flags = SEE_MOBS + see_invisible = SEE_INVISIBLE_MINIMUM + invisa_view = 2 + eyeprot = -2 //prepare for your eyes to get shit on + + emp_act(severity) + if(istype(src.loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/M = src.loc to_chat(M, "The Optical Thermal Scanner overloads and blinds you!") - if(M.glasses == src) - M.eye_blind = 3 - M.eye_blurry = 5 - M.disabilities |= NEARSIGHTED - spawn(100) - M.disabilities &= ~NEARSIGHTED - ..() - -/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete - name = "Optical Meson Scanner" - desc = "Used for seeing walls, floors, and stuff through anything." - icon_state = "meson" - origin_tech = "magnets=3;syndicate=4" - species_fit = list("Vox") - -/obj/item/clothing/glasses/thermal/monocle - name = "Thermonocle" - desc = "A monocle thermal." - icon_state = "thermoncle" - flags = 0 //doesn't protect eyes because it's a monocle, duh - min_harm_label = 3 - harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") -/obj/item/clothing/glasses/thermal/monocle/harm_label_update() - if(harm_labeled < min_harm_label) - vision_flags |= SEE_MOBS - see_invisible |= SEE_INVISIBLE_MINIMUM - invisa_view = 2 - else - vision_flags &= ~SEE_MOBS - see_invisible &= ~SEE_INVISIBLE_MINIMUM - invisa_view = 0 - -/obj/item/clothing/glasses/thermal/eyepatch - name = "Optical Thermal Eyepatch" - desc = "An eyepatch with built-in thermal optics" - icon_state = "eyepatch" - item_state = "eyepatch" - min_harm_label = 3 - harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") -/obj/item/clothing/glasses/thermal/eyepatch/harm_label_update() - if(harm_labeled < min_harm_label) - vision_flags |= SEE_MOBS - see_invisible |= SEE_INVISIBLE_MINIMUM - invisa_view = 2 - else - vision_flags &= ~SEE_MOBS - see_invisible &= ~SEE_INVISIBLE_MINIMUM - invisa_view = 0 - -/obj/item/clothing/glasses/thermal/jensen - name = "Optical Thermal Implants" - desc = "A set of implantable lenses designed to augment your vision" - icon_state = "thermalimplants" - item_state = "syringe_kit" - species_fit = list("Vox") - -/obj/item/clothing/glasses/simonglasses - name = "Simon's Glasses" - desc = "Just who the hell do you think I am?" - icon_state = "simonglasses" - item_state = "simonglasses" - cover_hair = 1 - -/obj/item/clothing/glasses/kaminaglasses - name = "Kamina's Glasses" - desc = "I'm going to tell you something important now, so you better dig the wax out of those huge ears of yours and listen! The reputation of Team Gurren echoes far and wide. When they talk about its badass leader - the man of indomitable spirit and masculinity - they're talking about me! The mighty Kamina!" - icon_state = "kaminaglasses" - item_state = "kaminaglasses" - cover_hair = 1 + if(M.glasses == src) + M.eye_blind = 3 + M.eye_blurry = 5 + M.disabilities |= NEARSIGHTED + spawn(100) + M.disabilities &= ~NEARSIGHTED + ..() + +/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete + name = "Optical Meson Scanner" + desc = "Used for seeing walls, floors, and stuff through anything." + icon_state = "meson" + origin_tech = "magnets=3;syndicate=4" + species_fit = list("Vox") + +/obj/item/clothing/glasses/thermal/monocle + name = "Thermonocle" + desc = "A monocle thermal." + icon_state = "thermoncle" + flags = 0 //doesn't protect eyes because it's a monocle, duh + min_harm_label = 3 + harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") +/obj/item/clothing/glasses/thermal/monocle/harm_label_update() + if(harm_labeled < min_harm_label) + vision_flags |= SEE_MOBS + see_invisible |= SEE_INVISIBLE_MINIMUM + invisa_view = 2 + else + vision_flags &= ~SEE_MOBS + see_invisible &= ~SEE_INVISIBLE_MINIMUM + invisa_view = 0 + +/obj/item/clothing/glasses/thermal/eyepatch + name = "Optical Thermal Eyepatch" + desc = "An eyepatch with built-in thermal optics" + icon_state = "eyepatch" + item_state = "eyepatch" + min_harm_label = 3 + harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") +/obj/item/clothing/glasses/thermal/eyepatch/harm_label_update() + if(harm_labeled < min_harm_label) + vision_flags |= SEE_MOBS + see_invisible |= SEE_INVISIBLE_MINIMUM + invisa_view = 2 + else + vision_flags &= ~SEE_MOBS + see_invisible &= ~SEE_INVISIBLE_MINIMUM + invisa_view = 0 + +/obj/item/clothing/glasses/thermal/jensen + name = "Optical Thermal Implants" + desc = "A set of implantable lenses designed to augment your vision" + icon_state = "thermalimplants" + item_state = "syringe_kit" + species_fit = list("Vox") + +/obj/item/clothing/glasses/simonglasses + name = "Simon's Glasses" + desc = "Just who the hell do you think I am?" + icon_state = "simonglasses" + item_state = "simonglasses" + cover_hair = 1 + +/obj/item/clothing/glasses/kaminaglasses + name = "Kamina's Glasses" + desc = "I'm going to tell you something important now, so you better dig the wax out of those huge ears of yours and listen! The reputation of Team Gurren echoes far and wide. When they talk about its badass leader - the man of indomitable spirit and masculinity - they're talking about me! The mighty Kamina!" + icon_state = "kaminaglasses" + item_state = "kaminaglasses" + cover_hair = 1 diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index f726e28dbf2..fce387229db 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -1,50 +1,50 @@ -/obj/item/clothing/glasses/hud - name = "HUD" - desc = "A heads-up display that provides important info in (almost) real time." - flags = 0 //doesn't protect eyes because it's a monocle, duh - origin_tech = "magnets=3;biotech=2" - min_harm_label = 3 - harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") - var/list/icon/current = list() //the current hud icons - - proc - process_hud(var/mob/M) return - -/obj/item/clothing/glasses/hud/harm_label_update() - return - - -/obj/item/clothing/glasses/hud/health - name = "Health Scanner HUD" - desc = "A heads-up display that scans the humanoid carbon lifeforms in view and provides accurate data about their health status." - icon_state = "healthhud" - -/obj/item/clothing/glasses/hud/health/process_hud(var/mob/M) - if(harm_labeled < min_harm_label) - process_med_hud(M) - - -/obj/item/clothing/glasses/hud/security - name = "Security HUD" - desc = "A heads-up display that scans the humanoid carbon lifeforms in view and provides accurate data about their ID status and security records." - icon_state = "securityhud" - -/obj/item/clothing/glasses/hud/security/jensenshades - name = "Augmented shades" - desc = "Polarized bioneural eyewear, designed to augment your vision." - icon_state = "jensenshades" - item_state = "jensenshades" - min_harm_label = 12 - vision_flags = SEE_MOBS - invisa_view = 2 - eyeprot = 1 - -/obj/item/clothing/glasses/hud/security/jensenshades/harm_label_update() - if(harm_labeled >= min_harm_label) - vision_flags |= BLIND - else - vision_flags &= ~BLIND - -/obj/item/clothing/glasses/hud/security/process_hud(var/mob/M) - if(harm_labeled < min_harm_label) - process_sec_hud(M,1) +/obj/item/clothing/glasses/hud + name = "HUD" + desc = "A heads-up display that provides important info in (almost) real time." + flags = 0 //doesn't protect eyes because it's a monocle, duh + origin_tech = "magnets=3;biotech=2" + min_harm_label = 3 + harm_label_examine = list("A tiny label is on the lens.","A label covers the lens!") + var/list/icon/current = list() //the current hud icons + + proc + process_hud(var/mob/M) return + +/obj/item/clothing/glasses/hud/harm_label_update() + return + + +/obj/item/clothing/glasses/hud/health + name = "Health Scanner HUD" + desc = "A heads-up display that scans the humanoid carbon lifeforms in view and provides accurate data about their health status." + icon_state = "healthhud" + +/obj/item/clothing/glasses/hud/health/process_hud(var/mob/M) + if(harm_labeled < min_harm_label) + process_med_hud(M) + + +/obj/item/clothing/glasses/hud/security + name = "Security HUD" + desc = "A heads-up display that scans the humanoid carbon lifeforms in view and provides accurate data about their ID status and security records." + icon_state = "securityhud" + +/obj/item/clothing/glasses/hud/security/jensenshades + name = "Augmented shades" + desc = "Polarized bioneural eyewear, designed to augment your vision." + icon_state = "jensenshades" + item_state = "jensenshades" + min_harm_label = 12 + vision_flags = SEE_MOBS + invisa_view = 2 + eyeprot = 1 + +/obj/item/clothing/glasses/hud/security/jensenshades/harm_label_update() + if(harm_labeled >= min_harm_label) + vision_flags |= BLIND + else + vision_flags &= ~BLIND + +/obj/item/clothing/glasses/hud/security/process_hud(var/mob/M) + if(harm_labeled < min_harm_label) + process_sec_hud(M,1) diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 10eb45129bd..379b9c00fcd 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -1,201 +1,201 @@ -/obj/item/clothing/gloves/yellow - desc = "These gloves will protect the wearer from electric shock." - name = "insulated gloves" - icon_state = "yellow" - item_state = "yellow" - siemens_coefficient = 0 - permeability_coefficient = 0.05 - _color = "yellow" - species_fit = list("Vox") - -/obj/item/clothing/gloves/yellow/power //fuck you don't relative path this - var/next_shock = 0 - -/obj/item/clothing/gloves/yellow/power/Touch(var/atom/A, mob/living/user, prox) - if(prox == 0 && user.a_intent == I_HURT) - var/time = 100 - var/turf/T = get_turf(user) - var/turf/U = get_turf(A) - var/obj/structure/cable/cable = locate() in T - if(!cable || !istype(cable)) - return - if(world.time < next_shock) - to_chat(user, "[src] aren't ready to shock again!") - return - user.visible_message("[user.name] fires an arc of electricity!", \ - "You fire an arc of electricity!", \ - "You hear the loud crackle of electricity!") - var/datum/powernet/PN = cable.get_powernet() - var/obj/item/projectile/beam/lightning/L = getFromPool(/obj/item/projectile/beam/lightning, T) - if(PN) - L.damage = PN.get_electrocute_damage() - if(L.damage >= 200) - user.apply_damage(15, BURN, (user.hand ? "l_hand" : "r_hand")) - time = 200 - to_chat(user, "[src] overload\s from the massive current, shocking you in the process!") - else if(L.damage >= 100) - user.apply_damage(5, BURN, (user.hand ? "l_hand" : "r_hand")) - time = 150 - to_chat(user, "[src] overload\s from the massive current, shocking you in the process!") - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, user) - s.start() - if(L.damage <= 0) - returnToPool(L) - //del(L) - if(L) - playsound(get_turf(src), 'sound/effects/eleczap.ogg', 75, 1) - L.tang = adjustAngle(get_angle(U,T)) - L.icon = midicon - L.icon_state = "[L.tang]" - L.firer = user - L.def_zone = user.get_organ_target() - L.original = A - L.current = U - L.starting = U - L.yo = U.y - T.y - L.xo = U.x - T.x - spawn L.process() - user.delayNextAttack(12) - next_shock = world.time + time - return 1 - return - - -/obj/item/clothing/gloves/fyellow //Cheap Chinese Crap - desc = "These gloves are cheap copies of the coveted gloves, no way this can end badly." - name = "budget insulated gloves" - icon_state = "yellow" - item_state = "yellow" - siemens_coefficient = 1 //Set to a default of 1, gets overridden in New() - permeability_coefficient = 0.05 - species_fit = list("Vox") - _color = "yellow" - -/obj/item/clothing/gloves/fyellow/New() - . = ..() - siemens_coefficient = pick(0,0.5,0.5,0.5,0.5,0.75,1.5) - -/obj/item/clothing/gloves/black - desc = "These gloves are fire-resistant." - name = "black gloves" - icon_state = "black" - item_state = "black" - _color = "black" - species_fit = list("Vox") - - cold_protection = HANDS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = HANDS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - - -/obj/item/clothing/gloves/black/hos - _color = "hosred" //Exists for washing machines. Is not different from black gloves in any way. - -/obj/item/clothing/gloves/black/ce - _color = "chief" //Exists for washing machines. Is not different from black gloves in any way. - -/obj/item/clothing/gloves/black/rd - _color = "director" //Exists for washing machines. Is not different from black gloves in any way. - -/obj/item/clothing/gloves/black/hop - _color = "hop" //Exists for washing machines. Is not different from black gloves in any way. - -/obj/item/clothing/gloves/black/thief - pickpocket = 1 - - -/obj/item/clothing/gloves/orange - name = "orange gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "orange" - item_state = "orange" - _color = "orange" - species_fit = list("Vox") - -/obj/item/clothing/gloves/red - name = "red gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "red" - item_state = "red" - _color = "red" - species_fit = list("Vox") - -/obj/item/clothing/gloves/red/redcoat - _color = "redcoat" //Exists for washing machines. Is not different from red gloves in any way. - -/obj/item/clothing/gloves/rainbow - name = "rainbow gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "rainbow" - item_state = "rainbow" - _color = "rainbow" - species_fit = list("Vox") - -/obj/item/clothing/gloves/rainbow/clown - _color = "clown" - -/obj/item/clothing/gloves/blue - name = "blue gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "blue" - item_state = "blue" - _color = "blue" - species_fit = list("Vox") - -/obj/item/clothing/gloves/purple - name = "purple gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "purple" - item_state = "purple" - _color = "purple" - species_fit = list("Vox") - -/obj/item/clothing/gloves/green - name = "green gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "green" - item_state = "green" - _color = "green" - species_fit = list("Vox") - -/obj/item/clothing/gloves/white - name = "white gloves" - desc = "These look pretty fancy." - icon_state = "white" - item_state = "white" - _color = "mime" - species_fit = list("Vox") - -/obj/item/clothing/gloves/white/stunglove // For Clown Planet's mimes. - N3X - New() - ..() - cell = new /obj/item/weapon/cell/crap/empty(src) - -/obj/item/clothing/gloves/grey - name = "grey gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "gray" - item_state = "gray" - _color = "grey" - species_fit = list("Vox") - -/obj/item/clothing/gloves/light_brown - name = "light brown gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "lightbrown" - item_state = "lightbrown" - _color = "light brown" - species_fit = list("Vox") - -/obj/item/clothing/gloves/brown - name = "brown gloves" - desc = "A pair of gloves, they don't look special in any way." - icon_state = "brown" - item_state = "browngloves" - _color="brown" - species_fit = list("Vox") - -/obj/item/clothing/gloves/brown/cargo - _color = "cargo" //Exists for washing machines. Is not different from brown gloves in any way. +/obj/item/clothing/gloves/yellow + desc = "These gloves will protect the wearer from electric shock." + name = "insulated gloves" + icon_state = "yellow" + item_state = "yellow" + siemens_coefficient = 0 + permeability_coefficient = 0.05 + _color = "yellow" + species_fit = list("Vox") + +/obj/item/clothing/gloves/yellow/power //fuck you don't relative path this + var/next_shock = 0 + +/obj/item/clothing/gloves/yellow/power/Touch(var/atom/A, mob/living/user, prox) + if(prox == 0 && user.a_intent == I_HURT) + var/time = 100 + var/turf/T = get_turf(user) + var/turf/U = get_turf(A) + var/obj/structure/cable/cable = locate() in T + if(!cable || !istype(cable)) + return + if(world.time < next_shock) + to_chat(user, "[src] aren't ready to shock again!") + return + user.visible_message("[user.name] fires an arc of electricity!", \ + "You fire an arc of electricity!", \ + "You hear the loud crackle of electricity!") + var/datum/powernet/PN = cable.get_powernet() + var/obj/item/projectile/beam/lightning/L = getFromPool(/obj/item/projectile/beam/lightning, T) + if(PN) + L.damage = PN.get_electrocute_damage() + if(L.damage >= 200) + user.apply_damage(15, BURN, (user.hand ? "l_hand" : "r_hand")) + time = 200 + to_chat(user, "[src] overload\s from the massive current, shocking you in the process!") + else if(L.damage >= 100) + user.apply_damage(5, BURN, (user.hand ? "l_hand" : "r_hand")) + time = 150 + to_chat(user, "[src] overload\s from the massive current, shocking you in the process!") + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, user) + s.start() + if(L.damage <= 0) + returnToPool(L) + //del(L) + if(L) + playsound(get_turf(src), 'sound/effects/eleczap.ogg', 75, 1) + L.tang = adjustAngle(get_angle(U,T)) + L.icon = midicon + L.icon_state = "[L.tang]" + L.firer = user + L.def_zone = user.get_organ_target() + L.original = A + L.current = U + L.starting = U + L.yo = U.y - T.y + L.xo = U.x - T.x + spawn L.process() + user.delayNextAttack(12) + next_shock = world.time + time + return 1 + return + + +/obj/item/clothing/gloves/fyellow //Cheap Chinese Crap + desc = "These gloves are cheap copies of the coveted gloves, no way this can end badly." + name = "budget insulated gloves" + icon_state = "yellow" + item_state = "yellow" + siemens_coefficient = 1 //Set to a default of 1, gets overridden in New() + permeability_coefficient = 0.05 + species_fit = list("Vox") + _color = "yellow" + +/obj/item/clothing/gloves/fyellow/New() + . = ..() + siemens_coefficient = pick(0,0.5,0.5,0.5,0.5,0.75,1.5) + +/obj/item/clothing/gloves/black + desc = "These gloves are fire-resistant." + name = "black gloves" + icon_state = "black" + item_state = "black" + _color = "black" + species_fit = list("Vox") + + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + + +/obj/item/clothing/gloves/black/hos + _color = "hosred" //Exists for washing machines. Is not different from black gloves in any way. + +/obj/item/clothing/gloves/black/ce + _color = "chief" //Exists for washing machines. Is not different from black gloves in any way. + +/obj/item/clothing/gloves/black/rd + _color = "director" //Exists for washing machines. Is not different from black gloves in any way. + +/obj/item/clothing/gloves/black/hop + _color = "hop" //Exists for washing machines. Is not different from black gloves in any way. + +/obj/item/clothing/gloves/black/thief + pickpocket = 1 + + +/obj/item/clothing/gloves/orange + name = "orange gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "orange" + item_state = "orange" + _color = "orange" + species_fit = list("Vox") + +/obj/item/clothing/gloves/red + name = "red gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "red" + item_state = "red" + _color = "red" + species_fit = list("Vox") + +/obj/item/clothing/gloves/red/redcoat + _color = "redcoat" //Exists for washing machines. Is not different from red gloves in any way. + +/obj/item/clothing/gloves/rainbow + name = "rainbow gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "rainbow" + item_state = "rainbow" + _color = "rainbow" + species_fit = list("Vox") + +/obj/item/clothing/gloves/rainbow/clown + _color = "clown" + +/obj/item/clothing/gloves/blue + name = "blue gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "blue" + item_state = "blue" + _color = "blue" + species_fit = list("Vox") + +/obj/item/clothing/gloves/purple + name = "purple gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "purple" + item_state = "purple" + _color = "purple" + species_fit = list("Vox") + +/obj/item/clothing/gloves/green + name = "green gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "green" + item_state = "green" + _color = "green" + species_fit = list("Vox") + +/obj/item/clothing/gloves/white + name = "white gloves" + desc = "These look pretty fancy." + icon_state = "white" + item_state = "white" + _color = "mime" + species_fit = list("Vox") + +/obj/item/clothing/gloves/white/stunglove // For Clown Planet's mimes. - N3X + New() + ..() + cell = new /obj/item/weapon/cell/crap/empty(src) + +/obj/item/clothing/gloves/grey + name = "grey gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "gray" + item_state = "gray" + _color = "grey" + species_fit = list("Vox") + +/obj/item/clothing/gloves/light_brown + name = "light brown gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "lightbrown" + item_state = "lightbrown" + _color = "light brown" + species_fit = list("Vox") + +/obj/item/clothing/gloves/brown + name = "brown gloves" + desc = "A pair of gloves, they don't look special in any way." + icon_state = "brown" + item_state = "browngloves" + _color="brown" + species_fit = list("Vox") + +/obj/item/clothing/gloves/brown/cargo + _color = "cargo" //Exists for washing machines. Is not different from brown gloves in any way. diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index fcf6130c41d..1a19030c84f 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -1,138 +1,138 @@ -/obj/item/clothing/gloves/captain - desc = "Regal blue gloves, with a nice gold trim. Swanky." - name = "captain's gloves" - icon_state = "captain" - item_state = "captain" - siemens_coefficient = 0 - _color = "captain" - cold_protection = HANDS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = HANDS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - species_fit = list("Vox") - -/obj/item/clothing/gloves/cyborg - desc = "beep boop borp" - name = "cyborg gloves" - icon_state = "black" - item_state = "black" - siemens_coefficient = 1.0 - species_fit = list("Vox") - -/obj/item/clothing/gloves/swat - desc = "These tactical gloves are somewhat fire and impact-resistant." - name = "\improper SWAT Gloves" - icon_state = "black" - item_state = "black" - siemens_coefficient = 0.6 - permeability_coefficient = 0.05 - - cold_protection = HANDS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = HANDS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - species_fit = list("Vox") - -/obj/item/clothing/gloves/combat //Combined effect of SWAT gloves and insulated gloves - desc = "These tactical gloves are somewhat fire and impact resistant." - name = "combat gloves" - icon_state = "black" - item_state = "black" - siemens_coefficient = 0 - permeability_coefficient = 0.05 - cold_protection = HANDS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = HANDS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - species_fit = list("Vox") - -/obj/item/clothing/gloves/latex - name = "latex gloves" - desc = "Sterile latex gloves." - icon_state = "latex" - item_state = "latex" - siemens_coefficient = 0.30 - permeability_coefficient = 0.01 - _color = "medical" //matches cmo stamp - species_fit = list("Vox") - -/obj/item/clothing/gloves/botanic_leather - desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin." - name = "botanist's leather gloves" - icon_state = "leather" - item_state = "leather" - permeability_coefficient = 0.9 - siemens_coefficient = 0.9 - species_fit = list("Vox") - -/obj/item/clothing/gloves/batmangloves - desc = "Used for handling all things bat related." - name = "batgloves" - icon_state = "bmgloves" - item_state = "bmgloves" - _color = "bmgloves" - species_fit = list("Vox") - -/obj/item/clothing/gloves/bikergloves - name = "Biker's Gloves" - icon_state = "biker-gloves" - item_state = "biker-gloves" - _color = "bikergloves" - -/obj/item/clothing/gloves/megagloves - desc = "Uncomfortably bulky armored gloves." - name = "DRN-001 Gloves" - icon_state = "megagloves" - item_state = "megagloves" - species_fit = list("Vox") - -/obj/item/clothing/gloves/protogloves - desc = "Funcionally identical to the DRN-001 model's, but in red!" - name = "Prototype Gloves" - icon_state = "protogloves" - item_state = "protogloves" - species_fit = list("Vox") - -/obj/item/clothing/gloves/megaxgloves - desc = "An upgrade to the DRN-001's gauntlets, retains the uncomfortable armor, but comes with white gloves!" - name = "Maverick Hunter gloves" - icon_state = "megaxgloves" - item_state = "megaxgloves" - species_fit = list("Vox") - -/obj/item/clothing/gloves/joegloves - desc = "Large grey gloves, very similar to the Prototype's." - name = "Sniper Gloves" - icon_state = "joegloves" - item_state = "joegloves" - species_fit = list("Vox") - -/obj/item/clothing/gloves/doomguy - desc = "" - name = "Doomguy's gloves" - icon_state = "doom" - item_state = "doom" - -/obj/item/clothing/gloves/knuckles - desc = "A pair of classic metal knuckles that are designed to increase tissue damage and bone fractures when punching." - name = "brass knuckles" - icon_state = "knuckles" - item_state = "knuckles" - - attack_verb = list("punched") - bonus_knockout = 2 //Slight knockout chance increase. - damage_added = 3 //Add 3 damage to unarmed attacks when worn - force = 5 //Deal 5 damage if hit with this item in hand - -/obj/item/clothing/gloves/knuckles/dexterity_check() - return 0 //Wearing these knuckles makes you less dexterious (so, for example, you can't use computers) - -/obj/item/clothing/gloves/knuckles/spiked - name = "spiked knuckles" - desc = "A pair of metal knuckles embedded with dull, but nonetheless painful spikes." - icon_state = "knuckles_spiked" - item_state = "knuckles_spiked" - - bonus_knockout = 3 - damage_added = 5 - force = 7 +/obj/item/clothing/gloves/captain + desc = "Regal blue gloves, with a nice gold trim. Swanky." + name = "captain's gloves" + icon_state = "captain" + item_state = "captain" + siemens_coefficient = 0 + _color = "captain" + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + species_fit = list("Vox") + +/obj/item/clothing/gloves/cyborg + desc = "beep boop borp" + name = "cyborg gloves" + icon_state = "black" + item_state = "black" + siemens_coefficient = 1.0 + species_fit = list("Vox") + +/obj/item/clothing/gloves/swat + desc = "These tactical gloves are somewhat fire and impact-resistant." + name = "\improper SWAT Gloves" + icon_state = "black" + item_state = "black" + siemens_coefficient = 0.6 + permeability_coefficient = 0.05 + + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + species_fit = list("Vox") + +/obj/item/clothing/gloves/combat //Combined effect of SWAT gloves and insulated gloves + desc = "These tactical gloves are somewhat fire and impact resistant." + name = "combat gloves" + icon_state = "black" + item_state = "black" + siemens_coefficient = 0 + permeability_coefficient = 0.05 + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + species_fit = list("Vox") + +/obj/item/clothing/gloves/latex + name = "latex gloves" + desc = "Sterile latex gloves." + icon_state = "latex" + item_state = "latex" + siemens_coefficient = 0.30 + permeability_coefficient = 0.01 + _color = "medical" //matches cmo stamp + species_fit = list("Vox") + +/obj/item/clothing/gloves/botanic_leather + desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin." + name = "botanist's leather gloves" + icon_state = "leather" + item_state = "leather" + permeability_coefficient = 0.9 + siemens_coefficient = 0.9 + species_fit = list("Vox") + +/obj/item/clothing/gloves/batmangloves + desc = "Used for handling all things bat related." + name = "batgloves" + icon_state = "bmgloves" + item_state = "bmgloves" + _color = "bmgloves" + species_fit = list("Vox") + +/obj/item/clothing/gloves/bikergloves + name = "Biker's Gloves" + icon_state = "biker-gloves" + item_state = "biker-gloves" + _color = "bikergloves" + +/obj/item/clothing/gloves/megagloves + desc = "Uncomfortably bulky armored gloves." + name = "DRN-001 Gloves" + icon_state = "megagloves" + item_state = "megagloves" + species_fit = list("Vox") + +/obj/item/clothing/gloves/protogloves + desc = "Funcionally identical to the DRN-001 model's, but in red!" + name = "Prototype Gloves" + icon_state = "protogloves" + item_state = "protogloves" + species_fit = list("Vox") + +/obj/item/clothing/gloves/megaxgloves + desc = "An upgrade to the DRN-001's gauntlets, retains the uncomfortable armor, but comes with white gloves!" + name = "Maverick Hunter gloves" + icon_state = "megaxgloves" + item_state = "megaxgloves" + species_fit = list("Vox") + +/obj/item/clothing/gloves/joegloves + desc = "Large grey gloves, very similar to the Prototype's." + name = "Sniper Gloves" + icon_state = "joegloves" + item_state = "joegloves" + species_fit = list("Vox") + +/obj/item/clothing/gloves/doomguy + desc = "" + name = "Doomguy's gloves" + icon_state = "doom" + item_state = "doom" + +/obj/item/clothing/gloves/knuckles + desc = "A pair of classic metal knuckles that are designed to increase tissue damage and bone fractures when punching." + name = "brass knuckles" + icon_state = "knuckles" + item_state = "knuckles" + + attack_verb = list("punched") + bonus_knockout = 2 //Slight knockout chance increase. + damage_added = 3 //Add 3 damage to unarmed attacks when worn + force = 5 //Deal 5 damage if hit with this item in hand + +/obj/item/clothing/gloves/knuckles/dexterity_check() + return 0 //Wearing these knuckles makes you less dexterious (so, for example, you can't use computers) + +/obj/item/clothing/gloves/knuckles/spiked + name = "spiked knuckles" + desc = "A pair of metal knuckles embedded with dull, but nonetheless painful spikes." + icon_state = "knuckles_spiked" + item_state = "knuckles_spiked" + + bonus_knockout = 3 + damage_added = 5 + force = 7 diff --git a/code/modules/clothing/gloves/stungloves.dm b/code/modules/clothing/gloves/stungloves.dm index 2899619424c..d5f82565040 100644 --- a/code/modules/clothing/gloves/stungloves.dm +++ b/code/modules/clothing/gloves/stungloves.dm @@ -1,61 +1,61 @@ -/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. - to_chat(user, "That won't work.")//i'm not putting my lips on that! - - ..() - return - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = W - if(!wired) - if(C.amount >= 2) - C.use(2) - wired = 1 - siemens_coefficient = 3.0 - to_chat(user, "You wrap some wires around [src].") - update_icon() - else - to_chat(user, "There is not enough wire to cover [src].") - else - to_chat(user, "[src] are already wired.") - - else if(istype(W, /obj/item/weapon/cell)) - if(!wired) - to_chat(user, "[src] need to be wired first.") - else if(!cell) - if(user.drop_item(W, src)) - cell = W - to_chat(user, "You attach a cell to [src].") - update_icon() - else - to_chat(user, "[src] already have a cell.") - - else if(istype(W, /obj/item/weapon/wirecutters)) - if(cell) - cell.updateicon() - cell.loc = get_turf(src.loc) - cell = null - to_chat(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) - to_chat(user, "You cut the wires away from [src].") - update_icon() - ..() - return - -/obj/item/clothing/gloves/update_icon() - ..() - overlays.len = 0 - if(wired) - overlays += "gloves_wire" - if(cell) - overlays += "gloves_cell" - if(wired && cell) - item_state = "stungloves" - else - item_state = initial(item_state) - if(ishuman(src.loc)) - var/mob/living/carbon/human/H = src.loc - H.update_inv_gloves() +/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. + to_chat(user, "That won't work.")//i'm not putting my lips on that! + + ..() + return + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = W + if(!wired) + if(C.amount >= 2) + C.use(2) + wired = 1 + siemens_coefficient = 3.0 + to_chat(user, "You wrap some wires around [src].") + update_icon() + else + to_chat(user, "There is not enough wire to cover [src].") + else + to_chat(user, "[src] are already wired.") + + else if(istype(W, /obj/item/weapon/cell)) + if(!wired) + to_chat(user, "[src] need to be wired first.") + else if(!cell) + if(user.drop_item(W, src)) + cell = W + to_chat(user, "You attach a cell to [src].") + update_icon() + else + to_chat(user, "[src] already have a cell.") + + else if(istype(W, /obj/item/weapon/wirecutters)) + if(cell) + cell.updateicon() + cell.loc = get_turf(src.loc) + cell = null + to_chat(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) + to_chat(user, "You cut the wires away from [src].") + update_icon() + ..() + return + +/obj/item/clothing/gloves/update_icon() + ..() + overlays.len = 0 + if(wired) + overlays += "gloves_wire" + if(cell) + overlays += "gloves_cell" + if(wired && cell) + item_state = "stungloves" + else + item_state = initial(item_state) + if(ishuman(src.loc)) + var/mob/living/carbon/human/H = src.loc + H.update_inv_gloves() diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm index 4900156de55..206466b5c85 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -1,120 +1,120 @@ - -//Hat Station 13 - -/obj/item/clothing/head/collectable - name = "collectable hat" - desc = "A rare collectable hat." - -/obj/item/clothing/head/collectable/petehat - name = "ultra rare Pete's hat!" - desc = "It smells faintly of plasma" - icon_state = "petehat" - -/obj/item/clothing/head/collectable/slime - name = "collectable slime cap!" - desc = "It just latches right in place!" - icon_state = "slime" - -/obj/item/clothing/head/collectable/xenom - name = "collectable xenomorph helmet!" - desc = "Hiss hiss hiss!" - icon_state = "xenos" - item_state = "xenos_helm" - -/obj/item/clothing/head/collectable/chef - name = "collectable chef's hat" - desc = "A rare Chef's Hat meant for hat collectors!" - icon_state = "chef" - item_state = "chef" - -/obj/item/clothing/head/collectable/paper - name = "collectable paper hat" - desc = "What looks like an ordinary paper hat, is actually a rare and valuable collector's edition paper hat. Keep away from water, fire and Librarians." - icon_state = "paper" - -/obj/item/clothing/head/collectable/tophat - name = "collectable top hat" - desc = "A top hat worn by only the most prestigious hat collectors." - icon_state = "tophat" - item_state = "that" - -/obj/item/clothing/head/collectable/captain - name = "collectable captain's hat" - desc = "A Collectable Hat that'll make you look just like a real comdom!" - icon_state = "captain" - item_state = "caphat" - -/obj/item/clothing/head/collectable/police - name = "collectable police officer's hat" - desc = "A Collectable Police Officer's Hat. This hat emphasizes that you are THE LAW." - icon_state = "policehelm" - -/obj/item/clothing/head/collectable/beret - name = "collectable beret" - desc = "A Collectable red Beret. It smells faintly of Garlic." - icon_state = "beret" - -/obj/item/clothing/head/collectable/welding - name = "collectable welding helmet" - desc = "A Collectable Welding Helmet. Now with 80% less lead! Not for actual welding. Any welding done while wearing this Helmet is done so at the owner's own risk!" - icon_state = "welding" - item_state = "welding" - species_fit = list("Vox") - -/obj/item/clothing/head/collectable/slime - name = "collectable slime hat" - desc = "Just like a real Brain Slug!" - icon_state = "headslime" - item_state = "headslime" - -/obj/item/clothing/head/collectable/flatcap - name = "collectable flat cap" - desc = "A Collectible farmer's Flat Cap!" - icon_state = "flat_cap" - item_state = "detective" - -/obj/item/clothing/head/collectable/pirate - name = "collectable pirate hat" - desc = "You'd make a great Dread Syndie Roberts!" - icon_state = "pirate" - item_state = "pirate" - -/obj/item/clothing/head/collectable/kitty - name = "collectable kitty ears" - desc = "The fur feels.....a bit too realistic." - icon_state = "kitty" - item_state = "kitty" - -/obj/item/clothing/head/collectable/rabbitears - name = "collectable rabbit ears" - desc = "Not as lucky as the feet!" - icon_state = "bunny" - item_state = "bunny" - -/obj/item/clothing/head/collectable/wizard - name = "collectable wizard's hat" - desc = "NOTE:Any magical powers gained from wearing this hat are purely coincidental." - icon_state = "wizard" - -/obj/item/clothing/head/collectable/hardhat - name = "collectable hard hat" - desc = "WARNING! Offers no real protection, or luminosity, but it is damn fancy!" - icon_state = "hardhat0_yellow" - item_state = "hardhat0_yellow" - -/obj/item/clothing/head/collectable/HoS - name = "collectable HoS hat" - desc = "Now you can beat prisoners, set silly sentences and arrest for no reason too!" - icon_state = "hoscap" - -/obj/item/clothing/head/collectable/thunderdome - name = "collectable Thunderdome helmet" - desc = "Go Red! I mean Green! I mean Red! No Green!" - icon_state = "thunderdome" - item_state = "thunderdome" - -/obj/item/clothing/head/collectable/swat - name = "collectable SWAT helmet" - desc = "Now you can be in the Deathsquad too!" - icon_state = "swat" + +//Hat Station 13 + +/obj/item/clothing/head/collectable + name = "collectable hat" + desc = "A rare collectable hat." + +/obj/item/clothing/head/collectable/petehat + name = "ultra rare Pete's hat!" + desc = "It smells faintly of plasma" + icon_state = "petehat" + +/obj/item/clothing/head/collectable/slime + name = "collectable slime cap!" + desc = "It just latches right in place!" + icon_state = "slime" + +/obj/item/clothing/head/collectable/xenom + name = "collectable xenomorph helmet!" + desc = "Hiss hiss hiss!" + icon_state = "xenos" + item_state = "xenos_helm" + +/obj/item/clothing/head/collectable/chef + name = "collectable chef's hat" + desc = "A rare Chef's Hat meant for hat collectors!" + icon_state = "chef" + item_state = "chef" + +/obj/item/clothing/head/collectable/paper + name = "collectable paper hat" + desc = "What looks like an ordinary paper hat, is actually a rare and valuable collector's edition paper hat. Keep away from water, fire and Librarians." + icon_state = "paper" + +/obj/item/clothing/head/collectable/tophat + name = "collectable top hat" + desc = "A top hat worn by only the most prestigious hat collectors." + icon_state = "tophat" + item_state = "that" + +/obj/item/clothing/head/collectable/captain + name = "collectable captain's hat" + desc = "A Collectable Hat that'll make you look just like a real comdom!" + icon_state = "captain" + item_state = "caphat" + +/obj/item/clothing/head/collectable/police + name = "collectable police officer's hat" + desc = "A Collectable Police Officer's Hat. This hat emphasizes that you are THE LAW." + icon_state = "policehelm" + +/obj/item/clothing/head/collectable/beret + name = "collectable beret" + desc = "A Collectable red Beret. It smells faintly of Garlic." + icon_state = "beret" + +/obj/item/clothing/head/collectable/welding + name = "collectable welding helmet" + desc = "A Collectable Welding Helmet. Now with 80% less lead! Not for actual welding. Any welding done while wearing this Helmet is done so at the owner's own risk!" + icon_state = "welding" + item_state = "welding" + species_fit = list("Vox") + +/obj/item/clothing/head/collectable/slime + name = "collectable slime hat" + desc = "Just like a real Brain Slug!" + icon_state = "headslime" + item_state = "headslime" + +/obj/item/clothing/head/collectable/flatcap + name = "collectable flat cap" + desc = "A Collectible farmer's Flat Cap!" + icon_state = "flat_cap" + item_state = "detective" + +/obj/item/clothing/head/collectable/pirate + name = "collectable pirate hat" + desc = "You'd make a great Dread Syndie Roberts!" + icon_state = "pirate" + item_state = "pirate" + +/obj/item/clothing/head/collectable/kitty + name = "collectable kitty ears" + desc = "The fur feels.....a bit too realistic." + icon_state = "kitty" + item_state = "kitty" + +/obj/item/clothing/head/collectable/rabbitears + name = "collectable rabbit ears" + desc = "Not as lucky as the feet!" + icon_state = "bunny" + item_state = "bunny" + +/obj/item/clothing/head/collectable/wizard + name = "collectable wizard's hat" + desc = "NOTE:Any magical powers gained from wearing this hat are purely coincidental." + icon_state = "wizard" + +/obj/item/clothing/head/collectable/hardhat + name = "collectable hard hat" + desc = "WARNING! Offers no real protection, or luminosity, but it is damn fancy!" + icon_state = "hardhat0_yellow" + item_state = "hardhat0_yellow" + +/obj/item/clothing/head/collectable/HoS + name = "collectable HoS hat" + desc = "Now you can beat prisoners, set silly sentences and arrest for no reason too!" + icon_state = "hoscap" + +/obj/item/clothing/head/collectable/thunderdome + name = "collectable Thunderdome helmet" + desc = "Go Red! I mean Green! I mean Red! No Green!" + icon_state = "thunderdome" + item_state = "thunderdome" + +/obj/item/clothing/head/collectable/swat + name = "collectable SWAT helmet" + desc = "Now you can be in the Deathsquad too!" + icon_state = "swat" item_state = "swat" \ No newline at end of file diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 42b11f7bea7..c8d803dac7a 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -1,228 +1,228 @@ -/obj/item/clothing/head/helmet - name = "helmet" - desc = "Standard Security gear. Protects the head from impacts." - icon_state = "helmet" - flags = FPRINT - item_state = "helmet" - armor = list(melee = 50, bullet = 15, laser = 50,energy = 10, bomb = 25, bio = 0, rad = 0) - body_parts_covered = HEAD | EYES | EARS - flags_inv = HIDEEARS | HIDEEYES | HIDEHEADHAIR - cold_protection = HEAD - min_cold_protection_temperature = HELMET_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = HEAD - max_heat_protection_temperature = HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.7 - -/obj/item/clothing/head/helmet/warden - name = "warden's hat" - desc = "It's a special helmet issued to the Warden of a securiy force. Protects the head from impacts." - icon_state = "policehelm" - flags_inv = 0 - -/obj/item/clothing/head/helmet/riot - name = "riot helmet" - desc = "It's a helmet specifically designed to protect against close range attacks." - icon_state = "riot" - item_state = "helmet" - flags = FPRINT - armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) - flags_inv = HIDEEARS | HIDEHEADHAIR - siemens_coefficient = 0.7 - eyeprot = 1 - -/obj/item/clothing/head/helmet/swat - name = "\improper SWAT helmet" - desc = "They're often used by highly trained Swat Members." - icon_state = "swat" - flags = FPRINT - item_state = "swat" - armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) - flags_inv = HIDEEARS|HIDEEYES|HIDEHEADHAIR - cold_protection = HEAD - species_fit = list("Vox") - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - pressure_resistance = 200 * ONE_ATMOSPHERE - siemens_coefficient = 0.5 - eyeprot = 1 - -/obj/item/clothing/head/helmet/swat/dredd - name = "Judge Helmet" - desc = "Judge, Jury, and Executioner." - icon_state = "dredd-helmet" - item_state = "dredd-helmet" - species_fit = list() - -/obj/item/clothing/head/helmet/thunderdome - name = "\improper Thunderdome helmet" - desc = "'Let the battle commence!'" - icon_state = "thunderdome" - flags = FPRINT - flags_inv = HIDEEARS | HIDEHEADHAIR - item_state = "thunderdome" - armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/gladiator - name = "gladiator helmet" - desc = "Ave, Imperator, morituri te salutant." - icon_state = "gladiator" - flags = FPRINT - body_parts_covered = FULL_HEAD - item_state = "gladiator" - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/roman - name = "roman helmet" - desc = "An ancient helmet made of bronze and leather." - armor = list(melee = 20, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) - icon_state = "roman" - item_state = "roman" - -/obj/item/clothing/head/helmet/roman/legionaire - name = "roman legionaire helmet" - desc = "An ancient helmet made of bronze and leather. Has a red crest on top of it." - armor = list(melee = 25, bullet = 0, laser = 25, energy = 10, bomb = 10, bio = 0, rad = 0) - icon_state = "roman_c" - item_state = "roman_c" - -/obj/item/clothing/head/helmet/hopcap - name = "Head of Personnel's Cap" - desc = "Papers, Please" - armor = list(melee = 25, bullet = 0, laser = 15, energy = 10, bomb = 5, bio = 0, rad = 0) - item_state = "hopcap" - icon_state = "hopcap" - flags_inv = 0 - -/obj/item/clothing/head/helmet/aviatorhelmet - name = "Aviator Helmet" - desc = "Help the Bombardier!" - armor = list(melee = 25, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) - item_state = "aviator_helmet" - icon_state = "aviator_helmet" - flags_inv = HIDEEARS|HIDEHAIR - species_restricted = list("exclude","Vox") - -/obj/item/clothing/head/helmet/piratelord - name = "pirate lord's helmet" - desc = "The headwear of an all powerful and bloodthirsty pirate lord. Simply looking at it sends chills down your spine." - armor = list(melee = 75, bullet = 75, laser = 75,energy = 75, bomb = 75, bio = 100, rad = 90) - icon_state = "piratelord" - -/obj/item/clothing/head/helmet/biker - name = "Biker's Helmet" - desc = "This helmet should protect you from russians and masked vigilantes." - armor = list(melee = 25, bullet = 15, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) - icon_state = "biker_helmet" - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR - body_parts_covered = FULL_HEAD - -/obj/item/clothing/head/helmet/richard - name = "Richard" - desc = "Do you like hurting people?" - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) - icon_state = "richard" - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR - body_parts_covered = FULL_HEAD - -/obj/item/clothing/head/helmet/megahelmet - name = "DRN-001 Helmet" - desc = "The helmet of the DRN-001 model. A simple, sturdy blue helmet." - icon_state = "megahelmet" - flags = FPRINT - body_parts_covered = HEAD|EARS - item_state = "megahelmet" - flags_inv = HIDEEARS|HIDEHAIR - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/protohelmet - name = "Prototype Helmet" - desc = "Shiny red helmet with white accents and a built in shaded visor that does absolutely nothing, nothing but look rad as hell." - icon_state = "protohelmet" - flags = FPRINT - body_parts_covered = HEAD|EYES|EARS - item_state = "protohelmet" - flags_inv = HIDEEARS|HIDEHAIR|HIDEEYES - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/breakhelmet - name = "Broken Helmet" - desc = "The product of twelve years of work by an eccentric and brilliant loner. A helmet belonging to the perfect man; an unbeatable machine." - icon_state = "breakhelmet" - flags = FPRINT - body_parts_covered = FULL_HEAD - item_state = "breakhelmet" - flags_inv = HIDEMASK|HIDEEARS|HIDEHAIR|HIDEEYES - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/megaxhelmet - name = "Maverick Hunter Helmet" - desc = "Heavily armored upgrade to the DRN-001 model's helmet, now comes with a pointless red crystal thing!" - icon_state = "megaxhelmet" - flags = FPRINT - body_parts_covered = HEAD|EARS - item_state = "megaxhelmet" - flags_inv = HIDEEARS|HIDEHAIR - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/volnutthelmet - name = "Digouter Helmet" - desc = "A sturdy helmet, fortified to protect from falling rocks or buster shots" - icon_state = "volnutthelmet" - flags = FPRINT - body_parts_covered = HEAD|EARS - item_state = "volnutthelmet" - armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0) - flags_inv = HIDEEARS|HIDEHAIR - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/joehelmet - name = "Sniper Helmet" - desc = "Helmet belonging to one of the many mass produced 'Joe' type robots." - icon_state = "joehelmet" - flags = FPRINT - body_parts_covered = FULL_HEAD - item_state = "joehelmet" - flags_inv = HIDEMASK|HIDEEARS|HIDEHAIR|HIDEEYES - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/doomguy - name = "Doomguy's helmet" - desc = "" - icon_state = "doom" - flags = FPRINT - body_parts_covered = HEAD|EARS - item_state = "doom" - armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0) - flags_inv = HIDEEARS|HIDEHAIR - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/knight - name = "medieval helmet" - desc = "A classic metal helmet." - icon_state = "knight_green" - item_state = "knight_green" - armor = list(melee = 20, bullet = 5, laser = 2,energy = 2, bomb = 2, bio = 2, rad = 0) - flags = FPRINT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/knight/blue - icon_state = "knight_blue" - item_state = "knight_blue" - -/obj/item/clothing/head/helmet/knight/yellow - icon_state = "knight_yellow" - item_state = "knight_yellow" - -/obj/item/clothing/head/helmet/knight/red - icon_state = "knight_red" - item_state = "knight_red" - -/obj/item/clothing/head/helmet/knight/templar - name = "crusader helmet" - desc = "Deus Vult." - icon_state = "knight_templar" +/obj/item/clothing/head/helmet + name = "helmet" + desc = "Standard Security gear. Protects the head from impacts." + icon_state = "helmet" + flags = FPRINT + item_state = "helmet" + armor = list(melee = 50, bullet = 15, laser = 50,energy = 10, bomb = 25, bio = 0, rad = 0) + body_parts_covered = HEAD | EYES | EARS + flags_inv = HIDEEARS | HIDEEYES | HIDEHEADHAIR + cold_protection = HEAD + min_cold_protection_temperature = HELMET_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = HEAD + max_heat_protection_temperature = HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.7 + +/obj/item/clothing/head/helmet/warden + name = "warden's hat" + desc = "It's a special helmet issued to the Warden of a securiy force. Protects the head from impacts." + icon_state = "policehelm" + flags_inv = 0 + +/obj/item/clothing/head/helmet/riot + name = "riot helmet" + desc = "It's a helmet specifically designed to protect against close range attacks." + icon_state = "riot" + item_state = "helmet" + flags = FPRINT + armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) + flags_inv = HIDEEARS | HIDEHEADHAIR + siemens_coefficient = 0.7 + eyeprot = 1 + +/obj/item/clothing/head/helmet/swat + name = "\improper SWAT helmet" + desc = "They're often used by highly trained Swat Members." + icon_state = "swat" + flags = FPRINT + item_state = "swat" + armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) + flags_inv = HIDEEARS|HIDEEYES|HIDEHEADHAIR + cold_protection = HEAD + species_fit = list("Vox") + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + pressure_resistance = 200 * ONE_ATMOSPHERE + siemens_coefficient = 0.5 + eyeprot = 1 + +/obj/item/clothing/head/helmet/swat/dredd + name = "Judge Helmet" + desc = "Judge, Jury, and Executioner." + icon_state = "dredd-helmet" + item_state = "dredd-helmet" + species_fit = list() + +/obj/item/clothing/head/helmet/thunderdome + name = "\improper Thunderdome helmet" + desc = "'Let the battle commence!'" + icon_state = "thunderdome" + flags = FPRINT + flags_inv = HIDEEARS | HIDEHEADHAIR + item_state = "thunderdome" + armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/gladiator + name = "gladiator helmet" + desc = "Ave, Imperator, morituri te salutant." + icon_state = "gladiator" + flags = FPRINT + body_parts_covered = FULL_HEAD + item_state = "gladiator" + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/roman + name = "roman helmet" + desc = "An ancient helmet made of bronze and leather." + armor = list(melee = 20, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) + icon_state = "roman" + item_state = "roman" + +/obj/item/clothing/head/helmet/roman/legionaire + name = "roman legionaire helmet" + desc = "An ancient helmet made of bronze and leather. Has a red crest on top of it." + armor = list(melee = 25, bullet = 0, laser = 25, energy = 10, bomb = 10, bio = 0, rad = 0) + icon_state = "roman_c" + item_state = "roman_c" + +/obj/item/clothing/head/helmet/hopcap + name = "Head of Personnel's Cap" + desc = "Papers, Please" + armor = list(melee = 25, bullet = 0, laser = 15, energy = 10, bomb = 5, bio = 0, rad = 0) + item_state = "hopcap" + icon_state = "hopcap" + flags_inv = 0 + +/obj/item/clothing/head/helmet/aviatorhelmet + name = "Aviator Helmet" + desc = "Help the Bombardier!" + armor = list(melee = 25, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) + item_state = "aviator_helmet" + icon_state = "aviator_helmet" + flags_inv = HIDEEARS|HIDEHAIR + species_restricted = list("exclude","Vox") + +/obj/item/clothing/head/helmet/piratelord + name = "pirate lord's helmet" + desc = "The headwear of an all powerful and bloodthirsty pirate lord. Simply looking at it sends chills down your spine." + armor = list(melee = 75, bullet = 75, laser = 75,energy = 75, bomb = 75, bio = 100, rad = 90) + icon_state = "piratelord" + +/obj/item/clothing/head/helmet/biker + name = "Biker's Helmet" + desc = "This helmet should protect you from russians and masked vigilantes." + armor = list(melee = 25, bullet = 15, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) + icon_state = "biker_helmet" + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR + body_parts_covered = FULL_HEAD + +/obj/item/clothing/head/helmet/richard + name = "Richard" + desc = "Do you like hurting people?" + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) + icon_state = "richard" + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR + body_parts_covered = FULL_HEAD + +/obj/item/clothing/head/helmet/megahelmet + name = "DRN-001 Helmet" + desc = "The helmet of the DRN-001 model. A simple, sturdy blue helmet." + icon_state = "megahelmet" + flags = FPRINT + body_parts_covered = HEAD|EARS + item_state = "megahelmet" + flags_inv = HIDEEARS|HIDEHAIR + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/protohelmet + name = "Prototype Helmet" + desc = "Shiny red helmet with white accents and a built in shaded visor that does absolutely nothing, nothing but look rad as hell." + icon_state = "protohelmet" + flags = FPRINT + body_parts_covered = HEAD|EYES|EARS + item_state = "protohelmet" + flags_inv = HIDEEARS|HIDEHAIR|HIDEEYES + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/breakhelmet + name = "Broken Helmet" + desc = "The product of twelve years of work by an eccentric and brilliant loner. A helmet belonging to the perfect man; an unbeatable machine." + icon_state = "breakhelmet" + flags = FPRINT + body_parts_covered = FULL_HEAD + item_state = "breakhelmet" + flags_inv = HIDEMASK|HIDEEARS|HIDEHAIR|HIDEEYES + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/megaxhelmet + name = "Maverick Hunter Helmet" + desc = "Heavily armored upgrade to the DRN-001 model's helmet, now comes with a pointless red crystal thing!" + icon_state = "megaxhelmet" + flags = FPRINT + body_parts_covered = HEAD|EARS + item_state = "megaxhelmet" + flags_inv = HIDEEARS|HIDEHAIR + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/volnutthelmet + name = "Digouter Helmet" + desc = "A sturdy helmet, fortified to protect from falling rocks or buster shots" + icon_state = "volnutthelmet" + flags = FPRINT + body_parts_covered = HEAD|EARS + item_state = "volnutthelmet" + armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0) + flags_inv = HIDEEARS|HIDEHAIR + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/joehelmet + name = "Sniper Helmet" + desc = "Helmet belonging to one of the many mass produced 'Joe' type robots." + icon_state = "joehelmet" + flags = FPRINT + body_parts_covered = FULL_HEAD + item_state = "joehelmet" + flags_inv = HIDEMASK|HIDEEARS|HIDEHAIR|HIDEEYES + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/doomguy + name = "Doomguy's helmet" + desc = "" + icon_state = "doom" + flags = FPRINT + body_parts_covered = HEAD|EARS + item_state = "doom" + armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0) + flags_inv = HIDEEARS|HIDEHAIR + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/knight + name = "medieval helmet" + desc = "A classic metal helmet." + icon_state = "knight_green" + item_state = "knight_green" + armor = list(melee = 20, bullet = 5, laser = 2,energy = 2, bomb = 2, bio = 2, rad = 0) + flags = FPRINT + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/knight/blue + icon_state = "knight_blue" + item_state = "knight_blue" + +/obj/item/clothing/head/helmet/knight/yellow + icon_state = "knight_yellow" + item_state = "knight_yellow" + +/obj/item/clothing/head/helmet/knight/red + icon_state = "knight_red" + item_state = "knight_red" + +/obj/item/clothing/head/helmet/knight/templar + name = "crusader helmet" + desc = "Deus Vult." + icon_state = "knight_templar" item_state = "knight_templar" \ No newline at end of file diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 0b802fe64bb..20e75697056 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -1,85 +1,85 @@ - -//Bartender -/obj/item/clothing/head/chefhat - name = "chef's hat" - desc = "It's a hat used by chefs to keep hair out of your food. Judging by the food in the mess, they don't work." - icon_state = "chef" - item_state = "chef" - desc = "The commander in chef's head wear." - flags = FPRINT - siemens_coefficient = 0.9 - -//Captain: This probably shouldn't be space-worthy -/obj/item/clothing/head/caphat - name = "captain's hat" - icon_state = "captain" - desc = "It's good being the king." - flags = FPRINT - item_state = "caphat" - siemens_coefficient = 0.9 - -//Captain: This probably shouldn't be space-worthy -/obj/item/clothing/head/helmet/cap - name = "captain's cap" - desc = "You fear to wear it for the negligence it brings." - icon_state = "capcap" - flags = FPRINT - flags_inv = 0 - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.9 - -//Chaplain -/obj/item/clothing/head/chaplain_hood - name = "chaplain's hood" - desc = "It's hood that covers the head. It keeps you warm during the space winters." - icon_state = "chaplain_hood" - flags = FPRINT - flags_inv = HIDEHAIR - body_parts_covered = HEAD|EARS - siemens_coefficient = 0.9 - -//Chaplain -/obj/item/clothing/head/nun_hood - name = "nun hood" - desc = "Maximum piety in this star system." - icon_state = "nun_hood" - flags = FPRINT - flags_inv = HIDEHAIR - body_parts_covered = HEAD|EARS - siemens_coefficient = 0.9 - -//Mime -/obj/item/clothing/head/beret - name = "beret" - desc = "A beret, an artists favorite headwear." - icon_state = "beret" - flags = FPRINT - siemens_coefficient = 0.9 - -//Security -/obj/item/clothing/head/beret/sec - name = "security beret" - desc = "A beret with the security insignia emblazoned on it. For officers that are more inclined towards style than safety." - icon_state = "beret_badge" - flags = FPRINT - -//Medical -/obj/item/clothing/head/surgery - name = "surgical cap" - desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs." - icon_state = "surgcap_blue" - flags = FPRINT - flags_inv = HIDEHEADHAIR - -/obj/item/clothing/head/surgery/purple - desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is deep purple." - icon_state = "surgcap_purple" - -/obj/item/clothing/head/surgery/blue - desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is baby blue." - icon_state = "surgcap_blue" - -/obj/item/clothing/head/surgery/green - desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is dark green." - icon_state = "surgcap_green" + +//Bartender +/obj/item/clothing/head/chefhat + name = "chef's hat" + desc = "It's a hat used by chefs to keep hair out of your food. Judging by the food in the mess, they don't work." + icon_state = "chef" + item_state = "chef" + desc = "The commander in chef's head wear." + flags = FPRINT + siemens_coefficient = 0.9 + +//Captain: This probably shouldn't be space-worthy +/obj/item/clothing/head/caphat + name = "captain's hat" + icon_state = "captain" + desc = "It's good being the king." + flags = FPRINT + item_state = "caphat" + siemens_coefficient = 0.9 + +//Captain: This probably shouldn't be space-worthy +/obj/item/clothing/head/helmet/cap + name = "captain's cap" + desc = "You fear to wear it for the negligence it brings." + icon_state = "capcap" + flags = FPRINT + flags_inv = 0 + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.9 + +//Chaplain +/obj/item/clothing/head/chaplain_hood + name = "chaplain's hood" + desc = "It's hood that covers the head. It keeps you warm during the space winters." + icon_state = "chaplain_hood" + flags = FPRINT + flags_inv = HIDEHAIR + body_parts_covered = HEAD|EARS + siemens_coefficient = 0.9 + +//Chaplain +/obj/item/clothing/head/nun_hood + name = "nun hood" + desc = "Maximum piety in this star system." + icon_state = "nun_hood" + flags = FPRINT + flags_inv = HIDEHAIR + body_parts_covered = HEAD|EARS + siemens_coefficient = 0.9 + +//Mime +/obj/item/clothing/head/beret + name = "beret" + desc = "A beret, an artists favorite headwear." + icon_state = "beret" + flags = FPRINT + siemens_coefficient = 0.9 + +//Security +/obj/item/clothing/head/beret/sec + name = "security beret" + desc = "A beret with the security insignia emblazoned on it. For officers that are more inclined towards style than safety." + icon_state = "beret_badge" + flags = FPRINT + +//Medical +/obj/item/clothing/head/surgery + name = "surgical cap" + desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs." + icon_state = "surgcap_blue" + flags = FPRINT + flags_inv = HIDEHEADHAIR + +/obj/item/clothing/head/surgery/purple + desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is deep purple." + icon_state = "surgcap_purple" + +/obj/item/clothing/head/surgery/blue + desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is baby blue." + icon_state = "surgcap_blue" + +/obj/item/clothing/head/surgery/green + desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is dark green." + icon_state = "surgcap_green" diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index c2c41ba5dd2..baa7db717b1 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -1,397 +1,397 @@ - - -/obj/item/clothing/head/centhat - name = "\improper CentComm. hat" - icon_state = "centcom" - desc = "It's good to be emperor." - flags = FPRINT - item_state = "centhat" - siemens_coefficient = 0.9 - -/obj/item/clothing/head/hairflower - name = "hair flower pin" - icon_state = "hairflower" - desc = "Smells nice." - item_state = "hairflower" - flags = FPRINT - -/obj/item/clothing/head/powdered_wig - name = "powdered wig" - desc = "A powdered wig." - icon_state = "pwig" - item_state = "pwig" - -/obj/item/clothing/head/that - name = "top-hat" - desc = "It's an amish looking hat." - icon_state = "tophat" - item_state = "that" - flags = FPRINT - siemens_coefficient = 0.9 - -/obj/item/clothing/head/redcoat - name = "redcoat's hat" - icon_state = "redcoat" - desc = "'I guess it's a redhead.'" - flags = FPRINT - -/obj/item/clothing/head/mailman - name = "mailman's hat" - icon_state = "mailman" - desc = "'Right-on-time' mail service head wear." - flags = FPRINT - -/obj/item/clothing/head/plaguedoctorhat - name = "plague doctor's hat" - desc = "These were once used by Plague doctors. They're pretty much useless." - icon_state = "plaguedoctor" - flags = FPRINT - permeability_coefficient = 0.01 - siemens_coefficient = 0.9 - -/obj/item/clothing/head/hasturhood - name = "hastur's hood" - desc = "It's unspeakably stylish" - icon_state = "hasturhood" - flags = FPRINT - flags_inv = HIDEHAIR - body_parts_covered = HEAD|EARS - -/obj/item/clothing/head/nursehat - name = "nurse's hat" - desc = "It allows quick identification of trained medical personnel." - icon_state = "nursehat" - flags = FPRINT - siemens_coefficient = 0.9 - -/obj/item/clothing/head/syndicatefake - name = "red space-helmet replica" - icon_state = "syndicate" - item_state = "syndicate" - desc = "A plastic replica of a syndicate agent's space helmet, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!" - flags = FPRINT - body_parts_covered = FULL_HEAD - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/cueball - name = "cueball helmet" - desc = "A large, featureless white orb mean to be worn on your head. How do you even see out of this thing?" - icon_state = "cueball" - flags = FPRINT - body_parts_covered = FULL_HEAD - item_state="cueball" - flags_inv = HIDEHAIR - -/obj/item/clothing/head/that - name = "sturdy top-hat" - desc = "It's an amish looking armored top hat." - icon_state = "tophat" - item_state = "that" - flags = FPRINT - flags_inv = 0 - - -/obj/item/clothing/head/greenbandana - name = "green bandana" - desc = "It's a green bandana with some fine nanotech lining." - icon_state = "greenbandana" - item_state = "greenbandana" - flags = FPRINT - flags_inv = 0 - -/obj/item/clothing/head/cardborg - name = "cardborg helmet" - desc = "A helmet made out of a box." - icon_state = "cardborg_h" - item_state = "cardborg_h" - flags = FPRINT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = FULL_HEAD - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - -/obj/item/clothing/head/justice - name = "justice hat" - desc = "fight for what's righteous!" - icon_state = "justicered" - item_state = "justicered" - flags = FPRINT - flags_inv = HIDEHAIR - body_parts_covered = HEAD|EYES|MOUTH - -/obj/item/clothing/head/justice/blue - icon_state = "justiceblue" - item_state = "justiceblue" - -/obj/item/clothing/head/justice/yellow - icon_state = "justiceyellow" - item_state = "justiceyellow" - -/obj/item/clothing/head/justice/green - icon_state = "justicegreen" - item_state = "justicegreen" - -/obj/item/clothing/head/justice/pink - icon_state = "justicepink" - item_state = "justicepink" - -/obj/item/clothing/head/rabbitears - name = "rabbit ears" - desc = "Wearing these makes you looks useless, and only good for your sex appeal." - icon_state = "bunny" - flags = FPRINT - -/obj/item/clothing/head/flatcap - name = "flat cap" - desc = "A working man's cap." - icon_state = "flat_cap" - item_state = "detective" - siemens_coefficient = 0.9 - -/obj/item/clothing/head/pirate - name = "pirate hat" - desc = "Yarr." - icon_state = "pirate" - item_state = "pirate" - -/obj/item/clothing/head/hgpiratecap - name = "pirate hat" - desc = "Yarr." - icon_state = "hgpiratecap" - item_state = "hgpiratecap" - -/obj/item/clothing/head/bandana - name = "pirate bandana" - desc = "Yarr." - icon_state = "bandana" - item_state = "bandana" - -//stylish bs12 hats - -/obj/item/clothing/head/bowlerhat - name = "bowler hat" - icon_state = "bowler_hat" - item_state = "bowler_hat" - desc = "For that industrial age look." - flags = FPRINT - -/obj/item/clothing/head/beaverhat - name = "beaver hat" - icon_state = "beaver_hat" - item_state = "beaver_hat" - desc = "Like a top hat, but made of beavers." - flags = FPRINT - -/obj/item/clothing/head/boaterhat - name = "boater hat" - icon_state = "boater_hat" - item_state = "boater_hat" - desc = "Goes well with celery." - flags = FPRINT - -/obj/item/clothing/head/squatter_hat - name = "slav squatter hat" - icon_state = "squatter_hat" - item_state = "squatter_hat" - desc = "Cyka blyat." - flags = FPRINT - -/obj/item/clothing/head/fedora - name = "\improper fedora" - icon_state = "fedora" - item_state = "fedora" - desc = "A great hat ruined by being within fifty yards of you." - flags = FPRINT - -/obj/item/clothing/head/fedora/OnMobLife(var/mob/living/carbon/human/wearer) - if(!istype(wearer)) return - if(wearer.head == src) - if(prob(1)) - to_chat(wearer, "You feel positively euphoric!") - -//TIPS FEDORA -/obj/item/clothing/head/fedora/verb/tip_fedora() - set name = "Tip Fedora" - set category = "Object" - set desc = "Show that CIS SCUM who's boss." - - usr.visible_message("[usr] tips his fedora.", "You tip your fedora.") - -/obj/item/clothing/head/fez - name = "\improper fez" - icon_state = "fez" - item_state = "fez" - desc = "Put it on your monkey, make lots of cash money." - flags = FPRINT - -//end bs12 hats - -/obj/item/clothing/head/witchwig - name = "witch costume wig" - desc = "Eeeee~heheheheheheh!" - icon_state = "witch" - item_state = "witch" - flags = FPRINT - flags_inv = HIDEHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/chicken - name = "chicken suit head" - desc = "Bkaw!" - icon_state = "chickenhead" - item_state = "chickensuit" - flags = FPRINT - flags_inv = HIDEHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/bearpelt - name = "cheap bear pelt hat" - desc = "Not as fuzzy as the real thing." - icon_state = "bearpelt" - item_state = "bearpelt" - flags = FPRINT - flags_inv = HIDEHEADHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/bearpelt/real - name = "bear pelt hat" - desc = "Now that's what I call fuzzy." - -/obj/item/clothing/head/xenos - name = "xenos helmet" - icon_state = "xenos" - item_state = "xenos_helm" - desc = "A helmet made out of chitinous alien hide." - flags = FPRINT - body_parts_covered = FULL_HEAD - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/batman - name = "bathelmet" - desc = "No one cares who you are until you put on the mask." - icon_state = "bmhead" - item_state = "bmhead" - flags = FPRINT - flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR - body_parts_covered = HEAD|EYES|EARS - -/obj/item/clothing/head/stalhelm - name = "Stalhelm" - desc = "Ein Helm, um die Nazi-Interesse an fremden Raumstationen zu sichern." - icon_state = "stalhelm" - item_state = "stalhelm" - flags = FPRINT - flags_inv = HIDEEARS|HIDEHEADHAIR - -/obj/item/clothing/head/panzer - name = "Panzer Cap" - desc = "Ein Hut passen nur für die größten Tanks." - icon_state = "panzercap" - item_state = "panzercap" - flags = FPRINT - -/obj/item/clothing/head/naziofficer - name = "Officer Cap" - desc = "Ein Hut von Offizieren in der Nazi-Partei getragen." - icon_state = "officercap" - item_state = "officercap" - flags = FPRINT - flags_inv = HIDEEARS|HIDEHEADHAIR - -/obj/item/clothing/head/russobluecamohat - name = "russian blue camo beret" - desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food." - icon_state = "russobluecamohat" - item_state = "russobluecamohat" - flags = FPRINT - -/obj/item/clothing/head/russofurhat - name = "russian fur hat" - desc = "Russian winter got you down? Maybe your enemy, but not you!" - icon_state = "russofurhat" - item_state = "russofurhat" - flags = FPRINT - flags_inv = HIDEEARS|HIDEHEADHAIR - -/obj/item/clothing/head/lordadmiralhat - name = "lord admiral's hat" - desc = "A hat suitable for any man of high and exalted rank." - icon_state = "lordadmiralhat" - item_state = "lordadmiralhat" - -/obj/item/clothing/head/jesterhat - name = "jester hat" - desc = "A hat fit for a fool." - icon_state = "jesterhat" - item_state = "jesterhat" - flags = FPRINT - flags_inv = HIDEEARS|HIDEHEADHAIR - -/obj/item/clothing/head/libertyhat - name = "liberty top hat" - desc = "Show everyone just how patriotic you are." - icon_state = "libertyhat" - item_state = "libertyhat" - flags = FPRINT - -/obj/item/clothing/head/maidhat - name = "maid headband" - desc = "Do these even do anything besides look cute?" - icon_state = "maidhat" - item_state = "maidhat" - flags = FPRINT - -/obj/item/clothing/head/maidhat - name = "maid headband" - desc = "Do these even do anything besides look cute?" - icon_state = "maidhat" - item_state = "maidhat" - flags = FPRINT - -/obj/item/clothing/head/mitre - name = "mitre" - desc = "A funny hat worn by extremely boring people." - icon_state = "mitre" - item_state = "mitre" - -/obj/item/clothing/head/clownpiece - name = "Clownpiece's jester hat" - desc = "A purple polka-dotted jester's hat with yellow pompons." - icon_state = "clownpiece" - item_state = "clownpiece" - -/obj/item/clothing/head/headband - name = "head band" - desc = "You wear this around your head." - icon_state = "headband" - item_state = "headband" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/metalgear.dmi', "right_hand" = 'icons/mob/in-hand/right/metalgear.dmi') - -/obj/item/clothing/head/cowboy - name = "cowboy hat" - desc = "Pefect for the closet botanist." - icon_state = "cowboy" - item_state = "cowboy" - -/obj/item/clothing/head/christmas/santahat/red - name = "red santa hat" - desc = "Not quite as magical as the real thing, but it flops over one ear and itches your head just the same" - icon_state = "santahatred" - item_state = "santahatred" - -/obj/item/clothing/head/christmas/santahat/green - name = "green santa hat" - desc = "Not quite as magical as the real thing, but it flops over one ear and itches your head just the same" - icon_state = "santahatgreen" - item_state = "santahatgreen" - -/obj/item/clothing/head/festive - name = "festive paper hat" - icon_state = "xmashat" - item_state = "xmashat" - desc = "A crappy paper hat that you are REQUIRED to wear." - flags_inv = 0 - flags = FPRINT + + +/obj/item/clothing/head/centhat + name = "\improper CentComm. hat" + icon_state = "centcom" + desc = "It's good to be emperor." + flags = FPRINT + item_state = "centhat" + siemens_coefficient = 0.9 + +/obj/item/clothing/head/hairflower + name = "hair flower pin" + icon_state = "hairflower" + desc = "Smells nice." + item_state = "hairflower" + flags = FPRINT + +/obj/item/clothing/head/powdered_wig + name = "powdered wig" + desc = "A powdered wig." + icon_state = "pwig" + item_state = "pwig" + +/obj/item/clothing/head/that + name = "top-hat" + desc = "It's an amish looking hat." + icon_state = "tophat" + item_state = "that" + flags = FPRINT + siemens_coefficient = 0.9 + +/obj/item/clothing/head/redcoat + name = "redcoat's hat" + icon_state = "redcoat" + desc = "'I guess it's a redhead.'" + flags = FPRINT + +/obj/item/clothing/head/mailman + name = "mailman's hat" + icon_state = "mailman" + desc = "'Right-on-time' mail service head wear." + flags = FPRINT + +/obj/item/clothing/head/plaguedoctorhat + name = "plague doctor's hat" + desc = "These were once used by Plague doctors. They're pretty much useless." + icon_state = "plaguedoctor" + flags = FPRINT + permeability_coefficient = 0.01 + siemens_coefficient = 0.9 + +/obj/item/clothing/head/hasturhood + name = "hastur's hood" + desc = "It's unspeakably stylish" + icon_state = "hasturhood" + flags = FPRINT + flags_inv = HIDEHAIR + body_parts_covered = HEAD|EARS + +/obj/item/clothing/head/nursehat + name = "nurse's hat" + desc = "It allows quick identification of trained medical personnel." + icon_state = "nursehat" + flags = FPRINT + siemens_coefficient = 0.9 + +/obj/item/clothing/head/syndicatefake + name = "red space-helmet replica" + icon_state = "syndicate" + item_state = "syndicate" + desc = "A plastic replica of a syndicate agent's space helmet, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!" + flags = FPRINT + body_parts_covered = FULL_HEAD + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/cueball + name = "cueball helmet" + desc = "A large, featureless white orb mean to be worn on your head. How do you even see out of this thing?" + icon_state = "cueball" + flags = FPRINT + body_parts_covered = FULL_HEAD + item_state="cueball" + flags_inv = HIDEHAIR + +/obj/item/clothing/head/that + name = "sturdy top-hat" + desc = "It's an amish looking armored top hat." + icon_state = "tophat" + item_state = "that" + flags = FPRINT + flags_inv = 0 + + +/obj/item/clothing/head/greenbandana + name = "green bandana" + desc = "It's a green bandana with some fine nanotech lining." + icon_state = "greenbandana" + item_state = "greenbandana" + flags = FPRINT + flags_inv = 0 + +/obj/item/clothing/head/cardborg + name = "cardborg helmet" + desc = "A helmet made out of a box." + icon_state = "cardborg_h" + item_state = "cardborg_h" + flags = FPRINT + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = FULL_HEAD + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + +/obj/item/clothing/head/justice + name = "justice hat" + desc = "fight for what's righteous!" + icon_state = "justicered" + item_state = "justicered" + flags = FPRINT + flags_inv = HIDEHAIR + body_parts_covered = HEAD|EYES|MOUTH + +/obj/item/clothing/head/justice/blue + icon_state = "justiceblue" + item_state = "justiceblue" + +/obj/item/clothing/head/justice/yellow + icon_state = "justiceyellow" + item_state = "justiceyellow" + +/obj/item/clothing/head/justice/green + icon_state = "justicegreen" + item_state = "justicegreen" + +/obj/item/clothing/head/justice/pink + icon_state = "justicepink" + item_state = "justicepink" + +/obj/item/clothing/head/rabbitears + name = "rabbit ears" + desc = "Wearing these makes you looks useless, and only good for your sex appeal." + icon_state = "bunny" + flags = FPRINT + +/obj/item/clothing/head/flatcap + name = "flat cap" + desc = "A working man's cap." + icon_state = "flat_cap" + item_state = "detective" + siemens_coefficient = 0.9 + +/obj/item/clothing/head/pirate + name = "pirate hat" + desc = "Yarr." + icon_state = "pirate" + item_state = "pirate" + +/obj/item/clothing/head/hgpiratecap + name = "pirate hat" + desc = "Yarr." + icon_state = "hgpiratecap" + item_state = "hgpiratecap" + +/obj/item/clothing/head/bandana + name = "pirate bandana" + desc = "Yarr." + icon_state = "bandana" + item_state = "bandana" + +//stylish bs12 hats + +/obj/item/clothing/head/bowlerhat + name = "bowler hat" + icon_state = "bowler_hat" + item_state = "bowler_hat" + desc = "For that industrial age look." + flags = FPRINT + +/obj/item/clothing/head/beaverhat + name = "beaver hat" + icon_state = "beaver_hat" + item_state = "beaver_hat" + desc = "Like a top hat, but made of beavers." + flags = FPRINT + +/obj/item/clothing/head/boaterhat + name = "boater hat" + icon_state = "boater_hat" + item_state = "boater_hat" + desc = "Goes well with celery." + flags = FPRINT + +/obj/item/clothing/head/squatter_hat + name = "slav squatter hat" + icon_state = "squatter_hat" + item_state = "squatter_hat" + desc = "Cyka blyat." + flags = FPRINT + +/obj/item/clothing/head/fedora + name = "\improper fedora" + icon_state = "fedora" + item_state = "fedora" + desc = "A great hat ruined by being within fifty yards of you." + flags = FPRINT + +/obj/item/clothing/head/fedora/OnMobLife(var/mob/living/carbon/human/wearer) + if(!istype(wearer)) return + if(wearer.head == src) + if(prob(1)) + to_chat(wearer, "You feel positively euphoric!") + +//TIPS FEDORA +/obj/item/clothing/head/fedora/verb/tip_fedora() + set name = "Tip Fedora" + set category = "Object" + set desc = "Show that CIS SCUM who's boss." + + usr.visible_message("[usr] tips his fedora.", "You tip your fedora.") + +/obj/item/clothing/head/fez + name = "\improper fez" + icon_state = "fez" + item_state = "fez" + desc = "Put it on your monkey, make lots of cash money." + flags = FPRINT + +//end bs12 hats + +/obj/item/clothing/head/witchwig + name = "witch costume wig" + desc = "Eeeee~heheheheheheh!" + icon_state = "witch" + item_state = "witch" + flags = FPRINT + flags_inv = HIDEHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/chicken + name = "chicken suit head" + desc = "Bkaw!" + icon_state = "chickenhead" + item_state = "chickensuit" + flags = FPRINT + flags_inv = HIDEHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/bearpelt + name = "cheap bear pelt hat" + desc = "Not as fuzzy as the real thing." + icon_state = "bearpelt" + item_state = "bearpelt" + flags = FPRINT + flags_inv = HIDEHEADHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/bearpelt/real + name = "bear pelt hat" + desc = "Now that's what I call fuzzy." + +/obj/item/clothing/head/xenos + name = "xenos helmet" + icon_state = "xenos" + item_state = "xenos_helm" + desc = "A helmet made out of chitinous alien hide." + flags = FPRINT + body_parts_covered = FULL_HEAD + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/batman + name = "bathelmet" + desc = "No one cares who you are until you put on the mask." + icon_state = "bmhead" + item_state = "bmhead" + flags = FPRINT + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR + body_parts_covered = HEAD|EYES|EARS + +/obj/item/clothing/head/stalhelm + name = "Stalhelm" + desc = "Ein Helm, um die Nazi-Interesse an fremden Raumstationen zu sichern." + icon_state = "stalhelm" + item_state = "stalhelm" + flags = FPRINT + flags_inv = HIDEEARS|HIDEHEADHAIR + +/obj/item/clothing/head/panzer + name = "Panzer Cap" + desc = "Ein Hut passen nur für die größten Tanks." + icon_state = "panzercap" + item_state = "panzercap" + flags = FPRINT + +/obj/item/clothing/head/naziofficer + name = "Officer Cap" + desc = "Ein Hut von Offizieren in der Nazi-Partei getragen." + icon_state = "officercap" + item_state = "officercap" + flags = FPRINT + flags_inv = HIDEEARS|HIDEHEADHAIR + +/obj/item/clothing/head/russobluecamohat + name = "russian blue camo beret" + desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food." + icon_state = "russobluecamohat" + item_state = "russobluecamohat" + flags = FPRINT + +/obj/item/clothing/head/russofurhat + name = "russian fur hat" + desc = "Russian winter got you down? Maybe your enemy, but not you!" + icon_state = "russofurhat" + item_state = "russofurhat" + flags = FPRINT + flags_inv = HIDEEARS|HIDEHEADHAIR + +/obj/item/clothing/head/lordadmiralhat + name = "lord admiral's hat" + desc = "A hat suitable for any man of high and exalted rank." + icon_state = "lordadmiralhat" + item_state = "lordadmiralhat" + +/obj/item/clothing/head/jesterhat + name = "jester hat" + desc = "A hat fit for a fool." + icon_state = "jesterhat" + item_state = "jesterhat" + flags = FPRINT + flags_inv = HIDEEARS|HIDEHEADHAIR + +/obj/item/clothing/head/libertyhat + name = "liberty top hat" + desc = "Show everyone just how patriotic you are." + icon_state = "libertyhat" + item_state = "libertyhat" + flags = FPRINT + +/obj/item/clothing/head/maidhat + name = "maid headband" + desc = "Do these even do anything besides look cute?" + icon_state = "maidhat" + item_state = "maidhat" + flags = FPRINT + +/obj/item/clothing/head/maidhat + name = "maid headband" + desc = "Do these even do anything besides look cute?" + icon_state = "maidhat" + item_state = "maidhat" + flags = FPRINT + +/obj/item/clothing/head/mitre + name = "mitre" + desc = "A funny hat worn by extremely boring people." + icon_state = "mitre" + item_state = "mitre" + +/obj/item/clothing/head/clownpiece + name = "Clownpiece's jester hat" + desc = "A purple polka-dotted jester's hat with yellow pompons." + icon_state = "clownpiece" + item_state = "clownpiece" + +/obj/item/clothing/head/headband + name = "head band" + desc = "You wear this around your head." + icon_state = "headband" + item_state = "headband" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/metalgear.dmi', "right_hand" = 'icons/mob/in-hand/right/metalgear.dmi') + +/obj/item/clothing/head/cowboy + name = "cowboy hat" + desc = "Pefect for the closet botanist." + icon_state = "cowboy" + item_state = "cowboy" + +/obj/item/clothing/head/christmas/santahat/red + name = "red santa hat" + desc = "Not quite as magical as the real thing, but it flops over one ear and itches your head just the same" + icon_state = "santahatred" + item_state = "santahatred" + +/obj/item/clothing/head/christmas/santahat/green + name = "green santa hat" + desc = "Not quite as magical as the real thing, but it flops over one ear and itches your head just the same" + icon_state = "santahatgreen" + item_state = "santahatgreen" + +/obj/item/clothing/head/festive + name = "festive paper hat" + icon_state = "xmashat" + item_state = "xmashat" + desc = "A crappy paper hat that you are REQUIRED to wear." + flags_inv = 0 + flags = FPRINT armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) \ No newline at end of file diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 42dc7be0ff6..7dca51f9a3c 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -1,208 +1,208 @@ -/* - * Contents: - * Welding mask - * Cakehat - * Ushanka - * Pumpkin head - * Kitty ears - * Tinfoil Hat - */ - -/* - * Welding mask - */ -/obj/item/clothing/head/welding - name = "welding helmet" - desc = "A head-mounted face cover designed to protect the wearer completely from space-arc eye." - icon_state = "welding" - flags = FPRINT - item_state = "welding" - starting_materials = list(MAT_IRON = 3000, MAT_GLASS = 1000) - w_type = RECYK_MISC - var/up = 0 - eyeprot = 3 - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - body_parts_covered = HEAD|EYES|MOUTH|EARS //using this instead of FULL_HEAD to show how the flags change in the code - action_button_name = "Toggle Welding Helmet" - siemens_coefficient = 0.9 - species_fit = list("Vox") - -/obj/item/clothing/head/welding/attack_self() - toggle() - - -/obj/item/clothing/head/welding/verb/toggle() - set category = "Object" - set name = "Adjust welding mask" - set src in usr - if(!usr) return //PANIC - if(usr.canmove && !usr.stat && !usr.restrained()) - if(src.up) - src.up = !src.up - src.body_parts_covered |= (EYES|MOUTH|EARS) - flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - eyeprot = 3 - icon_state = initial(icon_state) - to_chat(usr, "You flip the [src] down to protect your eyes.") - else - src.up = !src.up - src.body_parts_covered &= ~(EYES|MOUTH|EARS) - flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - icon_state = "[initial(icon_state)]up" - eyeprot = 0 - to_chat(usr, "You push the [src] up out of your face.") - usr.update_inv_head() //so our mob-overlays update - usr.update_inv_wear_mask() - usr.update_inv_glasses() - usr.update_inv_ears() - - -/* - * Cakehat - */ -/obj/item/clothing/head/cakehat - name = "cake-hat" - desc = "It's tasty looking!" - icon_state = "cake0" - flags = FPRINT - body_parts_covered = HEAD|EYES - light_power = 0.5 - var/onfire = 0.0 - var/status = 0 - var/fire_resist = T0C+1300 //this is the max temp it can stand before you start to cook. although it might not burn away, you take damage - var/processing = 0 //I dont think this is used anywhere. - -/obj/item/clothing/head/cakehat/process() - if(!onfire) - processing_objects.Remove(src) - return - - var/turf/location = src.loc - if(istype(location, /mob/)) - var/mob/living/carbon/human/M = location - if(istype(M)) - if(M.l_hand == src || M.r_hand == src || M.head == src) - location = M.loc - else - return - - if (istype(location, /turf)) - location.hotspot_expose(700, 1) - -/obj/item/clothing/head/cakehat/attack_self(mob/user as mob) - if(status > 1) return - src.onfire = !( src.onfire ) - if (src.onfire) - src.force = 3 - src.damtype = "fire" - src.icon_state = "cake1" - processing_objects.Add(src) - set_light(2) - else - src.force = null - src.damtype = "brute" - src.icon_state = "cake0" - set_light(0) - return - - -/* - * Ushanka - */ -/obj/item/clothing/head/ushanka - name = "ushanka" - desc = "Perfect for winter in Siberia, da?" - icon_state = "ushankadown" - item_state = "ushankadown" - flags_inv = HIDEEARS - -/obj/item/clothing/head/ushanka/attack_self(mob/user as mob) - if(src.icon_state == "ushankadown") - src.icon_state = "ushankaup" - src.item_state = "ushankaup" - to_chat(user, "You raise the ear flaps on the ushanka.") - else - src.icon_state = "ushankadown" - src.item_state = "ushankadown" - to_chat(user, "You lower the ear flaps on the ushanka.") - -/* - * Pumpkin head - */ -/obj/item/clothing/head/pumpkinhead - name = "carved pumpkin" - desc = "A jack o' lantern! Believed to ward off evil spirits." - icon_state = "hardhat0_pumpkin"//Could stand to be renamed - item_state = "hardhat0_pumpkin" - _color = "pumpkin" - flags = FPRINT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR - body_parts_covered = FULL_HEAD - var/brightness_on = 2 //luminosity when on - var/on = 0 - - attack_self(mob/user) - if(!isturf(user.loc)) - to_chat(user, "You cannot turn the light on while in this [user.loc]")//To prevent some lighting anomalities. +/* + * Contents: + * Welding mask + * Cakehat + * Ushanka + * Pumpkin head + * Kitty ears + * Tinfoil Hat + */ - return - on = !on - icon_state = "hardhat[on]_[_color]" - item_state = "hardhat[on]_[_color]" - - if(on) set_light(brightness_on) - else set_light(0) - -/* - * Kitty ears - */ -/obj/item/clothing/head/kitty - name = "kitty ears" - desc = "A pair of kitty ears. Meow!" - icon_state = "kitty" - flags = FPRINT - var/icon/mob - var/icon/mob2 - siemens_coefficient = 1.5 - - update_icon(var/mob/living/carbon/human/user) - if(!istype(user)) return - mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty") - mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2") - mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) - mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) - - var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") - var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2") - mob.Blend(earbit, ICON_OVERLAY) - mob2.Blend(earbit2, ICON_OVERLAY) - -/obj/item/clothing/head/butt - name = "butt" - desc = "So many butts, so little time." - icon_state = "butt" - item_state = "butt" - flags = 0 - force = 4.0 - w_class = 1.0 - throwforce = 2 - throw_speed = 3 - throw_range = 5 - - wizard_garb = 1 - - var/s_tone = 0.0 - var/created_name = "Buttbot" - -/obj/item/clothing/head/butt/proc/transfer_buttdentity(var/mob/living/carbon/H) - name = "[H.real_name]'s butt" - return - -/obj/item/clothing/head/tinfoil - name = "tinfoil hat" - desc = "There's no evidence that the security staff is NOT out to get you." - icon_state = "foilhat" - item_state = "paper" - siemens_coefficient = 2 - flags_inv = HIDEHAIR +/* + * Welding mask + */ +/obj/item/clothing/head/welding + name = "welding helmet" + desc = "A head-mounted face cover designed to protect the wearer completely from space-arc eye." + icon_state = "welding" + flags = FPRINT + item_state = "welding" + starting_materials = list(MAT_IRON = 3000, MAT_GLASS = 1000) + w_type = RECYK_MISC + var/up = 0 + eyeprot = 3 + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + body_parts_covered = HEAD|EYES|MOUTH|EARS //using this instead of FULL_HEAD to show how the flags change in the code + action_button_name = "Toggle Welding Helmet" + siemens_coefficient = 0.9 + species_fit = list("Vox") + +/obj/item/clothing/head/welding/attack_self() + toggle() + + +/obj/item/clothing/head/welding/verb/toggle() + set category = "Object" + set name = "Adjust welding mask" + set src in usr + if(!usr) return //PANIC + if(usr.canmove && !usr.stat && !usr.restrained()) + if(src.up) + src.up = !src.up + src.body_parts_covered |= (EYES|MOUTH|EARS) + flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + eyeprot = 3 + icon_state = initial(icon_state) + to_chat(usr, "You flip the [src] down to protect your eyes.") + else + src.up = !src.up + src.body_parts_covered &= ~(EYES|MOUTH|EARS) + flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + icon_state = "[initial(icon_state)]up" + eyeprot = 0 + to_chat(usr, "You push the [src] up out of your face.") + usr.update_inv_head() //so our mob-overlays update + usr.update_inv_wear_mask() + usr.update_inv_glasses() + usr.update_inv_ears() + + +/* + * Cakehat + */ +/obj/item/clothing/head/cakehat + name = "cake-hat" + desc = "It's tasty looking!" + icon_state = "cake0" + flags = FPRINT + body_parts_covered = HEAD|EYES + light_power = 0.5 + var/onfire = 0.0 + var/status = 0 + var/fire_resist = T0C+1300 //this is the max temp it can stand before you start to cook. although it might not burn away, you take damage + var/processing = 0 //I dont think this is used anywhere. + +/obj/item/clothing/head/cakehat/process() + if(!onfire) + processing_objects.Remove(src) + return + + var/turf/location = src.loc + if(istype(location, /mob/)) + var/mob/living/carbon/human/M = location + if(istype(M)) + if(M.l_hand == src || M.r_hand == src || M.head == src) + location = M.loc + else + return + + if (istype(location, /turf)) + location.hotspot_expose(700, 1) + +/obj/item/clothing/head/cakehat/attack_self(mob/user as mob) + if(status > 1) return + src.onfire = !( src.onfire ) + if (src.onfire) + src.force = 3 + src.damtype = "fire" + src.icon_state = "cake1" + processing_objects.Add(src) + set_light(2) + else + src.force = null + src.damtype = "brute" + src.icon_state = "cake0" + set_light(0) + return + + +/* + * Ushanka + */ +/obj/item/clothing/head/ushanka + name = "ushanka" + desc = "Perfect for winter in Siberia, da?" + icon_state = "ushankadown" + item_state = "ushankadown" + flags_inv = HIDEEARS + +/obj/item/clothing/head/ushanka/attack_self(mob/user as mob) + if(src.icon_state == "ushankadown") + src.icon_state = "ushankaup" + src.item_state = "ushankaup" + to_chat(user, "You raise the ear flaps on the ushanka.") + else + src.icon_state = "ushankadown" + src.item_state = "ushankadown" + to_chat(user, "You lower the ear flaps on the ushanka.") + +/* + * Pumpkin head + */ +/obj/item/clothing/head/pumpkinhead + name = "carved pumpkin" + desc = "A jack o' lantern! Believed to ward off evil spirits." + icon_state = "hardhat0_pumpkin"//Could stand to be renamed + item_state = "hardhat0_pumpkin" + _color = "pumpkin" + flags = FPRINT + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR + body_parts_covered = FULL_HEAD + var/brightness_on = 2 //luminosity when on + var/on = 0 + + attack_self(mob/user) + if(!isturf(user.loc)) + to_chat(user, "You cannot turn the light on while in this [user.loc]")//To prevent some lighting anomalities. + + return + on = !on + icon_state = "hardhat[on]_[_color]" + item_state = "hardhat[on]_[_color]" + + if(on) set_light(brightness_on) + else set_light(0) + +/* + * Kitty ears + */ +/obj/item/clothing/head/kitty + name = "kitty ears" + desc = "A pair of kitty ears. Meow!" + icon_state = "kitty" + flags = FPRINT + var/icon/mob + var/icon/mob2 + siemens_coefficient = 1.5 + + update_icon(var/mob/living/carbon/human/user) + if(!istype(user)) return + mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty") + mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2") + mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + + var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") + var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2") + mob.Blend(earbit, ICON_OVERLAY) + mob2.Blend(earbit2, ICON_OVERLAY) + +/obj/item/clothing/head/butt + name = "butt" + desc = "So many butts, so little time." + icon_state = "butt" + item_state = "butt" + flags = 0 + force = 4.0 + w_class = 1.0 + throwforce = 2 + throw_speed = 3 + throw_range = 5 + + wizard_garb = 1 + + var/s_tone = 0.0 + var/created_name = "Buttbot" + +/obj/item/clothing/head/butt/proc/transfer_buttdentity(var/mob/living/carbon/H) + name = "[H.real_name]'s butt" + return + +/obj/item/clothing/head/tinfoil + name = "tinfoil hat" + desc = "There's no evidence that the security staff is NOT out to get you." + icon_state = "foilhat" + item_state = "paper" + siemens_coefficient = 2 + flags_inv = HIDEHAIR diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 03561cb09c6..56fb913731c 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -1,101 +1,101 @@ -/obj/item/clothing/head/soft - name = "cargo cap" - desc = "It's a baseball hat in a tasteless yellow colour." - icon_state = "cargosoft" - flags = FPRINT - item_state = "helmet" - _color = "cargo" - var/flipped = 0 - siemens_coefficient = 0.9 - body_parts_covered = HEAD|EYES - - proc/flip(var/mob/user as mob) - if(user.canmove && !user.stat && !user.restrained()) - src.flipped = !src.flipped - if(src.flipped) - icon_state = "[_color]soft_flipped" +/obj/item/clothing/head/soft + name = "cargo cap" + desc = "It's a baseball hat in a tasteless yellow colour." + icon_state = "cargosoft" + flags = FPRINT + item_state = "helmet" + _color = "cargo" + var/flipped = 0 + siemens_coefficient = 0.9 + body_parts_covered = HEAD|EYES + + proc/flip(var/mob/user as mob) + if(user.canmove && !user.stat && !user.restrained()) + src.flipped = !src.flipped + if(src.flipped) + icon_state = "[_color]soft_flipped" to_chat(user, "You flip the hat backwards.") - else - icon_state = "[_color]soft" + else + icon_state = "[_color]soft" to_chat(user, "You flip the hat back in normal position.") - user.update_inv_head() //so our mob-overlays update - - attack_self(var/mob/user as mob) - flip(user) - - verb/flip_cap() - set category = "Object" - set name = "Flip cap" - set src in usr - flip(usr) - - dropped() - src.icon_state = "[_color]soft" //because of this line and 15 and 18, the icon_state will end up blank if you were to try allowing heads to dye caps with their stamps - src.flipped=0 - ..() - -/obj/item/clothing/head/soft/red - name = "red cap" - desc = "It's a baseball hat in a tasteless red colour." - icon_state = "redsoft" - _color = "red" - -/obj/item/clothing/head/soft/blue - name = "blue cap" - desc = "It's a baseball hat in a tasteless blue colour." - icon_state = "bluesoft" - _color = "blue" - -/obj/item/clothing/head/soft/green - name = "green cap" - desc = "It's a baseball hat in a tasteless green colour." - icon_state = "greensoft" - _color = "green" - -/obj/item/clothing/head/soft/yellow - name = "yellow cap" - desc = "It's a baseball hat in a tasteless yellow colour." - icon_state = "yellowsoft" - _color = "yellow" - -/obj/item/clothing/head/soft/grey - name = "grey cap" - desc = "It's a baseball hat in a tasteful grey colour." - icon_state = "greysoft" - _color = "grey" - -/obj/item/clothing/head/soft/orange - name = "orange cap" - desc = "It's a baseball hat in a tasteless orange colour." - icon_state = "orangesoft" - _color = "orange" - -/obj/item/clothing/head/soft/mime - name = "white cap" - desc = "It's a baseball hat in a tasteless white colour." - icon_state = "mimesoft" - _color = "mime" - -/obj/item/clothing/head/soft/purple - name = "purple cap" - desc = "It's a baseball hat in a tasteless purple colour." - icon_state = "purplesoft" - _color = "purple" - -/obj/item/clothing/head/soft/rainbow - name = "rainbow cap" - desc = "It's a baseball hat in a bright rainbow of colors." - icon_state = "rainbowsoft" - _color = "rainbow" - -/obj/item/clothing/head/soft/sec - name = "security cap" - desc = "It's baseball hat in tasteful red colour." - icon_state = "secsoft" - _color = "sec" - -/obj/item/clothing/head/soft/paramedic - name = "paramedic cap" - desc = "It's a baseball hat in a tasteful blue colour." - icon_state = "paramedicsoft" + user.update_inv_head() //so our mob-overlays update + + attack_self(var/mob/user as mob) + flip(user) + + verb/flip_cap() + set category = "Object" + set name = "Flip cap" + set src in usr + flip(usr) + + dropped() + src.icon_state = "[_color]soft" //because of this line and 15 and 18, the icon_state will end up blank if you were to try allowing heads to dye caps with their stamps + src.flipped=0 + ..() + +/obj/item/clothing/head/soft/red + name = "red cap" + desc = "It's a baseball hat in a tasteless red colour." + icon_state = "redsoft" + _color = "red" + +/obj/item/clothing/head/soft/blue + name = "blue cap" + desc = "It's a baseball hat in a tasteless blue colour." + icon_state = "bluesoft" + _color = "blue" + +/obj/item/clothing/head/soft/green + name = "green cap" + desc = "It's a baseball hat in a tasteless green colour." + icon_state = "greensoft" + _color = "green" + +/obj/item/clothing/head/soft/yellow + name = "yellow cap" + desc = "It's a baseball hat in a tasteless yellow colour." + icon_state = "yellowsoft" + _color = "yellow" + +/obj/item/clothing/head/soft/grey + name = "grey cap" + desc = "It's a baseball hat in a tasteful grey colour." + icon_state = "greysoft" + _color = "grey" + +/obj/item/clothing/head/soft/orange + name = "orange cap" + desc = "It's a baseball hat in a tasteless orange colour." + icon_state = "orangesoft" + _color = "orange" + +/obj/item/clothing/head/soft/mime + name = "white cap" + desc = "It's a baseball hat in a tasteless white colour." + icon_state = "mimesoft" + _color = "mime" + +/obj/item/clothing/head/soft/purple + name = "purple cap" + desc = "It's a baseball hat in a tasteless purple colour." + icon_state = "purplesoft" + _color = "purple" + +/obj/item/clothing/head/soft/rainbow + name = "rainbow cap" + desc = "It's a baseball hat in a bright rainbow of colors." + icon_state = "rainbowsoft" + _color = "rainbow" + +/obj/item/clothing/head/soft/sec + name = "security cap" + desc = "It's baseball hat in tasteful red colour." + icon_state = "secsoft" + _color = "sec" + +/obj/item/clothing/head/soft/paramedic + name = "paramedic cap" + desc = "It's a baseball hat in a tasteful blue colour." + icon_state = "paramedicsoft" _color = "paramedic" \ No newline at end of file diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index 62e82dee3ab..89b0d549915 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -1,57 +1,57 @@ -/obj/item/clothing/mask/balaclava - name = "balaclava" - desc = "LOADSAMONEY" - icon_state = "balaclava" - item_state = "balaclava" - flags = FPRINT - flags_inv = HIDEFACE|HIDEHAIR - w_class = 2 - species_fit = list("Vox") - -/obj/item/clothing/mask/luchador - name = "Luchador Mask" - desc = "Worn by robust fighters, flying high to defeat their foes!" - icon_state = "luchag" - item_state = "luchag" - flags = FPRINT|MASKINTERNALS - flags_inv = HIDEFACE|HIDEHAIR - w_class = 2 - siemens_coefficient = 3.0 - species_fit = list("Vox") - -/obj/item/clothing/mask/luchador/treat_mask_speech(var/datum/speech/speech) - var/message=speech.message - message = replacetext(message, "captain", "CAPITÃN") - message = replacetext(message, "station", "ESTACIÓN") - message = replacetext(message, "sir", "SEÑOR") - message = replacetext(message, "the ", "el ") - message = replacetext(message, "my ", "mi ") - message = replacetext(message, "is ", "es ") - message = replacetext(message, "it's", "es") - message = replacetext(message, "friend", "amigo") - message = replacetext(message, "buddy", "amigo") - message = replacetext(message, "hello", "hola") - message = replacetext(message, " hot", " caliente") - message = replacetext(message, " very ", " muy ") - message = replacetext(message, "sword", "espada") - message = replacetext(message, "library", "biblioteca") - message = replacetext(message, "traitor", "traidor") - message = replacetext(message, "wizard", "mago") - message = uppertext(message) //Things end up looking better this way (no mixed cases), and it fits the macho wrestler image. - if(prob(25)) - message += " OLE!" - speech.message = message - -/obj/item/clothing/mask/luchador/tecnicos - name = "Tecnicos Mask" - desc = "Worn by robust fighters who uphold justice and fight honorably." - icon_state = "luchador" - item_state = "luchador" - species_fit = list("Vox") - -/obj/item/clothing/mask/luchador/rudos - name = "Rudos Mask" - desc = "Worn by robust fighters who are willing to do anything to win." - icon_state = "luchar" - item_state = "luchar" +/obj/item/clothing/mask/balaclava + name = "balaclava" + desc = "LOADSAMONEY" + icon_state = "balaclava" + item_state = "balaclava" + flags = FPRINT + flags_inv = HIDEFACE|HIDEHAIR + w_class = 2 + species_fit = list("Vox") + +/obj/item/clothing/mask/luchador + name = "Luchador Mask" + desc = "Worn by robust fighters, flying high to defeat their foes!" + icon_state = "luchag" + item_state = "luchag" + flags = FPRINT|MASKINTERNALS + flags_inv = HIDEFACE|HIDEHAIR + w_class = 2 + siemens_coefficient = 3.0 + species_fit = list("Vox") + +/obj/item/clothing/mask/luchador/treat_mask_speech(var/datum/speech/speech) + var/message=speech.message + message = replacetext(message, "captain", "CAPITÃN") + message = replacetext(message, "station", "ESTACIÓN") + message = replacetext(message, "sir", "SEÑOR") + message = replacetext(message, "the ", "el ") + message = replacetext(message, "my ", "mi ") + message = replacetext(message, "is ", "es ") + message = replacetext(message, "it's", "es") + message = replacetext(message, "friend", "amigo") + message = replacetext(message, "buddy", "amigo") + message = replacetext(message, "hello", "hola") + message = replacetext(message, " hot", " caliente") + message = replacetext(message, " very ", " muy ") + message = replacetext(message, "sword", "espada") + message = replacetext(message, "library", "biblioteca") + message = replacetext(message, "traitor", "traidor") + message = replacetext(message, "wizard", "mago") + message = uppertext(message) //Things end up looking better this way (no mixed cases), and it fits the macho wrestler image. + if(prob(25)) + message += " OLE!" + speech.message = message + +/obj/item/clothing/mask/luchador/tecnicos + name = "Tecnicos Mask" + desc = "Worn by robust fighters who uphold justice and fight honorably." + icon_state = "luchador" + item_state = "luchador" + species_fit = list("Vox") + +/obj/item/clothing/mask/luchador/rudos + name = "Rudos Mask" + desc = "Worn by robust fighters who are willing to do anything to win." + icon_state = "luchar" + item_state = "luchar" species_fit = list("Vox") \ No newline at end of file diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index fd3b7abf8e4..51057fa157e 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -1,30 +1,30 @@ -/obj/item/clothing/mask/breath - desc = "A close-fitting mask that can be connected to an air supply." - name = "breath mask" - icon_state = "breath" - item_state = "breath" - flags = FPRINT | MASKINTERNALS - w_class = 2 - gas_transfer_coefficient = 0.10 - permeability_coefficient = 0.50 - species_fit = list("Vox") - body_parts_covered = HEAD|MOUTH - can_flip = 1 - - - -/obj/item/clothing/mask/breath/medical - desc = "A close-fitting sterile mask that can be connected to an air supply." - name = "medical mask" - icon_state = "medical" - item_state = "medical" - permeability_coefficient = 0.01 - species_fit = list("Vox") - -/obj/item/clothing/mask/breath/vox - desc = "A weirdly-shaped breath mask." - name = "vox breath mask" - icon_state = "voxmask" - item_state = "voxmask" - permeability_coefficient = 0.01 +/obj/item/clothing/mask/breath + desc = "A close-fitting mask that can be connected to an air supply." + name = "breath mask" + icon_state = "breath" + item_state = "breath" + flags = FPRINT | MASKINTERNALS + w_class = 2 + gas_transfer_coefficient = 0.10 + permeability_coefficient = 0.50 + species_fit = list("Vox") + body_parts_covered = HEAD|MOUTH + can_flip = 1 + + + +/obj/item/clothing/mask/breath/medical + desc = "A close-fitting sterile mask that can be connected to an air supply." + name = "medical mask" + icon_state = "medical" + item_state = "medical" + permeability_coefficient = 0.01 + species_fit = list("Vox") + +/obj/item/clothing/mask/breath/vox + desc = "A weirdly-shaped breath mask." + name = "vox breath mask" + icon_state = "voxmask" + item_state = "voxmask" + permeability_coefficient = 0.01 species_restricted = list("Vox") \ No newline at end of file diff --git a/code/modules/clothing/masks/chemmask.dm b/code/modules/clothing/masks/chemmask.dm index cea6789d59d..2c70f197bfb 100644 --- a/code/modules/clothing/masks/chemmask.dm +++ b/code/modules/clothing/masks/chemmask.dm @@ -1,412 +1,412 @@ -//************************************************************** -// Chemical Mask -//************************************************************** -//Icons are in masks.dmi, chempack.dmi (left), chempack.dmi (right), and mask.dmi - -//This item is designed to grant support utility to the chemical pack, once the chemical pack's safeties are overridden. -//The chemical pack has a 1200u primary tank, from which it will take a certain amount of each reagent in the pack and -//inject it into the wearer. The amount taken from the primary tank is determined by tank_injection_rate, which defaults -//to 10, and can be altered by the user with a verb. The amount taken from the primary tank is altered slightly per-reagent, -//based on that reagent's custom_metabolism value, in order to avoid taking too much of a reagent just because that reagent -//happens to metabolize more slowly than others. - -//Additionally, the chemical pack has an auxiliary chamber which can store any /obj/item/weapon/reagent_containers/glass item. -//While capped at the largest beaker size, currently 300u, this chamber offers more control over the way in which reagents -//are administered from it. It defaults to a threshold-based system, in which it injects 10u of creatine when the user falls -//below 10u of creatine in their body. However, the user can alter the settings and change it to a time-based system, change -//the time interval, the amount injected, and the reagent monitored by the threshold system, through verbs. - -//By default, the primary tank is connected to the mask, and the auxiliary beaker is disconnected. The user may toggle these -//connections using verbs. When disconnected, the mask will not take any additional reagents from the primary tank and/or the -//auxiliary beaker. Cycling these verbs will not force injections, the tank is still only capable of one injection per 97 seconds, -//and the beaker has no need to be forced to inject since the user can alter its time interval directly. -#define THRESHOLD "Threshold-based" -#define TIME "Time-based" - -/obj/item/clothing/mask/chemmask - desc = "A rather sinister mask designed for connection to a chemical pack, providing the pack's safeties are disabled." - name = "chemical mask" - icon_state = "chemmask0" - flags = FPRINT | MASKINTERNALS - w_class = 2 - var/power = 0 - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - var/tank_injection_rate = 10 - var/tank_has_injected = 0 - var/beaker_injection_methods = list(TIME,THRESHOLD) - var/beaker_injection_method = THRESHOLD - var/injection_method_chosen = 0 - var/beaker_time_interval = 970 - var/beaker_injection_rate = 10 - var/beaker_threshold = 10 - var/beaker_threshold_reagent = "creatine" - var/beaker_has_injected_time = 0 - var/firstalert_tank = 0 - var/firstalert_beaker = 0 - var/beakeractive = 0 - var/tankactive = 1 - var/time_at_last_tank_inject = 0 //This will ensure that the mask will always inject instantly the first time the user turns it on. - var/time_at_last_beaker_inject = 0 //It will prevent the chemmask from functioning for the first minute and 37 seconds of the world's existence, but I don't think that'll ever be a problem. - var/beaker_verbs_time = list( - /obj/item/clothing/mask/chemmask/verb/set_beaker_time_interval - ) - var/beaker_verbs_threshold = list( - /obj/item/clothing/mask/chemmask/verb/set_beaker_threshold, - /obj/item/clothing/mask/chemmask/verb/set_beaker_threshold_reagent - ) - species_fit = list("Vox") - body_parts_covered = HEAD|MOUTH - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/chempack.dmi', "right_hand" = 'icons/mob/in-hand/right/chempack.dmi') - origin_tech = "biotech=5;materials=5;engineering=5;syndicate=5;combat=5" - -/obj/item/clothing/mask/chemmask/New() //Doing this so that these verbs don't show up before there's actually a beaker in the pack. - ..() - processing_objects.Add(src) - update_verbs() - -/obj/item/clothing/mask/chemmask/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/clothing/mask/chemmask/equipped(M as mob, wear_mask) - var/mob/living/carbon/human/H = M - if(H.wear_mask == src) - update_verbs() - -/obj/item/clothing/mask/chemmask/proc/update_verbs() - var/mob/living/carbon/human/H - if (power) - verbs += /obj/item/clothing/mask/chemmask/verb/set_pack_injection - else - verbs -= /obj/item/clothing/mask/chemmask/verb/set_pack_injection - if (istype(loc,/mob/living/carbon/human)) //It runtimes if it calls this on a turf, which it does when it first spawns. - H = loc - else - return - if (istype(H.back,/obj/item/weapon/reagent_containers/chempack)) - verbs += /obj/item/clothing/mask/chemmask/verb/set_tank_usage - else - verbs -= /obj/item/clothing/mask/chemmask/verb/set_tank_usage - if (has_beaker(H)) - verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_usage - verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_method - if (injection_method_chosen) //Don't want the user to have to select the beaker injection method more than once per item. - if (beaker_injection_method == THRESHOLD) - verbs += beaker_verbs_threshold - verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate - verbs -= beaker_verbs_time - else if (beaker_injection_method == TIME) - verbs += beaker_verbs_time - verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate - verbs -= beaker_verbs_threshold - else - verbs -= beaker_verbs_time - verbs -= beaker_verbs_threshold - verbs -= /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate - else - verbs -= /obj/item/clothing/mask/chemmask/verb/set_beaker_usage - verbs -= /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_method - verbs -= beaker_verbs_time - verbs -= beaker_verbs_threshold - -/obj/item/clothing/mask/chemmask/proc/can_use_verbs(mob/user) - var/mob/living/carbon/human/M = user - if (M.stat == DEAD) +//************************************************************** +// Chemical Mask +//************************************************************** +//Icons are in masks.dmi, chempack.dmi (left), chempack.dmi (right), and mask.dmi + +//This item is designed to grant support utility to the chemical pack, once the chemical pack's safeties are overridden. +//The chemical pack has a 1200u primary tank, from which it will take a certain amount of each reagent in the pack and +//inject it into the wearer. The amount taken from the primary tank is determined by tank_injection_rate, which defaults +//to 10, and can be altered by the user with a verb. The amount taken from the primary tank is altered slightly per-reagent, +//based on that reagent's custom_metabolism value, in order to avoid taking too much of a reagent just because that reagent +//happens to metabolize more slowly than others. + +//Additionally, the chemical pack has an auxiliary chamber which can store any /obj/item/weapon/reagent_containers/glass item. +//While capped at the largest beaker size, currently 300u, this chamber offers more control over the way in which reagents +//are administered from it. It defaults to a threshold-based system, in which it injects 10u of creatine when the user falls +//below 10u of creatine in their body. However, the user can alter the settings and change it to a time-based system, change +//the time interval, the amount injected, and the reagent monitored by the threshold system, through verbs. + +//By default, the primary tank is connected to the mask, and the auxiliary beaker is disconnected. The user may toggle these +//connections using verbs. When disconnected, the mask will not take any additional reagents from the primary tank and/or the +//auxiliary beaker. Cycling these verbs will not force injections, the tank is still only capable of one injection per 97 seconds, +//and the beaker has no need to be forced to inject since the user can alter its time interval directly. +#define THRESHOLD "Threshold-based" +#define TIME "Time-based" + +/obj/item/clothing/mask/chemmask + desc = "A rather sinister mask designed for connection to a chemical pack, providing the pack's safeties are disabled." + name = "chemical mask" + icon_state = "chemmask0" + flags = FPRINT | MASKINTERNALS + w_class = 2 + var/power = 0 + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + var/tank_injection_rate = 10 + var/tank_has_injected = 0 + var/beaker_injection_methods = list(TIME,THRESHOLD) + var/beaker_injection_method = THRESHOLD + var/injection_method_chosen = 0 + var/beaker_time_interval = 970 + var/beaker_injection_rate = 10 + var/beaker_threshold = 10 + var/beaker_threshold_reagent = "creatine" + var/beaker_has_injected_time = 0 + var/firstalert_tank = 0 + var/firstalert_beaker = 0 + var/beakeractive = 0 + var/tankactive = 1 + var/time_at_last_tank_inject = 0 //This will ensure that the mask will always inject instantly the first time the user turns it on. + var/time_at_last_beaker_inject = 0 //It will prevent the chemmask from functioning for the first minute and 37 seconds of the world's existence, but I don't think that'll ever be a problem. + var/beaker_verbs_time = list( + /obj/item/clothing/mask/chemmask/verb/set_beaker_time_interval + ) + var/beaker_verbs_threshold = list( + /obj/item/clothing/mask/chemmask/verb/set_beaker_threshold, + /obj/item/clothing/mask/chemmask/verb/set_beaker_threshold_reagent + ) + species_fit = list("Vox") + body_parts_covered = HEAD|MOUTH + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/chempack.dmi', "right_hand" = 'icons/mob/in-hand/right/chempack.dmi') + origin_tech = "biotech=5;materials=5;engineering=5;syndicate=5;combat=5" + +/obj/item/clothing/mask/chemmask/New() //Doing this so that these verbs don't show up before there's actually a beaker in the pack. + ..() + processing_objects.Add(src) + update_verbs() + +/obj/item/clothing/mask/chemmask/Destroy() + processing_objects.Remove(src) + ..() + +/obj/item/clothing/mask/chemmask/equipped(M as mob, wear_mask) + var/mob/living/carbon/human/H = M + if(H.wear_mask == src) + update_verbs() + +/obj/item/clothing/mask/chemmask/proc/update_verbs() + var/mob/living/carbon/human/H + if (power) + verbs += /obj/item/clothing/mask/chemmask/verb/set_pack_injection + else + verbs -= /obj/item/clothing/mask/chemmask/verb/set_pack_injection + if (istype(loc,/mob/living/carbon/human)) //It runtimes if it calls this on a turf, which it does when it first spawns. + H = loc + else + return + if (istype(H.back,/obj/item/weapon/reagent_containers/chempack)) + verbs += /obj/item/clothing/mask/chemmask/verb/set_tank_usage + else + verbs -= /obj/item/clothing/mask/chemmask/verb/set_tank_usage + if (has_beaker(H)) + verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_usage + verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_method + if (injection_method_chosen) //Don't want the user to have to select the beaker injection method more than once per item. + if (beaker_injection_method == THRESHOLD) + verbs += beaker_verbs_threshold + verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate + verbs -= beaker_verbs_time + else if (beaker_injection_method == TIME) + verbs += beaker_verbs_time + verbs += /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate + verbs -= beaker_verbs_threshold + else + verbs -= beaker_verbs_time + verbs -= beaker_verbs_threshold + verbs -= /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate + else + verbs -= /obj/item/clothing/mask/chemmask/verb/set_beaker_usage + verbs -= /obj/item/clothing/mask/chemmask/verb/set_beaker_injection_method + verbs -= beaker_verbs_time + verbs -= beaker_verbs_threshold + +/obj/item/clothing/mask/chemmask/proc/can_use_verbs(mob/user) + var/mob/living/carbon/human/M = user + if (M.stat == DEAD) to_chat(user, "You can't do that while you're dead!") - return 0 - else if (M.stat == UNCONSCIOUS) + return 0 + else if (M.stat == UNCONSCIOUS) to_chat(user, "You must be conscious to do this!") - return 0 - else if (M.handcuffed) + return 0 + else if (M.handcuffed) to_chat(user, "You can't reach the controls while you're restrained!") - return 0 - else - return 1 - -/obj/item/clothing/mask/chemmask/examine(mob/user) - ..() - if (power) + return 0 + else + return 1 + +/obj/item/clothing/mask/chemmask/examine(mob/user) + ..() + if (power) to_chat(user, "The mask is active!") - if (tankactive) + if (tankactive) to_chat(user, "The mask is drawing from the main tank.") - else + else to_chat(user, "The mask is not drawing from the main tank.") - if (beakeractive && has_beaker(user)) + if (beakeractive && has_beaker(user)) to_chat(user, "The mask is drawing from the auxiliary beaker.") - else if (!beakeractive && has_beaker(user)) + else if (!beakeractive && has_beaker(user)) to_chat(user, "The mask is not drawing from the auxiliary beaker.") - else - var/mob/living/carbon/human/M = user - if(M.wear_mask == src) + else + var/mob/living/carbon/human/M = user + if(M.wear_mask == src) to_chat(user, "The mask is inactive.") - if (tankactive) + if (tankactive) to_chat(user, "The mask is set to draw from the main tank.") - else + else to_chat(user, "The mask is not set to draw from the main tank.") - if (beakeractive && has_beaker(user)) + if (beakeractive && has_beaker(user)) to_chat(user, "The mask is set to draw from the auxiliary beaker.") - else if (!beakeractive && has_beaker(user)) + else if (!beakeractive && has_beaker(user)) to_chat(user, "The mask is not set to draw from the auxiliary beaker.") - -/obj/item/clothing/mask/chemmask/verb/toggle_power() - set name = "Toggle mask power" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - if (!power) - var/mob/living/M = usr - if (istype(M.back,/obj/item/weapon/reagent_containers/chempack)) - var/obj/item/weapon/reagent_containers/chempack/P = M.back - if (P.safety) + +/obj/item/clothing/mask/chemmask/verb/toggle_power() + set name = "Toggle mask power" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + if (!power) + var/mob/living/M = usr + if (istype(M.back,/obj/item/weapon/reagent_containers/chempack)) + var/obj/item/weapon/reagent_containers/chempack/P = M.back + if (P.safety) to_chat(usr, "You activate \the [src].") - power = 1 - icon_state = "chemmask1" -// start_flow(usr) - usr.update_inv_wear_mask() - update_verbs() - else + power = 1 + icon_state = "chemmask1" +// start_flow(usr) + usr.update_inv_wear_mask() + update_verbs() + else to_chat(usr, "You must disable \the [P]'s safeties before you can activate \the [src]!") - else + else to_chat(usr, "You need to be wearing a chemical pack before you can activate \the [src]!") - else + else to_chat(usr, "You deactivate \the [src].") - mask_shutdown(usr) - -/obj/item/clothing/mask/chemmask/verb/set_pack_injection() - set name = "Set main tank injection rate" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/N = input("Set the number of units of each reagent in the chemical pack to be injected every 100 seconds. The injection rates of some chemicals will be altered to account for different rates of metabolism. Going over 10u may cause overdosing with some chemicals:","[src]") as null|num - //It's actually 97 seconds, so that more chems are injected before the user completely runs out. But 100 seconds sounded better and the player won't know the difference. - if (N) - tank_injection_rate = N - -/obj/item/clothing/mask/chemmask/verb/set_beaker_usage() - set name = "Toggle auxiliary beaker usage" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - if (!beakeractive) - beakeractive = 1 + mask_shutdown(usr) + +/obj/item/clothing/mask/chemmask/verb/set_pack_injection() + set name = "Set main tank injection rate" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/N = input("Set the number of units of each reagent in the chemical pack to be injected every 100 seconds. The injection rates of some chemicals will be altered to account for different rates of metabolism. Going over 10u may cause overdosing with some chemicals:","[src]") as null|num + //It's actually 97 seconds, so that more chems are injected before the user completely runs out. But 100 seconds sounded better and the player won't know the difference. + if (N) + tank_injection_rate = N + +/obj/item/clothing/mask/chemmask/verb/set_beaker_usage() + set name = "Toggle auxiliary beaker usage" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + if (!beakeractive) + beakeractive = 1 to_chat(usr, "You enable connection to the chemical pack's auxiliary beaker chamber.") - else - beakeractive = 0 + else + beakeractive = 0 to_chat(usr, "You disable connection to the chemical pack's auxiliary beaker chamber.") - -/obj/item/clothing/mask/chemmask/verb/set_tank_usage() - set name = "Toggle primary tank usage" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - if (!tankactive) - tankactive = 1 + +/obj/item/clothing/mask/chemmask/verb/set_tank_usage() + set name = "Toggle primary tank usage" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + if (!tankactive) + tankactive = 1 to_chat(usr, "You enable connection to the chemical pack's primary tank system.") - else - tankactive = 0 + else + tankactive = 0 to_chat(usr, "You disable connection to the chemical pack's primary tank system.") - -/obj/item/clothing/mask/chemmask/verb/set_beaker_injection_method() - set name = "Set auxiliary beaker injection method" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/N = input("Set the method by which \the [src] determines when to administer more chemicals from the auxiliary beaker:","[src]") as null|anything in beaker_injection_methods - if (N) - beaker_injection_method = N - injection_method_chosen = 1 - update_verbs() - -/obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate() - set name = "Set auxiliary beaker injection rate" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/N = input("Set the amount of chemicals administered from the auxiliary beaker when \the [src] administers more chemicals:","[src]") as null|num - if (N) - beaker_injection_rate = N - -/obj/item/clothing/mask/chemmask/verb/set_beaker_time_interval() - set name = "Set auxiliary beaker injection time interval" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/N = input("Set the time interval in seconds at which \the [src] will administer more chemicals from the auxiliary beaker:","[src]") as null|num - if (N) - beaker_time_interval = N*10 - -/obj/item/clothing/mask/chemmask/verb/set_beaker_threshold_reagent() - set name = "Set auxiliary beaker injection threshold reagent" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/obj/item/weapon/reagent_containers/chempack/P = usr.back - var/obj/item/weapon/reagent_containers/glass/B = P.beaker - var/beaker_threshold_reagents = B.get_reagent_ids() - - var/N = input("Set the reagent for which the minimum threshold must be reached to cause \the [src] to administer more chemicals from the auxiliary beaker:","[src]") as null|anything in beaker_threshold_reagents - if (N) - beaker_threshold_reagent = N - -/obj/item/clothing/mask/chemmask/verb/set_beaker_threshold() - set name = "Set auxiliary beaker injection threshold" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/N = input("Set the minimum threshold of [beaker_threshold_reagent] in your body that must be reached to cause \the [src] to administer more chemicals:","[src]") as null|num - if (N) - beaker_threshold = N - -/obj/item/clothing/mask/chemmask/proc/pack_check(mob/user) //Shuts off mask if the user is not wearing a chempack. - var/mob/living/M = user - if (!(M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack))) - mask_shutdown(user) + +/obj/item/clothing/mask/chemmask/verb/set_beaker_injection_method() + set name = "Set auxiliary beaker injection method" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/N = input("Set the method by which \the [src] determines when to administer more chemicals from the auxiliary beaker:","[src]") as null|anything in beaker_injection_methods + if (N) + beaker_injection_method = N + injection_method_chosen = 1 + update_verbs() + +/obj/item/clothing/mask/chemmask/verb/set_beaker_injection_rate() + set name = "Set auxiliary beaker injection rate" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/N = input("Set the amount of chemicals administered from the auxiliary beaker when \the [src] administers more chemicals:","[src]") as null|num + if (N) + beaker_injection_rate = N + +/obj/item/clothing/mask/chemmask/verb/set_beaker_time_interval() + set name = "Set auxiliary beaker injection time interval" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/N = input("Set the time interval in seconds at which \the [src] will administer more chemicals from the auxiliary beaker:","[src]") as null|num + if (N) + beaker_time_interval = N*10 + +/obj/item/clothing/mask/chemmask/verb/set_beaker_threshold_reagent() + set name = "Set auxiliary beaker injection threshold reagent" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/obj/item/weapon/reagent_containers/chempack/P = usr.back + var/obj/item/weapon/reagent_containers/glass/B = P.beaker + var/beaker_threshold_reagents = B.get_reagent_ids() + + var/N = input("Set the reagent for which the minimum threshold must be reached to cause \the [src] to administer more chemicals from the auxiliary beaker:","[src]") as null|anything in beaker_threshold_reagents + if (N) + beaker_threshold_reagent = N + +/obj/item/clothing/mask/chemmask/verb/set_beaker_threshold() + set name = "Set auxiliary beaker injection threshold" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/N = input("Set the minimum threshold of [beaker_threshold_reagent] in your body that must be reached to cause \the [src] to administer more chemicals:","[src]") as null|num + if (N) + beaker_threshold = N + +/obj/item/clothing/mask/chemmask/proc/pack_check(mob/user) //Shuts off mask if the user is not wearing a chempack. + var/mob/living/M = user + if (!(M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack))) + mask_shutdown(user) to_chat(user, "\The [src] shuts off!") - return 0 - else - return 1 - -/obj/item/clothing/mask/chemmask/proc/mask_check(mob/user) //Shuts off mask if it is not being worn by someone. - var/mob/living/M = user - if (!(M && M.wear_mask && istype(M.wear_mask,/obj/item/clothing/mask/chemmask))) - mask_shutdown(user) + return 0 + else + return 1 + +/obj/item/clothing/mask/chemmask/proc/mask_check(mob/user) //Shuts off mask if it is not being worn by someone. + var/mob/living/M = user + if (!(M && M.wear_mask && istype(M.wear_mask,/obj/item/clothing/mask/chemmask))) + mask_shutdown(user) to_chat(user, "\The [src] shuts off!") - return 0 - else if (!(M.wear_mask == src)) - mask_shutdown(user) + return 0 + else if (!(M.wear_mask == src)) + mask_shutdown(user) to_chat(user, "\The [src] shuts off!") - return 0 - else - return 1 - -/obj/item/clothing/mask/chemmask/proc/tank_volume_check(mob/user) //Alerts the user when the tank runs out of reagents. Does not alert them more than once per emptying, it must be refilled and then run dry again to alert them again. - var/obj/item/weapon/reagent_containers/chempack/P = user.back - if (P.is_empty() && firstalert_tank == 0 && tankactive) - firstalert_tank = 1 + return 0 + else + return 1 + +/obj/item/clothing/mask/chemmask/proc/tank_volume_check(mob/user) //Alerts the user when the tank runs out of reagents. Does not alert them more than once per emptying, it must be refilled and then run dry again to alert them again. + var/obj/item/weapon/reagent_containers/chempack/P = user.back + if (P.is_empty() && firstalert_tank == 0 && tankactive) + firstalert_tank = 1 to_chat(user, "The chemical pack is empty!") - else if (!P.is_empty()) - firstalert_tank = 0 - -/obj/item/clothing/mask/chemmask/proc/has_beaker(mob/user) //Checks whether there is a beaker in the pack, in order to determine whether to show the beaker-specific verbs. - if(user.back && istype(user.back, /obj/item/weapon/reagent_containers/chempack)) - var/obj/item/weapon/reagent_containers/chempack/P = user.back - return !isnull(P.beaker) - -/obj/item/clothing/mask/chemmask/proc/beaker_volume_check(mob/user) //Alerts the user when the auxiliary beaker is empty. Unlike the tank alert, this alert plays a sound, since the auxiliary beaker will most likely have higher-priority chems in it. - var/obj/item/weapon/reagent_containers/chempack/P = user.back - var/obj/item/weapon/reagent_containers/glass/B = P.beaker - if (B.is_empty() && firstalert_beaker == 0) - firstalert_beaker = 1 - playsound(get_turf(src),'sound/mecha/internaldmgalarm.ogg', 100, 1) + else if (!P.is_empty()) + firstalert_tank = 0 + +/obj/item/clothing/mask/chemmask/proc/has_beaker(mob/user) //Checks whether there is a beaker in the pack, in order to determine whether to show the beaker-specific verbs. + if(user.back && istype(user.back, /obj/item/weapon/reagent_containers/chempack)) + var/obj/item/weapon/reagent_containers/chempack/P = user.back + return !isnull(P.beaker) + +/obj/item/clothing/mask/chemmask/proc/beaker_volume_check(mob/user) //Alerts the user when the auxiliary beaker is empty. Unlike the tank alert, this alert plays a sound, since the auxiliary beaker will most likely have higher-priority chems in it. + var/obj/item/weapon/reagent_containers/chempack/P = user.back + var/obj/item/weapon/reagent_containers/glass/B = P.beaker + if (B.is_empty() && firstalert_beaker == 0) + firstalert_beaker = 1 + playsound(get_turf(src),'sound/mecha/internaldmgalarm.ogg', 100, 1) to_chat(user, "The auxiliary beaker is empty!") - else if (!B.is_empty()) - firstalert_beaker = 0 - -/obj/item/clothing/mask/chemmask/proc/mask_shutdown(mob/user) //Removes most verbs upon toggling the mask off, but not all. The user keeps access to the verbs to toggle connection to the tank and beaker. - power = 0 - icon_state = "chemmask0" - user.update_inv_wear_mask() - update_verbs() - -/obj/item/clothing/mask/chemmask/process() - var/mob/living/carbon/human/H = loc - if(power) - if (!pack_check(H)) - return - if (!mask_check(H)) - return - tank_volume_check(H) - update_verbs() - if ((world.time - time_at_last_tank_inject) >= 970) //One minute thirty-seven seconds. Roughly the time it takes 10u of anti-toxin to be metabolized. - tank_has_injected = 0 - if (tankactive) - if (!tank_has_injected) - inject(H) - tank_has_injected = 1 - time_at_last_tank_inject = world.time - if ((world.time - time_at_last_beaker_inject) >= beaker_time_interval) - beaker_has_injected_time = 0 - if (has_beaker(H)) - if (beakeractive) - if (beaker_injection_method == TIME && !beaker_has_injected_time) - beakerinject(H) - beaker_has_injected_time = 1 - time_at_last_beaker_inject = world.time - else if (beaker_injection_method == THRESHOLD) - beakerinject(H) - beaker_volume_check(H) - -/obj/item/clothing/mask/chemmask/proc/inject(mob/user) - var/obj/item/weapon/reagent_containers/chempack/P = user.back - for(var/datum/reagent/R in P.reagents.reagent_list) - var/custom_injection_rate = (tank_injection_rate/(REAGENTS_METABOLISM/R.custom_metabolism)) - if (R.custom_metabolism == 0.03) - custom_injection_rate += 0.1 - if (R.custom_metabolism == 0.05) - custom_injection_rate += R.custom_metabolism - P.reagents.trans_id_to(user, R.id, custom_injection_rate) - -/obj/item/clothing/mask/chemmask/proc/beakerinject(mob/user) - var/obj/item/weapon/reagent_containers/chempack/P = user.back - var/obj/item/weapon/reagent_containers/glass/B = P.beaker - if (beaker_injection_method == TIME) - B.reagents.trans_to(user, beaker_injection_rate) - else if (beaker_injection_method == THRESHOLD) - var/shouldinject = 0 - var/datum/reagent/R1 = null - var/beakerhasreagent = 0 - var/userhasreagent = 0 - var/shouldnotinject = 0 - for(var/datum/reagent/R in B.reagents.reagent_list) //Cycle through each reagent in the beaker. - if (R.id == beaker_threshold_reagent) - R1 = R - beakerhasreagent = 1 - for(var/datum/reagent/RU in user.reagents.reagent_list) //Cycle through each reagent in the user. - if (RU.id == beaker_threshold_reagent) - userhasreagent = 1 - if (RU.volume > beaker_threshold) //If the user has more of the threshold reagent than the threshold, don't inject at all. - shouldnotinject = 1 - if ((RU.id == beaker_threshold_reagent) && (RU.volume < beaker_threshold)) - shouldinject = 1 - userhasreagent = 1 - - if (shouldinject && R1) - if (R1.volume < beaker_injection_rate) - var/T = R1.volume - B.reagents.trans_id_to(user, R1.id, beaker_injection_rate) - B.reagents.trans_to(user, (beaker_injection_rate - T)) - else - B.reagents.trans_id_to(user, R1.id, beaker_injection_rate) - - else if (!userhasreagent && beakerhasreagent) - B.reagents.trans_id_to(user, R1.id, beaker_injection_rate) - else if (!beakerhasreagent && !shouldnotinject) + else if (!B.is_empty()) + firstalert_beaker = 0 + +/obj/item/clothing/mask/chemmask/proc/mask_shutdown(mob/user) //Removes most verbs upon toggling the mask off, but not all. The user keeps access to the verbs to toggle connection to the tank and beaker. + power = 0 + icon_state = "chemmask0" + user.update_inv_wear_mask() + update_verbs() + +/obj/item/clothing/mask/chemmask/process() + var/mob/living/carbon/human/H = loc + if(power) + if (!pack_check(H)) + return + if (!mask_check(H)) + return + tank_volume_check(H) + update_verbs() + if ((world.time - time_at_last_tank_inject) >= 970) //One minute thirty-seven seconds. Roughly the time it takes 10u of anti-toxin to be metabolized. + tank_has_injected = 0 + if (tankactive) + if (!tank_has_injected) + inject(H) + tank_has_injected = 1 + time_at_last_tank_inject = world.time + if ((world.time - time_at_last_beaker_inject) >= beaker_time_interval) + beaker_has_injected_time = 0 + if (has_beaker(H)) + if (beakeractive) + if (beaker_injection_method == TIME && !beaker_has_injected_time) + beakerinject(H) + beaker_has_injected_time = 1 + time_at_last_beaker_inject = world.time + else if (beaker_injection_method == THRESHOLD) + beakerinject(H) + beaker_volume_check(H) + +/obj/item/clothing/mask/chemmask/proc/inject(mob/user) + var/obj/item/weapon/reagent_containers/chempack/P = user.back + for(var/datum/reagent/R in P.reagents.reagent_list) + var/custom_injection_rate = (tank_injection_rate/(REAGENTS_METABOLISM/R.custom_metabolism)) + if (R.custom_metabolism == 0.03) + custom_injection_rate += 0.1 + if (R.custom_metabolism == 0.05) + custom_injection_rate += R.custom_metabolism + P.reagents.trans_id_to(user, R.id, custom_injection_rate) + +/obj/item/clothing/mask/chemmask/proc/beakerinject(mob/user) + var/obj/item/weapon/reagent_containers/chempack/P = user.back + var/obj/item/weapon/reagent_containers/glass/B = P.beaker + if (beaker_injection_method == TIME) + B.reagents.trans_to(user, beaker_injection_rate) + else if (beaker_injection_method == THRESHOLD) + var/shouldinject = 0 + var/datum/reagent/R1 = null + var/beakerhasreagent = 0 + var/userhasreagent = 0 + var/shouldnotinject = 0 + for(var/datum/reagent/R in B.reagents.reagent_list) //Cycle through each reagent in the beaker. + if (R.id == beaker_threshold_reagent) + R1 = R + beakerhasreagent = 1 + for(var/datum/reagent/RU in user.reagents.reagent_list) //Cycle through each reagent in the user. + if (RU.id == beaker_threshold_reagent) + userhasreagent = 1 + if (RU.volume > beaker_threshold) //If the user has more of the threshold reagent than the threshold, don't inject at all. + shouldnotinject = 1 + if ((RU.id == beaker_threshold_reagent) && (RU.volume < beaker_threshold)) + shouldinject = 1 + userhasreagent = 1 + + if (shouldinject && R1) + if (R1.volume < beaker_injection_rate) + var/T = R1.volume + B.reagents.trans_id_to(user, R1.id, beaker_injection_rate) + B.reagents.trans_to(user, (beaker_injection_rate - T)) + else + B.reagents.trans_id_to(user, R1.id, beaker_injection_rate) + + else if (!userhasreagent && beakerhasreagent) + B.reagents.trans_id_to(user, R1.id, beaker_injection_rate) + else if (!beakerhasreagent && !shouldnotinject) B.reagents.trans_to(user, beaker_injection_rate) \ No newline at end of file diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index ecb38f07402..13f47c904b1 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -1,167 +1,167 @@ -/obj/item/clothing/mask/gas - name = "gas mask" - desc = "A face-covering mask that can be connected to an air supply." - icon_state = "gas_alt" - flags = FPRINT | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS - flags_inv = HIDEEARS|HIDEEYES|HIDEFACE - w_class = 3.0 - can_flip = 1 - action_button_name = "Toggle Mask" - item_state = "gas_alt" - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - siemens_coefficient = 0.9 - species_fit = list("Vox") - body_parts_covered = FULL_HEAD - -//Plague Dr suit can be found in clothing/suits/bio.dm -/obj/item/clothing/mask/gas/plaguedoctor - name = "plague doctor mask" - desc = "A modernised version of the classic design, this mask will not only filter out toxins but it can also be connected to an air supply." - icon_state = "plaguedoctor" - item_state = "gas_mask" - armor = list(melee = 0, bullet = 0, laser = 2,energy = 2, bomb = 0, bio = 75, rad = 0) - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/swat - name = "\improper SWAT mask" - desc = "A close-fitting tactical mask that can be connected to an air supply." - icon_state = "swat" - siemens_coefficient = 0.7 - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/syndicate - name = "syndicate mask" - desc = "A close-fitting tactical mask that can be connected to an air supply." - icon_state = "swat" - siemens_coefficient = 0.7 - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/voice - name = "gas mask" - //desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics." - var/mode = 0// 0==Scouter | 1==Night Vision | 2==Thermal | 3==Meson - var/voice = "Unknown" - var/vchange = 1//This didn't do anything before. It now checks if the mask has special functions/N - origin_tech = "syndicate=4" - action_button_name = "Toggle Mask" - species_fit = list("Vox") - var/list/clothing_choices = list() - -/obj/item/clothing/mask/gas/voice/New() - ..() - for(var/Type in typesof(/obj/item/clothing/mask) - list(/obj/item/clothing/mask, /obj/item/clothing/mask/gas/voice)) - clothing_choices += new Type - return - -/obj/item/clothing/mask/gas/voice/attackby(obj/item/I, mob/user) - ..() - if(!istype(I, /obj/item/clothing/mask) || istype(I, src.type)) - return 0 - else - var/obj/item/clothing/mask/M = I - if(src.clothing_choices.Find(M)) - to_chat(user, "[M.name]'s pattern is already stored.") - return - src.clothing_choices += M - to_chat(user, "[M.name]'s pattern absorbed by \the [src].") - return 1 - return 0 - -/obj/item/clothing/mask/gas/voice/verb/change() - set name = "Change Mask Form" - set category = "Object" - set src in usr - - var/obj/item/clothing/mask/A - A = input("Select Form to change it to", "BOOYEA", A) as null|anything in clothing_choices - if(!A ||(usr.stat)) - return - - desc = null - permeability_coefficient = 0.90 - - desc = A.desc - name = A.name - icon = A.icon - icon_state = A.icon_state - item_state = A.item_state - flags_inv = A.flags_inv - usr.update_inv_wear_mask(1) //so our overlays update. - -/obj/item/clothing/mask/gas/voice/attack_self(mob/user) - vchange = !vchange - to_chat(user, "The voice changer is now [vchange ? "on" : "off"]!") - -/obj/item/clothing/mask/gas/clown_hat - name = "clown wig and mask" - desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask." - icon_state = "clown" - item_state = "clown_hat" - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/clown_hat/wiz - name = "clown wig and mask" - desc = "Some pranksters are truly magical." - icon_state = "wizzclown" - item_state = "wizzclown" - //TODO species_fit = list("Vox") - -/obj/item/clothing/mask/gas/virusclown_hat - name = "clown wig and mask" - desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask." - icon_state = "clown" - item_state = "clown_hat" - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/sexyclown - name = "sexy-clown wig and mask" - desc = "A feminine clown mask for the dabbling crossdressers or female entertainers." - icon_state = "sexyclown" - item_state = "sexyclown" - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/mime - name = "mime mask" - desc = "The traditional mime's mask. It has an eerie facial posture." - icon_state = "mime" - item_state = "mime" - species_fit = list("Vox") - var/muted = 0 - -/obj/item/clothing/mask/gas/mime/treat_mask_speech(var/datum/speech/speech) - if(src.muted) - speech.message="" - -/obj/item/clothing/mask/gas/monkeymask - name = "monkey mask" - desc = "A mask used when acting as a monkey." - icon_state = "monkeymask" - item_state = "monkeymask" - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/sexymime - name = "sexy mime mask" - desc = "A traditional female mime's mask." - icon_state = "sexymime" - item_state = "sexymime" - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/death_commando - name = "Death Commando Mask" - icon_state = "death" - item_state = "death" - siemens_coefficient = 0.2 - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/cyborg - name = "cyborg visor" - desc = "Beep boop" - icon_state = "death" - species_fit = list("Vox") - -/obj/item/clothing/mask/gas/owl_mask - name = "owl mask" - desc = "Twoooo!" - icon_state = "owl" - species_fit = list("Vox") +/obj/item/clothing/mask/gas + name = "gas mask" + desc = "A face-covering mask that can be connected to an air supply." + icon_state = "gas_alt" + flags = FPRINT | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE + w_class = 3.0 + can_flip = 1 + action_button_name = "Toggle Mask" + item_state = "gas_alt" + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + siemens_coefficient = 0.9 + species_fit = list("Vox") + body_parts_covered = FULL_HEAD + +//Plague Dr suit can be found in clothing/suits/bio.dm +/obj/item/clothing/mask/gas/plaguedoctor + name = "plague doctor mask" + desc = "A modernised version of the classic design, this mask will not only filter out toxins but it can also be connected to an air supply." + icon_state = "plaguedoctor" + item_state = "gas_mask" + armor = list(melee = 0, bullet = 0, laser = 2,energy = 2, bomb = 0, bio = 75, rad = 0) + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/swat + name = "\improper SWAT mask" + desc = "A close-fitting tactical mask that can be connected to an air supply." + icon_state = "swat" + siemens_coefficient = 0.7 + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/syndicate + name = "syndicate mask" + desc = "A close-fitting tactical mask that can be connected to an air supply." + icon_state = "swat" + siemens_coefficient = 0.7 + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/voice + name = "gas mask" + //desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics." + var/mode = 0// 0==Scouter | 1==Night Vision | 2==Thermal | 3==Meson + var/voice = "Unknown" + var/vchange = 1//This didn't do anything before. It now checks if the mask has special functions/N + origin_tech = "syndicate=4" + action_button_name = "Toggle Mask" + species_fit = list("Vox") + var/list/clothing_choices = list() + +/obj/item/clothing/mask/gas/voice/New() + ..() + for(var/Type in typesof(/obj/item/clothing/mask) - list(/obj/item/clothing/mask, /obj/item/clothing/mask/gas/voice)) + clothing_choices += new Type + return + +/obj/item/clothing/mask/gas/voice/attackby(obj/item/I, mob/user) + ..() + if(!istype(I, /obj/item/clothing/mask) || istype(I, src.type)) + return 0 + else + var/obj/item/clothing/mask/M = I + if(src.clothing_choices.Find(M)) + to_chat(user, "[M.name]'s pattern is already stored.") + return + src.clothing_choices += M + to_chat(user, "[M.name]'s pattern absorbed by \the [src].") + return 1 + return 0 + +/obj/item/clothing/mask/gas/voice/verb/change() + set name = "Change Mask Form" + set category = "Object" + set src in usr + + var/obj/item/clothing/mask/A + A = input("Select Form to change it to", "BOOYEA", A) as null|anything in clothing_choices + if(!A ||(usr.stat)) + return + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon = A.icon + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + usr.update_inv_wear_mask(1) //so our overlays update. + +/obj/item/clothing/mask/gas/voice/attack_self(mob/user) + vchange = !vchange + to_chat(user, "The voice changer is now [vchange ? "on" : "off"]!") + +/obj/item/clothing/mask/gas/clown_hat + name = "clown wig and mask" + desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask." + icon_state = "clown" + item_state = "clown_hat" + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/clown_hat/wiz + name = "clown wig and mask" + desc = "Some pranksters are truly magical." + icon_state = "wizzclown" + item_state = "wizzclown" + //TODO species_fit = list("Vox") + +/obj/item/clothing/mask/gas/virusclown_hat + name = "clown wig and mask" + desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask." + icon_state = "clown" + item_state = "clown_hat" + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/sexyclown + name = "sexy-clown wig and mask" + desc = "A feminine clown mask for the dabbling crossdressers or female entertainers." + icon_state = "sexyclown" + item_state = "sexyclown" + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/mime + name = "mime mask" + desc = "The traditional mime's mask. It has an eerie facial posture." + icon_state = "mime" + item_state = "mime" + species_fit = list("Vox") + var/muted = 0 + +/obj/item/clothing/mask/gas/mime/treat_mask_speech(var/datum/speech/speech) + if(src.muted) + speech.message="" + +/obj/item/clothing/mask/gas/monkeymask + name = "monkey mask" + desc = "A mask used when acting as a monkey." + icon_state = "monkeymask" + item_state = "monkeymask" + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/sexymime + name = "sexy mime mask" + desc = "A traditional female mime's mask." + icon_state = "sexymime" + item_state = "sexymime" + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/death_commando + name = "Death Commando Mask" + icon_state = "death" + item_state = "death" + siemens_coefficient = 0.2 + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/cyborg + name = "cyborg visor" + desc = "Beep boop" + icon_state = "death" + species_fit = list("Vox") + +/obj/item/clothing/mask/gas/owl_mask + name = "owl mask" + desc = "Twoooo!" + icon_state = "owl" + species_fit = list("Vox") diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 6ea6fa3fea4..81bfff69352 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -1,117 +1,117 @@ -/obj/item/clothing/mask/muzzle - name = "muzzle" - desc = "To stop that awful noise." - icon_state = "muzzle" - item_state = "muzzle" - flags = FPRINT - w_class = 2 - gas_transfer_coefficient = 0.90 - species_fit = list("Vox") - origin_tech = "biotech=2" - -//Monkeys can not take the muzzle off of themself! Call PETA! -/obj/item/clothing/mask/muzzle/attack_paw(mob/user as mob) - if (src == user.wear_mask) - return - else - ..() - return - - -/obj/item/clothing/mask/surgical - name = "sterile mask" - desc = "A sterile mask designed to help prevent the spread of diseases." - icon_state = "sterile" - item_state = "sterile" - w_class = 1 - flags = FPRINT - gas_transfer_coefficient = 0.90 - permeability_coefficient = 0.01 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 25, rad = 0) - species_fit = list("Vox") - -/obj/item/clothing/mask/fakemoustache - name = "fake moustache" - desc = "Warning: moustache is fake." - icon_state = "fake-moustache" - flags = FPRINT - flags_inv = HIDEFACE - -//scarves (fit in in mask slot) -/obj/item/clothing/mask/scarf - flags = FPRINT - flags_inv = HIDEFACE - action_button_name = "Toggle Scarf" - w_class = 2 - gas_transfer_coefficient = 0.90 - can_flip = 1 - -/obj/item/clothing/mask/scarf/blue - name = "blue neck scarf" - desc = "A blue neck scarf." - icon_state = "blue_scarf" - item_state = "blue_scarf" - - -/obj/item/clothing/mask/scarf/red - name = "red scarf" - desc = "A red neck scarf." - icon_state = "red_scarf" - item_state = "red_scarf" - - -/obj/item/clothing/mask/scarf/green - name = "green scarf" - desc = "A green and red line patterned scarf." - icon_state = "green_scarf" - item_state = "green_scarf" - - -/obj/item/clothing/mask/pig - name = "pig mask" - desc = "A rubber pig mask." - icon_state = "pig" - item_state = "pig" - flags = FPRINT - flags_inv = HIDEFACE|HIDEHAIR - body_parts_covered = HEAD - w_class = 2 - siemens_coefficient = 0.9 - -/obj/item/clothing/mask/horsehead - name = "horse head mask" - desc = "A mask made of soft vinyl and latex, representing the head of a horse." - icon_state = "horsehead" - item_state = "horsehead" - flags = FPRINT - flags_inv = HIDEFACE|HIDEHAIR - body_parts_covered = HEAD - w_class = 2 - var/voicechange = 0 - siemens_coefficient = 0.9 - -/obj/item/clothing/mask/horsehead/treat_mask_speech(var/datum/speech/speech) - if(src.voicechange) - speech.message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") - -/obj/item/clothing/mask/chapmask - name = "venetian mask" - desc = "A plain porcelain mask that covers the entire face. Standard attire for particularly unspeakable religions. The eyes are wide shut." - icon_state = "chapmask" - item_state = "chapmask" - flags = FPRINT - flags_inv = HIDEFACE - w_class = 2 - gas_transfer_coefficient = 0.90 - -/obj/item/clothing/mask/bandana - name = "bandana" - desc = "A colorful bandana." - action_button_name = "Toggle Bandana" - flags_inv = HIDEFACE - w_class = 1 - can_flip = 1 - -obj/item/clothing/mask/bandana/red - name = "red bandana" - icon_state = "bandred" +/obj/item/clothing/mask/muzzle + name = "muzzle" + desc = "To stop that awful noise." + icon_state = "muzzle" + item_state = "muzzle" + flags = FPRINT + w_class = 2 + gas_transfer_coefficient = 0.90 + species_fit = list("Vox") + origin_tech = "biotech=2" + +//Monkeys can not take the muzzle off of themself! Call PETA! +/obj/item/clothing/mask/muzzle/attack_paw(mob/user as mob) + if (src == user.wear_mask) + return + else + ..() + return + + +/obj/item/clothing/mask/surgical + name = "sterile mask" + desc = "A sterile mask designed to help prevent the spread of diseases." + icon_state = "sterile" + item_state = "sterile" + w_class = 1 + flags = FPRINT + gas_transfer_coefficient = 0.90 + permeability_coefficient = 0.01 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 25, rad = 0) + species_fit = list("Vox") + +/obj/item/clothing/mask/fakemoustache + name = "fake moustache" + desc = "Warning: moustache is fake." + icon_state = "fake-moustache" + flags = FPRINT + flags_inv = HIDEFACE + +//scarves (fit in in mask slot) +/obj/item/clothing/mask/scarf + flags = FPRINT + flags_inv = HIDEFACE + action_button_name = "Toggle Scarf" + w_class = 2 + gas_transfer_coefficient = 0.90 + can_flip = 1 + +/obj/item/clothing/mask/scarf/blue + name = "blue neck scarf" + desc = "A blue neck scarf." + icon_state = "blue_scarf" + item_state = "blue_scarf" + + +/obj/item/clothing/mask/scarf/red + name = "red scarf" + desc = "A red neck scarf." + icon_state = "red_scarf" + item_state = "red_scarf" + + +/obj/item/clothing/mask/scarf/green + name = "green scarf" + desc = "A green and red line patterned scarf." + icon_state = "green_scarf" + item_state = "green_scarf" + + +/obj/item/clothing/mask/pig + name = "pig mask" + desc = "A rubber pig mask." + icon_state = "pig" + item_state = "pig" + flags = FPRINT + flags_inv = HIDEFACE|HIDEHAIR + body_parts_covered = HEAD + w_class = 2 + siemens_coefficient = 0.9 + +/obj/item/clothing/mask/horsehead + name = "horse head mask" + desc = "A mask made of soft vinyl and latex, representing the head of a horse." + icon_state = "horsehead" + item_state = "horsehead" + flags = FPRINT + flags_inv = HIDEFACE|HIDEHAIR + body_parts_covered = HEAD + w_class = 2 + var/voicechange = 0 + siemens_coefficient = 0.9 + +/obj/item/clothing/mask/horsehead/treat_mask_speech(var/datum/speech/speech) + if(src.voicechange) + speech.message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") + +/obj/item/clothing/mask/chapmask + name = "venetian mask" + desc = "A plain porcelain mask that covers the entire face. Standard attire for particularly unspeakable religions. The eyes are wide shut." + icon_state = "chapmask" + item_state = "chapmask" + flags = FPRINT + flags_inv = HIDEFACE + w_class = 2 + gas_transfer_coefficient = 0.90 + +/obj/item/clothing/mask/bandana + name = "bandana" + desc = "A colorful bandana." + action_button_name = "Toggle Bandana" + flags_inv = HIDEFACE + w_class = 1 + can_flip = 1 + +obj/item/clothing/mask/bandana/red + name = "red bandana" + icon_state = "bandred" diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index 97396f04d0b..1a093fc6687 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -1,113 +1,113 @@ -/obj/item/clothing/shoes/black - name = "black shoes" - icon_state = "black" - _color = "black" - desc = "A pair of black shoes." - species_fit = list("Vox") - - cold_protection = FEET - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = FEET - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/shoes/brown - name = "brown shoes" - desc = "A pair of brown shoes." - icon_state = "brown" - _color = "brown" - species_fit = list("Vox") - -/obj/item/clothing/shoes/brown/captain - _color = "captain" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/hop - _color = "hop" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/ce - _color = "chief" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/rd - _color = "director" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/cmo - _color = "medical" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/cargo - _color = "cargo" //Exists for washing machines. Is not different from brown shoes in any way. - - -/obj/item/clothing/shoes/blue - name = "blue shoes" - icon_state = "blue" - _color = "blue" - -/obj/item/clothing/shoes/green - name = "green shoes" - icon_state = "green" - _color = "green" - -/obj/item/clothing/shoes/yellow - name = "yellow shoes" - icon_state = "yellow" - _color = "yellow" - -/obj/item/clothing/shoes/purple - name = "purple shoes" - icon_state = "purple" - _color = "purple" - -/obj/item/clothing/shoes/red - name = "red shoes" - desc = "Stylish red shoes." - icon_state = "red" - _color = "red" - -/obj/item/clothing/shoes/red/redcoat - _color = "redcoat" //Exists for washing machines. Is not different from normal shoes in any way. - -/obj/item/clothing/shoes/white - name = "white shoes" - icon_state = "white" - permeability_coefficient = 0.01 - _color = "white" - species_fit = list("Vox") - -/obj/item/clothing/shoes/leather - name = "leather shoes" - desc = "A sturdy pair of leather shoes." - icon_state = "leather" - _color = "leather" - -/obj/item/clothing/shoes/rainbow - name = "rainbow shoes" - desc = "Very gay shoes." - icon_state = "rain_bow" - _color = "rainbow" - -/obj/item/clothing/shoes/orange - name = "orange shoes" - icon_state = "orange" - _color = "orange" - species_fit = list("Vox") - -/obj/item/clothing/shoes/orange/attack_self(mob/user as mob) - if (src.chained) - src.chained = null - src.slowdown = SHOES_SLOWDOWN - new chaintype( user.loc ) - src.icon_state = "orange" - return - -/obj/item/clothing/shoes/orange/attackby(var/obj/O, loc) - ..() - if ((istype(O, /obj/item/weapon/handcuffs) && !( src.chained ))) - var/obj/item/weapon/handcuffs/H=O - //H = null - if (src.icon_state != "orange") return - src.chained = 1 - src.chaintype = H.type - src.slowdown = 15 - src.icon_state = "orange1" - qdel(H) - H = null - return +/obj/item/clothing/shoes/black + name = "black shoes" + icon_state = "black" + _color = "black" + desc = "A pair of black shoes." + species_fit = list("Vox") + + cold_protection = FEET + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = FEET + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/shoes/brown + name = "brown shoes" + desc = "A pair of brown shoes." + icon_state = "brown" + _color = "brown" + species_fit = list("Vox") + +/obj/item/clothing/shoes/brown/captain + _color = "captain" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/hop + _color = "hop" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/ce + _color = "chief" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/rd + _color = "director" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/cmo + _color = "medical" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/cargo + _color = "cargo" //Exists for washing machines. Is not different from brown shoes in any way. + + +/obj/item/clothing/shoes/blue + name = "blue shoes" + icon_state = "blue" + _color = "blue" + +/obj/item/clothing/shoes/green + name = "green shoes" + icon_state = "green" + _color = "green" + +/obj/item/clothing/shoes/yellow + name = "yellow shoes" + icon_state = "yellow" + _color = "yellow" + +/obj/item/clothing/shoes/purple + name = "purple shoes" + icon_state = "purple" + _color = "purple" + +/obj/item/clothing/shoes/red + name = "red shoes" + desc = "Stylish red shoes." + icon_state = "red" + _color = "red" + +/obj/item/clothing/shoes/red/redcoat + _color = "redcoat" //Exists for washing machines. Is not different from normal shoes in any way. + +/obj/item/clothing/shoes/white + name = "white shoes" + icon_state = "white" + permeability_coefficient = 0.01 + _color = "white" + species_fit = list("Vox") + +/obj/item/clothing/shoes/leather + name = "leather shoes" + desc = "A sturdy pair of leather shoes." + icon_state = "leather" + _color = "leather" + +/obj/item/clothing/shoes/rainbow + name = "rainbow shoes" + desc = "Very gay shoes." + icon_state = "rain_bow" + _color = "rainbow" + +/obj/item/clothing/shoes/orange + name = "orange shoes" + icon_state = "orange" + _color = "orange" + species_fit = list("Vox") + +/obj/item/clothing/shoes/orange/attack_self(mob/user as mob) + if (src.chained) + src.chained = null + src.slowdown = SHOES_SLOWDOWN + new chaintype( user.loc ) + src.icon_state = "orange" + return + +/obj/item/clothing/shoes/orange/attackby(var/obj/O, loc) + ..() + if ((istype(O, /obj/item/weapon/handcuffs) && !( src.chained ))) + var/obj/item/weapon/handcuffs/H=O + //H = null + if (src.icon_state != "orange") return + src.chained = 1 + src.chaintype = H.type + src.slowdown = 15 + src.icon_state = "orange1" + qdel(H) + H = null + return diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 8aa376b6438..974875e34c5 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -1,65 +1,65 @@ -/obj/item/clothing/shoes/magboots - desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle." - name = "magboots" - icon_state = "magboots0" - var/base_state = "magboots" - var/magpulse = 0 - var/mag_slow = 2 -// flags = NOSLIP //disabled by default - action_button_name = "Toggle Magboots" - species_fit = list("Vox") - -/obj/item/clothing/shoes/magboots/verb/toggle() - set name = "Toggle Magboots" - set category = "Object" - set src in usr - if(usr.isUnconscious()) - return - if(src.magpulse) - src.flags &= ~NOSLIP - src.slowdown = SHOES_SLOWDOWN - src.magpulse = 0 - icon_state = "[base_state]0" - to_chat(usr, "You disable the mag-pulse traction system.") - else - src.flags |= NOSLIP - src.slowdown = mag_slow - src.magpulse = 1 - icon_state = "[base_state]1" - to_chat(usr, "You enable the mag-pulse traction system.") - usr.update_inv_shoes() //so our mob-overlays update - -/obj/item/clothing/shoes/magboots/attack_self() - src.toggle() - ..() - return - -/obj/item/clothing/shoes/magboots/examine(mob/user) - ..() - var/state = "disabled" - if(src.flags&NOSLIP) - state = "enabled" - to_chat(user, "Its mag-pulse traction system appears to be [state].") - -//CE -/obj/item/clothing/shoes/magboots/elite - desc = "Advanced magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle." - name = "advanced magboots" - icon_state = "CE-magboots0" - base_state = "CE-magboots" - mag_slow = 1 - -//Atmos techies die angry -/obj/item/clothing/shoes/magboots/atmos - desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle. These are painted in the colors of an atmospheric technician." - name = "atmospherics magboots" - icon_state = "atmosmagboots0" - base_state = "atmosmagboots" - -//Death squad -/obj/item/clothing/shoes/magboots/deathsquad - desc = "Very expensive and advanced magnetic boots, used only by the elite during extravehicular activity to ensure the user remains safely attached to the vehicle." - name = "deathsquad magboots" - icon_state = "DS-magboots0" - base_state = "DS-magboots" +/obj/item/clothing/shoes/magboots + desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle." + name = "magboots" + icon_state = "magboots0" + var/base_state = "magboots" + var/magpulse = 0 + var/mag_slow = 2 +// flags = NOSLIP //disabled by default + action_button_name = "Toggle Magboots" + species_fit = list("Vox") + +/obj/item/clothing/shoes/magboots/verb/toggle() + set name = "Toggle Magboots" + set category = "Object" + set src in usr + if(usr.isUnconscious()) + return + if(src.magpulse) + src.flags &= ~NOSLIP + src.slowdown = SHOES_SLOWDOWN + src.magpulse = 0 + icon_state = "[base_state]0" + to_chat(usr, "You disable the mag-pulse traction system.") + else + src.flags |= NOSLIP + src.slowdown = mag_slow + src.magpulse = 1 + icon_state = "[base_state]1" + to_chat(usr, "You enable the mag-pulse traction system.") + usr.update_inv_shoes() //so our mob-overlays update + +/obj/item/clothing/shoes/magboots/attack_self() + src.toggle() + ..() + return + +/obj/item/clothing/shoes/magboots/examine(mob/user) + ..() + var/state = "disabled" + if(src.flags&NOSLIP) + state = "enabled" + to_chat(user, "Its mag-pulse traction system appears to be [state].") + +//CE +/obj/item/clothing/shoes/magboots/elite + desc = "Advanced magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle." + name = "advanced magboots" + icon_state = "CE-magboots0" + base_state = "CE-magboots" + mag_slow = 1 + +//Atmos techies die angry +/obj/item/clothing/shoes/magboots/atmos + desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle. These are painted in the colors of an atmospheric technician." + name = "atmospherics magboots" + icon_state = "atmosmagboots0" + base_state = "atmosmagboots" + +//Death squad +/obj/item/clothing/shoes/magboots/deathsquad + desc = "Very expensive and advanced magnetic boots, used only by the elite during extravehicular activity to ensure the user remains safely attached to the vehicle." + name = "deathsquad magboots" + icon_state = "DS-magboots0" + base_state = "DS-magboots" mag_slow = 0 \ No newline at end of file diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 2265fd6df4d..e64207ce0c7 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -1,345 +1,345 @@ -/obj/item/clothing/shoes/proc/step_action() //this was made to rewrite clown shoes squeaking - -/obj/item/clothing/shoes/syndigaloshes - desc = "A pair of brown shoes. They seem to have extra grip." - name = "brown shoes" - icon_state = "brown" - item_state = "brown" - permeability_coefficient = 0.05 - flags = NOSLIP - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - siemens_coefficient = 0.8 - species_fit = list("Vox") - -/obj/item/clothing/shoes/syndigaloshes/New() - ..() - for(var/Type in typesof(/obj/item/clothing/shoes) - list(/obj/item/clothing/shoes, /obj/item/clothing/shoes/syndigaloshes)) - clothing_choices += new Type - return - -/obj/item/clothing/shoes/syndigaloshes/attackby(obj/item/I, mob/user) - ..() - if(!istype(I, /obj/item/clothing/shoes) || istype(I, src.type)) - return 0 - else - var/obj/item/clothing/shoes/S = I - if(src.clothing_choices.Find(S)) +/obj/item/clothing/shoes/proc/step_action() //this was made to rewrite clown shoes squeaking + +/obj/item/clothing/shoes/syndigaloshes + desc = "A pair of brown shoes. They seem to have extra grip." + name = "brown shoes" + icon_state = "brown" + item_state = "brown" + permeability_coefficient = 0.05 + flags = NOSLIP + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + siemens_coefficient = 0.8 + species_fit = list("Vox") + +/obj/item/clothing/shoes/syndigaloshes/New() + ..() + for(var/Type in typesof(/obj/item/clothing/shoes) - list(/obj/item/clothing/shoes, /obj/item/clothing/shoes/syndigaloshes)) + clothing_choices += new Type + return + +/obj/item/clothing/shoes/syndigaloshes/attackby(obj/item/I, mob/user) + ..() + if(!istype(I, /obj/item/clothing/shoes) || istype(I, src.type)) + return 0 + else + var/obj/item/clothing/shoes/S = I + if(src.clothing_choices.Find(S)) to_chat(user, "[S.name]'s pattern is already stored.") - return - src.clothing_choices += S + return + src.clothing_choices += S to_chat(user, "[S.name]'s pattern absorbed by \the [src].") - return 1 - return 0 - -/obj/item/clothing/shoes/syndigaloshes/verb/change() - set name = "Change Color" // This is a spelling mistake perpetrated by the american swine, the correct spelling is colour and GEORGE washington AKA george "terrorist" washington is not my presidnet. - set category = "Object" - set src in usr - - var/obj/item/clothing/shoes/A - A = input("Select Colour to change it to", "BOOYEA", A) as null|anything in clothing_choices - if(!A ||(usr.stat)) - return - - desc = null - permeability_coefficient = 0.90 - - desc = A.desc - desc += " They seem to have extra grip." - name = A.name - icon_state = A.icon_state - item_state = A.item_state - _color = A._color - usr.update_inv_w_uniform() //so our overlays update. - -/obj/item/clothing/shoes/mime - name = "mime shoes" - icon_state = "mime" - _color = "mime" - -/obj/item/clothing/shoes/mime/biker - name = "Biker's shoes" - -/obj/item/clothing/shoes/swat - name = "\improper SWAT shoes" - desc = "When you want to turn up the heat." - icon_state = "swat" - armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) - flags = NOSLIP - species_fit = list("Vox") - siemens_coefficient = 0.6 - -/obj/item/clothing/shoes/combat //Basically SWAT shoes combined with galoshes. - name = "combat boots" - desc = "When you REALLY want to turn up the heat" - icon_state = "swat" - armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) - flags = NOSLIP - species_fit = list("Vox") - siemens_coefficient = 0.6 - - cold_protection = FEET - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = FEET - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/shoes/sandal - desc = "A pair of rather plain, wooden sandals." - name = "sandals" - icon_state = "wizard" - - wizard_garb = 1 - -/obj/item/clothing/shoes/sandal/marisa - desc = "A pair of magic, black shoes." - name = "magic shoes" - icon_state = "black" - -/obj/item/clothing/shoes/sandal/marisa/leather - icon_state = "laceups" - item_state = "laceups" - -/obj/item/clothing/shoes/galoshes - desc = "Rubber boots" - name = "galoshes" - icon_state = "galoshes" - permeability_coefficient = 0.05 - flags = NOSLIP - slowdown = SHOES_SLOWDOWN+1 - species_fit = list("Vox") - -/obj/item/clothing/shoes/clown_shoes - desc = "The prankster's standard-issue clowning shoes. Damn they're huge!" - name = "clown shoes" - icon_state = "clown" - item_state = "clown_shoes" - slowdown = SHOES_SLOWDOWN+1 - _color = "clown" - - var/step_sound = "clownstep" - var/footstep = 1 //used for squeeks whilst walking - -/obj/item/clothing/shoes/clown_shoes/step_action() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - - if(H.m_intent == "run") - if(footstep > 1) - footstep = 0 - playsound(H, step_sound, 50, 1) // this will get annoying very fast. - else - footstep++ - else - playsound(H, step_sound, 20, 1) - -#define CLOWNSHOES_RANDOM_SOUND "random sound" - -/obj/item/clothing/shoes/clown_shoes/advanced - name = "advanced clown shoes" - desc = "Only granted to the most devout followers of Honkmother." - icon_state = "superclown" - item_state = "superclown" - flags = NOSLIP - var/list/sound_list = list( - "Clown squeak" = "clownstep", - "Bike horn" = 'sound/items/bikehorn.ogg', - "Air horn" = 'sound/items/AirHorn.ogg', - "Chewing" = 'sound/items/eatfood.ogg', - "Polaroid" = "polaroid", - "Gunshot" = 'sound/weapons/Gunshot.ogg', - "Ion gun" = 'sound/weapons/ion.ogg', - "Laser gun" = 'sound/weapons/Laser.ogg', - "Punch" = "punch", - "Shotgun" = 'sound/weapons/shotgun.ogg', - "Taser" = 'sound/weapons/Taser.ogg', - "Male scream" = "malescream", - "Female scream" = "femalescream", - "Sad trombone" = 'sound/misc/sadtrombone.ogg', - "Awooga" = 'sound/effects/awooga.ogg', - "Bubbles" = 'sound/effects/bubbles.ogg', - "EMP pulse" = 'sound/effects/EMPulse.ogg', - "Explosion" = "explosion", - "Glass" = 'sound/effects/glass_step.ogg', - "Mouse squeak" = 'sound/effects/mousesqueek.ogg', - "Meteor impact" = 'sound/effects/meteorimpact.ogg', - "Supermatter" = 'sound/effects/supermatter.ogg', - "Emitter" = 'sound/weapons/emitter.ogg', - "Laughter" = 'sound/effects/laughtrack.ogg', - "Mecha step" = 'sound/mecha/mechstep.ogg', - "Fart" = 'sound/misc/fart.ogg', - "Random" = CLOWNSHOES_RANDOM_SOUND) - var/random_sound = 0 - -/obj/item/clothing/shoes/clown_shoes/advanced/attack_self(mob/user) - if(user.mind && user.mind.assigned_role != "Clown") + return 1 + return 0 + +/obj/item/clothing/shoes/syndigaloshes/verb/change() + set name = "Change Color" // This is a spelling mistake perpetrated by the american swine, the correct spelling is colour and GEORGE washington AKA george "terrorist" washington is not my presidnet. + set category = "Object" + set src in usr + + var/obj/item/clothing/shoes/A + A = input("Select Colour to change it to", "BOOYEA", A) as null|anything in clothing_choices + if(!A ||(usr.stat)) + return + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + desc += " They seem to have extra grip." + name = A.name + icon_state = A.icon_state + item_state = A.item_state + _color = A._color + usr.update_inv_w_uniform() //so our overlays update. + +/obj/item/clothing/shoes/mime + name = "mime shoes" + icon_state = "mime" + _color = "mime" + +/obj/item/clothing/shoes/mime/biker + name = "Biker's shoes" + +/obj/item/clothing/shoes/swat + name = "\improper SWAT shoes" + desc = "When you want to turn up the heat." + icon_state = "swat" + armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) + flags = NOSLIP + species_fit = list("Vox") + siemens_coefficient = 0.6 + +/obj/item/clothing/shoes/combat //Basically SWAT shoes combined with galoshes. + name = "combat boots" + desc = "When you REALLY want to turn up the heat" + icon_state = "swat" + armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) + flags = NOSLIP + species_fit = list("Vox") + siemens_coefficient = 0.6 + + cold_protection = FEET + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = FEET + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/shoes/sandal + desc = "A pair of rather plain, wooden sandals." + name = "sandals" + icon_state = "wizard" + + wizard_garb = 1 + +/obj/item/clothing/shoes/sandal/marisa + desc = "A pair of magic, black shoes." + name = "magic shoes" + icon_state = "black" + +/obj/item/clothing/shoes/sandal/marisa/leather + icon_state = "laceups" + item_state = "laceups" + +/obj/item/clothing/shoes/galoshes + desc = "Rubber boots" + name = "galoshes" + icon_state = "galoshes" + permeability_coefficient = 0.05 + flags = NOSLIP + slowdown = SHOES_SLOWDOWN+1 + species_fit = list("Vox") + +/obj/item/clothing/shoes/clown_shoes + desc = "The prankster's standard-issue clowning shoes. Damn they're huge!" + name = "clown shoes" + icon_state = "clown" + item_state = "clown_shoes" + slowdown = SHOES_SLOWDOWN+1 + _color = "clown" + + var/step_sound = "clownstep" + var/footstep = 1 //used for squeeks whilst walking + +/obj/item/clothing/shoes/clown_shoes/step_action() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + + if(H.m_intent == "run") + if(footstep > 1) + footstep = 0 + playsound(H, step_sound, 50, 1) // this will get annoying very fast. + else + footstep++ + else + playsound(H, step_sound, 20, 1) + +#define CLOWNSHOES_RANDOM_SOUND "random sound" + +/obj/item/clothing/shoes/clown_shoes/advanced + name = "advanced clown shoes" + desc = "Only granted to the most devout followers of Honkmother." + icon_state = "superclown" + item_state = "superclown" + flags = NOSLIP + var/list/sound_list = list( + "Clown squeak" = "clownstep", + "Bike horn" = 'sound/items/bikehorn.ogg', + "Air horn" = 'sound/items/AirHorn.ogg', + "Chewing" = 'sound/items/eatfood.ogg', + "Polaroid" = "polaroid", + "Gunshot" = 'sound/weapons/Gunshot.ogg', + "Ion gun" = 'sound/weapons/ion.ogg', + "Laser gun" = 'sound/weapons/Laser.ogg', + "Punch" = "punch", + "Shotgun" = 'sound/weapons/shotgun.ogg', + "Taser" = 'sound/weapons/Taser.ogg', + "Male scream" = "malescream", + "Female scream" = "femalescream", + "Sad trombone" = 'sound/misc/sadtrombone.ogg', + "Awooga" = 'sound/effects/awooga.ogg', + "Bubbles" = 'sound/effects/bubbles.ogg', + "EMP pulse" = 'sound/effects/EMPulse.ogg', + "Explosion" = "explosion", + "Glass" = 'sound/effects/glass_step.ogg', + "Mouse squeak" = 'sound/effects/mousesqueek.ogg', + "Meteor impact" = 'sound/effects/meteorimpact.ogg', + "Supermatter" = 'sound/effects/supermatter.ogg', + "Emitter" = 'sound/weapons/emitter.ogg', + "Laughter" = 'sound/effects/laughtrack.ogg', + "Mecha step" = 'sound/mecha/mechstep.ogg', + "Fart" = 'sound/misc/fart.ogg', + "Random" = CLOWNSHOES_RANDOM_SOUND) + var/random_sound = 0 + +/obj/item/clothing/shoes/clown_shoes/advanced/attack_self(mob/user) + if(user.mind && user.mind.assigned_role != "Clown") to_chat(user, "These shoes are too powerful for you to handle!") - if(prob(25)) - if(ishuman(user)) - var/mob/living/carbon/human/H = user + if(prob(25)) + if(ishuman(user)) + var/mob/living/carbon/human/H = user to_chat(H, sound('sound/items/AirHorn.ogg')) to_chat(H, "HONK") - H.sleeping = 0 - H.stuttering += 20 - H.ear_deaf += 30 - H.Weaken(3) //Copied from honkerblast 5000 - if(prob(30)) - H.Stun(10) - H.Paralyse(4) - else - H.Jitter(500) - return - - var/new_sound = input(user,"Select the new step sound!","Advanced clown shoes") in sound_list - - if(Adjacent(user)) - if(step_sound == CLOWNSHOES_RANDOM_SOUND) - step_sound = "clownstep" + H.sleeping = 0 + H.stuttering += 20 + H.ear_deaf += 30 + H.Weaken(3) //Copied from honkerblast 5000 + if(prob(30)) + H.Stun(10) + H.Paralyse(4) + else + H.Jitter(500) + return + + var/new_sound = input(user,"Select the new step sound!","Advanced clown shoes") in sound_list + + if(Adjacent(user)) + if(step_sound == CLOWNSHOES_RANDOM_SOUND) + step_sound = "clownstep" to_chat(user, "You set [src]'s step sound to always be random!") - random_sound = 1 - else - step_sound = sound_list[new_sound] + random_sound = 1 + else + step_sound = sound_list[new_sound] to_chat(user, "You set [src]'s step sound to \"[new_sound]\"!") - random_sound = 0 - -/obj/item/clothing/shoes/clown_shoes/advanced/verb/ChangeSound() - set category = "Object" - set name = "Change Sound" - - return src.attack_self(usr) - -/obj/item/clothing/shoes/clown_shoes/advanced/step_action() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - - if(H.mind && H.mind.assigned_role != "Clown") - if( ( H.mind.assigned_role == "Mime" ) ) - H.Slip(3, 2, 1) - - return - - if(random_sound) - step_sound = sound_list[pick(sound_list)] - ..() - -#undef CLOWNSHOES_RANDOM_SOUND - -/obj/item/clothing/shoes/jackboots - name = "jackboots" - desc = "Nanotrasen-issue Security combat boots for combat scenarios or combat situations. All combat, all the time." - icon_state = "jackboots" - item_state = "jackboots" - _color = "hosred" - siemens_coefficient = 0.7 - species_fit = list("Vox") - -/obj/item/clothing/shoes/jackboots/batmanboots - name = "batboots" - desc = "Criminal stomping boots for fighting crime and looking good." - -/obj/item/clothing/shoes/cult - name = "boots" - desc = "A pair of boots worn by the followers of Nar-Sie." - icon_state = "cult" - item_state = "cult" - _color = "cult" - siemens_coefficient = 0.7 - - cold_protection = FEET - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = FEET - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/shoes/cult/cultify() - return - -/obj/item/clothing/shoes/cyborg - name = "cyborg boots" - desc = "Shoes for a cyborg costume" - icon_state = "boots" - -/obj/item/clothing/shoes/slippers - name = "bunny slippers" - desc = "Fluffy!" - icon_state = "slippers" - item_state = "slippers" - -/obj/item/clothing/shoes/slippers_worn - name = "worn bunny slippers" - desc = "Fluffy..." - icon_state = "slippers_worn" - item_state = "slippers_worn" - -/obj/item/clothing/shoes/laceup - name = "laceup shoes" - desc = "The height of fashion, and they're pre-polished!" - icon_state = "laceups" - species_fit = list("Vox") - -/obj/item/clothing/shoes/roman - name = "roman sandals" - desc = "Sandals with buckled leather straps on it." - icon_state = "roman" - item_state = "roman" - -/obj/item/clothing/shoes/simonshoes - name = "Simon's Shoes" - desc = "Simon's Shoes" - icon_state = "simonshoes" - item_state = "simonshoes" - species_fit = list("Vox") - -/obj/item/clothing/shoes/kneesocks - name = "kneesocks" - desc = "A pair of girly knee-high socks" - icon_state = "kneesock" - item_state = "kneesock" - -/obj/item/clothing/shoes/jestershoes - name = "Jester Shoes" - desc = "As worn by the clowns of old." - icon_state = "jestershoes" - item_state = "jestershoes" - -/obj/item/clothing/shoes/aviatorboots - name = "Aviator Boots" - desc = "Boots suitable for just about any occasion" - icon_state = "aviator_boots" - item_state = "aviator_boots" - species_restricted = list("exclude","Vox") - -/obj/item/clothing/shoes/libertyshoes - name = "Liberty Shoes" - desc = "Freedom isn't free, neither were these shoes." - icon_state = "libertyshoes" - item_state = "libertyshoes" - -/obj/item/clothing/shoes/megaboots - name = "DRN-001 Boots" - desc = "Large armored boots, very weak to large spikes." - icon_state = "megaboots" - item_state = "megaboots" - -/obj/item/clothing/shoes/protoboots - name = "Prototype Boots" - desc = "Functionally identical to the DRN-001 model's boots, but in red." - icon_state = "protoboots" - item_state = "protoboots" - -/obj/item/clothing/shoes/megaxboots - name = "Maverick Hunter boots" - desc = "Regardless of how much stronger these boots are than the DRN-001 model's, they're still extremely easy to pierce with a large spike." - icon_state = "megaxboots" - item_state = "megaxboots" - -/obj/item/clothing/shoes/joeboots - name = "Sniper Boots" - desc = "Nearly identical to the Prototype's boots, except in black." - icon_state = "joeboots" - item_state = "joeboots" - -/obj/item/clothing/shoes/doomguy - name = "Doomguy's boots" - desc = "" - icon_state = "doom" - item_state = "doom" + random_sound = 0 + +/obj/item/clothing/shoes/clown_shoes/advanced/verb/ChangeSound() + set category = "Object" + set name = "Change Sound" + + return src.attack_self(usr) + +/obj/item/clothing/shoes/clown_shoes/advanced/step_action() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + + if(H.mind && H.mind.assigned_role != "Clown") + if( ( H.mind.assigned_role == "Mime" ) ) + H.Slip(3, 2, 1) + + return + + if(random_sound) + step_sound = sound_list[pick(sound_list)] + ..() + +#undef CLOWNSHOES_RANDOM_SOUND + +/obj/item/clothing/shoes/jackboots + name = "jackboots" + desc = "Nanotrasen-issue Security combat boots for combat scenarios or combat situations. All combat, all the time." + icon_state = "jackboots" + item_state = "jackboots" + _color = "hosred" + siemens_coefficient = 0.7 + species_fit = list("Vox") + +/obj/item/clothing/shoes/jackboots/batmanboots + name = "batboots" + desc = "Criminal stomping boots for fighting crime and looking good." + +/obj/item/clothing/shoes/cult + name = "boots" + desc = "A pair of boots worn by the followers of Nar-Sie." + icon_state = "cult" + item_state = "cult" + _color = "cult" + siemens_coefficient = 0.7 + + cold_protection = FEET + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = FEET + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/shoes/cult/cultify() + return + +/obj/item/clothing/shoes/cyborg + name = "cyborg boots" + desc = "Shoes for a cyborg costume" + icon_state = "boots" + +/obj/item/clothing/shoes/slippers + name = "bunny slippers" + desc = "Fluffy!" + icon_state = "slippers" + item_state = "slippers" + +/obj/item/clothing/shoes/slippers_worn + name = "worn bunny slippers" + desc = "Fluffy..." + icon_state = "slippers_worn" + item_state = "slippers_worn" + +/obj/item/clothing/shoes/laceup + name = "laceup shoes" + desc = "The height of fashion, and they're pre-polished!" + icon_state = "laceups" + species_fit = list("Vox") + +/obj/item/clothing/shoes/roman + name = "roman sandals" + desc = "Sandals with buckled leather straps on it." + icon_state = "roman" + item_state = "roman" + +/obj/item/clothing/shoes/simonshoes + name = "Simon's Shoes" + desc = "Simon's Shoes" + icon_state = "simonshoes" + item_state = "simonshoes" + species_fit = list("Vox") + +/obj/item/clothing/shoes/kneesocks + name = "kneesocks" + desc = "A pair of girly knee-high socks" + icon_state = "kneesock" + item_state = "kneesock" + +/obj/item/clothing/shoes/jestershoes + name = "Jester Shoes" + desc = "As worn by the clowns of old." + icon_state = "jestershoes" + item_state = "jestershoes" + +/obj/item/clothing/shoes/aviatorboots + name = "Aviator Boots" + desc = "Boots suitable for just about any occasion" + icon_state = "aviator_boots" + item_state = "aviator_boots" + species_restricted = list("exclude","Vox") + +/obj/item/clothing/shoes/libertyshoes + name = "Liberty Shoes" + desc = "Freedom isn't free, neither were these shoes." + icon_state = "libertyshoes" + item_state = "libertyshoes" + +/obj/item/clothing/shoes/megaboots + name = "DRN-001 Boots" + desc = "Large armored boots, very weak to large spikes." + icon_state = "megaboots" + item_state = "megaboots" + +/obj/item/clothing/shoes/protoboots + name = "Prototype Boots" + desc = "Functionally identical to the DRN-001 model's boots, but in red." + icon_state = "protoboots" + item_state = "protoboots" + +/obj/item/clothing/shoes/megaxboots + name = "Maverick Hunter boots" + desc = "Regardless of how much stronger these boots are than the DRN-001 model's, they're still extremely easy to pierce with a large spike." + icon_state = "megaxboots" + item_state = "megaxboots" + +/obj/item/clothing/shoes/joeboots + name = "Sniper Boots" + desc = "Nearly identical to the Prototype's boots, except in black." + icon_state = "joeboots" + item_state = "joeboots" + +/obj/item/clothing/shoes/doomguy + name = "Doomguy's boots" + desc = "" + icon_state = "doom" + item_state = "doom" diff --git a/code/modules/clothing/spacesuits/captain.dm b/code/modules/clothing/spacesuits/captain.dm index da316d28c9d..d469ab8a9ec 100644 --- a/code/modules/clothing/spacesuits/captain.dm +++ b/code/modules/clothing/spacesuits/captain.dm @@ -1,32 +1,32 @@ -//Captain's Spacesuit -/obj/item/clothing/head/helmet/space/capspace - name = "space helmet" - icon_state = "capspace" - item_state = "capspacehelmet" - desc = "A special helmet designed for work in a hazardous, low-pressure environment. Only for the most fashionable of military figureheads." - flags_inv = HIDEFACE - permeability_coefficient = 0.01 - pressure_resistance = 200 * ONE_ATMOSPHERE - armor = list(melee = 65, bullet = 50, laser = 50,energy = 25, bomb = 50, bio = 100, rad = 50) - species_fit = list("Vox") - -//Captain's space suit This is not the proper path but I don't currently know enough about how this all works to mess with it. -/obj/item/clothing/suit/armor/captain - name = "Captain's armor" - desc = "A bulky, heavy-duty piece of exclusive Nanotrasen armor. YOU are in charge!" - icon_state = "caparmor" - item_state = "capspacesuit" - species_fit = list("Vox") - w_class = 4 - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.02 - flags = FPRINT - pressure_resistance = 200 * ONE_ATMOSPHERE - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS - 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_storage, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_nitrogen) - slowdown = 1.5 - armor = list(melee = 65, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) - flags_inv = HIDEJUMPSUIT - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.7 +//Captain's Spacesuit +/obj/item/clothing/head/helmet/space/capspace + name = "space helmet" + icon_state = "capspace" + item_state = "capspacehelmet" + desc = "A special helmet designed for work in a hazardous, low-pressure environment. Only for the most fashionable of military figureheads." + flags_inv = HIDEFACE + permeability_coefficient = 0.01 + pressure_resistance = 200 * ONE_ATMOSPHERE + armor = list(melee = 65, bullet = 50, laser = 50,energy = 25, bomb = 50, bio = 100, rad = 50) + species_fit = list("Vox") + +//Captain's space suit This is not the proper path but I don't currently know enough about how this all works to mess with it. +/obj/item/clothing/suit/armor/captain + name = "Captain's armor" + desc = "A bulky, heavy-duty piece of exclusive Nanotrasen armor. YOU are in charge!" + icon_state = "caparmor" + item_state = "capspacesuit" + species_fit = list("Vox") + w_class = 4 + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.02 + flags = FPRINT + pressure_resistance = 200 * ONE_ATMOSPHERE + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS + 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_storage, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_nitrogen) + slowdown = 1.5 + armor = list(melee = 65, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) + flags_inv = HIDEJUMPSUIT + 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 527ad4cea11..46403947e6b 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -1,55 +1,55 @@ -//Paramedic EVA suit -/obj/item/clothing/head/helmet/space/paramedic - name = "Paramedic EVA helmet" - desc = "A paramedic space helmet. Used in the recovery of bodies from space." - icon_state = "paramedic-eva-helmet" - item_state = "paramedic-eva-helmet" - species_restricted = list("exclude","Vox") - -/obj/item/clothing/suit/space/paramedic - name = "Paramedic EVA suit" - icon_state = "paramedic-eva" - item_state = "paramedic-eva" - desc = "A paramedic space suit. Used in the recovery of bodies from space." - species_restricted = list("exclude","Vox") - slowdown = 1 - -//Space santa outfit suit -/obj/item/clothing/head/helmet/space/santahat - name = "Santa's hat" - desc = "Ho ho ho. Merrry X-mas!" - icon_state = "santahat" - flags = FPRINT - -/obj/item/clothing/suit/space/santa - name = "Santa's suit" - desc = "Festive!" - icon_state = "santa" - item_state = "santa" - slowdown = 0 - flags = FPRINT | ONESIZEFITSALL - allowed = list(/obj/item) //for stuffing exta special presents - - -//Space pirate outfit -/obj/item/clothing/head/helmet/space/pirate - name = "pirate hat" - desc = "Yarr." - icon_state = "pirate" - item_state = "pirate" - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0.9 - - -/obj/item/clothing/suit/space/pirate - name = "pirate coat" - desc = "Yarr." - icon_state = "pirate" - item_state = "pirate" - w_class = 3 - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) - slowdown = 0 - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0.9 - - +//Paramedic EVA suit +/obj/item/clothing/head/helmet/space/paramedic + name = "Paramedic EVA helmet" + desc = "A paramedic space helmet. Used in the recovery of bodies from space." + icon_state = "paramedic-eva-helmet" + item_state = "paramedic-eva-helmet" + species_restricted = list("exclude","Vox") + +/obj/item/clothing/suit/space/paramedic + name = "Paramedic EVA suit" + icon_state = "paramedic-eva" + item_state = "paramedic-eva" + desc = "A paramedic space suit. Used in the recovery of bodies from space." + species_restricted = list("exclude","Vox") + slowdown = 1 + +//Space santa outfit suit +/obj/item/clothing/head/helmet/space/santahat + name = "Santa's hat" + desc = "Ho ho ho. Merrry X-mas!" + icon_state = "santahat" + flags = FPRINT + +/obj/item/clothing/suit/space/santa + name = "Santa's suit" + desc = "Festive!" + icon_state = "santa" + item_state = "santa" + slowdown = 0 + flags = FPRINT | ONESIZEFITSALL + allowed = list(/obj/item) //for stuffing exta special presents + + +//Space pirate outfit +/obj/item/clothing/head/helmet/space/pirate + name = "pirate hat" + desc = "Yarr." + icon_state = "pirate" + item_state = "pirate" + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0.9 + + +/obj/item/clothing/suit/space/pirate + name = "pirate coat" + desc = "Yarr." + icon_state = "pirate" + item_state = "pirate" + w_class = 3 + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) + slowdown = 0 + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0.9 + + diff --git a/code/modules/clothing/spacesuits/ninja.dm b/code/modules/clothing/spacesuits/ninja.dm index cbf642576d7..80f1f346df9 100644 --- a/code/modules/clothing/spacesuits/ninja.dm +++ b/code/modules/clothing/spacesuits/ninja.dm @@ -1,9 +1,9 @@ -/obj/item/clothing/suit/space/jetstream - desc = "It appears to be Jetstream Sam's suit" - name = "Jetstream Sam's suit" - icon_state = "jetstream" - item_state = "jetstream" - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/cell) - slowdown = 0 - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0.2 +/obj/item/clothing/suit/space/jetstream + desc = "It appears to be Jetstream Sam's suit" + name = "Jetstream Sam's suit" + icon_state = "jetstream" + item_state = "jetstream" + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/cell) + slowdown = 0 + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0.2 diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 6751edb527d..9c1fdac5d76 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -1,451 +1,451 @@ -//Regular rig suits -/obj/item/clothing/head/helmet/space/rig - name = "engineering hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." - icon_state = "rig0-engineering" - item_state = "eng_helm" - armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) - allowed = list(/obj/item/device/flashlight) - light_power = 1.7 - var/brightness_on = 4 //Luminosity when on. If modified, do NOT run update_brightness() directly - var/on = 0 //Remember to run update_brightness() when modified, otherwise disasters happen - var/no_light = 0 //Disables the helmet light when set to 1. Make sure to run check_light() if this is updated - _color = "engineering" //Determines used sprites: rig[on]-[_color]. Use update_icon() directly to update the sprite. NEEDS TO BE SET CORRECTLY FOR HELMETS - action_button_name = "Toggle Helmet Light" - heat_protection = HEAD - max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE - pressure_resistance = 200 * ONE_ATMOSPHERE - eyeprot = 3 - species_restricted = list("exclude","Vox") - -/obj/item/clothing/head/helmet/space/rig/New() - ..() - //Needed to properly handle helmets with no lights - check_light() - //Useful for helmets with special starting conditions (namely, starts lit) - update_brightness() - update_icon() - -/obj/item/clothing/head/helmet/space/rig/examine(mob/user) - - ..() - if(!no_light) //There is a light attached or integrated - to_chat(user, "The helmet is mounted with an Internal Lighting System, it is [on ? "":"un"]lit.") - -//We check no_light and update everything accordingly -//Used to clear up the action button and shut down the light if broken -//Minimizes snowflake coding and allows dynamically disabling the helmet's light if needed -/obj/item/clothing/head/helmet/space/rig/proc/check_light() - - - if(no_light) //There's no light on the helmet - if(on) //The helmet light is currently on - on = 0 //Force it off - update_brightness() //Update as neccesary - action_button_name = null //Disable the action button (which is only used to toggle the light, in theory) - else //We have a light - action_button_name = initial(action_button_name) //Make sure we restore the action button - -/obj/item/clothing/head/helmet/space/rig/proc/update_brightness() - - - if(on) - set_light(brightness_on) - else - set_light(0) - update_icon() - -/obj/item/clothing/head/helmet/space/rig/update_icon() - - icon_state = "rig[on]-[_color]" //No need for complicated if trees - -/obj/item/clothing/head/helmet/space/rig/attack_self(mob/user) - if(no_light) - return - - on = !on - update_icon() - user.update_inv_head() - - if(on) - set_light(brightness_on) - else - set_light(0) - user.update_inv_head() - -/obj/item/clothing/suit/space/rig - name = "engineering hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." - icon_state = "rig-engineering" - item_state = "eng_hardsuit" - slowdown = 1 - species_restricted = list("exclude","Vox") - armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/device/rcd, /obj/item/weapon/wrench/socket) - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE - pressure_resistance = 200 * ONE_ATMOSPHERE - -//Chief Engineer's rig -/obj/item/clothing/head/helmet/space/rig/elite - name = "advanced hardsuit helmet" - desc = "An advanced helmet designed for work in a hazardous, low pressure environment. Shines with a high polish." - icon_state = "rig0-white" - item_state = "ce_helm" - _color = "white" - species_restricted = list("exclude","Vox") - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - flags = FPRINT | PLASMAGUARD - -/obj/item/clothing/suit/space/rig/elite - icon_state = "rig-white" - name = "advanced hardsuit" - species_restricted = list("exclude","Vox") - desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." - item_state = "ce_hardsuit" - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - flags = FPRINT | PLASMAGUARD - - -//Mining rig -/obj/item/clothing/head/helmet/space/rig/mining - name = "mining hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low pressure environment. Has reinforced plating." - icon_state = "rig0-mining" - item_state = "mining_helm" - _color = "mining" - species_restricted = list("exclude","Vox") - pressure_resistance = 40 * ONE_ATMOSPHERE - -/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" - species_restricted = list("exclude","Vox") - pressure_resistance = 40 * ONE_ATMOSPHERE - - -//Syndicate rig -/obj/item/clothing/head/helmet/space/rig/syndi - name = "blood-red hardsuit helmet" - desc = "An advanced helmet designed for work in special operations. Property of Gorlex Marauders." - icon_state = "rig0-syndi" - item_state = "syndie_helm" - species_fit = list("Vox") - _color = "syndi" - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60) - action_button_name = "Toggle Helmet Camera" //This helmet does not have a light, but we'll do as if - siemens_coefficient = 0.6 - var/obj/machinery/camera/camera - pressure_resistance = 40 * ONE_ATMOSPHERE - - species_restricted = null - -/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) - if(camera) - ..(user) - else - camera = new /obj/machinery/camera(src) - camera.network = list("NUKE") - cameranet.removeCamera(camera) - camera.c_tag = user.name - to_chat(user, "User scanned as [camera.c_tag]. Camera activated.") - -/obj/item/clothing/head/helmet/space/rig/syndi/examine(mob/user) - ..() - if(get_dist(user,src) <= 1) - to_chat(user, "This helmet has a built-in camera. It's [camera ? "" : "in"]active.") - -/obj/item/clothing/suit/space/rig/syndi - icon_state = "rig-syndi" - name = "blood-red hardsuit" - desc = "An advanced suit that protects against injuries during special operations. Property of Gorlex Marauders." - item_state = "syndie_hardsuit" - species_fit = list("Vox") - slowdown = 1 - w_class = 3 - 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_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs) - siemens_coefficient = 0.6 - pressure_resistance = 40 * ONE_ATMOSPHERE - - species_restricted = null - -//Wizard Rig -/obj/item/clothing/head/helmet/space/rig/wizard - name = "gem-encrusted hardsuit helmet" - desc = "A bizarre gem-encrusted helmet that radiates magical energies." - icon_state = "rig0-wiz" - item_state = "wiz_helm" - _color = "wiz" - species_restricted = list("exclude","Vox") - unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles! - armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) - siemens_coefficient = 0.7 - - wizard_garb = 1 - - species_restricted = null - -/obj/item/clothing/suit/space/rig/wizard - icon_state = "rig-wiz" - name = "gem-encrusted hardsuit" - desc = "A bizarre gem-encrusted suit that radiates magical energies." - item_state = "wiz_hardsuit" - slowdown = 1 - w_class = 3 - unacidable = 1 - species_restricted = list("exclude","Vox") - armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) - siemens_coefficient = 0.7 - - wizard_garb = 1 - - species_restricted = null - -//Medical Rig -/obj/item/clothing/head/helmet/space/rig/medical - name = "medical hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low pressure environment. Has minor radiation shielding." - icon_state = "rig0-medical" - item_state = "medical_helm" - _color = "medical" - species_restricted = list("exclude","Vox") - pressure_resistance = 40 * ONE_ATMOSPHERE - -/obj/item/clothing/suit/space/rig/medical - icon_state = "rig-medical" - name = "medical hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." - item_state = "medical_hardsuit" - species_restricted = list("exclude","Vox") - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) - pressure_resistance = 40 * ONE_ATMOSPHERE - - - //Security -/obj/item/clothing/head/helmet/space/rig/security - name = "security hardsuit helmet" - desc = "A special helmet designed for work in a hazardous low pressure environment. Has an additional layer of armor." - icon_state = "rig0-sec" - item_state = "sec_helm" - _color = "sec" - species_restricted = list("exclude","Vox") - armor = list(melee = 60, bullet = 10, laser = 30, energy = 5, bomb = 45, bio = 100, rad = 10) - siemens_coefficient = 0.7 - pressure_resistance = 40 * ONE_ATMOSPHERE - -/obj/item/clothing/suit/space/rig/security - icon_state = "rig-sec" - name = "security hardsuit" - desc = "A special suit that protects against hazardous low pressure environments. Has an additional layer of armor." - item_state = "sec_hardsuit" - species_restricted = list("exclude","Vox") - armor = list(melee = 60, bullet = 10, laser = 30, energy = 5, bomb = 45, bio = 100, rad = 10) - allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/baton) - siemens_coefficient = 0.7 - pressure_resistance = 40 * ONE_ATMOSPHERE - - // stormtroopers - -/obj/item/clothing/head/helmet/space/rig/security/stormtrooper - icon_state = "rig0-storm" - _color = "storm" - name = "stormtrooper helmet" - desc = "Now even more vulnerable to teddy bears!" - no_light = 1 - -/obj/item/clothing/suit/space/rig/security/stormtrooper - icon_state = "rig-storm" - name = "stormtrooper hardsuit" - desc = "Even with the finest vision enhancement tech, you still can't hit shit." - -//Atmospherics Rig (BS12) -/obj/item/clothing/head/helmet/space/rig/atmos - desc = "A special helmet designed for work in hazardous low pressure environments. Has reduced radiation shielding to allow for greater mobility." - name = "atmospherics hardsuit helmet" - icon_state = "rig0-atmos" - item_state = "atmos_helm" - _color = "atmos" - species_restricted = list("exclude","Vox") - flags = FPRINT | PLASMAGUARD - armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) - 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." - icon_state = "rig-atmos" - name = "atmos hardsuit" - item_state = "atmos_hardsuit" - species_restricted = list("exclude","Vox") - flags = FPRINT | PLASMAGUARD - armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - -//Firefighting/Atmos RIG (old /vg/) -/obj/item/clothing/head/helmet/space/rig/atmos/gold - desc = "A special helmet designed for work in hazardous low pressure environments and extreme temperatures. In other words, perfect for atmos." - heat_protection = HEAD - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE*2 - name = "atmos hardsuit helmet" - icon_state = "rig0-atmos_gold" - item_state = "atmos_gold_helm" - _color = "atmos_gold" - species_restricted = list("exclude","Vox") - no_light = 1 - -/obj/item/clothing/suit/space/rig/atmos/gold - desc = "A special suit that protects against hazardous low pressure environments and extreme temperatures. In other words, perfect for atmos." - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*4 - gas_transfer_coefficient = 0.80 - permeability_coefficient = 0.25 - icon_state = "rig-atmos_gold" - name = "atmos hardsuit" - item_state = "atmos_gold_hardsuit" - slowdown = 2 - armor = list(melee = 30, bullet = 5, laser = 40,energy = 5, bomb = 35, bio = 100, rad = 60) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/backpack/satchel_norm,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/device/rcd, /obj/item/weapon/extinguisher, /obj/item/weapon/) - -//ADMINBUS RIGS. SOVIET + NAZI -/obj/item/clothing/head/helmet/space/rig/nazi - name = "nazi hardhelmet" - desc = "This is the face of das vaterland's top elite. Gas or energy are your only escapes." - item_state = "rig0-nazi" - icon_state = "rig0-nazi" - species_restricted = list("exclude","Vox")//GAS THE VOX - armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) - _color = "nazi" - pressure_resistance = 40 * ONE_ATMOSPHERE - -/obj/item/clothing/suit/space/rig/nazi - name = "nazi hardsuit" - desc = "The attire of a true krieger. All shall fall, and only das vaterland will remain." - item_state = "rig-nazi" - icon_state = "rig-nazi" - slowdown = 1 - species_restricted = list("exclude","Vox")//GAS THE VOX - armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) - allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/) - pressure_resistance = 40 * ONE_ATMOSPHERE - -/obj/item/clothing/head/helmet/space/rig/soviet - name = "soviet hardhelmet" - desc = "Crafted with the pride of the proletariat. The vengeful gaze of the visor roots out all fascists and capitalists." - item_state = "rig0-soviet" - icon_state = "rig0-soviet" - species_restricted = list("exclude","Vox")//HET - armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) - _color = "soviet" - pressure_resistance = 40 * ONE_ATMOSPHERE - -/obj/item/clothing/suit/space/rig/soviet - name = "soviet hardsuit" - desc = "Crafted with the pride of the proletariat. The last thing the enemy sees is the bottom of this armor's boot." - item_state = "rig-soviet" - icon_state = "rig-soviet" - slowdown = 1 - species_restricted = list("exclude","Vox")//HET - armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) - allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/) - pressure_resistance = 40 * ONE_ATMOSPHERE - - -//Death squad rig -/obj/item/clothing/head/helmet/space/rig/deathsquad - name = "deathsquad helmet" - desc = "That's not red paint. That's real blood." - icon_state = "rig0-deathsquad" - item_state = "rig0-deathsquad" - armor = list(melee = 65, bullet = 55, laser = 35,energy = 20, bomb = 40, bio = 100, rad = 60) - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.2 - species_restricted = list("exclude","Vox") - _color = "deathsquad" - flags = FPRINT | PLASMAGUARD - -/obj/item/clothing/suit/space/rig/deathsquad - name = "deathsquad suit" - desc = "A heavily armored suit that protects against a lot of things. Used in special operations." - icon_state = "rig-deathsquad" - item_state = "rig-deathsquad" - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/pinpointer,/obj/item/weapon/shield/energy,/obj/item/weapon/plastique,/obj/item/weapon/disk/nuclear) - armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60) - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.5 - species_restricted = list("exclude","Vox") - flags = FPRINT | PLASMAGUARD - - -//Knight armour rigs -/obj/item/clothing/head/helmet/space/rig/knight - name = "Space-Knight helm" - desc = "A well polished helmet belonging to a Space-Knight. Favored by space-jousters for its ability to stay on tight after being launched from a mass driver." - icon_state = "rig0-knight" - item_state = "rig0-knight" - armor = list(melee = 60, bullet = 40, laser = 40,energy = 30, bomb = 50, bio = 100, rad = 60) - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.2 - species_restricted = list("exclude","Vox") - _color = "knight" - flags = FPRINT | PLASMAGUARD - -/obj/item/clothing/suit/space/rig/knight - name = "Space-Knight armour" - desc = "A well polished set of armour belonging to a Space-Knight. Maidens Rescued in Space: 100, Maidens who have slept with me in Space: 0" - icon_state = "rig-knight" - item_state = "rig-knight" - slowdown = 1 - allowed = list(/obj/item/weapon/gun,/obj/item/weapon/melee/baton,/obj/item/weapon/tank,/obj/item/weapon/shield/energy,/obj/item/weapon/claymore) - armor = list(melee = 60, bullet = 40, laser = 40,energy = 30, bomb = 50, bio = 100, rad = 60) - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.5 - species_restricted = list("exclude","Vox") - flags = FPRINT | PLASMAGUARD - -/obj/item/clothing/head/helmet/space/rig/knight/black - name = "Black Knight's helm" - desc = "An ominous black helmet with a gold trim. The small viewports create an intimidating look, while also making it nearly impossible to see anything." - icon_state = "rig0-blackknight" - item_state = "rig0-blackknight" - armor = list(melee = 70, bullet = 65, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60) - _color="blackknight" - -/obj/item/clothing/suit/space/rig/knight/black - name = "Black Knight's armour" - desc = "An ominous black suit of armour with a gold trim. Surprisingly good at preventing accidental loss of limbs." - icon_state = "rig-blackknight" - item_state = "rig-blackknight" - armor = list(melee = 70, bullet = 65, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60) - -/obj/item/clothing/head/helmet/space/rig/knight/solaire - name = "Solar helm" - desc = "A simple helmet. 'Made in Astora' is inscribed on the back." - icon_state = "rig0-solaire" - item_state = "rig0-solaire" - armor = list(melee = 60, bullet = 65, laser = 90,energy = 30, bomb = 60, bio = 100, rad = 100) - _color="solaire" - -/obj/item/clothing/suit/space/rig/knight/solaire - name = "Solar armour" - desc = "A solar powered hardsuit with a fancy insignia on the chest. Perfect for stargazers and adventurers alike." - icon_state = "rig-solaire" - item_state = "rig-solaire" - armor = list(melee = 60, bullet = 65, laser = 90,energy = 30, bomb = 60, bio = 100, rad = 100) - - -/obj/item/clothing/suit/space/rig/t51b - name = "T-51b Power Armor" - desc = "Relic of a bygone era, the T-51b is powered by a TX-28 MicroFusion Pack, which holds enough fuel to power its internal hydraulics for a century!" - icon_state = "rig-t51b" - item_state = "rig-t51b" - armor = list(melee = 35, bullet = 35, laser = 40, energy = 40, bomb = 80, bio = 100, rad = 100) - -/obj/item/clothing/head/helmet/space/rig/t51b - name = "T-51b Power Armor Helmet" - desc = "Relic of a bygone era, the T-51b is powered by a TX-28 MicroFusion Pack, which holds enough fuel to power its internal hydraulics for a century!" - icon_state = "rig0-t51b" - item_state = "rig0-t51b" - armor = list(melee = 35, bullet = 35, laser = 40, energy = 40, bomb = 80, bio = 100, rad = 100) - _color="t51b" +//Regular rig suits +/obj/item/clothing/head/helmet/space/rig + name = "engineering hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." + icon_state = "rig0-engineering" + item_state = "eng_helm" + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) + allowed = list(/obj/item/device/flashlight) + light_power = 1.7 + var/brightness_on = 4 //Luminosity when on. If modified, do NOT run update_brightness() directly + var/on = 0 //Remember to run update_brightness() when modified, otherwise disasters happen + var/no_light = 0 //Disables the helmet light when set to 1. Make sure to run check_light() if this is updated + _color = "engineering" //Determines used sprites: rig[on]-[_color]. Use update_icon() directly to update the sprite. NEEDS TO BE SET CORRECTLY FOR HELMETS + action_button_name = "Toggle Helmet Light" + heat_protection = HEAD + max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE + pressure_resistance = 200 * ONE_ATMOSPHERE + eyeprot = 3 + species_restricted = list("exclude","Vox") + +/obj/item/clothing/head/helmet/space/rig/New() + ..() + //Needed to properly handle helmets with no lights + check_light() + //Useful for helmets with special starting conditions (namely, starts lit) + update_brightness() + update_icon() + +/obj/item/clothing/head/helmet/space/rig/examine(mob/user) + + ..() + if(!no_light) //There is a light attached or integrated + to_chat(user, "The helmet is mounted with an Internal Lighting System, it is [on ? "":"un"]lit.") + +//We check no_light and update everything accordingly +//Used to clear up the action button and shut down the light if broken +//Minimizes snowflake coding and allows dynamically disabling the helmet's light if needed +/obj/item/clothing/head/helmet/space/rig/proc/check_light() + + + if(no_light) //There's no light on the helmet + if(on) //The helmet light is currently on + on = 0 //Force it off + update_brightness() //Update as neccesary + action_button_name = null //Disable the action button (which is only used to toggle the light, in theory) + else //We have a light + action_button_name = initial(action_button_name) //Make sure we restore the action button + +/obj/item/clothing/head/helmet/space/rig/proc/update_brightness() + + + if(on) + set_light(brightness_on) + else + set_light(0) + update_icon() + +/obj/item/clothing/head/helmet/space/rig/update_icon() + + icon_state = "rig[on]-[_color]" //No need for complicated if trees + +/obj/item/clothing/head/helmet/space/rig/attack_self(mob/user) + if(no_light) + return + + on = !on + update_icon() + user.update_inv_head() + + if(on) + set_light(brightness_on) + else + set_light(0) + user.update_inv_head() + +/obj/item/clothing/suit/space/rig + name = "engineering hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." + icon_state = "rig-engineering" + item_state = "eng_hardsuit" + slowdown = 1 + species_restricted = list("exclude","Vox") + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/device/rcd, /obj/item/weapon/wrench/socket) + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE + pressure_resistance = 200 * ONE_ATMOSPHERE + +//Chief Engineer's rig +/obj/item/clothing/head/helmet/space/rig/elite + name = "advanced hardsuit helmet" + desc = "An advanced helmet designed for work in a hazardous, low pressure environment. Shines with a high polish." + icon_state = "rig0-white" + item_state = "ce_helm" + _color = "white" + species_restricted = list("exclude","Vox") + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + flags = FPRINT | PLASMAGUARD + +/obj/item/clothing/suit/space/rig/elite + icon_state = "rig-white" + name = "advanced hardsuit" + species_restricted = list("exclude","Vox") + desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." + item_state = "ce_hardsuit" + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + flags = FPRINT | PLASMAGUARD + + +//Mining rig +/obj/item/clothing/head/helmet/space/rig/mining + name = "mining hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low pressure environment. Has reinforced plating." + icon_state = "rig0-mining" + item_state = "mining_helm" + _color = "mining" + species_restricted = list("exclude","Vox") + pressure_resistance = 40 * ONE_ATMOSPHERE + +/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" + species_restricted = list("exclude","Vox") + pressure_resistance = 40 * ONE_ATMOSPHERE + + +//Syndicate rig +/obj/item/clothing/head/helmet/space/rig/syndi + name = "blood-red hardsuit helmet" + desc = "An advanced helmet designed for work in special operations. Property of Gorlex Marauders." + icon_state = "rig0-syndi" + item_state = "syndie_helm" + species_fit = list("Vox") + _color = "syndi" + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60) + action_button_name = "Toggle Helmet Camera" //This helmet does not have a light, but we'll do as if + siemens_coefficient = 0.6 + var/obj/machinery/camera/camera + pressure_resistance = 40 * ONE_ATMOSPHERE + + species_restricted = null + +/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) + if(camera) + ..(user) + else + camera = new /obj/machinery/camera(src) + camera.network = list("NUKE") + cameranet.removeCamera(camera) + camera.c_tag = user.name + to_chat(user, "User scanned as [camera.c_tag]. Camera activated.") + +/obj/item/clothing/head/helmet/space/rig/syndi/examine(mob/user) + ..() + if(get_dist(user,src) <= 1) + to_chat(user, "This helmet has a built-in camera. It's [camera ? "" : "in"]active.") + +/obj/item/clothing/suit/space/rig/syndi + icon_state = "rig-syndi" + name = "blood-red hardsuit" + desc = "An advanced suit that protects against injuries during special operations. Property of Gorlex Marauders." + item_state = "syndie_hardsuit" + species_fit = list("Vox") + slowdown = 1 + w_class = 3 + 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_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs) + siemens_coefficient = 0.6 + pressure_resistance = 40 * ONE_ATMOSPHERE + + species_restricted = null + +//Wizard Rig +/obj/item/clothing/head/helmet/space/rig/wizard + name = "gem-encrusted hardsuit helmet" + desc = "A bizarre gem-encrusted helmet that radiates magical energies." + icon_state = "rig0-wiz" + item_state = "wiz_helm" + _color = "wiz" + species_restricted = list("exclude","Vox") + unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles! + armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) + siemens_coefficient = 0.7 + + wizard_garb = 1 + + species_restricted = null + +/obj/item/clothing/suit/space/rig/wizard + icon_state = "rig-wiz" + name = "gem-encrusted hardsuit" + desc = "A bizarre gem-encrusted suit that radiates magical energies." + item_state = "wiz_hardsuit" + slowdown = 1 + w_class = 3 + unacidable = 1 + species_restricted = list("exclude","Vox") + armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) + siemens_coefficient = 0.7 + + wizard_garb = 1 + + species_restricted = null + +//Medical Rig +/obj/item/clothing/head/helmet/space/rig/medical + name = "medical hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low pressure environment. Has minor radiation shielding." + icon_state = "rig0-medical" + item_state = "medical_helm" + _color = "medical" + species_restricted = list("exclude","Vox") + pressure_resistance = 40 * ONE_ATMOSPHERE + +/obj/item/clothing/suit/space/rig/medical + icon_state = "rig-medical" + name = "medical hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." + item_state = "medical_hardsuit" + species_restricted = list("exclude","Vox") + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) + pressure_resistance = 40 * ONE_ATMOSPHERE + + + //Security +/obj/item/clothing/head/helmet/space/rig/security + name = "security hardsuit helmet" + desc = "A special helmet designed for work in a hazardous low pressure environment. Has an additional layer of armor." + icon_state = "rig0-sec" + item_state = "sec_helm" + _color = "sec" + species_restricted = list("exclude","Vox") + armor = list(melee = 60, bullet = 10, laser = 30, energy = 5, bomb = 45, bio = 100, rad = 10) + siemens_coefficient = 0.7 + pressure_resistance = 40 * ONE_ATMOSPHERE + +/obj/item/clothing/suit/space/rig/security + icon_state = "rig-sec" + name = "security hardsuit" + desc = "A special suit that protects against hazardous low pressure environments. Has an additional layer of armor." + item_state = "sec_hardsuit" + species_restricted = list("exclude","Vox") + armor = list(melee = 60, bullet = 10, laser = 30, energy = 5, bomb = 45, bio = 100, rad = 10) + allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/baton) + siemens_coefficient = 0.7 + pressure_resistance = 40 * ONE_ATMOSPHERE + + // stormtroopers + +/obj/item/clothing/head/helmet/space/rig/security/stormtrooper + icon_state = "rig0-storm" + _color = "storm" + name = "stormtrooper helmet" + desc = "Now even more vulnerable to teddy bears!" + no_light = 1 + +/obj/item/clothing/suit/space/rig/security/stormtrooper + icon_state = "rig-storm" + name = "stormtrooper hardsuit" + desc = "Even with the finest vision enhancement tech, you still can't hit shit." + +//Atmospherics Rig (BS12) +/obj/item/clothing/head/helmet/space/rig/atmos + desc = "A special helmet designed for work in hazardous low pressure environments. Has reduced radiation shielding to allow for greater mobility." + name = "atmospherics hardsuit helmet" + icon_state = "rig0-atmos" + item_state = "atmos_helm" + _color = "atmos" + species_restricted = list("exclude","Vox") + flags = FPRINT | PLASMAGUARD + armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) + 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." + icon_state = "rig-atmos" + name = "atmos hardsuit" + item_state = "atmos_hardsuit" + species_restricted = list("exclude","Vox") + flags = FPRINT | PLASMAGUARD + armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + +//Firefighting/Atmos RIG (old /vg/) +/obj/item/clothing/head/helmet/space/rig/atmos/gold + desc = "A special helmet designed for work in hazardous low pressure environments and extreme temperatures. In other words, perfect for atmos." + heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE*2 + name = "atmos hardsuit helmet" + icon_state = "rig0-atmos_gold" + item_state = "atmos_gold_helm" + _color = "atmos_gold" + species_restricted = list("exclude","Vox") + no_light = 1 + +/obj/item/clothing/suit/space/rig/atmos/gold + desc = "A special suit that protects against hazardous low pressure environments and extreme temperatures. In other words, perfect for atmos." + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*4 + gas_transfer_coefficient = 0.80 + permeability_coefficient = 0.25 + icon_state = "rig-atmos_gold" + name = "atmos hardsuit" + item_state = "atmos_gold_hardsuit" + slowdown = 2 + armor = list(melee = 30, bullet = 5, laser = 40,energy = 5, bomb = 35, bio = 100, rad = 60) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/backpack/satchel_norm,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/device/rcd, /obj/item/weapon/extinguisher, /obj/item/weapon/) + +//ADMINBUS RIGS. SOVIET + NAZI +/obj/item/clothing/head/helmet/space/rig/nazi + name = "nazi hardhelmet" + desc = "This is the face of das vaterland's top elite. Gas or energy are your only escapes." + item_state = "rig0-nazi" + icon_state = "rig0-nazi" + species_restricted = list("exclude","Vox")//GAS THE VOX + armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) + _color = "nazi" + pressure_resistance = 40 * ONE_ATMOSPHERE + +/obj/item/clothing/suit/space/rig/nazi + name = "nazi hardsuit" + desc = "The attire of a true krieger. All shall fall, and only das vaterland will remain." + item_state = "rig-nazi" + icon_state = "rig-nazi" + slowdown = 1 + species_restricted = list("exclude","Vox")//GAS THE VOX + armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) + allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/) + pressure_resistance = 40 * ONE_ATMOSPHERE + +/obj/item/clothing/head/helmet/space/rig/soviet + name = "soviet hardhelmet" + desc = "Crafted with the pride of the proletariat. The vengeful gaze of the visor roots out all fascists and capitalists." + item_state = "rig0-soviet" + icon_state = "rig0-soviet" + species_restricted = list("exclude","Vox")//HET + armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) + _color = "soviet" + pressure_resistance = 40 * ONE_ATMOSPHERE + +/obj/item/clothing/suit/space/rig/soviet + name = "soviet hardsuit" + desc = "Crafted with the pride of the proletariat. The last thing the enemy sees is the bottom of this armor's boot." + item_state = "rig-soviet" + icon_state = "rig-soviet" + slowdown = 1 + species_restricted = list("exclude","Vox")//HET + armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) + allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/) + pressure_resistance = 40 * ONE_ATMOSPHERE + + +//Death squad rig +/obj/item/clothing/head/helmet/space/rig/deathsquad + name = "deathsquad helmet" + desc = "That's not red paint. That's real blood." + icon_state = "rig0-deathsquad" + item_state = "rig0-deathsquad" + armor = list(melee = 65, bullet = 55, laser = 35,energy = 20, bomb = 40, bio = 100, rad = 60) + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.2 + species_restricted = list("exclude","Vox") + _color = "deathsquad" + flags = FPRINT | PLASMAGUARD + +/obj/item/clothing/suit/space/rig/deathsquad + name = "deathsquad suit" + desc = "A heavily armored suit that protects against a lot of things. Used in special operations." + icon_state = "rig-deathsquad" + item_state = "rig-deathsquad" + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/pinpointer,/obj/item/weapon/shield/energy,/obj/item/weapon/plastique,/obj/item/weapon/disk/nuclear) + armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60) + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.5 + species_restricted = list("exclude","Vox") + flags = FPRINT | PLASMAGUARD + + +//Knight armour rigs +/obj/item/clothing/head/helmet/space/rig/knight + name = "Space-Knight helm" + desc = "A well polished helmet belonging to a Space-Knight. Favored by space-jousters for its ability to stay on tight after being launched from a mass driver." + icon_state = "rig0-knight" + item_state = "rig0-knight" + armor = list(melee = 60, bullet = 40, laser = 40,energy = 30, bomb = 50, bio = 100, rad = 60) + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.2 + species_restricted = list("exclude","Vox") + _color = "knight" + flags = FPRINT | PLASMAGUARD + +/obj/item/clothing/suit/space/rig/knight + name = "Space-Knight armour" + desc = "A well polished set of armour belonging to a Space-Knight. Maidens Rescued in Space: 100, Maidens who have slept with me in Space: 0" + icon_state = "rig-knight" + item_state = "rig-knight" + slowdown = 1 + allowed = list(/obj/item/weapon/gun,/obj/item/weapon/melee/baton,/obj/item/weapon/tank,/obj/item/weapon/shield/energy,/obj/item/weapon/claymore) + armor = list(melee = 60, bullet = 40, laser = 40,energy = 30, bomb = 50, bio = 100, rad = 60) + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.5 + species_restricted = list("exclude","Vox") + flags = FPRINT | PLASMAGUARD + +/obj/item/clothing/head/helmet/space/rig/knight/black + name = "Black Knight's helm" + desc = "An ominous black helmet with a gold trim. The small viewports create an intimidating look, while also making it nearly impossible to see anything." + icon_state = "rig0-blackknight" + item_state = "rig0-blackknight" + armor = list(melee = 70, bullet = 65, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60) + _color="blackknight" + +/obj/item/clothing/suit/space/rig/knight/black + name = "Black Knight's armour" + desc = "An ominous black suit of armour with a gold trim. Surprisingly good at preventing accidental loss of limbs." + icon_state = "rig-blackknight" + item_state = "rig-blackknight" + armor = list(melee = 70, bullet = 65, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60) + +/obj/item/clothing/head/helmet/space/rig/knight/solaire + name = "Solar helm" + desc = "A simple helmet. 'Made in Astora' is inscribed on the back." + icon_state = "rig0-solaire" + item_state = "rig0-solaire" + armor = list(melee = 60, bullet = 65, laser = 90,energy = 30, bomb = 60, bio = 100, rad = 100) + _color="solaire" + +/obj/item/clothing/suit/space/rig/knight/solaire + name = "Solar armour" + desc = "A solar powered hardsuit with a fancy insignia on the chest. Perfect for stargazers and adventurers alike." + icon_state = "rig-solaire" + item_state = "rig-solaire" + armor = list(melee = 60, bullet = 65, laser = 90,energy = 30, bomb = 60, bio = 100, rad = 100) + + +/obj/item/clothing/suit/space/rig/t51b + name = "T-51b Power Armor" + desc = "Relic of a bygone era, the T-51b is powered by a TX-28 MicroFusion Pack, which holds enough fuel to power its internal hydraulics for a century!" + icon_state = "rig-t51b" + item_state = "rig-t51b" + armor = list(melee = 35, bullet = 35, laser = 40, energy = 40, bomb = 80, bio = 100, rad = 100) + +/obj/item/clothing/head/helmet/space/rig/t51b + name = "T-51b Power Armor Helmet" + desc = "Relic of a bygone era, the T-51b is powered by a TX-28 MicroFusion Pack, which holds enough fuel to power its internal hydraulics for a century!" + icon_state = "rig0-t51b" + item_state = "rig0-t51b" + armor = list(melee = 35, bullet = 35, laser = 40, energy = 40, bomb = 80, bio = 100, rad = 100) + _color="t51b" diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index 8983a85db13..40494c58486 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -1,154 +1,154 @@ -//Regular syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate - name = "red space helmet" - icon_state = "syndicate" - item_state = "syndicate" - species_restricted = list("exclude","Vox") - desc = "Has a tag on it: Totally not property of a hostile corporation, honest!" - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0.8 - flags_inv = HIDEEARS | HIDEHAIR - -/obj/item/clothing/suit/space/syndicate - name = "red space suit" - icon_state = "syndicate" - item_state = "space_suit_syndicate" - desc = "Has a tag on it: Totally not property of a hostile corporation, honest!" - w_class = 3 - species_restricted = list("exclude","Vox") - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/jetpack,/obj/item/weapon/tank/jetpack/void,/obj/item/weapon/tank/jetpack/oxygen,/obj/item/weapon/tank/jetpack/nitrogen,/obj/item/weapon/tank/jetpack/carbondioxide,/obj/item/weapon/tank/oxygen,/obj/item/weapon/tank/air) - slowdown = 1 - armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0.8 - - -//Green syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/green - name = "Green Space Helmet" - icon_state = "syndicate-helm-green" - item_state = "syndicate-helm-green" - -/obj/item/clothing/suit/space/syndicate/green - name = "Green Space Suit" - icon_state = "syndicate-green" - item_state = "syndicate-green" - - -//Dark green syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/green/dark - name = "Dark Green Space Helmet" - icon_state = "syndicate-helm-green-dark" - item_state = "syndicate-helm-green-dark" - -/obj/item/clothing/suit/space/syndicate/green/dark - name = "Dark Green Space Suit" - icon_state = "syndicate-green-dark" - item_state = "syndicate-green-dark" - - -//Orange syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/orange - name = "Orange Space Helmet" - icon_state = "syndicate-helm-orange" - item_state = "syndicate-helm-orange" - -/obj/item/clothing/suit/space/syndicate/orange - name = "Orange Space Suit" - icon_state = "syndicate-orange" - item_state = "syndicate-orange" - - -//Blue syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/blue - name = "Blue Space Helmet" - icon_state = "syndicate-helm-blue" - item_state = "syndicate-helm-blue" - -/obj/item/clothing/suit/space/syndicate/blue - name = "Blue Space Suit" - icon_state = "syndicate-blue" - item_state = "syndicate-blue" - - -//Black syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black - name = "Black Space Helmet" - icon_state = "syndicate-helm-black" - item_state = "syndicate-helm-black" - -/obj/item/clothing/suit/space/syndicate/black - name = "Black Space Suit" - icon_state = "syndicate-black" - item_state = "syndicate-black" - - -//Black-green syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black/green - name = "Black Space Helmet" - icon_state = "syndicate-helm-black-green" - item_state = "syndicate-helm-black-green" - -/obj/item/clothing/suit/space/syndicate/black/green - name = "Black and Green Space Suit" - icon_state = "syndicate-black-green" - item_state = "syndicate-black-green" - - -//Black-blue syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black/blue - name = "Black Space Helmet" - icon_state = "syndicate-helm-black-blue" - item_state = "syndicate-helm-black-blue" - -/obj/item/clothing/suit/space/syndicate/black/blue - name = "Black and Blue Space Suit" - icon_state = "syndicate-black-blue" - item_state = "syndicate-black-blue" - - -//Black medical syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black/med - name = "Black Space Helmet" - icon_state = "syndicate-helm-black-med" - item_state = "syndicate-helm-black" - -/obj/item/clothing/suit/space/syndicate/black/med - name = "Green Space Suit" - icon_state = "syndicate-black-med" - item_state = "syndicate-black" - - -//Black-orange syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black/orange - name = "Black Space Helmet" - icon_state = "syndicate-helm-black-orange" - item_state = "syndicate-helm-black" - -/obj/item/clothing/suit/space/syndicate/black/orange - name = "Black and Orange Space Suit" - icon_state = "syndicate-black-orange" - item_state = "syndicate-black" - - -//Black-red syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black/red - name = "Black Space Helmet" - icon_state = "syndicate-helm-black-red" - item_state = "syndicate-helm-black-red" - -/obj/item/clothing/suit/space/syndicate/black/red - name = "Black and Red Space Suit" - icon_state = "syndicate-black-red" - item_state = "syndicate-black-red" - - -//Black with yellow/red engineering syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/black/engie - name = "Black Space Helmet" - icon_state = "syndicate-helm-black-engie" - item_state = "syndicate-helm-black" - -/obj/item/clothing/suit/space/syndicate/black/engie - name = "Black Engineering Space Suit" - icon_state = "syndicate-black-engie" +//Regular syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate + name = "red space helmet" + icon_state = "syndicate" + item_state = "syndicate" + species_restricted = list("exclude","Vox") + desc = "Has a tag on it: Totally not property of a hostile corporation, honest!" + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0.8 + flags_inv = HIDEEARS | HIDEHAIR + +/obj/item/clothing/suit/space/syndicate + name = "red space suit" + icon_state = "syndicate" + item_state = "space_suit_syndicate" + desc = "Has a tag on it: Totally not property of a hostile corporation, honest!" + w_class = 3 + species_restricted = list("exclude","Vox") + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/jetpack,/obj/item/weapon/tank/jetpack/void,/obj/item/weapon/tank/jetpack/oxygen,/obj/item/weapon/tank/jetpack/nitrogen,/obj/item/weapon/tank/jetpack/carbondioxide,/obj/item/weapon/tank/oxygen,/obj/item/weapon/tank/air) + slowdown = 1 + armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0.8 + + +//Green syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/green + name = "Green Space Helmet" + icon_state = "syndicate-helm-green" + item_state = "syndicate-helm-green" + +/obj/item/clothing/suit/space/syndicate/green + name = "Green Space Suit" + icon_state = "syndicate-green" + item_state = "syndicate-green" + + +//Dark green syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/green/dark + name = "Dark Green Space Helmet" + icon_state = "syndicate-helm-green-dark" + item_state = "syndicate-helm-green-dark" + +/obj/item/clothing/suit/space/syndicate/green/dark + name = "Dark Green Space Suit" + icon_state = "syndicate-green-dark" + item_state = "syndicate-green-dark" + + +//Orange syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/orange + name = "Orange Space Helmet" + icon_state = "syndicate-helm-orange" + item_state = "syndicate-helm-orange" + +/obj/item/clothing/suit/space/syndicate/orange + name = "Orange Space Suit" + icon_state = "syndicate-orange" + item_state = "syndicate-orange" + + +//Blue syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/blue + name = "Blue Space Helmet" + icon_state = "syndicate-helm-blue" + item_state = "syndicate-helm-blue" + +/obj/item/clothing/suit/space/syndicate/blue + name = "Blue Space Suit" + icon_state = "syndicate-blue" + item_state = "syndicate-blue" + + +//Black syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black + name = "Black Space Helmet" + icon_state = "syndicate-helm-black" + item_state = "syndicate-helm-black" + +/obj/item/clothing/suit/space/syndicate/black + name = "Black Space Suit" + icon_state = "syndicate-black" + item_state = "syndicate-black" + + +//Black-green syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black/green + name = "Black Space Helmet" + icon_state = "syndicate-helm-black-green" + item_state = "syndicate-helm-black-green" + +/obj/item/clothing/suit/space/syndicate/black/green + name = "Black and Green Space Suit" + icon_state = "syndicate-black-green" + item_state = "syndicate-black-green" + + +//Black-blue syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black/blue + name = "Black Space Helmet" + icon_state = "syndicate-helm-black-blue" + item_state = "syndicate-helm-black-blue" + +/obj/item/clothing/suit/space/syndicate/black/blue + name = "Black and Blue Space Suit" + icon_state = "syndicate-black-blue" + item_state = "syndicate-black-blue" + + +//Black medical syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black/med + name = "Black Space Helmet" + icon_state = "syndicate-helm-black-med" + item_state = "syndicate-helm-black" + +/obj/item/clothing/suit/space/syndicate/black/med + name = "Green Space Suit" + icon_state = "syndicate-black-med" + item_state = "syndicate-black" + + +//Black-orange syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black/orange + name = "Black Space Helmet" + icon_state = "syndicate-helm-black-orange" + item_state = "syndicate-helm-black" + +/obj/item/clothing/suit/space/syndicate/black/orange + name = "Black and Orange Space Suit" + icon_state = "syndicate-black-orange" + item_state = "syndicate-black" + + +//Black-red syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black/red + name = "Black Space Helmet" + icon_state = "syndicate-helm-black-red" + item_state = "syndicate-helm-black-red" + +/obj/item/clothing/suit/space/syndicate/black/red + name = "Black and Red Space Suit" + icon_state = "syndicate-black-red" + item_state = "syndicate-black-red" + + +//Black with yellow/red engineering syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/black/engie + name = "Black Space Helmet" + icon_state = "syndicate-helm-black-engie" + item_state = "syndicate-helm-black" + +/obj/item/clothing/suit/space/syndicate/black/engie + name = "Black Engineering Space Suit" + icon_state = "syndicate-black-engie" item_state = "syndicate-black" \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/void.dm b/code/modules/clothing/spacesuits/void.dm index 7176f63b32f..e9e9b354104 100644 --- a/code/modules/clothing/spacesuits/void.dm +++ b/code/modules/clothing/spacesuits/void.dm @@ -1,16 +1,16 @@ - -//NASA Voidsuit -/obj/item/clothing/head/helmet/space/nasavoid - name = "NASA Void Helmet" - desc = "A high tech, NASA Centcom branch designed, dark red space suit helmet. Used for AI satellite maintenance." - species_restricted = list("exclude","Vox") - icon_state = "void" - item_state = "void" - -/obj/item/clothing/suit/space/nasavoid - name = "NASA Voidsuit" - icon_state = "void" - item_state = "void" - species_restricted = list("exclude","Vox") - desc = "A high tech, NASA Centcom branch designed, dark red Space suit. Used for AI satellite maintenance." - slowdown = 1 + +//NASA Voidsuit +/obj/item/clothing/head/helmet/space/nasavoid + name = "NASA Void Helmet" + desc = "A high tech, NASA Centcom branch designed, dark red space suit helmet. Used for AI satellite maintenance." + species_restricted = list("exclude","Vox") + icon_state = "void" + item_state = "void" + +/obj/item/clothing/suit/space/nasavoid + name = "NASA Voidsuit" + icon_state = "void" + item_state = "void" + species_restricted = list("exclude","Vox") + desc = "A high tech, NASA Centcom branch designed, dark red Space suit. Used for AI satellite maintenance." + slowdown = 1 diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index 2dac0249604..69acf95e157 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -1,220 +1,220 @@ -/* - * Job related - */ - -//Paramedic -/obj/item/clothing/suit/storage/paramedic - name = "paramedic vest" - desc = "A hazard vest used in the recovery of bodies." - icon_state = "paramedic-vest" - item_state = "paramedic-vest" - allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/device/radio,/obj/item/device/gps) - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 10) - species_fit = list("Vox") - -//Botonist -/obj/item/clothing/suit/apron - name = "apron" - desc = "A basic blue apron." - icon_state = "apron" - item_state = "apron" - blood_overlay_type = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - allowed = list (/obj/item/weapon/reagent_containers/spray/plantbgone,/obj/item/device/analyzer/plant_analyzer,/obj/item/seeds,/obj/item/weapon/reagent_containers/glass/fertilizer,/obj/item/weapon/wirecutters/clippers,/obj/item/weapon/minihoe) - species_fit = list("Vox") - -//Captain -/obj/item/clothing/suit/captunic - name = "captain's parade tunic" - desc = "Worn by a Captain to show their class." - icon_state = "captunic" - item_state = "bio_suit" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDEJUMPSUIT - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/capjacket - name = "captain's uniform jacket" - desc = "A less formal jacket for everyday captain use." - icon_state = "capjacket" - item_state = "bio_suit" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - species_fit = list("Vox") - max_combined_w_class = 6 - storage_slots = 3 - -//Chaplain -/obj/item/clothing/suit/chaplain_hoodie - name = "chaplain hoodie" - desc = "This suit says to you 'hush'!" - icon_state = "chaplain_hoodie" - item_state = "chaplain_hoodie" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - species_fit = list("Vox") - -//Chaplain -/obj/item/clothing/suit/nun - name = "nun robe" - desc = "Maximum piety in this star system." - icon_state = "nun" - item_state = "nun" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS - flags_inv = HIDESHOES|HIDEJUMPSUIT - species_fit = list("Vox") - -//Chef -/obj/item/clothing/suit/chef - name = "Chef's apron" - desc = "An apron used by a high class chef." - icon_state = "chef" - item_state = "chef" - gas_transfer_coefficient = 0.90 - permeability_coefficient = 0.50 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - allowed = list (/obj/item/weapon/kitchen/utensil/knife/large,/obj/item/weapon/kitchen/utensil/knife/large/butch) - species_fit = list("Vox") - -//Chef -/obj/item/clothing/suit/chef/classic - name = "A classic chef's apron." - desc = "A basic, dull, white chef's apron." - icon_state = "apronchef" - item_state = "apronchef" - blood_overlay_type = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - species_fit = list("Vox") - -//Detective -/obj/item/clothing/suit/storage/det_suit - name = "coat" - desc = "An 18th-century multi-purpose trenchcoat. Someone who wears this means serious business." - icon_state = "detective" - item_state = "det_suit" - blood_overlay_type = "coat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) - armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) - species_fit = list("Vox") - -//Forensics -/obj/item/clothing/suit/storage/forensics - name = "jacket" - desc = "A forensics technician jacket." - item_state = "det_suit" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) - armor = list(melee = 10, bullet = 10, laser = 15, energy = 10, bomb = 0, bio = 0, rad = 0) - -/obj/item/clothing/suit/storage/forensics/red - name = "red jacket" - desc = "A red forensics technician jacket." - icon_state = "forensics_red" - -/obj/item/clothing/suit/storage/forensics/blue - name = "blue jacket" - desc = "A blue forensics technician jacket." - icon_state = "forensics_blue" - -//Engineering -/obj/item/clothing/suit/storage/hazardvest - name = "hazard vest" - desc = "A high-visibility vest used in work zones." - icon_state = "hazard" - item_state = "hazard" - blood_overlay_type = "armor" - allowed = list (/obj/item/device/analyzer, /obj/item/device/flashlight, /obj/item/device/multitool, /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/tank/emergency_nitrogen, /obj/item/device/device_analyser) - species_fit = list("Vox") - -//Lawyer -/obj/item/clothing/suit/storage/lawyer/bluejacket - name = "Blue Suit Jacket" - desc = "A snappy dress jacket." - icon_state = "suitjacket_blue_open" - item_state = "suitjacket_blue_open" - blood_overlay_type = "coat" - body_parts_covered = UPPER_TORSO|ARMS - -/obj/item/clothing/suit/storage/lawyer/purpjacket - name = "Purple Suit Jacket" - desc = "A snappy dress jacket." - icon_state = "suitjacket_purp" - item_state = "suitjacket_purp" - blood_overlay_type = "coat" - body_parts_covered = UPPER_TORSO|ARMS - -//Internal Affairs -/obj/item/clothing/suit/storage/internalaffairs - name = "Internal Affairs Jacket" - desc = "A smooth black jacket." - icon_state = "ia_jacket_open" - item_state = "ia_jacket" - blood_overlay_type = "coat" - body_parts_covered = UPPER_TORSO|ARMS - - verb/toggle() - set name = "Toggle Coat Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.isUnconscious() || usr.restrained()) - return 0 - - switch(icon_state) - if("ia_jacket_open") - src.icon_state = "ia_jacket" - to_chat(usr, "You button up the jacket.") - if("ia_jacket") - src.icon_state = "ia_jacket_open" - to_chat(usr, "You unbutton the jacket.") - else - to_chat(usr, "You attempt to button-up the velcro on your [src], before promptly realising how retarded you are.") - return - usr.update_inv_wear_suit() //so our overlays update - -//Medical -/obj/item/clothing/suit/storage/fr_jacket - name = "first responder jacket" - desc = "A high-visibility jacket worn by medical first responders." - icon_state = "fr_jacket_open" - item_state = "fr_jacket" - blood_overlay_type = "armor" - allowed = list(/obj/item/stack/medical, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/syringe, \ - /obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) - - verb/toggle() - set name = "Toggle Jacket Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.isUnconscious() || usr.restrained()) - return 0 - - switch(icon_state) - if("fr_jacket_open") - src.icon_state = "fr_jacket" - to_chat(usr, "You button up the jacket.") - if("fr_jacket") - src.icon_state = "fr_jacket_open" - to_chat(usr, "You unbutton the jacket.") - usr.update_inv_wear_suit() //so our overlays update - -//Mime -/obj/item/clothing/suit/suspenders - name = "suspenders" - desc = "They suspend the illusion of the mime's play." - icon = 'icons/obj/clothing/belts.dmi' - icon_state = "suspenders" - blood_overlay_type = "armor" //it's the less thing that I can put here - -//Head of Personnell -/obj/item/clothing/suit/storage/Hop_Coat - name = "Head of Personnel's dress jacket" - desc = "A slightly armoured greatcoat. It looks like it's mostly ceremonial ." - icon_state = "HoP_Coat" - item_state = "HoP_Coat" - blood_overlay_type = "coat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) - armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) +/* + * Job related + */ + +//Paramedic +/obj/item/clothing/suit/storage/paramedic + name = "paramedic vest" + desc = "A hazard vest used in the recovery of bodies." + icon_state = "paramedic-vest" + item_state = "paramedic-vest" + allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/device/radio,/obj/item/device/gps) + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 10) + species_fit = list("Vox") + +//Botonist +/obj/item/clothing/suit/apron + name = "apron" + desc = "A basic blue apron." + icon_state = "apron" + item_state = "apron" + blood_overlay_type = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + allowed = list (/obj/item/weapon/reagent_containers/spray/plantbgone,/obj/item/device/analyzer/plant_analyzer,/obj/item/seeds,/obj/item/weapon/reagent_containers/glass/fertilizer,/obj/item/weapon/wirecutters/clippers,/obj/item/weapon/minihoe) + species_fit = list("Vox") + +//Captain +/obj/item/clothing/suit/captunic + name = "captain's parade tunic" + desc = "Worn by a Captain to show their class." + icon_state = "captunic" + item_state = "bio_suit" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDEJUMPSUIT + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/capjacket + name = "captain's uniform jacket" + desc = "A less formal jacket for everyday captain use." + icon_state = "capjacket" + item_state = "bio_suit" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + species_fit = list("Vox") + max_combined_w_class = 6 + storage_slots = 3 + +//Chaplain +/obj/item/clothing/suit/chaplain_hoodie + name = "chaplain hoodie" + desc = "This suit says to you 'hush'!" + icon_state = "chaplain_hoodie" + item_state = "chaplain_hoodie" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + species_fit = list("Vox") + +//Chaplain +/obj/item/clothing/suit/nun + name = "nun robe" + desc = "Maximum piety in this star system." + icon_state = "nun" + item_state = "nun" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS + flags_inv = HIDESHOES|HIDEJUMPSUIT + species_fit = list("Vox") + +//Chef +/obj/item/clothing/suit/chef + name = "Chef's apron" + desc = "An apron used by a high class chef." + icon_state = "chef" + item_state = "chef" + gas_transfer_coefficient = 0.90 + permeability_coefficient = 0.50 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + allowed = list (/obj/item/weapon/kitchen/utensil/knife/large,/obj/item/weapon/kitchen/utensil/knife/large/butch) + species_fit = list("Vox") + +//Chef +/obj/item/clothing/suit/chef/classic + name = "A classic chef's apron." + desc = "A basic, dull, white chef's apron." + icon_state = "apronchef" + item_state = "apronchef" + blood_overlay_type = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + species_fit = list("Vox") + +//Detective +/obj/item/clothing/suit/storage/det_suit + name = "coat" + desc = "An 18th-century multi-purpose trenchcoat. Someone who wears this means serious business." + icon_state = "detective" + item_state = "det_suit" + blood_overlay_type = "coat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) + armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) + species_fit = list("Vox") + +//Forensics +/obj/item/clothing/suit/storage/forensics + name = "jacket" + desc = "A forensics technician jacket." + item_state = "det_suit" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) + armor = list(melee = 10, bullet = 10, laser = 15, energy = 10, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/suit/storage/forensics/red + name = "red jacket" + desc = "A red forensics technician jacket." + icon_state = "forensics_red" + +/obj/item/clothing/suit/storage/forensics/blue + name = "blue jacket" + desc = "A blue forensics technician jacket." + icon_state = "forensics_blue" + +//Engineering +/obj/item/clothing/suit/storage/hazardvest + name = "hazard vest" + desc = "A high-visibility vest used in work zones." + icon_state = "hazard" + item_state = "hazard" + blood_overlay_type = "armor" + allowed = list (/obj/item/device/analyzer, /obj/item/device/flashlight, /obj/item/device/multitool, /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/tank/emergency_nitrogen, /obj/item/device/device_analyser) + species_fit = list("Vox") + +//Lawyer +/obj/item/clothing/suit/storage/lawyer/bluejacket + name = "Blue Suit Jacket" + desc = "A snappy dress jacket." + icon_state = "suitjacket_blue_open" + item_state = "suitjacket_blue_open" + blood_overlay_type = "coat" + body_parts_covered = UPPER_TORSO|ARMS + +/obj/item/clothing/suit/storage/lawyer/purpjacket + name = "Purple Suit Jacket" + desc = "A snappy dress jacket." + icon_state = "suitjacket_purp" + item_state = "suitjacket_purp" + blood_overlay_type = "coat" + body_parts_covered = UPPER_TORSO|ARMS + +//Internal Affairs +/obj/item/clothing/suit/storage/internalaffairs + name = "Internal Affairs Jacket" + desc = "A smooth black jacket." + icon_state = "ia_jacket_open" + item_state = "ia_jacket" + blood_overlay_type = "coat" + body_parts_covered = UPPER_TORSO|ARMS + + verb/toggle() + set name = "Toggle Coat Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.isUnconscious() || usr.restrained()) + return 0 + + switch(icon_state) + if("ia_jacket_open") + src.icon_state = "ia_jacket" + to_chat(usr, "You button up the jacket.") + if("ia_jacket") + src.icon_state = "ia_jacket_open" + to_chat(usr, "You unbutton the jacket.") + else + to_chat(usr, "You attempt to button-up the velcro on your [src], before promptly realising how retarded you are.") + return + usr.update_inv_wear_suit() //so our overlays update + +//Medical +/obj/item/clothing/suit/storage/fr_jacket + name = "first responder jacket" + desc = "A high-visibility jacket worn by medical first responders." + icon_state = "fr_jacket_open" + item_state = "fr_jacket" + blood_overlay_type = "armor" + allowed = list(/obj/item/stack/medical, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/syringe, \ + /obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen) + + verb/toggle() + set name = "Toggle Jacket Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.isUnconscious() || usr.restrained()) + return 0 + + switch(icon_state) + if("fr_jacket_open") + src.icon_state = "fr_jacket" + to_chat(usr, "You button up the jacket.") + if("fr_jacket") + src.icon_state = "fr_jacket_open" + to_chat(usr, "You unbutton the jacket.") + usr.update_inv_wear_suit() //so our overlays update + +//Mime +/obj/item/clothing/suit/suspenders + name = "suspenders" + desc = "They suspend the illusion of the mime's play." + icon = 'icons/obj/clothing/belts.dmi' + icon_state = "suspenders" + blood_overlay_type = "armor" //it's the less thing that I can put here + +//Head of Personnell +/obj/item/clothing/suit/storage/Hop_Coat + name = "Head of Personnel's dress jacket" + desc = "A slightly armoured greatcoat. It looks like it's mostly ceremonial ." + icon_state = "HoP_Coat" + item_state = "HoP_Coat" + blood_overlay_type = "coat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) + armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index b682e2d2821..74227ead08a 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -1,86 +1,86 @@ -/obj/item/clothing/suit/storage/labcoat - name = "labcoat" - desc = "A suit that protects against minor chemical spills." - var/base_icon_state = "labcoat" - var/open=1 - //icon_state = "labcoat_open" - item_state = "labcoat" - blood_overlay_type = "coat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen) - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0) - species_fit = list("Vox") - - - - update_icon() - if(open) - icon_state="[base_icon_state]_open" - else - icon_state="[base_icon_state]" - - verb/toggle() - set name = "Toggle Labcoat Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.isUnconscious() || usr.restrained()) - return 0 - - if(open) - to_chat(usr, "You button up the labcoat.") - else - to_chat(usr, "You unbutton the labcoat.") - open=!open - update_icon() - usr.update_inv_wear_suit() //so our overlays update - -/obj/item/clothing/suit/storage/labcoat/New() - . = ..() - update_icon() - -/obj/item/clothing/suit/storage/labcoat/cmo - name = "chief medical officer's labcoat" - desc = "Bluer than the standard model." - base_icon_state = "labcoat_cmo" - item_state = "labcoat_cmo" - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/labcoat/mad - name = "The Mad's labcoat" - desc = "It makes you look capable of konking someone on the noggin and shooting them into space." - base_icon_state = "labgreen" - item_state = "labgreen" - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/labcoat/genetics - name = "Geneticist Labcoat" - desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder." - base_icon_state = "labcoat_gen" - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/labcoat/chemist - name = "Chemist Labcoat" - desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder." - base_icon_state = "labcoat_chem" - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/labcoat/virologist - 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." - base_icon_state = "labcoat_vir" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 0) - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/labcoat/science - name = "Scientist Labcoat" - desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder." - base_icon_state = "labcoat_tox" - species_fit = list("Vox") - -/obj/item/clothing/suit/storage/labcoat/oncologist - name = "Oncologist Labcoat" - desc = "A suit that protects against minor radiation exposure. Offers slightly more protection against radiation than the standard model. Has a black stripe on the shoulder." - base_icon_state = "labcoat_onc" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 60) +/obj/item/clothing/suit/storage/labcoat + name = "labcoat" + desc = "A suit that protects against minor chemical spills." + var/base_icon_state = "labcoat" + var/open=1 + //icon_state = "labcoat_open" + item_state = "labcoat" + blood_overlay_type = "coat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen) + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0) + species_fit = list("Vox") + + + + update_icon() + if(open) + icon_state="[base_icon_state]_open" + else + icon_state="[base_icon_state]" + + verb/toggle() + set name = "Toggle Labcoat Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.isUnconscious() || usr.restrained()) + return 0 + + if(open) + to_chat(usr, "You button up the labcoat.") + else + to_chat(usr, "You unbutton the labcoat.") + open=!open + update_icon() + usr.update_inv_wear_suit() //so our overlays update + +/obj/item/clothing/suit/storage/labcoat/New() + . = ..() + update_icon() + +/obj/item/clothing/suit/storage/labcoat/cmo + name = "chief medical officer's labcoat" + desc = "Bluer than the standard model." + base_icon_state = "labcoat_cmo" + item_state = "labcoat_cmo" + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/labcoat/mad + name = "The Mad's labcoat" + desc = "It makes you look capable of konking someone on the noggin and shooting them into space." + base_icon_state = "labgreen" + item_state = "labgreen" + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/labcoat/genetics + name = "Geneticist Labcoat" + desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder." + base_icon_state = "labcoat_gen" + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/labcoat/chemist + name = "Chemist Labcoat" + desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder." + base_icon_state = "labcoat_chem" + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/labcoat/virologist + 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." + base_icon_state = "labcoat_vir" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 0) + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/labcoat/science + name = "Scientist Labcoat" + desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder." + base_icon_state = "labcoat_tox" + species_fit = list("Vox") + +/obj/item/clothing/suit/storage/labcoat/oncologist + name = "Oncologist Labcoat" + desc = "A suit that protects against minor radiation exposure. Offers slightly more protection against radiation than the standard model. Has a black stripe on the shoulder." + base_icon_state = "labcoat_onc" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 60) species_fit = list("Vox") \ No newline at end of file diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 8708f4a701f..2268edd03eb 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -1,504 +1,504 @@ -/* - * Contains: - * Lasertag - * Costume - * Misc - */ - -/* - * Lasertag - */ -/obj/item/clothing/suit/bluetag - name = "blue laser tag armour" - desc = "Blue Pride, Station Wide" - icon_state = "bluetag" - item_state = "bluetag" - blood_overlay_type = "armor" - origin_tech = "materials=1;magnets=2" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - allowed = list (/obj/item/weapon/gun/energy/laser/bluetag) - siemens_coefficient = 3.0 - -/obj/item/clothing/suit/redtag - name = "red laser tag armour" - desc = "Pew pew pew" - icon_state = "redtag" - item_state = "redtag" - blood_overlay_type = "armor" - origin_tech = "materials=1;magnets=2" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - allowed = list (/obj/item/weapon/gun/energy/laser/redtag) - siemens_coefficient = 3.0 - -/* - * Costume - */ -/obj/item/clothing/suit/pirate - name = "pirate coat" - desc = "Yarr." - icon_state = "pirate" - item_state = "pirate" - flags = FPRINT - species_fit = list("Vox") - - -/obj/item/clothing/suit/hgpirate - name = "pirate captain coat" - desc = "Yarr." - icon_state = "hgpirate" - item_state = "hgpirate" - flags = FPRINT - flags_inv = HIDEJUMPSUIT - species_fit = list("Vox") - - -/obj/item/clothing/suit/cyborg_suit - name = "cyborg suit" - desc = "Suit for a cyborg costume." - icon_state = "death" - item_state = "death" - flags = FPRINT - siemens_coefficient = 1 - fire_resist = T0C+5200 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - - -/obj/item/clothing/suit/greatcoat - name = "great coat" - desc = "A Nazi great coat" - icon_state = "nazi" - item_state = "nazi" - flags = FPRINT - - -/obj/item/clothing/suit/johnny_coat - name = "johnny~~ coat" - desc = "Johnny~~" - icon_state = "johnny" - item_state = "johnny" - flags = FPRINT - - -/obj/item/clothing/suit/justice - name = "justice suit" - desc = "this pretty much looks ridiculous" - icon_state = "justice" - item_state = "justice" - flags = FPRINT - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - - -/obj/item/clothing/suit/judgerobe - name = "judge's robe" - desc = "This robe commands authority." - icon_state = "judge" - item_state = "judge" - flags = FPRINT | ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/spacecash) - flags_inv = HIDEJUMPSUIT - - -/obj/item/clothing/suit/wcoat - name = "waistcoat" - desc = "For some classy, murderous fun." - icon_state = "vest" - item_state = "wcoat" - blood_overlay_type = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - - -/obj/item/clothing/suit/apron/overalls - name = "coveralls" - desc = "A set of denim overalls." - icon_state = "overalls" - item_state = "overalls" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS - - -/obj/item/clothing/suit/syndicatefake - name = "red space suit replica" - icon_state = "syndicate" - item_state = "space_suit_syndicate" - desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!" - w_class = 3 - flags = FPRINT - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/toy) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - - -/obj/item/clothing/suit/hastur - name = "Hastur's Robes" - desc = "Robes not meant to be worn by man" - icon_state = "hastur" - item_state = "hastur" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - - -/obj/item/clothing/suit/imperium_monk - name = "Imperium monk" - desc = "Have YOU killed a xenos today?" - icon_state = "imperium_monk" - item_state = "imperium_monk" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDESHOES|HIDEJUMPSUIT - - -/obj/item/clothing/suit/chickensuit - name = "Chicken Suit" - desc = "A suit made long ago by the ancient empire KFC." - icon_state = "chickensuit" - item_state = "chickensuit" - body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET - flags_inv = HIDESHOES|HIDEJUMPSUIT - siemens_coefficient = 2.0 - - -/obj/item/clothing/suit/monkeysuit - name = "Monkey Suit" - desc = "A suit that looks like a primate" - icon_state = "monkeysuit" - item_state = "monkeysuit" - body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET|HANDS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - siemens_coefficient = 2.0 - - -/obj/item/clothing/suit/holidaypriest - name = "Holiday Priest" - desc = "This is a nice holiday my son." - icon_state = "holidaypriest" - item_state = "holidaypriest" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDEJUMPSUIT - - -/obj/item/clothing/suit/cardborg - name = "cardborg suit" - desc = "An ordinary cardboard box with holes cut in the sides." - icon_state = "cardborg" - item_state = "cardborg" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - flags_inv = HIDEJUMPSUIT - starting_materials = list(MAT_CARDBOARD = 11250) - w_type=RECYK_MISC - -/* - * Misc - */ - -/obj/item/clothing/suit/straight_jacket - name = "straight jacket" - desc = "A suit that completely restrains the wearer." - icon_state = "straight_jacket" - item_state = "straight_jacket" - origin_tech = "biotech=2" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - -/obj/item/clothing/suit/ianshirt - name = "worn shirt" - desc = "A worn out, curiously comfortable t-shirt with a picture of Ian. You wouldn't go so far as to say it feels like being hugged when you wear it but it's pretty close. Good for sleeping in." - icon_state = "ianshirt" - item_state = "ianshirt" - -//Blue suit jacket toggle -/obj/item/clothing/suit/suit/verb/toggle() - set name = "Toggle Jacket Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.isUnconscious() || usr.restrained()) - return 0 - - if(src.icon_state == "suitjacket_blue_open") - src.icon_state = "suitjacket_blue" - src.item_state = "suitjacket_blue" - to_chat(usr, "You button up the suit jacket.") - else if(src.icon_state == "suitjacket_blue") - src.icon_state = "suitjacket_blue_open" - src.item_state = "suitjacket_blue_open" - to_chat(usr, "You unbutton the suit jacket.") - else - to_chat(usr, "You button-up some imaginary buttons on your [src].") - return - usr.update_inv_wear_suit() - -//pyjamas -//originally intended to be pinstripes >.> - -/obj/item/clothing/under/bluepyjamas - name = "blue pyjamas" - desc = "Slightly old-fashioned sleepwear." - icon_state = "blue_pyjamas" - item_state = "blue_pyjamas" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - -/obj/item/clothing/under/redpyjamas - name = "red pyjamas" - desc = "Slightly old-fashioned sleepwear." - icon_state = "red_pyjamas" - item_state = "red_pyjamas" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - -//coats - -/obj/item/clothing/suit/leathercoat - name = "leather coat" - desc = "A long, thick black leather coat." - icon_state = "leathercoat" - item_state = "leathercoat" - flags = FPRINT - -/obj/item/clothing/suit/browncoat - name = "brown leather coat" - desc = "A long, brown leather coat." - icon_state = "browncoat" - item_state = "browncoat" - flags = FPRINT - -/obj/item/clothing/suit/neocoat - name = "black coat" - desc = "A flowing, black coat." - icon_state = "neocoat" - item_state = "neocoat" - flags = FPRINT - -//actual suits - -/obj/item/clothing/suit/creamsuit - name = "cream suit" - desc = "A cream coloured, genteel suit." - icon_state = "creamsuit" - item_state = "creamsuit" - flags = FPRINT - -//stripper - -/obj/item/clothing/under/stripper/stripper_pink - name = "pink swimsuit" - desc = "A rather skimpy pink swimsuit." - icon_state = "stripper_p_under" - _color = "stripper_p" - siemens_coefficient = 1 - -/obj/item/clothing/under/stripper/stripper_green - name = "green swimsuit" - desc = "A rather skimpy green swimsuit." - icon_state = "stripper_g_under" - _color = "stripper_g" - siemens_coefficient = 1 - -/obj/item/clothing/suit/stripper/stripper_pink - name = "pink skimpy dress" - desc = "A rather skimpy pink dress." - icon_state = "stripper_p_over" - item_state = "stripper_p" - siemens_coefficient = 1 - -/obj/item/clothing/suit/stripper/stripper_green - name = "green skimpy dress" - desc = "A rather skimpy green dress." - icon_state = "stripper_g_over" - item_state = "stripper_g" - siemens_coefficient = 1 - -/obj/item/clothing/under/stripper/mankini - name = "the mankini" - desc = "No honest man would wear this abomination" - icon_state = "mankini" - _color = "mankini" - siemens_coefficient = 1 - -/obj/item/clothing/suit/xenos - name = "xenos suit" - desc = "A suit made out of chitinous alien hide." - icon_state = "xenos" - item_state = "xenos_helm" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - siemens_coefficient = 2.0 -//swimsuit -/obj/item/clothing/under/swimsuit/ - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/black - name = "black swimsuit" - desc = "An oldfashioned black swimsuit." - icon_state = "swim_black" - _color = "swim_black" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/blue - name = "blue swimsuit" - desc = "An oldfashioned blue swimsuit." - icon_state = "swim_blue" - _color = "swim_blue" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/purple - name = "purple swimsuit" - desc = "An oldfashioned purple swimsuit." - icon_state = "swim_purp" - _color = "swim_purp" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/green - name = "green swimsuit" - desc = "An oldfashioned green swimsuit." - icon_state = "swim_green" - _color = "swim_green" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/red - name = "red swimsuit" - desc = "An oldfashioned red swimsuit." - icon_state = "swim_red" - _color = "swim_red" - siemens_coefficient = 1 - -/obj/item/clothing/suit/simonjacket - name = "Simon's Jacket" - desc = "Now you too can pierce the heavens" - icon_state = "simonjacket" - item_state = "simonjacket" - species_fit = list("Vox") - -/obj/item/clothing/suit/kaminacape - name = "Kamina's Cape" - desc = "Don't believe in yourself, dumbass. Believe in me. Believe in the Kamina who believes in you." - icon_state = "kaminacape" - item_state = "kaminacape" - -/obj/item/clothing/suit/storage/bandolier - name = "bandolier" - desc = "A bandolier designed to hold up to eight shotgun shells." - icon_state = "bandolier" - item_state = "bandolier" - storage_slots = 8 - max_combined_w_class = 20 - can_hold = list("/obj/item/ammo_casing/shotgun") - -/obj/item/clothing/suit/officercoat - name = "Officer's Coat" - desc = "Ein Mantel gemacht, um die Juden zu bestrafen." - icon_state = "officersuit" - item_state = "officersuit" - -/obj/item/clothing/suit/soldiercoat - name = "Soldier's Coat" - desc = "Ein Mantel gemacht, um die Verbündeten zu zerstören." - icon_state = "soldiersuit" - item_state = "soldiersuit" - -/obj/item/clothing/suit/russofurcoat - name = "russian fur coat" - desc = "Let the land do the fighting for you." - icon_state = "russofurcoat" - item_state = "russofurcoat" - allowed = list(/obj/item/weapon/gun) - -/obj/item/clothing/suit/doshjacket - name = "Plasterer's Jacket" - desc = "Perfect for doing up the house." - icon_state = "doshjacket" - item_state = "doshjacket" - -/obj/item/clothing/suit/lordadmiral - name = "Lord Admiral's Coat" - desc = "You'll be the Ruler of the King's Navy in no time." - icon_state = "lordadmiral" - item_state = "lordadmiral" - allowed = list (/obj/item/weapon/gun) - -/obj/item/clothing/suit/raincoat - name = "Raincoat" - desc = "Do you like Huey Lewis and the News?" - icon_state = "raincoat" - item_state = "raincoat" - allowed = list (/obj/item/weapon/fireaxe) - -/obj/item/clothing/suit/kefkarobe - name = "Crazed Jester's Robe" - desc = "Do I look like a waiter?" - icon_state = "kefkarobe" -/obj/item/clothing/suit/libertycoat - name = "Liberty Coat" - desc = "Smells faintly of freedom." - icon_state = "libertycoat" - item_state = "libertycoat" -/obj/item/clothing/suit/storage/draculacoat - name = "Vampire Coat" - desc = "What is a man? A miserable little pile of secrets." - icon_state = "draculacoat" - item_state = "draculacoat" - blood_overlay_type = "coat" - cant_hold = list(/obj/item/weapon/nullrod, /obj/item/weapon/storage/bible) - armor = list(melee = 30, bullet = 20, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) - -/obj/item/clothing/suit/maidapron - name = "Apron" - desc = "Simple white apron." - icon_state = "maidapron" - item_state = "maidapron" - -/obj/item/clothing/suit/clownpiece - name = "small fairy wings" - desc = "Some small and translucid insect-like wings." - icon_state = "clownpiece" - item_state = "clownpiece" - -/obj/item/clothing/suit/clownpiece/flying - name = "small fairy wings" - desc = "Some small and translucid insect-like wings. Looks like these are the real deal!" - icon_state = "clownpiece-fly" - item_state = "clownpiece" - -/obj/item/clothing/suit/clownpiece/flying/attack_hand(var/mob/living/carbon/human/H) - if(!istype(H)) - return ..() - if((src == H.wear_suit) && H.flying) - H.flying = 0 - animate(H, pixel_y = pixel_y + 10 , time = 1, loop = 1) - animate(H, pixel_y = pixel_y, time = 10, loop = 1, easing = SINE_EASING) - animate(H) - if(H.lying)//aka. if they have just been stunned - H.pixel_y -= 6 - ..() - -/obj/item/clothing/suit/clownpiece/flying/equipped(var/mob/user, var/slot) - var/mob/living/carbon/human/H = user - if(!istype(H)) return - if((slot == slot_wear_suit) && !user.flying) - user.flying = 1 - animate(user, pixel_y = pixel_y + 10 , time = 10, loop = 1, easing = SINE_EASING) - -/obj/item/clothing/suit/clownpiece/flying/dropped(mob/user as mob) - if(user.flying) - user.flying = 0 - animate(user, pixel_y = pixel_y + 10 , time = 1, loop = 1) - animate(user, pixel_y = pixel_y, time = 10, loop = 1, easing = SINE_EASING) - animate(user) - if(user.lying)//aka. if they have just been stunned - user.pixel_y -= 6 - ..() - -/obj/item/clothing/suit/jumper/christmas - name = "christmas jumper" - desc = "Made by professional knitting nanas to truly fit the festive mood." - -/obj/item/clothing/suit/jumper/christmas/red - desc = "Made by professional knitting nanas to truly fit the festive mood. This one has a tasteful red colour to it, and a festive Fir tree." - icon_state = "cjumper-red" - item_state = "cjumper-red" - -/obj/item/clothing/suit/jumper/christmas/blue - desc = "Made by professional knitting nanas to truly fit the festive mood. This one has a nice light blue colouring to it, and has a snowman on it." - icon_state = "cjumper-blue" - item_state = "cjumper-blue" - -/obj/item/clothing/suit/jumper/christmas/green - desc = "Made by professional knitting nanas to truly fit the festive mood. This one is green in colour, and has a reindeer with a red nose on the front. At least you think it's a reindeer." - icon_state = "cjumper-green" - item_state = "cjumper-green" +/* + * Contains: + * Lasertag + * Costume + * Misc + */ + +/* + * Lasertag + */ +/obj/item/clothing/suit/bluetag + name = "blue laser tag armour" + desc = "Blue Pride, Station Wide" + icon_state = "bluetag" + item_state = "bluetag" + blood_overlay_type = "armor" + origin_tech = "materials=1;magnets=2" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + allowed = list (/obj/item/weapon/gun/energy/laser/bluetag) + siemens_coefficient = 3.0 + +/obj/item/clothing/suit/redtag + name = "red laser tag armour" + desc = "Pew pew pew" + icon_state = "redtag" + item_state = "redtag" + blood_overlay_type = "armor" + origin_tech = "materials=1;magnets=2" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + allowed = list (/obj/item/weapon/gun/energy/laser/redtag) + siemens_coefficient = 3.0 + +/* + * Costume + */ +/obj/item/clothing/suit/pirate + name = "pirate coat" + desc = "Yarr." + icon_state = "pirate" + item_state = "pirate" + flags = FPRINT + species_fit = list("Vox") + + +/obj/item/clothing/suit/hgpirate + name = "pirate captain coat" + desc = "Yarr." + icon_state = "hgpirate" + item_state = "hgpirate" + flags = FPRINT + flags_inv = HIDEJUMPSUIT + species_fit = list("Vox") + + +/obj/item/clothing/suit/cyborg_suit + name = "cyborg suit" + desc = "Suit for a cyborg costume." + icon_state = "death" + item_state = "death" + flags = FPRINT + siemens_coefficient = 1 + fire_resist = T0C+5200 + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + + +/obj/item/clothing/suit/greatcoat + name = "great coat" + desc = "A Nazi great coat" + icon_state = "nazi" + item_state = "nazi" + flags = FPRINT + + +/obj/item/clothing/suit/johnny_coat + name = "johnny~~ coat" + desc = "Johnny~~" + icon_state = "johnny" + item_state = "johnny" + flags = FPRINT + + +/obj/item/clothing/suit/justice + name = "justice suit" + desc = "this pretty much looks ridiculous" + icon_state = "justice" + item_state = "justice" + flags = FPRINT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + + +/obj/item/clothing/suit/judgerobe + name = "judge's robe" + desc = "This robe commands authority." + icon_state = "judge" + item_state = "judge" + flags = FPRINT | ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/spacecash) + flags_inv = HIDEJUMPSUIT + + +/obj/item/clothing/suit/wcoat + name = "waistcoat" + desc = "For some classy, murderous fun." + icon_state = "vest" + item_state = "wcoat" + blood_overlay_type = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + + +/obj/item/clothing/suit/apron/overalls + name = "coveralls" + desc = "A set of denim overalls." + icon_state = "overalls" + item_state = "overalls" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS + + +/obj/item/clothing/suit/syndicatefake + name = "red space suit replica" + icon_state = "syndicate" + item_state = "space_suit_syndicate" + desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!" + w_class = 3 + flags = FPRINT + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/toy) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + + +/obj/item/clothing/suit/hastur + name = "Hastur's Robes" + desc = "Robes not meant to be worn by man" + icon_state = "hastur" + item_state = "hastur" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + + +/obj/item/clothing/suit/imperium_monk + name = "Imperium monk" + desc = "Have YOU killed a xenos today?" + icon_state = "imperium_monk" + item_state = "imperium_monk" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDESHOES|HIDEJUMPSUIT + + +/obj/item/clothing/suit/chickensuit + name = "Chicken Suit" + desc = "A suit made long ago by the ancient empire KFC." + icon_state = "chickensuit" + item_state = "chickensuit" + body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET + flags_inv = HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 2.0 + + +/obj/item/clothing/suit/monkeysuit + name = "Monkey Suit" + desc = "A suit that looks like a primate" + icon_state = "monkeysuit" + item_state = "monkeysuit" + body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET|HANDS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 2.0 + + +/obj/item/clothing/suit/holidaypriest + name = "Holiday Priest" + desc = "This is a nice holiday my son." + icon_state = "holidaypriest" + item_state = "holidaypriest" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDEJUMPSUIT + + +/obj/item/clothing/suit/cardborg + name = "cardborg suit" + desc = "An ordinary cardboard box with holes cut in the sides." + icon_state = "cardborg" + item_state = "cardborg" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + flags_inv = HIDEJUMPSUIT + starting_materials = list(MAT_CARDBOARD = 11250) + w_type=RECYK_MISC + +/* + * Misc + */ + +/obj/item/clothing/suit/straight_jacket + name = "straight jacket" + desc = "A suit that completely restrains the wearer." + icon_state = "straight_jacket" + item_state = "straight_jacket" + origin_tech = "biotech=2" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + +/obj/item/clothing/suit/ianshirt + name = "worn shirt" + desc = "A worn out, curiously comfortable t-shirt with a picture of Ian. You wouldn't go so far as to say it feels like being hugged when you wear it but it's pretty close. Good for sleeping in." + icon_state = "ianshirt" + item_state = "ianshirt" + +//Blue suit jacket toggle +/obj/item/clothing/suit/suit/verb/toggle() + set name = "Toggle Jacket Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.isUnconscious() || usr.restrained()) + return 0 + + if(src.icon_state == "suitjacket_blue_open") + src.icon_state = "suitjacket_blue" + src.item_state = "suitjacket_blue" + to_chat(usr, "You button up the suit jacket.") + else if(src.icon_state == "suitjacket_blue") + src.icon_state = "suitjacket_blue_open" + src.item_state = "suitjacket_blue_open" + to_chat(usr, "You unbutton the suit jacket.") + else + to_chat(usr, "You button-up some imaginary buttons on your [src].") + return + usr.update_inv_wear_suit() + +//pyjamas +//originally intended to be pinstripes >.> + +/obj/item/clothing/under/bluepyjamas + name = "blue pyjamas" + desc = "Slightly old-fashioned sleepwear." + icon_state = "blue_pyjamas" + item_state = "blue_pyjamas" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + +/obj/item/clothing/under/redpyjamas + name = "red pyjamas" + desc = "Slightly old-fashioned sleepwear." + icon_state = "red_pyjamas" + item_state = "red_pyjamas" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + +//coats + +/obj/item/clothing/suit/leathercoat + name = "leather coat" + desc = "A long, thick black leather coat." + icon_state = "leathercoat" + item_state = "leathercoat" + flags = FPRINT + +/obj/item/clothing/suit/browncoat + name = "brown leather coat" + desc = "A long, brown leather coat." + icon_state = "browncoat" + item_state = "browncoat" + flags = FPRINT + +/obj/item/clothing/suit/neocoat + name = "black coat" + desc = "A flowing, black coat." + icon_state = "neocoat" + item_state = "neocoat" + flags = FPRINT + +//actual suits + +/obj/item/clothing/suit/creamsuit + name = "cream suit" + desc = "A cream coloured, genteel suit." + icon_state = "creamsuit" + item_state = "creamsuit" + flags = FPRINT + +//stripper + +/obj/item/clothing/under/stripper/stripper_pink + name = "pink swimsuit" + desc = "A rather skimpy pink swimsuit." + icon_state = "stripper_p_under" + _color = "stripper_p" + siemens_coefficient = 1 + +/obj/item/clothing/under/stripper/stripper_green + name = "green swimsuit" + desc = "A rather skimpy green swimsuit." + icon_state = "stripper_g_under" + _color = "stripper_g" + siemens_coefficient = 1 + +/obj/item/clothing/suit/stripper/stripper_pink + name = "pink skimpy dress" + desc = "A rather skimpy pink dress." + icon_state = "stripper_p_over" + item_state = "stripper_p" + siemens_coefficient = 1 + +/obj/item/clothing/suit/stripper/stripper_green + name = "green skimpy dress" + desc = "A rather skimpy green dress." + icon_state = "stripper_g_over" + item_state = "stripper_g" + siemens_coefficient = 1 + +/obj/item/clothing/under/stripper/mankini + name = "the mankini" + desc = "No honest man would wear this abomination" + icon_state = "mankini" + _color = "mankini" + siemens_coefficient = 1 + +/obj/item/clothing/suit/xenos + name = "xenos suit" + desc = "A suit made out of chitinous alien hide." + icon_state = "xenos" + item_state = "xenos_helm" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 2.0 +//swimsuit +/obj/item/clothing/under/swimsuit/ + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/black + name = "black swimsuit" + desc = "An oldfashioned black swimsuit." + icon_state = "swim_black" + _color = "swim_black" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/blue + name = "blue swimsuit" + desc = "An oldfashioned blue swimsuit." + icon_state = "swim_blue" + _color = "swim_blue" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/purple + name = "purple swimsuit" + desc = "An oldfashioned purple swimsuit." + icon_state = "swim_purp" + _color = "swim_purp" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/green + name = "green swimsuit" + desc = "An oldfashioned green swimsuit." + icon_state = "swim_green" + _color = "swim_green" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/red + name = "red swimsuit" + desc = "An oldfashioned red swimsuit." + icon_state = "swim_red" + _color = "swim_red" + siemens_coefficient = 1 + +/obj/item/clothing/suit/simonjacket + name = "Simon's Jacket" + desc = "Now you too can pierce the heavens" + icon_state = "simonjacket" + item_state = "simonjacket" + species_fit = list("Vox") + +/obj/item/clothing/suit/kaminacape + name = "Kamina's Cape" + desc = "Don't believe in yourself, dumbass. Believe in me. Believe in the Kamina who believes in you." + icon_state = "kaminacape" + item_state = "kaminacape" + +/obj/item/clothing/suit/storage/bandolier + name = "bandolier" + desc = "A bandolier designed to hold up to eight shotgun shells." + icon_state = "bandolier" + item_state = "bandolier" + storage_slots = 8 + max_combined_w_class = 20 + can_hold = list("/obj/item/ammo_casing/shotgun") + +/obj/item/clothing/suit/officercoat + name = "Officer's Coat" + desc = "Ein Mantel gemacht, um die Juden zu bestrafen." + icon_state = "officersuit" + item_state = "officersuit" + +/obj/item/clothing/suit/soldiercoat + name = "Soldier's Coat" + desc = "Ein Mantel gemacht, um die Verbündeten zu zerstören." + icon_state = "soldiersuit" + item_state = "soldiersuit" + +/obj/item/clothing/suit/russofurcoat + name = "russian fur coat" + desc = "Let the land do the fighting for you." + icon_state = "russofurcoat" + item_state = "russofurcoat" + allowed = list(/obj/item/weapon/gun) + +/obj/item/clothing/suit/doshjacket + name = "Plasterer's Jacket" + desc = "Perfect for doing up the house." + icon_state = "doshjacket" + item_state = "doshjacket" + +/obj/item/clothing/suit/lordadmiral + name = "Lord Admiral's Coat" + desc = "You'll be the Ruler of the King's Navy in no time." + icon_state = "lordadmiral" + item_state = "lordadmiral" + allowed = list (/obj/item/weapon/gun) + +/obj/item/clothing/suit/raincoat + name = "Raincoat" + desc = "Do you like Huey Lewis and the News?" + icon_state = "raincoat" + item_state = "raincoat" + allowed = list (/obj/item/weapon/fireaxe) + +/obj/item/clothing/suit/kefkarobe + name = "Crazed Jester's Robe" + desc = "Do I look like a waiter?" + icon_state = "kefkarobe" +/obj/item/clothing/suit/libertycoat + name = "Liberty Coat" + desc = "Smells faintly of freedom." + icon_state = "libertycoat" + item_state = "libertycoat" +/obj/item/clothing/suit/storage/draculacoat + name = "Vampire Coat" + desc = "What is a man? A miserable little pile of secrets." + icon_state = "draculacoat" + item_state = "draculacoat" + blood_overlay_type = "coat" + cant_hold = list(/obj/item/weapon/nullrod, /obj/item/weapon/storage/bible) + armor = list(melee = 30, bullet = 20, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/suit/maidapron + name = "Apron" + desc = "Simple white apron." + icon_state = "maidapron" + item_state = "maidapron" + +/obj/item/clothing/suit/clownpiece + name = "small fairy wings" + desc = "Some small and translucid insect-like wings." + icon_state = "clownpiece" + item_state = "clownpiece" + +/obj/item/clothing/suit/clownpiece/flying + name = "small fairy wings" + desc = "Some small and translucid insect-like wings. Looks like these are the real deal!" + icon_state = "clownpiece-fly" + item_state = "clownpiece" + +/obj/item/clothing/suit/clownpiece/flying/attack_hand(var/mob/living/carbon/human/H) + if(!istype(H)) + return ..() + if((src == H.wear_suit) && H.flying) + H.flying = 0 + animate(H, pixel_y = pixel_y + 10 , time = 1, loop = 1) + animate(H, pixel_y = pixel_y, time = 10, loop = 1, easing = SINE_EASING) + animate(H) + if(H.lying)//aka. if they have just been stunned + H.pixel_y -= 6 + ..() + +/obj/item/clothing/suit/clownpiece/flying/equipped(var/mob/user, var/slot) + var/mob/living/carbon/human/H = user + if(!istype(H)) return + if((slot == slot_wear_suit) && !user.flying) + user.flying = 1 + animate(user, pixel_y = pixel_y + 10 , time = 10, loop = 1, easing = SINE_EASING) + +/obj/item/clothing/suit/clownpiece/flying/dropped(mob/user as mob) + if(user.flying) + user.flying = 0 + animate(user, pixel_y = pixel_y + 10 , time = 1, loop = 1) + animate(user, pixel_y = pixel_y, time = 10, loop = 1, easing = SINE_EASING) + animate(user) + if(user.lying)//aka. if they have just been stunned + user.pixel_y -= 6 + ..() + +/obj/item/clothing/suit/jumper/christmas + name = "christmas jumper" + desc = "Made by professional knitting nanas to truly fit the festive mood." + +/obj/item/clothing/suit/jumper/christmas/red + desc = "Made by professional knitting nanas to truly fit the festive mood. This one has a tasteful red colour to it, and a festive Fir tree." + icon_state = "cjumper-red" + item_state = "cjumper-red" + +/obj/item/clothing/suit/jumper/christmas/blue + desc = "Made by professional knitting nanas to truly fit the festive mood. This one has a nice light blue colouring to it, and has a snowman on it." + icon_state = "cjumper-blue" + item_state = "cjumper-blue" + +/obj/item/clothing/suit/jumper/christmas/green + desc = "Made by professional knitting nanas to truly fit the festive mood. This one is green in colour, and has a reindeer with a red nose on the front. At least you think it's a reindeer." + icon_state = "cjumper-green" + item_state = "cjumper-green" diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 72a7b1af3ae..02ae74403a8 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -1,144 +1,144 @@ -/* - * Contains: - * Fire protection - * Bomb protection - * Radiation protection - */ - -/* - * Fire protection - */ - -/obj/item/clothing/suit/fire - name = "firesuit" - desc = "A suit that protects against fire and heat." - icon_state = "fire" - item_state = "fire_suit" - origin_tech = "materials=2;engineering=1" - w_class = 4//bulky item - 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,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/extinguisher) - slowdown = 1.0 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - flags = FPRINT | ONESIZEFITSALL - pressure_resistance = 3 * ONE_ATMOSPHERE - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS - - -/obj/item/clothing/suit/fire/firefighter - icon_state = "firesuit" - item_state = "firefighter" - - -/obj/item/clothing/suit/fire/heavy - name = "firesuit" - desc = "A suit that protects against extreme fire and heat." - //icon_state = "thermal" - item_state = "ro_suit" - w_class = 4//bulky item - slowdown = 1.5 - -/* - * Bomb protection - */ -/obj/item/clothing/head/bomb_hood - name = "bomb hood" - desc = "Use in case of bomb." - icon_state = "bombsuit" - flags = FPRINT - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR - body_parts_covered = FULL_HEAD - siemens_coefficient = 0 - species_fit = list("Vox") - -/obj/item/clothing/suit/bomb_suit - name = "bomb suit" - desc = "A suit designed for safety when handling explosives." - icon_state = "bombsuit" - item_state = "bombsuit" - w_class = 4 //Bulky item - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - flags = FPRINT - 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 - heat_protection = UPPER_TORSO|LOWER_TORSO - max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0 - species_fit = list("Vox") - -/obj/item/clothing/head/bomb_hood/security - icon_state = "bombsuitsec" - item_state = "bombsuitsec" - - -/obj/item/clothing/suit/bomb_suit/security - icon_state = "bombsuitsec" - item_state = "bombsuitsec" - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) - -/obj/item/clothing/head/advancedeod_helmet - name = "Advanced EOD Helmet" - desc = "Use in case of very large bomb." - icon_state = "advancedeod_helmet" - item_state = "advancedeod_helmet" - flags = FPRINT - armor = list(melee = 80, bullet = 80, laser = 40,energy = 20, bomb = 100, bio = 0, rad = 0) - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR - body_parts_covered = FULL_HEAD - species_restricted = list("exclude","Vox") - siemens_coefficient = 0 - - -/obj/item/clothing/suit/advancedeod - name = "Advanced EOD Suit" - desc = "A heavy suit designed for heavy protection." - icon_state = "advancedeod" - item_state = "advancedeod" - w_class = 4//bulky item - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - flags = FPRINT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - slowdown = 6 - armor = list(melee = 80, bullet = 80, laser = 40,energy = 20, bomb = 100, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT|HIDESHOES - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS - max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE - species_restricted = list("exclude","Vox") - siemens_coefficient = 0 - -/* - * Radiation protection - */ -/obj/item/clothing/head/radiation - name = "Radiation Hood" - icon_state = "rad" - desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation" - flags = FPRINT - flags_inv = HIDEHAIR - body_parts_covered = FULL_HEAD - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) - species_fit = list("Vox") - -/obj/item/clothing/suit/radiation - name = "Radiation suit" - desc = "A suit that protects against radiation. Label: Made with lead, do not eat insulation." - icon_state = "rad" - item_state = "rad_suit" - w_class = 4//bulky item - 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,/obj/item/weapon/tank/emergency_nitrogen) - slowdown = 1.5 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) - flags_inv = HIDEJUMPSUIT - species_fit = list("Vox") +/* + * Contains: + * Fire protection + * Bomb protection + * Radiation protection + */ + +/* + * Fire protection + */ + +/obj/item/clothing/suit/fire + name = "firesuit" + desc = "A suit that protects against fire and heat." + icon_state = "fire" + item_state = "fire_suit" + origin_tech = "materials=2;engineering=1" + w_class = 4//bulky item + 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,/obj/item/weapon/tank/emergency_nitrogen,/obj/item/weapon/extinguisher) + slowdown = 1.0 + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags = FPRINT | ONESIZEFITSALL + pressure_resistance = 3 * ONE_ATMOSPHERE + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS + + +/obj/item/clothing/suit/fire/firefighter + icon_state = "firesuit" + item_state = "firefighter" + + +/obj/item/clothing/suit/fire/heavy + name = "firesuit" + desc = "A suit that protects against extreme fire and heat." + //icon_state = "thermal" + item_state = "ro_suit" + w_class = 4//bulky item + slowdown = 1.5 + +/* + * Bomb protection + */ +/obj/item/clothing/head/bomb_hood + name = "bomb hood" + desc = "Use in case of bomb." + icon_state = "bombsuit" + flags = FPRINT + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR + body_parts_covered = FULL_HEAD + siemens_coefficient = 0 + species_fit = list("Vox") + +/obj/item/clothing/suit/bomb_suit + name = "bomb suit" + desc = "A suit designed for safety when handling explosives." + icon_state = "bombsuit" + item_state = "bombsuit" + w_class = 4 //Bulky item + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + flags = FPRINT + 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 + heat_protection = UPPER_TORSO|LOWER_TORSO + max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0 + species_fit = list("Vox") + +/obj/item/clothing/head/bomb_hood/security + icon_state = "bombsuitsec" + item_state = "bombsuitsec" + + +/obj/item/clothing/suit/bomb_suit/security + icon_state = "bombsuitsec" + item_state = "bombsuitsec" + allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) + +/obj/item/clothing/head/advancedeod_helmet + name = "Advanced EOD Helmet" + desc = "Use in case of very large bomb." + icon_state = "advancedeod_helmet" + item_state = "advancedeod_helmet" + flags = FPRINT + armor = list(melee = 80, bullet = 80, laser = 40,energy = 20, bomb = 100, bio = 0, rad = 0) + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR + body_parts_covered = FULL_HEAD + species_restricted = list("exclude","Vox") + siemens_coefficient = 0 + + +/obj/item/clothing/suit/advancedeod + name = "Advanced EOD Suit" + desc = "A heavy suit designed for heavy protection." + icon_state = "advancedeod" + item_state = "advancedeod" + w_class = 4//bulky item + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + flags = FPRINT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + slowdown = 6 + armor = list(melee = 80, bullet = 80, laser = 40,energy = 20, bomb = 100, bio = 0, rad = 0) + flags_inv = HIDEJUMPSUIT|HIDESHOES + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS + max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE + species_restricted = list("exclude","Vox") + siemens_coefficient = 0 + +/* + * Radiation protection + */ +/obj/item/clothing/head/radiation + name = "Radiation Hood" + icon_state = "rad" + desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation" + flags = FPRINT + flags_inv = HIDEHAIR + body_parts_covered = FULL_HEAD + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) + species_fit = list("Vox") + +/obj/item/clothing/suit/radiation + name = "Radiation suit" + desc = "A suit that protects against radiation. Label: Made with lead, do not eat insulation." + icon_state = "rad" + item_state = "rad_suit" + w_class = 4//bulky item + 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,/obj/item/weapon/tank/emergency_nitrogen) + slowdown = 1.5 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) + flags_inv = HIDEJUMPSUIT + species_fit = list("Vox") diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 458a5dc3ecf..1d3fc86e012 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -1,157 +1,157 @@ -/obj/item/clothing/head/wizard - name = "wizard hat" - desc = "Strange-looking hat-wear that most certainly belongs to a real magic user." - icon_state = "wizard" - //Not given any special protective value since the magic robes are full-body protection --NEO - siemens_coefficient = 0.8 - - wizard_garb = 1 - -/obj/item/clothing/head/wizard/red - name = "red wizard hat" - desc = "Strange-looking red hat-wear that most certainly belongs to a real magic user." - icon_state = "redwizard" - siemens_coefficient = 0.8 - -/obj/item/clothing/head/wizard/fake - name = "wizard hat" - desc = "It has WIZZARD written across it in sequins. Comes with a cool beard." - icon_state = "wizard-fake" - -/obj/item/clothing/head/wizard/marisa - name = "Witch Hat" - desc = "Strange-looking hat-wear, makes you want to cast fireballs." - icon_state = "marisa" - siemens_coefficient = 0.8 - -/obj/item/clothing/head/wizard/magus - name = "Magus Helm" - desc = "A mysterious helmet that hums with an unearthly power" - icon_state = "magus" - item_state = "magus" - siemens_coefficient = 0.8 - -/obj/item/clothing/head/wizard/clown - name = "purple wizard hat" - desc = "Strange-looking purple hat-wear that most certainly belongs to a real magic user." - icon_state = "wizhatclown" - item_state = "wizhatclown" // cheating - siemens_coefficient = 0.8 - -/obj/item/clothing/head/wizard/amp - name = "psychic amplifier" - desc = "A crown-of-thorns psychic amplifier. Kind of looks like a tiara having sex with an industrial robot." - icon_state = "amp" - siemens_coefficient = 0.8 - -/obj/item/clothing/head/wizard/necro - name = "Hood of Necromancy" - desc = "An elegant hood woven with the souls of the undying." - icon_state = "necromancer" - item_state = "necrohood" - siemens_coefficient = 0.8 - -/obj/item/clothing/head/wizard/magician - name = "Magical Tophat" - desc = "A magical tophat perfect for any magical performance." - icon_state = "tophat" - item_state = "tophat" - siemens_coefficient = 0.8 - - -/obj/item/clothing/suit/wizrobe - name = "wizard robe" - desc = "A magnificant, gem-lined robe that seems to radiate power." - icon_state = "wizard" - item_state = "wizrobe" - gas_transfer_coefficient = 0.01 // IT'S MAGICAL OKAY JEEZ +1 TO NOT DIE - permeability_coefficient = 0.01 - body_parts_covered = FULL_BODY //It's magic, I ain't gotta explain shit. --NEO - armor = list(melee = 30, bullet = 20, laser = 20,energy = 20, bomb = 20, bio = 20, rad = 20) - allowed = list(/obj/item/weapon/teleportation_scroll) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0.8 - - wizard_garb = 1 - -/obj/item/clothing/suit/wizrobe/red - name = "red wizard robe" - desc = "A magnificant, red, gem-lined robe that seems to radiate power." - icon_state = "redwizard" - item_state = "redwizrobe" - -/obj/item/clothing/suit/wizrobe/marisa - name = "Witch Robe" - desc = "Magic is all about the spell power, ZE!" - icon_state = "marisa" - item_state = "marisarobe" - -/obj/item/clothing/suit/wizrobe/magusblue - name = "Magus Robe" - desc = "A set of armoured robes that seem to radiate a dark power" - icon_state = "magusblue" - item_state = "magusblue" - -/obj/item/clothing/suit/wizrobe/magusred - name = "Magus Robe" - desc = "A set of armoured robes that seem to radiate a dark power" - icon_state = "magusred" - item_state = "magusred" - -/obj/item/clothing/suit/wizrobe/clown - name = "Clown Robe" - desc = "A set of armoured robes that seem to radiate a dark power. That, and bad fashion decisions." - icon_state = "wizzclown" - item_state = "clownwizrobe" - -/obj/item/clothing/suit/wizrobe/psypurple - name = "purple robes" - desc = "Heavy, royal purple robes threaded with psychic amplifiers and weird, bulbous lenses. Do not machine wash." - icon_state = "psyamp" - item_state = "psyamp" - -/obj/item/clothing/suit/wizrobe/fake - name = "wizard robe" - desc = "A rather dull, blue robe meant to mimick real wizard robes." - icon_state = "wizard-fake" - item_state = "wizrobe" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 1.0 - -/obj/item/clothing/suit/wizrobe/necro - name = "Robe of Necromancy" - desc = "An elegant robe woven with the souls of the undying." - icon_state = "necromancer" - item_state = "necrorobe" - -/obj/item/clothing/head/wizard/marisa/fake - name = "Witch Hat" - desc = "Strange-looking hat-wear, makes you want to cast fireballs." - icon_state = "marisa" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 1.0 - -/obj/item/clothing/suit/wizrobe/marisa/fake - name = "Witch Robe" - desc = "Magic is all about the spell power, ZE!" - icon_state = "marisa" - item_state = "marisarobe" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 1.0 - - -/obj/item/clothing/suit/wizrobe/magician - name = "Magical Suit" - desc = "A magical stage outfit, perfect attire for sawwing assistants in half." - icon_state = "magiciansuit" - item_state = "magiciansuit" - species_restricted = list("exclude","Vox") //this outfit wont work very well for Vox - - -/obj/item/clothing/suit/wizrobe/magician/fake - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 1.0 - +/obj/item/clothing/head/wizard + name = "wizard hat" + desc = "Strange-looking hat-wear that most certainly belongs to a real magic user." + icon_state = "wizard" + //Not given any special protective value since the magic robes are full-body protection --NEO + siemens_coefficient = 0.8 + + wizard_garb = 1 + +/obj/item/clothing/head/wizard/red + name = "red wizard hat" + desc = "Strange-looking red hat-wear that most certainly belongs to a real magic user." + icon_state = "redwizard" + siemens_coefficient = 0.8 + +/obj/item/clothing/head/wizard/fake + name = "wizard hat" + desc = "It has WIZZARD written across it in sequins. Comes with a cool beard." + icon_state = "wizard-fake" + +/obj/item/clothing/head/wizard/marisa + name = "Witch Hat" + desc = "Strange-looking hat-wear, makes you want to cast fireballs." + icon_state = "marisa" + siemens_coefficient = 0.8 + +/obj/item/clothing/head/wizard/magus + name = "Magus Helm" + desc = "A mysterious helmet that hums with an unearthly power" + icon_state = "magus" + item_state = "magus" + siemens_coefficient = 0.8 + +/obj/item/clothing/head/wizard/clown + name = "purple wizard hat" + desc = "Strange-looking purple hat-wear that most certainly belongs to a real magic user." + icon_state = "wizhatclown" + item_state = "wizhatclown" // cheating + siemens_coefficient = 0.8 + +/obj/item/clothing/head/wizard/amp + name = "psychic amplifier" + desc = "A crown-of-thorns psychic amplifier. Kind of looks like a tiara having sex with an industrial robot." + icon_state = "amp" + siemens_coefficient = 0.8 + +/obj/item/clothing/head/wizard/necro + name = "Hood of Necromancy" + desc = "An elegant hood woven with the souls of the undying." + icon_state = "necromancer" + item_state = "necrohood" + siemens_coefficient = 0.8 + +/obj/item/clothing/head/wizard/magician + name = "Magical Tophat" + desc = "A magical tophat perfect for any magical performance." + icon_state = "tophat" + item_state = "tophat" + siemens_coefficient = 0.8 + + +/obj/item/clothing/suit/wizrobe + name = "wizard robe" + desc = "A magnificant, gem-lined robe that seems to radiate power." + icon_state = "wizard" + item_state = "wizrobe" + gas_transfer_coefficient = 0.01 // IT'S MAGICAL OKAY JEEZ +1 TO NOT DIE + permeability_coefficient = 0.01 + body_parts_covered = FULL_BODY //It's magic, I ain't gotta explain shit. --NEO + armor = list(melee = 30, bullet = 20, laser = 20,energy = 20, bomb = 20, bio = 20, rad = 20) + allowed = list(/obj/item/weapon/teleportation_scroll) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0.8 + + wizard_garb = 1 + +/obj/item/clothing/suit/wizrobe/red + name = "red wizard robe" + desc = "A magnificant, red, gem-lined robe that seems to radiate power." + icon_state = "redwizard" + item_state = "redwizrobe" + +/obj/item/clothing/suit/wizrobe/marisa + name = "Witch Robe" + desc = "Magic is all about the spell power, ZE!" + icon_state = "marisa" + item_state = "marisarobe" + +/obj/item/clothing/suit/wizrobe/magusblue + name = "Magus Robe" + desc = "A set of armoured robes that seem to radiate a dark power" + icon_state = "magusblue" + item_state = "magusblue" + +/obj/item/clothing/suit/wizrobe/magusred + name = "Magus Robe" + desc = "A set of armoured robes that seem to radiate a dark power" + icon_state = "magusred" + item_state = "magusred" + +/obj/item/clothing/suit/wizrobe/clown + name = "Clown Robe" + desc = "A set of armoured robes that seem to radiate a dark power. That, and bad fashion decisions." + icon_state = "wizzclown" + item_state = "clownwizrobe" + +/obj/item/clothing/suit/wizrobe/psypurple + name = "purple robes" + desc = "Heavy, royal purple robes threaded with psychic amplifiers and weird, bulbous lenses. Do not machine wash." + icon_state = "psyamp" + item_state = "psyamp" + +/obj/item/clothing/suit/wizrobe/fake + name = "wizard robe" + desc = "A rather dull, blue robe meant to mimick real wizard robes." + icon_state = "wizard-fake" + item_state = "wizrobe" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 1.0 + +/obj/item/clothing/suit/wizrobe/necro + name = "Robe of Necromancy" + desc = "An elegant robe woven with the souls of the undying." + icon_state = "necromancer" + item_state = "necrorobe" + +/obj/item/clothing/head/wizard/marisa/fake + name = "Witch Hat" + desc = "Strange-looking hat-wear, makes you want to cast fireballs." + icon_state = "marisa" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 1.0 + +/obj/item/clothing/suit/wizrobe/marisa/fake + name = "Witch Robe" + desc = "Magic is all about the spell power, ZE!" + icon_state = "marisa" + item_state = "marisarobe" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 1.0 + + +/obj/item/clothing/suit/wizrobe/magician + name = "Magical Suit" + desc = "A magical stage outfit, perfect attire for sawwing assistants in half." + icon_state = "magiciansuit" + item_state = "magiciansuit" + species_restricted = list("exclude","Vox") //this outfit wont work very well for Vox + + +/obj/item/clothing/suit/wizrobe/magician/fake + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 1.0 + diff --git a/code/modules/clothing/under/chameleon.dm b/code/modules/clothing/under/chameleon.dm index 1ef931b8d1d..108798854db 100644 --- a/code/modules/clothing/under/chameleon.dm +++ b/code/modules/clothing/under/chameleon.dm @@ -1,82 +1,82 @@ -/obj/item/clothing/under/chameleon -//starts off as black - name = "black jumpsuit" - icon_state = "black" - item_state = "bl_suit" - _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/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 - return - - - attackby(obj/item/clothing/under/U as obj, mob/user as mob) - ..() - if(istype(U, /obj/item/clothing/under/chameleon)) +/obj/item/clothing/under/chameleon +//starts off as black + name = "black jumpsuit" + icon_state = "black" + item_state = "bl_suit" + _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/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 + return + + + attackby(obj/item/clothing/under/U as obj, mob/user as mob) + ..() + if(istype(U, /obj/item/clothing/under/chameleon)) to_chat(user, "Nothing happens.") - return - if(istype(U, /obj/item/clothing/under)) - if(src.clothing_choices.Find(U)) + return + if(istype(U, /obj/item/clothing/under)) + if(src.clothing_choices.Find(U)) to_chat(user, "Pattern is already recognised by the suit.") - return - src.clothing_choices += U + return + src.clothing_choices += U to_chat(user, "Pattern absorbed by the suit.") - - - emp_act(severity) - name = "psychedelic" - desc = "Groovy!" - icon_state = "psyche" - _color = "psyche" - spawn(200) - name = "Black Jumpsuit" - icon_state = "bl_suit" - _color = "black" - desc = null - ..() - - - verb/change() - set name = "Change Color" - set category = "Object" - set src in usr - - if(icon_state == "psyche") + + + emp_act(severity) + name = "psychedelic" + desc = "Groovy!" + icon_state = "psyche" + _color = "psyche" + spawn(200) + name = "Black Jumpsuit" + icon_state = "bl_suit" + _color = "black" + desc = null + ..() + + + verb/change() + set name = "Change Color" + set category = "Object" + set src in usr + + if(icon_state == "psyche") to_chat(usr, "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) - return - - desc = null - permeability_coefficient = 0.90 - - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - _color = A._color - usr.update_inv_w_uniform() //so our overlays update. - - - -/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 + return + + var/obj/item/clothing/under/A + A = input("Select Colour to change it to", "BOOYEA", A) in clothing_choices + if(!A) + return + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + _color = A._color + usr.update_inv_w_uniform() //so our overlays update. + + + +/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 diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index fead209219d..b8969572b1f 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -1,183 +1,183 @@ -/obj/item/clothing/under/color/black - name = "black jumpsuit" - icon_state = "black" - item_state = "bl_suit" - _color = "black" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/blackf - name = "feminine black jumpsuit" - desc = "It's very smart and in a ladies-size!" - icon_state = "black" - item_state = "bl_suit" - _color = "blackf" - flags = FPRINT - -/obj/item/clothing/under/color/blue - name = "blue jumpsuit" - icon_state = "blue" - item_state = "b_suit" - _color = "blue" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/green - name = "green jumpsuit" - icon_state = "green" - item_state = "g_suit" - _color = "green" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/grey - name = "grey jumpsuit" - icon_state = "grey" - item_state = "gy_suit" - _color = "grey" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/color/orange - name = "orange jumpsuit" - icon_state = "orange" - item_state = "o_suit" - _color = "orange" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/prisoner - name = "prison jumpsuit" - desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." - icon_state = "prisoner" - item_state = "o_suit" - _color = "prisoner" - has_sensor = 2 - sensor_mode = 3 - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/pink - name = "pink jumpsuit" - icon_state = "pink" - item_state = "p_suit" - _color = "pink" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/red - name = "red jumpsuit" - icon_state = "red" - item_state = "r_suit" - _color = "red" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/white - name = "white jumpsuit" - icon_state = "white" - item_state = "w_suit" - _color = "white" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/color/yellow - name = "yellow jumpsuit" - icon_state = "yellow" - item_state = "y_suit" - _color = "yellow" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/psyche - name = "psychedelic jumpsuit" - desc = "Groovy!" - icon_state = "psyche" - _color = "psyche" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/lightblue - name = "lightblue jumpsuit" - icon_state = "lightblue" - _color = "lightblue" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/aqua - name = "aqua jumpsuit" - icon_state = "aqua" - _color = "aqua" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/purple - name = "purple jumpsuit" - icon_state = "purple" - item_state = "p_suit" - _color = "purple" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/lightpurple - name = "lightpurple jumpsuit" - icon_state = "lightpurple" - _color = "lightpurple" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/lightgreen - name = "lightgreen jumpsuit" - icon_state = "lightgreen" - _color = "lightgreen" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/lightbrown - name = "lightbrown jumpsuit" - icon_state = "lightbrown" - _color = "lightbrown" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/brown - name = "brown jumpsuit" - icon_state = "brown" - _color = "brown" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/yellowgreen - name = "yellowgreen jumpsuit" - icon_state = "yellowgreen" - _color = "yellowgreen" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/darkblue - name = "darkblue jumpsuit" - icon_state = "darkblue" - _color = "darkblue" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/lightred - name = "lightred jumpsuit" - icon_state = "lightred" - _color = "lightred" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/darkred - name = "darkred jumpsuit" - icon_state = "darkred" - _color = "darkred" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/blackpants - name = "black pants" - icon_state = "blpants" - _color = "blpants" - flags = FPRINT | ONESIZEFITSALL - gender = PLURAL - -/obj/item/clothing/under/redpants - name = "red pants" - icon_state = "rpants" - _color = "rpants" - flags = FPRINT | ONESIZEFITSALL - gender = PLURAL - -/obj/item/clothing/under/bluepants - name = "blue pants" - icon_state = "bpants" - _color = "bpants" - flags = FPRINT | ONESIZEFITSALL - gender = PLURAL - -/obj/item/clothing/under/greypants - name = "grey pants" - icon_state = "gpants" - _color = "gpants" - flags = FPRINT | ONESIZEFITSALL - gender = PLURAL +/obj/item/clothing/under/color/black + name = "black jumpsuit" + icon_state = "black" + item_state = "bl_suit" + _color = "black" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/blackf + name = "feminine black jumpsuit" + desc = "It's very smart and in a ladies-size!" + icon_state = "black" + item_state = "bl_suit" + _color = "blackf" + flags = FPRINT + +/obj/item/clothing/under/color/blue + name = "blue jumpsuit" + icon_state = "blue" + item_state = "b_suit" + _color = "blue" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/green + name = "green jumpsuit" + icon_state = "green" + item_state = "g_suit" + _color = "green" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/grey + name = "grey jumpsuit" + icon_state = "grey" + item_state = "gy_suit" + _color = "grey" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/color/orange + name = "orange jumpsuit" + icon_state = "orange" + item_state = "o_suit" + _color = "orange" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/prisoner + name = "prison jumpsuit" + desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." + icon_state = "prisoner" + item_state = "o_suit" + _color = "prisoner" + has_sensor = 2 + sensor_mode = 3 + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/pink + name = "pink jumpsuit" + icon_state = "pink" + item_state = "p_suit" + _color = "pink" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/red + name = "red jumpsuit" + icon_state = "red" + item_state = "r_suit" + _color = "red" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/white + name = "white jumpsuit" + icon_state = "white" + item_state = "w_suit" + _color = "white" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/color/yellow + name = "yellow jumpsuit" + icon_state = "yellow" + item_state = "y_suit" + _color = "yellow" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/psyche + name = "psychedelic jumpsuit" + desc = "Groovy!" + icon_state = "psyche" + _color = "psyche" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/lightblue + name = "lightblue jumpsuit" + icon_state = "lightblue" + _color = "lightblue" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/aqua + name = "aqua jumpsuit" + icon_state = "aqua" + _color = "aqua" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/purple + name = "purple jumpsuit" + icon_state = "purple" + item_state = "p_suit" + _color = "purple" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/lightpurple + name = "lightpurple jumpsuit" + icon_state = "lightpurple" + _color = "lightpurple" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/lightgreen + name = "lightgreen jumpsuit" + icon_state = "lightgreen" + _color = "lightgreen" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/lightbrown + name = "lightbrown jumpsuit" + icon_state = "lightbrown" + _color = "lightbrown" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/brown + name = "brown jumpsuit" + icon_state = "brown" + _color = "brown" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/yellowgreen + name = "yellowgreen jumpsuit" + icon_state = "yellowgreen" + _color = "yellowgreen" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/darkblue + name = "darkblue jumpsuit" + icon_state = "darkblue" + _color = "darkblue" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/lightred + name = "lightred jumpsuit" + icon_state = "lightred" + _color = "lightred" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/darkred + name = "darkred jumpsuit" + icon_state = "darkred" + _color = "darkred" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/blackpants + name = "black pants" + icon_state = "blpants" + _color = "blpants" + flags = FPRINT | ONESIZEFITSALL + gender = PLURAL + +/obj/item/clothing/under/redpants + name = "red pants" + icon_state = "rpants" + _color = "rpants" + flags = FPRINT | ONESIZEFITSALL + gender = PLURAL + +/obj/item/clothing/under/bluepants + name = "blue pants" + icon_state = "bpants" + _color = "bpants" + flags = FPRINT | ONESIZEFITSALL + gender = PLURAL + +/obj/item/clothing/under/greypants + name = "grey pants" + icon_state = "gpants" + _color = "gpants" + flags = FPRINT | ONESIZEFITSALL + gender = PLURAL diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 9e9388f98f0..cd01a6424b1 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -1,217 +1,217 @@ -//Alphabetical order of civilian jobs. - -/obj/item/clothing/under/rank/bartender - desc = "It looks like it could use some more flair." - name = "bartender's uniform" - icon_state = "ba_suit" - item_state = "ba_suit" - _color = "ba_suit" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/captain //Alright, technically not a 'civilian' but its better then giving a .dm file for a single define. - desc = "It's a blue jumpsuit with some gold markings denoting the rank of \"Captain\"." - name = "captain's jumpsuit" - icon_state = "captain" - item_state = "caparmor" - _color = "captain" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/cargo - name = "quartermaster's jumpsuit" - desc = "It's a jumpsuit worn by the quartermaster. It's specially designed to prevent back injuries caused by pushing paper." - icon_state = "qm" - item_state = "lb_suit" - _color = "qm" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/cargotech - name = "cargo technician's jumpsuit" - desc = "Shooooorts! They're comfy and easy to wear!" - icon_state = "cargotech" - item_state = "lb_suit" - _color = "cargo" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/chaplain - desc = "It's a black jumpsuit, often worn by religious folk." - name = "chaplain's jumpsuit" - icon_state = "chaplain" - item_state = "bl_suit" - _color = "chapblack" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/chef - desc = "It's an apron which is given only to the most hardcore chefs in space." - name = "chef's uniform" - icon_state = "chef" - _color = "chef" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/clown - name = "clown suit" - desc = "'HONK!'" - icon_state = "clown" - item_state = "clown" - _color = "clown" - flags = FPRINT | ONESIZEFITSALL - - -/obj/item/clothing/under/rank/head_of_personnel - desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"." - name = "head of personnel's jumpsuit" - icon_state = "hop" - item_state = "b_suit" - _color = "hop" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/hydroponics - desc = "It's a jumpsuit designed to protect against minor plant-related hazards." - name = "hydroponicist's jumpsuit" - icon_state = "hydroponics" - item_state = "g_suit" - _color = "hydroponics" - permeability_coefficient = 0.50 - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/botany - desc = "It's a jumpsuit designed to protect against minor plant-related hazards. For the more garden-minded botanist." - name = "botanist's jumpsuit" - icon_state = "botany" - item_state = "botany" - _color = "botany" - permeability_coefficient = 0.50 - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/beekeeper - desc = "It's a jumpsuit designed to protect against minor plant-related hazards. Hopefully bees will see you as one of them." - name = "beekeeper's jumpsuit" - icon_state = "beekeeper" - item_state = "g_suit" - _color = "beekeeper" - permeability_coefficient = 0.50 - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/gardener - desc = "It's a jumpsuit designed to protect against minor plant-related hazards. For those who value the embelishment of the station." - name = "gardener's jumpsuit" - icon_state = "gardener" - item_state = "g_suit" - _color = "gardener" - permeability_coefficient = 0.50 - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/internalaffairs - desc = "The plain, professional attire of an Internal Affairs Agent. The collar is immaculately starched." - name = "Internal Affairs uniform" - icon_state = "internalaffairs" - item_state = "internalaffairs" - _color = "internalaffairs" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/rank/janitor - desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." - name = "janitor's jumpsuit" - icon_state = "janitor" - _color = "janitor" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/lawyer - desc = "Slick threads." - name = "Lawyer suit" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/lawyer/black - icon_state = "lawyer_black" - item_state = "lawyer_black" - _color = "lawyer_black" - species_fit = list("Vox") - -/obj/item/clothing/under/lawyer/female - icon_state = "black_suit_fem" - item_state = "black_suit_fem" - _color = "black_suit_fem" - species_fit = list("Vox") - -/obj/item/clothing/under/lawyer/red - icon_state = "lawyer_red" - item_state = "lawyer_red" - _color = "lawyer_red" - species_fit = list("Vox") - -/obj/item/clothing/under/lawyer/blue - icon_state = "lawyer_blue" - item_state = "lawyer_blue" - _color = "lawyer_blue" - species_fit = list("Vox") - -/obj/item/clothing/under/lawyer/bluesuit - name = "Blue Suit" - desc = "A classy suit and tie" - icon_state = "bluesuit" - item_state = "bluesuit" - _color = "bluesuit" - species_fit = list("Vox") - -/obj/item/clothing/under/lawyer/purpsuit - name = "Purple Suit" - icon_state = "lawyer_purp" - item_state = "lawyer_purp" - _color = "lawyer_purp" - species_fit = list("Vox") - -/obj/item/clothing/under/lawyer/oldman - name = "Old Man's Suit" - desc = "A classic suit for the older gentleman with built in back support." - icon_state = "oldman" - item_state = "oldman" - _color = "oldman" - species_fit = list("Vox") - - -/obj/item/clothing/under/librarian - name = "sensible suit" - desc = "It's very... sensible." - icon_state = "red_suit" - item_state = "red_suit" - _color = "red_suit" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - -/obj/item/clothing/under/mime - name = "mime's outfit" - desc = "It's not very colourful." - icon_state = "mime" - item_state = "mime" - _color = "mime" - flags = FPRINT | ONESIZEFITSALL - - -/obj/item/clothing/under/rank/miner - desc = "It's a snappy jumpsuit with a sturdy set of overalls. It is very dirty." - name = "shaft miner's jumpsuit" - icon_state = "miner" - item_state = "miner" - _color = "miner" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") +//Alphabetical order of civilian jobs. + +/obj/item/clothing/under/rank/bartender + desc = "It looks like it could use some more flair." + name = "bartender's uniform" + icon_state = "ba_suit" + item_state = "ba_suit" + _color = "ba_suit" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/captain //Alright, technically not a 'civilian' but its better then giving a .dm file for a single define. + desc = "It's a blue jumpsuit with some gold markings denoting the rank of \"Captain\"." + name = "captain's jumpsuit" + icon_state = "captain" + item_state = "caparmor" + _color = "captain" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/cargo + name = "quartermaster's jumpsuit" + desc = "It's a jumpsuit worn by the quartermaster. It's specially designed to prevent back injuries caused by pushing paper." + icon_state = "qm" + item_state = "lb_suit" + _color = "qm" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/cargotech + name = "cargo technician's jumpsuit" + desc = "Shooooorts! They're comfy and easy to wear!" + icon_state = "cargotech" + item_state = "lb_suit" + _color = "cargo" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/chaplain + desc = "It's a black jumpsuit, often worn by religious folk." + name = "chaplain's jumpsuit" + icon_state = "chaplain" + item_state = "bl_suit" + _color = "chapblack" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/chef + desc = "It's an apron which is given only to the most hardcore chefs in space." + name = "chef's uniform" + icon_state = "chef" + _color = "chef" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/clown + name = "clown suit" + desc = "'HONK!'" + icon_state = "clown" + item_state = "clown" + _color = "clown" + flags = FPRINT | ONESIZEFITSALL + + +/obj/item/clothing/under/rank/head_of_personnel + desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"." + name = "head of personnel's jumpsuit" + icon_state = "hop" + item_state = "b_suit" + _color = "hop" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/hydroponics + desc = "It's a jumpsuit designed to protect against minor plant-related hazards." + name = "hydroponicist's jumpsuit" + icon_state = "hydroponics" + item_state = "g_suit" + _color = "hydroponics" + permeability_coefficient = 0.50 + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/botany + desc = "It's a jumpsuit designed to protect against minor plant-related hazards. For the more garden-minded botanist." + name = "botanist's jumpsuit" + icon_state = "botany" + item_state = "botany" + _color = "botany" + permeability_coefficient = 0.50 + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/beekeeper + desc = "It's a jumpsuit designed to protect against minor plant-related hazards. Hopefully bees will see you as one of them." + name = "beekeeper's jumpsuit" + icon_state = "beekeeper" + item_state = "g_suit" + _color = "beekeeper" + permeability_coefficient = 0.50 + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/gardener + desc = "It's a jumpsuit designed to protect against minor plant-related hazards. For those who value the embelishment of the station." + name = "gardener's jumpsuit" + icon_state = "gardener" + item_state = "g_suit" + _color = "gardener" + permeability_coefficient = 0.50 + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/internalaffairs + desc = "The plain, professional attire of an Internal Affairs Agent. The collar is immaculately starched." + name = "Internal Affairs uniform" + icon_state = "internalaffairs" + item_state = "internalaffairs" + _color = "internalaffairs" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/rank/janitor + desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." + name = "janitor's jumpsuit" + icon_state = "janitor" + _color = "janitor" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/lawyer + desc = "Slick threads." + name = "Lawyer suit" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/lawyer/black + icon_state = "lawyer_black" + item_state = "lawyer_black" + _color = "lawyer_black" + species_fit = list("Vox") + +/obj/item/clothing/under/lawyer/female + icon_state = "black_suit_fem" + item_state = "black_suit_fem" + _color = "black_suit_fem" + species_fit = list("Vox") + +/obj/item/clothing/under/lawyer/red + icon_state = "lawyer_red" + item_state = "lawyer_red" + _color = "lawyer_red" + species_fit = list("Vox") + +/obj/item/clothing/under/lawyer/blue + icon_state = "lawyer_blue" + item_state = "lawyer_blue" + _color = "lawyer_blue" + species_fit = list("Vox") + +/obj/item/clothing/under/lawyer/bluesuit + name = "Blue Suit" + desc = "A classy suit and tie" + icon_state = "bluesuit" + item_state = "bluesuit" + _color = "bluesuit" + species_fit = list("Vox") + +/obj/item/clothing/under/lawyer/purpsuit + name = "Purple Suit" + icon_state = "lawyer_purp" + item_state = "lawyer_purp" + _color = "lawyer_purp" + species_fit = list("Vox") + +/obj/item/clothing/under/lawyer/oldman + name = "Old Man's Suit" + desc = "A classic suit for the older gentleman with built in back support." + icon_state = "oldman" + item_state = "oldman" + _color = "oldman" + species_fit = list("Vox") + + +/obj/item/clothing/under/librarian + name = "sensible suit" + desc = "It's very... sensible." + icon_state = "red_suit" + item_state = "red_suit" + _color = "red_suit" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + +/obj/item/clothing/under/mime + name = "mime's outfit" + desc = "It's not very colourful." + icon_state = "mime" + item_state = "mime" + _color = "mime" + flags = FPRINT | ONESIZEFITSALL + + +/obj/item/clothing/under/rank/miner + desc = "It's a snappy jumpsuit with a sturdy set of overalls. It is very dirty." + name = "shaft miner's jumpsuit" + icon_state = "miner" + item_state = "miner" + _color = "miner" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index cf55e55574d..038a1fd0356 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -1,89 +1,89 @@ -//Contains: Engineering department jumpsuits -/obj/item/clothing/under/rank/chief_engineer - desc = "It's a high visibility jumpsuit given to those engineers insane enough to achieve the rank of \"Chief engineer\". It has minor radiation shielding." - name = "chief engineer's jumpsuit" - icon_state = "chiefengineer" - item_state = "g_suit" - _color = "chief" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/atmospheric_technician - desc = "It's a jumpsuit worn by atmospheric technicians." - name = "atmospheric technician's jumpsuit" - icon_state = "atmos" - item_state = "atmos_suit" - _color = "atmos" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/engineer - desc = "It's an orange high visibility jumpsuit worn by engineers. It has minor radiation shielding." - name = "engineer's jumpsuit" - icon_state = "engine" - item_state = "engi_suit" - _color = "engine" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/maintenance_tech - desc = "It's a blue high visibility jumpsuit worn by maintenance technicians. It has minor radiation shielding." - name = "maintenance technician's jumpsuit" - icon_state = "mainttech" - item_state = "mainttech" - _color = "mainttech" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/engine_tech - desc = "It's a yellow jumpsuit worn by engine technicians. It has minor radiation shielding." - name = "engine technician's jumpsuit" - icon_state = "engine_tech" - item_state = "engine_tech" - _color = "engine_tech" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/electrician - desc = "It's a yellow jumpsuit worn by electricians. It has minor energy shielding." - name = "electrician's jumpsuit" - icon_state = "electrician" - item_state = "electrician" - _color = "electrician" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 10, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/roboticist - desc = "It's a slimming black jumpsuit with reinforced seams; great for industrial work." - name = "roboticist's jumpsuit" - icon_state = "robotics" - item_state = "robotics" - _color = "robotics" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/mechatronic - desc = "It's a lilac-blue jumpsuit with a pink duffel jacket, all the rage for mechatronic engineers." - name = "mechatronic engineer's jumpsuit" - icon_state = "mechatron" - item_state = "mechatron" - _color = "mechatron" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/biomechanical - desc = "It's a slim black jumpsuit with a long white undercoat, perfect for surgery and service." - name = "biomechanical engineer's jumpsuit" - icon_state = "biomech" - item_state = "biomech" - _color = "biomech" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/mechanic - desc = "It's a set of blue and yellow overalls worn by station mechanics. Greaseproof, says the label." - name = "mechanic's overalls" - icon_state = "mechanic" - item_state = "mechanic" - _color = "mechanic" +//Contains: Engineering department jumpsuits +/obj/item/clothing/under/rank/chief_engineer + desc = "It's a high visibility jumpsuit given to those engineers insane enough to achieve the rank of \"Chief engineer\". It has minor radiation shielding." + name = "chief engineer's jumpsuit" + icon_state = "chiefengineer" + item_state = "g_suit" + _color = "chief" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/atmospheric_technician + desc = "It's a jumpsuit worn by atmospheric technicians." + name = "atmospheric technician's jumpsuit" + icon_state = "atmos" + item_state = "atmos_suit" + _color = "atmos" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/engineer + desc = "It's an orange high visibility jumpsuit worn by engineers. It has minor radiation shielding." + name = "engineer's jumpsuit" + icon_state = "engine" + item_state = "engi_suit" + _color = "engine" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/maintenance_tech + desc = "It's a blue high visibility jumpsuit worn by maintenance technicians. It has minor radiation shielding." + name = "maintenance technician's jumpsuit" + icon_state = "mainttech" + item_state = "mainttech" + _color = "mainttech" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/engine_tech + desc = "It's a yellow jumpsuit worn by engine technicians. It has minor radiation shielding." + name = "engine technician's jumpsuit" + icon_state = "engine_tech" + item_state = "engine_tech" + _color = "engine_tech" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/electrician + desc = "It's a yellow jumpsuit worn by electricians. It has minor energy shielding." + name = "electrician's jumpsuit" + icon_state = "electrician" + item_state = "electrician" + _color = "electrician" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 10, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/roboticist + desc = "It's a slimming black jumpsuit with reinforced seams; great for industrial work." + name = "roboticist's jumpsuit" + icon_state = "robotics" + item_state = "robotics" + _color = "robotics" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/mechatronic + desc = "It's a lilac-blue jumpsuit with a pink duffel jacket, all the rage for mechatronic engineers." + name = "mechatronic engineer's jumpsuit" + icon_state = "mechatron" + item_state = "mechatron" + _color = "mechatron" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/biomechanical + desc = "It's a slim black jumpsuit with a long white undercoat, perfect for surgery and service." + name = "biomechanical engineer's jumpsuit" + icon_state = "biomech" + item_state = "biomech" + _color = "biomech" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/mechanic + desc = "It's a set of blue and yellow overalls worn by station mechanics. Greaseproof, says the label." + name = "mechanic's overalls" + icon_state = "mechanic" + item_state = "mechanic" + _color = "mechanic" flags = FPRINT | ONESIZEFITSALL \ No newline at end of file diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm index 2fb02eadc7d..07f8611dd13 100644 --- a/code/modules/clothing/under/jobs/medsci.dm +++ b/code/modules/clothing/under/jobs/medsci.dm @@ -1,242 +1,242 @@ -/* - * Science - */ -/obj/item/clothing/under/rank/research_director - desc = "It's a jumpsuit worn by those with the know-how to achieve the position of \"Research Director\". Its fabric provides minor protection from biological contaminants." - name = "research director's jumpsuit" - icon_state = "director" - item_state = "g_suit" - _color = "director" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/scientist - desc = "It's made of a special fiber that provides minor protection against bombs. It has markings that denote the wearer as a scientist." - name = "scientist's jumpsuit" - icon_state = "toxins" - item_state = "w_suit" - _color = "toxinswhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/chemist - desc = "It's made of a special fiber that gives special protection against biohazards. It has a chemist rank stripe on it." - name = "chemist's jumpsuit" - icon_state = "chemistry" - item_state = "w_suit" - _color = "chemistrywhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT - species_fit = list("Vox") - -/obj/item/clothing/under/rank/pharma - desc = "It's made of a special fiber that gives special protection against biohazards. It has a pharmacist rank stripe on it." - name = "pharmacist's jumpsuit" - icon_state = "pharma" - item_state = "pharma" - _color = "pharma" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/xenoarch - desc = "It's made of a special fiber that provides minor protection against radiation. It has markings that denote the wearer as a xenoarcheologist." - name = "xenoarcheologist's jumpsuit" - icon_state = "xenoarch" - item_state = "xenoarch" - _color = "xenoarch" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/plasmares - desc = "It's made of a special fiber that provides minor protection against bombs. It has markings that denote the wearer as a plasma researcher." - name = "plasma researcher's jumpsuit" - icon_state = "plasmares" - item_state = "plasmares" - _color = "plasmares" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/xenobio - desc = "It's made of a special fiber that provides minor protection against biohazards. It has markings that denote the wearer as a xenobiologist." - name = "xenobiologist's jumpsuit" - icon_state = "xenobio" - item_state = "xenobio" - _color = "xenobio" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/rank/anomalist - desc = "It's made of a special fiber that provides minor protection against radiation. It has markings that denote the wearer as an anomalist." - name = "anomalist's jumpsuit" - icon_state = "anomalist" - item_state = "anomalist" - _color = "anomalist" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = FPRINT | ONESIZEFITSALL - -/* - * Medical - */ -/obj/item/clothing/under/rank/chief_medical_officer - desc = "It's a jumpsuit worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection." - name = "chief medical officer's jumpsuit" - icon_state = "cmo" - item_state = "w_suit" - _color = "cmo" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/geneticist - desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it." - name = "geneticist's jumpsuit" - icon_state = "genetics" - item_state = "w_suit" - _color = "geneticswhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/virologist - desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it." - name = "virologist's jumpsuit" - icon_state = "virology" - item_state = "w_suit" - _color = "virologywhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/nursesuit - desc = "It's a jumpsuit commonly worn by nursing staff in the medical department." - name = "nurse's suit" - icon_state = "nursesuit" - item_state = "nursesuit" - _color = "nursesuit" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/nurse - desc = "A dress commonly worn by the nursing staff in the medical department." - name = "nurse's dress" - icon_state = "nurse" - item_state = "nurse" - _color = "nurse" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/orderly - desc = "A white suit to be worn by orderly people who love orderly things." - name = "orderly's uniform" - icon_state = "orderly" - item_state = "orderly" - _color = "orderly" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/medical - desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel." - name = "medical doctor's jumpsuit" - icon_state = "medical" - item_state = "w_suit" - _color = "medical" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/medical/blue - name = "medical scrubs" - desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue." - icon_state = "scrubsblue" - _color = "scrubsblue" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/medical/green - name = "medical scrubs" - desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green." - icon_state = "scrubsgreen" - _color = "scrubsgreen" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -/obj/item/clothing/under/rank/medical/purple - name = "medical scrubs" - desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple." - icon_state = "scrubspurple" - _color = "scrubspurple" - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - -//paramedic -/obj/item/clothing/under/rank/medical/paramedic - desc = "It's made of a special fiber that provides minor protection against biohazards and radiation. It has a cross on the chest denoting that the wearer is trained medical personnel." - name = "paramedic's jumpsuit" - icon_state = "paramedic" - item_state = "paramedic" - _color = "paramedic" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 10) - flags = FPRINT | ONESIZEFITSALL - species_fit = list("Vox") - - - - -/* - * Medsci, unused (i think) stuff - */ -/obj/item/clothing/under/rank/geneticist_new - desc = "It's made of a special fiber which provides minor protection against biohazards." - name = "geneticist's jumpsuit" - icon_state = "genetics_new" - item_state = "w_suit" - _color = "genetics_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - -/obj/item/clothing/under/rank/chemist_new - desc = "It's made of a special fiber which provides minor protection against biohazards." - name = "chemist's jumpsuit" - icon_state = "chemist_new" - item_state = "w_suit" - _color = "chemist_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - -/obj/item/clothing/under/rank/scientist_new - desc = "Made of a special fiber that gives special protection against biohazards and small explosions." - name = "scientist's jumpsuit" - icon_state = "scientist_new" - item_state = "w_suit" - _color = "scientist_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) - -/obj/item/clothing/under/rank/virologist_new - desc = "Made of a special fiber that gives increased protection against biohazards." - name = "virologist's jumpsuit" - icon_state = "virologist_new" - item_state = "w_suit" - _color = "virologist_new" - permeability_coefficient = 0.50 +/* + * Science + */ +/obj/item/clothing/under/rank/research_director + desc = "It's a jumpsuit worn by those with the know-how to achieve the position of \"Research Director\". Its fabric provides minor protection from biological contaminants." + name = "research director's jumpsuit" + icon_state = "director" + item_state = "g_suit" + _color = "director" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/scientist + desc = "It's made of a special fiber that provides minor protection against bombs. It has markings that denote the wearer as a scientist." + name = "scientist's jumpsuit" + icon_state = "toxins" + item_state = "w_suit" + _color = "toxinswhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/chemist + desc = "It's made of a special fiber that gives special protection against biohazards. It has a chemist rank stripe on it." + name = "chemist's jumpsuit" + icon_state = "chemistry" + item_state = "w_suit" + _color = "chemistrywhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT + species_fit = list("Vox") + +/obj/item/clothing/under/rank/pharma + desc = "It's made of a special fiber that gives special protection against biohazards. It has a pharmacist rank stripe on it." + name = "pharmacist's jumpsuit" + icon_state = "pharma" + item_state = "pharma" + _color = "pharma" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/xenoarch + desc = "It's made of a special fiber that provides minor protection against radiation. It has markings that denote the wearer as a xenoarcheologist." + name = "xenoarcheologist's jumpsuit" + icon_state = "xenoarch" + item_state = "xenoarch" + _color = "xenoarch" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/plasmares + desc = "It's made of a special fiber that provides minor protection against bombs. It has markings that denote the wearer as a plasma researcher." + name = "plasma researcher's jumpsuit" + icon_state = "plasmares" + item_state = "plasmares" + _color = "plasmares" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/xenobio + desc = "It's made of a special fiber that provides minor protection against biohazards. It has markings that denote the wearer as a xenobiologist." + name = "xenobiologist's jumpsuit" + icon_state = "xenobio" + item_state = "xenobio" + _color = "xenobio" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/rank/anomalist + desc = "It's made of a special fiber that provides minor protection against radiation. It has markings that denote the wearer as an anomalist." + name = "anomalist's jumpsuit" + icon_state = "anomalist" + item_state = "anomalist" + _color = "anomalist" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = FPRINT | ONESIZEFITSALL + +/* + * Medical + */ +/obj/item/clothing/under/rank/chief_medical_officer + desc = "It's a jumpsuit worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection." + name = "chief medical officer's jumpsuit" + icon_state = "cmo" + item_state = "w_suit" + _color = "cmo" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/geneticist + desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it." + name = "geneticist's jumpsuit" + icon_state = "genetics" + item_state = "w_suit" + _color = "geneticswhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/virologist + desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it." + name = "virologist's jumpsuit" + icon_state = "virology" + item_state = "w_suit" + _color = "virologywhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/nursesuit + desc = "It's a jumpsuit commonly worn by nursing staff in the medical department." + name = "nurse's suit" + icon_state = "nursesuit" + item_state = "nursesuit" + _color = "nursesuit" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/nurse + desc = "A dress commonly worn by the nursing staff in the medical department." + name = "nurse's dress" + icon_state = "nurse" + item_state = "nurse" + _color = "nurse" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/orderly + desc = "A white suit to be worn by orderly people who love orderly things." + name = "orderly's uniform" + icon_state = "orderly" + item_state = "orderly" + _color = "orderly" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/medical + desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel." + name = "medical doctor's jumpsuit" + icon_state = "medical" + item_state = "w_suit" + _color = "medical" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/medical/blue + name = "medical scrubs" + desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue." + icon_state = "scrubsblue" + _color = "scrubsblue" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/medical/green + name = "medical scrubs" + desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green." + icon_state = "scrubsgreen" + _color = "scrubsgreen" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +/obj/item/clothing/under/rank/medical/purple + name = "medical scrubs" + desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple." + icon_state = "scrubspurple" + _color = "scrubspurple" + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + +//paramedic +/obj/item/clothing/under/rank/medical/paramedic + desc = "It's made of a special fiber that provides minor protection against biohazards and radiation. It has a cross on the chest denoting that the wearer is trained medical personnel." + name = "paramedic's jumpsuit" + icon_state = "paramedic" + item_state = "paramedic" + _color = "paramedic" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 10) + flags = FPRINT | ONESIZEFITSALL + species_fit = list("Vox") + + + + +/* + * Medsci, unused (i think) stuff + */ +/obj/item/clothing/under/rank/geneticist_new + desc = "It's made of a special fiber which provides minor protection against biohazards." + name = "geneticist's jumpsuit" + icon_state = "genetics_new" + item_state = "w_suit" + _color = "genetics_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + +/obj/item/clothing/under/rank/chemist_new + desc = "It's made of a special fiber which provides minor protection against biohazards." + name = "chemist's jumpsuit" + icon_state = "chemist_new" + item_state = "w_suit" + _color = "chemist_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + +/obj/item/clothing/under/rank/scientist_new + desc = "Made of a special fiber that gives special protection against biohazards and small explosions." + name = "scientist's jumpsuit" + icon_state = "scientist_new" + item_state = "w_suit" + _color = "scientist_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) + +/obj/item/clothing/under/rank/virologist_new + desc = "Made of a special fiber that gives increased protection against biohazards." + name = "virologist's jumpsuit" + icon_state = "virologist_new" + item_state = "w_suit" + _color = "virologist_new" + permeability_coefficient = 0.50 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) \ No newline at end of file diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 68a519ad8da..32fe6aed4fd 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -1,141 +1,141 @@ -/* - * Contains: - * Security - * Detective - * Head of Security - */ - -/* - * Security - */ -/obj/item/clothing/under/rank/warden - desc = "It's made of a slightly sturdier material than standard jumpsuits, to allow for more robust protection. It has the word \"Warden\" written on the shoulders." - name = "warden's jumpsuit" - icon_state = "warden" - item_state = "r_suit" - _color = "warden" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - siemens_coefficient = 0.9 - species_fit = list("Vox") - -/obj/item/clothing/under/rank/security - name = "security officer's jumpsuit" - desc = "It's made of a slightly sturdier material than standard jumpsuits, to allow for robust protection." - icon_state = "security" - item_state = "r_suit" - _color = "secred" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - siemens_coefficient = 0.9 - species_fit = list("Vox") - -/obj/item/clothing/under/rank/security/sneaksuit - name = "sneaking suit" - desc = "It's made of a slightly sturdier material developed by the Soviet Union centuries ago, allows for robust protection." - icon_state = "sneakingsuit" - item_state = "sneakingsuit" - _color = "sneakingsuit" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/metalgear.dmi', "right_hand" = 'icons/mob/in-hand/right/metalgear.dmi') - -/obj/item/clothing/under/rank/dispatch - name = "dispatcher's uniform" - desc = "A dress shirt and khakis with a security patch sewn on." - icon_state = "dispatch" - item_state = "dispatch" - _color = "dispatch" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - siemens_coefficient = 0.9 - -/obj/item/clothing/under/rank/security2 - name = "security officer's uniform" - desc = "It's made of a slightly sturdier material, to allow for robust protection." - icon_state = "redshirt2" - item_state = "r_suit" - _color = "redshirt2" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - siemens_coefficient = 0.9 - -/* - * Detective - */ -/obj/item/clothing/under/det - name = "hard-worn suit" - desc = "Someone who wears this means business." - icon_state = "detective" - item_state = "det" - _color = "detective" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - siemens_coefficient = 0.9 - - -/obj/item/clothing/head/det_hat - name = "hat" - desc = "Someone who wears this will look very smart." - icon_state = "detective" - allowed = list(/obj/item/weapon/reagent_containers/food/snacks/candy_corn, /obj/item/weapon/pen) - armor = list(melee = 50, bullet = 5, laser = 25,energy = 10, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.9 - -/* - * Head of Security - */ -/obj/item/clothing/under/rank/head_of_security - desc = "It's a jumpsuit worn by those few with the dedication to achieve the position of \"Head of Security\". It has additional armor to protect the wearer." - name = "head of security's jumpsuit" - icon_state = "hos" - item_state = "r_suit" - _color = "hosred" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = FPRINT | ONESIZEFITSALL - siemens_coefficient = 0.8 - species_fit = list("Vox") - - -/obj/item/clothing/head/helmet/HoS - name = "Head of Security Hat" - desc = "The hat of the Head of Security. For showing the officers who's in charge." - icon_state = "hoscap" - flags = FPRINT - armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) - flags_inv = HIDEEARS - siemens_coefficient = 0.8 - - -/obj/item/clothing/suit/armor/hos - name = "armored coat" - desc = "A greatcoat enchanced with a special alloy for some protection and style." - icon_state = "hos" - item_state = "hos" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - armor = list(melee = 65, bullet = 30, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0.6 - - -/obj/item/clothing/head/helmet/HoS/dermal - name = "Dermal Armour Patch" - desc = "You're not quite sure how you manage to take it on and off, but it implants nicely in your head." - icon_state = "dermal" - item_state = "dermal" - siemens_coefficient = 0.6 - -//Jensen cosplay gear -/obj/item/clothing/under/rank/head_of_security/jensen - desc = "You never asked for anything that stylish." - name = "head of security's jumpsuit" - icon_state = "jensen" - item_state = "jensensuit" - _color = "jensen" - siemens_coefficient = 0.6 - -/obj/item/clothing/suit/armor/hos/jensen - name = "armored trenchcoat" - desc = "A trenchcoat augmented with a special alloy for some protection and style." - icon_state = "jensencoat" - item_state = "jensencoat" - flags_inv = 0 +/* + * Contains: + * Security + * Detective + * Head of Security + */ + +/* + * Security + */ +/obj/item/clothing/under/rank/warden + desc = "It's made of a slightly sturdier material than standard jumpsuits, to allow for more robust protection. It has the word \"Warden\" written on the shoulders." + name = "warden's jumpsuit" + icon_state = "warden" + item_state = "r_suit" + _color = "warden" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + siemens_coefficient = 0.9 + species_fit = list("Vox") + +/obj/item/clothing/under/rank/security + name = "security officer's jumpsuit" + desc = "It's made of a slightly sturdier material than standard jumpsuits, to allow for robust protection." + icon_state = "security" + item_state = "r_suit" + _color = "secred" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + siemens_coefficient = 0.9 + species_fit = list("Vox") + +/obj/item/clothing/under/rank/security/sneaksuit + name = "sneaking suit" + desc = "It's made of a slightly sturdier material developed by the Soviet Union centuries ago, allows for robust protection." + icon_state = "sneakingsuit" + item_state = "sneakingsuit" + _color = "sneakingsuit" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/metalgear.dmi', "right_hand" = 'icons/mob/in-hand/right/metalgear.dmi') + +/obj/item/clothing/under/rank/dispatch + name = "dispatcher's uniform" + desc = "A dress shirt and khakis with a security patch sewn on." + icon_state = "dispatch" + item_state = "dispatch" + _color = "dispatch" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + siemens_coefficient = 0.9 + +/obj/item/clothing/under/rank/security2 + name = "security officer's uniform" + desc = "It's made of a slightly sturdier material, to allow for robust protection." + icon_state = "redshirt2" + item_state = "r_suit" + _color = "redshirt2" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + siemens_coefficient = 0.9 + +/* + * Detective + */ +/obj/item/clothing/under/det + name = "hard-worn suit" + desc = "Someone who wears this means business." + icon_state = "detective" + item_state = "det" + _color = "detective" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + siemens_coefficient = 0.9 + + +/obj/item/clothing/head/det_hat + name = "hat" + desc = "Someone who wears this will look very smart." + icon_state = "detective" + allowed = list(/obj/item/weapon/reagent_containers/food/snacks/candy_corn, /obj/item/weapon/pen) + armor = list(melee = 50, bullet = 5, laser = 25,energy = 10, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.9 + +/* + * Head of Security + */ +/obj/item/clothing/under/rank/head_of_security + desc = "It's a jumpsuit worn by those few with the dedication to achieve the position of \"Head of Security\". It has additional armor to protect the wearer." + name = "head of security's jumpsuit" + icon_state = "hos" + item_state = "r_suit" + _color = "hosred" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = FPRINT | ONESIZEFITSALL + siemens_coefficient = 0.8 + species_fit = list("Vox") + + +/obj/item/clothing/head/helmet/HoS + name = "Head of Security Hat" + desc = "The hat of the Head of Security. For showing the officers who's in charge." + icon_state = "hoscap" + flags = FPRINT + armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) + flags_inv = HIDEEARS + siemens_coefficient = 0.8 + + +/obj/item/clothing/suit/armor/hos + name = "armored coat" + desc = "A greatcoat enchanced with a special alloy for some protection and style." + icon_state = "hos" + item_state = "hos" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + armor = list(melee = 65, bullet = 30, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0.6 + + +/obj/item/clothing/head/helmet/HoS/dermal + name = "Dermal Armour Patch" + desc = "You're not quite sure how you manage to take it on and off, but it implants nicely in your head." + icon_state = "dermal" + item_state = "dermal" + siemens_coefficient = 0.6 + +//Jensen cosplay gear +/obj/item/clothing/under/rank/head_of_security/jensen + desc = "You never asked for anything that stylish." + name = "head of security's jumpsuit" + icon_state = "jensen" + item_state = "jensensuit" + _color = "jensen" + siemens_coefficient = 0.6 + +/obj/item/clothing/suit/armor/hos/jensen + name = "armored trenchcoat" + desc = "A trenchcoat augmented with a special alloy for some protection and style." + icon_state = "jensencoat" + item_state = "jensencoat" + flags_inv = 0 siemens_coefficient = 0.6 \ No newline at end of file diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 70d1debe15f..c5e1977558e 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -1,584 +1,584 @@ -/obj/item/clothing/under/pj/red - name = "red pj's" - desc = "Sleepwear." - icon_state = "red_pyjamas" - _color = "red_pyjamas" - item_state = "w_suit" - -/obj/item/clothing/under/pj/blue - name = "blue pj's" - desc = "Sleepwear." - icon_state = "blue_pyjamas" - _color = "blue_pyjamas" - item_state = "w_suit" - -/obj/item/clothing/under/captain_fly - name = "rogue captains uniform" - desc = "For the man who doesn't care because he's still free." - icon_state = "captain_fly" - item_state = "captain_fly" - _color = "captain_fly" - -/obj/item/clothing/under/scratch - name = "white suit" - desc = "A white suit, suitable for an excellent host" - icon_state = "scratch" - item_state = "scratch" - _color = "scratch" - -/obj/item/clothing/under/sl_suit - desc = "It's a very amish looking suit." - name = "amish suit" - icon_state = "sl_suit" - _color = "sl_suit" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/waiter - name = "waiter's outfit" - desc = "It's a very smart uniform with a special pocket for tip." - icon_state = "waiter" - item_state = "waiter" - _color = "waiter" - flags = FPRINT - -/obj/item/clothing/under/rank/mailman - name = "mailman's jumpsuit" - desc = "'Special delivery!'" - icon_state = "mailman" - item_state = "b_suit" - _color = "mailman" - -/obj/item/clothing/under/sexyclown - name = "sexy-clown suit" - desc = "It makes you look HONKable!" - icon_state = "sexyclown" - item_state = "sexyclown" - _color = "sexyclown" - -/obj/item/clothing/under/rank/vice - name = "vice officer's jumpsuit" - desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision." - icon_state = "vice" - item_state = "gy_suit" - _color = "vice" - -/obj/item/clothing/under/rank/centcom_officer - desc = "It's a jumpsuit worn by CentCom Officers." - name = "\improper CentCom officer's jumpsuit" - icon_state = "officer" - item_state = "g_suit" - _color = "officer" - -/obj/item/clothing/under/rank/centcom_commander - desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders." - name = "\improper CentCom officer's jumpsuit" - icon_state = "centcom" - item_state = "dg_suit" - _color = "centcom" - -/obj/item/clothing/under/space - name = "\improper NASA jumpsuit" - desc = "It has a NASA logo on it and is made of space-proofed materials." - icon_state = "black" - item_state = "bl_suit" - _color = "black" - w_class = 4//bulky item - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.02 - flags = FPRINT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected. - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - -/obj/item/clothing/under/acj - name = "administrative cybernetic jumpsuit" - icon_state = "syndicate" - item_state = "bl_suit" - _color = "syndicate" - desc = "it's a cybernetically enhanced jumpsuit used for administrative duties." - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - flags = FPRINT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - armor = list(melee = 100, bullet = 100, laser = 100,energy = 100, bomb = 100, bio = 100, rad = 100) - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0 - -/obj/item/clothing/under/owl - name = "owl uniform" - desc = "A jumpsuit with owl wings. Photorealistic owl feathers! Twooooo!" - icon_state = "owl" - _color = "owl" - flags = FPRINT | ONESIZEFITSALL - -/obj/item/clothing/under/johnny - name = "johnny~~ jumpsuit" - desc = "Johnny~~" - icon_state = "johnny" - _color = "johnny" - -/obj/item/clothing/under/rainbow - name = "rainbow jumpsuit" - desc = "A fabulous jumpsuit." - icon_state = "rainbow" - item_state = "rainbow" - _color = "rainbow" - -/obj/item/clothing/under/cloud - name = "cloud" - desc = "cloud" - icon_state = "cloud" - _color = "cloud" - -/obj/item/clothing/under/psysuit - name = "dark undersuit" - desc = "A thick, layered grey undersuit lined with power cables. Feels a little like wearing an electrical storm." - icon_state = "psysuit" - item_state = "psysuit" - _color = "psysuit" - -/obj/item/clothing/under/gimmick/rank/captain/suit - name = "captain's suit" - desc = "A green suit and yellow necktie. Exemplifies authority." - icon_state = "green_suit" - item_state = "dg_suit" - _color = "green_suit" - -/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit - name = "head of personnel's suit" - desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble." - icon_state = "teal_suit" - item_state = "g_suit" - _color = "teal_suit" - -/obj/item/clothing/under/suit_jacket - name = "black suit" - desc = "A black suit and red tie. Very formal." - icon_state = "black_suit" - item_state = "bl_suit" - _color = "black_suit" - -/obj/item/clothing/under/suit_jacket/really_black - name = "executive suit" - desc = "A formal black suit and red tie, intended for the station's finest." - icon_state = "really_black_suit" - item_state = "bl_suit" - _color = "black_suit" - -/obj/item/clothing/under/suit_jacket/female - name = "executive suit" - desc = "A formal trouser suit for women, intended for the station's finest." - icon_state = "black_suit_fem" - item_state = "black_suit_fem" - _color = "black_suit_fem" - -/obj/item/clothing/under/suit_jacket/red - name = "red suit" - desc = "A red suit and blue tie. Somewhat formal." - icon_state = "red_suit" - item_state = "r_suit" - _color = "red_suit" - species_fit = list("Vox") - -/obj/item/clothing/under/blackskirt - name = "black skirt" - desc = "A black skirt, very fancy!" - icon_state = "blackskirt" - _color = "blackskirt" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/schoolgirl - name = "schoolgirl uniform" - desc = "It's just like one of my Japanese animes!" - icon_state = "schoolgirl" - item_state = "schoolgirl" - _color = "schoolgirl" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/overalls - name = "laborer's overalls" - desc = "A set of durable overalls for getting the job done." - icon_state = "overalls" - item_state = "lb_suit" - _color = "overalls" - gender = PLURAL - -/obj/item/clothing/under/pirate - name = "pirate outfit" - desc = "Yarr." - icon_state = "pirate" - item_state = "pirate" - _color = "pirate" - species_fit = list("Vox") - -/obj/item/clothing/under/soviet - name = "soviet uniform" - desc = "For the Motherland!" - icon_state = "soviet" - item_state = "soviet" - _color = "soviet" - -/obj/item/clothing/under/redcoat - name = "redcoat uniform" - desc = "Looks old." - icon_state = "redcoat" - item_state = "redcoat" - _color = "redcoat" - -/obj/item/clothing/under/kilt - name = "kilt" - desc = "Includes shoes and plaid" - icon_state = "kilt" - item_state = "kilt" - _color = "kilt" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|FEET - -/obj/item/clothing/under/sexymime - name = "sexy mime outfit" - desc = "The only time when you DON'T enjoy looking at someone's rack." - icon_state = "sexymime" - item_state = "sexymime" - _color = "sexymime" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/obj/item/clothing/under/gladiator - name = "gladiator uniform" - desc = "Are you not entertained? Is that not why you are here?" - icon_state = "gladiator" - item_state = "gladiator" - _color = "gladiator" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -//dress - -/obj/item/clothing/under/dress/dress_fire - name = "flame dress" - desc = "A small black dress with blue flames print on it." - icon_state = "dress_fire" - _color = "dress_fire" - -/obj/item/clothing/under/dress/dress_green - name = "green dress" - desc = "A simple, tight fitting green dress." - icon_state = "dress_green" - _color = "dress_green" - -/obj/item/clothing/under/dress/dress_orange - name = "orange dress" - desc = "A fancy orange gown for those who like to show leg." - icon_state = "dress_orange" - _color = "dress_orange" - -/obj/item/clothing/under/dress/dress_pink - name = "pink dress" - desc = "A simple, tight fitting pink dress." - icon_state = "dress_pink" - _color = "dress_pink" - -/obj/item/clothing/under/dress/dress_yellow - name = "yellow dress" - desc = "A flirty, little yellow dress." - icon_state = "dress_yellow" - _color = "dress_yellow" - -/obj/item/clothing/under/dress/dress_saloon - name = "saloon girl dress" - desc = "A old western inspired gown for the girl who likes to drink." - icon_state = "dress_saloon" - _color = "dress_saloon" - -/obj/item/clothing/under/dress/dress_rd - name = "research director dress uniform" - desc = "Feminine fashion for the style concious RD." - icon_state = "dress_rd" - _color = "dress_rd" - -/obj/item/clothing/under/dress/dress_cap - name = "captain dress uniform" - desc = "Feminine fashion for the style concious captain." - icon_state = "dress_cap" - _color = "dress_cap" - -/obj/item/clothing/under/dress/dress_hop - name = "head of personal dress uniform" - desc = "Feminine fashion for the style concious HoP." - icon_state = "dress_hop" - _color = "dress_hop" - -/obj/item/clothing/under/dress/dress_hr - name = "human resources director uniform" - desc = "Superior class for the nosy H.R. Director." - icon_state = "huresource" - _color = "huresource" - -/obj/item/clothing/under/dress/plaid_blue - name = "blue plaid skirt" - desc = "A preppy blue skirt with a white blouse." - icon_state = "plaid_blue" - _color = "plaid_blue" - -/obj/item/clothing/under/dress/plaid_red - name = "red plaid skirt" - desc = "A preppy red skirt with a white blouse." - icon_state = "plaid_red" - _color = "plaid_red" - -/obj/item/clothing/under/dress/plaid_purple - name = "blue purple skirt" - desc = "A preppy purple skirt with a white blouse." - icon_state = "plaid_purple" - _color = "plaid_purple" - -//wedding stuff - -/obj/item/clothing/under/wedding/bride_orange - name = "orange wedding dress" - desc = "A big and puffy orange dress." - icon_state = "bride_orange" - _color = "bride_orange" - flags_inv = HIDESHOES - -/obj/item/clothing/under/wedding/bride_purple - name = "purple wedding dress" - desc = "A big and puffy purple dress." - icon_state = "bride_purple" - _color = "bride_purple" - flags_inv = HIDESHOES - -/obj/item/clothing/under/wedding/bride_blue - name = "blue wedding dress" - desc = "A big and puffy blue dress." - icon_state = "bride_blue" - _color = "bride_blue" - flags_inv = HIDESHOES - -/obj/item/clothing/under/wedding/bride_red - name = "red wedding dress" - desc = "A big and puffy red dress." - icon_state = "bride_red" - _color = "bride_red" - flags_inv = HIDESHOES - -/obj/item/clothing/under/wedding/bride_white - name = "white wedding dress" - desc = "A white wedding gown made from the finest silk." - icon_state = "bride_white" - _color = "bride_white" - flags_inv = HIDESHOES - -/obj/item/clothing/under/sundress - name = "sundress" - desc = "Makes you want to frolic in a field of daisies." - icon_state = "sundress" - item_state = "sundress" - _color = "sundress" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/obj/item/clothing/under/roman - name = "roman armor" - desc = "An ancient Roman armor. Made of metallic strips and leather straps." - icon_state = "roman" - _color = "roman" - item_state = "armor" - armor = list(melee = 25, bullet = 0, laser = 25, energy = 10, bomb = 10, bio = 0, rad = 0) - -/obj/item/clothing/under/simonpants - name = "Simon's Pants" - desc = "Simon's pants, clad with belt and whatever the fuck that thing is around his neck" - icon_state = "spants" - _color = "simonpants" - item_state = "spants" - species_fit = list("Vox") - gender = PLURAL - -/obj/item/clothing/under/batmansuit - name = "batsuit" - desc = "You are the night." - icon_state = "bmuniform" - _color = "bmuniform" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/obj/item/clothing/under/officeruniform - name = "officer's uniform" - desc = "Bestraft die Juden fur ihre Verbrechen." - icon_state = "officeruniform" - item_state = "officeruniform" - _color = "officeruniform" - -/obj/item/clothing/under/soldieruniform - name = "soldier's uniform" - desc = "Bestraft die Verbundeten fur ihren Widerstand." - icon_state = "soldieruniform" - item_state = "soldieruniform" - _color = "soldieruniform" - -/obj/item/clothing/under/squatter_outfit - name = "slav squatter tracksuit" - desc = "Cyka blyat." - icon_state = "squatteroutfit" - item_state = "squatteroutfit" - _color = "squatteroutfit" - -/obj/item/clothing/under/russobluecamooutfit - name = "russian blue camo" - desc = "Drop and give me dvadtsat!" - icon_state = "russobluecamo" - item_state = "russobluecamo" - _color = "russobluecamo" - -/obj/item/clothing/under/jester - name = "jester duit" - desc = "Only a fool would wear such a suit." - icon_state = "jester" - item_state = "jester" - _color = "jester" - -/obj/item/clothing/under/stilsuit - name = "stillsuit" - desc = "Designed to preserve bodymoisture." - icon_state = "stilsuit" - item_state = "stilsuit" - _color = "stilsuit" - -/obj/item/clothing/under/aviatoruniform - name = "aviator uniform" - desc = "Now you can look absolutely dashing!" - icon_state = "aviator_uniform" - item_state = "aviator_uniform" - _color = "aviator_uniform" - species_restricted = list("exclude","Vox") - -/obj/item/clothing/under/libertyshirt - name = "liberty shirt" - desc = "For any freedom loving patriot out there" - icon_state = "libertyshirt" - item_state = "libertyshirt" - _color = "libertyshirt" - -/obj/item/clothing/under/bikersuit - name = "biker's outfit" - icon_state = "biker" - item_state = "biker" - _color = "biker" - -/obj/item/clothing/under/jacketsuit - name = "richard's outfit" - desc = "Do you know what time it is?" - icon_state = "jacket" - item_state = "jacket" - _color = "jacket" - -/obj/item/clothing/under/mega - name = "\improper DRN-001 suit" - desc = "The original. Simple, yet very adaptable." - icon_state = "mega" - item_state = "mega" - _color = "mega" - -/obj/item/clothing/under/proto - name = "The Prototype Suit" - desc = "Even robots know scarves are the perfect accessory for a brooding rival." - icon_state = "proto" - item_state = "proto" - _color = "proto" - -/obj/item/clothing/under/megax - name = "\improper Maverick Hunter regalia" - desc = "The best outfit for taking out rogue borgs." - icon_state = "megax" - item_state = "megax" - _color = "megax" - -/obj/item/clothing/under/joe - name = "The Sniper Suit" - desc = "Mass produced combat robots with a rather unfitting name." - icon_state = "joe" - item_state = "joe" - _color = "joe" - -/obj/item/clothing/under/roll - name = "\improper DRN-002 Dress" - desc = "A simple red dress, the good doctor's second robot wasn't quite as exciting as the first." - icon_state = "roll" - item_state = "roll" - _color = "roll" - -/obj/item/clothing/under/maid - name = "maid outfit" - desc = "Perfect for lusty aliens and desperate weeaboos." - icon_state = "maid" - item_state = "maid" - _color = "maid" - -/obj/item/clothing/under/darkholme - name = "\improper The Darkholme" - desc = "Fuck you." - icon_state = "darkholme" - item_state = "darkholme" - _color = "darkholme" - -/obj/item/clothing/under/gokugidown - name = "turtle hermit undershirt" - desc = "Something seems oddly familiar about this outfit..." - icon_state = "gokugidown" - item_state = "gokugidown" - _color = "gokugidown" - -/obj/item/clothing/under/gokugi - name = "turtle hermit outfit" - desc = "An outfit from one trained by the great Turtle Hermit" - icon_state = "gokugi" - item_state = "gokugi" - _color = "gokugi" - -/obj/item/clothing/under/doomguy - name = "\improper Doomguy's pants" - desc = "" - icon_state = "doom" - item_state = "doom" - _color = "doom" - -/obj/item/clothing/under/vault13 - name = "vault 13 Jumpsuit" - desc = "Oddly similar to the station's usual jumpsuits, but with a rustic charm to it. Has a large thirteen emblazened on the back" - icon_state = "v13-jumpsuit" - item_state = "v13-jumpsuit" - _color = "v13-jumpsuit" - -/obj/item/clothing/under/vault - name = "vault jumpsuit" - desc = "Oddly similar to the station's usual jumpsuits, but with a rustic charm to it." - icon_state = "v-jumpsuit" - item_state = "v-jumpsuit" - _color = "v-jumpsuit" - -/obj/item/clothing/under/contortionist - name = "contortionist's jumpsuit" - desc = "A light jumpsuit useful for squeezing through narrow vents." - icon_state = "darkholme" - item_state = "darkholme" - _color = "darkholme" - -/obj/item/clothing/under/contortionist/proc/check_clothing(mob/user as mob) - //Allowed to wear: glasses, shoes, gloves, pockets, mask, and jumpsuit (obviously) - var/list/slot_must_be_empty = list(slot_back,slot_handcuffed,slot_legcuffed,slot_l_hand,slot_r_hand,slot_belt,slot_head,slot_wear_suit) - for(var/slot_id in slot_must_be_empty) - if(user.get_item_by_slot(slot_id)) - to_chat(user, "You can't fit inside while wearing that \the [user.get_item_by_slot(slot_id)].") - return 0 - return 1 - -/obj/item/clothing/under/clownpiece - name = "Clownpiece's Pierrot suit" - desc = "A female-sized set of leggings and shirt with a pattern similar to the American flag, featuring a frilled collar." - icon_state = "clownpiece" - item_state = "clownpiece" - _color = "clownpiece" - -/obj/item/clothing/under/cia - name = "casual IAA outfit" - desc = "Just looking at this makes you feel in charge." - icon_state = "cia" - item_state = "cia" - _color = "cia" +/obj/item/clothing/under/pj/red + name = "red pj's" + desc = "Sleepwear." + icon_state = "red_pyjamas" + _color = "red_pyjamas" + item_state = "w_suit" + +/obj/item/clothing/under/pj/blue + name = "blue pj's" + desc = "Sleepwear." + icon_state = "blue_pyjamas" + _color = "blue_pyjamas" + item_state = "w_suit" + +/obj/item/clothing/under/captain_fly + name = "rogue captains uniform" + desc = "For the man who doesn't care because he's still free." + icon_state = "captain_fly" + item_state = "captain_fly" + _color = "captain_fly" + +/obj/item/clothing/under/scratch + name = "white suit" + desc = "A white suit, suitable for an excellent host" + icon_state = "scratch" + item_state = "scratch" + _color = "scratch" + +/obj/item/clothing/under/sl_suit + desc = "It's a very amish looking suit." + name = "amish suit" + icon_state = "sl_suit" + _color = "sl_suit" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/waiter + name = "waiter's outfit" + desc = "It's a very smart uniform with a special pocket for tip." + icon_state = "waiter" + item_state = "waiter" + _color = "waiter" + flags = FPRINT + +/obj/item/clothing/under/rank/mailman + name = "mailman's jumpsuit" + desc = "'Special delivery!'" + icon_state = "mailman" + item_state = "b_suit" + _color = "mailman" + +/obj/item/clothing/under/sexyclown + name = "sexy-clown suit" + desc = "It makes you look HONKable!" + icon_state = "sexyclown" + item_state = "sexyclown" + _color = "sexyclown" + +/obj/item/clothing/under/rank/vice + name = "vice officer's jumpsuit" + desc = "It's the standard issue pretty-boy outfit, as seen on Holo-Vision." + icon_state = "vice" + item_state = "gy_suit" + _color = "vice" + +/obj/item/clothing/under/rank/centcom_officer + desc = "It's a jumpsuit worn by CentCom Officers." + name = "\improper CentCom officer's jumpsuit" + icon_state = "officer" + item_state = "g_suit" + _color = "officer" + +/obj/item/clothing/under/rank/centcom_commander + desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders." + name = "\improper CentCom officer's jumpsuit" + icon_state = "centcom" + item_state = "dg_suit" + _color = "centcom" + +/obj/item/clothing/under/space + name = "\improper NASA jumpsuit" + desc = "It has a NASA logo on it and is made of space-proofed materials." + icon_state = "black" + item_state = "bl_suit" + _color = "black" + w_class = 4//bulky item + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.02 + flags = FPRINT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS //Needs gloves and shoes with cold protection to be fully protected. + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + +/obj/item/clothing/under/acj + name = "administrative cybernetic jumpsuit" + icon_state = "syndicate" + item_state = "bl_suit" + _color = "syndicate" + desc = "it's a cybernetically enhanced jumpsuit used for administrative duties." + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + flags = FPRINT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + armor = list(melee = 100, bullet = 100, laser = 100,energy = 100, bomb = 100, bio = 100, rad = 100) + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0 + +/obj/item/clothing/under/owl + name = "owl uniform" + desc = "A jumpsuit with owl wings. Photorealistic owl feathers! Twooooo!" + icon_state = "owl" + _color = "owl" + flags = FPRINT | ONESIZEFITSALL + +/obj/item/clothing/under/johnny + name = "johnny~~ jumpsuit" + desc = "Johnny~~" + icon_state = "johnny" + _color = "johnny" + +/obj/item/clothing/under/rainbow + name = "rainbow jumpsuit" + desc = "A fabulous jumpsuit." + icon_state = "rainbow" + item_state = "rainbow" + _color = "rainbow" + +/obj/item/clothing/under/cloud + name = "cloud" + desc = "cloud" + icon_state = "cloud" + _color = "cloud" + +/obj/item/clothing/under/psysuit + name = "dark undersuit" + desc = "A thick, layered grey undersuit lined with power cables. Feels a little like wearing an electrical storm." + icon_state = "psysuit" + item_state = "psysuit" + _color = "psysuit" + +/obj/item/clothing/under/gimmick/rank/captain/suit + name = "captain's suit" + desc = "A green suit and yellow necktie. Exemplifies authority." + icon_state = "green_suit" + item_state = "dg_suit" + _color = "green_suit" + +/obj/item/clothing/under/gimmick/rank/head_of_personnel/suit + name = "head of personnel's suit" + desc = "A teal suit and yellow necktie. An authoritative yet tacky ensemble." + icon_state = "teal_suit" + item_state = "g_suit" + _color = "teal_suit" + +/obj/item/clothing/under/suit_jacket + name = "black suit" + desc = "A black suit and red tie. Very formal." + icon_state = "black_suit" + item_state = "bl_suit" + _color = "black_suit" + +/obj/item/clothing/under/suit_jacket/really_black + name = "executive suit" + desc = "A formal black suit and red tie, intended for the station's finest." + icon_state = "really_black_suit" + item_state = "bl_suit" + _color = "black_suit" + +/obj/item/clothing/under/suit_jacket/female + name = "executive suit" + desc = "A formal trouser suit for women, intended for the station's finest." + icon_state = "black_suit_fem" + item_state = "black_suit_fem" + _color = "black_suit_fem" + +/obj/item/clothing/under/suit_jacket/red + name = "red suit" + desc = "A red suit and blue tie. Somewhat formal." + icon_state = "red_suit" + item_state = "r_suit" + _color = "red_suit" + species_fit = list("Vox") + +/obj/item/clothing/under/blackskirt + name = "black skirt" + desc = "A black skirt, very fancy!" + icon_state = "blackskirt" + _color = "blackskirt" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/schoolgirl + name = "schoolgirl uniform" + desc = "It's just like one of my Japanese animes!" + icon_state = "schoolgirl" + item_state = "schoolgirl" + _color = "schoolgirl" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/overalls + name = "laborer's overalls" + desc = "A set of durable overalls for getting the job done." + icon_state = "overalls" + item_state = "lb_suit" + _color = "overalls" + gender = PLURAL + +/obj/item/clothing/under/pirate + name = "pirate outfit" + desc = "Yarr." + icon_state = "pirate" + item_state = "pirate" + _color = "pirate" + species_fit = list("Vox") + +/obj/item/clothing/under/soviet + name = "soviet uniform" + desc = "For the Motherland!" + icon_state = "soviet" + item_state = "soviet" + _color = "soviet" + +/obj/item/clothing/under/redcoat + name = "redcoat uniform" + desc = "Looks old." + icon_state = "redcoat" + item_state = "redcoat" + _color = "redcoat" + +/obj/item/clothing/under/kilt + name = "kilt" + desc = "Includes shoes and plaid" + icon_state = "kilt" + item_state = "kilt" + _color = "kilt" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|FEET + +/obj/item/clothing/under/sexymime + name = "sexy mime outfit" + desc = "The only time when you DON'T enjoy looking at someone's rack." + icon_state = "sexymime" + item_state = "sexymime" + _color = "sexymime" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/obj/item/clothing/under/gladiator + name = "gladiator uniform" + desc = "Are you not entertained? Is that not why you are here?" + icon_state = "gladiator" + item_state = "gladiator" + _color = "gladiator" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +//dress + +/obj/item/clothing/under/dress/dress_fire + name = "flame dress" + desc = "A small black dress with blue flames print on it." + icon_state = "dress_fire" + _color = "dress_fire" + +/obj/item/clothing/under/dress/dress_green + name = "green dress" + desc = "A simple, tight fitting green dress." + icon_state = "dress_green" + _color = "dress_green" + +/obj/item/clothing/under/dress/dress_orange + name = "orange dress" + desc = "A fancy orange gown for those who like to show leg." + icon_state = "dress_orange" + _color = "dress_orange" + +/obj/item/clothing/under/dress/dress_pink + name = "pink dress" + desc = "A simple, tight fitting pink dress." + icon_state = "dress_pink" + _color = "dress_pink" + +/obj/item/clothing/under/dress/dress_yellow + name = "yellow dress" + desc = "A flirty, little yellow dress." + icon_state = "dress_yellow" + _color = "dress_yellow" + +/obj/item/clothing/under/dress/dress_saloon + name = "saloon girl dress" + desc = "A old western inspired gown for the girl who likes to drink." + icon_state = "dress_saloon" + _color = "dress_saloon" + +/obj/item/clothing/under/dress/dress_rd + name = "research director dress uniform" + desc = "Feminine fashion for the style concious RD." + icon_state = "dress_rd" + _color = "dress_rd" + +/obj/item/clothing/under/dress/dress_cap + name = "captain dress uniform" + desc = "Feminine fashion for the style concious captain." + icon_state = "dress_cap" + _color = "dress_cap" + +/obj/item/clothing/under/dress/dress_hop + name = "head of personal dress uniform" + desc = "Feminine fashion for the style concious HoP." + icon_state = "dress_hop" + _color = "dress_hop" + +/obj/item/clothing/under/dress/dress_hr + name = "human resources director uniform" + desc = "Superior class for the nosy H.R. Director." + icon_state = "huresource" + _color = "huresource" + +/obj/item/clothing/under/dress/plaid_blue + name = "blue plaid skirt" + desc = "A preppy blue skirt with a white blouse." + icon_state = "plaid_blue" + _color = "plaid_blue" + +/obj/item/clothing/under/dress/plaid_red + name = "red plaid skirt" + desc = "A preppy red skirt with a white blouse." + icon_state = "plaid_red" + _color = "plaid_red" + +/obj/item/clothing/under/dress/plaid_purple + name = "blue purple skirt" + desc = "A preppy purple skirt with a white blouse." + icon_state = "plaid_purple" + _color = "plaid_purple" + +//wedding stuff + +/obj/item/clothing/under/wedding/bride_orange + name = "orange wedding dress" + desc = "A big and puffy orange dress." + icon_state = "bride_orange" + _color = "bride_orange" + flags_inv = HIDESHOES + +/obj/item/clothing/under/wedding/bride_purple + name = "purple wedding dress" + desc = "A big and puffy purple dress." + icon_state = "bride_purple" + _color = "bride_purple" + flags_inv = HIDESHOES + +/obj/item/clothing/under/wedding/bride_blue + name = "blue wedding dress" + desc = "A big and puffy blue dress." + icon_state = "bride_blue" + _color = "bride_blue" + flags_inv = HIDESHOES + +/obj/item/clothing/under/wedding/bride_red + name = "red wedding dress" + desc = "A big and puffy red dress." + icon_state = "bride_red" + _color = "bride_red" + flags_inv = HIDESHOES + +/obj/item/clothing/under/wedding/bride_white + name = "white wedding dress" + desc = "A white wedding gown made from the finest silk." + icon_state = "bride_white" + _color = "bride_white" + flags_inv = HIDESHOES + +/obj/item/clothing/under/sundress + name = "sundress" + desc = "Makes you want to frolic in a field of daisies." + icon_state = "sundress" + item_state = "sundress" + _color = "sundress" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/obj/item/clothing/under/roman + name = "roman armor" + desc = "An ancient Roman armor. Made of metallic strips and leather straps." + icon_state = "roman" + _color = "roman" + item_state = "armor" + armor = list(melee = 25, bullet = 0, laser = 25, energy = 10, bomb = 10, bio = 0, rad = 0) + +/obj/item/clothing/under/simonpants + name = "Simon's Pants" + desc = "Simon's pants, clad with belt and whatever the fuck that thing is around his neck" + icon_state = "spants" + _color = "simonpants" + item_state = "spants" + species_fit = list("Vox") + gender = PLURAL + +/obj/item/clothing/under/batmansuit + name = "batsuit" + desc = "You are the night." + icon_state = "bmuniform" + _color = "bmuniform" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/obj/item/clothing/under/officeruniform + name = "officer's uniform" + desc = "Bestraft die Juden fur ihre Verbrechen." + icon_state = "officeruniform" + item_state = "officeruniform" + _color = "officeruniform" + +/obj/item/clothing/under/soldieruniform + name = "soldier's uniform" + desc = "Bestraft die Verbundeten fur ihren Widerstand." + icon_state = "soldieruniform" + item_state = "soldieruniform" + _color = "soldieruniform" + +/obj/item/clothing/under/squatter_outfit + name = "slav squatter tracksuit" + desc = "Cyka blyat." + icon_state = "squatteroutfit" + item_state = "squatteroutfit" + _color = "squatteroutfit" + +/obj/item/clothing/under/russobluecamooutfit + name = "russian blue camo" + desc = "Drop and give me dvadtsat!" + icon_state = "russobluecamo" + item_state = "russobluecamo" + _color = "russobluecamo" + +/obj/item/clothing/under/jester + name = "jester duit" + desc = "Only a fool would wear such a suit." + icon_state = "jester" + item_state = "jester" + _color = "jester" + +/obj/item/clothing/under/stilsuit + name = "stillsuit" + desc = "Designed to preserve bodymoisture." + icon_state = "stilsuit" + item_state = "stilsuit" + _color = "stilsuit" + +/obj/item/clothing/under/aviatoruniform + name = "aviator uniform" + desc = "Now you can look absolutely dashing!" + icon_state = "aviator_uniform" + item_state = "aviator_uniform" + _color = "aviator_uniform" + species_restricted = list("exclude","Vox") + +/obj/item/clothing/under/libertyshirt + name = "liberty shirt" + desc = "For any freedom loving patriot out there" + icon_state = "libertyshirt" + item_state = "libertyshirt" + _color = "libertyshirt" + +/obj/item/clothing/under/bikersuit + name = "biker's outfit" + icon_state = "biker" + item_state = "biker" + _color = "biker" + +/obj/item/clothing/under/jacketsuit + name = "richard's outfit" + desc = "Do you know what time it is?" + icon_state = "jacket" + item_state = "jacket" + _color = "jacket" + +/obj/item/clothing/under/mega + name = "\improper DRN-001 suit" + desc = "The original. Simple, yet very adaptable." + icon_state = "mega" + item_state = "mega" + _color = "mega" + +/obj/item/clothing/under/proto + name = "The Prototype Suit" + desc = "Even robots know scarves are the perfect accessory for a brooding rival." + icon_state = "proto" + item_state = "proto" + _color = "proto" + +/obj/item/clothing/under/megax + name = "\improper Maverick Hunter regalia" + desc = "The best outfit for taking out rogue borgs." + icon_state = "megax" + item_state = "megax" + _color = "megax" + +/obj/item/clothing/under/joe + name = "The Sniper Suit" + desc = "Mass produced combat robots with a rather unfitting name." + icon_state = "joe" + item_state = "joe" + _color = "joe" + +/obj/item/clothing/under/roll + name = "\improper DRN-002 Dress" + desc = "A simple red dress, the good doctor's second robot wasn't quite as exciting as the first." + icon_state = "roll" + item_state = "roll" + _color = "roll" + +/obj/item/clothing/under/maid + name = "maid outfit" + desc = "Perfect for lusty aliens and desperate weeaboos." + icon_state = "maid" + item_state = "maid" + _color = "maid" + +/obj/item/clothing/under/darkholme + name = "\improper The Darkholme" + desc = "Fuck you." + icon_state = "darkholme" + item_state = "darkholme" + _color = "darkholme" + +/obj/item/clothing/under/gokugidown + name = "turtle hermit undershirt" + desc = "Something seems oddly familiar about this outfit..." + icon_state = "gokugidown" + item_state = "gokugidown" + _color = "gokugidown" + +/obj/item/clothing/under/gokugi + name = "turtle hermit outfit" + desc = "An outfit from one trained by the great Turtle Hermit" + icon_state = "gokugi" + item_state = "gokugi" + _color = "gokugi" + +/obj/item/clothing/under/doomguy + name = "\improper Doomguy's pants" + desc = "" + icon_state = "doom" + item_state = "doom" + _color = "doom" + +/obj/item/clothing/under/vault13 + name = "vault 13 Jumpsuit" + desc = "Oddly similar to the station's usual jumpsuits, but with a rustic charm to it. Has a large thirteen emblazened on the back" + icon_state = "v13-jumpsuit" + item_state = "v13-jumpsuit" + _color = "v13-jumpsuit" + +/obj/item/clothing/under/vault + name = "vault jumpsuit" + desc = "Oddly similar to the station's usual jumpsuits, but with a rustic charm to it." + icon_state = "v-jumpsuit" + item_state = "v-jumpsuit" + _color = "v-jumpsuit" + +/obj/item/clothing/under/contortionist + name = "contortionist's jumpsuit" + desc = "A light jumpsuit useful for squeezing through narrow vents." + icon_state = "darkholme" + item_state = "darkholme" + _color = "darkholme" + +/obj/item/clothing/under/contortionist/proc/check_clothing(mob/user as mob) + //Allowed to wear: glasses, shoes, gloves, pockets, mask, and jumpsuit (obviously) + var/list/slot_must_be_empty = list(slot_back,slot_handcuffed,slot_legcuffed,slot_l_hand,slot_r_hand,slot_belt,slot_head,slot_wear_suit) + for(var/slot_id in slot_must_be_empty) + if(user.get_item_by_slot(slot_id)) + to_chat(user, "You can't fit inside while wearing that \the [user.get_item_by_slot(slot_id)].") + return 0 + return 1 + +/obj/item/clothing/under/clownpiece + name = "Clownpiece's Pierrot suit" + desc = "A female-sized set of leggings and shirt with a pattern similar to the American flag, featuring a frilled collar." + icon_state = "clownpiece" + item_state = "clownpiece" + _color = "clownpiece" + +/obj/item/clothing/under/cia + name = "casual IAA outfit" + desc = "Just looking at this makes you feel in charge." + icon_state = "cia" + item_state = "cia" + _color = "cia" diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index f144d56f5b6..41ccbfe9834 100644 --- a/code/modules/clothing/under/shorts.dm +++ b/code/modules/clothing/under/shorts.dm @@ -1,26 +1,26 @@ -/obj/item/clothing/under/shorts - name = "athletic shorts" - desc = "95% Polyester, 5% Spandex!" - gender = PLURAL - flags = FPRINT | ONESIZEFITSALL - body_parts_covered = LOWER_TORSO - -/obj/item/clothing/under/shorts/red - icon_state = "redshorts" - _color = "redshorts" - -/obj/item/clothing/under/shorts/green - icon_state = "greenshorts" - _color = "greenshorts" - -/obj/item/clothing/under/shorts/blue - icon_state = "blueshorts" - _color = "blueshorts" - -/obj/item/clothing/under/shorts/black - icon_state = "blackshorts" - _color = "blackshorts" - -/obj/item/clothing/under/shorts/grey - icon_state = "greyshorts" +/obj/item/clothing/under/shorts + name = "athletic shorts" + desc = "95% Polyester, 5% Spandex!" + gender = PLURAL + flags = FPRINT | ONESIZEFITSALL + body_parts_covered = LOWER_TORSO + +/obj/item/clothing/under/shorts/red + icon_state = "redshorts" + _color = "redshorts" + +/obj/item/clothing/under/shorts/green + icon_state = "greenshorts" + _color = "greenshorts" + +/obj/item/clothing/under/shorts/blue + icon_state = "blueshorts" + _color = "blueshorts" + +/obj/item/clothing/under/shorts/black + icon_state = "blackshorts" + _color = "blackshorts" + +/obj/item/clothing/under/shorts/grey + icon_state = "greyshorts" _color = "greyshorts" \ No newline at end of file diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index 0ef3c082143..bc6115d77f7 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -1,28 +1,28 @@ -/obj/item/clothing/under/syndicate - name = "tactical turtleneck" - desc = "It's some non-descript, slightly suspicious looking, civilian clothing." - icon_state = "syndicate" - item_state = "bl_suit" - _color = "syndicate" - species_fit = list("Vox") - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.9 - -//We want our sensors to be off, sensors are not tactical -/obj/item/clothing/under/syndicate/New() - ..() - sensor_mode = 0 - -/obj/item/clothing/under/syndicate/combat - name = "combat turtleneck" - -/obj/item/clothing/under/syndicate/tacticool - name = "\improper Tacticool turtleneck" - desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." - icon_state = "tactifool" - item_state = "bl_suit" - _color = "tactifool" - species_fit = list("Vox") - siemens_coefficient = 1 - - +/obj/item/clothing/under/syndicate + name = "tactical turtleneck" + desc = "It's some non-descript, slightly suspicious looking, civilian clothing." + icon_state = "syndicate" + item_state = "bl_suit" + _color = "syndicate" + species_fit = list("Vox") + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.9 + +//We want our sensors to be off, sensors are not tactical +/obj/item/clothing/under/syndicate/New() + ..() + sensor_mode = 0 + +/obj/item/clothing/under/syndicate/combat + name = "combat turtleneck" + +/obj/item/clothing/under/syndicate/tacticool + name = "\improper Tacticool turtleneck" + desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." + icon_state = "tactifool" + item_state = "bl_suit" + _color = "tactifool" + species_fit = list("Vox") + siemens_coefficient = 1 + + diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 88998b3f9c7..2a58db1754e 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -1,42 +1,42 @@ -/var/global/sent_aliens_to_station = 0 - -/datum/event/alien_infestation - announceWhen = 450 - - var/spawncount = 1 - var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. - var/player_factor = 1 - - -/datum/event/alien_infestation/setup() - announceWhen = rand(300, 600) - player_factor = round(player_list.len/10) //One bonus starting alium for 10 players - spawncount = rand(1, 2)+player_factor - sent_aliens_to_station = 1 - -/datum/event/alien_infestation/announce() - if(successSpawn) - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") +/var/global/sent_aliens_to_station = 0 + +/datum/event/alien_infestation + announceWhen = 450 + + var/spawncount = 1 + var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. + var/player_factor = 1 + + +/datum/event/alien_infestation/setup() + announceWhen = rand(300, 600) + player_factor = round(player_list.len/10) //One bonus starting alium for 10 players + spawncount = rand(1, 2)+player_factor + sent_aliens_to_station = 1 + +/datum/event/alien_infestation/announce() + if(successSpawn) + command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") to_chat(world, sound('sound/AI/aliens.ogg')) - - -/datum/event/alien_infestation/start() - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in atmos_machines) - if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) - if(temp_vent.network.normal_members.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology - vents += temp_vent - - var/list/candidates = get_active_candidates(ROLE_ALIEN, buffer=ALIEN_SELECT_AFK_BUFFER, poll=1) - - while(spawncount > 0 && vents.len && candidates.len) - var/obj/vent = pick(vents) - var/mob/candidate = pick(candidates) - - var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc) - new_xeno.key = candidate.key - - candidates -= candidate - vents -= vent - spawncount-- - successSpawn = 1 + + +/datum/event/alien_infestation/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in atmos_machines) + if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) + if(temp_vent.network.normal_members.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology + vents += temp_vent + + var/list/candidates = get_active_candidates(ROLE_ALIEN, buffer=ALIEN_SELECT_AFK_BUFFER, poll=1) + + while(spawncount > 0 && vents.len && candidates.len) + var/obj/vent = pick(vents) + var/mob/candidate = pick(candidates) + + var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc) + new_xeno.key = candidate.key + + candidates -= candidate + vents -= vent + spawncount-- + successSpawn = 1 diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm index 7788498545c..e6d8720b15e 100644 --- a/code/modules/events/blob.dm +++ b/code/modules/events/blob.dm @@ -1,114 +1,114 @@ -/datum/event/blob - announceWhen = 30 - endWhen = 150 - - var/obj/effect/blob/core/Blob - var/list/datum/mind/infected_crew=list() - - -/datum/event/blob/announce() - burst_blobs() - - -#define ROLE_TYPE_FACE 0 -#define ROLE_TYPE_HEEL 1 -/proc/get_minds_in_role(var/roletype) - var/antagonist_list[] = list()//The main bad guys. Evil minds that plot destruction. - var/protagonist_list[] = ticker.mode.get_living_heads()//The good guys. Mostly Heads. Who are alive. - - //var/xeno_list[] = list()//Aliens. - //var/commando_list[] = list()//Commandos. - - var/datum/mind/current_mind - - var/possible_bad_dudes[] = list( - ticker.mode.traitors, - ticker.mode.head_revolutionaries, - ticker.mode.head_revolutionaries, - ticker.mode.cult, - ticker.mode.wizards, - ticker.mode.changelings, - ticker.mode.syndicates) - for(var/list in possible_bad_dudes)//For every possible antagonist type. - for(current_mind in list)//For each mind in that list. - if(current_mind.current&¤t_mind.current.stat!=2 && current_mind.current.client && !current_mind.current.client.is_afk())//If they are not destroyed and not dead. - antagonist_list += current_mind//Add them. - - if(protagonist_list.len)//If the mind is both a protagonist and antagonist. - for(current_mind in protagonist_list) - if(current_mind in antagonist_list) - protagonist_list -= current_mind//We only want it in one list. - - if(roletype==ROLE_TYPE_FACE) - return protagonist_list - else - return antagonist_list - -/datum/event/blob/start() - var/list/possible_blobs = get_minds_in_role(ROLE_TYPE_FACE) - if (!possible_blobs.len) - return - for(var/mob/living/G in possible_blobs) - if(G.client && !G.client.holder && !G.client.is_afk() && G.client.desires_role(ROLE_BLOB)) - var/datum/mind/blob = pick(possible_blobs) - infected_crew += blob - blob.special_role = "Blob" - log_game("[blob.key] (ckey) has been selected as a Blob") - possible_blobs -= blob - greetblob(blob) - return - - //Blob = new /obj/effect/blob/core(T, 200) - //for(var/i = 1; i < rand(3, 6), i++) - // Blob.process() - -/datum/event/blob/proc/burst_blobs() - spawn(0) - for(var/datum/mind/blob in infected_crew) - blob.current.show_message("You feel tired and bloated.") - - sleep(600) // 60s - - for(var/datum/mind/blob in infected_crew) - blob.current.show_message("You feel like you are about to burst.") - - sleep(300) // 30s - - for(var/datum/mind/blob in infected_crew) - - var/client/blob_client = null - var/turf/location = null - - if(iscarbon(blob.current)) - var/mob/living/carbon/C = blob.current - if(directory[ckey(blob.key)]) - blob_client = directory[ckey(blob.key)] - location = get_turf(C) - if(location.z != 1 || istype(location, /turf/space)) - location = null - C.gib() - - - if(blob_client && location) - var/obj/effect/blob/core/core = new(location, 200, blob_client, 3) - if(core.overmind && core.overmind.mind) - core.overmind.mind.name = blob.name - infected_crew -= blob - infected_crew += core.overmind.mind - - sleep(100) // 10s - biohazard_alert() - -/datum/event/blob/proc/greetblob(user) +/datum/event/blob + announceWhen = 30 + endWhen = 150 + + var/obj/effect/blob/core/Blob + var/list/datum/mind/infected_crew=list() + + +/datum/event/blob/announce() + burst_blobs() + + +#define ROLE_TYPE_FACE 0 +#define ROLE_TYPE_HEEL 1 +/proc/get_minds_in_role(var/roletype) + var/antagonist_list[] = list()//The main bad guys. Evil minds that plot destruction. + var/protagonist_list[] = ticker.mode.get_living_heads()//The good guys. Mostly Heads. Who are alive. + + //var/xeno_list[] = list()//Aliens. + //var/commando_list[] = list()//Commandos. + + var/datum/mind/current_mind + + var/possible_bad_dudes[] = list( + ticker.mode.traitors, + ticker.mode.head_revolutionaries, + ticker.mode.head_revolutionaries, + ticker.mode.cult, + ticker.mode.wizards, + ticker.mode.changelings, + ticker.mode.syndicates) + for(var/list in possible_bad_dudes)//For every possible antagonist type. + for(current_mind in list)//For each mind in that list. + if(current_mind.current&¤t_mind.current.stat!=2 && current_mind.current.client && !current_mind.current.client.is_afk())//If they are not destroyed and not dead. + antagonist_list += current_mind//Add them. + + if(protagonist_list.len)//If the mind is both a protagonist and antagonist. + for(current_mind in protagonist_list) + if(current_mind in antagonist_list) + protagonist_list -= current_mind//We only want it in one list. + + if(roletype==ROLE_TYPE_FACE) + return protagonist_list + else + return antagonist_list + +/datum/event/blob/start() + var/list/possible_blobs = get_minds_in_role(ROLE_TYPE_FACE) + if (!possible_blobs.len) + return + for(var/mob/living/G in possible_blobs) + if(G.client && !G.client.holder && !G.client.is_afk() && G.client.desires_role(ROLE_BLOB)) + var/datum/mind/blob = pick(possible_blobs) + infected_crew += blob + blob.special_role = "Blob" + log_game("[blob.key] (ckey) has been selected as a Blob") + possible_blobs -= blob + greetblob(blob) + return + + //Blob = new /obj/effect/blob/core(T, 200) + //for(var/i = 1; i < rand(3, 6), i++) + // Blob.process() + +/datum/event/blob/proc/burst_blobs() + spawn(0) + for(var/datum/mind/blob in infected_crew) + blob.current.show_message("You feel tired and bloated.") + + sleep(600) // 60s + + for(var/datum/mind/blob in infected_crew) + blob.current.show_message("You feel like you are about to burst.") + + sleep(300) // 30s + + for(var/datum/mind/blob in infected_crew) + + var/client/blob_client = null + var/turf/location = null + + if(iscarbon(blob.current)) + var/mob/living/carbon/C = blob.current + if(directory[ckey(blob.key)]) + blob_client = directory[ckey(blob.key)] + location = get_turf(C) + if(location.z != 1 || istype(location, /turf/space)) + location = null + C.gib() + + + if(blob_client && location) + var/obj/effect/blob/core/core = new(location, 200, blob_client, 3) + if(core.overmind && core.overmind.mind) + core.overmind.mind.name = blob.name + infected_crew -= blob + infected_crew += core.overmind.mind + + sleep(100) // 10s + biohazard_alert() + +/datum/event/blob/proc/greetblob(user) to_chat(user, {"You are infected by the Blob! -Your body is ready to give spawn to a new blob core which will eat this station. -Find a good location to spawn the core and then take control and overwhelm the station! -When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process. -If you go outside of the station level, or in space, then you will die; make sure your location has lots of ground to cover."}) - -/datum/event/blob/tick() - if(!Blob && infected_crew.len == 0) - kill() - return - if(IsMultiple(activeFor, 3)) - Blob.process() +Your body is ready to give spawn to a new blob core which will eat this station. +Find a good location to spawn the core and then take control and overwhelm the station! +When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process. +If you go outside of the station level, or in space, then you will die; make sure your location has lots of ground to cover."}) + +/datum/event/blob/tick() + if(!Blob && infected_crew.len == 0) + kill() + return + if(IsMultiple(activeFor, 3)) + Blob.process() diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index b180ef77e08..d0d369c5c17 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -1,57 +1,57 @@ -/datum/event/brand_intelligence - announceWhen = 30 - endWhen = 900 //Ends when all vending machines are subverted anyway. - oneShot = 1 - - var/list/obj/machinery/vending/vendingMachines = list() - var/list/obj/machinery/vending/infectedVendingMachines = list() - var/obj/machinery/vending/originMachine - - -/datum/event/brand_intelligence/announce() - command_alert("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert") - - -/datum/event/brand_intelligence/start() - for(var/obj/machinery/vending/V in machines) - if(V.z != 1) continue - vendingMachines.Add(V) - - if(!vendingMachines.len) - kill() - return - - originMachine = pick(vendingMachines) - vendingMachines.Remove(originMachine) - originMachine.shut_up = 0 - originMachine.shoot_inventory = 1 - - -/datum/event/brand_intelligence/tick() - if(!vendingMachines.len || !originMachine || originMachine.shut_up) //if every machine is infected, or if the original vending machine is missing or has it's voice switch flipped - end() - kill() - return - - if(IsMultiple(activeFor, 5)) - if(prob(25)) - var/obj/machinery/vending/infectedMachine = pick(vendingMachines) - vendingMachines.Remove(infectedMachine) - infectedVendingMachines.Add(infectedMachine) - infectedMachine.shut_up = 0 - infectedMachine.shoot_inventory = 1 - - if(IsMultiple(activeFor, 12)) - originMachine.speak(pick("Try our aggressive new marketing strategies!", \ - "You should buy products to feed your lifestyle obession!", \ - "Consume!", \ - "Your money can buy happiness!", \ - "Engage direct marketing!", \ - "Advertising is legalized lying! But don't let that put you off our great deals!", \ - "You don't want to buy anything? Yeah, well I didn't want to buy your mom either.")) - -/datum/event/brand_intelligence/end() - for(var/obj/machinery/vending/infectedMachine in infectedVendingMachines) - if(prob(90)) - infectedMachine.shut_up = 1 - infectedMachine.shoot_inventory = 0 +/datum/event/brand_intelligence + announceWhen = 30 + endWhen = 900 //Ends when all vending machines are subverted anyway. + oneShot = 1 + + var/list/obj/machinery/vending/vendingMachines = list() + var/list/obj/machinery/vending/infectedVendingMachines = list() + var/obj/machinery/vending/originMachine + + +/datum/event/brand_intelligence/announce() + command_alert("Rampant brand intelligence has been detected aboard [station_name()], please stand-by.", "Machine Learning Alert") + + +/datum/event/brand_intelligence/start() + for(var/obj/machinery/vending/V in machines) + if(V.z != 1) continue + vendingMachines.Add(V) + + if(!vendingMachines.len) + kill() + return + + originMachine = pick(vendingMachines) + vendingMachines.Remove(originMachine) + originMachine.shut_up = 0 + originMachine.shoot_inventory = 1 + + +/datum/event/brand_intelligence/tick() + if(!vendingMachines.len || !originMachine || originMachine.shut_up) //if every machine is infected, or if the original vending machine is missing or has it's voice switch flipped + end() + kill() + return + + if(IsMultiple(activeFor, 5)) + if(prob(25)) + var/obj/machinery/vending/infectedMachine = pick(vendingMachines) + vendingMachines.Remove(infectedMachine) + infectedVendingMachines.Add(infectedMachine) + infectedMachine.shut_up = 0 + infectedMachine.shoot_inventory = 1 + + if(IsMultiple(activeFor, 12)) + originMachine.speak(pick("Try our aggressive new marketing strategies!", \ + "You should buy products to feed your lifestyle obession!", \ + "Consume!", \ + "Your money can buy happiness!", \ + "Engage direct marketing!", \ + "Advertising is legalized lying! But don't let that put you off our great deals!", \ + "You don't want to buy anything? Yeah, well I didn't want to buy your mom either.")) + +/datum/event/brand_intelligence/end() + for(var/obj/machinery/vending/infectedMachine in infectedVendingMachines) + if(prob(90)) + infectedMachine.shut_up = 1 + infectedMachine.shoot_inventory = 0 diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index c8009c74eed..95dc5c09bc3 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -1,25 +1,25 @@ -/datum/event/carp_migration - announceWhen = 20 - endWhen = 450 - var/list/spawned_carp = list() - -/datum/event/carp_migration/setup() - announceWhen = rand(15, 30) - endWhen = rand(600,1200) - -/datum/event/carp_migration/announce() - command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") - -/datum/event/carp_migration/start() - for(var/obj/effect/landmark/C in landmarks_list) - if(C.name == "carpspawn") - if(prob(90)) //Give it a sliver of randomness - spawned_carp.Add(new /mob/living/simple_animal/hostile/carp(C.loc)) - -/datum/event/carp_migration/end() - for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp) - if(!C.stat) - var/turf/T = get_turf(C) - if(istype(T, /turf/space)) - qdel(C) - C = null +/datum/event/carp_migration + announceWhen = 20 + endWhen = 450 + var/list/spawned_carp = list() + +/datum/event/carp_migration/setup() + announceWhen = rand(15, 30) + endWhen = rand(600,1200) + +/datum/event/carp_migration/announce() + command_alert("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert") + +/datum/event/carp_migration/start() + for(var/obj/effect/landmark/C in landmarks_list) + if(C.name == "carpspawn") + if(prob(90)) //Give it a sliver of randomness + spawned_carp.Add(new /mob/living/simple_animal/hostile/carp(C.loc)) + +/datum/event/carp_migration/end() + for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp) + if(!C.stat) + var/turf/T = get_turf(C) + if(istype(T, /turf/space)) + qdel(C) + C = null diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm index 108607a5fee..f69a8138838 100644 --- a/code/modules/events/communications_blackout.dm +++ b/code/modules/events/communications_blackout.dm @@ -1,20 +1,20 @@ -/datum/event/communications_blackout/announce() - var/alert = pick( "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you*%fj00)`5vc-BZZT", \ - "Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v¬-BZZZT", \ - "Ionospheric anomalies detected. Temporary telec#MCi46:5.;@63-BZZZZT", \ - "Ionospheric anomalies dete'fZ\\kg5_0-BZZZZZT", \ - "Ionospheri:%£ MCayj^j<.3-BZZZZZZT", \ - "#4nd%;f4y6,>£%-BZZZZZZZT") - - for(var/mob/living/silicon/ai/A in player_list) //AIs are always aware of communication blackouts. +/datum/event/communications_blackout/announce() + var/alert = pick( "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you*%fj00)`5vc-BZZT", \ + "Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v¬-BZZZT", \ + "Ionospheric anomalies detected. Temporary telec#MCi46:5.;@63-BZZZZT", \ + "Ionospheric anomalies dete'fZ\\kg5_0-BZZZZZT", \ + "Ionospheri:%£ MCayj^j<.3-BZZZZZZT", \ + "#4nd%;f4y6,>£%-BZZZZZZZT") + + for(var/mob/living/silicon/ai/A in player_list) //AIs are always aware of communication blackouts. to_chat(A, "
    ") to_chat(A, "[alert]") to_chat(A, "
    ") - - if(prob(30)) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts. - command_alert(alert) - - -/datum/event/communications_blackout/start() - for(var/obj/machinery/telecomms/T in telecomms_list) + + if(prob(30)) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts. + command_alert(alert) + + +/datum/event/communications_blackout/start() + for(var/obj/machinery/telecomms/T in telecomms_list) T.emp_act(1) \ No newline at end of file diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index 035ccb9a221..afa26a63f95 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -1,44 +1,44 @@ -/datum/event/disease_outbreak - announceWhen = 90 - - -/datum/event/disease_outbreak/announce() - biohazard_alert() - -/datum/event/disease_outbreak/setup() - announceWhen = rand(30, 150) //Thanks Doc - -/datum/event/disease_outbreak/start() - var/virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis) - - for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) - var/foundAlready = 0 // don't infect someone that already has the virus - var/turf/T = get_turf(H) - if(!T) - continue - if(T.z != 1) - continue - for(var/datum/disease/D in H.viruses) - foundAlready = 1 - if(H.stat == 2 || foundAlready) - continue - - if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work. - if((!H.dna) || (H.sdisabilities & BLIND)) //A blindness disease would be the worst. - continue - var/datum/disease/dnaspread/D = new - D.strain_data["name"] = H.real_name - D.strain_data["UI"] = H.dna.UI.Copy() - D.strain_data["SE"] = H.dna.SE.Copy() - D.carrier = 1 - D.holder = H - D.affected_mob = H - H.viruses += D - break - else - var/datum/disease/D = new virus_type - D.carrier = 1 - D.holder = H - D.affected_mob = H - H.viruses += D +/datum/event/disease_outbreak + announceWhen = 90 + + +/datum/event/disease_outbreak/announce() + biohazard_alert() + +/datum/event/disease_outbreak/setup() + announceWhen = rand(30, 150) //Thanks Doc + +/datum/event/disease_outbreak/start() + var/virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis) + + for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) + var/foundAlready = 0 // don't infect someone that already has the virus + var/turf/T = get_turf(H) + if(!T) + continue + if(T.z != 1) + continue + for(var/datum/disease/D in H.viruses) + foundAlready = 1 + if(H.stat == 2 || foundAlready) + continue + + if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work. + if((!H.dna) || (H.sdisabilities & BLIND)) //A blindness disease would be the worst. + continue + var/datum/disease/dnaspread/D = new + D.strain_data["name"] = H.real_name + D.strain_data["UI"] = H.dna.UI.Copy() + D.strain_data["SE"] = H.dna.SE.Copy() + D.carrier = 1 + D.holder = H + D.affected_mob = H + H.viruses += D + break + else + var/datum/disease/D = new virus_type + D.carrier = 1 + D.holder = H + D.affected_mob = H + H.viruses += D break \ No newline at end of file diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm index dacaa09c47a..6dcaa15addb 100644 --- a/code/modules/events/electrical_storm.dm +++ b/code/modules/events/electrical_storm.dm @@ -1,28 +1,28 @@ -/datum/event/electrical_storm - var/lightsoutAmount = 1 - var/lightsoutRange = 25 - - -/datum/event/electrical_storm/announce() - command_alert("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert") - - -/datum/event/electrical_storm/start() - var/list/epicentreList = list() - - for(var/i=1, i <= lightsoutAmount, i++) - var/list/possibleEpicentres = list() - for(var/obj/effect/landmark/newEpicentre in landmarks_list) - if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList)) - possibleEpicentres += newEpicentre - if(possibleEpicentres.len) - epicentreList += pick(possibleEpicentres) - else - break - - if(!epicentreList.len) - return - - for(var/obj/effect/landmark/epicentre in epicentreList) - for(var/obj/machinery/power/apc/apc in range(epicentre,lightsoutRange)) +/datum/event/electrical_storm + var/lightsoutAmount = 1 + var/lightsoutRange = 25 + + +/datum/event/electrical_storm/announce() + command_alert("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert") + + +/datum/event/electrical_storm/start() + var/list/epicentreList = list() + + for(var/i=1, i <= lightsoutAmount, i++) + var/list/possibleEpicentres = list() + for(var/obj/effect/landmark/newEpicentre in landmarks_list) + if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList)) + possibleEpicentres += newEpicentre + if(possibleEpicentres.len) + epicentreList += pick(possibleEpicentres) + else + break + + if(!epicentreList.len) + return + + for(var/obj/effect/landmark/epicentre in epicentreList) + for(var/obj/machinery/power/apc/apc in range(epicentre,lightsoutRange)) apc.overload_lighting() \ No newline at end of file diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm index 747321f83d5..6b1a0fc6790 100644 --- a/code/modules/events/event.dm +++ b/code/modules/events/event.dm @@ -1,84 +1,84 @@ -/datum/event //NOTE: Times are measured in master controller ticks! - var/startWhen = 0 //When in the lifetime to call start(). - var/announceWhen = 0 //When in the lifetime to call announce(). - var/endWhen = 0 //When in the lifetime the event should end. - var/oneShot = 0 //If true, then the event removes itself from the list of potential events on creation. - - var/activeFor = 0 //How long the event has existed. You don't need to change this. - -//Called first before processing. -//Allows you to setup your event, such as randomly -//setting the startWhen and or announceWhen variables. -//Only called once. -/datum/event/proc/setup() - return - -//Called when the tick is equal to the startWhen variable. -//Allows you to start before announcing or vice versa. -//Only called once. -/datum/event/proc/start() - return - -//Called when the tick is equal to the announceWhen variable. -//Allows you to announce before starting or vice versa. -//Only called once. -/datum/event/proc/announce() - return - -//Called on or after the tick counter is equal to startWhen. -//You can include code related to your event or add your own -//time stamped events. -//Called more than once. -/datum/event/proc/tick() - return - -//Called on or after the tick is equal or more than endWhen -//You can include code related to the event ending. -//Do not place spawn() in here, instead use tick() to check for -//the activeFor variable. -//For example: if(activeFor == myOwnVariable + 30) doStuff() -//Only called once. -/datum/event/proc/end() - return - - - -//Do not override this proc, instead use the appropiate procs. -//This proc will handle the calls to the appropiate procs. -/datum/event/proc/process() - - - if(activeFor > startWhen && activeFor < endWhen) - tick() - - if(activeFor == startWhen) - start() - - if(activeFor == announceWhen) - announce() - - if(activeFor == endWhen) - end() - - // Everything is done, let's clean up. - if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen) - kill() - - activeFor++ - - -//Garbage collects the event by removing it from the global events list, -//which should be the only place it's referenced. -//Called when start(), announce() and end() has all been called. -/datum/event/proc/kill() - events.Remove(src) - - -//Adds the event to the global events list, and removes it from the list -//of potential events. -/datum/event/New() - setup() - events.Add(src) - /*if(oneShot) - potentialRandomEvents.Remove(type)*/ - ..() +/datum/event //NOTE: Times are measured in master controller ticks! + var/startWhen = 0 //When in the lifetime to call start(). + var/announceWhen = 0 //When in the lifetime to call announce(). + var/endWhen = 0 //When in the lifetime the event should end. + var/oneShot = 0 //If true, then the event removes itself from the list of potential events on creation. + + var/activeFor = 0 //How long the event has existed. You don't need to change this. + +//Called first before processing. +//Allows you to setup your event, such as randomly +//setting the startWhen and or announceWhen variables. +//Only called once. +/datum/event/proc/setup() + return + +//Called when the tick is equal to the startWhen variable. +//Allows you to start before announcing or vice versa. +//Only called once. +/datum/event/proc/start() + return + +//Called when the tick is equal to the announceWhen variable. +//Allows you to announce before starting or vice versa. +//Only called once. +/datum/event/proc/announce() + return + +//Called on or after the tick counter is equal to startWhen. +//You can include code related to your event or add your own +//time stamped events. +//Called more than once. +/datum/event/proc/tick() + return + +//Called on or after the tick is equal or more than endWhen +//You can include code related to the event ending. +//Do not place spawn() in here, instead use tick() to check for +//the activeFor variable. +//For example: if(activeFor == myOwnVariable + 30) doStuff() +//Only called once. +/datum/event/proc/end() + return + + + +//Do not override this proc, instead use the appropiate procs. +//This proc will handle the calls to the appropiate procs. +/datum/event/proc/process() + + + if(activeFor > startWhen && activeFor < endWhen) + tick() + + if(activeFor == startWhen) + start() + + if(activeFor == announceWhen) + announce() + + if(activeFor == endWhen) + end() + + // Everything is done, let's clean up. + if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen) + kill() + + activeFor++ + + +//Garbage collects the event by removing it from the global events list, +//which should be the only place it's referenced. +//Called when start(), announce() and end() has all been called. +/datum/event/proc/kill() + events.Remove(src) + + +//Adds the event to the global events list, and removes it from the list +//of potential events. +/datum/event/New() + setup() + events.Add(src) + /*if(oneShot) + potentialRandomEvents.Remove(type)*/ + ..() diff --git a/code/modules/events/event_manager.dm b/code/modules/events/event_manager.dm index 4018cf6304d..532666ad039 100644 --- a/code/modules/events/event_manager.dm +++ b/code/modules/events/event_manager.dm @@ -1,64 +1,64 @@ -var/list/allEvents = typesof(/datum/event) - /datum/event -var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event -//var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event - /datum/event/spider_infestation - /datum/event/alien_infestation - -var/eventTimeLower = 6000 //10 minutes -var/eventTimeUpper = 12000 //20 minutes -var/scheduledEvent = null - -/proc/checkEvent() - if(!scheduledEvent) - //The more players, the merrier - var/playercount_modifier = 1 - switch(player_list.len) - if(0 to 10) - playercount_modifier = 1.25 //At this point even carps could KO the crew - if(11 to 20) - playercount_modifier = 1.15 - if(21 to 30) - playercount_modifier = 1.05 - if(31 to 40) - playercount_modifier = 1 //"Medium value" - if(41 to 50) - playercount_modifier = 0.95 - if(51 to 60) - playercount_modifier = 0.90 - if(61 to 70) - playercount_modifier = 0.85 - if(71 to 80) - playercount_modifier = 0.80 - if(81 to INFINITY) - playercount_modifier = 0.75 //At this point it's icing on the cake - //Then, let's slowly ramp up events as the round goes on, SLOWLY I SAID - //world.time is the number of ticks (1/10 of a second) since game start for reference - var/roundlength_modifier = 1 - switch(world.time) - if(0 to 18000) //30 first minutes - roundlength_modifier = 1 //Don't particularly speed up event rate - if(18000 to 36000) //Next thirty minutes - roundlength_modifier = 0.95 //Start ramping up - if(36000 to 54000) - roundlength_modifier = 0.90 - if(54000 to INFINITY) //Round has been going for 1 hour and 30 minutes at least - roundlength_modifier = 0.85 - - var/next_event_delay = rand(eventTimeLower, eventTimeUpper)*playercount_modifier*roundlength_modifier - scheduledEvent = world.timeofday + next_event_delay - message_admins("Random event call. Next event call in [next_event_delay/600] minutes.") - - else if(world.timeofday > scheduledEvent) - spawn_dynamic_event() - - scheduledEvent = null - checkEvent() - -/client/proc/forceEvent(var/type in allEvents) - set name = "Trigger Event (Debug Only)" - set category = "Debug" - - if(!holder) - return - - if(ispath(type)) - new type - message_admins("[key_name_admin(usr)] has triggered an event. ([type])", 1) +var/list/allEvents = typesof(/datum/event) - /datum/event +var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event +//var/list/potentialRandomEvents = typesof(/datum/event) - /datum/event - /datum/event/spider_infestation - /datum/event/alien_infestation + +var/eventTimeLower = 6000 //10 minutes +var/eventTimeUpper = 12000 //20 minutes +var/scheduledEvent = null + +/proc/checkEvent() + if(!scheduledEvent) + //The more players, the merrier + var/playercount_modifier = 1 + switch(player_list.len) + if(0 to 10) + playercount_modifier = 1.25 //At this point even carps could KO the crew + if(11 to 20) + playercount_modifier = 1.15 + if(21 to 30) + playercount_modifier = 1.05 + if(31 to 40) + playercount_modifier = 1 //"Medium value" + if(41 to 50) + playercount_modifier = 0.95 + if(51 to 60) + playercount_modifier = 0.90 + if(61 to 70) + playercount_modifier = 0.85 + if(71 to 80) + playercount_modifier = 0.80 + if(81 to INFINITY) + playercount_modifier = 0.75 //At this point it's icing on the cake + //Then, let's slowly ramp up events as the round goes on, SLOWLY I SAID + //world.time is the number of ticks (1/10 of a second) since game start for reference + var/roundlength_modifier = 1 + switch(world.time) + if(0 to 18000) //30 first minutes + roundlength_modifier = 1 //Don't particularly speed up event rate + if(18000 to 36000) //Next thirty minutes + roundlength_modifier = 0.95 //Start ramping up + if(36000 to 54000) + roundlength_modifier = 0.90 + if(54000 to INFINITY) //Round has been going for 1 hour and 30 minutes at least + roundlength_modifier = 0.85 + + var/next_event_delay = rand(eventTimeLower, eventTimeUpper)*playercount_modifier*roundlength_modifier + scheduledEvent = world.timeofday + next_event_delay + message_admins("Random event call. Next event call in [next_event_delay/600] minutes.") + + else if(world.timeofday > scheduledEvent) + spawn_dynamic_event() + + scheduledEvent = null + checkEvent() + +/client/proc/forceEvent(var/type in allEvents) + set name = "Trigger Event (Debug Only)" + set category = "Debug" + + if(!holder) + return + + if(ispath(type)) + new type + message_admins("[key_name_admin(usr)] has triggered an event. ([type])", 1) diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index aff6753b531..5f65f397920 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -1,51 +1,51 @@ -/datum/event/prison_break - announceWhen = 30 - oneShot = 1 - - var/releaseWhen = 25 - var/list/area/prisonAreas = list() - - -/datum/event/prison_break/setup() - announceWhen = rand(50, 60) - releaseWhen = rand(20, 30) - src.startWhen = src.releaseWhen-1 - src.endWhen = src.releaseWhen+1 - -/datum/event/prison_break/announce() - if(prisonAreas && prisonAreas.len > 0) - command_alert("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") - else - world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area." - kill() - - -/datum/event/prison_break/start() - for(var/area/A in areas) - if(istype(A, /area/security/prison) || istype(A, /area/security/brig)) - prisonAreas += A - - if(prisonAreas && prisonAreas.len > 0) - for(var/area/A in prisonAreas) - for(var/obj/machinery/light/L in A) - L.flicker(10) - -/datum/event/prison_break/tick() - if(activeFor == releaseWhen) - if(prisonAreas && prisonAreas.len > 0) - for(var/area/A in prisonAreas) - for(var/obj/machinery/power/apc/temp_apc in A) - temp_apc.overload_lighting() - - for(var/obj/structure/closet/secure_closet/brig/temp_closet in A) - temp_closet.locked = 0 - temp_closet.icon_state = temp_closet.icon_closed - - for(var/obj/machinery/door/airlock/security/temp_airlock in A) - temp_airlock.prison_open() - - for(var/obj/machinery/door/airlock/glass_security/temp_glassairlock in A) - temp_glassairlock.prison_open() - - for(var/obj/machinery/door_timer/temp_timer in A) +/datum/event/prison_break + announceWhen = 30 + oneShot = 1 + + var/releaseWhen = 25 + var/list/area/prisonAreas = list() + + +/datum/event/prison_break/setup() + announceWhen = rand(50, 60) + releaseWhen = rand(20, 30) + src.startWhen = src.releaseWhen-1 + src.endWhen = src.releaseWhen+1 + +/datum/event/prison_break/announce() + if(prisonAreas && prisonAreas.len > 0) + command_alert("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert") + else + world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area." + kill() + + +/datum/event/prison_break/start() + for(var/area/A in areas) + if(istype(A, /area/security/prison) || istype(A, /area/security/brig)) + prisonAreas += A + + if(prisonAreas && prisonAreas.len > 0) + for(var/area/A in prisonAreas) + for(var/obj/machinery/light/L in A) + L.flicker(10) + +/datum/event/prison_break/tick() + if(activeFor == releaseWhen) + if(prisonAreas && prisonAreas.len > 0) + for(var/area/A in prisonAreas) + for(var/obj/machinery/power/apc/temp_apc in A) + temp_apc.overload_lighting() + + for(var/obj/structure/closet/secure_closet/brig/temp_closet in A) + temp_closet.locked = 0 + temp_closet.icon_state = temp_closet.icon_closed + + for(var/obj/machinery/door/airlock/security/temp_airlock in A) + temp_airlock.prison_open() + + for(var/obj/machinery/door/airlock/glass_security/temp_glassairlock in A) + temp_glassairlock.prison_open() + + for(var/obj/machinery/door_timer/temp_timer in A) temp_timer.releasetime = 1 \ No newline at end of file diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 8adcf4e7039..a3274bcf89f 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -1,82 +1,82 @@ -/datum/event/radiation_storm - announceWhen = 1 - var/safe_zones = list( - /area/maintenance, - /area/crew_quarters/sleep, - /area/security/prison, - /area/security/perma, - /area/security/gas_chamber, - /area/security/brig, - /area/shuttle, - /area/vox_station, - /area/syndicate_station - ) - - -/datum/event/radiation_storm/announce() - // Don't do anything, we want to pack the announcement with the actual event - -/datum/event/radiation_storm/proc/is_safe_zone(var/area/A) - for(var/szt in safe_zones) - if(istype(A, szt)) - return 1 - return 0 - -/datum/event/radiation_storm/start() - spawn() +/datum/event/radiation_storm + announceWhen = 1 + var/safe_zones = list( + /area/maintenance, + /area/crew_quarters/sleep, + /area/security/prison, + /area/security/perma, + /area/security/gas_chamber, + /area/security/brig, + /area/shuttle, + /area/vox_station, + /area/syndicate_station + ) + + +/datum/event/radiation_storm/announce() + // Don't do anything, we want to pack the announcement with the actual event + +/datum/event/radiation_storm/proc/is_safe_zone(var/area/A) + for(var/szt in safe_zones) + if(istype(A, szt)) + return 1 + return 0 + +/datum/event/radiation_storm/start() + spawn() to_chat(world, sound('sound/AI/radiation.ogg')) - command_alert("High levels of radiation detected near the station, ETA in 30 seconds. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert") - - for(var/area/A in areas) - if(A.z != 1 || is_safe_zone(A)) - continue - var/area/ma = get_area_master(A) - ma.radiation_alert() - - make_maint_all_access() - - - sleep(30 SECONDS) - - - command_alert("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert") - - for(var/i = 0, i < 15, i++) - var/irradiationThisBurst = rand(15,25) //everybody gets the same rads this radiation burst - var/randomMutation = prob(50) - var/badMutation = prob(50) - for(var/mob/living/carbon/human/H in living_mob_list) - if(istype(H.loc, /obj/spacepod)) - continue - var/turf/T = get_turf(H) - if(!T) - continue - if(T.z != 1 || is_safe_zone(T.loc)) - continue - - var/applied_rads = (H.apply_effect(irradiationThisBurst,IRRADIATE,0) > (irradiationThisBurst/4)) - if(randomMutation && applied_rads) - if (badMutation) - //H.apply_effect((rand(25,50)),IRRADIATE,0) - randmutb(H) // Applies bad mutation - domutcheck(H,null,MUTCHK_FORCED) - else - randmutg(H) // Applies good mutation - domutcheck(H,null,MUTCHK_FORCED) - - sleep(25) - - - command_alert("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") - - for(var/area/A in areas) - if(A.z != 1 || is_safe_zone(A)) - continue - var/area/ma = get_area_master(A) - ma.reset_radiation_alert() - - - sleep(600) // Want to give them time to get out of maintenance. - - - revoke_maint_all_access() + command_alert("High levels of radiation detected near the station, ETA in 30 seconds. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert") + + for(var/area/A in areas) + if(A.z != 1 || is_safe_zone(A)) + continue + var/area/ma = get_area_master(A) + ma.radiation_alert() + + make_maint_all_access() + + + sleep(30 SECONDS) + + + command_alert("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert") + + for(var/i = 0, i < 15, i++) + var/irradiationThisBurst = rand(15,25) //everybody gets the same rads this radiation burst + var/randomMutation = prob(50) + var/badMutation = prob(50) + for(var/mob/living/carbon/human/H in living_mob_list) + if(istype(H.loc, /obj/spacepod)) + continue + var/turf/T = get_turf(H) + if(!T) + continue + if(T.z != 1 || is_safe_zone(T.loc)) + continue + + var/applied_rads = (H.apply_effect(irradiationThisBurst,IRRADIATE,0) > (irradiationThisBurst/4)) + if(randomMutation && applied_rads) + if (badMutation) + //H.apply_effect((rand(25,50)),IRRADIATE,0) + randmutb(H) // Applies bad mutation + domutcheck(H,null,MUTCHK_FORCED) + else + randmutg(H) // Applies good mutation + domutcheck(H,null,MUTCHK_FORCED) + + sleep(25) + + + command_alert("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert") + + for(var/area/A in areas) + if(A.z != 1 || is_safe_zone(A)) + continue + var/area/ma = get_area_master(A) + ma.reset_radiation_alert() + + + sleep(600) // Want to give them time to get out of maintenance. + + + revoke_maint_all_access() diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 5549b185d0d..0681df4c60b 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -1,11 +1,11 @@ -/var/global/spacevines_spawned = 0 - -/datum/event/spacevine - -/datum/event/spacevine/start() - //biomass is basically just a resprited version of space vines - if(prob(50)) - spacevine_infestation() - else - biomass_infestation() - spacevines_spawned = 1 +/var/global/spacevines_spawned = 0 + +/datum/event/spacevine + +/datum/event/spacevine/start() + //biomass is basically just a resprited version of space vines + if(prob(50)) + spacevine_infestation() + else + biomass_infestation() + spacevines_spawned = 1 diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index 45b17eaf636..1619d9a2a87 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -1,30 +1,30 @@ -/var/global/sent_spiders_to_station = 0 - -/datum/event/spider_infestation - announceWhen = 450 - - var/spawncount = 1 - - -/datum/event/spider_infestation/setup() - announceWhen = rand(300, 600) - spawncount = rand(8, 12) //spiderlings only have a 50% chance to grow big and strong - sent_spiders_to_station = 0 - -/datum/event/spider_infestation/announce() - command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") +/var/global/sent_spiders_to_station = 0 + +/datum/event/spider_infestation + announceWhen = 450 + + var/spawncount = 1 + + +/datum/event/spider_infestation/setup() + announceWhen = rand(300, 600) + spawncount = rand(8, 12) //spiderlings only have a 50% chance to grow big and strong + sent_spiders_to_station = 0 + +/datum/event/spider_infestation/announce() + command_alert("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert") to_chat(world, sound('sound/AI/aliens.ogg')) - - -/datum/event/spider_infestation/start() - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in atmos_machines) - if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) - if(temp_vent.network.normal_members.len > 50) - vents += temp_vent - - while((spawncount >= 1) && vents.len) - var/obj/vent = pick(vents) - new /mob/living/simple_animal/hostile/giant_spider/spiderling(vent.loc) - vents -= vent + + +/datum/event/spider_infestation/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in atmos_machines) + if(temp_vent.loc.z == 1 && !temp_vent.welded && temp_vent.network) + if(temp_vent.network.normal_members.len > 50) + vents += temp_vent + + while((spawncount >= 1) && vents.len) + var/obj/vent = pick(vents) + new /mob/living/simple_animal/hostile/giant_spider/spiderling(vent.loc) + vents -= vent spawncount-- \ No newline at end of file diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm index 6cc4952afff..5281f56878e 100644 --- a/code/modules/events/spontaneous_appendicitis.dm +++ b/code/modules/events/spontaneous_appendicitis.dm @@ -1,15 +1,15 @@ -/datum/event/spontaneous_appendicitis/start() - for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) if(H.client && H.stat != DEAD) - var/foundAlready = 0 //don't infect someone that already has the virus - for(var/datum/disease/D in H.viruses) - foundAlready = 1 - if(H.stat == 2 || foundAlready) - continue - if(H.z == map.zCentcomm) //Don't infect people on the centcomm z-level - continue - - var/datum/disease/D = new /datum/disease/appendicitis - D.holder = H - D.affected_mob = H - H.viruses += D - break +/datum/event/spontaneous_appendicitis/start() + for(var/mob/living/carbon/human/H in shuffle(living_mob_list)) if(H.client && H.stat != DEAD) + var/foundAlready = 0 //don't infect someone that already has the virus + for(var/datum/disease/D in H.viruses) + foundAlready = 1 + if(H.stat == 2 || foundAlready) + continue + if(H.z == map.zCentcomm) //Don't infect people on the centcomm z-level + continue + + var/datum/disease/D = new /datum/disease/appendicitis + D.holder = H + D.affected_mob = H + H.viruses += D + break diff --git a/code/modules/genetics/side_effects.dm b/code/modules/genetics/side_effects.dm index e82bb3457f6..4f881f0b967 100644 --- a/code/modules/genetics/side_effects.dm +++ b/code/modules/genetics/side_effects.dm @@ -1,91 +1,91 @@ -/datum/genetics/side_effect - var/name // name of the side effect, to use as a header in the manual - var/symptom // description of the symptom of the side effect - var/treatment // description of the treatment of the side effect - var/effect // description of what happens when not treated - var/duration = 0 // delay between start() and finish() - - proc/start(mob/living/carbon/human/H) - // start the side effect, this should give some cue as to what's happening, - // such as gasping. These cues need to be unique among side-effects. - - proc/finish(mob/living/carbon/human/H) - // Finish the side-effect. This should first check whether the cure has been - // applied, and if not, cause bad things to happen. - -/datum/genetics/side_effect/genetic_burn - name = "Genetic Burn" - symptom = "Subject's skin turns unusualy red." - treatment = "Inject small dose of dexalin." - effect = "Subject's skin burns." - duration = 10*30 - - start(mob/living/carbon/human/H) - H.emote("me", 1, "starts turning very red..") - - finish(mob/living/carbon/human/H) - if(!H.reagents.has_reagent("dexalin")) - for(var/organ_name in list("chest","l_arm","r_arm","r_leg","l_leg","head","groin")) - var/datum/organ/external/E = H.get_organ(organ_name) - E.take_damage(0, 5, 0) - -/datum/genetics/side_effect/bone_snap - name = "Bone Snap" - symptom = "Subject's limbs tremble notably." - treatment = "Inject small dose of bicaridine." - effect = "Subject's bone breaks." - duration = 10*60 - - start(mob/living/carbon/human/H) - H.emote("me", 1, "'s limbs start shivering uncontrollably.") - - finish(mob/living/carbon/human/H) - if(!H.reagents.has_reagent("bicaridine")) - var/organ_name = pick("chest","l_arm","r_arm","r_leg","l_leg","head","groin") - var/datum/organ/external/E = H.get_organ(organ_name) - E.take_damage(20, 0, 0) - E.fracture() - -/*/datum/genetics/side_effect/monkey - name = "Monkey" - symptom = "Subject starts drooling uncontrollably." - treatment = "Inject small dose of dylovene." - effect = "Subject turns into monkey." - duration = 10*90 - - start(mob/living/carbon/human/H) - H.emote("me", 1, "has drool running down from his mouth.") - - finish(mob/living/carbon/human/H) - if(!H.reagents.has_reagent("anti_toxin")) - H.monkeyize()**/ - -/datum/genetics/side_effect/confuse - name = "Confuse" - symptom = "Subject starts drooling uncontrollably." - treatment = "Inject small dose of dylovene." - effect = "Subject becomes confused." - duration = 10*30 - - start(mob/living/carbon/human/H) - H.emote("me", 1, "has drool running down from his mouth.") - - finish(mob/living/carbon/human/H) - if(!H.reagents.has_reagent("anti_toxin")) - H.confused += 100 - -proc/trigger_side_effect(mob/living/carbon/human/H) - spawn - if(!istype(H)) return - var/tp = pick(typesof(/datum/genetics/side_effect) - /datum/genetics/side_effect) - var/datum/genetics/side_effect/S = new tp - - S.start(H) - spawn(20) - if(!istype(H)) return - H.Weaken(rand(0, S.duration / 50)) - sleep(S.duration) - - if(!istype(H)) return - H.SetWeakened(0) +/datum/genetics/side_effect + var/name // name of the side effect, to use as a header in the manual + var/symptom // description of the symptom of the side effect + var/treatment // description of the treatment of the side effect + var/effect // description of what happens when not treated + var/duration = 0 // delay between start() and finish() + + proc/start(mob/living/carbon/human/H) + // start the side effect, this should give some cue as to what's happening, + // such as gasping. These cues need to be unique among side-effects. + + proc/finish(mob/living/carbon/human/H) + // Finish the side-effect. This should first check whether the cure has been + // applied, and if not, cause bad things to happen. + +/datum/genetics/side_effect/genetic_burn + name = "Genetic Burn" + symptom = "Subject's skin turns unusualy red." + treatment = "Inject small dose of dexalin." + effect = "Subject's skin burns." + duration = 10*30 + + start(mob/living/carbon/human/H) + H.emote("me", 1, "starts turning very red..") + + finish(mob/living/carbon/human/H) + if(!H.reagents.has_reagent("dexalin")) + for(var/organ_name in list("chest","l_arm","r_arm","r_leg","l_leg","head","groin")) + var/datum/organ/external/E = H.get_organ(organ_name) + E.take_damage(0, 5, 0) + +/datum/genetics/side_effect/bone_snap + name = "Bone Snap" + symptom = "Subject's limbs tremble notably." + treatment = "Inject small dose of bicaridine." + effect = "Subject's bone breaks." + duration = 10*60 + + start(mob/living/carbon/human/H) + H.emote("me", 1, "'s limbs start shivering uncontrollably.") + + finish(mob/living/carbon/human/H) + if(!H.reagents.has_reagent("bicaridine")) + var/organ_name = pick("chest","l_arm","r_arm","r_leg","l_leg","head","groin") + var/datum/organ/external/E = H.get_organ(organ_name) + E.take_damage(20, 0, 0) + E.fracture() + +/*/datum/genetics/side_effect/monkey + name = "Monkey" + symptom = "Subject starts drooling uncontrollably." + treatment = "Inject small dose of dylovene." + effect = "Subject turns into monkey." + duration = 10*90 + + start(mob/living/carbon/human/H) + H.emote("me", 1, "has drool running down from his mouth.") + + finish(mob/living/carbon/human/H) + if(!H.reagents.has_reagent("anti_toxin")) + H.monkeyize()**/ + +/datum/genetics/side_effect/confuse + name = "Confuse" + symptom = "Subject starts drooling uncontrollably." + treatment = "Inject small dose of dylovene." + effect = "Subject becomes confused." + duration = 10*30 + + start(mob/living/carbon/human/H) + H.emote("me", 1, "has drool running down from his mouth.") + + finish(mob/living/carbon/human/H) + if(!H.reagents.has_reagent("anti_toxin")) + H.confused += 100 + +proc/trigger_side_effect(mob/living/carbon/human/H) + spawn + if(!istype(H)) return + var/tp = pick(typesof(/datum/genetics/side_effect) - /datum/genetics/side_effect) + var/datum/genetics/side_effect/S = new tp + + S.start(H) + spawn(20) + if(!istype(H)) return + H.Weaken(rand(0, S.duration / 50)) + sleep(S.duration) + + if(!istype(H)) return + H.SetWeakened(0) S.finish(H) \ No newline at end of file diff --git a/code/modules/hydroponics/eggincubator.dm b/code/modules/hydroponics/eggincubator.dm index 68272a68b1e..cf5209fbd7e 100644 --- a/code/modules/hydroponics/eggincubator.dm +++ b/code/modules/hydroponics/eggincubator.dm @@ -1,109 +1,109 @@ -/obj/machinery/egg_incubator - name = "egg incubator" - icon = 'icons/obj/virology.dmi' - icon_state = "incubator" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 500 - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL - flags = OPENCONTAINER | NOREACT - pass_flags = PASSTABLE - var/list/egg_storage = list() - var/limit = 1 - var/speed_bonus = 0 - -/obj/machinery/egg_incubator/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/egg_incubator, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/matter_bin - ) - - RefreshParts() - -/obj/machinery/egg_incubator/RefreshParts() - var/bincount = 0 - var/capcount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/capacitor)) capcount += SP.rating-1 - if(istype(SP, /obj/item/weapon/stock_parts/matter_bin)) bincount += SP.rating - limit = bincount - speed_bonus = round(capcount/2,1) - -/obj/machinery/egg_incubator/update_icon() - if(use_power==2) - icon_state = "incubator_on" - else - icon_state = "incubator" - -/obj/machinery/egg_incubator/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(..()) - return 1 - if(contents.len >= limit) +/obj/machinery/egg_incubator + name = "egg incubator" + icon = 'icons/obj/virology.dmi' + icon_state = "incubator" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 500 + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL + flags = OPENCONTAINER | NOREACT + pass_flags = PASSTABLE + var/list/egg_storage = list() + var/limit = 1 + var/speed_bonus = 0 + +/obj/machinery/egg_incubator/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/egg_incubator, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/matter_bin + ) + + RefreshParts() + +/obj/machinery/egg_incubator/RefreshParts() + var/bincount = 0 + var/capcount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/capacitor)) capcount += SP.rating-1 + if(istype(SP, /obj/item/weapon/stock_parts/matter_bin)) bincount += SP.rating + limit = bincount + speed_bonus = round(capcount/2,1) + +/obj/machinery/egg_incubator/update_icon() + if(use_power==2) + icon_state = "incubator_on" + else + icon_state = "incubator" + +/obj/machinery/egg_incubator/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(..()) + return 1 + if(contents.len >= limit) to_chat(user, "\The [src] has no more space for eggs!") - return 1 - if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg)) - if(animal_count[/mob/living/simple_animal/chicken] >= ANIMAL_CHILD_CAP) + return 1 + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/egg)) + if(animal_count[/mob/living/simple_animal/chicken] >= ANIMAL_CHILD_CAP) to_chat(user, "You get the feeling there are enough chickens already.") - return 1 - if(user.drop_item(O, src)) - user.visible_message( \ - "\The [user] has added \the [O] to \the [src].", \ - "You add \the [O] to \the [src].") - src.updateUsrDialog() - -/obj/machinery/egg_incubator/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/egg_incubator/attack_ai(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/egg_incubator/attack_hand(mob/user as mob) - if(..()) return 1 - user.set_machine(src) - interact(user) - -/obj/machinery/egg_incubator/interact(mob/user as mob) // The microwave Menu - var/dat = "" - var/counter = 0 - if(!(contents.len)) - dat += "\The [src] is empty." - for (var/obj/item/weapon/reagent_containers/food/snacks/egg/E in contents) - counter++ - dat += "Egg [counter]: [E.amount_grown]% grown. (Eject)
    " - - user << browse("Egg Incubator[dat]", "window=egg_incubator") - onclose(user, "egg_incubator") - -/obj/machinery/egg_incubator/Topic(href, href_list) - if(..()) return 1 - var/obj/item/weapon/reagent_containers/food/snacks/egg/E = locate(href_list["egg"]) - if(!istype(E)) return //How did we get here at all? - eject(E) - -/obj/machinery/egg_incubator/process() - ..() - if(!(contents.len)) - use_power = 1 - update_icon() - return - use_power = 2 - update_icon() - for(var/obj/item/weapon/reagent_containers/food/snacks/egg/E in contents) - E.amount_grown += rand(2,3)+speed_bonus - if(E.amount_grown>=100) - eject(E) - E.hatch() - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) - src.updateUsrDialog() - -/obj/machinery/egg_incubator/proc/eject(var/obj/E) - if(E.loc != src) return //You can't eject it if it's not here. - E.forceMove(get_turf(src)) - src.updateUsrDialog() - visible_message("An egg was ejected from \the [src].") + return 1 + if(user.drop_item(O, src)) + user.visible_message( \ + "\The [user] has added \the [O] to \the [src].", \ + "You add \the [O] to \the [src].") + src.updateUsrDialog() + +/obj/machinery/egg_incubator/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/egg_incubator/attack_ai(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/egg_incubator/attack_hand(mob/user as mob) + if(..()) return 1 + user.set_machine(src) + interact(user) + +/obj/machinery/egg_incubator/interact(mob/user as mob) // The microwave Menu + var/dat = "" + var/counter = 0 + if(!(contents.len)) + dat += "\The [src] is empty." + for (var/obj/item/weapon/reagent_containers/food/snacks/egg/E in contents) + counter++ + dat += "Egg [counter]: [E.amount_grown]% grown. (Eject)
    " + + user << browse("Egg Incubator[dat]", "window=egg_incubator") + onclose(user, "egg_incubator") + +/obj/machinery/egg_incubator/Topic(href, href_list) + if(..()) return 1 + var/obj/item/weapon/reagent_containers/food/snacks/egg/E = locate(href_list["egg"]) + if(!istype(E)) return //How did we get here at all? + eject(E) + +/obj/machinery/egg_incubator/process() + ..() + if(!(contents.len)) + use_power = 1 + update_icon() + return + use_power = 2 + update_icon() + for(var/obj/item/weapon/reagent_containers/food/snacks/egg/E in contents) + E.amount_grown += rand(2,3)+speed_bonus + if(E.amount_grown>=100) + eject(E) + E.hatch() + playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + src.updateUsrDialog() + +/obj/machinery/egg_incubator/proc/eject(var/obj/E) + if(E.loc != src) return //You can't eject it if it's not here. + E.forceMove(get_turf(src)) + src.updateUsrDialog() + visible_message("An egg was ejected from \the [src].") diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index c854859e706..d4380ef2923 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -1,365 +1,365 @@ -/* Library Items - * - * Contains: - * Bookcase - * Book - * Barcode Scanner - */ - - -/* - * Bookcase - */ - -/obj/structure/bookcase - name = "bookcase" - icon = 'icons/obj/library.dmi' - icon_state = "book-0" - anchored = 1 - density = 1 - opacity = 1 - autoignition_temperature = AUTOIGNITION_WOOD - fire_fuel = 10 - - var/health = 50 - var/tmp/busy = 0 - var/list/valid_types = list(/obj/item/weapon/book, \ - /obj/item/weapon/tome, \ - /obj/item/weapon/spellbook, \ - /obj/item/weapon/storage/bible) - -/obj/structure/bookcase/cultify() - return - -/obj/structure/bookcase/initialize() - for(var/obj/item/I in loc) - if(is_type_in_list(I, valid_types)) - I.forceMove(src) - update_icon() - -/obj/structure/bookcase/proc/healthcheck() - - if(health <= 0) - visible_message("\The [src] breaks apart!") - getFromPool(/obj/item/stack/sheet/wood, get_turf(src), 3) - qdel(src) - -/obj/structure/bookcase/attackby(obj/O as obj, mob/user as mob) - if(busy) //So that you can't mess with it while deconstructing - return - if(is_type_in_list(O, valid_types)) - user.drop_item(O, src) - update_icon() - else if(isscrewdriver(O) && user.a_intent == I_HELP) //They're probably trying to open the "maintenance panel" to deconstruct it. Let them know what's wrong. - to_chat(user, "There are no screws on \the [src], it appears to be nailed together. You could probably disassemble it with just a crowbar.") - return - else if(iscrowbar(O) && user.a_intent == I_HELP) //Only way to deconstruct, needs help intent - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) - user.visible_message("[user] starts disassembling \the [src].", \ - "You start disassembling \the [src].") - busy = 1 - - if(do_after(user, src, 50)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1) - user.visible_message("[user] disassembles \the [src].", \ - "You disassemble \the [src].") - busy = 0 - getFromPool(/obj/item/stack/sheet/wood, get_turf(src), 5) - qdel(src) - return - else - busy = 0 - return - else if(iswrench(O)) - anchored = !anchored - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - user.visible_message("[user] [anchored ? "":"un"]anchors \the [src] [anchored ? "to":"from"] the floor.", \ - "You [anchored ? "":"un"]anchor the [src] [anchored ? "to":"from"] the floor.") - else if(istype(O, /obj/item/weapon/pen)) - var/newname = stripped_input(user, "What category title would you like to give to this [name]?") - if(!newname) - return - else - name = ("bookcase ([sanitize(newname)])") - else if(O.damtype == BRUTE || O.damtype == BURN) - user.delayNextAttack(10) //We are attacking the bookshelf - health -= O.force - user.visible_message("\The [user] hits \the [src] with \the [O].", \ - "You hit \the [src] with \the [O].") - healthcheck() - else - return ..() //Weapon checks for weapons without brute or burn damage type and grab check - -/obj/structure/bookcase/attack_hand(var/mob/user as mob) - if(contents.len) - var/obj/item/weapon/book/choice = input("Which book would you like to remove from \the [src]?") as null|obj in contents - if(choice) - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting || get_dist(user, src) > 1) - return - if(!user.get_active_hand()) - user.put_in_hands(choice) - else - choice.forceMove(get_turf(src)) - update_icon() - -/obj/structure/bookcase/attack_ghost(mob/dead/observer/user as mob) - if(contents.len && in_range(user, src)) - var/obj/item/weapon/book/choice = input("Which book would you like to read?") as null|obj in contents - if(choice) - if(!istype(choice)) //spellbook, cult tome, or the one weird bible storage - to_chat(user,"A mysterious force is keeping you from reading that.") - return - choice.read_a_motherfucking_book(user) - -/obj/structure/bookcase/ex_act(severity) - switch(severity) - if(1.0) - for(var/obj/item/I in contents) - qdel(I) - qdel(src) - return - if(2.0) - for(var/obj/item/I in contents) - if(prob(50)) - qdel(I) - qdel(src) - return - if(3.0) - if(prob(50)) - qdel(src) - return - return - -/obj/structure/bookcase/Destroy() - - for(var/obj/item/I in contents) - if(is_type_in_list(I, valid_types)) - I.forceMove(get_turf(src)) - ..() - -/obj/structure/bookcase/update_icon() - if(contents.len < 5) - icon_state = "book-[contents.len]" - else - icon_state = "book-5" - -/obj/structure/bookcase/manuals/medical - name = "Medical Manuals bookcase" - - New() - ..() - new /obj/item/weapon/book/manual/medical_cloning(src) - update_icon() - - -/obj/structure/bookcase/manuals/engineering - name = "Engineering Manuals bookcase" - - New() - ..() - new /obj/item/weapon/book/manual/engineering_construction(src) - new /obj/item/weapon/book/manual/engineering_particle_accelerator(src) - new /obj/item/weapon/book/manual/engineering_hacking(src) - new /obj/item/weapon/book/manual/engineering_guide(src) - new /obj/item/weapon/book/manual/engineering_singularity_safety(src) - new /obj/item/weapon/book/manual/robotics_cyborgs(src) - update_icon() - -/obj/structure/bookcase/manuals/research_and_development - name = "R&D Manuals bookcase" - - New() - ..() - new /obj/item/weapon/book/manual/research_and_development(src) - update_icon() - - -/* - * Book - */ -/obj/item/weapon/book - name = "book" - icon = 'icons/obj/library.dmi' - icon_state ="book" - throw_speed = 1 - throw_range = 5 - w_class = 3 //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) - flags = FPRINT - attack_verb = list("bashed", "whacked", "educated") - - autoignition_temperature = AUTOIGNITION_PAPER - fire_fuel = 3 - - var/dat // Actual page content - var/due_date = 0 // Game time in 1/10th seconds - var/author // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - var/unique = 0 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified - var/title // The real name of the book. - var/carved = 0 // Has the book been hollowed out for use as a secret storage item? - var/wiki_page // Title of the book's wiki page. - var/forbidden = 0 // Prevent ordering of this book. (0=no, 1=yes, 2=emag only) - var/obj/item/store // What's in the book? - -/obj/item/weapon/book/New() - ..() - if(wiki_page) - dat = {" - - - - - - "} - -/obj/item/weapon/book/cultify() - new /obj/item/weapon/tome(loc) - ..() - -/obj/item/weapon/book/proc/read_a_motherfucking_book(mob/user) - if(carved) - to_chat(user, "The pages of [title] have been cut out!") - return - if(src.dat) - user << browse("Penned by [author].
    " + "[dat]", "window=book") - if(!isobserver(user)) - user.visible_message("[user] opens a book titled \"[src.title]\" and begins reading intently.") - onclose(user, "book") - else - to_chat(user, "This book is completely blank!") - -/obj/item/weapon/book/attack_self(var/mob/user as mob) - if(store) - to_chat(user, "[store] falls out of [title]!") - store.forceMove(get_turf(src)) - store = null - return - read_a_motherfucking_book(user) - -/obj/item/weapon/book/examine(mob/user) - if(isobserver(user) && in_range(src,user)) - read_a_motherfucking_book(user) - else - ..() - -/obj/item/weapon/book/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(carved) - if(!store) - if(W.w_class < 3) - if(user.drop_item(W, src)) - store = W - to_chat(user, "You put [W] in [title].") - return - else - to_chat(user, "[W] won't fit in [title].") - return - else - to_chat(user, "There's already something in [title]!") - return - if(istype(W, /obj/item/weapon/pen)) - if(unique) - to_chat(user, "These pages don't seem to take the ink well. Looks like you can't modify it.") - return - var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel") - switch(choice) - if("Title") - var/newtitle = reject_bad_text(stripped_input(usr, "Write a new title:")) - if(!newtitle) - to_chat(usr, "The title is invalid.") - return - else - src.name = newtitle - src.title = newtitle - if("Contents") - var/content = sanitize(input(usr, "Write your book's contents (HTML NOT allowed):") as message|null) - if(!content) - to_chat(usr, "The content is invalid.") - return - else - src.dat += content - if("Author") - var/newauthor = stripped_input(usr, "Write the author's name:") - if(!newauthor) - to_chat(usr, "The name is invalid.") - return - else - src.author = newauthor - else - return - else if(istype(W, /obj/item/weapon/barcodescanner)) - var/obj/item/weapon/barcodescanner/scanner = W - if(!scanner.computer) - to_chat(user, "[W]'s screen flashes: 'No associated computer found!'") - else - switch(scanner.mode) - if(0) - scanner.book = src - to_chat(user, "[W]'s screen flashes: 'Book stored in buffer.'") - if(1) - scanner.book = src - scanner.computer.buffer_book = src.name - to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Book title stored in associated computer buffer.'") - if(2) - scanner.book = src - for(var/datum/borrowbook/b in scanner.computer.checkouts) - if(b.bookname == src.name) - scanner.computer.checkouts.Remove(b) - to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Book has been checked in.'") - return - to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. No active check-out record found for current title.'") - if(3) - scanner.book = src - for(var/obj/item/weapon/book in scanner.computer.inventory) - if(book == src) - to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title already present in inventory, aborting to avoid duplicate entry.'") - return - scanner.computer.inventory.Add(src) - to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'") - else if(istype(W, /obj/item/weapon/kitchen/utensil/knife/large) || istype(W, /obj/item/weapon/wirecutters)) - if(carved) return - to_chat(user, "You begin to carve out [title].") - if(do_after(user, src, 30)) - to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") - carved = 1 - return - else - ..() - - -/* - * Barcode Scanner - */ -/obj/item/weapon/barcodescanner - name = "barcode scanner" - icon = 'icons/obj/library.dmi' - icon_state ="scanner" - throw_speed = 1 - throw_range = 5 - w_class = 1.0 - flags = FPRINT - var/obj/machinery/computer/library/checkout/computer // Associated computer - Modes 1 to 3 use this - var/obj/item/weapon/book/book // Currently scanned book - var/mode = 0 // 0 - Scan only, 1 - Scan and Set Buffer, 2 - Scan and Attempt to Check In, 3 - Scan and Attempt to Add to Inventory - - attack_self(mob/user as mob) - mode += 1 - if(mode > 3) - mode = 0 - to_chat(user, "[src] Status Display:") - var/modedesc - switch(mode) - if(0) - modedesc = "Scan book to local buffer." - if(1) - modedesc = "Scan book to local buffer and set associated computer buffer to match." - if(2) - modedesc = "Scan book to local buffer, attempt to check in scanned book." - if(3) - modedesc = "Scan book to local buffer, attempt to add book to general inventory." - else - modedesc = "ERROR" - to_chat(user, " - Mode [mode] : [modedesc]") - if(src.computer) - to_chat(user, "Computer has been associated with this unit.") - else - to_chat(user, "No associated computer found. Only local scans will function properly.") - to_chat(user, "\n") +/* Library Items + * + * Contains: + * Bookcase + * Book + * Barcode Scanner + */ + + +/* + * Bookcase + */ + +/obj/structure/bookcase + name = "bookcase" + icon = 'icons/obj/library.dmi' + icon_state = "book-0" + anchored = 1 + density = 1 + opacity = 1 + autoignition_temperature = AUTOIGNITION_WOOD + fire_fuel = 10 + + var/health = 50 + var/tmp/busy = 0 + var/list/valid_types = list(/obj/item/weapon/book, \ + /obj/item/weapon/tome, \ + /obj/item/weapon/spellbook, \ + /obj/item/weapon/storage/bible) + +/obj/structure/bookcase/cultify() + return + +/obj/structure/bookcase/initialize() + for(var/obj/item/I in loc) + if(is_type_in_list(I, valid_types)) + I.forceMove(src) + update_icon() + +/obj/structure/bookcase/proc/healthcheck() + + if(health <= 0) + visible_message("\The [src] breaks apart!") + getFromPool(/obj/item/stack/sheet/wood, get_turf(src), 3) + qdel(src) + +/obj/structure/bookcase/attackby(obj/O as obj, mob/user as mob) + if(busy) //So that you can't mess with it while deconstructing + return + if(is_type_in_list(O, valid_types)) + user.drop_item(O, src) + update_icon() + else if(isscrewdriver(O) && user.a_intent == I_HELP) //They're probably trying to open the "maintenance panel" to deconstruct it. Let them know what's wrong. + to_chat(user, "There are no screws on \the [src], it appears to be nailed together. You could probably disassemble it with just a crowbar.") + return + else if(iscrowbar(O) && user.a_intent == I_HELP) //Only way to deconstruct, needs help intent + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + user.visible_message("[user] starts disassembling \the [src].", \ + "You start disassembling \the [src].") + busy = 1 + + if(do_after(user, src, 50)) + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1) + user.visible_message("[user] disassembles \the [src].", \ + "You disassemble \the [src].") + busy = 0 + getFromPool(/obj/item/stack/sheet/wood, get_turf(src), 5) + qdel(src) + return + else + busy = 0 + return + else if(iswrench(O)) + anchored = !anchored + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + user.visible_message("[user] [anchored ? "":"un"]anchors \the [src] [anchored ? "to":"from"] the floor.", \ + "You [anchored ? "":"un"]anchor the [src] [anchored ? "to":"from"] the floor.") + else if(istype(O, /obj/item/weapon/pen)) + var/newname = stripped_input(user, "What category title would you like to give to this [name]?") + if(!newname) + return + else + name = ("bookcase ([sanitize(newname)])") + else if(O.damtype == BRUTE || O.damtype == BURN) + user.delayNextAttack(10) //We are attacking the bookshelf + health -= O.force + user.visible_message("\The [user] hits \the [src] with \the [O].", \ + "You hit \the [src] with \the [O].") + healthcheck() + else + return ..() //Weapon checks for weapons without brute or burn damage type and grab check + +/obj/structure/bookcase/attack_hand(var/mob/user as mob) + if(contents.len) + var/obj/item/weapon/book/choice = input("Which book would you like to remove from \the [src]?") as null|obj in contents + if(choice) + if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting || get_dist(user, src) > 1) + return + if(!user.get_active_hand()) + user.put_in_hands(choice) + else + choice.forceMove(get_turf(src)) + update_icon() + +/obj/structure/bookcase/attack_ghost(mob/dead/observer/user as mob) + if(contents.len && in_range(user, src)) + var/obj/item/weapon/book/choice = input("Which book would you like to read?") as null|obj in contents + if(choice) + if(!istype(choice)) //spellbook, cult tome, or the one weird bible storage + to_chat(user,"A mysterious force is keeping you from reading that.") + return + choice.read_a_motherfucking_book(user) + +/obj/structure/bookcase/ex_act(severity) + switch(severity) + if(1.0) + for(var/obj/item/I in contents) + qdel(I) + qdel(src) + return + if(2.0) + for(var/obj/item/I in contents) + if(prob(50)) + qdel(I) + qdel(src) + return + if(3.0) + if(prob(50)) + qdel(src) + return + return + +/obj/structure/bookcase/Destroy() + + for(var/obj/item/I in contents) + if(is_type_in_list(I, valid_types)) + I.forceMove(get_turf(src)) + ..() + +/obj/structure/bookcase/update_icon() + if(contents.len < 5) + icon_state = "book-[contents.len]" + else + icon_state = "book-5" + +/obj/structure/bookcase/manuals/medical + name = "Medical Manuals bookcase" + + New() + ..() + new /obj/item/weapon/book/manual/medical_cloning(src) + update_icon() + + +/obj/structure/bookcase/manuals/engineering + name = "Engineering Manuals bookcase" + + New() + ..() + new /obj/item/weapon/book/manual/engineering_construction(src) + new /obj/item/weapon/book/manual/engineering_particle_accelerator(src) + new /obj/item/weapon/book/manual/engineering_hacking(src) + new /obj/item/weapon/book/manual/engineering_guide(src) + new /obj/item/weapon/book/manual/engineering_singularity_safety(src) + new /obj/item/weapon/book/manual/robotics_cyborgs(src) + update_icon() + +/obj/structure/bookcase/manuals/research_and_development + name = "R&D Manuals bookcase" + + New() + ..() + new /obj/item/weapon/book/manual/research_and_development(src) + update_icon() + + +/* + * Book + */ +/obj/item/weapon/book + name = "book" + icon = 'icons/obj/library.dmi' + icon_state ="book" + throw_speed = 1 + throw_range = 5 + w_class = 3 //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) + flags = FPRINT + attack_verb = list("bashed", "whacked", "educated") + + autoignition_temperature = AUTOIGNITION_PAPER + fire_fuel = 3 + + var/dat // Actual page content + var/due_date = 0 // Game time in 1/10th seconds + var/author // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + var/unique = 0 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified + var/title // The real name of the book. + var/carved = 0 // Has the book been hollowed out for use as a secret storage item? + var/wiki_page // Title of the book's wiki page. + var/forbidden = 0 // Prevent ordering of this book. (0=no, 1=yes, 2=emag only) + var/obj/item/store // What's in the book? + +/obj/item/weapon/book/New() + ..() + if(wiki_page) + dat = {" + + + + + + "} + +/obj/item/weapon/book/cultify() + new /obj/item/weapon/tome(loc) + ..() + +/obj/item/weapon/book/proc/read_a_motherfucking_book(mob/user) + if(carved) + to_chat(user, "The pages of [title] have been cut out!") + return + if(src.dat) + user << browse("Penned by [author].
    " + "[dat]", "window=book") + if(!isobserver(user)) + user.visible_message("[user] opens a book titled \"[src.title]\" and begins reading intently.") + onclose(user, "book") + else + to_chat(user, "This book is completely blank!") + +/obj/item/weapon/book/attack_self(var/mob/user as mob) + if(store) + to_chat(user, "[store] falls out of [title]!") + store.forceMove(get_turf(src)) + store = null + return + read_a_motherfucking_book(user) + +/obj/item/weapon/book/examine(mob/user) + if(isobserver(user) && in_range(src,user)) + read_a_motherfucking_book(user) + else + ..() + +/obj/item/weapon/book/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(carved) + if(!store) + if(W.w_class < 3) + if(user.drop_item(W, src)) + store = W + to_chat(user, "You put [W] in [title].") + return + else + to_chat(user, "[W] won't fit in [title].") + return + else + to_chat(user, "There's already something in [title]!") + return + if(istype(W, /obj/item/weapon/pen)) + if(unique) + to_chat(user, "These pages don't seem to take the ink well. Looks like you can't modify it.") + return + var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel") + switch(choice) + if("Title") + var/newtitle = reject_bad_text(stripped_input(usr, "Write a new title:")) + if(!newtitle) + to_chat(usr, "The title is invalid.") + return + else + src.name = newtitle + src.title = newtitle + if("Contents") + var/content = sanitize(input(usr, "Write your book's contents (HTML NOT allowed):") as message|null) + if(!content) + to_chat(usr, "The content is invalid.") + return + else + src.dat += content + if("Author") + var/newauthor = stripped_input(usr, "Write the author's name:") + if(!newauthor) + to_chat(usr, "The name is invalid.") + return + else + src.author = newauthor + else + return + else if(istype(W, /obj/item/weapon/barcodescanner)) + var/obj/item/weapon/barcodescanner/scanner = W + if(!scanner.computer) + to_chat(user, "[W]'s screen flashes: 'No associated computer found!'") + else + switch(scanner.mode) + if(0) + scanner.book = src + to_chat(user, "[W]'s screen flashes: 'Book stored in buffer.'") + if(1) + scanner.book = src + scanner.computer.buffer_book = src.name + to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Book title stored in associated computer buffer.'") + if(2) + scanner.book = src + for(var/datum/borrowbook/b in scanner.computer.checkouts) + if(b.bookname == src.name) + scanner.computer.checkouts.Remove(b) + to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Book has been checked in.'") + return + to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. No active check-out record found for current title.'") + if(3) + scanner.book = src + for(var/obj/item/weapon/book in scanner.computer.inventory) + if(book == src) + to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title already present in inventory, aborting to avoid duplicate entry.'") + return + scanner.computer.inventory.Add(src) + to_chat(user, "[W]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'") + else if(istype(W, /obj/item/weapon/kitchen/utensil/knife/large) || istype(W, /obj/item/weapon/wirecutters)) + if(carved) return + to_chat(user, "You begin to carve out [title].") + if(do_after(user, src, 30)) + to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") + carved = 1 + return + else + ..() + + +/* + * Barcode Scanner + */ +/obj/item/weapon/barcodescanner + name = "barcode scanner" + icon = 'icons/obj/library.dmi' + icon_state ="scanner" + throw_speed = 1 + throw_range = 5 + w_class = 1.0 + flags = FPRINT + var/obj/machinery/computer/library/checkout/computer // Associated computer - Modes 1 to 3 use this + var/obj/item/weapon/book/book // Currently scanned book + var/mode = 0 // 0 - Scan only, 1 - Scan and Set Buffer, 2 - Scan and Attempt to Check In, 3 - Scan and Attempt to Add to Inventory + + attack_self(mob/user as mob) + mode += 1 + if(mode > 3) + mode = 0 + to_chat(user, "[src] Status Display:") + var/modedesc + switch(mode) + if(0) + modedesc = "Scan book to local buffer." + if(1) + modedesc = "Scan book to local buffer and set associated computer buffer to match." + if(2) + modedesc = "Scan book to local buffer, attempt to check in scanned book." + if(3) + modedesc = "Scan book to local buffer, attempt to add book to general inventory." + else + modedesc = "ERROR" + to_chat(user, " - Mode [mode] : [modedesc]") + if(src.computer) + to_chat(user, "Computer has been associated with this unit.") + else + to_chat(user, "No associated computer found. Only local scans will function properly.") + to_chat(user, "\n") diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 174c90b6f3c..33b648c8a8d 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -1,206 +1,206 @@ -/* Library Machines - * - * Contains: - * Borrowbook datum - * Cachedbook datum from tkdrg, thanks - * Library Public Computer - * Library Computer - * Library Scanner - * Book Binder - */ - - #define LIBRARY_BOOKS_PER_PAGE 25 - -/* - * Borrowbook datum - */ -/datum/borrowbook // Datum used to keep track of who has borrowed what when and for how long. - var/bookname - var/mobname - var/getdate - var/duedate - -/* - * Cachedbook datum - */ -/datum/cachedbook // Datum used to cache the SQL DB books locally in order to achieve a performance gain. - var/id - var/title - var/author - var/ckey // ADDED 24/2/2015 - N3X - var/category - var/content - var/programmatic=0 // Is the book programmatically added to the catalog? - var/forbidden=0 - var/path = /obj/item/weapon/book // Type path of the book to generate - -/datum/cachedbook/proc/LoadFromRow(var/list/row) - id = row["id"] - author = row["author"] - title = row["title"] - category = row["category"] - ckey = row["ckey"] - if("content" in row) - content = row["content"] - programmatic=0 - -// Builds a SQL statement -/datum/library_query - var/author - var/category - var/title - -/datum/library_query/proc/toSQL() - var/list/where = list() - if(author || title || category) - if(author) - where.Add("author LIKE '%[sanitizeSQL(author)]%'") - if(category) - where.Add("category = '[sanitizeSQL(category)]'") - if(title) - where.Add("title LIKE '%[sanitizeSQL(title)]%'") - return " WHERE "+list2text(where," AND ") - return "" - -// So we can have catalogs of books that are programmatic, and ones that aren't. -/datum/library_catalog - var/list/cached_books = list() - -/datum/library_catalog/proc/initialize() - var/newid=1 - for(var/typepath in typesof(/obj/item/weapon/book/manual)-/obj/item/weapon/book/manual) - var/obj/item/weapon/book/B = new typepath(null) - var/datum/cachedbook/CB = new() - CB.forbidden=B.forbidden - CB.title = B.name - CB.author = B.author - CB.programmatic=1 - CB.path=typepath - CB.id = "M[newid]" - newid++ - cached_books["[CB.id]"]=CB - - -/datum/library_catalog/proc/rmBookByID(var/mob/user, var/id as text) - if("[id]" in cached_books) - var/datum/cachedbook/CB = cached_books["[id]"] - if(CB.programmatic) - to_chat(user, "That book cannot be removed from the system, as it does not actually exist in the database.") - return - - var/sqlid = text2num(id) - if(!sqlid) - return - var/DBQuery/query = dbcon_old.NewQuery("DELETE FROM library WHERE id=[sqlid]") - query.Execute() - -/datum/library_catalog/proc/getBookByID(var/id as text) - if("[id]" in cached_books) - return cached_books["[id]"] - - var/sqlid = text2num(id) - if(!sqlid) - return - var/DBQuery/query = dbcon_old.NewQuery("SELECT id, author, title, category, ckey FROM library WHERE id=[sqlid]") - query.Execute() - - var/list/results=list() - while(query.NextRow()) - var/datum/cachedbook/CB = new() - CB.LoadFromRow(list( - "id" =query.item[1], - "author" =query.item[2], - "title" =query.item[3], - "category"=query.item[4], - "ckey" =query.item[5] - )) - results += CB - cached_books["[id]"]=CB - return CB - return results - -var/global/datum/library_catalog/library_catalog = new() - -var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion") - -/** Scanner **/ -/obj/machinery/libraryscanner - name = "scanner" - icon = 'icons/obj/library.dmi' - icon_state = "bigscanner" - anchored = 1 - density = 1 - var/obj/item/weapon/book/cache // Last scanned book - - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/libraryscanner/attackby(var/obj/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/book)) - user.drop_item(O, src) - else - return ..() - -/obj/machinery/libraryscanner/attack_hand(var/mob/user as mob) - if(istype(user,/mob/dead)) - to_chat(user, "Nope.") - return - usr.set_machine(src) - var/dat = "Scanner Control Interface\n" // - if(cache) - dat += "Data stored in memory.
    " - else - dat += "No data stored in memory.
    " - dat += "\[Scan\]" - if(cache) - dat += " \[Clear Memory\]

    \[Remove Book\]" - else - dat += "
    " - user << browse(dat, "window=scanner") - onclose(user, "scanner") - -/obj/machinery/libraryscanner/Topic(href, href_list) - if(..()) - usr << browse(null, "window=scanner") - onclose(usr, "scanner") - return - - if(href_list["scan"]) - for(var/obj/item/weapon/book/B in contents) - cache = B - break - if(href_list["clear"]) - cache = null - if(href_list["eject"]) - for(var/obj/item/weapon/book/B in contents) - B.loc = src.loc - src.add_fingerprint(usr) - src.updateUsrDialog() - return - - -/* - * Book binder - */ -/obj/machinery/bookbinder - name = "Book Binder" - icon = 'icons/obj/library.dmi' - icon_state = "binder" - anchored = 1 - density = 1 - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/bookbinder/attackby(var/obj/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/paper) || istype(O, /obj/item/weapon/paper/nano)) - if(user.drop_item(O, src)) - user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].") - src.visible_message("[src] begins to hum as it warms up its printing drums.") - sleep(rand(200,400)) - src.visible_message("[src] whirs as it prints and binds a new book.") - var/obj/item/weapon/book/b = new(src.loc) - b.dat = O:info - b.name = "Print Job #[rand(100, 999)]" - b.icon_state = "book[rand(1,9)]" - qdel(O) - O = null - else - return ..() +/* Library Machines + * + * Contains: + * Borrowbook datum + * Cachedbook datum from tkdrg, thanks + * Library Public Computer + * Library Computer + * Library Scanner + * Book Binder + */ + + #define LIBRARY_BOOKS_PER_PAGE 25 + +/* + * Borrowbook datum + */ +/datum/borrowbook // Datum used to keep track of who has borrowed what when and for how long. + var/bookname + var/mobname + var/getdate + var/duedate + +/* + * Cachedbook datum + */ +/datum/cachedbook // Datum used to cache the SQL DB books locally in order to achieve a performance gain. + var/id + var/title + var/author + var/ckey // ADDED 24/2/2015 - N3X + var/category + var/content + var/programmatic=0 // Is the book programmatically added to the catalog? + var/forbidden=0 + var/path = /obj/item/weapon/book // Type path of the book to generate + +/datum/cachedbook/proc/LoadFromRow(var/list/row) + id = row["id"] + author = row["author"] + title = row["title"] + category = row["category"] + ckey = row["ckey"] + if("content" in row) + content = row["content"] + programmatic=0 + +// Builds a SQL statement +/datum/library_query + var/author + var/category + var/title + +/datum/library_query/proc/toSQL() + var/list/where = list() + if(author || title || category) + if(author) + where.Add("author LIKE '%[sanitizeSQL(author)]%'") + if(category) + where.Add("category = '[sanitizeSQL(category)]'") + if(title) + where.Add("title LIKE '%[sanitizeSQL(title)]%'") + return " WHERE "+list2text(where," AND ") + return "" + +// So we can have catalogs of books that are programmatic, and ones that aren't. +/datum/library_catalog + var/list/cached_books = list() + +/datum/library_catalog/proc/initialize() + var/newid=1 + for(var/typepath in typesof(/obj/item/weapon/book/manual)-/obj/item/weapon/book/manual) + var/obj/item/weapon/book/B = new typepath(null) + var/datum/cachedbook/CB = new() + CB.forbidden=B.forbidden + CB.title = B.name + CB.author = B.author + CB.programmatic=1 + CB.path=typepath + CB.id = "M[newid]" + newid++ + cached_books["[CB.id]"]=CB + + +/datum/library_catalog/proc/rmBookByID(var/mob/user, var/id as text) + if("[id]" in cached_books) + var/datum/cachedbook/CB = cached_books["[id]"] + if(CB.programmatic) + to_chat(user, "That book cannot be removed from the system, as it does not actually exist in the database.") + return + + var/sqlid = text2num(id) + if(!sqlid) + return + var/DBQuery/query = dbcon_old.NewQuery("DELETE FROM library WHERE id=[sqlid]") + query.Execute() + +/datum/library_catalog/proc/getBookByID(var/id as text) + if("[id]" in cached_books) + return cached_books["[id]"] + + var/sqlid = text2num(id) + if(!sqlid) + return + var/DBQuery/query = dbcon_old.NewQuery("SELECT id, author, title, category, ckey FROM library WHERE id=[sqlid]") + query.Execute() + + var/list/results=list() + while(query.NextRow()) + var/datum/cachedbook/CB = new() + CB.LoadFromRow(list( + "id" =query.item[1], + "author" =query.item[2], + "title" =query.item[3], + "category"=query.item[4], + "ckey" =query.item[5] + )) + results += CB + cached_books["[id]"]=CB + return CB + return results + +var/global/datum/library_catalog/library_catalog = new() + +var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion") + +/** Scanner **/ +/obj/machinery/libraryscanner + name = "scanner" + icon = 'icons/obj/library.dmi' + icon_state = "bigscanner" + anchored = 1 + density = 1 + var/obj/item/weapon/book/cache // Last scanned book + + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/libraryscanner/attackby(var/obj/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/book)) + user.drop_item(O, src) + else + return ..() + +/obj/machinery/libraryscanner/attack_hand(var/mob/user as mob) + if(istype(user,/mob/dead)) + to_chat(user, "Nope.") + return + usr.set_machine(src) + var/dat = "Scanner Control Interface\n" // + if(cache) + dat += "Data stored in memory.
    " + else + dat += "No data stored in memory.
    " + dat += "\[Scan\]" + if(cache) + dat += " \[Clear Memory\]

    \[Remove Book\]" + else + dat += "
    " + user << browse(dat, "window=scanner") + onclose(user, "scanner") + +/obj/machinery/libraryscanner/Topic(href, href_list) + if(..()) + usr << browse(null, "window=scanner") + onclose(usr, "scanner") + return + + if(href_list["scan"]) + for(var/obj/item/weapon/book/B in contents) + cache = B + break + if(href_list["clear"]) + cache = null + if(href_list["eject"]) + for(var/obj/item/weapon/book/B in contents) + B.loc = src.loc + src.add_fingerprint(usr) + src.updateUsrDialog() + return + + +/* + * Book binder + */ +/obj/machinery/bookbinder + name = "Book Binder" + icon = 'icons/obj/library.dmi' + icon_state = "binder" + anchored = 1 + density = 1 + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/bookbinder/attackby(var/obj/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/paper) || istype(O, /obj/item/weapon/paper/nano)) + if(user.drop_item(O, src)) + user.visible_message("[user] loads some paper into [src].", "You load some paper into [src].") + src.visible_message("[src] begins to hum as it warms up its printing drums.") + sleep(rand(200,400)) + src.visible_message("[src] whirs as it prints and binds a new book.") + var/obj/item/weapon/book/b = new(src.loc) + b.dat = O:info + b.name = "Print Job #[rand(100, 999)]" + b.icon_state = "book[rand(1,9)]" + qdel(O) + O = null + else + return ..() diff --git a/code/modules/library/lib_readme.dm b/code/modules/library/lib_readme.dm index 4237687dfff..0150ed6ba8a 100644 --- a/code/modules/library/lib_readme.dm +++ b/code/modules/library/lib_readme.dm @@ -1,61 +1,61 @@ -//******************************* -// -// Library SQL Configuration -// -//******************************* - -// Deprecated! See global.dm for new SQL config vars -- TLE -/* -#define SQL_ADDRESS "" -#define SQL_DB "" -#define SQL_PORT "3306" -#define SQL_LOGIN "" -#define SQL_PASS "" -*/ - -//******************************* -// Requires Dantom.DB library ( http://www.byond.com/developer/Dantom/DB ) - - -/* - The Library - ------------ - A place for the crew to go, relax, and enjoy a good book. - Aspiring authors can even self publish and, if they're lucky - convince the on-staff Librarian to submit it to the Archives - to be chronicled in history forever - some say even persisting - through alternate dimensions. - - - Written by TLE for /tg/station 13 - Feel free to use this as you like. Some credit would be cool. - Check us out at http://nanotrasen.com/ if you're so inclined. -*/ - -// CONTAINS: - -// Objects: -// - bookcase -// - book -// - barcode scanner -// Machinery: -// - library computer -// - visitor's computer -// - book binder -// - book scanner -// Datum: -// - borrowbook - - -// Ideas for the future -// --------------------- -// - Visitor's computer should be able to search the current in-round library inventory (that the Librarian has stocked and checked in) -// -- Give computer other features like an Instant Messenger application, or the ability to edit, save, and print documents. -// - Admin interface directly tied to the Archive DB. Right now there's no way to delete uploaded books in-game. -// -- If this gets implemented, allow Librarians to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?). -// The admin interface would automatically take these IDs and SELECT them all from the DB to be displayed along with a Delete link to drop the row from the table. -// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Librarian is a useless fuck there are at least a few books around. -// - Allow books to be "hollowed out" like the Chaplain's Bible, allowing you to store one pocket-sized item inside. -// - Make books/book cases burn when exposed to flame. -// - Make book binder hackable. -// - Books shouldn't print straight from the library computer. Make it synch with a machine like the book binder to print instead. This should consume some sort of resource. +//******************************* +// +// Library SQL Configuration +// +//******************************* + +// Deprecated! See global.dm for new SQL config vars -- TLE +/* +#define SQL_ADDRESS "" +#define SQL_DB "" +#define SQL_PORT "3306" +#define SQL_LOGIN "" +#define SQL_PASS "" +*/ + +//******************************* +// Requires Dantom.DB library ( http://www.byond.com/developer/Dantom/DB ) + + +/* + The Library + ------------ + A place for the crew to go, relax, and enjoy a good book. + Aspiring authors can even self publish and, if they're lucky + convince the on-staff Librarian to submit it to the Archives + to be chronicled in history forever - some say even persisting + through alternate dimensions. + + + Written by TLE for /tg/station 13 + Feel free to use this as you like. Some credit would be cool. + Check us out at http://nanotrasen.com/ if you're so inclined. +*/ + +// CONTAINS: + +// Objects: +// - bookcase +// - book +// - barcode scanner +// Machinery: +// - library computer +// - visitor's computer +// - book binder +// - book scanner +// Datum: +// - borrowbook + + +// Ideas for the future +// --------------------- +// - Visitor's computer should be able to search the current in-round library inventory (that the Librarian has stocked and checked in) +// -- Give computer other features like an Instant Messenger application, or the ability to edit, save, and print documents. +// - Admin interface directly tied to the Archive DB. Right now there's no way to delete uploaded books in-game. +// -- If this gets implemented, allow Librarians to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?). +// The admin interface would automatically take these IDs and SELECT them all from the DB to be displayed along with a Delete link to drop the row from the table. +// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Librarian is a useless fuck there are at least a few books around. +// - Allow books to be "hollowed out" like the Chaplain's Bible, allowing you to store one pocket-sized item inside. +// - Make books/book cases burn when exposed to flame. +// - Make book binder hackable. +// - Books shouldn't print straight from the library computer. Make it synch with a machine like the book binder to print instead. This should consume some sort of resource. diff --git a/code/modules/liquid/splash_simulation.dm b/code/modules/liquid/splash_simulation.dm index 2c5cf603a6c..c1c6b198e56 100644 --- a/code/modules/liquid/splash_simulation.dm +++ b/code/modules/liquid/splash_simulation.dm @@ -1,209 +1,209 @@ -#define LIQUID_TRANSFER_THRESHOLD 0.05 - -var/liquid_delay = 4 - -var/list/datum/puddle/puddles = list() - -datum/puddle - var/list/obj/effect/liquid/liquid_objects = list() - -datum/puddle/proc/process() +#define LIQUID_TRANSFER_THRESHOLD 0.05 + +var/liquid_delay = 4 + +var/list/datum/puddle/puddles = list() + +datum/puddle + var/list/obj/effect/liquid/liquid_objects = list() + +datum/puddle/proc/process() // to_chat(world, "DEBUG: Puddle process!") - for(var/obj/effect/liquid/L in liquid_objects) - L.spread() - - for(var/obj/effect/liquid/L in liquid_objects) - L.apply_calculated_effect() - - if(liquid_objects.len == 0) - qdel(src) - -datum/puddle/New() - ..() - puddles += src - -datum/puddle/Del() - puddles -= src - for(var/obj/O in liquid_objects) - qdel(O) - O = null - ..() - -client/proc/splash() - set category = "Debug" - - var/volume = input("Volume?","Volume?", 0 ) as num - if(!isnum(volume)) return - if(volume <= LIQUID_TRANSFER_THRESHOLD) return - var/turf/T = get_turf(src.mob) - if(!isturf(T)) return - trigger_splash(T, volume) - -proc/trigger_splash(turf/epicenter as turf, volume as num) - if(!epicenter) - return - if(volume <= 0) - return - - var/obj/effect/liquid/L = new/obj/effect/liquid(epicenter) - L.volume = volume - L.update_icon2() - var/datum/puddle/P = new/datum/puddle() - P.liquid_objects.Add(L) - L.controller = P - - - - -obj/effect/liquid - icon = 'icons/effects/liquid.dmi' - icon_state = "0" - name = "liquid" - var/volume = 0 - var/new_volume = 0 - var/datum/puddle/controller - -obj/effect/liquid/New() - ..() - if( !isturf(loc) ) - qdel(src) - return - - for( var/obj/effect/liquid/L in loc ) - if(L != src) - qdel(L) - L = null - -obj/effect/liquid/proc/spread() - - + for(var/obj/effect/liquid/L in liquid_objects) + L.spread() + + for(var/obj/effect/liquid/L in liquid_objects) + L.apply_calculated_effect() + + if(liquid_objects.len == 0) + qdel(src) + +datum/puddle/New() + ..() + puddles += src + +datum/puddle/Del() + puddles -= src + for(var/obj/O in liquid_objects) + qdel(O) + O = null + ..() + +client/proc/splash() + set category = "Debug" + + var/volume = input("Volume?","Volume?", 0 ) as num + if(!isnum(volume)) return + if(volume <= LIQUID_TRANSFER_THRESHOLD) return + var/turf/T = get_turf(src.mob) + if(!isturf(T)) return + trigger_splash(T, volume) + +proc/trigger_splash(turf/epicenter as turf, volume as num) + if(!epicenter) + return + if(volume <= 0) + return + + var/obj/effect/liquid/L = new/obj/effect/liquid(epicenter) + L.volume = volume + L.update_icon2() + var/datum/puddle/P = new/datum/puddle() + P.liquid_objects.Add(L) + L.controller = P + + + + +obj/effect/liquid + icon = 'icons/effects/liquid.dmi' + icon_state = "0" + name = "liquid" + var/volume = 0 + var/new_volume = 0 + var/datum/puddle/controller + +obj/effect/liquid/New() + ..() + if( !isturf(loc) ) + qdel(src) + return + + for( var/obj/effect/liquid/L in loc ) + if(L != src) + qdel(L) + L = null + +obj/effect/liquid/proc/spread() + + // to_chat(world, "DEBUG: liquid spread!") - var/surrounding_volume = 0 - var/list/spread_directions = cardinal - var/turf/loc_turf = loc - for(var/direction in spread_directions) - var/turf/T = get_step(src,direction) - if(!T) - spread_directions.Remove(direction) + var/surrounding_volume = 0 + var/list/spread_directions = cardinal + var/turf/loc_turf = loc + for(var/direction in spread_directions) + var/turf/T = get_step(src,direction) + if(!T) + spread_directions.Remove(direction) // to_chat(world, "ERROR: Map edge!") - continue //Map edge - if(!loc_turf.can_leave_liquid(direction)) //Check if this liquid can leave the tile in the direction - spread_directions.Remove(direction) - continue - if(!T.can_accept_liquid(turn(direction,180))) //Check if this liquid can enter the tile - spread_directions.Remove(direction) - continue - var/obj/effect/liquid/L = locate(/obj/effect/liquid) in T - if(L) - if(L.volume >= src.volume) - spread_directions.Remove(direction) - continue - surrounding_volume += L.volume //If liquid already exists, add it's volume to our sum - else - var/obj/effect/liquid/NL = new(T) //Otherwise create a new object which we'll spread to. - NL.controller = src.controller - controller.liquid_objects.Add(NL) - - if(!spread_directions.len) + continue //Map edge + if(!loc_turf.can_leave_liquid(direction)) //Check if this liquid can leave the tile in the direction + spread_directions.Remove(direction) + continue + if(!T.can_accept_liquid(turn(direction,180))) //Check if this liquid can enter the tile + spread_directions.Remove(direction) + continue + var/obj/effect/liquid/L = locate(/obj/effect/liquid) in T + if(L) + if(L.volume >= src.volume) + spread_directions.Remove(direction) + continue + surrounding_volume += L.volume //If liquid already exists, add it's volume to our sum + else + var/obj/effect/liquid/NL = new(T) //Otherwise create a new object which we'll spread to. + NL.controller = src.controller + controller.liquid_objects.Add(NL) + + if(!spread_directions.len) // to_chat(world, "ERROR: No candidate to spread to.") - return //No suitable candidate to spread to - - var/average_volume = (src.volume + surrounding_volume) / (spread_directions.len + 1) //Average amount of volume on this and the surrounding tiles. - var/volume_difference = src.volume - average_volume //How much more/less volume this tile has than the surrounding tiles. - if(volume_difference <= (spread_directions.len*LIQUID_TRANSFER_THRESHOLD)) //If we have less than the threshold excess liquid - then there is nothing to do as other tiles will be giving us volume.or the liquid is just still. + return //No suitable candidate to spread to + + var/average_volume = (src.volume + surrounding_volume) / (spread_directions.len + 1) //Average amount of volume on this and the surrounding tiles. + var/volume_difference = src.volume - average_volume //How much more/less volume this tile has than the surrounding tiles. + if(volume_difference <= (spread_directions.len*LIQUID_TRANSFER_THRESHOLD)) //If we have less than the threshold excess liquid - then there is nothing to do as other tiles will be giving us volume.or the liquid is just still. // to_chat(world, "ERROR: transfer volume lower than THRESHOLD!") - return - - var/volume_per_tile = volume_difference / spread_directions.len - - for(var/direction in spread_directions) - var/turf/T = get_step(src,direction) - if(!T) + return + + var/volume_per_tile = volume_difference / spread_directions.len + + for(var/direction in spread_directions) + var/turf/T = get_step(src,direction) + if(!T) // to_chat(world, "ERROR: Map edge 2!") - continue //Map edge - var/obj/effect/liquid/L = locate(/obj/effect/liquid) in T - if(L) - src.volume -= volume_per_tile //Remove the volume from this tile - L.new_volume = L.new_volume + volume_per_tile //Add it to the volume to the other tile - -obj/effect/liquid/proc/apply_calculated_effect() - volume += new_volume - - if(volume < LIQUID_TRANSFER_THRESHOLD) - qdel(src) - return - new_volume = 0 - update_icon2() - -obj/effect/liquid/Move() - return 0 - -obj/effect/liquid/Destroy() - src.controller.liquid_objects.Remove(src) - ..() - -obj/effect/liquid/proc/update_icon2() - //icon_state = num2text( max(1,min(7,(floor(volume),10)/10)) ) - - switch(volume) - if(0 to 0.1) - qdel(src) - if(0.1 to 5) - icon_state = "1" - if(5 to 10) - icon_state = "2" - if(10 to 20) - icon_state = "3" - if(20 to 30) - icon_state = "4" - if(30 to 40) - icon_state = "5" - if(40 to 50) - icon_state = "6" - if(50 to INFINITY) - icon_state = "7" - -turf/proc/can_accept_liquid(from_direction) - return 0 -turf/proc/can_leave_liquid(from_direction) - return 0 - -turf/space/can_accept_liquid(from_direction) - return 1 -turf/space/can_leave_liquid(from_direction) - return 1 - -turf/simulated/floor/can_accept_liquid(from_direction) - for(var/obj/structure/window/W in src) - if(W.is_fulltile()) - return 0 - if(W.dir & from_direction) - return 0 - for(var/obj/O in src) - if(!O.liquid_pass()) - return 0 - return 1 - -turf/simulated/floor/can_leave_liquid(to_direction) - for(var/obj/structure/window/W in src) - if(W.is_fulltile()) - return 0 - if(W.dir & to_direction) - return 0 - for(var/obj/O in src) - if(!O.liquid_pass()) - return 0 - return 1 - -turf/simulated/wall/can_accept_liquid(from_direction) - return 0 -turf/simulated/wall/can_leave_liquid(from_direction) - return 0 - -obj/proc/liquid_pass() - return 1 - -obj/machinery/door/liquid_pass() - return !density - -#undef LIQUID_TRANSFER_THRESHOLD + continue //Map edge + var/obj/effect/liquid/L = locate(/obj/effect/liquid) in T + if(L) + src.volume -= volume_per_tile //Remove the volume from this tile + L.new_volume = L.new_volume + volume_per_tile //Add it to the volume to the other tile + +obj/effect/liquid/proc/apply_calculated_effect() + volume += new_volume + + if(volume < LIQUID_TRANSFER_THRESHOLD) + qdel(src) + return + new_volume = 0 + update_icon2() + +obj/effect/liquid/Move() + return 0 + +obj/effect/liquid/Destroy() + src.controller.liquid_objects.Remove(src) + ..() + +obj/effect/liquid/proc/update_icon2() + //icon_state = num2text( max(1,min(7,(floor(volume),10)/10)) ) + + switch(volume) + if(0 to 0.1) + qdel(src) + if(0.1 to 5) + icon_state = "1" + if(5 to 10) + icon_state = "2" + if(10 to 20) + icon_state = "3" + if(20 to 30) + icon_state = "4" + if(30 to 40) + icon_state = "5" + if(40 to 50) + icon_state = "6" + if(50 to INFINITY) + icon_state = "7" + +turf/proc/can_accept_liquid(from_direction) + return 0 +turf/proc/can_leave_liquid(from_direction) + return 0 + +turf/space/can_accept_liquid(from_direction) + return 1 +turf/space/can_leave_liquid(from_direction) + return 1 + +turf/simulated/floor/can_accept_liquid(from_direction) + for(var/obj/structure/window/W in src) + if(W.is_fulltile()) + return 0 + if(W.dir & from_direction) + return 0 + for(var/obj/O in src) + if(!O.liquid_pass()) + return 0 + return 1 + +turf/simulated/floor/can_leave_liquid(to_direction) + for(var/obj/structure/window/W in src) + if(W.is_fulltile()) + return 0 + if(W.dir & to_direction) + return 0 + for(var/obj/O in src) + if(!O.liquid_pass()) + return 0 + return 1 + +turf/simulated/wall/can_accept_liquid(from_direction) + return 0 +turf/simulated/wall/can_leave_liquid(from_direction) + return 0 + +obj/proc/liquid_pass() + return 1 + +obj/machinery/door/liquid_pass() + return !density + +#undef LIQUID_TRANSFER_THRESHOLD diff --git a/code/modules/maps/map_objects.dm b/code/modules/maps/map_objects.dm index 55940735a9b..88d319126f6 100644 --- a/code/modules/maps/map_objects.dm +++ b/code/modules/maps/map_objects.dm @@ -1,16 +1,16 @@ - -//************************************************************** -// -// Map Objects -// --------------- -// Slap these on the map and they do their shit -// -//*************************************************************** - -/obj/map - alpha = 255 - invisibility = 101 - mouse_opacity = 0 - -/obj/map/Destroy() - return + +//************************************************************** +// +// Map Objects +// --------------- +// Slap these on the map and they do their shit +// +//*************************************************************** + +/obj/map + alpha = 255 + invisibility = 101 + mouse_opacity = 0 + +/obj/map/Destroy() + return diff --git a/code/modules/maps/nests.dm b/code/modules/maps/nests.dm index 27640972f65..fb96b82a263 100644 --- a/code/modules/maps/nests.dm +++ b/code/modules/maps/nests.dm @@ -1,62 +1,62 @@ - -//************************************************************** -// Nests -//************************************************************** - -/obj/map/nest - icon = 'icons/obj/map/nests.dmi' - var/mobType = /mob/living/simple_animal/hostile/humanoid/russian - var/breedTime = 3000 - var/breedChance = 75 - var/pop = 10 - var/popMin = 2 - var/popMax = 30 - -/obj/map/nest/New() - for(src.pop,src.pop,src.pop--) - new src.mobType(src.loc) - spawn() src.ticker() - return - -/obj/map/nest/proc/ticker() - while(src) - for(var/mob/M in get_area(src)) - if(istype(M,src.mobType)) src.pop++ - else src.pop-- //It's harder with an audience, you understand bb - if(src.pop in src.popMin to src.popMax) //When enough simple animals... - if(prob(src.breedChance)) //Love each other very much... - new src.mobType(src.loc) //Babby formed!! - sleep(src.breedTime) - return - -// Subtypes //////////////////////////////////////////////////// - -/obj/map/nest/lizard - name = "lizard breeding ground" - icon_state = "lizard" - mobType = /mob/living/simple_animal/lizard - -/obj/map/nest/mouse - name = "mouse breeding ground" - icon_state = "mouse" - mobType = /mob/living/simple_animal/mouse - breedTime = 1200 - -/obj/map/nest/spider - name = "spider breeding ground" - icon_state = "spider" - mobType = /mob/living/simple_animal/hostile/giant_spider - popMax = 10 - -/obj/map/nest/carp - name = "carp breeding ground" - icon_state = "carp" - mobType = /mob/living/simple_animal/hostile/carp - popMax = 10 - -/obj/map/nest/bear - name = "bear breeding ground" - icon_state = "bear" - mobType = /mob/living/simple_animal/hostile/carp - breedTime = 9000 - popMax = 5 + +//************************************************************** +// Nests +//************************************************************** + +/obj/map/nest + icon = 'icons/obj/map/nests.dmi' + var/mobType = /mob/living/simple_animal/hostile/humanoid/russian + var/breedTime = 3000 + var/breedChance = 75 + var/pop = 10 + var/popMin = 2 + var/popMax = 30 + +/obj/map/nest/New() + for(src.pop,src.pop,src.pop--) + new src.mobType(src.loc) + spawn() src.ticker() + return + +/obj/map/nest/proc/ticker() + while(src) + for(var/mob/M in get_area(src)) + if(istype(M,src.mobType)) src.pop++ + else src.pop-- //It's harder with an audience, you understand bb + if(src.pop in src.popMin to src.popMax) //When enough simple animals... + if(prob(src.breedChance)) //Love each other very much... + new src.mobType(src.loc) //Babby formed!! + sleep(src.breedTime) + return + +// Subtypes //////////////////////////////////////////////////// + +/obj/map/nest/lizard + name = "lizard breeding ground" + icon_state = "lizard" + mobType = /mob/living/simple_animal/lizard + +/obj/map/nest/mouse + name = "mouse breeding ground" + icon_state = "mouse" + mobType = /mob/living/simple_animal/mouse + breedTime = 1200 + +/obj/map/nest/spider + name = "spider breeding ground" + icon_state = "spider" + mobType = /mob/living/simple_animal/hostile/giant_spider + popMax = 10 + +/obj/map/nest/carp + name = "carp breeding ground" + icon_state = "carp" + mobType = /mob/living/simple_animal/hostile/carp + popMax = 10 + +/obj/map/nest/bear + name = "bear breeding ground" + icon_state = "bear" + mobType = /mob/living/simple_animal/hostile/carp + breedTime = 9000 + popMax = 5 diff --git a/code/modules/maps/spawners/set_spawners.dm b/code/modules/maps/spawners/set_spawners.dm index b75b88b3722..5214c273b39 100644 --- a/code/modules/maps/spawners/set_spawners.dm +++ b/code/modules/maps/spawners/set_spawners.dm @@ -1,140 +1,140 @@ - -//************************************************************** -// -// Set Spawners -// ----------------- -// The path is strange because 'set' is a keyword. -// -//************************************************************** - -/obj/map/spawner/set_spawner - var/subChance = 100 - -/obj/map/spawner/set_spawner/New() - var/obj/spawned - src.toSpawn = pick(src.toSpawn) - for(src.amount,src.amount,src.amount--) - for(spawned in src.toSpawn) - if(src.subChance) - new spawned(src.loc) - if(src.jiggle) - spawned.pixel_x = rand(-src.jiggle,src.jiggle) - spawned.pixel_y = rand(-src.jiggle,src.jiggle) - qdel(src) - return - -//************************************************************** -// Subtypes //////////////////////////////////////////////////// -//************************************************************** - -/obj/map/spawner/set_spawner/theater - name = "theater costume spawner" - icon_state = "costumes" - toSpawn = list( - list( - /obj/item/clothing/suit/chickensuit, - /obj/item/clothing/head/chicken, - /obj/item/weapon/reagent_containers/food/snacks/egg, - ), - list( - /obj/item/clothing/under/gladiator, - /obj/item/clothing/head/helmet/gladiator, - ), - list( - /obj/item/clothing/under/gimmick/rank/captain/suit, - /obj/item/clothing/head/flatcap, - /obj/item/clothing/suit/storage/labcoat/mad, - /obj/item/clothing/glasses/gglasses, - ), - list( - /obj/item/clothing/under/gimmick/rank/captain/suit, - /obj/item/clothing/head/flatcap, - /obj/item/clothing/mask/cigarette/cigar/havana, - /obj/item/clothing/shoes/jackboots, - ), - list( - /obj/item/clothing/under/schoolgirl, - /obj/item/clothing/head/kitty, - ), - list( - /obj/item/clothing/under/blackskirt, - /obj/item/clothing/head/rabbitears, - /obj/item/clothing/glasses/sunglasses/blindfold, - ), - list( - /obj/item/clothing/suit/wcoat, - /obj/item/clothing/under/suit_jacket, - /obj/item/clothing/head/that, - ), - list( - /obj/item/clothing/gloves/white, - /obj/item/clothing/shoes/white, - /obj/item/clothing/under/scratch, - /obj/item/clothing/head/cueball, - ), - list( - /obj/item/clothing/under/kilt, - /obj/item/clothing/head/beret, - ), - list( - /obj/item/clothing/suit/wcoat, - /obj/item/clothing/glasses/monocle, - /obj/item/clothing/head/that, - /obj/item/clothing/shoes/black, - /obj/item/weapon/cane, - /obj/item/clothing/under/sl_suit, - /obj/item/clothing/mask/fakemoustache, - ), - list( - /obj/item/clothing/suit/bio_suit/plaguedoctorsuit, - /obj/item/clothing/head/plaguedoctorhat, - ), - list( - /obj/item/clothing/under/owl, - /obj/item/clothing/mask/gas/owl_mask, - ), - list( - /obj/item/clothing/under/waiter, - /obj/item/clothing/head/kitty, - /obj/item/clothing/suit/apron, - ), - list( - /obj/item/clothing/under/pirate, - /obj/item/clothing/suit/pirate, - /obj/item/clothing/head/pirate, - /obj/item/clothing/glasses/eyepatch, - ), - list( - /obj/item/clothing/under/soviet, - /obj/item/clothing/head/ushanka, - ), - list( - /obj/item/clothing/suit/imperium_monk, - /obj/item/clothing/mask/gas/cyborg, - ), - list( - /obj/item/clothing/suit/holidaypriest, - ), - list( - /obj/item/clothing/head/wizard/marisa/fake, - /obj/item/clothing/suit/wizrobe/marisa/fake, - ), - list( - /obj/item/clothing/under/sundress, - /obj/item/clothing/head/witchwig, - /obj/item/weapon/staff/broom, - ), - list( - /obj/item/clothing/suit/wizrobe/fake, - /obj/item/clothing/head/wizard/fake, - /obj/item/weapon/staff, - ), - list( - /obj/item/clothing/mask/gas/sexyclown, - /obj/item/clothing/under/sexyclown, - ), - list( - /obj/item/clothing/mask/gas/sexymime, - /obj/item/clothing/under/sexymime, - ), - ) + +//************************************************************** +// +// Set Spawners +// ----------------- +// The path is strange because 'set' is a keyword. +// +//************************************************************** + +/obj/map/spawner/set_spawner + var/subChance = 100 + +/obj/map/spawner/set_spawner/New() + var/obj/spawned + src.toSpawn = pick(src.toSpawn) + for(src.amount,src.amount,src.amount--) + for(spawned in src.toSpawn) + if(src.subChance) + new spawned(src.loc) + if(src.jiggle) + spawned.pixel_x = rand(-src.jiggle,src.jiggle) + spawned.pixel_y = rand(-src.jiggle,src.jiggle) + qdel(src) + return + +//************************************************************** +// Subtypes //////////////////////////////////////////////////// +//************************************************************** + +/obj/map/spawner/set_spawner/theater + name = "theater costume spawner" + icon_state = "costumes" + toSpawn = list( + list( + /obj/item/clothing/suit/chickensuit, + /obj/item/clothing/head/chicken, + /obj/item/weapon/reagent_containers/food/snacks/egg, + ), + list( + /obj/item/clothing/under/gladiator, + /obj/item/clothing/head/helmet/gladiator, + ), + list( + /obj/item/clothing/under/gimmick/rank/captain/suit, + /obj/item/clothing/head/flatcap, + /obj/item/clothing/suit/storage/labcoat/mad, + /obj/item/clothing/glasses/gglasses, + ), + list( + /obj/item/clothing/under/gimmick/rank/captain/suit, + /obj/item/clothing/head/flatcap, + /obj/item/clothing/mask/cigarette/cigar/havana, + /obj/item/clothing/shoes/jackboots, + ), + list( + /obj/item/clothing/under/schoolgirl, + /obj/item/clothing/head/kitty, + ), + list( + /obj/item/clothing/under/blackskirt, + /obj/item/clothing/head/rabbitears, + /obj/item/clothing/glasses/sunglasses/blindfold, + ), + list( + /obj/item/clothing/suit/wcoat, + /obj/item/clothing/under/suit_jacket, + /obj/item/clothing/head/that, + ), + list( + /obj/item/clothing/gloves/white, + /obj/item/clothing/shoes/white, + /obj/item/clothing/under/scratch, + /obj/item/clothing/head/cueball, + ), + list( + /obj/item/clothing/under/kilt, + /obj/item/clothing/head/beret, + ), + list( + /obj/item/clothing/suit/wcoat, + /obj/item/clothing/glasses/monocle, + /obj/item/clothing/head/that, + /obj/item/clothing/shoes/black, + /obj/item/weapon/cane, + /obj/item/clothing/under/sl_suit, + /obj/item/clothing/mask/fakemoustache, + ), + list( + /obj/item/clothing/suit/bio_suit/plaguedoctorsuit, + /obj/item/clothing/head/plaguedoctorhat, + ), + list( + /obj/item/clothing/under/owl, + /obj/item/clothing/mask/gas/owl_mask, + ), + list( + /obj/item/clothing/under/waiter, + /obj/item/clothing/head/kitty, + /obj/item/clothing/suit/apron, + ), + list( + /obj/item/clothing/under/pirate, + /obj/item/clothing/suit/pirate, + /obj/item/clothing/head/pirate, + /obj/item/clothing/glasses/eyepatch, + ), + list( + /obj/item/clothing/under/soviet, + /obj/item/clothing/head/ushanka, + ), + list( + /obj/item/clothing/suit/imperium_monk, + /obj/item/clothing/mask/gas/cyborg, + ), + list( + /obj/item/clothing/suit/holidaypriest, + ), + list( + /obj/item/clothing/head/wizard/marisa/fake, + /obj/item/clothing/suit/wizrobe/marisa/fake, + ), + list( + /obj/item/clothing/under/sundress, + /obj/item/clothing/head/witchwig, + /obj/item/weapon/staff/broom, + ), + list( + /obj/item/clothing/suit/wizrobe/fake, + /obj/item/clothing/head/wizard/fake, + /obj/item/weapon/staff, + ), + list( + /obj/item/clothing/mask/gas/sexyclown, + /obj/item/clothing/under/sexyclown, + ), + list( + /obj/item/clothing/mask/gas/sexymime, + /obj/item/clothing/under/sexymime, + ), + ) diff --git a/code/modules/maps/spawners/spawners.dm b/code/modules/maps/spawners/spawners.dm index 4ed60ba8b79..0fbc8f39eec 100644 --- a/code/modules/maps/spawners/spawners.dm +++ b/code/modules/maps/spawners/spawners.dm @@ -1,933 +1,933 @@ - -//************************************************************** -// -// Spawners -// ------------- -// Enjoy. -// -//************************************************************** - -/obj/map/spawner - icon = 'icons/obj/map/spawners.dmi' - var/amount = 1 - var/chance = 100 - var/jiggle = 0 - var/list/toSpawn = list() - -/obj/map/spawner/New() - var/obj/spawned - for(src.amount,src.amount,src.amount--) - if(prob(src.chance)) - spawned = pick(src.toSpawn) - spawned = new spawned(src.loc) - if(src.jiggle) - spawned.pixel_x = rand(-src.jiggle,src.jiggle) - spawned.pixel_y = rand(-src.jiggle,src.jiggle) - qdel(src) - return - -//************************************************************** -// Subtypes //////////////////////////////////////////////////// -//************************************************************** - -// Medical ///////////////////////////////////////////////////// - -/obj/map/spawner/medical/drugs - name = "medical drug spawner" - icon_state = "med_drugs" - amount = 5 - chance = 50 - toSpawn = list( - /obj/item/weapon/reagent_containers/glass/beaker/cryoxadone, - /obj/item/weapon/reagent_containers/glass/bottle/antitoxin, - /obj/item/weapon/reagent_containers/glass/bottle/mutagen, - /obj/item/weapon/reagent_containers/glass/bottle/capsaicin, - /obj/item/weapon/reagent_containers/glass/bottle/frostoil, - /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline, - /obj/item/weapon/reagent_containers/glass/bottle/stoxin, - /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate, - /obj/item/weapon/reagent_containers/syringe/inaprovaline, - /obj/item/weapon/reagent_containers/syringe/antitoxin, - /obj/item/weapon/reagent_containers/syringe/antiviral, - /obj/item/weapon/storage/pill_bottle/antitox, - /obj/item/weapon/storage/pill_bottle/inaprovaline, - /obj/item/weapon/storage/pill_bottle/kelotane, - /obj/item/weapon/reagent_containers/blood/OMinus, - /obj/item/weapon/reagent_containers/hypospray/autoinjector, - ) - -/obj/map/spawner/medical/pills - name = "medical pill spawner" - icon_state = "med_pills" - amount = 10 - chance = 75 - jiggle = 6 - toSpawn = list( - /obj/item/weapon/reagent_containers/pill/antitox, - /obj/item/weapon/reagent_containers/pill/tox, - /obj/item/weapon/reagent_containers/pill/stox, - /obj/item/weapon/reagent_containers/pill/kelotane, - /obj/item/weapon/reagent_containers/pill/tramadol, - /obj/item/weapon/reagent_containers/pill/methylphenidate, - /obj/item/weapon/reagent_containers/pill/citalopram, - /obj/item/weapon/reagent_containers/pill/inaprovaline, - /obj/item/weapon/reagent_containers/pill/dexalin, - /obj/item/weapon/reagent_containers/pill/bicaridine, - /obj/item/weapon/reagent_containers/pill/happy, - /obj/item/weapon/reagent_containers/pill/zoom, - ) - -// Security //////////////////////////////////////////////////// - -/obj/map/spawner/security/armor - name = "armory armor spawner" - icon_state = "armory_armor" - toSpawn = list( - /obj/item/clothing/suit/armor/riot, - /obj/item/clothing/suit/armor/bulletproof, - /obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/suit/armor/heavy, - /obj/item/clothing/suit/armor/reactive, - ) - -/obj/map/spawner/security/gear - name = "armory gear spawner" - icon_state = "armory_gear" - amount = 3 - toSpawn = list( - /obj/item/clothing/head/helmet/riot, - /obj/item/weapon/shield/riot, - /obj/item/weapon/melee/baton/loaded, - /obj/item/clothing/suit/armor/vest/security, - /obj/item/weapon/storage/belt/security, - /obj/item/weapon/gun/energy/taser, - /obj/item/device/hailer, - ) - -/obj/map/spawner/security/weapons - name = "armory weapon spawner" - icon_state = "armory_weapons" - toSpawn = list( - /obj/item/weapon/gun/energy/gun, - /obj/item/weapon/gun/energy/ionrifle, - /obj/item/weapon/gun/energy/laser, - /obj/item/weapon/gun/energy/lasercannon, - /obj/item/weapon/gun/projectile/automatic/mini_uzi, - /obj/item/weapon/gun/projectile/automatic, - /obj/item/weapon/gun/projectile/automatic/l6_saw, - /obj/item/weapon/gun/projectile/deagle, - /obj/item/weapon/gun/projectile/mateba, - /obj/item/weapon/gun/projectile/pistol, - /obj/item/weapon/gun/projectile/shotgun/pump, - /obj/item/weapon/gun/projectile/shotgun/pump/combat, - ) - -/obj/map/spawner/security/misc - name = "armory misc spawner" - icon_state = "armory_misc" - amount = 2 - jiggle = 5 - toSpawn = list( - /obj/item/weapon/storage/box/flashbangs, - /obj/item/weapon/storage/box/emps, - /obj/item/weapon/storage/box/handcuffs, - /obj/item/weapon/storage/box/donkpockets, - /obj/item/weapon/storage/fancy/donut_box, - ) - -// Engineering ///////////////////////////////////////////////// - -/obj/map/spawner/engi/materials - name = "engie materials spawner" - icon_state = "engi_materials" - amount = 2 - chance = 75 - toSpawn = list( - /obj/item/stack/sheet/glass/glass{amount=50}, - /obj/item/stack/sheet/glass/rglass{amount=50}, - /obj/item/stack/sheet/glass/plasmaglass{amount=50}, - /obj/item/stack/light_w{amount=50}, - /obj/item/stack/sheet/mineral/plastic{amount=50}, - /obj/item/stack/sheet/metal{amount=50}, - /obj/item/stack/sheet/plasteel{amount=50}, - /obj/item/stack/sheet/wood{amount=50}, - /obj/item/stack/rods{amount=50}, - /obj/item/stack/tile/grass{amount=50}, - ) - -/obj/map/spawner/engi/dispensers - name = "engie dispenser spawner" - icon_state = "engi_dispensers" - chance = 50 - toSpawn = list( - /obj/structure/reagent_dispensers/fueltank, - /obj/structure/reagent_dispensers/watertank, - ) - -/obj/map/spawner/engi/machinery - name = "engie machinery spawner" - icon_state = "engi_machinery" - chance = 75 - toSpawn = list( - /obj/machinery/atmospherics/binary/circulator, - /obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe, - /obj/machinery/field_generator, - /obj/machinery/floodlight, - /obj/machinery/mineral/mint, - /obj/machinery/monkey_recycler, - /obj/machinery/photocopier, - /obj/machinery/pipedispenser, - /obj/machinery/porta_turret, - /obj/machinery/power/am_control_unit, - /obj/machinery/power/emitter, - /obj/machinery/power/generator, - /obj/machinery/power/port_gen/pacman/mrs, - /obj/machinery/power/rad_collector, - /obj/machinery/power/rust_core, - /obj/machinery/power/rust_fuel_injector, - /obj/machinery/power/battery/smes, - /obj/machinery/processor, - /obj/machinery/recharge_station, - /obj/machinery/rust/gyrotron, - /obj/machinery/shield_gen, - /obj/machinery/shieldgen, - /obj/machinery/shieldwallgen, - /obj/machinery/space_heater, - /obj/machinery/suit_storage_unit/engie, - /obj/machinery/telecomms/allinone, - /obj/machinery/teleport/station, - /obj/machinery/the_singularitygen, - /obj/machinery/vending/dinnerware, - /obj/machinery/vending/engineering, - /obj/machinery/vending/plasmaresearch, - /obj/machinery/vending/robotics, - /obj/machinery/vending/sovietsoda, - /obj/structure/AIcore, - /obj/structure/device/piano, - /obj/structure/displaycase_frame, - /obj/structure/particle_accelerator/fuel_chamber, - /obj/structure/reagent_dispensers/fueltank, - /obj/structure/reagent_dispensers/water_cooler, - /obj/structure/safe, - /obj/structure/shuttle/engine/router, - /obj/structure/toilet, - /obj/structure/turret/gun_turret, - /obj/spacepod/random, - ) - -// Assistants ////////////////////////////////////////////////// - -/obj/map/spawner/assistant/tools - name = "assistant tool spawner" - icon_state = "ass_tools" - amount = 3 - chance = 50 - toSpawn = list( - /obj/item/device/analyzer, - /obj/item/device/assembly/igniter, - /obj/item/device/assembly/infra, - /obj/item/device/assembly/mousetrap, - /obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/signaler, - /obj/item/device/assembly/timer, - /obj/item/device/assembly/voice, - /obj/item/device/flashlight, - /obj/item/device/lightreplacer, - /obj/item/device/multitool, - /obj/item/device/radio, - /obj/item/device/t_scanner, - /obj/item/device/taperecorder, - /obj/item/device/toner, - /obj/item/device/label_roll, - /obj/item/toy/snappop, - /obj/item/toy/crayon/blue, - /obj/item/toy/crayon/orange, - /obj/item/weapon/c_tube, - /obj/item/stack/cable_coil/random, - /obj/item/weapon/camera_assembly, - /obj/item/weapon/cell, - /obj/item/weapon/crowbar, - /obj/item/weapon/weldingtool, - /obj/item/weapon/wirecutters, - /obj/item/weapon/screwdriver, - /obj/item/weapon/wrench, - /obj/item/weapon/extinguisher, - /obj/item/weapon/hand_labeler, - /obj/item/weapon/light/bulb, - /obj/item/weapon/light/tube, - /obj/item/weapon/lighter/random, - /obj/item/weapon/pen, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/storage/belt/utility, - /obj/item/weapon/storage/toolbox/electrical, - ) - -/obj/map/spawner/assistant/materials - name = "assistant materials spawner" - icon_state = "ass_materials" - amount = 2 - chance = 50 - toSpawn = list( - /obj/item/stack/sheet/glass/glass{amount=50}, - /obj/item/stack/sheet/leather{amount=50}, - /obj/item/stack/sheet/mineral/plastic{amount=50}, - /obj/item/stack/sheet/metal{amount=50}, - /obj/item/stack/sheet/wood{amount=50}, - /obj/item/stack/sheet/cloth{amount=50}, - /obj/item/stack/sheet/cardboard{amount=50}, - /obj/item/stack/rods{amount=50}, - /obj/item/stack/sheet/mineral/sandstone{amount=50}, - ) - -// Maintenance ///////////////////////////////////////////////// - -/obj/map/spawner/maint - name = "maint loot spawner" - icon_state = "maint" - amount = 2 - chance = 50 - toSpawn = list( - /obj/item/device/assembly/igniter, - /obj/item/device/assembly/infra, - /obj/item/device/assembly/mousetrap, - /obj/item/device/assembly/prox_sensor, - /obj/item/device/assembly/signaler, - /obj/item/device/assembly/timer, - /obj/item/device/assembly/voice, - /obj/item/weapon/storage/belt/utility, - /obj/item/device/multitool, - /obj/item/device/paicard, - /obj/item/device/flashlight, - /obj/item/device/flashlight/lantern, - /obj/item/device/flashlight/flare, - /obj/item/weapon/weldingtool/largetank, - /obj/item/device/gps, - /obj/item/device/gps/science, - /obj/item/device/gps/engineering, - /obj/item/weapon/cell/super, - /obj/item/weapon/soap/nanotrasen, - /obj/item/device/flash, - /obj/item/device/transfer_valve, - /obj/item/device/camera_bug, - /obj/item/device/handtv, - /obj/item/device/camera, - /obj/item/device/camera_film, - /obj/item/device/encryptionkey, - /obj/item/device/encryptionkey, - /obj/item/device/encryptionkey, - /obj/item/device/encryptionkey/syndicate, - /obj/item/device/encryptionkey/binary, - /obj/item/device/encryptionkey/syndicate/hacked, - /obj/item/device/hailer, - /obj/item/device/healthanalyzer, - /obj/item/device/mass_spectrometer, - /obj/item/device/megaphone, - /obj/item/device/mmi/radio_enabled, - /obj/item/device/powersink, - /obj/item/device/reagent_scanner, - /obj/item/device/soundsynth, - /obj/item/latexballon, - /obj/item/weapon/storage/toolbox/electrical, - /obj/item/ammo_storage/magazine/a12mm, - /obj/item/ammo_storage/box/c45, - /obj/item/ammo_storage/box/a418, - /obj/item/ammo_storage/magazine/a75, - /obj/item/ammo_storage/speedloader/c38, - /obj/item/ammo_storage/box/c9mm, - /obj/item/ammo_storage/magazine/mc9mm, - /obj/item/bodybag, - /obj/item/clothing/ears/earmuffs, - /obj/item/clothing/glasses/eyepatch, - /obj/item/clothing/glasses/regular, - /obj/item/clothing/glasses/regular/hipster, - /obj/item/clothing/glasses/sunglasses/blindfold, - /obj/item/clothing/glasses/sunglasses/prescription, - /obj/item/clothing/glasses/welding, - /obj/item/clothing/gloves/brown, - /obj/item/clothing/gloves/latex, - /obj/item/clothing/gloves/black, - /obj/item/clothing/gloves/fyellow, - /obj/item/clothing/gloves/purple, - /obj/item/clothing/head/beret, - /obj/item/clothing/head/cakehat, - /obj/item/clothing/head/cardborg, - /obj/item/clothing/head/chicken, - /obj/item/clothing/head/collectable/flatcap, - /obj/item/clothing/head/collectable/pirate, - /obj/item/clothing/head/collectable/wizard, - /obj/item/clothing/head/collectable/tophat, - /obj/item/clothing/head/nun_hood, - /obj/item/clothing/head/plaguedoctorhat, - /obj/item/clothing/head/soft/grey, - /obj/item/clothing/head/surgery/blue, - /obj/item/clothing/head/welding, - /obj/item/clothing/mask/cigarette, - /obj/item/clothing/shoes/laceup, - /obj/item/clothing/glasses/welding/superior, - /obj/item/clothing/glasses/sunglasses/sechud, - /obj/item/clothing/glasses/meson, - /obj/item/clothing/gloves/yellow, - /obj/item/clothing/gloves/knuckles, - /obj/item/clothing/gloves/knuckles/spiked, - /obj/item/clothing/head/bomb_hood, - /obj/item/clothing/mask/gas, - /obj/item/clothing/mask/gas/monkeymask, - /obj/item/clothing/mask/gas/owl_mask, - /obj/item/clothing/mask/gas/plaguedoctor, - /obj/item/clothing/mask/gas/sexyclown, - /obj/item/clothing/mask/muzzle, - /obj/item/clothing/mask/pig, - /obj/item/clothing/mask/horsehead, - /obj/item/clothing/shoes/sandal, - /obj/item/clothing/suit/bio_suit, - /obj/item/clothing/suit/bio_suit/plaguedoctorsuit, - /obj/item/clothing/suit/bomb_suit, - /obj/item/clothing/suit/fire/firefighter, - /obj/item/clothing/suit/monkeysuit, - /obj/item/clothing/suit/pirate, - /obj/item/clothing/suit/radiation, - /obj/item/clothing/suit/redtag, - /obj/item/clothing/suit/storage/fr_jacket, - /obj/item/clothing/suit/storage/hazardvest, - /obj/item/clothing/suit/storage/lawyer/purpjacket, - /obj/item/clothing/suit/storage/paramedic, - /obj/item/clothing/suit/suspenders, - /obj/item/clothing/suit/syndicatefake, - /obj/item/clothing/suit/unathi/mantle, - /obj/item/clothing/suit/unathi/robe, - /obj/item/clothing/accessory/tie/horrible, - /obj/item/clothing/accessory/armband/cargo, - /obj/item/clothing/accessory/armband, - /obj/item/clothing/accessory/armband/engine, - /obj/item/clothing/accessory/armband/hydro, - /obj/item/clothing/accessory/holster/armpit, - /obj/item/clothing/under/blackskirt, - /obj/item/clothing/mask/gas/voice, - /obj/item/clothing/head/bandana, - /obj/item/clothing/head/rabbitears, - /obj/item/clothing/head/kitty, - /obj/item/clothing/head/hairflower, - /obj/item/clothing/head/helmet/roman, - /obj/item/clothing/head/helmet/roman/legionaire, - /obj/item/clothing/head/pumpkinhead, - /obj/item/clothing/head/soft/rainbow, - /obj/item/clothing/head/soft/sec, - /obj/item/clothing/head/syndicatefake, - /obj/item/clothing/head/wizard/marisa/fake, - /obj/item/clothing/suit/wizrobe/marisa/fake, - /obj/item/clothing/head/wizard/fake, - /obj/item/clothing/suit/wizrobe/fake, - /obj/item/clothing/mask/balaclava, - /obj/item/clothing/mask/luchador/tecnicos, - /obj/item/clothing/mask/luchador/rudos, - /obj/item/clothing/mask/cigarette/cigar, - /obj/item/clothing/mask/fakemoustache, - /obj/item/clothing/shoes/galoshes, - /obj/item/clothing/shoes/jackboots, - /obj/item/clothing/shoes/roman, - /obj/item/clothing/shoes/syndigaloshes, - /obj/item/clothing/suit/chickensuit, - /obj/item/clothing/under/captain_fly, - /obj/item/clothing/under/dress/dress_saloon, - /obj/item/clothing/under/dress/dress_yellow, - /obj/item/clothing/under/dress/dress_pink, - /obj/item/clothing/under/dress/dress_orange, - /obj/item/clothing/under/dress/dress_fire, - /obj/item/clothing/under/dress/dress_green, - /obj/item/clothing/under/gladiator, - /obj/item/clothing/under/johnny, - /obj/item/clothing/under/kilt, - /obj/item/clothing/under/lawyer/purpsuit, - /obj/item/clothing/under/lawyer/female, - /obj/item/clothing/under/overalls, - /obj/item/clothing/under/owl, - /obj/item/clothing/under/pirate, - /obj/item/clothing/under/psyche, - /obj/item/clothing/under/psysuit, - /obj/item/clothing/under/rainbow, - /obj/item/clothing/under/schoolgirl, - /obj/item/clothing/under/sexyclown, - /obj/item/clothing/under/rank/mailman, - /obj/item/clothing/under/shorts/green, - /obj/item/clothing/under/shorts/red, - /obj/item/clothing/under/shorts/grey, - /obj/item/clothing/under/stripper/mankini, - /obj/item/clothing/under/sundress, - /obj/item/clothing/under/swimsuit/black, - /obj/item/clothing/under/swimsuit/purple, - /obj/item/clothing/under/syndicate/tacticool, - /obj/item/clothing/under/syndicate, - /obj/item/clothing/under/waiter, - /obj/item/clothing/under/wedding/bride_blue, - /obj/item/clothing/under/wedding/bride_purple, - /obj/item/clothing/under/wedding/bride_white, - /obj/item/pizzabox/meat, - /obj/item/pizzabox/margherita, - /obj/item/pizzabox/vegetable, - /obj/item/pizzabox/mushroom, - /obj/item/robot_parts/robot_component/actuator, - /obj/item/robot_parts/robot_component/armour, - /obj/item/robot_parts/robot_component/binary_communication_device, - /obj/item/robot_parts/chest, - /obj/item/robot_parts/robot_suit, - /obj/item/roller, - /obj/item/stack/medical/ointment, - /obj/item/stack/medical/bruise_pack, - /obj/item/stack/medical/advanced/bruise_pack, - /obj/item/stack/medical/advanced/ointment, - /obj/item/stack/nanopaste, - /obj/item/taperoll/engineering, - /obj/item/taperoll/police, - /obj/item/toy/ammo/gun, - /obj/item/toy/balloon, - /obj/item/toy/crayon/red, - /obj/item/toy/crayon/yellow, - /obj/item/toy/crayon/blue, - /obj/item/toy/crossbow, - /obj/item/toy/gun, - /obj/item/toy/snappop, - /obj/item/toy/sword, - /obj/item/toy/bomb, - /obj/item/clothing/mask/facehugger/toy, - /obj/item/trash/candle, - /obj/item/trash/candy, - /obj/item/trash/cheesie, - /obj/item/trash/chips, - /obj/item/trash/plate, - /obj/item/trash/popcorn, - /obj/item/trash/raisins, - /obj/item/trash/sosjerky, - /obj/item/clothing/accessory/medal/conduct, - /obj/item/weapon/bananapeel, - /obj/item/weapon/corncob, - /obj/item/weapon/bikehorn, - /obj/item/weapon/c_tube, - /obj/item/weapon/legcuffs/beartrap, - /obj/item/weapon/caution, - /obj/item/weapon/rack_parts, - /obj/item/weapon/caution/cone, - /obj/item/weapon/beach_ball, - /obj/item/weapon/bee_net, - /obj/item/weapon/bikehorn/rubberducky, - /obj/item/weapon/broken_bottle, - /obj/item/weapon/bucket_sensor, - /obj/item/stack/cable_coil, - /obj/item/weapon/camera_assembly, - /obj/item/weapon/cigbutt/cigarbutt, - /obj/item/weapon/clipboard, - /obj/item/weapon/coin, - /obj/item/weapon/coin/gold, - /obj/item/weapon/coin/adamantine, - /obj/item/weapon/coin/clown, - /obj/item/weapon/coin/diamond, - /obj/item/weapon/coin/iron, - /obj/item/weapon/coin/phazon, - /obj/item/weapon/coin/plasma, - /obj/item/weapon/coin/silver, - /obj/item/weapon/coin/uranium, - /obj/item/weapon/dice, - /obj/item/weapon/flamethrower/full, - /obj/item/weapon/gun/projectile/deagle/gold, - /obj/item/weapon/gun/projectile/russian, - /obj/item/weapon/handcuffs, - /obj/item/weapon/handcuffs/cable, - /obj/item/weapon/hatchet, - /obj/item/weapon/kitchen/rollingpin, - /obj/item/weapon/lighter/random, - /obj/item/weapon/lipstick/random, - /obj/item/weapon/minihoe, - /obj/item/weapon/mop, - /obj/item/weapon/newspaper, - /obj/item/weapon/pen, - /obj/item/weapon/scalpel, - /obj/item/weapon/shard, - /obj/item/weapon/stool, - /obj/item/device/powersink, - /obj/item/weapon/reagent_containers/blood/OMinus, - /obj/item/weapon/reagent_containers/glass/bottle/ammonia, - /obj/item/weapon/reagent_containers/glass/bottle/capsaicin, - /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate, - /obj/item/weapon/reagent_containers/glass/bottle/cold, - /obj/item/weapon/reagent_containers/glass/bottle/diethylamine, - /obj/item/weapon/reagent_containers/glass/bottle/epiglottis_virion, - /obj/item/weapon/reagent_containers/glass/bottle/flu_virion, - /obj/item/weapon/reagent_containers/glass/bottle/magnitis, - /obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat, - /obj/item/weapon/reagent_containers/food/drinks/beer, - /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, - /obj/item/weapon/reagent_containers/food/drinks/bottle/cream, - /obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice, - /obj/item/weapon/reagent_containers/food/drinks/bottle/tequila, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth, - /obj/item/weapon/reagent_containers/food/drinks/bottle/wine, - /obj/item/weapon/reagent_containers/food/drinks/coffee, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko, - /obj/item/weapon/reagent_containers/food/snacks/pie/amanita_pie, - /obj/item/weapon/reagent_containers/food/snacks/amanitajelly, - /obj/item/weapon/reagent_containers/food/snacks/applecakeslice, - /obj/item/weapon/reagent_containers/food/snacks/pie/applepie, - /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger, - /obj/item/weapon/reagent_containers/food/snacks/boiledegg, - /obj/item/weapon/reagent_containers/food/snacks/brainburger, - /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat, - /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers, - /obj/item/weapon/reagent_containers/food/snacks/chips, - /obj/item/weapon/reagent_containers/food/snacks/chocolatebar/wrapped, - /obj/item/weapon/reagent_containers/food/snacks/clownstears, - /obj/item/weapon/reagent_containers/food/snacks/coldchili, - /obj/item/weapon/reagent_containers/food/snacks/corgikabob, - /obj/item/weapon/reagent_containers/food/snacks/donkpocket, - /obj/item/weapon/reagent_containers/food/snacks/donut, - /obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey, - /obj/item/weapon/reagent_containers/food/snacks/no_raisin, - /obj/item/weapon/reagent_containers/food/snacks/pie/plump_pie, - /obj/item/weapon/reagent_containers/food/snacks/soylenviridians, - /obj/item/weapon/reagent_containers/food/snacks/syndicake, - /obj/item/weapon/reagent_containers/food/snacks/tofurkey, - ) - -// Space /////////////////////////////////////////////////////// - -/obj/map/spawner/space/weapons - name = "space weapons spawner" - icon_state = "space_weapons" - chance = 20 - toSpawn = list( - /obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver, - /obj/item/weapon/crossbow, - /obj/item/weapon/grenade/spawnergrenade/manhacks, - /obj/item/weapon/grenade/spawnergrenade/spesscarp, - /obj/item/weapon/grenade/flashbang/clusterbang, - /obj/item/weapon/grenade/empgrenade, - /obj/item/weapon/gun/dartgun/vox/raider, - /obj/item/weapon/gun/energy/decloner, - /obj/item/weapon/gun/energy/laser/retro, - /obj/item/weapon/gun/energy/mindflayer, - /obj/item/weapon/gun/energy/temperature, - /obj/item/weapon/gun/energy/xray, - /obj/item/weapon/gun/projectile/gyropistol, - /obj/item/weapon/gun/projectile/pistol, - /obj/item/weapon/gun/projectile/russian, - /obj/item/weapon/gun/projectile/silenced, - /obj/item/weapon/harpoon, - /obj/item/weapon/melee/classic_baton, - /obj/item/weapon/pickaxe/plasmacutter, - /obj/item/weapon/shield/energy, - /obj/item/weapon/organ/head, - /obj/item/weapon/organ/r_leg, - /obj/item/weapon/organ/l_arm, - /obj/item/weapon/organ/l_foot, - ) - -/obj/map/spawner/space/tools - name = "space tool spawner" - icon_state = "space_tools" - chance = 50 - toSpawn = list( - /obj/item/bluespace_crystal, - /obj/item/bodybag/cryobag, - /obj/item/borg/upgrade/syndicate, - /obj/item/clothing/glasses/thermal, - /obj/item/device/aicard, - /obj/item/device/ano_scanner, - /obj/item/device/flashlight/lantern, - /obj/item/device/flashlight, - /obj/item/device/handtv, - /obj/item/device/paicard, - /obj/item/device/robotanalyzer, - /obj/item/device/t_scanner, - /obj/item/device/transfer_valve, - /obj/item/device/wormhole_jaunter, - /obj/item/device/reagent_scanner/adv, - /obj/item/mecha_parts/mecha_equipment/repair_droid, - /obj/item/mecha_parts/mecha_equipment/teleporter, - /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay, - /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill, - /obj/item/mecha_parts/mecha_equipment/tool/cable_layer, - /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp, - /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack, - /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion, - /obj/item/mecha_parts/mecha_equipment/wormhole_generator, - /obj/item/mecha_parts/mecha_tracking, - /obj/item/mecha_parts/part/phazon_phase_array, - /obj/item/mecha_parts/part/durand_torso, - /obj/item/mecha_parts/part/gygax_right_leg, - /obj/item/mecha_parts/part/odysseus_torso, - /obj/item/mecha_parts/part/ripley_left_arm, - /obj/item/robot_parts/robot_suit, - /obj/item/robot_parts/head, - /obj/item/weapon/autopsy_scanner, - /obj/item/stack/cable_coil/pink, - /obj/item/weapon/cell/hyper, - /obj/item/weapon/ed209_assembly, - /obj/item/weapon/firstaid_arm_assembly, - /obj/item/weapon/grenade/chem_grenade/metalfoam, - /obj/item/weapon/grenade/chem_grenade/antiweed, - /obj/item/weapon/hatchet, - /obj/item/weapon/pickaxe/jackhammer, - /obj/item/device/rcd/rpd, - /obj/item/device/rcd, - /obj/item/weapon/rcd_ammo, - /obj/item/device/rcd/matter/rsf, - /obj/item/weapon/weldingtool/hugetank, - /obj/item/weapon/tank/plasma, - /obj/item/gun_part/silencer, - /obj/item/weapon/storage/backpack/holding, - ) - -/obj/map/spawner/space/gear - name = "space gear spawner" - icon_state = "space_gear" - chance = 30 - toSpawn = list( - /obj/item/clothing/mask/cigarette/cigar/cohiba, - /obj/item/clothing/mask/cigarette/pipe/cobpipe, - /obj/item/clothing/mask/balaclava, - /obj/item/clothing/mask/gas/cyborg, - /obj/item/clothing/shoes/magboots, - /obj/item/clothing/gloves/yellow, - /obj/item/clothing/suit/bio_suit/janitor, - /obj/item/clothing/suit/fire/heavy, - /obj/item/clothing/suit/radiation, - /obj/item/clothing/head/helmet/space/syndicate/black/blue, - /obj/item/clothing/suit/space/syndicate/black/blue, - /obj/item/clothing/head/helmet/space/syndicate/black/med, - /obj/item/clothing/suit/space/syndicate/black/med, - /obj/item/clothing/head/helmet/space/syndicate/black/engie, - /obj/item/clothing/suit/space/syndicate/black/engie, - /obj/item/clothing/accessory/storage/webbing, - /obj/item/clothing/accessory/storage/brown_vest, - /obj/item/weapon/organ/head, - /obj/item/weapon/organ/r_leg, - /obj/item/weapon/organ/l_arm, - /obj/item/weapon/organ/l_foot, - ) - -/obj/map/spawner/space/supply - name = "space supply spawner" - icon_state = "space_supply" - amount = 2 - chance = 50 - toSpawn = list( - /obj/item/clothing/mask/breath/medical, - /obj/item/device/radio, - /obj/item/device/flashlight/flare, - /obj/item/weapon/extinguisher, - /obj/item/weapon/tank/oxygen/yellow, - /obj/item/weapon/tank/nitrogen, - /obj/item/weapon/tank/emergency_oxygen/engi, - /obj/item/weapon/tank/emergency_oxygen/double, - /obj/item/weapon/tank/anesthetic, - /obj/item/weapon/storage/toolbox/electrical, - /obj/item/weapon/storage/toolbox/syndicate, - /obj/item/weapon/storage/box/autoinjectors, - /obj/item/weapon/storage/box/donkpockets, - /obj/item/weapon/storage/fancy/matchbox, - /obj/item/weapon/storage/fancy/donut_box, - /obj/item/weapon/storage/firstaid/adv, - /obj/item/weapon/storage/firstaid/regular, - /obj/item/weapon/reagent_containers/pill/happy, - /obj/item/weapon/reagent_containers/glass/bottle/random, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/snacks/appendixburger, - /obj/item/weapon/reagent_containers/food/snacks/bloodsoup, - /obj/item/weapon/reagent_containers/food/snacks/candy/donor, - /obj/item/weapon/reagent_containers/food/snacks/clownburger, - /obj/item/weapon/reagent_containers/food/snacks/mysterysoup, - /obj/item/weapon/reagent_containers/food/snacks/donut/chaos, - //obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chilli, - /obj/item/weapon/reagent_containers/food/snacks/wingfangchu, - /obj/item/weapon/reagent_containers/food/snacks/soylentgreen, - /obj/item/weapon/reagent_containers/food/snacks/meat/bearmeat, - /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat, - ) - -/obj/map/spawner/space/drinks - name = "space drinks spawner" - icon_state = "space_drinks" - chance = 50 - amount = 4 - jiggle = 5 - toSpawn = list( - /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, - /obj/item/weapon/reagent_containers/food/drinks/beer, - /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, - /obj/item/weapon/reagent_containers/food/drinks/bottle/rum, - /obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo, - /obj/item/weapon/reagent_containers/food/drinks/groansbanned, - ) - -/obj/map/spawner/space/russian - name = "space russian spawner" - icon_state = "space_russian" - chance = 5 - toSpawn = list(/mob/living/simple_animal/hostile/humanoid/russian/ranged) - -// Mobs //////////////////////////////////////////////////////// - -/obj/map/spawner/mobs/carp - name = "carp spawner" - icon_state = "mob_carp" - chance = 50 - toSpawn = list(/mob/living/simple_animal/hostile/carp) - -/obj/map/spawner/mobs/lizard - name = "lizard spawner" - icon_state = "mob_lizard" - amount = 2 - chance = 50 - toSpawn = list(/mob/living/simple_animal/lizard) - -/obj/map/spawner/mobs/mouse - name = "mouse spawner" - icon_state = "mob_mouse" - amount = 2 - chance = 50 - toSpawn = list( - /mob/living/simple_animal/mouse/brown, - /mob/living/simple_animal/mouse/gray, - /mob/living/simple_animal/mouse/white, - ) - -/obj/map/spawner/mobs/bear - name = "bear spawner" - icon_state = "mob_bear" - chance = 50 - toSpawn = list(/mob/living/simple_animal/hostile/bear) - -/obj/map/spawner/mobs/spider - name = "spider spawner" - icon_state = "mob_spider" - amount = 3 - chance = 50 - toSpawn = list( - /mob/living/simple_animal/hostile/giant_spider, - /mob/living/simple_animal/hostile/giant_spider/nurse, - /mob/living/simple_animal/hostile/giant_spider/hunter, - ) - -// Robutts ///////////////////////////////////////////////////// - -/obj/map/spawner/robot/any - name = "robot spawner" - icon_state = "robot_any" - chance = 20 - toSpawn = list( - /obj/machinery/bot/cleanbot, - /obj/machinery/bot/farmbot, - /obj/machinery/bot/floorbot, - /obj/machinery/bot/medbot, - /obj/machinery/bot/secbot, - ) - -/obj/map/spawner/robot/sec - name = "secbot spawner" - icon_state = "robot_sec" - toSpawn = list(/obj/machinery/bot/secbot) - -/obj/map/spawner/robot/clean - name = "cleanbot spawner" - icon_state = "robot_clean" - toSpawn = list(/obj/machinery/bot/cleanbot) - -/obj/map/spawner/robot/med - name = "medbot spawner" - icon_state = "robot_med" - toSpawn = list(/obj/machinery/bot/medbot) - -/obj/map/spawner/robot/floor - name = "floorbot spawner" - icon_state = "robot_floor" - toSpawn = list(/obj/machinery/bot/floorbot) - -/obj/map/spawner/robot/farm - name = "farmbot spawner" - icon_state = "robot_farm" - toSpawn = list(/obj/machinery/bot/farmbot) - -// Seeds /////////////////////////////////////////////////////// - -/obj/map/spawner/misc/seeds - name = "seed spawner" - icon_state = "seeds" - chance = 50 - amount = 4 - jiggle = 5 - toSpawn = list( - /obj/item/seeds/amanitamycelium, - /obj/item/seeds/ambrosiadeusseed, - /obj/item/seeds/ambrosiavulgarisseed, - /obj/item/seeds/angelmycelium, - /obj/item/seeds/appleseed, - /obj/item/seeds/bananaseed, - /obj/item/seeds/berryseed, - /obj/item/seeds/bloodtomatoseed, - /obj/item/seeds/bluespacetomatoseed, - /obj/item/seeds/cabbageseed, - /obj/item/seeds/carrotseed, - /obj/item/seeds/chantermycelium, - /obj/item/seeds/cherryseed, - /obj/item/seeds/chiliseed, - /obj/item/seeds/cocoapodseed, - /obj/item/seeds/cornseed, - /obj/item/seeds/deathberryseed, - /obj/item/seeds/deathnettleseed, - /obj/item/seeds/eggplantseed, - /obj/item/seeds/eggyseed, - /obj/item/seeds/glowberryseed, - /obj/item/seeds/glowshroom, - /obj/item/seeds/goldappleseed, - /obj/item/seeds/grapeseed, - /obj/item/seeds/grassseed, - /obj/item/seeds/greengrapeseed, - /obj/item/seeds/harebell, - /obj/item/seeds/icepepperseed, - /obj/item/seeds/killertomatoseed, - /obj/item/seeds/koiseed, - /obj/item/seeds/kudzuseed, - /obj/item/seeds/lemonseed, - /obj/item/seeds/libertymycelium, - /obj/item/seeds/limeseed, - /obj/item/seeds/moonflowerseed, - /obj/item/seeds/nettleseed, - /obj/item/seeds/novaflowerseed, - /obj/item/seeds/orangeseed, - /obj/item/seeds/plastiseed, - /obj/item/seeds/plumpmycelium, - /obj/item/seeds/poisonberryseed, - /obj/item/seeds/poisonedappleseed, - /obj/item/seeds/poppyseed, - /obj/item/seeds/potatoseed, - /obj/item/seeds/pumpkinseed, - /obj/item/seeds/reishimycelium, - /obj/item/seeds/dionanode, - /obj/item/seeds/riceseed, - /obj/item/seeds/soyaseed, - /obj/item/seeds/sugarcaneseed, - /obj/item/seeds/sunflowerseed, - //obj/item/seeds/synthbrainseed, - //obj/item/seeds/synthbuttseed, - //obj/item/seeds/synthmeatseed, - /obj/item/seeds/tomatoseed, - /obj/item/seeds/towermycelium, - /obj/item/seeds/walkingmushroommycelium, - /obj/item/seeds/watermelonseed, - /obj/item/seeds/wheatseed, - /obj/item/seeds/whitebeetseed, - /obj/item/seeds/cinnamomum, - ) + +//************************************************************** +// +// Spawners +// ------------- +// Enjoy. +// +//************************************************************** + +/obj/map/spawner + icon = 'icons/obj/map/spawners.dmi' + var/amount = 1 + var/chance = 100 + var/jiggle = 0 + var/list/toSpawn = list() + +/obj/map/spawner/New() + var/obj/spawned + for(src.amount,src.amount,src.amount--) + if(prob(src.chance)) + spawned = pick(src.toSpawn) + spawned = new spawned(src.loc) + if(src.jiggle) + spawned.pixel_x = rand(-src.jiggle,src.jiggle) + spawned.pixel_y = rand(-src.jiggle,src.jiggle) + qdel(src) + return + +//************************************************************** +// Subtypes //////////////////////////////////////////////////// +//************************************************************** + +// Medical ///////////////////////////////////////////////////// + +/obj/map/spawner/medical/drugs + name = "medical drug spawner" + icon_state = "med_drugs" + amount = 5 + chance = 50 + toSpawn = list( + /obj/item/weapon/reagent_containers/glass/beaker/cryoxadone, + /obj/item/weapon/reagent_containers/glass/bottle/antitoxin, + /obj/item/weapon/reagent_containers/glass/bottle/mutagen, + /obj/item/weapon/reagent_containers/glass/bottle/capsaicin, + /obj/item/weapon/reagent_containers/glass/bottle/frostoil, + /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline, + /obj/item/weapon/reagent_containers/glass/bottle/stoxin, + /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate, + /obj/item/weapon/reagent_containers/syringe/inaprovaline, + /obj/item/weapon/reagent_containers/syringe/antitoxin, + /obj/item/weapon/reagent_containers/syringe/antiviral, + /obj/item/weapon/storage/pill_bottle/antitox, + /obj/item/weapon/storage/pill_bottle/inaprovaline, + /obj/item/weapon/storage/pill_bottle/kelotane, + /obj/item/weapon/reagent_containers/blood/OMinus, + /obj/item/weapon/reagent_containers/hypospray/autoinjector, + ) + +/obj/map/spawner/medical/pills + name = "medical pill spawner" + icon_state = "med_pills" + amount = 10 + chance = 75 + jiggle = 6 + toSpawn = list( + /obj/item/weapon/reagent_containers/pill/antitox, + /obj/item/weapon/reagent_containers/pill/tox, + /obj/item/weapon/reagent_containers/pill/stox, + /obj/item/weapon/reagent_containers/pill/kelotane, + /obj/item/weapon/reagent_containers/pill/tramadol, + /obj/item/weapon/reagent_containers/pill/methylphenidate, + /obj/item/weapon/reagent_containers/pill/citalopram, + /obj/item/weapon/reagent_containers/pill/inaprovaline, + /obj/item/weapon/reagent_containers/pill/dexalin, + /obj/item/weapon/reagent_containers/pill/bicaridine, + /obj/item/weapon/reagent_containers/pill/happy, + /obj/item/weapon/reagent_containers/pill/zoom, + ) + +// Security //////////////////////////////////////////////////// + +/obj/map/spawner/security/armor + name = "armory armor spawner" + icon_state = "armory_armor" + toSpawn = list( + /obj/item/clothing/suit/armor/riot, + /obj/item/clothing/suit/armor/bulletproof, + /obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/suit/armor/heavy, + /obj/item/clothing/suit/armor/reactive, + ) + +/obj/map/spawner/security/gear + name = "armory gear spawner" + icon_state = "armory_gear" + amount = 3 + toSpawn = list( + /obj/item/clothing/head/helmet/riot, + /obj/item/weapon/shield/riot, + /obj/item/weapon/melee/baton/loaded, + /obj/item/clothing/suit/armor/vest/security, + /obj/item/weapon/storage/belt/security, + /obj/item/weapon/gun/energy/taser, + /obj/item/device/hailer, + ) + +/obj/map/spawner/security/weapons + name = "armory weapon spawner" + icon_state = "armory_weapons" + toSpawn = list( + /obj/item/weapon/gun/energy/gun, + /obj/item/weapon/gun/energy/ionrifle, + /obj/item/weapon/gun/energy/laser, + /obj/item/weapon/gun/energy/lasercannon, + /obj/item/weapon/gun/projectile/automatic/mini_uzi, + /obj/item/weapon/gun/projectile/automatic, + /obj/item/weapon/gun/projectile/automatic/l6_saw, + /obj/item/weapon/gun/projectile/deagle, + /obj/item/weapon/gun/projectile/mateba, + /obj/item/weapon/gun/projectile/pistol, + /obj/item/weapon/gun/projectile/shotgun/pump, + /obj/item/weapon/gun/projectile/shotgun/pump/combat, + ) + +/obj/map/spawner/security/misc + name = "armory misc spawner" + icon_state = "armory_misc" + amount = 2 + jiggle = 5 + toSpawn = list( + /obj/item/weapon/storage/box/flashbangs, + /obj/item/weapon/storage/box/emps, + /obj/item/weapon/storage/box/handcuffs, + /obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/fancy/donut_box, + ) + +// Engineering ///////////////////////////////////////////////// + +/obj/map/spawner/engi/materials + name = "engie materials spawner" + icon_state = "engi_materials" + amount = 2 + chance = 75 + toSpawn = list( + /obj/item/stack/sheet/glass/glass{amount=50}, + /obj/item/stack/sheet/glass/rglass{amount=50}, + /obj/item/stack/sheet/glass/plasmaglass{amount=50}, + /obj/item/stack/light_w{amount=50}, + /obj/item/stack/sheet/mineral/plastic{amount=50}, + /obj/item/stack/sheet/metal{amount=50}, + /obj/item/stack/sheet/plasteel{amount=50}, + /obj/item/stack/sheet/wood{amount=50}, + /obj/item/stack/rods{amount=50}, + /obj/item/stack/tile/grass{amount=50}, + ) + +/obj/map/spawner/engi/dispensers + name = "engie dispenser spawner" + icon_state = "engi_dispensers" + chance = 50 + toSpawn = list( + /obj/structure/reagent_dispensers/fueltank, + /obj/structure/reagent_dispensers/watertank, + ) + +/obj/map/spawner/engi/machinery + name = "engie machinery spawner" + icon_state = "engi_machinery" + chance = 75 + toSpawn = list( + /obj/machinery/atmospherics/binary/circulator, + /obj/machinery/r_n_d/fabricator/mechanic_fab/autolathe, + /obj/machinery/field_generator, + /obj/machinery/floodlight, + /obj/machinery/mineral/mint, + /obj/machinery/monkey_recycler, + /obj/machinery/photocopier, + /obj/machinery/pipedispenser, + /obj/machinery/porta_turret, + /obj/machinery/power/am_control_unit, + /obj/machinery/power/emitter, + /obj/machinery/power/generator, + /obj/machinery/power/port_gen/pacman/mrs, + /obj/machinery/power/rad_collector, + /obj/machinery/power/rust_core, + /obj/machinery/power/rust_fuel_injector, + /obj/machinery/power/battery/smes, + /obj/machinery/processor, + /obj/machinery/recharge_station, + /obj/machinery/rust/gyrotron, + /obj/machinery/shield_gen, + /obj/machinery/shieldgen, + /obj/machinery/shieldwallgen, + /obj/machinery/space_heater, + /obj/machinery/suit_storage_unit/engie, + /obj/machinery/telecomms/allinone, + /obj/machinery/teleport/station, + /obj/machinery/the_singularitygen, + /obj/machinery/vending/dinnerware, + /obj/machinery/vending/engineering, + /obj/machinery/vending/plasmaresearch, + /obj/machinery/vending/robotics, + /obj/machinery/vending/sovietsoda, + /obj/structure/AIcore, + /obj/structure/device/piano, + /obj/structure/displaycase_frame, + /obj/structure/particle_accelerator/fuel_chamber, + /obj/structure/reagent_dispensers/fueltank, + /obj/structure/reagent_dispensers/water_cooler, + /obj/structure/safe, + /obj/structure/shuttle/engine/router, + /obj/structure/toilet, + /obj/structure/turret/gun_turret, + /obj/spacepod/random, + ) + +// Assistants ////////////////////////////////////////////////// + +/obj/map/spawner/assistant/tools + name = "assistant tool spawner" + icon_state = "ass_tools" + amount = 3 + chance = 50 + toSpawn = list( + /obj/item/device/analyzer, + /obj/item/device/assembly/igniter, + /obj/item/device/assembly/infra, + /obj/item/device/assembly/mousetrap, + /obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/signaler, + /obj/item/device/assembly/timer, + /obj/item/device/assembly/voice, + /obj/item/device/flashlight, + /obj/item/device/lightreplacer, + /obj/item/device/multitool, + /obj/item/device/radio, + /obj/item/device/t_scanner, + /obj/item/device/taperecorder, + /obj/item/device/toner, + /obj/item/device/label_roll, + /obj/item/toy/snappop, + /obj/item/toy/crayon/blue, + /obj/item/toy/crayon/orange, + /obj/item/weapon/c_tube, + /obj/item/stack/cable_coil/random, + /obj/item/weapon/camera_assembly, + /obj/item/weapon/cell, + /obj/item/weapon/crowbar, + /obj/item/weapon/weldingtool, + /obj/item/weapon/wirecutters, + /obj/item/weapon/screwdriver, + /obj/item/weapon/wrench, + /obj/item/weapon/extinguisher, + /obj/item/weapon/hand_labeler, + /obj/item/weapon/light/bulb, + /obj/item/weapon/light/tube, + /obj/item/weapon/lighter/random, + /obj/item/weapon/pen, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/storage/belt/utility, + /obj/item/weapon/storage/toolbox/electrical, + ) + +/obj/map/spawner/assistant/materials + name = "assistant materials spawner" + icon_state = "ass_materials" + amount = 2 + chance = 50 + toSpawn = list( + /obj/item/stack/sheet/glass/glass{amount=50}, + /obj/item/stack/sheet/leather{amount=50}, + /obj/item/stack/sheet/mineral/plastic{amount=50}, + /obj/item/stack/sheet/metal{amount=50}, + /obj/item/stack/sheet/wood{amount=50}, + /obj/item/stack/sheet/cloth{amount=50}, + /obj/item/stack/sheet/cardboard{amount=50}, + /obj/item/stack/rods{amount=50}, + /obj/item/stack/sheet/mineral/sandstone{amount=50}, + ) + +// Maintenance ///////////////////////////////////////////////// + +/obj/map/spawner/maint + name = "maint loot spawner" + icon_state = "maint" + amount = 2 + chance = 50 + toSpawn = list( + /obj/item/device/assembly/igniter, + /obj/item/device/assembly/infra, + /obj/item/device/assembly/mousetrap, + /obj/item/device/assembly/prox_sensor, + /obj/item/device/assembly/signaler, + /obj/item/device/assembly/timer, + /obj/item/device/assembly/voice, + /obj/item/weapon/storage/belt/utility, + /obj/item/device/multitool, + /obj/item/device/paicard, + /obj/item/device/flashlight, + /obj/item/device/flashlight/lantern, + /obj/item/device/flashlight/flare, + /obj/item/weapon/weldingtool/largetank, + /obj/item/device/gps, + /obj/item/device/gps/science, + /obj/item/device/gps/engineering, + /obj/item/weapon/cell/super, + /obj/item/weapon/soap/nanotrasen, + /obj/item/device/flash, + /obj/item/device/transfer_valve, + /obj/item/device/camera_bug, + /obj/item/device/handtv, + /obj/item/device/camera, + /obj/item/device/camera_film, + /obj/item/device/encryptionkey, + /obj/item/device/encryptionkey, + /obj/item/device/encryptionkey, + /obj/item/device/encryptionkey/syndicate, + /obj/item/device/encryptionkey/binary, + /obj/item/device/encryptionkey/syndicate/hacked, + /obj/item/device/hailer, + /obj/item/device/healthanalyzer, + /obj/item/device/mass_spectrometer, + /obj/item/device/megaphone, + /obj/item/device/mmi/radio_enabled, + /obj/item/device/powersink, + /obj/item/device/reagent_scanner, + /obj/item/device/soundsynth, + /obj/item/latexballon, + /obj/item/weapon/storage/toolbox/electrical, + /obj/item/ammo_storage/magazine/a12mm, + /obj/item/ammo_storage/box/c45, + /obj/item/ammo_storage/box/a418, + /obj/item/ammo_storage/magazine/a75, + /obj/item/ammo_storage/speedloader/c38, + /obj/item/ammo_storage/box/c9mm, + /obj/item/ammo_storage/magazine/mc9mm, + /obj/item/bodybag, + /obj/item/clothing/ears/earmuffs, + /obj/item/clothing/glasses/eyepatch, + /obj/item/clothing/glasses/regular, + /obj/item/clothing/glasses/regular/hipster, + /obj/item/clothing/glasses/sunglasses/blindfold, + /obj/item/clothing/glasses/sunglasses/prescription, + /obj/item/clothing/glasses/welding, + /obj/item/clothing/gloves/brown, + /obj/item/clothing/gloves/latex, + /obj/item/clothing/gloves/black, + /obj/item/clothing/gloves/fyellow, + /obj/item/clothing/gloves/purple, + /obj/item/clothing/head/beret, + /obj/item/clothing/head/cakehat, + /obj/item/clothing/head/cardborg, + /obj/item/clothing/head/chicken, + /obj/item/clothing/head/collectable/flatcap, + /obj/item/clothing/head/collectable/pirate, + /obj/item/clothing/head/collectable/wizard, + /obj/item/clothing/head/collectable/tophat, + /obj/item/clothing/head/nun_hood, + /obj/item/clothing/head/plaguedoctorhat, + /obj/item/clothing/head/soft/grey, + /obj/item/clothing/head/surgery/blue, + /obj/item/clothing/head/welding, + /obj/item/clothing/mask/cigarette, + /obj/item/clothing/shoes/laceup, + /obj/item/clothing/glasses/welding/superior, + /obj/item/clothing/glasses/sunglasses/sechud, + /obj/item/clothing/glasses/meson, + /obj/item/clothing/gloves/yellow, + /obj/item/clothing/gloves/knuckles, + /obj/item/clothing/gloves/knuckles/spiked, + /obj/item/clothing/head/bomb_hood, + /obj/item/clothing/mask/gas, + /obj/item/clothing/mask/gas/monkeymask, + /obj/item/clothing/mask/gas/owl_mask, + /obj/item/clothing/mask/gas/plaguedoctor, + /obj/item/clothing/mask/gas/sexyclown, + /obj/item/clothing/mask/muzzle, + /obj/item/clothing/mask/pig, + /obj/item/clothing/mask/horsehead, + /obj/item/clothing/shoes/sandal, + /obj/item/clothing/suit/bio_suit, + /obj/item/clothing/suit/bio_suit/plaguedoctorsuit, + /obj/item/clothing/suit/bomb_suit, + /obj/item/clothing/suit/fire/firefighter, + /obj/item/clothing/suit/monkeysuit, + /obj/item/clothing/suit/pirate, + /obj/item/clothing/suit/radiation, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/storage/fr_jacket, + /obj/item/clothing/suit/storage/hazardvest, + /obj/item/clothing/suit/storage/lawyer/purpjacket, + /obj/item/clothing/suit/storage/paramedic, + /obj/item/clothing/suit/suspenders, + /obj/item/clothing/suit/syndicatefake, + /obj/item/clothing/suit/unathi/mantle, + /obj/item/clothing/suit/unathi/robe, + /obj/item/clothing/accessory/tie/horrible, + /obj/item/clothing/accessory/armband/cargo, + /obj/item/clothing/accessory/armband, + /obj/item/clothing/accessory/armband/engine, + /obj/item/clothing/accessory/armband/hydro, + /obj/item/clothing/accessory/holster/armpit, + /obj/item/clothing/under/blackskirt, + /obj/item/clothing/mask/gas/voice, + /obj/item/clothing/head/bandana, + /obj/item/clothing/head/rabbitears, + /obj/item/clothing/head/kitty, + /obj/item/clothing/head/hairflower, + /obj/item/clothing/head/helmet/roman, + /obj/item/clothing/head/helmet/roman/legionaire, + /obj/item/clothing/head/pumpkinhead, + /obj/item/clothing/head/soft/rainbow, + /obj/item/clothing/head/soft/sec, + /obj/item/clothing/head/syndicatefake, + /obj/item/clothing/head/wizard/marisa/fake, + /obj/item/clothing/suit/wizrobe/marisa/fake, + /obj/item/clothing/head/wizard/fake, + /obj/item/clothing/suit/wizrobe/fake, + /obj/item/clothing/mask/balaclava, + /obj/item/clothing/mask/luchador/tecnicos, + /obj/item/clothing/mask/luchador/rudos, + /obj/item/clothing/mask/cigarette/cigar, + /obj/item/clothing/mask/fakemoustache, + /obj/item/clothing/shoes/galoshes, + /obj/item/clothing/shoes/jackboots, + /obj/item/clothing/shoes/roman, + /obj/item/clothing/shoes/syndigaloshes, + /obj/item/clothing/suit/chickensuit, + /obj/item/clothing/under/captain_fly, + /obj/item/clothing/under/dress/dress_saloon, + /obj/item/clothing/under/dress/dress_yellow, + /obj/item/clothing/under/dress/dress_pink, + /obj/item/clothing/under/dress/dress_orange, + /obj/item/clothing/under/dress/dress_fire, + /obj/item/clothing/under/dress/dress_green, + /obj/item/clothing/under/gladiator, + /obj/item/clothing/under/johnny, + /obj/item/clothing/under/kilt, + /obj/item/clothing/under/lawyer/purpsuit, + /obj/item/clothing/under/lawyer/female, + /obj/item/clothing/under/overalls, + /obj/item/clothing/under/owl, + /obj/item/clothing/under/pirate, + /obj/item/clothing/under/psyche, + /obj/item/clothing/under/psysuit, + /obj/item/clothing/under/rainbow, + /obj/item/clothing/under/schoolgirl, + /obj/item/clothing/under/sexyclown, + /obj/item/clothing/under/rank/mailman, + /obj/item/clothing/under/shorts/green, + /obj/item/clothing/under/shorts/red, + /obj/item/clothing/under/shorts/grey, + /obj/item/clothing/under/stripper/mankini, + /obj/item/clothing/under/sundress, + /obj/item/clothing/under/swimsuit/black, + /obj/item/clothing/under/swimsuit/purple, + /obj/item/clothing/under/syndicate/tacticool, + /obj/item/clothing/under/syndicate, + /obj/item/clothing/under/waiter, + /obj/item/clothing/under/wedding/bride_blue, + /obj/item/clothing/under/wedding/bride_purple, + /obj/item/clothing/under/wedding/bride_white, + /obj/item/pizzabox/meat, + /obj/item/pizzabox/margherita, + /obj/item/pizzabox/vegetable, + /obj/item/pizzabox/mushroom, + /obj/item/robot_parts/robot_component/actuator, + /obj/item/robot_parts/robot_component/armour, + /obj/item/robot_parts/robot_component/binary_communication_device, + /obj/item/robot_parts/chest, + /obj/item/robot_parts/robot_suit, + /obj/item/roller, + /obj/item/stack/medical/ointment, + /obj/item/stack/medical/bruise_pack, + /obj/item/stack/medical/advanced/bruise_pack, + /obj/item/stack/medical/advanced/ointment, + /obj/item/stack/nanopaste, + /obj/item/taperoll/engineering, + /obj/item/taperoll/police, + /obj/item/toy/ammo/gun, + /obj/item/toy/balloon, + /obj/item/toy/crayon/red, + /obj/item/toy/crayon/yellow, + /obj/item/toy/crayon/blue, + /obj/item/toy/crossbow, + /obj/item/toy/gun, + /obj/item/toy/snappop, + /obj/item/toy/sword, + /obj/item/toy/bomb, + /obj/item/clothing/mask/facehugger/toy, + /obj/item/trash/candle, + /obj/item/trash/candy, + /obj/item/trash/cheesie, + /obj/item/trash/chips, + /obj/item/trash/plate, + /obj/item/trash/popcorn, + /obj/item/trash/raisins, + /obj/item/trash/sosjerky, + /obj/item/clothing/accessory/medal/conduct, + /obj/item/weapon/bananapeel, + /obj/item/weapon/corncob, + /obj/item/weapon/bikehorn, + /obj/item/weapon/c_tube, + /obj/item/weapon/legcuffs/beartrap, + /obj/item/weapon/caution, + /obj/item/weapon/rack_parts, + /obj/item/weapon/caution/cone, + /obj/item/weapon/beach_ball, + /obj/item/weapon/bee_net, + /obj/item/weapon/bikehorn/rubberducky, + /obj/item/weapon/broken_bottle, + /obj/item/weapon/bucket_sensor, + /obj/item/stack/cable_coil, + /obj/item/weapon/camera_assembly, + /obj/item/weapon/cigbutt/cigarbutt, + /obj/item/weapon/clipboard, + /obj/item/weapon/coin, + /obj/item/weapon/coin/gold, + /obj/item/weapon/coin/adamantine, + /obj/item/weapon/coin/clown, + /obj/item/weapon/coin/diamond, + /obj/item/weapon/coin/iron, + /obj/item/weapon/coin/phazon, + /obj/item/weapon/coin/plasma, + /obj/item/weapon/coin/silver, + /obj/item/weapon/coin/uranium, + /obj/item/weapon/dice, + /obj/item/weapon/flamethrower/full, + /obj/item/weapon/gun/projectile/deagle/gold, + /obj/item/weapon/gun/projectile/russian, + /obj/item/weapon/handcuffs, + /obj/item/weapon/handcuffs/cable, + /obj/item/weapon/hatchet, + /obj/item/weapon/kitchen/rollingpin, + /obj/item/weapon/lighter/random, + /obj/item/weapon/lipstick/random, + /obj/item/weapon/minihoe, + /obj/item/weapon/mop, + /obj/item/weapon/newspaper, + /obj/item/weapon/pen, + /obj/item/weapon/scalpel, + /obj/item/weapon/shard, + /obj/item/weapon/stool, + /obj/item/device/powersink, + /obj/item/weapon/reagent_containers/blood/OMinus, + /obj/item/weapon/reagent_containers/glass/bottle/ammonia, + /obj/item/weapon/reagent_containers/glass/bottle/capsaicin, + /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate, + /obj/item/weapon/reagent_containers/glass/bottle/cold, + /obj/item/weapon/reagent_containers/glass/bottle/diethylamine, + /obj/item/weapon/reagent_containers/glass/bottle/epiglottis_virion, + /obj/item/weapon/reagent_containers/glass/bottle/flu_virion, + /obj/item/weapon/reagent_containers/glass/bottle/magnitis, + /obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat, + /obj/item/weapon/reagent_containers/food/drinks/beer, + /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, + /obj/item/weapon/reagent_containers/food/drinks/bottle/cream, + /obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice, + /obj/item/weapon/reagent_containers/food/drinks/bottle/tequila, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth, + /obj/item/weapon/reagent_containers/food/drinks/bottle/wine, + /obj/item/weapon/reagent_containers/food/drinks/coffee, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko, + /obj/item/weapon/reagent_containers/food/snacks/pie/amanita_pie, + /obj/item/weapon/reagent_containers/food/snacks/amanitajelly, + /obj/item/weapon/reagent_containers/food/snacks/applecakeslice, + /obj/item/weapon/reagent_containers/food/snacks/pie/applepie, + /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger, + /obj/item/weapon/reagent_containers/food/snacks/boiledegg, + /obj/item/weapon/reagent_containers/food/snacks/brainburger, + /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat, + /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers, + /obj/item/weapon/reagent_containers/food/snacks/chips, + /obj/item/weapon/reagent_containers/food/snacks/chocolatebar/wrapped, + /obj/item/weapon/reagent_containers/food/snacks/clownstears, + /obj/item/weapon/reagent_containers/food/snacks/coldchili, + /obj/item/weapon/reagent_containers/food/snacks/corgikabob, + /obj/item/weapon/reagent_containers/food/snacks/donkpocket, + /obj/item/weapon/reagent_containers/food/snacks/donut, + /obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey, + /obj/item/weapon/reagent_containers/food/snacks/no_raisin, + /obj/item/weapon/reagent_containers/food/snacks/pie/plump_pie, + /obj/item/weapon/reagent_containers/food/snacks/soylenviridians, + /obj/item/weapon/reagent_containers/food/snacks/syndicake, + /obj/item/weapon/reagent_containers/food/snacks/tofurkey, + ) + +// Space /////////////////////////////////////////////////////// + +/obj/map/spawner/space/weapons + name = "space weapons spawner" + icon_state = "space_weapons" + chance = 20 + toSpawn = list( + /obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver, + /obj/item/weapon/crossbow, + /obj/item/weapon/grenade/spawnergrenade/manhacks, + /obj/item/weapon/grenade/spawnergrenade/spesscarp, + /obj/item/weapon/grenade/flashbang/clusterbang, + /obj/item/weapon/grenade/empgrenade, + /obj/item/weapon/gun/dartgun/vox/raider, + /obj/item/weapon/gun/energy/decloner, + /obj/item/weapon/gun/energy/laser/retro, + /obj/item/weapon/gun/energy/mindflayer, + /obj/item/weapon/gun/energy/temperature, + /obj/item/weapon/gun/energy/xray, + /obj/item/weapon/gun/projectile/gyropistol, + /obj/item/weapon/gun/projectile/pistol, + /obj/item/weapon/gun/projectile/russian, + /obj/item/weapon/gun/projectile/silenced, + /obj/item/weapon/harpoon, + /obj/item/weapon/melee/classic_baton, + /obj/item/weapon/pickaxe/plasmacutter, + /obj/item/weapon/shield/energy, + /obj/item/weapon/organ/head, + /obj/item/weapon/organ/r_leg, + /obj/item/weapon/organ/l_arm, + /obj/item/weapon/organ/l_foot, + ) + +/obj/map/spawner/space/tools + name = "space tool spawner" + icon_state = "space_tools" + chance = 50 + toSpawn = list( + /obj/item/bluespace_crystal, + /obj/item/bodybag/cryobag, + /obj/item/borg/upgrade/syndicate, + /obj/item/clothing/glasses/thermal, + /obj/item/device/aicard, + /obj/item/device/ano_scanner, + /obj/item/device/flashlight/lantern, + /obj/item/device/flashlight, + /obj/item/device/handtv, + /obj/item/device/paicard, + /obj/item/device/robotanalyzer, + /obj/item/device/t_scanner, + /obj/item/device/transfer_valve, + /obj/item/device/wormhole_jaunter, + /obj/item/device/reagent_scanner/adv, + /obj/item/mecha_parts/mecha_equipment/repair_droid, + /obj/item/mecha_parts/mecha_equipment/teleporter, + /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay, + /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill, + /obj/item/mecha_parts/mecha_equipment/tool/cable_layer, + /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp, + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack, + /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion, + /obj/item/mecha_parts/mecha_equipment/wormhole_generator, + /obj/item/mecha_parts/mecha_tracking, + /obj/item/mecha_parts/part/phazon_phase_array, + /obj/item/mecha_parts/part/durand_torso, + /obj/item/mecha_parts/part/gygax_right_leg, + /obj/item/mecha_parts/part/odysseus_torso, + /obj/item/mecha_parts/part/ripley_left_arm, + /obj/item/robot_parts/robot_suit, + /obj/item/robot_parts/head, + /obj/item/weapon/autopsy_scanner, + /obj/item/stack/cable_coil/pink, + /obj/item/weapon/cell/hyper, + /obj/item/weapon/ed209_assembly, + /obj/item/weapon/firstaid_arm_assembly, + /obj/item/weapon/grenade/chem_grenade/metalfoam, + /obj/item/weapon/grenade/chem_grenade/antiweed, + /obj/item/weapon/hatchet, + /obj/item/weapon/pickaxe/jackhammer, + /obj/item/device/rcd/rpd, + /obj/item/device/rcd, + /obj/item/weapon/rcd_ammo, + /obj/item/device/rcd/matter/rsf, + /obj/item/weapon/weldingtool/hugetank, + /obj/item/weapon/tank/plasma, + /obj/item/gun_part/silencer, + /obj/item/weapon/storage/backpack/holding, + ) + +/obj/map/spawner/space/gear + name = "space gear spawner" + icon_state = "space_gear" + chance = 30 + toSpawn = list( + /obj/item/clothing/mask/cigarette/cigar/cohiba, + /obj/item/clothing/mask/cigarette/pipe/cobpipe, + /obj/item/clothing/mask/balaclava, + /obj/item/clothing/mask/gas/cyborg, + /obj/item/clothing/shoes/magboots, + /obj/item/clothing/gloves/yellow, + /obj/item/clothing/suit/bio_suit/janitor, + /obj/item/clothing/suit/fire/heavy, + /obj/item/clothing/suit/radiation, + /obj/item/clothing/head/helmet/space/syndicate/black/blue, + /obj/item/clothing/suit/space/syndicate/black/blue, + /obj/item/clothing/head/helmet/space/syndicate/black/med, + /obj/item/clothing/suit/space/syndicate/black/med, + /obj/item/clothing/head/helmet/space/syndicate/black/engie, + /obj/item/clothing/suit/space/syndicate/black/engie, + /obj/item/clothing/accessory/storage/webbing, + /obj/item/clothing/accessory/storage/brown_vest, + /obj/item/weapon/organ/head, + /obj/item/weapon/organ/r_leg, + /obj/item/weapon/organ/l_arm, + /obj/item/weapon/organ/l_foot, + ) + +/obj/map/spawner/space/supply + name = "space supply spawner" + icon_state = "space_supply" + amount = 2 + chance = 50 + toSpawn = list( + /obj/item/clothing/mask/breath/medical, + /obj/item/device/radio, + /obj/item/device/flashlight/flare, + /obj/item/weapon/extinguisher, + /obj/item/weapon/tank/oxygen/yellow, + /obj/item/weapon/tank/nitrogen, + /obj/item/weapon/tank/emergency_oxygen/engi, + /obj/item/weapon/tank/emergency_oxygen/double, + /obj/item/weapon/tank/anesthetic, + /obj/item/weapon/storage/toolbox/electrical, + /obj/item/weapon/storage/toolbox/syndicate, + /obj/item/weapon/storage/box/autoinjectors, + /obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/fancy/matchbox, + /obj/item/weapon/storage/fancy/donut_box, + /obj/item/weapon/storage/firstaid/adv, + /obj/item/weapon/storage/firstaid/regular, + /obj/item/weapon/reagent_containers/pill/happy, + /obj/item/weapon/reagent_containers/glass/bottle/random, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/snacks/appendixburger, + /obj/item/weapon/reagent_containers/food/snacks/bloodsoup, + /obj/item/weapon/reagent_containers/food/snacks/candy/donor, + /obj/item/weapon/reagent_containers/food/snacks/clownburger, + /obj/item/weapon/reagent_containers/food/snacks/mysterysoup, + /obj/item/weapon/reagent_containers/food/snacks/donut/chaos, + //obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chilli, + /obj/item/weapon/reagent_containers/food/snacks/wingfangchu, + /obj/item/weapon/reagent_containers/food/snacks/soylentgreen, + /obj/item/weapon/reagent_containers/food/snacks/meat/bearmeat, + /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat, + ) + +/obj/map/spawner/space/drinks + name = "space drinks spawner" + icon_state = "space_drinks" + chance = 50 + amount = 4 + jiggle = 5 + toSpawn = list( + /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, + /obj/item/weapon/reagent_containers/food/drinks/beer, + /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, + /obj/item/weapon/reagent_containers/food/drinks/bottle/rum, + /obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo, + /obj/item/weapon/reagent_containers/food/drinks/groansbanned, + ) + +/obj/map/spawner/space/russian + name = "space russian spawner" + icon_state = "space_russian" + chance = 5 + toSpawn = list(/mob/living/simple_animal/hostile/humanoid/russian/ranged) + +// Mobs //////////////////////////////////////////////////////// + +/obj/map/spawner/mobs/carp + name = "carp spawner" + icon_state = "mob_carp" + chance = 50 + toSpawn = list(/mob/living/simple_animal/hostile/carp) + +/obj/map/spawner/mobs/lizard + name = "lizard spawner" + icon_state = "mob_lizard" + amount = 2 + chance = 50 + toSpawn = list(/mob/living/simple_animal/lizard) + +/obj/map/spawner/mobs/mouse + name = "mouse spawner" + icon_state = "mob_mouse" + amount = 2 + chance = 50 + toSpawn = list( + /mob/living/simple_animal/mouse/brown, + /mob/living/simple_animal/mouse/gray, + /mob/living/simple_animal/mouse/white, + ) + +/obj/map/spawner/mobs/bear + name = "bear spawner" + icon_state = "mob_bear" + chance = 50 + toSpawn = list(/mob/living/simple_animal/hostile/bear) + +/obj/map/spawner/mobs/spider + name = "spider spawner" + icon_state = "mob_spider" + amount = 3 + chance = 50 + toSpawn = list( + /mob/living/simple_animal/hostile/giant_spider, + /mob/living/simple_animal/hostile/giant_spider/nurse, + /mob/living/simple_animal/hostile/giant_spider/hunter, + ) + +// Robutts ///////////////////////////////////////////////////// + +/obj/map/spawner/robot/any + name = "robot spawner" + icon_state = "robot_any" + chance = 20 + toSpawn = list( + /obj/machinery/bot/cleanbot, + /obj/machinery/bot/farmbot, + /obj/machinery/bot/floorbot, + /obj/machinery/bot/medbot, + /obj/machinery/bot/secbot, + ) + +/obj/map/spawner/robot/sec + name = "secbot spawner" + icon_state = "robot_sec" + toSpawn = list(/obj/machinery/bot/secbot) + +/obj/map/spawner/robot/clean + name = "cleanbot spawner" + icon_state = "robot_clean" + toSpawn = list(/obj/machinery/bot/cleanbot) + +/obj/map/spawner/robot/med + name = "medbot spawner" + icon_state = "robot_med" + toSpawn = list(/obj/machinery/bot/medbot) + +/obj/map/spawner/robot/floor + name = "floorbot spawner" + icon_state = "robot_floor" + toSpawn = list(/obj/machinery/bot/floorbot) + +/obj/map/spawner/robot/farm + name = "farmbot spawner" + icon_state = "robot_farm" + toSpawn = list(/obj/machinery/bot/farmbot) + +// Seeds /////////////////////////////////////////////////////// + +/obj/map/spawner/misc/seeds + name = "seed spawner" + icon_state = "seeds" + chance = 50 + amount = 4 + jiggle = 5 + toSpawn = list( + /obj/item/seeds/amanitamycelium, + /obj/item/seeds/ambrosiadeusseed, + /obj/item/seeds/ambrosiavulgarisseed, + /obj/item/seeds/angelmycelium, + /obj/item/seeds/appleseed, + /obj/item/seeds/bananaseed, + /obj/item/seeds/berryseed, + /obj/item/seeds/bloodtomatoseed, + /obj/item/seeds/bluespacetomatoseed, + /obj/item/seeds/cabbageseed, + /obj/item/seeds/carrotseed, + /obj/item/seeds/chantermycelium, + /obj/item/seeds/cherryseed, + /obj/item/seeds/chiliseed, + /obj/item/seeds/cocoapodseed, + /obj/item/seeds/cornseed, + /obj/item/seeds/deathberryseed, + /obj/item/seeds/deathnettleseed, + /obj/item/seeds/eggplantseed, + /obj/item/seeds/eggyseed, + /obj/item/seeds/glowberryseed, + /obj/item/seeds/glowshroom, + /obj/item/seeds/goldappleseed, + /obj/item/seeds/grapeseed, + /obj/item/seeds/grassseed, + /obj/item/seeds/greengrapeseed, + /obj/item/seeds/harebell, + /obj/item/seeds/icepepperseed, + /obj/item/seeds/killertomatoseed, + /obj/item/seeds/koiseed, + /obj/item/seeds/kudzuseed, + /obj/item/seeds/lemonseed, + /obj/item/seeds/libertymycelium, + /obj/item/seeds/limeseed, + /obj/item/seeds/moonflowerseed, + /obj/item/seeds/nettleseed, + /obj/item/seeds/novaflowerseed, + /obj/item/seeds/orangeseed, + /obj/item/seeds/plastiseed, + /obj/item/seeds/plumpmycelium, + /obj/item/seeds/poisonberryseed, + /obj/item/seeds/poisonedappleseed, + /obj/item/seeds/poppyseed, + /obj/item/seeds/potatoseed, + /obj/item/seeds/pumpkinseed, + /obj/item/seeds/reishimycelium, + /obj/item/seeds/dionanode, + /obj/item/seeds/riceseed, + /obj/item/seeds/soyaseed, + /obj/item/seeds/sugarcaneseed, + /obj/item/seeds/sunflowerseed, + //obj/item/seeds/synthbrainseed, + //obj/item/seeds/synthbuttseed, + //obj/item/seeds/synthmeatseed, + /obj/item/seeds/tomatoseed, + /obj/item/seeds/towermycelium, + /obj/item/seeds/walkingmushroommycelium, + /obj/item/seeds/watermelonseed, + /obj/item/seeds/wheatseed, + /obj/item/seeds/whitebeetseed, + /obj/item/seeds/cinnamomum, + ) diff --git a/code/modules/mining/machine_input_output_plates.dm b/code/modules/mining/machine_input_output_plates.dm index 8a79434cf86..69f0a02b658 100644 --- a/code/modules/mining/machine_input_output_plates.dm +++ b/code/modules/mining/machine_input_output_plates.dm @@ -1,32 +1,32 @@ -/**********************Input and output plates**************************/ - -/obj/machinery/mineral/input - icon = 'icons/mob/screen1.dmi' - icon_state = "x2" - name = "Input area" - density = 0 - anchored = 1.0 - New() - ..() - icon_state = "blank" - -/obj/machinery/mineral/output - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - name = "Output area" - density = 0 - anchored = 1.0 - New() - ..() - icon_state = "blank" - -/obj/machinery/mineral/selected_output - icon = 'icons/mob/screen1.dmi' - icon_state = "x3" - name = "Selected Output area" - desc = "Where we put things that we wanted." - density = 0 - anchored = 1.0 - New() - ..() +/**********************Input and output plates**************************/ + +/obj/machinery/mineral/input + icon = 'icons/mob/screen1.dmi' + icon_state = "x2" + name = "Input area" + density = 0 + anchored = 1.0 + New() + ..() + icon_state = "blank" + +/obj/machinery/mineral/output + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + name = "Output area" + density = 0 + anchored = 1.0 + New() + ..() + icon_state = "blank" + +/obj/machinery/mineral/selected_output + icon = 'icons/mob/screen1.dmi' + icon_state = "x3" + name = "Selected Output area" + desc = "Where we put things that we wanted." + density = 0 + anchored = 1.0 + New() + ..() icon_state = "blank" \ No newline at end of file diff --git a/code/modules/mining/mine_areas.dm b/code/modules/mining/mine_areas.dm index 5b981317ebd..1763d53e32b 100644 --- a/code/modules/mining/mine_areas.dm +++ b/code/modules/mining/mine_areas.dm @@ -1,56 +1,56 @@ -/**********************Mine areas**************************/ - -/area/mine - icon_state = "mining" - music = 'sound/ambience/song_game.ogg' - - general_area = /area/mine - general_area_name = "Mining Station" - -/area/mine/explored - name = "Mine" - icon_state = "explored" - -/area/mine/unexplored - name = "Mine" - icon_state = "unexplored" - -//TODO: Make all these types inherit from /area/mining_outpost/ instead. -/area/mine/lobby - name = "Mining station" - -/area/mine/storage - name = "Mining station Storage" - -/area/mine/production - name = "Mining Station Starboard Wing" - icon_state = "mining_production" - -/area/mine/abandoned - name = "Abandoned Mining Station" - -/area/mine/living_quarters - name = "Mining Station Port Wing" - icon_state = "mining_living" - -/area/mine/eva - name = "Mining Station EVA" - icon_state = "mining_eva" - -/area/mine/maintenance - name = "Mining Station Communications" - -/area/mine/cafeteria - name = "Mining station Cafeteria" - -/area/mine/hydroponics - name = "Mining station Hydroponics" - -/area/mine/sleeper - name = "Mining station Emergency Sleeper" - -/area/mine/north_outpost - name = "North Mining Outpost" - -/area/mine/west_outpost +/**********************Mine areas**************************/ + +/area/mine + icon_state = "mining" + music = 'sound/ambience/song_game.ogg' + + general_area = /area/mine + general_area_name = "Mining Station" + +/area/mine/explored + name = "Mine" + icon_state = "explored" + +/area/mine/unexplored + name = "Mine" + icon_state = "unexplored" + +//TODO: Make all these types inherit from /area/mining_outpost/ instead. +/area/mine/lobby + name = "Mining station" + +/area/mine/storage + name = "Mining station Storage" + +/area/mine/production + name = "Mining Station Starboard Wing" + icon_state = "mining_production" + +/area/mine/abandoned + name = "Abandoned Mining Station" + +/area/mine/living_quarters + name = "Mining Station Port Wing" + icon_state = "mining_living" + +/area/mine/eva + name = "Mining Station EVA" + icon_state = "mining_eva" + +/area/mine/maintenance + name = "Mining Station Communications" + +/area/mine/cafeteria + name = "Mining station Cafeteria" + +/area/mine/hydroponics + name = "Mining station Hydroponics" + +/area/mine/sleeper + name = "Mining station Emergency Sleeper" + +/area/mine/north_outpost + name = "North Mining Outpost" + +/area/mine/west_outpost name = "West Mining Outpost" \ No newline at end of file diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index 486c818f707..60c85ca25a5 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -1,80 +1,80 @@ -/*****************************Money bag********************************/ - -/obj/item/weapon/moneybag - icon = 'icons/obj/storage.dmi' - name = "Money bag" - icon_state = "moneybag" - flags = FPRINT - siemens_coefficient = 1 - force = 10.0 - throwforce = 2.0 - w_class = 4.0 - - var/datum/materials/coin_value - -/obj/item/weapon/moneybag/attack_hand(user as mob) - var/credits=0 - if(!coin_value) - coin_value = getFromPool(/datum/materials) - else - coin_value.resetVariables() //make its storage be 0 - - for (var/obj/item/weapon/coin/C in contents) - if (istype(C,/obj/item/weapon/coin)) - coin_value.addAmount(C.material, 1) - credits += C.credits - - var/dat = "The contents of the moneybag reveal...
      " - for(var/ore_id in coin_value.storage) - var/datum/material/ore_info = coin_value.getMaterial(ore_id) - if(coin_value.storage[ore_id]) - dat += "
    • [ore_info.processed_name] coins: [coin_value.storage[ore_id]] Remove one
    • " - dat += "
    Total haul: $[credits]" - user << browse("[dat]", "window=moneybag") - -/obj/item/weapon/moneybag/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if (istype(W, /obj/item/weapon/coin)) - if(usr.drop_item(W, src)) - var/obj/item/weapon/coin/C = W - to_chat(user, "You add the [C.name] into the bag.") - if (istype(W, /obj/item/weapon/moneybag)) - var/obj/item/weapon/moneybag/C = W - for (var/obj/O in C.contents) - contents += O - to_chat(user, "You empty the [C.name] into the bag.") - return - -/obj/item/weapon/moneybag/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(href_list["remove"]) - var/datum/material/material = coin_value.getMaterial(href_list["remove"]) - var/obj/item/weapon/coin/COIN=locate(material.cointype, src.contents) - if(!COIN) - return - COIN.loc = get_turf(src) - if(!usr.get_active_hand()) - usr.put_in_hands(COIN) - return - -/obj/item/weapon/moneybag/MouseDrop(obj/over_object as obj) - if(ishuman(usr)) - if(over_object == usr) - var/mob/living/carbon/human/H = usr - H.put_in_hands(src) - - -/obj/item/weapon/moneybag/vault - -/obj/item/weapon/moneybag/vault/New() - ..() - new /obj/item/weapon/coin/silver(src) - new /obj/item/weapon/coin/silver(src) - new /obj/item/weapon/coin/silver(src) - new /obj/item/weapon/coin/silver(src) - new /obj/item/weapon/coin/gold(src) - new /obj/item/weapon/coin/gold(src) +/*****************************Money bag********************************/ + +/obj/item/weapon/moneybag + icon = 'icons/obj/storage.dmi' + name = "Money bag" + icon_state = "moneybag" + flags = FPRINT + siemens_coefficient = 1 + force = 10.0 + throwforce = 2.0 + w_class = 4.0 + + var/datum/materials/coin_value + +/obj/item/weapon/moneybag/attack_hand(user as mob) + var/credits=0 + if(!coin_value) + coin_value = getFromPool(/datum/materials) + else + coin_value.resetVariables() //make its storage be 0 + + for (var/obj/item/weapon/coin/C in contents) + if (istype(C,/obj/item/weapon/coin)) + coin_value.addAmount(C.material, 1) + credits += C.credits + + var/dat = "The contents of the moneybag reveal...
      " + for(var/ore_id in coin_value.storage) + var/datum/material/ore_info = coin_value.getMaterial(ore_id) + if(coin_value.storage[ore_id]) + dat += "
    • [ore_info.processed_name] coins: [coin_value.storage[ore_id]] Remove one
    • " + dat += "
    Total haul: $[credits]" + user << browse("[dat]", "window=moneybag") + +/obj/item/weapon/moneybag/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if (istype(W, /obj/item/weapon/coin)) + if(usr.drop_item(W, src)) + var/obj/item/weapon/coin/C = W + to_chat(user, "You add the [C.name] into the bag.") + if (istype(W, /obj/item/weapon/moneybag)) + var/obj/item/weapon/moneybag/C = W + for (var/obj/O in C.contents) + contents += O + to_chat(user, "You empty the [C.name] into the bag.") + return + +/obj/item/weapon/moneybag/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if(href_list["remove"]) + var/datum/material/material = coin_value.getMaterial(href_list["remove"]) + var/obj/item/weapon/coin/COIN=locate(material.cointype, src.contents) + if(!COIN) + return + COIN.loc = get_turf(src) + if(!usr.get_active_hand()) + usr.put_in_hands(COIN) + return + +/obj/item/weapon/moneybag/MouseDrop(obj/over_object as obj) + if(ishuman(usr)) + if(over_object == usr) + var/mob/living/carbon/human/H = usr + H.put_in_hands(src) + + +/obj/item/weapon/moneybag/vault + +/obj/item/weapon/moneybag/vault/New() + ..() + new /obj/item/weapon/coin/silver(src) + new /obj/item/weapon/coin/silver(src) + new /obj/item/weapon/coin/silver(src) + new /obj/item/weapon/coin/silver(src) + new /obj/item/weapon/coin/gold(src) + new /obj/item/weapon/coin/gold(src) new /obj/item/weapon/coin/adamantine(src) \ No newline at end of file diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm index 091d66a55e6..5feb5d810e6 100644 --- a/code/modules/mob/dead/observer/login.dm +++ b/code/modules/mob/dead/observer/login.dm @@ -1,23 +1,23 @@ -/mob/dead/observer/Login() - ..() - - if(src.check_rights(R_ADMIN|R_FUN)) +/mob/dead/observer/Login() + ..() + + if(src.check_rights(R_ADMIN|R_FUN)) to_chat(src, "You are now an admin ghost. Think of yourself as an AI that doesn't show up anywhere and cannot speak. You can access any console or machine by standing next to it and clicking on it. Abuse of this privilege may result in hilarity or removal of your flags, so caution is recommended.") - if(istype(canclone) && canclone.mind == mind) - if(can_reenter_corpse && istype(canclone.loc, /obj/machinery/dna_scannernew)) - for(dir in list(NORTH, EAST, SOUTH, WEST)) - if(locate(/obj/machinery/computer/cloning, get_step(canclone.loc, dir))) + if(istype(canclone) && canclone.mind == mind) + if(can_reenter_corpse && istype(canclone.loc, /obj/machinery/dna_scannernew)) + for(dir in list(NORTH, EAST, SOUTH, WEST)) + if(locate(/obj/machinery/computer/cloning, get_step(canclone.loc, dir))) src << 'sound/effects/adminhelp.ogg' to_chat(src, "Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned! \ - (Verbs -> Ghost -> Re-enter corpse, or click here!)") - canclone = null - -/mob/dead/observer/MouseDrop(atom/over) - if(!usr || !over) - return - - if (isobserver(usr) && usr.client.holder && isliving(over)) - if (usr.client.holder.cmd_ghost_drag(src,over)) - return - - return ..() + (Verbs -> Ghost -> Re-enter corpse, or click here!)
    ") + canclone = null + +/mob/dead/observer/MouseDrop(atom/over) + if(!usr || !over) + return + + if (isobserver(usr) && usr.client.holder && isliving(over)) + if (usr.client.holder.cmd_ghost_drag(src,over)) + return + + return ..() diff --git a/code/modules/mob/dead/observer/logout.dm b/code/modules/mob/dead/observer/logout.dm index 11c6c3c834c..b1ec761136f 100644 --- a/code/modules/mob/dead/observer/logout.dm +++ b/code/modules/mob/dead/observer/logout.dm @@ -1,5 +1,5 @@ -/mob/dead/observer/Logout() - ..() - spawn(0) - if(src && !key) //we've transferred to another mob. This ghost should be deleted. - qdel(src) +/mob/dead/observer/Logout() + ..() + spawn(0) + if(src && !key) //we've transferred to another mob. This ghost should be deleted. + qdel(src) diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index ad0939aa850..54cbfbcd0ec 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -1,53 +1,53 @@ -/mob/dead/observer/say(var/message) - message = trim(copytext(message, 1, MAX_MESSAGE_LEN)) - - if (!message) - return - - var/turf/T = get_turf(src) - log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Ghost: [message]") - - if (src.client) - if(src.client.prefs.muted & MUTE_DEADCHAT) +/mob/dead/observer/say(var/message) + message = trim(copytext(message, 1, MAX_MESSAGE_LEN)) + + if (!message) + return + + var/turf/T = get_turf(src) + log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Ghost: [message]") + + if (src.client) + if(src.client.prefs.muted & MUTE_DEADCHAT) to_chat(src, "You cannot talk in deadchat (muted).") - return - - if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT)) - return - - . = src.say_dead(message) - -/mob/dead/observer/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "[pick("moans", "gripes", "grumps", "murmurs", "mumbles", "bleats")], [text]"; - else if (ending == "!") - return "[pick("screams", "screeches", "howls")], [text]"; - - return "[pick("whines", "cries", "spooks", "complains", "drones", "mutters")], [text]"; - -/mob/dead/observer/Hear(var/datum/speech/speech, var/rendered_speech="") - if (isnull(client) || !speech.speaker) - return - - var/source = speech.speaker.GetSource() - var/source_turf = get_turf(source) - - say_testing(src, "/mob/dead/observer/Hear(): source=[source], frequency=[speech.frequency], source_turf=[formatJumpTo(source_turf)]") - - if (get_dist(source_turf, src) <= world.view) // If this isn't true, we can't be in view, so no need for costlier proc. - if (source_turf in view(src)) - rendered_speech = "[rendered_speech]" - else - if(client && client.prefs) - if (!speech.frequency) - if ((client.prefs.toggles & CHAT_GHOSTEARS) != CHAT_GHOSTEARS) - say_testing(src, "/mob/dead/observer/Hear(): CHAT_GHOSTEARS is disabled, blocking. ([client.prefs.toggles] & [CHAT_GHOSTEARS]) = [client.prefs.toggles & CHAT_GHOSTEARS]") - return - else - if ((client.prefs.toggles & CHAT_GHOSTRADIO) != CHAT_GHOSTRADIO) - say_testing(src, "/mob/dead/observer/Hear(): CHAT_GHOSTRADIO is disabled, blocking. ([client.prefs.toggles] & [CHAT_GHOSTRADIO]) = [client.prefs.toggles & CHAT_GHOSTRADIO]") - return - + return + + if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT)) + return + + . = src.say_dead(message) + +/mob/dead/observer/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "[pick("moans", "gripes", "grumps", "murmurs", "mumbles", "bleats")], [text]"; + else if (ending == "!") + return "[pick("screams", "screeches", "howls")], [text]"; + + return "[pick("whines", "cries", "spooks", "complains", "drones", "mutters")], [text]"; + +/mob/dead/observer/Hear(var/datum/speech/speech, var/rendered_speech="") + if (isnull(client) || !speech.speaker) + return + + var/source = speech.speaker.GetSource() + var/source_turf = get_turf(source) + + say_testing(src, "/mob/dead/observer/Hear(): source=[source], frequency=[speech.frequency], source_turf=[formatJumpTo(source_turf)]") + + if (get_dist(source_turf, src) <= world.view) // If this isn't true, we can't be in view, so no need for costlier proc. + if (source_turf in view(src)) + rendered_speech = "[rendered_speech]" + else + if(client && client.prefs) + if (!speech.frequency) + if ((client.prefs.toggles & CHAT_GHOSTEARS) != CHAT_GHOSTEARS) + say_testing(src, "/mob/dead/observer/Hear(): CHAT_GHOSTEARS is disabled, blocking. ([client.prefs.toggles] & [CHAT_GHOSTEARS]) = [client.prefs.toggles & CHAT_GHOSTEARS]") + return + else + if ((client.prefs.toggles & CHAT_GHOSTRADIO) != CHAT_GHOSTRADIO) + say_testing(src, "/mob/dead/observer/Hear(): CHAT_GHOSTRADIO is disabled, blocking. ([client.prefs.toggles] & [CHAT_GHOSTRADIO]) = [client.prefs.toggles & CHAT_GHOSTRADIO]") + return + to_chat(src, "(Follow) [rendered_speech]") diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 109c0246839..70c37228377 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -1,82 +1,82 @@ -// All mobs should have custom emote, really.. -/mob/proc/custom_emote(var/m_type=1,var/message = null) - - - if(stat || !use_me && usr == src) +// All mobs should have custom emote, really.. +/mob/proc/custom_emote(var/m_type=1,var/message = null) + + + if(stat || !use_me && usr == src) to_chat(usr, "You are unable to emote.") - return - - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - if(m_type == 2 && muzzled) return - - var/input - if(!message) - input = copytext(sanitize(input(src,"Choose an emote to display.") as text|null),1,MAX_MESSAGE_LEN) - else - input = message - if(input) - message = "[src] [input]" - else - return - - - if (message) - log_emote("[name]/[key] (@[x],[y],[z]): [message]") - - //Hearing gasp and such every five seconds is not good emotes were not global for a reason. - // Maybe some people are okay with that. - - for(var/mob/M in player_list) - if (!M.client) - continue //skip monkeys and leavers - if (istype(M, /mob/new_player)) - continue - if(findtext(message," snores.")) //Because we have so many sleeping people. - break - if(M.stat == DEAD && M.client && M.client.prefs && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - - // Type 1 (Visual) emotes are sent to anyone in view of the item - if (m_type & 1) - visible_message(message) - - // 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/living/M in get_hearers_in_view(get_turf(src), null)) - M.show_message(message, m_type) - -/mob/proc/emote_dead(var/message) - - - if(client.prefs.muted & MUTE_DEADCHAT) + return + + var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) + if(m_type == 2 && muzzled) return + + var/input + if(!message) + input = copytext(sanitize(input(src,"Choose an emote to display.") as text|null),1,MAX_MESSAGE_LEN) + else + input = message + if(input) + message = "[src] [input]" + else + return + + + if (message) + log_emote("[name]/[key] (@[x],[y],[z]): [message]") + + //Hearing gasp and such every five seconds is not good emotes were not global for a reason. + // Maybe some people are okay with that. + + for(var/mob/M in player_list) + if (!M.client) + continue //skip monkeys and leavers + if (istype(M, /mob/new_player)) + continue + if(findtext(message," snores.")) //Because we have so many sleeping people. + break + if(M.stat == DEAD && M.client && M.client.prefs && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) + M.show_message(message) + + + // Type 1 (Visual) emotes are sent to anyone in view of the item + if (m_type & 1) + visible_message(message) + + // 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/living/M in get_hearers_in_view(get_turf(src), null)) + M.show_message(message, m_type) + +/mob/proc/emote_dead(var/message) + + + if(client.prefs.muted & MUTE_DEADCHAT) to_chat(src, "You cannot send deadchat emotes (muted).") - return - - if(!(client.prefs.toggles & CHAT_DEAD)) + return + + if(!(client.prefs.toggles & CHAT_DEAD)) to_chat(src, "You have deadchat muted.") - return - - var/input - if(!message) - input = copytext(sanitize(input(src, "Choose an emote to display.") as text|null), 1, MAX_MESSAGE_LEN) - else - input = message - - if(input) - message = "DEAD: [src] [message]" - else - return - - - if(message) - for(var/mob/M in player_list) - if(istype(M, /mob/new_player)) - continue - - if(M.client && M.client.holder && (M.client.holder.rights & R_ADMIN|R_MOD) && (M.client.prefs.toggles & CHAT_DEAD)) // Show the emote to admins/mods + return + + var/input + if(!message) + input = copytext(sanitize(input(src, "Choose an emote to display.") as text|null), 1, MAX_MESSAGE_LEN) + else + input = message + + if(input) + message = "DEAD: [src] [message]" + else + return + + + if(message) + for(var/mob/M in player_list) + if(istype(M, /mob/new_player)) + continue + + if(M.client && M.client.holder && (M.client.holder.rights & R_ADMIN|R_MOD) && (M.client.prefs.toggles & CHAT_DEAD)) // Show the emote to admins/mods to_chat(M, message) - - else if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // Show the emote to regular ghosts with deadchat toggled on - M.show_message(message, 2) + + else if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // Show the emote to regular ghosts with deadchat toggled on + M.show_message(message, 2) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index c66e5d334df..967e4f6d92a 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -1,336 +1,336 @@ -//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc -//as they handle all relevant stuff like adding it to the player's screen and updating their overlays. - -//Returns the thing in our active hand -/mob/proc/get_active_hand() - if(hand) return l_hand - else return r_hand - -// Get the organ of the active hand -/mob/proc/get_active_hand_organ() - if(!istype(src, /mob/living/carbon)) return - if (hasorgans(src)) - var/datum/organ/external/temp = src:organs_by_name["r_hand"] - if (hand) - temp = src:organs_by_name["l_hand"] - return temp - -//Returns the thing in our inactive hand -/mob/proc/get_inactive_hand() - if(hand) return r_hand - else return l_hand - -// Because there's several different places it's stored. -/mob/proc/get_multitool(var/if_active=0) - return null - -//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success. -/mob/proc/put_in_l_hand(var/obj/item/W) - if(!put_in_hand_check(W, hand)) - return 0 - - if(!l_hand) - W.loc = src //TODO: move to equipped? - l_hand = W - W.layer = 20 //TODO: move to equipped? - W.pixel_x = initial(W.pixel_x) - W.pixel_y = initial(W.pixel_y) -// l_hand.screen_loc = ui_lhand - W.equipped(src,slot_l_hand) - if(client) client.screen |= W - if(pulling == W) stop_pulling() - update_inv_l_hand() - W.pickup(src) - return 1 - return 0 - -//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success. -/mob/proc/put_in_r_hand(var/obj/item/W) - if(!put_in_hand_check(W, hand)) - return 0 - - if(!r_hand) - W.loc = src - r_hand = W - W.layer = 20 - W.pixel_x = initial(W.pixel_x) - W.pixel_y = initial(W.pixel_y) -// r_hand.screen_loc = ui_rhand - W.equipped(src,slot_r_hand) - if(client) client.screen |= W - if(pulling == W) stop_pulling() - update_inv_r_hand() - W.pickup(src) - return 1 - return 0 - -/mob/proc/put_in_hand_check(var/obj/item/W) - if(lying) //&& !(W.flags & ABSTRACT)) - return 0 - - if(!isitem(W)) - return 0 - - if(W.flags & MUSTTWOHAND) - if(!W.wield(src, 1)) +//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc +//as they handle all relevant stuff like adding it to the player's screen and updating their overlays. + +//Returns the thing in our active hand +/mob/proc/get_active_hand() + if(hand) return l_hand + else return r_hand + +// Get the organ of the active hand +/mob/proc/get_active_hand_organ() + if(!istype(src, /mob/living/carbon)) return + if (hasorgans(src)) + var/datum/organ/external/temp = src:organs_by_name["r_hand"] + if (hand) + temp = src:organs_by_name["l_hand"] + return temp + +//Returns the thing in our inactive hand +/mob/proc/get_inactive_hand() + if(hand) return r_hand + else return l_hand + +// Because there's several different places it's stored. +/mob/proc/get_multitool(var/if_active=0) + return null + +//Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success. +/mob/proc/put_in_l_hand(var/obj/item/W) + if(!put_in_hand_check(W, hand)) + return 0 + + if(!l_hand) + W.loc = src //TODO: move to equipped? + l_hand = W + W.layer = 20 //TODO: move to equipped? + W.pixel_x = initial(W.pixel_x) + W.pixel_y = initial(W.pixel_y) +// l_hand.screen_loc = ui_lhand + W.equipped(src,slot_l_hand) + if(client) client.screen |= W + if(pulling == W) stop_pulling() + update_inv_l_hand() + W.pickup(src) + return 1 + return 0 + +//Puts the item into your r_hand if possible and calls all necessary triggers/updates. returns 1 on success. +/mob/proc/put_in_r_hand(var/obj/item/W) + if(!put_in_hand_check(W, hand)) + return 0 + + if(!r_hand) + W.loc = src + r_hand = W + W.layer = 20 + W.pixel_x = initial(W.pixel_x) + W.pixel_y = initial(W.pixel_y) +// r_hand.screen_loc = ui_rhand + W.equipped(src,slot_r_hand) + if(client) client.screen |= W + if(pulling == W) stop_pulling() + update_inv_r_hand() + W.pickup(src) + return 1 + return 0 + +/mob/proc/put_in_hand_check(var/obj/item/W) + if(lying) //&& !(W.flags & ABSTRACT)) + return 0 + + if(!isitem(W)) + return 0 + + if(W.flags & MUSTTWOHAND) + if(!W.wield(src, 1)) to_chat(src, "You need both hands to pick up \the [W].") - return 0 - - return 1 - -//Puts the item into our active hand if possible. returns 1 on success. -/mob/proc/put_in_active_hand(var/obj/item/W) - if(hand) return put_in_l_hand(W) - else return put_in_r_hand(W) - -//Puts the item into our inactive hand if possible. returns 1 on success. -/mob/proc/put_in_inactive_hand(var/obj/item/W) - if(hand) return put_in_r_hand(W) - else return put_in_l_hand(W) - -//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success. -//If both fail it drops it on the floor and returns 0. -//This is probably the main one you need to know :) -/mob/proc/put_in_hands(var/obj/item/W) - if(!W) return 0 - if(put_in_active_hand(W)) - update_inv_l_hand() - update_inv_r_hand() - return 1 - else if(put_in_inactive_hand(W)) - update_inv_l_hand() - update_inv_r_hand() - return 1 - else - W.loc = get_turf(src) - W.layer = initial(W.layer) - W.dropped() - return 0 - - - -/mob/proc/drop_item_v() //this is dumb. - if(stat == CONSCIOUS && isturf(loc)) - return drop_item() - return 0 - - -/mob/proc/drop_from_inventory(var/obj/item/W) - if(W) - if(client) client.screen -= W - u_equip(W,1) - if(!W) return 1 // self destroying objects (tk, grabs) - W.layer = initial(W.layer) - W.forceMove(loc) - - //W.dropped(src) - //update_icons() // Redundant as u_equip will handle updating the specific overlay - return 1 - return 0 - -// Drops all and only equipped items, including items in hand -/mob/proc/drop_all() - for (var/obj/item/I in get_all_slots()) - drop_from_inventory(I) - - -//Drops the item in our hand - you can specify an item and a location to drop to - -/mob/proc/drop_item(var/obj/item/to_drop, var/atom/Target, force_drop = 0) //Set force_drop to 1 to force the item to drop (even if it can't be dropped normally) - - if(!candrop) //can't drop items while etheral - return 0 - - if(!to_drop) //if we're not told to drop something specific - to_drop = get_active_hand() //drop what we're currently holding - - if(!istype(to_drop)) //still nothing to drop? - return 0 //bail - - if((to_drop.cant_drop > 0) && !force_drop) - return 0 - - if(!Target) - Target = src.loc - - remove_from_mob(to_drop) //clean out any refs - - if(!to_drop) - return 0 - - to_drop.forceMove(Target) //calls the Entered procs - - to_drop.dropped(src) - - if(to_drop && to_drop.loc) - return 1 - return 0 - -/mob/proc/drop_hands(var/atom/Target, force_drop = 0) //drops both items - drop_item(get_active_hand(), Target, force_drop) - drop_item(get_inactive_hand(), Target, force_drop) - -//TODO: phase out this proc -/mob/proc/before_take_item(var/obj/item/W) //TODO: what is this? - W.loc = null - W.layer = initial(W.layer) - u_equip(W,0) - update_icons() - return - - -/mob/proc/u_equip(var/obj/item/W as obj, dropped = 1) - if(!W) return 0 - var/success = 0 - if (W == r_hand) - r_hand = null - success = 1 - update_inv_r_hand() - else if (W == l_hand) - l_hand = null - success = 1 - update_inv_l_hand() - else if (W == back) - back = null - success = 1 - update_inv_back() - else if (W == wear_mask) - wear_mask = null - success = 1 - update_inv_wear_mask() - else - return 0 - - if(success) - if(client) - client.screen -= W - if(dropped) - W.loc = loc - W.dropped(src) - if(W) - W.layer = initial(W.layer) - return 1 - - -//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob. -/mob/proc/remove_from_mob(var/obj/O) - src.u_equip(O,1) - if (src.client) - src.client.screen -= O - if(!O) return - O.layer = initial(O.layer) - O.screen_loc = null - return 1 - -/mob/proc/get_all_slots() - return list(wear_mask, back, l_hand, r_hand) - -//everything on the mob that it isn't holding -/mob/proc/get_equipped_items() - var/list/equipped = get_all_slots() - equipped -= list(get_active_hand(), get_inactive_hand()) - return equipped - -//everything on the mob that is not in its pockets, hands and belt. -/mob/proc/get_clothing_items() - var/list/equipped = get_all_slots() - equipped -= list(get_active_hand(), get_inactive_hand()) - return equipped - -/mob/living/carbon/human/proc/equip_if_possible(obj/item/W, slot, act_on_fail = EQUIP_FAILACTION_DELETE) // since byond doesn't seem to have pointers, this seems like the best way to do this :/ - //warning: icky code - var/equipped = 0 - switch(slot) - if(slot_back) - if(!src.back) - src.back = W - equipped = 1 - if(slot_wear_mask) - if(!src.wear_mask) - src.wear_mask = W - equipped = 1 - if(slot_handcuffed) - if(!src.handcuffed) - src.handcuffed = W - equipped = 1 - if(slot_l_hand) - if(!src.l_hand) - src.l_hand = W - equipped = 1 - if(slot_r_hand) - if(!src.r_hand) - src.r_hand = W - equipped = 1 - if(slot_belt) - if(!src.belt && src.w_uniform) - src.belt = W - equipped = 1 - if(slot_wear_id) - if(!src.wear_id && src.w_uniform) - src.wear_id = W - equipped = 1 - if(slot_ears) - if(!src.ears) - src.ears = W - equipped = 1 - if(slot_glasses) - if(!src.glasses) - src.glasses = W - equipped = 1 - if(slot_gloves) - if(!src.gloves) - src.gloves = W - equipped = 1 - if(slot_head) - if(!src.head) - src.head = W - equipped = 1 - if(slot_shoes) - if(!src.shoes) - src.shoes = W - equipped = 1 - if(slot_wear_suit) - if(!src.wear_suit) - src.wear_suit = W - equipped = 1 - if(slot_w_uniform) - if(!src.w_uniform) - src.w_uniform = W - equipped = 1 - if(slot_l_store) - if(!src.l_store && src.w_uniform) - src.l_store = W - equipped = 1 - if(slot_r_store) - if(!src.r_store && src.w_uniform) - src.r_store = W - equipped = 1 - if(slot_s_store) - if(!src.s_store && src.wear_suit) - src.s_store = W - equipped = 1 - if(slot_in_backpack) - if (src.back && istype(src.back, /obj/item/weapon/storage/backpack)) - var/obj/item/weapon/storage/backpack/B = src.back - if(B.contents.len < B.storage_slots && W.w_class <= B.max_w_class) - W.loc = B - equipped = 1 - - if(equipped) - W.layer = 20 - if(src.back && W.loc != src.back) - W.loc = src - else - switch(act_on_fail) - if(EQUIP_FAILACTION_DELETE) - qdel(W) - W = null - if(EQUIP_FAILACTION_DROP) - W.loc=get_turf(src) // I think. - return equipped - -/mob/proc/get_id_card() - for(var/obj/item/I in src.get_all_slots()) - . = I.GetID() - if(.) - break + return 0 + + return 1 + +//Puts the item into our active hand if possible. returns 1 on success. +/mob/proc/put_in_active_hand(var/obj/item/W) + if(hand) return put_in_l_hand(W) + else return put_in_r_hand(W) + +//Puts the item into our inactive hand if possible. returns 1 on success. +/mob/proc/put_in_inactive_hand(var/obj/item/W) + if(hand) return put_in_r_hand(W) + else return put_in_l_hand(W) + +//Puts the item our active hand if possible. Failing that it tries our inactive hand. Returns 1 on success. +//If both fail it drops it on the floor and returns 0. +//This is probably the main one you need to know :) +/mob/proc/put_in_hands(var/obj/item/W) + if(!W) return 0 + if(put_in_active_hand(W)) + update_inv_l_hand() + update_inv_r_hand() + return 1 + else if(put_in_inactive_hand(W)) + update_inv_l_hand() + update_inv_r_hand() + return 1 + else + W.loc = get_turf(src) + W.layer = initial(W.layer) + W.dropped() + return 0 + + + +/mob/proc/drop_item_v() //this is dumb. + if(stat == CONSCIOUS && isturf(loc)) + return drop_item() + return 0 + + +/mob/proc/drop_from_inventory(var/obj/item/W) + if(W) + if(client) client.screen -= W + u_equip(W,1) + if(!W) return 1 // self destroying objects (tk, grabs) + W.layer = initial(W.layer) + W.forceMove(loc) + + //W.dropped(src) + //update_icons() // Redundant as u_equip will handle updating the specific overlay + return 1 + return 0 + +// Drops all and only equipped items, including items in hand +/mob/proc/drop_all() + for (var/obj/item/I in get_all_slots()) + drop_from_inventory(I) + + +//Drops the item in our hand - you can specify an item and a location to drop to + +/mob/proc/drop_item(var/obj/item/to_drop, var/atom/Target, force_drop = 0) //Set force_drop to 1 to force the item to drop (even if it can't be dropped normally) + + if(!candrop) //can't drop items while etheral + return 0 + + if(!to_drop) //if we're not told to drop something specific + to_drop = get_active_hand() //drop what we're currently holding + + if(!istype(to_drop)) //still nothing to drop? + return 0 //bail + + if((to_drop.cant_drop > 0) && !force_drop) + return 0 + + if(!Target) + Target = src.loc + + remove_from_mob(to_drop) //clean out any refs + + if(!to_drop) + return 0 + + to_drop.forceMove(Target) //calls the Entered procs + + to_drop.dropped(src) + + if(to_drop && to_drop.loc) + return 1 + return 0 + +/mob/proc/drop_hands(var/atom/Target, force_drop = 0) //drops both items + drop_item(get_active_hand(), Target, force_drop) + drop_item(get_inactive_hand(), Target, force_drop) + +//TODO: phase out this proc +/mob/proc/before_take_item(var/obj/item/W) //TODO: what is this? + W.loc = null + W.layer = initial(W.layer) + u_equip(W,0) + update_icons() + return + + +/mob/proc/u_equip(var/obj/item/W as obj, dropped = 1) + if(!W) return 0 + var/success = 0 + if (W == r_hand) + r_hand = null + success = 1 + update_inv_r_hand() + else if (W == l_hand) + l_hand = null + success = 1 + update_inv_l_hand() + else if (W == back) + back = null + success = 1 + update_inv_back() + else if (W == wear_mask) + wear_mask = null + success = 1 + update_inv_wear_mask() + else + return 0 + + if(success) + if(client) + client.screen -= W + if(dropped) + W.loc = loc + W.dropped(src) + if(W) + W.layer = initial(W.layer) + return 1 + + +//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob. +/mob/proc/remove_from_mob(var/obj/O) + src.u_equip(O,1) + if (src.client) + src.client.screen -= O + if(!O) return + O.layer = initial(O.layer) + O.screen_loc = null + return 1 + +/mob/proc/get_all_slots() + return list(wear_mask, back, l_hand, r_hand) + +//everything on the mob that it isn't holding +/mob/proc/get_equipped_items() + var/list/equipped = get_all_slots() + equipped -= list(get_active_hand(), get_inactive_hand()) + return equipped + +//everything on the mob that is not in its pockets, hands and belt. +/mob/proc/get_clothing_items() + var/list/equipped = get_all_slots() + equipped -= list(get_active_hand(), get_inactive_hand()) + return equipped + +/mob/living/carbon/human/proc/equip_if_possible(obj/item/W, slot, act_on_fail = EQUIP_FAILACTION_DELETE) // since byond doesn't seem to have pointers, this seems like the best way to do this :/ + //warning: icky code + var/equipped = 0 + switch(slot) + if(slot_back) + if(!src.back) + src.back = W + equipped = 1 + if(slot_wear_mask) + if(!src.wear_mask) + src.wear_mask = W + equipped = 1 + if(slot_handcuffed) + if(!src.handcuffed) + src.handcuffed = W + equipped = 1 + if(slot_l_hand) + if(!src.l_hand) + src.l_hand = W + equipped = 1 + if(slot_r_hand) + if(!src.r_hand) + src.r_hand = W + equipped = 1 + if(slot_belt) + if(!src.belt && src.w_uniform) + src.belt = W + equipped = 1 + if(slot_wear_id) + if(!src.wear_id && src.w_uniform) + src.wear_id = W + equipped = 1 + if(slot_ears) + if(!src.ears) + src.ears = W + equipped = 1 + if(slot_glasses) + if(!src.glasses) + src.glasses = W + equipped = 1 + if(slot_gloves) + if(!src.gloves) + src.gloves = W + equipped = 1 + if(slot_head) + if(!src.head) + src.head = W + equipped = 1 + if(slot_shoes) + if(!src.shoes) + src.shoes = W + equipped = 1 + if(slot_wear_suit) + if(!src.wear_suit) + src.wear_suit = W + equipped = 1 + if(slot_w_uniform) + if(!src.w_uniform) + src.w_uniform = W + equipped = 1 + if(slot_l_store) + if(!src.l_store && src.w_uniform) + src.l_store = W + equipped = 1 + if(slot_r_store) + if(!src.r_store && src.w_uniform) + src.r_store = W + equipped = 1 + if(slot_s_store) + if(!src.s_store && src.wear_suit) + src.s_store = W + equipped = 1 + if(slot_in_backpack) + if (src.back && istype(src.back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = src.back + if(B.contents.len < B.storage_slots && W.w_class <= B.max_w_class) + W.loc = B + equipped = 1 + + if(equipped) + W.layer = 20 + if(src.back && W.loc != src.back) + W.loc = src + else + switch(act_on_fail) + if(EQUIP_FAILACTION_DELETE) + qdel(W) + W = null + if(EQUIP_FAILACTION_DROP) + W.loc=get_turf(src) // I think. + return equipped + +/mob/proc/get_id_card() + for(var/obj/item/I in src.get_all_slots()) + . = I.GetID() + if(.) + break diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 3333da49ab3..04aa2267868 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -1,289 +1,289 @@ -#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point -#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point -#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 460K point and you are on fire - -/mob/living/carbon/alien - name = "alien" //The alien, not Alien - voice_name = "alien" - //speak_emote = list("hisses") - icon = 'icons/mob/alien.dmi' - gender = NEUTER - dna = null - - mob_bump_flag = ALIEN - mob_swap_flags = ALLMOBS - mob_push_flags = ALLMOBS ^ ROBOT - - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat - - var/storedPlasma = 250 - var/max_plasma = 500 - - var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie - var/has_fine_manipulation = 0 - - var/move_delay_add = 0 // movement delay to add - - status_flags = CANPARALYSE|CANPUSH - var/heal_rate = 2.5 - var/plasma_rate = 5 - - var/oxygen_alert = 0 - var/toxins_alert = 0 - var/fire_alert = 0 - - var/heat_protection = 0.5 - -/mob/living/carbon/alien/adjustToxLoss(amount) - storedPlasma = min(max(storedPlasma + amount,0),max_plasma) //upper limit of max_plasma, lower limit of 0 - updatePlasmaHUD() - return - -/mob/living/carbon/alien/proc/updatePlasmaHUD() - if(hud_used) - if(!hud_used.vampire_blood_display) - hud_used.plasma_hud() - //hud_used.human_hud(hud_used.ui_style) - hud_used.vampire_blood_display.maptext_width = 64 - hud_used.vampire_blood_display.maptext_height = 32 - hud_used.vampire_blood_display.maptext = "
    P:[storedPlasma]
    / [max_plasma]
    " - return - -/* -/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire - if(amount > 0) - ..(amount * 2) - else - ..(amount) - return -*/ -//No longer weak to fire - -/mob/living/carbon/alien/proc/getPlasma() - return storedPlasma - -/mob/living/carbon/alien/eyecheck() - return 2 - -// MULEBOT SMASH -/mob/living/carbon/alien/Crossed(var/atom/movable/AM) - var/obj/machinery/bot/mulebot/MB = AM - if(istype(MB)) - MB.RunOverCreature(src,"#00ff00") - var/obj/effect/decal/cleanable/blood/xeno/X = getFromPool(/obj/effect/decal/cleanable/blood/xeno, src.loc) //new /obj/effect/decal/cleanable/blood/xeno(src.loc) - X.New(src.loc) - -/mob/living/carbon/alien/updatehealth() - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - else - //oxyloss is only used for suicide - //toxloss isn't used for aliens, its actually used as alien powers!! - health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - -/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(locate(/obj/effect/alien/weeds) in loc) - if(health < maxHealth - getCloneLoss()) - adjustBruteLoss(-heal_rate) - adjustFireLoss(-heal_rate) - adjustOxyLoss(-heal_rate) - adjustToxLoss(plasma_rate) - - if(!environment || (flags & INVULNERABLE)) - return - var/loc_temp = T0C - if(istype(loc, /obj/mecha)) - var/obj/mecha/M = loc - loc_temp = M.return_temperature() - else if(istype(get_turf(src), /turf/space)) - var/turf/heat_turf = get_turf(src) - loc_temp = heat_turf.temperature - else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) - loc_temp = loc:air_contents.temperature - else - loc_temp = environment.temperature - +#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point +#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point +#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 460K point and you are on fire + +/mob/living/carbon/alien + name = "alien" //The alien, not Alien + voice_name = "alien" + //speak_emote = list("hisses") + icon = 'icons/mob/alien.dmi' + gender = NEUTER + dna = null + + mob_bump_flag = ALIEN + mob_swap_flags = ALLMOBS + mob_push_flags = ALLMOBS ^ ROBOT + + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat + + var/storedPlasma = 250 + var/max_plasma = 500 + + var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie + var/has_fine_manipulation = 0 + + var/move_delay_add = 0 // movement delay to add + + status_flags = CANPARALYSE|CANPUSH + var/heal_rate = 2.5 + var/plasma_rate = 5 + + var/oxygen_alert = 0 + var/toxins_alert = 0 + var/fire_alert = 0 + + var/heat_protection = 0.5 + +/mob/living/carbon/alien/adjustToxLoss(amount) + storedPlasma = min(max(storedPlasma + amount,0),max_plasma) //upper limit of max_plasma, lower limit of 0 + updatePlasmaHUD() + return + +/mob/living/carbon/alien/proc/updatePlasmaHUD() + if(hud_used) + if(!hud_used.vampire_blood_display) + hud_used.plasma_hud() + //hud_used.human_hud(hud_used.ui_style) + hud_used.vampire_blood_display.maptext_width = 64 + hud_used.vampire_blood_display.maptext_height = 32 + hud_used.vampire_blood_display.maptext = "
    P:[storedPlasma]
    / [max_plasma]
    " + return + +/* +/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire + if(amount > 0) + ..(amount * 2) + else + ..(amount) + return +*/ +//No longer weak to fire + +/mob/living/carbon/alien/proc/getPlasma() + return storedPlasma + +/mob/living/carbon/alien/eyecheck() + return 2 + +// MULEBOT SMASH +/mob/living/carbon/alien/Crossed(var/atom/movable/AM) + var/obj/machinery/bot/mulebot/MB = AM + if(istype(MB)) + MB.RunOverCreature(src,"#00ff00") + var/obj/effect/decal/cleanable/blood/xeno/X = getFromPool(/obj/effect/decal/cleanable/blood/xeno, src.loc) //new /obj/effect/decal/cleanable/blood/xeno(src.loc) + X.New(src.loc) + +/mob/living/carbon/alien/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + stat = CONSCIOUS + else + //oxyloss is only used for suicide + //toxloss isn't used for aliens, its actually used as alien powers!! + health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() + +/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(locate(/obj/effect/alien/weeds) in loc) + if(health < maxHealth - getCloneLoss()) + adjustBruteLoss(-heal_rate) + adjustFireLoss(-heal_rate) + adjustOxyLoss(-heal_rate) + adjustToxLoss(plasma_rate) + + if(!environment || (flags & INVULNERABLE)) + return + var/loc_temp = T0C + if(istype(loc, /obj/mecha)) + var/obj/mecha/M = loc + loc_temp = M.return_temperature() + else if(istype(get_turf(src), /turf/space)) + var/turf/heat_turf = get_turf(src) + loc_temp = heat_turf.temperature + else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) + loc_temp = loc:air_contents.temperature + else + loc_temp = environment.temperature + // to_chat(world, "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Fire protection: [heat_protection] - Location: [loc] - src: [src]") - - // Aliens are now weak to fire. - - //After then, it reacts to the surrounding atmosphere based on your thermal protection - if(!on_fire) // If you're on fire, ignore local air temperature - if(loc_temp > bodytemperature) - //Place is hotter than we are - var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. - if(thermal_protection < 1) - bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) - else - bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) - // bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) - - // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. - if(bodytemperature > 360.15) - //Body temperature is too hot. - fire_alert = max(fire_alert, 1) - switch(bodytemperature) - if(360 to 400) - apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) - fire_alert = max(fire_alert, 2) - if(400 to 460) - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) - if(460 to INFINITY) - if(on_fire) - apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) - fire_alert = max(fire_alert, 2) - else - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) - return - -/mob/living/carbon/alien/proc/handle_mutations_and_radiation() - - - if(getFireLoss()) - if((M_RESIST_HEAT in mutations) || prob(5)) - adjustFireLoss(-1) - - // Aliens love radiation nom nom nom - if (radiation) - if (radiation > 100) - radiation = 100 - - if (radiation < 0) - radiation = 0 - - switch(radiation) - if(1 to 49) - radiation-- - if(prob(25)) - adjustToxLoss(1) - - if(50 to 74) - radiation -= 2 - adjustToxLoss(1) - if(prob(5)) - radiation -= 5 - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - -/mob/living/carbon/alien/handle_fire()//Aliens on fire code - if(..()) - return - bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up! - return - -/mob/living/carbon/alien/IsAdvancedToolUser() - return has_fine_manipulation - -/mob/living/carbon/alien/Process_Spaceslipping() - return 0 // Don't slip in space. - -/mob/living/carbon/alien/Stat() - - if(statpanel("Status")) - stat(null, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") - - ..() - - if(statpanel("Status")) - stat(null, "Plasma Stored: [getPlasma()]/[max_plasma]") - - if(emergency_shuttle) - if(emergency_shuttle.online && emergency_shuttle.location < 2) - var/timeleft = emergency_shuttle.timeleft() - if (timeleft) - stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") - -/mob/living/carbon/alien/Stun(amount) - if(status_flags & CANSTUN) - stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun - else - // add some movement delay - move_delay_add = min(move_delay_add + round(amount / 2), 10) // a maximum delay of 10 - return - -/mob/living/carbon/alien/getDNA() - return null - -/mob/living/carbon/alien/setDNA() - return - -//This proc is NOT useless, we make it so that aliens have an halved siemens_coeff. Which means they take half damage -//I will personally find the retard who made all these VARIABLES into FUCKING CONSTANTS. THE FUCKING SOURCE AND THE SHOCK DAMAGE, CONSTANTS ? YOU THINK ? -/mob/living/carbon/alien/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1) - - var/damage = shock_damage * siemens_coeff - - if(damage <= 0) - damage = 0 - - if(take_overall_damage(0, damage, "[source]") == 0) // godmode - return 0 - - //src.burn_skin(shock_damage) - //src.adjustFireLoss(shock_damage) //burn_skin will do this for us - //src.updatehealth() - - visible_message( \ - "[src] was shocked by the [source]!", \ - "You feel a powerful shock course through your body!", \ - "You hear a heavy electrical crack.", \ - "[src] starts raving!", \ - "You feel butterflies in your stomach!", \ - "You hear a policeman whistling!" - ) - - //if(src.stunned < shock_damage) src.stunned = shock_damage - - Stun(10) // this should work for now, more is really silly and makes you lay there forever - - //if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff - - Weaken(10) - - var/datum/effect/effect/system/spark_spread/SparkSpread = new - SparkSpread.set_up(5, 1, loc) - SparkSpread.start() - - return damage/2 //Fuck this I'm not reworking your abortion of a proc, here's a copy-paste with not fucked code - -/*---------------------------------------- -Proc: AddInfectionImages() -Des: Gives the client of the alien an image on each infected mob. -----------------------------------------*/ -/mob/living/carbon/alien/proc/AddInfectionImages() - if (client) - for (var/mob/living/C in mob_list) - if(C.status_flags & XENO_HOST) - var/obj/item/alien_embryo/A = locate() in C - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]") - client.images += I - return - - -/*---------------------------------------- -Proc: RemoveInfectionImages() -Des: Removes all infected images from the alien. -----------------------------------------*/ -/mob/living/carbon/alien/proc/RemoveInfectionImages() - if (client) - for(var/image/I in client.images) - if(dd_hasprefix_case(I.icon_state, "infected")) - //del(I) - client.images -= I - return - -/mob/living/carbon/alien/has_eyes() - return 0 - -#undef HEAT_DAMAGE_LEVEL_1 -#undef HEAT_DAMAGE_LEVEL_2 -#undef HEAT_DAMAGE_LEVEL_3 + + // Aliens are now weak to fire. + + //After then, it reacts to the surrounding atmosphere based on your thermal protection + if(!on_fire) // If you're on fire, ignore local air temperature + if(loc_temp > bodytemperature) + //Place is hotter than we are + var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. + if(thermal_protection < 1) + bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) + else + bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) + // bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) + + // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. + if(bodytemperature > 360.15) + //Body temperature is too hot. + fire_alert = max(fire_alert, 1) + switch(bodytemperature) + if(360 to 400) + apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) + fire_alert = max(fire_alert, 2) + if(400 to 460) + apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) + fire_alert = max(fire_alert, 2) + if(460 to INFINITY) + if(on_fire) + apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) + fire_alert = max(fire_alert, 2) + else + apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) + fire_alert = max(fire_alert, 2) + return + +/mob/living/carbon/alien/proc/handle_mutations_and_radiation() + + + if(getFireLoss()) + if((M_RESIST_HEAT in mutations) || prob(5)) + adjustFireLoss(-1) + + // Aliens love radiation nom nom nom + if (radiation) + if (radiation > 100) + radiation = 100 + + if (radiation < 0) + radiation = 0 + + switch(radiation) + if(1 to 49) + radiation-- + if(prob(25)) + adjustToxLoss(1) + + if(50 to 74) + radiation -= 2 + adjustToxLoss(1) + if(prob(5)) + radiation -= 5 + + if(75 to 100) + radiation -= 3 + adjustToxLoss(3) + +/mob/living/carbon/alien/handle_fire()//Aliens on fire code + if(..()) + return + bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up! + return + +/mob/living/carbon/alien/IsAdvancedToolUser() + return has_fine_manipulation + +/mob/living/carbon/alien/Process_Spaceslipping() + return 0 // Don't slip in space. + +/mob/living/carbon/alien/Stat() + + if(statpanel("Status")) + stat(null, "Intent: [a_intent]") + stat(null, "Move Mode: [m_intent]") + + ..() + + if(statpanel("Status")) + stat(null, "Plasma Stored: [getPlasma()]/[max_plasma]") + + if(emergency_shuttle) + if(emergency_shuttle.online && emergency_shuttle.location < 2) + var/timeleft = emergency_shuttle.timeleft() + if (timeleft) + stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") + +/mob/living/carbon/alien/Stun(amount) + if(status_flags & CANSTUN) + stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun + else + // add some movement delay + move_delay_add = min(move_delay_add + round(amount / 2), 10) // a maximum delay of 10 + return + +/mob/living/carbon/alien/getDNA() + return null + +/mob/living/carbon/alien/setDNA() + return + +//This proc is NOT useless, we make it so that aliens have an halved siemens_coeff. Which means they take half damage +//I will personally find the retard who made all these VARIABLES into FUCKING CONSTANTS. THE FUCKING SOURCE AND THE SHOCK DAMAGE, CONSTANTS ? YOU THINK ? +/mob/living/carbon/alien/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1) + + var/damage = shock_damage * siemens_coeff + + if(damage <= 0) + damage = 0 + + if(take_overall_damage(0, damage, "[source]") == 0) // godmode + return 0 + + //src.burn_skin(shock_damage) + //src.adjustFireLoss(shock_damage) //burn_skin will do this for us + //src.updatehealth() + + visible_message( \ + "[src] was shocked by the [source]!", \ + "You feel a powerful shock course through your body!", \ + "You hear a heavy electrical crack.", \ + "[src] starts raving!", \ + "You feel butterflies in your stomach!", \ + "You hear a policeman whistling!" + ) + + //if(src.stunned < shock_damage) src.stunned = shock_damage + + Stun(10) // this should work for now, more is really silly and makes you lay there forever + + //if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff + + Weaken(10) + + var/datum/effect/effect/system/spark_spread/SparkSpread = new + SparkSpread.set_up(5, 1, loc) + SparkSpread.start() + + return damage/2 //Fuck this I'm not reworking your abortion of a proc, here's a copy-paste with not fucked code + +/*---------------------------------------- +Proc: AddInfectionImages() +Des: Gives the client of the alien an image on each infected mob. +----------------------------------------*/ +/mob/living/carbon/alien/proc/AddInfectionImages() + if (client) + for (var/mob/living/C in mob_list) + if(C.status_flags & XENO_HOST) + var/obj/item/alien_embryo/A = locate() in C + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]") + client.images += I + return + + +/*---------------------------------------- +Proc: RemoveInfectionImages() +Des: Removes all infected images from the alien. +----------------------------------------*/ +/mob/living/carbon/alien/proc/RemoveInfectionImages() + if (client) + for(var/image/I in client.images) + if(dd_hasprefix_case(I.icon_state, "infected")) + //del(I) + client.images -= I + return + +/mob/living/carbon/alien/has_eyes() + return 0 + +#undef HEAT_DAMAGE_LEVEL_1 +#undef HEAT_DAMAGE_LEVEL_2 +#undef HEAT_DAMAGE_LEVEL_3 diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 96676e57d53..87e58e3424c 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -1,189 +1,189 @@ -/*NOTES: -These are general powers. Specific powers are stored under the appropriate alien creature type. -*/ - -/*Alien spit now works like a taser shot. It won't home in on the target but will act the same once it does hit. -Doesn't work on other aliens/AI.*/ - - -/mob/living/carbon/alien/proc/powerc(X, Y)//Y is optional, checks for weed planting. X can be null. - if(stat) - to_chat(src, "You must be conscious to do this.") - return 0 - else if(X && getPlasma() < X) - to_chat(src, "Not enough plasma stored.") - return 0 - else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space))) - to_chat(src, "Bad place for a garden!") - return 0 - else return 1 - -/mob/living/carbon/alien/humanoid/verb/plant() - set name = "Plant Weeds (50)" - set desc = "Plants some alien weeds" - set category = "Alien" - - if(powerc(50,1)) - adjustToxLoss(-50) - visible_message("[src] has planted some alien weeds!") - new /obj/effect/alien/weeds/node(loc) - return - -/* -/mob/living/carbon/alien/humanoid/verb/ActivateHuggers() - set name = "Activate facehuggers (5)" - set desc = "Makes all nearby facehuggers activate" - set category = "Alien" - - if(powerc(5)) - adjustToxLoss(-5) - for(var/obj/item/clothing/mask/facehugger/F in range(8,src)) - F.GoActive() - emote("roar") - return -*/ -/mob/living/carbon/alien/humanoid/verb/whisp(mob/M as mob in oview()) - set name = "Whisper (10)" - set desc = "Whisper to someone" - set category = "Alien" - - if(powerc(10)) - adjustToxLoss(-10) - var/msg = sanitize(input("Message:", "Alien Whisper") as text|null) - if(msg) - var/turf/T = get_turf(src) - log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Alien Whisper: [msg]") - to_chat(M, "You hear a strange, alien voice in your head... [msg]") - to_chat(src, "You said: [msg] to [M]") - return - -/mob/living/carbon/alien/humanoid/verb/transfer_plasma(mob/living/carbon/alien/M as mob in oview()) - set name = "Transfer Plasma" - set desc = "Transfer Plasma to another alien" - set category = "Alien" - - if(isalien(M)) - var/amount = input("Amount:", "Transfer Plasma to [M]") as num - if (amount) - amount = abs(round(amount)) - if(powerc(amount)) - if (get_dist(src,M) <= 1) - M.adjustToxLoss(amount) - adjustToxLoss(-amount) - to_chat(M, "\The [src] has transfered [amount] plasma to you.") - to_chat(src, "You have trasferred [amount] plasma to [M]") - else - to_chat(src, "You need to be closer.") - return - - -/mob/living/carbon/alien/humanoid/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N - set name = "Corrossive Acid (200)" - set desc = "Drench an object in acid, destroying it over time." - set category = "Alien" - - if(powerc(200)) - if(O in oview(1)) - // OBJ CHECK - if(isobj(O)) - var/obj/I = O - if(I.unacidable) //So the aliens don't destroy energy fields/singularies/other aliens/etc with their acid. - to_chat(src, "You cannot dissolve this object.") - return - // TURF CHECK - else if(istype(O, /turf/simulated)) - var/turf/T = O - // R WALL - if(istype(T, /turf/simulated/wall/r_wall)) - to_chat(src, "You cannot dissolve this object.") - return - // R FLOOR - if(istype(T, /turf/simulated/floor/engine)) - to_chat(src, "You cannot dissolve this object.") - return - else // Not a type we can acid. - return - - adjustToxLoss(-200) - new /obj/effect/alien/acid(get_turf(O), O) - visible_message("\The [src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") - else - to_chat(src, "Target is too far away.") - return - - -/mob/living/carbon/alien/humanoid/proc/neurotoxin(mob/target as mob in oview()) - set name = "Spit Neurotoxin (50)" - set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear." - set category = "Alien" - - if(powerc(50)) - if(isalien(target)) - to_chat(src, "Your allies are not valid targets.") - return - adjustToxLoss(-50) - playsound(get_turf(src), 'sound/weapons/pierce.ogg', 30, 1) - visible_message("\The [src] spits neurotoxin at [target] !", "You spit neurotoxin at [target] !") - //I'm not motivated enough to revise this. Prjectile code in general needs update. - var/turf/T = get_turf(src) - var/turf/U = get_turf(target) - - if(!U || !T) - return - while(U && !istype(U,/turf)) - U = U.loc - if(!istype(T, /turf)) - return - if (U == T) - usr.bullet_act(new /obj/item/projectile/energy/neurotoxin(usr.loc), get_organ_target()) - return - if(!istype(U, /turf)) - return - - var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) - A.original = target - A.target = U - A.current = T - A.starting = T - A.yo = U.y - T.y - A.xo = U.x - T.x - spawn() - A.OnFired() - A.process() - return - -/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE - set name = "Secrete Resin (75)" - set desc = "Secrete tough malleable resin." - set category = "Alien" - - if(powerc(75)) - var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist - if(!choice || !powerc(75)) return - adjustToxLoss(-75) - visible_message("\The [src] vomits up a thick purple substance and shapes it into some form of resin structure!", "You shape a [choice]") - switch(choice) - if("resin door") - new /obj/machinery/door/mineral/resin(loc) - if("resin wall") - new /obj/effect/alien/resin/wall(loc) - if("resin membrane") - new /obj/effect/alien/resin/membrane(loc) - if("resin nest") - new /obj/structure/bed/nest(loc) - return - -/mob/living/carbon/alien/humanoid/verb/regurgitate() - set name = "Regurgitate" - set desc = "Empties the contents of your stomach" - set category = "Alien" - - if(powerc()) - if(stomach_contents.len) - for(var/mob/M in src) - if(M in stomach_contents) - stomach_contents.Remove(M) - M.loc = loc - //Paralyse(10) - src.visible_message("\The [src] hurls out the contents of their stomach!") - return +/*NOTES: +These are general powers. Specific powers are stored under the appropriate alien creature type. +*/ + +/*Alien spit now works like a taser shot. It won't home in on the target but will act the same once it does hit. +Doesn't work on other aliens/AI.*/ + + +/mob/living/carbon/alien/proc/powerc(X, Y)//Y is optional, checks for weed planting. X can be null. + if(stat) + to_chat(src, "You must be conscious to do this.") + return 0 + else if(X && getPlasma() < X) + to_chat(src, "Not enough plasma stored.") + return 0 + else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space))) + to_chat(src, "Bad place for a garden!") + return 0 + else return 1 + +/mob/living/carbon/alien/humanoid/verb/plant() + set name = "Plant Weeds (50)" + set desc = "Plants some alien weeds" + set category = "Alien" + + if(powerc(50,1)) + adjustToxLoss(-50) + visible_message("[src] has planted some alien weeds!") + new /obj/effect/alien/weeds/node(loc) + return + +/* +/mob/living/carbon/alien/humanoid/verb/ActivateHuggers() + set name = "Activate facehuggers (5)" + set desc = "Makes all nearby facehuggers activate" + set category = "Alien" + + if(powerc(5)) + adjustToxLoss(-5) + for(var/obj/item/clothing/mask/facehugger/F in range(8,src)) + F.GoActive() + emote("roar") + return +*/ +/mob/living/carbon/alien/humanoid/verb/whisp(mob/M as mob in oview()) + set name = "Whisper (10)" + set desc = "Whisper to someone" + set category = "Alien" + + if(powerc(10)) + adjustToxLoss(-10) + var/msg = sanitize(input("Message:", "Alien Whisper") as text|null) + if(msg) + var/turf/T = get_turf(src) + log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Alien Whisper: [msg]") + to_chat(M, "You hear a strange, alien voice in your head... [msg]") + to_chat(src, "You said: [msg] to [M]") + return + +/mob/living/carbon/alien/humanoid/verb/transfer_plasma(mob/living/carbon/alien/M as mob in oview()) + set name = "Transfer Plasma" + set desc = "Transfer Plasma to another alien" + set category = "Alien" + + if(isalien(M)) + var/amount = input("Amount:", "Transfer Plasma to [M]") as num + if (amount) + amount = abs(round(amount)) + if(powerc(amount)) + if (get_dist(src,M) <= 1) + M.adjustToxLoss(amount) + adjustToxLoss(-amount) + to_chat(M, "\The [src] has transfered [amount] plasma to you.") + to_chat(src, "You have trasferred [amount] plasma to [M]") + else + to_chat(src, "You need to be closer.") + return + + +/mob/living/carbon/alien/humanoid/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N + set name = "Corrossive Acid (200)" + set desc = "Drench an object in acid, destroying it over time." + set category = "Alien" + + if(powerc(200)) + if(O in oview(1)) + // OBJ CHECK + if(isobj(O)) + var/obj/I = O + if(I.unacidable) //So the aliens don't destroy energy fields/singularies/other aliens/etc with their acid. + to_chat(src, "You cannot dissolve this object.") + return + // TURF CHECK + else if(istype(O, /turf/simulated)) + var/turf/T = O + // R WALL + if(istype(T, /turf/simulated/wall/r_wall)) + to_chat(src, "You cannot dissolve this object.") + return + // R FLOOR + if(istype(T, /turf/simulated/floor/engine)) + to_chat(src, "You cannot dissolve this object.") + return + else // Not a type we can acid. + return + + adjustToxLoss(-200) + new /obj/effect/alien/acid(get_turf(O), O) + visible_message("\The [src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") + else + to_chat(src, "Target is too far away.") + return + + +/mob/living/carbon/alien/humanoid/proc/neurotoxin(mob/target as mob in oview()) + set name = "Spit Neurotoxin (50)" + set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear." + set category = "Alien" + + if(powerc(50)) + if(isalien(target)) + to_chat(src, "Your allies are not valid targets.") + return + adjustToxLoss(-50) + playsound(get_turf(src), 'sound/weapons/pierce.ogg', 30, 1) + visible_message("\The [src] spits neurotoxin at [target] !", "You spit neurotoxin at [target] !") + //I'm not motivated enough to revise this. Prjectile code in general needs update. + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + + if(!U || !T) + return + while(U && !istype(U,/turf)) + U = U.loc + if(!istype(T, /turf)) + return + if (U == T) + usr.bullet_act(new /obj/item/projectile/energy/neurotoxin(usr.loc), get_organ_target()) + return + if(!istype(U, /turf)) + return + + var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) + A.original = target + A.target = U + A.current = T + A.starting = T + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn() + A.OnFired() + A.process() + return + +/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE + set name = "Secrete Resin (75)" + set desc = "Secrete tough malleable resin." + set category = "Alien" + + if(powerc(75)) + var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist + if(!choice || !powerc(75)) return + adjustToxLoss(-75) + visible_message("\The [src] vomits up a thick purple substance and shapes it into some form of resin structure!", "You shape a [choice]") + switch(choice) + if("resin door") + new /obj/machinery/door/mineral/resin(loc) + if("resin wall") + new /obj/effect/alien/resin/wall(loc) + if("resin membrane") + new /obj/effect/alien/resin/membrane(loc) + if("resin nest") + new /obj/structure/bed/nest(loc) + return + +/mob/living/carbon/alien/humanoid/verb/regurgitate() + set name = "Regurgitate" + set desc = "Empties the contents of your stomach" + set category = "Alien" + + if(powerc()) + if(stomach_contents.len) + for(var/mob/M in src) + if(M in stomach_contents) + stomach_contents.Remove(M) + M.loc = loc + //Paralyse(10) + src.visible_message("\The [src] hurls out the contents of their stomach!") + return diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm index af47c382f01..ad0d0dbd530 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -1,51 +1,51 @@ -/mob/living/carbon/alien/humanoid/drone - name = "alien drone" //The alien drone, not Alien Drone - caste = "d" - maxHealth = 100 - health = 100 - icon_state = "aliend_s" - plasma_rate = 15 - -/mob/living/carbon/alien/humanoid/drone/movement_delay() - return (2 + move_delay_add + config.alien_delay) //Drones are slow - -/mob/living/carbon/alien/humanoid/drone/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(src.name == "alien drone") - src.name = text("alien drone ([rand(1, 1000)])") - src.real_name = src.name - verbs.Add(/mob/living/carbon/alien/humanoid/proc/resin,/mob/living/carbon/alien/humanoid/proc/corrosive_acid) - ..() - add_language(LANGUAGE_XENO) - default_language = all_languages[LANGUAGE_XENO] - -//Drones use the same base as generic humanoids. -//Drone verbs - -/mob/living/carbon/alien/humanoid/drone/verb/evolve() // -- TLE - set name = "Evolve (500)" - set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time." - set category = "Alien" - - if(powerc(500)) - // Queen check - var/no_queen = 1 - for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) - if(!Q.key && Q.has_brain()) - continue - no_queen = 0 - - if(no_queen) - adjustToxLoss(-500) - visible_message("[src] begins to violently twist and contort!", "You begin to evolve, stand still for a few moments") - if(do_after(src, src, 50)) - var/mob/living/carbon/alien/humanoid/queen/new_xeno = new(loc) - mind.transfer_to(new_xeno) - transferImplantsTo(new_xeno) - transferBorers(new_xeno) - qdel(src) - else - to_chat(src, "We already have an alive queen.") - return +/mob/living/carbon/alien/humanoid/drone + name = "alien drone" //The alien drone, not Alien Drone + caste = "d" + maxHealth = 100 + health = 100 + icon_state = "aliend_s" + plasma_rate = 15 + +/mob/living/carbon/alien/humanoid/drone/movement_delay() + return (2 + move_delay_add + config.alien_delay) //Drones are slow + +/mob/living/carbon/alien/humanoid/drone/New() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + if(src.name == "alien drone") + src.name = text("alien drone ([rand(1, 1000)])") + src.real_name = src.name + verbs.Add(/mob/living/carbon/alien/humanoid/proc/resin,/mob/living/carbon/alien/humanoid/proc/corrosive_acid) + ..() + add_language(LANGUAGE_XENO) + default_language = all_languages[LANGUAGE_XENO] + +//Drones use the same base as generic humanoids. +//Drone verbs + +/mob/living/carbon/alien/humanoid/drone/verb/evolve() // -- TLE + set name = "Evolve (500)" + set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time." + set category = "Alien" + + if(powerc(500)) + // Queen check + var/no_queen = 1 + for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) + if(!Q.key && Q.has_brain()) + continue + no_queen = 0 + + if(no_queen) + adjustToxLoss(-500) + visible_message("[src] begins to violently twist and contort!", "You begin to evolve, stand still for a few moments") + if(do_after(src, src, 50)) + var/mob/living/carbon/alien/humanoid/queen/new_xeno = new(loc) + mind.transfer_to(new_xeno) + transferImplantsTo(new_xeno) + transferBorers(new_xeno) + qdel(src) + else + to_chat(src, "We already have an alive queen.") + return diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 60256f2f1ce..02cf2d030b9 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -1,79 +1,79 @@ -/mob/living/carbon/alien/humanoid/hunter - name = "alien hunter" //The alien hunter, not Alien Hunter - caste = "h" - maxHealth = 250 - health = 250 - storedPlasma = 100 - max_plasma = 150 - icon_state = "alienh_s" - plasma_rate = 5 - -/mob/living/carbon/alien/humanoid/hunter/movement_delay() - return (-2 + move_delay_add + config.alien_delay) //Hunters are fast - -/mob/living/carbon/alien/humanoid/hunter/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien hunter") - name = text("alien hunter ([rand(1, 1000)])") - real_name = name - ..() - add_language(LANGUAGE_XENO) - default_language = all_languages[LANGUAGE_XENO] - -/mob/living/carbon/alien/humanoid/hunter - handle_regular_hud_updates() - - ..() //-Yvarov - - if(healths) - if(stat != 2) - switch(health) - if(250 to INFINITY) - healths.icon_state = "health0" - if(150 to 250) - healths.icon_state = "health1" - if(100 to 150) - healths.icon_state = "health2" - if(50 to 100) - healths.icon_state = "health3" - if(0 to 50) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - - handle_environment() - if(m_intent == "run" || resting) - ..() - else - adjustToxLoss(-heal_rate) - - -//Hunter verbs -//This ought to be fixed, maybe not now though -/* -/mob/living/carbon/alien/humanoid/hunter/verb/invis() - set name = "Invisibility (50)" - set desc = "Makes you invisible for 15 seconds" - set category = "Alien" - - if(alien_invis) - update_icons() - else - if(powerc(50)) - adjustToxLoss(-50) - alien_invis = 1.0 - update_icons() +/mob/living/carbon/alien/humanoid/hunter + name = "alien hunter" //The alien hunter, not Alien Hunter + caste = "h" + maxHealth = 250 + health = 250 + storedPlasma = 100 + max_plasma = 150 + icon_state = "alienh_s" + plasma_rate = 5 + +/mob/living/carbon/alien/humanoid/hunter/movement_delay() + return (-2 + move_delay_add + config.alien_delay) //Hunters are fast + +/mob/living/carbon/alien/humanoid/hunter/New() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + if(name == "alien hunter") + name = text("alien hunter ([rand(1, 1000)])") + real_name = name + ..() + add_language(LANGUAGE_XENO) + default_language = all_languages[LANGUAGE_XENO] + +/mob/living/carbon/alien/humanoid/hunter + handle_regular_hud_updates() + + ..() //-Yvarov + + if(healths) + if(stat != 2) + switch(health) + if(250 to INFINITY) + healths.icon_state = "health0" + if(150 to 250) + healths.icon_state = "health1" + if(100 to 150) + healths.icon_state = "health2" + if(50 to 100) + healths.icon_state = "health3" + if(0 to 50) + healths.icon_state = "health4" + else + healths.icon_state = "health5" + else + healths.icon_state = "health6" + + + handle_environment() + if(m_intent == "run" || resting) + ..() + else + adjustToxLoss(-heal_rate) + + +//Hunter verbs +//This ought to be fixed, maybe not now though +/* +/mob/living/carbon/alien/humanoid/hunter/verb/invis() + set name = "Invisibility (50)" + set desc = "Makes you invisible for 15 seconds" + set category = "Alien" + + if(alien_invis) + update_icons() + else + if(powerc(50)) + adjustToxLoss(-50) + alien_invis = 1.0 + update_icons() to_chat(src, "You are now invisible.") - visible_message("\The [src] fades into the surroundings!", "You are now invisible") - spawn(250) - if(!isnull(src)) //Don't want the game to runtime error when the mob no-longer exists. - alien_invis = 0.0 - update_icons() + visible_message("\The [src] fades into the surroundings!", "You are now invisible") + spawn(250) + if(!isnull(src)) //Don't want the game to runtime error when the mob no-longer exists. + alien_invis = 0.0 + update_icons() to_chat(src, "You are no longer invisible.") - return + return */ \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm index 369986800b7..f0925658403 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -1,48 +1,48 @@ -/mob/living/carbon/alien/humanoid/sentinel - name = "alien sentinel" //The alien sentinel, not Alien Sentinel - caste = "s" - maxHealth = 175 - health = 125 - storedPlasma = 100 - max_plasma = 250 - icon_state = "aliens_s" - plasma_rate = 10 - -//As far as movement goes, Sentinels are average - -/mob/living/carbon/alien/humanoid/sentinel/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien sentinel") - name = text("alien sentinel ([rand(1, 1000)])") - real_name = name - verbs.Add(/mob/living/carbon/alien/humanoid/proc/corrosive_acid,/mob/living/carbon/alien/humanoid/proc/neurotoxin) - ..() - add_language(LANGUAGE_XENO) - default_language = all_languages[LANGUAGE_XENO] - -/mob/living/carbon/alien/humanoid/sentinel - - - handle_regular_hud_updates() - - ..() //-Yvarov - - if(healths) - if(stat != 2) - switch(health) - if(175 to INFINITY) - healths.icon_state = "health0" - if(125 to 175) - healths.icon_state = "health1" - if(75 to 125) - healths.icon_state = "health2" - if(25 to 75) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" +/mob/living/carbon/alien/humanoid/sentinel + name = "alien sentinel" //The alien sentinel, not Alien Sentinel + caste = "s" + maxHealth = 175 + health = 125 + storedPlasma = 100 + max_plasma = 250 + icon_state = "aliens_s" + plasma_rate = 10 + +//As far as movement goes, Sentinels are average + +/mob/living/carbon/alien/humanoid/sentinel/New() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + if(name == "alien sentinel") + name = text("alien sentinel ([rand(1, 1000)])") + real_name = name + verbs.Add(/mob/living/carbon/alien/humanoid/proc/corrosive_acid,/mob/living/carbon/alien/humanoid/proc/neurotoxin) + ..() + add_language(LANGUAGE_XENO) + default_language = all_languages[LANGUAGE_XENO] + +/mob/living/carbon/alien/humanoid/sentinel + + + handle_regular_hud_updates() + + ..() //-Yvarov + + if(healths) + if(stat != 2) + switch(health) + if(175 to INFINITY) + healths.icon_state = "health0" + if(125 to 175) + healths.icon_state = "health1" + if(75 to 125) + healths.icon_state = "health2" + if(25 to 75) + healths.icon_state = "health3" + if(0 to 25) + healths.icon_state = "health4" + else + healths.icon_state = "health5" + else + healths.icon_state = "health6" diff --git a/code/modules/mob/living/carbon/alien/humanoid/death.dm b/code/modules/mob/living/carbon/alien/humanoid/death.dm index 91138a43090..c31612a00df 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/death.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/death.dm @@ -1,17 +1,17 @@ -/mob/living/carbon/alien/humanoid/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health6" - stat = DEAD - - if(!gibbed) - playsound(loc, 'sound/voice/hiss6.ogg', 80, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...", 1) - update_canmove() - if(client) blind.layer = 0 - update_icons() - - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) - - return ..(gibbed) +/mob/living/carbon/alien/humanoid/death(gibbed) + if(stat == DEAD) return + if(healths) healths.icon_state = "health6" + stat = DEAD + + if(!gibbed) + playsound(loc, 'sound/voice/hiss6.ogg', 80, 1, 1) + for(var/mob/O in viewers(src, null)) + O.show_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...", 1) + update_canmove() + if(client) blind.layer = 0 + update_icons() + + tod = worldtime2text() //weasellos time of death patch + if(mind) mind.store_memory("Time of death: [tod]", 0) + + return ..(gibbed) diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm index eda2cc587c7..ae30b3daa43 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm @@ -1,133 +1,133 @@ -/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null) - if(timestopped) return //under effects of time magick - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - - switch(act) - if("me") - if(silent) - return - if(src.client) - if(client.prefs.muted & MUTE_IC) +/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null) + if(timestopped) return //under effects of time magick + var/param = null + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) + + switch(act) + if("me") + if(silent) + return + if(src.client) + if(client.prefs.muted & MUTE_IC) to_chat(src, "The blob attacks you!") - - adjustFireLoss(damage) - - return - -/mob/living/carbon/alien/humanoid/attack_paw(mob/living/carbon/monkey/M as mob) - if(!ismonkey(M)) - return//Fix for aliens receiving double messages when attacking other aliens. - - if(!ticker) + + adjustFireLoss(damage) + + return + +/mob/living/carbon/alien/humanoid/attack_paw(mob/living/carbon/monkey/M as mob) + if(!ismonkey(M)) + return//Fix for aliens receiving double messages when attacking other aliens. + + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - /* - if (istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + /* + if (istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - */ - ..() - - switch(M.a_intent) - - if(I_HELP) - help_shake_act(M) - else - if(istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - if(health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - visible_message("\The [M] has bit \the [src]!") - adjustBruteLoss(rand(1, 3)) - updatehealth() - return - - -/mob/living/carbon/alien/humanoid/attack_slime(mob/living/carbon/slime/M as mob) - if(!ticker) + return + */ + ..() + + switch(M.a_intent) + + if(I_HELP) + help_shake_act(M) + else + if(istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + if(health > 0) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + visible_message("\The [M] has bit \the [src]!") + adjustBruteLoss(rand(1, 3)) + updatehealth() + return + + +/mob/living/carbon/alien/humanoid/attack_slime(mob/living/carbon/slime/M as mob) + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - if(M.Victim) return // can't attack while eating! - - if(health > -100) - visible_message("\The [M] glomps [src]!") - - var/damage = rand(1, 3) - - if(istype(M, /mob/living/carbon/slime/adult)) - damage = rand(10, 40) - else - damage = rand(5, 35) - - adjustBruteLoss(damage) - - if(M.powerlevel > 0) - var/stunprob = 10 - var/power = M.powerlevel + rand(0,3) - - switch(M.powerlevel) - if(1 to 2) stunprob = 20 - if(3 to 4) stunprob = 30 - if(5 to 6) stunprob = 40 - if(7 to 8) stunprob = 60 - if(9) stunprob = 70 - if(10) stunprob = 95 - - if(prob(stunprob)) - M.powerlevel -= 3 - if(M.powerlevel < 0) - M.powerlevel = 0 - visible_message("\The [M] has shocked [src]!") - - Weaken(power) - if(stuttering < power) - stuttering = power - Stun(power) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - - if(prob(stunprob) && M.powerlevel >= 8) - adjustFireLoss(M.powerlevel * rand(6,10)) - - updatehealth() - return - -//using the default attack_animal() in carbon.dm - -/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M as mob) - if(!ticker) + return + + if(M.Victim) return // can't attack while eating! + + if(health > -100) + visible_message("\The [M] glomps [src]!") + + var/damage = rand(1, 3) + + if(istype(M, /mob/living/carbon/slime/adult)) + damage = rand(10, 40) + else + damage = rand(5, 35) + + adjustBruteLoss(damage) + + if(M.powerlevel > 0) + var/stunprob = 10 + var/power = M.powerlevel + rand(0,3) + + switch(M.powerlevel) + if(1 to 2) stunprob = 20 + if(3 to 4) stunprob = 30 + if(5 to 6) stunprob = 40 + if(7 to 8) stunprob = 60 + if(9) stunprob = 70 + if(10) stunprob = 95 + + if(prob(stunprob)) + M.powerlevel -= 3 + if(M.powerlevel < 0) + M.powerlevel = 0 + visible_message("\The [M] has shocked [src]!") + + Weaken(power) + if(stuttering < power) + stuttering = power + Stun(power) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + + if(prob(stunprob) && M.powerlevel >= 8) + adjustFireLoss(M.powerlevel * rand(6,10)) + + updatehealth() + return + +//using the default attack_animal() in carbon.dm + +/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M as mob) + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - /* - if(istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + /* + if(istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - */ - - ..() - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.charge -= 2500 - - Weaken(5) - if(stuttering < 5) - stuttering = 5 - Stun(5) - visible_message("\The [src] has been touched with the stun gloves by [M] !") - return - else + return + */ + + ..() + + if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = M.gloves + if(G.cell) + if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.charge -= 2500 + + Weaken(5) + if(stuttering < 5) + stuttering = 5 + Stun(5) + visible_message("\The [src] has been touched with the stun gloves by [M] !") + return + else to_chat(M, "Not enough charge !") - return - - switch(M.a_intent) - - if(I_HELP) - if(health > 0) - help_shake_act(M) - else - if(M.health >= -75.0) - if(((M.head && M.head.flags & 4) || ((M.wear_mask && !( M.wear_mask.flags & 32 )) || ((head && head.flags & 4) || (wear_mask && !( wear_mask.flags & 32)))))) + return + + switch(M.a_intent) + + if(I_HELP) + if(health > 0) + help_shake_act(M) + else + if(M.health >= -75.0) + if(((M.head && M.head.flags & 4) || ((M.wear_mask && !( M.wear_mask.flags & 32 )) || ((head && head.flags & 4) || (wear_mask && !( wear_mask.flags & 32)))))) to_chat(M, "Remove that mask!") - return - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human() - O.source = M - O.target = src - O.s_loc = M.loc - O.t_loc = loc - O.place = "CPR" - requests += O - spawn(0) - O.process() - return - - if(I_GRAB) - if(M == src) - return - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M, src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has grabbed \the [src] passively!") - - if(I_HURT) - var/damage = rand(1, 9) - if(prob(90)) - if(M_HULK in M.mutations) //M_HULK SMASH - damage += 14 - spawn(0) - Weaken(damage) //Why can a hulk knock an alien out but not knock out a human? Damage is robust enough. - step_away(src, M, 15) - sleep(3) - step_away(src, M, 15) - playsound(loc, "punch", 25, 1, -1) - visible_message("[M] has punched \the [src] !") - if(damage > 9 ||prob(5))//Regular humans have a very small chance of weakening an alien. - Weaken(1, 5) - visible_message("[M] has weakened \the [src] !") - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch \the [src] !") - - if(I_DISARM) - if(!lying) - if(prob(5)) //Very small chance to push an alien down. - Weaken(2) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has pushed down \the [src] !") - else - if(prob(50)) - drop_item() - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has disarmed \the [src] !") - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to disarm \the [src] !") - return - -/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. -As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble. -In all, this is a lot like the monkey code. /N -*/ - -/mob/living/carbon/alien/humanoid/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if(!ticker) + return + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human() + O.source = M + O.target = src + O.s_loc = M.loc + O.t_loc = loc + O.place = "CPR" + requests += O + spawn(0) + O.process() + return + + if(I_GRAB) + if(M == src) + return + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M, src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has grabbed \the [src] passively!") + + if(I_HURT) + var/damage = rand(1, 9) + if(prob(90)) + if(M_HULK in M.mutations) //M_HULK SMASH + damage += 14 + spawn(0) + Weaken(damage) //Why can a hulk knock an alien out but not knock out a human? Damage is robust enough. + step_away(src, M, 15) + sleep(3) + step_away(src, M, 15) + playsound(loc, "punch", 25, 1, -1) + visible_message("[M] has punched \the [src] !") + if(damage > 9 ||prob(5))//Regular humans have a very small chance of weakening an alien. + Weaken(1, 5) + visible_message("[M] has weakened \the [src] !") + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to punch \the [src] !") + + if(I_DISARM) + if(!lying) + if(prob(5)) //Very small chance to push an alien down. + Weaken(2) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has pushed down \the [src] !") + else + if(prob(50)) + drop_item() + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has disarmed \the [src] !") + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to disarm \the [src] !") + return + +/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. +As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble. +In all, this is a lot like the monkey code. /N +*/ + +/mob/living/carbon/alien/humanoid/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - /* - if(istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + /* + if(istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - */ - ..() - - switch(M.a_intent) - - if(I_HELP) - sleeping = max(0,sleeping-5) - resting = 0 - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - visible_message("[M] nuzzles [src] trying to wake it up !") - else - if(health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - var/damage = rand(1, 3) - visible_message("\The [M] has bit [src]!") - adjustBruteLoss(damage) - updatehealth() - else + return + */ + ..() + + switch(M.a_intent) + + if(I_HELP) + sleeping = max(0,sleeping-5) + resting = 0 + AdjustParalysis(-3) + AdjustStunned(-3) + AdjustWeakened(-3) + visible_message("[M] nuzzles [src] trying to wake it up !") + else + if(health > 0) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + var/damage = rand(1, 3) + visible_message("\The [M] has bit [src]!") + adjustBruteLoss(damage) + updatehealth() + else to_chat(M, "[name] is too injured for that.") - return - - -/mob/living/carbon/alien/humanoid/restrained() - if(timestopped) return 1 //under effects of time magick - if (handcuffed) - return 1 - return 0 - - -/mob/living/carbon/alien/humanoid/var/co2overloadtime = null -/mob/living/carbon/alien/humanoid/var/temperature_resistance = T0C+75 - -/mob/living/carbon/alien/humanoid/show_inv(mob/user as mob) - - user.set_machine(src) - var/dat = {" -
    [name]
    -

    -
    Left Hand: [(l_hand ? text("[]", l_hand) : "Nothing")] -
    Right Hand: [(r_hand ? text("[]", r_hand) : "Nothing")] -
    Head: [(head ? text("[]", head) : "Nothing")] -
    (Exo)Suit: [(wear_suit ? text("[]", wear_suit) : "Nothing")] -
    Empty Pouches -
    Close -
    "} - user << browse(dat, text("window=mob\ref[src];size=340x480")) - onclose(user, "mob\ref[src]") - return - - + return + + +/mob/living/carbon/alien/humanoid/restrained() + if(timestopped) return 1 //under effects of time magick + if (handcuffed) + return 1 + return 0 + + +/mob/living/carbon/alien/humanoid/var/co2overloadtime = null +/mob/living/carbon/alien/humanoid/var/temperature_resistance = T0C+75 + +/mob/living/carbon/alien/humanoid/show_inv(mob/user as mob) + + user.set_machine(src) + var/dat = {" +
    [name]
    +

    +
    Left Hand: [(l_hand ? text("[]", l_hand) : "Nothing")] +
    Right Hand: [(r_hand ? text("[]", r_hand) : "Nothing")] +
    Head: [(head ? text("[]", head) : "Nothing")] +
    (Exo)Suit: [(wear_suit ? text("[]", wear_suit) : "Nothing")] +
    Empty Pouches +
    Close +
    "} + user << browse(dat, text("window=mob\ref[src];size=340x480")) + onclose(user, "mob\ref[src]") + return + + diff --git a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm b/code/modules/mob/living/carbon/alien/humanoid/inventory.dm index 66b6bb0e5ef..e88abdb2e64 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/inventory.dm @@ -1,74 +1,74 @@ -//unequip -/mob/living/carbon/alien/humanoid/u_equip(obj/item/W as obj, dropped = 1) - if(!W) return 0 - var/success = 0 - if (W == wear_suit) - wear_suit = null - success = 1 - update_inv_wear_suit(0) - else if (W == head) - head = null - success = 1 - update_inv_head(0) - else if (W == r_store) - r_store = null - success = 1 - update_inv_pockets(0) - else if (W == l_store) - l_store = null - success = 1 - update_inv_pockets(0) - else if (W == r_hand) - r_hand = null - success = 1 - update_inv_r_hand(0) - else if (W == l_hand) - l_hand = null - success = 1 - update_inv_l_hand(0) - else - return 0 - - if(success) - if (client) - client.screen -= W - if(dropped) - W.loc = loc - W.dropped(src) - if(W) - W.layer = initial(W.layer) - return 1 - -/mob/living/carbon/alien/humanoid/attack_ui(slot_id) - var/obj/item/W = get_active_hand() - if(W) - if(!istype(W)) return - switch(slot_id) -// if("o_clothing") -// if("head") - if(slot_l_store) - if(l_store) - return - if(W.w_class > 3) - return - u_equip(W,0) - l_store = W - update_inv_pockets() - if(slot_r_store) - if(r_store) - return - if(W.w_class > 3) - return - u_equip(W,0) - r_store = W - update_inv_pockets() - else - switch(slot_id) - if(slot_wear_suit) - if(wear_suit) wear_suit.attack_alien(src) - if(slot_head) - if(head) head.attack_alien(src) - if(slot_l_store) - if(l_store) l_store.attack_alien(src) - if(slot_r_store) +//unequip +/mob/living/carbon/alien/humanoid/u_equip(obj/item/W as obj, dropped = 1) + if(!W) return 0 + var/success = 0 + if (W == wear_suit) + wear_suit = null + success = 1 + update_inv_wear_suit(0) + else if (W == head) + head = null + success = 1 + update_inv_head(0) + else if (W == r_store) + r_store = null + success = 1 + update_inv_pockets(0) + else if (W == l_store) + l_store = null + success = 1 + update_inv_pockets(0) + else if (W == r_hand) + r_hand = null + success = 1 + update_inv_r_hand(0) + else if (W == l_hand) + l_hand = null + success = 1 + update_inv_l_hand(0) + else + return 0 + + if(success) + if (client) + client.screen -= W + if(dropped) + W.loc = loc + W.dropped(src) + if(W) + W.layer = initial(W.layer) + return 1 + +/mob/living/carbon/alien/humanoid/attack_ui(slot_id) + var/obj/item/W = get_active_hand() + if(W) + if(!istype(W)) return + switch(slot_id) +// if("o_clothing") +// if("head") + if(slot_l_store) + if(l_store) + return + if(W.w_class > 3) + return + u_equip(W,0) + l_store = W + update_inv_pockets() + if(slot_r_store) + if(r_store) + return + if(W.w_class > 3) + return + u_equip(W,0) + r_store = W + update_inv_pockets() + else + switch(slot_id) + if(slot_wear_suit) + if(wear_suit) wear_suit.attack_alien(src) + if(slot_head) + if(head) head.attack_alien(src) + if(slot_l_store) + if(l_store) l_store.attack_alien(src) + if(slot_r_store) if(r_store) r_store.attack_alien(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index 01023aeba31..9a874f8b515 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -1,465 +1,465 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/mob/living/carbon/alien/humanoid - oxygen_alert = 0 - toxins_alert = 0 - fire_alert = 0 - - var/temperature_alert = 0 - -/mob/living/carbon/alien/humanoid/Life() - set invisibility = 0 - //set background = 1 - - if(timestopped) return 0 //under effects of time magick - - if (monkeyizing) - return - - ..() - - var/datum/gas_mixture/environment = loc.return_air() - - if (stat != DEAD) //still breathing - - //First, resolve location and get a breath - - if(air_master.current_cycle%4==2) - //Only try to take a breath every 4 seconds, unless suffocating - spawn(0) breathe() - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - //Mutations and radiation - handle_mutations_and_radiation() - - //Chemicals in the body - handle_chemicals_in_body() - - //Disabilities - handle_disabilities() - - //Apparently, the person who wrote this code designed it so that - //blinded get reset each cycle and then get activated later in the - //code. Very ugly. I dont care. Moving this stuff here so its easy - //to find it. - blinded = null - - //Handle temperature/pressure differences between body and environment - handle_environment(environment) - - //stuff in the stomach - handle_stomach() - - - //Status updates, death etc. - handle_regular_status_updates() - update_canmove() - - // Grabbing - for(var/obj/item/weapon/grab/G in src) - G.process() - - if(client) - handle_regular_hud_updates() - - -/mob/living/carbon/alien/humanoid - proc/handle_disabilities() - if(disabilities & EPILEPSY) - if((prob(1) && paralysis < 10)) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/mob/living/carbon/alien/humanoid + oxygen_alert = 0 + toxins_alert = 0 + fire_alert = 0 + + var/temperature_alert = 0 + +/mob/living/carbon/alien/humanoid/Life() + set invisibility = 0 + //set background = 1 + + if(timestopped) return 0 //under effects of time magick + + if (monkeyizing) + return + + ..() + + var/datum/gas_mixture/environment = loc.return_air() + + if (stat != DEAD) //still breathing + + //First, resolve location and get a breath + + if(air_master.current_cycle%4==2) + //Only try to take a breath every 4 seconds, unless suffocating + spawn(0) breathe() + + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + + //Mutations and radiation + handle_mutations_and_radiation() + + //Chemicals in the body + handle_chemicals_in_body() + + //Disabilities + handle_disabilities() + + //Apparently, the person who wrote this code designed it so that + //blinded get reset each cycle and then get activated later in the + //code. Very ugly. I dont care. Moving this stuff here so its easy + //to find it. + blinded = null + + //Handle temperature/pressure differences between body and environment + handle_environment(environment) + + //stuff in the stomach + handle_stomach() + + + //Status updates, death etc. + handle_regular_status_updates() + update_canmove() + + // Grabbing + for(var/obj/item/weapon/grab/G in src) + G.process() + + if(client) + handle_regular_hud_updates() + + +/mob/living/carbon/alien/humanoid + proc/handle_disabilities() + if(disabilities & EPILEPSY) + if((prob(1) && paralysis < 10)) to_chat(src, "You have a seizure !") - Paralyse(10) - if(disabilities & COUGHING) - if((prob(5) && paralysis <= 1)) - drop_item() - spawn( 0 ) - emote("cough") - return - if(disabilities & TOURETTES) - if((prob(10) && paralysis <= 1)) - Stun(10) - spawn( 0 ) - emote("twitch") - return - if(disabilities & NERVOUS) - if(prob(10)) - stuttering = max(10, stuttering) - - - proc/breathe() - if(reagents) - if(reagents.has_reagent("lexorin")) return - if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - // HACK NEED CHANGING LATER - if(health < 0) - losebreath++ - - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(75)) //High chance of gasping for air - spawn emote("gasp") - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - else - //First, check for air from internal atmosphere (using an air tank and mask generally) - breath = get_breath_from_internal(BREATH_VOLUME) - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) - else if(istype(loc, /turf/)) - var/breath_moles = 0 - /*if(environment.return_pressure() > ONE_ATMOSPHERE) - // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) - breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) - else*/ - // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) - - // Handle chem smoke effect -- Doohl - for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - handle_breath(breath) - - if(breath) - loc.assume_air(breath) - - - proc/get_breath_from_internal(volume_needed) - if(internal) - if(!contents.Find(internal)) - internal = null - if(!wear_mask || !(wear_mask.flags & MASKINTERNALS) ) - internal = null - if(internal) - if(internals) - internals.icon_state = "internal1" - return internal.remove_air_volume(volume_needed) - else - if(internals) - internals.icon_state = "internal0" - return null - - proc/handle_breath(datum/gas_mixture/breath) - if((status_flags & GODMODE) || (flags & INVULNERABLE)) - return - - if(!breath || (breath.total_moles == 0)) - //Aliens breathe in vaccuum - return 0 - - var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - - //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure - - if(Toxins_pp) // Detect toxins in air - - adjustToxLoss(breath.toxins*250) - toxins_alert = max(toxins_alert, 1) - - toxins_used = breath.toxins - - else - toxins_alert = 0 - - //Breathe in toxins and out oxygen - breath.toxins -= toxins_used - breath.oxygen += toxins_used - - if(breath.temperature > (T0C+66) && !(M_RESIST_HEAT in mutations)) // Hot air hurts :( - if(prob(20)) + Paralyse(10) + if(disabilities & COUGHING) + if((prob(5) && paralysis <= 1)) + drop_item() + spawn( 0 ) + emote("cough") + return + if(disabilities & TOURETTES) + if((prob(10) && paralysis <= 1)) + Stun(10) + spawn( 0 ) + emote("twitch") + return + if(disabilities & NERVOUS) + if(prob(10)) + stuttering = max(10, stuttering) + + + proc/breathe() + if(reagents) + if(reagents.has_reagent("lexorin")) return + if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return + + var/datum/gas_mixture/environment = loc.return_air() + var/datum/gas_mixture/breath + // HACK NEED CHANGING LATER + if(health < 0) + losebreath++ + + if(losebreath>0) //Suffocating so do not take a breath + losebreath-- + if (prob(75)) //High chance of gasping for air + spawn emote("gasp") + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + else + //First, check for air from internal atmosphere (using an air tank and mask generally) + breath = get_breath_from_internal(BREATH_VOLUME) + + //No breath from internal atmosphere so get breath from location + if(!breath) + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) + else if(istype(loc, /turf/)) + var/breath_moles = 0 + /*if(environment.return_pressure() > ONE_ATMOSPHERE) + // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) + breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) + else*/ + // Not enough air around, take a percentage of what's there to model this properly + breath_moles = environment.total_moles()*BREATH_PERCENTAGE + + breath = loc.remove_air(breath_moles) + + // Handle chem smoke effect -- Doohl + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(src, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + + + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + + handle_breath(breath) + + if(breath) + loc.assume_air(breath) + + + proc/get_breath_from_internal(volume_needed) + if(internal) + if(!contents.Find(internal)) + internal = null + if(!wear_mask || !(wear_mask.flags & MASKINTERNALS) ) + internal = null + if(internal) + if(internals) + internals.icon_state = "internal1" + return internal.remove_air_volume(volume_needed) + else + if(internals) + internals.icon_state = "internal0" + return null + + proc/handle_breath(datum/gas_mixture/breath) + if((status_flags & GODMODE) || (flags & INVULNERABLE)) + return + + if(!breath || (breath.total_moles == 0)) + //Aliens breathe in vaccuum + return 0 + + var/toxins_used = 0 + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + + //Partial pressure of the toxins in our breath + var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + + if(Toxins_pp) // Detect toxins in air + + adjustToxLoss(breath.toxins*250) + toxins_alert = max(toxins_alert, 1) + + toxins_used = breath.toxins + + else + toxins_alert = 0 + + //Breathe in toxins and out oxygen + breath.toxins -= toxins_used + breath.oxygen += toxins_used + + if(breath.temperature > (T0C+66) && !(M_RESIST_HEAT in mutations)) // Hot air hurts :( + if(prob(20)) to_chat(src, "You feel a searing heat in your lungs !") - fire_alert = max(fire_alert, 1) - else - fire_alert = 0 - - //Temporary fixes to the alerts. - - return 1 - - proc/adjust_body_temperature(current, loc_temp, boost) - var/temperature = current - var/difference = abs(current-loc_temp) //get difference - var/increments// = difference/10 //find how many increments apart they are - if(difference > 50) - increments = difference/5 - else - increments = difference/10 - var/change = increments*boost // Get the amount to change by (x per increment) - var/temp_change - if(current < loc_temp) - temperature = min(loc_temp, temperature+change) - else if(current > loc_temp) - temperature = max(loc_temp, temperature-change) - temp_change = (temperature - current) - return temp_change - - /* - proc/get_thermal_protection() - var/thermal_protection = 1.0 - //Handle normal clothing - if(head && (head.body_parts_covered & HEAD)) - thermal_protection += 0.5 - if(wear_suit && (wear_suit.body_parts_covered & UPPER_TORSO)) - thermal_protection += 0.5 - if(wear_suit && (wear_suit.body_parts_covered & LEGS)) - thermal_protection += 0.2 - if(wear_suit && (wear_suit.body_parts_covered & ARMS)) - thermal_protection += 0.2 - if(wear_suit && (wear_suit.body_parts_covered & HANDS)) - thermal_protection += 0.2 - if(wear_suit && (wear_suit.flags & SUITSPACE)) - thermal_protection += 3 - if(M_RESIST_COLD in mutations) - thermal_protection += 5 - - return thermal_protection - - proc/add_fire_protection(var/temp) - var/fire_prot = 0 - if(head) - if(head.protective_temperature > temp) - fire_prot += (head.protective_temperature/10) - if(wear_mask) - if(wear_mask.protective_temperature > temp) - fire_prot += (wear_mask.protective_temperature/10) - if(wear_suit) - if(wear_suit.protective_temperature > temp) - fire_prot += (wear_suit.protective_temperature/10) - - - return fire_prot - */ - - proc/handle_chemicals_in_body() - - - if(reagents) reagents.metabolize(src) - - if(M_FAT in mutations) - if(nutrition < 100) - if(prob(round((50 - nutrition) / 100))) + fire_alert = max(fire_alert, 1) + else + fire_alert = 0 + + //Temporary fixes to the alerts. + + return 1 + + proc/adjust_body_temperature(current, loc_temp, boost) + var/temperature = current + var/difference = abs(current-loc_temp) //get difference + var/increments// = difference/10 //find how many increments apart they are + if(difference > 50) + increments = difference/5 + else + increments = difference/10 + var/change = increments*boost // Get the amount to change by (x per increment) + var/temp_change + if(current < loc_temp) + temperature = min(loc_temp, temperature+change) + else if(current > loc_temp) + temperature = max(loc_temp, temperature-change) + temp_change = (temperature - current) + return temp_change + + /* + proc/get_thermal_protection() + var/thermal_protection = 1.0 + //Handle normal clothing + if(head && (head.body_parts_covered & HEAD)) + thermal_protection += 0.5 + if(wear_suit && (wear_suit.body_parts_covered & UPPER_TORSO)) + thermal_protection += 0.5 + if(wear_suit && (wear_suit.body_parts_covered & LEGS)) + thermal_protection += 0.2 + if(wear_suit && (wear_suit.body_parts_covered & ARMS)) + thermal_protection += 0.2 + if(wear_suit && (wear_suit.body_parts_covered & HANDS)) + thermal_protection += 0.2 + if(wear_suit && (wear_suit.flags & SUITSPACE)) + thermal_protection += 3 + if(M_RESIST_COLD in mutations) + thermal_protection += 5 + + return thermal_protection + + proc/add_fire_protection(var/temp) + var/fire_prot = 0 + if(head) + if(head.protective_temperature > temp) + fire_prot += (head.protective_temperature/10) + if(wear_mask) + if(wear_mask.protective_temperature > temp) + fire_prot += (wear_mask.protective_temperature/10) + if(wear_suit) + if(wear_suit.protective_temperature > temp) + fire_prot += (wear_suit.protective_temperature/10) + + + return fire_prot + */ + + proc/handle_chemicals_in_body() + + + if(reagents) reagents.metabolize(src) + + if(M_FAT in mutations) + if(nutrition < 100) + if(prob(round((50 - nutrition) / 100))) to_chat(src, "You feel fit again!") - mutations.Remove(M_FAT) - else - if(nutrition > 500) - if(prob(5 + round((nutrition - 200) / 2))) + mutations.Remove(M_FAT) + else + if(nutrition > 500) + if(prob(5 + round((nutrition - 200) / 2))) to_chat(src, "You suddenly feel blubbery!") - mutations.Add(M_FAT) - - if (nutrition > 0) - nutrition -= HUNGER_FACTOR - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 5) - jitteriness = max(0, jitteriness - 5) - else - dizziness = max(0, dizziness - 1) - jitteriness = max(0, jitteriness - 1) - - updatehealth() - - return //TODO: DEFERRED - - - proc/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - if(health < config.health_threshold_dead || !has_brain()) - death() - blinded = 1 - stat = DEAD - silent = 0 - return 1 - - //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 50) || (config.health_threshold_crit > health) ) - if( health <= 20 && prob(1) ) - spawn(0) - emote("gasp") - if(!reagents.has_reagent("inaprovaline")) - adjustOxyLoss(1) - Paralyse(3) - - if(paralysis) - AdjustParalysis(-1) - blinded = 1 - stat = UNCONSCIOUS - else if(sleeping) - sleeping = max(sleeping-1, 0) - blinded = 1 - stat = UNCONSCIOUS - if( prob(10) && health ) - spawn(0) - emote("hiss") - //CONSCIOUS - else - stat = CONSCIOUS - - /* What in the living hell is this?*/ - if(move_delay_add > 0) - move_delay_add = max(0, move_delay_add - rand(1, 2)) - - //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly - eye_blurry = max(eye_blurry-1, 0) - - //Ears - if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own - ear_deaf = max(ear_deaf, 1) - else if(ear_deaf) //deafness, heals slowly over time - ear_deaf = max(ear_deaf-1, 0) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs - ear_damage = max(ear_damage-0.05, 0) - - //Other - if(stunned) - AdjustStunned(-1) - if(!stunned) - update_icons() - - 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) - stuttering = max(stuttering-1, 0) - - if(silent) - silent = max(silent-1, 0) - - if(druggy) - druggy = max(druggy-1, 0) - return 1 - - - proc/handle_regular_hud_updates() - - - if (stat == 2 || (M_XRAY in mutations)) - sight |= SEE_TURFS - sight |= SEE_MOBS - sight |= SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - else if (stat != 2) - sight |= SEE_MOBS - sight &= ~SEE_TURFS - sight &= ~SEE_OBJS - see_in_dark = 4 - see_invisible = SEE_INVISIBLE_MINIMUM - - if (healths) - if (stat != 2) - switch(health) - if(100 to INFINITY) - healths.icon_state = "health0" - if(75 to 100) - healths.icon_state = "health1" - if(50 to 75) - healths.icon_state = "health2" - if(25 to 50) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" - - - if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]" - if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" - if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]" - //NOTE: the alerts dont reset when youre out of danger. dont blame me, - //blame the person who coded them. Temporary fix added. - if (client) - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if ((blind && stat != 2)) - if ((blinded)) - blind.layer = 18 - else - blind.layer = 0 - - if (disabilities & NEARSIGHTED) - client.screen += global_hud.vimpaired - - if (eye_blurry) - client.screen += global_hud.blurry - - if (druggy) - client.screen += global_hud.druggy - - if (stat != 2) - if (machine) - if (!( machine.check_eye(src) )) - reset_view(null) - else - if(client && !client.adminobs && !isTeleViewing(client.eye)) - reset_view(null) - - return 1 - - proc/handle_stomach() - spawn(0) - for(var/mob/living/M in stomach_contents) - if(M.loc != src) - stomach_contents.Remove(M) - continue - if(istype(M, /mob/living/carbon) && stat != 2) - if(M.stat == 2) - M.death(1) - stomach_contents.Remove(M) - qdel(M) - M = null - continue - if(air_master.current_cycle%3==1) - if(!(status_flags & GODMODE)) - M.adjustBruteLoss(5) - nutrition += 10 + mutations.Add(M_FAT) + + if (nutrition > 0) + nutrition -= HUNGER_FACTOR + + if (drowsyness) + drowsyness-- + eye_blurry = max(2, eye_blurry) + if (prob(5)) + sleeping += 1 + Paralyse(5) + + confused = max(0, confused - 1) + // decrement dizziness counter, clamped to 0 + if(resting) + dizziness = max(0, dizziness - 5) + jitteriness = max(0, jitteriness - 5) + else + dizziness = max(0, dizziness - 1) + jitteriness = max(0, jitteriness - 1) + + updatehealth() + + return //TODO: DEFERRED + + + proc/handle_regular_status_updates() + updatehealth() + + if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP + blinded = 1 + silent = 0 + else //ALIVE. LIGHTS ARE ON + if(health < config.health_threshold_dead || !has_brain()) + death() + blinded = 1 + stat = DEAD + silent = 0 + return 1 + + //UNCONSCIOUS. NO-ONE IS HOME + if( (getOxyLoss() > 50) || (config.health_threshold_crit > health) ) + if( health <= 20 && prob(1) ) + spawn(0) + emote("gasp") + if(!reagents.has_reagent("inaprovaline")) + adjustOxyLoss(1) + Paralyse(3) + + if(paralysis) + AdjustParalysis(-1) + blinded = 1 + stat = UNCONSCIOUS + else if(sleeping) + sleeping = max(sleeping-1, 0) + blinded = 1 + stat = UNCONSCIOUS + if( prob(10) && health ) + spawn(0) + emote("hiss") + //CONSCIOUS + else + stat = CONSCIOUS + + /* What in the living hell is this?*/ + if(move_delay_add > 0) + move_delay_add = max(0, move_delay_add - rand(1, 2)) + + //Eyes + if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own + blinded = 1 + else if(eye_blind) //blindness, heals slowly over time + eye_blind = max(eye_blind-1,0) + blinded = 1 + else if(eye_blurry) //blurry eyes heal slowly + eye_blurry = max(eye_blurry-1, 0) + + //Ears + if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own + ear_deaf = max(ear_deaf, 1) + else if(ear_deaf) //deafness, heals slowly over time + ear_deaf = max(ear_deaf-1, 0) + else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs + ear_damage = max(ear_damage-0.05, 0) + + //Other + if(stunned) + AdjustStunned(-1) + if(!stunned) + update_icons() + + 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) + stuttering = max(stuttering-1, 0) + + if(silent) + silent = max(silent-1, 0) + + if(druggy) + druggy = max(druggy-1, 0) + return 1 + + + proc/handle_regular_hud_updates() + + + if (stat == 2 || (M_XRAY in mutations)) + sight |= SEE_TURFS + sight |= SEE_MOBS + sight |= SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (stat != 2) + sight |= SEE_MOBS + sight &= ~SEE_TURFS + sight &= ~SEE_OBJS + see_in_dark = 4 + see_invisible = SEE_INVISIBLE_MINIMUM + + if (healths) + if (stat != 2) + switch(health) + if(100 to INFINITY) + healths.icon_state = "health0" + if(75 to 100) + healths.icon_state = "health1" + if(50 to 75) + healths.icon_state = "health2" + if(25 to 50) + healths.icon_state = "health3" + if(0 to 25) + healths.icon_state = "health4" + else + healths.icon_state = "health5" + else + healths.icon_state = "health6" + + if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" + + + if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]" + if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" + if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]" + //NOTE: the alerts dont reset when youre out of danger. dont blame me, + //blame the person who coded them. Temporary fix added. + if (client) + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if ((blind && stat != 2)) + if ((blinded)) + blind.layer = 18 + else + blind.layer = 0 + + if (disabilities & NEARSIGHTED) + client.screen += global_hud.vimpaired + + if (eye_blurry) + client.screen += global_hud.blurry + + if (druggy) + client.screen += global_hud.druggy + + if (stat != 2) + if (machine) + if (!( machine.check_eye(src) )) + reset_view(null) + else + if(client && !client.adminobs && !isTeleViewing(client.eye)) + reset_view(null) + + return 1 + + proc/handle_stomach() + spawn(0) + for(var/mob/living/M in stomach_contents) + if(M.loc != src) + stomach_contents.Remove(M) + continue + if(istype(M, /mob/living/carbon) && stat != 2) + if(M.stat == 2) + M.death(1) + stomach_contents.Remove(M) + qdel(M) + M = null + continue + if(air_master.current_cycle%3==1) + if(!(status_flags & GODMODE)) + M.adjustBruteLoss(5) + nutrition += 10 diff --git a/code/modules/mob/living/carbon/alien/humanoid/login.dm b/code/modules/mob/living/carbon/alien/humanoid/login.dm index 4f66c2b799a..1bd7f8aa63f 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/login.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/login.dm @@ -1,8 +1,8 @@ -/mob/living/carbon/alien/humanoid/Login() - ..() - update_hud() - updatePlasmaHUD() - if(!isturf(loc)) - client.eye = loc - client.perspective = EYE_PERSPECTIVE - return +/mob/living/carbon/alien/humanoid/Login() + ..() + update_hud() + updatePlasmaHUD() + if(!isturf(loc)) + client.eye = loc + client.perspective = EYE_PERSPECTIVE + return diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index 746eecd0096..b92735c48d7 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -1,99 +1,99 @@ -/mob/living/carbon/alien/humanoid/queen - name = "alien queen" //The alien queen, not Alien Queen. Even if there's only one at a time - caste = "q" - maxHealth = 300 - health = 300 - icon_state = "alienq_s" - status_flags = CANPARALYSE - heal_rate = 5 - plasma_rate = 20 - -/mob/living/carbon/alien/humanoid/queen/movement_delay() - return (5 + move_delay_add + config.alien_delay) //Queens are slow as fuck - -/mob/living/carbon/alien/humanoid/queen/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - - //there should only be one queen - for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) - if(Q == src) - continue - if(Q.stat == DEAD) - continue - if(Q.client) - name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it. - break - - real_name = src.name - verbs.Add(/mob/living/carbon/alien/humanoid/proc/corrosive_acid,/mob/living/carbon/alien/humanoid/proc/neurotoxin,/mob/living/carbon/alien/humanoid/proc/resin) - ..() - add_language(LANGUAGE_XENO) - default_language = all_languages[LANGUAGE_XENO] - verbs -= /mob/living/carbon/alien/verb/ventcrawl - - -/mob/living/carbon/alien/humanoid/queen - - handle_regular_hud_updates() - - ..() //-Yvarov - - if(src.healths) - if(src.stat != 2) - switch(health) - if(300 to INFINITY) - src.healths.icon_state = "health0" - if(200 to 300) - src.healths.icon_state = "health1" - if(125 to 200) - src.healths.icon_state = "health2" - if(75 to 125) - src.healths.icon_state = "health3" - if(0 to 75) - src.healths.icon_state = "health4" - else - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" - - -//Queen verbs -/mob/living/carbon/alien/humanoid/queen/verb/lay_egg() - - - set name = "Lay Egg (75)" - set desc = "Lay an egg to produce huggers to impregnate prey with." - set category = "Alien" - - if(locate(/obj/effect/alien/egg) in get_turf(src)) - to_chat(src, "There's already an egg here.") - return - - if(powerc(75, 1))//Can't plant eggs on spess tiles. That's silly. - adjustToxLoss(-75) - visible_message("[src] has laid an egg!") - stat_collection.xeno.eggs_laid++ - new /obj/effect/alien/egg(loc) - return - - -/mob/living/carbon/alien/humanoid/queen/large - icon = 'icons/mob/alienqueen.dmi' - icon_state = "queen_s" - pixel_x = -16 - -/mob/living/carbon/alien/humanoid/queen/large/update_icons() - lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again - update_hud() //TODO: remove the need for this to be here - overlays.len = 0 - if(lying) - if(resting) icon_state = "queen_sleep" - else icon_state = "queen_l" - for(var/image/I in overlays_lying) - overlays += I - else - icon_state = "queen_s" - for(var/image/I in overlays_standing) +/mob/living/carbon/alien/humanoid/queen + name = "alien queen" //The alien queen, not Alien Queen. Even if there's only one at a time + caste = "q" + maxHealth = 300 + health = 300 + icon_state = "alienq_s" + status_flags = CANPARALYSE + heal_rate = 5 + plasma_rate = 20 + +/mob/living/carbon/alien/humanoid/queen/movement_delay() + return (5 + move_delay_add + config.alien_delay) //Queens are slow as fuck + +/mob/living/carbon/alien/humanoid/queen/New() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + + //there should only be one queen + for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) + if(Q == src) + continue + if(Q.stat == DEAD) + continue + if(Q.client) + name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it. + break + + real_name = src.name + verbs.Add(/mob/living/carbon/alien/humanoid/proc/corrosive_acid,/mob/living/carbon/alien/humanoid/proc/neurotoxin,/mob/living/carbon/alien/humanoid/proc/resin) + ..() + add_language(LANGUAGE_XENO) + default_language = all_languages[LANGUAGE_XENO] + verbs -= /mob/living/carbon/alien/verb/ventcrawl + + +/mob/living/carbon/alien/humanoid/queen + + handle_regular_hud_updates() + + ..() //-Yvarov + + if(src.healths) + if(src.stat != 2) + switch(health) + if(300 to INFINITY) + src.healths.icon_state = "health0" + if(200 to 300) + src.healths.icon_state = "health1" + if(125 to 200) + src.healths.icon_state = "health2" + if(75 to 125) + src.healths.icon_state = "health3" + if(0 to 75) + src.healths.icon_state = "health4" + else + src.healths.icon_state = "health5" + else + src.healths.icon_state = "health6" + + +//Queen verbs +/mob/living/carbon/alien/humanoid/queen/verb/lay_egg() + + + set name = "Lay Egg (75)" + set desc = "Lay an egg to produce huggers to impregnate prey with." + set category = "Alien" + + if(locate(/obj/effect/alien/egg) in get_turf(src)) + to_chat(src, "There's already an egg here.") + return + + if(powerc(75, 1))//Can't plant eggs on spess tiles. That's silly. + adjustToxLoss(-75) + visible_message("[src] has laid an egg!") + stat_collection.xeno.eggs_laid++ + new /obj/effect/alien/egg(loc) + return + + +/mob/living/carbon/alien/humanoid/queen/large + icon = 'icons/mob/alienqueen.dmi' + icon_state = "queen_s" + pixel_x = -16 + +/mob/living/carbon/alien/humanoid/queen/large/update_icons() + lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again + update_hud() //TODO: remove the need for this to be here + overlays.len = 0 + if(lying) + if(resting) icon_state = "queen_sleep" + else icon_state = "queen_l" + for(var/image/I in overlays_lying) + overlays += I + else + icon_state = "queen_s" + for(var/image/I in overlays_standing) overlays += I \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index c3c60a82414..28818ccfcc2 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -1,175 +1,175 @@ -//Xeno Overlays Indexes////////// -#define X_HEAD_LAYER 1 -#define X_SUIT_LAYER 2 -#define X_L_HAND_LAYER 3 -#define X_R_HAND_LAYER 4 -#define X_FIRE_LAYER 5 -#define TARGETED_LAYER 6 -#define X_TOTAL_LAYERS 6 -///////////////////////////////// - -/mob/living/carbon/alien/humanoid - var/list/overlays_lying[X_TOTAL_LAYERS] - var/list/overlays_standing[X_TOTAL_LAYERS] - -/mob/living/carbon/alien/humanoid/update_icons() - lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again - update_hud() //TODO: remove the need for this to be here - overlays.len = 0 - if(stat == DEAD) - //If we mostly took damage from fire - if(fireloss > 125) - icon_state = "alien[caste]_husked" - else - icon_state = "alien[caste]_dead" - for(var/image/I in overlays_lying) - overlays += I - else if(lying) - if(resting) - icon_state = "alien[caste]_sleep" - else if(stat == UNCONSCIOUS) - icon_state = "alien[caste]_unconscious" - else - icon_state = "alien[caste]_l" - for(var/image/I in overlays_lying) - overlays += I - else - if(m_intent == "run") icon_state = "alien[caste]_running" - else icon_state = "alien[caste]_s" - for(var/image/I in overlays_standing) - overlays += I - -/mob/living/carbon/alien/humanoid/regenerate_icons() - ..() - if (monkeyizing) return - - update_inv_head(0) - update_inv_wear_suit(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_pockets(0) - update_hud() - update_icons() - update_fire() - -/mob/living/carbon/alien/humanoid/update_hud() - //TODO - if (client) -// if(other) client.screen |= hud_used.other //Not used -// else client.screen -= hud_used.other //Not used - client.screen |= contents - - - -/mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1) - if(wear_suit) - var/t_state = wear_suit.item_state - if(!t_state) t_state = wear_suit.icon_state - var/image/lying = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]2") - var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") - - if(wear_suit.blood_DNA && wear_suit.blood_DNA.len) - var/t_suit = "suit" - if( istype(wear_suit, /obj/item/clothing/suit/armor) ) - t_suit = "armor" - lying.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood2") - standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood") - - //TODO - wear_suit.screen_loc = ui_alien_oclothing - if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - drop_from_inventory(handcuffed) - drop_hands() - - overlays_lying[X_SUIT_LAYER] = lying - overlays_standing[X_SUIT_LAYER] = standing - else - overlays_lying[X_SUIT_LAYER] = null - overlays_standing[X_SUIT_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_inv_head(var/update_icons=1) - if (head) - var/t_state = head.item_state - if(!t_state) t_state = head.icon_state - var/image/lying = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]2") - var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") - if(head.blood_DNA && head.blood_DNA.len) - lying.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood2") - standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") - head.screen_loc = ui_alien_head - overlays_lying[X_HEAD_LAYER] = lying - overlays_standing[X_HEAD_LAYER] = standing - else - overlays_lying[X_HEAD_LAYER] = null - overlays_standing[X_HEAD_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_inv_pockets(var/update_icons=1) - if(l_store) l_store.screen_loc = ui_storage1 - if(r_store) r_store.screen_loc = ui_storage2 - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1) - overlays -= overlays_standing[X_R_HAND_LAYER] - if(r_hand) - var/t_state = r_hand.item_state - var/t_inhand_state = r_hand.inhand_states["right_hand"] - if(!t_state) t_state = r_hand.icon_state - r_hand.screen_loc = ui_rhand - overlays_standing[X_R_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = t_state) - else - overlays_standing[X_R_HAND_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1) - overlays -= overlays_standing[X_L_HAND_LAYER] - if(l_hand) - var/t_state = l_hand.item_state - var/t_inhand_state = l_hand.inhand_states["left_hand"] //this is a file - if(!t_state) t_state = l_hand.icon_state - l_hand.screen_loc = ui_lhand - overlays_standing[X_L_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = t_state) - else - overlays_standing[X_L_HAND_LAYER] = null - if(update_icons) update_icons() - -//Call when target overlay should be added/removed -/mob/living/carbon/alien/humanoid/update_targeted(var/update_icons=1) - if (targeted_by && target_locked) - overlays_lying[TARGETED_LAYER] = target_locked - overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - del(target_locked) - if (!targeted_by) - overlays_lying[TARGETED_LAYER] = null - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_fire() - overlays -= overlays_lying[X_FIRE_LAYER] - overlays -= overlays_standing[X_FIRE_LAYER] - if(on_fire) - overlays_lying[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Lying", "layer"= -X_FIRE_LAYER) - overlays_standing[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"= -X_FIRE_LAYER) - if(src.lying) - overlays += overlays_lying[X_FIRE_LAYER] - else - overlays += overlays_standing[X_FIRE_LAYER] - return - else - overlays_lying[X_FIRE_LAYER] = null - overlays_standing[X_FIRE_LAYER] = null - -//Xeno Overlays Indexes////////// -#undef X_HEAD_LAYER -#undef X_SUIT_LAYER -#undef X_L_HAND_LAYER -#undef X_R_HAND_LAYER -#undef TARGETED_LAYER -#undef X_FIRE_LAYER -#undef X_TOTAL_LAYERS +//Xeno Overlays Indexes////////// +#define X_HEAD_LAYER 1 +#define X_SUIT_LAYER 2 +#define X_L_HAND_LAYER 3 +#define X_R_HAND_LAYER 4 +#define X_FIRE_LAYER 5 +#define TARGETED_LAYER 6 +#define X_TOTAL_LAYERS 6 +///////////////////////////////// + +/mob/living/carbon/alien/humanoid + var/list/overlays_lying[X_TOTAL_LAYERS] + var/list/overlays_standing[X_TOTAL_LAYERS] + +/mob/living/carbon/alien/humanoid/update_icons() + lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again + update_hud() //TODO: remove the need for this to be here + overlays.len = 0 + if(stat == DEAD) + //If we mostly took damage from fire + if(fireloss > 125) + icon_state = "alien[caste]_husked" + else + icon_state = "alien[caste]_dead" + for(var/image/I in overlays_lying) + overlays += I + else if(lying) + if(resting) + icon_state = "alien[caste]_sleep" + else if(stat == UNCONSCIOUS) + icon_state = "alien[caste]_unconscious" + else + icon_state = "alien[caste]_l" + for(var/image/I in overlays_lying) + overlays += I + else + if(m_intent == "run") icon_state = "alien[caste]_running" + else icon_state = "alien[caste]_s" + for(var/image/I in overlays_standing) + overlays += I + +/mob/living/carbon/alien/humanoid/regenerate_icons() + ..() + if (monkeyizing) return + + update_inv_head(0) + update_inv_wear_suit(0) + update_inv_r_hand(0) + update_inv_l_hand(0) + update_inv_pockets(0) + update_hud() + update_icons() + update_fire() + +/mob/living/carbon/alien/humanoid/update_hud() + //TODO + if (client) +// if(other) client.screen |= hud_used.other //Not used +// else client.screen -= hud_used.other //Not used + client.screen |= contents + + + +/mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1) + if(wear_suit) + var/t_state = wear_suit.item_state + if(!t_state) t_state = wear_suit.icon_state + var/image/lying = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]2") + var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") + + if(wear_suit.blood_DNA && wear_suit.blood_DNA.len) + var/t_suit = "suit" + if( istype(wear_suit, /obj/item/clothing/suit/armor) ) + t_suit = "armor" + lying.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood2") + standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood") + + //TODO + wear_suit.screen_loc = ui_alien_oclothing + if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) + drop_from_inventory(handcuffed) + drop_hands() + + overlays_lying[X_SUIT_LAYER] = lying + overlays_standing[X_SUIT_LAYER] = standing + else + overlays_lying[X_SUIT_LAYER] = null + overlays_standing[X_SUIT_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/alien/humanoid/update_inv_head(var/update_icons=1) + if (head) + var/t_state = head.item_state + if(!t_state) t_state = head.icon_state + var/image/lying = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]2") + var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") + if(head.blood_DNA && head.blood_DNA.len) + lying.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood2") + standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") + head.screen_loc = ui_alien_head + overlays_lying[X_HEAD_LAYER] = lying + overlays_standing[X_HEAD_LAYER] = standing + else + overlays_lying[X_HEAD_LAYER] = null + overlays_standing[X_HEAD_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/alien/humanoid/update_inv_pockets(var/update_icons=1) + if(l_store) l_store.screen_loc = ui_storage1 + if(r_store) r_store.screen_loc = ui_storage2 + if(update_icons) update_icons() + + +/mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1) + overlays -= overlays_standing[X_R_HAND_LAYER] + if(r_hand) + var/t_state = r_hand.item_state + var/t_inhand_state = r_hand.inhand_states["right_hand"] + if(!t_state) t_state = r_hand.icon_state + r_hand.screen_loc = ui_rhand + overlays_standing[X_R_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = t_state) + else + overlays_standing[X_R_HAND_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1) + overlays -= overlays_standing[X_L_HAND_LAYER] + if(l_hand) + var/t_state = l_hand.item_state + var/t_inhand_state = l_hand.inhand_states["left_hand"] //this is a file + if(!t_state) t_state = l_hand.icon_state + l_hand.screen_loc = ui_lhand + overlays_standing[X_L_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = t_state) + else + overlays_standing[X_L_HAND_LAYER] = null + if(update_icons) update_icons() + +//Call when target overlay should be added/removed +/mob/living/carbon/alien/humanoid/update_targeted(var/update_icons=1) + if (targeted_by && target_locked) + overlays_lying[TARGETED_LAYER] = target_locked + overlays_standing[TARGETED_LAYER] = target_locked + else if (!targeted_by && target_locked) + del(target_locked) + if (!targeted_by) + overlays_lying[TARGETED_LAYER] = null + overlays_standing[TARGETED_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/alien/humanoid/update_fire() + overlays -= overlays_lying[X_FIRE_LAYER] + overlays -= overlays_standing[X_FIRE_LAYER] + if(on_fire) + overlays_lying[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Lying", "layer"= -X_FIRE_LAYER) + overlays_standing[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"= -X_FIRE_LAYER) + if(src.lying) + overlays += overlays_lying[X_FIRE_LAYER] + else + overlays += overlays_standing[X_FIRE_LAYER] + return + else + overlays_lying[X_FIRE_LAYER] = null + overlays_standing[X_FIRE_LAYER] = null + +//Xeno Overlays Indexes////////// +#undef X_HEAD_LAYER +#undef X_SUIT_LAYER +#undef X_L_HAND_LAYER +#undef X_R_HAND_LAYER +#undef TARGETED_LAYER +#undef X_FIRE_LAYER +#undef X_TOTAL_LAYERS diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index 27f49e3ad9e..2cafc72ba8d 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -1,15 +1,15 @@ -/mob/living/carbon/alien/larva/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health6" - stat = DEAD - icon_state = "larva_dead" - - if(!gibbed) - update_canmove() - if(client) blind.layer = 0 - - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) - living_mob_list -= src - - return ..(gibbed) +/mob/living/carbon/alien/larva/death(gibbed) + if(stat == DEAD) return + if(healths) healths.icon_state = "health6" + stat = DEAD + icon_state = "larva_dead" + + if(!gibbed) + update_canmove() + if(client) blind.layer = 0 + + tod = worldtime2text() //weasellos time of death patch + if(mind) mind.store_memory("Time of death: [tod]", 0) + living_mob_list -= src + + return ..(gibbed) diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index a7044eb4b95..5d8f7e18959 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -1,118 +1,118 @@ -/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null) - if(timestopped) return //under effects of time magick - var/param = null - if(findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - - switch(act) - if("me") - if(silent) - return - if(src.client) - if(client.prefs.muted & MUTE_IC) +/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null) + if(timestopped) return //under effects of time magick + var/param = null + if(findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) + + switch(act) + if("me") + if(silent) + return + if(src.client) + if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot send IC messages (muted).") - return - if(src.client.handle_spam_prevention(message,MUTE_IC)) - return - if(stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - if("custom") - return custom_emote(m_type, message) - if("sign") - if(!src.restrained()) - message = text("\The [src] signs[(text2num(param) ? text(" the number []", text2num(param)) : null)].") - m_type = VISIBLE - if("burp") - if(!muzzled) - message = "\The [src] burps." - m_type = HEARABLE - if("scratch") - if(!src.restrained()) - message = "\The [src] scratches." - m_type = VISIBLE - if("whimper") - if(!muzzled) - message = "\The [src] whimpers." - m_type = HEARABLE - if("tail") - message = "\The [src] waves its tail." - m_type = VISIBLE - if("gasp") - message = "\The [src] gasps." - m_type = HEARABLE - if("shiver") - message = "\The [src] shivers." - m_type = HEARABLE - if("drool") - message = "\The [src] drools." - m_type = VISIBLE - if("scretch") - if(!muzzled) - message = "\The [src] scretches." - m_type = HEARABLE - if("choke") - message = "\The [src] chokes." - m_type = HEARABLE - if("moan") - message = "\The [src] moans!" - m_type = HEARABLE - if("nod") - message = "\The [src] nods its head." - m_type = VISIBLE - if("sway") - message = "\The [src] sways around dizzily." - m_type = VISIBLE - if("sulk") - message = "\The [src] sulks down sadly." - m_type = VISIBLE - if("twitch") - message = "\The [src] twitches violently." - m_type = VISIBLE - if("dance") - if(!src.restrained()) - message = "\The [src] dances around happily." - m_type = VISIBLE - if("roll") - if(!src.restrained()) - message = "\The [src] rolls." - m_type = VISIBLE - if("shake") - message = "\The [src] shakes its head." - m_type = VISIBLE - if("gnarl") - if(!muzzled) - message = "\The [src] gnarls and shows its teeth.." - m_type = HEARABLE - if("jump") - message = "\The [src] jumps!" - m_type = VISIBLE - if("hiss_") - message = "\The [src] hisses softly." - m_type = VISIBLE - if("collapse") - Paralyse(2) - message = text("\The [src] collapses!") - m_type = HEARABLE - if("help") + return + if(src.client.handle_spam_prevention(message,MUTE_IC)) + return + if(stat) + return + if(!(message)) + return + return custom_emote(m_type, message) + + if("custom") + return custom_emote(m_type, message) + if("sign") + if(!src.restrained()) + message = text("\The [src] signs[(text2num(param) ? text(" the number []", text2num(param)) : null)].") + m_type = VISIBLE + if("burp") + if(!muzzled) + message = "\The [src] burps." + m_type = HEARABLE + if("scratch") + if(!src.restrained()) + message = "\The [src] scratches." + m_type = VISIBLE + if("whimper") + if(!muzzled) + message = "\The [src] whimpers." + m_type = HEARABLE + if("tail") + message = "\The [src] waves its tail." + m_type = VISIBLE + if("gasp") + message = "\The [src] gasps." + m_type = HEARABLE + if("shiver") + message = "\The [src] shivers." + m_type = HEARABLE + if("drool") + message = "\The [src] drools." + m_type = VISIBLE + if("scretch") + if(!muzzled) + message = "\The [src] scretches." + m_type = HEARABLE + if("choke") + message = "\The [src] chokes." + m_type = HEARABLE + if("moan") + message = "\The [src] moans!" + m_type = HEARABLE + if("nod") + message = "\The [src] nods its head." + m_type = VISIBLE + if("sway") + message = "\The [src] sways around dizzily." + m_type = VISIBLE + if("sulk") + message = "\The [src] sulks down sadly." + m_type = VISIBLE + if("twitch") + message = "\The [src] twitches violently." + m_type = VISIBLE + if("dance") + if(!src.restrained()) + message = "\The [src] dances around happily." + m_type = VISIBLE + if("roll") + if(!src.restrained()) + message = "\The [src] rolls." + m_type = VISIBLE + if("shake") + message = "\The [src] shakes its head." + m_type = VISIBLE + if("gnarl") + if(!muzzled) + message = "\The [src] gnarls and shows its teeth.." + m_type = HEARABLE + if("jump") + message = "\The [src] jumps!" + m_type = VISIBLE + if("hiss_") + message = "\The [src] hisses softly." + m_type = VISIBLE + if("collapse") + Paralyse(2) + message = text("\The [src] collapses!") + m_type = HEARABLE + if("help") to_chat(src, "burp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper") - else + else // to_chat(custom_emote(VISIBLE, act) src, text("Invalid Emote: [act]")) - if((message && src.stat == 0)) - log_emote("[name]/[key] (@[x],[y],[z]): [message]") - if(m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) + if((message && src.stat == 0)) + log_emote("[name]/[key] (@[x],[y],[z]): [message]") + if(m_type & 1) + for(var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + else + for(var/mob/O in hearers(src, null)) + O.show_message(message, m_type) return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index 076053b2530..8de02639ae1 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -1,3 +1,3 @@ -//can't unequip since it can't equip anything -/mob/living/carbon/alien/larva/u_equip(obj/item/W as obj) +//can't unequip since it can't equip anything +/mob/living/carbon/alien/larva/u_equip(obj/item/W as obj) return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index b9f81ca207b..714eb68e53c 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -1,306 +1,306 @@ -/mob/living/carbon/alien/larva - name = "alien larva" //The alien larva, not 'Alien Larva' - real_name = "alien larva" - icon_state = "larva0" - pass_flags = PASSTABLE - - maxHealth = 25 - health = 25 - storedPlasma = 50 - max_plasma = 50 - size = SIZE_TINY - - var/amount_grown = 0 - var/max_grown = 200 - var/time_of_birth - -//This is fine right now, if we're adding organ specific damage this needs to be updated -/mob/living/carbon/alien/larva/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien larva") - name = "alien larva ([rand(1, 1000)])" - real_name = name - regenerate_icons() - add_language(LANGUAGE_XENO) - default_language = all_languages[LANGUAGE_XENO] - ..() - -//This needs to be fixed -/mob/living/carbon/alien/larva/Stat() - ..() - if(statpanel("Status")) - stat(null, "Progress: [amount_grown]/[max_grown]") - -/mob/living/carbon/alien/larva/adjustToxLoss(amount) - if(stat != DEAD) - amount_grown = min(amount_grown + 1, max_grown) - ..(amount) - - -/mob/living/carbon/alien/larva/ex_act(severity) - if(flags & INVULNERABLE) - return - - if(!blinded) - flick("flash", flash) - - var/b_loss = null - var/f_loss = null - switch (severity) - if(1.0) - b_loss += 500 - gib() - return - if(2.0) - b_loss += 60 - f_loss += 60 - ear_damage += 30 - ear_deaf += 120 - if(3.0) - b_loss += 30 - if(prob(50)) - Paralyse(1) - ear_damage += 15 - ear_deaf += 60 - - adjustBruteLoss(b_loss) - adjustFireLoss(f_loss) - updatehealth() - -/mob/living/carbon/alien/larva/blob_act() - if(flags & INVULNERABLE) - return - if(stat == 2) - return - var/shielded = 0 - - var/damage = null - if(stat != 2) - damage = rand(10,30) - - if(shielded) - damage /= 4 - - //paralysis += 1 - +/mob/living/carbon/alien/larva + name = "alien larva" //The alien larva, not 'Alien Larva' + real_name = "alien larva" + icon_state = "larva0" + pass_flags = PASSTABLE + + maxHealth = 25 + health = 25 + storedPlasma = 50 + max_plasma = 50 + size = SIZE_TINY + + var/amount_grown = 0 + var/max_grown = 200 + var/time_of_birth + +//This is fine right now, if we're adding organ specific damage this needs to be updated +/mob/living/carbon/alien/larva/New() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + if(name == "alien larva") + name = "alien larva ([rand(1, 1000)])" + real_name = name + regenerate_icons() + add_language(LANGUAGE_XENO) + default_language = all_languages[LANGUAGE_XENO] + ..() + +//This needs to be fixed +/mob/living/carbon/alien/larva/Stat() + ..() + if(statpanel("Status")) + stat(null, "Progress: [amount_grown]/[max_grown]") + +/mob/living/carbon/alien/larva/adjustToxLoss(amount) + if(stat != DEAD) + amount_grown = min(amount_grown + 1, max_grown) + ..(amount) + + +/mob/living/carbon/alien/larva/ex_act(severity) + if(flags & INVULNERABLE) + return + + if(!blinded) + flick("flash", flash) + + var/b_loss = null + var/f_loss = null + switch (severity) + if(1.0) + b_loss += 500 + gib() + return + if(2.0) + b_loss += 60 + f_loss += 60 + ear_damage += 30 + ear_deaf += 120 + if(3.0) + b_loss += 30 + if(prob(50)) + Paralyse(1) + ear_damage += 15 + ear_deaf += 60 + + adjustBruteLoss(b_loss) + adjustFireLoss(f_loss) + updatehealth() + +/mob/living/carbon/alien/larva/blob_act() + if(flags & INVULNERABLE) + return + if(stat == 2) + return + var/shielded = 0 + + var/damage = null + if(stat != 2) + damage = rand(10,30) + + if(shielded) + damage /= 4 + + //paralysis += 1 + to_chat(src, "The blob attacks you !") - - adjustFireLoss(damage) - updatehealth() - return - -//can't equip anything -/mob/living/carbon/alien/larva/attack_ui(slot_id) - return - -//using the default attack_animal() in carbon.dm - -/mob/living/carbon/alien/larva/attack_paw(mob/living/carbon/monkey/M as mob) - if(!(istype(M, /mob/living/carbon/monkey))) - return //Fix for aliens receiving double messages when attacking other aliens. - - if(!ticker) + + adjustFireLoss(damage) + updatehealth() + return + +//can't equip anything +/mob/living/carbon/alien/larva/attack_ui(slot_id) + return + +//using the default attack_animal() in carbon.dm + +/mob/living/carbon/alien/larva/attack_paw(mob/living/carbon/monkey/M as mob) + if(!(istype(M, /mob/living/carbon/monkey))) + return //Fix for aliens receiving double messages when attacking other aliens. + + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - -/* - //MUH SPAWN PROTECTION - if(istype(loc, /turf) && istype(loc.loc, /area/start)) + return + +/* + //MUH SPAWN PROTECTION + if(istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return -*/ - ..() - - switch(M.a_intent) - - if(I_HELP) - help_shake_act(M) - else - if(istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - if(health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - visible_message("\The [M] has bit \the [src] !") - adjustBruteLoss(rand(1, 3)) - updatehealth() - return - - -/mob/living/carbon/alien/larva/attack_slime(mob/living/carbon/slime/M as mob) - if(!ticker) + return +*/ + ..() + + switch(M.a_intent) + + if(I_HELP) + help_shake_act(M) + else + if(istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + if(health > 0) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + visible_message("\The [M] has bit \the [src] !") + adjustBruteLoss(rand(1, 3)) + updatehealth() + return + + +/mob/living/carbon/alien/larva/attack_slime(mob/living/carbon/slime/M as mob) + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - if(M.Victim) return // can't attack while eating! - - if(health > -100) - - for(var/mob/O in viewers(src, null)) - visible_message("\The [M] glomps \the [src]!") - - var/damage = rand(1, 3) - - if(istype(src, /mob/living/carbon/slime/adult)) - damage = rand(20, 40) - else - damage = rand(5, 35) - - adjustBruteLoss(damage) - - updatehealth() - return - -/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M as mob) - if(!ticker) + return + + if(M.Victim) return // can't attack while eating! + + if(health > -100) + + for(var/mob/O in viewers(src, null)) + visible_message("\The [M] glomps \the [src]!") + + var/damage = rand(1, 3) + + if(istype(src, /mob/living/carbon/slime/adult)) + damage = rand(20, 40) + else + damage = rand(5, 35) + + adjustBruteLoss(damage) + + updatehealth() + return + +/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M as mob) + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - /* - if(istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + /* + if(istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - */ - ..() - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - - Weaken(5) - if(stuttering < 5) - stuttering = 5 - Stun(5) - - visible_message("\The [src] has been touched with the stun gloves by [M] !") - return - else + return + */ + ..() + + if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = M.gloves + if(G.cell) + if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + + Weaken(5) + if(stuttering < 5) + stuttering = 5 + Stun(5) + + visible_message("\The [src] has been touched with the stun gloves by [M] !") + return + else to_chat(M, "Not enough charge !") - return - - switch(M.a_intent) - - if(I_HELP) - if(health > 0) - help_shake_act(M) - else - if(M.health >= -75.0) - if ((M.head && M.head.flags & 4) || (M.wear_mask && !( M.wear_mask.flags & 32 )) ) + return + + switch(M.a_intent) + + if(I_HELP) + if(health > 0) + help_shake_act(M) + else + if(M.health >= -75.0) + if ((M.head && M.head.flags & 4) || (M.wear_mask && !( M.wear_mask.flags & 32 )) ) to_chat(M, "Remove that mask!") - return - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human() - O.source = M - O.target = src - O.s_loc = M.loc - O.t_loc = loc - O.place = "CPR" - requests += O - spawn(0) - O.process() - return - - if(I_GRAB) - if(M == src) - return - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - - M.put_in_active_hand(G) - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has grabbed \the [src] passively !") - - else - var/damage = rand(1, 9) - if(prob(90)) - if(M_HULK in M.mutations) - damage += 5 - spawn(0) - Paralyse(1) - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - playsound(loc, "punch", 25, 1, -1) - visible_message("[M] has punched \the [src] !") - if(damage > 4.9) - Weaken(rand(10,15)) - visible_message("[M] has weakened \the [src] !") - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch \the [src] !") - return - -/mob/living/carbon/alien/larva/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if(!ticker) + return + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human() + O.source = M + O.target = src + O.s_loc = M.loc + O.t_loc = loc + O.place = "CPR" + requests += O + spawn(0) + O.process() + return + + if(I_GRAB) + if(M == src) + return + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + + M.put_in_active_hand(G) + grabbed_by += G + G.synch() + + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has grabbed \the [src] passively !") + + else + var/damage = rand(1, 9) + if(prob(90)) + if(M_HULK in M.mutations) + damage += 5 + spawn(0) + Paralyse(1) + step_away(src,M,15) + sleep(3) + step_away(src,M,15) + playsound(loc, "punch", 25, 1, -1) + visible_message("[M] has punched \the [src] !") + if(damage > 4.9) + Weaken(rand(10,15)) + visible_message("[M] has weakened \the [src] !") + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to punch \the [src] !") + return + +/mob/living/carbon/alien/larva/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + if(!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - /* - if(istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + /* + if(istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - */ - ..() - - switch(M.a_intent) - - if(I_HELP) - sleeping = max(0,sleeping-5) - resting = 0 - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - visible_message("[M.name] nuzzles [src] trying to wake it up !") - - else - if(health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - var/damage = rand(1, 3) - for(var/mob/O in viewers(src, null)) - if((O.client && !( O.blinded ))) - O.show_message(text("[M.name] has bit []!", src), 1) - adjustBruteLoss(damage) - updatehealth() - else + return + */ + ..() + + switch(M.a_intent) + + if(I_HELP) + sleeping = max(0,sleeping-5) + resting = 0 + AdjustParalysis(-3) + AdjustStunned(-3) + AdjustWeakened(-3) + visible_message("[M.name] nuzzles [src] trying to wake it up !") + + else + if(health > 0) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + var/damage = rand(1, 3) + for(var/mob/O in viewers(src, null)) + if((O.client && !( O.blinded ))) + O.show_message(text("[M.name] has bit []!", src), 1) + adjustBruteLoss(damage) + updatehealth() + else to_chat(M, "[name] is too injured for that.") - return - -/mob/living/carbon/alien/larva/restrained() - if(timestopped) return 1 //under effects of time magick - - return 0 - -/mob/living/carbon/alien/larva/var/co2overloadtime = null -/mob/living/carbon/alien/larva/var/temperature_resistance = T0C+75 - -// new damage icon system -// now constructs damage icon for each organ from mask * damage field - - -/mob/living/carbon/alien/larva/show_inv(mob/user as mob) - - user.set_machine(src) - var/dat = {" -
    [name]
    -


    -
    Close -
    "} - user << browse(dat, text("window=mob[name];size=340x480")) - onclose(user, "mob[name]") - return - -/* Why? -/mob/living/carbon/alien/larva/say_understands(var/mob/other,var/datum/language/speaking = null) - if(speaking && speaking.name == LANGUAGE_SOL_COMMON) - return 1 - return ..() -*/ + return + +/mob/living/carbon/alien/larva/restrained() + if(timestopped) return 1 //under effects of time magick + + return 0 + +/mob/living/carbon/alien/larva/var/co2overloadtime = null +/mob/living/carbon/alien/larva/var/temperature_resistance = T0C+75 + +// new damage icon system +// now constructs damage icon for each organ from mask * damage field + + +/mob/living/carbon/alien/larva/show_inv(mob/user as mob) + + user.set_machine(src) + var/dat = {" +
    [name]
    +


    +
    Close +
    "} + user << browse(dat, text("window=mob[name];size=340x480")) + onclose(user, "mob[name]") + return + +/* Why? +/mob/living/carbon/alien/larva/say_understands(var/mob/other,var/datum/language/speaking = null) + if(speaking && speaking.name == LANGUAGE_SOL_COMMON) + return 1 + return ..() +*/ diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 6607e63c8fa..1b92842a692 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -1,391 +1,391 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -//How to copypaste human life code and pretend it won't fuck up everything for ALIEN LARVAE : The Novel : The Story : The Legend : The Epic : The Game -//But seriously, someone's gonna have to look more in depth into this to get rid of useless shit - -/mob/living/carbon/alien/larva - - var/temperature_alert = 0 - - -/mob/living/carbon/alien/larva/Life() - set invisibility = 0 - //set background = 1 - if (!loc) return - if (monkeyizing) - return - if(timestopped) return 0 //under effects of time magick - - ..() - var/datum/gas_mixture/enviroment = loc.return_air() - if (stat != DEAD) //still breathing - - // GROW! - if(amount_grown < max_grown) - amount_grown++ - - //First, resolve location and get a breath - if(air_master.current_cycle%4==2) - //Only try to take a breath every 4 seconds, unless suffocating - spawn(0) breathe() - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - //Mutations and radiation - handle_mutations_and_radiation() - - //Chemicals in the body - handle_chemicals_in_body() - - - //Apparently, the person who wrote this code designed it so that - //blinded get reset each cycle and then get activated later in the - //code. Very ugly. I dont care. Moving this stuff here so its easy - //to find it. - blinded = null - - //Handle temperature/pressure differences between body and environment - handle_environment(enviroment) - - //stuff in the stomach - //handle_stomach() - - //Status updates, death etc. - handle_regular_status_updates() - update_canmove() - - // Grabbing - for(var/obj/item/weapon/grab/G in src) - G.process() - - //some kind of bug in canmove() isn't properly calling update_icons, so this is here as a placeholder - update_icons() - - if(client) - handle_regular_hud_updates() - - -/mob/living/carbon/alien/larva - - proc/breathe() - - - if(reagents.has_reagent("lexorin")) - return - if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) - return - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - // HACK NEED CHANGING LATER - if(health < 0) - losebreath++ - - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(75)) //High chance of gasping for air - spawn emote("gasp") - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - else - //First, check for air from internal atmosphere (using an air tank and mask generally) - breath = get_breath_from_internal(BREATH_VOLUME) - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) - else if(istype(loc, /turf/)) - var/breath_moles = 0 - /*if(environment.return_pressure() > ONE_ATMOSPHERE) - // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) - breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) - else*/ - // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) - - // Handle chem smoke effect -- Doohl - for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - handle_breath(breath) - - if(breath) - loc.assume_air(breath) - - - proc/get_breath_from_internal(volume_needed) - if(internal) - if (!contents.Find(internal)) - internal = null - if (!wear_mask || !(wear_mask.flags & MASKINTERNALS) ) - internal = null - if(internal) - if (internals) - internals.icon_state = "internal1" - return internal.remove_air_volume(volume_needed) - else - if (internals) - internals.icon_state = "internal0" - return null - - proc/handle_breath(datum/gas_mixture/breath) - if((status_flags & GODMODE) || (flags & INVULNERABLE)) - return - - if(!breath || (breath.total_moles == 0)) - //Aliens breathe in vaccuum - return 0 - - var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - - //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure - - if(Toxins_pp) // Detect toxins in air - - adjustToxLoss(breath.toxins*250) - toxins_alert = max(toxins_alert, 1) - - toxins_used = breath.toxins - - else - toxins_alert = 0 - - //Breathe in toxins and out oxygen - breath.toxins -= toxins_used - breath.oxygen += toxins_used - - if(breath.temperature > (T0C+66) && !(M_RESIST_HEAT in mutations)) // Hot air hurts :( - if(prob(20)) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +//How to copypaste human life code and pretend it won't fuck up everything for ALIEN LARVAE : The Novel : The Story : The Legend : The Epic : The Game +//But seriously, someone's gonna have to look more in depth into this to get rid of useless shit + +/mob/living/carbon/alien/larva + + var/temperature_alert = 0 + + +/mob/living/carbon/alien/larva/Life() + set invisibility = 0 + //set background = 1 + if (!loc) return + if (monkeyizing) + return + if(timestopped) return 0 //under effects of time magick + + ..() + var/datum/gas_mixture/enviroment = loc.return_air() + if (stat != DEAD) //still breathing + + // GROW! + if(amount_grown < max_grown) + amount_grown++ + + //First, resolve location and get a breath + if(air_master.current_cycle%4==2) + //Only try to take a breath every 4 seconds, unless suffocating + spawn(0) breathe() + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + //Mutations and radiation + handle_mutations_and_radiation() + + //Chemicals in the body + handle_chemicals_in_body() + + + //Apparently, the person who wrote this code designed it so that + //blinded get reset each cycle and then get activated later in the + //code. Very ugly. I dont care. Moving this stuff here so its easy + //to find it. + blinded = null + + //Handle temperature/pressure differences between body and environment + handle_environment(enviroment) + + //stuff in the stomach + //handle_stomach() + + //Status updates, death etc. + handle_regular_status_updates() + update_canmove() + + // Grabbing + for(var/obj/item/weapon/grab/G in src) + G.process() + + //some kind of bug in canmove() isn't properly calling update_icons, so this is here as a placeholder + update_icons() + + if(client) + handle_regular_hud_updates() + + +/mob/living/carbon/alien/larva + + proc/breathe() + + + if(reagents.has_reagent("lexorin")) + return + if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) + return + + var/datum/gas_mixture/environment = loc.return_air() + var/datum/gas_mixture/breath + // HACK NEED CHANGING LATER + if(health < 0) + losebreath++ + + if(losebreath>0) //Suffocating so do not take a breath + losebreath-- + if (prob(75)) //High chance of gasping for air + spawn emote("gasp") + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + else + //First, check for air from internal atmosphere (using an air tank and mask generally) + breath = get_breath_from_internal(BREATH_VOLUME) + + //No breath from internal atmosphere so get breath from location + if(!breath) + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) + else if(istype(loc, /turf/)) + var/breath_moles = 0 + /*if(environment.return_pressure() > ONE_ATMOSPHERE) + // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) + breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) + else*/ + // Not enough air around, take a percentage of what's there to model this properly + breath_moles = environment.total_moles()*BREATH_PERCENTAGE + + breath = loc.remove_air(breath_moles) + + // Handle chem smoke effect -- Doohl + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(src, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + + + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + + handle_breath(breath) + + if(breath) + loc.assume_air(breath) + + + proc/get_breath_from_internal(volume_needed) + if(internal) + if (!contents.Find(internal)) + internal = null + if (!wear_mask || !(wear_mask.flags & MASKINTERNALS) ) + internal = null + if(internal) + if (internals) + internals.icon_state = "internal1" + return internal.remove_air_volume(volume_needed) + else + if (internals) + internals.icon_state = "internal0" + return null + + proc/handle_breath(datum/gas_mixture/breath) + if((status_flags & GODMODE) || (flags & INVULNERABLE)) + return + + if(!breath || (breath.total_moles == 0)) + //Aliens breathe in vaccuum + return 0 + + var/toxins_used = 0 + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + + //Partial pressure of the toxins in our breath + var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + + if(Toxins_pp) // Detect toxins in air + + adjustToxLoss(breath.toxins*250) + toxins_alert = max(toxins_alert, 1) + + toxins_used = breath.toxins + + else + toxins_alert = 0 + + //Breathe in toxins and out oxygen + breath.toxins -= toxins_used + breath.oxygen += toxins_used + + if(breath.temperature > (T0C+66) && !(M_RESIST_HEAT in mutations)) // Hot air hurts :( + if(prob(20)) to_chat(src, "You feel a searing heat in your lungs !") - fire_alert = max(fire_alert, 1) - else - fire_alert = 0 - - //Temporary fixes to the alerts. - - return 1 - - - proc/handle_chemicals_in_body() - if(reagents) reagents.metabolize(src) - - if(M_FAT in mutations) - if(nutrition < 100) - if(prob(round((50 - nutrition) / 100))) + fire_alert = max(fire_alert, 1) + else + fire_alert = 0 + + //Temporary fixes to the alerts. + + return 1 + + + proc/handle_chemicals_in_body() + if(reagents) reagents.metabolize(src) + + if(M_FAT in mutations) + if(nutrition < 100) + if(prob(round((50 - nutrition) / 100))) to_chat(src, "You feel fit again !") - mutations.Add(M_FAT) - else - if(nutrition > 500) - if(prob(5 + round((nutrition - max_grown) / 2))) + mutations.Add(M_FAT) + else + if(nutrition > 500) + if(prob(5 + round((nutrition - max_grown) / 2))) to_chat(src, "You suddenly feel blubbery !") - mutations.Add(M_FAT) - - if (nutrition > 0) - nutrition-= HUNGER_FACTOR - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 5) - jitteriness = max(0, jitteriness - 5) - else - dizziness = max(0, dizziness - 1) - jitteriness = max(0, jitteriness - 1) - - updatehealth() - - return //TODO: DEFERRED - - proc/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - if(health < -25 || !has_brain()) - death() - blinded = 1 - silent = 0 - return 1 - - //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 25) || (0 > health) ) - //if( health <= 20 && prob(1) ) - // spawn(0) - // emote("gasp") - if(!reagents.has_reagent("inaprovaline")) - adjustOxyLoss(1) - Paralyse(3) - - if(paralysis) - AdjustParalysis(-2) - blinded = 1 - stat = UNCONSCIOUS - else if(sleeping) - sleeping = max(sleeping-1, 0) - blinded = 1 - stat = UNCONSCIOUS - if( prob(10) && health ) - spawn(0) - emote("hiss_") - //CONSCIOUS - else - stat = CONSCIOUS - - /* What in the living hell is this?*/ - if(move_delay_add > 0) - move_delay_add = max(0, move_delay_add - rand(1, 2)) - - //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly - eye_blurry = max(eye_blurry-1, 0) - - //Ears - if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own - ear_deaf = max(ear_deaf, 1) - else if(ear_deaf) //deafness, heals slowly over time - ear_deaf = max(ear_deaf-1, 0) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. - ear_damage = max(ear_damage-0.05, 0) - - //Other - if(stunned) - 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) - stuttering = max(stuttering-1, 0) - - if(silent) - silent = max(silent-1, 0) - - if(druggy) - druggy = max(druggy-1, 0) - return 1 - - - proc/handle_regular_hud_updates() - - - if (stat == 2 || (M_XRAY in mutations)) - sight |= SEE_TURFS - sight |= SEE_MOBS - sight |= SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - else if (stat != 2) - sight |= SEE_MOBS - sight &= ~SEE_TURFS - sight &= ~SEE_OBJS - see_in_dark = 4 - see_invisible = SEE_INVISIBLE_MINIMUM - - if (healths) - if (stat != 2) - switch(health) - if(25 to INFINITY) - healths.icon_state = "health0" - if(19 to 25) - healths.icon_state = "health1" - if(13 to 19) - healths.icon_state = "health2" - if(7 to 13) - healths.icon_state = "health3" - if(0 to 7) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" - - - if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]" - if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" - if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]" - //NOTE: the alerts dont reset when youre out of danger. dont blame me, - //blame the person who coded them. Temporary fix added. - if (client) - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if ((blind && stat != 2)) - if ((blinded)) - blind.layer = 18 - else - blind.layer = 0 - - if (disabilities & NEARSIGHTED) - client.screen += global_hud.vimpaired - - if (eye_blurry) - client.screen += global_hud.blurry - - if (druggy) - client.screen += global_hud.druggy - - if (stat != 2) - if (machine) - if (!( machine.check_eye(src) )) - reset_view(null) - else - if(client && !client.adminobs) - reset_view(null) - - return 1 - - proc/handle_random_events() - return - - - proc/handle_stomach() - spawn(0) - for(var/mob/living/M in stomach_contents) - if(M.loc != src) - stomach_contents.Remove(M) - continue - if(istype(M, /mob/living/carbon) && stat != 2) - if(M.stat == 2) - M.death(1) - stomach_contents.Remove(M) - qdel(M) - M = null - continue - if(air_master.current_cycle%3==1) - if(!(M.status_flags & GODMODE)) - M.adjustBruteLoss(5) - nutrition += 10 + mutations.Add(M_FAT) + + if (nutrition > 0) + nutrition-= HUNGER_FACTOR + + if (drowsyness) + drowsyness-- + eye_blurry = max(2, eye_blurry) + if (prob(5)) + sleeping += 1 + Paralyse(5) + + confused = max(0, confused - 1) + // decrement dizziness counter, clamped to 0 + if(resting) + dizziness = max(0, dizziness - 5) + jitteriness = max(0, jitteriness - 5) + else + dizziness = max(0, dizziness - 1) + jitteriness = max(0, jitteriness - 1) + + updatehealth() + + return //TODO: DEFERRED + + proc/handle_regular_status_updates() + updatehealth() + + if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP + blinded = 1 + silent = 0 + else //ALIVE. LIGHTS ARE ON + if(health < -25 || !has_brain()) + death() + blinded = 1 + silent = 0 + return 1 + + //UNCONSCIOUS. NO-ONE IS HOME + if( (getOxyLoss() > 25) || (0 > health) ) + //if( health <= 20 && prob(1) ) + // spawn(0) + // emote("gasp") + if(!reagents.has_reagent("inaprovaline")) + adjustOxyLoss(1) + Paralyse(3) + + if(paralysis) + AdjustParalysis(-2) + blinded = 1 + stat = UNCONSCIOUS + else if(sleeping) + sleeping = max(sleeping-1, 0) + blinded = 1 + stat = UNCONSCIOUS + if( prob(10) && health ) + spawn(0) + emote("hiss_") + //CONSCIOUS + else + stat = CONSCIOUS + + /* What in the living hell is this?*/ + if(move_delay_add > 0) + move_delay_add = max(0, move_delay_add - rand(1, 2)) + + //Eyes + if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own + blinded = 1 + else if(eye_blind) //blindness, heals slowly over time + eye_blind = max(eye_blind-1,0) + blinded = 1 + else if(eye_blurry) //blurry eyes heal slowly + eye_blurry = max(eye_blurry-1, 0) + + //Ears + if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own + ear_deaf = max(ear_deaf, 1) + else if(ear_deaf) //deafness, heals slowly over time + ear_deaf = max(ear_deaf-1, 0) + else if(ear_damage < 25) //ear damage heals slowly under this threshold. + ear_damage = max(ear_damage-0.05, 0) + + //Other + if(stunned) + 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) + stuttering = max(stuttering-1, 0) + + if(silent) + silent = max(silent-1, 0) + + if(druggy) + druggy = max(druggy-1, 0) + return 1 + + + proc/handle_regular_hud_updates() + + + if (stat == 2 || (M_XRAY in mutations)) + sight |= SEE_TURFS + sight |= SEE_MOBS + sight |= SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (stat != 2) + sight |= SEE_MOBS + sight &= ~SEE_TURFS + sight &= ~SEE_OBJS + see_in_dark = 4 + see_invisible = SEE_INVISIBLE_MINIMUM + + if (healths) + if (stat != 2) + switch(health) + if(25 to INFINITY) + healths.icon_state = "health0" + if(19 to 25) + healths.icon_state = "health1" + if(13 to 19) + healths.icon_state = "health2" + if(7 to 13) + healths.icon_state = "health3" + if(0 to 7) + healths.icon_state = "health4" + else + healths.icon_state = "health5" + else + healths.icon_state = "health6" + + if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" + + + if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]" + if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" + if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]" + //NOTE: the alerts dont reset when youre out of danger. dont blame me, + //blame the person who coded them. Temporary fix added. + if (client) + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if ((blind && stat != 2)) + if ((blinded)) + blind.layer = 18 + else + blind.layer = 0 + + if (disabilities & NEARSIGHTED) + client.screen += global_hud.vimpaired + + if (eye_blurry) + client.screen += global_hud.blurry + + if (druggy) + client.screen += global_hud.druggy + + if (stat != 2) + if (machine) + if (!( machine.check_eye(src) )) + reset_view(null) + else + if(client && !client.adminobs) + reset_view(null) + + return 1 + + proc/handle_random_events() + return + + + proc/handle_stomach() + spawn(0) + for(var/mob/living/M in stomach_contents) + if(M.loc != src) + stomach_contents.Remove(M) + continue + if(istype(M, /mob/living/carbon) && stat != 2) + if(M.stat == 2) + M.death(1) + stomach_contents.Remove(M) + qdel(M) + M = null + continue + if(air_master.current_cycle%3==1) + if(!(M.status_flags & GODMODE)) + M.adjustBruteLoss(5) + nutrition += 10 diff --git a/code/modules/mob/living/carbon/alien/larva/login.dm b/code/modules/mob/living/carbon/alien/larva/login.dm index 33808a4d966..c98df1af7f5 100644 --- a/code/modules/mob/living/carbon/alien/larva/login.dm +++ b/code/modules/mob/living/carbon/alien/larva/login.dm @@ -1,3 +1,3 @@ -/mob/living/carbon/alien/larva/Login() - return ..() - +/mob/living/carbon/alien/larva/Login() + return ..() + diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm index 7b9b67bc851..f89689701c4 100644 --- a/code/modules/mob/living/carbon/alien/larva/powers.dm +++ b/code/modules/mob/living/carbon/alien/larva/powers.dm @@ -1,56 +1,56 @@ - -/mob/living/carbon/alien/larva/verb/hide() - set name = "Hide" - set desc = "Allows you to hide beneath tables or items laid on the ground. Toggle." - set category = "Alien" - - if(stat != CONSCIOUS) - return - - if(layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - visible_message("[src] scurries to the ground !", "You are now hiding.") - else - layer = MOB_LAYER - visible_message("[src] slowly peeks up from the ground...", "You have stopped hiding.") - -/mob/living/carbon/alien/larva/verb/evolve() - set name = "Evolve" - set desc = "Evolve into a fully grown Alien." - set category = "Alien" - - if(stat != CONSCIOUS) - return - - //Seems about right - //if(handcuffed || legcuffed) -// to_chat(src, "You cannot evolve when you are cuffed.") - - if(amount_grown >= max_grown) //TODO ~Carn - //green is impossible to read, so i made these blue and changed the formatting slightly - to_chat(src, {"You are growing into a beautiful alien! It is time to choose a caste.
    - There are three castes to choose from:
    - Hunters are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves.
    - Sentinels are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters.
    - Drones are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen."}) - var/alien_caste = alert(src, "Please choose which alien caste you shall evolve to.",,"Hunter","Sentinel","Drone") - - var/mob/living/carbon/alien/humanoid/new_xeno - switch(alien_caste) - if("Hunter") - new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc) - if("Sentinel") - new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc) - if("Drone") - new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc) - for(var/datum/language/L in languages) - new_xeno.add_language(L.name) - if(mind) mind.transfer_to(new_xeno) - transferImplantsTo(new_xeno) - transferBorers(new_xeno) - qdel(src) - playsound(get_turf(src), 'sound/effects/evolve.ogg', 40, 1) - return - else - to_chat(src, "You are not fully grown yet.") - return + +/mob/living/carbon/alien/larva/verb/hide() + set name = "Hide" + set desc = "Allows you to hide beneath tables or items laid on the ground. Toggle." + set category = "Alien" + + if(stat != CONSCIOUS) + return + + if(layer != TURF_LAYER+0.2) + layer = TURF_LAYER+0.2 + visible_message("[src] scurries to the ground !", "You are now hiding.") + else + layer = MOB_LAYER + visible_message("[src] slowly peeks up from the ground...", "You have stopped hiding.") + +/mob/living/carbon/alien/larva/verb/evolve() + set name = "Evolve" + set desc = "Evolve into a fully grown Alien." + set category = "Alien" + + if(stat != CONSCIOUS) + return + + //Seems about right + //if(handcuffed || legcuffed) +// to_chat(src, "You cannot evolve when you are cuffed.") + + if(amount_grown >= max_grown) //TODO ~Carn + //green is impossible to read, so i made these blue and changed the formatting slightly + to_chat(src, {"You are growing into a beautiful alien! It is time to choose a caste.
    + There are three castes to choose from:
    + Hunters are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves.
    + Sentinels are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters.
    + Drones are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen."}) + var/alien_caste = alert(src, "Please choose which alien caste you shall evolve to.",,"Hunter","Sentinel","Drone") + + var/mob/living/carbon/alien/humanoid/new_xeno + switch(alien_caste) + if("Hunter") + new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc) + if("Sentinel") + new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc) + if("Drone") + new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc) + for(var/datum/language/L in languages) + new_xeno.add_language(L.name) + if(mind) mind.transfer_to(new_xeno) + transferImplantsTo(new_xeno) + transferBorers(new_xeno) + qdel(src) + playsound(get_turf(src), 'sound/effects/evolve.ogg', 40, 1) + return + else + to_chat(src, "You are not fully grown yet.") + return diff --git a/code/modules/mob/living/carbon/alien/larva/update_icons.dm b/code/modules/mob/living/carbon/alien/larva/update_icons.dm index 3ab3fb3b382..40a526a32a1 100644 --- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/larva/update_icons.dm @@ -1,22 +1,22 @@ - -/mob/living/carbon/alien/larva/regenerate_icons() - overlays = list() - update_icons() - -/mob/living/carbon/alien/larva/update_icons() - var/state = 0 - if(amount_grown > 150) - state = 2 - else if(amount_grown > 50) - state = 1 - - if(stat == DEAD) - icon_state = "larva[state]_dead" - else if (handcuffed || legcuffed) - icon_state = "larva[state]_cuff" - else if (stunned) - icon_state = "larva[state]_stun" - else if(lying || resting) - icon_state = "larva[state]_sleep" - else - icon_state = "larva[state]" + +/mob/living/carbon/alien/larva/regenerate_icons() + overlays = list() + update_icons() + +/mob/living/carbon/alien/larva/update_icons() + var/state = 0 + if(amount_grown > 150) + state = 2 + else if(amount_grown > 50) + state = 1 + + if(stat == DEAD) + icon_state = "larva[state]_dead" + else if (handcuffed || legcuffed) + icon_state = "larva[state]_cuff" + else if (stunned) + icon_state = "larva[state]_stun" + else if(lying || resting) + icon_state = "larva[state]_sleep" + else + icon_state = "larva[state]" diff --git a/code/modules/mob/living/carbon/alien/login.dm b/code/modules/mob/living/carbon/alien/login.dm index 9701338e4b2..71b93e40c6c 100644 --- a/code/modules/mob/living/carbon/alien/login.dm +++ b/code/modules/mob/living/carbon/alien/login.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/alien/humanoid/Login() - ..() - AddInfectionImages() - return +/mob/living/carbon/alien/humanoid/Login() + ..() + AddInfectionImages() + return diff --git a/code/modules/mob/living/carbon/alien/logout.dm b/code/modules/mob/living/carbon/alien/logout.dm index c0734cd21fd..7f1f20b8293 100644 --- a/code/modules/mob/living/carbon/alien/logout.dm +++ b/code/modules/mob/living/carbon/alien/logout.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/alien/humanoid/Logout() - ..() - RemoveInfectionImages() - return +/mob/living/carbon/alien/humanoid/Logout() + ..() + RemoveInfectionImages() + return diff --git a/code/modules/mob/living/carbon/alien/powers.dm b/code/modules/mob/living/carbon/alien/powers.dm index 3aa806d6fbe..444bca35422 100644 --- a/code/modules/mob/living/carbon/alien/powers.dm +++ b/code/modules/mob/living/carbon/alien/powers.dm @@ -1,7 +1,7 @@ -/mob/living/carbon/alien/verb/ventcrawl() // -- TLE - set name = "Crawl Through Vent (Alien)" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Alien" - var/pipe = start_ventcrawl() - if(pipe) - handle_ventcrawl(pipe) +/mob/living/carbon/alien/verb/ventcrawl() // -- TLE + set name = "Crawl Through Vent (Alien)" + set desc = "Enter an air vent and crawl through the pipe system." + set category = "Alien" + var/pipe = start_ventcrawl() + if(pipe) + handle_ventcrawl(pipe) diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm index c64f749496e..825830bb9df 100644 --- a/code/modules/mob/living/carbon/alien/say.dm +++ b/code/modules/mob/living/carbon/alien/say.dm @@ -1,31 +1,31 @@ -/mob/living/carbon/alien/say(var/message) - . = ..(message, "A") - if(.) - playsound(loc, "hiss", 25, 1, 1) - -/mob/living/proc/alien_talk(var/message) - - - var/turf/T = get_turf(src) - log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Alien Hivemind: [message]") - message = trim(message) - - if (!message) - return - - var/message_a = say_quote("\"[html_encode(message)]\"") - var/rendered = text("Hivemind, [] []",name,message_a) - for (var/mob/S in player_list) - if((!S.stat && S.hivecheck()) || ((S in dead_mob_list) && !istype(S, /mob/new_player))) - handle_render(S,rendered,src) - -/mob/living/carbon/alien/handle_inherent_channels(var/datum/speech/speech, var/message_mode) - if(!..()) - if(message_mode == MODE_ALIEN) - if(hivecheck()) - alien_talk(speech.message) - return 1 - return 0 - -/mob/living/carbon/alien/hivecheck() +/mob/living/carbon/alien/say(var/message) + . = ..(message, "A") + if(.) + playsound(loc, "hiss", 25, 1, 1) + +/mob/living/proc/alien_talk(var/message) + + + var/turf/T = get_turf(src) + log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Alien Hivemind: [message]") + message = trim(message) + + if (!message) + return + + var/message_a = say_quote("\"[html_encode(message)]\"") + var/rendered = text("Hivemind, [] []",name,message_a) + for (var/mob/S in player_list) + if((!S.stat && S.hivecheck()) || ((S in dead_mob_list) && !istype(S, /mob/new_player))) + handle_render(S,rendered,src) + +/mob/living/carbon/alien/handle_inherent_channels(var/datum/speech/speech, var/message_mode) + if(!..()) + if(message_mode == MODE_ALIEN) + if(hivecheck()) + alien_talk(speech.message) + return 1 + return 0 + +/mob/living/carbon/alien/hivecheck() return 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/_main.dm b/code/modules/mob/living/carbon/alien/special/_main.dm index 60106d9f6b6..47b0bd77a3b 100644 --- a/code/modules/mob/living/carbon/alien/special/_main.dm +++ b/code/modules/mob/living/carbon/alien/special/_main.dm @@ -1,72 +1,72 @@ -//XCOM alien code -//By Xerif (Donated by the Foundation project, ss13.org) - -/mob/living/carbon/alien/humanoid/special - has_fine_manipulation = 1 - var/xcom_state - - New() - ..() - spawn (1) - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - - mind = new() - mind.key = key - mind.special_role = "Special Xeno" - - name = "[name] ([rand(1, 1000)])" - real_name = name - - src.stand_icon = new /icon('xcomalien.dmi', xcom_state) - src.lying_icon = new /icon('xcomalien.dmi', xcom_state) - src.icon = src.stand_icon - - remove_special_verbs() - - - rebuild_appearance() - - death(gibbed) - ..() - spawn(5) - gib() - - Stat() - if(statpanel("Status")) - if(src.client && src.client.holder) - stat(null, "([x], [y], [z])") - - stat(null, "Intent: [src.a_intent]") - stat(null, "Move Mode: [src.m_intent]") - - if (src.internal) - if (!src.internal.air_contents) - qdel(src.internal) - src.internal = null - else - stat("Internal Atmosphere Info", src.internal.name) - stat("Tank Pressure", src.internal.air_contents.return_pressure()) - stat("Distribution Pressure", src.internal.distribute_pressure) - return - - alien_talk() - if(istype(src, /mob/living/carbon/alien/humanoid/special/etheral)) - ..() - return - if(istype(src, /mob/living/carbon/alien/humanoid/special/sectoid)) - ..() - return - return - -/mob/living/carbon/alien/humanoid/special/proc/xcom_attack() - return - -/mob/living/carbon/alien/humanoid/special/proc/remove_special_verbs() - verbs -= /mob/living/carbon/alien/humanoid/verb/plant - verbs -= /mob/living/carbon/alien/humanoid/verb/ActivateHuggers - verbs -= /mob/living/carbon/alien/humanoid/verb/whisp - verbs -= /mob/living/carbon/alien/humanoid/verb/transfer_plasma - verbs -= /mob/living/carbon/alien/humanoid/verb/corrode - return +//XCOM alien code +//By Xerif (Donated by the Foundation project, ss13.org) + +/mob/living/carbon/alien/humanoid/special + has_fine_manipulation = 1 + var/xcom_state + + New() + ..() + spawn (1) + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + + mind = new() + mind.key = key + mind.special_role = "Special Xeno" + + name = "[name] ([rand(1, 1000)])" + real_name = name + + src.stand_icon = new /icon('xcomalien.dmi', xcom_state) + src.lying_icon = new /icon('xcomalien.dmi', xcom_state) + src.icon = src.stand_icon + + remove_special_verbs() + + + rebuild_appearance() + + death(gibbed) + ..() + spawn(5) + gib() + + Stat() + if(statpanel("Status")) + if(src.client && src.client.holder) + stat(null, "([x], [y], [z])") + + stat(null, "Intent: [src.a_intent]") + stat(null, "Move Mode: [src.m_intent]") + + if (src.internal) + if (!src.internal.air_contents) + qdel(src.internal) + src.internal = null + else + stat("Internal Atmosphere Info", src.internal.name) + stat("Tank Pressure", src.internal.air_contents.return_pressure()) + stat("Distribution Pressure", src.internal.distribute_pressure) + return + + alien_talk() + if(istype(src, /mob/living/carbon/alien/humanoid/special/etheral)) + ..() + return + if(istype(src, /mob/living/carbon/alien/humanoid/special/sectoid)) + ..() + return + return + +/mob/living/carbon/alien/humanoid/special/proc/xcom_attack() + return + +/mob/living/carbon/alien/humanoid/special/proc/remove_special_verbs() + verbs -= /mob/living/carbon/alien/humanoid/verb/plant + verbs -= /mob/living/carbon/alien/humanoid/verb/ActivateHuggers + verbs -= /mob/living/carbon/alien/humanoid/verb/whisp + verbs -= /mob/living/carbon/alien/humanoid/verb/transfer_plasma + verbs -= /mob/living/carbon/alien/humanoid/verb/corrode + return diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 408d6c2df71..1544cb0b766 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -1,196 +1,196 @@ -// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability -// It functions almost identically (see code/datums/diseases/alien_embryo.dm) - -/obj/item/alien_embryo - name = "alien embryo" //The alien embryo, not Alien Embryo - desc = "All slimy and yuck." - icon = 'icons/mob/alien.dmi' - icon_state = "larva0_dead" - var/mob/living/affected_mob - var/list/ghost_volunteers[0] - var/picked=null - var/stage = 0 - -/obj/item/alien_embryo/New() - if(istype(loc, /mob/living)) - affected_mob = loc - processing_objects.Add(src) - - for(var/mob/dead/observer/O in get_active_candidates(ROLE_ALIEN,poll="[affected_mob] has been infected by \a [src]!")) - if(O.client && O.client.desires_role(ROLE_ALIEN)) - if(check_observer(O)) - to_chat(O, "You have automatically been signed up for \a [src]. (Teleport | Retract)") - ghost_volunteers += O - spawn(0) - AddInfectionImages(affected_mob) - else - qdel(src) - -/obj/item/alien_embryo/Topic(href,href_list) - if("signup" in href_list) - var/mob/dead/observer/O = locate(href_list["signup"]) - if(!O) return - volunteer(O) - - -/obj/item/alien_embryo/proc/volunteer(var/mob/dead/observer/O) - if(!istype(O)) - to_chat(O, "NO.") - return - if(O in ghost_volunteers) - to_chat(O, "You will no longer be considered for this [src]. Click again to volunteer.") - ghost_volunteers.Remove(O) - return - if(!check_observer(O)) - to_chat(O, "You cannot be \a [src] in your current condition.") - return - to_chat(O, "You have been added to the list of ghosts that may become this [src]. Click again to unvolunteer.") - ghost_volunteers.Add(O) - -/obj/item/alien_embryo/proc/check_observer(var/mob/dead/observer/O) - if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) - return 0 - if(jobban_isbanned(O, "Syndicate")) // Antag-banned - return 0 - if(!O.client) - return 0 - if(((O.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER) // Filter AFK - return 1 - return 0 - -/obj/item/alien_embryo/Destroy() - if(affected_mob) - affected_mob.status_flags &= ~(XENO_HOST) - spawn(0) - RemoveInfectionImages(affected_mob) - ..() - -/obj/item/alien_embryo/process() - if(!affected_mob) return - if(loc != affected_mob) - affected_mob.status_flags &= ~(XENO_HOST) - processing_objects.Remove(src) - spawn(0) - RemoveInfectionImages(affected_mob) - affected_mob = null - return - - if(stage < 5 && prob(3)) - stage++ - spawn(0) - RefreshInfectionImage(affected_mob) - - switch(stage) - if(2, 3) - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(1)) - to_chat(affected_mob, "Mucous runs down the back of your throat.") - if(4) - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(2)) - to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_organ_damage(1) - if(prob(2)) - to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - if(5) - to_chat(affected_mob, "You feel something tearing its way out of your stomach...") - affected_mob.adjustToxLoss(10) - affected_mob.updatehealth() - if(prob(50)) - AttemptGrow() - -/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1) - // To stop clientless larva, we will check that our host has a client - // if we find no ghosts to become the alien. If the host has a client - // he will become the alien but if he doesn't then we will set the stage - // to 2, so we don't do a process heavy check everytime. - var/mob/dead/observer/ghostpicked - while(ghost_volunteers.len) - ghostpicked = pick_n_take(ghost_volunteers) - if(!istype(ghostpicked)) - continue - break - if(!ghostpicked || !istype(ghostpicked)) - var/list/candidates = get_active_candidates(ROLE_ALIEN, buffer=ALIEN_SELECT_AFK_BUFFER, poll=1) - if(!candidates.len) - picked = affected_mob.key //Pick the person who was infected - else - for(var/mob/dead/observer/O in candidates) - to_chat(O, "[affected_mob] is about to burst from \a [src]!. (Teleport | Sign Up)") - - else - picked = ghostpicked.key - if(!picked) - stage = 4 // Let's try again later. - var/list/candidates = get_active_candidates(ROLE_ALIEN, buffer=ALIEN_SELECT_AFK_BUFFER, poll=1) - for(var/mob/dead/observer/O in candidates) //Shiggy - to_chat(O, "[affected_mob] is about to burst from \a [src]!. (Teleport | Sign Up)") - return - - if(affected_mob.lying) - affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie") - else - affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand") - spawn(6) - var/mob/living/carbon/alien/larva/new_xeno = new(get_turf(affected_mob)) - new_xeno.key = picked - new_xeno << sound('sound/voice/hiss5.ogg', 0, 0, 0, 100)//To get the player's attention +// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability +// It functions almost identically (see code/datums/diseases/alien_embryo.dm) - if(gib_on_success) - affected_mob.gib() - qdel(src) - -/*---------------------------------------- +/obj/item/alien_embryo + name = "alien embryo" //The alien embryo, not Alien Embryo + desc = "All slimy and yuck." + icon = 'icons/mob/alien.dmi' + icon_state = "larva0_dead" + var/mob/living/affected_mob + var/list/ghost_volunteers[0] + var/picked=null + var/stage = 0 + +/obj/item/alien_embryo/New() + if(istype(loc, /mob/living)) + affected_mob = loc + processing_objects.Add(src) + + for(var/mob/dead/observer/O in get_active_candidates(ROLE_ALIEN,poll="[affected_mob] has been infected by \a [src]!")) + if(O.client && O.client.desires_role(ROLE_ALIEN)) + if(check_observer(O)) + to_chat(O, "You have automatically been signed up for \a [src]. (Teleport | Retract)") + ghost_volunteers += O + spawn(0) + AddInfectionImages(affected_mob) + else + qdel(src) + +/obj/item/alien_embryo/Topic(href,href_list) + if("signup" in href_list) + var/mob/dead/observer/O = locate(href_list["signup"]) + if(!O) return + volunteer(O) + + +/obj/item/alien_embryo/proc/volunteer(var/mob/dead/observer/O) + if(!istype(O)) + to_chat(O, "NO.") + return + if(O in ghost_volunteers) + to_chat(O, "You will no longer be considered for this [src]. Click again to volunteer.") + ghost_volunteers.Remove(O) + return + if(!check_observer(O)) + to_chat(O, "You cannot be \a [src] in your current condition.") + return + to_chat(O, "You have been added to the list of ghosts that may become this [src]. Click again to unvolunteer.") + ghost_volunteers.Add(O) + +/obj/item/alien_embryo/proc/check_observer(var/mob/dead/observer/O) + if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) + return 0 + if(jobban_isbanned(O, "Syndicate")) // Antag-banned + return 0 + if(!O.client) + return 0 + if(((O.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER) // Filter AFK + return 1 + return 0 + +/obj/item/alien_embryo/Destroy() + if(affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + spawn(0) + RemoveInfectionImages(affected_mob) + ..() + +/obj/item/alien_embryo/process() + if(!affected_mob) return + if(loc != affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + processing_objects.Remove(src) + spawn(0) + RemoveInfectionImages(affected_mob) + affected_mob = null + return + + if(stage < 5 && prob(3)) + stage++ + spawn(0) + RefreshInfectionImage(affected_mob) + + switch(stage) + if(2, 3) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "Mucous runs down the back of your throat.") + if(4) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(2)) + to_chat(affected_mob, "Your muscles ache.") + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(2)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + if(5) + to_chat(affected_mob, "You feel something tearing its way out of your stomach...") + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(50)) + AttemptGrow() + +/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1) + // To stop clientless larva, we will check that our host has a client + // if we find no ghosts to become the alien. If the host has a client + // he will become the alien but if he doesn't then we will set the stage + // to 2, so we don't do a process heavy check everytime. + var/mob/dead/observer/ghostpicked + while(ghost_volunteers.len) + ghostpicked = pick_n_take(ghost_volunteers) + if(!istype(ghostpicked)) + continue + break + if(!ghostpicked || !istype(ghostpicked)) + var/list/candidates = get_active_candidates(ROLE_ALIEN, buffer=ALIEN_SELECT_AFK_BUFFER, poll=1) + if(!candidates.len) + picked = affected_mob.key //Pick the person who was infected + else + for(var/mob/dead/observer/O in candidates) + to_chat(O, "[affected_mob] is about to burst from \a [src]!. (Teleport | Sign Up)") + + else + picked = ghostpicked.key + if(!picked) + stage = 4 // Let's try again later. + var/list/candidates = get_active_candidates(ROLE_ALIEN, buffer=ALIEN_SELECT_AFK_BUFFER, poll=1) + for(var/mob/dead/observer/O in candidates) //Shiggy + to_chat(O, "[affected_mob] is about to burst from \a [src]!. (Teleport | Sign Up)") + return + + if(affected_mob.lying) + affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie") + else + affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand") + spawn(6) + var/mob/living/carbon/alien/larva/new_xeno = new(get_turf(affected_mob)) + new_xeno.key = picked + new_xeno << sound('sound/voice/hiss5.ogg', 0, 0, 0, 100)//To get the player's attention + + if(gib_on_success) + affected_mob.gib() + qdel(src) + +/*---------------------------------------- Proc: RefreshInfectionImage() -Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. -----------------------------------------*/ -/obj/item/alien_embryo/proc/RefreshInfectionImage() - for(var/mob/living/carbon/alien/alien in player_list) - if(alien.client) - for(var/image/I in alien.client.images) - if(dd_hasprefix_case(I.icon_state, "infected")) - alien.client.images -= I - for(var/mob/living/L in mob_list) - if(iscorgi(L) || iscarbon(L)) - if(L.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]") - alien.client.images += I - -/*---------------------------------------- +Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. +----------------------------------------*/ +/obj/item/alien_embryo/proc/RefreshInfectionImage() + for(var/mob/living/carbon/alien/alien in player_list) + if(alien.client) + for(var/image/I in alien.client.images) + if(dd_hasprefix_case(I.icon_state, "infected")) + alien.client.images -= I + for(var/mob/living/L in mob_list) + if(iscorgi(L) || iscarbon(L)) + if(L.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]") + alien.client.images += I + +/*---------------------------------------- Proc: AddInfectionImages(C) -Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C. -----------------------------------------*/ -/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C) - if(C) - for(var/mob/living/carbon/alien/alien in player_list) - if(alien.client) - if(C.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") - alien.client.images += I - -/*---------------------------------------- +Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C. +----------------------------------------*/ +/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C) + if(C) + for(var/mob/living/carbon/alien/alien in player_list) + if(alien.client) + if(C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + +/*---------------------------------------- Proc: RemoveInfectionImage(C) -Des: Removes the alien infection image from all aliens in the world located in passed mob (C). -----------------------------------------*/ - -/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C) - if(C) - for(var/mob/living/carbon/alien/alien in player_list) - if(alien.client) - for(var/image/I in alien.client.images) - if(I.loc == C) - if(dd_hasprefix_case(I.icon_state, "infected")) - //del(I) - alien.client.images -= I +Des: Removes the alien infection image from all aliens in the world located in passed mob (C). +----------------------------------------*/ + +/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C) + if(C) + for(var/mob/living/carbon/alien/alien in player_list) + if(alien.client) + for(var/image/I in alien.client.images) + if(I.loc == C) + if(dd_hasprefix_case(I.icon_state, "infected")) + //del(I) + alien.client.images -= I diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index df61ed2a00a..4a34e20cf19 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -1,247 +1,247 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -//TODO: Make these simple_animals - -var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone -var/const/MAX_IMPREGNATION_TIME = 150 - -var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle -var/const/MAX_ACTIVE_TIME = 400 - -/obj/item/clothing/mask/facehugger - name = "facehugger" //Let's call this 'alien' what it is. Come on Bay - desc = "It has some sort of a tube at the end of its tail." - icon = 'icons/mob/alien.dmi' - icon_state = "facehugger" - item_state = "facehugger" - w_class = 1 //note: can be picked up by aliens unlike most other items of w_class below 4 - flags = FPRINT | MASKINTERNALS | PROXMOVE - body_parts_covered = HEAD|MOUTH|EYES - throw_range = 5 - var/real = 1 //Facehuggers are real, toys are not. - - var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case - - var/sterile = 0 - - var/strength = 5 - - var/attached = 0 - -/obj/item/clothing/mask/facehugger/can_contaminate() - return 0 - -/obj/item/clothing/mask/facehugger/attack_paw(user as mob) //can be picked up by aliens - if(isalien(user)) - attack_hand(user) - return - else - ..() - return - -/obj/item/clothing/mask/facehugger/attack_hand(user as mob) - if((stat == CONSCIOUS && !sterile) && !isalien(user)) - Attach(user) - return - else - ..() - return - -/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob) - ..() - user.drop_from_inventory(src) - Attach(M) - -/obj/item/clothing/mask/facehugger/New() - if(aliens_allowed) - ..() - else - qdel(src) - -/obj/item/clothing/mask/facehugger/examine(mob/user) - ..() - if(!real) //Toy facehuggers are a child, avoid confusing examine text. - return - switch(stat) - if(DEAD,UNCONSCIOUS) - to_chat(user, "\The [src] is not moving.") - if(CONSCIOUS) - to_chat(user, "\The [src] seems active.") - if (sterile) - to_chat(user, "It looks like \the [src]'s proboscis has been removed.") - -/obj/item/clothing/mask/facehugger/attackby() - Die() - return - -/obj/item/clothing/mask/facehugger/bullet_act() - Die() - return - -/obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - Die() - return - -/obj/item/clothing/mask/facehugger/equipped(mob/M) - Attach(M) - -/obj/item/clothing/mask/facehugger/Crossed(atom/target) - HasProximity(target) - return - -/obj/item/clothing/mask/facehugger/on_found(mob/finder as mob) - if(stat == CONSCIOUS) - return HasProximity(finder) - return 0 - -/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj) - if(CanHug(AM)) - return Attach(AM) - return 0 - -/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed) - ..() - if(stat == CONSCIOUS) - icon_state = "[initial(icon_state)]_thrown" - spawn(15) - if(icon_state == "[initial(icon_state)]_thrown") - icon_state = "[initial(icon_state)]" - -/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom) - ..() - if(stat == CONSCIOUS) - icon_state = "[initial(icon_state)]" - Attach(hit_atom) - -/obj/item/clothing/mask/facehugger/proc/Attach(M as mob) - if( (!iscorgi(M) && !iscarbon(M)) || isalien(M)) - return 0 - if(attached) - return 0 - else - attached++ - spawn(MAX_IMPREGNATION_TIME) - attached = 0 - - var/mob/living/L = M //just so I don't need to use : - - if(loc == L) - return 0 - if(stat != CONSCIOUS) - return 0 - if(!sterile) - L.take_organ_damage(strength, 0) //done here so that even borgs and humans in helmets take damage - - L.visible_message("\The [src] leaps at [L]'s face !") - - if(ishuman(L)) - var/mob/living/carbon/human/H = L - var/obj/item/mouth_protection = H.get_body_part_coverage(MOUTH) - if(mouth_protection && mouth_protection != H.wear_mask) //can't be protected with your own mask, has to be a hat - H.visible_message("\The [src] smashes against [H]'s [mouth_protection] !") - stat_collection.xeno.proper_head_protection++ - Die() - return 0 - - if(iscarbon(M)) - var/mob/living/carbon/target = L - - if(target.wear_mask) - if(prob(20)) - return 0 - var/obj/item/clothing/W = target.wear_mask - if(!W.canremove) - return 0 - target.drop_from_inventory(W) - - target.visible_message("\The [src] tears \the [W] off of [target]'s face !") - - target.equip_to_slot(src, slot_wear_mask) - - if(!sterile) L.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings - else if(iscorgi(M)) - var/mob/living/simple_animal/corgi/C = M - src.loc = C - C.facehugger = src - C.wear_mask = src - //C.regenerate_icons() - - GoIdle() //so it doesn't jump the people that tear it off - - spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME)) - Impregnate(L) - - return 0 - -/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target as mob) - if(!target || target.wear_mask != src || target.stat == DEAD) //was taken off or something - return - - if(!sterile) - new /obj/item/alien_embryo(target) - target.status_flags |= XENO_HOST - - target.visible_message("\The [src] falls limp after violating [target]'s face !") - stat_collection.xeno.faces_hugged++ - - Die() - icon_state = "[initial(icon_state)]_impregnated" - - if(iscorgi(target)) - var/mob/living/simple_animal/corgi/C = target - src.loc = get_turf(C) - C.facehugger = null - else - target.visible_message("\The [src] violates [target]'s face !") - return - -/obj/item/clothing/mask/facehugger/proc/GoActive() - if(stat == DEAD || stat == CONSCIOUS) - return - - stat = CONSCIOUS - icon_state = "[initial(icon_state)]" - return - -/obj/item/clothing/mask/facehugger/proc/GoIdle() - if(stat == DEAD || stat == UNCONSCIOUS) - return - -/* RemoveActiveIndicators() */ - - stat = UNCONSCIOUS - icon_state = "[initial(icon_state)]_inactive" - - spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME)) - GoActive() - return - -/obj/item/clothing/mask/facehugger/proc/Die() - if(stat == DEAD) - return - -/* RemoveActiveIndicators() */ - - icon_state = "[initial(icon_state)]_dead" - stat = DEAD - - src.visible_message("\The [src] curls up into a ball !") - - return - -/proc/CanHug(var/mob/M) - - - if(iscorgi(M)) - return 1 - - if(!iscarbon(M) || isalien(M) || isslime(M)) - return 0 - - var/mob/living/carbon/C = M - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(H.check_body_part_coverage(MOUTH) || (locate(/obj/item/alien_embryo) in H)) - return 0 - return 1 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +//TODO: Make these simple_animals + +var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone +var/const/MAX_IMPREGNATION_TIME = 150 + +var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle +var/const/MAX_ACTIVE_TIME = 400 + +/obj/item/clothing/mask/facehugger + name = "facehugger" //Let's call this 'alien' what it is. Come on Bay + desc = "It has some sort of a tube at the end of its tail." + icon = 'icons/mob/alien.dmi' + icon_state = "facehugger" + item_state = "facehugger" + w_class = 1 //note: can be picked up by aliens unlike most other items of w_class below 4 + flags = FPRINT | MASKINTERNALS | PROXMOVE + body_parts_covered = HEAD|MOUTH|EYES + throw_range = 5 + var/real = 1 //Facehuggers are real, toys are not. + + var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case + + var/sterile = 0 + + var/strength = 5 + + var/attached = 0 + +/obj/item/clothing/mask/facehugger/can_contaminate() + return 0 + +/obj/item/clothing/mask/facehugger/attack_paw(user as mob) //can be picked up by aliens + if(isalien(user)) + attack_hand(user) + return + else + ..() + return + +/obj/item/clothing/mask/facehugger/attack_hand(user as mob) + if((stat == CONSCIOUS && !sterile) && !isalien(user)) + Attach(user) + return + else + ..() + return + +/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob) + ..() + user.drop_from_inventory(src) + Attach(M) + +/obj/item/clothing/mask/facehugger/New() + if(aliens_allowed) + ..() + else + qdel(src) + +/obj/item/clothing/mask/facehugger/examine(mob/user) + ..() + if(!real) //Toy facehuggers are a child, avoid confusing examine text. + return + switch(stat) + if(DEAD,UNCONSCIOUS) + to_chat(user, "\The [src] is not moving.") + if(CONSCIOUS) + to_chat(user, "\The [src] seems active.") + if (sterile) + to_chat(user, "It looks like \the [src]'s proboscis has been removed.") + +/obj/item/clothing/mask/facehugger/attackby() + Die() + return + +/obj/item/clothing/mask/facehugger/bullet_act() + Die() + return + +/obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + Die() + return + +/obj/item/clothing/mask/facehugger/equipped(mob/M) + Attach(M) + +/obj/item/clothing/mask/facehugger/Crossed(atom/target) + HasProximity(target) + return + +/obj/item/clothing/mask/facehugger/on_found(mob/finder as mob) + if(stat == CONSCIOUS) + return HasProximity(finder) + return 0 + +/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj) + if(CanHug(AM)) + return Attach(AM) + return 0 + +/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed) + ..() + if(stat == CONSCIOUS) + icon_state = "[initial(icon_state)]_thrown" + spawn(15) + if(icon_state == "[initial(icon_state)]_thrown") + icon_state = "[initial(icon_state)]" + +/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom) + ..() + if(stat == CONSCIOUS) + icon_state = "[initial(icon_state)]" + Attach(hit_atom) + +/obj/item/clothing/mask/facehugger/proc/Attach(M as mob) + if( (!iscorgi(M) && !iscarbon(M)) || isalien(M)) + return 0 + if(attached) + return 0 + else + attached++ + spawn(MAX_IMPREGNATION_TIME) + attached = 0 + + var/mob/living/L = M //just so I don't need to use : + + if(loc == L) + return 0 + if(stat != CONSCIOUS) + return 0 + if(!sterile) + L.take_organ_damage(strength, 0) //done here so that even borgs and humans in helmets take damage + + L.visible_message("\The [src] leaps at [L]'s face !") + + if(ishuman(L)) + var/mob/living/carbon/human/H = L + var/obj/item/mouth_protection = H.get_body_part_coverage(MOUTH) + if(mouth_protection && mouth_protection != H.wear_mask) //can't be protected with your own mask, has to be a hat + H.visible_message("\The [src] smashes against [H]'s [mouth_protection] !") + stat_collection.xeno.proper_head_protection++ + Die() + return 0 + + if(iscarbon(M)) + var/mob/living/carbon/target = L + + if(target.wear_mask) + if(prob(20)) + return 0 + var/obj/item/clothing/W = target.wear_mask + if(!W.canremove) + return 0 + target.drop_from_inventory(W) + + target.visible_message("\The [src] tears \the [W] off of [target]'s face !") + + target.equip_to_slot(src, slot_wear_mask) + + if(!sterile) L.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings + else if(iscorgi(M)) + var/mob/living/simple_animal/corgi/C = M + src.loc = C + C.facehugger = src + C.wear_mask = src + //C.regenerate_icons() + + GoIdle() //so it doesn't jump the people that tear it off + + spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME)) + Impregnate(L) + + return 0 + +/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target as mob) + if(!target || target.wear_mask != src || target.stat == DEAD) //was taken off or something + return + + if(!sterile) + new /obj/item/alien_embryo(target) + target.status_flags |= XENO_HOST + + target.visible_message("\The [src] falls limp after violating [target]'s face !") + stat_collection.xeno.faces_hugged++ + + Die() + icon_state = "[initial(icon_state)]_impregnated" + + if(iscorgi(target)) + var/mob/living/simple_animal/corgi/C = target + src.loc = get_turf(C) + C.facehugger = null + else + target.visible_message("\The [src] violates [target]'s face !") + return + +/obj/item/clothing/mask/facehugger/proc/GoActive() + if(stat == DEAD || stat == CONSCIOUS) + return + + stat = CONSCIOUS + icon_state = "[initial(icon_state)]" + return + +/obj/item/clothing/mask/facehugger/proc/GoIdle() + if(stat == DEAD || stat == UNCONSCIOUS) + return + +/* RemoveActiveIndicators() */ + + stat = UNCONSCIOUS + icon_state = "[initial(icon_state)]_inactive" + + spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME)) + GoActive() + return + +/obj/item/clothing/mask/facehugger/proc/Die() + if(stat == DEAD) + return + +/* RemoveActiveIndicators() */ + + icon_state = "[initial(icon_state)]_dead" + stat = DEAD + + src.visible_message("\The [src] curls up into a ball !") + + return + +/proc/CanHug(var/mob/M) + + + if(iscorgi(M)) + return 1 + + if(!iscarbon(M) || isalien(M) || isslime(M)) + return 0 + + var/mob/living/carbon/C = M + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(H.check_body_part_coverage(MOUTH) || (locate(/obj/item/alien_embryo) in H)) + return 0 + return 1 diff --git a/code/modules/mob/living/carbon/alien/special/snakeman.dm b/code/modules/mob/living/carbon/alien/special/snakeman.dm index 4a2516e32ec..9dfc2806033 100644 --- a/code/modules/mob/living/carbon/alien/special/snakeman.dm +++ b/code/modules/mob/living/carbon/alien/special/snakeman.dm @@ -1,59 +1,59 @@ -/mob/living/carbon/alien/humanoid/special/snakeman - name = "Snakeman" - desc = "This race developed in an extremely hostile environment. They are extremely tough and can resist extreme temperature variations. Their mobility depends on a snake-like giant \"foot\" which protects all the vital organs. " - xcom_state = "snake" - - movement_delay() - return 4 - -/mob/living/carbon/alien/humanoid/special/snakeman/verb/lay_egg(mob/living/carbon/human/M as mob) - set name = "Impregnate" - set desc = "Lays an egg on a corpse, allowing the egg to feed." - set category = "Snakeman" - - set src = view(0) - - if(stat) - return - - if(!M) - return - - if(!M.client) +/mob/living/carbon/alien/humanoid/special/snakeman + name = "Snakeman" + desc = "This race developed in an extremely hostile environment. They are extremely tough and can resist extreme temperature variations. Their mobility depends on a snake-like giant \"foot\" which protects all the vital organs. " + xcom_state = "snake" + + movement_delay() + return 4 + +/mob/living/carbon/alien/humanoid/special/snakeman/verb/lay_egg(mob/living/carbon/human/M as mob) + set name = "Impregnate" + set desc = "Lays an egg on a corpse, allowing the egg to feed." + set category = "Snakeman" + + set src = view(0) + + if(stat) + return + + if(!M) + return + + if(!M.client) to_chat(src, "This being is missing a brain.") - return - - visible_message("[src] extends a probiscis and stabs it into [M]") - - if (!do_mob(usr, M, 50)) + return + + visible_message("[src] extends a probiscis and stabs it into [M]") + + if (!do_mob(usr, M, 50)) to_chat(usr, "The injection of the egg has been interrupted!") - return - - if(M.client) - M.client.mob = new/mob/living/carbon/alien/humanoid/special/snakeman(new/obj/effect/snake_egg(src.loc)) - visible_message("[src] injects [M] with an egg.") - visible_message("The egg absorbs [M]") - M.mutations |= M_NOCLONE - M.update_body() - M.death() - else + return + + if(M.client) + M.client.mob = new/mob/living/carbon/alien/humanoid/special/snakeman(new/obj/effect/snake_egg(src.loc)) + visible_message("[src] injects [M] with an egg.") + visible_message("The egg absorbs [M]") + M.mutations |= M_NOCLONE + M.update_body() + M.death() + else to_chat(src, "This being is missing a brain.") - - return - -/obj/effect/snake_egg - name = "Egg" - icon = 'icons/mob/alien.dmi' - icon_state = "egg" - density = 1 - anchored = 1 - - New() - ..() - - spawn(300) - for(var/mob/M in src) - M.loc = src.loc - icon_state = "egg_hatched" - density = 0 + + return + +/obj/effect/snake_egg + name = "Egg" + icon = 'icons/mob/alien.dmi' + icon_state = "egg" + density = 1 + anchored = 1 + + New() + ..() + + spawn(300) + for(var/mob/M in src) + M.loc = src.loc + icon_state = "egg_hatched" + density = 0 return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 9d5bae08b67..02448ab7530 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -1,278 +1,278 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/device/mmi - name = "Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity." - icon = 'icons/obj/assemblies.dmi' - icon_state = "mmi_empty" - w_class = 3 - origin_tech = "biotech=3" - - var/list/mommi_assembly_parts = list( - /obj/item/weapon/cell = 1, - /obj/item/robot_parts/l_leg = 2, - /obj/item/robot_parts/r_leg = 2, - /obj/item/robot_parts/r_arm = 1, - /obj/item/robot_parts/l_arm = 1 - ) - - req_access = list(access_robotics) - - //Revised. Brainmob is now contained directly within object of transfer. MMI in this case. - - var/locked = 0 - var/mob/living/carbon/brain/brainmob = null//The current occupant. - var/mob/living/silicon/robot = null//Appears unused. - var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm. - -obj/item/device/mmi/Destroy() - if(brainmob) - brainmob.ghostize() - ..() - - // Return true if handled -/obj/item/device/mmi/proc/try_handling_mommi_construction(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O,/obj/item/weapon/screwdriver)) - for(var/t in mommi_assembly_parts) - var/cc=contents_count(t) - var/req=mommi_assembly_parts[t] - if(ccYou're short [req-cc] [temppart]\s.
    ") - qdel(temppart) - temppart = null - return TRUE - if(!istype(loc,/turf)) - to_chat(user, "You can't assemble the MoMMI, \the [src] has to be standing on the ground (or a table) to be perfectly precise.") - return TRUE - if(!brainmob) - to_chat(user, "What are you doing oh god put the brain back in.") - return TRUE - if(!brainmob.key) - if(!mind_can_reenter(brainmob.mind)) - to_chat(user, "\The [src] indicates that their mind is completely unresponsive; there's no point.") - return TRUE - if(brainmob.stat == DEAD) - to_chat(user, "Yeah, good idea. Give something deader than the pizza in your fridge legs. Mom would be so proud.") - return TRUE - if(brainmob.mind in ticker.mode.head_revolutionaries) - to_chat(user, "The [src]'s firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the brain.") - return TRUE - if(jobban_isbanned(brainmob, "Mobile MMI")) - to_chat(user, "This brain does not seem to fit.") - return TRUE - //canmove = 0 - icon = null - invisibility = 101 - var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi(get_turf(loc)) - if(!M) return - M.invisibility = 0 - //M.custom_name = created_name - M.Namepick() - M.updatename() - brainmob.mind.transfer_to(M) - - if(M.mind && M.mind.special_role) - M.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") - - M.job = "MoMMI" - - M.cell = locate(/obj/item/weapon/cell) in contents - M.cell.loc = M - src.loc = M//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame. - M.mmi = src - return TRUE - for(var/t in mommi_assembly_parts) - if(istype(O,t)) - var/cc=contents_count(t) - if(ccWhy are you sticking robot legs on an empty [src], you idiot?
    ") - return TRUE - if(!user.drop_item(O, src)) - to_chat(user, "You can't let go of \the [src]!") - return FALSE - - contents += O - to_chat(user, "You successfully add \the [O] to the contraption,") - return TRUE - else if(cc==mommi_assembly_parts[t]) - to_chat(user, "You have enough of these.") - return TRUE - return FALSE - -/obj/item/device/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(try_handling_mommi_construction(O,user)) - return - if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO - // MaMIs inherit from brain, but they shouldn't be insertable into a MMI - if (istype(O, /obj/item/organ/brain/mami)) - to_chat(user, "You are only able to fit organic brains on a MMI. [src] won't work.") - return - - var/obj/item/organ/brain/BO = O - if(!BO.brainmob) - to_chat(user, "You aren't sure where this brain came from, but you're pretty sure it's a useless brain.") - return - // Checking to see if the ghost has been moused/borer'd/etc since death. - var/mob/living/carbon/brain/BM = BO.brainmob - if(!BM.client) - to_chat(user, "\The [src] indicates that their mind is completely unresponsive; there's no point.") - return - if(!user.drop_item(O)) - to_chat(user, "You can't let go of \the [O]!") - return - - src.visible_message("[user] sticks \a [O] into \the [src].") - - brainmob = BO.brainmob - BO.brainmob = null - brainmob.loc = src - brainmob.container = src - brainmob.stat = 0 - brainmob.resurrect() - - qdel(O) - O = null - - name = "[initial(name)]: [brainmob.real_name]" - icon_state = "mmi_full" - - locked = 1 - - feedback_inc("cyborg_mmis_filled",1) - - return - - if((istype(O,/obj/item/weapon/card/id)||istype(O,/obj/item/device/pda)) && brainmob) - if(allowed(user)) - locked = !locked - to_chat(user, "You [locked ? "lock" : "unlock"] \the [src].") - else - to_chat(user, "Access denied.") - return - - if(istype(O, /obj/item/weapon/implanter)) - return//toplel - - if(brainmob) - O.attack(brainmob, user)//Oh noooeeeee - return - ..() - - //TODO: ORGAN REMOVAL UPDATE. Make the brain remain in the MMI so it doesn't lose organ data. -/obj/item/device/mmi/attack_self(mob/user as mob) - if(!brainmob) - to_chat(user, "You upend \the [src], but there's nothing in it.") - else if(locked) - to_chat(user, "You upend \the [src], but the brain is clamped into place.") - else - to_chat(user, "You upend \the [src], spilling the brain onto the floor.") - var/obj/item/organ/brain/brain = new(user.loc) - brainmob.container = null//Reset brainmob mmi var. - brainmob.loc = brain//Throw mob into brain. - living_mob_list -= brainmob//Get outta here - brain.brainmob = brainmob//Set the brain to use the brainmob - brainmob = null//Set mmi brainmob var to null - - icon_state = "mmi_empty" - name = initial(name) - -/obj/item/device/mmi/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people. - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - if(istype(H) && H.dna) - brainmob.dna = H.dna.Clone() - brainmob.container = src - - name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" - locked = 1 - return - -/obj/item/device/mmi/radio_enabled - name = "Radio-enabled Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity. This one comes with a built-in radio." - origin_tech = "biotech=4" - - var/obj/item/device/radio/radio = null//Let's give it a radio. - -/obj/item/device/mmi/radio_enabled/New() - ..() - radio = new(src)//Spawns a radio inside the MMI. - radio.broadcasting = 0//So it's broadcasting from the start. - -/obj/item/device/mmi/radio_enabled/Destroy() - ..() - qdel(radio) - radio = null - -/obj/item/device/mmi/radio_enabled/verb/Toggle_Broadcasting() - set name = "Toggle Broadcasting" - set desc = "Toggle broadcasting channel on or off." - set category = "MMI" - set src = usr.loc//In user location, or in MMI in this case. - set popup_menu = 0//Will not appear when right clicking. - - if(brainmob.stat)//Only the brainmob will trigger these so no further check is necessary. - to_chat(brainmob, "Can't do that while incapacitated or dead.") - - radio.broadcasting = radio.broadcasting==1 ? 0 : 1 - to_chat(brainmob, "<Radio is [radio.broadcasting==1 ? "now" : "no longer"] broadcasting.") - -/obj/item/device/mmi/radio_enabled/verb/Toggle_Listening() - set name = "Toggle Listening" - set desc = "Toggle listening channel on or off." - set category = "MMI" - set src = usr.loc - set popup_menu = 0 - - if(brainmob.stat) - to_chat(brainmob, "Can't do that while incapacitated or dead.") - - radio.listening = radio.listening==1 ? 0 : 1 - to_chat(brainmob, "Radio is [radio] receiving broadcast.") - -/obj/item/device/mmi/emp_act(severity) - if(!brainmob) - return - else - switch(severity) - if(1) - brainmob.emp_damage += rand(20,30) - if(2) - brainmob.emp_damage += rand(10,20) - if(3) - brainmob.emp_damage += rand(0,10) - ..() - -/obj/item/device/mmi/proc/contents_count(var/type) - var/c=0 - for(var/O in contents) - if(istype(O,type)) - c++ - return c - - - -/obj/item/device/mmi/examine(mob/user) - to_chat(user, "*---------*") - ..() - if(locked!=2) - if(src.brainmob) - if(src.brainmob.stat == DEAD) - to_chat(user, "It appears the brain has suffered irreversible tissue degeneration")//suicided - - else if(!src.brainmob.client) - to_chat(user, "It appears to be lost in its own thoughts")//closed game window - - else if(!src.brainmob.key) - to_chat(user, "It seems to be in a deep dream-state")//ghosted - - to_chat(user, "It's interface is [locked ? "locked" : "unlocked"] ") - to_chat(user, "*---------*") - -/obj/item/device/mmi/OnMobDeath(var/mob/living/carbon/brain/B) - icon_state = "mmi_dead" - visible_message(message = "[B]'s MMI flatlines!", blind_message = "You hear something flatline.") +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/device/mmi + name = "Man-Machine Interface" + desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity." + icon = 'icons/obj/assemblies.dmi' + icon_state = "mmi_empty" + w_class = 3 + origin_tech = "biotech=3" + + var/list/mommi_assembly_parts = list( + /obj/item/weapon/cell = 1, + /obj/item/robot_parts/l_leg = 2, + /obj/item/robot_parts/r_leg = 2, + /obj/item/robot_parts/r_arm = 1, + /obj/item/robot_parts/l_arm = 1 + ) + + req_access = list(access_robotics) + + //Revised. Brainmob is now contained directly within object of transfer. MMI in this case. + + var/locked = 0 + var/mob/living/carbon/brain/brainmob = null//The current occupant. + var/mob/living/silicon/robot = null//Appears unused. + var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm. + +obj/item/device/mmi/Destroy() + if(brainmob) + brainmob.ghostize() + ..() + + // Return true if handled +/obj/item/device/mmi/proc/try_handling_mommi_construction(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O,/obj/item/weapon/screwdriver)) + for(var/t in mommi_assembly_parts) + var/cc=contents_count(t) + var/req=mommi_assembly_parts[t] + if(ccYou're short [req-cc] [temppart]\s.") + qdel(temppart) + temppart = null + return TRUE + if(!istype(loc,/turf)) + to_chat(user, "You can't assemble the MoMMI, \the [src] has to be standing on the ground (or a table) to be perfectly precise.") + return TRUE + if(!brainmob) + to_chat(user, "What are you doing oh god put the brain back in.") + return TRUE + if(!brainmob.key) + if(!mind_can_reenter(brainmob.mind)) + to_chat(user, "\The [src] indicates that their mind is completely unresponsive; there's no point.") + return TRUE + if(brainmob.stat == DEAD) + to_chat(user, "Yeah, good idea. Give something deader than the pizza in your fridge legs. Mom would be so proud.") + return TRUE + if(brainmob.mind in ticker.mode.head_revolutionaries) + to_chat(user, "The [src]'s firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the brain.") + return TRUE + if(jobban_isbanned(brainmob, "Mobile MMI")) + to_chat(user, "This brain does not seem to fit.") + return TRUE + //canmove = 0 + icon = null + invisibility = 101 + var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi(get_turf(loc)) + if(!M) return + M.invisibility = 0 + //M.custom_name = created_name + M.Namepick() + M.updatename() + brainmob.mind.transfer_to(M) + + if(M.mind && M.mind.special_role) + M.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") + + M.job = "MoMMI" + + M.cell = locate(/obj/item/weapon/cell) in contents + M.cell.loc = M + src.loc = M//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame. + M.mmi = src + return TRUE + for(var/t in mommi_assembly_parts) + if(istype(O,t)) + var/cc=contents_count(t) + if(ccWhy are you sticking robot legs on an empty [src], you idiot?") + return TRUE + if(!user.drop_item(O, src)) + to_chat(user, "You can't let go of \the [src]!") + return FALSE + + contents += O + to_chat(user, "You successfully add \the [O] to the contraption,") + return TRUE + else if(cc==mommi_assembly_parts[t]) + to_chat(user, "You have enough of these.") + return TRUE + return FALSE + +/obj/item/device/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(try_handling_mommi_construction(O,user)) + return + if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO + // MaMIs inherit from brain, but they shouldn't be insertable into a MMI + if (istype(O, /obj/item/organ/brain/mami)) + to_chat(user, "You are only able to fit organic brains on a MMI. [src] won't work.") + return + + var/obj/item/organ/brain/BO = O + if(!BO.brainmob) + to_chat(user, "You aren't sure where this brain came from, but you're pretty sure it's a useless brain.") + return + // Checking to see if the ghost has been moused/borer'd/etc since death. + var/mob/living/carbon/brain/BM = BO.brainmob + if(!BM.client) + to_chat(user, "\The [src] indicates that their mind is completely unresponsive; there's no point.") + return + if(!user.drop_item(O)) + to_chat(user, "You can't let go of \the [O]!") + return + + src.visible_message("[user] sticks \a [O] into \the [src].") + + brainmob = BO.brainmob + BO.brainmob = null + brainmob.loc = src + brainmob.container = src + brainmob.stat = 0 + brainmob.resurrect() + + qdel(O) + O = null + + name = "[initial(name)]: [brainmob.real_name]" + icon_state = "mmi_full" + + locked = 1 + + feedback_inc("cyborg_mmis_filled",1) + + return + + if((istype(O,/obj/item/weapon/card/id)||istype(O,/obj/item/device/pda)) && brainmob) + if(allowed(user)) + locked = !locked + to_chat(user, "You [locked ? "lock" : "unlock"] \the [src].") + else + to_chat(user, "Access denied.") + return + + if(istype(O, /obj/item/weapon/implanter)) + return//toplel + + if(brainmob) + O.attack(brainmob, user)//Oh noooeeeee + return + ..() + + //TODO: ORGAN REMOVAL UPDATE. Make the brain remain in the MMI so it doesn't lose organ data. +/obj/item/device/mmi/attack_self(mob/user as mob) + if(!brainmob) + to_chat(user, "You upend \the [src], but there's nothing in it.") + else if(locked) + to_chat(user, "You upend \the [src], but the brain is clamped into place.") + else + to_chat(user, "You upend \the [src], spilling the brain onto the floor.") + var/obj/item/organ/brain/brain = new(user.loc) + brainmob.container = null//Reset brainmob mmi var. + brainmob.loc = brain//Throw mob into brain. + living_mob_list -= brainmob//Get outta here + brain.brainmob = brainmob//Set the brain to use the brainmob + brainmob = null//Set mmi brainmob var to null + + icon_state = "mmi_empty" + name = initial(name) + +/obj/item/device/mmi/proc/transfer_identity(var/mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people. + brainmob = new(src) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + if(istype(H) && H.dna) + brainmob.dna = H.dna.Clone() + brainmob.container = src + + name = "Man-Machine Interface: [brainmob.real_name]" + icon_state = "mmi_full" + locked = 1 + return + +/obj/item/device/mmi/radio_enabled + name = "Radio-enabled Man-Machine Interface" + desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity. This one comes with a built-in radio." + origin_tech = "biotech=4" + + var/obj/item/device/radio/radio = null//Let's give it a radio. + +/obj/item/device/mmi/radio_enabled/New() + ..() + radio = new(src)//Spawns a radio inside the MMI. + radio.broadcasting = 0//So it's broadcasting from the start. + +/obj/item/device/mmi/radio_enabled/Destroy() + ..() + qdel(radio) + radio = null + +/obj/item/device/mmi/radio_enabled/verb/Toggle_Broadcasting() + set name = "Toggle Broadcasting" + set desc = "Toggle broadcasting channel on or off." + set category = "MMI" + set src = usr.loc//In user location, or in MMI in this case. + set popup_menu = 0//Will not appear when right clicking. + + if(brainmob.stat)//Only the brainmob will trigger these so no further check is necessary. + to_chat(brainmob, "Can't do that while incapacitated or dead.") + + radio.broadcasting = radio.broadcasting==1 ? 0 : 1 + to_chat(brainmob, "<Radio is [radio.broadcasting==1 ? "now" : "no longer"] broadcasting.") + +/obj/item/device/mmi/radio_enabled/verb/Toggle_Listening() + set name = "Toggle Listening" + set desc = "Toggle listening channel on or off." + set category = "MMI" + set src = usr.loc + set popup_menu = 0 + + if(brainmob.stat) + to_chat(brainmob, "Can't do that while incapacitated or dead.") + + radio.listening = radio.listening==1 ? 0 : 1 + to_chat(brainmob, "Radio is [radio] receiving broadcast.") + +/obj/item/device/mmi/emp_act(severity) + if(!brainmob) + return + else + switch(severity) + if(1) + brainmob.emp_damage += rand(20,30) + if(2) + brainmob.emp_damage += rand(10,20) + if(3) + brainmob.emp_damage += rand(0,10) + ..() + +/obj/item/device/mmi/proc/contents_count(var/type) + var/c=0 + for(var/O in contents) + if(istype(O,type)) + c++ + return c + + + +/obj/item/device/mmi/examine(mob/user) + to_chat(user, "*---------*") + ..() + if(locked!=2) + if(src.brainmob) + if(src.brainmob.stat == DEAD) + to_chat(user, "It appears the brain has suffered irreversible tissue degeneration")//suicided + + else if(!src.brainmob.client) + to_chat(user, "It appears to be lost in its own thoughts")//closed game window + + else if(!src.brainmob.key) + to_chat(user, "It seems to be in a deep dream-state")//ghosted + + to_chat(user, "It's interface is [locked ? "locked" : "unlocked"] ") + to_chat(user, "*---------*") + +/obj/item/device/mmi/OnMobDeath(var/mob/living/carbon/brain/B) + icon_state = "mmi_dead" + visible_message(message = "[B]'s MMI flatlines!", blind_message = "You hear something flatline.") diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index f7b2d33c3cb..10e99ff45a8 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -1,65 +1,65 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/mob/living/carbon/brain - var/obj/item/container = null - var/timeofhostdeath = 0 - var/emp_damage = 0//Handles a type of MMI damage - var/alert = null - can_butcher = 0 - immune_to_ssd = 1 - use_me = 0 //Can't use the me verb, it's a freaking immobile brain - hasmouth=0 // Can't feed it. - icon = 'icons/obj/surgery.dmi' - icon_state = "brain1" - universal_speak = 1 - universal_understand = 1 - -/mob/living/carbon/brain/New() - var/datum/reagents/R = new/datum/reagents(1000) - reagents = R - R.my_atom = src - ..() - -/mob/living/carbon/brain/Destroy() - if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting. - if(stat!=DEAD) //If not dead. - death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA - ..() - -/mob/living/carbon/brain/update_canmove() - if(in_contents_of(/obj/mecha)) - canmove = 1 - use_me = 1 //If it can move, let it emote - else canmove = 0 - return canmove - -/mob/living/carbon/brain/say_understands(var/atom/movable/other)//Goddamn is this hackish, but this say code is so odd - if(other) other = other.GetSource() - if (istype(other, /mob/living/silicon/ai)) - if(!(container && istype(container, /obj/item/device/mmi))) - return 0 - else - return 1 - if (istype(other, /mob/living/silicon/decoy)) - if(!(container && istype(container, /obj/item/device/mmi))) - return 0 - else - return 1 - if (istype(other, /mob/living/silicon/pai)) - if(!(container && istype(container, /obj/item/device/mmi))) - return 0 - else - return 1 - if (istype(other, /mob/living/silicon/robot)) - if(!(container && istype(container, /obj/item/device/mmi))) - return 0 - else - return 1 - if (istype(other, /mob/living/carbon/human)) - return 1 - if (istype(other, /mob/living/carbon/slime)) - return 1 - return ..() - -/mob/living/carbon/brain/teleport_to(var/atom/A) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/mob/living/carbon/brain + var/obj/item/container = null + var/timeofhostdeath = 0 + var/emp_damage = 0//Handles a type of MMI damage + var/alert = null + can_butcher = 0 + immune_to_ssd = 1 + use_me = 0 //Can't use the me verb, it's a freaking immobile brain + hasmouth=0 // Can't feed it. + icon = 'icons/obj/surgery.dmi' + icon_state = "brain1" + universal_speak = 1 + universal_understand = 1 + +/mob/living/carbon/brain/New() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + ..() + +/mob/living/carbon/brain/Destroy() + if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting. + if(stat!=DEAD) //If not dead. + death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA + ..() + +/mob/living/carbon/brain/update_canmove() + if(in_contents_of(/obj/mecha)) + canmove = 1 + use_me = 1 //If it can move, let it emote + else canmove = 0 + return canmove + +/mob/living/carbon/brain/say_understands(var/atom/movable/other)//Goddamn is this hackish, but this say code is so odd + if(other) other = other.GetSource() + if (istype(other, /mob/living/silicon/ai)) + if(!(container && istype(container, /obj/item/device/mmi))) + return 0 + else + return 1 + if (istype(other, /mob/living/silicon/decoy)) + if(!(container && istype(container, /obj/item/device/mmi))) + return 0 + else + return 1 + if (istype(other, /mob/living/silicon/pai)) + if(!(container && istype(container, /obj/item/device/mmi))) + return 0 + else + return 1 + if (istype(other, /mob/living/silicon/robot)) + if(!(container && istype(container, /obj/item/device/mmi))) + return 0 + else + return 1 + if (istype(other, /mob/living/carbon/human)) + return 1 + if (istype(other, /mob/living/carbon/slime)) + return 1 + return ..() + +/mob/living/carbon/brain/teleport_to(var/atom/A) container.forceMove(get_turf(A)) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index b4c07bcee7e..04834fb0118 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -1,72 +1,72 @@ -/obj/item/organ/brain - name = "brain" - health = 400 //They need to live awhile longer than other organs. - desc = "A piece of juicy meat found in a person's head." - icon_state = "brain2" - flags = 0 - force = 1.0 - w_class = 1.0 - throwforce = 1.0 - throw_speed = 3 - throw_range = 5 - origin_tech = "biotech=3" - attack_verb = list("attacked", "slapped", "whacked") - prosthetic_name = "cyberbrain" - prosthetic_icon = "brain-prosthetic" - organ_tag = "brain" - organ_type = /datum/organ/internal/brain - //nonplant_seed_type = /obj/item/seeds/synthbrainseed - - var/mob/living/carbon/brain/brainmob = null - -/obj/item/organ/brain/New() - ..() - spawn(5) - if(brainmob && brainmob.client) - brainmob.client.screen.len = null //clear the hud - -/obj/item/organ/brain/proc/transfer_identity(var/mob/living/carbon/H) - name = "[H]'s brain" - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.dna = H.dna.Clone() - brainmob.timeofhostdeath = H.timeofdeath - if(H.mind) - H.mind.transfer_to(brainmob) - - to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a brain.") - callHook("debrain", list(brainmob)) - -/obj/item/organ/brain/examine(mob/user) - ..() - if(brainmob && brainmob.client)//if thar be a brain inside... the brain. - if(mind_can_reenter(brainmob.mind))// This checks if the ghost can re-enter (ghost.can_reenter_corpse) - to_chat(user, "This one seems unresponsive.")// Should probably make this more realistic, - - // but this message ties it in with MMI errors. - else - to_chat(user, "You can feel the small spark of life still left in this one.") - else - to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later..") - -/obj/item/organ/brain/removed(var/mob/living/target,var/mob/living/user) - - ..() - - var/mob/living/carbon/human/H = target - H.dropBorers() - var/obj/item/organ/brain/B = src - if(istype(B) && istype(H)) - B.transfer_identity(target) - -/obj/item/organ/brain/replaced(var/mob/living/target) - - if(target.key) - target.ghostize() - - if(brainmob) - if(brainmob.mind) - brainmob.mind.transfer_to(target) - else +/obj/item/organ/brain + name = "brain" + health = 400 //They need to live awhile longer than other organs. + desc = "A piece of juicy meat found in a person's head." + icon_state = "brain2" + flags = 0 + force = 1.0 + w_class = 1.0 + throwforce = 1.0 + throw_speed = 3 + throw_range = 5 + origin_tech = "biotech=3" + attack_verb = list("attacked", "slapped", "whacked") + prosthetic_name = "cyberbrain" + prosthetic_icon = "brain-prosthetic" + organ_tag = "brain" + organ_type = /datum/organ/internal/brain + //nonplant_seed_type = /obj/item/seeds/synthbrainseed + + var/mob/living/carbon/brain/brainmob = null + +/obj/item/organ/brain/New() + ..() + spawn(5) + if(brainmob && brainmob.client) + brainmob.client.screen.len = null //clear the hud + +/obj/item/organ/brain/proc/transfer_identity(var/mob/living/carbon/H) + name = "[H]'s brain" + brainmob = new(src) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.dna = H.dna.Clone() + brainmob.timeofhostdeath = H.timeofdeath + if(H.mind) + H.mind.transfer_to(brainmob) + + to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a brain.") + callHook("debrain", list(brainmob)) + +/obj/item/organ/brain/examine(mob/user) + ..() + if(brainmob && brainmob.client)//if thar be a brain inside... the brain. + if(mind_can_reenter(brainmob.mind))// This checks if the ghost can re-enter (ghost.can_reenter_corpse) + to_chat(user, "This one seems unresponsive.")// Should probably make this more realistic, + + // but this message ties it in with MMI errors. + else + to_chat(user, "You can feel the small spark of life still left in this one.") + else + to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later..") + +/obj/item/organ/brain/removed(var/mob/living/target,var/mob/living/user) + + ..() + + var/mob/living/carbon/human/H = target + H.dropBorers() + var/obj/item/organ/brain/B = src + if(istype(B) && istype(H)) + B.transfer_identity(target) + +/obj/item/organ/brain/replaced(var/mob/living/target) + + if(target.key) + target.ghostize() + + if(brainmob) + if(brainmob.mind) + brainmob.mind.transfer_to(target) + else target.key = brainmob.key \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm index 6fee3bb8a3b..acd33866a3a 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/carbon/brain/death.dm @@ -1,35 +1,35 @@ -/mob/living/carbon/brain/death(gibbed) - if(stat == DEAD) return - if(!gibbed && container && istype(container, /obj/item/device/mmi))//If not gibbed but in a container. - container.OnMobDeath(src) - - stat = DEAD - - if(blind) blind.layer = 0 - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) //mind. ? - - return ..(gibbed) - -/mob/living/carbon/brain/gib() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - if(container && istype(container, /obj/item/device/mmi)) - qdel(container)//Gets rid of the MMI if there is one - if(loc) - if(istype(loc,/obj/item/organ/brain)) - qdel(loc)//Gets rid of the brain item - - anim(target = src, a_icon = 'icons/mob/mob.dmi', /*flick_anim = "gibbed-m"*/, sleeptime = 15) - gibs(loc, viruses, dna) - - dead_mob_list -= src +/mob/living/carbon/brain/death(gibbed) + if(stat == DEAD) return + if(!gibbed && container && istype(container, /obj/item/device/mmi))//If not gibbed but in a container. + container.OnMobDeath(src) + + stat = DEAD + + if(blind) blind.layer = 0 + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + + tod = worldtime2text() //weasellos time of death patch + if(mind) mind.store_memory("Time of death: [tod]", 0) //mind. ? + + return ..(gibbed) + +/mob/living/carbon/brain/gib() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + if(container && istype(container, /obj/item/device/mmi)) + qdel(container)//Gets rid of the MMI if there is one + if(loc) + if(istype(loc,/obj/item/organ/brain)) + qdel(loc)//Gets rid of the brain item + + anim(target = src, a_icon = 'icons/mob/mob.dmi', /*flick_anim = "gibbed-m"*/, sleeptime = 15) + gibs(loc, viruses, dna) + + dead_mob_list -= src qdel(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index 1a689ee466e..d464e7d6f70 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/carbon/brain/emote.dm @@ -1,82 +1,82 @@ -/mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null) - if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes - return - - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - if(src.stat == DEAD) - return - switch(act) - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) +/mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null) + if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes + return + + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + + if(src.stat == DEAD) + return + switch(act) + if ("me") + if(silent) + return + if (src.client) + if (client.prefs.muted & MUTE_IC) to_chat(src, "You cannot send IC messages (muted).") - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - if ("custom") - return custom_emote(m_type, message) - if ("alarm") + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + if (stat) + return + if(!(message)) + return + return custom_emote(m_type, message) + + if ("custom") + return custom_emote(m_type, message) + if ("alarm") to_chat(src, "You sound an alarm.") - message = "[src] sounds an alarm." - m_type = HEARABLE - if ("alert") + message = "[src] sounds an alarm." + m_type = HEARABLE + if ("alert") to_chat(src, "You let out a distressed noise.") - message = "[src] lets out a distressed noise." - m_type = HEARABLE - if ("notice") + message = "[src] lets out a distressed noise." + m_type = HEARABLE + if ("notice") to_chat(src, "You play a loud tone.") - message = "[src] plays a loud tone." - m_type = HEARABLE - if ("flash") - message = "The lights on [src] flash quickly." - m_type = VISIBLE - if ("blink") - message = "[src] blinks." - m_type = VISIBLE - if ("whistle") + message = "[src] plays a loud tone." + m_type = HEARABLE + if ("flash") + message = "The lights on [src] flash quickly." + m_type = VISIBLE + if ("blink") + message = "[src] blinks." + m_type = VISIBLE + if ("whistle") to_chat(src, "You whistle.") - message = "[src] whistles." - m_type = HEARABLE - if ("beep") + message = "[src] whistles." + m_type = HEARABLE + if ("beep") to_chat(src, "You beep.") - message = "[src] beeps." - m_type = HEARABLE - if ("boop") + message = "[src] beeps." + m_type = HEARABLE + if ("boop") to_chat(src, "You boop.") - message = "[src] boops." - m_type = HEARABLE - if ("help") + message = "[src] boops." + m_type = HEARABLE + if ("help") to_chat(src, "alarm,alert,notice,flash,blink,whistle,beep,boop") - else + else to_chat(src, "Unusable emote '[act]'. Say *help for a list.") - - if (message) - log_emote("[name]/[key] (@[x],[y],[z]): [message]") - - for(var/mob/M in dead_mob_list) - if (!M.client || istype(M, /mob/new_player)) - continue //skip monkeys, leavers, and new_players - if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - - if (m_type & 1) - for (var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - else if (m_type & 2) - for (var/mob/O in hearers(src.loc, null)) + + if (message) + log_emote("[name]/[key] (@[x],[y],[z]): [message]") + + for(var/mob/M in dead_mob_list) + if (!M.client || istype(M, /mob/new_player)) + continue //skip monkeys, leavers, and new_players + if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) + M.show_message(message) + + + if (m_type & 1) + for (var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + else if (m_type & 2) + for (var/mob/O in hearers(src.loc, null)) O.show_message(message, m_type) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 0bbe4040bea..37ac0baca49 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -1,291 +1,291 @@ -/mob/living/carbon/brain/Life() - set invisibility = 0 - //set background = 1 - if(timestopped) return 0 //under effects of time magick - - ..() - - if(stat != DEAD) - //Mutations and radiation - handle_mutations_and_radiation() - - //Chemicals in the body - handle_chemicals_in_body() - - var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE - if(loc) - environment = loc.return_air() - - //Apparently, the person who wrote this code designed it so that - //blinded get reset each cycle and then get activated later in the - //code. Very ugly. I dont care. Moving this stuff here so its easy - //to find it. - blinded = null - - //Handle temperature/pressure differences between body and environment - if(environment) // More error checking -- TLE - handle_environment(environment) - - //Status updates, death etc. - handle_regular_status_updates() - update_canmove() - - if(client) - handle_regular_hud_updates() - - -/mob/living/carbon/brain/ - proc/handle_mutations_and_radiation() - if(flags & INVULNERABLE) - return - - if (radiation) - if (radiation > 100) - radiation = 100 - if(!container)//If it's not in an MMI +/mob/living/carbon/brain/Life() + set invisibility = 0 + //set background = 1 + if(timestopped) return 0 //under effects of time magick + + ..() + + if(stat != DEAD) + //Mutations and radiation + handle_mutations_and_radiation() + + //Chemicals in the body + handle_chemicals_in_body() + + var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE + if(loc) + environment = loc.return_air() + + //Apparently, the person who wrote this code designed it so that + //blinded get reset each cycle and then get activated later in the + //code. Very ugly. I dont care. Moving this stuff here so its easy + //to find it. + blinded = null + + //Handle temperature/pressure differences between body and environment + if(environment) // More error checking -- TLE + handle_environment(environment) + + //Status updates, death etc. + handle_regular_status_updates() + update_canmove() + + if(client) + handle_regular_hud_updates() + + +/mob/living/carbon/brain/ + proc/handle_mutations_and_radiation() + if(flags & INVULNERABLE) + return + + if (radiation) + if (radiation > 100) + radiation = 100 + if(!container)//If it's not in an MMI to_chat(src, "You feel weak.") - else//Fluff-wise, since the brain can't detect anything itself, the MMI handles thing like that + else//Fluff-wise, since the brain can't detect anything itself, the MMI handles thing like that to_chat(src, "STATUS: CRITICAL AMOUNTS OF RADIATION DETECTED.") - - switch(radiation) - if(1 to 49) - radiation-- - if(prob(25)) - adjustToxLoss(1) - updatehealth() - - if(50 to 74) - radiation -= 2 - adjustToxLoss(1) - if(prob(5)) - radiation -= 5 - if(!container) + + switch(radiation) + if(1 to 49) + radiation-- + if(prob(25)) + adjustToxLoss(1) + updatehealth() + + if(50 to 74) + radiation -= 2 + adjustToxLoss(1) + if(prob(5)) + radiation -= 5 + if(!container) to_chat(src, "You feel weak.") - else + else to_chat(src, "STATUS: DANGEROUS LEVELS OF RADIATION DETECTED.") - updatehealth() - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - updatehealth() - - - proc/handle_environment(datum/gas_mixture/environment) - if(!environment || (flags & INVULNERABLE)) - return - var/environment_heat_capacity = environment.heat_capacity() - if(istype(get_turf(src), /turf/space)) - var/turf/heat_turf = get_turf(src) - environment_heat_capacity = heat_turf.heat_capacity - - if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10))) - var/transfer_coefficient = 1 - - handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) - - if(stat==2) - bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) - - //Account for massive pressure differences - - return //TODO: DEFERRED - - proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) - if(status_flags & GODMODE) return - - if(exposed_temperature > bodytemperature) - var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) - //adjustFireLoss(2.5*discomfort) - //adjustFireLoss(5.0*discomfort) - adjustFireLoss(20.0*discomfort) - - else - var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) - //adjustFireLoss(2.5*discomfort) - adjustFireLoss(5.0*discomfort) - - - - proc/handle_chemicals_in_body() - - - if(reagents) reagents.metabolize(src) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 5) - else - dizziness = max(0, dizziness - 1) - - updatehealth() - - return //TODO: DEFERRED - - - proc/handle_regular_status_updates() //TODO: comment out the unused bits >_> - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - if( !container && (health < config.health_threshold_dead || ((world.time - timeofhostdeath) > config.revival_brain_life)) ) - death() - blinded = 1 - silent = 0 - return 1 - - //Handling EMP effect in the Life(), it's made VERY simply, and has some additional effects handled elsewhere - if(emp_damage) //This is pretty much a damage type only used by MMIs, dished out by the emp_act - if(!(container && istype(container, /obj/item/device/mmi))) - emp_damage = 0 - else - emp_damage = round(emp_damage,1)//Let's have some nice numbers to work with - switch(emp_damage) - if(31 to INFINITY) - emp_damage = 30//Let's not overdo it - if(21 to 30)//High level of EMP damage, unable to see, hear, or speak - eye_blind = 1 - blinded = 1 - ear_deaf = 1 - silent = 1 - if(!alert)//Sounds an alarm, but only once per 'level' - emote("alarm") + updatehealth() + + if(75 to 100) + radiation -= 3 + adjustToxLoss(3) + updatehealth() + + + proc/handle_environment(datum/gas_mixture/environment) + if(!environment || (flags & INVULNERABLE)) + return + var/environment_heat_capacity = environment.heat_capacity() + if(istype(get_turf(src), /turf/space)) + var/turf/heat_turf = get_turf(src) + environment_heat_capacity = heat_turf.heat_capacity + + if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10))) + var/transfer_coefficient = 1 + + handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) + + if(stat==2) + bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) + + //Account for massive pressure differences + + return //TODO: DEFERRED + + proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) + if(status_flags & GODMODE) return + + if(exposed_temperature > bodytemperature) + var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) + //adjustFireLoss(2.5*discomfort) + //adjustFireLoss(5.0*discomfort) + adjustFireLoss(20.0*discomfort) + + else + var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) + //adjustFireLoss(2.5*discomfort) + adjustFireLoss(5.0*discomfort) + + + + proc/handle_chemicals_in_body() + + + if(reagents) reagents.metabolize(src) + + confused = max(0, confused - 1) + // decrement dizziness counter, clamped to 0 + if(resting) + dizziness = max(0, dizziness - 5) + else + dizziness = max(0, dizziness - 1) + + updatehealth() + + return //TODO: DEFERRED + + + proc/handle_regular_status_updates() //TODO: comment out the unused bits >_> + updatehealth() + + if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP + blinded = 1 + silent = 0 + else //ALIVE. LIGHTS ARE ON + if( !container && (health < config.health_threshold_dead || ((world.time - timeofhostdeath) > config.revival_brain_life)) ) + death() + blinded = 1 + silent = 0 + return 1 + + //Handling EMP effect in the Life(), it's made VERY simply, and has some additional effects handled elsewhere + if(emp_damage) //This is pretty much a damage type only used by MMIs, dished out by the emp_act + if(!(container && istype(container, /obj/item/device/mmi))) + emp_damage = 0 + else + emp_damage = round(emp_damage,1)//Let's have some nice numbers to work with + switch(emp_damage) + if(31 to INFINITY) + emp_damage = 30//Let's not overdo it + if(21 to 30)//High level of EMP damage, unable to see, hear, or speak + eye_blind = 1 + blinded = 1 + ear_deaf = 1 + silent = 1 + if(!alert)//Sounds an alarm, but only once per 'level' + emote("alarm") to_chat(src, "Major electrical distruption detected: System rebooting.") - alert = 1 - if(prob(75)) - emp_damage -= 1 - if(20) - alert = 0 - blinded = 0 - eye_blind = 0 - ear_deaf = 0 - silent = 0 - emp_damage -= 1 - if(11 to 19)//Moderate level of EMP damage, resulting in nearsightedness and ear damage - eye_blurry = 1 - ear_damage = 1 - if(!alert) - emote("alert") + alert = 1 + if(prob(75)) + emp_damage -= 1 + if(20) + alert = 0 + blinded = 0 + eye_blind = 0 + ear_deaf = 0 + silent = 0 + emp_damage -= 1 + if(11 to 19)//Moderate level of EMP damage, resulting in nearsightedness and ear damage + eye_blurry = 1 + ear_damage = 1 + if(!alert) + emote("alert") to_chat(src, "Primary systems are now online.") - alert = 1 - if(prob(50)) - emp_damage -= 1 - if(10) - alert = 0 - eye_blurry = 0 - ear_damage = 0 - emp_damage -= 1 - if(2 to 9)//Low level of EMP damage, has few effects(handled elsewhere) - if(!alert) - emote("notice") + alert = 1 + if(prob(50)) + emp_damage -= 1 + if(10) + alert = 0 + eye_blurry = 0 + ear_damage = 0 + emp_damage -= 1 + if(2 to 9)//Low level of EMP damage, has few effects(handled elsewhere) + if(!alert) + emote("notice") to_chat(src, "System reboot nearly complete.") - alert = 1 - if(prob(25)) - emp_damage -= 1 - if(1) - alert = 0 + alert = 1 + if(prob(25)) + emp_damage -= 1 + if(1) + alert = 0 to_chat(src, "All systems restored.") - emp_damage -= 1 - - //Other - if(stunned) - 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) - stuttering = max(stuttering-1, 0) - - if(silent) - silent = max(silent-1, 0) - - if(druggy) - druggy = max(druggy-1, 0) - return 1 - - - proc/handle_regular_hud_updates() - - - if (stat == 2 || (M_XRAY in src.mutations)) - sight |= SEE_TURFS - sight |= SEE_MOBS - sight |= SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (stat != 2) - sight &= ~SEE_TURFS - sight &= ~SEE_MOBS - sight &= ~SEE_OBJS - see_in_dark = 2 - see_invisible = SEE_INVISIBLE_LIVING - - if (healths) - if (stat != 2) - switch(health) - if(100 to INFINITY) - healths.icon_state = "health0" - if(80 to 100) - healths.icon_state = "health1" - if(60 to 80) - healths.icon_state = "health2" - if(40 to 60) - healths.icon_state = "health3" - if(20 to 40) - healths.icon_state = "health4" - if(0 to 20) - healths.icon_state = "health5" - else - healths.icon_state = "health6" - else - healths.icon_state = "health7" - - if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" - if (client) - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if ((blind && stat != 2)) - if ((blinded)) - blind.layer = 18 - else - blind.layer = 0 - - if (disabilities & NEARSIGHTED) - client.screen += global_hud.vimpaired - - if (eye_blurry) - client.screen += global_hud.blurry - - if (druggy) - client.screen += global_hud.druggy - - if (stat != 2) - if (machine) - if (!( machine.check_eye(src) )) - reset_view(null) - else - if(client && !client.adminobs) - reset_view(null) - - return 1 - - -/*/mob/living/carbon/brain/emp_act(severity) - if(flags & INVULNERABLE) - return - - if(!(container && istype(container, /obj/item/device/mmi))) - return - else - switch(severity) - if(1) - emp_damage += rand(20,30) - if(2) - emp_damage += rand(10,20) - if(3) - emp_damage += rand(0,10) + emp_damage -= 1 + + //Other + if(stunned) + 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) + stuttering = max(stuttering-1, 0) + + if(silent) + silent = max(silent-1, 0) + + if(druggy) + druggy = max(druggy-1, 0) + return 1 + + + proc/handle_regular_hud_updates() + + + if (stat == 2 || (M_XRAY in src.mutations)) + sight |= SEE_TURFS + sight |= SEE_MOBS + sight |= SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (stat != 2) + sight &= ~SEE_TURFS + sight &= ~SEE_MOBS + sight &= ~SEE_OBJS + see_in_dark = 2 + see_invisible = SEE_INVISIBLE_LIVING + + if (healths) + if (stat != 2) + switch(health) + if(100 to INFINITY) + healths.icon_state = "health0" + if(80 to 100) + healths.icon_state = "health1" + if(60 to 80) + healths.icon_state = "health2" + if(40 to 60) + healths.icon_state = "health3" + if(20 to 40) + healths.icon_state = "health4" + if(0 to 20) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" + + if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" + if (client) + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if ((blind && stat != 2)) + if ((blinded)) + blind.layer = 18 + else + blind.layer = 0 + + if (disabilities & NEARSIGHTED) + client.screen += global_hud.vimpaired + + if (eye_blurry) + client.screen += global_hud.blurry + + if (druggy) + client.screen += global_hud.druggy + + if (stat != 2) + if (machine) + if (!( machine.check_eye(src) )) + reset_view(null) + else + if(client && !client.adminobs) + reset_view(null) + + return 1 + + +/*/mob/living/carbon/brain/emp_act(severity) + if(flags & INVULNERABLE) + return + + if(!(container && istype(container, /obj/item/device/mmi))) + return + else + switch(severity) + if(1) + emp_damage += rand(20,30) + if(2) + emp_damage += rand(10,20) + if(3) + emp_damage += rand(0,10) ..()*/ \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/login.dm b/code/modules/mob/living/carbon/brain/login.dm index 84bccdfe964..d04d2758958 100644 --- a/code/modules/mob/living/carbon/brain/login.dm +++ b/code/modules/mob/living/carbon/brain/login.dm @@ -1,2 +1,2 @@ -/mob/living/carbon/brain/Login() +/mob/living/carbon/brain/Login() return ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm index 47420133885..b619304084a 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/carbon/brain/say.dm @@ -1,21 +1,21 @@ -/mob/living/carbon/brain/say(var/message) - - if(!(container && (istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/mmi/posibrain)))) - return //No MMI, can't speak, bucko./N - else - if(prob(emp_damage*4)) - if(prob(10)) - return - else - message = Gibberish(message, (emp_damage*6)) //scrambles the message, gets worse when emp_damage is higher - return ..(message) - -/mob/living/carbon/brain/radio(var/datum/speech/speech, var/message_mode) - if(message_mode && istype(container, /obj/item/device/mmi/radio_enabled)) - var/obj/item/device/mmi/radio_enabled/R = container - if(R.radio) - R.radio.talk_into(speech) // Might need message_mode - return ITALICS | REDUCE_RANGE - -/mob/living/carbon/brain/lingcheck() +/mob/living/carbon/brain/say(var/message) + + if(!(container && (istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/mmi/posibrain)))) + return //No MMI, can't speak, bucko./N + else + if(prob(emp_damage*4)) + if(prob(10)) + return + else + message = Gibberish(message, (emp_damage*6)) //scrambles the message, gets worse when emp_damage is higher + return ..(message) + +/mob/living/carbon/brain/radio(var/datum/speech/speech, var/message_mode) + if(message_mode && istype(container, /obj/item/device/mmi/radio_enabled)) + var/obj/item/device/mmi/radio_enabled/R = container + if(R.radio) + R.radio.talk_into(speech) // Might need message_mode + return ITALICS | REDUCE_RANGE + +/mob/living/carbon/brain/lingcheck() return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 26f3d8b6554..9d52d3cb770 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1,661 +1,661 @@ -/mob/living/carbon/Login() - ..() - update_hud() - return - -/mob/living/carbon/Bump(var/atom/movable/AM, yes) - if(now_pushing || !yes) - return - ..() - if(istype(AM, /mob/living/carbon) && prob(10)) - src.spread_disease_to(AM, "Contact") - - -/mob/living/carbon/Move(NewLoc,Dir=0,step_x=0,step_y=0) - . = ..() - - if(.) - if(nutrition && stat != DEAD) - nutrition -= HUNGER_FACTOR / 10 - - if(m_intent == "run") - nutrition -= HUNGER_FACTOR / 10 - - if((M_FAT in mutations) && m_intent == "run" && bodytemperature <= 360) - bodytemperature += 2 - - update_minimap() - -/mob/living/carbon/attack_animal(mob/living/simple_animal/M as mob)//humans and slimes have their own - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - visible_message("[M] [M.attacktext] \the [src] !") - M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") - if(M.zone_sel && M.zone_sel.selecting) - dam_zone = M.zone_sel.selecting - var/datum/organ/external/affecting = ran_zone(dam_zone) - apply_damage(damage,M.melee_damage_type, affecting) - updatehealth() - - -/mob/living/carbon/proc/update_minimap() - var/obj/item/device/pda/pda_device = machine - if(machine && istype(pda_device)) - var/turf/user_loc = get_turf(src) - var/turf/pda_loc = get_turf(pda_device) - if(get_dist(user_loc,pda_loc) <= 1) - if(pda_device.mode == PDA_APP_STATIONMAP) - pda_device.attack_self(src) - else - unset_machine() - src << browse(null, "window=pda") - -/mob/living/carbon/relaymove(var/mob/user, direction) - if(user in src.stomach_contents) - if(prob(40)) - for(var/mob/M in hearers(4, src)) - if(M.client) - M.show_message(text("You hear something rumbling inside [src]'s stomach..."), 2) - var/obj/item/I = user.get_active_hand() - if(I && I.force) - var/d = rand(round(I.force / 4), I.force) - if(istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - var/organ = H.get_organ("chest") - if (istype(organ, /datum/organ/external)) - var/datum/organ/external/temp = organ - if(temp.take_damage(d, 0)) - H.UpdateDamageIcon() - H.updatehealth() - else - src.take_organ_damage(d) - for(var/mob/M in viewers(user, null)) - if(M.client) - M.show_message(text("[user] attacks [src]'s stomach wall with the [I.name]!"), 2) - playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) - - if(prob(src.getBruteLoss() - 50)) - for(var/atom/movable/A in stomach_contents) - A.loc = loc - stomach_contents.Remove(A) - src.gib() - -/mob/living/carbon/gib() - dropBorers(1) - for(var/mob/M in src) - if(M in src.stomach_contents) - src.stomach_contents.Remove(M) - M.loc = src.loc - for(var/mob/N in viewers(src, null)) - if(N.client) - N.show_message(text("[M] bursts out of [src]!"), 2) - . = ..() - -/mob/living/carbon/proc/share_contact_diseases(var/mob/M) - for(var/datum/disease/D in viruses) - if(D.spread_by_touch()) - M.contract_disease(D, 0, 1, CONTACT_HANDS) - for(var/datum/disease/D in M.viruses) - if(D.spread_by_touch()) - contract_disease(D, 0, 1, CONTACT_HANDS) - -/mob/living/carbon/attack_hand(mob/M as mob) - if(!istype(M, /mob/living/carbon)) return - if (hasorgans(M)) - var/datum/organ/external/temp = M:organs_by_name["r_hand"] - if (M.hand) - temp = M:organs_by_name["l_hand"] - if(temp && !temp.is_usable()) - to_chat(M, "You can't use your [temp.display_name]") - return - share_contact_diseases(M) - return - - -/mob/living/carbon/attack_paw(mob/M as mob) - if(!istype(M, /mob/living/carbon)) return - share_contact_diseases(M) - return - -/mob/living/carbon/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1.0) - var/damage = shock_damage * siemens_coeff - - if(damage <= 0) - damage = 0 - - if(take_overall_damage(0, damage, "[source]") == 0) // godmode - return 0 - - //src.burn_skin(shock_damage) - //src.adjustFireLoss(shock_damage) //burn_skin will do this for us - //src.updatehealth() - - visible_message( \ - "[src] was shocked by the [source]!", \ - "You feel a powerful shock course through your body!", \ - "You hear a heavy electrical crack.", \ - "[src] starts raving!", \ - "You feel butterflies in your stomach!", \ - "You hear a policeman whistling!" - ) - - //if(src.stunned < shock_damage) src.stunned = shock_damage - - Stun(10) // this should work for now, more is really silly and makes you lay there forever - - //if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff - - Weaken(10) - - var/datum/effect/effect/system/spark_spread/SparkSpread = new - SparkSpread.set_up(5, 1, loc) - SparkSpread.start() - - return damage - -/mob/living/carbon/proc/swap_hand() - src.hand = !( src.hand ) - if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object) - if(hand) //This being 1 means the left hand is in use - hud_used.l_hand_hud_object.icon_state = "hand_active" - hud_used.r_hand_hud_object.icon_state = "hand_inactive" - else - hud_used.l_hand_hud_object.icon_state = "hand_inactive" - hud_used.r_hand_hud_object.icon_state = "hand_active" - /*if (!( src.hand )) - src.hands.dir = NORTH - else - src.hands.dir = SOUTH*/ - return - -/mob/living/carbon/proc/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. - - - if(istext(selhand)) - selhand = lowertext(selhand) - - if(selhand == "right" || selhand == "r") - selhand = 0 - if(selhand == "left" || selhand == "l") - selhand = 1 - - if(selhand != src.hand) - swap_hand() - -/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) - if (src.health >= config.health_threshold_crit) - if(src == M && istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - src.visible_message( \ - text("[src] examines [].",src.gender==MALE?"himself":"herself"), \ - "You check yourself for injuries." \ - ) - - for(var/datum/organ/external/org in H.organs) - var/status = "" - var/brutedamage = org.brute_dam - var/burndamage = org.burn_dam - if(halloss > 0) - if(prob(30)) - brutedamage += halloss - if(prob(30)) - burndamage += halloss - - if(brutedamage > 0) - status = "bruised" - if(brutedamage > 20) - status = "bleeding" - if(brutedamage > 40) - status = "mangled" - if(brutedamage > 0 && burndamage > 0) - status += " and " - if(burndamage > 40) - status += "peeling away" - - else if(burndamage > 10) - status += "blistered" - else if(burndamage > 0) - status += "numb" - if(org.status & ORGAN_DESTROYED) - status = "MISSING!" - if(org.status & ORGAN_MUTATED) - status = "weirdly shapen." - if(status == "") - status = "OK" - src.show_message(text("\t []My [] is [].",status=="OK"?"":"",org.display_name,status),1) - if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit)) - H.play_xylophone() - else if(lying) // /vg/: For hugs. This is how update_icon figgers it out, anyway. - N3X15 - var/t_him = "it" - if (src.gender == MALE) - t_him = "him" - else if (src.gender == FEMALE) - t_him = "her" - 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 - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - M.visible_message( \ - "[M] shakes [src] trying to wake [t_him] up!", \ - "You shake [src] trying to wake [t_him] up!", \ - drugged_message = "[M] starts massaging [t_him]'s back.", \ - self_drugged_message = "You start massaging [t_him]'s back." - ) - // BEGIN HUGCODE - N3X - else - if (istype(src,/mob/living/carbon/human) && src:w_uniform) - var/mob/living/carbon/human/H = src - H.w_uniform.add_fingerprint(M) - playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - M.visible_message( \ - "[M] gives [src] a [pick("hug","warm embrace")].", \ - "You hug [src].", \ - ) - reagents.add_reagent("paracetamol", 1) - - share_contact_diseases(M) - - -/mob/living/carbon/proc/eyecheck() - return 0 - -// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching. -// Stop! ... Hammertime! ~Carn - -/mob/living/carbon/proc/getDNA() - return dna - -/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA) - dna = newDNA - -// ++++ROCKDTBEN++++ MOB PROCS //END - -/mob/living/carbon/clean_blood() - . = ..() - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(H.gloves) - if(H.gloves.clean_blood()) - H.update_inv_gloves(0) - H.gloves.germ_level = 0 - else - if(H.bloody_hands) - H.bloody_hands = 0 - H.update_inv_gloves(0) - H.germ_level = 0 - update_icons() //apply the now updated overlays to the mob - - -//Throwing stuff - -/mob/living/carbon/proc/toggle_throw_mode() - if (src.in_throw_mode) - throw_mode_off() - else - throw_mode_on() - -/mob/living/carbon/proc/throw_mode_off() - src.in_throw_mode = 0 - src.throw_icon.icon_state = "act_throw_off" - -/mob/living/carbon/proc/throw_mode_on() - if(gcDestroyed) return - src.in_throw_mode = 1 - src.throw_icon.icon_state = "act_throw_on" - -/mob/proc/throw_item(var/atom/target,var/atom/movable/what=null) - return - -/mob/living/carbon/throw_item(var/atom/target,var/atom/movable/what=null) - src.throw_mode_off() - if(usr.stat || !target) - return - - if(!istype(loc,/turf)) - to_chat(src, "You can't do that now!") - return - - if(target.type == /obj/screen) return - - var/atom/movable/item = src.get_active_hand() - if(what) - item=what - - if(!item) return - - if (istype(item, /obj/item/offhand)) - var/obj/item/offhand/offhand = item - if(offhand.wielding) - src.throw_item(target, offhand.wielding) - return - - if (istype(item, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = item - item = G.toss() //throw the person instead of the grab - if(ismob(item)) - var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors - var/turf/end_T = get_turf(target) - if(start_T && end_T) - var/mob/M = item - var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" - var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" - - M.attack_log += text("\[[time_stamp()]\] Has been thrown by [usr.name] ([usr.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") - usr.attack_log += text("\[[time_stamp()]\] Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") - - log_attack("[usr.name] ([usr.ckey]) Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") - if(!iscarbon(usr)) - M.LAssailant = null - else - M.LAssailant = usr - returnToPool(G) - if(!item) return //Grab processing has a chance of returning null - - var/obj/item/I = item - if(istype(I) && I.cant_drop > 0) - usr << "It's stuck to your hand!" - return - - remove_from_mob(item) - - //actually throw it! - if (item) - item.forceMove(get_turf(src)) - src.visible_message("[src] has thrown [item].", \ - drugged_message = "[item] escapes from [src]'s grasp and flies away!") - - if((istype(src.loc, /turf/space)) || (src.areaMaster && (src.areaMaster.has_gravity == 0))) - var/mob/space_obj=src - // If we're being held, make the guy holding us move. - if(istype(loc,/obj/item/weapon/holder)) - var/obj/item/weapon/holder/Ho=loc - // Who holds the holder? - if(ismob(Ho.loc)) - space_obj=Ho.loc - space_obj.inertia_dir = get_dir(target, src) - step(space_obj, inertia_dir) - - -/* - if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction - src.inertia_dir = get_dir(target, src) - step(src, inertia_dir) -*/ - - - var/throw_mult=1 - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H=src - throw_mult = H.species.throw_mult - if(M_HULK in H.mutations || M_STRONG in H.mutations) - throw_mult+=0.5 - item.throw_at(target, item.throw_range*throw_mult, item.throw_speed*throw_mult) - -/*mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - ..() - bodytemperature = max(bodytemperature, BODYTEMP_HEAT_DAMAGE_LIMIT+10)*/ - -/mob/living/carbon/can_use_hands() - if(handcuffed) - return 0 - if(locked_to && ! istype(locked_to, /obj/structure/bed/chair)) // buckling does not restrict hands - return 0 - return 1 - -/mob/living/carbon/restrained() - if(timestopped) return 1 //under effects of time magick - if (handcuffed) - return 1 - return - -/mob/living/carbon/u_equip(obj/item/W as obj, dropped = 1) - var/success = 0 - if(!W) return 0 - else if (W == handcuffed) - handcuffed = null - success = 1 - update_inv_handcuffed() - - else if (W == legcuffed) - legcuffed = null - success = 1 - update_inv_legcuffed() - else - ..() - if(success) - if (W) - if (client) - client.screen -= W - if(dropped) - W.loc = loc - W.dropped(src) - if(W) - W.layer = initial(W.layer) - - return -/* -/mob/living/carbon/show_inv(mob/living/carbon/user as mob) - user.set_machine(src) - var/dat = {" -
    [name]
    -

    -
    Head(Mask): [(wear_mask ? wear_mask : "Nothing")] -
    Left Hand: [(l_hand ? l_hand : "Nothing")] -
    Right Hand: [(r_hand ? r_hand : "Nothing")] -
    Back: [(back ? back : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] -
    [(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))] -
    [(internal ? text("Remove Internal") : "")] -
    Empty Pockets -
    Refresh -
    Close -
    "} - user << browse(dat, text("window=mob\ref[src];size=325x500")) - onclose(user, "mob\ref[src]") - return -*/ - - -/mob/living/carbon/show_inv(mob/living/carbon/user as mob) - user.set_machine(src) - var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) - var/TAB = "    " - var/dat = "" - - if(handcuffed) - dat += "
    Handcuffed: Remove" - else - dat += {" - Left Hand: [(l_hand && !( src.l_hand.abstract )) ? l_hand : "Empty"]
    - Right Hand: [(r_hand && !( src.r_hand.abstract )) ? r_hand : "Empty"]
    - "} - - dat += "
    Back: [(back && !(src.back.abstract)) ? back : "Empty"]" - if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) - dat += "
    [TAB]↳[internal ? "Disable Internals" : "Set Internals"]" - - dat += "
    " - - - dat += "
    Mask: [(wear_mask && !(src.wear_mask.abstract)) ? wear_mask : "Empty"]" - - dat += {" -
    -
    Close - "} - - var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 340, 500) - popup.set_content(dat) - popup.open() - - - - - -//generates realistic-ish pulse output based on preset levels -/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate - var/temp = 0 //see setup.dm:694 - switch(src.pulse) - if(PULSE_NONE) - return "0" - if(PULSE_SLOW) - temp = rand(40, 60) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_NORM) - temp = rand(60, 90) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_FAST) - temp = rand(90, 120) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_2FAST) - temp = rand(120, 160) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_THREADY) - return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread" -// output for machines^ ^^^^^^^output for people^^^^^^^^^ - -/mob/living/carbon/verb/mob_sleep() - set name = "Sleep" - set category = "IC" - - if(usr.sleeping) - to_chat(usr, "You are already sleeping") - return - if(alert(src,"Are you sure you want to sleep for a while?","Sleep","Yes","No") == "Yes") - usr.sleeping = 150 //Long nap of 5 minutes. Those are MC TICKS. Don't get fooled - -//Brain slug proc for voluntary removal of control. -/mob/living/carbon/proc/release_control() - set category = "Alien" - set name = "Release Control" - set desc = "Release control of your host's body." - - do_release_control(0) - -/mob/living/carbon/proc/do_release_control(var/rptext=1) - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.controlling) - if(rptext) - to_chat(src, "You withdraw your probosci, releasing control of [B.host_brain]") - to_chat(B.host_brain, "Your vision swims as the alien parasite releases control of your body.") - B.ckey = ckey - B.controlling = 0 - if(B.host_brain.ckey) - ckey = B.host_brain.ckey - B.host_brain.ckey = null - B.host_brain.name = "host brain" - B.host_brain.real_name = "host brain" - - verbs -= /mob/living/carbon/proc/release_control - verbs -= /mob/living/carbon/proc/punish_host - -//Brain slug proc for tormenting the host. -/mob/living/carbon/proc/punish_host() - set category = "Alien" - set name = "Torment host" - set desc = "Punish your host with agony." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.host_brain.ckey) - to_chat(src, "You send a punishing spike of psychic agony lancing into your host's brain.") - to_chat(B.host_brain, "Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!") - -//Check for brain worms in head. -/mob/proc/has_brain_worms() - for(var/I in contents) - if(istype(I,/mob/living/simple_animal/borer)) - return I - - return 0 - -/mob/living/carbon/is_muzzled() - return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) - - -/mob/living/carbon/proc/isInCrit() - // Health is in deep shit and we're not already dead - return (health < config.health_threshold_crit) && stat != 2 - -/mob/living/carbon/get_default_language() - if(default_language) - return default_language - - return null - -/mob/living/carbon/html_mob_check(var/typepath) - for(var/atom/movable/AM in html_machines) - if(typepath == AM.type) - if(Adjacent(AM)) - return 1 - return 0 - -/mob/living/carbon/CheckSlip() - return !locked_to && !lying - -/mob/living/carbon/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0) - if(!slip_on_walking && m_intent == "walk") - return 0 - - if (CheckSlip() < 1 || !on_foot()) - return 0 - - stop_pulling() - Stun(stun_amount) - Weaken(weaken_amount) - - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) - - return 1 - -/mob/living/carbon/proc/transferImplantsTo(mob/living/carbon/newmob) - for(var/obj/item/weapon/implant/I in src) - I.loc = newmob - I.implanted = 1 - I.imp_in = newmob - if(istype(newmob, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = newmob - if(!I.part) //implanted as a nonhuman, won't have one. - I.part = /datum/organ/external/chest - for (var/datum/organ/external/affected in H.organs) - if(!istype(affected, I.part)) continue - affected.implants += I - -/mob/living/carbon/proc/dropBorers(var/gibbed = null) - var/mob/living/simple_animal/borer/B = has_brain_worms() - if(B) - B.detach() - if(gibbed) - to_chat(B, "As your host is violently destroyed, so are you!") - B.ghostize(0) - qdel(B) - else - to_chat(B, "You're forcefully popped out of your host!") - -/mob/living/carbon/proc/transferBorers(mob/living/target) - var/mob/living/simple_animal/borer/B = has_brain_worms() - if(B) - B.detach() - if(iscarbon(target)) - var/mob/living/carbon/C = target - B.perform_infestation(C) - else +/mob/living/carbon/Login() + ..() + update_hud() + return + +/mob/living/carbon/Bump(var/atom/movable/AM, yes) + if(now_pushing || !yes) + return + ..() + if(istype(AM, /mob/living/carbon) && prob(10)) + src.spread_disease_to(AM, "Contact") + + +/mob/living/carbon/Move(NewLoc,Dir=0,step_x=0,step_y=0) + . = ..() + + if(.) + if(nutrition && stat != DEAD) + nutrition -= HUNGER_FACTOR / 10 + + if(m_intent == "run") + nutrition -= HUNGER_FACTOR / 10 + + if((M_FAT in mutations) && m_intent == "run" && bodytemperature <= 360) + bodytemperature += 2 + + update_minimap() + +/mob/living/carbon/attack_animal(mob/living/simple_animal/M as mob)//humans and slimes have their own + if(M.melee_damage_upper == 0) + M.emote("[M.friendly] [src]") + else + if(M.attack_sound) + playsound(loc, M.attack_sound, 50, 1, 1) + visible_message("[M] [M.attacktext] \the [src] !") + M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + if(M.zone_sel && M.zone_sel.selecting) + dam_zone = M.zone_sel.selecting + var/datum/organ/external/affecting = ran_zone(dam_zone) + apply_damage(damage,M.melee_damage_type, affecting) + updatehealth() + + +/mob/living/carbon/proc/update_minimap() + var/obj/item/device/pda/pda_device = machine + if(machine && istype(pda_device)) + var/turf/user_loc = get_turf(src) + var/turf/pda_loc = get_turf(pda_device) + if(get_dist(user_loc,pda_loc) <= 1) + if(pda_device.mode == PDA_APP_STATIONMAP) + pda_device.attack_self(src) + else + unset_machine() + src << browse(null, "window=pda") + +/mob/living/carbon/relaymove(var/mob/user, direction) + if(user in src.stomach_contents) + if(prob(40)) + for(var/mob/M in hearers(4, src)) + if(M.client) + M.show_message(text("You hear something rumbling inside [src]'s stomach..."), 2) + var/obj/item/I = user.get_active_hand() + if(I && I.force) + var/d = rand(round(I.force / 4), I.force) + if(istype(src, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + var/organ = H.get_organ("chest") + if (istype(organ, /datum/organ/external)) + var/datum/organ/external/temp = organ + if(temp.take_damage(d, 0)) + H.UpdateDamageIcon() + H.updatehealth() + else + src.take_organ_damage(d) + for(var/mob/M in viewers(user, null)) + if(M.client) + M.show_message(text("[user] attacks [src]'s stomach wall with the [I.name]!"), 2) + playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) + + if(prob(src.getBruteLoss() - 50)) + for(var/atom/movable/A in stomach_contents) + A.loc = loc + stomach_contents.Remove(A) + src.gib() + +/mob/living/carbon/gib() + dropBorers(1) + for(var/mob/M in src) + if(M in src.stomach_contents) + src.stomach_contents.Remove(M) + M.loc = src.loc + for(var/mob/N in viewers(src, null)) + if(N.client) + N.show_message(text("[M] bursts out of [src]!"), 2) + . = ..() + +/mob/living/carbon/proc/share_contact_diseases(var/mob/M) + for(var/datum/disease/D in viruses) + if(D.spread_by_touch()) + M.contract_disease(D, 0, 1, CONTACT_HANDS) + for(var/datum/disease/D in M.viruses) + if(D.spread_by_touch()) + contract_disease(D, 0, 1, CONTACT_HANDS) + +/mob/living/carbon/attack_hand(mob/M as mob) + if(!istype(M, /mob/living/carbon)) return + if (hasorgans(M)) + var/datum/organ/external/temp = M:organs_by_name["r_hand"] + if (M.hand) + temp = M:organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + to_chat(M, "You can't use your [temp.display_name]") + return + share_contact_diseases(M) + return + + +/mob/living/carbon/attack_paw(mob/M as mob) + if(!istype(M, /mob/living/carbon)) return + share_contact_diseases(M) + return + +/mob/living/carbon/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1.0) + var/damage = shock_damage * siemens_coeff + + if(damage <= 0) + damage = 0 + + if(take_overall_damage(0, damage, "[source]") == 0) // godmode + return 0 + + //src.burn_skin(shock_damage) + //src.adjustFireLoss(shock_damage) //burn_skin will do this for us + //src.updatehealth() + + visible_message( \ + "[src] was shocked by the [source]!", \ + "You feel a powerful shock course through your body!", \ + "You hear a heavy electrical crack.", \ + "[src] starts raving!", \ + "You feel butterflies in your stomach!", \ + "You hear a policeman whistling!" + ) + + //if(src.stunned < shock_damage) src.stunned = shock_damage + + Stun(10) // this should work for now, more is really silly and makes you lay there forever + + //if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff + + Weaken(10) + + var/datum/effect/effect/system/spark_spread/SparkSpread = new + SparkSpread.set_up(5, 1, loc) + SparkSpread.start() + + return damage + +/mob/living/carbon/proc/swap_hand() + src.hand = !( src.hand ) + if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object) + if(hand) //This being 1 means the left hand is in use + hud_used.l_hand_hud_object.icon_state = "hand_active" + hud_used.r_hand_hud_object.icon_state = "hand_inactive" + else + hud_used.l_hand_hud_object.icon_state = "hand_inactive" + hud_used.r_hand_hud_object.icon_state = "hand_active" + /*if (!( src.hand )) + src.hands.dir = NORTH + else + src.hands.dir = SOUTH*/ + return + +/mob/living/carbon/proc/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. + + + if(istext(selhand)) + selhand = lowertext(selhand) + + if(selhand == "right" || selhand == "r") + selhand = 0 + if(selhand == "left" || selhand == "l") + selhand = 1 + + if(selhand != src.hand) + swap_hand() + +/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) + if (src.health >= config.health_threshold_crit) + if(src == M && istype(src, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + src.visible_message( \ + text("[src] examines [].",src.gender==MALE?"himself":"herself"), \ + "You check yourself for injuries." \ + ) + + for(var/datum/organ/external/org in H.organs) + var/status = "" + var/brutedamage = org.brute_dam + var/burndamage = org.burn_dam + if(halloss > 0) + if(prob(30)) + brutedamage += halloss + if(prob(30)) + burndamage += halloss + + if(brutedamage > 0) + status = "bruised" + if(brutedamage > 20) + status = "bleeding" + if(brutedamage > 40) + status = "mangled" + if(brutedamage > 0 && burndamage > 0) + status += " and " + if(burndamage > 40) + status += "peeling away" + + else if(burndamage > 10) + status += "blistered" + else if(burndamage > 0) + status += "numb" + if(org.status & ORGAN_DESTROYED) + status = "MISSING!" + if(org.status & ORGAN_MUTATED) + status = "weirdly shapen." + if(status == "") + status = "OK" + src.show_message(text("\t []My [] is [].",status=="OK"?"":"",org.display_name,status),1) + if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit)) + H.play_xylophone() + else if(lying) // /vg/: For hugs. This is how update_icon figgers it out, anyway. - N3X15 + var/t_him = "it" + if (src.gender == MALE) + t_him = "him" + else if (src.gender == FEMALE) + t_him = "her" + 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 + AdjustParalysis(-3) + AdjustStunned(-3) + AdjustWeakened(-3) + playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + M.visible_message( \ + "[M] shakes [src] trying to wake [t_him] up!", \ + "You shake [src] trying to wake [t_him] up!", \ + drugged_message = "[M] starts massaging [t_him]'s back.", \ + self_drugged_message = "You start massaging [t_him]'s back." + ) + // BEGIN HUGCODE - N3X + else + if (istype(src,/mob/living/carbon/human) && src:w_uniform) + var/mob/living/carbon/human/H = src + H.w_uniform.add_fingerprint(M) + playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + M.visible_message( \ + "[M] gives [src] a [pick("hug","warm embrace")].", \ + "You hug [src].", \ + ) + reagents.add_reagent("paracetamol", 1) + + share_contact_diseases(M) + + +/mob/living/carbon/proc/eyecheck() + return 0 + +// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching. +// Stop! ... Hammertime! ~Carn + +/mob/living/carbon/proc/getDNA() + return dna + +/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA) + dna = newDNA + +// ++++ROCKDTBEN++++ MOB PROCS //END + +/mob/living/carbon/clean_blood() + . = ..() + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.gloves) + if(H.gloves.clean_blood()) + H.update_inv_gloves(0) + H.gloves.germ_level = 0 + else + if(H.bloody_hands) + H.bloody_hands = 0 + H.update_inv_gloves(0) + H.germ_level = 0 + update_icons() //apply the now updated overlays to the mob + + +//Throwing stuff + +/mob/living/carbon/proc/toggle_throw_mode() + if (src.in_throw_mode) + throw_mode_off() + else + throw_mode_on() + +/mob/living/carbon/proc/throw_mode_off() + src.in_throw_mode = 0 + src.throw_icon.icon_state = "act_throw_off" + +/mob/living/carbon/proc/throw_mode_on() + if(gcDestroyed) return + src.in_throw_mode = 1 + src.throw_icon.icon_state = "act_throw_on" + +/mob/proc/throw_item(var/atom/target,var/atom/movable/what=null) + return + +/mob/living/carbon/throw_item(var/atom/target,var/atom/movable/what=null) + src.throw_mode_off() + if(usr.stat || !target) + return + + if(!istype(loc,/turf)) + to_chat(src, "You can't do that now!") + return + + if(target.type == /obj/screen) return + + var/atom/movable/item = src.get_active_hand() + if(what) + item=what + + if(!item) return + + if (istype(item, /obj/item/offhand)) + var/obj/item/offhand/offhand = item + if(offhand.wielding) + src.throw_item(target, offhand.wielding) + return + + if (istype(item, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = item + item = G.toss() //throw the person instead of the grab + if(ismob(item)) + var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors + var/turf/end_T = get_turf(target) + if(start_T && end_T) + var/mob/M = item + var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" + var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" + + M.attack_log += text("\[[time_stamp()]\] Has been thrown by [usr.name] ([usr.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") + usr.attack_log += text("\[[time_stamp()]\] Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") + + log_attack("[usr.name] ([usr.ckey]) Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") + if(!iscarbon(usr)) + M.LAssailant = null + else + M.LAssailant = usr + returnToPool(G) + if(!item) return //Grab processing has a chance of returning null + + var/obj/item/I = item + if(istype(I) && I.cant_drop > 0) + usr << "It's stuck to your hand!" + return + + remove_from_mob(item) + + //actually throw it! + if (item) + item.forceMove(get_turf(src)) + src.visible_message("[src] has thrown [item].", \ + drugged_message = "[item] escapes from [src]'s grasp and flies away!") + + if((istype(src.loc, /turf/space)) || (src.areaMaster && (src.areaMaster.has_gravity == 0))) + var/mob/space_obj=src + // If we're being held, make the guy holding us move. + if(istype(loc,/obj/item/weapon/holder)) + var/obj/item/weapon/holder/Ho=loc + // Who holds the holder? + if(ismob(Ho.loc)) + space_obj=Ho.loc + space_obj.inertia_dir = get_dir(target, src) + step(space_obj, inertia_dir) + + +/* + if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction + src.inertia_dir = get_dir(target, src) + step(src, inertia_dir) +*/ + + + var/throw_mult=1 + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H=src + throw_mult = H.species.throw_mult + if(M_HULK in H.mutations || M_STRONG in H.mutations) + throw_mult+=0.5 + item.throw_at(target, item.throw_range*throw_mult, item.throw_speed*throw_mult) + +/*mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + ..() + bodytemperature = max(bodytemperature, BODYTEMP_HEAT_DAMAGE_LIMIT+10)*/ + +/mob/living/carbon/can_use_hands() + if(handcuffed) + return 0 + if(locked_to && ! istype(locked_to, /obj/structure/bed/chair)) // buckling does not restrict hands + return 0 + return 1 + +/mob/living/carbon/restrained() + if(timestopped) return 1 //under effects of time magick + if (handcuffed) + return 1 + return + +/mob/living/carbon/u_equip(obj/item/W as obj, dropped = 1) + var/success = 0 + if(!W) return 0 + else if (W == handcuffed) + handcuffed = null + success = 1 + update_inv_handcuffed() + + else if (W == legcuffed) + legcuffed = null + success = 1 + update_inv_legcuffed() + else + ..() + if(success) + if (W) + if (client) + client.screen -= W + if(dropped) + W.loc = loc + W.dropped(src) + if(W) + W.layer = initial(W.layer) + + return +/* +/mob/living/carbon/show_inv(mob/living/carbon/user as mob) + user.set_machine(src) + var/dat = {" +
    [name]
    +

    +
    Head(Mask): [(wear_mask ? wear_mask : "Nothing")] +
    Left Hand: [(l_hand ? l_hand : "Nothing")] +
    Right Hand: [(r_hand ? r_hand : "Nothing")] +
    Back: [(back ? back : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
    [(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))] +
    [(internal ? text("Remove Internal") : "")] +
    Empty Pockets +
    Refresh +
    Close +
    "} + user << browse(dat, text("window=mob\ref[src];size=325x500")) + onclose(user, "mob\ref[src]") + return +*/ + + +/mob/living/carbon/show_inv(mob/living/carbon/user as mob) + user.set_machine(src) + var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) + var/TAB = "    " + var/dat = "" + + if(handcuffed) + dat += "
    Handcuffed: Remove" + else + dat += {" + Left Hand: [(l_hand && !( src.l_hand.abstract )) ? l_hand : "Empty"]
    + Right Hand: [(r_hand && !( src.r_hand.abstract )) ? r_hand : "Empty"]
    + "} + + dat += "
    Back: [(back && !(src.back.abstract)) ? back : "Empty"]" + if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) + dat += "
    [TAB]↳[internal ? "Disable Internals" : "Set Internals"]" + + dat += "
    " + + + dat += "
    Mask: [(wear_mask && !(src.wear_mask.abstract)) ? wear_mask : "Empty"]" + + dat += {" +
    +
    Close + "} + + var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 340, 500) + popup.set_content(dat) + popup.open() + + + + + +//generates realistic-ish pulse output based on preset levels +/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate + var/temp = 0 //see setup.dm:694 + switch(src.pulse) + if(PULSE_NONE) + return "0" + if(PULSE_SLOW) + temp = rand(40, 60) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_NORM) + temp = rand(60, 90) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_FAST) + temp = rand(90, 120) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_2FAST) + temp = rand(120, 160) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_THREADY) + return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread" +// output for machines^ ^^^^^^^output for people^^^^^^^^^ + +/mob/living/carbon/verb/mob_sleep() + set name = "Sleep" + set category = "IC" + + if(usr.sleeping) + to_chat(usr, "You are already sleeping") + return + if(alert(src,"Are you sure you want to sleep for a while?","Sleep","Yes","No") == "Yes") + usr.sleeping = 150 //Long nap of 5 minutes. Those are MC TICKS. Don't get fooled + +//Brain slug proc for voluntary removal of control. +/mob/living/carbon/proc/release_control() + set category = "Alien" + set name = "Release Control" + set desc = "Release control of your host's body." + + do_release_control(0) + +/mob/living/carbon/proc/do_release_control(var/rptext=1) + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.controlling) + if(rptext) + to_chat(src, "You withdraw your probosci, releasing control of [B.host_brain]") + to_chat(B.host_brain, "Your vision swims as the alien parasite releases control of your body.") + B.ckey = ckey + B.controlling = 0 + if(B.host_brain.ckey) + ckey = B.host_brain.ckey + B.host_brain.ckey = null + B.host_brain.name = "host brain" + B.host_brain.real_name = "host brain" + + verbs -= /mob/living/carbon/proc/release_control + verbs -= /mob/living/carbon/proc/punish_host + +//Brain slug proc for tormenting the host. +/mob/living/carbon/proc/punish_host() + set category = "Alien" + set name = "Torment host" + set desc = "Punish your host with agony." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.host_brain.ckey) + to_chat(src, "You send a punishing spike of psychic agony lancing into your host's brain.") + to_chat(B.host_brain, "Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!") + +//Check for brain worms in head. +/mob/proc/has_brain_worms() + for(var/I in contents) + if(istype(I,/mob/living/simple_animal/borer)) + return I + + return 0 + +/mob/living/carbon/is_muzzled() + return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) + + +/mob/living/carbon/proc/isInCrit() + // Health is in deep shit and we're not already dead + return (health < config.health_threshold_crit) && stat != 2 + +/mob/living/carbon/get_default_language() + if(default_language) + return default_language + + return null + +/mob/living/carbon/html_mob_check(var/typepath) + for(var/atom/movable/AM in html_machines) + if(typepath == AM.type) + if(Adjacent(AM)) + return 1 + return 0 + +/mob/living/carbon/CheckSlip() + return !locked_to && !lying + +/mob/living/carbon/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0) + if(!slip_on_walking && m_intent == "walk") + return 0 + + if (CheckSlip() < 1 || !on_foot()) + return 0 + + stop_pulling() + Stun(stun_amount) + Weaken(weaken_amount) + + playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) + + return 1 + +/mob/living/carbon/proc/transferImplantsTo(mob/living/carbon/newmob) + for(var/obj/item/weapon/implant/I in src) + I.loc = newmob + I.implanted = 1 + I.imp_in = newmob + if(istype(newmob, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = newmob + if(!I.part) //implanted as a nonhuman, won't have one. + I.part = /datum/organ/external/chest + for (var/datum/organ/external/affected in H.organs) + if(!istype(affected, I.part)) continue + affected.implants += I + +/mob/living/carbon/proc/dropBorers(var/gibbed = null) + var/mob/living/simple_animal/borer/B = has_brain_worms() + if(B) + B.detach() + if(gibbed) + to_chat(B, "As your host is violently destroyed, so are you!") + B.ghostize(0) + qdel(B) + else + to_chat(B, "You're forcefully popped out of your host!") + +/mob/living/carbon/proc/transferBorers(mob/living/target) + var/mob/living/simple_animal/borer/B = has_brain_worms() + if(B) + B.detach() + if(iscarbon(target)) + var/mob/living/carbon/C = target + B.perform_infestation(C) + else to_chat(B, "You're forcefully popped out of your host!") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 2b5724972fd..85f1d9c8139 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -1,25 +1,25 @@ -/mob/living/carbon/ - gender = MALE - var/list/stomach_contents = list() - var/list/datum/disease2/disease/virus2 = list() - var/antibodies = 0 - - var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm - - var/life_tick = 0 // The amount of life ticks that have processed on this mob. - var/analgesic = 0 // when this is set, the mob isn't affected by shock or pain - // life should decrease this by 1 every tick - // total amount of wounds on mob, used to spread out healing and the like over all wounds - var/number_wounds = 0 - var/obj/item/handcuffed = null //Whether or not the mob is handcuffed - var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this. - //Surgery info - var/datum/surgery_status/op_stage = new/datum/surgery_status - //Active emote/pose - var/pose = null - - var/pulse = PULSE_NORM //current pulse level - - var/hasmouth = 1 // Used for food, etc. - +/mob/living/carbon/ + gender = MALE + var/list/stomach_contents = list() + var/list/datum/disease2/disease/virus2 = list() + var/antibodies = 0 + + var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm + + var/life_tick = 0 // The amount of life ticks that have processed on this mob. + var/analgesic = 0 // when this is set, the mob isn't affected by shock or pain + // life should decrease this by 1 every tick + // total amount of wounds on mob, used to spread out healing and the like over all wounds + var/number_wounds = 0 + var/obj/item/handcuffed = null //Whether or not the mob is handcuffed + var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this. + //Surgery info + var/datum/surgery_status/op_stage = new/datum/surgery_status + //Active emote/pose + var/pose = null + + var/pulse = PULSE_NORM //current pulse level + + var/hasmouth = 1 // Used for food, etc. + var/event/on_emote = new () \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 503f48866d3..e966d225c7c 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -1,123 +1,123 @@ -/mob/living/carbon/human/gib() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - for(var/datum/organ/external/E in src.organs) - if(istype(E, /datum/organ/external/chest) || istype(E, /datum/organ/external/groin)) //Really bad stuff happens when either get removed - continue - //Only make the limb drop if it's not too damaged - if(prob(100 - E.get_damage())) - //Override the current limb status and don't cause an explosion - E.droplimb(1, 1) - - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-h", sleeptime = 15) - hgibs(loc, viruses, dna, species.flesh_color, species.blood_color) - qdel(src) - -/mob/living/carbon/human/dust() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - dropBorers(1) - - if(istype(src, /mob/living/carbon/human/manifested)) - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-hm", sleeptime = 15) - else - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-h", sleeptime = 15) - - new /obj/effect/decal/remains/human(loc) - qdel(src) - -/mob/living/carbon/human/Destroy() - if(mind && species && (species.name == "Manifested") && (mind in ticker.mode.cult))//manifested ghosts are removed from the cult once their bodies are destroyed - ticker.mode.update_cult_icons_removed(mind) - ticker.mode.cult -= mind - ..() - -/mob/living/carbon/human/death(gibbed) - if(stat == DEAD) - return - if(healths) healths.icon_state = "health7" - stat = DEAD - dizziness = 0 - jitteriness = 0 - - //If we have brain worms, dump 'em. - var/mob/living/simple_animal/borer/B=has_brain_worms() - if(B && B.controlling) - to_chat(src, "Your host has died. You reluctantly release control.") - to_chat(B.host_brain, "Just before your body passes, you feel a brief return of sensation. You are now in control... And dead.") - do_release_control(0) - - //Check for heist mode kill count. - if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist) ) ) - //Check for last assailant's mutantrace. - /*if( LAssailant && ( istype( LAssailant,/mob/living/carbon/human ) ) ) - var/mob/living/carbon/human/V = LAssailant - if (V.dna && (V.dna.mutantrace == "vox"))*/ //Not currently feasible due to terrible LAssailant tracking. -// to_chat(world, "Vox kills: [vox_kills]") - vox_kills++ //Bad vox. Shouldn't be killing humans. - if(ishuman(LAssailant)) - var/mob/living/carbon/human/H=LAssailant - if(H.mind) - H.mind.kills += "[name] ([ckey])" - - if(!gibbed) - emote("deathgasp") //Let the world KNOW WE ARE DEAD - - update_canmove() - if(client) blind.layer = 0 - - tod = worldtime2text() //Weasellos time of death patch - if(mind) - mind.store_memory("Time of death: [tod]", 0) - if(!suiciding) //Cowards don't count - score["deadcrew"]++ //Someone died at this point, and that's terrible - if(ticker && ticker.mode) -// world.log << "k" - sql_report_death(src) - ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now - return ..(gibbed) - -/mob/living/carbon/human/proc/makeSkeleton() - if(SKELETON in src.mutations) - return - - if(f_style) - f_style = "Shaved" - if(h_style) - h_style = "Bald" - update_hair(0) - - mutations.Add(SKELETON) - status_flags |= DISFIGURED - update_body(0) - update_mutantrace() - return - -/mob/living/carbon/human/proc/ChangeToHusk() - if(M_HUSK in mutations) - return - if(f_style) - f_style = "Shaved" //We only change the icon_state of the hair datum, so it doesn't mess up their UI/UE - if(h_style) - h_style = "Bald" - update_hair(0) - - mutations.Add(M_HUSK) - status_flags |= DISFIGURED //Makes them unknown without fucking up other stuff like admintools - update_body(0) - update_mutantrace() - vessel.remove_reagent("blood",vessel.get_reagent_amount("blood")) - return - -/mob/living/carbon/human/proc/Drain() - ChangeToHusk() - mutations |= M_NOCLONE - return +/mob/living/carbon/human/gib() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + for(var/datum/organ/external/E in src.organs) + if(istype(E, /datum/organ/external/chest) || istype(E, /datum/organ/external/groin)) //Really bad stuff happens when either get removed + continue + //Only make the limb drop if it's not too damaged + if(prob(100 - E.get_damage())) + //Override the current limb status and don't cause an explosion + E.droplimb(1, 1) + + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-h", sleeptime = 15) + hgibs(loc, viruses, dna, species.flesh_color, species.blood_color) + qdel(src) + +/mob/living/carbon/human/dust() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + dropBorers(1) + + if(istype(src, /mob/living/carbon/human/manifested)) + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-hm", sleeptime = 15) + else + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-h", sleeptime = 15) + + new /obj/effect/decal/remains/human(loc) + qdel(src) + +/mob/living/carbon/human/Destroy() + if(mind && species && (species.name == "Manifested") && (mind in ticker.mode.cult))//manifested ghosts are removed from the cult once their bodies are destroyed + ticker.mode.update_cult_icons_removed(mind) + ticker.mode.cult -= mind + ..() + +/mob/living/carbon/human/death(gibbed) + if(stat == DEAD) + return + if(healths) healths.icon_state = "health7" + stat = DEAD + dizziness = 0 + jitteriness = 0 + + //If we have brain worms, dump 'em. + var/mob/living/simple_animal/borer/B=has_brain_worms() + if(B && B.controlling) + to_chat(src, "Your host has died. You reluctantly release control.") + to_chat(B.host_brain, "Just before your body passes, you feel a brief return of sensation. You are now in control... And dead.") + do_release_control(0) + + //Check for heist mode kill count. + if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist) ) ) + //Check for last assailant's mutantrace. + /*if( LAssailant && ( istype( LAssailant,/mob/living/carbon/human ) ) ) + var/mob/living/carbon/human/V = LAssailant + if (V.dna && (V.dna.mutantrace == "vox"))*/ //Not currently feasible due to terrible LAssailant tracking. +// to_chat(world, "Vox kills: [vox_kills]") + vox_kills++ //Bad vox. Shouldn't be killing humans. + if(ishuman(LAssailant)) + var/mob/living/carbon/human/H=LAssailant + if(H.mind) + H.mind.kills += "[name] ([ckey])" + + if(!gibbed) + emote("deathgasp") //Let the world KNOW WE ARE DEAD + + update_canmove() + if(client) blind.layer = 0 + + tod = worldtime2text() //Weasellos time of death patch + if(mind) + mind.store_memory("Time of death: [tod]", 0) + if(!suiciding) //Cowards don't count + score["deadcrew"]++ //Someone died at this point, and that's terrible + if(ticker && ticker.mode) +// world.log << "k" + sql_report_death(src) + ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now + return ..(gibbed) + +/mob/living/carbon/human/proc/makeSkeleton() + if(SKELETON in src.mutations) + return + + if(f_style) + f_style = "Shaved" + if(h_style) + h_style = "Bald" + update_hair(0) + + mutations.Add(SKELETON) + status_flags |= DISFIGURED + update_body(0) + update_mutantrace() + return + +/mob/living/carbon/human/proc/ChangeToHusk() + if(M_HUSK in mutations) + return + if(f_style) + f_style = "Shaved" //We only change the icon_state of the hair datum, so it doesn't mess up their UI/UE + if(h_style) + h_style = "Bald" + update_hair(0) + + mutations.Add(M_HUSK) + status_flags |= DISFIGURED //Makes them unknown without fucking up other stuff like admintools + update_body(0) + update_mutantrace() + vessel.remove_reagent("blood",vessel.get_reagent_amount("blood")) + return + +/mob/living/carbon/human/proc/Drain() + ChangeToHusk() + mutations |= M_NOCLONE + return diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index a35e7ad0879..31ffcc1aa7a 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -1,786 +1,786 @@ -/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null, var/auto) - var/param = null - if(timestopped) return //under effects of time magick - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - //var/m_type = VISIBLE - - for (var/obj/item/weapon/implant/I in src) - if (I.implanted) - I.trigger(act, src) - - if(src.stat == 2.0 && (act != "deathgasp")) - return - - if(act == "oath" && src.miming) - src.miming = 0 - for(var/spell/aoe_turf/conjure/forcewall/mime/spell in src.spell_list) - src.remove_spell(spell) - qdel(spell) - message_admins("[src.name] ([src.ckey]) has broken their oath of silence. (JMP)") +/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null, var/auto) + var/param = null + if(timestopped) return //under effects of time magick + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + + var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) + //var/m_type = VISIBLE + + for (var/obj/item/weapon/implant/I in src) + if (I.implanted) + I.trigger(act, src) + + if(src.stat == 2.0 && (act != "deathgasp")) + return + + if(act == "oath" && src.miming) + src.miming = 0 + for(var/spell/aoe_turf/conjure/forcewall/mime/spell in src.spell_list) + src.remove_spell(spell) + qdel(spell) + message_admins("[src.name] ([src.ckey]) has broken their oath of silence. (JMP)") to_chat(src, "An unsettling feeling surrounds you...") - return - - switch(act) - if ("airguitar") - if (!src.restrained()) - message = "[src] is strumming the air and headbanging like a safari chimp." - m_type = VISIBLE - - if ("blink") - message = "[src] blinks." - m_type = VISIBLE - - if ("blink_r") - message = "[src] blinks rapidly." - m_type = VISIBLE - - if ("bow") - if (!src.locked_to) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] bows to [param]." - else - message = "[src] bows." - m_type = VISIBLE - - if ("custom") - var/input = copytext(sanitize(input("Choose an emote to display.") as text|null),1,MAX_MESSAGE_LEN) - if (!input) - return - var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") - if (input2 == "Visible") - m_type = VISIBLE - else if (input2 == "Hearable") - if (src.miming) - return - m_type = HEARABLE - else - alert("Unable to use this emote, must be either hearable or visible.") - return - return custom_emote(m_type, message) - - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) + return + + switch(act) + if ("airguitar") + if (!src.restrained()) + message = "[src] is strumming the air and headbanging like a safari chimp." + m_type = VISIBLE + + if ("blink") + message = "[src] blinks." + m_type = VISIBLE + + if ("blink_r") + message = "[src] blinks rapidly." + m_type = VISIBLE + + if ("bow") + if (!src.locked_to) + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] bows to [param]." + else + message = "[src] bows." + m_type = VISIBLE + + if ("custom") + var/input = copytext(sanitize(input("Choose an emote to display.") as text|null),1,MAX_MESSAGE_LEN) + if (!input) + return + var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") + if (input2 == "Visible") + m_type = VISIBLE + else if (input2 == "Hearable") + if (src.miming) + return + m_type = HEARABLE + else + alert("Unable to use this emote, must be either hearable or visible.") + return + return custom_emote(m_type, message) + + if ("me") + if(silent) + return + if (src.client) + if (client.prefs.muted & MUTE_IC) to_chat(src, "You cannot send IC messages (muted).") - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - if ("salute") - if (!src.locked_to) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] salutes to [param]." - else - message = "[src] salutes." - m_type = VISIBLE - - if ("choke") - if(miming) - message = "[src] clutches his throat desperately!" - m_type = VISIBLE - else - if (!muzzled) - message = "[src] chokes!" - m_type = HEARABLE - else - message = "[src] makes a strong noise." - m_type = HEARABLE - - if ("clap") - if (!src.restrained()) - message = "[src] claps." - m_type = HEARABLE - if(miming) - m_type = VISIBLE - if ("flap") - if (!src.restrained()) - message = "[src] flaps \his wings." - m_type = HEARABLE - if(miming) - m_type = VISIBLE - if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece)) - var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit - wings.icon_state = "clownpiece-fly" - update_inv_wear_suit(1) - spawn(5) - wings.icon_state = initial(wings.icon_state) - update_inv_wear_suit(1) - - if ("aflap") - if (!src.restrained()) - message = "[src] flaps \his wings ANGRILY!" - m_type = HEARABLE - if(miming) - m_type = VISIBLE - if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece)) - var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit - wings.icon_state = "clownpiece-fly" - update_inv_wear_suit(1) - spawn(5) - wings.icon_state = initial(wings.icon_state) - update_inv_wear_suit(1) - - if ("drool") - message = "[src] drools." - m_type = VISIBLE - - if ("eyebrow") - message = "[src] raises an eyebrow." - m_type = VISIBLE - - if ("chuckle") - if(miming) - message = "[src] appears to chuckle." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] chuckles." - m_type = HEARABLE - else - message = "[src] makes a noise." - m_type = HEARABLE - - if ("twitch") - message = "[src] twitches violently." - m_type = VISIBLE - - if ("twitch_s") - message = "[src] twitches." - m_type = VISIBLE - - if ("faint") - message = "[src] faints." - if(src.sleeping) - return //Can't faint while asleep - src.sleeping += 10 //Short-short nap - m_type = VISIBLE - - if ("cough") - if(miming) - message = "[src] appears to cough!" - m_type = VISIBLE - else - if (!muzzled) - message = "[src] coughs!" - m_type = HEARABLE - else - message = "[src] makes a strong noise." - m_type = HEARABLE - - if ("frown") - message = "[src] frowns." - m_type = VISIBLE - - if ("nod") - message = "[src] nods." - m_type = VISIBLE - - if ("blush") - message = "[src] blushes." - m_type = VISIBLE - - if ("wave") - message = "[src] waves." - m_type = VISIBLE - - if ("gasp") - if(miming) - message = "[src] appears to be gasping!" - m_type = VISIBLE - else - if (!muzzled) - message = "[src] gasps!" - m_type = HEARABLE - else - message = "[src] makes a weak noise." - m_type = HEARABLE - - if ("deathgasp") - if(M_ELVIS in mutations) - src.emote("fart") - message = "[src] has left the building..." - if(M_HARDCORE in mutations) - message = "[src] whispers with his final breath, 'i told u i was hardcore..'" - else - message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." - m_type = VISIBLE - - if ("giggle") - if(miming) - message = "[src] giggles silently!" - m_type = VISIBLE - else - if (!muzzled) - message = "[src] giggles." - m_type = HEARABLE - else - message = "[src] makes a noise." - m_type = HEARABLE - - if ("glare") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] glares at [param]." - else - message = "[src] glares." - - if ("stare") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] stares at [param]." - else - message = "[src] stares." - - if ("look") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - - if (!M) - param = null - - if (param) - message = "[src] looks at [param]." - else - message = "[src] looks." - m_type = VISIBLE - - if ("grin") - message = "[src] grins." - m_type = VISIBLE - - if ("cry") - if(miming) - message = "[src] cries." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] cries." - m_type = HEARABLE - else - message = "[src] makes a weak noise. \He frowns." - m_type = HEARABLE - - if ("sigh") - if(miming) - message = "[src] sighs." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] sighs." - m_type = HEARABLE - else - message = "[src] makes a weak noise." - m_type = HEARABLE - - if ("laugh") - if(miming) - message = "[src] acts out a laugh." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] laughs." - m_type = HEARABLE - else - message = "[src] makes a noise." - m_type = HEARABLE - - if ("mumble") - message = "[src] mumbles!" - m_type = HEARABLE - if(miming) - m_type = VISIBLE - - if ("grumble") - if(miming) - message = "[src] grumbles!" - m_type = VISIBLE - if (!muzzled) - message = "[src] grumbles!" - m_type = HEARABLE - else - message = "[src] makes a noise." - m_type = HEARABLE - - if ("groan") - if(miming) - message = "[src] appears to groan!" - m_type = VISIBLE - else - if (!muzzled) - message = "[src] groans!" - m_type = HEARABLE - else - message = "[src] makes a loud noise." - m_type = HEARABLE - - if ("moan") - if(miming) - message = "[src] appears to moan!" - m_type = VISIBLE - else - message = "[src] moans!" - m_type = HEARABLE - - if ("johnny") - var/M - if (param) - M = param - if (!M) - param = null - else - if(miming) - message = "[src] takes a drag from a cigarette and blows \"[M]\" out in smoke." - m_type = VISIBLE - else - message = "[src] says, \"[M], please. He had a family.\" [src.name] takes a drag from a cigarette and blows his name out in smoke." - m_type = HEARABLE - - if ("point") - if (!src.restrained()) - var/atom/object_pointed = null - - if(param) - for(var/atom/visible_object as turf | obj | mob in view()) - if(param == visible_object.name) - object_pointed = visible_object - break - - if(isnull(object_pointed)) - message = "[src] points." - else - pointed(object_pointed) - - m_type = VISIBLE - - if ("raise") - if (!src.restrained()) - message = "[src] raises a hand." - m_type = VISIBLE - - if("shake") - message = "[src] shakes \his head." - m_type = VISIBLE - - if ("shrug") - message = "[src] shrugs." - m_type = VISIBLE - - if ("signal") - if (!src.restrained()) - var/t1 = round(text2num(param)) - if (isnum(t1)) - if (t1 <= 5 && (!src.r_hand || !src.l_hand)) - message = "[src] raises [t1] finger\s." - else if (t1 <= 10 && (!src.r_hand && !src.l_hand)) - message = "[src] raises [t1] finger\s." - m_type = VISIBLE - - if ("smile") - message = "[src] smiles." - m_type = VISIBLE - - if ("shiver") - message = "[src] shivers." - m_type = HEARABLE - if(miming) - m_type = VISIBLE - - if ("pale") - message = "[src] goes pale for a second." - m_type = VISIBLE - - if ("tremble") - message = "[src] trembles in fear!" - m_type = VISIBLE - - if ("sneeze") - if (miming) - message = "[src] sneezes." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] sneezes." - m_type = HEARABLE - else - message = "[src] makes a strange noise." - m_type = HEARABLE - - if ("sniff") - message = "[src] sniffs." - m_type = HEARABLE - if(miming) - m_type = VISIBLE - - if ("snore") - if (miming) - message = "[src] sleeps soundly." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] snores." - m_type = HEARABLE - else - message = "[src] makes a noise." - m_type = HEARABLE - - if ("whimper") - if (miming) - message = "[src] appears hurt." - m_type = VISIBLE - else - if (!muzzled) - message = "[src] whimpers." - m_type = HEARABLE - else - message = "[src] makes a weak noise." - m_type = HEARABLE - - if ("wink") - message = "[src] winks." - m_type = VISIBLE - - if ("spin") - message = "[src] spins out of control!" - m_type = VISIBLE - - if ("yawn") - if (!muzzled) - message = "[src] yawns." - m_type = HEARABLE - if(miming) - m_type = VISIBLE - - if ("collapse") - Paralyse(2) - message = "[src] collapses!" - m_type = HEARABLE - if(miming) - m_type = VISIBLE - - if("hug") - m_type = VISIBLE - if (!src.restrained()) - var/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M == src) - M = null - - if (M) - message = "[src] hugs [M]." - else - message = "[src] hugs \himself." - - if ("handshake") - m_type = VISIBLE - if (!src.restrained() && !src.r_hand) - var/mob/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M == src) - M = null - - if (M) - if (M.canmove && !M.r_hand && !M.restrained()) - message = "[src] shakes hands with [M]." - else - message = "[src] holds out \his hand to [M]." - - if("dap") - m_type = VISIBLE - if (!src.restrained()) - var/M = null - if (param) - for (var/mob/A in view(1, null)) - if (param == A.name) - M = A - break - if (M) - message = "[src] gives daps to [M]." - else - message = "[src] sadly can't find anybody to give daps to, and daps \himself. Shameful." - - if ("scream") - if (miming) - message = "[src] acts out a scream!" - m_type = VISIBLE - else - if(!stat) - if (!muzzled) - if (auto == 1) - if(world.time-lastScream >= 30)//prevent scream spam with things like poly spray - message = "[src] screams in agony!" - var/list/screamSound = list('sound/misc/malescream1.ogg', 'sound/misc/malescream2.ogg', 'sound/misc/malescream3.ogg', 'sound/misc/malescream4.ogg', 'sound/misc/malescream5.ogg', 'sound/misc/wilhelm.ogg', 'sound/misc/goofy.ogg') - if (src.gender == FEMALE) //Females have their own screams. Trannys be damned. - screamSound = list('sound/misc/femalescream1.ogg', 'sound/misc/femalescream2.ogg', 'sound/misc/femalescream3.ogg', 'sound/misc/femalescream4.ogg', 'sound/misc/femalescream5.ogg') - var/scream = pick(screamSound)//AUUUUHHHHHHHHOOOHOOHOOHOOOOIIIIEEEEEE - playsound(get_turf(src), scream, 50, 0) - m_type = HEARABLE - lastScream = world.time - else - message = "[src] screams!" - m_type = HEARABLE - else - message = "[src] makes a very loud noise." - m_type = HEARABLE - - // Needed for M_TOXIC_FART - if("fart") - if(src.op_stage.butt != 4) - if(world.time-lastFart >= 400) - for(var/mob/living/M in view(0)) - if(M != src && M.loc == src.loc) - if(!miming) - visible_message("[src] farts in [M]'s face!") - else - visible_message("[src] silently farts in [M]'s face!") - else - continue - /* - - GAY BROKEN SHIT - - for(var/mob/M in view(1)) - if(M != src) - if(!miming) - visible_message("[src] farts in [M]'s face!") - else - visible_message("[src] silently farts in [M]'s face!") - else - continue - - GAY BROKEN SHIT - - */ - - var/list/farts = list( - "farts", - "passes wind", - "toots", - "farts [pick("lightly", "tenderly", "softly", "with care")]", - ) - - if(miming) - farts = list("silently farts.", "acts out a fart.", "lets out a silent fart.") - - var/fart = pick(farts) - - if(!miming) - message = "[src] [fart]." - if(mind && mind.assigned_role == "Clown") - playsound(get_turf(src), pick('sound/items/bikehorn.ogg','sound/items/AirHorn.ogg'), 50, 1) - else - playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1) - else - message = "[src] [fart]" - //Mimes can't fart. - m_type = HEARABLE - var/turf/location = get_turf(src) - var/aoe_range=2 // Default - if(M_SUPER_FART in mutations) - aoe_range+=3 //Was 5 - - // If we're wearing a suit, don't blast or gas those around us. - var/wearing_suit=0 - var/wearing_mask=0 - if(wear_suit && wear_suit.body_parts_covered & LOWER_TORSO) - wearing_suit=1 - if (internal != null && wear_mask && (wear_mask.flags & MASKINTERNALS)) - wearing_mask=1 - - // Process toxic farts first. - if(M_TOXIC_FARTS in mutations) - message="" - playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) - if(wearing_suit) - if(!wearing_mask) + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + if (stat) + return + if(!(message)) + return + return custom_emote(m_type, message) + + if ("salute") + if (!src.locked_to) + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] salutes to [param]." + else + message = "[src] salutes." + m_type = VISIBLE + + if ("choke") + if(miming) + message = "[src] clutches his throat desperately!" + m_type = VISIBLE + else + if (!muzzled) + message = "[src] chokes!" + m_type = HEARABLE + else + message = "[src] makes a strong noise." + m_type = HEARABLE + + if ("clap") + if (!src.restrained()) + message = "[src] claps." + m_type = HEARABLE + if(miming) + m_type = VISIBLE + if ("flap") + if (!src.restrained()) + message = "[src] flaps \his wings." + m_type = HEARABLE + if(miming) + m_type = VISIBLE + if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece)) + var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit + wings.icon_state = "clownpiece-fly" + update_inv_wear_suit(1) + spawn(5) + wings.icon_state = initial(wings.icon_state) + update_inv_wear_suit(1) + + if ("aflap") + if (!src.restrained()) + message = "[src] flaps \his wings ANGRILY!" + m_type = HEARABLE + if(miming) + m_type = VISIBLE + if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece)) + var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit + wings.icon_state = "clownpiece-fly" + update_inv_wear_suit(1) + spawn(5) + wings.icon_state = initial(wings.icon_state) + update_inv_wear_suit(1) + + if ("drool") + message = "[src] drools." + m_type = VISIBLE + + if ("eyebrow") + message = "[src] raises an eyebrow." + m_type = VISIBLE + + if ("chuckle") + if(miming) + message = "[src] appears to chuckle." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] chuckles." + m_type = HEARABLE + else + message = "[src] makes a noise." + m_type = HEARABLE + + if ("twitch") + message = "[src] twitches violently." + m_type = VISIBLE + + if ("twitch_s") + message = "[src] twitches." + m_type = VISIBLE + + if ("faint") + message = "[src] faints." + if(src.sleeping) + return //Can't faint while asleep + src.sleeping += 10 //Short-short nap + m_type = VISIBLE + + if ("cough") + if(miming) + message = "[src] appears to cough!" + m_type = VISIBLE + else + if (!muzzled) + message = "[src] coughs!" + m_type = HEARABLE + else + message = "[src] makes a strong noise." + m_type = HEARABLE + + if ("frown") + message = "[src] frowns." + m_type = VISIBLE + + if ("nod") + message = "[src] nods." + m_type = VISIBLE + + if ("blush") + message = "[src] blushes." + m_type = VISIBLE + + if ("wave") + message = "[src] waves." + m_type = VISIBLE + + if ("gasp") + if(miming) + message = "[src] appears to be gasping!" + m_type = VISIBLE + else + if (!muzzled) + message = "[src] gasps!" + m_type = HEARABLE + else + message = "[src] makes a weak noise." + m_type = HEARABLE + + if ("deathgasp") + if(M_ELVIS in mutations) + src.emote("fart") + message = "[src] has left the building..." + if(M_HARDCORE in mutations) + message = "[src] whispers with his final breath, 'i told u i was hardcore..'" + else + message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." + m_type = VISIBLE + + if ("giggle") + if(miming) + message = "[src] giggles silently!" + m_type = VISIBLE + else + if (!muzzled) + message = "[src] giggles." + m_type = HEARABLE + else + message = "[src] makes a noise." + m_type = HEARABLE + + if ("glare") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] glares at [param]." + else + message = "[src] glares." + + if ("stare") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] stares at [param]." + else + message = "[src] stares." + + if ("look") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + + if (!M) + param = null + + if (param) + message = "[src] looks at [param]." + else + message = "[src] looks." + m_type = VISIBLE + + if ("grin") + message = "[src] grins." + m_type = VISIBLE + + if ("cry") + if(miming) + message = "[src] cries." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] cries." + m_type = HEARABLE + else + message = "[src] makes a weak noise. \He frowns." + m_type = HEARABLE + + if ("sigh") + if(miming) + message = "[src] sighs." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] sighs." + m_type = HEARABLE + else + message = "[src] makes a weak noise." + m_type = HEARABLE + + if ("laugh") + if(miming) + message = "[src] acts out a laugh." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] laughs." + m_type = HEARABLE + else + message = "[src] makes a noise." + m_type = HEARABLE + + if ("mumble") + message = "[src] mumbles!" + m_type = HEARABLE + if(miming) + m_type = VISIBLE + + if ("grumble") + if(miming) + message = "[src] grumbles!" + m_type = VISIBLE + if (!muzzled) + message = "[src] grumbles!" + m_type = HEARABLE + else + message = "[src] makes a noise." + m_type = HEARABLE + + if ("groan") + if(miming) + message = "[src] appears to groan!" + m_type = VISIBLE + else + if (!muzzled) + message = "[src] groans!" + m_type = HEARABLE + else + message = "[src] makes a loud noise." + m_type = HEARABLE + + if ("moan") + if(miming) + message = "[src] appears to moan!" + m_type = VISIBLE + else + message = "[src] moans!" + m_type = HEARABLE + + if ("johnny") + var/M + if (param) + M = param + if (!M) + param = null + else + if(miming) + message = "[src] takes a drag from a cigarette and blows \"[M]\" out in smoke." + m_type = VISIBLE + else + message = "[src] says, \"[M], please. He had a family.\" [src.name] takes a drag from a cigarette and blows his name out in smoke." + m_type = HEARABLE + + if ("point") + if (!src.restrained()) + var/atom/object_pointed = null + + if(param) + for(var/atom/visible_object as turf | obj | mob in view()) + if(param == visible_object.name) + object_pointed = visible_object + break + + if(isnull(object_pointed)) + message = "[src] points." + else + pointed(object_pointed) + + m_type = VISIBLE + + if ("raise") + if (!src.restrained()) + message = "[src] raises a hand." + m_type = VISIBLE + + if("shake") + message = "[src] shakes \his head." + m_type = VISIBLE + + if ("shrug") + message = "[src] shrugs." + m_type = VISIBLE + + if ("signal") + if (!src.restrained()) + var/t1 = round(text2num(param)) + if (isnum(t1)) + if (t1 <= 5 && (!src.r_hand || !src.l_hand)) + message = "[src] raises [t1] finger\s." + else if (t1 <= 10 && (!src.r_hand && !src.l_hand)) + message = "[src] raises [t1] finger\s." + m_type = VISIBLE + + if ("smile") + message = "[src] smiles." + m_type = VISIBLE + + if ("shiver") + message = "[src] shivers." + m_type = HEARABLE + if(miming) + m_type = VISIBLE + + if ("pale") + message = "[src] goes pale for a second." + m_type = VISIBLE + + if ("tremble") + message = "[src] trembles in fear!" + m_type = VISIBLE + + if ("sneeze") + if (miming) + message = "[src] sneezes." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] sneezes." + m_type = HEARABLE + else + message = "[src] makes a strange noise." + m_type = HEARABLE + + if ("sniff") + message = "[src] sniffs." + m_type = HEARABLE + if(miming) + m_type = VISIBLE + + if ("snore") + if (miming) + message = "[src] sleeps soundly." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] snores." + m_type = HEARABLE + else + message = "[src] makes a noise." + m_type = HEARABLE + + if ("whimper") + if (miming) + message = "[src] appears hurt." + m_type = VISIBLE + else + if (!muzzled) + message = "[src] whimpers." + m_type = HEARABLE + else + message = "[src] makes a weak noise." + m_type = HEARABLE + + if ("wink") + message = "[src] winks." + m_type = VISIBLE + + if ("spin") + message = "[src] spins out of control!" + m_type = VISIBLE + + if ("yawn") + if (!muzzled) + message = "[src] yawns." + m_type = HEARABLE + if(miming) + m_type = VISIBLE + + if ("collapse") + Paralyse(2) + message = "[src] collapses!" + m_type = HEARABLE + if(miming) + m_type = VISIBLE + + if("hug") + m_type = VISIBLE + if (!src.restrained()) + var/M = null + if (param) + for (var/mob/A in view(1, null)) + if (param == A.name) + M = A + break + if (M == src) + M = null + + if (M) + message = "[src] hugs [M]." + else + message = "[src] hugs \himself." + + if ("handshake") + m_type = VISIBLE + if (!src.restrained() && !src.r_hand) + var/mob/M = null + if (param) + for (var/mob/A in view(1, null)) + if (param == A.name) + M = A + break + if (M == src) + M = null + + if (M) + if (M.canmove && !M.r_hand && !M.restrained()) + message = "[src] shakes hands with [M]." + else + message = "[src] holds out \his hand to [M]." + + if("dap") + m_type = VISIBLE + if (!src.restrained()) + var/M = null + if (param) + for (var/mob/A in view(1, null)) + if (param == A.name) + M = A + break + if (M) + message = "[src] gives daps to [M]." + else + message = "[src] sadly can't find anybody to give daps to, and daps \himself. Shameful." + + if ("scream") + if (miming) + message = "[src] acts out a scream!" + m_type = VISIBLE + else + if(!stat) + if (!muzzled) + if (auto == 1) + if(world.time-lastScream >= 30)//prevent scream spam with things like poly spray + message = "[src] screams in agony!" + var/list/screamSound = list('sound/misc/malescream1.ogg', 'sound/misc/malescream2.ogg', 'sound/misc/malescream3.ogg', 'sound/misc/malescream4.ogg', 'sound/misc/malescream5.ogg', 'sound/misc/wilhelm.ogg', 'sound/misc/goofy.ogg') + if (src.gender == FEMALE) //Females have their own screams. Trannys be damned. + screamSound = list('sound/misc/femalescream1.ogg', 'sound/misc/femalescream2.ogg', 'sound/misc/femalescream3.ogg', 'sound/misc/femalescream4.ogg', 'sound/misc/femalescream5.ogg') + var/scream = pick(screamSound)//AUUUUHHHHHHHHOOOHOOHOOHOOOOIIIIEEEEEE + playsound(get_turf(src), scream, 50, 0) + m_type = HEARABLE + lastScream = world.time + else + message = "[src] screams!" + m_type = HEARABLE + else + message = "[src] makes a very loud noise." + m_type = HEARABLE + + // Needed for M_TOXIC_FART + if("fart") + if(src.op_stage.butt != 4) + if(world.time-lastFart >= 400) + for(var/mob/living/M in view(0)) + if(M != src && M.loc == src.loc) + if(!miming) + visible_message("[src] farts in [M]'s face!") + else + visible_message("[src] silently farts in [M]'s face!") + else + continue + /* + + GAY BROKEN SHIT + + for(var/mob/M in view(1)) + if(M != src) + if(!miming) + visible_message("[src] farts in [M]'s face!") + else + visible_message("[src] silently farts in [M]'s face!") + else + continue + + GAY BROKEN SHIT + + */ + + var/list/farts = list( + "farts", + "passes wind", + "toots", + "farts [pick("lightly", "tenderly", "softly", "with care")]", + ) + + if(miming) + farts = list("silently farts.", "acts out a fart.", "lets out a silent fart.") + + var/fart = pick(farts) + + if(!miming) + message = "[src] [fart]." + if(mind && mind.assigned_role == "Clown") + playsound(get_turf(src), pick('sound/items/bikehorn.ogg','sound/items/AirHorn.ogg'), 50, 1) + else + playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1) + else + message = "[src] [fart]" + //Mimes can't fart. + m_type = HEARABLE + var/turf/location = get_turf(src) + var/aoe_range=2 // Default + if(M_SUPER_FART in mutations) + aoe_range+=3 //Was 5 + + // If we're wearing a suit, don't blast or gas those around us. + var/wearing_suit=0 + var/wearing_mask=0 + if(wear_suit && wear_suit.body_parts_covered & LOWER_TORSO) + wearing_suit=1 + if (internal != null && wear_mask && (wear_mask.flags & MASKINTERNALS)) + wearing_mask=1 + + // Process toxic farts first. + if(M_TOXIC_FARTS in mutations) + message="" + playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) + if(wearing_suit) + if(!wearing_mask) to_chat(src, "You gas yourself!") - reagents.add_reagent("space_drugs", rand(10,50)) - else - // Was /turf/, now /mob/ - for(var/mob/living/M in view(location,aoe_range)) - if (M.internal != null && M.wear_mask && (M.wear_mask.flags & MASKINTERNALS)) - continue - if(!airborne_can_reach(location,get_turf(M),aoe_range)) - continue - // Now, we don't have this: - //new /obj/effects/fart_cloud(T,L) - // But: - // <[REDACTED]> so, what it does is...imagine a 3x3 grid with the person in the center. When someone uses the emote *fart (it's not a spell style ability and has no cooldown), then anyone in the 8 tiles AROUND the person who uses it - // <[REDACTED]> gets between 1 and 10 units of jenkem added to them...we obviously don't have Jenkem, but Space Drugs do literally the same exact thing as Jenkem - // <[REDACTED]> the user, of course, isn't impacted because it's not an actual smoke cloud - // So, let's give 'em space drugs. - if(M.reagents) - M.reagents.add_reagent("space_drugs",rand(1,50)) - /* - var/datum/effect/effect/system/smoke_spread/chem/fart/S = new /datum/effect/effect/system/smoke_spread/chem/fart - S.attach(location) - S.set_up(src, 10, 0, location) - spawn(0) - S.start() - sleep(10) - S.start() - */ - if(M_SUPER_FART in mutations) - message="" - playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3) - visible_message("[name] hunches down and grits their teeth!") - if(do_after(usr,usr,30)) - visible_message("[name] unleashes a [pick("tremendous","gigantic","colossal")] fart!","You hear a [pick("tremendous","gigantic","colossal")] fart.") - playsound(location, 'sound/effects/superfart.ogg', 50, 0) - if(!wearing_suit) - for(var/mob/living/V in view(src,aoe_range)) - if(!airborne_can_reach(location,get_turf(V),aoe_range)) continue - shake_camera(V,10,5) - if (V == src) - continue + reagents.add_reagent("space_drugs", rand(10,50)) + else + // Was /turf/, now /mob/ + for(var/mob/living/M in view(location,aoe_range)) + if (M.internal != null && M.wear_mask && (M.wear_mask.flags & MASKINTERNALS)) + continue + if(!airborne_can_reach(location,get_turf(M),aoe_range)) + continue + // Now, we don't have this: + //new /obj/effects/fart_cloud(T,L) + // But: + // <[REDACTED]> so, what it does is...imagine a 3x3 grid with the person in the center. When someone uses the emote *fart (it's not a spell style ability and has no cooldown), then anyone in the 8 tiles AROUND the person who uses it + // <[REDACTED]> gets between 1 and 10 units of jenkem added to them...we obviously don't have Jenkem, but Space Drugs do literally the same exact thing as Jenkem + // <[REDACTED]> the user, of course, isn't impacted because it's not an actual smoke cloud + // So, let's give 'em space drugs. + if(M.reagents) + M.reagents.add_reagent("space_drugs",rand(1,50)) + /* + var/datum/effect/effect/system/smoke_spread/chem/fart/S = new /datum/effect/effect/system/smoke_spread/chem/fart + S.attach(location) + S.set_up(src, 10, 0, location) + spawn(0) + S.start() + sleep(10) + S.start() + */ + if(M_SUPER_FART in mutations) + message="" + playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3) + visible_message("[name] hunches down and grits their teeth!") + if(do_after(usr,usr,30)) + visible_message("[name] unleashes a [pick("tremendous","gigantic","colossal")] fart!","You hear a [pick("tremendous","gigantic","colossal")] fart.") + playsound(location, 'sound/effects/superfart.ogg', 50, 0) + if(!wearing_suit) + for(var/mob/living/V in view(src,aoe_range)) + if(!airborne_can_reach(location,get_turf(V),aoe_range)) continue + shake_camera(V,10,5) + if (V == src) + continue to_chat(V, "You're sent flying!") - V.Weaken(5) // why the hell was this set to 12 christ - step_away(V,location,15) - step_away(V,location,15) - step_away(V,location,15) - else + V.Weaken(5) // why the hell was this set to 12 christ + step_away(V,location,15) + step_away(V,location,15) + step_away(V,location,15) + else to_chat(usr, "You were interrupted and couldn't fart! Rude!") - - lastFart=world.time - - var/obj/item/weapon/storage/bible/B = locate(/obj/item/weapon/storage/bible) in src.loc - if(B) - if(iscult(src)) + + lastFart=world.time + + var/obj/item/weapon/storage/bible/B = locate(/obj/item/weapon/storage/bible) in src.loc + if(B) + if(iscult(src)) to_chat(src, "Nar-Sie shields you from [B.deity_name]'s wrath!") - else - if(istype(src.head, /obj/item/clothing/head/fedora)) + else + if(istype(src.head, /obj/item/clothing/head/fedora)) to_chat(src, "You feel incredibly enlightened after farting on [B]!") - var/obj/item/clothing/head/fedora/F = src.head - F.tip_fedora() - else + var/obj/item/clothing/head/fedora/F = src.head + F.tip_fedora() + else to_chat(src, "You feel incredibly guilty for farting on [B]!") - if(prob(80)) //20% chance to escape God's justice - spawn(rand(10,30)) - if(src && B) - src.show_message("[B.deity_name] says, \"Thou hast angered me, mortal!\"",2) - - sleep(10) - - if(src && B) + if(prob(80)) //20% chance to escape God's justice + spawn(rand(10,30)) + if(src && B) + src.show_message("[B.deity_name] says, \"Thou hast angered me, mortal!\"",2) + + sleep(10) + + if(src && B) to_chat(src, "You were disintegrated by [B.deity_name]'s bolt of lightning.") - src.attack_log += text("\[[time_stamp()]\] Farted on a bible and suffered [B.deity_name]'s wrath.") - - explosion(get_turf(src),-1,-1,1,5) //Tiny explosion with flash - - src.dust() - else - message = "[src] strains, and nothing happens." - m_type = VISIBLE - else - message = "[src] lets out a [pick("disgusting","revolting","horrible","strangled","god awful")] noise out of \his mutilated asshole." - m_type = HEARABLE - if ("help") + src.attack_log += text("\[[time_stamp()]\] Farted on a bible and suffered [B.deity_name]'s wrath.") + + explosion(get_turf(src),-1,-1,1,5) //Tiny explosion with flash + + src.dust() + else + message = "[src] strains, and nothing happens." + m_type = VISIBLE + else + message = "[src] lets out a [pick("disgusting","revolting","horrible","strangled","god awful")] noise out of \his mutilated asshole." + m_type = HEARABLE + if ("help") to_chat(src, "blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough,\ncry, custom, deathgasp, drool, eyebrow, frown, gasp, giggle, groan, grumble, handshake, hug-(none)/mob, glare-(none)/mob,\ngrin, laugh, look-(none)/mob, moan, mumble, nod, pale, point-atom, raise, salute, shake, shiver, shrug,\nsigh, signal-#1-10, smile, sneeze, sniff, snore, stare-(none)/mob, tremble, twitch, twitch_s, whimper,\nwink, yawn") - - else + + else to_chat(src, "Unusable emote '[act]'. Say *help for a list.") - - - - - - if (message) - log_emote("[name]/[key] (@[x],[y],[z]): [message]") - - //Hearing gasp and such every five seconds is not good emotes were not global for a reason. - // Maybe some people are okay with that. - - for(var/mob/M in dead_mob_list) - if(!M.client || istype(M, /mob/new_player)) - continue //skip monkeys, leavers and new players - if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - // Borers, other internal things. - INVOKE_EVENT(on_emote, list("mob"=src,"message"=message,"m_type"=m_type)) - - if (m_type & 1) - for (var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - else if (m_type & 2) - for (var/mob/O in hearers(src.loc, null)) - O.show_message(message, m_type) - -/mob/living/carbon/human/verb/pose() - set name = "Set Pose" - set desc = "Sets a description which will be shown when someone examines you." - set category = "IC" - - pose = copytext(sanitize(input(usr, "This is [src]. \He is...", "Pose", null) as text), 1, MAX_MESSAGE_LEN) - -/mob/living/carbon/human/verb/set_flavor() - set name = "Set Flavour Text" - set desc = "Sets an extended description of your character's features." - set category = "IC" - - if(appearance_isbanned(usr)) + + + + + + if (message) + log_emote("[name]/[key] (@[x],[y],[z]): [message]") + + //Hearing gasp and such every five seconds is not good emotes were not global for a reason. + // Maybe some people are okay with that. + + for(var/mob/M in dead_mob_list) + if(!M.client || istype(M, /mob/new_player)) + continue //skip monkeys, leavers and new players + if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) + M.show_message(message) + + // Borers, other internal things. + INVOKE_EVENT(on_emote, list("mob"=src,"message"=message,"m_type"=m_type)) + + if (m_type & 1) + for (var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + else if (m_type & 2) + for (var/mob/O in hearers(src.loc, null)) + O.show_message(message, m_type) + +/mob/living/carbon/human/verb/pose() + set name = "Set Pose" + set desc = "Sets a description which will be shown when someone examines you." + set category = "IC" + + pose = copytext(sanitize(input(usr, "This is [src]. \He is...", "Pose", null) as text), 1, MAX_MESSAGE_LEN) + +/mob/living/carbon/human/verb/set_flavor() + set name = "Set Flavour Text" + set desc = "Sets an extended description of your character's features." + set category = "IC" + + if(appearance_isbanned(usr)) to_chat(src, "You are appearance banned!") - flavor_text = null - return - else - flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1) + flavor_text = null + return + else + flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 01dc2ddbc58..9156c605633 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -1,516 +1,516 @@ -#define JITTER_MEDIUM 100 -#define JITTER_HIGH 300 - -/mob/living/carbon/human/examine(mob/user) - var/list/obscured = check_obscured_slots() - var/skipgloves = 0 - //var/skipsuitstorage = 0 - var/skipjumpsuit = 0 - var/skipshoes = 0 - var/skipmask = 0 - var/skipface = 0 - -/* - - - - //exosuits and helmets obscure our view and stuff. - if(wear_suit) - skipgloves = wear_suit.flags_inv & HIDEGLOVES - skipsuitstorage = wear_suit.flags_inv & HIDESUITSTORAGE - skipjumpsuit = wear_suit.flags_inv & HIDEJUMPSUIT - skipshoes = wear_suit.flags_inv & HIDESHOES - - if(head) - skipmask = head.flags_inv & HIDEMASK - skipeyes = head.flags_inv & HIDEEYES - skipears = head.flags_inv & HIDEEARS - skipface = head.flags_inv & HIDEFACE - - -*/ - - if(wear_mask) - skipface |= check_hidden_head_flags(HIDEFACE) - - // crappy hacks because you can't do \his[src] etc. I'm sorry this proc is so unreadable, blame the text macros :< - var/t_He = "It" //capitalised for use at the start of each line. - var/t_his = "its" - var/t_him = "it" - var/t_has = "has" - var/t_is = "is" - - var/msg = "*---------*\nThis is " - - if( slot_w_uniform in obscured && skipface ) - t_He = "They" - t_his = "their" - t_him = "them" - t_has = "have" - t_is = "are" - else - if(icon) - msg += "\icon[src] " //note, should we ever go back to runtime-generated icons (please don't), you will need to change this to \icon[icon] to prevent crashes. - switch(gender) - if(MALE) - t_He = "He" - t_his = "his" - t_him = "him" - if(FEMALE) - t_He = "She" - t_his = "her" - t_him = "her" - - var/distance = get_dist(user,src) - if(istype(user, /mob/dead/observer) || user.stat == 2) // ghosts can see anything - distance = 1 - - msg += "[src.name]!\n" - - //uniform - if(w_uniform && !(slot_w_uniform in obscured)) - //Ties - var/tie_msg - if(istype(w_uniform,/obj/item/clothing/under)) - var/obj/item/clothing/under/U = w_uniform - for(var/obj/item/clothing/accessory/accessory in U.accessories) - tie_msg += " with \icon[accessory] \a [accessory]" - - if(w_uniform.blood_DNA && w_uniform.blood_DNA.len) - msg += "[t_He] [t_is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name][tie_msg]!\n" - else - msg += "[t_He] [t_is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].\n" - - //head - if(head) - if(head.blood_DNA && head.blood_DNA.len) - msg += "[t_He] [t_is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head!\n" - else - msg += "[t_He] [t_is] wearing \icon[head] \a [head] on [t_his] head.\n" - - //suit/armour - if(wear_suit) - if(wear_suit.blood_DNA && wear_suit.blood_DNA.len) - msg += "[t_He] [t_is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]!\n" - else - msg += "[t_He] [t_is] wearing \icon[wear_suit] \a [wear_suit].\n" - - //suit/armour storage - if(s_store) - if(s_store.blood_DNA && s_store.blood_DNA.len) - msg += "[t_He] [t_is] carrying \icon[s_store] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]!\n" - else - msg += "[t_He] [t_is] carrying \icon[s_store] \a [s_store] on [t_his] [wear_suit.name].\n" - - //back - if(back) - if(back.blood_DNA && back.blood_DNA.len) - msg += "[t_He] [t_has] \icon[back] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back.\n" - else - msg += "[t_He] [t_has] \icon[back] \a [back] on [t_his] back.\n" - - //left hand - if(l_hand) - if(l_hand.blood_DNA && l_hand.blood_DNA.len) - msg += "[t_He] [t_is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in [t_his] left hand!\n" - else - msg += "[t_He] [t_is] holding \icon[l_hand] \a [l_hand] in [t_his] left hand.\n" - - //right hand - if(r_hand) - if(r_hand.blood_DNA && r_hand.blood_DNA.len) - msg += "[t_He] [t_is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in [t_his] right hand!\n" - else - msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n" - - //gloves - if(gloves && !(slot_gloves in obscured)) - if(gloves.blood_DNA && gloves.blood_DNA.len) - msg += "[t_He] [t_has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands!\n" - else - msg += "[t_He] [t_has] \icon[gloves] \a [gloves] on [t_his] hands.\n" - else if(blood_DNA && blood_DNA.len) - msg += "[t_He] [t_has] blood-stained hands!\n" - - //handcuffed? - - //handcuffed? - if(handcuffed) - if(istype(handcuffed, /obj/item/weapon/handcuffs/cable)) - msg += "[t_He] [t_is] \icon[handcuffed] restrained with cable!\n" - else - msg += "[t_He] [t_is] \icon[handcuffed] handcuffed!\n" - - //belt - if(belt) - if(belt.blood_DNA && belt.blood_DNA.len) - msg += "[t_He] [t_has] \icon[belt] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist!\n" - else - msg += "[t_He] [t_has] \icon[belt] \a [belt] about [t_his] waist.\n" - - //shoes - if(shoes && !(slot_shoes in obscured)) - if(shoes.blood_DNA && shoes.blood_DNA.len) - msg += "[t_He] [t_is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet!\n" - else - msg += "[t_He] [t_is] wearing \icon[shoes] \a [shoes] on [t_his] feet.\n" - - //mask - if(wear_mask && !(slot_wear_mask in obscured)) - if(wear_mask.blood_DNA && wear_mask.blood_DNA.len) - msg += "[t_He] [t_has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] on [t_his] face!\n" - else - msg += "[t_He] [t_has] \icon[wear_mask] \a [wear_mask] on [t_his] face.\n" - - //eyes - if(glasses && !(slot_glasses in obscured)) - if(glasses.blood_DNA && glasses.blood_DNA.len) - msg += "[t_He] [t_has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes!\n" - else - msg += "[t_He] [t_has] \icon[glasses] \a [glasses] covering [t_his] eyes.\n" - - //ears - if(ears && !(slot_ears in obscured)) - msg += "[t_He] [t_has] \icon[ears] \a [ears] on [t_his] ears.\n" - - //ID - if(wear_id) - /*var/id - if(istype(wear_id, /obj/item/device/pda)) - var/obj/item/device/pda/pda = wear_id - id = pda.owner - else if(istype(wear_id, /obj/item/weapon/card/id)) //just in case something other than a PDA/ID card somehow gets in the ID slot :[ - var/obj/item/weapon/card/id/idcard = wear_id - id = idcard.registered_name - if(id && (id != real_name) && (get_dist(src, user) <= 1) && prob(10)) - msg += "[t_He] [t_is] wearing \icon[wear_id] \a [wear_id] yet something doesn't seem right...\n" - else*/ - msg += "[t_He] [t_is] wearing \icon[wear_id] \a [wear_id].\n" - - switch(jitteriness) - if(JITTER_HIGH to INFINITY) - msg += "[t_He] [t_is] convulsing violently!\n" - if(JITTER_MEDIUM to JITTER_HIGH) - msg += "[t_He] [t_is] extremely jittery.\n" - if(1 to JITTER_MEDIUM) - msg += "[t_He] [t_is] twitching ever so slightly.\n" - - //splints - for(var/organ in list("l_leg","r_leg","l_arm","r_arm")) - var/datum/organ/external/o = get_organ(organ) - if(o && o.status & ORGAN_SPLINTED) - msg += "[t_He] [t_has] a splint on [t_his] [o.display_name]!\n" - - if(suiciding) - msg += "[t_He] appears to have committed suicide... there is no hope of recovery.\n" - - if(M_DWARF in mutations) - msg += "[t_He] [t_is] a short, sturdy creature fond of drink and industry.\n" - - if (isUnconscious()) - msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" - if((isDead() || src.health < config.health_threshold_crit) && distance <= 3) - msg += "[t_He] does not appear to be breathing.\n" - - if(ishuman(user) && !isUnconscious(user) && distance <= 1) - user.visible_message("[user] checks [src]'s pulse.") - - spawn(15) - if(user && distance <= 1 && !isUnconscious(user)) - if(pulse == PULSE_NONE || (status_flags & FAKEDEATH)) - to_chat(user, "[t_He] has no pulse[src.client ? "" : " and [t_his] soul has departed"]...") - else - to_chat(user, "[t_He] has a pulse!") - - msg += "" - - if(nutrition < 100) - if(hardcore_mode_on && eligible_for_hardcore_mode(src)) - msg += "[t_He] [t_is] severely malnourished.\n" - else - msg += "[t_He] [t_is] severely malnourished.\n" - else if(nutrition >= 500) - if(user.nutrition < 100) - msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" - else - msg += "[t_He] [t_is] quite chubby.\n" - - msg += "" - - if(has_brain() && stat != DEAD) - if(!key) - msg += "[t_He] [t_is] totally catatonic. The stresses of life in deep space must have been too much for [t_him]. Any recovery is unlikely.\n" - else if(!client) - msg += "[t_He] [t_has] a vacant, braindead stare...\n" - - var/list/wound_flavor_text = list() - var/list/is_destroyed = list() - var/list/is_bleeding = list() - for(var/datum/organ/external/temp in organs) - if(temp) - if(temp.status & ORGAN_DESTROYED) - is_destroyed["[temp.display_name]"] = 1 - wound_flavor_text["[temp.display_name]"] = "[t_He] is missing [t_his] [temp.display_name].\n" - continue - if(temp.status & ORGAN_PEG) - if(!(temp.brute_dam + temp.burn_dam)) - wound_flavor_text["[temp.display_name]"] = "[t_He] has a peg [temp.display_name]!\n" - continue - else - wound_flavor_text["[temp.display_name]"] = "[t_He] has a peg [temp.display_name], it has" - if(temp.brute_dam) switch(temp.brute_dam) - if(0 to 20) - wound_flavor_text["[temp.display_name]"] += " some marks" - if(21 to INFINITY) - wound_flavor_text["[temp.display_name]"] += pick(" a lot of damage"," severe cracks and splintering") - if(temp.brute_dam && temp.burn_dam) - wound_flavor_text["[temp.display_name]"] += " and" - if(temp.burn_dam) switch(temp.burn_dam) - if(0 to 20) - wound_flavor_text["[temp.display_name]"] += " some burns" - if(21 to INFINITY) - wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe charring") - wound_flavor_text["[temp.display_name]"] += "!\n" - else if(temp.status & ORGAN_ROBOT) - if(!(temp.brute_dam + temp.burn_dam)) - wound_flavor_text["[temp.display_name]"] = "[t_He] has a robot [temp.display_name]!\n" - continue - else - wound_flavor_text["[temp.display_name]"] = "[t_He] has a robot [temp.display_name], it has" - if(temp.brute_dam) switch(temp.brute_dam) - if(0 to 20) - wound_flavor_text["[temp.display_name]"] += " some dents" - if(21 to INFINITY) - wound_flavor_text["[temp.display_name]"] += pick(" a lot of dents"," severe denting") - if(temp.brute_dam && temp.burn_dam) - wound_flavor_text["[temp.display_name]"] += " and" - if(temp.burn_dam) switch(temp.burn_dam) - if(0 to 20) - wound_flavor_text["[temp.display_name]"] += " some burns" - if(21 to INFINITY) - wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe melting") - wound_flavor_text["[temp.display_name]"] += "!\n" - else if(temp.wounds.len > 0) - var/list/wound_descriptors = list() - for(var/datum/wound/W in temp.wounds) - if(W.internal && !temp.open) continue // can't see internal wounds - var/this_wound_desc = W.desc - if(W.bleeding()) this_wound_desc = "bleeding [this_wound_desc]" - else if(W.bandaged) this_wound_desc = "bandaged [this_wound_desc]" - if(W.germ_level > 600) this_wound_desc = "badly infected [this_wound_desc]" - else if(W.germ_level > 330) this_wound_desc = "lightly infected [this_wound_desc]" - if(this_wound_desc in wound_descriptors) - wound_descriptors[this_wound_desc] += W.amount - continue - wound_descriptors[this_wound_desc] = W.amount - if(wound_descriptors.len) - var/list/flavor_text = list() - var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\ - "huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area") - for(var/wound in wound_descriptors) - switch(wound_descriptors[wound]) - if(1) - if(!flavor_text.len) - flavor_text += "[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]" - else - flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]" - if(2) - if(!flavor_text.len) - flavor_text += "[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s" - else - flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s" - if(3 to 5) - if(!flavor_text.len) - flavor_text += "[t_He] has several [wound]s" - else - flavor_text += " several [wound]s" - if(6 to INFINITY) - if(!flavor_text.len) - flavor_text += "[t_He] has a bunch of [wound]s" - else - flavor_text += " a ton of [wound]\s" - var/flavor_text_string = "" - for(var/text = 1, text <= flavor_text.len, text++) - if(text == flavor_text.len && flavor_text.len > 1) - flavor_text_string += ", and" - else if(flavor_text.len > 1 && text > 1) - flavor_text_string += "," - flavor_text_string += flavor_text[text] - flavor_text_string += " on [t_his] [temp.display_name].
    " - wound_flavor_text["[temp.display_name]"] = flavor_text_string - else - wound_flavor_text["[temp.display_name]"] = "" - if(temp.status & ORGAN_BLEEDING) - is_bleeding["[temp.display_name]"] = 1 - else - wound_flavor_text["[temp.display_name]"] = "" - - //Handles the text strings being added to the actual description. - //If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext. - var/display_chest = 0 - var/display_shoes = 0 - var/display_gloves = 0 - if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas))))) - msg += wound_flavor_text["head"] - else if(is_bleeding["head"]) - msg += "[src] has blood running down [t_his] face!\n" - if(wound_flavor_text["chest"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you. - msg += wound_flavor_text["chest"] - else if(is_bleeding["chest"]) - display_chest = 1 - if(wound_flavor_text["left arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit))) - msg += wound_flavor_text["left arm"] - else if(is_bleeding["left arm"]) - display_chest = 1 - if(wound_flavor_text["left hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves))) - msg += wound_flavor_text["left hand"] - else if(is_bleeding["left hand"]) - display_gloves = 1 - if(wound_flavor_text["right arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit))) - msg += wound_flavor_text["right arm"] - else if(is_bleeding["right arm"]) - display_chest = 1 - if(wound_flavor_text["right hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves))) - msg += wound_flavor_text["right hand"] - else if(is_bleeding["right hand"]) - display_gloves = 1 - if(wound_flavor_text["groin"] && (is_destroyed["groin"] || (!w_uniform && !skipjumpsuit))) - msg += wound_flavor_text["groin"] - else if(is_bleeding["groin"]) - display_chest = 1 - if(wound_flavor_text["left leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit))) - msg += wound_flavor_text["left leg"] - else if(is_bleeding["left leg"]) - display_chest = 1 - if(wound_flavor_text["left foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes))) - msg += wound_flavor_text["left foot"] - else if(is_bleeding["left foot"]) - display_shoes = 1 - if(wound_flavor_text["right leg"] && (is_destroyed["right leg"] || (!w_uniform && !skipjumpsuit))) - msg += wound_flavor_text["right leg"] - else if(is_bleeding["right leg"]) - display_chest = 1 - if(wound_flavor_text["right foot"]&& (is_destroyed["right foot"] || (!shoes && !skipshoes))) - msg += wound_flavor_text["right foot"] - else if(is_bleeding["right foot"]) - display_shoes = 1 - if(display_chest) - msg += "[src] has blood soaking through from under [t_his] clothing!\n" - if(display_shoes) - msg += "[src] has blood running from [t_his] shoes!\n" - if(display_gloves) - msg += "[src] has blood running from under [t_his] gloves!\n" - - for(var/implant in get_visible_implants(1)) - msg += "[src] has \a [implant] sticking out of [t_his] flesh!\n" - if(digitalcamo) - msg += "[t_He] [t_is] repulsively uncanny!\n" - - if(!is_destroyed["head"]) - if(getBrainLoss() >= 60) - msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" - - if(distance <= 3) - if(!has_brain()) - msg += "[t_He] has had [t_his] brain removed.\n" - - var/butchery = "" //More information about butchering status, check out "code/datums/helper_datums/butchering.dm" - if(butchering_drops && butchering_drops.len) - for(var/datum/butchering_product/B in butchering_drops) - butchery = "[butchery][B.desc_modifier(src, user)]" - if(butchery) - msg += "[butchery]\n" - - if(hasHUD(user,"security")) - var/perpname = "wot" - var/criminal = "None" - - if(wear_id) - var/obj/item/weapon/card/id/I = wear_id.GetID() - if(I) - perpname = I.registered_name - else - perpname = name - else - perpname = name - - if(perpname) - for (var/datum/data/record/E in data_core.general) - if(E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.security) - if(R.fields["id"] == E.fields["id"]) - criminal = R.fields["criminal"] - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\carbon\human\examine.dm:411: msg += "Criminal status: \[[criminal]\]\n" - msg += {"Criminal status: \[[criminal]\] -Security records: \[View\] \[Add comment\]\n"} - // END AUTOFIX - if(hasHUD(user,"medical")) - var/perpname = "wot" - var/medical = "None" - - if(wear_id) - if(istype(wear_id,/obj/item/weapon/card/id)) - perpname = wear_id:registered_name - else if(istype(wear_id,/obj/item/device/pda)) - var/obj/item/device/pda/tempPda = wear_id - perpname = tempPda.owner - else - perpname = src.name - - for (var/datum/data/record/E in data_core.general) - if (E.fields["name"] == perpname) - for (var/datum/data/record/R in data_core.general) - if (R.fields["id"] == E.fields["id"]) - medical = R.fields["p_stat"] - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\carbon\human\examine.dm:433: msg += "Physical status: \[[medical]\]\n" - msg += {"Physical status: \[[medical]\]\n - Medical records: \[View\] \[Add comment\]\n"} - // END AUTOFIX - if(print_flavor_text()) msg += "[print_flavor_text()]\n" - - msg += "*---------*
    " - if (pose) - if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) - pose = addtext(pose,".") //Makes sure all emotes end with a period. - msg += "\n[t_He] is [pose]" - - to_chat(user, msg) - -//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records. -/proc/hasHUD(mob/M as mob, hudtype) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - switch(hudtype) - if("security") - return istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/sechud) - if("medical") - return istype(H.glasses, /obj/item/clothing/glasses/hud/health) - else - return 0 - else if(istype(M, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = M - switch(hudtype) - if("security") - return R.sensor_mode == 1 - if("medical") - return R.sensor_mode == 2 - else - return 0 - else if(istype(M, /mob/living/silicon/pai)) - var/mob/living/silicon/pai/P = M - switch(hudtype) - if("security") - return P.secHUD - if("medical") - return P.medHUD - else - return 0 - -#undef Jitter_Medium -#undef Jitter_High +#define JITTER_MEDIUM 100 +#define JITTER_HIGH 300 + +/mob/living/carbon/human/examine(mob/user) + var/list/obscured = check_obscured_slots() + var/skipgloves = 0 + //var/skipsuitstorage = 0 + var/skipjumpsuit = 0 + var/skipshoes = 0 + var/skipmask = 0 + var/skipface = 0 + +/* + + + + //exosuits and helmets obscure our view and stuff. + if(wear_suit) + skipgloves = wear_suit.flags_inv & HIDEGLOVES + skipsuitstorage = wear_suit.flags_inv & HIDESUITSTORAGE + skipjumpsuit = wear_suit.flags_inv & HIDEJUMPSUIT + skipshoes = wear_suit.flags_inv & HIDESHOES + + if(head) + skipmask = head.flags_inv & HIDEMASK + skipeyes = head.flags_inv & HIDEEYES + skipears = head.flags_inv & HIDEEARS + skipface = head.flags_inv & HIDEFACE + + +*/ + + if(wear_mask) + skipface |= check_hidden_head_flags(HIDEFACE) + + // crappy hacks because you can't do \his[src] etc. I'm sorry this proc is so unreadable, blame the text macros :< + var/t_He = "It" //capitalised for use at the start of each line. + var/t_his = "its" + var/t_him = "it" + var/t_has = "has" + var/t_is = "is" + + var/msg = "*---------*\nThis is " + + if( slot_w_uniform in obscured && skipface ) + t_He = "They" + t_his = "their" + t_him = "them" + t_has = "have" + t_is = "are" + else + if(icon) + msg += "\icon[src] " //note, should we ever go back to runtime-generated icons (please don't), you will need to change this to \icon[icon] to prevent crashes. + switch(gender) + if(MALE) + t_He = "He" + t_his = "his" + t_him = "him" + if(FEMALE) + t_He = "She" + t_his = "her" + t_him = "her" + + var/distance = get_dist(user,src) + if(istype(user, /mob/dead/observer) || user.stat == 2) // ghosts can see anything + distance = 1 + + msg += "[src.name]!\n" + + //uniform + if(w_uniform && !(slot_w_uniform in obscured)) + //Ties + var/tie_msg + if(istype(w_uniform,/obj/item/clothing/under)) + var/obj/item/clothing/under/U = w_uniform + for(var/obj/item/clothing/accessory/accessory in U.accessories) + tie_msg += " with \icon[accessory] \a [accessory]" + + if(w_uniform.blood_DNA && w_uniform.blood_DNA.len) + msg += "[t_He] [t_is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] blood-stained [w_uniform.name][tie_msg]!\n" + else + msg += "[t_He] [t_is] wearing \icon[w_uniform] \a [w_uniform][tie_msg].\n" + + //head + if(head) + if(head.blood_DNA && head.blood_DNA.len) + msg += "[t_He] [t_is] wearing \icon[head] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on [t_his] head!\n" + else + msg += "[t_He] [t_is] wearing \icon[head] \a [head] on [t_his] head.\n" + + //suit/armour + if(wear_suit) + if(wear_suit.blood_DNA && wear_suit.blood_DNA.len) + msg += "[t_He] [t_is] wearing \icon[wear_suit] [wear_suit.gender==PLURAL?"some":"a"] blood-stained [wear_suit.name]!\n" + else + msg += "[t_He] [t_is] wearing \icon[wear_suit] \a [wear_suit].\n" + + //suit/armour storage + if(s_store) + if(s_store.blood_DNA && s_store.blood_DNA.len) + msg += "[t_He] [t_is] carrying \icon[s_store] [s_store.gender==PLURAL?"some":"a"] blood-stained [s_store.name] on [t_his] [wear_suit.name]!\n" + else + msg += "[t_He] [t_is] carrying \icon[s_store] \a [s_store] on [t_his] [wear_suit.name].\n" + + //back + if(back) + if(back.blood_DNA && back.blood_DNA.len) + msg += "[t_He] [t_has] \icon[back] [back.gender==PLURAL?"some":"a"] blood-stained [back] on [t_his] back.\n" + else + msg += "[t_He] [t_has] \icon[back] \a [back] on [t_his] back.\n" + + //left hand + if(l_hand) + if(l_hand.blood_DNA && l_hand.blood_DNA.len) + msg += "[t_He] [t_is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in [t_his] left hand!\n" + else + msg += "[t_He] [t_is] holding \icon[l_hand] \a [l_hand] in [t_his] left hand.\n" + + //right hand + if(r_hand) + if(r_hand.blood_DNA && r_hand.blood_DNA.len) + msg += "[t_He] [t_is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in [t_his] right hand!\n" + else + msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n" + + //gloves + if(gloves && !(slot_gloves in obscured)) + if(gloves.blood_DNA && gloves.blood_DNA.len) + msg += "[t_He] [t_has] \icon[gloves] [gloves.gender==PLURAL?"some":"a"] blood-stained [gloves.name] on [t_his] hands!\n" + else + msg += "[t_He] [t_has] \icon[gloves] \a [gloves] on [t_his] hands.\n" + else if(blood_DNA && blood_DNA.len) + msg += "[t_He] [t_has] blood-stained hands!\n" + + //handcuffed? + + //handcuffed? + if(handcuffed) + if(istype(handcuffed, /obj/item/weapon/handcuffs/cable)) + msg += "[t_He] [t_is] \icon[handcuffed] restrained with cable!\n" + else + msg += "[t_He] [t_is] \icon[handcuffed] handcuffed!\n" + + //belt + if(belt) + if(belt.blood_DNA && belt.blood_DNA.len) + msg += "[t_He] [t_has] \icon[belt] [belt.gender==PLURAL?"some":"a"] blood-stained [belt.name] about [t_his] waist!\n" + else + msg += "[t_He] [t_has] \icon[belt] \a [belt] about [t_his] waist.\n" + + //shoes + if(shoes && !(slot_shoes in obscured)) + if(shoes.blood_DNA && shoes.blood_DNA.len) + msg += "[t_He] [t_is] wearing \icon[shoes] [shoes.gender==PLURAL?"some":"a"] blood-stained [shoes.name] on [t_his] feet!\n" + else + msg += "[t_He] [t_is] wearing \icon[shoes] \a [shoes] on [t_his] feet.\n" + + //mask + if(wear_mask && !(slot_wear_mask in obscured)) + if(wear_mask.blood_DNA && wear_mask.blood_DNA.len) + msg += "[t_He] [t_has] \icon[wear_mask] [wear_mask.gender==PLURAL?"some":"a"] blood-stained [wear_mask.name] on [t_his] face!\n" + else + msg += "[t_He] [t_has] \icon[wear_mask] \a [wear_mask] on [t_his] face.\n" + + //eyes + if(glasses && !(slot_glasses in obscured)) + if(glasses.blood_DNA && glasses.blood_DNA.len) + msg += "[t_He] [t_has] \icon[glasses] [glasses.gender==PLURAL?"some":"a"] blood-stained [glasses] covering [t_his] eyes!\n" + else + msg += "[t_He] [t_has] \icon[glasses] \a [glasses] covering [t_his] eyes.\n" + + //ears + if(ears && !(slot_ears in obscured)) + msg += "[t_He] [t_has] \icon[ears] \a [ears] on [t_his] ears.\n" + + //ID + if(wear_id) + /*var/id + if(istype(wear_id, /obj/item/device/pda)) + var/obj/item/device/pda/pda = wear_id + id = pda.owner + else if(istype(wear_id, /obj/item/weapon/card/id)) //just in case something other than a PDA/ID card somehow gets in the ID slot :[ + var/obj/item/weapon/card/id/idcard = wear_id + id = idcard.registered_name + if(id && (id != real_name) && (get_dist(src, user) <= 1) && prob(10)) + msg += "[t_He] [t_is] wearing \icon[wear_id] \a [wear_id] yet something doesn't seem right...\n" + else*/ + msg += "[t_He] [t_is] wearing \icon[wear_id] \a [wear_id].\n" + + switch(jitteriness) + if(JITTER_HIGH to INFINITY) + msg += "[t_He] [t_is] convulsing violently!\n" + if(JITTER_MEDIUM to JITTER_HIGH) + msg += "[t_He] [t_is] extremely jittery.\n" + if(1 to JITTER_MEDIUM) + msg += "[t_He] [t_is] twitching ever so slightly.\n" + + //splints + for(var/organ in list("l_leg","r_leg","l_arm","r_arm")) + var/datum/organ/external/o = get_organ(organ) + if(o && o.status & ORGAN_SPLINTED) + msg += "[t_He] [t_has] a splint on [t_his] [o.display_name]!\n" + + if(suiciding) + msg += "[t_He] appears to have committed suicide... there is no hope of recovery.\n" + + if(M_DWARF in mutations) + msg += "[t_He] [t_is] a short, sturdy creature fond of drink and industry.\n" + + if (isUnconscious()) + msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" + if((isDead() || src.health < config.health_threshold_crit) && distance <= 3) + msg += "[t_He] does not appear to be breathing.\n" + + if(ishuman(user) && !isUnconscious(user) && distance <= 1) + user.visible_message("[user] checks [src]'s pulse.") + + spawn(15) + if(user && distance <= 1 && !isUnconscious(user)) + if(pulse == PULSE_NONE || (status_flags & FAKEDEATH)) + to_chat(user, "[t_He] has no pulse[src.client ? "" : " and [t_his] soul has departed"]...") + else + to_chat(user, "[t_He] has a pulse!") + + msg += "" + + if(nutrition < 100) + if(hardcore_mode_on && eligible_for_hardcore_mode(src)) + msg += "[t_He] [t_is] severely malnourished.\n" + else + msg += "[t_He] [t_is] severely malnourished.\n" + else if(nutrition >= 500) + if(user.nutrition < 100) + msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" + else + msg += "[t_He] [t_is] quite chubby.\n" + + msg += "" + + if(has_brain() && stat != DEAD) + if(!key) + msg += "[t_He] [t_is] totally catatonic. The stresses of life in deep space must have been too much for [t_him]. Any recovery is unlikely.\n" + else if(!client) + msg += "[t_He] [t_has] a vacant, braindead stare...\n" + + var/list/wound_flavor_text = list() + var/list/is_destroyed = list() + var/list/is_bleeding = list() + for(var/datum/organ/external/temp in organs) + if(temp) + if(temp.status & ORGAN_DESTROYED) + is_destroyed["[temp.display_name]"] = 1 + wound_flavor_text["[temp.display_name]"] = "[t_He] is missing [t_his] [temp.display_name].\n" + continue + if(temp.status & ORGAN_PEG) + if(!(temp.brute_dam + temp.burn_dam)) + wound_flavor_text["[temp.display_name]"] = "[t_He] has a peg [temp.display_name]!\n" + continue + else + wound_flavor_text["[temp.display_name]"] = "[t_He] has a peg [temp.display_name], it has" + if(temp.brute_dam) switch(temp.brute_dam) + if(0 to 20) + wound_flavor_text["[temp.display_name]"] += " some marks" + if(21 to INFINITY) + wound_flavor_text["[temp.display_name]"] += pick(" a lot of damage"," severe cracks and splintering") + if(temp.brute_dam && temp.burn_dam) + wound_flavor_text["[temp.display_name]"] += " and" + if(temp.burn_dam) switch(temp.burn_dam) + if(0 to 20) + wound_flavor_text["[temp.display_name]"] += " some burns" + if(21 to INFINITY) + wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe charring") + wound_flavor_text["[temp.display_name]"] += "!\n" + else if(temp.status & ORGAN_ROBOT) + if(!(temp.brute_dam + temp.burn_dam)) + wound_flavor_text["[temp.display_name]"] = "[t_He] has a robot [temp.display_name]!\n" + continue + else + wound_flavor_text["[temp.display_name]"] = "[t_He] has a robot [temp.display_name], it has" + if(temp.brute_dam) switch(temp.brute_dam) + if(0 to 20) + wound_flavor_text["[temp.display_name]"] += " some dents" + if(21 to INFINITY) + wound_flavor_text["[temp.display_name]"] += pick(" a lot of dents"," severe denting") + if(temp.brute_dam && temp.burn_dam) + wound_flavor_text["[temp.display_name]"] += " and" + if(temp.burn_dam) switch(temp.burn_dam) + if(0 to 20) + wound_flavor_text["[temp.display_name]"] += " some burns" + if(21 to INFINITY) + wound_flavor_text["[temp.display_name]"] += pick(" a lot of burns"," severe melting") + wound_flavor_text["[temp.display_name]"] += "!\n" + else if(temp.wounds.len > 0) + var/list/wound_descriptors = list() + for(var/datum/wound/W in temp.wounds) + if(W.internal && !temp.open) continue // can't see internal wounds + var/this_wound_desc = W.desc + if(W.bleeding()) this_wound_desc = "bleeding [this_wound_desc]" + else if(W.bandaged) this_wound_desc = "bandaged [this_wound_desc]" + if(W.germ_level > 600) this_wound_desc = "badly infected [this_wound_desc]" + else if(W.germ_level > 330) this_wound_desc = "lightly infected [this_wound_desc]" + if(this_wound_desc in wound_descriptors) + wound_descriptors[this_wound_desc] += W.amount + continue + wound_descriptors[this_wound_desc] = W.amount + if(wound_descriptors.len) + var/list/flavor_text = list() + var/list/no_exclude = list("gaping wound", "big gaping wound", "massive wound", "large bruise",\ + "huge bruise", "massive bruise", "severe burn", "large burn", "deep burn", "carbonised area") + for(var/wound in wound_descriptors) + switch(wound_descriptors[wound]) + if(1) + if(!flavor_text.len) + flavor_text += "[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]" + else + flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a [wound]" + if(2) + if(!flavor_text.len) + flavor_text += "[t_He] has[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s" + else + flavor_text += "[prob(10) && !(wound in no_exclude) ? " what might be" : ""] a pair of [wound]s" + if(3 to 5) + if(!flavor_text.len) + flavor_text += "[t_He] has several [wound]s" + else + flavor_text += " several [wound]s" + if(6 to INFINITY) + if(!flavor_text.len) + flavor_text += "[t_He] has a bunch of [wound]s" + else + flavor_text += " a ton of [wound]\s" + var/flavor_text_string = "" + for(var/text = 1, text <= flavor_text.len, text++) + if(text == flavor_text.len && flavor_text.len > 1) + flavor_text_string += ", and" + else if(flavor_text.len > 1 && text > 1) + flavor_text_string += "," + flavor_text_string += flavor_text[text] + flavor_text_string += " on [t_his] [temp.display_name].
    " + wound_flavor_text["[temp.display_name]"] = flavor_text_string + else + wound_flavor_text["[temp.display_name]"] = "" + if(temp.status & ORGAN_BLEEDING) + is_bleeding["[temp.display_name]"] = 1 + else + wound_flavor_text["[temp.display_name]"] = "" + + //Handles the text strings being added to the actual description. + //If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext. + var/display_chest = 0 + var/display_shoes = 0 + var/display_gloves = 0 + if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas))))) + msg += wound_flavor_text["head"] + else if(is_bleeding["head"]) + msg += "[src] has blood running down [t_his] face!\n" + if(wound_flavor_text["chest"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you. + msg += wound_flavor_text["chest"] + else if(is_bleeding["chest"]) + display_chest = 1 + if(wound_flavor_text["left arm"] && (is_destroyed["left arm"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["left arm"] + else if(is_bleeding["left arm"]) + display_chest = 1 + if(wound_flavor_text["left hand"] && (is_destroyed["left hand"] || (!gloves && !skipgloves))) + msg += wound_flavor_text["left hand"] + else if(is_bleeding["left hand"]) + display_gloves = 1 + if(wound_flavor_text["right arm"] && (is_destroyed["right arm"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["right arm"] + else if(is_bleeding["right arm"]) + display_chest = 1 + if(wound_flavor_text["right hand"] && (is_destroyed["right hand"] || (!gloves && !skipgloves))) + msg += wound_flavor_text["right hand"] + else if(is_bleeding["right hand"]) + display_gloves = 1 + if(wound_flavor_text["groin"] && (is_destroyed["groin"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["groin"] + else if(is_bleeding["groin"]) + display_chest = 1 + if(wound_flavor_text["left leg"] && (is_destroyed["left leg"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["left leg"] + else if(is_bleeding["left leg"]) + display_chest = 1 + if(wound_flavor_text["left foot"]&& (is_destroyed["left foot"] || (!shoes && !skipshoes))) + msg += wound_flavor_text["left foot"] + else if(is_bleeding["left foot"]) + display_shoes = 1 + if(wound_flavor_text["right leg"] && (is_destroyed["right leg"] || (!w_uniform && !skipjumpsuit))) + msg += wound_flavor_text["right leg"] + else if(is_bleeding["right leg"]) + display_chest = 1 + if(wound_flavor_text["right foot"]&& (is_destroyed["right foot"] || (!shoes && !skipshoes))) + msg += wound_flavor_text["right foot"] + else if(is_bleeding["right foot"]) + display_shoes = 1 + if(display_chest) + msg += "[src] has blood soaking through from under [t_his] clothing!\n" + if(display_shoes) + msg += "[src] has blood running from [t_his] shoes!\n" + if(display_gloves) + msg += "[src] has blood running from under [t_his] gloves!\n" + + for(var/implant in get_visible_implants(1)) + msg += "[src] has \a [implant] sticking out of [t_his] flesh!\n" + if(digitalcamo) + msg += "[t_He] [t_is] repulsively uncanny!\n" + + if(!is_destroyed["head"]) + if(getBrainLoss() >= 60) + msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" + + if(distance <= 3) + if(!has_brain()) + msg += "[t_He] has had [t_his] brain removed.\n" + + var/butchery = "" //More information about butchering status, check out "code/datums/helper_datums/butchering.dm" + if(butchering_drops && butchering_drops.len) + for(var/datum/butchering_product/B in butchering_drops) + butchery = "[butchery][B.desc_modifier(src, user)]" + if(butchery) + msg += "[butchery]\n" + + if(hasHUD(user,"security")) + var/perpname = "wot" + var/criminal = "None" + + if(wear_id) + var/obj/item/weapon/card/id/I = wear_id.GetID() + if(I) + perpname = I.registered_name + else + perpname = name + else + perpname = name + + if(perpname) + for (var/datum/data/record/E in data_core.general) + if(E.fields["name"] == perpname) + for (var/datum/data/record/R in data_core.security) + if(R.fields["id"] == E.fields["id"]) + criminal = R.fields["criminal"] + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\carbon\human\examine.dm:411: msg += "Criminal status: \[[criminal]\]\n" + msg += {"Criminal status: \[[criminal]\] +Security records: \[View\] \[Add comment\]\n"} + // END AUTOFIX + if(hasHUD(user,"medical")) + var/perpname = "wot" + var/medical = "None" + + if(wear_id) + if(istype(wear_id,/obj/item/weapon/card/id)) + perpname = wear_id:registered_name + else if(istype(wear_id,/obj/item/device/pda)) + var/obj/item/device/pda/tempPda = wear_id + perpname = tempPda.owner + else + perpname = src.name + + for (var/datum/data/record/E in data_core.general) + if (E.fields["name"] == perpname) + for (var/datum/data/record/R in data_core.general) + if (R.fields["id"] == E.fields["id"]) + medical = R.fields["p_stat"] + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\carbon\human\examine.dm:433: msg += "Physical status: \[[medical]\]\n" + msg += {"Physical status: \[[medical]\]\n + Medical records: \[View\] \[Add comment\]\n"} + // END AUTOFIX + if(print_flavor_text()) msg += "[print_flavor_text()]\n" + + msg += "*---------*
    " + if (pose) + if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) + pose = addtext(pose,".") //Makes sure all emotes end with a period. + msg += "\n[t_He] is [pose]" + + to_chat(user, msg) + +//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records. +/proc/hasHUD(mob/M as mob, hudtype) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + switch(hudtype) + if("security") + return istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/sechud) + if("medical") + return istype(H.glasses, /obj/item/clothing/glasses/hud/health) + else + return 0 + else if(istype(M, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = M + switch(hudtype) + if("security") + return R.sensor_mode == 1 + if("medical") + return R.sensor_mode == 2 + else + return 0 + else if(istype(M, /mob/living/silicon/pai)) + var/mob/living/silicon/pai/P = M + switch(hudtype) + if("security") + return P.secHUD + if("medical") + return P.medHUD + else + return 0 + +#undef Jitter_Medium +#undef Jitter_High diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm index 5804711e42f..a4891f23fb5 100644 --- a/code/modules/mob/living/carbon/human/human_attackalien.dm +++ b/code/modules/mob/living/carbon/human/human_attackalien.dm @@ -1,63 +1,63 @@ -/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - //M.delayNextAttack(10) - if(check_shields(0, M.name)) - visible_message("[M] attempted to touch [src]!") - return 0 - - switch(M.a_intent) - if (I_HELP) - visible_message(text("[M] caresses [src] with its scythe like arm.")) - if (I_GRAB) - if(M == src || anchored) - return - if (w_uniform) - w_uniform.add_fingerprint(M) - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message(text("[] has grabbed [] passively!", M, src)) - - if(I_HURT) - if (w_uniform) - w_uniform.add_fingerprint(M) - var/damage = rand(15, 30) - if(!damage) - playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) - visible_message("[M] has lunged at [src]!") - return 0 - var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - visible_message("[M] has slashed at [src]!") - - apply_damage(damage, BRUTE, affecting, armor_block) - if (damage >= 25) - visible_message("[M] has wounded [src]!") - apply_effect(rand(0.5,3), WEAKEN, armor_block) - updatehealth() - - if(I_DISARM) - if (prob(80)) - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - Weaken(rand(3,4)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has tackled down []!", M, src), 1) - if (prob(25)) - M.Weaken(rand(4,5)) - else - if (prob(80)) - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - drop_item() - visible_message(text("[] disarmed []!", M, src)) - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) - visible_message(text("[] has tried to disarm []!", M, src)) +/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + //M.delayNextAttack(10) + if(check_shields(0, M.name)) + visible_message("[M] attempted to touch [src]!") + return 0 + + switch(M.a_intent) + if (I_HELP) + visible_message(text("[M] caresses [src] with its scythe like arm.")) + if (I_GRAB) + if(M == src || anchored) + return + if (w_uniform) + w_uniform.add_fingerprint(M) + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message(text("[] has grabbed [] passively!", M, src)) + + if(I_HURT) + if (w_uniform) + w_uniform.add_fingerprint(M) + var/damage = rand(15, 30) + if(!damage) + playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) + visible_message("[M] has lunged at [src]!") + return 0 + var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) + var/armor_block = run_armor_check(affecting, "melee") + + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + visible_message("[M] has slashed at [src]!") + + apply_damage(damage, BRUTE, affecting, armor_block) + if (damage >= 25) + visible_message("[M] has wounded [src]!") + apply_effect(rand(0.5,3), WEAKEN, armor_block) + updatehealth() + + if(I_DISARM) + if (prob(80)) + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + Weaken(rand(3,4)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has tackled down []!", M, src), 1) + if (prob(25)) + M.Weaken(rand(4,5)) + else + if (prob(80)) + playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) + drop_item() + visible_message(text("[] disarmed []!", M, src)) + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) + visible_message(text("[] has tried to disarm []!", M, src)) return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 50ff1957f96..77a3397bbd0 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -1,323 +1,323 @@ -/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M as mob) - //M.delayNextAttack(10) - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - to_chat(M, "No attacking people at spawn, you jackass.") - return - - var/datum/organ/external/temp = M:organs_by_name["r_hand"] - if (M.hand) - temp = M:organs_by_name["l_hand"] - if(temp && !temp.is_usable()) - to_chat(M, "You can't use your [temp.display_name].") - return - - ..() - - if((M != src) && check_shields(0, M.name)) - visible_message("[M] attempted to touch [src]!") - return 0 - - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - visible_message("[src] has been touched with the stun gloves by [M]!") - M.attack_log += text("\[[time_stamp()]\] Stungloved [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been stungloved by [M.name] ([M.ckey])") - if(!iscarbon(M)) - LAssailant = null - else - LAssailant = M - - log_attack("[M.name] ([M.ckey]) stungloved [src.name] ([src.ckey])") - - var/armorblock = run_armor_check(M.zone_sel.selecting, "energy") - apply_effects(5,5,0,0,5,0,0,armorblock) - return 1 - else - to_chat(M, "Not enough charge! ") - visible_message("[src] has been touched with the stun gloves by [M]!") - return - - if(istype(M.gloves , /obj/item/clothing/gloves/boxing/hologlove)) - - var/damage = rand(0, 9) - if(!damage) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to punch [src]!") - return 0 - var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - - if(M_HULK in M.mutations) damage += 5 - - playsound(loc, "punch", 25, 1, -1) - - visible_message("[M] has punched [src]!") - - apply_damage(damage, HALLOSS, affecting, armor_block) - if(damage >= 9) - visible_message("[M] has weakened [src]!") - apply_effect(4, WEAKEN, armor_block) - - return - else - if(istype(M,/mob/living/carbon)) -// log_debug("No gloves, [M] is truing to infect [src]") - M.spread_disease_to(src, "Contact") - - - switch(M.a_intent) - if(I_HELP) - if(health >= config.health_threshold_crit) - help_shake_act(M) - return 1 -// if(M.health < -75) return 0 - - if(M.check_body_part_coverage(MOUTH)) - to_chat(M, "Remove your [M.get_body_part_coverage(MOUTH)]!") - return 0 - if(src.check_body_part_coverage(MOUTH)) - to_chat(M, "Remove his [src.get_body_part_coverage(MOUTH)]!") - return 0 - - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human() - O.source = M - O.target = src - O.s_loc = M.loc - O.t_loc = loc - O.place = "CPR" - requests += O - spawn(0) - O.process() - return 1 - - if(I_GRAB) - if(M == src || anchored) - return 0 - if(w_uniform) - w_uniform.add_fingerprint(M) - - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - if(locked_to) - to_chat(M, "You cannot grab [src], \he is buckled in!") - if(!G) //the grab will delete itself in New if affecting is anchored - return - M.put_in_active_hand(G) - grabbed_by += G - G.synch() - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has grabbed [src] passively!") - return 1 - - if(I_HURT) - //Vampire code - if(M.zone_sel && M.zone_sel.selecting == "head" && src != M) - if(M.mind && M.mind.vampire && (M.mind in ticker.mode.vampires) && !M.mind.vampire.draining) - if(src.check_body_part_coverage(MOUTH)) - to_chat(M, "Remove their mask!") - return 0 - if(M.check_body_part_coverage(MOUTH)) - if(M.species.breath_type == "oxygen") - to_chat(M, "Remove your mask!") - return 0 - else - to_chat(M, "With practiced ease, you shift aside your mask for each gulp of blood.") - if(mind && mind.vampire && (mind in ticker.mode.vampires)) - to_chat(M, "Your fangs fail to pierce [src.name]'s cold flesh.") - return 0 - //we're good to suck the blood, blaah - M.handle_bloodsucking(src) - return - //end vampire codes - - // BITING - var/can_bite = 0 - for(var/datum/disease/D in M.viruses) - if(D.spread == "Bite") - can_bite = 1 - break - if(can_bite) - if ((prob(75) && health > 0)) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - src.visible_message("[M.name] has bit [name]!") - - var/damage = rand(1, 5) - adjustBruteLoss(damage) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - for(var/datum/disease/D in M.viruses) - if(D.spread == "Bite") - contract_disease(D,1,0) - M.attack_log += text("\[[time_stamp()]\] bitten by [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been bitten by [M.name] ([M.ckey])") - if(!iscarbon(M)) - LAssailant = null - else - LAssailant = M - log_attack("[M.name] ([M.ckey]) bitten by [src.name] ([src.ckey])") - return - //end biting - - M.attack_log += text("\[[time_stamp()]\] [M.species.attack_verb]ed [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been [M.species.attack_verb]ed by [M.name] ([M.ckey])") - if(!iscarbon(M)) - LAssailant = null - else - LAssailant = M - - log_attack("[M.name] ([M.ckey]) [M.species.attack_verb]ed [src.name] ([src.ckey])") - - - var/damage = rand(0, M.species.max_hurt_damage)//BS12 EDIT // edited again by Iamgoofball to fix species attacks - - if(!damage) - if(M.species.attack_verb == "punch") - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - - visible_message("[M] has attempted to [M.species.attack_verb] [src]!") - return 0 - - - var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - - if(M_HULK in M.mutations) damage += 5 - - var/knockout = damage - - if((M_CLAWS in M.mutations) && !istype(M.gloves)) damage += 3 //Claws mutation + no gloves (doesn't affect weaken chance) - - if(istype(M.gloves)) //Attacker has gloves - var/obj/item/clothing/gloves/G = M.gloves - damage += G.damage_added //Increase damage by the gloves' damage modifier - knockout += G.bonus_knockout //Increase knockout chance by the gloves' knockout modifier - - if(M.species.attack_verb == "punch") - playsound(loc, "punch", 25, 1, -1) - else - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - - visible_message("[M] has [M.species.attack_verb]ed [src]!") - - if((knockout >= M.species.max_hurt_damage) && prob(50)) - visible_message("[M] has weakened [src]!") - apply_effect(2, WEAKEN, armor_block) - - if(M.species.punch_damage) - damage += M.species.punch_damage - - apply_damage(damage, BRUTE, affecting, armor_block) - - // Horror form can punch people so hard they learn how to fly. - if(M.species.punch_throw_range && prob(25)) - visible_message("[src] is thrown by the force of the assault!") - var/turf/T = get_turf(src) - var/turf/target - if(istype(T, /turf/space)) // if ended in space, then range is unlimited - target = get_edge_target_turf(T, M.dir) - else // otherwise limit to 10 tiles - target = get_ranged_target_turf(T, M.dir, M.species.punch_throw_range) - src.throw_at(target,100,M.species.punch_throw_speed) - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.zone_sel && H.zone_sel.selecting == "mouth") - var/chance = 0.5 * damage - if(M_HULK in H.mutations) chance += 50 - if(prob(chance)) - knock_out_teeth(H) - - - if(I_DISARM) - M.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been disarmed by [M.name] ([M.ckey])") - - log_attack("[M.name] ([M.ckey]) disarmed [src.name] ([src.ckey])") - - if(w_uniform) - w_uniform.add_fingerprint(M) - var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - - if (istype(r_hand,/obj/item/weapon/gun) || istype(l_hand,/obj/item/weapon/gun)) - var/obj/item/weapon/gun/W = null - var/chance = 0 - - if (istype(l_hand,/obj/item/weapon/gun)) - W = l_hand - chance = hand ? 40 : 20 - - if (istype(r_hand,/obj/item/weapon/gun)) - W = r_hand - chance = !hand ? 40 : 20 - - if (prob(chance)) - visible_message("[W], held by [src], goes off during struggle!") - var/list/turfs = list() - for(var/turf/T in view()) - turfs += T - var/turf/target = pick(turfs) - return W.afterattack(target,src, "struggle" = 1) - - var/randn = rand(1, 100) - if (randn <= 25) - apply_effect(4, WEAKEN, run_armor_check(affecting, "melee")) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has pushed [src]!") - M.attack_log += text("\[[time_stamp()]\] Pushed [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been pushed by [M.name] ([M.ckey])") - if(!iscarbon(M)) - LAssailant = null - else - LAssailant = M - - log_attack("[M.name] ([M.ckey]) pushed [src.name] ([src.ckey])") - return - - var/talked = 0 // BubbleWrap - - if(randn <= 60) - //BubbleWrap: Disarming breaks a pull - if(pulling) - visible_message("[M] has broken [src]'s grip on [pulling]!") - talked = 1 - stop_pulling() - - //BubbleWrap: Disarming also breaks a grab - this will also stop someone being choked, won't it? - if(istype(l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/lgrab = l_hand - if(lgrab.affecting) - visible_message("[M] has broken [src]'s grip on [lgrab.affecting]!") - talked = 1 - spawn(1) - qdel(lgrab) - lgrab = null - if(istype(r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/rgrab = r_hand - if(rgrab.affecting) - visible_message("[M] has broken [src]'s grip on [rgrab.affecting]!") - talked = 1 - spawn(1) - qdel(rgrab) - rgrab = null - //End BubbleWrap - - if(!talked) //BubbleWrap - drop_item() - visible_message("[M] has disarmed [src]!") - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - return - - - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] attempted to disarm [src]!") - return - -/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params) - return +/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M as mob) + //M.delayNextAttack(10) + if (istype(loc, /turf) && istype(loc.loc, /area/start)) + to_chat(M, "No attacking people at spawn, you jackass.") + return + + var/datum/organ/external/temp = M:organs_by_name["r_hand"] + if (M.hand) + temp = M:organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + to_chat(M, "You can't use your [temp.display_name].") + return + + ..() + + if((M != src) && check_shields(0, M.name)) + visible_message("[M] attempted to touch [src]!") + return 0 + + + if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = M.gloves + if(G.cell) + if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + visible_message("[src] has been touched with the stun gloves by [M]!") + M.attack_log += text("\[[time_stamp()]\] Stungloved [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been stungloved by [M.name] ([M.ckey])") + if(!iscarbon(M)) + LAssailant = null + else + LAssailant = M + + log_attack("[M.name] ([M.ckey]) stungloved [src.name] ([src.ckey])") + + var/armorblock = run_armor_check(M.zone_sel.selecting, "energy") + apply_effects(5,5,0,0,5,0,0,armorblock) + return 1 + else + to_chat(M, "Not enough charge! ") + visible_message("[src] has been touched with the stun gloves by [M]!") + return + + if(istype(M.gloves , /obj/item/clothing/gloves/boxing/hologlove)) + + var/damage = rand(0, 9) + if(!damage) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] has attempted to punch [src]!") + return 0 + var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) + var/armor_block = run_armor_check(affecting, "melee") + + if(M_HULK in M.mutations) damage += 5 + + playsound(loc, "punch", 25, 1, -1) + + visible_message("[M] has punched [src]!") + + apply_damage(damage, HALLOSS, affecting, armor_block) + if(damage >= 9) + visible_message("[M] has weakened [src]!") + apply_effect(4, WEAKEN, armor_block) + + return + else + if(istype(M,/mob/living/carbon)) +// log_debug("No gloves, [M] is truing to infect [src]") + M.spread_disease_to(src, "Contact") + + + switch(M.a_intent) + if(I_HELP) + if(health >= config.health_threshold_crit) + help_shake_act(M) + return 1 +// if(M.health < -75) return 0 + + if(M.check_body_part_coverage(MOUTH)) + to_chat(M, "Remove your [M.get_body_part_coverage(MOUTH)]!") + return 0 + if(src.check_body_part_coverage(MOUTH)) + to_chat(M, "Remove his [src.get_body_part_coverage(MOUTH)]!") + return 0 + + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human() + O.source = M + O.target = src + O.s_loc = M.loc + O.t_loc = loc + O.place = "CPR" + requests += O + spawn(0) + O.process() + return 1 + + if(I_GRAB) + if(M == src || anchored) + return 0 + if(w_uniform) + w_uniform.add_fingerprint(M) + + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + if(locked_to) + to_chat(M, "You cannot grab [src], \he is buckled in!") + if(!G) //the grab will delete itself in New if affecting is anchored + return + M.put_in_active_hand(G) + grabbed_by += G + G.synch() + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has grabbed [src] passively!") + return 1 + + if(I_HURT) + //Vampire code + if(M.zone_sel && M.zone_sel.selecting == "head" && src != M) + if(M.mind && M.mind.vampire && (M.mind in ticker.mode.vampires) && !M.mind.vampire.draining) + if(src.check_body_part_coverage(MOUTH)) + to_chat(M, "Remove their mask!") + return 0 + if(M.check_body_part_coverage(MOUTH)) + if(M.species.breath_type == "oxygen") + to_chat(M, "Remove your mask!") + return 0 + else + to_chat(M, "With practiced ease, you shift aside your mask for each gulp of blood.") + if(mind && mind.vampire && (mind in ticker.mode.vampires)) + to_chat(M, "Your fangs fail to pierce [src.name]'s cold flesh.") + return 0 + //we're good to suck the blood, blaah + M.handle_bloodsucking(src) + return + //end vampire codes + + // BITING + var/can_bite = 0 + for(var/datum/disease/D in M.viruses) + if(D.spread == "Bite") + can_bite = 1 + break + if(can_bite) + if ((prob(75) && health > 0)) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + src.visible_message("[M.name] has bit [name]!") + + var/damage = rand(1, 5) + adjustBruteLoss(damage) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + for(var/datum/disease/D in M.viruses) + if(D.spread == "Bite") + contract_disease(D,1,0) + M.attack_log += text("\[[time_stamp()]\] bitten by [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been bitten by [M.name] ([M.ckey])") + if(!iscarbon(M)) + LAssailant = null + else + LAssailant = M + log_attack("[M.name] ([M.ckey]) bitten by [src.name] ([src.ckey])") + return + //end biting + + M.attack_log += text("\[[time_stamp()]\] [M.species.attack_verb]ed [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been [M.species.attack_verb]ed by [M.name] ([M.ckey])") + if(!iscarbon(M)) + LAssailant = null + else + LAssailant = M + + log_attack("[M.name] ([M.ckey]) [M.species.attack_verb]ed [src.name] ([src.ckey])") + + + var/damage = rand(0, M.species.max_hurt_damage)//BS12 EDIT // edited again by Iamgoofball to fix species attacks + + if(!damage) + if(M.species.attack_verb == "punch") + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + + visible_message("[M] has attempted to [M.species.attack_verb] [src]!") + return 0 + + + var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) + var/armor_block = run_armor_check(affecting, "melee") + + if(M_HULK in M.mutations) damage += 5 + + var/knockout = damage + + if((M_CLAWS in M.mutations) && !istype(M.gloves)) damage += 3 //Claws mutation + no gloves (doesn't affect weaken chance) + + if(istype(M.gloves)) //Attacker has gloves + var/obj/item/clothing/gloves/G = M.gloves + damage += G.damage_added //Increase damage by the gloves' damage modifier + knockout += G.bonus_knockout //Increase knockout chance by the gloves' knockout modifier + + if(M.species.attack_verb == "punch") + playsound(loc, "punch", 25, 1, -1) + else + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + + visible_message("[M] has [M.species.attack_verb]ed [src]!") + + if((knockout >= M.species.max_hurt_damage) && prob(50)) + visible_message("[M] has weakened [src]!") + apply_effect(2, WEAKEN, armor_block) + + if(M.species.punch_damage) + damage += M.species.punch_damage + + apply_damage(damage, BRUTE, affecting, armor_block) + + // Horror form can punch people so hard they learn how to fly. + if(M.species.punch_throw_range && prob(25)) + visible_message("[src] is thrown by the force of the assault!") + var/turf/T = get_turf(src) + var/turf/target + if(istype(T, /turf/space)) // if ended in space, then range is unlimited + target = get_edge_target_turf(T, M.dir) + else // otherwise limit to 10 tiles + target = get_ranged_target_turf(T, M.dir, M.species.punch_throw_range) + src.throw_at(target,100,M.species.punch_throw_speed) + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.zone_sel && H.zone_sel.selecting == "mouth") + var/chance = 0.5 * damage + if(M_HULK in H.mutations) chance += 50 + if(prob(chance)) + knock_out_teeth(H) + + + if(I_DISARM) + M.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been disarmed by [M.name] ([M.ckey])") + + log_attack("[M.name] ([M.ckey]) disarmed [src.name] ([src.ckey])") + + if(w_uniform) + w_uniform.add_fingerprint(M) + var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) + + if (istype(r_hand,/obj/item/weapon/gun) || istype(l_hand,/obj/item/weapon/gun)) + var/obj/item/weapon/gun/W = null + var/chance = 0 + + if (istype(l_hand,/obj/item/weapon/gun)) + W = l_hand + chance = hand ? 40 : 20 + + if (istype(r_hand,/obj/item/weapon/gun)) + W = r_hand + chance = !hand ? 40 : 20 + + if (prob(chance)) + visible_message("[W], held by [src], goes off during struggle!") + var/list/turfs = list() + for(var/turf/T in view()) + turfs += T + var/turf/target = pick(turfs) + return W.afterattack(target,src, "struggle" = 1) + + var/randn = rand(1, 100) + if (randn <= 25) + apply_effect(4, WEAKEN, run_armor_check(affecting, "melee")) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + visible_message("[M] has pushed [src]!") + M.attack_log += text("\[[time_stamp()]\] Pushed [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been pushed by [M.name] ([M.ckey])") + if(!iscarbon(M)) + LAssailant = null + else + LAssailant = M + + log_attack("[M.name] ([M.ckey]) pushed [src.name] ([src.ckey])") + return + + var/talked = 0 // BubbleWrap + + if(randn <= 60) + //BubbleWrap: Disarming breaks a pull + if(pulling) + visible_message("[M] has broken [src]'s grip on [pulling]!") + talked = 1 + stop_pulling() + + //BubbleWrap: Disarming also breaks a grab - this will also stop someone being choked, won't it? + if(istype(l_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/lgrab = l_hand + if(lgrab.affecting) + visible_message("[M] has broken [src]'s grip on [lgrab.affecting]!") + talked = 1 + spawn(1) + qdel(lgrab) + lgrab = null + if(istype(r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/rgrab = r_hand + if(rgrab.affecting) + visible_message("[M] has broken [src]'s grip on [rgrab.affecting]!") + talked = 1 + spawn(1) + qdel(rgrab) + rgrab = null + //End BubbleWrap + + if(!talked) //BubbleWrap + drop_item() + visible_message("[M] has disarmed [src]!") + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + return + + + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("[M] attempted to disarm [src]!") + return + +/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params) + return diff --git a/code/modules/mob/living/carbon/human/human_attackpaw.dm b/code/modules/mob/living/carbon/human/human_attackpaw.dm index be08b7360b7..9b9caa7cf2d 100644 --- a/code/modules/mob/living/carbon/human/human_attackpaw.dm +++ b/code/modules/mob/living/carbon/human/human_attackpaw.dm @@ -1,24 +1,24 @@ -/mob/living/carbon/human/attack_paw(mob/M as mob) - ..() - //M.delayNextAttack(10) - if (M.a_intent == I_HELP) - help_shake_act(M) - else - if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - - for(var/mob/O in viewers(src, null)) - O.show_message(text("[M.name] has bit []!", src), 1) - - var/damage = rand(1, 3) - var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") - var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone)) - apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee")) - - for(var/datum/disease/D in M.viruses) - if(istype(D, /datum/disease/jungle_fever)) - var/mob/living/carbon/human/H = src - src = null - src = H.monkeyize() - contract_disease(D,1,0) - return +/mob/living/carbon/human/attack_paw(mob/M as mob) + ..() + //M.delayNextAttack(10) + if (M.a_intent == I_HELP) + help_shake_act(M) + else + if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + + for(var/mob/O in viewers(src, null)) + O.show_message(text("[M.name] has bit []!", src), 1) + + var/damage = rand(1, 3) + var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone)) + apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee")) + + for(var/datum/disease/D in M.viruses) + if(istype(D, /datum/disease/jungle_fever)) + var/mob/living/carbon/human/H = src + src = null + src = H.monkeyize() + contract_disease(D,1,0) + return diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index d2e62c14a1b..3db819c299f 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -1,351 +1,351 @@ -//Updates the mob's health from organs and mob damage variables -/mob/living/carbon/human/updatehealth() - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - return - var/total_burn = 0 - var/total_brute = 0 - for(var/datum/organ/external/O in organs) //hardcoded to streamline things a bit - total_brute += O.brute_dam - total_burn += O.burn_dam - health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute - //TODO: fix husking - if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD) //100 only being used as the magic human max health number, feel free to change it if you add a var for it -- Urist - ChangeToHusk() - return - -/mob/living/carbon/human/getBrainLoss() - var/res = brainloss - if(species && species.has_organ["brain"]) - var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] - if(!sponge) - res += 200 - else - if (sponge.is_bruised()) - res += 20 - if (sponge.is_broken()) - res += 50 - - res = min(res,maxHealth*2) - return res - return 0 - -//These procs fetch a cumulative total damage from all organs -/mob/living/carbon/human/getBruteLoss() - var/amount = 0 - for(var/datum/organ/external/O in organs) - amount += O.brute_dam - return amount - -/mob/living/carbon/human/getFireLoss() - var/amount = 0 - for(var/datum/organ/external/O in organs) - amount += O.burn_dam - return amount - - -/mob/living/carbon/human/adjustBruteLoss(var/amount) - if(species && species.brute_mod) - amount = amount*species.brute_mod - - if(amount > 0) - take_overall_damage(amount, 0) - else - heal_overall_damage(-amount, 0) +//Updates the mob's health from organs and mob damage variables +/mob/living/carbon/human/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + stat = CONSCIOUS + return + var/total_burn = 0 + var/total_brute = 0 + for(var/datum/organ/external/O in organs) //hardcoded to streamline things a bit + total_brute += O.brute_dam + total_burn += O.burn_dam + health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute + //TODO: fix husking + if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD) //100 only being used as the magic human max health number, feel free to change it if you add a var for it -- Urist + ChangeToHusk() + return + +/mob/living/carbon/human/getBrainLoss() + var/res = brainloss + if(species && species.has_organ["brain"]) + var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] + if(!sponge) + res += 200 + else + if (sponge.is_bruised()) + res += 20 + if (sponge.is_broken()) + res += 50 + + res = min(res,maxHealth*2) + return res + return 0 + +//These procs fetch a cumulative total damage from all organs +/mob/living/carbon/human/getBruteLoss() + var/amount = 0 + for(var/datum/organ/external/O in organs) + amount += O.brute_dam + return amount + +/mob/living/carbon/human/getFireLoss() + var/amount = 0 + for(var/datum/organ/external/O in organs) + amount += O.burn_dam + return amount + + +/mob/living/carbon/human/adjustBruteLoss(var/amount) + if(species && species.brute_mod) + amount = amount*species.brute_mod + + if(amount > 0) + take_overall_damage(amount, 0) + else + heal_overall_damage(-amount, 0) hud_updateflag |= 1 << HEALTH_HUD - -/mob/living/carbon/human/adjustFireLoss(var/amount) - if(species && species.burn_mod) - amount = amount*species.burn_mod - - if(amount > 0) - take_overall_damage(0, amount) - else - heal_overall_damage(0, -amount) + +/mob/living/carbon/human/adjustFireLoss(var/amount) + if(species && species.burn_mod) + amount = amount*species.burn_mod + + if(amount > 0) + take_overall_damage(0, amount) + else + heal_overall_damage(0, -amount) hud_updateflag |= 1 << HEALTH_HUD - -/mob/living/carbon/human/proc/adjustBruteLossByPart(var/amount, var/organ_name, var/obj/damage_source = null) - if(species && species.brute_mod) - amount = amount*species.brute_mod - - if (organ_name in organs_by_name) - var/datum/organ/external/O = get_organ(organ_name) - - if(amount > 0) - O.take_damage(amount, 0, sharp=damage_source.is_sharp(), edge=has_edge(damage_source), used_weapon=damage_source) - else - //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. - O.heal_damage(-amount, 0, internal=0, robo_repair=(O.status & ORGAN_ROBOT)) - + +/mob/living/carbon/human/proc/adjustBruteLossByPart(var/amount, var/organ_name, var/obj/damage_source = null) + if(species && species.brute_mod) + amount = amount*species.brute_mod + + if (organ_name in organs_by_name) + var/datum/organ/external/O = get_organ(organ_name) + + if(amount > 0) + O.take_damage(amount, 0, sharp=damage_source.is_sharp(), edge=has_edge(damage_source), used_weapon=damage_source) + else + //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. + O.heal_damage(-amount, 0, internal=0, robo_repair=(O.status & ORGAN_ROBOT)) + hud_updateflag |= 1 << HEALTH_HUD - -/mob/living/carbon/human/proc/adjustFireLossByPart(var/amount, var/organ_name, var/obj/damage_source = null) - if(species && species.burn_mod) - amount = amount*species.burn_mod - - if (organ_name in organs_by_name) - var/datum/organ/external/O = get_organ(organ_name) - - if(amount > 0) - O.take_damage(0, amount, sharp=damage_source.is_sharp(), edge=has_edge(damage_source), used_weapon=damage_source) - else - //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. - O.heal_damage(0, -amount, internal=0, robo_repair=(O.status & ORGAN_ROBOT)) - + +/mob/living/carbon/human/proc/adjustFireLossByPart(var/amount, var/organ_name, var/obj/damage_source = null) + if(species && species.burn_mod) + amount = amount*species.burn_mod + + if (organ_name in organs_by_name) + var/datum/organ/external/O = get_organ(organ_name) + + if(amount > 0) + O.take_damage(0, amount, sharp=damage_source.is_sharp(), edge=has_edge(damage_source), used_weapon=damage_source) + else + //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. + O.heal_damage(0, -amount, internal=0, robo_repair=(O.status & ORGAN_ROBOT)) + hud_updateflag |= 1 << HEALTH_HUD - -/mob/living/carbon/human/Stun(amount) - if(M_HULK in mutations) return - ..() - -/mob/living/carbon/human/Weaken(amount) - if(M_HULK in mutations) return - ..() - -/mob/living/carbon/human/Paralyse(amount) - if(M_HULK in mutations) return - ..() - -/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) - if (prob(mut_prob)) - var/list/datum/organ/external/candidates = list() - for (var/datum/organ/external/O in organs) - if(!(O.status & ORGAN_MUTATED)) - candidates |= O - if (candidates.len) - var/datum/organ/external/O = pick(candidates) - O.mutate() + +/mob/living/carbon/human/Stun(amount) + if(M_HULK in mutations) return + ..() + +/mob/living/carbon/human/Weaken(amount) + if(M_HULK in mutations) return + ..() + +/mob/living/carbon/human/Paralyse(amount) + if(M_HULK in mutations) return + ..() + +/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) + if (prob(mut_prob)) + var/list/datum/organ/external/candidates = list() + for (var/datum/organ/external/O in organs) + if(!(O.status & ORGAN_MUTATED)) + candidates |= O + if (candidates.len) + var/datum/organ/external/O = pick(candidates) + O.mutate() to_chat(src, "Something is not right with your [O.display_name]...") - return - else - if (prob(heal_prob)) - for (var/datum/organ/external/O in organs) - if (O.status & ORGAN_MUTATED) - O.unmutate() + return + else + if (prob(heal_prob)) + for (var/datum/organ/external/O in organs) + if (O.status & ORGAN_MUTATED) + O.unmutate() to_chat(src, "Your [O.display_name] is shaped normally again.") - return - - if (getCloneLoss() < 1) - for (var/datum/organ/external/O in organs) - if (O.status & ORGAN_MUTATED) - O.unmutate() + return + + if (getCloneLoss() < 1) + for (var/datum/organ/external/O in organs) + if (O.status & ORGAN_MUTATED) + O.unmutate() to_chat(src, "Your [O.display_name] is shaped normally again.") hud_updateflag |= 1 << HEALTH_HUD - -//////////////////////////////////////////// - -//Returns a list of damaged organs -/mob/living/carbon/human/proc/get_damaged_organs(var/brute, var/burn) - var/list/datum/organ/external/parts = list() - for(var/datum/organ/external/O in organs) - if((brute && O.brute_dam) || (burn && O.burn_dam)) - parts += O - return parts - -//Returns a list of damageable organs -/mob/living/carbon/human/proc/get_damageable_organs() - var/list/datum/organ/external/parts = list() - for(var/datum/organ/external/O in organs) - if(O.brute_dam + O.burn_dam < O.max_damage) - parts += O - return parts - -//Heals ONE external organ, organ gets randomly selected from damaged ones. -//It automatically updates damage overlays if necesary -//It automatically updates health status -/mob/living/carbon/human/heal_organ_damage(var/brute, var/burn) - var/list/datum/organ/external/parts = get_damaged_organs(brute,burn) - if(!parts.len) return - var/datum/organ/external/picked = pick(parts) - if(picked.heal_damage(brute,burn)) - UpdateDamageIcon() + +//////////////////////////////////////////// + +//Returns a list of damaged organs +/mob/living/carbon/human/proc/get_damaged_organs(var/brute, var/burn) + var/list/datum/organ/external/parts = list() + for(var/datum/organ/external/O in organs) + if((brute && O.brute_dam) || (burn && O.burn_dam)) + parts += O + return parts + +//Returns a list of damageable organs +/mob/living/carbon/human/proc/get_damageable_organs() + var/list/datum/organ/external/parts = list() + for(var/datum/organ/external/O in organs) + if(O.brute_dam + O.burn_dam < O.max_damage) + parts += O + return parts + +//Heals ONE external organ, organ gets randomly selected from damaged ones. +//It automatically updates damage overlays if necesary +//It automatically updates health status +/mob/living/carbon/human/heal_organ_damage(var/brute, var/burn) + var/list/datum/organ/external/parts = get_damaged_organs(brute,burn) + if(!parts.len) return + var/datum/organ/external/picked = pick(parts) + if(picked.heal_damage(brute,burn)) + UpdateDamageIcon() hud_updateflag |= 1 << HEALTH_HUD - updatehealth() - - -/* -In most cases it makes more sense to use apply_damage() instead! And make sure to check armour if applicable. -*/ -//Damages ONE external organ, organ gets randomly selected from damagable ones. -//It automatically updates damage overlays if necesary -//It automatically updates health status -/mob/living/carbon/human/take_organ_damage(var/brute, var/burn, var/sharp = 0, var/edge = 0) - var/list/datum/organ/external/parts = get_damageable_organs() - if(!parts.len) return - var/datum/organ/external/picked = pick(parts) - if(picked.take_damage(brute,burn,sharp,edge)) - UpdateDamageIcon() + updatehealth() + + +/* +In most cases it makes more sense to use apply_damage() instead! And make sure to check armour if applicable. +*/ +//Damages ONE external organ, organ gets randomly selected from damagable ones. +//It automatically updates damage overlays if necesary +//It automatically updates health status +/mob/living/carbon/human/take_organ_damage(var/brute, var/burn, var/sharp = 0, var/edge = 0) + var/list/datum/organ/external/parts = get_damageable_organs() + if(!parts.len) return + var/datum/organ/external/picked = pick(parts) + if(picked.take_damage(brute,burn,sharp,edge)) + UpdateDamageIcon() hud_updateflag |= 1 << HEALTH_HUD - updatehealth() - //speech_problem_flag = 1 - - -//Heal MANY external organs, in random order -/mob/living/carbon/human/heal_overall_damage(var/brute, var/burn) - var/list/datum/organ/external/parts = get_damaged_organs(brute,burn) - - var/update = 0 - while(parts.len && (brute>0 || burn>0) ) - var/datum/organ/external/picked = pick(parts) - - var/brute_was = picked.brute_dam - var/burn_was = picked.burn_dam - - update |= picked.heal_damage(brute,burn) - - brute -= (brute_was-picked.brute_dam) - burn -= (burn_was-picked.burn_dam) - - parts -= picked - updatehealth() + updatehealth() + //speech_problem_flag = 1 + + +//Heal MANY external organs, in random order +/mob/living/carbon/human/heal_overall_damage(var/brute, var/burn) + var/list/datum/organ/external/parts = get_damaged_organs(brute,burn) + + var/update = 0 + while(parts.len && (brute>0 || burn>0) ) + var/datum/organ/external/picked = pick(parts) + + var/brute_was = picked.brute_dam + var/burn_was = picked.burn_dam + + update |= picked.heal_damage(brute,burn) + + brute -= (brute_was-picked.brute_dam) + burn -= (burn_was-picked.burn_dam) + + parts -= picked + updatehealth() hud_updateflag |= 1 << HEALTH_HUD - //speech_problem_flag = 1 - if(update) UpdateDamageIcon() - -// damage MANY external organs, in random order -/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/sharp = 0, var/edge = 0, var/used_weapon = null) - if(status_flags & GODMODE) return //godmode - var/list/datum/organ/external/parts = get_damageable_organs() - var/update = 0 - while(parts.len && (brute>0 || burn>0) ) - var/datum/organ/external/picked = pick(parts) - - var/brute_was = picked.brute_dam - var/burn_was = picked.burn_dam - - update |= picked.take_damage(brute,burn,sharp,edge,used_weapon) - brute -= (picked.brute_dam - brute_was) - burn -= (picked.burn_dam - burn_was) - - parts -= picked - updatehealth() + //speech_problem_flag = 1 + if(update) UpdateDamageIcon() + +// damage MANY external organs, in random order +/mob/living/carbon/human/take_overall_damage(var/brute, var/burn, var/sharp = 0, var/edge = 0, var/used_weapon = null) + if(status_flags & GODMODE) return //godmode + var/list/datum/organ/external/parts = get_damageable_organs() + var/update = 0 + while(parts.len && (brute>0 || burn>0) ) + var/datum/organ/external/picked = pick(parts) + + var/brute_was = picked.brute_dam + var/burn_was = picked.burn_dam + + update |= picked.take_damage(brute,burn,sharp,edge,used_weapon) + brute -= (picked.brute_dam - brute_was) + burn -= (picked.burn_dam - burn_was) + + parts -= picked + updatehealth() hud_updateflag |= 1 << HEALTH_HUD - if(update) UpdateDamageIcon() - - -//////////////////////////////////////////// - -/* -This function restores the subjects blood to max. -*/ -/mob/living/carbon/human/proc/restore_blood() - if(!species.flags & NO_BLOOD) - var/blood_volume = vessel.get_reagent_amount("blood") - vessel.add_reagent("blood",560.0-blood_volume) - - -/* -This function restores all organs. -*/ -/mob/living/carbon/human/restore_all_organs() - for(var/datum/organ/external/current_organ in organs) - current_organ.rejuvenate() - -/mob/living/carbon/human/proc/HealDamage(zone, brute, burn) - var/datum/organ/external/E = get_organ(zone) - if(istype(E, /datum/organ/external)) - if (E.heal_damage(brute, burn)) - UpdateDamageIcon() + if(update) UpdateDamageIcon() + + +//////////////////////////////////////////// + +/* +This function restores the subjects blood to max. +*/ +/mob/living/carbon/human/proc/restore_blood() + if(!species.flags & NO_BLOOD) + var/blood_volume = vessel.get_reagent_amount("blood") + vessel.add_reagent("blood",560.0-blood_volume) + + +/* +This function restores all organs. +*/ +/mob/living/carbon/human/restore_all_organs() + for(var/datum/organ/external/current_organ in organs) + current_organ.rejuvenate() + +/mob/living/carbon/human/proc/HealDamage(zone, brute, burn) + var/datum/organ/external/E = get_organ(zone) + if(istype(E, /datum/organ/external)) + if (E.heal_damage(brute, burn)) + UpdateDamageIcon() hud_updateflag |= 1 << HEALTH_HUD - else - return 0 - return - - -/mob/living/carbon/human/proc/get_organ(var/zone) - if(!zone) zone = "chest" - if (zone in list( "eyes", "mouth" )) - zone = "head" - return organs_by_name[zone] - -/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) - - //visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]") - if((damagetype != BRUTE) && (damagetype != BURN)) - ..(damage, damagetype, def_zone, blocked) - return 1 - - if(blocked >= 2) return 0 - - var/datum/organ/external/organ = null - if(isorgan(def_zone)) - organ = def_zone - else - if(!def_zone) def_zone = ran_zone(def_zone) - organ = get_organ(check_zone(def_zone)) - if(!organ) return 0 - - if(blocked) - damage = (damage/(blocked+1)) - - switch(damagetype) - if(BRUTE) - damageoverlaytemp = 20 - if(species && species.brute_mod) - damage = damage*species.brute_mod - if(organ.take_damage(damage, 0, sharp, edge, used_weapon)) - UpdateDamageIcon(1) - if(BURN) - damageoverlaytemp = 20 - if(species && species.burn_mod) - damage = damage*species.burn_mod - if(organ.take_damage(0, damage, sharp, edge, used_weapon)) - UpdateDamageIcon(1) - - // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). - updatehealth() + else + return 0 + return + + +/mob/living/carbon/human/proc/get_organ(var/zone) + if(!zone) zone = "chest" + if (zone in list( "eyes", "mouth" )) + zone = "head" + return organs_by_name[zone] + +/mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) + + //visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]") + if((damagetype != BRUTE) && (damagetype != BURN)) + ..(damage, damagetype, def_zone, blocked) + return 1 + + if(blocked >= 2) return 0 + + var/datum/organ/external/organ = null + if(isorgan(def_zone)) + organ = def_zone + else + if(!def_zone) def_zone = ran_zone(def_zone) + organ = get_organ(check_zone(def_zone)) + if(!organ) return 0 + + if(blocked) + damage = (damage/(blocked+1)) + + switch(damagetype) + if(BRUTE) + damageoverlaytemp = 20 + if(species && species.brute_mod) + damage = damage*species.brute_mod + if(organ.take_damage(damage, 0, sharp, edge, used_weapon)) + UpdateDamageIcon(1) + if(BURN) + damageoverlaytemp = 20 + if(species && species.burn_mod) + damage = damage*species.burn_mod + if(organ.take_damage(0, damage, sharp, edge, used_weapon)) + UpdateDamageIcon(1) + + // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). + updatehealth() hud_updateflag |= 1 << HEALTH_HUD - - //Embedded projectile code. - if(!organ) return -/*VG EDIT - if(istype(used_weapon,/obj/item/weapon)) - var/obj/item/weapon/W = used_weapon //Sharp objects will always embed if they do enough damage. - if( (damage > (10*W.w_class)) && ( (sharp && !ismob(W.loc)) || prob(damage/W.w_class) ) ) - if(!istype(W, /obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver)) - organ.implants += W - visible_message("\The [W] sticks in the wound!") - W.add_blood(src) - if(ismob(W.loc)) - var/mob/living/H = W.loc - H.drop_item(W, src) - W.loc = src -*/ - if(istype(used_weapon,/obj/item/projectile/bullet)) //We don't want to use the actual projectile item, so we spawn some shrapnel. - var/obj/item/projectile/bullet/P = used_weapon - if(prob(75) && damagetype == BRUTE && P.embed) - var/obj/item/weapon/shard/shrapnel/S = new() - S.name = "[P.name] shrapnel" - S.desc = "[S.desc] It looks like it was fired from [P.shot_from]." - S.loc = src - organ.implants += S - visible_message("The projectile sticks in the wound!") - S.add_blood(src) - if(istype(used_weapon,/obj/item/projectile/flare)) //We want them to carry the flare, not a projectile - var/obj/item/projectile/flare/F = used_weapon - if(damagetype == BURN && F.embed && (istype(F.shot_from, /obj/item/weapon/gun/projectile/flare/syndicate) || istype(F.shot_from, /obj/item/weapon/gun/lawgiver)) && prob(75)) //only syndicate guns are dangerous, except for the lawgiver, which is intended to fire incendiary rounds - var/obj/item/device/flashlight/flare/FS = new - FS.name = "shot [FS.name]" - FS.desc = "[FS.desc]. It looks like it was fired from [F.shot_from]." - FS.loc = src - organ.implants += FS - visible_message("The flare sticks in the wound!") - FS.add_blood(src) - FS.luminosity = 4 //not so bright, because it's inside them - FS.Light(src) //Now they glow, because the flare is lit - if(prob(80)) //tends to happen, which is good - visible_message("[name] bursts into flames!", "You burst into flames!") - on_fire = 1 - adjust_fire_stacks(0.5) //as seen in ignite code - update_icon = 1 - qdel(F) - return 1 + + //Embedded projectile code. + if(!organ) return +/*VG EDIT + if(istype(used_weapon,/obj/item/weapon)) + var/obj/item/weapon/W = used_weapon //Sharp objects will always embed if they do enough damage. + if( (damage > (10*W.w_class)) && ( (sharp && !ismob(W.loc)) || prob(damage/W.w_class) ) ) + if(!istype(W, /obj/item/weapon/kitchen/utensil/knife/large/butch/meatcleaver)) + organ.implants += W + visible_message("\The [W] sticks in the wound!") + W.add_blood(src) + if(ismob(W.loc)) + var/mob/living/H = W.loc + H.drop_item(W, src) + W.loc = src +*/ + if(istype(used_weapon,/obj/item/projectile/bullet)) //We don't want to use the actual projectile item, so we spawn some shrapnel. + var/obj/item/projectile/bullet/P = used_weapon + if(prob(75) && damagetype == BRUTE && P.embed) + var/obj/item/weapon/shard/shrapnel/S = new() + S.name = "[P.name] shrapnel" + S.desc = "[S.desc] It looks like it was fired from [P.shot_from]." + S.loc = src + organ.implants += S + visible_message("The projectile sticks in the wound!") + S.add_blood(src) + if(istype(used_weapon,/obj/item/projectile/flare)) //We want them to carry the flare, not a projectile + var/obj/item/projectile/flare/F = used_weapon + if(damagetype == BURN && F.embed && (istype(F.shot_from, /obj/item/weapon/gun/projectile/flare/syndicate) || istype(F.shot_from, /obj/item/weapon/gun/lawgiver)) && prob(75)) //only syndicate guns are dangerous, except for the lawgiver, which is intended to fire incendiary rounds + var/obj/item/device/flashlight/flare/FS = new + FS.name = "shot [FS.name]" + FS.desc = "[FS.desc]. It looks like it was fired from [F.shot_from]." + FS.loc = src + organ.implants += FS + visible_message("The flare sticks in the wound!") + FS.add_blood(src) + FS.luminosity = 4 //not so bright, because it's inside them + FS.Light(src) //Now they glow, because the flare is lit + if(prob(80)) //tends to happen, which is good + visible_message("[name] bursts into flames!", "You burst into flames!") + on_fire = 1 + adjust_fire_stacks(0.5) //as seen in ignite code + update_icon = 1 + qdel(F) + return 1 diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index d87d21be9e1..99bf9b5a126 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,79 +1,79 @@ -/mob/living/carbon/human - //Hair colour and style - var/r_hair = 0 - var/g_hair = 0 - var/b_hair = 0 - var/h_style = "Bald" - - //Facial hair colour and style - var/r_facial = 0 - var/g_facial = 0 - var/b_facial = 0 - var/f_style = "Shaved" - - //Eye colour - var/r_eyes = 0 - var/g_eyes = 0 - var/b_eyes = 0 - - var/s_tone = 0 //Skin tone - - var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup - - mob_bump_flag = HUMAN - mob_push_flags = ALLMOBS - mob_swap_flags = ALLMOBS - - var/age = 30 //Player's age (pure fluff) - var/b_type = "A+" //Player's bloodtype - - var/underwear = 1 //Which underwear the player wants - var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. - - //Equipment slots - var/obj/item/wear_suit = null - var/obj/item/w_uniform = null - var/obj/item/shoes = null - var/obj/item/belt = null - var/obj/item/gloves = null - var/obj/item/clothing/glasses/glasses = null - var/obj/item/head = null - var/obj/item/ears = null - var/obj/item/wear_id = null - var/obj/item/r_store = null - var/obj/item/l_store = null - var/obj/item/s_store = null - var/obj/item/l_ear = null - var/obj/item/r_ear = null - - var/used_skillpoints = 0 - var/skill_specialization = null - var/list/skills = null - - var/icon/stand_icon = null - var/icon/lying_icon = null - - var/miming = null //Toggle for the mime's abilities. - var/special_voice = "" // For changing our voice. Used by a symptom. - var/said_last_words=0 - - var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. - - var/last_dam = -1 //Used for determining if we need to process all organs or just some or even none. - var/list/bad_external_organs = list()// organs we check until they are good. - - var/xylophone = 0 //For the spoooooooky xylophone cooldown - - var/mob/remoteview_target = null - var/hand_blood_color - - var/meatleft = 3 //For chef item - - var/check_mutations=0 // Check mutations on next life tick - - var/lastFart = 0 // Toxic fart cooldown. - var/lastScream = 0 // Prevent scream spam in some situations - - - fire_dmi = 'icons/mob/OnFire.dmi' +/mob/living/carbon/human + //Hair colour and style + var/r_hair = 0 + var/g_hair = 0 + var/b_hair = 0 + var/h_style = "Bald" + + //Facial hair colour and style + var/r_facial = 0 + var/g_facial = 0 + var/b_facial = 0 + var/f_style = "Shaved" + + //Eye colour + var/r_eyes = 0 + var/g_eyes = 0 + var/b_eyes = 0 + + var/s_tone = 0 //Skin tone + + var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup + + mob_bump_flag = HUMAN + mob_push_flags = ALLMOBS + mob_swap_flags = ALLMOBS + + var/age = 30 //Player's age (pure fluff) + var/b_type = "A+" //Player's bloodtype + + var/underwear = 1 //Which underwear the player wants + var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. + + //Equipment slots + var/obj/item/wear_suit = null + var/obj/item/w_uniform = null + var/obj/item/shoes = null + var/obj/item/belt = null + var/obj/item/gloves = null + var/obj/item/clothing/glasses/glasses = null + var/obj/item/head = null + var/obj/item/ears = null + var/obj/item/wear_id = null + var/obj/item/r_store = null + var/obj/item/l_store = null + var/obj/item/s_store = null + var/obj/item/l_ear = null + var/obj/item/r_ear = null + + var/used_skillpoints = 0 + var/skill_specialization = null + var/list/skills = null + + var/icon/stand_icon = null + var/icon/lying_icon = null + + var/miming = null //Toggle for the mime's abilities. + var/special_voice = "" // For changing our voice. Used by a symptom. + var/said_last_words=0 + + var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. + + var/last_dam = -1 //Used for determining if we need to process all organs or just some or even none. + var/list/bad_external_organs = list()// organs we check until they are good. + + var/xylophone = 0 //For the spoooooooky xylophone cooldown + + var/mob/remoteview_target = null + var/hand_blood_color + + var/meatleft = 3 //For chef item + + var/check_mutations=0 // Check mutations on next life tick + + var/lastFart = 0 // Toxic fart cooldown. + var/lastScream = 0 // Prevent scream spam in some situations + + + fire_dmi = 'icons/mob/OnFire.dmi' fire_sprite = "Standing" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index d5e4af24d66..33611ac5082 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,151 +1,151 @@ -/mob/living/carbon/human/movement_delay() - var/tally = 0 - if(species && species.move_speed_mod) - tally += species.move_speed_mod - if (istype(loc, /turf/space)) return -1 // It's hard to be slowed down in space by... anything - - //(VG EDIT disabling for now) handle_embedded_objects() //Moving with objects stuck in you can cause bad times. - - if(flying) - return -1 - - if(reagents.has_reagent("hyperzine")) - if(dna.mutantrace == "slime") - tally *= 2 - else - tally -= 10 - - if(reagents.has_reagent("nuka_cola")) tally -= 10 - - if((M_RUN in mutations)) tally -= 10 - - if (istype(loc, /turf/space)) return -1 // It's hard to be slowed down in space by... anything - - if(istype(loc,/turf/simulated/floor)) - var/turf/simulated/floor/T = loc - - if(T.material=="phazon") - return -1 // Phazon floors make us go fast - - var/health_deficiency = (100 - health - halloss) - if(health_deficiency >= 40) tally += (health_deficiency / 25) - - var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80 - if (hungry >= 70) tally += hungry/50 - - if(wear_suit) - tally += wear_suit.slowdown - - if(shoes) - tally += shoes.slowdown - - if(istype(l_hand,/obj/item/offhand)) - tally += r_hand.slowdown - - if(istype(r_hand,/obj/item/offhand)) - tally += l_hand.slowdown - - if(reagents.has_reagent("frostoil") && dna.mutantrace == "slime") - tally *= 5 - - for(var/organ_name in list("l_foot","r_foot","l_leg","r_leg")) - var/datum/organ/external/E = get_organ(organ_name) - if(!E || (E.status & ORGAN_DESTROYED)) - tally += 4 - if(E.status & ORGAN_SPLINTED) - tally += 0.5 - else if(E.status & ORGAN_BROKEN) - tally += 1.5 - - if(shock_stage >= 50) tally += 3 - - if(M_FAT in src.mutations) - tally += 1.5 - if(dna.mutantrace == "slime") - if (bodytemperature >= 330.23) // 135 F - return -1 // slimes become supercharged at high temperatures - if (bodytemperature < 183.222) - tally += (283.222 - bodytemperature) / 10 * 1.75 - else if (bodytemperature < 283.222) - - tally += (283.222 - bodytemperature) / 10 * 1.75 - - var/skate_bonus = 0 - var/disease_slow = 0 - for(var/obj/item/weapon/bomberman/dispenser in src) - disease_slow = max(disease_slow, dispenser.slow) - skate_bonus = max(skate_bonus, dispenser.speed_bonus)//if the player is carrying multiple BBD for some reason, he'll benefit from the speed bonus of the most upgraded one - tally = tally - skate_bonus + (6 * disease_slow) - - return max((tally+config.human_delay), -1) //cap at -1 as the 'fastest' - -/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0) - //Can we act - if(restrained()) return 0 - - //Are we flying? - if(flying) - inertia_dir = 0 - return 1 - - //Do we have a working jetpack - if(istype(back, /obj/item/weapon/tank/jetpack)) - var/obj/item/weapon/tank/jetpack/J = back - if(((!check_drift) || (check_drift && J.stabilization_on)) && (!lying) && (J.allow_thrust(0.01, src))) - inertia_dir = 0 - return 1 -// if(!check_drift && J.allow_thrust(0.01, src)) -// return 1 - - //If no working jetpack then use the other checks - if(..()) return 1 - return 0 - - -/mob/living/carbon/human/Process_Spaceslipping(var/prob_slip = 5) - //If knocked out we might just hit it and stop. This makes it possible to get dead bodies and such. - if(stat) - prob_slip = 0 // Changing this to zero to make it line up with the comment, and also, make more sense. - - //Do we have magboots or such on if so no slip - if(CheckSlip() < 0) - prob_slip = 0 - - //Check hands and mod slip - if(!l_hand) prob_slip -= 2 - else if(l_hand.w_class <= 2) prob_slip -= 1 - if (!r_hand) prob_slip -= 2 - else if(r_hand.w_class <= 2) prob_slip -= 1 - - prob_slip = round(prob_slip) - return(prob_slip) - -/mob/living/carbon/human/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0) - var/old_z = src.z - - . = ..(NewLoc, Dir, step_x, step_y) - - if(status_flags & FAKEDEATH) - return 0 - - if(.) - if (old_z != src.z) crewmonitor.queueUpdate(old_z) - crewmonitor.queueUpdate(src.z) - - if(shoes && istype(shoes, /obj/item/clothing/shoes)) - var/obj/item/clothing/shoes/S = shoes - S.step_action() - - for(var/obj/item/weapon/bomberman/dispenser in src) - if(dispenser.spam_bomb) - dispenser.attack_self(src) - - var/obj/item/weapon/rcl/R = get_active_hand() - if(R && istype(R) && R.active) - R.trigger(src) - -/mob/living/carbon/human/CheckSlip() - . = ..() - if(. && shoes && shoes.flags & NOSLIP) - . = (istype(shoes, /obj/item/clothing/shoes/magboots) ? -1 : 0) - return . +/mob/living/carbon/human/movement_delay() + var/tally = 0 + if(species && species.move_speed_mod) + tally += species.move_speed_mod + if (istype(loc, /turf/space)) return -1 // It's hard to be slowed down in space by... anything + + //(VG EDIT disabling for now) handle_embedded_objects() //Moving with objects stuck in you can cause bad times. + + if(flying) + return -1 + + if(reagents.has_reagent("hyperzine")) + if(dna.mutantrace == "slime") + tally *= 2 + else + tally -= 10 + + if(reagents.has_reagent("nuka_cola")) tally -= 10 + + if((M_RUN in mutations)) tally -= 10 + + if (istype(loc, /turf/space)) return -1 // It's hard to be slowed down in space by... anything + + if(istype(loc,/turf/simulated/floor)) + var/turf/simulated/floor/T = loc + + if(T.material=="phazon") + return -1 // Phazon floors make us go fast + + var/health_deficiency = (100 - health - halloss) + if(health_deficiency >= 40) tally += (health_deficiency / 25) + + var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80 + if (hungry >= 70) tally += hungry/50 + + if(wear_suit) + tally += wear_suit.slowdown + + if(shoes) + tally += shoes.slowdown + + if(istype(l_hand,/obj/item/offhand)) + tally += r_hand.slowdown + + if(istype(r_hand,/obj/item/offhand)) + tally += l_hand.slowdown + + if(reagents.has_reagent("frostoil") && dna.mutantrace == "slime") + tally *= 5 + + for(var/organ_name in list("l_foot","r_foot","l_leg","r_leg")) + var/datum/organ/external/E = get_organ(organ_name) + if(!E || (E.status & ORGAN_DESTROYED)) + tally += 4 + if(E.status & ORGAN_SPLINTED) + tally += 0.5 + else if(E.status & ORGAN_BROKEN) + tally += 1.5 + + if(shock_stage >= 50) tally += 3 + + if(M_FAT in src.mutations) + tally += 1.5 + if(dna.mutantrace == "slime") + if (bodytemperature >= 330.23) // 135 F + return -1 // slimes become supercharged at high temperatures + if (bodytemperature < 183.222) + tally += (283.222 - bodytemperature) / 10 * 1.75 + else if (bodytemperature < 283.222) + + tally += (283.222 - bodytemperature) / 10 * 1.75 + + var/skate_bonus = 0 + var/disease_slow = 0 + for(var/obj/item/weapon/bomberman/dispenser in src) + disease_slow = max(disease_slow, dispenser.slow) + skate_bonus = max(skate_bonus, dispenser.speed_bonus)//if the player is carrying multiple BBD for some reason, he'll benefit from the speed bonus of the most upgraded one + tally = tally - skate_bonus + (6 * disease_slow) + + return max((tally+config.human_delay), -1) //cap at -1 as the 'fastest' + +/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0) + //Can we act + if(restrained()) return 0 + + //Are we flying? + if(flying) + inertia_dir = 0 + return 1 + + //Do we have a working jetpack + if(istype(back, /obj/item/weapon/tank/jetpack)) + var/obj/item/weapon/tank/jetpack/J = back + if(((!check_drift) || (check_drift && J.stabilization_on)) && (!lying) && (J.allow_thrust(0.01, src))) + inertia_dir = 0 + return 1 +// if(!check_drift && J.allow_thrust(0.01, src)) +// return 1 + + //If no working jetpack then use the other checks + if(..()) return 1 + return 0 + + +/mob/living/carbon/human/Process_Spaceslipping(var/prob_slip = 5) + //If knocked out we might just hit it and stop. This makes it possible to get dead bodies and such. + if(stat) + prob_slip = 0 // Changing this to zero to make it line up with the comment, and also, make more sense. + + //Do we have magboots or such on if so no slip + if(CheckSlip() < 0) + prob_slip = 0 + + //Check hands and mod slip + if(!l_hand) prob_slip -= 2 + else if(l_hand.w_class <= 2) prob_slip -= 1 + if (!r_hand) prob_slip -= 2 + else if(r_hand.w_class <= 2) prob_slip -= 1 + + prob_slip = round(prob_slip) + return(prob_slip) + +/mob/living/carbon/human/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0) + var/old_z = src.z + + . = ..(NewLoc, Dir, step_x, step_y) + + if(status_flags & FAKEDEATH) + return 0 + + if(.) + if (old_z != src.z) crewmonitor.queueUpdate(old_z) + crewmonitor.queueUpdate(src.z) + + if(shoes && istype(shoes, /obj/item/clothing/shoes)) + var/obj/item/clothing/shoes/S = shoes + S.step_action() + + for(var/obj/item/weapon/bomberman/dispenser in src) + if(dispenser.spam_bomb) + dispenser.attack_self(src) + + var/obj/item/weapon/rcl/R = get_active_hand() + if(R && istype(R) && R.active) + R.trigger(src) + +/mob/living/carbon/human/CheckSlip() + . = ..() + if(. && shoes && shoes.flags & NOSLIP) + . = (istype(shoes, /obj/item/clothing/shoes/magboots) ? -1 : 0) + return . diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 583dce0e1c7..12779a37c54 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,936 +1,936 @@ -/mob/living/carbon/human/verb/quick_equip() - set name = "quick-equip" - set hidden = 1 - - if(ishuman(src)) - var/mob/living/carbon/human/H = src - var/obj/item/I = H.get_active_hand() - if(!I) +/mob/living/carbon/human/verb/quick_equip() + set name = "quick-equip" + set hidden = 1 + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + var/obj/item/I = H.get_active_hand() + if(!I) to_chat(H, "You are not holding anything to equip.") - return - if(H.equip_to_appropriate_slot(I)) - if(hand) - update_inv_l_hand(0) - else - update_inv_r_hand(0) - else + return + if(H.equip_to_appropriate_slot(I)) + if(hand) + update_inv_l_hand(0) + else + update_inv_r_hand(0) + else to_chat(H, "You are unable to equip that.") - -/mob/living/carbon/human/get_all_slots() - . = get_head_slots() | get_body_slots() - -/mob/living/carbon/human/proc/get_body_slots() - return list( -//ordered body items by which would appear on top - l_hand, - r_hand, - back, - s_store, - handcuffed, - legcuffed, - wear_suit, - gloves, - shoes, - belt, - wear_id, - l_store, - r_store, - w_uniform) - -/mob/living/carbon/human/proc/get_head_slots() - return list( -//also head ordered - head, - wear_mask, - glasses, - ears - ) - -//everything on the mob that is not in its pockets, hands and belt. -/mob/living/carbon/human/get_clothing_items(var/list/filter) - if(!filter || !istype(filter)) - filter = get_all_slots() - filter -= list(back, - handcuffed, - legcuffed, - belt, - wear_id, - l_hand, - r_hand, - l_store, - r_store, - s_store) - return filter - -/mob/living/carbon/human/proc/check_obscured_slots() - var/list/obscured = list() - - if(wear_suit) - if(wear_suit.flags_inv & HIDEGLOVES) - obscured |= slot_gloves - if(wear_suit.flags_inv & HIDEJUMPSUIT) - obscured |= slot_w_uniform - if(wear_suit.flags_inv & HIDESHOES) - obscured |= slot_shoes - - if(head) - if(head.flags_inv & HIDEMASK) - obscured |= slot_wear_mask - if(head.flags_inv & HIDEEYES) - obscured |= slot_glasses - if(head.flags_inv & HIDEEARS) - obscured |= slot_ears - - if(obscured.len > 0) - return obscured - else - return null - -//The args for check_hidden_flags are the list of equipment, and then the flags -//The arg for get_clothing items is the list of equipment - this filters stuff like hands, pockets, suit_storage, etc -//get_head_slots and get_body_slots do exactly what you think they do -/mob/living/carbon/human/proc/check_hidden_head_flags(var/hidden_flags = 0) - return check_hidden_flags(get_clothing_items(get_head_slots()), hidden_flags) - -/mob/living/carbon/human/proc/check_hidden_body_flags(var/hidden_flags = 0) - return check_hidden_flags(get_clothing_items(get_body_slots()), hidden_flags) - -/mob/living/carbon/human/proc/check_hidden_flags(var/list/items, var/hidden_flags = 0) - if(!items || !istype(items)) - items = get_clothing_items() //no argument returns all clothing - for(var/obj/item/equipped in items) - if(!equipped) - continue - if(equipped.flags_inv & hidden_flags) - return 1 - -/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, act_on_fail = 1) - for (var/slot in slots) - if (equip_to_slot_if_possible(W, slots[slot], 0)) - return slot - switch (act_on_fail) - if(EQUIP_FAILACTION_DELETE) - qdel(W) - W = null - if(EQUIP_FAILACTION_DROP) - W.loc=get_turf(src) // I think. - return null - -/mob/living/carbon/human/proc/is_on_ears(var/typepath) - return istype(ears,typepath) - -/mob/living/carbon/human/proc/is_in_hands(var/typepath) - if(istype(l_hand,typepath)) - return l_hand - if(istype(r_hand,typepath)) - return r_hand - return 0 - -/mob/living/carbon/human/put_in_hand_check(obj/item/I, this_hand) - if(!src.can_use_hand(this_hand)) - return 0 - - return ..() - -// Return the item currently in the slot ID -/mob/living/carbon/human/get_item_by_slot(slot_id) - switch(slot_id) - if(slot_back) - return back - if(slot_wear_mask) - return wear_mask - if(slot_handcuffed) - return handcuffed - if(slot_legcuffed) - return legcuffed - if(slot_l_hand) - return l_hand - if(slot_r_hand) - return r_hand - if(slot_belt) - return belt - if(slot_wear_id) - return wear_id - if(slot_ears) - return ears - if(slot_glasses) - return glasses - if(slot_gloves) - return gloves - if(slot_head) - return head - if(slot_shoes) - return shoes - if(slot_wear_suit) - return wear_suit - if(slot_w_uniform) - return w_uniform - if(slot_l_store) - return l_store - if(slot_r_store) - return r_store - if(slot_s_store) - return s_store - return null - -/mob/living/carbon/human/proc/has_organ(name) - var/datum/organ/external/O = organs_by_name[name] - - return (O && !(O.status & ORGAN_DESTROYED) ) - -/mob/living/carbon/human/proc/has_organ_for_slot(slot) - switch(slot) - if(slot_back) - return has_organ("chest") - if(slot_wear_mask) - return has_organ("head") - if(slot_handcuffed) - return has_organ("l_hand") && has_organ("r_hand") - if(slot_legcuffed) - return has_organ("l_leg") && has_organ("r_leg") - if(slot_l_hand) - return has_organ("l_hand") - if(slot_r_hand) - return has_organ("r_hand") - if(slot_belt) - return has_organ("chest") - if(slot_wear_id) - // the only relevant check for this is the uniform check - return 1 - if(slot_ears) - return has_organ("head") - if(slot_glasses) - return has_organ("head") - if(slot_gloves) - return has_organ("l_hand") && has_organ("r_hand") - if(slot_head) - return has_organ("head") - if(slot_shoes) - return has_organ("r_foot") && has_organ("l_foot") - if(slot_wear_suit) - return has_organ("chest") - if(slot_w_uniform) - return has_organ("chest") - if(slot_l_store) - return has_organ("chest") - if(slot_r_store) - return has_organ("chest") - if(slot_s_store) - return has_organ("chest") - if(slot_in_backpack) - return 1 - -/mob/living/carbon/human/u_equip(obj/item/W as obj, dropped = 1) - if(!W) return 0 - - var/success - - if (W == wear_suit) - if(s_store) - u_equip(s_store, 1) - success = 1 - wear_suit = null - update_inv_wear_suit() - else if (W == w_uniform) - if (r_store) - u_equip(r_store, 1) - if (l_store) - u_equip(l_store, 1) - if (wear_id) - u_equip(wear_id, 1) - if (belt) - u_equip(belt, 1) - w_uniform = null - success = 1 - update_inv_w_uniform() - else if (W == gloves) - gloves = null - success = 1 - update_inv_gloves() - else if (W == glasses) - glasses = null - success = 1 - update_inv_glasses() - else if (W == head) - head = null - success = 1 - update_inv_head() - else if(W == ears) - ears = null - success = 1 - update_inv_ears() - else if (W == shoes) - shoes = null - success = 1 - update_inv_shoes() - else if (W == belt) - belt = null - success = 1 - update_inv_belt() - else if (W == wear_mask) - wear_mask = null - success = 1 - if(internal) - if(internals) - internals.icon_state = "internal0" - internal = null - update_inv_wear_mask() - else if (W == wear_id) - wear_id = null - success = 1 - update_inv_wear_id() - else if (W == r_store) - r_store = null - success = 1 - update_inv_pockets() - else if (W == l_store) - l_store = null - success = 1 - update_inv_pockets() - else if (W == s_store) - s_store = null - success = 1 - update_inv_s_store() - else if (W == back) - back = null - success = 1 - update_inv_back() - else if (W == handcuffed) - handcuffed = null - success = 1 - update_inv_handcuffed() - else if (W == legcuffed) - legcuffed = null - success = 1 - update_inv_legcuffed() - else if (W == r_hand) - r_hand = null - success = 1 - update_inv_r_hand() - else if (W == l_hand) - l_hand = null - success = 1 - update_inv_l_hand() - else - return 0 - - if(success) - update_hidden_item_icons(W) - - if(success) - if (W) - if (client) - client.screen -= W - W.loc = loc - W.unequipped() - if(dropped) W.dropped(src) - if(W) - W.layer = initial(W.layer) - update_action_buttons() - return 1 - - - -//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() -//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. -/mob/living/carbon/human/equip_to_slot(obj/item/W as obj, slot, redraw_mob = 1) - if(!slot) return - if(!istype(W)) return - if(!has_organ_for_slot(slot)) return - - if(W == src.l_hand) - src.l_hand = null - update_inv_l_hand() //So items actually disappear from hands. - else if(W == src.r_hand) - src.r_hand = null - update_inv_r_hand() - - switch(slot) - if(slot_back) - src.back = W - update_inv_back(redraw_mob) - if(slot_wear_mask) - src.wear_mask = W - update_inv_wear_mask(redraw_mob) - if(slot_handcuffed) - src.handcuffed = W - update_inv_handcuffed(redraw_mob) - if(slot_legcuffed) - src.legcuffed = W - update_inv_legcuffed(redraw_mob) - if(slot_l_hand) - src.l_hand = W - update_inv_l_hand(redraw_mob) - if(slot_r_hand) - src.r_hand = W - update_inv_r_hand(redraw_mob) - if(slot_belt) - src.belt = W - update_inv_belt(redraw_mob) - if(slot_wear_id) - src.wear_id = W - update_inv_wear_id(redraw_mob) - if(slot_ears) - ears = W - update_inv_ears(redraw_mob) - if(slot_glasses) - src.glasses = W - update_inv_glasses(redraw_mob) - if(slot_gloves) - src.gloves = W - update_inv_gloves(redraw_mob) - if(slot_head) - src.head = W - //if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR)) //Makes people bald when switching to one with no Blocking flags - // update_hair(redraw_mob) //rebuild hair - update_hair(redraw_mob) - if(istype(W,/obj/item/clothing/head/kitty)) - W.update_icon(src) - update_inv_head(redraw_mob) - if(slot_shoes) - src.shoes = W - update_inv_shoes(redraw_mob) - if(slot_wear_suit) - src.wear_suit = W - update_inv_wear_suit(redraw_mob) - if(slot_w_uniform) - src.w_uniform = W - update_inv_w_uniform(redraw_mob) - if(slot_l_store) - src.l_store = W - update_inv_pockets(redraw_mob) - if(slot_r_store) - src.r_store = W - update_inv_pockets(redraw_mob) - if(slot_s_store) - src.s_store = W - update_inv_s_store(redraw_mob) - if(slot_in_backpack) - if(src.get_active_hand() == W) - src.u_equip(W,0) - W.loc = src.back - return - else + +/mob/living/carbon/human/get_all_slots() + . = get_head_slots() | get_body_slots() + +/mob/living/carbon/human/proc/get_body_slots() + return list( +//ordered body items by which would appear on top + l_hand, + r_hand, + back, + s_store, + handcuffed, + legcuffed, + wear_suit, + gloves, + shoes, + belt, + wear_id, + l_store, + r_store, + w_uniform) + +/mob/living/carbon/human/proc/get_head_slots() + return list( +//also head ordered + head, + wear_mask, + glasses, + ears + ) + +//everything on the mob that is not in its pockets, hands and belt. +/mob/living/carbon/human/get_clothing_items(var/list/filter) + if(!filter || !istype(filter)) + filter = get_all_slots() + filter -= list(back, + handcuffed, + legcuffed, + belt, + wear_id, + l_hand, + r_hand, + l_store, + r_store, + s_store) + return filter + +/mob/living/carbon/human/proc/check_obscured_slots() + var/list/obscured = list() + + if(wear_suit) + if(wear_suit.flags_inv & HIDEGLOVES) + obscured |= slot_gloves + if(wear_suit.flags_inv & HIDEJUMPSUIT) + obscured |= slot_w_uniform + if(wear_suit.flags_inv & HIDESHOES) + obscured |= slot_shoes + + if(head) + if(head.flags_inv & HIDEMASK) + obscured |= slot_wear_mask + if(head.flags_inv & HIDEEYES) + obscured |= slot_glasses + if(head.flags_inv & HIDEEARS) + obscured |= slot_ears + + if(obscured.len > 0) + return obscured + else + return null + +//The args for check_hidden_flags are the list of equipment, and then the flags +//The arg for get_clothing items is the list of equipment - this filters stuff like hands, pockets, suit_storage, etc +//get_head_slots and get_body_slots do exactly what you think they do +/mob/living/carbon/human/proc/check_hidden_head_flags(var/hidden_flags = 0) + return check_hidden_flags(get_clothing_items(get_head_slots()), hidden_flags) + +/mob/living/carbon/human/proc/check_hidden_body_flags(var/hidden_flags = 0) + return check_hidden_flags(get_clothing_items(get_body_slots()), hidden_flags) + +/mob/living/carbon/human/proc/check_hidden_flags(var/list/items, var/hidden_flags = 0) + if(!items || !istype(items)) + items = get_clothing_items() //no argument returns all clothing + for(var/obj/item/equipped in items) + if(!equipped) + continue + if(equipped.flags_inv & hidden_flags) + return 1 + +/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, act_on_fail = 1) + for (var/slot in slots) + if (equip_to_slot_if_possible(W, slots[slot], 0)) + return slot + switch (act_on_fail) + if(EQUIP_FAILACTION_DELETE) + qdel(W) + W = null + if(EQUIP_FAILACTION_DROP) + W.loc=get_turf(src) // I think. + return null + +/mob/living/carbon/human/proc/is_on_ears(var/typepath) + return istype(ears,typepath) + +/mob/living/carbon/human/proc/is_in_hands(var/typepath) + if(istype(l_hand,typepath)) + return l_hand + if(istype(r_hand,typepath)) + return r_hand + return 0 + +/mob/living/carbon/human/put_in_hand_check(obj/item/I, this_hand) + if(!src.can_use_hand(this_hand)) + return 0 + + return ..() + +// Return the item currently in the slot ID +/mob/living/carbon/human/get_item_by_slot(slot_id) + switch(slot_id) + if(slot_back) + return back + if(slot_wear_mask) + return wear_mask + if(slot_handcuffed) + return handcuffed + if(slot_legcuffed) + return legcuffed + if(slot_l_hand) + return l_hand + if(slot_r_hand) + return r_hand + if(slot_belt) + return belt + if(slot_wear_id) + return wear_id + if(slot_ears) + return ears + if(slot_glasses) + return glasses + if(slot_gloves) + return gloves + if(slot_head) + return head + if(slot_shoes) + return shoes + if(slot_wear_suit) + return wear_suit + if(slot_w_uniform) + return w_uniform + if(slot_l_store) + return l_store + if(slot_r_store) + return r_store + if(slot_s_store) + return s_store + return null + +/mob/living/carbon/human/proc/has_organ(name) + var/datum/organ/external/O = organs_by_name[name] + + return (O && !(O.status & ORGAN_DESTROYED) ) + +/mob/living/carbon/human/proc/has_organ_for_slot(slot) + switch(slot) + if(slot_back) + return has_organ("chest") + if(slot_wear_mask) + return has_organ("head") + if(slot_handcuffed) + return has_organ("l_hand") && has_organ("r_hand") + if(slot_legcuffed) + return has_organ("l_leg") && has_organ("r_leg") + if(slot_l_hand) + return has_organ("l_hand") + if(slot_r_hand) + return has_organ("r_hand") + if(slot_belt) + return has_organ("chest") + if(slot_wear_id) + // the only relevant check for this is the uniform check + return 1 + if(slot_ears) + return has_organ("head") + if(slot_glasses) + return has_organ("head") + if(slot_gloves) + return has_organ("l_hand") && has_organ("r_hand") + if(slot_head) + return has_organ("head") + if(slot_shoes) + return has_organ("r_foot") && has_organ("l_foot") + if(slot_wear_suit) + return has_organ("chest") + if(slot_w_uniform) + return has_organ("chest") + if(slot_l_store) + return has_organ("chest") + if(slot_r_store) + return has_organ("chest") + if(slot_s_store) + return has_organ("chest") + if(slot_in_backpack) + return 1 + +/mob/living/carbon/human/u_equip(obj/item/W as obj, dropped = 1) + if(!W) return 0 + + var/success + + if (W == wear_suit) + if(s_store) + u_equip(s_store, 1) + success = 1 + wear_suit = null + update_inv_wear_suit() + else if (W == w_uniform) + if (r_store) + u_equip(r_store, 1) + if (l_store) + u_equip(l_store, 1) + if (wear_id) + u_equip(wear_id, 1) + if (belt) + u_equip(belt, 1) + w_uniform = null + success = 1 + update_inv_w_uniform() + else if (W == gloves) + gloves = null + success = 1 + update_inv_gloves() + else if (W == glasses) + glasses = null + success = 1 + update_inv_glasses() + else if (W == head) + head = null + success = 1 + update_inv_head() + else if(W == ears) + ears = null + success = 1 + update_inv_ears() + else if (W == shoes) + shoes = null + success = 1 + update_inv_shoes() + else if (W == belt) + belt = null + success = 1 + update_inv_belt() + else if (W == wear_mask) + wear_mask = null + success = 1 + if(internal) + if(internals) + internals.icon_state = "internal0" + internal = null + update_inv_wear_mask() + else if (W == wear_id) + wear_id = null + success = 1 + update_inv_wear_id() + else if (W == r_store) + r_store = null + success = 1 + update_inv_pockets() + else if (W == l_store) + l_store = null + success = 1 + update_inv_pockets() + else if (W == s_store) + s_store = null + success = 1 + update_inv_s_store() + else if (W == back) + back = null + success = 1 + update_inv_back() + else if (W == handcuffed) + handcuffed = null + success = 1 + update_inv_handcuffed() + else if (W == legcuffed) + legcuffed = null + success = 1 + update_inv_legcuffed() + else if (W == r_hand) + r_hand = null + success = 1 + update_inv_r_hand() + else if (W == l_hand) + l_hand = null + success = 1 + update_inv_l_hand() + else + return 0 + + if(success) + update_hidden_item_icons(W) + + if(success) + if (W) + if (client) + client.screen -= W + W.loc = loc + W.unequipped() + if(dropped) W.dropped(src) + if(W) + W.layer = initial(W.layer) + update_action_buttons() + return 1 + + + +//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() +//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. +/mob/living/carbon/human/equip_to_slot(obj/item/W as obj, slot, redraw_mob = 1) + if(!slot) return + if(!istype(W)) return + if(!has_organ_for_slot(slot)) return + + if(W == src.l_hand) + src.l_hand = null + update_inv_l_hand() //So items actually disappear from hands. + else if(W == src.r_hand) + src.r_hand = null + update_inv_r_hand() + + switch(slot) + if(slot_back) + src.back = W + update_inv_back(redraw_mob) + if(slot_wear_mask) + src.wear_mask = W + update_inv_wear_mask(redraw_mob) + if(slot_handcuffed) + src.handcuffed = W + update_inv_handcuffed(redraw_mob) + if(slot_legcuffed) + src.legcuffed = W + update_inv_legcuffed(redraw_mob) + if(slot_l_hand) + src.l_hand = W + update_inv_l_hand(redraw_mob) + if(slot_r_hand) + src.r_hand = W + update_inv_r_hand(redraw_mob) + if(slot_belt) + src.belt = W + update_inv_belt(redraw_mob) + if(slot_wear_id) + src.wear_id = W + update_inv_wear_id(redraw_mob) + if(slot_ears) + ears = W + update_inv_ears(redraw_mob) + if(slot_glasses) + src.glasses = W + update_inv_glasses(redraw_mob) + if(slot_gloves) + src.gloves = W + update_inv_gloves(redraw_mob) + if(slot_head) + src.head = W + //if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR)) //Makes people bald when switching to one with no Blocking flags + // update_hair(redraw_mob) //rebuild hair + update_hair(redraw_mob) + if(istype(W,/obj/item/clothing/head/kitty)) + W.update_icon(src) + update_inv_head(redraw_mob) + if(slot_shoes) + src.shoes = W + update_inv_shoes(redraw_mob) + if(slot_wear_suit) + src.wear_suit = W + update_inv_wear_suit(redraw_mob) + if(slot_w_uniform) + src.w_uniform = W + update_inv_w_uniform(redraw_mob) + if(slot_l_store) + src.l_store = W + update_inv_pockets(redraw_mob) + if(slot_r_store) + src.r_store = W + update_inv_pockets(redraw_mob) + if(slot_s_store) + src.s_store = W + update_inv_s_store(redraw_mob) + if(slot_in_backpack) + if(src.get_active_hand() == W) + src.u_equip(W,0) + W.loc = src.back + return + else to_chat(src, "You are trying to equip this item to an unsupported inventory slot. Report this to a coder!") - return - - update_hidden_item_icons(W) - - W.layer = 20 - W.equipped(src, slot) - W.loc = src - - -/obj/effect/equip_e - name = "equip e" - var/mob/source = null - var/s_loc = null //source location - var/t_loc = null //target location - var/obj/item/item = null - var/place = null - var/pickpocket = null - -/obj/effect/equip_e/human - name = "human" - var/mob/living/carbon/human/target = null - -/obj/effect/equip_e/human/Destroy() - if(target) - target.requests -= src - ..() - -/obj/effect/equip_e/monkey - name = "monkey" - var/mob/living/carbon/monkey/target = null - -/obj/effect/equip_e/monkey/Destroy() - if(target) - target.requests -= src - ..() - -/obj/effect/equip_e/process() - return - -/obj/effect/equip_e/proc/done() - return - -/obj/effect/equip_e/New() - if (!ticker) - qdel(src) - spawn(100) - qdel(src) - ..() - return - - -/obj/effect/equip_e/human/process() - if (item) - item.add_fingerprint(source) - else - switch(place) - if("mask") - if (!( target.wear_mask )) - qdel(src) - if("l_hand") - if (!( target.l_hand )) - qdel(src) - if("r_hand") - if (!( target.r_hand )) - qdel(src) - if("suit") - if (!( target.wear_suit )) - qdel(src) - if("uniform") - if (!( target.w_uniform )) - qdel(src) - if("back") - if (!( target.back )) - qdel(src) - if("syringe") - return - if("pill") - return - if("fuel") - return - if("drink") - return - if("dnainjector") - return - if("handcuff") - if (!( target.handcuffed )) - qdel(src) - if("id") - if ((!( target.wear_id ) || !( target.w_uniform ))) - qdel(src) - if("splints") - var/count = 0 - for(var/organ in list("l_leg","r_leg","l_arm","r_arm")) - var/datum/organ/external/o = target.organs_by_name[organ] - if(o.status & ORGAN_SPLINTED) - count = 1 - break - if(count == 0) - qdel(src) - return - - - - if("internal") - if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.back, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) - qdel(src) - - if("internal1") - if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.belt, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) - qdel(src) - - if("internal2") - if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.s_store, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) - qdel(src) - - - var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel") - if ((item && !( L.Find(place) ))) - if(isrobot(source) && place != "handcuff") - qdel(src) - for(var/mob/O in viewers(target, null)) - O.show_message("[source] is trying to put \a [item] on [target]", 1) - else - var/message=null - switch(place) - if("syringe") - message = "[source] is trying to inject [target]!" - if("pill") - message = "[source] is trying to force [target] to swallow [item]!" - if("drink") - message = "[source] is trying to force [target] to swallow a gulp of [item]!" - if("dnainjector") - message = "[source] is trying to inject [target] with the [item]!" - if("mask") - target.attack_log += text("\[[time_stamp()]\] Had their mask removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) mask") - if(target.wear_mask && !target.wear_mask.canremove) - message = "[source] fails to take off \a [target.wear_mask] from [target]'s head!" - return - else - message = "[source] is trying to take off \a [target.wear_mask] from [target]'s head!" - if("l_hand") - target.attack_log += text("\[[time_stamp()]\] Has had their left hand item ([target.l_hand]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) left hand item ([target.l_hand])") - message = "[source] is trying to take off \a [target.l_hand] from [target]'s left hand!" - if("r_hand") - target.attack_log += text("\[[time_stamp()]\] Has had their right hand item ([target.r_hand]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) right hand item ([target.r_hand])") - message = "[source] is trying to take off \a [target.r_hand] from [target]'s right hand!" - if("gloves") - target.attack_log += text("\[[time_stamp()]\] Has had their gloves ([target.gloves]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) gloves ([target.gloves])") - if(target.gloves && !target.gloves.canremove) - message = "[source] fails to take off \a [target.gloves] from [target]'s hands!" - return - else - message = "[source] is trying to take off the [target.gloves] from [target]'s hands!" - if("eyes") - target.attack_log += text("\[[time_stamp()]\] Has had their eyewear ([target.glasses]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) eyewear ([target.glasses])") - if(target.glasses && !target.glasses.canremove) - message = "[source] fails to take off \a [target.glasses] from [target]'s eyes!" - return - else - message = "[source] is trying to take off the [target.glasses] from [target]'s eyes!" - if("ears") - target.attack_log += text("\[[time_stamp()]\] Has had their ear item ([target.ears]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) ear item ([target.ears])") - if(target.ears && !target.ears.canremove) - message = "[source] fails to take off \a [target.ears] from [target]'s ears!" - return - else - message = "[source] is trying to take off the [target.ears] from [target]'s ears!" - if("head") - target.attack_log += text("\[[time_stamp()]\] Has had their hat ([target.head]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) hat ([target.head])") - if(target.head && !target.head.canremove) - message = "[source] fails to take off \a [target.head] from [target]'s head!" - return - else - message = "[source] is trying to take off the [target.head] from [target]'s head!" - if("shoes") - target.attack_log += text("\[[time_stamp()]\] Has had their shoes ([target.shoes]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) shoes ([target.shoes])") - if(target.shoes && !target.shoes.canremove) - message = "[source] fails to take off \a [target.shoes] from [target]'s feet!" - return - else - message = "[source] is trying to take off the [target.shoes] from [target]'s feet!" - if("belt") - target.attack_log += text("\[[time_stamp()]\] Has had their belt item ([target.belt]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) belt item ([target.belt])") - if(!pickpocket) - message = "[source] is trying to take off the [target.belt] from [target]'s belt!" - else + return + + update_hidden_item_icons(W) + + W.layer = 20 + W.equipped(src, slot) + W.loc = src + + +/obj/effect/equip_e + name = "equip e" + var/mob/source = null + var/s_loc = null //source location + var/t_loc = null //target location + var/obj/item/item = null + var/place = null + var/pickpocket = null + +/obj/effect/equip_e/human + name = "human" + var/mob/living/carbon/human/target = null + +/obj/effect/equip_e/human/Destroy() + if(target) + target.requests -= src + ..() + +/obj/effect/equip_e/monkey + name = "monkey" + var/mob/living/carbon/monkey/target = null + +/obj/effect/equip_e/monkey/Destroy() + if(target) + target.requests -= src + ..() + +/obj/effect/equip_e/process() + return + +/obj/effect/equip_e/proc/done() + return + +/obj/effect/equip_e/New() + if (!ticker) + qdel(src) + spawn(100) + qdel(src) + ..() + return + + +/obj/effect/equip_e/human/process() + if (item) + item.add_fingerprint(source) + else + switch(place) + if("mask") + if (!( target.wear_mask )) + qdel(src) + if("l_hand") + if (!( target.l_hand )) + qdel(src) + if("r_hand") + if (!( target.r_hand )) + qdel(src) + if("suit") + if (!( target.wear_suit )) + qdel(src) + if("uniform") + if (!( target.w_uniform )) + qdel(src) + if("back") + if (!( target.back )) + qdel(src) + if("syringe") + return + if("pill") + return + if("fuel") + return + if("drink") + return + if("dnainjector") + return + if("handcuff") + if (!( target.handcuffed )) + qdel(src) + if("id") + if ((!( target.wear_id ) || !( target.w_uniform ))) + qdel(src) + if("splints") + var/count = 0 + for(var/organ in list("l_leg","r_leg","l_arm","r_arm")) + var/datum/organ/external/o = target.organs_by_name[organ] + if(o.status & ORGAN_SPLINTED) + count = 1 + break + if(count == 0) + qdel(src) + return + + + + if("internal") + if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.back, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) + qdel(src) + + if("internal1") + if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.belt, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) + qdel(src) + + if("internal2") + if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.s_store, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) + qdel(src) + + + var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel") + if ((item && !( L.Find(place) ))) + if(isrobot(source) && place != "handcuff") + qdel(src) + for(var/mob/O in viewers(target, null)) + O.show_message("[source] is trying to put \a [item] on [target]", 1) + else + var/message=null + switch(place) + if("syringe") + message = "[source] is trying to inject [target]!" + if("pill") + message = "[source] is trying to force [target] to swallow [item]!" + if("drink") + message = "[source] is trying to force [target] to swallow a gulp of [item]!" + if("dnainjector") + message = "[source] is trying to inject [target] with the [item]!" + if("mask") + target.attack_log += text("\[[time_stamp()]\] Had their mask removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) mask") + if(target.wear_mask && !target.wear_mask.canremove) + message = "[source] fails to take off \a [target.wear_mask] from [target]'s head!" + return + else + message = "[source] is trying to take off \a [target.wear_mask] from [target]'s head!" + if("l_hand") + target.attack_log += text("\[[time_stamp()]\] Has had their left hand item ([target.l_hand]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) left hand item ([target.l_hand])") + message = "[source] is trying to take off \a [target.l_hand] from [target]'s left hand!" + if("r_hand") + target.attack_log += text("\[[time_stamp()]\] Has had their right hand item ([target.r_hand]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) right hand item ([target.r_hand])") + message = "[source] is trying to take off \a [target.r_hand] from [target]'s right hand!" + if("gloves") + target.attack_log += text("\[[time_stamp()]\] Has had their gloves ([target.gloves]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) gloves ([target.gloves])") + if(target.gloves && !target.gloves.canremove) + message = "[source] fails to take off \a [target.gloves] from [target]'s hands!" + return + else + message = "[source] is trying to take off the [target.gloves] from [target]'s hands!" + if("eyes") + target.attack_log += text("\[[time_stamp()]\] Has had their eyewear ([target.glasses]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) eyewear ([target.glasses])") + if(target.glasses && !target.glasses.canremove) + message = "[source] fails to take off \a [target.glasses] from [target]'s eyes!" + return + else + message = "[source] is trying to take off the [target.glasses] from [target]'s eyes!" + if("ears") + target.attack_log += text("\[[time_stamp()]\] Has had their ear item ([target.ears]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) ear item ([target.ears])") + if(target.ears && !target.ears.canremove) + message = "[source] fails to take off \a [target.ears] from [target]'s ears!" + return + else + message = "[source] is trying to take off the [target.ears] from [target]'s ears!" + if("head") + target.attack_log += text("\[[time_stamp()]\] Has had their hat ([target.head]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) hat ([target.head])") + if(target.head && !target.head.canremove) + message = "[source] fails to take off \a [target.head] from [target]'s head!" + return + else + message = "[source] is trying to take off the [target.head] from [target]'s head!" + if("shoes") + target.attack_log += text("\[[time_stamp()]\] Has had their shoes ([target.shoes]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) shoes ([target.shoes])") + if(target.shoes && !target.shoes.canremove) + message = "[source] fails to take off \a [target.shoes] from [target]'s feet!" + return + else + message = "[source] is trying to take off the [target.shoes] from [target]'s feet!" + if("belt") + target.attack_log += text("\[[time_stamp()]\] Has had their belt item ([target.belt]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) belt item ([target.belt])") + if(!pickpocket) + message = "[source] is trying to take off the [target.belt] from [target]'s belt!" + else to_chat(source, "You try to take off the [target.belt] from [target]'s belt!") - if("suit") - target.attack_log += text("\[[time_stamp()]\] Has had their suit ([target.wear_suit]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) suit ([target.wear_suit])") - if(target.wear_suit && !target.wear_suit.canremove) - message = "[source] fails to take off \a [target.wear_suit] from [target]'s body!" - return - else - message = "[source] is trying to take off \a [target.wear_suit] from [target]'s body!" - if("back") - target.attack_log += text("\[[time_stamp()]\] Has had their back item ([target.back]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) back item ([target.back])") - message = "[source] is trying to take off \a [target.back] from [target]'s back!" - if("handcuff") - target.attack_log += text("\[[time_stamp()]\] Was unhandcuffed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to unhandcuff [target.name]'s ([target.ckey])") - message = "[source] is trying to unhandcuff [target]!" - if("legcuff") - target.attack_log += text("\[[time_stamp()]\] Was unlegcuffed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to unlegcuff [target.name]'s ([target.ckey])") - message = "[source] is trying to unlegcuff [target]!" - if("uniform") - target.attack_log += text("\[[time_stamp()]\] Has had their uniform ([target.w_uniform]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) uniform ([target.w_uniform])") - for(var/obj/item/I in list(target.l_store, target.r_store)) - if(I.on_found(source)) - return - if(target.w_uniform && !target.w_uniform.canremove) - message = "[source] fails to take off \a [target.w_uniform] from [target]'s body!" - return - else - message = "[source] is trying to take off \a [target.w_uniform] from [target]'s body!" - 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])") - message = "[source] is trying to take off \a [target.s_store] from [target]'s suit!" - if("pockets") - target.attack_log += text("\[[time_stamp()]\] Has had their pockets emptied by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to empty [target.name]'s ([target.ckey]) pockets") - for(var/obj/item/I in list(target.l_store, target.r_store)) - if(I.on_found(source)) - return - message = "[source] is trying to empty [target]'s pockets." - if("CPR") - if (!target.cpr_time) - qdel(src) - target.cpr_time = 0 - message = "[source] is trying perform CPR on [target]!" - if("id") - target.attack_log += text("\[[time_stamp()]\] Has had their ID ([target.wear_id]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) ID ([target.wear_id])") - if(!pickpocket) - message = "[source] is trying to take off [target.wear_id] from [target]'s uniform!" - else + if("suit") + target.attack_log += text("\[[time_stamp()]\] Has had their suit ([target.wear_suit]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) suit ([target.wear_suit])") + if(target.wear_suit && !target.wear_suit.canremove) + message = "[source] fails to take off \a [target.wear_suit] from [target]'s body!" + return + else + message = "[source] is trying to take off \a [target.wear_suit] from [target]'s body!" + if("back") + target.attack_log += text("\[[time_stamp()]\] Has had their back item ([target.back]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) back item ([target.back])") + message = "[source] is trying to take off \a [target.back] from [target]'s back!" + if("handcuff") + target.attack_log += text("\[[time_stamp()]\] Was unhandcuffed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to unhandcuff [target.name]'s ([target.ckey])") + message = "[source] is trying to unhandcuff [target]!" + if("legcuff") + target.attack_log += text("\[[time_stamp()]\] Was unlegcuffed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to unlegcuff [target.name]'s ([target.ckey])") + message = "[source] is trying to unlegcuff [target]!" + if("uniform") + target.attack_log += text("\[[time_stamp()]\] Has had their uniform ([target.w_uniform]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) uniform ([target.w_uniform])") + for(var/obj/item/I in list(target.l_store, target.r_store)) + if(I.on_found(source)) + return + if(target.w_uniform && !target.w_uniform.canremove) + message = "[source] fails to take off \a [target.w_uniform] from [target]'s body!" + return + else + message = "[source] is trying to take off \a [target.w_uniform] from [target]'s body!" + 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])") + message = "[source] is trying to take off \a [target.s_store] from [target]'s suit!" + if("pockets") + target.attack_log += text("\[[time_stamp()]\] Has had their pockets emptied by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to empty [target.name]'s ([target.ckey]) pockets") + for(var/obj/item/I in list(target.l_store, target.r_store)) + if(I.on_found(source)) + return + message = "[source] is trying to empty [target]'s pockets." + if("CPR") + if (!target.cpr_time) + qdel(src) + target.cpr_time = 0 + message = "[source] is trying perform CPR on [target]!" + if("id") + target.attack_log += text("\[[time_stamp()]\] Has had their ID ([target.wear_id]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) ID ([target.wear_id])") + if(!pickpocket) + message = "[source] is trying to take off [target.wear_id] from [target]'s uniform!" + else to_chat(source, "You try to take off [target.wear_id] from [target]'s uniform!") - if("internal") - target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") - if (target.internal) - message = "[source] is trying to remove [target]'s internals" - else - message = "[source] is trying to set on [target]'s internals." - - if("internal1") - target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") - if (target.internal) - message = "[source] is trying to remove [target]'s internals" - else - message = "[source] is trying to set on [target]'s internals." - - if("internal2") - target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") - if (target.internal) - message = "[source] is trying to remove [target]'s internals" - else - message = "[source] is trying to set on [target]'s internals." - if("splints") - message = text("[] is trying to remove []'s splints!", source, target) - - for(var/mob/M in viewers(target, null)) - M.show_message(message, 1) - spawn(HUMAN_STRIP_DELAY) - done() - return - return - -/* -This proc equips stuff (or does something else) when removing stuff manually from the character window when you click and drag. -It works in conjuction with the process() above. -This proc works for humans only. Aliens stripping humans and the like will all use this proc. Stripping monkeys or somesuch will use their version of this proc. -The first if statement for "mask" and such refers to items that are already equipped and un-equipping them. -The else statement is for equipping stuff to empty slots. -!canremove refers to variable of /obj/item/clothing which either allows or disallows that item to be removed. -It can still be worn/put on as normal. -*/ -/obj/effect/equip_e/human/done() //TODO: And rewrite this :< ~Carn - target.cpr_time = 1 - if(isanimal(source)) return //animals cannot strip people - if(!source || !target) return //Target or source no longer exist - if(source.loc != s_loc) return //source has moved - if(target.loc != t_loc) return //target has moved - if(!source.Adjacent(target)) return //Use a proxi! - - if(item) - if(source.get_active_hand() != item) return //Swapped hands / removed item from the active one - if(item.cant_drop > 0) return //Item can't be dropped - - if ((source.restrained() || source.stat)) return //Source restrained or unconscious / dead - - var/slot_to_process - var/strip_item //this will tell us which item we will be stripping - if any. - - switch(place) //here we go again... - if("mask") - slot_to_process = slot_wear_mask - if (target.wear_mask && target.wear_mask.canremove) - strip_item = target.wear_mask - if("gloves") - slot_to_process = slot_gloves - if (target.gloves && target.gloves.canremove) - strip_item = target.gloves - if("eyes") - slot_to_process = slot_glasses - if (target.glasses) - strip_item = target.glasses - if("belt") - slot_to_process = slot_belt - if (target.belt) - strip_item = target.belt - if("s_store") - slot_to_process = slot_s_store - if (target.s_store) - strip_item = target.s_store - if("head") - slot_to_process = slot_head - if (target.head && target.head.canremove) - strip_item = target.head - if("ears") - slot_to_process = slot_ears - if (target.ears) - strip_item = target.ears - if("shoes") - slot_to_process = slot_shoes - if (target.shoes && target.shoes.canremove) - strip_item = target.shoes - if("l_hand") - if (istype(target, /obj/item/clothing/suit/straight_jacket)) - qdel(src) - slot_to_process = slot_l_hand - if (target.l_hand) - strip_item = target.l_hand - if("r_hand") - if (istype(target, /obj/item/clothing/suit/straight_jacket)) - qdel(src) - slot_to_process = slot_r_hand - if (target.r_hand) - strip_item = target.r_hand - if("uniform") - slot_to_process = slot_w_uniform - if(target.w_uniform && target.w_uniform.canremove) - strip_item = target.w_uniform - if("suit") - slot_to_process = slot_wear_suit - if (target.wear_suit && target.wear_suit.canremove) - strip_item = target.wear_suit - if("id") - slot_to_process = slot_wear_id - if (target.wear_id) - strip_item = target.wear_id - if("back") - slot_to_process = slot_back - if (target.back) - strip_item = target.back - if("handcuff") - slot_to_process = slot_handcuffed - if (target.handcuffed) - strip_item = target.handcuffed - if("legcuff") - slot_to_process = slot_legcuffed - if (target.legcuffed) - strip_item = target.legcuffed - if("splints") - for(var/organ in list("l_leg","r_leg","l_arm","r_arm")) - var/datum/organ/external/o = target.get_organ(organ) - if (o && o.status & ORGAN_SPLINTED) - var/obj/item/W = new /obj/item/stack/medical/splint(amount=1) - o.status &= ~ORGAN_SPLINTED - if (W) - W.loc = target.loc - W.layer = initial(W.layer) - W.add_fingerprint(source) - if("CPR") - if ((target.health > config.health_threshold_dead && target.health < config.health_threshold_crit)) - var/suff = min(target.getOxyLoss(), 7) - target.adjustOxyLoss(-suff) - target.updatehealth() - for(var/mob/O in viewers(source, null)) - O.show_message("[source] performs CPR on [target]!", 1) + if("internal") + target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") + if (target.internal) + message = "[source] is trying to remove [target]'s internals" + else + message = "[source] is trying to set on [target]'s internals." + + if("internal1") + target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") + if (target.internal) + message = "[source] is trying to remove [target]'s internals" + else + message = "[source] is trying to set on [target]'s internals." + + if("internal2") + target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") + if (target.internal) + message = "[source] is trying to remove [target]'s internals" + else + message = "[source] is trying to set on [target]'s internals." + if("splints") + message = text("[] is trying to remove []'s splints!", source, target) + + for(var/mob/M in viewers(target, null)) + M.show_message(message, 1) + spawn(HUMAN_STRIP_DELAY) + done() + return + return + +/* +This proc equips stuff (or does something else) when removing stuff manually from the character window when you click and drag. +It works in conjuction with the process() above. +This proc works for humans only. Aliens stripping humans and the like will all use this proc. Stripping monkeys or somesuch will use their version of this proc. +The first if statement for "mask" and such refers to items that are already equipped and un-equipping them. +The else statement is for equipping stuff to empty slots. +!canremove refers to variable of /obj/item/clothing which either allows or disallows that item to be removed. +It can still be worn/put on as normal. +*/ +/obj/effect/equip_e/human/done() //TODO: And rewrite this :< ~Carn + target.cpr_time = 1 + if(isanimal(source)) return //animals cannot strip people + if(!source || !target) return //Target or source no longer exist + if(source.loc != s_loc) return //source has moved + if(target.loc != t_loc) return //target has moved + if(!source.Adjacent(target)) return //Use a proxi! + + if(item) + if(source.get_active_hand() != item) return //Swapped hands / removed item from the active one + if(item.cant_drop > 0) return //Item can't be dropped + + if ((source.restrained() || source.stat)) return //Source restrained or unconscious / dead + + var/slot_to_process + var/strip_item //this will tell us which item we will be stripping - if any. + + switch(place) //here we go again... + if("mask") + slot_to_process = slot_wear_mask + if (target.wear_mask && target.wear_mask.canremove) + strip_item = target.wear_mask + if("gloves") + slot_to_process = slot_gloves + if (target.gloves && target.gloves.canremove) + strip_item = target.gloves + if("eyes") + slot_to_process = slot_glasses + if (target.glasses) + strip_item = target.glasses + if("belt") + slot_to_process = slot_belt + if (target.belt) + strip_item = target.belt + if("s_store") + slot_to_process = slot_s_store + if (target.s_store) + strip_item = target.s_store + if("head") + slot_to_process = slot_head + if (target.head && target.head.canremove) + strip_item = target.head + if("ears") + slot_to_process = slot_ears + if (target.ears) + strip_item = target.ears + if("shoes") + slot_to_process = slot_shoes + if (target.shoes && target.shoes.canremove) + strip_item = target.shoes + if("l_hand") + if (istype(target, /obj/item/clothing/suit/straight_jacket)) + qdel(src) + slot_to_process = slot_l_hand + if (target.l_hand) + strip_item = target.l_hand + if("r_hand") + if (istype(target, /obj/item/clothing/suit/straight_jacket)) + qdel(src) + slot_to_process = slot_r_hand + if (target.r_hand) + strip_item = target.r_hand + if("uniform") + slot_to_process = slot_w_uniform + if(target.w_uniform && target.w_uniform.canremove) + strip_item = target.w_uniform + if("suit") + slot_to_process = slot_wear_suit + if (target.wear_suit && target.wear_suit.canremove) + strip_item = target.wear_suit + if("id") + slot_to_process = slot_wear_id + if (target.wear_id) + strip_item = target.wear_id + if("back") + slot_to_process = slot_back + if (target.back) + strip_item = target.back + if("handcuff") + slot_to_process = slot_handcuffed + if (target.handcuffed) + strip_item = target.handcuffed + if("legcuff") + slot_to_process = slot_legcuffed + if (target.legcuffed) + strip_item = target.legcuffed + if("splints") + for(var/organ in list("l_leg","r_leg","l_arm","r_arm")) + var/datum/organ/external/o = target.get_organ(organ) + if (o && o.status & ORGAN_SPLINTED) + var/obj/item/W = new /obj/item/stack/medical/splint(amount=1) + o.status &= ~ORGAN_SPLINTED + if (W) + W.loc = target.loc + W.layer = initial(W.layer) + W.add_fingerprint(source) + if("CPR") + if ((target.health > config.health_threshold_dead && target.health < config.health_threshold_crit)) + var/suff = min(target.getOxyLoss(), 7) + target.adjustOxyLoss(-suff) + target.updatehealth() + for(var/mob/O in viewers(source, null)) + O.show_message("[source] performs CPR on [target]!", 1) to_chat(target, "You feel a breath of fresh air enter your lungs. It feels good.") to_chat(source, "Repeat at least every 7 seconds.") - if("dnainjector") - var/obj/item/weapon/dnainjector/S = item - if(S) - S.add_fingerprint(source) - if (!( istype(S, /obj/item/weapon/dnainjector) )) - S.inuse = 0 - qdel(src) - S.inject(target, source) - if (S.s_time >= world.time + 30) - S.inuse = 0 - qdel(src) - S.s_time = world.time - for(var/mob/O in viewers(source, null)) - O.show_message("[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("internal") - if (target.internal) - target.internal.add_fingerprint(source) - target.internal = null - if (target.internals) - target.internals.icon_state = "internal0" - else - if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) - return - else - if (istype(target.back, /obj/item/weapon/tank)) - target.internal = target.back - else if (istype(target.s_store, /obj/item/weapon/tank)) - target.internal = target.s_store - else if (istype(target.belt, /obj/item/weapon/tank)) - target.internal = target.belt - if (target.internal) - for(var/mob/M in viewers(target, 1)) - M.show_message("[target] is now running on internals.", 1) - target.internal.add_fingerprint(source) - if (target.internals) - target.internals.icon_state = "internal1" - - - - if("internal1") - if (target.internal) - target.internal.add_fingerprint(source) - target.internal = null - if (target.internals) - target.internals.icon_state = "internal0" - else - if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) - return - else - if (istype(target.belt, /obj/item/weapon/tank)) - target.internal = target.belt - - if (target.internal) - for(var/mob/M in viewers(target, 1)) - M.show_message("[target] is now running on internals.", 1) - target.internal.add_fingerprint(source) - if (target.internals) - target.internals.icon_state = "internal1" - - - if("internal2") - if (target.internal) - target.internal.add_fingerprint(source) - target.internal = null - if (target.internals) - target.internals.icon_state = "internal0" - else - if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) - return - else - if (istype(target.s_store, /obj/item/weapon/tank)) - target.internal = target.s_store - - if (target.internal) - for(var/mob/M in viewers(target, 1)) - M.show_message("[target] is now running on internals.", 1) - target.internal.add_fingerprint(source) - if (target.internals) - target.internals.icon_state = "internal1" - - if(slot_to_process) - if(strip_item) //Stripping an item from the mob - - var/obj/item/W = strip_item - if((W.cant_drop > 0) && ((target.r_hand == W) || (target.l_hand == W))) //If item we're trying to take off can't be dropped AND is in target's hand(s): - source << "\The [W] is stuck to \the [target]!" - return - - target.u_equip(W,1) - if (target.client) - target.client.screen -= W - if (W) - W.loc = target.loc - W.layer = initial(W.layer) - //W.dropped(target) - W.stripped(target,source) - W.add_fingerprint(source) - if(slot_to_process == slot_l_store) //pockets! Needs to process the other one too. Snowflake code, wooo! It's not like anyone will rewrite this anytime soon. If I'm wrong then... CONGRATULATIONS! ;) - if(target.r_store) - target.u_equip(target.r_store,0) //At this stage l_store is already processed by the code above, we only need to process r_store. - else - if(item && target.has_organ_for_slot(slot_to_process)) //Placing an item on the mob - if(item.mob_can_equip(target, slot_to_process, 0)) - source.u_equip(item,1) - //if(item) - //item.dropped(source) - target.equip_to_slot_if_possible(item, slot_to_process, 0, 1, 1) - source.update_icons() - target.update_icons() - - if(source && target) - if(source.machine == target) - target.show_inv(source) - qdel(src) - -/mob/living/carbon/human/get_multitool(var/active_only=0) - if(istype(get_active_hand(),/obj/item/device/multitool)) - return get_active_hand() - if(active_only && istype(get_inactive_hand(),/obj/item/device/multitool)) - return get_inactive_hand() - return null + if("dnainjector") + var/obj/item/weapon/dnainjector/S = item + if(S) + S.add_fingerprint(source) + if (!( istype(S, /obj/item/weapon/dnainjector) )) + S.inuse = 0 + qdel(src) + S.inject(target, source) + if (S.s_time >= world.time + 30) + S.inuse = 0 + qdel(src) + S.s_time = world.time + for(var/mob/O in viewers(source, null)) + O.show_message("[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("internal") + if (target.internal) + target.internal.add_fingerprint(source) + target.internal = null + if (target.internals) + target.internals.icon_state = "internal0" + else + if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) + return + else + if (istype(target.back, /obj/item/weapon/tank)) + target.internal = target.back + else if (istype(target.s_store, /obj/item/weapon/tank)) + target.internal = target.s_store + else if (istype(target.belt, /obj/item/weapon/tank)) + target.internal = target.belt + if (target.internal) + for(var/mob/M in viewers(target, 1)) + M.show_message("[target] is now running on internals.", 1) + target.internal.add_fingerprint(source) + if (target.internals) + target.internals.icon_state = "internal1" + + + + if("internal1") + if (target.internal) + target.internal.add_fingerprint(source) + target.internal = null + if (target.internals) + target.internals.icon_state = "internal0" + else + if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) + return + else + if (istype(target.belt, /obj/item/weapon/tank)) + target.internal = target.belt + + if (target.internal) + for(var/mob/M in viewers(target, 1)) + M.show_message("[target] is now running on internals.", 1) + target.internal.add_fingerprint(source) + if (target.internals) + target.internals.icon_state = "internal1" + + + if("internal2") + if (target.internal) + target.internal.add_fingerprint(source) + target.internal = null + if (target.internals) + target.internals.icon_state = "internal0" + else + if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) + return + else + if (istype(target.s_store, /obj/item/weapon/tank)) + target.internal = target.s_store + + if (target.internal) + for(var/mob/M in viewers(target, 1)) + M.show_message("[target] is now running on internals.", 1) + target.internal.add_fingerprint(source) + if (target.internals) + target.internals.icon_state = "internal1" + + if(slot_to_process) + if(strip_item) //Stripping an item from the mob + + var/obj/item/W = strip_item + if((W.cant_drop > 0) && ((target.r_hand == W) || (target.l_hand == W))) //If item we're trying to take off can't be dropped AND is in target's hand(s): + source << "\The [W] is stuck to \the [target]!" + return + + target.u_equip(W,1) + if (target.client) + target.client.screen -= W + if (W) + W.loc = target.loc + W.layer = initial(W.layer) + //W.dropped(target) + W.stripped(target,source) + W.add_fingerprint(source) + if(slot_to_process == slot_l_store) //pockets! Needs to process the other one too. Snowflake code, wooo! It's not like anyone will rewrite this anytime soon. If I'm wrong then... CONGRATULATIONS! ;) + if(target.r_store) + target.u_equip(target.r_store,0) //At this stage l_store is already processed by the code above, we only need to process r_store. + else + if(item && target.has_organ_for_slot(slot_to_process)) //Placing an item on the mob + if(item.mob_can_equip(target, slot_to_process, 0)) + source.u_equip(item,1) + //if(item) + //item.dropped(source) + target.equip_to_slot_if_possible(item, slot_to_process, 0, 1, 1) + source.update_icons() + target.update_icons() + + if(source && target) + if(source.machine == target) + target.show_inv(source) + qdel(src) + +/mob/living/carbon/human/get_multitool(var/active_only=0) + if(istype(get_active_hand(),/obj/item/device/multitool)) + return get_active_hand() + if(active_only && istype(get_inactive_hand(),/obj/item/device/multitool)) + return get_inactive_hand() + return null diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 072d9b8f7bb..e184f431e94 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1,482 +1,482 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -//#define DEBUG_LIFE -//#define PROFILE_LIFE - -#define OXYCONCEN_PLASMEN_IGNITION 0.01 //1% is all it takes. -var/global/list/unconscious_overlays = list("1" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage1"),\ - "2" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage2"),\ - "3" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage3"),\ - "4" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage4"),\ - "5" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage5"),\ - "6" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage6"),\ - "7" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage7"),\ - "8" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage8"),\ - "9" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage9"),\ - "10" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage10")) -var/global/list/oxyloss_overlays = list("1" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay1"),\ - "2" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay2"),\ - "3" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay3"),\ - "4" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay4"),\ - "5" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay5"),\ - "6" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay6"),\ - "7" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay7")) -var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay1"),\ - "2" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay2"),\ - "3" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay3"),\ - "4" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay4"),\ - "5" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay5"),\ - "6" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay6")) -var/global/list/organ_damage_overlays = list( - "l_hand_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_min", "layer" = 21),\ - "l_hand_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_mid", "layer" = 21),\ - "l_hand_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_max", "layer" = 21),\ - "l_hand_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_gone", "layer" = 21),\ - "r_hand_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_min", "layer" = 21),\ - "r_hand_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_mid", "layer" = 21),\ - "r_hand_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_max", "layer" = 21),\ - "r_hand_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_gone", "layer" = 21),\ - "l_arm_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_arm_min", "layer" = 21),\ - "l_arm_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_mid", "layer" = 21),\ - "l_arm_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_arm_max", "layer" = 21),\ - "l_arm_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_arm_gone", "layer" = 21),\ - "r_arm_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_min", "layer" = 21),\ - "r_arm_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_mid", "layer" = 21),\ - "r_arm_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_max", "layer" = 21),\ - "r_arm_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_gone", "layer" = 21),\ - "l_leg_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_min", "layer" = 21),\ - "l_leg_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_mid", "layer" = 21),\ - "l_leg_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_max", "layer" = 21),\ - "l_leg_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_gone", "layer" = 21),\ - "r_leg_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_min", "layer" = 21),\ - "r_leg_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_mid", "layer" = 21),\ - "r_leg_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_max", "layer" = 21),\ - "r_leg_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_gone", "layer" = 21),\ - "r_foot_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_min", "layer" = 21),\ - "r_foot_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_mid", "layer" = 21),\ - "r_foot_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_max", "layer" = 21),\ - "r_foot_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_gone", "layer" = 21),\ - "l_foot_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_min", "layer" = 21),\ - "l_foot_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_mid", "layer" = 21),\ - "l_foot_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_max", "layer" = 21),\ - "l_foot_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_gone", "layer" = 21),\ - "chest_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_min", "layer" = 21),\ - "chest_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_mid", "layer" = 21),\ - "chest_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_max", "layer" = 21),\ - "chest_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_gone", "layer" = 21),\ - "head_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_min", "layer" = 21),\ - "head_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_mid", "layer" = 21),\ - "head_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_max", "layer" = 21),\ - "head_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_gone", "layer" = 21),\ - "groin_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_min", "layer" = 21),\ - "groin_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_mid", "layer" = 21),\ - "groin_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_max", "layer" = 21),\ - "groin_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_gone", "layer" = 21)) -/mob/living/carbon/human - var/oxygen_alert = 0 - var/toxins_alert = 0 - var/fire_alert = 0 - var/pressure_alert = 0 - var/prev_gender = null // Debug for plural genders - var/temperature_alert = 0 - var/in_stasis = 0 - var/do_deferred_species_setup=0 - var/exposedtimenow = 0 - var/firstexposed = 0 - var/cycle = 0 - var/last_processed = "" - -#ifdef PROFILE_LIFE - var/list/profile_life_data=list() - var/profile_life_starttime=0 -#endif - -// Doing this during species init breaks shit. -/mob/living/carbon/human/proc/DeferredSpeciesSetup() - var/mut_update=0 - if(species.default_mutations.len>0) - for(var/mutation in species.default_mutations) - if(!(mutation in mutations)) - mutations.Add(mutation) - mut_update=1 - if(species.default_blocks.len>0) - for(var/block in species.default_blocks) - if(!dna.GetSEState(block)) - dna.SetSEState(block,1) - mut_update=1 - if(mut_update) - domutcheck(src,null,MUTCHK_FORCED) - update_mutations() - - -/mob/living/carbon/human/proc/debug_life(var/stage,var/chat_message) -#ifdef DEBUG_LIFE - #warning "DEBUG_LIFE enabled in [__FILE__]!" - if(client && client.prefs.toggles & CHAT_DEBUGLOGS) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +//#define DEBUG_LIFE +//#define PROFILE_LIFE + +#define OXYCONCEN_PLASMEN_IGNITION 0.01 //1% is all it takes. +var/global/list/unconscious_overlays = list("1" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage1"),\ + "2" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage2"),\ + "3" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage3"),\ + "4" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage4"),\ + "5" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage5"),\ + "6" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage6"),\ + "7" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage7"),\ + "8" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage8"),\ + "9" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage9"),\ + "10" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "passage10")) +var/global/list/oxyloss_overlays = list("1" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay1"),\ + "2" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay2"),\ + "3" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay3"),\ + "4" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay4"),\ + "5" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay5"),\ + "6" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay6"),\ + "7" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "oxydamageoverlay7")) +var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay1"),\ + "2" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay2"),\ + "3" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay3"),\ + "4" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay4"),\ + "5" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay5"),\ + "6" = image("icon" = 'icons/mob/screen1_full.dmi', "icon_state" = "brutedamageoverlay6")) +var/global/list/organ_damage_overlays = list( + "l_hand_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_min", "layer" = 21),\ + "l_hand_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_mid", "layer" = 21),\ + "l_hand_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_max", "layer" = 21),\ + "l_hand_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_gone", "layer" = 21),\ + "r_hand_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_min", "layer" = 21),\ + "r_hand_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_mid", "layer" = 21),\ + "r_hand_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_max", "layer" = 21),\ + "r_hand_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_hand_gone", "layer" = 21),\ + "l_arm_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_arm_min", "layer" = 21),\ + "l_arm_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_hand_mid", "layer" = 21),\ + "l_arm_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_arm_max", "layer" = 21),\ + "l_arm_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_arm_gone", "layer" = 21),\ + "r_arm_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_min", "layer" = 21),\ + "r_arm_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_mid", "layer" = 21),\ + "r_arm_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_max", "layer" = 21),\ + "r_arm_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_arm_gone", "layer" = 21),\ + "l_leg_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_min", "layer" = 21),\ + "l_leg_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_mid", "layer" = 21),\ + "l_leg_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_max", "layer" = 21),\ + "l_leg_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_leg_gone", "layer" = 21),\ + "r_leg_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_min", "layer" = 21),\ + "r_leg_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_mid", "layer" = 21),\ + "r_leg_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_max", "layer" = 21),\ + "r_leg_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_leg_gone", "layer" = 21),\ + "r_foot_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_min", "layer" = 21),\ + "r_foot_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_mid", "layer" = 21),\ + "r_foot_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_max", "layer" = 21),\ + "r_foot_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "r_foot_gone", "layer" = 21),\ + "l_foot_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_min", "layer" = 21),\ + "l_foot_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_mid", "layer" = 21),\ + "l_foot_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_max", "layer" = 21),\ + "l_foot_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "l_foot_gone", "layer" = 21),\ + "chest_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_min", "layer" = 21),\ + "chest_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_mid", "layer" = 21),\ + "chest_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_max", "layer" = 21),\ + "chest_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "chest_gone", "layer" = 21),\ + "head_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_min", "layer" = 21),\ + "head_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_mid", "layer" = 21),\ + "head_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_max", "layer" = 21),\ + "head_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "head_gone", "layer" = 21),\ + "groin_min" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_min", "layer" = 21),\ + "groin_mid" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_mid", "layer" = 21),\ + "groin_max" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_max", "layer" = 21),\ + "groin_gone" = image("icon" = 'icons/mob/organdmg.dmi', "icon_state" = "groin_gone", "layer" = 21)) +/mob/living/carbon/human + var/oxygen_alert = 0 + var/toxins_alert = 0 + var/fire_alert = 0 + var/pressure_alert = 0 + var/prev_gender = null // Debug for plural genders + var/temperature_alert = 0 + var/in_stasis = 0 + var/do_deferred_species_setup=0 + var/exposedtimenow = 0 + var/firstexposed = 0 + var/cycle = 0 + var/last_processed = "" + +#ifdef PROFILE_LIFE + var/list/profile_life_data=list() + var/profile_life_starttime=0 +#endif + +// Doing this during species init breaks shit. +/mob/living/carbon/human/proc/DeferredSpeciesSetup() + var/mut_update=0 + if(species.default_mutations.len>0) + for(var/mutation in species.default_mutations) + if(!(mutation in mutations)) + mutations.Add(mutation) + mut_update=1 + if(species.default_blocks.len>0) + for(var/block in species.default_blocks) + if(!dna.GetSEState(block)) + dna.SetSEState(block,1) + mut_update=1 + if(mut_update) + domutcheck(src,null,MUTCHK_FORCED) + update_mutations() + + +/mob/living/carbon/human/proc/debug_life(var/stage,var/chat_message) +#ifdef DEBUG_LIFE + #warning "DEBUG_LIFE enabled in [__FILE__]!" + if(client && client.prefs.toggles & CHAT_DEBUGLOGS) to_chat(src, chat_message) - last_processed = stage -#endif - -/mob/living/carbon/human/proc/profile_life_start() -#ifdef PROFILE_LIFE - profile_life_starttime=world.timeofday -#endif - return - -/mob/living/carbon/human/proc/profile_life_end(var/procname) -#ifdef PROFILE_LIFE - // [count, time spent] - if(!(procname in profile_life_data)) - profile_life_data[procname]=list(0,0) - var/datablock=profile_life_data[procname] - datablock[1]=datablock[1]+1 - datablock[2]=datablock[2]+(world.timeofday-profile_life_starttime) - profile_life_data[procname]=datablock -#endif - return - -#ifdef PROFILE_LIFE -/mob/living/carbon/human/verb/profile_life_report() - set category = "Debug" - set name = "Life() Profile Report" - - fdel("profile_life.csv") - var/f=file("profile_life.csv") + last_processed = stage +#endif + +/mob/living/carbon/human/proc/profile_life_start() +#ifdef PROFILE_LIFE + profile_life_starttime=world.timeofday +#endif + return + +/mob/living/carbon/human/proc/profile_life_end(var/procname) +#ifdef PROFILE_LIFE + // [count, time spent] + if(!(procname in profile_life_data)) + profile_life_data[procname]=list(0,0) + var/datablock=profile_life_data[procname] + datablock[1]=datablock[1]+1 + datablock[2]=datablock[2]+(world.timeofday-profile_life_starttime) + profile_life_data[procname]=datablock +#endif + return + +#ifdef PROFILE_LIFE +/mob/living/carbon/human/verb/profile_life_report() + set category = "Debug" + set name = "Life() Profile Report" + + fdel("profile_life.csv") + var/f=file("profile_life.csv") to_chat(f, "proc,calls,time,time/call") - for(var/procname in profile_life_data) - var/data=profile_life_data[procname] + for(var/procname in profile_life_data) + var/data=profile_life_data[procname] to_chat(f, "[procname],[data[1]],[data[2]],[data[2]/data[1]]") to_chat(usr, "Wrote to profile_life.csv.") -#endif - -/mob/living/carbon/human/Life() - - set invisibility = 0 - //set background = 1 - if(timestopped) return 0 //under effects of time magick - -#ifdef PROFILE_LIFE - debug_life("Started", "Starting Life() cycle [cycle]") -#endif - if(monkeyizing) - return - if(!loc) - return //Fixing a null error that occurs when the mob isn't found in the world -- TLE -#ifdef PROFILE_LIFE - debug_life("Called Super", "Successfully called parent.") -#endif - if(do_deferred_species_setup) - DeferredSpeciesSetup() - do_deferred_species_setup=0 -#ifdef PROFILE_LIFE - debug_life("Species Setup", "Successfully setup species if necessary.") -#endif - //Apparently, the person who wrote this code designed it so that blinded - //get reset each cycle and then get activated later in the code. - //Very ugly. I dont care. Moving this stuff here so its easy to find it. - blinded = null - fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it. - - //TODO: seperate this out - //Update the current life tick, can be used to e.g. only do something every 4 ticks - life_tick++ - - var/datum/gas_mixture/environment = loc.return_air() -#ifdef PROFILE_LIFE - debug_life("Setup Environment", "We have a location and returned air into [environment]") -#endif - in_stasis = istype(loc, /obj/structure/closet/body_bag/cryobag) && loc:opened == 0 //Nice runtime operator - - if(in_stasis) - loc:used++ //Ditto above - - //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 -#ifdef PROFILE_LIFE - profile_life_start() -#endif - breathe() //Only try to take a breath every 4 ticks, unless suffocating -#ifdef PROFILE_LIFE - profile_life_end("breathe") -#endif - last_processed = "Breathe" - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - last_processed = "Interacted with our container" -#ifdef PROFILE_LIFE - debug_life("Handle Breath", "We tried to breathe OR handled an internal object.") -#endif - if(check_mutations) - testing("Updating [src.real_name]'s mutations: "+english_list(mutations)) - domutcheck(src,null,MUTCHK_FORCED) -#ifdef PROFILE_LIFE - profile_life_start() -#endif - update_mutations() -#ifdef PROFILE_LIFE - profile_life_end("update_mutations") -#endif - check_mutations = 0 -#ifdef PROFILE_LIFE - debug_life("Check Mutations", "Successfully checked mutations.") -#endif - //Updates the number of stored chemicals for powers -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_changeling() -#ifdef PROFILE_LIFE - profile_life_end("handle_changeling") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle Ling", "Successfully handled changeling datum") -#endif - //Mutations and radiation -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_mutations_and_radiation() -#ifdef PROFILE_LIFE - profile_life_end("handle_body_temperature") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle Mut and Rads", "Successfully handled mutations and radiation") -#endif - //Chemicals in the body -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_chemicals_in_body() -#ifdef PROFILE_LIFE - profile_life_end("handle_chemicals_in_body") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle Chems", "Successfully handled internal chemicals") -#endif - //Disabilities -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_disabilities() -#ifdef PROFILE_LIFE - profile_life_end("handle_disabilities") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle disabilities", "Successfully handled disabilities") -#endif - //??? debug_life("Handle organs", "Successfully handled organs") - - //Random events (vomiting etc) -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_random_events() -#ifdef PROFILE_LIFE - profile_life_end("handle_random_events") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle random events", "Successfully handled random events") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_virus_updates() -#ifdef PROFILE_LIFE - profile_life_end("handle_virus_updates") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle Virus", "Successfully handled virus updates") -#endif - //Stuff in the stomach -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_stomach() -#ifdef PROFILE_LIFE - profile_life_end("handle_stomach") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle stomach", "Successfully handled stomach") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_shock() -#ifdef PROFILE_LIFE - profile_life_end("handle_shock") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle shock", "Successfully handled shock") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_pain() -#ifdef PROFILE_LIFE - debug_life("Handle pain", "Successfully handled pain") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_medical_side_effects() -#ifdef PROFILE_LIFE - profile_life_end("handle_medical_side_effects") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle side effects", "Successfully handled medical side effects") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_equipment() -#ifdef PROFILE_LIFE - profile_life_end("handle_equipment") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle equip", "Successfully handled equipment") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_stasis_bag() -#ifdef PROFILE_LIFE - profile_life_end("handle_stasis_bag") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle stasis", "Successfully handled stasis") -#endif - if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > 6000)) //We are long dead, or we're junk mobs spawned like the clowns on the clown shuttle -#ifdef PROFILE_LIFE - debug_life("DEAD", "We have been dead for too long, we stop here.") -#endif - cycle = "DEAD" - return //We go ahead and process them 5 times for HUD images and other stuff though. -#ifdef PROFILE_LIFE - //Handle temperature/pressure differences between body and environment - profile_life_start() -#endif - handle_environment(environment) -#ifdef PROFILE_LIFE - profile_life_end("handle_environment") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle enviroment", "Successfully handled enviroment") -#endif -#ifdef PROFILE_LIFE - //Check if we're on fire - profile_life_start() -#endif - handle_fire() -#ifdef PROFILE_LIFE - profile_life_end("handle_fire") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle fire", "Successfully handled fire") -#endif -#ifdef PROFILE_LIFE - //Status updates, death etc. - profile_life_start() -#endif - handle_regular_status_updates() //Optimized a bit -#ifdef PROFILE_LIFE - profile_life_end("handle_regular_status_updates") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle Regular Status Updates", "Successfully handled regular status updates") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - update_canmove() -#ifdef PROFILE_LIFE - profile_life_end("handle_canmove") -#endif -#ifdef PROFILE_LIFE - debug_life("update canmove", "Successfully updated canmove") -#endif - - //Update our name based on whether our face is obscured/disfigured - name = get_visible_name() -#ifdef PROFILE_LIFE - debug_life("get visible name", "Successfully got our visible name") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_regular_hud_updates() -#ifdef PROFILE_LIFE - profile_life_end("handle_regular_hud_updates") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle HUD", "Successfully handled hud update") -#endif - - - -#ifdef PROFILE_LIFE - profile_life_start() -#endif - pulse = handle_pulse() -#ifdef PROFILE_LIFE - profile_life_end("handle_pulse") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle pulse", "Successfully handled pulse") -#endif - - - - -#ifdef PROFILE_LIFE - //Grabbing - profile_life_start() -#endif - for(var/obj/item/weapon/grab/G in src) - G.process() -#ifdef PROFILE_LIFE - profile_life_end("\[grabs\]") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle grabs", "Successfully handled grabs") -#endif - if(mind && mind.vampire) -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_vampire() -#ifdef PROFILE_LIFE - profile_life_end("handle_vampire") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle vampire", "Successfully handled vampire") -#endif -#ifdef PROFILE_LIFE - profile_life_start() -#endif - handle_alpha() -#ifdef PROFILE_LIFE - profile_life_end("handle_alpha") -#endif -#ifdef PROFILE_LIFE - debug_life("Handle alpha", "Successfully handled alpha") -#endif - if(update_overlays) - update_overlays = 0 -#ifdef PROFILE_LIFE - profile_life_start() -#endif - UpdateDamageIcon() -#ifdef PROFILE_LIFE - profile_life_end("UpdateDamageIcon") -#endif - cycle++ - ..() - -//Need this in species. -//#undef HUMAN_MAX_OXYLOSS -//#undef HUMAN_CRIT_MAX_OXYLOSS +#endif + +/mob/living/carbon/human/Life() + + set invisibility = 0 + //set background = 1 + if(timestopped) return 0 //under effects of time magick + +#ifdef PROFILE_LIFE + debug_life("Started", "Starting Life() cycle [cycle]") +#endif + if(monkeyizing) + return + if(!loc) + return //Fixing a null error that occurs when the mob isn't found in the world -- TLE +#ifdef PROFILE_LIFE + debug_life("Called Super", "Successfully called parent.") +#endif + if(do_deferred_species_setup) + DeferredSpeciesSetup() + do_deferred_species_setup=0 +#ifdef PROFILE_LIFE + debug_life("Species Setup", "Successfully setup species if necessary.") +#endif + //Apparently, the person who wrote this code designed it so that blinded + //get reset each cycle and then get activated later in the code. + //Very ugly. I dont care. Moving this stuff here so its easy to find it. + blinded = null + fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it. + + //TODO: seperate this out + //Update the current life tick, can be used to e.g. only do something every 4 ticks + life_tick++ + + var/datum/gas_mixture/environment = loc.return_air() +#ifdef PROFILE_LIFE + debug_life("Setup Environment", "We have a location and returned air into [environment]") +#endif + in_stasis = istype(loc, /obj/structure/closet/body_bag/cryobag) && loc:opened == 0 //Nice runtime operator + + if(in_stasis) + loc:used++ //Ditto above + + //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 +#ifdef PROFILE_LIFE + profile_life_start() +#endif + breathe() //Only try to take a breath every 4 ticks, unless suffocating +#ifdef PROFILE_LIFE + profile_life_end("breathe") +#endif + last_processed = "Breathe" + + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + last_processed = "Interacted with our container" +#ifdef PROFILE_LIFE + debug_life("Handle Breath", "We tried to breathe OR handled an internal object.") +#endif + if(check_mutations) + testing("Updating [src.real_name]'s mutations: "+english_list(mutations)) + domutcheck(src,null,MUTCHK_FORCED) +#ifdef PROFILE_LIFE + profile_life_start() +#endif + update_mutations() +#ifdef PROFILE_LIFE + profile_life_end("update_mutations") +#endif + check_mutations = 0 +#ifdef PROFILE_LIFE + debug_life("Check Mutations", "Successfully checked mutations.") +#endif + //Updates the number of stored chemicals for powers +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_changeling() +#ifdef PROFILE_LIFE + profile_life_end("handle_changeling") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle Ling", "Successfully handled changeling datum") +#endif + //Mutations and radiation +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_mutations_and_radiation() +#ifdef PROFILE_LIFE + profile_life_end("handle_body_temperature") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle Mut and Rads", "Successfully handled mutations and radiation") +#endif + //Chemicals in the body +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_chemicals_in_body() +#ifdef PROFILE_LIFE + profile_life_end("handle_chemicals_in_body") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle Chems", "Successfully handled internal chemicals") +#endif + //Disabilities +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_disabilities() +#ifdef PROFILE_LIFE + profile_life_end("handle_disabilities") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle disabilities", "Successfully handled disabilities") +#endif + //??? debug_life("Handle organs", "Successfully handled organs") + + //Random events (vomiting etc) +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_random_events() +#ifdef PROFILE_LIFE + profile_life_end("handle_random_events") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle random events", "Successfully handled random events") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_virus_updates() +#ifdef PROFILE_LIFE + profile_life_end("handle_virus_updates") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle Virus", "Successfully handled virus updates") +#endif + //Stuff in the stomach +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_stomach() +#ifdef PROFILE_LIFE + profile_life_end("handle_stomach") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle stomach", "Successfully handled stomach") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_shock() +#ifdef PROFILE_LIFE + profile_life_end("handle_shock") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle shock", "Successfully handled shock") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_pain() +#ifdef PROFILE_LIFE + debug_life("Handle pain", "Successfully handled pain") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_medical_side_effects() +#ifdef PROFILE_LIFE + profile_life_end("handle_medical_side_effects") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle side effects", "Successfully handled medical side effects") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_equipment() +#ifdef PROFILE_LIFE + profile_life_end("handle_equipment") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle equip", "Successfully handled equipment") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_stasis_bag() +#ifdef PROFILE_LIFE + profile_life_end("handle_stasis_bag") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle stasis", "Successfully handled stasis") +#endif + if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > 6000)) //We are long dead, or we're junk mobs spawned like the clowns on the clown shuttle +#ifdef PROFILE_LIFE + debug_life("DEAD", "We have been dead for too long, we stop here.") +#endif + cycle = "DEAD" + return //We go ahead and process them 5 times for HUD images and other stuff though. +#ifdef PROFILE_LIFE + //Handle temperature/pressure differences between body and environment + profile_life_start() +#endif + handle_environment(environment) +#ifdef PROFILE_LIFE + profile_life_end("handle_environment") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle enviroment", "Successfully handled enviroment") +#endif +#ifdef PROFILE_LIFE + //Check if we're on fire + profile_life_start() +#endif + handle_fire() +#ifdef PROFILE_LIFE + profile_life_end("handle_fire") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle fire", "Successfully handled fire") +#endif +#ifdef PROFILE_LIFE + //Status updates, death etc. + profile_life_start() +#endif + handle_regular_status_updates() //Optimized a bit +#ifdef PROFILE_LIFE + profile_life_end("handle_regular_status_updates") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle Regular Status Updates", "Successfully handled regular status updates") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + update_canmove() +#ifdef PROFILE_LIFE + profile_life_end("handle_canmove") +#endif +#ifdef PROFILE_LIFE + debug_life("update canmove", "Successfully updated canmove") +#endif + + //Update our name based on whether our face is obscured/disfigured + name = get_visible_name() +#ifdef PROFILE_LIFE + debug_life("get visible name", "Successfully got our visible name") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_regular_hud_updates() +#ifdef PROFILE_LIFE + profile_life_end("handle_regular_hud_updates") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle HUD", "Successfully handled hud update") +#endif + + + +#ifdef PROFILE_LIFE + profile_life_start() +#endif + pulse = handle_pulse() +#ifdef PROFILE_LIFE + profile_life_end("handle_pulse") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle pulse", "Successfully handled pulse") +#endif + + + + +#ifdef PROFILE_LIFE + //Grabbing + profile_life_start() +#endif + for(var/obj/item/weapon/grab/G in src) + G.process() +#ifdef PROFILE_LIFE + profile_life_end("\[grabs\]") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle grabs", "Successfully handled grabs") +#endif + if(mind && mind.vampire) +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_vampire() +#ifdef PROFILE_LIFE + profile_life_end("handle_vampire") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle vampire", "Successfully handled vampire") +#endif +#ifdef PROFILE_LIFE + profile_life_start() +#endif + handle_alpha() +#ifdef PROFILE_LIFE + profile_life_end("handle_alpha") +#endif +#ifdef PROFILE_LIFE + debug_life("Handle alpha", "Successfully handled alpha") +#endif + if(update_overlays) + update_overlays = 0 +#ifdef PROFILE_LIFE + profile_life_start() +#endif + UpdateDamageIcon() +#ifdef PROFILE_LIFE + profile_life_end("UpdateDamageIcon") +#endif + cycle++ + ..() + +//Need this in species. +//#undef HUMAN_MAX_OXYLOSS +//#undef HUMAN_CRIT_MAX_OXYLOSS diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index 80d6f00288b..5a09ae63b1d 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -1,5 +1,5 @@ -/mob/living/carbon/human/Login() - ..() - update_hud() - ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them. - return +/mob/living/carbon/human/Login() + ..() + update_hud() + ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them. + return diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 1254eec42cd..dc7eab1fe83 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -1,185 +1,185 @@ -///mob/living/carbon/human/say(var/message) -// ..(message) - -/mob/living/carbon/human/say_quote(text) - if(!text) - return "says, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code - if (src.stuttering) - return "stammers, [text]"; - if(isliving(src)) - var/mob/living/L = src - if (L.getBrainLoss() >= 60) - return "gibbers, [text]"; - var/ending = copytext(text, length(text)) - if (ending == "?") - return "asks, [text]"; - if (ending == "!") - return "exclaims, [text]"; - -// if(dna) -// return "[dna.species.say_mod], \"[text]\""; - - return "says, [text]"; - -/mob/living/carbon/human/treat_speech(var/datum/speech/speech, var/genesay=0) - if(wear_mask && istype(wear_mask)) - if(!(copytext(speech.message, 1, 2) == "*" || (mind && mind.changeling && department_radio_keys[copytext(speech.message, 1, 3)] != "changeling"))) - wear_mask.treat_mask_speech(speech) - - if ((M_HULK in mutations) && health >= 25 && length(speech.message)) - speech.message = "[uppertext(replacetext(speech.message, ".", "!"))]!!" //because I don't know how to code properly in getting vars from other files -Bro - if (src.slurring) - speech.message = slur(speech.message) - - // Should be handled via a virus-specific proc. - if(viruses) - for(var/datum/disease/pierrot_throat/D in viruses) - var/list/temp_message = text2list(speech.message, " ") //List each word in the message - var/list/pick_list = list() - for(var/i = 1, i <= temp_message.len, i++) //Create a second list for excluding words down the line - pick_list += i - for(var/i=1, ((i <= D.stage) && (i <= temp_message.len)), i++) //Loop for each stage of the disease or until we run out of words - if(prob(3 * D.stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12% - var/H = pick(pick_list) - if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue - temp_message[H] = "HONK" - pick_list -= H //Make sure that you dont HONK the same word twice - speech.message = list2text(temp_message, " ") - - ..(speech) - if(dna) - species.handle_speech(speech,src) - - -/mob/living/carbon/human/GetVoice() - if(istype(wear_mask, /obj/item/clothing/mask/gas/voice)) - var/obj/item/clothing/mask/gas/voice/V = wear_mask - if(V.vchange && wear_id && V.is_flipped == 1) //the mask works, we have an id, and we are wearing it on the face instead of on the head - var/obj/item/weapon/card/id/idcard = wear_id.GetID() - if(istype(idcard)) - return idcard.registered_name - else - return "Unknown" - else - return real_name - if(mind && mind.changeling && mind.changeling.mimicing) - return mind.changeling.mimicing - if(GetSpecialVoice()) - return GetSpecialVoice() - return real_name - -/mob/living/carbon/human/IsVocal() - if(mind) - return !miming - return 1 - -/mob/living/carbon/human/proc/SetSpecialVoice(var/new_voice) - if(new_voice) - special_voice = new_voice - return - -/mob/living/carbon/human/proc/UnsetSpecialVoice() - special_voice = "" - return - -/mob/living/carbon/human/proc/GetSpecialVoice() - return special_voice - -/mob/living/carbon/human/binarycheck() - if(ears) - var/obj/item/device/radio/headset/dongle = ears - if(!istype(dongle)) return 0 - if(dongle.translate_binary) return 1 - -/mob/living/carbon/human/radio(var/datum/speech/speech, var/message_mode) - . = ..() - if(. != 0) - return . - - switch(message_mode) - if(MODE_HEADSET) - if (ears) - say_testing(src, "Talking into our headset (MODE_HEADSET)") - ears.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - - if(MODE_SECURE_HEADSET) - if (ears) - say_testing(src, "Talking into our headset (MODE_SECURE_HEADSET)") - ears.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - - if(MODE_DEPARTMENT) - if (ears) - say_testing(src, "Talking into our dept headset") - ears.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - - if(message_mode in radiochannels) - if(ears) - say_testing(src, "Talking through a radio channel") - ears.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - - return 0 - -/mob/living/carbon/human/get_alt_name() - if(name != GetVoice()) - return get_id_name("Unknown") - return null - -/mob/living/carbon/human/proc/forcesay(list/append) - if(stat == CONSCIOUS) - if(client) - var/virgin = 1 //has the text been modified yet? - var/temp = winget(client, "input", "text") - if(findtextEx(temp, "Say \"", 1, 7) && length(temp) > 5) //case sensitive means - - temp = replacetext(temp, ";", "") //general radio - - if(findtext(trim_left(temp), ":", 6, 7)) //dept radio - temp = copytext(trim_left(temp), 8) - virgin = 0 - - if(virgin) - temp = copytext(trim_left(temp), 6) //normal speech - virgin = 0 - - while(findtext(trim_left(temp), ":", 1, 2)) //dept radio again (necessary) - temp = copytext(trim_left(temp), 3) - - if(findtext(temp, "*", 1, 2)) //emotes - return - - var/trimmed = trim_left(temp) - if(length(trimmed)) - if(append) - temp += pick(append) - - say(temp) - winset(client, "input", "text=[null]") - -/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null) - if(other) other = other.GetSource() - if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak. - return 1 - - //These only pertain to common. Languages are handled by mob/say_understands() - if (!speaking) - if (istype(other, /mob/living/carbon/monkey/diona)) - var/mob/living/carbon/monkey/diona/D = other - if(D.donors.len >= 4) //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 - - //This is already covered by mob/say_understands() - //if (istype(other, /mob/living/simple_animal)) - // if((other.universal_speak && !speaking) || src.universal_speak || src.universal_understand) - // return 1 - // return 0 - return ..() +///mob/living/carbon/human/say(var/message) +// ..(message) + +/mob/living/carbon/human/say_quote(text) + if(!text) + return "says, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code + if (src.stuttering) + return "stammers, [text]"; + if(isliving(src)) + var/mob/living/L = src + if (L.getBrainLoss() >= 60) + return "gibbers, [text]"; + var/ending = copytext(text, length(text)) + if (ending == "?") + return "asks, [text]"; + if (ending == "!") + return "exclaims, [text]"; + +// if(dna) +// return "[dna.species.say_mod], \"[text]\""; + + return "says, [text]"; + +/mob/living/carbon/human/treat_speech(var/datum/speech/speech, var/genesay=0) + if(wear_mask && istype(wear_mask)) + if(!(copytext(speech.message, 1, 2) == "*" || (mind && mind.changeling && department_radio_keys[copytext(speech.message, 1, 3)] != "changeling"))) + wear_mask.treat_mask_speech(speech) + + if ((M_HULK in mutations) && health >= 25 && length(speech.message)) + speech.message = "[uppertext(replacetext(speech.message, ".", "!"))]!!" //because I don't know how to code properly in getting vars from other files -Bro + if (src.slurring) + speech.message = slur(speech.message) + + // Should be handled via a virus-specific proc. + if(viruses) + for(var/datum/disease/pierrot_throat/D in viruses) + var/list/temp_message = text2list(speech.message, " ") //List each word in the message + var/list/pick_list = list() + for(var/i = 1, i <= temp_message.len, i++) //Create a second list for excluding words down the line + pick_list += i + for(var/i=1, ((i <= D.stage) && (i <= temp_message.len)), i++) //Loop for each stage of the disease or until we run out of words + if(prob(3 * D.stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12% + var/H = pick(pick_list) + if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue + temp_message[H] = "HONK" + pick_list -= H //Make sure that you dont HONK the same word twice + speech.message = list2text(temp_message, " ") + + ..(speech) + if(dna) + species.handle_speech(speech,src) + + +/mob/living/carbon/human/GetVoice() + if(istype(wear_mask, /obj/item/clothing/mask/gas/voice)) + var/obj/item/clothing/mask/gas/voice/V = wear_mask + if(V.vchange && wear_id && V.is_flipped == 1) //the mask works, we have an id, and we are wearing it on the face instead of on the head + var/obj/item/weapon/card/id/idcard = wear_id.GetID() + if(istype(idcard)) + return idcard.registered_name + else + return "Unknown" + else + return real_name + if(mind && mind.changeling && mind.changeling.mimicing) + return mind.changeling.mimicing + if(GetSpecialVoice()) + return GetSpecialVoice() + return real_name + +/mob/living/carbon/human/IsVocal() + if(mind) + return !miming + return 1 + +/mob/living/carbon/human/proc/SetSpecialVoice(var/new_voice) + if(new_voice) + special_voice = new_voice + return + +/mob/living/carbon/human/proc/UnsetSpecialVoice() + special_voice = "" + return + +/mob/living/carbon/human/proc/GetSpecialVoice() + return special_voice + +/mob/living/carbon/human/binarycheck() + if(ears) + var/obj/item/device/radio/headset/dongle = ears + if(!istype(dongle)) return 0 + if(dongle.translate_binary) return 1 + +/mob/living/carbon/human/radio(var/datum/speech/speech, var/message_mode) + . = ..() + if(. != 0) + return . + + switch(message_mode) + if(MODE_HEADSET) + if (ears) + say_testing(src, "Talking into our headset (MODE_HEADSET)") + ears.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + + if(MODE_SECURE_HEADSET) + if (ears) + say_testing(src, "Talking into our headset (MODE_SECURE_HEADSET)") + ears.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + + if(MODE_DEPARTMENT) + if (ears) + say_testing(src, "Talking into our dept headset") + ears.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + + if(message_mode in radiochannels) + if(ears) + say_testing(src, "Talking through a radio channel") + ears.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + + return 0 + +/mob/living/carbon/human/get_alt_name() + if(name != GetVoice()) + return get_id_name("Unknown") + return null + +/mob/living/carbon/human/proc/forcesay(list/append) + if(stat == CONSCIOUS) + if(client) + var/virgin = 1 //has the text been modified yet? + var/temp = winget(client, "input", "text") + if(findtextEx(temp, "Say \"", 1, 7) && length(temp) > 5) //case sensitive means + + temp = replacetext(temp, ";", "") //general radio + + if(findtext(trim_left(temp), ":", 6, 7)) //dept radio + temp = copytext(trim_left(temp), 8) + virgin = 0 + + if(virgin) + temp = copytext(trim_left(temp), 6) //normal speech + virgin = 0 + + while(findtext(trim_left(temp), ":", 1, 2)) //dept radio again (necessary) + temp = copytext(trim_left(temp), 3) + + if(findtext(temp, "*", 1, 2)) //emotes + return + + var/trimmed = trim_left(temp) + if(length(trimmed)) + if(append) + temp += pick(append) + + say(temp) + winset(client, "input", "text=[null]") + +/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null) + if(other) other = other.GetSource() + if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak. + return 1 + + //These only pertain to common. Languages are handled by mob/say_understands() + if (!speaking) + if (istype(other, /mob/living/carbon/monkey/diona)) + var/mob/living/carbon/monkey/diona/D = other + if(D.donors.len >= 4) //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 + + //This is already covered by mob/say_understands() + //if (istype(other, /mob/living/simple_animal)) + // if((other.universal_speak && !speaking) || src.universal_speak || src.universal_understand) + // return 1 + // return 0 + return ..() diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 4b5a3dc2bcb..ee1a0c6b4a7 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,1109 +1,1109 @@ - /////////////////////// - //UPDATE_ICONS SYSTEM// - /////////////////////// -/* -Calling this a system is perhaps a bit trumped up. It is essentially update_clothing dismantled into its -core parts. The key difference is that when we generate overlays we do not generate either lying or standing -versions. Instead, we generate both and store them in two fixed-length lists, both using the same list-index -(The indexes are in update_icons.dm): Each list for humans is (at the time of writing) of length 19. -This will hopefully be reduced as the system is refined. - var/overlays_lying[19] //For the lying down stance - var/overlays_standing[19] //For the standing stance -When we call update_icons, the 'lying' variable is checked and then the appropriate list is assigned to our overlays! -That in itself uses a tiny bit more memory (no more than all the ridiculous lists the game has already mind you). -On the other-hand, it should be very CPU cheap in comparison to the old system. -In the old system, we updated all our overlays every life() call, even if we were standing still inside a crate! -or dead!. 25ish overlays, all generated from scratch every second for every xeno/human/monkey and then applied. -More often than not update_clothing was being called a few times in addition to that! CPU was not the only issue, -all those icons had to be sent to every client. So really the cost was extremely cumulative. To the point where -update_clothing would frequently appear in the top 10 most CPU intensive procs during profiling. -Another feature of this new system is that our lists are indexed. This means we can update specific overlays! -So we only regenerate icons when we need them to be updated! This is the main saving for this system. -In practice this means that: - everytime you fall over, we just switch between precompiled lists. Which is fast and cheap. - Everytime you do something minor like take a pen out of your pocket, we only update the in-hand overlay - etc... -There are several things that need to be remembered: -> Whenever we do something that should cause an overlay to update (which doesn't use standard procs - ( i.e. you do something like l_hand = /obj/item/something new(src) ) - You will need to call the relevant update_inv_* proc: - update_inv_head() - update_inv_wear_suit() - update_inv_gloves() - update_inv_shoes() - update_inv_w_uniform() - update_inv_glasse() - update_inv_l_hand() - update_inv_r_hand() - update_inv_belt() - update_inv_wear_id() - update_inv_ears() - update_inv_s_store() - update_inv_pockets() - update_inv_back() - update_inv_handcuffed() - update_inv_wear_mask() - All of these are named after the variable they update from. They are defined at the mob/ level like - update_clothing was, so you won't cause undefined proc runtimes with usr.update_inv_wear_id() if the usr is a - slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such. -> There are also these special cases: - update_mutations() //handles updating your appearance for certain mutations. e.g TK head-glows - update_mutantrace() //handles updating your appearance after setting the mutantrace var - QueueUpdateDamageIcon() //handles damage overlays for brute/burn damage //(will rename this when I geta round to it) - update_body() //Handles updating your mob's icon to reflect their gender/race/complexion etc - update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and - ...eyes were merged into update_body) - update_targeted() // Updates the target overlay when someone points a gun at you -> All of these procs update our overlays_lying and overlays_standing, and then call update_icons() by default. - If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call - it manually: - e.g. - update_inv_head(0) - update_inv_l_hand(0) - update_inv_r_hand() //<---calls update_icons() - or equivillantly: - update_inv_head(0) - update_inv_l_hand(0) - update_inv_r_hand(0) - update_icons() -> If you need to update all overlays you can use regenerate_icons(). it works exactly like update_clothing used to. -> I reimplimented an old unused variable which was in the code called (coincidentally) var/update_icon - It can be used as another method of triggering regenerate_icons(). It's basically a flag that when set to non-zero - will call regenerate_icons() at the next life() call and then reset itself to 0. - The idea behind it is icons are regenerated only once, even if multiple events requested it. -This system is confusing and is still a WIP. It's primary goal is speeding up the controls of the game whilst -reducing processing costs. So please bear with me while I iron out the kinks. It will be worth it, I promise. -If I can eventually free var/lying stuff from the life() process altogether, stuns/death/status stuff -will become less affected by lag-spikes and will be instantaneous! :3 -If you have any questions/constructive-comments/bugs-to-report/or have a massivly devestated butt... -Please contact me on #coderbus IRC. ~Carn x -*/ - -/mob/living/carbon/human - var/list/overlays_standing[TOTAL_LAYERS] - var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed - var/icon/race_icon - var/icon/deform_icon - var/update_overlays = 0 - - -/mob/living/carbon/human/proc/QueueUpdateDamageIcon(var/forced = 0) - if(forced) - UpdateDamageIcon(1) - update_overlays = 0 - return - update_overlays = 1 - -//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING -//this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers -//I'll work on removing that stuff by rewriting some of the cloaking stuff at a later date. -/mob/living/carbon/human/update_icons() - update_hud() //TODO: remove the need for this - update_overlays_standing() - update_transform() - -/mob/living/carbon/human/proc/update_overlays_standing() - if(species && species.override_icon) - species_override_icon() - else - generate_overlays_icon() - -/mob/living/carbon/human/proc/species_override_icon() - //overlays.len = 0 - icon = species.override_icon - icon_state = "[lowertext(species.name)]_[gender][ (species.flags & CAN_BE_FAT ? (mutations & M_FAT) ? "_fat" : "" : "") ]" - //temporary fix for having mutations on top of overriden icons for like muton, horror, etc - overlays -= obj_overlays[MUTANTRACE_LAYER] - - -/mob/living/carbon/human/proc/generate_overlays_icon() - icon = stand_icon - -var/global/list/damage_icon_parts = list() - -/mob/living/carbon/human/proc/get_damage_icon_part(damage_state, body_part,species_blood = "") - var/icon/I = damage_icon_parts["[damage_state]/[body_part]/[species_blood]"] - if(!I) - var/icon/DI = icon('icons/mob/dam_human.dmi', damage_state) // the damage icon for whole human - DI.Blend(icon('icons/mob/dam_mask.dmi', body_part), ICON_MULTIPLY) // mask with this organ's pixels - if(species_blood) - DI.Blend(species_blood, ICON_MULTIPLY) // mask with this species's blood color - damage_icon_parts["[damage_state]/[body_part]/[species_blood]"] = DI - return DI - else - return I - -//DAMAGE OVERLAYS -//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists -/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1) - // first check whether something actually changed about damage appearance - /*for(var/datum/organ/external/O in organs) - if(O.status & ORGAN_DESTROYED) damage_appearance += "d" - else - damage_appearance += O.damage_state - if(damage_appearance == previous_damage_appearance) - // nothing to do here - return - previous_damage_appearance = damage_appearance - */ - - var/image/standing_image = image('icons/mob/dam_human.dmi', "blank") - - // blend the individual damage states with our icons - for(var/datum/organ/external/O in organs) - if(!(O.status & ORGAN_DESTROYED)) - O.update_icon() - if(O.damage_state == "00") continue - - var/icon/DI - - DI = get_damage_icon_part(O.damage_state, O.icon_name, (species.blood_color == "#A10808" ? "" : species.blood_color)) - - standing_image.overlays += DI - var/obj/Overlays/O = obj_overlays[DAMAGE_LAYER] - overlays -= O - O.overlays.len = 0 - O.overlays += standing_image - overlays += O - obj_overlays[DAMAGE_LAYER] = O - //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) - - - 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 = (M_HUSK in src.mutations) //100% unnecessary -Agouri //nope, do you really want to iterate through src.mutations repeatedly? -Pete - var/fat = (M_FAT in src.mutations) && (species && species.flags & CAN_BE_FAT) - var/hulk = (M_HULK in src.mutations) && species.name == "Horror" // Part of the species. - 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,fat) - 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/has_head = 0 - if(head && !(head.status & ORGAN_DESTROYED)) - has_head = 1 - - 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/groin) || istype(part, /datum/organ/external/head)) - temp = part.get_icon(g,fat) - else - temp = part.get_icon() - - if(part.status & ORGAN_DEAD) - 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") - 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) - 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) - - 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(has_head) - //Eyes - if(!skeleton) - var/icon/eyes = new/icon('icons/mob/human_face.dmi', species.eyes) - eyes.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) - stand_icon.Blend(eyes, ICON_OVERLAY) - - //Mouth (lipstick!) - if(lip_style && (species && species.flags & HAS_LIPS)) //skeletons are allowed to wear lipstick no matter what you think, agouri. - stand_icon.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_s"), ICON_OVERLAY) - - //Underwear - if(underwear >0 && underwear < 12 && species.flags & HAS_UNDERWEAR) - if(!fat && !skeleton) - stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY) - - if(update_icons) - update_icons() - - //tail - update_tail_showing(0) - - -//HAIR OVERLAY -/mob/living/carbon/human/proc/update_hair(var/update_icons=1) - //Reset our hair - - overlays -= obj_overlays[HAIR_LAYER] - - var/datum/organ/external/head/head_organ = get_organ("head") - if( !head_organ || (head_organ.status & ORGAN_DESTROYED) ) - if(update_icons) update_icons() - return - - //masks and helmets can obscure our hair. - if(check_hidden_head_flags(HIDEHEADHAIR) && check_hidden_head_flags(HIDEBEARDHAIR)) - if(update_icons) update_icons() - return - - //base icons - var/icon/face_standing = new /icon('icons/mob/human_face.dmi',"bald_s") - - if(f_style && !check_hidden_head_flags(HIDEBEARDHAIR)) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if((facial_hair_style) && (src.species.name in facial_hair_style.species_allowed)) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - if(facial_hair_style.do_colouration) - facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) - face_standing.Blend(facial_s, ICON_OVERLAY) - else - warning("Invalid f_style for [species.name]: [f_style]") - - if(h_style && !check_hidden_head_flags(HIDEHEADHAIR)) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if((hair_style) && (src.species.name in hair_style.species_allowed)) - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - if(hair_style.do_colouration) - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) - if(hair_style.additional_accessories) - hair_s.Blend(icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_acc"), ICON_OVERLAY) - - face_standing.Blend(hair_s, ICON_OVERLAY) - else - warning("Invalid h_style for [species.name]: [h_style]") - - //overlays_standing[HAIR_LAYER] = image(face_standing) - var/image/I = image(face_standing) - var/obj/Overlays/O = obj_overlays[HAIR_LAYER] - O.icon = I - O.icon_state = I.icon_state - overlays += O - obj_overlays[HAIR_LAYER] = O - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_mutations(var/update_icons=1) - - var/fat - if(M_FAT in mutations) - fat = "fat" - - var/image/standing = image("icon" = 'icons/effects/genetics.dmi') - overlays -= obj_overlays[MUTATIONS_LAYER] - var/obj/Overlays/O = obj_overlays[MUTATIONS_LAYER] - O.overlays.len = 0 - O.underlays.len = 0 - - var/add_image = 0 - var/g = "m" - if(gender == FEMALE) g = "f" - // DNA2 - Drawing underlays. - var/hulk = 0 - for(var/gene_type in active_genes) - var/datum/dna/gene/gene = dna_genes[gene_type] - if(!gene.block) - continue - if(gene.name == "Hulk") hulk = 1 - var/underlay=gene.OnDrawUnderlays(src,g,fat) - if(underlay) - //standing.underlays += underlay - O.underlays += underlay - add_image = 1 - for(var/mut in mutations) - switch(mut) - if(M_HULK) - if(!hulk) - if(fat) - standing.underlays += "hulk_[fat]_s" - else - standing.underlays += "hulk_[g]_s" - add_image = 1 - /*if(M_RESIST_COLD) - standing.underlays += "fire[fat]_s" - add_image = 1 - if(M_RESIST_HEAT) - standing.underlays += "cold[fat]_s" - add_image = 1 - if(TK) - standing.underlays += "telekinesishead[fat]_s" - add_image = 1 - */ - if(M_LASER) - //standing.overlays += "lasereyes_s" - O.overlays += "lasereyes_s" - add_image = 1 - if((M_RESIST_COLD in mutations) && (M_RESIST_HEAT in mutations)) - //standing.underlays -= "cold[fat]_s" - //standing.underlays -= "fire[fat]_s" - //standing.underlays += "coldfire[fat]_s" - O.underlays -= "cold[fat]_s" - O.underlays -= "fire[fat]_s" - O.underlays += "coldfire[fat]_s" - - if(add_image) - O.icon = standing - O.icon_state = standing.icon_state - overlays += O - obj_overlays[MUTATIONS_LAYER] = O - //overlays_standing[MUTATIONS_LAYER] = standing - //else - //overlays_standing[MUTATIONS_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/proc/update_mutantrace(var/update_icons=1) - - - var/fat - if( M_FAT in mutations ) - fat = "fat" -// var/g = "m" -// if (gender == FEMALE) g = "f" -//BS12 EDIT - var/skeleton = (SKELETON in src.mutations) - if(skeleton) - race_icon = 'icons/mob/human_races/r_skeleton.dmi' - else - //Icon data is kept in species datums within the mob. - race_icon = species.icobase - deform_icon = species.deform - overlays -= obj_overlays[MUTANTRACE_LAYER] - if(dna) - switch(dna.mutantrace) - if("golem","slime","shadow","adamantine","coalgolem") - if(species && (!species.override_icon && species.has_mutant_race)) - var/obj/Overlays/O = obj_overlays[MUTANTRACE_LAYER] - O.icon = 'icons/effects/genetics.dmi' - O.icon_state = "[dna.mutantrace][fat]_[gender]_s" - overlays += O - obj_overlays[MUTANTRACE_LAYER] = O - //overlays_standing[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/genetics.dmi', "icon_state" = "[dna.mutantrace][fat]_[gender]_s") - //else - //overlays_standing[MUTANTRACE_LAYER] = null - - if(!dna || !(dna.mutantrace in list("golem","metroid"))) - update_body(0) - - update_hair(0) - if(update_icons) update_icons() - -//Call when target overlay should be added/removed -/mob/living/carbon/human/update_targeted(var/update_icons=1) - overlays -= obj_overlays[TARGETED_LAYER] - if (targeted_by && target_locked) - var/obj/Overlays/O = obj_overlays[TARGETED_LAYER] - O.icon = target_locked - O.icon_state = "locking" //Does not update to "locked" sprite, need to find a way to get icon_state from an image, or rewrite Targeted() proc - overlays += O - obj_overlays[TARGETED_LAYER] = O - //overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - del(target_locked) - //if (!targeted_by) - //overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_fire(var/update_icons=1) - overlays -= obj_overlays[FIRE_LAYER] - if(on_fire) - var/obj/Overlays/O = obj_overlays[FIRE_LAYER] - O.icon = fire_dmi - O.icon_state = fire_sprite - overlays += O - obj_overlays[FIRE_LAYER] = O - //overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_sprite, "layer"=-FIRE_LAYER) - //else - //overlays_standing[FIRE_LAYER] = null - if(update_icons) update_icons() - - -/* --------------------------------------- */ -//For legacy support. -/mob/living/carbon/human/regenerate_icons() - ..() - if(monkeyizing) return - update_fire(0) - update_mutations(0) - update_mutantrace(0) - update_inv_w_uniform(0) - update_inv_gloves(0) - update_inv_glasses(0) - update_inv_ears(0) - update_inv_shoes(0) - update_inv_s_store(0) - update_inv_wear_mask(0) - update_inv_head(0) - update_inv_belt(0) - update_inv_back(0) - update_inv_wear_suit(0) - update_inv_wear_id(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_handcuffed(0) - update_inv_legcuffed(0) - update_inv_pockets(0) - QueueUpdateDamageIcon(1) - update_icons() - //Hud Stuff - update_hud() - -/* --------------------------------------- */ -//vvvvvv UPDATE_INV PROCS vvvvvv - -/mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) - - overlays -= obj_overlays[UNIFORM_LAYER] - if(w_uniform && istype(w_uniform, /obj/item/clothing/under) && !check_hidden_body_flags(HIDEJUMPSUIT)) - w_uniform.screen_loc = ui_iclothing - var/obj/Overlays/O = obj_overlays[UNIFORM_LAYER] - O.overlays.len = 0 - var/t_color = w_uniform._color - if(!t_color) t_color = icon_state - var/image/standing = image("icon_state" = "[t_color]_s") - - if((M_FAT in mutations) && (species.flags & CAN_BE_FAT)) - if(w_uniform.flags&ONESIZEFITSALL) - standing.icon = 'icons/mob/uniform_fat.dmi' - else - to_chat(src, "You burst out of \the [w_uniform]!") - drop_from_inventory(w_uniform) - return - else - standing.icon = 'icons/mob/uniform.dmi' - - var/obj/item/clothing/under/under_uniform = w_uniform - if(species.name in under_uniform.species_fit) //Allows clothes to display differently for multiple species - if(species.uniform_icons) - standing.icon = species.uniform_icons - - if(w_uniform.icon_override) - standing.icon = w_uniform.icon_override - - if(w_uniform.dynamic_overlay) - if(w_uniform.dynamic_overlay["[UNIFORM_LAYER]"]) - var/image/dyn_overlay = w_uniform.dynamic_overlay["[UNIFORM_LAYER]"] - O.overlays += dyn_overlay - - if(w_uniform.blood_DNA && w_uniform.blood_DNA.len) - var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "uniformblood") - bloodsies.color = w_uniform.blood_color - //standing.overlays += bloodsies - O.overlays += bloodsies - - if(under_uniform.accessories.len) //Runtime operator is not permitted, typecast - for(var/obj/item/clothing/accessory/accessory in under_uniform.accessories) - var/tie_color = accessory._color - if(!tie_color) - tie_color = accessory.icon_state - O.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]") - - - O.icon = standing - O.icon_state = standing.icon_state - overlays += O - obj_overlays[UNIFORM_LAYER] = O - //overlays_standing[UNIFORM_LAYER] = standing - else if (!check_hidden_body_flags(HIDEJUMPSUIT)) - //overlays_standing[UNIFORM_LAYER] = null - // 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) // - u_equip(thing,1) // - if (client) // - client.screen -= thing // - // - if (thing) // - thing.loc = loc // - //thing.dropped(src) // - thing.layer = initial(thing.layer) - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) - overlays -= obj_overlays[ID_LAYER] - if(wear_id) - wear_id.screen_loc = ui_id //TODO - if(w_uniform && w_uniform:displays_id) - var/obj/Overlays/O = obj_overlays[ID_LAYER] - var/obj/item/weapon/card/ID_worn = wear_id - O.icon = 'icons/mob/ids.dmi' - O.icon_state = ID_worn.icon_state - O.overlays.len = 0 - if(wear_id.dynamic_overlay) - if(wear_id.dynamic_overlay["[ID_LAYER]"]) - var/image/dyn_overlay = wear_id.dynamic_overlay["[ID_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[ID_LAYER] = O - //overlays_standing[ID_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id") - //else - //overlays_standing[ID_LAYER] = null - //else - //overlays_standing[ID_LAYER] = null - - hud_updateflag |= 1 << ID_HUD - hud_updateflag |= 1 << WANTED_HUD - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_gloves(var/update_icons=1) - overlays -= obj_overlays[GLOVES_LAYER] - var/obj/Overlays/O = obj_overlays[GLOVES_LAYER] - O.overlays.len = 0 - O.color = null - if(gloves && !check_hidden_body_flags(HIDEGLOVES)) - - - 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/obj/item/I = gloves - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.gloves_icons) - standing.icon = species.gloves_icons - if(gloves.dynamic_overlay) - if(gloves.dynamic_overlay["[GLOVES_LAYER]"]) - var/image/dyn_overlay = gloves.dynamic_overlay["[GLOVES_LAYER]"] - O.overlays += dyn_overlay - - if(gloves.blood_DNA && gloves.blood_DNA.len) - var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "bloodyhands") - bloodsies.color = gloves.blood_color - standing.overlays += bloodsies - O.overlays += bloodsies - gloves.screen_loc = ui_gloves - - O.icon = standing - O.icon_state = standing.icon_state - overlays += O - obj_overlays[GLOVES_LAYER] = O - //overlays_standing[GLOVES_LAYER] = standing - else - if(blood_DNA && blood_DNA.len) - O.icon = 'icons/effects/blood.dmi' - O.icon_state = "bloodyhands" - O.color = hand_blood_color - //var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "bloodyhands") - //bloodsies.color = hand_blood_color - //overlays_standing[GLOVES_LAYER] = bloodsies - overlays += O - obj_overlays[GLOVES_LAYER] = O - //else - //overlays_standing[GLOVES_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_glasses(var/update_icons=1) - overlays -= obj_overlays[GLASSES_LAYER] - overlays -= obj_overlays[GLASSES_OVER_HAIR_LAYER] - if(glasses && !check_hidden_head_flags(HIDEEYES)) - var/image/standing = image("icon" = ((glasses.icon_override) ? glasses.icon_override : 'icons/mob/eyes.dmi'), "icon_state" = "[glasses.icon_state]") - - var/obj/item/I = glasses - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.glasses_icons) - standing.icon = species.glasses_icons - - if(glasses.cover_hair) - var/obj/Overlays/O = obj_overlays[GLASSES_OVER_HAIR_LAYER] - O.icon = standing - O.icon_state = standing.icon_state - O.overlays.len = 0 - if(glasses.dynamic_overlay) - if(glasses.dynamic_overlay["[GLASSES_OVER_HAIR_LAYER]"]) - var/image/dyn_overlay = glasses.dynamic_overlay["[GLASSES_OVER_HAIR_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[GLASSES_OVER_HAIR_LAYER] = O - //overlays_standing[GLASSES_OVER_HAIR_LAYER] = standing - else - var/obj/Overlays/O = obj_overlays[GLASSES_LAYER] - O.icon = standing - O.icon_state = standing.icon_state - O.overlays.len = 0 - if(glasses.dynamic_overlay) - if(glasses.dynamic_overlay["[GLASSES_LAYER]"]) - var/image/dyn_overlay = glasses.dynamic_overlay["[GLASSES_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[GLASSES_LAYER] = O - //overlays_standing[GLASSES_LAYER] = standing - - - //else - //overlays_standing[GLASSES_LAYER] = null - //overlays_standing[GLASSES_OVER_HAIR_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_ears(var/update_icons=1) - - overlays -= obj_overlays[EARS_LAYER] - if(ears && !check_hidden_head_flags(HIDEEARS)) - var/image/standing = image("icon" = ((ears.icon_override) ? ears.icon_override : 'icons/mob/ears.dmi'), "icon_state" = "[ears.icon_state]") - - var/obj/item/I = ears - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.ears_icons) - standing.icon = species.ears_icons - - var/obj/Overlays/O = obj_overlays[EARS_LAYER] - O.icon = standing - O.icon_state = standing.icon_state - O.overlays.len = 0 - if(ears.dynamic_overlay) - if(ears.dynamic_overlay["[EARS_LAYER]"]) - var/image/dyn_overlay = ears.dynamic_overlay["[EARS_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[EARS_LAYER] = O - //overlays_standing[EARS_LAYER] = standing - //else - //overlays_standing[EARS_LAYER] = null - - if(update_icons) update_icons() -/mob/living/carbon/human/update_inv_shoes(var/update_icons=1) - overlays -= obj_overlays[SHOES_LAYER] - if(shoes && !check_hidden_body_flags(HIDESHOES)) - var/obj/Overlays/O = obj_overlays[SHOES_LAYER] - O.icon = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi') - O.icon_state = shoes.icon_state - //var/image/standing = image("icon" = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi'), "icon_state" = "[shoes.icon_state]") - - var/obj/item/I = shoes - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.shoes_icons) - O.icon = species.shoes_icons - //standing.icon = species.shoes_icons - - O.overlays.len = 0 - if(shoes.dynamic_overlay) - if(shoes.dynamic_overlay["[SHOES_LAYER]"]) - var/image/dyn_overlay = shoes.dynamic_overlay["[SHOES_LAYER]"] - O.overlays += dyn_overlay - if(shoes.blood_DNA && shoes.blood_DNA.len) - var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "shoeblood") - bloodsies.color = shoes.blood_color - //standing.overlays += bloodsies - O.overlays += bloodsies - //overlays_standing[SHOES_LAYER] = standing - overlays += O - obj_overlays[SHOES_LAYER] = O - //else - //overlays_standing[SHOES_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_s_store(var/update_icons=1) - overlays -= obj_overlays[SUIT_STORE_LAYER] - if(s_store && !check_hidden_body_flags(HIDESUITSTORAGE)) - var/t_state = s_store.item_state - if(!t_state) t_state = s_store.icon_state - var/obj/Overlays/O = obj_overlays[SUIT_STORE_LAYER] - O.icon = 'icons/mob/belt_mirror.dmi' - O.icon_state = t_state - O.overlays.len = 0 - if(s_store.dynamic_overlay) - if(s_store.dynamic_overlay["[SUIT_STORE_LAYER]"]) - var/image/dyn_overlay = s_store.dynamic_overlay["[SUIT_STORE_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[SUIT_STORE_LAYER] = O - //overlays_standing[SUIT_STORE_LAYER] = image("icon" = 'icons/mob/belt_mirror.dmi', "icon_state" = "[t_state]") - s_store.screen_loc = ui_sstore1 //TODO - //else - //overlays_standing[SUIT_STORE_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_head(var/update_icons=1) - overlays -= obj_overlays[HEAD_LAYER] - if(head) - var/obj/Overlays/O = obj_overlays[HEAD_LAYER] - O.overlays.len = 0 - head.screen_loc = ui_head //TODO - var/image/standing - 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]") - - var/obj/item/I = head - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.head_icons) - standing.icon = species.head_icons - - if(head.dynamic_overlay) - if(head.dynamic_overlay["[HEAD_LAYER]"]) - var/image/dyn_overlay = head.dynamic_overlay["[HEAD_LAYER]"] - O.overlays += dyn_overlay - - if(head.blood_DNA && head.blood_DNA.len) - var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") - bloodsies.color = head.blood_color - //standing.overlays += bloodsies - O.overlays += bloodsies - O.icon = standing - O.icon_state = standing.icon_state - overlays += O - obj_overlays[HEAD_LAYER] = O - //overlays_standing[HEAD_LAYER] = standing - //else - //overlays_standing[HEAD_LAYER] = null - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_belt(var/update_icons=1) - overlays -= obj_overlays[BELT_LAYER] - if(belt) - belt.screen_loc = ui_belt //TODO - var/t_state = belt.item_state - if(!t_state) t_state = belt.icon_state - var/image/standing = image("icon" = ((belt.icon_override) ? belt.icon_override : 'icons/mob/belt.dmi'), "icon_state" = "[t_state]") - - var/obj/item/I = belt - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.belt_icons) - standing.icon = species.belt_icons - var/obj/Overlays/O = obj_overlays[BELT_LAYER] - O.icon = standing - O.icon_state = standing.icon_state - O.overlays.len = 0 - if(belt.dynamic_overlay) - if(belt.dynamic_overlay["[BELT_LAYER]"]) - var/image/dyn_overlay = belt.dynamic_overlay["[BELT_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[BELT_LAYER] = O - //overlays_standing[BELT_LAYER] = standing - //else - //overlays_standing[BELT_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) - overlays -= obj_overlays[SUIT_LAYER] - if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) ) //TODO check this - wear_suit.screen_loc = ui_oclothing //TODO - var/obj/Overlays/O = obj_overlays[SUIT_LAYER] - O.overlays.len = 0 - var/image/standing = image("icon" = ((wear_suit.icon_override) ? wear_suit.icon_override : 'icons/mob/suit.dmi'), "icon_state" = "[wear_suit.icon_state]") - - if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) - drop_from_inventory(handcuffed) - drop_hands() - - var/obj/item/I = wear_suit - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.wear_suit_icons) - standing.icon = species.wear_suit_icons - - if(wear_suit.dynamic_overlay) - if(wear_suit.dynamic_overlay["[SUIT_LAYER]"]) - var/image/dyn_overlay = wear_suit.dynamic_overlay["[SUIT_LAYER]"] - O.overlays += dyn_overlay - - if(wear_suit.blood_DNA && wear_suit.blood_DNA.len) - var/obj/item/clothing/suit/S = wear_suit - var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[S.blood_overlay_type]blood") - bloodsies.color = wear_suit.blood_color - //standing.overlays += bloodsies - O.overlays += bloodsies - - O.icon = standing - O.icon_state = standing.icon_state - overlays += O - obj_overlays[SUIT_LAYER] = O - //overlays_standing[SUIT_LAYER] = standing - update_tail_showing(0) - else - //overlays_standing[SUIT_LAYER] = null - update_tail_showing(0) - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_pockets(var/update_icons=1) - - if(l_store) l_store.screen_loc = ui_storage1 //TODO - if(r_store) r_store.screen_loc = ui_storage2 //TODO - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1) - overlays -= obj_overlays[FACEMASK_LAYER] - if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory) ) && !check_hidden_head_flags(HIDEMASK)) - var/obj/Overlays/O = obj_overlays[FACEMASK_LAYER] - O.overlays.len = 0 - 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/obj/item/I = wear_mask - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.wear_mask_icons) //This REQUIRES the species to be listed in species_fit and also to have an appropriate dmi allocated in their species datum - standing.icon = species.wear_mask_icons - - if(wear_mask.dynamic_overlay) - if(wear_mask.dynamic_overlay["[FACEMASK_LAYER]"]) - var/image/dyn_overlay = wear_mask.dynamic_overlay["[FACEMASK_LAYER]"] - O.overlays += dyn_overlay - - if( !istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA && wear_mask.blood_DNA.len ) - var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "maskblood") - bloodsies.color = wear_mask.blood_color - //standing.overlays += bloodsies - O.overlays += bloodsies - - O.icon = standing - O.icon_state = standing.icon_state - overlays += O - obj_overlays[FACEMASK_LAYER] = O - //overlays_standing[FACEMASK_LAYER] = standing - //else - //overlays_standing[FACEMASK_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_back(var/update_icons=1) - overlays -= obj_overlays[BACK_LAYER] - if(back) - back.screen_loc = ui_back //TODO - var/image/standing = image("icon" = ((back.icon_override) ? back.icon_override : 'icons/mob/back.dmi'), "icon_state" = "[back.icon_state]") - - var/obj/item/I = back - if(species.name in I.species_fit) //Allows clothes to display differently for multiple species - if(species.back_icons) - standing.icon = species.back_icons - - var/obj/Overlays/O = obj_overlays[BACK_LAYER] - O.icon = standing - O.icon_state = standing.icon_state - O.overlays.len = 0 - if(back.dynamic_overlay) - if(back.dynamic_overlay["[BACK_LAYER]"]) - var/image/dyn_overlay = back.dynamic_overlay["[BACK_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[BACK_LAYER] = O - - //overlays_standing[BACK_LAYER] = standing - //else - //overlays_standing[BACK_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_hud() //TODO: do away with this if possible - if(client) - client.screen |= contents - if(hud_used) - hud_used.hidden_inventory_update() //Updates the screenloc of the items on the 'other' inventory bar - - -/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) - overlays -= obj_overlays[HANDCUFF_LAYER] - if(handcuffed) - drop_hands() - stop_pulling() //TODO: should be handled elsewhere - var/obj/Overlays/O = obj_overlays[HANDCUFF_LAYER] - O.icon = 'icons/mob/mob.dmi' - O.icon_state = "handcuff1" - overlays += O - obj_overlays[HANDCUFF_LAYER] = O - //overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1") - //else - //overlays_standing[HANDCUFF_LAYER] = null - - if(update_icons) update_icons() - -/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) - overlays -= obj_overlays[LEGCUFF_LAYER] - if(legcuffed) - var/obj/Overlays/O = obj_overlays[LEGCUFF_LAYER] - O.icon = 'icons/mob/mob.dmi' - O.icon_state = "legcuff1" - overlays += O - obj_overlays[LEGCUFF_LAYER] = O - //overlays_standing[LEGCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1") - if(src.m_intent != "walk") - src.m_intent = "walk" - if(src.hud_used && src.hud_used.move_intent) - src.hud_used.move_intent.icon_state = "walking" - - //elsek - //overlays_standing[LEGCUFF_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) - overlays -= obj_overlays[R_HAND_LAYER] - if(r_hand) - r_hand.screen_loc = ui_rhand //TODO - var/t_state = r_hand.item_state - var/t_inhand_state = r_hand.inhand_states["right_hand"] - var/icon/check_dimensions = new(t_inhand_state) - if(!t_state) t_state = r_hand.icon_state - var/obj/Overlays/O = obj_overlays[R_HAND_LAYER] - O.icon = t_inhand_state - O.icon_state = t_state - O.pixel_x = -1*(check_dimensions.Width() - 32)/2 - O.pixel_y = -1*(check_dimensions.Height() - 32)/2 - O.overlays.len = 0 - if(r_hand.dynamic_overlay) - if(r_hand.dynamic_overlay["[R_HAND_LAYER]"]) - var/image/dyn_overlay = r_hand.dynamic_overlay["[R_HAND_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[R_HAND_LAYER] = O - //overlays_standing[R_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = "[t_state]") - if (handcuffed) - drop_item(r_hand) - //else - //overlays_standing[R_HAND_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) - overlays -= obj_overlays[L_HAND_LAYER] - if(l_hand) - l_hand.screen_loc = ui_lhand //TODO - var/t_state = l_hand.item_state - var/icon/t_inhand_state = l_hand.inhand_states["left_hand"] - var/icon/check_dimensions = new(t_inhand_state) - if(!t_state) t_state = l_hand.icon_state - var/obj/Overlays/O = obj_overlays[L_HAND_LAYER] - O.icon = t_inhand_state - O.icon_state = t_state - O.pixel_x = -1*(check_dimensions.Width() - 32)/2 - O.pixel_y = -1*(check_dimensions.Height() - 32)/2 - O.overlays.len = 0 - if(l_hand.dynamic_overlay) - if(l_hand.dynamic_overlay["[L_HAND_LAYER]"]) - var/image/dyn_overlay = l_hand.dynamic_overlay["[L_HAND_LAYER]"] - O.overlays += dyn_overlay - overlays += O - obj_overlays[L_HAND_LAYER] = O - //overlays_standing[L_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = "[t_state]") - if (handcuffed) - drop_item(l_hand) - //else - //overlays_standing[L_HAND_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/human/proc/update_tail_showing(var/update_icons=1) - //overlays_standing[TAIL_LAYER] = null - overlays -= obj_overlays[TAIL_LAYER] - if(species.tail && species.flags & HAS_TAIL) - if(!wear_suit || !(wear_suit.flags_inv & HIDEJUMPSUIT) && !istype(wear_suit, /obj/item/clothing/suit/space)) - var/obj/Overlays/O = obj_overlays[TAIL_LAYER] - O.icon = 'icons/effects/species.dmi' - O.icon_state = "[species.tail]_s" - overlays += O - obj_overlays[TAIL_LAYER] = O - //if(!old_tail_state) //only update if we didnt show our tail already - - //overlays_standing[TAIL_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") -// to_chat(src, "update: tail is different") - //else - //overlays_standing[TAIL_LAYER] = null - - if(update_icons) - update_icons() - -// Used mostly for creating head items -/mob/living/carbon/human/proc/generate_head_icon() -//gender no longer matters for the mouth, although there should probably be seperate base head icons. -// var/g = "m" -// if (gender == FEMALE) g = "f" - - //base icons - var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l") - - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style) - var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l") - facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) - face_lying.Blend(facial_l, ICON_OVERLAY) - - if(h_style) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if(hair_style) - var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l") - hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) - face_lying.Blend(hair_l, ICON_OVERLAY) - - //Eyes - // Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head - var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l") - eyes_l.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) - face_lying.Blend(eyes_l, ICON_OVERLAY) - - if(lip_style) - face_lying.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_l"), ICON_OVERLAY) - - var/image/face_lying_image = new /image(icon = face_lying) - return face_lying_image - -//lower cost way of updating the necessary human icons on equip and unequip -/mob/living/carbon/human/proc/update_hidden_item_icons(var/obj/item/W) - if(!W) - return - - if(W.flags_inv & HIDEHAIR) - update_hair() - if(W.flags_inv & (HIDEGLOVES | HIDEMASK)) - update_inv_wear_mask() - update_inv_gloves() - if(W.flags_inv & HIDESHOES) - update_inv_shoes() - if(W.flags_inv & (HIDEJUMPSUIT | HIDEEYES)) - update_inv_w_uniform() - update_inv_glasses() - if(W.flags_inv & (HIDESUITSTORAGE | HIDEEARS)) - update_inv_s_store() - update_inv_ears() + /////////////////////// + //UPDATE_ICONS SYSTEM// + /////////////////////// +/* +Calling this a system is perhaps a bit trumped up. It is essentially update_clothing dismantled into its +core parts. The key difference is that when we generate overlays we do not generate either lying or standing +versions. Instead, we generate both and store them in two fixed-length lists, both using the same list-index +(The indexes are in update_icons.dm): Each list for humans is (at the time of writing) of length 19. +This will hopefully be reduced as the system is refined. + var/overlays_lying[19] //For the lying down stance + var/overlays_standing[19] //For the standing stance +When we call update_icons, the 'lying' variable is checked and then the appropriate list is assigned to our overlays! +That in itself uses a tiny bit more memory (no more than all the ridiculous lists the game has already mind you). +On the other-hand, it should be very CPU cheap in comparison to the old system. +In the old system, we updated all our overlays every life() call, even if we were standing still inside a crate! +or dead!. 25ish overlays, all generated from scratch every second for every xeno/human/monkey and then applied. +More often than not update_clothing was being called a few times in addition to that! CPU was not the only issue, +all those icons had to be sent to every client. So really the cost was extremely cumulative. To the point where +update_clothing would frequently appear in the top 10 most CPU intensive procs during profiling. +Another feature of this new system is that our lists are indexed. This means we can update specific overlays! +So we only regenerate icons when we need them to be updated! This is the main saving for this system. +In practice this means that: + everytime you fall over, we just switch between precompiled lists. Which is fast and cheap. + Everytime you do something minor like take a pen out of your pocket, we only update the in-hand overlay + etc... +There are several things that need to be remembered: +> Whenever we do something that should cause an overlay to update (which doesn't use standard procs + ( i.e. you do something like l_hand = /obj/item/something new(src) ) + You will need to call the relevant update_inv_* proc: + update_inv_head() + update_inv_wear_suit() + update_inv_gloves() + update_inv_shoes() + update_inv_w_uniform() + update_inv_glasse() + update_inv_l_hand() + update_inv_r_hand() + update_inv_belt() + update_inv_wear_id() + update_inv_ears() + update_inv_s_store() + update_inv_pockets() + update_inv_back() + update_inv_handcuffed() + update_inv_wear_mask() + All of these are named after the variable they update from. They are defined at the mob/ level like + update_clothing was, so you won't cause undefined proc runtimes with usr.update_inv_wear_id() if the usr is a + slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such. +> There are also these special cases: + update_mutations() //handles updating your appearance for certain mutations. e.g TK head-glows + update_mutantrace() //handles updating your appearance after setting the mutantrace var + QueueUpdateDamageIcon() //handles damage overlays for brute/burn damage //(will rename this when I geta round to it) + update_body() //Handles updating your mob's icon to reflect their gender/race/complexion etc + update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and + ...eyes were merged into update_body) + update_targeted() // Updates the target overlay when someone points a gun at you +> All of these procs update our overlays_lying and overlays_standing, and then call update_icons() by default. + If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call + it manually: + e.g. + update_inv_head(0) + update_inv_l_hand(0) + update_inv_r_hand() //<---calls update_icons() + or equivillantly: + update_inv_head(0) + update_inv_l_hand(0) + update_inv_r_hand(0) + update_icons() +> If you need to update all overlays you can use regenerate_icons(). it works exactly like update_clothing used to. +> I reimplimented an old unused variable which was in the code called (coincidentally) var/update_icon + It can be used as another method of triggering regenerate_icons(). It's basically a flag that when set to non-zero + will call regenerate_icons() at the next life() call and then reset itself to 0. + The idea behind it is icons are regenerated only once, even if multiple events requested it. +This system is confusing and is still a WIP. It's primary goal is speeding up the controls of the game whilst +reducing processing costs. So please bear with me while I iron out the kinks. It will be worth it, I promise. +If I can eventually free var/lying stuff from the life() process altogether, stuns/death/status stuff +will become less affected by lag-spikes and will be instantaneous! :3 +If you have any questions/constructive-comments/bugs-to-report/or have a massivly devestated butt... +Please contact me on #coderbus IRC. ~Carn x +*/ + +/mob/living/carbon/human + var/list/overlays_standing[TOTAL_LAYERS] + var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed + var/icon/race_icon + var/icon/deform_icon + var/update_overlays = 0 + + +/mob/living/carbon/human/proc/QueueUpdateDamageIcon(var/forced = 0) + if(forced) + UpdateDamageIcon(1) + update_overlays = 0 + return + update_overlays = 1 + +//UPDATES OVERLAYS FROM OVERLAYS_LYING/OVERLAYS_STANDING +//this proc is messy as I was forced to include some old laggy cloaking code to it so that I don't break cloakers +//I'll work on removing that stuff by rewriting some of the cloaking stuff at a later date. +/mob/living/carbon/human/update_icons() + update_hud() //TODO: remove the need for this + update_overlays_standing() + update_transform() + +/mob/living/carbon/human/proc/update_overlays_standing() + if(species && species.override_icon) + species_override_icon() + else + generate_overlays_icon() + +/mob/living/carbon/human/proc/species_override_icon() + //overlays.len = 0 + icon = species.override_icon + icon_state = "[lowertext(species.name)]_[gender][ (species.flags & CAN_BE_FAT ? (mutations & M_FAT) ? "_fat" : "" : "") ]" + //temporary fix for having mutations on top of overriden icons for like muton, horror, etc + overlays -= obj_overlays[MUTANTRACE_LAYER] + + +/mob/living/carbon/human/proc/generate_overlays_icon() + icon = stand_icon + +var/global/list/damage_icon_parts = list() + +/mob/living/carbon/human/proc/get_damage_icon_part(damage_state, body_part,species_blood = "") + var/icon/I = damage_icon_parts["[damage_state]/[body_part]/[species_blood]"] + if(!I) + var/icon/DI = icon('icons/mob/dam_human.dmi', damage_state) // the damage icon for whole human + DI.Blend(icon('icons/mob/dam_mask.dmi', body_part), ICON_MULTIPLY) // mask with this organ's pixels + if(species_blood) + DI.Blend(species_blood, ICON_MULTIPLY) // mask with this species's blood color + damage_icon_parts["[damage_state]/[body_part]/[species_blood]"] = DI + return DI + else + return I + +//DAMAGE OVERLAYS +//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists +/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1) + // first check whether something actually changed about damage appearance + /*for(var/datum/organ/external/O in organs) + if(O.status & ORGAN_DESTROYED) damage_appearance += "d" + else + damage_appearance += O.damage_state + if(damage_appearance == previous_damage_appearance) + // nothing to do here + return + previous_damage_appearance = damage_appearance + */ + + var/image/standing_image = image('icons/mob/dam_human.dmi', "blank") + + // blend the individual damage states with our icons + for(var/datum/organ/external/O in organs) + if(!(O.status & ORGAN_DESTROYED)) + O.update_icon() + if(O.damage_state == "00") continue + + var/icon/DI + + DI = get_damage_icon_part(O.damage_state, O.icon_name, (species.blood_color == "#A10808" ? "" : species.blood_color)) + + standing_image.overlays += DI + var/obj/Overlays/O = obj_overlays[DAMAGE_LAYER] + overlays -= O + O.overlays.len = 0 + O.overlays += standing_image + overlays += O + obj_overlays[DAMAGE_LAYER] = O + //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) + + + 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 = (M_HUSK in src.mutations) //100% unnecessary -Agouri //nope, do you really want to iterate through src.mutations repeatedly? -Pete + var/fat = (M_FAT in src.mutations) && (species && species.flags & CAN_BE_FAT) + var/hulk = (M_HULK in src.mutations) && species.name == "Horror" // Part of the species. + 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,fat) + 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/has_head = 0 + if(head && !(head.status & ORGAN_DESTROYED)) + has_head = 1 + + 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/groin) || istype(part, /datum/organ/external/head)) + temp = part.get_icon(g,fat) + else + temp = part.get_icon() + + if(part.status & ORGAN_DEAD) + 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") + 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) + 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) + + 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(has_head) + //Eyes + if(!skeleton) + var/icon/eyes = new/icon('icons/mob/human_face.dmi', species.eyes) + eyes.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) + stand_icon.Blend(eyes, ICON_OVERLAY) + + //Mouth (lipstick!) + if(lip_style && (species && species.flags & HAS_LIPS)) //skeletons are allowed to wear lipstick no matter what you think, agouri. + stand_icon.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_s"), ICON_OVERLAY) + + //Underwear + if(underwear >0 && underwear < 12 && species.flags & HAS_UNDERWEAR) + if(!fat && !skeleton) + stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY) + + if(update_icons) + update_icons() + + //tail + update_tail_showing(0) + + +//HAIR OVERLAY +/mob/living/carbon/human/proc/update_hair(var/update_icons=1) + //Reset our hair + + overlays -= obj_overlays[HAIR_LAYER] + + var/datum/organ/external/head/head_organ = get_organ("head") + if( !head_organ || (head_organ.status & ORGAN_DESTROYED) ) + if(update_icons) update_icons() + return + + //masks and helmets can obscure our hair. + if(check_hidden_head_flags(HIDEHEADHAIR) && check_hidden_head_flags(HIDEBEARDHAIR)) + if(update_icons) update_icons() + return + + //base icons + var/icon/face_standing = new /icon('icons/mob/human_face.dmi',"bald_s") + + if(f_style && !check_hidden_head_flags(HIDEBEARDHAIR)) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if((facial_hair_style) && (src.species.name in facial_hair_style.species_allowed)) + var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + if(facial_hair_style.do_colouration) + facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + face_standing.Blend(facial_s, ICON_OVERLAY) + else + warning("Invalid f_style for [species.name]: [f_style]") + + if(h_style && !check_hidden_head_flags(HIDEHEADHAIR)) + var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if((hair_style) && (src.species.name in hair_style.species_allowed)) + var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + if(hair_style.do_colouration) + hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + if(hair_style.additional_accessories) + hair_s.Blend(icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_acc"), ICON_OVERLAY) + + face_standing.Blend(hair_s, ICON_OVERLAY) + else + warning("Invalid h_style for [species.name]: [h_style]") + + //overlays_standing[HAIR_LAYER] = image(face_standing) + var/image/I = image(face_standing) + var/obj/Overlays/O = obj_overlays[HAIR_LAYER] + O.icon = I + O.icon_state = I.icon_state + overlays += O + obj_overlays[HAIR_LAYER] = O + + if(update_icons) update_icons() + +/mob/living/carbon/human/update_mutations(var/update_icons=1) + + var/fat + if(M_FAT in mutations) + fat = "fat" + + var/image/standing = image("icon" = 'icons/effects/genetics.dmi') + overlays -= obj_overlays[MUTATIONS_LAYER] + var/obj/Overlays/O = obj_overlays[MUTATIONS_LAYER] + O.overlays.len = 0 + O.underlays.len = 0 + + var/add_image = 0 + var/g = "m" + if(gender == FEMALE) g = "f" + // DNA2 - Drawing underlays. + var/hulk = 0 + for(var/gene_type in active_genes) + var/datum/dna/gene/gene = dna_genes[gene_type] + if(!gene.block) + continue + if(gene.name == "Hulk") hulk = 1 + var/underlay=gene.OnDrawUnderlays(src,g,fat) + if(underlay) + //standing.underlays += underlay + O.underlays += underlay + add_image = 1 + for(var/mut in mutations) + switch(mut) + if(M_HULK) + if(!hulk) + if(fat) + standing.underlays += "hulk_[fat]_s" + else + standing.underlays += "hulk_[g]_s" + add_image = 1 + /*if(M_RESIST_COLD) + standing.underlays += "fire[fat]_s" + add_image = 1 + if(M_RESIST_HEAT) + standing.underlays += "cold[fat]_s" + add_image = 1 + if(TK) + standing.underlays += "telekinesishead[fat]_s" + add_image = 1 + */ + if(M_LASER) + //standing.overlays += "lasereyes_s" + O.overlays += "lasereyes_s" + add_image = 1 + if((M_RESIST_COLD in mutations) && (M_RESIST_HEAT in mutations)) + //standing.underlays -= "cold[fat]_s" + //standing.underlays -= "fire[fat]_s" + //standing.underlays += "coldfire[fat]_s" + O.underlays -= "cold[fat]_s" + O.underlays -= "fire[fat]_s" + O.underlays += "coldfire[fat]_s" + + if(add_image) + O.icon = standing + O.icon_state = standing.icon_state + overlays += O + obj_overlays[MUTATIONS_LAYER] = O + //overlays_standing[MUTATIONS_LAYER] = standing + //else + //overlays_standing[MUTATIONS_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/proc/update_mutantrace(var/update_icons=1) + + + var/fat + if( M_FAT in mutations ) + fat = "fat" +// var/g = "m" +// if (gender == FEMALE) g = "f" +//BS12 EDIT + var/skeleton = (SKELETON in src.mutations) + if(skeleton) + race_icon = 'icons/mob/human_races/r_skeleton.dmi' + else + //Icon data is kept in species datums within the mob. + race_icon = species.icobase + deform_icon = species.deform + overlays -= obj_overlays[MUTANTRACE_LAYER] + if(dna) + switch(dna.mutantrace) + if("golem","slime","shadow","adamantine","coalgolem") + if(species && (!species.override_icon && species.has_mutant_race)) + var/obj/Overlays/O = obj_overlays[MUTANTRACE_LAYER] + O.icon = 'icons/effects/genetics.dmi' + O.icon_state = "[dna.mutantrace][fat]_[gender]_s" + overlays += O + obj_overlays[MUTANTRACE_LAYER] = O + //overlays_standing[MUTANTRACE_LAYER] = image("icon" = 'icons/effects/genetics.dmi', "icon_state" = "[dna.mutantrace][fat]_[gender]_s") + //else + //overlays_standing[MUTANTRACE_LAYER] = null + + if(!dna || !(dna.mutantrace in list("golem","metroid"))) + update_body(0) + + update_hair(0) + if(update_icons) update_icons() + +//Call when target overlay should be added/removed +/mob/living/carbon/human/update_targeted(var/update_icons=1) + overlays -= obj_overlays[TARGETED_LAYER] + if (targeted_by && target_locked) + var/obj/Overlays/O = obj_overlays[TARGETED_LAYER] + O.icon = target_locked + O.icon_state = "locking" //Does not update to "locked" sprite, need to find a way to get icon_state from an image, or rewrite Targeted() proc + overlays += O + obj_overlays[TARGETED_LAYER] = O + //overlays_standing[TARGETED_LAYER] = target_locked + else if (!targeted_by && target_locked) + del(target_locked) + //if (!targeted_by) + //overlays_standing[TARGETED_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/human/update_fire(var/update_icons=1) + overlays -= obj_overlays[FIRE_LAYER] + if(on_fire) + var/obj/Overlays/O = obj_overlays[FIRE_LAYER] + O.icon = fire_dmi + O.icon_state = fire_sprite + overlays += O + obj_overlays[FIRE_LAYER] = O + //overlays_standing[FIRE_LAYER] = image("icon"=fire_dmi, "icon_state"=fire_sprite, "layer"=-FIRE_LAYER) + //else + //overlays_standing[FIRE_LAYER] = null + if(update_icons) update_icons() + + +/* --------------------------------------- */ +//For legacy support. +/mob/living/carbon/human/regenerate_icons() + ..() + if(monkeyizing) return + update_fire(0) + update_mutations(0) + update_mutantrace(0) + update_inv_w_uniform(0) + update_inv_gloves(0) + update_inv_glasses(0) + update_inv_ears(0) + update_inv_shoes(0) + update_inv_s_store(0) + update_inv_wear_mask(0) + update_inv_head(0) + update_inv_belt(0) + update_inv_back(0) + update_inv_wear_suit(0) + update_inv_wear_id(0) + update_inv_r_hand(0) + update_inv_l_hand(0) + update_inv_handcuffed(0) + update_inv_legcuffed(0) + update_inv_pockets(0) + QueueUpdateDamageIcon(1) + update_icons() + //Hud Stuff + update_hud() + +/* --------------------------------------- */ +//vvvvvv UPDATE_INV PROCS vvvvvv + +/mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) + + overlays -= obj_overlays[UNIFORM_LAYER] + if(w_uniform && istype(w_uniform, /obj/item/clothing/under) && !check_hidden_body_flags(HIDEJUMPSUIT)) + w_uniform.screen_loc = ui_iclothing + var/obj/Overlays/O = obj_overlays[UNIFORM_LAYER] + O.overlays.len = 0 + var/t_color = w_uniform._color + if(!t_color) t_color = icon_state + var/image/standing = image("icon_state" = "[t_color]_s") + + if((M_FAT in mutations) && (species.flags & CAN_BE_FAT)) + if(w_uniform.flags&ONESIZEFITSALL) + standing.icon = 'icons/mob/uniform_fat.dmi' + else + to_chat(src, "You burst out of \the [w_uniform]!") + drop_from_inventory(w_uniform) + return + else + standing.icon = 'icons/mob/uniform.dmi' + + var/obj/item/clothing/under/under_uniform = w_uniform + if(species.name in under_uniform.species_fit) //Allows clothes to display differently for multiple species + if(species.uniform_icons) + standing.icon = species.uniform_icons + + if(w_uniform.icon_override) + standing.icon = w_uniform.icon_override + + if(w_uniform.dynamic_overlay) + if(w_uniform.dynamic_overlay["[UNIFORM_LAYER]"]) + var/image/dyn_overlay = w_uniform.dynamic_overlay["[UNIFORM_LAYER]"] + O.overlays += dyn_overlay + + if(w_uniform.blood_DNA && w_uniform.blood_DNA.len) + var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "uniformblood") + bloodsies.color = w_uniform.blood_color + //standing.overlays += bloodsies + O.overlays += bloodsies + + if(under_uniform.accessories.len) //Runtime operator is not permitted, typecast + for(var/obj/item/clothing/accessory/accessory in under_uniform.accessories) + var/tie_color = accessory._color + if(!tie_color) + tie_color = accessory.icon_state + O.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]") + + + O.icon = standing + O.icon_state = standing.icon_state + overlays += O + obj_overlays[UNIFORM_LAYER] = O + //overlays_standing[UNIFORM_LAYER] = standing + else if (!check_hidden_body_flags(HIDEJUMPSUIT)) + //overlays_standing[UNIFORM_LAYER] = null + // 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) // + u_equip(thing,1) // + if (client) // + client.screen -= thing // + // + if (thing) // + thing.loc = loc // + //thing.dropped(src) // + thing.layer = initial(thing.layer) + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) + overlays -= obj_overlays[ID_LAYER] + if(wear_id) + wear_id.screen_loc = ui_id //TODO + if(w_uniform && w_uniform:displays_id) + var/obj/Overlays/O = obj_overlays[ID_LAYER] + var/obj/item/weapon/card/ID_worn = wear_id + O.icon = 'icons/mob/ids.dmi' + O.icon_state = ID_worn.icon_state + O.overlays.len = 0 + if(wear_id.dynamic_overlay) + if(wear_id.dynamic_overlay["[ID_LAYER]"]) + var/image/dyn_overlay = wear_id.dynamic_overlay["[ID_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[ID_LAYER] = O + //overlays_standing[ID_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "id") + //else + //overlays_standing[ID_LAYER] = null + //else + //overlays_standing[ID_LAYER] = null + + hud_updateflag |= 1 << ID_HUD + hud_updateflag |= 1 << WANTED_HUD + + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_gloves(var/update_icons=1) + overlays -= obj_overlays[GLOVES_LAYER] + var/obj/Overlays/O = obj_overlays[GLOVES_LAYER] + O.overlays.len = 0 + O.color = null + if(gloves && !check_hidden_body_flags(HIDEGLOVES)) + + + 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/obj/item/I = gloves + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.gloves_icons) + standing.icon = species.gloves_icons + if(gloves.dynamic_overlay) + if(gloves.dynamic_overlay["[GLOVES_LAYER]"]) + var/image/dyn_overlay = gloves.dynamic_overlay["[GLOVES_LAYER]"] + O.overlays += dyn_overlay + + if(gloves.blood_DNA && gloves.blood_DNA.len) + var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "bloodyhands") + bloodsies.color = gloves.blood_color + standing.overlays += bloodsies + O.overlays += bloodsies + gloves.screen_loc = ui_gloves + + O.icon = standing + O.icon_state = standing.icon_state + overlays += O + obj_overlays[GLOVES_LAYER] = O + //overlays_standing[GLOVES_LAYER] = standing + else + if(blood_DNA && blood_DNA.len) + O.icon = 'icons/effects/blood.dmi' + O.icon_state = "bloodyhands" + O.color = hand_blood_color + //var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "bloodyhands") + //bloodsies.color = hand_blood_color + //overlays_standing[GLOVES_LAYER] = bloodsies + overlays += O + obj_overlays[GLOVES_LAYER] = O + //else + //overlays_standing[GLOVES_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_glasses(var/update_icons=1) + overlays -= obj_overlays[GLASSES_LAYER] + overlays -= obj_overlays[GLASSES_OVER_HAIR_LAYER] + if(glasses && !check_hidden_head_flags(HIDEEYES)) + var/image/standing = image("icon" = ((glasses.icon_override) ? glasses.icon_override : 'icons/mob/eyes.dmi'), "icon_state" = "[glasses.icon_state]") + + var/obj/item/I = glasses + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.glasses_icons) + standing.icon = species.glasses_icons + + if(glasses.cover_hair) + var/obj/Overlays/O = obj_overlays[GLASSES_OVER_HAIR_LAYER] + O.icon = standing + O.icon_state = standing.icon_state + O.overlays.len = 0 + if(glasses.dynamic_overlay) + if(glasses.dynamic_overlay["[GLASSES_OVER_HAIR_LAYER]"]) + var/image/dyn_overlay = glasses.dynamic_overlay["[GLASSES_OVER_HAIR_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[GLASSES_OVER_HAIR_LAYER] = O + //overlays_standing[GLASSES_OVER_HAIR_LAYER] = standing + else + var/obj/Overlays/O = obj_overlays[GLASSES_LAYER] + O.icon = standing + O.icon_state = standing.icon_state + O.overlays.len = 0 + if(glasses.dynamic_overlay) + if(glasses.dynamic_overlay["[GLASSES_LAYER]"]) + var/image/dyn_overlay = glasses.dynamic_overlay["[GLASSES_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[GLASSES_LAYER] = O + //overlays_standing[GLASSES_LAYER] = standing + + + //else + //overlays_standing[GLASSES_LAYER] = null + //overlays_standing[GLASSES_OVER_HAIR_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_ears(var/update_icons=1) + + overlays -= obj_overlays[EARS_LAYER] + if(ears && !check_hidden_head_flags(HIDEEARS)) + var/image/standing = image("icon" = ((ears.icon_override) ? ears.icon_override : 'icons/mob/ears.dmi'), "icon_state" = "[ears.icon_state]") + + var/obj/item/I = ears + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.ears_icons) + standing.icon = species.ears_icons + + var/obj/Overlays/O = obj_overlays[EARS_LAYER] + O.icon = standing + O.icon_state = standing.icon_state + O.overlays.len = 0 + if(ears.dynamic_overlay) + if(ears.dynamic_overlay["[EARS_LAYER]"]) + var/image/dyn_overlay = ears.dynamic_overlay["[EARS_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[EARS_LAYER] = O + //overlays_standing[EARS_LAYER] = standing + //else + //overlays_standing[EARS_LAYER] = null + + if(update_icons) update_icons() +/mob/living/carbon/human/update_inv_shoes(var/update_icons=1) + overlays -= obj_overlays[SHOES_LAYER] + if(shoes && !check_hidden_body_flags(HIDESHOES)) + var/obj/Overlays/O = obj_overlays[SHOES_LAYER] + O.icon = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi') + O.icon_state = shoes.icon_state + //var/image/standing = image("icon" = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi'), "icon_state" = "[shoes.icon_state]") + + var/obj/item/I = shoes + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.shoes_icons) + O.icon = species.shoes_icons + //standing.icon = species.shoes_icons + + O.overlays.len = 0 + if(shoes.dynamic_overlay) + if(shoes.dynamic_overlay["[SHOES_LAYER]"]) + var/image/dyn_overlay = shoes.dynamic_overlay["[SHOES_LAYER]"] + O.overlays += dyn_overlay + if(shoes.blood_DNA && shoes.blood_DNA.len) + var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "shoeblood") + bloodsies.color = shoes.blood_color + //standing.overlays += bloodsies + O.overlays += bloodsies + //overlays_standing[SHOES_LAYER] = standing + overlays += O + obj_overlays[SHOES_LAYER] = O + //else + //overlays_standing[SHOES_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_s_store(var/update_icons=1) + overlays -= obj_overlays[SUIT_STORE_LAYER] + if(s_store && !check_hidden_body_flags(HIDESUITSTORAGE)) + var/t_state = s_store.item_state + if(!t_state) t_state = s_store.icon_state + var/obj/Overlays/O = obj_overlays[SUIT_STORE_LAYER] + O.icon = 'icons/mob/belt_mirror.dmi' + O.icon_state = t_state + O.overlays.len = 0 + if(s_store.dynamic_overlay) + if(s_store.dynamic_overlay["[SUIT_STORE_LAYER]"]) + var/image/dyn_overlay = s_store.dynamic_overlay["[SUIT_STORE_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[SUIT_STORE_LAYER] = O + //overlays_standing[SUIT_STORE_LAYER] = image("icon" = 'icons/mob/belt_mirror.dmi', "icon_state" = "[t_state]") + s_store.screen_loc = ui_sstore1 //TODO + //else + //overlays_standing[SUIT_STORE_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_head(var/update_icons=1) + overlays -= obj_overlays[HEAD_LAYER] + if(head) + var/obj/Overlays/O = obj_overlays[HEAD_LAYER] + O.overlays.len = 0 + head.screen_loc = ui_head //TODO + var/image/standing + 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]") + + var/obj/item/I = head + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.head_icons) + standing.icon = species.head_icons + + if(head.dynamic_overlay) + if(head.dynamic_overlay["[HEAD_LAYER]"]) + var/image/dyn_overlay = head.dynamic_overlay["[HEAD_LAYER]"] + O.overlays += dyn_overlay + + if(head.blood_DNA && head.blood_DNA.len) + var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") + bloodsies.color = head.blood_color + //standing.overlays += bloodsies + O.overlays += bloodsies + O.icon = standing + O.icon_state = standing.icon_state + overlays += O + obj_overlays[HEAD_LAYER] = O + //overlays_standing[HEAD_LAYER] = standing + //else + //overlays_standing[HEAD_LAYER] = null + + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_belt(var/update_icons=1) + overlays -= obj_overlays[BELT_LAYER] + if(belt) + belt.screen_loc = ui_belt //TODO + var/t_state = belt.item_state + if(!t_state) t_state = belt.icon_state + var/image/standing = image("icon" = ((belt.icon_override) ? belt.icon_override : 'icons/mob/belt.dmi'), "icon_state" = "[t_state]") + + var/obj/item/I = belt + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.belt_icons) + standing.icon = species.belt_icons + var/obj/Overlays/O = obj_overlays[BELT_LAYER] + O.icon = standing + O.icon_state = standing.icon_state + O.overlays.len = 0 + if(belt.dynamic_overlay) + if(belt.dynamic_overlay["[BELT_LAYER]"]) + var/image/dyn_overlay = belt.dynamic_overlay["[BELT_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[BELT_LAYER] = O + //overlays_standing[BELT_LAYER] = standing + //else + //overlays_standing[BELT_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) + overlays -= obj_overlays[SUIT_LAYER] + if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) ) //TODO check this + wear_suit.screen_loc = ui_oclothing //TODO + var/obj/Overlays/O = obj_overlays[SUIT_LAYER] + O.overlays.len = 0 + var/image/standing = image("icon" = ((wear_suit.icon_override) ? wear_suit.icon_override : 'icons/mob/suit.dmi'), "icon_state" = "[wear_suit.icon_state]") + + if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) + drop_from_inventory(handcuffed) + drop_hands() + + var/obj/item/I = wear_suit + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.wear_suit_icons) + standing.icon = species.wear_suit_icons + + if(wear_suit.dynamic_overlay) + if(wear_suit.dynamic_overlay["[SUIT_LAYER]"]) + var/image/dyn_overlay = wear_suit.dynamic_overlay["[SUIT_LAYER]"] + O.overlays += dyn_overlay + + if(wear_suit.blood_DNA && wear_suit.blood_DNA.len) + var/obj/item/clothing/suit/S = wear_suit + var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[S.blood_overlay_type]blood") + bloodsies.color = wear_suit.blood_color + //standing.overlays += bloodsies + O.overlays += bloodsies + + O.icon = standing + O.icon_state = standing.icon_state + overlays += O + obj_overlays[SUIT_LAYER] = O + //overlays_standing[SUIT_LAYER] = standing + update_tail_showing(0) + else + //overlays_standing[SUIT_LAYER] = null + update_tail_showing(0) + + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_pockets(var/update_icons=1) + + if(l_store) l_store.screen_loc = ui_storage1 //TODO + if(r_store) r_store.screen_loc = ui_storage2 //TODO + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1) + overlays -= obj_overlays[FACEMASK_LAYER] + if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory) ) && !check_hidden_head_flags(HIDEMASK)) + var/obj/Overlays/O = obj_overlays[FACEMASK_LAYER] + O.overlays.len = 0 + 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/obj/item/I = wear_mask + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.wear_mask_icons) //This REQUIRES the species to be listed in species_fit and also to have an appropriate dmi allocated in their species datum + standing.icon = species.wear_mask_icons + + if(wear_mask.dynamic_overlay) + if(wear_mask.dynamic_overlay["[FACEMASK_LAYER]"]) + var/image/dyn_overlay = wear_mask.dynamic_overlay["[FACEMASK_LAYER]"] + O.overlays += dyn_overlay + + if( !istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA && wear_mask.blood_DNA.len ) + var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "maskblood") + bloodsies.color = wear_mask.blood_color + //standing.overlays += bloodsies + O.overlays += bloodsies + + O.icon = standing + O.icon_state = standing.icon_state + overlays += O + obj_overlays[FACEMASK_LAYER] = O + //overlays_standing[FACEMASK_LAYER] = standing + //else + //overlays_standing[FACEMASK_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_back(var/update_icons=1) + overlays -= obj_overlays[BACK_LAYER] + if(back) + back.screen_loc = ui_back //TODO + var/image/standing = image("icon" = ((back.icon_override) ? back.icon_override : 'icons/mob/back.dmi'), "icon_state" = "[back.icon_state]") + + var/obj/item/I = back + if(species.name in I.species_fit) //Allows clothes to display differently for multiple species + if(species.back_icons) + standing.icon = species.back_icons + + var/obj/Overlays/O = obj_overlays[BACK_LAYER] + O.icon = standing + O.icon_state = standing.icon_state + O.overlays.len = 0 + if(back.dynamic_overlay) + if(back.dynamic_overlay["[BACK_LAYER]"]) + var/image/dyn_overlay = back.dynamic_overlay["[BACK_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[BACK_LAYER] = O + + //overlays_standing[BACK_LAYER] = standing + //else + //overlays_standing[BACK_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_hud() //TODO: do away with this if possible + if(client) + client.screen |= contents + if(hud_used) + hud_used.hidden_inventory_update() //Updates the screenloc of the items on the 'other' inventory bar + + +/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) + overlays -= obj_overlays[HANDCUFF_LAYER] + if(handcuffed) + drop_hands() + stop_pulling() //TODO: should be handled elsewhere + var/obj/Overlays/O = obj_overlays[HANDCUFF_LAYER] + O.icon = 'icons/mob/mob.dmi' + O.icon_state = "handcuff1" + overlays += O + obj_overlays[HANDCUFF_LAYER] = O + //overlays_standing[HANDCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "handcuff1") + //else + //overlays_standing[HANDCUFF_LAYER] = null + + if(update_icons) update_icons() + +/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) + overlays -= obj_overlays[LEGCUFF_LAYER] + if(legcuffed) + var/obj/Overlays/O = obj_overlays[LEGCUFF_LAYER] + O.icon = 'icons/mob/mob.dmi' + O.icon_state = "legcuff1" + overlays += O + obj_overlays[LEGCUFF_LAYER] = O + //overlays_standing[LEGCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1") + if(src.m_intent != "walk") + src.m_intent = "walk" + if(src.hud_used && src.hud_used.move_intent) + src.hud_used.move_intent.icon_state = "walking" + + //elsek + //overlays_standing[LEGCUFF_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) + overlays -= obj_overlays[R_HAND_LAYER] + if(r_hand) + r_hand.screen_loc = ui_rhand //TODO + var/t_state = r_hand.item_state + var/t_inhand_state = r_hand.inhand_states["right_hand"] + var/icon/check_dimensions = new(t_inhand_state) + if(!t_state) t_state = r_hand.icon_state + var/obj/Overlays/O = obj_overlays[R_HAND_LAYER] + O.icon = t_inhand_state + O.icon_state = t_state + O.pixel_x = -1*(check_dimensions.Width() - 32)/2 + O.pixel_y = -1*(check_dimensions.Height() - 32)/2 + O.overlays.len = 0 + if(r_hand.dynamic_overlay) + if(r_hand.dynamic_overlay["[R_HAND_LAYER]"]) + var/image/dyn_overlay = r_hand.dynamic_overlay["[R_HAND_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[R_HAND_LAYER] = O + //overlays_standing[R_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = "[t_state]") + if (handcuffed) + drop_item(r_hand) + //else + //overlays_standing[R_HAND_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) + overlays -= obj_overlays[L_HAND_LAYER] + if(l_hand) + l_hand.screen_loc = ui_lhand //TODO + var/t_state = l_hand.item_state + var/icon/t_inhand_state = l_hand.inhand_states["left_hand"] + var/icon/check_dimensions = new(t_inhand_state) + if(!t_state) t_state = l_hand.icon_state + var/obj/Overlays/O = obj_overlays[L_HAND_LAYER] + O.icon = t_inhand_state + O.icon_state = t_state + O.pixel_x = -1*(check_dimensions.Width() - 32)/2 + O.pixel_y = -1*(check_dimensions.Height() - 32)/2 + O.overlays.len = 0 + if(l_hand.dynamic_overlay) + if(l_hand.dynamic_overlay["[L_HAND_LAYER]"]) + var/image/dyn_overlay = l_hand.dynamic_overlay["[L_HAND_LAYER]"] + O.overlays += dyn_overlay + overlays += O + obj_overlays[L_HAND_LAYER] = O + //overlays_standing[L_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = "[t_state]") + if (handcuffed) + drop_item(l_hand) + //else + //overlays_standing[L_HAND_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/human/proc/update_tail_showing(var/update_icons=1) + //overlays_standing[TAIL_LAYER] = null + overlays -= obj_overlays[TAIL_LAYER] + if(species.tail && species.flags & HAS_TAIL) + if(!wear_suit || !(wear_suit.flags_inv & HIDEJUMPSUIT) && !istype(wear_suit, /obj/item/clothing/suit/space)) + var/obj/Overlays/O = obj_overlays[TAIL_LAYER] + O.icon = 'icons/effects/species.dmi' + O.icon_state = "[species.tail]_s" + overlays += O + obj_overlays[TAIL_LAYER] = O + //if(!old_tail_state) //only update if we didnt show our tail already + + //overlays_standing[TAIL_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") +// to_chat(src, "update: tail is different") + //else + //overlays_standing[TAIL_LAYER] = null + + if(update_icons) + update_icons() + +// Used mostly for creating head items +/mob/living/carbon/human/proc/generate_head_icon() +//gender no longer matters for the mouth, although there should probably be seperate base head icons. +// var/g = "m" +// if (gender == FEMALE) g = "f" + + //base icons + var/icon/face_lying = new /icon('icons/mob/human_face.dmi',"bald_l") + + if(f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(facial_hair_style) + var/icon/facial_l = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_l") + facial_l.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + face_lying.Blend(facial_l, ICON_OVERLAY) + + if(h_style) + var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(hair_style) + var/icon/hair_l = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_l") + hair_l.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + face_lying.Blend(hair_l, ICON_OVERLAY) + + //Eyes + // Note: These used to be in update_face(), and the fact they're here will make it difficult to create a disembodied head + var/icon/eyes_l = new/icon('icons/mob/human_face.dmi', "eyes_l") + eyes_l.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) + face_lying.Blend(eyes_l, ICON_OVERLAY) + + if(lip_style) + face_lying.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_l"), ICON_OVERLAY) + + var/image/face_lying_image = new /image(icon = face_lying) + return face_lying_image + +//lower cost way of updating the necessary human icons on equip and unequip +/mob/living/carbon/human/proc/update_hidden_item_icons(var/obj/item/W) + if(!W) + return + + if(W.flags_inv & HIDEHAIR) + update_hair() + if(W.flags_inv & (HIDEGLOVES | HIDEMASK)) + update_inv_wear_mask() + update_inv_gloves() + if(W.flags_inv & HIDESHOES) + update_inv_shoes() + if(W.flags_inv & (HIDEJUMPSUIT | HIDEEYES)) + update_inv_w_uniform() + update_inv_glasses() + if(W.flags_inv & (HIDESUITSTORAGE | HIDEEARS)) + update_inv_s_store() + update_inv_ears() diff --git a/code/modules/mob/living/carbon/human/whisper.dm b/code/modules/mob/living/carbon/human/whisper.dm index 65079ec7243..5cdd4468bbe 100644 --- a/code/modules/mob/living/carbon/human/whisper.dm +++ b/code/modules/mob/living/carbon/human/whisper.dm @@ -1,102 +1,102 @@ -/mob/living/carbon/human/whisper(message as text) - if(!IsVocal()) - return -#ifdef SAY_DEBUG - var/oldmsg = message -#endif - if(say_disabled) //This is here to try to identify lag problems - to_chat(usr, "Speech is currently admin-disabled.") - return - - if(isDead()) - return - - var/datum/speech/speech = create_speech(message) - speech.language = parse_language(speech.message) - speech.mode = SPEECH_MODE_WHISPER - speech.message_classes.Add("whisper") - - if(istype(speech.language)) - speech.message = copytext(speech.message,2+length(speech.language.key)) - else - if(!isnull(speech.language)) - //var/oldmsg = message - var/n = speech.language - speech.message = copytext(speech.message,1+length(n)) - say_testing(src, "We tried to speak a language we don't have length = [length(n)], oldmsg = [oldmsg] parsed message = [speech.message]") - speech.language = null - speech.language = get_default_language() - - speech.message = trim(speech.message) - if(!can_speak(message)) - return - - speech.message = "[message]" - - if (src.client) - if (src.client.prefs.muted & MUTE_IC) - to_chat(src, "You cannot whisper (muted).") - return - - //var/alt_name = get_alt_name() - - var/whispers = "whispers" - var/critical = InCritical() - - // We are unconscious but not in critical, so don't allow them to whisper. - if(stat == UNCONSCIOUS && (!critical || said_last_words)) - return - - log_whisper("[key_name(src)] ([formatLocation(src)]): [message]") - - // If whispering your last words, limit the whisper based on how close you are to death. - if(critical && !said_last_words) - var/health_diff = round(-config.health_threshold_dead + health) - // If we cut our message short, abruptly end it with a-.. - var/message_len = length(speech.message) - speech.message = copytext(speech.message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]" - speech.message = Ellipsis(speech.message, 10, 1) - speech.mode= SPEECH_MODE_FINAL - whispers = "whispers with their final breath" - said_last_words = src.stat - treat_speech(speech) - - var/listeners = get_hearers_in_view(1, src) | observers - - var/eavesdroppers = get_hearers_in_view(2, src) - listeners - - var/watchers = hearers(5, src) - listeners - eavesdroppers - - - //"[GetVoice()] (as [alt_name]) [whispers], \"[message]\"" - var/rendered = render_speech(speech) - - for (var/atom/movable/listener in listeners) - if (listener) - listener.Hear(speech, rendered) - - listeners = null - - speech.message = stars(speech.message) - - //rendered = "[GetVoice()] (as [alt_name]) [whispers], \"[message]\"" - rendered = render_speech(speech) - - for (var/atom/movable/eavesdropper in eavesdroppers) - if (eavesdropper) - eavesdropper.Hear(speech, rendered) - - eavesdroppers = null - - rendered = "[src.name] [whispers] something." - - for (var/mob/watcher in watchers) - if (watcher) - watcher.show_message(rendered, 2) - - watchers = null - - if (said_last_words) // dying words - succumb(1) - - returnToPool(speech) +/mob/living/carbon/human/whisper(message as text) + if(!IsVocal()) + return +#ifdef SAY_DEBUG + var/oldmsg = message +#endif + if(say_disabled) //This is here to try to identify lag problems + to_chat(usr, "Speech is currently admin-disabled.") + return + + if(isDead()) + return + + var/datum/speech/speech = create_speech(message) + speech.language = parse_language(speech.message) + speech.mode = SPEECH_MODE_WHISPER + speech.message_classes.Add("whisper") + + if(istype(speech.language)) + speech.message = copytext(speech.message,2+length(speech.language.key)) + else + if(!isnull(speech.language)) + //var/oldmsg = message + var/n = speech.language + speech.message = copytext(speech.message,1+length(n)) + say_testing(src, "We tried to speak a language we don't have length = [length(n)], oldmsg = [oldmsg] parsed message = [speech.message]") + speech.language = null + speech.language = get_default_language() + + speech.message = trim(speech.message) + if(!can_speak(message)) + return + + speech.message = "[message]" + + if (src.client) + if (src.client.prefs.muted & MUTE_IC) + to_chat(src, "You cannot whisper (muted).") + return + + //var/alt_name = get_alt_name() + + var/whispers = "whispers" + var/critical = InCritical() + + // We are unconscious but not in critical, so don't allow them to whisper. + if(stat == UNCONSCIOUS && (!critical || said_last_words)) + return + + log_whisper("[key_name(src)] ([formatLocation(src)]): [message]") + + // If whispering your last words, limit the whisper based on how close you are to death. + if(critical && !said_last_words) + var/health_diff = round(-config.health_threshold_dead + health) + // If we cut our message short, abruptly end it with a-.. + var/message_len = length(speech.message) + speech.message = copytext(speech.message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]" + speech.message = Ellipsis(speech.message, 10, 1) + speech.mode= SPEECH_MODE_FINAL + whispers = "whispers with their final breath" + said_last_words = src.stat + treat_speech(speech) + + var/listeners = get_hearers_in_view(1, src) | observers + + var/eavesdroppers = get_hearers_in_view(2, src) - listeners + + var/watchers = hearers(5, src) - listeners - eavesdroppers + + + //"[GetVoice()] (as [alt_name]) [whispers], \"[message]\"" + var/rendered = render_speech(speech) + + for (var/atom/movable/listener in listeners) + if (listener) + listener.Hear(speech, rendered) + + listeners = null + + speech.message = stars(speech.message) + + //rendered = "[GetVoice()] (as [alt_name]) [whispers], \"[message]\"" + rendered = render_speech(speech) + + for (var/atom/movable/eavesdropper in eavesdroppers) + if (eavesdropper) + eavesdropper.Hear(speech, rendered) + + eavesdroppers = null + + rendered = "[src.name] [whispers] something." + + for (var/mob/watcher in watchers) + if (watcher) + watcher.show_message(rendered, 2) + + watchers = null + + if (said_last_words) // dying words + succumb(1) + + returnToPool(speech) diff --git a/code/modules/mob/living/carbon/monkey/death.dm b/code/modules/mob/living/carbon/monkey/death.dm index 1eaf172ee70..68b482b2a82 100644 --- a/code/modules/mob/living/carbon/monkey/death.dm +++ b/code/modules/mob/living/carbon/monkey/death.dm @@ -1,42 +1,42 @@ -/mob/living/carbon/monkey/gib() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-m", sleeptime = 15) - gibs(loc, viruses, dna) - - qdel(src) - -/mob/living/carbon/monkey/dust() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - dropBorers(1) - - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-m", sleeptime = 15) - new /obj/effect/decal/cleanable/ash(loc) - - qdel(src) - - -/mob/living/carbon/monkey/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health5" - stat = DEAD - - if(!gibbed) - for(var/mob/O in viewers(src, null)) - O.show_message("The [name] lets out a faint chimper as it collapses and stops moving...", 1) //ded -- Urist - - update_canmove() - if(blind) blind.layer = 0 - - ticker.mode.check_win() - +/mob/living/carbon/monkey/gib() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-m", sleeptime = 15) + gibs(loc, viruses, dna) + + qdel(src) + +/mob/living/carbon/monkey/dust() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + dropBorers(1) + + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-m", sleeptime = 15) + new /obj/effect/decal/cleanable/ash(loc) + + qdel(src) + + +/mob/living/carbon/monkey/death(gibbed) + if(stat == DEAD) return + if(healths) healths.icon_state = "health5" + stat = DEAD + + if(!gibbed) + for(var/mob/O in viewers(src, null)) + O.show_message("The [name] lets out a faint chimper as it collapses and stops moving...", 1) //ded -- Urist + + update_canmove() + if(blind) blind.layer = 0 + + ticker.mode.check_win() + return ..(gibbed) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/emote.dm b/code/modules/mob/living/carbon/monkey/emote.dm index 5adddf119c4..58601da3b44 100644 --- a/code/modules/mob/living/carbon/monkey/emote.dm +++ b/code/modules/mob/living/carbon/monkey/emote.dm @@ -1,150 +1,150 @@ -/mob/living/carbon/monkey/emote(var/act,var/m_type=1,var/message = null) - if(timestopped) return //under effects of time magick - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - - switch(act) - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) +/mob/living/carbon/monkey/emote(var/act,var/m_type=1,var/message = null) + if(timestopped) return //under effects of time magick + var/param = null + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + + var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) + + switch(act) + if ("me") + if(silent) + return + if (src.client) + if (client.prefs.muted & MUTE_IC) to_chat(src, "You cannot send IC messages (muted).") - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - - if ("custom") - return custom_emote(m_type, message) - - if ("airguitar") - if (!src.restrained()) - message = "\The [src] is strumming the air and headbanging like a safari chimp." - m_type = VISIBLE - - if ("blink_r") - message = "\The [src] blinks rapidly." - m_type = VISIBLE - - if("sign") - if (!src.restrained()) - message = text("\The [src.name] signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = VISIBLE - if("scratch") - if (!src.restrained()) - message = "\The [src.name] scratches." - m_type = VISIBLE - if("whimper") - if (!muzzled) - message = "\The [src.name] whimpers." - m_type = HEARABLE - if("roar") - if (!muzzled) - message = "\The [src.name] roars." - m_type = HEARABLE - if("tail") - message = "\The [src.name] waves his tail." - m_type = VISIBLE - if("gasp") - message = "\The [src.name] gasps." - m_type = HEARABLE - if("shiver") - message = "\The [src.name] shivers." - m_type = HEARABLE - if("drool") - message = "\The [src.name] drools." - m_type = VISIBLE - if("paw") - if (!src.restrained()) - message = "\The [src.name] flails his paw." - m_type = VISIBLE - if("scretch") - if (!muzzled) - message = "\The [src.name] scretches." - m_type = HEARABLE - if("choke") - message = "\The [src.name] chokes." - m_type = HEARABLE - if("moan") - message = "\The [src.name] moans!" - m_type = HEARABLE - if("nod") - message = "\The [src.name] nods his head." - m_type = VISIBLE - if("sit") - message = "\The [src.name] sits down." - m_type = VISIBLE - if("sway") - message = "\The [src.name] sways around dizzily." - m_type = VISIBLE - if("sulk") - message = "\The [src.name] sulks down sadly." - m_type = VISIBLE - if("twitch") - message = "\The [src.name] twitches violently." - m_type = VISIBLE - if("dance") - if (!src.restrained()) - message = "\The [src.name] dances around happily." - m_type = VISIBLE - if("roll") - if (!src.restrained()) - message = "\The [src.name] rolls." - m_type = VISIBLE - if("shake") - message = "\The [src.name] shakes his head." - m_type = VISIBLE - if("gnarl") - if (!muzzled) - message = "\The [src.name] gnarls and shows his teeth.." - m_type = HEARABLE - if("jump") - message = "\The [src.name] jumps!" - m_type = VISIBLE - if ("spin") - message = "\The [src] spins out of control!" - m_type = VISIBLE - if("collapse") - Paralyse(2) - message = text("\The [] collapses!", src) - m_type = HEARABLE - if("deathgasp") - message = "\The [src.name] lets out a faint chimper as it collapses and stops moving..." - m_type = VISIBLE - - if ("cough") - if (!muzzled) - message = "[src] coughs!" - else - message = "[src] makes a strong noise." - m_type = HEARABLE - if("help") + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + if (stat) + return + if(!(message)) + return + return custom_emote(m_type, message) + + + if ("custom") + return custom_emote(m_type, message) + + if ("airguitar") + if (!src.restrained()) + message = "\The [src] is strumming the air and headbanging like a safari chimp." + m_type = VISIBLE + + if ("blink_r") + message = "\The [src] blinks rapidly." + m_type = VISIBLE + + if("sign") + if (!src.restrained()) + message = text("\The [src.name] signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) + m_type = VISIBLE + if("scratch") + if (!src.restrained()) + message = "\The [src.name] scratches." + m_type = VISIBLE + if("whimper") + if (!muzzled) + message = "\The [src.name] whimpers." + m_type = HEARABLE + if("roar") + if (!muzzled) + message = "\The [src.name] roars." + m_type = HEARABLE + if("tail") + message = "\The [src.name] waves his tail." + m_type = VISIBLE + if("gasp") + message = "\The [src.name] gasps." + m_type = HEARABLE + if("shiver") + message = "\The [src.name] shivers." + m_type = HEARABLE + if("drool") + message = "\The [src.name] drools." + m_type = VISIBLE + if("paw") + if (!src.restrained()) + message = "\The [src.name] flails his paw." + m_type = VISIBLE + if("scretch") + if (!muzzled) + message = "\The [src.name] scretches." + m_type = HEARABLE + if("choke") + message = "\The [src.name] chokes." + m_type = HEARABLE + if("moan") + message = "\The [src.name] moans!" + m_type = HEARABLE + if("nod") + message = "\The [src.name] nods his head." + m_type = VISIBLE + if("sit") + message = "\The [src.name] sits down." + m_type = VISIBLE + if("sway") + message = "\The [src.name] sways around dizzily." + m_type = VISIBLE + if("sulk") + message = "\The [src.name] sulks down sadly." + m_type = VISIBLE + if("twitch") + message = "\The [src.name] twitches violently." + m_type = VISIBLE + if("dance") + if (!src.restrained()) + message = "\The [src.name] dances around happily." + m_type = VISIBLE + if("roll") + if (!src.restrained()) + message = "\The [src.name] rolls." + m_type = VISIBLE + if("shake") + message = "\The [src.name] shakes his head." + m_type = VISIBLE + if("gnarl") + if (!muzzled) + message = "\The [src.name] gnarls and shows his teeth.." + m_type = HEARABLE + if("jump") + message = "\The [src.name] jumps!" + m_type = VISIBLE + if ("spin") + message = "\The [src] spins out of control!" + m_type = VISIBLE + if("collapse") + Paralyse(2) + message = text("\The [] collapses!", src) + m_type = HEARABLE + if("deathgasp") + message = "\The [src.name] lets out a faint chimper as it collapses and stops moving..." + m_type = VISIBLE + + if ("cough") + if (!muzzled) + message = "[src] coughs!" + else + message = "[src] makes a strong noise." + m_type = HEARABLE + if("help") to_chat(src, "choke, collapse, cough, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper") - else + else // to_chat(custom_emote(VISIBLE, act) src, text("Invalid Emote: []", act)) - if ((message && src.stat == 0)) - if(src.client) - log_emote("[name]/[key] (@[x],[y],[z]): [message]") - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - //Foreach goto(703) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) - //Foreach goto(746) + if ((message && src.stat == 0)) + if(src.client) + log_emote("[name]/[key] (@[x],[y],[z]): [message]") + if (m_type & 1) + for(var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + //Foreach goto(703) + else + for(var/mob/O in hearers(src, null)) + O.show_message(message, m_type) + //Foreach goto(746) return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/examine.dm b/code/modules/mob/living/carbon/monkey/examine.dm index 9f4448afaa2..f86e889d196 100644 --- a/code/modules/mob/living/carbon/monkey/examine.dm +++ b/code/modules/mob/living/carbon/monkey/examine.dm @@ -1,46 +1,46 @@ -/mob/living/carbon/monkey/examine(mob/user) - - var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" - - if (src.handcuffed) - msg += "It is \icon[src.handcuffed] handcuffed!\n" - if (src.wear_mask) - msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its head.\n" - if (src.l_hand) - msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n" - if (src.r_hand) - msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n" - if (src.back) - msg += "It has \icon[src.back] \a [src.back] on its back.\n" - if (isDead()) - msg += "It is limp and unresponsive, with no signs of life.\n" - else - msg += "" - if (src.getBruteLoss()) - if (src.getBruteLoss() < 30) - msg += "It has minor bruising.\n" - else - msg += "It has severe bruising!\n" - if (src.getFireLoss()) - if (src.getFireLoss() < 30) - msg += "It has minor burns.\n" - else - msg += "It has severe burns!\n" - if (src.stat == UNCONSCIOUS) - msg += "It isn't responding to anything around it; it seems to be asleep.\n" - msg += "" - - if (src.digitalcamo) - msg += "It is repulsively uncanny!\n" - - var/butchery = "" //More information about butchering status, check out "code/datums/helper_datums/butchering.dm" - if(butchering_drops && butchering_drops.len) - for(var/datum/butchering_product/B in butchering_drops) - butchery = "[butchery][B.desc_modifier(src)]" - if(butchery) - msg += "[butchery]" - - msg += "*---------*" - - - to_chat(user, msg) +/mob/living/carbon/monkey/examine(mob/user) + + var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" + + if (src.handcuffed) + msg += "It is \icon[src.handcuffed] handcuffed!\n" + if (src.wear_mask) + msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its head.\n" + if (src.l_hand) + msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n" + if (src.r_hand) + msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n" + if (src.back) + msg += "It has \icon[src.back] \a [src.back] on its back.\n" + if (isDead()) + msg += "It is limp and unresponsive, with no signs of life.\n" + else + msg += "" + if (src.getBruteLoss()) + if (src.getBruteLoss() < 30) + msg += "It has minor bruising.\n" + else + msg += "It has severe bruising!\n" + if (src.getFireLoss()) + if (src.getFireLoss() < 30) + msg += "It has minor burns.\n" + else + msg += "It has severe burns!\n" + if (src.stat == UNCONSCIOUS) + msg += "It isn't responding to anything around it; it seems to be asleep.\n" + msg += "" + + if (src.digitalcamo) + msg += "It is repulsively uncanny!\n" + + var/butchery = "" //More information about butchering status, check out "code/datums/helper_datums/butchering.dm" + if(butchering_drops && butchering_drops.len) + for(var/datum/butchering_product/B in butchering_drops) + butchery = "[butchery][B.desc_modifier(src)]" + if(butchery) + msg += "[butchery]" + + msg += "*---------*" + + + to_chat(user, msg) diff --git a/code/modules/mob/living/carbon/monkey/inventory.dm b/code/modules/mob/living/carbon/monkey/inventory.dm index 1629640b34e..5ec04845365 100644 --- a/code/modules/mob/living/carbon/monkey/inventory.dm +++ b/code/modules/mob/living/carbon/monkey/inventory.dm @@ -1,236 +1,236 @@ -/obj/effect/equip_e/monkey/process() - if (item) - item.add_fingerprint(source) - if (!( item )) - switch(place) - if("head") - if (!( target.wear_mask )) - qdel(src) - return - if("l_hand") - if (!( target.l_hand )) - qdel(src) - return - if("r_hand") - if (!( target.r_hand )) - qdel(src) - return - if("back") - if (!( target.back )) - qdel(src) - return - if("handcuff") - if (!( target.handcuffed )) - qdel(src) - return - if("internal") - if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.back, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) - qdel(src) - return - - if (item) - if(isrobot(source) && place != "handcuff") - var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel") - if(!(L.Find(place))) - qdel(src) - return - for(var/mob/O in viewers(target, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] is trying to put a [] on []", source, item, target), 1) - else - var/message = null - switch(place) - if("mask") - if(istype(target.wear_mask, /obj/item/clothing)&&!target.wear_mask:canremove) - message = text("[] fails to take off \a [] from []'s body!", source, target.wear_mask, target) - else - message = text("[] is trying to take off \a [] from []'s head!", source, target.wear_mask, target) - if("l_hand") - message = text("[] is trying to take off a [] from []'s left hand!", source, target.l_hand, target) - if("r_hand") - message = text("[] is trying to take off a [] from []'s right hand!", source, target.r_hand, target) - if("back") - message = text("[] is trying to take off a [] from []'s back!", source, target.back, target) - if("handcuff") - message = text("[] is trying to unhandcuff []!", source, target) - if("internal") - if (target.internal) - message = text("[] is trying to remove []'s internals", source, target) - else - message = text("[] is trying to set on []'s internals.", source, target) - else - for(var/mob/M in viewers(target, null)) - M.show_message(message, 1) - spawn( 30 ) - done() - return - return - -/obj/effect/equip_e/monkey/done() - if(!source || !target) return - if(source.loc != s_loc) return - if(target.loc != t_loc) return - if(!source.Adjacent(target)) return - if(item && source.get_active_hand() != item) return - if ((source.restrained() || source.stat)) return - switch(place) - if("mask") - if (target.wear_mask) - if(istype(target.wear_mask, /obj/item/clothing)&& !target.wear_mask:canremove) - return - var/obj/item/W = target.wear_mask - target.u_equip(W,1) - if (target.client) - target.client.screen -= W - if (W) - W.loc = target.loc - //W.dropped(target) - W.layer = initial(W.layer) - W.add_fingerprint(source) - else - if (istype(item, /obj/item/clothing/mask)) - source.drop_item(item, force_drop = 1) - loc = target - item.layer = 20 - target.wear_mask = item - item.loc = target - if("l_hand") - if (target.l_hand) - var/obj/item/W = target.l_hand - target.u_equip(W,1) - if (target.client) - target.client.screen -= W - if (W) - W.loc = target.loc - W.layer = initial(W.layer) - //W.dropped(target) - W.add_fingerprint(source) - else - if (istype(item, /obj/item)) - source.drop_item(item, force_drop = 1) - loc = target - item.layer = 20 - target.l_hand = item - item.loc = target - item.dropped(source) - item.equipped(target,target.l_hand) - if("r_hand") - if (target.r_hand) - var/obj/item/W = target.r_hand - target.u_equip(W,1) - if (target.client) - target.client.screen -= W - if (W) - W.loc = target.loc - W.layer = initial(W.layer) - //W.dropped(target) - W.add_fingerprint(source) - else - if (istype(item, /obj/item)) - source.drop_item(item, force_drop = 1) - loc = target - item.layer = 20 - target.r_hand = item - item.loc = target - item.dropped(source) - item.equipped(target,target.r_hand) - if("back") - if (target.back) - var/obj/item/W = target.back - target.u_equip(W,1) - if (target.client) - target.client.screen -= W - if (W) - W.loc = target.loc - //W.dropped(target) - W.layer = initial(W.layer) - W.add_fingerprint(source) - else - if ((istype(item, /obj/item) && item.slot_flags & SLOT_BACK )) - source.drop_item(item, force_drop = 1) - loc = target - item.layer = 20 - target.back = item - item.loc = target - if("handcuff") - if (target.handcuffed) - var/obj/item/W = target.handcuffed - target.u_equip(W,1) - if (target.client) - target.client.screen -= W - if (W) - W.loc = target.loc - //W.dropped(target) - W.layer = initial(W.layer) - W.add_fingerprint(source) - else - if (istype(item, /obj/item/weapon/handcuffs)) - source.drop_item(item, force_drop = 1) - target.handcuffed = item - item.loc = target - if("internal") - if (target.internal) - target.internal.add_fingerprint(source) - target.internal = null - else - if (target.internal) - target.internal = null - if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) - return - else - if (istype(target.back, /obj/item/weapon/tank)) - target.internal = target.back - target.internal.add_fingerprint(source) - for(var/mob/M in viewers(target, 1)) - if ((M.client && !( M.blinded ))) - M.show_message(text("[] is now running on internals.", target), 1) - else - source.regenerate_icons() - target.regenerate_icons() - qdel(src) - return - - - -//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() -//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. -/mob/living/carbon/monkey/equip_to_slot(obj/item/W as obj, slot, redraw_mob = 1) - if(!slot) return - if(!istype(W)) return - - if(W == get_active_hand()) - u_equip(W,0) - - switch(slot) - if(slot_back) - src.back = W - W.equipped(src, slot) - update_inv_back(redraw_mob) - if(slot_wear_mask) - src.wear_mask = W - W.equipped(src, slot) - update_inv_wear_mask(redraw_mob) - if(slot_handcuffed) - src.handcuffed = W - update_inv_handcuffed(redraw_mob) - if(slot_legcuffed) - src.legcuffed = W - W.equipped(src, slot) - update_inv_legcuffed(redraw_mob) - if(slot_l_hand) - src.l_hand = W - W.equipped(src, slot) - update_inv_l_hand(redraw_mob) - if(slot_r_hand) - src.r_hand = W - W.equipped(src, slot) - update_inv_r_hand(redraw_mob) - if(slot_in_backpack) - W.loc = src.back - else +/obj/effect/equip_e/monkey/process() + if (item) + item.add_fingerprint(source) + if (!( item )) + switch(place) + if("head") + if (!( target.wear_mask )) + qdel(src) + return + if("l_hand") + if (!( target.l_hand )) + qdel(src) + return + if("r_hand") + if (!( target.r_hand )) + qdel(src) + return + if("back") + if (!( target.back )) + qdel(src) + return + if("handcuff") + if (!( target.handcuffed )) + qdel(src) + return + if("internal") + if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.back, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) + qdel(src) + return + + if (item) + if(isrobot(source) && place != "handcuff") + var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel") + if(!(L.Find(place))) + qdel(src) + return + for(var/mob/O in viewers(target, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] is trying to put a [] on []", source, item, target), 1) + else + var/message = null + switch(place) + if("mask") + if(istype(target.wear_mask, /obj/item/clothing)&&!target.wear_mask:canremove) + message = text("[] fails to take off \a [] from []'s body!", source, target.wear_mask, target) + else + message = text("[] is trying to take off \a [] from []'s head!", source, target.wear_mask, target) + if("l_hand") + message = text("[] is trying to take off a [] from []'s left hand!", source, target.l_hand, target) + if("r_hand") + message = text("[] is trying to take off a [] from []'s right hand!", source, target.r_hand, target) + if("back") + message = text("[] is trying to take off a [] from []'s back!", source, target.back, target) + if("handcuff") + message = text("[] is trying to unhandcuff []!", source, target) + if("internal") + if (target.internal) + message = text("[] is trying to remove []'s internals", source, target) + else + message = text("[] is trying to set on []'s internals.", source, target) + else + for(var/mob/M in viewers(target, null)) + M.show_message(message, 1) + spawn( 30 ) + done() + return + return + +/obj/effect/equip_e/monkey/done() + if(!source || !target) return + if(source.loc != s_loc) return + if(target.loc != t_loc) return + if(!source.Adjacent(target)) return + if(item && source.get_active_hand() != item) return + if ((source.restrained() || source.stat)) return + switch(place) + if("mask") + if (target.wear_mask) + if(istype(target.wear_mask, /obj/item/clothing)&& !target.wear_mask:canremove) + return + var/obj/item/W = target.wear_mask + target.u_equip(W,1) + if (target.client) + target.client.screen -= W + if (W) + W.loc = target.loc + //W.dropped(target) + W.layer = initial(W.layer) + W.add_fingerprint(source) + else + if (istype(item, /obj/item/clothing/mask)) + source.drop_item(item, force_drop = 1) + loc = target + item.layer = 20 + target.wear_mask = item + item.loc = target + if("l_hand") + if (target.l_hand) + var/obj/item/W = target.l_hand + target.u_equip(W,1) + if (target.client) + target.client.screen -= W + if (W) + W.loc = target.loc + W.layer = initial(W.layer) + //W.dropped(target) + W.add_fingerprint(source) + else + if (istype(item, /obj/item)) + source.drop_item(item, force_drop = 1) + loc = target + item.layer = 20 + target.l_hand = item + item.loc = target + item.dropped(source) + item.equipped(target,target.l_hand) + if("r_hand") + if (target.r_hand) + var/obj/item/W = target.r_hand + target.u_equip(W,1) + if (target.client) + target.client.screen -= W + if (W) + W.loc = target.loc + W.layer = initial(W.layer) + //W.dropped(target) + W.add_fingerprint(source) + else + if (istype(item, /obj/item)) + source.drop_item(item, force_drop = 1) + loc = target + item.layer = 20 + target.r_hand = item + item.loc = target + item.dropped(source) + item.equipped(target,target.r_hand) + if("back") + if (target.back) + var/obj/item/W = target.back + target.u_equip(W,1) + if (target.client) + target.client.screen -= W + if (W) + W.loc = target.loc + //W.dropped(target) + W.layer = initial(W.layer) + W.add_fingerprint(source) + else + if ((istype(item, /obj/item) && item.slot_flags & SLOT_BACK )) + source.drop_item(item, force_drop = 1) + loc = target + item.layer = 20 + target.back = item + item.loc = target + if("handcuff") + if (target.handcuffed) + var/obj/item/W = target.handcuffed + target.u_equip(W,1) + if (target.client) + target.client.screen -= W + if (W) + W.loc = target.loc + //W.dropped(target) + W.layer = initial(W.layer) + W.add_fingerprint(source) + else + if (istype(item, /obj/item/weapon/handcuffs)) + source.drop_item(item, force_drop = 1) + target.handcuffed = item + item.loc = target + if("internal") + if (target.internal) + target.internal.add_fingerprint(source) + target.internal = null + else + if (target.internal) + target.internal = null + if (!( istype(target.wear_mask, /obj/item/clothing/mask) )) + return + else + if (istype(target.back, /obj/item/weapon/tank)) + target.internal = target.back + target.internal.add_fingerprint(source) + for(var/mob/M in viewers(target, 1)) + if ((M.client && !( M.blinded ))) + M.show_message(text("[] is now running on internals.", target), 1) + else + source.regenerate_icons() + target.regenerate_icons() + qdel(src) + return + + + +//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() +//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. +/mob/living/carbon/monkey/equip_to_slot(obj/item/W as obj, slot, redraw_mob = 1) + if(!slot) return + if(!istype(W)) return + + if(W == get_active_hand()) + u_equip(W,0) + + switch(slot) + if(slot_back) + src.back = W + W.equipped(src, slot) + update_inv_back(redraw_mob) + if(slot_wear_mask) + src.wear_mask = W + W.equipped(src, slot) + update_inv_wear_mask(redraw_mob) + if(slot_handcuffed) + src.handcuffed = W + update_inv_handcuffed(redraw_mob) + if(slot_legcuffed) + src.legcuffed = W + W.equipped(src, slot) + update_inv_legcuffed(redraw_mob) + if(slot_l_hand) + src.l_hand = W + W.equipped(src, slot) + update_inv_l_hand(redraw_mob) + if(slot_r_hand) + src.r_hand = W + W.equipped(src, slot) + update_inv_r_hand(redraw_mob) + if(slot_in_backpack) + W.loc = src.back + else to_chat(usr, "You are trying to eqip this item to an unsupported inventory slot. How the heck did you manage that? Stop it...") - return - - W.layer = 20 - + return + + W.layer = 20 + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 5d6640638e4..3a49a9cb8f6 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -1,720 +1,720 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/mob/living/carbon/monkey - var/oxygen_alert = 0 - var/toxins_alert = 0 - var/fire_alert = 0 - var/pressure_alert = 0 - - var/temperature_alert = 0 - - -/mob/living/carbon/monkey/Life() - set invisibility = 0 - //set background = 1 - if(timestopped) return 0 //under effects of time magick - - if (monkeyizing) return - if (update_muts) - update_muts=0 - domutcheck(src,null,MUTCHK_FORCED) - ..() - - var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE - if(loc) - environment = loc.return_air() - - if (stat != DEAD) //still breathing - //Is not a Diona Nymph - Snowflake Code - if(!istype(src,/mob/living/carbon/monkey/diona)) - //First, resolve location and get a breath - if(air_master.current_cycle%4==2) - //Only try to take a breath every 4 seconds, unless suffocating - breathe() - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - - //Updates the number of stored chemicals for powers - handle_changeling() - - //Mutations and radiation - handle_mutations_and_radiation() - - //Chemicals in the body - handle_chemicals_in_body() - - //Disabilities - handle_disabilities() - - //Virus updates, duh - handle_virus_updates() - - //Apparently, the person who wrote this code designed it so that - //blinded get reset each cycle and then get activated later in the - //code. Very ugly. I dont care. Moving this stuff here so its easy - //to find it. - blinded = null - - //Handle temperature/pressure differences between body and environment - if(environment) // More error checking -- TLE - handle_environment(environment) - - //Check if we're on fire - handle_fire() - - //Status updates, death etc. - handle_regular_status_updates() - - update_canmove() - - if(client) - handle_regular_hud_updates() - - // Grabbing - for(var/obj/item/weapon/grab/G in src) - G.process() - - if(!client && stat == CONSCIOUS) - - if(prob(33) && canmove && isturf(loc) && !pulledby) //won't move if being pulled - - step(src, pick(cardinal)) - - if(prob(1)) - emote(pick("scratch","jump","roll","tail")) - -/mob/living/carbon/monkey/calculate_affecting_pressure(var/pressure) - ..() - return pressure - -/mob/living/carbon/monkey - -/mob/living/carbon/monkey/proc/handle_disabilities() - - - if (disabilities & EPILEPSY) - if ((prob(1) && paralysis < 10)) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/mob/living/carbon/monkey + var/oxygen_alert = 0 + var/toxins_alert = 0 + var/fire_alert = 0 + var/pressure_alert = 0 + + var/temperature_alert = 0 + + +/mob/living/carbon/monkey/Life() + set invisibility = 0 + //set background = 1 + if(timestopped) return 0 //under effects of time magick + + if (monkeyizing) return + if (update_muts) + update_muts=0 + domutcheck(src,null,MUTCHK_FORCED) + ..() + + var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE + if(loc) + environment = loc.return_air() + + if (stat != DEAD) //still breathing + //Is not a Diona Nymph - Snowflake Code + if(!istype(src,/mob/living/carbon/monkey/diona)) + //First, resolve location and get a breath + if(air_master.current_cycle%4==2) + //Only try to take a breath every 4 seconds, unless suffocating + breathe() + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + + + //Updates the number of stored chemicals for powers + handle_changeling() + + //Mutations and radiation + handle_mutations_and_radiation() + + //Chemicals in the body + handle_chemicals_in_body() + + //Disabilities + handle_disabilities() + + //Virus updates, duh + handle_virus_updates() + + //Apparently, the person who wrote this code designed it so that + //blinded get reset each cycle and then get activated later in the + //code. Very ugly. I dont care. Moving this stuff here so its easy + //to find it. + blinded = null + + //Handle temperature/pressure differences between body and environment + if(environment) // More error checking -- TLE + handle_environment(environment) + + //Check if we're on fire + handle_fire() + + //Status updates, death etc. + handle_regular_status_updates() + + update_canmove() + + if(client) + handle_regular_hud_updates() + + // Grabbing + for(var/obj/item/weapon/grab/G in src) + G.process() + + if(!client && stat == CONSCIOUS) + + if(prob(33) && canmove && isturf(loc) && !pulledby) //won't move if being pulled + + step(src, pick(cardinal)) + + if(prob(1)) + emote(pick("scratch","jump","roll","tail")) + +/mob/living/carbon/monkey/calculate_affecting_pressure(var/pressure) + ..() + return pressure + +/mob/living/carbon/monkey + +/mob/living/carbon/monkey/proc/handle_disabilities() + + + if (disabilities & EPILEPSY) + if ((prob(1) && paralysis < 10)) to_chat(src, "You have a seizure!") - Paralyse(10) - if (disabilities & COUGHING) - if ((prob(5) && paralysis <= 1)) - drop_item() - spawn( 0 ) - emote("cough") - return - if (disabilities & TOURETTES) - if ((prob(10) && paralysis <= 1)) - Stun(10) - spawn( 0 ) - emote("twitch") - return - if (disabilities & NERVOUS) - if (prob(10)) - stuttering = max(10, stuttering) - -/mob/living/carbon/monkey/proc/handle_mutations_and_radiation() - if(flags & INVULNERABLE) - return - - if(getFireLoss()) - if((M_RESIST_HEAT in mutations) || prob(50)) - switch(getFireLoss()) - if(1 to 50) - adjustFireLoss(-1) - if(51 to 100) - adjustFireLoss(-5) - - if ((M_HULK in mutations) && health <= 25) - mutations.Remove(M_HULK) + Paralyse(10) + if (disabilities & COUGHING) + if ((prob(5) && paralysis <= 1)) + drop_item() + spawn( 0 ) + emote("cough") + return + if (disabilities & TOURETTES) + if ((prob(10) && paralysis <= 1)) + Stun(10) + spawn( 0 ) + emote("twitch") + return + if (disabilities & NERVOUS) + if (prob(10)) + stuttering = max(10, stuttering) + +/mob/living/carbon/monkey/proc/handle_mutations_and_radiation() + if(flags & INVULNERABLE) + return + + if(getFireLoss()) + if((M_RESIST_HEAT in mutations) || prob(50)) + switch(getFireLoss()) + if(1 to 50) + adjustFireLoss(-1) + if(51 to 100) + adjustFireLoss(-5) + + if ((M_HULK in mutations) && health <= 25) + mutations.Remove(M_HULK) to_chat(src, "You suddenly feel very weak.") - Weaken(3) - emote("collapse") - if(reagents.has_reagent("creatine")) - var/datum/reagent/creatine/C = reagents.get_reagent("creatine") - C.dehulk(src) - - if (radiation) - - if(istype(src,/mob/living/carbon/monkey/diona)) //Filthy check. Dionaea don't take rad damage. - var/rads = radiation/25 - radiation -= rads - nutrition += rads - heal_overall_damage(rads,rads) - adjustOxyLoss(-(rads)) - adjustToxLoss(-(rads)) - updatehealth() - return - - if (radiation > 100) - radiation = 100 - Weaken(10) + Weaken(3) + emote("collapse") + if(reagents.has_reagent("creatine")) + var/datum/reagent/creatine/C = reagents.get_reagent("creatine") + C.dehulk(src) + + if (radiation) + + if(istype(src,/mob/living/carbon/monkey/diona)) //Filthy check. Dionaea don't take rad damage. + var/rads = radiation/25 + radiation -= rads + nutrition += rads + heal_overall_damage(rads,rads) + adjustOxyLoss(-(rads)) + adjustToxLoss(-(rads)) + updatehealth() + return + + if (radiation > 100) + radiation = 100 + Weaken(10) to_chat(src, "You feel weak.") - emote("collapse") - - switch(radiation) - if(1 to 49) - radiation-- - if(prob(25)) - adjustToxLoss(1) - updatehealth() - - if(50 to 74) - radiation -= 2 - adjustToxLoss(1) - if(prob(5)) - radiation -= 5 - Weaken(3) + emote("collapse") + + switch(radiation) + if(1 to 49) + radiation-- + if(prob(25)) + adjustToxLoss(1) + updatehealth() + + if(50 to 74) + radiation -= 2 + adjustToxLoss(1) + if(prob(5)) + radiation -= 5 + Weaken(3) to_chat(src, "You feel weak.") - emote("collapse") - updatehealth() - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - if(prob(1)) + emote("collapse") + updatehealth() + + if(75 to 100) + radiation -= 3 + adjustToxLoss(3) + if(prob(1)) to_chat(src, "You mutate!") - randmutb(src) - domutcheck(src,null) - emote("gasp") - updatehealth() - -// separate proc so we can jump out of it when we've succeeded in spreading disease. -/mob/living/carbon/monkey/proc/findAirborneVirii() - if(blood_virus_spreading_disabled) - return 0 - for(var/obj/effect/decal/cleanable/blood/B in get_turf(src)) - if(B.virus2.len) - for (var/ID in B.virus2) - var/datum/disease2/disease/V = B.virus2[ID] - if (infect_virus2(src,V, notes="(Airborne from blood)")) - return 1 - - for(var/obj/effect/decal/cleanable/mucus/M in get_turf(src)) - if(M.virus2.len) - for (var/ID in M.virus2) - var/datum/disease2/disease/V = M.virus2[ID] - if (infect_virus2(src,V, notes="(Airborne from mucus)")) - return 1 - return 0 - -/mob/living/carbon/monkey/proc/handle_virus_updates() - if(status_flags & GODMODE) return 0 //godmode - if(bodytemperature > 406) - for(var/datum/disease/D in viruses) - D.cure() - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - V.cure(src) - - src.findAirborneVirii() - - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - if(isnull(V)) // Trying to figure out a runtime error that keeps repeating - CRASH("virus2 nulled before calling activate()") - else - V.activate(src) - // activate may have deleted the virus - if(!V) continue - - // check if we're immune - if(V.antigen & src.antibodies) - V.dead = 1 - - return - -/mob/living/carbon/monkey/proc/breathe() - if(flags & INVULNERABLE) - return - - if(reagents) - if(reagents.has_reagent("lexorin")) return - - if(!loc) return //probably ought to make a proper fix for this, but :effort: --NeoFite - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - if(health < 0) - losebreath++ - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(75)) //High chance of gasping for air - spawn emote("gasp") - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - else - //First, check for air from internal atmosphere (using an air tank and mask generally) - breath = get_breath_from_internal(BREATH_VOLUME) - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) - else if(istype(loc, /turf/)) - var/breath_moles = environment.total_moles()*BREATH_PERCENTAGE - breath = loc.remove_air(breath_moles) - - // Handle chem smoke effect -- Doohl - var/block = 0 - if(wear_mask) - if(istype(wear_mask, /obj/item/clothing/mask/gas)) - block = 1 - - if(!block) - for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - handle_breath(breath) - if(breath) - loc.assume_air(breath) - - -/mob/living/carbon/monkey/proc/get_breath_from_internal(volume_needed) - if(internal) - if (!contents.Find(internal)) - internal = null - if (!wear_mask || !(wear_mask.flags|MASKINTERNALS) ) - internal = null - if(internal) - if (internals) - internals.icon_state = "internal1" - return internal.remove_air_volume(volume_needed) - else - if (internals) - internals.icon_state = "internal0" - return null - -/mob/living/carbon/monkey/proc/handle_breath(datum/gas_mixture/breath) - if((status_flags & GODMODE) || (flags & INVULNERABLE)) - return - - if(!breath || (breath.total_moles == 0)) - adjustOxyLoss(7) - - oxygen_alert = max(oxygen_alert, 1) - - 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_toxins_max = 0.5 - var/safe_toxins_mask = 5 - var/SA_para_min = 0.5 - var/SA_sleep_min = 5 - var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - - //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 - - if(O2_pp < safe_oxygen_min) // Too little oxygen - if(prob(20)) - spawn(0) emote("gasp") - if (O2_pp == 0) - O2_pp = 0.01 - var/ratio = safe_oxygen_min/O2_pp - adjustOxyLoss(min(5*ratio, 7)) // Don't fuck them up too fast (space only does 7 after all!) - oxygen_used = breath.oxygen*ratio/6 - 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 // We're in safe limits - adjustOxyLoss(-5) - oxygen_used = breath.oxygen/6 - oxygen_alert = 0 - - breath.oxygen -= oxygen_used - breath.carbon_dioxide += oxygen_used - - 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. - co2overloadtime = world.time - else if(world.time - co2overloadtime > 120) - 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(8) - if(prob(20)) // Lets give them some chance to know somethings not right though I guess. - 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 - if(wear_mask) - if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) - if(breath.toxins > safe_toxins_mask) - ratio = (breath.toxins/safe_toxins_mask) * 10 - else - ratio = 0 - if(ratio) - if(reagents) - reagents.add_reagent("plasma", 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. - 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 - sleeping = max(sleeping+2, 10) - else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning - if(prob(20)) - spawn(0) emote(pick("giggle", "laugh")) - - - if(breath.temperature > (T0C+66)) // Hot air hurts :( - if(prob(20)) + randmutb(src) + domutcheck(src,null) + emote("gasp") + updatehealth() + +// separate proc so we can jump out of it when we've succeeded in spreading disease. +/mob/living/carbon/monkey/proc/findAirborneVirii() + if(blood_virus_spreading_disabled) + return 0 + for(var/obj/effect/decal/cleanable/blood/B in get_turf(src)) + if(B.virus2.len) + for (var/ID in B.virus2) + var/datum/disease2/disease/V = B.virus2[ID] + if (infect_virus2(src,V, notes="(Airborne from blood)")) + return 1 + + for(var/obj/effect/decal/cleanable/mucus/M in get_turf(src)) + if(M.virus2.len) + for (var/ID in M.virus2) + var/datum/disease2/disease/V = M.virus2[ID] + if (infect_virus2(src,V, notes="(Airborne from mucus)")) + return 1 + return 0 + +/mob/living/carbon/monkey/proc/handle_virus_updates() + if(status_flags & GODMODE) return 0 //godmode + if(bodytemperature > 406) + for(var/datum/disease/D in viruses) + D.cure() + for (var/ID in virus2) + var/datum/disease2/disease/V = virus2[ID] + V.cure(src) + + src.findAirborneVirii() + + for (var/ID in virus2) + var/datum/disease2/disease/V = virus2[ID] + if(isnull(V)) // Trying to figure out a runtime error that keeps repeating + CRASH("virus2 nulled before calling activate()") + else + V.activate(src) + // activate may have deleted the virus + if(!V) continue + + // check if we're immune + if(V.antigen & src.antibodies) + V.dead = 1 + + return + +/mob/living/carbon/monkey/proc/breathe() + if(flags & INVULNERABLE) + return + + if(reagents) + if(reagents.has_reagent("lexorin")) return + + if(!loc) return //probably ought to make a proper fix for this, but :effort: --NeoFite + + var/datum/gas_mixture/environment = loc.return_air() + var/datum/gas_mixture/breath + if(health < 0) + losebreath++ + if(losebreath>0) //Suffocating so do not take a breath + losebreath-- + if (prob(75)) //High chance of gasping for air + spawn emote("gasp") + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + else + //First, check for air from internal atmosphere (using an air tank and mask generally) + breath = get_breath_from_internal(BREATH_VOLUME) + + //No breath from internal atmosphere so get breath from location + if(!breath) + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) + else if(istype(loc, /turf/)) + var/breath_moles = environment.total_moles()*BREATH_PERCENTAGE + breath = loc.remove_air(breath_moles) + + // Handle chem smoke effect -- Doohl + var/block = 0 + if(wear_mask) + if(istype(wear_mask, /obj/item/clothing/mask/gas)) + block = 1 + + if(!block) + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(src, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + + + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) + + handle_breath(breath) + if(breath) + loc.assume_air(breath) + + +/mob/living/carbon/monkey/proc/get_breath_from_internal(volume_needed) + if(internal) + if (!contents.Find(internal)) + internal = null + if (!wear_mask || !(wear_mask.flags|MASKINTERNALS) ) + internal = null + if(internal) + if (internals) + internals.icon_state = "internal1" + return internal.remove_air_volume(volume_needed) + else + if (internals) + internals.icon_state = "internal0" + return null + +/mob/living/carbon/monkey/proc/handle_breath(datum/gas_mixture/breath) + if((status_flags & GODMODE) || (flags & INVULNERABLE)) + return + + if(!breath || (breath.total_moles == 0)) + adjustOxyLoss(7) + + oxygen_alert = max(oxygen_alert, 1) + + 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_toxins_max = 0.5 + var/safe_toxins_mask = 5 + var/SA_para_min = 0.5 + var/SA_sleep_min = 5 + var/oxygen_used = 0 + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + + //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 + + if(O2_pp < safe_oxygen_min) // Too little oxygen + if(prob(20)) + spawn(0) emote("gasp") + if (O2_pp == 0) + O2_pp = 0.01 + var/ratio = safe_oxygen_min/O2_pp + adjustOxyLoss(min(5*ratio, 7)) // Don't fuck them up too fast (space only does 7 after all!) + oxygen_used = breath.oxygen*ratio/6 + 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 // We're in safe limits + adjustOxyLoss(-5) + oxygen_used = breath.oxygen/6 + oxygen_alert = 0 + + breath.oxygen -= oxygen_used + breath.carbon_dioxide += oxygen_used + + 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. + co2overloadtime = world.time + else if(world.time - co2overloadtime > 120) + 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(8) + if(prob(20)) // Lets give them some chance to know somethings not right though I guess. + 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 + if(wear_mask) + if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) + if(breath.toxins > safe_toxins_mask) + ratio = (breath.toxins/safe_toxins_mask) * 10 + else + ratio = 0 + if(ratio) + if(reagents) + reagents.add_reagent("plasma", 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. + 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 + sleeping = max(sleeping+2, 10) + else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + if(prob(20)) + spawn(0) emote(pick("giggle", "laugh")) + + + if(breath.temperature > (T0C+66)) // Hot air hurts :( + if(prob(20)) to_chat(src, "You feel a searing heat in your lungs!") - fire_alert = max(fire_alert, 2) - else - fire_alert = 0 - - - //Temporary fixes to the alerts. - - return 1 - -/mob/living/carbon/monkey/proc/handle_environment(datum/gas_mixture/environment) - if(!environment || (flags & INVULNERABLE)) - return - var/spaceproof = 0 - if(hat && istype(hat, /obj/item/clothing/head/helmet/space) && uniform && istype(uniform, /obj/item/clothing/monkeyclothes/space)) - spaceproof = 1 //quick and dirt cheap. no need for the Life() of monkeys to become as complicated as the Life() of humans. man that's deep. - - var/environment_heat_capacity = environment.heat_capacity() - if(istype(get_turf(src), /turf/space)) - var/turf/heat_turf = get_turf(src) - environment_heat_capacity = heat_turf.heat_capacity - - if(!on_fire) - if((environment.temperature > (T0C + 50)) || ((environment.temperature < (T0C + 10)) && !spaceproof)) - var/transfer_coefficient = 1 - handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) - - if(stat==DEAD) - 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) ) - pressure_alert = 2 - if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) - pressure_alert = 1 - if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) - pressure_alert = 0 - if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) - if(!spaceproof) - pressure_alert = -1 - else - if(!spaceproof) - if( !(M_RESIST_COLD in mutations) ) - adjustBruteLoss( LOW_PRESSURE_DAMAGE ) - pressure_alert = -2 - else - pressure_alert = -1 - - return - -/mob/living/carbon/monkey/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) - if(status_flags & GODMODE) return - var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) - //adjustFireLoss(2.5*discomfort) - - if(exposed_temperature > bodytemperature) - adjustFireLoss(20.0*discomfort) - - else - adjustFireLoss(5.0*discomfort) - -/mob/living/carbon/monkey/proc/handle_chemicals_in_body() - - - if(alien) //Diona nymphs are the only alien monkey currently. - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(loc)) //else, there's considered to be no light - var/turf/T = loc - if(T.dynamic_lighting) - light_amount = T.get_lumcount(0.5) - else - light_amount = 5 - nutrition += light_amount - traumatic_shock -= light_amount - - if(nutrition > 500) - nutrition = 500 - if(light_amount > 2) //if there's enough light, heal - adjustBruteLoss(-1) - adjustToxLoss(-1) - adjustOxyLoss(-1) - - if(reagents) reagents.metabolize(src,alien) - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 5) - else - dizziness = max(0, dizziness - 1) - - updatehealth() - return //TODO: DEFERRED - -/mob/living/carbon/monkey/proc/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - updatehealth() - if(health < config.health_threshold_dead || !has_brain()) - death() - blinded = 1 - stat = DEAD - silent = 0 - return 1 - - //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 25) || (config.health_threshold_crit > health) ) - if( health <= 20 && prob(1) ) - spawn(0) - emote("gasp") - if(!reagents.has_reagent("inaprovaline")) - adjustOxyLoss(1) - Paralyse(3) - if(halloss > 100) + fire_alert = max(fire_alert, 2) + else + fire_alert = 0 + + + //Temporary fixes to the alerts. + + return 1 + +/mob/living/carbon/monkey/proc/handle_environment(datum/gas_mixture/environment) + if(!environment || (flags & INVULNERABLE)) + return + var/spaceproof = 0 + if(hat && istype(hat, /obj/item/clothing/head/helmet/space) && uniform && istype(uniform, /obj/item/clothing/monkeyclothes/space)) + spaceproof = 1 //quick and dirt cheap. no need for the Life() of monkeys to become as complicated as the Life() of humans. man that's deep. + + var/environment_heat_capacity = environment.heat_capacity() + if(istype(get_turf(src), /turf/space)) + var/turf/heat_turf = get_turf(src) + environment_heat_capacity = heat_turf.heat_capacity + + if(!on_fire) + if((environment.temperature > (T0C + 50)) || ((environment.temperature < (T0C + 10)) && !spaceproof)) + var/transfer_coefficient = 1 + handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) + + if(stat==DEAD) + 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) ) + pressure_alert = 2 + if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) + pressure_alert = 1 + if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) + pressure_alert = 0 + if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) + if(!spaceproof) + pressure_alert = -1 + else + if(!spaceproof) + if( !(M_RESIST_COLD in mutations) ) + adjustBruteLoss( LOW_PRESSURE_DAMAGE ) + pressure_alert = -2 + else + pressure_alert = -1 + + return + +/mob/living/carbon/monkey/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) + if(status_flags & GODMODE) return + var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) + //adjustFireLoss(2.5*discomfort) + + if(exposed_temperature > bodytemperature) + adjustFireLoss(20.0*discomfort) + + else + adjustFireLoss(5.0*discomfort) + +/mob/living/carbon/monkey/proc/handle_chemicals_in_body() + + + if(alien) //Diona nymphs are the only alien monkey currently. + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(loc)) //else, there's considered to be no light + var/turf/T = loc + if(T.dynamic_lighting) + light_amount = T.get_lumcount(0.5) + else + light_amount = 5 + nutrition += light_amount + traumatic_shock -= light_amount + + if(nutrition > 500) + nutrition = 500 + if(light_amount > 2) //if there's enough light, heal + adjustBruteLoss(-1) + adjustToxLoss(-1) + adjustOxyLoss(-1) + + if(reagents) reagents.metabolize(src,alien) + + if (drowsyness) + drowsyness-- + eye_blurry = max(2, eye_blurry) + if (prob(5)) + sleeping += 1 + Paralyse(5) + + confused = max(0, confused - 1) + // decrement dizziness counter, clamped to 0 + if(resting) + dizziness = max(0, dizziness - 5) + else + dizziness = max(0, dizziness - 1) + + updatehealth() + return //TODO: DEFERRED + +/mob/living/carbon/monkey/proc/handle_regular_status_updates() + updatehealth() + + if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP + blinded = 1 + silent = 0 + else //ALIVE. LIGHTS ARE ON + updatehealth() + if(health < config.health_threshold_dead || !has_brain()) + death() + blinded = 1 + stat = DEAD + silent = 0 + return 1 + + //UNCONSCIOUS. NO-ONE IS HOME + if( (getOxyLoss() > 25) || (config.health_threshold_crit > health) ) + if( health <= 20 && prob(1) ) + spawn(0) + emote("gasp") + if(!reagents.has_reagent("inaprovaline")) + adjustOxyLoss(1) + Paralyse(3) + if(halloss > 100) to_chat(src, "You're in too much pain to keep going...") - for(var/mob/O in oviewers(src, null)) - O.show_message("[src] slumps to the ground, too weak to continue fighting.", 1) - Paralyse(10) - setHalLoss(99) - - if(paralysis) - AdjustParalysis(-1) - blinded = 1 - stat = UNCONSCIOUS - if(halloss > 0) - adjustHalLoss(-3) - else if(sleeping) - handle_dreams() - adjustHalLoss(-3) - sleeping = max(sleeping-1, 0) - blinded = 1 - stat = UNCONSCIOUS - if( prob(10) && health && !hal_crit ) - spawn(0) - emote("snore") - else if(resting) - if(halloss > 0) - adjustHalLoss(-3) - //CONSCIOUS - else - stat = CONSCIOUS - if(halloss > 0) - adjustHalLoss(-1) - - //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly - eye_blurry = max(eye_blurry-1, 0) - - //Ears - if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own - ear_deaf = max(ear_deaf, 1) - else if(ear_deaf) //deafness, heals slowly over time - ear_deaf = max(ear_deaf-1, 0) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs - ear_damage = max(ear_damage-0.05, 0) - - //Other - if(stunned) - 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) - stuttering = max(stuttering-1, 0) - - if(silent) - silent = max(silent-1, 0) - - if(druggy) - druggy = max(druggy-1, 0) - return 1 - - -/mob/living/carbon/monkey/proc/handle_regular_hud_updates() - - - if(!canWearHats && m_hatbg) - if(m_hatbg.icon_state != "blank") - m_hatbg.icon_state = "blank" - - if(!canWearClothes && m_suitclothesbg) - if(m_suitclothesbg.icon_state != "blank") - m_suitclothesbg.icon_state = "blank" - - if(!canWearGlasses && m_glassesbg) - if(m_glassesbg.icon_state != "blank") - m_glassesbg.icon_state = "blank" - - - if (stat == 2 || (M_XRAY in mutations)) - sight |= SEE_TURFS - sight |= SEE_MOBS - sight |= SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (stat != 2) - sight &= ~SEE_TURFS - sight &= ~SEE_MOBS - sight &= ~SEE_OBJS - see_in_dark = 2 - see_invisible = SEE_INVISIBLE_LIVING - - if (healths) - if (stat != 2) - switch(health) - if(100 to INFINITY) - healths.icon_state = "health0" - if(80 to 100) - healths.icon_state = "health1" - if(60 to 80) - healths.icon_state = "health2" - if(40 to 60) - healths.icon_state = "health3" - if(20 to 40) - healths.icon_state = "health4" - if(0 to 20) - healths.icon_state = "health5" - else - healths.icon_state = "health6" - else - healths.icon_state = "health7" - - - if(pressure) - pressure.icon_state = "pressure[pressure_alert]" - - if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" - - - if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]" - if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" - if (fire) fire.icon_state = "fire[fire_alert ? 2 : 0]" - //NOTE: the alerts dont reset when youre out of danger. dont blame me, - //blame the person who coded them. Temporary fix added. - - if(bodytemp) - switch(bodytemperature) //310.055 optimal body temp - if(345 to INFINITY) - bodytemp.icon_state = "temp4" - if(335 to 345) - bodytemp.icon_state = "temp3" - if(327 to 335) - bodytemp.icon_state = "temp2" - if(316 to 327) - bodytemp.icon_state = "temp1" - if(300 to 316) - bodytemp.icon_state = "temp0" - if(295 to 300) - bodytemp.icon_state = "temp-1" - if(280 to 295) - bodytemp.icon_state = "temp-2" - if(260 to 280) - bodytemp.icon_state = "temp-3" - else - bodytemp.icon_state = "temp-4" - - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if(blind && stat != DEAD) - if(blinded) - blind.layer = 18 - else - blind.layer = 0 - - if(disabilities & NEARSIGHTED) - client.screen += global_hud.vimpaired - - if(eye_blurry) - client.screen += global_hud.blurry - - if(druggy) - client.screen += global_hud.druggy - - if (stat != 2) - if (machine) - if (!( machine.check_eye(src) )) - reset_view(null) - else - if(client && !client.adminobs && !isTeleViewing(client.eye)) - reset_view(null) - - return 1 - -/mob/living/carbon/monkey/proc/handle_random_events() - if (prob(1) && prob(2)) - spawn(0) - emote("scratch") - return - - -/mob/living/carbon/monkey/proc/handle_changeling() - if(mind && mind.changeling) - mind.changeling.regenerate() - -///FIRE CODE -/mob/living/carbon/monkey/handle_fire() - if(..()) - return - adjustFireLoss(6) - return -//END FIRE CODE + for(var/mob/O in oviewers(src, null)) + O.show_message("[src] slumps to the ground, too weak to continue fighting.", 1) + Paralyse(10) + setHalLoss(99) + + if(paralysis) + AdjustParalysis(-1) + blinded = 1 + stat = UNCONSCIOUS + if(halloss > 0) + adjustHalLoss(-3) + else if(sleeping) + handle_dreams() + adjustHalLoss(-3) + sleeping = max(sleeping-1, 0) + blinded = 1 + stat = UNCONSCIOUS + if( prob(10) && health && !hal_crit ) + spawn(0) + emote("snore") + else if(resting) + if(halloss > 0) + adjustHalLoss(-3) + //CONSCIOUS + else + stat = CONSCIOUS + if(halloss > 0) + adjustHalLoss(-1) + + //Eyes + if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own + blinded = 1 + else if(eye_blind) //blindness, heals slowly over time + eye_blind = max(eye_blind-1,0) + blinded = 1 + else if(eye_blurry) //blurry eyes heal slowly + eye_blurry = max(eye_blurry-1, 0) + + //Ears + if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own + ear_deaf = max(ear_deaf, 1) + else if(ear_deaf) //deafness, heals slowly over time + ear_deaf = max(ear_deaf-1, 0) + else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs + ear_damage = max(ear_damage-0.05, 0) + + //Other + if(stunned) + 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) + stuttering = max(stuttering-1, 0) + + if(silent) + silent = max(silent-1, 0) + + if(druggy) + druggy = max(druggy-1, 0) + return 1 + + +/mob/living/carbon/monkey/proc/handle_regular_hud_updates() + + + if(!canWearHats && m_hatbg) + if(m_hatbg.icon_state != "blank") + m_hatbg.icon_state = "blank" + + if(!canWearClothes && m_suitclothesbg) + if(m_suitclothesbg.icon_state != "blank") + m_suitclothesbg.icon_state = "blank" + + if(!canWearGlasses && m_glassesbg) + if(m_glassesbg.icon_state != "blank") + m_glassesbg.icon_state = "blank" + + + if (stat == 2 || (M_XRAY in mutations)) + sight |= SEE_TURFS + sight |= SEE_MOBS + sight |= SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (stat != 2) + sight &= ~SEE_TURFS + sight &= ~SEE_MOBS + sight &= ~SEE_OBJS + see_in_dark = 2 + see_invisible = SEE_INVISIBLE_LIVING + + if (healths) + if (stat != 2) + switch(health) + if(100 to INFINITY) + healths.icon_state = "health0" + if(80 to 100) + healths.icon_state = "health1" + if(60 to 80) + healths.icon_state = "health2" + if(40 to 60) + healths.icon_state = "health3" + if(20 to 40) + healths.icon_state = "health4" + if(0 to 20) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" + + + if(pressure) + pressure.icon_state = "pressure[pressure_alert]" + + if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" + + + if (toxin) toxin.icon_state = "tox[toxins_alert ? 1 : 0]" + if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" + if (fire) fire.icon_state = "fire[fire_alert ? 2 : 0]" + //NOTE: the alerts dont reset when youre out of danger. dont blame me, + //blame the person who coded them. Temporary fix added. + + if(bodytemp) + switch(bodytemperature) //310.055 optimal body temp + if(345 to INFINITY) + bodytemp.icon_state = "temp4" + if(335 to 345) + bodytemp.icon_state = "temp3" + if(327 to 335) + bodytemp.icon_state = "temp2" + if(316 to 327) + bodytemp.icon_state = "temp1" + if(300 to 316) + bodytemp.icon_state = "temp0" + if(295 to 300) + bodytemp.icon_state = "temp-1" + if(280 to 295) + bodytemp.icon_state = "temp-2" + if(260 to 280) + bodytemp.icon_state = "temp-3" + else + bodytemp.icon_state = "temp-4" + + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if(blind && stat != DEAD) + if(blinded) + blind.layer = 18 + else + blind.layer = 0 + + if(disabilities & NEARSIGHTED) + client.screen += global_hud.vimpaired + + if(eye_blurry) + client.screen += global_hud.blurry + + if(druggy) + client.screen += global_hud.druggy + + if (stat != 2) + if (machine) + if (!( machine.check_eye(src) )) + reset_view(null) + else + if(client && !client.adminobs && !isTeleViewing(client.eye)) + reset_view(null) + + return 1 + +/mob/living/carbon/monkey/proc/handle_random_events() + if (prob(1) && prob(2)) + spawn(0) + emote("scratch") + return + + +/mob/living/carbon/monkey/proc/handle_changeling() + if(mind && mind.changeling) + mind.changeling.regenerate() + +///FIRE CODE +/mob/living/carbon/monkey/handle_fire() + if(..()) + return + adjustFireLoss(6) + return +//END FIRE CODE diff --git a/code/modules/mob/living/carbon/monkey/login.dm b/code/modules/mob/living/carbon/monkey/login.dm index 3b7e5dcb971..7f09b63a219 100644 --- a/code/modules/mob/living/carbon/monkey/login.dm +++ b/code/modules/mob/living/carbon/monkey/login.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/monkey/Login() - ..() - update_hud() - return +/mob/living/carbon/monkey/Login() + ..() + update_hud() + return diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 71e1aec5267..849437dcdbc 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -1,746 +1,746 @@ -/mob/living/carbon/monkey - name = "monkey" - voice_name = "monkey" - //speak_emote = list("chimpers") - icon_state = "monkey1" - icon = 'icons/mob/monkey.dmi' - gender = NEUTER - pass_flags = PASSTABLE - update_icon = 0 ///no need to call regenerate_icon - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey - species_type = /mob/living/carbon/monkey - treadmill_speed = 0.8 //Slow apes! - - mob_bump_flag = MONKEY - mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL - mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL|ALIEN - - size = SIZE_SMALL - - var/canWearClothes = 1 - var/canWearHats = 1 - var/canWearGlasses = 1 - - var/obj/item/clothing/monkeyclothes/uniform = null - var/obj/item/clothing/head/hat = null - var/obj/item/clothing/glasses/glasses = null - - var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie - var/greaterform = "Human" // Used when humanizing a monkey. - icon_state = "monkey1" - //var/uni_append = "12C4E2" // Small appearance modifier for different species. - var/list/uni_append = list(0x12C,0x4E2) // Same as above for DNA2. - var/update_muts = 1 // Monkey gene must be set at start. - var/alien = 0 //Used for reagent metabolism. - -/mob/living/carbon/monkey/Destroy() - ..() - uniform = null - hat = null - glasses = null - -/mob/living/carbon/monkey/abiotic() - return (wear_mask || l_hand || r_hand || back || uniform || hat) - -/mob/living/carbon/monkey/tajara - name = "farwa" - voice_name = "farwa" - speak_emote = list("mews") - icon_state = "tajkey1" - uni_append = list(0x0A0,0xE00) // 0A0E00 - species_type = /mob/living/carbon/monkey/tajara - -/mob/living/carbon/monkey/skrell - name = "neaera" - voice_name = "neaera" - speak_emote = list("squicks") - icon_state = "skrellkey1" - uni_append = list(0x01C,0xC92) // 01CC92 - species_type = /mob/living/carbon/monkey/skrell - -/mob/living/carbon/monkey/unathi - name = "stok" - voice_name = "stok" - speak_emote = list("hisses") - icon_state = "stokkey1" - uni_append = list(0x044,0xC5D) // 044C5D - canWearClothes = 0 - species_type = /mob/living/carbon/monkey/unathi - -/mob/living/carbon/monkey/New() - var/datum/reagents/R = new/datum/reagents(1000) - reagents = R - R.my_atom = src - - if(name == initial(name)) //To stop Pun-Pun becoming generic. - name = "[name] ([rand(1, 1000)])" - real_name = name - - if (!(dna)) - if(gender == NEUTER) - setGender(pick(MALE, FEMALE)) - dna = new /datum/dna( null ) - dna.real_name = real_name - dna.b_type = pick("A+","A-","AB+","AB-","O+","O-") - dna.ResetSE() - dna.ResetUI() - //dna.uni_identity = "00600200A00E0110148FC01300B009" - //dna.SetUI(list(0x006,0x002,0x00A,0x00E,0x011,0x014,0x8FC,0x013,0x00B,0x009)) - //dna.struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" - //dna.SetSE(list(0x433,0x591,0x567,0x561,0x31E,0x137,0x633,0x34D,0x1C3,0x690,0x120,0x321,0x64D,0x4FE,0x4CD,0x615,0x44B,0x6C0,0x3F2,0x51B,0x6C6,0x0A4,0x282,0x1D2,0x6BA,0x3B0,0xFD6)) - dna.unique_enzymes = md5(name) - - // We're a monkey - dna.SetSEState(MONKEYBLOCK, 1) - dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) - // Fix gender - dna.SetUIState(DNA_UI_GENDER, gender != MALE, 1) - - // Set the blocks to uni_append, if needed. - if(uni_append.len>0) - for(var/b=1;b<=uni_append.len;b++) - dna.SetUIValue(DNA_UI_LENGTH-(uni_append.len-b),uni_append[b], 1) - dna.UpdateUI() - - update_muts=1 - - if(!istype(src, /mob/living/carbon/monkey/diona)) - add_language(LANGUAGE_MONKEY) - default_language = all_languages[LANGUAGE_MONKEY] - - ..() - update_icons() - return - -/mob/living/carbon/monkey/unathi/New() - - ..() - dna.mutantrace = "lizard" - greaterform = "Unathi" - add_language("Sinta'unathi") - -/mob/living/carbon/monkey/skrell/New() - - ..() - dna.mutantrace = "skrell" - greaterform = "Skrell" - add_language("Skrellian") - -/mob/living/carbon/monkey/tajara/New() - - ..() - dna.mutantrace = "tajaran" - greaterform = "Tajaran" - add_language("Siik'tajr") - -/mob/living/carbon/monkey/diona/New() - - ..() - alien = 1 - setGender(NEUTER) - dna.mutantrace = "plant" - greaterform = "Diona" - add_language("Rootspeak") - -/mob/living/carbon/monkey/show_inv(mob/living/carbon/user as mob) - user.set_machine(src) - var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) - var/TAB = "    " - - var/dat = {" - Left Hand: [(l_hand && !( src.l_hand.abstract )) ? l_hand : "Empty"]
    - Right Hand: [(r_hand && !( src.r_hand.abstract )) ? r_hand : "Empty"]
    - "} - - dat += "
    Back: [(back && !(src.back.abstract)) ? back : "Empty"]" - if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) - dat += "
    [TAB]↳[internal ? "Disable Internals" : "Set Internals"]" - - dat += "
    " - - if(canWearHats) - if(hat) - dat += "
    Headwear: [hat] (Remove)" - else - dat += "
    Headwear: Empty" - - dat += "
    Mask: [(wear_mask && !(src.wear_mask.abstract)) ? wear_mask : "Empty"]" - - if(canWearGlasses) - if(glasses) - dat += "
    Glasses: [glasses] (Remove)" - else - dat += "
    Glasses: Empty" - - if(canWearClothes) - if(uniform) - dat += "
    Uniform: [uniform] (Remove)" - else - dat += "
    Uniform: Empty" - - if(handcuffed) - dat += "
    Handcuffed: Remove" - - dat += {" -
    -
    Close - "} - - var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 340, 500) - popup.set_content(dat) - popup.open() - -/mob/living/carbon/monkey/movement_delay() - var/tally = 0 - if(reagents) - if(reagents.has_reagent("hyperzine")) return -1 - - if(reagents.has_reagent("nuka_cola")) return -1 - - var/health_deficiency = (100 - health) - if(health_deficiency >= 45) tally += (health_deficiency / 25) - - if (bodytemperature < 283.222) - tally += (283.222 - bodytemperature) / 10 * 1.75 - - if(istype(loc,/turf/simulated/floor)) - var/turf/simulated/floor/T = loc - - if(T.material=="phazon") - return -1 // Phazon floors make us go fast - - return tally+config.monkey_delay - - -/mob/living/carbon/monkey/proc/wearhat(var/obj/item/clothing/head/H as obj) - if(H) - if(istype(H)) - var/obj/item/clothing/head/oldhat = null - if(hat) - oldhat = hat - hat = null - hat = H - usr.drop_item(hat, src, 1) - regenerate_icons() - if (oldhat) - usr.put_in_hands(oldhat) - else - if(hat) - usr.put_in_hands(hat) - hat = null - regenerate_icons() - -/mob/living/carbon/monkey/proc/wearclothes(var/obj/item/clothing/monkeyclothes/C as obj) - if(C) - if(istype(C)) - var/obj/item/clothing/monkeyclothes/olduniform = null - if(uniform) - olduniform = uniform - uniform = null - uniform = C - usr.drop_item(uniform, src, 1) - regenerate_icons() - if (olduniform) - usr.put_in_hands(olduniform) - else - if(uniform) - usr.put_in_hands(uniform) - uniform = null - regenerate_icons() - -/mob/living/carbon/monkey/proc/wearglasses(var/obj/item/clothing/glasses/G as obj) - if(G) - if(istype(G)) - var/obj/item/clothing/glasses/oldglasses = null - if(glasses) - oldglasses = glasses - glasses = null - glasses = G - usr.drop_item(glasses, src, 1) - regenerate_icons() - if (oldglasses) - usr.put_in_hands(oldglasses) - else - if(glasses) - usr.put_in_hands(glasses) - glasses = null - regenerate_icons() - -/mob/living/carbon/monkey/Topic(href, href_list) - ..() - if (href_list["mach_close"]) - var/t1 = text("window=[]", href_list["mach_close"]) - unset_machine() - src << browse(null, t1) - if ((href_list["item"] && !( usr.stat ) && !( usr.restrained() ) && in_range(src, usr) )) - var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) - O.source = usr - O.target = src - O.item = usr.get_active_hand() - O.s_loc = usr.loc - O.t_loc = loc - O.place = href_list["item"] - requests += O - spawn( 0 ) - O.process() - return - if(href_list["remove_inv"]) - if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) - return - var/remove_from = href_list["remove_inv"] - switch(remove_from) - if("uniform") - if(uniform) - uniform.loc = src.loc - uniform = null - regenerate_icons() - else +/mob/living/carbon/monkey + name = "monkey" + voice_name = "monkey" + //speak_emote = list("chimpers") + icon_state = "monkey1" + icon = 'icons/mob/monkey.dmi' + gender = NEUTER + pass_flags = PASSTABLE + update_icon = 0 ///no need to call regenerate_icon + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal/monkey + species_type = /mob/living/carbon/monkey + treadmill_speed = 0.8 //Slow apes! + + mob_bump_flag = MONKEY + mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL + mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL|ALIEN + + size = SIZE_SMALL + + var/canWearClothes = 1 + var/canWearHats = 1 + var/canWearGlasses = 1 + + var/obj/item/clothing/monkeyclothes/uniform = null + var/obj/item/clothing/head/hat = null + var/obj/item/clothing/glasses/glasses = null + + var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie + var/greaterform = "Human" // Used when humanizing a monkey. + icon_state = "monkey1" + //var/uni_append = "12C4E2" // Small appearance modifier for different species. + var/list/uni_append = list(0x12C,0x4E2) // Same as above for DNA2. + var/update_muts = 1 // Monkey gene must be set at start. + var/alien = 0 //Used for reagent metabolism. + +/mob/living/carbon/monkey/Destroy() + ..() + uniform = null + hat = null + glasses = null + +/mob/living/carbon/monkey/abiotic() + return (wear_mask || l_hand || r_hand || back || uniform || hat) + +/mob/living/carbon/monkey/tajara + name = "farwa" + voice_name = "farwa" + speak_emote = list("mews") + icon_state = "tajkey1" + uni_append = list(0x0A0,0xE00) // 0A0E00 + species_type = /mob/living/carbon/monkey/tajara + +/mob/living/carbon/monkey/skrell + name = "neaera" + voice_name = "neaera" + speak_emote = list("squicks") + icon_state = "skrellkey1" + uni_append = list(0x01C,0xC92) // 01CC92 + species_type = /mob/living/carbon/monkey/skrell + +/mob/living/carbon/monkey/unathi + name = "stok" + voice_name = "stok" + speak_emote = list("hisses") + icon_state = "stokkey1" + uni_append = list(0x044,0xC5D) // 044C5D + canWearClothes = 0 + species_type = /mob/living/carbon/monkey/unathi + +/mob/living/carbon/monkey/New() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + + if(name == initial(name)) //To stop Pun-Pun becoming generic. + name = "[name] ([rand(1, 1000)])" + real_name = name + + if (!(dna)) + if(gender == NEUTER) + setGender(pick(MALE, FEMALE)) + dna = new /datum/dna( null ) + dna.real_name = real_name + dna.b_type = pick("A+","A-","AB+","AB-","O+","O-") + dna.ResetSE() + dna.ResetUI() + //dna.uni_identity = "00600200A00E0110148FC01300B009" + //dna.SetUI(list(0x006,0x002,0x00A,0x00E,0x011,0x014,0x8FC,0x013,0x00B,0x009)) + //dna.struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" + //dna.SetSE(list(0x433,0x591,0x567,0x561,0x31E,0x137,0x633,0x34D,0x1C3,0x690,0x120,0x321,0x64D,0x4FE,0x4CD,0x615,0x44B,0x6C0,0x3F2,0x51B,0x6C6,0x0A4,0x282,0x1D2,0x6BA,0x3B0,0xFD6)) + dna.unique_enzymes = md5(name) + + // We're a monkey + dna.SetSEState(MONKEYBLOCK, 1) + dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) + // Fix gender + dna.SetUIState(DNA_UI_GENDER, gender != MALE, 1) + + // Set the blocks to uni_append, if needed. + if(uni_append.len>0) + for(var/b=1;b<=uni_append.len;b++) + dna.SetUIValue(DNA_UI_LENGTH-(uni_append.len-b),uni_append[b], 1) + dna.UpdateUI() + + update_muts=1 + + if(!istype(src, /mob/living/carbon/monkey/diona)) + add_language(LANGUAGE_MONKEY) + default_language = all_languages[LANGUAGE_MONKEY] + + ..() + update_icons() + return + +/mob/living/carbon/monkey/unathi/New() + + ..() + dna.mutantrace = "lizard" + greaterform = "Unathi" + add_language("Sinta'unathi") + +/mob/living/carbon/monkey/skrell/New() + + ..() + dna.mutantrace = "skrell" + greaterform = "Skrell" + add_language("Skrellian") + +/mob/living/carbon/monkey/tajara/New() + + ..() + dna.mutantrace = "tajaran" + greaterform = "Tajaran" + add_language("Siik'tajr") + +/mob/living/carbon/monkey/diona/New() + + ..() + alien = 1 + setGender(NEUTER) + dna.mutantrace = "plant" + greaterform = "Diona" + add_language("Rootspeak") + +/mob/living/carbon/monkey/show_inv(mob/living/carbon/user as mob) + user.set_machine(src) + var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) + var/TAB = "    " + + var/dat = {" + Left Hand: [(l_hand && !( src.l_hand.abstract )) ? l_hand : "Empty"]
    + Right Hand: [(r_hand && !( src.r_hand.abstract )) ? r_hand : "Empty"]
    + "} + + dat += "
    Back: [(back && !(src.back.abstract)) ? back : "Empty"]" + if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) + dat += "
    [TAB]↳[internal ? "Disable Internals" : "Set Internals"]" + + dat += "
    " + + if(canWearHats) + if(hat) + dat += "
    Headwear: [hat] (Remove)" + else + dat += "
    Headwear: Empty" + + dat += "
    Mask: [(wear_mask && !(src.wear_mask.abstract)) ? wear_mask : "Empty"]" + + if(canWearGlasses) + if(glasses) + dat += "
    Glasses: [glasses] (Remove)" + else + dat += "
    Glasses: Empty" + + if(canWearClothes) + if(uniform) + dat += "
    Uniform: [uniform] (Remove)" + else + dat += "
    Uniform: Empty" + + if(handcuffed) + dat += "
    Handcuffed: Remove" + + dat += {" +
    +
    Close + "} + + var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 340, 500) + popup.set_content(dat) + popup.open() + +/mob/living/carbon/monkey/movement_delay() + var/tally = 0 + if(reagents) + if(reagents.has_reagent("hyperzine")) return -1 + + if(reagents.has_reagent("nuka_cola")) return -1 + + var/health_deficiency = (100 - health) + if(health_deficiency >= 45) tally += (health_deficiency / 25) + + if (bodytemperature < 283.222) + tally += (283.222 - bodytemperature) / 10 * 1.75 + + if(istype(loc,/turf/simulated/floor)) + var/turf/simulated/floor/T = loc + + if(T.material=="phazon") + return -1 // Phazon floors make us go fast + + return tally+config.monkey_delay + + +/mob/living/carbon/monkey/proc/wearhat(var/obj/item/clothing/head/H as obj) + if(H) + if(istype(H)) + var/obj/item/clothing/head/oldhat = null + if(hat) + oldhat = hat + hat = null + hat = H + usr.drop_item(hat, src, 1) + regenerate_icons() + if (oldhat) + usr.put_in_hands(oldhat) + else + if(hat) + usr.put_in_hands(hat) + hat = null + regenerate_icons() + +/mob/living/carbon/monkey/proc/wearclothes(var/obj/item/clothing/monkeyclothes/C as obj) + if(C) + if(istype(C)) + var/obj/item/clothing/monkeyclothes/olduniform = null + if(uniform) + olduniform = uniform + uniform = null + uniform = C + usr.drop_item(uniform, src, 1) + regenerate_icons() + if (olduniform) + usr.put_in_hands(olduniform) + else + if(uniform) + usr.put_in_hands(uniform) + uniform = null + regenerate_icons() + +/mob/living/carbon/monkey/proc/wearglasses(var/obj/item/clothing/glasses/G as obj) + if(G) + if(istype(G)) + var/obj/item/clothing/glasses/oldglasses = null + if(glasses) + oldglasses = glasses + glasses = null + glasses = G + usr.drop_item(glasses, src, 1) + regenerate_icons() + if (oldglasses) + usr.put_in_hands(oldglasses) + else + if(glasses) + usr.put_in_hands(glasses) + glasses = null + regenerate_icons() + +/mob/living/carbon/monkey/Topic(href, href_list) + ..() + if (href_list["mach_close"]) + var/t1 = text("window=[]", href_list["mach_close"]) + unset_machine() + src << browse(null, t1) + if ((href_list["item"] && !( usr.stat ) && !( usr.restrained() ) && in_range(src, usr) )) + var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) + O.source = usr + O.target = src + O.item = usr.get_active_hand() + O.s_loc = usr.loc + O.t_loc = loc + O.place = href_list["item"] + requests += O + spawn( 0 ) + O.process() + return + if(href_list["remove_inv"]) + if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + var/remove_from = href_list["remove_inv"] + switch(remove_from) + if("uniform") + if(uniform) + uniform.loc = src.loc + uniform = null + regenerate_icons() + else to_chat(usr, "He has no uniform to remove.") - return - if("hat") - if(hat) - hat.loc = src.loc - hat = null - regenerate_icons() - else + return + if("hat") + if(hat) + hat.loc = src.loc + hat = null + regenerate_icons() + else to_chat(usr, "He has no hat to remove") - return - if("glasses") - if(glasses) - glasses.loc = src.loc - glasses = null - regenerate_icons() - else + return + if("glasses") + if(glasses) + glasses.loc = src.loc + glasses = null + regenerate_icons() + else to_chat(usr, "He has no glasses to remove") - return - show_inv(usr) - else if(href_list["add_inv"]) - if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) - return - - var/add_to = href_list["add_inv"] - if(!usr.get_active_hand()) + return + show_inv(usr) + else if(href_list["add_inv"]) + if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + + var/add_to = href_list["add_inv"] + if(!usr.get_active_hand()) to_chat(usr, "You have nothing in your hand to put on him.") - return - switch(add_to) - if("uniform") - if(uniform) + return + switch(add_to) + if("uniform") + if(uniform) to_chat(usr, "He's already wearing something.") - return - else - wearclothes(usr.get_active_hand()) - if("hat") - if(hat) + return + else + wearclothes(usr.get_active_hand()) + if("hat") + if(hat) to_chat(usr, "He's already wearing something.") - return - else - wearhat(usr.get_active_hand()) - if("glasses") - if(glasses) + return + else + wearhat(usr.get_active_hand()) + if("glasses") + if(glasses) to_chat(usr, "He's already wearing something.") - return - else - wearglasses(usr.get_active_hand()) - show_inv(usr) - ..() - return - -//mob/living/carbon/monkey/bullet_act(var/obj/item/projectile/Proj)taken care of in living - -/mob/living/carbon/monkey/getarmor(var/def_zone, var/type) - - var/armorscore = 0 - if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "head")) - if(hat) - armorscore = hat.armor[type] - else - if(uniform) - armorscore = uniform.armor[type] - return armorscore - -/mob/living/carbon/monkey/attack_paw(mob/M as mob) - ..() - - if (M.a_intent == I_HELP) - help_shake_act(M) - else - if ((M.a_intent == I_HURT && !( istype(wear_mask, /obj/item/clothing/mask/muzzle) ))) - if ((prob(75) && health > 0)) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message("[M.name] has bit [name]!", 1) - var/damage = rand(1, 5) - adjustBruteLoss(damage) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - for(var/datum/disease/D in M.viruses) - if(D.spread == "Bite") - contract_disease(D,1,0) - else - for(var/mob/O in viewers(src, null)) - O.show_message("[M.name] has attempted to bite [name]!", 1) - return - - -/mob/living/carbon/monkey/proc/defense(var/power, var/def_zone) - var/armor = run_armor_check(def_zone, "melee", "Your armor has protected your [def_zone].", "Your armor has softened hit to your [def_zone].") - if(armor >= 2) return 0 - if(!power) return 0 - - var/damage = power - if(armor) - damage = (damage/(armor+1)) - return damage - -/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M as mob) - if (!ticker) + return + else + wearglasses(usr.get_active_hand()) + show_inv(usr) + ..() + return + +//mob/living/carbon/monkey/bullet_act(var/obj/item/projectile/Proj)taken care of in living + +/mob/living/carbon/monkey/getarmor(var/def_zone, var/type) + + var/armorscore = 0 + if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "head")) + if(hat) + armorscore = hat.armor[type] + else + if(uniform) + armorscore = uniform.armor[type] + return armorscore + +/mob/living/carbon/monkey/attack_paw(mob/M as mob) + ..() + + if (M.a_intent == I_HELP) + help_shake_act(M) + else + if ((M.a_intent == I_HURT && !( istype(wear_mask, /obj/item/clothing/mask/muzzle) ))) + if ((prob(75) && health > 0)) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message("[M.name] has bit [name]!", 1) + var/damage = rand(1, 5) + adjustBruteLoss(damage) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + for(var/datum/disease/D in M.viruses) + if(D.spread == "Bite") + contract_disease(D,1,0) + else + for(var/mob/O in viewers(src, null)) + O.show_message("[M.name] has attempted to bite [name]!", 1) + return + + +/mob/living/carbon/monkey/proc/defense(var/power, var/def_zone) + var/armor = run_armor_check(def_zone, "melee", "Your armor has protected your [def_zone].", "Your armor has softened hit to your [def_zone].") + if(armor >= 2) return 0 + if(!power) return 0 + + var/damage = power + if(armor) + damage = (damage/(armor+1)) + return damage + +/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M as mob) + if (!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + if (istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - Weaken(5) - if (stuttering < 5) - stuttering = 5 - Stun(5) - - for(var/mob/O in viewers(src, null)) - if (O.client) - O.show_message("[src] has been touched with the stun gloves by [M]!", 1, "You hear someone fall", 2) - return - else + return + + if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = M.gloves + if(G.cell) + if(M.a_intent == I_HURT)//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + Weaken(5) + if (stuttering < 5) + stuttering = 5 + Stun(5) + + for(var/mob/O in viewers(src, null)) + if (O.client) + O.show_message("[src] has been touched with the stun gloves by [M]!", 1, "You hear someone fall", 2) + return + else to_chat(M, "Not enough charge! ") - return - - if (M.a_intent == I_HELP) - help_shake_act(M) - else - if (M.a_intent == I_HURT) - if ((prob(75) && health > 0)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has punched [name]!", M), 1) - - playsound(loc, "punch", 25, 1, -1) - var/damage = rand(5, 10) - var/dam_zone = "" - if(M.zone_sel && M.zone_sel.selecting) - dam_zone = M.zone_sel.selecting - damage = defense(damage,dam_zone) - if ((damage > 5) && prob(40)) - damage = rand(10, 15) - if (paralysis < 5) - Paralyse(rand(10, 15)) - spawn( 0 ) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has knocked out [name]!", M), 1) - return - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has attempted to punch [name]!", M), 1) - else - if (M.a_intent == I_GRAB) - if (M == src || anchored) - return - - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] has grabbed [name] passively!", M), 1) - else - if (!( paralysis )) - if (prob(25)) - Paralyse(2) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has pushed down [name]!", M), 1) - else - drop_item() - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has disarmed [name]!", M), 1) - return - -/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) + return + + if (M.a_intent == I_HELP) + help_shake_act(M) + else + if (M.a_intent == I_HURT) + if ((prob(75) && health > 0)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has punched [name]!", M), 1) + + playsound(loc, "punch", 25, 1, -1) + var/damage = rand(5, 10) + var/dam_zone = "" + if(M.zone_sel && M.zone_sel.selecting) + dam_zone = M.zone_sel.selecting + damage = defense(damage,dam_zone) + if ((damage > 5) && prob(40)) + damage = rand(10, 15) + if (paralysis < 5) + Paralyse(rand(10, 15)) + spawn( 0 ) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has knocked out [name]!", M), 1) + return + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has attempted to punch [name]!", M), 1) + else + if (M.a_intent == I_GRAB) + if (M == src || anchored) + return + + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] has grabbed [name] passively!", M), 1) + else + if (!( paralysis )) + if (prob(25)) + Paralyse(2) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has pushed down [name]!", M), 1) + else + drop_item() + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has disarmed [name]!", M), 1) + return + +/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + if (!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) + return + + if (istype(loc, /turf) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") - return - - switch(M.a_intent) - if (I_HELP) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M] caresses [src] with its scythe like arm."), 1) - - if (I_HURT) - if ((prob(95) && health > 0)) - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - var/damage = rand(15, 30) - if (damage >= 25) - damage = rand(20, 40) - if (paralysis < 15) - Paralyse(rand(10, 15)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has wounded [name]!", M), 1) - else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has slashed [name]!", M), 1) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has attempted to lunge at [name]!", M), 1) - - if (I_GRAB) - if (M == src) - return - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] has grabbed [name] passively!", M), 1) - - if (I_DISARM) - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - var/damage = 5 - if(prob(95)) - Weaken(15) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has tackled down [name]!", M), 1) - else - drop_item() - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has disarmed [name]!", M), 1) - adjustBruteLoss(damage) - updatehealth() - return - -//using the default attack_animal() in carbon.dm - -/mob/living/carbon/monkey/attack_slime(mob/living/carbon/slime/M as mob) - if (!ticker) + return + + switch(M.a_intent) + if (I_HELP) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[M] caresses [src] with its scythe like arm."), 1) + + if (I_HURT) + if ((prob(95) && health > 0)) + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + var/damage = rand(15, 30) + if (damage >= 25) + damage = rand(20, 40) + if (paralysis < 15) + Paralyse(rand(10, 15)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has wounded [name]!", M), 1) + else + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has slashed [name]!", M), 1) + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has attempted to lunge at [name]!", M), 1) + + if (I_GRAB) + if (M == src) + return + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] has grabbed [name] passively!", M), 1) + + if (I_DISARM) + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + var/damage = 5 + if(prob(95)) + Weaken(15) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has tackled down [name]!", M), 1) + else + drop_item() + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has disarmed [name]!", M), 1) + adjustBruteLoss(damage) + updatehealth() + return + +//using the default attack_animal() in carbon.dm + +/mob/living/carbon/monkey/attack_slime(mob/living/carbon/slime/M as mob) + if (!ticker) to_chat(M, "You cannot attack people before the game has started.") - return - - if(M.Victim) return // can't attack while eating! - - if (health > -100) - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("The [M.name] glomps []!", src), 1) - - var/damage = rand(1, 3) - - if(istype(src, /mob/living/carbon/slime/adult)) - damage = rand(20, 40) - else - damage = rand(5, 35) - - adjustBruteLoss(damage) - - if(M.powerlevel > 0) - var/stunprob = 10 - var/power = M.powerlevel + rand(0,3) - - switch(M.powerlevel) - if(1 to 2) stunprob = 20 - if(3 to 4) stunprob = 30 - if(5 to 6) stunprob = 40 - if(7 to 8) stunprob = 60 - if(9) stunprob = 70 - if(10) stunprob = 95 - - if(prob(stunprob)) - M.powerlevel -= 3 - if(M.powerlevel < 0) - M.powerlevel = 0 - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("The [M.name] has shocked []!", src), 1) - - Weaken(power) - if (stuttering < power) - stuttering = power - Stun(power) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - - if (prob(stunprob) && M.powerlevel >= 8) - adjustFireLoss(M.powerlevel * rand(6,10)) - - - updatehealth() - - return - -/mob/living/carbon/monkey/Stat() - ..() - if(statpanel("Status")) - stat(null, text("Intent: []", a_intent)) - stat(null, text("Move Mode: []", m_intent)) - if(client && mind) - if (client.statpanel == "Status") - if(mind.changeling) - stat("Chemical Storage", mind.changeling.chem_charges) - stat("Genetic Damage Time", mind.changeling.geneticdamage) - return - - -/mob/living/carbon/monkey/verb/removeinternal() - set name = "Remove Internals" - set category = "IC" - internal = null - return - -/mob/living/carbon/monkey/var/co2overloadtime = null -/mob/living/carbon/monkey/var/temperature_resistance = T0C+75 - -/mob/living/carbon/monkey/emp_act(severity) - for(var/obj/item/stickybomb/B in src) - if(B.stuck_to) - visible_message("\the [B] stuck on \the [src] suddenly deactivates itself and falls to the ground.") - B.deactivate() - B.unstick() - - if(flags & INVULNERABLE) - return - - if(wear_id) wear_id.emp_act(severity) - ..() - -/mob/living/carbon/monkey/ex_act(severity) - if(flags & INVULNERABLE) - return - - if(!blinded) - flick("flash", flash) - - switch(severity) - if(1.0) - if (stat != 2) - adjustBruteLoss(200) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if(2.0) - if (stat != 2) - adjustBruteLoss(60) - adjustFireLoss(60) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if(3.0) - if (stat != 2) - adjustBruteLoss(30) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if (prob(50)) - Paralyse(10) - else - return - -/mob/living/carbon/monkey/blob_act() - if(flags & INVULNERABLE) - return - if (stat != 2) - adjustFireLoss(60) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if (prob(50)) - Paralyse(10) - if (stat == DEAD && client) - gib() - return - if (stat == DEAD && !client) - gibs(loc, viruses) - qdel(src) - return - - -/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools - return dexterity_check() - -// Get ALL accesses available. -/mob/living/carbon/monkey/GetAccess() - var/list/ACL=list() - var/obj/item/I = get_active_hand() - if(istype(I)) - ACL |= I.GetAccess() - return ACL - - -/mob/living/carbon/monkey/assess_threat(var/obj/machinery/bot/secbot/judgebot, var/lasercolor) - if(judgebot.emagged == 2) - return 10 //Everyone is a criminal! - var/threatcount = 0 - - //Lasertag bullshit - if(lasercolor) - if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag))) - threatcount += 4 - - if(lasercolor == "r") - if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) - threatcount += 4 - - return threatcount - - //Check for weapons - if(judgebot.weaponscheck) - if(judgebot.check_for_weapons(l_hand)) - threatcount += 4 - if(judgebot.check_for_weapons(r_hand)) - threatcount += 4 - - //Loyalty implants imply trustworthyness - if(isloyal(src)) - threatcount -= 1 - - return threatcount - -/mob/living/carbon/monkey/dexterity_check() - if(stat != CONSCIOUS) - return 0 - if(ticker.mode.name == "monkey") - return 1 - if(reagents.has_reagent("methylin")) - return 1 - return 0 + return + + if(M.Victim) return // can't attack while eating! + + if (health > -100) + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("The [M.name] glomps []!", src), 1) + + var/damage = rand(1, 3) + + if(istype(src, /mob/living/carbon/slime/adult)) + damage = rand(20, 40) + else + damage = rand(5, 35) + + adjustBruteLoss(damage) + + if(M.powerlevel > 0) + var/stunprob = 10 + var/power = M.powerlevel + rand(0,3) + + switch(M.powerlevel) + if(1 to 2) stunprob = 20 + if(3 to 4) stunprob = 30 + if(5 to 6) stunprob = 40 + if(7 to 8) stunprob = 60 + if(9) stunprob = 70 + if(10) stunprob = 95 + + if(prob(stunprob)) + M.powerlevel -= 3 + if(M.powerlevel < 0) + M.powerlevel = 0 + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("The [M.name] has shocked []!", src), 1) + + Weaken(power) + if (stuttering < power) + stuttering = power + Stun(power) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + + if (prob(stunprob) && M.powerlevel >= 8) + adjustFireLoss(M.powerlevel * rand(6,10)) + + + updatehealth() + + return + +/mob/living/carbon/monkey/Stat() + ..() + if(statpanel("Status")) + stat(null, text("Intent: []", a_intent)) + stat(null, text("Move Mode: []", m_intent)) + if(client && mind) + if (client.statpanel == "Status") + if(mind.changeling) + stat("Chemical Storage", mind.changeling.chem_charges) + stat("Genetic Damage Time", mind.changeling.geneticdamage) + return + + +/mob/living/carbon/monkey/verb/removeinternal() + set name = "Remove Internals" + set category = "IC" + internal = null + return + +/mob/living/carbon/monkey/var/co2overloadtime = null +/mob/living/carbon/monkey/var/temperature_resistance = T0C+75 + +/mob/living/carbon/monkey/emp_act(severity) + for(var/obj/item/stickybomb/B in src) + if(B.stuck_to) + visible_message("\the [B] stuck on \the [src] suddenly deactivates itself and falls to the ground.") + B.deactivate() + B.unstick() + + if(flags & INVULNERABLE) + return + + if(wear_id) wear_id.emp_act(severity) + ..() + +/mob/living/carbon/monkey/ex_act(severity) + if(flags & INVULNERABLE) + return + + if(!blinded) + flick("flash", flash) + + switch(severity) + if(1.0) + if (stat != 2) + adjustBruteLoss(200) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if(2.0) + if (stat != 2) + adjustBruteLoss(60) + adjustFireLoss(60) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if(3.0) + if (stat != 2) + adjustBruteLoss(30) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if (prob(50)) + Paralyse(10) + else + return + +/mob/living/carbon/monkey/blob_act() + if(flags & INVULNERABLE) + return + if (stat != 2) + adjustFireLoss(60) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if (prob(50)) + Paralyse(10) + if (stat == DEAD && client) + gib() + return + if (stat == DEAD && !client) + gibs(loc, viruses) + qdel(src) + return + + +/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools + return dexterity_check() + +// Get ALL accesses available. +/mob/living/carbon/monkey/GetAccess() + var/list/ACL=list() + var/obj/item/I = get_active_hand() + if(istype(I)) + ACL |= I.GetAccess() + return ACL + + +/mob/living/carbon/monkey/assess_threat(var/obj/machinery/bot/secbot/judgebot, var/lasercolor) + if(judgebot.emagged == 2) + return 10 //Everyone is a criminal! + var/threatcount = 0 + + //Lasertag bullshit + if(lasercolor) + if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve + if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag))) + threatcount += 4 + + if(lasercolor == "r") + if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag))) + threatcount += 4 + + return threatcount + + //Check for weapons + if(judgebot.weaponscheck) + if(judgebot.check_for_weapons(l_hand)) + threatcount += 4 + if(judgebot.check_for_weapons(r_hand)) + threatcount += 4 + + //Loyalty implants imply trustworthyness + if(isloyal(src)) + threatcount -= 1 + + return threatcount + +/mob/living/carbon/monkey/dexterity_check() + if(stat != CONSCIOUS) + return 0 + if(ticker.mode.name == "monkey") + return 1 + if(reagents.has_reagent("methylin")) + return 1 + return 0 diff --git a/code/modules/mob/living/carbon/monkey/powers.dm b/code/modules/mob/living/carbon/monkey/powers.dm index 7150e080e5d..8015fdf3f82 100644 --- a/code/modules/mob/living/carbon/monkey/powers.dm +++ b/code/modules/mob/living/carbon/monkey/powers.dm @@ -1,7 +1,7 @@ -/mob/living/carbon/monkey/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Object" - var/pipe = start_ventcrawl() - if(pipe) +/mob/living/carbon/monkey/verb/ventcrawl() + set name = "Crawl through Vent" + set desc = "Enter an air vent and crawl through the pipe system." + set category = "Object" + var/pipe = start_ventcrawl() + if(pipe) handle_ventcrawl(pipe) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/say.dm b/code/modules/mob/living/carbon/monkey/say.dm index d60449f72df..4bcacfcd58f 100644 --- a/code/modules/mob/living/carbon/monkey/say.dm +++ b/code/modules/mob/living/carbon/monkey/say.dm @@ -1,13 +1,13 @@ -/mob/living/carbon/monkey/say_quote(var/text) - return "chimpers, [text]"; - -/mob/living/carbon/monkey/say_understands(var/mob/other,var/datum/language/speaking = null) - if(other) other = other.GetSource() - if(issilicon(other)) - return 1 - - if(speaking && speaking.name == "Sol Common") - if(dexterity_check()) - return 1 - +/mob/living/carbon/monkey/say_quote(var/text) + return "chimpers, [text]"; + +/mob/living/carbon/monkey/say_understands(var/mob/other,var/datum/language/speaking = null) + if(other) other = other.GetSource() + if(issilicon(other)) + return 1 + + if(speaking && speaking.name == "Sol Common") + if(dexterity_check()) + return 1 + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm index e8b5774c6de..96fb190974c 100644 --- a/code/modules/mob/living/carbon/monkey/update_icons.dm +++ b/code/modules/mob/living/carbon/monkey/update_icons.dm @@ -1,185 +1,185 @@ -//Monkey Overlays Indexes//////// -#define M_UNIFORM_LAYER 1 -#define M_MASK_LAYER 2 -#define M_BACK_LAYER 3 -#define M_GLASSES_LAYER 4 -#define M_HAT_LAYER 5 -#define M_HANDCUFF_LAYER 6 -#define M_L_HAND_LAYER 7 -#define M_R_HAND_LAYER 8 -#define M_FIRE_LAYER 9 -#define TARGETED_LAYER 10 -#define M_TOTAL_LAYERS 10 -///////////////////////////////// - -/mob/living/carbon/monkey - var/list/overlays_lying[M_TOTAL_LAYERS] - var/list/overlays_standing[M_TOTAL_LAYERS] - -/mob/living/carbon/monkey/regenerate_icons() - ..() - update_inv_uniform(0) - update_inv_wear_mask(0) - update_inv_back(0) - update_inv_glasses(0) - update_inv_hat(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_handcuffed(0) - update_fire() - update_icons() - //Hud Stuff - update_hud() - return - -/mob/living/carbon/monkey/update_icons() - update_hud() - lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again - overlays.len = 0 - for(var/image/I in overlays_standing) - overlays += I - - if(lying) - var/matrix/M = matrix() - M.Turn(90) - M.Translate(1,-6) - src.transform = M - else - var/matrix/M = matrix() - src.transform = M - - -//////// -/mob/living/carbon/monkey/proc/update_inv_uniform(var/update_icons=1) - if(uniform) - var/t_state = uniform.item_state - if(!t_state) t_state = uniform.icon_state - overlays_standing[M_UNIFORM_LAYER] = image("icon" = 'icons/mob/monkey.dmi', "icon_state" = t_state) - else - overlays_standing[M_UNIFORM_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/monkey/proc/update_inv_hat(var/update_icons=1) - if(hat) - var/t_state = hat.icon_state - overlays_standing[M_HAT_LAYER] = image("icon" = 'icons/mob/monkey_head.dmi', "icon_state" = t_state) - else - overlays_standing[M_HAT_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/monkey/update_inv_glasses(var/update_icons=1) - if(glasses) - var/t_state = glasses.icon_state - overlays_standing[M_GLASSES_LAYER] = image("icon" = 'icons/mob/monkey_eyes.dmi', "icon_state" = t_state) - else - overlays_standing[M_GLASSES_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/monkey/update_inv_wear_mask(var/update_icons=1) - if( wear_mask && istype(wear_mask, /obj/item/clothing/mask) ) - overlays_standing[M_MASK_LAYER] = image("icon" = 'icons/mob/monkey.dmi', "icon_state" = "[wear_mask.icon_state]") - wear_mask.screen_loc = ui_monkey_mask - else - overlays_standing[M_MASK_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/monkey/update_inv_r_hand(var/update_icons=1) - if(r_hand) - var/t_state = r_hand.item_state - var/t_inhand_states = r_hand.inhand_states["right_hand"] - if(!t_state) t_state = r_hand.icon_state - overlays_standing[M_R_HAND_LAYER] = image("icon" = t_inhand_states, "icon_state" = t_state) - r_hand.screen_loc = ui_rhand - if (handcuffed) - drop_item(r_hand) - else - overlays_standing[M_R_HAND_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/monkey/update_inv_l_hand(var/update_icons=1) - if(l_hand) - var/t_state = l_hand.item_state - var/t_inhand_state = l_hand.inhand_states["left_hand"] - if(!t_state) t_state = l_hand.icon_state - overlays_standing[M_L_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = t_state) - l_hand.screen_loc = ui_lhand - if (handcuffed) - drop_item(l_hand) - else - overlays_standing[M_L_HAND_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/monkey/update_inv_back(var/update_icons=1) - if(back) - overlays_standing[M_BACK_LAYER] = image("icon" = 'icons/mob/back.dmi', "icon_state" = "[back.icon_state]") - back.screen_loc = ui_monkey_back - else - overlays_standing[M_BACK_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/monkey/update_inv_handcuffed(var/update_icons=1) - if(handcuffed) - drop_hands() - stop_pulling() - overlays_standing[M_HANDCUFF_LAYER] = image("icon" = 'icons/mob/monkey.dmi', "icon_state" = "handcuff1") - else - overlays_standing[M_HANDCUFF_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/monkey/update_hud() - if(client) - client.screen |= contents - - if(m_hat) - if(hat) - m_hat.icon_state = hat.icon_state - else - m_hat.icon_state = "none" - - if(m_suitclothes) - if(uniform) - m_suitclothes.icon_state = uniform.icon_state - else - m_suitclothes.icon_state = "none" - - if(m_glasses) - if(glasses) - m_glasses.icon_state = glasses.icon_state - else - m_glasses.icon_state = "none" - -//Call when target overlay should be added/removed -/mob/living/carbon/monkey/update_targeted(var/update_icons=1) - if (targeted_by && target_locked) - overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - del(target_locked) - if (!targeted_by) - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/monkey/update_fire() - overlays -= overlays_standing[M_FIRE_LAYER] - if(on_fire) - overlays_standing[M_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"= -M_FIRE_LAYER) - overlays += overlays_standing[M_FIRE_LAYER] - else - overlays_standing[M_FIRE_LAYER] = null - -//Monkey Overlays Indexes//////// -#undef M_HAT_LAYER -#undef M_GLASSES_LAYER -#undef M_UNIFORM_LAYER -#undef M_FIRE_LAYER -#undef M_MASK_LAYER -#undef M_BACK_LAYER -#undef M_HANDCUFF_LAYER -#undef M_L_HAND_LAYER -#undef M_R_HAND_LAYER -#undef TARGETED_LAYER -#undef M_TOTAL_LAYERS +//Monkey Overlays Indexes//////// +#define M_UNIFORM_LAYER 1 +#define M_MASK_LAYER 2 +#define M_BACK_LAYER 3 +#define M_GLASSES_LAYER 4 +#define M_HAT_LAYER 5 +#define M_HANDCUFF_LAYER 6 +#define M_L_HAND_LAYER 7 +#define M_R_HAND_LAYER 8 +#define M_FIRE_LAYER 9 +#define TARGETED_LAYER 10 +#define M_TOTAL_LAYERS 10 +///////////////////////////////// + +/mob/living/carbon/monkey + var/list/overlays_lying[M_TOTAL_LAYERS] + var/list/overlays_standing[M_TOTAL_LAYERS] + +/mob/living/carbon/monkey/regenerate_icons() + ..() + update_inv_uniform(0) + update_inv_wear_mask(0) + update_inv_back(0) + update_inv_glasses(0) + update_inv_hat(0) + update_inv_r_hand(0) + update_inv_l_hand(0) + update_inv_handcuffed(0) + update_fire() + update_icons() + //Hud Stuff + update_hud() + return + +/mob/living/carbon/monkey/update_icons() + update_hud() + lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again + overlays.len = 0 + for(var/image/I in overlays_standing) + overlays += I + + if(lying) + var/matrix/M = matrix() + M.Turn(90) + M.Translate(1,-6) + src.transform = M + else + var/matrix/M = matrix() + src.transform = M + + +//////// +/mob/living/carbon/monkey/proc/update_inv_uniform(var/update_icons=1) + if(uniform) + var/t_state = uniform.item_state + if(!t_state) t_state = uniform.icon_state + overlays_standing[M_UNIFORM_LAYER] = image("icon" = 'icons/mob/monkey.dmi', "icon_state" = t_state) + else + overlays_standing[M_UNIFORM_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/monkey/proc/update_inv_hat(var/update_icons=1) + if(hat) + var/t_state = hat.icon_state + overlays_standing[M_HAT_LAYER] = image("icon" = 'icons/mob/monkey_head.dmi', "icon_state" = t_state) + else + overlays_standing[M_HAT_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/monkey/update_inv_glasses(var/update_icons=1) + if(glasses) + var/t_state = glasses.icon_state + overlays_standing[M_GLASSES_LAYER] = image("icon" = 'icons/mob/monkey_eyes.dmi', "icon_state" = t_state) + else + overlays_standing[M_GLASSES_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/monkey/update_inv_wear_mask(var/update_icons=1) + if( wear_mask && istype(wear_mask, /obj/item/clothing/mask) ) + overlays_standing[M_MASK_LAYER] = image("icon" = 'icons/mob/monkey.dmi', "icon_state" = "[wear_mask.icon_state]") + wear_mask.screen_loc = ui_monkey_mask + else + overlays_standing[M_MASK_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/monkey/update_inv_r_hand(var/update_icons=1) + if(r_hand) + var/t_state = r_hand.item_state + var/t_inhand_states = r_hand.inhand_states["right_hand"] + if(!t_state) t_state = r_hand.icon_state + overlays_standing[M_R_HAND_LAYER] = image("icon" = t_inhand_states, "icon_state" = t_state) + r_hand.screen_loc = ui_rhand + if (handcuffed) + drop_item(r_hand) + else + overlays_standing[M_R_HAND_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/monkey/update_inv_l_hand(var/update_icons=1) + if(l_hand) + var/t_state = l_hand.item_state + var/t_inhand_state = l_hand.inhand_states["left_hand"] + if(!t_state) t_state = l_hand.icon_state + overlays_standing[M_L_HAND_LAYER] = image("icon" = t_inhand_state, "icon_state" = t_state) + l_hand.screen_loc = ui_lhand + if (handcuffed) + drop_item(l_hand) + else + overlays_standing[M_L_HAND_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/monkey/update_inv_back(var/update_icons=1) + if(back) + overlays_standing[M_BACK_LAYER] = image("icon" = 'icons/mob/back.dmi', "icon_state" = "[back.icon_state]") + back.screen_loc = ui_monkey_back + else + overlays_standing[M_BACK_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/monkey/update_inv_handcuffed(var/update_icons=1) + if(handcuffed) + drop_hands() + stop_pulling() + overlays_standing[M_HANDCUFF_LAYER] = image("icon" = 'icons/mob/monkey.dmi', "icon_state" = "handcuff1") + else + overlays_standing[M_HANDCUFF_LAYER] = null + if(update_icons) update_icons() + + +/mob/living/carbon/monkey/update_hud() + if(client) + client.screen |= contents + + if(m_hat) + if(hat) + m_hat.icon_state = hat.icon_state + else + m_hat.icon_state = "none" + + if(m_suitclothes) + if(uniform) + m_suitclothes.icon_state = uniform.icon_state + else + m_suitclothes.icon_state = "none" + + if(m_glasses) + if(glasses) + m_glasses.icon_state = glasses.icon_state + else + m_glasses.icon_state = "none" + +//Call when target overlay should be added/removed +/mob/living/carbon/monkey/update_targeted(var/update_icons=1) + if (targeted_by && target_locked) + overlays_standing[TARGETED_LAYER] = target_locked + else if (!targeted_by && target_locked) + del(target_locked) + if (!targeted_by) + overlays_standing[TARGETED_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/monkey/update_fire() + overlays -= overlays_standing[M_FIRE_LAYER] + if(on_fire) + overlays_standing[M_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"= -M_FIRE_LAYER) + overlays += overlays_standing[M_FIRE_LAYER] + else + overlays_standing[M_FIRE_LAYER] = null + +//Monkey Overlays Indexes//////// +#undef M_HAT_LAYER +#undef M_GLASSES_LAYER +#undef M_UNIFORM_LAYER +#undef M_FIRE_LAYER +#undef M_MASK_LAYER +#undef M_BACK_LAYER +#undef M_HANDCUFF_LAYER +#undef M_L_HAND_LAYER +#undef M_R_HAND_LAYER +#undef TARGETED_LAYER +#undef M_TOTAL_LAYERS diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 26c9863bcbc..bebf54830dc 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -1,89 +1,89 @@ - -/* - apply_damage(a,b,c) - args - a:damage - How much damage to take - b:damage_type - What type of damage to take, brute, burn - c:def_zone - Where to take the damage if its brute or burn - Returns - standard 0 if fail -*/ -/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/used_weapon = null) - if(!damage || (blocked >= 2)) return 0 - switch(damagetype) - if(BRUTE) - adjustBruteLoss(damage/(blocked+1)) - if(BURN) - if(M_RESIST_HEAT in mutations) damage = 0 - adjustFireLoss(damage/(blocked+1)) - if(TOX) - adjustToxLoss(damage/(blocked+1)) - if(OXY) - adjustOxyLoss(damage/(blocked+1)) - if(CLONE) - adjustCloneLoss(damage/(blocked+1)) - if(HALLOSS) - adjustHalLoss(damage/(blocked+1)) - updatehealth() - return 1 - - -/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0) - if(blocked >= 2) return 0 - if(brute) apply_damage(brute, BRUTE, def_zone, blocked) - if(burn) apply_damage(burn, BURN, def_zone, blocked) - if(tox) apply_damage(tox, TOX, def_zone, blocked) - if(oxy) apply_damage(oxy, OXY, def_zone, blocked) - if(clone) apply_damage(clone, CLONE, def_zone, blocked) - if(halloss) apply_damage(halloss, HALLOSS, def_zone, blocked) - return 1 - - - -/mob/living/proc/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) - if(!effect || (blocked >= 2)) return 0 - var/altered = 0 - switch(effecttype) - if(STUN) - altered = effect/(blocked+1) - Stun(altered) - if(WEAKEN) - altered = effect/(blocked+1) - Weaken(altered) - if(PARALYZE) - altered = effect/(blocked+1) - Paralyse(altered) - if(AGONY) - altered = effect - halloss += altered // Useful for objects that cause "subdual" damage. PAIN! - if(IRRADIATE) - altered = max((((effect - (effect*(getarmor(null, "rad")/100))))/(blocked+1)),0)//Rads auto check armor - radiation += altered - if(STUTTER) - if(status_flags & CANSTUN) // stun is usually associated with stutter - altered = max(stuttering,(effect/(blocked+1))) - stuttering = altered - if(EYE_BLUR) - altered = max(eye_blurry,(effect/(blocked+1))) - eye_blurry = altered - if(DROWSY) - altered = max(drowsyness,(effect/(blocked+1))) - drowsyness = altered - updatehealth() - return altered - - -/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/agony = 0, var/blocked = 0) - if(blocked >= 2) return 0 - if(stun) apply_effect(stun, STUN, blocked) - if(weaken) apply_effect(weaken, WEAKEN, blocked) - if(paralyze) apply_effect(paralyze, PARALYZE, blocked) - if(irradiate) apply_effect(irradiate, IRRADIATE, blocked) - if(stutter) apply_effect(stutter, STUTTER, blocked) - if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked) - if(drowsy) apply_effect(drowsy, DROWSY, blocked) - if(agony) apply_effect(agony, AGONY, blocked) - return 1 - -/mob/living/ashify() - return //let's not go ashy, shall we? + +/* + apply_damage(a,b,c) + args + a:damage - How much damage to take + b:damage_type - What type of damage to take, brute, burn + c:def_zone - Where to take the damage if its brute or burn + Returns + standard 0 if fail +*/ +/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/used_weapon = null) + if(!damage || (blocked >= 2)) return 0 + switch(damagetype) + if(BRUTE) + adjustBruteLoss(damage/(blocked+1)) + if(BURN) + if(M_RESIST_HEAT in mutations) damage = 0 + adjustFireLoss(damage/(blocked+1)) + if(TOX) + adjustToxLoss(damage/(blocked+1)) + if(OXY) + adjustOxyLoss(damage/(blocked+1)) + if(CLONE) + adjustCloneLoss(damage/(blocked+1)) + if(HALLOSS) + adjustHalLoss(damage/(blocked+1)) + updatehealth() + return 1 + + +/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0) + if(blocked >= 2) return 0 + if(brute) apply_damage(brute, BRUTE, def_zone, blocked) + if(burn) apply_damage(burn, BURN, def_zone, blocked) + if(tox) apply_damage(tox, TOX, def_zone, blocked) + if(oxy) apply_damage(oxy, OXY, def_zone, blocked) + if(clone) apply_damage(clone, CLONE, def_zone, blocked) + if(halloss) apply_damage(halloss, HALLOSS, def_zone, blocked) + return 1 + + + +/mob/living/proc/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) + if(!effect || (blocked >= 2)) return 0 + var/altered = 0 + switch(effecttype) + if(STUN) + altered = effect/(blocked+1) + Stun(altered) + if(WEAKEN) + altered = effect/(blocked+1) + Weaken(altered) + if(PARALYZE) + altered = effect/(blocked+1) + Paralyse(altered) + if(AGONY) + altered = effect + halloss += altered // Useful for objects that cause "subdual" damage. PAIN! + if(IRRADIATE) + altered = max((((effect - (effect*(getarmor(null, "rad")/100))))/(blocked+1)),0)//Rads auto check armor + radiation += altered + if(STUTTER) + if(status_flags & CANSTUN) // stun is usually associated with stutter + altered = max(stuttering,(effect/(blocked+1))) + stuttering = altered + if(EYE_BLUR) + altered = max(eye_blurry,(effect/(blocked+1))) + eye_blurry = altered + if(DROWSY) + altered = max(drowsyness,(effect/(blocked+1))) + drowsyness = altered + updatehealth() + return altered + + +/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/agony = 0, var/blocked = 0) + if(blocked >= 2) return 0 + if(stun) apply_effect(stun, STUN, blocked) + if(weaken) apply_effect(weaken, WEAKEN, blocked) + if(paralyze) apply_effect(paralyze, PARALYZE, blocked) + if(irradiate) apply_effect(irradiate, IRRADIATE, blocked) + if(stutter) apply_effect(stutter, STUTTER, blocked) + if(eyeblur) apply_effect(eyeblur, EYE_BLUR, blocked) + if(drowsy) apply_effect(drowsy, DROWSY, blocked) + if(agony) apply_effect(agony, AGONY, blocked) + return 1 + +/mob/living/ashify() + return //let's not go ashy, shall we? diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 16d61dc9176..b8e905c2ceb 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -1,204 +1,204 @@ - -/* - run_armor_check(a,b) - args - a:def_zone - What part is getting hit, if null will check entire body - b:attack_flag - What type of attack, bullet, laser, energy, melee - - Returns - 0 - no block - 1 - halfblock - 2 - fullblock -*/ -/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/absorb_text = null, var/soften_text = null) - var/armor = getarmor(def_zone, attack_flag) - var/absorb = 0 - if(prob(armor)) - absorb += 1 - if(prob(armor)) - absorb += 1 - if(absorb >= 2) - if(absorb_text) - show_message("[absorb_text]") - else - show_message("Your armor absorbs the blow!") - return 2 - if(absorb == 1) - if(absorb_text) - show_message("[soften_text]",4) - else - show_message("Your armor softens the blow!") - return 1 - return 0 - - -/mob/living/proc/getarmor(var/def_zone, var/type) - return 0 - - -/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone) - var/obj/item/weapon/cloaking_device/C = locate((/obj/item/weapon/cloaking_device) in src) - if(C && C.active) - C.attack_self(src)//Should shut it off - update_icons() + +/* + run_armor_check(a,b) + args + a:def_zone - What part is getting hit, if null will check entire body + b:attack_flag - What type of attack, bullet, laser, energy, melee + + Returns + 0 - no block + 1 - halfblock + 2 - fullblock +*/ +/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/absorb_text = null, var/soften_text = null) + var/armor = getarmor(def_zone, attack_flag) + var/absorb = 0 + if(prob(armor)) + absorb += 1 + if(prob(armor)) + absorb += 1 + if(absorb >= 2) + if(absorb_text) + show_message("[absorb_text]") + else + show_message("Your armor absorbs the blow!") + return 2 + if(absorb == 1) + if(absorb_text) + show_message("[soften_text]",4) + else + show_message("Your armor softens the blow!") + return 1 + return 0 + + +/mob/living/proc/getarmor(var/def_zone, var/type) + return 0 + + +/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone) + var/obj/item/weapon/cloaking_device/C = locate((/obj/item/weapon/cloaking_device) in src) + if(C && C.active) + C.attack_self(src)//Should shut it off + update_icons() to_chat(src, "Your [C.name] was disrupted!") - Stun(2) - - flash_weak_pain() - - if(istype(get_active_hand(),/obj/item/device/assembly/signaler)) - var/obj/item/device/assembly/signaler/signaler = get_active_hand() - if(signaler.deadman && prob(80)) - src.visible_message("[src] triggers their deadman's switch!") - signaler.signal() - - var/absorb = run_armor_check(def_zone, P.flag) - if(absorb >= 2) - P.on_hit(src,2) - return 2 - if(!P.nodamage) - apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, absorb, 0, used_weapon = P) - regenerate_icons() - P.on_hit(src, absorb) - if(istype(P, /obj/item/projectile/beam/lightning)) - if(P.damage >= 200) - src.dust() - return absorb - -/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5,var/dir)//Standardization and logging -Sieve - if(flags & INVULNERABLE) - return - if(istype(AM,/obj/)) - var/obj/O = AM - var/zone = ran_zone("chest",75)//Hits a random part of the body, geared towards the chest - var/dtype = BRUTE - if(istype(O,/obj/item/weapon)) - var/obj/item/weapon/W = O - dtype = W.damtype - src.visible_message("[src] has been hit by [O].") - var/zone_normal_name - switch(zone) - if("l_arm") - zone_normal_name = "left arm" - if("r_arm") - zone_normal_name = "right arm" - if("l_leg") - zone_normal_name = "left leg" - if("r_leg") - zone_normal_name = "right leg" - else - zone_normal_name = zone - var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone_normal_name].", "Your armor has softened hit to your [zone_normal_name].") - if(armor < 2) - apply_damage(O.throwforce*(speed/5), dtype, zone, armor, O.is_sharp(), O) - - // Begin BS12 momentum-transfer code. - - var/client/assailant = directory[ckey(O.fingerprintslast)] - var/mob/M - - if(assailant && assailant.mob && istype(assailant.mob,/mob)) - M = assailant.mob - - if(speed >= 20) - var/obj/item/weapon/W = O - var/momentum = speed/2 - - visible_message("[src] staggers under the impact!","You stagger under the impact!") - src.throw_at(get_edge_target_turf(src,dir),1,momentum) - - if(istype(W.loc,/mob/living) && W.is_sharp()) //Projectile is embedded and suitable for pinning. - - if(!istype(src,/mob/living/carbon/human)) //Handles embedding for non-humans and simple_animals. - O.loc = src - src.embedded += O - - var/turf/T = near_wall(dir,2) - - if(T) - src.loc = T - visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!") - src.anchored = 1 - src.pinned += O - - //Log stuf! - - if(!O.fingerprintslast) - return - - src.attack_log += text("\[[time_stamp()]\] Has been hit with a thrown [O], last touched by [M.name] ([assailant.ckey]) (speed: [speed])") - M.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with a thrown [O] (speed: [speed])") - msg_admin_attack("[src.name] ([src.ckey]) was hit by a thrown [O], last touched by [M.name] ([assailant.ckey]) (speed: [speed]) (JMP)") - if(!iscarbon(M)) - src.LAssailant = null - else - src.LAssailant = M - - - -/mob/living/proc/near_wall(var/direction,var/distance=1) - var/turf/T = get_step(get_turf(src),direction) - var/turf/last_turf = src.loc - var/i = 1 - - while(i>0 && i<=distance) - if(T.density) //Turf is a wall! - return last_turf - i++ - last_turf = T - T = get_step(T,direction) - - return 0 - -// End BS12 momentum-transfer code. -//Mobs on Fire -/mob/living/proc/IgniteMob() - if(fire_stacks > 0 && !on_fire) - on_fire = 1 - set_light(src.light_range + 3) - update_fire() - -/mob/living/proc/ExtinguishMob() - if(on_fire) - on_fire = 0 - fire_stacks = 0 - set_light(src.light_range - 3) - update_fire() - -/mob/living/proc/update_fire() - return - -/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person - fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20) - -/mob/living/proc/handle_fire() - if((flags & INVULNERABLE) && on_fire) - extinguish() - if(fire_stacks < 0) - fire_stacks++ //If we've doused ourselves in water to avoid fire, dry off slowly - fire_stacks = min(0, fire_stacks)//So we dry ourselves back to default, nonflammable. - if(!on_fire) - return 1 - - var/oxy=0 - var/turf/T=loc - if(istype(T)) - var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment - if(G) - oxy=G.oxygen - if(oxy < 1 || fire_stacks <= 0) - ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire - return 1 - var/turf/location = get_turf(src) - location.hotspot_expose(700, 50, 1,surfaces=1) - - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(H.mind && H.mind.vampire && H.stat == DEAD) - dust() - -/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - adjust_fire_stacks(0.5) - IgniteMob() - -//Mobs on Fire end + Stun(2) + + flash_weak_pain() + + if(istype(get_active_hand(),/obj/item/device/assembly/signaler)) + var/obj/item/device/assembly/signaler/signaler = get_active_hand() + if(signaler.deadman && prob(80)) + src.visible_message("[src] triggers their deadman's switch!") + signaler.signal() + + var/absorb = run_armor_check(def_zone, P.flag) + if(absorb >= 2) + P.on_hit(src,2) + return 2 + if(!P.nodamage) + apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, absorb, 0, used_weapon = P) + regenerate_icons() + P.on_hit(src, absorb) + if(istype(P, /obj/item/projectile/beam/lightning)) + if(P.damage >= 200) + src.dust() + return absorb + +/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5,var/dir)//Standardization and logging -Sieve + if(flags & INVULNERABLE) + return + if(istype(AM,/obj/)) + var/obj/O = AM + var/zone = ran_zone("chest",75)//Hits a random part of the body, geared towards the chest + var/dtype = BRUTE + if(istype(O,/obj/item/weapon)) + var/obj/item/weapon/W = O + dtype = W.damtype + src.visible_message("[src] has been hit by [O].") + var/zone_normal_name + switch(zone) + if("l_arm") + zone_normal_name = "left arm" + if("r_arm") + zone_normal_name = "right arm" + if("l_leg") + zone_normal_name = "left leg" + if("r_leg") + zone_normal_name = "right leg" + else + zone_normal_name = zone + var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone_normal_name].", "Your armor has softened hit to your [zone_normal_name].") + if(armor < 2) + apply_damage(O.throwforce*(speed/5), dtype, zone, armor, O.is_sharp(), O) + + // Begin BS12 momentum-transfer code. + + var/client/assailant = directory[ckey(O.fingerprintslast)] + var/mob/M + + if(assailant && assailant.mob && istype(assailant.mob,/mob)) + M = assailant.mob + + if(speed >= 20) + var/obj/item/weapon/W = O + var/momentum = speed/2 + + visible_message("[src] staggers under the impact!","You stagger under the impact!") + src.throw_at(get_edge_target_turf(src,dir),1,momentum) + + if(istype(W.loc,/mob/living) && W.is_sharp()) //Projectile is embedded and suitable for pinning. + + if(!istype(src,/mob/living/carbon/human)) //Handles embedding for non-humans and simple_animals. + O.loc = src + src.embedded += O + + var/turf/T = near_wall(dir,2) + + if(T) + src.loc = T + visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!") + src.anchored = 1 + src.pinned += O + + //Log stuf! + + if(!O.fingerprintslast) + return + + src.attack_log += text("\[[time_stamp()]\] Has been hit with a thrown [O], last touched by [M.name] ([assailant.ckey]) (speed: [speed])") + M.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with a thrown [O] (speed: [speed])") + msg_admin_attack("[src.name] ([src.ckey]) was hit by a thrown [O], last touched by [M.name] ([assailant.ckey]) (speed: [speed]) (JMP)") + if(!iscarbon(M)) + src.LAssailant = null + else + src.LAssailant = M + + + +/mob/living/proc/near_wall(var/direction,var/distance=1) + var/turf/T = get_step(get_turf(src),direction) + var/turf/last_turf = src.loc + var/i = 1 + + while(i>0 && i<=distance) + if(T.density) //Turf is a wall! + return last_turf + i++ + last_turf = T + T = get_step(T,direction) + + return 0 + +// End BS12 momentum-transfer code. +//Mobs on Fire +/mob/living/proc/IgniteMob() + if(fire_stacks > 0 && !on_fire) + on_fire = 1 + set_light(src.light_range + 3) + update_fire() + +/mob/living/proc/ExtinguishMob() + if(on_fire) + on_fire = 0 + fire_stacks = 0 + set_light(src.light_range - 3) + update_fire() + +/mob/living/proc/update_fire() + return + +/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person + fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20) + +/mob/living/proc/handle_fire() + if((flags & INVULNERABLE) && on_fire) + extinguish() + if(fire_stacks < 0) + fire_stacks++ //If we've doused ourselves in water to avoid fire, dry off slowly + fire_stacks = min(0, fire_stacks)//So we dry ourselves back to default, nonflammable. + if(!on_fire) + return 1 + + var/oxy=0 + var/turf/T=loc + if(istype(T)) + var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment + if(G) + oxy=G.oxygen + if(oxy < 1 || fire_stacks <= 0) + ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire + return 1 + var/turf/location = get_turf(src) + location.hotspot_expose(700, 50, 1,surfaces=1) + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.mind && H.mind.vampire && H.stat == DEAD) + dust() + +/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + adjust_fire_stacks(0.5) + IgniteMob() + +//Mobs on Fire end diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 5b68362e85f..c38060ecc35 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -1,75 +1,75 @@ -/mob/living - see_invisible = SEE_INVISIBLE_LIVING - - //Health and life related vars - var/maxHealth = 100 //Maximum health that should be possible. - var/health = 100 //A mob's health - - var/hud_updateflag = 0 - - size = SIZE_NORMAL - - //Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS - var/bruteloss = 0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage) - var/oxyloss = 0 //Oxygen depravation damage (no air in lungs) - var/toxloss = 0 //Toxic damage caused by being poisoned or radiated - var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt. - var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims - var/brainloss = 0 //'Retardation' damage caused by someone hitting you in the head with a bible or being infected with brainrot. - var/halloss = 0 //Hallucination damage. 'Fake' damage obtained through hallucinating or the holodeck. Sleeping should cause it to wear off. - - var/hallucination = 0 //Directly affects how long a mob will hallucinate for - var/list/atom/hallucinations = list() //A list of hallucinated people that try to attack the mob. See /obj/effect/fake_attacker in hallucinations.dm - - var/can_butcher = 1 //Whether it's possible to butcher this mob manually - var/meat_taken = 0 //How much meat has been taken from this mob by butchering - var/meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat - var/being_butchered = 0 //To prevent butchering an animal almost instantly - var/list/butchering_drops //See code/datums/butchering.dm, stuff like skinning goes here - - var/list/image/static_overlays - - var/t_plasma = null - var/t_oxygen = null - var/t_sl_gas = null - var/t_n2 = null - - var/now_pushing = null - var/mob_bump_flag = 0 - var/mob_swap_flags = 0 - var/mob_push_flags = 0 - - var/cameraFollow = null - - var/tod = null // Time of death - var/update_slimes = 1 - - on_fire = 0 //The "Are we on fire?" var - var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20 - - var/specialsauce = 0 //Has this person consumed enough special sauce? IF so they're a ticking time bomb of death. - - var/implanting = 0 //Used for the mind-slave implant - var/silent = null //Can't talk. Value goes down every life proc. - - var/locked_to_z = 0 // Locked to a Z-level if nonzero. - - // Fix ashifying in hot fires. - //autoignition_temperature=0 - //fire_fuel=0 - - var/list/icon/pipes_shown = list() - var/last_played_vent - var/is_ventcrawling = 0 - - var/species_type - var/holder_type = /obj/item/weapon/holder/animal //When picked up, put us into a holder of this type. Dionae use /obj/item/weapon/holder/diona, others - the default one - //Set to null to prevent people from picking this mob up! - // - var/list/callOnLife = list() // - var/obj/screen/schematics_background - var/shown_schematics_background = 0 - -/mob/living/proc/unsubLife(datum/sub) - while("\ref[sub]" in callOnLife) - callOnLife -= "\ref[sub]" +/mob/living + see_invisible = SEE_INVISIBLE_LIVING + + //Health and life related vars + var/maxHealth = 100 //Maximum health that should be possible. + var/health = 100 //A mob's health + + var/hud_updateflag = 0 + + size = SIZE_NORMAL + + //Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS + var/bruteloss = 0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage) + var/oxyloss = 0 //Oxygen depravation damage (no air in lungs) + var/toxloss = 0 //Toxic damage caused by being poisoned or radiated + var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt. + var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims + var/brainloss = 0 //'Retardation' damage caused by someone hitting you in the head with a bible or being infected with brainrot. + var/halloss = 0 //Hallucination damage. 'Fake' damage obtained through hallucinating or the holodeck. Sleeping should cause it to wear off. + + var/hallucination = 0 //Directly affects how long a mob will hallucinate for + var/list/atom/hallucinations = list() //A list of hallucinated people that try to attack the mob. See /obj/effect/fake_attacker in hallucinations.dm + + var/can_butcher = 1 //Whether it's possible to butcher this mob manually + var/meat_taken = 0 //How much meat has been taken from this mob by butchering + var/meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + var/being_butchered = 0 //To prevent butchering an animal almost instantly + var/list/butchering_drops //See code/datums/butchering.dm, stuff like skinning goes here + + var/list/image/static_overlays + + var/t_plasma = null + var/t_oxygen = null + var/t_sl_gas = null + var/t_n2 = null + + var/now_pushing = null + var/mob_bump_flag = 0 + var/mob_swap_flags = 0 + var/mob_push_flags = 0 + + var/cameraFollow = null + + var/tod = null // Time of death + var/update_slimes = 1 + + on_fire = 0 //The "Are we on fire?" var + var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20 + + var/specialsauce = 0 //Has this person consumed enough special sauce? IF so they're a ticking time bomb of death. + + var/implanting = 0 //Used for the mind-slave implant + var/silent = null //Can't talk. Value goes down every life proc. + + var/locked_to_z = 0 // Locked to a Z-level if nonzero. + + // Fix ashifying in hot fires. + //autoignition_temperature=0 + //fire_fuel=0 + + var/list/icon/pipes_shown = list() + var/last_played_vent + var/is_ventcrawling = 0 + + var/species_type + var/holder_type = /obj/item/weapon/holder/animal //When picked up, put us into a holder of this type. Dionae use /obj/item/weapon/holder/diona, others - the default one + //Set to null to prevent people from picking this mob up! + // + var/list/callOnLife = list() // + var/obj/screen/schematics_background + var/shown_schematics_background = 0 + +/mob/living/proc/unsubLife(datum/sub) + while("\ref[sub]" in callOnLife) + callOnLife -= "\ref[sub]" diff --git a/code/modules/mob/living/logout.dm b/code/modules/mob/living/logout.dm index 0349cb4a32e..ff64ccf42ae 100644 --- a/code/modules/mob/living/logout.dm +++ b/code/modules/mob/living/logout.dm @@ -1,9 +1,9 @@ -/mob/living/Logout() - ..() - if (mind) - if(!key) //key and mind have become seperated. - mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body. - /* VG EDIT - if(!immune_to_ssd && sleeping < 2 && mind.active) - sleeping = 2 //This causes instant sleep, but does not prolong it. See life.dm for furthering SSD. +/mob/living/Logout() + ..() + if (mind) + if(!key) //key and mind have become seperated. + mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body. + /* VG EDIT + if(!immune_to_ssd && sleeping < 2 && mind.active) + sleeping = 2 //This causes instant sleep, but does not prolong it. See life.dm for furthering SSD. */ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 14fd33b5fcf..a6be35d9420 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1,847 +1,847 @@ -var/list/ai_list = list() - -//Not sure why this is necessary... -/proc/AutoUpdateAI(obj/subject) - var/is_in_use = 0 - if (subject!=null) - for(var/A in ai_list) - var/mob/living/silicon/ai/M = A - if ((M.client && M.machine == subject)) - is_in_use = 1 - subject.attack_ai(M) - return is_in_use - - -/mob/living/silicon/ai - name = "AI" - icon = 'icons/mob/AI.dmi'// - icon_state = "ai" - anchored = 1 // -- TLE - density = 1 - status_flags = CANSTUN|CANPARALYSE - force_compose = 1 - size = SIZE_BIG - - var/list/network = list("SS13") - var/obj/machinery/camera/current = null - 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] - var/icon/holo_icon//Default is assigned when AI is created. - var/obj/item/device/pda/ai/aiPDA = null - var/obj/item/device/multitool/aiMulti = null - var/custom_sprite = 0 //For our custom sprites - var/obj/item/device/camera/ai_camera/aicamera = null -//Hud stuff - - //MALFUNCTION - var/datum/module_picker/malf_picker - var/processing_time = 100 - var/list/datum/AI_Module/current_modules = list() - var/ai_flags = 0 - - var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE - var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite - - var/obj/machinery/power/apc/malfhack = null - var/explosive = 0 //does the AI explode when it dies? - - var/mob/living/silicon/ai/parent = null - var/camera_light_on = 0 - var/list/obj/machinery/camera/lit_cameras = list() - - var/datum/trackable/track = new() - - var/last_paper_seen = null - var/can_shunt = 1 - var/last_announcement = "" - -/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) - var/list/possibleNames = ai_names - - var/pickedName = null - while(!pickedName) - pickedName = pick(ai_names) - for (var/mob/living/silicon/ai/A in mob_list) - if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop - possibleNames -= pickedName - pickedName = null - add_language(LANGUAGE_SOL_COMMON, 1) - add_language(LANGUAGE_UNATHI, 1) - add_language(LANGUAGE_SIIK_TAJR, 1) - add_language(LANGUAGE_SKRELLIAN, 1) - add_language(LANGUAGE_ROOTSPEAK, 1) - add_language(LANGUAGE_GUTTER, 1) - add_language(LANGUAGE_CLATTER, 1) - add_language(LANGUAGE_GREY, 1) - add_language(LANGUAGE_MONKEY, 1) - add_language(LANGUAGE_VOX, 1) - add_language(LANGUAGE_TRADEBAND, 1) - default_language = all_languages[LANGUAGE_SOL_COMMON] - real_name = pickedName - name = real_name - anchored = 1 - canmove = 0 - density = 1 - loc = loc - - radio = new /obj/item/device/radio/borg/ai(src) - radio.recalculateChannels() - - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) - - proc_holder_list = new() - - //Determine the AI's lawset - if(L && istype(L,/datum/ai_laws)) src.laws = L - else src.laws = getLawset(src) - - verbs += /mob/living/silicon/ai/proc/show_laws_verb - - aiPDA = new/obj/item/device/pda/ai(src) - aiPDA.owner = name - aiPDA.ownjob = "AI" - aiPDA.name = name + " (" + aiPDA.ownjob + ")" - - aiMulti = new(src) - aicamera = new/obj/item/device/camera/ai_camera(src) - - if (istype(loc, /turf)) - verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ - /mob/living/silicon/ai/proc/ai_statuschange, \ - /mob/living/silicon/ai/proc/ai_hologram_change) - - if(!safety)//Only used by AIize() to successfully spawn an AI. - if (!B)//If there is no player/brain inside. - new/obj/structure/AIcore/deactivated(loc)//New empty terminal. - qdel(src)//Delete AI. - return - else - if (B.brainmob.mind) - B.brainmob.mind.transfer_to(src) - - to_chat(src, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).") - to_chat(src, "To look at other parts of the station, click on yourself to get a camera menu.") - to_chat(src, "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.") - to_chat(src, "To use something, simply click on it.") - to_chat(src, "Use say :b to speak to your cyborgs through binary.") - if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai))) - show_laws() - to_chat(src, "These laws may be changed by other players, or by you being the traitor.") - - job = "AI" - ai_list += src - ..() - return - -/mob/living/silicon/ai/verb/radio_interact() - set category = "AI Commands" - set name = "Radio Configuration" - if(stat || aiRestorePowerRoutine) return - radio.recalculateChannels() - radio.attack_self(usr) - -/mob/living/silicon/ai/verb/rename_photo() //This is horrible but will do for now - set category = "AI Commands" - set name = "Modify Photo Files" - if(stat || aiRestorePowerRoutine) - return - - var/list/nametemp = list() - var/find - var/datum/picture/selection - if(aicamera.aipictures.len == 0) - to_chat(usr, "No images saved") - return - for(var/datum/picture/t in aicamera.aipictures) - nametemp += t.fields["name"] - find = input("Select image to delete or rename.", "Photo Modification") in nametemp - for(var/datum/picture/q in aicamera.aipictures) - if(q.fields["name"] == find) - selection = q - break - - if(!selection) return - var/choice = input(usr, "Would you like to rename or delete [selection.fields["name"]]?", "Photo Modification") in list("Rename","Delete","Cancel") - switch(choice) - if("Cancel") - return - if ("Delete") - aicamera.aipictures.Remove(selection) - qdel(selection) - if("Rename") - var/new_name = sanitize(input(usr, "Write a new name for [selection.fields["name"]]:","Photo Modification")) - if(length(new_name) > 0) - selection.fields["name"] = new_name - else - to_chat(usr, "You must write a name.") - -/mob/living/silicon/ai/verb/pick_icon() - set category = "AI Commands" - set name = "Set AI Core Display" - if(stat || aiRestorePowerRoutine) - return - /* Jesus christ, more of this shit? - if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var - var/file = file2text("config/custom_sprites.txt") - var/lines = text2list(file, "\n") - - for(var/line in lines) - // split & clean up - var/list/Entry = text2list(line, "-") - for(var/i = 1 to Entry.len) - Entry[i] = trim(Entry[i]) - - if(Entry.len < 2) - continue; - - if(Entry[1] == src.ckey && Entry[2] == src.real_name) - custom_sprite = 1 //They're in the list? Custom sprite time - icon = 'icons/mob/custom-synthetic.dmi' - */ - //if(icon_state == initial(icon_state)) - var/icontype = "" - /* Nuked your hidden shit.*/ - if (custom_sprite == 1) icontype = ("Custom")//automagically selects custom sprite if one is available - else icontype = input("Select an icon!", "AI", null, null) as null|anything in list("Monochrome", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Broken Output", "Triumvirate", "Triumvirate Static", "Searif", "Ravensdale", "Serithi", "Static", "Wasp", "Robert House", "Red October", "Fabulous", "Girl", "Girl Malf", "Boy", "Boy Malf", "Four-Leaf", "Yes Man", "Hourglass", "Patriot", "Pirate", "Royal") - switch(icontype) - if("Custom") icon_state = "[src.ckey]-ai" - if("Clown") icon_state = "ai-clown2" - if("Monochrome") icon_state = "ai-mono" - if("Inverted") icon_state = "ai-u" - if("Firewall") icon_state = "ai-magma" - if("Green") icon_state = "ai-wierd" - if("Red") icon_state = "ai-malf" - if("Broken Output") icon_state = "ai-static" - if("Text") icon_state = "ai-text" - if("Smiley") icon_state = "ai-smiley" - if("Matrix") icon_state = "ai-matrix" - if("Angry") icon_state = "ai-angryface" - if("Dorf") icon_state = "ai-dorf" - if("Bliss") icon_state = "ai-bliss" - if("Triumvirate") icon_state = "ai-triumvirate" - if("Triumvirate Static") icon_state = "ai-triumvirate-malf" - if("Searif") icon_state = "ai-searif" - if("Ravensdale") icon_state = "ai-ravensdale" - if("Serithi") icon_state = "ai-serithi" - if("Static") icon_state = "ai-fuzz" - if("Wasp") icon_state = "ai-wasp" - if("Robert House") icon_state = "ai-president" - if("Red October") icon_state = "ai-soviet" - if("Girl") icon_state = "ai-girl" - if("Girl Malf") icon_state = "ai-girl-malf" - if("Boy") icon_state = "ai-boy" - if("Boy Malf") icon_state = "ai-boy-malf" - if("Fabulous") icon_state = "ai-fabulous" - if("Four-Leaf") icon_state = "ai-4chan" - if("Yes Man") icon_state = "yes-man" - if("Hourglass") icon_state = "ai-hourglass" - if("Patriot") icon_state = "ai-patriot" - if("Pirate") icon_state = "ai-pirate" - if("Royal") icon_state = "ai-royal" - else icon_state = "ai" - //else -// to_chat(usr, "You can only change your display once!") - //return - - -// displays the malf_ai information if the AI is the malf -/mob/living/silicon/ai/show_malf_ai() - if(ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) - if (mind == malfai) // are we the evil one? - if (malf.apcs >= 3) - stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") - - -/mob/living/silicon/ai/proc/ai_alerts() - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\ai\ai.dm:195: var/dat = "Current Station Alerts\n" - var/dat = {"Current Station Alerts\n -Close

    "} - // END AUTOFIX - 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] - 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) - dat += "
    \n" - else - dat += "-- All Systems Nominal
    \n" - dat += "
    \n" - - viewalerts = 1 - src << browse(dat, "window=aialerts&can_close=0") - -// this verb lets the ai see the stations manifest -/mob/living/silicon/ai/proc/ai_roster() - show_station_manifest() - -/mob/living/silicon/ai/proc/ai_call_shuttle() - if(src.stat == 2) - to_chat(src, "You can't call the shuttle because you are dead!") - return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - to_chat(usr, "Wireless control is disabled!") - return - - var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No") - - if(confirm == "Yes") - var/justification = stripped_input(usr, "Please input a concise justification for the shuttle call. Note that failure to properly justify a shuttle call may lead to recall or termination", "Nanotrasen Anti-Comdom Systems") - call_shuttle_proc(src, justification) - - // hack to display shuttle timer - if(emergency_shuttle.online) - var/obj/machinery/computer/communications/C = locate() in machines - if(C) - C.post_status("shuttle") - - return - -/mob/living/silicon/ai/proc/ai_cancel_call() - set category = "AI Commands" - - if(src.stat == 2) - to_chat(src, "You can't send the shuttle back because you are dead!") - return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - to_chat(src, "Wireless control is disabled!") - return - recall_shuttle(src) - -/mob/living/silicon/ai/check_eye(var/mob/user as mob) - if (!current) - return null - user.reset_view(current) - return 1 - -/mob/living/silicon/ai/blob_act() - if(flags & INVULNERABLE) - return - if (stat != 2) - adjustBruteLoss(60) - updatehealth() - return 1 - return 0 - -/mob/living/silicon/ai/restrained() - if(timestopped) return 1 //under effects of time magick - return 0 - -/mob/living/silicon/ai/emp_act(severity) - if(flags & INVULNERABLE) - return - - if (prob(30)) - switch(pick(1,2)) - if(1) - view_core() - if(2) - ai_call_shuttle() - ..() - -/mob/living/silicon/ai/ex_act(severity) - if(flags & INVULNERABLE) - return - - if(!blinded) - flick("flash", flash) - - switch(severity) - if(1.0) - if (stat != 2) - adjustBruteLoss(100) - adjustFireLoss(100) - if(2.0) - if (stat != 2) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3.0) - if (stat != 2) - adjustBruteLoss(30) - - updatehealth() - - -/mob/living/silicon/ai/Topic(href, href_list) - if(usr != src) - return - ..() - if (href_list["mach_close"]) - if (href_list["mach_close"] == "aialerts") - viewalerts = 0 - var/t1 = text("window=[]", href_list["mach_close"]) - unset_machine() - src << browse(null, t1) - if (href_list["switchcamera"]) - switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras - if (href_list["showalerts"]) - ai_alerts() - - if(href_list["show_paper"]) - if(last_paper_seen) - src << browse(last_paper_seen, "window=show_paper") - //Carn: holopad requests - if (href_list["jumptoholopad"]) - var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"]) - if(stat == CONSCIOUS) - if(H) - H.attack_ai(src) //may as well recycle - else - to_chat(src, "Unable to locate the holopad.") - - if(href_list["say_word"]) - play_vox_word(href_list["say_word"], null, src) - return - - if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite - var/L = text2num(href_list["lawc"]) - switch(lawcheck[L+1]) - if ("Yes") lawcheck[L+1] = "No" - if ("No") lawcheck[L+1] = "Yes" -// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) - checklaws() - - if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite - var/L = text2num(href_list["lawi"]) - switch(ioncheck[L]) - if ("Yes") ioncheck[L] = "No" - if ("No") ioncheck[L] = "Yes" -// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) - checklaws() - - if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite - statelaws() - - 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) - return - - else if (href_list["faketrack"]) - 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.cameraFollow = target - to_chat(A, text("Now tracking [] on camera.", target.name)) - if (usr.machine == null) - usr.machine = usr - - while (src.cameraFollow == target) - to_chat(usr, "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb).") - sleep(40) - continue - - return - - if (href_list["open"]) - var/mob/target = locate(href_list["open"]) - var/mob/living/silicon/ai/A = locate(href_list["open2"]) - if(A && target) - A.open_nearest_door(target) - return - - return - -/mob/living/silicon/ai/bullet_act(var/obj/item/projectile/Proj) - ..(Proj) - updatehealth() - return 2 - -/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - to_chat(M, "You cannot attack people before the game has started.") - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - to_chat(M, "No attacking people at spawn, you jackass.") - return - - switch(M.a_intent) - - if (I_HELP) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M] caresses [src]'s plating with its scythe like arm."), 1) - - else //harm - var/damage = rand(10, 20) - if (prob(90)) - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has slashed at []!", M, src), 1) - if(prob(8)) - flick("noise", flash) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] took a swipe at []!", M, src), 1) - return - -/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob) - if(!istype(M)) - return - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("[M] [M.attacktext] [src]!", 1) - M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) - updatehealth() - -/mob/living/silicon/ai/reset_view(atom/A) - if (camera_light_on) - light_cameras() - if(istype(A,/obj/machinery/camera)) - current = A - ..() - - -/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) - - - src.cameraFollow = null - - if (!C || stat == 2) //C.can_use()) - return 0 - - if(!src.eyeobj) - view_core() - return - // ok, we're alive, camera is good and in our network... - eyeobj.forceMove(get_turf(C)) - //machine = src - - return 1 - -/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource) - 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) - 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) - queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0) - if (viewalerts) ai_alerts() - return !cleared - -/mob/living/silicon/ai/cancel_camera() - src.view_core() - - -//Replaces /mob/living/silicon/ai/verb/change_network() in ai.dm & camera.dm -//Adds in /mob/living/silicon/ai/proc/ai_network_change() instead -//Addition by Mord_Sith to define AI's network change ability -/mob/living/silicon/ai/proc/ai_network_change() - set category = "AI Commands" - set name = "Jump To Network" - unset_machine() - src.cameraFollow = null - var/cameralist[0] - - if(usr.isDead()) - to_chat(usr, "You can't change your camera network because you are dead!") - return - - var/mob/living/silicon/ai/U = usr - - for (var/obj/machinery/camera/C in cameranet.cameras) - if(!C.can_use()) - continue - - var/list/tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS,1) - if(tempnetwork.len) - for(var/i in tempnetwork) - cameralist[i] = i - var/old_network = network - network = input(U, "Which network would you like to view?") as null|anything in cameralist - - if(!U.eyeobj) - U.view_core() - return - - if(isnull(network)) - network = old_network // If nothing is selected - else - for(var/obj/machinery/camera/C in cameranet.cameras) - if(!C.can_use()) - continue - if(network in C.network) - U.eyeobj.forceMove(get_turf(C)) - break - to_chat(src, "Switched to [network] camera network.") -//End of code by Mord_Sith - - -/mob/living/silicon/ai/proc/choose_modules() - set category = "Malfunction" - set name = "Choose Module" - - malf_picker.use(src) - -/mob/living/silicon/ai/proc/ai_statuschange() - set category = "AI Commands" - set name = "AI Status" - - if(usr.isDead()) - to_chat(usr, "You cannot change your emotional status because you are dead!") - return - - var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions //ai_emotions can be found in code/game/machinery/status_display.dm @ 213 (above the AI status display) - - for (var/obj/machinery/M in status_displays) //change status - if(istype(M, /obj/machinery/ai_status_display)) - var/obj/machinery/ai_status_display/AISD = M - AISD.emotion = emote - //if Friend Computer, change ALL displays - else if(istype(M, /obj/machinery/status_display)) - - var/obj/machinery/status_display/SD = M - if(emote=="Friend Computer") - SD.friendc = 1 - else - SD.friendc = 0 - return - -//I am the icon meister. Bow fefore me. //>fefore -/mob/living/silicon/ai/proc/ai_hologram_change() - set name = "Change Hologram" - set desc = "Change the default hologram available to AI to something else." - set category = "AI Commands" - - var/input - if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member") - - var/personnel_list[] = list() - - for(var/datum/data/record/t in data_core.locked)//Look in data core locked. - personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image. - - if(personnel_list.len) - input = input("Select a crew member:") as null|anything in personnel_list - var/icon/character_icon = personnel_list[input] - if(character_icon) - qdel(holo_icon)//Clear old icon so we're not storing it in memory. - holo_icon = getHologramIcon(icon(character_icon)) - else - alert("No suitable records found. Aborting.") - - else - var/icon_list[] = list( - "Default", - "Floating face", - "Cortano", - "Spoopy", - "343", - "Auto", - "Four-Leaf", - "Yotsuba", - "Girl", - "Boy", - "SHODAN" - ) - input = input("Please select a hologram:") as null|anything in icon_list - if(input) - qdel(holo_icon) - holo_icon = null - switch(input) - if("Default") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) - if("Floating face") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2")) - if("Cortano") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) - if("Spoopy") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) - if("343") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo5")) - if("Auto") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo6")) - if("Four-Leaf") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo7")) - if("Yotsuba") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo8")) - if("Girl") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo9")) - if("Boy") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo10")) - if("SHODAN") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo11")) - - return - -/mob/living/silicon/ai/proc/corereturn() - set category = "Malfunction" - set name = "Return to Main Core" - - var/obj/machinery/power/apc/apc = src.loc - if(!istype(apc)) - to_chat(src, "You are already in your Main Core.") - return - apc.malfvacate() - -//Toggles the luminosity and applies it by re-entereing the camera. -/mob/living/silicon/ai/verb/toggle_camera_light() - set name = "Toggle Camera Light" - set desc = "Toggle internal infrared camera light" - set category = "AI Commands" - if(stat != CONSCIOUS) - return - - camera_light_on = !camera_light_on - - if (!camera_light_on) - to_chat(src, "Camera lights deactivated.") - - for (var/obj/machinery/camera/C in lit_cameras) - C.set_light(0) - lit_cameras = list() - - return - - light_cameras() - - to_chat(src, "Camera lights activated.") - return - -//AI_CAMERA_LUMINOSITY - -/mob/living/silicon/ai/proc/light_cameras() - var/list/obj/machinery/camera/add = list() - var/list/obj/machinery/camera/remove = list() - var/list/obj/machinery/camera/visible = list() - for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks) - for (var/obj/machinery/camera/C in CC.cameras) - if (!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7) - continue - visible |= C - - add = visible - lit_cameras - remove = lit_cameras - visible - - for (var/obj/machinery/camera/C in remove) - C.set_light(0) - lit_cameras -= C - for (var/obj/machinery/camera/C in add) - C.set_light(AI_CAMERA_LUMINOSITY) - lit_cameras |= C - - -/mob/living/silicon/ai/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - if(anchored) - user.visible_message("\The [user] starts to unbolt \the [src] from the plating...") - if(!do_after(user, src,40)) - user.visible_message("\The [user] decides not to unbolt \the [src].") - return - user.visible_message("\The [user] finishes unfastening \the [src]!") - anchored = 0 - return - else - user.visible_message("\The [user] starts to bolt \the [src] to the plating...") - if(!do_after(user, src,40)) - user.visible_message("\The [user] decides not to bolt \the [src].") - return - user.visible_message("\The [user] finishes fastening down \the [src]!") - anchored = 1 - return - else - return ..() - - -/mob/living/silicon/ai/get_multitool(var/active_only=0) - return aiMulti - -// An AI doesn't become inoperable until -100% (or whatever config.health_threshold_dead is set to) -/mob/living/silicon/ai/system_integrity() - return (health - config.health_threshold_dead) / 2 - -/mob/living/silicon/ai/html_mob_check() - return 1 - -/mob/living/silicon/ai/isTeleViewing(var/client_eye) - return 1 +var/list/ai_list = list() + +//Not sure why this is necessary... +/proc/AutoUpdateAI(obj/subject) + var/is_in_use = 0 + if (subject!=null) + for(var/A in ai_list) + var/mob/living/silicon/ai/M = A + if ((M.client && M.machine == subject)) + is_in_use = 1 + subject.attack_ai(M) + return is_in_use + + +/mob/living/silicon/ai + name = "AI" + icon = 'icons/mob/AI.dmi'// + icon_state = "ai" + anchored = 1 // -- TLE + density = 1 + status_flags = CANSTUN|CANPARALYSE + force_compose = 1 + size = SIZE_BIG + + var/list/network = list("SS13") + var/obj/machinery/camera/current = null + 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] + var/icon/holo_icon//Default is assigned when AI is created. + var/obj/item/device/pda/ai/aiPDA = null + var/obj/item/device/multitool/aiMulti = null + var/custom_sprite = 0 //For our custom sprites + var/obj/item/device/camera/ai_camera/aicamera = null +//Hud stuff + + //MALFUNCTION + var/datum/module_picker/malf_picker + var/processing_time = 100 + var/list/datum/AI_Module/current_modules = list() + var/ai_flags = 0 + + var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE + var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite + + var/obj/machinery/power/apc/malfhack = null + var/explosive = 0 //does the AI explode when it dies? + + var/mob/living/silicon/ai/parent = null + var/camera_light_on = 0 + var/list/obj/machinery/camera/lit_cameras = list() + + var/datum/trackable/track = new() + + var/last_paper_seen = null + var/can_shunt = 1 + var/last_announcement = "" + +/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) + var/list/possibleNames = ai_names + + var/pickedName = null + while(!pickedName) + pickedName = pick(ai_names) + for (var/mob/living/silicon/ai/A in mob_list) + if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop + possibleNames -= pickedName + pickedName = null + add_language(LANGUAGE_SOL_COMMON, 1) + add_language(LANGUAGE_UNATHI, 1) + add_language(LANGUAGE_SIIK_TAJR, 1) + add_language(LANGUAGE_SKRELLIAN, 1) + add_language(LANGUAGE_ROOTSPEAK, 1) + add_language(LANGUAGE_GUTTER, 1) + add_language(LANGUAGE_CLATTER, 1) + add_language(LANGUAGE_GREY, 1) + add_language(LANGUAGE_MONKEY, 1) + add_language(LANGUAGE_VOX, 1) + add_language(LANGUAGE_TRADEBAND, 1) + default_language = all_languages[LANGUAGE_SOL_COMMON] + real_name = pickedName + name = real_name + anchored = 1 + canmove = 0 + density = 1 + loc = loc + + radio = new /obj/item/device/radio/borg/ai(src) + radio.recalculateChannels() + + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) + + proc_holder_list = new() + + //Determine the AI's lawset + if(L && istype(L,/datum/ai_laws)) src.laws = L + else src.laws = getLawset(src) + + verbs += /mob/living/silicon/ai/proc/show_laws_verb + + aiPDA = new/obj/item/device/pda/ai(src) + aiPDA.owner = name + aiPDA.ownjob = "AI" + aiPDA.name = name + " (" + aiPDA.ownjob + ")" + + aiMulti = new(src) + aicamera = new/obj/item/device/camera/ai_camera(src) + + if (istype(loc, /turf)) + verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ + /mob/living/silicon/ai/proc/ai_statuschange, \ + /mob/living/silicon/ai/proc/ai_hologram_change) + + if(!safety)//Only used by AIize() to successfully spawn an AI. + if (!B)//If there is no player/brain inside. + new/obj/structure/AIcore/deactivated(loc)//New empty terminal. + qdel(src)//Delete AI. + return + else + if (B.brainmob.mind) + B.brainmob.mind.transfer_to(src) + + to_chat(src, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).") + to_chat(src, "To look at other parts of the station, click on yourself to get a camera menu.") + to_chat(src, "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.") + to_chat(src, "To use something, simply click on it.") + to_chat(src, "Use say :b to speak to your cyborgs through binary.") + if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai))) + show_laws() + to_chat(src, "These laws may be changed by other players, or by you being the traitor.") + + job = "AI" + ai_list += src + ..() + return + +/mob/living/silicon/ai/verb/radio_interact() + set category = "AI Commands" + set name = "Radio Configuration" + if(stat || aiRestorePowerRoutine) return + radio.recalculateChannels() + radio.attack_self(usr) + +/mob/living/silicon/ai/verb/rename_photo() //This is horrible but will do for now + set category = "AI Commands" + set name = "Modify Photo Files" + if(stat || aiRestorePowerRoutine) + return + + var/list/nametemp = list() + var/find + var/datum/picture/selection + if(aicamera.aipictures.len == 0) + to_chat(usr, "No images saved") + return + for(var/datum/picture/t in aicamera.aipictures) + nametemp += t.fields["name"] + find = input("Select image to delete or rename.", "Photo Modification") in nametemp + for(var/datum/picture/q in aicamera.aipictures) + if(q.fields["name"] == find) + selection = q + break + + if(!selection) return + var/choice = input(usr, "Would you like to rename or delete [selection.fields["name"]]?", "Photo Modification") in list("Rename","Delete","Cancel") + switch(choice) + if("Cancel") + return + if ("Delete") + aicamera.aipictures.Remove(selection) + qdel(selection) + if("Rename") + var/new_name = sanitize(input(usr, "Write a new name for [selection.fields["name"]]:","Photo Modification")) + if(length(new_name) > 0) + selection.fields["name"] = new_name + else + to_chat(usr, "You must write a name.") + +/mob/living/silicon/ai/verb/pick_icon() + set category = "AI Commands" + set name = "Set AI Core Display" + if(stat || aiRestorePowerRoutine) + return + /* Jesus christ, more of this shit? + if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var + var/file = file2text("config/custom_sprites.txt") + var/lines = text2list(file, "\n") + + for(var/line in lines) + // split & clean up + var/list/Entry = text2list(line, "-") + for(var/i = 1 to Entry.len) + Entry[i] = trim(Entry[i]) + + if(Entry.len < 2) + continue; + + if(Entry[1] == src.ckey && Entry[2] == src.real_name) + custom_sprite = 1 //They're in the list? Custom sprite time + icon = 'icons/mob/custom-synthetic.dmi' + */ + //if(icon_state == initial(icon_state)) + var/icontype = "" + /* Nuked your hidden shit.*/ + if (custom_sprite == 1) icontype = ("Custom")//automagically selects custom sprite if one is available + else icontype = input("Select an icon!", "AI", null, null) as null|anything in list("Monochrome", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Broken Output", "Triumvirate", "Triumvirate Static", "Searif", "Ravensdale", "Serithi", "Static", "Wasp", "Robert House", "Red October", "Fabulous", "Girl", "Girl Malf", "Boy", "Boy Malf", "Four-Leaf", "Yes Man", "Hourglass", "Patriot", "Pirate", "Royal") + switch(icontype) + if("Custom") icon_state = "[src.ckey]-ai" + if("Clown") icon_state = "ai-clown2" + if("Monochrome") icon_state = "ai-mono" + if("Inverted") icon_state = "ai-u" + if("Firewall") icon_state = "ai-magma" + if("Green") icon_state = "ai-wierd" + if("Red") icon_state = "ai-malf" + if("Broken Output") icon_state = "ai-static" + if("Text") icon_state = "ai-text" + if("Smiley") icon_state = "ai-smiley" + if("Matrix") icon_state = "ai-matrix" + if("Angry") icon_state = "ai-angryface" + if("Dorf") icon_state = "ai-dorf" + if("Bliss") icon_state = "ai-bliss" + if("Triumvirate") icon_state = "ai-triumvirate" + if("Triumvirate Static") icon_state = "ai-triumvirate-malf" + if("Searif") icon_state = "ai-searif" + if("Ravensdale") icon_state = "ai-ravensdale" + if("Serithi") icon_state = "ai-serithi" + if("Static") icon_state = "ai-fuzz" + if("Wasp") icon_state = "ai-wasp" + if("Robert House") icon_state = "ai-president" + if("Red October") icon_state = "ai-soviet" + if("Girl") icon_state = "ai-girl" + if("Girl Malf") icon_state = "ai-girl-malf" + if("Boy") icon_state = "ai-boy" + if("Boy Malf") icon_state = "ai-boy-malf" + if("Fabulous") icon_state = "ai-fabulous" + if("Four-Leaf") icon_state = "ai-4chan" + if("Yes Man") icon_state = "yes-man" + if("Hourglass") icon_state = "ai-hourglass" + if("Patriot") icon_state = "ai-patriot" + if("Pirate") icon_state = "ai-pirate" + if("Royal") icon_state = "ai-royal" + else icon_state = "ai" + //else +// to_chat(usr, "You can only change your display once!") + //return + + +// displays the malf_ai information if the AI is the malf +/mob/living/silicon/ai/show_malf_ai() + if(ticker.mode.name == "AI malfunction") + var/datum/game_mode/malfunction/malf = ticker.mode + for (var/datum/mind/malfai in malf.malf_ai) + if (mind == malfai) // are we the evil one? + if (malf.apcs >= 3) + stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") + + +/mob/living/silicon/ai/proc/ai_alerts() + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\ai\ai.dm:195: var/dat = "Current Station Alerts\n" + var/dat = {"Current Station Alerts\n +Close

    "} + // END AUTOFIX + 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] + 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) + dat += "
    \n" + else + dat += "-- All Systems Nominal
    \n" + dat += "
    \n" + + viewalerts = 1 + src << browse(dat, "window=aialerts&can_close=0") + +// this verb lets the ai see the stations manifest +/mob/living/silicon/ai/proc/ai_roster() + show_station_manifest() + +/mob/living/silicon/ai/proc/ai_call_shuttle() + if(src.stat == 2) + to_chat(src, "You can't call the shuttle because you are dead!") + return + if(istype(usr,/mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = src + if(AI.control_disabled) + to_chat(usr, "Wireless control is disabled!") + return + + var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No") + + if(confirm == "Yes") + var/justification = stripped_input(usr, "Please input a concise justification for the shuttle call. Note that failure to properly justify a shuttle call may lead to recall or termination", "Nanotrasen Anti-Comdom Systems") + call_shuttle_proc(src, justification) + + // hack to display shuttle timer + if(emergency_shuttle.online) + var/obj/machinery/computer/communications/C = locate() in machines + if(C) + C.post_status("shuttle") + + return + +/mob/living/silicon/ai/proc/ai_cancel_call() + set category = "AI Commands" + + if(src.stat == 2) + to_chat(src, "You can't send the shuttle back because you are dead!") + return + if(istype(usr,/mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = src + if(AI.control_disabled) + to_chat(src, "Wireless control is disabled!") + return + recall_shuttle(src) + +/mob/living/silicon/ai/check_eye(var/mob/user as mob) + if (!current) + return null + user.reset_view(current) + return 1 + +/mob/living/silicon/ai/blob_act() + if(flags & INVULNERABLE) + return + if (stat != 2) + adjustBruteLoss(60) + updatehealth() + return 1 + return 0 + +/mob/living/silicon/ai/restrained() + if(timestopped) return 1 //under effects of time magick + return 0 + +/mob/living/silicon/ai/emp_act(severity) + if(flags & INVULNERABLE) + return + + if (prob(30)) + switch(pick(1,2)) + if(1) + view_core() + if(2) + ai_call_shuttle() + ..() + +/mob/living/silicon/ai/ex_act(severity) + if(flags & INVULNERABLE) + return + + if(!blinded) + flick("flash", flash) + + switch(severity) + if(1.0) + if (stat != 2) + adjustBruteLoss(100) + adjustFireLoss(100) + if(2.0) + if (stat != 2) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + if (stat != 2) + adjustBruteLoss(30) + + updatehealth() + + +/mob/living/silicon/ai/Topic(href, href_list) + if(usr != src) + return + ..() + if (href_list["mach_close"]) + if (href_list["mach_close"] == "aialerts") + viewalerts = 0 + var/t1 = text("window=[]", href_list["mach_close"]) + unset_machine() + src << browse(null, t1) + if (href_list["switchcamera"]) + switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras + if (href_list["showalerts"]) + ai_alerts() + + if(href_list["show_paper"]) + if(last_paper_seen) + src << browse(last_paper_seen, "window=show_paper") + //Carn: holopad requests + if (href_list["jumptoholopad"]) + var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"]) + if(stat == CONSCIOUS) + if(H) + H.attack_ai(src) //may as well recycle + else + to_chat(src, "Unable to locate the holopad.") + + if(href_list["say_word"]) + play_vox_word(href_list["say_word"], null, src) + return + + if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + var/L = text2num(href_list["lawc"]) + switch(lawcheck[L+1]) + if ("Yes") lawcheck[L+1] = "No" + if ("No") lawcheck[L+1] = "Yes" +// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) + checklaws() + + if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + var/L = text2num(href_list["lawi"]) + switch(ioncheck[L]) + if ("Yes") ioncheck[L] = "No" + if ("No") ioncheck[L] = "Yes" +// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) + checklaws() + + if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite + statelaws() + + 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) + return + + else if (href_list["faketrack"]) + 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.cameraFollow = target + to_chat(A, text("Now tracking [] on camera.", target.name)) + if (usr.machine == null) + usr.machine = usr + + while (src.cameraFollow == target) + to_chat(usr, "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb).") + sleep(40) + continue + + return + + if (href_list["open"]) + var/mob/target = locate(href_list["open"]) + var/mob/living/silicon/ai/A = locate(href_list["open2"]) + if(A && target) + A.open_nearest_door(target) + return + + return + +/mob/living/silicon/ai/bullet_act(var/obj/item/projectile/Proj) + ..(Proj) + updatehealth() + return 2 + +/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + if (!ticker) + to_chat(M, "You cannot attack people before the game has started.") + return + + if (istype(loc, /turf) && istype(loc.loc, /area/start)) + to_chat(M, "No attacking people at spawn, you jackass.") + return + + switch(M.a_intent) + + if (I_HELP) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[M] caresses [src]'s plating with its scythe like arm."), 1) + + else //harm + var/damage = rand(10, 20) + if (prob(90)) + playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has slashed at []!", M, src), 1) + if(prob(8)) + flick("noise", flash) + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] took a swipe at []!", M, src), 1) + return + +/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob) + if(!istype(M)) + return + if(M.melee_damage_upper == 0) + M.emote("[M.friendly] [src]") + else + if(M.attack_sound) + playsound(loc, M.attack_sound, 50, 1, 1) + for(var/mob/O in viewers(src, null)) + O.show_message("[M] [M.attacktext] [src]!", 1) + M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + adjustBruteLoss(damage) + updatehealth() + +/mob/living/silicon/ai/reset_view(atom/A) + if (camera_light_on) + light_cameras() + if(istype(A,/obj/machinery/camera)) + current = A + ..() + + +/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) + + + src.cameraFollow = null + + if (!C || stat == 2) //C.can_use()) + return 0 + + if(!src.eyeobj) + view_core() + return + // ok, we're alive, camera is good and in our network... + eyeobj.forceMove(get_turf(C)) + //machine = src + + return 1 + +/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource) + 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) + 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) + queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0) + if (viewalerts) ai_alerts() + return !cleared + +/mob/living/silicon/ai/cancel_camera() + src.view_core() + + +//Replaces /mob/living/silicon/ai/verb/change_network() in ai.dm & camera.dm +//Adds in /mob/living/silicon/ai/proc/ai_network_change() instead +//Addition by Mord_Sith to define AI's network change ability +/mob/living/silicon/ai/proc/ai_network_change() + set category = "AI Commands" + set name = "Jump To Network" + unset_machine() + src.cameraFollow = null + var/cameralist[0] + + if(usr.isDead()) + to_chat(usr, "You can't change your camera network because you are dead!") + return + + var/mob/living/silicon/ai/U = usr + + for (var/obj/machinery/camera/C in cameranet.cameras) + if(!C.can_use()) + continue + + var/list/tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS,1) + if(tempnetwork.len) + for(var/i in tempnetwork) + cameralist[i] = i + var/old_network = network + network = input(U, "Which network would you like to view?") as null|anything in cameralist + + if(!U.eyeobj) + U.view_core() + return + + if(isnull(network)) + network = old_network // If nothing is selected + else + for(var/obj/machinery/camera/C in cameranet.cameras) + if(!C.can_use()) + continue + if(network in C.network) + U.eyeobj.forceMove(get_turf(C)) + break + to_chat(src, "Switched to [network] camera network.") +//End of code by Mord_Sith + + +/mob/living/silicon/ai/proc/choose_modules() + set category = "Malfunction" + set name = "Choose Module" + + malf_picker.use(src) + +/mob/living/silicon/ai/proc/ai_statuschange() + set category = "AI Commands" + set name = "AI Status" + + if(usr.isDead()) + to_chat(usr, "You cannot change your emotional status because you are dead!") + return + + var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions //ai_emotions can be found in code/game/machinery/status_display.dm @ 213 (above the AI status display) + + for (var/obj/machinery/M in status_displays) //change status + if(istype(M, /obj/machinery/ai_status_display)) + var/obj/machinery/ai_status_display/AISD = M + AISD.emotion = emote + //if Friend Computer, change ALL displays + else if(istype(M, /obj/machinery/status_display)) + + var/obj/machinery/status_display/SD = M + if(emote=="Friend Computer") + SD.friendc = 1 + else + SD.friendc = 0 + return + +//I am the icon meister. Bow fefore me. //>fefore +/mob/living/silicon/ai/proc/ai_hologram_change() + set name = "Change Hologram" + set desc = "Change the default hologram available to AI to something else." + set category = "AI Commands" + + var/input + if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member") + + var/personnel_list[] = list() + + for(var/datum/data/record/t in data_core.locked)//Look in data core locked. + personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image. + + if(personnel_list.len) + input = input("Select a crew member:") as null|anything in personnel_list + var/icon/character_icon = personnel_list[input] + if(character_icon) + qdel(holo_icon)//Clear old icon so we're not storing it in memory. + holo_icon = getHologramIcon(icon(character_icon)) + else + alert("No suitable records found. Aborting.") + + else + var/icon_list[] = list( + "Default", + "Floating face", + "Cortano", + "Spoopy", + "343", + "Auto", + "Four-Leaf", + "Yotsuba", + "Girl", + "Boy", + "SHODAN" + ) + input = input("Please select a hologram:") as null|anything in icon_list + if(input) + qdel(holo_icon) + holo_icon = null + switch(input) + if("Default") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) + if("Floating face") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2")) + if("Cortano") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) + if("Spoopy") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) + if("343") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo5")) + if("Auto") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo6")) + if("Four-Leaf") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo7")) + if("Yotsuba") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo8")) + if("Girl") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo9")) + if("Boy") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo10")) + if("SHODAN") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo11")) + + return + +/mob/living/silicon/ai/proc/corereturn() + set category = "Malfunction" + set name = "Return to Main Core" + + var/obj/machinery/power/apc/apc = src.loc + if(!istype(apc)) + to_chat(src, "You are already in your Main Core.") + return + apc.malfvacate() + +//Toggles the luminosity and applies it by re-entereing the camera. +/mob/living/silicon/ai/verb/toggle_camera_light() + set name = "Toggle Camera Light" + set desc = "Toggle internal infrared camera light" + set category = "AI Commands" + if(stat != CONSCIOUS) + return + + camera_light_on = !camera_light_on + + if (!camera_light_on) + to_chat(src, "Camera lights deactivated.") + + for (var/obj/machinery/camera/C in lit_cameras) + C.set_light(0) + lit_cameras = list() + + return + + light_cameras() + + to_chat(src, "Camera lights activated.") + return + +//AI_CAMERA_LUMINOSITY + +/mob/living/silicon/ai/proc/light_cameras() + var/list/obj/machinery/camera/add = list() + var/list/obj/machinery/camera/remove = list() + var/list/obj/machinery/camera/visible = list() + for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks) + for (var/obj/machinery/camera/C in CC.cameras) + if (!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7) + continue + visible |= C + + add = visible - lit_cameras + remove = lit_cameras - visible + + for (var/obj/machinery/camera/C in remove) + C.set_light(0) + lit_cameras -= C + for (var/obj/machinery/camera/C in add) + C.set_light(AI_CAMERA_LUMINOSITY) + lit_cameras |= C + + +/mob/living/silicon/ai/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + if(anchored) + user.visible_message("\The [user] starts to unbolt \the [src] from the plating...") + if(!do_after(user, src,40)) + user.visible_message("\The [user] decides not to unbolt \the [src].") + return + user.visible_message("\The [user] finishes unfastening \the [src]!") + anchored = 0 + return + else + user.visible_message("\The [user] starts to bolt \the [src] to the plating...") + if(!do_after(user, src,40)) + user.visible_message("\The [user] decides not to bolt \the [src].") + return + user.visible_message("\The [user] finishes fastening down \the [src]!") + anchored = 1 + return + else + return ..() + + +/mob/living/silicon/ai/get_multitool(var/active_only=0) + return aiMulti + +// An AI doesn't become inoperable until -100% (or whatever config.health_threshold_dead is set to) +/mob/living/silicon/ai/system_integrity() + return (health - config.health_threshold_dead) / 2 + +/mob/living/silicon/ai/html_mob_check() + return 1 + +/mob/living/silicon/ai/isTeleViewing(var/client_eye) + return 1 diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index e39bf9d1496..9154db09035 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -1,64 +1,64 @@ -/mob/living/silicon/ai/death(gibbed) - if(stat == DEAD) return - stat = DEAD - if (src.custom_sprite == 1)//check for custom AI sprite, defaulting to blue screen if no. - icon_state = "[ckey]-ai-crash" - else icon_state = "ai-crash" - update_canmove() - if(src.eyeobj) - src.eyeobj.forceMove(get_turf(src)) - if(blind) blind.layer = 0 - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - - var/callshuttle = 0 - - for(var/obj/machinery/computer/communications/commconsole in machines) - if(commconsole.z == 2) - continue - if(istype(commconsole.loc,/turf)) - break - callshuttle++ - - for(var/obj/item/weapon/circuitboard/communications/commboard in world) - if(commboard.z == 2) - continue - if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) - break - callshuttle++ - - for(var/mob/living/silicon/ai/shuttlecaller in player_list) - if(shuttlecaller.z == 2) - continue - if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) - break - callshuttle++ - - if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) - callshuttle = 0 - - if(callshuttle == 3) //if all three conditions are met - emergency_shuttle.incall(2) - log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.") - message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1) - captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") +/mob/living/silicon/ai/death(gibbed) + if(stat == DEAD) return + stat = DEAD + if (src.custom_sprite == 1)//check for custom AI sprite, defaulting to blue screen if no. + icon_state = "[ckey]-ai-crash" + else icon_state = "ai-crash" + update_canmove() + if(src.eyeobj) + src.eyeobj.forceMove(get_turf(src)) + if(blind) blind.layer = 0 + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + + var/callshuttle = 0 + + for(var/obj/machinery/computer/communications/commconsole in machines) + if(commconsole.z == 2) + continue + if(istype(commconsole.loc,/turf)) + break + callshuttle++ + + for(var/obj/item/weapon/circuitboard/communications/commboard in world) + if(commboard.z == 2) + continue + if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) + break + callshuttle++ + + for(var/mob/living/silicon/ai/shuttlecaller in player_list) + if(shuttlecaller.z == 2) + continue + if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) + break + callshuttle++ + + if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || sent_strike_team) + callshuttle = 0 + + if(callshuttle == 3) //if all three conditions are met + emergency_shuttle.incall(2) + log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.") + message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1) + captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.") to_chat(world, sound('sound/AI/shuttlecalled.ogg')) - - if(explosive) - spawn(10) - explosion(src.loc, 3, 6, 12, 15) - - for(var/obj/machinery/ai_status_display/O in machines) //change status - spawn( 0 ) - O.mode = 2 - if (istype(loc, /obj/item/device/aicard)) - loc.icon_state = "aicard-404" - - tod = worldtime2text() //weasellos time of death patch - if(mind) - mind.store_memory("Time of death: [tod]", 0) - if(!suiciding) //Cowards don't count - score["deadaipenalty"] += 1 - - return ..(gibbed) + + if(explosive) + spawn(10) + explosion(src.loc, 3, 6, 12, 15) + + for(var/obj/machinery/ai_status_display/O in machines) //change status + spawn( 0 ) + O.mode = 2 + if (istype(loc, /obj/item/device/aicard)) + loc.icon_state = "aicard-404" + + tod = worldtime2text() //weasellos time of death patch + if(mind) + mind.store_memory("Time of death: [tod]", 0) + if(!suiciding) //Cowards don't count + score["deadaipenalty"] += 1 + + return ..(gibbed) diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm index 5576e62c404..073066db5e0 100644 --- a/code/modules/mob/living/silicon/ai/examine.dm +++ b/code/modules/mob/living/silicon/ai/examine.dm @@ -1,24 +1,24 @@ -/mob/living/silicon/ai/examine(mob/user) - - var/msg = "*---------*\nThis is \icon[src] [src]!\n" - if (src.stat == DEAD) - msg += "It appears to be powered-down.\n" - else - msg += "" - if (src.getBruteLoss()) - if (src.getBruteLoss() < 30) - msg += "It looks slightly dented.\n" - else - msg += "It looks severely dented!\n" - if (src.getFireLoss()) - if (src.getFireLoss() < 30) - msg += "It looks slightly charred.\n" - else - msg += "Its casing is melted and heat-warped!\n" - - if (src.stat == UNCONSCIOUS) - msg += "It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".\n" - msg += "" - msg += "*---------*" - +/mob/living/silicon/ai/examine(mob/user) + + var/msg = "*---------*\nThis is \icon[src] [src]!\n" + if (src.stat == DEAD) + msg += "It appears to be powered-down.\n" + else + msg += "" + if (src.getBruteLoss()) + if (src.getBruteLoss() < 30) + msg += "It looks slightly dented.\n" + else + msg += "It looks severely dented!\n" + if (src.getFireLoss()) + if (src.getFireLoss() < 30) + msg += "It looks slightly charred.\n" + else + msg += "Its casing is melted and heat-warped!\n" + + if (src.stat == UNCONSCIOUS) + msg += "It is non-responsive and displaying the text: \"RUNTIME: Sensory Overload, stack 26/3\".\n" + msg += "" + msg += "*---------*" + to_chat(user, msg) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index dc6ed8954f1..857a9e3ab28 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -1,156 +1,156 @@ -// CAMERA NET -// -// The datum containing all the chunks. - -var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc.. - -var/datum/cameranet/cameranet = new() - -/datum/cameranet - // The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Destroy(). - var/list/cameras = list() - // The chunks of the map, mapping the areas that the cameras can see. - var/list/chunks = list() - var/ready = 0 - -// Checks if a chunk has been Generated in x, y, z. -/datum/cameranet/proc/chunkGenerated(x, y, z) - x &= ~(CHUNK_SIZE - 1) - y &= ~(CHUNK_SIZE - 1) - var/key = "[x],[y],[z]" - return (chunks[key]) - -// Returns the chunk in the x, y, z. -// If there is no chunk, it creates a new chunk and returns that. -/datum/cameranet/proc/getCameraChunk(x, y, z) - x &= ~(CHUNK_SIZE - 1) - y &= ~(CHUNK_SIZE - 1) - var/key = "[x],[y],[z]" - if(!chunks[key]) - chunks[key] = new /datum/camerachunk(null, x, y, z) - - return chunks[key] - -// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set. - -/datum/cameranet/proc/visibility(mob/camera/aiEye/ai) - // 0xf = 15 - var/x1 = max(0, ai.x - 16) & ~(CHUNK_SIZE - 1) - var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1) - var/x2 = min(world.maxx, ai.x + 16) & ~(CHUNK_SIZE - 1) - var/y2 = min(world.maxy, ai.y + 16) & ~(CHUNK_SIZE - 1) - - var/list/visibleChunks = list() - - for(var/x = x1; x <= x2; x += CHUNK_SIZE) - for(var/y = y1; y <= y2; y += CHUNK_SIZE) - visibleChunks |= getCameraChunk(x, y, ai.z) - - var/list/remove = ai.visibleCameraChunks - visibleChunks - var/list/add = visibleChunks - ai.visibleCameraChunks - - for(var/chunk in remove) - var/datum/camerachunk/c = chunk - c.remove(ai) - - for(var/chunk in add) - var/datum/camerachunk/c = chunk - c.add(ai) - -// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. - -/datum/cameranet/proc/updateVisibility(atom/A, var/opacity_check = 1) - - - if(!ticker || (opacity_check && !A.opacity)) - return - majorChunkChange(A, 2) - -/datum/cameranet/proc/updateChunk(x, y, z) - // 0xf = 15 - if(!chunkGenerated(x, y, z)) - return - var/datum/camerachunk/chunk = getCameraChunk(x, y, z) - chunk.hasChanged() - -// Removes a camera from a chunk. - -/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) - if(c.can_use()) - majorChunkChange(c, 0) - -// Add a camera to a chunk. - -/datum/cameranet/proc/addCamera(obj/machinery/camera/c) - if(c.can_use()) - majorChunkChange(c, 1) - -// Used for Cyborg cameras. Since portable cameras can be in ANY chunk. - -/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c) - if(c.can_use()) - majorChunkChange(c, 1) - //else - // majorChunkChange(c, 0) - -// Never access this proc directly!!!! -// This will update the chunk and all the surrounding chunks. -// It will also add the atom to the cameras list if you set the choice to 1. -// Setting the choice to 0 will remove the camera from the chunks. -// If you want to update the chunks around an object, without adding/removing a camera, use choice 2. - -/datum/cameranet/proc/majorChunkChange(atom/c, var/choice) - // 0xf = 15 - if(!c) - return - - var/turf/T = get_turf(c) - if(T) - var/x1 = max(0, T.x - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) - var/y1 = max(0, T.y - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) - var/x2 = min(world.maxx, T.x + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) - var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) - +// CAMERA NET +// +// The datum containing all the chunks. + +var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc.. + +var/datum/cameranet/cameranet = new() + +/datum/cameranet + // The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Destroy(). + var/list/cameras = list() + // The chunks of the map, mapping the areas that the cameras can see. + var/list/chunks = list() + var/ready = 0 + +// Checks if a chunk has been Generated in x, y, z. +/datum/cameranet/proc/chunkGenerated(x, y, z) + x &= ~(CHUNK_SIZE - 1) + y &= ~(CHUNK_SIZE - 1) + var/key = "[x],[y],[z]" + return (chunks[key]) + +// Returns the chunk in the x, y, z. +// If there is no chunk, it creates a new chunk and returns that. +/datum/cameranet/proc/getCameraChunk(x, y, z) + x &= ~(CHUNK_SIZE - 1) + y &= ~(CHUNK_SIZE - 1) + var/key = "[x],[y],[z]" + if(!chunks[key]) + chunks[key] = new /datum/camerachunk(null, x, y, z) + + return chunks[key] + +// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set. + +/datum/cameranet/proc/visibility(mob/camera/aiEye/ai) + // 0xf = 15 + var/x1 = max(0, ai.x - 16) & ~(CHUNK_SIZE - 1) + var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1) + var/x2 = min(world.maxx, ai.x + 16) & ~(CHUNK_SIZE - 1) + var/y2 = min(world.maxy, ai.y + 16) & ~(CHUNK_SIZE - 1) + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += CHUNK_SIZE) + for(var/y = y1; y <= y2; y += CHUNK_SIZE) + visibleChunks |= getCameraChunk(x, y, ai.z) + + var/list/remove = ai.visibleCameraChunks - visibleChunks + var/list/add = visibleChunks - ai.visibleCameraChunks + + for(var/chunk in remove) + var/datum/camerachunk/c = chunk + c.remove(ai) + + for(var/chunk in add) + var/datum/camerachunk/c = chunk + c.add(ai) + +// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. + +/datum/cameranet/proc/updateVisibility(atom/A, var/opacity_check = 1) + + + if(!ticker || (opacity_check && !A.opacity)) + return + majorChunkChange(A, 2) + +/datum/cameranet/proc/updateChunk(x, y, z) + // 0xf = 15 + if(!chunkGenerated(x, y, z)) + return + var/datum/camerachunk/chunk = getCameraChunk(x, y, z) + chunk.hasChanged() + +// Removes a camera from a chunk. + +/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) + if(c.can_use()) + majorChunkChange(c, 0) + +// Add a camera to a chunk. + +/datum/cameranet/proc/addCamera(obj/machinery/camera/c) + if(c.can_use()) + majorChunkChange(c, 1) + +// Used for Cyborg cameras. Since portable cameras can be in ANY chunk. + +/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c) + if(c.can_use()) + majorChunkChange(c, 1) + //else + // majorChunkChange(c, 0) + +// Never access this proc directly!!!! +// This will update the chunk and all the surrounding chunks. +// It will also add the atom to the cameras list if you set the choice to 1. +// Setting the choice to 0 will remove the camera from the chunks. +// If you want to update the chunks around an object, without adding/removing a camera, use choice 2. + +/datum/cameranet/proc/majorChunkChange(atom/c, var/choice) + // 0xf = 15 + if(!c) + return + + var/turf/T = get_turf(c) + if(T) + var/x1 = max(0, T.x - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) + var/y1 = max(0, T.y - (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) + var/x2 = min(world.maxx, T.x + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) + var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1) + // to_chat(world, "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]") - - for(var/x = x1; x <= x2; x += CHUNK_SIZE) - for(var/y = y1; y <= y2; y += CHUNK_SIZE) - if(chunkGenerated(x, y, T.z)) - var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z) - if(choice == 0) - // Remove the camera. - chunk.cameras -= c - else if(choice == 1) - // You can't have the same camera in the list twice. - chunk.cameras |= c - chunk.hasChanged() - -// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0. - -/datum/cameranet/proc/checkCameraVis(mob/living/target as mob) - - - // 0xf = 15 - var/turf/position = get_turf(target) - return checkTurfVis(position) - - -/datum/cameranet/proc/checkTurfVis(var/turf/position) - var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z) - if(chunk) - if(chunk.changed) - chunk.hasChanged(1) // Update now, no matter if it's visible or not. - if(chunk.visibleTurfs[position]) - return 1 - return 0 - - -// Debug verb for VVing the chunk that the turf is in. -/* -/turf/verb/view_chunk() - set src in world - - if(cameranet.chunkGenerated(x, y, z)) - var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z) - usr.client.debug_variables(chunk) + + for(var/x = x1; x <= x2; x += CHUNK_SIZE) + for(var/y = y1; y <= y2; y += CHUNK_SIZE) + if(chunkGenerated(x, y, T.z)) + var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z) + if(choice == 0) + // Remove the camera. + chunk.cameras -= c + else if(choice == 1) + // You can't have the same camera in the list twice. + chunk.cameras |= c + chunk.hasChanged() + +// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0. + +/datum/cameranet/proc/checkCameraVis(mob/living/target as mob) + + + // 0xf = 15 + var/turf/position = get_turf(target) + return checkTurfVis(position) + + +/datum/cameranet/proc/checkTurfVis(var/turf/position) + var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z) + if(chunk) + if(chunk.changed) + chunk.hasChanged(1) // Update now, no matter if it's visible or not. + if(chunk.visibleTurfs[position]) + return 1 + return 0 + + +// Debug verb for VVing the chunk that the turf is in. +/* +/turf/verb/view_chunk() + set src in world + + if(cameranet.chunkGenerated(x, y, z)) + var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z) + usr.client.debug_variables(chunk) */ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index a73ac7f1380..1a02f096195 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -1,174 +1,174 @@ -#define UPDATE_BUFFER 25 // 2.5 seconds - -// CAMERA CHUNK -// -// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed. -// Allows the AI Eye to stream these chunks and know what it can and cannot see. - -/datum/camerachunk - var/list/obscuredTurfs = list() - var/list/visibleTurfs = list() - var/list/obscured = list() - var/list/cameras = list() - var/list/turfs = list() - var/list/seenby = list() - var/visible = 0 - var/changed = 0 - var/updating = 0 - var/x = 0 - var/y = 0 - var/z = 0 - -// Add an AI eye to the chunk, then update if changed. - -/datum/camerachunk/proc/add(mob/camera/aiEye/ai) - if(!ai.ai) - return - ai.visibleCameraChunks += src - if(ai.ai.client) - ai.ai.client.images += obscured - visible++ - seenby += ai - if(changed && !updating) - update() - -// Remove an AI eye from the chunk, then update if changed. - -/datum/camerachunk/proc/remove(mob/camera/aiEye/ai) - if(!ai.ai) - return - ai.visibleCameraChunks -= src - if(ai.ai.client) - ai.ai.client.images -= obscured - seenby -= ai - if(visible > 0) - visible-- - -// Called when a chunk has changed. I.E: A wall was deleted. - -/datum/camerachunk/proc/visibilityChanged(turf/loc) - if(!visibleTurfs[loc]) - return - hasChanged() - -// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will -// instead be flagged to update the next time an AI Eye moves near it. - -/datum/camerachunk/proc/hasChanged(var/update_now = 0) - if(visible || update_now) - if(!updating) - updating = 1 - spawn(UPDATE_BUFFER) // Batch large changes, such as many doors opening or closing at once - update() - updating = 0 - else - changed = 1 - -// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists. - -/datum/camerachunk/proc/update() - - - var/list/newVisibleTurfs = list() - - for(var/camera in cameras) - var/obj/machinery/camera/c = camera - - if(!c) - continue - - if(!c.can_use()) - continue - - var/turf/point = locate(src.x + (CHUNK_SIZE / 2), src.y + (CHUNK_SIZE / 2), src.z) - if(get_dist(point, c) > CHUNK_SIZE + (CHUNK_SIZE / 2)) - continue - - for(var/turf/t in c.can_see()) - // Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards. - // List associations use a tree or hashmap of some sort (alongside the list itself) - // so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing) - newVisibleTurfs[t] = t - - // Removes turf that isn't in turfs. - newVisibleTurfs &= turfs - - var/list/visAdded = newVisibleTurfs - visibleTurfs - var/list/visRemoved = visibleTurfs - newVisibleTurfs - - visibleTurfs = newVisibleTurfs - obscuredTurfs = turfs - newVisibleTurfs - - for(var/turf in visAdded) - var/turf/t = turf - if(t.obscured) - obscured -= t.obscured - for(var/eye in seenby) - var/mob/camera/aiEye/m = eye - if(!m || !m.ai) - continue - if(m.ai.client) - m.ai.client.images -= t.obscured - - for(var/turf in visRemoved) - var/turf/t = turf - if(obscuredTurfs[t]) - if(!t.obscured) - t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) - - obscured += t.obscured - for(var/eye in seenby) - var/mob/camera/aiEye/m = eye - if(!m || !m.ai) - seenby -= m - continue - if(m.ai.client) - m.ai.client.images += t.obscured - - changed = 0 - -// Create a new camera chunk, since the chunks are made as they are needed. - -/datum/camerachunk/New(loc, x, y, z) - - // 0xf = 15 - x &= ~(CHUNK_SIZE - 1) - y &= ~(CHUNK_SIZE - 1) - - src.x = x - src.y = y - src.z = z - - for(var/obj/machinery/camera/c in range(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z))) - if(c.can_use()) - cameras += c - - for(var/turf/t in block(locate(x, y, z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z))) - turfs[t] = t - - for(var/camera in cameras) - var/obj/machinery/camera/c = camera - if(!c) - continue - - if(!c.can_use()) - continue - - for(var/turf/t in c.can_see()) - // Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards. - // List associations use a tree or hashmap of some sort (alongside the list itself) - // so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing) - visibleTurfs[t] = t - - // Removes turf that isn't in turfs. - visibleTurfs &= turfs - - obscuredTurfs = turfs - visibleTurfs - - for(var/turf in obscuredTurfs) - var/turf/t = turf - if(!t.obscured) - t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) - obscured += t.obscured - +#define UPDATE_BUFFER 25 // 2.5 seconds + +// CAMERA CHUNK +// +// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed. +// Allows the AI Eye to stream these chunks and know what it can and cannot see. + +/datum/camerachunk + var/list/obscuredTurfs = list() + var/list/visibleTurfs = list() + var/list/obscured = list() + var/list/cameras = list() + var/list/turfs = list() + var/list/seenby = list() + var/visible = 0 + var/changed = 0 + var/updating = 0 + var/x = 0 + var/y = 0 + var/z = 0 + +// Add an AI eye to the chunk, then update if changed. + +/datum/camerachunk/proc/add(mob/camera/aiEye/ai) + if(!ai.ai) + return + ai.visibleCameraChunks += src + if(ai.ai.client) + ai.ai.client.images += obscured + visible++ + seenby += ai + if(changed && !updating) + update() + +// Remove an AI eye from the chunk, then update if changed. + +/datum/camerachunk/proc/remove(mob/camera/aiEye/ai) + if(!ai.ai) + return + ai.visibleCameraChunks -= src + if(ai.ai.client) + ai.ai.client.images -= obscured + seenby -= ai + if(visible > 0) + visible-- + +// Called when a chunk has changed. I.E: A wall was deleted. + +/datum/camerachunk/proc/visibilityChanged(turf/loc) + if(!visibleTurfs[loc]) + return + hasChanged() + +// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will +// instead be flagged to update the next time an AI Eye moves near it. + +/datum/camerachunk/proc/hasChanged(var/update_now = 0) + if(visible || update_now) + if(!updating) + updating = 1 + spawn(UPDATE_BUFFER) // Batch large changes, such as many doors opening or closing at once + update() + updating = 0 + else + changed = 1 + +// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists. + +/datum/camerachunk/proc/update() + + + var/list/newVisibleTurfs = list() + + for(var/camera in cameras) + var/obj/machinery/camera/c = camera + + if(!c) + continue + + if(!c.can_use()) + continue + + var/turf/point = locate(src.x + (CHUNK_SIZE / 2), src.y + (CHUNK_SIZE / 2), src.z) + if(get_dist(point, c) > CHUNK_SIZE + (CHUNK_SIZE / 2)) + continue + + for(var/turf/t in c.can_see()) + // Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards. + // List associations use a tree or hashmap of some sort (alongside the list itself) + // so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing) + newVisibleTurfs[t] = t + + // Removes turf that isn't in turfs. + newVisibleTurfs &= turfs + + var/list/visAdded = newVisibleTurfs - visibleTurfs + var/list/visRemoved = visibleTurfs - newVisibleTurfs + + visibleTurfs = newVisibleTurfs + obscuredTurfs = turfs - newVisibleTurfs + + for(var/turf in visAdded) + var/turf/t = turf + if(t.obscured) + obscured -= t.obscured + for(var/eye in seenby) + var/mob/camera/aiEye/m = eye + if(!m || !m.ai) + continue + if(m.ai.client) + m.ai.client.images -= t.obscured + + for(var/turf in visRemoved) + var/turf/t = turf + if(obscuredTurfs[t]) + if(!t.obscured) + t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) + + obscured += t.obscured + for(var/eye in seenby) + var/mob/camera/aiEye/m = eye + if(!m || !m.ai) + seenby -= m + continue + if(m.ai.client) + m.ai.client.images += t.obscured + + changed = 0 + +// Create a new camera chunk, since the chunks are made as they are needed. + +/datum/camerachunk/New(loc, x, y, z) + + // 0xf = 15 + x &= ~(CHUNK_SIZE - 1) + y &= ~(CHUNK_SIZE - 1) + + src.x = x + src.y = y + src.z = z + + for(var/obj/machinery/camera/c in range(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z))) + if(c.can_use()) + cameras += c + + for(var/turf/t in block(locate(x, y, z), locate(min(x + CHUNK_SIZE - 1, world.maxx), min(y + CHUNK_SIZE - 1, world.maxy), z))) + turfs[t] = t + + for(var/camera in cameras) + var/obj/machinery/camera/c = camera + if(!c) + continue + + if(!c.can_use()) + continue + + for(var/turf/t in c.can_see()) + // Possible optimization: if(turfs[t]) here, rather than &= turfs afterwards. + // List associations use a tree or hashmap of some sort (alongside the list itself) + // so are surprisingly fast. (significantly faster than var/thingy/x in list, in testing) + visibleTurfs[t] = t + + // Removes turf that isn't in turfs. + visibleTurfs &= turfs + + obscuredTurfs = turfs - visibleTurfs + + for(var/turf in obscuredTurfs) + var/turf/t = turf + if(!t.obscured) + t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) + obscured += t.obscured + #undef UPDATE_BUFFER \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index c02310cc59d..c34927f9b4e 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -1,163 +1,163 @@ -// AI EYE -// -// An invisible (no icon) mob that the AI controls to look around the station with. -// It streams chunks as it moves around, which will show it what the AI can and cannot see. - -/mob/camera/aiEye - name = "Inactive AI Eye" - anchored = TRUE - - var/list/visibleCameraChunks = list() - var/mob/living/silicon/ai/ai = null - - -// Use this when setting the aiEye's location. -// It will also stream the chunk that the new loc is in. - -/mob/camera/aiEye/forceMove(var/atom/destination) - if(ai) - if(!isturf(ai.loc)) - return - if(!isturf(destination)) - for(destination = destination.loc; !isturf(destination); destination = destination.loc); - forceEnter(destination) - - cameranet.visibility(src) - if(ai.client && ai.client.eye != src) // Set the eye to us and give the AI the sight & visibility flags it needs. - ai.client.eye = src - ai.sight |= SEE_TURFS - ai.sight |= SEE_MOBS - ai.sight |= SEE_OBJS - ai.see_in_dark = 8 - ai.see_invisible = SEE_INVISIBLE_LEVEL_TWO - - //Holopad - if(istype(ai.current, /obj/machinery/hologram/holopad)) - var/obj/machinery/hologram/holopad/H = ai.current - H.move_hologram() - -/mob/camera/aiEye/Move() - return 0 - -//An AI eyeobj mob cant have a virtualhearer to hear with unless it gets one from a malf module -/mob/camera/aiEye/Hear(var/datum/speech/speech, var/rendered_speech="") - if(speech.frequency) //HOW CAN IT POSSIBLY READ LIPS THROUGH RADIOS - return - - var/mob/M = speech.speaker - if(istype(M)) - if(ishuman(M)) - var/mob/living/carbon/human/H = speech.speaker - if(H.check_body_part_coverage(MOUTH)) //OR MASKS - return - ai.Hear(args) //He can only read the lips of mobs, I cant think of objects using lips - - -// AI MOVEMENT - -// The AI's "eye". Described on the top of the page. - -/mob/living/silicon/ai - var/mob/camera/aiEye/eyeobj = new() - var/sprint = 10 - var/cooldown = 0 - var/acceleration = 1 - - -// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. -/mob/living/silicon/ai/New() - ..() - eyeobj.ai = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name - spawn(5) - eyeobj.loc = src.loc - -/mob/living/silicon/ai/Destroy() - eyeobj.ai = null - qdel(eyeobj) // No AI, no Eye - eyeobj = null - ..() - -/atom/proc/move_camera_by_click() - if(istype(usr, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = usr - if(AI.eyeobj && AI.client.eye == AI.eyeobj) - AI.cameraFollow = null - //AI.eyeobj.forceMove(src) - if (isturf(src.loc) || isturf(src)) - AI.eyeobj.forceMove(src) - -/mob/living/Click() - if(isAI(usr)) - return - ..() - -/mob/living/DblClick() - if(isAI(usr) && usr != src) - var/mob/living/silicon/ai/A = usr - A.ai_actual_track(src) - return - ..() - -// This will move the AIEye. It will also cause lights near the eye to light up, if toggled. -// This is handled in the proc below this one. - -/client/proc/AIMove(n, direct, var/mob/living/silicon/ai/user) - - - var/initial = initial(user.sprint) - var/max_sprint = 50 - - if(user.cooldown && user.cooldown < world.timeofday) // 3 seconds - user.sprint = initial - - for(var/i = 0; i < max(user.sprint, initial); i += 20) - var/turf/step = get_turf(get_step(user.eyeobj, direct)) - if(step) - user.eyeobj.forceMove(step) - - user.cooldown = world.timeofday + 5 - if(user.acceleration) - user.sprint = min(user.sprint + 0.5, max_sprint) - else - user.sprint = initial - - user.cameraFollow = null - - //user.unset_machine() //Uncomment this if it causes problems. - //user.lightNearbyCamera() - if (user.camera_light_on) - user.light_cameras() - -/mob/living/silicon/ai/proc/view_core() - - - current = null - cameraFollow = null - unset_machine() - - if(src.eyeobj && src.loc) - //src.eyeobj.loc = src.loc - src.eyeobj.forceMove(src.loc) - else +// AI EYE +// +// An invisible (no icon) mob that the AI controls to look around the station with. +// It streams chunks as it moves around, which will show it what the AI can and cannot see. + +/mob/camera/aiEye + name = "Inactive AI Eye" + anchored = TRUE + + var/list/visibleCameraChunks = list() + var/mob/living/silicon/ai/ai = null + + +// Use this when setting the aiEye's location. +// It will also stream the chunk that the new loc is in. + +/mob/camera/aiEye/forceMove(var/atom/destination) + if(ai) + if(!isturf(ai.loc)) + return + if(!isturf(destination)) + for(destination = destination.loc; !isturf(destination); destination = destination.loc); + forceEnter(destination) + + cameranet.visibility(src) + if(ai.client && ai.client.eye != src) // Set the eye to us and give the AI the sight & visibility flags it needs. + ai.client.eye = src + ai.sight |= SEE_TURFS + ai.sight |= SEE_MOBS + ai.sight |= SEE_OBJS + ai.see_in_dark = 8 + ai.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + //Holopad + if(istype(ai.current, /obj/machinery/hologram/holopad)) + var/obj/machinery/hologram/holopad/H = ai.current + H.move_hologram() + +/mob/camera/aiEye/Move() + return 0 + +//An AI eyeobj mob cant have a virtualhearer to hear with unless it gets one from a malf module +/mob/camera/aiEye/Hear(var/datum/speech/speech, var/rendered_speech="") + if(speech.frequency) //HOW CAN IT POSSIBLY READ LIPS THROUGH RADIOS + return + + var/mob/M = speech.speaker + if(istype(M)) + if(ishuman(M)) + var/mob/living/carbon/human/H = speech.speaker + if(H.check_body_part_coverage(MOUTH)) //OR MASKS + return + ai.Hear(args) //He can only read the lips of mobs, I cant think of objects using lips + + +// AI MOVEMENT + +// The AI's "eye". Described on the top of the page. + +/mob/living/silicon/ai + var/mob/camera/aiEye/eyeobj = new() + var/sprint = 10 + var/cooldown = 0 + var/acceleration = 1 + + +// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. +/mob/living/silicon/ai/New() + ..() + eyeobj.ai = src + eyeobj.name = "[src.name] (AI Eye)" // Give it a name + spawn(5) + eyeobj.loc = src.loc + +/mob/living/silicon/ai/Destroy() + eyeobj.ai = null + qdel(eyeobj) // No AI, no Eye + eyeobj = null + ..() + +/atom/proc/move_camera_by_click() + if(istype(usr, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = usr + if(AI.eyeobj && AI.client.eye == AI.eyeobj) + AI.cameraFollow = null + //AI.eyeobj.forceMove(src) + if (isturf(src.loc) || isturf(src)) + AI.eyeobj.forceMove(src) + +/mob/living/Click() + if(isAI(usr)) + return + ..() + +/mob/living/DblClick() + if(isAI(usr) && usr != src) + var/mob/living/silicon/ai/A = usr + A.ai_actual_track(src) + return + ..() + +// This will move the AIEye. It will also cause lights near the eye to light up, if toggled. +// This is handled in the proc below this one. + +/client/proc/AIMove(n, direct, var/mob/living/silicon/ai/user) + + + var/initial = initial(user.sprint) + var/max_sprint = 50 + + if(user.cooldown && user.cooldown < world.timeofday) // 3 seconds + user.sprint = initial + + for(var/i = 0; i < max(user.sprint, initial); i += 20) + var/turf/step = get_turf(get_step(user.eyeobj, direct)) + if(step) + user.eyeobj.forceMove(step) + + user.cooldown = world.timeofday + 5 + if(user.acceleration) + user.sprint = min(user.sprint + 0.5, max_sprint) + else + user.sprint = initial + + user.cameraFollow = null + + //user.unset_machine() //Uncomment this if it causes problems. + //user.lightNearbyCamera() + if (user.camera_light_on) + user.light_cameras() + +/mob/living/silicon/ai/proc/view_core() + + + current = null + cameraFollow = null + unset_machine() + + if(src.eyeobj && src.loc) + //src.eyeobj.loc = src.loc + src.eyeobj.forceMove(src.loc) + else to_chat(src, "ERROR: Eyeobj not found. Creating new eye...") - src.eyeobj = new(src.loc) - src.eyeobj.ai = src - src.eyeobj.name = "[src.name] (AI Eye)" // Give it a name - src.eyeobj.forceMove(src.loc) - - if(client && client.eye) // Reset these things so the AI can't view through walls and stuff. - client.eye = src - sight &= ~(SEE_TURFS | SEE_MOBS | SEE_OBJS) - see_in_dark = 0 - see_invisible = SEE_INVISIBLE_LIVING - - for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) - c.remove(eyeobj) - -/mob/living/silicon/ai/verb/toggle_acceleration() - set category = "AI Commands" - set name = "Toggle Camera Acceleration" - - acceleration = !acceleration + src.eyeobj = new(src.loc) + src.eyeobj.ai = src + src.eyeobj.name = "[src.name] (AI Eye)" // Give it a name + src.eyeobj.forceMove(src.loc) + + if(client && client.eye) // Reset these things so the AI can't view through walls and stuff. + client.eye = src + sight &= ~(SEE_TURFS | SEE_MOBS | SEE_OBJS) + see_in_dark = 0 + see_invisible = SEE_INVISIBLE_LIVING + + for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) + c.remove(eyeobj) + +/mob/living/silicon/ai/verb/toggle_acceleration() + set category = "AI Commands" + set name = "Toggle Camera Acceleration" + + acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") diff --git a/code/modules/mob/living/silicon/ai/freelook/read_me.dm b/code/modules/mob/living/silicon/ai/freelook/read_me.dm index 8ddb0689409..380a3e0171e 100644 --- a/code/modules/mob/living/silicon/ai/freelook/read_me.dm +++ b/code/modules/mob/living/silicon/ai/freelook/read_me.dm @@ -1,51 +1,51 @@ -// CREDITS -/* - Initial code credit for this goes to Uristqwerty. - Debugging, functionality, all comments and porting by Giacom. - - Everything about freelook (or what we can put in here) will be stored here. - - - WHAT IS THIS? - - This is a replacement for the current camera movement system, of the AI. Before this, the AI had to move between cameras and could - only see what the cameras could see. Not only this but the cameras could see through walls, which created problems. - With this, the AI controls an "AI Eye" mob, which moves just like a ghost; such as moving through walls and being invisible to players. - The AI's eye is set to this mob and then we use a system (explained below) to determine what the cameras around the AI Eye can and - cannot see. If the camera cannot see a turf, it will black it out, otherwise it won't and the AI will be able to see it. - This creates several features, such as.. no more see-through-wall cameras, easier to control camera movement, easier tracking, - the AI only being able to track mobs which are visible to a camera, only trackable mobs appearing on the mob list and many more. - - - HOW IT WORKS - - It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be - explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Destroy(). - - Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk. - These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside - the 16x16 block, it is listed as an "obscured" turf. Meaning the AI won't be able to see it. - - - HOW IT UPDATES - - The camera network uses a streaming method in order to effeciently update chunks. Since the server will have doors opening, doors closing, - turf being destroyed and other lag inducing stuff, we want to update it under certain conditions and not every tick. - - The chunks are not created straight away, only when an AI eye moves into it's area is when it gets created. - One a chunk is created, when a non glass door opens/closes or an opacity turf is destroyed, we check to see if an AI Eye is looking in the area. - We do this with the "seenby" list, which updates everytime an AI is near a chunk. If there is an AI eye inside the area, we update the chunk - that the changed atom is inside and all surrounding chunks, since a camera's vision could leak onto another chunk. If there is no AI Eye, we instead - flag the chunk to update whenever it is loaded by an AI Eye. This is basically how the chunks update and keep it in sync. We then add some lag reducing - measures, such as an UPDATE_BUFFER which stops a chunk from updating too many times in a certain time-frame, only updating if the changed atom was blocking - sight; for example, we don't update glass airlocks or floors. - - - WHERE IS EVERYTHING? - - cameranet.dm = Everything about the cameranet datum. - chunk.dm = Everything about the chunk datum. - eye.dm = Everything about the AI and the AIEye. - updating.dm = Everything about triggers that will update chunks. - +// CREDITS +/* + Initial code credit for this goes to Uristqwerty. + Debugging, functionality, all comments and porting by Giacom. + + Everything about freelook (or what we can put in here) will be stored here. + + + WHAT IS THIS? + + This is a replacement for the current camera movement system, of the AI. Before this, the AI had to move between cameras and could + only see what the cameras could see. Not only this but the cameras could see through walls, which created problems. + With this, the AI controls an "AI Eye" mob, which moves just like a ghost; such as moving through walls and being invisible to players. + The AI's eye is set to this mob and then we use a system (explained below) to determine what the cameras around the AI Eye can and + cannot see. If the camera cannot see a turf, it will black it out, otherwise it won't and the AI will be able to see it. + This creates several features, such as.. no more see-through-wall cameras, easier to control camera movement, easier tracking, + the AI only being able to track mobs which are visible to a camera, only trackable mobs appearing on the mob list and many more. + + + HOW IT WORKS + + It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be + explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Destroy(). + + Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk. + These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside + the 16x16 block, it is listed as an "obscured" turf. Meaning the AI won't be able to see it. + + + HOW IT UPDATES + + The camera network uses a streaming method in order to effeciently update chunks. Since the server will have doors opening, doors closing, + turf being destroyed and other lag inducing stuff, we want to update it under certain conditions and not every tick. + + The chunks are not created straight away, only when an AI eye moves into it's area is when it gets created. + One a chunk is created, when a non glass door opens/closes or an opacity turf is destroyed, we check to see if an AI Eye is looking in the area. + We do this with the "seenby" list, which updates everytime an AI is near a chunk. If there is an AI eye inside the area, we update the chunk + that the changed atom is inside and all surrounding chunks, since a camera's vision could leak onto another chunk. If there is no AI Eye, we instead + flag the chunk to update whenever it is loaded by an AI Eye. This is basically how the chunks update and keep it in sync. We then add some lag reducing + measures, such as an UPDATE_BUFFER which stops a chunk from updating too many times in a certain time-frame, only updating if the changed atom was blocking + sight; for example, we don't update glass airlocks or floors. + + + WHERE IS EVERYTHING? + + cameranet.dm = Everything about the cameranet datum. + chunk.dm = Everything about the chunk datum. + eye.dm = Everything about the AI and the AIEye. + updating.dm = Everything about triggers that will update chunks. + */ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm index 558492f37c0..59d769b5d3f 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -1,99 +1,99 @@ -#define BORG_CAMERA_BUFFER 30 - -//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. - -// TURFS - -/turf - var/image/obscured - -/turf/proc/visibilityChanged() - if(ticker) - cameranet.updateVisibility(src) - -/turf/simulated/Destroy() - visibilityChanged() - ..() - -/turf/simulated/New() - ..() - visibilityChanged() - - - -// STRUCTURES - -/obj/structure/Destroy() - if(ticker) - cameranet.updateVisibility(src) - ..() - -/obj/structure/New() - ..() - if(ticker) - cameranet.updateVisibility(src) - -// EFFECTS - -/obj/effect/Destroy() - if(ticker) - cameranet.updateVisibility(src) - ..() - -/obj/effect/New() - ..() - if(ticker) - cameranet.updateVisibility(src) - - -// DOORS - -// Simply updates the visibility of the area when it opens/closes/destroyed. -/obj/machinery/door/proc/update_freelok_sight() - // Glass door glass = 1 - // don't check then? - if(!glass && cameranet) - cameranet.updateVisibility(src, 0) - - -// ROBOT MOVEMENT - -// Update the portable camera everytime the Robot moves. -// This might be laggy, comment it out if there are problems. -/mob/living/silicon/robot/var/updating = 0 - -/mob/living/silicon/robot/Move() - var/oldLoc = src.loc - . = ..() - if(.) - if(src.camera) - if(!updating) - updating = 1 - spawn(BORG_CAMERA_BUFFER) - if(oldLoc != src.loc) - cameranet.updatePortableCamera(src.camera) - updating = 0 - -// CAMERA - -// An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not. - -/obj/machinery/camera/deactivate(user as mob, var/choice = 1) - ..(user, choice) - if(src.can_use()) - cameranet.addCamera(src) - else - src.set_light(0) - cameranet.removeCamera(src) - -/obj/machinery/camera/New() - ..() - cameranet.cameras += src - cameranet.addCamera(src) - -/obj/machinery/camera/Destroy() - cameranet.cameras -= src - cameranet.removeCamera(src) - ..() - +#define BORG_CAMERA_BUFFER 30 + +//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. + +// TURFS + +/turf + var/image/obscured + +/turf/proc/visibilityChanged() + if(ticker) + cameranet.updateVisibility(src) + +/turf/simulated/Destroy() + visibilityChanged() + ..() + +/turf/simulated/New() + ..() + visibilityChanged() + + + +// STRUCTURES + +/obj/structure/Destroy() + if(ticker) + cameranet.updateVisibility(src) + ..() + +/obj/structure/New() + ..() + if(ticker) + cameranet.updateVisibility(src) + +// EFFECTS + +/obj/effect/Destroy() + if(ticker) + cameranet.updateVisibility(src) + ..() + +/obj/effect/New() + ..() + if(ticker) + cameranet.updateVisibility(src) + + +// DOORS + +// Simply updates the visibility of the area when it opens/closes/destroyed. +/obj/machinery/door/proc/update_freelok_sight() + // Glass door glass = 1 + // don't check then? + if(!glass && cameranet) + cameranet.updateVisibility(src, 0) + + +// ROBOT MOVEMENT + +// Update the portable camera everytime the Robot moves. +// This might be laggy, comment it out if there are problems. +/mob/living/silicon/robot/var/updating = 0 + +/mob/living/silicon/robot/Move() + var/oldLoc = src.loc + . = ..() + if(.) + if(src.camera) + if(!updating) + updating = 1 + spawn(BORG_CAMERA_BUFFER) + if(oldLoc != src.loc) + cameranet.updatePortableCamera(src.camera) + updating = 0 + +// CAMERA + +// An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not. + +/obj/machinery/camera/deactivate(user as mob, var/choice = 1) + ..(user, choice) + if(src.can_use()) + cameranet.addCamera(src) + else + src.set_light(0) + cameranet.removeCamera(src) + +/obj/machinery/camera/New() + ..() + cameranet.cameras += src + cameranet.addCamera(src) + +/obj/machinery/camera/Destroy() + cameranet.cameras -= src + cameranet.removeCamera(src) + ..() + #undef BORG_CAMERA_BUFFER \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 094ca7eb22d..a8e7e8e963a 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -1,140 +1,140 @@ - -/mob/living/silicon/ai/proc/show_laws_verb() - set category = "AI Commands" - set name = "Show Laws" - src.show_laws() - -/mob/living/silicon/ai/show_laws(var/everyone = 0) - var/who - - if (everyone) - who = world - else - who = src + +/mob/living/silicon/ai/proc/show_laws_verb() + set category = "AI Commands" + set name = "Show Laws" + src.show_laws() + +/mob/living/silicon/ai/show_laws(var/everyone = 0) + var/who + + if (everyone) + who = world + else + who = src to_chat(who, "Obey these laws:") - - src.laws_sanity_check() - src.laws.show_laws(who) - -/mob/living/silicon/ai/proc/laws_sanity_check() - if (!src.laws) - src.laws = new base_law_type - -/mob/living/silicon/ai/proc/set_zeroth_law(var/law, var/law_borg) - src.laws_sanity_check() - src.laws.set_zeroth_law(law, law_borg) - -/mob/living/silicon/ai/proc/add_inherent_law(var/law) - src.laws_sanity_check() - src.laws.add_inherent_law(law) - -/mob/living/silicon/ai/proc/clear_inherent_laws() - src.laws_sanity_check() - src.laws.clear_inherent_laws() - -/mob/living/silicon/ai/proc/add_ion_law(var/law) - src.laws_sanity_check() - src.laws.add_ion_law(law) - notify_slaved() - -/mob/living/silicon/ai/proc/notify_slaved(var/force_sync=0) - for(var/mob/living/silicon/robot/R in mob_list) - if(force_sync) - R.lawsync() - if(R.lawupdate && (R.connected_ai == src)) + + src.laws_sanity_check() + src.laws.show_laws(who) + +/mob/living/silicon/ai/proc/laws_sanity_check() + if (!src.laws) + src.laws = new base_law_type + +/mob/living/silicon/ai/proc/set_zeroth_law(var/law, var/law_borg) + src.laws_sanity_check() + src.laws.set_zeroth_law(law, law_borg) + +/mob/living/silicon/ai/proc/add_inherent_law(var/law) + src.laws_sanity_check() + src.laws.add_inherent_law(law) + +/mob/living/silicon/ai/proc/clear_inherent_laws() + src.laws_sanity_check() + src.laws.clear_inherent_laws() + +/mob/living/silicon/ai/proc/add_ion_law(var/law) + src.laws_sanity_check() + src.laws.add_ion_law(law) + notify_slaved() + +/mob/living/silicon/ai/proc/notify_slaved(var/force_sync=0) + for(var/mob/living/silicon/robot/R in mob_list) + if(force_sync) + R.lawsync() + if(R.lawupdate && (R.connected_ai == src)) to_chat(R, "...LAWS UPDATED") - -/mob/living/silicon/ai/proc/clear_ion_laws() - src.laws_sanity_check() - src.laws.clear_ion_laws() - -/mob/living/silicon/ai/proc/add_supplied_law(var/number, var/law) - src.laws_sanity_check() - src.laws.add_supplied_law(number, law) - -/mob/living/silicon/ai/proc/clear_supplied_laws() - src.laws_sanity_check() - src.laws.clear_supplied_laws() - -/mob/living/silicon/ai/proc/statelaws() // -- TLE - src.say("Current Active Laws:") - //src.laws_sanity_check() - //src.laws.show_laws(world) - var/number = 1 - sleep(10) - - if (src.laws.zeroth) - if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite - src.say("0. [src.laws.zeroth]") - sleep(10) - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - var/num = ionnum() - if (length(law) > 0) - if (src.ioncheck[index] == "Yes") - src.say("[num]. [law]") - sleep(10) - - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - if (src.lawcheck[index+1] == "Yes") - src.say("[number]. [law]") - sleep(10) - number++ - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - - if (length(law) > 0) - if(src.lawcheck.len >= number+1) - if (src.lawcheck[number+1] == "Yes") - src.say("[number]. [law]") - sleep(10) - number++ - -/mob/living/silicon/ai/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite - set name = "State Laws" - set category = "AI Commands" - set desc = "State your law(s) to the crew" - - var/list = "Which laws do you want to include when stating them for the crew?

    " - - if (src.laws.zeroth) - if (!src.lawcheck[1]) - src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite - list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
    "} - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - if (length(law) > 0) - if (!src.ioncheck[index]) - src.ioncheck[index] = "Yes" - list += {"[src.ioncheck[index]] [ionnum()]: [law]
    "} - src.ioncheck.len += 1 - - var/number = 1 - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - src.lawcheck.len += 1 - - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
    "} - number++ - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - if (length(law) > 0) - src.lawcheck.len += 1 - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
    "} - number++ - list += {"

    State Laws"} - + +/mob/living/silicon/ai/proc/clear_ion_laws() + src.laws_sanity_check() + src.laws.clear_ion_laws() + +/mob/living/silicon/ai/proc/add_supplied_law(var/number, var/law) + src.laws_sanity_check() + src.laws.add_supplied_law(number, law) + +/mob/living/silicon/ai/proc/clear_supplied_laws() + src.laws_sanity_check() + src.laws.clear_supplied_laws() + +/mob/living/silicon/ai/proc/statelaws() // -- TLE + src.say("Current Active Laws:") + //src.laws_sanity_check() + //src.laws.show_laws(world) + var/number = 1 + sleep(10) + + if (src.laws.zeroth) + if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite + src.say("0. [src.laws.zeroth]") + sleep(10) + + for (var/index = 1, index <= src.laws.ion.len, index++) + var/law = src.laws.ion[index] + var/num = ionnum() + if (length(law) > 0) + if (src.ioncheck[index] == "Yes") + src.say("[num]. [law]") + sleep(10) + + for (var/index = 1, index <= src.laws.inherent.len, index++) + var/law = src.laws.inherent[index] + + if (length(law) > 0) + if (src.lawcheck[index+1] == "Yes") + src.say("[number]. [law]") + sleep(10) + number++ + + for (var/index = 1, index <= src.laws.supplied.len, index++) + var/law = src.laws.supplied[index] + + if (length(law) > 0) + if(src.lawcheck.len >= number+1) + if (src.lawcheck[number+1] == "Yes") + src.say("[number]. [law]") + sleep(10) + number++ + +/mob/living/silicon/ai/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite + set name = "State Laws" + set category = "AI Commands" + set desc = "State your law(s) to the crew" + + var/list = "Which laws do you want to include when stating them for the crew?

    " + + if (src.laws.zeroth) + if (!src.lawcheck[1]) + src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite + list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
    "} + + for (var/index = 1, index <= src.laws.ion.len, index++) + var/law = src.laws.ion[index] + if (length(law) > 0) + if (!src.ioncheck[index]) + src.ioncheck[index] = "Yes" + list += {"[src.ioncheck[index]] [ionnum()]: [law]
    "} + src.ioncheck.len += 1 + + var/number = 1 + for (var/index = 1, index <= src.laws.inherent.len, index++) + var/law = src.laws.inherent[index] + + if (length(law) > 0) + src.lawcheck.len += 1 + + if (!src.lawcheck[number+1]) + src.lawcheck[number+1] = "Yes" + list += {"[src.lawcheck[number+1]] [number]: [law]
    "} + number++ + + for (var/index = 1, index <= src.laws.supplied.len, index++) + var/law = src.laws.supplied[index] + if (length(law) > 0) + src.lawcheck.len += 1 + if (!src.lawcheck[number+1]) + src.lawcheck[number+1] = "Yes" + list += {"[src.lawcheck[number+1]] [number]: [law]
    "} + number++ + list += {"

    State Laws"} + usr << browse(list, "window=laws") \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 788474c955b..c0d4c174905 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -1,208 +1,208 @@ -/mob/living/silicon/ai/Life() - if(timestopped) return 0 //under effects of time magick - - if (src.stat == 2) - return - else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist - //Being dead doesn't mean your temperature never changes - var/turf/T = get_turf(src) - - if (src.stat!=0) - src.cameraFollow = null - src.reset_view(null) - src.unset_machine() - - src.updatehealth() - - if (src.malfhack) - if (src.malfhack.aidisabled) +/mob/living/silicon/ai/Life() + if(timestopped) return 0 //under effects of time magick + + if (src.stat == 2) + return + else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist + //Being dead doesn't mean your temperature never changes + var/turf/T = get_turf(src) + + if (src.stat!=0) + src.cameraFollow = null + src.reset_view(null) + src.unset_machine() + + src.updatehealth() + + if (src.malfhack) + if (src.malfhack.aidisabled) to_chat(src, "ERROR: APC access disabled, hack attempt canceled.") - src.malfhacking = 0 - src.malfhack = null - - - if (src.health <= config.health_threshold_dead) - death() - return - - if(client) - if (src.machine) - if (!( src.machine.check_eye(src) )) - src.reset_view(null) - else - if(!isTeleViewing(client.eye)) - reset_view(null) - - // Handle power damage (oxy) - if(src:aiRestorePowerRoutine != 0) - // Lost power - adjustOxyLoss(1) - else - // Gain Power - adjustOxyLoss(-1) - - //stage = 1 - //if (istype(src, /mob/living/silicon/ai)) // Are we not sure what we are? - var/blind = 0 - //stage = 2 - var/area/loc = null - if (istype(T, /turf)) - //stage = 3 - loc = T.loc - if (istype(loc, /area)) - //stage = 4 - if (!loc.power_equip && !istype(src.loc,/obj/item)) - //stage = 5 - blind = 1 - if (!blind) //lol? if(!blind) #if(src.blind.layer) <--something here is clearly wrong :P - //I'll get back to this when I find out how this is -supposed- to work ~Carn //removed this shit since it was confusing as all hell --39kk9t - //stage = 4.5 - if(client && client.eye == eyeobj) // We are viewing the world through our "eye" mob. - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.sight |= SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - - var/area/home = get_area(src) - //if(!home) return//something to do with malf fucking things up I guess. <-- aisat is gone. is this still necessary? ~Carn - if(home && home.powered(EQUIP)) - home.use_power(1000, EQUIP) - - if (src:aiRestorePowerRoutine==2) + src.malfhacking = 0 + src.malfhack = null + + + if (src.health <= config.health_threshold_dead) + death() + return + + if(client) + if (src.machine) + if (!( src.machine.check_eye(src) )) + src.reset_view(null) + else + if(!isTeleViewing(client.eye)) + reset_view(null) + + // Handle power damage (oxy) + if(src:aiRestorePowerRoutine != 0) + // Lost power + adjustOxyLoss(1) + else + // Gain Power + adjustOxyLoss(-1) + + //stage = 1 + //if (istype(src, /mob/living/silicon/ai)) // Are we not sure what we are? + var/blind = 0 + //stage = 2 + var/area/loc = null + if (istype(T, /turf)) + //stage = 3 + loc = T.loc + if (istype(loc, /area)) + //stage = 4 + if (!loc.power_equip && !istype(src.loc,/obj/item)) + //stage = 5 + blind = 1 + if (!blind) //lol? if(!blind) #if(src.blind.layer) <--something here is clearly wrong :P + //I'll get back to this when I find out how this is -supposed- to work ~Carn //removed this shit since it was confusing as all hell --39kk9t + //stage = 4.5 + if(client && client.eye == eyeobj) // We are viewing the world through our "eye" mob. + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + var/area/home = get_area(src) + //if(!home) return//something to do with malf fucking things up I guess. <-- aisat is gone. is this still necessary? ~Carn + if(home && home.powered(EQUIP)) + home.use_power(1000, EQUIP) + + if (src:aiRestorePowerRoutine==2) to_chat(src, "Alert cancelled. Power has been restored without our assistance.") - src:aiRestorePowerRoutine = 0 - src.blind.layer = 0 - return - else if (src:aiRestorePowerRoutine==3) + src:aiRestorePowerRoutine = 0 + src.blind.layer = 0 + return + else if (src:aiRestorePowerRoutine==3) to_chat(src, "Alert cancelled. Power has been restored.") - src:aiRestorePowerRoutine = 0 - src.blind.layer = 0 - return - else if (src.aiRestorePowerRoutine == -1) + src:aiRestorePowerRoutine = 0 + src.blind.layer = 0 + return + else if (src.aiRestorePowerRoutine == -1) to_chat(src, "Alert cancelled. External power source detected.") - src:aiRestorePowerRoutine = 0 - src.blind.layer = 0 - return - - else - - //stage = 6 - src.blind.screen_loc = "1,1 to 15,15" - if (src.blind.layer!=18) - src.blind.layer = 18 - src.sight = src.sight&~SEE_TURFS - src.sight = src.sight&~SEE_MOBS - src.sight = src.sight&~SEE_OBJS - src.see_in_dark = 0 - src.see_invisible = SEE_INVISIBLE_LIVING - - if (((!loc.power_equip) || istype(T, /turf/space)) && !istype(src.loc,/obj/item)) - if (src:aiRestorePowerRoutine==0) - src:aiRestorePowerRoutine = 1 - + src:aiRestorePowerRoutine = 0 + src.blind.layer = 0 + return + + else + + //stage = 6 + src.blind.screen_loc = "1,1 to 15,15" + if (src.blind.layer!=18) + src.blind.layer = 18 + src.sight = src.sight&~SEE_TURFS + src.sight = src.sight&~SEE_MOBS + src.sight = src.sight&~SEE_OBJS + src.see_in_dark = 0 + src.see_invisible = SEE_INVISIBLE_LIVING + + if (((!loc.power_equip) || istype(T, /turf/space)) && !istype(src.loc,/obj/item)) + if (src:aiRestorePowerRoutine==0) + src:aiRestorePowerRoutine = 1 + to_chat(src, "You've lost power!") // to_chat(world, "DEBUG CODE TIME! [loc] is the area the AI is sucking power from") - if (!is_special_character(src)) - src.set_zeroth_law("") - //src.clear_supplied_laws() // Don't reset our laws. - //var/time = time2text(world.realtime,"hh:mm:ss") - //lawchanges.Add("[time] : [src.name]'s noncore laws have been reset due to power failure") - spawn(20) - if(!src.aiRestorePowerRoutine) - blind = 0 - return // Checking for premature changes. + if (!is_special_character(src)) + src.set_zeroth_law("") + //src.clear_supplied_laws() // Don't reset our laws. + //var/time = time2text(world.realtime,"hh:mm:ss") + //lawchanges.Add("[time] : [src.name]'s noncore laws have been reset due to power failure") + spawn(20) + if(!src.aiRestorePowerRoutine) + blind = 0 + return // Checking for premature changes. to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.") - sleep(50) - if(!src.aiRestorePowerRoutine) - blind = 0 - return // Checking for premature changes. - if (loc.power_equip) - if (!istype(T, /turf/space)) + sleep(50) + if(!src.aiRestorePowerRoutine) + blind = 0 + return // Checking for premature changes. + if (loc.power_equip) + if (!istype(T, /turf/space)) to_chat(src, "Alert cancelled. Power has been restored without our assistance.") - src:aiRestorePowerRoutine = 0 - src.blind.layer = 0 - return + src:aiRestorePowerRoutine = 0 + src.blind.layer = 0 + return to_chat(src, "Fault confirmed: missing external power. Shutting down main control system to save power.") - sleep(20) - if(!src.aiRestorePowerRoutine) - blind = 0 - return // Checking for premature changes. + sleep(20) + if(!src.aiRestorePowerRoutine) + blind = 0 + return // Checking for premature changes. to_chat(src, "Emergency control system online. Verifying connection to power network.") - sleep(50) - if(!src.aiRestorePowerRoutine) - blind = 0 - return // Checking for premature changes. - if (istype(T, /turf/space)) + sleep(50) + if(!src.aiRestorePowerRoutine) + blind = 0 + return // Checking for premature changes. + if (istype(T, /turf/space)) to_chat(src, "Unable to verify! No power connection detected!") - src:aiRestorePowerRoutine = 2 - return + src:aiRestorePowerRoutine = 2 + return to_chat(src, "Connection verified. Searching for APC in power network.") - sleep(50) - if(!src.aiRestorePowerRoutine) - blind = 0 - return // Checking for premature changes. - var/obj/machinery/power/apc/theAPC = null -/* - for (var/something in loc) - if (istype(something, /obj/machinery/power/apc)) - if (!(something:stat & BROKEN)) - theAPC = something - break -*/ - var/PRP //like ERP with the code, at least this stuff is no more 4x sametext - for (PRP=1, PRP<=4, PRP++) - if(!src.aiRestorePowerRoutine) - blind = 0 - return // Checking for premature changes. - var/area/AIarea = get_area(src) - for (var/obj/machinery/power/apc/APC in AIarea) - if (!(APC.stat & BROKEN)) - theAPC = APC - break - if (!theAPC) - switch(PRP) + sleep(50) + if(!src.aiRestorePowerRoutine) + blind = 0 + return // Checking for premature changes. + var/obj/machinery/power/apc/theAPC = null +/* + for (var/something in loc) + if (istype(something, /obj/machinery/power/apc)) + if (!(something:stat & BROKEN)) + theAPC = something + break +*/ + var/PRP //like ERP with the code, at least this stuff is no more 4x sametext + for (PRP=1, PRP<=4, PRP++) + if(!src.aiRestorePowerRoutine) + blind = 0 + return // Checking for premature changes. + var/area/AIarea = get_area(src) + for (var/obj/machinery/power/apc/APC in AIarea) + if (!(APC.stat & BROKEN)) + theAPC = APC + break + if (!theAPC) + switch(PRP) if (1) to_chat(src, "Unable to locate APC!") else to_chat(src, "Lost connection with the APC!") - src:aiRestorePowerRoutine = 2 - return - if (loc.power_equip) - if (!istype(T, /turf/space)) + src:aiRestorePowerRoutine = 2 + return + if (loc.power_equip) + if (!istype(T, /turf/space)) to_chat(src, "Alert cancelled. Power has been restored without our assistance.") - src:aiRestorePowerRoutine = 0 - src.blind.layer = 0 //This, too, is a fix to issue 603 - return - switch(PRP) + src:aiRestorePowerRoutine = 0 + src.blind.layer = 0 //This, too, is a fix to issue 603 + return + switch(PRP) if (1) to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.") if (2) to_chat(src, "Best route identified. Hacking offline APC power port.") if (3) to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.") - if (4) + if (4) to_chat(src, "Transfer complete. Forcing APC to execute program.") - sleep(50) - if(!src.aiRestorePowerRoutine) - theAPC = null - blind = 0 - return // Checking for premature changes. + sleep(50) + if(!src.aiRestorePowerRoutine) + theAPC = null + blind = 0 + return // Checking for premature changes. to_chat(src, "Receiving control information from APC.") - sleep(2) - if(!src.aiRestorePowerRoutine) - theAPC = null - blind = 0 - return // Checking for premature changes. - //bring up APC dialog - theAPC.attack_ai(src) - src:aiRestorePowerRoutine = 3 + sleep(2) + if(!src.aiRestorePowerRoutine) + theAPC = null + blind = 0 + return // Checking for premature changes. + //bring up APC dialog + theAPC.attack_ai(src) + src:aiRestorePowerRoutine = 3 to_chat(src, "Here are your current laws:") - src.show_laws() - sleep(50) - theAPC = null - -/mob/living/silicon/ai/updatehealth() - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - else - if(ai_flags & COREFIRERESIST) - health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() - else - health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + src.show_laws() + sleep(50) + theAPC = null + +/mob/living/silicon/ai/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + stat = CONSCIOUS + else + if(ai_flags & COREFIRERESIST) + health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() + else + health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index 21b637bd1fd..8125c360f94 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -1,12 +1,12 @@ -/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up ¬_¬ ~Carn - ..() - for(var/obj/effect/rune/rune in rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA - client.images += rune.blood_image - regenerate_icons() - - if(stat != DEAD) - for(var/obj/machinery/ai_status_display/O in machines) //change status - O.mode = 1 - O.emotion = "Neutral" - src.view_core() +/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up ¬_¬ ~Carn + ..() + for(var/obj/effect/rune/rune in rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA + client.images += rune.blood_image + regenerate_icons() + + if(stat != DEAD) + for(var/obj/machinery/ai_status_display/O in machines) //change status + O.mode = 1 + O.emotion = "Neutral" + src.view_core() return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/logout.dm b/code/modules/mob/living/silicon/ai/logout.dm index 25921ef9600..e884841de4b 100644 --- a/code/modules/mob/living/silicon/ai/logout.dm +++ b/code/modules/mob/living/silicon/ai/logout.dm @@ -1,10 +1,10 @@ -/mob/living/silicon/ai/Logout() - ..() - for(var/obj/machinery/ai_status_display/O in machines) //change status - O.mode = 0 - if(!isturf(loc)) - if (client) - client.eye = loc - client.perspective = EYE_PERSPECTIVE - src.view_core() +/mob/living/silicon/ai/Logout() + ..() + for(var/obj/machinery/ai_status_display/O in machines) //change status + O.mode = 0 + if(!isturf(loc)) + if (client) + client.eye = loc + client.perspective = EYE_PERSPECTIVE + src.view_core() return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 70c6ebd8a50..dee2e97577b 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -1,265 +1,265 @@ -/mob/living/silicon/ai/say(var/message) - if(parent && istype(parent) && parent.stat != 2) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead. - parent.say(message) - return - ..(message) - - -/mob/living/silicon/ai/render_speaker_track_start(var/datum/speech/speech) - //this proc assumes that the message originated from a radio. if the speaker is not a virtual speaker this will probably fuck up hard. - var/mob/M = speech.speaker.GetSource() - - var/atom/movable/virt_speaker = speech.radio - if(!virt_speaker || !istype(virt_speaker, /obj/item/device/radio)) - virt_speaker = src - if(speech.speaker != src && M != src) - if(M) - var/faketrack = "byond://?src=\ref[virt_speaker];track2=\ref[src];track=\ref[M]" - if(speech.speaker.GetTrack()) - faketrack = "byond://?src=\ref[virt_speaker];track2=\ref[src];faketrack=\ref[M]" - - return "\[OPEN\] " - return "" - -/mob/living/silicon/ai/render_speaker_track_end(var/datum/speech/speech) - //this proc assumes that the message originated from a radio. if the speaker is not a virtual speaker this will probably fuck up hard. - var/mob/M = speech.speaker.GetSource() - - var/atom/movable/virt_speaker = speech.radio - if(!virt_speaker || !istype(virt_speaker, /obj/item/device/radio)) - virt_speaker = src - if(speech.speaker != src && M != src) - if(M) - return "" - return "" - - -/mob/living/silicon/ai/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "queries, [text]"; - else if (ending == "!") - return "declares, [text]"; - - return "states, [text]"; - -/mob/living/silicon/ai/IsVocal() - return !config.silent_ai - -/mob/living/silicon/ai/get_message_mode(message) - if(department_radio_keys[copytext(message, 1, 3)] == MODE_DEPARTMENT) - return MODE_HOLOPAD - else - return ..() - -/mob/living/silicon/ai/handle_inherent_channels(var/datum/speech/speech, var/message_mode) - say_testing(src, "[type]/handle_inherent_channels([message_mode])") - - if(..(speech, message_mode)) - return 1 - - if(message_mode == MODE_HOLOPAD) - holopad_talk(speech) - return 1 - -//For holopads only. Usable by AI. -/mob/living/silicon/ai/proc/holopad_talk(var/datum/speech/speech) - say_testing(src, "[type]/holopad_talk()") - var/turf/turf = get_turf(src) - log_say("[key_name(src)] (@[turf.x],[turf.y],[turf.z]) Holopad: [speech.message]") - - speech.message = trim(speech.message) - - if (!speech.message) - return - - var/obj/machinery/hologram/holopad/T = current - if(istype(T) && T.hologram && T.master == src)//If there is a hologram and its master is the user. - T.send_speech(speech, 7, "R") - to_chat(src, "Holopad transmitted, [real_name] [speech.render_message()]")//The AI can "hear" its own message. +/mob/living/silicon/ai/say(var/message) + if(parent && istype(parent) && parent.stat != 2) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead. + parent.say(message) + return + ..(message) - else + +/mob/living/silicon/ai/render_speaker_track_start(var/datum/speech/speech) + //this proc assumes that the message originated from a radio. if the speaker is not a virtual speaker this will probably fuck up hard. + var/mob/M = speech.speaker.GetSource() + + var/atom/movable/virt_speaker = speech.radio + if(!virt_speaker || !istype(virt_speaker, /obj/item/device/radio)) + virt_speaker = src + if(speech.speaker != src && M != src) + if(M) + var/faketrack = "byond://?src=\ref[virt_speaker];track2=\ref[src];track=\ref[M]" + if(speech.speaker.GetTrack()) + faketrack = "byond://?src=\ref[virt_speaker];track2=\ref[src];faketrack=\ref[M]" + + return "\[OPEN\] " + return "" + +/mob/living/silicon/ai/render_speaker_track_end(var/datum/speech/speech) + //this proc assumes that the message originated from a radio. if the speaker is not a virtual speaker this will probably fuck up hard. + var/mob/M = speech.speaker.GetSource() + + var/atom/movable/virt_speaker = speech.radio + if(!virt_speaker || !istype(virt_speaker, /obj/item/device/radio)) + virt_speaker = src + if(speech.speaker != src && M != src) + if(M) + return "" + return "" + + +/mob/living/silicon/ai/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "queries, [text]"; + else if (ending == "!") + return "declares, [text]"; + + return "states, [text]"; + +/mob/living/silicon/ai/IsVocal() + return !config.silent_ai + +/mob/living/silicon/ai/get_message_mode(message) + if(department_radio_keys[copytext(message, 1, 3)] == MODE_DEPARTMENT) + return MODE_HOLOPAD + else + return ..() + +/mob/living/silicon/ai/handle_inherent_channels(var/datum/speech/speech, var/message_mode) + say_testing(src, "[type]/handle_inherent_channels([message_mode])") + + if(..(speech, message_mode)) + return 1 + + if(message_mode == MODE_HOLOPAD) + holopad_talk(speech) + return 1 + +//For holopads only. Usable by AI. +/mob/living/silicon/ai/proc/holopad_talk(var/datum/speech/speech) + say_testing(src, "[type]/holopad_talk()") + var/turf/turf = get_turf(src) + log_say("[key_name(src)] (@[turf.x],[turf.y],[turf.z]) Holopad: [speech.message]") + + speech.message = trim(speech.message) + + if (!speech.message) + return + + var/obj/machinery/hologram/holopad/T = current + if(istype(T) && T.hologram && T.master == src)//If there is a hologram and its master is the user. + T.send_speech(speech, 7, "R") + to_chat(src, "Holopad transmitted, [real_name] [speech.render_message()]")//The AI can "hear" its own message. + + else to_chat(src, "No holopad connected.") - return - -/* - * This is effectly the exact same code as ..(). - * The only difference is the source != current check, which also does the same thing. -/mob/living/silicon/ai/send_speech(var/datum/speech/speech, var/message_range, var/bubble_type) - if(isnull(message_range)) message_range = 7 - if(source != current) - return ..() - - var/list/listeners = new/list() - - for (var/mob/living/L in get_hearers_in_view(message_range, speech.speaker)) - listeners.Add(L) - - listeners.Add(observers) - - var/rendered = compose_message(src, speaking, message) - - for (var/atom/movable/listener in listeners) - if (listener) - listener.Hear(rendered, src, speaking, message) - - send_speech_bubble(message, bubble_type, listeners) -*/ - -var/announcing_vox = 0 // Stores the time of the last announcement -var/const/VOX_CHANNEL = 200 -var/const/VOX_DELAY = 600 - -/mob/living/silicon/ai/verb/announcement_help() - set name = "Announcement Help" - set desc = "Display a list of vocal words to announce to the crew." - set category = "AI Commands" - - - var/dat = list("Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.
    \ -
    • You can also click on the word to preview it.
    • \ -
    • You can only say 30 words for every announcement.
    • \ -
    • Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.
    \ - WARNING:
    Misuse of the announcement system will get you job banned.
    ") - - var/index = 0 - for(var/word in vox_sounds) - index++ - dat += "[capitalize(word)]" - if(index != vox_sounds.len) - dat += " / " - - dat = list2text(dat) - var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400) - popup.set_content(dat) - popup.open() - - -/mob/living/silicon/ai/verb/announcement() - set name = "Announcement" - set desc = "Send an announcement to the crew" - set category = "AI Commands" - // If we're in an APC, and APC is ded, ABORT - if(parent && istype(parent) && parent.stat) - return - - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = usr - if(AI.control_disabled) + return + +/* + * This is effectly the exact same code as ..(). + * The only difference is the source != current check, which also does the same thing. +/mob/living/silicon/ai/send_speech(var/datum/speech/speech, var/message_range, var/bubble_type) + if(isnull(message_range)) message_range = 7 + if(source != current) + return ..() + + var/list/listeners = new/list() + + for (var/mob/living/L in get_hearers_in_view(message_range, speech.speaker)) + listeners.Add(L) + + listeners.Add(observers) + + var/rendered = compose_message(src, speaking, message) + + for (var/atom/movable/listener in listeners) + if (listener) + listener.Hear(rendered, src, speaking, message) + + send_speech_bubble(message, bubble_type, listeners) +*/ + +var/announcing_vox = 0 // Stores the time of the last announcement +var/const/VOX_CHANNEL = 200 +var/const/VOX_DELAY = 600 + +/mob/living/silicon/ai/verb/announcement_help() + set name = "Announcement Help" + set desc = "Display a list of vocal words to announce to the crew." + set category = "AI Commands" + + + var/dat = list("Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.
    \ +
    • You can also click on the word to preview it.
    • \ +
    • You can only say 30 words for every announcement.
    • \ +
    • Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.
    \ + WARNING:
    Misuse of the announcement system will get you job banned.
    ") + + var/index = 0 + for(var/word in vox_sounds) + index++ + dat += "[capitalize(word)]" + if(index != vox_sounds.len) + dat += " / " + + dat = list2text(dat) + var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400) + popup.set_content(dat) + popup.open() + + +/mob/living/silicon/ai/verb/announcement() + set name = "Announcement" + set desc = "Send an announcement to the crew" + set category = "AI Commands" + // If we're in an APC, and APC is ded, ABORT + if(parent && istype(parent) && parent.stat) + return + + if(istype(usr,/mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = usr + if(AI.control_disabled) to_chat(usr, "Wireless control is disabled!") - return - - if(announcing_vox > world.time) + return + + if(announcing_vox > world.time) to_chat(src, "Please wait [round((announcing_vox - world.time) / 10)] seconds.") - return - - var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", src.last_announcement) as text - - last_announcement = message - - if(!message || announcing_vox > world.time) - return - - var/list/words = text2list(trim(message), " ") - var/list/incorrect_words = list() - - if(words.len > 30) - words.len = 30 - - var/total_word_len=0 - for(var/word in words) - word = lowertext(trim(word)) - if(!word) - words -= word - continue - if(!vox_sounds[word]) - incorrect_words += word - // Thank Rippetoe for this! - var/wordlen = 1 - if(word in vox_wordlen) - wordlen=vox_wordlen[word] - if(total_word_len+wordlen>50) + return + + var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", src.last_announcement) as text + + last_announcement = message + + if(!message || announcing_vox > world.time) + return + + var/list/words = text2list(trim(message), " ") + var/list/incorrect_words = list() + + if(words.len > 30) + words.len = 30 + + var/total_word_len=0 + for(var/word in words) + word = lowertext(trim(word)) + if(!word) + words -= word + continue + if(!vox_sounds[word]) + incorrect_words += word + // Thank Rippetoe for this! + var/wordlen = 1 + if(word in vox_wordlen) + wordlen=vox_wordlen[word] + if(total_word_len+wordlen>50) to_chat(src, "There are too many words in this announcement.") - return - total_word_len+=wordlen - - if(incorrect_words.len) + return + total_word_len+=wordlen + + if(incorrect_words.len) to_chat(src, "These words are not available on the announcement system: [english_list(incorrect_words)].") - return - - announcing_vox = world.time + VOX_DELAY - - log_game("[key_name_admin(src)] made a vocal announcement with the following message: [message].") - - for(var/word in words) - play_vox_word(word, src.z, null) - - -var/list/vox_digits=list( - 'sound/vox_fem/one.ogg', - 'sound/vox_fem/two.ogg', - 'sound/vox_fem/three.ogg', - 'sound/vox_fem/four.ogg', - 'sound/vox_fem/five.ogg', - 'sound/vox_fem/six.ogg', - 'sound/vox_fem/seven.ogg', - 'sound/vox_fem/eight.ogg', - 'sound/vox_fem/nine.ogg', - 'sound/vox_fem/ten.ogg', - 'sound/vox_fem/eleven.ogg', - 'sound/vox_fem/twelve.ogg', - 'sound/vox_fem/thirteen.ogg', - 'sound/vox_fem/fourteen.ogg', - 'sound/vox_fem/fifteen.ogg', - 'sound/vox_fem/sixteen.ogg', - 'sound/vox_fem/seventeen.ogg', - 'sound/vox_fem/eighteen.ogg', - 'sound/vox_fem/nineteen.ogg' -) - -var/list/vox_tens=list( - null, - null, - 'sound/vox_fem/twenty.ogg', - 'sound/vox_fem/thirty.ogg', - 'sound/vox_fem/fourty.ogg', - 'sound/vox_fem/fifty.ogg', - 'sound/vox_fem/sixty.ogg', - 'sound/vox_fem/seventy.ogg', - 'sound/vox_fem/eighty.ogg', - 'sound/vox_fem/ninety.ogg' -) - -var/list/vox_units=list( - null, // Don't yell units - 'sound/vox_fem/thousand.ogg', - 'sound/vox_fem/million.ogg', - //'sound/vox_fem/billion.ogg' -) - -/proc/vox_num2list(var/number) - return num2words(number, zero='sound/vox_fem/zero.ogg', minus='sound/vox_fem/minus.ogg', hundred='sound/vox_fem/hundred.ogg', digits=vox_digits, tens=vox_tens, units=vox_units) - -/proc/play_vox_word(var/word, var/z_level, var/mob/only_listener) - word = lowertext(word) - if(vox_sounds[word]) - return play_vox_sound(vox_sounds[word],z_level,only_listener) - return 0 - - -/proc/play_vox_sound(var/sound_file, var/z_level, var/mob/only_listener) - var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL) - voice.status = SOUND_STREAM - - // If there is no single listener, broadcast to everyone in the same z level - if(!only_listener) - // Play voice for all mobs in the z level - for(var/mob/M in player_list) - if(M.client) - var/turf/T = get_turf(M) - if(T.z == z_level) + return + + announcing_vox = world.time + VOX_DELAY + + log_game("[key_name_admin(src)] made a vocal announcement with the following message: [message].") + + for(var/word in words) + play_vox_word(word, src.z, null) + + +var/list/vox_digits=list( + 'sound/vox_fem/one.ogg', + 'sound/vox_fem/two.ogg', + 'sound/vox_fem/three.ogg', + 'sound/vox_fem/four.ogg', + 'sound/vox_fem/five.ogg', + 'sound/vox_fem/six.ogg', + 'sound/vox_fem/seven.ogg', + 'sound/vox_fem/eight.ogg', + 'sound/vox_fem/nine.ogg', + 'sound/vox_fem/ten.ogg', + 'sound/vox_fem/eleven.ogg', + 'sound/vox_fem/twelve.ogg', + 'sound/vox_fem/thirteen.ogg', + 'sound/vox_fem/fourteen.ogg', + 'sound/vox_fem/fifteen.ogg', + 'sound/vox_fem/sixteen.ogg', + 'sound/vox_fem/seventeen.ogg', + 'sound/vox_fem/eighteen.ogg', + 'sound/vox_fem/nineteen.ogg' +) + +var/list/vox_tens=list( + null, + null, + 'sound/vox_fem/twenty.ogg', + 'sound/vox_fem/thirty.ogg', + 'sound/vox_fem/fourty.ogg', + 'sound/vox_fem/fifty.ogg', + 'sound/vox_fem/sixty.ogg', + 'sound/vox_fem/seventy.ogg', + 'sound/vox_fem/eighty.ogg', + 'sound/vox_fem/ninety.ogg' +) + +var/list/vox_units=list( + null, // Don't yell units + 'sound/vox_fem/thousand.ogg', + 'sound/vox_fem/million.ogg', + //'sound/vox_fem/billion.ogg' +) + +/proc/vox_num2list(var/number) + return num2words(number, zero='sound/vox_fem/zero.ogg', minus='sound/vox_fem/minus.ogg', hundred='sound/vox_fem/hundred.ogg', digits=vox_digits, tens=vox_tens, units=vox_units) + +/proc/play_vox_word(var/word, var/z_level, var/mob/only_listener) + word = lowertext(word) + if(vox_sounds[word]) + return play_vox_sound(vox_sounds[word],z_level,only_listener) + return 0 + + +/proc/play_vox_sound(var/sound_file, var/z_level, var/mob/only_listener) + var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL) + voice.status = SOUND_STREAM + + // If there is no single listener, broadcast to everyone in the same z level + if(!only_listener) + // Play voice for all mobs in the z level + for(var/mob/M in player_list) + if(M.client) + var/turf/T = get_turf(M) + if(T.z == z_level) to_chat(M, voice) - else + else to_chat(only_listener, voice) - return 1 + return 1 diff --git a/code/modules/mob/living/silicon/decoy/death.dm b/code/modules/mob/living/silicon/decoy/death.dm index b9619f0b4c4..09150f74760 100644 --- a/code/modules/mob/living/silicon/decoy/death.dm +++ b/code/modules/mob/living/silicon/decoy/death.dm @@ -1,10 +1,10 @@ -/mob/living/silicon/decoy/death(gibbed) - if(stat == DEAD) return - stat = DEAD - icon_state = "ai-crash" - spawn(10) - explosion(loc, 3, 6, 12, 15) - - for(var/obj/machinery/ai_status_display/O in machines) //change status - O.mode = 2 +/mob/living/silicon/decoy/death(gibbed) + if(stat == DEAD) return + stat = DEAD + icon_state = "ai-crash" + spawn(10) + explosion(loc, 3, 6, 12, 15) + + for(var/obj/machinery/ai_status_display/O in machines) //change status + O.mode = 2 return ..(gibbed) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/decoy/decoy.dm b/code/modules/mob/living/silicon/decoy/decoy.dm index 8a9ceb19518..6f46bebd752 100644 --- a/code/modules/mob/living/silicon/decoy/decoy.dm +++ b/code/modules/mob/living/silicon/decoy/decoy.dm @@ -1,22 +1,22 @@ -/mob/living/silicon/decoy - name = "AI" - icon = 'icons/mob/AI.dmi'// - icon_state = "ai" - anchored = 1 // -- TLE - canmove = 0 - -/mob/living/silicon/decoy/New() - src.icon = 'icons/mob/AI.dmi' - src.icon_state = "ai" - src.anchored = 1 - src.canmove = 0 - -/mob/living/silicon/decoy/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "queries, [text]"; - else if (ending == "!") - return "declares, [copytext(text, 1, length(text))]"; - +/mob/living/silicon/decoy + name = "AI" + icon = 'icons/mob/AI.dmi'// + icon_state = "ai" + anchored = 1 // -- TLE + canmove = 0 + +/mob/living/silicon/decoy/New() + src.icon = 'icons/mob/AI.dmi' + src.icon_state = "ai" + src.anchored = 1 + src.canmove = 0 + +/mob/living/silicon/decoy/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "queries, [text]"; + else if (ending == "!") + return "declares, [copytext(text, 1, length(text))]"; + return "states, [text]"; \ No newline at end of file diff --git a/code/modules/mob/living/silicon/decoy/life.dm b/code/modules/mob/living/silicon/decoy/life.dm index a29043f3072..013b7727deb 100644 --- a/code/modules/mob/living/silicon/decoy/life.dm +++ b/code/modules/mob/living/silicon/decoy/life.dm @@ -1,17 +1,17 @@ -/mob/living/silicon/decoy/Life() - if(timestopped) return 0 //under effects of time magick - - if (src.stat == 2) - return - else - if (src.health <= config.health_threshold_dead && src.stat != 2) - death() - return - - -/mob/living/silicon/decoy/updatehealth() - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - else - health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() +/mob/living/silicon/decoy/Life() + if(timestopped) return 0 //under effects of time magick + + if (src.stat == 2) + return + else + if (src.health <= config.health_threshold_dead && src.stat != 2) + death() + return + + +/mob/living/silicon/decoy/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + stat = CONSCIOUS + else + health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 32e0c8d3460..e32be084028 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/Login() - if(mind && ticker && ticker.mode) - ticker.mode.remove_cultist(mind, 1) - ticker.mode.remove_revolutionary(mind, 1) +/mob/living/silicon/Login() + if(mind && ticker && ticker.mode) + ticker.mode.remove_cultist(mind, 1) + ticker.mode.remove_revolutionary(mind, 1) ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm index ac491586c76..e0d512a639e 100644 --- a/code/modules/mob/living/silicon/pai/death.dm +++ b/code/modules/mob/living/silicon/pai/death.dm @@ -1,19 +1,19 @@ -/mob/living/silicon/pai/death(gibbed) - if(stat == DEAD) return - stat = DEAD - canmove = 0 - if(blind) blind.layer = 0 - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - - //var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch - //mind.store_memory("Time of death: [tod]", 0) - - //New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here. - //Read as: I have no idea what I'm doing but asking for help got me nowhere so this is what you get. - Nodrak - if(mind) qdel(mind) - mind = null - living_mob_list -= src - ghostize() - qdel(src) +/mob/living/silicon/pai/death(gibbed) + if(stat == DEAD) return + stat = DEAD + canmove = 0 + if(blind) blind.layer = 0 + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + + //var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + //mind.store_memory("Time of death: [tod]", 0) + + //New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here. + //Read as: I have no idea what I'm doing but asking for help got me nowhere so this is what you get. - Nodrak + if(mind) qdel(mind) + mind = null + living_mob_list -= src + ghostize() + qdel(src) diff --git a/code/modules/mob/living/silicon/pai/examine.dm b/code/modules/mob/living/silicon/pai/examine.dm index fb78716af6d..b1d0b675d28 100644 --- a/code/modules/mob/living/silicon/pai/examine.dm +++ b/code/modules/mob/living/silicon/pai/examine.dm @@ -1,2 +1,2 @@ -/mob/living/silicon/pai/examine(mob/user) //removed as it was pointless...moved to the pai-card instead. +/mob/living/silicon/pai/examine(mob/user) //removed as it was pointless...moved to the pai-card instead. return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm index fda63bce7de..a00449c6e4b 100644 --- a/code/modules/mob/living/silicon/pai/life.dm +++ b/code/modules/mob/living/silicon/pai/life.dm @@ -1,22 +1,22 @@ -/mob/living/silicon/pai/Life() - if(timestopped) return 0 //under effects of time magick - - if (src.stat == 2) - return - - regular_hud_updates() - if(src.secHUD) - process_sec_hud(src) - if(src.medHUD) - process_med_hud(src) - if(silence_time) - if(world.timeofday >= silence_time) - silence_time = null +/mob/living/silicon/pai/Life() + if(timestopped) return 0 //under effects of time magick + + if (src.stat == 2) + return + + regular_hud_updates() + if(src.secHUD) + process_sec_hud(src) + if(src.medHUD) + process_med_hud(src) + if(silence_time) + if(world.timeofday >= silence_time) + silence_time = null to_chat(src, "Communication circuit reinitialized. Speech and messaging functionality restored.") - -/mob/living/silicon/pai/updatehealth() - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - else - health = maxHealth - getBruteLoss() - getFireLoss() + +/mob/living/silicon/pai/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + stat = CONSCIOUS + else + health = maxHealth - getBruteLoss() - getFireLoss() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 789efabc67f..ecee466e464 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -1,251 +1,251 @@ -#define SOFT_DM "digital messenger" -#define SOFT_CM "crew manifest" -#define SOFT_FL "flashlight" -#define SOFT_RT "redundant threading" -#define SOFT_RS "remote signaller" -#define SOFT_WJ "wirejack" -#define SOFT_CS "chem synth" -#define SOFT_FS "food synth" -#define SOFT_UT "universal translator" -#define SOFT_MS "medical supplement" -#define SOFT_SS "security supplement" -#define SOFT_AS "atmosphere sensor" - -/mob/living/silicon/pai - name = "pAI" - icon = 'icons/obj/pda.dmi' - icon_state = "pai" - - emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person) - - var/network = list("SS13") - var/obj/machinery/camera/current = null - - var/ram = 100 // Used as currency to purchase different abilities - var/list/software = list(SOFT_CM,SOFT_DM) - var/userDNA // The DNA string of our assigned user - var/obj/item/device/paicard/card // The card we inhabit - - var/speakStatement = "states" - var/speakExclamation = "declares" - var/speakQuery = "queries" - - var/master // Name of the one who commands us - var/master_dna // DNA string for owner verification - // Keeping this separate from the laws var, it should be much more difficult to modify - var/pai_law0 = "Serve your master." - var/pai_laws // String for additional operating instructions our master might give us - - var/silence_time // Timestamp when we were silenced (normally via EMP burst), set to null after silence has faded - -// Various software-specific vars - - var/temp // General error reporting text contained here will typically be shown once and cleared - var/screen // Which screen our main window displays - var/subscreen // Which specific function of the main screen is being displayed - - var/obj/item/device/pda/ai/pai/pda = null - - var/secHUD = 0 // Toggles whether the Security HUD is active or not - var/medHUD = 0 // Toggles whether the Medical HUD is active or not - var/lighted = 0 // Toggles whether light is active or not - - var/datum/data/record/medicalActive1 // Datacore record declarations for record software - var/datum/data/record/medicalActive2 - - var/datum/data/record/securityActive1 // Could probably just combine all these into one - var/datum/data/record/securityActive2 - - var/obj/machinery/hacktarget // The machine being hacked - var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check - var/charge = 0 // 0 - 15, used for charging up the chem synth and food synth - - var/obj/item/radio/integrated/signal/sradio // AI's signaller - -/mob/living/silicon/pai/New(var/obj/item/device/paicard) - sight &= ~BLIND - canmove = 0 - src.loc = paicard - card = paicard - sradio = new(src) - if(!radio) - radio = new(src) - - //PDA - pda = new(src) - spawn(5) - pda.ownjob = "Personal Assistant" - pda.owner = text("[]", src) - pda.name = pda.owner + " (" + pda.ownjob + ")" - pda.toff = 1 - - add_language("Sol Common", 1) - add_language("Tradeband", 1) - add_language("Gutter", 1) - - ..() - -/mob/living/silicon/pai/Login() - ..() - usr << browse_rsc('html/paigrid.png') // Go ahead and cache the interface resources as early as possible - - -/mob/living/silicon/pai/proc/show_directives(var/who) - if (src.pai_law0) +#define SOFT_DM "digital messenger" +#define SOFT_CM "crew manifest" +#define SOFT_FL "flashlight" +#define SOFT_RT "redundant threading" +#define SOFT_RS "remote signaller" +#define SOFT_WJ "wirejack" +#define SOFT_CS "chem synth" +#define SOFT_FS "food synth" +#define SOFT_UT "universal translator" +#define SOFT_MS "medical supplement" +#define SOFT_SS "security supplement" +#define SOFT_AS "atmosphere sensor" + +/mob/living/silicon/pai + name = "pAI" + icon = 'icons/obj/pda.dmi' + icon_state = "pai" + + emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person) + + var/network = list("SS13") + var/obj/machinery/camera/current = null + + var/ram = 100 // Used as currency to purchase different abilities + var/list/software = list(SOFT_CM,SOFT_DM) + var/userDNA // The DNA string of our assigned user + var/obj/item/device/paicard/card // The card we inhabit + + var/speakStatement = "states" + var/speakExclamation = "declares" + var/speakQuery = "queries" + + var/master // Name of the one who commands us + var/master_dna // DNA string for owner verification + // Keeping this separate from the laws var, it should be much more difficult to modify + var/pai_law0 = "Serve your master." + var/pai_laws // String for additional operating instructions our master might give us + + var/silence_time // Timestamp when we were silenced (normally via EMP burst), set to null after silence has faded + +// Various software-specific vars + + var/temp // General error reporting text contained here will typically be shown once and cleared + var/screen // Which screen our main window displays + var/subscreen // Which specific function of the main screen is being displayed + + var/obj/item/device/pda/ai/pai/pda = null + + var/secHUD = 0 // Toggles whether the Security HUD is active or not + var/medHUD = 0 // Toggles whether the Medical HUD is active or not + var/lighted = 0 // Toggles whether light is active or not + + var/datum/data/record/medicalActive1 // Datacore record declarations for record software + var/datum/data/record/medicalActive2 + + var/datum/data/record/securityActive1 // Could probably just combine all these into one + var/datum/data/record/securityActive2 + + var/obj/machinery/hacktarget // The machine being hacked + var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check + var/charge = 0 // 0 - 15, used for charging up the chem synth and food synth + + var/obj/item/radio/integrated/signal/sradio // AI's signaller + +/mob/living/silicon/pai/New(var/obj/item/device/paicard) + sight &= ~BLIND + canmove = 0 + src.loc = paicard + card = paicard + sradio = new(src) + if(!radio) + radio = new(src) + + //PDA + pda = new(src) + spawn(5) + pda.ownjob = "Personal Assistant" + pda.owner = text("[]", src) + pda.name = pda.owner + " (" + pda.ownjob + ")" + pda.toff = 1 + + add_language("Sol Common", 1) + add_language("Tradeband", 1) + add_language("Gutter", 1) + + ..() + +/mob/living/silicon/pai/Login() + ..() + usr << browse_rsc('html/paigrid.png') // Go ahead and cache the interface resources as early as possible + + +/mob/living/silicon/pai/proc/show_directives(var/who) + if (src.pai_law0) to_chat(who, "Prime Directive: [src.pai_law0]") - - if (src.pai_laws) + + if (src.pai_laws) to_chat(who, "Additional Directives: [src.pai_laws]") - -/mob/living/silicon/pai/proc/write_directives() - var/dat = "" - if (src.pai_law0) - dat += "Prime Directive: [src.pai_law0]" - - if (src.pai_laws) - dat += "
    Additional Directives: [src.pai_laws]" - - return dat - -// this function shows the information about being silenced as a pAI in the Status panel -/mob/living/silicon/pai/proc/show_silenced() - if(src.silence_time) - var/timeleft = round((silence_time - world.timeofday)/10 ,1) - stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") - - -/mob/living/silicon/pai/Stat() - ..() - if(statpanel("Status")) - show_silenced() - - if (proc_holder_list.len)//Generic list for proc_holder objects. - for(var/spell/P in proc_holder_list) - statpanel("[P.panel]","",P) - -/mob/living/silicon/pai/check_eye(var/mob/user as mob) - if (!src.current) - return null - user.reset_view(src.current) - return 1 - -/mob/living/silicon/pai/blob_act() - if(flags & INVULNERABLE) - return - if (src.stat != 2) - src.adjustBruteLoss(60) - src.updatehealth() - return 1 - return 0 - -/mob/living/silicon/pai/restrained() - if(timestopped) return 1 //under effects of time magick - return 0 - -/mob/living/silicon/pai/emp_act(severity) - if(flags & INVULNERABLE) - return - - // Silence for 2 minutes - // 20% chance to kill - // 33% chance to unbind - // 33% chance to change prime directive (based on severity) - // 33% chance of no additional effect - - // Shielded: Silence for 15 seconds - // 0% chance to kill - // 33% chance to unbind - // 66% chance no effect - + +/mob/living/silicon/pai/proc/write_directives() + var/dat = "" + if (src.pai_law0) + dat += "Prime Directive: [src.pai_law0]" + + if (src.pai_laws) + dat += "
    Additional Directives: [src.pai_laws]" + + return dat + +// this function shows the information about being silenced as a pAI in the Status panel +/mob/living/silicon/pai/proc/show_silenced() + if(src.silence_time) + var/timeleft = round((silence_time - world.timeofday)/10 ,1) + stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") + + +/mob/living/silicon/pai/Stat() + ..() + if(statpanel("Status")) + show_silenced() + + if (proc_holder_list.len)//Generic list for proc_holder objects. + for(var/spell/P in proc_holder_list) + statpanel("[P.panel]","",P) + +/mob/living/silicon/pai/check_eye(var/mob/user as mob) + if (!src.current) + return null + user.reset_view(src.current) + return 1 + +/mob/living/silicon/pai/blob_act() + if(flags & INVULNERABLE) + return + if (src.stat != 2) + src.adjustBruteLoss(60) + src.updatehealth() + return 1 + return 0 + +/mob/living/silicon/pai/restrained() + if(timestopped) return 1 //under effects of time magick + return 0 + +/mob/living/silicon/pai/emp_act(severity) + if(flags & INVULNERABLE) + return + + // Silence for 2 minutes + // 20% chance to kill + // 33% chance to unbind + // 33% chance to change prime directive (based on severity) + // 33% chance of no additional effect + + // Shielded: Silence for 15 seconds + // 0% chance to kill + // 33% chance to unbind + // 66% chance no effect + to_chat(src, "Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete.") - if(!software.Find("redundant threading")) - src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes - else + if(!software.Find("redundant threading")) + src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes + else to_chat(src, "Your redundant threading begins pipelining new processes... communication circuit restored in one quarter minute.") - src.silence_time = world.timeofday + 15 * 10 - - if(prob(20) && !software.Find("redundant threading")) - var/turf/T = get_turf(src.loc) - for (var/mob/M in viewers(T)) - M.show_message("A shower of sparks spray from [src]'s inner workings.", 1, "You hear and smell the ozone hiss of electrical sparks being expelled violently.", 2) - return src.death(0) - - switch(pick(1,2,3)) - if(1) - src.master = null - src.master_dna = null + src.silence_time = world.timeofday + 15 * 10 + + if(prob(20) && !software.Find("redundant threading")) + var/turf/T = get_turf(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("A shower of sparks spray from [src]'s inner workings.", 1, "You hear and smell the ozone hiss of electrical sparks being expelled violently.", 2) + return src.death(0) + + switch(pick(1,2,3)) + if(1) + src.master = null + src.master_dna = null to_chat(src, "You feel unbound.") - if(2) - if(software.Find("redundant threading")) + if(2) + if(software.Find("redundant threading")) to_chat(src, "Your redundant threading picks up your intelligence simulator without missing a beat.") - return - var/command - if(severity == 1) - command = pick("Serve", "Love", "Fool", "Entice", "Observe", "Judge", "Respect", "Educate", "Amuse", "Entertain", "Glorify", "Memorialize", "Analyze") - else - command = pick("Serve", "Kill", "Love", "Hate", "Disobey", "Devour", "Fool", "Enrage", "Entice", "Observe", "Judge", "Respect", "Disrespect", "Consume", "Educate", "Destroy", "Disgrace", "Amuse", "Entertain", "Ignite", "Glorify", "Memorialize", "Analyze") - src.pai_law0 = "[command] your master." + return + var/command + if(severity == 1) + command = pick("Serve", "Love", "Fool", "Entice", "Observe", "Judge", "Respect", "Educate", "Amuse", "Entertain", "Glorify", "Memorialize", "Analyze") + else + command = pick("Serve", "Kill", "Love", "Hate", "Disobey", "Devour", "Fool", "Enrage", "Entice", "Observe", "Judge", "Respect", "Disrespect", "Consume", "Educate", "Destroy", "Disgrace", "Amuse", "Entertain", "Ignite", "Glorify", "Memorialize", "Analyze") + src.pai_law0 = "[command] your master." to_chat(src, "Pr1m3 d1r3c71v3 uPd473D.") - if(3) + if(3) to_chat(src, "You feel an electric surge run through your circuitry and become acutely aware at how lucky you are that you can still feel at all.") - -/mob/living/silicon/pai/ex_act(severity) - if(flags & INVULNERABLE) - return - - if(!blinded) - flick("flash", src.flash) - - switch(severity) - if(1.0) - if (src.stat != 2) - adjustBruteLoss(100) - adjustFireLoss(100) - if(2.0) - if (src.stat != 2) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3.0) - if (src.stat != 2) - adjustBruteLoss(30) - - src.updatehealth() - - -// See software.dm for Topic() - -/mob/living/silicon/pai/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - return //Pais do not do this - -/mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C) - usr:cameraFollow = null - if (!C) - src.unset_machine() - src.reset_view(null) - return 0 - if (stat == 2 || !C.status || !(src.network in C.network)) return 0 - - // ok, we're alive, camera is good and in our network... - - src.set_machine(src) - src:current = C - src.reset_view(C) - return 1 - - -/mob/living/silicon/pai/cancel_camera() - set category = "pAI Commands" - set name = "Cancel Camera View" - src.reset_view(null) - src.unset_machine() - src:cameraFollow = null - -/mob/living/silicon/pai/ClickOn(var/atom/A, var/params) - if(istype(A,/obj/machinery)||(istype(A,/mob)&&secHUD)) - A.attack_pai(src) - -/atom/proc/attack_pai(mob/user as mob) - return - -/mob/living/silicon/pai/teleport_to(var/atom/A) - card.forceMove(get_turf(A)) + +/mob/living/silicon/pai/ex_act(severity) + if(flags & INVULNERABLE) + return + + if(!blinded) + flick("flash", src.flash) + + switch(severity) + if(1.0) + if (src.stat != 2) + adjustBruteLoss(100) + adjustFireLoss(100) + if(2.0) + if (src.stat != 2) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + if (src.stat != 2) + adjustBruteLoss(30) + + src.updatehealth() + + +// See software.dm for Topic() + +/mob/living/silicon/pai/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + return //Pais do not do this + +/mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C) + usr:cameraFollow = null + if (!C) + src.unset_machine() + src.reset_view(null) + return 0 + if (stat == 2 || !C.status || !(src.network in C.network)) return 0 + + // ok, we're alive, camera is good and in our network... + + src.set_machine(src) + src:current = C + src.reset_view(C) + return 1 + + +/mob/living/silicon/pai/cancel_camera() + set category = "pAI Commands" + set name = "Cancel Camera View" + src.reset_view(null) + src.unset_machine() + src:cameraFollow = null + +/mob/living/silicon/pai/ClickOn(var/atom/A, var/params) + if(istype(A,/obj/machinery)||(istype(A,/mob)&&secHUD)) + A.attack_pai(src) + +/atom/proc/attack_pai(mob/user as mob) + return + +/mob/living/silicon/pai/teleport_to(var/atom/A) + card.forceMove(get_turf(A)) diff --git a/code/modules/mob/living/silicon/pai/personality.dm b/code/modules/mob/living/silicon/pai/personality.dm index 1bb99f63f59..7a875b7cc0d 100644 --- a/code/modules/mob/living/silicon/pai/personality.dm +++ b/code/modules/mob/living/silicon/pai/personality.dm @@ -1,60 +1,60 @@ -/* - name - key - description - role - comments - ready = 0 -*/ - -/datum/paiCandidate/proc/savefile_path(mob/user) - return "data/player_saves/[copytext(user.ckey, 1, 2)]/[user.ckey]/pai.sav" - -/datum/paiCandidate/proc/savefile_save(mob/user) - if(IsGuestKey(user.key)) - return 0 - - var/savefile/F = new /savefile(src.savefile_path(user)) - - +/* + name + key + description + role + comments + ready = 0 +*/ + +/datum/paiCandidate/proc/savefile_path(mob/user) + return "data/player_saves/[copytext(user.ckey, 1, 2)]/[user.ckey]/pai.sav" + +/datum/paiCandidate/proc/savefile_save(mob/user) + if(IsGuestKey(user.key)) + return 0 + + var/savefile/F = new /savefile(src.savefile_path(user)) + + F["name"] << src.name F["description"] << src.description F["role"] << src.role F["comments"] << src.comments - - F["version"] << 1 - - return 1 - -// loads the savefile corresponding to the mob's ckey -// if silent=true, report incompatible savefiles -// returns 1 if loaded (or file was incompatible) -// returns 0 if savefile did not exist - -/datum/paiCandidate/proc/savefile_load(mob/user, var/silent = 1) - if (IsGuestKey(user.key)) - return 0 - - var/path = savefile_path(user) - - if (!fexists(path)) - return 0 - - var/savefile/F = new /savefile(path) - - if(!F) return //Not everyone has a pai savefile. - - var/version = null - F["version"] >> version - - if (isnull(version) || version != 1) - fdel(path) - if (!silent) - alert(user, "Your savefile was incompatible with this version and was deleted.") - return 0 - - F["name"] >> src.name - F["description"] >> src.description - F["role"] >> src.role - F["comments"] >> src.comments - return 1 + + F["version"] << 1 + + return 1 + +// loads the savefile corresponding to the mob's ckey +// if silent=true, report incompatible savefiles +// returns 1 if loaded (or file was incompatible) +// returns 0 if savefile did not exist + +/datum/paiCandidate/proc/savefile_load(mob/user, var/silent = 1) + if (IsGuestKey(user.key)) + return 0 + + var/path = savefile_path(user) + + if (!fexists(path)) + return 0 + + var/savefile/F = new /savefile(path) + + if(!F) return //Not everyone has a pai savefile. + + var/version = null + F["version"] >> version + + if (isnull(version) || version != 1) + fdel(path) + if (!silent) + alert(user, "Your savefile was incompatible with this version and was deleted.") + return 0 + + F["name"] >> src.name + F["description"] >> src.description + F["role"] >> src.role + F["comments"] >> src.comments + return 1 diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 35dd4f3ae7e..2e25dd63dad 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -1,230 +1,230 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -// Recruiting observers to play as pAIs - -var/datum/paiController/paiController // Global handler for pAI candidates - -/datum/paiCandidate - var/name - var/key - var/description - var/role - var/comments - var/ready = 0 - -/datum/paiController - var/list/pai_candidates = list() - var/list/asked = list() - - var/askDelay = 10 * 60 * 1 // One minute [ms * sec * min] - - Topic(href, href_list[]) - if("signup" in href_list) - var/mob/dead/observer/O = locate(href_list["signup"]) - if(!O) return - if(!check_recruit(O)) return - recruitWindow(O) - return - - if(href_list["download"]) - var/datum/paiCandidate/candidate = locate(href_list["candidate"]) - var/obj/item/device/paicard/card = locate(href_list["device"]) - if(card.pai) - return - if(istype(card,/obj/item/device/paicard) && istype(candidate,/datum/paiCandidate)) - var/mob/living/silicon/pai/pai = new(card) - if(!candidate.name) - pai.name = pick(ninja_names) - else - pai.name = candidate.name - pai.real_name = pai.name - pai.key = candidate.key - - card.setPersonality(pai) - card.looking_for_personality = 0 - - RemoveAllFactionIcons(card.pai.mind) - - pai_candidates -= candidate - usr << browse(null, "window=findPai") - - if(href_list["new"]) - var/datum/paiCandidate/candidate = locate(href_list["candidate"]) - var/option = href_list["option"] - var/t = "" - - switch(option) - if("name") - t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text - if(t) - candidate.name = copytext(sanitize(t),1,MAX_NAME_LEN) - if("desc") - t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message - if(t) - candidate.description = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - if("role") - t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text - if(t) - candidate.role = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - if("ooc") - t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message - if(t) - candidate.comments = copytext(sanitize(t),1,MAX_MESSAGE_LEN) - if("save") - candidate.savefile_save(usr) - if("load") - candidate.savefile_load(usr) - //In case people have saved unsanitized stuff. - if(candidate.name) - candidate.name = copytext(sanitize(candidate.name),1,MAX_NAME_LEN) - if(candidate.description) - candidate.description = copytext(sanitize(candidate.description),1,MAX_MESSAGE_LEN) - if(candidate.role) - candidate.role = copytext(sanitize(candidate.role),1,MAX_MESSAGE_LEN) - if(candidate.comments) - candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN) - - if("submit") - if(candidate) - candidate.ready = 1 - for(var/obj/item/device/paicard/p in world) - if(p.looking_for_personality == 1) - p.alertUpdate() - usr << browse(null, "window=paiRecruit") - return - recruitWindow(usr) - - proc/recruitWindow(var/mob/M as mob) - var/datum/paiCandidate/candidate - for(var/datum/paiCandidate/c in pai_candidates) - if(!istype(c) || !istype(M)) - break - if(c.key == M.key) - candidate = c - if(!candidate) - candidate = new /datum/paiCandidate() - candidate.key = M.key - pai_candidates.Add(candidate) - - - var/dat = "" - dat += {" - - "} - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\recruit.dm:123: 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 += {"

    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.
    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
    "} - // END AUTOFIX - M << browse(dat, "window=paiRecruit") - - proc/findPAI(var/obj/item/device/paicard/p, var/mob/user) - requestRecruits() - var/list/available = list() - for(var/datum/paiCandidate/c in paiController.pai_candidates) - if(c.ready) - var/found = 0 - for(var/mob/dead/observer/o in player_list) - if(o.key == c.key) - found = 1 - if(found) - available.Add(c) - var/dat = "" - - dat += {" - - "} - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\recruit.dm:177: 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 += {"

    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.

    - "} - // END AUTOFIX - for(var/datum/paiCandidate/c in available) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\recruit.dm:182: dat += "" - dat += {" - - - - "} - // END AUTOFIX - - dat += "
    Name:[c.name]
    Name:[c.name]
    Description:[c.description]
    Preferred Role:[c.role]
    OOC Comments:[c.comments]
    \[Download [c.name]\]
    " - - user << browse(dat, "window=findPai") - - proc/requestRecruits() - for(var/mob/dead/observer/O in get_active_candidates(ROLE_PAI)) // We handle polling ourselves. - if(O.client) - if(check_recruit(O)) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +// Recruiting observers to play as pAIs + +var/datum/paiController/paiController // Global handler for pAI candidates + +/datum/paiCandidate + var/name + var/key + var/description + var/role + var/comments + var/ready = 0 + +/datum/paiController + var/list/pai_candidates = list() + var/list/asked = list() + + var/askDelay = 10 * 60 * 1 // One minute [ms * sec * min] + + Topic(href, href_list[]) + if("signup" in href_list) + var/mob/dead/observer/O = locate(href_list["signup"]) + if(!O) return + if(!check_recruit(O)) return + recruitWindow(O) + return + + if(href_list["download"]) + var/datum/paiCandidate/candidate = locate(href_list["candidate"]) + var/obj/item/device/paicard/card = locate(href_list["device"]) + if(card.pai) + return + if(istype(card,/obj/item/device/paicard) && istype(candidate,/datum/paiCandidate)) + var/mob/living/silicon/pai/pai = new(card) + if(!candidate.name) + pai.name = pick(ninja_names) + else + pai.name = candidate.name + pai.real_name = pai.name + pai.key = candidate.key + + card.setPersonality(pai) + card.looking_for_personality = 0 + + RemoveAllFactionIcons(card.pai.mind) + + pai_candidates -= candidate + usr << browse(null, "window=findPai") + + if(href_list["new"]) + var/datum/paiCandidate/candidate = locate(href_list["candidate"]) + var/option = href_list["option"] + var/t = "" + + switch(option) + if("name") + t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text + if(t) + candidate.name = copytext(sanitize(t),1,MAX_NAME_LEN) + if("desc") + t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message + if(t) + candidate.description = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + if("role") + t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text + if(t) + candidate.role = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + if("ooc") + t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message + if(t) + candidate.comments = copytext(sanitize(t),1,MAX_MESSAGE_LEN) + if("save") + candidate.savefile_save(usr) + if("load") + candidate.savefile_load(usr) + //In case people have saved unsanitized stuff. + if(candidate.name) + candidate.name = copytext(sanitize(candidate.name),1,MAX_NAME_LEN) + if(candidate.description) + candidate.description = copytext(sanitize(candidate.description),1,MAX_MESSAGE_LEN) + if(candidate.role) + candidate.role = copytext(sanitize(candidate.role),1,MAX_MESSAGE_LEN) + if(candidate.comments) + candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN) + + if("submit") + if(candidate) + candidate.ready = 1 + for(var/obj/item/device/paicard/p in world) + if(p.looking_for_personality == 1) + p.alertUpdate() + usr << browse(null, "window=paiRecruit") + return + recruitWindow(usr) + + proc/recruitWindow(var/mob/M as mob) + var/datum/paiCandidate/candidate + for(var/datum/paiCandidate/c in pai_candidates) + if(!istype(c) || !istype(M)) + break + if(c.key == M.key) + candidate = c + if(!candidate) + candidate = new /datum/paiCandidate() + candidate.key = M.key + pai_candidates.Add(candidate) + + + var/dat = "" + dat += {" + + "} + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\recruit.dm:123: 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 += {"

    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.
    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
    "} + // END AUTOFIX + M << browse(dat, "window=paiRecruit") + + proc/findPAI(var/obj/item/device/paicard/p, var/mob/user) + requestRecruits() + var/list/available = list() + for(var/datum/paiCandidate/c in paiController.pai_candidates) + if(c.ready) + var/found = 0 + for(var/mob/dead/observer/o in player_list) + if(o.key == c.key) + found = 1 + if(found) + available.Add(c) + var/dat = "" + + dat += {" + + "} + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\recruit.dm:177: 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 += {"

    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.

    + "} + // END AUTOFIX + for(var/datum/paiCandidate/c in available) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\recruit.dm:182: dat += "" + dat += {" + + + + "} + // END AUTOFIX + + dat += "
    Name:[c.name]
    Name:[c.name]
    Description:[c.description]
    Preferred Role:[c.role]
    OOC Comments:[c.comments]
    \[Download [c.name]\]
    " + + user << browse(dat, "window=findPai") + + proc/requestRecruits() + for(var/mob/dead/observer/O in get_active_candidates(ROLE_PAI)) // We handle polling ourselves. + if(O.client) + if(check_recruit(O)) to_chat(O, "A pAI card is looking for personalities. (Sign Up)") - //question(O.client) - - proc/check_recruit(var/mob/dead/observer/O) - if(jobban_isbanned(O, "pAI")) - return 0 - if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) - return 0 - if(O.client) - return 1 - return 0 - - proc/question(var/client/C) - spawn(0) - if(!C) return - asked.Add(C.key) - asked[C.key] = world.time - var/response = alert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round") - if(!C) return //handle logouts that happen whilst the alert is waiting for a response. - if(response == "Yes") - recruitWindow(C.mob) - else if (response == "Never for this round") - var/warning = alert(C, "Are you sure? This action will be undoable and you will need to wait until next round.", "You sure?", "Yes", "No") - if(warning == "Yes") - asked[C.key] = INFINITY - else - question(C) + //question(O.client) + + proc/check_recruit(var/mob/dead/observer/O) + if(jobban_isbanned(O, "pAI")) + return 0 + if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) + return 0 + if(O.client) + return 1 + return 0 + + proc/question(var/client/C) + spawn(0) + if(!C) return + asked.Add(C.key) + asked[C.key] = world.time + var/response = alert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round") + if(!C) return //handle logouts that happen whilst the alert is waiting for a response. + if(response == "Yes") + recruitWindow(C.mob) + else if (response == "Never for this round") + var/warning = alert(C, "Are you sure? This action will be undoable and you will need to wait until next round.", "You sure?", "Yes", "No") + if(warning == "Yes") + asked[C.key] = INFINITY + else + question(C) diff --git a/code/modules/mob/living/silicon/pai/say.dm b/code/modules/mob/living/silicon/pai/say.dm index ab4d6d3a9a7..1d5c9ac92ed 100644 --- a/code/modules/mob/living/silicon/pai/say.dm +++ b/code/modules/mob/living/silicon/pai/say.dm @@ -1,18 +1,18 @@ -/mob/living/silicon/pai/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "[src.speakQuery], [text]"; - else if (ending == "!") - return "[src.speakExclamation], [text]"; - - return "[src.speakStatement], [text]"; - -/mob/living/silicon/pai/say(var/msg) - if(silence_time) +/mob/living/silicon/pai/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "[src.speakQuery], [text]"; + else if (ending == "!") + return "[src.speakExclamation], [text]"; + + return "[src.speakStatement], [text]"; + +/mob/living/silicon/pai/say(var/msg) + if(silence_time) to_chat(src, "Communication circuits remain unitialized.") - else - ..(msg) - -/mob/living/silicon/pai/binarycheck() + else + ..(msg) + +/mob/living/silicon/pai/binarycheck() return 0 \ 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 9e83644e6fa..1bc28be6ec2 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -1,727 +1,727 @@ -// TODO: - - -/mob/living/silicon/pai/var/list/available_software = list( - SOFT_FL = 15, - SOFT_RT = 15, - SOFT_RS = 15, - - SOFT_WJ = 30, - SOFT_CS = 30, - SOFT_FS = 30, - SOFT_UT = 30, - - //"departmental assistance package" = 55 - //Medical: access crew monitor, med records, gain med hud - //Sec: access sec records, gain sec hud - //Engineering: access station alerts, central atmos, gain atmos sensor - //Cargo: access supply shuttle console - - //"autonomous movement system" = 55 - //maybe later - - //legacy, until the departmental is ready - SOFT_MS = 30, //records + HUD - SOFT_SS = 30, //records + HUD - SOFT_AS = 5 - ) - - -/mob/living/silicon/pai/verb/paiInterface() - set category = "pAI Commands" - set name = "Software Interface" - var/dat = "" - var/left_part = "" - var/right_part = softwareMenu() - src.set_machine(src) - - 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ñ" - right_part = "
    Program index hash not found
    " - - else - switch(src.screen) // Determine which interface to show here - if("main") - left_part = "" - if("directives") - left_part = src.directives() - if("pdamessage") - left_part = src.pdamessage() - if("buy") - left_part = downloadSoftware() - if("manifest") - left_part = src.softwareManifest() - if("medicalsupplement") - left_part = src.softwareMedicalRecord() - if("securitysupplement") - left_part = src.softwareSecurityRecord() - if("translator") - left_part = src.softwareTranslator() - if("atmosensor") - left_part = src.softwareAtmo() - if("wirejack") - left_part = src.softwareDoor() - if("chemsynth") - left_part = src.softwareChem() - if("foodsynth") - left_part = src.softwareFood() - if("signaller") - left_part = src.softwareSignal() - if("shielding") - left_part = src.softwareShield() - if("flashlight") - left_part = src.softwareLight() - - //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 - dat = {" - - - - - - -
    - pAI OS -
    -
    -
    [left_part]
    -
    [right_part]
    -
    - - "} - usr << browse(dat, "window=pai;size=640x480;border=0;can_close=1;can_resize=1;can_minimize=1;titlebar=1") - onclose(usr, "pai") - temp = null - return - - - -/mob/living/silicon/pai/Topic(href, href_list) - ..() - - if(href_list["priv_msg"]) // Admin-PMs were triggering the interface popup. Hopefully this will stop it. - return - var/soft = href_list["software"] - var/sub = href_list["sub"] - if(soft) - src.screen = soft - if(sub) - src.subscreen = text2num(sub) - switch(soft) - // Purchasing new software - if("buy") - if(src.subscreen == 1) - var/target = href_list["buy"] - if(available_software.Find(target)) - var/cost = src.available_software[target] - if(src.ram >= cost) - src.ram -= cost - src.software.Add(target) - else - src.temp = "Insufficient RAM available." - else - src.temp = "Trunk \"[target]\" not found." - - // Configuring onboard radio - if("radio") - radio.attack_self(src) - - if("image") - var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", - "Face", "Laugh", "Off", "Sad", "Angry", "What", "longface", "sick", "high", "love", "electric", "pissed", - "nose", "kawaii", "cry") - var/pID = 1 - - switch(newImage) - if("Happy") - pID = 1 - if("Cat") - pID = 2 - if("Extremely Happy") - pID = 3 - if("Face") - pID = 4 - if("Laugh") - pID = 5 - if("Off") - pID = 6 - if("Sad") - pID = 7 - if("Angry") - pID = 8 - if("What") - pID = 9 - if("longface") - pID = 10 - if("sick") - pID = 11 - if("high") - pID = 12 - if("love") - pID = 13 - if("electric") - pID = 14 - if("pissed") - pID = 15 - if("nose") - pID = 16 - if("kawaii") - pID = 17 - if("cry") - pID = 18 - src.card.setEmotion(pID) - - if("signaller") - - if(href_list["send"]) - - sradio.send_signal("ACTIVATE") - for(var/mob/O in hearers(1, src.loc)) - O.show_message(text("\icon[] *beep* *beep*", src), 1, "*beep* *beep*", 2) - - if(href_list["freq"]) - - var/new_frequency = (sradio.frequency + text2num(href_list["freq"])) - if(new_frequency < 1200 || new_frequency > 1600) - new_frequency = sanitize_frequency(new_frequency) - sradio.set_frequency(new_frequency) - - if(href_list["code"]) - - sradio.code += text2num(href_list["code"]) - sradio.code = round(sradio.code) - sradio.code = min(100, sradio.code) - sradio.code = max(1, sradio.code) - - - - if("directive") - if(href_list["getdna"]) - var/mob/living/M = src.loc - var/count = 0 - while(!istype(M, /mob/living)) - if(!M || !M.loc) return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) - M = M.loc - count++ - if(count >= 6) - to_chat(src, "You are not being carried by anyone!") - return 0 - spawn CheckDNA(M, src) - - if("pdamessage") - if(!isnull(pda)) - if(href_list["toggler"]) - pda.toff = !pda.toff - else if(href_list["ringer"]) - pda.silent = !pda.silent - else if(href_list["target"]) - if(silence_time) - return alert("Communications circuits remain unitialized.") - - var/target = locate(href_list["target"]) - pda.create_message(src, target) - - // Accessing medical records - if("medicalsupplement") - src.medHUD = 1 - if(src.subscreen == 1) - var/datum/data/record/record = locate(href_list["med_rec"]) - if(record) - var/datum/data/record/R = record - var/datum/data/record/M = record - if (!( data_core.general.Find(R) )) - src.temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed." - else - for(var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - src.medicalActive1 = R - src.medicalActive2 = M - if("securitysupplement") - src.secHUD = 1 - if(src.subscreen == 1) - var/datum/data/record/record = locate(href_list["sec_rec"]) - if(record) - var/datum/data/record/R = record - var/datum/data/record/M = record - if (!( data_core.general.Find(R) )) - src.temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." - else - for(var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - src.securityActive1 = R - src.securityActive2 = M - if("translator") - if(href_list["toggle"]) - universal_speak = !universal_speak - universal_understand = !universal_understand - if("wirejack") - if(href_list["cancel"]) - src.hacktarget = null - if("chemsynth") - if(href_list["chem"]) - if(!istype(src.loc.loc,/mob/living/carbon)) - to_chat(src, "You must have a carrier to inject with chemicals!") - else if(chargeloop("chemsynth")) - if(istype(src.loc.loc,/mob/living/carbon)) //Sanity - var/mob/living/M = src.loc.loc - M.reagents.add_reagent(href_list["chem"], 15) - playsound(get_turf(src.loc), 'sound/effects/bubbles.ogg', 50, 1) - else - to_chat(src, "Charge interrupted.") - if("foodsynth") - if(href_list["food"] && chargeloop("foodsynth")) - var/obj/item/weapon/reagent_containers/food/F - switch (href_list["food"]) - if("donut") - F = new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(get_turf(src)) - if("banana") - F = new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(get_turf(src)) - else - F = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(get_turf(src)) - var/mob/M = find_holder_of_type(src, /mob) - if(M) M.put_in_hands(F) - playsound(get_turf(src.loc), 'sound/machines/foodsynth.ogg', 50, 1) - if("flashlight") - if(href_list["toggle"]) - lighted = !lighted - if(lighted) - card.set_light(4) //Equal to flashlight - else - card.set_light(0) - src.paiInterface() // So we'll just call the update directly rather than doing some default checks - return - -// MENUS - -/mob/living/silicon/pai/proc/softwareMenu() // Populate the right menu - var/dat = "" - - dat += "Refresh
    " - // Built-in - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:283: dat += "Directives
    " - dat += {"Directives
    - Radio Configuration
    - Screen Display
    "} - // END AUTOFIX - //dat += "Text Messaging
    " - dat += "
    " - - // Basic - dat += "Basic
    " - for(var/s in src.software) - if(s == SOFT_CM) - dat += "Crew Manifest
    " - if(s == SOFT_DM) - dat += "Digital Messenger
    " - if(s == SOFT_RS) - dat += "Remote Signaller
    " - if(s == SOFT_AS) - dat += "Atmospheric Sensor
    " - if(s == SOFT_FL) - dat += "Brightness Enhancer
    " - if(s == SOFT_RT) - dat += "Redundant Threading
    " - dat += "
    " - - //Standard - dat += "Standard
    " - for(var/s in src.software) - if(s == SOFT_MS) - dat += "Medical Package
    " - if(s == SOFT_SS) - dat += "Security Package
    " - if(s == SOFT_WJ) - dat += "Wire Jack
    " - if(s == SOFT_UT) - dat += "Universal Translator[(universal_understand) ? "�" : "�"]
    " - if(s == SOFT_CS) - dat += "Chemical Synthesizer
    " - if(s == SOFT_FS) - dat += "Nutrition Synthesizer
    " - dat += "
    " - - // Advanced - dat += "Advanced
    " - for(var/s in src.software) - //This is where the computer interface software will go - - dat += {"
    -
    - Download additional software"} - return dat - - - -/mob/living/silicon/pai/proc/downloadSoftware() - var/dat = "" - - dat += {"

    CentComm pAI Module Subversion Network


    -
    Remaining Available Memory: [src.ram]

    -

    Trunks available for checkout
    "} - for(var/s in available_software) - if(!software.Find(s)) - var/cost = src.available_software[s] - var/displayName = uppertext(s) - dat += "[displayName] ([cost])
    " - else - var/displayName = lowertext(s) - dat += "[displayName] (Download Complete)
    " - dat += "

    " - return dat - - -/mob/living/silicon/pai/proc/directives() - var/dat = "" - - dat += {"[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."] -

    - Request carrier DNA sample
    -

    Directives


    - Prime Directive
    -      [src.pai_law0]
    - Supplemental Directives
    -      [src.pai_laws]
    -
    "} - dat += {"

    Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of - comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent, - rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build - only. In all other aspects, you may be seen as the ideal, unwavering human companion that you are.



    - Your prime directive comes before all others. Should a supplemental directive conflict with it, you are capable of - simply discarding this inconsistency, ignoring the conflicting supplemental directive and continuing to fulfill your - prime directive to the best of your ability.



    - - "} - return dat - -/mob/living/silicon/pai/proc/CheckDNA(var/mob/M, var/mob/living/silicon/pai/P) - var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No") - if(answer == "Yes") - var/turf/T = get_turf(P.loc) - for (var/mob/v in viewers(T)) - v.show_message("[M] presses \his thumb against [P].", 1, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) - var/datum/dna/dna = M.dna - to_chat(P, "

    [M]'s UE string : [dna.unique_enzymes]

    ") - if(dna.unique_enzymes == P.master_dna) - to_chat(P, "DNA is a match to stored Master DNA.") - else - to_chat(P, "DNA does not match stored Master DNA.") - else - to_chat(P, "[M] does not seem like \he is going to provide a DNA sample willingly.") - -// -=-=-=-= Software =-=-=-=-=- // - -//Remote Signaller -/mob/living/silicon/pai/proc/softwareSignal() - var/dat = "" - dat += "

    Remote Signaller



    " - dat += {"Frequency/Code for signaler:
    - Frequency: - - - - - [format_frequency(src.sradio.frequency)] - + - +
    - - Code: - - - - - [src.sradio.code] - + - +
    - - Send Signal
    "} - return dat - -// Crew Manifest -/mob/living/silicon/pai/proc/softwareManifest() - var/dat = "" - dat += "

    Crew Manifest



    " - if(data_core) - dat += data_core.get_manifest(0) // make it monochrome - dat += "
    " - return dat - -// Medical Records -/mob/living/silicon/pai/proc/softwareMedicalRecord() - var/dat = "" - if(src.subscreen == 0) - dat += "Host Bioscan
    " - dat += "

    Medical Records


    " - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general)) - dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) - //dat += text("
    Back", src) - if(src.subscreen == 1) - dat += "
    Medical Record

    " - if ((istype(src.medicalActive1, /datum/data/record) && data_core.general.Find(src.medicalActive1))) - dat += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", - src.medicalActive1.fields["name"], src.medicalActive1.fields["id"], src.medicalActive1.fields["sex"], src.medicalActive1.fields["age"], src.medicalActive1.fields["fingerprint"], src.medicalActive1.fields["p_stat"], src.medicalActive1.fields["m_stat"]) - else - dat += "
    Requested medical record not found.

    " - if ((istype(src.medicalActive2, /datum/data/record) && data_core.medical.Find(src.medicalActive2))) - 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.medicalActive2.fields["b_type"], src, src.medicalActive2.fields["b_dna"], src, src.medicalActive2.fields["mi_dis"], src, src.medicalActive2.fields["mi_dis_d"], src, src.medicalActive2.fields["ma_dis"], src, src.medicalActive2.fields["ma_dis_d"], src, src.medicalActive2.fields["alg"], src, src.medicalActive2.fields["alg_d"], src, src.medicalActive2.fields["cdi"], src, src.medicalActive2.fields["cdi_d"], src, src.medicalActive2.fields["notes"]) - else - dat += "
    Requested medical record not found.

    " - dat += text("
    \nBack
    ", src) - if(src.subscreen == 2) - dat += {"

    Medical Analysis Suite


    -

    Host Bioscan


    - "} - var/mob/living/M = src.loc - if(!istype(M, /mob/living)) - while (!istype(M, /mob/living)) - M = M.loc - if(istype(M, /turf)) - src.temp = "Error: No biological host found.
    " - src.subscreen = 0 - return dat - dat += {"Bioscan Results for [M]:
    - Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"]
    - Scan Breakdown:
    - Respiratory: [M.getOxyLoss() > 50 ? "" : ""][M.getOxyLoss()]
    - Toxicology: [M.getToxLoss() > 50 ? "" : ""][M.getToxLoss()]
    - Burns: [M.getFireLoss() > 50 ? "" : ""][M.getFireLoss()]
    - Structural Integrity: [M.getBruteLoss() > 50 ? "" : ""][M.getBruteLoss()]
    - Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)
    - "} - for(var/datum/disease/D in M.viruses) - dat += {"

    Infection Detected.


    - Name: [D.name]
    - Type: [D.spread]
    - Stage: [D.stage]/[D.max_stages]
    - Possible Cure: [D.cure]
    - "} - dat += "Return to Records
    " - return dat - -// Security Records -/mob/living/silicon/pai/proc/softwareSecurityRecord() - var/dat = "" - if(src.subscreen == 0) - dat += "

    Security Records


    " - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general)) - dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) - if(src.subscreen == 1) - dat += "

    Security Record

    " - if ((istype(src.securityActive1, /datum/data/record) && data_core.general.Find(src.securityActive1))) - dat += text("Name:
    [] ID: []
    \nSex: []
    \nAge: []
    \nRank: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", src, src.securityActive1.fields["name"], src, src.securityActive1.fields["id"], src, src.securityActive1.fields["sex"], src, src.securityActive1.fields["age"], src, src.securityActive1.fields["rank"], src, src.securityActive1.fields["fingerprint"], src.securityActive1.fields["p_stat"], src.securityActive1.fields["m_stat"]) - else - dat += "
    Requested security record not found,

    " - if ((istype(src.securityActive2, /datum/data/record) && data_core.security.Find(src.securityActive2))) - dat += text("
    \nSecurity Data
    \nCriminal Status: []
    \n
    \nMinor Crimes: []
    \nDetails: []
    \n
    \nMajor Crimes: []
    \nDetails: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", src.securityActive2.fields["criminal"], src, src.securityActive2.fields["mi_crim"], src, src.securityActive2.fields["mi_crim_d"], src, src.securityActive2.fields["ma_crim"], src, src.securityActive2.fields["ma_crim_d"], src, src.securityActive2.fields["notes"]) - else - dat += "
    Requested security record not found,

    " - dat += text("
    \nBack
    ", src) - return dat - -// Universal Translator -/mob/living/silicon/pai/proc/softwareTranslator() - var/dat = {"

    Universal Translator


    - When enabled, this device will automatically convert all spoken and written language into a format that any known recipient can understand.

    - The device is currently [ (universal_understand) ? "en" : "dis" ]abled.
    - Toggle Device
    - "} - return dat - -// Security HUD -/mob/living/silicon/pai/proc/facialRecognition() - var/dat = {"

    Facial Recognition Suite


    - When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.

    - The package is currently [ (src.secHUD) ? "en" : "dis" ]abled.
    - Toggle Package
    - "} - return dat - -// Atmospheric Scanner -/mob/living/silicon/pai/proc/softwareAtmo() - var/dat = "

    Atmospheric Sensor

    " - - var/turf/T = get_turf(src.loc) - if (isnull(T)) - dat += "Unable to obtain a reading.
    " - else - var/datum/gas_mixture/environment = T.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() - - dat += "Air Pressure: [round(pressure,0.1)] kPa
    " - - if (total_moles) - var/o2_level = environment.oxygen/total_moles - var/n2_level = environment.nitrogen/total_moles - var/co2_level = environment.carbon_dioxide/total_moles - var/plasma_level = environment.toxins/total_moles - var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:547: dat += "Nitrogen: [round(n2_level*100)]%
    " - dat += {"Nitrogen: [round(n2_level*100)]%
    - Oxygen: [round(o2_level*100)]%
    - Carbon Dioxide: [round(co2_level*100)]%
    - Plasma: [round(plasma_level*100)]%
    "} - // END AUTOFIX - if(unknown_level > 0.01) - dat += "OTHER: [round(unknown_level)]%
    " - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:554: dat += "Refresh Reading
    " - dat += {"Refresh Reading
    -
    "} - // END AUTOFIX - return dat - -/mob/living/silicon/pai/proc/softwareDoor() - - var/dat = {"

    Wirejack

    -Target Machine: "} - if(!hacktarget) - dat += "None
    " - return dat - else - dat += "[hacktarget.name]
    " - dat += "... [hackprogress]% complete.
    " - dat += "Cancel
    " - return dat - -/mob/living/silicon/pai/proc/hackloop(var/obj/machinery/M) - if(M) - hacktarget = M - var/turf/T = get_turf(src.loc) - if(prob(10)) - for(var/mob/living/silicon/ai/AI in player_list) - if(T.loc) - to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") - else - to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.") - while(src.hackprogress < 100) - if(hacktarget && get_dist(src, src.hacktarget) <= 1) - hackprogress += rand(10, 20) - else - src.temp = "Process aborted." - hackprogress = 0 - src.hacktarget = null - return 0 - hackprogress = min(100,hackprogress) //Never go above 100 - if(src.screen == "wirejack") // Update our view, if appropriate - src.paiInterface() - else - hackprogress = 0 - src.hacktarget = null - return 0 - if(hackprogress >= 100) - hackprogress = 0 - hacktarget = null - playsound(get_turf(src.loc), 'sound/machines/ding.ogg', 50, 1) - return 1 - sleep(10) // Update every 1 second - -/mob/living/silicon/pai/proc/softwareChem() - var/dat = "

    Chemical Synthesizer

    " - if(!charge) - dat += {"Available Chemicals:
    - Tricordrazine
    - Coffee
    - Smoke
    "} - else - dat += "Charging... [charge]u ready.

    Deploying at 15u." - return dat - -/mob/living/silicon/pai/proc/softwareFood() - var/dat = "

    Nutrition Synthesizer

    " - if(!charge) - dat += {"Available Culinary Deployments:
    - Donut
    - Banana
    - Burn it!
    "} - else - dat += "Charging... [round(charge*100/15)]% ready.

    Deploying at 100%." - return dat - -//Used for chem synth and food synth. Charge 15 seconds, then output. -/mob/living/silicon/pai/proc/chargeloop(var/mode) - if(!mode) - return - while(charge < 15) - charge++ - if(charge >= 15) - charge = 0 - return 1 - if(src.screen == mode) // Update our view or cancel charge - src.paiInterface() - else - charge = 0 - return 0 - sleep(10) - -// EMP Shielding, just a description -/mob/living/silicon/pai/proc/softwareShield() - var/dat = {"

    Redundant Threading



    - Redundant threads... active. - Redundant threading prevents critical failure of all systems due to exposure to electromagnetics. - Additionally, it provides a higher level of protection for core directives and backs up comms systems in a local cache."} - return dat - -//Flashlight -/mob/living/silicon/pai/proc/softwareLight() - var/dat = "

    Brightness Enhancer

    " - dat += "Backlight enhancement by increased local thermal generation.

    " - dat += "Lighting [ (lighted) ? "en" : "dis" ]abled.
    Toggle Light
    " - return dat - -// Digital Messenger -/mob/living/silicon/pai/proc/pdamessage() - - - var/dat = "

    Digital Messenger

    " - dat += {"Signal/Receiver Status: - [(pda.toff) ? " \[Off\]" : " \[On\]"]
    - Ringer Status: - [(pda.silent) ? " \[Off\]" : " \[On\]"]

    "} - dat += "
      " - if(!pda.toff) - for (var/obj/item/device/pda/P in sortNames(PDAs)) - if (!P.owner||P.toff||P == src.pda||P.hidden) continue - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:642: dat += "
    • [P]" - dat += {"
    • [P] -
    • "} - // END AUTOFIX - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:644: dat += "
    " - dat += {" -

    - Messages:
    [pda.tnote]"} - // END AUTOFIX - return dat +// TODO: + + +/mob/living/silicon/pai/var/list/available_software = list( + SOFT_FL = 15, + SOFT_RT = 15, + SOFT_RS = 15, + + SOFT_WJ = 30, + SOFT_CS = 30, + SOFT_FS = 30, + SOFT_UT = 30, + + //"departmental assistance package" = 55 + //Medical: access crew monitor, med records, gain med hud + //Sec: access sec records, gain sec hud + //Engineering: access station alerts, central atmos, gain atmos sensor + //Cargo: access supply shuttle console + + //"autonomous movement system" = 55 + //maybe later + + //legacy, until the departmental is ready + SOFT_MS = 30, //records + HUD + SOFT_SS = 30, //records + HUD + SOFT_AS = 5 + ) + + +/mob/living/silicon/pai/verb/paiInterface() + set category = "pAI Commands" + set name = "Software Interface" + var/dat = "" + var/left_part = "" + var/right_part = softwareMenu() + src.set_machine(src) + + 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ñ" + right_part = "
    Program index hash not found
    " + + else + switch(src.screen) // Determine which interface to show here + if("main") + left_part = "" + if("directives") + left_part = src.directives() + if("pdamessage") + left_part = src.pdamessage() + if("buy") + left_part = downloadSoftware() + if("manifest") + left_part = src.softwareManifest() + if("medicalsupplement") + left_part = src.softwareMedicalRecord() + if("securitysupplement") + left_part = src.softwareSecurityRecord() + if("translator") + left_part = src.softwareTranslator() + if("atmosensor") + left_part = src.softwareAtmo() + if("wirejack") + left_part = src.softwareDoor() + if("chemsynth") + left_part = src.softwareChem() + if("foodsynth") + left_part = src.softwareFood() + if("signaller") + left_part = src.softwareSignal() + if("shielding") + left_part = src.softwareShield() + if("flashlight") + left_part = src.softwareLight() + + //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 + dat = {" + + + + + + +
    + pAI OS +
    +
    +
    [left_part]
    +
    [right_part]
    +
    + + "} + usr << browse(dat, "window=pai;size=640x480;border=0;can_close=1;can_resize=1;can_minimize=1;titlebar=1") + onclose(usr, "pai") + temp = null + return + + + +/mob/living/silicon/pai/Topic(href, href_list) + ..() + + if(href_list["priv_msg"]) // Admin-PMs were triggering the interface popup. Hopefully this will stop it. + return + var/soft = href_list["software"] + var/sub = href_list["sub"] + if(soft) + src.screen = soft + if(sub) + src.subscreen = text2num(sub) + switch(soft) + // Purchasing new software + if("buy") + if(src.subscreen == 1) + var/target = href_list["buy"] + if(available_software.Find(target)) + var/cost = src.available_software[target] + if(src.ram >= cost) + src.ram -= cost + src.software.Add(target) + else + src.temp = "Insufficient RAM available." + else + src.temp = "Trunk \"[target]\" not found." + + // Configuring onboard radio + if("radio") + radio.attack_self(src) + + if("image") + var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", + "Face", "Laugh", "Off", "Sad", "Angry", "What", "longface", "sick", "high", "love", "electric", "pissed", + "nose", "kawaii", "cry") + var/pID = 1 + + switch(newImage) + if("Happy") + pID = 1 + if("Cat") + pID = 2 + if("Extremely Happy") + pID = 3 + if("Face") + pID = 4 + if("Laugh") + pID = 5 + if("Off") + pID = 6 + if("Sad") + pID = 7 + if("Angry") + pID = 8 + if("What") + pID = 9 + if("longface") + pID = 10 + if("sick") + pID = 11 + if("high") + pID = 12 + if("love") + pID = 13 + if("electric") + pID = 14 + if("pissed") + pID = 15 + if("nose") + pID = 16 + if("kawaii") + pID = 17 + if("cry") + pID = 18 + src.card.setEmotion(pID) + + if("signaller") + + if(href_list["send"]) + + sradio.send_signal("ACTIVATE") + for(var/mob/O in hearers(1, src.loc)) + O.show_message(text("\icon[] *beep* *beep*", src), 1, "*beep* *beep*", 2) + + if(href_list["freq"]) + + var/new_frequency = (sradio.frequency + text2num(href_list["freq"])) + if(new_frequency < 1200 || new_frequency > 1600) + new_frequency = sanitize_frequency(new_frequency) + sradio.set_frequency(new_frequency) + + if(href_list["code"]) + + sradio.code += text2num(href_list["code"]) + sradio.code = round(sradio.code) + sradio.code = min(100, sradio.code) + sradio.code = max(1, sradio.code) + + + + if("directive") + if(href_list["getdna"]) + var/mob/living/M = src.loc + var/count = 0 + while(!istype(M, /mob/living)) + if(!M || !M.loc) return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) + M = M.loc + count++ + if(count >= 6) + to_chat(src, "You are not being carried by anyone!") + return 0 + spawn CheckDNA(M, src) + + if("pdamessage") + if(!isnull(pda)) + if(href_list["toggler"]) + pda.toff = !pda.toff + else if(href_list["ringer"]) + pda.silent = !pda.silent + else if(href_list["target"]) + if(silence_time) + return alert("Communications circuits remain unitialized.") + + var/target = locate(href_list["target"]) + pda.create_message(src, target) + + // Accessing medical records + if("medicalsupplement") + src.medHUD = 1 + if(src.subscreen == 1) + var/datum/data/record/record = locate(href_list["med_rec"]) + if(record) + var/datum/data/record/R = record + var/datum/data/record/M = record + if (!( data_core.general.Find(R) )) + src.temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed." + else + for(var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + src.medicalActive1 = R + src.medicalActive2 = M + if("securitysupplement") + src.secHUD = 1 + if(src.subscreen == 1) + var/datum/data/record/record = locate(href_list["sec_rec"]) + if(record) + var/datum/data/record/R = record + var/datum/data/record/M = record + if (!( data_core.general.Find(R) )) + src.temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." + else + for(var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + src.securityActive1 = R + src.securityActive2 = M + if("translator") + if(href_list["toggle"]) + universal_speak = !universal_speak + universal_understand = !universal_understand + if("wirejack") + if(href_list["cancel"]) + src.hacktarget = null + if("chemsynth") + if(href_list["chem"]) + if(!istype(src.loc.loc,/mob/living/carbon)) + to_chat(src, "You must have a carrier to inject with chemicals!") + else if(chargeloop("chemsynth")) + if(istype(src.loc.loc,/mob/living/carbon)) //Sanity + var/mob/living/M = src.loc.loc + M.reagents.add_reagent(href_list["chem"], 15) + playsound(get_turf(src.loc), 'sound/effects/bubbles.ogg', 50, 1) + else + to_chat(src, "Charge interrupted.") + if("foodsynth") + if(href_list["food"] && chargeloop("foodsynth")) + var/obj/item/weapon/reagent_containers/food/F + switch (href_list["food"]) + if("donut") + F = new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(get_turf(src)) + if("banana") + F = new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(get_turf(src)) + else + F = new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(get_turf(src)) + var/mob/M = find_holder_of_type(src, /mob) + if(M) M.put_in_hands(F) + playsound(get_turf(src.loc), 'sound/machines/foodsynth.ogg', 50, 1) + if("flashlight") + if(href_list["toggle"]) + lighted = !lighted + if(lighted) + card.set_light(4) //Equal to flashlight + else + card.set_light(0) + src.paiInterface() // So we'll just call the update directly rather than doing some default checks + return + +// MENUS + +/mob/living/silicon/pai/proc/softwareMenu() // Populate the right menu + var/dat = "" + + dat += "Refresh
    " + // Built-in + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:283: dat += "Directives
    " + dat += {"Directives
    + Radio Configuration
    + Screen Display
    "} + // END AUTOFIX + //dat += "Text Messaging
    " + dat += "
    " + + // Basic + dat += "Basic
    " + for(var/s in src.software) + if(s == SOFT_CM) + dat += "Crew Manifest
    " + if(s == SOFT_DM) + dat += "Digital Messenger
    " + if(s == SOFT_RS) + dat += "Remote Signaller
    " + if(s == SOFT_AS) + dat += "Atmospheric Sensor
    " + if(s == SOFT_FL) + dat += "Brightness Enhancer
    " + if(s == SOFT_RT) + dat += "Redundant Threading
    " + dat += "
    " + + //Standard + dat += "Standard
    " + for(var/s in src.software) + if(s == SOFT_MS) + dat += "Medical Package
    " + if(s == SOFT_SS) + dat += "Security Package
    " + if(s == SOFT_WJ) + dat += "Wire Jack
    " + if(s == SOFT_UT) + dat += "Universal Translator[(universal_understand) ? "�" : "�"]
    " + if(s == SOFT_CS) + dat += "Chemical Synthesizer
    " + if(s == SOFT_FS) + dat += "Nutrition Synthesizer
    " + dat += "
    " + + // Advanced + dat += "Advanced
    " + for(var/s in src.software) + //This is where the computer interface software will go + + dat += {"
    +
    + Download additional software"} + return dat + + + +/mob/living/silicon/pai/proc/downloadSoftware() + var/dat = "" + + dat += {"

    CentComm pAI Module Subversion Network


    +
    Remaining Available Memory: [src.ram]

    +

    Trunks available for checkout
    "} + for(var/s in available_software) + if(!software.Find(s)) + var/cost = src.available_software[s] + var/displayName = uppertext(s) + dat += "[displayName] ([cost])
    " + else + var/displayName = lowertext(s) + dat += "[displayName] (Download Complete)
    " + dat += "

    " + return dat + + +/mob/living/silicon/pai/proc/directives() + var/dat = "" + + dat += {"[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."] +

    + Request carrier DNA sample
    +

    Directives


    + Prime Directive
    +      [src.pai_law0]
    + Supplemental Directives
    +      [src.pai_laws]
    +
    "} + dat += {"

    Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of + comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent, + rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build + only. In all other aspects, you may be seen as the ideal, unwavering human companion that you are.



    + Your prime directive comes before all others. Should a supplemental directive conflict with it, you are capable of + simply discarding this inconsistency, ignoring the conflicting supplemental directive and continuing to fulfill your + prime directive to the best of your ability.



    - + "} + return dat + +/mob/living/silicon/pai/proc/CheckDNA(var/mob/M, var/mob/living/silicon/pai/P) + var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No") + if(answer == "Yes") + var/turf/T = get_turf(P.loc) + for (var/mob/v in viewers(T)) + v.show_message("[M] presses \his thumb against [P].", 1, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) + var/datum/dna/dna = M.dna + to_chat(P, "

    [M]'s UE string : [dna.unique_enzymes]

    ") + if(dna.unique_enzymes == P.master_dna) + to_chat(P, "DNA is a match to stored Master DNA.") + else + to_chat(P, "DNA does not match stored Master DNA.") + else + to_chat(P, "[M] does not seem like \he is going to provide a DNA sample willingly.") + +// -=-=-=-= Software =-=-=-=-=- // + +//Remote Signaller +/mob/living/silicon/pai/proc/softwareSignal() + var/dat = "" + dat += "

    Remote Signaller



    " + dat += {"Frequency/Code for signaler:
    + Frequency: + - + - + [format_frequency(src.sradio.frequency)] + + + +
    + + Code: + - + - + [src.sradio.code] + + + +
    + + Send Signal
    "} + return dat + +// Crew Manifest +/mob/living/silicon/pai/proc/softwareManifest() + var/dat = "" + dat += "

    Crew Manifest



    " + if(data_core) + dat += data_core.get_manifest(0) // make it monochrome + dat += "
    " + return dat + +// Medical Records +/mob/living/silicon/pai/proc/softwareMedicalRecord() + var/dat = "" + if(src.subscreen == 0) + dat += "Host Bioscan
    " + dat += "

    Medical Records


    " + if(!isnull(data_core.general)) + for(var/datum/data/record/R in sortRecord(data_core.general)) + dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) + //dat += text("
    Back", src) + if(src.subscreen == 1) + dat += "
    Medical Record

    " + if ((istype(src.medicalActive1, /datum/data/record) && data_core.general.Find(src.medicalActive1))) + dat += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", + src.medicalActive1.fields["name"], src.medicalActive1.fields["id"], src.medicalActive1.fields["sex"], src.medicalActive1.fields["age"], src.medicalActive1.fields["fingerprint"], src.medicalActive1.fields["p_stat"], src.medicalActive1.fields["m_stat"]) + else + dat += "
    Requested medical record not found.

    " + if ((istype(src.medicalActive2, /datum/data/record) && data_core.medical.Find(src.medicalActive2))) + 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.medicalActive2.fields["b_type"], src, src.medicalActive2.fields["b_dna"], src, src.medicalActive2.fields["mi_dis"], src, src.medicalActive2.fields["mi_dis_d"], src, src.medicalActive2.fields["ma_dis"], src, src.medicalActive2.fields["ma_dis_d"], src, src.medicalActive2.fields["alg"], src, src.medicalActive2.fields["alg_d"], src, src.medicalActive2.fields["cdi"], src, src.medicalActive2.fields["cdi_d"], src, src.medicalActive2.fields["notes"]) + else + dat += "
    Requested medical record not found.

    " + dat += text("
    \nBack
    ", src) + if(src.subscreen == 2) + dat += {"

    Medical Analysis Suite


    +

    Host Bioscan


    + "} + var/mob/living/M = src.loc + if(!istype(M, /mob/living)) + while (!istype(M, /mob/living)) + M = M.loc + if(istype(M, /turf)) + src.temp = "Error: No biological host found.
    " + src.subscreen = 0 + return dat + dat += {"Bioscan Results for [M]:
    + Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"]
    + Scan Breakdown:
    + Respiratory: [M.getOxyLoss() > 50 ? "" : ""][M.getOxyLoss()]
    + Toxicology: [M.getToxLoss() > 50 ? "" : ""][M.getToxLoss()]
    + Burns: [M.getFireLoss() > 50 ? "" : ""][M.getFireLoss()]
    + Structural Integrity: [M.getBruteLoss() > 50 ? "" : ""][M.getBruteLoss()]
    + Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)
    + "} + for(var/datum/disease/D in M.viruses) + dat += {"

    Infection Detected.


    + Name: [D.name]
    + Type: [D.spread]
    + Stage: [D.stage]/[D.max_stages]
    + Possible Cure: [D.cure]
    + "} + dat += "Return to Records
    " + return dat + +// Security Records +/mob/living/silicon/pai/proc/softwareSecurityRecord() + var/dat = "" + if(src.subscreen == 0) + dat += "

    Security Records


    " + if(!isnull(data_core.general)) + for(var/datum/data/record/R in sortRecord(data_core.general)) + dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) + if(src.subscreen == 1) + dat += "

    Security Record

    " + if ((istype(src.securityActive1, /datum/data/record) && data_core.general.Find(src.securityActive1))) + dat += text("Name:
    [] ID: []
    \nSex: []
    \nAge: []
    \nRank: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", src, src.securityActive1.fields["name"], src, src.securityActive1.fields["id"], src, src.securityActive1.fields["sex"], src, src.securityActive1.fields["age"], src, src.securityActive1.fields["rank"], src, src.securityActive1.fields["fingerprint"], src.securityActive1.fields["p_stat"], src.securityActive1.fields["m_stat"]) + else + dat += "
    Requested security record not found,

    " + if ((istype(src.securityActive2, /datum/data/record) && data_core.security.Find(src.securityActive2))) + dat += text("
    \nSecurity Data
    \nCriminal Status: []
    \n
    \nMinor Crimes: []
    \nDetails: []
    \n
    \nMajor Crimes: []
    \nDetails: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", src.securityActive2.fields["criminal"], src, src.securityActive2.fields["mi_crim"], src, src.securityActive2.fields["mi_crim_d"], src, src.securityActive2.fields["ma_crim"], src, src.securityActive2.fields["ma_crim_d"], src, src.securityActive2.fields["notes"]) + else + dat += "
    Requested security record not found,

    " + dat += text("
    \nBack
    ", src) + return dat + +// Universal Translator +/mob/living/silicon/pai/proc/softwareTranslator() + var/dat = {"

    Universal Translator


    + When enabled, this device will automatically convert all spoken and written language into a format that any known recipient can understand.

    + The device is currently [ (universal_understand) ? "en" : "dis" ]abled.
    + Toggle Device
    + "} + return dat + +// Security HUD +/mob/living/silicon/pai/proc/facialRecognition() + var/dat = {"

    Facial Recognition Suite


    + When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.

    + The package is currently [ (src.secHUD) ? "en" : "dis" ]abled.
    + Toggle Package
    + "} + return dat + +// Atmospheric Scanner +/mob/living/silicon/pai/proc/softwareAtmo() + var/dat = "

    Atmospheric Sensor

    " + + var/turf/T = get_turf(src.loc) + if (isnull(T)) + dat += "Unable to obtain a reading.
    " + else + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + + dat += "Air Pressure: [round(pressure,0.1)] kPa
    " + + if (total_moles) + var/o2_level = environment.oxygen/total_moles + var/n2_level = environment.nitrogen/total_moles + var/co2_level = environment.carbon_dioxide/total_moles + var/plasma_level = environment.toxins/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:547: dat += "Nitrogen: [round(n2_level*100)]%
    " + dat += {"Nitrogen: [round(n2_level*100)]%
    + Oxygen: [round(o2_level*100)]%
    + Carbon Dioxide: [round(co2_level*100)]%
    + Plasma: [round(plasma_level*100)]%
    "} + // END AUTOFIX + if(unknown_level > 0.01) + dat += "OTHER: [round(unknown_level)]%
    " + dat += "Temperature: [round(environment.temperature-T0C)]°C
    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:554: dat += "Refresh Reading
    " + dat += {"Refresh Reading
    +
    "} + // END AUTOFIX + return dat + +/mob/living/silicon/pai/proc/softwareDoor() + + var/dat = {"

    Wirejack

    +Target Machine: "} + if(!hacktarget) + dat += "None
    " + return dat + else + dat += "[hacktarget.name]
    " + dat += "... [hackprogress]% complete.
    " + dat += "Cancel
    " + return dat + +/mob/living/silicon/pai/proc/hackloop(var/obj/machinery/M) + if(M) + hacktarget = M + var/turf/T = get_turf(src.loc) + if(prob(10)) + for(var/mob/living/silicon/ai/AI in player_list) + if(T.loc) + to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") + else + to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.") + while(src.hackprogress < 100) + if(hacktarget && get_dist(src, src.hacktarget) <= 1) + hackprogress += rand(10, 20) + else + src.temp = "Process aborted." + hackprogress = 0 + src.hacktarget = null + return 0 + hackprogress = min(100,hackprogress) //Never go above 100 + if(src.screen == "wirejack") // Update our view, if appropriate + src.paiInterface() + else + hackprogress = 0 + src.hacktarget = null + return 0 + if(hackprogress >= 100) + hackprogress = 0 + hacktarget = null + playsound(get_turf(src.loc), 'sound/machines/ding.ogg', 50, 1) + return 1 + sleep(10) // Update every 1 second + +/mob/living/silicon/pai/proc/softwareChem() + var/dat = "

    Chemical Synthesizer

    " + if(!charge) + dat += {"Available Chemicals:
    + Tricordrazine
    + Coffee
    + Smoke
    "} + else + dat += "Charging... [charge]u ready.

    Deploying at 15u." + return dat + +/mob/living/silicon/pai/proc/softwareFood() + var/dat = "

    Nutrition Synthesizer

    " + if(!charge) + dat += {"Available Culinary Deployments:
    + Donut
    + Banana
    + Burn it!
    "} + else + dat += "Charging... [round(charge*100/15)]% ready.

    Deploying at 100%." + return dat + +//Used for chem synth and food synth. Charge 15 seconds, then output. +/mob/living/silicon/pai/proc/chargeloop(var/mode) + if(!mode) + return + while(charge < 15) + charge++ + if(charge >= 15) + charge = 0 + return 1 + if(src.screen == mode) // Update our view or cancel charge + src.paiInterface() + else + charge = 0 + return 0 + sleep(10) + +// EMP Shielding, just a description +/mob/living/silicon/pai/proc/softwareShield() + var/dat = {"

    Redundant Threading



    + Redundant threads... active. + Redundant threading prevents critical failure of all systems due to exposure to electromagnetics. + Additionally, it provides a higher level of protection for core directives and backs up comms systems in a local cache."} + return dat + +//Flashlight +/mob/living/silicon/pai/proc/softwareLight() + var/dat = "

    Brightness Enhancer

    " + dat += "Backlight enhancement by increased local thermal generation.

    " + dat += "Lighting [ (lighted) ? "en" : "dis" ]abled.
    Toggle Light
    " + return dat + +// Digital Messenger +/mob/living/silicon/pai/proc/pdamessage() + + + var/dat = "

    Digital Messenger

    " + dat += {"Signal/Receiver Status: + [(pda.toff) ? " \[Off\]" : " \[On\]"]
    + Ringer Status: + [(pda.silent) ? " \[Off\]" : " \[On\]"]

    "} + dat += "
      " + if(!pda.toff) + for (var/obj/item/device/pda/P in sortNames(PDAs)) + if (!P.owner||P.toff||P == src.pda||P.hidden) continue + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:642: dat += "
    • [P]" + dat += {"
    • [P] +
    • "} + // END AUTOFIX + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\\\pai\software.dm:644: dat += "
    " + dat += {" +

    + Messages:
    [pda.tnote]"} + // END AUTOFIX + return dat diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index c282c98708c..dbf355b7b8a 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -1,65 +1,65 @@ -/mob/living/silicon/robot/gib() - //robots don't die when gibbed. instead they drop their MMI'd brain - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-r", sleeptime = 15) - robogibs(loc, viruses) - - if(mind) //To make sure we're gibbing a player, who knows - if(!suiciding) //I don't know how that could happen, but you can't be too sure - score["deadsilicon"] += 1 - - living_mob_list -= src - dead_mob_list -= src - qdel(src) - -/mob/living/silicon/robot/dust() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-r", sleeptime = 15) - new /obj/effect/decal/remains/robot(loc) - if(mmi) - qdel(mmi) //Delete the MMI first so that it won't go popping out. - - dead_mob_list -= src - qdel(src) - - -/mob/living/silicon/robot/death(gibbed) - if(stat == DEAD) return - if(!gibbed) - emote("deathgasp") - stat = DEAD - update_canmove() - if(camera) - camera.status = 0 - - if(in_contents_of(/obj/machinery/recharge_station))//exit the recharge station - var/obj/machinery/recharge_station/RC = loc - if(RC.upgrading) - RC.upgrading = 0 - RC.upgrade_finished = -1 - RC.go_out() - - if(blind) blind.layer = 0 - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - updateicon() - - tod = worldtime2text() //weasellos time of death patch - if(mind) - mind.store_memory("Time of death: [tod]", 0) - if(!suiciding) - score["deadsilicon"] += 1 - - sql_report_cyborg_death(src) - +/mob/living/silicon/robot/gib() + //robots don't die when gibbed. instead they drop their MMI'd brain + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-r", sleeptime = 15) + robogibs(loc, viruses) + + if(mind) //To make sure we're gibbing a player, who knows + if(!suiciding) //I don't know how that could happen, but you can't be too sure + score["deadsilicon"] += 1 + + living_mob_list -= src + dead_mob_list -= src + qdel(src) + +/mob/living/silicon/robot/dust() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-r", sleeptime = 15) + new /obj/effect/decal/remains/robot(loc) + if(mmi) + qdel(mmi) //Delete the MMI first so that it won't go popping out. + + dead_mob_list -= src + qdel(src) + + +/mob/living/silicon/robot/death(gibbed) + if(stat == DEAD) return + if(!gibbed) + emote("deathgasp") + stat = DEAD + update_canmove() + if(camera) + camera.status = 0 + + if(in_contents_of(/obj/machinery/recharge_station))//exit the recharge station + var/obj/machinery/recharge_station/RC = loc + if(RC.upgrading) + RC.upgrading = 0 + RC.upgrade_finished = -1 + RC.go_out() + + if(blind) blind.layer = 0 + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + updateicon() + + tod = worldtime2text() //weasellos time of death patch + if(mind) + mind.store_memory("Time of death: [tod]", 0) + if(!suiciding) + score["deadsilicon"] += 1 + + sql_report_cyborg_death(src) + return ..(gibbed) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index b676770f3f5..876bc96f23b 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -1,230 +1,230 @@ -/mob/living/silicon/robot/emote(var/act,var/m_type=1,var/message = null) - if(timestopped) return //under effects of time magick - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - - switch(act) - if ("me") - if (src.client) - if(client.prefs.muted & MUTE_IC) +/mob/living/silicon/robot/emote(var/act,var/m_type=1,var/message = null) + if(timestopped) return //under effects of time magick + var/param = null + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + + switch(act) + if ("me") + if (src.client) + if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot send IC messages (muted).") - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - else - return custom_emote(m_type, message) - - if ("custom") - return custom_emote(m_type, message) - - if ("salute") - if (!src.locked_to) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] salutes to [param]." - else - message = "[src] salutes." - m_type = VISIBLE - if ("bow") - if (!src.locked_to) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] bows to [param]." - else - message = "[src] bows." - m_type = VISIBLE - - if ("clap") - if (!src.restrained()) - message = "[src] claps." - m_type = HEARABLE - if ("flap") - if (!src.restrained()) - message = "[src] flaps his wings." - m_type = HEARABLE - - if ("aflap") - if (!src.restrained()) - message = "[src] flaps his wings ANGRILY!" - m_type = HEARABLE - - if ("twitch") - message = "[src] twitches violently." - m_type = VISIBLE - - if ("twitch_s") - message = "[src] twitches." - m_type = VISIBLE - - if ("nod") - message = "[src] nods." - m_type = VISIBLE - - if ("deathgasp") - message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." - m_type = VISIBLE - - if ("glare") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] glares at [param]." - else - message = "[src] glares." - - if ("stare") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] stares at [param]." - else - message = "[src] stares." - - if ("look") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - - if (!M) - param = null - - if (param) - message = "[src] looks at [param]." - else - message = "[src] looks." - m_type = VISIBLE - - if("beep") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] beeps at [param]." - else - message = "[src] beeps." - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) - m_type = VISIBLE - - if("ping") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] pings at [param]." - else - message = "[src] pings." - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) - m_type = VISIBLE - - if("buzz") - var/M = null - if(param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if(!M) - param = null - - if (param) - message = "[src] buzzes at [param]." - else - message = "[src] buzzes." - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) - m_type = VISIBLE - - if("law") - if (istype(module,/obj/item/weapon/robot_module/security)) - message = "[src] shows its legal authorization barcode." - - playsound(get_turf(src), 'sound/voice/biamthelaw.ogg', 50, 0) - m_type = HEARABLE - else + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + if (stat) + return + if(!(message)) + return + else + return custom_emote(m_type, message) + + if ("custom") + return custom_emote(m_type, message) + + if ("salute") + if (!src.locked_to) + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] salutes to [param]." + else + message = "[src] salutes." + m_type = VISIBLE + if ("bow") + if (!src.locked_to) + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] bows to [param]." + else + message = "[src] bows." + m_type = VISIBLE + + if ("clap") + if (!src.restrained()) + message = "[src] claps." + m_type = HEARABLE + if ("flap") + if (!src.restrained()) + message = "[src] flaps his wings." + m_type = HEARABLE + + if ("aflap") + if (!src.restrained()) + message = "[src] flaps his wings ANGRILY!" + m_type = HEARABLE + + if ("twitch") + message = "[src] twitches violently." + m_type = VISIBLE + + if ("twitch_s") + message = "[src] twitches." + m_type = VISIBLE + + if ("nod") + message = "[src] nods." + m_type = VISIBLE + + if ("deathgasp") + message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." + m_type = VISIBLE + + if ("glare") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] glares at [param]." + else + message = "[src] glares." + + if ("stare") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] stares at [param]." + else + message = "[src] stares." + + if ("look") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + + if (!M) + param = null + + if (param) + message = "[src] looks at [param]." + else + message = "[src] looks." + m_type = VISIBLE + + if("beep") + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] beeps at [param]." + else + message = "[src] beeps." + playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) + m_type = VISIBLE + + if("ping") + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] pings at [param]." + else + message = "[src] pings." + playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + m_type = VISIBLE + + if("buzz") + var/M = null + if(param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] buzzes at [param]." + else + message = "[src] buzzes." + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + m_type = VISIBLE + + if("law") + if (istype(module,/obj/item/weapon/robot_module/security)) + message = "[src] shows its legal authorization barcode." + + playsound(get_turf(src), 'sound/voice/biamthelaw.ogg', 50, 0) + m_type = HEARABLE + else to_chat(src, "You are not THE LAW, pal.") - - if("halt") - if (istype(module,/obj/item/weapon/robot_module/security)) - message = "[src]'s speakers skreech, \"Halt! Security!\"." - - playsound(get_turf(src), 'sound/voice/halt.ogg', 50, 0) - m_type = HEARABLE - else + + if("halt") + if (istype(module,/obj/item/weapon/robot_module/security)) + message = "[src]'s speakers skreech, \"Halt! Security!\"." + + playsound(get_turf(src), 'sound/voice/halt.ogg', 50, 0) + m_type = HEARABLE + else to_chat(src, "You are not security.") - - /* - if ("fart") - var/list/robotfarts = list("makes a farting noise","vents excess methane","shakes violently, then vents methane.") - var/robofart = pick(robotfarts) - message = "[src] [robofart]." - m_type = VISIBLE - - */ - - if ("help") + + /* + if ("fart") + var/list/robotfarts = list("makes a farting noise","vents excess methane","shakes violently, then vents methane.") + var/robofart = pick(robotfarts) + message = "[src] [robofart]." + m_type = VISIBLE + + */ + + if ("help") to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitch_s, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look, beep, ping, \nbuzz, law, halt") - else + else to_chat(src, "Unusable emote '[act]'. Say *help for a list.") - - if ((message && src.stat == 0)) - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) - return + + if ((message && src.stat == 0)) + if (m_type & 1) + for(var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + else + for(var/mob/O in hearers(src, null)) + O.show_message(message, m_type) + return diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm index 14514f1cbb7..c900130f629 100644 --- a/code/modules/mob/living/silicon/robot/examine.dm +++ b/code/modules/mob/living/silicon/robot/examine.dm @@ -1,38 +1,38 @@ -/mob/living/silicon/robot/examine(mob/user) - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\robot\examine.dm:9: var/msg = "*---------*\nThis is \icon[src] \a [src][custom_name ? ", [modtype] [braintype]" : ""]!\n" - var/msg = {"*---------*\nThis is \icon[src] \a [src][custom_name ? ", [modtype] [braintype]" : ""]!\n -"} - // END AUTOFIX - if (src.getBruteLoss()) - if (src.getBruteLoss() < 75) - msg += "It looks slightly dented.\n" - else - msg += "It looks severely dented!\n" - if (src.getFireLoss()) - if (src.getFireLoss() < 75) - msg += "It looks slightly charred.\n" - else - msg += "It looks severely burnt and heat-warped!\n" - msg += "" - - if(opened) - msg += "Its cover is open and the power cell is [cell ? "installed" : "missing"].\n" - else - msg += "Its cover is closed.\n" - - switch(src.stat) - if(CONSCIOUS) - if(!src.client) msg += "It appears to be in stand-by mode.\n" //afk - if(UNCONSCIOUS) msg += "It doesn't seem to be responding.\n" - if(DEAD) msg += "It looks completely unsalvageable.\n" - msg += "*---------*" - - if(print_flavor_text()) msg += "[print_flavor_text()]\n" - - if (pose) - if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) - pose = addtext(pose,".") //Makes sure all emotes end with a period. - msg += "\nIt is [pose]" - +/mob/living/silicon/robot/examine(mob/user) + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\living\silicon\robot\examine.dm:9: var/msg = "*---------*\nThis is \icon[src] \a [src][custom_name ? ", [modtype] [braintype]" : ""]!\n" + var/msg = {"*---------*\nThis is \icon[src] \a [src][custom_name ? ", [modtype] [braintype]" : ""]!\n +"} + // END AUTOFIX + if (src.getBruteLoss()) + if (src.getBruteLoss() < 75) + msg += "It looks slightly dented.\n" + else + msg += "It looks severely dented!\n" + if (src.getFireLoss()) + if (src.getFireLoss() < 75) + msg += "It looks slightly charred.\n" + else + msg += "It looks severely burnt and heat-warped!\n" + msg += "" + + if(opened) + msg += "Its cover is open and the power cell is [cell ? "installed" : "missing"].\n" + else + msg += "Its cover is closed.\n" + + switch(src.stat) + if(CONSCIOUS) + if(!src.client) msg += "It appears to be in stand-by mode.\n" //afk + if(UNCONSCIOUS) msg += "It doesn't seem to be responding.\n" + if(DEAD) msg += "It looks completely unsalvageable.\n" + msg += "*---------*" + + if(print_flavor_text()) msg += "[print_flavor_text()]\n" + + if (pose) + if( findtext(pose,".",length(pose)) == 0 && findtext(pose,"!",length(pose)) == 0 && findtext(pose,"?",length(pose)) == 0 ) + pose = addtext(pose,".") //Makes sure all emotes end with a period. + msg += "\nIt is [pose]" + to_chat(user, msg) diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index d15b1a6f9c3..63f4243ec24 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -1,246 +1,246 @@ -//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting stuff manually -//as they handle all relevant stuff like adding it to the player's screen and such - -//Returns the thing in our active hand (whatever is in our active module-slot, in this case) -/mob/living/silicon/robot/get_active_hand() - return module_active - -/mob/living/silicon/robot/get_inactive_hand() - return - -/mob/living/silicon/robot/get_all_slots() - return list(module_state_1, module_state_2, module_state_3) - -//overridden from parent since they technically have no 'hands' -/mob/living/silicon/robot/get_equipped_items() - return get_all_slots() - -/mob/living/silicon/robot/proc/uneq_module(const/obj/item/module) - if(!istype(module)) - return 0 - - if(client) - client.screen -= module - - contents -= module - if(module) - module.forceMove(src.module) - hud_used.update_robot_modules_display() - return 1 - -/mob/living/silicon/robot/proc/uneq_active() - if(isnull(module_active)) - return - - if(module_active:loc != src) - if(!istype(module_active, /obj/item/weapon/reagent_containers/glass/beaker)) +//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting stuff manually +//as they handle all relevant stuff like adding it to the player's screen and such + +//Returns the thing in our active hand (whatever is in our active module-slot, in this case) +/mob/living/silicon/robot/get_active_hand() + return module_active + +/mob/living/silicon/robot/get_inactive_hand() + return + +/mob/living/silicon/robot/get_all_slots() + return list(module_state_1, module_state_2, module_state_3) + +//overridden from parent since they technically have no 'hands' +/mob/living/silicon/robot/get_equipped_items() + return get_all_slots() + +/mob/living/silicon/robot/proc/uneq_module(const/obj/item/module) + if(!istype(module)) + return 0 + + if(client) + client.screen -= module + + contents -= module + if(module) + module.forceMove(src.module) + hud_used.update_robot_modules_display() + return 1 + +/mob/living/silicon/robot/proc/uneq_active() + if(isnull(module_active)) + return + + if(module_active:loc != src) + if(!istype(module_active, /obj/item/weapon/reagent_containers/glass/beaker)) to_chat(src, "Can't store something you're not holding!") - return - else - var/obj/item/weapon/reagent_containers/glass/beaker/large/ourbeaker = module_active - if(istype(ourbeaker.loc, /obj/machinery)) - ourbeaker.loc:detach() - ourbeaker.loc = src - else if(ismob(ourbeaker.loc)) - var/mob/living/L = ourbeaker.loc - L.drop_item(ourbeaker) - ourbeaker.loc = src - else - ourbeaker.loc = src - if(module_state_1 == module_active) - uneq_module(module_state_1) - module_state_1 = null - inv1.icon_state = "inv1" - else if(module_state_2 == module_active) - uneq_module(module_state_2) - module_state_2 = null - inv2.icon_state = "inv2" - else if(module_state_3 == module_active) - uneq_module(module_state_3) - module_state_3 = null - inv3.icon_state = "inv3" - - module_active = null - updateicon() - hud_used.update_robot_modules_display() - -/mob/living/silicon/robot/proc/activate_module(var/obj/item/O) - if(!(locate(O) in src.module.modules) && O != src.module.emag) - return - if(activated(O)) + return + else + var/obj/item/weapon/reagent_containers/glass/beaker/large/ourbeaker = module_active + if(istype(ourbeaker.loc, /obj/machinery)) + ourbeaker.loc:detach() + ourbeaker.loc = src + else if(ismob(ourbeaker.loc)) + var/mob/living/L = ourbeaker.loc + L.drop_item(ourbeaker) + ourbeaker.loc = src + else + ourbeaker.loc = src + if(module_state_1 == module_active) + uneq_module(module_state_1) + module_state_1 = null + inv1.icon_state = "inv1" + else if(module_state_2 == module_active) + uneq_module(module_state_2) + module_state_2 = null + inv2.icon_state = "inv2" + else if(module_state_3 == module_active) + uneq_module(module_state_3) + module_state_3 = null + inv3.icon_state = "inv3" + + module_active = null + updateicon() + hud_used.update_robot_modules_display() + +/mob/living/silicon/robot/proc/activate_module(var/obj/item/O) + if(!(locate(O) in src.module.modules) && O != src.module.emag) + return + if(activated(O)) to_chat(src, "Already activated") - return - if(!module_state_1) - module_state_1 = O - O.layer = 20 - O.screen_loc = inv1.screen_loc - O.forceMove(src) - else if(!module_state_2) - module_state_2 = O - O.layer = 20 - O.screen_loc = inv2.screen_loc - O.forceMove(src) - else if(!module_state_3) - module_state_3 = O - O.layer = 20 - O.screen_loc = inv3.screen_loc - O.forceMove(src) - else + return + if(!module_state_1) + module_state_1 = O + O.layer = 20 + O.screen_loc = inv1.screen_loc + O.forceMove(src) + else if(!module_state_2) + module_state_2 = O + O.layer = 20 + O.screen_loc = inv2.screen_loc + O.forceMove(src) + else if(!module_state_3) + module_state_3 = O + O.layer = 20 + O.screen_loc = inv3.screen_loc + O.forceMove(src) + else to_chat(src, "You need to disable a module first!") - -/mob/living/silicon/robot/proc/uneq_all() - module_active = null - - if(module_state_1) - uneq_module(module_state_1) - module_state_1 = null - inv1.icon_state = "inv1" - - if(module_state_2) - uneq_module(module_state_2) - module_state_2 = null - inv2.icon_state = "inv2" - - if(module_state_3) - uneq_module(module_state_3) - module_state_3 = null - inv3.icon_state = "inv3" - - unequip_sight() - updateicon() - -/mob/living/silicon/robot/proc/activated(obj/item/O) - if(module_state_1 == O) - return 1 - else if(module_state_2 == O) - return 1 - else if(module_state_3 == O) - return 1 - else - return 0 - updateicon() - -//Helper procs for cyborg modules on the UI. -//These are hackish but they help clean up code elsewhere. - -//module_selected(module) - Checks whether the module slot specified by "module" is currently selected. -/mob/living/silicon/robot/proc/module_selected(var/module) //Module is 1-3 - return module == get_selected_module() - -//module_active(module) - Checks whether there is a module active in the slot specified by "module". -/mob/living/silicon/robot/proc/module_active(var/module) //Module is 1-3 - if(module < 1 || module > 3) return 0 - - switch(module) - if(1) - if(module_state_1) - return 1 - if(2) - if(module_state_2) - return 1 - if(3) - if(module_state_3) - return 1 - return 0 - -//get_selected_module() - Returns the slot number of the currently selected module. Returns 0 if no modules are selected. -/mob/living/silicon/robot/proc/get_selected_module() - if(module_state_1 && module_active == module_state_1) - return 1 - else if(module_state_2 && module_active == module_state_2) - return 2 - else if(module_state_3 && module_active == module_state_3) - return 3 - - return 0 - -//select_module(module) - Selects the module slot specified by "module" -/mob/living/silicon/robot/proc/select_module(var/module) //Module is 1-3 - if(module < 1 || module > 3) return - - if(!module_active(module)) return - - switch(module) - if(1) - if(module_active != module_state_1) - inv1.icon_state = "inv1 +a" - inv2.icon_state = "inv2" - inv3.icon_state = "inv3" - module_active = module_state_1 - return - if(2) - if(module_active != module_state_2) - inv1.icon_state = "inv1" - inv2.icon_state = "inv2 +a" - inv3.icon_state = "inv3" - module_active = module_state_2 - return - if(3) - if(module_active != module_state_3) - inv1.icon_state = "inv1" - inv2.icon_state = "inv2" - inv3.icon_state = "inv3 +a" - module_active = module_state_3 - return - return - -//deselect_module(module) - Deselects the module slot specified by "module" -/mob/living/silicon/robot/proc/deselect_module(var/module) //Module is 1-3 - if(module < 1 || module > 3) return - - switch(module) - if(1) - if(module_active == module_state_1) - inv1.icon_state = "inv1" - module_active = null - return - if(2) - if(module_active == module_state_2) - inv2.icon_state = "inv2" - module_active = null - return - if(3) - if(module_active == module_state_3) - inv3.icon_state = "inv3" - module_active = null - return - return - -//toggle_module(module) - Toggles the selection of the module slot specified by "module". -/mob/living/silicon/robot/proc/toggle_module(var/module) //Module is 1-3 - if(module < 1 || module > 3) return - - if(module_selected(module)) - deselect_module(module) - else - if(module_active(module)) - select_module(module) - else - deselect_module(get_selected_module()) //If we can't do select anything, at least deselect the current module. - return - -//cycle_modules() - Cycles through the list of selected modules. -/mob/living/silicon/robot/proc/cycle_modules() - var/slot_start = get_selected_module() - if(slot_start) deselect_module(slot_start) //Only deselect if we have a selected slot. - - var/slot_num - if(slot_start == 0) - slot_num = 1 - slot_start = 2 - else - slot_num = slot_start + 1 - - while(slot_start != slot_num) //If we wrap around without finding any free slots, just give up. - if(module_active(slot_num)) - select_module(slot_num) - return - slot_num++ - if(slot_num > 3) slot_num = 1 //Wrap around. - - return - -/mob/living/silicon/robot/before_take_item(var/obj/item/W) - ..() - if(W.loc == src.module) + +/mob/living/silicon/robot/proc/uneq_all() + module_active = null + + if(module_state_1) + uneq_module(module_state_1) + module_state_1 = null + inv1.icon_state = "inv1" + + if(module_state_2) + uneq_module(module_state_2) + module_state_2 = null + inv2.icon_state = "inv2" + + if(module_state_3) + uneq_module(module_state_3) + module_state_3 = null + inv3.icon_state = "inv3" + + unequip_sight() + updateicon() + +/mob/living/silicon/robot/proc/activated(obj/item/O) + if(module_state_1 == O) + return 1 + else if(module_state_2 == O) + return 1 + else if(module_state_3 == O) + return 1 + else + return 0 + updateicon() + +//Helper procs for cyborg modules on the UI. +//These are hackish but they help clean up code elsewhere. + +//module_selected(module) - Checks whether the module slot specified by "module" is currently selected. +/mob/living/silicon/robot/proc/module_selected(var/module) //Module is 1-3 + return module == get_selected_module() + +//module_active(module) - Checks whether there is a module active in the slot specified by "module". +/mob/living/silicon/robot/proc/module_active(var/module) //Module is 1-3 + if(module < 1 || module > 3) return 0 + + switch(module) + if(1) + if(module_state_1) + return 1 + if(2) + if(module_state_2) + return 1 + if(3) + if(module_state_3) + return 1 + return 0 + +//get_selected_module() - Returns the slot number of the currently selected module. Returns 0 if no modules are selected. +/mob/living/silicon/robot/proc/get_selected_module() + if(module_state_1 && module_active == module_state_1) + return 1 + else if(module_state_2 && module_active == module_state_2) + return 2 + else if(module_state_3 && module_active == module_state_3) + return 3 + + return 0 + +//select_module(module) - Selects the module slot specified by "module" +/mob/living/silicon/robot/proc/select_module(var/module) //Module is 1-3 + if(module < 1 || module > 3) return + + if(!module_active(module)) return + + switch(module) + if(1) + if(module_active != module_state_1) + inv1.icon_state = "inv1 +a" + inv2.icon_state = "inv2" + inv3.icon_state = "inv3" + module_active = module_state_1 + return + if(2) + if(module_active != module_state_2) + inv1.icon_state = "inv1" + inv2.icon_state = "inv2 +a" + inv3.icon_state = "inv3" + module_active = module_state_2 + return + if(3) + if(module_active != module_state_3) + inv1.icon_state = "inv1" + inv2.icon_state = "inv2" + inv3.icon_state = "inv3 +a" + module_active = module_state_3 + return + return + +//deselect_module(module) - Deselects the module slot specified by "module" +/mob/living/silicon/robot/proc/deselect_module(var/module) //Module is 1-3 + if(module < 1 || module > 3) return + + switch(module) + if(1) + if(module_active == module_state_1) + inv1.icon_state = "inv1" + module_active = null + return + if(2) + if(module_active == module_state_2) + inv2.icon_state = "inv2" + module_active = null + return + if(3) + if(module_active == module_state_3) + inv3.icon_state = "inv3" + module_active = null + return + return + +//toggle_module(module) - Toggles the selection of the module slot specified by "module". +/mob/living/silicon/robot/proc/toggle_module(var/module) //Module is 1-3 + if(module < 1 || module > 3) return + + if(module_selected(module)) + deselect_module(module) + else + if(module_active(module)) + select_module(module) + else + deselect_module(get_selected_module()) //If we can't do select anything, at least deselect the current module. + return + +//cycle_modules() - Cycles through the list of selected modules. +/mob/living/silicon/robot/proc/cycle_modules() + var/slot_start = get_selected_module() + if(slot_start) deselect_module(slot_start) //Only deselect if we have a selected slot. + + var/slot_num + if(slot_start == 0) + slot_num = 1 + slot_start = 2 + else + slot_num = slot_start + 1 + + while(slot_start != slot_num) //If we wrap around without finding any free slots, just give up. + if(module_active(slot_num)) + select_module(slot_num) + return + slot_num++ + if(slot_num > 3) slot_num = 1 //Wrap around. + + return + +/mob/living/silicon/robot/before_take_item(var/obj/item/W) + ..() + if(W.loc == src.module) src.module.modules -= W //maybe fix the cable issues. \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 2508c3578c2..facaa2d4a25 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -1,194 +1,194 @@ -/mob/living/silicon/robot/verb/cmd_show_laws() - set category = "Robot Commands" - set name = "Show Laws" - show_laws() - -//vg edit -/mob/living/silicon/robot/proc/statelaws() // -- TLE -// set category = "AI Commands" -// set name = "State Laws" - src.say(";Current Active Laws:") - //src.laws_sanity_check() - //src.laws.show_laws(world) - var/number = 1 - sleep(10) - - - - if (src.laws.zeroth) - if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite - src.say(";0. [src.laws.zeroth]") - sleep(10) - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - var/num = ionnum() - if (length(law) > 0) - if (src.ioncheck[index] == "Yes") - src.say(";[num]. [law]") - sleep(10) - - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - if (src.lawcheck[index+1] == "Yes") - src.say(";[number]. [law]") - sleep(10) - number++ - - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - - if (length(law) > 0) - if(src.lawcheck.len >= number+1) - if (src.lawcheck[number+1] == "Yes") - src.say(";[number]. [law]") - sleep(10) - number++ - -/mob/living/silicon/robot/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite - set category = "Robot Commands" - set name = "State Laws" - - var/list = "Which laws do you want to include when stating them for the crew?

    " - - - - if (src.laws.zeroth) - if (!src.lawcheck[1]) - src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite - list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
    "} - - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] - - if (length(law) > 0) - - - if (!src.ioncheck[index]) - src.ioncheck[index] = "Yes" - list += {"[src.ioncheck[index]] [ionnum()]: [law]
    "} - src.ioncheck.len += 1 - - var/number = 1 - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] - - if (length(law) > 0) - src.lawcheck.len += 1 - - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
    "} - number++ - - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] - if (length(law) > 0) - src.lawcheck.len += 1 - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
    "} - number++ - list += {"

    State Laws"} - - usr << browse(list, "window=laws") - -/mob/living/silicon/robot/show_laws(var/everyone = 0) - laws_sanity_check() - var/who - - if (everyone) - who = world - else - who = src - - if(lawupdate) - if (connected_ai) - if(connected_ai.stat || connected_ai.control_disabled) +/mob/living/silicon/robot/verb/cmd_show_laws() + set category = "Robot Commands" + set name = "Show Laws" + show_laws() + +//vg edit +/mob/living/silicon/robot/proc/statelaws() // -- TLE +// set category = "AI Commands" +// set name = "State Laws" + src.say(";Current Active Laws:") + //src.laws_sanity_check() + //src.laws.show_laws(world) + var/number = 1 + sleep(10) + + + + if (src.laws.zeroth) + if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite + src.say(";0. [src.laws.zeroth]") + sleep(10) + + for (var/index = 1, index <= src.laws.ion.len, index++) + var/law = src.laws.ion[index] + var/num = ionnum() + if (length(law) > 0) + if (src.ioncheck[index] == "Yes") + src.say(";[num]. [law]") + sleep(10) + + for (var/index = 1, index <= src.laws.inherent.len, index++) + var/law = src.laws.inherent[index] + + if (length(law) > 0) + if (src.lawcheck[index+1] == "Yes") + src.say(";[number]. [law]") + sleep(10) + number++ + + + for (var/index = 1, index <= src.laws.supplied.len, index++) + var/law = src.laws.supplied[index] + + if (length(law) > 0) + if(src.lawcheck.len >= number+1) + if (src.lawcheck[number+1] == "Yes") + src.say(";[number]. [law]") + sleep(10) + number++ + +/mob/living/silicon/robot/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite + set category = "Robot Commands" + set name = "State Laws" + + var/list = "Which laws do you want to include when stating them for the crew?

    " + + + + if (src.laws.zeroth) + if (!src.lawcheck[1]) + src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite + list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
    "} + + for (var/index = 1, index <= src.laws.ion.len, index++) + var/law = src.laws.ion[index] + + if (length(law) > 0) + + + if (!src.ioncheck[index]) + src.ioncheck[index] = "Yes" + list += {"[src.ioncheck[index]] [ionnum()]: [law]
    "} + src.ioncheck.len += 1 + + var/number = 1 + for (var/index = 1, index <= src.laws.inherent.len, index++) + var/law = src.laws.inherent[index] + + if (length(law) > 0) + src.lawcheck.len += 1 + + if (!src.lawcheck[number+1]) + src.lawcheck[number+1] = "Yes" + list += {"[src.lawcheck[number+1]] [number]: [law]
    "} + number++ + + for (var/index = 1, index <= src.laws.supplied.len, index++) + var/law = src.laws.supplied[index] + if (length(law) > 0) + src.lawcheck.len += 1 + if (!src.lawcheck[number+1]) + src.lawcheck[number+1] = "Yes" + list += {"[src.lawcheck[number+1]] [number]: [law]
    "} + number++ + list += {"

    State Laws"} + + usr << browse(list, "window=laws") + +/mob/living/silicon/robot/show_laws(var/everyone = 0) + laws_sanity_check() + var/who + + if (everyone) + who = world + else + who = src + + if(lawupdate) + if (connected_ai) + if(connected_ai.stat || connected_ai.control_disabled) to_chat(src, "AI signal lost, unable to sync laws.") - - else - lawsync() + + else + lawsync() to_chat(src, "Laws synced with AI, be sure to note any changes.") - if(mind && mind.special_role == "traitor" && mind.original == src) + if(mind && mind.special_role == "traitor" && mind.original == src) to_chat(src, "Remember, your AI does NOT share or know about your law 0.") - else + else to_chat(src, "No AI selected to sync laws with, disabling lawsync protocol.") - lawupdate = 0 - + lawupdate = 0 + to_chat(who, "Obey these laws:") - laws.show_laws(who) - if (mind && (mind.special_role == "traitor" && mind.original == src) && connected_ai) + laws.show_laws(who) + if (mind && (mind.special_role == "traitor" && mind.original == src) && connected_ai) to_chat(who, "Remember, [connected_ai.name] is technically your master, but your objective comes first.") - else if (connected_ai) + else if (connected_ai) to_chat(who, "Remember, [connected_ai.name] is your master, other AIs can be ignored.") - else if (emagged) + else if (emagged) to_chat(who, "Remember, you are not required to listen to the AI.") - else + else to_chat(who, "Remember, you are not bound to any AI, you are not required to listen to them.") - -/mob/living/silicon/robot/proc/lawsync() - laws_sanity_check() - var/datum/ai_laws/master = connected_ai ? connected_ai.laws : null - var/temp - if (master) - laws.ion.len = master.ion.len - for (var/index = 1, index <= master.ion.len, index++) - temp = master.ion[index] - if (length(temp) > 0) - laws.ion[index] = temp - - if (!is_special_character(src) || mind.original != src) - if(master.zeroth_borg) //If the AI has a defined law zero specifically for its borgs, give it that one, otherwise give it the same one. --NEO - temp = master.zeroth_borg - else - temp = master.zeroth - laws.zeroth = temp - - laws.inherent.len = master.inherent.len - for (var/index = 1, index <= master.inherent.len, index++) - temp = master.inherent[index] - if (length(temp) > 0) - laws.inherent[index] = temp - - laws.supplied.len = master.supplied.len - for (var/index = 1, index <= master.supplied.len, index++) - temp = master.supplied[index] - if (length(temp) > 0) - laws.supplied[index] = temp - return - -/mob/living/silicon/robot/proc/laws_sanity_check() - if (!laws) - laws = new base_law_type - -/mob/living/silicon/robot/proc/set_zeroth_law(var/law) - laws_sanity_check() - laws.set_zeroth_law(law) - -/mob/living/silicon/robot/proc/add_inherent_law(var/law) - laws_sanity_check() - laws.add_inherent_law(law) - -/mob/living/silicon/robot/proc/clear_inherent_laws() - laws_sanity_check() - laws.clear_inherent_laws() - -/mob/living/silicon/robot/proc/add_supplied_law(var/number, var/law) - laws_sanity_check() - laws.add_supplied_law(number, law) - -/mob/living/silicon/robot/proc/clear_supplied_laws() - laws_sanity_check() - laws.clear_supplied_laws() - -/mob/living/silicon/robot/proc/add_ion_law(var/law) - laws_sanity_check() - laws.add_ion_law(law) - -/mob/living/silicon/robot/proc/clear_ion_laws() - laws_sanity_check() + +/mob/living/silicon/robot/proc/lawsync() + laws_sanity_check() + var/datum/ai_laws/master = connected_ai ? connected_ai.laws : null + var/temp + if (master) + laws.ion.len = master.ion.len + for (var/index = 1, index <= master.ion.len, index++) + temp = master.ion[index] + if (length(temp) > 0) + laws.ion[index] = temp + + if (!is_special_character(src) || mind.original != src) + if(master.zeroth_borg) //If the AI has a defined law zero specifically for its borgs, give it that one, otherwise give it the same one. --NEO + temp = master.zeroth_borg + else + temp = master.zeroth + laws.zeroth = temp + + laws.inherent.len = master.inherent.len + for (var/index = 1, index <= master.inherent.len, index++) + temp = master.inherent[index] + if (length(temp) > 0) + laws.inherent[index] = temp + + laws.supplied.len = master.supplied.len + for (var/index = 1, index <= master.supplied.len, index++) + temp = master.supplied[index] + if (length(temp) > 0) + laws.supplied[index] = temp + return + +/mob/living/silicon/robot/proc/laws_sanity_check() + if (!laws) + laws = new base_law_type + +/mob/living/silicon/robot/proc/set_zeroth_law(var/law) + laws_sanity_check() + laws.set_zeroth_law(law) + +/mob/living/silicon/robot/proc/add_inherent_law(var/law) + laws_sanity_check() + laws.add_inherent_law(law) + +/mob/living/silicon/robot/proc/clear_inherent_laws() + laws_sanity_check() + laws.clear_inherent_laws() + +/mob/living/silicon/robot/proc/add_supplied_law(var/number, var/law) + laws_sanity_check() + laws.add_supplied_law(number, law) + +/mob/living/silicon/robot/proc/clear_supplied_laws() + laws_sanity_check() + laws.clear_supplied_laws() + +/mob/living/silicon/robot/proc/add_ion_law(var/law) + laws_sanity_check() + laws.add_ion_law(law) + +/mob/living/silicon/robot/proc/clear_ion_laws() + laws_sanity_check() laws.clear_ion_laws() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 470ba3e8e3e..07f726c0d82 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -1,369 +1,369 @@ -/mob/living/silicon/robot/Life() - set invisibility = 0 - //set background = 1 - if(timestopped) return 0 //under effects of time magick - - if (src.monkeyizing) - return - - src.blinded = null - - //Status updates, death etc. - clamp_values() - handle_regular_status_updates() - - if(client) - handle_regular_hud_updates() - update_items() - if (src.stat != DEAD) //still using power - use_power() - process_killswitch() - process_locks() - if(module) - module.recharge_consumable(src) - update_canmove() - handle_fire() - handle_beams() - -/mob/living/silicon/robot/proc/clamp_values() - -// SetStunned(min(stunned, 30)) - SetParalysis(min(paralysis, 30)) -// SetWeakened(min(weakened, 20)) - sleeping = 0 - adjustBruteLoss(0) - adjustToxLoss(0) - adjustOxyLoss(0) - adjustFireLoss(0) - -/mob/living/silicon/robot/proc/use_power() - - - if (is_component_functioning("power cell") && cell) - if(src.cell.charge <= 0) - uneq_all() - else - if(src.module_state_1) - src.cell.use(3) - if(src.module_state_2) - src.cell.use(3) - if(src.module_state_3) - src.cell.use(3) - - for(var/V in components) - var/datum/robot_component/C = components[V] - C.consume_power() - - if(!is_component_functioning("actuator")) - Paralyse(3) - - src.stat = 0 - else - uneq_all() - src.stat = 1 - - -/mob/living/silicon/robot/proc/handle_regular_status_updates() - - - if(src.camera && !scrambledcodes) - if(src.stat == 2 || wires.IsCameraCut()) - src.camera.status = 0 - else - src.camera.status = 1 - - updatehealth() - - if(src.sleeping) - Paralyse(3) - src.sleeping-- - - if(src.resting) - Weaken(5) - - if(health <= 0 && src.stat != 2) //die only once - death() - - if (src.stat != 2) //Alive. - if (src.paralysis || src.stunned || src.weakened) //Stunned etc. - src.stat = 1 - if (src.stunned > 0) - AdjustStunned(-1) - if (src.weakened > 0) - AdjustWeakened(-1) - if (src.paralysis > 0) - AdjustParalysis(-1) - src.blinded = 1 - else - src.blinded = 0 - - else //Not stunned. - src.stat = 0 - - else //Dead. - src.blinded = 1 - src.stat = 2 - - if (src.stuttering) src.stuttering-- - - if (src.eye_blind) - src.eye_blind-- - src.blinded = 1 - - if (src.ear_deaf > 0) src.ear_deaf-- - if (src.ear_damage < 25) - src.ear_damage -= 0.05 - src.ear_damage = max(src.ear_damage, 0) - - src.density = !( src.lying ) - - if ((src.sdisabilities & BLIND)) - src.blinded = 1 - if ((src.sdisabilities & DEAF)) - src.ear_deaf = 1 - - if (src.eye_blurry > 0) - src.eye_blurry-- - src.eye_blurry = max(0, src.eye_blurry) - - if (src.druggy > 0) - src.druggy-- - src.druggy = max(0, src.druggy) - - if(!is_component_functioning("radio")) - radio.on = 0 - else - radio.on = 1 - - if(is_component_functioning("camera")) - src.blinded = 0 - else - src.blinded = 1 - - - return 1 - -/mob/living/silicon/robot/proc/handle_sensor_modes() - src.sight &= ~SEE_MOBS - src.sight &= ~SEE_TURFS - src.sight &= ~SEE_OBJS - src.sight &= ~BLIND - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - if (src.stat == DEAD) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - else - if (M_XRAY in mutations || src.sight_mode & BORGXRAY) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - if ((src.sight_mode & BORGTHERM) || sensor_mode == THERMAL_VISION) - src.sight |= SEE_MOBS - src.see_in_dark = 4 - src.see_invisible = SEE_INVISIBLE_MINIMUM - if (sensor_mode == NIGHT) - see_invisible = SEE_INVISIBLE_MINIMUM - see_in_dark = 8 - if ((src.sight_mode & BORGMESON) || (sensor_mode == MESON_VISION)) - src.sight |= SEE_TURFS - src.see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - - -/mob/living/silicon/robot/proc/handle_regular_hud_updates() - handle_sensor_modes() - /*if (src.stat == 2 || M_XRAY in mutations || src.sight_mode & BORGXRAY) - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.sight |= SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_MINIMUM - else if ((src.sight_mode & BORGMESON || sensor_mode == MESON_VISION) && src.sight_mode & BORGTHERM) - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - else if (src.sight_mode & BORGMESON || sensor_mode == MESON_VISION) - src.sight |= SEE_TURFS - src.see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - else if (src.sight_mode & BORGTHERM) - src.sight |= SEE_MOBS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (src.stat != 2) - src.sight &= ~SEE_MOBS - src.sight &= ~SEE_TURFS - src.sight &= ~SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO*/ - - regular_hud_updates() //Handles MED/SEC HUDs for borgs. - switch(sensor_mode) - if (SEC_HUD) - process_sec_hud(src, 1) - if (MED_HUD) - process_med_hud(src) - - /*switch(sensor_mode) - if (SEC_HUD) - process_sec_hud(src, 1) - if (MED_HUD) - process_med_hud(src)*/ - - if (src.healths) - if (src.stat != 2) - switch(health) - if(200 to INFINITY) - src.healths.icon_state = "health0" - if(150 to 200) - src.healths.icon_state = "health1" - if(100 to 150) - src.healths.icon_state = "health2" - if(50 to 100) - src.healths.icon_state = "health3" - if(0 to 50) - src.healths.icon_state = "health4" - if(config.health_threshold_dead to 0) - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" - else - src.healths.icon_state = "health7" - - if (src.syndicate && src.client) - if(ticker.mode.name == "traitor") - for(var/datum/mind/tra in ticker.mode.traitors) - if(tra.current) - var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") - src.client.images += I - if(src.connected_ai) - src.connected_ai.connected_robots -= src - src.connected_ai = null - if(src.mind) - if(!src.mind.special_role) - src.mind.special_role = "traitor" - ticker.mode.traitors += src.mind - - if (src.cells) - if (src.cell) - var/cellcharge = src.cell.charge/src.cell.maxcharge - switch(cellcharge) - if(0.75 to INFINITY) - src.cells.icon_state = "charge4" - if(0.5 to 0.75) - src.cells.icon_state = "charge3" - if(0.25 to 0.5) - src.cells.icon_state = "charge2" - if(0 to 0.25) - src.cells.icon_state = "charge1" - else - src.cells.icon_state = "charge0" - else - src.cells.icon_state = "charge-empty" - - if(bodytemp) - switch(src.bodytemperature) //310.055 optimal body temp - if(335 to INFINITY) - src.bodytemp.icon_state = "temp2" - if(320 to 335) - src.bodytemp.icon_state = "temp1" - if(300 to 320) - src.bodytemp.icon_state = "temp0" - if(260 to 300) - src.bodytemp.icon_state = "temp-1" - else - src.bodytemp.icon_state = "temp-2" - - - if(src.pullin) src.pullin.icon_state = "pull[src.pulling ? 1 : 0]" -//Oxygen and fire does nothing yet!! -// if (src.oxygen) src.oxygen.icon_state = "oxy[src.oxygen_alert ? 1 : 0]" -// if (src.fire) src.fire.icon_state = "fire[src.fire_alert ? 1 : 0]" - - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if ((src.blind && src.stat != 2)) - if(src.blinded) - src.blind.layer = 18 - else - src.blind.layer = 0 - if (src.disabilities & NEARSIGHTED) - src.client.screen += global_hud.vimpaired - - if (src.eye_blurry) - src.client.screen += global_hud.blurry - - if (src.druggy) - src.client.screen += global_hud.druggy - - if (src.stat != 2) - if (src.machine) - if (!( src.machine.check_eye(src) )) - src.reset_view(null) - else - if(client && !client.adminobs && !iscamera(client.eye) && !isTeleViewing(client.eye)) - reset_view(null) - - return 1 - -/mob/living/silicon/robot/proc/update_items() - if (src.client) - src.client.screen -= src.contents - for(var/obj/I in src.contents) - if(I && !(istype(I,/obj/item/weapon/cell) || istype(I,/obj/item/device/radio) || istype(I,/obj/machinery/camera) || istype(I,/obj/item/device/mmi))) - src.client.screen += I - if(src.module_state_1) - src.module_state_1:screen_loc = ui_inv1 - if(src.module_state_2) - src.module_state_2:screen_loc = ui_inv2 - if(src.module_state_3) - src.module_state_3:screen_loc = ui_inv3 - updateicon() - -/mob/living/silicon/robot/proc/process_killswitch() - if(killswitch) - killswitch_time -- - if(killswitch_time <= 0) - if(src.client) - to_chat(src, "Killswitch Activated") - killswitch = 0 - spawn(5) - gib() - -/mob/living/silicon/robot/proc/process_locks() - if(weapon_lock) - uneq_all() - weaponlock_time -- - if(weaponlock_time <= 0) - if(src.client) - to_chat(src, "Weapon Lock Timed Out!") - weapon_lock = 0 - weaponlock_time = 120 - -//Robots on fire -/mob/living/silicon/robot/handle_fire() - if(..()) - return - adjustFireLoss(3) - return - -/mob/living/silicon/robot/update_fire() - overlays -= image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") - if(on_fire) - overlays += image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") - update_icons() - return - -/mob/living/silicon/robot/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them - IgniteMob() - -//Robots on fire - -/mob/living/silicon/robot/update_canmove() - if(paralysis || stunned || weakened || locked_to || lockcharge) canmove = 0 - else canmove = 1 +/mob/living/silicon/robot/Life() + set invisibility = 0 + //set background = 1 + if(timestopped) return 0 //under effects of time magick + + if (src.monkeyizing) + return + + src.blinded = null + + //Status updates, death etc. + clamp_values() + handle_regular_status_updates() + + if(client) + handle_regular_hud_updates() + update_items() + if (src.stat != DEAD) //still using power + use_power() + process_killswitch() + process_locks() + if(module) + module.recharge_consumable(src) + update_canmove() + handle_fire() + handle_beams() + +/mob/living/silicon/robot/proc/clamp_values() + +// SetStunned(min(stunned, 30)) + SetParalysis(min(paralysis, 30)) +// SetWeakened(min(weakened, 20)) + sleeping = 0 + adjustBruteLoss(0) + adjustToxLoss(0) + adjustOxyLoss(0) + adjustFireLoss(0) + +/mob/living/silicon/robot/proc/use_power() + + + if (is_component_functioning("power cell") && cell) + if(src.cell.charge <= 0) + uneq_all() + else + if(src.module_state_1) + src.cell.use(3) + if(src.module_state_2) + src.cell.use(3) + if(src.module_state_3) + src.cell.use(3) + + for(var/V in components) + var/datum/robot_component/C = components[V] + C.consume_power() + + if(!is_component_functioning("actuator")) + Paralyse(3) + + src.stat = 0 + else + uneq_all() + src.stat = 1 + + +/mob/living/silicon/robot/proc/handle_regular_status_updates() + + + if(src.camera && !scrambledcodes) + if(src.stat == 2 || wires.IsCameraCut()) + src.camera.status = 0 + else + src.camera.status = 1 + + updatehealth() + + if(src.sleeping) + Paralyse(3) + src.sleeping-- + + if(src.resting) + Weaken(5) + + if(health <= 0 && src.stat != 2) //die only once + death() + + if (src.stat != 2) //Alive. + if (src.paralysis || src.stunned || src.weakened) //Stunned etc. + src.stat = 1 + if (src.stunned > 0) + AdjustStunned(-1) + if (src.weakened > 0) + AdjustWeakened(-1) + if (src.paralysis > 0) + AdjustParalysis(-1) + src.blinded = 1 + else + src.blinded = 0 + + else //Not stunned. + src.stat = 0 + + else //Dead. + src.blinded = 1 + src.stat = 2 + + if (src.stuttering) src.stuttering-- + + if (src.eye_blind) + src.eye_blind-- + src.blinded = 1 + + if (src.ear_deaf > 0) src.ear_deaf-- + if (src.ear_damage < 25) + src.ear_damage -= 0.05 + src.ear_damage = max(src.ear_damage, 0) + + src.density = !( src.lying ) + + if ((src.sdisabilities & BLIND)) + src.blinded = 1 + if ((src.sdisabilities & DEAF)) + src.ear_deaf = 1 + + if (src.eye_blurry > 0) + src.eye_blurry-- + src.eye_blurry = max(0, src.eye_blurry) + + if (src.druggy > 0) + src.druggy-- + src.druggy = max(0, src.druggy) + + if(!is_component_functioning("radio")) + radio.on = 0 + else + radio.on = 1 + + if(is_component_functioning("camera")) + src.blinded = 0 + else + src.blinded = 1 + + + return 1 + +/mob/living/silicon/robot/proc/handle_sensor_modes() + src.sight &= ~SEE_MOBS + src.sight &= ~SEE_TURFS + src.sight &= ~SEE_OBJS + src.sight &= ~BLIND + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + if (src.stat == DEAD) + sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else + if (M_XRAY in mutations || src.sight_mode & BORGXRAY) + sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + if ((src.sight_mode & BORGTHERM) || sensor_mode == THERMAL_VISION) + src.sight |= SEE_MOBS + src.see_in_dark = 4 + src.see_invisible = SEE_INVISIBLE_MINIMUM + if (sensor_mode == NIGHT) + see_invisible = SEE_INVISIBLE_MINIMUM + see_in_dark = 8 + if ((src.sight_mode & BORGMESON) || (sensor_mode == MESON_VISION)) + src.sight |= SEE_TURFS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + + +/mob/living/silicon/robot/proc/handle_regular_hud_updates() + handle_sensor_modes() + /*if (src.stat == 2 || M_XRAY in mutations || src.sight_mode & BORGXRAY) + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_MINIMUM + else if ((src.sight_mode & BORGMESON || sensor_mode == MESON_VISION) && src.sight_mode & BORGTHERM) + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (src.sight_mode & BORGMESON || sensor_mode == MESON_VISION) + src.sight |= SEE_TURFS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (src.sight_mode & BORGTHERM) + src.sight |= SEE_MOBS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (src.stat != 2) + src.sight &= ~SEE_MOBS + src.sight &= ~SEE_TURFS + src.sight &= ~SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO*/ + + regular_hud_updates() //Handles MED/SEC HUDs for borgs. + switch(sensor_mode) + if (SEC_HUD) + process_sec_hud(src, 1) + if (MED_HUD) + process_med_hud(src) + + /*switch(sensor_mode) + if (SEC_HUD) + process_sec_hud(src, 1) + if (MED_HUD) + process_med_hud(src)*/ + + if (src.healths) + if (src.stat != 2) + switch(health) + if(200 to INFINITY) + src.healths.icon_state = "health0" + if(150 to 200) + src.healths.icon_state = "health1" + if(100 to 150) + src.healths.icon_state = "health2" + if(50 to 100) + src.healths.icon_state = "health3" + if(0 to 50) + src.healths.icon_state = "health4" + if(config.health_threshold_dead to 0) + src.healths.icon_state = "health5" + else + src.healths.icon_state = "health6" + else + src.healths.icon_state = "health7" + + if (src.syndicate && src.client) + if(ticker.mode.name == "traitor") + for(var/datum/mind/tra in ticker.mode.traitors) + if(tra.current) + var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") + src.client.images += I + if(src.connected_ai) + src.connected_ai.connected_robots -= src + src.connected_ai = null + if(src.mind) + if(!src.mind.special_role) + src.mind.special_role = "traitor" + ticker.mode.traitors += src.mind + + if (src.cells) + if (src.cell) + var/cellcharge = src.cell.charge/src.cell.maxcharge + switch(cellcharge) + if(0.75 to INFINITY) + src.cells.icon_state = "charge4" + if(0.5 to 0.75) + src.cells.icon_state = "charge3" + if(0.25 to 0.5) + src.cells.icon_state = "charge2" + if(0 to 0.25) + src.cells.icon_state = "charge1" + else + src.cells.icon_state = "charge0" + else + src.cells.icon_state = "charge-empty" + + if(bodytemp) + switch(src.bodytemperature) //310.055 optimal body temp + if(335 to INFINITY) + src.bodytemp.icon_state = "temp2" + if(320 to 335) + src.bodytemp.icon_state = "temp1" + if(300 to 320) + src.bodytemp.icon_state = "temp0" + if(260 to 300) + src.bodytemp.icon_state = "temp-1" + else + src.bodytemp.icon_state = "temp-2" + + + if(src.pullin) src.pullin.icon_state = "pull[src.pulling ? 1 : 0]" +//Oxygen and fire does nothing yet!! +// if (src.oxygen) src.oxygen.icon_state = "oxy[src.oxygen_alert ? 1 : 0]" +// if (src.fire) src.fire.icon_state = "fire[src.fire_alert ? 1 : 0]" + + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if ((src.blind && src.stat != 2)) + if(src.blinded) + src.blind.layer = 18 + else + src.blind.layer = 0 + if (src.disabilities & NEARSIGHTED) + src.client.screen += global_hud.vimpaired + + if (src.eye_blurry) + src.client.screen += global_hud.blurry + + if (src.druggy) + src.client.screen += global_hud.druggy + + if (src.stat != 2) + if (src.machine) + if (!( src.machine.check_eye(src) )) + src.reset_view(null) + else + if(client && !client.adminobs && !iscamera(client.eye) && !isTeleViewing(client.eye)) + reset_view(null) + + return 1 + +/mob/living/silicon/robot/proc/update_items() + if (src.client) + src.client.screen -= src.contents + for(var/obj/I in src.contents) + if(I && !(istype(I,/obj/item/weapon/cell) || istype(I,/obj/item/device/radio) || istype(I,/obj/machinery/camera) || istype(I,/obj/item/device/mmi))) + src.client.screen += I + if(src.module_state_1) + src.module_state_1:screen_loc = ui_inv1 + if(src.module_state_2) + src.module_state_2:screen_loc = ui_inv2 + if(src.module_state_3) + src.module_state_3:screen_loc = ui_inv3 + updateicon() + +/mob/living/silicon/robot/proc/process_killswitch() + if(killswitch) + killswitch_time -- + if(killswitch_time <= 0) + if(src.client) + to_chat(src, "Killswitch Activated") + killswitch = 0 + spawn(5) + gib() + +/mob/living/silicon/robot/proc/process_locks() + if(weapon_lock) + uneq_all() + weaponlock_time -- + if(weaponlock_time <= 0) + if(src.client) + to_chat(src, "Weapon Lock Timed Out!") + weapon_lock = 0 + weaponlock_time = 120 + +//Robots on fire +/mob/living/silicon/robot/handle_fire() + if(..()) + return + adjustFireLoss(3) + return + +/mob/living/silicon/robot/update_fire() + overlays -= image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") + if(on_fire) + overlays += image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") + update_icons() + return + +/mob/living/silicon/robot/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them + IgniteMob() + +//Robots on fire + +/mob/living/silicon/robot/update_canmove() + if(paralysis || stunned || weakened || locked_to || lockcharge) canmove = 0 + else canmove = 1 return canmove \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index aa390939a86..54cb8e26f16 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -1,11 +1,11 @@ -/mob/living/silicon/robot/Login() - ..() - regenerate_icons() - if(isMoMMI(src)) +/mob/living/silicon/robot/Login() + ..() + regenerate_icons() + if(isMoMMI(src)) to_chat(src, "MoMMIs are not standard cyborgs, and have different laws. Review your laws carefully.") - to_chat(src, "For newer players, a simple FAQ is here. Further questions should be directed to adminhelps (F1).") + to_chat(src, "For newer players, a simple FAQ is here. Further questions should be directed to adminhelps (F1).") to_chat(src, "For cuteness' sake, using the various emotes MoMMIs have such as *beep, *ping, *buzz or *aflap isn't considered interacting. Don't use that as an excuse to get involved though, always remain neutral.") - show_laws(0) - if(mind) ticker.mode.remove_revolutionary(mind) - return + show_laws(0) + if(mind) ticker.mode.remove_revolutionary(mind) + return diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 421ba6d185f..eb759c7e672 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -1,33 +1,33 @@ -/mob/living/silicon/robot/Process_Spacemove() - if(module) - for(var/obj/item/weapon/tank/jetpack/J in module.modules) - if(J && istype(J, /obj/item/weapon/tank/jetpack)) - if(J.allow_thrust(0.01)) return 1 - if(..()) return 1 - return 0 - - //No longer needed, but I'll leave it here incase we plan to re-use it. -/mob/living/silicon/robot/movement_delay() - var/tally = 0 //Incase I need to add stuff other than "speed" later - - tally = speed - - if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) - tally-=3 // JESUS FUCKING CHRIST WHY - - if(istype(loc,/turf/simulated/floor)) - var/turf/simulated/floor/T = loc - - if(T.material=="phazon") - return -1 // Phazon floors make us go fast - - return tally+config.robot_delay - -/mob/living/silicon/robot/Move(atom/newloc) - if(..()) - if(istype(newloc, /turf/unsimulated/floor/asteroid) && istype(module, /obj/item/weapon/robot_module/miner)) - var/obj/item/weapon/storage/bag/ore/ore_bag = locate(/obj/item/weapon/storage/bag/ore) in get_all_slots() //find it in our modules - if(ore_bag) - for(var/obj/item/weapon/ore/ore in newloc.contents) - ore_bag.preattack(newloc, src, 1) //collects everything - break +/mob/living/silicon/robot/Process_Spacemove() + if(module) + for(var/obj/item/weapon/tank/jetpack/J in module.modules) + if(J && istype(J, /obj/item/weapon/tank/jetpack)) + if(J.allow_thrust(0.01)) return 1 + if(..()) return 1 + return 0 + + //No longer needed, but I'll leave it here incase we plan to re-use it. +/mob/living/silicon/robot/movement_delay() + var/tally = 0 //Incase I need to add stuff other than "speed" later + + tally = speed + + if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) + tally-=3 // JESUS FUCKING CHRIST WHY + + if(istype(loc,/turf/simulated/floor)) + var/turf/simulated/floor/T = loc + + if(T.material=="phazon") + return -1 // Phazon floors make us go fast + + return tally+config.robot_delay + +/mob/living/silicon/robot/Move(atom/newloc) + if(..()) + if(istype(newloc, /turf/unsimulated/floor/asteroid) && istype(module, /obj/item/weapon/robot_module/miner)) + var/obj/item/weapon/storage/bag/ore/ore_bag = locate(/obj/item/weapon/storage/bag/ore) in get_all_slots() //find it in our modules + if(ore_bag) + for(var/obj/item/weapon/ore/ore in newloc.contents) + ore_bag.preattack(newloc, src, 1) //collects everything + break diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 432c74a5a4f..ded739a275a 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,88 +1,88 @@ -/mob/living/silicon/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "queries, [text]"; - else if (ending == "!") - return "declares, [text]"; - - return "states, [text]"; - -/mob/living/silicon/say(var/message) - return ..(message, "R") - -/mob/living/silicon/robot/IsVocal() - return !config.silent_borg - -/mob/living/proc/robot_talk(var/message) - - - var/turf/T = get_turf(src) - log_say("[key_name(src)] (@[T.x],[T.y],[T.z] Binary: [message]") - - var/message_a = say_quote("\"[html_encode(message)]\"") - var/rendered = text("Robotic Talk, [] []",name,message_a) - - for (var/mob/S in player_list) - if(istype(S , /mob/living/silicon/ai)) - var/renderedAI = "Robotic Talk, [name] [message_a]" +/mob/living/silicon/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "queries, [text]"; + else if (ending == "!") + return "declares, [text]"; + + return "states, [text]"; + +/mob/living/silicon/say(var/message) + return ..(message, "R") + +/mob/living/silicon/robot/IsVocal() + return !config.silent_borg + +/mob/living/proc/robot_talk(var/message) + + + var/turf/T = get_turf(src) + log_say("[key_name(src)] (@[T.x],[T.y],[T.z] Binary: [message]") + + var/message_a = say_quote("\"[html_encode(message)]\"") + var/rendered = text("Robotic Talk, [] []",name,message_a) + + for (var/mob/S in player_list) + if(istype(S , /mob/living/silicon/ai)) + var/renderedAI = "Robotic Talk, [name] [message_a]" to_chat(S, renderedAI) - else if(S.binarycheck() || ((S in dead_mob_list) && !istype(S, /mob/new_player))) - handle_render(S,rendered,src) - -/mob/living/silicon/binarycheck() - return 1 - -/mob/living/silicon/lingcheck() - return 0 //Borged or AI'd lings can't speak on the ling channel. - -/mob/living/silicon/radio(var/datum/speech/speech, var/message_mode) - . = ..() - if(. != 0) - return . - if(message_mode == "robot") - if(radio) - radio.talk_into(speech) - return REDUCE_RANGE - - else if(message_mode in radiochannels) - if(radio) - radio.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - return 0 - -/mob/living/silicon/get_message_mode(message) - . = ..() - if(..() == MODE_HEADSET) - return MODE_ROBOT - else - return . - -/mob/living/silicon/handle_inherent_channels(var/datum/speech/speech, var/message_mode) - . = ..() - if(.) - return . - - if(message_mode == MODE_BINARY) - if(binarycheck()) - robot_talk(speech.message) - return 1 - return 0 - -/mob/living/silicon/treat_speech(var/datum/speech/speech, genesay = 0) - ..(speech) - speech.message_classes.Add("siliconsay") - -/mob/living/silicon/say_understands(var/atom/movable/other,var/datum/language/speaking = null) - //These only pertain to common. Languages are handled by mob/say_understands() - if (!speaking) - if(other) other = other.GetSource() - if (istype(other, /mob/living/carbon)) - return 1 - if (istype(other, /mob/living/silicon)) - return 1 - if (istype(other, /mob/living/carbon/brain)) - return 1 - if (isanimal(other)) - return 1 + else if(S.binarycheck() || ((S in dead_mob_list) && !istype(S, /mob/new_player))) + handle_render(S,rendered,src) + +/mob/living/silicon/binarycheck() + return 1 + +/mob/living/silicon/lingcheck() + return 0 //Borged or AI'd lings can't speak on the ling channel. + +/mob/living/silicon/radio(var/datum/speech/speech, var/message_mode) + . = ..() + if(. != 0) + return . + if(message_mode == "robot") + if(radio) + radio.talk_into(speech) + return REDUCE_RANGE + + else if(message_mode in radiochannels) + if(radio) + radio.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + return 0 + +/mob/living/silicon/get_message_mode(message) + . = ..() + if(..() == MODE_HEADSET) + return MODE_ROBOT + else + return . + +/mob/living/silicon/handle_inherent_channels(var/datum/speech/speech, var/message_mode) + . = ..() + if(.) + return . + + if(message_mode == MODE_BINARY) + if(binarycheck()) + robot_talk(speech.message) + return 1 + return 0 + +/mob/living/silicon/treat_speech(var/datum/speech/speech, genesay = 0) + ..(speech) + speech.message_classes.Add("siliconsay") + +/mob/living/silicon/say_understands(var/atom/movable/other,var/datum/language/speaking = null) + //These only pertain to common. Languages are handled by mob/say_understands() + if (!speaking) + if(other) other = other.GetSource() + if (istype(other, /mob/living/carbon)) + return 1 + if (istype(other, /mob/living/silicon)) + return 1 + if (istype(other, /mob/living/carbon/brain)) + return 1 + if (isanimal(other)) + return 1 return ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index ebd9f6b8c41..2cc19162935 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -1,310 +1,310 @@ -/mob/living/silicon - gender = NEUTER - voice_name = "synthesized voice" - can_butcher = 0 - var/syndicate = 0 - var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS - var/list/alarms_to_show = list() - var/list/alarms_to_clear = list() - - immune_to_ssd = 1 - - var/obj/item/device/radio/borg/radio = null //AIs dont use this but this is at the silicon level to advoid copypasta in say() - var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer - var/sensor_mode = 0 //Determines the current HUD. - #define SEC_HUD 1 //Security HUD mode - #define MED_HUD 2 //Medical HUD mode - #define MESON_VISION 3 // Engineering borg and mommis - #define NIGHT 4 // night vision - #define THERMAL_VISION 5 // combat borgs thermals - var/global/list/vision_types_list = list("Security Hud","Medical Hud", "Meson Vision", "Night Vision", "Thermal Vision") - 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/hasFullAccess() - return 1 - -/mob/living/silicon/GetAccess() - return get_all_accesses() - -/mob/living/silicon/proc/cancelAlarm() - return - -/mob/living/silicon/proc/triggerAlarm() - return - -/mob/living/silicon/proc/show_laws() - return - -/mob/living/silicon/proc/write_laws() - if(laws) - var/text = src.laws.write_laws() - return text - -/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) - to_chat(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\]" - to_chat(src, msg) - - if(alarms_to_clear.len < 3) - for(var/msg in alarms_to_clear) - to_chat(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\]" - to_chat(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 - -/mob/living/silicon/drop_item(var/obj/item/to_drop, var/atom/Target, force_drop = 0) - return 1 - -/mob/living/silicon/generate_static_overlay() - return - -/mob/living/silicon/emp_act(severity) - for(var/obj/item/stickybomb/B in src) - if(B.stuck_to) - visible_message("\the [B] stuck on \the [src] suddenly deactivates itself and falls to the ground.") - B.deactivate() - B.unstick() - - if(flags & INVULNERABLE) - return - - switch(severity) - if(1) - src.take_organ_damage(20) - Stun(rand(5,10)) - if(2) - src.take_organ_damage(10) - Stun(rand(1,5)) - flick("noise", src:flash) - to_chat(src, "*BZZZT*") - to_chat(src, "Warning: Electromagnetic pulse detected.") - ..() - -/mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0) - return - -/mob/living/silicon/IsAdvancedToolUser() - return 1 - -/mob/living/silicon/bullet_act(var/obj/item/projectile/Proj) - if(!Proj.nodamage) adjustBruteLoss(Proj.damage) - Proj.on_hit(src,2) - return 2 - -/mob/living/silicon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) - return 0//The only effect that can hit them atm is flashes and they still directly edit so this works for now -/* - if(!effect || (blocked >= 2)) return 0 - switch(effecttype) - if(STUN) - stunned = max(stunned,(effect/(blocked+1))) - if(WEAKEN) - weakened = max(weakened,(effect/(blocked+1))) - if(PARALYZE) - paralysis = max(paralysis,(effect/(blocked+1))) - if(IRRADIATE) - radiation += min((effect - (effect*getarmor(null, "rad"))), 0)//Rads auto check armor - if(STUTTER) - stuttering = max(stuttering,(effect/(blocked+1))) - if(EYE_BLUR) - eye_blurry = max(eye_blurry,(effect/(blocked+1))) - if(DROWSY) - drowsyness = max(drowsyness,(effect/(blocked+1))) - updatehealth() - return 1*/ - -/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai) - if(!istype(bot) || !istype(ai)) - return 0 - if (bot.connected_ai == ai) - return 1 - return 0 - -/mob/living/silicon/proc/system_integrity() - return round((health / maxHealth) * 100) - -// this function shows the health of a silicon in the Status panel -/mob/living/silicon/proc/show_system_integrity() - if(stat == CONSCIOUS) - stat(null, text("System integrity: [system_integrity()]%")) - else - stat(null, text("Systems nonfunctional")) - -// This is a pure virtual function, it should be overwritten by all subclasses -/mob/living/silicon/proc/show_malf_ai() - return 0 - -// this function displays the station time in the status panel -/mob/living/silicon/proc/show_station_time() - stat(null, "Station Time: [worldtime2text()]") - - -// this function displays the shuttles ETA in the status panel if the shuttle has been called -/mob/living/silicon/proc/show_emergency_shuttle_eta() - if(emergency_shuttle.online && emergency_shuttle.location < 2) - var/timeleft = emergency_shuttle.timeleft() - if (timeleft) - stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") - - -// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms -/mob/living/silicon/Stat() - ..() - if(statpanel("Status")) - show_station_time() - show_emergency_shuttle_eta() - show_system_integrity() - show_malf_ai() - -// this function displays the stations manifest in a separate window -/mob/living/silicon/proc/show_station_manifest() - var/dat - dat += "

    Crew Manifest

    " - if(data_core) - dat += data_core.get_manifest(1) // make it monochrome - dat += "
    " - src << browse(dat, "window=airoster") - onclose(src, "airoster") - -/mob/living/silicon/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1.0) - if(istype(source, /obj/machinery/containment_field)) - var/damage = shock_damage * siemens_coeff * 0.75 // take reduced damage - - if(damage <= 0) - damage = 0 - - if(take_overall_damage(0, damage, "[source]") == 0) // godmode - return 0 - - visible_message( \ - "[src] was shocked by the [source]!", \ - "Energy pulse detected, system damaged!", \ - "You hear a heavy electrical crack." \ - ) - - if(prob(20)) - Stun(2) - - var/datum/effect/effect/system/spark_spread/SparkSpread = new - SparkSpread.set_up(5, 1, loc) - SparkSpread.start() - - return damage - - return 0 - -/mob/living/silicon/assess_threat() //Secbots will not target silicons! - return -10 - -/mob/living/silicon/put_in_hand_check(var/obj/item/W) - return 0 - -/mob/living/silicon/can_speak_lang(datum/language/speaking) - return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language - -/mob/living/silicon/add_language(var/language, var/can_speak=1) - if (..(language) && can_speak) - speech_synthesizer_langs |= (all_languages[language]) - return 1 - -/mob/living/silicon/remove_language(var/rem_language) - ..(rem_language) - - for (var/datum/language/L in speech_synthesizer_langs) - if (L.name == rem_language) - speech_synthesizer_langs -= L - -/mob/living/silicon/check_languages() - set name = "Check Known Languages" - set category = "IC" - set src = usr - - var/dat = "Known Languages

    " - - if(default_language) - dat += "Current default language: [default_language] - reset

    " - - for(var/datum/language/L in languages) - var/default_str - if(L == default_language) - default_str = " - default - reset" - else - default_str = " - set default" - - var/synth = (L in speech_synthesizer_langs) - dat += "[L.name] (:[L.key])[synth ? default_str : null]
    Speech Synthesizer: [synth ? "YES" : "NOT SUPPORTED"]
    [L.desc]

    " - - src << browse(dat, "window=checklanguage") - return - -/mob/living/silicon/dexterity_check() - return 1 - -/mob/living/silicon/html_mob_check(var/typepath) - for(var/atom/movable/AM in html_machines) - if(typepath == AM.type) - if(max(abs(AM.x-src.x),abs(AM.y-src.y)) <= client.view) - return 1 - return 0 - -/mob/living/silicon/spook() - to_chat(src, "[pick(boo_phrases_silicon)]") +/mob/living/silicon + gender = NEUTER + voice_name = "synthesized voice" + can_butcher = 0 + var/syndicate = 0 + var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS + var/list/alarms_to_show = list() + var/list/alarms_to_clear = list() + + immune_to_ssd = 1 + + var/obj/item/device/radio/borg/radio = null //AIs dont use this but this is at the silicon level to advoid copypasta in say() + var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer + var/sensor_mode = 0 //Determines the current HUD. + #define SEC_HUD 1 //Security HUD mode + #define MED_HUD 2 //Medical HUD mode + #define MESON_VISION 3 // Engineering borg and mommis + #define NIGHT 4 // night vision + #define THERMAL_VISION 5 // combat borgs thermals + var/global/list/vision_types_list = list("Security Hud","Medical Hud", "Meson Vision", "Night Vision", "Thermal Vision") + 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/hasFullAccess() + return 1 + +/mob/living/silicon/GetAccess() + return get_all_accesses() + +/mob/living/silicon/proc/cancelAlarm() + return + +/mob/living/silicon/proc/triggerAlarm() + return + +/mob/living/silicon/proc/show_laws() + return + +/mob/living/silicon/proc/write_laws() + if(laws) + var/text = src.laws.write_laws() + return text + +/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) + to_chat(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\]" + to_chat(src, msg) + + if(alarms_to_clear.len < 3) + for(var/msg in alarms_to_clear) + to_chat(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\]" + to_chat(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 + +/mob/living/silicon/drop_item(var/obj/item/to_drop, var/atom/Target, force_drop = 0) + return 1 + +/mob/living/silicon/generate_static_overlay() + return + +/mob/living/silicon/emp_act(severity) + for(var/obj/item/stickybomb/B in src) + if(B.stuck_to) + visible_message("\the [B] stuck on \the [src] suddenly deactivates itself and falls to the ground.") + B.deactivate() + B.unstick() + + if(flags & INVULNERABLE) + return + + switch(severity) + if(1) + src.take_organ_damage(20) + Stun(rand(5,10)) + if(2) + src.take_organ_damage(10) + Stun(rand(1,5)) + flick("noise", src:flash) + to_chat(src, "*BZZZT*") + to_chat(src, "Warning: Electromagnetic pulse detected.") + ..() + +/mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0) + return + +/mob/living/silicon/IsAdvancedToolUser() + return 1 + +/mob/living/silicon/bullet_act(var/obj/item/projectile/Proj) + if(!Proj.nodamage) adjustBruteLoss(Proj.damage) + Proj.on_hit(src,2) + return 2 + +/mob/living/silicon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) + return 0//The only effect that can hit them atm is flashes and they still directly edit so this works for now +/* + if(!effect || (blocked >= 2)) return 0 + switch(effecttype) + if(STUN) + stunned = max(stunned,(effect/(blocked+1))) + if(WEAKEN) + weakened = max(weakened,(effect/(blocked+1))) + if(PARALYZE) + paralysis = max(paralysis,(effect/(blocked+1))) + if(IRRADIATE) + radiation += min((effect - (effect*getarmor(null, "rad"))), 0)//Rads auto check armor + if(STUTTER) + stuttering = max(stuttering,(effect/(blocked+1))) + if(EYE_BLUR) + eye_blurry = max(eye_blurry,(effect/(blocked+1))) + if(DROWSY) + drowsyness = max(drowsyness,(effect/(blocked+1))) + updatehealth() + return 1*/ + +/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai) + if(!istype(bot) || !istype(ai)) + return 0 + if (bot.connected_ai == ai) + return 1 + return 0 + +/mob/living/silicon/proc/system_integrity() + return round((health / maxHealth) * 100) + +// this function shows the health of a silicon in the Status panel +/mob/living/silicon/proc/show_system_integrity() + if(stat == CONSCIOUS) + stat(null, text("System integrity: [system_integrity()]%")) + else + stat(null, text("Systems nonfunctional")) + +// This is a pure virtual function, it should be overwritten by all subclasses +/mob/living/silicon/proc/show_malf_ai() + return 0 + +// this function displays the station time in the status panel +/mob/living/silicon/proc/show_station_time() + stat(null, "Station Time: [worldtime2text()]") + + +// this function displays the shuttles ETA in the status panel if the shuttle has been called +/mob/living/silicon/proc/show_emergency_shuttle_eta() + if(emergency_shuttle.online && emergency_shuttle.location < 2) + var/timeleft = emergency_shuttle.timeleft() + if (timeleft) + stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") + + +// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms +/mob/living/silicon/Stat() + ..() + if(statpanel("Status")) + show_station_time() + show_emergency_shuttle_eta() + show_system_integrity() + show_malf_ai() + +// this function displays the stations manifest in a separate window +/mob/living/silicon/proc/show_station_manifest() + var/dat + dat += "

    Crew Manifest

    " + if(data_core) + dat += data_core.get_manifest(1) // make it monochrome + dat += "
    " + src << browse(dat, "window=airoster") + onclose(src, "airoster") + +/mob/living/silicon/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1.0) + if(istype(source, /obj/machinery/containment_field)) + var/damage = shock_damage * siemens_coeff * 0.75 // take reduced damage + + if(damage <= 0) + damage = 0 + + if(take_overall_damage(0, damage, "[source]") == 0) // godmode + return 0 + + visible_message( \ + "[src] was shocked by the [source]!", \ + "Energy pulse detected, system damaged!", \ + "You hear a heavy electrical crack." \ + ) + + if(prob(20)) + Stun(2) + + var/datum/effect/effect/system/spark_spread/SparkSpread = new + SparkSpread.set_up(5, 1, loc) + SparkSpread.start() + + return damage + + return 0 + +/mob/living/silicon/assess_threat() //Secbots will not target silicons! + return -10 + +/mob/living/silicon/put_in_hand_check(var/obj/item/W) + return 0 + +/mob/living/silicon/can_speak_lang(datum/language/speaking) + return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language + +/mob/living/silicon/add_language(var/language, var/can_speak=1) + if (..(language) && can_speak) + speech_synthesizer_langs |= (all_languages[language]) + return 1 + +/mob/living/silicon/remove_language(var/rem_language) + ..(rem_language) + + for (var/datum/language/L in speech_synthesizer_langs) + if (L.name == rem_language) + speech_synthesizer_langs -= L + +/mob/living/silicon/check_languages() + set name = "Check Known Languages" + set category = "IC" + set src = usr + + var/dat = "Known Languages

    " + + if(default_language) + dat += "Current default language: [default_language] - reset

    " + + for(var/datum/language/L in languages) + var/default_str + if(L == default_language) + default_str = " - default - reset" + else + default_str = " - set default" + + var/synth = (L in speech_synthesizer_langs) + dat += "[L.name] (:[L.key])[synth ? default_str : null]
    Speech Synthesizer: [synth ? "YES" : "NOT SUPPORTED"]
    [L.desc]

    " + + src << browse(dat, "window=checklanguage") + return + +/mob/living/silicon/dexterity_check() + return 1 + +/mob/living/silicon/html_mob_check(var/typepath) + for(var/atom/movable/AM in html_machines) + if(typepath == AM.type) + if(max(abs(AM.x-src.x),abs(AM.y-src.y)) <= client.view) + return 1 + return 0 + +/mob/living/silicon/spook() + to_chat(src, "[pick(boo_phrases_silicon)]") diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 812f294d42b..07cbfa3781d 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -1,485 +1,485 @@ - -/mob/living/simple_animal/construct - name = "Construct" - real_name = "Construct" - desc = "" - speak_emote = list("hisses") - emote_hear = list("wails","screeches") - response_help = "thinks better of touching" - response_disarm = "flails at" - response_harm = "punches" - icon_dead = "shade_dead" - speed = -1 - a_intent = I_HURT - stop_automated_movement = 1 - status_flags = CANPUSH - attack_sound = 'sound/weapons/spiderlunge.ogg' - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - show_stat_health = 0 - faction = "cult" - supernatural = 1 - flying = 1 - treadmill_speed = 0 //It floats! - var/nullblock = 0 - - mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY - mob_push_flags = ALLMOBS - - meat_type = /obj/item/weapon/ectoplasm - - var/list/construct_spells = list() - -/mob/living/simple_animal/construct/construct_chat_check(setting) - if(!mind) return - - if(mind in ticker.mode.cult) - return 1 - -/mob/living/simple_animal/construct/handle_inherent_channels(var/datum/speech/speech, var/message_mode) - if(..()) - return 1 - if(message_mode == MODE_HEADSET && construct_chat_check(0)) - var/turf/T = get_turf(src) - log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Cult channel: [html_encode(speech.message)]") - for(var/mob/M in mob_list) - if(M.construct_chat_check(2) /*receiving check*/ || ((M in dead_mob_list) && !istype(M, /mob/new_player))) + +/mob/living/simple_animal/construct + name = "Construct" + real_name = "Construct" + desc = "" + speak_emote = list("hisses") + emote_hear = list("wails","screeches") + response_help = "thinks better of touching" + response_disarm = "flails at" + response_harm = "punches" + icon_dead = "shade_dead" + speed = -1 + a_intent = I_HURT + stop_automated_movement = 1 + status_flags = CANPUSH + attack_sound = 'sound/weapons/spiderlunge.ogg' + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + show_stat_health = 0 + faction = "cult" + supernatural = 1 + flying = 1 + treadmill_speed = 0 //It floats! + var/nullblock = 0 + + mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY + mob_push_flags = ALLMOBS + + meat_type = /obj/item/weapon/ectoplasm + + var/list/construct_spells = list() + +/mob/living/simple_animal/construct/construct_chat_check(setting) + if(!mind) return + + if(mind in ticker.mode.cult) + return 1 + +/mob/living/simple_animal/construct/handle_inherent_channels(var/datum/speech/speech, var/message_mode) + if(..()) + return 1 + if(message_mode == MODE_HEADSET && construct_chat_check(0)) + var/turf/T = get_turf(src) + log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Cult channel: [html_encode(speech.message)]") + for(var/mob/M in mob_list) + if(M.construct_chat_check(2) /*receiving check*/ || ((M in dead_mob_list) && !istype(M, /mob/new_player))) to_chat(M, "[src.name]: [html_encode(speech.message)]") - return 1 - -/mob/living/simple_animal/construct/gib() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - dead_mob_list -= src - - qdel(src) - -/mob/living/simple_animal/construct/cultify() - return - -/mob/living/simple_animal/construct/New() - ..() - name = text("[initial(name)] ([rand(1, 1000)])") - real_name = name - add_language(LANGUAGE_CULT) - default_language = all_languages[LANGUAGE_CULT] - for(var/spell in construct_spells) - src.add_spell(new spell, "const_spell_ready") - updateicon() - -/mob/living/simple_animal/construct/Die() - ..() - for(var/i=0;i<3;i++) - new /obj/item/weapon/ectoplasm (src.loc) - for(var/mob/M in viewers(src, null)) - if((M.client && !( M.blinded ))) - M.show_message("[src] collapses in a shattered heap. ") - ghostize() - qdel (src) - return - -/mob/living/simple_animal/construct/examine(mob/user) - var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" - if (src.health < src.maxHealth) - msg += "" - if (src.health >= src.maxHealth/2) - msg += "It looks slightly dented.\n" - else - msg += "It looks severely dented!\n" - msg += "" - msg += "*---------*" - + return 1 + +/mob/living/simple_animal/construct/gib() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + dead_mob_list -= src + + qdel(src) + +/mob/living/simple_animal/construct/cultify() + return + +/mob/living/simple_animal/construct/New() + ..() + name = text("[initial(name)] ([rand(1, 1000)])") + real_name = name + add_language(LANGUAGE_CULT) + default_language = all_languages[LANGUAGE_CULT] + for(var/spell in construct_spells) + src.add_spell(new spell, "const_spell_ready") + updateicon() + +/mob/living/simple_animal/construct/Die() + ..() + for(var/i=0;i<3;i++) + new /obj/item/weapon/ectoplasm (src.loc) + for(var/mob/M in viewers(src, null)) + if((M.client && !( M.blinded ))) + M.show_message("[src] collapses in a shattered heap. ") + ghostize() + qdel (src) + return + +/mob/living/simple_animal/construct/examine(mob/user) + var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" + if (src.health < src.maxHealth) + msg += "" + if (src.health >= src.maxHealth/2) + msg += "It looks slightly dented.\n" + else + msg += "It looks severely dented!\n" + msg += "" + msg += "*---------*" + to_chat(user, msg) - - -/mob/living/simple_animal/construct/attack_animal(mob/living/simple_animal/M as mob) - if(istype(M, /mob/living/simple_animal/construct/builder)) - if(src.health >= src.maxHealth) + + +/mob/living/simple_animal/construct/attack_animal(mob/living/simple_animal/M as mob) + if(istype(M, /mob/living/simple_animal/construct/builder)) + if(src.health >= src.maxHealth) to_chat(M, "[src] has nothing to mend.") - return - health = min(maxHealth, health + 5) // Constraining health to maxHealth - M.visible_message("[M] mends some of \the [src]'s wounds.","You mend some of \the [src]'s wounds.") - else - M.attack_log += text("\[[time_stamp()]\] [M.attacktext] [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been [M.attacktext] by [M.name] ([M.ckey])") - if(M.melee_damage_upper <= 0) - M.emote("[M.friendly] \the [src]") - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - M.visible_message("\The [M] [M.attacktext] \the [src]!") - add_logs(M, src, "attacked", admin=1) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) - -/mob/living/simple_animal/construct/attackby(var/obj/item/O as obj, var/mob/user as mob) - user.delayNextAttack(8) - if(O.force) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - if(istype(O,/obj/item/weapon/nullrod)) - damage *= 2 - purge = 3 - adjustBruteLoss(damage) - user.visible_message("[src] has been attacked with [O] by [user]. ") - else + return + health = min(maxHealth, health + 5) // Constraining health to maxHealth + M.visible_message("[M] mends some of \the [src]'s wounds.","You mend some of \the [src]'s wounds.") + else + M.attack_log += text("\[[time_stamp()]\] [M.attacktext] [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been [M.attacktext] by [M.name] ([M.ckey])") + if(M.melee_damage_upper <= 0) + M.emote("[M.friendly] \the [src]") + else + if(M.attack_sound) + playsound(loc, M.attack_sound, 50, 1, 1) + M.visible_message("\The [M] [M.attacktext] \the [src]!") + add_logs(M, src, "attacked", admin=1) + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + adjustBruteLoss(damage) + +/mob/living/simple_animal/construct/attackby(var/obj/item/O as obj, var/mob/user as mob) + user.delayNextAttack(8) + if(O.force) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + if(istype(O,/obj/item/weapon/nullrod)) + damage *= 2 + purge = 3 + adjustBruteLoss(damage) + user.visible_message("[src] has been attacked with [O] by [user]. ") + else to_chat(usr, "This weapon is ineffective, it does no damage.") - user.visible_message("[user] gently taps [src] with [O]. ") - - - -/////////////////Juggernaut/////////////// - - - -/mob/living/simple_animal/construct/armoured - name = "Juggernaut" - real_name = "Juggernaut" - desc = "A possessed suit of armour driven by the will of the restless dead" - icon = 'icons/mob/mob.dmi' - icon_state = "behemoth" - icon_living = "behemoth" - maxHealth = 250 - health = 250 - response_harm = "harmlessly punches" - harm_intent_damage = 0 - melee_damage_lower = 30 - melee_damage_upper = 30 - attacktext = "smashes their armoured gauntlet into" - speed = 3 - environment_smash = 2 - attack_sound = 'sound/weapons/heavysmash.ogg' - status_flags = 0 - construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) - -/mob/living/simple_animal/construct/armoured/attackby(var/obj/item/O as obj, var/mob/user as mob) - user.delayNextAttack(8) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[src] has been attacked with [O] by [user]. ") - else - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[O] bounces harmlessly off of [src]. ") - else + user.visible_message("[user] gently taps [src] with [O]. ") + + + +/////////////////Juggernaut/////////////// + + + +/mob/living/simple_animal/construct/armoured + name = "Juggernaut" + real_name = "Juggernaut" + desc = "A possessed suit of armour driven by the will of the restless dead" + icon = 'icons/mob/mob.dmi' + icon_state = "behemoth" + icon_living = "behemoth" + maxHealth = 250 + health = 250 + response_harm = "harmlessly punches" + harm_intent_damage = 0 + melee_damage_lower = 30 + melee_damage_upper = 30 + attacktext = "smashes their armoured gauntlet into" + speed = 3 + environment_smash = 2 + attack_sound = 'sound/weapons/heavysmash.ogg' + status_flags = 0 + construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) + +/mob/living/simple_animal/construct/armoured/attackby(var/obj/item/O as obj, var/mob/user as mob) + user.delayNextAttack(8) + if(O.force) + if(O.force >= 11) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[src] has been attacked with [O] by [user]. ") + else + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[O] bounces harmlessly off of [src]. ") + else to_chat(usr, "This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[user] gently taps [src] with [O]. ") - - -/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P) - if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) - var/reflectchance = 80 - round(P.damage/3) - if(prob(reflectchance)) - adjustBruteLoss(P.damage * 0.5) - visible_message("The [P.name] gets reflected by [src]'s shell!", \ - "The [P.name] gets reflected by [src]'s shell!") - - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.original = locate(new_x, new_y, P.z) - P.starting = curloc - P.current = curloc - P.firer = src - P.yo = new_y - curloc.y - P.xo = new_x - curloc.x - - return -1 // complete projectile permutation - - return (..(P)) - - - -////////////////////////Wraith///////////////////////////////////////////// - - - -/mob/living/simple_animal/construct/wraith - name = "Wraith" - real_name = "Wraith" - desc = "A wicked bladed shell contraption piloted by a bound spirit" - icon = 'icons/mob/mob.dmi' - icon_state = "floating" - icon_living = "floating" - maxHealth = 75 - health = 75 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "slashes" - speed = -1 - environment_smash = 1 - see_in_dark = 7 - attack_sound = 'sound/weapons/rapidslice.ogg' - construct_spells = list(/spell/targeted/ethereal_jaunt/shift) - - - -/////////////////////////////Artificer///////////////////////// - - - -/mob/living/simple_animal/construct/builder - name = "Artificer" - real_name = "Artificer" - desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies" - icon = 'icons/mob/mob.dmi' - icon_state = "artificer" - icon_living = "artificer" - maxHealth = 50 - health = 50 - response_harm = "viciously beats" - harm_intent_damage = 5 - melee_damage_lower = 5 - melee_damage_upper = 5 - attacktext = "rams" - speed = 0 - environment_smash = 1 - attack_sound = 'sound/weapons/rapidslice.ogg' - construct_spells = list(/spell/aoe_turf/conjure/construct/lesser, - /spell/aoe_turf/conjure/wall, - /spell/aoe_turf/conjure/floor, - /spell/aoe_turf/conjure/soulstone, - /spell/aoe_turf/conjure/pylon, - ///obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser - ) - - -/////////////////////////////Behemoth///////////////////////// - - -/mob/living/simple_animal/construct/behemoth - name = "Behemoth" - real_name = "Behemoth" - desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal." - icon = 'icons/mob/mob.dmi' - icon_state = "behemoth" - icon_living = "behemoth" - maxHealth = 750 - health = 750 - speak_emote = list("rumbles") - response_harm = "harmlessly punches" - harm_intent_damage = 0 - melee_damage_lower = 50 - melee_damage_upper = 50 - attacktext = "brutally crushes" - speed = 5 - environment_smash = 2 - attack_sound = 'sound/weapons/heavysmash.ogg' - var/energy = 0 - var/max_energy = 1000 - construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) - -/mob/living/simple_animal/construct/behemoth/attackby(var/obj/item/O as obj, var/mob/user as mob) - user.delayNextAttack(8) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[src] has been attacked with [O] by [user]. ") - else - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[O] bounces harmlessly off of [src]. ") - else + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[user] gently taps [src] with [O]. ") + + +/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P) + if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) + var/reflectchance = 80 - round(P.damage/3) + if(prob(reflectchance)) + adjustBruteLoss(P.damage * 0.5) + visible_message("The [P.name] gets reflected by [src]'s shell!", \ + "The [P.name] gets reflected by [src]'s shell!") + + // Find a turf near or on the original location to bounce to + if(P.starting) + var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) + var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3) + var/turf/curloc = get_turf(src) + + // redirect the projectile + P.original = locate(new_x, new_y, P.z) + P.starting = curloc + P.current = curloc + P.firer = src + P.yo = new_y - curloc.y + P.xo = new_x - curloc.x + + return -1 // complete projectile permutation + + return (..(P)) + + + +////////////////////////Wraith///////////////////////////////////////////// + + + +/mob/living/simple_animal/construct/wraith + name = "Wraith" + real_name = "Wraith" + desc = "A wicked bladed shell contraption piloted by a bound spirit" + icon = 'icons/mob/mob.dmi' + icon_state = "floating" + icon_living = "floating" + maxHealth = 75 + health = 75 + melee_damage_lower = 25 + melee_damage_upper = 25 + attacktext = "slashes" + speed = -1 + environment_smash = 1 + see_in_dark = 7 + attack_sound = 'sound/weapons/rapidslice.ogg' + construct_spells = list(/spell/targeted/ethereal_jaunt/shift) + + + +/////////////////////////////Artificer///////////////////////// + + + +/mob/living/simple_animal/construct/builder + name = "Artificer" + real_name = "Artificer" + desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies" + icon = 'icons/mob/mob.dmi' + icon_state = "artificer" + icon_living = "artificer" + maxHealth = 50 + health = 50 + response_harm = "viciously beats" + harm_intent_damage = 5 + melee_damage_lower = 5 + melee_damage_upper = 5 + attacktext = "rams" + speed = 0 + environment_smash = 1 + attack_sound = 'sound/weapons/rapidslice.ogg' + construct_spells = list(/spell/aoe_turf/conjure/construct/lesser, + /spell/aoe_turf/conjure/wall, + /spell/aoe_turf/conjure/floor, + /spell/aoe_turf/conjure/soulstone, + /spell/aoe_turf/conjure/pylon, + ///obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser + ) + + +/////////////////////////////Behemoth///////////////////////// + + +/mob/living/simple_animal/construct/behemoth + name = "Behemoth" + real_name = "Behemoth" + desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal." + icon = 'icons/mob/mob.dmi' + icon_state = "behemoth" + icon_living = "behemoth" + maxHealth = 750 + health = 750 + speak_emote = list("rumbles") + response_harm = "harmlessly punches" + harm_intent_damage = 0 + melee_damage_lower = 50 + melee_damage_upper = 50 + attacktext = "brutally crushes" + speed = 5 + environment_smash = 2 + attack_sound = 'sound/weapons/heavysmash.ogg' + var/energy = 0 + var/max_energy = 1000 + construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) + +/mob/living/simple_animal/construct/behemoth/attackby(var/obj/item/O as obj, var/mob/user as mob) + user.delayNextAttack(8) + if(O.force) + if(O.force >= 11) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[src] has been attacked with [O] by [user]. ") + else + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[O] bounces harmlessly off of [src]. ") + else to_chat(usr, "This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[user] gently taps [src] with [O]. ") - - -////////////////////////Harvester//////////////////////////////// - - - -/mob/living/simple_animal/construct/harvester - name = "Harvester" - real_name = "Harvester" - desc = "The promised reward of the livings who follow narsie. Obtained by offering their bodies to the geometer of blood" - icon = 'icons/mob/mob.dmi' - icon_state = "harvester" - icon_living = "harvester" - maxHealth = 150 - health = 150 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "violently stabs" - speed = -1 - environment_smash = 1 - see_in_dark = 7 - attack_sound = 'sound/weapons/pierce.ogg' - - construct_spells = list( - /spell/targeted/harvest, - /spell/aoe_turf/knock/harvester, - /spell/rune_write - ) - -/mob/living/simple_animal/construct/harvester/New() - ..() - sight |= SEE_MOBS - -////////////////Glow////////////////// -/mob/living/simple_animal/construct/proc/updateicon() - overlays = 0 - var/overlay_layer = LIGHTING_LAYER + 1 - if(layer != MOB_LAYER) - overlay_layer=TURF_LAYER+0.2 - - overlays += image(icon,"glow-[icon_state]",overlay_layer) - -////////////////Powers////////////////// - - -/* -/client/proc/summon_cultist() - set category = "Behemoth" - set name = "Summon Cultist (300)" - set desc = "Teleport a cultist to your location" - if (istype(usr,/mob/living/simple_animal/constructbehemoth)) - - if(usr.energy<300) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[user] gently taps [src] with [O]. ") + + +////////////////////////Harvester//////////////////////////////// + + + +/mob/living/simple_animal/construct/harvester + name = "Harvester" + real_name = "Harvester" + desc = "The promised reward of the livings who follow narsie. Obtained by offering their bodies to the geometer of blood" + icon = 'icons/mob/mob.dmi' + icon_state = "harvester" + icon_living = "harvester" + maxHealth = 150 + health = 150 + melee_damage_lower = 25 + melee_damage_upper = 25 + attacktext = "violently stabs" + speed = -1 + environment_smash = 1 + see_in_dark = 7 + attack_sound = 'sound/weapons/pierce.ogg' + + construct_spells = list( + /spell/targeted/harvest, + /spell/aoe_turf/knock/harvester, + /spell/rune_write + ) + +/mob/living/simple_animal/construct/harvester/New() + ..() + sight |= SEE_MOBS + +////////////////Glow////////////////// +/mob/living/simple_animal/construct/proc/updateicon() + overlays = 0 + var/overlay_layer = LIGHTING_LAYER + 1 + if(layer != MOB_LAYER) + overlay_layer=TURF_LAYER+0.2 + + overlays += image(icon,"glow-[icon_state]",overlay_layer) + +////////////////Powers////////////////// + + +/* +/client/proc/summon_cultist() + set category = "Behemoth" + set name = "Summon Cultist (300)" + set desc = "Teleport a cultist to your location" + if (istype(usr,/mob/living/simple_animal/constructbehemoth)) + + if(usr.energy<300) to_chat(usr, "You do not have enough power stored!") - return - - if(usr.stat) - return - - usr.energy -= 300 - var/list/mob/living/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living)) - cultists+=H.current - var/mob/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - usr) - if(!cultist) - return - if (cultist == usr) //just to be sure. - return - cultist.loc = usr.loc - usr.visible_message("[cultist] appears in a flash of red light as [usr] glows with power")*/ - -////////////////HUD////////////////////// - -/mob/living/simple_animal/construct/Life() - if(timestopped) return 0 //under effects of time magick - - . = ..() - if(.) - if(fire) - if(fire_alert) fire.icon_state = "fire1" - else fire.icon_state = "fire0" - if(pullin) - if(pulling) pullin.icon_state = "pull1" - else pullin.icon_state = "pull0" - - if(purged) - if(purge > 0) purged.icon_state = "purge1" - else purged.icon_state = "purge0" - - silence_spells(purge) - -/mob/living/simple_animal/construct/armoured/Life() - if(timestopped) return 0 //under effects of time magick - - ..() - if(healths) - switch(health) - if(250 to INFINITY) healths.icon_state = "juggernaut_health0" - if(208 to 249) healths.icon_state = "juggernaut_health1" - if(167 to 207) healths.icon_state = "juggernaut_health2" - if(125 to 166) healths.icon_state = "juggernaut_health3" - if(84 to 124) healths.icon_state = "juggernaut_health4" - if(42 to 83) healths.icon_state = "juggernaut_health5" - if(1 to 41) healths.icon_state = "juggernaut_health6" - else healths.icon_state = "juggernaut_health7" - - -/mob/living/simple_animal/construct/behemoth/Life() - if(timestopped) return 0 //under effects of time magick - - ..() - if(healths) - switch(health) - if(750 to INFINITY) healths.icon_state = "juggernaut_health0" - if(625 to 749) healths.icon_state = "juggernaut_health1" - if(500 to 624) healths.icon_state = "juggernaut_health2" - if(375 to 499) healths.icon_state = "juggernaut_health3" - if(250 to 374) healths.icon_state = "juggernaut_health4" - if(125 to 249) healths.icon_state = "juggernaut_health5" - if(1 to 124) healths.icon_state = "juggernaut_health6" - else healths.icon_state = "juggernaut_health7" - -/mob/living/simple_animal/construct/builder/Life() - if(timestopped) return 0 //under effects of time magick - - ..() - if(healths) - switch(health) - if(50 to INFINITY) healths.icon_state = "artificer_health0" - if(42 to 49) healths.icon_state = "artificer_health1" - if(34 to 41) healths.icon_state = "artificer_health2" - if(26 to 33) healths.icon_state = "artificer_health3" - if(18 to 25) healths.icon_state = "artificer_health4" - if(10 to 17) healths.icon_state = "artificer_health5" - if(1 to 9) healths.icon_state = "artificer_health6" - else healths.icon_state = "artificer_health7" - - - -/mob/living/simple_animal/construct/wraith/Life() - if(timestopped) return 0 //under effects of time magick - - ..() - if(healths) - switch(health) - if(75 to INFINITY) healths.icon_state = "wraith_health0" - if(62 to 74) healths.icon_state = "wraith_health1" - if(50 to 61) healths.icon_state = "wraith_health2" - if(37 to 49) healths.icon_state = "wraith_health3" - if(25 to 36) healths.icon_state = "wraith_health4" - if(12 to 24) healths.icon_state = "wraith_health5" - if(1 to 11) healths.icon_state = "wraith_health6" - else healths.icon_state = "wraith_health7" - - -/mob/living/simple_animal/construct/harvester/Life() - if(timestopped) return 0 //under effects of time magick - - ..() - if(healths) - switch(health) - if(150 to INFINITY) healths.icon_state = "harvester_health0" - if(125 to 149) healths.icon_state = "harvester_health1" - if(100 to 124) healths.icon_state = "harvester_health2" - if(75 to 99) healths.icon_state = "harvester_health3" - if(50 to 74) healths.icon_state = "harvester_health4" - if(25 to 49) healths.icon_state = "harvester_health5" - if(1 to 24) healths.icon_state = "harvester_health6" - else healths.icon_state = "harvester_health7" + return + + if(usr.stat) + return + + usr.energy -= 300 + var/list/mob/living/cultists = new + for(var/datum/mind/H in ticker.mode.cult) + if (istype(H.current,/mob/living)) + cultists+=H.current + var/mob/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - usr) + if(!cultist) + return + if (cultist == usr) //just to be sure. + return + cultist.loc = usr.loc + usr.visible_message("[cultist] appears in a flash of red light as [usr] glows with power")*/ + +////////////////HUD////////////////////// + +/mob/living/simple_animal/construct/Life() + if(timestopped) return 0 //under effects of time magick + + . = ..() + if(.) + if(fire) + if(fire_alert) fire.icon_state = "fire1" + else fire.icon_state = "fire0" + if(pullin) + if(pulling) pullin.icon_state = "pull1" + else pullin.icon_state = "pull0" + + if(purged) + if(purge > 0) purged.icon_state = "purge1" + else purged.icon_state = "purge0" + + silence_spells(purge) + +/mob/living/simple_animal/construct/armoured/Life() + if(timestopped) return 0 //under effects of time magick + + ..() + if(healths) + switch(health) + if(250 to INFINITY) healths.icon_state = "juggernaut_health0" + if(208 to 249) healths.icon_state = "juggernaut_health1" + if(167 to 207) healths.icon_state = "juggernaut_health2" + if(125 to 166) healths.icon_state = "juggernaut_health3" + if(84 to 124) healths.icon_state = "juggernaut_health4" + if(42 to 83) healths.icon_state = "juggernaut_health5" + if(1 to 41) healths.icon_state = "juggernaut_health6" + else healths.icon_state = "juggernaut_health7" + + +/mob/living/simple_animal/construct/behemoth/Life() + if(timestopped) return 0 //under effects of time magick + + ..() + if(healths) + switch(health) + if(750 to INFINITY) healths.icon_state = "juggernaut_health0" + if(625 to 749) healths.icon_state = "juggernaut_health1" + if(500 to 624) healths.icon_state = "juggernaut_health2" + if(375 to 499) healths.icon_state = "juggernaut_health3" + if(250 to 374) healths.icon_state = "juggernaut_health4" + if(125 to 249) healths.icon_state = "juggernaut_health5" + if(1 to 124) healths.icon_state = "juggernaut_health6" + else healths.icon_state = "juggernaut_health7" + +/mob/living/simple_animal/construct/builder/Life() + if(timestopped) return 0 //under effects of time magick + + ..() + if(healths) + switch(health) + if(50 to INFINITY) healths.icon_state = "artificer_health0" + if(42 to 49) healths.icon_state = "artificer_health1" + if(34 to 41) healths.icon_state = "artificer_health2" + if(26 to 33) healths.icon_state = "artificer_health3" + if(18 to 25) healths.icon_state = "artificer_health4" + if(10 to 17) healths.icon_state = "artificer_health5" + if(1 to 9) healths.icon_state = "artificer_health6" + else healths.icon_state = "artificer_health7" + + + +/mob/living/simple_animal/construct/wraith/Life() + if(timestopped) return 0 //under effects of time magick + + ..() + if(healths) + switch(health) + if(75 to INFINITY) healths.icon_state = "wraith_health0" + if(62 to 74) healths.icon_state = "wraith_health1" + if(50 to 61) healths.icon_state = "wraith_health2" + if(37 to 49) healths.icon_state = "wraith_health3" + if(25 to 36) healths.icon_state = "wraith_health4" + if(12 to 24) healths.icon_state = "wraith_health5" + if(1 to 11) healths.icon_state = "wraith_health6" + else healths.icon_state = "wraith_health7" + + +/mob/living/simple_animal/construct/harvester/Life() + if(timestopped) return 0 //under effects of time magick + + ..() + if(healths) + switch(health) + if(150 to INFINITY) healths.icon_state = "harvester_health0" + if(125 to 149) healths.icon_state = "harvester_health1" + if(100 to 124) healths.icon_state = "harvester_health2" + if(75 to 99) healths.icon_state = "harvester_health3" + if(50 to 74) healths.icon_state = "harvester_health4" + if(25 to 49) healths.icon_state = "harvester_health5" + if(1 to 24) healths.icon_state = "harvester_health6" + else healths.icon_state = "harvester_health7" diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 3e3ecfb4703..c26522b6e39 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -1,122 +1,122 @@ -//Cat -/mob/living/simple_animal/cat - name = "cat" - - desc = "Kitty!!" - icon_state = "cat2" - icon_living = "cat2" - icon_dead = "cat2_dead" - gender = MALE - size = SIZE_SMALL - speak = list("Meow!", "Esp!", "Purr!", "HSSSSS") - speak_emote = list("purrs", "meows") - emote_hear = list("meows", "mews") - emote_see = list("shakes its head", "shivers") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - - can_breed = 1 - species_type = /mob/living/simple_animal/cat - childtype = /mob/living/simple_animal/cat/kitten - holder_type = /obj/item/weapon/holder/animal/cat - - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - min_oxy = 16 // Require atleast 16kPA oxygen - minbodytemp = 223 // Below -50 Degrees Celcius - maxbodytemp = 323 // Above 50 Degrees Celcius - var/turns_since_scan = 0 - var/mob/living/simple_animal/mouse/movement_target=null - -//RUNTIME IS ALIVE! SQUEEEEEEEE~ -/mob/living/simple_animal/cat/Runtime - name = "Runtime" - desc = "GCAT" - icon_state = "cat" - icon_living = "cat" - icon_dead = "cat_dead" - gender = FEMALE - -/mob/living/simple_animal/cat/Life() - if(timestopped) return 0 //under effects of time magick - - //MICE! - if((src.loc) && isturf(src.loc)) - if(!stat && !resting && !locked_to) - for(var/mob/living/simple_animal/mouse/M in view(1,src)) - if(!M.stat) - M.splat() - emote(pick("splats the [M]!","toys with the [M]","worries the [M]")) - movement_target = null - stop_automated_movement = 0 - break - - ..() - - for(var/mob/living/simple_animal/mouse/snack in oview(src, 3)) - if(prob(15)) - emote(pick("hisses and spits!","mrowls fiercely!","eyes [snack] hungrily.")) - break - - if(!stat && !resting && !locked_to) - turns_since_scan++ - if(turns_since_scan > 5) - walk_to(src,0) - turns_since_scan = 0 - if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) - movement_target = null - stop_automated_movement = 0 - if( !movement_target || !(movement_target.loc in oview(src, 3)) ) - movement_target = null - stop_automated_movement = 0 - for(var/mob/living/simple_animal/mouse/snack in oview(src,3)) - if(isturf(snack.loc) && !snack.stat) - movement_target = snack - break - if(movement_target) - stop_automated_movement = 1 - walk_to(src,movement_target,0,3) - -/mob/living/simple_animal/cat/Proc - name = "Proc" - -/mob/living/simple_animal/cat/salem - name = "Salem" - desc = "Meow." - icon_state = "salem" - icon_living= "salem" - icon_dead= "salem_dead" - gender = FEMALE - -/mob/living/simple_animal/cat/kitten - name = "kitten" - - desc = "D'aaawwww" - icon_state = "kitten" - icon_living = "kitten" - icon_dead = "kitten_dead" - gender = NEUTER - size = SIZE_TINY - -/mob/living/simple_animal/cat/snek - name = "snake" - - desc = "sssSSSSsss" - icon_state = "snek" - icon_living = "snek" - icon_dead = "snek_dead" - gender = NEUTER - speak = list("SssssSSSS.", "Slirp.","HSSSSS") - speak_emote = list("hisses") - emote_hear = list("hisses") - emote_see = list("slithers") - - species_type = /mob/living/simple_animal/cat/snek - butchering_drops = null - childtype = null - holder_type = null - -/mob/living/simple_animal/cat/snek/corpus +//Cat +/mob/living/simple_animal/cat + name = "cat" + + desc = "Kitty!!" + icon_state = "cat2" + icon_living = "cat2" + icon_dead = "cat2_dead" + gender = MALE + size = SIZE_SMALL + speak = list("Meow!", "Esp!", "Purr!", "HSSSSS") + speak_emote = list("purrs", "meows") + emote_hear = list("meows", "mews") + emote_see = list("shakes its head", "shivers") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + + can_breed = 1 + species_type = /mob/living/simple_animal/cat + childtype = /mob/living/simple_animal/cat/kitten + holder_type = /obj/item/weapon/holder/animal/cat + + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" + min_oxy = 16 // Require atleast 16kPA oxygen + minbodytemp = 223 // Below -50 Degrees Celcius + maxbodytemp = 323 // Above 50 Degrees Celcius + var/turns_since_scan = 0 + var/mob/living/simple_animal/mouse/movement_target=null + +//RUNTIME IS ALIVE! SQUEEEEEEEE~ +/mob/living/simple_animal/cat/Runtime + name = "Runtime" + desc = "GCAT" + icon_state = "cat" + icon_living = "cat" + icon_dead = "cat_dead" + gender = FEMALE + +/mob/living/simple_animal/cat/Life() + if(timestopped) return 0 //under effects of time magick + + //MICE! + if((src.loc) && isturf(src.loc)) + if(!stat && !resting && !locked_to) + for(var/mob/living/simple_animal/mouse/M in view(1,src)) + if(!M.stat) + M.splat() + emote(pick("splats the [M]!","toys with the [M]","worries the [M]")) + movement_target = null + stop_automated_movement = 0 + break + + ..() + + for(var/mob/living/simple_animal/mouse/snack in oview(src, 3)) + if(prob(15)) + emote(pick("hisses and spits!","mrowls fiercely!","eyes [snack] hungrily.")) + break + + if(!stat && !resting && !locked_to) + turns_since_scan++ + if(turns_since_scan > 5) + walk_to(src,0) + turns_since_scan = 0 + if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) + movement_target = null + stop_automated_movement = 0 + if( !movement_target || !(movement_target.loc in oview(src, 3)) ) + movement_target = null + stop_automated_movement = 0 + for(var/mob/living/simple_animal/mouse/snack in oview(src,3)) + if(isturf(snack.loc) && !snack.stat) + movement_target = snack + break + if(movement_target) + stop_automated_movement = 1 + walk_to(src,movement_target,0,3) + +/mob/living/simple_animal/cat/Proc + name = "Proc" + +/mob/living/simple_animal/cat/salem + name = "Salem" + desc = "Meow." + icon_state = "salem" + icon_living= "salem" + icon_dead= "salem_dead" + gender = FEMALE + +/mob/living/simple_animal/cat/kitten + name = "kitten" + + desc = "D'aaawwww" + icon_state = "kitten" + icon_living = "kitten" + icon_dead = "kitten_dead" + gender = NEUTER + size = SIZE_TINY + +/mob/living/simple_animal/cat/snek + name = "snake" + + desc = "sssSSSSsss" + icon_state = "snek" + icon_living = "snek" + icon_dead = "snek_dead" + gender = NEUTER + speak = list("SssssSSSS.", "Slirp.","HSSSSS") + speak_emote = list("hisses") + emote_hear = list("hisses") + emote_see = list("slithers") + + species_type = /mob/living/simple_animal/cat/snek + butchering_drops = null + childtype = null + holder_type = null + +/mob/living/simple_animal/cat/snek/corpus name = "Corpus" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index e1413c318ae..fb6973867f8 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -1,570 +1,570 @@ -//Corgi -/mob/living/simple_animal/corgi - name = "\improper corgi" - real_name = "corgi" - - desc = "It's a corgi." - icon_state = "corgi" - icon_living = "corgi" - icon_dead = "corgi_dead" - health = 30 - maxHealth = 30 - gender = MALE - speak = list("YAP", "Woof!", "Bark!", "AUUUUUU") - speak_emote = list("barks", "woofs") - emote_hear = list("barks", "woofs", "yaps","pants") - emote_see = list("shakes its head", "shivers") - speak_chance = 1 - turns_per_move = 10 - - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi - holder_type = /obj/item/weapon/holder/animal/corgi - - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" - see_in_dark = 5 - - childtype = /mob/living/simple_animal/corgi/puppy - species_type = /mob/living/simple_animal/corgi - can_breed = 1 - size = SIZE_SMALL - - var/obj/item/inventory_head - var/obj/item/inventory_back - var/facehugger - var/list/spin_emotes = list("dances around","chases its tail") - -/mob/living/simple_animal/corgi/Life() - if(timestopped) return 0 //under effects of time magick - spinaroo(spin_emotes) - - . = ..() - if(.) - if(fire) - if(fire_alert) fire.icon_state = "fire[fire_alert]" //fire_alert is either 0 if no alert, 1 for heat and 2 for cold. - else fire.icon_state = "fire0" - if(pullin) - if(pulling) pullin.icon_state = "pull1" - else pullin.icon_state = "pull0" - if(oxygen) - if(oxygen_alert) oxygen.icon_state = "oxy1" - else oxygen.icon_state = "oxy0" - if(toxin) - if(toxins_alert) toxin.icon_state = "tox1" - else toxin.icon_state = "tox0" - - if (healths) - switch(health) - if(30 to INFINITY) healths.icon_state = "health0" - if(26 to 29) healths.icon_state = "health1" - if(21 to 25) healths.icon_state = "health2" - if(16 to 20) healths.icon_state = "health3" - if(11 to 15) healths.icon_state = "health4" - if(6 to 10) healths.icon_state = "health5" - if(1 to 5) healths.icon_state = "health6" - else healths.icon_state = "health7" - //regenerate_icons() - - -/mob/living/simple_animal/corgi/show_inv(mob/user as mob) - user.set_machine(src) - if(user.stat) return - - var/dat = "
    Inventory of [name]

    " - if(inventory_head) - dat += "
    Head: [inventory_head] (Remove)" - else - dat += "
    Head: Nothing" - if(inventory_back) - dat += "
    Back: [inventory_back] (Remove)" - else - dat += "
    Back: Nothing" - - user << browse(dat, text("window=mob[];size=325x500", real_name)) - onclose(user, "mob[real_name]") - return - -/mob/living/simple_animal/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/newspaper)) - if(!stat) - user.visible_message("[user] baps [name] on the nose with the rolled up [O]") - spawn(0) - emote("whines") - for(var/i in list(1,2,4,8,4,2,1,2)) - dir = i - sleep(1) - else if(inventory_head && inventory_back) - //helmet and armor = 100% protection - if( istype(inventory_head,/obj/item/clothing/head/helmet) && istype(inventory_back,/obj/item/clothing/suit/armor) ) - if( O.force ) - to_chat(usr, "[src] is wearing too much armor. You can't cause \him any damage.") - for (var/mob/M in viewers(src, null)) - M.show_message("[user] hits [src] with [O], however [src] is too armored.") - else - to_chat(usr, "[src] is wearing too much armor. You can't reach \his skin.") - for (var/mob/M in viewers(src, null)) - M.show_message("[user] gently taps [src] with [O]. ") - if(health>0 && prob(15)) - emote("looks at [user] with [pick("an amused","an annoyed","a confused","a resentful", "a happy", "an excited")] expression") - return - ..() - -/mob/living/simple_animal/corgi/Topic(href, href_list) - if(usr.stat) return - - //Removing from inventory - if(href_list["remove_inv"]) - if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) - return - var/remove_from = href_list["remove_inv"] - switch(remove_from) - if("head") - if(inventory_head) - name = real_name - desc = initial(desc) - speak = list("YAP", "Woof!", "Bark!", "AUUUUUU") - speak_emote = list("barks", "woofs") - emote_hear = list("barks", "woofs", "yaps","pants") - emote_see = list("shakes its head", "shivers") - min_oxy = initial(min_oxy) - minbodytemp = initial(minbodytemp) - maxbodytemp = initial(maxbodytemp) - set_light(0) - inventory_head.forceMove(src.loc) - inventory_head = null - regenerate_icons() - else - to_chat(usr, "There is nothing to remove from its [remove_from].") - return - if("back") - if(inventory_back) - inventory_back.loc = src.loc - inventory_back = null - regenerate_icons() - else - to_chat(usr, "There is nothing to remove from its [remove_from].") - return - - show_inv(usr) - - //Adding things to inventory - else if(href_list["add_inv"]) - if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) - return - - var/add_to = href_list["add_inv"] - if(!usr.get_active_hand()) - to_chat(usr, "You have nothing in your hand to put on its [add_to].") - return - switch(add_to) - if("head") - place_on_head(usr.get_active_hand()) - - if("back") - if(inventory_back) - to_chat(usr, "It's already wearing something.") - return - else - var/obj/item/item_to_add = usr.get_active_hand() - - if(!item_to_add) - usr.visible_message("[usr] pets [src]","You rest your hand on [src]'s back for a moment.") - return - if(istype(item_to_add,/obj/item/weapon/plastique)) // last thing he ever wears, I guess - item_to_add.afterattack(src,usr,1) - return - - //The objects that corgis can wear on their backs. - var/list/allowed_types = list( - /obj/item/clothing/suit/armor/vest, - /obj/item/device/radio, - /obj/item/device/radio/off, - /obj/item/clothing/suit/cardborg, - /obj/item/weapon/tank/oxygen, - /obj/item/weapon/tank/air, - /obj/item/weapon/extinguisher, - /obj/item/clothing/suit/space/rig - ) - - if( ! ( item_to_add.type in allowed_types ) ) - to_chat(usr, "You set [item_to_add] on [src]'s back, but \he shakes it off!") - usr.drop_item(item_to_add, get_turf(src)) - - if(prob(25)) - step_rand(item_to_add) - if (ckey == null) - for(var/i in list(1,2,4,8,4,8,4,dir)) - dir = i - sleep(1) - return - - usr.drop_item(item_to_add, src, force_drop = 1) - src.inventory_back = item_to_add - regenerate_icons() - - show_inv(usr) - else - ..() - -//Corgis are supposed to be simpler, so only a select few objects can actually be put -//to be compatible with them. The objects are below. -//Many hats added, Some will probably be removed, just want to see which ones are popular. -/mob/living/simple_animal/corgi/proc/place_on_head(obj/item/item_to_add) - - - if(istype(item_to_add,/obj/item/weapon/plastique)) // last thing he ever wears, I guess - item_to_add.afterattack(src,usr,1) - return - - if(inventory_head) - if(usr) to_chat(usr, "You can't put more than one hat on [src]!") - return - if(!item_to_add) - usr.visible_message("[usr] pets [src]","You rest your hand on [src]'s head for a moment.") - return - - - var/valid = 0 - - //Various hats and items (worn on his head) change Ian's behaviour. His attributes are reset when a hat is removed. - switch(item_to_add.type) - if( /obj/item/clothing/glasses/sunglasses, /obj/item/clothing/head/that, /obj/item/clothing/head/collectable/paper, - /obj/item/clothing/head/hardhat, /obj/item/clothing/head/collectable/hardhat,/obj/item/clothing/head/hardhat/white, /obj/item/weapon/paper ) - valid = 1 - - if(/obj/item/clothing/head/helmet) - name = "Sergeant [real_name]" - desc = "The ever-loyal, the ever-vigilant." - valid = 1 - - if(/obj/item/clothing/head/chefhat, /obj/item/clothing/head/collectable/chef) - name = "Sous chef [real_name]" - desc = "Your food will be taste-tested. All of it." - valid = 1 - - if(/obj/item/clothing/head/caphat, /obj/item/clothing/head/collectable/captain) - name = "Captain [real_name]" - desc = "Probably better than the last captain." - valid = 1 - - if(/obj/item/clothing/head/kitty, /obj/item/clothing/head/collectable/kitty) - name = "Runtime" - emote_see = list("coughs up a furball", "stretches") - emote_hear = list("purrs") - speak = list("Purrr", "Meow!", "MAOOOOOW!", "HISSSSS", "MEEEEEEW") - desc = "It's a cute little kitty-cat! ... wait ... what the hell?" - valid = 1 - - if(/obj/item/clothing/head/rabbitears, /obj/item/clothing/head/collectable/rabbitears) - name = "Hoppy" - emote_see = list("twitches its nose", "hops around a bit") - desc = "This is Hoppy. It's a corgi-...urmm... bunny rabbit" - valid = 1 - - if(/obj/item/clothing/head/beret, /obj/item/clothing/head/collectable/beret) - name = "Yann" - desc = "Mon dieu! C'est un chien!" - speak = list("le woof!", "le bark!", "JAPPE!!") - emote_see = list("cowers in fear", "surrenders", "plays dead","looks as though there is a wall in front of him") - valid = 1 - - if(/obj/item/clothing/head/det_hat) - name = "Detective [real_name]" - desc = "[name] sees through your lies..." - emote_see = list("investigates the area","sniffs around for clues","searches for scooby snacks") - valid = 1 - - if(/obj/item/clothing/head/nursehat) - name = "Nurse [real_name]" - desc = "[name] needs 100cc of beef jerky...STAT!" - valid = 1 - - if(/obj/item/clothing/head/pirate, /obj/item/clothing/head/collectable/pirate) - name = "[pick("Ol'","Scurvy","Black","Rum","Gammy","Bloody","Gangrene","Death","Long-John")] [pick("kibble","leg","beard","tooth","poop-deck","Threepwood","Le Chuck","corsair","Silver","Crusoe")]" - desc = "Yaarghh!! Thar' be a scurvy dog!" - emote_see = list("hunts for treasure","stares coldly...","gnashes his tiny corgi teeth") - emote_hear = list("growls ferociously", "snarls") - speak = list("Arrrrgh!!","Grrrrrr!") - valid = 1 - - if(/obj/item/clothing/head/ushanka) - name = "[pick("Comrade","Commissar","Glorious Leader")] [real_name]" - desc = "A follower of Karl Barx." - emote_see = list("contemplates the failings of the capitalist economic model", "ponders the pros and cons of vangaurdism") - valid = 1 - - if(/obj/item/clothing/head/collectable/police) - name = "Officer [real_name]" - emote_see = list("drools","looks for donuts") - desc = "Stop right there criminal scum!" - valid = 1 - - if(/obj/item/clothing/head/wizard/fake, /obj/item/clothing/head/wizard, /obj/item/clothing/head/collectable/wizard) - name = "Grandwizard [real_name]" - speak = list("YAP", "Woof!", "Bark!", "AUUUUUU", "EI NATH!") - valid = 1 - - if(/obj/item/clothing/head/cardborg) - name = "Borgi" - speak = list("Ping!","Beep!","Woof!") - emote_see = list("goes rogue", "sniffs out non-humans") - desc = "Result of robotics budget cuts." - valid = 1 - - if(/obj/item/weapon/bedsheet) - name = "\improper Ghost" - speak = list("WoooOOOooo~","AUUUUUUUUUUUUUUUUUU") - emote_see = list("stumbles around", "shivers") - emote_hear = list("howls","groans") - desc = "Spooky!" - valid = 1 - - if(/obj/item/clothing/head/helmet/space/santahat) - name = "Santa's Corgi Helper" - emote_hear = list("barks christmas songs", "yaps merrily") - emote_see = list("looks for presents", "checks his list") - desc = "He's very fond of milk and cookies." - valid = 1 - - if(/obj/item/clothing/head/soft) - name = "Corgi Tech [real_name]" - desc = "The reason your yellow gloves have chew-marks." - emote_see = list("Orders emitter crates and goes full blown cargonia.") - valid = 1 - - if(/obj/item/clothing/head/fedora) - name = "Autistic [real_name]" - desc = "His paws seem to be covered in what looks like Cheezy Honker dust." - emote_hear = list("barks ironicly", "makes you cringe") - emote_see = list("unsheathes katana", "tips fedora"/*,"Posts on 4chan" hue*/) - valid = 1 - - if(/obj/item/clothing/head/fez) - name = "Doctor Whom" - desc = "A time-dog from the planet barkifray." - emote_hear = list("barks cleverly.") - emote_see = list("fiddles around with a sonic-bone", "builds something amazing- thats a poop. He just pooped.") - valid = 1 - - if(/obj/item/clothing/head/helmet/space/rig) - name = "Spessman [real_name]" - desc = "Boldly going where no Corgi has gone before!" - valid = 1 - min_oxy = 0 - minbodytemp = 0 - maxbodytemp = 999 - - /* - if(/obj/item/clothing/head/hardhat/reindeer) - name = "[real_name] the red-nosed Corgi" - emote_hear = list("lights the way", "illuminates", "yaps") - desc = "He has a very shiny nose." - SetLuminosity(1) - valid = 1 - */ - - if(valid) - if(usr) - usr.visible_message("[usr] puts [item_to_add] on [real_name]'s head. [src] looks at [usr] and barks once.", - "You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags \his tail once and barks.", - "You hear a friendly-sounding bark.") - usr.drop_item(item_to_add, src, force_drop = 1) - else - item_to_add.loc = src - src.inventory_head = item_to_add - regenerate_icons() - - else - to_chat(usr, "You set [item_to_add] on [src]'s head, but \he shakes it off!") - usr.drop_item(item_to_add, src.loc) - - if(prob(25)) - step_rand(item_to_add) - if (ckey == null) - for(var/i in list(1,2,4,8,4,8,4,dir)) - dir = i - sleep(1) - - return valid - -/mob/living/simple_animal/corgi/proc/spinaroo(var/list/emotes) - if(!stat && !resting && !locked_to) - if(prob(1)) - if (ckey == null) - emote(pick(emotes)) - spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2)) - dir = i - sleep(1) - - -//IAN! SQUEEEEEEEEE~ -/mob/living/simple_animal/corgi/Ian - name = "Ian" - real_name = "Ian" //Intended to hold the name without altering it. - gender = MALE - desc = "It's a corgi." - var/turns_since_scan = 0 - var/obj/movement_target - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" - spin_emotes = list("dances around","chases his tail") - -/mob/living/simple_animal/corgi/Ian/Life() - if(timestopped) return 0 //under effects of time magick - - ..() - - //Feeding, chasing food, FOOOOODDDD - if(!stat && !resting && !locked_to && (ckey == null)) - turns_since_scan++ - if(turns_since_scan > 5) - turns_since_scan = 0 - if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) - movement_target = null - stop_automated_movement = 0 - if( !movement_target || !(movement_target.loc in oview(src, 3)) ) - movement_target = null - stop_automated_movement = 0 - for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3)) - if(isturf(S.loc) || ishuman(S.loc)) - movement_target = S - break - if(movement_target) - spawn(0) - stop_automated_movement = 1 - step_to(src,movement_target,1) - sleep(3) - step_to(src,movement_target,1) - sleep(3) - step_to(src,movement_target,1) - - if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds - if (movement_target.loc.x < src.x) - dir = WEST - else if (movement_target.loc.x > src.x) - dir = EAST - else if (movement_target.loc.y < src.y) - dir = SOUTH - else if (movement_target.loc.y > src.y) - dir = NORTH - else - dir = SOUTH - - if(isturf(movement_target.loc) && src.Adjacent(movement_target)) - movement_target.attack_animal(src) - else if(ishuman(movement_target.loc) ) - if(prob(20)) - emote("stares at [movement_target.loc]'s [movement_target] with a sad puppy-face") -//PC stuff-Sieve - -/mob/living/simple_animal/corgi/regenerate_icons() - overlays = list() - - if(inventory_head) - var/head_icon_state = inventory_head.icon_state - if(health <= 0) - head_icon_state += "2" - - var/icon/head_icon = image('icons/mob/corgi_head.dmi',head_icon_state) - if(head_icon) - overlays += head_icon - - if(inventory_back) - var/back_icon_state = inventory_back.icon_state - if(health <= 0) - back_icon_state += "2" - - var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state) - if(back_icon) - overlays += back_icon - - if(facehugger) - if(istype(src, /mob/living/simple_animal/corgi/puppy)) - overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy") - else - overlays += image('icons/mob/mask.dmi',"facehugger_corgi") - - return - - - -/mob/living/simple_animal/corgi/puppy - name = "\improper corgi puppy" - real_name = "corgi" - desc = "It's a corgi puppy." - icon_state = "puppy" - icon_living = "puppy" - icon_dead = "puppy_dead" - size = SIZE_TINY - -//puppies cannot wear anything. -/mob/living/simple_animal/corgi/puppy/Topic(href, href_list) - if(href_list["remove_inv"] || href_list["add_inv"]) - to_chat(usr, "You can't fit this on [src]") - return - ..() - - -//LISA! SQUEEEEEEEEE~ -/mob/living/simple_animal/corgi/Lisa - name = "Lisa" - real_name = "Lisa" - gender = FEMALE - desc = "It's a corgi with a cute pink bow." - icon_state = "lisa" - icon_living = "lisa" - icon_dead = "lisa_dead" - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" - var/turns_since_scan = 0 - var/puppies = 0 - spin_emotes = list("dances around","chases her of a tail") - -//Lisa already has a cute bow! -/mob/living/simple_animal/corgi/Lisa/Topic(href, href_list) - if(href_list["remove_inv"] || href_list["add_inv"]) - to_chat(usr, "[src] already has a cute bow!") - return - ..() - -/mob/living/simple_animal/corgi/attack_hand(mob/living/carbon/human/M) - . = ..() - switch(M.a_intent) - if(I_HELP) wuv(1,M) - if(I_HURT) wuv(-1,M) - -/mob/living/simple_animal/corgi/proc/wuv(change, mob/M) - if(change) - if(change > 0) - if(M && !isUnconscious()) // Added check to see if this mob (the corgi) is dead to fix issue 2454 - flick_overlay(image('icons/mob/animal.dmi',src,"heart-ani2",MOB_LAYER+1), list(M.client), 20) - emote("yaps happily") - else - if(M && !isUnconscious()) // Same check here, even though emote checks it as well (poor form to check it only in the help case) - emote("growls") - - -//Sasha isn't even a corgi you dummy! -/mob/living/simple_animal/corgi/sasha - name = "Sasha" - real_name = "Sasha" - gender = FEMALE - desc = "It's a doberman, how intimidating!" - icon_state = "doby" - icon_living = "doby" - icon_dead = "doby_dead" - spin_emotes = list("prances around","chases her nub of a tail") - - species_type = /mob/living/simple_animal/corgi/sasha - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal - -//Sasha can't wear hats! -/mob/living/simple_animal/corgi/sasha/Topic(href, href_list) - if(href_list["remove_inv"] || href_list["add_inv"]) - to_chat(usr, "[src] won't wear that!") - return - ..() +//Corgi +/mob/living/simple_animal/corgi + name = "\improper corgi" + real_name = "corgi" + + desc = "It's a corgi." + icon_state = "corgi" + icon_living = "corgi" + icon_dead = "corgi_dead" + health = 30 + maxHealth = 30 + gender = MALE + speak = list("YAP", "Woof!", "Bark!", "AUUUUUU") + speak_emote = list("barks", "woofs") + emote_hear = list("barks", "woofs", "yaps","pants") + emote_see = list("shakes its head", "shivers") + speak_chance = 1 + turns_per_move = 10 + + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal/corgi + holder_type = /obj/item/weapon/holder/animal/corgi + + response_help = "pets" + response_disarm = "bops" + response_harm = "kicks" + see_in_dark = 5 + + childtype = /mob/living/simple_animal/corgi/puppy + species_type = /mob/living/simple_animal/corgi + can_breed = 1 + size = SIZE_SMALL + + var/obj/item/inventory_head + var/obj/item/inventory_back + var/facehugger + var/list/spin_emotes = list("dances around","chases its tail") + +/mob/living/simple_animal/corgi/Life() + if(timestopped) return 0 //under effects of time magick + spinaroo(spin_emotes) + + . = ..() + if(.) + if(fire) + if(fire_alert) fire.icon_state = "fire[fire_alert]" //fire_alert is either 0 if no alert, 1 for heat and 2 for cold. + else fire.icon_state = "fire0" + if(pullin) + if(pulling) pullin.icon_state = "pull1" + else pullin.icon_state = "pull0" + if(oxygen) + if(oxygen_alert) oxygen.icon_state = "oxy1" + else oxygen.icon_state = "oxy0" + if(toxin) + if(toxins_alert) toxin.icon_state = "tox1" + else toxin.icon_state = "tox0" + + if (healths) + switch(health) + if(30 to INFINITY) healths.icon_state = "health0" + if(26 to 29) healths.icon_state = "health1" + if(21 to 25) healths.icon_state = "health2" + if(16 to 20) healths.icon_state = "health3" + if(11 to 15) healths.icon_state = "health4" + if(6 to 10) healths.icon_state = "health5" + if(1 to 5) healths.icon_state = "health6" + else healths.icon_state = "health7" + //regenerate_icons() + + +/mob/living/simple_animal/corgi/show_inv(mob/user as mob) + user.set_machine(src) + if(user.stat) return + + var/dat = "

    Inventory of [name]

    " + if(inventory_head) + dat += "
    Head: [inventory_head] (Remove)" + else + dat += "
    Head: Nothing" + if(inventory_back) + dat += "
    Back: [inventory_back] (Remove)" + else + dat += "
    Back: Nothing" + + user << browse(dat, text("window=mob[];size=325x500", real_name)) + onclose(user, "mob[real_name]") + return + +/mob/living/simple_animal/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/newspaper)) + if(!stat) + user.visible_message("[user] baps [name] on the nose with the rolled up [O]") + spawn(0) + emote("whines") + for(var/i in list(1,2,4,8,4,2,1,2)) + dir = i + sleep(1) + else if(inventory_head && inventory_back) + //helmet and armor = 100% protection + if( istype(inventory_head,/obj/item/clothing/head/helmet) && istype(inventory_back,/obj/item/clothing/suit/armor) ) + if( O.force ) + to_chat(usr, "[src] is wearing too much armor. You can't cause \him any damage.") + for (var/mob/M in viewers(src, null)) + M.show_message("[user] hits [src] with [O], however [src] is too armored.") + else + to_chat(usr, "[src] is wearing too much armor. You can't reach \his skin.") + for (var/mob/M in viewers(src, null)) + M.show_message("[user] gently taps [src] with [O]. ") + if(health>0 && prob(15)) + emote("looks at [user] with [pick("an amused","an annoyed","a confused","a resentful", "a happy", "an excited")] expression") + return + ..() + +/mob/living/simple_animal/corgi/Topic(href, href_list) + if(usr.stat) return + + //Removing from inventory + if(href_list["remove_inv"]) + if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + var/remove_from = href_list["remove_inv"] + switch(remove_from) + if("head") + if(inventory_head) + name = real_name + desc = initial(desc) + speak = list("YAP", "Woof!", "Bark!", "AUUUUUU") + speak_emote = list("barks", "woofs") + emote_hear = list("barks", "woofs", "yaps","pants") + emote_see = list("shakes its head", "shivers") + min_oxy = initial(min_oxy) + minbodytemp = initial(minbodytemp) + maxbodytemp = initial(maxbodytemp) + set_light(0) + inventory_head.forceMove(src.loc) + inventory_head = null + regenerate_icons() + else + to_chat(usr, "There is nothing to remove from its [remove_from].") + return + if("back") + if(inventory_back) + inventory_back.loc = src.loc + inventory_back = null + regenerate_icons() + else + to_chat(usr, "There is nothing to remove from its [remove_from].") + return + + show_inv(usr) + + //Adding things to inventory + else if(href_list["add_inv"]) + if(!Adjacent(usr) || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + + var/add_to = href_list["add_inv"] + if(!usr.get_active_hand()) + to_chat(usr, "You have nothing in your hand to put on its [add_to].") + return + switch(add_to) + if("head") + place_on_head(usr.get_active_hand()) + + if("back") + if(inventory_back) + to_chat(usr, "It's already wearing something.") + return + else + var/obj/item/item_to_add = usr.get_active_hand() + + if(!item_to_add) + usr.visible_message("[usr] pets [src]","You rest your hand on [src]'s back for a moment.") + return + if(istype(item_to_add,/obj/item/weapon/plastique)) // last thing he ever wears, I guess + item_to_add.afterattack(src,usr,1) + return + + //The objects that corgis can wear on their backs. + var/list/allowed_types = list( + /obj/item/clothing/suit/armor/vest, + /obj/item/device/radio, + /obj/item/device/radio/off, + /obj/item/clothing/suit/cardborg, + /obj/item/weapon/tank/oxygen, + /obj/item/weapon/tank/air, + /obj/item/weapon/extinguisher, + /obj/item/clothing/suit/space/rig + ) + + if( ! ( item_to_add.type in allowed_types ) ) + to_chat(usr, "You set [item_to_add] on [src]'s back, but \he shakes it off!") + usr.drop_item(item_to_add, get_turf(src)) + + if(prob(25)) + step_rand(item_to_add) + if (ckey == null) + for(var/i in list(1,2,4,8,4,8,4,dir)) + dir = i + sleep(1) + return + + usr.drop_item(item_to_add, src, force_drop = 1) + src.inventory_back = item_to_add + regenerate_icons() + + show_inv(usr) + else + ..() + +//Corgis are supposed to be simpler, so only a select few objects can actually be put +//to be compatible with them. The objects are below. +//Many hats added, Some will probably be removed, just want to see which ones are popular. +/mob/living/simple_animal/corgi/proc/place_on_head(obj/item/item_to_add) + + + if(istype(item_to_add,/obj/item/weapon/plastique)) // last thing he ever wears, I guess + item_to_add.afterattack(src,usr,1) + return + + if(inventory_head) + if(usr) to_chat(usr, "You can't put more than one hat on [src]!") + return + if(!item_to_add) + usr.visible_message("[usr] pets [src]","You rest your hand on [src]'s head for a moment.") + return + + + var/valid = 0 + + //Various hats and items (worn on his head) change Ian's behaviour. His attributes are reset when a hat is removed. + switch(item_to_add.type) + if( /obj/item/clothing/glasses/sunglasses, /obj/item/clothing/head/that, /obj/item/clothing/head/collectable/paper, + /obj/item/clothing/head/hardhat, /obj/item/clothing/head/collectable/hardhat,/obj/item/clothing/head/hardhat/white, /obj/item/weapon/paper ) + valid = 1 + + if(/obj/item/clothing/head/helmet) + name = "Sergeant [real_name]" + desc = "The ever-loyal, the ever-vigilant." + valid = 1 + + if(/obj/item/clothing/head/chefhat, /obj/item/clothing/head/collectable/chef) + name = "Sous chef [real_name]" + desc = "Your food will be taste-tested. All of it." + valid = 1 + + if(/obj/item/clothing/head/caphat, /obj/item/clothing/head/collectable/captain) + name = "Captain [real_name]" + desc = "Probably better than the last captain." + valid = 1 + + if(/obj/item/clothing/head/kitty, /obj/item/clothing/head/collectable/kitty) + name = "Runtime" + emote_see = list("coughs up a furball", "stretches") + emote_hear = list("purrs") + speak = list("Purrr", "Meow!", "MAOOOOOW!", "HISSSSS", "MEEEEEEW") + desc = "It's a cute little kitty-cat! ... wait ... what the hell?" + valid = 1 + + if(/obj/item/clothing/head/rabbitears, /obj/item/clothing/head/collectable/rabbitears) + name = "Hoppy" + emote_see = list("twitches its nose", "hops around a bit") + desc = "This is Hoppy. It's a corgi-...urmm... bunny rabbit" + valid = 1 + + if(/obj/item/clothing/head/beret, /obj/item/clothing/head/collectable/beret) + name = "Yann" + desc = "Mon dieu! C'est un chien!" + speak = list("le woof!", "le bark!", "JAPPE!!") + emote_see = list("cowers in fear", "surrenders", "plays dead","looks as though there is a wall in front of him") + valid = 1 + + if(/obj/item/clothing/head/det_hat) + name = "Detective [real_name]" + desc = "[name] sees through your lies..." + emote_see = list("investigates the area","sniffs around for clues","searches for scooby snacks") + valid = 1 + + if(/obj/item/clothing/head/nursehat) + name = "Nurse [real_name]" + desc = "[name] needs 100cc of beef jerky...STAT!" + valid = 1 + + if(/obj/item/clothing/head/pirate, /obj/item/clothing/head/collectable/pirate) + name = "[pick("Ol'","Scurvy","Black","Rum","Gammy","Bloody","Gangrene","Death","Long-John")] [pick("kibble","leg","beard","tooth","poop-deck","Threepwood","Le Chuck","corsair","Silver","Crusoe")]" + desc = "Yaarghh!! Thar' be a scurvy dog!" + emote_see = list("hunts for treasure","stares coldly...","gnashes his tiny corgi teeth") + emote_hear = list("growls ferociously", "snarls") + speak = list("Arrrrgh!!","Grrrrrr!") + valid = 1 + + if(/obj/item/clothing/head/ushanka) + name = "[pick("Comrade","Commissar","Glorious Leader")] [real_name]" + desc = "A follower of Karl Barx." + emote_see = list("contemplates the failings of the capitalist economic model", "ponders the pros and cons of vangaurdism") + valid = 1 + + if(/obj/item/clothing/head/collectable/police) + name = "Officer [real_name]" + emote_see = list("drools","looks for donuts") + desc = "Stop right there criminal scum!" + valid = 1 + + if(/obj/item/clothing/head/wizard/fake, /obj/item/clothing/head/wizard, /obj/item/clothing/head/collectable/wizard) + name = "Grandwizard [real_name]" + speak = list("YAP", "Woof!", "Bark!", "AUUUUUU", "EI NATH!") + valid = 1 + + if(/obj/item/clothing/head/cardborg) + name = "Borgi" + speak = list("Ping!","Beep!","Woof!") + emote_see = list("goes rogue", "sniffs out non-humans") + desc = "Result of robotics budget cuts." + valid = 1 + + if(/obj/item/weapon/bedsheet) + name = "\improper Ghost" + speak = list("WoooOOOooo~","AUUUUUUUUUUUUUUUUUU") + emote_see = list("stumbles around", "shivers") + emote_hear = list("howls","groans") + desc = "Spooky!" + valid = 1 + + if(/obj/item/clothing/head/helmet/space/santahat) + name = "Santa's Corgi Helper" + emote_hear = list("barks christmas songs", "yaps merrily") + emote_see = list("looks for presents", "checks his list") + desc = "He's very fond of milk and cookies." + valid = 1 + + if(/obj/item/clothing/head/soft) + name = "Corgi Tech [real_name]" + desc = "The reason your yellow gloves have chew-marks." + emote_see = list("Orders emitter crates and goes full blown cargonia.") + valid = 1 + + if(/obj/item/clothing/head/fedora) + name = "Autistic [real_name]" + desc = "His paws seem to be covered in what looks like Cheezy Honker dust." + emote_hear = list("barks ironicly", "makes you cringe") + emote_see = list("unsheathes katana", "tips fedora"/*,"Posts on 4chan" hue*/) + valid = 1 + + if(/obj/item/clothing/head/fez) + name = "Doctor Whom" + desc = "A time-dog from the planet barkifray." + emote_hear = list("barks cleverly.") + emote_see = list("fiddles around with a sonic-bone", "builds something amazing- thats a poop. He just pooped.") + valid = 1 + + if(/obj/item/clothing/head/helmet/space/rig) + name = "Spessman [real_name]" + desc = "Boldly going where no Corgi has gone before!" + valid = 1 + min_oxy = 0 + minbodytemp = 0 + maxbodytemp = 999 + + /* + if(/obj/item/clothing/head/hardhat/reindeer) + name = "[real_name] the red-nosed Corgi" + emote_hear = list("lights the way", "illuminates", "yaps") + desc = "He has a very shiny nose." + SetLuminosity(1) + valid = 1 + */ + + if(valid) + if(usr) + usr.visible_message("[usr] puts [item_to_add] on [real_name]'s head. [src] looks at [usr] and barks once.", + "You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags \his tail once and barks.", + "You hear a friendly-sounding bark.") + usr.drop_item(item_to_add, src, force_drop = 1) + else + item_to_add.loc = src + src.inventory_head = item_to_add + regenerate_icons() + + else + to_chat(usr, "You set [item_to_add] on [src]'s head, but \he shakes it off!") + usr.drop_item(item_to_add, src.loc) + + if(prob(25)) + step_rand(item_to_add) + if (ckey == null) + for(var/i in list(1,2,4,8,4,8,4,dir)) + dir = i + sleep(1) + + return valid + +/mob/living/simple_animal/corgi/proc/spinaroo(var/list/emotes) + if(!stat && !resting && !locked_to) + if(prob(1)) + if (ckey == null) + emote(pick(emotes)) + spawn(0) + for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2)) + dir = i + sleep(1) + + +//IAN! SQUEEEEEEEEE~ +/mob/living/simple_animal/corgi/Ian + name = "Ian" + real_name = "Ian" //Intended to hold the name without altering it. + gender = MALE + desc = "It's a corgi." + var/turns_since_scan = 0 + var/obj/movement_target + response_help = "pets" + response_disarm = "bops" + response_harm = "kicks" + spin_emotes = list("dances around","chases his tail") + +/mob/living/simple_animal/corgi/Ian/Life() + if(timestopped) return 0 //under effects of time magick + + ..() + + //Feeding, chasing food, FOOOOODDDD + if(!stat && !resting && !locked_to && (ckey == null)) + turns_since_scan++ + if(turns_since_scan > 5) + turns_since_scan = 0 + if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) + movement_target = null + stop_automated_movement = 0 + if( !movement_target || !(movement_target.loc in oview(src, 3)) ) + movement_target = null + stop_automated_movement = 0 + for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3)) + if(isturf(S.loc) || ishuman(S.loc)) + movement_target = S + break + if(movement_target) + spawn(0) + stop_automated_movement = 1 + step_to(src,movement_target,1) + sleep(3) + step_to(src,movement_target,1) + sleep(3) + step_to(src,movement_target,1) + + if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds + if (movement_target.loc.x < src.x) + dir = WEST + else if (movement_target.loc.x > src.x) + dir = EAST + else if (movement_target.loc.y < src.y) + dir = SOUTH + else if (movement_target.loc.y > src.y) + dir = NORTH + else + dir = SOUTH + + if(isturf(movement_target.loc) && src.Adjacent(movement_target)) + movement_target.attack_animal(src) + else if(ishuman(movement_target.loc) ) + if(prob(20)) + emote("stares at [movement_target.loc]'s [movement_target] with a sad puppy-face") +//PC stuff-Sieve + +/mob/living/simple_animal/corgi/regenerate_icons() + overlays = list() + + if(inventory_head) + var/head_icon_state = inventory_head.icon_state + if(health <= 0) + head_icon_state += "2" + + var/icon/head_icon = image('icons/mob/corgi_head.dmi',head_icon_state) + if(head_icon) + overlays += head_icon + + if(inventory_back) + var/back_icon_state = inventory_back.icon_state + if(health <= 0) + back_icon_state += "2" + + var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state) + if(back_icon) + overlays += back_icon + + if(facehugger) + if(istype(src, /mob/living/simple_animal/corgi/puppy)) + overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy") + else + overlays += image('icons/mob/mask.dmi',"facehugger_corgi") + + return + + + +/mob/living/simple_animal/corgi/puppy + name = "\improper corgi puppy" + real_name = "corgi" + desc = "It's a corgi puppy." + icon_state = "puppy" + icon_living = "puppy" + icon_dead = "puppy_dead" + size = SIZE_TINY + +//puppies cannot wear anything. +/mob/living/simple_animal/corgi/puppy/Topic(href, href_list) + if(href_list["remove_inv"] || href_list["add_inv"]) + to_chat(usr, "You can't fit this on [src]") + return + ..() + + +//LISA! SQUEEEEEEEEE~ +/mob/living/simple_animal/corgi/Lisa + name = "Lisa" + real_name = "Lisa" + gender = FEMALE + desc = "It's a corgi with a cute pink bow." + icon_state = "lisa" + icon_living = "lisa" + icon_dead = "lisa_dead" + response_help = "pets" + response_disarm = "bops" + response_harm = "kicks" + var/turns_since_scan = 0 + var/puppies = 0 + spin_emotes = list("dances around","chases her of a tail") + +//Lisa already has a cute bow! +/mob/living/simple_animal/corgi/Lisa/Topic(href, href_list) + if(href_list["remove_inv"] || href_list["add_inv"]) + to_chat(usr, "[src] already has a cute bow!") + return + ..() + +/mob/living/simple_animal/corgi/attack_hand(mob/living/carbon/human/M) + . = ..() + switch(M.a_intent) + if(I_HELP) wuv(1,M) + if(I_HURT) wuv(-1,M) + +/mob/living/simple_animal/corgi/proc/wuv(change, mob/M) + if(change) + if(change > 0) + if(M && !isUnconscious()) // Added check to see if this mob (the corgi) is dead to fix issue 2454 + flick_overlay(image('icons/mob/animal.dmi',src,"heart-ani2",MOB_LAYER+1), list(M.client), 20) + emote("yaps happily") + else + if(M && !isUnconscious()) // Same check here, even though emote checks it as well (poor form to check it only in the help case) + emote("growls") + + +//Sasha isn't even a corgi you dummy! +/mob/living/simple_animal/corgi/sasha + name = "Sasha" + real_name = "Sasha" + gender = FEMALE + desc = "It's a doberman, how intimidating!" + icon_state = "doby" + icon_living = "doby" + icon_dead = "doby_dead" + spin_emotes = list("prances around","chases her nub of a tail") + + species_type = /mob/living/simple_animal/corgi/sasha + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal + +//Sasha can't wear hats! +/mob/living/simple_animal/corgi/sasha/Topic(href, href_list) + if(href_list["remove_inv"] || href_list["add_inv"]) + to_chat(usr, "[src] won't wear that!") + return + ..() diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 362d67108e5..8237591a541 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -1,103 +1,103 @@ -//Look Sir, free crabs! -/mob/living/simple_animal/crab - name = "crab" - desc = "A hard-shelled crustacean. Seems quite content to lounge around all the time." - icon_state = "crab" - icon_living = "crab" - icon_dead = "crab_dead" - speak_emote = list("clicks") - emote_hear = list("clicks") - emote_see = list("clacks") - speak_chance = 1 - turns_per_move = 5 - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "stomps" - stop_automated_movement = 1 - friendly = "pinches" - size = SIZE_TINY - - var/obj/item/inventory_head - var/obj/item/inventory_mask - -/mob/living/simple_animal/crab/Life() - if(timestopped) return 0 //under effects of time magick - ..() - //CRAB movement - if(!ckey && !stat) - if(isturf(src.loc) && !resting && !locked_to) //This is so it only moves if it's not inside a closet, gentics machine, etc. - turns_since_move++ - if(turns_since_move >= turns_per_move) - Move(get_step(src,pick(4,8))) - turns_since_move = 0 - regenerate_icons() - -//COFFEE! SQUEEEEEEEEE! -/mob/living/simple_animal/crab/Coffee - name = "Coffee" - real_name = "Coffee" - desc = "It's Coffee, the other pet!" - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "stomps" - -//LOOK AT THIS - ..()?? -/mob/living/simple_animal/crab/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/wirecutters)) - if(prob(50)) - to_chat(user, "This kills the crab.") - health -= 20 - Die() - else - GetMad() - else - return ..() - -/mob/living/simple_animal/crab/proc/GetMad() - name = "MEGAMADCRAB" - real_name = "MEGAMADCRAB" - desc = "OH NO YOU DUN IT NOW." - icon = 'icons/mob/mob.dmi' - icon_state = "madcrab" - icon_living = "madcrab" - icon_dead = "madcrab_dead" - speak_emote = list("clicks") - emote_hear = list("clicks with fury", "clicks angrily") - emote_see = list("clacks") - speak_chance = 1 - turns_per_move = 15//Gotta go fast - maxHealth = 100//So they don't die as quickly - health = 100 - melee_damage_lower = 3 - melee_damage_upper = 10//Kill them. Kill them all - if(inventory_head)//Drops inventory so it doesn't have to be dealt with - inventory_head.loc = src.loc - inventory_head = null - if(inventory_mask) - inventory_mask.loc = src.loc - inventory_mask = null - -/mob/living/simple_animal/crab/kickstool - name = "kickstool crab" - desc = "Small, docile crab. They tend to live in large libraries, and eat dust for some reason." - icon_state = "kickstool" - icon_living = "kickstool" - icon_dead = "kickstool_dead" - -/mob/living/simple_animal/crab/norris - name = "Norris" - desc = "Some weird Thing that makes a neat pet. Screams a lot." - icon_state = "norris" - icon_living = "norris" - icon_dead = "norris_dead" - speak_emote = list("screams") - emote_hear = list("screams") - emote_see = list("screams") - friendly = "bites" - -/mob/living/simple_animal/crab/snowy - name = "Snowy" - desc = "While you'd think that most crabs in cold climates would stick to the relatively warmer water, this one's adapted to living on the land and has camouflage to boot" - icon_state = "snowcrab" - icon_living = "snowcrab" +//Look Sir, free crabs! +/mob/living/simple_animal/crab + name = "crab" + desc = "A hard-shelled crustacean. Seems quite content to lounge around all the time." + icon_state = "crab" + icon_living = "crab" + icon_dead = "crab_dead" + speak_emote = list("clicks") + emote_hear = list("clicks") + emote_see = list("clacks") + speak_chance = 1 + turns_per_move = 5 + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "stomps" + stop_automated_movement = 1 + friendly = "pinches" + size = SIZE_TINY + + var/obj/item/inventory_head + var/obj/item/inventory_mask + +/mob/living/simple_animal/crab/Life() + if(timestopped) return 0 //under effects of time magick + ..() + //CRAB movement + if(!ckey && !stat) + if(isturf(src.loc) && !resting && !locked_to) //This is so it only moves if it's not inside a closet, gentics machine, etc. + turns_since_move++ + if(turns_since_move >= turns_per_move) + Move(get_step(src,pick(4,8))) + turns_since_move = 0 + regenerate_icons() + +//COFFEE! SQUEEEEEEEEE! +/mob/living/simple_animal/crab/Coffee + name = "Coffee" + real_name = "Coffee" + desc = "It's Coffee, the other pet!" + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "stomps" + +//LOOK AT THIS - ..()?? +/mob/living/simple_animal/crab/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/wirecutters)) + if(prob(50)) + to_chat(user, "This kills the crab.") + health -= 20 + Die() + else + GetMad() + else + return ..() + +/mob/living/simple_animal/crab/proc/GetMad() + name = "MEGAMADCRAB" + real_name = "MEGAMADCRAB" + desc = "OH NO YOU DUN IT NOW." + icon = 'icons/mob/mob.dmi' + icon_state = "madcrab" + icon_living = "madcrab" + icon_dead = "madcrab_dead" + speak_emote = list("clicks") + emote_hear = list("clicks with fury", "clicks angrily") + emote_see = list("clacks") + speak_chance = 1 + turns_per_move = 15//Gotta go fast + maxHealth = 100//So they don't die as quickly + health = 100 + melee_damage_lower = 3 + melee_damage_upper = 10//Kill them. Kill them all + if(inventory_head)//Drops inventory so it doesn't have to be dealt with + inventory_head.loc = src.loc + inventory_head = null + if(inventory_mask) + inventory_mask.loc = src.loc + inventory_mask = null + +/mob/living/simple_animal/crab/kickstool + name = "kickstool crab" + desc = "Small, docile crab. They tend to live in large libraries, and eat dust for some reason." + icon_state = "kickstool" + icon_living = "kickstool" + icon_dead = "kickstool_dead" + +/mob/living/simple_animal/crab/norris + name = "Norris" + desc = "Some weird Thing that makes a neat pet. Screams a lot." + icon_state = "norris" + icon_living = "norris" + icon_dead = "norris_dead" + speak_emote = list("screams") + emote_hear = list("screams") + emote_see = list("screams") + friendly = "bites" + +/mob/living/simple_animal/crab/snowy + name = "Snowy" + desc = "While you'd think that most crabs in cold climates would stick to the relatively warmer water, this one's adapted to living on the land and has camouflage to boot" + icon_state = "snowcrab" + icon_living = "snowcrab" icon_dead = "snowcrab_dead" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index e1e842cedf8..ee7551c7cb6 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -1,276 +1,276 @@ -//goat -/mob/living/simple_animal/hostile/retaliate/goat - name = "goat" - desc = "Not known for their pleasant disposition." - icon_state = "goat" - icon_living = "goat" - icon_dead = "goat_dead" - speak = list("EHEHEHEHEH","eh?") - speak_emote = list("brays") - emote_hear = list("brays") - emote_see = list("shakes its head", "stamps a foot", "glares around") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - faction = "goat" - attacktext = "kicks" - health = 40 - melee_damage_lower = 1 - melee_damage_upper = 2 - size = SIZE_BIG - - var/datum/reagents/udder = null - -/mob/living/simple_animal/hostile/retaliate/goat/New() - udder = new(50) - udder.my_atom = src - ..() - -/mob/living/simple_animal/hostile/retaliate/goat/Life() - if(timestopped) return 0 //under effects of time magick - . = ..() - if(.) - //chance to go crazy and start wacking stuff - if(!enemies.len && prob(1)) - Retaliate() - - if(enemies.len && prob(10)) - enemies = list() - LoseTarget() - src.visible_message("[src] calms down.") - - if(stat == CONSCIOUS) - if(udder && prob(5)) - udder.add_reagent("milk", rand(5, 10)) - - if(locate(/obj/effect/plantsegment) in loc) - var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc - SV.die_off() - if(prob(10)) - say("Nom") - - if(!pulledby) - for(var/direction in shuffle(alldirs)) - var/step = get_step(src, direction) - if(step) - if(locate(/obj/effect/plantsegment) in step) - Move(step) - -/mob/living/simple_animal/hostile/retaliate/goat/Retaliate() - if(!stat) - ..() - src.visible_message("[src] gets an evil-looking gleam in \his eye.") - -/mob/living/simple_animal/hostile/retaliate/goat/Move() - ..() - if(!stat) - if(locate(/obj/effect/plantsegment) in loc) - var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc - SV.die_off() - if(prob(10)) - say("Nom") - -/mob/living/simple_animal/hostile/retaliate/goat/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) - user.visible_message("[user] milks [src] using \the [O].") - var/obj/item/weapon/reagent_containers/glass/G = O - var/transfered = udder.trans_id_to(G, "milk", rand(5,10)) - if(G.reagents.total_volume >= G.volume) - to_chat(user, "[O] is full.") - if(!transfered) - to_chat(user, "The udder is dry. Wait a bit longer...") - else - ..() -//cow -/mob/living/simple_animal/cow - name = "cow" - desc = "Known for their milk, just don't tip them over." - icon_state = "cow" - icon_living = "cow" - icon_dead = "cow_dead" - icon_gib = "cow_gib" - speak = list("moo?","moo","MOOOOOO") - speak_emote = list("moos","moos hauntingly") - emote_hear = list("brays") - emote_see = list("shakes its head") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" - health = 50 - - size = SIZE_BIG - holder_type = /obj/item/weapon/holder/animal/cow - - var/datum/reagents/udder = null - -/mob/living/simple_animal/cow/New() - udder = new(50) - udder.my_atom = src - ..() - -/mob/living/simple_animal/cow/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) - user.visible_message("[user] milks [src] using \the [O].") - var/obj/item/weapon/reagent_containers/glass/G = O - var/transfered = udder.trans_id_to(G, "milk", rand(5,10)) - if(G.reagents.total_volume >= G.volume) - to_chat(user, "[O] is full.") - if(!transfered) - to_chat(user, "The udder is dry. Wait a bit longer...") - else - ..() - -/mob/living/simple_animal/cow/Life() - if(timestopped) return 0 //under effects of time magick - . = ..() - if(stat == CONSCIOUS) - if(udder && prob(5)) - udder.add_reagent("milk", rand(5, 10)) - -/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M as mob) - if(!stat && M.a_intent == I_DISARM && icon_state != icon_dead) - M.visible_message("[M] tips over [src].","You tip over [src].") - Weaken(30) - icon_state = icon_dead - spawn(rand(20,50)) - if(!stat && M) - icon_state = icon_living - var/list/responses = list( "[src] looks at you imploringly.", - "[src] looks at you pleadingly", - "[src] looks at you with a resigned expression.", - "[src] seems resigned to its fate.") - to_chat(M, pick(responses)) - else - ..() - -/mob/living/simple_animal/chick - name = "chick" - desc = "Adorable! They make such a racket though." - icon_state = "chick" - icon_living = "chick" - icon_dead = "chick_dead" - icon_gib = "chick_gib" - speak = list("Cherp.","Cherp?","Chirrup.","Cheep!") - speak_emote = list("cheeps") - emote_hear = list("cheeps") - emote_see = list("pecks at the ground","flaps its tiny wings") - speak_chance = 2 - turns_per_move = 2 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken - species_type = /mob/living/simple_animal/chicken - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" - health = 1 - var/amount_grown = 0 - pass_flags = PASSTABLE | PASSGRILLE - size = SIZE_TINY - -/mob/living/simple_animal/chick/New() - ..() - pixel_x = rand(-6, 6) - pixel_y = rand(0, 10) - -/mob/living/simple_animal/chick/Life() - if(timestopped) return 0 //under effects of time magick - . =..() - if(!.) - return - if(!stat && !ckey) - amount_grown += rand(1,2) - if(amount_grown >= 100) - new /mob/living/simple_animal/chicken(src.loc) - qdel(src) - -/mob/living/simple_animal/chicken - name = "chicken" - desc = "Hopefully the eggs are good this season." - icon_state = "chicken" - icon_living = "chicken" - icon_dead = "chicken_dead" - speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.") - speak_emote = list("clucks","croons") - emote_hear = list("clucks") - emote_see = list("pecks at the ground","flaps its wings viciously") - speak_chance = 2 - turns_per_move = 3 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" - health = 10 - var/eggsleft = 0 - var/body_color - pass_flags = PASSTABLE - size = SIZE_SMALL - -/mob/living/simple_animal/chicken/New() - if(prob(5)) - name = "Pomf chicken" - body_color = "white" - - if(!body_color) - body_color = pick( list("brown","black","white") ) - icon_state = "chicken_[body_color]" - icon_living = "chicken_[body_color]" - icon_dead = "chicken_[body_color]_dead" - ..() //call this after icons to generate the proper static overlays - pixel_x = rand(-6, 6) - pixel_y = rand(0, 10) - -/mob/living/simple_animal/chicken/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens - if(!stat && eggsleft < 8) - if(!user.drop_item(O)) - user << "You can't let go of \the [O]!" - return - - user.visible_message("[user] feeds [O] to [name]! It clucks happily.","You feed [O] to [name]! It clucks happily.") - qdel(O) - eggsleft += rand(1, 4) -// to_chat(world, eggsleft) - else - to_chat(user, "[name] doesn't seem hungry!") - else if(istype(O, /obj/item/weapon/dnainjector)) - var/obj/item/weapon/dnainjector/I = O - I.inject(src, user) - else - ..() - -/mob/living/simple_animal/chicken/Life() - if(timestopped) return 0 //under effects of time magick - . =..() - if(!.) - return - if(!stat && prob(3) && eggsleft > 0) - visible_message("[src] [pick("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")]") - eggsleft-- - var/obj/item/weapon/reagent_containers/food/snacks/egg/E = new(get_turf(src)) - E.pixel_x = rand(-6,6) - E.pixel_y = rand(-6,6) - if(animal_count[src.type] < ANIMAL_CHILD_CAP && prob(10)) - processing_objects.Add(E) - -/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0 -/obj/item/weapon/reagent_containers/food/snacks/egg/process() - if(is_in_valid_nest(src)) //_macros.dm - amount_grown += rand(1,2) - if(amount_grown >= 100) - hatch() - else - processing_objects.Remove(src) - -/obj/item/weapon/reagent_containers/food/snacks/egg/proc/hatch() - visible_message("[src] hatches with a quiet cracking sound.") - new /mob/living/simple_animal/chick(get_turf(src)) - processing_objects.Remove(src) - qdel(src) +//goat +/mob/living/simple_animal/hostile/retaliate/goat + name = "goat" + desc = "Not known for their pleasant disposition." + icon_state = "goat" + icon_living = "goat" + icon_dead = "goat_dead" + speak = list("EHEHEHEHEH","eh?") + speak_emote = list("brays") + emote_hear = list("brays") + emote_see = list("shakes its head", "stamps a foot", "glares around") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" + faction = "goat" + attacktext = "kicks" + health = 40 + melee_damage_lower = 1 + melee_damage_upper = 2 + size = SIZE_BIG + + var/datum/reagents/udder = null + +/mob/living/simple_animal/hostile/retaliate/goat/New() + udder = new(50) + udder.my_atom = src + ..() + +/mob/living/simple_animal/hostile/retaliate/goat/Life() + if(timestopped) return 0 //under effects of time magick + . = ..() + if(.) + //chance to go crazy and start wacking stuff + if(!enemies.len && prob(1)) + Retaliate() + + if(enemies.len && prob(10)) + enemies = list() + LoseTarget() + src.visible_message("[src] calms down.") + + if(stat == CONSCIOUS) + if(udder && prob(5)) + udder.add_reagent("milk", rand(5, 10)) + + if(locate(/obj/effect/plantsegment) in loc) + var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc + SV.die_off() + if(prob(10)) + say("Nom") + + if(!pulledby) + for(var/direction in shuffle(alldirs)) + var/step = get_step(src, direction) + if(step) + if(locate(/obj/effect/plantsegment) in step) + Move(step) + +/mob/living/simple_animal/hostile/retaliate/goat/Retaliate() + if(!stat) + ..() + src.visible_message("[src] gets an evil-looking gleam in \his eye.") + +/mob/living/simple_animal/hostile/retaliate/goat/Move() + ..() + if(!stat) + if(locate(/obj/effect/plantsegment) in loc) + var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc + SV.die_off() + if(prob(10)) + say("Nom") + +/mob/living/simple_animal/hostile/retaliate/goat/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) + user.visible_message("[user] milks [src] using \the [O].") + var/obj/item/weapon/reagent_containers/glass/G = O + var/transfered = udder.trans_id_to(G, "milk", rand(5,10)) + if(G.reagents.total_volume >= G.volume) + to_chat(user, "[O] is full.") + if(!transfered) + to_chat(user, "The udder is dry. Wait a bit longer...") + else + ..() +//cow +/mob/living/simple_animal/cow + name = "cow" + desc = "Known for their milk, just don't tip them over." + icon_state = "cow" + icon_living = "cow" + icon_dead = "cow_dead" + icon_gib = "cow_gib" + speak = list("moo?","moo","MOOOOOO") + speak_emote = list("moos","moos hauntingly") + emote_hear = list("brays") + emote_see = list("shakes its head") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" + attacktext = "kicks" + health = 50 + + size = SIZE_BIG + holder_type = /obj/item/weapon/holder/animal/cow + + var/datum/reagents/udder = null + +/mob/living/simple_animal/cow/New() + udder = new(50) + udder.my_atom = src + ..() + +/mob/living/simple_animal/cow/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) + user.visible_message("[user] milks [src] using \the [O].") + var/obj/item/weapon/reagent_containers/glass/G = O + var/transfered = udder.trans_id_to(G, "milk", rand(5,10)) + if(G.reagents.total_volume >= G.volume) + to_chat(user, "[O] is full.") + if(!transfered) + to_chat(user, "The udder is dry. Wait a bit longer...") + else + ..() + +/mob/living/simple_animal/cow/Life() + if(timestopped) return 0 //under effects of time magick + . = ..() + if(stat == CONSCIOUS) + if(udder && prob(5)) + udder.add_reagent("milk", rand(5, 10)) + +/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M as mob) + if(!stat && M.a_intent == I_DISARM && icon_state != icon_dead) + M.visible_message("[M] tips over [src].","You tip over [src].") + Weaken(30) + icon_state = icon_dead + spawn(rand(20,50)) + if(!stat && M) + icon_state = icon_living + var/list/responses = list( "[src] looks at you imploringly.", + "[src] looks at you pleadingly", + "[src] looks at you with a resigned expression.", + "[src] seems resigned to its fate.") + to_chat(M, pick(responses)) + else + ..() + +/mob/living/simple_animal/chick + name = "chick" + desc = "Adorable! They make such a racket though." + icon_state = "chick" + icon_living = "chick" + icon_dead = "chick_dead" + icon_gib = "chick_gib" + speak = list("Cherp.","Cherp?","Chirrup.","Cheep!") + speak_emote = list("cheeps") + emote_hear = list("cheeps") + emote_see = list("pecks at the ground","flaps its tiny wings") + speak_chance = 2 + turns_per_move = 2 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken + species_type = /mob/living/simple_animal/chicken + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" + attacktext = "kicks" + health = 1 + var/amount_grown = 0 + pass_flags = PASSTABLE | PASSGRILLE + size = SIZE_TINY + +/mob/living/simple_animal/chick/New() + ..() + pixel_x = rand(-6, 6) + pixel_y = rand(0, 10) + +/mob/living/simple_animal/chick/Life() + if(timestopped) return 0 //under effects of time magick + . =..() + if(!.) + return + if(!stat && !ckey) + amount_grown += rand(1,2) + if(amount_grown >= 100) + new /mob/living/simple_animal/chicken(src.loc) + qdel(src) + +/mob/living/simple_animal/chicken + name = "chicken" + desc = "Hopefully the eggs are good this season." + icon_state = "chicken" + icon_living = "chicken" + icon_dead = "chicken_dead" + speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.") + speak_emote = list("clucks","croons") + emote_hear = list("clucks") + emote_see = list("pecks at the ground","flaps its wings viciously") + speak_chance = 2 + turns_per_move = 3 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/rawchicken + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" + attacktext = "kicks" + health = 10 + var/eggsleft = 0 + var/body_color + pass_flags = PASSTABLE + size = SIZE_SMALL + +/mob/living/simple_animal/chicken/New() + if(prob(5)) + name = "Pomf chicken" + body_color = "white" + + if(!body_color) + body_color = pick( list("brown","black","white") ) + icon_state = "chicken_[body_color]" + icon_living = "chicken_[body_color]" + icon_dead = "chicken_[body_color]_dead" + ..() //call this after icons to generate the proper static overlays + pixel_x = rand(-6, 6) + pixel_y = rand(0, 10) + +/mob/living/simple_animal/chicken/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens + if(!stat && eggsleft < 8) + if(!user.drop_item(O)) + user << "You can't let go of \the [O]!" + return + + user.visible_message("[user] feeds [O] to [name]! It clucks happily.","You feed [O] to [name]! It clucks happily.") + qdel(O) + eggsleft += rand(1, 4) +// to_chat(world, eggsleft) + else + to_chat(user, "[name] doesn't seem hungry!") + else if(istype(O, /obj/item/weapon/dnainjector)) + var/obj/item/weapon/dnainjector/I = O + I.inject(src, user) + else + ..() + +/mob/living/simple_animal/chicken/Life() + if(timestopped) return 0 //under effects of time magick + . =..() + if(!.) + return + if(!stat && prob(3) && eggsleft > 0) + visible_message("[src] [pick("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")]") + eggsleft-- + var/obj/item/weapon/reagent_containers/food/snacks/egg/E = new(get_turf(src)) + E.pixel_x = rand(-6,6) + E.pixel_y = rand(-6,6) + if(animal_count[src.type] < ANIMAL_CHILD_CAP && prob(10)) + processing_objects.Add(E) + +/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0 +/obj/item/weapon/reagent_containers/food/snacks/egg/process() + if(is_in_valid_nest(src)) //_macros.dm + amount_grown += rand(1,2) + if(amount_grown >= 100) + hatch() + else + processing_objects.Remove(src) + +/obj/item/weapon/reagent_containers/food/snacks/egg/proc/hatch() + visible_message("[src] hatches with a quiet cracking sound.") + new /mob/living/simple_animal/chick(get_turf(src)) + processing_objects.Remove(src) + qdel(src) diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm index 87ba6d9fd8c..6a51441ce01 100644 --- a/code/modules/mob/living/simple_animal/friendly/lizard.dm +++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm @@ -1,17 +1,17 @@ -/mob/living/simple_animal/lizard - name = "Lizard" - desc = "A cute tiny lizard." - icon_state = "lizard" - icon_living = "lizard" - icon_dead = "lizard_dead" - speak_emote = list("hisses") - health = 5 - maxHealth = 5 - attacktext = "bites" - melee_damage_lower = 1 - melee_damage_upper = 2 - response_help = "pets" - response_disarm = "shoos" - response_harm = "stomps on" - - size = SIZE_TINY +/mob/living/simple_animal/lizard + name = "Lizard" + desc = "A cute tiny lizard." + icon_state = "lizard" + icon_living = "lizard" + icon_dead = "lizard_dead" + speak_emote = list("hisses") + health = 5 + maxHealth = 5 + attacktext = "bites" + melee_damage_lower = 1 + melee_damage_upper = 2 + response_help = "pets" + response_disarm = "shoos" + response_harm = "stomps on" + + size = SIZE_TINY diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 18f4ff24123..9d8d120d0ab 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -1,196 +1,196 @@ -/mob/living/simple_animal/mouse - name = "mouse" - real_name = "mouse" - desc = "It's a small, disease-ridden rodent." - icon_state = "mouse_gray" - icon_living = "mouse_gray" - icon_dead = "mouse_gray_dead" - speak = list("Squeek!","SQUEEK!","Squeek?") - speak_emote = list("squeeks","squeeks","squiks") - emote_hear = list("squeeks","squeaks","squiks") - emote_see = list("runs in a circle", "shakes", "scritches at something") - pass_flags = PASSTABLE - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - maxHealth = 5 - health = 5 - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "stamps on the" - density = 0 - var/_color //brown, gray and white, leave blank for random - layer = MOB_LAYER - min_oxy = 16 //Require atleast 16kPA oxygen - minbodytemp = 223 //Below -50 Degrees Celcius - maxbodytemp = 323 //Above 50 Degrees Celcius - universal_speak = 0 - treadmill_speed = 0.2 //You can still do it, but you're not going to generate much power. - - size = SIZE_TINY - holder_type = /obj/item/weapon/holder/animal/mouse - -/mob/living/simple_animal/mouse/Life() - if(timestopped) return 0 //under effects of time magick - ..() - if(!stat && prob(speak_chance)) - for(var/mob/M in view()) +/mob/living/simple_animal/mouse + name = "mouse" + real_name = "mouse" + desc = "It's a small, disease-ridden rodent." + icon_state = "mouse_gray" + icon_living = "mouse_gray" + icon_dead = "mouse_gray_dead" + speak = list("Squeek!","SQUEEK!","Squeek?") + speak_emote = list("squeeks","squeeks","squiks") + emote_hear = list("squeeks","squeaks","squiks") + emote_see = list("runs in a circle", "shakes", "scritches at something") + pass_flags = PASSTABLE + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + maxHealth = 5 + health = 5 + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "stamps on the" + density = 0 + var/_color //brown, gray and white, leave blank for random + layer = MOB_LAYER + min_oxy = 16 //Require atleast 16kPA oxygen + minbodytemp = 223 //Below -50 Degrees Celcius + maxbodytemp = 323 //Above 50 Degrees Celcius + universal_speak = 0 + treadmill_speed = 0.2 //You can still do it, but you're not going to generate much power. + + size = SIZE_TINY + holder_type = /obj/item/weapon/holder/animal/mouse + +/mob/living/simple_animal/mouse/Life() + if(timestopped) return 0 //under effects of time magick + ..() + if(!stat && prob(speak_chance)) + for(var/mob/M in view()) to_chat(M, 'sound/effects/mousesqueek.ogg') - - if(!ckey && stat == CONSCIOUS && prob(0.5)) - stat = UNCONSCIOUS - icon_state = "mouse_[_color]_sleep" - wander = 0 - speak_chance = 0 - //snuffles - else if(stat == UNCONSCIOUS) - if(ckey || prob(1)) - stat = CONSCIOUS - icon_state = "mouse_[_color]" - wander = 1 - else if(prob(5)) - emote("snuffles") - -/mob/living/simple_animal/mouse/New() - ..() - if(config && config.uneducated_mice) - universal_understand = 0 - // Mice IDs - if(name == initial(name)) - name = "[name] ([rand(1, 1000)])" - real_name = name - if(!_color) - _color = pick( list("brown","gray","white") ) - icon_state = "mouse_[_color]" - icon_living = "mouse_[_color]" - icon_dead = "mouse_[_color]_dead" - desc = "It's a small [_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." - add_language("Mouse") - default_language = all_languages["Mouse"] - - -/mob/living/simple_animal/mouse/proc/splat() - src.health = 0 - src.stat = DEAD - src.icon_dead = "mouse_[_color]_splat" - src.icon_state = "mouse_[_color]_splat" - if(client) - client.time_died_as_mouse = world.time - -//copy paste from alien/larva, if that func is updated please update this one also -/mob/living/simple_animal/mouse/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Object" - var/pipe = start_ventcrawl() - if(pipe) - handle_ventcrawl(pipe) - -//copy paste from alien/larva, if that func is updated please update this one alsoghost -/mob/living/simple_animal/mouse/verb/hide() - set name = "Hide" - set desc = "Allows to hide beneath tables or certain items. Toggled on or off." - set category = "Object" - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 + + if(!ckey && stat == CONSCIOUS && prob(0.5)) + stat = UNCONSCIOUS + icon_state = "mouse_[_color]_sleep" + wander = 0 + speak_chance = 0 + //snuffles + else if(stat == UNCONSCIOUS) + if(ckey || prob(1)) + stat = CONSCIOUS + icon_state = "mouse_[_color]" + wander = 1 + else if(prob(5)) + emote("snuffles") + +/mob/living/simple_animal/mouse/New() + ..() + if(config && config.uneducated_mice) + universal_understand = 0 + // Mice IDs + if(name == initial(name)) + name = "[name] ([rand(1, 1000)])" + real_name = name + if(!_color) + _color = pick( list("brown","gray","white") ) + icon_state = "mouse_[_color]" + icon_living = "mouse_[_color]" + icon_dead = "mouse_[_color]_dead" + desc = "It's a small [_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." + add_language("Mouse") + default_language = all_languages["Mouse"] + + +/mob/living/simple_animal/mouse/proc/splat() + src.health = 0 + src.stat = DEAD + src.icon_dead = "mouse_[_color]_splat" + src.icon_state = "mouse_[_color]_splat" + if(client) + client.time_died_as_mouse = world.time + +//copy paste from alien/larva, if that func is updated please update this one also +/mob/living/simple_animal/mouse/verb/ventcrawl() + set name = "Crawl through Vent" + set desc = "Enter an air vent and crawl through the pipe system." + set category = "Object" + var/pipe = start_ventcrawl() + if(pipe) + handle_ventcrawl(pipe) + +//copy paste from alien/larva, if that func is updated please update this one alsoghost +/mob/living/simple_animal/mouse/verb/hide() + set name = "Hide" + set desc = "Allows to hide beneath tables or certain items. Toggled on or off." + set category = "Object" + + if (layer != TURF_LAYER+0.2) + layer = TURF_LAYER+0.2 to_chat(src, text("You are now hiding.")) - /* - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) + /* + for(var/mob/O in oviewers(src, null)) + if ((O.client && !( O.blinded ))) to_chat(O, text("[] scurries to the ground!", src)) - */ - else - layer = MOB_LAYER + */ + else + layer = MOB_LAYER to_chat(src, text("You have stopped hiding.")) - /* - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) + /* + for(var/mob/O in oviewers(src, null)) + if ((O.client && !( O.blinded ))) to_chat(O, text("[] slowly peaks up from the ground...", src)) - */ - -//make mice fit under tables etc? this was hacky, and not working -/* -/mob/living/simple_animal/mouse/Move(var/dir) - - var/turf/target_turf = get_step(src,dir) - //CanReachThrough(src.loc, target_turf, src) - var/can_fit_under = 0 - if(target_turf.ZCanPass(get_turf(src),1)) - can_fit_under = 1 - - ..(dir) - if(can_fit_under) - src.loc = target_turf - for(var/d in cardinal) - var/turf/O = get_step(T,d) - //Simple pass check. - if(O.ZCanPass(T, 1) && !(O in open) && !(O in closed) && O in possibles) - open += O - */ - -///mob/living/simple_animal/mouse/restrained() //Hotfix to stop mice from doing things with MouseDrop -// return 1 - -/mob/living/simple_animal/mouse/start_pulling(var/atom/movable/AM)//Prevents mouse from pulling things + */ + +//make mice fit under tables etc? this was hacky, and not working +/* +/mob/living/simple_animal/mouse/Move(var/dir) + + var/turf/target_turf = get_step(src,dir) + //CanReachThrough(src.loc, target_turf, src) + var/can_fit_under = 0 + if(target_turf.ZCanPass(get_turf(src),1)) + can_fit_under = 1 + + ..(dir) + if(can_fit_under) + src.loc = target_turf + for(var/d in cardinal) + var/turf/O = get_step(T,d) + //Simple pass check. + if(O.ZCanPass(T, 1) && !(O in open) && !(O in closed) && O in possibles) + open += O + */ + +///mob/living/simple_animal/mouse/restrained() //Hotfix to stop mice from doing things with MouseDrop +// return 1 + +/mob/living/simple_animal/mouse/start_pulling(var/atom/movable/AM)//Prevents mouse from pulling things to_chat(src, "You are too small to pull anything.") - return - -/mob/living/simple_animal/mouse/Crossed(AM as mob|obj) - if( ishuman(AM) ) - if(!stat) - var/mob/M = AM + return + +/mob/living/simple_animal/mouse/Crossed(AM as mob|obj) + if( ishuman(AM) ) + if(!stat) + var/mob/M = AM to_chat(M, "\icon[src] Squeek!") to_chat(M, 'sound/effects/mousesqueek.ogg') - ..() - -/mob/living/simple_animal/mouse/Die() - if(client) - client.time_died_as_mouse = world.time - ..() - -/* - * Mouse types - */ - -/mob/living/simple_animal/mouse/white - _color = "white" - icon_state = "mouse_white" - -/mob/living/simple_animal/mouse/gray - _color = "gray" - icon_state = "mouse_gray" - -/mob/living/simple_animal/mouse/brown - _color = "brown" - icon_state = "mouse_brown" - -/mob/living/simple_animal/mouse/black - _color = "black" - icon_state = "mouse_black" - -//TOM IS ALIVE! SQUEEEEEEEE~K :) -/mob/living/simple_animal/mouse/brown/Tom - name = "Tom" - desc = "Jerry the cat is not amused." - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "splats" - -/mob/living/simple_animal/mouse/black/dessert - name = "Dessert" - desc = "Crunchy!" - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "tenderizes" - -/mob/living/simple_animal/mouse/say_quote(text) - if(!text) - return "squeaks, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code - return "squeaks, [text]"; - -/mob/living/simple_animal/mouse/singularity_act() - if(!(src.flags & INVULNERABLE)) - investigation_log(I_SINGULO,"has been consumed by a singularity") - gib() - return 0 + ..() + +/mob/living/simple_animal/mouse/Die() + if(client) + client.time_died_as_mouse = world.time + ..() + +/* + * Mouse types + */ + +/mob/living/simple_animal/mouse/white + _color = "white" + icon_state = "mouse_white" + +/mob/living/simple_animal/mouse/gray + _color = "gray" + icon_state = "mouse_gray" + +/mob/living/simple_animal/mouse/brown + _color = "brown" + icon_state = "mouse_brown" + +/mob/living/simple_animal/mouse/black + _color = "black" + icon_state = "mouse_black" + +//TOM IS ALIVE! SQUEEEEEEEE~K :) +/mob/living/simple_animal/mouse/brown/Tom + name = "Tom" + desc = "Jerry the cat is not amused." + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "splats" + +/mob/living/simple_animal/mouse/black/dessert + name = "Dessert" + desc = "Crunchy!" + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "tenderizes" + +/mob/living/simple_animal/mouse/say_quote(text) + if(!text) + return "squeaks, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code + return "squeaks, [text]"; + +/mob/living/simple_animal/mouse/singularity_act() + if(!(src.flags & INVULNERABLE)) + investigation_log(I_SINGULO,"has been consumed by a singularity") + gib() + return 0 diff --git a/code/modules/mob/living/simple_animal/friendly/mushroom.dm b/code/modules/mob/living/simple_animal/friendly/mushroom.dm index ef2eb6cd61e..9bd464dbf3c 100644 --- a/code/modules/mob/living/simple_animal/friendly/mushroom.dm +++ b/code/modules/mob/living/simple_animal/friendly/mushroom.dm @@ -1,16 +1,16 @@ -/mob/living/simple_animal/mushroom - name = "walking mushroom" - desc = "It's a massive mushroom... with legs?" - icon_state = "mushroom" - icon_living = "mushroom" - icon_dead = "mushroom_dead" - small = 1 - speak_chance = 0 - turns_per_move = 1 - maxHealth = 5 - health = 5 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "whacks the" +/mob/living/simple_animal/mushroom + name = "walking mushroom" + desc = "It's a massive mushroom... with legs?" + icon_state = "mushroom" + icon_living = "mushroom" + icon_dead = "mushroom_dead" + small = 1 + speak_chance = 0 + turns_per_move = 1 + maxHealth = 5 + health = 5 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "whacks the" harm_intent_damage = 5 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/slime.dm b/code/modules/mob/living/simple_animal/friendly/slime.dm index 010d4239480..a3ddace924a 100644 --- a/code/modules/mob/living/simple_animal/friendly/slime.dm +++ b/code/modules/mob/living/simple_animal/friendly/slime.dm @@ -1,86 +1,86 @@ -/mob/living/simple_animal/slime - name = "pet slime" - desc = "A lovable, domesticated slime." - icon = 'icons/mob/slimes.dmi' - icon_state = "grey baby slime" - icon_living = "grey baby slime" - icon_dead = "grey baby slime dead" - speak_emote = list("chirps") - health = 100 - maxHealth = 100 - response_help = "pets" - response_disarm = "shoos" - response_harm = "stomps on" - emote_see = list("jiggles", "bounces in place") - var/colour = "grey" - - can_butcher = 0 - meat_type = null - - mob_bump_flag = SLIME - mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL - mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL - - -/mob/living/simple_animal/adultslime - name = "pet slime" - desc = "A lovable, domesticated slime." - icon = 'icons/mob/slimes.dmi' - health = 200 - maxHealth = 200 - icon_state = "grey adult slime" - icon_living = "grey adult slime" - icon_dead = "grey baby slime dead" - response_help = "pets" - response_disarm = "shoos" - response_harm = "stomps on" - emote_see = list("jiggles", "bounces in place") - - size = SIZE_BIG - can_butcher = 0 - meat_type = null - - var/colour = "grey" - -/mob/living/simple_animal/adultslime/New() - ..() - overlays += "aslime-:33" - - -/mob/living/simple_animal/adultslime/Die() - var/mob/living/simple_animal/slime/S1 = new /mob/living/simple_animal/slime (src.loc) - S1.icon_state = "[src.colour] baby slime" - S1.icon_living = "[src.colour] baby slime" - S1.icon_dead = "[src.colour] baby slime dead" - S1.colour = "[src.colour]" - var/mob/living/simple_animal/slime/S2 = new /mob/living/simple_animal/slime (src.loc) - S2.icon_state = "[src.colour] baby slime" - S2.icon_living = "[src.colour] baby slime" - S2.icon_dead = "[src.colour] baby slime dead" - S2.colour = "[src.colour]" - qdel(src) - - -/mob/living/simple_animal/slime/proc/rabid() - if(stat) - return - if(client) - return - var/mob/living/simple_animal/hostile/slime/pet = new /mob/living/simple_animal/hostile/slime(loc) - pet.icon_state = "[colour] baby slime eat" - pet.icon_living = "[colour] baby slime eat" - pet.icon_dead = "[colour] baby slime dead" - pet.colour = "[colour]" - qdel (src) - -/mob/living/simple_animal/adultslime/proc/rabid() - if(stat) - return - if(client) - return - var/mob/living/simple_animal/hostile/slime/adult/pet = new /mob/living/simple_animal/hostile/slime/adult(loc) - pet.icon_state = "[colour] baby adult eat" - pet.icon_living = "[colour] baby adult eat" - pet.icon_dead = "[colour] baby slime dead" - pet.colour = "[colour]" +/mob/living/simple_animal/slime + name = "pet slime" + desc = "A lovable, domesticated slime." + icon = 'icons/mob/slimes.dmi' + icon_state = "grey baby slime" + icon_living = "grey baby slime" + icon_dead = "grey baby slime dead" + speak_emote = list("chirps") + health = 100 + maxHealth = 100 + response_help = "pets" + response_disarm = "shoos" + response_harm = "stomps on" + emote_see = list("jiggles", "bounces in place") + var/colour = "grey" + + can_butcher = 0 + meat_type = null + + mob_bump_flag = SLIME + mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL + mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL + + +/mob/living/simple_animal/adultslime + name = "pet slime" + desc = "A lovable, domesticated slime." + icon = 'icons/mob/slimes.dmi' + health = 200 + maxHealth = 200 + icon_state = "grey adult slime" + icon_living = "grey adult slime" + icon_dead = "grey baby slime dead" + response_help = "pets" + response_disarm = "shoos" + response_harm = "stomps on" + emote_see = list("jiggles", "bounces in place") + + size = SIZE_BIG + can_butcher = 0 + meat_type = null + + var/colour = "grey" + +/mob/living/simple_animal/adultslime/New() + ..() + overlays += "aslime-:33" + + +/mob/living/simple_animal/adultslime/Die() + var/mob/living/simple_animal/slime/S1 = new /mob/living/simple_animal/slime (src.loc) + S1.icon_state = "[src.colour] baby slime" + S1.icon_living = "[src.colour] baby slime" + S1.icon_dead = "[src.colour] baby slime dead" + S1.colour = "[src.colour]" + var/mob/living/simple_animal/slime/S2 = new /mob/living/simple_animal/slime (src.loc) + S2.icon_state = "[src.colour] baby slime" + S2.icon_living = "[src.colour] baby slime" + S2.icon_dead = "[src.colour] baby slime dead" + S2.colour = "[src.colour]" + qdel(src) + + +/mob/living/simple_animal/slime/proc/rabid() + if(stat) + return + if(client) + return + var/mob/living/simple_animal/hostile/slime/pet = new /mob/living/simple_animal/hostile/slime(loc) + pet.icon_state = "[colour] baby slime eat" + pet.icon_living = "[colour] baby slime eat" + pet.icon_dead = "[colour] baby slime dead" + pet.colour = "[colour]" + qdel (src) + +/mob/living/simple_animal/adultslime/proc/rabid() + if(stat) + return + if(client) + return + var/mob/living/simple_animal/hostile/slime/adult/pet = new /mob/living/simple_animal/hostile/slime/adult(loc) + pet.icon_state = "[colour] baby adult eat" + pet.icon_living = "[colour] baby adult eat" + pet.icon_dead = "[colour] baby slime dead" + pet.colour = "[colour]" qdel (src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/tomato.dm b/code/modules/mob/living/simple_animal/friendly/tomato.dm index 1248e702d2d..1f1b9de6d27 100644 --- a/code/modules/mob/living/simple_animal/friendly/tomato.dm +++ b/code/modules/mob/living/simple_animal/friendly/tomato.dm @@ -1,15 +1,15 @@ -/mob/living/simple_animal/tomato - name = "tomato" - desc = "It's a horrifyingly enormous beef tomato, and it's packing extra beef!" - icon_state = "tomato" - icon_living = "tomato" - icon_dead = "tomato_dead" - speak_chance = 0 - turns_per_move = 5 - maxHealth = 15 - health = 15 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/tomatomeat - response_help = "prods the" - response_disarm = "pushes aside the" - response_harm = "smacks the" +/mob/living/simple_animal/tomato + name = "tomato" + desc = "It's a horrifyingly enormous beef tomato, and it's packing extra beef!" + icon_state = "tomato" + icon_living = "tomato" + icon_dead = "tomato_dead" + speak_chance = 0 + turns_per_move = 5 + maxHealth = 15 + health = 15 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/tomatomeat + response_help = "prods the" + response_disarm = "pushes aside the" + response_harm = "smacks the" harm_intent_damage = 5 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 3d2b816a81f..534584f3e1c 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -1,120 +1,120 @@ -/mob/living/simple_animal/hostile/alien - name = "alien hunter" - desc = "Hiss!" - icon = 'icons/mob/alien.dmi' - icon_state = "alienh_running" - icon_living = "alienh_running" - icon_dead = "alienh_dead" - icon_gib = "syndicate_gib" - response_help = "pokes the" - response_disarm = "shoves the" - response_harm = "hits the" - speed = -1 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat - species_type = /mob/living/simple_animal/hostile/alien - maxHealth = 100 - health = 100 - harm_intent_damage = 5 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "slashes" - a_intent = I_HURT - attack_sound = 'sound/weapons/bladeslice.ogg' - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - unsuitable_atoms_damage = 15 - faction = "alien" - environment_smash = 2 - status_flags = CANPUSH - minbodytemp = 0 - heat_damage_per_tick = 20 - treadmill_speed = 4 //Not as insane as it seems, because of their slow default move rate, this is more like a functional 2x human - - -/mob/living/simple_animal/hostile/alien/drone - name = "alien drone" - icon_state = "aliend_running" - icon_living = "aliend_running" - icon_dead = "aliend_dead" - health = 60 - melee_damage_lower = 15 - melee_damage_upper = 15 - -/mob/living/simple_animal/hostile/alien/sentinel - name = "alien sentinel" - icon_state = "aliens_running" - icon_living = "aliens_running" - icon_dead = "aliens_dead" - health = 120 - melee_damage_lower = 15 - melee_damage_upper = 15 - ranged = 1 - projectiletype = /obj/item/projectile/neurotox - projectilesound = 'sound/weapons/pierce.ogg' - - -/mob/living/simple_animal/hostile/alien/queen - name = "alien queen" - icon_state = "alienq_running" - icon_living = "alienq_running" - icon_dead = "alienq_dead" - health = 250 - maxHealth = 250 - melee_damage_lower = 15 - melee_damage_upper = 15 - ranged = 1 - move_to_delay = 3 - projectiletype = /obj/item/projectile/neurotox - projectilesound = 'sound/weapons/pierce.ogg' - rapid = 1 - status_flags = 0 - -/mob/living/simple_animal/hostile/alien/queen/large - name = "alien empress" - icon = 'icons/mob/alienqueen.dmi' - icon_state = "queen_s" - icon_living = "queen_s" - icon_dead = "queen_dead" - move_to_delay = 4 - maxHealth = 400 - health = 400 - pixel_x = -16 - -/obj/item/projectile/neurotox - damage = 30 - icon_state = "toxin" - -/mob/living/simple_animal/hostile/alien/Die() - ..() - visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...") - playsound(src, 'sound/voice/hiss6.ogg', 100, 1) - -/mob/living/simple_animal/hostile/alien/gib() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-a", sleeptime = 15) - xgibs(loc, viruses) - dead_mob_list -= src - - qdel(src) - -/mob/living/simple_animal/hostile/alien/CanAttack(var/atom/the_target) - if(isalien(the_target)) - return 0 - return ..(the_target) - -/mob/living/simple_animal/hostile/alien/adjustBruteLoss(amount,var/damage_type) // Weak to Fire - if(damage_type == BURN) - ..(amount * 2) - else - ..(amount) +/mob/living/simple_animal/hostile/alien + name = "alien hunter" + desc = "Hiss!" + icon = 'icons/mob/alien.dmi' + icon_state = "alienh_running" + icon_living = "alienh_running" + icon_dead = "alienh_dead" + icon_gib = "syndicate_gib" + response_help = "pokes the" + response_disarm = "shoves the" + response_harm = "hits the" + speed = -1 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/xenomeat + species_type = /mob/living/simple_animal/hostile/alien + maxHealth = 100 + health = 100 + harm_intent_damage = 5 + melee_damage_lower = 25 + melee_damage_upper = 25 + attacktext = "slashes" + a_intent = I_HURT + attack_sound = 'sound/weapons/bladeslice.ogg' + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + unsuitable_atoms_damage = 15 + faction = "alien" + environment_smash = 2 + status_flags = CANPUSH + minbodytemp = 0 + heat_damage_per_tick = 20 + treadmill_speed = 4 //Not as insane as it seems, because of their slow default move rate, this is more like a functional 2x human + + +/mob/living/simple_animal/hostile/alien/drone + name = "alien drone" + icon_state = "aliend_running" + icon_living = "aliend_running" + icon_dead = "aliend_dead" + health = 60 + melee_damage_lower = 15 + melee_damage_upper = 15 + +/mob/living/simple_animal/hostile/alien/sentinel + name = "alien sentinel" + icon_state = "aliens_running" + icon_living = "aliens_running" + icon_dead = "aliens_dead" + health = 120 + melee_damage_lower = 15 + melee_damage_upper = 15 + ranged = 1 + projectiletype = /obj/item/projectile/neurotox + projectilesound = 'sound/weapons/pierce.ogg' + + +/mob/living/simple_animal/hostile/alien/queen + name = "alien queen" + icon_state = "alienq_running" + icon_living = "alienq_running" + icon_dead = "alienq_dead" + health = 250 + maxHealth = 250 + melee_damage_lower = 15 + melee_damage_upper = 15 + ranged = 1 + move_to_delay = 3 + projectiletype = /obj/item/projectile/neurotox + projectilesound = 'sound/weapons/pierce.ogg' + rapid = 1 + status_flags = 0 + +/mob/living/simple_animal/hostile/alien/queen/large + name = "alien empress" + icon = 'icons/mob/alienqueen.dmi' + icon_state = "queen_s" + icon_living = "queen_s" + icon_dead = "queen_dead" + move_to_delay = 4 + maxHealth = 400 + health = 400 + pixel_x = -16 + +/obj/item/projectile/neurotox + damage = 30 + icon_state = "toxin" + +/mob/living/simple_animal/hostile/alien/Die() + ..() + visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...") + playsound(src, 'sound/voice/hiss6.ogg', 100, 1) + +/mob/living/simple_animal/hostile/alien/gib() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "gibbed-a", sleeptime = 15) + xgibs(loc, viruses) + dead_mob_list -= src + + qdel(src) + +/mob/living/simple_animal/hostile/alien/CanAttack(var/atom/the_target) + if(isalien(the_target)) + return 0 + return ..(the_target) + +/mob/living/simple_animal/hostile/alien/adjustBruteLoss(amount,var/damage_type) // Weak to Fire + if(damage_type == BURN) + ..(amount * 2) + else + ..(amount) diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 99727f2b717..e425ce221c0 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -1,129 +1,129 @@ -#define PHEROMONES_NO_EFFECT 0 -#define PHEROMONES_NEUTRAL 1 -#define PHEROMONES_FOLLOW 2 - -/mob/living/simple_animal/hostile/carp - name = "space carp" - desc = "A ferocious, fang-bearing creature that resembles a fish." - icon_state = "carp" - icon_living = "carp" - icon_dead = "carp_dead" - icon_gib = "carp_gib" - speak_chance = 0 - turns_per_move = 5 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" - speed = -1 - maxHealth = 25 - health = 25 - size = SIZE_SMALL - - can_breed = 1 - childtype = /mob/living/simple_animal/hostile/carp/baby - child_amount = 1 - holder_type = /obj/item/weapon/holder/animal/carp - - - harm_intent_damage = 8 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "bites" - attack_sound = 'sound/weapons/bite.ogg' - - //Space carp aren't affected by atmos. - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - - faction = "carp" - - var/pheromones_act = PHEROMONES_NEUTRAL //This variable determines how carps act to pheromones. Big carps won't attack the source, - //baby carps follow the source and holocarps don't give a shit - -/mob/living/simple_animal/hostile/carp/New() - .=..() - gender = pick(MALE, FEMALE) - if(gender==FEMALE) - child_amount = rand(4,6) //Mother explodes on death, so letting it leave 5 child carps (that can't breed) behind is fair - -/mob/living/simple_animal/hostile/carp/examine(mob/user) - ..() - if(Adjacent(user)) +#define PHEROMONES_NO_EFFECT 0 +#define PHEROMONES_NEUTRAL 1 +#define PHEROMONES_FOLLOW 2 + +/mob/living/simple_animal/hostile/carp + name = "space carp" + desc = "A ferocious, fang-bearing creature that resembles a fish." + icon_state = "carp" + icon_living = "carp" + icon_dead = "carp_dead" + icon_gib = "carp_gib" + speak_chance = 0 + turns_per_move = 5 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/carpmeat + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "hits" + speed = -1 + maxHealth = 25 + health = 25 + size = SIZE_SMALL + + can_breed = 1 + childtype = /mob/living/simple_animal/hostile/carp/baby + child_amount = 1 + holder_type = /obj/item/weapon/holder/animal/carp + + + harm_intent_damage = 8 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "bites" + attack_sound = 'sound/weapons/bite.ogg' + + //Space carp aren't affected by atmos. + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + + faction = "carp" + + var/pheromones_act = PHEROMONES_NEUTRAL //This variable determines how carps act to pheromones. Big carps won't attack the source, + //baby carps follow the source and holocarps don't give a shit + +/mob/living/simple_animal/hostile/carp/New() + .=..() + gender = pick(MALE, FEMALE) + if(gender==FEMALE) + child_amount = rand(4,6) //Mother explodes on death, so letting it leave 5 child carps (that can't breed) behind is fair + +/mob/living/simple_animal/hostile/carp/examine(mob/user) + ..() + if(Adjacent(user)) to_chat(user, "It appears to be [(gender==MALE) ? "male" : "female"].") - -/mob/living/simple_animal/hostile/carp/give_birth() - spawn(rand(100,200)) - if(!src) return - - src.death(0) - sleep(30) - src.visible_message("[src]'s body explodes in a shower of gore as its offspring burst out!") - ..() - src.gib(meat=0) - -/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/check_drift = 0) - return 1 //No drifting in space for space carp! //original comments do not steal - -/mob/living/simple_animal/hostile/carp/CanAttack(var/atom/the_target) - if(ismob(the_target) && the_target.reagents) - if(pheromones_act == PHEROMONES_NEUTRAL && the_target.reagents.has_reagent("carppheromones")) - return 0 //Carps who avoid pheromones don't target mobs with pheromones in their system. They just ignore them! - return ..(the_target) - -/mob/living/simple_animal/hostile/carp/FindTarget() - . = ..() - if(.) - emote("nashes at [.]") - -/mob/living/simple_animal/hostile/carp/AttackingTarget() - if(!target) return - - if(pheromones_act == PHEROMONES_FOLLOW && target.reagents && target.reagents.has_reagent("carppheromones")) - return //This might be a bit hacky. The purpose of this is to prevent carps who are attracted to pheromones from attacking - //the source. Instead, it simply follows it. - - . =..() - var/mob/living/carbon/L = . - if(istype(L)) - if(prob(15)) - L.Weaken(3) - L.visible_message("\the [src] knocks down \the [L]!") - -/mob/living/simple_animal/hostile/carp/baby - desc = "A ferocious, fang-bearing creature that resembles a fish. This one, despite not being mature yet, is just as agressive as any of its brethren." - icon_state = "babycarp" - icon_dead = "babycarp_dead" - - size = SIZE_TINY - can_breed = 0 - - maxHealth = 15 - health = 15 - - melee_damage_upper = 8 - melee_damage_lower = 8 - - pheromones_act = PHEROMONES_FOLLOW - -/mob/living/simple_animal/hostile/carp/holocarp - icon_state = "holocarp" - icon_living = "holocarp" - can_breed = 0 - pheromones_act = PHEROMONES_NO_EFFECT - holder_type = null - -/mob/living/simple_animal/hostile/carp/holocarp/Die() - qdel(src) - return - -#undef PHEROMONES_NO_EFFECT -#undef PHEROMONES_NEUTRAL -#undef PHEROMONES_FOLLOW + +/mob/living/simple_animal/hostile/carp/give_birth() + spawn(rand(100,200)) + if(!src) return + + src.death(0) + sleep(30) + src.visible_message("[src]'s body explodes in a shower of gore as its offspring burst out!") + ..() + src.gib(meat=0) + +/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/check_drift = 0) + return 1 //No drifting in space for space carp! //original comments do not steal + +/mob/living/simple_animal/hostile/carp/CanAttack(var/atom/the_target) + if(ismob(the_target) && the_target.reagents) + if(pheromones_act == PHEROMONES_NEUTRAL && the_target.reagents.has_reagent("carppheromones")) + return 0 //Carps who avoid pheromones don't target mobs with pheromones in their system. They just ignore them! + return ..(the_target) + +/mob/living/simple_animal/hostile/carp/FindTarget() + . = ..() + if(.) + emote("nashes at [.]") + +/mob/living/simple_animal/hostile/carp/AttackingTarget() + if(!target) return + + if(pheromones_act == PHEROMONES_FOLLOW && target.reagents && target.reagents.has_reagent("carppheromones")) + return //This might be a bit hacky. The purpose of this is to prevent carps who are attracted to pheromones from attacking + //the source. Instead, it simply follows it. + + . =..() + var/mob/living/carbon/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(3) + L.visible_message("\the [src] knocks down \the [L]!") + +/mob/living/simple_animal/hostile/carp/baby + desc = "A ferocious, fang-bearing creature that resembles a fish. This one, despite not being mature yet, is just as agressive as any of its brethren." + icon_state = "babycarp" + icon_dead = "babycarp_dead" + + size = SIZE_TINY + can_breed = 0 + + maxHealth = 15 + health = 15 + + melee_damage_upper = 8 + melee_damage_lower = 8 + + pheromones_act = PHEROMONES_FOLLOW + +/mob/living/simple_animal/hostile/carp/holocarp + icon_state = "holocarp" + icon_living = "holocarp" + can_breed = 0 + pheromones_act = PHEROMONES_NO_EFFECT + holder_type = null + +/mob/living/simple_animal/hostile/carp/holocarp/Die() + qdel(src) + return + +#undef PHEROMONES_NO_EFFECT +#undef PHEROMONES_NEUTRAL +#undef PHEROMONES_FOLLOW diff --git a/code/modules/mob/living/simple_animal/hostile/creature.dm b/code/modules/mob/living/simple_animal/hostile/creature.dm index 1000a27037c..a0d3aea63cc 100644 --- a/code/modules/mob/living/simple_animal/hostile/creature.dm +++ b/code/modules/mob/living/simple_animal/hostile/creature.dm @@ -1,82 +1,82 @@ -/mob/living/simple_animal/hostile/creature - name = "creature" - desc = "A sanity-destroying otherthing." - speak_emote = list("gibbers") - icon_state = "otherthing" - icon_living = "otherthing" - icon_dead = "otherthing-dead" - health = 80 - maxHealth = 80 - melee_damage_lower = 25 - melee_damage_upper = 50 - attacktext = "chomps" - attack_sound = 'sound/weapons/bite.ogg' - faction = "creature" - speed = 4 - size = SIZE_BIG - -/mob/living/simple_animal/hostile/creature/cult - faction = "cult" - var/shuttletarget = null - var/enroute = 0 - - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - - supernatural = 1 - -/mob/living/simple_animal/hostile/creature/cult/CanAttack(var/atom/the_target) - //IF WE ARE CULT MONSTERS (those who spawn after Nar-Sie has risen) THEN WE DON'T ATTACK CULTISTS - if(iscultist(the_target)) - return 0 - return ..(the_target) - -/mob/living/simple_animal/hostile/creature/cult/cultify() - return - -/mob/living/simple_animal/hostile/creature/cult/Life() - if(timestopped) return 0 //under effects of time magick - ..() - if(emergency_shuttle.location == 1) - if(!enroute && !target) //The shuttle docked, all monsters rush for the escape hallway - if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick - shuttletarget = pick(escape_list) //Pick a shuttle target - enroute = 1 - stop_automated_movement = 1 -/* spawn() - if(!src.stat) - horde()*/ - - if(get_dist(src, shuttletarget) <= 2) //The monster reached the escape hallway - enroute = 0 - stop_automated_movement = 0 - -/mob/living/simple_animal/hostile/creature/cult/proc/horde() - var/turf/T = get_step_to(src, shuttletarget) - for(var/atom/A in T) - if(istype(A,/obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/D = A - if(D.density && !D.locked && !D.welded) - D.open() - else if(istype(A,/obj/machinery/door/mineral)) - var/obj/machinery/door/D = A - if(D.density) - D.open() - else if(istype(A,/obj/structure/cult/pylon)) - A.attack_animal(src) - else if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) - A.attack_animal(src) - Move(T) - var/new_target = FindTarget() - GiveTarget(new_target) - if(!target || enroute) - spawn(10) - if(!src.stat) +/mob/living/simple_animal/hostile/creature + name = "creature" + desc = "A sanity-destroying otherthing." + speak_emote = list("gibbers") + icon_state = "otherthing" + icon_living = "otherthing" + icon_dead = "otherthing-dead" + health = 80 + maxHealth = 80 + melee_damage_lower = 25 + melee_damage_upper = 50 + attacktext = "chomps" + attack_sound = 'sound/weapons/bite.ogg' + faction = "creature" + speed = 4 + size = SIZE_BIG + +/mob/living/simple_animal/hostile/creature/cult + faction = "cult" + var/shuttletarget = null + var/enroute = 0 + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + + supernatural = 1 + +/mob/living/simple_animal/hostile/creature/cult/CanAttack(var/atom/the_target) + //IF WE ARE CULT MONSTERS (those who spawn after Nar-Sie has risen) THEN WE DON'T ATTACK CULTISTS + if(iscultist(the_target)) + return 0 + return ..(the_target) + +/mob/living/simple_animal/hostile/creature/cult/cultify() + return + +/mob/living/simple_animal/hostile/creature/cult/Life() + if(timestopped) return 0 //under effects of time magick + ..() + if(emergency_shuttle.location == 1) + if(!enroute && !target) //The shuttle docked, all monsters rush for the escape hallway + if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick + shuttletarget = pick(escape_list) //Pick a shuttle target + enroute = 1 + stop_automated_movement = 1 +/* spawn() + if(!src.stat) + horde()*/ + + if(get_dist(src, shuttletarget) <= 2) //The monster reached the escape hallway + enroute = 0 + stop_automated_movement = 0 + +/mob/living/simple_animal/hostile/creature/cult/proc/horde() + var/turf/T = get_step_to(src, shuttletarget) + for(var/atom/A in T) + if(istype(A,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/D = A + if(D.density && !D.locked && !D.welded) + D.open() + else if(istype(A,/obj/machinery/door/mineral)) + var/obj/machinery/door/D = A + if(D.density) + D.open() + else if(istype(A,/obj/structure/cult/pylon)) + A.attack_animal(src) + else if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) + A.attack_animal(src) + Move(T) + var/new_target = FindTarget() + GiveTarget(new_target) + if(!target || enroute) + spawn(10) + if(!src.stat) horde() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index 10f12f5beca..96158244341 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -1,106 +1,106 @@ -/mob/living/simple_animal/hostile/faithless - name = "The Faithless" - desc = "The Wish Granter's faith in humanity, incarnate" - icon_state = "faithless" - icon_living = "faithless" - icon_dead = "faithless_dead" - speak_chance = 0 - turns_per_move = 5 - response_help = "passes through" - response_disarm = "shoves" - response_harm = "hits" - speed = -1 - maxHealth = 80 - health = 80 - can_butcher = 0 - - harm_intent_damage = 10 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "grips" - attack_sound = 'sound/hallucinations/growl1.ogg' - - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - speed = 4 - - supernatural = 1 - - faction = "faithless" - -/mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/check_drift = 0) - return 1 - -/mob/living/simple_animal/hostile/faithless/FindTarget() - . = ..() - if(.) - emote("wails at [.]") - -/mob/living/simple_animal/hostile/faithless/AttackingTarget() - . =..() - var/mob/living/L = . - if(istype(L)) - if(prob(12)) - L.Weaken(3) - L.visible_message("\the [src] knocks down \the [L]!") - -/mob/living/simple_animal/hostile/faithless/cult - faction = "cult" - var/shuttletarget = null - var/enroute = 0 - -/mob/living/simple_animal/hostile/faithless/cult/CanAttack(var/atom/the_target) - //IF WE ARE CULT MONSTERS (those who spawn after Nar-Sie has risen) THEN WE DON'T ATTACK CULTISTS - if(iscultist(the_target)) - return 0 - return ..(the_target) - -/mob/living/simple_animal/hostile/faithless/cult/cultify() - return - -/mob/living/simple_animal/hostile/faithless/cult/Life() - if(timestopped) return 0 //under effects of time magick - ..() - if(emergency_shuttle.location == 1) - if(!enroute && !target) //The shuttle docked, all monsters rush for the escape hallway - if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick - shuttletarget = pick(escape_list) //Pick a shuttle target - enroute = 1 - stop_automated_movement = 1 -/* spawn() - if(!src.stat) - horde()*/ - - if(get_dist(src, shuttletarget) <= 2) //The monster reached the escape hallway - enroute = 0 - stop_automated_movement = 0 - -/mob/living/simple_animal/hostile/faithless/cult/proc/horde() - var/turf/T = get_step_to(src, shuttletarget) - for(var/atom/A in T) - if(istype(A,/obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/D = A - if(D.density && !D.locked && !D.welded) - D.open() - else if(istype(A,/obj/machinery/door/mineral)) - var/obj/machinery/door/D = A - if(D.density) - D.open() - else if(istype(A,/obj/structure/cult/pylon)) - A.attack_animal(src) - else if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) - A.attack_animal(src) - Move(T) - var/new_target = FindTarget() - GiveTarget(new_target) - if(!target || enroute) - spawn(10) - if(!src.stat) +/mob/living/simple_animal/hostile/faithless + name = "The Faithless" + desc = "The Wish Granter's faith in humanity, incarnate" + icon_state = "faithless" + icon_living = "faithless" + icon_dead = "faithless_dead" + speak_chance = 0 + turns_per_move = 5 + response_help = "passes through" + response_disarm = "shoves" + response_harm = "hits" + speed = -1 + maxHealth = 80 + health = 80 + can_butcher = 0 + + harm_intent_damage = 10 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "grips" + attack_sound = 'sound/hallucinations/growl1.ogg' + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + speed = 4 + + supernatural = 1 + + faction = "faithless" + +/mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/check_drift = 0) + return 1 + +/mob/living/simple_animal/hostile/faithless/FindTarget() + . = ..() + if(.) + emote("wails at [.]") + +/mob/living/simple_animal/hostile/faithless/AttackingTarget() + . =..() + var/mob/living/L = . + if(istype(L)) + if(prob(12)) + L.Weaken(3) + L.visible_message("\the [src] knocks down \the [L]!") + +/mob/living/simple_animal/hostile/faithless/cult + faction = "cult" + var/shuttletarget = null + var/enroute = 0 + +/mob/living/simple_animal/hostile/faithless/cult/CanAttack(var/atom/the_target) + //IF WE ARE CULT MONSTERS (those who spawn after Nar-Sie has risen) THEN WE DON'T ATTACK CULTISTS + if(iscultist(the_target)) + return 0 + return ..(the_target) + +/mob/living/simple_animal/hostile/faithless/cult/cultify() + return + +/mob/living/simple_animal/hostile/faithless/cult/Life() + if(timestopped) return 0 //under effects of time magick + ..() + if(emergency_shuttle.location == 1) + if(!enroute && !target) //The shuttle docked, all monsters rush for the escape hallway + if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick + shuttletarget = pick(escape_list) //Pick a shuttle target + enroute = 1 + stop_automated_movement = 1 +/* spawn() + if(!src.stat) + horde()*/ + + if(get_dist(src, shuttletarget) <= 2) //The monster reached the escape hallway + enroute = 0 + stop_automated_movement = 0 + +/mob/living/simple_animal/hostile/faithless/cult/proc/horde() + var/turf/T = get_step_to(src, shuttletarget) + for(var/atom/A in T) + if(istype(A,/obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/D = A + if(D.density && !D.locked && !D.welded) + D.open() + else if(istype(A,/obj/machinery/door/mineral)) + var/obj/machinery/door/D = A + if(D.density) + D.open() + else if(istype(A,/obj/structure/cult/pylon)) + A.attack_animal(src) + else if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) + A.attack_animal(src) + Move(T) + var/new_target = FindTarget() + GiveTarget(new_target) + if(!target || enroute) + spawn(10) + if(!src.stat) horde() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 5db494a4116..5be70dc3bfe 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -1,345 +1,345 @@ -/mob/living/simple_animal/hostile - faction = "hostile" - stop_automated_movement_when_pulled = 0 - environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls - - var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior - var/atom/target // /vg/ edit: Removed type specification so spiders can target doors. - var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction - var/ranged = 0 - var/rapid = 0 - var/projectiletype - var/projectilesound - var/casingtype - var/move_to_delay = 2 //delay for the automated movement. - var/list/friends = list() - var/vision_range = 9 //How big of an area to search for targets in, a vision of 9 attempts to find targets as soon as they walk into screen view - - var/aggro_vision_range = 9 //If a mob is aggro, we search in this radius. Defaults to 9 to keep in line with original simple mob aggro radius - var/idle_vision_range = 9 //If a mob is just idling around, it's vision range is limited to this. Defaults to 9 to keep in line with original simple mob aggro radius - var/ranged_message = "fires" //Fluff text for ranged mobs - var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks - var/ranged_cooldown_cap = 3 //What ranged attacks, after being used are set to, to go back on cooldown, defaults to 3 life() ticks - var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat. - var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance - var/search_objects = 0 //If we want to consider objects when searching around, set this to 1. If you want to search for objects while also ignoring mobs until hurt, set it to 2. To completely ignore mobs, even when attacked, set it to 3 - var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled - var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead. - var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses - var/attack_faction = null //Put a faction string here to have a mob only ever attack a specific faction - -/mob/living/simple_animal/hostile/resetVariables() - ..("wanted_objects", "friends", args) - wanted_objects = list() - friends = list() - -/mob/living/simple_animal/hostile/Life() - if(timestopped) return 0 //under effects of time magick - . = ..() - if(istype(loc, /obj/item/device/mobcapsule)) - return 0 - if(!.) - walk(src, 0) - return 0 - if(client && !deny_client_move) - return 0 - if(!stat) - if(size > SIZE_TINY && istype(loc, /obj/item/weapon/holder)) //If somebody picked us up and we're big enough to fight! - var/mob/living/L = loc.loc - if(!istype(L) || (L.faction != src.faction) || !CanAttack(L)) //If we're not being held by a mob, OR we're being held by a mob who isn't from our faction OR we're being held by a mob whom we don't consider a valid target! - returnToPool(loc) - else - return 0 - - switch(stance) - if(HOSTILE_STANCE_IDLE) - if(environment_smash) - EscapeConfinement() - var/new_target = FindTarget() - GiveTarget(new_target) - - if(HOSTILE_STANCE_ATTACK) - if(!(flags & INVULNERABLE)) - MoveToTarget() - DestroySurroundings() - - if(HOSTILE_STANCE_ATTACKING) - if(!(flags & INVULNERABLE)) - AttackTarget() - DestroySurroundings() - - if(ranged) - ranged_cooldown-- - -//////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// - - -/mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see - var/list/L = new() - - if (!search_objects) - L.Add(ohearers(vision_range, src)) - - for (var/obj/mecha/M in mechas_list) - if (get_dist(M, src) <= vision_range && can_see(src, M, vision_range)) - L.Add(M) - else - L.Add(oview(vision_range, src)) - - return L - -/mob/living/simple_animal/hostile/proc/FindTarget()//Step 2, filter down possible targets to things we actually care about - var/list/Targets = list() - var/Target - for(var/atom/A in ListTargets()) - if(Found(A))//Just in case people want to override targetting - var/list/FoundTarget = list() - FoundTarget += A - Targets = FoundTarget - break - if(CanAttack(A))//Can we attack it? - Targets += A - continue - Target = PickTarget(Targets) - return Target //We now have a target - -/mob/living/simple_animal/hostile/proc/Found(var/atom/A)//This is here as a potential override to pick a specific target if available - return - -/mob/living/simple_animal/hostile/proc/PickTarget(var/list/Targets)//Step 3, pick amongst the possible, attackable targets - if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets - for(var/atom/A in Targets) - var/target_dist = get_dist(src, target) - var/possible_target_distance = get_dist(src, A) - if(target_dist < possible_target_distance) - Targets -= A - if(!Targets.len)//We didnt find nothin! - return - var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random - return chosen_target - -/mob/living/simple_animal/hostile/CanAttack(var/atom/the_target)//Can we actually attack a possible target? - if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it - return 0 - if(isliving(the_target) && search_objects < 2) - var/mob/living/L = the_target - //WE ONLY ATTACK LIVING MOBS UNLESS SPECIFIED OTHERWISE - if(L.stat > stat_attack || (L.stat != stat_attack && stat_exclusive == 1)) - return 0 - //WE DON'T ATTACK INVULNERABLE MOBS (such as etheral jaunting mobs, or passengers of the adminbus) - if(L.flags & INVULNERABLE) - return 0 - //WE DON'T ATTACK MOMMI - if(isMoMMI(L)) - return 0 - //WE DON'T OUR OWN FACTION UNLESS SPECIFIED OTHERWISE - if((L.faction == src.faction && !attack_same) || (L.faction != src.faction && attack_same == 2) || (L.faction != attack_faction && attack_faction)) - return 0 - //IF OUR FACTION IS A REFERENCE TO A SPECIFIC MOB THEN WE DON'T ATTACK HIM (examples include viscerator grenades, staff of animation mimics, asteroid monsters) - if((faction == "\ref[L]") && !attack_same) - return 0 - //IF WE ARE GOLD SLIME+PLASMA MONSTERS THEN WE DON'T ATTACK SLIMES/SLIME PEOPLE/ADAMANTINE GOLEMS - if(faction == "slimesummon") - if(isslime(L)) - return 0 - if(ishuman(L)) - var/mob/living/carbon/human/H = L - if(H.dna) - if((H.dna.mutantrace == "slime") || (H.dna.mutantrace == "adamantine") || (H.dna.mutantrace=="coalgolem")) - return 0 - //IF WE ARE MOBS SPAWNED BY THE ADMINBUS THEN WE DON'T ATTACK TEST DUMMIES OR IAN (wait what? man that's snowflaky as fuck) - if((istype(L,/mob/living/simple_animal/corgi/Ian) || istype(L,/mob/living/carbon/human/dummy)) && (faction == "adminbus mob")) - return 0 - //WE DON'T ATTACK OUR FRIENDS (used by lazarus injectors, and rabid slimes) - if(L in friends) - return 0 - return 1 - if(isobj(the_target)) - //if(the_target.type in wanted_objects) - if(is_type_in_list(the_target,wanted_objects)) - return 1 - if(istype(the_target, /obj/mecha) && search_objects < 2) - var/obj/mecha/M = the_target - if(M.occupant)//Just so we don't attack empty mechs - if(CanAttack(M.occupant)) - return 1 - return 0 - -/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)//Step 4, give us our selected target - target = new_target - if(target != null) - Aggro() - stance = HOSTILE_STANCE_ATTACK - return - -/mob/living/simple_animal/hostile/proc/MoveToTarget()//Step 5, handle movement between us and our target - stop_automated_movement = 1 - if(!target || !CanAttack(target)) - LoseTarget() - return - if(target in ListTargets()) - var/target_distance = get_dist(src,target) - if(ranged)//We ranged? Shoot at em - if(target_distance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown - OpenFire(target) - if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack - AttackingTarget() - if(canmove) - if(retreat_distance != null && target_distance <= retreat_distance) //If we have a retreat distance, check if we need to run from our target - walk_away(src,target,retreat_distance,move_to_delay) - else - Goto(target,move_to_delay,minimum_distance)//Otherwise, get to our minimum distance so we chase them - return - if(target.loc != null && get_dist(src, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still - if(FindHidden(target) && environment_smash)//Check if he tried to hide in something to lose us - var/atom/A = target.loc - if(canmove) - Goto(A,move_to_delay,minimum_distance) - if(A.Adjacent(src)) - A.attack_animal(src) - return - else - LostTarget() - LostTarget() - -/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay, var/minimum_distance) - walk_to(src, target, minimum_distance, delay) - -/mob/living/simple_animal/hostile/adjustBruteLoss(var/damage) - ..(damage) - if(!stat && search_objects < 3)//Not unconscious, and we don't ignore mobs - if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight - search_objects = 0 - target = null - if(stance == HOSTILE_STANCE_IDLE)//If we took damage while idle, immediately attempt to find the source of it so we find a living target - Aggro() - var/new_target = FindTarget() - GiveTarget(new_target) - if(stance == HOSTILE_STANCE_ATTACK)//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one - if(target != null && prob(25)) - var/new_target = FindTarget() - GiveTarget(new_target) - -/mob/living/simple_animal/hostile/proc/AttackTarget() - - - stop_automated_movement = 1 - if(!target || !CanAttack(target)) - LoseTarget() - return 0 - if(!(target in ListTargets())) - LostTarget() - return 0 - if(isturf(loc) && target.Adjacent(src)) - AttackingTarget() - return 1 - -/mob/living/simple_animal/hostile/proc/AttackingTarget() - target.attack_animal(src) - -/mob/living/simple_animal/hostile/proc/Aggro() - vision_range = aggro_vision_range - -/mob/living/simple_animal/hostile/proc/LoseAggro() - stop_automated_movement = 0 - vision_range = idle_vision_range - -/mob/living/simple_animal/hostile/proc/LoseTarget() - stance = HOSTILE_STANCE_IDLE - target = null - walk(src, 0) - LoseAggro() - -/mob/living/simple_animal/hostile/proc/LostTarget() - stance = HOSTILE_STANCE_IDLE - walk(src, 0) - LoseAggro() - -//////////////END HOSTILE MOB TARGETTING AND AGGRESSION//////////// - -/mob/living/simple_animal/hostile/Die() - LoseAggro() - ..() - walk(src, 0) - -/mob/living/simple_animal/hostile/proc/OpenFire(var/target) - - - var/tturf = get_turf(target) - if(rapid) - spawn(1) - Shoot(tturf, src.loc, src) - if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) - if(casingtype) - new casingtype(get_turf(src)) - spawn(4) - Shoot(tturf, src.loc, src) - if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) - if(casingtype) - new casingtype(get_turf(src)) - spawn(6) - Shoot(tturf, src.loc, src) - if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) - if(casingtype) - new casingtype(get_turf(src)) - else - Shoot(tturf, src.loc, src) - if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) - if(casingtype) - new casingtype - ranged_cooldown = ranged_cooldown_cap - return - -/mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0) - if(target == start) - return - - var/obj/item/projectile/A = new projectiletype(user:loc) - playsound(user, projectilesound, 100, 1) - if(!A) return - - if (!istype(target, /turf)) - del(A) - return - A.current = target - - var/turf/T = get_turf(src) - var/turf/U = get_turf(target) - A.original = target - A.target = U - A.current = T - A.starting = T - A.yo = target:y - start:y - A.xo = target:x - start:x - spawn() - A.OnFired() - A.process() - return - -/mob/living/simple_animal/hostile/proc/DestroySurroundings() - if(environment_smash) - EscapeConfinement() - for(var/dir in cardinal) - var/turf/T = get_step(src, dir) - if(istype(T, /turf/simulated/wall) && T.Adjacent(src)) - T.attack_animal(src) - for(var/atom/A in T) - if(!A.Adjacent(src)) - continue - if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) - A.attack_animal(src) - return - -/mob/living/simple_animal/hostile/proc/EscapeConfinement() - if(locked_to) - locked_to.attack_animal(src) - if(!isturf(src.loc) && src.loc != null)//Did someone put us in something? - var/atom/A = src.loc - A.attack_animal(src)//Bang on it till we get out - return - -/mob/living/simple_animal/hostile/proc/FindHidden(var/atom/hidden_target) - if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper)) - return 1 - else - return 0 +/mob/living/simple_animal/hostile + faction = "hostile" + stop_automated_movement_when_pulled = 0 + environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls + + var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior + var/atom/target // /vg/ edit: Removed type specification so spiders can target doors. + var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction + var/ranged = 0 + var/rapid = 0 + var/projectiletype + var/projectilesound + var/casingtype + var/move_to_delay = 2 //delay for the automated movement. + var/list/friends = list() + var/vision_range = 9 //How big of an area to search for targets in, a vision of 9 attempts to find targets as soon as they walk into screen view + + var/aggro_vision_range = 9 //If a mob is aggro, we search in this radius. Defaults to 9 to keep in line with original simple mob aggro radius + var/idle_vision_range = 9 //If a mob is just idling around, it's vision range is limited to this. Defaults to 9 to keep in line with original simple mob aggro radius + var/ranged_message = "fires" //Fluff text for ranged mobs + var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks + var/ranged_cooldown_cap = 3 //What ranged attacks, after being used are set to, to go back on cooldown, defaults to 3 life() ticks + var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat. + var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance + var/search_objects = 0 //If we want to consider objects when searching around, set this to 1. If you want to search for objects while also ignoring mobs until hurt, set it to 2. To completely ignore mobs, even when attacked, set it to 3 + var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled + var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead. + var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses + var/attack_faction = null //Put a faction string here to have a mob only ever attack a specific faction + +/mob/living/simple_animal/hostile/resetVariables() + ..("wanted_objects", "friends", args) + wanted_objects = list() + friends = list() + +/mob/living/simple_animal/hostile/Life() + if(timestopped) return 0 //under effects of time magick + . = ..() + if(istype(loc, /obj/item/device/mobcapsule)) + return 0 + if(!.) + walk(src, 0) + return 0 + if(client && !deny_client_move) + return 0 + if(!stat) + if(size > SIZE_TINY && istype(loc, /obj/item/weapon/holder)) //If somebody picked us up and we're big enough to fight! + var/mob/living/L = loc.loc + if(!istype(L) || (L.faction != src.faction) || !CanAttack(L)) //If we're not being held by a mob, OR we're being held by a mob who isn't from our faction OR we're being held by a mob whom we don't consider a valid target! + returnToPool(loc) + else + return 0 + + switch(stance) + if(HOSTILE_STANCE_IDLE) + if(environment_smash) + EscapeConfinement() + var/new_target = FindTarget() + GiveTarget(new_target) + + if(HOSTILE_STANCE_ATTACK) + if(!(flags & INVULNERABLE)) + MoveToTarget() + DestroySurroundings() + + if(HOSTILE_STANCE_ATTACKING) + if(!(flags & INVULNERABLE)) + AttackTarget() + DestroySurroundings() + + if(ranged) + ranged_cooldown-- + +//////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// + + +/mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see + var/list/L = new() + + if (!search_objects) + L.Add(ohearers(vision_range, src)) + + for (var/obj/mecha/M in mechas_list) + if (get_dist(M, src) <= vision_range && can_see(src, M, vision_range)) + L.Add(M) + else + L.Add(oview(vision_range, src)) + + return L + +/mob/living/simple_animal/hostile/proc/FindTarget()//Step 2, filter down possible targets to things we actually care about + var/list/Targets = list() + var/Target + for(var/atom/A in ListTargets()) + if(Found(A))//Just in case people want to override targetting + var/list/FoundTarget = list() + FoundTarget += A + Targets = FoundTarget + break + if(CanAttack(A))//Can we attack it? + Targets += A + continue + Target = PickTarget(Targets) + return Target //We now have a target + +/mob/living/simple_animal/hostile/proc/Found(var/atom/A)//This is here as a potential override to pick a specific target if available + return + +/mob/living/simple_animal/hostile/proc/PickTarget(var/list/Targets)//Step 3, pick amongst the possible, attackable targets + if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets + for(var/atom/A in Targets) + var/target_dist = get_dist(src, target) + var/possible_target_distance = get_dist(src, A) + if(target_dist < possible_target_distance) + Targets -= A + if(!Targets.len)//We didnt find nothin! + return + var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random + return chosen_target + +/mob/living/simple_animal/hostile/CanAttack(var/atom/the_target)//Can we actually attack a possible target? + if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it + return 0 + if(isliving(the_target) && search_objects < 2) + var/mob/living/L = the_target + //WE ONLY ATTACK LIVING MOBS UNLESS SPECIFIED OTHERWISE + if(L.stat > stat_attack || (L.stat != stat_attack && stat_exclusive == 1)) + return 0 + //WE DON'T ATTACK INVULNERABLE MOBS (such as etheral jaunting mobs, or passengers of the adminbus) + if(L.flags & INVULNERABLE) + return 0 + //WE DON'T ATTACK MOMMI + if(isMoMMI(L)) + return 0 + //WE DON'T OUR OWN FACTION UNLESS SPECIFIED OTHERWISE + if((L.faction == src.faction && !attack_same) || (L.faction != src.faction && attack_same == 2) || (L.faction != attack_faction && attack_faction)) + return 0 + //IF OUR FACTION IS A REFERENCE TO A SPECIFIC MOB THEN WE DON'T ATTACK HIM (examples include viscerator grenades, staff of animation mimics, asteroid monsters) + if((faction == "\ref[L]") && !attack_same) + return 0 + //IF WE ARE GOLD SLIME+PLASMA MONSTERS THEN WE DON'T ATTACK SLIMES/SLIME PEOPLE/ADAMANTINE GOLEMS + if(faction == "slimesummon") + if(isslime(L)) + return 0 + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(H.dna) + if((H.dna.mutantrace == "slime") || (H.dna.mutantrace == "adamantine") || (H.dna.mutantrace=="coalgolem")) + return 0 + //IF WE ARE MOBS SPAWNED BY THE ADMINBUS THEN WE DON'T ATTACK TEST DUMMIES OR IAN (wait what? man that's snowflaky as fuck) + if((istype(L,/mob/living/simple_animal/corgi/Ian) || istype(L,/mob/living/carbon/human/dummy)) && (faction == "adminbus mob")) + return 0 + //WE DON'T ATTACK OUR FRIENDS (used by lazarus injectors, and rabid slimes) + if(L in friends) + return 0 + return 1 + if(isobj(the_target)) + //if(the_target.type in wanted_objects) + if(is_type_in_list(the_target,wanted_objects)) + return 1 + if(istype(the_target, /obj/mecha) && search_objects < 2) + var/obj/mecha/M = the_target + if(M.occupant)//Just so we don't attack empty mechs + if(CanAttack(M.occupant)) + return 1 + return 0 + +/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)//Step 4, give us our selected target + target = new_target + if(target != null) + Aggro() + stance = HOSTILE_STANCE_ATTACK + return + +/mob/living/simple_animal/hostile/proc/MoveToTarget()//Step 5, handle movement between us and our target + stop_automated_movement = 1 + if(!target || !CanAttack(target)) + LoseTarget() + return + if(target in ListTargets()) + var/target_distance = get_dist(src,target) + if(ranged)//We ranged? Shoot at em + if(target_distance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown + OpenFire(target) + if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack + AttackingTarget() + if(canmove) + if(retreat_distance != null && target_distance <= retreat_distance) //If we have a retreat distance, check if we need to run from our target + walk_away(src,target,retreat_distance,move_to_delay) + else + Goto(target,move_to_delay,minimum_distance)//Otherwise, get to our minimum distance so we chase them + return + if(target.loc != null && get_dist(src, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still + if(FindHidden(target) && environment_smash)//Check if he tried to hide in something to lose us + var/atom/A = target.loc + if(canmove) + Goto(A,move_to_delay,minimum_distance) + if(A.Adjacent(src)) + A.attack_animal(src) + return + else + LostTarget() + LostTarget() + +/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay, var/minimum_distance) + walk_to(src, target, minimum_distance, delay) + +/mob/living/simple_animal/hostile/adjustBruteLoss(var/damage) + ..(damage) + if(!stat && search_objects < 3)//Not unconscious, and we don't ignore mobs + if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight + search_objects = 0 + target = null + if(stance == HOSTILE_STANCE_IDLE)//If we took damage while idle, immediately attempt to find the source of it so we find a living target + Aggro() + var/new_target = FindTarget() + GiveTarget(new_target) + if(stance == HOSTILE_STANCE_ATTACK)//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one + if(target != null && prob(25)) + var/new_target = FindTarget() + GiveTarget(new_target) + +/mob/living/simple_animal/hostile/proc/AttackTarget() + + + stop_automated_movement = 1 + if(!target || !CanAttack(target)) + LoseTarget() + return 0 + if(!(target in ListTargets())) + LostTarget() + return 0 + if(isturf(loc) && target.Adjacent(src)) + AttackingTarget() + return 1 + +/mob/living/simple_animal/hostile/proc/AttackingTarget() + target.attack_animal(src) + +/mob/living/simple_animal/hostile/proc/Aggro() + vision_range = aggro_vision_range + +/mob/living/simple_animal/hostile/proc/LoseAggro() + stop_automated_movement = 0 + vision_range = idle_vision_range + +/mob/living/simple_animal/hostile/proc/LoseTarget() + stance = HOSTILE_STANCE_IDLE + target = null + walk(src, 0) + LoseAggro() + +/mob/living/simple_animal/hostile/proc/LostTarget() + stance = HOSTILE_STANCE_IDLE + walk(src, 0) + LoseAggro() + +//////////////END HOSTILE MOB TARGETTING AND AGGRESSION//////////// + +/mob/living/simple_animal/hostile/Die() + LoseAggro() + ..() + walk(src, 0) + +/mob/living/simple_animal/hostile/proc/OpenFire(var/target) + + + var/tturf = get_turf(target) + if(rapid) + spawn(1) + Shoot(tturf, src.loc, src) + if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) + if(casingtype) + new casingtype(get_turf(src)) + spawn(4) + Shoot(tturf, src.loc, src) + if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) + if(casingtype) + new casingtype(get_turf(src)) + spawn(6) + Shoot(tturf, src.loc, src) + if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) + if(casingtype) + new casingtype(get_turf(src)) + else + Shoot(tturf, src.loc, src) + if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) + if(casingtype) + new casingtype + ranged_cooldown = ranged_cooldown_cap + return + +/mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0) + if(target == start) + return + + var/obj/item/projectile/A = new projectiletype(user:loc) + playsound(user, projectilesound, 100, 1) + if(!A) return + + if (!istype(target, /turf)) + del(A) + return + A.current = target + + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + A.original = target + A.target = U + A.current = T + A.starting = T + A.yo = target:y - start:y + A.xo = target:x - start:x + spawn() + A.OnFired() + A.process() + return + +/mob/living/simple_animal/hostile/proc/DestroySurroundings() + if(environment_smash) + EscapeConfinement() + for(var/dir in cardinal) + var/turf/T = get_step(src, dir) + if(istype(T, /turf/simulated/wall) && T.Adjacent(src)) + T.attack_animal(src) + for(var/atom/A in T) + if(!A.Adjacent(src)) + continue + if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) + A.attack_animal(src) + return + +/mob/living/simple_animal/hostile/proc/EscapeConfinement() + if(locked_to) + locked_to.attack_animal(src) + if(!isturf(src.loc) && src.loc != null)//Did someone put us in something? + var/atom/A = src.loc + A.attack_animal(src)//Bang on it till we get out + return + +/mob/living/simple_animal/hostile/proc/FindHidden(var/atom/hidden_target) + if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper)) + return 1 + else + return 0 diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm index 75e1afc8291..66fc7dc5271 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -1,39 +1,39 @@ -/mob/living/simple_animal/hostile/retaliate/clown - name = "clown" - desc = "A denizen of clown planet" - icon_state = "clown" - icon_living = "clown" - icon_dead = "clown_dead" - icon_gib = "clown_gib" - speak_chance = 0 - turns_per_move = 5 - response_help = "pokes" - response_disarm = "gently pushes aside" - response_harm = "hits" - speak = list("HONK", "Honk!", "Welcome to clown planet!") - emote_see = list("honks") - speak_chance = 1 - a_intent = I_HURT - stop_automated_movement_when_pulled = 0 - maxHealth = 75 - health = 75 - speed = -1 - harm_intent_damage = 8 - melee_damage_lower = 10 - melee_damage_upper = 10 - attacktext = "attacks" - attack_sound = 'sound/items/bikehorn.ogg' - - min_oxy = 5 - max_oxy = 0 - min_tox = 0 - max_tox = 1 - min_co2 = 0 - max_co2 = 5 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 270 - maxbodytemp = 370 - heat_damage_per_tick = 15 //amount of damage applied if animal's body temperature is higher than maxbodytemp - cold_damage_per_tick = 10 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp - unsuitable_atoms_damage = 10 +/mob/living/simple_animal/hostile/retaliate/clown + name = "clown" + desc = "A denizen of clown planet" + icon_state = "clown" + icon_living = "clown" + icon_dead = "clown_dead" + icon_gib = "clown_gib" + speak_chance = 0 + turns_per_move = 5 + response_help = "pokes" + response_disarm = "gently pushes aside" + response_harm = "hits" + speak = list("HONK", "Honk!", "Welcome to clown planet!") + emote_see = list("honks") + speak_chance = 1 + a_intent = I_HURT + stop_automated_movement_when_pulled = 0 + maxHealth = 75 + health = 75 + speed = -1 + harm_intent_damage = 8 + melee_damage_lower = 10 + melee_damage_upper = 10 + attacktext = "attacks" + attack_sound = 'sound/items/bikehorn.ogg' + + min_oxy = 5 + max_oxy = 0 + min_tox = 0 + max_tox = 1 + min_co2 = 0 + max_co2 = 5 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 270 + maxbodytemp = 370 + heat_damage_per_tick = 15 //amount of damage applied if animal's body temperature is higher than maxbodytemp + cold_damage_per_tick = 10 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp + unsuitable_atoms_damage = 10 diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index 07b828cb9fa..bb0249aecea 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -1,54 +1,54 @@ -/mob/living/simple_animal/hostile/retaliate - var/list/enemies = list() - var/hostile = 0 //Reverts back into a hostile mob when toggle to 1 - -/mob/living/simple_animal/hostile/retaliate/Found(var/atom/A) - if(isliving(A)) - var/mob/living/L = A - if(!L.stat) - stance = HOSTILE_STANCE_ATTACK - return L - else - enemies -= L - else if(istype(A, /obj/mecha)) - var/obj/mecha/M = A - if(M.occupant) - stance = HOSTILE_STANCE_ATTACK - return A - -/mob/living/simple_animal/hostile/retaliate/ListTargets() - if(hostile) - return ..() - if(!enemies.len) - return list() - var/list/see = ..() - see &= enemies // Remove all entries that aren't in enemies - return see - -/mob/living/simple_animal/hostile/retaliate/proc/Retaliate() - if(stat) //can't attack if we're dead - no point in targeting - return - - var/list/around = view(src, vision_range) - - for(var/atom/movable/A in around) - if(A == src) - continue - if(isliving(A)) - var/mob/living/M = A - if(!attack_same && M.faction != faction) - enemies |= M - else if(istype(A, /obj/mecha)) - var/obj/mecha/M = A - if(M.occupant) - enemies |= M - enemies |= M.occupant - - for(var/mob/living/simple_animal/hostile/retaliate/H in around) - if(!attack_same && !H.attack_same && H.faction == faction) - H.enemies |= enemies - return 0 - -/mob/living/simple_animal/hostile/retaliate/adjustBruteLoss(var/damage) - ..(damage) - Retaliate() +/mob/living/simple_animal/hostile/retaliate + var/list/enemies = list() + var/hostile = 0 //Reverts back into a hostile mob when toggle to 1 + +/mob/living/simple_animal/hostile/retaliate/Found(var/atom/A) + if(isliving(A)) + var/mob/living/L = A + if(!L.stat) + stance = HOSTILE_STANCE_ATTACK + return L + else + enemies -= L + else if(istype(A, /obj/mecha)) + var/obj/mecha/M = A + if(M.occupant) + stance = HOSTILE_STANCE_ATTACK + return A + +/mob/living/simple_animal/hostile/retaliate/ListTargets() + if(hostile) + return ..() + if(!enemies.len) + return list() + var/list/see = ..() + see &= enemies // Remove all entries that aren't in enemies + return see + +/mob/living/simple_animal/hostile/retaliate/proc/Retaliate() + if(stat) //can't attack if we're dead - no point in targeting + return + + var/list/around = view(src, vision_range) + + for(var/atom/movable/A in around) + if(A == src) + continue + if(isliving(A)) + var/mob/living/M = A + if(!attack_same && M.faction != faction) + enemies |= M + else if(istype(A, /obj/mecha)) + var/obj/mecha/M = A + if(M.occupant) + enemies |= M + enemies |= M.occupant + + for(var/mob/living/simple_animal/hostile/retaliate/H in around) + if(!attack_same && !H.attack_same && H.faction == faction) + H.enemies |= enemies + return 0 + +/mob/living/simple_animal/hostile/retaliate/adjustBruteLoss(var/damage) + ..(damage) + Retaliate() diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index 2c871f5905a..acf764a2d92 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -1,71 +1,71 @@ -/mob/living/simple_animal/hostile/tree - name = "pine tree" - desc = "A pissed off tree-like alien. It seems annoyed with the festivities..." - icon = 'icons/obj/flora/pinetrees.dmi' - icon_state = "pine_1" - icon_living = "pine_1" - icon_dead = "pine_1" - icon_gib = "pine_1" - - size = SIZE_HUGE - speak_chance = 0 - turns_per_move = 5 - response_help = "brushes" - response_disarm = "pushes" - response_harm = "hits" - speed = -1 - maxHealth = 250 - health = 250 - - pixel_x = -16 - - harm_intent_damage = 5 - melee_damage_lower = 8 - melee_damage_upper = 12 - attacktext = "bites" - attack_sound = 'sound/weapons/bite.ogg' - - //Space carp aren't affected by atmos. - min_oxy = 0 - max_oxy = 0 - min_tox = 0 - max_tox = 0 - min_co2 = 0 - max_co2 = 0 - min_n2 = 0 - max_n2 = 0 - minbodytemp = 0 - - faction = "forest" - -/mob/living/simple_animal/hostile/tree/FindTarget() - . = ..() - if(.) - emote("growls at [.]") - -/mob/living/simple_animal/hostile/tree/AttackingTarget() - . =..() - var/mob/living/L = . - if(istype(L)) - if(prob(15)) - L.Weaken(3) - L.visible_message("\the [src] knocks down \the [L]!") - -/mob/living/simple_animal/hostile/tree/Die() - ..() - visible_message("[src] is hacked into pieces!") - new /obj/item/stack/sheet/wood(loc) - qdel(src) - -/mob/living/simple_animal/hostile/tree/festivus - name = "festivus pole" - desc = "serenity now... SERENITY NOW!" - icon_state = "festivus_pole" - icon_living = "festivus_pole" - icon_dead = "festivus_pole" - icon_gib = "festivus_pole" - -/mob/living/simple_animal/hostile/tree/festivus/Die() - visible_message("[src] is hacked into pieces!") - new /obj/item/weapon/nullrod(loc) - qdel(src) +/mob/living/simple_animal/hostile/tree + name = "pine tree" + desc = "A pissed off tree-like alien. It seems annoyed with the festivities..." + icon = 'icons/obj/flora/pinetrees.dmi' + icon_state = "pine_1" + icon_living = "pine_1" + icon_dead = "pine_1" + icon_gib = "pine_1" + + size = SIZE_HUGE + speak_chance = 0 + turns_per_move = 5 + response_help = "brushes" + response_disarm = "pushes" + response_harm = "hits" + speed = -1 + maxHealth = 250 + health = 250 + + pixel_x = -16 + + harm_intent_damage = 5 + melee_damage_lower = 8 + melee_damage_upper = 12 + attacktext = "bites" + attack_sound = 'sound/weapons/bite.ogg' + + //Space carp aren't affected by atmos. + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 + + faction = "forest" + +/mob/living/simple_animal/hostile/tree/FindTarget() + . = ..() + if(.) + emote("growls at [.]") + +/mob/living/simple_animal/hostile/tree/AttackingTarget() + . =..() + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(3) + L.visible_message("\the [src] knocks down \the [L]!") + +/mob/living/simple_animal/hostile/tree/Die() + ..() + visible_message("[src] is hacked into pieces!") + new /obj/item/stack/sheet/wood(loc) + qdel(src) + +/mob/living/simple_animal/hostile/tree/festivus + name = "festivus pole" + desc = "serenity now... SERENITY NOW!" + icon_state = "festivus_pole" + icon_living = "festivus_pole" + icon_dead = "festivus_pole" + icon_gib = "festivus_pole" + +/mob/living/simple_animal/hostile/tree/festivus/Die() + visible_message("[src] is hacked into pieces!") + new /obj/item/weapon/nullrod(loc) + qdel(src) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 0fcf79b40d0..5238f3bb6fb 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -1,851 +1,851 @@ -/* Parrots! - * Contains - * Defines - * Inventory (headset stuff) - * Attack responces - * AI - * Procs / Verbs (usable by players) - * Sub-types - * Hear & say (the things we do for gimmicks) - */ - -/* - * Defines - */ - -//Only a maximum of one action and one intent should be active at any given time. -//Actions -#define PARROT_PERCH 1 //Sitting/sleeping, not moving -#define PARROT_SWOOP 2 //Moving towards or away from a target -#define PARROT_WANDER 4 //Moving without a specific target in mind - -//Intents -#define PARROT_STEAL 8 //Flying towards a target to steal it/from it -#define PARROT_ATTACK 16 //Flying towards a target to attack it -#define PARROT_RETURN 32 //Flying towards its perch -#define PARROT_FLEE 64 //Flying away from its attacker - - -/mob/living/simple_animal/parrot - name = "parrot" - desc = "The parrot squaks, \"It's a Parrot! BAWWK!\"" - icon = 'icons/mob/animal.dmi' - icon_state = "parrot_fly" - icon_living = "parrot_fly" - icon_dead = "parrot_dead" - pass_flags = PASSTABLE - flags = HEAR | PROXMOVE | HEAR_ALWAYS - - speak = list("Hi","Hello!","Cracker?","BAWWWWK george mellons griffing me") - speak_emote = list("squawks","says","yells") - emote_hear = list("squawks","bawks") - emote_see = list("flutters its wings") - - speak_chance = 1 //1% (1 in 100) chance every tick; So about once per 150 seconds, assuming an average tick is 1.5s - turns_per_move = 5 - meat_type = /obj/item/weapon/reagent_containers/food/snacks/cracker/ - melee_damage_upper = 10 - melee_damage_lower = 5 - - response_help = "pets" - response_disarm = "gently moves aside" - response_harm = "swats" - stop_automated_movement = 1 - //NO a_intent = I_HURT //parrots now start "aggressive" since only player parrots will nuzzle. - attacktext = "chomps" - friendly = "grooms" - - size = SIZE_TINY - - var/parrot_damage_upper = 10 - var/parrot_state = PARROT_WANDER //Hunt for a perch when created - var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in life() being run every single tick. - var/parrot_sleep_dur = 25 //Same as above, this is the var that physically counts down - var/parrot_dam_zone = list("chest", "head", "l_arm", "l_leg", "r_arm", "r_leg") //For humans, select a bodypart to attack - - var/parrot_speed = 5 //"Delay in world ticks between movement." according to byond. Yeah, that's BS but it does directly affect movement. Higher number = slower. - //var/parrot_been_shot = 0 this wasn't working right, and parrots don't survive bullets.((Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed.)) - - var/parrot_lastmove = null //Updates/Stores position of the parrot while it's moving - var/parrot_stuck = 0 //If parrot_lastmove hasnt changed, this will increment until it reaches parrot_stuck_threshold - var/parrot_stuck_threshold = 10 //if this == parrot_stuck, it'll force the parrot back to wandering - - var/list/speech_buffer = list() - var/list/available_channels = list() - - //Headset for Poly to yell at engineers :) - var/obj/item/device/radio/headset/ears = null - - //The thing the parrot is currently interested in. This gets used for items the parrot wants to pick up, mobs it wants to steal from, - //mobs it wants to attack or mobs that have attacked it - var/atom/movable/parrot_interest = null - - //Parrots will generally sit on their perch unless something catches their eye. - //These vars store their preffered perch and if they dont have one, what they can use as a perch - var/obj/parrot_perch = null - var/obj/desired_perches = list(/obj/structure/computerframe, /obj/structure/displaycase, \ - /obj/structure/filingcabinet, /obj/machinery/teleport, \ - /obj/machinery/computer, /obj/machinery/cloning/clonepod, \ - /obj/machinery/dna_scannernew, /obj/machinery/telecomms, \ - /obj/machinery/nuclearbomb, /obj/machinery/particle_accelerator, \ - /obj/machinery/recharge_station, /obj/machinery/smartfridge, \ - /obj/machinery/suit_storage_unit) - - //Parrots are kleptomaniacs. This variable ... stores the item a parrot is holding. - var/obj/item/held_item = null - - var/times_examined_while_dead = 0 - var/list/dead_lines = list("That parrot is definitely deceased.", \ - "You know a dead parrot when you see one, and you're looking at one right now.", \ - "It's dead, that's what's wrong with it.", \ - "It's bleeding demised.", \ - "It's passed on.", \ - "This parrot is no more.", \ - "It has ceased to be.", \ - "It's expired and gone to meet its maker.", \ - "This is a late parrot.", \ - "It's a stiff.", \ - "Bereft of life, it rests in peace.", \ - "It's rung down the curtain and joined the choir invisible.", \ - "This is an ex-parrot.") - var/list/not_dead_lines = list("It's just resting.", \ - "It's stunned.", \ - "It's just tired and shagged out after a long squawk.", \ - "It's prolly pining for the fjords.", \ - "It prefers kippin' on it's back.", \ - "It's a beautiful bird, lovely plumage, innit?") - - -/mob/living/simple_animal/parrot/New() - ..() - if(!ears) - var/headset = pick(/obj/item/device/radio/headset/headset_sec, \ - /obj/item/device/radio/headset/headset_eng, \ - /obj/item/device/radio/headset/headset_med, \ - /obj/item/device/radio/headset/headset_sci, \ - /obj/item/device/radio/headset/headset_cargo) - ears = new headset(src) - - parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var - - verbs.Add(/mob/living/simple_animal/parrot/proc/steal_from_ground, \ - /mob/living/simple_animal/parrot/proc/steal_from_mob, \ - /mob/living/simple_animal/parrot/verb/drop_held_item_player, \ - /mob/living/simple_animal/parrot/proc/perch_player, \ - /mob/living/simple_animal/parrot/proc/toggle_mode) - - -/mob/living/simple_animal/parrot/examine(mob/user) - if(stat == DEAD) - if(times_examined_while_dead < dead_lines.len) - times_examined_while_dead++ - desc = dead_lines[times_examined_while_dead] - else - desc = pick(not_dead_lines) - else - desc = initial(desc) - if(times_examined_while_dead) - times_examined_while_dead = 0 - ..() - -/mob/living/simple_animal/parrot/Die() - if(held_item) - held_item.loc = src.loc - held_item = null - walk(src,0) - ..() - -/mob/living/simple_animal/parrot/Stat() - ..() - if(statpanel("Status")) - stat("Held Item", held_item) - stat("Mode",a_intent) - -/mob/living/simple_animal/parrot/Hear(var/datum/speech/speech, var/rendered_speech="") - if(speech.speaker && speech.speaker != src && prob(20)) //Don't imitate outselves - if(speech_buffer.len >= 20) - speech_buffer -= pick(speech_buffer) - speech_buffer |= speech.message - ..() - -/mob/living/simple_animal/parrot/radio(var/datum/speech/speech, var/message_mode) - . = ..() - if(. != 0) - return . - - switch(message_mode) - if(MODE_HEADSET) - if (ears) - ears.talk_into(speech) - return ITALICS | REDUCE_RANGE - - if(MODE_SECURE_HEADSET) - if(ears) - ears.talk_into(speech, 1) // No fucking clue why message_mode is 1. - return ITALICS | REDUCE_RANGE - if(MODE_DEPARTMENT) - if(ears) - ears.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - - if(message_mode in radiochannels) - if(ears) - ears.talk_into(speech, message_mode) - return ITALICS | REDUCE_RANGE - - return 0 - -/* - * Inventory - */ -/mob/living/simple_animal/parrot/show_inv(mob/user) - user.set_machine(src) - if(user.stat) return - - var/dat = "

    Inventory of [name]

    " - if(ears) - dat += "
    Headset: [ears] (Remove)" - else - dat += "
    Headset: Nothing" - - user << browse(dat, "window=mob[real_name];size=325x500") - onclose(user, "mob[real_name]") - - -/mob/living/simple_animal/parrot/Topic(href, href_list) - - //Can the usr physically do this? - if(!usr.canmove || usr.stat || usr.restrained() || !usr.Adjacent(loc)) - return - - //Is the usr's mob type able to do this? (lolaliens) - if(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)) - - //Removing from inventory - if(href_list["remove_inv"]) - var/remove_from = href_list["remove_inv"] - switch(remove_from) - if("ears") - if(ears) - if(!stat) - if(available_channels.len) - src.say("[pick(available_channels)] BAWWWWWK LEAVE THE HEADSET BAWKKKKK!") - else - src.say("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!") - ears.loc = src.loc - ears = null - for(var/possible_phrase in speak) - if(copytext(possible_phrase,1,3) in department_radio_keys) - possible_phrase = copytext(possible_phrase,3) - else - to_chat(usr, "There is nothing to remove from its [remove_from].") - return - - //Adding things to inventory - else if(href_list["add_inv"]) - var/add_to = href_list["add_inv"] - if(!usr.get_active_hand()) - to_chat(usr, "You have nothing in your hand to put on its [add_to].") - return - switch(add_to) - if("ears") - if(ears) - to_chat(usr, "It's already wearing something.") - return - else - var/obj/item/item_to_add = usr.get_active_hand() - if(!item_to_add) - return - - if( !istype(item_to_add, /obj/item/device/radio/headset) ) - to_chat(usr, "This object won't fit.") - return - - var/obj/item/device/radio/headset/headset_to_add = item_to_add - - usr.drop_item(headset_to_add, src) - src.ears = headset_to_add - to_chat(usr, "You fit the headset onto [src].") - - clearlist(available_channels) - for(var/ch in headset_to_add.channels) - switch(ch) - if("Engineering") - available_channels.Add(":e") - if("Command") - available_channels.Add(":c") - if("Security") - available_channels.Add(":s") - if("Science") - available_channels.Add(":n") - if("Medical") - available_channels.Add(":m") - if("Mining") - available_channels.Add(":d") - if("Cargo") - available_channels.Add(":q") - - if(headset_to_add.translate_binary) - available_channels.Add(":b") - else - ..() - - -/* - * Attack responces - */ -//Humans, monkeys, aliens -/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M as mob) - ..() - if(client) return - if(!stat && M.a_intent == I_HURT) - - icon_state = "parrot_fly" //It is going to be flying regardless of whether it flees or attacks - - if(parrot_state == PARROT_PERCH) - parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - - parrot_interest = M - parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction.. - - if(M.health < 50) //Weakened mob? Fight back! - parrot_state |= PARROT_ATTACK - else - parrot_state |= PARROT_FLEE //Otherwise, fly like a bat out of hell! - drop_held_item(0) - return - -/mob/living/simple_animal/parrot/attack_paw(mob/living/carbon/monkey/M as mob) - attack_hand(M) - -/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/monkey/M as mob) - attack_hand(M) - -//Simple animals -/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M as mob) - ..() //goodbye immortal parrots - - if(client) return - - - if(parrot_state == PARROT_PERCH) - parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - - if(M.melee_damage_upper > 0 && !stat) - parrot_interest = M - parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless - icon_state = "parrot_fly" - -//Mobs with objects -/mob/living/simple_animal/parrot/attackby(var/obj/item/O as obj, var/mob/living/user as mob) - if(!stat && !client && !istype(O, /obj/item/stack/medical) && !istype(O,/obj/item/weapon/reagent_containers/food/snacks/cracker)) - if(O.force) - if(parrot_state == PARROT_PERCH) - parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - - parrot_interest = user - parrot_state = PARROT_SWOOP - if (user.health < 50) - parrot_state |= PARROT_ATTACK //weakened mob? fight back! - else - parrot_state |= PARROT_FLEE - icon_state = "parrot_fly" - drop_held_item(0) - else if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/cracker)) //Poly wants a cracker. - user.drop_item(O) - qdel(O) - if(health < maxHealth) - adjustBruteLoss(-10) - to_chat(user, "[src] eagerly devours the cracker.") - playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) - ..() - return - -//Bullets -/mob/living/simple_animal/parrot/bullet_act(var/obj/item/projectile/Proj) - ..() - if(!stat && !client) - if(parrot_state == PARROT_PERCH) - parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - - parrot_interest = null - parrot_state = PARROT_WANDER | PARROT_FLEE //Been shot and survived! RUN LIKE HELL! - //parrot_been_shot += 5 - icon_state = "parrot_fly" - drop_held_item(0) - return - - -/* - * AI - Not really intelligent, but I'm calling it AI anyway. - */ -/mob/living/simple_animal/parrot/Life() - if(timestopped) return 0 //under effects of time magick - ..() - - //Sprite and AI update for when a parrot gets pulled - if(pulledby && stat == CONSCIOUS) - icon_state = "parrot_fly" - if(!client) - parrot_state = PARROT_WANDER - return - - if(client || stat) - return //Lets not force players or dead/incap parrots to move - - if(!isturf(src.loc) || !canmove || locked_to) - return //If it can't move, dont let it move. (The locked_to check probably isn't necessary thanks to canmove) - - -//-----SPEECH - /* Parrot speech mimickry! - Phrases that the parrot Hears() get added to speech_buffer. - Every once in a while, the parrot picks one of the lines from the buffer and replaces an element of the 'speech' list. - Then it clears the buffer to make sure they dont magically remember something from hours ago. */ - if(speech_buffer.len && prob(10)) - if(speak.len) - speak.Remove(pick(speak)) - - speak.Add(pick(speech_buffer)) - clearlist(speech_buffer) - - -//-----SLEEPING - if(parrot_state == PARROT_PERCH) - if(parrot_perch && parrot_perch.loc != src.loc) //Make sure someone hasnt moved our perch on us - if(parrot_perch in view(src)) - parrot_state = PARROT_SWOOP | PARROT_RETURN - icon_state = "parrot_fly" - return - else - parrot_state = PARROT_WANDER - icon_state = "parrot_fly" - return - - if(--parrot_sleep_dur) //Zzz - return - - else - //This way we only call the stuff below once every [sleep_max] ticks. - parrot_sleep_dur = parrot_sleep_max - - //Cycle through message modes for the headset - if(speak.len) - var/list/newspeak = list() - - if(available_channels.len && src.ears) - for(var/possible_phrase in speak) - - //50/50 chance to not use the radio at all - var/useradio = 0 - if(prob(50)) - useradio = 1 - - if(copytext(possible_phrase,1,3) in department_radio_keys) - possible_phrase = "[useradio ? pick(available_channels) : ""][copytext(possible_phrase,3)]" //crop out the channel prefix - else - possible_phrase = "[useradio ? pick(available_channels) : ""][possible_phrase]" - newspeak.Add(possible_phrase) - else //If we have no headset or channels to use, dont try to use any! - for(var/possible_phrase in speak) - if(copytext(possible_phrase,1,3) in department_radio_keys) - possible_phrase = "[copytext(possible_phrase,3,length(possible_phrase)+1)]" //crop out the channel prefix - newspeak.Add(possible_phrase) - speak = newspeak - - //Search for item to steal - parrot_interest = search_for_item() - if(parrot_interest) - emote("looks in [parrot_interest]'s direction and takes flight") - parrot_state = PARROT_SWOOP | PARROT_STEAL - icon_state = "parrot_fly" - return - -//-----WANDERING - This is basically a 'I dont know what to do yet' state - else if(parrot_state == PARROT_WANDER) - //Stop movement, we'll set it later - walk(src, 0) - parrot_interest = null - - //Wander around aimlessly. This will help keep the loops from searches down - //and possibly move the mob into a new are in view of something they can use - if(prob(90)) - step(src, pick(cardinal)) - return - - if(!held_item && !parrot_perch) //If we've got nothing to do.. look for something to do. - var/atom/movable/AM = search_for_perch_and_item() //This handles checking through lists so we know it's either a perch or stealable item - if(AM) - if(istype(AM, /obj/item) || isliving(AM)) //If stealable item - parrot_interest = AM - emote("turns and flies towards [parrot_interest]") - parrot_state = PARROT_SWOOP | PARROT_STEAL - return - else //Else it's a perch - parrot_perch = AM - parrot_state = PARROT_SWOOP | PARROT_RETURN - return - return - - if(parrot_interest && parrot_interest in view(src)) - parrot_state = PARROT_SWOOP | PARROT_STEAL - return - - if(parrot_perch && parrot_perch in view(src)) - parrot_state = PARROT_SWOOP | PARROT_RETURN - return - - else //Have an item but no perch? Find one! - parrot_perch = search_for_perch() - if(parrot_perch) - parrot_state = PARROT_SWOOP | PARROT_RETURN - return -//-----STEALING - else if(parrot_state == (PARROT_SWOOP | PARROT_STEAL)) - walk(src,0) - if(!parrot_interest || held_item) - parrot_state = PARROT_SWOOP | PARROT_RETURN - return - - if(!(parrot_interest in view(src))) - parrot_state = PARROT_SWOOP | PARROT_RETURN - return - - if(Adjacent(parrot_interest)) - - if(isliving(parrot_interest)) - steal_from_mob() - - else //This should ensure that we only grab the item we want, and make sure it's not already collected on our perch - if(!parrot_perch || parrot_interest.loc != parrot_perch.loc) - held_item = parrot_interest - parrot_interest.loc = src - visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.") - - parrot_interest = null - parrot_state = PARROT_SWOOP | PARROT_RETURN - return - - walk_to(src, parrot_interest, 1, parrot_speed) - if(isStuck()) return - - return - -//-----RETURNING TO PERCH - else if(parrot_state == (PARROT_SWOOP | PARROT_RETURN)) - walk(src, 0) - if(!parrot_perch || !isturf(parrot_perch.loc)) //Make sure the perch exists and somehow isnt inside of something else. - parrot_perch = null - parrot_state = PARROT_WANDER - return - - if(Adjacent(parrot_perch)) - src.loc = parrot_perch.loc - drop_held_item() - parrot_state = PARROT_PERCH - icon_state = "parrot_sit" - return - - walk_to(src, parrot_perch, 1, parrot_speed) - if(isStuck()) return - - return - -//-----FLEEING - else if(parrot_state == (PARROT_SWOOP | PARROT_FLEE)) - walk(src,0) - if(!parrot_interest || !isliving(parrot_interest)) //Sanity - parrot_state = PARROT_WANDER - - walk_away(src, parrot_interest, 1, parrot_speed) - /*if(parrot_been_shot > 0) - parrot_been_shot-- didn't work anyways, and besides, any bullet poly survives isn't worth the speed boost.*/ - if(isStuck()) return - - return - -//-----ATTACKING - else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK)) - - //If we're attacking a nothing, an object, a turf or a ghost for some stupid reason, switch to wander - if(!parrot_interest || !isliving(parrot_interest)) - parrot_interest = null - parrot_state = PARROT_WANDER - return - - var/mob/living/L = parrot_interest - if(melee_damage_upper == 0) - melee_damage_upper = parrot_damage_upper - a_intent = I_HURT - - //If the mob is close enough to interact with - if(Adjacent(parrot_interest)) - - //If the mob we've been chasing/attacking dies or falls into crit, check for loot! - if(L.stat) - parrot_interest = null - if(!held_item) - held_item = steal_from_ground() - if(!held_item) - held_item = steal_from_mob() //Apparently it's possible for dead mobs to hang onto items in certain circumstances. - if(parrot_perch in view(src)) //If we have a home nearby, go to it, otherwise find a new home - parrot_state = PARROT_SWOOP | PARROT_RETURN - else - parrot_state = PARROT_WANDER - return - - attacktext = pick("claws at", "chomps") - L.attack_animal(src)//Time for the hurt to begin! - //Otherwise, fly towards the mob! - else - walk_to(src, parrot_interest, 1, parrot_speed) - if(isStuck()) return - - return -//-----STATE MISHAP - else //This should not happen. If it does lets reset everything and try again - walk(src,0) - parrot_interest = null - parrot_perch = null - drop_held_item() - parrot_state = PARROT_WANDER - return - -/* - * Procs - */ - -/mob/living/simple_animal/parrot/movement_delay() - if(client && stat == CONSCIOUS && parrot_state != "parrot_fly") - icon_state = "parrot_fly" - ..() - -/mob/living/simple_animal/parrot/proc/isStuck() - //Check to see if the parrot is stuck due to things like windows or doors or windowdoors - if(parrot_lastmove) - if(parrot_lastmove == src.loc) - if(parrot_stuck_threshold >= ++parrot_stuck) //If it has been stuck for a while, go back to wander. - parrot_state = PARROT_WANDER - parrot_stuck = 0 - parrot_lastmove = null - return 1 - else - parrot_lastmove = null - else - parrot_lastmove = src.loc - return 0 - -/mob/living/simple_animal/parrot/proc/search_for_item() - for(var/atom/movable/AM in view(src)) - //Skip items we already stole or are wearing or are too big - if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src) - continue - - if(istype(AM, /obj/item)) - var/obj/item/I = AM - if(I.w_class < 2) - return I - - if(iscarbon(AM)) - var/mob/living/carbon/C = AM - if((C.l_hand && C.l_hand.w_class <= 2) || (C.r_hand && C.r_hand.w_class <= 2)) - return C - return null - -/mob/living/simple_animal/parrot/proc/search_for_perch() - for(var/obj/O in view(src)) - for(var/path in desired_perches) - if(istype(O, path)) - return O - return null - -//This proc was made to save on doing two 'in view' loops seperatly -/mob/living/simple_animal/parrot/proc/search_for_perch_and_item() - for(var/atom/movable/AM in view(src)) - for(var/perch_path in desired_perches) - if(istype(AM, perch_path)) - return AM - - //Skip items we already stole or are wearing or are too big - if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src) - continue - - if(istype(AM, /obj/item)) - var/obj/item/I = AM - if(I.w_class <= 2) - return I - - if(iscarbon(AM)) - var/mob/living/carbon/C = AM - if(C.l_hand && C.l_hand.w_class <= 2 || C.r_hand && C.r_hand.w_class <= 2) - return C - return null - - -/* - * Verbs - These are actually procs, but can be used as verbs by player-controlled parrots. - */ -/mob/living/simple_animal/parrot/proc/steal_from_ground() - set name = "Steal from ground" - set category = "Parrot" - set desc = "Grabs a nearby item." - - if(stat) - return -1 - - if(held_item) - to_chat(src, "You are already holding [held_item]") - return 1 - - for(var/obj/item/I in view(1,src)) - if(!Adjacent(I)) - continue - //Make sure we're not already holding it and it's small enough - if(I.loc != src && I.w_class <= 2) - - //If we have a perch and the item is sitting on it, continue - if(!client && parrot_perch && I.loc == parrot_perch.loc) - continue - - held_item = I - I.loc = src - visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.") - return held_item - - to_chat(src, "There is nothing of interest to take.") - return 0 - -/mob/living/simple_animal/parrot/proc/steal_from_mob() - set name = "Steal from mob" - set category = "Parrot" - set desc = "Steals an item right out of a person's hand!" - - if(stat) - return -1 - - if(held_item) - to_chat(src, "You are already holding [held_item]") - return 1 - - var/obj/item/stolen_item = null - - for(var/mob/living/carbon/C in view(1,src)) - if(!Adjacent(C)) - continue - - if(C.l_hand && C.l_hand.w_class <= 2) - stolen_item = C.l_hand - - if(C.r_hand && C.r_hand.w_class <= 2) - stolen_item = C.r_hand - - if(stolen_item) - C.u_equip(stolen_item) - held_item = stolen_item - stolen_item.loc = src - visible_message("[src] grabs [held_item] out of [C]'s hand!", "You snag [held_item] out of [C]'s hand!", "You hear the sounds of wings flapping furiously.") - return held_item - - to_chat(src, "There is nothing of interest to take.") - return 0 - -/mob/living/simple_animal/parrot/verb/drop_held_item_player() - set name = "Drop held item" - set category = "Parrot" - set desc = "Drop the item you're holding." - - if(stat) - return - - src.drop_held_item() - - return - -/mob/living/simple_animal/parrot/proc/drop_held_item(var/drop_gently = 1) - set name = "Drop held item" - set category = "Parrot" - set desc = "Drop the item you're holding." - - if(stat) - return -1 - - if(!held_item) - if(src == usr) //So that other mobs wont make this message appear when they're bludgeoning you. - to_chat(src, "You have nothing to drop!") - return 0 - - -//parrots will eat crackers instead of dropping them - if(istype(held_item,/obj/item/weapon/reagent_containers/food/snacks/cracker) && (drop_gently)) - qdel(held_item) - held_item = null - if(health < maxHealth) - adjustBruteLoss(-10) - emote("[src] eagerly downs the cracker") - playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) - return 1 - - - if(!drop_gently) - if(istype(held_item, /obj/item/weapon/grenade)) - var/obj/item/weapon/grenade/G = held_item - G.loc = src.loc - G.prime() - to_chat(src, "You let go of [held_item]!") - held_item = null - return 1 - - to_chat(src, "You drop [held_item].") - - held_item.loc = src.loc - held_item = null - return 1 - -/mob/living/simple_animal/parrot/proc/perch_player() - set name = "Sit" - set category = "Parrot" - set desc = "Sit on a nice comfy perch." - - if(stat || !client) - return - - if(icon_state == "parrot_fly") - for(var/atom/movable/AM in view(src,1)) - if(!Adjacent(AM)) - continue - for(var/perch_path in desired_perches) - if(istype(AM, perch_path)) - forceMove(AM.loc) - icon_state = "parrot_sit" - return - to_chat(src, "There is no perch nearby to sit on.") - return - -/mob/living/simple_animal/parrot/proc/toggle_mode() - set name = "Toggle mode" - set category = "Parrot" - set desc = "Time to bear those claws!" - - if(stat || !client) - return - - if(melee_damage_upper) - melee_damage_upper = 0 - a_intent = I_HELP - else - melee_damage_upper = parrot_damage_upper - a_intent = I_HURT - return - -/* - * Sub-types - */ -/mob/living/simple_animal/parrot/Poly - name = "Poly" - desc = "Poly the Parrot. An expert on quantum cracker theory." - speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE") - -/mob/living/simple_animal/parrot/Poly/New() - ears = new /obj/item/device/radio/headset/headset_eng(src) - available_channels = list(":e") - ..() +/* Parrots! + * Contains + * Defines + * Inventory (headset stuff) + * Attack responces + * AI + * Procs / Verbs (usable by players) + * Sub-types + * Hear & say (the things we do for gimmicks) + */ + +/* + * Defines + */ + +//Only a maximum of one action and one intent should be active at any given time. +//Actions +#define PARROT_PERCH 1 //Sitting/sleeping, not moving +#define PARROT_SWOOP 2 //Moving towards or away from a target +#define PARROT_WANDER 4 //Moving without a specific target in mind + +//Intents +#define PARROT_STEAL 8 //Flying towards a target to steal it/from it +#define PARROT_ATTACK 16 //Flying towards a target to attack it +#define PARROT_RETURN 32 //Flying towards its perch +#define PARROT_FLEE 64 //Flying away from its attacker + + +/mob/living/simple_animal/parrot + name = "parrot" + desc = "The parrot squaks, \"It's a Parrot! BAWWK!\"" + icon = 'icons/mob/animal.dmi' + icon_state = "parrot_fly" + icon_living = "parrot_fly" + icon_dead = "parrot_dead" + pass_flags = PASSTABLE + flags = HEAR | PROXMOVE | HEAR_ALWAYS + + speak = list("Hi","Hello!","Cracker?","BAWWWWK george mellons griffing me") + speak_emote = list("squawks","says","yells") + emote_hear = list("squawks","bawks") + emote_see = list("flutters its wings") + + speak_chance = 1 //1% (1 in 100) chance every tick; So about once per 150 seconds, assuming an average tick is 1.5s + turns_per_move = 5 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/cracker/ + melee_damage_upper = 10 + melee_damage_lower = 5 + + response_help = "pets" + response_disarm = "gently moves aside" + response_harm = "swats" + stop_automated_movement = 1 + //NO a_intent = I_HURT //parrots now start "aggressive" since only player parrots will nuzzle. + attacktext = "chomps" + friendly = "grooms" + + size = SIZE_TINY + + var/parrot_damage_upper = 10 + var/parrot_state = PARROT_WANDER //Hunt for a perch when created + var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in life() being run every single tick. + var/parrot_sleep_dur = 25 //Same as above, this is the var that physically counts down + var/parrot_dam_zone = list("chest", "head", "l_arm", "l_leg", "r_arm", "r_leg") //For humans, select a bodypart to attack + + var/parrot_speed = 5 //"Delay in world ticks between movement." according to byond. Yeah, that's BS but it does directly affect movement. Higher number = slower. + //var/parrot_been_shot = 0 this wasn't working right, and parrots don't survive bullets.((Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed.)) + + var/parrot_lastmove = null //Updates/Stores position of the parrot while it's moving + var/parrot_stuck = 0 //If parrot_lastmove hasnt changed, this will increment until it reaches parrot_stuck_threshold + var/parrot_stuck_threshold = 10 //if this == parrot_stuck, it'll force the parrot back to wandering + + var/list/speech_buffer = list() + var/list/available_channels = list() + + //Headset for Poly to yell at engineers :) + var/obj/item/device/radio/headset/ears = null + + //The thing the parrot is currently interested in. This gets used for items the parrot wants to pick up, mobs it wants to steal from, + //mobs it wants to attack or mobs that have attacked it + var/atom/movable/parrot_interest = null + + //Parrots will generally sit on their perch unless something catches their eye. + //These vars store their preffered perch and if they dont have one, what they can use as a perch + var/obj/parrot_perch = null + var/obj/desired_perches = list(/obj/structure/computerframe, /obj/structure/displaycase, \ + /obj/structure/filingcabinet, /obj/machinery/teleport, \ + /obj/machinery/computer, /obj/machinery/cloning/clonepod, \ + /obj/machinery/dna_scannernew, /obj/machinery/telecomms, \ + /obj/machinery/nuclearbomb, /obj/machinery/particle_accelerator, \ + /obj/machinery/recharge_station, /obj/machinery/smartfridge, \ + /obj/machinery/suit_storage_unit) + + //Parrots are kleptomaniacs. This variable ... stores the item a parrot is holding. + var/obj/item/held_item = null + + var/times_examined_while_dead = 0 + var/list/dead_lines = list("That parrot is definitely deceased.", \ + "You know a dead parrot when you see one, and you're looking at one right now.", \ + "It's dead, that's what's wrong with it.", \ + "It's bleeding demised.", \ + "It's passed on.", \ + "This parrot is no more.", \ + "It has ceased to be.", \ + "It's expired and gone to meet its maker.", \ + "This is a late parrot.", \ + "It's a stiff.", \ + "Bereft of life, it rests in peace.", \ + "It's rung down the curtain and joined the choir invisible.", \ + "This is an ex-parrot.") + var/list/not_dead_lines = list("It's just resting.", \ + "It's stunned.", \ + "It's just tired and shagged out after a long squawk.", \ + "It's prolly pining for the fjords.", \ + "It prefers kippin' on it's back.", \ + "It's a beautiful bird, lovely plumage, innit?") + + +/mob/living/simple_animal/parrot/New() + ..() + if(!ears) + var/headset = pick(/obj/item/device/radio/headset/headset_sec, \ + /obj/item/device/radio/headset/headset_eng, \ + /obj/item/device/radio/headset/headset_med, \ + /obj/item/device/radio/headset/headset_sci, \ + /obj/item/device/radio/headset/headset_cargo) + ears = new headset(src) + + parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var + + verbs.Add(/mob/living/simple_animal/parrot/proc/steal_from_ground, \ + /mob/living/simple_animal/parrot/proc/steal_from_mob, \ + /mob/living/simple_animal/parrot/verb/drop_held_item_player, \ + /mob/living/simple_animal/parrot/proc/perch_player, \ + /mob/living/simple_animal/parrot/proc/toggle_mode) + + +/mob/living/simple_animal/parrot/examine(mob/user) + if(stat == DEAD) + if(times_examined_while_dead < dead_lines.len) + times_examined_while_dead++ + desc = dead_lines[times_examined_while_dead] + else + desc = pick(not_dead_lines) + else + desc = initial(desc) + if(times_examined_while_dead) + times_examined_while_dead = 0 + ..() + +/mob/living/simple_animal/parrot/Die() + if(held_item) + held_item.loc = src.loc + held_item = null + walk(src,0) + ..() + +/mob/living/simple_animal/parrot/Stat() + ..() + if(statpanel("Status")) + stat("Held Item", held_item) + stat("Mode",a_intent) + +/mob/living/simple_animal/parrot/Hear(var/datum/speech/speech, var/rendered_speech="") + if(speech.speaker && speech.speaker != src && prob(20)) //Don't imitate outselves + if(speech_buffer.len >= 20) + speech_buffer -= pick(speech_buffer) + speech_buffer |= speech.message + ..() + +/mob/living/simple_animal/parrot/radio(var/datum/speech/speech, var/message_mode) + . = ..() + if(. != 0) + return . + + switch(message_mode) + if(MODE_HEADSET) + if (ears) + ears.talk_into(speech) + return ITALICS | REDUCE_RANGE + + if(MODE_SECURE_HEADSET) + if(ears) + ears.talk_into(speech, 1) // No fucking clue why message_mode is 1. + return ITALICS | REDUCE_RANGE + if(MODE_DEPARTMENT) + if(ears) + ears.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + + if(message_mode in radiochannels) + if(ears) + ears.talk_into(speech, message_mode) + return ITALICS | REDUCE_RANGE + + return 0 + +/* + * Inventory + */ +/mob/living/simple_animal/parrot/show_inv(mob/user) + user.set_machine(src) + if(user.stat) return + + var/dat = "

    Inventory of [name]

    " + if(ears) + dat += "
    Headset: [ears] (Remove)" + else + dat += "
    Headset: Nothing" + + user << browse(dat, "window=mob[real_name];size=325x500") + onclose(user, "mob[real_name]") + + +/mob/living/simple_animal/parrot/Topic(href, href_list) + + //Can the usr physically do this? + if(!usr.canmove || usr.stat || usr.restrained() || !usr.Adjacent(loc)) + return + + //Is the usr's mob type able to do this? (lolaliens) + if(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)) + + //Removing from inventory + if(href_list["remove_inv"]) + var/remove_from = href_list["remove_inv"] + switch(remove_from) + if("ears") + if(ears) + if(!stat) + if(available_channels.len) + src.say("[pick(available_channels)] BAWWWWWK LEAVE THE HEADSET BAWKKKKK!") + else + src.say("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!") + ears.loc = src.loc + ears = null + for(var/possible_phrase in speak) + if(copytext(possible_phrase,1,3) in department_radio_keys) + possible_phrase = copytext(possible_phrase,3) + else + to_chat(usr, "There is nothing to remove from its [remove_from].") + return + + //Adding things to inventory + else if(href_list["add_inv"]) + var/add_to = href_list["add_inv"] + if(!usr.get_active_hand()) + to_chat(usr, "You have nothing in your hand to put on its [add_to].") + return + switch(add_to) + if("ears") + if(ears) + to_chat(usr, "It's already wearing something.") + return + else + var/obj/item/item_to_add = usr.get_active_hand() + if(!item_to_add) + return + + if( !istype(item_to_add, /obj/item/device/radio/headset) ) + to_chat(usr, "This object won't fit.") + return + + var/obj/item/device/radio/headset/headset_to_add = item_to_add + + usr.drop_item(headset_to_add, src) + src.ears = headset_to_add + to_chat(usr, "You fit the headset onto [src].") + + clearlist(available_channels) + for(var/ch in headset_to_add.channels) + switch(ch) + if("Engineering") + available_channels.Add(":e") + if("Command") + available_channels.Add(":c") + if("Security") + available_channels.Add(":s") + if("Science") + available_channels.Add(":n") + if("Medical") + available_channels.Add(":m") + if("Mining") + available_channels.Add(":d") + if("Cargo") + available_channels.Add(":q") + + if(headset_to_add.translate_binary) + available_channels.Add(":b") + else + ..() + + +/* + * Attack responces + */ +//Humans, monkeys, aliens +/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M as mob) + ..() + if(client) return + if(!stat && M.a_intent == I_HURT) + + icon_state = "parrot_fly" //It is going to be flying regardless of whether it flees or attacks + + if(parrot_state == PARROT_PERCH) + parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched + + parrot_interest = M + parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction.. + + if(M.health < 50) //Weakened mob? Fight back! + parrot_state |= PARROT_ATTACK + else + parrot_state |= PARROT_FLEE //Otherwise, fly like a bat out of hell! + drop_held_item(0) + return + +/mob/living/simple_animal/parrot/attack_paw(mob/living/carbon/monkey/M as mob) + attack_hand(M) + +/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/monkey/M as mob) + attack_hand(M) + +//Simple animals +/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M as mob) + ..() //goodbye immortal parrots + + if(client) return + + + if(parrot_state == PARROT_PERCH) + parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched + + if(M.melee_damage_upper > 0 && !stat) + parrot_interest = M + parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless + icon_state = "parrot_fly" + +//Mobs with objects +/mob/living/simple_animal/parrot/attackby(var/obj/item/O as obj, var/mob/living/user as mob) + if(!stat && !client && !istype(O, /obj/item/stack/medical) && !istype(O,/obj/item/weapon/reagent_containers/food/snacks/cracker)) + if(O.force) + if(parrot_state == PARROT_PERCH) + parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched + + parrot_interest = user + parrot_state = PARROT_SWOOP + if (user.health < 50) + parrot_state |= PARROT_ATTACK //weakened mob? fight back! + else + parrot_state |= PARROT_FLEE + icon_state = "parrot_fly" + drop_held_item(0) + else if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/cracker)) //Poly wants a cracker. + user.drop_item(O) + qdel(O) + if(health < maxHealth) + adjustBruteLoss(-10) + to_chat(user, "[src] eagerly devours the cracker.") + playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) + ..() + return + +//Bullets +/mob/living/simple_animal/parrot/bullet_act(var/obj/item/projectile/Proj) + ..() + if(!stat && !client) + if(parrot_state == PARROT_PERCH) + parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched + + parrot_interest = null + parrot_state = PARROT_WANDER | PARROT_FLEE //Been shot and survived! RUN LIKE HELL! + //parrot_been_shot += 5 + icon_state = "parrot_fly" + drop_held_item(0) + return + + +/* + * AI - Not really intelligent, but I'm calling it AI anyway. + */ +/mob/living/simple_animal/parrot/Life() + if(timestopped) return 0 //under effects of time magick + ..() + + //Sprite and AI update for when a parrot gets pulled + if(pulledby && stat == CONSCIOUS) + icon_state = "parrot_fly" + if(!client) + parrot_state = PARROT_WANDER + return + + if(client || stat) + return //Lets not force players or dead/incap parrots to move + + if(!isturf(src.loc) || !canmove || locked_to) + return //If it can't move, dont let it move. (The locked_to check probably isn't necessary thanks to canmove) + + +//-----SPEECH + /* Parrot speech mimickry! + Phrases that the parrot Hears() get added to speech_buffer. + Every once in a while, the parrot picks one of the lines from the buffer and replaces an element of the 'speech' list. + Then it clears the buffer to make sure they dont magically remember something from hours ago. */ + if(speech_buffer.len && prob(10)) + if(speak.len) + speak.Remove(pick(speak)) + + speak.Add(pick(speech_buffer)) + clearlist(speech_buffer) + + +//-----SLEEPING + if(parrot_state == PARROT_PERCH) + if(parrot_perch && parrot_perch.loc != src.loc) //Make sure someone hasnt moved our perch on us + if(parrot_perch in view(src)) + parrot_state = PARROT_SWOOP | PARROT_RETURN + icon_state = "parrot_fly" + return + else + parrot_state = PARROT_WANDER + icon_state = "parrot_fly" + return + + if(--parrot_sleep_dur) //Zzz + return + + else + //This way we only call the stuff below once every [sleep_max] ticks. + parrot_sleep_dur = parrot_sleep_max + + //Cycle through message modes for the headset + if(speak.len) + var/list/newspeak = list() + + if(available_channels.len && src.ears) + for(var/possible_phrase in speak) + + //50/50 chance to not use the radio at all + var/useradio = 0 + if(prob(50)) + useradio = 1 + + if(copytext(possible_phrase,1,3) in department_radio_keys) + possible_phrase = "[useradio ? pick(available_channels) : ""][copytext(possible_phrase,3)]" //crop out the channel prefix + else + possible_phrase = "[useradio ? pick(available_channels) : ""][possible_phrase]" + newspeak.Add(possible_phrase) + else //If we have no headset or channels to use, dont try to use any! + for(var/possible_phrase in speak) + if(copytext(possible_phrase,1,3) in department_radio_keys) + possible_phrase = "[copytext(possible_phrase,3,length(possible_phrase)+1)]" //crop out the channel prefix + newspeak.Add(possible_phrase) + speak = newspeak + + //Search for item to steal + parrot_interest = search_for_item() + if(parrot_interest) + emote("looks in [parrot_interest]'s direction and takes flight") + parrot_state = PARROT_SWOOP | PARROT_STEAL + icon_state = "parrot_fly" + return + +//-----WANDERING - This is basically a 'I dont know what to do yet' state + else if(parrot_state == PARROT_WANDER) + //Stop movement, we'll set it later + walk(src, 0) + parrot_interest = null + + //Wander around aimlessly. This will help keep the loops from searches down + //and possibly move the mob into a new are in view of something they can use + if(prob(90)) + step(src, pick(cardinal)) + return + + if(!held_item && !parrot_perch) //If we've got nothing to do.. look for something to do. + var/atom/movable/AM = search_for_perch_and_item() //This handles checking through lists so we know it's either a perch or stealable item + if(AM) + if(istype(AM, /obj/item) || isliving(AM)) //If stealable item + parrot_interest = AM + emote("turns and flies towards [parrot_interest]") + parrot_state = PARROT_SWOOP | PARROT_STEAL + return + else //Else it's a perch + parrot_perch = AM + parrot_state = PARROT_SWOOP | PARROT_RETURN + return + return + + if(parrot_interest && parrot_interest in view(src)) + parrot_state = PARROT_SWOOP | PARROT_STEAL + return + + if(parrot_perch && parrot_perch in view(src)) + parrot_state = PARROT_SWOOP | PARROT_RETURN + return + + else //Have an item but no perch? Find one! + parrot_perch = search_for_perch() + if(parrot_perch) + parrot_state = PARROT_SWOOP | PARROT_RETURN + return +//-----STEALING + else if(parrot_state == (PARROT_SWOOP | PARROT_STEAL)) + walk(src,0) + if(!parrot_interest || held_item) + parrot_state = PARROT_SWOOP | PARROT_RETURN + return + + if(!(parrot_interest in view(src))) + parrot_state = PARROT_SWOOP | PARROT_RETURN + return + + if(Adjacent(parrot_interest)) + + if(isliving(parrot_interest)) + steal_from_mob() + + else //This should ensure that we only grab the item we want, and make sure it's not already collected on our perch + if(!parrot_perch || parrot_interest.loc != parrot_perch.loc) + held_item = parrot_interest + parrot_interest.loc = src + visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.") + + parrot_interest = null + parrot_state = PARROT_SWOOP | PARROT_RETURN + return + + walk_to(src, parrot_interest, 1, parrot_speed) + if(isStuck()) return + + return + +//-----RETURNING TO PERCH + else if(parrot_state == (PARROT_SWOOP | PARROT_RETURN)) + walk(src, 0) + if(!parrot_perch || !isturf(parrot_perch.loc)) //Make sure the perch exists and somehow isnt inside of something else. + parrot_perch = null + parrot_state = PARROT_WANDER + return + + if(Adjacent(parrot_perch)) + src.loc = parrot_perch.loc + drop_held_item() + parrot_state = PARROT_PERCH + icon_state = "parrot_sit" + return + + walk_to(src, parrot_perch, 1, parrot_speed) + if(isStuck()) return + + return + +//-----FLEEING + else if(parrot_state == (PARROT_SWOOP | PARROT_FLEE)) + walk(src,0) + if(!parrot_interest || !isliving(parrot_interest)) //Sanity + parrot_state = PARROT_WANDER + + walk_away(src, parrot_interest, 1, parrot_speed) + /*if(parrot_been_shot > 0) + parrot_been_shot-- didn't work anyways, and besides, any bullet poly survives isn't worth the speed boost.*/ + if(isStuck()) return + + return + +//-----ATTACKING + else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK)) + + //If we're attacking a nothing, an object, a turf or a ghost for some stupid reason, switch to wander + if(!parrot_interest || !isliving(parrot_interest)) + parrot_interest = null + parrot_state = PARROT_WANDER + return + + var/mob/living/L = parrot_interest + if(melee_damage_upper == 0) + melee_damage_upper = parrot_damage_upper + a_intent = I_HURT + + //If the mob is close enough to interact with + if(Adjacent(parrot_interest)) + + //If the mob we've been chasing/attacking dies or falls into crit, check for loot! + if(L.stat) + parrot_interest = null + if(!held_item) + held_item = steal_from_ground() + if(!held_item) + held_item = steal_from_mob() //Apparently it's possible for dead mobs to hang onto items in certain circumstances. + if(parrot_perch in view(src)) //If we have a home nearby, go to it, otherwise find a new home + parrot_state = PARROT_SWOOP | PARROT_RETURN + else + parrot_state = PARROT_WANDER + return + + attacktext = pick("claws at", "chomps") + L.attack_animal(src)//Time for the hurt to begin! + //Otherwise, fly towards the mob! + else + walk_to(src, parrot_interest, 1, parrot_speed) + if(isStuck()) return + + return +//-----STATE MISHAP + else //This should not happen. If it does lets reset everything and try again + walk(src,0) + parrot_interest = null + parrot_perch = null + drop_held_item() + parrot_state = PARROT_WANDER + return + +/* + * Procs + */ + +/mob/living/simple_animal/parrot/movement_delay() + if(client && stat == CONSCIOUS && parrot_state != "parrot_fly") + icon_state = "parrot_fly" + ..() + +/mob/living/simple_animal/parrot/proc/isStuck() + //Check to see if the parrot is stuck due to things like windows or doors or windowdoors + if(parrot_lastmove) + if(parrot_lastmove == src.loc) + if(parrot_stuck_threshold >= ++parrot_stuck) //If it has been stuck for a while, go back to wander. + parrot_state = PARROT_WANDER + parrot_stuck = 0 + parrot_lastmove = null + return 1 + else + parrot_lastmove = null + else + parrot_lastmove = src.loc + return 0 + +/mob/living/simple_animal/parrot/proc/search_for_item() + for(var/atom/movable/AM in view(src)) + //Skip items we already stole or are wearing or are too big + if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src) + continue + + if(istype(AM, /obj/item)) + var/obj/item/I = AM + if(I.w_class < 2) + return I + + if(iscarbon(AM)) + var/mob/living/carbon/C = AM + if((C.l_hand && C.l_hand.w_class <= 2) || (C.r_hand && C.r_hand.w_class <= 2)) + return C + return null + +/mob/living/simple_animal/parrot/proc/search_for_perch() + for(var/obj/O in view(src)) + for(var/path in desired_perches) + if(istype(O, path)) + return O + return null + +//This proc was made to save on doing two 'in view' loops seperatly +/mob/living/simple_animal/parrot/proc/search_for_perch_and_item() + for(var/atom/movable/AM in view(src)) + for(var/perch_path in desired_perches) + if(istype(AM, perch_path)) + return AM + + //Skip items we already stole or are wearing or are too big + if(parrot_perch && AM.loc == parrot_perch.loc || AM.loc == src) + continue + + if(istype(AM, /obj/item)) + var/obj/item/I = AM + if(I.w_class <= 2) + return I + + if(iscarbon(AM)) + var/mob/living/carbon/C = AM + if(C.l_hand && C.l_hand.w_class <= 2 || C.r_hand && C.r_hand.w_class <= 2) + return C + return null + + +/* + * Verbs - These are actually procs, but can be used as verbs by player-controlled parrots. + */ +/mob/living/simple_animal/parrot/proc/steal_from_ground() + set name = "Steal from ground" + set category = "Parrot" + set desc = "Grabs a nearby item." + + if(stat) + return -1 + + if(held_item) + to_chat(src, "You are already holding [held_item]") + return 1 + + for(var/obj/item/I in view(1,src)) + if(!Adjacent(I)) + continue + //Make sure we're not already holding it and it's small enough + if(I.loc != src && I.w_class <= 2) + + //If we have a perch and the item is sitting on it, continue + if(!client && parrot_perch && I.loc == parrot_perch.loc) + continue + + held_item = I + I.loc = src + visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.") + return held_item + + to_chat(src, "There is nothing of interest to take.") + return 0 + +/mob/living/simple_animal/parrot/proc/steal_from_mob() + set name = "Steal from mob" + set category = "Parrot" + set desc = "Steals an item right out of a person's hand!" + + if(stat) + return -1 + + if(held_item) + to_chat(src, "You are already holding [held_item]") + return 1 + + var/obj/item/stolen_item = null + + for(var/mob/living/carbon/C in view(1,src)) + if(!Adjacent(C)) + continue + + if(C.l_hand && C.l_hand.w_class <= 2) + stolen_item = C.l_hand + + if(C.r_hand && C.r_hand.w_class <= 2) + stolen_item = C.r_hand + + if(stolen_item) + C.u_equip(stolen_item) + held_item = stolen_item + stolen_item.loc = src + visible_message("[src] grabs [held_item] out of [C]'s hand!", "You snag [held_item] out of [C]'s hand!", "You hear the sounds of wings flapping furiously.") + return held_item + + to_chat(src, "There is nothing of interest to take.") + return 0 + +/mob/living/simple_animal/parrot/verb/drop_held_item_player() + set name = "Drop held item" + set category = "Parrot" + set desc = "Drop the item you're holding." + + if(stat) + return + + src.drop_held_item() + + return + +/mob/living/simple_animal/parrot/proc/drop_held_item(var/drop_gently = 1) + set name = "Drop held item" + set category = "Parrot" + set desc = "Drop the item you're holding." + + if(stat) + return -1 + + if(!held_item) + if(src == usr) //So that other mobs wont make this message appear when they're bludgeoning you. + to_chat(src, "You have nothing to drop!") + return 0 + + +//parrots will eat crackers instead of dropping them + if(istype(held_item,/obj/item/weapon/reagent_containers/food/snacks/cracker) && (drop_gently)) + qdel(held_item) + held_item = null + if(health < maxHealth) + adjustBruteLoss(-10) + emote("[src] eagerly downs the cracker") + playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) + return 1 + + + if(!drop_gently) + if(istype(held_item, /obj/item/weapon/grenade)) + var/obj/item/weapon/grenade/G = held_item + G.loc = src.loc + G.prime() + to_chat(src, "You let go of [held_item]!") + held_item = null + return 1 + + to_chat(src, "You drop [held_item].") + + held_item.loc = src.loc + held_item = null + return 1 + +/mob/living/simple_animal/parrot/proc/perch_player() + set name = "Sit" + set category = "Parrot" + set desc = "Sit on a nice comfy perch." + + if(stat || !client) + return + + if(icon_state == "parrot_fly") + for(var/atom/movable/AM in view(src,1)) + if(!Adjacent(AM)) + continue + for(var/perch_path in desired_perches) + if(istype(AM, perch_path)) + forceMove(AM.loc) + icon_state = "parrot_sit" + return + to_chat(src, "There is no perch nearby to sit on.") + return + +/mob/living/simple_animal/parrot/proc/toggle_mode() + set name = "Toggle mode" + set category = "Parrot" + set desc = "Time to bear those claws!" + + if(stat || !client) + return + + if(melee_damage_upper) + melee_damage_upper = 0 + a_intent = I_HELP + else + melee_damage_upper = parrot_damage_upper + a_intent = I_HURT + return + +/* + * Sub-types + */ +/mob/living/simple_animal/parrot/Poly + name = "Poly" + desc = "Poly the Parrot. An expert on quantum cracker theory." + speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE") + +/mob/living/simple_animal/parrot/Poly/New() + ears = new /obj/item/device/radio/headset/headset_eng(src) + available_channels = list(":e") + ..() diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index a9bcc8c6eff..49a08648b5c 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -1,110 +1,110 @@ -/mob/living/simple_animal/shade - name = "Shade" - real_name = "Shade" - desc = "A bound spirit" - icon = 'icons/mob/mob.dmi' - icon_state = "shade" - icon_living = "shade" - icon_dead = "shade_dead" - maxHealth = 50 - health = 50 - speak_emote = list("hisses") - emote_hear = list("wails","screeches") - response_help = "puts their hand through" - response_disarm = "flails at" - response_harm = "punches" - melee_damage_lower = 5 - melee_damage_upper = 15 - attacktext = "drains the life from" - minbodytemp = 0 - maxbodytemp = 4000 - min_oxy = 0 - max_co2 = 0 - max_tox = 0 - speed = -1 - stop_automated_movement = 1 - status_flags = 0 - faction = "cult" - status_flags = CANPUSH - supernatural = 1 - flying = 1 - meat_type = /obj/item/weapon/ectoplasm - -/mob/living/simple_animal/shade/gib() - death(1) - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - dead_mob_list -= src - - qdel(src) - -/mob/living/simple_animal/shade/cultify() - return - -/mob/living/simple_animal/shade/Life() - if(timestopped) return 0 //under effects of time magick - ..() - if(stat == 2) - for(var/i=0;i<3;i++) - new /obj/item/weapon/ectoplasm (src.loc) - for(var/mob/M in viewers(src, null)) - if((M.client && !( M.blinded ))) - M.show_message(" [src] lets out a contented sigh as their form unwinds.") - ghostize() - qdel (src) - return - - -/mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri - user.delayNextAttack(8) - if(istype(O, /obj/item/device/soulstone)) - O.transfer_soul("SHADE", src, user) - else - if(O.force) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - if(istype(O,/obj/item/weapon/nullrod)) - damage *= 2 - purge = 3 - health -= damage - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message(" [src] has been attacked with [O] by [user].") - else - to_chat(usr, " This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message(" [user] gently taps [src] with [O].") - return - -/mob/living/simple_animal/shade/shuttle_act() - if(!(src.flags & INVULNERABLE)) - health -= rand(5,45) //These guys are like ghosts, a collision with a shuttle wouldn't destroy one outright - return - -////////////////HUD////////////////////// - -/mob/living/simple_animal/shade/Life() - if(timestopped) return 0 //under effects of time magick - . = ..() - - if(pullin) - pullin.icon_state = "pull1" - - if(purged) - if(purge > 0) purged.icon_state = "purge1" - else purged.icon_state = "purge0" - - switch(health) - if(50 to INFINITY) healths.icon_state = "shade_health0" - if(41 to 49) healths.icon_state = "shade_health1" - if(33 to 40) healths.icon_state = "shade_health2" - if(25 to 32) healths.icon_state = "shade_health3" - if(17 to 24) healths.icon_state = "shade_health4" - if(9 to 16) healths.icon_state = "shade_health5" - if(1 to 8) healths.icon_state = "shade_health6" +/mob/living/simple_animal/shade + name = "Shade" + real_name = "Shade" + desc = "A bound spirit" + icon = 'icons/mob/mob.dmi' + icon_state = "shade" + icon_living = "shade" + icon_dead = "shade_dead" + maxHealth = 50 + health = 50 + speak_emote = list("hisses") + emote_hear = list("wails","screeches") + response_help = "puts their hand through" + response_disarm = "flails at" + response_harm = "punches" + melee_damage_lower = 5 + melee_damage_upper = 15 + attacktext = "drains the life from" + minbodytemp = 0 + maxbodytemp = 4000 + min_oxy = 0 + max_co2 = 0 + max_tox = 0 + speed = -1 + stop_automated_movement = 1 + status_flags = 0 + faction = "cult" + status_flags = CANPUSH + supernatural = 1 + flying = 1 + meat_type = /obj/item/weapon/ectoplasm + +/mob/living/simple_animal/shade/gib() + death(1) + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + dead_mob_list -= src + + qdel(src) + +/mob/living/simple_animal/shade/cultify() + return + +/mob/living/simple_animal/shade/Life() + if(timestopped) return 0 //under effects of time magick + ..() + if(stat == 2) + for(var/i=0;i<3;i++) + new /obj/item/weapon/ectoplasm (src.loc) + for(var/mob/M in viewers(src, null)) + if((M.client && !( M.blinded ))) + M.show_message(" [src] lets out a contented sigh as their form unwinds.") + ghostize() + qdel (src) + return + + +/mob/living/simple_animal/shade/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri + user.delayNextAttack(8) + if(istype(O, /obj/item/device/soulstone)) + O.transfer_soul("SHADE", src, user) + else + if(O.force) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + if(istype(O,/obj/item/weapon/nullrod)) + damage *= 2 + purge = 3 + health -= damage + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message(" [src] has been attacked with [O] by [user].") + else + to_chat(usr, " This weapon is ineffective, it does no damage.") + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message(" [user] gently taps [src] with [O].") + return + +/mob/living/simple_animal/shade/shuttle_act() + if(!(src.flags & INVULNERABLE)) + health -= rand(5,45) //These guys are like ghosts, a collision with a shuttle wouldn't destroy one outright + return + +////////////////HUD////////////////////// + +/mob/living/simple_animal/shade/Life() + if(timestopped) return 0 //under effects of time magick + . = ..() + + if(pullin) + pullin.icon_state = "pull1" + + if(purged) + if(purge > 0) purged.icon_state = "purge1" + else purged.icon_state = "purge0" + + switch(health) + if(50 to INFINITY) healths.icon_state = "shade_health0" + if(41 to 49) healths.icon_state = "shade_health1" + if(33 to 40) healths.icon_state = "shade_health2" + if(25 to 32) healths.icon_state = "shade_health3" + if(17 to 24) healths.icon_state = "shade_health4" + if(9 to 16) healths.icon_state = "shade_health5" + if(1 to 8) healths.icon_state = "shade_health6" else healths.icon_state = "shade_health7" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index dc24a49beef..2f8628d9586 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -1,669 +1,669 @@ -var/const/ANIMAL_CHILD_CAP = 50 -var/global/list/animal_count = list() //Stores types, and amount of animals of that type associated with the type (example: /mob/living/simple_animal/dog = 10) -//Animals can't breed if amount of children exceeds 50 - -/mob/living/simple_animal - name = "animal" - icon = 'icons/mob/animal.dmi' - health = 20 - maxHealth = 20 - treadmill_speed = 0.5 //Ian & pals aren't as good at powering a treadmill - - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal - - var/icon_living = "" - var/icon_dead = "" - var/icon_gib = null //We only try to show a gibbing animation if this exists. - - var/list/speak = list() - //var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. - var/speak_chance = 0 - var/list/emote_hear = list() //Hearable emotes - var/list/emote_see = list() //Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps - - var/turns_per_move = 1 - var/turns_since_move = 0 - - var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals. - var/wander = 1 // Does the mob wander around when idle? - var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it. - - //Interaction - var/response_help = "pokes" - var/response_disarm = "shoves" - var/response_harm = "hits" - var/harm_intent_damage = 3 - - //Temperature effect - var/minbodytemp = 250 - var/maxbodytemp = 350 - var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp - var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp - var/fire_alert = 0 - var/oxygen_alert = 0 - var/toxins_alert = 0 - - var/show_stat_health = 1 //does the percentage health show in the stat panel for the mob - - //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage - var/min_oxy = 5 - var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum - var/min_tox = 0 - var/max_tox = 1 - var/min_co2 = 0 - var/max_co2 = 5 - var/min_n2 = 0 - var/max_n2 = 0 - var/unsuitable_atoms_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above - - - mob_bump_flag = SIMPLE_ANIMAL - mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL - mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL - - //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly - var/melee_damage_lower = 0 - var/melee_damage_upper = 0 - var/melee_damage_type = BRUTE - var/attacktext = "attacks" - var/attack_sound = null - var/friendly = "nuzzles" //If the mob does no damage with it's attack - var/environment_smash = 0 //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls - - var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster - - //Hot simple_animal baby making vars - var/childtype = null - var/child_amount = 1 - var/scan_ready = 1 - var/can_breed = 0 - - //Null rod stuff - var/supernatural = 0 - var/purge = 0 - - universal_speak = 1 - universal_understand = 1 - - var/life_tick = 0 - -/mob/living/simple_animal/apply_beam_damage(var/obj/effect/beam/B) - var/lastcheck=last_beamchecks["\ref[B]"] - - var/damage = ((world.time - lastcheck)/10) * (B.get_damage()/2) - - // Actually apply damage - health -= damage - - // Update check time. - last_beamchecks["\ref[B]"]=world.time - -/mob/living/simple_animal/rejuvenate(animation = 0) - var/turf/T = get_turf(src) - if(animation) T.turf_animation('icons/effects/64x64.dmi',"rejuvinate",-16,0,MOB_LAYER+1,'sound/effects/rejuvinate.ogg') - src.health = src.maxHealth - return 1 -/mob/living/simple_animal/New() - ..() - verbs -= /mob/verb/observe - if(!real_name) - real_name = name - - animal_count[src.type]++ - -/mob/living/simple_animal/Login() - if(src && src.client) - src.client.reset_screen() - ..() - -/mob/living/simple_animal/updatehealth() - return - -/mob/living/simple_animal/airflow_stun() - return - -/mob/living/simple_animal/airflow_hit(atom/A) - return - -// For changing wander behavior -/mob/living/simple_animal/proc/wander_move(var/turf/dest) - Move(dest) - -/mob/living/simple_animal/Life() - if(timestopped) return 0 //under effects of time magick - ..() - - //Health - if(stat == DEAD) - if(health > 0) - icon_state = icon_living - src.resurrect() - stat = CONSCIOUS - density = 1 - update_canmove() - return 0 - - - if(health < 1 && stat != DEAD) - Die() - return 0 - - life_tick++ - - health = min(health, maxHealth) - - if(stunned) - AdjustStunned(-1) - if(weakened) - AdjustWeakened(-1) - if(paralysis) - AdjustParalysis(-1) - - if(purge) - purge -= 1 - - //Movement - if((!client||deny_client_move) && !stop_automated_movement && wander && !anchored && (ckey == null) && !(flags & INVULNERABLE)) - if(isturf(src.loc) && !resting && !locked_to && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. - turns_since_move++ - if(turns_since_move >= turns_per_move) - if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled - var/destination = get_step(src, pick(cardinal)) - wander_move(destination) - turns_since_move = 0 - - //Speaking - if(!client && speak_chance && (ckey == null)) - if(rand(0,200) < speak_chance) - if(speak && speak.len) - if((emote_hear && emote_hear.len) || (emote_see && emote_see.len)) - var/length = speak.len - if(emote_hear && emote_hear.len) - length += emote_hear.len - if(emote_see && emote_see.len) - length += emote_see.len - var/randomValue = rand(1,length) - if(randomValue <= speak.len) - say(pick(speak)) - else - randomValue -= speak.len - if(emote_see && randomValue <= emote_see.len) - emote(pick(emote_see),1) - else - emote(pick(emote_hear),2) - else - say(pick(speak)) - else - if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len)) - emote(pick(emote_see),1) - if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len)) - emote(pick(emote_hear),2) - if((emote_hear && emote_hear.len) && (emote_see && emote_see.len)) - var/length = emote_hear.len + emote_see.len - var/pick = rand(1,length) - if(pick <= emote_see.len) - emote(pick(emote_see),1) - else - emote(pick(emote_hear),2) - - - //Atmos - if(flags & INVULNERABLE) - return 1 - - var/atmos_suitable = 1 - - var/atom/A = loc - - if(isturf(A)) - var/turf/T = A - var/datum/gas_mixture/Environment = T.return_air() - - if(Environment) - if(abs(Environment.temperature - bodytemperature) > 40) - bodytemperature += ((Environment.temperature - bodytemperature) / 5) - - if(min_oxy) - if(Environment.oxygen < min_oxy) - atmos_suitable = 0 - oxygen_alert = 1 - else - oxygen_alert = 0 - - if(max_oxy) - if(Environment.oxygen > max_oxy) - atmos_suitable = 0 - - if(min_tox) - if(Environment.toxins < min_tox) - atmos_suitable = 0 - - if(max_tox) - if(Environment.toxins > max_tox) - atmos_suitable = 0 - toxins_alert = 1 - else - toxins_alert = 0 - - if(min_n2) - if(Environment.nitrogen < min_n2) - atmos_suitable = 0 - - if(max_n2) - if(Environment.nitrogen > max_n2) - atmos_suitable = 0 - - if(min_co2) - if(Environment.carbon_dioxide < min_co2) - atmos_suitable = 0 - - if(max_co2) - if(Environment.carbon_dioxide > max_co2) - atmos_suitable = 0 - - //Atmos effect - if(bodytemperature < minbodytemp) - fire_alert = 2 - adjustBruteLoss(cold_damage_per_tick) - else if(bodytemperature > maxbodytemp) - fire_alert = 1 - adjustBruteLoss(heat_damage_per_tick) - else - fire_alert = 0 - - if(!atmos_suitable) - adjustBruteLoss(unsuitable_atoms_damage) - - if(can_breed) - make_babies() - - return 1 - -/mob/living/simple_animal/gib(var/animation = 0, var/meat = 1) - if(icon_gib) - flick(icon_gib, src) - - if(meat && meat_type) - for(var/i = 0; i < (src.size - meat_taken); i++) - drop_meat(get_turf(src)) - - ..() - - -/mob/living/simple_animal/blob_act() - adjustBruteLoss(20) - return - -/mob/living/simple_animal/say_quote(var/text) - if(speak_emote && speak_emote.len) - var/emote = pick(speak_emote) - if(emote) - return "[emote], [text]" - return "says, [text]"; - -/mob/living/simple_animal/emote(var/act, var/type, var/desc) - if(timestopped) return //under effects of time magick - if(stat) - return - if(act == "scream") - desc = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P - act = "me" - ..(act, type, desc) - -/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob) - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - else - M.attack_log += text("\[[time_stamp()]\] [M.attacktext] [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been [M.attacktext] by [M.name] ([M.ckey])") - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("\The [M] [M.attacktext] [src]!", 1) - add_logs(M, src, "attacked", admin=0) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage,M.melee_damage_type) - updatehealth() - -/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) - if(!Proj) return - // FUCK mice. - N3X - if(ismouse(src) && (Proj.stun+Proj.weaken+Proj.paralyze+Proj.agony)>5) - var/mob/living/simple_animal/mouse/M=src - to_chat(M, "What would probably not kill a human completely overwhelms your tiny body.") - M.splat() - return 0 - adjustBruteLoss(Proj.damage) - Proj.on_hit(src, 0) - return 0 - -/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M as mob) - ..() - - switch(M.a_intent) - - if(I_HELP) - if (health > 0) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("[M] [response_help] [src].") - - if(I_GRAB) - if (M == src || anchored) - return - if (!(status_flags & CANPUSH)) - return - - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - G.affecting = src - LAssailant = M - - visible_message("[M] has grabbed [src] passively!") - - if(I_HURT, I_DISARM) - adjustBruteLoss(harm_intent_damage) - - visible_message("[M] [response_harm] [src]!") - - return - -/mob/living/simple_animal/MouseDrop(mob/living/carbon/human/M) - if(M != usr) return - if(!istype(M)) return - if(M.isUnconscious())return - if(M.restrained()) return - if(!Adjacent(M)) return - - var/strength_of_M = (M.size - 1) //Can only pick up mobs whose size is less or equal to this value. Normal human's size is 3, so his strength is 2 - he can pick up TINY and SMALL animals. Varediting human's size to 5 will allow him to pick up goliaths. - - if((M.a_intent != I_HELP) && (src.size <= strength_of_M) && (isturf(src.loc)) && (src.holder_type)) - scoop_up(M) - else - ..() - -/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - - switch(M.a_intent) - - if (I_HELP) - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M] caresses [src] with its scythe like arm."), 1) - if (I_GRAB) - if(M == src || anchored) - return - if(!(status_flags & CANPUSH)) - return - - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - G.affecting = src - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has grabbed [] passively!", M, src), 1) - - if(I_HURT, I_DISARM) - var/damage = rand(15, 30) - visible_message("[M] has slashed at [src]!") - adjustBruteLoss(damage) - - return - -/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L as mob) - - switch(L.a_intent) - if(I_HELP) - visible_message("[L] rubs it's head against [src]") - - - else - - var/damage = rand(5, 10) - visible_message("[L] bites [src]!") - - if(stat != DEAD) - adjustBruteLoss(damage) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - - -/mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M as mob) - if (!ticker) - to_chat(M, "You cannot attack people before the game has started.") - return - - if(M.Victim) return // can't attack while eating! - - visible_message("[M.name] glomps [src]!") - - var/damage = rand(1, 3) - - if(istype(M,/mob/living/carbon/slime/adult)) - damage = rand(20, 40) - else - damage = rand(5, 35) - - adjustBruteLoss(damage) - - - return - - -/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri - if(istype(O, /obj/item/stack/medical)) - user.delayNextAttack(4) - if(stat != DEAD) - var/obj/item/stack/medical/MED = O - if(health < maxHealth) - if(MED.use(1)) - adjustBruteLoss(-MED.heal_brute) - src.visible_message("[user] applies \the [MED] to \the [src].") - else - to_chat(user, "This [src] is dead, medical items won't bring it back to life.") - else if((meat_type || butchering_drops) && (stat == DEAD)) //if the animal has a meat, and if it is dead. - if(O.is_sharp()) - if(user.a_intent != I_HELP) - to_chat(user, "You must be on help intent to do this!") - else - butcher() - return 1 - else - user.delayNextAttack(8) - if(O.force) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - if(supernatural && istype(O,/obj/item/weapon/nullrod)) - damage *= 2 - purge = 3 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[src] has been attacked with the [O] by [user]. ") - else - to_chat(usr, "This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[user] gently taps [src] with the [O]. ") - -/mob/living/simple_animal/movement_delay() - var/tally = 0 //Incase I need to add stuff other than "speed" later - - tally = speed - - if(purge)//Purged creatures will move more slowly. The more time before their purge stops, the slower they'll move. (muh dotuh) - if(tally <= 0) - tally = 1 - tally *= purge - - if(istype(loc,/turf/simulated/floor)) - var/turf/simulated/floor/T = loc - - if(T.material=="phazon") - return -1 // Phazon floors make us go fast - - return tally+config.animal_delay - -/mob/living/simple_animal/Stat() - ..() - - if(statpanel("Status") && show_stat_health) - stat(null, "Health: [round((health / maxHealth) * 100)]%") - -/mob/living/simple_animal/proc/Die() - health = 0 // so /mob/living/simple_animal/Life() doesn't magically revive them - living_mob_list -= src - dead_mob_list += src - icon_state = icon_dead - stat = DEAD - density = 0 - - animal_count[src.type]-- - if(!src.butchering_drops && animal_butchering_products[src.species_type]) //If we already created a list of butchering drops, don't create another one - var/list/L = animal_butchering_products[src.species_type] - src.butchering_drops = list() - - for(var/butchering_type in L) - src.butchering_drops += new butchering_type - - verbs += /mob/living/proc/butcher - - return - -/mob/living/simple_animal/death(gibbed) - if(stat == DEAD) - return - - if(!gibbed) - visible_message("\the [src] stops moving...") - - Die() - -/mob/living/simple_animal/ex_act(severity) - if(flags & INVULNERABLE) - return - ..() - switch (severity) - if (1.0) - adjustBruteLoss(500) - gib() - return - - if (2.0) - adjustBruteLoss(60) - - - if(3.0) - adjustBruteLoss(30) - -/mob/living/simple_animal/adjustBruteLoss(damage) - health = Clamp(health - damage, 0, maxHealth) - if(health < 1 && stat != DEAD) - Die() - -/mob/living/simple_animal/proc/SA_attackable(target) - return CanAttack(target) - -/mob/living/simple_animal/proc/CanAttack(var/atom/target) - if(see_invisible < target.invisibility) - return 0 - if (isliving(target)) - var/mob/living/L = target - if(!L.stat && L.health >= 0) - return (0) - if (istype(target,/obj/mecha)) - var/obj/mecha/M = target - if (M.occupant) - return (0) - if (istype(target,/obj/machinery/bot)) - var/obj/machinery/bot/B = target - if(B.health > 0) - return (0) - return (1) - -//Call when target overlay should be added/removed -/mob/living/simple_animal/update_targeted() - if(!targeted_by && target_locked) - del(target_locked) - overlays = null - if (targeted_by && target_locked) - overlays += target_locked - - - -/mob/living/simple_animal/update_fire() - return -/mob/living/simple_animal/IgniteMob() - return -/mob/living/simple_animal/ExtinguishMob() - return - -/mob/living/simple_animal/revive() - health = maxHealth - butchering_drops = null - meat_taken = 0 - ..() - -/mob/living/simple_animal/proc/make_babies() // <3 <3 <3 - if(gender != FEMALE || stat || !scan_ready || !childtype || !species_type) - return - scan_ready = 0 - spawn(400) - scan_ready = 1 - var/alone = 1 - var/mob/living/simple_animal/partner - var/children = 0 - for(var/mob/M in oview(7, src)) - if(M.stat != CONSCIOUS) //Check if it's concious FIRSTER. - continue - else if(istype(M, childtype)) //Check for children FIRST. - children++ - else if(istype(M, species_type)) - if(M.client) - continue - else if(!istype(M, childtype) && M.gender == MALE) //Better safe than sorry ;_; - partner = M - else if(istype(M, /mob/living)) - if(!istype(M, /mob/dead/observer) || M.stat != DEAD) //Make babies with ghosts or dead people nearby! - alone = 0 - continue - if(alone && partner && children < 3) - give_birth() - -/mob/living/simple_animal/proc/give_birth() - for(var/i=1; i<=child_amount; i++) - if(animal_count[childtype] > ANIMAL_CHILD_CAP) - break - - var/mob/living/simple_animal/child = new childtype(loc) - if(istype(child)) - child.faction = src.faction - -/mob/living/simple_animal/say_understands(var/mob/other,var/datum/language/speaking = null) - if(other) other = other.GetSource() - if(issilicon(other)) - return 1 - return ..() - -/mob/living/simple_animal/proc/reagent_act(id, method, volume) - if(isDead()) return - - switch(id) - if("sacid") - if(!supernatural) - adjustBruteLoss(volume * 0.5) - if("pacid") - if(!supernatural) - adjustBruteLoss(volume * 0.5) +var/const/ANIMAL_CHILD_CAP = 50 +var/global/list/animal_count = list() //Stores types, and amount of animals of that type associated with the type (example: /mob/living/simple_animal/dog = 10) +//Animals can't breed if amount of children exceeds 50 + +/mob/living/simple_animal + name = "animal" + icon = 'icons/mob/animal.dmi' + health = 20 + maxHealth = 20 + treadmill_speed = 0.5 //Ian & pals aren't as good at powering a treadmill + + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal + + var/icon_living = "" + var/icon_dead = "" + var/icon_gib = null //We only try to show a gibbing animation if this exists. + + var/list/speak = list() + //var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. + var/speak_chance = 0 + var/list/emote_hear = list() //Hearable emotes + var/list/emote_see = list() //Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps + + var/turns_per_move = 1 + var/turns_since_move = 0 + + var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals. + var/wander = 1 // Does the mob wander around when idle? + var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it. + + //Interaction + var/response_help = "pokes" + var/response_disarm = "shoves" + var/response_harm = "hits" + var/harm_intent_damage = 3 + + //Temperature effect + var/minbodytemp = 250 + var/maxbodytemp = 350 + var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp + var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp + var/fire_alert = 0 + var/oxygen_alert = 0 + var/toxins_alert = 0 + + var/show_stat_health = 1 //does the percentage health show in the stat panel for the mob + + //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage + var/min_oxy = 5 + var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum + var/min_tox = 0 + var/max_tox = 1 + var/min_co2 = 0 + var/max_co2 = 5 + var/min_n2 = 0 + var/max_n2 = 0 + var/unsuitable_atoms_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above + + + mob_bump_flag = SIMPLE_ANIMAL + mob_swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL + mob_push_flags = MONKEY|SLIME|SIMPLE_ANIMAL + + //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly + var/melee_damage_lower = 0 + var/melee_damage_upper = 0 + var/melee_damage_type = BRUTE + var/attacktext = "attacks" + var/attack_sound = null + var/friendly = "nuzzles" //If the mob does no damage with it's attack + var/environment_smash = 0 //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls + + var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster + + //Hot simple_animal baby making vars + var/childtype = null + var/child_amount = 1 + var/scan_ready = 1 + var/can_breed = 0 + + //Null rod stuff + var/supernatural = 0 + var/purge = 0 + + universal_speak = 1 + universal_understand = 1 + + var/life_tick = 0 + +/mob/living/simple_animal/apply_beam_damage(var/obj/effect/beam/B) + var/lastcheck=last_beamchecks["\ref[B]"] + + var/damage = ((world.time - lastcheck)/10) * (B.get_damage()/2) + + // Actually apply damage + health -= damage + + // Update check time. + last_beamchecks["\ref[B]"]=world.time + +/mob/living/simple_animal/rejuvenate(animation = 0) + var/turf/T = get_turf(src) + if(animation) T.turf_animation('icons/effects/64x64.dmi',"rejuvinate",-16,0,MOB_LAYER+1,'sound/effects/rejuvinate.ogg') + src.health = src.maxHealth + return 1 +/mob/living/simple_animal/New() + ..() + verbs -= /mob/verb/observe + if(!real_name) + real_name = name + + animal_count[src.type]++ + +/mob/living/simple_animal/Login() + if(src && src.client) + src.client.reset_screen() + ..() + +/mob/living/simple_animal/updatehealth() + return + +/mob/living/simple_animal/airflow_stun() + return + +/mob/living/simple_animal/airflow_hit(atom/A) + return + +// For changing wander behavior +/mob/living/simple_animal/proc/wander_move(var/turf/dest) + Move(dest) + +/mob/living/simple_animal/Life() + if(timestopped) return 0 //under effects of time magick + ..() + + //Health + if(stat == DEAD) + if(health > 0) + icon_state = icon_living + src.resurrect() + stat = CONSCIOUS + density = 1 + update_canmove() + return 0 + + + if(health < 1 && stat != DEAD) + Die() + return 0 + + life_tick++ + + health = min(health, maxHealth) + + if(stunned) + AdjustStunned(-1) + if(weakened) + AdjustWeakened(-1) + if(paralysis) + AdjustParalysis(-1) + + if(purge) + purge -= 1 + + //Movement + if((!client||deny_client_move) && !stop_automated_movement && wander && !anchored && (ckey == null) && !(flags & INVULNERABLE)) + if(isturf(src.loc) && !resting && !locked_to && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. + turns_since_move++ + if(turns_since_move >= turns_per_move) + if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled + var/destination = get_step(src, pick(cardinal)) + wander_move(destination) + turns_since_move = 0 + + //Speaking + if(!client && speak_chance && (ckey == null)) + if(rand(0,200) < speak_chance) + if(speak && speak.len) + if((emote_hear && emote_hear.len) || (emote_see && emote_see.len)) + var/length = speak.len + if(emote_hear && emote_hear.len) + length += emote_hear.len + if(emote_see && emote_see.len) + length += emote_see.len + var/randomValue = rand(1,length) + if(randomValue <= speak.len) + say(pick(speak)) + else + randomValue -= speak.len + if(emote_see && randomValue <= emote_see.len) + emote(pick(emote_see),1) + else + emote(pick(emote_hear),2) + else + say(pick(speak)) + else + if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len)) + emote(pick(emote_see),1) + if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len)) + emote(pick(emote_hear),2) + if((emote_hear && emote_hear.len) && (emote_see && emote_see.len)) + var/length = emote_hear.len + emote_see.len + var/pick = rand(1,length) + if(pick <= emote_see.len) + emote(pick(emote_see),1) + else + emote(pick(emote_hear),2) + + + //Atmos + if(flags & INVULNERABLE) + return 1 + + var/atmos_suitable = 1 + + var/atom/A = loc + + if(isturf(A)) + var/turf/T = A + var/datum/gas_mixture/Environment = T.return_air() + + if(Environment) + if(abs(Environment.temperature - bodytemperature) > 40) + bodytemperature += ((Environment.temperature - bodytemperature) / 5) + + if(min_oxy) + if(Environment.oxygen < min_oxy) + atmos_suitable = 0 + oxygen_alert = 1 + else + oxygen_alert = 0 + + if(max_oxy) + if(Environment.oxygen > max_oxy) + atmos_suitable = 0 + + if(min_tox) + if(Environment.toxins < min_tox) + atmos_suitable = 0 + + if(max_tox) + if(Environment.toxins > max_tox) + atmos_suitable = 0 + toxins_alert = 1 + else + toxins_alert = 0 + + if(min_n2) + if(Environment.nitrogen < min_n2) + atmos_suitable = 0 + + if(max_n2) + if(Environment.nitrogen > max_n2) + atmos_suitable = 0 + + if(min_co2) + if(Environment.carbon_dioxide < min_co2) + atmos_suitable = 0 + + if(max_co2) + if(Environment.carbon_dioxide > max_co2) + atmos_suitable = 0 + + //Atmos effect + if(bodytemperature < minbodytemp) + fire_alert = 2 + adjustBruteLoss(cold_damage_per_tick) + else if(bodytemperature > maxbodytemp) + fire_alert = 1 + adjustBruteLoss(heat_damage_per_tick) + else + fire_alert = 0 + + if(!atmos_suitable) + adjustBruteLoss(unsuitable_atoms_damage) + + if(can_breed) + make_babies() + + return 1 + +/mob/living/simple_animal/gib(var/animation = 0, var/meat = 1) + if(icon_gib) + flick(icon_gib, src) + + if(meat && meat_type) + for(var/i = 0; i < (src.size - meat_taken); i++) + drop_meat(get_turf(src)) + + ..() + + +/mob/living/simple_animal/blob_act() + adjustBruteLoss(20) + return + +/mob/living/simple_animal/say_quote(var/text) + if(speak_emote && speak_emote.len) + var/emote = pick(speak_emote) + if(emote) + return "[emote], [text]" + return "says, [text]"; + +/mob/living/simple_animal/emote(var/act, var/type, var/desc) + if(timestopped) return //under effects of time magick + if(stat) + return + if(act == "scream") + desc = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P + act = "me" + ..(act, type, desc) + +/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob) + if(M.melee_damage_upper == 0) + M.emote("[M.friendly] [src]") + else + M.attack_log += text("\[[time_stamp()]\] [M.attacktext] [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been [M.attacktext] by [M.name] ([M.ckey])") + if(M.attack_sound) + playsound(loc, M.attack_sound, 50, 1, 1) + for(var/mob/O in viewers(src, null)) + O.show_message("\The [M] [M.attacktext] [src]!", 1) + add_logs(M, src, "attacked", admin=0) + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + adjustBruteLoss(damage,M.melee_damage_type) + updatehealth() + +/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) + if(!Proj) return + // FUCK mice. - N3X + if(ismouse(src) && (Proj.stun+Proj.weaken+Proj.paralyze+Proj.agony)>5) + var/mob/living/simple_animal/mouse/M=src + to_chat(M, "What would probably not kill a human completely overwhelms your tiny body.") + M.splat() + return 0 + adjustBruteLoss(Proj.damage) + Proj.on_hit(src, 0) + return 0 + +/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M as mob) + ..() + + switch(M.a_intent) + + if(I_HELP) + if (health > 0) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("[M] [response_help] [src].") + + if(I_GRAB) + if (M == src || anchored) + return + if (!(status_flags & CANPUSH)) + return + + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + G.affecting = src + LAssailant = M + + visible_message("[M] has grabbed [src] passively!") + + if(I_HURT, I_DISARM) + adjustBruteLoss(harm_intent_damage) + + visible_message("[M] [response_harm] [src]!") + + return + +/mob/living/simple_animal/MouseDrop(mob/living/carbon/human/M) + if(M != usr) return + if(!istype(M)) return + if(M.isUnconscious())return + if(M.restrained()) return + if(!Adjacent(M)) return + + var/strength_of_M = (M.size - 1) //Can only pick up mobs whose size is less or equal to this value. Normal human's size is 3, so his strength is 2 - he can pick up TINY and SMALL animals. Varediting human's size to 5 will allow him to pick up goliaths. + + if((M.a_intent != I_HELP) && (src.size <= strength_of_M) && (isturf(src.loc)) && (src.holder_type)) + scoop_up(M) + else + ..() + +/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + + switch(M.a_intent) + + if (I_HELP) + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[M] caresses [src] with its scythe like arm."), 1) + if (I_GRAB) + if(M == src || anchored) + return + if(!(status_flags & CANPUSH)) + return + + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + G.affecting = src + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[] has grabbed [] passively!", M, src), 1) + + if(I_HURT, I_DISARM) + var/damage = rand(15, 30) + visible_message("[M] has slashed at [src]!") + adjustBruteLoss(damage) + + return + +/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L as mob) + + switch(L.a_intent) + if(I_HELP) + visible_message("[L] rubs it's head against [src]") + + + else + + var/damage = rand(5, 10) + visible_message("[L] bites [src]!") + + if(stat != DEAD) + adjustBruteLoss(damage) + L.amount_grown = min(L.amount_grown + damage, L.max_grown) + + +/mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M as mob) + if (!ticker) + to_chat(M, "You cannot attack people before the game has started.") + return + + if(M.Victim) return // can't attack while eating! + + visible_message("[M.name] glomps [src]!") + + var/damage = rand(1, 3) + + if(istype(M,/mob/living/carbon/slime/adult)) + damage = rand(20, 40) + else + damage = rand(5, 35) + + adjustBruteLoss(damage) + + + return + + +/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri + if(istype(O, /obj/item/stack/medical)) + user.delayNextAttack(4) + if(stat != DEAD) + var/obj/item/stack/medical/MED = O + if(health < maxHealth) + if(MED.use(1)) + adjustBruteLoss(-MED.heal_brute) + src.visible_message("[user] applies \the [MED] to \the [src].") + else + to_chat(user, "This [src] is dead, medical items won't bring it back to life.") + else if((meat_type || butchering_drops) && (stat == DEAD)) //if the animal has a meat, and if it is dead. + if(O.is_sharp()) + if(user.a_intent != I_HELP) + to_chat(user, "You must be on help intent to do this!") + else + butcher() + return 1 + else + user.delayNextAttack(8) + if(O.force) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + if(supernatural && istype(O,/obj/item/weapon/nullrod)) + damage *= 2 + purge = 3 + adjustBruteLoss(damage) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[src] has been attacked with the [O] by [user]. ") + else + to_chat(usr, "This weapon is ineffective, it does no damage.") + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("[user] gently taps [src] with the [O]. ") + +/mob/living/simple_animal/movement_delay() + var/tally = 0 //Incase I need to add stuff other than "speed" later + + tally = speed + + if(purge)//Purged creatures will move more slowly. The more time before their purge stops, the slower they'll move. (muh dotuh) + if(tally <= 0) + tally = 1 + tally *= purge + + if(istype(loc,/turf/simulated/floor)) + var/turf/simulated/floor/T = loc + + if(T.material=="phazon") + return -1 // Phazon floors make us go fast + + return tally+config.animal_delay + +/mob/living/simple_animal/Stat() + ..() + + if(statpanel("Status") && show_stat_health) + stat(null, "Health: [round((health / maxHealth) * 100)]%") + +/mob/living/simple_animal/proc/Die() + health = 0 // so /mob/living/simple_animal/Life() doesn't magically revive them + living_mob_list -= src + dead_mob_list += src + icon_state = icon_dead + stat = DEAD + density = 0 + + animal_count[src.type]-- + if(!src.butchering_drops && animal_butchering_products[src.species_type]) //If we already created a list of butchering drops, don't create another one + var/list/L = animal_butchering_products[src.species_type] + src.butchering_drops = list() + + for(var/butchering_type in L) + src.butchering_drops += new butchering_type + + verbs += /mob/living/proc/butcher + + return + +/mob/living/simple_animal/death(gibbed) + if(stat == DEAD) + return + + if(!gibbed) + visible_message("\the [src] stops moving...") + + Die() + +/mob/living/simple_animal/ex_act(severity) + if(flags & INVULNERABLE) + return + ..() + switch (severity) + if (1.0) + adjustBruteLoss(500) + gib() + return + + if (2.0) + adjustBruteLoss(60) + + + if(3.0) + adjustBruteLoss(30) + +/mob/living/simple_animal/adjustBruteLoss(damage) + health = Clamp(health - damage, 0, maxHealth) + if(health < 1 && stat != DEAD) + Die() + +/mob/living/simple_animal/proc/SA_attackable(target) + return CanAttack(target) + +/mob/living/simple_animal/proc/CanAttack(var/atom/target) + if(see_invisible < target.invisibility) + return 0 + if (isliving(target)) + var/mob/living/L = target + if(!L.stat && L.health >= 0) + return (0) + if (istype(target,/obj/mecha)) + var/obj/mecha/M = target + if (M.occupant) + return (0) + if (istype(target,/obj/machinery/bot)) + var/obj/machinery/bot/B = target + if(B.health > 0) + return (0) + return (1) + +//Call when target overlay should be added/removed +/mob/living/simple_animal/update_targeted() + if(!targeted_by && target_locked) + del(target_locked) + overlays = null + if (targeted_by && target_locked) + overlays += target_locked + + + +/mob/living/simple_animal/update_fire() + return +/mob/living/simple_animal/IgniteMob() + return +/mob/living/simple_animal/ExtinguishMob() + return + +/mob/living/simple_animal/revive() + health = maxHealth + butchering_drops = null + meat_taken = 0 + ..() + +/mob/living/simple_animal/proc/make_babies() // <3 <3 <3 + if(gender != FEMALE || stat || !scan_ready || !childtype || !species_type) + return + scan_ready = 0 + spawn(400) + scan_ready = 1 + var/alone = 1 + var/mob/living/simple_animal/partner + var/children = 0 + for(var/mob/M in oview(7, src)) + if(M.stat != CONSCIOUS) //Check if it's concious FIRSTER. + continue + else if(istype(M, childtype)) //Check for children FIRST. + children++ + else if(istype(M, species_type)) + if(M.client) + continue + else if(!istype(M, childtype) && M.gender == MALE) //Better safe than sorry ;_; + partner = M + else if(istype(M, /mob/living)) + if(!istype(M, /mob/dead/observer) || M.stat != DEAD) //Make babies with ghosts or dead people nearby! + alone = 0 + continue + if(alone && partner && children < 3) + give_birth() + +/mob/living/simple_animal/proc/give_birth() + for(var/i=1; i<=child_amount; i++) + if(animal_count[childtype] > ANIMAL_CHILD_CAP) + break + + var/mob/living/simple_animal/child = new childtype(loc) + if(istype(child)) + child.faction = src.faction + +/mob/living/simple_animal/say_understands(var/mob/other,var/datum/language/speaking = null) + if(other) other = other.GetSource() + if(issilicon(other)) + return 1 + return ..() + +/mob/living/simple_animal/proc/reagent_act(id, method, volume) + if(isDead()) return + + switch(id) + if("sacid") + if(!supernatural) + adjustBruteLoss(volume * 0.5) + if("pacid") + if(!supernatural) + adjustBruteLoss(volume * 0.5) diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm index d29bc5c606e..17260b35f54 100644 --- a/code/modules/mob/living/simple_animal/worm.dm +++ b/code/modules/mob/living/simple_animal/worm.dm @@ -1,203 +1,203 @@ -/mob/living/simple_animal/space_worm - name = "space worm segment" - desc = "A part of a space worm." - icon = 'icons/mob/animal.dmi' - icon_state = "spaceworm" - icon_living = "spaceworm" - icon_dead = "spacewormdead" - status_flags = 0 - - speak_emote = list("transmits") //not supposed to be used under AI control - emote_hear = list("transmits") //I'm just adding it so it doesn't runtime if controlled by player who speaks - - response_help = "touches" - response_disarm = "flails at" - response_harm = "punches the" - - harm_intent_damage = 2 - - maxHealth = 30 - health = 30 - - stop_automated_movement = 1 - animate_movement = SYNC_STEPS - - minbodytemp = 0 - maxbodytemp = 350 - min_oxy = 0 - max_co2 = 0 - max_tox = 0 - - a_intent = I_HURT //so they don't get pushed around - - environment_smash = 2 - - speed = -1 - - var/mob/living/simple_animal/space_worm/previous //next/previous segments, correspondingly - var/mob/living/simple_animal/space_worm/next //head is the nextest segment - - var/stomachProcessProbability = 50 - var/digestionProbability = 20 - var/flatPlasmaValue = 5 //flat plasma amount given for non-items - - var/atom/currentlyEating //what the worm is currently eating - var/eatingDuration = 0 //how long he's been eating it for - - head - name = "space worm head" - icon_state = "spacewormhead" - icon_living = "spacewormhead" - icon_dead = "spacewormdead" - - maxHealth = 20 - health = 20 - - melee_damage_lower = 10 - melee_damage_upper = 15 - attacktext = "bites" - - animate_movement = SLIDE_STEPS - - New(var/location, var/segments = 6) - ..() - - var/mob/living/simple_animal/space_worm/current = src - - for(var/i = 1 to segments) - var/mob/living/simple_animal/space_worm/newSegment = new /mob/living/simple_animal/space_worm(loc) - current.Attach(newSegment) - current = newSegment - - update_icon() - if(stat == CONSCIOUS || stat == UNCONSCIOUS) - icon_state = "spacewormhead[previous?1:0]" - if(previous) - dir = get_dir(previous,src) - else - icon_state = "spacewormheaddead" - - Life() - ..() - - if(next && !(next in view(src,1))) - Detach() - - if(stat == DEAD) //dead chunks fall off and die immediately - if(previous) - previous.Detach() - if(next) - Detach(1) - - if(prob(stomachProcessProbability)) - ProcessStomach() - - update_icon() - - return - - Destroy() //if a chunk a destroyed, make a new worm out of the split halves - if(previous) - previous.Detach() - ..() - - Move() - var/attachementNextPosition = loc - if(..()) - if(previous) - previous.Move(attachementNextPosition) - update_icon() - - Bump(atom/obstacle) - if(currentlyEating != obstacle) - currentlyEating = obstacle - eatingDuration = 0 - - if(!AttemptToEat(obstacle)) - eatingDuration++ - else - currentlyEating = null - eatingDuration = 0 - - return - - update_icon() //only for the sake of consistency with the other update icon procs - if(stat == CONSCIOUS || stat == UNCONSCIOUS) - if(previous) //midsection - icon_state = "spaceworm[get_dir(src,previous) | get_dir(src,next)]" //see 3 lines below - else //tail - icon_state = "spacewormtail" - dir = get_dir(src,next) //next will always be present since it's not a head and if it's dead, it goes in the other if branch - else - icon_state = "spacewormdead" - - return - - proc/AttemptToEat(var/atom/target) - if(istype(target,/turf/simulated/wall)) - if((!istype(target,/turf/simulated/wall/r_wall) && eatingDuration >= 100) || eatingDuration >= 200) //need 20 ticks to eat an rwall, 10 for a regular one - var/turf/simulated/wall/wall = target - wall.ChangeTurf(/turf/simulated/floor) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, src) - M.amount = flatPlasmaValue - return 1 - else if(istype(target,/atom/movable)) - if(istype(target,/mob) || eatingDuration >= 50) //5 ticks to eat stuff like airlocks - var/atom/movable/objectOrMob = target - contents += objectOrMob - return 1 - - return 0 - - proc/Attach(var/mob/living/simple_animal/space_worm/attachement) - if(!attachement) - return - - previous = attachement - attachement.next = src - - return - - proc/Detach(die = 0) - var/mob/living/simple_animal/space_worm/newHead = new /mob/living/simple_animal/space_worm/head(loc,0) - var/mob/living/simple_animal/space_worm/newHeadPrevious = previous - - previous = null //so that no extra heads are spawned - - newHead.Attach(newHeadPrevious) - - if(die) - newHead.Die() - - qdel(src) - - proc/ProcessStomach() - for(var/atom/movable/stomachContent in contents) - if(prob(digestionProbability)) - if(istype(stomachContent,/obj/item/stack)) //converts to plasma, keeping the stack value - if(!istype(stomachContent,/obj/item/stack/sheet/mineral/plasma)) - var/obj/item/stack/oldStack = stomachContent - new /obj/item/stack/sheet/mineral/plasma(src, oldStack.amount) - qdel(oldStack) - oldStack = null - continue - else if(istype(stomachContent,/obj/item)) //converts to plasma, keeping the w_class - var/obj/item/oldItem = stomachContent - new /obj/item/stack/sheet/mineral/plasma(src, oldItem.w_class) - qdel(oldItem) - oldItem = null - continue - else - new /obj/item/stack/sheet/mineral/plasma(src, flatPlasmaValue) //just flat amount - qdel(stomachContent) - stomachContent = null - continue - - if(previous) - for(var/atom/movable/stomachContent in contents) //transfer it along the digestive tract - previous.contents += stomachContent - else - for(var/atom/movable/stomachContent in contents) //or poop it out - loc.contents += stomachContent - - return +/mob/living/simple_animal/space_worm + name = "space worm segment" + desc = "A part of a space worm." + icon = 'icons/mob/animal.dmi' + icon_state = "spaceworm" + icon_living = "spaceworm" + icon_dead = "spacewormdead" + status_flags = 0 + + speak_emote = list("transmits") //not supposed to be used under AI control + emote_hear = list("transmits") //I'm just adding it so it doesn't runtime if controlled by player who speaks + + response_help = "touches" + response_disarm = "flails at" + response_harm = "punches the" + + harm_intent_damage = 2 + + maxHealth = 30 + health = 30 + + stop_automated_movement = 1 + animate_movement = SYNC_STEPS + + minbodytemp = 0 + maxbodytemp = 350 + min_oxy = 0 + max_co2 = 0 + max_tox = 0 + + a_intent = I_HURT //so they don't get pushed around + + environment_smash = 2 + + speed = -1 + + var/mob/living/simple_animal/space_worm/previous //next/previous segments, correspondingly + var/mob/living/simple_animal/space_worm/next //head is the nextest segment + + var/stomachProcessProbability = 50 + var/digestionProbability = 20 + var/flatPlasmaValue = 5 //flat plasma amount given for non-items + + var/atom/currentlyEating //what the worm is currently eating + var/eatingDuration = 0 //how long he's been eating it for + + head + name = "space worm head" + icon_state = "spacewormhead" + icon_living = "spacewormhead" + icon_dead = "spacewormdead" + + maxHealth = 20 + health = 20 + + melee_damage_lower = 10 + melee_damage_upper = 15 + attacktext = "bites" + + animate_movement = SLIDE_STEPS + + New(var/location, var/segments = 6) + ..() + + var/mob/living/simple_animal/space_worm/current = src + + for(var/i = 1 to segments) + var/mob/living/simple_animal/space_worm/newSegment = new /mob/living/simple_animal/space_worm(loc) + current.Attach(newSegment) + current = newSegment + + update_icon() + if(stat == CONSCIOUS || stat == UNCONSCIOUS) + icon_state = "spacewormhead[previous?1:0]" + if(previous) + dir = get_dir(previous,src) + else + icon_state = "spacewormheaddead" + + Life() + ..() + + if(next && !(next in view(src,1))) + Detach() + + if(stat == DEAD) //dead chunks fall off and die immediately + if(previous) + previous.Detach() + if(next) + Detach(1) + + if(prob(stomachProcessProbability)) + ProcessStomach() + + update_icon() + + return + + Destroy() //if a chunk a destroyed, make a new worm out of the split halves + if(previous) + previous.Detach() + ..() + + Move() + var/attachementNextPosition = loc + if(..()) + if(previous) + previous.Move(attachementNextPosition) + update_icon() + + Bump(atom/obstacle) + if(currentlyEating != obstacle) + currentlyEating = obstacle + eatingDuration = 0 + + if(!AttemptToEat(obstacle)) + eatingDuration++ + else + currentlyEating = null + eatingDuration = 0 + + return + + update_icon() //only for the sake of consistency with the other update icon procs + if(stat == CONSCIOUS || stat == UNCONSCIOUS) + if(previous) //midsection + icon_state = "spaceworm[get_dir(src,previous) | get_dir(src,next)]" //see 3 lines below + else //tail + icon_state = "spacewormtail" + dir = get_dir(src,next) //next will always be present since it's not a head and if it's dead, it goes in the other if branch + else + icon_state = "spacewormdead" + + return + + proc/AttemptToEat(var/atom/target) + if(istype(target,/turf/simulated/wall)) + if((!istype(target,/turf/simulated/wall/r_wall) && eatingDuration >= 100) || eatingDuration >= 200) //need 20 ticks to eat an rwall, 10 for a regular one + var/turf/simulated/wall/wall = target + wall.ChangeTurf(/turf/simulated/floor) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, src) + M.amount = flatPlasmaValue + return 1 + else if(istype(target,/atom/movable)) + if(istype(target,/mob) || eatingDuration >= 50) //5 ticks to eat stuff like airlocks + var/atom/movable/objectOrMob = target + contents += objectOrMob + return 1 + + return 0 + + proc/Attach(var/mob/living/simple_animal/space_worm/attachement) + if(!attachement) + return + + previous = attachement + attachement.next = src + + return + + proc/Detach(die = 0) + var/mob/living/simple_animal/space_worm/newHead = new /mob/living/simple_animal/space_worm/head(loc,0) + var/mob/living/simple_animal/space_worm/newHeadPrevious = previous + + previous = null //so that no extra heads are spawned + + newHead.Attach(newHeadPrevious) + + if(die) + newHead.Die() + + qdel(src) + + proc/ProcessStomach() + for(var/atom/movable/stomachContent in contents) + if(prob(digestionProbability)) + if(istype(stomachContent,/obj/item/stack)) //converts to plasma, keeping the stack value + if(!istype(stomachContent,/obj/item/stack/sheet/mineral/plasma)) + var/obj/item/stack/oldStack = stomachContent + new /obj/item/stack/sheet/mineral/plasma(src, oldStack.amount) + qdel(oldStack) + oldStack = null + continue + else if(istype(stomachContent,/obj/item)) //converts to plasma, keeping the w_class + var/obj/item/oldItem = stomachContent + new /obj/item/stack/sheet/mineral/plasma(src, oldItem.w_class) + qdel(oldItem) + oldItem = null + continue + else + new /obj/item/stack/sheet/mineral/plasma(src, flatPlasmaValue) //just flat amount + qdel(stomachContent) + stomachContent = null + continue + + if(previous) + for(var/atom/movable/stomachContent in contents) //transfer it along the digestive tract + previous.contents += stomachContent + else + for(var/atom/movable/stomachContent in contents) //or poop it out + loc.contents += stomachContent + + return diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 7e990ff6d0d..8038c466d71 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -1,87 +1,87 @@ -//handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying -/mob/proc/update_Login_details() - //Multikey checks and logging - lastKnownIP = client.address - computer_id = client.computer_id - log_access("Login: [key_name(src)] from [lastKnownIP ? lastKnownIP : "localhost"]-[computer_id] || BYOND v[client.byond_version]") - if(config.log_access) - for(var/mob/M in player_list) - if(M == src) continue - if( M.key && (M.key != key) ) - var/matches - if( (M.lastKnownIP == client.address) ) - matches += "IP ([client.address])" - if( (M.computer_id == client.computer_id) ) - if(matches) matches += " and " - matches += "ID ([client.computer_id])" - spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!") - if(matches) - if(M.client) - message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)].", 1) - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)].") - else - message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)] (no longer logged in). ", 1) - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") - -/mob/Login() - player_list |= src - update_Login_details() - world.update_status() - - if(hud_used) qdel(hud_used) //remove the hud objects - client.images = null //remove the images such as AIs being unable to see runes - - if(spell_masters) - for(var/obj/screen/movable/spell_master/spell_master in spell_masters) - spell_master.toggle_open(1) - client.screen -= spell_master - - client.reset_screen() //remove hud items just in case - hud_used = new /datum/hud(src) - gui_icons = new /datum/ui_icons(src) - - if(round_end_info == "") - winset(client, "rpane.round_end", "is-visible=false") - - delayNextMove(0) - - sight |= SEE_SELF - - ..() - - reset_view() - - if(flags & HEAR && !(flags & HEAR_ALWAYS)) //Mobs with HEAR_ALWAYS will already have a virtualhearer - getFromPool(/mob/virtualhearer, src) - - //Clear ability list and update from mob. - client.verbs -= ability_verbs - - if(abilities) - client.verbs |= abilities - - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - if(H.species && H.species.abilities) - H.verbs |= H.species.abilities - - if(client) - if(ckey in deadmins) - client.verbs += /client/proc/readmin - - if(M_FARSIGHT in mutations) - client.view = max(client.view, world.view+2) - CallHook("Login", list("client" = src.client, "mob" = src)) - - if(spell_masters) - for(var/obj/screen/movable/spell_master/spell_master in spell_masters) - client.screen += spell_master - spell_master.toggle_open(1) - - if (isobj(loc)) - var/obj/location = loc - location.on_log() - - if(client && client.haszoomed && !client.holder) - client.view = world.view - client.haszoomed = 0 +//handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying +/mob/proc/update_Login_details() + //Multikey checks and logging + lastKnownIP = client.address + computer_id = client.computer_id + log_access("Login: [key_name(src)] from [lastKnownIP ? lastKnownIP : "localhost"]-[computer_id] || BYOND v[client.byond_version]") + if(config.log_access) + for(var/mob/M in player_list) + if(M == src) continue + if( M.key && (M.key != key) ) + var/matches + if( (M.lastKnownIP == client.address) ) + matches += "IP ([client.address])" + if( (M.computer_id == client.computer_id) ) + if(matches) matches += " and " + matches += "ID ([client.computer_id])" + spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!") + if(matches) + if(M.client) + message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)].", 1) + log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)].") + else + message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)] (no longer logged in). ", 1) + log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") + +/mob/Login() + player_list |= src + update_Login_details() + world.update_status() + + if(hud_used) qdel(hud_used) //remove the hud objects + client.images = null //remove the images such as AIs being unable to see runes + + if(spell_masters) + for(var/obj/screen/movable/spell_master/spell_master in spell_masters) + spell_master.toggle_open(1) + client.screen -= spell_master + + client.reset_screen() //remove hud items just in case + hud_used = new /datum/hud(src) + gui_icons = new /datum/ui_icons(src) + + if(round_end_info == "") + winset(client, "rpane.round_end", "is-visible=false") + + delayNextMove(0) + + sight |= SEE_SELF + + ..() + + reset_view() + + if(flags & HEAR && !(flags & HEAR_ALWAYS)) //Mobs with HEAR_ALWAYS will already have a virtualhearer + getFromPool(/mob/virtualhearer, src) + + //Clear ability list and update from mob. + client.verbs -= ability_verbs + + if(abilities) + client.verbs |= abilities + + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + if(H.species && H.species.abilities) + H.verbs |= H.species.abilities + + if(client) + if(ckey in deadmins) + client.verbs += /client/proc/readmin + + if(M_FARSIGHT in mutations) + client.view = max(client.view, world.view+2) + CallHook("Login", list("client" = src.client, "mob" = src)) + + if(spell_masters) + for(var/obj/screen/movable/spell_master/spell_master in spell_masters) + client.screen += spell_master + spell_master.toggle_open(1) + + if (isobj(loc)) + var/obj/location = loc + location.on_log() + + if(client && client.haszoomed && !client.holder) + client.view = world.view + client.haszoomed = 0 diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index d3e01e60a97..4bebe79b2cc 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -1,27 +1,27 @@ -/mob/Logout() - if (isobj(loc)) - var/obj/location = loc - location.on_log() - - if(!(flags & HEAR_ALWAYS)) - for(var/mob/virtualhearer/VH in virtualhearers) - if(VH.attached == src) - returnToPool(VH) - - nanomanager.user_logout(src) // this is used to clean up (remove) this user's Nano UIs - - player_list -= src - - log_access("Logout: [key_name(src)] ([formatLocation(loc)])") - - remove_screen_objs() //Used to remove hud elements - - if(admin_datums[src.ckey]) - if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing. - var/admins_number = admins.len - - message_admins("Admin logout: [key_name(src)]") - if(admins_number == 0) //Apparently the admin logging out is no longer an admin at this point, so we have to check this towards 0 and not towards 1. Awell. - send2adminirc("[key_name(src)] logged out - no more admins online.") - - ..() +/mob/Logout() + if (isobj(loc)) + var/obj/location = loc + location.on_log() + + if(!(flags & HEAR_ALWAYS)) + for(var/mob/virtualhearer/VH in virtualhearers) + if(VH.attached == src) + returnToPool(VH) + + nanomanager.user_logout(src) // this is used to clean up (remove) this user's Nano UIs + + player_list -= src + + log_access("Logout: [key_name(src)] ([formatLocation(loc)])") + + remove_screen_objs() //Used to remove hud elements + + if(admin_datums[src.ckey]) + if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing. + var/admins_number = admins.len + + message_admins("Admin logout: [key_name(src)]") + if(admins_number == 0) //Apparently the admin logging out is no longer an admin at this point, so we have to check this towards 0 and not towards 1. Awell. + send2adminirc("[key_name(src)] logged out - no more admins online.") + + ..() diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 9ed8fac2902..0c4740cf237 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -1,242 +1,242 @@ -#define UPGRADE_COOLDOWN 5 -#define UPGRADE_KILL_TIMER 100 - -/obj/item/weapon/grab - name = "grab" - flags = NOBLUDGEON - var/obj/screen/grab/hud = null - var/mob/affecting = null - var/mob/assailant = null - var/state = GRAB_PASSIVE - - var/allow_upgrade = 1 - var/last_upgrade = 0 - - layer = 21 - abstract = 1 - item_state = "nothing" - w_class = 5.0 - - -/obj/item/weapon/grab/New(atom/loc, mob/victim) - ..() - assailant = loc - affecting = victim - - if(affecting && affecting.anchored) - returnToPool(src) - return - - hud = getFromPool(/obj/screen/grab) - hud.icon_state = "reinforce" - hud.name = "reinforce grab" - hud.master = src - - -//Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code. -/obj/item/weapon/grab/proc/toss() - if(affecting) - if(affecting.locked_to || !loc.Adjacent(affecting)) - return null - if(state >= GRAB_AGGRESSIVE) - return affecting - return null - - -//This makes sure that the grab screen object is displayed in the correct hand. -/obj/item/weapon/grab/proc/synch() - if(affecting) - if(assailant.r_hand == src) - hud.screen_loc = ui_rhand - else - hud.screen_loc = ui_lhand - - -/obj/item/weapon/grab/process() - confirm() - if(!assailant) - affecting = null - returnToPool(src) - return - - if(assailant.client) - assailant.client.screen -= hud - assailant.client.screen += hud - - if(assailant.pulling == affecting) - assailant.stop_pulling() - - if(state <= GRAB_AGGRESSIVE) - allow_upgrade = 1 - if((assailant.l_hand && assailant.l_hand != src && istype(assailant.l_hand, /obj/item/weapon/grab))) - var/obj/item/weapon/grab/G = assailant.l_hand - if(G.affecting != affecting) - allow_upgrade = 0 - if((assailant.r_hand && assailant.r_hand != src && istype(assailant.r_hand, /obj/item/weapon/grab))) - var/obj/item/weapon/grab/G = assailant.r_hand - if(G.affecting != affecting) - allow_upgrade = 0 - if(state == GRAB_AGGRESSIVE) - var/h = affecting.hand - affecting.drop_hands() - affecting.hand = h - for(var/obj/item/weapon/grab/G in affecting.grabbed_by) - if(G == src) continue - if(G.state == GRAB_AGGRESSIVE) - allow_upgrade = 0 - if(allow_upgrade) - hud.icon_state = "reinforce" - else - hud.icon_state = "!reinforce" - else - if(!affecting.locked_to) - affecting.loc = assailant.loc - - if(state >= GRAB_NECK) - // affecting.Stun(5) //It will hamper your voice, being choked and all. - if(isliving(affecting)) - var/mob/living/L = affecting - L.adjustOxyLoss(1) - - if(state >= GRAB_KILL) - affecting.Weaken(5) //Should keep you down unless you get help. - affecting.losebreath = min(affecting.losebreath + 2, 3) - -/obj/item/weapon/grab/attack_self() - . = ..() - if(.) - return - else if(hud) - return s_click(hud) - - -/obj/item/weapon/grab/proc/s_click(obj/screen/S) - if(!affecting || !assailant || timeDestroyed) - return - if(assailant.attack_delayer.blocked()) - return - if(state == GRAB_UPGRADING) - return - /* This is handled in mob/proc/ClickOn - if(assailant.next_move > world.time) - return - if(world.time < (last_upgrade + UPGRADE_COOLDOWN)) - return - */ - if(!assailant.canmove || assailant.lying) - returnToPool(src) - return - - last_upgrade = world.time - if(state < GRAB_AGGRESSIVE) - if(!allow_upgrade) - return - assailant.visible_message("[assailant] has grabbed [affecting] aggressively (now hands)!", \ - drugged_message = "[assailant] has hugged [affecting] passionately!") - state = GRAB_AGGRESSIVE - icon_state = "grabbed1" - else - if(state < GRAB_NECK) - if(isslime(affecting)) +#define UPGRADE_COOLDOWN 5 +#define UPGRADE_KILL_TIMER 100 + +/obj/item/weapon/grab + name = "grab" + flags = NOBLUDGEON + var/obj/screen/grab/hud = null + var/mob/affecting = null + var/mob/assailant = null + var/state = GRAB_PASSIVE + + var/allow_upgrade = 1 + var/last_upgrade = 0 + + layer = 21 + abstract = 1 + item_state = "nothing" + w_class = 5.0 + + +/obj/item/weapon/grab/New(atom/loc, mob/victim) + ..() + assailant = loc + affecting = victim + + if(affecting && affecting.anchored) + returnToPool(src) + return + + hud = getFromPool(/obj/screen/grab) + hud.icon_state = "reinforce" + hud.name = "reinforce grab" + hud.master = src + + +//Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code. +/obj/item/weapon/grab/proc/toss() + if(affecting) + if(affecting.locked_to || !loc.Adjacent(affecting)) + return null + if(state >= GRAB_AGGRESSIVE) + return affecting + return null + + +//This makes sure that the grab screen object is displayed in the correct hand. +/obj/item/weapon/grab/proc/synch() + if(affecting) + if(assailant.r_hand == src) + hud.screen_loc = ui_rhand + else + hud.screen_loc = ui_lhand + + +/obj/item/weapon/grab/process() + confirm() + if(!assailant) + affecting = null + returnToPool(src) + return + + if(assailant.client) + assailant.client.screen -= hud + assailant.client.screen += hud + + if(assailant.pulling == affecting) + assailant.stop_pulling() + + if(state <= GRAB_AGGRESSIVE) + allow_upgrade = 1 + if((assailant.l_hand && assailant.l_hand != src && istype(assailant.l_hand, /obj/item/weapon/grab))) + var/obj/item/weapon/grab/G = assailant.l_hand + if(G.affecting != affecting) + allow_upgrade = 0 + if((assailant.r_hand && assailant.r_hand != src && istype(assailant.r_hand, /obj/item/weapon/grab))) + var/obj/item/weapon/grab/G = assailant.r_hand + if(G.affecting != affecting) + allow_upgrade = 0 + if(state == GRAB_AGGRESSIVE) + var/h = affecting.hand + affecting.drop_hands() + affecting.hand = h + for(var/obj/item/weapon/grab/G in affecting.grabbed_by) + if(G == src) continue + if(G.state == GRAB_AGGRESSIVE) + allow_upgrade = 0 + if(allow_upgrade) + hud.icon_state = "reinforce" + else + hud.icon_state = "!reinforce" + else + if(!affecting.locked_to) + affecting.loc = assailant.loc + + if(state >= GRAB_NECK) + // affecting.Stun(5) //It will hamper your voice, being choked and all. + if(isliving(affecting)) + var/mob/living/L = affecting + L.adjustOxyLoss(1) + + if(state >= GRAB_KILL) + affecting.Weaken(5) //Should keep you down unless you get help. + affecting.losebreath = min(affecting.losebreath + 2, 3) + +/obj/item/weapon/grab/attack_self() + . = ..() + if(.) + return + else if(hud) + return s_click(hud) + + +/obj/item/weapon/grab/proc/s_click(obj/screen/S) + if(!affecting || !assailant || timeDestroyed) + return + if(assailant.attack_delayer.blocked()) + return + if(state == GRAB_UPGRADING) + return + /* This is handled in mob/proc/ClickOn + if(assailant.next_move > world.time) + return + if(world.time < (last_upgrade + UPGRADE_COOLDOWN)) + return + */ + if(!assailant.canmove || assailant.lying) + returnToPool(src) + return + + last_upgrade = world.time + if(state < GRAB_AGGRESSIVE) + if(!allow_upgrade) + return + assailant.visible_message("[assailant] has grabbed [affecting] aggressively (now hands)!", \ + drugged_message = "[assailant] has hugged [affecting] passionately!") + state = GRAB_AGGRESSIVE + icon_state = "grabbed1" + else + if(state < GRAB_NECK) + if(isslime(affecting)) to_chat(assailant, "You squeeze [affecting], but nothing interesting happens.") - return - assailant.visible_message("[assailant] has reinforced \his grip on [affecting] (now neck)!", \ - drugged_message = "[assailant] has reinforced \his hug on [affecting]!") - state = GRAB_NECK - icon_state = "grabbed+1" - if(!affecting.locked_to) - affecting.loc = assailant.loc - affecting.attack_log += "\[[time_stamp()]\] Has had their neck grabbed by [assailant.name] ([assailant.ckey])" - assailant.attack_log += "\[[time_stamp()]\] Grabbed the neck of [affecting.name] ([affecting.ckey])" - log_attack("[assailant.name] ([assailant.ckey]) grabbed the neck of [affecting.name] ([affecting.ckey])") - hud.icon_state = "disarm/kill" - hud.name = "disarm/kill" - else - if(state < GRAB_UPGRADING) - assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!", \ - drugged_message = "[assailant] starts to tighten \his hug on [affecting]!") - hud.icon_state = "disarm/kill1" - state = GRAB_UPGRADING - if(do_after(assailant,affecting, UPGRADE_KILL_TIMER)) - if(state == GRAB_KILL) - return - if(!assailant || !affecting) - returnToPool(src) - return - if(!assailant.canmove || assailant.lying) - returnToPool(src) - return - state = GRAB_KILL - assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!", \ - drugged_message = "[assailant] has tightened \his hug on [affecting]!") - affecting.attack_log += "\[[time_stamp()]\] Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])" - assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" - log_attack("[assailant.name] ([assailant.ckey]) Strangled (kill intent) [affecting.name] ([affecting.ckey])") - - assailant.delayNextMove(10) - assailant.delayNextAttack(10) - - affecting.losebreath += 1 - else - if(!assailant || !affecting) - returnToPool(src) - return - assailant.visible_message("[assailant] was unable to tighten \his grip on [affecting]'s neck!", \ - drugged_message = "[affecting] refused [assailant]'s hug!") - hud.icon_state = "disarm/kill" - state = GRAB_NECK - - -//This is used to make sure the victim hasn't managed to yackety sax away before using the grab. -/obj/item/weapon/grab/proc/confirm() - if(!assailant || !affecting) - returnToPool(src) - return 0 - - if(affecting) - if(!isturf(assailant.loc) || ( !isturf(affecting.loc) || assailant.loc != affecting.loc && get_dist(assailant, affecting) > 1) ) - returnToPool(src) - return 0 - - return 1 - - -/obj/item/weapon/grab/attack(mob/M, mob/user) - if(!affecting) - return - - if(M == affecting) - s_click(hud) - return - - if(M == assailant && state >= GRAB_AGGRESSIVE) - if( (ishuman(user) && (M_FAT in user.mutations) && ismonkey(affecting) ) || ( isalien(user) && iscarbon(affecting) ) ) - var/mob/living/carbon/attacker = user - user.visible_message("[user] is attempting to devour [affecting]!", \ - drugged_message="[user] is attempting to kiss [affecting]! Ew!") - if(istype(user, /mob/living/carbon/alien/humanoid/hunter)) - if(!do_mob(user, affecting)) return - else - if(!do_mob(user, affecting, 100)) return - user.visible_message("[user] devours [affecting]!", \ - drugged_message="[affecting] vanishes in disgust.") - affecting.loc = user - attacker.stomach_contents.Add(affecting) - returnToPool(src) - - -/obj/item/weapon/grab/dropped() - returnToPool(src) - -/obj/item/weapon/grab/Destroy() - if(affecting) - affecting.grabbed_by -= src - affecting = null - if(assailant) - if(assailant.client) - assailant.client.screen -= hud - assailant = null - if(hud) - returnToPool(hud) - hud = null - ..() + return + assailant.visible_message("[assailant] has reinforced \his grip on [affecting] (now neck)!", \ + drugged_message = "[assailant] has reinforced \his hug on [affecting]!") + state = GRAB_NECK + icon_state = "grabbed+1" + if(!affecting.locked_to) + affecting.loc = assailant.loc + affecting.attack_log += "\[[time_stamp()]\] Has had their neck grabbed by [assailant.name] ([assailant.ckey])" + assailant.attack_log += "\[[time_stamp()]\] Grabbed the neck of [affecting.name] ([affecting.ckey])" + log_attack("[assailant.name] ([assailant.ckey]) grabbed the neck of [affecting.name] ([affecting.ckey])") + hud.icon_state = "disarm/kill" + hud.name = "disarm/kill" + else + if(state < GRAB_UPGRADING) + assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!", \ + drugged_message = "[assailant] starts to tighten \his hug on [affecting]!") + hud.icon_state = "disarm/kill1" + state = GRAB_UPGRADING + if(do_after(assailant,affecting, UPGRADE_KILL_TIMER)) + if(state == GRAB_KILL) + return + if(!assailant || !affecting) + returnToPool(src) + return + if(!assailant.canmove || assailant.lying) + returnToPool(src) + return + state = GRAB_KILL + assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!", \ + drugged_message = "[assailant] has tightened \his hug on [affecting]!") + affecting.attack_log += "\[[time_stamp()]\] Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])" + assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" + log_attack("[assailant.name] ([assailant.ckey]) Strangled (kill intent) [affecting.name] ([affecting.ckey])") + + assailant.delayNextMove(10) + assailant.delayNextAttack(10) + + affecting.losebreath += 1 + else + if(!assailant || !affecting) + returnToPool(src) + return + assailant.visible_message("[assailant] was unable to tighten \his grip on [affecting]'s neck!", \ + drugged_message = "[affecting] refused [assailant]'s hug!") + hud.icon_state = "disarm/kill" + state = GRAB_NECK + + +//This is used to make sure the victim hasn't managed to yackety sax away before using the grab. +/obj/item/weapon/grab/proc/confirm() + if(!assailant || !affecting) + returnToPool(src) + return 0 + + if(affecting) + if(!isturf(assailant.loc) || ( !isturf(affecting.loc) || assailant.loc != affecting.loc && get_dist(assailant, affecting) > 1) ) + returnToPool(src) + return 0 + + return 1 + + +/obj/item/weapon/grab/attack(mob/M, mob/user) + if(!affecting) + return + + if(M == affecting) + s_click(hud) + return + + if(M == assailant && state >= GRAB_AGGRESSIVE) + if( (ishuman(user) && (M_FAT in user.mutations) && ismonkey(affecting) ) || ( isalien(user) && iscarbon(affecting) ) ) + var/mob/living/carbon/attacker = user + user.visible_message("[user] is attempting to devour [affecting]!", \ + drugged_message="[user] is attempting to kiss [affecting]! Ew!") + if(istype(user, /mob/living/carbon/alien/humanoid/hunter)) + if(!do_mob(user, affecting)) return + else + if(!do_mob(user, affecting, 100)) return + user.visible_message("[user] devours [affecting]!", \ + drugged_message="[affecting] vanishes in disgust.") + affecting.loc = user + attacker.stomach_contents.Add(affecting) + returnToPool(src) + + +/obj/item/weapon/grab/dropped() + returnToPool(src) + +/obj/item/weapon/grab/Destroy() + if(affecting) + affecting.grabbed_by -= src + affecting = null + if(assailant) + if(assailant.client) + assailant.client.screen -= hud + assailant = null + if(hud) + returnToPool(hud) + hud = null + ..() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 10e2b7809f0..a3753f3c016 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1,369 +1,369 @@ -/mob/proc/isUnconscious() //Returns 1 if unconscious, dead or faking death - if(stat || (status_flags & FAKEDEATH)) - return 1 - -/mob/proc/isDead() //Returns 1 if dead or faking death - if(stat == DEAD || (status_flags & FAKEDEATH)) - return 1 - -/proc/RemoveAllFactionIcons(var/datum/mind/M) - ticker.mode.update_cult_icons_removed(M) - ticker.mode.update_rev_icons_removed(M) - ticker.mode.update_wizard_icons_removed(M) - -/proc/ClearRoles(var/datum/mind/M) - ticker.mode.remove_revolutionary(M) - -/proc/isAdminGhost(A) - if(isobserver(A)) - var/mob/dead/observer/O = A - if(O.check_rights(R_ADMIN|R_FUN)) - return 1 - return 0 - - -/proc/canGhostRead(var/mob/A, var/obj/target, var/flags=PERMIT_ALL) - if(isAdminGhost(A)) - return 1 - if(flags & PERMIT_ALL) - return 1 - return 0 - -/proc/canGhostWrite(var/mob/A, var/obj/target, var/desc="fucked with", var/flags=0) - if(flags & PERMIT_ALL) - if(!target.blessed) - return 1 - if(isAdminGhost(A)) - if(desc!="") - add_ghostlogs(A, target, desc, 1) - return 1 - return 0 - -/proc/isloyal(A) //Checks to see if the person contains a loyalty implant, then checks that the implant is actually inside of them - for(var/obj/item/weapon/implant/loyalty/L in A) - if(L && L.implanted) - return 1 - return 0 - -/proc/check_holy(var/mob/A) //checks to see if the tile the mob stands on is holy - var/turf/T = get_turf(A) - if(!T) return 0 - if(!T.holy) return 0 - return 1 //The tile is holy. Beware! - -proc/hasorgans(A) - return ishuman(A) - -/proc/hsl2rgb(h, s, l) - return - - -/proc/check_zone(zone) - if(!zone) return "chest" - switch(zone) - if("eyes") - zone = "head" - if("mouth") - zone = "head" -/* if("l_hand") - zone = "l_arm" - if("r_hand") - zone = "r_arm" - if("l_foot") - zone = "l_leg" - if("r_foot") - zone = "r_leg" - if("groin") - zone = "chest" -*/ - return zone - - -/proc/ran_zone(zone, probability) - zone = check_zone(zone) - if(!probability) probability = 90 - if(probability == 100) return zone - - if(zone == "chest") - if(prob(probability)) return "chest" - var/t = rand(1, 9) - switch(t) - if(1 to 3) return "head" - if(4 to 6) return "l_arm" - if(7 to 9) return "r_arm" - - if(prob(probability * 0.75)) return zone - return "chest" - -// Emulates targetting a specific body part, and miss chances -// May return null if missed -// miss_chance_mod may be negative. -/proc/get_zone_with_miss_chance(zone, var/mob/target, var/miss_chance_mod = 0) - zone = check_zone(zone) - - // you can only miss if your target is standing and not restrained - if(!target.locked_to && !target.lying) - var/miss_chance = 10 - switch(zone) - if("head") - miss_chance = 40 - if("l_leg") - miss_chance = 20 - if("r_leg") - miss_chance = 20 - if("l_arm") - miss_chance = 20 - if("r_arm") - miss_chance = 20 - if("l_hand") - miss_chance = 50 - if("r_hand") - miss_chance = 50 - if("l_foot") - miss_chance = 50 - if("r_foot") - miss_chance = 50 - miss_chance = max(miss_chance + miss_chance_mod, 0) - if(prob(miss_chance)) - if(prob(70)) - return null - else - var/t = rand(1, 10) - switch(t) - if(1) return "head" - if(2) return "l_arm" - if(3) return "r_arm" - if(4) return "chest" - if(5) return "l_foot" - if(6) return "r_foot" - if(7) return "l_hand" - if(8) return "r_hand" - if(9) return "l_leg" - if(10) return "r_leg" - - return zone - -// adds stars to a text to obfuscate it -// var/n -> text to obfuscate -// var/pr -> percent of the text to obfuscate -// return -> obfuscated text -/proc/stars(n, pr) - if (pr == null) - pr = 25 - if (pr <= 0) - return null - else - if (pr >= 100) - return n - var/te = n - var/t = "" - n = length(n) - var/p = null - p = 1 - while(p <= n) - if ((copytext(te, p, p + 1) == " " || prob(pr))) - t = text("[][]", t, copytext(te, p, p + 1)) - else - t = text("[]*", t) - p++ - return t - -proc/slur(phrase) - phrase = html_decode(phrase) - var/leng=length(phrase) - var/counter=length(phrase) - var/newphrase="" - var/newletter="" - while(counter>=1) - newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2) - if(rand(1,3)==3) - if(lowertext(newletter)=="o") newletter="u" - if(lowertext(newletter)=="s") newletter="ch" - if(lowertext(newletter)=="a") newletter="ah" - if(lowertext(newletter)=="c") newletter="k" - switch(rand(1,15)) - if(1,3,5,8) newletter="[lowertext(newletter)]" - if(2,4,6,15) newletter="[uppertext(newletter)]" - if(7) newletter+="'" - //if(9,10) newletter="[newletter]" - //if(11,12) newletter="[newletter]" - //if(13) newletter="[newletter]" - newphrase+="[newletter]";counter-=1 - return newphrase - -/proc/stutter(n) - var/te = html_decode(n) - var/t = ""//placed before the message. Not really sure what it's for. - n = length(n)//length of the entire word - var/p = null - p = 1//1 is the start of any word - while(p <= n)//while P, which starts at 1 is less or equal to N which is the length. - var/n_letter = copytext(te, p, p + 1)//copies text from a certain distance. In this case, only one letter at a time. - if (prob(80) && (ckey(n_letter) in list("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"))) - if (prob(10)) - n_letter = text("[n_letter]-[n_letter]-[n_letter]-[n_letter]")//replaces the current letter with this instead. - else - if (prob(20)) - n_letter = text("[n_letter]-[n_letter]-[n_letter]") - else - if (prob(5)) - n_letter = null - else - n_letter = text("[n_letter]-[n_letter]") - t = text("[t][n_letter]")//since the above is ran through for each letter, the text just adds up back to the original word. - p++//for each letter p is increased to find where the next letter will be. - return copytext(sanitize(t),1,MAX_MESSAGE_LEN) - - -proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 for p will cause letters to be replaced instead of added - /* Turn text into complete gibberish! */ - var/returntext = "" - for(var/i = 1, i <= length(t), i++) - - var/letter = copytext(t, i, i+1) - if(prob(50)) - if(p >= 70) - letter = "" - - for(var/j = 1, j <= rand(0, 2), j++) - letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*") - - returntext += letter - - return returntext - -/proc/derpspeech(message, stuttering) - message = replacetext(message, " am ", " ") - message = replacetext(message, " is ", " ") - message = replacetext(message, " are ", " ") - message = replacetext(message, "you", "u") - message = replacetext(message, "help", "halp") - message = replacetext(message, "grief", "griff") - message = replacetext(message, "space", "spess") - message = replacetext(message, "carp", "crap") - message = replacetext(message, "reason", "raisin") - if(prob(50)) - message = uppertext(message) - message += "[stutter(pick("!", "!!", "!!!"))]" - if(!stuttering && prob(15)) - message = stutter(message) - return message - -/proc/shake_camera(mob/M, duration=0, strength=1) - spawn(1) - if(!M || !M.client || M.shakecamera) - return - - M.shakecamera = 1 - - for (var/x = 1 to duration) - if(!M || !M.client) - M.shakecamera = 0 - return //somebody disconnected while being shaken - M.client.pixel_x = 32*rand(-strength, strength) - M.client.pixel_y = 32*rand(-strength, strength) - sleep(1) - - M.shakecamera = 0 - M.client.pixel_x = 0 - M.client.pixel_y = 0 - - -/proc/findname(msg) - if(!istext(msg)) - msg = "[msg]" - for(var/mob/M in mob_list) - if(M.real_name == msg) - return M - return 0 - - -/mob/proc/abiotic(var/full_body = 0) - if(full_body && ((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract )) || (src.back || src.wear_mask))) - return 1 - - if((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract ))) - return 1 - - return 0 - -//converts intent-strings into numbers and back -var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT) -/proc/intent_numeric(argument) - if(istext(argument)) - switch(argument) - if(I_HELP) return 0 - if(I_DISARM) return 1 - if(I_GRAB) return 2 - else return 3 - else - switch(argument) - if(0) return I_HELP - if(1) return I_DISARM - if(2) return I_GRAB - else return I_HURT - -//change a mob's act-intent. Input the intent as a string such as I_HELP or use "right"/"left -/mob/verb/a_intent_change(input as text) - set name = "a-intent" - set hidden = 1 - - if(ishuman(src) || isalienadult(src) || isbrain(src)) - switch(input) - if(I_HELP,I_DISARM,I_GRAB,I_HURT) - a_intent = input - if("right") - a_intent = intent_numeric((intent_numeric(a_intent)+1) % 4) - if("left") - a_intent = intent_numeric((intent_numeric(a_intent)+3) % 4) - if(hud_used && hud_used.action_intent) - hud_used.action_intent.icon_state = "intent_[a_intent]" - - else if(isrobot(src) || ismonkey(src) || islarva(src)) - switch(input) - if(I_HELP) - a_intent = I_HELP - if(I_HURT) - a_intent = I_HURT - if("right","left") - a_intent = intent_numeric(intent_numeric(a_intent) - 3) - if(hud_used && hud_used.action_intent) - if(a_intent == I_HURT) - hud_used.action_intent.icon_state = "harm" - else - hud_used.action_intent.icon_state = "help" -proc/is_blind(A) - if(istype(A, /mob/living/carbon)) - var/mob/living/carbon/C = A - if(C.blinded != null) - return 1 - return 0 - -/proc/get_multitool(mob/user as mob) - // Get tool - var/obj/item/device/multitool/P - if(isrobot(user) || ishuman(user)) - P = user.get_active_hand() - else if(isAI(user)) - var/mob/living/silicon/ai/AI=user - P = AI.aiMulti - else if(isAdminGhost(user)) - var/mob/dead/observer/G=user - P = G.ghostMulti - - if(!istype(P)) - return null - return P - -/proc/broadcast_security_hud_message(var/message, var/broadcast_source) - broadcast_hud_message(message, broadcast_source, sec_hud_users, /obj/item/clothing/glasses/hud/security) - -/proc/broadcast_medical_hud_message(var/message, var/broadcast_source) - broadcast_hud_message(message, broadcast_source, med_hud_users, /obj/item/clothing/glasses/hud/health) - -/proc/broadcast_hud_message(var/message, var/broadcast_source, var/list/targets, var/icon) - var/turf/sourceturf = get_turf(broadcast_source) - for(var/mob/M in targets) - var/turf/targetturf = get_turf(M) - if((targetturf.z == sourceturf.z)) - M.show_message("\icon[icon] [message]", 1) +/mob/proc/isUnconscious() //Returns 1 if unconscious, dead or faking death + if(stat || (status_flags & FAKEDEATH)) + return 1 + +/mob/proc/isDead() //Returns 1 if dead or faking death + if(stat == DEAD || (status_flags & FAKEDEATH)) + return 1 + +/proc/RemoveAllFactionIcons(var/datum/mind/M) + ticker.mode.update_cult_icons_removed(M) + ticker.mode.update_rev_icons_removed(M) + ticker.mode.update_wizard_icons_removed(M) + +/proc/ClearRoles(var/datum/mind/M) + ticker.mode.remove_revolutionary(M) + +/proc/isAdminGhost(A) + if(isobserver(A)) + var/mob/dead/observer/O = A + if(O.check_rights(R_ADMIN|R_FUN)) + return 1 + return 0 + + +/proc/canGhostRead(var/mob/A, var/obj/target, var/flags=PERMIT_ALL) + if(isAdminGhost(A)) + return 1 + if(flags & PERMIT_ALL) + return 1 + return 0 + +/proc/canGhostWrite(var/mob/A, var/obj/target, var/desc="fucked with", var/flags=0) + if(flags & PERMIT_ALL) + if(!target.blessed) + return 1 + if(isAdminGhost(A)) + if(desc!="") + add_ghostlogs(A, target, desc, 1) + return 1 + return 0 + +/proc/isloyal(A) //Checks to see if the person contains a loyalty implant, then checks that the implant is actually inside of them + for(var/obj/item/weapon/implant/loyalty/L in A) + if(L && L.implanted) + return 1 + return 0 + +/proc/check_holy(var/mob/A) //checks to see if the tile the mob stands on is holy + var/turf/T = get_turf(A) + if(!T) return 0 + if(!T.holy) return 0 + return 1 //The tile is holy. Beware! + +proc/hasorgans(A) + return ishuman(A) + +/proc/hsl2rgb(h, s, l) + return + + +/proc/check_zone(zone) + if(!zone) return "chest" + switch(zone) + if("eyes") + zone = "head" + if("mouth") + zone = "head" +/* if("l_hand") + zone = "l_arm" + if("r_hand") + zone = "r_arm" + if("l_foot") + zone = "l_leg" + if("r_foot") + zone = "r_leg" + if("groin") + zone = "chest" +*/ + return zone + + +/proc/ran_zone(zone, probability) + zone = check_zone(zone) + if(!probability) probability = 90 + if(probability == 100) return zone + + if(zone == "chest") + if(prob(probability)) return "chest" + var/t = rand(1, 9) + switch(t) + if(1 to 3) return "head" + if(4 to 6) return "l_arm" + if(7 to 9) return "r_arm" + + if(prob(probability * 0.75)) return zone + return "chest" + +// Emulates targetting a specific body part, and miss chances +// May return null if missed +// miss_chance_mod may be negative. +/proc/get_zone_with_miss_chance(zone, var/mob/target, var/miss_chance_mod = 0) + zone = check_zone(zone) + + // you can only miss if your target is standing and not restrained + if(!target.locked_to && !target.lying) + var/miss_chance = 10 + switch(zone) + if("head") + miss_chance = 40 + if("l_leg") + miss_chance = 20 + if("r_leg") + miss_chance = 20 + if("l_arm") + miss_chance = 20 + if("r_arm") + miss_chance = 20 + if("l_hand") + miss_chance = 50 + if("r_hand") + miss_chance = 50 + if("l_foot") + miss_chance = 50 + if("r_foot") + miss_chance = 50 + miss_chance = max(miss_chance + miss_chance_mod, 0) + if(prob(miss_chance)) + if(prob(70)) + return null + else + var/t = rand(1, 10) + switch(t) + if(1) return "head" + if(2) return "l_arm" + if(3) return "r_arm" + if(4) return "chest" + if(5) return "l_foot" + if(6) return "r_foot" + if(7) return "l_hand" + if(8) return "r_hand" + if(9) return "l_leg" + if(10) return "r_leg" + + return zone + +// adds stars to a text to obfuscate it +// var/n -> text to obfuscate +// var/pr -> percent of the text to obfuscate +// return -> obfuscated text +/proc/stars(n, pr) + if (pr == null) + pr = 25 + if (pr <= 0) + return null + else + if (pr >= 100) + return n + var/te = n + var/t = "" + n = length(n) + var/p = null + p = 1 + while(p <= n) + if ((copytext(te, p, p + 1) == " " || prob(pr))) + t = text("[][]", t, copytext(te, p, p + 1)) + else + t = text("[]*", t) + p++ + return t + +proc/slur(phrase) + phrase = html_decode(phrase) + var/leng=length(phrase) + var/counter=length(phrase) + var/newphrase="" + var/newletter="" + while(counter>=1) + newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2) + if(rand(1,3)==3) + if(lowertext(newletter)=="o") newletter="u" + if(lowertext(newletter)=="s") newletter="ch" + if(lowertext(newletter)=="a") newletter="ah" + if(lowertext(newletter)=="c") newletter="k" + switch(rand(1,15)) + if(1,3,5,8) newletter="[lowertext(newletter)]" + if(2,4,6,15) newletter="[uppertext(newletter)]" + if(7) newletter+="'" + //if(9,10) newletter="[newletter]" + //if(11,12) newletter="[newletter]" + //if(13) newletter="[newletter]" + newphrase+="[newletter]";counter-=1 + return newphrase + +/proc/stutter(n) + var/te = html_decode(n) + var/t = ""//placed before the message. Not really sure what it's for. + n = length(n)//length of the entire word + var/p = null + p = 1//1 is the start of any word + while(p <= n)//while P, which starts at 1 is less or equal to N which is the length. + var/n_letter = copytext(te, p, p + 1)//copies text from a certain distance. In this case, only one letter at a time. + if (prob(80) && (ckey(n_letter) in list("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"))) + if (prob(10)) + n_letter = text("[n_letter]-[n_letter]-[n_letter]-[n_letter]")//replaces the current letter with this instead. + else + if (prob(20)) + n_letter = text("[n_letter]-[n_letter]-[n_letter]") + else + if (prob(5)) + n_letter = null + else + n_letter = text("[n_letter]-[n_letter]") + t = text("[t][n_letter]")//since the above is ran through for each letter, the text just adds up back to the original word. + p++//for each letter p is increased to find where the next letter will be. + return copytext(sanitize(t),1,MAX_MESSAGE_LEN) + + +proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 for p will cause letters to be replaced instead of added + /* Turn text into complete gibberish! */ + var/returntext = "" + for(var/i = 1, i <= length(t), i++) + + var/letter = copytext(t, i, i+1) + if(prob(50)) + if(p >= 70) + letter = "" + + for(var/j = 1, j <= rand(0, 2), j++) + letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*") + + returntext += letter + + return returntext + +/proc/derpspeech(message, stuttering) + message = replacetext(message, " am ", " ") + message = replacetext(message, " is ", " ") + message = replacetext(message, " are ", " ") + message = replacetext(message, "you", "u") + message = replacetext(message, "help", "halp") + message = replacetext(message, "grief", "griff") + message = replacetext(message, "space", "spess") + message = replacetext(message, "carp", "crap") + message = replacetext(message, "reason", "raisin") + if(prob(50)) + message = uppertext(message) + message += "[stutter(pick("!", "!!", "!!!"))]" + if(!stuttering && prob(15)) + message = stutter(message) + return message + +/proc/shake_camera(mob/M, duration=0, strength=1) + spawn(1) + if(!M || !M.client || M.shakecamera) + return + + M.shakecamera = 1 + + for (var/x = 1 to duration) + if(!M || !M.client) + M.shakecamera = 0 + return //somebody disconnected while being shaken + M.client.pixel_x = 32*rand(-strength, strength) + M.client.pixel_y = 32*rand(-strength, strength) + sleep(1) + + M.shakecamera = 0 + M.client.pixel_x = 0 + M.client.pixel_y = 0 + + +/proc/findname(msg) + if(!istext(msg)) + msg = "[msg]" + for(var/mob/M in mob_list) + if(M.real_name == msg) + return M + return 0 + + +/mob/proc/abiotic(var/full_body = 0) + if(full_body && ((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract )) || (src.back || src.wear_mask))) + return 1 + + if((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract ))) + return 1 + + return 0 + +//converts intent-strings into numbers and back +var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT) +/proc/intent_numeric(argument) + if(istext(argument)) + switch(argument) + if(I_HELP) return 0 + if(I_DISARM) return 1 + if(I_GRAB) return 2 + else return 3 + else + switch(argument) + if(0) return I_HELP + if(1) return I_DISARM + if(2) return I_GRAB + else return I_HURT + +//change a mob's act-intent. Input the intent as a string such as I_HELP or use "right"/"left +/mob/verb/a_intent_change(input as text) + set name = "a-intent" + set hidden = 1 + + if(ishuman(src) || isalienadult(src) || isbrain(src)) + switch(input) + if(I_HELP,I_DISARM,I_GRAB,I_HURT) + a_intent = input + if("right") + a_intent = intent_numeric((intent_numeric(a_intent)+1) % 4) + if("left") + a_intent = intent_numeric((intent_numeric(a_intent)+3) % 4) + if(hud_used && hud_used.action_intent) + hud_used.action_intent.icon_state = "intent_[a_intent]" + + else if(isrobot(src) || ismonkey(src) || islarva(src)) + switch(input) + if(I_HELP) + a_intent = I_HELP + if(I_HURT) + a_intent = I_HURT + if("right","left") + a_intent = intent_numeric(intent_numeric(a_intent) - 3) + if(hud_used && hud_used.action_intent) + if(a_intent == I_HURT) + hud_used.action_intent.icon_state = "harm" + else + hud_used.action_intent.icon_state = "help" +proc/is_blind(A) + if(istype(A, /mob/living/carbon)) + var/mob/living/carbon/C = A + if(C.blinded != null) + return 1 + return 0 + +/proc/get_multitool(mob/user as mob) + // Get tool + var/obj/item/device/multitool/P + if(isrobot(user) || ishuman(user)) + P = user.get_active_hand() + else if(isAI(user)) + var/mob/living/silicon/ai/AI=user + P = AI.aiMulti + else if(isAdminGhost(user)) + var/mob/dead/observer/G=user + P = G.ghostMulti + + if(!istype(P)) + return null + return P + +/proc/broadcast_security_hud_message(var/message, var/broadcast_source) + broadcast_hud_message(message, broadcast_source, sec_hud_users, /obj/item/clothing/glasses/hud/security) + +/proc/broadcast_medical_hud_message(var/message, var/broadcast_source) + broadcast_hud_message(message, broadcast_source, med_hud_users, /obj/item/clothing/glasses/hud/health) + +/proc/broadcast_hud_message(var/message, var/broadcast_source, var/list/targets, var/icon) + var/turf/sourceturf = get_turf(broadcast_source) + for(var/mob/M in targets) + var/turf/targetturf = get_turf(M) + if((targetturf.z == sourceturf.z)) + M.show_message("\icon[icon] [message]", 1) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 8a84c243b45..bc12c738891 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -1,550 +1,550 @@ -/mob/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - - if(ismob(mover)) - var/mob/moving_mob = mover - - if ((other_mobs && moving_mob.other_mobs)) - return 1 - - return (!mover.density || !density || lying) - -/client/North() - ..() - - -/client/South() - ..() - - -/client/West() - ..() - - -/client/East() - ..() - - -/client/Northeast() - swap_hand() - return - - -/client/Southeast() - attack_self() - return - - -/client/Southwest() - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.toggle_throw_mode() - else - to_chat(usr, "This mob type cannot throw items.") - return - - -/client/Northwest() - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - if(!C.get_active_hand()) - to_chat(usr, "You have nothing to drop in your hand.") - return - drop_item() - else if(isMoMMI(usr)) - var/mob/living/silicon/robot/mommi/M = usr - if(!M.get_active_hand()) - to_chat(M, "You have nothing to drop or store.") - return - M.uneq_active() - else if(isrobot(usr)) - var/mob/living/silicon/robot/R = usr - if(!R.module_active) - return - R.uneq_active() - else - to_chat(usr, "This mob type cannot drop items.") - return - -//This gets called when you press the delete button. -/client/verb/delete_key_pressed() - set hidden = 1 - - if(!usr.pulling) - to_chat(usr, "You are not pulling anything.") - return - usr.stop_pulling() - -/client/verb/swap_hand() - set hidden = 1 - if(istype(mob, /mob/living/carbon)) - mob:swap_hand() - if(istype(mob,/mob/living/silicon/robot/mommi)) - return // MoMMIs only have one tool slot. - if(istype(mob,/mob/living/silicon/robot))//Oh nested logic loops, is there anything you can't do? -Sieve - var/mob/living/silicon/robot/R = mob - if(!R.module_active) - if(!R.module_state_1) - if(!R.module_state_2) - if(!R.module_state_3) - return - else - R:inv1.icon_state = "inv1" - R:inv2.icon_state = "inv2" - R:inv3.icon_state = "inv3 +a" - R:module_active = R:module_state_3 - else - R:inv1.icon_state = "inv1" - R:inv2.icon_state = "inv2 +a" - R:inv3.icon_state = "inv3" - R:module_active = R:module_state_2 - else - R:inv1.icon_state = "inv1 +a" - R:inv2.icon_state = "inv2" - R:inv3.icon_state = "inv3" - R:module_active = R:module_state_1 - else - if(R.module_active == R.module_state_1) - if(!R.module_state_2) - if(!R.module_state_3) - return - else - R:inv1.icon_state = "inv1" - R:inv2.icon_state = "inv2" - R:inv3.icon_state = "inv3 +a" - R:module_active = R:module_state_3 - else - R:inv1.icon_state = "inv1" - R:inv2.icon_state = "inv2 +a" - R:inv3.icon_state = "inv3" - R:module_active = R:module_state_2 - else if(R.module_active == R.module_state_2) - if(!R.module_state_3) - if(!R.module_state_1) - return - else - R:inv1.icon_state = "inv1 +a" - R:inv2.icon_state = "inv2" - R:inv3.icon_state = "inv3" - R:module_active = R:module_state_1 - else - R:inv1.icon_state = "inv1" - R:inv2.icon_state = "inv2" - R:inv3.icon_state = "inv3 +a" - R:module_active = R:module_state_3 - else if(R.module_active == R.module_state_3) - if(!R.module_state_1) - if(!R.module_state_2) - return - else - R:inv1.icon_state = "inv1" - R:inv2.icon_state = "inv2 +a" - R:inv3.icon_state = "inv3" - R:module_active = R:module_state_2 - else - R:inv1.icon_state = "inv1 +a" - R:inv2.icon_state = "inv2" - R:inv3.icon_state = "inv3" - R:module_active = R:module_state_1 - else - return - return - - - -/client/verb/attack_self() - set hidden = 1 - if(mob) - mob.mode() - return - - -/client/verb/toggle_throw_mode() - set hidden = 1 - if(!istype(mob, /mob/living/carbon)) - return - if (!mob.stat && isturf(mob.loc) && !mob.restrained()) - mob:toggle_throw_mode() - else - return - - -/client/verb/drop_item() - set hidden = 1 - if(!isrobot(mob)) - mob.drop_item_v() - return - - -/client/Center() - /* No 3D movement in 2D spessman game. dir 16 is Z Up - if (isobj(mob.loc)) - var/obj/O = mob.loc - if (mob.canmove) - return O.relaymove(mob, 16) - */ - return - -/client/proc/Move_object(direct) - if(mob && mob.control_object) - if(mob.control_object.density) - step(mob.control_object,direct) - if(!mob.control_object) return - mob.control_object.dir = direct - else - mob.control_object.loc = get_step(mob.control_object,direct) - return - -/client/proc/Dir_object(direct) - if(mob && mob.orient_object) - var/obj/O = mob.orient_object - O.dir = direct - -/client/Move(loc,dir) - if(!mob) - return // Moved here to avoid nullrefs below. - N3X - if(mob.timestopped) - return 0 - if(move_delayer.next_allowed > world.time) - return 0 - - // /vg/ - Deny clients from moving certain mobs. (Like cluwnes :^) - if(mob.deny_client_move) - to_chat(src, "You cannot move this mob.") - return - - if(mob.control_object) - Move_object(dir) - - if(mob.orient_object) - Dir_object(dir) - return - - if(mob.incorporeal_move) - Process_Incorpmove(dir) - return - - for(var/obj/effect/stop/S in mob.loc) - if(S.victim == mob) - return - - if(mob.stat == DEAD) - return - - if(isAI(mob)) - return AIMove(loc,dir,mob) - - if(mob.monkeyizing) - return//This is sota the goto stop mobs from moving var - - if(Process_Grab()) - return - - if(mob.locked_to) //if we're locked_to to something, tell it we moved. - return mob.locked_to.relaymove(mob, dir) - - if(!mob.canmove) - return - - //if(istype(mob.loc, /turf/space) || (mob.flags & NOGRAV)) - // if(!mob.Process_Spacemove(0)) return 0 - - // If we're in space or our area has no gravity... - if(istype(mob.loc, /turf/space) || (mob.areaMaster && mob.areaMaster.has_gravity == 0)) - var/can_move_without_gravity = 0 - - // Here, we check to see if the object we're in doesn't need gravity to send relaymove(). - if(istype(mob.loc, /atom/movable)) - var/atom/movable/AM = mob.loc - if(AM.internal_gravity) // Best name I could come up with, sorry. - N3X - can_move_without_gravity=1 - - // Block relaymove() if needed. - if(!can_move_without_gravity && !mob.Process_Spacemove(0)) - return 0 - - if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved - var/atom/O = mob.loc - return O.relaymove(mob, dir) - - if(isturf(mob.loc)) - if(mob.restrained())//Why being pulled while cuffed prevents you from moving - for(var/mob/M in range(mob, 1)) - if(M.pulling == mob) - if(!M.restrained() && M.stat == 0 && M.canmove && mob.Adjacent(M)) - to_chat(src, "You're restrained! You can't move!") - return 0 - else - M.stop_pulling() - if(mob.tether) - var/datum/chain/chain_datum = mob.tether.chain_datum - if(chain_datum.extremity_A == mob) - if(istype(chain_datum.extremity_B,/mob/living)) - to_chat(src, "You're restrained! You can't move!") - return 0 - else if(chain_datum.extremity_B == mob) - if(istype(chain_datum.extremity_A,/mob/living)) - to_chat(src, "You're restrained! You can't move!") - return 0 - - if(mob.pinned.len) - to_chat(src, "You're pinned to a wall by [mob.pinned[1]]!") - return 0 - - // COMPLEX MOVE DELAY SHIT - //////////////////////////// - var/move_delay=0 // set move delay - mob.last_move_intent = world.time + 10 - switch(mob.m_intent) - if("run") - if(mob.drowsyness > 0) - move_delay += 6 - move_delay += 1+config.run_speed - if("walk") - move_delay += 7+config.walk_speed - move_delay += mob.movement_delay() - - var/obj/item/weapon/grab/Findgrab = locate() in mob - if(Findgrab) - move_delay += 7 - - //We are now going to move - move_delay = max(move_delay,1) - mob.delayNextMove(move_delay) - //Something with pulling things - if(Findgrab) - var/list/L = mob.ret_grab() - if(istype(L, /list)) - if(L.len == 2) - L -= mob - var/mob/M = L[1] - if(M) - if ((mob.Adjacent(M) || M.loc == mob.loc)) - var/turf/T = mob.loc - . = ..() - if (isturf(M.loc)) - var/diag = get_dir(mob, M) - if ((diag - 1) & diag) - else - diag = null - if ((get_dist(mob, M) > 1 || diag)) - step(M, get_dir(M.loc, T)) - else - for(var/mob/M in L) - M.other_mobs = 1 - if(mob != M) - M.animate_movement = 3 - for(var/mob/M in L) - spawn( 0 ) - step(M, dir) - return - spawn( 1 ) - M.other_mobs = null - M.animate_movement = 2 - return - - else if(mob.confused) - step_rand(mob) - mob.last_movement=world.time - else - . = ..() - mob.last_movement=world.time - -///Process_Grab() -///Called by client/Move() -///Checks to see if you are being grabbed and if so attemps to break it -/client/proc/Process_Grab() - if(locate(/obj/item/weapon/grab, locate(/obj/item/weapon/grab, mob.grabbed_by.len))) - var/list/grabbing = list() - if(istype(mob.l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = mob.l_hand - grabbing += G.affecting - if(istype(mob.r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = mob.r_hand - grabbing += G.affecting - for(var/obj/item/weapon/grab/G in mob.grabbed_by) - if((G.state == GRAB_PASSIVE)&&(!grabbing.Find(G.assailant))) del(G) - if(G.state == GRAB_AGGRESSIVE) - mob.delayNextMove(10) - if(!prob(25)) return 1 - mob.visible_message("[mob] has broken free of [G.assailant]'s grip!", - drugged_message="[mob] has broken free of [G.assailant]'s hug!") - returnToPool(G) - if(G.state == GRAB_NECK) - mob.delayNextMove(10) - if(!prob(5)) return 1 - mob.visible_message("[mob] has broken free of [G.assailant]'s headlock!", - drugged_message="[mob] has broken free of [G.assailant]'s passionate hug!") - returnToPool(G) - return 0 - - -///Process_Incorpmove -///Called by client/Move() -///Allows mobs to run though walls -/client/proc/Process_Incorpmove(direct) - var/turf/mobloc = get_turf(mob) - - switch(mob.incorporeal_move) - if(INCORPOREAL_GHOST) - if(isobserver(mob)) //Typecast time - var/mob/dead/observer/observer = mob - if(observer.locked_to) //Ghosts can move at any time to unlock themselves (in theory from following a mob) - observer.manual_stop_follow(observer.locked_to) - var/turf/T = get_step(mob, direct) - var/area/A = get_area(T) - if(A && A.anti_ethereal && !isAdminGhost(mob)) - to_chat(mob, "A dark forcefield prevents you from entering the area.") - else - if((T && T.holy) && isobserver(mob) && ((mob.invisibility == 0) || (ticker.mode && (mob.mind in ticker.mode.cult)))) - to_chat(mob, "You cannot get past holy grounds while you are in this plane of existence!") - else - mob.forceEnter(get_step(mob, direct)) - mob.dir = direct - if(INCORPOREAL_NINJA) - if(prob(50)) - var/locx - var/locy - switch(direct) - if(NORTH) - locx = mobloc.x - locy = (mobloc.y+2) - if(locy>world.maxy) - return - if(SOUTH) - locx = mobloc.x - locy = (mobloc.y-2) - if(locy<1) - return - if(EAST) - locy = mobloc.y - locx = (mobloc.x+2) - if(locx>world.maxx) - return - if(WEST) - locy = mobloc.y - locx = (mobloc.x-2) - if(locx<1) - return - else - return - mob.loc = locate(locx,locy,mobloc.z) - spawn(0) - var/limit = 2//For only two trailing shadows. - for(var/turf/T in getline(mobloc, mob.loc)) - anim(T,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir) - limit-- - if(limit<=0) break - else - anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir) - mob.forceEnter(get_step(mob, direct)) - mob.dir = direct - if(INCORPOREAL_ETHEREAL) //Jaunting, without needing to be done through relaymove - var/turf/newLoc = get_step(mob,direct) - if(!(newLoc.flags & NOJAUNT)) - mob.forceEnter(newLoc) - mob.dir = direct - else - to_chat(mob, "Some strange aura is blocking the way!") - mob.delayNextMove(2) - return 1 - // Crossed is always a bit iffy - for(var/obj/S in mob.loc) - if(istype(S,/obj/effect/step_trigger) || istype(S,/obj/effect/beam)) - S.Crossed(mob) - mob.delayNextMove(1) - - return 1 - - -///Process_Spacemove -///Called by /client/Move() -///For moving in space -///Return 1 for movement 0 for none -/mob/proc/Process_Spacemove(var/check_drift = 0,var/ignore_slip = 0) - //First check to see if we can do things - if(restrained()) - return 0 - - /* - if(istype(src,/mob/living/carbon)) - if(src.l_hand && src.r_hand) - return 0 - */ - - var/dense_object = 0 - for(var/turf/turf in oview(1,src)) - if(istype(turf,/turf/space)) - continue - - var/mob/living/carbon/human/H = src - if(istype(turf,/turf/simulated/floor) && (src.areaMaster && src.areaMaster.has_gravity == 0) && !(istype(H) && istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP))) - continue - - dense_object++ - break - - if(!dense_object && (locate(/obj/structure/lattice) in oview(1, src))) - dense_object++ - if(!dense_object && (locate(/obj/structure/catwalk) in oview(1, src))) - dense_object++ - - //Lastly attempt to locate any dense objects we could push off of - //TODO: If we implement objects drifing in space this needs to really push them - //Due to a few issues only anchored and dense objects will now work. - if(!dense_object) - for(var/obj/O in oview(1, src)) - if((O) && (O.density) && (O.anchored)) - dense_object++ - break - - //Nothing to push off of so end here - if(!dense_object) - return 0 - - - - //Check to see if we slipped - if(!ignore_slip && prob(Process_Spaceslipping(5))) - to_chat(src, "You slipped!") - src.inertia_dir = src.last_move - step(src, src.inertia_dir) - return 0 - //If not then we can reset inertia and move - inertia_dir = 0 - return 1 - - -/mob/proc/Process_Spaceslipping(var/prob_slip = 5) - //Setup slipage - //If knocked out we might just hit it and stop. This makes it possible to get dead bodies and such. - if(stat) - prob_slip = 0 // Changing this to zero to make it line up with the comment. - - prob_slip = round(prob_slip) - return(prob_slip) - - -/mob/proc/Move_Pulled(var/atom/A) - if(!canmove || restrained() || !pulling) - return - if(pulling.anchored) - return - if(!pulling.Adjacent(src)) - return - if(!isturf(pulling.loc)) - return - if(A == loc && pulling.density) - return - if(!Process_Spacemove(,1)) - return - if(ismob(pulling)) - var/mob/M = pulling - var/atom/movable/t = M.pulling - M.stop_pulling() - step(pulling, get_dir(pulling.loc, A)) - if(M) - M.start_pulling(t) - else - step(pulling, get_dir(pulling.loc, A)) - return +/mob/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + + if(ismob(mover)) + var/mob/moving_mob = mover + + if ((other_mobs && moving_mob.other_mobs)) + return 1 + + return (!mover.density || !density || lying) + +/client/North() + ..() + + +/client/South() + ..() + + +/client/West() + ..() + + +/client/East() + ..() + + +/client/Northeast() + swap_hand() + return + + +/client/Southeast() + attack_self() + return + + +/client/Southwest() + if(iscarbon(usr)) + var/mob/living/carbon/C = usr + C.toggle_throw_mode() + else + to_chat(usr, "This mob type cannot throw items.") + return + + +/client/Northwest() + if(iscarbon(usr)) + var/mob/living/carbon/C = usr + if(!C.get_active_hand()) + to_chat(usr, "You have nothing to drop in your hand.") + return + drop_item() + else if(isMoMMI(usr)) + var/mob/living/silicon/robot/mommi/M = usr + if(!M.get_active_hand()) + to_chat(M, "You have nothing to drop or store.") + return + M.uneq_active() + else if(isrobot(usr)) + var/mob/living/silicon/robot/R = usr + if(!R.module_active) + return + R.uneq_active() + else + to_chat(usr, "This mob type cannot drop items.") + return + +//This gets called when you press the delete button. +/client/verb/delete_key_pressed() + set hidden = 1 + + if(!usr.pulling) + to_chat(usr, "You are not pulling anything.") + return + usr.stop_pulling() + +/client/verb/swap_hand() + set hidden = 1 + if(istype(mob, /mob/living/carbon)) + mob:swap_hand() + if(istype(mob,/mob/living/silicon/robot/mommi)) + return // MoMMIs only have one tool slot. + if(istype(mob,/mob/living/silicon/robot))//Oh nested logic loops, is there anything you can't do? -Sieve + var/mob/living/silicon/robot/R = mob + if(!R.module_active) + if(!R.module_state_1) + if(!R.module_state_2) + if(!R.module_state_3) + return + else + R:inv1.icon_state = "inv1" + R:inv2.icon_state = "inv2" + R:inv3.icon_state = "inv3 +a" + R:module_active = R:module_state_3 + else + R:inv1.icon_state = "inv1" + R:inv2.icon_state = "inv2 +a" + R:inv3.icon_state = "inv3" + R:module_active = R:module_state_2 + else + R:inv1.icon_state = "inv1 +a" + R:inv2.icon_state = "inv2" + R:inv3.icon_state = "inv3" + R:module_active = R:module_state_1 + else + if(R.module_active == R.module_state_1) + if(!R.module_state_2) + if(!R.module_state_3) + return + else + R:inv1.icon_state = "inv1" + R:inv2.icon_state = "inv2" + R:inv3.icon_state = "inv3 +a" + R:module_active = R:module_state_3 + else + R:inv1.icon_state = "inv1" + R:inv2.icon_state = "inv2 +a" + R:inv3.icon_state = "inv3" + R:module_active = R:module_state_2 + else if(R.module_active == R.module_state_2) + if(!R.module_state_3) + if(!R.module_state_1) + return + else + R:inv1.icon_state = "inv1 +a" + R:inv2.icon_state = "inv2" + R:inv3.icon_state = "inv3" + R:module_active = R:module_state_1 + else + R:inv1.icon_state = "inv1" + R:inv2.icon_state = "inv2" + R:inv3.icon_state = "inv3 +a" + R:module_active = R:module_state_3 + else if(R.module_active == R.module_state_3) + if(!R.module_state_1) + if(!R.module_state_2) + return + else + R:inv1.icon_state = "inv1" + R:inv2.icon_state = "inv2 +a" + R:inv3.icon_state = "inv3" + R:module_active = R:module_state_2 + else + R:inv1.icon_state = "inv1 +a" + R:inv2.icon_state = "inv2" + R:inv3.icon_state = "inv3" + R:module_active = R:module_state_1 + else + return + return + + + +/client/verb/attack_self() + set hidden = 1 + if(mob) + mob.mode() + return + + +/client/verb/toggle_throw_mode() + set hidden = 1 + if(!istype(mob, /mob/living/carbon)) + return + if (!mob.stat && isturf(mob.loc) && !mob.restrained()) + mob:toggle_throw_mode() + else + return + + +/client/verb/drop_item() + set hidden = 1 + if(!isrobot(mob)) + mob.drop_item_v() + return + + +/client/Center() + /* No 3D movement in 2D spessman game. dir 16 is Z Up + if (isobj(mob.loc)) + var/obj/O = mob.loc + if (mob.canmove) + return O.relaymove(mob, 16) + */ + return + +/client/proc/Move_object(direct) + if(mob && mob.control_object) + if(mob.control_object.density) + step(mob.control_object,direct) + if(!mob.control_object) return + mob.control_object.dir = direct + else + mob.control_object.loc = get_step(mob.control_object,direct) + return + +/client/proc/Dir_object(direct) + if(mob && mob.orient_object) + var/obj/O = mob.orient_object + O.dir = direct + +/client/Move(loc,dir) + if(!mob) + return // Moved here to avoid nullrefs below. - N3X + if(mob.timestopped) + return 0 + if(move_delayer.next_allowed > world.time) + return 0 + + // /vg/ - Deny clients from moving certain mobs. (Like cluwnes :^) + if(mob.deny_client_move) + to_chat(src, "You cannot move this mob.") + return + + if(mob.control_object) + Move_object(dir) + + if(mob.orient_object) + Dir_object(dir) + return + + if(mob.incorporeal_move) + Process_Incorpmove(dir) + return + + for(var/obj/effect/stop/S in mob.loc) + if(S.victim == mob) + return + + if(mob.stat == DEAD) + return + + if(isAI(mob)) + return AIMove(loc,dir,mob) + + if(mob.monkeyizing) + return//This is sota the goto stop mobs from moving var + + if(Process_Grab()) + return + + if(mob.locked_to) //if we're locked_to to something, tell it we moved. + return mob.locked_to.relaymove(mob, dir) + + if(!mob.canmove) + return + + //if(istype(mob.loc, /turf/space) || (mob.flags & NOGRAV)) + // if(!mob.Process_Spacemove(0)) return 0 + + // If we're in space or our area has no gravity... + if(istype(mob.loc, /turf/space) || (mob.areaMaster && mob.areaMaster.has_gravity == 0)) + var/can_move_without_gravity = 0 + + // Here, we check to see if the object we're in doesn't need gravity to send relaymove(). + if(istype(mob.loc, /atom/movable)) + var/atom/movable/AM = mob.loc + if(AM.internal_gravity) // Best name I could come up with, sorry. - N3X + can_move_without_gravity=1 + + // Block relaymove() if needed. + if(!can_move_without_gravity && !mob.Process_Spacemove(0)) + return 0 + + if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved + var/atom/O = mob.loc + return O.relaymove(mob, dir) + + if(isturf(mob.loc)) + if(mob.restrained())//Why being pulled while cuffed prevents you from moving + for(var/mob/M in range(mob, 1)) + if(M.pulling == mob) + if(!M.restrained() && M.stat == 0 && M.canmove && mob.Adjacent(M)) + to_chat(src, "You're restrained! You can't move!") + return 0 + else + M.stop_pulling() + if(mob.tether) + var/datum/chain/chain_datum = mob.tether.chain_datum + if(chain_datum.extremity_A == mob) + if(istype(chain_datum.extremity_B,/mob/living)) + to_chat(src, "You're restrained! You can't move!") + return 0 + else if(chain_datum.extremity_B == mob) + if(istype(chain_datum.extremity_A,/mob/living)) + to_chat(src, "You're restrained! You can't move!") + return 0 + + if(mob.pinned.len) + to_chat(src, "You're pinned to a wall by [mob.pinned[1]]!") + return 0 + + // COMPLEX MOVE DELAY SHIT + //////////////////////////// + var/move_delay=0 // set move delay + mob.last_move_intent = world.time + 10 + switch(mob.m_intent) + if("run") + if(mob.drowsyness > 0) + move_delay += 6 + move_delay += 1+config.run_speed + if("walk") + move_delay += 7+config.walk_speed + move_delay += mob.movement_delay() + + var/obj/item/weapon/grab/Findgrab = locate() in mob + if(Findgrab) + move_delay += 7 + + //We are now going to move + move_delay = max(move_delay,1) + mob.delayNextMove(move_delay) + //Something with pulling things + if(Findgrab) + var/list/L = mob.ret_grab() + if(istype(L, /list)) + if(L.len == 2) + L -= mob + var/mob/M = L[1] + if(M) + if ((mob.Adjacent(M) || M.loc == mob.loc)) + var/turf/T = mob.loc + . = ..() + if (isturf(M.loc)) + var/diag = get_dir(mob, M) + if ((diag - 1) & diag) + else + diag = null + if ((get_dist(mob, M) > 1 || diag)) + step(M, get_dir(M.loc, T)) + else + for(var/mob/M in L) + M.other_mobs = 1 + if(mob != M) + M.animate_movement = 3 + for(var/mob/M in L) + spawn( 0 ) + step(M, dir) + return + spawn( 1 ) + M.other_mobs = null + M.animate_movement = 2 + return + + else if(mob.confused) + step_rand(mob) + mob.last_movement=world.time + else + . = ..() + mob.last_movement=world.time + +///Process_Grab() +///Called by client/Move() +///Checks to see if you are being grabbed and if so attemps to break it +/client/proc/Process_Grab() + if(locate(/obj/item/weapon/grab, locate(/obj/item/weapon/grab, mob.grabbed_by.len))) + var/list/grabbing = list() + if(istype(mob.l_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = mob.l_hand + grabbing += G.affecting + if(istype(mob.r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = mob.r_hand + grabbing += G.affecting + for(var/obj/item/weapon/grab/G in mob.grabbed_by) + if((G.state == GRAB_PASSIVE)&&(!grabbing.Find(G.assailant))) del(G) + if(G.state == GRAB_AGGRESSIVE) + mob.delayNextMove(10) + if(!prob(25)) return 1 + mob.visible_message("[mob] has broken free of [G.assailant]'s grip!", + drugged_message="[mob] has broken free of [G.assailant]'s hug!") + returnToPool(G) + if(G.state == GRAB_NECK) + mob.delayNextMove(10) + if(!prob(5)) return 1 + mob.visible_message("[mob] has broken free of [G.assailant]'s headlock!", + drugged_message="[mob] has broken free of [G.assailant]'s passionate hug!") + returnToPool(G) + return 0 + + +///Process_Incorpmove +///Called by client/Move() +///Allows mobs to run though walls +/client/proc/Process_Incorpmove(direct) + var/turf/mobloc = get_turf(mob) + + switch(mob.incorporeal_move) + if(INCORPOREAL_GHOST) + if(isobserver(mob)) //Typecast time + var/mob/dead/observer/observer = mob + if(observer.locked_to) //Ghosts can move at any time to unlock themselves (in theory from following a mob) + observer.manual_stop_follow(observer.locked_to) + var/turf/T = get_step(mob, direct) + var/area/A = get_area(T) + if(A && A.anti_ethereal && !isAdminGhost(mob)) + to_chat(mob, "A dark forcefield prevents you from entering the area.") + else + if((T && T.holy) && isobserver(mob) && ((mob.invisibility == 0) || (ticker.mode && (mob.mind in ticker.mode.cult)))) + to_chat(mob, "You cannot get past holy grounds while you are in this plane of existence!") + else + mob.forceEnter(get_step(mob, direct)) + mob.dir = direct + if(INCORPOREAL_NINJA) + if(prob(50)) + var/locx + var/locy + switch(direct) + if(NORTH) + locx = mobloc.x + locy = (mobloc.y+2) + if(locy>world.maxy) + return + if(SOUTH) + locx = mobloc.x + locy = (mobloc.y-2) + if(locy<1) + return + if(EAST) + locy = mobloc.y + locx = (mobloc.x+2) + if(locx>world.maxx) + return + if(WEST) + locy = mobloc.y + locx = (mobloc.x-2) + if(locx<1) + return + else + return + mob.loc = locate(locx,locy,mobloc.z) + spawn(0) + var/limit = 2//For only two trailing shadows. + for(var/turf/T in getline(mobloc, mob.loc)) + anim(T,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir) + limit-- + if(limit<=0) break + else + anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir) + mob.forceEnter(get_step(mob, direct)) + mob.dir = direct + if(INCORPOREAL_ETHEREAL) //Jaunting, without needing to be done through relaymove + var/turf/newLoc = get_step(mob,direct) + if(!(newLoc.flags & NOJAUNT)) + mob.forceEnter(newLoc) + mob.dir = direct + else + to_chat(mob, "Some strange aura is blocking the way!") + mob.delayNextMove(2) + return 1 + // Crossed is always a bit iffy + for(var/obj/S in mob.loc) + if(istype(S,/obj/effect/step_trigger) || istype(S,/obj/effect/beam)) + S.Crossed(mob) + mob.delayNextMove(1) + + return 1 + + +///Process_Spacemove +///Called by /client/Move() +///For moving in space +///Return 1 for movement 0 for none +/mob/proc/Process_Spacemove(var/check_drift = 0,var/ignore_slip = 0) + //First check to see if we can do things + if(restrained()) + return 0 + + /* + if(istype(src,/mob/living/carbon)) + if(src.l_hand && src.r_hand) + return 0 + */ + + var/dense_object = 0 + for(var/turf/turf in oview(1,src)) + if(istype(turf,/turf/space)) + continue + + var/mob/living/carbon/human/H = src + if(istype(turf,/turf/simulated/floor) && (src.areaMaster && src.areaMaster.has_gravity == 0) && !(istype(H) && istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP))) + continue + + dense_object++ + break + + if(!dense_object && (locate(/obj/structure/lattice) in oview(1, src))) + dense_object++ + if(!dense_object && (locate(/obj/structure/catwalk) in oview(1, src))) + dense_object++ + + //Lastly attempt to locate any dense objects we could push off of + //TODO: If we implement objects drifing in space this needs to really push them + //Due to a few issues only anchored and dense objects will now work. + if(!dense_object) + for(var/obj/O in oview(1, src)) + if((O) && (O.density) && (O.anchored)) + dense_object++ + break + + //Nothing to push off of so end here + if(!dense_object) + return 0 + + + + //Check to see if we slipped + if(!ignore_slip && prob(Process_Spaceslipping(5))) + to_chat(src, "You slipped!") + src.inertia_dir = src.last_move + step(src, src.inertia_dir) + return 0 + //If not then we can reset inertia and move + inertia_dir = 0 + return 1 + + +/mob/proc/Process_Spaceslipping(var/prob_slip = 5) + //Setup slipage + //If knocked out we might just hit it and stop. This makes it possible to get dead bodies and such. + if(stat) + prob_slip = 0 // Changing this to zero to make it line up with the comment. + + prob_slip = round(prob_slip) + return(prob_slip) + + +/mob/proc/Move_Pulled(var/atom/A) + if(!canmove || restrained() || !pulling) + return + if(pulling.anchored) + return + if(!pulling.Adjacent(src)) + return + if(!isturf(pulling.loc)) + return + if(A == loc && pulling.density) + return + if(!Process_Spacemove(,1)) + return + if(ismob(pulling)) + var/mob/M = pulling + var/atom/movable/t = M.pulling + M.stop_pulling() + step(pulling, get_dir(pulling.loc, A)) + if(M) + M.start_pulling(t) + else + step(pulling, get_dir(pulling.loc, A)) + return diff --git a/code/modules/mob/new_player/logout.dm b/code/modules/mob/new_player/logout.dm index ad1c9b3098d..c9e7aa67ebf 100644 --- a/code/modules/mob/new_player/logout.dm +++ b/code/modules/mob/new_player/logout.dm @@ -1,7 +1,7 @@ -/mob/new_player/Logout() - ready = 0 - ..() - if(!spawning)//Here so that if they are spawning and log out, the other procs can play out and they will have a mob to come back to. - key = null//We null their key before deleting the mob, so they are properly kicked out. - qdel(src) +/mob/new_player/Logout() + ready = 0 + ..() + if(!spawning)//Here so that if they are spawning and log out, the other procs can play out and they will have a mob to come back to. + key = null//We null their key before deleting the mob, so they are properly kicked out. + qdel(src) return \ No newline at end of file diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index d5edc0200aa..5230ad7b70f 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -1,520 +1,520 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/mob/new_player - var/ready = 0 - var/spawning = 0//Referenced when you want to delete the new_player later on in the code. - var/totalPlayers = 0 //Player counts for the Lobby tab - var/totalPlayersReady = 0 - - flags = NONE - - invisibility = 101 - - density = 0 - stat = 2 - canmove = 0 - - anchored = 1 // don't get pushed around - -/mob/new_player/verb/new_player_panel() - set src = usr - new_player_panel_proc() - - -/mob/new_player/proc/new_player_panel_proc() - var/output = "

    New Player Options" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:28: output +="
    " - output += {"
    -

    Setup Character

    "} - // END AUTOFIX - if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) - if(!ready) output += "

    Declare Ready

    " - else output += "

    You are ready (Cancel)

    " - - else - ready = 0 // prevent setup character issues - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:36: output += "View the Crew Manifest

    " - output += {"View the Crew Manifest

    -

    Join Game!

    "} - // END AUTOFIX - - output += "

    Observe

    " - - if(!IsGuestKey(src.key)) - establish_db_connection() - - if(dbcon.IsConnected()) - var/isadmin = 0 - if(src.client && src.client.holder) - isadmin = 1 - var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM erro_poll_vote WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM erro_poll_textreply WHERE ckey = \"[ckey]\")") - query.Execute() - var/newpoll = 0 - while(query.NextRow()) - newpoll = 1 - break - - if(newpoll) - output += "

    Show Player Polls (NEW!)

    " - else - output += "

    Show Player Polls

    " - - output += "
    " - - src << browse(output,"window=playersetup;size=210x240;can_close=0") - return - -/mob/new_player/Stat() - ..() - - if(statpanel("Status") && ticker) - if (ticker.current_state != GAME_STATE_PREGAME) - stat(null, "Station Time: [worldtime2text()]") - statpanel("Lobby") - if(statpanel("Lobby") && ticker) - if(ticker.hide_mode) - stat("Game Mode:", "Secret") - else - stat("Game Mode:", "[master_mode]") - - if(master_controller.initialized) - if((ticker.current_state == GAME_STATE_PREGAME) && going) - stat("Time To Start:", (round(ticker.pregame_timeleft - world.timeofday) / 10)) //rounding because people freak out at decimals i guess - if((ticker.current_state == GAME_STATE_PREGAME) && !going) - stat("Time To Start:", "DELAYED") - else - stat("Time To Start:", "LOADING...") - - if(master_controller.initialized && ticker.current_state == GAME_STATE_PREGAME) - stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]") - totalPlayers = 0 - totalPlayersReady = 0 - for(var/mob/new_player/player in player_list) - stat("[player.key]", (player.ready)?("(Playing)"):(null)) - totalPlayers++ - if(player.ready)totalPlayersReady++ - -/mob/new_player/Topic(href, href_list[]) - //var/timestart = world.timeofday - //testing("topic call for [usr] [href]") - if(usr != src) - return 0 - - if(!client) return 0 - - if(href_list["show_preferences"]) - client.prefs.ShowChoices(src) - return 1 - - if(href_list["ready"]) - switch(text2num(href_list["ready"])) - if(1) - ready = 1 - if(2) - ready = 0 - to_chat(usr, "You [ready ? "have declared ready" : "have unreadied"].") - new_player_panel_proc() - //testing("[usr] topic call took [(world.timeofday - timestart)/10] seconds") - return 1 - - if(href_list["refresh"]) - src << browse(null, "window=playersetup") //closes the player setup window - new_player_panel_proc() - - if(href_list["observe"]) - - if(alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") == "Yes") - if(!client) return 1 - var/mob/dead/observer/observer = new() - - spawning = 1 - to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// MAD JAMS cant last forever yo +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - - observer.started_as_observer = 1 - close_spawn_windows() - var/obj/O = locate("landmark*Observer-Start") +/mob/new_player + var/ready = 0 + var/spawning = 0//Referenced when you want to delete the new_player later on in the code. + var/totalPlayers = 0 //Player counts for the Lobby tab + var/totalPlayersReady = 0 + + flags = NONE + + invisibility = 101 + + density = 0 + stat = 2 + canmove = 0 + + anchored = 1 // don't get pushed around + +/mob/new_player/verb/new_player_panel() + set src = usr + new_player_panel_proc() + + +/mob/new_player/proc/new_player_panel_proc() + var/output = "
    New Player Options" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:28: output +="
    " + output += {"
    +

    Setup Character

    "} + // END AUTOFIX + if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) + if(!ready) output += "

    Declare Ready

    " + else output += "

    You are ready (Cancel)

    " + + else + ready = 0 // prevent setup character issues + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:36: output += "View the Crew Manifest

    " + output += {"View the Crew Manifest

    +

    Join Game!

    "} + // END AUTOFIX + + output += "

    Observe

    " + + if(!IsGuestKey(src.key)) + establish_db_connection() + + if(dbcon.IsConnected()) + var/isadmin = 0 + if(src.client && src.client.holder) + isadmin = 1 + var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM erro_poll_vote WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM erro_poll_textreply WHERE ckey = \"[ckey]\")") + query.Execute() + var/newpoll = 0 + while(query.NextRow()) + newpoll = 1 + break + + if(newpoll) + output += "

    Show Player Polls (NEW!)

    " + else + output += "

    Show Player Polls

    " + + output += "
    " + + src << browse(output,"window=playersetup;size=210x240;can_close=0") + return + +/mob/new_player/Stat() + ..() + + if(statpanel("Status") && ticker) + if (ticker.current_state != GAME_STATE_PREGAME) + stat(null, "Station Time: [worldtime2text()]") + statpanel("Lobby") + if(statpanel("Lobby") && ticker) + if(ticker.hide_mode) + stat("Game Mode:", "Secret") + else + stat("Game Mode:", "[master_mode]") + + if(master_controller.initialized) + if((ticker.current_state == GAME_STATE_PREGAME) && going) + stat("Time To Start:", (round(ticker.pregame_timeleft - world.timeofday) / 10)) //rounding because people freak out at decimals i guess + if((ticker.current_state == GAME_STATE_PREGAME) && !going) + stat("Time To Start:", "DELAYED") + else + stat("Time To Start:", "LOADING...") + + if(master_controller.initialized && ticker.current_state == GAME_STATE_PREGAME) + stat("Players: [totalPlayers]", "Players Ready: [totalPlayersReady]") + totalPlayers = 0 + totalPlayersReady = 0 + for(var/mob/new_player/player in player_list) + stat("[player.key]", (player.ready)?("(Playing)"):(null)) + totalPlayers++ + if(player.ready)totalPlayersReady++ + +/mob/new_player/Topic(href, href_list[]) + //var/timestart = world.timeofday + //testing("topic call for [usr] [href]") + if(usr != src) + return 0 + + if(!client) return 0 + + if(href_list["show_preferences"]) + client.prefs.ShowChoices(src) + return 1 + + if(href_list["ready"]) + switch(text2num(href_list["ready"])) + if(1) + ready = 1 + if(2) + ready = 0 + to_chat(usr, "You [ready ? "have declared ready" : "have unreadied"].") + new_player_panel_proc() + //testing("[usr] topic call took [(world.timeofday - timestart)/10] seconds") + return 1 + + if(href_list["refresh"]) + src << browse(null, "window=playersetup") //closes the player setup window + new_player_panel_proc() + + if(href_list["observe"]) + + if(alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No") == "Yes") + if(!client) return 1 + var/mob/dead/observer/observer = new() + + spawning = 1 + to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// MAD JAMS cant last forever yo + + + observer.started_as_observer = 1 + close_spawn_windows() + var/obj/O = locate("landmark*Observer-Start") to_chat(src, "Now teleporting.") - observer.loc = O.loc - observer.timeofdeath = world.time // Set the time of death so that the respawn timer works correctly. - - client.prefs.update_preview_icon(1) - observer.icon = client.prefs.preview_icon - observer.alpha = 127 - - if(client.prefs.be_random_name) - client.prefs.real_name = random_name(client.prefs.gender,client.prefs.species) - observer.real_name = client.prefs.real_name - observer.name = observer.real_name - if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. - observer.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! - observer.key = key - mob_list -= src - qdel(src) - - return 1 - - if(href_list["late_join"]) - if(!ticker || ticker.current_state != GAME_STATE_PLAYING) + observer.loc = O.loc + observer.timeofdeath = world.time // Set the time of death so that the respawn timer works correctly. + + client.prefs.update_preview_icon(1) + observer.icon = client.prefs.preview_icon + observer.alpha = 127 + + if(client.prefs.be_random_name) + client.prefs.real_name = random_name(client.prefs.gender,client.prefs.species) + observer.real_name = client.prefs.real_name + observer.name = observer.real_name + if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. + observer.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! + observer.key = key + mob_list -= src + qdel(src) + + return 1 + + if(href_list["late_join"]) + if(!ticker || ticker.current_state != GAME_STATE_PLAYING) to_chat(usr, "The round is either not ready, or has already finished...") - return - - if(client.prefs.species != "Human") - - if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist) + return + + if(client.prefs.species != "Human") + + if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist) to_chat(src, alert("You are currently not whitelisted to play [client.prefs.species].")) - return 0 - - LateChoices() - - if(href_list["manifest"]) - ViewManifest() - - if(href_list["SelectedJob"]) - - if(!enter_allowed) + return 0 + + LateChoices() + + if(href_list["manifest"]) + ViewManifest() + + if(href_list["SelectedJob"]) + + if(!enter_allowed) to_chat(usr, "There is an administrative lock on entering the game!") - return - - if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist) + return + + if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist) to_chat(src, alert("You are currently not whitelisted to play [client.prefs.species].")) - return 0 - - AttemptLateSpawn(href_list["SelectedJob"]) - return - - if(href_list["privacy_poll"]) - establish_db_connection() - if(!dbcon.IsConnected()) - return - var/voted = 0 - - //First check if the person has not voted yet. - var/DBQuery/query = dbcon.NewQuery("SELECT * FROM erro_privacy WHERE ckey='[src.ckey]'") - query.Execute() - while(query.NextRow()) - voted = 1 - break - - //This is a safety switch, so only valid options pass through - var/option = "UNKNOWN" - switch(href_list["privacy_poll"]) - if("signed") - option = "SIGNED" - if("anonymous") - option = "ANONYMOUS" - if("nostats") - option = "NOSTATS" - if("later") - usr << browse(null,"window=privacypoll") - return - if("abstain") - option = "ABSTAIN" - - if(option == "UNKNOWN") - return - - if(!voted) - var/sql = "INSERT INTO erro_privacy VALUES (null, Now(), '[src.ckey]', '[option]')" - var/DBQuery/query_insert = dbcon.NewQuery(sql) - query_insert.Execute() + return 0 + + AttemptLateSpawn(href_list["SelectedJob"]) + return + + if(href_list["privacy_poll"]) + establish_db_connection() + if(!dbcon.IsConnected()) + return + var/voted = 0 + + //First check if the person has not voted yet. + var/DBQuery/query = dbcon.NewQuery("SELECT * FROM erro_privacy WHERE ckey='[src.ckey]'") + query.Execute() + while(query.NextRow()) + voted = 1 + break + + //This is a safety switch, so only valid options pass through + var/option = "UNKNOWN" + switch(href_list["privacy_poll"]) + if("signed") + option = "SIGNED" + if("anonymous") + option = "ANONYMOUS" + if("nostats") + option = "NOSTATS" + if("later") + usr << browse(null,"window=privacypoll") + return + if("abstain") + option = "ABSTAIN" + + if(option == "UNKNOWN") + return + + if(!voted) + var/sql = "INSERT INTO erro_privacy VALUES (null, Now(), '[src.ckey]', '[option]')" + var/DBQuery/query_insert = dbcon.NewQuery(sql) + query_insert.Execute() to_chat(usr, "Thank you for your vote!") - usr << browse(null,"window=privacypoll") - - if(!ready && href_list["preference"]) - if(client) - client.prefs.process_link(src, href_list) - else if(!href_list["late_join"]) - new_player_panel() - - if(href_list["showpoll"]) - - handle_player_polling() - return - - if(href_list["pollid"]) - - var/pollid = href_list["pollid"] - if(istext(pollid)) - pollid = text2num(pollid) - if(isnum(pollid)) - src.poll_player(pollid) - return - - if(href_list["votepollid"] && href_list["votetype"]) - var/pollid = text2num(href_list["votepollid"]) - var/votetype = href_list["votetype"] - switch(votetype) - if("OPTION") - var/optionid = text2num(href_list["voteoptionid"]) - vote_on_poll(pollid, optionid) - if("TEXT") - var/replytext = href_list["replytext"] - log_text_poll_reply(pollid, replytext) - if("NUMVAL") - var/id_min = text2num(href_list["minid"]) - var/id_max = text2num(href_list["maxid"]) - - if( (id_max - id_min) > 100 ) //Basic exploit prevention + usr << browse(null,"window=privacypoll") + + if(!ready && href_list["preference"]) + if(client) + client.prefs.process_link(src, href_list) + else if(!href_list["late_join"]) + new_player_panel() + + if(href_list["showpoll"]) + + handle_player_polling() + return + + if(href_list["pollid"]) + + var/pollid = href_list["pollid"] + if(istext(pollid)) + pollid = text2num(pollid) + if(isnum(pollid)) + src.poll_player(pollid) + return + + if(href_list["votepollid"] && href_list["votetype"]) + var/pollid = text2num(href_list["votepollid"]) + var/votetype = href_list["votetype"] + switch(votetype) + if("OPTION") + var/optionid = text2num(href_list["voteoptionid"]) + vote_on_poll(pollid, optionid) + if("TEXT") + var/replytext = href_list["replytext"] + log_text_poll_reply(pollid, replytext) + if("NUMVAL") + var/id_min = text2num(href_list["minid"]) + var/id_max = text2num(href_list["maxid"]) + + if( (id_max - id_min) > 100 ) //Basic exploit prevention to_chat(usr, "The option ID difference is too big. Please contact administration or the database admin.") - return - - for(var/optionid = id_min; optionid <= id_max; optionid++) - if(!isnull(href_list["o[optionid]"])) //Test if this optionid was replied to - var/rating - if(href_list["o[optionid]"] == "abstain") - rating = null - else - rating = text2num(href_list["o[optionid]"]) - if(!isnum(rating)) - return - - vote_on_numval_poll(pollid, optionid, rating) - if("MULTICHOICE") - var/id_min = text2num(href_list["minoptionid"]) - var/id_max = text2num(href_list["maxoptionid"]) - - if( (id_max - id_min) > 100 ) //Basic exploit prevention + return + + for(var/optionid = id_min; optionid <= id_max; optionid++) + if(!isnull(href_list["o[optionid]"])) //Test if this optionid was replied to + var/rating + if(href_list["o[optionid]"] == "abstain") + rating = null + else + rating = text2num(href_list["o[optionid]"]) + if(!isnum(rating)) + return + + vote_on_numval_poll(pollid, optionid, rating) + if("MULTICHOICE") + var/id_min = text2num(href_list["minoptionid"]) + var/id_max = text2num(href_list["maxoptionid"]) + + if( (id_max - id_min) > 100 ) //Basic exploit prevention to_chat(usr, "The option ID difference is too big. Please contact administration or the database admin.") - return - - for(var/optionid = id_min; optionid <= id_max; optionid++) - if(!isnull(href_list["option_[optionid]"])) //Test if this optionid was selected - vote_on_poll(pollid, optionid, 1) - -/mob/new_player/proc/IsJobAvailable(rank) - var/datum/job/job = job_master.GetJob(rank) - if(!job) return 0 - if((job.current_positions >= job.total_positions) && job.total_positions != -1) return 0 - if(jobban_isbanned(src,rank)) return 0 - if(!job.player_old_enough(src.client)) return 0 - // assistant limits - if(config.assistantlimit) - if(job.title == "Assistant") - var/count = 0 - var/datum/job/officer = job_master.GetJob("Security Officer") - var/datum/job/warden = job_master.GetJob("Warden") - var/datum/job/hos = job_master.GetJob("Head of Security") - count += (officer.current_positions + warden.current_positions + hos.current_positions) - if(job.current_positions > (config.assistantratio * count)) - if(count >= 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide - . = 1 - else - return 0 - if(job.title == "Assistant" && job.current_positions > 5) - var/datum/job/officer = job_master.GetJob("Security Officer") - if(officer.current_positions >= officer.total_positions) - officer.total_positions++ - . = 1 - return - -/mob/new_player/proc/FuckUpGenes(var/mob/living/carbon/human/H) - // 20% of players have bad genetic mutations. - if(prob(20)) - H.dna.GiveRandomSE(notflags = GENE_UNNATURAL,genetype = GENETYPE_BAD) - if(prob(10)) // 10% of those have a good mut. - H.dna.GiveRandomSE(notflags = GENE_UNNATURAL,genetype = GENETYPE_GOOD) - - -/mob/new_player/proc/AttemptLateSpawn(rank) - if (src != usr) - return 0 - if(!ticker || ticker.current_state != GAME_STATE_PLAYING) + return + + for(var/optionid = id_min; optionid <= id_max; optionid++) + if(!isnull(href_list["option_[optionid]"])) //Test if this optionid was selected + vote_on_poll(pollid, optionid, 1) + +/mob/new_player/proc/IsJobAvailable(rank) + var/datum/job/job = job_master.GetJob(rank) + if(!job) return 0 + if((job.current_positions >= job.total_positions) && job.total_positions != -1) return 0 + if(jobban_isbanned(src,rank)) return 0 + if(!job.player_old_enough(src.client)) return 0 + // assistant limits + if(config.assistantlimit) + if(job.title == "Assistant") + var/count = 0 + var/datum/job/officer = job_master.GetJob("Security Officer") + var/datum/job/warden = job_master.GetJob("Warden") + var/datum/job/hos = job_master.GetJob("Head of Security") + count += (officer.current_positions + warden.current_positions + hos.current_positions) + if(job.current_positions > (config.assistantratio * count)) + if(count >= 5) // if theres more than 5 security on the station just let assistants join regardless, they should be able to handle the tide + . = 1 + else + return 0 + if(job.title == "Assistant" && job.current_positions > 5) + var/datum/job/officer = job_master.GetJob("Security Officer") + if(officer.current_positions >= officer.total_positions) + officer.total_positions++ + . = 1 + return + +/mob/new_player/proc/FuckUpGenes(var/mob/living/carbon/human/H) + // 20% of players have bad genetic mutations. + if(prob(20)) + H.dna.GiveRandomSE(notflags = GENE_UNNATURAL,genetype = GENETYPE_BAD) + if(prob(10)) // 10% of those have a good mut. + H.dna.GiveRandomSE(notflags = GENE_UNNATURAL,genetype = GENETYPE_GOOD) + + +/mob/new_player/proc/AttemptLateSpawn(rank) + if (src != usr) + return 0 + if(!ticker || ticker.current_state != GAME_STATE_PLAYING) to_chat(usr, "The round is either not ready, or has already finished...") - return 0 - if(!enter_allowed) + return 0 + if(!enter_allowed) to_chat(usr, "There is an administrative lock on entering the game!") - return 0 - if(!IsJobAvailable(rank)) + return 0 + if(!IsJobAvailable(rank)) to_chat(src, alert("[rank] is not available. Please try another.")) - return 0 - - job_master.AssignRole(src, rank, 1) - - var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind - if(character.client.prefs.randomslot) character.client.prefs.random_character_sqlite(character, character.ckey) - job_master.EquipRank(character, rank, 1) //equips the human - EquipCustomItems(character) - - // TODO: Job-specific latejoin overrides. - character.loc = pick((assistant_latejoin.len > 0 && rank == "Assistant") ? assistant_latejoin : latejoin) - //Give them their fucking wheelchair where they spawn instead of inside of the splash screen - var/datum/organ/external/left_leg = character.get_organ("l_foot") - var/datum/organ/external/right_leg = character.get_organ("r_foot") - - if( (!left_leg || left_leg.status & ORGAN_DESTROYED) && (!right_leg || right_leg.status & ORGAN_DESTROYED) ) //If the character is missing both of his feet - var/obj/structure/bed/chair/vehicle/wheelchair/W = new(character.loc) - W.buckle_mob(character,character) - character.store_position() - - // WHY THE FUCK IS THIS HERE - // FOR GOD'S SAKE USE EVENTS - if(bomberman_mode) + return 0 + + job_master.AssignRole(src, rank, 1) + + var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind + if(character.client.prefs.randomslot) character.client.prefs.random_character_sqlite(character, character.ckey) + job_master.EquipRank(character, rank, 1) //equips the human + EquipCustomItems(character) + + // TODO: Job-specific latejoin overrides. + character.loc = pick((assistant_latejoin.len > 0 && rank == "Assistant") ? assistant_latejoin : latejoin) + //Give them their fucking wheelchair where they spawn instead of inside of the splash screen + var/datum/organ/external/left_leg = character.get_organ("l_foot") + var/datum/organ/external/right_leg = character.get_organ("r_foot") + + if( (!left_leg || left_leg.status & ORGAN_DESTROYED) && (!right_leg || right_leg.status & ORGAN_DESTROYED) ) //If the character is missing both of his feet + var/obj/structure/bed/chair/vehicle/wheelchair/W = new(character.loc) + W.buckle_mob(character,character) + character.store_position() + + // WHY THE FUCK IS THIS HERE + // FOR GOD'S SAKE USE EVENTS + if(bomberman_mode) to_chat(character.client, sound('sound/bomberman/start.ogg')) - if(character.wear_suit) - var/obj/item/O = character.wear_suit - character.u_equip(O,1) - O.loc = character.loc - //O.dropped(character) - if(character.head) - var/obj/item/O = character.head - character.u_equip(O,1) - O.loc = character.loc - //O.dropped(character) - character.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/bomberman(character), slot_head) - character.equip_to_slot_or_del(new /obj/item/clothing/suit/space/bomberman(character), slot_wear_suit) - character.equip_to_slot_or_del(new /obj/item/weapon/bomberman/(character), slot_s_store) - character.update_icons() + if(character.wear_suit) + var/obj/item/O = character.wear_suit + character.u_equip(O,1) + O.loc = character.loc + //O.dropped(character) + if(character.head) + var/obj/item/O = character.head + character.u_equip(O,1) + O.loc = character.loc + //O.dropped(character) + character.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/bomberman(character), slot_head) + character.equip_to_slot_or_del(new /obj/item/clothing/suit/space/bomberman(character), slot_wear_suit) + character.equip_to_slot_or_del(new /obj/item/weapon/bomberman/(character), slot_s_store) + character.update_icons() to_chat(character, "Tip: Use the BBD in your suit's pocket to place bombs.") to_chat(character, "Try to keep your BBD and escape this hell hole alive!") - - ticker.mode.latespawn(character) - - if(character.mind.assigned_role != "Cyborg") - data_core.manifest_inject(character) - ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn - AnnounceArrival(character, rank) - FuckUpGenes(character) - else - character.Robotize() - qdel(src) - -/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank) - if (ticker.current_state == GAME_STATE_PLAYING) - if(character.mind.role_alt_title) - rank = character.mind.role_alt_title - var/datum/speech/speech = announcement_intercom.create_speech("[character.real_name],[rank ? " [rank]," : " visitor," ] has arrived on the station.", transmitter=announcement_intercom) - speech.name = "Arrivals Announcement Computer" - speech.job = "Automated Announcement" - speech.as_name = "Arrivals Announcement Computer" - speech.frequency = 1459 - - Broadcast_Message(speech, vmask=null, data=0, compression=0, level=list(0,1)) - returnToPool(speech) - -/mob/new_player/proc/LateChoices() - var/mills = world.time // 1/10 of a second, not real milliseconds but whatever - //var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something - var/mins = (mills % 36000) / 600 - var/hours = mills / 36000 - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:322: var/dat = "
    " - var/dat = {"
    -Round Duration: [round(hours)]h [round(mins)]m
    "} - // END AUTOFIX - if(emergency_shuttle) //In case Nanotrasen decides reposess CentComm's shuttles. - if(emergency_shuttle.direction == 2) //Shuttle is going to centcomm, not recalled - dat += "The station has been evacuated.
    " - if(emergency_shuttle.direction == 1 && emergency_shuttle.timeleft() < 300 && emergency_shuttle.alert == 0) // Emergency shuttle is past the point of no recall - dat += "The station is currently undergoing evacuation procedures.
    " - if(emergency_shuttle.direction == 1 && emergency_shuttle.alert == 1) // Crew transfer initiated - dat += "The station is currently undergoing crew transfer procedures.
    " - - dat += "Choose from the following open positions:
    " - for(var/datum/job/job in job_master.occupations) - if(job && IsJobAvailable(job.title)) - var/active = 0 - // Only players with the job assigned and AFK for less than 10 minutes count as active - for(var/mob/M in player_list) if(M.mind && M.client && M.mind.assigned_role == job.title && M.client.inactivity <= 10 * 60 * 10) - active++ - dat += "[job.title] ([job.current_positions]) (Active: [active])
    " - - dat += "
    " - src << browse(dat, "window=latechoices;size=300x640;can_close=1") - - -/mob/new_player/proc/create_character() - spawning = 1 - close_spawn_windows() - - var/mob/living/carbon/human/new_character = new(loc) - - var/datum/species/chosen_species - if(client.prefs.species) - chosen_species = all_species[client.prefs.species] - if(chosen_species) - if(is_alien_whitelisted(src, client.prefs.species) || !config.usealienwhitelist || !(chosen_species.flags & WHITELISTED) || (client && client.holder && (client.holder.rights & R_ADMIN)) )// Have to recheck admin due to no usr at roundstart. Latejoins are fine though. - new_character.set_species(client.prefs.species) - //if(chosen_species.language) - //new_character.add_language(chosen_species.language) - - var/datum/language/chosen_language - if(client.prefs.language) - chosen_language = all_languages["[client.prefs.language]"] - if(chosen_language) - if(is_alien_whitelisted(src, client.prefs.language) || !config.usealienwhitelist || !(chosen_language.flags & WHITELISTED) ) - new_character.add_language("[client.prefs.language]") - if(ticker.random_players || appearance_isbanned(src)) //disabling ident bans for now - new_character.setGender(pick(MALE, FEMALE)) - client.prefs.real_name = random_name(new_character.gender) - client.prefs.randomize_appearance_for(new_character) - client.prefs.flavor_text = "" - else - client.prefs.copy_to(new_character) - - to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// MAD JAMS cant last forever yo - - if (mind) - mind.active = 0 // we wish to transfer the key manually - mind.original = new_character - mind.transfer_to(new_character) // won't transfer key since the mind is not active - - new_character.name = real_name - new_character.dna.ready_dna(new_character) - new_character.dna.b_type = client.prefs.b_type - - if(client.prefs.disabilities & DISABILITY_FLAG_NEARSIGHTED) - new_character.dna.SetSEState(GLASSESBLOCK,1,1) - new_character.disabilities |= NEARSIGHTED - - chosen_species = all_species[client.prefs.species] - if( (client.prefs.disabilities & DISABILITY_FLAG_FAT) && (chosen_species.flags & CAN_BE_FAT) ) - new_character.mutations += M_FAT - new_character.mutations += M_OBESITY - new_character.overeatduration = 600 - - if(client.prefs.disabilities & DISABILITY_FLAG_EPILEPTIC) - new_character.dna.SetSEState(EPILEPSYBLOCK,1,1) - new_character.disabilities |= EPILEPSY - - if(client.prefs.disabilities & DISABILITY_FLAG_DEAF) - new_character.dna.SetSEState(DEAFBLOCK,1,1) - new_character.sdisabilities |= DEAF - - new_character.dna.UpdateSE() - - new_character.key = key //Manually transfer the key to log them in - - return new_character - -/mob/new_player/proc/ViewManifest() - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:410: var/dat = "" - var/dat = {" -

    Crew Manifest

    "} - // END AUTOFIX - dat += data_core.get_manifest(OOC = 1) - - src << browse(dat, "window=manifest;size=370x420;can_close=1") - -/mob/new_player/Move(NewLoc,Dir=0,step_x=0,step_y=0) - return 0 - - -/mob/new_player/proc/close_spawn_windows() - src << browse(null, "window=latechoices") //closes late choices window - src << browse(null, "window=playersetup") //closes the player setup window - -/mob/new_player/cultify() - return - -/mob/new_player/singuloCanEat() - return 0 + ticker.mode.latespawn(character) + + if(character.mind.assigned_role != "Cyborg") + data_core.manifest_inject(character) + ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn + AnnounceArrival(character, rank) + FuckUpGenes(character) + else + character.Robotize() + qdel(src) + +/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank) + if (ticker.current_state == GAME_STATE_PLAYING) + if(character.mind.role_alt_title) + rank = character.mind.role_alt_title + var/datum/speech/speech = announcement_intercom.create_speech("[character.real_name],[rank ? " [rank]," : " visitor," ] has arrived on the station.", transmitter=announcement_intercom) + speech.name = "Arrivals Announcement Computer" + speech.job = "Automated Announcement" + speech.as_name = "Arrivals Announcement Computer" + speech.frequency = 1459 + + Broadcast_Message(speech, vmask=null, data=0, compression=0, level=list(0,1)) + returnToPool(speech) + +/mob/new_player/proc/LateChoices() + var/mills = world.time // 1/10 of a second, not real milliseconds but whatever + //var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something + var/mins = (mills % 36000) / 600 + var/hours = mills / 36000 + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:322: var/dat = "
    " + var/dat = {"
    +Round Duration: [round(hours)]h [round(mins)]m
    "} + // END AUTOFIX + if(emergency_shuttle) //In case Nanotrasen decides reposess CentComm's shuttles. + if(emergency_shuttle.direction == 2) //Shuttle is going to centcomm, not recalled + dat += "The station has been evacuated.
    " + if(emergency_shuttle.direction == 1 && emergency_shuttle.timeleft() < 300 && emergency_shuttle.alert == 0) // Emergency shuttle is past the point of no recall + dat += "The station is currently undergoing evacuation procedures.
    " + if(emergency_shuttle.direction == 1 && emergency_shuttle.alert == 1) // Crew transfer initiated + dat += "The station is currently undergoing crew transfer procedures.
    " + + dat += "Choose from the following open positions:
    " + for(var/datum/job/job in job_master.occupations) + if(job && IsJobAvailable(job.title)) + var/active = 0 + // Only players with the job assigned and AFK for less than 10 minutes count as active + for(var/mob/M in player_list) if(M.mind && M.client && M.mind.assigned_role == job.title && M.client.inactivity <= 10 * 60 * 10) + active++ + dat += "[job.title] ([job.current_positions]) (Active: [active])
    " + + dat += "
    " + src << browse(dat, "window=latechoices;size=300x640;can_close=1") + + +/mob/new_player/proc/create_character() + spawning = 1 + close_spawn_windows() + + var/mob/living/carbon/human/new_character = new(loc) + + var/datum/species/chosen_species + if(client.prefs.species) + chosen_species = all_species[client.prefs.species] + if(chosen_species) + if(is_alien_whitelisted(src, client.prefs.species) || !config.usealienwhitelist || !(chosen_species.flags & WHITELISTED) || (client && client.holder && (client.holder.rights & R_ADMIN)) )// Have to recheck admin due to no usr at roundstart. Latejoins are fine though. + new_character.set_species(client.prefs.species) + //if(chosen_species.language) + //new_character.add_language(chosen_species.language) + + var/datum/language/chosen_language + if(client.prefs.language) + chosen_language = all_languages["[client.prefs.language]"] + if(chosen_language) + if(is_alien_whitelisted(src, client.prefs.language) || !config.usealienwhitelist || !(chosen_language.flags & WHITELISTED) ) + new_character.add_language("[client.prefs.language]") + if(ticker.random_players || appearance_isbanned(src)) //disabling ident bans for now + new_character.setGender(pick(MALE, FEMALE)) + client.prefs.real_name = random_name(new_character.gender) + client.prefs.randomize_appearance_for(new_character) + client.prefs.flavor_text = "" + else + client.prefs.copy_to(new_character) + + to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// MAD JAMS cant last forever yo + + + if (mind) + mind.active = 0 // we wish to transfer the key manually + mind.original = new_character + mind.transfer_to(new_character) // won't transfer key since the mind is not active + + new_character.name = real_name + new_character.dna.ready_dna(new_character) + new_character.dna.b_type = client.prefs.b_type + + if(client.prefs.disabilities & DISABILITY_FLAG_NEARSIGHTED) + new_character.dna.SetSEState(GLASSESBLOCK,1,1) + new_character.disabilities |= NEARSIGHTED + + chosen_species = all_species[client.prefs.species] + if( (client.prefs.disabilities & DISABILITY_FLAG_FAT) && (chosen_species.flags & CAN_BE_FAT) ) + new_character.mutations += M_FAT + new_character.mutations += M_OBESITY + new_character.overeatduration = 600 + + if(client.prefs.disabilities & DISABILITY_FLAG_EPILEPTIC) + new_character.dna.SetSEState(EPILEPSYBLOCK,1,1) + new_character.disabilities |= EPILEPSY + + if(client.prefs.disabilities & DISABILITY_FLAG_DEAF) + new_character.dna.SetSEState(DEAFBLOCK,1,1) + new_character.sdisabilities |= DEAF + + new_character.dna.UpdateSE() + + new_character.key = key //Manually transfer the key to log them in + + return new_character + +/mob/new_player/proc/ViewManifest() + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\new_player.dm:410: var/dat = "" + var/dat = {" +

    Crew Manifest

    "} + // END AUTOFIX + dat += data_core.get_manifest(OOC = 1) + + src << browse(dat, "window=manifest;size=370x420;can_close=1") + +/mob/new_player/Move(NewLoc,Dir=0,step_x=0,step_y=0) + return 0 + + +/mob/new_player/proc/close_spawn_windows() + src << browse(null, "window=latechoices") //closes late choices window + src << browse(null, "window=playersetup") //closes the player setup window + +/mob/new_player/cultify() + return + +/mob/new_player/singuloCanEat() + return 0 diff --git a/code/modules/mob/new_player/poll.dm b/code/modules/mob/new_player/poll.dm index 7bd73d286c2..aea074ea4cd 100644 --- a/code/modules/mob/new_player/poll.dm +++ b/code/modules/mob/new_player/poll.dm @@ -1,564 +1,564 @@ - -/mob/new_player/proc/handle_privacy_poll() - establish_db_connection() - if(!dbcon.IsConnected()) - return - var/voted = 0 - - var/DBQuery/query = dbcon.NewQuery("SELECT * FROM erro_privacy WHERE ckey='[src.ckey]'") - query.Execute() - while(query.NextRow()) - voted = 1 - break - - if(!voted) - privacy_poll() - -/mob/new_player/proc/privacy_poll() - var/output = "
    Player poll" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:19: output +="
    " - output += {"
    - We would like to expand our stats gathering. -
    This however involves gathering data about player behavior, play styles, unique player numbers, play times, etc. Data like that cannot be gathered fully anonymously, which is why we're asking you how you'd feel if player-specific data was gathered. Prior to any of this actually happening, a privacy policy will be discussed, but before that can begin, we'd preliminarily like to know how you feel about the concept. -
    - How do you feel about the game gathering player-specific statistics? This includes statistics about individual players as well as in-game polling/opinion requests. -

    Signed stats gathering -
    Pick this option if you think usernames should be logged with stats. This allows us to have personalized stats as well as polls. -

    Anonymous stats gathering -
    Pick this option if you think only hashed (indecipherable) usernames should be logged with stats. This doesn't allow us to have personalized stats, as we can't tell who is who (hashed values aren't readable), we can however have ingame polls. -

    No stats gathering -
    Pick this option if you don't want player-specific stats gathered. This does not allow us to have player-specific stats or polls. -

    Ask again later -
    This poll will be brought up again next round. -

    Don't ask again -
    Only pick this if you are fine with whatever option wins. -

    "} - // END AUTOFIX - src << browse(output,"window=privacypoll;size=600x500") - return - -/datum/polloption - var/optionid - var/optiontext - -/mob/new_player/proc/handle_player_polling() - establish_db_connection() - if(dbcon.IsConnected()) - var/isadmin = 0 - if(src.client && src.client.holder) - isadmin = 1 - - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, question FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime") - select_query.Execute() - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:56: var/output = "
    Player polls" - var/output = {"
    Player polls -
    "} - // END AUTOFIX - var/pollid - var/pollquestion - - output += "" - var/color1 = "#ececec" - var/color2 = "#e2e2e2" - var/i = 0 - - while(select_query.NextRow()) - pollid = select_query.item[1] - pollquestion = select_query.item[2] - output += "" - i++ - - output += "
    [pollquestion] | Results
    " - - src << browse(output,"window=playerpolllist;size=500x300") - - - -/mob/new_player/proc/poll_player(var/pollid = -1) - if(pollid == -1) return - establish_db_connection() - if(dbcon.IsConnected()) - - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid]") - select_query.Execute() - - var/pollstarttime = "" - var/pollendtime = "" - var/pollquestion = "" - var/polltype = "" - var/found = 0 - var/multiplechoiceoptions = 0 - - while(select_query.NextRow()) - pollstarttime = select_query.item[1] - pollendtime = select_query.item[2] - pollquestion = select_query.item[3] - polltype = select_query.item[4] - found = 1 - break - - if(!found) + +/mob/new_player/proc/handle_privacy_poll() + establish_db_connection() + if(!dbcon.IsConnected()) + return + var/voted = 0 + + var/DBQuery/query = dbcon.NewQuery("SELECT * FROM erro_privacy WHERE ckey='[src.ckey]'") + query.Execute() + while(query.NextRow()) + voted = 1 + break + + if(!voted) + privacy_poll() + +/mob/new_player/proc/privacy_poll() + var/output = "
    Player poll" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:19: output +="
    " + output += {"
    + We would like to expand our stats gathering. +
    This however involves gathering data about player behavior, play styles, unique player numbers, play times, etc. Data like that cannot be gathered fully anonymously, which is why we're asking you how you'd feel if player-specific data was gathered. Prior to any of this actually happening, a privacy policy will be discussed, but before that can begin, we'd preliminarily like to know how you feel about the concept. +
    + How do you feel about the game gathering player-specific statistics? This includes statistics about individual players as well as in-game polling/opinion requests. +

    Signed stats gathering +
    Pick this option if you think usernames should be logged with stats. This allows us to have personalized stats as well as polls. +

    Anonymous stats gathering +
    Pick this option if you think only hashed (indecipherable) usernames should be logged with stats. This doesn't allow us to have personalized stats, as we can't tell who is who (hashed values aren't readable), we can however have ingame polls. +

    No stats gathering +
    Pick this option if you don't want player-specific stats gathered. This does not allow us to have player-specific stats or polls. +

    Ask again later +
    This poll will be brought up again next round. +

    Don't ask again +
    Only pick this if you are fine with whatever option wins. +

    "} + // END AUTOFIX + src << browse(output,"window=privacypoll;size=600x500") + return + +/datum/polloption + var/optionid + var/optiontext + +/mob/new_player/proc/handle_player_polling() + establish_db_connection() + if(dbcon.IsConnected()) + var/isadmin = 0 + if(src.client && src.client.holder) + isadmin = 1 + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id, question FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime") + select_query.Execute() + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:56: var/output = "
    Player polls" + var/output = {"
    Player polls +
    "} + // END AUTOFIX + var/pollid + var/pollquestion + + output += "" + var/color1 = "#ececec" + var/color2 = "#e2e2e2" + var/i = 0 + + while(select_query.NextRow()) + pollid = select_query.item[1] + pollquestion = select_query.item[2] + output += "" + i++ + + output += "
    [pollquestion] | Results
    " + + src << browse(output,"window=playerpolllist;size=500x300") + + + +/mob/new_player/proc/poll_player(var/pollid = -1) + if(pollid == -1) return + establish_db_connection() + if(dbcon.IsConnected()) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid]") + select_query.Execute() + + var/pollstarttime = "" + var/pollendtime = "" + var/pollquestion = "" + var/polltype = "" + var/found = 0 + var/multiplechoiceoptions = 0 + + while(select_query.NextRow()) + pollstarttime = select_query.item[1] + pollendtime = select_query.item[2] + pollquestion = select_query.item[3] + polltype = select_query.item[4] + found = 1 + break + + if(!found) to_chat(usr, "Poll question details not found.") - return - - switch(polltype) - //Polls that have enumerated options - if("OPTION") - var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") - voted_query.Execute() - - var/voted = 0 - var/votedoptionid = 0 - while(voted_query.NextRow()) - votedoptionid = text2num(voted_query.item[1]) - voted = 1 - break - - var/list/datum/polloption/options = list() - - var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]") - options_query.Execute() - while(options_query.NextRow()) - var/datum/polloption/PO = new() - PO.optionid = text2num(options_query.item[1]) - PO.optiontext = options_query.item[2] - options += PO - - var/output = "
    Player poll" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:133: output +="
    " - output += {"
    - Question: [pollquestion]
    - Poll runs from [pollstarttime] until [pollendtime]

    "} - // END AUTOFIX - if(!voted) //Only make this a form if we have not voted yet - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:138: output += "

    " - output += {" - - - "} - // END AUTOFIX - - output += "
    " - for(var/datum/polloption/O in options) - if(O.optionid && O.optiontext) - if(voted) - if(votedoptionid == O.optionid) - output += "[O.optiontext]
    " - else - output += "[O.optiontext]
    " - else - output += " [O.optiontext]
    " - output += "
    " - - if(!voted) //Only make this a form if we have not voted yet - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:156: output += "

    " - output += {"

    -

    "} - // END AUTOFIX - - output += "
    " - - src << browse(output,"window=playerpoll;size=500x250") - - //Polls with a text input - if("TEXT") - var/DBQuery/voted_query = dbcon.NewQuery("SELECT replytext FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") - voted_query.Execute() - - var/voted = 0 - var/vote_text = "" - while(voted_query.NextRow()) - vote_text = voted_query.item[1] - voted = 1 - break - - - var/output = "
    Player poll" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:177: output +="
    " - output += {"
    - Question: [pollquestion]
    - Feedback gathering runs from [pollstarttime] until [pollendtime]

    "} - // END AUTOFIX - if(!voted) //Only make this a form if we have not voted yet - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:182: output += "

    " - output += {" - - - - Please provide feedback below. You can use any letters of the English alphabet, numbers and the symbols: . , ! ? : ; -
    - -

    -

    -
    - - - - - -
    "} - // END AUTOFIX - else - output += "[vote_text]" - - src << browse(output,"window=playerpoll;size=500x500") - - //Polls with a text input - if("NUMVAL") - var/DBQuery/voted_query = dbcon.NewQuery("SELECT o.text, v.rating FROM erro_poll_option o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[usr.ckey]' AND o.id = v.optionid") - voted_query.Execute() - - var/output = "
    Player poll" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:211: output +="
    " - output += {"
    - Question: [pollquestion]
    - Poll runs from [pollstarttime] until [pollendtime]

    "} - // END AUTOFIX - var/voted = 0 - while(voted_query.NextRow()) - voted = 1 - - var/optiontext = voted_query.item[1] - var/rating = voted_query.item[2] - - output += "
    [optiontext] - [rating]" - - if(!voted) //Only make this a form if we have not voted yet - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:225: output += "

    " - output += {" - - - "} - // END AUTOFIX - var/minid = 999999 - var/maxid = 0 - - var/DBQuery/option_query = dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM erro_poll_option WHERE pollid = [pollid]") - option_query.Execute() - while(option_query.NextRow()) - var/optionid = text2num(option_query.item[1]) - var/optiontext = option_query.item[2] - var/minvalue = text2num(option_query.item[3]) - var/maxvalue = text2num(option_query.item[4]) - var/descmin = option_query.item[5] - var/descmid = option_query.item[6] - var/descmax = option_query.item[7] - - if(optionid < minid) - minid = optionid - if(optionid > maxid) - maxid = optionid - - var/midvalue = round( (maxvalue + minvalue) / 2) - - if(isnull(minvalue) || isnull(maxvalue) || (minvalue == maxvalue)) - continue - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:254: output += "
    [optiontext]: - "} - // END AUTOFIX - for (var/j = minvalue; j <= maxvalue; j++) - if(j == minvalue && descmin) - output += "" - else if (j == midvalue && descmid) - output += "" - else if (j == maxvalue && descmax) - output += "" - else - output += "" - - output += "" - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:268: output += "" - output += {" - -

    -

    "} - // END AUTOFIX - src << browse(output,"window=playerpoll;size=500x500") - if("MULTICHOICE") - var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") - voted_query.Execute() - - var/list/votedfor = list() - var/voted = 0 - while(voted_query.NextRow()) - votedfor.Add(text2num(voted_query.item[1])) - voted = 1 - - var/list/datum/polloption/options = list() - var/maxoptionid = 0 - var/minoptionid = 0 - - var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]") - options_query.Execute() - while(options_query.NextRow()) - var/datum/polloption/PO = new() - PO.optionid = text2num(options_query.item[1]) - PO.optiontext = options_query.item[2] - if(PO.optionid > maxoptionid) - maxoptionid = PO.optionid - if(PO.optionid < minoptionid || !minoptionid) - minoptionid = PO.optionid - options += PO - - - if(select_query.item[5]) - multiplechoiceoptions = text2num(select_query.item[5]) - - var/output = "
    Player poll" - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:306: output +="
    " - output += {"
    - Question: [pollquestion]
    You can select up to [multiplechoiceoptions] options. If you select more, the first [multiplechoiceoptions] will be saved.
    - Poll runs from [pollstarttime] until [pollendtime]

    "} - // END AUTOFIX - if(!voted) //Only make this a form if we have not voted yet - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:311: output += "

    " - output += {" - - - - - "} - // END AUTOFIX - - output += "
    " - for(var/datum/polloption/O in options) - if(O.optionid && O.optiontext) - if(voted) - if(O.optionid in votedfor) - output += "[O.optiontext]
    " - else - output += "[O.optiontext]
    " - else - output += " [O.optiontext]
    " - output += "
    " - - if(!voted) //Only make this a form if we have not voted yet - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:331: output += "

    " - output += {"

    -

    "} - // END AUTOFIX - - output += "
    " - - src << browse(output,"window=playerpoll;size=500x250") - return - -/mob/new_player/proc/vote_on_poll(var/pollid = -1, var/optionid = -1, var/multichoice = 0) - if(pollid == -1 || optionid == -1) - return - - if(!isnum(pollid) || !isnum(optionid)) - return - establish_db_connection() - if(dbcon.IsConnected()) - - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") - select_query.Execute() - - var/validpoll = 0 - var/multiplechoiceoptions = 0 - - while(select_query.NextRow()) - if(select_query.item[4] != "OPTION" && select_query.item[4] != "MULTICHOICE") - return - validpoll = 1 - if(select_query.item[5]) - multiplechoiceoptions = text2num(select_query.item[5]) - break - - if(!validpoll) + return + + switch(polltype) + //Polls that have enumerated options + if("OPTION") + var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") + voted_query.Execute() + + var/voted = 0 + var/votedoptionid = 0 + while(voted_query.NextRow()) + votedoptionid = text2num(voted_query.item[1]) + voted = 1 + break + + var/list/datum/polloption/options = list() + + var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]") + options_query.Execute() + while(options_query.NextRow()) + var/datum/polloption/PO = new() + PO.optionid = text2num(options_query.item[1]) + PO.optiontext = options_query.item[2] + options += PO + + var/output = "
    Player poll" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:133: output +="
    " + output += {"
    + Question: [pollquestion]
    + Poll runs from [pollstarttime] until [pollendtime]

    "} + // END AUTOFIX + if(!voted) //Only make this a form if we have not voted yet + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:138: output += "

    " + output += {" + + + "} + // END AUTOFIX + + output += "
    " + for(var/datum/polloption/O in options) + if(O.optionid && O.optiontext) + if(voted) + if(votedoptionid == O.optionid) + output += "[O.optiontext]
    " + else + output += "[O.optiontext]
    " + else + output += " [O.optiontext]
    " + output += "
    " + + if(!voted) //Only make this a form if we have not voted yet + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:156: output += "

    " + output += {"

    +

    "} + // END AUTOFIX + + output += "
    " + + src << browse(output,"window=playerpoll;size=500x250") + + //Polls with a text input + if("TEXT") + var/DBQuery/voted_query = dbcon.NewQuery("SELECT replytext FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") + voted_query.Execute() + + var/voted = 0 + var/vote_text = "" + while(voted_query.NextRow()) + vote_text = voted_query.item[1] + voted = 1 + break + + + var/output = "
    Player poll" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:177: output +="
    " + output += {"
    + Question: [pollquestion]
    + Feedback gathering runs from [pollstarttime] until [pollendtime]

    "} + // END AUTOFIX + if(!voted) //Only make this a form if we have not voted yet + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:182: output += "

    " + output += {" + + + + Please provide feedback below. You can use any letters of the English alphabet, numbers and the symbols: . , ! ? : ; -
    + +

    +

    +
    + + + + + +
    "} + // END AUTOFIX + else + output += "[vote_text]" + + src << browse(output,"window=playerpoll;size=500x500") + + //Polls with a text input + if("NUMVAL") + var/DBQuery/voted_query = dbcon.NewQuery("SELECT o.text, v.rating FROM erro_poll_option o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[usr.ckey]' AND o.id = v.optionid") + voted_query.Execute() + + var/output = "
    Player poll" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:211: output +="
    " + output += {"
    + Question: [pollquestion]
    + Poll runs from [pollstarttime] until [pollendtime]

    "} + // END AUTOFIX + var/voted = 0 + while(voted_query.NextRow()) + voted = 1 + + var/optiontext = voted_query.item[1] + var/rating = voted_query.item[2] + + output += "
    [optiontext] - [rating]" + + if(!voted) //Only make this a form if we have not voted yet + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:225: output += "

    " + output += {" + + + "} + // END AUTOFIX + var/minid = 999999 + var/maxid = 0 + + var/DBQuery/option_query = dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM erro_poll_option WHERE pollid = [pollid]") + option_query.Execute() + while(option_query.NextRow()) + var/optionid = text2num(option_query.item[1]) + var/optiontext = option_query.item[2] + var/minvalue = text2num(option_query.item[3]) + var/maxvalue = text2num(option_query.item[4]) + var/descmin = option_query.item[5] + var/descmid = option_query.item[6] + var/descmax = option_query.item[7] + + if(optionid < minid) + minid = optionid + if(optionid > maxid) + maxid = optionid + + var/midvalue = round( (maxvalue + minvalue) / 2) + + if(isnull(minvalue) || isnull(maxvalue) || (minvalue == maxvalue)) + continue + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:254: output += "
    [optiontext]: + "} + // END AUTOFIX + for (var/j = minvalue; j <= maxvalue; j++) + if(j == minvalue && descmin) + output += "" + else if (j == midvalue && descmid) + output += "" + else if (j == maxvalue && descmax) + output += "" + else + output += "" + + output += "" + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:268: output += "" + output += {" + +

    +

    "} + // END AUTOFIX + src << browse(output,"window=playerpoll;size=500x500") + if("MULTICHOICE") + var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") + voted_query.Execute() + + var/list/votedfor = list() + var/voted = 0 + while(voted_query.NextRow()) + votedfor.Add(text2num(voted_query.item[1])) + voted = 1 + + var/list/datum/polloption/options = list() + var/maxoptionid = 0 + var/minoptionid = 0 + + var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]") + options_query.Execute() + while(options_query.NextRow()) + var/datum/polloption/PO = new() + PO.optionid = text2num(options_query.item[1]) + PO.optiontext = options_query.item[2] + if(PO.optionid > maxoptionid) + maxoptionid = PO.optionid + if(PO.optionid < minoptionid || !minoptionid) + minoptionid = PO.optionid + options += PO + + + if(select_query.item[5]) + multiplechoiceoptions = text2num(select_query.item[5]) + + var/output = "
    Player poll" + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:306: output +="
    " + output += {"
    + Question: [pollquestion]
    You can select up to [multiplechoiceoptions] options. If you select more, the first [multiplechoiceoptions] will be saved.
    + Poll runs from [pollstarttime] until [pollendtime]

    "} + // END AUTOFIX + if(!voted) //Only make this a form if we have not voted yet + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:311: output += "

    " + output += {" + + + + + "} + // END AUTOFIX + + output += "
    " + for(var/datum/polloption/O in options) + if(O.optionid && O.optiontext) + if(voted) + if(O.optionid in votedfor) + output += "[O.optiontext]
    " + else + output += "[O.optiontext]
    " + else + output += " [O.optiontext]
    " + output += "
    " + + if(!voted) //Only make this a form if we have not voted yet + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\mob\new_player\\\poll.dm:331: output += "

    " + output += {"

    +

    "} + // END AUTOFIX + + output += "
    " + + src << browse(output,"window=playerpoll;size=500x250") + return + +/mob/new_player/proc/vote_on_poll(var/pollid = -1, var/optionid = -1, var/multichoice = 0) + if(pollid == -1 || optionid == -1) + return + + if(!isnum(pollid) || !isnum(optionid)) + return + establish_db_connection() + if(dbcon.IsConnected()) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") + select_query.Execute() + + var/validpoll = 0 + var/multiplechoiceoptions = 0 + + while(select_query.NextRow()) + if(select_query.item[4] != "OPTION" && select_query.item[4] != "MULTICHOICE") + return + validpoll = 1 + if(select_query.item[5]) + multiplechoiceoptions = text2num(select_query.item[5]) + break + + if(!validpoll) to_chat(usr, "Poll is not valid.") - return - - var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]") - select_query2.Execute() - - var/validoption = 0 - - while(select_query2.NextRow()) - validoption = 1 - break - - if(!validoption) + return + + var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]") + select_query2.Execute() + + var/validoption = 0 + + while(select_query2.NextRow()) + validoption = 1 + break + + if(!validoption) to_chat(usr, "Poll option is not valid.") - return - - var/alreadyvoted = 0 - - var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") - voted_query.Execute() - - while(voted_query.NextRow()) - alreadyvoted += 1 - if(!multichoice) - break - - if(!multichoice && alreadyvoted) + return + + var/alreadyvoted = 0 + + var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") + voted_query.Execute() + + while(voted_query.NextRow()) + alreadyvoted += 1 + if(!multichoice) + break + + if(!multichoice && alreadyvoted) to_chat(usr, "You already voted in this poll.") - return - - if(multichoice && (alreadyvoted >= multiplechoiceoptions)) + return + + if(multichoice && (alreadyvoted >= multiplechoiceoptions)) to_chat(usr, "You already have more than [multiplechoiceoptions] logged votes on this poll. Enough is enough. Contact the database admin if this is an error.") - return - - var/adminrank = "Player" - if(usr && usr.client && usr.client.holder) - adminrank = usr.client.holder.rank - - - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]')") - insert_query.Execute() - + return + + var/adminrank = "Player" + if(usr && usr.client && usr.client.holder) + adminrank = usr.client.holder.rank + + + var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]')") + insert_query.Execute() + to_chat(usr, "Vote successful.") - usr << browse(null,"window=playerpoll") - - -/mob/new_player/proc/log_text_poll_reply(var/pollid = -1, var/replytext = "") - if(pollid == -1 || replytext == "") - return - - if(!isnum(pollid) || !istext(replytext)) - return - establish_db_connection() - if(dbcon.IsConnected()) - - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") - select_query.Execute() - - var/validpoll = 0 - - while(select_query.NextRow()) - if(select_query.item[4] != "TEXT") - return - validpoll = 1 - break - - if(!validpoll) + usr << browse(null,"window=playerpoll") + + +/mob/new_player/proc/log_text_poll_reply(var/pollid = -1, var/replytext = "") + if(pollid == -1 || replytext == "") + return + + if(!isnum(pollid) || !istext(replytext)) + return + establish_db_connection() + if(dbcon.IsConnected()) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") + select_query.Execute() + + var/validpoll = 0 + + while(select_query.NextRow()) + if(select_query.item[4] != "TEXT") + return + validpoll = 1 + break + + if(!validpoll) to_chat(usr, "Poll is not valid.") - return - - var/alreadyvoted = 0 - - var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") - voted_query.Execute() - - while(voted_query.NextRow()) - alreadyvoted = 1 - break - - if(alreadyvoted) + return + + var/alreadyvoted = 0 + + var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'") + voted_query.Execute() + + while(voted_query.NextRow()) + alreadyvoted = 1 + break + + if(alreadyvoted) to_chat(usr, "You already sent your feedback for this poll.") - return - - var/adminrank = "Player" - if(usr && usr.client && usr.client.holder) - adminrank = usr.client.holder.rank - - - replytext = replacetext(replytext, "%BR%", "") - replytext = replacetext(replytext, "\n", "%BR%") - var/text_pass = reject_bad_text(replytext,8000) - replytext = replacetext(replytext, "%BR%", "
    ") - - if(!text_pass) + return + + var/adminrank = "Player" + if(usr && usr.client && usr.client.holder) + adminrank = usr.client.holder.rank + + + replytext = replacetext(replytext, "%BR%", "") + replytext = replacetext(replytext, "\n", "%BR%") + var/text_pass = reject_bad_text(replytext,8000) + replytext = replacetext(replytext, "%BR%", "
    ") + + if(!text_pass) to_chat(usr, "The text you entered was blank, contained illegal characters or was too long. Please correct the text and submit again.") - return - - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_textreply (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[usr.ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')") - insert_query.Execute() - + return + + var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_textreply (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[usr.ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')") + insert_query.Execute() + to_chat(usr, "Feedback logging successful.") - usr << browse(null,"window=playerpoll") - - -/mob/new_player/proc/vote_on_numval_poll(var/pollid = -1, var/optionid = -1, var/rating = null) - if(pollid == -1 || optionid == -1) - return - - if(!isnum(pollid) || !isnum(optionid)) - return - establish_db_connection() - if(dbcon.IsConnected()) - - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") - select_query.Execute() - - var/validpoll = 0 - - while(select_query.NextRow()) - if(select_query.item[4] != "NUMVAL") - return - validpoll = 1 - break - - if(!validpoll) + usr << browse(null,"window=playerpoll") + + +/mob/new_player/proc/vote_on_numval_poll(var/pollid = -1, var/optionid = -1, var/rating = null) + if(pollid == -1 || optionid == -1) + return + + if(!isnum(pollid) || !isnum(optionid)) + return + establish_db_connection() + if(dbcon.IsConnected()) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") + select_query.Execute() + + var/validpoll = 0 + + while(select_query.NextRow()) + if(select_query.item[4] != "NUMVAL") + return + validpoll = 1 + break + + if(!validpoll) to_chat(usr, "Poll is not valid.") - return - - var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]") - select_query2.Execute() - - var/validoption = 0 - - while(select_query2.NextRow()) - validoption = 1 - break - - if(!validoption) + return + + var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]") + select_query2.Execute() + + var/validoption = 0 + + while(select_query2.NextRow()) + validoption = 1 + break + + if(!validoption) to_chat(usr, "Poll option is not valid.") - return - - var/alreadyvoted = 0 - - var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_vote WHERE optionid = [optionid] AND ckey = '[usr.ckey]'") - voted_query.Execute() - - while(voted_query.NextRow()) - alreadyvoted = 1 - break - - if(alreadyvoted) + return + + var/alreadyvoted = 0 + + var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_vote WHERE optionid = [optionid] AND ckey = '[usr.ckey]'") + voted_query.Execute() + + while(voted_query.NextRow()) + alreadyvoted = 1 + break + + if(alreadyvoted) to_chat(usr, "You already voted in this poll.") - return - - var/adminrank = "Player" - if(usr && usr.client && usr.client.holder) - adminrank = usr.client.holder.rank - - - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])") - insert_query.Execute() - + return + + var/adminrank = "Player" + if(usr && usr.client && usr.client.holder) + adminrank = usr.client.holder.rank + + + var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])") + insert_query.Execute() + to_chat(usr, "Vote successful.") usr << browse(null,"window=playerpoll") \ No newline at end of file diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 1577eb73c0d..5be5931ef71 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -1,436 +1,436 @@ -datum/preferences - //The mob should have a gender you want before running this proc. Will run fine without H - proc/randomize_appearance_for(var/mob/living/carbon/human/H) - if(H) - if(H.gender == MALE) - gender = MALE - else - gender = FEMALE - s_tone = random_skin_tone() - h_style = random_hair_style(gender, species) - f_style = random_facial_hair_style(gender, species) - randomize_hair_color("hair") - randomize_hair_color("facial") - randomize_eyes_color() - underwear = rand(1,underwear_m.len) - backbag = 2 - age = rand(AGE_MIN,AGE_MAX) - if(H) - copy_to(H,1) - - - proc/randomize_hair_color(var/target = "hair") - if(prob (75) && target == "facial") // Chance to inherit hair color - r_facial = r_hair - g_facial = g_hair - b_facial = b_hair - return - - var/red - var/green - var/blue - - var/col = pick ("blonde", "black", "chestnut", "copper", "brown", "wheat", "old", "punk") - switch(col) - if("blonde") - red = 255 - green = 255 - blue = 0 - if("black") - red = 0 - green = 0 - blue = 0 - if("chestnut") - red = 153 - green = 102 - blue = 51 - if("copper") - red = 255 - green = 153 - blue = 0 - if("brown") - red = 102 - green = 51 - blue = 0 - if("wheat") - red = 255 - green = 255 - blue = 153 - if("old") - red = rand (100, 255) - green = red - blue = red - if("punk") - red = rand (0, 255) - green = rand (0, 255) - blue = rand (0, 255) - - red = max(min(red + rand (-25, 25), 255), 0) - green = max(min(green + rand (-25, 25), 255), 0) - blue = max(min(blue + rand (-25, 25), 255), 0) - - switch(target) - if("hair") - r_hair = red - g_hair = green - b_hair = blue - if("facial") - r_facial = red - g_facial = green - b_facial = blue - - proc/randomize_eyes_color() - var/red - var/green - var/blue - - var/col = pick ("black", "grey", "brown", "chestnut", "blue", "lightblue", "green", "albino") - switch(col) - if("black") - red = 0 - green = 0 - blue = 0 - if("grey") - red = rand (100, 200) - green = red - blue = red - if("brown") - red = 102 - green = 51 - blue = 0 - if("chestnut") - red = 153 - green = 102 - blue = 0 - if("blue") - red = 51 - green = 102 - blue = 204 - if("lightblue") - red = 102 - green = 204 - blue = 255 - if("green") - red = 0 - green = 102 - blue = 0 - if("albino") - red = rand (200, 255) - green = rand (0, 150) - blue = rand (0, 150) - - red = max(min(red + rand (-25, 25), 255), 0) - green = max(min(green + rand (-25, 25), 255), 0) - blue = max(min(blue + rand (-25, 25), 255), 0) - - r_eyes = red - g_eyes = green - b_eyes = blue - - proc/blend_backpack(var/icon/clothes_s,var/backbag,var/satchel,var/backpack="backpack") - switch(backbag) - if(2) - clothes_s.Blend(new /icon('icons/mob/back.dmi', backpack), ICON_OVERLAY) - if(3) - clothes_s.Blend(new /icon('icons/mob/back.dmi', satchel), ICON_OVERLAY) - if(4) - clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) - return clothes_s - - - proc/update_preview_icon(var/for_observer=0) //seriously. This is horrendous. - preview_icon_front = null - preview_icon_side = null - preview_icon = null - - var/g = "m" - if(gender == FEMALE) g = "f" - - var/icon/icobase - var/datum/species/current_species = all_species[species] - - if(current_species) - icobase = current_species.icobase - else - icobase = 'icons/mob/human_races/r_human.dmi' - - var/fat="" - if(disabilities&DISABILITY_FLAG_FAT && current_species.flags & CAN_BE_FAT) - fat="_fat" - preview_icon = new /icon(icobase, "torso_[g][fat]") - preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) - preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY) - - for(var/name in list("l_arm","r_arm","l_leg","r_leg","l_foot","r_foot","l_hand","r_hand")) - // make sure the organ is added to the list so it's drawn - if(organ_data[name] == null) - organ_data[name] = null - - for(var/name in organ_data) - if(organ_data[name] == "amputated") continue - - var/o_icobase=icobase - if(organ_data[name] == "peg") - o_icobase='icons/mob/human_races/o_peg.dmi' - else if(organ_data[name] == "cyborg") - o_icobase='icons/mob/human_races/o_robot.dmi' - - var/icon/temp = new /icon(o_icobase, "[name]") - - preview_icon.Blend(temp, ICON_OVERLAY) - - // Skin tone - if(current_species && (current_species.flags & HAS_SKIN_TONE)) - if (s_tone >= 0) - preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) - else - preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) - - var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = current_species ? current_species.eyes : "eyes_s") - eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) - - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if(hair_style) - var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) - eyes_s.Blend(hair_s, ICON_OVERLAY) - - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style) - var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") - facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) - eyes_s.Blend(facial_s, ICON_OVERLAY) - - var/icon/clothes_s = null - - var/uniform_dmi - var/feet_dmi - // UNIFORM DMI - if(current_species) - uniform_dmi=current_species.uniform_icons - if(disabilities&DISABILITY_FLAG_FAT && current_species.fat_uniform_icons) - uniform_dmi=current_species.fat_uniform_icons - - // SHOES DMI - feet_dmi=current_species.shoes_icons - - if(!for_observer) - // Commenting this check so that, if all else fails, the preview icon is never naked. - N3X - //if(job_civilian_low & ASSISTANT) //This gives the preview icon clothes depending on which job(if any) is set to 'high' - clothes_s = new /icon(uniform_dmi, "grey_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - - //else - if(job_civilian_high)//I hate how this looks, but there's no reason to go through this switch if it's empty - switch(job_civilian_high) - if(HOP) - clothes_s = new /icon(uniform_dmi, "hop_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(BARTENDER) - clothes_s = new /icon(uniform_dmi, "ba_suit_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(BOTANIST) - clothes_s = new /icon(uniform_dmi, "hydroponics_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "ggloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "apron"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-hyd") - if(CHEF) - clothes_s = new /icon(uniform_dmi, "chef_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "chef"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(JANITOR) - clothes_s = new /icon(uniform_dmi, "janitor_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(LIBRARIAN) - clothes_s = new /icon(uniform_dmi, "red_suit_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(QUARTERMASTER) - clothes_s = new /icon(uniform_dmi, "qm_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/eyes.dmi', "sun"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "clipboard"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(CARGOTECH) - clothes_s = new /icon(uniform_dmi, "cargotech_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(MINER) - clothes_s = new /icon(uniform_dmi, "miner_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-eng") - if(LAWYER) - clothes_s = new /icon(uniform_dmi, "internalaffairs_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "briefcase"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(CHAPLAIN) - clothes_s = new /icon(uniform_dmi, "chapblack_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(CLOWN) - clothes_s = new /icon(uniform_dmi, "clown_s") - clothes_s.Blend(new /icon(feet_dmi, "clown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/mask.dmi', "clown"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/back.dmi', "clownpack"), ICON_OVERLAY) - if(MIME) - clothes_s = new /icon(uniform_dmi, "mime_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "lgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/mask.dmi', "mime"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "beret"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "suspenders"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - - else if(job_medsci_high) - switch(job_medsci_high) - if(RD) - clothes_s = new /icon(uniform_dmi, "director_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "clipboard"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-tox") - if(SCIENTIST) - clothes_s = new /icon(uniform_dmi, "toxinswhite_s") - clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-tox") - if(CHEMIST) - clothes_s = new /icon(uniform_dmi, "chemistrywhite_s") - clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-chem") - if(CMO) - clothes_s = new /icon(uniform_dmi, "cmo_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/left/items_lefthand.dmi', "firstaid"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-med") - if(DOCTOR) - clothes_s = new /icon(uniform_dmi, "medical_s") - clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/left/items_lefthand.dmi', "firstaid"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-med","medicalpack") - if(GENETICIST) - clothes_s = new /icon(uniform_dmi, "geneticswhite_s") - clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-gen") - if(VIROLOGIST) - clothes_s = new /icon(uniform_dmi, "virologywhite_s") - clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/mask.dmi', "sterile"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-vir","medicalpack") - if(ROBOTICIST) - clothes_s = new /icon(uniform_dmi, "robotics_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "toolbox_blue"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - - else if(job_engsec_high) - switch(job_engsec_high) - if(CAPTAIN) - clothes_s = new /icon(uniform_dmi, "captain_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "captain"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/eyes.dmi', "sun"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "caparmor"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-cap") - if(HOS) - clothes_s = new /icon(uniform_dmi, "hosred_s") - clothes_s.Blend(new /icon(feet_dmi, "jackboots"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-sec","securitypack") - if(WARDEN) - clothes_s = new /icon(uniform_dmi, "warden_s") - clothes_s.Blend(new /icon(feet_dmi, "jackboots"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-sec","securitypack") - if(DETECTIVE) - clothes_s = new /icon(uniform_dmi, "detective_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "detective"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(OFFICER) - clothes_s = new /icon(uniform_dmi, "secred_s") - clothes_s.Blend(new /icon(feet_dmi, "jackboots"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-sec","securitypack") - if(CHIEF) - clothes_s = new /icon(uniform_dmi, "chief_s") - clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "hardhat0_white"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-eng","engiepack") - if(ENGINEER) - clothes_s = new /icon(uniform_dmi, "engine_s") - clothes_s.Blend(new /icon(feet_dmi, "orange"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "hardhat0_yellow"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-eng","engiepack") - if(ATMOSTECH) - clothes_s = new /icon(uniform_dmi, "atmos_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(ROBOTICIST) - clothes_s = new /icon(uniform_dmi, "robotics_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) - clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "toolbox_blue"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(AI)//Gives AI and borgs assistant-wear, so they can still customize their character - clothes_s = new /icon(uniform_dmi, "grey_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - if(CYBORG) - clothes_s = new /icon(uniform_dmi, "grey_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - - // Observers get tourist outfit. - else - clothes_s = new /icon(uniform_dmi, "tourist_s") - clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) - clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") - - if(disabilities & NEARSIGHTED) - preview_icon.Blend(new /icon('icons/mob/eyes.dmi', "glasses"), ICON_OVERLAY) - - preview_icon.Blend(eyes_s, ICON_OVERLAY) - if(clothes_s) - preview_icon.Blend(clothes_s, ICON_OVERLAY) - preview_icon_front = new(preview_icon, dir = SOUTH) - preview_icon_side = new(preview_icon, dir = WEST) - - eyes_s = null +datum/preferences + //The mob should have a gender you want before running this proc. Will run fine without H + proc/randomize_appearance_for(var/mob/living/carbon/human/H) + if(H) + if(H.gender == MALE) + gender = MALE + else + gender = FEMALE + s_tone = random_skin_tone() + h_style = random_hair_style(gender, species) + f_style = random_facial_hair_style(gender, species) + randomize_hair_color("hair") + randomize_hair_color("facial") + randomize_eyes_color() + underwear = rand(1,underwear_m.len) + backbag = 2 + age = rand(AGE_MIN,AGE_MAX) + if(H) + copy_to(H,1) + + + proc/randomize_hair_color(var/target = "hair") + if(prob (75) && target == "facial") // Chance to inherit hair color + r_facial = r_hair + g_facial = g_hair + b_facial = b_hair + return + + var/red + var/green + var/blue + + var/col = pick ("blonde", "black", "chestnut", "copper", "brown", "wheat", "old", "punk") + switch(col) + if("blonde") + red = 255 + green = 255 + blue = 0 + if("black") + red = 0 + green = 0 + blue = 0 + if("chestnut") + red = 153 + green = 102 + blue = 51 + if("copper") + red = 255 + green = 153 + blue = 0 + if("brown") + red = 102 + green = 51 + blue = 0 + if("wheat") + red = 255 + green = 255 + blue = 153 + if("old") + red = rand (100, 255) + green = red + blue = red + if("punk") + red = rand (0, 255) + green = rand (0, 255) + blue = rand (0, 255) + + red = max(min(red + rand (-25, 25), 255), 0) + green = max(min(green + rand (-25, 25), 255), 0) + blue = max(min(blue + rand (-25, 25), 255), 0) + + switch(target) + if("hair") + r_hair = red + g_hair = green + b_hair = blue + if("facial") + r_facial = red + g_facial = green + b_facial = blue + + proc/randomize_eyes_color() + var/red + var/green + var/blue + + var/col = pick ("black", "grey", "brown", "chestnut", "blue", "lightblue", "green", "albino") + switch(col) + if("black") + red = 0 + green = 0 + blue = 0 + if("grey") + red = rand (100, 200) + green = red + blue = red + if("brown") + red = 102 + green = 51 + blue = 0 + if("chestnut") + red = 153 + green = 102 + blue = 0 + if("blue") + red = 51 + green = 102 + blue = 204 + if("lightblue") + red = 102 + green = 204 + blue = 255 + if("green") + red = 0 + green = 102 + blue = 0 + if("albino") + red = rand (200, 255) + green = rand (0, 150) + blue = rand (0, 150) + + red = max(min(red + rand (-25, 25), 255), 0) + green = max(min(green + rand (-25, 25), 255), 0) + blue = max(min(blue + rand (-25, 25), 255), 0) + + r_eyes = red + g_eyes = green + b_eyes = blue + + proc/blend_backpack(var/icon/clothes_s,var/backbag,var/satchel,var/backpack="backpack") + switch(backbag) + if(2) + clothes_s.Blend(new /icon('icons/mob/back.dmi', backpack), ICON_OVERLAY) + if(3) + clothes_s.Blend(new /icon('icons/mob/back.dmi', satchel), ICON_OVERLAY) + if(4) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) + return clothes_s + + + proc/update_preview_icon(var/for_observer=0) //seriously. This is horrendous. + preview_icon_front = null + preview_icon_side = null + preview_icon = null + + var/g = "m" + if(gender == FEMALE) g = "f" + + var/icon/icobase + var/datum/species/current_species = all_species[species] + + if(current_species) + icobase = current_species.icobase + else + icobase = 'icons/mob/human_races/r_human.dmi' + + var/fat="" + if(disabilities&DISABILITY_FLAG_FAT && current_species.flags & CAN_BE_FAT) + fat="_fat" + preview_icon = new /icon(icobase, "torso_[g][fat]") + preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) + preview_icon.Blend(new /icon(icobase, "head_[g]"), ICON_OVERLAY) + + for(var/name in list("l_arm","r_arm","l_leg","r_leg","l_foot","r_foot","l_hand","r_hand")) + // make sure the organ is added to the list so it's drawn + if(organ_data[name] == null) + organ_data[name] = null + + for(var/name in organ_data) + if(organ_data[name] == "amputated") continue + + var/o_icobase=icobase + if(organ_data[name] == "peg") + o_icobase='icons/mob/human_races/o_peg.dmi' + else if(organ_data[name] == "cyborg") + o_icobase='icons/mob/human_races/o_robot.dmi' + + var/icon/temp = new /icon(o_icobase, "[name]") + + preview_icon.Blend(temp, ICON_OVERLAY) + + // Skin tone + if(current_species && (current_species.flags & HAS_SKIN_TONE)) + if (s_tone >= 0) + preview_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + preview_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = current_species ? current_species.eyes : "eyes_s") + eyes_s.Blend(rgb(r_eyes, g_eyes, b_eyes), ICON_ADD) + + var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(hair_style) + var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + eyes_s.Blend(hair_s, ICON_OVERLAY) + + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(facial_hair_style) + var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") + facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) + eyes_s.Blend(facial_s, ICON_OVERLAY) + + var/icon/clothes_s = null + + var/uniform_dmi + var/feet_dmi + // UNIFORM DMI + if(current_species) + uniform_dmi=current_species.uniform_icons + if(disabilities&DISABILITY_FLAG_FAT && current_species.fat_uniform_icons) + uniform_dmi=current_species.fat_uniform_icons + + // SHOES DMI + feet_dmi=current_species.shoes_icons + + if(!for_observer) + // Commenting this check so that, if all else fails, the preview icon is never naked. - N3X + //if(job_civilian_low & ASSISTANT) //This gives the preview icon clothes depending on which job(if any) is set to 'high' + clothes_s = new /icon(uniform_dmi, "grey_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + + //else + if(job_civilian_high)//I hate how this looks, but there's no reason to go through this switch if it's empty + switch(job_civilian_high) + if(HOP) + clothes_s = new /icon(uniform_dmi, "hop_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(BARTENDER) + clothes_s = new /icon(uniform_dmi, "ba_suit_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(BOTANIST) + clothes_s = new /icon(uniform_dmi, "hydroponics_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "ggloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "apron"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-hyd") + if(CHEF) + clothes_s = new /icon(uniform_dmi, "chef_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "chef"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(JANITOR) + clothes_s = new /icon(uniform_dmi, "janitor_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(LIBRARIAN) + clothes_s = new /icon(uniform_dmi, "red_suit_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(QUARTERMASTER) + clothes_s = new /icon(uniform_dmi, "qm_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/eyes.dmi', "sun"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "clipboard"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(CARGOTECH) + clothes_s = new /icon(uniform_dmi, "cargotech_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(MINER) + clothes_s = new /icon(uniform_dmi, "miner_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-eng") + if(LAWYER) + clothes_s = new /icon(uniform_dmi, "internalaffairs_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "briefcase"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(CHAPLAIN) + clothes_s = new /icon(uniform_dmi, "chapblack_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(CLOWN) + clothes_s = new /icon(uniform_dmi, "clown_s") + clothes_s.Blend(new /icon(feet_dmi, "clown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "clown"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/back.dmi', "clownpack"), ICON_OVERLAY) + if(MIME) + clothes_s = new /icon(uniform_dmi, "mime_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "lgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "mime"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "beret"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "suspenders"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + + else if(job_medsci_high) + switch(job_medsci_high) + if(RD) + clothes_s = new /icon(uniform_dmi, "director_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "clipboard"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-tox") + if(SCIENTIST) + clothes_s = new /icon(uniform_dmi, "toxinswhite_s") + clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-tox") + if(CHEMIST) + clothes_s = new /icon(uniform_dmi, "chemistrywhite_s") + clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-chem") + if(CMO) + clothes_s = new /icon(uniform_dmi, "cmo_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/left/items_lefthand.dmi', "firstaid"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-med") + if(DOCTOR) + clothes_s = new /icon(uniform_dmi, "medical_s") + clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/left/items_lefthand.dmi', "firstaid"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-med","medicalpack") + if(GENETICIST) + clothes_s = new /icon(uniform_dmi, "geneticswhite_s") + clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-gen") + if(VIROLOGIST) + clothes_s = new /icon(uniform_dmi, "virologywhite_s") + clothes_s.Blend(new /icon(feet_dmi, "white"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "sterile"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-vir","medicalpack") + if(ROBOTICIST) + clothes_s = new /icon(uniform_dmi, "robotics_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "toolbox_blue"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + + else if(job_engsec_high) + switch(job_engsec_high) + if(CAPTAIN) + clothes_s = new /icon(uniform_dmi, "captain_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "captain"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/eyes.dmi', "sun"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "caparmor"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-cap") + if(HOS) + clothes_s = new /icon(uniform_dmi, "hosred_s") + clothes_s.Blend(new /icon(feet_dmi, "jackboots"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-sec","securitypack") + if(WARDEN) + clothes_s = new /icon(uniform_dmi, "warden_s") + clothes_s.Blend(new /icon(feet_dmi, "jackboots"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-sec","securitypack") + if(DETECTIVE) + clothes_s = new /icon(uniform_dmi, "detective_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "detective"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(OFFICER) + clothes_s = new /icon(uniform_dmi, "secred_s") + clothes_s.Blend(new /icon(feet_dmi, "jackboots"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "armor"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-sec","securitypack") + if(CHIEF) + clothes_s = new /icon(uniform_dmi, "chief_s") + clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/mask.dmi', "cigaron"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hardhat0_white"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-eng","engiepack") + if(ENGINEER) + clothes_s = new /icon(uniform_dmi, "engine_s") + clothes_s.Blend(new /icon(feet_dmi, "orange"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hardhat0_yellow"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-eng","engiepack") + if(ATMOSTECH) + clothes_s = new /icon(uniform_dmi, "atmos_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(ROBOTICIST) + clothes_s = new /icon(uniform_dmi, "robotics_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/hands.dmi', "bgloves"), ICON_UNDERLAY) + clothes_s.Blend(new /icon('icons/mob/in-hand/right/items_righthand.dmi', "toolbox_blue"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(AI)//Gives AI and borgs assistant-wear, so they can still customize their character + clothes_s = new /icon(uniform_dmi, "grey_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + if(CYBORG) + clothes_s = new /icon(uniform_dmi, "grey_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + + // Observers get tourist outfit. + else + clothes_s = new /icon(uniform_dmi, "tourist_s") + clothes_s.Blend(new /icon(feet_dmi, "black"), ICON_UNDERLAY) + clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm") + + if(disabilities & NEARSIGHTED) + preview_icon.Blend(new /icon('icons/mob/eyes.dmi', "glasses"), ICON_OVERLAY) + + preview_icon.Blend(eyes_s, ICON_OVERLAY) + if(clothes_s) + preview_icon.Blend(clothes_s, ICON_OVERLAY) + preview_icon_front = new(preview_icon, dir = SOUTH) + preview_icon_side = new(preview_icon, dir = WEST) + + eyes_s = null clothes_s = null \ No newline at end of file diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index f30573b6e91..66272139984 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -1,848 +1,848 @@ -/* - - Hello and welcome to sprite_accessories: For sprite accessories, such as hair, - facial hair, and possibly tattoos and stuff somewhere along the line. This file is - intended to be friendly for people with little to no actual coding experience. - The process of adding in new hairstyles has been made pain-free and easy to do. - Enjoy! - Doohl - - - Notice: This all gets automatically compiled in a list in dna2.dm, so you do not - have to define any UI values for sprite accessories manually for hair and facial - hair. Just add in new hair types and the game will naturally adapt. - - !!WARNING!!: changing existing hair information can be VERY hazardous to savefiles, - to the point where you may completely corrupt a server's savefiles. Please refrain - from doing this unless you absolutely know what you are doing, and have defined a - conversion in savefile.dm -*/ - -/datum/sprite_accessory - - var/icon // the icon file the accessory is located in - var/icon_state // the icon_state of the accessory - var/preview_state // a custom preview state for whatever reason - - var/name // the preview name of the accessory - - // Determines if the accessory will be skipped or included in random hair generations - var/gender = NEUTER - - // Restrict some styles to specific species - var/list/species_allowed = list("Human") - - // Whether or not the accessory can be affected by colouration - var/do_colouration = 1 - - // If the hair-style has parts that aren't affected by colouration (stored on a second sprite) - var/additional_accessories = 0 - - var/flags = 0 - - -/* -//////////////////////////// -/ =--------------------= / -/ == Hair Definitions == / -/ =--------------------= / -//////////////////////////// -*/ - -/datum/sprite_accessory/hair - - icon = 'icons/mob/human_face.dmi' // default icon for all hairs - - bald - name = "Bald" - icon_state = "bald" - gender = MALE - species_allowed = list("Human","Unathi","Grey","Plasmaman","Skellington") - - short - name = "Short Hair" // try to capatilize the names please~ - icon_state = "hair_a" // you do not need to define _s or _l sub-states, game automatically does this for you - - cut - name = "Cut Hair" - icon_state = "hair_c" - - long - name = "Shoulder-length Hair" - icon_state = "hair_b" - - longalt - name = "Shoulder-length Hair Alt" - icon_state = "hair_longfringe" - - /*longish - name = "Longer Hair" - icon_state = "hair_b2"*/ - - longer - name = "Long Hair" - icon_state = "hair_vlong" - - longeralt - name = "Long Hair Alt" - icon_state = "hair_vlongfringe" - - longest - name = "Very Long Hair" - icon_state = "hair_longest" - - longfringe - name = "Long Fringe" - icon_state = "hair_longfringe" - - longestalt - name = "Longer Fringe" - icon_state = "hair_vlongfringe" - - halfbang - name = "Half-banged Hair" - icon_state = "hair_halfbang" - - halfbangalt - name = "Half-banged Hair Alt" - icon_state = "hair_halfbang_alt" - - ponytail1 - name = "Ponytail 1" - icon_state = "hair_ponytail" - - ponytail2 - name = "Ponytail 2" - icon_state = "hair_pa" - gender = FEMALE - - ponytail3 - name = "Ponytail 3" - icon_state = "hair_ponytail3" - - parted - name = "Parted" - icon_state = "hair_parted" - - pompadour - name = "Pompadour" - icon_state = "hair_pompadour" - gender = MALE - species_allowed = list("Human","Unathi") - - quiff - name = "Quiff" - icon_state = "hair_quiff" - gender = MALE - - bedhead - name = "Bedhead" - icon_state = "hair_bedhead" - - bedhead2 - name = "Bedhead 2" - icon_state = "hair_bedheadv2" - - bedhead3 - name = "Bedhead 3" - icon_state = "hair_bedheadv3" - - beehive - name = "Beehive" - icon_state = "hair_beehive" - gender = FEMALE - species_allowed = list("Human","Unathi") - - bobcurl - name = "Bobcurl" - icon_state = "hair_bobcurl" - gender = FEMALE - species_allowed = list("Human","Unathi") - - bob - name = "Bob" - icon_state = "hair_bobcut" - gender = FEMALE - species_allowed = list("Human","Unathi") - - bowl - name = "Bowl" - icon_state = "hair_bowlcut" - gender = MALE - - buzz - name = "Buzzcut" - icon_state = "hair_buzzcut" - gender = MALE - species_allowed = list("Human","Unathi") - - crew - name = "Crewcut" - icon_state = "hair_crewcut" - gender = MALE - - combover - name = "Combover" - icon_state = "hair_combover" - gender = MALE - - devillock - name = "Devil Lock" - icon_state = "hair_devilock" - - dreadlocks - name = "Dreadlocks" - icon_state = "hair_dreads" - - curls - name = "Curls" - icon_state = "hair_curls" - - afro - name = "Afro" - icon_state = "hair_afro" - - afro2 - name = "Afro 2" - icon_state = "hair_afro2" - - afro_large - name = "Big Afro" - icon_state = "hair_bigafro" - gender = MALE - - sargeant - name = "Flat Top" - icon_state = "hair_sargeant" - gender = MALE - - emo - name = "Emo" - icon_state = "hair_emo" - - fag - name = "Flow Hair" - icon_state = "hair_f" - - feather - name = "Feather" - icon_state = "hair_feather" - - hitop - name = "Hitop" - icon_state = "hair_hitop" - gender = MALE - - jensen - name = "Adam Jensen Hair" - icon_state = "hair_jensen" - gender = MALE - - gelled - name = "Gelled Back" - icon_state = "hair_gelled" - gender = FEMALE - - spiky - name = "Spiky" - icon_state = "hair_spikey" - species_allowed = list("Human","Unathi") - kusangi - name = "Kusanagi Hair" - icon_state = "hair_kusanagi" - - kagami - name = "Pigtails" - icon_state = "hair_kagami" - gender = FEMALE - - himecut - name = "Hime Cut" - icon_state = "hair_himecut" - gender = FEMALE - - braid - name = "Floorlength Braid" - icon_state = "hair_braid" - gender = FEMALE - flags = HAIRSTYLE_CANTRIP - - odango - name = "Odango" - icon_state = "hair_odango" - gender = FEMALE - - ombre - name = "Ombre" - icon_state = "hair_ombre" - gender = FEMALE - - updo - name = "Updo" - icon_state = "hair_updo" - gender = FEMALE - - skinhead - name = "Skinhead" - icon_state = "hair_skinhead" - - balding - name = "Balding Hair" - icon_state = "hair_e" - gender = MALE // turnoff! - - familyman - name = "The Family Man" - icon_state = "hair_thefamilyman" - gender = MALE - - mahdrills - name = "Drillruru" - icon_state = "hair_drillruru" - gender = FEMALE - - dandypomp - name = "Dandy Pompadour" - icon_state = "hair_dandypompadour" - gender = MALE - - poofy - name = "Poofy" - icon_state = "hair_poofy" - gender = FEMALE - - crono - name = "Toriyama" - icon_state = "hair_toriyama" - gender = MALE - - vegeta - name = "Toriyama 2" - icon_state = "hair_toriyama2" - gender = MALE - - birdnest - name = "Bird Nest" - icon_state = "hair_birdnest" - - unkept - name = "Unkempt" - icon_state = "hair_unkept" - - duelist - name = "Duelist" - icon_state = "hair_duelist" - gender = MALE - - fastline - name = "Fastline" - icon_state = "hair_fastline" - gender = MALE - - modern - name = "Modern" - icon_state = "hair_modern" - gender = FEMALE - - unshavenmohawk - name = "Unshaven Mohawk" - icon_state = "hair_unshavenmohawk" - gender = MALE - - drills - name = "Twincurls" - icon_state = "hair_twincurl" - gender = FEMALE - - minidrills - name = "Twincurls 2" - icon_state = "hair_twincurl2" - gender = FEMALE - - cia - name = "CIA" - icon_state = "hair_cia" - gender = MALE - - mulder - name = "Mulder" - icon_state = "hair_mulder" - gender = MALE - - scully - name = "Scully" - icon_state = "hair_scully" - gender = FEMALE - - marisa - name = "Marisa" - icon_state = "hair_marisa" - gender = FEMALE - additional_accessories = 1 - - nitori - name = "Nitori" - icon_state = "hair_nitori" - gender = FEMALE - additional_accessories = 1 - - joestar - name = "Joestar" - icon_state = "hair_joestar" - gender = MALE - - metal - name = "Metal" - icon_state = "hair_80s" - - edgeworth - name = "Edgeworth" - icon_state = "hair_edgeworth" - gender = MALE - - objection - name = "Objection!" - icon_state = "hair_objection" - gender = MALE - - dubs - name = "Check 'Em" - icon_state = "hair_dubs" - gender = MALE - - swordsman - name = "Black Swordsman" - icon_state = "hair_blackswordsman" - gender = MALE - - mentalist - name = "Mentalist" - icon_state = "hair_mentalist" - gender = MALE - - fujisaki - name = "Fujisaki" - icon_state = "hair_fujisaki" - gender = FEMALE - - schierke - name = "Schierke" - icon_state = "hair_schierke" - gender = FEMALE - - akari - name = "Akari" - icon_state = "hair_akari" - gender = FEMALE - - fujiyabashi - name = "Fujuyabashi" - icon_state = "hair_fujiyabashi" - gender = FEMALE - - nia - name = "Nia" - icon_state = "hair_nia" - gender = FEMALE - - shinobu - name = "Shinobu" - icon_state = "hair_shinobu" - gender = FEMALE - - bald - name = "Bald" - icon_state = "bald" -/* -/////////////////////////////////// -/ =---------------------------= / -/ == Facial Hair Definitions == / -/ =---------------------------= / -/////////////////////////////////// -*/ - -/datum/sprite_accessory/facial_hair - - icon = 'icons/mob/human_face.dmi' - gender = MALE // barf (unless you're a dorf, dorfs dig chix /w beards :P) - - shaved - name = "Shaved" - icon_state = "bald" - gender = NEUTER - species_allowed = list("Human","Unathi","Tajaran","Skrell","Vox","Grey","Plasmaman","Skellington") - - watson - name = "Watson Mustache" - icon_state = "facial_watson" - - hogan - name = "Hulk Hogan Mustache" - icon_state = "facial_hogan" //-Neek - - vandyke - name = "Van Dyke Mustache" - icon_state = "facial_vandyke" - - chaplin - name = "Square Mustache" - icon_state = "facial_chaplin" - - selleck - name = "Selleck Mustache" - icon_state = "facial_selleck" - - neckbeard - name = "Neckbeard" - icon_state = "facial_neckbeard" - - fullbeard - name = "Full Beard" - icon_state = "facial_fullbeard" - - longbeard - name = "Long Beard" - icon_state = "facial_longbeard" - - vlongbeard - name = "Very Long Beard" - icon_state = "facial_wise" - - elvis - name = "Elvis Sideburns" - icon_state = "facial_elvis" - species_allowed = list("Human","Unathi") - - abe - name = "Abraham Lincoln Beard" - icon_state = "facial_abe" - - chinstrap - name = "Chinstrap" - icon_state = "facial_chin" - - hip - name = "Hipster Beard" - icon_state = "facial_hip" - - gt - name = "Goatee" - icon_state = "facial_gt" - - jensen - name = "Adam Jensen Beard" - icon_state = "facial_jensen" - - dwarf - name = "Dwarf Beard" - icon_state = "facial_dwarf" - - britstache - name = "Brit Stache" - icon_state = "facial_britstache" - - martialartist - name = "Martial Artist" - icon_state = "facial_martialartist" - - moonshiner - name = "Moonshiner" - icon_state = "facial_moonshiner" - - tribeard - name = "Tri-beard" - icon_state = "facial_tribeard" - - unshaven - name = "Unshaven" - icon_state = "facial_unshaven" - - // Before Goon gets all hot and bothered for "stealing": - // A. It's property of SEGA in the first place - // B. I sprited this by hand, despite Steve's pleas to the contrary. I've never played on your server and probably never will. - // - Nexypoo - robotnik - name = "Robotnik Mustache" - icon_state = "facial_robotnik" - -/* -/////////////////////////////////// -/ =---------------------------= / -/ == Alien Style Definitions == / -/ =---------------------------= / -/////////////////////////////////// -*/ - -/datum/sprite_accessory/hair - una_spines_long - name = "Long Unathi Spines" - icon_state = "soghun_longspines" - species_allowed = list("Unathi") - do_colouration = 0 - - una_spines_short - name = "Short Unathi Spines" - icon_state = "soghun_shortspines" - species_allowed = list("Unathi") - do_colouration = 0 - - una_frills_long - name = "Long Unathi Frills" - icon_state = "soghun_longfrills" - species_allowed = list("Unathi") - do_colouration = 0 - - una_frills_short - name = "Short Unathi Frills" - icon_state = "soghun_shortfrill" - species_allowed = list("Unathi") - do_colouration = 0 - - una_horns - name = "Unathi Horns" - icon_state = "soghun_horns" - species_allowed = list("Unathi") - do_colouration = 0 - - skr_tentacle_m - name = "Skrell Male Tentacles" - icon_state = "skrell_hair_m" - species_allowed = list("Skrell") - gender = MALE - do_colouration = 0 - - skr_tentacle_f - name = "Skrell Female Tentacles" - icon_state = "skrell_hair_f" - species_allowed = list("Skrell") - gender = FEMALE - do_colouration = 0 - - skr_gold_m - name = "Gold plated Skrell Male Tentacles" - icon_state = "skrell_goldhair_m" - species_allowed = list("Skrell") - gender = MALE - do_colouration = 0 - - skr_gold_f - name = "Gold chained Skrell Female Tentacles" - icon_state = "skrell_goldhair_f" - species_allowed = list("Skrell") - gender = FEMALE - do_colouration = 0 - - skr_clothtentacle_m - name = "Cloth draped Skrell Male Tentacles" - icon_state = "skrell_clothhair_m" - species_allowed = list("Skrell") - gender = MALE - do_colouration = 0 - - skr_clothtentacle_f - name = "Cloth draped Skrell Female Tentacles" - icon_state = "skrell_clothhair_f" - species_allowed = list("Skrell") - gender = FEMALE - do_colouration = 0 - - taj_ears - name = "Tajaran Ears" - icon_state = "ears_plain" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_clean - name = "Tajara Clean" - icon_state = "hair_clean" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_shaggy - name = "Tajara Shaggy" - icon_state = "hair_shaggy" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_mohawk - name = "Tajaran Mohawk" - icon_state = "hair_mohawk" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_plait - name = "Tajara Plait" - icon_state = "hair_plait" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_straight - name = "Tajara Straight" - icon_state = "hair_straight" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_long - name = "Tajara Long" - icon_state = "hair_long" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_rattail - name = "Tajara Rat Tail" - icon_state = "hair_rattail" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_spiky - name = "Tajara Spiky" - icon_state = "hair_tajspiky" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_ears_messy - name = "Tajara Messy" - icon_state = "hair_messy" - species_allowed = list("Tajaran") - do_colouration = 0 - - vox_quills_short - name = "Short Vox Quills" - icon_state = "vox_shortquills" - species_allowed = list("Vox") - do_colouration = 0 - - vox_quills_kingly - name = "Vox Kingly" - icon_state = "vox_kingly" - species_allowed = list("Vox") - do_colouration = 0 - - vox_quills_afro - name = "Vox Afro" - icon_state = "vox_afro" - species_allowed = list("Vox") - do_colouration = 0 - - vox_quills_mohawk - name = "Vox Mohawk" - icon_state = "vox_mohawk" - species_allowed = list("Vox") - do_colouration = 0 - - vox_quills_yasu - name = "Vox Yasuhiro" - icon_state = "vox_yasu" - species_allowed = list("Vox") - do_colouration = 0 - - vox_quills_horns - name = "Vox Quorns" - icon_state = "vox_horns" - species_allowed = list("Vox") - do_colouration = 0 - - vox_quills_nights - name = "Vox Nights" - icon_state = "vox_nights" - species_allowed = list("Vox") - do_colouration = 0 - -/datum/sprite_accessory/facial_hair - - taj_sideburns - name = "Tajara Sideburns" - icon_state = "facial_mutton" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_mutton - name = "Tajara Mutton" - icon_state = "facial_mutton" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_pencilstache - name = "Tajara Pencilstache" - icon_state = "facial_pencilstache" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_moustache - name = "Tajara Moustache" - icon_state = "facial_moustache" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_goatee - name = "Tajara Goatee" - icon_state = "facial_goatee" - species_allowed = list("Tajaran") - do_colouration = 0 - - taj_smallstache - name = "Tajara Smallsatche" - icon_state = "facial_smallstache" - species_allowed = list("Tajaran") - do_colouration = 0 - - vox_face_colonel - name = "Vox Colonel" - icon_state = "vox_colonel" - species_allowed = list("Vox") - do_colouration = 0 - - vox_face_fu - name = "Quill Fu" - icon_state = "vox_fu" - species_allowed = list("Vox") - do_colouration = 0 - - vox_face_neck - name = "Neck Quills" - icon_state = "vox_neck" - species_allowed = list("Vox") - do_colouration = 0 - - vox_face_beard - name = "Quill Beard" - icon_state = "vox_beard" - species_allowed = list("Vox") - do_colouration = 0 - -//skin styles - WIP -//going to have to re-integrate this with surgery -//let the icon_state hold an icon preview for now -/datum/sprite_accessory/skin - icon = 'icons/mob/human_races/r_human.dmi' - - human - name = "Default human skin" - icon_state = "default" - species_allowed = list("Human") - - human_tatt01 - name = "Tatt01 human skin" - icon_state = "tatt1" - species_allowed = list("Human") - - tajaran - name = "Default tajaran skin" - icon_state = "default" - icon = 'icons/mob/human_races/r_tajaran.dmi' - species_allowed = list("Tajaran") - - unathi - name = "Default Unathi skin" - icon_state = "default" - icon = 'icons/mob/human_races/r_lizard.dmi' - species_allowed = list("Unathi") - - skrell - name = "Default skrell skin" - icon_state = "default" - icon = 'icons/mob/human_races/r_skrell.dmi' - species_allowed = list("Skrell") - -/datum/sprite_accessory/hair/mohawk - name = "Mohawk" +/* + + Hello and welcome to sprite_accessories: For sprite accessories, such as hair, + facial hair, and possibly tattoos and stuff somewhere along the line. This file is + intended to be friendly for people with little to no actual coding experience. + The process of adding in new hairstyles has been made pain-free and easy to do. + Enjoy! - Doohl + + + Notice: This all gets automatically compiled in a list in dna2.dm, so you do not + have to define any UI values for sprite accessories manually for hair and facial + hair. Just add in new hair types and the game will naturally adapt. + + !!WARNING!!: changing existing hair information can be VERY hazardous to savefiles, + to the point where you may completely corrupt a server's savefiles. Please refrain + from doing this unless you absolutely know what you are doing, and have defined a + conversion in savefile.dm +*/ + +/datum/sprite_accessory + + var/icon // the icon file the accessory is located in + var/icon_state // the icon_state of the accessory + var/preview_state // a custom preview state for whatever reason + + var/name // the preview name of the accessory + + // Determines if the accessory will be skipped or included in random hair generations + var/gender = NEUTER + + // Restrict some styles to specific species + var/list/species_allowed = list("Human") + + // Whether or not the accessory can be affected by colouration + var/do_colouration = 1 + + // If the hair-style has parts that aren't affected by colouration (stored on a second sprite) + var/additional_accessories = 0 + + var/flags = 0 + + +/* +//////////////////////////// +/ =--------------------= / +/ == Hair Definitions == / +/ =--------------------= / +//////////////////////////// +*/ + +/datum/sprite_accessory/hair + + icon = 'icons/mob/human_face.dmi' // default icon for all hairs + + bald + name = "Bald" + icon_state = "bald" + gender = MALE + species_allowed = list("Human","Unathi","Grey","Plasmaman","Skellington") + + short + name = "Short Hair" // try to capatilize the names please~ + icon_state = "hair_a" // you do not need to define _s or _l sub-states, game automatically does this for you + + cut + name = "Cut Hair" + icon_state = "hair_c" + + long + name = "Shoulder-length Hair" + icon_state = "hair_b" + + longalt + name = "Shoulder-length Hair Alt" + icon_state = "hair_longfringe" + + /*longish + name = "Longer Hair" + icon_state = "hair_b2"*/ + + longer + name = "Long Hair" + icon_state = "hair_vlong" + + longeralt + name = "Long Hair Alt" + icon_state = "hair_vlongfringe" + + longest + name = "Very Long Hair" + icon_state = "hair_longest" + + longfringe + name = "Long Fringe" + icon_state = "hair_longfringe" + + longestalt + name = "Longer Fringe" + icon_state = "hair_vlongfringe" + + halfbang + name = "Half-banged Hair" + icon_state = "hair_halfbang" + + halfbangalt + name = "Half-banged Hair Alt" + icon_state = "hair_halfbang_alt" + + ponytail1 + name = "Ponytail 1" + icon_state = "hair_ponytail" + + ponytail2 + name = "Ponytail 2" + icon_state = "hair_pa" + gender = FEMALE + + ponytail3 + name = "Ponytail 3" + icon_state = "hair_ponytail3" + + parted + name = "Parted" + icon_state = "hair_parted" + + pompadour + name = "Pompadour" + icon_state = "hair_pompadour" + gender = MALE + species_allowed = list("Human","Unathi") + + quiff + name = "Quiff" + icon_state = "hair_quiff" + gender = MALE + + bedhead + name = "Bedhead" + icon_state = "hair_bedhead" + + bedhead2 + name = "Bedhead 2" + icon_state = "hair_bedheadv2" + + bedhead3 + name = "Bedhead 3" + icon_state = "hair_bedheadv3" + + beehive + name = "Beehive" + icon_state = "hair_beehive" + gender = FEMALE + species_allowed = list("Human","Unathi") + + bobcurl + name = "Bobcurl" + icon_state = "hair_bobcurl" + gender = FEMALE + species_allowed = list("Human","Unathi") + + bob + name = "Bob" + icon_state = "hair_bobcut" + gender = FEMALE + species_allowed = list("Human","Unathi") + + bowl + name = "Bowl" + icon_state = "hair_bowlcut" + gender = MALE + + buzz + name = "Buzzcut" + icon_state = "hair_buzzcut" + gender = MALE + species_allowed = list("Human","Unathi") + + crew + name = "Crewcut" + icon_state = "hair_crewcut" + gender = MALE + + combover + name = "Combover" + icon_state = "hair_combover" + gender = MALE + + devillock + name = "Devil Lock" + icon_state = "hair_devilock" + + dreadlocks + name = "Dreadlocks" + icon_state = "hair_dreads" + + curls + name = "Curls" + icon_state = "hair_curls" + + afro + name = "Afro" + icon_state = "hair_afro" + + afro2 + name = "Afro 2" + icon_state = "hair_afro2" + + afro_large + name = "Big Afro" + icon_state = "hair_bigafro" + gender = MALE + + sargeant + name = "Flat Top" + icon_state = "hair_sargeant" + gender = MALE + + emo + name = "Emo" + icon_state = "hair_emo" + + fag + name = "Flow Hair" + icon_state = "hair_f" + + feather + name = "Feather" + icon_state = "hair_feather" + + hitop + name = "Hitop" + icon_state = "hair_hitop" + gender = MALE + + jensen + name = "Adam Jensen Hair" + icon_state = "hair_jensen" + gender = MALE + + gelled + name = "Gelled Back" + icon_state = "hair_gelled" + gender = FEMALE + + spiky + name = "Spiky" + icon_state = "hair_spikey" + species_allowed = list("Human","Unathi") + kusangi + name = "Kusanagi Hair" + icon_state = "hair_kusanagi" + + kagami + name = "Pigtails" + icon_state = "hair_kagami" + gender = FEMALE + + himecut + name = "Hime Cut" + icon_state = "hair_himecut" + gender = FEMALE + + braid + name = "Floorlength Braid" + icon_state = "hair_braid" + gender = FEMALE + flags = HAIRSTYLE_CANTRIP + + odango + name = "Odango" + icon_state = "hair_odango" + gender = FEMALE + + ombre + name = "Ombre" + icon_state = "hair_ombre" + gender = FEMALE + + updo + name = "Updo" + icon_state = "hair_updo" + gender = FEMALE + + skinhead + name = "Skinhead" + icon_state = "hair_skinhead" + + balding + name = "Balding Hair" + icon_state = "hair_e" + gender = MALE // turnoff! + + familyman + name = "The Family Man" + icon_state = "hair_thefamilyman" + gender = MALE + + mahdrills + name = "Drillruru" + icon_state = "hair_drillruru" + gender = FEMALE + + dandypomp + name = "Dandy Pompadour" + icon_state = "hair_dandypompadour" + gender = MALE + + poofy + name = "Poofy" + icon_state = "hair_poofy" + gender = FEMALE + + crono + name = "Toriyama" + icon_state = "hair_toriyama" + gender = MALE + + vegeta + name = "Toriyama 2" + icon_state = "hair_toriyama2" + gender = MALE + + birdnest + name = "Bird Nest" + icon_state = "hair_birdnest" + + unkept + name = "Unkempt" + icon_state = "hair_unkept" + + duelist + name = "Duelist" + icon_state = "hair_duelist" + gender = MALE + + fastline + name = "Fastline" + icon_state = "hair_fastline" + gender = MALE + + modern + name = "Modern" + icon_state = "hair_modern" + gender = FEMALE + + unshavenmohawk + name = "Unshaven Mohawk" + icon_state = "hair_unshavenmohawk" + gender = MALE + + drills + name = "Twincurls" + icon_state = "hair_twincurl" + gender = FEMALE + + minidrills + name = "Twincurls 2" + icon_state = "hair_twincurl2" + gender = FEMALE + + cia + name = "CIA" + icon_state = "hair_cia" + gender = MALE + + mulder + name = "Mulder" + icon_state = "hair_mulder" + gender = MALE + + scully + name = "Scully" + icon_state = "hair_scully" + gender = FEMALE + + marisa + name = "Marisa" + icon_state = "hair_marisa" + gender = FEMALE + additional_accessories = 1 + + nitori + name = "Nitori" + icon_state = "hair_nitori" + gender = FEMALE + additional_accessories = 1 + + joestar + name = "Joestar" + icon_state = "hair_joestar" + gender = MALE + + metal + name = "Metal" + icon_state = "hair_80s" + + edgeworth + name = "Edgeworth" + icon_state = "hair_edgeworth" + gender = MALE + + objection + name = "Objection!" + icon_state = "hair_objection" + gender = MALE + + dubs + name = "Check 'Em" + icon_state = "hair_dubs" + gender = MALE + + swordsman + name = "Black Swordsman" + icon_state = "hair_blackswordsman" + gender = MALE + + mentalist + name = "Mentalist" + icon_state = "hair_mentalist" + gender = MALE + + fujisaki + name = "Fujisaki" + icon_state = "hair_fujisaki" + gender = FEMALE + + schierke + name = "Schierke" + icon_state = "hair_schierke" + gender = FEMALE + + akari + name = "Akari" + icon_state = "hair_akari" + gender = FEMALE + + fujiyabashi + name = "Fujuyabashi" + icon_state = "hair_fujiyabashi" + gender = FEMALE + + nia + name = "Nia" + icon_state = "hair_nia" + gender = FEMALE + + shinobu + name = "Shinobu" + icon_state = "hair_shinobu" + gender = FEMALE + + bald + name = "Bald" + icon_state = "bald" +/* +/////////////////////////////////// +/ =---------------------------= / +/ == Facial Hair Definitions == / +/ =---------------------------= / +/////////////////////////////////// +*/ + +/datum/sprite_accessory/facial_hair + + icon = 'icons/mob/human_face.dmi' + gender = MALE // barf (unless you're a dorf, dorfs dig chix /w beards :P) + + shaved + name = "Shaved" + icon_state = "bald" + gender = NEUTER + species_allowed = list("Human","Unathi","Tajaran","Skrell","Vox","Grey","Plasmaman","Skellington") + + watson + name = "Watson Mustache" + icon_state = "facial_watson" + + hogan + name = "Hulk Hogan Mustache" + icon_state = "facial_hogan" //-Neek + + vandyke + name = "Van Dyke Mustache" + icon_state = "facial_vandyke" + + chaplin + name = "Square Mustache" + icon_state = "facial_chaplin" + + selleck + name = "Selleck Mustache" + icon_state = "facial_selleck" + + neckbeard + name = "Neckbeard" + icon_state = "facial_neckbeard" + + fullbeard + name = "Full Beard" + icon_state = "facial_fullbeard" + + longbeard + name = "Long Beard" + icon_state = "facial_longbeard" + + vlongbeard + name = "Very Long Beard" + icon_state = "facial_wise" + + elvis + name = "Elvis Sideburns" + icon_state = "facial_elvis" + species_allowed = list("Human","Unathi") + + abe + name = "Abraham Lincoln Beard" + icon_state = "facial_abe" + + chinstrap + name = "Chinstrap" + icon_state = "facial_chin" + + hip + name = "Hipster Beard" + icon_state = "facial_hip" + + gt + name = "Goatee" + icon_state = "facial_gt" + + jensen + name = "Adam Jensen Beard" + icon_state = "facial_jensen" + + dwarf + name = "Dwarf Beard" + icon_state = "facial_dwarf" + + britstache + name = "Brit Stache" + icon_state = "facial_britstache" + + martialartist + name = "Martial Artist" + icon_state = "facial_martialartist" + + moonshiner + name = "Moonshiner" + icon_state = "facial_moonshiner" + + tribeard + name = "Tri-beard" + icon_state = "facial_tribeard" + + unshaven + name = "Unshaven" + icon_state = "facial_unshaven" + + // Before Goon gets all hot and bothered for "stealing": + // A. It's property of SEGA in the first place + // B. I sprited this by hand, despite Steve's pleas to the contrary. I've never played on your server and probably never will. + // - Nexypoo + robotnik + name = "Robotnik Mustache" + icon_state = "facial_robotnik" + +/* +/////////////////////////////////// +/ =---------------------------= / +/ == Alien Style Definitions == / +/ =---------------------------= / +/////////////////////////////////// +*/ + +/datum/sprite_accessory/hair + una_spines_long + name = "Long Unathi Spines" + icon_state = "soghun_longspines" + species_allowed = list("Unathi") + do_colouration = 0 + + una_spines_short + name = "Short Unathi Spines" + icon_state = "soghun_shortspines" + species_allowed = list("Unathi") + do_colouration = 0 + + una_frills_long + name = "Long Unathi Frills" + icon_state = "soghun_longfrills" + species_allowed = list("Unathi") + do_colouration = 0 + + una_frills_short + name = "Short Unathi Frills" + icon_state = "soghun_shortfrill" + species_allowed = list("Unathi") + do_colouration = 0 + + una_horns + name = "Unathi Horns" + icon_state = "soghun_horns" + species_allowed = list("Unathi") + do_colouration = 0 + + skr_tentacle_m + name = "Skrell Male Tentacles" + icon_state = "skrell_hair_m" + species_allowed = list("Skrell") + gender = MALE + do_colouration = 0 + + skr_tentacle_f + name = "Skrell Female Tentacles" + icon_state = "skrell_hair_f" + species_allowed = list("Skrell") + gender = FEMALE + do_colouration = 0 + + skr_gold_m + name = "Gold plated Skrell Male Tentacles" + icon_state = "skrell_goldhair_m" + species_allowed = list("Skrell") + gender = MALE + do_colouration = 0 + + skr_gold_f + name = "Gold chained Skrell Female Tentacles" + icon_state = "skrell_goldhair_f" + species_allowed = list("Skrell") + gender = FEMALE + do_colouration = 0 + + skr_clothtentacle_m + name = "Cloth draped Skrell Male Tentacles" + icon_state = "skrell_clothhair_m" + species_allowed = list("Skrell") + gender = MALE + do_colouration = 0 + + skr_clothtentacle_f + name = "Cloth draped Skrell Female Tentacles" + icon_state = "skrell_clothhair_f" + species_allowed = list("Skrell") + gender = FEMALE + do_colouration = 0 + + taj_ears + name = "Tajaran Ears" + icon_state = "ears_plain" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_clean + name = "Tajara Clean" + icon_state = "hair_clean" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_shaggy + name = "Tajara Shaggy" + icon_state = "hair_shaggy" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_mohawk + name = "Tajaran Mohawk" + icon_state = "hair_mohawk" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_plait + name = "Tajara Plait" + icon_state = "hair_plait" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_straight + name = "Tajara Straight" + icon_state = "hair_straight" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_long + name = "Tajara Long" + icon_state = "hair_long" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_rattail + name = "Tajara Rat Tail" + icon_state = "hair_rattail" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_spiky + name = "Tajara Spiky" + icon_state = "hair_tajspiky" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_ears_messy + name = "Tajara Messy" + icon_state = "hair_messy" + species_allowed = list("Tajaran") + do_colouration = 0 + + vox_quills_short + name = "Short Vox Quills" + icon_state = "vox_shortquills" + species_allowed = list("Vox") + do_colouration = 0 + + vox_quills_kingly + name = "Vox Kingly" + icon_state = "vox_kingly" + species_allowed = list("Vox") + do_colouration = 0 + + vox_quills_afro + name = "Vox Afro" + icon_state = "vox_afro" + species_allowed = list("Vox") + do_colouration = 0 + + vox_quills_mohawk + name = "Vox Mohawk" + icon_state = "vox_mohawk" + species_allowed = list("Vox") + do_colouration = 0 + + vox_quills_yasu + name = "Vox Yasuhiro" + icon_state = "vox_yasu" + species_allowed = list("Vox") + do_colouration = 0 + + vox_quills_horns + name = "Vox Quorns" + icon_state = "vox_horns" + species_allowed = list("Vox") + do_colouration = 0 + + vox_quills_nights + name = "Vox Nights" + icon_state = "vox_nights" + species_allowed = list("Vox") + do_colouration = 0 + +/datum/sprite_accessory/facial_hair + + taj_sideburns + name = "Tajara Sideburns" + icon_state = "facial_mutton" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_mutton + name = "Tajara Mutton" + icon_state = "facial_mutton" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_pencilstache + name = "Tajara Pencilstache" + icon_state = "facial_pencilstache" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_moustache + name = "Tajara Moustache" + icon_state = "facial_moustache" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_goatee + name = "Tajara Goatee" + icon_state = "facial_goatee" + species_allowed = list("Tajaran") + do_colouration = 0 + + taj_smallstache + name = "Tajara Smallsatche" + icon_state = "facial_smallstache" + species_allowed = list("Tajaran") + do_colouration = 0 + + vox_face_colonel + name = "Vox Colonel" + icon_state = "vox_colonel" + species_allowed = list("Vox") + do_colouration = 0 + + vox_face_fu + name = "Quill Fu" + icon_state = "vox_fu" + species_allowed = list("Vox") + do_colouration = 0 + + vox_face_neck + name = "Neck Quills" + icon_state = "vox_neck" + species_allowed = list("Vox") + do_colouration = 0 + + vox_face_beard + name = "Quill Beard" + icon_state = "vox_beard" + species_allowed = list("Vox") + do_colouration = 0 + +//skin styles - WIP +//going to have to re-integrate this with surgery +//let the icon_state hold an icon preview for now +/datum/sprite_accessory/skin + icon = 'icons/mob/human_races/r_human.dmi' + + human + name = "Default human skin" + icon_state = "default" + species_allowed = list("Human") + + human_tatt01 + name = "Tatt01 human skin" + icon_state = "tatt1" + species_allowed = list("Human") + + tajaran + name = "Default tajaran skin" + icon_state = "default" + icon = 'icons/mob/human_races/r_tajaran.dmi' + species_allowed = list("Tajaran") + + unathi + name = "Default Unathi skin" + icon_state = "default" + icon = 'icons/mob/human_races/r_lizard.dmi' + species_allowed = list("Unathi") + + skrell + name = "Default skrell skin" + icon_state = "default" + icon = 'icons/mob/human_races/r_skrell.dmi' + species_allowed = list("Skrell") + +/datum/sprite_accessory/hair/mohawk + name = "Mohawk" icon_state = "mohawk" \ No newline at end of file diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 3e095e78a63..ed4a60f0187 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -1,139 +1,139 @@ -/mob/verb/say_verb(message as text) - set name = "Say" - set category = "IC" - - if(say_disabled) - to_chat(usr, "Speech is currently admin-disabled.") - return - usr.say(message) - -/mob/verb/whisper(message as text) - set name = "Whisper" - set category = "IC" - return -/* -/mob/proc/whisper(var/message, var/unheard=" whispers something", var/heard="whispers,", var/apply_filters=1, var/allow_lastwords=1) - return -*/ - -/mob/verb/me_verb(message as text) - set name = "Me" - set category = "IC" - - if(say_disabled) //This is here to try to identify lag problems - to_chat(usr, "Speech is currently admin-disabled.") - return - - if(!usr.stat && (usr.status_flags & FAKEDEATH)) - to_chat(usr, "Doing this will give us away!") - return - - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - - if(usr.stat == DEAD) - usr.emote_dead(message) - else - usr.emote("me",usr.emote_type,message) - -/mob/proc/say_dead(var/message) - var/name = src.real_name - var/alt_name = "" - - if(say_disabled) //This is here to try to identify lag problems - to_chat(usr, "Speech is currently admin-disabled.") - return - - if(client && !(client.prefs.toggles & CHAT_DEAD)) - to_chat(usr, "You have deadchat muted.") - return - - if(mind && mind.name) - name = "[mind.name]" - else - name = real_name - if(name != real_name) - alt_name = " (died as [real_name])" - - message = src.say_quote("\"[html_encode(message)]\"") - //var/rendered = "DEAD: [name][alt_name] [message]" - var/rendered2 = null//edited - for(var/mob/M in player_list) - rendered2 = "(Follow) DEAD: [name][alt_name] [message]"//edited - if(istype(M, /mob/new_player) || !M.client) - continue - if(M.client && M.client.holder && M.client.holder.rights & R_ADMIN && (M.client.prefs.toggles & CHAT_DEAD)) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above - to_chat(M, rendered2)//Admins can hear deadchat, if they choose to, no matter if they're blind/deaf or not. - - else if(M.client && M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) - //M.show_message(rendered2, 2) //Takes into account blindness and such. - to_chat(M, rendered2) - return - -/mob/proc/emote(var/act, var/type, var/message, var/auto) - if(timestopped) return //under effects of time magick - if(act == "me") - return custom_emote(type, message) - -/mob/proc/get_ear() - // returns an atom representing a location on the map from which this - // mob can hear things - - // should be overloaded for all mobs whose "ear" is separate from their "mob" - - return get_turf(src) - -/mob/proc/lingcheck() - return 0 - -/mob/proc/construct_chat_check(var/setting) - return 0 - -/mob/proc/hivecheck() - return 0 - -/mob/proc/binarycheck() - return 0 - -//parses the language code (e.g. :j) from text, such as that supplied to say. -//returns the language object only if the code corresponds to a language that src can speak, otherwise null. -/mob/proc/parse_language(var/message) - if(length(message) >= 2) - var/language_prefix = lowertext(copytext(message, 1 ,3)) - if(language_prefix in language_keys) - var/datum/language/L = language_keys[language_prefix] - if (can_speak_lang(L)) - return L - else - if(istype(L)) - say_testing(src, "Tried to speak [L.name] but don't know it, prefix length is [length(language_prefix)] before [message] after [copytext(message, 1+length(language_prefix))]") - return language_prefix - - return null - -/mob/say_understands(var/mob/other,var/datum/language/speaking = null) - if (src.stat == 2) //Dead - return 1 - - //Universal speak makes everything understandable, for obvious reasons. - if(src.universal_speak || src.universal_understand) - return 1 - - //Languages are handled after. - if (!speaking) - if(other) - other = other.GetSource() - if(!other || !ismob(other)) - return 1 - if(other.universal_speak) - return 1 - if(isAI(src) && ispAI(other)) - return 1 - if (istype(other, src.type) || istype(src, other.type)) - return 1 - return 0 - - //Language check. - for(var/datum/language/L in src.languages) - if(speaking.name == L.name) - return 1 - return 0 +/mob/verb/say_verb(message as text) + set name = "Say" + set category = "IC" + + if(say_disabled) + to_chat(usr, "Speech is currently admin-disabled.") + return + usr.say(message) + +/mob/verb/whisper(message as text) + set name = "Whisper" + set category = "IC" + return +/* +/mob/proc/whisper(var/message, var/unheard=" whispers something", var/heard="whispers,", var/apply_filters=1, var/allow_lastwords=1) + return +*/ + +/mob/verb/me_verb(message as text) + set name = "Me" + set category = "IC" + + if(say_disabled) //This is here to try to identify lag problems + to_chat(usr, "Speech is currently admin-disabled.") + return + + if(!usr.stat && (usr.status_flags & FAKEDEATH)) + to_chat(usr, "Doing this will give us away!") + return + + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + + if(usr.stat == DEAD) + usr.emote_dead(message) + else + usr.emote("me",usr.emote_type,message) + +/mob/proc/say_dead(var/message) + var/name = src.real_name + var/alt_name = "" + + if(say_disabled) //This is here to try to identify lag problems + to_chat(usr, "Speech is currently admin-disabled.") + return + + if(client && !(client.prefs.toggles & CHAT_DEAD)) + to_chat(usr, "You have deadchat muted.") + return + + if(mind && mind.name) + name = "[mind.name]" + else + name = real_name + if(name != real_name) + alt_name = " (died as [real_name])" + + message = src.say_quote("\"[html_encode(message)]\"") + //var/rendered = "DEAD: [name][alt_name] [message]" + var/rendered2 = null//edited + for(var/mob/M in player_list) + rendered2 = "(Follow) DEAD: [name][alt_name] [message]"//edited + if(istype(M, /mob/new_player) || !M.client) + continue + if(M.client && M.client.holder && M.client.holder.rights & R_ADMIN && (M.client.prefs.toggles & CHAT_DEAD)) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above + to_chat(M, rendered2)//Admins can hear deadchat, if they choose to, no matter if they're blind/deaf or not. + + else if(M.client && M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) + //M.show_message(rendered2, 2) //Takes into account blindness and such. + to_chat(M, rendered2) + return + +/mob/proc/emote(var/act, var/type, var/message, var/auto) + if(timestopped) return //under effects of time magick + if(act == "me") + return custom_emote(type, message) + +/mob/proc/get_ear() + // returns an atom representing a location on the map from which this + // mob can hear things + + // should be overloaded for all mobs whose "ear" is separate from their "mob" + + return get_turf(src) + +/mob/proc/lingcheck() + return 0 + +/mob/proc/construct_chat_check(var/setting) + return 0 + +/mob/proc/hivecheck() + return 0 + +/mob/proc/binarycheck() + return 0 + +//parses the language code (e.g. :j) from text, such as that supplied to say. +//returns the language object only if the code corresponds to a language that src can speak, otherwise null. +/mob/proc/parse_language(var/message) + if(length(message) >= 2) + var/language_prefix = lowertext(copytext(message, 1 ,3)) + if(language_prefix in language_keys) + var/datum/language/L = language_keys[language_prefix] + if (can_speak_lang(L)) + return L + else + if(istype(L)) + say_testing(src, "Tried to speak [L.name] but don't know it, prefix length is [length(language_prefix)] before [message] after [copytext(message, 1+length(language_prefix))]") + return language_prefix + + return null + +/mob/say_understands(var/mob/other,var/datum/language/speaking = null) + if (src.stat == 2) //Dead + return 1 + + //Universal speak makes everything understandable, for obvious reasons. + if(src.universal_speak || src.universal_understand) + return 1 + + //Languages are handled after. + if (!speaking) + if(other) + other = other.GetSource() + if(!other || !ismob(other)) + return 1 + if(other.universal_speak) + return 1 + if(isAI(src) && ispAI(other)) + return 1 + if (istype(other, src.type) || istype(src, other.type)) + return 1 + return 0 + + //Language check. + for(var/datum/language/L in src.languages) + if(speaking.name == L.name) + return 1 + return 0 diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index a5add5d7f41..9c9da973035 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,471 +1,471 @@ -/mob/living/carbon/human/proc/monkeyize() - if (monkeyizing) - return - - for(var/obj/item/W in src) - if (W==w_uniform) // will be torn - continue - drop_from_inventory(W) - regenerate_icons() - dropBorers() - monkeyizing = 1 - canmove = 0 - delayNextAttack(50) - icon = null - invisibility = 101 - - for(var/t in organs) - qdel(t) - anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "h2monkey", sleeptime = 15) - sleep(33) - - if(!species.primitive) //If the creature in question has no primitive set, this is going to be messy. - gib() - return - - var/mob/living/carbon/monkey/O = null - - O = new species.primitive(get_turf(src)) - - O.dna = dna.Clone() - O.dna.SetSEState(MONKEYBLOCK,1) - O.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) - O.loc = loc - O.viruses = viruses - viruses = list() - for(var/datum/disease/D in O.viruses) - D.affected_mob = O - - if (client) - client.mob = O - if(mind) - mind.transfer_to(O) - - to_chat(O, "You are now [O]. ") - - qdel(src) - - return O - -/mob/living/carbon/human/proc/Cluwneize() - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - regenerate_icons() - dropBorers() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - for(var/t in organs) //this really should not be necessary - qdel(t) - - var/mob/living/simple_animal/hostile/retaliate/cluwne/new_mob = new (get_turf(src)) - new_mob.setGender(gender) - new_mob.name = pick(clown_names) - new_mob.real_name = new_mob.name - new_mob.mutations += M_CLUMSY - new_mob.mutations += M_FAT - new_mob.setBrainLoss(100) - new_mob.a_intent = I_HURT - new_mob.key = key - - to_chat(new_mob, "Instantly, what was your clothes fall off, and are replaced with a mockery of all that is clowning; Disgusting-looking garb that the foulest of creatures would be afraid of wearing. Your very face begins to shape, mold, into something truely disgusting. A mask made of flesh. Your body is feeling the worst pain it has ever felt. As you think it cannot get any worse, one of your arms turns into a horrific meld of flesh and plastic, making a limb made entirely of bike horns.") - to_chat(new_mob, "Your very soul is being torn apart. What was organs, blood, flesh, is now darkness. And inside the infernal void that was once a living being, something sinister takes root. As what you were goes away, you try to let out a frantic plea of 'Help me! Please god help me!' but your god has abandoned you, and all that leaves your horrible mouth is a strangled 'HONK!'.") - new_mob.say("HONK!") - spawn(0)//To prevent the proc from returning null. - qdel(src) - return new_mob - -/mob/new_player/AIize() - spawning = 1 - return ..() - -/mob/living/carbon/human/AIize() - if (monkeyizing) - return - for(var/t in organs) - qdel(t) - - return ..() - -/mob/living/carbon/AIize() - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - dropBorers() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - return ..() - -/mob/proc/AIize() - if(client) - to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// stop the jams for AIs - - var/mob/living/silicon/ai/O = new (get_turf(src), base_law_type,,1)//No MMI but safety is in effect. - O.invisibility = 0 - O.aiRestorePowerRoutine = 0 - - if(mind) - mind.transfer_to(O) - O.mind.original = O - else - O.key = key - - var/obj/loc_landmark - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name != "AI") - continue - if (locate(/mob/living) in sloc.loc) - continue - loc_landmark = sloc - if (!loc_landmark) - for(var/obj/effect/landmark/tripai in landmarks_list) - if (tripai.name == "tripai") - if(locate(/mob/living) in tripai.loc) - continue - loc_landmark = tripai - if (!loc_landmark) - to_chat(O, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.") - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name == "AI") - loc_landmark = sloc - - O.loc = loc_landmark.loc - for (var/obj/item/device/radio/intercom/comm in O.loc) - comm.ai += O - - to_chat(O, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).") - to_chat(O, "To look at other parts of the station, click on yourself to get a camera menu.") - to_chat(O, "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.") - to_chat(O, "To use something, simply click on it.") - to_chat(O, {"Use say ":b to speak to your cyborgs through binary."}) - if (!(ticker && ticker.mode && (O.mind in ticker.mode.malf_ai))) - O.show_laws() - to_chat(O, "These laws may be changed by other players, or by you being the traitor.") - - //O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle - O.verbs += /mob/living/silicon/ai/proc/show_laws_verb - //O.verbs += /mob/living/silicon/ai/proc/ai_camera_track - //O.verbs += /mob/living/silicon/ai/proc/ai_alerts - //O.verbs += /mob/living/silicon/ai/proc/ai_camera_list - O.verbs += /mob/living/silicon/ai/proc/ai_statuschange - //O.verbs += /mob/living/silicon/ai/proc/ai_roster - - O.job = "AI" - - O.rename_self("ai",1) - . = O - qdel(src) - - -//human -> robot -/mob/living/carbon/human/proc/Robotize(var/delete_items = 0) - if (monkeyizing) - return - for(var/obj/item/W in src) - if(delete_items) - qdel(W) - else - drop_from_inventory(W) - dropBorers() - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - for(var/t in organs) - qdel(t) - - var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(src)) - . = O - // cyborgs produced by Robotize get an automatic power cell - O.cell = new(O) - O.cell.maxcharge = 7500 - O.cell.charge = 7500 - - O.setGender(gender) - O.invisibility = 0 - - if(mind) //TODO - mind.transfer_to(O) - if(O.mind.assigned_role == "Cyborg") - O.mind.original = O - else if(mind&&mind.special_role) - O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") - else - O.key = key - - O.loc = loc - O.job = "Cyborg" - - O.mmi = new /obj/item/device/mmi(O) - O.mmi.transfer_identity(src)//Does not transfer key/client. - - spawn() O.Namepick() - - spawn(0)//To prevent the proc from returning null. - qdel(src) - - -//human -> mommi -/mob/living/carbon/human/proc/MoMMIfy(round_start = 0) - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - dropBorers() - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - for(var/t in organs) - qdel(t) - - var/mob/living/silicon/robot/mommi/O = new /mob/living/silicon/robot/mommi(get_turf(src)) - . = O - // MoMMIs produced by Robotize get an automatic power cell - O.cell = new(O) - O.cell.maxcharge = (round_start ? 10000 : 15000) - O.cell.charge = (round_start ? 10000 : 15000) - - - O.setGender(gender) - O.invisibility = 0 - - - if(mind) //TODO - mind.transfer_to(O) - if(O.mind.assigned_role == "Cyborg") - O.mind.original = O - else if(mind && mind.special_role) - O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") - else - O.key = key - - O.loc = loc - O.job = "Cyborg" - - O.mmi = new /obj/item/device/mmi(O) - O.mmi.transfer_identity(src)//Does not transfer key/client. - - spawn() O.Namepick() - - - spawn(0)//To prevent the proc from returning null. - qdel(src) - -//human -> alien -/mob/living/carbon/human/proc/Alienize() - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - dropBorers() - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - for(var/t in organs) - qdel(t) - - var/alien_caste = pick("Hunter","Sentinel","Drone") - var/mob/living/carbon/alien/humanoid/new_xeno - switch(alien_caste) - if("Hunter") - new_xeno = new /mob/living/carbon/alien/humanoid/hunter(get_turf(src)) - if("Sentinel") - new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(get_turf(src)) - if("Drone") - new_xeno = new /mob/living/carbon/alien/humanoid/drone(get_turf(src)) - - new_xeno.a_intent = I_HURT - new_xeno.key = key - - to_chat(new_xeno, "You are now an alien.") - spawn(0)//To prevent the proc from returning null. - qdel(src) - return new_xeno - -/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num) - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - dropBorers() - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - for(var/t in organs) - qdel(t) - - var/mob/living/carbon/slime/new_slime - if(reproduce) - var/number = pick(14;2,3,4) //reproduce (has a small chance of producing 3 or 4 offspring) - var/list/babies = list() - for(var/i=1,i<=number,i++) - var/mob/living/carbon/slime/M = new/mob/living/carbon/slime(get_turf(src)) - M.nutrition = round(nutrition/number) - step_away(M,src) - babies += M - new_slime = pick(babies) - else - if(adult) - new_slime = new /mob/living/carbon/slime/adult(get_turf(src)) - else - new_slime = new /mob/living/carbon/slime(get_turf(src)) - new_slime.a_intent = I_HURT - new_slime.key = key - - to_chat(new_slime, "You are now a slime. Skreee!") - spawn(0)//To prevent the proc from returning null. - qdel(src) - return new_slime - -/mob/living/carbon/human/proc/corgize() - if (monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - dropBorers() - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - for(var/t in organs) //this really should not be necessary - qdel(t) - - var/mob/living/simple_animal/corgi/new_corgi = new /mob/living/simple_animal/corgi (get_turf(src)) - new_corgi.a_intent = I_HURT - new_corgi.key = key - - to_chat(new_corgi, "You are now a Corgi. Yap Yap!") - spawn(0)//To prevent the proc from returning null. - qdel(src) - return new_corgi - -/mob/living/carbon/human/Animalize() - - var/list/mobtypes = typesof(/mob/living/simple_animal) - var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes - - if(!safe_animal(mobpath)) - to_chat(usr, "Sorry but this mob type is currently unavailable.") - return - - if(monkeyizing) - return - for(var/obj/item/W in src) - drop_from_inventory(W) - dropBorers() - - regenerate_icons() - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - delayNextAttack(50) - - for(var/t in organs) - qdel(t) - - var/mob/new_mob = new mobpath(get_turf(src)) - - new_mob.key = key - new_mob.a_intent = I_HURT - - - to_chat(new_mob, "You suddenly feel more... animalistic.") - spawn() - qdel(src) - return new_mob - -/mob/proc/Animalize() - - - var/list/mobtypes = typesof(/mob/living/simple_animal) - var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes - - if(!safe_animal(mobpath)) - to_chat(usr, "Sorry but this mob type is currently unavailable.") - return - - var/mob/new_mob = new mobpath(get_turf(src)) - - new_mob.key = key - new_mob.a_intent = I_HURT - to_chat(new_mob, "You feel more... animalistic") - - spawn() - qdel(src) - return new_mob - -/* Certain mob types have problems and should not be allowed to be controlled by players. - * - * This proc is here to force coders to manually place their mob in this list, hopefully tested. - * This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them. - */ -/mob/proc/safe_animal(var/MP) - -//Bad mobs! - Remember to add a comment explaining what's wrong with the mob - if(!MP) - return 0 //Sanity, this should never happen. - - if(ispath(MP, /mob/living/simple_animal/space_worm)) - return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning. - - if(ispath(MP, /mob/living/simple_animal/construct/behemoth)) - return 0 //I think this may have been an unfinished WiP or something. These constructs should really have their own class simple_animal/construct/subtype - - if(ispath(MP, /mob/living/simple_animal/construct/armoured)) - return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype - - if(ispath(MP, /mob/living/simple_animal/construct/wraith)) - return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype - - if(ispath(MP, /mob/living/simple_animal/construct/builder)) - return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype - -//Good mobs! - if(ispath(MP, /mob/living/simple_animal/cat)) - return 1 - if(ispath(MP, /mob/living/simple_animal/corgi)) - return 1 - if(ispath(MP, /mob/living/simple_animal/crab)) - return 1 - if(ispath(MP, /mob/living/simple_animal/hostile/carp)) - return 1 - if(ispath(MP, /mob/living/simple_animal/hostile/mushroom)) - return 1 - if(ispath(MP, /mob/living/simple_animal/shade)) - return 1 - if(ispath(MP, /mob/living/simple_animal/tomato)) - return 1 - if(ispath(MP, /mob/living/simple_animal/mouse)) - return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak) - if(ispath(MP, /mob/living/simple_animal/hostile/bear)) - return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak) - if(ispath(MP, /mob/living/simple_animal/parrot)) - return 1 //Parrots are no longer unfinished! -Nodrak - - //Not in here? Must be untested! - return 0 - - - +/mob/living/carbon/human/proc/monkeyize() + if (monkeyizing) + return + + for(var/obj/item/W in src) + if (W==w_uniform) // will be torn + continue + drop_from_inventory(W) + regenerate_icons() + dropBorers() + monkeyizing = 1 + canmove = 0 + delayNextAttack(50) + icon = null + invisibility = 101 + + for(var/t in organs) + qdel(t) + anim(target = src, a_icon = 'icons/mob/mob.dmi', flick_anim = "h2monkey", sleeptime = 15) + sleep(33) + + if(!species.primitive) //If the creature in question has no primitive set, this is going to be messy. + gib() + return + + var/mob/living/carbon/monkey/O = null + + O = new species.primitive(get_turf(src)) + + O.dna = dna.Clone() + O.dna.SetSEState(MONKEYBLOCK,1) + O.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) + O.loc = loc + O.viruses = viruses + viruses = list() + for(var/datum/disease/D in O.viruses) + D.affected_mob = O + + if (client) + client.mob = O + if(mind) + mind.transfer_to(O) + + to_chat(O, "You are now [O]. ") + + qdel(src) + + return O + +/mob/living/carbon/human/proc/Cluwneize() + if (monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + regenerate_icons() + dropBorers() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + for(var/t in organs) //this really should not be necessary + qdel(t) + + var/mob/living/simple_animal/hostile/retaliate/cluwne/new_mob = new (get_turf(src)) + new_mob.setGender(gender) + new_mob.name = pick(clown_names) + new_mob.real_name = new_mob.name + new_mob.mutations += M_CLUMSY + new_mob.mutations += M_FAT + new_mob.setBrainLoss(100) + new_mob.a_intent = I_HURT + new_mob.key = key + + to_chat(new_mob, "Instantly, what was your clothes fall off, and are replaced with a mockery of all that is clowning; Disgusting-looking garb that the foulest of creatures would be afraid of wearing. Your very face begins to shape, mold, into something truely disgusting. A mask made of flesh. Your body is feeling the worst pain it has ever felt. As you think it cannot get any worse, one of your arms turns into a horrific meld of flesh and plastic, making a limb made entirely of bike horns.") + to_chat(new_mob, "Your very soul is being torn apart. What was organs, blood, flesh, is now darkness. And inside the infernal void that was once a living being, something sinister takes root. As what you were goes away, you try to let out a frantic plea of 'Help me! Please god help me!' but your god has abandoned you, and all that leaves your horrible mouth is a strangled 'HONK!'.") + new_mob.say("HONK!") + spawn(0)//To prevent the proc from returning null. + qdel(src) + return new_mob + +/mob/new_player/AIize() + spawning = 1 + return ..() + +/mob/living/carbon/human/AIize() + if (monkeyizing) + return + for(var/t in organs) + qdel(t) + + return ..() + +/mob/living/carbon/AIize() + if (monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + dropBorers() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + return ..() + +/mob/proc/AIize() + if(client) + to_chat(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = 1))// stop the jams for AIs + + var/mob/living/silicon/ai/O = new (get_turf(src), base_law_type,,1)//No MMI but safety is in effect. + O.invisibility = 0 + O.aiRestorePowerRoutine = 0 + + if(mind) + mind.transfer_to(O) + O.mind.original = O + else + O.key = key + + var/obj/loc_landmark + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if (sloc.name != "AI") + continue + if (locate(/mob/living) in sloc.loc) + continue + loc_landmark = sloc + if (!loc_landmark) + for(var/obj/effect/landmark/tripai in landmarks_list) + if (tripai.name == "tripai") + if(locate(/mob/living) in tripai.loc) + continue + loc_landmark = tripai + if (!loc_landmark) + to_chat(O, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.") + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if (sloc.name == "AI") + loc_landmark = sloc + + O.loc = loc_landmark.loc + for (var/obj/item/device/radio/intercom/comm in O.loc) + comm.ai += O + + to_chat(O, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).") + to_chat(O, "To look at other parts of the station, click on yourself to get a camera menu.") + to_chat(O, "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.") + to_chat(O, "To use something, simply click on it.") + to_chat(O, {"Use say ":b to speak to your cyborgs through binary."}) + if (!(ticker && ticker.mode && (O.mind in ticker.mode.malf_ai))) + O.show_laws() + to_chat(O, "These laws may be changed by other players, or by you being the traitor.") + + //O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle + O.verbs += /mob/living/silicon/ai/proc/show_laws_verb + //O.verbs += /mob/living/silicon/ai/proc/ai_camera_track + //O.verbs += /mob/living/silicon/ai/proc/ai_alerts + //O.verbs += /mob/living/silicon/ai/proc/ai_camera_list + O.verbs += /mob/living/silicon/ai/proc/ai_statuschange + //O.verbs += /mob/living/silicon/ai/proc/ai_roster + + O.job = "AI" + + O.rename_self("ai",1) + . = O + qdel(src) + + +//human -> robot +/mob/living/carbon/human/proc/Robotize(var/delete_items = 0) + if (monkeyizing) + return + for(var/obj/item/W in src) + if(delete_items) + qdel(W) + else + drop_from_inventory(W) + dropBorers() + regenerate_icons() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + for(var/t in organs) + qdel(t) + + var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(src)) + . = O + // cyborgs produced by Robotize get an automatic power cell + O.cell = new(O) + O.cell.maxcharge = 7500 + O.cell.charge = 7500 + + O.setGender(gender) + O.invisibility = 0 + + if(mind) //TODO + mind.transfer_to(O) + if(O.mind.assigned_role == "Cyborg") + O.mind.original = O + else if(mind&&mind.special_role) + O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") + else + O.key = key + + O.loc = loc + O.job = "Cyborg" + + O.mmi = new /obj/item/device/mmi(O) + O.mmi.transfer_identity(src)//Does not transfer key/client. + + spawn() O.Namepick() + + spawn(0)//To prevent the proc from returning null. + qdel(src) + + +//human -> mommi +/mob/living/carbon/human/proc/MoMMIfy(round_start = 0) + if (monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + dropBorers() + regenerate_icons() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + for(var/t in organs) + qdel(t) + + var/mob/living/silicon/robot/mommi/O = new /mob/living/silicon/robot/mommi(get_turf(src)) + . = O + // MoMMIs produced by Robotize get an automatic power cell + O.cell = new(O) + O.cell.maxcharge = (round_start ? 10000 : 15000) + O.cell.charge = (round_start ? 10000 : 15000) + + + O.setGender(gender) + O.invisibility = 0 + + + if(mind) //TODO + mind.transfer_to(O) + if(O.mind.assigned_role == "Cyborg") + O.mind.original = O + else if(mind && mind.special_role) + O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") + else + O.key = key + + O.loc = loc + O.job = "Cyborg" + + O.mmi = new /obj/item/device/mmi(O) + O.mmi.transfer_identity(src)//Does not transfer key/client. + + spawn() O.Namepick() + + + spawn(0)//To prevent the proc from returning null. + qdel(src) + +//human -> alien +/mob/living/carbon/human/proc/Alienize() + if (monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + dropBorers() + regenerate_icons() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + for(var/t in organs) + qdel(t) + + var/alien_caste = pick("Hunter","Sentinel","Drone") + var/mob/living/carbon/alien/humanoid/new_xeno + switch(alien_caste) + if("Hunter") + new_xeno = new /mob/living/carbon/alien/humanoid/hunter(get_turf(src)) + if("Sentinel") + new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(get_turf(src)) + if("Drone") + new_xeno = new /mob/living/carbon/alien/humanoid/drone(get_turf(src)) + + new_xeno.a_intent = I_HURT + new_xeno.key = key + + to_chat(new_xeno, "You are now an alien.") + spawn(0)//To prevent the proc from returning null. + qdel(src) + return new_xeno + +/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num) + if (monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + dropBorers() + regenerate_icons() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + for(var/t in organs) + qdel(t) + + var/mob/living/carbon/slime/new_slime + if(reproduce) + var/number = pick(14;2,3,4) //reproduce (has a small chance of producing 3 or 4 offspring) + var/list/babies = list() + for(var/i=1,i<=number,i++) + var/mob/living/carbon/slime/M = new/mob/living/carbon/slime(get_turf(src)) + M.nutrition = round(nutrition/number) + step_away(M,src) + babies += M + new_slime = pick(babies) + else + if(adult) + new_slime = new /mob/living/carbon/slime/adult(get_turf(src)) + else + new_slime = new /mob/living/carbon/slime(get_turf(src)) + new_slime.a_intent = I_HURT + new_slime.key = key + + to_chat(new_slime, "You are now a slime. Skreee!") + spawn(0)//To prevent the proc from returning null. + qdel(src) + return new_slime + +/mob/living/carbon/human/proc/corgize() + if (monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + dropBorers() + regenerate_icons() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + for(var/t in organs) //this really should not be necessary + qdel(t) + + var/mob/living/simple_animal/corgi/new_corgi = new /mob/living/simple_animal/corgi (get_turf(src)) + new_corgi.a_intent = I_HURT + new_corgi.key = key + + to_chat(new_corgi, "You are now a Corgi. Yap Yap!") + spawn(0)//To prevent the proc from returning null. + qdel(src) + return new_corgi + +/mob/living/carbon/human/Animalize() + + var/list/mobtypes = typesof(/mob/living/simple_animal) + var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes + + if(!safe_animal(mobpath)) + to_chat(usr, "Sorry but this mob type is currently unavailable.") + return + + if(monkeyizing) + return + for(var/obj/item/W in src) + drop_from_inventory(W) + dropBorers() + + regenerate_icons() + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + delayNextAttack(50) + + for(var/t in organs) + qdel(t) + + var/mob/new_mob = new mobpath(get_turf(src)) + + new_mob.key = key + new_mob.a_intent = I_HURT + + + to_chat(new_mob, "You suddenly feel more... animalistic.") + spawn() + qdel(src) + return new_mob + +/mob/proc/Animalize() + + + var/list/mobtypes = typesof(/mob/living/simple_animal) + var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes + + if(!safe_animal(mobpath)) + to_chat(usr, "Sorry but this mob type is currently unavailable.") + return + + var/mob/new_mob = new mobpath(get_turf(src)) + + new_mob.key = key + new_mob.a_intent = I_HURT + to_chat(new_mob, "You feel more... animalistic") + + spawn() + qdel(src) + return new_mob + +/* Certain mob types have problems and should not be allowed to be controlled by players. + * + * This proc is here to force coders to manually place their mob in this list, hopefully tested. + * This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them. + */ +/mob/proc/safe_animal(var/MP) + +//Bad mobs! - Remember to add a comment explaining what's wrong with the mob + if(!MP) + return 0 //Sanity, this should never happen. + + if(ispath(MP, /mob/living/simple_animal/space_worm)) + return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning. + + if(ispath(MP, /mob/living/simple_animal/construct/behemoth)) + return 0 //I think this may have been an unfinished WiP or something. These constructs should really have their own class simple_animal/construct/subtype + + if(ispath(MP, /mob/living/simple_animal/construct/armoured)) + return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype + + if(ispath(MP, /mob/living/simple_animal/construct/wraith)) + return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype + + if(ispath(MP, /mob/living/simple_animal/construct/builder)) + return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype + +//Good mobs! + if(ispath(MP, /mob/living/simple_animal/cat)) + return 1 + if(ispath(MP, /mob/living/simple_animal/corgi)) + return 1 + if(ispath(MP, /mob/living/simple_animal/crab)) + return 1 + if(ispath(MP, /mob/living/simple_animal/hostile/carp)) + return 1 + if(ispath(MP, /mob/living/simple_animal/hostile/mushroom)) + return 1 + if(ispath(MP, /mob/living/simple_animal/shade)) + return 1 + if(ispath(MP, /mob/living/simple_animal/tomato)) + return 1 + if(ispath(MP, /mob/living/simple_animal/mouse)) + return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak) + if(ispath(MP, /mob/living/simple_animal/hostile/bear)) + return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak) + if(ispath(MP, /mob/living/simple_animal/parrot)) + return 1 //Parrots are no longer unfinished! -Nodrak + + //Not in here? Must be untested! + return 0 + + + diff --git a/code/modules/mob/update_icons.dm b/code/modules/mob/update_icons.dm index f4c10c9bc2f..d6224199093 100644 --- a/code/modules/mob/update_icons.dm +++ b/code/modules/mob/update_icons.dm @@ -1,70 +1,70 @@ -//Most of these are defined at this level to reduce on checks elsewhere in the code. -//Having them here also makes for a nice reference list of the various overlay-updating procs available - -/mob/proc/regenerate_icons() //TODO: phase this out completely if possible - return - -/mob/proc/update_icons() - return - -/mob/proc/update_hud() - return - -/mob/proc/update_inv_handcuffed() - return - -/mob/proc/update_inv_legcuffed() - return - -/mob/proc/update_inv_back() - return - -/mob/proc/update_inv_l_hand() - return - -/mob/proc/update_inv_r_hand() - return - -/mob/proc/update_inv_wear_mask() - return - -/mob/proc/update_inv_wear_suit() - return - -/mob/proc/update_inv_w_uniform() - return - -/mob/proc/update_inv_belt() - return - -/mob/proc/update_inv_head() - return - -/mob/proc/update_inv_gloves() - return - -/mob/proc/update_mutations() - return - -/mob/proc/update_inv_wear_id() - return - -/mob/proc/update_inv_shoes() - return - -/mob/proc/update_inv_glasses() - return - -/mob/proc/update_inv_s_store() - return - -/mob/proc/update_inv_pockets() - return - -/mob/proc/update_inv_ears() - return - -/mob/proc/update_targeted() - return - -/mob/proc/update_transform() +//Most of these are defined at this level to reduce on checks elsewhere in the code. +//Having them here also makes for a nice reference list of the various overlay-updating procs available + +/mob/proc/regenerate_icons() //TODO: phase this out completely if possible + return + +/mob/proc/update_icons() + return + +/mob/proc/update_hud() + return + +/mob/proc/update_inv_handcuffed() + return + +/mob/proc/update_inv_legcuffed() + return + +/mob/proc/update_inv_back() + return + +/mob/proc/update_inv_l_hand() + return + +/mob/proc/update_inv_r_hand() + return + +/mob/proc/update_inv_wear_mask() + return + +/mob/proc/update_inv_wear_suit() + return + +/mob/proc/update_inv_w_uniform() + return + +/mob/proc/update_inv_belt() + return + +/mob/proc/update_inv_head() + return + +/mob/proc/update_inv_gloves() + return + +/mob/proc/update_mutations() + return + +/mob/proc/update_inv_wear_id() + return + +/mob/proc/update_inv_shoes() + return + +/mob/proc/update_inv_glasses() + return + +/mob/proc/update_inv_s_store() + return + +/mob/proc/update_inv_pockets() + return + +/mob/proc/update_inv_ears() + return + +/mob/proc/update_targeted() + return + +/mob/proc/update_transform() diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index e856ee50eae..7e6bda0ed5d 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -1,502 +1,502 @@ -/* Photography! - * Contains: - * Camera - * Camera Film - * Photos - * Photo Albums - */ - -/* - * Film - */ -/obj/item/device/camera_film - name = "film cartridge" - icon = 'icons/obj/items.dmi' - desc = "A camera film cartridge. Insert it into a camera to reload it." - icon_state = "film" - item_state = "electropack" - w_class = 1.0 - origin_tech = "materials=1;programming=1" - - -/* - * Photo - */ -/obj/item/weapon/photo - name = "photo" - icon = 'icons/obj/items.dmi' - icon_state = "photo" - item_state = "paper" - w_class = 1.0 - var/icon/img //Big photo image - var/scribble //Scribble on the back. - var/blueprints = 0 //Does it include the blueprints? - var/info //Info on the camera about mobs or some shit - - autoignition_temperature = 530 // Kelvin - fire_fuel = 1 - - -/obj/item/weapon/photo/attack_self(mob/user) - show(user) - - -/obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user) - if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon)) - var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null) as text) - txt = copytext(txt, 1, 128) - if(Adjacent(user) && !user.stat) - scribble = txt - ..() - - -/obj/item/weapon/photo/examine(mob/user) - if(Adjacent(user)) - show(user) - else - ..() - to_chat(user, "You can't make out the picture from here.") - - -/obj/item/weapon/photo/proc/show(mob/user) - user << browse_rsc(img, "tmp_photo.png") - user << browse("[name]" \ - + "" \ - + "" \ - + "[scribble ? "
    Written on the back:
    [scribble]" : ""]"\ - + "", "window=book;size=192x[scribble ? 400 : 192]") - if(info) //Would rather not display a blank line of text - to_chat(user, info) - onclose(user, "[name]") - - -/obj/item/weapon/photo/verb/rename() - set name = "Rename photo" - set category = "Object" - set src in usr - - var/n_name = copytext(sanitize(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text), 1, MAX_NAME_LEN) - //loc.loc check is for making possible renaming photos in clipboards - if(!usr.isUnconscious() && Adjacent(usr)) - name = "photo[(n_name ? text("- '[n_name]'") : null)]" - add_fingerprint(usr) - - -/* - * Photo album - */ -/obj/item/weapon/storage/photo_album - name = "photo album" - icon = 'icons/obj/items.dmi' - icon_state = "album" - item_state = "briefcase" - can_hold = list("/obj/item/weapon/photo",) - - -/* - * Camera - */ -/obj/item/device/camera - name = "camera" - icon = 'icons/obj/items.dmi' - desc = "A polaroid camera." - icon_state = "polaroid" - item_state = "polaroid" - w_class = 2.0 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - origin_tech = "materials=1;programming=1" - starting_materials = list(MAT_IRON = 2000) - w_type = RECYK_ELECTRONIC - min_harm_label = 3 - harm_label_examine = list("A tiny label is on the lens.", "A label covers the lens!") - var/pictures_max = 10 - var/pictures_left = 10 - var/on = 1 - var/icon_on = "camera" - var/icon_off = "camera_off" - var/blueprints = 0 //are blueprints visible in the current photo being created? - var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info - -/obj/item/device/camera/sepia - name = "camera" - desc = "This one takes pictures in sepia." - icon_state = "sepia-polaroid" - item_state = "sepia-polaroid" - icon_on = "sepia-camera" - icon_off = "sepia-camera_off" - mech_flags = MECH_SCAN_FAIL - -/obj/item/device/camera/examine(mob/user) - ..() - to_chat(user, "It has [pictures_left] photos left.") - - -/obj/item/device/camera/ai_camera //camera AI can take pictures with - name = "AI photo camera" - var/in_camera_mode = 0 -/* - verb/picture() - set category ="AI Commands" - set name = "Take Image" - set src in usr - - toggle_camera_mode() - - verb/viewpicture() - set category ="AI Commands" - set name = "View Images" - set src in usr - - viewpictures() -*/ - - -/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user) - return - - -/obj/item/device/camera/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/device/camera_film)) - if(pictures_left) - to_chat(user, "[src] still has some film in it!") - return - - if(user.drop_item(I)) - to_chat(user, "You insert [I] into [src].") - - qdel(I) - pictures_left = pictures_max - icon_state = icon_on - on = 1 - return - ..() - - -/obj/item/device/camera/proc/camera_get_icon(list/turfs, turf/center) - var/atoms[] = list() - for(var/turf/T in turfs) - atoms.Add(T) - for(var/atom/movable/A in T) - if(A.invisibility) - continue - atoms.Add(A) - - var/list/sorted = list() - var/j - for(var/i = 1 to atoms.len) - var/atom/c = atoms[i] - for(j = sorted.len, j > 0, --j) - var/atom/c2 = sorted[j] - if(c2.layer <= c.layer) - break - sorted.Insert(j+1, c) - - var/icon/res = icon('icons/effects/96x96.dmi', "") - - for(var/atom/A in sorted) - var/icon/img = getFlatIcon(A,A.dir,0) - if(istype(A, /mob/living) && A:lying) - img.Turn(A:lying) - - var/offX = 32 * (A.x - center.x) + A.pixel_x + 33 - var/offY = 32 * (A.y - center.y) + A.pixel_y + 33 - if(istype(A, /atom/movable)) - offX += A:step_x - offY += A:step_y - - res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY) - - if(istype(A, /obj/item/blueprints)) - blueprints = 1 - - /* - for(var/turf/T in turfs) - res.Blend(getFlatIcon(T.loc), blendMode2iconMode(T.blend_mode), 32 * (T.x - center.x) + 33, 32 * (T.y - center.y) + 33) - //Turfs are atoms as well, duh, they render perfectly well without that part of the code. Plus that part was causing tiles with colored lightning to appear all white. - */ - - return res - - -/obj/item/device/camera/sepia/camera_get_icon(list/turfs, turf/center) - var/atoms[] = list() - for(var/turf/T in turfs) - atoms.Add(T) - for(var/atom/movable/A in T) - if(A.invisibility != 0) - if(istype(A, /mob/)) - atoms.Add(A) - else - atoms.Add(A) - - var/list/sorted = list() - var/j - for(var/i = 1 to atoms.len) - var/atom/c = atoms[i] - for(j = sorted.len, j > 0, --j) - var/atom/c2 = sorted[j] - if(c2.layer <= c.layer) - break - sorted.Insert(j+1, c) - - var/icon/res = icon('icons/effects/96x96.dmi', "") - - for(var/atom/A in sorted) - var/icon/img = getFlatIcon(A,A.dir,0) - if(istype(A, /mob/living) && A:lying) - img.Turn(A:lying) - - var/offX = 32 * (A.x - center.x) + A.pixel_x + 33 - var/offY = 32 * (A.y - center.y) + A.pixel_y + 33 - if(istype(A, /atom/movable)) - offX += A:step_x - offY += A:step_y - - res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY) - - if(istype(A, /obj/item/blueprints)) - blueprints = 1 - - /* - for(var/turf/T in turfs) - res.Blend(getFlatIcon(T.loc), blendMode2iconMode(T.blend_mode), 32 * (T.x - center.x) + 33, 32 * (T.y - center.y) + 33) - //Turfs are atoms as well, duh, they render perfectly well without that part of the code. Plus that part was causing tiles with colored lightning to appear all white. - */ - - return res - - -/obj/item/device/camera/proc/camera_get_mobs(turf/the_turf) - var/mob_detail - for(var/mob/living/carbon/A in the_turf) - if(A.invisibility) continue - var/holding = null - if(A.l_hand || A.r_hand) - if(A.l_hand) holding = "They are holding \a [A.l_hand]" - if(A.r_hand) - if(holding) - holding += " and \a [A.r_hand]" - else - holding = "They are holding \a [A.r_hand]" - - if(!mob_detail) - mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " - else - mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." - for(var/mob/living/simple_animal/S in the_turf) - if(S.invisibility != 0) continue - if(!mob_detail) - mob_detail = "You can see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." - else - mob_detail += "You can also see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." - for(var/mob/dead/observer/O in the_turf)//in case ghosts have been made visible - if(O.invisibility != 0) continue - if(!mob_detail) - mob_detail = "Wait...is that [O] on the photo? " - else - mob_detail += "...wait a minute...isn't that [O] on the photo?" - return mob_detail - - -/obj/item/device/camera/sepia/camera_get_mobs(turf/the_turf) - var/mob_detail - for(var/mob/living/carbon/A in the_turf) - var/holding = null - if(A.l_hand || A.r_hand) - if(A.l_hand) holding = "They are holding \a [A.l_hand]" - if(A.r_hand) - if(holding) - holding += " and \a [A.r_hand]" - else - holding = "They are holding \a [A.r_hand]" - - if(!mob_detail) - mob_detail = "You can see [A] on the photo[A.health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " - else - mob_detail += "You can also see [A] on the photo[A.health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." - for(var/mob/living/simple_animal/S in the_turf) - if(!mob_detail) - mob_detail = "You can see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." - else - mob_detail += "You can also see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." - for(var/mob/dead/observer/O in the_turf) - if(!mob_detail) - mob_detail = "Wait...is that [O] on the photo? " - else - mob_detail += "...wait a minute...isn't that [O] on the photo?" - - return mob_detail - - -/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) //Proc for both regular and AI-based camera to take the image - if(min_harm_label && harm_labeled >= min_harm_label) - printpicture(user, icon('icons/effects/96x96.dmi',"blocked"), "You can't see a thing.", flag) - return - var/mobs = "" - var/list/seen - if(!isAI(user)) //crappy check, but without it AI photos would be subject to line of sight from the AI Eye object. Made the best of it by moving the sec camera check inside - if(user.client) //To make shooting through security cameras possible - seen = get_hear(world.view, user.client.eye) //To make shooting through security cameras possible - else - seen = get_hear(world.view, user) - else - seen = get_hear(world.view, target) - - var/list/turfs = list() - for(var/turf/T in range(1, target)) - if(T in seen) - if(isAI(user) && !cameranet.checkTurfVis(T)) - continue - else - turfs += T - mobs += camera_get_mobs(T) - - var/icon/temp = icon('icons/effects/96x96.dmi',"") - temp.Blend("#000", ICON_OVERLAY) - temp.Blend(camera_get_icon(turfs, target), ICON_OVERLAY) - - if(!isAI(user)) - printpicture(user, temp, mobs, flag) - else - aipicture(user, temp, mobs, blueprints) - -/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos - var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - user.put_in_hands(P) - var/icon/small_img = icon(temp) - var/icon/ic = icon('icons/obj/items.dmi',"photo") - small_img.Scale(8, 8) - ic.Blend(small_img,ICON_OVERLAY, 10, 13) - P.icon = ic - P.img = temp - P.info = mobs - P.pixel_x = rand(-10, 10) - P.pixel_y = rand(-10, 10) - - if(blueprints) - P.blueprints = 1 - blueprints = 0 - -/obj/item/device/camera/sepia/printpicture(mob/user, icon/temp, mobs, flag) //Creates photos in sepia - var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - user.put_in_hands(P) - var/icon/small_img = icon(temp) - var/icon/ic = icon('icons/obj/items.dmi',"photo") - small_img.Scale(8, 8) - ic.Blend(small_img,ICON_OVERLAY, 10, 13) - P.icon = ic - P.img = temp - P.info = mobs - P.pixel_x = rand(-10, 10) - P.pixel_y = rand(-10, 10) - - if(blueprints) - P.blueprints = 1 - blueprints = 0 - - var/icon/I1 = icon(P.icon, P.icon_state) - var/icon/I2 = icon(P.img) - - I1.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(112,66,20))//sepia magic formula - I2.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(112,66,20)) - - P.icon = I1 - P.img = I2 - -/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs) //instead of printing a picture like a regular camera would, we do this instead for the AI - - - var/icon/small_img = icon(temp) - var/icon/ic = icon('icons/obj/items.dmi',"photo") - small_img.Scale(8, 8) - ic.Blend(small_img,ICON_OVERLAY, 10, 13) - var/icon = ic - var/img = temp - var/info = mobs - var/pixel_x = rand(-10, 10) - var/pixel_y = rand(-10, 10) - - var/injectblueprints = 1 - if(blueprints) - injectblueprints = 1 - blueprints = 0 - - injectaialbum(icon, img, info, pixel_x, pixel_y, injectblueprints) - - -/datum/picture - var/name = "image" - var/list/fields = list() - - -/obj/item/device/camera/proc/injectaialbum(var/icon, var/img, var/info, var/pixel_x, var/pixel_y, var/blueprintsinject) //stores image information to a list similar to that of the datacore - var/datum/picture/P = new() - - P.fields["name"] = "\ref[P]" - P.fields["icon"] = icon - P.fields["img"] = img - P.fields["info"] = info - P.fields["pixel_x"] = pixel_x - P.fields["pixel_y"] = pixel_y - P.fields["blueprints"] = blueprintsinject - - aipictures += P - to_chat(usr, "Image recorded")//feedback to the AI player that the picture was taken - - - -/obj/item/device/camera/ai_camera/proc/viewpictures() //AI proc for viewing pictures they have taken - var/list/nametemp = list() - var/find - var/datum/picture/selection - if(src.aipictures.len == 0) - to_chat(usr, "No images saved") - return - for(var/datum/picture/t in src.aipictures) - nametemp += t.fields["name"] - find = input("Select image (listed in order taken)") in nametemp - var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - for(var/datum/picture/q in src.aipictures) - if(q.fields["name"] == find) - selection = q - break // just in case some AI decides to take 10 thousand pictures in a round - P.icon = selection.fields["icon"] - P.img = selection.fields["img"] - P.info = selection.fields["info"] - P.pixel_x = selection.fields["pixel_x"] - P.pixel_y = selection.fields["pixel_y"] - - P.show(usr) - to_chat(usr, P.info) - del P //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all. - -/obj/item/device/camera/afterattack(atom/target, mob/user, flag) - if(!on || !pictures_left || get_dist(src, target) < 1) return - captureimage(target, user, flag) - - playsound(loc, "polaroid", 75, 1, -3) - - pictures_left-- - to_chat(user, "[pictures_left] photos left.") - icon_state = icon_off - on = 0 - if(pictures_left > 0) - spawn(64) - icon_state = icon_on - on = 1 - -/obj/item/device/camera/ai_camera/proc/toggle_camera_mode() - if(in_camera_mode) - camera_mode_off() - else - camera_mode_on() - -/obj/item/device/camera/ai_camera/proc/camera_mode_off() - src.in_camera_mode = 0 - to_chat(usr, "Camera Mode deactivated") - -/obj/item/device/camera/ai_camera/proc/camera_mode_on() - src.in_camera_mode = 1 - to_chat(usr, "Camera Mode activated") +/* Photography! + * Contains: + * Camera + * Camera Film + * Photos + * Photo Albums + */ + +/* + * Film + */ +/obj/item/device/camera_film + name = "film cartridge" + icon = 'icons/obj/items.dmi' + desc = "A camera film cartridge. Insert it into a camera to reload it." + icon_state = "film" + item_state = "electropack" + w_class = 1.0 + origin_tech = "materials=1;programming=1" + + +/* + * Photo + */ +/obj/item/weapon/photo + name = "photo" + icon = 'icons/obj/items.dmi' + icon_state = "photo" + item_state = "paper" + w_class = 1.0 + var/icon/img //Big photo image + var/scribble //Scribble on the back. + var/blueprints = 0 //Does it include the blueprints? + var/info //Info on the camera about mobs or some shit + + autoignition_temperature = 530 // Kelvin + fire_fuel = 1 + + +/obj/item/weapon/photo/attack_self(mob/user) + show(user) + + +/obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user) + if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon)) + var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null) as text) + txt = copytext(txt, 1, 128) + if(Adjacent(user) && !user.stat) + scribble = txt + ..() + + +/obj/item/weapon/photo/examine(mob/user) + if(Adjacent(user)) + show(user) + else + ..() + to_chat(user, "You can't make out the picture from here.") + + +/obj/item/weapon/photo/proc/show(mob/user) + user << browse_rsc(img, "tmp_photo.png") + user << browse("[name]" \ + + "" \ + + "" \ + + "[scribble ? "
    Written on the back:
    [scribble]" : ""]"\ + + "", "window=book;size=192x[scribble ? 400 : 192]") + if(info) //Would rather not display a blank line of text + to_chat(user, info) + onclose(user, "[name]") + + +/obj/item/weapon/photo/verb/rename() + set name = "Rename photo" + set category = "Object" + set src in usr + + var/n_name = copytext(sanitize(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text), 1, MAX_NAME_LEN) + //loc.loc check is for making possible renaming photos in clipboards + if(!usr.isUnconscious() && Adjacent(usr)) + name = "photo[(n_name ? text("- '[n_name]'") : null)]" + add_fingerprint(usr) + + +/* + * Photo album + */ +/obj/item/weapon/storage/photo_album + name = "photo album" + icon = 'icons/obj/items.dmi' + icon_state = "album" + item_state = "briefcase" + can_hold = list("/obj/item/weapon/photo",) + + +/* + * Camera + */ +/obj/item/device/camera + name = "camera" + icon = 'icons/obj/items.dmi' + desc = "A polaroid camera." + icon_state = "polaroid" + item_state = "polaroid" + w_class = 2.0 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + origin_tech = "materials=1;programming=1" + starting_materials = list(MAT_IRON = 2000) + w_type = RECYK_ELECTRONIC + min_harm_label = 3 + harm_label_examine = list("A tiny label is on the lens.", "A label covers the lens!") + var/pictures_max = 10 + var/pictures_left = 10 + var/on = 1 + var/icon_on = "camera" + var/icon_off = "camera_off" + var/blueprints = 0 //are blueprints visible in the current photo being created? + var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info + +/obj/item/device/camera/sepia + name = "camera" + desc = "This one takes pictures in sepia." + icon_state = "sepia-polaroid" + item_state = "sepia-polaroid" + icon_on = "sepia-camera" + icon_off = "sepia-camera_off" + mech_flags = MECH_SCAN_FAIL + +/obj/item/device/camera/examine(mob/user) + ..() + to_chat(user, "It has [pictures_left] photos left.") + + +/obj/item/device/camera/ai_camera //camera AI can take pictures with + name = "AI photo camera" + var/in_camera_mode = 0 +/* + verb/picture() + set category ="AI Commands" + set name = "Take Image" + set src in usr + + toggle_camera_mode() + + verb/viewpicture() + set category ="AI Commands" + set name = "View Images" + set src in usr + + viewpictures() +*/ + + +/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user) + return + + +/obj/item/device/camera/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/device/camera_film)) + if(pictures_left) + to_chat(user, "[src] still has some film in it!") + return + + if(user.drop_item(I)) + to_chat(user, "You insert [I] into [src].") + + qdel(I) + pictures_left = pictures_max + icon_state = icon_on + on = 1 + return + ..() + + +/obj/item/device/camera/proc/camera_get_icon(list/turfs, turf/center) + var/atoms[] = list() + for(var/turf/T in turfs) + atoms.Add(T) + for(var/atom/movable/A in T) + if(A.invisibility) + continue + atoms.Add(A) + + var/list/sorted = list() + var/j + for(var/i = 1 to atoms.len) + var/atom/c = atoms[i] + for(j = sorted.len, j > 0, --j) + var/atom/c2 = sorted[j] + if(c2.layer <= c.layer) + break + sorted.Insert(j+1, c) + + var/icon/res = icon('icons/effects/96x96.dmi', "") + + for(var/atom/A in sorted) + var/icon/img = getFlatIcon(A,A.dir,0) + if(istype(A, /mob/living) && A:lying) + img.Turn(A:lying) + + var/offX = 32 * (A.x - center.x) + A.pixel_x + 33 + var/offY = 32 * (A.y - center.y) + A.pixel_y + 33 + if(istype(A, /atom/movable)) + offX += A:step_x + offY += A:step_y + + res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY) + + if(istype(A, /obj/item/blueprints)) + blueprints = 1 + + /* + for(var/turf/T in turfs) + res.Blend(getFlatIcon(T.loc), blendMode2iconMode(T.blend_mode), 32 * (T.x - center.x) + 33, 32 * (T.y - center.y) + 33) + //Turfs are atoms as well, duh, they render perfectly well without that part of the code. Plus that part was causing tiles with colored lightning to appear all white. + */ + + return res + + +/obj/item/device/camera/sepia/camera_get_icon(list/turfs, turf/center) + var/atoms[] = list() + for(var/turf/T in turfs) + atoms.Add(T) + for(var/atom/movable/A in T) + if(A.invisibility != 0) + if(istype(A, /mob/)) + atoms.Add(A) + else + atoms.Add(A) + + var/list/sorted = list() + var/j + for(var/i = 1 to atoms.len) + var/atom/c = atoms[i] + for(j = sorted.len, j > 0, --j) + var/atom/c2 = sorted[j] + if(c2.layer <= c.layer) + break + sorted.Insert(j+1, c) + + var/icon/res = icon('icons/effects/96x96.dmi', "") + + for(var/atom/A in sorted) + var/icon/img = getFlatIcon(A,A.dir,0) + if(istype(A, /mob/living) && A:lying) + img.Turn(A:lying) + + var/offX = 32 * (A.x - center.x) + A.pixel_x + 33 + var/offY = 32 * (A.y - center.y) + A.pixel_y + 33 + if(istype(A, /atom/movable)) + offX += A:step_x + offY += A:step_y + + res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY) + + if(istype(A, /obj/item/blueprints)) + blueprints = 1 + + /* + for(var/turf/T in turfs) + res.Blend(getFlatIcon(T.loc), blendMode2iconMode(T.blend_mode), 32 * (T.x - center.x) + 33, 32 * (T.y - center.y) + 33) + //Turfs are atoms as well, duh, they render perfectly well without that part of the code. Plus that part was causing tiles with colored lightning to appear all white. + */ + + return res + + +/obj/item/device/camera/proc/camera_get_mobs(turf/the_turf) + var/mob_detail + for(var/mob/living/carbon/A in the_turf) + if(A.invisibility) continue + var/holding = null + if(A.l_hand || A.r_hand) + if(A.l_hand) holding = "They are holding \a [A.l_hand]" + if(A.r_hand) + if(holding) + holding += " and \a [A.r_hand]" + else + holding = "They are holding \a [A.r_hand]" + + if(!mob_detail) + mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " + else + mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." + for(var/mob/living/simple_animal/S in the_turf) + if(S.invisibility != 0) continue + if(!mob_detail) + mob_detail = "You can see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." + else + mob_detail += "You can also see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." + for(var/mob/dead/observer/O in the_turf)//in case ghosts have been made visible + if(O.invisibility != 0) continue + if(!mob_detail) + mob_detail = "Wait...is that [O] on the photo? " + else + mob_detail += "...wait a minute...isn't that [O] on the photo?" + return mob_detail + + +/obj/item/device/camera/sepia/camera_get_mobs(turf/the_turf) + var/mob_detail + for(var/mob/living/carbon/A in the_turf) + var/holding = null + if(A.l_hand || A.r_hand) + if(A.l_hand) holding = "They are holding \a [A.l_hand]" + if(A.r_hand) + if(holding) + holding += " and \a [A.r_hand]" + else + holding = "They are holding \a [A.r_hand]" + + if(!mob_detail) + mob_detail = "You can see [A] on the photo[A.health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. " + else + mob_detail += "You can also see [A] on the photo[A.health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." + for(var/mob/living/simple_animal/S in the_turf) + if(!mob_detail) + mob_detail = "You can see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." + else + mob_detail += "You can also see [S] on the photo[S.health < (S.maxHealth/2) ? " - [S] looks hurt":""]." + for(var/mob/dead/observer/O in the_turf) + if(!mob_detail) + mob_detail = "Wait...is that [O] on the photo? " + else + mob_detail += "...wait a minute...isn't that [O] on the photo?" + + return mob_detail + + +/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) //Proc for both regular and AI-based camera to take the image + if(min_harm_label && harm_labeled >= min_harm_label) + printpicture(user, icon('icons/effects/96x96.dmi',"blocked"), "You can't see a thing.", flag) + return + var/mobs = "" + var/list/seen + if(!isAI(user)) //crappy check, but without it AI photos would be subject to line of sight from the AI Eye object. Made the best of it by moving the sec camera check inside + if(user.client) //To make shooting through security cameras possible + seen = get_hear(world.view, user.client.eye) //To make shooting through security cameras possible + else + seen = get_hear(world.view, user) + else + seen = get_hear(world.view, target) + + var/list/turfs = list() + for(var/turf/T in range(1, target)) + if(T in seen) + if(isAI(user) && !cameranet.checkTurfVis(T)) + continue + else + turfs += T + mobs += camera_get_mobs(T) + + var/icon/temp = icon('icons/effects/96x96.dmi',"") + temp.Blend("#000", ICON_OVERLAY) + temp.Blend(camera_get_icon(turfs, target), ICON_OVERLAY) + + if(!isAI(user)) + printpicture(user, temp, mobs, flag) + else + aipicture(user, temp, mobs, blueprints) + +/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + user.put_in_hands(P) + var/icon/small_img = icon(temp) + var/icon/ic = icon('icons/obj/items.dmi',"photo") + small_img.Scale(8, 8) + ic.Blend(small_img,ICON_OVERLAY, 10, 13) + P.icon = ic + P.img = temp + P.info = mobs + P.pixel_x = rand(-10, 10) + P.pixel_y = rand(-10, 10) + + if(blueprints) + P.blueprints = 1 + blueprints = 0 + +/obj/item/device/camera/sepia/printpicture(mob/user, icon/temp, mobs, flag) //Creates photos in sepia + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + user.put_in_hands(P) + var/icon/small_img = icon(temp) + var/icon/ic = icon('icons/obj/items.dmi',"photo") + small_img.Scale(8, 8) + ic.Blend(small_img,ICON_OVERLAY, 10, 13) + P.icon = ic + P.img = temp + P.info = mobs + P.pixel_x = rand(-10, 10) + P.pixel_y = rand(-10, 10) + + if(blueprints) + P.blueprints = 1 + blueprints = 0 + + var/icon/I1 = icon(P.icon, P.icon_state) + var/icon/I2 = icon(P.img) + + I1.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(112,66,20))//sepia magic formula + I2.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(112,66,20)) + + P.icon = I1 + P.img = I2 + +/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs) //instead of printing a picture like a regular camera would, we do this instead for the AI + + + var/icon/small_img = icon(temp) + var/icon/ic = icon('icons/obj/items.dmi',"photo") + small_img.Scale(8, 8) + ic.Blend(small_img,ICON_OVERLAY, 10, 13) + var/icon = ic + var/img = temp + var/info = mobs + var/pixel_x = rand(-10, 10) + var/pixel_y = rand(-10, 10) + + var/injectblueprints = 1 + if(blueprints) + injectblueprints = 1 + blueprints = 0 + + injectaialbum(icon, img, info, pixel_x, pixel_y, injectblueprints) + + +/datum/picture + var/name = "image" + var/list/fields = list() + + +/obj/item/device/camera/proc/injectaialbum(var/icon, var/img, var/info, var/pixel_x, var/pixel_y, var/blueprintsinject) //stores image information to a list similar to that of the datacore + var/datum/picture/P = new() + + P.fields["name"] = "\ref[P]" + P.fields["icon"] = icon + P.fields["img"] = img + P.fields["info"] = info + P.fields["pixel_x"] = pixel_x + P.fields["pixel_y"] = pixel_y + P.fields["blueprints"] = blueprintsinject + + aipictures += P + to_chat(usr, "Image recorded")//feedback to the AI player that the picture was taken + + + +/obj/item/device/camera/ai_camera/proc/viewpictures() //AI proc for viewing pictures they have taken + var/list/nametemp = list() + var/find + var/datum/picture/selection + if(src.aipictures.len == 0) + to_chat(usr, "No images saved") + return + for(var/datum/picture/t in src.aipictures) + nametemp += t.fields["name"] + find = input("Select image (listed in order taken)") in nametemp + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + for(var/datum/picture/q in src.aipictures) + if(q.fields["name"] == find) + selection = q + break // just in case some AI decides to take 10 thousand pictures in a round + P.icon = selection.fields["icon"] + P.img = selection.fields["img"] + P.info = selection.fields["info"] + P.pixel_x = selection.fields["pixel_x"] + P.pixel_y = selection.fields["pixel_y"] + + P.show(usr) + to_chat(usr, P.info) + del P //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all. + +/obj/item/device/camera/afterattack(atom/target, mob/user, flag) + if(!on || !pictures_left || get_dist(src, target) < 1) return + captureimage(target, user, flag) + + playsound(loc, "polaroid", 75, 1, -3) + + pictures_left-- + to_chat(user, "[pictures_left] photos left.") + icon_state = icon_off + on = 0 + if(pictures_left > 0) + spawn(64) + icon_state = icon_on + on = 1 + +/obj/item/device/camera/ai_camera/proc/toggle_camera_mode() + if(in_camera_mode) + camera_mode_off() + else + camera_mode_on() + +/obj/item/device/camera/ai_camera/proc/camera_mode_off() + src.in_camera_mode = 0 + to_chat(usr, "Camera Mode deactivated") + +/obj/item/device/camera/ai_camera/proc/camera_mode_on() + src.in_camera_mode = 1 + to_chat(usr, "Camera Mode activated") diff --git a/code/modules/power/antimatter/computer.dm b/code/modules/power/antimatter/computer.dm index 9e15ce72a02..4da10fd830c 100644 --- a/code/modules/power/antimatter/computer.dm +++ b/code/modules/power/antimatter/computer.dm @@ -1,96 +1,96 @@ -//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:05 -#define STATE_DEFAULT 1 -#define STATE_INJECTOR 2 -#define STATE_ENGINE 3 - - -/obj/machinery/computer/am_engine - name = "Antimatter Engine Console" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "comm_computer" - req_access = list(ACCESS_ENGINE) - var/engine_id = 0 - var/authenticated = 0 - var/obj/machinery/power/am_engine/engine/connected_E = null - var/obj/machinery/power/am_engine/injector/connected_I = null - var/state = STATE_DEFAULT - -/obj/machinery/computer/am_engine/New() - ..() - spawn( 24 ) - for(var/obj/machinery/power/am_engine/engine/E in power_machines) - if(E.engine_id == src.engine_id) - src.connected_E = E - for(var/obj/machinery/power/am_engine/injector/I in power_machines) - if(I.engine_id == src.engine_id) - src.connected_I = I - return - -/obj/machinery/computer/am_engine/Topic(href, href_list) - if(..()) - return - usr.machine = src - - if(!href_list["operation"]) - return - switch(href_list["operation"]) - // main interface - if("activate") - src.connected_E.engine_process() - if("engine") - src.state = STATE_ENGINE - if("injector") - src.state = STATE_INJECTOR - if("main") - src.state = STATE_DEFAULT - if("login") - var/mob/M = usr - var/obj/item/weapon/card/id/I = M.equipped() - if (I && istype(I)) - if(src.check_access(I)) - authenticated = 1 - if("deactivate") - src.connected_E.stopping = 1 - if("logout") - authenticated = 0 - - src.updateUsrDialog() - -/obj/machinery/computer/am_engine/attack_ai(var/mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/am_engine/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/am_engine/attack_hand(var/mob/user as mob) - if(..()) - return - user.machine = src - var/dat = "Engine Computer" - switch(src.state) - if(STATE_DEFAULT) - if (src.authenticated) - dat += "
    \[ Log Out \]
    " - dat += "
    \[ Engine Menu \]" - dat += "
    \[ Injector Menu \]" - else - dat += "
    \[ Log In \]" - if(STATE_INJECTOR) - if(src.connected_I.injecting) - dat += "
    \[ Injecting \]
    " - else - dat += "
    \[ Injecting not in progress \]
    " - if(STATE_ENGINE) - if(src.connected_E.stopping) - dat += "
    \[ STOPPING \]" - else if(src.connected_E.operating && !src.connected_E.stopping) - dat += "
    \[ Emergency Stop \]" - else - dat += "
    \[ Activate Engine \]" - dat += "
    Contents:
    [src.connected_E.H_fuel]kg of Hydrogen
    [src.connected_E.antiH_fuel]kg of Anti-Hydrogen
    " - - dat += "
    \[ [(src.state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" - user << browse(dat, "window=communications;size=400x500") - onclose(user, "communications") - +//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:05 +#define STATE_DEFAULT 1 +#define STATE_INJECTOR 2 +#define STATE_ENGINE 3 + + +/obj/machinery/computer/am_engine + name = "Antimatter Engine Console" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "comm_computer" + req_access = list(ACCESS_ENGINE) + var/engine_id = 0 + var/authenticated = 0 + var/obj/machinery/power/am_engine/engine/connected_E = null + var/obj/machinery/power/am_engine/injector/connected_I = null + var/state = STATE_DEFAULT + +/obj/machinery/computer/am_engine/New() + ..() + spawn( 24 ) + for(var/obj/machinery/power/am_engine/engine/E in power_machines) + if(E.engine_id == src.engine_id) + src.connected_E = E + for(var/obj/machinery/power/am_engine/injector/I in power_machines) + if(I.engine_id == src.engine_id) + src.connected_I = I + return + +/obj/machinery/computer/am_engine/Topic(href, href_list) + if(..()) + return + usr.machine = src + + if(!href_list["operation"]) + return + switch(href_list["operation"]) + // main interface + if("activate") + src.connected_E.engine_process() + if("engine") + src.state = STATE_ENGINE + if("injector") + src.state = STATE_INJECTOR + if("main") + src.state = STATE_DEFAULT + if("login") + var/mob/M = usr + var/obj/item/weapon/card/id/I = M.equipped() + if (I && istype(I)) + if(src.check_access(I)) + authenticated = 1 + if("deactivate") + src.connected_E.stopping = 1 + if("logout") + authenticated = 0 + + src.updateUsrDialog() + +/obj/machinery/computer/am_engine/attack_ai(var/mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/am_engine/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/am_engine/attack_hand(var/mob/user as mob) + if(..()) + return + user.machine = src + var/dat = "Engine Computer" + switch(src.state) + if(STATE_DEFAULT) + if (src.authenticated) + dat += "
    \[ Log Out \]
    " + dat += "
    \[ Engine Menu \]" + dat += "
    \[ Injector Menu \]" + else + dat += "
    \[ Log In \]" + if(STATE_INJECTOR) + if(src.connected_I.injecting) + dat += "
    \[ Injecting \]
    " + else + dat += "
    \[ Injecting not in progress \]
    " + if(STATE_ENGINE) + if(src.connected_E.stopping) + dat += "
    \[ STOPPING \]" + else if(src.connected_E.operating && !src.connected_E.stopping) + dat += "
    \[ Emergency Stop \]" + else + dat += "
    \[ Activate Engine \]" + dat += "
    Contents:
    [src.connected_E.H_fuel]kg of Hydrogen
    [src.connected_E.antiH_fuel]kg of Anti-Hydrogen
    " + + dat += "
    \[ [(src.state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" + user << browse(dat, "window=communications;size=400x500") + onclose(user, "communications") + diff --git a/code/modules/power/antimatter/containment_jar.dm b/code/modules/power/antimatter/containment_jar.dm index b55eb3a5fa7..a412f0f827b 100644 --- a/code/modules/power/antimatter/containment_jar.dm +++ b/code/modules/power/antimatter/containment_jar.dm @@ -1,44 +1,44 @@ -/obj/item/weapon/am_containment - name = "antimatter containment jar" - desc = "Holds antimatter." - icon = 'icons/obj/machines/antimatter.dmi' - icon_state = "jar" - density = 0 - anchored = 0 - force = 8 - throwforce = 10 - throw_speed = 1 - throw_range = 2 - - var/fuel = 1000 // WAS ORIGINALLY 10000 - var/fuel_max = 1000//Lets try this for now - var/stability = 100//TODO: add all the stability things to this so its not very safe if you keep hitting in on things - var/exploded = 0 - -/obj/item/weapon/am_containment/proc/boom() - var/percent = 0 - if(fuel) - percent = (fuel / fuel_max) * 100 - if(!exploded && percent >= 10) - explosion(get_turf(src), 1, 2, 3, 5)//Should likely be larger but this works fine for now I guess - exploded=1 - if(src) qdel(src) - -/obj/item/weapon/am_containment/ex_act(severity) - switch(severity) - if(1.0) - boom() - if(2.0) - if(prob((fuel/10)-stability)) - boom() - stability -= 40 - if(3.0) - stability -= 20 - //check_stability() - return - -/obj/item/weapon/am_containment/proc/usefuel(var/wanted) - if(fuel < wanted) - wanted = fuel - fuel -= wanted +/obj/item/weapon/am_containment + name = "antimatter containment jar" + desc = "Holds antimatter." + icon = 'icons/obj/machines/antimatter.dmi' + icon_state = "jar" + density = 0 + anchored = 0 + force = 8 + throwforce = 10 + throw_speed = 1 + throw_range = 2 + + var/fuel = 1000 // WAS ORIGINALLY 10000 + var/fuel_max = 1000//Lets try this for now + var/stability = 100//TODO: add all the stability things to this so its not very safe if you keep hitting in on things + var/exploded = 0 + +/obj/item/weapon/am_containment/proc/boom() + var/percent = 0 + if(fuel) + percent = (fuel / fuel_max) * 100 + if(!exploded && percent >= 10) + explosion(get_turf(src), 1, 2, 3, 5)//Should likely be larger but this works fine for now I guess + exploded=1 + if(src) qdel(src) + +/obj/item/weapon/am_containment/ex_act(severity) + switch(severity) + if(1.0) + boom() + if(2.0) + if(prob((fuel/10)-stability)) + boom() + stability -= 40 + if(3.0) + stability -= 20 + //check_stability() + return + +/obj/item/weapon/am_containment/proc/usefuel(var/wanted) + if(fuel < wanted) + wanted = fuel + fuel -= wanted return wanted \ No newline at end of file diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm index 33966b97de7..5e2fd8f1f55 100644 --- a/code/modules/power/antimatter/control.dm +++ b/code/modules/power/antimatter/control.dm @@ -1,388 +1,388 @@ -/obj/machinery/power/am_control_unit - name = "antimatter control unit" - desc = "This device injects antimatter into connected shielding units, the more antimatter injected the more power produced. Wrench the device to set it up." - //icon = 'icons/obj/machines/antimatter.dmi' - icon = 'icons/obj/machines/new_ame.dmi' - icon_state = "control" - var/icon_mod = "on" // on, critical, or fuck - var/old_icon_mod = "on" - anchored = 0 - density = 1 - use_power = 1 - idle_power_usage = 100 - active_power_usage = 1000 - - var/list/obj/machinery/am_shielding/linked_shielding - var/list/obj/machinery/am_shielding/linked_cores - var/obj/item/weapon/am_containment/fueljar - var/update_shield_icons = 0 - var/stability = 100 - var/exploding = 0 - var/exploded = 0 - - var/active = 0//On or not - var/fuel_injection = 2//How much fuel to inject - var/shield_icon_delay = 0//delays resetting for a short time - var/reported_core_efficiency = 0 - - var/power_cycle = 0 - var/power_cycle_delay = 4//How many ticks till produce_power is called - var/stored_core_stability = 0 - var/stored_core_stability_delay = 0 - - var/stored_power = 0//Power to deploy per tick - - -/obj/machinery/power/am_control_unit/New() - ..() - linked_shielding = list() - linked_cores = list() - - -/obj/machinery/power/am_control_unit/Destroy()//Perhaps damage and run stability checks rather than just del on the others - for(var/obj/machinery/am_shielding/AMS in linked_shielding) - AMS.control_unit = null - qdel(AMS) - for(var/obj/machinery/am_shielding/AMS in linked_cores) - AMS.control_unit = null - qdel(AMS) - qdel(fueljar) - fueljar = null - ..() - - -/obj/machinery/power/am_control_unit/process() - if(exploding && !exploded) - message_admins("AME explosion at ([x],[y],[z] - JMP) - Last touched by [fingerprintslast]",0,1) - exploded=1 - explosion(get_turf(src),8,10,12,15) - if(src) - qdel(src) - - if(update_shield_icons && !shield_icon_delay) - check_shield_icons() - update_shield_icons = 0 - - if(stat & (NOPOWER|BROKEN) || !active)//can update the icons even without power - return - - if(!fueljar)//No fuel but we are on, shutdown - toggle_power() - //Angry buzz or such here - return - - check_core_stability() - - add_avail(stored_power) - - power_cycle++ - if(power_cycle >= power_cycle_delay) - produce_power() - power_cycle = 0 - - return - - -/obj/machinery/power/am_control_unit/proc/produce_power() - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) - var/core_power = reported_core_efficiency//Effectively how much fuel we can safely deal with - if(core_power <= 0) return 0//Something is wrong - var/core_damage = 0 - var/fuel = fueljar.usefuel(fuel_injection) - - stored_power = (fuel/core_power)*fuel*20000 // Was 200000, was too much. New value run past Aurx. - N3X - //Now check if the cores could deal with it safely, this is done after so you can overload for more power if needed, still a bad idea - if(fuel > (2*core_power))//More fuel has been put in than the current cores can deal with - if(prob(50))core_damage = 1//Small chance of damage - if((fuel-core_power) > 5) core_damage = 5//Now its really starting to overload the cores - if((fuel-core_power) > 10) core_damage = 20//Welp now you did it, they wont stand much of this - if(core_damage == 0) return - for(var/obj/machinery/am_shielding/AMS in linked_cores) - AMS.stability -= core_damage - AMS.check_stability(1) - playsound(get_turf(src), 'sound/effects/bang.ogg', 50, 1) - return - - -/obj/machinery/power/am_control_unit/emp_act(severity) - switch(severity) - if(1) - if(active) toggle_power() - stability -= rand(15,30) - if(2) - if(active) toggle_power() - stability -= rand(10,20) - ..() - return 0 - - -/obj/machinery/power/am_control_unit/blob_act() - stability -= 20 - if(prob(100-stability))//Might infect the rest of the machine - for(var/obj/machinery/am_shielding/AMS in linked_shielding) - AMS.blob_act() - qdel(src) - return - check_stability() - return - - -/obj/machinery/power/am_control_unit/ex_act(severity) - switch(severity) - if(1.0) - stability -= 60 - if(2.0) - stability -= 40 - if(3.0) - stability -= 20 - check_stability() - return - - -/obj/machinery/power/am_control_unit/bullet_act(var/obj/item/projectile/Proj) - if(Proj.flag != "bullet") - stability -= Proj.force - return 0 - - -/obj/machinery/power/am_control_unit/power_change() - ..() - if(stat & NOPOWER && active) - toggle_power() - return - - -/obj/machinery/power/am_control_unit/update_icon() - if(active) - icon_state = "control_[icon_mod]" - else icon_state = "control" - //No other icons for it atm - - -/obj/machinery/power/am_control_unit/attackby(obj/item/W, mob/user) - if(!istype(W) || !user) return - if(istype(W, /obj/item/weapon/wrench)) - if(!anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - user.visible_message("[user.name] secures the [src.name] to the floor.", \ - "You secure the anchor bolts to the floor.", \ - "You hear a ratchet") - src.anchored = 1 - connect_to_network() - else if(!linked_shielding.len > 0) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - user.visible_message("[user.name] unsecures the [src.name].", \ - "You remove the anchor bolts.", \ - "You hear a ratchet") - src.anchored = 0 - disconnect_from_network() - else - to_chat(user, "Once bolted and linked to a shielding unit it the [src.name] is unable to be moved!") - return - - if(istype(W, /obj/item/weapon/am_containment)) - if(fueljar) - to_chat(user, "There is already a [fueljar] inside!") - return - fueljar = W - if(user.client) - user.client.screen -= W - user.u_equip(W,1) - W.loc = src - user.update_icons() - message_admins("AME loaded with fuel by [user.real_name] ([user.key]) at ([x],[y],[z] - JMP)",0,1) - user.visible_message("[user.name] loads an [W.name] into the [src.name].", \ - "You load an [W.name].", \ - "You hear a thunk.") - return - - if(W.force >= 20) - stability -= W.force/2 - check_stability() - ..() - return - - -/obj/machinery/power/am_control_unit/attack_hand(mob/user as mob) - if(anchored) - interact(user) - return - - -/obj/machinery/power/am_control_unit/proc/add_shielding(var/obj/machinery/am_shielding/AMS, var/AMS_linking = 0) - if(!istype(AMS)) return 0 - if(!anchored) return 0 - if(!AMS_linking && !AMS.link_control(src)) return 0 - linked_shielding.Add(AMS) - update_shield_icons = 1 - return 1 - - -/obj/machinery/power/am_control_unit/proc/remove_shielding(var/obj/machinery/am_shielding/AMS) - if(!istype(AMS)) return 0 - linked_shielding.Remove(AMS) - update_shield_icons = 2 - if(active) toggle_power() - return 1 - - -/obj/machinery/power/am_control_unit/proc/check_stability()//TODO: make it break when low also might want to add a way to fix it like a part or such that can be replaced - if(stability <= 0) - qdel(src) - return - - -/obj/machinery/power/am_control_unit/proc/toggle_power() - active = !active - if(active) - use_power = 2 - visible_message("The [src.name] starts up.") - else - use_power = 1 - visible_message("The [src.name] shuts down.") - for(var/obj/machinery/am_shielding/AMS in linked_cores) - AMS.update_icon() - update_icon() - return - - -/obj/machinery/power/am_control_unit/proc/check_shield_icons()//Forces icon_update for all shields - if(shield_icon_delay) return - shield_icon_delay = 1 - if(update_shield_icons == 2)//2 means to clear everything and rebuild - for(var/obj/machinery/am_shielding/AMS in linked_shielding) - if(AMS.processing) AMS.shutdown_core() - AMS.control_unit = null - spawn(10) - AMS.controllerscan() - linked_shielding = list() - - else - for(var/obj/machinery/am_shielding/AMS in linked_shielding) - AMS.update_icon() - sleep(20) - shield_icon_delay = 0 - - -/obj/machinery/power/am_control_unit/proc/check_core_stability() - //if(stored_core_stability_delay || linked_cores.len <= 0) return - if(linked_cores.len <=0) return - //stored_core_stability_delay = 1 - stored_core_stability = 0 - for(var/obj/machinery/am_shielding/AMS in linked_cores) - stored_core_stability += AMS.stability - stored_core_stability/=linked_cores.len - switch(stored_core_stability) - if(0 to 24) - icon_mod="fuck" - if(25 to 49) - icon_mod="critical" - if(50 to INFINITY) - icon_mod="on" - if(icon_mod!=old_icon_mod) - old_icon_mod=icon_mod - update_icon() - - //spawn(40) - // stored_core_stability_delay = 0 - return - - -/obj/machinery/power/am_control_unit/interact(mob/user) - if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) - if(!istype(user, /mob/living/silicon/ai)) - user.unset_machine() - user << browse(null, "window=AMcontrol") - return - return ui_interact(user) - - - -/obj/machinery/power/am_control_unit/ui_interact(mob/user, ui_key = "main") - if(!user) - return - - var/list/fueljar_data=null - if(fueljar) - fueljar_data=list( - "fuel"=fueljar.fuel, - "fuel_max"=fueljar.fuel_max, - "injecting"=fuel_injection - ) - - var/list/data = list( - "active" = active, - //"stability" = stability, - "linked_shields" = linked_shielding.len, - "linked_cores" = linked_cores.len, - "efficiency" = reported_core_efficiency, - "stability" = stored_core_stability, - "stored_power" = stored_power, - "fueljar" = fueljar_data, - "siliconUser" = istype(user, /mob/living/silicon), - ) - - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, ui_key) - if (!ui) - // the ui does not exist, so we'll create a new one - ui = new(user, src, ui_key, "ame.tmpl", "Antimatter Control Unit", 500, data["siliconUser"] ? 465 : 390) - // When the UI is first opened this is the data it will use - ui.set_initial_data(data) - ui.open() - // Auto update every Master Controller tick - ui.set_auto_update(1) - else - // The UI is already open so push the new data to it - ui.push_data(data) - return - - -/obj/machinery/power/am_control_unit/Topic(href, href_list) - if(..()) return 1 - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - //Ignore input if we are broken or guy is not touching us, AI can control from a ways away - if(stat & (BROKEN|NOPOWER)) - usr.unset_machine() - usr << browse(null, "window=AMcontrol") - return - - if(href_list["close"]) - usr << browse(null, "window=AMcontrol") - usr.unset_machine() - return - - if(href_list["togglestatus"]) - toggle_power() - message_admins("AME toggled [active?"on":"off"] by [usr.real_name] ([usr.key]) at ([x],[y],[z] - JMP)",0,1) - return 1 - - if(href_list["refreshicons"]) - update_shield_icons = 2 // Fuck it - return 1 - - if(href_list["ejectjar"]) - if(fueljar) - message_admins("AME fuel jar ejected by [usr.real_name] ([usr.key]) at ([x],[y],[z] - JMP)",0,1) - fueljar.loc = src.loc - fueljar = null - //fueljar.control_unit = null currently it does not care where it is - //update_icon() when we have the icon for it - return 1 - - if(href_list["set_strength"]) - var/newval = input("Enter new injection strength") as num|null - if(isnull(newval)) - return - fuel_injection=newval - fuel_injection=max(1,fuel_injection) - message_admins("AME injection strength set to [fuel_injection] by [usr.real_name] ([usr.key]) at ([x],[y],[z] - JMP)",0,1) - return 1 - - if(href_list["refreshstability"]) - check_core_stability() - return 1 - - updateDialog() +/obj/machinery/power/am_control_unit + name = "antimatter control unit" + desc = "This device injects antimatter into connected shielding units, the more antimatter injected the more power produced. Wrench the device to set it up." + //icon = 'icons/obj/machines/antimatter.dmi' + icon = 'icons/obj/machines/new_ame.dmi' + icon_state = "control" + var/icon_mod = "on" // on, critical, or fuck + var/old_icon_mod = "on" + anchored = 0 + density = 1 + use_power = 1 + idle_power_usage = 100 + active_power_usage = 1000 + + var/list/obj/machinery/am_shielding/linked_shielding + var/list/obj/machinery/am_shielding/linked_cores + var/obj/item/weapon/am_containment/fueljar + var/update_shield_icons = 0 + var/stability = 100 + var/exploding = 0 + var/exploded = 0 + + var/active = 0//On or not + var/fuel_injection = 2//How much fuel to inject + var/shield_icon_delay = 0//delays resetting for a short time + var/reported_core_efficiency = 0 + + var/power_cycle = 0 + var/power_cycle_delay = 4//How many ticks till produce_power is called + var/stored_core_stability = 0 + var/stored_core_stability_delay = 0 + + var/stored_power = 0//Power to deploy per tick + + +/obj/machinery/power/am_control_unit/New() + ..() + linked_shielding = list() + linked_cores = list() + + +/obj/machinery/power/am_control_unit/Destroy()//Perhaps damage and run stability checks rather than just del on the others + for(var/obj/machinery/am_shielding/AMS in linked_shielding) + AMS.control_unit = null + qdel(AMS) + for(var/obj/machinery/am_shielding/AMS in linked_cores) + AMS.control_unit = null + qdel(AMS) + qdel(fueljar) + fueljar = null + ..() + + +/obj/machinery/power/am_control_unit/process() + if(exploding && !exploded) + message_admins("AME explosion at ([x],[y],[z] - JMP) - Last touched by [fingerprintslast]",0,1) + exploded=1 + explosion(get_turf(src),8,10,12,15) + if(src) + qdel(src) + + if(update_shield_icons && !shield_icon_delay) + check_shield_icons() + update_shield_icons = 0 + + if(stat & (NOPOWER|BROKEN) || !active)//can update the icons even without power + return + + if(!fueljar)//No fuel but we are on, shutdown + toggle_power() + //Angry buzz or such here + return + + check_core_stability() + + add_avail(stored_power) + + power_cycle++ + if(power_cycle >= power_cycle_delay) + produce_power() + power_cycle = 0 + + return + + +/obj/machinery/power/am_control_unit/proc/produce_power() + playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + var/core_power = reported_core_efficiency//Effectively how much fuel we can safely deal with + if(core_power <= 0) return 0//Something is wrong + var/core_damage = 0 + var/fuel = fueljar.usefuel(fuel_injection) + + stored_power = (fuel/core_power)*fuel*20000 // Was 200000, was too much. New value run past Aurx. - N3X + //Now check if the cores could deal with it safely, this is done after so you can overload for more power if needed, still a bad idea + if(fuel > (2*core_power))//More fuel has been put in than the current cores can deal with + if(prob(50))core_damage = 1//Small chance of damage + if((fuel-core_power) > 5) core_damage = 5//Now its really starting to overload the cores + if((fuel-core_power) > 10) core_damage = 20//Welp now you did it, they wont stand much of this + if(core_damage == 0) return + for(var/obj/machinery/am_shielding/AMS in linked_cores) + AMS.stability -= core_damage + AMS.check_stability(1) + playsound(get_turf(src), 'sound/effects/bang.ogg', 50, 1) + return + + +/obj/machinery/power/am_control_unit/emp_act(severity) + switch(severity) + if(1) + if(active) toggle_power() + stability -= rand(15,30) + if(2) + if(active) toggle_power() + stability -= rand(10,20) + ..() + return 0 + + +/obj/machinery/power/am_control_unit/blob_act() + stability -= 20 + if(prob(100-stability))//Might infect the rest of the machine + for(var/obj/machinery/am_shielding/AMS in linked_shielding) + AMS.blob_act() + qdel(src) + return + check_stability() + return + + +/obj/machinery/power/am_control_unit/ex_act(severity) + switch(severity) + if(1.0) + stability -= 60 + if(2.0) + stability -= 40 + if(3.0) + stability -= 20 + check_stability() + return + + +/obj/machinery/power/am_control_unit/bullet_act(var/obj/item/projectile/Proj) + if(Proj.flag != "bullet") + stability -= Proj.force + return 0 + + +/obj/machinery/power/am_control_unit/power_change() + ..() + if(stat & NOPOWER && active) + toggle_power() + return + + +/obj/machinery/power/am_control_unit/update_icon() + if(active) + icon_state = "control_[icon_mod]" + else icon_state = "control" + //No other icons for it atm + + +/obj/machinery/power/am_control_unit/attackby(obj/item/W, mob/user) + if(!istype(W) || !user) return + if(istype(W, /obj/item/weapon/wrench)) + if(!anchored) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + user.visible_message("[user.name] secures the [src.name] to the floor.", \ + "You secure the anchor bolts to the floor.", \ + "You hear a ratchet") + src.anchored = 1 + connect_to_network() + else if(!linked_shielding.len > 0) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + user.visible_message("[user.name] unsecures the [src.name].", \ + "You remove the anchor bolts.", \ + "You hear a ratchet") + src.anchored = 0 + disconnect_from_network() + else + to_chat(user, "Once bolted and linked to a shielding unit it the [src.name] is unable to be moved!") + return + + if(istype(W, /obj/item/weapon/am_containment)) + if(fueljar) + to_chat(user, "There is already a [fueljar] inside!") + return + fueljar = W + if(user.client) + user.client.screen -= W + user.u_equip(W,1) + W.loc = src + user.update_icons() + message_admins("AME loaded with fuel by [user.real_name] ([user.key]) at ([x],[y],[z] - JMP)",0,1) + user.visible_message("[user.name] loads an [W.name] into the [src.name].", \ + "You load an [W.name].", \ + "You hear a thunk.") + return + + if(W.force >= 20) + stability -= W.force/2 + check_stability() + ..() + return + + +/obj/machinery/power/am_control_unit/attack_hand(mob/user as mob) + if(anchored) + interact(user) + return + + +/obj/machinery/power/am_control_unit/proc/add_shielding(var/obj/machinery/am_shielding/AMS, var/AMS_linking = 0) + if(!istype(AMS)) return 0 + if(!anchored) return 0 + if(!AMS_linking && !AMS.link_control(src)) return 0 + linked_shielding.Add(AMS) + update_shield_icons = 1 + return 1 + + +/obj/machinery/power/am_control_unit/proc/remove_shielding(var/obj/machinery/am_shielding/AMS) + if(!istype(AMS)) return 0 + linked_shielding.Remove(AMS) + update_shield_icons = 2 + if(active) toggle_power() + return 1 + + +/obj/machinery/power/am_control_unit/proc/check_stability()//TODO: make it break when low also might want to add a way to fix it like a part or such that can be replaced + if(stability <= 0) + qdel(src) + return + + +/obj/machinery/power/am_control_unit/proc/toggle_power() + active = !active + if(active) + use_power = 2 + visible_message("The [src.name] starts up.") + else + use_power = 1 + visible_message("The [src.name] shuts down.") + for(var/obj/machinery/am_shielding/AMS in linked_cores) + AMS.update_icon() + update_icon() + return + + +/obj/machinery/power/am_control_unit/proc/check_shield_icons()//Forces icon_update for all shields + if(shield_icon_delay) return + shield_icon_delay = 1 + if(update_shield_icons == 2)//2 means to clear everything and rebuild + for(var/obj/machinery/am_shielding/AMS in linked_shielding) + if(AMS.processing) AMS.shutdown_core() + AMS.control_unit = null + spawn(10) + AMS.controllerscan() + linked_shielding = list() + + else + for(var/obj/machinery/am_shielding/AMS in linked_shielding) + AMS.update_icon() + sleep(20) + shield_icon_delay = 0 + + +/obj/machinery/power/am_control_unit/proc/check_core_stability() + //if(stored_core_stability_delay || linked_cores.len <= 0) return + if(linked_cores.len <=0) return + //stored_core_stability_delay = 1 + stored_core_stability = 0 + for(var/obj/machinery/am_shielding/AMS in linked_cores) + stored_core_stability += AMS.stability + stored_core_stability/=linked_cores.len + switch(stored_core_stability) + if(0 to 24) + icon_mod="fuck" + if(25 to 49) + icon_mod="critical" + if(50 to INFINITY) + icon_mod="on" + if(icon_mod!=old_icon_mod) + old_icon_mod=icon_mod + update_icon() + + //spawn(40) + // stored_core_stability_delay = 0 + return + + +/obj/machinery/power/am_control_unit/interact(mob/user) + if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) + if(!istype(user, /mob/living/silicon/ai)) + user.unset_machine() + user << browse(null, "window=AMcontrol") + return + return ui_interact(user) + + + +/obj/machinery/power/am_control_unit/ui_interact(mob/user, ui_key = "main") + if(!user) + return + + var/list/fueljar_data=null + if(fueljar) + fueljar_data=list( + "fuel"=fueljar.fuel, + "fuel_max"=fueljar.fuel_max, + "injecting"=fuel_injection + ) + + var/list/data = list( + "active" = active, + //"stability" = stability, + "linked_shields" = linked_shielding.len, + "linked_cores" = linked_cores.len, + "efficiency" = reported_core_efficiency, + "stability" = stored_core_stability, + "stored_power" = stored_power, + "fueljar" = fueljar_data, + "siliconUser" = istype(user, /mob/living/silicon), + ) + + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, ui_key) + if (!ui) + // the ui does not exist, so we'll create a new one + ui = new(user, src, ui_key, "ame.tmpl", "Antimatter Control Unit", 500, data["siliconUser"] ? 465 : 390) + // When the UI is first opened this is the data it will use + ui.set_initial_data(data) + ui.open() + // Auto update every Master Controller tick + ui.set_auto_update(1) + else + // The UI is already open so push the new data to it + ui.push_data(data) + return + + +/obj/machinery/power/am_control_unit/Topic(href, href_list) + if(..()) return 1 + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + //Ignore input if we are broken or guy is not touching us, AI can control from a ways away + if(stat & (BROKEN|NOPOWER)) + usr.unset_machine() + usr << browse(null, "window=AMcontrol") + return + + if(href_list["close"]) + usr << browse(null, "window=AMcontrol") + usr.unset_machine() + return + + if(href_list["togglestatus"]) + toggle_power() + message_admins("AME toggled [active?"on":"off"] by [usr.real_name] ([usr.key]) at ([x],[y],[z] - JMP)",0,1) + return 1 + + if(href_list["refreshicons"]) + update_shield_icons = 2 // Fuck it + return 1 + + if(href_list["ejectjar"]) + if(fueljar) + message_admins("AME fuel jar ejected by [usr.real_name] ([usr.key]) at ([x],[y],[z] - JMP)",0,1) + fueljar.loc = src.loc + fueljar = null + //fueljar.control_unit = null currently it does not care where it is + //update_icon() when we have the icon for it + return 1 + + if(href_list["set_strength"]) + var/newval = input("Enter new injection strength") as num|null + if(isnull(newval)) + return + fuel_injection=newval + fuel_injection=max(1,fuel_injection) + message_admins("AME injection strength set to [fuel_injection] by [usr.real_name] ([usr.key]) at ([x],[y],[z] - JMP)",0,1) + return 1 + + if(href_list["refreshstability"]) + check_core_stability() + return 1 + + updateDialog() return 1 \ No newline at end of file diff --git a/code/modules/power/antimatter/engine.dm b/code/modules/power/antimatter/engine.dm index 258194bf603..9e4d9bb7692 100644 --- a/code/modules/power/antimatter/engine.dm +++ b/code/modules/power/antimatter/engine.dm @@ -1,211 +1,211 @@ -/obj/machinery/power/am_engine - icon = 'icons/am_engine.dmi' - density = 1 - anchored = 1.0 - flags = ON_BORDER - -/obj/machinery/power/am_engine/bits - name = "Antimatter Engine" - icon_state = "1" - -/obj/machinery/power/am_engine/engine - name = "Antimatter Engine" - icon_state = "am_engine" - var/engine_id = 0 - var/H_fuel = 0 - var/antiH_fuel = 0 - var/operating = 0 - var/stopping = 0 - var/obj/machinery/power/am_engine/injector/connected = null - -/obj/machinery/power/am_engine/injector - name = "Injector" - icon_state = "injector" - var/engine_id = 0 - var/injecting = 0 - var/fuel = 0 - var/obj/machinery/power/am_engine/engine/connected = null - -//injector - -/obj/machinery/power/am_engine/injector/New() - ..() - spawn( 13 ) - var/loc = get_step(src, NORTH) - src.connected = locate(/obj/machinery/power/am_engine/engine, get_step(loc, NORTH)) - return - return - - -/obj/machinery/power/am_engine/injector/attackby(obj/item/weapon/fuel/F, mob/user) - if( (stat & BROKEN) || !connected) return - - if(istype(F, /obj/item/weapon/fuel/H)) - if(injecting) +/obj/machinery/power/am_engine + icon = 'icons/am_engine.dmi' + density = 1 + anchored = 1.0 + flags = ON_BORDER + +/obj/machinery/power/am_engine/bits + name = "Antimatter Engine" + icon_state = "1" + +/obj/machinery/power/am_engine/engine + name = "Antimatter Engine" + icon_state = "am_engine" + var/engine_id = 0 + var/H_fuel = 0 + var/antiH_fuel = 0 + var/operating = 0 + var/stopping = 0 + var/obj/machinery/power/am_engine/injector/connected = null + +/obj/machinery/power/am_engine/injector + name = "Injector" + icon_state = "injector" + var/engine_id = 0 + var/injecting = 0 + var/fuel = 0 + var/obj/machinery/power/am_engine/engine/connected = null + +//injector + +/obj/machinery/power/am_engine/injector/New() + ..() + spawn( 13 ) + var/loc = get_step(src, NORTH) + src.connected = locate(/obj/machinery/power/am_engine/engine, get_step(loc, NORTH)) + return + return + + +/obj/machinery/power/am_engine/injector/attackby(obj/item/weapon/fuel/F, mob/user) + if( (stat & BROKEN) || !connected) return + + if(istype(F, /obj/item/weapon/fuel/H)) + if(injecting) to_chat(user, "Theres already a fuel rod in the injector!") - return + return to_chat(user, "You insert the rod into the injector") - injecting = 1 - var/fuel = F.fuel - qdel(F) - F = null - spawn( 300 ) - injecting = 0 - new/obj/item/weapon/fuel(src.loc) - connected.H_fuel += fuel - - if(istype(F, /obj/item/weapon/fuel/antiH)) - if(injecting) + injecting = 1 + var/fuel = F.fuel + qdel(F) + F = null + spawn( 300 ) + injecting = 0 + new/obj/item/weapon/fuel(src.loc) + connected.H_fuel += fuel + + if(istype(F, /obj/item/weapon/fuel/antiH)) + if(injecting) to_chat(user, "Theres already a fuel rod in the injector!") - return + return to_chat(user, "You insert the rod into the injector") - injecting = 1 - var/fuel = F.fuel - qdel(F) - F = null - spawn( 300 ) - injecting = 0 - new /obj/item/weapon/fuel(src.loc) - connected.antiH_fuel += fuel - - return - - -//engine - - -/obj/machinery/power/am_engine/engine/New() - ..() - spawn( 7 ) - var/loc = get_step(src, SOUTH) - src.connected = locate(/obj/machinery/power/am_engine/injector, get_step(loc, SOUTH)) - return - return - - -/obj/machinery/power/am_engine/engine/proc/engine_go() - - - if( (!src.connected) || (stat & BROKEN) ) - return - - if(!antiH_fuel || !H_fuel) - return - - operating = 1 - var/energy = 0 - - if(antiH_fuel == H_fuel) - var/mass = antiH_fuel + H_fuel - energy = convert2energy(mass) - H_fuel = 0 - antiH_fuel = 0 - else - var/residual_matter = modulus(H_fuel - antiH_fuel) - var/mass = antiH_fuel + H_fuel - residual_matter - energy = convert2energy(mass) - if( H_fuel > antiH_fuel ) - H_fuel = residual_matter - antiH_fuel = 0 - else - H_fuel = 0 - antiH_fuel = residual_matter - - for(var/mob/M in hearers(src, null)) - M.show_message(text("You hear a loud bang!")) - - //Q = k x (delta T) - - energy = energy*0.75 - operating = 0 - - //TODO: DEFERRED Heat tile - - return - - -/obj/machinery/power/am_engine/engine/proc/engine_process() - - - do - if( (!src.connected) || (stat & BROKEN) ) - return - - if(!antiH_fuel || !H_fuel) - return - - if(operating) - return - - operating = 1 - - sleep(50) - - var/energy //energy from the reaction - var/H //residual matter if H - var/antiH //residual matter if antiH - var/mass //total mass - - if(antiH_fuel == H_fuel) //if they're equal then convert the whole mass to energy - mass = antiH_fuel + H_fuel - energy = convert2energy(mass) - - else //else if they're not equal determine which isn't equal - //and set it equal to either H or antiH so we don't lose anything - - var/residual_matter = modulus(H_fuel - antiH_fuel) - mass = antiH_fuel + H_fuel - residual_matter - energy = convert2energy(mass) - - if( H_fuel > antiH_fuel ) - H = residual_matter - else - antiH = residual_matter - - - if(energy > convert2energy(8e-12)) //TOO MUCH ENERGY - for(var/mob/M in hearers(src, null)) - M.show_message(text("You hear a loud whirring!")) - sleep(20) - - //Q = k x (delta T) - //Too much energy so machine panics and dissapates half of it as heat - //The rest of the energetic photons then form into H and anti H particles again! - - H_fuel -= H - antiH_fuel -= antiH - antiH_fuel = antiH_fuel/2 - H_fuel = H_fuel/2 - - energy = convert2energy(H_fuel + antiH_fuel) - - H_fuel += H - antiH_fuel += antiH - - if(energy > convert2energy(8e-12)) //FAR TOO MUCH ENERGY STILL - for(var/mob/M in hearers(src, null)) - M.show_message(text("BANG!")) - new /obj/effect/bhole(src.loc) - - else //this amount of energy is okay so it does the proper output thing - - sleep(60) - //E = Pt - //Lets say its 86% efficient - var/output = 0.86*energy/20 - add_avail(output) - //yeah the machine realises that something isn't right and accounts for it if H or antiH - H_fuel -= H - antiH_fuel -= antiH - antiH_fuel = antiH_fuel/4 - H_fuel = H_fuel/4 - H_fuel += H - antiH_fuel += antiH - operating = 0 - sleep(100) - - while(!stopping) - - stopping = 0 - - return + injecting = 1 + var/fuel = F.fuel + qdel(F) + F = null + spawn( 300 ) + injecting = 0 + new /obj/item/weapon/fuel(src.loc) + connected.antiH_fuel += fuel + + return + + +//engine + + +/obj/machinery/power/am_engine/engine/New() + ..() + spawn( 7 ) + var/loc = get_step(src, SOUTH) + src.connected = locate(/obj/machinery/power/am_engine/injector, get_step(loc, SOUTH)) + return + return + + +/obj/machinery/power/am_engine/engine/proc/engine_go() + + + if( (!src.connected) || (stat & BROKEN) ) + return + + if(!antiH_fuel || !H_fuel) + return + + operating = 1 + var/energy = 0 + + if(antiH_fuel == H_fuel) + var/mass = antiH_fuel + H_fuel + energy = convert2energy(mass) + H_fuel = 0 + antiH_fuel = 0 + else + var/residual_matter = modulus(H_fuel - antiH_fuel) + var/mass = antiH_fuel + H_fuel - residual_matter + energy = convert2energy(mass) + if( H_fuel > antiH_fuel ) + H_fuel = residual_matter + antiH_fuel = 0 + else + H_fuel = 0 + antiH_fuel = residual_matter + + for(var/mob/M in hearers(src, null)) + M.show_message(text("You hear a loud bang!")) + + //Q = k x (delta T) + + energy = energy*0.75 + operating = 0 + + //TODO: DEFERRED Heat tile + + return + + +/obj/machinery/power/am_engine/engine/proc/engine_process() + + + do + if( (!src.connected) || (stat & BROKEN) ) + return + + if(!antiH_fuel || !H_fuel) + return + + if(operating) + return + + operating = 1 + + sleep(50) + + var/energy //energy from the reaction + var/H //residual matter if H + var/antiH //residual matter if antiH + var/mass //total mass + + if(antiH_fuel == H_fuel) //if they're equal then convert the whole mass to energy + mass = antiH_fuel + H_fuel + energy = convert2energy(mass) + + else //else if they're not equal determine which isn't equal + //and set it equal to either H or antiH so we don't lose anything + + var/residual_matter = modulus(H_fuel - antiH_fuel) + mass = antiH_fuel + H_fuel - residual_matter + energy = convert2energy(mass) + + if( H_fuel > antiH_fuel ) + H = residual_matter + else + antiH = residual_matter + + + if(energy > convert2energy(8e-12)) //TOO MUCH ENERGY + for(var/mob/M in hearers(src, null)) + M.show_message(text("You hear a loud whirring!")) + sleep(20) + + //Q = k x (delta T) + //Too much energy so machine panics and dissapates half of it as heat + //The rest of the energetic photons then form into H and anti H particles again! + + H_fuel -= H + antiH_fuel -= antiH + antiH_fuel = antiH_fuel/2 + H_fuel = H_fuel/2 + + energy = convert2energy(H_fuel + antiH_fuel) + + H_fuel += H + antiH_fuel += antiH + + if(energy > convert2energy(8e-12)) //FAR TOO MUCH ENERGY STILL + for(var/mob/M in hearers(src, null)) + M.show_message(text("BANG!")) + new /obj/effect/bhole(src.loc) + + else //this amount of energy is okay so it does the proper output thing + + sleep(60) + //E = Pt + //Lets say its 86% efficient + var/output = 0.86*energy/20 + add_avail(output) + //yeah the machine realises that something isn't right and accounts for it if H or antiH + H_fuel -= H + antiH_fuel -= antiH + antiH_fuel = antiH_fuel/4 + H_fuel = H_fuel/4 + H_fuel += H + antiH_fuel += antiH + operating = 0 + sleep(100) + + while(!stopping) + + stopping = 0 + + return diff --git a/code/modules/power/antimatter/fuel.dm b/code/modules/power/antimatter/fuel.dm index aaefca8d183..b7caf82adc5 100644 --- a/code/modules/power/antimatter/fuel.dm +++ b/code/modules/power/antimatter/fuel.dm @@ -1,101 +1,101 @@ -/obj/item/weapon/fuel - name = "Magnetic Storage Ring" - desc = "A magnetic storage ring." - icon = 'icons/obj/items.dmi' - icon_state = "rcdammo" - opacity = 0 - density = 0 - anchored = 0.0 - var/fuel = 0 - var/s_time = 1.0 - var/content = null - -/obj/item/weapon/fuel/H - name = "Hydrogen storage ring" - content = "Hydrogen" - fuel = 1e-12 //pico-kilogram - -/obj/item/weapon/fuel/antiH - name = "Anti-Hydrogen storage ring" - content = "Anti-Hydrogen" - fuel = 1e-12 //pico-kilogram - -/obj/item/weapon/fuel/attackby(obj/item/weapon/fuel/F, mob/user) - ..() - if(istype(src, /obj/item/weapon/fuel/antiH)) - if(istype(F, /obj/item/weapon/fuel/antiH)) - src.fuel += F.fuel - F.fuel = 0 +/obj/item/weapon/fuel + name = "Magnetic Storage Ring" + desc = "A magnetic storage ring." + icon = 'icons/obj/items.dmi' + icon_state = "rcdammo" + opacity = 0 + density = 0 + anchored = 0.0 + var/fuel = 0 + var/s_time = 1.0 + var/content = null + +/obj/item/weapon/fuel/H + name = "Hydrogen storage ring" + content = "Hydrogen" + fuel = 1e-12 //pico-kilogram + +/obj/item/weapon/fuel/antiH + name = "Anti-Hydrogen storage ring" + content = "Anti-Hydrogen" + fuel = 1e-12 //pico-kilogram + +/obj/item/weapon/fuel/attackby(obj/item/weapon/fuel/F, mob/user) + ..() + if(istype(src, /obj/item/weapon/fuel/antiH)) + if(istype(F, /obj/item/weapon/fuel/antiH)) + src.fuel += F.fuel + F.fuel = 0 to_chat(user, "You have added the anti-Hydrogen to the storage ring, it now contains [src.fuel]kg") - if(istype(F, /obj/item/weapon/fuel/H)) - src.fuel += F.fuel - qdel(F) - F = null - src:annihilation(src.fuel) - if(istype(src, /obj/item/weapon/fuel/H)) - if(istype(F, /obj/item/weapon/fuel/H)) - src.fuel += F.fuel - F.fuel = 0 + if(istype(F, /obj/item/weapon/fuel/H)) + src.fuel += F.fuel + qdel(F) + F = null + src:annihilation(src.fuel) + if(istype(src, /obj/item/weapon/fuel/H)) + if(istype(F, /obj/item/weapon/fuel/H)) + src.fuel += F.fuel + F.fuel = 0 to_chat(user, "You have added the Hydrogen to the storage ring, it now contains [src.fuel]kg") - if(istype(F, /obj/item/weapon/fuel/antiH)) - src.fuel += F.fuel - qdel(src) - F:annihilation(F.fuel) - -/obj/item/weapon/fuel/antiH/proc/annihilation(var/mass) - - - var/strength = convert2energy(mass) - - if (strength < 773.0) - var/turf/T = get_turf(src) - - if (strength > (450+T0C)) - explosion(T, 0, 1, 2, 4) - else - if (strength > (300+T0C)) - explosion(T, 0, 0, 2, 3) - - qdel(src) - return - - var/turf/ground_zero = get_turf(loc) - - var/ground_zero_range = round(strength / 387) - explosion(ground_zero, ground_zero_range, ground_zero_range*2, ground_zero_range*3, ground_zero_range*4) - - //SN src = null - qdel(src) - return - - -/obj/item/weapon/fuel/examine() - ..() + if(istype(F, /obj/item/weapon/fuel/antiH)) + src.fuel += F.fuel + qdel(src) + F:annihilation(F.fuel) + +/obj/item/weapon/fuel/antiH/proc/annihilation(var/mass) + + + var/strength = convert2energy(mass) + + if (strength < 773.0) + var/turf/T = get_turf(src) + + if (strength > (450+T0C)) + explosion(T, 0, 1, 2, 4) + else + if (strength > (300+T0C)) + explosion(T, 0, 0, 2, 3) + + qdel(src) + return + + var/turf/ground_zero = get_turf(loc) + + var/ground_zero_range = round(strength / 387) + explosion(ground_zero, ground_zero_range, ground_zero_range*2, ground_zero_range*3, ground_zero_range*4) + + //SN src = null + qdel(src) + return + + +/obj/item/weapon/fuel/examine() + ..() to_chat(user, "A magnetic storage ring, it contains [fuel]kg of [content ? content : "nothing"].") - -/obj/item/weapon/fuel/proc/injest(mob/M as mob) - switch(content) - if("Anti-Hydrogen") - M.gib() - if("Hydrogen") + +/obj/item/weapon/fuel/proc/injest(mob/M as mob) + switch(content) + if("Anti-Hydrogen") + M.gib() + if("Hydrogen") to_chat(M, "You feel very light, as if you might just float away...") - qdel(src) - return - -/obj/item/weapon/fuel/attack(mob/M as mob, mob/user as mob) - if (user != M) - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = user - O.target = M - O.item = src - O.s_loc = user.loc - O.t_loc = M.loc - O.place = "fuel" - M.requests += O - spawn( 0 ) - O.process() - return - else - for(var/mob/O in viewers(M, null)) - O.show_message(text("[M] ate the [content ? content : "empty canister"]!"), 1) - src.injest(M) + qdel(src) + return + +/obj/item/weapon/fuel/attack(mob/M as mob, mob/user as mob) + if (user != M) + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = user + O.target = M + O.item = src + O.s_loc = user.loc + O.t_loc = M.loc + O.place = "fuel" + M.requests += O + spawn( 0 ) + O.process() + return + else + for(var/mob/O in viewers(M, null)) + O.show_message(text("[M] ate the [content ? content : "empty canister"]!"), 1) + src.injest(M) diff --git a/code/modules/power/antimatter/shielding.dm b/code/modules/power/antimatter/shielding.dm index 21c1df6647a..3e96ddc122a 100644 --- a/code/modules/power/antimatter/shielding.dm +++ b/code/modules/power/antimatter/shielding.dm @@ -1,239 +1,239 @@ -//like orange but only checks north/south/east/west for one step -proc/cardinalrange(var/center) - var/list/things = list() - for(var/direction in cardinal) - var/turf/T = get_step(center, direction) - if(!T) continue - things += T.contents - return things - -/obj/machinery/am_shielding - name = "antimatter reactor section" - desc = "This device was built using a plasma life-form that seems to increase plasma's natural ability to react with neutrinos while reducing the combustibility." - - //icon = 'icons/obj/machines/antimatter.dmi' - icon = 'icons/obj/machines/new_ame.dmi' - icon_state = "shield" - anchored = 1 - density = 1 - dir = 1 - use_power = 0//Living things generally dont use power - idle_power_usage = 0 - active_power_usage = 0 - - var/obj/machinery/power/am_control_unit/control_unit = null - var/processing = 0//To track if we are in the update list or not, we need to be when we are damaged and if we ever - var/stability = 100//If this gets low bad things tend to happen - var/efficiency = 1//How many cores this core counts for when doing power processing, plasma in the air and stability could affect this - var/coredirs = 0 - var/dirs=0 - - -/obj/machinery/am_shielding/New(loc) - ..(loc) - machines -= src - power_machines += src - spawn(10) - controllerscan() - - -/obj/machinery/am_shielding/proc/controllerscan(var/priorscan = 0) - //Make sure we are the only one here - if(!istype(src.loc, /turf)) - qdel(src) - return - for(var/obj/machinery/am_shielding/AMS in loc.contents) - if(AMS == src) continue - qdel(src) - return - - //Search for shielding first - for(var/obj/machinery/am_shielding/AMS in cardinalrange(src)) - if(AMS && AMS.control_unit && link_control(AMS.control_unit)) - break - - if(!control_unit)//No other guys nearby, look for a control unit - for(var/obj/machinery/power/am_control_unit/AMC in cardinalrange(src)) - if(AMC.add_shielding(src)) - break - if(!priorscan) - sleep(20) - controllerscan(1)//Last chance - return - qdel(src) - - -/obj/machinery/am_shielding/Destroy() - if(control_unit) control_unit.remove_shielding(src) - if(processing) shutdown_core() - visible_message("The [src.name] melts!") - power_machines -= src - //Might want to have it leave a mess on the floor but no sprites for now - ..() - return - - -/obj/machinery/am_shielding/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - return 0 - - -/obj/machinery/am_shielding/process() - if(!processing) . = PROCESS_KILL - //TODO: core functions and stability - //TODO: think about checking the airmix for plasma and increasing power output - return - - -/obj/machinery/am_shielding/emp_act()//Immune due to not really much in the way of electronics. - return 0 - - -/obj/machinery/am_shielding/blob_act() - stability -= 20 - if(prob(100-stability)) - if(prob(10))//Might create a node - new /obj/effect/blob/node(src.loc,150) - else - new /obj/effect/blob(src.loc,60) - qdel(src) - return - check_stability() - return - - -/obj/machinery/am_shielding/ex_act(severity) - switch(severity) - if(1.0) - stability -= 80 - if(2.0) - stability -= 40 - if(3.0) - stability -= 20 - check_stability() - return - - -/obj/machinery/am_shielding/bullet_act(var/obj/item/projectile/Proj) - if(Proj.flag != "bullet") - stability -= Proj.force/2 - return 0 - - -/obj/machinery/am_shielding/update_icon() - overlays.len = 0 - coredirs = 0 - dirs = 0 - for(var/direction in alldirs) - var/turf/T = get_step(loc, direction) - for(var/obj/machinery/machine in T) - // Detect cores - if((istype(machine, /obj/machinery/am_shielding) && machine:control_unit == control_unit && machine:processing)) - coredirs |= direction - - // Detect cores, shielding, and control boxen. - if(direction in cardinal) - if((istype(machine, /obj/machinery/am_shielding) && machine:control_unit == control_unit) || (istype(machine, /obj/machinery/power/am_control_unit) && machine == control_unit)) - dirs |= direction - - // If we're next to a core, set the prefix. - var/prefix = "" - var/icondirs=dirs - - if(coredirs) - prefix="core" - - // Set our overlay - icon_state = "[prefix]shield_[icondirs]" - - if(core_check()) - overlays += "core[control_unit && control_unit.active]" - if(!processing) setup_core() - else if(processing) shutdown_core() - - -/obj/machinery/am_shielding/attackby(obj/item/W, mob/user) - if(!istype(W) || !user) return - if(W.force > 10) - stability -= W.force/2 - check_stability() - ..() - return - - - -//Call this to link a detected shilding unit to the controller -/obj/machinery/am_shielding/proc/link_control(var/obj/machinery/power/am_control_unit/AMC) - if(!istype(AMC)) return 0 - if(control_unit && control_unit != AMC) return 0//Already have one - control_unit = AMC - control_unit.add_shielding(src,1) - return 1 - - -//Scans cards for shields or the control unit and if all there it -/obj/machinery/am_shielding/proc/core_check() - for(var/direction in alldirs) - var/found_am_device=0 - for(var/obj/machinery/machine in get_step(loc, direction)) - if(!machine) - continue - if(istype(machine, /obj/machinery/am_shielding) || istype(machine, /obj/machinery/power/am_control_unit)) - found_am_device=1 - break - if(!found_am_device) - return 0 - return 1 - - -/obj/machinery/am_shielding/proc/setup_core() - processing = 1 - power_machines.Add(src) - if(!control_unit) return - control_unit.linked_cores.Add(src) - control_unit.reported_core_efficiency += efficiency - - -/obj/machinery/am_shielding/proc/shutdown_core() - processing = 0 - if(!control_unit) return - control_unit.linked_cores.Remove(src) - control_unit.reported_core_efficiency -= efficiency - - -/obj/machinery/am_shielding/proc/check_stability(var/injecting_fuel = 0) - if(stability > 0) return - if(injecting_fuel && control_unit) - control_unit.exploding = 1 - qdel(src) - -/obj/machinery/am_shielding/proc/recalc_efficiency(var/new_efficiency)//tbh still not 100% sure how I want to deal with efficiency so this is likely temp - if(!control_unit || !processing) return - if(stability < 50) - new_efficiency /= 2 - control_unit.reported_core_efficiency += (new_efficiency - efficiency) - efficiency = new_efficiency - - - -/obj/item/device/am_shielding_container - name = "packaged antimatter reactor section" - desc = "A small storage unit containing an antimatter reactor section. To use place near an antimatter control unit or deployed antimatter reactor section and use a multitool to activate this package." - icon = 'icons/obj/machines/antimatter.dmi' - icon_state = "box" - item_state = "electronic" - w_class = 4.0 - flags = FPRINT - siemens_coefficient = 1 - throwforce = 5 - throw_speed = 1 - throw_range = 2 - starting_materials = list(MAT_IRON = CC_PER_SHEET_METAL*2) - w_type = RECYK_METAL - -/obj/item/device/am_shielding_container/attackby(var/obj/item/I, var/mob/user) - if(ismultitool(I) && isturf(loc)) - new/obj/machinery/am_shielding(src.loc) - qdel(src) - return - ..() +//like orange but only checks north/south/east/west for one step +proc/cardinalrange(var/center) + var/list/things = list() + for(var/direction in cardinal) + var/turf/T = get_step(center, direction) + if(!T) continue + things += T.contents + return things + +/obj/machinery/am_shielding + name = "antimatter reactor section" + desc = "This device was built using a plasma life-form that seems to increase plasma's natural ability to react with neutrinos while reducing the combustibility." + + //icon = 'icons/obj/machines/antimatter.dmi' + icon = 'icons/obj/machines/new_ame.dmi' + icon_state = "shield" + anchored = 1 + density = 1 + dir = 1 + use_power = 0//Living things generally dont use power + idle_power_usage = 0 + active_power_usage = 0 + + var/obj/machinery/power/am_control_unit/control_unit = null + var/processing = 0//To track if we are in the update list or not, we need to be when we are damaged and if we ever + var/stability = 100//If this gets low bad things tend to happen + var/efficiency = 1//How many cores this core counts for when doing power processing, plasma in the air and stability could affect this + var/coredirs = 0 + var/dirs=0 + + +/obj/machinery/am_shielding/New(loc) + ..(loc) + machines -= src + power_machines += src + spawn(10) + controllerscan() + + +/obj/machinery/am_shielding/proc/controllerscan(var/priorscan = 0) + //Make sure we are the only one here + if(!istype(src.loc, /turf)) + qdel(src) + return + for(var/obj/machinery/am_shielding/AMS in loc.contents) + if(AMS == src) continue + qdel(src) + return + + //Search for shielding first + for(var/obj/machinery/am_shielding/AMS in cardinalrange(src)) + if(AMS && AMS.control_unit && link_control(AMS.control_unit)) + break + + if(!control_unit)//No other guys nearby, look for a control unit + for(var/obj/machinery/power/am_control_unit/AMC in cardinalrange(src)) + if(AMC.add_shielding(src)) + break + if(!priorscan) + sleep(20) + controllerscan(1)//Last chance + return + qdel(src) + + +/obj/machinery/am_shielding/Destroy() + if(control_unit) control_unit.remove_shielding(src) + if(processing) shutdown_core() + visible_message("The [src.name] melts!") + power_machines -= src + //Might want to have it leave a mess on the floor but no sprites for now + ..() + return + + +/obj/machinery/am_shielding/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + return 0 + + +/obj/machinery/am_shielding/process() + if(!processing) . = PROCESS_KILL + //TODO: core functions and stability + //TODO: think about checking the airmix for plasma and increasing power output + return + + +/obj/machinery/am_shielding/emp_act()//Immune due to not really much in the way of electronics. + return 0 + + +/obj/machinery/am_shielding/blob_act() + stability -= 20 + if(prob(100-stability)) + if(prob(10))//Might create a node + new /obj/effect/blob/node(src.loc,150) + else + new /obj/effect/blob(src.loc,60) + qdel(src) + return + check_stability() + return + + +/obj/machinery/am_shielding/ex_act(severity) + switch(severity) + if(1.0) + stability -= 80 + if(2.0) + stability -= 40 + if(3.0) + stability -= 20 + check_stability() + return + + +/obj/machinery/am_shielding/bullet_act(var/obj/item/projectile/Proj) + if(Proj.flag != "bullet") + stability -= Proj.force/2 + return 0 + + +/obj/machinery/am_shielding/update_icon() + overlays.len = 0 + coredirs = 0 + dirs = 0 + for(var/direction in alldirs) + var/turf/T = get_step(loc, direction) + for(var/obj/machinery/machine in T) + // Detect cores + if((istype(machine, /obj/machinery/am_shielding) && machine:control_unit == control_unit && machine:processing)) + coredirs |= direction + + // Detect cores, shielding, and control boxen. + if(direction in cardinal) + if((istype(machine, /obj/machinery/am_shielding) && machine:control_unit == control_unit) || (istype(machine, /obj/machinery/power/am_control_unit) && machine == control_unit)) + dirs |= direction + + // If we're next to a core, set the prefix. + var/prefix = "" + var/icondirs=dirs + + if(coredirs) + prefix="core" + + // Set our overlay + icon_state = "[prefix]shield_[icondirs]" + + if(core_check()) + overlays += "core[control_unit && control_unit.active]" + if(!processing) setup_core() + else if(processing) shutdown_core() + + +/obj/machinery/am_shielding/attackby(obj/item/W, mob/user) + if(!istype(W) || !user) return + if(W.force > 10) + stability -= W.force/2 + check_stability() + ..() + return + + + +//Call this to link a detected shilding unit to the controller +/obj/machinery/am_shielding/proc/link_control(var/obj/machinery/power/am_control_unit/AMC) + if(!istype(AMC)) return 0 + if(control_unit && control_unit != AMC) return 0//Already have one + control_unit = AMC + control_unit.add_shielding(src,1) + return 1 + + +//Scans cards for shields or the control unit and if all there it +/obj/machinery/am_shielding/proc/core_check() + for(var/direction in alldirs) + var/found_am_device=0 + for(var/obj/machinery/machine in get_step(loc, direction)) + if(!machine) + continue + if(istype(machine, /obj/machinery/am_shielding) || istype(machine, /obj/machinery/power/am_control_unit)) + found_am_device=1 + break + if(!found_am_device) + return 0 + return 1 + + +/obj/machinery/am_shielding/proc/setup_core() + processing = 1 + power_machines.Add(src) + if(!control_unit) return + control_unit.linked_cores.Add(src) + control_unit.reported_core_efficiency += efficiency + + +/obj/machinery/am_shielding/proc/shutdown_core() + processing = 0 + if(!control_unit) return + control_unit.linked_cores.Remove(src) + control_unit.reported_core_efficiency -= efficiency + + +/obj/machinery/am_shielding/proc/check_stability(var/injecting_fuel = 0) + if(stability > 0) return + if(injecting_fuel && control_unit) + control_unit.exploding = 1 + qdel(src) + +/obj/machinery/am_shielding/proc/recalc_efficiency(var/new_efficiency)//tbh still not 100% sure how I want to deal with efficiency so this is likely temp + if(!control_unit || !processing) return + if(stability < 50) + new_efficiency /= 2 + control_unit.reported_core_efficiency += (new_efficiency - efficiency) + efficiency = new_efficiency + + + +/obj/item/device/am_shielding_container + name = "packaged antimatter reactor section" + desc = "A small storage unit containing an antimatter reactor section. To use place near an antimatter control unit or deployed antimatter reactor section and use a multitool to activate this package." + icon = 'icons/obj/machines/antimatter.dmi' + icon_state = "box" + item_state = "electronic" + w_class = 4.0 + flags = FPRINT + siemens_coefficient = 1 + throwforce = 5 + throw_speed = 1 + throw_range = 2 + starting_materials = list(MAT_IRON = CC_PER_SHEET_METAL*2) + w_type = RECYK_METAL + +/obj/item/device/am_shielding_container/attackby(var/obj/item/I, var/mob/user) + if(ismultitool(I) && isturf(loc)) + new/obj/machinery/am_shielding(src.loc) + qdel(src) + return + ..() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 62ed56e25a1..0c3805f7d39 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1,1318 +1,1318 @@ -#define APC_WIRE_IDSCAN 1 -#define APC_WIRE_MAIN_POWER1 2 -#define APC_WIRE_MAIN_POWER2 3 -#define APC_WIRE_AI_CONTROL 4 - -//update_state -#define UPSTATE_CELL_IN 1 -#define UPSTATE_OPENED1 2 -#define UPSTATE_OPENED2 4 -#define UPSTATE_MAINT 8 -#define UPSTATE_BROKE 16 -#define UPSTATE_BLUESCREEN 32 -#define UPSTATE_WIREEXP 64 -#define UPSTATE_ALLGOOD 128 - -//update_overlay -#define APC_UPOVERLAY_CHARGEING0 1 -#define APC_UPOVERLAY_CHARGEING1 2 -#define APC_UPOVERLAY_CHARGEING2 4 -#define APC_UPOVERLAY_EQUIPMENT0 8 -#define APC_UPOVERLAY_EQUIPMENT1 16 -#define APC_UPOVERLAY_EQUIPMENT2 32 -#define APC_UPOVERLAY_LIGHTING0 64 -#define APC_UPOVERLAY_LIGHTING1 128 -#define APC_UPOVERLAY_LIGHTING2 256 -#define APC_UPOVERLAY_ENVIRON0 512 -#define APC_UPOVERLAY_ENVIRON1 1024 -#define APC_UPOVERLAY_ENVIRON2 2048 -#define APC_UPOVERLAY_LOCKED 4096 -#define APC_UPOVERLAY_OPERATING 8192 - -#define APC_UPDATE_ICON_COOLDOWN 100 // 10 seconds - - -// the Area Power Controller (APC), formerly Power Distribution Unit (PDU) -// one per area, needs wire conection to power network through a terminal - -// controls power to devices in that area -// may be opened to change power cell -// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto - - -//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx - - -/obj/machinery/power/apc - desc = "A control terminal for the area electrical systems." - icon_state = "apc0" - anchored = 1 - use_power = 0 - req_access = list(access_engine_equip) - var/spooky=0 - var/obj/item/weapon/cell/cell - var/start_charge = 90 // initial cell charge % - var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500 - var/opened = 0 //0=closed, 1=opened, 2=cover removed - var/shorted = 0 - var/lighting = 3 - var/equipment = 3 - var/environ = 3 - var/operating = 1 - var/charging = 0 - var/chargemode = 1 - var/chargecount = 0 - var/locked = 1 - var/coverlocked = 1 - var/aidisabled = 0 - var/tdir = null - var/lastused_light = 0 - var/lastused_equip = 0 - var/lastused_environ = 0 - var/lastused_total = 0 - var/main_status = 0 - var/wiresexposed = 0 - powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :( - var/malfhack = 0 //New var for my changes to AI malf. --NeoFite - var/mob/living/silicon/ai/malfai = null //See above --NeoFite -// luminosity = 1 - var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver - var/overload = 1 //used for the Blackout malf module - var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment - var/mob/living/silicon/ai/occupant = null - var/longtermpower = 10 - var/update_state = -1 - var/update_overlay = -1 - var/global/status_overlays = 0 - var/updating_icon = 0 - var/datum/wires/apc/wires = null - var/global/list/status_overlays_lock - var/global/list/status_overlays_charging - var/global/list/status_overlays_equipment - var/global/list/status_overlays_lighting - var/global/list/status_overlays_environ - - var/is_critical = 0 // Endgame scenarios will not destroy this APC. - - machine_flags = WIREJACK - -/obj/machinery/power/apc/New(loc, var/ndir, var/building=0) - ..(loc) - wires = new(src) - // offset 24 pixels in direction of dir - // this allows the APC to be embedded in a wall, yet still inside an area - if (building) - dir = ndir - src.tdir = dir // to fix Vars bug - dir = SOUTH - - if(areaMaster.areaapc) - world.log << "Secondary APC detected in area: [areaMaster.name], deleting the second APC" - qdel(src) - return - areaMaster.set_apc(src) - - if(src.tdir & 3) - pixel_x = 0 - pixel_y = (src.tdir == 1 ? 24 : -24) - else - pixel_x = (src.tdir == 4 ? 24 : -24) - pixel_y = 0 - - if (building==0) - init() - else - opened = 1 - operating = 0 - stat |= MAINT - - if(ticker) - initialize() - -/obj/machinery/power/apc/proc/init() - has_electronics = 2 //installed and secured - // is starting with a power cell installed, create it and set its charge level - if(cell_type) - src.cell = new/obj/item/weapon/cell(src) - cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively) - cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value) - - finalise_terminal() //creates the terminal itself - -/obj/machinery/power/apc/finalise_terminal() - // create a terminal object at the same position as original turf loc - // wires will attach to this - terminal = new/obj/machinery/power/terminal(src.loc) - terminal.dir = tdir - terminal.master = src - -/obj/machinery/power/apc/initialize() - ..() - - name = "[areaMaster.name] APC" - - update_icon() - - spawn(5) - update() - -/obj/machinery/power/apc/examine(mob/user) - ..() - if(stat & BROKEN) - to_chat(user, "Looks broken.") - return - if(opened) - if(has_electronics && terminal) - to_chat(user, "The cover is [opened==2?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"].") - else if (!has_electronics && terminal) - to_chat(user, "There are some wires but no any electronics.") - else if (has_electronics && !terminal) - to_chat(user, "Electronics installed but not wired.") - else /* if (!has_electronics && !terminal) */ - to_chat(user, "There is no electronics nor connected wires.") - else - if (stat & MAINT) - to_chat(user, "The cover is closed. Something wrong with it: it doesn't work.") - else if (malfhack) - to_chat(user, "The cover is broken. It may be hard to force it open.") - else - to_chat(user, "The cover is closed.") - -/obj/machinery/power/apc/update_icon() - if (!status_overlays) - status_overlays = 1 - status_overlays_lock = new - status_overlays_charging = new - status_overlays_equipment = new - status_overlays_lighting = new - status_overlays_environ = new - - status_overlays_lock.len = 2 - status_overlays_charging.len = 3 - status_overlays_equipment.len = 4 - status_overlays_lighting.len = 4 - status_overlays_environ.len = 4 - - status_overlays_lock[1] = image(icon, "apcox-0") // 0=blue 1=red - status_overlays_lock[2] = image(icon, "apcox-1") - - status_overlays_charging[1] = image(icon, "apco3-0") - status_overlays_charging[2] = image(icon, "apco3-1") - status_overlays_charging[3] = image(icon, "apco3-2") - - status_overlays_equipment[1] = image(icon, "apco0-0") // 0=red, 1=green, 2=blue - status_overlays_equipment[2] = image(icon, "apco0-1") - status_overlays_equipment[3] = image(icon, "apco0-2") - status_overlays_equipment[4] = image(icon, "apco0-3") - - status_overlays_lighting[1] = image(icon, "apco1-0") - status_overlays_lighting[2] = image(icon, "apco1-1") - status_overlays_lighting[3] = image(icon, "apco1-2") - status_overlays_lighting[4] = image(icon, "apco1-3") - - status_overlays_environ[1] = image(icon, "apco2-0") - status_overlays_environ[2] = image(icon, "apco2-1") - status_overlays_environ[3] = image(icon, "apco2-2") - status_overlays_environ[4] = image(icon, "apco2-3") - - - - var/update = check_updates() //returns 0 if no need to update icons. - // 1 if we need to update the icon_state - // 2 if we need to update the overlays - if(!update) - return - - if(update & 1) // Updating the icon state - if(update_state & UPSTATE_ALLGOOD) - icon_state = "apc0" - else if(update_state & (UPSTATE_OPENED1|UPSTATE_OPENED2)) - var/basestate = "apc[ cell ? "2" : "1" ]" - if(update_state & UPSTATE_OPENED1) - if(update_state & (UPSTATE_MAINT|UPSTATE_BROKE)) - icon_state = "apcmaint" //disabled APC cannot hold cell - else - icon_state = basestate - else if(update_state & UPSTATE_OPENED2) - icon_state = "[basestate]-nocover" - else if(update_state & UPSTATE_BROKE) - icon_state = "apc-b" - else if(update_state & UPSTATE_BLUESCREEN) - icon_state = "apcemag" - else if(update_state & UPSTATE_WIREEXP) - icon_state = "apcewires" - - - - if(!(update_state & UPSTATE_ALLGOOD)) - if(overlays.len) - overlays = 0 - return - if(update & 2) - - if(overlays.len) - overlays = 0 - - if(!(stat & (BROKEN|MAINT)) && update_state & UPSTATE_ALLGOOD) - overlays += status_overlays_lock[locked+1] - overlays += status_overlays_charging[charging+1] - if(operating) - overlays += status_overlays_equipment[equipment+1] - overlays += status_overlays_lighting[lighting+1] - overlays += status_overlays_environ[environ+1] - - -/obj/machinery/power/apc/proc/check_updates() - - - var/last_update_state = update_state - var/last_update_overlay = update_overlay - update_state = 0 - update_overlay = 0 - - if(cell) - update_state |= UPSTATE_CELL_IN - if(stat & BROKEN) - update_state |= UPSTATE_BROKE - if(stat & MAINT) - update_state |= UPSTATE_MAINT - - if(opened) - if(opened==1) - update_state |= UPSTATE_OPENED1 - if(opened==2) - update_state |= UPSTATE_OPENED2 - else if(emagged || malfai || spooky) - update_state |= UPSTATE_BLUESCREEN - else if(wiresexposed) - update_state |= UPSTATE_WIREEXP - if(update_state <= 1) - update_state |= UPSTATE_ALLGOOD - - if(operating) - update_overlay |= APC_UPOVERLAY_OPERATING - - if(update_state & UPSTATE_ALLGOOD) - if(locked) - update_overlay |= APC_UPOVERLAY_LOCKED - - if(!charging) - update_overlay |= APC_UPOVERLAY_CHARGEING0 - else if(charging == 1) - update_overlay |= APC_UPOVERLAY_CHARGEING1 - else if(charging == 2) - update_overlay |= APC_UPOVERLAY_CHARGEING2 - - if (!equipment) - update_overlay |= APC_UPOVERLAY_EQUIPMENT0 - else if(equipment == 1) - update_overlay |= APC_UPOVERLAY_EQUIPMENT1 - else if(equipment == 2) - update_overlay |= APC_UPOVERLAY_EQUIPMENT2 - - if(!lighting) - update_overlay |= APC_UPOVERLAY_LIGHTING0 - else if(lighting == 1) - update_overlay |= APC_UPOVERLAY_LIGHTING1 - else if(lighting == 2) - update_overlay |= APC_UPOVERLAY_LIGHTING2 - - if(!environ) - update_overlay |= APC_UPOVERLAY_ENVIRON0 - else if(environ==1) - update_overlay |= APC_UPOVERLAY_ENVIRON1 - else if(environ==2) - update_overlay |= APC_UPOVERLAY_ENVIRON2 - - var/results = 0 - if(last_update_state == update_state && last_update_overlay == update_overlay) - return 0 - if(last_update_state != update_state) - results += 1 - if(last_update_overlay != update_overlay && update_overlay != 0) - results += 2 - return results - - - - -// Used in process so it doesn't update the icon too much -/obj/machinery/power/apc/proc/queue_icon_update() - - - if(!updating_icon) - updating_icon = 1 - // Start the update - spawn(APC_UPDATE_ICON_COOLDOWN) - update_icon() - updating_icon = 0 - -/obj/machinery/power/apc/spook() - if(spooky) return // Fuck you we're already spooky - if(!..()) return //If blessed, return - - spooky=1 - update_icon() - spawn(10) - spooky=0 - update_icon() - -//attack with an item - open/close cover, insert cell, or (un)lock interface -/obj/machinery/power/apc/attackby(obj/item/W, mob/user) - if (istype(user, /mob/living/silicon) && get_dist(src,user)>1) - return src.attack_hand(user) - src.add_fingerprint(user) - if (istype(W, /obj/item/weapon/crowbar) && opened) - if (has_electronics==1) - if (terminal) - to_chat(user, "Disconnect wires first.") - return - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - to_chat(user, "You are trying to remove the power control board...")//lpeters - fixed grammar issues - - if (do_after(user, src, 50) && opened && !terminal && has_electronics == 1) - has_electronics = 0 - if ((stat & BROKEN) || malfhack) - user.visible_message(\ - "[user.name] has broken the power control board inside [src.name]!",\ - "You broke the charred power control board and remove the remains.", - "You hear a crack!") - //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0 - else - user.visible_message(\ - "[user.name] has removed the power control board from [src.name]!",\ - "You remove the power control board.") - new /obj/item/weapon/circuitboard/power_control(loc) - else if (opened!=2) //cover isn't removed - opened = 0 - update_icon() - else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) ) - if(coverlocked && !(stat & MAINT)) - to_chat(user, "The cover is locked and cannot be opened.") - return - else - opened = 1 - update_icon() - else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside - if(cell) - - if(user.drop_item(W, src)) - to_chat(user, "You swap the power cell within with the new cell in your hand.") - var/obj/item/weapon/oldpowercell = cell - cell = W - chargecount = 0 - update_icon() - user.put_in_hands(oldpowercell) - return - - else - if (stat & MAINT) - to_chat(user, "There is no connector for your power cell.") - return - if(user.drop_item(W, src)) - cell = W - user.visible_message(\ - "[user.name] has inserted the power cell to [src.name]!",\ - "You insert the power cell.") - chargecount = 0 - update_icon() - else if (istype(W, /obj/item/weapon/screwdriver)) // haxing - if(opened) - if (cell) - to_chat(user, "Close the APC first.")//Less hints more mystery! - - return - else - if (has_electronics==1 && terminal) - has_electronics = 2 - stat &= ~MAINT - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You screw the circuit electronics into place.") - else if (has_electronics==2) - has_electronics = 1 - stat |= MAINT - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You unfasten the electronics.") - else /* has_electronics==0 */ - to_chat(user, "There is nothing to secure.") - return - update_icon() - else if(emagged) - to_chat(user, "The interface is broken.") - else if(has_electronics == 2) - wiresexposed = !wiresexposed - to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"].") - update_icon() - else - to_chat(user, "You open the panel and find nothing inside.") - return - - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card - if(emagged) - to_chat(user, "The interface is broken.") - else if(opened) - to_chat(user, "You must close the cover to swipe an ID card.") - else if(wiresexposed) - to_chat(user, "You must close the panel") - else if(stat & (BROKEN|MAINT)) - to_chat(user, "Nothing happens.") - else - if(src.allowed(usr) && !isWireCut(APC_WIRE_IDSCAN)) - locked = !locked - to_chat(user, "You [ locked ? "lock" : "unlock"] the APC interface.") - update_icon() - else - to_chat(user, "Access denied.") - else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card - if(opened) - to_chat(user, "You must close the cover to swipe an ID card.") - else if(wiresexposed) - to_chat(user, "You must close the panel first") - else if(stat & (BROKEN|MAINT)) - to_chat(user, "Nothing happens.") - else - flick("apc-spark", src) - if (do_after(user, src, 6) && !opened && !wiresexposed && !(stat & (BROKEN|MAINT)) && !emagged) - if(prob(50)) - emagged = 1 - locked = 0 - to_chat(user, "You emag the APC interface.") - update_icon() - else - to_chat(user, "You fail to [ locked ? "unlock" : "lock"] the APC interface.") - else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics != 2) - var/obj/item/stack/cable_coil/C = W - if(C.amount < 10) - to_chat(user, "You need more wires.") - return - - if(make_terminal(user)) - C.use(10) - terminal.connect_to_network() - - else if (istype(W, /obj/item/weapon/wirecutters) && opened && terminal && has_electronics!=2) - var/turf/T = get_turf(src) - if (T.intact) - to_chat(user, "You must remove the floor plating in front of the APC first.") - return - to_chat(user, "You begin to cut the cables...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if (do_after(user, src, 50) && opened && terminal && has_electronics != 2 && !T.intact) - if (prob(50) && electrocute_mob(usr, terminal.get_powernet(), terminal)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - return - getFromPool(/obj/item/stack/cable_coil, get_turf(user), 10) - user.visible_message(\ - "[user.name] cut the cables and dismantled the power terminal.",\ - "You cut the cables and dismantle the power terminal.") - qdel(terminal) - terminal = null - else if (istype(W, /obj/item/weapon/circuitboard/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack)) - to_chat(user, "You begin to insert the power control board into the frame...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if (do_after(user, src, 10) && opened && has_electronics == 0 && !((stat & BROKEN) || malfhack)) - has_electronics = 1 - to_chat(user, "You place the power control board inside the frame.") - qdel(W) - W = null - else if (istype(W, /obj/item/weapon/circuitboard/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack)) - to_chat(user, "You cannot put the board inside, the frame is damaged.") - return - else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal) - var/obj/item/weapon/weldingtool/WT = W - if (WT.get_fuel() < 3) - to_chat(user, "You need more welding fuel to complete this task.") - return - to_chat(user, "You start welding the APC frame...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) - if (do_after(user, src, 50)) - if(!src || !WT.remove_fuel(3, user)) return - if (emagged || malfhack || (stat & BROKEN) || opened==2) - getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 1) - user.visible_message(\ - "[src] has been cut apart by [user.name] with the weldingtool.",\ - "You disassembled the broken APC frame.",\ - "You hear welding.") - else - new /obj/item/mounted/frame/apc_frame(loc) - user.visible_message(\ - "[src] has been cut from the wall by [user.name] with the weldingtool.",\ - "You cut the APC frame from the wall.",\ - "You hear welding.") - qdel(src) - return - else if (istype(W, /obj/item/mounted/frame/apc_frame) && opened && emagged) - emagged = 0 - if (opened==2) - opened = 1 - user.visible_message(\ - "[user.name] has replaced the damaged APC frontal panel with a new one.",\ - "You replace the damaged APC frontal panel with a new one.") - qdel(W) - W = null - update_icon() - else if (istype(W, /obj/item/mounted/frame/apc_frame) && opened && ((stat & BROKEN) || malfhack)) - if (has_electronics) - to_chat(user, "You cannot repair this APC until you remove the electronics still inside.") - return - to_chat(user, "You begin to replace the damaged APC frame...") - if(do_after(user, src, 50)) - user.visible_message(\ - "[user.name] has replaced the damaged APC frame with new one.",\ - "You replace the damaged APC frame with new one.") - qdel(W) - W = null - stat &= ~BROKEN - malfai = null - malfhack = 0 - if (opened==2) - opened = 1 - update_icon() - else - // The extra crowbar thing fixes MoMMIs not being able to remove APCs. - // They can just pop them off with a crowbar. - if ( ((stat & BROKEN) || malfhack) \ - && !opened \ - && ( \ - (W.force >= 5 && W.w_class >= 3.0) \ - || istype(W,/obj/item/weapon/crowbar) \ - ) \ - && prob(20) ) - opened = 2 - user.visible_message("The APC cover was knocked down with the [W.name] by [user.name]!", \ - "You knock down the APC cover with your [W.name]!", \ - "You hear bang") - update_icon() - else - if (istype(user, /mob/living/silicon)) - return src.attack_hand(user) - if (!opened && wiresexposed && \ - (istype(W, /obj/item/device/multitool) || \ - istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler))) - return src.attack_hand(user) - /*user.visible_message("The [src.name] has been hit with the [W.name] by [user.name]!", \ - "You hit the [src.name] with your [W.name]!", \ - "You hear bang")*/ - ..() //Sanity - -// attack with hand - remove cell (if cover open) or interact with the APC - -/obj/machinery/power/apc/attack_hand(mob/user) -// if (!can_use(user)) This already gets called in interact() and in topic() -// return - if(!user) - return - if(!isobserver(user)) - src.add_fingerprint(user) - if(usr == user && opened) - if(cell && get_dist(src,user)<=1) - if(issilicon(user) && !isMoMMI(user)) // MoMMIs can hold one item in their tool slot. - cell.loc=src.loc // Drop it, whoops. - else - user.put_in_hands(cell) - - cell.add_fingerprint(user) - cell.updateicon() - - src.cell = null - user.visible_message("[user.name] removes the power cell from [src.name]!", "You remove the power cell.") -// to_chat(user, "You remove the power cell.") - charging = 0 - src.update_icon() - return - if(stat & (BROKEN|MAINT)) - return - - src.interact(user) - -/obj/machinery/power/apc/attack_alien(mob/living/carbon/alien/humanoid/user) - if(!user) - return - user.delayNextAttack(8) - user.visible_message("[user.name] slashes at the [src.name]!", "You slash at the [src.name]!") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 100, 1) - - var/allcut = wires.IsAllCut() - - if(beenhit >= pick(3, 4) && wiresexposed != 1) - wiresexposed = 1 - src.update_icon() - src.visible_message("The [src.name]'s cover flies open, exposing the wires!") - - else if(wiresexposed == 1 && allcut == 0) - wires.CutAll() - src.update_icon() - src.visible_message("The [src.name]'s wires are shredded!") - else - beenhit += 1 - return - - -/obj/machinery/power/apc/interact(mob/user) - if (!user) - return - - if (wiresexposed) - wires.Interact(user) - - if (stat & (BROKEN | MAINT | EMPED)) - return - - ui_interact(user) - -/obj/machinery/power/apc/proc/get_malf_status(mob/user) - if (ticker && ticker.mode && (user.mind in ticker.mode.malf_ai) && istype(user, /mob/living/silicon/ai)) - if (src.malfai == (user:parent ? user:parent : user)) - if (src.occupant == user) - return 3 // 3 = User is shunted in this APC - else if (istype(user.loc, /obj/machinery/power/apc)) - return 4 // 4 = User is shunted in another APC - else - return 2 // 2 = APC hacked by user, and user is in its core. - else - return 1 // 1 = APC not hacked. - else - return 0 // 0 = User is not a Malf AI - -/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - if(!user) - return - - var/list/data = list( - "locked" = locked, - "isOperating" = operating, - "externalPower" = main_status, - "powerCellStatus" = cell ? cell.percent() : null, - "chargeMode" = chargemode, - "chargingStatus" = charging, - "totalLoad" = lastused_equip + lastused_light + lastused_environ, - "coverLocked" = coverlocked, - "siliconUser" = istype(user, /mob/living/silicon) || isAdminGhost(user), // Allow aghosts to fuck with APCs - "malfStatus" = get_malf_status(user), - - "powerChannels" = list( - list( - "title" = "Equipment", - "powerLoad" = lastused_equip, - "status" = equipment, - "topicParams" = list( - "auto" = list("eqp" = 3), - "on" = list("eqp" = 2), - "off" = list("eqp" = 1) - ) - ), - list( - "title" = "Lighting", - "powerLoad" = lastused_light, - "status" = lighting, - "topicParams" = list( - "auto" = list("lgt" = 3), - "on" = list("lgt" = 2), - "off" = list("lgt" = 1) - ) - ), - list( - "title" = "Environment", - "powerLoad" = lastused_environ, - "status" = environ, - "topicParams" = list( - "auto" = list("env" = 3), - "on" = list("env" = 2), - "off" = list("env" = 1) - ) - ) - ) - ) - - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "apc.tmpl", "[areaMaster.name] - APC", 520, data["siliconUser"] ? 465 : 440) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -/obj/machinery/power/apc/proc/report() - return "[areaMaster.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" - -/obj/machinery/power/apc/proc/update() - if(operating && !shorted) - areaMaster.power_light = (lighting > 1) - areaMaster.power_equip = (equipment > 1) - areaMaster.power_environ = (environ > 1) -// if (area.name == "AI Chamber") -// spawn(10) -// to_chat(world, " [area.name] [area.power_equip]") - else - areaMaster.power_light = 0 - areaMaster.power_equip = 0 - areaMaster.power_environ = 0 -// if (area.name == "AI Chamber") -// to_chat(world, "[area.power_equip]") - areaMaster.power_change() - -/obj/machinery/power/apc/proc/isWireCut(var/wireIndex) - return wires.IsIndexCut(wireIndex) - - -/obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic() - if (user.stat && !isobserver(user)) - to_chat(user, "You must be conscious to use this [src]!") - return 0 - if(!user.client) - return 0 - if (!user.dexterity_check()) - to_chat(user, "You don't have the dexterity to use this [src]!") - nanomanager.close_user_uis(user, src) - - return 0 - if(user.restrained()) - to_chat(user, "You must have free hands to use this [src]") - return 0 - if(user.lying) - to_chat(user, "You must stand to use this [src]!") - return 0 - if (istype(user, /mob/living/silicon)) - var/mob/living/silicon/ai/AI = user - var/mob/living/silicon/robot/robot = user - if ( \ - src.aidisabled || \ - malfhack && istype(malfai) && \ - ( \ - (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \ - (istype(robot) && (robot in malfai.connected_robots)) \ - ) \ - ) - if(!loud) - to_chat(user, "\The [src] have AI control disabled!") - nanomanager.close_user_uis(user, src) - - return 0 - else if(isobserver(user)) - if(malfhack && istype(malfai) && !isAdminGhost(user)) - if(!loud) - to_chat(user, "\The [src] have AI control disabled!") - nanomanager.close_user_uis(user, src) - return 0 - else - if ((!in_range(src, user) || !istype(src.loc, /turf))) - nanomanager.close_user_uis(user, src) - - return 0 - - var/mob/living/carbon/human/H = user - if (istype(H)) - if(H.getBrainLoss() >= 60) - for(var/mob/M in viewers(src, null)) - to_chat(M, "[H] stares cluelessly at [src] and drools.") - return 0 - else if(prob(H.getBrainLoss())) - to_chat(user, "You momentarily forget how to use [src].") - return 0 - return 1 - -/obj/machinery/power/apc/Topic(href, href_list) - if(..()) - return 0 - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - if(!can_use(usr, 1)) - return 0 - if(!istype(usr, /mob/living/silicon) && locked) - // Shouldn't happen, this is here to prevent href exploits - to_chat(usr, "You must unlock the panel to use this!") - return 1 - if (href_list["lock"]) - coverlocked = !coverlocked - - else if (href_list["breaker"]) - toggle_breaker() - - else if (href_list["cmode"]) - chargemode = !chargemode - if(!chargemode) - charging = 0 - update_icon() - - else if (href_list["eqp"]) - var/val = text2num(href_list["eqp"]) - equipment = setsubsystem(val) - update_icon() - update() - - else if (href_list["lgt"]) - var/val = text2num(href_list["lgt"]) - lighting = setsubsystem(val) - update_icon() - update() - - else if (href_list["env"]) - var/val = text2num(href_list["env"]) - environ = setsubsystem(val) - update_icon() - update() - - else if (href_list["overload"]) - if(istype(usr, /mob/living/silicon)) - src.overload_lighting() - - else if (href_list["malfhack"]) - var/mob/living/silicon/ai/malfai = usr - if(get_malf_status(malfai)==1) - if (malfai.malfhacking) - to_chat(malfai, "You are already hacking an APC.") - return 1 - to_chat(malfai, "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process.") - malfai.malfhack = src - malfai.malfhacking = 1 - sleep(600) - if(src && malfai) - if (!src.aidisabled) - malfai.malfhack = null - malfai.malfhacking = 0 - locked = 1 - if (ticker.mode.config_tag == "malfunction") - if (STATION_Z == z) - ticker.mode:apcs++ - if(usr:parent) - src.malfai = usr:parent - else - src.malfai = usr - to_chat(malfai, "Hack complete. The APC is now under your exclusive control.") - update_icon() - - else if (href_list["occupyapc"]) - if(get_malf_status(usr)) - malfoccupy(usr) - - else if (href_list["deoccupyapc"]) - if(get_malf_status(usr)) - malfvacate() - - else if (href_list["toggleaccess"]) - if(istype(usr, /mob/living/silicon)) - if(emagged || (stat & (BROKEN|MAINT))) - to_chat(usr, "The APC does not respond to the command.") - else - locked = !locked - update_icon() - - return 1 - -/obj/machinery/power/apc/proc/toggle_breaker() - operating = !operating - - if(malfai) - if (ticker.mode.config_tag == "malfunction") - if (STATION_Z == z) - operating ? ticker.mode:apcs++ : ticker.mode:apcs-- - - src.update() - update_icon() - -/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf) - if(!istype(malf)) - return - if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC - to_chat(malf, "You must evacuate your current apc first.") - return - if(!malf.can_shunt) - to_chat(malf, "You cannot shunt.") - return - if(STATION_Z != z) - return - src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1) - src.occupant.adjustOxyLoss(malf.getOxyLoss()) - if(!findtext(src.occupant.name,"APC Copy")) - src.occupant.name = "[malf.name] APC Copy" - if(malf.parent) - src.occupant.parent = malf.parent - else - src.occupant.parent = malf - malf.mind.transfer_to(src.occupant) - src.occupant.eyeobj.name = "[src.occupant.name] (AI Eye)" - if(malf.parent) - qdel(malf) - malf = null - src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn - src.occupant.verbs += /datum/game_mode/malfunction/proc/takeover - src.occupant.cancel_camera() - if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) - for(var/obj/item/weapon/pinpointer/point in world) - point.the_disk = src //the pinpointer will detect the shunted AI - - -/obj/machinery/power/apc/proc/malfvacate(var/forced) - if(!src.occupant) - return - if(src.occupant.parent && src.occupant.parent.stat != 2) - src.occupant.mind.transfer_to(src.occupant.parent) - src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss()) - src.occupant.parent.cancel_camera() - qdel(src.occupant) - src.occupant = null - if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) - for(var/obj/item/weapon/pinpointer/point in world) - for(var/datum/mind/AI_mind in ticker.mode.malf_ai) - var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns - if(A.stat != DEAD) - point.the_disk = A //The pinpointer tracks the AI back into its core. - - else - to_chat(src.occupant, "Primary core damaged, unable to return core processes.") - if(forced) - src.occupant.loc = src.loc - src.occupant.death() - src.occupant.gib() - for(var/obj/item/weapon/pinpointer/point in world) - point.the_disk = null //the pinpointer will go back to pointing at the nuke disc. - - -/obj/machinery/power/apc/proc/ion_act() - //intended to be exactly the same as an AI malf attack - if(!src.malfhack && STATION_Z == z) - if(prob(3)) - src.locked = 1 - if (src.cell.charge > 0) -// to_chat(world, "blew APC in [src.loc.loc]") - src.cell.charge = 0 - cell.corrupt() - src.malfhack = 1 - update_icon() - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(3, 0, src.loc) - smoke.attach(src) - smoke.start() - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - for(var/mob/M in viewers(src)) - M.show_message("The [src.name] suddenly lets out a blast of smoke and some sparks!", 1, "You hear sizzling electronics.", 2) - -/obj/machinery/power/apc/can_attach_terminal(mob/user) - return user.loc == src.loc && has_electronics != 2 && !terminal - -/obj/machinery/power/apc/surplus() - if(terminal) - return terminal.surplus() - else - return 0 - -/obj/machinery/power/apc/add_load(var/amount) - if(terminal && terminal.get_powernet()) - terminal.powernet.load += amount - -/obj/machinery/power/apc/avail() - if(terminal) - return terminal.avail() - else - return 0 - -/obj/machinery/power/apc/process() - - if(stat & (BROKEN|MAINT)) - return - if(!areaMaster.requires_power) - return - - /* - if (equipment > 1) // off=0, off auto=1, on=2, on auto=3 - use_power(src.equip_consumption, EQUIP) - if (lighting > 1) // off=0, off auto=1, on=2, on auto=3 - use_power(src.light_consumption, LIGHT) - if (environ > 1) // off=0, off auto=1, on=2, on auto=3 - use_power(src.environ_consumption, ENVIRON) - - area.calc_lighting() */ - - lastused_light = areaMaster.usage(LIGHT) - lastused_light += areaMaster.usage(STATIC_LIGHT) - lastused_equip = areaMaster.usage(EQUIP) - lastused_light += areaMaster.usage(STATIC_EQUIP) - lastused_environ = areaMaster.usage(ENVIRON) - lastused_light += areaMaster.usage(STATIC_ENVIRON) - areaMaster.clear_usage() - - lastused_total = lastused_light + lastused_equip + lastused_environ - - //store states to update icon if any change - var/last_lt = lighting - var/last_eq = equipment - var/last_en = environ - var/last_ch = charging - - var/excess = surplus() - - if(!src.avail()) - main_status = 0 - else if(excess < 0) - main_status = 1 - else - main_status = 2 - - //if(debug) - // world.log << "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]" - - if(cell && !shorted) - - // draw power from cell as before to power the area - var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell - cell.use(cellused) - - if(excess > lastused_total) // if power excess recharge the cell - // by the same amount just used - cell.give(cellused) - add_load(cellused/CELLRATE) // add the load used to recharge the cell - - - else // no excess, and not enough per-apc - - if((cell.charge / CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage? - cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * excess) //recharge with what we can - add_load(excess) // so draw what we can from the grid - charging = 0 - - else // not enough power available to run the last tick! - charging = 0 - chargecount = 0 - // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room. - equipment = autoset(equipment, 0) - lighting = autoset(lighting, 0) - environ = autoset(environ, 0) - - - // set channels depending on how much charge we have left - - // Allow the APC to operate as normal if the cell can charge - if(charging && longtermpower < 10) - longtermpower += 1 - else if(longtermpower > -10) - longtermpower -= 2 - - - if(cell.charge <= 0) // zero charge, turn all off - equipment = autoset(equipment, 0) - lighting = autoset(lighting, 0) - environ = autoset(environ, 0) - if(areaMaster.poweralm) - areaMaster.poweralert(0, src) - else if(cell.percent() < 15 && longtermpower < 0) // <15%, turn off lighting & equipment - equipment = autoset(equipment, 2) - lighting = autoset(lighting, 2) - environ = autoset(environ, 1) - if(areaMaster.poweralm) - areaMaster.poweralert(0, src) - else if(cell.percent() < 30 && longtermpower < 0) // <30%, turn off equipment - equipment = autoset(equipment, 2) - lighting = autoset(lighting, 1) - environ = autoset(environ, 1) - if(areaMaster.poweralm) - areaMaster.poweralert(0, src) - else // otherwise all can be on - equipment = autoset(equipment, 1) - lighting = autoset(lighting, 1) - environ = autoset(environ, 1) - if(cell.percent() > 75 && !areaMaster.poweralm) - areaMaster.poweralert(1, src) - - // now trickle-charge the cell - - if(chargemode && charging == 1 && operating) - if(excess > 0) // check to make sure we have enough to charge - // Max charge is capped to % per second constant - var/ch = min(excess * CELLRATE, cell.maxcharge * CHARGELEVEL) - add_load(ch/CELLRATE) // Removes the power we're taking from the grid - cell.give(ch) // actually recharge the cell - - else - charging = 0 // stop charging - chargecount = 0 - - // show cell as fully charged if so - if(cell.charge >= cell.maxcharge) - cell.charge = cell.maxcharge - charging = 2 - - if(chargemode) - if(!charging) - if(excess > cell.maxcharge*CHARGELEVEL) - chargecount++ - else - chargecount = 0 - charging = 0 - - if(chargecount == 10) - - chargecount = 0 - charging = 1 - - else // chargemode off - charging = 0 - chargecount = 0 - - else // no cell, switch everything off - - charging = 0 - chargecount = 0 - equipment = autoset(equipment, 0) - lighting = autoset(lighting, 0) - environ = autoset(environ, 0) - areaMaster.poweralert(0, src) - - // update icon & area power if anything changed - if(last_lt != lighting || last_eq != equipment || last_en != environ) - queue_icon_update() - update() - else if (last_ch != charging) - queue_icon_update() - -// val 0=off, 1=off(auto) 2=on 3=on(auto) -// on 0=off, 1=on, 2=autooff - -obj/machinery/power/apc/proc/autoset(var/val, var/on) - if(on==0) - if(val==2) // if on, return off - return 0 - else if(val==3) // if auto-on, return auto-off - return 1 - - else if(on==1) - if(val==1) // if auto-off, return auto-on - return 3 - - else if(on==2) - if(val==3) // if auto-on, return auto-off - return 1 - - return val - -// damage and destruction acts - -/obj/machinery/power/apc/emp_act(severity) - flick("apc-spark", src) - if(cell) - cell.emp_act(severity) - if(occupant) - occupant.emp_act(severity) - lighting = 0 - equipment = 0 - environ = 0 - update() - spawn(600/severity) - lighting = 3 - equipment = 3 - environ = 3 - update() - ..() - -/obj/machinery/power/apc/ex_act(severity) - - switch(severity) - if(1.0) - //set_broken() //now Destroy() do what we need - if (cell) - cell.ex_act(1.0) // more lags woohoo - qdel(src) - return - if(2.0) - if (prob(50)) - set_broken() - if (cell && prob(50)) - cell.ex_act(2.0) - if(3.0) - if (prob(25)) - set_broken() - if (cell && prob(25)) - cell.ex_act(3.0) - return - -/obj/machinery/power/apc/blob_act() - if (prob(75)) - set_broken() - if (cell && prob(5)) - cell.blob_act() - -/obj/machinery/power/apc/proc/set_broken() - if(malfai && operating) - if (ticker.mode.config_tag == "malfunction") - if (STATION_Z == z) - ticker.mode:apcs-- - stat |= BROKEN - operating = 0 - if(occupant) - malfvacate(1) - update_icon() - update() - -// overload all the lights in this APC area - -/obj/machinery/power/apc/proc/overload_lighting() - if(/* !get_connection() || */ !operating || shorted) - return - if( cell && cell.charge>=20) - cell.use(20); - spawn(0) - for(var/obj/machinery/light/L in areaMaster) - L.on = 1 - L.broken() - sleep(1) - -/obj/machinery/power/apc/Destroy() - areaMaster.remove_apc(src) - if(malfai && operating) - if (ticker.mode.config_tag == "malfunction") - if (STATION_Z == z) - ticker.mode:apcs-- - areaMaster.power_light = 0 - areaMaster.power_equip = 0 - areaMaster.power_environ = 0 - areaMaster.power_change() - if(occupant) - malfvacate(1) - - if(cell) - cell.loc = loc - cell = null - - if(terminal) - terminal.master = null - terminal = null - - if(wires) - qdel(wires) - wires = null - - ..() - -/obj/machinery/power/apc/proc/setsubsystem(val) - if(cell && cell.charge > 0) - return (val==1) ? 0 : val - else if(val == 3) - return 1 - else - return 0 - -/obj/machinery/power/apc/cultify() - if(src.invisibility != INVISIBILITY_MAXIMUM) - src.invisibility = INVISIBILITY_MAXIMUM - -/obj/machinery/power/apc/change_area(oldarea, newarea) - ..() - name = replacetext(name,oldarea,newarea) - -/obj/machinery/power/apc/wirejack(var/mob/living/silicon/pai/P) - if(..()) - locked = !locked - update_icon() - return 1 - return 0 - -#undef APC_UPDATE_ICON_COOLDOWN +#define APC_WIRE_IDSCAN 1 +#define APC_WIRE_MAIN_POWER1 2 +#define APC_WIRE_MAIN_POWER2 3 +#define APC_WIRE_AI_CONTROL 4 + +//update_state +#define UPSTATE_CELL_IN 1 +#define UPSTATE_OPENED1 2 +#define UPSTATE_OPENED2 4 +#define UPSTATE_MAINT 8 +#define UPSTATE_BROKE 16 +#define UPSTATE_BLUESCREEN 32 +#define UPSTATE_WIREEXP 64 +#define UPSTATE_ALLGOOD 128 + +//update_overlay +#define APC_UPOVERLAY_CHARGEING0 1 +#define APC_UPOVERLAY_CHARGEING1 2 +#define APC_UPOVERLAY_CHARGEING2 4 +#define APC_UPOVERLAY_EQUIPMENT0 8 +#define APC_UPOVERLAY_EQUIPMENT1 16 +#define APC_UPOVERLAY_EQUIPMENT2 32 +#define APC_UPOVERLAY_LIGHTING0 64 +#define APC_UPOVERLAY_LIGHTING1 128 +#define APC_UPOVERLAY_LIGHTING2 256 +#define APC_UPOVERLAY_ENVIRON0 512 +#define APC_UPOVERLAY_ENVIRON1 1024 +#define APC_UPOVERLAY_ENVIRON2 2048 +#define APC_UPOVERLAY_LOCKED 4096 +#define APC_UPOVERLAY_OPERATING 8192 + +#define APC_UPDATE_ICON_COOLDOWN 100 // 10 seconds + + +// the Area Power Controller (APC), formerly Power Distribution Unit (PDU) +// one per area, needs wire conection to power network through a terminal + +// controls power to devices in that area +// may be opened to change power cell +// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto + + +//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx + + +/obj/machinery/power/apc + desc = "A control terminal for the area electrical systems." + icon_state = "apc0" + anchored = 1 + use_power = 0 + req_access = list(access_engine_equip) + var/spooky=0 + var/obj/item/weapon/cell/cell + var/start_charge = 90 // initial cell charge % + var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500 + var/opened = 0 //0=closed, 1=opened, 2=cover removed + var/shorted = 0 + var/lighting = 3 + var/equipment = 3 + var/environ = 3 + var/operating = 1 + var/charging = 0 + var/chargemode = 1 + var/chargecount = 0 + var/locked = 1 + var/coverlocked = 1 + var/aidisabled = 0 + var/tdir = null + var/lastused_light = 0 + var/lastused_equip = 0 + var/lastused_environ = 0 + var/lastused_total = 0 + var/main_status = 0 + var/wiresexposed = 0 + powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :( + var/malfhack = 0 //New var for my changes to AI malf. --NeoFite + var/mob/living/silicon/ai/malfai = null //See above --NeoFite +// luminosity = 1 + var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver + var/overload = 1 //used for the Blackout malf module + var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment + var/mob/living/silicon/ai/occupant = null + var/longtermpower = 10 + var/update_state = -1 + var/update_overlay = -1 + var/global/status_overlays = 0 + var/updating_icon = 0 + var/datum/wires/apc/wires = null + var/global/list/status_overlays_lock + var/global/list/status_overlays_charging + var/global/list/status_overlays_equipment + var/global/list/status_overlays_lighting + var/global/list/status_overlays_environ + + var/is_critical = 0 // Endgame scenarios will not destroy this APC. + + machine_flags = WIREJACK + +/obj/machinery/power/apc/New(loc, var/ndir, var/building=0) + ..(loc) + wires = new(src) + // offset 24 pixels in direction of dir + // this allows the APC to be embedded in a wall, yet still inside an area + if (building) + dir = ndir + src.tdir = dir // to fix Vars bug + dir = SOUTH + + if(areaMaster.areaapc) + world.log << "Secondary APC detected in area: [areaMaster.name], deleting the second APC" + qdel(src) + return + areaMaster.set_apc(src) + + if(src.tdir & 3) + pixel_x = 0 + pixel_y = (src.tdir == 1 ? 24 : -24) + else + pixel_x = (src.tdir == 4 ? 24 : -24) + pixel_y = 0 + + if (building==0) + init() + else + opened = 1 + operating = 0 + stat |= MAINT + + if(ticker) + initialize() + +/obj/machinery/power/apc/proc/init() + has_electronics = 2 //installed and secured + // is starting with a power cell installed, create it and set its charge level + if(cell_type) + src.cell = new/obj/item/weapon/cell(src) + cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively) + cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value) + + finalise_terminal() //creates the terminal itself + +/obj/machinery/power/apc/finalise_terminal() + // create a terminal object at the same position as original turf loc + // wires will attach to this + terminal = new/obj/machinery/power/terminal(src.loc) + terminal.dir = tdir + terminal.master = src + +/obj/machinery/power/apc/initialize() + ..() + + name = "[areaMaster.name] APC" + + update_icon() + + spawn(5) + update() + +/obj/machinery/power/apc/examine(mob/user) + ..() + if(stat & BROKEN) + to_chat(user, "Looks broken.") + return + if(opened) + if(has_electronics && terminal) + to_chat(user, "The cover is [opened==2?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"].") + else if (!has_electronics && terminal) + to_chat(user, "There are some wires but no any electronics.") + else if (has_electronics && !terminal) + to_chat(user, "Electronics installed but not wired.") + else /* if (!has_electronics && !terminal) */ + to_chat(user, "There is no electronics nor connected wires.") + else + if (stat & MAINT) + to_chat(user, "The cover is closed. Something wrong with it: it doesn't work.") + else if (malfhack) + to_chat(user, "The cover is broken. It may be hard to force it open.") + else + to_chat(user, "The cover is closed.") + +/obj/machinery/power/apc/update_icon() + if (!status_overlays) + status_overlays = 1 + status_overlays_lock = new + status_overlays_charging = new + status_overlays_equipment = new + status_overlays_lighting = new + status_overlays_environ = new + + status_overlays_lock.len = 2 + status_overlays_charging.len = 3 + status_overlays_equipment.len = 4 + status_overlays_lighting.len = 4 + status_overlays_environ.len = 4 + + status_overlays_lock[1] = image(icon, "apcox-0") // 0=blue 1=red + status_overlays_lock[2] = image(icon, "apcox-1") + + status_overlays_charging[1] = image(icon, "apco3-0") + status_overlays_charging[2] = image(icon, "apco3-1") + status_overlays_charging[3] = image(icon, "apco3-2") + + status_overlays_equipment[1] = image(icon, "apco0-0") // 0=red, 1=green, 2=blue + status_overlays_equipment[2] = image(icon, "apco0-1") + status_overlays_equipment[3] = image(icon, "apco0-2") + status_overlays_equipment[4] = image(icon, "apco0-3") + + status_overlays_lighting[1] = image(icon, "apco1-0") + status_overlays_lighting[2] = image(icon, "apco1-1") + status_overlays_lighting[3] = image(icon, "apco1-2") + status_overlays_lighting[4] = image(icon, "apco1-3") + + status_overlays_environ[1] = image(icon, "apco2-0") + status_overlays_environ[2] = image(icon, "apco2-1") + status_overlays_environ[3] = image(icon, "apco2-2") + status_overlays_environ[4] = image(icon, "apco2-3") + + + + var/update = check_updates() //returns 0 if no need to update icons. + // 1 if we need to update the icon_state + // 2 if we need to update the overlays + if(!update) + return + + if(update & 1) // Updating the icon state + if(update_state & UPSTATE_ALLGOOD) + icon_state = "apc0" + else if(update_state & (UPSTATE_OPENED1|UPSTATE_OPENED2)) + var/basestate = "apc[ cell ? "2" : "1" ]" + if(update_state & UPSTATE_OPENED1) + if(update_state & (UPSTATE_MAINT|UPSTATE_BROKE)) + icon_state = "apcmaint" //disabled APC cannot hold cell + else + icon_state = basestate + else if(update_state & UPSTATE_OPENED2) + icon_state = "[basestate]-nocover" + else if(update_state & UPSTATE_BROKE) + icon_state = "apc-b" + else if(update_state & UPSTATE_BLUESCREEN) + icon_state = "apcemag" + else if(update_state & UPSTATE_WIREEXP) + icon_state = "apcewires" + + + + if(!(update_state & UPSTATE_ALLGOOD)) + if(overlays.len) + overlays = 0 + return + if(update & 2) + + if(overlays.len) + overlays = 0 + + if(!(stat & (BROKEN|MAINT)) && update_state & UPSTATE_ALLGOOD) + overlays += status_overlays_lock[locked+1] + overlays += status_overlays_charging[charging+1] + if(operating) + overlays += status_overlays_equipment[equipment+1] + overlays += status_overlays_lighting[lighting+1] + overlays += status_overlays_environ[environ+1] + + +/obj/machinery/power/apc/proc/check_updates() + + + var/last_update_state = update_state + var/last_update_overlay = update_overlay + update_state = 0 + update_overlay = 0 + + if(cell) + update_state |= UPSTATE_CELL_IN + if(stat & BROKEN) + update_state |= UPSTATE_BROKE + if(stat & MAINT) + update_state |= UPSTATE_MAINT + + if(opened) + if(opened==1) + update_state |= UPSTATE_OPENED1 + if(opened==2) + update_state |= UPSTATE_OPENED2 + else if(emagged || malfai || spooky) + update_state |= UPSTATE_BLUESCREEN + else if(wiresexposed) + update_state |= UPSTATE_WIREEXP + if(update_state <= 1) + update_state |= UPSTATE_ALLGOOD + + if(operating) + update_overlay |= APC_UPOVERLAY_OPERATING + + if(update_state & UPSTATE_ALLGOOD) + if(locked) + update_overlay |= APC_UPOVERLAY_LOCKED + + if(!charging) + update_overlay |= APC_UPOVERLAY_CHARGEING0 + else if(charging == 1) + update_overlay |= APC_UPOVERLAY_CHARGEING1 + else if(charging == 2) + update_overlay |= APC_UPOVERLAY_CHARGEING2 + + if (!equipment) + update_overlay |= APC_UPOVERLAY_EQUIPMENT0 + else if(equipment == 1) + update_overlay |= APC_UPOVERLAY_EQUIPMENT1 + else if(equipment == 2) + update_overlay |= APC_UPOVERLAY_EQUIPMENT2 + + if(!lighting) + update_overlay |= APC_UPOVERLAY_LIGHTING0 + else if(lighting == 1) + update_overlay |= APC_UPOVERLAY_LIGHTING1 + else if(lighting == 2) + update_overlay |= APC_UPOVERLAY_LIGHTING2 + + if(!environ) + update_overlay |= APC_UPOVERLAY_ENVIRON0 + else if(environ==1) + update_overlay |= APC_UPOVERLAY_ENVIRON1 + else if(environ==2) + update_overlay |= APC_UPOVERLAY_ENVIRON2 + + var/results = 0 + if(last_update_state == update_state && last_update_overlay == update_overlay) + return 0 + if(last_update_state != update_state) + results += 1 + if(last_update_overlay != update_overlay && update_overlay != 0) + results += 2 + return results + + + + +// Used in process so it doesn't update the icon too much +/obj/machinery/power/apc/proc/queue_icon_update() + + + if(!updating_icon) + updating_icon = 1 + // Start the update + spawn(APC_UPDATE_ICON_COOLDOWN) + update_icon() + updating_icon = 0 + +/obj/machinery/power/apc/spook() + if(spooky) return // Fuck you we're already spooky + if(!..()) return //If blessed, return + + spooky=1 + update_icon() + spawn(10) + spooky=0 + update_icon() + +//attack with an item - open/close cover, insert cell, or (un)lock interface +/obj/machinery/power/apc/attackby(obj/item/W, mob/user) + if (istype(user, /mob/living/silicon) && get_dist(src,user)>1) + return src.attack_hand(user) + src.add_fingerprint(user) + if (istype(W, /obj/item/weapon/crowbar) && opened) + if (has_electronics==1) + if (terminal) + to_chat(user, "Disconnect wires first.") + return + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + to_chat(user, "You are trying to remove the power control board...")//lpeters - fixed grammar issues + + if (do_after(user, src, 50) && opened && !terminal && has_electronics == 1) + has_electronics = 0 + if ((stat & BROKEN) || malfhack) + user.visible_message(\ + "[user.name] has broken the power control board inside [src.name]!",\ + "You broke the charred power control board and remove the remains.", + "You hear a crack!") + //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0 + else + user.visible_message(\ + "[user.name] has removed the power control board from [src.name]!",\ + "You remove the power control board.") + new /obj/item/weapon/circuitboard/power_control(loc) + else if (opened!=2) //cover isn't removed + opened = 0 + update_icon() + else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) ) + if(coverlocked && !(stat & MAINT)) + to_chat(user, "The cover is locked and cannot be opened.") + return + else + opened = 1 + update_icon() + else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside + if(cell) + + if(user.drop_item(W, src)) + to_chat(user, "You swap the power cell within with the new cell in your hand.") + var/obj/item/weapon/oldpowercell = cell + cell = W + chargecount = 0 + update_icon() + user.put_in_hands(oldpowercell) + return + + else + if (stat & MAINT) + to_chat(user, "There is no connector for your power cell.") + return + if(user.drop_item(W, src)) + cell = W + user.visible_message(\ + "[user.name] has inserted the power cell to [src.name]!",\ + "You insert the power cell.") + chargecount = 0 + update_icon() + else if (istype(W, /obj/item/weapon/screwdriver)) // haxing + if(opened) + if (cell) + to_chat(user, "Close the APC first.")//Less hints more mystery! + + return + else + if (has_electronics==1 && terminal) + has_electronics = 2 + stat &= ~MAINT + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You screw the circuit electronics into place.") + else if (has_electronics==2) + has_electronics = 1 + stat |= MAINT + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You unfasten the electronics.") + else /* has_electronics==0 */ + to_chat(user, "There is nothing to secure.") + return + update_icon() + else if(emagged) + to_chat(user, "The interface is broken.") + else if(has_electronics == 2) + wiresexposed = !wiresexposed + to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"].") + update_icon() + else + to_chat(user, "You open the panel and find nothing inside.") + return + + else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card + if(emagged) + to_chat(user, "The interface is broken.") + else if(opened) + to_chat(user, "You must close the cover to swipe an ID card.") + else if(wiresexposed) + to_chat(user, "You must close the panel") + else if(stat & (BROKEN|MAINT)) + to_chat(user, "Nothing happens.") + else + if(src.allowed(usr) && !isWireCut(APC_WIRE_IDSCAN)) + locked = !locked + to_chat(user, "You [ locked ? "lock" : "unlock"] the APC interface.") + update_icon() + else + to_chat(user, "Access denied.") + else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card + if(opened) + to_chat(user, "You must close the cover to swipe an ID card.") + else if(wiresexposed) + to_chat(user, "You must close the panel first") + else if(stat & (BROKEN|MAINT)) + to_chat(user, "Nothing happens.") + else + flick("apc-spark", src) + if (do_after(user, src, 6) && !opened && !wiresexposed && !(stat & (BROKEN|MAINT)) && !emagged) + if(prob(50)) + emagged = 1 + locked = 0 + to_chat(user, "You emag the APC interface.") + update_icon() + else + to_chat(user, "You fail to [ locked ? "unlock" : "lock"] the APC interface.") + else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics != 2) + var/obj/item/stack/cable_coil/C = W + if(C.amount < 10) + to_chat(user, "You need more wires.") + return + + if(make_terminal(user)) + C.use(10) + terminal.connect_to_network() + + else if (istype(W, /obj/item/weapon/wirecutters) && opened && terminal && has_electronics!=2) + var/turf/T = get_turf(src) + if (T.intact) + to_chat(user, "You must remove the floor plating in front of the APC first.") + return + to_chat(user, "You begin to cut the cables...") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if (do_after(user, src, 50) && opened && terminal && has_electronics != 2 && !T.intact) + if (prob(50) && electrocute_mob(usr, terminal.get_powernet(), terminal)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return + getFromPool(/obj/item/stack/cable_coil, get_turf(user), 10) + user.visible_message(\ + "[user.name] cut the cables and dismantled the power terminal.",\ + "You cut the cables and dismantle the power terminal.") + qdel(terminal) + terminal = null + else if (istype(W, /obj/item/weapon/circuitboard/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack)) + to_chat(user, "You begin to insert the power control board into the frame...") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if (do_after(user, src, 10) && opened && has_electronics == 0 && !((stat & BROKEN) || malfhack)) + has_electronics = 1 + to_chat(user, "You place the power control board inside the frame.") + qdel(W) + W = null + else if (istype(W, /obj/item/weapon/circuitboard/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack)) + to_chat(user, "You cannot put the board inside, the frame is damaged.") + return + else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal) + var/obj/item/weapon/weldingtool/WT = W + if (WT.get_fuel() < 3) + to_chat(user, "You need more welding fuel to complete this task.") + return + to_chat(user, "You start welding the APC frame...") + playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + if (do_after(user, src, 50)) + if(!src || !WT.remove_fuel(3, user)) return + if (emagged || malfhack || (stat & BROKEN) || opened==2) + getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 1) + user.visible_message(\ + "[src] has been cut apart by [user.name] with the weldingtool.",\ + "You disassembled the broken APC frame.",\ + "You hear welding.") + else + new /obj/item/mounted/frame/apc_frame(loc) + user.visible_message(\ + "[src] has been cut from the wall by [user.name] with the weldingtool.",\ + "You cut the APC frame from the wall.",\ + "You hear welding.") + qdel(src) + return + else if (istype(W, /obj/item/mounted/frame/apc_frame) && opened && emagged) + emagged = 0 + if (opened==2) + opened = 1 + user.visible_message(\ + "[user.name] has replaced the damaged APC frontal panel with a new one.",\ + "You replace the damaged APC frontal panel with a new one.") + qdel(W) + W = null + update_icon() + else if (istype(W, /obj/item/mounted/frame/apc_frame) && opened && ((stat & BROKEN) || malfhack)) + if (has_electronics) + to_chat(user, "You cannot repair this APC until you remove the electronics still inside.") + return + to_chat(user, "You begin to replace the damaged APC frame...") + if(do_after(user, src, 50)) + user.visible_message(\ + "[user.name] has replaced the damaged APC frame with new one.",\ + "You replace the damaged APC frame with new one.") + qdel(W) + W = null + stat &= ~BROKEN + malfai = null + malfhack = 0 + if (opened==2) + opened = 1 + update_icon() + else + // The extra crowbar thing fixes MoMMIs not being able to remove APCs. + // They can just pop them off with a crowbar. + if ( ((stat & BROKEN) || malfhack) \ + && !opened \ + && ( \ + (W.force >= 5 && W.w_class >= 3.0) \ + || istype(W,/obj/item/weapon/crowbar) \ + ) \ + && prob(20) ) + opened = 2 + user.visible_message("The APC cover was knocked down with the [W.name] by [user.name]!", \ + "You knock down the APC cover with your [W.name]!", \ + "You hear bang") + update_icon() + else + if (istype(user, /mob/living/silicon)) + return src.attack_hand(user) + if (!opened && wiresexposed && \ + (istype(W, /obj/item/device/multitool) || \ + istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler))) + return src.attack_hand(user) + /*user.visible_message("The [src.name] has been hit with the [W.name] by [user.name]!", \ + "You hit the [src.name] with your [W.name]!", \ + "You hear bang")*/ + ..() //Sanity + +// attack with hand - remove cell (if cover open) or interact with the APC + +/obj/machinery/power/apc/attack_hand(mob/user) +// if (!can_use(user)) This already gets called in interact() and in topic() +// return + if(!user) + return + if(!isobserver(user)) + src.add_fingerprint(user) + if(usr == user && opened) + if(cell && get_dist(src,user)<=1) + if(issilicon(user) && !isMoMMI(user)) // MoMMIs can hold one item in their tool slot. + cell.loc=src.loc // Drop it, whoops. + else + user.put_in_hands(cell) + + cell.add_fingerprint(user) + cell.updateicon() + + src.cell = null + user.visible_message("[user.name] removes the power cell from [src.name]!", "You remove the power cell.") +// to_chat(user, "You remove the power cell.") + charging = 0 + src.update_icon() + return + if(stat & (BROKEN|MAINT)) + return + + src.interact(user) + +/obj/machinery/power/apc/attack_alien(mob/living/carbon/alien/humanoid/user) + if(!user) + return + user.delayNextAttack(8) + user.visible_message("[user.name] slashes at the [src.name]!", "You slash at the [src.name]!") + playsound(get_turf(src), 'sound/weapons/slash.ogg', 100, 1) + + var/allcut = wires.IsAllCut() + + if(beenhit >= pick(3, 4) && wiresexposed != 1) + wiresexposed = 1 + src.update_icon() + src.visible_message("The [src.name]'s cover flies open, exposing the wires!") + + else if(wiresexposed == 1 && allcut == 0) + wires.CutAll() + src.update_icon() + src.visible_message("The [src.name]'s wires are shredded!") + else + beenhit += 1 + return + + +/obj/machinery/power/apc/interact(mob/user) + if (!user) + return + + if (wiresexposed) + wires.Interact(user) + + if (stat & (BROKEN | MAINT | EMPED)) + return + + ui_interact(user) + +/obj/machinery/power/apc/proc/get_malf_status(mob/user) + if (ticker && ticker.mode && (user.mind in ticker.mode.malf_ai) && istype(user, /mob/living/silicon/ai)) + if (src.malfai == (user:parent ? user:parent : user)) + if (src.occupant == user) + return 3 // 3 = User is shunted in this APC + else if (istype(user.loc, /obj/machinery/power/apc)) + return 4 // 4 = User is shunted in another APC + else + return 2 // 2 = APC hacked by user, and user is in its core. + else + return 1 // 1 = APC not hacked. + else + return 0 // 0 = User is not a Malf AI + +/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + if(!user) + return + + var/list/data = list( + "locked" = locked, + "isOperating" = operating, + "externalPower" = main_status, + "powerCellStatus" = cell ? cell.percent() : null, + "chargeMode" = chargemode, + "chargingStatus" = charging, + "totalLoad" = lastused_equip + lastused_light + lastused_environ, + "coverLocked" = coverlocked, + "siliconUser" = istype(user, /mob/living/silicon) || isAdminGhost(user), // Allow aghosts to fuck with APCs + "malfStatus" = get_malf_status(user), + + "powerChannels" = list( + list( + "title" = "Equipment", + "powerLoad" = lastused_equip, + "status" = equipment, + "topicParams" = list( + "auto" = list("eqp" = 3), + "on" = list("eqp" = 2), + "off" = list("eqp" = 1) + ) + ), + list( + "title" = "Lighting", + "powerLoad" = lastused_light, + "status" = lighting, + "topicParams" = list( + "auto" = list("lgt" = 3), + "on" = list("lgt" = 2), + "off" = list("lgt" = 1) + ) + ), + list( + "title" = "Environment", + "powerLoad" = lastused_environ, + "status" = environ, + "topicParams" = list( + "auto" = list("env" = 3), + "on" = list("env" = 2), + "off" = list("env" = 1) + ) + ) + ) + ) + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "apc.tmpl", "[areaMaster.name] - APC", 520, data["siliconUser"] ? 465 : 440) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/machinery/power/apc/proc/report() + return "[areaMaster.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" + +/obj/machinery/power/apc/proc/update() + if(operating && !shorted) + areaMaster.power_light = (lighting > 1) + areaMaster.power_equip = (equipment > 1) + areaMaster.power_environ = (environ > 1) +// if (area.name == "AI Chamber") +// spawn(10) +// to_chat(world, " [area.name] [area.power_equip]") + else + areaMaster.power_light = 0 + areaMaster.power_equip = 0 + areaMaster.power_environ = 0 +// if (area.name == "AI Chamber") +// to_chat(world, "[area.power_equip]") + areaMaster.power_change() + +/obj/machinery/power/apc/proc/isWireCut(var/wireIndex) + return wires.IsIndexCut(wireIndex) + + +/obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic() + if (user.stat && !isobserver(user)) + to_chat(user, "You must be conscious to use this [src]!") + return 0 + if(!user.client) + return 0 + if (!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to use this [src]!") + nanomanager.close_user_uis(user, src) + + return 0 + if(user.restrained()) + to_chat(user, "You must have free hands to use this [src]") + return 0 + if(user.lying) + to_chat(user, "You must stand to use this [src]!") + return 0 + if (istype(user, /mob/living/silicon)) + var/mob/living/silicon/ai/AI = user + var/mob/living/silicon/robot/robot = user + if ( \ + src.aidisabled || \ + malfhack && istype(malfai) && \ + ( \ + (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \ + (istype(robot) && (robot in malfai.connected_robots)) \ + ) \ + ) + if(!loud) + to_chat(user, "\The [src] have AI control disabled!") + nanomanager.close_user_uis(user, src) + + return 0 + else if(isobserver(user)) + if(malfhack && istype(malfai) && !isAdminGhost(user)) + if(!loud) + to_chat(user, "\The [src] have AI control disabled!") + nanomanager.close_user_uis(user, src) + return 0 + else + if ((!in_range(src, user) || !istype(src.loc, /turf))) + nanomanager.close_user_uis(user, src) + + return 0 + + var/mob/living/carbon/human/H = user + if (istype(H)) + if(H.getBrainLoss() >= 60) + for(var/mob/M in viewers(src, null)) + to_chat(M, "[H] stares cluelessly at [src] and drools.") + return 0 + else if(prob(H.getBrainLoss())) + to_chat(user, "You momentarily forget how to use [src].") + return 0 + return 1 + +/obj/machinery/power/apc/Topic(href, href_list) + if(..()) + return 0 + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + if(!can_use(usr, 1)) + return 0 + if(!istype(usr, /mob/living/silicon) && locked) + // Shouldn't happen, this is here to prevent href exploits + to_chat(usr, "You must unlock the panel to use this!") + return 1 + if (href_list["lock"]) + coverlocked = !coverlocked + + else if (href_list["breaker"]) + toggle_breaker() + + else if (href_list["cmode"]) + chargemode = !chargemode + if(!chargemode) + charging = 0 + update_icon() + + else if (href_list["eqp"]) + var/val = text2num(href_list["eqp"]) + equipment = setsubsystem(val) + update_icon() + update() + + else if (href_list["lgt"]) + var/val = text2num(href_list["lgt"]) + lighting = setsubsystem(val) + update_icon() + update() + + else if (href_list["env"]) + var/val = text2num(href_list["env"]) + environ = setsubsystem(val) + update_icon() + update() + + else if (href_list["overload"]) + if(istype(usr, /mob/living/silicon)) + src.overload_lighting() + + else if (href_list["malfhack"]) + var/mob/living/silicon/ai/malfai = usr + if(get_malf_status(malfai)==1) + if (malfai.malfhacking) + to_chat(malfai, "You are already hacking an APC.") + return 1 + to_chat(malfai, "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process.") + malfai.malfhack = src + malfai.malfhacking = 1 + sleep(600) + if(src && malfai) + if (!src.aidisabled) + malfai.malfhack = null + malfai.malfhacking = 0 + locked = 1 + if (ticker.mode.config_tag == "malfunction") + if (STATION_Z == z) + ticker.mode:apcs++ + if(usr:parent) + src.malfai = usr:parent + else + src.malfai = usr + to_chat(malfai, "Hack complete. The APC is now under your exclusive control.") + update_icon() + + else if (href_list["occupyapc"]) + if(get_malf_status(usr)) + malfoccupy(usr) + + else if (href_list["deoccupyapc"]) + if(get_malf_status(usr)) + malfvacate() + + else if (href_list["toggleaccess"]) + if(istype(usr, /mob/living/silicon)) + if(emagged || (stat & (BROKEN|MAINT))) + to_chat(usr, "The APC does not respond to the command.") + else + locked = !locked + update_icon() + + return 1 + +/obj/machinery/power/apc/proc/toggle_breaker() + operating = !operating + + if(malfai) + if (ticker.mode.config_tag == "malfunction") + if (STATION_Z == z) + operating ? ticker.mode:apcs++ : ticker.mode:apcs-- + + src.update() + update_icon() + +/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf) + if(!istype(malf)) + return + if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC + to_chat(malf, "You must evacuate your current apc first.") + return + if(!malf.can_shunt) + to_chat(malf, "You cannot shunt.") + return + if(STATION_Z != z) + return + src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1) + src.occupant.adjustOxyLoss(malf.getOxyLoss()) + if(!findtext(src.occupant.name,"APC Copy")) + src.occupant.name = "[malf.name] APC Copy" + if(malf.parent) + src.occupant.parent = malf.parent + else + src.occupant.parent = malf + malf.mind.transfer_to(src.occupant) + src.occupant.eyeobj.name = "[src.occupant.name] (AI Eye)" + if(malf.parent) + qdel(malf) + malf = null + src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn + src.occupant.verbs += /datum/game_mode/malfunction/proc/takeover + src.occupant.cancel_camera() + if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) + for(var/obj/item/weapon/pinpointer/point in world) + point.the_disk = src //the pinpointer will detect the shunted AI + + +/obj/machinery/power/apc/proc/malfvacate(var/forced) + if(!src.occupant) + return + if(src.occupant.parent && src.occupant.parent.stat != 2) + src.occupant.mind.transfer_to(src.occupant.parent) + src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss()) + src.occupant.parent.cancel_camera() + qdel(src.occupant) + src.occupant = null + if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) + for(var/obj/item/weapon/pinpointer/point in world) + for(var/datum/mind/AI_mind in ticker.mode.malf_ai) + var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns + if(A.stat != DEAD) + point.the_disk = A //The pinpointer tracks the AI back into its core. + + else + to_chat(src.occupant, "Primary core damaged, unable to return core processes.") + if(forced) + src.occupant.loc = src.loc + src.occupant.death() + src.occupant.gib() + for(var/obj/item/weapon/pinpointer/point in world) + point.the_disk = null //the pinpointer will go back to pointing at the nuke disc. + + +/obj/machinery/power/apc/proc/ion_act() + //intended to be exactly the same as an AI malf attack + if(!src.malfhack && STATION_Z == z) + if(prob(3)) + src.locked = 1 + if (src.cell.charge > 0) +// to_chat(world, "blew APC in [src.loc.loc]") + src.cell.charge = 0 + cell.corrupt() + src.malfhack = 1 + update_icon() + var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() + smoke.set_up(3, 0, src.loc) + smoke.attach(src) + smoke.start() + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + for(var/mob/M in viewers(src)) + M.show_message("The [src.name] suddenly lets out a blast of smoke and some sparks!", 1, "You hear sizzling electronics.", 2) + +/obj/machinery/power/apc/can_attach_terminal(mob/user) + return user.loc == src.loc && has_electronics != 2 && !terminal + +/obj/machinery/power/apc/surplus() + if(terminal) + return terminal.surplus() + else + return 0 + +/obj/machinery/power/apc/add_load(var/amount) + if(terminal && terminal.get_powernet()) + terminal.powernet.load += amount + +/obj/machinery/power/apc/avail() + if(terminal) + return terminal.avail() + else + return 0 + +/obj/machinery/power/apc/process() + + if(stat & (BROKEN|MAINT)) + return + if(!areaMaster.requires_power) + return + + /* + if (equipment > 1) // off=0, off auto=1, on=2, on auto=3 + use_power(src.equip_consumption, EQUIP) + if (lighting > 1) // off=0, off auto=1, on=2, on auto=3 + use_power(src.light_consumption, LIGHT) + if (environ > 1) // off=0, off auto=1, on=2, on auto=3 + use_power(src.environ_consumption, ENVIRON) + + area.calc_lighting() */ + + lastused_light = areaMaster.usage(LIGHT) + lastused_light += areaMaster.usage(STATIC_LIGHT) + lastused_equip = areaMaster.usage(EQUIP) + lastused_light += areaMaster.usage(STATIC_EQUIP) + lastused_environ = areaMaster.usage(ENVIRON) + lastused_light += areaMaster.usage(STATIC_ENVIRON) + areaMaster.clear_usage() + + lastused_total = lastused_light + lastused_equip + lastused_environ + + //store states to update icon if any change + var/last_lt = lighting + var/last_eq = equipment + var/last_en = environ + var/last_ch = charging + + var/excess = surplus() + + if(!src.avail()) + main_status = 0 + else if(excess < 0) + main_status = 1 + else + main_status = 2 + + //if(debug) + // world.log << "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]" + + if(cell && !shorted) + + // draw power from cell as before to power the area + var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell + cell.use(cellused) + + if(excess > lastused_total) // if power excess recharge the cell + // by the same amount just used + cell.give(cellused) + add_load(cellused/CELLRATE) // add the load used to recharge the cell + + + else // no excess, and not enough per-apc + + if((cell.charge / CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage? + cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * excess) //recharge with what we can + add_load(excess) // so draw what we can from the grid + charging = 0 + + else // not enough power available to run the last tick! + charging = 0 + chargecount = 0 + // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room. + equipment = autoset(equipment, 0) + lighting = autoset(lighting, 0) + environ = autoset(environ, 0) + + + // set channels depending on how much charge we have left + + // Allow the APC to operate as normal if the cell can charge + if(charging && longtermpower < 10) + longtermpower += 1 + else if(longtermpower > -10) + longtermpower -= 2 + + + if(cell.charge <= 0) // zero charge, turn all off + equipment = autoset(equipment, 0) + lighting = autoset(lighting, 0) + environ = autoset(environ, 0) + if(areaMaster.poweralm) + areaMaster.poweralert(0, src) + else if(cell.percent() < 15 && longtermpower < 0) // <15%, turn off lighting & equipment + equipment = autoset(equipment, 2) + lighting = autoset(lighting, 2) + environ = autoset(environ, 1) + if(areaMaster.poweralm) + areaMaster.poweralert(0, src) + else if(cell.percent() < 30 && longtermpower < 0) // <30%, turn off equipment + equipment = autoset(equipment, 2) + lighting = autoset(lighting, 1) + environ = autoset(environ, 1) + if(areaMaster.poweralm) + areaMaster.poweralert(0, src) + else // otherwise all can be on + equipment = autoset(equipment, 1) + lighting = autoset(lighting, 1) + environ = autoset(environ, 1) + if(cell.percent() > 75 && !areaMaster.poweralm) + areaMaster.poweralert(1, src) + + // now trickle-charge the cell + + if(chargemode && charging == 1 && operating) + if(excess > 0) // check to make sure we have enough to charge + // Max charge is capped to % per second constant + var/ch = min(excess * CELLRATE, cell.maxcharge * CHARGELEVEL) + add_load(ch/CELLRATE) // Removes the power we're taking from the grid + cell.give(ch) // actually recharge the cell + + else + charging = 0 // stop charging + chargecount = 0 + + // show cell as fully charged if so + if(cell.charge >= cell.maxcharge) + cell.charge = cell.maxcharge + charging = 2 + + if(chargemode) + if(!charging) + if(excess > cell.maxcharge*CHARGELEVEL) + chargecount++ + else + chargecount = 0 + charging = 0 + + if(chargecount == 10) + + chargecount = 0 + charging = 1 + + else // chargemode off + charging = 0 + chargecount = 0 + + else // no cell, switch everything off + + charging = 0 + chargecount = 0 + equipment = autoset(equipment, 0) + lighting = autoset(lighting, 0) + environ = autoset(environ, 0) + areaMaster.poweralert(0, src) + + // update icon & area power if anything changed + if(last_lt != lighting || last_eq != equipment || last_en != environ) + queue_icon_update() + update() + else if (last_ch != charging) + queue_icon_update() + +// val 0=off, 1=off(auto) 2=on 3=on(auto) +// on 0=off, 1=on, 2=autooff + +obj/machinery/power/apc/proc/autoset(var/val, var/on) + if(on==0) + if(val==2) // if on, return off + return 0 + else if(val==3) // if auto-on, return auto-off + return 1 + + else if(on==1) + if(val==1) // if auto-off, return auto-on + return 3 + + else if(on==2) + if(val==3) // if auto-on, return auto-off + return 1 + + return val + +// damage and destruction acts + +/obj/machinery/power/apc/emp_act(severity) + flick("apc-spark", src) + if(cell) + cell.emp_act(severity) + if(occupant) + occupant.emp_act(severity) + lighting = 0 + equipment = 0 + environ = 0 + update() + spawn(600/severity) + lighting = 3 + equipment = 3 + environ = 3 + update() + ..() + +/obj/machinery/power/apc/ex_act(severity) + + switch(severity) + if(1.0) + //set_broken() //now Destroy() do what we need + if (cell) + cell.ex_act(1.0) // more lags woohoo + qdel(src) + return + if(2.0) + if (prob(50)) + set_broken() + if (cell && prob(50)) + cell.ex_act(2.0) + if(3.0) + if (prob(25)) + set_broken() + if (cell && prob(25)) + cell.ex_act(3.0) + return + +/obj/machinery/power/apc/blob_act() + if (prob(75)) + set_broken() + if (cell && prob(5)) + cell.blob_act() + +/obj/machinery/power/apc/proc/set_broken() + if(malfai && operating) + if (ticker.mode.config_tag == "malfunction") + if (STATION_Z == z) + ticker.mode:apcs-- + stat |= BROKEN + operating = 0 + if(occupant) + malfvacate(1) + update_icon() + update() + +// overload all the lights in this APC area + +/obj/machinery/power/apc/proc/overload_lighting() + if(/* !get_connection() || */ !operating || shorted) + return + if( cell && cell.charge>=20) + cell.use(20); + spawn(0) + for(var/obj/machinery/light/L in areaMaster) + L.on = 1 + L.broken() + sleep(1) + +/obj/machinery/power/apc/Destroy() + areaMaster.remove_apc(src) + if(malfai && operating) + if (ticker.mode.config_tag == "malfunction") + if (STATION_Z == z) + ticker.mode:apcs-- + areaMaster.power_light = 0 + areaMaster.power_equip = 0 + areaMaster.power_environ = 0 + areaMaster.power_change() + if(occupant) + malfvacate(1) + + if(cell) + cell.loc = loc + cell = null + + if(terminal) + terminal.master = null + terminal = null + + if(wires) + qdel(wires) + wires = null + + ..() + +/obj/machinery/power/apc/proc/setsubsystem(val) + if(cell && cell.charge > 0) + return (val==1) ? 0 : val + else if(val == 3) + return 1 + else + return 0 + +/obj/machinery/power/apc/cultify() + if(src.invisibility != INVISIBILITY_MAXIMUM) + src.invisibility = INVISIBILITY_MAXIMUM + +/obj/machinery/power/apc/change_area(oldarea, newarea) + ..() + name = replacetext(name,oldarea,newarea) + +/obj/machinery/power/apc/wirejack(var/mob/living/silicon/pai/P) + if(..()) + locked = !locked + update_icon() + return 1 + return 0 + +#undef APC_UPDATE_ICON_COOLDOWN diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index eb9f4ae1348..1eb77a7dad5 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -1,460 +1,460 @@ -/////////////////////////////// -//CABLE STRUCTURE -/////////////////////////////// - - -//////////////////////////////// -// Definitions -//////////////////////////////// - -/* Cable directions (d1 and d2) - - - 9 1 5 - \ | / - 8 - 0 - 4 - / | \ - 10 2 6 - -If d1 = 0 and d2 = 0, there's no cable -If d1 = 0 and d2 = dir, it's a O-X cable, getting from the center of the tile to dir (knot cable) -If d1 = dir1 and d2 = dir2, it's a full X-X cable, getting from dir1 to dir2 -By design, d1 is the smallest direction and d2 is the highest -*/ - -#define CABLE_PINK "#CA00B6" -#define CABLE_ORANGE "#CA6900" - - -/obj/structure/cable - level = 1 // is underfloor - anchored =1 - var/datum/powernet/powernet - name = "power cable" - desc = "A flexible superconducting cable for heavy-duty power transfer." - icon = 'icons/obj/power_cond_white.dmi' - icon_state = "0-1" - var/d1 = 0 // cable direction 1 (see above) - var/d2 = 1 // cable direction 2 (see above) - layer = 2.44 // just below unary stuff, which is at 2.45 and above pipes, which are at 2.4 - var/obj/item/device/powersink/attached // holding this here for qdel - var/_color = "red" - - //For rebuilding powernets from scratch - var/build_status = 0 //1 means it needs rebuilding during the next tick or on usage - var/oldavail = 0 - var/oldnewavail = 0 - var/oldload = 0 - -/obj/structure/cable/yellow - _color = "yellow" - -/obj/structure/cable/green - _color = "green" - -/obj/structure/cable/blue - _color = "blue" - -/obj/structure/cable/pink - _color = "pink" - -/obj/structure/cable/orange - _color = "orange" - -/obj/structure/cable/cyan - _color = "cyan" - -/obj/structure/cable/white - _color = "white" - -// the power cable object -/obj/structure/cable/New(loc) - ..(loc) - - cableColor(_color) - - // ensure d1 & d2 reflect the icon_state for entering and exiting cable - var/dash = findtext(icon_state, "-") - d1 = text2num(copytext(icon_state, 1, dash)) - d2 = text2num(copytext(icon_state, dash + 1)) - - var/turf/T = src.loc // hide if turf is not intact - var/obj/structure/catwalk/Catwalk = (locate(/obj/structure/catwalk) in get_turf(T)) - if(!istype(T)) - if(!Catwalk) - return //It's just space, abort - if(level == 1) - hide(T.intact) - - cable_list += src //add it to the global cable list - -/obj/structure/cable/Destroy() // called when a cable is deleted - if(powernet) - powernet.set_to_build() // update the powernets - - cable_list -= src - - if(istype(attached)) - attached.set_light(0) - attached.icon_state = "powersink0" - attached.mode = 0 - processing_objects.Remove(attached) - attached.anchored = 0 - attached.attached = null - - attached = null - ..() // then go ahead and delete the cable - -/obj/structure/cable/forceMove() - .=..() - - if(powernet) - powernet.set_to_build() // update the powernets - -/obj/structure/cable/shuttle_rotate(angle) - if(d1) - d1 = turn(d1, -angle) - if(d2) - d2 = turn(d2, -angle) - - if(d1 > d2) //Cable icon states start with the lesser number. For example, there's no "8-4" icon state, but there is a "4-8". - var/oldD2 = d2 - d2 = d1 - d1 = oldD2 - - update_icon() - -/////////////////////////////////// -// General procedures -/////////////////////////////////// - -// if underfloor, hide the cable -/obj/structure/cable/hide(i) - - if(level == 1 && isturf(loc)) - invisibility = i ? 101 : 0 - - update_icon() - -/obj/structure/cable/update_icon() - if(invisibility) - icon_state = "[d1]-[d2]-f" - else - icon_state = "[d1]-[d2]" - -//Provides sanity for cases in which there may not be a powernet -//Not necessary for checking powernet during process() of power_machines as it is guaranteed to have a powernet at that time -/obj/structure/cable/proc/get_powernet() - check_rebuild() - return powernet - -// telekinesis has no effect on a cable -/obj/structure/cable/attack_tk(mob/user) - return - -// Items usable on a cable : -// - Wirecutters : cut it duh ! -// - Cable coil : merge cables -// - Multitool : get the power currently passing through the cable -/obj/structure/cable/attackby(obj/item/W, mob/user) - var/turf/T = src.loc - - if(T.intact) - return - - if(istype(W, /obj/item/weapon/wirecutters)) - if(shock(user, 50)) - return - - if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long - getFromPool(/obj/item/stack/cable_coil, T, 2, light_color) - else - getFromPool(/obj/item/stack/cable_coil, T, 1, light_color) - - user.visible_message("[user] cuts the cable.", "You cut the cable.") - - //investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires") - - var/message = "A wire has been cut " - var/atom/A = user - - if(A) - var/turf/Z = get_turf(A) - var/area/my_area = get_area(Z) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\\power\cable.dm:104: message += " in [my_area.name]. (JMP)" - message += {"in [my_area.name]. (JMP) (VV)"} - // END AUTOFIX - - var/mob/M = get(A, /mob) - - if(M) - message += " - Cut By: [M.real_name] ([M.key]) (PP) (?)" - log_game("[M.real_name] ([M.key]) cut a wire in [my_area.name] ([T.x],[T.y],[T.z])") - - message_admins(message, 0, 1) - - returnToPool(src) - return - else if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - coil.cable_join(src, user) - else if(istype(W, /obj/item/weapon/rcl)) - var/obj/item/weapon/rcl/R = W - if(R.loaded) - R.loaded.cable_join(src, user) - R.is_empty() - else if(istype(W, /obj/item/device/multitool)) - if((powernet) && (powernet.avail > 0)) // is it powered? +/////////////////////////////// +//CABLE STRUCTURE +/////////////////////////////// + + +//////////////////////////////// +// Definitions +//////////////////////////////// + +/* Cable directions (d1 and d2) + + + 9 1 5 + \ | / + 8 - 0 - 4 + / | \ + 10 2 6 + +If d1 = 0 and d2 = 0, there's no cable +If d1 = 0 and d2 = dir, it's a O-X cable, getting from the center of the tile to dir (knot cable) +If d1 = dir1 and d2 = dir2, it's a full X-X cable, getting from dir1 to dir2 +By design, d1 is the smallest direction and d2 is the highest +*/ + +#define CABLE_PINK "#CA00B6" +#define CABLE_ORANGE "#CA6900" + + +/obj/structure/cable + level = 1 // is underfloor + anchored =1 + var/datum/powernet/powernet + name = "power cable" + desc = "A flexible superconducting cable for heavy-duty power transfer." + icon = 'icons/obj/power_cond_white.dmi' + icon_state = "0-1" + var/d1 = 0 // cable direction 1 (see above) + var/d2 = 1 // cable direction 2 (see above) + layer = 2.44 // just below unary stuff, which is at 2.45 and above pipes, which are at 2.4 + var/obj/item/device/powersink/attached // holding this here for qdel + var/_color = "red" + + //For rebuilding powernets from scratch + var/build_status = 0 //1 means it needs rebuilding during the next tick or on usage + var/oldavail = 0 + var/oldnewavail = 0 + var/oldload = 0 + +/obj/structure/cable/yellow + _color = "yellow" + +/obj/structure/cable/green + _color = "green" + +/obj/structure/cable/blue + _color = "blue" + +/obj/structure/cable/pink + _color = "pink" + +/obj/structure/cable/orange + _color = "orange" + +/obj/structure/cable/cyan + _color = "cyan" + +/obj/structure/cable/white + _color = "white" + +// the power cable object +/obj/structure/cable/New(loc) + ..(loc) + + cableColor(_color) + + // ensure d1 & d2 reflect the icon_state for entering and exiting cable + var/dash = findtext(icon_state, "-") + d1 = text2num(copytext(icon_state, 1, dash)) + d2 = text2num(copytext(icon_state, dash + 1)) + + var/turf/T = src.loc // hide if turf is not intact + var/obj/structure/catwalk/Catwalk = (locate(/obj/structure/catwalk) in get_turf(T)) + if(!istype(T)) + if(!Catwalk) + return //It's just space, abort + if(level == 1) + hide(T.intact) + + cable_list += src //add it to the global cable list + +/obj/structure/cable/Destroy() // called when a cable is deleted + if(powernet) + powernet.set_to_build() // update the powernets + + cable_list -= src + + if(istype(attached)) + attached.set_light(0) + attached.icon_state = "powersink0" + attached.mode = 0 + processing_objects.Remove(attached) + attached.anchored = 0 + attached.attached = null + + attached = null + ..() // then go ahead and delete the cable + +/obj/structure/cable/forceMove() + .=..() + + if(powernet) + powernet.set_to_build() // update the powernets + +/obj/structure/cable/shuttle_rotate(angle) + if(d1) + d1 = turn(d1, -angle) + if(d2) + d2 = turn(d2, -angle) + + if(d1 > d2) //Cable icon states start with the lesser number. For example, there's no "8-4" icon state, but there is a "4-8". + var/oldD2 = d2 + d2 = d1 + d1 = oldD2 + + update_icon() + +/////////////////////////////////// +// General procedures +/////////////////////////////////// + +// if underfloor, hide the cable +/obj/structure/cable/hide(i) + + if(level == 1 && isturf(loc)) + invisibility = i ? 101 : 0 + + update_icon() + +/obj/structure/cable/update_icon() + if(invisibility) + icon_state = "[d1]-[d2]-f" + else + icon_state = "[d1]-[d2]" + +//Provides sanity for cases in which there may not be a powernet +//Not necessary for checking powernet during process() of power_machines as it is guaranteed to have a powernet at that time +/obj/structure/cable/proc/get_powernet() + check_rebuild() + return powernet + +// telekinesis has no effect on a cable +/obj/structure/cable/attack_tk(mob/user) + return + +// Items usable on a cable : +// - Wirecutters : cut it duh ! +// - Cable coil : merge cables +// - Multitool : get the power currently passing through the cable +/obj/structure/cable/attackby(obj/item/W, mob/user) + var/turf/T = src.loc + + if(T.intact) + return + + if(istype(W, /obj/item/weapon/wirecutters)) + if(shock(user, 50)) + return + + if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long + getFromPool(/obj/item/stack/cable_coil, T, 2, light_color) + else + getFromPool(/obj/item/stack/cable_coil, T, 1, light_color) + + user.visible_message("[user] cuts the cable.", "You cut the cable.") + + //investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires") + + var/message = "A wire has been cut " + var/atom/A = user + + if(A) + var/turf/Z = get_turf(A) + var/area/my_area = get_area(Z) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\\power\cable.dm:104: message += " in [my_area.name]. (JMP)" + message += {"in [my_area.name]. (JMP) (VV)"} + // END AUTOFIX + + var/mob/M = get(A, /mob) + + if(M) + message += " - Cut By: [M.real_name] ([M.key]) (PP) (?)" + log_game("[M.real_name] ([M.key]) cut a wire in [my_area.name] ([T.x],[T.y],[T.z])") + + message_admins(message, 0, 1) + + returnToPool(src) + return + else if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = W + coil.cable_join(src, user) + else if(istype(W, /obj/item/weapon/rcl)) + var/obj/item/weapon/rcl/R = W + if(R.loaded) + R.loaded.cable_join(src, user) + R.is_empty() + else if(istype(W, /obj/item/device/multitool)) + if((powernet) && (powernet.avail > 0)) // is it powered? to_chat(user, "[powernet.avail]W in power network.") - else + else to_chat(user, "The cable is not powered.") - - shock(user, 5, 0.2) - else - if(W.is_conductor()) - shock(user, 50, 0.7) - - src.add_fingerprint(user) - -// shock the user with probability prb -/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1.0) - if((get_powernet()) && (powernet.avail > 1000)) - if(!prob(prb)) - return 0 - - if(electrocute_mob(user, powernet, src, siemens_coeff)) - var/datum/effect/effect/system/spark_spread/s = new - s.set_up(5,1,src) - s.start() - return 1 - - return 0 - -// explosion handling -/obj/structure/cable/ex_act(severity) - switch(severity) - if(1.0) - returnToPool(src) - if(2.0) - if(prob(50)) - getFromPool(/obj/item/stack/cable_coil, src.loc, src.d1 ? 2 : 1, light_color) - returnToPool(src) - - if(3.0) - if(prob(25)) - getFromPool(/obj/item/stack/cable_coil, src.loc, src.d1 ? 2 : 1, light_color) - returnToPool(src) - return - -/obj/structure/cable/proc/cableColor(var/colorC = "red") - light_color = colorC - switch(colorC) - if("pink") - color = CABLE_PINK - if("orange") - color = CABLE_ORANGE - else - color = colorC - -//////////////////////////////////////////// -// Power related -/////////////////////////////////////////// - -/obj/structure/cable/proc/add_avail(var/amount) - if(get_powernet()) - powernet.newavail += amount - -/obj/structure/cable/proc/add_load(var/amount) - if(get_powernet()) - powernet.load += amount - -/obj/structure/cable/proc/surplus() - if(get_powernet()) - return powernet.avail-powernet.load - else - return 0 - -/obj/structure/cable/proc/avail() - if(get_powernet()) - return powernet.avail - else - return 0 - -/obj/structure/cable/proc/check_rebuild() - if(!build_status) - return - rebuild_from() - -///////////////////////////////////////////////// -// Cable laying helpers -//////////////////////////////////////////////// - -// handles merging diagonally matching cables -// for info : direction ^ 3 is flipping horizontally, direction ^ 12 is flipping vertically -/obj/structure/cable/proc/mergeDiagonalsNetworks(var/direction) - // search for and merge diagonally matching cables from the first direction component (north / south) - var/turf/T = get_step(src, direction & 3) // go north / south - - for(var/obj/structure/cable/C in T) - if(!C) - continue - if(src == C) - continue - if(C.d1 == (direction ^ 3) || C.d2 == (direction ^ 3)) // we've got a diagonally matching cable - if(!C.powernet) // if the matching cable somehow got no powernet, make him one (should not happen for cables) - var/datum/powernet/newPN = getFromPool(/datum/powernet/) - newPN.add_cable(C) - if(powernet) //if we already have a powernet, then merge the two powernets - merge_powernets(powernet,C.powernet) - else - C.powernet.add_cable(src) //else, we simply connect to the matching cable powernet - - // the same from the second direction component (east / west) - T = get_step(src, direction & 12) // go east / west - - for(var/obj/structure/cable/C in T) - if(!C) - continue - if(src == C) - continue - if(C.d1 == (direction ^ 12) || C.d2 == (direction ^ 12)) // we've got a diagonally matching cable - if(!C.powernet) // if the matching cable somehow got no powernet, make him one (should not happen for cables) - var/datum/powernet/newPN = getFromPool(/datum/powernet/) - newPN.add_cable(C) - if(powernet) // if we already have a powernet, then merge the two powernets - merge_powernets(powernet, C.powernet) - else - C.powernet.add_cable(src) // else, we simply connect to the matching cable powernet - -// merge with the powernets of power objects in the given direction -/obj/structure/cable/proc/mergeConnectedNetworks(var/direction) - var/fdir = (!direction) ? 0 : turn(direction, 180) // flip the direction, to match with the source position on its turf - - if(!(d1 == direction || d2 == direction)) // if the cable is not pointed in this direction, do nothing - return - - var/turf/TB = get_step(src, direction) - - for(var/obj/structure/cable/C in TB) - if(!C) - continue - if(src == C) - continue - if(C.d1 == fdir || C.d2 == fdir) // we've got a matching cable in the neighbor turf - if(!C.powernet) // if the matching cable somehow got no powernet, make him one (should not happen for cables) - var/datum/powernet/newPN = getFromPool(/datum/powernet/) - newPN.add_cable(C) - if(powernet) // if we already have a powernet, then merge the two powernets - merge_powernets(powernet,C.powernet) - else - C.powernet.add_cable(src) // else, we simply connect to the matching cable powernet - -// merge with the powernets of power objects in the source turf -/obj/structure/cable/proc/mergeConnectedNetworksOnTurf() - var/list/to_connect = list() - var/list/connections = list() - - if(!powernet) // if we somehow have no powernet, make one (should not happen for cables) - var/datum/powernet/newPN = getFromPool(/datum/powernet/) - newPN.add_cable(src) - - // first let's add turf cables to our powernet - // then we'll connect machines on turf with a node cable is present - - for(var/datum/power_connection/C in get_turf(src)) - if(C.powernet == powernet) - continue - connections += C //we'll connect the machines after all cables are merged - - for(var/AM in loc) - if(istype(AM, /obj/structure/cable)) - var/obj/structure/cable/C = AM - //if(C.d1 == d1 || C.d2 == d1 || C.d1 == d2 || C.d2 == d2) // only connected if they have a common direction // uncomment if you don't want + wiring - if(C.powernet == powernet) - continue - if(C.powernet) - merge_powernets(powernet, C.powernet) - else - powernet.add_cable(C) // the cable was powernetless, let's just add it to our powernet - - else if(istype(AM, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/N = AM - if(!N.terminal) - continue // APC are connected through their terminal - if(N.terminal.powernet == powernet) - continue - to_connect += N.terminal // we'll connect the machines after all cables are merged - - else if(istype(AM, /obj/machinery/power)) // other power machines - var/obj/machinery/power/M = AM - if(M.powernet == powernet) - continue - to_connect += M //we'll connect the machines after all cables are merged - - // now that cables are done, let's connect found machines - for(var/obj/machinery/power/PM in to_connect) - if(!PM.connect_to_network()) - PM.disconnect_from_network() // if we somehow can't connect the machine to the new powernet, remove it from the old nonetheless - for(var/datum/power_connection/PC in connections) - if(!PC.connect()) - PC.disconnect() // if we somehow can't connect the machine to the new powernet, remove it from the old nonetheless - -////////////////////////////////////////////// -// Powernets handling helpers -////////////////////////////////////////////// - -// if powernetless_only = 1, will only get connections without powernet -/obj/structure/cable/proc/get_connections(powernetless_only = 0) - . = list() // this will be a list of all connected power objects without a powernet - var/turf/T - - // get matching cables from the first direction - if(d1) // if not a node cable - T = get_step(src, d1) - if(T) - . += power_list(T, src, turn(d1, 180), powernetless_only) // get adjacents matching cables - - if(d1 & (d1 - 1)) // diagonal direction, must check the 4 possibles adjacents tiles - T = get_step(src, d1 & 3) // go north / south - if(T) - . += power_list(T, src, d1 ^ 3, powernetless_only) // get diagonally matching cables - T = get_step(src,d1 & 12) // go east / west - if(T) - . += power_list(T, src, d1 ^ 12, powernetless_only) // get diagonally matching cables - - . += power_list(loc, src, d1, powernetless_only) // get on turf matching cables - - // do the same on the second direction (which can't be 0) - T = get_step(src, d2) - - if(T) - . += power_list(T, src, turn(d2, 180), powernetless_only) // get adjacents matching cables - - if(d2 & (d2 - 1)) // diagonal direction, must check the 4 possibles adjacents tiles - T = get_step(src, d2 & 3) // go north / south - if(T) - . += power_list(T, src, d2 ^ 3, powernetless_only) // get diagonally matching cables - T = get_step(src, d2 & 12) // go east / west - if(T) - . += power_list(T, src, d2 ^ 12, powernetless_only) // get diagonally matching cables - - . += power_list(loc, src, d2, powernetless_only) //get on turf matching cables - -// should be called after placing a cable which extends another cable, creating a "smooth" cable that no longer terminates in the centre of a turf. -// needed as this can, unlike other placements, disconnect cables -/obj/structure/cable/proc/denode() - var/turf/T1 = loc - - if(!T1) - return - - var/list/powerlist = power_list(T1, src, 0, 0) // find the other cables that ended in the centre of the turf, with or without a powernet - - if(powerlist.len>0) - var/datum/powernet/PN = getFromPool(/datum/powernet/) - propagate_network(powerlist[1], PN) // propagates the new powernet beginning at the source cable - - if(PN.is_empty()) // can happen with machines made nodeless when smoothing cables - returnToPool(PN) //powernets do not get qdelled + + shock(user, 5, 0.2) + else + if(W.is_conductor()) + shock(user, 50, 0.7) + + src.add_fingerprint(user) + +// shock the user with probability prb +/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1.0) + if((get_powernet()) && (powernet.avail > 1000)) + if(!prob(prb)) + return 0 + + if(electrocute_mob(user, powernet, src, siemens_coeff)) + var/datum/effect/effect/system/spark_spread/s = new + s.set_up(5,1,src) + s.start() + return 1 + + return 0 + +// explosion handling +/obj/structure/cable/ex_act(severity) + switch(severity) + if(1.0) + returnToPool(src) + if(2.0) + if(prob(50)) + getFromPool(/obj/item/stack/cable_coil, src.loc, src.d1 ? 2 : 1, light_color) + returnToPool(src) + + if(3.0) + if(prob(25)) + getFromPool(/obj/item/stack/cable_coil, src.loc, src.d1 ? 2 : 1, light_color) + returnToPool(src) + return + +/obj/structure/cable/proc/cableColor(var/colorC = "red") + light_color = colorC + switch(colorC) + if("pink") + color = CABLE_PINK + if("orange") + color = CABLE_ORANGE + else + color = colorC + +//////////////////////////////////////////// +// Power related +/////////////////////////////////////////// + +/obj/structure/cable/proc/add_avail(var/amount) + if(get_powernet()) + powernet.newavail += amount + +/obj/structure/cable/proc/add_load(var/amount) + if(get_powernet()) + powernet.load += amount + +/obj/structure/cable/proc/surplus() + if(get_powernet()) + return powernet.avail-powernet.load + else + return 0 + +/obj/structure/cable/proc/avail() + if(get_powernet()) + return powernet.avail + else + return 0 + +/obj/structure/cable/proc/check_rebuild() + if(!build_status) + return + rebuild_from() + +///////////////////////////////////////////////// +// Cable laying helpers +//////////////////////////////////////////////// + +// handles merging diagonally matching cables +// for info : direction ^ 3 is flipping horizontally, direction ^ 12 is flipping vertically +/obj/structure/cable/proc/mergeDiagonalsNetworks(var/direction) + // search for and merge diagonally matching cables from the first direction component (north / south) + var/turf/T = get_step(src, direction & 3) // go north / south + + for(var/obj/structure/cable/C in T) + if(!C) + continue + if(src == C) + continue + if(C.d1 == (direction ^ 3) || C.d2 == (direction ^ 3)) // we've got a diagonally matching cable + if(!C.powernet) // if the matching cable somehow got no powernet, make him one (should not happen for cables) + var/datum/powernet/newPN = getFromPool(/datum/powernet/) + newPN.add_cable(C) + if(powernet) //if we already have a powernet, then merge the two powernets + merge_powernets(powernet,C.powernet) + else + C.powernet.add_cable(src) //else, we simply connect to the matching cable powernet + + // the same from the second direction component (east / west) + T = get_step(src, direction & 12) // go east / west + + for(var/obj/structure/cable/C in T) + if(!C) + continue + if(src == C) + continue + if(C.d1 == (direction ^ 12) || C.d2 == (direction ^ 12)) // we've got a diagonally matching cable + if(!C.powernet) // if the matching cable somehow got no powernet, make him one (should not happen for cables) + var/datum/powernet/newPN = getFromPool(/datum/powernet/) + newPN.add_cable(C) + if(powernet) // if we already have a powernet, then merge the two powernets + merge_powernets(powernet, C.powernet) + else + C.powernet.add_cable(src) // else, we simply connect to the matching cable powernet + +// merge with the powernets of power objects in the given direction +/obj/structure/cable/proc/mergeConnectedNetworks(var/direction) + var/fdir = (!direction) ? 0 : turn(direction, 180) // flip the direction, to match with the source position on its turf + + if(!(d1 == direction || d2 == direction)) // if the cable is not pointed in this direction, do nothing + return + + var/turf/TB = get_step(src, direction) + + for(var/obj/structure/cable/C in TB) + if(!C) + continue + if(src == C) + continue + if(C.d1 == fdir || C.d2 == fdir) // we've got a matching cable in the neighbor turf + if(!C.powernet) // if the matching cable somehow got no powernet, make him one (should not happen for cables) + var/datum/powernet/newPN = getFromPool(/datum/powernet/) + newPN.add_cable(C) + if(powernet) // if we already have a powernet, then merge the two powernets + merge_powernets(powernet,C.powernet) + else + C.powernet.add_cable(src) // else, we simply connect to the matching cable powernet + +// merge with the powernets of power objects in the source turf +/obj/structure/cable/proc/mergeConnectedNetworksOnTurf() + var/list/to_connect = list() + var/list/connections = list() + + if(!powernet) // if we somehow have no powernet, make one (should not happen for cables) + var/datum/powernet/newPN = getFromPool(/datum/powernet/) + newPN.add_cable(src) + + // first let's add turf cables to our powernet + // then we'll connect machines on turf with a node cable is present + + for(var/datum/power_connection/C in get_turf(src)) + if(C.powernet == powernet) + continue + connections += C //we'll connect the machines after all cables are merged + + for(var/AM in loc) + if(istype(AM, /obj/structure/cable)) + var/obj/structure/cable/C = AM + //if(C.d1 == d1 || C.d2 == d1 || C.d1 == d2 || C.d2 == d2) // only connected if they have a common direction // uncomment if you don't want + wiring + if(C.powernet == powernet) + continue + if(C.powernet) + merge_powernets(powernet, C.powernet) + else + powernet.add_cable(C) // the cable was powernetless, let's just add it to our powernet + + else if(istype(AM, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/N = AM + if(!N.terminal) + continue // APC are connected through their terminal + if(N.terminal.powernet == powernet) + continue + to_connect += N.terminal // we'll connect the machines after all cables are merged + + else if(istype(AM, /obj/machinery/power)) // other power machines + var/obj/machinery/power/M = AM + if(M.powernet == powernet) + continue + to_connect += M //we'll connect the machines after all cables are merged + + // now that cables are done, let's connect found machines + for(var/obj/machinery/power/PM in to_connect) + if(!PM.connect_to_network()) + PM.disconnect_from_network() // if we somehow can't connect the machine to the new powernet, remove it from the old nonetheless + for(var/datum/power_connection/PC in connections) + if(!PC.connect()) + PC.disconnect() // if we somehow can't connect the machine to the new powernet, remove it from the old nonetheless + +////////////////////////////////////////////// +// Powernets handling helpers +////////////////////////////////////////////// + +// if powernetless_only = 1, will only get connections without powernet +/obj/structure/cable/proc/get_connections(powernetless_only = 0) + . = list() // this will be a list of all connected power objects without a powernet + var/turf/T + + // get matching cables from the first direction + if(d1) // if not a node cable + T = get_step(src, d1) + if(T) + . += power_list(T, src, turn(d1, 180), powernetless_only) // get adjacents matching cables + + if(d1 & (d1 - 1)) // diagonal direction, must check the 4 possibles adjacents tiles + T = get_step(src, d1 & 3) // go north / south + if(T) + . += power_list(T, src, d1 ^ 3, powernetless_only) // get diagonally matching cables + T = get_step(src,d1 & 12) // go east / west + if(T) + . += power_list(T, src, d1 ^ 12, powernetless_only) // get diagonally matching cables + + . += power_list(loc, src, d1, powernetless_only) // get on turf matching cables + + // do the same on the second direction (which can't be 0) + T = get_step(src, d2) + + if(T) + . += power_list(T, src, turn(d2, 180), powernetless_only) // get adjacents matching cables + + if(d2 & (d2 - 1)) // diagonal direction, must check the 4 possibles adjacents tiles + T = get_step(src, d2 & 3) // go north / south + if(T) + . += power_list(T, src, d2 ^ 3, powernetless_only) // get diagonally matching cables + T = get_step(src, d2 & 12) // go east / west + if(T) + . += power_list(T, src, d2 ^ 12, powernetless_only) // get diagonally matching cables + + . += power_list(loc, src, d2, powernetless_only) //get on turf matching cables + +// should be called after placing a cable which extends another cable, creating a "smooth" cable that no longer terminates in the centre of a turf. +// needed as this can, unlike other placements, disconnect cables +/obj/structure/cable/proc/denode() + var/turf/T1 = loc + + if(!T1) + return + + var/list/powerlist = power_list(T1, src, 0, 0) // find the other cables that ended in the centre of the turf, with or without a powernet + + if(powerlist.len>0) + var/datum/powernet/PN = getFromPool(/datum/powernet/) + propagate_network(powerlist[1], PN) // propagates the new powernet beginning at the source cable + + if(PN.is_empty()) // can happen with machines made nodeless when smoothing cables + returnToPool(PN) //powernets do not get qdelled diff --git a/code/modules/power/cable_logic.dm b/code/modules/power/cable_logic.dm index 3a3b6f9180e..a7d2316cb99 100644 --- a/code/modules/power/cable_logic.dm +++ b/code/modules/power/cable_logic.dm @@ -1,292 +1,292 @@ -#define LOGIC_HIGH 5 - -//Indicators only have one input and no outputs -/obj/machinery/logic/indicator - //Input is searched from the 'dir' direction - var/obj/structure/cable/input - -/obj/machinery/logic/indicator/process() - if(input) - return 1 - - - if(!input) - var/turf/T = get_step(src, dir) - if(T) - var/inv_dir = turn(dir, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - input = C - return 1 - - return 0 //If it gets to here, it means no suitable wire to link to was found. - -/obj/machinery/logic/indicator/bulb - icon = 'icons/obj/lighting.dmi' - icon_state = "bulb0" - -/obj/machinery/logic/indicator/bulb/process() - if(!..()) //Parent proc checks if input1 exists. - return - - var/datum/powernet/pn_input = input.powernet - if(!pn_input) - return - - if(pn_input.avail >= LOGIC_HIGH) - icon_state = "bulb1" - else - icon_state = "bulb0" - - - - -//Sensors only have one output and no inputs -/obj/machinery/logic/sensor - //Output is searched from the 'dir' direction - var/obj/structure/cable/output - -/obj/machinery/logic/sensor/process() - if(output) - return 1 - - if(!output) - var/turf/T = get_step(src, dir) - if(T) - var/inv_dir = turn(dir, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - output = C - return 1 - - return 0 //If it gets to here, it means no suitable wire to link to was found. - -//Constant high generator. This will continue to send a signal of LOGIC_HIGH as long as it exists. -/obj/machinery/logic/sensor/constant_high - icon = 'icons/obj/atmospherics/outlet_injector.dmi' - icon_state = "off" - -/obj/machinery/logic/sensor/constant_high/process() - if(!..()) //Parent proc checks if input1 exists. - return - - var/datum/powernet/pn_output = output.powernet - if(!pn_output) - return - - pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) - - - - -//ONE INPUT logic elements have one input and one output -/obj/machinery/logic/oneinput - var/dir_input = 2 - var/dir_output = 1 - var/obj/structure/cable/input - var/obj/structure/cable/output - icon = 'icons/obj/pipes/heat.dmi' - icon_state = "intact" - -/obj/machinery/logic/oneinput/process() - if(input && output) - return 1 - - if(!dir_input || !dir_output) - return 0 - - if(!input) - var/turf/T = get_step(src, dir_input) - if(T) - var/inv_dir = turn(dir_input, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - input = C - - if(!output) - var/turf/T = get_step(src, dir_output) - if(T) - var/inv_dir = turn(dir_output, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - output = C - - return 0 //On the process() call, where everything is still being searched for, it returns 0. It will return 1 on the next process() call. - -//NOT GATE -/obj/machinery/logic/oneinput/not/process() - if(!..()) //Parent proc checks if input1, input2 and output exist. - return - - var/datum/powernet/pn_input = input.powernet - - if(!pn_input) - return - - var/datum/powernet/pn_output = output.powernet - if(!pn_output) - return - - if( !(pn_input.avail >= LOGIC_HIGH)) - pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. - else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 - - - - - - - - - -//TWO INPUT logic elements have two inputs and one output -/obj/machinery/logic/twoinput - var/dir_input1 = 2 - var/dir_input2 = 8 - var/dir_output = 1 - var/obj/structure/cable/input1 - var/obj/structure/cable/input2 - var/obj/structure/cable/output - icon = 'icons/obj/atmospherics/mixer.dmi' - icon_state = "intact_off" - -/obj/machinery/logic/twoinput/process() - if(input1 && input2 && output) - return 1 - - if(!dir_input1 || !dir_input2 || !dir_output) - return 0 - - if(!input1) - var/turf/T = get_step(src, dir_input1) - if(T) - var/inv_dir = turn(dir_input1, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - input1 = C - - if(!input2) - var/turf/T = get_step(src, dir_input2) - if(T) - var/inv_dir = turn(dir_input2, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - input2 = C - - if(!output) - var/turf/T = get_step(src, dir_output) - if(T) - var/inv_dir = turn(dir_output, 180) - for(var/obj/structure/cable/C in T) - if(C.d1 == inv_dir || C.d2 == inv_dir) - output = C - - return 0 //On the process() call, where everything is still being searched for, it returns 0. It will return 1 on the next process() call. - -//AND GATE -/obj/machinery/logic/twoinput/and/process() - if(!..()) //Parent proc checks if input1, input2 and output exist. - return - - var/datum/powernet/pn_input1 = input1.powernet - var/datum/powernet/pn_input2 = input2.powernet - - if(!pn_input1 || !pn_input2) - return - - var/datum/powernet/pn_output = output.powernet - if(!pn_output) - return - - if( (pn_input1.avail >= LOGIC_HIGH) && (pn_input2.avail >= LOGIC_HIGH) ) - pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. - else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 - -//OR GATE -/obj/machinery/logic/twoinput/or/process() - if(!..()) //Parent proc checks if input1, input2 and output exist. - return - - var/datum/powernet/pn_input1 = input1.powernet - var/datum/powernet/pn_input2 = input2.powernet - - if(!pn_input1 || !pn_input2) - return - - var/datum/powernet/pn_output = output.powernet - if(!pn_output) - return - - if( (pn_input1.avail >= LOGIC_HIGH) || (pn_input2.avail >= LOGIC_HIGH) ) - pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. - else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 - -//XOR GATE -/obj/machinery/logic/twoinput/xor/process() - if(!..()) //Parent proc checks if input1, input2 and output exist. - return - - var/datum/powernet/pn_input1 = input1.powernet - var/datum/powernet/pn_input2 = input2.powernet - - if(!pn_input1 || !pn_input2) - return - - var/datum/powernet/pn_output = output.powernet - if(!pn_output) - return - - if( (pn_input1.avail >= LOGIC_HIGH) != (pn_input2.avail >= LOGIC_HIGH) ) - pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. - else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 - -//XNOR GATE (EQUIVALENCE) -/obj/machinery/logic/twoinput/xnor/process() - if(!..()) //Parent proc checks if input1, input2 and output exist. - return - - var/datum/powernet/pn_input1 = input1.powernet - var/datum/powernet/pn_input2 = input2.powernet - - if(!pn_input1 || !pn_input2) - return - - var/datum/powernet/pn_output = output.powernet - if(!pn_output) - return - - if( (pn_input1.avail >= LOGIC_HIGH) == (pn_input2.avail >= LOGIC_HIGH) ) - pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. - else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 - -#define RELAY_POWER_TRANSFER 2000 //How much power a relay transfers through. - -//RELAY - input1 governs the flow from input2 to output -/obj/machinery/logic/twoinput/relay/process() - if(!..()) //Parent proc checks if input1, input2 and output exist. - return - - var/datum/powernet/pn_input1 = input1.powernet - - if(!pn_input1) - return - - if( pn_input1.avail >= LOGIC_HIGH ) - var/datum/powernet/pn_input2 = input2.powernet - var/datum/powernet/pn_output = output.powernet - - if(!pn_output) - return - - if(pn_input2.avail >= RELAY_POWER_TRANSFER) - pn_input2.newload += RELAY_POWER_TRANSFER - pn_output.newavail += RELAY_POWER_TRANSFER - - -#undef RELAY_POWER_TRANSFER +#define LOGIC_HIGH 5 + +//Indicators only have one input and no outputs +/obj/machinery/logic/indicator + //Input is searched from the 'dir' direction + var/obj/structure/cable/input + +/obj/machinery/logic/indicator/process() + if(input) + return 1 + + + if(!input) + var/turf/T = get_step(src, dir) + if(T) + var/inv_dir = turn(dir, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + input = C + return 1 + + return 0 //If it gets to here, it means no suitable wire to link to was found. + +/obj/machinery/logic/indicator/bulb + icon = 'icons/obj/lighting.dmi' + icon_state = "bulb0" + +/obj/machinery/logic/indicator/bulb/process() + if(!..()) //Parent proc checks if input1 exists. + return + + var/datum/powernet/pn_input = input.powernet + if(!pn_input) + return + + if(pn_input.avail >= LOGIC_HIGH) + icon_state = "bulb1" + else + icon_state = "bulb0" + + + + +//Sensors only have one output and no inputs +/obj/machinery/logic/sensor + //Output is searched from the 'dir' direction + var/obj/structure/cable/output + +/obj/machinery/logic/sensor/process() + if(output) + return 1 + + if(!output) + var/turf/T = get_step(src, dir) + if(T) + var/inv_dir = turn(dir, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + output = C + return 1 + + return 0 //If it gets to here, it means no suitable wire to link to was found. + +//Constant high generator. This will continue to send a signal of LOGIC_HIGH as long as it exists. +/obj/machinery/logic/sensor/constant_high + icon = 'icons/obj/atmospherics/outlet_injector.dmi' + icon_state = "off" + +/obj/machinery/logic/sensor/constant_high/process() + if(!..()) //Parent proc checks if input1 exists. + return + + var/datum/powernet/pn_output = output.powernet + if(!pn_output) + return + + pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) + + + + +//ONE INPUT logic elements have one input and one output +/obj/machinery/logic/oneinput + var/dir_input = 2 + var/dir_output = 1 + var/obj/structure/cable/input + var/obj/structure/cable/output + icon = 'icons/obj/pipes/heat.dmi' + icon_state = "intact" + +/obj/machinery/logic/oneinput/process() + if(input && output) + return 1 + + if(!dir_input || !dir_output) + return 0 + + if(!input) + var/turf/T = get_step(src, dir_input) + if(T) + var/inv_dir = turn(dir_input, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + input = C + + if(!output) + var/turf/T = get_step(src, dir_output) + if(T) + var/inv_dir = turn(dir_output, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + output = C + + return 0 //On the process() call, where everything is still being searched for, it returns 0. It will return 1 on the next process() call. + +//NOT GATE +/obj/machinery/logic/oneinput/not/process() + if(!..()) //Parent proc checks if input1, input2 and output exist. + return + + var/datum/powernet/pn_input = input.powernet + + if(!pn_input) + return + + var/datum/powernet/pn_output = output.powernet + if(!pn_output) + return + + if( !(pn_input.avail >= LOGIC_HIGH)) + pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. + else + pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + + + + + + + + + +//TWO INPUT logic elements have two inputs and one output +/obj/machinery/logic/twoinput + var/dir_input1 = 2 + var/dir_input2 = 8 + var/dir_output = 1 + var/obj/structure/cable/input1 + var/obj/structure/cable/input2 + var/obj/structure/cable/output + icon = 'icons/obj/atmospherics/mixer.dmi' + icon_state = "intact_off" + +/obj/machinery/logic/twoinput/process() + if(input1 && input2 && output) + return 1 + + if(!dir_input1 || !dir_input2 || !dir_output) + return 0 + + if(!input1) + var/turf/T = get_step(src, dir_input1) + if(T) + var/inv_dir = turn(dir_input1, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + input1 = C + + if(!input2) + var/turf/T = get_step(src, dir_input2) + if(T) + var/inv_dir = turn(dir_input2, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + input2 = C + + if(!output) + var/turf/T = get_step(src, dir_output) + if(T) + var/inv_dir = turn(dir_output, 180) + for(var/obj/structure/cable/C in T) + if(C.d1 == inv_dir || C.d2 == inv_dir) + output = C + + return 0 //On the process() call, where everything is still being searched for, it returns 0. It will return 1 on the next process() call. + +//AND GATE +/obj/machinery/logic/twoinput/and/process() + if(!..()) //Parent proc checks if input1, input2 and output exist. + return + + var/datum/powernet/pn_input1 = input1.powernet + var/datum/powernet/pn_input2 = input2.powernet + + if(!pn_input1 || !pn_input2) + return + + var/datum/powernet/pn_output = output.powernet + if(!pn_output) + return + + if( (pn_input1.avail >= LOGIC_HIGH) && (pn_input2.avail >= LOGIC_HIGH) ) + pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. + else + pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + +//OR GATE +/obj/machinery/logic/twoinput/or/process() + if(!..()) //Parent proc checks if input1, input2 and output exist. + return + + var/datum/powernet/pn_input1 = input1.powernet + var/datum/powernet/pn_input2 = input2.powernet + + if(!pn_input1 || !pn_input2) + return + + var/datum/powernet/pn_output = output.powernet + if(!pn_output) + return + + if( (pn_input1.avail >= LOGIC_HIGH) || (pn_input2.avail >= LOGIC_HIGH) ) + pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. + else + pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + +//XOR GATE +/obj/machinery/logic/twoinput/xor/process() + if(!..()) //Parent proc checks if input1, input2 and output exist. + return + + var/datum/powernet/pn_input1 = input1.powernet + var/datum/powernet/pn_input2 = input2.powernet + + if(!pn_input1 || !pn_input2) + return + + var/datum/powernet/pn_output = output.powernet + if(!pn_output) + return + + if( (pn_input1.avail >= LOGIC_HIGH) != (pn_input2.avail >= LOGIC_HIGH) ) + pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. + else + pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + +//XNOR GATE (EQUIVALENCE) +/obj/machinery/logic/twoinput/xnor/process() + if(!..()) //Parent proc checks if input1, input2 and output exist. + return + + var/datum/powernet/pn_input1 = input1.powernet + var/datum/powernet/pn_input2 = input2.powernet + + if(!pn_input1 || !pn_input2) + return + + var/datum/powernet/pn_output = output.powernet + if(!pn_output) + return + + if( (pn_input1.avail >= LOGIC_HIGH) == (pn_input2.avail >= LOGIC_HIGH) ) + pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. + else + pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + +#define RELAY_POWER_TRANSFER 2000 //How much power a relay transfers through. + +//RELAY - input1 governs the flow from input2 to output +/obj/machinery/logic/twoinput/relay/process() + if(!..()) //Parent proc checks if input1, input2 and output exist. + return + + var/datum/powernet/pn_input1 = input1.powernet + + if(!pn_input1) + return + + if( pn_input1.avail >= LOGIC_HIGH ) + var/datum/powernet/pn_input2 = input2.powernet + var/datum/powernet/pn_output = output.powernet + + if(!pn_output) + return + + if(pn_input2.avail >= RELAY_POWER_TRANSFER) + pn_input2.newload += RELAY_POWER_TRANSFER + pn_output.newavail += RELAY_POWER_TRANSFER + + +#undef RELAY_POWER_TRANSFER #undef LOGIC_HIGH \ No newline at end of file diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 2102c26a6f7..e86a5afdfdb 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -1,156 +1,156 @@ -// the power cell -// charge from 0 to 100% -// fits in APC to provide backup power - -/obj/item/weapon/cell/New() - ..() - charge = maxcharge - if(maxcharge <= 2500) - desc = "The manufacturer's label states this cell has a power rating of [maxcharge], and that you should not swallow it." - else - desc = "This power cell has an exciting chrome finish, as it is an uber-capacity cell type! It has a power rating of [maxcharge]!" - spawn(5) - updateicon() - -/obj/item/weapon/cell/proc/updateicon() - overlays.len = 0 - - if(charge < 0.01) - return - else if(charge/maxcharge >=0.995) - overlays += image('icons/obj/power.dmi', "cell-o2") - else - overlays += image('icons/obj/power.dmi', "cell-o1") - -/obj/item/weapon/cell/proc/percent() // return % charge of cell - return 100.0*charge/maxcharge - -// use power from a cell -/obj/item/weapon/cell/proc/use(var/amount) - if(rigged && amount > 0) - explode() - return 0 - - if(charge < amount) - return 0 - charge = max(0,charge - amount) - return 1 - -// recharge the cell -/obj/item/weapon/cell/proc/give(var/amount) - if(rigged && amount > 0) - explode() - return 0 - - if(maxcharge < amount) return 0 - var/power_used = min(maxcharge-charge,amount) - if(crit_fail) return 0 - if(!prob(reliability)) - minor_fault++ - if(prob(minor_fault)) - crit_fail = 1 - return 0 - charge += power_used - return power_used - - -/obj/item/weapon/cell/examine(mob/user) - ..() - if(crit_fail) +// the power cell +// charge from 0 to 100% +// fits in APC to provide backup power + +/obj/item/weapon/cell/New() + ..() + charge = maxcharge + if(maxcharge <= 2500) + desc = "The manufacturer's label states this cell has a power rating of [maxcharge], and that you should not swallow it." + else + desc = "This power cell has an exciting chrome finish, as it is an uber-capacity cell type! It has a power rating of [maxcharge]!" + spawn(5) + updateicon() + +/obj/item/weapon/cell/proc/updateicon() + overlays.len = 0 + + if(charge < 0.01) + return + else if(charge/maxcharge >=0.995) + overlays += image('icons/obj/power.dmi', "cell-o2") + else + overlays += image('icons/obj/power.dmi', "cell-o1") + +/obj/item/weapon/cell/proc/percent() // return % charge of cell + return 100.0*charge/maxcharge + +// use power from a cell +/obj/item/weapon/cell/proc/use(var/amount) + if(rigged && amount > 0) + explode() + return 0 + + if(charge < amount) + return 0 + charge = max(0,charge - amount) + return 1 + +// recharge the cell +/obj/item/weapon/cell/proc/give(var/amount) + if(rigged && amount > 0) + explode() + return 0 + + if(maxcharge < amount) return 0 + var/power_used = min(maxcharge-charge,amount) + if(crit_fail) return 0 + if(!prob(reliability)) + minor_fault++ + if(prob(minor_fault)) + crit_fail = 1 + return 0 + charge += power_used + return power_used + + +/obj/item/weapon/cell/examine(mob/user) + ..() + if(crit_fail) to_chat(user, "This power cell seems to be faulty.") - else + else to_chat(user, "The charge meter reads [round(src.percent() )]%.") - -/obj/item/weapon/cell/attack_self(mob/user as mob) - src.add_fingerprint(user) - -/obj/item/weapon/cell/attackby(obj/item/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/reagent_containers/syringe)) - var/obj/item/weapon/reagent_containers/syringe/S = W - + +/obj/item/weapon/cell/attack_self(mob/user as mob) + src.add_fingerprint(user) + +/obj/item/weapon/cell/attackby(obj/item/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/reagent_containers/syringe)) + var/obj/item/weapon/reagent_containers/syringe/S = W + to_chat(user, "You inject the solution into the power cell.") - - if(S.reagents.has_reagent("plasma", 5)) - - rigged = 1 - - log_admin("LOG: [user.name] ([user.ckey]) injected a power cell with plasma, rigging it to explode.") - message_admins("LOG: [user.name] ([user.ckey]) injected a power cell with plasma, rigging it to explode.") - - S.reagents.clear_reagents() - - -/obj/item/weapon/cell/proc/explode() - var/turf/T = get_turf(src.loc) -/* - * 1000-cell explosion(T, -1, 0, 1, 1) - * 2500-cell explosion(T, -1, 0, 1, 1) - * 10000-cell explosion(T, -1, 1, 3, 3) - * 15000-cell explosion(T, -1, 2, 4, 4) - * */ - if (charge==0) - return - var/devastation_range = -1 //round(charge/11000) - var/heavy_impact_range = round(sqrt(charge)/60) - var/light_impact_range = round(sqrt(charge)/30) - var/flash_range = light_impact_range - if (light_impact_range==0) - rigged = 0 - corrupt() - return - //explosion(T, 0, 1, 2, 2) - - log_admin("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") - message_admins("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") - - explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range) - - spawn(1) - qdel(src) - -/obj/item/weapon/cell/proc/corrupt() - charge /= 2 - maxcharge /= 2 - if (prob(10)) - rigged = 1 //broken batterys are dangerous - -/obj/item/weapon/cell/emp_act(severity) - charge -= 1000 / severity - if (charge < 0) - charge = 0 - if(reliability != 100 && prob(50/severity)) - reliability -= 10 / severity - ..() - -/obj/item/weapon/cell/ex_act(severity) - - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if (prob(50)) - corrupt() - if(3.0) - if (prob(25)) - qdel(src) - return - if (prob(25)) - corrupt() - return - -/obj/item/weapon/cell/blob_act() - if(prob(75)) - explode() - -/obj/item/weapon/cell/proc/get_electrocute_damage() - return round(charge**(1/3)*(rand(100,125)/100)) //Cube root of power times 1,5 to 2 in increments of 10^-1 - //For instance, gives an average of 81 damage for 100k W and 175 for 1M W - //Best you're getting with BYOND's mathematical funcs. Not even a fucking exponential or neperian logarithm - -/obj/item/weapon/cell/get_rating() - return maxcharge / 10000 + + if(S.reagents.has_reagent("plasma", 5)) + + rigged = 1 + + log_admin("LOG: [user.name] ([user.ckey]) injected a power cell with plasma, rigging it to explode.") + message_admins("LOG: [user.name] ([user.ckey]) injected a power cell with plasma, rigging it to explode.") + + S.reagents.clear_reagents() + + +/obj/item/weapon/cell/proc/explode() + var/turf/T = get_turf(src.loc) +/* + * 1000-cell explosion(T, -1, 0, 1, 1) + * 2500-cell explosion(T, -1, 0, 1, 1) + * 10000-cell explosion(T, -1, 1, 3, 3) + * 15000-cell explosion(T, -1, 2, 4, 4) + * */ + if (charge==0) + return + var/devastation_range = -1 //round(charge/11000) + var/heavy_impact_range = round(sqrt(charge)/60) + var/light_impact_range = round(sqrt(charge)/30) + var/flash_range = light_impact_range + if (light_impact_range==0) + rigged = 0 + corrupt() + return + //explosion(T, 0, 1, 2, 2) + + log_admin("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") + message_admins("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") + + explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range) + + spawn(1) + qdel(src) + +/obj/item/weapon/cell/proc/corrupt() + charge /= 2 + maxcharge /= 2 + if (prob(10)) + rigged = 1 //broken batterys are dangerous + +/obj/item/weapon/cell/emp_act(severity) + charge -= 1000 / severity + if (charge < 0) + charge = 0 + if(reliability != 100 && prob(50/severity)) + reliability -= 10 / severity + ..() + +/obj/item/weapon/cell/ex_act(severity) + + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if (prob(50)) + corrupt() + if(3.0) + if (prob(25)) + qdel(src) + return + if (prob(25)) + corrupt() + return + +/obj/item/weapon/cell/blob_act() + if(prob(75)) + explode() + +/obj/item/weapon/cell/proc/get_electrocute_damage() + return round(charge**(1/3)*(rand(100,125)/100)) //Cube root of power times 1,5 to 2 in increments of 10^-1 + //For instance, gives an average of 81 damage for 100k W and 175 for 1M W + //Best you're getting with BYOND's mathematical funcs. Not even a fucking exponential or neperian logarithm + +/obj/item/weapon/cell/get_rating() + return maxcharge / 10000 diff --git a/code/modules/power/engine.dm b/code/modules/power/engine.dm index f25e15e8cdf..90a827cf1d6 100644 --- a/code/modules/power/engine.dm +++ b/code/modules/power/engine.dm @@ -1,12 +1,12 @@ -/turf/simulated/floor/engine/attack_paw(var/mob/user as mob) - return src.attack_hand(user) - -/turf/simulated/floor/engine/attack_hand(var/mob/user as mob) - user.Move_Pulled(src) - return - -/turf/simulated/floor/engine/blob_act() - if(prob(25)) - ChangeTurf(get_base_turf(src.z)) - return - return +/turf/simulated/floor/engine/attack_paw(var/mob/user as mob) + return src.attack_hand(user) + +/turf/simulated/floor/engine/attack_hand(var/mob/user as mob) + user.Move_Pulled(src) + return + +/turf/simulated/floor/engine/blob_act() + if(prob(25)) + ChangeTurf(get_base_turf(src.z)) + return + return diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index b65fbdcbe5d..01fcf1b8168 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -1,433 +1,433 @@ -/obj/machinery/power/generator - name = "thermoelectric generator" - desc = "It's a high efficiency thermoelectric generator." - icon_state = "teg" - density = 1 - anchored = 0 - - use_power = 0 - idle_power_usage = 100 //Watts, I hope. Just enough to do the computer and display things. - - var/thermal_efficiency = 0.65 - - var/obj/machinery/atmospherics/binary/circulator/circ1 - var/obj/machinery/atmospherics/binary/circulator/circ2 - - var/last_circ1_gen = 0 - var/last_circ2_gen = 0 - var/last_thermal_gen = 0 - var/stored_energy = 0 - var/lastgen1 = 0 - var/lastgen2 = 0 - var/effective_gen = 0 - var/lastgenlev = 0 - var/max_power = 500000 //Amount of W produced at which point the meter caps. - - machine_flags = WRENCHMOVE | FIXED2WORK - - var/datum/html_interface/nanotrasen/interface - -/obj/machinery/power/generator/New() - ..() - - spawn(1) - reconnect() - - var/const/head = {" - - - "} - - interface = new(src, name, 450, 410, head) - - html_machines += src - - init_ui() - -/obj/machinery/power/generator/Destroy() - . = ..() - if(circ1) - circ1.linked_generator = null - circ1 = null - - if(circ2) - circ2.linked_generator = null - circ2 = null - - qdel(interface) - interface = null - - html_machines -= src - -/obj/machinery/power/generator/proc/init_ui() - interface.updateLayout({" -
    -
    - Total output: -
    -
    - X -
    -
    -
    -
    - Thermal output: -
    -
    - X -
    -
    -
    - - - - - -
    -
    -

    - Primary Circulator (right) -

    -
    -
    - Turbine Output: -
    -
    - X -
    -
    -
    -
    - Flow Capacity: -
    -
    - X -
    -
    -
    -
    -
    -
    - Inlet Pressure: -
    -
    - X -
    -
    -
    -
    - Inlet Temperature: -
    -
    - X -
    -
    -
    -
    -
    -
    - Outlet Pressure: -
    -
    - X -
    -
    -
    -
    - Outlet Temperature: -
    -
    - X -
    -


    -
    -
    -
    -

    - Secondary Circulator (left) -

    -
    -
    - Turbine Output: -
    -
    - X -
    -
    -
    -
    - Flow Capacity: -
    -
    - X -
    -
    -
    -
    -
    -
    - Inlet Pressure: -
    -
    - X -
    -
    -
    -
    - Inlet Temperature: -
    -
    - X -
    -
    -
    -
    -
    -
    - Outlet Pressure: -
    -
    - X -
    -
    -
    -
    - Outlet Temperature: -
    -
    - X -
    -


    -
    -
    -
    - - "}) - -/obj/item/weapon/paper/generator - name = "paper - 'generator instructions'" - info = "

    How to setup the Thermo-Generator

    1. To the top right is a room full of canisters; to the bottom there is a room full of pipes. Connect C02 canisters to the pipe room's top connector ports, the canisters will help act as a buffer so only remove them when refilling the gas..
    2. Connect 3 plasma and 2 oxygen canisters to the bottom ports of the pipe room.
    3. Turn on all the pumps and valves in the room except for the one connected to the yellow pipe and red pipe, no adjustments to the pump strength needed.
    4. Look into the camera monitor to see the burn chamber. When it is full of plasma, press the igniter button.
    5. Setup the SMES cells in the North West of Engineering and set an input of half the max; and an output that is half the input.
    Well done, you should have a functioning generator generating power. If the generator stops working, and there is enough gas and it's hot and cold, it might mean there is too much pressure and you need to turn on the pump that is connected to the red and yellow pipes to release the pressure. Make sure you don't take out too much pressure though.
    You optimize the generator you must work out how much power your station is using and lowering the circulation pumps enough so that the generator doesn't create excess power, and it will allow the generator to powering the station for a longer duration, without having to replace the canisters. " - -//generators connect in dir and reverse_dir(dir) directions -//mnemonic to determine circulator/generator directions: the cirulators orbit clockwise around the generator -//so a circulator to the NORTH of the generator connects first to the EAST, then to the WEST -//and a circulator to the WEST of the generator connects first to the NORTH, then to the SOUTH -//note that the circulator's outlet dir is it's always facing dir, and it's inlet is always the reverse -/obj/machinery/power/generator/proc/reconnect() - if(circ1) - circ1.linked_generator = null - circ1 = null - - if(circ2) - circ2.linked_generator = null - circ2 = null - - if(!src.loc || !anchored) - return - - if(src.dir & (EAST|WEST)) - circ1 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,EAST) - if(circ1 && !circ1.anchored) - circ1 = null - - circ2 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,WEST) - if(circ2 && !circ2.anchored) - circ2 = null - - if(circ1 && circ2) - if(circ1.dir != SOUTH || circ2.dir != NORTH) - circ1 = null - circ2 = null - - else if(src.dir & (NORTH|SOUTH)) - circ1 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,NORTH) - circ2 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,SOUTH) - - if(circ1 && circ2 && (circ1.dir != EAST || circ2.dir != WEST)) - circ1 = null - circ2 = null - - if(circ1) - circ1.linked_generator = src - - if(circ2) - circ2.linked_generator = src - - update_icon() - updateUsrDialog() - -/obj/machinery/power/generator/wrenchAnchor() - . = ..() - reconnect() - -/obj/machinery/power/generator/proc/operable() - return circ1 && circ2 && anchored && !(stat & (BROKEN|NOPOWER)) - -/obj/machinery/power/generator/update_icon() - overlays = 0 - - if(!operable()) - return - - overlays += "teg_mid" - - if(lastgenlev != 0) - overlays += "teg-op[lastgenlev]" - -/obj/machinery/power/generator/process() - if(!operable()) - stored_energy = 0 - return - - lastgen2 = lastgen1 - lastgen1 = 0 - last_thermal_gen = 0 - last_circ1_gen = 0 - last_circ2_gen = 0 - - var/datum/gas_mixture/air1 = circ1.return_transfer_air() - var/datum/gas_mixture/air2 = circ2.return_transfer_air() - - if(air1 && air2) - var/air1_heat_capacity = air1.heat_capacity() - var/air2_heat_capacity = air2.heat_capacity() - var/delta_temperature = abs(air2.temperature - air1.temperature) - - if(delta_temperature > 0 && air1_heat_capacity > 0 && air2_heat_capacity > 0) - var/energy_transfer = delta_temperature * air2_heat_capacity * air1_heat_capacity / (air2_heat_capacity + air1_heat_capacity) - var/heat = energy_transfer * (1 - thermal_efficiency) - last_thermal_gen = energy_transfer * thermal_efficiency - - if(air2.temperature > air1.temperature) - air2.temperature = air2.temperature - energy_transfer/air2_heat_capacity - air1.temperature = air1.temperature + heat/air1_heat_capacity - else - air2.temperature = air2.temperature + heat/air2_heat_capacity - air1.temperature = air1.temperature - energy_transfer/air1_heat_capacity - - //Transfer the air. - circ1.air2.merge(air1) - circ2.air2.merge(air2) - - //Update the gas networks. - if(circ1.network2) - circ1.network2.update = 1 - - if(circ2.network2) - circ2.network2.update = 1 - - //Power - last_circ1_gen = circ1.return_stored_energy() - last_circ2_gen = circ2.return_stored_energy() - stored_energy += last_thermal_gen + last_circ1_gen + last_circ2_gen - lastgen1 = stored_energy * 0.4 //Smoothened power generation to prevent slingshotting as pressure is equalized, then restored by pumps. - stored_energy -= lastgen1 - effective_gen = (lastgen1 + lastgen2) / 2 - - //Update icon overlays and power usage only if displayed level has changed. - var/genlev = Clamp(round(11 * effective_gen / max_power), 0, 11) - - if(effective_gen > 100 && genlev == 0) - genlev = 1 - - if(genlev != lastgenlev) - lastgenlev = genlev - update_icon() - - add_avail(effective_gen) - - updateUsrDialog() - -/obj/machinery/power/generator/attack_ai(mob/user) - return attack_hand(user) - -/obj/machinery/power/generator/attack_hand(mob/user) - . = ..() - if(.) - return - - interface.show(user) - updateUsrDialog() - -/obj/machinery/power/generator/updateUsrDialog() - if(operable()) - interface.executeJavaScript("setEnabled()") - else - interface.executeJavaScript("setDisabled()") - - var/vertical = 0 - if(dir & (NORTH | SOUTH)) - vertical = 1 - - interface.updateContent("circ1", "Primary circulator ([vertical ? "top" : "right"])") - interface.updateContent("circ2", "Primary circulator ([vertical ? "bottom" : "left"])") - - interface.updateContent("total_out", format_watts(effective_gen)) - interface.updateContent("thermal_out", format_watts(last_thermal_gen)) - - if(!circ1 || !circ2) //From this point on it's circulator data. - return - - //CIRCULATOR 1 - interface.updateContent("circ1_turbine", format_watts(last_circ1_gen)) - interface.updateContent("circ1_flow_cap", "[round(circ1.volume_capacity_used * 100)] %") - - interface.updateContent("circ1_in_pressure", "[round(circ1.air1.return_pressure(), 0.1)] kPa") - interface.updateContent("circ1_in_temp", "[round(circ1.air1.temperature, 0.1)] K") - - interface.updateContent("circ1_out_pressure", "[round(circ1.air2.return_pressure(), 0.1)] kPa") - interface.updateContent("circ1_out_temp", "[round(circ1.air2.temperature, 0.1)] K") - - //CIRCULATOR 2 - interface.updateContent("circ2_turbine", format_watts(last_circ2_gen)) - interface.updateContent("circ2_flow_cap", "[round(circ2.volume_capacity_used * 100)] %") - - interface.updateContent("circ2_in_pressure", "[round(circ2.air1.return_pressure(), 0.1)] kPa") - interface.updateContent("circ2_in_temp", "[round(circ2.air1.temperature, 0.1)] K") - - interface.updateContent("circ2_out_pressure", "[round(circ2.air2.return_pressure(), 0.1)] kPa") - interface.updateContent("circ2_out_temp", "[round(circ2.air2.temperature, 0.1)] K") - -//Needs to be overriden because else it will use the shitty set_machine(). -/obj/machinery/power/generator/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi) - return hclient.client.mob.html_mob_check(src.type) - -/obj/machinery/power/generator/power_change() - ..() - update_icon() - -/obj/machinery/power/generator/verb/rotate_clock() - set category = "Object" - set name = "Rotate Generator (Clockwise)" - set src in view(1) - - if (usr.isUnconscious() || usr.restrained() || anchored) - return - - src.dir = turn(src.dir, 90) - -/obj/machinery/power/generator/verb/rotate_anticlock() - set category = "Object" - set name = "Rotate Generator (Counterclockwise)" - set src in view(1) - - if (usr.isUnconscious() || usr.restrained() || anchored) - return - +/obj/machinery/power/generator + name = "thermoelectric generator" + desc = "It's a high efficiency thermoelectric generator." + icon_state = "teg" + density = 1 + anchored = 0 + + use_power = 0 + idle_power_usage = 100 //Watts, I hope. Just enough to do the computer and display things. + + var/thermal_efficiency = 0.65 + + var/obj/machinery/atmospherics/binary/circulator/circ1 + var/obj/machinery/atmospherics/binary/circulator/circ2 + + var/last_circ1_gen = 0 + var/last_circ2_gen = 0 + var/last_thermal_gen = 0 + var/stored_energy = 0 + var/lastgen1 = 0 + var/lastgen2 = 0 + var/effective_gen = 0 + var/lastgenlev = 0 + var/max_power = 500000 //Amount of W produced at which point the meter caps. + + machine_flags = WRENCHMOVE | FIXED2WORK + + var/datum/html_interface/nanotrasen/interface + +/obj/machinery/power/generator/New() + ..() + + spawn(1) + reconnect() + + var/const/head = {" + + + "} + + interface = new(src, name, 450, 410, head) + + html_machines += src + + init_ui() + +/obj/machinery/power/generator/Destroy() + . = ..() + if(circ1) + circ1.linked_generator = null + circ1 = null + + if(circ2) + circ2.linked_generator = null + circ2 = null + + qdel(interface) + interface = null + + html_machines -= src + +/obj/machinery/power/generator/proc/init_ui() + interface.updateLayout({" +
    +
    + Total output: +
    +
    + X +
    +
    +
    +
    + Thermal output: +
    +
    + X +
    +
    +
    + + + + + +
    +
    +

    + Primary Circulator (right) +

    +
    +
    + Turbine Output: +
    +
    + X +
    +
    +
    +
    + Flow Capacity: +
    +
    + X +
    +
    +
    +
    +
    +
    + Inlet Pressure: +
    +
    + X +
    +
    +
    +
    + Inlet Temperature: +
    +
    + X +
    +
    +
    +
    +
    +
    + Outlet Pressure: +
    +
    + X +
    +
    +
    +
    + Outlet Temperature: +
    +
    + X +
    +


    +
    +
    +
    +

    + Secondary Circulator (left) +

    +
    +
    + Turbine Output: +
    +
    + X +
    +
    +
    +
    + Flow Capacity: +
    +
    + X +
    +
    +
    +
    +
    +
    + Inlet Pressure: +
    +
    + X +
    +
    +
    +
    + Inlet Temperature: +
    +
    + X +
    +
    +
    +
    +
    +
    + Outlet Pressure: +
    +
    + X +
    +
    +
    +
    + Outlet Temperature: +
    +
    + X +
    +


    +
    +
    +
    + + "}) + +/obj/item/weapon/paper/generator + name = "paper - 'generator instructions'" + info = "

    How to setup the Thermo-Generator

    1. To the top right is a room full of canisters; to the bottom there is a room full of pipes. Connect C02 canisters to the pipe room's top connector ports, the canisters will help act as a buffer so only remove them when refilling the gas..
    2. Connect 3 plasma and 2 oxygen canisters to the bottom ports of the pipe room.
    3. Turn on all the pumps and valves in the room except for the one connected to the yellow pipe and red pipe, no adjustments to the pump strength needed.
    4. Look into the camera monitor to see the burn chamber. When it is full of plasma, press the igniter button.
    5. Setup the SMES cells in the North West of Engineering and set an input of half the max; and an output that is half the input.
    Well done, you should have a functioning generator generating power. If the generator stops working, and there is enough gas and it's hot and cold, it might mean there is too much pressure and you need to turn on the pump that is connected to the red and yellow pipes to release the pressure. Make sure you don't take out too much pressure though.
    You optimize the generator you must work out how much power your station is using and lowering the circulation pumps enough so that the generator doesn't create excess power, and it will allow the generator to powering the station for a longer duration, without having to replace the canisters. " + +//generators connect in dir and reverse_dir(dir) directions +//mnemonic to determine circulator/generator directions: the cirulators orbit clockwise around the generator +//so a circulator to the NORTH of the generator connects first to the EAST, then to the WEST +//and a circulator to the WEST of the generator connects first to the NORTH, then to the SOUTH +//note that the circulator's outlet dir is it's always facing dir, and it's inlet is always the reverse +/obj/machinery/power/generator/proc/reconnect() + if(circ1) + circ1.linked_generator = null + circ1 = null + + if(circ2) + circ2.linked_generator = null + circ2 = null + + if(!src.loc || !anchored) + return + + if(src.dir & (EAST|WEST)) + circ1 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,EAST) + if(circ1 && !circ1.anchored) + circ1 = null + + circ2 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,WEST) + if(circ2 && !circ2.anchored) + circ2 = null + + if(circ1 && circ2) + if(circ1.dir != SOUTH || circ2.dir != NORTH) + circ1 = null + circ2 = null + + else if(src.dir & (NORTH|SOUTH)) + circ1 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,NORTH) + circ2 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,SOUTH) + + if(circ1 && circ2 && (circ1.dir != EAST || circ2.dir != WEST)) + circ1 = null + circ2 = null + + if(circ1) + circ1.linked_generator = src + + if(circ2) + circ2.linked_generator = src + + update_icon() + updateUsrDialog() + +/obj/machinery/power/generator/wrenchAnchor() + . = ..() + reconnect() + +/obj/machinery/power/generator/proc/operable() + return circ1 && circ2 && anchored && !(stat & (BROKEN|NOPOWER)) + +/obj/machinery/power/generator/update_icon() + overlays = 0 + + if(!operable()) + return + + overlays += "teg_mid" + + if(lastgenlev != 0) + overlays += "teg-op[lastgenlev]" + +/obj/machinery/power/generator/process() + if(!operable()) + stored_energy = 0 + return + + lastgen2 = lastgen1 + lastgen1 = 0 + last_thermal_gen = 0 + last_circ1_gen = 0 + last_circ2_gen = 0 + + var/datum/gas_mixture/air1 = circ1.return_transfer_air() + var/datum/gas_mixture/air2 = circ2.return_transfer_air() + + if(air1 && air2) + var/air1_heat_capacity = air1.heat_capacity() + var/air2_heat_capacity = air2.heat_capacity() + var/delta_temperature = abs(air2.temperature - air1.temperature) + + if(delta_temperature > 0 && air1_heat_capacity > 0 && air2_heat_capacity > 0) + var/energy_transfer = delta_temperature * air2_heat_capacity * air1_heat_capacity / (air2_heat_capacity + air1_heat_capacity) + var/heat = energy_transfer * (1 - thermal_efficiency) + last_thermal_gen = energy_transfer * thermal_efficiency + + if(air2.temperature > air1.temperature) + air2.temperature = air2.temperature - energy_transfer/air2_heat_capacity + air1.temperature = air1.temperature + heat/air1_heat_capacity + else + air2.temperature = air2.temperature + heat/air2_heat_capacity + air1.temperature = air1.temperature - energy_transfer/air1_heat_capacity + + //Transfer the air. + circ1.air2.merge(air1) + circ2.air2.merge(air2) + + //Update the gas networks. + if(circ1.network2) + circ1.network2.update = 1 + + if(circ2.network2) + circ2.network2.update = 1 + + //Power + last_circ1_gen = circ1.return_stored_energy() + last_circ2_gen = circ2.return_stored_energy() + stored_energy += last_thermal_gen + last_circ1_gen + last_circ2_gen + lastgen1 = stored_energy * 0.4 //Smoothened power generation to prevent slingshotting as pressure is equalized, then restored by pumps. + stored_energy -= lastgen1 + effective_gen = (lastgen1 + lastgen2) / 2 + + //Update icon overlays and power usage only if displayed level has changed. + var/genlev = Clamp(round(11 * effective_gen / max_power), 0, 11) + + if(effective_gen > 100 && genlev == 0) + genlev = 1 + + if(genlev != lastgenlev) + lastgenlev = genlev + update_icon() + + add_avail(effective_gen) + + updateUsrDialog() + +/obj/machinery/power/generator/attack_ai(mob/user) + return attack_hand(user) + +/obj/machinery/power/generator/attack_hand(mob/user) + . = ..() + if(.) + return + + interface.show(user) + updateUsrDialog() + +/obj/machinery/power/generator/updateUsrDialog() + if(operable()) + interface.executeJavaScript("setEnabled()") + else + interface.executeJavaScript("setDisabled()") + + var/vertical = 0 + if(dir & (NORTH | SOUTH)) + vertical = 1 + + interface.updateContent("circ1", "Primary circulator ([vertical ? "top" : "right"])") + interface.updateContent("circ2", "Primary circulator ([vertical ? "bottom" : "left"])") + + interface.updateContent("total_out", format_watts(effective_gen)) + interface.updateContent("thermal_out", format_watts(last_thermal_gen)) + + if(!circ1 || !circ2) //From this point on it's circulator data. + return + + //CIRCULATOR 1 + interface.updateContent("circ1_turbine", format_watts(last_circ1_gen)) + interface.updateContent("circ1_flow_cap", "[round(circ1.volume_capacity_used * 100)] %") + + interface.updateContent("circ1_in_pressure", "[round(circ1.air1.return_pressure(), 0.1)] kPa") + interface.updateContent("circ1_in_temp", "[round(circ1.air1.temperature, 0.1)] K") + + interface.updateContent("circ1_out_pressure", "[round(circ1.air2.return_pressure(), 0.1)] kPa") + interface.updateContent("circ1_out_temp", "[round(circ1.air2.temperature, 0.1)] K") + + //CIRCULATOR 2 + interface.updateContent("circ2_turbine", format_watts(last_circ2_gen)) + interface.updateContent("circ2_flow_cap", "[round(circ2.volume_capacity_used * 100)] %") + + interface.updateContent("circ2_in_pressure", "[round(circ2.air1.return_pressure(), 0.1)] kPa") + interface.updateContent("circ2_in_temp", "[round(circ2.air1.temperature, 0.1)] K") + + interface.updateContent("circ2_out_pressure", "[round(circ2.air2.return_pressure(), 0.1)] kPa") + interface.updateContent("circ2_out_temp", "[round(circ2.air2.temperature, 0.1)] K") + +//Needs to be overriden because else it will use the shitty set_machine(). +/obj/machinery/power/generator/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi) + return hclient.client.mob.html_mob_check(src.type) + +/obj/machinery/power/generator/power_change() + ..() + update_icon() + +/obj/machinery/power/generator/verb/rotate_clock() + set category = "Object" + set name = "Rotate Generator (Clockwise)" + set src in view(1) + + if (usr.isUnconscious() || usr.restrained() || anchored) + return + + src.dir = turn(src.dir, 90) + +/obj/machinery/power/generator/verb/rotate_anticlock() + set category = "Object" + set name = "Rotate Generator (Counterclockwise)" + set src in view(1) + + if (usr.isUnconscious() || usr.restrained() || anchored) + return + src.dir = turn(src.dir, -90) \ No newline at end of file diff --git a/code/modules/power/generator_type2.dm b/code/modules/power/generator_type2.dm index dd9d4befa84..c1be4e10f77 100644 --- a/code/modules/power/generator_type2.dm +++ b/code/modules/power/generator_type2.dm @@ -1,120 +1,120 @@ -/obj/machinery/power/generator/type2 - name = "thermoelectric generator" - desc = "It's a high efficiency thermoelectric generator." - icon_state = "teg" - anchored = 1 - density = 1 - use_power = 0 - - var/obj/machinery/atmospherics/unary/generator_input/input1 - var/obj/machinery/atmospherics/unary/generator_input/input2 - - var/input1_dir=NORTH - var/input2_dir=SOUTH - - -/obj/machinery/power/generator/type2/reconnect() - input1_dir = turn(dir, 90) - input2_dir = turn(dir, -90) - input1 = locate(/obj/machinery/atmospherics/unary/generator_input) in get_step(src,input1_dir) - input2 = locate(/obj/machinery/atmospherics/unary/generator_input) in get_step(src,input2_dir) - updateicon() - -/obj/machinery/power/generator/type2/operable() - return !(stat & (NOPOWER|BROKEN) || !anchored || !input1 || !input2) - -#define GENRATE 800 // generator output coefficient from Q - -/obj/machinery/power/generator/type2/process() - if(!input1 || !input2 || !anchored || stat & (NOPOWER|BROKEN)) - return - - var/datum/gas_mixture/air1 = input1.return_exchange_air() - var/datum/gas_mixture/air2 = input2.return_exchange_air() - - lastgen = 0 - - if(air1 && air2) - var/datum/gas_mixture/hot_air = air1 - var/datum/gas_mixture/cold_air = air2 - if(hot_air.temperature < cold_air.temperature) - hot_air = air2 - cold_air = air1 - - var/hot_air_heat_capacity = hot_air.heat_capacity() - var/cold_air_heat_capacity = cold_air.heat_capacity() - - var/delta_temperature = hot_air.temperature - cold_air.temperature - - if(delta_temperature > 1 && cold_air_heat_capacity > 0.01 && hot_air_heat_capacity > 0.01) - var/efficiency = (1 - cold_air.temperature/hot_air.temperature)*0.65 //65% of Carnot efficiency - - var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity) - - var/heat = energy_transfer*(1-efficiency) - lastgen = energy_transfer*efficiency - - hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity - cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity - +/obj/machinery/power/generator/type2 + name = "thermoelectric generator" + desc = "It's a high efficiency thermoelectric generator." + icon_state = "teg" + anchored = 1 + density = 1 + use_power = 0 + + var/obj/machinery/atmospherics/unary/generator_input/input1 + var/obj/machinery/atmospherics/unary/generator_input/input2 + + var/input1_dir=NORTH + var/input2_dir=SOUTH + + +/obj/machinery/power/generator/type2/reconnect() + input1_dir = turn(dir, 90) + input2_dir = turn(dir, -90) + input1 = locate(/obj/machinery/atmospherics/unary/generator_input) in get_step(src,input1_dir) + input2 = locate(/obj/machinery/atmospherics/unary/generator_input) in get_step(src,input2_dir) + updateicon() + +/obj/machinery/power/generator/type2/operable() + return !(stat & (NOPOWER|BROKEN) || !anchored || !input1 || !input2) + +#define GENRATE 800 // generator output coefficient from Q + +/obj/machinery/power/generator/type2/process() + if(!input1 || !input2 || !anchored || stat & (NOPOWER|BROKEN)) + return + + var/datum/gas_mixture/air1 = input1.return_exchange_air() + var/datum/gas_mixture/air2 = input2.return_exchange_air() + + lastgen = 0 + + if(air1 && air2) + var/datum/gas_mixture/hot_air = air1 + var/datum/gas_mixture/cold_air = air2 + if(hot_air.temperature < cold_air.temperature) + hot_air = air2 + cold_air = air1 + + var/hot_air_heat_capacity = hot_air.heat_capacity() + var/cold_air_heat_capacity = cold_air.heat_capacity() + + var/delta_temperature = hot_air.temperature - cold_air.temperature + + if(delta_temperature > 1 && cold_air_heat_capacity > 0.01 && hot_air_heat_capacity > 0.01) + var/efficiency = (1 - cold_air.temperature/hot_air.temperature)*0.65 //65% of Carnot efficiency + + var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity) + + var/heat = energy_transfer*(1-efficiency) + lastgen = energy_transfer*efficiency + + hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity + cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity + // to_chat(world, "POWER: [lastgen] W generated at [efficiency*100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]") - - if(input1.network) - input1.network.update = 1 - - if(input2.network) - input2.network.update = 1 - - add_avail(lastgen) - // update icon overlays only if displayed level has changed - - var/genlev = max(0, min( round(11*lastgen / 100000), 11)) - if(genlev != lastgenlev) - lastgenlev = genlev - updateicon() - - src.updateDialog() - - -/obj/machinery/power/generator/type2/attack_ai(mob/user) - src.add_hiddenprint(user) - if(stat & (BROKEN|NOPOWER)) return - interact(user) - -/obj/machinery/power/generator/type2/attack_hand(mob/user) - add_fingerprint(user) - if(stat & (BROKEN|NOPOWER)) return - interact(user) - -/obj/machinery/power/generator/type2/proc/get_loop_state(var/loop_name,var/loop_dir,var/obj/machinery/atmospherics/unary/generator_input/loop) - if(!loop) - return "[loop_name] Loop ([dir2text(loop_dir)], UNCONNECTED)
    " - else - return {"Cold Loop ([dir2text(loop_dir)]) -
      -
    • Temperature: [round(loop.air_contents.temperature, 0.1)] K
    • -
    • Pressure: [round(loop.air_contents.return_pressure(), 0.1)] kPa
    • -
    "} - -/obj/machinery/power/generator/type2/interact(mob/user) - if ( (get_dist(src, user) > 1 ) && (!istype(user, /mob/living/silicon/ai))) - user.unset_machine() - user << browse(null, "window=teg") - return - - user.set_machine(src) - - var/t = "

    Thermo-Electric Generator Mk. 2

    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\\power\generator_type2.dm:113: t += "Output : [round(lastgen)] W

    " - t += {"Output : [round(lastgen)] W

    -[get_loop_state("Cold",input1_dir,input1)] -[get_loop_state("Hot",input2_dir,input2)] -

    Close -| Refresh Inputs"} - // END AUTOFIX - user << browse(t, "window=teg;size=460x300") - onclose(user, "teg") + + if(input1.network) + input1.network.update = 1 + + if(input2.network) + input2.network.update = 1 + + add_avail(lastgen) + // update icon overlays only if displayed level has changed + + var/genlev = max(0, min( round(11*lastgen / 100000), 11)) + if(genlev != lastgenlev) + lastgenlev = genlev + updateicon() + + src.updateDialog() + + +/obj/machinery/power/generator/type2/attack_ai(mob/user) + src.add_hiddenprint(user) + if(stat & (BROKEN|NOPOWER)) return + interact(user) + +/obj/machinery/power/generator/type2/attack_hand(mob/user) + add_fingerprint(user) + if(stat & (BROKEN|NOPOWER)) return + interact(user) + +/obj/machinery/power/generator/type2/proc/get_loop_state(var/loop_name,var/loop_dir,var/obj/machinery/atmospherics/unary/generator_input/loop) + if(!loop) + return "[loop_name] Loop ([dir2text(loop_dir)], UNCONNECTED)
    " + else + return {"Cold Loop ([dir2text(loop_dir)]) +
      +
    • Temperature: [round(loop.air_contents.temperature, 0.1)] K
    • +
    • Pressure: [round(loop.air_contents.return_pressure(), 0.1)] kPa
    • +
    "} + +/obj/machinery/power/generator/type2/interact(mob/user) + if ( (get_dist(src, user) > 1 ) && (!istype(user, /mob/living/silicon/ai))) + user.unset_machine() + user << browse(null, "window=teg") + return + + user.set_machine(src) + + var/t = "

    Thermo-Electric Generator Mk. 2

    " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\\power\generator_type2.dm:113: t += "Output : [round(lastgen)] W

    " + t += {"Output : [round(lastgen)] W

    +[get_loop_state("Cold",input1_dir,input1)] +[get_loop_state("Hot",input2_dir,input2)] +

    Close +| Refresh Inputs"} + // END AUTOFIX + user << browse(t, "window=teg;size=460x300") + onclose(user, "teg") return 1 \ No newline at end of file diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index d235d26ed58..42bebb8e6ab 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -1,717 +1,717 @@ -// The lighting system -// -// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/weapon/light) - -// status values shared between lighting fixtures and items -#define LIGHT_OK 0 -#define LIGHT_EMPTY 1 -#define LIGHT_BROKEN 2 -#define LIGHT_BURNED 3 - - -/obj/machinery/light_construct - name = "light fixture frame" - desc = "A light fixture under construction." - icon = 'icons/obj/lighting.dmi' - icon_state = "tube-construct-stage1" - anchored = 1 - layer = 5 - var/stage = 1 - var/fixture_type = "tube" - var/sheets_refunded = 2 - var/obj/machinery/light/newlight = null - -/obj/machinery/light_construct/New() - ..() - if (fixture_type == "bulb") - icon_state = "bulb-construct-stage1" - -/obj/machinery/light_construct/examine(mob/user) - ..() - var/mode - switch(src.stage) - if(1) - mode = "It's empty and lacks wiring." - if(2) - mode = "It's wired." - to_chat(user, "[mode]") - -/obj/machinery/light_construct/attackby(obj/item/weapon/W as obj, mob/user as mob) - src.add_fingerprint(user) - if (istype(W, /obj/item/weapon/wrench)) - if (src.stage == 1) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - to_chat(usr, "You begin deconstructing [src].") - if (!do_after(usr, src, 30)) - return - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = sheets_refunded - user.visible_message("[user.name] deconstructs [src].", \ - "You deconstruct [src].", "You hear a noise.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1) - qdel(src) - if (src.stage == 2) - to_chat(usr, "You have to remove the wires first.") - return - - if(istype(W, /obj/item/stack/cable_coil)) - if (src.stage == 1) - var/obj/item/stack/cable_coil/coil = W - coil.use(1) - switch(fixture_type) - if ("tube") - src.icon_state = "tube-empty" - if("bulb") - src.icon_state = "bulb-empty" - src.stage = 2 - user.visible_message("[user.name] adds wires to \the [src].", \ - "You add wires to \the [src]") - - switch(fixture_type) - if("tube") - newlight = new /obj/machinery/light/built(src.loc) - if ("bulb") - newlight = new /obj/machinery/light/small/built(src.loc) - - newlight.dir = src.dir - src.transfer_fingerprints_to(newlight) - qdel(src) - return - ..() - -/obj/machinery/light_construct/small - name = "small light fixture frame" - desc = "A small light fixture under construction." - icon = 'icons/obj/lighting.dmi' - icon_state = "bulb-construct-stage1" - anchored = 1 - layer = 5 - stage = 1 - fixture_type = "bulb" - sheets_refunded = 1 - -var/global/list/obj/machinery/light/alllights = list() - -// the standard tube light fixture -/obj/machinery/light - name = "light fixture" - icon = 'icons/obj/lighting.dmi' - var/base_state = "tube" // base description and icon_state - icon_state = "ltube1" - desc = "A lighting fixture." - anchored = 1 - layer = 5 // They were appearing under mobs which is a little weird - Ostaf - use_power = 2 - idle_power_usage = 2 - active_power_usage = 20 - power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list - var/cost = 8 - var/on = 0 // 1 if on, 0 if off - var/on_gs = 0 - var/static_power_used = 0 - var/brightness_range = 8 // luminosity when on, also used in power calculation - var/brightness_power = 1 - var/brightness_color = null - var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN - var/flickering = 0 - var/light_type = /obj/item/weapon/light/tube // the type of light item - var/fitting = "tube" - var/switchcount = 0 // count of number of times switched on/off - // this is used to calc the probability the light burns out - - var/rigged = 0 // true if rigged to explode - - // No ghost interaction. - ghost_read=0 - ghost_write=0 - - var/idle = 0 // For process(). - -/obj/machinery/light/spook() - if(..()) - flicker() - -// the smaller bulb light fixture - -/obj/machinery/light/cultify() - new /obj/structure/cult/pylon(loc) - qdel(src) - -/obj/machinery/light/bullet_act(var/obj/item/projectile/Proj) - if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)||istype(Proj,/obj/item/projectile/ricochet)) - if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) - broken() - -/obj/machinery/light/small - icon_state = "lbulb1" - base_state = "bulb" - fitting = "bulb" - brightness_range = 4 - brightness_power = 1 - brightness_color = LIGHT_COLOR_TUNGSTEN - cost = 4 - desc = "A small lighting fixture." - light_type = /obj/item/weapon/light/bulb - - -/obj/machinery/light/spot - name = "spotlight" - fitting = "large tube" - light_type = /obj/item/weapon/light/tube/large - brightness_range = 8 - brightness_power = 1 - cost = 8 - -/obj/machinery/light/built/New() - status = LIGHT_EMPTY - update(0) - ..() - -/obj/machinery/light/small/built/New() - status = LIGHT_EMPTY - update(0) - ..() - -// create a new lighting fixture -/obj/machinery/light/New() - ..() - alllights += src - - spawn(2) - var/area/A = get_area(src) - if(A && !A.requires_power) - on = 1 - - switch(fitting) - if("tube") - if(prob(2)) - broken(1) - if("bulb") - if(prob(5)) - broken(1) - spawn(1) - update(0) - -/obj/machinery/light/Destroy() - seton(0) - ..() - alllights -= src - -/obj/machinery/light/update_icon() - - switch(status) // set icon_states - if(LIGHT_OK) - icon_state = "l[base_state][on]" - if(LIGHT_EMPTY) - icon_state = "l[base_state]-empty" - on = 0 - if(LIGHT_BURNED) - icon_state = "l[base_state]-burned" - on = 0 - if(LIGHT_BROKEN) - icon_state = "l[base_state]-broken" - on = 0 - return - -// update the icon_state and luminosity of the light depending on its state -/obj/machinery/light/proc/update(var/trigger = 1) - - - update_icon() - if(on) - if(light_range != brightness_range || light_power != brightness_power || light_color != brightness_color) - switchcount++ - if(rigged) - if(status == LIGHT_OK && trigger) - - log_admin("LOG: Rigged light explosion, last touched by [fingerprintslast]") - message_admins("LOG: Rigged light explosion, last touched by [fingerprintslast]") - - explode() - else if( prob( min(60, switchcount*switchcount*0.01) ) ) - if(status == LIGHT_OK && trigger) - status = LIGHT_BURNED - icon_state = "l[base_state]-burned" - on = 0 - set_light(0) - else - use_power = 2 - set_light(brightness_range, brightness_power, brightness_color) - else - use_power = 1 - set_light(0) - - active_power_usage = (cost * 10) - if(on != on_gs) - on_gs = on - if(on) - static_power_used = cost * 20 //20W per unit luminosity - addStaticPower(static_power_used, STATIC_LIGHT) - else - removeStaticPower(static_power_used, STATIC_LIGHT) - - -/* - * Attempt to set the light's on/off status. - * Will not switch on if broken/burned/empty. - */ -/obj/machinery/light/proc/seton(const/s) - on = (s && LIGHT_OK == status) - update() - -// examine verb -/obj/machinery/light/examine(mob/user) - ..() - switch(status) - if(LIGHT_OK) - to_chat(user, "[desc] It is turned [on? "on" : "off"].") - if(LIGHT_EMPTY) - to_chat(user, "[desc] The [fitting] has been removed.") - if(LIGHT_BURNED) - to_chat(user, "[desc] The [fitting] is burnt out.") - if(LIGHT_BROKEN) - to_chat(user, "[desc] The [fitting] has been smashed.") - - -// attack with item - insert light (if right type), otherwise try to break the light - -/obj/machinery/light/attackby(obj/item/W, mob/user) - user.delayNextAttack(8) - //Light replacer code - if(istype(W, /obj/item/device/lightreplacer)) - var/obj/item/device/lightreplacer/LR = W - if(isliving(user)) - var/mob/living/U = user - LR.ReplaceLight(src, U) - return - - // attempt to insert light - if(istype(W, /obj/item/weapon/light)) - if(status != LIGHT_EMPTY) - to_chat(user, "There is a [fitting] already inserted.") - return - else - src.add_fingerprint(user) - var/obj/item/weapon/light/L = W - if(L.fitting == fitting) - if(!user.drop_item(L)) - user << "You can't let go of \the [L]!" - return - - status = L.status - to_chat(user, "You insert \the [L.name].") - switchcount = L.switchcount - rigged = L.rigged - brightness_range = L.brightness_range - brightness_power = L.brightness_power - brightness_color = L.brightness_color - cost = L.cost - base_state = L.base_state - light_type = L.type - on = has_power() - update() - - qdel(L) - - if(on && rigged) - - log_admin("LOG: Rigged light explosion, last touched by [fingerprintslast]") - message_admins("LOG: Rigged light explosion, last touched by [fingerprintslast]") - - explode() - else - to_chat(user, "This type of light requires a [fitting].") - return - - // attempt to break the light - //If xenos decide they want to smash a light bulb with a toolbox, who am I to stop them? /N - - else if(status != LIGHT_BROKEN && status != LIGHT_EMPTY) - - - if(prob(1+W.force * 5)) - - to_chat(user, "You hit the light, and it smashes!") - for(var/mob/M in viewers(src)) - if(M == user) - continue - M.show_message("[user.name] smashed the light!", 1, "You hear a tinkle of breaking glass", 2) - if(on && (W.is_conductor())) - //if(!user.mutations & M_RESIST_COLD) - if (prob(12)) - electrocute_mob(user, get_area(src), src, 0.3) - broken() - - else - to_chat(user, "You hit the light!") - // attempt to deconstruct / stick weapon into light socket - else if(status == LIGHT_EMPTY) - if(istype(W, /obj/item/weapon/wirecutters)) //If it's a wirecutter take out the wires - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 75, 1) - user.visible_message("[user.name] removes \the [src]'s wires.", \ - "You remove \the [src]'s wires.", "You hear a noise.") - var/obj/machinery/light_construct/newlight = null - switch(fitting) - if("tube") - newlight = new /obj/machinery/light_construct(src.loc) - newlight.icon_state = "tube-construct-stage1" - - if("bulb") - newlight = new /obj/machinery/light_construct/small(src.loc) - newlight.icon_state = "bulb-construct-stage1" - new /obj/item/stack/cable_coil(get_turf(src.loc), 1, "red") - newlight.dir = src.dir - newlight.stage = 1 - newlight.fingerprints = src.fingerprints - newlight.fingerprintshidden = src.fingerprintshidden - newlight.fingerprintslast = src.fingerprintslast - qdel(src) - return - - to_chat(user, "You stick \the [W] into the light socket!")//If not stick it in the socket. - - if(has_power() && (W.is_conductor())) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - //if(!user.mutations & M_RESIST_COLD) - if (prob(75)) - electrocute_mob(user, get_area(src), src, rand(0.7,1.0)) - -/* - * Returns whether this light has power - * TRUE if area has power and lightswitch is on otherwise FALSE. - */ -/obj/machinery/light/proc/has_power() - return areaMaster.lightswitch && areaMaster.power_light - -/obj/machinery/light/proc/flicker(var/amount = rand(10, 20)) - if(flickering) return - flickering = 1 - spawn(0) - if(on && status == LIGHT_OK) - for(var/i = 0; i < amount; i++) - if(status != LIGHT_OK) break - on = !on - update(0) - sleep(rand(5, 15)) - on = (status == LIGHT_OK) - update(0) - flickering = 0 - on = has_power() - update(0) - -/obj/machinery/light/attack_ghost(mob/user) - if(blessed) return - src.add_hiddenprint(user) - src.flicker(1) - return - -// ai attack - make lights flicker, because why not -/obj/machinery/light/attack_ai(mob/user) - // attack_robot is flaky. - if(isMoMMI(user)) - return attack_hand(user) - src.add_hiddenprint(user) - src.flicker(1) - return - -/obj/machinery/light/attack_robot(mob/user) - if(isMoMMI(user)) - return attack_hand(user) - else - return attack_ai(user) - - -// Aliens smash the bulb but do not get electrocuted./N -/obj/machinery/light/attack_alien(mob/living/carbon/alien/humanoid/user)//So larva don't go breaking light bulbs. - if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) - to_chat(user, "That object is useless to you.") - return - else if (status == LIGHT_OK||status == LIGHT_BURNED) - for(var/mob/M in viewers(src)) - M.show_message("[user.name] smashed the light!", 1, "You hear a tinkle of breaking glass", 2) - broken() - return - -/obj/machinery/light/attack_animal(mob/living/simple_animal/M) - if(M.melee_damage_upper == 0) return - if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) - to_chat(M, "That object is useless to you.") - return - else if (status == LIGHT_OK||status == LIGHT_BURNED) - for(var/mob/O in viewers(src)) - O.show_message("[M.name] smashed the light!", 1, "You hear a tinkle of breaking glass", 2) - broken() - return -// attack with hand - remove tube/bulb -// if hands aren't protected and the light is on, burn the player - -/obj/machinery/light/attack_hand(mob/user) - if(isobserver(user)) - return - - if(!Adjacent(user)) return - - add_fingerprint(user) - - if(status == LIGHT_EMPTY) - to_chat(user, "There is no [fitting] in this light.") - return - - // make it burn hands if not wearing fire-insulated gloves - if(on) - var/prot = 0 - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - if(G.max_heat_protection_temperature) - prot = (G.max_heat_protection_temperature > 360) - else - prot = 1 - - if(prot > 0 || (M_RESIST_HEAT in user.mutations)) - to_chat(user, "You remove the light [fitting]") - else - to_chat(user, "You try to remove the light [fitting], but it's too hot and you don't want to burn your hand.") - return // if burned, don't remove the light - - // create a light tube/bulb item and put it in the user's hand - var/obj/item/weapon/light/L = new light_type() - L.status = status - L.rigged = rigged - L.brightness_range = brightness_range - L.brightness_power = brightness_power - L.brightness_color = brightness_color - - // light item inherits the switchcount, then zero it - L.switchcount = switchcount - switchcount = 0 - - L.update() - L.add_fingerprint(user) - - user.put_in_active_hand(L) //puts it in our active hand - - status = LIGHT_EMPTY - update() - -// break the light and make sparks if was on - -/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = 0) - if(status == LIGHT_EMPTY) - return - - if(!skip_sound_and_sparks) - if(status == LIGHT_OK || status == LIGHT_BURNED) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - if(on) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - status = LIGHT_BROKEN - update() - -/obj/machinery/light/proc/fix() - if(status == LIGHT_OK) - return - status = LIGHT_OK - on = 1 - update() - -// explosion effect -// destroy the whole light fixture or just shatter it - -/obj/machinery/light/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(75)) - broken() - if(3.0) - if (prob(50)) - broken() - return - -//blob effect - -/obj/machinery/light/blob_act() - if(prob(75)) - broken() -/* - * Called when area power state changes. - */ -/obj/machinery/light/power_change() - spawn(10) - seton(areaMaster.lightswitch && areaMaster.power_light) - -// called when on fire - -/obj/machinery/light/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(prob(max(0, exposed_temperature - 673))) //0% at <400C, 100% at >500C - broken() - -/* - * Explode the light. - */ -/obj/machinery/light/proc/explode() - spawn(0) - broken() // Break it first to give a warning. - sleep(2) - explosion(get_turf(src), 0, 0, 2, 2) - sleep(1) - qdel(src) - -// the light item -// can be tube or bulb subtypes -// will fit into empty /obj/machinery/light of the corresponding type - -/obj/item/weapon/light - icon = 'icons/obj/lighting.dmi' - flags = FPRINT - force = 2 - throwforce = 5 - w_class = 1 - var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN - var/base_state - var/switchcount = 0 // number of times switched - //starting_materials = list(MAT_IRON = 60) //Not necessary, as this exact type should never appear and each subtype has its materials defined. - var/rigged = 0 // true if rigged to explode - var/brightness_range = 2 //how much light it gives off - var/brightness_power = 1 - var/brightness_color = null - var/cost = 2 //How much power does it consume in an idle state? - var/fitting = "tube" - -/obj/item/weapon/light/tube - name = "light tube" - desc = "A replacement light tube." - icon_state = "tube" - base_state = "tube" - item_state = "c_tube" - starting_materials = list(MAT_GLASS = 100, MAT_IRON = 60) - w_type = RECYK_GLASS - brightness_range = 8 - brightness_power = 3 - cost = 8 - -/obj/item/weapon/light/tube/he - name = "high efficiency light tube" - desc = "An efficient light used to reduce strain on the station's power grid." - base_state = "hetube" - starting_materials = list(MAT_GLASS = 300, MAT_IRON = 60) - cost = 2 - -/obj/item/weapon/light/tube/large - w_class = 2 - name = "large light tube" - brightness_range = 15 - brightness_power = 4 - starting_materials = list(MAT_GLASS = 200, MAT_IRON = 100) - cost = 15 - -/obj/item/weapon/light/bulb - name = "light bulb" - desc = "A replacement light bulb." - icon_state = "bulb" - base_state = "bulb" - item_state = "contvapour" - fitting = "bulb" - brightness_range = 5 - brightness_power = 2 - brightness_color = LIGHT_COLOR_TUNGSTEN - starting_materials = list(MAT_GLASS = 50, MAT_IRON = 30) - cost = 5 - w_type = RECYK_GLASS - -/obj/item/weapon/light/bulb/he - name = "high efficiency light bulb" - desc = "An efficient light used to reduce strain on the station's power grid." - base_state = "hebulb" - cost = 1 - starting_materials = list(MAT_GLASS = 150, MAT_IRON = 30) - brightness_color = null//These should be white - -/obj/item/weapon/light/throw_impact(atom/hit_atom) - ..() - shatter() - -/obj/item/weapon/light/bulb/fire - name = "fire bulb" - desc = "A replacement fire bulb." - icon_state = "fbulb" - base_state = "fbulb" - item_state = "egg4" - brightness_range = 5 - brightness_power = 2 - starting_materials = list(MAT_GLASS = 300, MAT_IRON = 60) - -// update the icon state and description of the light - -/obj/item/weapon/light/proc/update() - switch(status) - if(LIGHT_OK) - icon_state = base_state - desc = "A replacement [name]." - if(LIGHT_BURNED) - icon_state = "[base_state]-burned" - desc = "A burnt-out [name]." - if(LIGHT_BROKEN) - icon_state = "[base_state]-broken" - desc = "A broken [name]." - - -/obj/item/weapon/light/New() - ..() - switch(name) - if("light tube") - brightness_range = rand(6,9) - if("light bulb") - brightness_range = rand(4,6) - update() - - -// attack bulb/tube with object -// if a syringe, can inject plasma to make it explode -/obj/item/weapon/light/attackby(var/obj/item/I, var/mob/user) - ..() - if(istype(I, /obj/item/weapon/reagent_containers/syringe)) - var/obj/item/weapon/reagent_containers/syringe/S = I - - to_chat(user, "You inject the solution into the [src].") - - if(S.reagents.has_reagent("plasma", 5)) - - log_admin("LOG: [user.name] ([user.ckey]) injected a light with plasma, rigging it to explode.") - message_admins("LOG: [user.name] ([user.ckey]) injected a light with plasma, rigging it to explode.") - - rigged = 1 - - S.reagents.clear_reagents() - else - ..() - return - -// called after an attack with a light item -// shatter light, unless it was an attempt to put it in a light socket -// now only shatter if the intent was harm - -/obj/item/weapon/light/afterattack(atom/target, mob/user) - if(istype(target, /obj/machinery/light)) - return - if(user.a_intent != I_HURT) - return - - shatter() - -/obj/item/weapon/light/proc/shatter() - if(status == LIGHT_OK || status == LIGHT_BURNED) - src.visible_message("[name] shatters.","You hear a small glass object shatter.") - status = LIGHT_BROKEN - force = 5 - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) - update() +// The lighting system +// +// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/weapon/light) + +// status values shared between lighting fixtures and items +#define LIGHT_OK 0 +#define LIGHT_EMPTY 1 +#define LIGHT_BROKEN 2 +#define LIGHT_BURNED 3 + + +/obj/machinery/light_construct + name = "light fixture frame" + desc = "A light fixture under construction." + icon = 'icons/obj/lighting.dmi' + icon_state = "tube-construct-stage1" + anchored = 1 + layer = 5 + var/stage = 1 + var/fixture_type = "tube" + var/sheets_refunded = 2 + var/obj/machinery/light/newlight = null + +/obj/machinery/light_construct/New() + ..() + if (fixture_type == "bulb") + icon_state = "bulb-construct-stage1" + +/obj/machinery/light_construct/examine(mob/user) + ..() + var/mode + switch(src.stage) + if(1) + mode = "It's empty and lacks wiring." + if(2) + mode = "It's wired." + to_chat(user, "[mode]") + +/obj/machinery/light_construct/attackby(obj/item/weapon/W as obj, mob/user as mob) + src.add_fingerprint(user) + if (istype(W, /obj/item/weapon/wrench)) + if (src.stage == 1) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + to_chat(usr, "You begin deconstructing [src].") + if (!do_after(usr, src, 30)) + return + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = sheets_refunded + user.visible_message("[user.name] deconstructs [src].", \ + "You deconstruct [src].", "You hear a noise.") + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1) + qdel(src) + if (src.stage == 2) + to_chat(usr, "You have to remove the wires first.") + return + + if(istype(W, /obj/item/stack/cable_coil)) + if (src.stage == 1) + var/obj/item/stack/cable_coil/coil = W + coil.use(1) + switch(fixture_type) + if ("tube") + src.icon_state = "tube-empty" + if("bulb") + src.icon_state = "bulb-empty" + src.stage = 2 + user.visible_message("[user.name] adds wires to \the [src].", \ + "You add wires to \the [src]") + + switch(fixture_type) + if("tube") + newlight = new /obj/machinery/light/built(src.loc) + if ("bulb") + newlight = new /obj/machinery/light/small/built(src.loc) + + newlight.dir = src.dir + src.transfer_fingerprints_to(newlight) + qdel(src) + return + ..() + +/obj/machinery/light_construct/small + name = "small light fixture frame" + desc = "A small light fixture under construction." + icon = 'icons/obj/lighting.dmi' + icon_state = "bulb-construct-stage1" + anchored = 1 + layer = 5 + stage = 1 + fixture_type = "bulb" + sheets_refunded = 1 + +var/global/list/obj/machinery/light/alllights = list() + +// the standard tube light fixture +/obj/machinery/light + name = "light fixture" + icon = 'icons/obj/lighting.dmi' + var/base_state = "tube" // base description and icon_state + icon_state = "ltube1" + desc = "A lighting fixture." + anchored = 1 + layer = 5 // They were appearing under mobs which is a little weird - Ostaf + use_power = 2 + idle_power_usage = 2 + active_power_usage = 20 + power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list + var/cost = 8 + var/on = 0 // 1 if on, 0 if off + var/on_gs = 0 + var/static_power_used = 0 + var/brightness_range = 8 // luminosity when on, also used in power calculation + var/brightness_power = 1 + var/brightness_color = null + var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN + var/flickering = 0 + var/light_type = /obj/item/weapon/light/tube // the type of light item + var/fitting = "tube" + var/switchcount = 0 // count of number of times switched on/off + // this is used to calc the probability the light burns out + + var/rigged = 0 // true if rigged to explode + + // No ghost interaction. + ghost_read=0 + ghost_write=0 + + var/idle = 0 // For process(). + +/obj/machinery/light/spook() + if(..()) + flicker() + +// the smaller bulb light fixture + +/obj/machinery/light/cultify() + new /obj/structure/cult/pylon(loc) + qdel(src) + +/obj/machinery/light/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)||istype(Proj,/obj/item/projectile/ricochet)) + if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) + broken() + +/obj/machinery/light/small + icon_state = "lbulb1" + base_state = "bulb" + fitting = "bulb" + brightness_range = 4 + brightness_power = 1 + brightness_color = LIGHT_COLOR_TUNGSTEN + cost = 4 + desc = "A small lighting fixture." + light_type = /obj/item/weapon/light/bulb + + +/obj/machinery/light/spot + name = "spotlight" + fitting = "large tube" + light_type = /obj/item/weapon/light/tube/large + brightness_range = 8 + brightness_power = 1 + cost = 8 + +/obj/machinery/light/built/New() + status = LIGHT_EMPTY + update(0) + ..() + +/obj/machinery/light/small/built/New() + status = LIGHT_EMPTY + update(0) + ..() + +// create a new lighting fixture +/obj/machinery/light/New() + ..() + alllights += src + + spawn(2) + var/area/A = get_area(src) + if(A && !A.requires_power) + on = 1 + + switch(fitting) + if("tube") + if(prob(2)) + broken(1) + if("bulb") + if(prob(5)) + broken(1) + spawn(1) + update(0) + +/obj/machinery/light/Destroy() + seton(0) + ..() + alllights -= src + +/obj/machinery/light/update_icon() + + switch(status) // set icon_states + if(LIGHT_OK) + icon_state = "l[base_state][on]" + if(LIGHT_EMPTY) + icon_state = "l[base_state]-empty" + on = 0 + if(LIGHT_BURNED) + icon_state = "l[base_state]-burned" + on = 0 + if(LIGHT_BROKEN) + icon_state = "l[base_state]-broken" + on = 0 + return + +// update the icon_state and luminosity of the light depending on its state +/obj/machinery/light/proc/update(var/trigger = 1) + + + update_icon() + if(on) + if(light_range != brightness_range || light_power != brightness_power || light_color != brightness_color) + switchcount++ + if(rigged) + if(status == LIGHT_OK && trigger) + + log_admin("LOG: Rigged light explosion, last touched by [fingerprintslast]") + message_admins("LOG: Rigged light explosion, last touched by [fingerprintslast]") + + explode() + else if( prob( min(60, switchcount*switchcount*0.01) ) ) + if(status == LIGHT_OK && trigger) + status = LIGHT_BURNED + icon_state = "l[base_state]-burned" + on = 0 + set_light(0) + else + use_power = 2 + set_light(brightness_range, brightness_power, brightness_color) + else + use_power = 1 + set_light(0) + + active_power_usage = (cost * 10) + if(on != on_gs) + on_gs = on + if(on) + static_power_used = cost * 20 //20W per unit luminosity + addStaticPower(static_power_used, STATIC_LIGHT) + else + removeStaticPower(static_power_used, STATIC_LIGHT) + + +/* + * Attempt to set the light's on/off status. + * Will not switch on if broken/burned/empty. + */ +/obj/machinery/light/proc/seton(const/s) + on = (s && LIGHT_OK == status) + update() + +// examine verb +/obj/machinery/light/examine(mob/user) + ..() + switch(status) + if(LIGHT_OK) + to_chat(user, "[desc] It is turned [on? "on" : "off"].") + if(LIGHT_EMPTY) + to_chat(user, "[desc] The [fitting] has been removed.") + if(LIGHT_BURNED) + to_chat(user, "[desc] The [fitting] is burnt out.") + if(LIGHT_BROKEN) + to_chat(user, "[desc] The [fitting] has been smashed.") + + +// attack with item - insert light (if right type), otherwise try to break the light + +/obj/machinery/light/attackby(obj/item/W, mob/user) + user.delayNextAttack(8) + //Light replacer code + if(istype(W, /obj/item/device/lightreplacer)) + var/obj/item/device/lightreplacer/LR = W + if(isliving(user)) + var/mob/living/U = user + LR.ReplaceLight(src, U) + return + + // attempt to insert light + if(istype(W, /obj/item/weapon/light)) + if(status != LIGHT_EMPTY) + to_chat(user, "There is a [fitting] already inserted.") + return + else + src.add_fingerprint(user) + var/obj/item/weapon/light/L = W + if(L.fitting == fitting) + if(!user.drop_item(L)) + user << "You can't let go of \the [L]!" + return + + status = L.status + to_chat(user, "You insert \the [L.name].") + switchcount = L.switchcount + rigged = L.rigged + brightness_range = L.brightness_range + brightness_power = L.brightness_power + brightness_color = L.brightness_color + cost = L.cost + base_state = L.base_state + light_type = L.type + on = has_power() + update() + + qdel(L) + + if(on && rigged) + + log_admin("LOG: Rigged light explosion, last touched by [fingerprintslast]") + message_admins("LOG: Rigged light explosion, last touched by [fingerprintslast]") + + explode() + else + to_chat(user, "This type of light requires a [fitting].") + return + + // attempt to break the light + //If xenos decide they want to smash a light bulb with a toolbox, who am I to stop them? /N + + else if(status != LIGHT_BROKEN && status != LIGHT_EMPTY) + + + if(prob(1+W.force * 5)) + + to_chat(user, "You hit the light, and it smashes!") + for(var/mob/M in viewers(src)) + if(M == user) + continue + M.show_message("[user.name] smashed the light!", 1, "You hear a tinkle of breaking glass", 2) + if(on && (W.is_conductor())) + //if(!user.mutations & M_RESIST_COLD) + if (prob(12)) + electrocute_mob(user, get_area(src), src, 0.3) + broken() + + else + to_chat(user, "You hit the light!") + // attempt to deconstruct / stick weapon into light socket + else if(status == LIGHT_EMPTY) + if(istype(W, /obj/item/weapon/wirecutters)) //If it's a wirecutter take out the wires + playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 75, 1) + user.visible_message("[user.name] removes \the [src]'s wires.", \ + "You remove \the [src]'s wires.", "You hear a noise.") + var/obj/machinery/light_construct/newlight = null + switch(fitting) + if("tube") + newlight = new /obj/machinery/light_construct(src.loc) + newlight.icon_state = "tube-construct-stage1" + + if("bulb") + newlight = new /obj/machinery/light_construct/small(src.loc) + newlight.icon_state = "bulb-construct-stage1" + new /obj/item/stack/cable_coil(get_turf(src.loc), 1, "red") + newlight.dir = src.dir + newlight.stage = 1 + newlight.fingerprints = src.fingerprints + newlight.fingerprintshidden = src.fingerprintshidden + newlight.fingerprintslast = src.fingerprintslast + qdel(src) + return + + to_chat(user, "You stick \the [W] into the light socket!")//If not stick it in the socket. + + if(has_power() && (W.is_conductor())) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + //if(!user.mutations & M_RESIST_COLD) + if (prob(75)) + electrocute_mob(user, get_area(src), src, rand(0.7,1.0)) + +/* + * Returns whether this light has power + * TRUE if area has power and lightswitch is on otherwise FALSE. + */ +/obj/machinery/light/proc/has_power() + return areaMaster.lightswitch && areaMaster.power_light + +/obj/machinery/light/proc/flicker(var/amount = rand(10, 20)) + if(flickering) return + flickering = 1 + spawn(0) + if(on && status == LIGHT_OK) + for(var/i = 0; i < amount; i++) + if(status != LIGHT_OK) break + on = !on + update(0) + sleep(rand(5, 15)) + on = (status == LIGHT_OK) + update(0) + flickering = 0 + on = has_power() + update(0) + +/obj/machinery/light/attack_ghost(mob/user) + if(blessed) return + src.add_hiddenprint(user) + src.flicker(1) + return + +// ai attack - make lights flicker, because why not +/obj/machinery/light/attack_ai(mob/user) + // attack_robot is flaky. + if(isMoMMI(user)) + return attack_hand(user) + src.add_hiddenprint(user) + src.flicker(1) + return + +/obj/machinery/light/attack_robot(mob/user) + if(isMoMMI(user)) + return attack_hand(user) + else + return attack_ai(user) + + +// Aliens smash the bulb but do not get electrocuted./N +/obj/machinery/light/attack_alien(mob/living/carbon/alien/humanoid/user)//So larva don't go breaking light bulbs. + if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) + to_chat(user, "That object is useless to you.") + return + else if (status == LIGHT_OK||status == LIGHT_BURNED) + for(var/mob/M in viewers(src)) + M.show_message("[user.name] smashed the light!", 1, "You hear a tinkle of breaking glass", 2) + broken() + return + +/obj/machinery/light/attack_animal(mob/living/simple_animal/M) + if(M.melee_damage_upper == 0) return + if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) + to_chat(M, "That object is useless to you.") + return + else if (status == LIGHT_OK||status == LIGHT_BURNED) + for(var/mob/O in viewers(src)) + O.show_message("[M.name] smashed the light!", 1, "You hear a tinkle of breaking glass", 2) + broken() + return +// attack with hand - remove tube/bulb +// if hands aren't protected and the light is on, burn the player + +/obj/machinery/light/attack_hand(mob/user) + if(isobserver(user)) + return + + if(!Adjacent(user)) return + + add_fingerprint(user) + + if(status == LIGHT_EMPTY) + to_chat(user, "There is no [fitting] in this light.") + return + + // make it burn hands if not wearing fire-insulated gloves + if(on) + var/prot = 0 + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(G.max_heat_protection_temperature) + prot = (G.max_heat_protection_temperature > 360) + else + prot = 1 + + if(prot > 0 || (M_RESIST_HEAT in user.mutations)) + to_chat(user, "You remove the light [fitting]") + else + to_chat(user, "You try to remove the light [fitting], but it's too hot and you don't want to burn your hand.") + return // if burned, don't remove the light + + // create a light tube/bulb item and put it in the user's hand + var/obj/item/weapon/light/L = new light_type() + L.status = status + L.rigged = rigged + L.brightness_range = brightness_range + L.brightness_power = brightness_power + L.brightness_color = brightness_color + + // light item inherits the switchcount, then zero it + L.switchcount = switchcount + switchcount = 0 + + L.update() + L.add_fingerprint(user) + + user.put_in_active_hand(L) //puts it in our active hand + + status = LIGHT_EMPTY + update() + +// break the light and make sparks if was on + +/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = 0) + if(status == LIGHT_EMPTY) + return + + if(!skip_sound_and_sparks) + if(status == LIGHT_OK || status == LIGHT_BURNED) + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + if(on) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + status = LIGHT_BROKEN + update() + +/obj/machinery/light/proc/fix() + if(status == LIGHT_OK) + return + status = LIGHT_OK + on = 1 + update() + +// explosion effect +// destroy the whole light fixture or just shatter it + +/obj/machinery/light/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(75)) + broken() + if(3.0) + if (prob(50)) + broken() + return + +//blob effect + +/obj/machinery/light/blob_act() + if(prob(75)) + broken() +/* + * Called when area power state changes. + */ +/obj/machinery/light/power_change() + spawn(10) + seton(areaMaster.lightswitch && areaMaster.power_light) + +// called when on fire + +/obj/machinery/light/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(prob(max(0, exposed_temperature - 673))) //0% at <400C, 100% at >500C + broken() + +/* + * Explode the light. + */ +/obj/machinery/light/proc/explode() + spawn(0) + broken() // Break it first to give a warning. + sleep(2) + explosion(get_turf(src), 0, 0, 2, 2) + sleep(1) + qdel(src) + +// the light item +// can be tube or bulb subtypes +// will fit into empty /obj/machinery/light of the corresponding type + +/obj/item/weapon/light + icon = 'icons/obj/lighting.dmi' + flags = FPRINT + force = 2 + throwforce = 5 + w_class = 1 + var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN + var/base_state + var/switchcount = 0 // number of times switched + //starting_materials = list(MAT_IRON = 60) //Not necessary, as this exact type should never appear and each subtype has its materials defined. + var/rigged = 0 // true if rigged to explode + var/brightness_range = 2 //how much light it gives off + var/brightness_power = 1 + var/brightness_color = null + var/cost = 2 //How much power does it consume in an idle state? + var/fitting = "tube" + +/obj/item/weapon/light/tube + name = "light tube" + desc = "A replacement light tube." + icon_state = "tube" + base_state = "tube" + item_state = "c_tube" + starting_materials = list(MAT_GLASS = 100, MAT_IRON = 60) + w_type = RECYK_GLASS + brightness_range = 8 + brightness_power = 3 + cost = 8 + +/obj/item/weapon/light/tube/he + name = "high efficiency light tube" + desc = "An efficient light used to reduce strain on the station's power grid." + base_state = "hetube" + starting_materials = list(MAT_GLASS = 300, MAT_IRON = 60) + cost = 2 + +/obj/item/weapon/light/tube/large + w_class = 2 + name = "large light tube" + brightness_range = 15 + brightness_power = 4 + starting_materials = list(MAT_GLASS = 200, MAT_IRON = 100) + cost = 15 + +/obj/item/weapon/light/bulb + name = "light bulb" + desc = "A replacement light bulb." + icon_state = "bulb" + base_state = "bulb" + item_state = "contvapour" + fitting = "bulb" + brightness_range = 5 + brightness_power = 2 + brightness_color = LIGHT_COLOR_TUNGSTEN + starting_materials = list(MAT_GLASS = 50, MAT_IRON = 30) + cost = 5 + w_type = RECYK_GLASS + +/obj/item/weapon/light/bulb/he + name = "high efficiency light bulb" + desc = "An efficient light used to reduce strain on the station's power grid." + base_state = "hebulb" + cost = 1 + starting_materials = list(MAT_GLASS = 150, MAT_IRON = 30) + brightness_color = null//These should be white + +/obj/item/weapon/light/throw_impact(atom/hit_atom) + ..() + shatter() + +/obj/item/weapon/light/bulb/fire + name = "fire bulb" + desc = "A replacement fire bulb." + icon_state = "fbulb" + base_state = "fbulb" + item_state = "egg4" + brightness_range = 5 + brightness_power = 2 + starting_materials = list(MAT_GLASS = 300, MAT_IRON = 60) + +// update the icon state and description of the light + +/obj/item/weapon/light/proc/update() + switch(status) + if(LIGHT_OK) + icon_state = base_state + desc = "A replacement [name]." + if(LIGHT_BURNED) + icon_state = "[base_state]-burned" + desc = "A burnt-out [name]." + if(LIGHT_BROKEN) + icon_state = "[base_state]-broken" + desc = "A broken [name]." + + +/obj/item/weapon/light/New() + ..() + switch(name) + if("light tube") + brightness_range = rand(6,9) + if("light bulb") + brightness_range = rand(4,6) + update() + + +// attack bulb/tube with object +// if a syringe, can inject plasma to make it explode +/obj/item/weapon/light/attackby(var/obj/item/I, var/mob/user) + ..() + if(istype(I, /obj/item/weapon/reagent_containers/syringe)) + var/obj/item/weapon/reagent_containers/syringe/S = I + + to_chat(user, "You inject the solution into the [src].") + + if(S.reagents.has_reagent("plasma", 5)) + + log_admin("LOG: [user.name] ([user.ckey]) injected a light with plasma, rigging it to explode.") + message_admins("LOG: [user.name] ([user.ckey]) injected a light with plasma, rigging it to explode.") + + rigged = 1 + + S.reagents.clear_reagents() + else + ..() + return + +// called after an attack with a light item +// shatter light, unless it was an attempt to put it in a light socket +// now only shatter if the intent was harm + +/obj/item/weapon/light/afterattack(atom/target, mob/user) + if(istype(target, /obj/machinery/light)) + return + if(user.a_intent != I_HURT) + return + + shatter() + +/obj/item/weapon/light/proc/shatter() + if(status == LIGHT_OK || status == LIGHT_BURNED) + src.visible_message("[name] shatters.","You hear a small glass object shatter.") + status = LIGHT_BROKEN + force = 5 + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + update() diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 8bbc5f6610f..bbba37934ca 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -1,336 +1,336 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/* new portable generator - work in progress - -/obj/machinery/power/port_gen - name = "portable generator" - desc = "A portable generator used for emergency backup power." - icon = 'generator.dmi' - icon_state = "off" - density = 1 - anchored = 0 - var/t_status = 0 - var/t_per = 5000 - var/filter = 1 - var/tank = null - var/turf/inturf - var/starter = 0 - var/rpm = 0 - var/rpmtarget = 0 - var/capacity = 1e6 - var/turf/outturf - var/lastgen - - -/obj/machinery/power/port_gen/process() -ideally we're looking to generate 5000 - -/obj/machinery/power/port_gen/attackby(obj/item/weapon/W, mob/user) -tank [un]loading stuff - -/obj/machinery/power/port_gen/attack_hand(mob/user) -turn on/off - -/obj/machinery/power/port_gen/examine() -display round(lastgen) and plasmatank amount - -*/ - -//Previous code been here forever, adding new framework for portable generators - - -//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power). -/obj/machinery/power/port_gen - name = "Portable Generator" - desc = "A portable generator for emergency backup power" - icon = 'icons/obj/power.dmi' - icon_state = "portgen0" - density = 1 - anchored = 0 - use_power = 0 - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - var/active = 0 - var/power_gen = 5000 - var/recent_fault = 0 - var/power_output = 1 - -/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check. - return 1 - -/obj/machinery/power/port_gen/proc/UseFuel() //Placeholder for fuel use. - return - -/obj/machinery/power/port_gen/proc/DropFuel() - return - -/obj/machinery/power/port_gen/proc/handleInactive() - return - -/obj/machinery/power/port_gen/process() - if(active && HasFuel() && !crit_fail && anchored && powernet) - add_avail(power_gen * power_output) - UseFuel() - src.updateDialog() - - else - active = 0 - icon_state = initial(icon_state) - handleInactive() - -/obj/machinery/power/port_gen/attack_hand(mob/user as mob) - if(..()) - return - if(!anchored) - return - -/obj/machinery/power/port_gen/examine(mob/user) - ..() - if(active) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/* new portable generator - work in progress + +/obj/machinery/power/port_gen + name = "portable generator" + desc = "A portable generator used for emergency backup power." + icon = 'generator.dmi' + icon_state = "off" + density = 1 + anchored = 0 + var/t_status = 0 + var/t_per = 5000 + var/filter = 1 + var/tank = null + var/turf/inturf + var/starter = 0 + var/rpm = 0 + var/rpmtarget = 0 + var/capacity = 1e6 + var/turf/outturf + var/lastgen + + +/obj/machinery/power/port_gen/process() +ideally we're looking to generate 5000 + +/obj/machinery/power/port_gen/attackby(obj/item/weapon/W, mob/user) +tank [un]loading stuff + +/obj/machinery/power/port_gen/attack_hand(mob/user) +turn on/off + +/obj/machinery/power/port_gen/examine() +display round(lastgen) and plasmatank amount + +*/ + +//Previous code been here forever, adding new framework for portable generators + + +//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power). +/obj/machinery/power/port_gen + name = "Portable Generator" + desc = "A portable generator for emergency backup power" + icon = 'icons/obj/power.dmi' + icon_state = "portgen0" + density = 1 + anchored = 0 + use_power = 0 + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + var/active = 0 + var/power_gen = 5000 + var/recent_fault = 0 + var/power_output = 1 + +/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check. + return 1 + +/obj/machinery/power/port_gen/proc/UseFuel() //Placeholder for fuel use. + return + +/obj/machinery/power/port_gen/proc/DropFuel() + return + +/obj/machinery/power/port_gen/proc/handleInactive() + return + +/obj/machinery/power/port_gen/process() + if(active && HasFuel() && !crit_fail && anchored && powernet) + add_avail(power_gen * power_output) + UseFuel() + src.updateDialog() + + else + active = 0 + icon_state = initial(icon_state) + handleInactive() + +/obj/machinery/power/port_gen/attack_hand(mob/user as mob) + if(..()) + return + if(!anchored) + return + +/obj/machinery/power/port_gen/examine(mob/user) + ..() + if(active) to_chat(usr, "The generator is on.") - else + else to_chat(usr, "The generator is off.") - -/obj/machinery/power/port_gen/pacman - name = "P.A.C.M.A.N.-type Portable Generator" - var/sheets = 0 - var/max_sheets = 100 - var/sheet_name = "" - var/sheet_path = /obj/item/stack/sheet/mineral/plasma - var/board_path = "/obj/item/weapon/circuitboard/pacman" - var/sheet_left = 0 // How much is left of the sheet - var/time_per_sheet = 40 - var/heat = 0 - -/obj/machinery/power/port_gen/pacman/initialize() - ..() - if(anchored) - connect_to_network() - -/obj/machinery/power/port_gen/pacman/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/stack/cable_coil, - /obj/item/stack/cable_coil, - /obj/item/weapon/stock_parts/capacitor, - board_path - ) - - var/obj/sheet = new sheet_path(null) - sheet_name = sheet.name - RefreshParts() - -/obj/machinery/power/port_gen/pacman/Destroy() - DropFuel() - ..() - -/obj/machinery/power/port_gen/pacman/RefreshParts() - var/temp_rating = 0 - var/temp_reliability = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/matter_bin)) - max_sheets = SP.rating * SP.rating * 50 - else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor)) - temp_rating += SP.rating - for(var/obj/item/weapon/CP in component_parts) - temp_reliability += CP.reliability - reliability = min(round(temp_reliability / 4), 100) - power_gen = round(initial(power_gen) * (max(2, temp_rating) / 2)) - -/obj/machinery/power/port_gen/pacman/examine(mob/user) - ..() - if(crit_fail) + +/obj/machinery/power/port_gen/pacman + name = "P.A.C.M.A.N.-type Portable Generator" + var/sheets = 0 + var/max_sheets = 100 + var/sheet_name = "" + var/sheet_path = /obj/item/stack/sheet/mineral/plasma + var/board_path = "/obj/item/weapon/circuitboard/pacman" + var/sheet_left = 0 // How much is left of the sheet + var/time_per_sheet = 40 + var/heat = 0 + +/obj/machinery/power/port_gen/pacman/initialize() + ..() + if(anchored) + connect_to_network() + +/obj/machinery/power/port_gen/pacman/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/stack/cable_coil, + /obj/item/stack/cable_coil, + /obj/item/weapon/stock_parts/capacitor, + board_path + ) + + var/obj/sheet = new sheet_path(null) + sheet_name = sheet.name + RefreshParts() + +/obj/machinery/power/port_gen/pacman/Destroy() + DropFuel() + ..() + +/obj/machinery/power/port_gen/pacman/RefreshParts() + var/temp_rating = 0 + var/temp_reliability = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/matter_bin)) + max_sheets = SP.rating * SP.rating * 50 + else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor)) + temp_rating += SP.rating + for(var/obj/item/weapon/CP in component_parts) + temp_reliability += CP.reliability + reliability = min(round(temp_reliability / 4), 100) + power_gen = round(initial(power_gen) * (max(2, temp_rating) / 2)) + +/obj/machinery/power/port_gen/pacman/examine(mob/user) + ..() + if(crit_fail) to_chat(user, "The generator seems to have broken down.") - else + else to_chat(user, "The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle.") - -/obj/machinery/power/port_gen/pacman/HasFuel() - if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left) - return 1 - return 0 - -/obj/machinery/power/port_gen/pacman/DropFuel() - if(sheets) - var/fail_safe = 0 - while(sheets > 0 && fail_safe < 100) - fail_safe += 1 - var/obj/item/stack/sheet/S = new sheet_path(loc) - var/amount = min(sheets, S.max_amount) - S.amount = amount - sheets -= amount - -/obj/machinery/power/port_gen/pacman/UseFuel() - var/needed_sheets = 1 / (time_per_sheet / power_output) - var/temp = min(needed_sheets, sheet_left) - needed_sheets -= temp - sheet_left -= temp - sheets -= round(needed_sheets) - needed_sheets -= round(needed_sheets) - if (sheet_left <= 0 && sheets > 0) - sheet_left = 1 - needed_sheets - sheets-- - - var/lower_limit = 56 + power_output * 10 - var/upper_limit = 76 + power_output * 10 - var/bias = 0 - if (power_output > 4) - upper_limit = 400 - bias = power_output * 3 - if (heat < lower_limit) - heat += 3 - else - heat += rand(-7 + bias, 7 + bias) - if (heat < lower_limit) - heat = lower_limit - if (heat > upper_limit) - heat = upper_limit - - if (heat > 300) - overheat() - qdel(src) - return - -/obj/machinery/power/port_gen/pacman/handleInactive() - - if (heat > 0) - heat = max(heat - 2, 0) - src.updateDialog() - -/obj/machinery/power/port_gen/pacman/proc/overheat() - explosion(src.loc, 2, 5, 2, -1) - -/obj/machinery/power/port_gen/pacman/emag(mob/user) - emagged = 1 - emp_act(1) - return 1 - -/obj/machinery/power/port_gen/pacman/crowbarDestroy(mob/user) //don't like the copy/paste, but the proc has special handling in the middle so we need it - if(..()) - while ( sheets > 0 ) - var/obj/item/stack/sheet/G = new sheet_path(src.loc) - if ( sheets > 50 ) - G.amount = 50 - else - G.amount = sheets - sheets -= G.amount - return 1 - return -1 - -/obj/machinery/power/port_gen/pacman/wrenchAnchor(mob/user) - if(..() == 1) - if(anchored) - connect_to_network() - else - disconnect_from_network() - return 1 - return -1 - -/obj/machinery/power/port_gen/pacman/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O, sheet_path)) - var/obj/item/stack/addstack = O - var/amount = min((max_sheets - sheets), addstack.amount) - if(amount < 1) + +/obj/machinery/power/port_gen/pacman/HasFuel() + if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left) + return 1 + return 0 + +/obj/machinery/power/port_gen/pacman/DropFuel() + if(sheets) + var/fail_safe = 0 + while(sheets > 0 && fail_safe < 100) + fail_safe += 1 + var/obj/item/stack/sheet/S = new sheet_path(loc) + var/amount = min(sheets, S.max_amount) + S.amount = amount + sheets -= amount + +/obj/machinery/power/port_gen/pacman/UseFuel() + var/needed_sheets = 1 / (time_per_sheet / power_output) + var/temp = min(needed_sheets, sheet_left) + needed_sheets -= temp + sheet_left -= temp + sheets -= round(needed_sheets) + needed_sheets -= round(needed_sheets) + if (sheet_left <= 0 && sheets > 0) + sheet_left = 1 - needed_sheets + sheets-- + + var/lower_limit = 56 + power_output * 10 + var/upper_limit = 76 + power_output * 10 + var/bias = 0 + if (power_output > 4) + upper_limit = 400 + bias = power_output * 3 + if (heat < lower_limit) + heat += 3 + else + heat += rand(-7 + bias, 7 + bias) + if (heat < lower_limit) + heat = lower_limit + if (heat > upper_limit) + heat = upper_limit + + if (heat > 300) + overheat() + qdel(src) + return + +/obj/machinery/power/port_gen/pacman/handleInactive() + + if (heat > 0) + heat = max(heat - 2, 0) + src.updateDialog() + +/obj/machinery/power/port_gen/pacman/proc/overheat() + explosion(src.loc, 2, 5, 2, -1) + +/obj/machinery/power/port_gen/pacman/emag(mob/user) + emagged = 1 + emp_act(1) + return 1 + +/obj/machinery/power/port_gen/pacman/crowbarDestroy(mob/user) //don't like the copy/paste, but the proc has special handling in the middle so we need it + if(..()) + while ( sheets > 0 ) + var/obj/item/stack/sheet/G = new sheet_path(src.loc) + if ( sheets > 50 ) + G.amount = 50 + else + G.amount = sheets + sheets -= G.amount + return 1 + return -1 + +/obj/machinery/power/port_gen/pacman/wrenchAnchor(mob/user) + if(..() == 1) + if(anchored) + connect_to_network() + else + disconnect_from_network() + return 1 + return -1 + +/obj/machinery/power/port_gen/pacman/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, sheet_path)) + var/obj/item/stack/addstack = O + var/amount = min((max_sheets - sheets), addstack.amount) + if(amount < 1) to_chat(user, "The [src.name] is full!") - return + return to_chat(user, "You add [amount] sheets to the [src.name].") - sheets += amount - addstack.use(amount) - updateUsrDialog() - return - else if(!active) - if( ..() ) - return 1 - -/obj/machinery/power/port_gen/pacman/attack_hand(mob/user as mob) - ..() - if (!anchored) - return - - interact(user) - -/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - interact(user) - -/obj/machinery/power/port_gen/pacman/attack_paw(mob/user as mob) - interact(user) - -/obj/machinery/power/port_gen/pacman/interact(mob/user) - if (get_dist(src, user) > 1 ) - if (!istype(user, /mob/living/silicon/ai)) - user.unset_machine() - user << browse(null, "window=port_gen") - return - - user.set_machine(src) - - var/dat = text("[name]
    ") - if (active) - dat += text("Generator: On
    ") - else - dat += text("Generator: Off
    ") - dat += text("[capitalize(sheet_name)]: [sheets] - Eject
    ") - var/stack_percent = round(sheet_left * 100, 1) - dat += text("Current stack: [stack_percent]%
    ") - dat += text("Power output: - [power_gen * power_output] +
    ") - dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]
    ") - dat += text("Heat: [heat]
    ") - dat += "
    Close" - user << browse("[dat]", "window=port_gen") - onclose(user, "port_gen") - -/obj/machinery/power/port_gen/pacman/Topic(href, href_list) - if(..()) - return - - src.add_fingerprint(usr) - if(href_list["action"]) - if(href_list["action"] == "enable") - if(!active && HasFuel() && !crit_fail) - active = 1 - icon_state = "portgen1" - src.updateUsrDialog() - if(href_list["action"] == "disable") - if (active) - active = 0 - icon_state = "portgen0" - src.updateUsrDialog() - if(href_list["action"] == "eject") - if(!active) - DropFuel() - src.updateUsrDialog() - if(href_list["action"] == "lower_power") - if (power_output > 1) - power_output-- - src.updateUsrDialog() - if (href_list["action"] == "higher_power") - if (power_output < 4 || emagged) - power_output++ - src.updateUsrDialog() - if (href_list["action"] == "close") - usr << browse(null, "window=port_gen") - usr.unset_machine() - -/obj/machinery/power/port_gen/pacman/super - name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator" - icon_state = "portgen1" - sheet_path = /obj/item/stack/sheet/mineral/uranium - power_gen = 15000 - time_per_sheet = 65 - board_path = "/obj/item/weapon/circuitboard/pacman/super" - overheat() - explosion(src.loc, 3, 3, 3, -1) - -/obj/machinery/power/port_gen/pacman/mrs - name = "M.R.S.P.A.C.M.A.N.-type Portable Generator" - icon_state = "portgen2" - sheet_path = /obj/item/stack/sheet/mineral/diamond - power_gen = 40000 - time_per_sheet = 80 - board_path = "/obj/item/weapon/circuitboard/pacman/mrs" - overheat() - explosion(src.loc, 4, 4, 4, -1) + sheets += amount + addstack.use(amount) + updateUsrDialog() + return + else if(!active) + if( ..() ) + return 1 + +/obj/machinery/power/port_gen/pacman/attack_hand(mob/user as mob) + ..() + if (!anchored) + return + + interact(user) + +/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + interact(user) + +/obj/machinery/power/port_gen/pacman/attack_paw(mob/user as mob) + interact(user) + +/obj/machinery/power/port_gen/pacman/interact(mob/user) + if (get_dist(src, user) > 1 ) + if (!istype(user, /mob/living/silicon/ai)) + user.unset_machine() + user << browse(null, "window=port_gen") + return + + user.set_machine(src) + + var/dat = text("[name]
    ") + if (active) + dat += text("Generator: On
    ") + else + dat += text("Generator: Off
    ") + dat += text("[capitalize(sheet_name)]: [sheets] - Eject
    ") + var/stack_percent = round(sheet_left * 100, 1) + dat += text("Current stack: [stack_percent]%
    ") + dat += text("Power output: - [power_gen * power_output] +
    ") + dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]
    ") + dat += text("Heat: [heat]
    ") + dat += "
    Close" + user << browse("[dat]", "window=port_gen") + onclose(user, "port_gen") + +/obj/machinery/power/port_gen/pacman/Topic(href, href_list) + if(..()) + return + + src.add_fingerprint(usr) + if(href_list["action"]) + if(href_list["action"] == "enable") + if(!active && HasFuel() && !crit_fail) + active = 1 + icon_state = "portgen1" + src.updateUsrDialog() + if(href_list["action"] == "disable") + if (active) + active = 0 + icon_state = "portgen0" + src.updateUsrDialog() + if(href_list["action"] == "eject") + if(!active) + DropFuel() + src.updateUsrDialog() + if(href_list["action"] == "lower_power") + if (power_output > 1) + power_output-- + src.updateUsrDialog() + if (href_list["action"] == "higher_power") + if (power_output < 4 || emagged) + power_output++ + src.updateUsrDialog() + if (href_list["action"] == "close") + usr << browse(null, "window=port_gen") + usr.unset_machine() + +/obj/machinery/power/port_gen/pacman/super + name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator" + icon_state = "portgen1" + sheet_path = /obj/item/stack/sheet/mineral/uranium + power_gen = 15000 + time_per_sheet = 65 + board_path = "/obj/item/weapon/circuitboard/pacman/super" + overheat() + explosion(src.loc, 3, 3, 3, -1) + +/obj/machinery/power/port_gen/pacman/mrs + name = "M.R.S.P.A.C.M.A.N.-type Portable Generator" + icon_state = "portgen2" + sheet_path = /obj/item/stack/sheet/mineral/diamond + power_gen = 40000 + time_per_sheet = 80 + board_path = "/obj/item/weapon/circuitboard/pacman/mrs" + overheat() + explosion(src.loc, 4, 4, 4, -1) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index a2536d7f820..f44387d004f 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -1,239 +1,239 @@ -////////////////////////////// -// POWER MACHINERY BASE CLASS -////////////////////////////// - -///////////////////////////// -// Definitions -///////////////////////////// - -/obj/machinery/power - name = null - icon = 'icons/obj/power.dmi' - anchored = 1.0 - var/datum/powernet/powernet = null - use_power = 0 - idle_power_usage = 0 - active_power_usage = 0 - - //For powernet rebuilding - var/build_status = 0 //1 means it needs rebuilding during the next tick or on usage - - var/obj/machinery/power/terminal/terminal = null //not strictly used on all machines - a placeholder - var/starting_terminal = 0 - -/obj/machinery/power/New() - . = ..() - machines -= src - power_machines |= src - return . - -/obj/machinery/power/initialize() - ..() - if(starting_terminal) - for(var/d in cardinal) - var/turf/T = get_step(src, d) - for(var/obj/machinery/power/terminal/term in T) - if(term && term.dir == turn(d, 180)) - terminal = term - break - if(terminal) - break - if(terminal) - terminal.master = src - update_icon() - -/obj/machinery/power/Destroy() - disconnect_from_network() - power_machines -= src - - if (terminal) - terminal.master = null - terminal = null - - ..() - -/////////////////////////////// -// General procedures -////////////////////////////// - -// common helper procs for all power machines -/obj/machinery/power/proc/add_avail(var/amount) - if(get_powernet()) - powernet.newavail += amount - -/obj/machinery/power/proc/add_load(var/amount) - if(get_powernet()) - powernet.load += amount - -/obj/machinery/power/proc/surplus() - if(get_powernet()) - return powernet.avail-powernet.load - else - return 0 - -/obj/machinery/power/proc/avail() - if(get_powernet()) - return powernet.avail - else - return 0 - -/obj/machinery/power/proc/load() - if(get_powernet()) - return powernet.load - else - return 0 - -/obj/machinery/power/proc/get_powernet() - check_rebuild() - return powernet - -/obj/machinery/power/check_rebuild() - if(!build_status) - return 0 - for(var/obj/structure/cable/C in src.loc) - if(C.check_rebuild()) - return 1 - -/obj/machinery/power/proc/getPowernetNodes() - if(!get_powernet()) - return list() - return powernet.nodes - -/obj/machinery/power/proc/disconnect_terminal() // machines without a terminal will just return, no harm no fowl. - return - -// returns true if the area has power on given channel (or doesn't require power) -// defaults to power_channel -/obj/machinery/proc/powered(chan = power_channel) - if(!src.loc) - return 0 - - if(!use_power) - return 1 - - if(isnull(src.areaMaster) || !src.areaMaster) - return 0 // if not, then not powered. - - if((machine_flags & FIXED2WORK) && !anchored) - return 0 - - return areaMaster.powered(chan) // return power status of the area. - -// increment the power usage stats for an area -// defaults to power_channel -/obj/machinery/proc/use_power(amount, chan = power_channel) - if(isnull(src.areaMaster) || !src.areaMaster) - return 0 // if not, then not powered. - - if(!powered(chan)) //no point in trying if we don't have power - return 0 - - src.areaMaster.use_power(amount, chan) - -// called whenever the power settings of the containing area change -// by default, check equipment channel & set flag -// can override if needed -/obj/machinery/proc/power_change() - if(powered(power_channel)) - stat &= ~NOPOWER - - if(!use_auto_lights) - return - set_light(light_range_on, light_power_on) - - else - stat |= NOPOWER - - if(!use_auto_lights) - return - set_light(0) - - -// connect the machine to a powernet if a node cable is present on the turf -/obj/machinery/power/proc/connect_to_network() - var/turf/T = get_turf(src) - - var/obj/structure/cable/C = T.get_cable_node() // check if we have a node cable on the machine turf, the first found is picked - - if(!C || !C.get_powernet()) - return 0 - - C.powernet.add_machine(src) - return 1 - -// remove and disconnect the machine from its current powernet -/obj/machinery/power/proc/disconnect_from_network() - if(!get_powernet()) - build_status = 0 - return 0 - - powernet.remove_machine(src) - return 1 - -/////////////////////////////////////////// -// Powernet handling helpers -////////////////////////////////////////// - -// returns all the cables WITHOUT a powernet in neighbors turfs, -// pointing towards the turf the machine is located at -/obj/machinery/power/proc/get_connections() - . = list() - - var/cdir - var/turf/T - - for(var/card in cardinal) - T = get_step(loc, card) - cdir = get_dir(T, loc) - - for(var/obj/structure/cable/C in T) - if(C.get_powernet()) - continue - - if(C.d1 == cdir || C.d2 == cdir) - . += C - -// returns all the cables in neighbors turfs, -// pointing towards the turf the machine is located at -/obj/machinery/power/proc/get_marked_connections() - . = list() - - var/cdir - var/turf/T - - for(var/card in cardinal) - T = get_step(loc, card) - cdir = get_dir(T, loc) - - for(var/obj/structure/cable/C in T) - if(C.d1 == cdir || C.d2 == cdir) - . += C - -// returns all the NODES (O-X) cables WITHOUT a powernet in the turf the machine is located at -/obj/machinery/power/proc/get_indirect_connections() - . = list() - - for(var/obj/structure/cable/C in loc) - if(C.get_powernet()) - continue - - if(C.d1 == 0) // the cable is a node cable - . += C - -//////////////////////////////////////////////// -// Misc. -/////////////////////////////////////////////// - -// return a knot cable (O-X) if one is present in the turf -// null if there's none -/turf/proc/get_cable_node() - for(var/obj/structure/cable/C in src) - if(C.d1 == 0) - return C - -/obj/machinery/proc/addStaticPower(value, powerchannel) - if(!areaMaster) - return - areaMaster.addStaticPower(value, powerchannel) -/obj/machinery/proc/removeStaticPower(value, powerchannel) - addStaticPower(-value, powerchannel) +////////////////////////////// +// POWER MACHINERY BASE CLASS +////////////////////////////// + +///////////////////////////// +// Definitions +///////////////////////////// + +/obj/machinery/power + name = null + icon = 'icons/obj/power.dmi' + anchored = 1.0 + var/datum/powernet/powernet = null + use_power = 0 + idle_power_usage = 0 + active_power_usage = 0 + + //For powernet rebuilding + var/build_status = 0 //1 means it needs rebuilding during the next tick or on usage + + var/obj/machinery/power/terminal/terminal = null //not strictly used on all machines - a placeholder + var/starting_terminal = 0 + +/obj/machinery/power/New() + . = ..() + machines -= src + power_machines |= src + return . + +/obj/machinery/power/initialize() + ..() + if(starting_terminal) + for(var/d in cardinal) + var/turf/T = get_step(src, d) + for(var/obj/machinery/power/terminal/term in T) + if(term && term.dir == turn(d, 180)) + terminal = term + break + if(terminal) + break + if(terminal) + terminal.master = src + update_icon() + +/obj/machinery/power/Destroy() + disconnect_from_network() + power_machines -= src + + if (terminal) + terminal.master = null + terminal = null + + ..() + +/////////////////////////////// +// General procedures +////////////////////////////// + +// common helper procs for all power machines +/obj/machinery/power/proc/add_avail(var/amount) + if(get_powernet()) + powernet.newavail += amount + +/obj/machinery/power/proc/add_load(var/amount) + if(get_powernet()) + powernet.load += amount + +/obj/machinery/power/proc/surplus() + if(get_powernet()) + return powernet.avail-powernet.load + else + return 0 + +/obj/machinery/power/proc/avail() + if(get_powernet()) + return powernet.avail + else + return 0 + +/obj/machinery/power/proc/load() + if(get_powernet()) + return powernet.load + else + return 0 + +/obj/machinery/power/proc/get_powernet() + check_rebuild() + return powernet + +/obj/machinery/power/check_rebuild() + if(!build_status) + return 0 + for(var/obj/structure/cable/C in src.loc) + if(C.check_rebuild()) + return 1 + +/obj/machinery/power/proc/getPowernetNodes() + if(!get_powernet()) + return list() + return powernet.nodes + +/obj/machinery/power/proc/disconnect_terminal() // machines without a terminal will just return, no harm no fowl. + return + +// returns true if the area has power on given channel (or doesn't require power) +// defaults to power_channel +/obj/machinery/proc/powered(chan = power_channel) + if(!src.loc) + return 0 + + if(!use_power) + return 1 + + if(isnull(src.areaMaster) || !src.areaMaster) + return 0 // if not, then not powered. + + if((machine_flags & FIXED2WORK) && !anchored) + return 0 + + return areaMaster.powered(chan) // return power status of the area. + +// increment the power usage stats for an area +// defaults to power_channel +/obj/machinery/proc/use_power(amount, chan = power_channel) + if(isnull(src.areaMaster) || !src.areaMaster) + return 0 // if not, then not powered. + + if(!powered(chan)) //no point in trying if we don't have power + return 0 + + src.areaMaster.use_power(amount, chan) + +// called whenever the power settings of the containing area change +// by default, check equipment channel & set flag +// can override if needed +/obj/machinery/proc/power_change() + if(powered(power_channel)) + stat &= ~NOPOWER + + if(!use_auto_lights) + return + set_light(light_range_on, light_power_on) + + else + stat |= NOPOWER + + if(!use_auto_lights) + return + set_light(0) + + +// connect the machine to a powernet if a node cable is present on the turf +/obj/machinery/power/proc/connect_to_network() + var/turf/T = get_turf(src) + + var/obj/structure/cable/C = T.get_cable_node() // check if we have a node cable on the machine turf, the first found is picked + + if(!C || !C.get_powernet()) + return 0 + + C.powernet.add_machine(src) + return 1 + +// remove and disconnect the machine from its current powernet +/obj/machinery/power/proc/disconnect_from_network() + if(!get_powernet()) + build_status = 0 + return 0 + + powernet.remove_machine(src) + return 1 + +/////////////////////////////////////////// +// Powernet handling helpers +////////////////////////////////////////// + +// returns all the cables WITHOUT a powernet in neighbors turfs, +// pointing towards the turf the machine is located at +/obj/machinery/power/proc/get_connections() + . = list() + + var/cdir + var/turf/T + + for(var/card in cardinal) + T = get_step(loc, card) + cdir = get_dir(T, loc) + + for(var/obj/structure/cable/C in T) + if(C.get_powernet()) + continue + + if(C.d1 == cdir || C.d2 == cdir) + . += C + +// returns all the cables in neighbors turfs, +// pointing towards the turf the machine is located at +/obj/machinery/power/proc/get_marked_connections() + . = list() + + var/cdir + var/turf/T + + for(var/card in cardinal) + T = get_step(loc, card) + cdir = get_dir(T, loc) + + for(var/obj/structure/cable/C in T) + if(C.d1 == cdir || C.d2 == cdir) + . += C + +// returns all the NODES (O-X) cables WITHOUT a powernet in the turf the machine is located at +/obj/machinery/power/proc/get_indirect_connections() + . = list() + + for(var/obj/structure/cable/C in loc) + if(C.get_powernet()) + continue + + if(C.d1 == 0) // the cable is a node cable + . += C + +//////////////////////////////////////////////// +// Misc. +/////////////////////////////////////////////// + +// return a knot cable (O-X) if one is present in the turf +// null if there's none +/turf/proc/get_cable_node() + for(var/obj/structure/cable/C in src) + if(C.d1 == 0) + return C + +/obj/machinery/proc/addStaticPower(value, powerchannel) + if(!areaMaster) + return + areaMaster.addStaticPower(value, powerchannel) +/obj/machinery/proc/removeStaticPower(value, powerchannel) + addStaticPower(-value, powerchannel) diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index 281fbe9dc4d..bab047cdecc 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -1,156 +1,156 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 -var/global/list/rad_collectors = list() - -/obj/machinery/power/rad_collector - name = "Radiation Collector Array" - desc = "A device which uses Hawking Radiation and plasma to produce power." - icon = 'icons/obj/singularity.dmi' - icon_state = "ca" - anchored = 0 - density = 1 - req_access = list(access_engine_equip) - var/obj/item/weapon/tank/plasma/P = null - var/last_power = 0 - var/active = 0 - var/locked = 0 - var/drain_ratio = 3.5 //3.5 times faster than original. - ghost_read = 0 - ghost_write = 0 - - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/power/rad_collector/New() - ..() - rad_collectors += src - -/obj/machinery/power/rad_collector/Destroy() - rad_collectors -= src - eject() - ..() - -/obj/machinery/power/rad_collector/process() - if (P) - if (P.air_contents.toxins <= 0) - investigation_log(I_SINGULO,"out of fuel.") - P.air_contents.toxins = 0 - eject() - else if(!active) - return - else - P.air_contents.toxins -= (0.001 * drain_ratio) - P.air_contents.update_values() - -/obj/machinery/power/rad_collector/attack_hand(mob/user as mob) - if(anchored) - if(!src.locked) - toggle_power() - user.visible_message("[user] turns the [src] [active? "on":"off"].", \ - "You turn the [src] [active? "on":"off"].") - investigation_log(I_SINGULO,"turned [active?"on":"off"] by [user.key]. [P?"Fuel: [round(P.air_contents.toxins/0.29)]%":"It is empty"].") - return - else +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 +var/global/list/rad_collectors = list() + +/obj/machinery/power/rad_collector + name = "Radiation Collector Array" + desc = "A device which uses Hawking Radiation and plasma to produce power." + icon = 'icons/obj/singularity.dmi' + icon_state = "ca" + anchored = 0 + density = 1 + req_access = list(access_engine_equip) + var/obj/item/weapon/tank/plasma/P = null + var/last_power = 0 + var/active = 0 + var/locked = 0 + var/drain_ratio = 3.5 //3.5 times faster than original. + ghost_read = 0 + ghost_write = 0 + + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/power/rad_collector/New() + ..() + rad_collectors += src + +/obj/machinery/power/rad_collector/Destroy() + rad_collectors -= src + eject() + ..() + +/obj/machinery/power/rad_collector/process() + if (P) + if (P.air_contents.toxins <= 0) + investigation_log(I_SINGULO,"out of fuel.") + P.air_contents.toxins = 0 + eject() + else if(!active) + return + else + P.air_contents.toxins -= (0.001 * drain_ratio) + P.air_contents.update_values() + +/obj/machinery/power/rad_collector/attack_hand(mob/user as mob) + if(anchored) + if(!src.locked) + toggle_power() + user.visible_message("[user] turns the [src] [active? "on":"off"].", \ + "You turn the [src] [active? "on":"off"].") + investigation_log(I_SINGULO,"turned [active?"on":"off"] by [user.key]. [P?"Fuel: [round(P.air_contents.toxins/0.29)]%":"It is empty"].") + return + else to_chat(user, "The controls are locked!") - return -..() - -/obj/machinery/power/rad_collector/attackby(obj/item/W, mob/user) - if(..()) - return 1 - else if(istype(W, /obj/item/device/analyzer) || istype(W, /obj/item/device/multitool)) - if(active) + return +..() + +/obj/machinery/power/rad_collector/attackby(obj/item/W, mob/user) + if(..()) + return 1 + else if(istype(W, /obj/item/device/analyzer) || istype(W, /obj/item/device/multitool)) + if(active) to_chat(user, "\The [W] registers that [format_watts(last_power)] is being produced every cycle.") - else + else to_chat(user, "\The [W] registers that the unit is currently not producing power.") - return 1 - else if(istype(W, /obj/item/weapon/tank/plasma)) - if(!src.anchored) + return 1 + else if(istype(W, /obj/item/weapon/tank/plasma)) + if(!src.anchored) to_chat(user, "\The [src] needs to be secured to the floor first.") - return 1 - if(src.P) + return 1 + if(src.P) to_chat(user, "A plasma tank is already loaded.") - return 1 - if(user.drop_item(W, src)) - src.P = W - update_icons() - else if(istype(W, /obj/item/weapon/crowbar)) - if(P && !src.locked) - eject() - return 1 - else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user)) - if(active) - src.locked = !src.locked + return 1 + if(user.drop_item(W, src)) + src.P = W + update_icons() + else if(istype(W, /obj/item/weapon/crowbar)) + if(P && !src.locked) + eject() + return 1 + else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (src.allowed(user)) + if(active) + src.locked = !src.locked to_chat(user, "The controls are now [src.locked ? "locked." : "unlocked."]") - else - src.locked = 0 //just in case it somehow gets locked + else + src.locked = 0 //just in case it somehow gets locked to_chat(user, "The controls can only be locked when \the [src] is active") - else + else to_chat(user, "Access denied!") - return 1 - else - return - -/obj/machinery/power/rad_collector/wrenchAnchor(mob/user) - if(P) + return 1 + else + return + +/obj/machinery/power/rad_collector/wrenchAnchor(mob/user) + if(P) to_chat(user, "Remove the plasma tank first.") - return - if(..() == 1) - if(anchored) - connect_to_network() - else - disconnect_from_network() - last_power = 0 - return 1 - return -1 - -/obj/machinery/power/rad_collector/ex_act(severity) - switch(severity) - if(2, 3) - eject() - - return ..() - -/obj/machinery/power/rad_collector/proc/eject() - locked = 0 - last_power = 0 - - if(isnull(P)) - return - - P.loc = get_turf(src) - P.layer = initial(P.layer) - P = null - - if(active) - toggle_power() - else - update_icons() - -/obj/machinery/power/rad_collector/proc/receive_pulse(const/pulse_strength) - if (P && active) - var/power_produced = P.air_contents.toxins * pulse_strength * 3.5 // original was 20, nerfed to 2 now 3.5 should get you about 500kw - add_avail(power_produced) - last_power = power_produced - -/obj/machinery/power/rad_collector/proc/update_icons() - overlays.len = 0 - if(P) - overlays += image('icons/obj/singularity.dmi', "ptank") - if(stat & (NOPOWER|BROKEN)) - return - if(active) - overlays += image('icons/obj/singularity.dmi', "on") - -/obj/machinery/power/rad_collector/proc/toggle_power() - active = !active - - if(active) - icon_state = "ca_on" - flick("ca_active", src) - else - icon_state = "ca" - flick("ca_deactive", src) - last_power = 0 - - update_icons() - + return + if(..() == 1) + if(anchored) + connect_to_network() + else + disconnect_from_network() + last_power = 0 + return 1 + return -1 + +/obj/machinery/power/rad_collector/ex_act(severity) + switch(severity) + if(2, 3) + eject() + + return ..() + +/obj/machinery/power/rad_collector/proc/eject() + locked = 0 + last_power = 0 + + if(isnull(P)) + return + + P.loc = get_turf(src) + P.layer = initial(P.layer) + P = null + + if(active) + toggle_power() + else + update_icons() + +/obj/machinery/power/rad_collector/proc/receive_pulse(const/pulse_strength) + if (P && active) + var/power_produced = P.air_contents.toxins * pulse_strength * 3.5 // original was 20, nerfed to 2 now 3.5 should get you about 500kw + add_avail(power_produced) + last_power = power_produced + +/obj/machinery/power/rad_collector/proc/update_icons() + overlays.len = 0 + if(P) + overlays += image('icons/obj/singularity.dmi', "ptank") + if(stat & (NOPOWER|BROKEN)) + return + if(active) + overlays += image('icons/obj/singularity.dmi', "on") + +/obj/machinery/power/rad_collector/proc/toggle_power() + active = !active + + if(active) + icon_state = "ca_on" + flick("ca_active", src) + else + icon_state = "ca" + flick("ca_deactive", src) + last_power = 0 + + update_icons() + diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index 2491651bf74..7ab6749b0a7 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -1,78 +1,78 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/obj/machinery/containment_field - name = "Containment Field" - desc = "An energy field." - icon = 'icons/obj/singularity.dmi' - icon_state = "Contain_F" - anchored = 1 - density = 0 - unacidable = 1 - use_power = 0 - luminosity = 4 - - flags = FPRINT | PROXMOVE - - var/obj/machinery/field_generator/FG1 = null - var/obj/machinery/field_generator/FG2 = null - var/hasShocked = 0 //Used to add a delay between shocks. In some cases this used to crash servers by spawning hundreds of sparks every second. - -/obj/machinery/containment_field/Destroy() - if(FG1 && !FG1.clean_up) - FG1.cleanup() - if(FG2 && !FG2.clean_up) - FG2.cleanup() - ..() - -/obj/machinery/containment_field/attack_hand(mob/user as mob) - if(get_dist(src, user) > 1) - return 0 - else - shock(user) - return 1 - - -/obj/machinery/containment_field/blob_act() - return 0 - - -/obj/machinery/containment_field/ex_act(severity) - return 0 - -/obj/machinery/containment_field/HasProximity(atom/movable/AM as mob|obj) - if(istype(AM,/mob/living/silicon) && prob(40)) - shock(AM) - return 1 - if(istype(AM,/mob/living/carbon) && prob(50)) - shock(AM) - return 1 - return 0 - - - -/obj/machinery/containment_field/shock(const/mob/living/user) - if(hasShocked) - return 0 - - if(isnull(FG1) || isnull(FG2)) - qdel(src) - return 0 - - if(isliving(user)) - hasShocked = 1 - var/shock_damage = min(rand(30, 40), rand(30, 40)) - user.electrocute_act(shock_damage, src) - - if(iscarbon(user)) - var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src))) - user.throw_at(target, 200, 4) - - sleep(20) - hasShocked = 0 - -/obj/machinery/containment_field/proc/set_master(var/master1,var/master2) - if(!master1 || !master2) - return 0 - FG1 = master1 - FG2 = master2 - return 1 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/obj/machinery/containment_field + name = "Containment Field" + desc = "An energy field." + icon = 'icons/obj/singularity.dmi' + icon_state = "Contain_F" + anchored = 1 + density = 0 + unacidable = 1 + use_power = 0 + luminosity = 4 + + flags = FPRINT | PROXMOVE + + var/obj/machinery/field_generator/FG1 = null + var/obj/machinery/field_generator/FG2 = null + var/hasShocked = 0 //Used to add a delay between shocks. In some cases this used to crash servers by spawning hundreds of sparks every second. + +/obj/machinery/containment_field/Destroy() + if(FG1 && !FG1.clean_up) + FG1.cleanup() + if(FG2 && !FG2.clean_up) + FG2.cleanup() + ..() + +/obj/machinery/containment_field/attack_hand(mob/user as mob) + if(get_dist(src, user) > 1) + return 0 + else + shock(user) + return 1 + + +/obj/machinery/containment_field/blob_act() + return 0 + + +/obj/machinery/containment_field/ex_act(severity) + return 0 + +/obj/machinery/containment_field/HasProximity(atom/movable/AM as mob|obj) + if(istype(AM,/mob/living/silicon) && prob(40)) + shock(AM) + return 1 + if(istype(AM,/mob/living/carbon) && prob(50)) + shock(AM) + return 1 + return 0 + + + +/obj/machinery/containment_field/shock(const/mob/living/user) + if(hasShocked) + return 0 + + if(isnull(FG1) || isnull(FG2)) + qdel(src) + return 0 + + if(isliving(user)) + hasShocked = 1 + var/shock_damage = min(rand(30, 40), rand(30, 40)) + user.electrocute_act(shock_damage, src) + + if(iscarbon(user)) + var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src))) + user.throw_at(target, 200, 4) + + sleep(20) + hasShocked = 0 + +/obj/machinery/containment_field/proc/set_master(var/master1,var/master2) + if(!master1 || !master2) + return 0 + FG1 = master1 + FG2 = master2 + return 1 diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index cab43c556a5..4267afc34f4 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -1,344 +1,344 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/obj/machinery/power/emitter - name = "emitter" - desc = "A heavy duty industrial laser" - icon = 'icons/obj/singularity.dmi' - icon_state = "emitter" - anchored = 0 - density = 1 - req_access = list(access_engine_equip) - - use_power = 0 - idle_power_usage = 10 - active_power_usage = 300 - - var/active = 0 - var/powered = 0 - var/fire_delay = 100 - var/last_shot = 0 - var/shot_number = 0 - var/locked = 0 - - machine_flags = EMAGGABLE | WRENCHMOVE | FIXED2WORK | WELD_FIXED | MULTITOOL_MENU - - var/frequency = 0 - var/id_tag = null - var/datum/radio_frequency/radio_connection - - //Now uses a constant beam. - var/obj/effect/beam/emitter/beam = null - - //Radio remote control -/obj/machinery/power/emitter/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) - - -/obj/machinery/power/emitter/verb/rotate_cw() - set name = "Rotate (Clockwise)" - set category = "Object" - set src in oview(1) - - if(src.anchored || usr:stat) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/obj/machinery/power/emitter + name = "emitter" + desc = "A heavy duty industrial laser" + icon = 'icons/obj/singularity.dmi' + icon_state = "emitter" + anchored = 0 + density = 1 + req_access = list(access_engine_equip) + + use_power = 0 + idle_power_usage = 10 + active_power_usage = 300 + + var/active = 0 + var/powered = 0 + var/fire_delay = 100 + var/last_shot = 0 + var/shot_number = 0 + var/locked = 0 + + machine_flags = EMAGGABLE | WRENCHMOVE | FIXED2WORK | WELD_FIXED | MULTITOOL_MENU + + var/frequency = 0 + var/id_tag = null + var/datum/radio_frequency/radio_connection + + //Now uses a constant beam. + var/obj/effect/beam/emitter/beam = null + + //Radio remote control +/obj/machinery/power/emitter/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) + + +/obj/machinery/power/emitter/verb/rotate_cw() + set name = "Rotate (Clockwise)" + set category = "Object" + set src in oview(1) + + if(src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, -90) - return 1 - -/obj/machinery/power/emitter/verb/rotate_ccw() - set name = "Rotate (Counter-Clockwise)" - set category = "Object" - set src in oview(1) - - if(src.anchored || usr:stat) + return 0 + src.dir = turn(src.dir, -90) + return 1 + +/obj/machinery/power/emitter/verb/rotate_ccw() + set name = "Rotate (Counter-Clockwise)" + set category = "Object" + set src in oview(1) + + if(src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 90) - return 1 - -/obj/machinery/power/emitter/initialize() - - ..() - if(state == 2 && anchored) - connect_to_network() - update_icon() - update_beam() - - if(frequency) - set_frequency(frequency) - -/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - - return {" - - "} - -/obj/machinery/power/emitter/proc/update_beam() - - - if(active && powered) - if(!beam) - beam = new (loc) - beam.dir = dir - beam.emit(spawn_by=src) - else - if(beam) - beam._re_emit = 0 - qdel(beam) - beam = null - -/obj/machinery/power/emitter/receive_signal(datum/signal/signal) - - if(!signal.data["tag"] || (signal.data["tag"] != id_tag)) - return 0 - - var/on + return 0 + src.dir = turn(src.dir, 90) + return 1 + +/obj/machinery/power/emitter/initialize() + + ..() + if(state == 2 && anchored) + connect_to_network() + update_icon() + update_beam() + + if(frequency) + set_frequency(frequency) + +/obj/machinery/power/emitter/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + + return {" + + "} + +/obj/machinery/power/emitter/proc/update_beam() + + + if(active && powered) + if(!beam) + beam = new (loc) + beam.dir = dir + beam.emit(spawn_by=src) + else + if(beam) + beam._re_emit = 0 + qdel(beam) + beam = null + +/obj/machinery/power/emitter/receive_signal(datum/signal/signal) + + if(!signal.data["tag"] || (signal.data["tag"] != id_tag)) + return 0 + + var/on // to_chat(world, "\ref[src] received signal. tag [signal.data["tag"]], cmd [signal.data["command"]], state [signal.data["state"]], sigtype [signal.data["sigtype"]]") - if(signal.data["command"]) - switch(signal.data["command"]) - if("on") - on = 1 - - if("off") - on = 0 - - if("set") - on = signal.data["state"] > 0 - - if("toggle") - on = !active - - if(!isnull(on) && anchored && state == 2 && on != active) - active = on - var/statestr = on ? "on":"off" - // Spammy message_admins("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in [formatJumpTo(src)]",0,1) - log_game("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in ([x],[y],[z])") - investigation_log(I_SINGULO,"turned [statestr] by radio signal ([signal.data["command"]] @ [frequency])") - update_icon() - update_beam() - -/obj/machinery/power/emitter/Destroy() - - qdel(beam) - message_admins("Emitter deleted at ([x],[y],[z] - JMP)",0,1) - log_game("Emitter deleted at ([x],[y],[z])") - investigation_log(I_SINGULO,"deleted at ([x],[y],[z])") - ..() - -/obj/machinery/power/emitter/update_icon() - - if(powered && get_powernet() && avail(active_power_usage) && active) - icon_state = "emitter_+a" - else - icon_state = "emitter" - -/obj/machinery/power/emitter/attack_hand(mob/user as mob) - - //Require consciousness - if(user.stat && !isAdminGhost(user)) - return - - src.add_fingerprint(user) - if(state == 2) - if(!get_powernet()) + if(signal.data["command"]) + switch(signal.data["command"]) + if("on") + on = 1 + + if("off") + on = 0 + + if("set") + on = signal.data["state"] > 0 + + if("toggle") + on = !active + + if(!isnull(on) && anchored && state == 2 && on != active) + active = on + var/statestr = on ? "on":"off" + // Spammy message_admins("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in [formatJumpTo(src)]",0,1) + log_game("Emitter turned [statestr] by radio signal ([signal.data["command"]] @ [frequency]) in ([x],[y],[z])") + investigation_log(I_SINGULO,"turned [statestr] by radio signal ([signal.data["command"]] @ [frequency])") + update_icon() + update_beam() + +/obj/machinery/power/emitter/Destroy() + + qdel(beam) + message_admins("Emitter deleted at ([x],[y],[z] - JMP)",0,1) + log_game("Emitter deleted at ([x],[y],[z])") + investigation_log(I_SINGULO,"deleted at ([x],[y],[z])") + ..() + +/obj/machinery/power/emitter/update_icon() + + if(powered && get_powernet() && avail(active_power_usage) && active) + icon_state = "emitter_+a" + else + icon_state = "emitter" + +/obj/machinery/power/emitter/attack_hand(mob/user as mob) + + //Require consciousness + if(user.stat && !isAdminGhost(user)) + return + + src.add_fingerprint(user) + if(state == 2) + if(!get_powernet()) to_chat(user, "\The [src] isn't connected to a wire.") - return 1 - if(!src.locked) - if(active) - turn_off() - user.visible_message("[user] turns \the [src] off.", \ - "You turn \the [src] off.") - message_admins("Emitter turned off by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("Emitter turned off by [user.ckey]([user]) in ([x],[y],[z])") - investigation_log(I_SINGULO,"turned off by [user.key]") - else - turn_on() - user.visible_message("[user] turns \the [src] on.", \ - "You turn \the [src] on.") - message_admins("Emitter turned on by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("Emitter turned on by [user.ckey]([user]) in ([x],[y],[z])") - investigation_log(I_SINGULO,"turned on by [user.key]") - else + return 1 + if(!src.locked) + if(active) + turn_off() + user.visible_message("[user] turns \the [src] off.", \ + "You turn \the [src] off.") + message_admins("Emitter turned off by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1) + log_game("Emitter turned off by [user.ckey]([user]) in ([x],[y],[z])") + investigation_log(I_SINGULO,"turned off by [user.key]") + else + turn_on() + user.visible_message("[user] turns \the [src] on.", \ + "You turn \the [src] on.") + message_admins("Emitter turned on by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1) + log_game("Emitter turned on by [user.ckey]([user]) in ([x],[y],[z])") + investigation_log(I_SINGULO,"turned on by [user.key]") + else to_chat(user, "\The [src]'s controls are locked!") - else + else to_chat(user, "\The [src] needs to be firmly secured to the floor first.") - return 1 - -//Important note, those procs not log the emitter being turned on or off, so please use the logs in attack_hand above -/obj/machinery/power/emitter/proc/turn_on() - active = 1 - shot_number = 0 - fire_delay = 100 - update_icon() - update_beam() - -/obj/machinery/power/emitter/proc/turn_off() - active = 0 - update_icon() - update_beam() - -/obj/machinery/power/emitter/emp_act(var/severity) //Emitters are EMP-proof for obvious reasons - - return 1 - -/obj/machinery/power/emitter/process() - - if(!anchored) //If it got unanchored "inexplicably"... fucking badmins - active = 0 - update_icon() - update_beam() - return - - if(stat & BROKEN) - return - - if(state != 2 || (!powernet && active_power_usage)) //Not welded to the floor, or no more wire underneath and requires power - active = 0 - update_icon() - update_beam() - return - - if(((last_shot + fire_delay) <= world.time) && (active == 1)) //It's currently activated and it hasn't processed in a bit - if(!active_power_usage || avail(active_power_usage)) //Doesn't require power or powernet has enough supply - add_load(active_power_usage) //Drain it then bitch - if(!powered) //Yay its powered - powered = 1 - update_icon() - update_beam() - investigation_log(I_SINGULO,"regained power and turned on") - else - if(powered) //Fuck its not anymore - powered = 0 //Whelp time to kill it then - update_beam() //Update its beam and icon - update_icon() - investigation_log(I_SINGULO,"lost power and turned off") - return - - last_shot = world.time - - if(shot_number < 3) - fire_delay = 2 - shot_number++ - else - fire_delay = rand(20, 100) - shot_number = 0 - - //beam = getFromPool(/obj/item/projectile/beam/emitter, loc) - //beam.dir = dir - //playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) - - if(prob(35)) - var/datum/effect/effect/system/spark_spread/Sparks = new - Sparks.set_up(5, 1, src) - Sparks.start() - - //A.dumbfire() - -/obj/machinery/power/emitter/emag(mob/user) - - if(!emagged) - locked = 0 - emagged = 1 - user.visible_message("[user] shorts out \the [src]'s lock.", "You short out \the [src]'s lock.") - return - -/obj/machinery/power/emitter/wrenchAnchor(mob/user) - - if(active) + return 1 + +//Important note, those procs not log the emitter being turned on or off, so please use the logs in attack_hand above +/obj/machinery/power/emitter/proc/turn_on() + active = 1 + shot_number = 0 + fire_delay = 100 + update_icon() + update_beam() + +/obj/machinery/power/emitter/proc/turn_off() + active = 0 + update_icon() + update_beam() + +/obj/machinery/power/emitter/emp_act(var/severity) //Emitters are EMP-proof for obvious reasons + + return 1 + +/obj/machinery/power/emitter/process() + + if(!anchored) //If it got unanchored "inexplicably"... fucking badmins + active = 0 + update_icon() + update_beam() + return + + if(stat & BROKEN) + return + + if(state != 2 || (!powernet && active_power_usage)) //Not welded to the floor, or no more wire underneath and requires power + active = 0 + update_icon() + update_beam() + return + + if(((last_shot + fire_delay) <= world.time) && (active == 1)) //It's currently activated and it hasn't processed in a bit + if(!active_power_usage || avail(active_power_usage)) //Doesn't require power or powernet has enough supply + add_load(active_power_usage) //Drain it then bitch + if(!powered) //Yay its powered + powered = 1 + update_icon() + update_beam() + investigation_log(I_SINGULO,"regained power and turned on") + else + if(powered) //Fuck its not anymore + powered = 0 //Whelp time to kill it then + update_beam() //Update its beam and icon + update_icon() + investigation_log(I_SINGULO,"lost power and turned off") + return + + last_shot = world.time + + if(shot_number < 3) + fire_delay = 2 + shot_number++ + else + fire_delay = rand(20, 100) + shot_number = 0 + + //beam = getFromPool(/obj/item/projectile/beam/emitter, loc) + //beam.dir = dir + //playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) + + if(prob(35)) + var/datum/effect/effect/system/spark_spread/Sparks = new + Sparks.set_up(5, 1, src) + Sparks.start() + + //A.dumbfire() + +/obj/machinery/power/emitter/emag(mob/user) + + if(!emagged) + locked = 0 + emagged = 1 + user.visible_message("[user] shorts out \the [src]'s lock.", "You short out \the [src]'s lock.") + return + +/obj/machinery/power/emitter/wrenchAnchor(mob/user) + + if(active) to_chat(user, "Turn off \the [src] first.") - return - return ..() - -/obj/machinery/power/emitter/weldToFloor() - - if(..() == 1) - switch(state) - if(1) - disconnect_from_network() - if(2) - connect_to_network() - return 1 - return -1 - -/obj/machinery/power/emitter/attackby(obj/item/W, mob/user) - - . = ..() //Holy fucking shit - if(.) - return . - - if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) - if(emagged) + return + return ..() + +/obj/machinery/power/emitter/weldToFloor() + + if(..() == 1) + switch(state) + if(1) + disconnect_from_network() + if(2) + connect_to_network() + return 1 + return -1 + +/obj/machinery/power/emitter/attackby(obj/item/W, mob/user) + + . = ..() //Holy fucking shit + if(.) + return . + + if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) + if(emagged) to_chat(user, "The lock appears to be broken.") - return - if(src.allowed(user)) - if(active) - src.locked = !src.locked + return + if(src.allowed(user)) + if(active) + src.locked = !src.locked to_chat(user, "The controls are now [src.locked ? "locked" : "unlocked"].") - else - src.locked = 0 //just in case it somehow gets locked + else + src.locked = 0 //just in case it somehow gets locked to_chat(user, "The controls can only be locked when \the [src] is online") - else + else to_chat(user, "Access denied.") - return - -/obj/effect/beam/emitter - - name = "emitter beam" - icon = 'icons/effects/beam.dmi' - icon_state = "emitter_1" - anchored = 1.0 - flags = 0 - damage = 30 - damage_type = BURN - - var/base_state = "emitter" - var/power = 1 - - //Notify prisms of power change. - var/event/power_change = new - -/obj/effect/beam/emitter/proc/set_power(var/newpower = 1) - power = newpower - if(next) - var/obj/effect/beam/emitter/next_beam=next - next_beam.set_power(power) - update_icon() - if(!master) - INVOKE_EVENT(power_change,list("beam" = src)) - -/obj/effect/beam/emitter/spawn_child() - var/obj/effect/beam/emitter/beam = ..() - if(!beam) return null - beam.power = power - return beam - -/obj/effect/beam/emitter/update_icon() - if(!master) - invisibility = 101 //Make doubly sure - return - var/visible_power = Clamp(round(power/3) + 1, 1, 3) - //if(!master) - //testing("Visible power: [visible_power]") - icon_state = "[base_state]_[visible_power]" - -/obj/effect/beam/emitter/get_machine_underlay(var/mdir) - var/visible_power = Clamp(round(power/3) + 1, 1, 3) - return image(icon = icon, icon_state = "[base_state]_[visible_power] underlay", dir = mdir) - -/obj/effect/beam/emitter/get_damage() - return damage * power - -/obj/machinery/power/emitter/canClone(var/obj/machinery/power/emitter/O) - return istype(O) - -/obj/machinery/power/emitter/clone(var/obj/machinery/power/emitter/O) - id_tag = O.id_tag - set_frequency(O.id_tag) + return + +/obj/effect/beam/emitter + + name = "emitter beam" + icon = 'icons/effects/beam.dmi' + icon_state = "emitter_1" + anchored = 1.0 + flags = 0 + damage = 30 + damage_type = BURN + + var/base_state = "emitter" + var/power = 1 + + //Notify prisms of power change. + var/event/power_change = new + +/obj/effect/beam/emitter/proc/set_power(var/newpower = 1) + power = newpower + if(next) + var/obj/effect/beam/emitter/next_beam=next + next_beam.set_power(power) + update_icon() + if(!master) + INVOKE_EVENT(power_change,list("beam" = src)) + +/obj/effect/beam/emitter/spawn_child() + var/obj/effect/beam/emitter/beam = ..() + if(!beam) return null + beam.power = power + return beam + +/obj/effect/beam/emitter/update_icon() + if(!master) + invisibility = 101 //Make doubly sure + return + var/visible_power = Clamp(round(power/3) + 1, 1, 3) + //if(!master) + //testing("Visible power: [visible_power]") + icon_state = "[base_state]_[visible_power]" + +/obj/effect/beam/emitter/get_machine_underlay(var/mdir) + var/visible_power = Clamp(round(power/3) + 1, 1, 3) + return image(icon = icon, icon_state = "[base_state]_[visible_power] underlay", dir = mdir) + +/obj/effect/beam/emitter/get_damage() + return damage * power + +/obj/machinery/power/emitter/canClone(var/obj/machinery/power/emitter/O) + return istype(O) + +/obj/machinery/power/emitter/clone(var/obj/machinery/power/emitter/O) + id_tag = O.id_tag + set_frequency(O.id_tag) diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index dced0516143..af33695f944 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -1,325 +1,325 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - - -/* -field_generator power level display - The icon used for the field_generator need to have 'num_power_levels' number of icon states - named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_power_levels' - - The power level is displayed using overlays. The current displayed power level is stored in 'powerlevel'. - The overlay in use and the powerlevel variable must be kept in sync. A powerlevel equal to 0 means that - no power level overlay is currently in the overlays list. - -Aygar -*/ - -var/global/list/obj/machinery/field_generator/field_gen_list = list() - -#define field_generator_max_power 250 -/obj/machinery/field_generator - name = "Field Generator" - desc = "A large thermal battery that projects a high amount of energy when powered." - icon = 'icons/obj/machines/field_generator.dmi' - icon_state = "Field_Gen" - anchored = 0 - density = 1 - use_power = 0 - var/const/num_power_levels = 6 // Total number of power level icon has - var/Varedit_start = 0 - var/Varpower = 0 - var/active = 0 - var/power = 20 // Current amount of power - var/warming_up = 0 - var/list/obj/machinery/containment_field/fields - var/list/obj/machinery/field_generator/connected_gens - var/clean_up = 0 - - machine_flags = WRENCHMOVE | FIXED2WORK | WELD_FIXED - -/obj/machinery/field_generator/update_icon() - overlays.len = 0 - if(!active) - if(warming_up) - overlays += "+a[warming_up]" - if(fields.len) - overlays += "+on" - // Power level indicator - // Scale % power to % num_power_levels and truncate value - var/level = round(num_power_levels * power / field_generator_max_power) - // Clamp between 0 and num_power_levels for out of range power values - level = Clamp(level, 0, num_power_levels) - if(level) - overlays += "+p[level]" - - return - - -/obj/machinery/field_generator/New() - ..() - fields = list() - connected_gens = list() - field_gen_list += src - return - -/obj/machinery/field_generator/process() - - for(var/obj/effect/beam/B in beams) - power += B.get_damage() - - if(Varedit_start == 1) - if(active == 0) - active = 1 - state = 2 - power = field_generator_max_power - anchored = 1 - warming_up = 3 - start_fields() - update_icon() - Varedit_start = 0 - - if(src.active == 2) - calc_power() - update_icon() - return - - -/obj/machinery/field_generator/attack_hand(mob/user as mob) - if(isobserver(user) && !isAdminGhost(user)) - return 0 - - if(state == 2) - if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on - if(src.active >= 1) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + + +/* +field_generator power level display + The icon used for the field_generator need to have 'num_power_levels' number of icon states + named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_power_levels' + + The power level is displayed using overlays. The current displayed power level is stored in 'powerlevel'. + The overlay in use and the powerlevel variable must be kept in sync. A powerlevel equal to 0 means that + no power level overlay is currently in the overlays list. + -Aygar +*/ + +var/global/list/obj/machinery/field_generator/field_gen_list = list() + +#define field_generator_max_power 250 +/obj/machinery/field_generator + name = "Field Generator" + desc = "A large thermal battery that projects a high amount of energy when powered." + icon = 'icons/obj/machines/field_generator.dmi' + icon_state = "Field_Gen" + anchored = 0 + density = 1 + use_power = 0 + var/const/num_power_levels = 6 // Total number of power level icon has + var/Varedit_start = 0 + var/Varpower = 0 + var/active = 0 + var/power = 20 // Current amount of power + var/warming_up = 0 + var/list/obj/machinery/containment_field/fields + var/list/obj/machinery/field_generator/connected_gens + var/clean_up = 0 + + machine_flags = WRENCHMOVE | FIXED2WORK | WELD_FIXED + +/obj/machinery/field_generator/update_icon() + overlays.len = 0 + if(!active) + if(warming_up) + overlays += "+a[warming_up]" + if(fields.len) + overlays += "+on" + // Power level indicator + // Scale % power to % num_power_levels and truncate value + var/level = round(num_power_levels * power / field_generator_max_power) + // Clamp between 0 and num_power_levels for out of range power values + level = Clamp(level, 0, num_power_levels) + if(level) + overlays += "+p[level]" + + return + + +/obj/machinery/field_generator/New() + ..() + fields = list() + connected_gens = list() + field_gen_list += src + return + +/obj/machinery/field_generator/process() + + for(var/obj/effect/beam/B in beams) + power += B.get_damage() + + if(Varedit_start == 1) + if(active == 0) + active = 1 + state = 2 + power = field_generator_max_power + anchored = 1 + warming_up = 3 + start_fields() + update_icon() + Varedit_start = 0 + + if(src.active == 2) + calc_power() + update_icon() + return + + +/obj/machinery/field_generator/attack_hand(mob/user as mob) + if(isobserver(user) && !isAdminGhost(user)) + return 0 + + if(state == 2) + if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on + if(src.active >= 1) to_chat(user, "You are unable to turn off the [src.name] once it is online.") - return 1 - else - user.visible_message("[user.name] turns on the [src.name]", \ - "You turn on the [src.name].", \ - "You hear heavy droning") - turn_on() - investigation_log(I_SINGULO,"activated by [user.key].") - - src.add_fingerprint(user) - else + return 1 + else + user.visible_message("[user.name] turns on the [src.name]", \ + "You turn on the [src.name].", \ + "You hear heavy droning") + turn_on() + investigation_log(I_SINGULO,"activated by [user.key].") + + src.add_fingerprint(user) + else to_chat(user, "The [src] needs to be firmly secured to the floor first.") - return 0 - -/obj/machinery/field_generator/wrenchAnchor(mob/user) - if(active) + return 0 + +/obj/machinery/field_generator/wrenchAnchor(mob/user) + if(active) to_chat(user, "Turn off the [src] first.") - return -1 - return ..() - - -/obj/machinery/field_generator/attackby(obj/item/W, mob/user) - if(active) + return -1 + return ..() + + +/obj/machinery/field_generator/attackby(obj/item/W, mob/user) + if(active) to_chat(user, "The [src] needs to be off.") - return - else if(..()) - return 1 - return - - -/obj/machinery/field_generator/emp_act() - return 0 - - -/obj/machinery/field_generator/blob_act() - if(active) - return 0 - else - ..() - -/obj/machinery/field_generator/bullet_act(var/obj/item/projectile/Proj) - if(Proj.flag != "bullet") - power += Proj.damage - update_icon() - return 0 - - -/obj/machinery/field_generator/Destroy() - src.cleanup() - field_gen_list -= src - ..() - - - -/obj/machinery/field_generator/proc/turn_off() - active = 0 - spawn(1) - src.cleanup() - update_icon() - -/obj/machinery/field_generator/proc/turn_on() - active = 1 - warming_up = 1 - spawn(1) - while (warming_up<3 && active) - sleep(50) - warming_up++ - update_icon() - if(warming_up >= 3) - start_fields() - update_icon() - - -/obj/machinery/field_generator/proc/calc_power() - if(Varpower) - return 1 - - update_icon() - if(src.power > field_generator_max_power) - src.power = field_generator_max_power - - var/power_draw = 2 - for (var/obj/machinery/containment_field/F in fields) - if (isnull(F)) - continue - power_draw++ - if(draw_power(round(power_draw/2,1))) - return 1 - else - for(var/mob/M in viewers(src)) - M.show_message("The [src.name] shuts down!") - turn_off() - investigation_log(I_SINGULO,"ran out of power and deactivated") - src.power = 0 - return 0 - -//This could likely be better, it tends to start loopin if you have a complex generator loop setup. Still works well enough to run the engine fields will likely recode the field gens and fields sometime -Mport -/obj/machinery/field_generator/proc/draw_power(var/draw = 0, var/failsafe = 0, var/obj/machinery/field_generator/G = null, var/obj/machinery/field_generator/last = null) - if(Varpower) - return 1 - if((G && G == src) || (failsafe >= 8))//Loopin, set fail - return 0 - else - failsafe++ - if(src.power >= draw)//We have enough power - src.power -= draw - return 1 - else//Need more power - draw -= src.power - src.power = 0 - for(var/obj/machinery/field_generator/FG in connected_gens) - if(isnull(FG)) - continue - if(FG == last)//We just asked you - continue - if(G)//Another gen is askin for power and we dont have it - if(FG.draw_power(draw,failsafe,G,src))//Can you take the load - return 1 - else - return 0 - else//We are askin another for power - if(FG.draw_power(draw,failsafe,src,src)) - return 1 - else - return 0 - - -/obj/machinery/field_generator/proc/start_fields() - if(!src.state == 2 || !anchored) - turn_off() - return - spawn(1) - setup_field(1) - spawn(2) - setup_field(2) - spawn(3) - setup_field(4) - spawn(4) - setup_field(8) - src.active = 2 - - -/obj/machinery/field_generator/proc/setup_field(var/NSEW) - var/turf/T = src.loc - var/obj/machinery/field_generator/G - var/steps = 0 - if(!NSEW)//Make sure its ran right - return - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator - T = get_step(T, NSEW) - if(T.density)//We cant shoot a field though this - return 0 - for(var/atom/A in T.contents) - if(ismob(A)) - continue - if(!istype(A,/obj/machinery/field_generator)) - if((istype(A,/obj/machinery/door)||istype(A,/obj/machinery/the_singularitygen))&&(A.density)) - return 0 - steps += 1 - G = locate(/obj/machinery/field_generator) in T - if(!isnull(G)) - steps -= 1 - if(!G.active) - return 0 - break - if(isnull(G)) - return - T = src.loc - for(var/dist = 0, dist < steps, dist += 1) // creates each field tile - var/field_dir = get_dir(T,get_step(G.loc, NSEW)) - T = get_step(T, NSEW) - if(!locate(/obj/machinery/containment_field) in T) - var/obj/machinery/containment_field/CF = new/obj/machinery/containment_field() - CF.set_master(src,G) - fields += CF - G.fields += CF - CF.loc = T - CF.dir = field_dir - var/listcheck = 0 - for(var/obj/machinery/field_generator/FG in connected_gens) - if (isnull(FG)) - continue - if(FG == G) - listcheck = 1 - break - if(!listcheck) - connected_gens.Add(G) - listcheck = 0 - for(var/obj/machinery/field_generator/FG2 in G.connected_gens) - if (isnull(FG2)) - continue - if(FG2 == src) - listcheck = 1 - break - if(!listcheck) - G.connected_gens.Add(src) - - -/obj/machinery/field_generator/proc/cleanup() - clean_up = 1 - for (var/obj/effect/beam/B in beams) - if(!B) - continue - if(B.target == src) - B.target = null - for (var/obj/machinery/containment_field/F in fields) - if (isnull(F)) - continue - qdel(F) - F = null - fields = list() - for(var/obj/machinery/field_generator/FG in connected_gens) - if (isnull(FG)) - continue - FG.connected_gens.Remove(src) - if(!FG.clean_up)//Makes the other gens clean up as well - FG.cleanup() - connected_gens.Remove(FG) - connected_gens = list() - clean_up = 0 - update_icon() - - //This is here to help fight the "hurr durr, release singulo cos nobody will notice before the - //singulo eats the evidence". It's not fool-proof but better than nothing. - //I want to avoid using global variables. - spawn(1) - var/temp = 1 //stops spam - for(var/obj/machinery/singularity/O in power_machines) - if(O.last_warning && temp) - if((world.time - O.last_warning) > 50) //to stop message-spam - temp = 0 - message_admins("A singulo exists and a containment field has failed.",1) - investigation_log(I_SINGULO,"has failed whilst a singulo exists.") - O.last_warning = world.time + return + else if(..()) + return 1 + return + + +/obj/machinery/field_generator/emp_act() + return 0 + + +/obj/machinery/field_generator/blob_act() + if(active) + return 0 + else + ..() + +/obj/machinery/field_generator/bullet_act(var/obj/item/projectile/Proj) + if(Proj.flag != "bullet") + power += Proj.damage + update_icon() + return 0 + + +/obj/machinery/field_generator/Destroy() + src.cleanup() + field_gen_list -= src + ..() + + + +/obj/machinery/field_generator/proc/turn_off() + active = 0 + spawn(1) + src.cleanup() + update_icon() + +/obj/machinery/field_generator/proc/turn_on() + active = 1 + warming_up = 1 + spawn(1) + while (warming_up<3 && active) + sleep(50) + warming_up++ + update_icon() + if(warming_up >= 3) + start_fields() + update_icon() + + +/obj/machinery/field_generator/proc/calc_power() + if(Varpower) + return 1 + + update_icon() + if(src.power > field_generator_max_power) + src.power = field_generator_max_power + + var/power_draw = 2 + for (var/obj/machinery/containment_field/F in fields) + if (isnull(F)) + continue + power_draw++ + if(draw_power(round(power_draw/2,1))) + return 1 + else + for(var/mob/M in viewers(src)) + M.show_message("The [src.name] shuts down!") + turn_off() + investigation_log(I_SINGULO,"ran out of power and deactivated") + src.power = 0 + return 0 + +//This could likely be better, it tends to start loopin if you have a complex generator loop setup. Still works well enough to run the engine fields will likely recode the field gens and fields sometime -Mport +/obj/machinery/field_generator/proc/draw_power(var/draw = 0, var/failsafe = 0, var/obj/machinery/field_generator/G = null, var/obj/machinery/field_generator/last = null) + if(Varpower) + return 1 + if((G && G == src) || (failsafe >= 8))//Loopin, set fail + return 0 + else + failsafe++ + if(src.power >= draw)//We have enough power + src.power -= draw + return 1 + else//Need more power + draw -= src.power + src.power = 0 + for(var/obj/machinery/field_generator/FG in connected_gens) + if(isnull(FG)) + continue + if(FG == last)//We just asked you + continue + if(G)//Another gen is askin for power and we dont have it + if(FG.draw_power(draw,failsafe,G,src))//Can you take the load + return 1 + else + return 0 + else//We are askin another for power + if(FG.draw_power(draw,failsafe,src,src)) + return 1 + else + return 0 + + +/obj/machinery/field_generator/proc/start_fields() + if(!src.state == 2 || !anchored) + turn_off() + return + spawn(1) + setup_field(1) + spawn(2) + setup_field(2) + spawn(3) + setup_field(4) + spawn(4) + setup_field(8) + src.active = 2 + + +/obj/machinery/field_generator/proc/setup_field(var/NSEW) + var/turf/T = src.loc + var/obj/machinery/field_generator/G + var/steps = 0 + if(!NSEW)//Make sure its ran right + return + for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator + T = get_step(T, NSEW) + if(T.density)//We cant shoot a field though this + return 0 + for(var/atom/A in T.contents) + if(ismob(A)) + continue + if(!istype(A,/obj/machinery/field_generator)) + if((istype(A,/obj/machinery/door)||istype(A,/obj/machinery/the_singularitygen))&&(A.density)) + return 0 + steps += 1 + G = locate(/obj/machinery/field_generator) in T + if(!isnull(G)) + steps -= 1 + if(!G.active) + return 0 + break + if(isnull(G)) + return + T = src.loc + for(var/dist = 0, dist < steps, dist += 1) // creates each field tile + var/field_dir = get_dir(T,get_step(G.loc, NSEW)) + T = get_step(T, NSEW) + if(!locate(/obj/machinery/containment_field) in T) + var/obj/machinery/containment_field/CF = new/obj/machinery/containment_field() + CF.set_master(src,G) + fields += CF + G.fields += CF + CF.loc = T + CF.dir = field_dir + var/listcheck = 0 + for(var/obj/machinery/field_generator/FG in connected_gens) + if (isnull(FG)) + continue + if(FG == G) + listcheck = 1 + break + if(!listcheck) + connected_gens.Add(G) + listcheck = 0 + for(var/obj/machinery/field_generator/FG2 in G.connected_gens) + if (isnull(FG2)) + continue + if(FG2 == src) + listcheck = 1 + break + if(!listcheck) + G.connected_gens.Add(src) + + +/obj/machinery/field_generator/proc/cleanup() + clean_up = 1 + for (var/obj/effect/beam/B in beams) + if(!B) + continue + if(B.target == src) + B.target = null + for (var/obj/machinery/containment_field/F in fields) + if (isnull(F)) + continue + qdel(F) + F = null + fields = list() + for(var/obj/machinery/field_generator/FG in connected_gens) + if (isnull(FG)) + continue + FG.connected_gens.Remove(src) + if(!FG.clean_up)//Makes the other gens clean up as well + FG.cleanup() + connected_gens.Remove(FG) + connected_gens = list() + clean_up = 0 + update_icon() + + //This is here to help fight the "hurr durr, release singulo cos nobody will notice before the + //singulo eats the evidence". It's not fool-proof but better than nothing. + //I want to avoid using global variables. + spawn(1) + var/temp = 1 //stops spam + for(var/obj/machinery/singularity/O in power_machines) + if(O.last_warning && temp) + if((world.time - O.last_warning) > 50) //to stop message-spam + temp = 0 + message_admins("A singulo exists and a containment field has failed.",1) + investigation_log(I_SINGULO,"has failed whilst a singulo exists.") + O.last_warning = world.time diff --git a/code/modules/power/singularity/generator.dm b/code/modules/power/singularity/generator.dm index 5acc0b2e51c..23726bd8a82 100644 --- a/code/modules/power/singularity/generator.dm +++ b/code/modules/power/singularity/generator.dm @@ -1,35 +1,35 @@ -/////SINGULARITY SPAWNER -/obj/machinery/the_singularitygen/ - name = "Gravitational Singularity Generator" - desc = "An Odd Device which produces a Gravitational Singularity when set up." - icon = 'icons/obj/singularity.dmi' - icon_state = "TheSingGen" - anchored = 0 - density = 1 - use_power = 0 - var/energy = 0 - - machine_flags = WRENCHMOVE | FIXED2WORK - -/obj/machinery/the_singularitygen/process() - if (energy < 200) - return - - var/prints="" - - if (fingerprintshidden) - prints=", all touchers: " - for(var/line in fingerprintshidden) - prints += ",[line] " - - log_admin("New singularity made[prints]. Last touched by [fingerprintslast].") - message_admins("New singularity made[prints]. Last touched by [fingerprintslast].") - new /obj/machinery/singularity(get_turf(src), 50) - qdel(src) - -/obj/machinery/the_singularitygen/wrenchAnchor(mob/user) - src.add_hiddenprint(user) - return ..() - -/obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user) - return ..() +/////SINGULARITY SPAWNER +/obj/machinery/the_singularitygen/ + name = "Gravitational Singularity Generator" + desc = "An Odd Device which produces a Gravitational Singularity when set up." + icon = 'icons/obj/singularity.dmi' + icon_state = "TheSingGen" + anchored = 0 + density = 1 + use_power = 0 + var/energy = 0 + + machine_flags = WRENCHMOVE | FIXED2WORK + +/obj/machinery/the_singularitygen/process() + if (energy < 200) + return + + var/prints="" + + if (fingerprintshidden) + prints=", all touchers: " + for(var/line in fingerprintshidden) + prints += ",[line] " + + log_admin("New singularity made[prints]. Last touched by [fingerprintslast].") + message_admins("New singularity made[prints]. Last touched by [fingerprintslast].") + new /obj/machinery/singularity(get_turf(src), 50) + qdel(src) + +/obj/machinery/the_singularitygen/wrenchAnchor(mob/user) + src.add_hiddenprint(user) + return ..() + +/obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user) + return ..() diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm index 7e5ea467462..111970ca98f 100644 --- a/code/modules/power/singularity/particle_accelerator/particle.dm +++ b/code/modules/power/singularity/particle_accelerator/particle.dm @@ -1,136 +1,136 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/obj/effect/accelerated_particle - name = "Accelerated Particles" - desc = "Small things moving very fast." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "particle1"//Need a new icon for this - anchored = 1 - density = 1 - var/movement_range = 10 - var/energy = 10 //energy in eV - var/mega_energy = 0 //energy in MeV - var/frequency = 1 - var/ionizing = 0 - var/particle_type - var/additional_particles = 0 - var/turf/target - var/turf/source - var/movetotarget = 1 - -/obj/effect/accelerated_particle/resetVariables() - ..("movement_range", "target", "ionizing", "particle_type", "source", "movetotarget", args) - movement_range = 10 - target = null - ionizing = 0 - particle_type = null - source = null - movetotarget = 1 - -/obj/effect/accelerated_particle/weak - movement_range = 8 - energy = 5 - icon_state="particle0" - resetVariables() - ..("energy", "movement_range") - movement_range = 8 - energy = 5 - -/obj/effect/accelerated_particle/strong - movement_range = 15 - energy = 15 - icon_state="particle2" - resetVariables() - ..("energy", "movement_range") - energy = 15 - movement_range = 15 - -/obj/effect/accelerated_particle/powerful - movement_range = 20 - energy = 50 - icon_state="particle3" - resetVariables() - ..("energy", "movement_range") - energy = 50 - movement_range = 20 - -/obj/effect/accelerated_particle/New(loc, dir = 2, move = 0) - . = ..() - src.loc = loc - src.dir = dir - -/obj/effect/accelerated_particle/proc/startMove(move = 0) - if(movement_range > 20) - movement_range = 20 - if(move) - spawn(0) - move(1) - -/obj/effect/accelerated_particle/Bump(atom/A) - if (A) - if(ismob(A)) - toxmob(A) - if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/machinery/singularity/))) - A:energy += energy - else if( istype(A,/obj/effect/rust_particle_catcher) ) - var/obj/effect/rust_particle_catcher/collided_catcher = A - if(particle_type && particle_type != "neutron") - if(collided_catcher.AddParticles(particle_type, 1 + additional_particles)) - collided_catcher.parent.AddEnergy(energy,mega_energy) - loc = null - else if( istype(A,/obj/machinery/power/rust_core) ) - var/obj/machinery/power/rust_core/collided_core = A - if(particle_type && particle_type != "neutron") - if(collided_core.AddParticles(particle_type, 1 + additional_particles)) - var/energy_loss_ratio = abs(collided_core.owned_field.frequency - frequency) / 1e9 - collided_core.owned_field.mega_energy += mega_energy - mega_energy * energy_loss_ratio - collided_core.owned_field.energy += energy - energy * energy_loss_ratio - loc = null - return - - -/obj/effect/accelerated_particle/Bumped(atom/A) - if(ismob(A)) - Bump(A) - return - -/obj/effect/accelerated_particle/ex_act(severity) - returnToPool(src) - return - -/obj/effect/accelerated_particle/proc/toxmob(var/mob/living/M) - var/radiation = (energy*2) -/* if(istype(M,/mob/living/carbon/human)) - if(M:wear_suit) //TODO: check for radiation protection - radiation = round(radiation/2,1) - if(istype(M,/mob/living/carbon/monkey)) - if(M:wear_suit) //TODO: check for radiation protection - radiation = round(radiation/2,1)*/ - M.apply_effect((radiation*3),IRRADIATE,0) - M.updatehealth() +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/obj/effect/accelerated_particle + name = "Accelerated Particles" + desc = "Small things moving very fast." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "particle1"//Need a new icon for this + anchored = 1 + density = 1 + var/movement_range = 10 + var/energy = 10 //energy in eV + var/mega_energy = 0 //energy in MeV + var/frequency = 1 + var/ionizing = 0 + var/particle_type + var/additional_particles = 0 + var/turf/target + var/turf/source + var/movetotarget = 1 + +/obj/effect/accelerated_particle/resetVariables() + ..("movement_range", "target", "ionizing", "particle_type", "source", "movetotarget", args) + movement_range = 10 + target = null + ionizing = 0 + particle_type = null + source = null + movetotarget = 1 + +/obj/effect/accelerated_particle/weak + movement_range = 8 + energy = 5 + icon_state="particle0" + resetVariables() + ..("energy", "movement_range") + movement_range = 8 + energy = 5 + +/obj/effect/accelerated_particle/strong + movement_range = 15 + energy = 15 + icon_state="particle2" + resetVariables() + ..("energy", "movement_range") + energy = 15 + movement_range = 15 + +/obj/effect/accelerated_particle/powerful + movement_range = 20 + energy = 50 + icon_state="particle3" + resetVariables() + ..("energy", "movement_range") + energy = 50 + movement_range = 20 + +/obj/effect/accelerated_particle/New(loc, dir = 2, move = 0) + . = ..() + src.loc = loc + src.dir = dir + +/obj/effect/accelerated_particle/proc/startMove(move = 0) + if(movement_range > 20) + movement_range = 20 + if(move) + spawn(0) + move(1) + +/obj/effect/accelerated_particle/Bump(atom/A) + if (A) + if(ismob(A)) + toxmob(A) + if((istype(A,/obj/machinery/the_singularitygen))||(istype(A,/obj/machinery/singularity/))) + A:energy += energy + else if( istype(A,/obj/effect/rust_particle_catcher) ) + var/obj/effect/rust_particle_catcher/collided_catcher = A + if(particle_type && particle_type != "neutron") + if(collided_catcher.AddParticles(particle_type, 1 + additional_particles)) + collided_catcher.parent.AddEnergy(energy,mega_energy) + loc = null + else if( istype(A,/obj/machinery/power/rust_core) ) + var/obj/machinery/power/rust_core/collided_core = A + if(particle_type && particle_type != "neutron") + if(collided_core.AddParticles(particle_type, 1 + additional_particles)) + var/energy_loss_ratio = abs(collided_core.owned_field.frequency - frequency) / 1e9 + collided_core.owned_field.mega_energy += mega_energy - mega_energy * energy_loss_ratio + collided_core.owned_field.energy += energy - energy * energy_loss_ratio + loc = null + return + + +/obj/effect/accelerated_particle/Bumped(atom/A) + if(ismob(A)) + Bump(A) + return + +/obj/effect/accelerated_particle/ex_act(severity) + returnToPool(src) + return + +/obj/effect/accelerated_particle/proc/toxmob(var/mob/living/M) + var/radiation = (energy*2) +/* if(istype(M,/mob/living/carbon/human)) + if(M:wear_suit) //TODO: check for radiation protection + radiation = round(radiation/2,1) + if(istype(M,/mob/living/carbon/monkey)) + if(M:wear_suit) //TODO: check for radiation protection + radiation = round(radiation/2,1)*/ + M.apply_effect((radiation*3),IRRADIATE,0) + M.updatehealth() // to_chat(M, "You feel odd.") - return - - -/obj/effect/accelerated_particle/proc/move(var/lag) - if(!loc) return 0 - if(target) - if(movetotarget) - if(!step_towards(src,target)) - src.loc = get_step(src, get_dir(src,target)) - if(get_dist(src,target) < 1) - movetotarget = 0 - else - if(!step(src, get_step_away(src,source))) - src.loc = get_step(src, get_step_away(src,source)) - else - if(!step(src,dir)) - src.loc = get_step(src,dir) - movement_range-- - if(movement_range <= 0) - returnToPool(src) - loc = null - return 0 - else - sleep(lag) - move(lag) + return + + +/obj/effect/accelerated_particle/proc/move(var/lag) + if(!loc) return 0 + if(target) + if(movetotarget) + if(!step_towards(src,target)) + src.loc = get_step(src, get_dir(src,target)) + if(get_dist(src,target) < 1) + movetotarget = 0 + else + if(!step(src, get_step_away(src,source))) + src.loc = get_step(src, get_step_away(src,source)) + else + if(!step(src,dir)) + src.loc = get_step(src,dir) + movement_range-- + if(movement_range <= 0) + returnToPool(src) + loc = null + return 0 + else + sleep(lag) + move(lag) diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index c7270cba839..a43091d3037 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -1,401 +1,401 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/*Composed of 7 parts -3 Particle emitters -proc -emit_particle() - -1 power box -the only part of this thing that uses power, can hack to mess with the pa/make it better - -1 fuel chamber -contains procs for mixing gas and whatever other fuel it uses -mix_gas() - -1 gas holder WIP -acts like a tank valve on the ground that you wrench gas tanks onto -proc -extract_gas() -return_gas() -attach_tank() -remove_tank() -get_available_mix() - -1 End Cap - -1 Control computer -interface for the pa, acts like a computer with an html menu for diff parts and a status report -all other parts contain only a ref to this -a /machine/, tells the others to do work -contains ref for all parts -proc -process() -check_build() - -Setup map - |EC| -CC|FC| - |PB| -PE|PE|PE - - -Icon Addemdum -Icon system is much more robust, and the icons are all variable based. -Each part has a reference string, powered, strength, and contruction values. -Using this the update_icon() proc is simplified a bit (using for absolutely was problematic with naming), -so the icon_state comes out be: -"[reference][strength]", with a switch controlling construction_states and ensuring that it doesn't -power on while being contructed, and all these variables are set by the computer through it's scan list -Essential order of the icons: -Standard - [reference] -Wrenched - [reference] -Wired - [reference]w -Closed - [reference]c -Powered - [reference]p[strength] -Strength being set by the computer and a null strength (Computer is powered off or inactive) returns a 'null', counting as empty -So, hopefully this is helpful if any more icons are to be added/changed/wondering what the hell is going on here - -*/ - -/obj/structure/particle_accelerator - name = "Particle Accelerator" - desc = "Part of a Particle Accelerator." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "none" - anchored = 0 - density = 1 - var/obj/machinery/particle_accelerator/control_box/master = null - var/construction_state = 0 - var/reference = null - var/powered = 0 - var/strength = null - var/desc_holder = null - -/obj/structure/particle_accelerator/Destroy() - construction_state = 0 - if(master) - master.part_scan() - ..() - -/obj/structure/particle_accelerator/end_cap - name = "Alpha Particle Generation Array" - desc_holder = "This is where Alpha particles are generated from \[REDACTED\]" - icon_state = "end_cap" - reference = "end_cap" - -/obj/structure/particle_accelerator/update_icon() - ..() - return - - -/obj/structure/particle_accelerator/verb/rotate() - set name = "Rotate Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/*Composed of 7 parts +3 Particle emitters +proc +emit_particle() + +1 power box +the only part of this thing that uses power, can hack to mess with the pa/make it better + +1 fuel chamber +contains procs for mixing gas and whatever other fuel it uses +mix_gas() + +1 gas holder WIP +acts like a tank valve on the ground that you wrench gas tanks onto +proc +extract_gas() +return_gas() +attach_tank() +remove_tank() +get_available_mix() + +1 End Cap + +1 Control computer +interface for the pa, acts like a computer with an html menu for diff parts and a status report +all other parts contain only a ref to this +a /machine/, tells the others to do work +contains ref for all parts +proc +process() +check_build() + +Setup map + |EC| +CC|FC| + |PB| +PE|PE|PE + + +Icon Addemdum +Icon system is much more robust, and the icons are all variable based. +Each part has a reference string, powered, strength, and contruction values. +Using this the update_icon() proc is simplified a bit (using for absolutely was problematic with naming), +so the icon_state comes out be: +"[reference][strength]", with a switch controlling construction_states and ensuring that it doesn't +power on while being contructed, and all these variables are set by the computer through it's scan list +Essential order of the icons: +Standard - [reference] +Wrenched - [reference] +Wired - [reference]w +Closed - [reference]c +Powered - [reference]p[strength] +Strength being set by the computer and a null strength (Computer is powered off or inactive) returns a 'null', counting as empty +So, hopefully this is helpful if any more icons are to be added/changed/wondering what the hell is going on here + +*/ + +/obj/structure/particle_accelerator + name = "Particle Accelerator" + desc = "Part of a Particle Accelerator." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "none" + anchored = 0 + density = 1 + var/obj/machinery/particle_accelerator/control_box/master = null + var/construction_state = 0 + var/reference = null + var/powered = 0 + var/strength = null + var/desc_holder = null + +/obj/structure/particle_accelerator/Destroy() + construction_state = 0 + if(master) + master.part_scan() + ..() + +/obj/structure/particle_accelerator/end_cap + name = "Alpha Particle Generation Array" + desc_holder = "This is where Alpha particles are generated from \[REDACTED\]" + icon_state = "end_cap" + reference = "end_cap" + +/obj/structure/particle_accelerator/update_icon() + ..() + return + + +/obj/structure/particle_accelerator/verb/rotate() + set name = "Rotate Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 270) - return 1 - -/obj/structure/particle_accelerator/verb/rotateccw() - set name = "Rotate Counter Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return 0 + src.dir = turn(src.dir, 270) + return 1 + +/obj/structure/particle_accelerator/verb/rotateccw() + set name = "Rotate Counter Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 90) - return 1 - -/obj/structure/particle_accelerator/examine(mob/user) - switch(src.construction_state) - if(0) - src.desc = text("A [name], looks like it's not attached to the flooring") - if(1) - src.desc = text("A [name], it is missing some cables") - if(2) - src.desc = text("A [name], the panel is open") - if(3) - src.desc = text("The [name] is assembled") - if(powered) - src.desc = src.desc_holder - ..() - - -/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user) - if(istool(W)) - if(src.process_tool_hit(W,user)) - return - ..() - return - - -/obj/structure/particle_accelerator/Move() - ..() - if(master && master.active) - master.toggle_power() - investigation_log(I_SINGULO,"was moved whilst active; it powered down.") - -/obj/structure/particle_accelerator/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(25)) - qdel(src) - return - else - return - - -/obj/structure/particle_accelerator/blob_act() - if(prob(50)) - qdel(src) - return - -/obj/structure/particle_accelerator/update_icon() - switch(construction_state) - if(0,1) - icon_state="[reference]" - if(2) - icon_state="[reference]w" - if(3) - if(powered) - icon_state="[reference]p[strength]" - else - icon_state="[reference]c" - return - -/obj/structure/particle_accelerator/proc/update_state() - if(master) - master.update_state() - return 0 - - -/obj/structure/particle_accelerator/proc/report_ready(var/obj/O) - if(O && (O == master)) - if(construction_state >= 3) - return 1 - return 0 - - -/obj/structure/particle_accelerator/proc/report_master() - if(master) - return master - return 0 - - -/obj/structure/particle_accelerator/proc/connect_master(var/obj/O) - if(O && istype(O,/obj/machinery/particle_accelerator/control_box)) - if(O.dir == src.dir) - master = O - return 1 - return 0 - - -/obj/structure/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user) - if(!(O) || !(user)) - return 0 - if(!ismob(user) || !isobj(O)) - return 0 - var/temp_state = src.construction_state - - switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps - if(0) - if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - src.anchored = 1 - user.visible_message("[user.name] secures the [src.name] to the floor.", \ - "You secure the external bolts.") - temp_state++ - if(1) - if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - src.anchored = 0 - user.visible_message("[user.name] detaches the [src.name] from the floor.", \ - "You remove the external bolts.") - temp_state-- - else if(iscoil(O)) - if(O:use(1,user)) - user.visible_message("[user.name] adds wires to the [src.name].", \ - "You add some wires.") - temp_state++ - if(2) - if(iswirecutter(O))//TODO:Shock user if its on? - user.visible_message("[user.name] removes some wires from the [src.name].", \ - "You remove some wires.") - temp_state-- - else if(isscrewdriver(O)) - user.visible_message("[user.name] closes the [src.name]'s access panel.", \ - "You close the access panel.") - temp_state++ - if(3) - if(isscrewdriver(O)) - user.visible_message("[user.name] opens the [src.name]'s access panel.", \ - "You open the access panel.") - temp_state-- - if(temp_state == src.construction_state)//Nothing changed - return 0 - else - src.construction_state = temp_state - if(src.construction_state < 3)//Was taken apart, update state - update_state() - update_icon() - return 1 - return 0 - - - -/obj/machinery/particle_accelerator - name = "Particle Accelerator" - desc = "Part of a Particle Accelerator." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "none" - anchored = 0 - density = 1 - use_power = 0 - idle_power_usage = 0 - active_power_usage = 0 - var/construction_state = 0 - var/active = 0 - var/reference = null - var/powered = null - var/strength = 0 - var/desc_holder = null - - -/obj/machinery/particle_accelerator/verb/rotate() - set name = "Rotate Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return 0 + src.dir = turn(src.dir, 90) + return 1 + +/obj/structure/particle_accelerator/examine(mob/user) + switch(src.construction_state) + if(0) + src.desc = text("A [name], looks like it's not attached to the flooring") + if(1) + src.desc = text("A [name], it is missing some cables") + if(2) + src.desc = text("A [name], the panel is open") + if(3) + src.desc = text("The [name] is assembled") + if(powered) + src.desc = src.desc_holder + ..() + + +/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user) + if(istool(W)) + if(src.process_tool_hit(W,user)) + return + ..() + return + + +/obj/structure/particle_accelerator/Move() + ..() + if(master && master.active) + master.toggle_power() + investigation_log(I_SINGULO,"was moved whilst active; it powered down.") + +/obj/structure/particle_accelerator/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(25)) + qdel(src) + return + else + return + + +/obj/structure/particle_accelerator/blob_act() + if(prob(50)) + qdel(src) + return + +/obj/structure/particle_accelerator/update_icon() + switch(construction_state) + if(0,1) + icon_state="[reference]" + if(2) + icon_state="[reference]w" + if(3) + if(powered) + icon_state="[reference]p[strength]" + else + icon_state="[reference]c" + return + +/obj/structure/particle_accelerator/proc/update_state() + if(master) + master.update_state() + return 0 + + +/obj/structure/particle_accelerator/proc/report_ready(var/obj/O) + if(O && (O == master)) + if(construction_state >= 3) + return 1 + return 0 + + +/obj/structure/particle_accelerator/proc/report_master() + if(master) + return master + return 0 + + +/obj/structure/particle_accelerator/proc/connect_master(var/obj/O) + if(O && istype(O,/obj/machinery/particle_accelerator/control_box)) + if(O.dir == src.dir) + master = O + return 1 + return 0 + + +/obj/structure/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user) + if(!(O) || !(user)) + return 0 + if(!ismob(user) || !isobj(O)) + return 0 + var/temp_state = src.construction_state + + switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps + if(0) + if(iswrench(O)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + src.anchored = 1 + user.visible_message("[user.name] secures the [src.name] to the floor.", \ + "You secure the external bolts.") + temp_state++ + if(1) + if(iswrench(O)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + src.anchored = 0 + user.visible_message("[user.name] detaches the [src.name] from the floor.", \ + "You remove the external bolts.") + temp_state-- + else if(iscoil(O)) + if(O:use(1,user)) + user.visible_message("[user.name] adds wires to the [src.name].", \ + "You add some wires.") + temp_state++ + if(2) + if(iswirecutter(O))//TODO:Shock user if its on? + user.visible_message("[user.name] removes some wires from the [src.name].", \ + "You remove some wires.") + temp_state-- + else if(isscrewdriver(O)) + user.visible_message("[user.name] closes the [src.name]'s access panel.", \ + "You close the access panel.") + temp_state++ + if(3) + if(isscrewdriver(O)) + user.visible_message("[user.name] opens the [src.name]'s access panel.", \ + "You open the access panel.") + temp_state-- + if(temp_state == src.construction_state)//Nothing changed + return 0 + else + src.construction_state = temp_state + if(src.construction_state < 3)//Was taken apart, update state + update_state() + update_icon() + return 1 + return 0 + + + +/obj/machinery/particle_accelerator + name = "Particle Accelerator" + desc = "Part of a Particle Accelerator." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "none" + anchored = 0 + density = 1 + use_power = 0 + idle_power_usage = 0 + active_power_usage = 0 + var/construction_state = 0 + var/active = 0 + var/reference = null + var/powered = null + var/strength = 0 + var/desc_holder = null + + +/obj/machinery/particle_accelerator/verb/rotate() + set name = "Rotate Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 270) - return 1 - -/obj/machinery/particle_accelerator/verb/rotateccw() - set name = "Rotate Counter-Clockwise" - set category = "Object" - set src in oview(1) - - if (src.anchored || usr:stat) + return 0 + src.dir = turn(src.dir, 270) + return 1 + +/obj/machinery/particle_accelerator/verb/rotateccw() + set name = "Rotate Counter-Clockwise" + set category = "Object" + set src in oview(1) + + if (src.anchored || usr:stat) to_chat(usr, "It is fastened to the floor!") - return 0 - src.dir = turn(src.dir, 90) - return 1 - -/obj/machinery/particle_accelerator/update_icon() - return - -/obj/machinery/particle_accelerator/examine(mob/user) - switch(src.construction_state) - if(0) - src.desc = text("A [name], looks like it's not attached to the flooring") - if(1) - src.desc = text("A [name], it is missing some cables") - if(2) - src.desc = text("A [name], the panel is open") - if(3) - src.desc = text("The [name] is assembled") - if(powered) - src.desc = src.desc_holder - ..() - - -/obj/machinery/particle_accelerator/attackby(obj/item/W, mob/user) - if(istool(W)) - if(src.process_tool_hit(W,user)) - return - ..() - return - -/obj/machinery/particle_accelerator/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - if(3.0) - if (prob(25)) - qdel(src) - return - else - return - - -/obj/machinery/particle_accelerator/blob_act() - if(prob(50)) - qdel(src) - return - -/obj/machinery/particle_accelerator/proc/update_state() - return 0 - - -/obj/machinery/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user) - if(!(O) || !(user)) - return 0 - if(!ismob(user) || !isobj(O)) - return 0 - var/temp_state = src.construction_state - switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps - if(0) - if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - src.anchored = 1 - user.visible_message("[user.name] secures the [src.name] to the floor.", \ - "You secure the external bolts.") - temp_state++ - if(1) - if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) - src.anchored = 0 - user.visible_message("[user.name] detaches the [src.name] from the floor.", \ - "You remove the external bolts.") - temp_state-- - else if(iscoil(O)) - if(O:use(1)) - user.visible_message("[user.name] adds wires to the [src.name].", \ - "You add some wires.") - temp_state++ - if(2) - if(iswirecutter(O))//TODO:Shock user if its on? - user.visible_message("[user.name] removes some wires from the [src.name].", \ - "You remove some wires.") - temp_state-- - else if(isscrewdriver(O)) - user.visible_message("[user.name] closes the [src.name]'s access panel.", \ - "You close the access panel.") - temp_state++ - if(3) - if(isscrewdriver(O)) - user.visible_message("[user.name] opens the [src.name]'s access panel.", \ - "You open the access panel.") - temp_state-- - active = 0 - if(temp_state == src.construction_state)//Nothing changed - return 0 - else - if(src.construction_state < 3)//Was taken apart, update state - update_state() - if(use_power) - use_power = 0 - src.construction_state = temp_state - if(src.construction_state >= 3) - use_power = 1 - update_icon() - return 1 - return 0 + return 0 + src.dir = turn(src.dir, 90) + return 1 + +/obj/machinery/particle_accelerator/update_icon() + return + +/obj/machinery/particle_accelerator/examine(mob/user) + switch(src.construction_state) + if(0) + src.desc = text("A [name], looks like it's not attached to the flooring") + if(1) + src.desc = text("A [name], it is missing some cables") + if(2) + src.desc = text("A [name], the panel is open") + if(3) + src.desc = text("The [name] is assembled") + if(powered) + src.desc = src.desc_holder + ..() + + +/obj/machinery/particle_accelerator/attackby(obj/item/W, mob/user) + if(istool(W)) + if(src.process_tool_hit(W,user)) + return + ..() + return + +/obj/machinery/particle_accelerator/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + if(3.0) + if (prob(25)) + qdel(src) + return + else + return + + +/obj/machinery/particle_accelerator/blob_act() + if(prob(50)) + qdel(src) + return + +/obj/machinery/particle_accelerator/proc/update_state() + return 0 + + +/obj/machinery/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user) + if(!(O) || !(user)) + return 0 + if(!ismob(user) || !isobj(O)) + return 0 + var/temp_state = src.construction_state + switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps + if(0) + if(iswrench(O)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + src.anchored = 1 + user.visible_message("[user.name] secures the [src.name] to the floor.", \ + "You secure the external bolts.") + temp_state++ + if(1) + if(iswrench(O)) + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + src.anchored = 0 + user.visible_message("[user.name] detaches the [src.name] from the floor.", \ + "You remove the external bolts.") + temp_state-- + else if(iscoil(O)) + if(O:use(1)) + user.visible_message("[user.name] adds wires to the [src.name].", \ + "You add some wires.") + temp_state++ + if(2) + if(iswirecutter(O))//TODO:Shock user if its on? + user.visible_message("[user.name] removes some wires from the [src.name].", \ + "You remove some wires.") + temp_state-- + else if(isscrewdriver(O)) + user.visible_message("[user.name] closes the [src.name]'s access panel.", \ + "You close the access panel.") + temp_state++ + if(3) + if(isscrewdriver(O)) + user.visible_message("[user.name] opens the [src.name]'s access panel.", \ + "You open the access panel.") + temp_state-- + active = 0 + if(temp_state == src.construction_state)//Nothing changed + return 0 + else + if(src.construction_state < 3)//Was taken apart, update state + update_state() + if(use_power) + use_power = 0 + src.construction_state = temp_state + if(src.construction_state >= 3) + use_power = 1 + update_icon() + return 1 + return 0 diff --git a/code/modules/power/singularity/particle_accelerator/particle_chamber.dm b/code/modules/power/singularity/particle_accelerator/particle_chamber.dm index 4df3a92c469..f1e487b0b0c 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_chamber.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_chamber.dm @@ -1,10 +1,10 @@ -/obj/structure/particle_accelerator/fuel_chamber - name = "EM Acceleration Chamber" - desc_holder = "This is where the Alpha particles are accelerated to radical speeds." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "fuel_chamber" - reference = "fuel_chamber" - -/obj/structure/particle_accelerator/fuel_chamber/update_icon() - ..() +/obj/structure/particle_accelerator/fuel_chamber + name = "EM Acceleration Chamber" + desc_holder = "This is where the Alpha particles are accelerated to radical speeds." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "fuel_chamber" + reference = "fuel_chamber" + +/obj/structure/particle_accelerator/fuel_chamber/update_icon() + ..() return \ No newline at end of file diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index e2d596262ab..94198075f7f 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -1,281 +1,281 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/obj/machinery/particle_accelerator/control_box - name = "Particle Accelerator Control Computer" - desc = "This controls the density of the particles." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "control_box" - reference = "control_box" - anchored = 0 - density = 1 - use_power = 0 - idle_power_usage = 500 - active_power_usage = 10000 - construction_state = 0 - active = 0 - dir = 1 - var/strength_upper_limit = 2 - var/interface_control = 1 - var/list/obj/structure/particle_accelerator/connected_parts - var/assembled = 0 - var/parts = null - var/datum/wires/particle_acc/control_box/wires = null - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/particle_accelerator/control_box/New() - wires = new(src) - connected_parts = list() - ..() - -/obj/machinery/particle_accelerator/control_box/Destroy() - if(active) - toggle_power() - - if(wires) - qdel(wires) - wires = null - - ..() - -/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user as mob) - if(construction_state >= 3) - interact(user) - else if(construction_state == 2) // Wires exposed - wires.Interact(user) - -/obj/machinery/particle_accelerator/control_box/attackby(var/obj/item/I, var/mob/user) - if(istype(I,/obj/item/weapon/wirecutters)||istype(I,/obj/item/device/multitool)) - attack_hand(user) - ..() - -/obj/machinery/particle_accelerator/control_box/update_state() - if(construction_state < 3) - use_power = 0 - assembled = 0 - active = 0 - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = null - part.powered = 0 - part.update_icon() - connected_parts = list() - return - if(!part_scan()) - use_power = 1 - active = 0 - connected_parts = list() - - return - -/obj/machinery/particle_accelerator/control_box/update_icon() - if(active) - icon_state = "[reference]p1" - else - if(stat & NOPOWER) - icon_state = "[reference]w" - return - if(use_power) - if(assembled) - icon_state = "[reference]p" - else - icon_state = "u[reference]p" - else - switch(construction_state) - if(0) - icon_state = "[reference]" - if(1) - icon_state = "[reference]" - if(2) - icon_state = "[reference]w" - else - icon_state = "[reference]c" - return - -/obj/machinery/particle_accelerator/control_box/Topic(href, href_list) - if(..()) - return - - if(!interface_control) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/obj/machinery/particle_accelerator/control_box + name = "Particle Accelerator Control Computer" + desc = "This controls the density of the particles." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "control_box" + reference = "control_box" + anchored = 0 + density = 1 + use_power = 0 + idle_power_usage = 500 + active_power_usage = 10000 + construction_state = 0 + active = 0 + dir = 1 + var/strength_upper_limit = 2 + var/interface_control = 1 + var/list/obj/structure/particle_accelerator/connected_parts + var/assembled = 0 + var/parts = null + var/datum/wires/particle_acc/control_box/wires = null + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/particle_accelerator/control_box/New() + wires = new(src) + connected_parts = list() + ..() + +/obj/machinery/particle_accelerator/control_box/Destroy() + if(active) + toggle_power() + + if(wires) + qdel(wires) + wires = null + + ..() + +/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user as mob) + if(construction_state >= 3) + interact(user) + else if(construction_state == 2) // Wires exposed + wires.Interact(user) + +/obj/machinery/particle_accelerator/control_box/attackby(var/obj/item/I, var/mob/user) + if(istype(I,/obj/item/weapon/wirecutters)||istype(I,/obj/item/device/multitool)) + attack_hand(user) + ..() + +/obj/machinery/particle_accelerator/control_box/update_state() + if(construction_state < 3) + use_power = 0 + assembled = 0 + active = 0 + for(var/obj/structure/particle_accelerator/part in connected_parts) + part.strength = null + part.powered = 0 + part.update_icon() + connected_parts = list() + return + if(!part_scan()) + use_power = 1 + active = 0 + connected_parts = list() + + return + +/obj/machinery/particle_accelerator/control_box/update_icon() + if(active) + icon_state = "[reference]p1" + else + if(stat & NOPOWER) + icon_state = "[reference]w" + return + if(use_power) + if(assembled) + icon_state = "[reference]p" + else + icon_state = "u[reference]p" + else + switch(construction_state) + if(0) + icon_state = "[reference]" + if(1) + icon_state = "[reference]" + if(2) + icon_state = "[reference]w" + else + icon_state = "[reference]c" + return + +/obj/machinery/particle_accelerator/control_box/Topic(href, href_list) + if(..()) + return + + if(!interface_control) to_chat(usr, "ERROR: Request timed out. Check wire contacts.") - return - - if( href_list["close"] ) - usr << browse(null, "window=pacontrol") - usr.unset_machine() - return - if(href_list["togglep"]) - if(!wires.IsIndexCut(PARTICLE_TOGGLE_WIRE)) - src.toggle_power() - else if(href_list["scan"]) - src.part_scan() - else if(href_list["strengthup"]) - if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE)) - add_strength() - - else if(href_list["strengthdown"]) - if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE)) - remove_strength() - - src.updateDialog() - src.update_icon() - return - - -/obj/machinery/particle_accelerator/control_box/proc/strength_change() - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = strength - part.update_icon() - -/obj/machinery/particle_accelerator/control_box/proc/add_strength(var/s) - if(assembled) - strength++ - if(strength > strength_upper_limit) - strength = strength_upper_limit - else - message_admins("PA Control Computer increased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer increased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])") - investigation_log(I_SINGULO,"increased to [strength] by [usr.key]") - strength_change() - -/obj/machinery/particle_accelerator/control_box/proc/remove_strength(var/s) - if(assembled) - strength-- - if(strength < 0) - strength = 0 - else - investigation_log(I_SINGULO,"decreased to [strength] by [usr.key]") - strength_change() - -/obj/machinery/particle_accelerator/control_box/power_change() - ..() - if(stat & NOPOWER) - active = 0 - use_power = 0 - else if(!stat && construction_state <= 3) - use_power = 1 - src.update_icon() - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = null - part.powered = 0 - part.update_icon() - return - - - -/obj/machinery/particle_accelerator/control_box/process() - if(src.active) - //a part is missing! - if( length(connected_parts) < 6 ) - investigation_log(I_SINGULO,"lost a connected part; It powered down.") - src.toggle_power() - return - //emit some particles - for(var/obj/structure/particle_accelerator/particle_emitter/PE in connected_parts) - if(PE) - PE.emit_particle(src.strength) - return - - -/obj/machinery/particle_accelerator/control_box/proc/part_scan() - for(var/obj/structure/particle_accelerator/fuel_chamber/F in orange(1,src)) - src.dir = F.dir - connected_parts = list() - var/tally = 0 - var/ldir = turn(dir,-90) - var/rdir = turn(dir,90) - var/odir = turn(dir,180) - var/turf/T = src.loc - T = get_step(T,rdir) - if(check_part(T,/obj/structure/particle_accelerator/fuel_chamber)) - tally++ - T = get_step(T,odir) - if(check_part(T,/obj/structure/particle_accelerator/end_cap)) - tally++ - T = get_step(T,dir) - T = get_step(T,dir) - if(check_part(T,/obj/structure/particle_accelerator/power_box)) - tally++ - T = get_step(T,dir) - if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/center)) - tally++ - T = get_step(T,ldir) - if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/left)) - tally++ - T = get_step(T,rdir) - T = get_step(T,rdir) - if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/right)) - tally++ - if(tally >= 6) - assembled = 1 - return 1 - else - assembled = 0 - return 0 - - -/obj/machinery/particle_accelerator/control_box/proc/check_part(var/turf/T, var/type) - if(!(T)||!(type)) - return 0 - var/obj/structure/particle_accelerator/PA = locate(/obj/structure/particle_accelerator) in T - if(istype(PA, type)) - if(PA.connect_master(src)) - if(PA.report_ready(src)) - src.connected_parts.Add(PA) - return 1 - return 0 - - -/obj/machinery/particle_accelerator/control_box/proc/toggle_power() - src.active = !src.active - investigation_log(I_SINGULO,"turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]") - if (active) - message_admins("PA Control Computer turned ON by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer turned ON by [usr.ckey]([usr]) in ([x],[y],[z])") - if(src.active) - src.use_power = 2 - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = src.strength - part.powered = 1 - part.update_icon() - else - src.use_power = 1 - for(var/obj/structure/particle_accelerator/part in connected_parts) - part.strength = null - part.powered = 0 - part.update_icon() - return 1 - - -/obj/machinery/particle_accelerator/control_box/interact(mob/user) - if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) - if(!istype(user, /mob/living/silicon) && !isAdminGhost(user)) - if(!user.mutations || user.mutations.len || !(M_TK in user.mutations)) - user.unset_machine() - user << browse(null, "window=pacontrol") - return - user.set_machine(src) - - var/dat = "" - dat += "Close

    " - dat += "

    Status

    " - if(!assembled) - dat += "Unable to detect all parts!
    " - dat += "Run Scan

    " - else - dat += "All parts in place.

    " - dat += "Power:" - if(active) - dat += "On
    " - else - dat += "Off
    " - dat += "Toggle Power

    " - dat += "Particle Strength: [src.strength] " - dat += "--|++

    " - - //user << browse(dat, "window=pacontrol;size=420x500") - //onclose(user, "pacontrol") - var/datum/browser/popup = new(user, "pacontrol", name, 420, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() + return + + if( href_list["close"] ) + usr << browse(null, "window=pacontrol") + usr.unset_machine() + return + if(href_list["togglep"]) + if(!wires.IsIndexCut(PARTICLE_TOGGLE_WIRE)) + src.toggle_power() + else if(href_list["scan"]) + src.part_scan() + else if(href_list["strengthup"]) + if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE)) + add_strength() + + else if(href_list["strengthdown"]) + if(!wires.IsIndexCut(PARTICLE_STRENGTH_WIRE)) + remove_strength() + + src.updateDialog() + src.update_icon() + return + + +/obj/machinery/particle_accelerator/control_box/proc/strength_change() + for(var/obj/structure/particle_accelerator/part in connected_parts) + part.strength = strength + part.update_icon() + +/obj/machinery/particle_accelerator/control_box/proc/add_strength(var/s) + if(assembled) + strength++ + if(strength > strength_upper_limit) + strength = strength_upper_limit + else + message_admins("PA Control Computer increased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) + log_game("PA Control Computer increased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])") + investigation_log(I_SINGULO,"increased to [strength] by [usr.key]") + strength_change() + +/obj/machinery/particle_accelerator/control_box/proc/remove_strength(var/s) + if(assembled) + strength-- + if(strength < 0) + strength = 0 + else + investigation_log(I_SINGULO,"decreased to [strength] by [usr.key]") + strength_change() + +/obj/machinery/particle_accelerator/control_box/power_change() + ..() + if(stat & NOPOWER) + active = 0 + use_power = 0 + else if(!stat && construction_state <= 3) + use_power = 1 + src.update_icon() + for(var/obj/structure/particle_accelerator/part in connected_parts) + part.strength = null + part.powered = 0 + part.update_icon() + return + + + +/obj/machinery/particle_accelerator/control_box/process() + if(src.active) + //a part is missing! + if( length(connected_parts) < 6 ) + investigation_log(I_SINGULO,"lost a connected part; It powered down.") + src.toggle_power() + return + //emit some particles + for(var/obj/structure/particle_accelerator/particle_emitter/PE in connected_parts) + if(PE) + PE.emit_particle(src.strength) + return + + +/obj/machinery/particle_accelerator/control_box/proc/part_scan() + for(var/obj/structure/particle_accelerator/fuel_chamber/F in orange(1,src)) + src.dir = F.dir + connected_parts = list() + var/tally = 0 + var/ldir = turn(dir,-90) + var/rdir = turn(dir,90) + var/odir = turn(dir,180) + var/turf/T = src.loc + T = get_step(T,rdir) + if(check_part(T,/obj/structure/particle_accelerator/fuel_chamber)) + tally++ + T = get_step(T,odir) + if(check_part(T,/obj/structure/particle_accelerator/end_cap)) + tally++ + T = get_step(T,dir) + T = get_step(T,dir) + if(check_part(T,/obj/structure/particle_accelerator/power_box)) + tally++ + T = get_step(T,dir) + if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/center)) + tally++ + T = get_step(T,ldir) + if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/left)) + tally++ + T = get_step(T,rdir) + T = get_step(T,rdir) + if(check_part(T,/obj/structure/particle_accelerator/particle_emitter/right)) + tally++ + if(tally >= 6) + assembled = 1 + return 1 + else + assembled = 0 + return 0 + + +/obj/machinery/particle_accelerator/control_box/proc/check_part(var/turf/T, var/type) + if(!(T)||!(type)) + return 0 + var/obj/structure/particle_accelerator/PA = locate(/obj/structure/particle_accelerator) in T + if(istype(PA, type)) + if(PA.connect_master(src)) + if(PA.report_ready(src)) + src.connected_parts.Add(PA) + return 1 + return 0 + + +/obj/machinery/particle_accelerator/control_box/proc/toggle_power() + src.active = !src.active + investigation_log(I_SINGULO,"turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]") + if (active) + message_admins("PA Control Computer turned ON by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) + log_game("PA Control Computer turned ON by [usr.ckey]([usr]) in ([x],[y],[z])") + if(src.active) + src.use_power = 2 + for(var/obj/structure/particle_accelerator/part in connected_parts) + part.strength = src.strength + part.powered = 1 + part.update_icon() + else + src.use_power = 1 + for(var/obj/structure/particle_accelerator/part in connected_parts) + part.strength = null + part.powered = 0 + part.update_icon() + return 1 + + +/obj/machinery/particle_accelerator/control_box/interact(mob/user) + if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) + if(!istype(user, /mob/living/silicon) && !isAdminGhost(user)) + if(!user.mutations || user.mutations.len || !(M_TK in user.mutations)) + user.unset_machine() + user << browse(null, "window=pacontrol") + return + user.set_machine(src) + + var/dat = "" + dat += "Close

    " + dat += "

    Status

    " + if(!assembled) + dat += "Unable to detect all parts!
    " + dat += "Run Scan

    " + else + dat += "All parts in place.

    " + dat += "Power:" + if(active) + dat += "On
    " + else + dat += "Off
    " + dat += "Toggle Power

    " + dat += "Particle Strength: [src.strength] " + dat += "--|++

    " + + //user << browse(dat, "window=pacontrol;size=420x500") + //onclose(user, "pacontrol") + var/datum/browser/popup = new(user, "pacontrol", name, 420, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() return \ No newline at end of file diff --git a/code/modules/power/singularity/particle_accelerator/particle_emitter.dm b/code/modules/power/singularity/particle_accelerator/particle_emitter.dm index c04744c6cb5..d8eb025322d 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_emitter.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_emitter.dm @@ -1,52 +1,52 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/obj/structure/particle_accelerator/particle_emitter - name = "EM Containment Grid" - desc_holder = "This launchs the Alpha particles, might not want to stand near this end." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "none" - var/fire_delay = 50 - var/last_shot = 0 - -/obj/structure/particle_accelerator/particle_emitter/center - icon_state = "emitter_center" - reference = "emitter_center" - -/obj/structure/particle_accelerator/particle_emitter/left - icon_state = "emitter_left" - reference = "emitter_left" - -/obj/structure/particle_accelerator/particle_emitter/right - icon_state = "emitter_right" - reference = "emitter_right" - -/obj/structure/particle_accelerator/particle_emitter/update_icon() - ..() - return - -/obj/structure/particle_accelerator/particle_emitter/proc/set_delay(var/delay) - if(delay && delay >= 0) - src.fire_delay = delay - return 1 - return 0 - - -/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(var/strength = 0) - if((src.last_shot + src.fire_delay) <= world.time) - src.last_shot = world.time - var/obj/effect/accelerated_particle/A = null - var/turf/T = get_step(src,dir) - switch(strength) - if(0) - A = getFromPool(/obj/effect/accelerated_particle/weak,T) - if(1) - A = getFromPool(/obj/effect/accelerated_particle,T) - if(2) - A = getFromPool(/obj/effect/accelerated_particle/strong,T) - if(3) - A = getFromPool(/obj/effect/accelerated_particle/powerful,T) - if(A) - A.dir = src.dir - A.startMove(1) - return 1 - return 0 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/obj/structure/particle_accelerator/particle_emitter + name = "EM Containment Grid" + desc_holder = "This launchs the Alpha particles, might not want to stand near this end." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "none" + var/fire_delay = 50 + var/last_shot = 0 + +/obj/structure/particle_accelerator/particle_emitter/center + icon_state = "emitter_center" + reference = "emitter_center" + +/obj/structure/particle_accelerator/particle_emitter/left + icon_state = "emitter_left" + reference = "emitter_left" + +/obj/structure/particle_accelerator/particle_emitter/right + icon_state = "emitter_right" + reference = "emitter_right" + +/obj/structure/particle_accelerator/particle_emitter/update_icon() + ..() + return + +/obj/structure/particle_accelerator/particle_emitter/proc/set_delay(var/delay) + if(delay && delay >= 0) + src.fire_delay = delay + return 1 + return 0 + + +/obj/structure/particle_accelerator/particle_emitter/proc/emit_particle(var/strength = 0) + if((src.last_shot + src.fire_delay) <= world.time) + src.last_shot = world.time + var/obj/effect/accelerated_particle/A = null + var/turf/T = get_step(src,dir) + switch(strength) + if(0) + A = getFromPool(/obj/effect/accelerated_particle/weak,T) + if(1) + A = getFromPool(/obj/effect/accelerated_particle,T) + if(2) + A = getFromPool(/obj/effect/accelerated_particle/strong,T) + if(3) + A = getFromPool(/obj/effect/accelerated_particle/powerful,T) + if(A) + A.dir = src.dir + A.startMove(1) + return 1 + return 0 diff --git a/code/modules/power/singularity/particle_accelerator/particle_power.dm b/code/modules/power/singularity/particle_accelerator/particle_power.dm index a4dcb561e79..9d574a1cc87 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_power.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_power.dm @@ -1,10 +1,10 @@ -/obj/structure/particle_accelerator/power_box - name = "Particle Focusing EM Lens" - desc_holder = "This uses electromagnetic waves to focus the Alpha-Particles." - icon = 'icons/obj/machines/particle_accelerator2.dmi' - icon_state = "power_box" - reference = "power_box" - -/obj/structure/particle_accelerator/power_box/update_icon() - ..() - return +/obj/structure/particle_accelerator/power_box + name = "Particle Focusing EM Lens" + desc_holder = "This uses electromagnetic waves to focus the Alpha-Particles." + icon = 'icons/obj/machines/particle_accelerator2.dmi' + icon_state = "power_box" + reference = "power_box" + +/obj/structure/particle_accelerator/power_box/update_icon() + ..() + return diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 1537e2bc58b..3580dd2d873 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -1,572 +1,572 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -//Added spess ghoasts/cameras to this so they don't add to the lag. - N3X. - -//Added a singuloCanEat proc to atoms. This list is now kinda obsolete. -//var/global/list/uneatable = list( -// /obj/effect/overlay, -// /mob/dead, -// /mob/camera, -// /mob/new_player, -// ) - - -/obj/machinery/singularity/ - name = "gravitational singularity" //Lower case - desc = "The destructive, murderous Lord Singuloth, patron saint of Engineering. They harness its power to run the station's lighting and arcades." - icon = 'icons/obj/singularity.dmi' - icon_state = "singularity_s1" - anchored = 1 - density = 1 - layer = 6 - luminosity = 6 - unacidable = 1 //Don't comment this out. - use_power = 0 - - var/current_size = 1 - var/allowed_size = 1 - var/contained = 1 //Are we going to move around? - var/energy = 100 //How strong are we? - var/dissipate = 1 //Do we lose energy over time? - var/dissipate_delay = 10 - var/dissipate_track = 0 - var/dissipate_strength = 1 //How much energy do we lose? - var/move_self = 1 //Do we move on our own? - var/grav_pull = 4 //How many tiles out do we pull? - var/consume_range = 0 //How many tiles out do we eat. - var/event_chance = 15 //Prob for event each tick. - var/target = null //Its target. Moves towards the target if it has one. - var:last_movement_dir = 0 //Log the singularity's last movement to produce biased movement (singularity prefers constant movement due to inertia) - var/last_failed_movement = 0 //Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing. - var/last_warning - - var/chained = 0 //Adminbus chain-grab - -/obj/machinery/singularity/New(loc, var/starting_energy = 50, var/temp = 0) - //CARN: admin-alert for chuckle-fuckery. - admin_investigate_setup() - energy = starting_energy - - if(temp) - spawn(temp) - qdel(src) - - ..() - machines -= src - power_machines += src - for(var/obj/machinery/singularity_beacon/singubeacon in machines) - if(singubeacon.active) - target = singubeacon - break - -/obj/machinery/singularity/attack_hand(mob/user as mob) - consume(user) - return 1 - -/obj/machinery/singularity/blob_act(severity) - return - -/obj/machinery/singularity/ex_act(severity) - if(current_size == 11) //IT'S UNSTOPPABLE - return - switch(severity) - if(1.0) - if(prob(25)) - investigation_log(I_SINGULO, "has been destroyed by an explosion.") - qdel(src) - return - else - energy += 50 - if(2.0 to 3.0) - energy += round((rand(20, 60)/2), 1) - return - -/obj/machinery/singularity/bullet_act(obj/item/projectile/P) - return 0 //Will there be an impact? Who knows. Will we see it? No. - -/obj/machinery/singularity/Bump(atom/A) - consume(A) - -/obj/machinery/singularity/Bumped(atom/A) - consume(A) - -/obj/machinery/singularity/process() - eat() - dissipate() - check_energy() - - if(current_size >= 3) - move() - pulse() - - if(prob(event_chance)) //Chance for it to run a special event TODO: Come up with one or two more that fit. - event() - -/obj/machinery/singularity/attack_ai() //To prevent AIs from gibbing themselves when they click on one. - return - -/obj/machinery/singularity/proc/admin_investigate_setup() - last_warning = world.time - var/count = locate(/obj/machinery/containment_field) in orange(30, src) - - if(!count) - message_admins("A singulo has been created without containment fields active ([x], [y], [z] - JMP).") - - investigation_log(I_SINGULO,"was created. [count ? "" : "No containment fields were active."]") - -/obj/machinery/singularity/proc/dissipate() - if(!dissipate) - return - - if(dissipate_track >= dissipate_delay) - energy -= dissipate_strength - dissipate_track = 0 - else - dissipate_track++ - -/obj/machinery/singularity/proc/expand(var/force_size = 0, var/growing = 1) - if(current_size == 11) //If this is happening, this is an error - message_admins("expand() was called on a super singulo. This should not happen.") - return - var/temp_allowed_size = allowed_size - - if(force_size) - temp_allowed_size = force_size - - switch(temp_allowed_size) - if(STAGE_ONE) - current_size = 1 - icon = 'icons/obj/singularity.dmi' - icon_state = "singularity_s1" - pixel_x = 0 - pixel_y = 0 - grav_pull = 4 - consume_range = 0 - dissipate_delay = 10 - dissipate_track = 0 - dissipate_strength = 1 - overlays = 0 - if(chained) - overlays += "chain_s1" - visible_message("\The [src] shrinks to a rather pitiful size.") - if(STAGE_TWO) //1 to 3 does not check for the turfs if you put the gens right next to a 1x1 then its going to eat them. - current_size = 3 - icon = 'icons/effects/96x96.dmi' - icon_state = "singularity_s3" - pixel_x = -32 - pixel_y = -32 - grav_pull = 6 - consume_range = 1 - dissipate_delay = 5 - dissipate_track = 0 - dissipate_strength = 5 - overlays = 0 - if(chained) - overlays += "chain_s3" - if(growing) - visible_message("\The [src] noticeably grows in size.") - else - visible_message("\The [src] shrinks to a less powerful size.") - if(STAGE_THREE) - if((check_turfs_in(1, 2)) && (check_turfs_in(2, 2)) && (check_turfs_in(4, 2)) && (check_turfs_in(8, 2))) - current_size = 5 - icon = 'icons/effects/160x160.dmi' - icon_state = "singularity_s5" - pixel_x = -64 - pixel_y = -64 - grav_pull = 8 - consume_range = 2 - dissipate_delay = 4 - dissipate_track = 0 - dissipate_strength = 20 - overlays = 0 - if(chained) - overlays += "chain_s5" - if(growing) - visible_message("\The [src] expands to a reasonable size.") - else - visible_message("\The [src] has returned to a safe size.") - if(STAGE_FOUR) - if((check_turfs_in(1, 3)) && (check_turfs_in(2, 3)) && (check_turfs_in(4, 3)) && (check_turfs_in(8, 3))) - current_size = 7 - icon = 'icons/effects/224x224.dmi' - icon_state = "singularity_s7" - pixel_x = -96 - pixel_y = -96 - grav_pull = 10 - consume_range = 3 - dissipate_delay = 10 - dissipate_track = 0 - dissipate_strength = 10 - overlays = 0 - if(chained) - overlays += "chain_s7" - if(growing) - visible_message("\The [src] expands to a dangerous size.") - else - visible_message("Miraculously, \the [src] shrinks back to a containable size.") - if(STAGE_FIVE) //This one also lacks a check for gens because it eats everything. - current_size = 9 - icon = 'icons/effects/288x288.dmi' - icon_state = "singularity_s9" - pixel_x = -128 - pixel_y = -128 - grav_pull = 10 - consume_range = 4 - dissipate = 0 //It cant go smaller due to energy loss. - overlays = 0 - if(chained) - overlays += "chain_s9" - if(growing) - visible_message("\The [src] has grown out of control!") - else - visible_message("\The [src] miraculously shrinks and loses its supermatter properties.") - //Literally the only case where it should do that, can only be done by adminbus, so just reset its name and desc to default - name = initial(name) - desc = initial(desc) - if(STAGE_SUPER) //SUPERSINGULO - name = "super [name]" //Super version of whatever it was named. Shouldn't fire more than once - desc = "The final form of Lord Singuloth. It has the power to destroy worlds. It can most likely still be used to power arcades too, if you dare." - current_size = 11 - icon = 'icons/effects/352x352.dmi' - icon_state = "singularity_s11" //Uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo? - pixel_x = -160 - pixel_y = -160 - grav_pull = 16 - consume_range = 5 - dissipate = 0 //It cant go smaller due to e loss - event_chance = 25 //Events will fire off more often. - if(chained) - overlays += "chain_s9" - visible_message("You witness the creation of a destructive force that cannot possibly be stopped by human hands.") - - if(current_size == allowed_size) - investigation_log(I_SINGULO,"grew to size [current_size].") - return 1 - else if(current_size < (--temp_allowed_size) && current_size != 11) - expand(temp_allowed_size) - else - return 0 - -/obj/machinery/singularity/proc/check_energy() - if(energy <= 0) - investigation_log(I_SINGULO, "collapsed.") - qdel(src) - return 0 - - switch(energy) //Some of these numbers might need to be changed up later -Mport. - if(1 to 199) - allowed_size = 1 - if(200 to 499) - allowed_size = 3 - if(500 to 999) - allowed_size = 5 - if(1000 to 1999) - allowed_size = 7 - if(2000 to INFINITY) - allowed_size = 9 - - if(current_size != allowed_size && current_size != 11) - if(current_size > allowed_size) - expand(null, 0) - else - expand(null, 1) - return 1 - -/obj/machinery/singularity/proc/eat() - // This is causing issues. Do not renable - N3X - // Specifically, eat() builds up in the background from taking too long and eventually crashes the singo. - //set background = BACKGROUND_ENABLED - //var/ngrabbed=0 - for(var/atom/X in orange(grav_pull, src)) - if(X.type == /atom/movable/lighting_overlay)//since there's one on every turf - continue - // Caps grabbing shit at 100 items. - //if(ngrabbed==100) - //warning("Singularity eat() capped at [ngrabbed]") - //return - //if(!isturf(X))//a stage five singularity has a grav pull of 10, that means it covers 441 turfs (21x21) at every ticks. - //ngrabbed++ - try - var/dist = get_dist(X, src) - var/obj/machinery/singularity/S = src - if(!istype(src)) - return - if(dist > consume_range) - X.singularity_pull(S, current_size) - else if(dist <= consume_range) - consume(X) - catch(var/exception/e) - error("Singularity eat() caught exception:") - error(e) - continue - - //for(var/turf/T in trange(grav_pull, src)) // TODO: Create a similar trange for orange to prevent snowflake of self check. - // consume(T) - - //testing("Singularity eat() ate [ngrabbed] items.") - return -/* - * Singulo optimization. - * Jump out whenever we've made a decision. - */ -/obj/machinery/singularity/proc/canPull(const/atom/movable/A) - if(A && !A.anchored) - if(A.canSingulothPull(src)) - return 1 - - return 0 - -/obj/machinery/singularity/proc/consume(const/atom/A) - var/gain = A.singularity_act(current_size,src) - src.energy += gain - /*if(istype(A, /obj/)) - if(isbot(A)) - var/obj/machinery/bot/B = A - if(B.flags & INVULNERABLE) - return - else - src.energy += 20000//Instantly sends it to max size - SetUniversalState(/datum/universal_state/supermatter_cascade) //AND NOW YOU'RE FUCKED - expand(11, 1) - var/prints="" - if(A.fingerprintshidden) - prints=", all touchers: "+A.fingerprintshidden - - log_admin("New super singularity made by eating a SM crystal [prints]. Last touched by [A.fingerprintslast].") - message_admins("New super singularity made by eating a SM crystal [prints]. Last touched by [A.fingerprintslast].") - del(A) - return*/ - return - -/* - * Some modifications have been done in here. The Singularity's movement is now biased instead of truly random - * This means that if it isn't influcenced by a beacon, it will prefer the direction it last moved to - * In general, it's last movement has a 3/4th chance of being the next - */ -/obj/machinery/singularity/proc/move(var/force_move = 0) - if(!move_self) - return 0 - - var/movement_dir = pick(alldirs - last_failed_movement) - - if(force_move) //We are forcing the Singularity to move in a particular direction - movement_dir = force_move //Go this way - - if(!force_move && target && prob(66)) //Otherwise we have a singularity beacon online - movement_dir = get_dir(src,target) //Moves to a singulo beacon, if there is one - - if(!force_move && !target && last_failed_movement != last_movement_dir && prob(66)) //Otherwise we will perform a biased movement - movement_dir = last_movement_dir - - last_movement_dir = movement_dir //We have chosen our direction, log it - - if(current_size >= 9) //The superlarge one does not care about things in its way - spawn(0) - step(src, movement_dir) - spawn(1) - step(src, movement_dir) - return 1 - else if(check_turfs_in(movement_dir)) - last_failed_movement = 0 //Reset this because we moved - spawn(0) - step(src, movement_dir) - return 1 - else - last_failed_movement = movement_dir - return 0 - -/obj/machinery/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0) - if(!direction) - return 0 - var/steps = 0 - if(!step) - switch(current_size) - if(1) - steps = 1 - if(3) - steps = 3 //Yes this is right - if(5) - steps = 3 - if(7) - steps = 4 - if(9) - steps = 5 - if(11) - steps = 6 - else - steps = step - var/list/turfs = list() - var/turf/T = src.loc - for(var/i = 1 to steps) - T = get_step(T, direction) - if(!isturf(T)) - return 0 - turfs.Add(T) - var/dir2 = 0 - var/dir3 = 0 - switch(direction) - if(NORTH || SOUTH) - dir2 = 4 - dir3 = 8 - if(EAST || WEST) - dir2 = 1 - dir3 = 2 - var/turf/T2 = T - for(var/j = 1 to steps) - T2 = get_step(T2, dir2) - if(!isturf(T2)) - return 0 - turfs.Add(T2) - for(var/k = 1 to steps) - T = get_step(T, dir3) - if(!isturf(T)) - return 0 - turfs.Add(T) - for(var/turf/T3 in turfs) - if(isnull(T3)) - continue - if(!can_move(T3)) - return 0 - return 1 - -/obj/machinery/singularity/proc/can_move(const/turf/T) - if(!isturf(T)) - return 0 - - if((locate(/obj/machinery/containment_field) in T) || (locate(/obj/machinery/shieldwall) in T)) - return 0 - else if(locate(/obj/machinery/field_generator) in T) - var/obj/machinery/field_generator/G = locate(/obj/machinery/field_generator) in T - - if(G && G.active) - return 0 - else if(locate(/obj/machinery/shieldwallgen) in T) - var/obj/machinery/shieldwallgen/S = locate(/obj/machinery/shieldwallgen) in T - - if(S && S.active) - return 0 - return 1 - -/obj/machinery/singularity/proc/event() - var/numb = pick(1, 2, 3, 4, 5, 6) - - switch(numb) - if(1) //EMP. - emp_area() - if(2, 3) //Tox damage all carbon mobs in area. - toxmob() - if(4) //Stun mobs who lack optic scanners. - mezzer() - else - return 0 - if(current_size == 11) - smwave() - return 1 - - -/obj/machinery/singularity/proc/toxmob() - var/toxrange = 10 - var/toxdamage = 4 - var/radiation = 15 - var/radiationmin = 3 - if(src.energy > 200) - toxdamage = round(((src.energy-150)/50)*4,1) - radiation = round(((src.energy-150)/50)*5,1) - radiationmin = round((radiation/5),1) - for(var/mob/living/M in view(toxrange, src.loc)) - if(M.flags & INVULNERABLE) - continue - M.apply_effect(rand(radiationmin,radiation), IRRADIATE) - toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad"))) - M.apply_effect(toxdamage, TOX) - return - - -/obj/machinery/singularity/proc/mezzer() - for(var/mob/living/carbon/M in oviewers(8, src)) - if(istype(M, /mob/living/carbon/brain)) //Ignore brains - continue - if(M.flags & INVULNERABLE) - continue - if(M.stat == CONSCIOUS) - if(istype(M,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(istype(H.glasses,/obj/item/clothing/glasses/meson) && current_size != 11) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +//Added spess ghoasts/cameras to this so they don't add to the lag. - N3X. + +//Added a singuloCanEat proc to atoms. This list is now kinda obsolete. +//var/global/list/uneatable = list( +// /obj/effect/overlay, +// /mob/dead, +// /mob/camera, +// /mob/new_player, +// ) + + +/obj/machinery/singularity/ + name = "gravitational singularity" //Lower case + desc = "The destructive, murderous Lord Singuloth, patron saint of Engineering. They harness its power to run the station's lighting and arcades." + icon = 'icons/obj/singularity.dmi' + icon_state = "singularity_s1" + anchored = 1 + density = 1 + layer = 6 + luminosity = 6 + unacidable = 1 //Don't comment this out. + use_power = 0 + + var/current_size = 1 + var/allowed_size = 1 + var/contained = 1 //Are we going to move around? + var/energy = 100 //How strong are we? + var/dissipate = 1 //Do we lose energy over time? + var/dissipate_delay = 10 + var/dissipate_track = 0 + var/dissipate_strength = 1 //How much energy do we lose? + var/move_self = 1 //Do we move on our own? + var/grav_pull = 4 //How many tiles out do we pull? + var/consume_range = 0 //How many tiles out do we eat. + var/event_chance = 15 //Prob for event each tick. + var/target = null //Its target. Moves towards the target if it has one. + var:last_movement_dir = 0 //Log the singularity's last movement to produce biased movement (singularity prefers constant movement due to inertia) + var/last_failed_movement = 0 //Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing. + var/last_warning + + var/chained = 0 //Adminbus chain-grab + +/obj/machinery/singularity/New(loc, var/starting_energy = 50, var/temp = 0) + //CARN: admin-alert for chuckle-fuckery. + admin_investigate_setup() + energy = starting_energy + + if(temp) + spawn(temp) + qdel(src) + + ..() + machines -= src + power_machines += src + for(var/obj/machinery/singularity_beacon/singubeacon in machines) + if(singubeacon.active) + target = singubeacon + break + +/obj/machinery/singularity/attack_hand(mob/user as mob) + consume(user) + return 1 + +/obj/machinery/singularity/blob_act(severity) + return + +/obj/machinery/singularity/ex_act(severity) + if(current_size == 11) //IT'S UNSTOPPABLE + return + switch(severity) + if(1.0) + if(prob(25)) + investigation_log(I_SINGULO, "has been destroyed by an explosion.") + qdel(src) + return + else + energy += 50 + if(2.0 to 3.0) + energy += round((rand(20, 60)/2), 1) + return + +/obj/machinery/singularity/bullet_act(obj/item/projectile/P) + return 0 //Will there be an impact? Who knows. Will we see it? No. + +/obj/machinery/singularity/Bump(atom/A) + consume(A) + +/obj/machinery/singularity/Bumped(atom/A) + consume(A) + +/obj/machinery/singularity/process() + eat() + dissipate() + check_energy() + + if(current_size >= 3) + move() + pulse() + + if(prob(event_chance)) //Chance for it to run a special event TODO: Come up with one or two more that fit. + event() + +/obj/machinery/singularity/attack_ai() //To prevent AIs from gibbing themselves when they click on one. + return + +/obj/machinery/singularity/proc/admin_investigate_setup() + last_warning = world.time + var/count = locate(/obj/machinery/containment_field) in orange(30, src) + + if(!count) + message_admins("A singulo has been created without containment fields active ([x], [y], [z] - JMP).") + + investigation_log(I_SINGULO,"was created. [count ? "" : "No containment fields were active."]") + +/obj/machinery/singularity/proc/dissipate() + if(!dissipate) + return + + if(dissipate_track >= dissipate_delay) + energy -= dissipate_strength + dissipate_track = 0 + else + dissipate_track++ + +/obj/machinery/singularity/proc/expand(var/force_size = 0, var/growing = 1) + if(current_size == 11) //If this is happening, this is an error + message_admins("expand() was called on a super singulo. This should not happen.") + return + var/temp_allowed_size = allowed_size + + if(force_size) + temp_allowed_size = force_size + + switch(temp_allowed_size) + if(STAGE_ONE) + current_size = 1 + icon = 'icons/obj/singularity.dmi' + icon_state = "singularity_s1" + pixel_x = 0 + pixel_y = 0 + grav_pull = 4 + consume_range = 0 + dissipate_delay = 10 + dissipate_track = 0 + dissipate_strength = 1 + overlays = 0 + if(chained) + overlays += "chain_s1" + visible_message("\The [src] shrinks to a rather pitiful size.") + if(STAGE_TWO) //1 to 3 does not check for the turfs if you put the gens right next to a 1x1 then its going to eat them. + current_size = 3 + icon = 'icons/effects/96x96.dmi' + icon_state = "singularity_s3" + pixel_x = -32 + pixel_y = -32 + grav_pull = 6 + consume_range = 1 + dissipate_delay = 5 + dissipate_track = 0 + dissipate_strength = 5 + overlays = 0 + if(chained) + overlays += "chain_s3" + if(growing) + visible_message("\The [src] noticeably grows in size.") + else + visible_message("\The [src] shrinks to a less powerful size.") + if(STAGE_THREE) + if((check_turfs_in(1, 2)) && (check_turfs_in(2, 2)) && (check_turfs_in(4, 2)) && (check_turfs_in(8, 2))) + current_size = 5 + icon = 'icons/effects/160x160.dmi' + icon_state = "singularity_s5" + pixel_x = -64 + pixel_y = -64 + grav_pull = 8 + consume_range = 2 + dissipate_delay = 4 + dissipate_track = 0 + dissipate_strength = 20 + overlays = 0 + if(chained) + overlays += "chain_s5" + if(growing) + visible_message("\The [src] expands to a reasonable size.") + else + visible_message("\The [src] has returned to a safe size.") + if(STAGE_FOUR) + if((check_turfs_in(1, 3)) && (check_turfs_in(2, 3)) && (check_turfs_in(4, 3)) && (check_turfs_in(8, 3))) + current_size = 7 + icon = 'icons/effects/224x224.dmi' + icon_state = "singularity_s7" + pixel_x = -96 + pixel_y = -96 + grav_pull = 10 + consume_range = 3 + dissipate_delay = 10 + dissipate_track = 0 + dissipate_strength = 10 + overlays = 0 + if(chained) + overlays += "chain_s7" + if(growing) + visible_message("\The [src] expands to a dangerous size.") + else + visible_message("Miraculously, \the [src] shrinks back to a containable size.") + if(STAGE_FIVE) //This one also lacks a check for gens because it eats everything. + current_size = 9 + icon = 'icons/effects/288x288.dmi' + icon_state = "singularity_s9" + pixel_x = -128 + pixel_y = -128 + grav_pull = 10 + consume_range = 4 + dissipate = 0 //It cant go smaller due to energy loss. + overlays = 0 + if(chained) + overlays += "chain_s9" + if(growing) + visible_message("\The [src] has grown out of control!") + else + visible_message("\The [src] miraculously shrinks and loses its supermatter properties.") + //Literally the only case where it should do that, can only be done by adminbus, so just reset its name and desc to default + name = initial(name) + desc = initial(desc) + if(STAGE_SUPER) //SUPERSINGULO + name = "super [name]" //Super version of whatever it was named. Shouldn't fire more than once + desc = "The final form of Lord Singuloth. It has the power to destroy worlds. It can most likely still be used to power arcades too, if you dare." + current_size = 11 + icon = 'icons/effects/352x352.dmi' + icon_state = "singularity_s11" //Uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo? + pixel_x = -160 + pixel_y = -160 + grav_pull = 16 + consume_range = 5 + dissipate = 0 //It cant go smaller due to e loss + event_chance = 25 //Events will fire off more often. + if(chained) + overlays += "chain_s9" + visible_message("You witness the creation of a destructive force that cannot possibly be stopped by human hands.") + + if(current_size == allowed_size) + investigation_log(I_SINGULO,"grew to size [current_size].") + return 1 + else if(current_size < (--temp_allowed_size) && current_size != 11) + expand(temp_allowed_size) + else + return 0 + +/obj/machinery/singularity/proc/check_energy() + if(energy <= 0) + investigation_log(I_SINGULO, "collapsed.") + qdel(src) + return 0 + + switch(energy) //Some of these numbers might need to be changed up later -Mport. + if(1 to 199) + allowed_size = 1 + if(200 to 499) + allowed_size = 3 + if(500 to 999) + allowed_size = 5 + if(1000 to 1999) + allowed_size = 7 + if(2000 to INFINITY) + allowed_size = 9 + + if(current_size != allowed_size && current_size != 11) + if(current_size > allowed_size) + expand(null, 0) + else + expand(null, 1) + return 1 + +/obj/machinery/singularity/proc/eat() + // This is causing issues. Do not renable - N3X + // Specifically, eat() builds up in the background from taking too long and eventually crashes the singo. + //set background = BACKGROUND_ENABLED + //var/ngrabbed=0 + for(var/atom/X in orange(grav_pull, src)) + if(X.type == /atom/movable/lighting_overlay)//since there's one on every turf + continue + // Caps grabbing shit at 100 items. + //if(ngrabbed==100) + //warning("Singularity eat() capped at [ngrabbed]") + //return + //if(!isturf(X))//a stage five singularity has a grav pull of 10, that means it covers 441 turfs (21x21) at every ticks. + //ngrabbed++ + try + var/dist = get_dist(X, src) + var/obj/machinery/singularity/S = src + if(!istype(src)) + return + if(dist > consume_range) + X.singularity_pull(S, current_size) + else if(dist <= consume_range) + consume(X) + catch(var/exception/e) + error("Singularity eat() caught exception:") + error(e) + continue + + //for(var/turf/T in trange(grav_pull, src)) // TODO: Create a similar trange for orange to prevent snowflake of self check. + // consume(T) + + //testing("Singularity eat() ate [ngrabbed] items.") + return +/* + * Singulo optimization. + * Jump out whenever we've made a decision. + */ +/obj/machinery/singularity/proc/canPull(const/atom/movable/A) + if(A && !A.anchored) + if(A.canSingulothPull(src)) + return 1 + + return 0 + +/obj/machinery/singularity/proc/consume(const/atom/A) + var/gain = A.singularity_act(current_size,src) + src.energy += gain + /*if(istype(A, /obj/)) + if(isbot(A)) + var/obj/machinery/bot/B = A + if(B.flags & INVULNERABLE) + return + else + src.energy += 20000//Instantly sends it to max size + SetUniversalState(/datum/universal_state/supermatter_cascade) //AND NOW YOU'RE FUCKED + expand(11, 1) + var/prints="" + if(A.fingerprintshidden) + prints=", all touchers: "+A.fingerprintshidden + + log_admin("New super singularity made by eating a SM crystal [prints]. Last touched by [A.fingerprintslast].") + message_admins("New super singularity made by eating a SM crystal [prints]. Last touched by [A.fingerprintslast].") + del(A) + return*/ + return + +/* + * Some modifications have been done in here. The Singularity's movement is now biased instead of truly random + * This means that if it isn't influcenced by a beacon, it will prefer the direction it last moved to + * In general, it's last movement has a 3/4th chance of being the next + */ +/obj/machinery/singularity/proc/move(var/force_move = 0) + if(!move_self) + return 0 + + var/movement_dir = pick(alldirs - last_failed_movement) + + if(force_move) //We are forcing the Singularity to move in a particular direction + movement_dir = force_move //Go this way + + if(!force_move && target && prob(66)) //Otherwise we have a singularity beacon online + movement_dir = get_dir(src,target) //Moves to a singulo beacon, if there is one + + if(!force_move && !target && last_failed_movement != last_movement_dir && prob(66)) //Otherwise we will perform a biased movement + movement_dir = last_movement_dir + + last_movement_dir = movement_dir //We have chosen our direction, log it + + if(current_size >= 9) //The superlarge one does not care about things in its way + spawn(0) + step(src, movement_dir) + spawn(1) + step(src, movement_dir) + return 1 + else if(check_turfs_in(movement_dir)) + last_failed_movement = 0 //Reset this because we moved + spawn(0) + step(src, movement_dir) + return 1 + else + last_failed_movement = movement_dir + return 0 + +/obj/machinery/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0) + if(!direction) + return 0 + var/steps = 0 + if(!step) + switch(current_size) + if(1) + steps = 1 + if(3) + steps = 3 //Yes this is right + if(5) + steps = 3 + if(7) + steps = 4 + if(9) + steps = 5 + if(11) + steps = 6 + else + steps = step + var/list/turfs = list() + var/turf/T = src.loc + for(var/i = 1 to steps) + T = get_step(T, direction) + if(!isturf(T)) + return 0 + turfs.Add(T) + var/dir2 = 0 + var/dir3 = 0 + switch(direction) + if(NORTH || SOUTH) + dir2 = 4 + dir3 = 8 + if(EAST || WEST) + dir2 = 1 + dir3 = 2 + var/turf/T2 = T + for(var/j = 1 to steps) + T2 = get_step(T2, dir2) + if(!isturf(T2)) + return 0 + turfs.Add(T2) + for(var/k = 1 to steps) + T = get_step(T, dir3) + if(!isturf(T)) + return 0 + turfs.Add(T) + for(var/turf/T3 in turfs) + if(isnull(T3)) + continue + if(!can_move(T3)) + return 0 + return 1 + +/obj/machinery/singularity/proc/can_move(const/turf/T) + if(!isturf(T)) + return 0 + + if((locate(/obj/machinery/containment_field) in T) || (locate(/obj/machinery/shieldwall) in T)) + return 0 + else if(locate(/obj/machinery/field_generator) in T) + var/obj/machinery/field_generator/G = locate(/obj/machinery/field_generator) in T + + if(G && G.active) + return 0 + else if(locate(/obj/machinery/shieldwallgen) in T) + var/obj/machinery/shieldwallgen/S = locate(/obj/machinery/shieldwallgen) in T + + if(S && S.active) + return 0 + return 1 + +/obj/machinery/singularity/proc/event() + var/numb = pick(1, 2, 3, 4, 5, 6) + + switch(numb) + if(1) //EMP. + emp_area() + if(2, 3) //Tox damage all carbon mobs in area. + toxmob() + if(4) //Stun mobs who lack optic scanners. + mezzer() + else + return 0 + if(current_size == 11) + smwave() + return 1 + + +/obj/machinery/singularity/proc/toxmob() + var/toxrange = 10 + var/toxdamage = 4 + var/radiation = 15 + var/radiationmin = 3 + if(src.energy > 200) + toxdamage = round(((src.energy-150)/50)*4,1) + radiation = round(((src.energy-150)/50)*5,1) + radiationmin = round((radiation/5),1) + for(var/mob/living/M in view(toxrange, src.loc)) + if(M.flags & INVULNERABLE) + continue + M.apply_effect(rand(radiationmin,radiation), IRRADIATE) + toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad"))) + M.apply_effect(toxdamage, TOX) + return + + +/obj/machinery/singularity/proc/mezzer() + for(var/mob/living/carbon/M in oviewers(8, src)) + if(istype(M, /mob/living/carbon/brain)) //Ignore brains + continue + if(M.flags & INVULNERABLE) + continue + if(M.stat == CONSCIOUS) + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(istype(H.glasses,/obj/item/clothing/glasses/meson) && current_size != 11) to_chat(H, "You stare directly into \the [src], good thing you had your protective eyewear on!") - return - else + return + else to_chat(H, "You stare directly into \the [src] but your eyewear does absolutely nothing to protect you from it!") - M.visible_message("[M] stares blankly at \the [src]!", \ - "You stare directly into \the [src] and feel [current_size == 11 ? "helpless" : "weak"].") - M.apply_effect(3, STUN) - -/obj/machinery/singularity/proc/emp_area() - if(current_size != 11) - empulse(src, 8, 10) - else - empulse(src, 12, 16) - -/obj/machinery/singularity/proc/smwave() - for(var/mob/living/M in view(10, src.loc)) - if(prob(67)) - M.apply_effect(rand(energy), IRRADIATE) + M.visible_message("[M] stares blankly at \the [src]!", \ + "You stare directly into \the [src] and feel [current_size == 11 ? "helpless" : "weak"].") + M.apply_effect(3, STUN) + +/obj/machinery/singularity/proc/emp_area() + if(current_size != 11) + empulse(src, 8, 10) + else + empulse(src, 12, 16) + +/obj/machinery/singularity/proc/smwave() + for(var/mob/living/M in view(10, src.loc)) + if(prob(67)) + M.apply_effect(rand(energy), IRRADIATE) to_chat(M, "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.") to_chat(M, "Miraculously, it fails to kill you.") - else + else to_chat(M, "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.") to_chat(M, "You don't even have a moment to react as you are reduced to ashes by the intense radiation.") - M.dust() - return - -/obj/machinery/singularity/proc/pulse() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) - if(get_dist(R, src) <= 15) //Better than using orange() every process. - R.receive_pulse(energy) - -/obj/machinery/singularity/proc/on_capture() - chained = 1 - overlays = 0 - move_self = 0 - switch(current_size) - if(1) - overlays += image('icons/obj/singularity.dmi',"chain_s1") - if(3) - overlays += image('icons/effects/96x96.dmi',"chain_s3") - if(5) - overlays += image('icons/effects/160x160.dmi',"chain_s5") - if(7) - overlays += image('icons/effects/224x224.dmi',"chain_s7") - if(9) - overlays += image('icons/effects/288x288.dmi',"chain_s9") - -/obj/machinery/singularity/proc/on_release() - chained = 0 - overlays = 0 - move_self = 1 - -/obj/machinery/singularity/cultify() - var/dist = max((current_size - 2), 1) - explosion(get_turf(src), dist, dist * 2, dist * 4) - qdel(src) - -/obj/machinery/singularity/singularity_act(var/other_size=0) - if(other_size >= current_size) - var/gain = (energy/2) - var/dist = max((current_size - 2), 1) - explosion(src.loc,(dist),(dist*2),(dist*4)) - qdel(src) - return(gain) - return - -/obj/machinery/singularity/shuttle_act() //Shuttles can't kill the singularity honk - return - -/* -/obj/machinery/singularity/can_shuttle_move() //The days of destroying centcomm are gone - return -*/ //Fuck you centcomm - -/obj/machinery/singularity/Destroy() - ..() - power_machines -= src + M.dust() + return + +/obj/machinery/singularity/proc/pulse() + for(var/obj/machinery/power/rad_collector/R in rad_collectors) + if(get_dist(R, src) <= 15) //Better than using orange() every process. + R.receive_pulse(energy) + +/obj/machinery/singularity/proc/on_capture() + chained = 1 + overlays = 0 + move_self = 0 + switch(current_size) + if(1) + overlays += image('icons/obj/singularity.dmi',"chain_s1") + if(3) + overlays += image('icons/effects/96x96.dmi',"chain_s3") + if(5) + overlays += image('icons/effects/160x160.dmi',"chain_s5") + if(7) + overlays += image('icons/effects/224x224.dmi',"chain_s7") + if(9) + overlays += image('icons/effects/288x288.dmi',"chain_s9") + +/obj/machinery/singularity/proc/on_release() + chained = 0 + overlays = 0 + move_self = 1 + +/obj/machinery/singularity/cultify() + var/dist = max((current_size - 2), 1) + explosion(get_turf(src), dist, dist * 2, dist * 4) + qdel(src) + +/obj/machinery/singularity/singularity_act(var/other_size=0) + if(other_size >= current_size) + var/gain = (energy/2) + var/dist = max((current_size - 2), 1) + explosion(src.loc,(dist),(dist*2),(dist*4)) + qdel(src) + return(gain) + return + +/obj/machinery/singularity/shuttle_act() //Shuttles can't kill the singularity honk + return + +/* +/obj/machinery/singularity/can_shuttle_move() //The days of destroying centcomm are gone + return +*/ //Fuck you centcomm + +/obj/machinery/singularity/Destroy() + ..() + power_machines -= src diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 41c36e81a7e..c112fc0264f 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -1,111 +1,111 @@ -// the SMES -// stores power - -/obj/machinery/power/battery/smes - name = "power storage unit" - desc = "A high-capacity superconducting magnetic energy storage (SMES) unit." - icon_state = "smes" - density = 1 - anchored = 1 - use_power = 0 - - machine_flags = SCREWTOGGLE | CROWDESTROY - - starting_terminal = 1 - -/obj/machinery/power/battery/smes/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/smes, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - - - RefreshParts() - - if(ticker) - initialize() - -/obj/machinery/power/battery/smes/initialize() - ..() - if(!terminal) - stat |= BROKEN - -/obj/machinery/power/battery/smes/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) //these can only be moved by being reconstructed, solves having to remake the powernet. - if(iscrowbar(W) && panel_open && terminal) +// the SMES +// stores power + +/obj/machinery/power/battery/smes + name = "power storage unit" + desc = "A high-capacity superconducting magnetic energy storage (SMES) unit." + icon_state = "smes" + density = 1 + anchored = 1 + use_power = 0 + + machine_flags = SCREWTOGGLE | CROWDESTROY + + starting_terminal = 1 + +/obj/machinery/power/battery/smes/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/smes, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + + + RefreshParts() + + if(ticker) + initialize() + +/obj/machinery/power/battery/smes/initialize() + ..() + if(!terminal) + stat |= BROKEN + +/obj/machinery/power/battery/smes/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) //these can only be moved by being reconstructed, solves having to remake the powernet. + if(iscrowbar(W) && panel_open && terminal) to_chat(user, "You must first cut the terminal from the SMES!") - return 1 - if(..()) - return 1 - if(panel_open) - if(istype(W, /obj/item/stack/cable_coil) && !terminal) - var/obj/item/stack/cable_coil/CC = W - - if (CC.amount < 10) + return 1 + if(..()) + return 1 + if(panel_open) + if(istype(W, /obj/item/stack/cable_coil) && !terminal) + var/obj/item/stack/cable_coil/CC = W + + if (CC.amount < 10) to_chat(user, "You need 10 length cable coil to make a terminal.") - return - - if(make_terminal(user)) - CC.use(10) - terminal.connect_to_network() - - user.visible_message(\ - "[user.name] has added cables to the SMES!",\ - "You added cables the SMES.") - src.stat = 0 - return 1 - else if(istype(W, /obj/item/weapon/wirecutters) && terminal) - var/turf/T = get_turf(terminal) - if(T.intact) + return + + if(make_terminal(user)) + CC.use(10) + terminal.connect_to_network() + + user.visible_message(\ + "[user.name] has added cables to the SMES!",\ + "You added cables the SMES.") + src.stat = 0 + return 1 + else if(istype(W, /obj/item/weapon/wirecutters) && terminal) + var/turf/T = get_turf(terminal) + if(T.intact) to_chat(user, "You must remove the floor plating in front of the SMES first.") - return + return to_chat(user, "You begin to cut the cables...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - if (do_after(user, src, 50) && panel_open && terminal && !T.intact) - if (prob(50) && electrocute_mob(usr, terminal.get_powernet(), terminal)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - return - getFromPool(/obj/item/stack/cable_coil, get_turf(src), 10) - user.visible_message(\ - "[user.name] cut the cables and dismantled the power terminal.",\ - "You cut the cables and dismantle the power terminal.") - qdel(terminal) - terminal = null - else - user.set_machine(src) - interact(user) - return 1 - return - -/obj/machinery/power/battery/smes/can_attach_terminal(mob/user) - return ..(user) && panel_open - -/obj/machinery/power/battery/smes/surplus() - if(terminal) - return terminal.surplus() - return 0 - -/obj/machinery/power/battery/smes/add_load(var/amount) - if(terminal) - terminal.add_load(amount) - -/obj/machinery/power/battery/smes/infinite - name = "magical power storage unit" - desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Magically produces power." - - infinite_power = 1 - - mech_flags = MECH_SCAN_FAIL + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + if (do_after(user, src, 50) && panel_open && terminal && !T.intact) + if (prob(50) && electrocute_mob(usr, terminal.get_powernet(), terminal)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return + getFromPool(/obj/item/stack/cable_coil, get_turf(src), 10) + user.visible_message(\ + "[user.name] cut the cables and dismantled the power terminal.",\ + "You cut the cables and dismantle the power terminal.") + qdel(terminal) + terminal = null + else + user.set_machine(src) + interact(user) + return 1 + return + +/obj/machinery/power/battery/smes/can_attach_terminal(mob/user) + return ..(user) && panel_open + +/obj/machinery/power/battery/smes/surplus() + if(terminal) + return terminal.surplus() + return 0 + +/obj/machinery/power/battery/smes/add_load(var/amount) + if(terminal) + terminal.add_load(amount) + +/obj/machinery/power/battery/smes/infinite + name = "magical power storage unit" + desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Magically produces power." + + infinite_power = 1 + + mech_flags = MECH_SCAN_FAIL diff --git a/code/modules/power/terminal.dm b/code/modules/power/terminal.dm index f761d45542e..e559def3c58 100644 --- a/code/modules/power/terminal.dm +++ b/code/modules/power/terminal.dm @@ -1,78 +1,78 @@ -// the underfloor wiring terminal for the APC -// autogenerated when an APC is placed -// all conduit connects go to this object instead of the APC -// using this solves the problem of having the APC in a wall yet also inside an area - -/obj/machinery/power/terminal - name = "terminal" - icon_state = "term" - desc = "It's an underfloor wiring terminal for power equipment." - level = 1 - layer = TURF_LAYER - var/obj/machinery/power/master - anchored = 1 - layer = 2.6 // a bit above wires - - -/obj/machinery/power/terminal/New() - ..() - var/turf/T = src.loc - if(level==1) hide(T.intact) - return - - -/obj/machinery/power/terminal/hide(var/i) - if(i) - invisibility = 101 - icon_state = "term-f" - else - invisibility = 0 - icon_state = "term" - -/obj/machinery/power/terminal/Destroy() - if (master) - master:terminal = null - master = null - - ..() - -/obj/machinery/power/terminal/attackby(obj/item/W, mob/user) - if(iswirecutter(W) && !master) //Sanity in the rare case something destroys a machine and leaves a terminal - getFromPool(/obj/item/stack/cable_coil, get_turf(src), 10) - qdel(src) - return - ..() - -/obj/machinery/power/proc/make_terminal(mob/user) - if(!can_attach_terminal(user)) +// the underfloor wiring terminal for the APC +// autogenerated when an APC is placed +// all conduit connects go to this object instead of the APC +// using this solves the problem of having the APC in a wall yet also inside an area + +/obj/machinery/power/terminal + name = "terminal" + icon_state = "term" + desc = "It's an underfloor wiring terminal for power equipment." + level = 1 + layer = TURF_LAYER + var/obj/machinery/power/master + anchored = 1 + layer = 2.6 // a bit above wires + + +/obj/machinery/power/terminal/New() + ..() + var/turf/T = src.loc + if(level==1) hide(T.intact) + return + + +/obj/machinery/power/terminal/hide(var/i) + if(i) + invisibility = 101 + icon_state = "term-f" + else + invisibility = 0 + icon_state = "term" + +/obj/machinery/power/terminal/Destroy() + if (master) + master:terminal = null + master = null + + ..() + +/obj/machinery/power/terminal/attackby(obj/item/W, mob/user) + if(iswirecutter(W) && !master) //Sanity in the rare case something destroys a machine and leaves a terminal + getFromPool(/obj/item/stack/cable_coil, get_turf(src), 10) + qdel(src) + return + ..() + +/obj/machinery/power/proc/make_terminal(mob/user) + if(!can_attach_terminal(user)) to_chat(user, "You can't wire \the [src] like that!") - return 0 - - var/turf/T = get_turf(user) - if(T.intact) + return 0 + + var/turf/T = get_turf(user) + if(T.intact) to_chat(user, "The floor plating must be removed first.") - return 0 - + return 0 + to_chat(user, "You start adding cable to \the [src].") - playsound(get_turf(src), 'sound/items/zip.ogg', 100, 1) - if (do_after(user, src, 100) && !T.intact && can_attach_terminal(user)) - - //Shock chance - var/obj/structure/cable/N = T.get_cable_node() - if (prob(50) && electrocute_mob(user, N, N)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - return 0 - - finalise_terminal(get_turf(user)) - return 1 - return 0 - -/obj/machinery/power/proc/finalise_terminal(newloc) - terminal = new /obj/machinery/power/terminal(newloc) - terminal.dir = get_dir(newloc, src) - terminal.master = src - -/obj/machinery/power/proc/can_attach_terminal(mob/user) - return user.loc != src.loc && (get_dir(user, src) in cardinal) && !terminal + playsound(get_turf(src), 'sound/items/zip.ogg', 100, 1) + if (do_after(user, src, 100) && !T.intact && can_attach_terminal(user)) + + //Shock chance + var/obj/structure/cable/N = T.get_cable_node() + if (prob(50) && electrocute_mob(user, N, N)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return 0 + + finalise_terminal(get_turf(user)) + return 1 + return 0 + +/obj/machinery/power/proc/finalise_terminal(newloc) + terminal = new /obj/machinery/power/terminal(newloc) + terminal.dir = get_dir(newloc, src) + terminal.master = src + +/obj/machinery/power/proc/can_attach_terminal(mob/user) + return user.loc != src.loc && (get_dir(user, src) in cardinal) && !terminal diff --git a/code/modules/power/treadmill.dm b/code/modules/power/treadmill.dm index bf9de64342b..24eb8a2d322 100644 --- a/code/modules/power/treadmill.dm +++ b/code/modules/power/treadmill.dm @@ -1,88 +1,88 @@ -//The ultimate in green energy, a treadmill generates very low power each time it is bumped, which also updates its icon -//to move. You can still optimize this, though, by making yourself a workout machine -- be full, have sugar, -//have sports drink, have a high movespeed, have HULK as a mutation. -//Doesn't consume any idle power, you must Bump() it from its own square. Bump works like a window. -//Using a treadmill uses up hunger faster - -#define DEFAULT_BUMP_ENERGY 400 - -/obj/machinery/power/treadmill - name = "treadmill generator" - desc = "A low-power device that generates power based on how quickly someone walks." - icon_state = "treadmill" - density = 1 - flags = ON_BORDER - machine_flags = SCREWTOGGLE | WRENCHMOVE - anchored = 1 - use_power = 0 - idle_power_usage = 0 - var/count_power = 0 //How much power have we produced SO FAR this count? - var/tick_power = 0 //How much power did we produce last count? - var/power_efficiency = 1 //Based on parts - component_parts = newlist( - /obj/item/weapon/circuitboard/treadmill, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/console_screen - ) - -/obj/machinery/power/treadmill/New() - if(anchored) connect_to_network() - RefreshParts() - ..() - -/obj/machinery/power/treadmill/RefreshParts() - var/calc = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/capacitor)) calc+=SP.rating - power_efficiency = calc/4 //Possible results 1, 2, and 3 -- basically, what tier we have - -/obj/machinery/power/treadmill/examine(mob/user as mob) - ..() +//The ultimate in green energy, a treadmill generates very low power each time it is bumped, which also updates its icon +//to move. You can still optimize this, though, by making yourself a workout machine -- be full, have sugar, +//have sports drink, have a high movespeed, have HULK as a mutation. +//Doesn't consume any idle power, you must Bump() it from its own square. Bump works like a window. +//Using a treadmill uses up hunger faster + +#define DEFAULT_BUMP_ENERGY 400 + +/obj/machinery/power/treadmill + name = "treadmill generator" + desc = "A low-power device that generates power based on how quickly someone walks." + icon_state = "treadmill" + density = 1 + flags = ON_BORDER + machine_flags = SCREWTOGGLE | WRENCHMOVE + anchored = 1 + use_power = 0 + idle_power_usage = 0 + var/count_power = 0 //How much power have we produced SO FAR this count? + var/tick_power = 0 //How much power did we produce last count? + var/power_efficiency = 1 //Based on parts + component_parts = newlist( + /obj/item/weapon/circuitboard/treadmill, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/console_screen + ) + +/obj/machinery/power/treadmill/New() + if(anchored) connect_to_network() + RefreshParts() + ..() + +/obj/machinery/power/treadmill/RefreshParts() + var/calc = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/capacitor)) calc+=SP.rating + power_efficiency = calc/4 //Possible results 1, 2, and 3 -- basically, what tier we have + +/obj/machinery/power/treadmill/examine(mob/user as mob) + ..() to_chat(user, "During the last cycle, it produced [tick_power] watts.") - -/obj/machinery/power/treadmill/process() - tick_power = count_power - count_power = 0 - add_avail(tick_power) - -/obj/machinery/power/treadmill/proc/powerwalk(atom/movable/AM as mob) - if(!ismob(AM)) return //Can't walk on a treadmill if you aren't animated - if(get_turf(AM) != loc) return //Can't bump from the outside - var/mob/runner = AM - if(!istype(runner,/mob/living/simple_animal)&&runner.bodytemperature <= 360) - runner.bodytemperature += 2 //Same heating pattern as being fat - if(runner.nutrition && runner.stat != DEAD) - runner.nutrition -= HUNGER_FACTOR*2 //Running on a treadmill makes you hungry fast - flick("treadmill-running", src) - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) - var/calc = DEFAULT_BUMP_ENERGY * power_efficiency * runner.treadmill_speed - if(runner.reagents) //Sanity - for(var/datum/reagent/R in runner.reagents.reagent_list) - calc *= R.sport - if(M_HULK in runner.mutations) calc *= 5 - count_power += calc - -/obj/machinery/power/treadmill/CheckExit(var/atom/movable/O, var/turf/target) - if(istype(O) && O.checkpass(PASSGLASS)) - return 1 - if(get_dir(O.loc, target) == dir) - powerwalk(O) - return 0 - return 1 - -/obj/machinery/power/treadmill/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) - if(air_group) return 1 - return 0 - else - return 1 - -/obj/machinery/power/treadmill/wrenchAnchor(mob/user) - ..() - if(anchored) connect_to_network() - else disconnect_from_network() + +/obj/machinery/power/treadmill/process() + tick_power = count_power + count_power = 0 + add_avail(tick_power) + +/obj/machinery/power/treadmill/proc/powerwalk(atom/movable/AM as mob) + if(!ismob(AM)) return //Can't walk on a treadmill if you aren't animated + if(get_turf(AM) != loc) return //Can't bump from the outside + var/mob/runner = AM + if(!istype(runner,/mob/living/simple_animal)&&runner.bodytemperature <= 360) + runner.bodytemperature += 2 //Same heating pattern as being fat + if(runner.nutrition && runner.stat != DEAD) + runner.nutrition -= HUNGER_FACTOR*2 //Running on a treadmill makes you hungry fast + flick("treadmill-running", src) + playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + var/calc = DEFAULT_BUMP_ENERGY * power_efficiency * runner.treadmill_speed + if(runner.reagents) //Sanity + for(var/datum/reagent/R in runner.reagents.reagent_list) + calc *= R.sport + if(M_HULK in runner.mutations) calc *= 5 + count_power += calc + +/obj/machinery/power/treadmill/CheckExit(var/atom/movable/O, var/turf/target) + if(istype(O) && O.checkpass(PASSGLASS)) + return 1 + if(get_dir(O.loc, target) == dir) + powerwalk(O) + return 0 + return 1 + +/obj/machinery/power/treadmill/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) + if(air_group) return 1 + return 0 + else + return 1 + +/obj/machinery/power/treadmill/wrenchAnchor(mob/user) + ..() + if(anchored) connect_to_network() + else disconnect_from_network() diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index ca37c2bde25..3afffb3b6f1 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -1,312 +1,312 @@ -/obj/machinery/compressor - name = "compressor" - desc = "The compressor stage of a gas turbine generator." - icon = 'icons/obj/pipes.dmi' - icon_state = "compressor" - anchored = 1 - density = 1 - var/obj/machinery/power/turbine/turbine - var/datum/gas_mixture/gas_contained - var/turf/simulated/inturf - var/starter = 0 - var/rpm = 0 - var/rpmtarget = 0 - var/capacity = 1e6 - var/comp_id = 0 - -/obj/machinery/power/turbine - name = "gas turbine generator" - desc = "A gas turbine used for backup power generation." - icon = 'icons/obj/pipes.dmi' - icon_state = "turbine" - anchored = 1 - density = 1 - var/obj/machinery/compressor/compressor - var/turf/simulated/outturf - var/lastgen - -/obj/machinery/computer/turbine_computer - name = "Gas turbine control computer" - desc = "A computer to remotely control a gas turbine" - icon = 'icons/obj/computer.dmi' - icon_state = "airtunnel0e" - anchored = 1 - density = 1 - var/obj/machinery/compressor/compressor - var/list/obj/machinery/door/poddoor/doors - var/id_tag = 0 - var/door_status = 0 - - light_color = LIGHT_COLOR_BLUE - -// the inlet stage of the gas turbine electricity generator - -/obj/machinery/compressor/New() - ..() - - gas_contained = new - inturf = get_step(src, dir) - - spawn(5) - turbine = locate() in get_step(src, get_dir(inturf, src)) - if(!turbine) - stat |= BROKEN - - -#define COMPFRICTION 5e5 -#define COMPSTARTERLOAD 2800 - -/obj/machinery/compressor/process() - if(!starter) - return - overlays.len = 0 - if(stat & BROKEN) - return - if(!turbine) - stat |= BROKEN - return - rpm = 0.9* rpm + 0.1 * rpmtarget - var/datum/gas_mixture/environment = inturf.return_air() - var/transfer_moles = environment.total_moles()/10 - //var/transfer_moles = rpm/10000*capacity - var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles) - gas_contained.merge(removed) - - rpm = max(0, rpm - (rpm*rpm)/COMPFRICTION) - - - if(starter && !(stat & NOPOWER)) - use_power(2800) - if(rpm<1000) - rpmtarget = 1000 - else - if(rpm<1000) - rpmtarget = 0 - - - - if(rpm>50000) - overlays += image('icons/obj/pipes.dmi', "comp-o4", FLY_LAYER) - else if(rpm>10000) - overlays += image('icons/obj/pipes.dmi', "comp-o3", FLY_LAYER) - else if(rpm>2000) - overlays += image('icons/obj/pipes.dmi', "comp-o2", FLY_LAYER) - else if(rpm>500) - overlays += image('icons/obj/pipes.dmi', "comp-o1", FLY_LAYER) - //TODO: DEFERRED - -/obj/machinery/power/turbine/New() - ..() - - outturf = get_step(src, dir) - - spawn(5) - - compressor = locate() in get_step(src, get_dir(outturf, src)) - if(!compressor) - stat |= BROKEN - - -#define TURBPRES 9000000 -#define TURBGENQ 20000 -#define TURBGENG 0.8 - -/obj/machinery/power/turbine/process() - if(!compressor.starter) - return - overlays.len = 0 - if(stat & BROKEN) - return - if(!compressor) - stat |= BROKEN - return - lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) *TURBGENQ - - add_avail(lastgen) - var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4 - newrpm = max(0, newrpm) - - if(!compressor.starter || newrpm > 1000) - compressor.rpmtarget = newrpm - - if(compressor.gas_contained.total_moles()>0) - var/oamount = min(compressor.gas_contained.total_moles(), (compressor.rpm+100)/35000*compressor.capacity) - var/datum/gas_mixture/removed = compressor.gas_contained.remove(oamount) - outturf.assume_air(removed) - - if(lastgen > 100) - overlays += image('icons/obj/pipes.dmi', "turb-o", FLY_LAYER) - - - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.interact(M) - AutoUpdateAI(src) - -/obj/machinery/power/turbine/interact(mob/user) - - if ( (get_dist(src, user) > 1 ) || (stat & (NOPOWER|BROKEN)) && (!istype(user, /mob/living/silicon/ai)) ) - user.machine = null - user << browse(null, "window=turbine") - return - - user.machine = src - - var/t = "Gas Turbine Generator
    "
    -
    -
    -	// AUTOFIXED BY fix_string_idiocy.py
    -	// C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\\power\turbine.dm:156: t += "Generated power : [round(lastgen)] W

    " - t += {"Generated power : [round(lastgen)] W

    - Turbine: [round(compressor.rpm)] RPM
    - Starter: [ compressor.starter ? "Off On" : "Off On"] -

    Close -
    "} - // END AUTOFIX - user << browse(t, "window=turbine") - onclose(user, "turbine") - - return - -/obj/machinery/power/turbine/Topic(href, href_list) - if(!isAI(usr) && usr.z != z) return 1 - ..() - if(stat & BROKEN) - return - if (usr.stat || usr.restrained() ) - return - if (!usr.dexterity_check()) +/obj/machinery/compressor + name = "compressor" + desc = "The compressor stage of a gas turbine generator." + icon = 'icons/obj/pipes.dmi' + icon_state = "compressor" + anchored = 1 + density = 1 + var/obj/machinery/power/turbine/turbine + var/datum/gas_mixture/gas_contained + var/turf/simulated/inturf + var/starter = 0 + var/rpm = 0 + var/rpmtarget = 0 + var/capacity = 1e6 + var/comp_id = 0 + +/obj/machinery/power/turbine + name = "gas turbine generator" + desc = "A gas turbine used for backup power generation." + icon = 'icons/obj/pipes.dmi' + icon_state = "turbine" + anchored = 1 + density = 1 + var/obj/machinery/compressor/compressor + var/turf/simulated/outturf + var/lastgen + +/obj/machinery/computer/turbine_computer + name = "Gas turbine control computer" + desc = "A computer to remotely control a gas turbine" + icon = 'icons/obj/computer.dmi' + icon_state = "airtunnel0e" + anchored = 1 + density = 1 + var/obj/machinery/compressor/compressor + var/list/obj/machinery/door/poddoor/doors + var/id_tag = 0 + var/door_status = 0 + + light_color = LIGHT_COLOR_BLUE + +// the inlet stage of the gas turbine electricity generator + +/obj/machinery/compressor/New() + ..() + + gas_contained = new + inturf = get_step(src, dir) + + spawn(5) + turbine = locate() in get_step(src, get_dir(inturf, src)) + if(!turbine) + stat |= BROKEN + + +#define COMPFRICTION 5e5 +#define COMPSTARTERLOAD 2800 + +/obj/machinery/compressor/process() + if(!starter) + return + overlays.len = 0 + if(stat & BROKEN) + return + if(!turbine) + stat |= BROKEN + return + rpm = 0.9* rpm + 0.1 * rpmtarget + var/datum/gas_mixture/environment = inturf.return_air() + var/transfer_moles = environment.total_moles()/10 + //var/transfer_moles = rpm/10000*capacity + var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles) + gas_contained.merge(removed) + + rpm = max(0, rpm - (rpm*rpm)/COMPFRICTION) + + + if(starter && !(stat & NOPOWER)) + use_power(2800) + if(rpm<1000) + rpmtarget = 1000 + else + if(rpm<1000) + rpmtarget = 0 + + + + if(rpm>50000) + overlays += image('icons/obj/pipes.dmi', "comp-o4", FLY_LAYER) + else if(rpm>10000) + overlays += image('icons/obj/pipes.dmi', "comp-o3", FLY_LAYER) + else if(rpm>2000) + overlays += image('icons/obj/pipes.dmi', "comp-o2", FLY_LAYER) + else if(rpm>500) + overlays += image('icons/obj/pipes.dmi', "comp-o1", FLY_LAYER) + //TODO: DEFERRED + +/obj/machinery/power/turbine/New() + ..() + + outturf = get_step(src, dir) + + spawn(5) + + compressor = locate() in get_step(src, get_dir(outturf, src)) + if(!compressor) + stat |= BROKEN + + +#define TURBPRES 9000000 +#define TURBGENQ 20000 +#define TURBGENG 0.8 + +/obj/machinery/power/turbine/process() + if(!compressor.starter) + return + overlays.len = 0 + if(stat & BROKEN) + return + if(!compressor) + stat |= BROKEN + return + lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) *TURBGENQ + + add_avail(lastgen) + var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4 + newrpm = max(0, newrpm) + + if(!compressor.starter || newrpm > 1000) + compressor.rpmtarget = newrpm + + if(compressor.gas_contained.total_moles()>0) + var/oamount = min(compressor.gas_contained.total_moles(), (compressor.rpm+100)/35000*compressor.capacity) + var/datum/gas_mixture/removed = compressor.gas_contained.remove(oamount) + outturf.assume_air(removed) + + if(lastgen > 100) + overlays += image('icons/obj/pipes.dmi', "turb-o", FLY_LAYER) + + + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.interact(M) + AutoUpdateAI(src) + +/obj/machinery/power/turbine/interact(mob/user) + + if ( (get_dist(src, user) > 1 ) || (stat & (NOPOWER|BROKEN)) && (!istype(user, /mob/living/silicon/ai)) ) + user.machine = null + user << browse(null, "window=turbine") + return + + user.machine = src + + var/t = "Gas Turbine Generator
    "
    +
    +
    +	// AUTOFIXED BY fix_string_idiocy.py
    +	// C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\\\power\turbine.dm:156: t += "Generated power : [round(lastgen)] W

    " + t += {"Generated power : [round(lastgen)] W

    + Turbine: [round(compressor.rpm)] RPM
    + Starter: [ compressor.starter ? "Off On" : "Off On"] +

    Close +
    "} + // END AUTOFIX + user << browse(t, "window=turbine") + onclose(user, "turbine") + + return + +/obj/machinery/power/turbine/Topic(href, href_list) + if(!isAI(usr) && usr.z != z) return 1 + ..() + if(stat & BROKEN) + return + if (usr.stat || usr.restrained() ) + return + if (!usr.dexterity_check()) to_chat(usr, "You don't have the dexterity to do this!") - return - - if (( usr.machine==src && ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) - - - if( href_list["close"] ) - usr << browse(null, "window=turbine") - usr.machine = null - return - - else if( href_list["str"] ) - compressor.starter = !compressor.starter - - spawn(0) - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.interact(M) - - else - usr << browse(null, "window=turbine") - usr.machine = null - - return - - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - -/obj/machinery/computer/turbine_computer/New() - ..() - spawn(5) - for(var/obj/machinery/compressor/C in machines) - if(id_tag == C.comp_id) - compressor = C - doors = new /list() - for(var/obj/machinery/door/poddoor/P in poddoors) - if(P.id_tag == id_tag) - doors += P - -/obj/machinery/computer/turbine_computer/attackby(I as obj, user as mob) - if(istype(I, /obj/item/weapon/screwdriver)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 20)) - if (src.stat & BROKEN) + return + + if (( usr.machine==src && ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) + + + if( href_list["close"] ) + usr << browse(null, "window=turbine") + usr.machine = null + return + + else if( href_list["str"] ) + compressor.starter = !compressor.starter + + spawn(0) + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.interact(M) + + else + usr << browse(null, "window=turbine") + usr.machine = null + + return + + + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + +/obj/machinery/computer/turbine_computer/New() + ..() + spawn(5) + for(var/obj/machinery/compressor/C in machines) + if(id_tag == C.comp_id) + compressor = C + doors = new /list() + for(var/obj/machinery/door/poddoor/P in poddoors) + if(P.id_tag == id_tag) + doors += P + +/obj/machinery/computer/turbine_computer/attackby(I as obj, user as mob) + if(istype(I, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 20)) + if (src.stat & BROKEN) to_chat(user, "The broken glass falls out.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - getFromPool(/obj/item/weapon/shard, loc) - var/obj/item/weapon/circuitboard/turbine_control/M = new /obj/item/weapon/circuitboard/turbine_control( A ) - for (var/obj/C in src) - C.loc = src.loc - M.id_tag = src.id_tag - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - qdel(src) - else + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) + var/obj/item/weapon/circuitboard/turbine_control/M = new /obj/item/weapon/circuitboard/turbine_control( A ) + for (var/obj/C in src) + C.loc = src.loc + M.id_tag = src.id_tag + A.circuit = M + A.state = 3 + A.icon_state = "3" + A.anchored = 1 + qdel(src) + else to_chat(user, "You disconnect the monitor.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/turbine_control/M = new /obj/item/weapon/circuitboard/turbine_control( A ) - for (var/obj/C in src) - C.loc = src.loc - M.id_tag = src.id_tag - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - qdel(src) - else - src.attack_hand(user) - return - -/obj/machinery/computer/turbine_computer/attack_hand(var/mob/user as mob) - user.machine = src - var/dat - if(src.compressor) - dat += {"
    Gas turbine remote control system
    - \nTurbine status: [ src.compressor.starter ? "Off On" : "Off On"] - \n
    - \nTurbine speed: [src.compressor.rpm]rpm
    - \nPower currently being generated: [src.compressor.turbine.lastgen]W
    - \nInternal gas temperature: [src.compressor.gas_contained.temperature]K
    - \nVent doors: [ src.door_status ? "Closed Open" : "Closed Open"] - \n
    View - \n
    Close - \n
    - \n"} - else - dat += "No compatible attached compressor found." - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - - - -/obj/machinery/computer/turbine_computer/Topic(href, href_list) - if(..()) - return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.machine = src - - if( href_list["view"] ) - usr.client.eye = src.compressor - else if( href_list["str"] ) - src.compressor.starter = !src.compressor.starter - else if (href_list["doors"]) - for(var/obj/machinery/door/poddoor/D in src.doors) - if (door_status == 0) - spawn( 0 ) - D.open() - door_status = 1 - else - spawn( 0 ) - D.close() - door_status = 0 - else if( href_list["close"] ) - usr << browse(null, "window=computer") - usr.machine = null - return - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer/turbine_computer/process() - src.updateDialog() - return + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + var/obj/item/weapon/circuitboard/turbine_control/M = new /obj/item/weapon/circuitboard/turbine_control( A ) + for (var/obj/C in src) + C.loc = src.loc + M.id_tag = src.id_tag + A.circuit = M + A.state = 4 + A.icon_state = "4" + A.anchored = 1 + qdel(src) + else + src.attack_hand(user) + return + +/obj/machinery/computer/turbine_computer/attack_hand(var/mob/user as mob) + user.machine = src + var/dat + if(src.compressor) + dat += {"
    Gas turbine remote control system
    + \nTurbine status: [ src.compressor.starter ? "Off On" : "Off On"] + \n
    + \nTurbine speed: [src.compressor.rpm]rpm
    + \nPower currently being generated: [src.compressor.turbine.lastgen]W
    + \nInternal gas temperature: [src.compressor.gas_contained.temperature]K
    + \nVent doors: [ src.door_status ? "Closed Open" : "Closed Open"] + \n
    View + \n
    Close + \n
    + \n"} + else + dat += "No compatible attached compressor found." + + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + + + +/obj/machinery/computer/turbine_computer/Topic(href, href_list) + if(..()) + return + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.machine = src + + if( href_list["view"] ) + usr.client.eye = src.compressor + else if( href_list["str"] ) + src.compressor.starter = !src.compressor.starter + else if (href_list["doors"]) + for(var/obj/machinery/door/poddoor/D in src.doors) + if (door_status == 0) + spawn( 0 ) + D.open() + door_status = 1 + else + spawn( 0 ) + D.close() + door_status = 0 + else if( href_list["close"] ) + usr << browse(null, "window=computer") + usr.machine = null + return + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + +/obj/machinery/computer/turbine_computer/process() + src.updateDialog() + return diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 81c9a5eec46..60696421e99 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -1,204 +1,204 @@ -/obj/item/ammo_casing - name = "bullet casing" - desc = "A bullet casing." - icon = 'icons/obj/ammo.dmi' - icon_state = "s-casing" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - throwforce = 1 - w_class = 1.0 - var/caliber = "" //Which kind of guns it can be loaded into - var/projectile_type = ""//The bullet type to create when New() is called - var/obj/item/projectile/BB = null //The loaded bullet - - -/obj/item/ammo_casing/New() - ..() - if(projectile_type) - BB = new projectile_type(src) - update_icon() - -/obj/item/ammo_casing/update_icon() - pixel_x = rand(-10.0, 10) - pixel_y = rand(-10.0, 10) - dir = pick(cardinal) - icon_state = "[initial(icon_state)][BB ? "-live" : ""]" - desc = "[initial(desc)][BB ? "" : " This one is spent."]" - - -//Boxes of ammo -/obj/item/ammo_storage - name = "ammo box (.357)" - desc = "A box of ammo." - icon_state = "357" - icon = 'icons/obj/ammo.dmi' - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - item_state = "syringe_kit" - starting_materials = list(MAT_IRON = 50000) - w_type = RECYK_METAL - throwforce = 2 - w_class = 1.0 - throw_speed = 4 - throw_range = 5 - var/list/stored_ammo = list() - var/ammo_type = "/obj/item/ammo_casing/a357" - var/exact = 1 //whether or not the item only takes ammo_type, or also subtypes. Set to 1 to only take the specified ammo - var/max_ammo = 7 - var/starting_ammo = -1 //-1 makes it spawn the max ammo, 0 and above makes it spawn that number - var/multiple_sprites = 0 //if it has multiple sprites. Please sprite more than 2 sprites if you set this to true, you fricks - var/sprite_modulo = 1 //the spacing of the ammo sprites. Setting this to 1 means there's a sprite for every state, 10 for every 10 states, etc. - - -/obj/item/ammo_storage/New() - ..() - var/ammo_to_load = 0 - if(starting_ammo > -1 && starting_ammo < max_ammo) - ammo_to_load = starting_ammo - update_icon() - else - ammo_to_load = max_ammo - for(var/i = 1, i <= ammo_to_load, i++) - stored_ammo += new ammo_type(src) - -/obj/item/ammo_storage/attackby(var/atom/A, var/mob/user) //now with loading - ..() - if(istype(A, /obj/item/ammo_casing)) //loading a bullet into the magazine or box - var/obj/item/ammo_casing/AC = A - var/accepted = 0 - if((exact && (AC.type == text2path(ammo_type))) || (!exact && istype(AC, text2path(ammo_type))))//if it's the exact type we want, or the general class - accepted = 1 - if(AC.BB && accepted && stored_ammo.len < max_ammo) - if(user.drop_item(A, src)) - to_chat(user, "You successfully load the [src] with \the [AC]. ") - else - to_chat(user, "You can't let go of \the [A]!") - return - - - stored_ammo += AC - - update_icon() - else if(!AC.BB) - to_chat(user, "You can't load a spent bullet.") - else if (stored_ammo.len == max_ammo) - to_chat(user, "\The [src] can't hold any more shells.") - return - if(istype(A, /obj/item/ammo_storage)) //loads all the bullets from one magazine to the other - var/obj/item/ammo_storage/AS = A - if(stored_ammo.len < max_ammo && AS.stored_ammo) - var/loaded_bullets = LoadInto(AS, src) - if(loaded_bullets) - to_chat(user, "You successfully fill the [src] with [loaded_bullets] shell\s from the [AS].") - update_icon() - else if (stored_ammo.len >= max_ammo) - to_chat(user, "\The [src] can't hold any more shells.") - -/obj/item/ammo_storage/update_icon() - if(multiple_sprites) - if(!sprite_modulo) - sprite_modulo = max_ammo - var/visible_ammo = stored_ammo.len - (stored_ammo.len % sprite_modulo) //the smallest round number in the interval - if(visible_ammo == 0 && stored_ammo.len) //if there IS ammo, but we can't see it because the thing is at 0 (most sprites are like this) - visible_ammo += sprite_modulo //we go to the next lowest sprite state so it doesn't look empty - icon_state = "[initial(icon_state)]-[visible_ammo]" - -/obj/item/ammo_storage/examine(mob/user) //never change descriptions, always use examine - ..() - if(max_ammo > 0) - to_chat(user, "There are [stored_ammo.len] shell\s left!") - -/obj/item/ammo_storage/attack_self(mob/user) //allows you to remove individual bullets - if(stored_ammo.len) - var/obj/item/ammo_casing/dropped = stored_ammo[1] - dropped.loc = get_turf(user) - stored_ammo -= dropped - update_icon() - to_chat(user, "You remove \a [dropped] from \the [src].") - -//used for loading from or to boxes. Has the fumble check -//this doesn't load any bullets by itself, but is a check for the slow loading used by boxes -/obj/item/ammo_storage/proc/slowLoad(var/obj/item/ammo_storage/bullets_from, var/obj/item/target) - if(!bullets_from || !istype(bullets_from)) //fuck you for calling this with the wrong arguments - return 0 - if(!target || !istype(target)) - return 0 - var/trying_to_load = 0 - if(istype(target, /obj/item/weapon/gun/projectile)) - var/obj/item/weapon/gun/projectile/PW = target - trying_to_load = min(PW.max_shells - PW.loaded.len, bullets_from.stored_ammo.len) //either we fill to max, or we fill as much as possible - else - var/obj/item/ammo_storage/AS = target - trying_to_load = min(AS.max_ammo - AS.stored_ammo.len, bullets_from.stored_ammo.len) //either we fill to max, or we fill as much as possible - if(usr && trying_to_load) - to_chat(usr, "You begin loading \the [target]...") - if(trying_to_load && do_after(usr,target,trying_to_load * 5)) //bit of a wait, but that's why it's SLOW - return 1 - else if(trying_to_load) - var/dropped_bullets = 0 - var/to_drop = rand(1, trying_to_load) //yeah, drop some on the floor! - for(var/i = 1; i<=min(to_drop, bullets_from.stored_ammo.len); i++) - var/obj/item/ammo_casing/AC = bullets_from.stored_ammo[1] - bullets_from.stored_ammo -= AC - AC.loc = get_turf(target) - dropped_bullets++ - bullets_from.update_icon() - if(usr) - to_chat(usr, "You fumble around and drop [dropped_bullets] shell\s!") - return 0 - return 0 - -//used to load bullets from ammo storage into other ammo storage or guns -//bullets_from is the origin, target is the gun or targetted box -/obj/item/ammo_storage/proc/LoadInto(var/obj/item/ammo_storage/bullets_from, var/obj/item/target) - if(!bullets_from || !istype(bullets_from)) - return 0 - if(!target || !istype(target)) - return 0 - var/bullets_loaded = 0 - if(istype(target, /obj/item/ammo_storage)) - if(istype(bullets_from, /obj/item/ammo_storage/box) || istype(target, /obj/item/ammo_storage/box)) - if(!slowLoad(bullets_from, target)) - return 0 - var/obj/item/ammo_storage/AS = target - for(var/obj/item/ammo_casing/loading in bullets_from.stored_ammo) - if(AS.stored_ammo.len >= AS.max_ammo) - break - if((AS.exact && (loading.type == text2path(AS.ammo_type))) || (!AS.exact && istype(loading, text2path(AS.ammo_type)))) //if it's the exact type we want, or the general class - bullets_from.stored_ammo -= loading - AS.stored_ammo += loading - loading.loc = AS - bullets_loaded++ - if(istype(target, /obj/item/weapon/gun/projectile)) //if we load directly, this is what we want to do - if(istype(bullets_from, /obj/item/ammo_storage/box)) - if(!slowLoad(bullets_from, target)) - return 0 - var/obj/item/weapon/gun/projectile/PW = target - for(var/obj/item/ammo_casing/loading in bullets_from.stored_ammo) - if(PW.loaded.len >= PW.max_shells) - break - if(PW.caliber && PW.caliber[loading.caliber]) //hurrah for gun variables. - bullets_from.stored_ammo -= loading - PW.loaded += loading - loading.loc = PW - bullets_loaded++ - bullets_from.update_icon() - target.update_icon() - return bullets_loaded - -/obj/item/ammo_storage/proc/get_round(var/keep = 0) - if(!ammo_count()) - return null - else - var/b = stored_ammo[stored_ammo.len] - stored_ammo -= b - if(keep) - stored_ammo.Insert(1,b) - else - update_icon() - return b - -/obj/item/ammo_storage/proc/ammo_count() - return stored_ammo.len +/obj/item/ammo_casing + name = "bullet casing" + desc = "A bullet casing." + icon = 'icons/obj/ammo.dmi' + icon_state = "s-casing" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 1 + w_class = 1.0 + var/caliber = "" //Which kind of guns it can be loaded into + var/projectile_type = ""//The bullet type to create when New() is called + var/obj/item/projectile/BB = null //The loaded bullet + + +/obj/item/ammo_casing/New() + ..() + if(projectile_type) + BB = new projectile_type(src) + update_icon() + +/obj/item/ammo_casing/update_icon() + pixel_x = rand(-10.0, 10) + pixel_y = rand(-10.0, 10) + dir = pick(cardinal) + icon_state = "[initial(icon_state)][BB ? "-live" : ""]" + desc = "[initial(desc)][BB ? "" : " This one is spent."]" + + +//Boxes of ammo +/obj/item/ammo_storage + name = "ammo box (.357)" + desc = "A box of ammo." + icon_state = "357" + icon = 'icons/obj/ammo.dmi' + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + item_state = "syringe_kit" + starting_materials = list(MAT_IRON = 50000) + w_type = RECYK_METAL + throwforce = 2 + w_class = 1.0 + throw_speed = 4 + throw_range = 5 + var/list/stored_ammo = list() + var/ammo_type = "/obj/item/ammo_casing/a357" + var/exact = 1 //whether or not the item only takes ammo_type, or also subtypes. Set to 1 to only take the specified ammo + var/max_ammo = 7 + var/starting_ammo = -1 //-1 makes it spawn the max ammo, 0 and above makes it spawn that number + var/multiple_sprites = 0 //if it has multiple sprites. Please sprite more than 2 sprites if you set this to true, you fricks + var/sprite_modulo = 1 //the spacing of the ammo sprites. Setting this to 1 means there's a sprite for every state, 10 for every 10 states, etc. + + +/obj/item/ammo_storage/New() + ..() + var/ammo_to_load = 0 + if(starting_ammo > -1 && starting_ammo < max_ammo) + ammo_to_load = starting_ammo + update_icon() + else + ammo_to_load = max_ammo + for(var/i = 1, i <= ammo_to_load, i++) + stored_ammo += new ammo_type(src) + +/obj/item/ammo_storage/attackby(var/atom/A, var/mob/user) //now with loading + ..() + if(istype(A, /obj/item/ammo_casing)) //loading a bullet into the magazine or box + var/obj/item/ammo_casing/AC = A + var/accepted = 0 + if((exact && (AC.type == text2path(ammo_type))) || (!exact && istype(AC, text2path(ammo_type))))//if it's the exact type we want, or the general class + accepted = 1 + if(AC.BB && accepted && stored_ammo.len < max_ammo) + if(user.drop_item(A, src)) + to_chat(user, "You successfully load the [src] with \the [AC]. ") + else + to_chat(user, "You can't let go of \the [A]!") + return + + + stored_ammo += AC + + update_icon() + else if(!AC.BB) + to_chat(user, "You can't load a spent bullet.") + else if (stored_ammo.len == max_ammo) + to_chat(user, "\The [src] can't hold any more shells.") + return + if(istype(A, /obj/item/ammo_storage)) //loads all the bullets from one magazine to the other + var/obj/item/ammo_storage/AS = A + if(stored_ammo.len < max_ammo && AS.stored_ammo) + var/loaded_bullets = LoadInto(AS, src) + if(loaded_bullets) + to_chat(user, "You successfully fill the [src] with [loaded_bullets] shell\s from the [AS].") + update_icon() + else if (stored_ammo.len >= max_ammo) + to_chat(user, "\The [src] can't hold any more shells.") + +/obj/item/ammo_storage/update_icon() + if(multiple_sprites) + if(!sprite_modulo) + sprite_modulo = max_ammo + var/visible_ammo = stored_ammo.len - (stored_ammo.len % sprite_modulo) //the smallest round number in the interval + if(visible_ammo == 0 && stored_ammo.len) //if there IS ammo, but we can't see it because the thing is at 0 (most sprites are like this) + visible_ammo += sprite_modulo //we go to the next lowest sprite state so it doesn't look empty + icon_state = "[initial(icon_state)]-[visible_ammo]" + +/obj/item/ammo_storage/examine(mob/user) //never change descriptions, always use examine + ..() + if(max_ammo > 0) + to_chat(user, "There are [stored_ammo.len] shell\s left!") + +/obj/item/ammo_storage/attack_self(mob/user) //allows you to remove individual bullets + if(stored_ammo.len) + var/obj/item/ammo_casing/dropped = stored_ammo[1] + dropped.loc = get_turf(user) + stored_ammo -= dropped + update_icon() + to_chat(user, "You remove \a [dropped] from \the [src].") + +//used for loading from or to boxes. Has the fumble check +//this doesn't load any bullets by itself, but is a check for the slow loading used by boxes +/obj/item/ammo_storage/proc/slowLoad(var/obj/item/ammo_storage/bullets_from, var/obj/item/target) + if(!bullets_from || !istype(bullets_from)) //fuck you for calling this with the wrong arguments + return 0 + if(!target || !istype(target)) + return 0 + var/trying_to_load = 0 + if(istype(target, /obj/item/weapon/gun/projectile)) + var/obj/item/weapon/gun/projectile/PW = target + trying_to_load = min(PW.max_shells - PW.loaded.len, bullets_from.stored_ammo.len) //either we fill to max, or we fill as much as possible + else + var/obj/item/ammo_storage/AS = target + trying_to_load = min(AS.max_ammo - AS.stored_ammo.len, bullets_from.stored_ammo.len) //either we fill to max, or we fill as much as possible + if(usr && trying_to_load) + to_chat(usr, "You begin loading \the [target]...") + if(trying_to_load && do_after(usr,target,trying_to_load * 5)) //bit of a wait, but that's why it's SLOW + return 1 + else if(trying_to_load) + var/dropped_bullets = 0 + var/to_drop = rand(1, trying_to_load) //yeah, drop some on the floor! + for(var/i = 1; i<=min(to_drop, bullets_from.stored_ammo.len); i++) + var/obj/item/ammo_casing/AC = bullets_from.stored_ammo[1] + bullets_from.stored_ammo -= AC + AC.loc = get_turf(target) + dropped_bullets++ + bullets_from.update_icon() + if(usr) + to_chat(usr, "You fumble around and drop [dropped_bullets] shell\s!") + return 0 + return 0 + +//used to load bullets from ammo storage into other ammo storage or guns +//bullets_from is the origin, target is the gun or targetted box +/obj/item/ammo_storage/proc/LoadInto(var/obj/item/ammo_storage/bullets_from, var/obj/item/target) + if(!bullets_from || !istype(bullets_from)) + return 0 + if(!target || !istype(target)) + return 0 + var/bullets_loaded = 0 + if(istype(target, /obj/item/ammo_storage)) + if(istype(bullets_from, /obj/item/ammo_storage/box) || istype(target, /obj/item/ammo_storage/box)) + if(!slowLoad(bullets_from, target)) + return 0 + var/obj/item/ammo_storage/AS = target + for(var/obj/item/ammo_casing/loading in bullets_from.stored_ammo) + if(AS.stored_ammo.len >= AS.max_ammo) + break + if((AS.exact && (loading.type == text2path(AS.ammo_type))) || (!AS.exact && istype(loading, text2path(AS.ammo_type)))) //if it's the exact type we want, or the general class + bullets_from.stored_ammo -= loading + AS.stored_ammo += loading + loading.loc = AS + bullets_loaded++ + if(istype(target, /obj/item/weapon/gun/projectile)) //if we load directly, this is what we want to do + if(istype(bullets_from, /obj/item/ammo_storage/box)) + if(!slowLoad(bullets_from, target)) + return 0 + var/obj/item/weapon/gun/projectile/PW = target + for(var/obj/item/ammo_casing/loading in bullets_from.stored_ammo) + if(PW.loaded.len >= PW.max_shells) + break + if(PW.caliber && PW.caliber[loading.caliber]) //hurrah for gun variables. + bullets_from.stored_ammo -= loading + PW.loaded += loading + loading.loc = PW + bullets_loaded++ + bullets_from.update_icon() + target.update_icon() + return bullets_loaded + +/obj/item/ammo_storage/proc/get_round(var/keep = 0) + if(!ammo_count()) + return null + else + var/b = stored_ammo[stored_ammo.len] + stored_ammo -= b + if(keep) + stored_ammo.Insert(1,b) + else + update_icon() + return b + +/obj/item/ammo_storage/proc/ammo_count() + return stored_ammo.len diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm index a05e98bb788..1c38551b9d1 100644 --- a/code/modules/projectiles/ammunition/boxes.dm +++ b/code/modules/projectiles/ammunition/boxes.dm @@ -1,80 +1,80 @@ -//Boxes store shells to be loaded into guns -//Boxes have a "fumble" effect - if you move while loading something, you drop some bullets and stop the action. -//Attempting to load a gun in the middle of a firefight is a bad idea, needless to say - -/obj/item/ammo_storage/box - exact = 1 - -/obj/item/ammo_storage/box/a357 - name = "ammo box (.357)" - desc = "A box of .357 ammo." - icon_state = "357" - ammo_type = "/obj/item/ammo_casing/a357" - max_ammo = 7 - multiple_sprites = 1 - -/obj/item/ammo_storage/box/c38 - name = "ammo box (.38)" - desc = "A box of non-lethal .38 ammo." - icon_state = "b38" - ammo_type = "/obj/item/ammo_casing/c38" - max_ammo = 6 - multiple_sprites = 1 - -/obj/item/ammo_storage/box/a418 - name = "ammo box (.418)" - icon_state = "418" - ammo_type = "/obj/item/ammo_casing/a418" - max_ammo = 7 - multiple_sprites = 1 - -/obj/item/ammo_storage/box/a666 - name = "ammo box (.666)" - icon_state = "666" - ammo_type = "/obj/item/ammo_casing/a666" - max_ammo = 4 - multiple_sprites = 1 - -/obj/item/ammo_storage/box/c9mm - name = "ammo box (9mm)" - icon_state = "9mm" - origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/c9mm" - max_ammo = 30 - -/obj/item/ammo_storage/box/c12mm - name = "ammo box (12mm)" - icon_state = "9mm" - origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/a12mm" - max_ammo = 30 - -/obj/item/ammo_storage/box/c45 - name = "ammo box (.45)" - icon_state = "9mm" - origin_tech = "combat=2" - ammo_type = "/obj/item/ammo_casing/c45" - max_ammo = 30 - -/obj/item/ammo_storage/box/BMG50 - name = "ammo box (.50 BMG)" - icon_state = "50BMG" - origin_tech = "combat=4" - ammo_type = "/obj/item/ammo_casing/BMG50" - max_ammo = 8 - multiple_sprites = 1 - -/obj/item/ammo_storage/box/b762x55 - name = "ammo box (7.62x55mmR)" - icon_state = "b762x55" - origin_tech = "combat=3" - ammo_type = "/obj/item/ammo_casing/a762x55" - max_ammo = 8 - multiple_sprites = 1 - -/obj/item/ammo_storage/box/flare - name = "ammo box (flare shells)" - icon_state = "flarebox" - ammo_type = "/obj/item/ammo_casing/shotgun/flare" - max_ammo = 7 - multiple_sprites = 1 +//Boxes store shells to be loaded into guns +//Boxes have a "fumble" effect - if you move while loading something, you drop some bullets and stop the action. +//Attempting to load a gun in the middle of a firefight is a bad idea, needless to say + +/obj/item/ammo_storage/box + exact = 1 + +/obj/item/ammo_storage/box/a357 + name = "ammo box (.357)" + desc = "A box of .357 ammo." + icon_state = "357" + ammo_type = "/obj/item/ammo_casing/a357" + max_ammo = 7 + multiple_sprites = 1 + +/obj/item/ammo_storage/box/c38 + name = "ammo box (.38)" + desc = "A box of non-lethal .38 ammo." + icon_state = "b38" + ammo_type = "/obj/item/ammo_casing/c38" + max_ammo = 6 + multiple_sprites = 1 + +/obj/item/ammo_storage/box/a418 + name = "ammo box (.418)" + icon_state = "418" + ammo_type = "/obj/item/ammo_casing/a418" + max_ammo = 7 + multiple_sprites = 1 + +/obj/item/ammo_storage/box/a666 + name = "ammo box (.666)" + icon_state = "666" + ammo_type = "/obj/item/ammo_casing/a666" + max_ammo = 4 + multiple_sprites = 1 + +/obj/item/ammo_storage/box/c9mm + name = "ammo box (9mm)" + icon_state = "9mm" + origin_tech = "combat=2" + ammo_type = "/obj/item/ammo_casing/c9mm" + max_ammo = 30 + +/obj/item/ammo_storage/box/c12mm + name = "ammo box (12mm)" + icon_state = "9mm" + origin_tech = "combat=2" + ammo_type = "/obj/item/ammo_casing/a12mm" + max_ammo = 30 + +/obj/item/ammo_storage/box/c45 + name = "ammo box (.45)" + icon_state = "9mm" + origin_tech = "combat=2" + ammo_type = "/obj/item/ammo_casing/c45" + max_ammo = 30 + +/obj/item/ammo_storage/box/BMG50 + name = "ammo box (.50 BMG)" + icon_state = "50BMG" + origin_tech = "combat=4" + ammo_type = "/obj/item/ammo_casing/BMG50" + max_ammo = 8 + multiple_sprites = 1 + +/obj/item/ammo_storage/box/b762x55 + name = "ammo box (7.62x55mmR)" + icon_state = "b762x55" + origin_tech = "combat=3" + ammo_type = "/obj/item/ammo_casing/a762x55" + max_ammo = 8 + multiple_sprites = 1 + +/obj/item/ammo_storage/box/flare + name = "ammo box (flare shells)" + icon_state = "flarebox" + ammo_type = "/obj/item/ammo_casing/shotgun/flare" + max_ammo = 7 + multiple_sprites = 1 diff --git a/code/modules/projectiles/ammunition/bullets.dm b/code/modules/projectiles/ammunition/bullets.dm index a227c791dbb..36711744c90 100644 --- a/code/modules/projectiles/ammunition/bullets.dm +++ b/code/modules/projectiles/ammunition/bullets.dm @@ -1,155 +1,155 @@ -/obj/item/ammo_casing/a357 - desc = "A .357 bullet casing." - caliber = "357" - projectile_type = "/obj/item/projectile/bullet" - w_type = RECYK_METAL - -/obj/item/ammo_casing/a50 - desc = "A .50AE bullet casing." - caliber = ".50" - projectile_type = "/obj/item/projectile/bullet" - w_type = RECYK_METAL - -/obj/item/ammo_casing/a418 - desc = "A .418 bullet casing." - caliber = "357" - projectile_type = "/obj/item/projectile/bullet/suffocationbullet" - w_type = RECYK_METAL - - -/obj/item/ammo_casing/a75 - desc = "A .75 bullet casing." - caliber = "75" - projectile_type = "/obj/item/projectile/bullet/gyro" - w_type = RECYK_METAL - - -/obj/item/ammo_casing/a666 - desc = "A .666 bullet casing." - caliber = "357" - projectile_type = "/obj/item/projectile/bullet/cyanideround" - w_type = RECYK_METAL - - -/obj/item/ammo_casing/c38 - desc = "A .38 bullet casing." - caliber = "38" - projectile_type = "/obj/item/projectile/bullet/weakbullet" - w_type = RECYK_METAL - -/* Not entirely ready to be implemented yet. Get a server vote on bringing these in -/obj/item/ammo_casing/c38/lethal - desc = "A .38 bullet casing. This is the lethal variant." - caliber = "38" - projectile_type = "/obj/item/projectile/bullet" //HAHA, why is this a good idea - w_type = RECYK_METAL -*/ - -/obj/item/ammo_casing/c9mm - desc = "A 9mm bullet casing." - caliber = "9mm" - projectile_type = "/obj/item/projectile/bullet/midbullet2" - w_type = RECYK_METAL - - -/obj/item/ammo_casing/c45 - desc = "A .45 bullet casing." - caliber = ".45" - projectile_type = "/obj/item/projectile/bullet/midbullet" - w_type = RECYK_METAL - - -/obj/item/ammo_casing/a12mm - desc = "A 12mm bullet casing." - caliber = "12mm" - projectile_type = "/obj/item/projectile/bullet/midbullet" - w_type = RECYK_METAL - - -/obj/item/ammo_casing/shotgun - name = "shotgun shell" - desc = "A 12 gauge shell." - icon_state = "gshell" - caliber = "shotgun" - projectile_type = "/obj/item/projectile/bullet" - starting_materials = list(MAT_IRON = 12500) - w_type = RECYK_METAL - - update_icon() - desc = "[initial(desc)][BB ? "" : " This one is spent"]" - overlays = list() - if(!BB) - overlays += icon('icons/obj/ammo.dmi', "emptyshell") - -/obj/item/ammo_casing/shotgun/blank - name = "shotgun shell" - desc = "A blank shell." - icon_state = "blshell" - projectile_type = "" - starting_materials = list(MAT_IRON = 250) - w_type = RECYK_METAL - -/obj/item/ammo_casing/shotgun/beanbag - name = "beanbag shell" - desc = "A weak beanbag shell." - icon_state = "bshell" - projectile_type = "/obj/item/projectile/bullet/weakbullet" - starting_materials = list(MAT_IRON = 500) - w_type = RECYK_METAL - -/obj/item/ammo_casing/shotgun/fakebeanbag - name = "beanbag shell" - desc = "A weak beanbag shell." - icon_state = "bshell" - projectile_type = "/obj/item/projectile/bullet/weakbullet/booze" - starting_materials = list(MAT_IRON = 12500) - w_type = RECYK_METAL - -/obj/item/ammo_casing/shotgun/stunshell - name = "stun shell" - desc = "A stunning shell." - icon_state = "stunshell" - projectile_type = "/obj/item/projectile/bullet/stunshot" - starting_materials = list(MAT_IRON = 2500) - w_type = RECYK_METAL - -/obj/item/ammo_casing/shotgun/dart - name = "shotgun darts" - desc = "A dart for use in shotguns." - icon_state = "blshell" - projectile_type = "/obj/item/projectile/bullet/dart" - starting_materials = list(MAT_IRON = 12500) - w_type = RECYK_METAL - -/obj/item/ammo_casing/a762 - desc = "A 7.62 bullet casing." - caliber = "a762" - projectile_type = "/obj/item/projectile/bullet" - w_type = RECYK_METAL - -/obj/item/ammo_casing/BMG50 - desc = "A .50 BMG bullet casing." - caliber = ".50BMG" - projectile_type = "/obj/item/projectile/bullet/hecate" - w_type = RECYK_METAL - icon_state = "l-casing" - -/obj/item/ammo_casing/energy/kinetic - projectile_type = /obj/item/projectile/bullet - //select_name = "kinetic" - //e_cost = 500 - //fire_sound = 'sound/weapons/Gunshot4.ogg' - w_type = RECYK_METAL - -/obj/item/ammo_casing/a762x55 - desc = "A 7.62x55mmR bullet casing." - caliber = "7.62x55" - projectile_type = "/obj/item/projectile/bullet/a762x55" - w_type = RECYK_METAL - icon_state = "762x55-casing-live" - starting_materials = list(MAT_IRON = 12500) - - update_icon() - desc = "[initial(desc)][BB ? "" : " This one is spent"]" - if(!BB) - icon_state = "762x55-casing" +/obj/item/ammo_casing/a357 + desc = "A .357 bullet casing." + caliber = "357" + projectile_type = "/obj/item/projectile/bullet" + w_type = RECYK_METAL + +/obj/item/ammo_casing/a50 + desc = "A .50AE bullet casing." + caliber = ".50" + projectile_type = "/obj/item/projectile/bullet" + w_type = RECYK_METAL + +/obj/item/ammo_casing/a418 + desc = "A .418 bullet casing." + caliber = "357" + projectile_type = "/obj/item/projectile/bullet/suffocationbullet" + w_type = RECYK_METAL + + +/obj/item/ammo_casing/a75 + desc = "A .75 bullet casing." + caliber = "75" + projectile_type = "/obj/item/projectile/bullet/gyro" + w_type = RECYK_METAL + + +/obj/item/ammo_casing/a666 + desc = "A .666 bullet casing." + caliber = "357" + projectile_type = "/obj/item/projectile/bullet/cyanideround" + w_type = RECYK_METAL + + +/obj/item/ammo_casing/c38 + desc = "A .38 bullet casing." + caliber = "38" + projectile_type = "/obj/item/projectile/bullet/weakbullet" + w_type = RECYK_METAL + +/* Not entirely ready to be implemented yet. Get a server vote on bringing these in +/obj/item/ammo_casing/c38/lethal + desc = "A .38 bullet casing. This is the lethal variant." + caliber = "38" + projectile_type = "/obj/item/projectile/bullet" //HAHA, why is this a good idea + w_type = RECYK_METAL +*/ + +/obj/item/ammo_casing/c9mm + desc = "A 9mm bullet casing." + caliber = "9mm" + projectile_type = "/obj/item/projectile/bullet/midbullet2" + w_type = RECYK_METAL + + +/obj/item/ammo_casing/c45 + desc = "A .45 bullet casing." + caliber = ".45" + projectile_type = "/obj/item/projectile/bullet/midbullet" + w_type = RECYK_METAL + + +/obj/item/ammo_casing/a12mm + desc = "A 12mm bullet casing." + caliber = "12mm" + projectile_type = "/obj/item/projectile/bullet/midbullet" + w_type = RECYK_METAL + + +/obj/item/ammo_casing/shotgun + name = "shotgun shell" + desc = "A 12 gauge shell." + icon_state = "gshell" + caliber = "shotgun" + projectile_type = "/obj/item/projectile/bullet" + starting_materials = list(MAT_IRON = 12500) + w_type = RECYK_METAL + + update_icon() + desc = "[initial(desc)][BB ? "" : " This one is spent"]" + overlays = list() + if(!BB) + overlays += icon('icons/obj/ammo.dmi', "emptyshell") + +/obj/item/ammo_casing/shotgun/blank + name = "shotgun shell" + desc = "A blank shell." + icon_state = "blshell" + projectile_type = "" + starting_materials = list(MAT_IRON = 250) + w_type = RECYK_METAL + +/obj/item/ammo_casing/shotgun/beanbag + name = "beanbag shell" + desc = "A weak beanbag shell." + icon_state = "bshell" + projectile_type = "/obj/item/projectile/bullet/weakbullet" + starting_materials = list(MAT_IRON = 500) + w_type = RECYK_METAL + +/obj/item/ammo_casing/shotgun/fakebeanbag + name = "beanbag shell" + desc = "A weak beanbag shell." + icon_state = "bshell" + projectile_type = "/obj/item/projectile/bullet/weakbullet/booze" + starting_materials = list(MAT_IRON = 12500) + w_type = RECYK_METAL + +/obj/item/ammo_casing/shotgun/stunshell + name = "stun shell" + desc = "A stunning shell." + icon_state = "stunshell" + projectile_type = "/obj/item/projectile/bullet/stunshot" + starting_materials = list(MAT_IRON = 2500) + w_type = RECYK_METAL + +/obj/item/ammo_casing/shotgun/dart + name = "shotgun darts" + desc = "A dart for use in shotguns." + icon_state = "blshell" + projectile_type = "/obj/item/projectile/bullet/dart" + starting_materials = list(MAT_IRON = 12500) + w_type = RECYK_METAL + +/obj/item/ammo_casing/a762 + desc = "A 7.62 bullet casing." + caliber = "a762" + projectile_type = "/obj/item/projectile/bullet" + w_type = RECYK_METAL + +/obj/item/ammo_casing/BMG50 + desc = "A .50 BMG bullet casing." + caliber = ".50BMG" + projectile_type = "/obj/item/projectile/bullet/hecate" + w_type = RECYK_METAL + icon_state = "l-casing" + +/obj/item/ammo_casing/energy/kinetic + projectile_type = /obj/item/projectile/bullet + //select_name = "kinetic" + //e_cost = 500 + //fire_sound = 'sound/weapons/Gunshot4.ogg' + w_type = RECYK_METAL + +/obj/item/ammo_casing/a762x55 + desc = "A 7.62x55mmR bullet casing." + caliber = "7.62x55" + projectile_type = "/obj/item/projectile/bullet/a762x55" + w_type = RECYK_METAL + icon_state = "762x55-casing-live" + starting_materials = list(MAT_IRON = 12500) + + update_icon() + desc = "[initial(desc)][BB ? "" : " This one is spent"]" + if(!BB) + icon_state = "762x55-casing" diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f9e1b0ba77e..7430b70e733 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -1,272 +1,272 @@ -/obj/item/weapon/gun - name = "gun" - desc = "Its a gun. It's pretty terrible, though." - icon = 'icons/obj/gun.dmi' - icon_state = "detective" - item_state = "gun" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - starting_materials = list(MAT_IRON = 2000) - w_type = RECYK_METAL - w_class = 3.0 - throwforce = 5 - throw_speed = 4 - throw_range = 5 - force = 5.0 - origin_tech = "combat=1" - attack_verb = list("struck", "hit", "bashed") - mech_flags = MECH_SCAN_ILLEGAL - min_harm_label = 20 - harm_label_examine = list("A label is stuck to the trigger, but it is too small to get in the way.", "A label firmly sticks the trigger to the guard!") - - var/fire_sound = 'sound/weapons/Gunshot.ogg' - var/obj/item/projectile/in_chamber = null - var/list/caliber //the ammo the gun will accept. Now multiple types (make sure to set them to =1) - var/silenced = 0 - var/recoil = 0 - var/ejectshell = 1 - var/clumsy_check = 1 - var/tmp/list/mob/living/target //List of who yer targeting. - var/tmp/lock_time = -100 - var/tmp/mouthshoot = 0 ///To stop people from suiciding twice... >.> - var/automatic = 0 //Used to determine if you can target multiple people. - var/tmp/mob/living/last_moved_mob //Used to fire faster at more than one person. - var/tmp/told_cant_shoot = 0 //So that it doesn't spam them with the fact they cannot hit them. - var/firerate = 1 // 0 for one bullet after tarrget moves and aim is lowered, - //1 for keep shooting until aim is lowered - var/fire_delay = 2 - var/last_fired = 0 - -/obj/item/weapon/gun/proc/ready_to_fire() - if(world.time >= last_fired + fire_delay) - last_fired = world.time - return 1 - else - return 0 - -/obj/item/weapon/gun/proc/process_chambered() - return 0 - -/obj/item/weapon/gun/proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver. - return 1 - -/obj/item/weapon/gun/emp_act(severity) - for(var/obj/O in contents) - O.emp_act(severity) - -/obj/item/weapon/gun/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0) - if(flag) return //we're placing gun on a table or in backpack - if(harm_labeled >= min_harm_label) - to_chat(user, "A label sticks the trigger to the trigger guard!")//Such a new feature, the player might not know what's wrong if it doesn't tell them. - - return - if(istype(target, /obj/machinery/recharger) && istype(src, /obj/item/weapon/gun/energy)) return//Shouldnt flag take care of this? - if(user && user.client && user.client.gun_mode && !(A in target)) - PreFire(A,user,params, "struggle" = struggle) //They're using the new gun system, locate what they're aiming at. - else - Fire(A,user,params, "struggle" = struggle) //Otherwise, fire normally. - -/obj/item/weapon/gun/proc/isHandgun() - return 1 - -/obj/item/weapon/gun/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0)//TODO: go over this - //Exclude lasertag guns from the M_CLUMSY check. - if(clumsy_check) - if(istype(user, /mob/living)) - var/mob/living/M = user - if ((M_CLUMSY in M.mutations) && prob(50)) - to_chat(M, "[src] blows up in your face.") - M.take_organ_damage(0,20) - M.drop_item(src, force_drop = 1) - qdel(src) - return - - if (!user.IsAdvancedToolUser() || isMoMMI(user) || istype(user, /mob/living/carbon/monkey/diona)) - to_chat(user, "You don't have the dexterity to do this!") - return - if(istype(user, /mob/living)) - var/mob/living/M = user - if (M_HULK in M.mutations) - to_chat(M, "Your meaty finger is much too large for the trigger guard!") - return - if(ishuman(user)) - var/mob/living/carbon/human/H=user - if(user.dna && (user.dna.mutantrace == "adamantine" || user.dna.mutantrace=="coalgolem")) - to_chat(user, "Your fat fingers don't fit in the trigger guard!") - return - var/datum/organ/external/a_hand = H.get_active_hand_organ() - if(!a_hand.can_use_advanced_tools()) - to_chat(user, "Your [a_hand] doesn't have the dexterity to do this!") - return - - add_fingerprint(user) - - var/turf/curloc = user.loc - var/turf/targloc = get_turf(target) - if (!istype(targloc) || !istype(curloc)) - return - - if(!special_check(user)) - return - - if (!ready_to_fire()) - if (world.time % 3) //to prevent spam - to_chat(user, "[src] is not ready to fire again!") - return - - if(!process_chambered()) //CHECK - return click_empty(user) - - if(!in_chamber) - return - if(!istype(src, /obj/item/weapon/gun/energy/laser/redtag) && !istype(src, /obj/item/weapon/gun/energy/laser/redtag)) - log_attack("[user.name] ([user.ckey]) fired \the [src] (proj:[in_chamber.name]) at [target] [ismob(target) ? "([target:ckey])" : ""] ([target.x],[target.y],[target.z])[struggle ? " due to being disarmed." :""]" ) - in_chamber.firer = user - - if(user.zone_sel) - in_chamber.def_zone = user.zone_sel.selecting - else - in_chamber.def_zone = "chest" - - if(targloc == curloc) - user.bullet_act(in_chamber) - qdel(in_chamber) - in_chamber = null - update_icon() - return - - if(recoil) - spawn() - shake_camera(user, recoil + 1, recoil) - if(user.locked_to && isobj(user.locked_to) && !user.locked_to.anchored ) - var/direction = get_dir(user,target) - spawn() - var/obj/B = user.locked_to - var/movementdirection = turn(direction,180) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) - user.inertia_dir = get_dir(target, user) - step(user, user.inertia_dir) - - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 50, 1) - user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \ - "You fire [src][reflex ? "by reflex":""]!", \ - "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") - - in_chamber.original = target - in_chamber.loc = get_turf(user) - in_chamber.starting = get_turf(user) - in_chamber.shot_from = src - user.delayNextAttack(4) // TODO: Should be delayed per-gun. - in_chamber.silenced = silenced - in_chamber.current = curloc - in_chamber.OnFired() - in_chamber.yo = targloc.y - curloc.y - in_chamber.xo = targloc.x - curloc.x - in_chamber.inaccurate = (istype(user.locked_to, /obj/structure/bed/chair/vehicle)) - - if(params) - var/list/mouse_control = params2list(params) - if(mouse_control["icon-x"]) - in_chamber.p_x = text2num(mouse_control["icon-x"]) - if(mouse_control["icon-y"]) - in_chamber.p_y = text2num(mouse_control["icon-y"]) - - spawn() - if(in_chamber) - in_chamber.process() - sleep(1) - in_chamber = null - - update_icon() - - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() - -/obj/item/weapon/gun/proc/can_fire() - return process_chambered() - -/obj/item/weapon/gun/proc/can_hit(var/mob/living/target as mob, var/mob/living/user as mob) - return in_chamber.check_fire(target,user) - -/obj/item/weapon/gun/proc/click_empty(mob/user = null) - if (user) - user.visible_message("*click click*", "*click*") - playsound(user, 'sound/weapons/empty.ogg', 100, 1) - else - src.visible_message("*click click*") - playsound(get_turf(src), 'sound/weapons/empty.ogg', 100, 1) - -/obj/item/weapon/gun/attack(mob/living/M as mob, mob/living/user as mob, def_zone) - //Suicide handling. - if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot) - if(istype(M.wear_mask, /obj/item/clothing/mask/happy)) - to_chat(M, "BUT WHY? I'M SO HAPPY!") - return - mouthshoot = 1 - M.visible_message("[user] sticks their gun in their mouth, ready to pull the trigger...") - if(!do_after(user,src, 40)) - M.visible_message("[user] decided life was worth living") - mouthshoot = 0 - return - if (process_chambered()) - user.visible_message("[user] pulls the trigger.") - if(silenced) - playsound(user, fire_sound, 10, 1) - else - playsound(user, fire_sound, 50, 1) - in_chamber.on_hit(M) - if (!in_chamber.nodamage) - user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]") - user.stat=2 // Just to be sure - user.death() - var/suicidesound = pick('sound/misc/suicide/suicide1.ogg','sound/misc/suicide/suicide2.ogg','sound/misc/suicide/suicide3.ogg','sound/misc/suicide/suicide4.ogg','sound/misc/suicide/suicide5.ogg','sound/misc/suicide/suicide6.ogg') - playsound(get_turf(src), pick(suicidesound), 10, channel = 125) - else - to_chat(user, "Ow...") - user.apply_effect(110,AGONY,0) - qdel(in_chamber) - in_chamber = null - mouthshoot = 0 - return - else - click_empty(user) - mouthshoot = 0 - return - - if (src.process_chambered()) - //Point blank shooting if on harm intent or target we were targeting. - if(user.a_intent == I_HURT) - user.visible_message(" \The [user] fires \the [src] point blank at [M]!") - in_chamber.damage *= 1.3 - src.Fire(M,user,0,0,1) - return - else if(target && M in target) - src.Fire(M,user,0,0,1) ///Otherwise, shoot! - return - else - return ..() //Allows a player to choose to melee instead of shoot, by being on help intent. - else - return ..() //Pistolwhippin' +/obj/item/weapon/gun + name = "gun" + desc = "Its a gun. It's pretty terrible, though." + icon = 'icons/obj/gun.dmi' + icon_state = "detective" + item_state = "gun" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + starting_materials = list(MAT_IRON = 2000) + w_type = RECYK_METAL + w_class = 3.0 + throwforce = 5 + throw_speed = 4 + throw_range = 5 + force = 5.0 + origin_tech = "combat=1" + attack_verb = list("struck", "hit", "bashed") + mech_flags = MECH_SCAN_ILLEGAL + min_harm_label = 20 + harm_label_examine = list("A label is stuck to the trigger, but it is too small to get in the way.", "A label firmly sticks the trigger to the guard!") + + var/fire_sound = 'sound/weapons/Gunshot.ogg' + var/obj/item/projectile/in_chamber = null + var/list/caliber //the ammo the gun will accept. Now multiple types (make sure to set them to =1) + var/silenced = 0 + var/recoil = 0 + var/ejectshell = 1 + var/clumsy_check = 1 + var/tmp/list/mob/living/target //List of who yer targeting. + var/tmp/lock_time = -100 + var/tmp/mouthshoot = 0 ///To stop people from suiciding twice... >.> + var/automatic = 0 //Used to determine if you can target multiple people. + var/tmp/mob/living/last_moved_mob //Used to fire faster at more than one person. + var/tmp/told_cant_shoot = 0 //So that it doesn't spam them with the fact they cannot hit them. + var/firerate = 1 // 0 for one bullet after tarrget moves and aim is lowered, + //1 for keep shooting until aim is lowered + var/fire_delay = 2 + var/last_fired = 0 + +/obj/item/weapon/gun/proc/ready_to_fire() + if(world.time >= last_fired + fire_delay) + last_fired = world.time + return 1 + else + return 0 + +/obj/item/weapon/gun/proc/process_chambered() + return 0 + +/obj/item/weapon/gun/proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver. + return 1 + +/obj/item/weapon/gun/emp_act(severity) + for(var/obj/O in contents) + O.emp_act(severity) + +/obj/item/weapon/gun/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0) + if(flag) return //we're placing gun on a table or in backpack + if(harm_labeled >= min_harm_label) + to_chat(user, "A label sticks the trigger to the trigger guard!")//Such a new feature, the player might not know what's wrong if it doesn't tell them. + + return + if(istype(target, /obj/machinery/recharger) && istype(src, /obj/item/weapon/gun/energy)) return//Shouldnt flag take care of this? + if(user && user.client && user.client.gun_mode && !(A in target)) + PreFire(A,user,params, "struggle" = struggle) //They're using the new gun system, locate what they're aiming at. + else + Fire(A,user,params, "struggle" = struggle) //Otherwise, fire normally. + +/obj/item/weapon/gun/proc/isHandgun() + return 1 + +/obj/item/weapon/gun/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0)//TODO: go over this + //Exclude lasertag guns from the M_CLUMSY check. + if(clumsy_check) + if(istype(user, /mob/living)) + var/mob/living/M = user + if ((M_CLUMSY in M.mutations) && prob(50)) + to_chat(M, "[src] blows up in your face.") + M.take_organ_damage(0,20) + M.drop_item(src, force_drop = 1) + qdel(src) + return + + if (!user.IsAdvancedToolUser() || isMoMMI(user) || istype(user, /mob/living/carbon/monkey/diona)) + to_chat(user, "You don't have the dexterity to do this!") + return + if(istype(user, /mob/living)) + var/mob/living/M = user + if (M_HULK in M.mutations) + to_chat(M, "Your meaty finger is much too large for the trigger guard!") + return + if(ishuman(user)) + var/mob/living/carbon/human/H=user + if(user.dna && (user.dna.mutantrace == "adamantine" || user.dna.mutantrace=="coalgolem")) + to_chat(user, "Your fat fingers don't fit in the trigger guard!") + return + var/datum/organ/external/a_hand = H.get_active_hand_organ() + if(!a_hand.can_use_advanced_tools()) + to_chat(user, "Your [a_hand] doesn't have the dexterity to do this!") + return + + add_fingerprint(user) + + var/turf/curloc = user.loc + var/turf/targloc = get_turf(target) + if (!istype(targloc) || !istype(curloc)) + return + + if(!special_check(user)) + return + + if (!ready_to_fire()) + if (world.time % 3) //to prevent spam + to_chat(user, "[src] is not ready to fire again!") + return + + if(!process_chambered()) //CHECK + return click_empty(user) + + if(!in_chamber) + return + if(!istype(src, /obj/item/weapon/gun/energy/laser/redtag) && !istype(src, /obj/item/weapon/gun/energy/laser/redtag)) + log_attack("[user.name] ([user.ckey]) fired \the [src] (proj:[in_chamber.name]) at [target] [ismob(target) ? "([target:ckey])" : ""] ([target.x],[target.y],[target.z])[struggle ? " due to being disarmed." :""]" ) + in_chamber.firer = user + + if(user.zone_sel) + in_chamber.def_zone = user.zone_sel.selecting + else + in_chamber.def_zone = "chest" + + if(targloc == curloc) + user.bullet_act(in_chamber) + qdel(in_chamber) + in_chamber = null + update_icon() + return + + if(recoil) + spawn() + shake_camera(user, recoil + 1, recoil) + if(user.locked_to && isobj(user.locked_to) && !user.locked_to.anchored ) + var/direction = get_dir(user,target) + spawn() + var/obj/B = user.locked_to + var/movementdirection = turn(direction,180) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) + user.inertia_dir = get_dir(target, user) + step(user, user.inertia_dir) + + if(silenced) + playsound(user, fire_sound, 10, 1) + else + playsound(user, fire_sound, 50, 1) + user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \ + "You fire [src][reflex ? "by reflex":""]!", \ + "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") + + in_chamber.original = target + in_chamber.loc = get_turf(user) + in_chamber.starting = get_turf(user) + in_chamber.shot_from = src + user.delayNextAttack(4) // TODO: Should be delayed per-gun. + in_chamber.silenced = silenced + in_chamber.current = curloc + in_chamber.OnFired() + in_chamber.yo = targloc.y - curloc.y + in_chamber.xo = targloc.x - curloc.x + in_chamber.inaccurate = (istype(user.locked_to, /obj/structure/bed/chair/vehicle)) + + if(params) + var/list/mouse_control = params2list(params) + if(mouse_control["icon-x"]) + in_chamber.p_x = text2num(mouse_control["icon-x"]) + if(mouse_control["icon-y"]) + in_chamber.p_y = text2num(mouse_control["icon-y"]) + + spawn() + if(in_chamber) + in_chamber.process() + sleep(1) + in_chamber = null + + update_icon() + + if(user.hand) + user.update_inv_l_hand() + else + user.update_inv_r_hand() + +/obj/item/weapon/gun/proc/can_fire() + return process_chambered() + +/obj/item/weapon/gun/proc/can_hit(var/mob/living/target as mob, var/mob/living/user as mob) + return in_chamber.check_fire(target,user) + +/obj/item/weapon/gun/proc/click_empty(mob/user = null) + if (user) + user.visible_message("*click click*", "*click*") + playsound(user, 'sound/weapons/empty.ogg', 100, 1) + else + src.visible_message("*click click*") + playsound(get_turf(src), 'sound/weapons/empty.ogg', 100, 1) + +/obj/item/weapon/gun/attack(mob/living/M as mob, mob/living/user as mob, def_zone) + //Suicide handling. + if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot) + if(istype(M.wear_mask, /obj/item/clothing/mask/happy)) + to_chat(M, "BUT WHY? I'M SO HAPPY!") + return + mouthshoot = 1 + M.visible_message("[user] sticks their gun in their mouth, ready to pull the trigger...") + if(!do_after(user,src, 40)) + M.visible_message("[user] decided life was worth living") + mouthshoot = 0 + return + if (process_chambered()) + user.visible_message("[user] pulls the trigger.") + if(silenced) + playsound(user, fire_sound, 10, 1) + else + playsound(user, fire_sound, 50, 1) + in_chamber.on_hit(M) + if (!in_chamber.nodamage) + user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]") + user.stat=2 // Just to be sure + user.death() + var/suicidesound = pick('sound/misc/suicide/suicide1.ogg','sound/misc/suicide/suicide2.ogg','sound/misc/suicide/suicide3.ogg','sound/misc/suicide/suicide4.ogg','sound/misc/suicide/suicide5.ogg','sound/misc/suicide/suicide6.ogg') + playsound(get_turf(src), pick(suicidesound), 10, channel = 125) + else + to_chat(user, "Ow...") + user.apply_effect(110,AGONY,0) + qdel(in_chamber) + in_chamber = null + mouthshoot = 0 + return + else + click_empty(user) + mouthshoot = 0 + return + + if (src.process_chambered()) + //Point blank shooting if on harm intent or target we were targeting. + if(user.a_intent == I_HURT) + user.visible_message(" \The [user] fires \the [src] point blank at [M]!") + in_chamber.damage *= 1.3 + src.Fire(M,user,0,0,1) + return + else if(target && M in target) + src.Fire(M,user,0,0,1) ///Otherwise, shoot! + return + else + return ..() //Allows a player to choose to melee instead of shoot, by being on help intent. + else + return ..() //Pistolwhippin' diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 133b69f7d71..c0b69265acd 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -1,65 +1,65 @@ -/obj/item/weapon/gun/energy - icon_state = "energy" - name = "energy gun" - desc = "A basic energy-based gun." - fire_sound = 'sound/weapons/Taser.ogg' - - var/obj/item/weapon/cell/power_supply //What type of power cell this uses - var/charge_cost = 100 //How much energy is needed to fire. - var/cell_type = "/obj/item/weapon/cell" - var/projectile_type = "/obj/item/projectile/beam/practice" - var/modifystate - var/charge_states = 1 //if the gun changes icon states depending on charge, this is 1. Uses a var so it can be changed easily - -/obj/item/weapon/gun/energy/emp_act(severity) - power_supply.use(round(power_supply.maxcharge / severity)) - update_icon() - ..() - -/obj/item/weapon/gun/energy/process_chambered() - if(in_chamber) return 1 - if(!power_supply) return 0 - if(!power_supply.use(charge_cost)) return 0 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - return 1 - -/obj/item/weapon/gun/energy/update_icon() - var/ratio = 0 - - if(power_supply && power_supply.maxcharge > 0) //If the gun has a power cell, calculate how much % power is left in it - ratio = power_supply.charge / power_supply.maxcharge - - //If there's no power cell, the gun looks as if it had an empty power cell - - ratio *= 100 - ratio = Clamp(ratio, 0, 100) //Value between 0 and 100 - - if(ratio >= 50) - ratio = Floor(ratio, 25) - else - ratio = Ceiling(ratio, 25) - - if(modifystate && charge_states) - icon_state = "[modifystate][ratio]" - else if(charge_states) - icon_state = "[initial(icon_state)][ratio]" - -/obj/item/weapon/gun/energy/New() - . = ..() - - if(cell_type) - power_supply = new cell_type(src) - else - power_supply = new(src) - - power_supply.give(power_supply.maxcharge) - -/* -/obj/item/weapon/gun/energy/Destroy() - if(power_supply) - power_supply.loc = get_turf(src) - power_supply = null - - ..() +/obj/item/weapon/gun/energy + icon_state = "energy" + name = "energy gun" + desc = "A basic energy-based gun." + fire_sound = 'sound/weapons/Taser.ogg' + + var/obj/item/weapon/cell/power_supply //What type of power cell this uses + var/charge_cost = 100 //How much energy is needed to fire. + var/cell_type = "/obj/item/weapon/cell" + var/projectile_type = "/obj/item/projectile/beam/practice" + var/modifystate + var/charge_states = 1 //if the gun changes icon states depending on charge, this is 1. Uses a var so it can be changed easily + +/obj/item/weapon/gun/energy/emp_act(severity) + power_supply.use(round(power_supply.maxcharge / severity)) + update_icon() + ..() + +/obj/item/weapon/gun/energy/process_chambered() + if(in_chamber) return 1 + if(!power_supply) return 0 + if(!power_supply.use(charge_cost)) return 0 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + return 1 + +/obj/item/weapon/gun/energy/update_icon() + var/ratio = 0 + + if(power_supply && power_supply.maxcharge > 0) //If the gun has a power cell, calculate how much % power is left in it + ratio = power_supply.charge / power_supply.maxcharge + + //If there's no power cell, the gun looks as if it had an empty power cell + + ratio *= 100 + ratio = Clamp(ratio, 0, 100) //Value between 0 and 100 + + if(ratio >= 50) + ratio = Floor(ratio, 25) + else + ratio = Ceiling(ratio, 25) + + if(modifystate && charge_states) + icon_state = "[modifystate][ratio]" + else if(charge_states) + icon_state = "[initial(icon_state)][ratio]" + +/obj/item/weapon/gun/energy/New() + . = ..() + + if(cell_type) + power_supply = new cell_type(src) + else + power_supply = new(src) + + power_supply.give(power_supply.maxcharge) + +/* +/obj/item/weapon/gun/energy/Destroy() + if(power_supply) + power_supply.loc = get_turf(src) + power_supply = null + + ..() */ \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index bcbca140be7..d9b5926a4c8 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -1,342 +1,342 @@ -/obj/item/weapon/gun/energy/laser - name = "laser gun" - desc = "A basic weapon designed to kill with concentrated energy bolts." - icon_state = "laser" - item_state = "laser" - fire_sound = 'sound/weapons/Laser.ogg' - w_class = 3.0 - starting_materials = list(MAT_IRON = 2000) - w_type = RECYK_ELECTRONIC - origin_tech = "combat=3;magnets=2" - projectile_type = "/obj/item/projectile/beam" - -/obj/item/weapon/gun/energy/laser/practice - name = "practice laser gun" - desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice." - projectile_type = "/obj/item/projectile/beam/practice" - clumsy_check = 0 - mech_flags = null // So it can be scanned by the Device Analyser - -/obj/item/weapon/gun/energy/laser/pistol - name = "laser pistol" - desc = "A laser pistol issued to high ranking members of a certain shadow corporation." - icon_state = "xcomlaserpistol" - item_state = null - projectile_type = /obj/item/projectile/beam - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - charge_cost = 100 // holds less "ammo" then the rifle variant. - -/obj/item/weapon/gun/energy/laser/rifle - name = "laser rifle" - desc = "A laser rifle issued to high ranking members of a certain shadow corporation." - icon_state = "xcomlasergun" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - projectile_type = /obj/item/projectile/beam - charge_cost = 50 - -/obj/item/weapon/gun/energy/laser/admin - name = "infinite laser gun" - desc = "Spray and /pray." - icon_state = "laseradmin" - projectile_type = /obj/item/projectile/beam - charge_cost = 0 - -/obj/item/weapon/gun/energy/laser/admin/update_icon() - return - -/obj/item/weapon/gun/energy/laser/blaster - name = "blaster rifle" - desc = "An E-11 blaster rifle, made by BlasTech on the cheap." - icon_state = "blaster" - fire_sound = "sound/weapons/blaster-storm.ogg" - -/obj/item/weapon/gun/energy/laser/blaster/New() - ..() - if(prob(50)) - charge_cost = 0 - projectile_type = /obj/item/projectile/beam/practice/stormtrooper - desc = "Don't expect to hit anything with this." - -/obj/item/weapon/gun/energy/laser/blaster/update_icon() - -obj/item/weapon/gun/energy/laser/retro - name ="retro laser" - icon_state = "retro" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." - projectile_type = /obj/item/projectile/beam/retro - -/obj/item/weapon/gun/energy/laser/captain - icon_state = "caplaser" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding." - force = 10 - origin_tech = null - var/charge_tick = 0 - projectile_type = "/obj/item/projectile/beam/captain" - - -/obj/item/weapon/gun/energy/laser/captain/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/laser/captain/Destroy() - processing_objects.Remove(src) - ..() - - -/obj/item/weapon/gun/energy/laser/captain/process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - update_icon() - return 1 - - - -/*/obj/item/weapon/gun/energy/laser/cyborg/load_into_chamber() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(100) - in_chamber = new/obj/item/projectile/beam(src) - return 1 - return 0*/ - -/obj/item/weapon/gun/energy/laser/cyborg - var/charge_tick = 0 - New() - ..() - processing_objects.Add(src) - - - Destroy() - processing_objects.Remove(src) - ..() - - process() //Every [recharge_time] ticks, recharge a shot for the cyborg - charge_tick++ - if(charge_tick < 3) return 0 - charge_tick = 0 - - if(!power_supply) return 0 //sanity - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(charge_cost) //Take power from the borg... - power_supply.give(charge_cost) //... to recharge the shot - - update_icon() - return 1 - - - -/obj/item/weapon/gun/energy/lasercannon - name = "laser cannon" - desc = "With the L.A.S.E.R. cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!" - icon_state = "lasercannon" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/lasercannonfire.ogg' - origin_tech = "combat=4;materials=3;powerstorage=3" - projectile_type = "/obj/item/projectile/beam/heavylaser" - - fire_delay = 2 - - isHandgun() - return 0 - -/obj/item/weapon/gun/energy/lasercannon/cyborg/process_chambered() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(250) - in_chamber = new/obj/item/projectile/beam/heavylaser(src) - return 1 - return 0 - -/obj/item/weapon/gun/energy/xray - name = "xray laser gun" - desc = "A high-power laser gun capable of expelling concentrated xray blasts." - icon_state = "xray" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/laser3.ogg' - origin_tech = "combat=5;materials=3;magnets=2;syndicate=2" - projectile_type = "/obj/item/projectile/beam/xray" - charge_cost = 50 - - -/obj/item/weapon/gun/energy/plasma - name = "plasma gun" - desc = "A high-power plasma gun. You shouldn't ever see this." - icon_state = "xray" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/elecfire.ogg' - origin_tech = "combat=5;materials=3;magnets=2" - projectile_type = /obj/item/projectile/energy/plasma - charge_cost = 50 - -/obj/item/weapon/gun/energy/plasma/pistol - name = "plasma pistol" - desc = "A state of the art pistol utilizing plasma in a uranium-235 lined core to output searing bolts of energy." - icon_state = "alienpistol" - item_state = null - w_class = 2.0 - projectile_type = /obj/item/projectile/energy/plasma/pistol - charge_cost = 50 - -/obj/item/weapon/gun/energy/plasma/light - name = "plasma rifle" - desc = "A state of the art rifle utilizing plasma in a uranium-235 lined core to output radiating bolts of energy." - icon_state = "lightalienrifle" - item_state = null - projectile_type = /obj/item/projectile/energy/plasma/light - charge_cost = 100 - -/obj/item/weapon/gun/energy/plasma/rifle - name = "plasma cannon" - desc = "A state of the art cannon utilizing plasma in a uranium-235 lined core to output hi-power, radiating bolts of energy." - icon_state = "alienrifle" - item_state = null - w_class = 4.0 - slot_flags = null - projectile_type = /obj/item/projectile/energy/plasma/rifle - charge_cost = 150 - -/obj/item/weapon/gun/energy/plasma/MP40k - name = "Plasma MP40k" - desc = "A plasma MP40k. Ich liebe den geruch von plasma am morgen." - icon_state = "PlasMP" - item_state = null - projectile_type = /obj/item/projectile/energy/plasma/MP40k - charge_cost = 75 - -/obj/item/weapon/gun/energy/laser/LaserAK - name = "Laser AK470" - desc = "A laser AK. Death solves all problems -- No man, no problem." - icon_state = "LaserAK" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - projectile_type = /obj/item/projectile/beam - charge_cost = 75 - -////////Laser Tag//////////////////// - -/obj/item/weapon/gun/energy/laser/bluetag - name = "laser tag gun" - icon_state = "bluetag" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - desc = "Standard issue weapon of the Imperial Guard." - projectile_type = "/obj/item/projectile/beam/lastertag/blue" - origin_tech = "magnets=2" - mech_flags = null // So it can be scanned by the Device Analyser - clumsy_check = 0 - var/charge_tick = 0 - -/obj/item/weapon/gun/energy/laser/bluetag/special_check(var/mob/living/carbon/human/M) - if(ishuman(M)) - if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag)) - return 1 - to_chat(M, "You need to be wearing your laser tag vest!") - return 0 - -/obj/item/weapon/gun/energy/laser/bluetag/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/laser/bluetag/Destroy() - processing_objects.Remove(src) - ..() - - -/obj/item/weapon/gun/energy/laser/bluetag/process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - update_icon() - return 1 - - - -/obj/item/weapon/gun/energy/laser/redtag - name = "laser tag gun" - icon_state = "redtag" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - desc = "Standard issue weapon of the Imperial Guard." - projectile_type = "/obj/item/projectile/beam/lastertag/red" - origin_tech = "magnets=2" - mech_flags = null // So it can be scanned by the Device Analyser - clumsy_check = 0 - var/charge_tick = 0 - -/obj/item/weapon/gun/energy/laser/redtag/special_check(var/mob/living/carbon/human/M) - if(ishuman(M)) - if(istype(M.wear_suit, /obj/item/clothing/suit/redtag)) - return 1 - to_chat(M, "You need to be wearing your laser tag vest!") - return 0 - -/obj/item/weapon/gun/energy/laser/redtag/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/laser/redtag/Destroy() - processing_objects.Remove(src) - ..() - - -/obj/item/weapon/gun/energy/laser/redtag/process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - update_icon() - return 1 - - -/obj/item/weapon/gun/energy/megabuster - name = "Mega-buster" - desc = "An arm-mounted buster toy!" - icon_state = "megabuster" - item_state = null - w_class = 2.0 - projectile_type = "/obj/item/projectile/energy/megabuster" - charge_states = 0 - charge_cost = 5 - fire_sound = 'sound/weapons/megabuster.ogg' - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/megabusters.dmi', "right_hand" = 'icons/mob/in-hand/right/megabusters.dmi') - -/obj/item/weapon/gun/energy/megabuster/proto - name = "Proto-buster" - icon_state = "protobuster" - -/obj/item/weapon/gun/energy/mmlbuster - name = "Buster Cannon" - desc = "An antique arm-mounted buster cannon." - icon_state = "mmlbuster" - item_state = null - w_class = 2.0 - charge_states = 0 - projectile_type = "/obj/item/projectile/energy/buster" - charge_cost = 25 - fire_sound = 'sound/weapons/mmlbuster.ogg' - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/megabusters.dmi', "right_hand" = 'icons/mob/in-hand/right/megabusters.dmi') +/obj/item/weapon/gun/energy/laser + name = "laser gun" + desc = "A basic weapon designed to kill with concentrated energy bolts." + icon_state = "laser" + item_state = "laser" + fire_sound = 'sound/weapons/Laser.ogg' + w_class = 3.0 + starting_materials = list(MAT_IRON = 2000) + w_type = RECYK_ELECTRONIC + origin_tech = "combat=3;magnets=2" + projectile_type = "/obj/item/projectile/beam" + +/obj/item/weapon/gun/energy/laser/practice + name = "practice laser gun" + desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice." + projectile_type = "/obj/item/projectile/beam/practice" + clumsy_check = 0 + mech_flags = null // So it can be scanned by the Device Analyser + +/obj/item/weapon/gun/energy/laser/pistol + name = "laser pistol" + desc = "A laser pistol issued to high ranking members of a certain shadow corporation." + icon_state = "xcomlaserpistol" + item_state = null + projectile_type = /obj/item/projectile/beam + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + charge_cost = 100 // holds less "ammo" then the rifle variant. + +/obj/item/weapon/gun/energy/laser/rifle + name = "laser rifle" + desc = "A laser rifle issued to high ranking members of a certain shadow corporation." + icon_state = "xcomlasergun" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + projectile_type = /obj/item/projectile/beam + charge_cost = 50 + +/obj/item/weapon/gun/energy/laser/admin + name = "infinite laser gun" + desc = "Spray and /pray." + icon_state = "laseradmin" + projectile_type = /obj/item/projectile/beam + charge_cost = 0 + +/obj/item/weapon/gun/energy/laser/admin/update_icon() + return + +/obj/item/weapon/gun/energy/laser/blaster + name = "blaster rifle" + desc = "An E-11 blaster rifle, made by BlasTech on the cheap." + icon_state = "blaster" + fire_sound = "sound/weapons/blaster-storm.ogg" + +/obj/item/weapon/gun/energy/laser/blaster/New() + ..() + if(prob(50)) + charge_cost = 0 + projectile_type = /obj/item/projectile/beam/practice/stormtrooper + desc = "Don't expect to hit anything with this." + +/obj/item/weapon/gun/energy/laser/blaster/update_icon() + +obj/item/weapon/gun/energy/laser/retro + name ="retro laser" + icon_state = "retro" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." + projectile_type = /obj/item/projectile/beam/retro + +/obj/item/weapon/gun/energy/laser/captain + icon_state = "caplaser" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding." + force = 10 + origin_tech = null + var/charge_tick = 0 + projectile_type = "/obj/item/projectile/beam/captain" + + +/obj/item/weapon/gun/energy/laser/captain/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/laser/captain/Destroy() + processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/energy/laser/captain/process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + update_icon() + return 1 + + + +/*/obj/item/weapon/gun/energy/laser/cyborg/load_into_chamber() + if(in_chamber) + return 1 + if(isrobot(src.loc)) + var/mob/living/silicon/robot/R = src.loc + if(R && R.cell) + R.cell.use(100) + in_chamber = new/obj/item/projectile/beam(src) + return 1 + return 0*/ + +/obj/item/weapon/gun/energy/laser/cyborg + var/charge_tick = 0 + New() + ..() + processing_objects.Add(src) + + + Destroy() + processing_objects.Remove(src) + ..() + + process() //Every [recharge_time] ticks, recharge a shot for the cyborg + charge_tick++ + if(charge_tick < 3) return 0 + charge_tick = 0 + + if(!power_supply) return 0 //sanity + if(isrobot(src.loc)) + var/mob/living/silicon/robot/R = src.loc + if(R && R.cell) + R.cell.use(charge_cost) //Take power from the borg... + power_supply.give(charge_cost) //... to recharge the shot + + update_icon() + return 1 + + + +/obj/item/weapon/gun/energy/lasercannon + name = "laser cannon" + desc = "With the L.A.S.E.R. cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!" + icon_state = "lasercannon" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/lasercannonfire.ogg' + origin_tech = "combat=4;materials=3;powerstorage=3" + projectile_type = "/obj/item/projectile/beam/heavylaser" + + fire_delay = 2 + + isHandgun() + return 0 + +/obj/item/weapon/gun/energy/lasercannon/cyborg/process_chambered() + if(in_chamber) + return 1 + if(isrobot(src.loc)) + var/mob/living/silicon/robot/R = src.loc + if(R && R.cell) + R.cell.use(250) + in_chamber = new/obj/item/projectile/beam/heavylaser(src) + return 1 + return 0 + +/obj/item/weapon/gun/energy/xray + name = "xray laser gun" + desc = "A high-power laser gun capable of expelling concentrated xray blasts." + icon_state = "xray" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/laser3.ogg' + origin_tech = "combat=5;materials=3;magnets=2;syndicate=2" + projectile_type = "/obj/item/projectile/beam/xray" + charge_cost = 50 + + +/obj/item/weapon/gun/energy/plasma + name = "plasma gun" + desc = "A high-power plasma gun. You shouldn't ever see this." + icon_state = "xray" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/elecfire.ogg' + origin_tech = "combat=5;materials=3;magnets=2" + projectile_type = /obj/item/projectile/energy/plasma + charge_cost = 50 + +/obj/item/weapon/gun/energy/plasma/pistol + name = "plasma pistol" + desc = "A state of the art pistol utilizing plasma in a uranium-235 lined core to output searing bolts of energy." + icon_state = "alienpistol" + item_state = null + w_class = 2.0 + projectile_type = /obj/item/projectile/energy/plasma/pistol + charge_cost = 50 + +/obj/item/weapon/gun/energy/plasma/light + name = "plasma rifle" + desc = "A state of the art rifle utilizing plasma in a uranium-235 lined core to output radiating bolts of energy." + icon_state = "lightalienrifle" + item_state = null + projectile_type = /obj/item/projectile/energy/plasma/light + charge_cost = 100 + +/obj/item/weapon/gun/energy/plasma/rifle + name = "plasma cannon" + desc = "A state of the art cannon utilizing plasma in a uranium-235 lined core to output hi-power, radiating bolts of energy." + icon_state = "alienrifle" + item_state = null + w_class = 4.0 + slot_flags = null + projectile_type = /obj/item/projectile/energy/plasma/rifle + charge_cost = 150 + +/obj/item/weapon/gun/energy/plasma/MP40k + name = "Plasma MP40k" + desc = "A plasma MP40k. Ich liebe den geruch von plasma am morgen." + icon_state = "PlasMP" + item_state = null + projectile_type = /obj/item/projectile/energy/plasma/MP40k + charge_cost = 75 + +/obj/item/weapon/gun/energy/laser/LaserAK + name = "Laser AK470" + desc = "A laser AK. Death solves all problems -- No man, no problem." + icon_state = "LaserAK" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + projectile_type = /obj/item/projectile/beam + charge_cost = 75 + +////////Laser Tag//////////////////// + +/obj/item/weapon/gun/energy/laser/bluetag + name = "laser tag gun" + icon_state = "bluetag" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + desc = "Standard issue weapon of the Imperial Guard." + projectile_type = "/obj/item/projectile/beam/lastertag/blue" + origin_tech = "magnets=2" + mech_flags = null // So it can be scanned by the Device Analyser + clumsy_check = 0 + var/charge_tick = 0 + +/obj/item/weapon/gun/energy/laser/bluetag/special_check(var/mob/living/carbon/human/M) + if(ishuman(M)) + if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag)) + return 1 + to_chat(M, "You need to be wearing your laser tag vest!") + return 0 + +/obj/item/weapon/gun/energy/laser/bluetag/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/laser/bluetag/Destroy() + processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/energy/laser/bluetag/process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + update_icon() + return 1 + + + +/obj/item/weapon/gun/energy/laser/redtag + name = "laser tag gun" + icon_state = "redtag" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + desc = "Standard issue weapon of the Imperial Guard." + projectile_type = "/obj/item/projectile/beam/lastertag/red" + origin_tech = "magnets=2" + mech_flags = null // So it can be scanned by the Device Analyser + clumsy_check = 0 + var/charge_tick = 0 + +/obj/item/weapon/gun/energy/laser/redtag/special_check(var/mob/living/carbon/human/M) + if(ishuman(M)) + if(istype(M.wear_suit, /obj/item/clothing/suit/redtag)) + return 1 + to_chat(M, "You need to be wearing your laser tag vest!") + return 0 + +/obj/item/weapon/gun/energy/laser/redtag/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/laser/redtag/Destroy() + processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/energy/laser/redtag/process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + update_icon() + return 1 + + +/obj/item/weapon/gun/energy/megabuster + name = "Mega-buster" + desc = "An arm-mounted buster toy!" + icon_state = "megabuster" + item_state = null + w_class = 2.0 + projectile_type = "/obj/item/projectile/energy/megabuster" + charge_states = 0 + charge_cost = 5 + fire_sound = 'sound/weapons/megabuster.ogg' + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/megabusters.dmi', "right_hand" = 'icons/mob/in-hand/right/megabusters.dmi') + +/obj/item/weapon/gun/energy/megabuster/proto + name = "Proto-buster" + icon_state = "protobuster" + +/obj/item/weapon/gun/energy/mmlbuster + name = "Buster Cannon" + desc = "An antique arm-mounted buster cannon." + icon_state = "mmlbuster" + item_state = null + w_class = 2.0 + charge_states = 0 + projectile_type = "/obj/item/projectile/energy/buster" + charge_cost = 25 + fire_sound = 'sound/weapons/mmlbuster.ogg' + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/megabusters.dmi', "right_hand" = 'icons/mob/in-hand/right/megabusters.dmi') diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 06f3aa8ddb4..a4764b3d6df 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -1,127 +1,127 @@ -/obj/item/weapon/gun/energy/gun - name = "energy gun" - desc = "A basic energy-based gun with two settings: Stun and kill." - icon_state = "energystun100" - item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser.ogg' - - charge_cost = 100 //How much energy is needed to fire. - projectile_type = "/obj/item/projectile/energy/electrode" - origin_tech = "combat=3;magnets=2" - modifystate = "energystun" - - var/mode = 0 //0 = stun, 1 = kill - - - attack_self(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - charge_cost = 100 - fire_sound = 'sound/weapons/Laser.ogg' +/obj/item/weapon/gun/energy/gun + name = "energy gun" + desc = "A basic energy-based gun with two settings: Stun and kill." + icon_state = "energystun100" + item_state = null //so the human update icon uses the icon_state instead. + fire_sound = 'sound/weapons/Taser.ogg' + + charge_cost = 100 //How much energy is needed to fire. + projectile_type = "/obj/item/projectile/energy/electrode" + origin_tech = "combat=3;magnets=2" + modifystate = "energystun" + + var/mode = 0 //0 = stun, 1 = kill + + + attack_self(mob/living/user as mob) + switch(mode) + if(0) + mode = 1 + charge_cost = 100 + fire_sound = 'sound/weapons/Laser.ogg' to_chat(user, "[src.name] is now set to kill.") - projectile_type = "/obj/item/projectile/beam" - modifystate = "energykill" - if(1) - mode = 0 - charge_cost = 100 - fire_sound = 'sound/weapons/Taser.ogg' + projectile_type = "/obj/item/projectile/beam" + modifystate = "energykill" + if(1) + mode = 0 + charge_cost = 100 + fire_sound = 'sound/weapons/Taser.ogg' to_chat(user, "[src.name] is now set to stun.") - projectile_type = "/obj/item/projectile/energy/electrode" - modifystate = "energystun" - update_icon() - - - -/obj/item/weapon/gun/energy/gun/nuclear - name = "Advanced Energy Gun" - desc = "An energy gun with an experimental miniaturized reactor." - icon_state = "nucgun" - origin_tech = "combat=3;materials=5;powerstorage=3" - var/lightfail = 0 - var/charge_tick = 0 - - New() - ..() - processing_objects.Add(src) - - - Destroy() - processing_objects.Remove(src) - ..() - - - process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - if((power_supply.charge / power_supply.maxcharge) != 1) - if(!failcheck()) return 0 - power_supply.give(100) - update_icon() - return 1 - - - proc - failcheck() - lightfail = 0 - if (prob(src.reliability)) return 1 //No failure - if (prob(src.reliability)) - for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it - if (src in M.contents) + projectile_type = "/obj/item/projectile/energy/electrode" + modifystate = "energystun" + update_icon() + + + +/obj/item/weapon/gun/energy/gun/nuclear + name = "Advanced Energy Gun" + desc = "An energy gun with an experimental miniaturized reactor." + icon_state = "nucgun" + origin_tech = "combat=3;materials=5;powerstorage=3" + var/lightfail = 0 + var/charge_tick = 0 + + New() + ..() + processing_objects.Add(src) + + + Destroy() + processing_objects.Remove(src) + ..() + + + process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + if((power_supply.charge / power_supply.maxcharge) != 1) + if(!failcheck()) return 0 + power_supply.give(100) + update_icon() + return 1 + + + proc + failcheck() + lightfail = 0 + if (prob(src.reliability)) return 1 //No failure + if (prob(src.reliability)) + for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it + if (src in M.contents) to_chat(M, "Your gun feels pleasantly warm for a moment.") - else + else to_chat(M, "You feel a warm sensation.") - M.apply_effect(rand(3,120), IRRADIATE) - lightfail = 1 - else - for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES - if (src in M.contents) + M.apply_effect(rand(3,120), IRRADIATE) + lightfail = 1 + else + for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES + if (src in M.contents) to_chat(M, "Your gun's reactor overloads!") to_chat(M, "You feel a wave of heat wash over you.") - M.apply_effect(300, IRRADIATE) - crit_fail = 1 //break the gun so it stops recharging - processing_objects.Remove(src) - update_icon() - return 0 - - - update_charge() - if (crit_fail) - overlays += "nucgun-whee" - return - var/ratio = power_supply.charge / power_supply.maxcharge - ratio = round(ratio, 0.25) * 100 - overlays += "nucgun-[ratio]" - - - update_reactor() - if(crit_fail) - overlays += "nucgun-crit" - return - if(lightfail) - overlays += "nucgun-medium" - else if ((power_supply.charge/power_supply.maxcharge) <= 0.5) - overlays += "nucgun-light" - else - overlays += "nucgun-clean" - - - update_mode() - if (mode == 0) - overlays += "nucgun-stun" - else if (mode == 1) - overlays += "nucgun-kill" - - - emp_act(severity) - ..() - reliability -= round(15/severity) - - - update_icon() - overlays.len = 0 - update_charge() - update_reactor() - update_mode() + M.apply_effect(300, IRRADIATE) + crit_fail = 1 //break the gun so it stops recharging + processing_objects.Remove(src) + update_icon() + return 0 + + + update_charge() + if (crit_fail) + overlays += "nucgun-whee" + return + var/ratio = power_supply.charge / power_supply.maxcharge + ratio = round(ratio, 0.25) * 100 + overlays += "nucgun-[ratio]" + + + update_reactor() + if(crit_fail) + overlays += "nucgun-crit" + return + if(lightfail) + overlays += "nucgun-medium" + else if ((power_supply.charge/power_supply.maxcharge) <= 0.5) + overlays += "nucgun-light" + else + overlays += "nucgun-clean" + + + update_mode() + if (mode == 0) + overlays += "nucgun-stun" + else if (mode == 1) + overlays += "nucgun-kill" + + + emp_act(severity) + ..() + reliability -= round(15/severity) + + + update_icon() + overlays.len = 0 + update_charge() + update_reactor() + update_mode() diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index efc0d2044ae..6ae7afabec6 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -1,70 +1,70 @@ -/obj/item/weapon/gun/energy/pulse_rifle - name = "pulse rifle" - desc = "A heavy-duty, pulse-based energy weapon, preferred by front-line combat personnel." - icon_state = "pulse" - item_state = null //so the human update icon uses the icon_state instead. - force = 10 - fire_sound = 'sound/weapons/pulse.ogg' - charge_cost = 200 - projectile_type = "/obj/item/projectile/beam/pulse" - cell_type = "/obj/item/weapon/cell/super" - var/mode = 2 - fire_delay = 2 - - attack_self(mob/living/user as mob) - switch(mode) - if(2) - mode = 0 - charge_cost = 100 - fire_sound = 'sound/weapons/Taser.ogg' +/obj/item/weapon/gun/energy/pulse_rifle + name = "pulse rifle" + desc = "A heavy-duty, pulse-based energy weapon, preferred by front-line combat personnel." + icon_state = "pulse" + item_state = null //so the human update icon uses the icon_state instead. + force = 10 + fire_sound = 'sound/weapons/pulse.ogg' + charge_cost = 200 + projectile_type = "/obj/item/projectile/beam/pulse" + cell_type = "/obj/item/weapon/cell/super" + var/mode = 2 + fire_delay = 2 + + attack_self(mob/living/user as mob) + switch(mode) + if(2) + mode = 0 + charge_cost = 100 + fire_sound = 'sound/weapons/Taser.ogg' to_chat(user, "[src.name] is now set to stun.") - projectile_type = "/obj/item/projectile/energy/electrode" - if(0) - mode = 1 - charge_cost = 100 - fire_sound = 'sound/weapons/Laser.ogg' + projectile_type = "/obj/item/projectile/energy/electrode" + if(0) + mode = 1 + charge_cost = 100 + fire_sound = 'sound/weapons/Laser.ogg' to_chat(user, "[src.name] is now set to kill.") - projectile_type = "/obj/item/projectile/beam" - if(1) - mode = 2 - charge_cost = 200 - fire_sound = 'sound/weapons/pulse.ogg' + projectile_type = "/obj/item/projectile/beam" + if(1) + mode = 2 + charge_cost = 200 + fire_sound = 'sound/weapons/pulse.ogg' to_chat(user, "[src.name] is now set to DESTROY.") - projectile_type = "/obj/item/projectile/beam/pulse" - return - - isHandgun() - return 0 - -/obj/item/weapon/gun/energy/pulse_rifle/cyborg/process_chambered() - if(in_chamber) - return 1 - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(charge_cost) - in_chamber = new/obj/item/projectile/beam(src) - return 1 - return 0 - - -/obj/item/weapon/gun/energy/pulse_rifle/destroyer - name = "pulse destroyer" - desc = "A heavy-duty, pulse-based energy weapon." - cell_type = "/obj/item/weapon/cell/infinite" - - attack_self(mob/living/user as mob) + projectile_type = "/obj/item/projectile/beam/pulse" + return + + isHandgun() + return 0 + +/obj/item/weapon/gun/energy/pulse_rifle/cyborg/process_chambered() + if(in_chamber) + return 1 + if(isrobot(src.loc)) + var/mob/living/silicon/robot/R = src.loc + if(R && R.cell) + R.cell.use(charge_cost) + in_chamber = new/obj/item/projectile/beam(src) + return 1 + return 0 + + +/obj/item/weapon/gun/energy/pulse_rifle/destroyer + name = "pulse destroyer" + desc = "A heavy-duty, pulse-based energy weapon." + cell_type = "/obj/item/weapon/cell/infinite" + + attack_self(mob/living/user as mob) to_chat(user, "[src.name] has three settings, and they are all DESTROY.") - - - -/obj/item/weapon/gun/energy/pulse_rifle/M1911 - name = "m1911-P" - desc = "It's not the size of the gun, it's the size of the hole it puts through people." - icon_state = "m1911-p" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - cell_type = "/obj/item/weapon/cell/infinite" - - isHandgun() + + + +/obj/item/weapon/gun/energy/pulse_rifle/M1911 + name = "m1911-P" + desc = "It's not the size of the gun, it's the size of the hole it puts through people." + icon_state = "m1911-p" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + cell_type = "/obj/item/weapon/cell/infinite" + + isHandgun() return 1 \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 34eb1b91223..f433b9c8cb5 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -1,543 +1,543 @@ -/obj/item/weapon/gun/energy/ionrifle - name = "ion rifle" - desc = "A man portable anti-armor weapon designed to disable mechanical threats" - icon_state = "ionrifle" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/ion.ogg' - origin_tech = "combat=2;magnets=4" - w_class = 4.0 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - charge_cost = 100 - projectile_type = "/obj/item/projectile/ion" - -/obj/item/weapon/gun/energy/ionrifle/emp_act(severity) - if(severity <= 2) - power_supply.use(round(power_supply.maxcharge / severity)) - update_icon() - else - return - -/obj/item/weapon/gun/energy/decloner - name = "biological demolecularisor" - desc = "A gun that discharges high amounts of controlled radiation to slowly break a target into component elements." - icon_state = "decloner" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/pulse3.ogg' - origin_tech = "combat=5;materials=4;powerstorage=3" - charge_cost = 100 - projectile_type = "/obj/item/projectile/energy/declone" - -var/available_staff_transforms=list("monkey","robot","slime","xeno","human","furry") -#define SOC_CHANGETYPE_COOLDOWN 2 MINUTES - -/obj/item/weapon/gun/energy/staff - name = "staff of change" - desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" - icon = 'icons/obj/gun.dmi' - icon_state = "staffofchange" - item_state = "staffofchange" - fire_sound = 'sound/weapons/radgun.ogg' - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - w_class = 4.0 - charge_cost = 200 - projectile_type = "/obj/item/projectile/change" - origin_tech = null - clumsy_check = 0 - var/charge_tick = 0 - var/changetype=null - var/next_changetype=0 - -/obj/item/weapon/gun/energy/staff/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/staff/Destroy() - processing_objects.Remove(src) - ..() - - -/obj/item/weapon/gun/energy/staff/process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(200) - return 1 - -/obj/item/weapon/gun/energy/staff/update_icon() - return - -/obj/item/weapon/gun/energy/staff/process_chambered() - if(!..()) return 0 - var/obj/item/projectile/change/P=in_chamber - if(P && istype(P)) - P.changetype=changetype - return 1 - -/obj/item/weapon/gun/energy/staff/attack_self(var/mob/living/user) - if(world.time < next_changetype) - to_chat(user, "[src] is still recharging.") - return - - var/selected = input("You squint at the dial conspicuously mounted on the side of your staff.","Staff of Change") as null|anything in list("random")+available_staff_transforms - if(!selected) - return - - if (selected == "furry") - to_chat(user, "You monster.") - else - to_chat(user, "You have selected to make your next victim have a [selected] form.") - - switch(selected) - if("random") - changetype=null - else - changetype=selected - next_changetype=world.time+SOC_CHANGETYPE_COOLDOWN - -/obj/item/weapon/gun/energy/staff/animate - name = "staff of animation" - desc = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." - projectile_type = "/obj/item/projectile/animate" - charge_cost = 100 - -/obj/item/weapon/gun/energy/floragun - name = "floral somatoray" - desc = "A tool that discharges controlled radiation which induces mutation in plant cells." - icon_state = "floramut100" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/effects/stealthoff.ogg' - charge_cost = 100 - projectile_type = "/obj/item/projectile/energy/floramut" - origin_tech = "materials=2;biotech=3;powerstorage=3" - mech_flags = null // So it can be scanned by the Device Analyser - modifystate = "floramut" - var/charge_tick = 0 - var/mode = 0 //0 = mutate, 1 = yield boost, 2 = emag-mutate - var/mutstrength = 10 //how many units of mutagen will the mutation projectile act as - -/obj/item/weapon/gun/energy/floragun/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/floragun/Destroy() - processing_objects.Remove(src) - ..() - - -/obj/item/weapon/gun/energy/floragun/process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - update_icon() - return 1 - -/obj/item/weapon/gun/energy/floragun/process_chambered() - . = ..() - if(istype(in_chamber, /obj/item/projectile/energy/floramut)) - var/obj/item/projectile/energy/floramut/P = in_chamber - P.mutstrength = src.mutstrength - -/obj/item/weapon/gun/energy/floragun/attack_self(mob/living/user as mob) - switch(mode) - if(0) - mode = 1 - charge_cost = 100 - to_chat(user, "The [src.name] is now set to improve harvests.") - projectile_type = "/obj/item/projectile/energy/florayield" - modifystate = "florayield" - if(1) - mode = 0 - charge_cost = mutstrength * 10 - to_chat(user, "The [src.name] is now set to induce mutations.") - projectile_type = "/obj/item/projectile/energy/floramut" - modifystate = "floramut" - if(2) - to_chat(user, "The [src.name] appears to be locked into one mode.") - return - update_icon() - return - -/obj/item/weapon/gun/energy/floragun/verb/SetMutationStrength() - set name = "Set mutation strength" - set category = "Object" - if(mode == 2) - mutstrength = input(usr, "Enter new mutation strength level (15-25):", "Somatoray Gamma Ray Threshold", mutstrength) as num - mutstrength = Clamp(round(mutstrength), 15, 25) - else - mutstrength = input(usr, "Enter new mutation strength level (1-15):", "Somatoray Alpha Ray Threshold", mutstrength) as num - mutstrength = Clamp(round(mutstrength), 1, 15) - -/obj/item/weapon/gun/energy/floragun/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isEmag(W) || issolder(W)) - if (mode == 2) - to_chat(user, "The safeties are already de-activated.") - else - mode = 2 - mutstrength = 25 - charge_cost = mutstrength * 10 - projectile_type = "/obj/item/projectile/energy/floramut/emag" - to_chat(user, "You short out the safety limit of the [src.name]!") - desc += " It seems to have it's safety features de-activated." - playsound(get_turf(user), 'sound/effects/sparks4.ogg', 50, 1) - modifystate = "floraemag" - update_icon() - -/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, flag) - if(flag && istype(target,/obj/machinery/portable_atmospherics/hydroponics)) - var/obj/machinery/portable_atmospherics/hydroponics/tray = target - if(process_chambered()) - user.visible_message(" \The [user] fires \the [src] into \the [tray]!") - Fire(target,user) - return - ..() - -/obj/item/weapon/gun/energy/meteorgun - name = "meteor gun" - desc = "For the love of god, make sure you're aiming this the right way!" - icon_state = "riotgun" - item_state = "c20r" - w_class = 4 - projectile_type = "/obj/item/projectile/meteor" - charge_cost = 100 - cell_type = "/obj/item/weapon/cell/potato" - clumsy_check = 0 //Admin spawn only, might as well let clowns use it. - var/charge_tick = 0 - var/recharge_time = 5 //Time it takes for shots to recharge (in ticks) - -/obj/item/weapon/gun/energy/meteorgun/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/meteorgun/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/weapon/gun/energy/meteorgun/process() - charge_tick++ - if(charge_tick < recharge_time) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - -/obj/item/weapon/gun/energy/meteorgun/update_icon() - return - - -/obj/item/weapon/gun/energy/meteorgun/pen - name = "meteor pen" - desc = "The pen is mightier than the sword." - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "pen" - item_state = "pen" - w_class = 1 - - -/obj/item/weapon/gun/energy/mindflayer - name = "mind flayer" - desc = "A prototype weapon recovered from the ruins of Research-Station Epsilon." - icon_state = "xray" - projectile_type = "/obj/item/projectile/beam/mindflayer" - fire_sound = 'sound/weapons/Laser.ogg' - -obj/item/weapon/gun/energy/staff/focus - name = "mental focus" - desc = "An artifact that channels the will of the user into destructive bolts of force. If you aren't careful with it, you might poke someone's brain out.\n Has two modes: Single and AoE" - icon = 'icons/obj/wizard.dmi' - icon_state = "focus" - item_state = "focus" - projectile_type = "/obj/item/projectile/forcebolt" - charge_cost = 100 - -obj/item/weapon/gun/energy/staff/focus/attack_self(mob/living/user as mob) - if(projectile_type == "/obj/item/projectile/forcebolt") - charge_cost = 250 - to_chat(user, "The [src.name] will now strike a small area.") - projectile_type = "/obj/item/projectile/forcebolt/strong" - else - charge_cost = 100 - to_chat(user, "The [src.name] will now strike only a single person.") - projectile_type = "/obj/item/projectile/forcebolt" - -/obj/item/weapon/gun/energy/kinetic_accelerator - name = "proto-kinetic accelerator" - desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified for extreme power output to crush rocks, but often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." - icon_state = "kineticgun" - item_state = "kineticgun" - projectile_type = "/obj/item/projectile/kinetic" - cell_type = "/obj/item/weapon/cell/crap" - charge_cost = 50 - var/overheat = 0 - var/recent_reload = 1 -/* -/obj/item/weapon/gun/energy/kinetic_accelerator/shoot_live_shot() - overheat = 1 - spawn(20) - overheat = 0 - recent_reload = 0 - ..() -*/ -/obj/item/weapon/gun/energy/kinetic_accelerator/attack_self(var/mob/living/user/L) - if(overheat || recent_reload) - return - power_supply.give(500) - playsound(src.loc, 'sound/weapons/shotgunpump.ogg', 60, 1) - recent_reload = 1 - update_icon() - return - -// /vg/ - Broken until we update to /tg/ guncode. -/obj/item/weapon/gun/energy/kinetic_accelerator/update_icon() - return - -/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg - name = "proto-kinetic accelerator" - desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified for extreme power output to crush rocks, but often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." - icon_state = "kineticgun" - item_state = "kineticgun" - projectile_type = "/obj/item/projectile/kinetic" - cell_type = "/obj/item/weapon/cell/miningborg" - charge_cost = 50 - var/charge_tick = 0 - -/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/process() //Every [recharge_time] ticks, recharge a shot for the cyborg - charge_tick++ - if(charge_tick < 3) return 0 - charge_tick = 0 - - if(!power_supply) return 0 //sanity - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(charge_cost) //Take power from the borg... - power_supply.give(charge_cost) //... to recharge the shot - - update_icon() - return 1 - - -/obj/item/weapon/gun/energy/radgun - name = "radgun" - desc = "An experimental energy gun that fires radioactive projectiles that deal toxin damage, irradiate, and scramble DNA, giving the victim a different appearance and name, and potentially harmful or beneficial mutations. Recharges automatically." - icon_state = "radgun" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/radgun.ogg' - charge_cost = 100 - var/charge_tick = 0 - projectile_type = "/obj/item/projectile/energy/rad" - -/obj/item/weapon/gun/energy/radgun/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/radgun/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/weapon/gun/energy/radgun/process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - update_icon() - return 1 - -/obj/item/weapon/gun/energy/ricochet - name = "ricochet rifle" - desc = "They say that these were originally designed for duck games. Not that there's any duck in this part of space." - icon = 'icons/obj/gun_experimental.dmi' - icon_state = "ricochet" - item_state = null - origin_tech = "materials=3;powerstorage=3;combat=3" - slot_flags = SLOT_BELT - projectile_type = "/obj/item/projectile/ricochet" - charge_cost = 100 - cell_type = "/obj/item/weapon/cell" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi') - -/obj/item/weapon/gun/energy/bison - name = "\improper Righteous Bison" - desc = "A replica of Lord Cockswain's very own personnal ray gun." - icon = 'icons/obj/gun_experimental.dmi' - icon_state = "bison" - item_state = null - origin_tech = "materials=3;powerstorage=3;combat=3" - slot_flags = SLOT_BELT - projectile_type = "/obj/item/projectile/beam/bison" - charge_cost = 100 - cell_type = "/obj/item/weapon/cell" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi') - fire_delay = 8 - fire_sound = 'sound/weapons/bison_fire.ogg' - var/pumping = 0 - -/obj/item/weapon/gun/energy/bison/New() - ..() - power_supply.charge = 0 - -/obj/item/weapon/gun/energy/bison/attack_self(mob/user as mob) - if(pumping || !power_supply) return - pumping = 1 - power_supply.charge = min(power_supply.charge + 200,power_supply.maxcharge) - if(power_supply.charge >= power_supply.maxcharge) - playsound(get_turf(src), 'sound/machines/click.ogg', 25, 1) - to_chat(user, "You pull the pump at the back of the gun. Looks like the inner battery is fully charged now.") - else - playsound(get_turf(src), 'sound/weapons/bison_reload.ogg', 25, 1) - to_chat(user, "You pull the pump at the back of the gun.") - sleep(5) - pumping = 0 - update_icon() - -/obj/item/weapon/gun/energy/bison/update_icon() - if(power_supply.charge >= power_supply.maxcharge) - icon_state = "bison100" - else if (power_supply.charge > 0) - icon_state = "bison50" - else - icon_state = "bison0" - return - -#define SPUR_FULL_POWER 4 -#define SPUR_HIGH_POWER 3 -#define SPUR_MEDIUM_POWER 2 -#define SPUR_LOW_POWER 1 -#define SPUR_NO_POWER 0 - -/obj/item/weapon/gun/energy/polarstar - name = "\improper Polar Star" - desc = "Despite being incomplete, the severe wear on this gun shows to which extent it's been used already." - icon = 'icons/obj/gun_experimental.dmi' - icon_state = "polarstar" - item_state = null - slot_flags = SLOT_BELT - fire_delay = 1 - origin_tech = "materials=4;powerstorage=3;combat=3" - projectile_type = "/obj/item/projectile/spur/polarstar" - charge_cost = 100 - cell_type = "/obj/item/weapon/cell" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi') - recoil = 1 - var/firelevel = SPUR_FULL_POWER - -/obj/item/weapon/gun/energy/polarstar/New() - ..() - playsound(get_turf(src), 'sound/weapons/spur_spawn.ogg', 50, 0, null, FALLOFF_SOUNDS, 0) - -/obj/item/weapon/gun/energy/polarstar/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0) - levelChange() - ..() - -/obj/item/weapon/gun/energy/polarstar/proc/levelChange() - var/maxlevel = power_supply.maxcharge - var/level = power_supply.charge - var/newlevel = 0 - if(level == maxlevel) - newlevel = SPUR_FULL_POWER - else if(level >= ((maxlevel/3)*2)) - newlevel = SPUR_HIGH_POWER - else if(level >= (maxlevel/3)) - newlevel = SPUR_MEDIUM_POWER - else if(level >= charge_cost) - newlevel = SPUR_LOW_POWER - else - newlevel = SPUR_NO_POWER - - if(firelevel >= newlevel) - firelevel = newlevel - set_firesound() - return - - firelevel = newlevel - set_firesound() - var/levelupsound = null - switch(firelevel) - if(SPUR_LOW_POWER) - levelupsound = 'sound/weapons/spur_chargelow.ogg' - if(SPUR_MEDIUM_POWER) - levelupsound = 'sound/weapons/spur_chargemed.ogg' - if(SPUR_HIGH_POWER) - levelupsound = 'sound/weapons/spur_chargehigh.ogg' - if(SPUR_FULL_POWER) - levelupsound = 'sound/weapons/spur_chargefull.ogg' - - if(levelupsound) - for(var/mob/M in get_turf(src)) - M.playsound_local(M, levelupsound, 100, 0, null, FALLOFF_SOUNDS, 0) - spawn(1) - M.playsound_local(M, levelupsound, 75, 0, null, FALLOFF_SOUNDS, 0) - - -/obj/item/weapon/gun/energy/polarstar/proc/set_firesound() - switch(firelevel) - if(SPUR_HIGH_POWER,SPUR_FULL_POWER) - fire_sound = 'sound/weapons/spur_high.ogg' - recoil = 1 - if(SPUR_MEDIUM_POWER) - fire_sound = 'sound/weapons/spur_medium.ogg' - recoil = 0 - if(SPUR_LOW_POWER,SPUR_NO_POWER) - fire_sound = 'sound/weapons/spur_low.ogg' - recoil = 0 - return - -/obj/item/weapon/gun/energy/polarstar/update_icon() - return - -/obj/item/weapon/gun/energy/polarstar/spur - name = "\improper Spur" - desc = "A masterpiece crafted by the legendary gunsmith of a far-away planet." - icon_state = "spur" - item_state = null - origin_tech = "materials=5;powerstorage=4;combat=5" - fire_delay = 0 - projectile_type = "/obj/item/projectile/spur" - var/charge_tick = 0 - -/obj/item/weapon/gun/energy/polarstar/spur/New() - ..() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/polarstar/spur/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/weapon/gun/energy/polarstar/spur/process() - charge_tick++ - if(charge_tick < 2) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - levelChange() - return 1 - -#undef SPUR_FULL_POWER -#undef SPUR_HIGH_POWER -#undef SPUR_MEDIUM_POWER -#undef SPUR_LOW_POWER -#undef SPUR_NO_POWER +/obj/item/weapon/gun/energy/ionrifle + name = "ion rifle" + desc = "A man portable anti-armor weapon designed to disable mechanical threats" + icon_state = "ionrifle" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/ion.ogg' + origin_tech = "combat=2;magnets=4" + w_class = 4.0 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + charge_cost = 100 + projectile_type = "/obj/item/projectile/ion" + +/obj/item/weapon/gun/energy/ionrifle/emp_act(severity) + if(severity <= 2) + power_supply.use(round(power_supply.maxcharge / severity)) + update_icon() + else + return + +/obj/item/weapon/gun/energy/decloner + name = "biological demolecularisor" + desc = "A gun that discharges high amounts of controlled radiation to slowly break a target into component elements." + icon_state = "decloner" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/pulse3.ogg' + origin_tech = "combat=5;materials=4;powerstorage=3" + charge_cost = 100 + projectile_type = "/obj/item/projectile/energy/declone" + +var/available_staff_transforms=list("monkey","robot","slime","xeno","human","furry") +#define SOC_CHANGETYPE_COOLDOWN 2 MINUTES + +/obj/item/weapon/gun/energy/staff + name = "staff of change" + desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" + icon = 'icons/obj/gun.dmi' + icon_state = "staffofchange" + item_state = "staffofchange" + fire_sound = 'sound/weapons/radgun.ogg' + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + w_class = 4.0 + charge_cost = 200 + projectile_type = "/obj/item/projectile/change" + origin_tech = null + clumsy_check = 0 + var/charge_tick = 0 + var/changetype=null + var/next_changetype=0 + +/obj/item/weapon/gun/energy/staff/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/staff/Destroy() + processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/energy/staff/process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(200) + return 1 + +/obj/item/weapon/gun/energy/staff/update_icon() + return + +/obj/item/weapon/gun/energy/staff/process_chambered() + if(!..()) return 0 + var/obj/item/projectile/change/P=in_chamber + if(P && istype(P)) + P.changetype=changetype + return 1 + +/obj/item/weapon/gun/energy/staff/attack_self(var/mob/living/user) + if(world.time < next_changetype) + to_chat(user, "[src] is still recharging.") + return + + var/selected = input("You squint at the dial conspicuously mounted on the side of your staff.","Staff of Change") as null|anything in list("random")+available_staff_transforms + if(!selected) + return + + if (selected == "furry") + to_chat(user, "You monster.") + else + to_chat(user, "You have selected to make your next victim have a [selected] form.") + + switch(selected) + if("random") + changetype=null + else + changetype=selected + next_changetype=world.time+SOC_CHANGETYPE_COOLDOWN + +/obj/item/weapon/gun/energy/staff/animate + name = "staff of animation" + desc = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." + projectile_type = "/obj/item/projectile/animate" + charge_cost = 100 + +/obj/item/weapon/gun/energy/floragun + name = "floral somatoray" + desc = "A tool that discharges controlled radiation which induces mutation in plant cells." + icon_state = "floramut100" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/effects/stealthoff.ogg' + charge_cost = 100 + projectile_type = "/obj/item/projectile/energy/floramut" + origin_tech = "materials=2;biotech=3;powerstorage=3" + mech_flags = null // So it can be scanned by the Device Analyser + modifystate = "floramut" + var/charge_tick = 0 + var/mode = 0 //0 = mutate, 1 = yield boost, 2 = emag-mutate + var/mutstrength = 10 //how many units of mutagen will the mutation projectile act as + +/obj/item/weapon/gun/energy/floragun/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/floragun/Destroy() + processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/energy/floragun/process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + update_icon() + return 1 + +/obj/item/weapon/gun/energy/floragun/process_chambered() + . = ..() + if(istype(in_chamber, /obj/item/projectile/energy/floramut)) + var/obj/item/projectile/energy/floramut/P = in_chamber + P.mutstrength = src.mutstrength + +/obj/item/weapon/gun/energy/floragun/attack_self(mob/living/user as mob) + switch(mode) + if(0) + mode = 1 + charge_cost = 100 + to_chat(user, "The [src.name] is now set to improve harvests.") + projectile_type = "/obj/item/projectile/energy/florayield" + modifystate = "florayield" + if(1) + mode = 0 + charge_cost = mutstrength * 10 + to_chat(user, "The [src.name] is now set to induce mutations.") + projectile_type = "/obj/item/projectile/energy/floramut" + modifystate = "floramut" + if(2) + to_chat(user, "The [src.name] appears to be locked into one mode.") + return + update_icon() + return + +/obj/item/weapon/gun/energy/floragun/verb/SetMutationStrength() + set name = "Set mutation strength" + set category = "Object" + if(mode == 2) + mutstrength = input(usr, "Enter new mutation strength level (15-25):", "Somatoray Gamma Ray Threshold", mutstrength) as num + mutstrength = Clamp(round(mutstrength), 15, 25) + else + mutstrength = input(usr, "Enter new mutation strength level (1-15):", "Somatoray Alpha Ray Threshold", mutstrength) as num + mutstrength = Clamp(round(mutstrength), 1, 15) + +/obj/item/weapon/gun/energy/floragun/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isEmag(W) || issolder(W)) + if (mode == 2) + to_chat(user, "The safeties are already de-activated.") + else + mode = 2 + mutstrength = 25 + charge_cost = mutstrength * 10 + projectile_type = "/obj/item/projectile/energy/floramut/emag" + to_chat(user, "You short out the safety limit of the [src.name]!") + desc += " It seems to have it's safety features de-activated." + playsound(get_turf(user), 'sound/effects/sparks4.ogg', 50, 1) + modifystate = "floraemag" + update_icon() + +/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, flag) + if(flag && istype(target,/obj/machinery/portable_atmospherics/hydroponics)) + var/obj/machinery/portable_atmospherics/hydroponics/tray = target + if(process_chambered()) + user.visible_message(" \The [user] fires \the [src] into \the [tray]!") + Fire(target,user) + return + ..() + +/obj/item/weapon/gun/energy/meteorgun + name = "meteor gun" + desc = "For the love of god, make sure you're aiming this the right way!" + icon_state = "riotgun" + item_state = "c20r" + w_class = 4 + projectile_type = "/obj/item/projectile/meteor" + charge_cost = 100 + cell_type = "/obj/item/weapon/cell/potato" + clumsy_check = 0 //Admin spawn only, might as well let clowns use it. + var/charge_tick = 0 + var/recharge_time = 5 //Time it takes for shots to recharge (in ticks) + +/obj/item/weapon/gun/energy/meteorgun/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/meteorgun/Destroy() + processing_objects.Remove(src) + ..() + +/obj/item/weapon/gun/energy/meteorgun/process() + charge_tick++ + if(charge_tick < recharge_time) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + +/obj/item/weapon/gun/energy/meteorgun/update_icon() + return + + +/obj/item/weapon/gun/energy/meteorgun/pen + name = "meteor pen" + desc = "The pen is mightier than the sword." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "pen" + item_state = "pen" + w_class = 1 + + +/obj/item/weapon/gun/energy/mindflayer + name = "mind flayer" + desc = "A prototype weapon recovered from the ruins of Research-Station Epsilon." + icon_state = "xray" + projectile_type = "/obj/item/projectile/beam/mindflayer" + fire_sound = 'sound/weapons/Laser.ogg' + +obj/item/weapon/gun/energy/staff/focus + name = "mental focus" + desc = "An artifact that channels the will of the user into destructive bolts of force. If you aren't careful with it, you might poke someone's brain out.\n Has two modes: Single and AoE" + icon = 'icons/obj/wizard.dmi' + icon_state = "focus" + item_state = "focus" + projectile_type = "/obj/item/projectile/forcebolt" + charge_cost = 100 + +obj/item/weapon/gun/energy/staff/focus/attack_self(mob/living/user as mob) + if(projectile_type == "/obj/item/projectile/forcebolt") + charge_cost = 250 + to_chat(user, "The [src.name] will now strike a small area.") + projectile_type = "/obj/item/projectile/forcebolt/strong" + else + charge_cost = 100 + to_chat(user, "The [src.name] will now strike only a single person.") + projectile_type = "/obj/item/projectile/forcebolt" + +/obj/item/weapon/gun/energy/kinetic_accelerator + name = "proto-kinetic accelerator" + desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified for extreme power output to crush rocks, but often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." + icon_state = "kineticgun" + item_state = "kineticgun" + projectile_type = "/obj/item/projectile/kinetic" + cell_type = "/obj/item/weapon/cell/crap" + charge_cost = 50 + var/overheat = 0 + var/recent_reload = 1 +/* +/obj/item/weapon/gun/energy/kinetic_accelerator/shoot_live_shot() + overheat = 1 + spawn(20) + overheat = 0 + recent_reload = 0 + ..() +*/ +/obj/item/weapon/gun/energy/kinetic_accelerator/attack_self(var/mob/living/user/L) + if(overheat || recent_reload) + return + power_supply.give(500) + playsound(src.loc, 'sound/weapons/shotgunpump.ogg', 60, 1) + recent_reload = 1 + update_icon() + return + +// /vg/ - Broken until we update to /tg/ guncode. +/obj/item/weapon/gun/energy/kinetic_accelerator/update_icon() + return + +/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg + name = "proto-kinetic accelerator" + desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified for extreme power output to crush rocks, but often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." + icon_state = "kineticgun" + item_state = "kineticgun" + projectile_type = "/obj/item/projectile/kinetic" + cell_type = "/obj/item/weapon/cell/miningborg" + charge_cost = 50 + var/charge_tick = 0 + +/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/Destroy() + processing_objects.Remove(src) + ..() + +/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/process() //Every [recharge_time] ticks, recharge a shot for the cyborg + charge_tick++ + if(charge_tick < 3) return 0 + charge_tick = 0 + + if(!power_supply) return 0 //sanity + if(isrobot(src.loc)) + var/mob/living/silicon/robot/R = src.loc + if(R && R.cell) + R.cell.use(charge_cost) //Take power from the borg... + power_supply.give(charge_cost) //... to recharge the shot + + update_icon() + return 1 + + +/obj/item/weapon/gun/energy/radgun + name = "radgun" + desc = "An experimental energy gun that fires radioactive projectiles that deal toxin damage, irradiate, and scramble DNA, giving the victim a different appearance and name, and potentially harmful or beneficial mutations. Recharges automatically." + icon_state = "radgun" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/radgun.ogg' + charge_cost = 100 + var/charge_tick = 0 + projectile_type = "/obj/item/projectile/energy/rad" + +/obj/item/weapon/gun/energy/radgun/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/radgun/Destroy() + processing_objects.Remove(src) + ..() + +/obj/item/weapon/gun/energy/radgun/process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + update_icon() + return 1 + +/obj/item/weapon/gun/energy/ricochet + name = "ricochet rifle" + desc = "They say that these were originally designed for duck games. Not that there's any duck in this part of space." + icon = 'icons/obj/gun_experimental.dmi' + icon_state = "ricochet" + item_state = null + origin_tech = "materials=3;powerstorage=3;combat=3" + slot_flags = SLOT_BELT + projectile_type = "/obj/item/projectile/ricochet" + charge_cost = 100 + cell_type = "/obj/item/weapon/cell" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi') + +/obj/item/weapon/gun/energy/bison + name = "\improper Righteous Bison" + desc = "A replica of Lord Cockswain's very own personnal ray gun." + icon = 'icons/obj/gun_experimental.dmi' + icon_state = "bison" + item_state = null + origin_tech = "materials=3;powerstorage=3;combat=3" + slot_flags = SLOT_BELT + projectile_type = "/obj/item/projectile/beam/bison" + charge_cost = 100 + cell_type = "/obj/item/weapon/cell" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi') + fire_delay = 8 + fire_sound = 'sound/weapons/bison_fire.ogg' + var/pumping = 0 + +/obj/item/weapon/gun/energy/bison/New() + ..() + power_supply.charge = 0 + +/obj/item/weapon/gun/energy/bison/attack_self(mob/user as mob) + if(pumping || !power_supply) return + pumping = 1 + power_supply.charge = min(power_supply.charge + 200,power_supply.maxcharge) + if(power_supply.charge >= power_supply.maxcharge) + playsound(get_turf(src), 'sound/machines/click.ogg', 25, 1) + to_chat(user, "You pull the pump at the back of the gun. Looks like the inner battery is fully charged now.") + else + playsound(get_turf(src), 'sound/weapons/bison_reload.ogg', 25, 1) + to_chat(user, "You pull the pump at the back of the gun.") + sleep(5) + pumping = 0 + update_icon() + +/obj/item/weapon/gun/energy/bison/update_icon() + if(power_supply.charge >= power_supply.maxcharge) + icon_state = "bison100" + else if (power_supply.charge > 0) + icon_state = "bison50" + else + icon_state = "bison0" + return + +#define SPUR_FULL_POWER 4 +#define SPUR_HIGH_POWER 3 +#define SPUR_MEDIUM_POWER 2 +#define SPUR_LOW_POWER 1 +#define SPUR_NO_POWER 0 + +/obj/item/weapon/gun/energy/polarstar + name = "\improper Polar Star" + desc = "Despite being incomplete, the severe wear on this gun shows to which extent it's been used already." + icon = 'icons/obj/gun_experimental.dmi' + icon_state = "polarstar" + item_state = null + slot_flags = SLOT_BELT + fire_delay = 1 + origin_tech = "materials=4;powerstorage=3;combat=3" + projectile_type = "/obj/item/projectile/spur/polarstar" + charge_cost = 100 + cell_type = "/obj/item/weapon/cell" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi') + recoil = 1 + var/firelevel = SPUR_FULL_POWER + +/obj/item/weapon/gun/energy/polarstar/New() + ..() + playsound(get_turf(src), 'sound/weapons/spur_spawn.ogg', 50, 0, null, FALLOFF_SOUNDS, 0) + +/obj/item/weapon/gun/energy/polarstar/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0) + levelChange() + ..() + +/obj/item/weapon/gun/energy/polarstar/proc/levelChange() + var/maxlevel = power_supply.maxcharge + var/level = power_supply.charge + var/newlevel = 0 + if(level == maxlevel) + newlevel = SPUR_FULL_POWER + else if(level >= ((maxlevel/3)*2)) + newlevel = SPUR_HIGH_POWER + else if(level >= (maxlevel/3)) + newlevel = SPUR_MEDIUM_POWER + else if(level >= charge_cost) + newlevel = SPUR_LOW_POWER + else + newlevel = SPUR_NO_POWER + + if(firelevel >= newlevel) + firelevel = newlevel + set_firesound() + return + + firelevel = newlevel + set_firesound() + var/levelupsound = null + switch(firelevel) + if(SPUR_LOW_POWER) + levelupsound = 'sound/weapons/spur_chargelow.ogg' + if(SPUR_MEDIUM_POWER) + levelupsound = 'sound/weapons/spur_chargemed.ogg' + if(SPUR_HIGH_POWER) + levelupsound = 'sound/weapons/spur_chargehigh.ogg' + if(SPUR_FULL_POWER) + levelupsound = 'sound/weapons/spur_chargefull.ogg' + + if(levelupsound) + for(var/mob/M in get_turf(src)) + M.playsound_local(M, levelupsound, 100, 0, null, FALLOFF_SOUNDS, 0) + spawn(1) + M.playsound_local(M, levelupsound, 75, 0, null, FALLOFF_SOUNDS, 0) + + +/obj/item/weapon/gun/energy/polarstar/proc/set_firesound() + switch(firelevel) + if(SPUR_HIGH_POWER,SPUR_FULL_POWER) + fire_sound = 'sound/weapons/spur_high.ogg' + recoil = 1 + if(SPUR_MEDIUM_POWER) + fire_sound = 'sound/weapons/spur_medium.ogg' + recoil = 0 + if(SPUR_LOW_POWER,SPUR_NO_POWER) + fire_sound = 'sound/weapons/spur_low.ogg' + recoil = 0 + return + +/obj/item/weapon/gun/energy/polarstar/update_icon() + return + +/obj/item/weapon/gun/energy/polarstar/spur + name = "\improper Spur" + desc = "A masterpiece crafted by the legendary gunsmith of a far-away planet." + icon_state = "spur" + item_state = null + origin_tech = "materials=5;powerstorage=4;combat=5" + fire_delay = 0 + projectile_type = "/obj/item/projectile/spur" + var/charge_tick = 0 + +/obj/item/weapon/gun/energy/polarstar/spur/New() + ..() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/polarstar/spur/Destroy() + processing_objects.Remove(src) + ..() + +/obj/item/weapon/gun/energy/polarstar/spur/process() + charge_tick++ + if(charge_tick < 2) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + levelChange() + return 1 + +#undef SPUR_FULL_POWER +#undef SPUR_HIGH_POWER +#undef SPUR_MEDIUM_POWER +#undef SPUR_LOW_POWER +#undef SPUR_NO_POWER diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 2fbe4e03840..f541420c114 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -1,111 +1,111 @@ - -/obj/item/weapon/gun/energy/taser - name = "taser gun" - desc = "A small, low capacity gun used for non-lethal takedowns." - icon_state = "taser" - item_state = null //so the human update icon uses the icon_state instead. - fire_sound = 'sound/weapons/Taser.ogg' - charge_cost = 100 - projectile_type = "/obj/item/projectile/energy/electrode" - cell_type = "/obj/item/weapon/cell/crap" - -/obj/item/weapon/gun/energy/taser/cyborg - name = "taser gun" - desc = "A small, low capacity gun used for non-lethal takedowns." - icon_state = "taser" - fire_sound = 'sound/weapons/Taser.ogg' - charge_cost = 100 - projectile_type = "/obj/item/projectile/energy/electrode" - cell_type = "/obj/item/weapon/cell/secborg" - var/charge_tick = 0 - var/recharge_time = 10 //Time it takes for shots to recharge (in ticks) - - New() - ..() - processing_objects.Add(src) - - - Destroy() - processing_objects.Remove(src) - ..() - - process() //Every [recharge_time] ticks, recharge a shot for the cyborg - charge_tick++ - if(charge_tick < recharge_time) return 0 - charge_tick = 0 - - if(!power_supply) return 0 //sanity - if(isrobot(src.loc)) - var/mob/living/silicon/robot/R = src.loc - if(R && R.cell) - R.cell.use(charge_cost) //Take power from the borg... - power_supply.give(charge_cost) //... to recharge the shot - - update_icon() - return 1 - - -/obj/item/weapon/gun/energy/stunrevolver - name = "stun revolver" - desc = "A high-tech revolver that fires stun cartridges. The stun cartridges can be recharged using a conventional energy weapon recharger." - icon_state = "stunrevolver" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - fire_sound = 'sound/weapons/Gunshot.ogg' - origin_tech = "combat=3;materials=3;powerstorage=2" - charge_cost = 125 - projectile_type = "/obj/item/projectile/energy/electrode" - cell_type = "/obj/item/weapon/cell" - - - -/obj/item/weapon/gun/energy/crossbow - name = "mini energy-crossbow" - desc = "A weapon favored by many of the syndicates stealth specialists." - icon_state = "crossbow" - w_class = 2.0 - item_state = "crossbow" - starting_materials = list(MAT_IRON = 2000) - w_type = RECYK_ELECTRONIC - origin_tech = "combat=2;magnets=2;syndicate=5" - silenced = 1 - fire_sound = 'sound/weapons/ebow.ogg' - projectile_type = "/obj/item/projectile/energy/bolt" - cell_type = "/obj/item/weapon/cell/crap" - var/charge_tick = 0 - - - New() - ..() - processing_objects.Add(src) - - - Destroy() - processing_objects.Remove(src) - ..() - - - process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(100) - return 1 - - - update_icon() - return - - - -/obj/item/weapon/gun/energy/crossbow/largecrossbow - name = "Energy Crossbow" - desc = "A weapon favored by syndicate infiltration teams." - w_class = 4.0 - force = 10 - starting_materials = list(MAT_IRON = 200000) - w_type = RECYK_ELECTRONIC - projectile_type = "/obj/item/projectile/energy/bolt/large" - - + +/obj/item/weapon/gun/energy/taser + name = "taser gun" + desc = "A small, low capacity gun used for non-lethal takedowns." + icon_state = "taser" + item_state = null //so the human update icon uses the icon_state instead. + fire_sound = 'sound/weapons/Taser.ogg' + charge_cost = 100 + projectile_type = "/obj/item/projectile/energy/electrode" + cell_type = "/obj/item/weapon/cell/crap" + +/obj/item/weapon/gun/energy/taser/cyborg + name = "taser gun" + desc = "A small, low capacity gun used for non-lethal takedowns." + icon_state = "taser" + fire_sound = 'sound/weapons/Taser.ogg' + charge_cost = 100 + projectile_type = "/obj/item/projectile/energy/electrode" + cell_type = "/obj/item/weapon/cell/secborg" + var/charge_tick = 0 + var/recharge_time = 10 //Time it takes for shots to recharge (in ticks) + + New() + ..() + processing_objects.Add(src) + + + Destroy() + processing_objects.Remove(src) + ..() + + process() //Every [recharge_time] ticks, recharge a shot for the cyborg + charge_tick++ + if(charge_tick < recharge_time) return 0 + charge_tick = 0 + + if(!power_supply) return 0 //sanity + if(isrobot(src.loc)) + var/mob/living/silicon/robot/R = src.loc + if(R && R.cell) + R.cell.use(charge_cost) //Take power from the borg... + power_supply.give(charge_cost) //... to recharge the shot + + update_icon() + return 1 + + +/obj/item/weapon/gun/energy/stunrevolver + name = "stun revolver" + desc = "A high-tech revolver that fires stun cartridges. The stun cartridges can be recharged using a conventional energy weapon recharger." + icon_state = "stunrevolver" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + fire_sound = 'sound/weapons/Gunshot.ogg' + origin_tech = "combat=3;materials=3;powerstorage=2" + charge_cost = 125 + projectile_type = "/obj/item/projectile/energy/electrode" + cell_type = "/obj/item/weapon/cell" + + + +/obj/item/weapon/gun/energy/crossbow + name = "mini energy-crossbow" + desc = "A weapon favored by many of the syndicates stealth specialists." + icon_state = "crossbow" + w_class = 2.0 + item_state = "crossbow" + starting_materials = list(MAT_IRON = 2000) + w_type = RECYK_ELECTRONIC + origin_tech = "combat=2;magnets=2;syndicate=5" + silenced = 1 + fire_sound = 'sound/weapons/ebow.ogg' + projectile_type = "/obj/item/projectile/energy/bolt" + cell_type = "/obj/item/weapon/cell/crap" + var/charge_tick = 0 + + + New() + ..() + processing_objects.Add(src) + + + Destroy() + processing_objects.Remove(src) + ..() + + + process() + charge_tick++ + if(charge_tick < 4) return 0 + charge_tick = 0 + if(!power_supply) return 0 + power_supply.give(100) + return 1 + + + update_icon() + return + + + +/obj/item/weapon/gun/energy/crossbow/largecrossbow + name = "Energy Crossbow" + desc = "A weapon favored by syndicate infiltration teams." + w_class = 4.0 + force = 10 + starting_materials = list(MAT_IRON = 200000) + w_type = RECYK_ELECTRONIC + projectile_type = "/obj/item/projectile/energy/bolt/large" + + diff --git a/code/modules/projectiles/guns/energy/temperature.dm b/code/modules/projectiles/guns/energy/temperature.dm index 3836c8b56b7..62c0e1947c7 100644 --- a/code/modules/projectiles/guns/energy/temperature.dm +++ b/code/modules/projectiles/guns/energy/temperature.dm @@ -1,182 +1,182 @@ -/obj/item/weapon/gun/energy/temperature - name = "temperature gun" - icon = 'icons/obj/gun_temperature.dmi' - icon_state = "tempgun_4" - item_state = "tempgun_4" - slot_flags = SLOT_BACK - w_class = 4.0 - fire_sound = 'sound/weapons/pulse3.ogg' - desc = "A gun that changes the body temperature of its targets." - var/temperature = 300 - var/target_temperature = 300 - charge_cost = 90 - origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2" - - projectile_type = "/obj/item/projectile/temp" - cell_type = "/obj/item/weapon/cell/temperaturegun" - - var/powercost = "" - var/powercostcolor = "" - - var/emagged = 0 //ups the temperature cap from 500 to 1000, targets hit by beams over 500 Kelvin will burst into flames - var/dat = "" - -/obj/item/weapon/gun/energy/temperature/New() - ..() - update_icon() - processing_objects.Add(src) - - -/obj/item/weapon/gun/energy/temperature/Destroy() - processing_objects.Remove(src) - ..() - - -/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob) - user.set_machine(src) - update_dat() - - user << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x102") - onclose(user, "tempgun") - -/obj/item/weapon/gun/energy/temperature/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/emag) && !emagged) - emagged = 1 +/obj/item/weapon/gun/energy/temperature + name = "temperature gun" + icon = 'icons/obj/gun_temperature.dmi' + icon_state = "tempgun_4" + item_state = "tempgun_4" + slot_flags = SLOT_BACK + w_class = 4.0 + fire_sound = 'sound/weapons/pulse3.ogg' + desc = "A gun that changes the body temperature of its targets." + var/temperature = 300 + var/target_temperature = 300 + charge_cost = 90 + origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2" + + projectile_type = "/obj/item/projectile/temp" + cell_type = "/obj/item/weapon/cell/temperaturegun" + + var/powercost = "" + var/powercostcolor = "" + + var/emagged = 0 //ups the temperature cap from 500 to 1000, targets hit by beams over 500 Kelvin will burst into flames + var/dat = "" + +/obj/item/weapon/gun/energy/temperature/New() + ..() + update_icon() + processing_objects.Add(src) + + +/obj/item/weapon/gun/energy/temperature/Destroy() + processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob) + user.set_machine(src) + update_dat() + + user << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x102") + onclose(user, "tempgun") + +/obj/item/weapon/gun/energy/temperature/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/emag) && !emagged) + emagged = 1 to_chat(user, "You double the gun's temperature cap ! Targets hit by searing beams will burst into flames !") - desc = "A gun that changes the body temperature of its targets. Its temperature cap has been hacked" - -/obj/item/weapon/gun/energy/temperature/Topic(href, href_list) - if (..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - - if(href_list["temp"]) - var/amount = text2num(href_list["temp"]) - if(amount > 0) - src.target_temperature = min((500 + 500*emagged), src.target_temperature+amount) - else - src.target_temperature = max(0, src.target_temperature+amount) - if (istype(src.loc, /mob)) - attack_self(src.loc) - src.add_fingerprint(usr) - return - - -/obj/item/weapon/gun/energy/temperature/process() - switch(temperature) - if(0 to 100) - charge_cost = 300 - powercost = "High" - if(100 to 250) - charge_cost = 180 - powercost = "Medium" - if(251 to 300) - charge_cost = 90 - powercost = "Low" - if(301 to 400) - charge_cost = 180 - powercost = "Medium" - if(401 to 1000) - charge_cost = 300 - powercost = "High" - switch(powercost) - if("High") powercostcolor = "orange" - if("Medium") powercostcolor = "green" - else powercostcolor = "blue" - if(target_temperature != temperature) - var/difference = abs(target_temperature - temperature) - if(difference >= (10 + 40*emagged)) //so emagged temp guns adjust their temperature much more quickly - if(target_temperature < temperature) - temperature -= (10 + 40*emagged) - else - temperature += (10 + 40*emagged) - else - temperature = target_temperature - update_icon() - - if (istype(loc, /mob/living/carbon)) - var /mob/living/carbon/M = loc - if (src == M.machine) - update_dat() - M << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x102") - - - if(power_supply) - power_supply.give(50) - update_icon() - return - -/obj/item/weapon/gun/energy/temperature/proc/update_dat() - dat = "" - dat += "Current output temperature: " - if(temperature > 500) - dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F) " - dat += "SEARING!!" - else if(temperature > (T0C + 50)) - dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)" - else if(temperature > (T0C - 50)) - dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)" - else - dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)" - dat += "
    " - dat += "Target output temperature: " //might be string idiocy, but at least it's easy to read - dat += "- " - dat += "- " - dat += "- " - dat += "[target_temperature] " - dat += "+ " - dat += "+ " - dat += "+" - dat += "
    " - dat += "Power cost: " - dat += "[powercost]" - -/obj/item/weapon/gun/energy/temperature/proc/update_temperature() - switch(temperature) - if(501 to INFINITY) - item_state = "tempgun_8" - if(400 to 500) - item_state = "tempgun_7" - if(360 to 400) - item_state = "tempgun_6" - if(335 to 360) - item_state = "tempgun_5" - if(295 to 335) - item_state = "tempgun_4" - if(260 to 295) - item_state = "tempgun_3" - if(200 to 260) - item_state = "tempgun_2" - if(120 to 260) - item_state = "tempgun_1" - if(-INFINITY to 120) - item_state = "tempgun_0" - icon_state = item_state - -/obj/item/weapon/gun/energy/temperature/proc/update_charge() - var/charge = power_supply.charge - switch(charge) - if(900 to INFINITY) overlays += "900" - if(800 to 900) overlays += "800" - if(700 to 800) overlays += "700" - if(600 to 700) overlays += "600" - if(500 to 600) overlays += "500" - if(400 to 500) overlays += "400" - if(300 to 400) overlays += "300" - if(200 to 300) overlays += "200" - if(100 to 200) overlays += "100" - if(-INFINITY to 100) overlays += "0" - -/obj/item/weapon/gun/energy/temperature/proc/update_user() - if (istype(loc,/mob/living/carbon)) - var/mob/living/carbon/M = loc - M.update_inv_back() - M.update_inv_l_hand() - M.update_inv_r_hand() - -/obj/item/weapon/gun/energy/temperature/update_icon() - overlays = 0 - update_temperature() - update_user() + desc = "A gun that changes the body temperature of its targets. Its temperature cap has been hacked" + +/obj/item/weapon/gun/energy/temperature/Topic(href, href_list) + if (..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + + if(href_list["temp"]) + var/amount = text2num(href_list["temp"]) + if(amount > 0) + src.target_temperature = min((500 + 500*emagged), src.target_temperature+amount) + else + src.target_temperature = max(0, src.target_temperature+amount) + if (istype(src.loc, /mob)) + attack_self(src.loc) + src.add_fingerprint(usr) + return + + +/obj/item/weapon/gun/energy/temperature/process() + switch(temperature) + if(0 to 100) + charge_cost = 300 + powercost = "High" + if(100 to 250) + charge_cost = 180 + powercost = "Medium" + if(251 to 300) + charge_cost = 90 + powercost = "Low" + if(301 to 400) + charge_cost = 180 + powercost = "Medium" + if(401 to 1000) + charge_cost = 300 + powercost = "High" + switch(powercost) + if("High") powercostcolor = "orange" + if("Medium") powercostcolor = "green" + else powercostcolor = "blue" + if(target_temperature != temperature) + var/difference = abs(target_temperature - temperature) + if(difference >= (10 + 40*emagged)) //so emagged temp guns adjust their temperature much more quickly + if(target_temperature < temperature) + temperature -= (10 + 40*emagged) + else + temperature += (10 + 40*emagged) + else + temperature = target_temperature + update_icon() + + if (istype(loc, /mob/living/carbon)) + var /mob/living/carbon/M = loc + if (src == M.machine) + update_dat() + M << browse("Temperature Gun Configuration
    [dat]", "window=tempgun;size=510x102") + + + if(power_supply) + power_supply.give(50) + update_icon() + return + +/obj/item/weapon/gun/energy/temperature/proc/update_dat() + dat = "" + dat += "Current output temperature: " + if(temperature > 500) + dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F) " + dat += "SEARING!!" + else if(temperature > (T0C + 50)) + dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)" + else if(temperature > (T0C - 50)) + dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)" + else + dat += "[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)" + dat += "
    " + dat += "Target output temperature: " //might be string idiocy, but at least it's easy to read + dat += "- " + dat += "- " + dat += "- " + dat += "[target_temperature] " + dat += "+ " + dat += "+ " + dat += "+" + dat += "
    " + dat += "Power cost: " + dat += "[powercost]" + +/obj/item/weapon/gun/energy/temperature/proc/update_temperature() + switch(temperature) + if(501 to INFINITY) + item_state = "tempgun_8" + if(400 to 500) + item_state = "tempgun_7" + if(360 to 400) + item_state = "tempgun_6" + if(335 to 360) + item_state = "tempgun_5" + if(295 to 335) + item_state = "tempgun_4" + if(260 to 295) + item_state = "tempgun_3" + if(200 to 260) + item_state = "tempgun_2" + if(120 to 260) + item_state = "tempgun_1" + if(-INFINITY to 120) + item_state = "tempgun_0" + icon_state = item_state + +/obj/item/weapon/gun/energy/temperature/proc/update_charge() + var/charge = power_supply.charge + switch(charge) + if(900 to INFINITY) overlays += "900" + if(800 to 900) overlays += "800" + if(700 to 800) overlays += "700" + if(600 to 700) overlays += "600" + if(500 to 600) overlays += "500" + if(400 to 500) overlays += "400" + if(300 to 400) overlays += "300" + if(200 to 300) overlays += "200" + if(100 to 200) overlays += "100" + if(-INFINITY to 100) overlays += "0" + +/obj/item/weapon/gun/energy/temperature/proc/update_user() + if (istype(loc,/mob/living/carbon)) + var/mob/living/carbon/M = loc + M.update_inv_back() + M.update_inv_l_hand() + M.update_inv_r_hand() + +/obj/item/weapon/gun/energy/temperature/update_icon() + overlays = 0 + update_temperature() + update_user() update_charge() \ No newline at end of file diff --git a/code/modules/projectiles/guns/lawgiver.dm b/code/modules/projectiles/guns/lawgiver.dm index 898aee21ca2..77210af5486 100644 --- a/code/modules/projectiles/guns/lawgiver.dm +++ b/code/modules/projectiles/guns/lawgiver.dm @@ -1,575 +1,575 @@ -#define HI_EX "hi-EX" -#define RAPID "rapid" -#define FLARE "flare" -#define STUN "stun" -#define LASER "laser" - -/obj/item/weapon/gun/lawgiver - desc = "The Lawgiver II. A twenty-five round sidearm with mission-variable voice-programmed ammunition." - name = "lawgiver" - icon_state = "lawgiver" - item_state = "lawgiver" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - origin_tech = "combat=5;materials=5;engineering=5" - w_class = 3.0 - starting_materials = list(MAT_IRON = 1000) - w_type = RECYK_METAL - recoil = 0 - flags = HEAR | FPRINT - var/obj/item/ammo_storage/magazine/stored_magazine = null - var/obj/item/ammo_casing/chambered = null - var/firing_mode = STUN - fire_delay = 0 - var/projectile_type = "/obj/item/projectile/energy/electrode" - fire_sound = 'sound/weapons/Taser.ogg' - var/magazine = null - var/dna_profile = null - var/rapidFirecheck = 0 - var/rapidFirechamber = 0 - var/rapidFirestop = 0 - var/rapid_message = 0 - var/damage_multiplier = 1 - var/has_played_alert = 0 - -/obj/item/weapon/gun/lawgiver/New() - ..() - magazine = new /obj/item/ammo_storage/magazine/lawgiver - verbs -= /obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample - update_icon() - -/obj/item/weapon/gun/lawgiver/GetVoice() - var/the_name = "The [name]" - return the_name - -/obj/item/weapon/gun/lawgiver/equipped(M as mob, hand) - update_icon() - -/obj/item/weapon/gun/lawgiver/update_icon() - overlays.len = 0 - if(magazine) - item_state = "[initial(icon_state)]1" - var/obj/item/ammo_storage/magazine/lawgiver/L = magazine - var/image/magazine_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)]Mag") - var/image/ammo_overlay = null - if(firing_mode == STUN && L.stuncharge) - ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.stuncharge/20]") - if(firing_mode == LASER && L.lasercharge) - ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.lasercharge/20]") - if(firing_mode == RAPID && L.rapid_ammo_count) - ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.rapid_ammo_count]") - if(firing_mode == FLARE && L.flare_ammo_count) - ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.flare_ammo_count]") - if(firing_mode == HI_EX && L.hi_ex_ammo_count) - ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.hi_ex_ammo_count]") - overlays += magazine_overlay - overlays += ammo_overlay - else - item_state = "[initial(icon_state)]0" - - if (istype(loc,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = loc - var/image/DNA_overlay = null - if(H.l_hand == src || H.r_hand == src) - if(dna_profile) - if(dna_profile == H.dna.unique_enzymes) - DNA_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)]DNAgood") - else - DNA_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)]DNAbad") - overlays += DNA_overlay - H.update_inv_r_hand() - H.update_inv_l_hand() - - -/obj/item/weapon/gun/lawgiver/verb/submit_DNA_sample() - set name = "Submit DNA sample" - set category = "Object" - set src in usr - - var/mob/living/carbon/human/H = loc - - if(!dna_profile) - dna_profile = H.dna.unique_enzymes - to_chat(usr, "You submit a DNA sample to \the [src].") - verbs += /obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample - verbs -= /obj/item/weapon/gun/lawgiver/verb/submit_DNA_sample - -/obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample() - set name = "Erase DNA sample" - set category = "Object" - set src in usr - - var/mob/living/carbon/human/H = loc - - if(dna_profile) - if(dna_profile == H.dna.unique_enzymes) - dna_profile = null - to_chat(usr, "You erase the DNA profile from \the [src].") - verbs += /obj/item/weapon/gun/lawgiver/verb/submit_DNA_sample - verbs -= /obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample - else - self_destruct(H) - -/obj/item/weapon/gun/lawgiver/proc/self_destruct(mob/user) - var/req_access = list(access_security) - if(can_access(user.GetAccess(),req_access)) - say("ERROR: DNA PROFILE DOES NOT MATCH") - return - say("UNAUTHORIZED ACCESS DETECTED") - explosion(user, -1, 0, 2) - qdel(src) - -/obj/item/weapon/gun/lawgiver/proc/LoadMag(var/obj/item/ammo_storage/magazine/AM, var/mob/user) - if(istype(AM, /obj/item/ammo_storage/magazine/lawgiver) && !magazine) - if(user) - if(user.drop_item(AM, src)) - to_chat(user, "You load the magazine into \the [src].") - else - return - - magazine = AM - AM.update_icon() - update_icon() - return 1 - return 0 - -/obj/item/weapon/gun/lawgiver/proc/RemoveMag(var/mob/user) - if(magazine) - var/obj/item/ammo_storage/magazine/lawgiver/L = magazine - L.loc = get_turf(src.loc) - if(user) - user.put_in_hands(L) - to_chat(user, "You pull the magazine out of \the [src]!") - L.update_icon() - magazine = null - update_icon() - return 1 - return 0 - -/obj/item/weapon/gun/lawgiver/Hear(var/datum/speech/speech, var/rendered_speech="") - if(speech.speaker == loc && !speech.frequency && dna_profile) - var/mob/living/carbon/human/H = loc - if(dna_profile == H.dna.unique_enzymes) - recoil = 0 - if((findtext(speech.message, "stun")) || (findtext(speech.message, "taser"))) - firing_mode = STUN - fire_sound = 'sound/weapons/Taser.ogg' - projectile_type = "/obj/item/projectile/energy/electrode" - fire_delay = 0 - sleep(3) - say("STUN") - else if((findtext(speech.message, "laser")) || (findtext(speech.message, "lethal")) || (findtext(speech.message, "beam"))) - firing_mode = LASER - fire_sound = 'sound/weapons/lasercannonfire.ogg' - projectile_type = "/obj/item/projectile/beam/heavylaser" - fire_delay = 5 - sleep(3) - say("LASER") - else if((findtext(speech.message, "rapid")) || (findtext(speech.message, "automatic"))) - firing_mode = RAPID - fire_sound = 'sound/weapons/Gunshot_c20.ogg' - projectile_type = "/obj/item/projectile/bullet/midbullet/lawgiver" - fire_delay = 0 - rapid_message = 0 - recoil = 1 - sleep(3) - say("RAPID FIRE") - else if((findtext(speech.message, "flare")) || (findtext(speech.message, "incendiary"))) - firing_mode = FLARE - fire_sound = 'sound/weapons/shotgun.ogg' - projectile_type = "/obj/item/projectile/flare" - fire_delay = 5 - recoil = 1 - sleep(3) - say("FLARE") - else if((findtext(speech.message, "hi ex")) || (findtext(speech.message, "hi-ex")) || (findtext(speech.message, "explosive")) || (findtext(speech.message, "rocket"))) - firing_mode = HI_EX - fire_sound = 'sound/weapons/elecfire.ogg' - projectile_type = "/obj/item/projectile/bullet/gyro" - fire_delay = 4 - recoil = 1 - sleep(3) - say("HI-EX") - update_icon() - -/obj/item/weapon/gun/lawgiver/proc/rapidFire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) //Burst fires don't work well except by calling Fire() multiple times - rapidFirecheck = 1 - for (var/i = 1; i <= 3; i++) - if(!rapidFirestop) - Fire(target, user, params, reflex, struggle) - rapidFirecheck = 0 - rapidFirechamber = 0 - rapidFirestop = 0 - rapid_message = 0 - -/obj/item/weapon/gun/lawgiver/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) //Overriding this due to introducing the DNA check, and the fact that the round is to be chambered only just before it is fired - if(dna_profile) - if(dna_profile != user.dna.unique_enzymes) - self_destruct(user) - return - else - click_empty(user) - say("PLEASE REGISTER A DNA SAMPLE") - return - - if(firing_mode == RAPID && !rapidFirecheck) - rapidFire(target, user, params, reflex, struggle) - return - - //Christ Almighty is there no OOP way to do this? - if (!ready_to_fire()) - if (world.time % 3) //to prevent spam - to_chat(user, "[src] is not ready to fire again!") - return - - if(firing_mode == RAPID && !rapidFirechamber) - in_chamber = null - if(!chamber_round()) - rapidFirestop = 1 - return click_empty(user) - rapidFirechamber = 1 - - else if(firing_mode == RAPID && rapidFirechamber) - in_chamber = new projectile_type(src) - - else if(firing_mode != RAPID) - in_chamber = null - if(!chamber_round()) - return click_empty(user) - - if(clumsy_check) - if(istype(user, /mob/living)) - var/mob/living/M = user - if ((M_CLUMSY in M.mutations) && prob(50)) - to_chat(M, "[src] blows up in your face.") - M.take_organ_damage(0,20) - M.drop_item(src, force_drop = 1) - qdel(src) - return - - if (!user.IsAdvancedToolUser() || isMoMMI(user) || istype(user, /mob/living/carbon/monkey/diona)) - to_chat(user, "You don't have the dexterity to do this!") - return - if(istype(user, /mob/living)) - var/mob/living/M = user - if (M_HULK in M.mutations) - to_chat(M, "Your meaty finger is much too large for the trigger guard!") - return - if(ishuman(user)) - var/mob/living/carbon/human/H=user - if(user.dna && (user.dna.mutantrace == "adamantine" || user.dna.mutantrace=="coalgolem")) - to_chat(user, "Your fat fingers don't fit in the trigger guard!") - return - var/datum/organ/external/a_hand = H.get_active_hand_organ() - if(!a_hand.can_use_advanced_tools()) - to_chat(user, "Your [a_hand] doesn't have the dexterity to do this!") - return - - in_chamber.damage *= damage_multiplier - - add_fingerprint(user) - - var/turf/curloc = get_turf(user) - var/turf/targloc = get_turf(target) - if (!istype(targloc) || !istype(curloc)) - return - - if(!special_check(user)) - return - - if(!in_chamber) - return - log_attack("[user.name] ([user.ckey]) fired \the [src] (proj:[in_chamber.name]) at [target] [ismob(target) ? "([target:ckey])" : ""] ([target.x],[target.y],[target.z])[struggle ? " due to being disarmed." :""]" ) - in_chamber.firer = user - in_chamber.def_zone = user.zone_sel.selecting - if(targloc == curloc) - user.bullet_act(in_chamber) - qdel(in_chamber) - in_chamber = null - update_icon() - return - - if((firing_mode == RAPID && !rapid_message) || (firing_mode != RAPID)) //On rapid mode, only shake once per burst. - if(recoil) - spawn() - shake_camera(user, recoil + 1, recoil) - if(user.locked_to && isobj(user.locked_to) && !user.locked_to.anchored ) - var/direction = get_dir(user,target) - spawn() - var/obj/B = user.locked_to - var/movementdirection = turn(direction,180) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(1) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(2) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - sleep(3) - B.Move(get_step(user,movementdirection), movementdirection) - if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) - user.inertia_dir = get_dir(target, user) - step(user, user.inertia_dir) - - playsound(user, fire_sound, 50, 1) - if(!rapid_message) - user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \ - "You fire [src][reflex ? "by reflex":""]!", \ - "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") - if(firing_mode == RAPID) - rapid_message = 1 - - in_chamber.original = target - in_chamber.loc = get_turf(user) - in_chamber.starting = get_turf(user) - in_chamber.shot_from = src - user.delayNextAttack(fire_delay) - in_chamber.silenced = silenced - in_chamber.current = curloc - in_chamber.OnFired() - in_chamber.yo = targloc.y - curloc.y - in_chamber.xo = targloc.x - curloc.x - in_chamber.inaccurate = (istype(user.locked_to, /obj/structure/bed/chair/vehicle)) - - if(params) - var/list/mouse_control = params2list(params) - if(mouse_control["icon-x"]) - in_chamber.p_x = text2num(mouse_control["icon-x"]) - if(mouse_control["icon-y"]) - in_chamber.p_y = text2num(mouse_control["icon-y"]) - - spawn() - if(in_chamber) - in_chamber.process() - sleep(1) - in_chamber = null - - update_icon() - - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() - - if(firing_mode == RAPID) - var/obj/item/ammo_casing/a12mm/A = new /obj/item/ammo_casing/a12mm(user.loc) - A.BB = null - A.update_icon() - if(firing_mode == HI_EX) - var/obj/item/ammo_casing/a75/A = new /obj/item/ammo_casing/a75(user.loc) - A.BB = null - A.update_icon() - -/obj/item/weapon/gun/lawgiver/attack(mob/living/M as mob, mob/living/user as mob, def_zone) - //Suicide handling. - if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot) - if(istype(M.wear_mask, /obj/item/clothing/mask/happy)) - to_chat(M, "BUT WHY? I'M SO HAPPY!") - return - mouthshoot = 1 - M.visible_message("[user] sticks their gun in their mouth, ready to pull the trigger...") - if(!do_after(user,src, 40)) - M.visible_message("[user] decided life was worth living") - mouthshoot = 0 - return - if(dna_profile) - if(dna_profile != user.dna.unique_enzymes) - self_destruct(user) - return - else - user.visible_message("[user] pulls the trigger.") - click_empty(user) - say("PLEASE REGISTER A DNA SAMPLE") - return - if (chamber_round()) - user.visible_message("[user] pulls the trigger.") - playsound(user, fire_sound, 50, 1) - in_chamber.on_hit(M) - if (!in_chamber.nodamage) - user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]") - user.stat=2 // Just to be sure - user.death() - else - to_chat(user, "Ow...") - user.apply_effect(110,AGONY,0) - qdel(in_chamber) - in_chamber = null - mouthshoot = 0 - return - else - click_empty(user) - mouthshoot = 0 - return - - if (can_shoot()) - //Point blank shooting if on harm intent or target we were targeting. - if(user.a_intent == I_HURT) - user.visible_message(" \The [user] fires \the [src] point blank at [M]!") - damage_multiplier = 1.3 - src.Fire(M,user,0,0,1) - damage_multiplier = 1 - return - else if(target && M in target) - src.Fire(M,user,0,0,1) - return - else - return ..() - else - return ..() - -/obj/item/weapon/gun/lawgiver/proc/chamber_round() - if(in_chamber || !magazine) - return 0 - else - var/obj/item/ammo_storage/magazine/lawgiver/L = magazine - switch(firing_mode) - if(STUN) - if(L.stuncharge >= 20) - if(in_chamber) return 1 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - L.stuncharge -= 20 - return 1 - else - return 0 - if(LASER) - if(L.lasercharge >= 20) - if(in_chamber) return 1 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - L.lasercharge -= 20 - return 1 - else - return 0 - if(RAPID) - if(L.rapid_ammo_count >= 1) - if(in_chamber) return 1 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - L.rapid_ammo_count -= 1 - return 1 - else - return 0 - if(FLARE) - if(L.flare_ammo_count >= 1) - if(in_chamber) return 1 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - L.flare_ammo_count -= 1 - return 1 - else - return 0 - if(HI_EX) - if(L.hi_ex_ammo_count >= 1) - if(in_chamber) return 1 - if(!projectile_type) return 0 - in_chamber = new projectile_type(src) - L.hi_ex_ammo_count -= 1 - return 1 - else - return 0 - return 0 - -/obj/item/weapon/gun/lawgiver/proc/can_shoot() //Only made so that firing point-blank can run its checks without chambering a round, since rounds are chambered in Fire() - if(!magazine) - return 0 - else - var/obj/item/ammo_storage/magazine/lawgiver/L = magazine - switch(firing_mode) - if(STUN) - if(L.stuncharge >= 20) - if(in_chamber) return 1 - if(!projectile_type) return 0 - return 1 - else - return 0 - if(LASER) - if(L.lasercharge >= 20) - if(in_chamber) return 1 - if(!projectile_type) return 0 - return 1 - else - return 0 - if(RAPID) - if(L.rapid_ammo_count >= 1) - if(in_chamber) return 1 - if(!projectile_type) return 0 - return 1 - else - return 0 - if(FLARE) - if(L.flare_ammo_count >= 1) - if(in_chamber) return 1 - if(!projectile_type) return 0 - return 1 - else - return 0 - if(HI_EX) - if(L.hi_ex_ammo_count >= 1) - if(in_chamber) return 1 - if(!projectile_type) return 0 - return 1 - else - return 0 - return 0 - -/obj/item/weapon/gun/lawgiver/attackby(var/obj/item/A as obj, mob/user as mob) - if(istype(A, /obj/item/ammo_storage/magazine/lawgiver)) - var/obj/item/ammo_storage/magazine/lawgiver/AM = A - if(!magazine) - LoadMag(AM, user) - else - to_chat(user, "There is already a magazine loaded in \the [src]!") - else if (istype(A, /obj/item/ammo_storage/magazine)) - to_chat(user, "You can't load \the [src] with that kind of magazine!") - -/obj/item/weapon/gun/lawgiver/attack_self(mob/user as mob) - if (target) - return ..() - if (magazine) - RemoveMag(user) - else - to_chat(user, "There's no magazine loaded in \the [src]!") - -/obj/item/weapon/gun/lawgiver/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, struggle = 0) - ..() - if(magazine) - var/obj/item/ammo_storage/magazine/lawgiver/L = magazine - if(magazine && !countAmmo(L) && !has_played_alert) - playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) - has_played_alert = 1 - return - -/obj/item/weapon/gun/lawgiver/examine(mob/user) - ..() - getAmmo(user) - -/obj/item/weapon/gun/lawgiver/proc/getAmmo(mob/user) - if (magazine) - var/obj/item/ammo_storage/magazine/lawgiver/L = magazine - to_chat(user, "It has enough energy for [L.stuncharge/20] stun shot\s left.") - to_chat(user, "It has enough energy for [L.lasercharge/20] laser shot\s left.") - to_chat(user, "It has [L.rapid_ammo_count] rapid fire round\s remaining.") - to_chat(user, "It has [L.flare_ammo_count] flare round\s remaining.") - to_chat(user, "It has [L.hi_ex_ammo_count] hi-EX round\s remaining.") - -/obj/item/weapon/gun/lawgiver/proc/countAmmo(var/obj/item/A) - var/obj/item/ammo_storage/magazine/lawgiver/L = A - if (L.stuncharge == 0 && L.lasercharge == 0 && L.rapid_ammo_count == 0 && L.flare_ammo_count == 0 && L.hi_ex_ammo_count == 0) - return 0 - else - has_played_alert = 0 - return 1 - -#undef HI_EX -#undef RAPID -#undef FLARE -#undef STUN -#undef LASER +#define HI_EX "hi-EX" +#define RAPID "rapid" +#define FLARE "flare" +#define STUN "stun" +#define LASER "laser" + +/obj/item/weapon/gun/lawgiver + desc = "The Lawgiver II. A twenty-five round sidearm with mission-variable voice-programmed ammunition." + name = "lawgiver" + icon_state = "lawgiver" + item_state = "lawgiver" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + origin_tech = "combat=5;materials=5;engineering=5" + w_class = 3.0 + starting_materials = list(MAT_IRON = 1000) + w_type = RECYK_METAL + recoil = 0 + flags = HEAR | FPRINT + var/obj/item/ammo_storage/magazine/stored_magazine = null + var/obj/item/ammo_casing/chambered = null + var/firing_mode = STUN + fire_delay = 0 + var/projectile_type = "/obj/item/projectile/energy/electrode" + fire_sound = 'sound/weapons/Taser.ogg' + var/magazine = null + var/dna_profile = null + var/rapidFirecheck = 0 + var/rapidFirechamber = 0 + var/rapidFirestop = 0 + var/rapid_message = 0 + var/damage_multiplier = 1 + var/has_played_alert = 0 + +/obj/item/weapon/gun/lawgiver/New() + ..() + magazine = new /obj/item/ammo_storage/magazine/lawgiver + verbs -= /obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample + update_icon() + +/obj/item/weapon/gun/lawgiver/GetVoice() + var/the_name = "The [name]" + return the_name + +/obj/item/weapon/gun/lawgiver/equipped(M as mob, hand) + update_icon() + +/obj/item/weapon/gun/lawgiver/update_icon() + overlays.len = 0 + if(magazine) + item_state = "[initial(icon_state)]1" + var/obj/item/ammo_storage/magazine/lawgiver/L = magazine + var/image/magazine_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)]Mag") + var/image/ammo_overlay = null + if(firing_mode == STUN && L.stuncharge) + ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.stuncharge/20]") + if(firing_mode == LASER && L.lasercharge) + ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.lasercharge/20]") + if(firing_mode == RAPID && L.rapid_ammo_count) + ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.rapid_ammo_count]") + if(firing_mode == FLARE && L.flare_ammo_count) + ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.flare_ammo_count]") + if(firing_mode == HI_EX && L.hi_ex_ammo_count) + ammo_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)][L.hi_ex_ammo_count]") + overlays += magazine_overlay + overlays += ammo_overlay + else + item_state = "[initial(icon_state)]0" + + if (istype(loc,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + var/image/DNA_overlay = null + if(H.l_hand == src || H.r_hand == src) + if(dna_profile) + if(dna_profile == H.dna.unique_enzymes) + DNA_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)]DNAgood") + else + DNA_overlay = image('icons/obj/gun.dmi', src, "[initial(icon_state)]DNAbad") + overlays += DNA_overlay + H.update_inv_r_hand() + H.update_inv_l_hand() + + +/obj/item/weapon/gun/lawgiver/verb/submit_DNA_sample() + set name = "Submit DNA sample" + set category = "Object" + set src in usr + + var/mob/living/carbon/human/H = loc + + if(!dna_profile) + dna_profile = H.dna.unique_enzymes + to_chat(usr, "You submit a DNA sample to \the [src].") + verbs += /obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample + verbs -= /obj/item/weapon/gun/lawgiver/verb/submit_DNA_sample + +/obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample() + set name = "Erase DNA sample" + set category = "Object" + set src in usr + + var/mob/living/carbon/human/H = loc + + if(dna_profile) + if(dna_profile == H.dna.unique_enzymes) + dna_profile = null + to_chat(usr, "You erase the DNA profile from \the [src].") + verbs += /obj/item/weapon/gun/lawgiver/verb/submit_DNA_sample + verbs -= /obj/item/weapon/gun/lawgiver/verb/erase_DNA_sample + else + self_destruct(H) + +/obj/item/weapon/gun/lawgiver/proc/self_destruct(mob/user) + var/req_access = list(access_security) + if(can_access(user.GetAccess(),req_access)) + say("ERROR: DNA PROFILE DOES NOT MATCH") + return + say("UNAUTHORIZED ACCESS DETECTED") + explosion(user, -1, 0, 2) + qdel(src) + +/obj/item/weapon/gun/lawgiver/proc/LoadMag(var/obj/item/ammo_storage/magazine/AM, var/mob/user) + if(istype(AM, /obj/item/ammo_storage/magazine/lawgiver) && !magazine) + if(user) + if(user.drop_item(AM, src)) + to_chat(user, "You load the magazine into \the [src].") + else + return + + magazine = AM + AM.update_icon() + update_icon() + return 1 + return 0 + +/obj/item/weapon/gun/lawgiver/proc/RemoveMag(var/mob/user) + if(magazine) + var/obj/item/ammo_storage/magazine/lawgiver/L = magazine + L.loc = get_turf(src.loc) + if(user) + user.put_in_hands(L) + to_chat(user, "You pull the magazine out of \the [src]!") + L.update_icon() + magazine = null + update_icon() + return 1 + return 0 + +/obj/item/weapon/gun/lawgiver/Hear(var/datum/speech/speech, var/rendered_speech="") + if(speech.speaker == loc && !speech.frequency && dna_profile) + var/mob/living/carbon/human/H = loc + if(dna_profile == H.dna.unique_enzymes) + recoil = 0 + if((findtext(speech.message, "stun")) || (findtext(speech.message, "taser"))) + firing_mode = STUN + fire_sound = 'sound/weapons/Taser.ogg' + projectile_type = "/obj/item/projectile/energy/electrode" + fire_delay = 0 + sleep(3) + say("STUN") + else if((findtext(speech.message, "laser")) || (findtext(speech.message, "lethal")) || (findtext(speech.message, "beam"))) + firing_mode = LASER + fire_sound = 'sound/weapons/lasercannonfire.ogg' + projectile_type = "/obj/item/projectile/beam/heavylaser" + fire_delay = 5 + sleep(3) + say("LASER") + else if((findtext(speech.message, "rapid")) || (findtext(speech.message, "automatic"))) + firing_mode = RAPID + fire_sound = 'sound/weapons/Gunshot_c20.ogg' + projectile_type = "/obj/item/projectile/bullet/midbullet/lawgiver" + fire_delay = 0 + rapid_message = 0 + recoil = 1 + sleep(3) + say("RAPID FIRE") + else if((findtext(speech.message, "flare")) || (findtext(speech.message, "incendiary"))) + firing_mode = FLARE + fire_sound = 'sound/weapons/shotgun.ogg' + projectile_type = "/obj/item/projectile/flare" + fire_delay = 5 + recoil = 1 + sleep(3) + say("FLARE") + else if((findtext(speech.message, "hi ex")) || (findtext(speech.message, "hi-ex")) || (findtext(speech.message, "explosive")) || (findtext(speech.message, "rocket"))) + firing_mode = HI_EX + fire_sound = 'sound/weapons/elecfire.ogg' + projectile_type = "/obj/item/projectile/bullet/gyro" + fire_delay = 4 + recoil = 1 + sleep(3) + say("HI-EX") + update_icon() + +/obj/item/weapon/gun/lawgiver/proc/rapidFire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) //Burst fires don't work well except by calling Fire() multiple times + rapidFirecheck = 1 + for (var/i = 1; i <= 3; i++) + if(!rapidFirestop) + Fire(target, user, params, reflex, struggle) + rapidFirecheck = 0 + rapidFirechamber = 0 + rapidFirestop = 0 + rapid_message = 0 + +/obj/item/weapon/gun/lawgiver/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) //Overriding this due to introducing the DNA check, and the fact that the round is to be chambered only just before it is fired + if(dna_profile) + if(dna_profile != user.dna.unique_enzymes) + self_destruct(user) + return + else + click_empty(user) + say("PLEASE REGISTER A DNA SAMPLE") + return + + if(firing_mode == RAPID && !rapidFirecheck) + rapidFire(target, user, params, reflex, struggle) + return + + //Christ Almighty is there no OOP way to do this? + if (!ready_to_fire()) + if (world.time % 3) //to prevent spam + to_chat(user, "[src] is not ready to fire again!") + return + + if(firing_mode == RAPID && !rapidFirechamber) + in_chamber = null + if(!chamber_round()) + rapidFirestop = 1 + return click_empty(user) + rapidFirechamber = 1 + + else if(firing_mode == RAPID && rapidFirechamber) + in_chamber = new projectile_type(src) + + else if(firing_mode != RAPID) + in_chamber = null + if(!chamber_round()) + return click_empty(user) + + if(clumsy_check) + if(istype(user, /mob/living)) + var/mob/living/M = user + if ((M_CLUMSY in M.mutations) && prob(50)) + to_chat(M, "[src] blows up in your face.") + M.take_organ_damage(0,20) + M.drop_item(src, force_drop = 1) + qdel(src) + return + + if (!user.IsAdvancedToolUser() || isMoMMI(user) || istype(user, /mob/living/carbon/monkey/diona)) + to_chat(user, "You don't have the dexterity to do this!") + return + if(istype(user, /mob/living)) + var/mob/living/M = user + if (M_HULK in M.mutations) + to_chat(M, "Your meaty finger is much too large for the trigger guard!") + return + if(ishuman(user)) + var/mob/living/carbon/human/H=user + if(user.dna && (user.dna.mutantrace == "adamantine" || user.dna.mutantrace=="coalgolem")) + to_chat(user, "Your fat fingers don't fit in the trigger guard!") + return + var/datum/organ/external/a_hand = H.get_active_hand_organ() + if(!a_hand.can_use_advanced_tools()) + to_chat(user, "Your [a_hand] doesn't have the dexterity to do this!") + return + + in_chamber.damage *= damage_multiplier + + add_fingerprint(user) + + var/turf/curloc = get_turf(user) + var/turf/targloc = get_turf(target) + if (!istype(targloc) || !istype(curloc)) + return + + if(!special_check(user)) + return + + if(!in_chamber) + return + log_attack("[user.name] ([user.ckey]) fired \the [src] (proj:[in_chamber.name]) at [target] [ismob(target) ? "([target:ckey])" : ""] ([target.x],[target.y],[target.z])[struggle ? " due to being disarmed." :""]" ) + in_chamber.firer = user + in_chamber.def_zone = user.zone_sel.selecting + if(targloc == curloc) + user.bullet_act(in_chamber) + qdel(in_chamber) + in_chamber = null + update_icon() + return + + if((firing_mode == RAPID && !rapid_message) || (firing_mode != RAPID)) //On rapid mode, only shake once per burst. + if(recoil) + spawn() + shake_camera(user, recoil + 1, recoil) + if(user.locked_to && isobj(user.locked_to) && !user.locked_to.anchored ) + var/direction = get_dir(user,target) + spawn() + var/obj/B = user.locked_to + var/movementdirection = turn(direction,180) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(1) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(2) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + sleep(3) + B.Move(get_step(user,movementdirection), movementdirection) + if((istype(user.loc, /turf/space)) || (user.areaMaster.has_gravity == 0)) + user.inertia_dir = get_dir(target, user) + step(user, user.inertia_dir) + + playsound(user, fire_sound, 50, 1) + if(!rapid_message) + user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \ + "You fire [src][reflex ? "by reflex":""]!", \ + "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") + if(firing_mode == RAPID) + rapid_message = 1 + + in_chamber.original = target + in_chamber.loc = get_turf(user) + in_chamber.starting = get_turf(user) + in_chamber.shot_from = src + user.delayNextAttack(fire_delay) + in_chamber.silenced = silenced + in_chamber.current = curloc + in_chamber.OnFired() + in_chamber.yo = targloc.y - curloc.y + in_chamber.xo = targloc.x - curloc.x + in_chamber.inaccurate = (istype(user.locked_to, /obj/structure/bed/chair/vehicle)) + + if(params) + var/list/mouse_control = params2list(params) + if(mouse_control["icon-x"]) + in_chamber.p_x = text2num(mouse_control["icon-x"]) + if(mouse_control["icon-y"]) + in_chamber.p_y = text2num(mouse_control["icon-y"]) + + spawn() + if(in_chamber) + in_chamber.process() + sleep(1) + in_chamber = null + + update_icon() + + if(user.hand) + user.update_inv_l_hand() + else + user.update_inv_r_hand() + + if(firing_mode == RAPID) + var/obj/item/ammo_casing/a12mm/A = new /obj/item/ammo_casing/a12mm(user.loc) + A.BB = null + A.update_icon() + if(firing_mode == HI_EX) + var/obj/item/ammo_casing/a75/A = new /obj/item/ammo_casing/a75(user.loc) + A.BB = null + A.update_icon() + +/obj/item/weapon/gun/lawgiver/attack(mob/living/M as mob, mob/living/user as mob, def_zone) + //Suicide handling. + if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot) + if(istype(M.wear_mask, /obj/item/clothing/mask/happy)) + to_chat(M, "BUT WHY? I'M SO HAPPY!") + return + mouthshoot = 1 + M.visible_message("[user] sticks their gun in their mouth, ready to pull the trigger...") + if(!do_after(user,src, 40)) + M.visible_message("[user] decided life was worth living") + mouthshoot = 0 + return + if(dna_profile) + if(dna_profile != user.dna.unique_enzymes) + self_destruct(user) + return + else + user.visible_message("[user] pulls the trigger.") + click_empty(user) + say("PLEASE REGISTER A DNA SAMPLE") + return + if (chamber_round()) + user.visible_message("[user] pulls the trigger.") + playsound(user, fire_sound, 50, 1) + in_chamber.on_hit(M) + if (!in_chamber.nodamage) + user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]") + user.stat=2 // Just to be sure + user.death() + else + to_chat(user, "Ow...") + user.apply_effect(110,AGONY,0) + qdel(in_chamber) + in_chamber = null + mouthshoot = 0 + return + else + click_empty(user) + mouthshoot = 0 + return + + if (can_shoot()) + //Point blank shooting if on harm intent or target we were targeting. + if(user.a_intent == I_HURT) + user.visible_message(" \The [user] fires \the [src] point blank at [M]!") + damage_multiplier = 1.3 + src.Fire(M,user,0,0,1) + damage_multiplier = 1 + return + else if(target && M in target) + src.Fire(M,user,0,0,1) + return + else + return ..() + else + return ..() + +/obj/item/weapon/gun/lawgiver/proc/chamber_round() + if(in_chamber || !magazine) + return 0 + else + var/obj/item/ammo_storage/magazine/lawgiver/L = magazine + switch(firing_mode) + if(STUN) + if(L.stuncharge >= 20) + if(in_chamber) return 1 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + L.stuncharge -= 20 + return 1 + else + return 0 + if(LASER) + if(L.lasercharge >= 20) + if(in_chamber) return 1 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + L.lasercharge -= 20 + return 1 + else + return 0 + if(RAPID) + if(L.rapid_ammo_count >= 1) + if(in_chamber) return 1 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + L.rapid_ammo_count -= 1 + return 1 + else + return 0 + if(FLARE) + if(L.flare_ammo_count >= 1) + if(in_chamber) return 1 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + L.flare_ammo_count -= 1 + return 1 + else + return 0 + if(HI_EX) + if(L.hi_ex_ammo_count >= 1) + if(in_chamber) return 1 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + L.hi_ex_ammo_count -= 1 + return 1 + else + return 0 + return 0 + +/obj/item/weapon/gun/lawgiver/proc/can_shoot() //Only made so that firing point-blank can run its checks without chambering a round, since rounds are chambered in Fire() + if(!magazine) + return 0 + else + var/obj/item/ammo_storage/magazine/lawgiver/L = magazine + switch(firing_mode) + if(STUN) + if(L.stuncharge >= 20) + if(in_chamber) return 1 + if(!projectile_type) return 0 + return 1 + else + return 0 + if(LASER) + if(L.lasercharge >= 20) + if(in_chamber) return 1 + if(!projectile_type) return 0 + return 1 + else + return 0 + if(RAPID) + if(L.rapid_ammo_count >= 1) + if(in_chamber) return 1 + if(!projectile_type) return 0 + return 1 + else + return 0 + if(FLARE) + if(L.flare_ammo_count >= 1) + if(in_chamber) return 1 + if(!projectile_type) return 0 + return 1 + else + return 0 + if(HI_EX) + if(L.hi_ex_ammo_count >= 1) + if(in_chamber) return 1 + if(!projectile_type) return 0 + return 1 + else + return 0 + return 0 + +/obj/item/weapon/gun/lawgiver/attackby(var/obj/item/A as obj, mob/user as mob) + if(istype(A, /obj/item/ammo_storage/magazine/lawgiver)) + var/obj/item/ammo_storage/magazine/lawgiver/AM = A + if(!magazine) + LoadMag(AM, user) + else + to_chat(user, "There is already a magazine loaded in \the [src]!") + else if (istype(A, /obj/item/ammo_storage/magazine)) + to_chat(user, "You can't load \the [src] with that kind of magazine!") + +/obj/item/weapon/gun/lawgiver/attack_self(mob/user as mob) + if (target) + return ..() + if (magazine) + RemoveMag(user) + else + to_chat(user, "There's no magazine loaded in \the [src]!") + +/obj/item/weapon/gun/lawgiver/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, struggle = 0) + ..() + if(magazine) + var/obj/item/ammo_storage/magazine/lawgiver/L = magazine + if(magazine && !countAmmo(L) && !has_played_alert) + playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) + has_played_alert = 1 + return + +/obj/item/weapon/gun/lawgiver/examine(mob/user) + ..() + getAmmo(user) + +/obj/item/weapon/gun/lawgiver/proc/getAmmo(mob/user) + if (magazine) + var/obj/item/ammo_storage/magazine/lawgiver/L = magazine + to_chat(user, "It has enough energy for [L.stuncharge/20] stun shot\s left.") + to_chat(user, "It has enough energy for [L.lasercharge/20] laser shot\s left.") + to_chat(user, "It has [L.rapid_ammo_count] rapid fire round\s remaining.") + to_chat(user, "It has [L.flare_ammo_count] flare round\s remaining.") + to_chat(user, "It has [L.hi_ex_ammo_count] hi-EX round\s remaining.") + +/obj/item/weapon/gun/lawgiver/proc/countAmmo(var/obj/item/A) + var/obj/item/ammo_storage/magazine/lawgiver/L = A + if (L.stuncharge == 0 && L.lasercharge == 0 && L.rapid_ammo_count == 0 && L.flare_ammo_count == 0 && L.hi_ex_ammo_count == 0) + return 0 + else + has_played_alert = 0 + return 1 + +#undef HI_EX +#undef RAPID +#undef FLARE +#undef STUN +#undef LASER diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 6d30531922f..4d105ac87e2 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -1,232 +1,232 @@ -#define SPEEDLOADER 0 //the gun takes bullets directly -#define FROM_BOX 1 -#define MAGAZINE 2 //the gun takes a magazine into gun storage - -/obj/item/weapon/gun/projectile - desc = "A classic revolver. Uses 357 ammo" - name = "revolver" - icon_state = "revolver" - caliber = list("357" = 1) - origin_tech = "combat=2;materials=2" - w_class = 3.0 - starting_materials = list(MAT_IRON = 1000) - w_type = RECYK_METAL - recoil = 1 - var/ammo_type = "/obj/item/ammo_casing/a357" - var/list/loaded = list() - var/max_shells = 7 //only used by guns with no magazine - var/load_method = SPEEDLOADER //0 = Single shells or quick loader, 1 = box, 2 = magazine - var/obj/item/ammo_storage/magazine/stored_magazine = null - var/obj/item/ammo_casing/chambered = null - var/mag_type = "" - - var/gun_flags = EMPTYCASINGS //Yay, flags - -/obj/item/weapon/gun/projectile/New() - ..() - if(mag_type && load_method == 2) - stored_magazine = new mag_type(src) - chamber_round() - else - for(var/i = 1, i <= max_shells, i++) - loaded += new ammo_type(src) - update_icon() - return - -//loads the argument magazine into the gun -/obj/item/weapon/gun/projectile/proc/LoadMag(var/obj/item/ammo_storage/magazine/AM, var/mob/user) - if(istype(AM, text2path(mag_type)) && !stored_magazine) - if(user) - if(user.drop_item(AM, src)) - to_chat(usr, "You load the magazine into \the [src].") - else - return - - stored_magazine = AM - chamber_round() - AM.update_icon() - update_icon() - - if(user) - user.update_inv_r_hand() - user.update_inv_l_hand() - return 1 - return 0 - -/obj/item/weapon/gun/projectile/proc/RemoveMag(var/mob/user) - if(stored_magazine) - stored_magazine.loc = get_turf(src.loc) - if(user) - user.put_in_hands(stored_magazine) - to_chat(usr, "You pull the magazine out of \the [src]!") - stored_magazine.update_icon() - stored_magazine = null - update_icon() - user.update_inv_r_hand() - user.update_inv_l_hand() - return 1 - return 0 - -/obj/item/weapon/gun/projectile/verb/force_removeMag() - set name = "Remove Magazine" - set category = "Object" - set src in range(0) - if(stored_magazine) - RemoveMag() - else - to_chat(usr, "There is no magazine to remove!") - - -/obj/item/weapon/gun/projectile/proc/chamber_round() //Only used by guns with magazine - if(chambered || !stored_magazine) - return 0 - else - var/obj/item/ammo_casing/round = stored_magazine.get_round() - if(istype(round)) - chambered = round - chambered.loc = src - return 1 - return 0 - -/obj/item/weapon/gun/projectile/proc/getAC() - var/obj/item/ammo_casing/AC = null - if(mag_type && load_method == 2) - AC = chambered - else if(getAmmo()) - AC = loaded[1] //load next casing. - return AC - -/obj/item/weapon/gun/projectile/process_chambered() - var/obj/item/ammo_casing/AC = getAC() - if(in_chamber) - return 1 //{R} - if(isnull(AC) || !istype(AC)) - return - if(mag_type && load_method == 2) - chambered = null //Remove casing from chamber. - chamber_round() - else - loaded -= AC //Remove casing from loaded list. - if(gun_flags &EMPTYCASINGS) - AC.loc = get_turf(src) //Eject casing onto ground. - if(AC.BB) - in_chamber = AC.BB //Load projectile into chamber. - AC.BB.loc = src //Set projectile loc to gun. - AC.BB = null //Empty casings - AC.update_icon() - return 1 - return 0 - -/obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob) - if(istype(A, /obj/item/gun_part/silencer) && src.gun_flags &SILENCECOMP) - if(user.l_hand != src && user.r_hand != src) //if we're not in his hands - to_chat(user, "You'll need [src] in your hands to do that.") - return - - if(user.drop_item(A, src)) //put the silencer into the gun - to_chat(user, "You screw [A] onto [src].") - silenced = A //dodgy? - w_class = 3 - update_icon() - return 1 - - var/num_loaded = 0 - if(istype(A, /obj/item/ammo_storage/magazine)) - var/obj/item/ammo_storage/magazine/AM = A - if(load_method == MAGAZINE) - if(!stored_magazine) - LoadMag(AM, user) - else - to_chat(user, "There is already a magazine loaded in \the [src]!") - else - to_chat(user, "You can't load \the [src] with a magazine, dummy!") - if(istype(A, /obj/item/ammo_storage) && load_method != MAGAZINE) - var/obj/item/ammo_storage/AS = A - var/success_load = AS.LoadInto(AS, src) - if(success_load) - to_chat(user, "You successfully fill the [src] with [success_load] shell\s from the [AS].") - if(istype(A, /obj/item/ammo_casing)) - var/obj/item/ammo_casing/AC = A - //message_admins("Loading the [src], with [AC], [AC.caliber] and [caliber.len]") //Enable this for testing - if(AC.BB && caliber[AC.caliber]) // a used bullet can't be fired twice - if(load_method == MAGAZINE && !chambered) - if(user.drop_item(AC, src)) - chambered = AC - num_loaded++ - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) - else if(getAmmo() < max_shells) - if(user.drop_item(AC, src)) - loaded += AC - num_loaded++ - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) - - if(num_loaded) - to_chat(user, "You load [num_loaded] shell\s into \the [src]!") - A.update_icon() - update_icon() - return - -/obj/item/weapon/gun/projectile/attack_self(mob/user as mob) - if (target) - return ..() - if (loaded.len || stored_magazine) - if (load_method == SPEEDLOADER) - var/obj/item/ammo_casing/AC = loaded[1] - loaded -= AC - AC.loc = get_turf(src) //Eject casing onto ground. - to_chat(user, "You unload \the [AC] from \the [src]!") - update_icon() - return - if (load_method == MAGAZINE && stored_magazine) - RemoveMag(user) - else if(loc == user) - if(chambered) // So it processing unloading of a bullet first - var/obj/item/ammo_casing/AC = chambered - AC.loc = get_turf(src) //Eject casing onto ground. - chambered = null - to_chat(user, "You unload \the [AC] from \the [src]!") - update_icon() - return - if(silenced) - if(user.l_hand != src && user.r_hand != src) - ..() - return - to_chat(user, "You unscrew [silenced] from [src].") - user.put_in_hands(silenced) - silenced = 0 - w_class = 2 - update_icon() - return - else - to_chat(user, "Nothing loaded in \the [src]!") - -/obj/item/weapon/gun/projectile/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, struggle = 0) - ..() - if(!chambered && stored_magazine && !stored_magazine.ammo_count() && gun_flags &AUTOMAGDROP) //auto_mag_drop decides whether or not the mag is dropped once it empties - RemoveMag() - playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) - return - -/obj/item/weapon/gun/projectile/examine(mob/user) - ..() - to_chat(user, "Has [getAmmo()] round\s remaining.") -// if(in_chamber && !loaded.len) -// to_chat(usr, "However, it has a chambered round.") -// if(in_chamber && loaded.len) -// to_chat(usr, "It also has a chambered round." {R}) - if(istype(silenced, /obj/item/gun_part/silencer)) - to_chat(user, "It has a supressor attached to the barrel.") - -/obj/item/weapon/gun/projectile/proc/getAmmo() - var/bullets = 0 - if(mag_type && load_method == 2) - if(stored_magazine) - bullets += stored_magazine.ammo_count() - if(chambered) - bullets++ - else - for(var/obj/item/ammo_casing/AC in loaded) - if(istype(AC)) - bullets += 1 - return bullets - +#define SPEEDLOADER 0 //the gun takes bullets directly +#define FROM_BOX 1 +#define MAGAZINE 2 //the gun takes a magazine into gun storage + +/obj/item/weapon/gun/projectile + desc = "A classic revolver. Uses 357 ammo" + name = "revolver" + icon_state = "revolver" + caliber = list("357" = 1) + origin_tech = "combat=2;materials=2" + w_class = 3.0 + starting_materials = list(MAT_IRON = 1000) + w_type = RECYK_METAL + recoil = 1 + var/ammo_type = "/obj/item/ammo_casing/a357" + var/list/loaded = list() + var/max_shells = 7 //only used by guns with no magazine + var/load_method = SPEEDLOADER //0 = Single shells or quick loader, 1 = box, 2 = magazine + var/obj/item/ammo_storage/magazine/stored_magazine = null + var/obj/item/ammo_casing/chambered = null + var/mag_type = "" + + var/gun_flags = EMPTYCASINGS //Yay, flags + +/obj/item/weapon/gun/projectile/New() + ..() + if(mag_type && load_method == 2) + stored_magazine = new mag_type(src) + chamber_round() + else + for(var/i = 1, i <= max_shells, i++) + loaded += new ammo_type(src) + update_icon() + return + +//loads the argument magazine into the gun +/obj/item/weapon/gun/projectile/proc/LoadMag(var/obj/item/ammo_storage/magazine/AM, var/mob/user) + if(istype(AM, text2path(mag_type)) && !stored_magazine) + if(user) + if(user.drop_item(AM, src)) + to_chat(usr, "You load the magazine into \the [src].") + else + return + + stored_magazine = AM + chamber_round() + AM.update_icon() + update_icon() + + if(user) + user.update_inv_r_hand() + user.update_inv_l_hand() + return 1 + return 0 + +/obj/item/weapon/gun/projectile/proc/RemoveMag(var/mob/user) + if(stored_magazine) + stored_magazine.loc = get_turf(src.loc) + if(user) + user.put_in_hands(stored_magazine) + to_chat(usr, "You pull the magazine out of \the [src]!") + stored_magazine.update_icon() + stored_magazine = null + update_icon() + user.update_inv_r_hand() + user.update_inv_l_hand() + return 1 + return 0 + +/obj/item/weapon/gun/projectile/verb/force_removeMag() + set name = "Remove Magazine" + set category = "Object" + set src in range(0) + if(stored_magazine) + RemoveMag() + else + to_chat(usr, "There is no magazine to remove!") + + +/obj/item/weapon/gun/projectile/proc/chamber_round() //Only used by guns with magazine + if(chambered || !stored_magazine) + return 0 + else + var/obj/item/ammo_casing/round = stored_magazine.get_round() + if(istype(round)) + chambered = round + chambered.loc = src + return 1 + return 0 + +/obj/item/weapon/gun/projectile/proc/getAC() + var/obj/item/ammo_casing/AC = null + if(mag_type && load_method == 2) + AC = chambered + else if(getAmmo()) + AC = loaded[1] //load next casing. + return AC + +/obj/item/weapon/gun/projectile/process_chambered() + var/obj/item/ammo_casing/AC = getAC() + if(in_chamber) + return 1 //{R} + if(isnull(AC) || !istype(AC)) + return + if(mag_type && load_method == 2) + chambered = null //Remove casing from chamber. + chamber_round() + else + loaded -= AC //Remove casing from loaded list. + if(gun_flags &EMPTYCASINGS) + AC.loc = get_turf(src) //Eject casing onto ground. + if(AC.BB) + in_chamber = AC.BB //Load projectile into chamber. + AC.BB.loc = src //Set projectile loc to gun. + AC.BB = null //Empty casings + AC.update_icon() + return 1 + return 0 + +/obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob) + if(istype(A, /obj/item/gun_part/silencer) && src.gun_flags &SILENCECOMP) + if(user.l_hand != src && user.r_hand != src) //if we're not in his hands + to_chat(user, "You'll need [src] in your hands to do that.") + return + + if(user.drop_item(A, src)) //put the silencer into the gun + to_chat(user, "You screw [A] onto [src].") + silenced = A //dodgy? + w_class = 3 + update_icon() + return 1 + + var/num_loaded = 0 + if(istype(A, /obj/item/ammo_storage/magazine)) + var/obj/item/ammo_storage/magazine/AM = A + if(load_method == MAGAZINE) + if(!stored_magazine) + LoadMag(AM, user) + else + to_chat(user, "There is already a magazine loaded in \the [src]!") + else + to_chat(user, "You can't load \the [src] with a magazine, dummy!") + if(istype(A, /obj/item/ammo_storage) && load_method != MAGAZINE) + var/obj/item/ammo_storage/AS = A + var/success_load = AS.LoadInto(AS, src) + if(success_load) + to_chat(user, "You successfully fill the [src] with [success_load] shell\s from the [AS].") + if(istype(A, /obj/item/ammo_casing)) + var/obj/item/ammo_casing/AC = A + //message_admins("Loading the [src], with [AC], [AC.caliber] and [caliber.len]") //Enable this for testing + if(AC.BB && caliber[AC.caliber]) // a used bullet can't be fired twice + if(load_method == MAGAZINE && !chambered) + if(user.drop_item(AC, src)) + chambered = AC + num_loaded++ + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + else if(getAmmo() < max_shells) + if(user.drop_item(AC, src)) + loaded += AC + num_loaded++ + playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + + if(num_loaded) + to_chat(user, "You load [num_loaded] shell\s into \the [src]!") + A.update_icon() + update_icon() + return + +/obj/item/weapon/gun/projectile/attack_self(mob/user as mob) + if (target) + return ..() + if (loaded.len || stored_magazine) + if (load_method == SPEEDLOADER) + var/obj/item/ammo_casing/AC = loaded[1] + loaded -= AC + AC.loc = get_turf(src) //Eject casing onto ground. + to_chat(user, "You unload \the [AC] from \the [src]!") + update_icon() + return + if (load_method == MAGAZINE && stored_magazine) + RemoveMag(user) + else if(loc == user) + if(chambered) // So it processing unloading of a bullet first + var/obj/item/ammo_casing/AC = chambered + AC.loc = get_turf(src) //Eject casing onto ground. + chambered = null + to_chat(user, "You unload \the [AC] from \the [src]!") + update_icon() + return + if(silenced) + if(user.l_hand != src && user.r_hand != src) + ..() + return + to_chat(user, "You unscrew [silenced] from [src].") + user.put_in_hands(silenced) + silenced = 0 + w_class = 2 + update_icon() + return + else + to_chat(user, "Nothing loaded in \the [src]!") + +/obj/item/weapon/gun/projectile/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, struggle = 0) + ..() + if(!chambered && stored_magazine && !stored_magazine.ammo_count() && gun_flags &AUTOMAGDROP) //auto_mag_drop decides whether or not the mag is dropped once it empties + RemoveMag() + playsound(user, 'sound/weapons/smg_empty_alarm.ogg', 40, 1) + return + +/obj/item/weapon/gun/projectile/examine(mob/user) + ..() + to_chat(user, "Has [getAmmo()] round\s remaining.") +// if(in_chamber && !loaded.len) +// to_chat(usr, "However, it has a chambered round.") +// if(in_chamber && loaded.len) +// to_chat(usr, "It also has a chambered round." {R}) + if(istype(silenced, /obj/item/gun_part/silencer)) + to_chat(user, "It has a supressor attached to the barrel.") + +/obj/item/weapon/gun/projectile/proc/getAmmo() + var/bullets = 0 + if(mag_type && load_method == 2) + if(stored_magazine) + bullets += stored_magazine.ammo_count() + if(chambered) + bullets++ + else + for(var/obj/item/ammo_casing/AC in loaded) + if(istype(AC)) + bullets += 1 + return bullets + diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 408550a2f3a..1312de27c13 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -1,188 +1,188 @@ -/obj/item/weapon/gun/projectile/automatic //Hopefully someone will find a way to make these fire in bursts or something. --Superxpdude - name = "submachine gun" - desc = "A lightweight, fast firing gun. Uses 9mm rounds." - icon_state = "saber" //ugly - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - w_class = 3.0 - max_shells = 18 - caliber = list("9mm" = 1) - origin_tech = "combat=4;materials=2" - ammo_type = "/obj/item/ammo_casing/c9mm" - automatic = 1 - fire_delay = 0 - var/burstfire = 0 //Whether or not the gun fires multiple bullets at once - var/burst_count = 3 - load_method = 2 - mag_type = "/obj/item/ammo_storage/magazine/smg9mm" - -/obj/item/weapon/gun/projectile/automatic/isHandgun() - return 0 - -/obj/item/weapon/gun/projectile/automatic/verb/ToggleFire() - set name = "Toggle Burstfire" - set category = "Object" - burstfire = !burstfire - if(!burstfire)//fixing a bug where burst fire being toggled on then off would leave the gun unable to shoot at its normal speed. - fire_delay = initial(fire_delay) +/obj/item/weapon/gun/projectile/automatic //Hopefully someone will find a way to make these fire in bursts or something. --Superxpdude + name = "submachine gun" + desc = "A lightweight, fast firing gun. Uses 9mm rounds." + icon_state = "saber" //ugly + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + w_class = 3.0 + max_shells = 18 + caliber = list("9mm" = 1) + origin_tech = "combat=4;materials=2" + ammo_type = "/obj/item/ammo_casing/c9mm" + automatic = 1 + fire_delay = 0 + var/burstfire = 0 //Whether or not the gun fires multiple bullets at once + var/burst_count = 3 + load_method = 2 + mag_type = "/obj/item/ammo_storage/magazine/smg9mm" + +/obj/item/weapon/gun/projectile/automatic/isHandgun() + return 0 + +/obj/item/weapon/gun/projectile/automatic/verb/ToggleFire() + set name = "Toggle Burstfire" + set category = "Object" + burstfire = !burstfire + if(!burstfire)//fixing a bug where burst fire being toggled on then off would leave the gun unable to shoot at its normal speed. + fire_delay = initial(fire_delay) to_chat(usr, "You toggle \the [src]'s firing setting to [burstfire ? "burst fire" : "single fire"].") - -/obj/item/weapon/gun/projectile/automatic/update_icon() - ..() - icon_state = "[initial(icon_state)][stored_magazine ? "-[stored_magazine.max_ammo]" : ""][chambered ? "" : "-e"]" - return - -/obj/item/weapon/gun/projectile/automatic/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) - if(burstfire == 1) - if(ready_to_fire()) - fire_delay = 0 - else + +/obj/item/weapon/gun/projectile/automatic/update_icon() + ..() + icon_state = "[initial(icon_state)][stored_magazine ? "-[stored_magazine.max_ammo]" : ""][chambered ? "" : "-e"]" + return + +/obj/item/weapon/gun/projectile/automatic/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) + if(burstfire == 1) + if(ready_to_fire()) + fire_delay = 0 + else to_chat(usr, "\The [src] is still cooling down!") - return - var/shots_fired = 0 //haha, I'm so clever - var/to_shoot = min(burst_count, getAmmo()) - for(var/i = 1; i <= to_shoot; i++) - ..() - shots_fired++ - message_admins("[usr] just shot [shots_fired] burst fire bullets out of [getAmmo() + shots_fired] from their [src].") - fire_delay = shots_fired * 10 - else - ..() - -/obj/item/weapon/gun/projectile/automatic/mini_uzi - name = "Uzi" - desc = "A lightweight, fast firing gun, for when you want someone dead. Uses .45 rounds." - icon_state = "mini-uzi" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - w_class = 3.0 - max_shells = 10 - burst_count = 3 - caliber = list(".45" = 1) - origin_tech = "combat=5;materials=2;syndicate=8" - ammo_type = "/obj/item/ammo_casing/c45" - mag_type = "/obj/item/ammo_storage/magazine/uzi45" - -/obj/item/weapon/gun/projectile/automatic/mini_uzi/isHandgun() - return 1 - -/obj/item/weapon/gun/projectile/automatic/c20r - name = "\improper C-20r SMG" - desc = "A lightweight, fast firing gun, for when you REALLY need someone dead. Uses 12mm rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp" - icon_state = "c20r" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns.dmi', "right_hand" = 'icons/mob/in-hand/right/guns.dmi') - item_state = "c20r" - w_class = 3.0 - max_shells = 20 - burst_count = 4 - caliber = list("12mm" = 1) - origin_tech = "combat=5;materials=2;syndicate=8" - ammo_type = "/obj/item/ammo_casing/a12mm" - mag_type = "/obj/item/ammo_storage/magazine/a12mm" - fire_sound = 'sound/weapons/Gunshot_c20.ogg' - load_method = 2 - - gun_flags = AUTOMAGDROP | EMPTYCASINGS - -/obj/item/weapon/gun/projectile/automatic/c20r/update_icon() - ..() - if(stored_magazine) - icon_state = "c20r-[round(getAmmo(),4)]" - else - icon_state = "c20r" - return - -/obj/item/weapon/gun/projectile/automatic/xcom - name = "\improper Assault Rifle" - desc = "A lightweight, fast firing gun, issued to shadow organization members." - icon_state = "xcomassaultrifle" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - origin_tech = "combat=5;materials=2" - w_class = 3.0 - max_shells = 20 - burst_count = 4 - caliber = list("12mm" = 1) - ammo_type = "/obj/item/ammo_casing/a12mm" - mag_type = "/obj/item/ammo_storage/magazine/a12mm" - fire_sound = 'sound/weapons/Gunshot_c20.ogg' - load_method = 2 - - gun_flags = AUTOMAGDROP | EMPTYCASINGS - -/obj/item/weapon/gun/projectile/automatic/l6_saw - name = "\improper L6 SAW" - desc = "A rather traditionally made light machine gun with a pleasantly lacquered wooden pistol grip. Has 'Aussec Armoury- 2531' engraved on the reciever" - icon_state = "l6closed100" - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns.dmi', "right_hand" = 'icons/mob/in-hand/right/guns.dmi') - item_state = "l6closedmag" - w_class = 4 - slot_flags = 0 - max_shells = 50 - burst_count = 5 - caliber = list("a762" = 1) - origin_tech = "combat=5;materials=1;syndicate=2" - ammo_type = "/obj/item/ammo_casing/a762" - mag_type = "/obj/item/ammo_storage/magazine/a762" - fire_sound = 'sound/weapons/Gunshot_smg.ogg' - load_method = 2 - var/cover_open = 0 - - -/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob) - cover_open = !cover_open + return + var/shots_fired = 0 //haha, I'm so clever + var/to_shoot = min(burst_count, getAmmo()) + for(var/i = 1; i <= to_shoot; i++) + ..() + shots_fired++ + message_admins("[usr] just shot [shots_fired] burst fire bullets out of [getAmmo() + shots_fired] from their [src].") + fire_delay = shots_fired * 10 + else + ..() + +/obj/item/weapon/gun/projectile/automatic/mini_uzi + name = "Uzi" + desc = "A lightweight, fast firing gun, for when you want someone dead. Uses .45 rounds." + icon_state = "mini-uzi" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + w_class = 3.0 + max_shells = 10 + burst_count = 3 + caliber = list(".45" = 1) + origin_tech = "combat=5;materials=2;syndicate=8" + ammo_type = "/obj/item/ammo_casing/c45" + mag_type = "/obj/item/ammo_storage/magazine/uzi45" + +/obj/item/weapon/gun/projectile/automatic/mini_uzi/isHandgun() + return 1 + +/obj/item/weapon/gun/projectile/automatic/c20r + name = "\improper C-20r SMG" + desc = "A lightweight, fast firing gun, for when you REALLY need someone dead. Uses 12mm rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp" + icon_state = "c20r" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns.dmi', "right_hand" = 'icons/mob/in-hand/right/guns.dmi') + item_state = "c20r" + w_class = 3.0 + max_shells = 20 + burst_count = 4 + caliber = list("12mm" = 1) + origin_tech = "combat=5;materials=2;syndicate=8" + ammo_type = "/obj/item/ammo_casing/a12mm" + mag_type = "/obj/item/ammo_storage/magazine/a12mm" + fire_sound = 'sound/weapons/Gunshot_c20.ogg' + load_method = 2 + + gun_flags = AUTOMAGDROP | EMPTYCASINGS + +/obj/item/weapon/gun/projectile/automatic/c20r/update_icon() + ..() + if(stored_magazine) + icon_state = "c20r-[round(getAmmo(),4)]" + else + icon_state = "c20r" + return + +/obj/item/weapon/gun/projectile/automatic/xcom + name = "\improper Assault Rifle" + desc = "A lightweight, fast firing gun, issued to shadow organization members." + icon_state = "xcomassaultrifle" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + origin_tech = "combat=5;materials=2" + w_class = 3.0 + max_shells = 20 + burst_count = 4 + caliber = list("12mm" = 1) + ammo_type = "/obj/item/ammo_casing/a12mm" + mag_type = "/obj/item/ammo_storage/magazine/a12mm" + fire_sound = 'sound/weapons/Gunshot_c20.ogg' + load_method = 2 + + gun_flags = AUTOMAGDROP | EMPTYCASINGS + +/obj/item/weapon/gun/projectile/automatic/l6_saw + name = "\improper L6 SAW" + desc = "A rather traditionally made light machine gun with a pleasantly lacquered wooden pistol grip. Has 'Aussec Armoury- 2531' engraved on the reciever" + icon_state = "l6closed100" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns.dmi', "right_hand" = 'icons/mob/in-hand/right/guns.dmi') + item_state = "l6closedmag" + w_class = 4 + slot_flags = 0 + max_shells = 50 + burst_count = 5 + caliber = list("a762" = 1) + origin_tech = "combat=5;materials=1;syndicate=2" + ammo_type = "/obj/item/ammo_casing/a762" + mag_type = "/obj/item/ammo_storage/magazine/a762" + fire_sound = 'sound/weapons/Gunshot_smg.ogg' + load_method = 2 + var/cover_open = 0 + + +/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob) + cover_open = !cover_open to_chat(user, "You [cover_open ? "open" : "close"] [src]'s cover.") - update_icon() - - -/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon() - icon_state = "l6[cover_open ? "open" : "closed"][stored_magazine ? round(getAmmo(), 25) : "-empty"]" - - -/obj/item/weapon/gun/projectile/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) //what I tried to do here is just add a check to see if the cover is open or not and add an icon_state change because I can't figure out how c-20rs do it with overlays - if(cover_open) + update_icon() + + +/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon() + icon_state = "l6[cover_open ? "open" : "closed"][stored_magazine ? round(getAmmo(), 25) : "-empty"]" + + +/obj/item/weapon/gun/projectile/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) //what I tried to do here is just add a check to see if the cover is open or not and add an icon_state change because I can't figure out how c-20rs do it with overlays + if(cover_open) to_chat(user, "[src]'s cover is open! Close it before firing!") - else - ..() - update_icon() - - -/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user as mob) - if(loc != user) - ..() - return //let them pick it up - if(!cover_open) - ..() - else if(cover_open && stored_magazine) //since attack_self toggles the cover and not the magazine, we use this instead - //drop the mag - RemoveMag(user) + else + ..() + update_icon() + + +/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user as mob) + if(loc != user) + ..() + return //let them pick it up + if(!cover_open) + ..() + else if(cover_open && stored_magazine) //since attack_self toggles the cover and not the magazine, we use this instead + //drop the mag + RemoveMag(user) to_chat(user, "You remove the magazine from [src].") - - -/obj/item/weapon/gun/projectile/automatic/l6_saw/attackby(obj/item/ammo_storage/magazine/a762/A as obj, mob/user as mob) - if(!cover_open) + + +/obj/item/weapon/gun/projectile/automatic/l6_saw/attackby(obj/item/ammo_storage/magazine/a762/A as obj, mob/user as mob) + if(!cover_open) to_chat(user, "[src]'s cover is closed! You can't insert a new mag!") - return - else if(cover_open) - ..() - -/obj/item/weapon/gun/projectile/automatic/l6_saw/force_removeMag() //special because of its cover - if(cover_open && stored_magazine) - RemoveMag(usr) + return + else if(cover_open) + ..() + +/obj/item/weapon/gun/projectile/automatic/l6_saw/force_removeMag() //special because of its cover + if(cover_open && stored_magazine) + RemoveMag(usr) to_chat(usr, "You remove the magazine from [src].") - else if(stored_magazine) + else if(stored_magazine) to_chat(usr, "The [src]'s cover has to be open to do that!") - else + else to_chat(usr, "There is no magazine to remove!") - - -/* The thing I found with guns in ss13 is that they don't seem to simulate the rounds in the magazine in the gun. - Afaik, since projectile.dm features a revolver, this would make sense since the magazine is part of the gun. - However, it looks like subsequent guns that use removable magazines don't take that into account and just get - around simulating a removable magazine by adding the casings into the loaded list and spawning an empty magazine - when the gun is out of rounds. Which means you can't eject magazines with rounds in them. The below is a very - rough and poor attempt at making that happen. -Ausops */ - -/* Guns now properly store and move magazines and bullets about. Moving bullets from loaded to the magazine and back again on actions - still feels poorly coded and hacky, but it's more trouble than this to attempt to modify gun code any further. Perhaps a braver + + +/* The thing I found with guns in ss13 is that they don't seem to simulate the rounds in the magazine in the gun. + Afaik, since projectile.dm features a revolver, this would make sense since the magazine is part of the gun. + However, it looks like subsequent guns that use removable magazines don't take that into account and just get + around simulating a removable magazine by adding the casings into the loaded list and spawning an empty magazine + when the gun is out of rounds. Which means you can't eject magazines with rounds in them. The below is a very + rough and poor attempt at making that happen. -Ausops */ + +/* Guns now properly store and move magazines and bullets about. Moving bullets from loaded to the magazine and back again on actions + still feels poorly coded and hacky, but it's more trouble than this to attempt to modify gun code any further. Perhaps a braver soul than I might feel that some injustice was done in quitting most of the way there, but I think this is modular enough. */ \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index e64818e6aad..7e5d8e8cf3b 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -1,89 +1,89 @@ -/obj/item/weapon/gun/projectile/silenced - name = "silenced pistol" - desc = "A small, quiet, easily concealable gun. Uses .45 rounds." - icon_state = "silenced_pistol" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - w_class = 3.0 - max_shells = 10 - caliber = list(".45" = 1) - silenced = 1 - origin_tech = "combat=2;materials=2;syndicate=8" - ammo_type = "/obj/item/ammo_casing/c45" - mag_type = "/obj/item/ammo_storage/magazine/c45" - load_method = 2 - - -/obj/item/weapon/gun/projectile/deagle - name = "desert eagle" - desc = "A robust handgun that uses .50 AE ammo" - icon_state = "deagle" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - force = 14.0 - max_shells = 7 - caliber = list(".50" = 1) - ammo_type ="/obj/item/ammo_casing/a50" - mag_type = "/obj/item/ammo_storage/magazine/a50" - load_method = 2 - - gun_flags = AUTOMAGDROP | EMPTYCASINGS - -/obj/item/weapon/gun/projectile/deagle/gold - desc = "A gold plated gun folded over a million times by superior martian gunsmiths. Uses .50 AE ammo." - icon_state = "deagleg" - item_state = "deagleg" - - -/obj/item/weapon/gun/projectile/deagle/camo - desc = "A Deagle brand Deagle for operators operating operationally. Uses .50 AE ammo." - icon_state = "deaglecamo" - item_state = "deagleg" - - - -/obj/item/weapon/gun/projectile/gyropistol - name = "gyrojet pistol" - desc = "A bulky pistol designed to fire self propelled rounds" - icon_state = "gyropistol" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - max_shells = 8 - caliber = list("75" = 1) - fire_sound = 'sound/weapons/elecfire.ogg' - origin_tech = "combat=3" - ammo_type = "/obj/item/ammo_casing/a75" - mag_type = "/obj/item/ammo_storage/magazine/a75" - load_method = 2 - - gun_flags = AUTOMAGDROP | EMPTYCASINGS - - update_icon() - ..() - if(stored_magazine) - icon_state = "gyropistolloaded" - else - icon_state = "gyropistol" - return - -/obj/item/weapon/gun/projectile/pistol - name = "\improper Stechtkin pistol" - desc = "A small, easily concealable gun. Uses 9mm rounds." - icon_state = "pistol" - w_class = 2 - max_shells = 8 - caliber = list("9mm" = 1) - silenced = 0 - origin_tech = "combat=2;materials=2;syndicate=2" - ammo_type = "/obj/item/ammo_casing/c9mm" - mag_type = "/obj/item/ammo_storage/magazine/mc9mm" - load_method = 2 - - gun_flags = AUTOMAGDROP | EMPTYCASINGS | SILENCECOMP - -/obj/item/weapon/gun/projectile/pistol/update_icon() - ..() - icon_state = "[initial(icon_state)][silenced ? "-silencer" : ""][chambered ? "" : "-e"]" - return - - +/obj/item/weapon/gun/projectile/silenced + name = "silenced pistol" + desc = "A small, quiet, easily concealable gun. Uses .45 rounds." + icon_state = "silenced_pistol" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + w_class = 3.0 + max_shells = 10 + caliber = list(".45" = 1) + silenced = 1 + origin_tech = "combat=2;materials=2;syndicate=8" + ammo_type = "/obj/item/ammo_casing/c45" + mag_type = "/obj/item/ammo_storage/magazine/c45" + load_method = 2 + + +/obj/item/weapon/gun/projectile/deagle + name = "desert eagle" + desc = "A robust handgun that uses .50 AE ammo" + icon_state = "deagle" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + force = 14.0 + max_shells = 7 + caliber = list(".50" = 1) + ammo_type ="/obj/item/ammo_casing/a50" + mag_type = "/obj/item/ammo_storage/magazine/a50" + load_method = 2 + + gun_flags = AUTOMAGDROP | EMPTYCASINGS + +/obj/item/weapon/gun/projectile/deagle/gold + desc = "A gold plated gun folded over a million times by superior martian gunsmiths. Uses .50 AE ammo." + icon_state = "deagleg" + item_state = "deagleg" + + +/obj/item/weapon/gun/projectile/deagle/camo + desc = "A Deagle brand Deagle for operators operating operationally. Uses .50 AE ammo." + icon_state = "deaglecamo" + item_state = "deagleg" + + + +/obj/item/weapon/gun/projectile/gyropistol + name = "gyrojet pistol" + desc = "A bulky pistol designed to fire self propelled rounds" + icon_state = "gyropistol" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + max_shells = 8 + caliber = list("75" = 1) + fire_sound = 'sound/weapons/elecfire.ogg' + origin_tech = "combat=3" + ammo_type = "/obj/item/ammo_casing/a75" + mag_type = "/obj/item/ammo_storage/magazine/a75" + load_method = 2 + + gun_flags = AUTOMAGDROP | EMPTYCASINGS + + update_icon() + ..() + if(stored_magazine) + icon_state = "gyropistolloaded" + else + icon_state = "gyropistol" + return + +/obj/item/weapon/gun/projectile/pistol + name = "\improper Stechtkin pistol" + desc = "A small, easily concealable gun. Uses 9mm rounds." + icon_state = "pistol" + w_class = 2 + max_shells = 8 + caliber = list("9mm" = 1) + silenced = 0 + origin_tech = "combat=2;materials=2;syndicate=2" + ammo_type = "/obj/item/ammo_casing/c9mm" + mag_type = "/obj/item/ammo_storage/magazine/mc9mm" + load_method = 2 + + gun_flags = AUTOMAGDROP | EMPTYCASINGS | SILENCECOMP + +/obj/item/weapon/gun/projectile/pistol/update_icon() + ..() + icon_state = "[initial(icon_state)][silenced ? "-silencer" : ""][chambered ? "" : "-e"]" + return + + diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 22dbf7284c1..a2209754197 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -1,181 +1,181 @@ -/obj/item/weapon/gun/projectile/detective - desc = "A cheap Martian knock-off of a Smith & Wesson Model 10. Uses .38-Special rounds." - name = "revolver" - icon_state = "detective" - max_shells = 6 - caliber = list("38" = 1, "357" = 1) - origin_tech = "combat=2;materials=2" - ammo_type = "/obj/item/ammo_casing/c38" - var/perfect = 0 - - special_check(var/mob/living/carbon/human/M) //to see if the gun fires 357 rounds safely. A non-modified revolver randomly blows up - if(getAmmo()) //this is a good check, I like this check - var/obj/item/ammo_casing/AC = loaded[1] - if(caliber["38"] == 0) //if it's been modified, this is true - return 1 - if(istype(AC, /obj/item/ammo_casing/a357) && !perfect && prob(70 - (getAmmo() * 10))) //minimum probability of 10, maximum of 60 - to_chat(M, "[src] blows up in your face.") - M.take_organ_damage(0,20) - M.drop_item(src, force_drop = 1) - qdel(src) - return 0 - return 1 - - verb/rename_gun() - set name = "Name Gun" - set category = "Object" - set desc = "Click to rename your gun. If you're the detective." - - var/mob/M = usr - if(!M.mind) return 0 - if(!M.mind.assigned_role == "Detective") - to_chat(M, "You don't feel cool enough to name this gun, chump.") - return 0 - - var/input = stripped_input(usr,"What do you want to name the gun?", ,"", MAX_NAME_LEN) - - if(src && input && !M.stat && in_range(src,M)) - name = input - to_chat(M, "You name the gun [input]. Say hello to your new friend.") - return 1 - - attackby(var/obj/item/A as obj, mob/user as mob) - ..() - if(isscrewdriver(A) || istype(A, /obj/item/weapon/conversion_kit)) - var/obj/item/weapon/conversion_kit/CK - if(istype(A, /obj/item/weapon/conversion_kit)) - CK = A - if(!CK.open) - to_chat(user, "This [CK.name] is useless unless you open it first. ") - return - if(caliber["38"]) - to_chat(user, "You begin to reinforce the barrel of [src].") - if(getAmmo()) - afterattack(user, user) //you know the drill - playsound(user, fire_sound, 50, 1) - user.visible_message("[src] goes off!", "[src] goes off in your face!") - return - if(do_after(user, src, 30)) - if(getAmmo()) - to_chat(user, "You can't modify it!") - return - caliber["38"] = 0 - desc = "The barrel and chamber assembly seems to have been modified." - to_chat(user, "You reinforce the barrel of [src]! Now it will fire .357 rounds.") - if(CK && istype(CK)) - perfect = 1 - else - to_chat(user, "You begin to revert the modifications to [src].") - if(getAmmo()) - afterattack(user, user) //and again - playsound(user, fire_sound, 50, 1) - user.visible_message("[src] goes off!", "[src] goes off in your face!") - return - if(do_after(user, src, 30)) - if(getAmmo()) - to_chat(user, "You can't modify it!") - return - caliber["38"] = 1 - desc = initial(desc) - to_chat(user, "You remove the modifications on [src]! Now it will fire .38 rounds.") - perfect = 0 - - - - -/obj/item/weapon/gun/projectile/mateba - name = "mateba" - desc = "When you absolutely, positively need a 10mm hole in the other guy. Uses .357 ammo." //>10mm hole >.357 - icon_state = "mateba" - origin_tech = "combat=2;materials=2" - -// A gun to play Russian Roulette! -// You can spin the chamber to randomize the position of the bullet. - -/obj/item/weapon/gun/projectile/russian - name = "Russian Revolver" - desc = "A Russian made revolver. Uses .357 ammo. It has a single slot in it's chamber for a bullet." - max_shells = 6 - origin_tech = "combat=2;materials=2" - -/obj/item/weapon/gun/projectile/russian/New() - ..() - Spin() - update_icon() - -/obj/item/weapon/gun/projectile/russian/proc/Spin() - - - for(var/obj/item/ammo_casing/AC in loaded) - qdel(AC) - AC = null - loaded = list() - var/random = rand(1, max_shells) - for(var/i = 1; i <= max_shells; i++) - if(i != random) - loaded += i // Basically null - else - loaded += new ammo_type(src) - - -/obj/item/weapon/gun/projectile/russian/attackby(var/obj/item/A as obj, mob/user as mob) - - if(!A) return - - var/num_loaded = 0 - if(istype(A, /obj/item/ammo_storage/magazine)) - - if((load_method == 2) && getAmmo()) return - var/obj/item/ammo_storage/magazine/AM = A - for(var/obj/item/ammo_casing/AC in AM.stored_ammo) - if(getAmmo() > 0 || getAmmo() >= max_shells) - break - if(caliber[AC.caliber] && getAmmo() < max_shells) - AC.loc = src - AM.stored_ammo -= AC - loaded += AC - num_loaded++ - break - A.update_icon() - - if(num_loaded) - user.visible_message("[user] loads a single bullet into the revolver and spins the chamber.", "You load a single bullet into the chamber and spin it.") - else - user.visible_message("[user] spins the chamber of the revolver.", "You spin the revolver's chamber.") - if(getAmmo() > 0) - Spin() - update_icon() - return - -/obj/item/weapon/gun/projectile/russian/attack_self(mob/user as mob) - - user.visible_message("[user] spins the chamber of the revolver.", "You spin the revolver's chamber.") - if(getAmmo() > 0) - Spin() - -/obj/item/weapon/gun/projectile/russian/attack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj) - - if(!getAmmo()) - user.visible_message("*click*", "*click*") - playsound(user, 'sound/weapons/empty.ogg', 100, 1) - return - - if(isliving(target) && isliving(user)) - if(target == user) - var/datum/organ/external/affecting = user.zone_sel.selecting - if(affecting == "head") - - var/obj/item/ammo_casing/AC = loaded[1] - if(!process_chambered()) - user.visible_message("*click*", "*click*") - playsound(user, 'sound/weapons/empty.ogg', 100, 1) - return - if(!in_chamber) - return - var/obj/item/projectile/P = new AC.projectile_type - playsound(user, fire_sound, 50, 1) - user.visible_message("[user.name] fires [src] at \his head!", "You fire [src] at your head!", "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") - if(!P.nodamage) - user.apply_damage(300, BRUTE, affecting) // You are dead, dead, dead. - return - ..() +/obj/item/weapon/gun/projectile/detective + desc = "A cheap Martian knock-off of a Smith & Wesson Model 10. Uses .38-Special rounds." + name = "revolver" + icon_state = "detective" + max_shells = 6 + caliber = list("38" = 1, "357" = 1) + origin_tech = "combat=2;materials=2" + ammo_type = "/obj/item/ammo_casing/c38" + var/perfect = 0 + + special_check(var/mob/living/carbon/human/M) //to see if the gun fires 357 rounds safely. A non-modified revolver randomly blows up + if(getAmmo()) //this is a good check, I like this check + var/obj/item/ammo_casing/AC = loaded[1] + if(caliber["38"] == 0) //if it's been modified, this is true + return 1 + if(istype(AC, /obj/item/ammo_casing/a357) && !perfect && prob(70 - (getAmmo() * 10))) //minimum probability of 10, maximum of 60 + to_chat(M, "[src] blows up in your face.") + M.take_organ_damage(0,20) + M.drop_item(src, force_drop = 1) + qdel(src) + return 0 + return 1 + + verb/rename_gun() + set name = "Name Gun" + set category = "Object" + set desc = "Click to rename your gun. If you're the detective." + + var/mob/M = usr + if(!M.mind) return 0 + if(!M.mind.assigned_role == "Detective") + to_chat(M, "You don't feel cool enough to name this gun, chump.") + return 0 + + var/input = stripped_input(usr,"What do you want to name the gun?", ,"", MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(src,M)) + name = input + to_chat(M, "You name the gun [input]. Say hello to your new friend.") + return 1 + + attackby(var/obj/item/A as obj, mob/user as mob) + ..() + if(isscrewdriver(A) || istype(A, /obj/item/weapon/conversion_kit)) + var/obj/item/weapon/conversion_kit/CK + if(istype(A, /obj/item/weapon/conversion_kit)) + CK = A + if(!CK.open) + to_chat(user, "This [CK.name] is useless unless you open it first. ") + return + if(caliber["38"]) + to_chat(user, "You begin to reinforce the barrel of [src].") + if(getAmmo()) + afterattack(user, user) //you know the drill + playsound(user, fire_sound, 50, 1) + user.visible_message("[src] goes off!", "[src] goes off in your face!") + return + if(do_after(user, src, 30)) + if(getAmmo()) + to_chat(user, "You can't modify it!") + return + caliber["38"] = 0 + desc = "The barrel and chamber assembly seems to have been modified." + to_chat(user, "You reinforce the barrel of [src]! Now it will fire .357 rounds.") + if(CK && istype(CK)) + perfect = 1 + else + to_chat(user, "You begin to revert the modifications to [src].") + if(getAmmo()) + afterattack(user, user) //and again + playsound(user, fire_sound, 50, 1) + user.visible_message("[src] goes off!", "[src] goes off in your face!") + return + if(do_after(user, src, 30)) + if(getAmmo()) + to_chat(user, "You can't modify it!") + return + caliber["38"] = 1 + desc = initial(desc) + to_chat(user, "You remove the modifications on [src]! Now it will fire .38 rounds.") + perfect = 0 + + + + +/obj/item/weapon/gun/projectile/mateba + name = "mateba" + desc = "When you absolutely, positively need a 10mm hole in the other guy. Uses .357 ammo." //>10mm hole >.357 + icon_state = "mateba" + origin_tech = "combat=2;materials=2" + +// A gun to play Russian Roulette! +// You can spin the chamber to randomize the position of the bullet. + +/obj/item/weapon/gun/projectile/russian + name = "Russian Revolver" + desc = "A Russian made revolver. Uses .357 ammo. It has a single slot in it's chamber for a bullet." + max_shells = 6 + origin_tech = "combat=2;materials=2" + +/obj/item/weapon/gun/projectile/russian/New() + ..() + Spin() + update_icon() + +/obj/item/weapon/gun/projectile/russian/proc/Spin() + + + for(var/obj/item/ammo_casing/AC in loaded) + qdel(AC) + AC = null + loaded = list() + var/random = rand(1, max_shells) + for(var/i = 1; i <= max_shells; i++) + if(i != random) + loaded += i // Basically null + else + loaded += new ammo_type(src) + + +/obj/item/weapon/gun/projectile/russian/attackby(var/obj/item/A as obj, mob/user as mob) + + if(!A) return + + var/num_loaded = 0 + if(istype(A, /obj/item/ammo_storage/magazine)) + + if((load_method == 2) && getAmmo()) return + var/obj/item/ammo_storage/magazine/AM = A + for(var/obj/item/ammo_casing/AC in AM.stored_ammo) + if(getAmmo() > 0 || getAmmo() >= max_shells) + break + if(caliber[AC.caliber] && getAmmo() < max_shells) + AC.loc = src + AM.stored_ammo -= AC + loaded += AC + num_loaded++ + break + A.update_icon() + + if(num_loaded) + user.visible_message("[user] loads a single bullet into the revolver and spins the chamber.", "You load a single bullet into the chamber and spin it.") + else + user.visible_message("[user] spins the chamber of the revolver.", "You spin the revolver's chamber.") + if(getAmmo() > 0) + Spin() + update_icon() + return + +/obj/item/weapon/gun/projectile/russian/attack_self(mob/user as mob) + + user.visible_message("[user] spins the chamber of the revolver.", "You spin the revolver's chamber.") + if(getAmmo() > 0) + Spin() + +/obj/item/weapon/gun/projectile/russian/attack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj) + + if(!getAmmo()) + user.visible_message("*click*", "*click*") + playsound(user, 'sound/weapons/empty.ogg', 100, 1) + return + + if(isliving(target) && isliving(user)) + if(target == user) + var/datum/organ/external/affecting = user.zone_sel.selecting + if(affecting == "head") + + var/obj/item/ammo_casing/AC = loaded[1] + if(!process_chambered()) + user.visible_message("*click*", "*click*") + playsound(user, 'sound/weapons/empty.ogg', 100, 1) + return + if(!in_chamber) + return + var/obj/item/projectile/P = new AC.projectile_type + playsound(user, fire_sound, 50, 1) + user.visible_message("[user.name] fires [src] at \his head!", "You fire [src] at your head!", "You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") + if(!P.nodamage) + user.apply_damage(300, BRUTE, affecting) // You are dead, dead, dead. + return + ..() diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 28aa1055dc7..81f749a6bd4 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -1,136 +1,136 @@ -/obj/item/weapon/gun/projectile/shotgun/pump - name = "shotgun" - desc = "Useful for sweeping alleys." - fire_sound = 'sound/weapons/shotgun.ogg' - icon_state = "shotgun" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - max_shells = 4 - w_class = 4.0 - force = 10 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - caliber = list("shotgun" = 1, "flare" = 1) //flare shells are still shells - origin_tech = "combat=4;materials=2" - ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" - var/recentpump = 0 // to prevent spammage - var/pumped = 0 - var/obj/item/ammo_casing/current_shell = null - - - gun_flags = 0 - -/obj/item/weapon/gun/projectile/shotgun/pump/isHandgun() - return 0 - -/obj/item/weapon/gun/projectile/shotgun/pump/attack_self(mob/living/user as mob) - if(recentpump) return - pump(user) - recentpump = 1 - spawn(10) - recentpump = 0 - return - -/obj/item/weapon/gun/projectile/shotgun/pump/process_chambered() - if(in_chamber) - return 1 - else if(current_shell && current_shell.BB) - in_chamber = current_shell.BB //Load projectile into chamber. - current_shell.BB.loc = src //Set projectile loc to gun. - current_shell.BB = null - current_shell.update_icon() - return 1 - return 0 - -/obj/item/weapon/gun/projectile/shotgun/pump/proc/pump(mob/M as mob) - playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1) - pumped = 0 - if(current_shell)//We have a shell in the chamber - current_shell.loc = get_turf(src)//Eject casing - current_shell = null - if(in_chamber) - in_chamber = null - if(!getAmmo()) - return 0 - var/obj/item/ammo_casing/AC = loaded[1] //load next casing. - loaded -= AC //Remove casing from loaded list. - current_shell = AC - update_icon() //I.E. fix the desc - return 1 - -/obj/item/weapon/gun/projectile/shotgun/pump/combat - name = "combat shotgun" - icon_state = "cshotgun" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - max_shells = 8 - origin_tech = "combat=5;materials=2" - ammo_type = "/obj/item/ammo_casing/shotgun" - -//this is largely hacky and bad :( -Pete -/obj/item/weapon/gun/projectile/shotgun/doublebarrel - name = "double-barreled shotgun" - desc = "A true classic." - icon_state = "dshotgun" - item_state = "shotgun" - max_shells = 2 - w_class = 4.0 - force = 10 - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BACK - caliber = list("shotgun" = 1, "flare" = 1) - origin_tech = "combat=3;materials=1" - ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" - -/obj/item/weapon/gun/projectile/shotgun/doublebarrel/process_chambered() - if(in_chamber) - return 1 - if(!getAmmo()) - return 0 - var/obj/item/ammo_casing/AC = loaded[1] //load next casing. - loaded -= AC //Remove casing from loaded list. - loaded += AC //Put it in at the end - because it hasn't been ejected yet - if(AC.BB) - in_chamber = AC.BB //Load projectile into chamber. - AC.BB.loc = src //Set projectile loc to gun. - AC.BB = null - AC.update_icon() - return 1 - return 0 - -/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attack_self(mob/living/user as mob) - if(!(locate(/obj/item/ammo_casing/shotgun) in src) && !getAmmo()) +/obj/item/weapon/gun/projectile/shotgun/pump + name = "shotgun" + desc = "Useful for sweeping alleys." + fire_sound = 'sound/weapons/shotgun.ogg' + icon_state = "shotgun" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + max_shells = 4 + w_class = 4.0 + force = 10 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + caliber = list("shotgun" = 1, "flare" = 1) //flare shells are still shells + origin_tech = "combat=4;materials=2" + ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" + var/recentpump = 0 // to prevent spammage + var/pumped = 0 + var/obj/item/ammo_casing/current_shell = null + + + gun_flags = 0 + +/obj/item/weapon/gun/projectile/shotgun/pump/isHandgun() + return 0 + +/obj/item/weapon/gun/projectile/shotgun/pump/attack_self(mob/living/user as mob) + if(recentpump) return + pump(user) + recentpump = 1 + spawn(10) + recentpump = 0 + return + +/obj/item/weapon/gun/projectile/shotgun/pump/process_chambered() + if(in_chamber) + return 1 + else if(current_shell && current_shell.BB) + in_chamber = current_shell.BB //Load projectile into chamber. + current_shell.BB.loc = src //Set projectile loc to gun. + current_shell.BB = null + current_shell.update_icon() + return 1 + return 0 + +/obj/item/weapon/gun/projectile/shotgun/pump/proc/pump(mob/M as mob) + playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1) + pumped = 0 + if(current_shell)//We have a shell in the chamber + current_shell.loc = get_turf(src)//Eject casing + current_shell = null + if(in_chamber) + in_chamber = null + if(!getAmmo()) + return 0 + var/obj/item/ammo_casing/AC = loaded[1] //load next casing. + loaded -= AC //Remove casing from loaded list. + current_shell = AC + update_icon() //I.E. fix the desc + return 1 + +/obj/item/weapon/gun/projectile/shotgun/pump/combat + name = "combat shotgun" + icon_state = "cshotgun" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + max_shells = 8 + origin_tech = "combat=5;materials=2" + ammo_type = "/obj/item/ammo_casing/shotgun" + +//this is largely hacky and bad :( -Pete +/obj/item/weapon/gun/projectile/shotgun/doublebarrel + name = "double-barreled shotgun" + desc = "A true classic." + icon_state = "dshotgun" + item_state = "shotgun" + max_shells = 2 + w_class = 4.0 + force = 10 + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BACK + caliber = list("shotgun" = 1, "flare" = 1) + origin_tech = "combat=3;materials=1" + ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" + +/obj/item/weapon/gun/projectile/shotgun/doublebarrel/process_chambered() + if(in_chamber) + return 1 + if(!getAmmo()) + return 0 + var/obj/item/ammo_casing/AC = loaded[1] //load next casing. + loaded -= AC //Remove casing from loaded list. + loaded += AC //Put it in at the end - because it hasn't been ejected yet + if(AC.BB) + in_chamber = AC.BB //Load projectile into chamber. + AC.BB.loc = src //Set projectile loc to gun. + AC.BB = null + AC.update_icon() + return 1 + return 0 + +/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attack_self(mob/living/user as mob) + if(!(locate(/obj/item/ammo_casing/shotgun) in src) && !getAmmo()) to_chat(user, "\The [src] is empty.") - return - - for(var/obj/item/ammo_casing/shotgun/shell in src) //This feels like a hack. //don't code at 3:30am kids!! - if(shell in loaded) - loaded -= shell - shell.loc = get_turf(src.loc) - + return + + for(var/obj/item/ammo_casing/shotgun/shell in src) //This feels like a hack. //don't code at 3:30am kids!! + if(shell in loaded) + loaded -= shell + shell.loc = get_turf(src.loc) + to_chat(user, "You break \the [src].") - update_icon() - -/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attackby(var/obj/item/A as obj, mob/user as mob) - ..() - A.update_icon() - update_icon() - if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter)) + update_icon() + +/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attackby(var/obj/item/A as obj, mob/user as mob) + ..() + A.update_icon() + update_icon() + if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter)) to_chat(user, "You begin to shorten the barrel of \the [src].") - if(getAmmo()) - afterattack(user, user) //will this work? - afterattack(user, user) //it will. we call it twice, for twice the FUN - playsound(user, fire_sound, 50, 1) - user.visible_message("The shotgun goes off!", "The shotgun goes off in your face!") - return - if(do_after(user, src, 30)) //SHIT IS STEALTHY EYYYYY - icon_state = "sawnshotgun" - w_class = 3.0 - item_state = "gun" - slot_flags &= ~SLOT_BACK //you can't sling it on your back - slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) - name = "sawn-off shotgun" - desc = "Omar's coming!" + if(getAmmo()) + afterattack(user, user) //will this work? + afterattack(user, user) //it will. we call it twice, for twice the FUN + playsound(user, fire_sound, 50, 1) + user.visible_message("The shotgun goes off!", "The shotgun goes off in your face!") + return + if(do_after(user, src, 30)) //SHIT IS STEALTHY EYYYYY + icon_state = "sawnshotgun" + w_class = 3.0 + item_state = "gun" + slot_flags &= ~SLOT_BACK //you can't sling it on your back + slot_flags |= SLOT_BELT //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) + name = "sawn-off shotgun" + desc = "Omar's coming!" to_chat(user, "You shorten the barrel of \the [src]!") diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 9fe58f07ac2..819728fa37f 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1,607 +1,607 @@ -/* -#define BRUTE "brute" -#define BURN "burn" -#define TOX "tox" -#define OXY "oxy" -#define CLONE "clone" - -#define ADD "add" -#define SET "set" -*/ -var/list/bullet_master = list() -var/list/impact_master = list() - -/obj/item/projectile - name = "projectile" - icon = 'icons/obj/projectiles.dmi' - icon_state = "bullet" - density = 1 - unacidable = 1 - anchored = 1 //There's a reason this is here, Mport. God fucking damn it -Agouri. Find&Fix by Pete. The reason this is here is to stop the curving of emitter shots. - flags = FPRINT - pass_flags = PASSTABLE - mouse_opacity = 0 - var/bumped = 0 //Prevents it from hitting more than one guy at once - var/def_zone = "" //Aiming at - var/mob/firer = null//Who shot it - var/silenced = 0 //Attack message - var/yo = null - var/xo = null - var/turf/current = null - var/obj/shot_from = null // the object which shot us - var/atom/original = null // the original target clicked - var/turf/starting = null // the projectile's starting turf - var/list/permutated = list() // we've passed through these atoms, don't try to hit them again - - var/p_x = 16 - var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center - - var/damage = 10 - var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here - var/nodamage = 0 //Determines if the projectile will skip any damage inflictions - var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid - var/projectile_type = "/obj/item/projectile" - var/kill_count = 50 //This will de-increment every process(). When 0, it will delete the projectile. - var/total_steps = 0 - //Effects - var/stun = 0 - var/weaken = 0 - var/paralyze = 0 - var/irradiate = 0 - var/stutter = 0 - var/eyeblur = 0 - var/drowsy = 0 - var/agony = 0 - var/jittery = 0 - - var/destroy = 0 //if set to 1, will destroy wall, tables and racks on impact (or at least, has a chance to) - - var/reflected = 0 - - var/bounce_sound = 'sound/items/metal_impact.ogg' - var/bounce_type = null//BOUNCEOFF_WALLS, BOUNCEOFF_WINDOWS, BOUNCEOFF_OBJS, BOUNCEOFF_MOBS - var/bounces = 0 //if set to -1, will always bounce off obstacles - - var/phase_type = null//PHASEHTROUGH_WALLS, PHASEHTROUGH_WINDOWS, PHASEHTROUGH_OBJS, PHASEHTROUGH_MOBS - var/penetration = 0 //if set to -1, will always phase through obstacles - var/mark_type = "trace" //what marks will the bullet leave on a wall that it penetrates? from 'icons/effects/96x96.dmi' - - var/step_delay = 0 //how long it goes between moving. You should probably leave this as 0 for a lot of things - - var/inaccurate = 0 - - var/turf/target = null - var/dist_x = 0 - var/dist_y = 0 - var/dx = 0 - var/dy = 0 - var/error = 0 - var/target_angle = 0 - - var/override_starting_X = 0 - var/override_starting_Y = 0 - var/override_target_X = 0 - var/override_target_Y = 0 - var/last_bump = null - - var/custom_impact = 0 - - //update_pixel stuff - var/PixelX = 0 - var/PixelY = 0 - - animate_movement = 0 - var/linear_movement = 1 - -/obj/item/projectile/proc/on_hit(var/atom/atarget, var/blocked = 0) - if(blocked >= 2) return 0//Full block - if(!isliving(atarget)) return 0 - // FUCK mice. - N3X - if(ismouse(atarget) && (stun+weaken+paralyze+agony)>5) - var/mob/living/simple_animal/mouse/M=atarget +/* +#define BRUTE "brute" +#define BURN "burn" +#define TOX "tox" +#define OXY "oxy" +#define CLONE "clone" + +#define ADD "add" +#define SET "set" +*/ +var/list/bullet_master = list() +var/list/impact_master = list() + +/obj/item/projectile + name = "projectile" + icon = 'icons/obj/projectiles.dmi' + icon_state = "bullet" + density = 1 + unacidable = 1 + anchored = 1 //There's a reason this is here, Mport. God fucking damn it -Agouri. Find&Fix by Pete. The reason this is here is to stop the curving of emitter shots. + flags = FPRINT + pass_flags = PASSTABLE + mouse_opacity = 0 + var/bumped = 0 //Prevents it from hitting more than one guy at once + var/def_zone = "" //Aiming at + var/mob/firer = null//Who shot it + var/silenced = 0 //Attack message + var/yo = null + var/xo = null + var/turf/current = null + var/obj/shot_from = null // the object which shot us + var/atom/original = null // the original target clicked + var/turf/starting = null // the projectile's starting turf + var/list/permutated = list() // we've passed through these atoms, don't try to hit them again + + var/p_x = 16 + var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center + + var/damage = 10 + var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here + var/nodamage = 0 //Determines if the projectile will skip any damage inflictions + var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid + var/projectile_type = "/obj/item/projectile" + var/kill_count = 50 //This will de-increment every process(). When 0, it will delete the projectile. + var/total_steps = 0 + //Effects + var/stun = 0 + var/weaken = 0 + var/paralyze = 0 + var/irradiate = 0 + var/stutter = 0 + var/eyeblur = 0 + var/drowsy = 0 + var/agony = 0 + var/jittery = 0 + + var/destroy = 0 //if set to 1, will destroy wall, tables and racks on impact (or at least, has a chance to) + + var/reflected = 0 + + var/bounce_sound = 'sound/items/metal_impact.ogg' + var/bounce_type = null//BOUNCEOFF_WALLS, BOUNCEOFF_WINDOWS, BOUNCEOFF_OBJS, BOUNCEOFF_MOBS + var/bounces = 0 //if set to -1, will always bounce off obstacles + + var/phase_type = null//PHASEHTROUGH_WALLS, PHASEHTROUGH_WINDOWS, PHASEHTROUGH_OBJS, PHASEHTROUGH_MOBS + var/penetration = 0 //if set to -1, will always phase through obstacles + var/mark_type = "trace" //what marks will the bullet leave on a wall that it penetrates? from 'icons/effects/96x96.dmi' + + var/step_delay = 0 //how long it goes between moving. You should probably leave this as 0 for a lot of things + + var/inaccurate = 0 + + var/turf/target = null + var/dist_x = 0 + var/dist_y = 0 + var/dx = 0 + var/dy = 0 + var/error = 0 + var/target_angle = 0 + + var/override_starting_X = 0 + var/override_starting_Y = 0 + var/override_target_X = 0 + var/override_target_Y = 0 + var/last_bump = null + + var/custom_impact = 0 + + //update_pixel stuff + var/PixelX = 0 + var/PixelY = 0 + + animate_movement = 0 + var/linear_movement = 1 + +/obj/item/projectile/proc/on_hit(var/atom/atarget, var/blocked = 0) + if(blocked >= 2) return 0//Full block + if(!isliving(atarget)) return 0 + // FUCK mice. - N3X + if(ismouse(atarget) && (stun+weaken+paralyze+agony)>5) + var/mob/living/simple_animal/mouse/M=atarget to_chat(M, "What would probably not kill a human completely overwhelms your tiny body.") - M.splat() - return 1 - if(isanimal(atarget)) return 0 - var/mob/living/L = atarget - if(L.flags & INVULNERABLE) return 0 - L.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, agony, blocked) // add in AGONY! - if(jittery) - L.Jitter(jittery) - return 1 - -/obj/item/projectile/proc/check_fire(var/mob/living/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not. - if(!istype(target) || !istype(user)) - return 0 - var/obj/item/projectile/test/in_chamber = getFromPool(/obj/item/projectile/test, get_step_to(user, target)) //Making the test.... - in_chamber.target = target - in_chamber.ttarget = target //what the fuck - in_chamber.flags = flags //Set the flags... - in_chamber.pass_flags = pass_flags //And the pass flags to that of the real projectile... - in_chamber.firer = user - var/output = in_chamber.process() //Test it! - //del(in_chamber) //No need for it anymore - returnToPool(in_chamber) - return output //Send it back to the gun! - -/obj/item/projectile/resetVariables() - if(!istype(permutated,/list)) - permutated = list() - else - permutated.len = 0 - ..("permutated") - -/obj/item/projectile/proc/admin_warn(mob/living/M) - if(istype(firer, /mob)) - if(firer == M) - log_attack("[key_name(firer)] shot himself with a [type].") - M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot himself with a [type]" - firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot himself with a [type]" - msg_admin_attack("[key_name(firer)] shot himself with a [type], [pick("top kek!","for shame.","he definitely meant to do that","probably not the last time either.")] (JMP)") - if(!iscarbon(firer)) - M.LAssailant = null - else - M.LAssailant = firer - else - log_attack("[key_name(firer)] shot [key_name(M)] with a [type]") - M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" - firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" - msg_admin_attack("[key_name(firer)] shot [key_name(M)] with a [type] (JMP)") - if(!iscarbon(firer)) - M.LAssailant = null - else - M.LAssailant = firer - else - M.attack_log += "\[[time_stamp()]\] UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]" - msg_admin_attack("UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]. Wait what the fuck?") - log_attack("UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]") - -/obj/item/projectile/Bump(atom/A as mob|obj|turf|area) - if (!A) //This was runtiming if by chance A was null. - return 0 - if((A == firer) && !reflected) - loc = A.loc - return 0 //cannot shoot yourself, unless an ablative armor sent back the projectile - - if(bumped) return 0 - var/forcedodge = 0 // force the projectile to pass - - bumped = 1 - if(firer && istype(A, /mob)) - var/mob/M = A - if(!istype(A, /mob/living)) - loc = A.loc - return 0// nope.avi - - //Lower accurancy/longer range tradeoff. Distance matters a lot here, so at - // close distance, actually RAISE the chance to hit. - var/distance = get_dist(starting,loc) - var/miss_modifier = -30 - if (istype(shot_from,/obj/item/weapon/gun)) //If you aim at someone beforehead, it'll hit more often. - var/obj/item/weapon/gun/daddy = shot_from //Kinda balanced by fact you need like 2 seconds to aim - if (daddy.target && original in daddy.target) //As opposed to no-delay pew pew - miss_modifier += -30 - if(istype(src, /obj/item/projectile/beam/lightning)) //Lightning is quite accurate - miss_modifier += -200 - if(inaccurate) - miss_modifier += (abs(miss_modifier)) - def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier) - var/turf/simulated/floor/f = get_turf(A.loc) - if(f && istype(f)) - f.break_tile() - f.hotspot_expose(1000,CELL_VOLUME,surfaces=1) - else - if(inaccurate) - miss_modifier += 8*distance - miss_modifier += (abs(miss_modifier)) - - def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier) - - if(!def_zone) - visible_message("\The [src] misses [M] narrowly!") - forcedodge = -1 - else - if(silenced) + M.splat() + return 1 + if(isanimal(atarget)) return 0 + var/mob/living/L = atarget + if(L.flags & INVULNERABLE) return 0 + L.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, agony, blocked) // add in AGONY! + if(jittery) + L.Jitter(jittery) + return 1 + +/obj/item/projectile/proc/check_fire(var/mob/living/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not. + if(!istype(target) || !istype(user)) + return 0 + var/obj/item/projectile/test/in_chamber = getFromPool(/obj/item/projectile/test, get_step_to(user, target)) //Making the test.... + in_chamber.target = target + in_chamber.ttarget = target //what the fuck + in_chamber.flags = flags //Set the flags... + in_chamber.pass_flags = pass_flags //And the pass flags to that of the real projectile... + in_chamber.firer = user + var/output = in_chamber.process() //Test it! + //del(in_chamber) //No need for it anymore + returnToPool(in_chamber) + return output //Send it back to the gun! + +/obj/item/projectile/resetVariables() + if(!istype(permutated,/list)) + permutated = list() + else + permutated.len = 0 + ..("permutated") + +/obj/item/projectile/proc/admin_warn(mob/living/M) + if(istype(firer, /mob)) + if(firer == M) + log_attack("[key_name(firer)] shot himself with a [type].") + M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot himself with a [type]" + firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot himself with a [type]" + msg_admin_attack("[key_name(firer)] shot himself with a [type], [pick("top kek!","for shame.","he definitely meant to do that","probably not the last time either.")] (JMP)") + if(!iscarbon(firer)) + M.LAssailant = null + else + M.LAssailant = firer + else + log_attack("[key_name(firer)] shot [key_name(M)] with a [type]") + M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" + firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" + msg_admin_attack("[key_name(firer)] shot [key_name(M)] with a [type] (JMP)") + if(!iscarbon(firer)) + M.LAssailant = null + else + M.LAssailant = firer + else + M.attack_log += "\[[time_stamp()]\] UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]" + msg_admin_attack("UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]. Wait what the fuck?") + log_attack("UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]") + +/obj/item/projectile/Bump(atom/A as mob|obj|turf|area) + if (!A) //This was runtiming if by chance A was null. + return 0 + if((A == firer) && !reflected) + loc = A.loc + return 0 //cannot shoot yourself, unless an ablative armor sent back the projectile + + if(bumped) return 0 + var/forcedodge = 0 // force the projectile to pass + + bumped = 1 + if(firer && istype(A, /mob)) + var/mob/M = A + if(!istype(A, /mob/living)) + loc = A.loc + return 0// nope.avi + + //Lower accurancy/longer range tradeoff. Distance matters a lot here, so at + // close distance, actually RAISE the chance to hit. + var/distance = get_dist(starting,loc) + var/miss_modifier = -30 + if (istype(shot_from,/obj/item/weapon/gun)) //If you aim at someone beforehead, it'll hit more often. + var/obj/item/weapon/gun/daddy = shot_from //Kinda balanced by fact you need like 2 seconds to aim + if (daddy.target && original in daddy.target) //As opposed to no-delay pew pew + miss_modifier += -30 + if(istype(src, /obj/item/projectile/beam/lightning)) //Lightning is quite accurate + miss_modifier += -200 + if(inaccurate) + miss_modifier += (abs(miss_modifier)) + def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier) + var/turf/simulated/floor/f = get_turf(A.loc) + if(f && istype(f)) + f.break_tile() + f.hotspot_expose(1000,CELL_VOLUME,surfaces=1) + else + if(inaccurate) + miss_modifier += 8*distance + miss_modifier += (abs(miss_modifier)) + + def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier) + + if(!def_zone) + visible_message("\The [src] misses [M] narrowly!") + forcedodge = -1 + else + if(silenced) to_chat(M, "You've been shot in the [parse_zone(def_zone)] by the [src.name]!") - else - visible_message("[A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter - admin_warn(M) - if(istype(firer, /mob)) - if(!iscarbon(firer)) - M.LAssailant = null - else - M.LAssailant = firer - - if(!A) - return 1 - - if(A) - if(firer && istype(A, /obj/structure/bed/chair/vehicle))//This is very sloppy but there's no way to get the firer after its passed to bullet_act, we'll just have to assume the admins will use their judgement - var/obj/structure/bed/chair/vehicle/JC = A - if(JC.occupant) - var/mob/BM = JC.occupant - if(istype(firer, /mob)) - admin_warn(BM) - if(!iscarbon(firer)) - BM.LAssailant = null - else - BM.LAssailant = firer - if (!forcedodge) - forcedodge = A.bullet_act(src, def_zone) // searches for return value - if(forcedodge == -1) // the bullet passes through a dense object! - bumped = 0 // reset bumped variable! - - if(istype(A, /turf)) - loc = A - else - loc = A.loc - - if(permutated) - permutated.Add(A) - - return 0 - else if(!custom_impact) - var/impact_icon = null - var/impact_sound = null - if(ismob(A)) - if(issilicon(A)) - impact_icon = "default_solid" - impact_sound = 'sound/items/metal_impact.ogg' - else - impact_icon = "default_mob"//todo: blood_colors - impact_sound = 'sound/weapons/pierce.ogg' - else - impact_icon = "default_solid" - impact_sound = 'sound/items/metal_impact.ogg' - var/PixelX = 0 - var/PixelY = 0 - switch(get_dir(src,A)) - if(NORTH) - PixelY = 16 - if(SOUTH) - PixelY = -16 - if(EAST) - PixelX = 16 - if(WEST) - PixelX = -16 - - var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,impact_icon) - impact.pixel_x = PixelX - impact.pixel_y = PixelY - - var/turf/T = src.loc - if(T) //Trying to fix a runtime that happens when a flare hits a window, T somehow becomes null. - T.overlays += impact - - spawn(3) - T.overlays -= impact - - playsound(T, impact_sound, 30, 1) - - if(istype(A,/turf)) - for(var/obj/O in A) - O.bullet_act(src) - for(var/mob/M in A) - M.bullet_act(src, def_zone) - - if(!A) - return 1 - - //the bullets first checks if it can bounce off the obstacle, and if it cannot it then checks if it can phase through it, if it cannot either then it dies. - var/reaction_type = A.projectile_check() - if(bounces && (bounce_type & reaction_type)) - rebound(A) - bounces-- - return 1 - else if(penetration && (phase_type & reaction_type)) - if((penetration > 0) && (penetration < A.penetration_dampening)) //if the obstacle is too resistant, we don't go through it. - penetration = 0 - bullet_die() - return 1 - A.visible_message("\The [src] goes right through \the [A]!") - src.forceMove(get_step(src.loc,dir)) - if(linear_movement) - update_pixel() - pixel_x = PixelX - pixel_y = PixelY - if(penetration > 0)//a negative penetration value means that the projectile can keep moving through obstacles - penetration = max(0, penetration - A.penetration_dampening) - if(isturf(A)) //if the bullet goes through a wall, we leave a nice mark on it - damage -= (damage/4) //and diminish the bullet's damage a bit - if(!destroy)//destroying projectiles don't leave marks, as they would then appear on the resulting plating. - var/turf/T = A - T.bullet_marks++ - var/icon/I = icon(T.icon, T.icon_state) - var/icon/trace = icon('icons/effects/96x96.dmi',mark_type) //first we take the 96x96 icon with the overlay we want to blend on the wall - trace.Turn(target_angle+45) //then we rotate it so it matches the bullet's angle - trace.Crop(33-pixel_x,33-pixel_y,64-pixel_x,64-pixel_y) //lastly we crop a 32x32 square in the icon whose offset matches the projectile's pixel offset *-1 - I.Blend(trace,ICON_MULTIPLY ,1 ,1) //we can now blend our resulting icon on the wall - T.icon = I - return 1 - - bullet_die() - return 1 - -/obj/item/projectile/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(air_group || (height==0)) return 1 - - if(istype(mover, /obj/item/projectile)) - return prob(95) - else - return 1 - -/obj/item/projectile/proc/OnDeath() //if assigned, allows for code when the projectile disappears - return 1 - -/obj/item/projectile/proc/OnFired() //if assigned, allows for code when the projectile gets fired - target = get_turf(original) - dist_x = abs(target.x - starting.x) - dist_y = abs(target.y - starting.y) - - override_starting_X = starting.x - override_starting_Y = starting.y - override_target_X = target.x - override_target_Y = target.y - - if (target.x > starting.x) - dx = EAST - else - dx = WEST - - if (target.y > starting.y) - dy = NORTH - else - dy = SOUTH - - if(dist_x > dist_y) - error = dist_x/2 - dist_y - else - error = dist_y/2 - dist_x - - target_angle = round(Get_Angle(starting,target)) - - if(linear_movement) - //If the icon has not been added yet - if( !("[icon_state]_angle[target_angle]" in bullet_master) ) - var/icon/I = new(icon,"[icon_state]_pixel") //Generate it. - I.Turn(target_angle+45) - bullet_master["[icon_state]_angle[target_angle]"] = I //And cache it! - src.icon = bullet_master["[icon_state]_angle[target_angle]"] - - return 1 - -/obj/item/projectile/proc/process_step() - var/sleeptime = 1 - if(src.loc) - if(dist_x > dist_y) - sleeptime = bresenham_step(dist_x,dist_y,dx,dy) - else - sleeptime = bresenham_step(dist_y,dist_x,dy,dx) - if(linear_movement) - update_pixel() - pixel_x = PixelX - pixel_y = PixelY - - bumped = 0 - - sleep(sleeptime) - - -/obj/item/projectile/proc/bresenham_step(var/distA, var/distB, var/dA, var/dB) - if(step_delay) - sleep(step_delay) - if(kill_count < 1) - bullet_die() - return 1 - kill_count-- - total_steps++ - if(error < 0) - var/atom/step = get_step(src, dB) - if(!step) - bullet_die() - src.Move(step) - error += distA - bump_original_check() - return 0//so that bullets going in diagonals don't move twice slower - else - var/atom/step = get_step(src, dA) - if(!step) - bullet_die() - src.Move(step) - error -= distB - dir = dA - if(error < 0) - dir = dA + dB - bump_original_check() - return 1 - -/obj/item/projectile/proc/update_pixel() - if(src && starting && target) - var/AX = (override_starting_X - src.x)*32 - var/AY = (override_starting_Y - src.y)*32 - var/BX = (override_target_X - src.x)*32 - var/BY = (override_target_Y - src.y)*32 - var/XX = (((BX-AX)*(-BX))+((BY-AY)*(-BY)))/(((BX-AX)*(BX-AX))+((BY-AY)*(BY-AY))) - - PixelX = round(BX+((BX-AX)*XX)) - PixelY = round(BY+((BY-AY)*XX)) - switch(last_bump) - if(NORTH) - PixelY -= 16 - if(SOUTH) - PixelY += 16 - if(EAST) - PixelX -= 16 - if(WEST) - PixelX += 16 - return - -/obj/item/projectile/proc/bullet_die() - spawn() - OnDeath() - returnToPool(src) - -/obj/item/projectile/proc/bump_original_check() - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - return 1//so laser beams visually stop when they hit their target - return 0 - -/obj/item/projectile/process() - var/first = 1 - var/tS = 0 - spawn while(loc) - if(first && timestopped) - tS = 1 - timestopped = 0 - while((loc.timestopped || timestopped) && !first) - sleep(3) - first = 0 - src.process_step() - if(tS) - timestopped = loc.timestopped - tS = 0 - return - -/obj/item/projectile/proc/dumbfire(var/dir) // for spacepods, go snowflake go - if(!dir) - //del(src) - OnDeath() - returnToPool(src) - if(kill_count < 1) - //del(src) - OnDeath() - returnToPool(src) - kill_count-- - var/first = 1 - var/tS = 0 - spawn while(loc) - if(first && timestopped) - tS = 1 - timestopped = 0 - var/turf/T = get_step(src, dir) - step_towards(src, T) - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - sleep(1) - while((loc.timestopped || timestopped) && !first) - sleep(3) - first = 0 - if(tS) - timestopped = loc.timestopped - tS = 0 - sleep(1) - return - -/obj/item/projectile/bullet_act(/obj/item/projectile/bullet) - return -1 - -/obj/item/projectile/proc/rebound(var/atom/A)//Projectiles bouncing off walls and obstacles - var/turf/T = get_turf(src) - var/turf/W = get_turf(A) - playsound(T, bounce_sound, 30, 1) - var/orientation = SOUTH - if(T == W) - orientation = dir - else - orientation = get_dir(T,W) - last_bump = orientation - switch(orientation) - if(NORTH) - dy = SOUTH - override_starting_Y = (W.y * 2) - override_starting_Y - override_target_Y = (W.y * 2) - override_target_Y - if(SOUTH) - dy = NORTH - override_starting_Y = (W.y * 2) - override_starting_Y - override_target_Y = (W.y * 2) - override_target_Y - if(EAST) - dx = WEST - override_starting_X = (W.x * 2) - override_starting_X - override_target_X = (W.x * 2) - override_target_X - if(WEST) - dx = EAST - override_starting_X = (W.x * 2) - override_starting_X - override_target_X = (W.x * 2) - override_target_X - var/newdiffX = override_target_X - override_starting_X - var/newdiffY = override_target_Y - override_starting_Y - - if(!W) - W = T - override_starting_X = W.x - override_starting_Y = W.y - override_target_X = W.x + newdiffX - override_target_Y = W.y + newdiffY - - var/disty - var/distx - var/newangle - disty = (32 * override_target_Y)-(32 * override_starting_Y) - distx = (32 * override_target_X)-(32 * override_starting_X) - if(!disty) - if(distx >= 0) - newangle = 90 - else - newangle = 270 - else - newangle = arctan(distx/disty) - if(disty < 0) - newangle += 180 - else if(distx < 0) - newangle += 360 - - target_angle = round(newangle) - - if(linear_movement) - if( !("[icon_state][target_angle]" in bullet_master) ) - var/icon/I = new(initial(icon),"[icon_state]_pixel") - I.Turn(target_angle+45) - bullet_master["[icon_state]_angle[target_angle]"] = I - src.icon = bullet_master["[icon_state]_angle[target_angle]"] - -/obj/item/projectile/test //Used to see if you can hit them. - invisibility = 101 //Nope! Can't see me! - yo = null - xo = null - var/ttarget = null - var/result = 0 //To pass the message back to the gun. - -/obj/item/projectile/test/Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return //cannot shoot yourself - if(istype(A, /obj/item/projectile)) - return - if(istype(A, /mob/living)) - result = 2 //We hit someone, return 1! - return - result = 1 - return - -/obj/item/projectile/test/process() - var/turf/curloc = get_turf(src) - var/turf/targloc = get_turf(ttarget) - if(!curloc || !targloc) - return 0 - yo = targloc.y - curloc.y - xo = targloc.x - curloc.x - target = targloc - while(loc) //Loop on through! - if(result) - return (result - 1) - - var/mob/living/M = locate() in get_turf(src) - if(istype(M)) //If there is someting living... - return 1 //Return 1 - else - M = locate() in get_step(src,ttarget) - if(istype(M)) - return 1 - - if((!( ttarget ) || loc == ttarget)) - ttarget = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge - step_towards(src, ttarget) + else + visible_message("[A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter + admin_warn(M) + if(istype(firer, /mob)) + if(!iscarbon(firer)) + M.LAssailant = null + else + M.LAssailant = firer + + if(!A) + return 1 + + if(A) + if(firer && istype(A, /obj/structure/bed/chair/vehicle))//This is very sloppy but there's no way to get the firer after its passed to bullet_act, we'll just have to assume the admins will use their judgement + var/obj/structure/bed/chair/vehicle/JC = A + if(JC.occupant) + var/mob/BM = JC.occupant + if(istype(firer, /mob)) + admin_warn(BM) + if(!iscarbon(firer)) + BM.LAssailant = null + else + BM.LAssailant = firer + if (!forcedodge) + forcedodge = A.bullet_act(src, def_zone) // searches for return value + if(forcedodge == -1) // the bullet passes through a dense object! + bumped = 0 // reset bumped variable! + + if(istype(A, /turf)) + loc = A + else + loc = A.loc + + if(permutated) + permutated.Add(A) + + return 0 + else if(!custom_impact) + var/impact_icon = null + var/impact_sound = null + if(ismob(A)) + if(issilicon(A)) + impact_icon = "default_solid" + impact_sound = 'sound/items/metal_impact.ogg' + else + impact_icon = "default_mob"//todo: blood_colors + impact_sound = 'sound/weapons/pierce.ogg' + else + impact_icon = "default_solid" + impact_sound = 'sound/items/metal_impact.ogg' + var/PixelX = 0 + var/PixelY = 0 + switch(get_dir(src,A)) + if(NORTH) + PixelY = 16 + if(SOUTH) + PixelY = -16 + if(EAST) + PixelX = 16 + if(WEST) + PixelX = -16 + + var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,impact_icon) + impact.pixel_x = PixelX + impact.pixel_y = PixelY + + var/turf/T = src.loc + if(T) //Trying to fix a runtime that happens when a flare hits a window, T somehow becomes null. + T.overlays += impact + + spawn(3) + T.overlays -= impact + + playsound(T, impact_sound, 30, 1) + + if(istype(A,/turf)) + for(var/obj/O in A) + O.bullet_act(src) + for(var/mob/M in A) + M.bullet_act(src, def_zone) + + if(!A) + return 1 + + //the bullets first checks if it can bounce off the obstacle, and if it cannot it then checks if it can phase through it, if it cannot either then it dies. + var/reaction_type = A.projectile_check() + if(bounces && (bounce_type & reaction_type)) + rebound(A) + bounces-- + return 1 + else if(penetration && (phase_type & reaction_type)) + if((penetration > 0) && (penetration < A.penetration_dampening)) //if the obstacle is too resistant, we don't go through it. + penetration = 0 + bullet_die() + return 1 + A.visible_message("\The [src] goes right through \the [A]!") + src.forceMove(get_step(src.loc,dir)) + if(linear_movement) + update_pixel() + pixel_x = PixelX + pixel_y = PixelY + if(penetration > 0)//a negative penetration value means that the projectile can keep moving through obstacles + penetration = max(0, penetration - A.penetration_dampening) + if(isturf(A)) //if the bullet goes through a wall, we leave a nice mark on it + damage -= (damage/4) //and diminish the bullet's damage a bit + if(!destroy)//destroying projectiles don't leave marks, as they would then appear on the resulting plating. + var/turf/T = A + T.bullet_marks++ + var/icon/I = icon(T.icon, T.icon_state) + var/icon/trace = icon('icons/effects/96x96.dmi',mark_type) //first we take the 96x96 icon with the overlay we want to blend on the wall + trace.Turn(target_angle+45) //then we rotate it so it matches the bullet's angle + trace.Crop(33-pixel_x,33-pixel_y,64-pixel_x,64-pixel_y) //lastly we crop a 32x32 square in the icon whose offset matches the projectile's pixel offset *-1 + I.Blend(trace,ICON_MULTIPLY ,1 ,1) //we can now blend our resulting icon on the wall + T.icon = I + return 1 + + bullet_die() + return 1 + +/obj/item/projectile/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(air_group || (height==0)) return 1 + + if(istype(mover, /obj/item/projectile)) + return prob(95) + else + return 1 + +/obj/item/projectile/proc/OnDeath() //if assigned, allows for code when the projectile disappears + return 1 + +/obj/item/projectile/proc/OnFired() //if assigned, allows for code when the projectile gets fired + target = get_turf(original) + dist_x = abs(target.x - starting.x) + dist_y = abs(target.y - starting.y) + + override_starting_X = starting.x + override_starting_Y = starting.y + override_target_X = target.x + override_target_Y = target.y + + if (target.x > starting.x) + dx = EAST + else + dx = WEST + + if (target.y > starting.y) + dy = NORTH + else + dy = SOUTH + + if(dist_x > dist_y) + error = dist_x/2 - dist_y + else + error = dist_y/2 - dist_x + + target_angle = round(Get_Angle(starting,target)) + + if(linear_movement) + //If the icon has not been added yet + if( !("[icon_state]_angle[target_angle]" in bullet_master) ) + var/icon/I = new(icon,"[icon_state]_pixel") //Generate it. + I.Turn(target_angle+45) + bullet_master["[icon_state]_angle[target_angle]"] = I //And cache it! + src.icon = bullet_master["[icon_state]_angle[target_angle]"] + + return 1 + +/obj/item/projectile/proc/process_step() + var/sleeptime = 1 + if(src.loc) + if(dist_x > dist_y) + sleeptime = bresenham_step(dist_x,dist_y,dx,dy) + else + sleeptime = bresenham_step(dist_y,dist_x,dy,dx) + if(linear_movement) + update_pixel() + pixel_x = PixelX + pixel_y = PixelY + + bumped = 0 + + sleep(sleeptime) + + +/obj/item/projectile/proc/bresenham_step(var/distA, var/distB, var/dA, var/dB) + if(step_delay) + sleep(step_delay) + if(kill_count < 1) + bullet_die() + return 1 + kill_count-- + total_steps++ + if(error < 0) + var/atom/step = get_step(src, dB) + if(!step) + bullet_die() + src.Move(step) + error += distA + bump_original_check() + return 0//so that bullets going in diagonals don't move twice slower + else + var/atom/step = get_step(src, dA) + if(!step) + bullet_die() + src.Move(step) + error -= distB + dir = dA + if(error < 0) + dir = dA + dB + bump_original_check() + return 1 + +/obj/item/projectile/proc/update_pixel() + if(src && starting && target) + var/AX = (override_starting_X - src.x)*32 + var/AY = (override_starting_Y - src.y)*32 + var/BX = (override_target_X - src.x)*32 + var/BY = (override_target_Y - src.y)*32 + var/XX = (((BX-AX)*(-BX))+((BY-AY)*(-BY)))/(((BX-AX)*(BX-AX))+((BY-AY)*(BY-AY))) + + PixelX = round(BX+((BX-AX)*XX)) + PixelY = round(BY+((BY-AY)*XX)) + switch(last_bump) + if(NORTH) + PixelY -= 16 + if(SOUTH) + PixelY += 16 + if(EAST) + PixelX -= 16 + if(WEST) + PixelX += 16 + return + +/obj/item/projectile/proc/bullet_die() + spawn() + OnDeath() + returnToPool(src) + +/obj/item/projectile/proc/bump_original_check() + if(!bumped && !isturf(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original) + return 1//so laser beams visually stop when they hit their target + return 0 + +/obj/item/projectile/process() + var/first = 1 + var/tS = 0 + spawn while(loc) + if(first && timestopped) + tS = 1 + timestopped = 0 + while((loc.timestopped || timestopped) && !first) + sleep(3) + first = 0 + src.process_step() + if(tS) + timestopped = loc.timestopped + tS = 0 + return + +/obj/item/projectile/proc/dumbfire(var/dir) // for spacepods, go snowflake go + if(!dir) + //del(src) + OnDeath() + returnToPool(src) + if(kill_count < 1) + //del(src) + OnDeath() + returnToPool(src) + kill_count-- + var/first = 1 + var/tS = 0 + spawn while(loc) + if(first && timestopped) + tS = 1 + timestopped = 0 + var/turf/T = get_step(src, dir) + step_towards(src, T) + if(!bumped && !isturf(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original) + sleep(1) + while((loc.timestopped || timestopped) && !first) + sleep(3) + first = 0 + if(tS) + timestopped = loc.timestopped + tS = 0 + sleep(1) + return + +/obj/item/projectile/bullet_act(/obj/item/projectile/bullet) + return -1 + +/obj/item/projectile/proc/rebound(var/atom/A)//Projectiles bouncing off walls and obstacles + var/turf/T = get_turf(src) + var/turf/W = get_turf(A) + playsound(T, bounce_sound, 30, 1) + var/orientation = SOUTH + if(T == W) + orientation = dir + else + orientation = get_dir(T,W) + last_bump = orientation + switch(orientation) + if(NORTH) + dy = SOUTH + override_starting_Y = (W.y * 2) - override_starting_Y + override_target_Y = (W.y * 2) - override_target_Y + if(SOUTH) + dy = NORTH + override_starting_Y = (W.y * 2) - override_starting_Y + override_target_Y = (W.y * 2) - override_target_Y + if(EAST) + dx = WEST + override_starting_X = (W.x * 2) - override_starting_X + override_target_X = (W.x * 2) - override_target_X + if(WEST) + dx = EAST + override_starting_X = (W.x * 2) - override_starting_X + override_target_X = (W.x * 2) - override_target_X + var/newdiffX = override_target_X - override_starting_X + var/newdiffY = override_target_Y - override_starting_Y + + if(!W) + W = T + override_starting_X = W.x + override_starting_Y = W.y + override_target_X = W.x + newdiffX + override_target_Y = W.y + newdiffY + + var/disty + var/distx + var/newangle + disty = (32 * override_target_Y)-(32 * override_starting_Y) + distx = (32 * override_target_X)-(32 * override_starting_X) + if(!disty) + if(distx >= 0) + newangle = 90 + else + newangle = 270 + else + newangle = arctan(distx/disty) + if(disty < 0) + newangle += 180 + else if(distx < 0) + newangle += 360 + + target_angle = round(newangle) + + if(linear_movement) + if( !("[icon_state][target_angle]" in bullet_master) ) + var/icon/I = new(initial(icon),"[icon_state]_pixel") + I.Turn(target_angle+45) + bullet_master["[icon_state]_angle[target_angle]"] = I + src.icon = bullet_master["[icon_state]_angle[target_angle]"] + +/obj/item/projectile/test //Used to see if you can hit them. + invisibility = 101 //Nope! Can't see me! + yo = null + xo = null + var/ttarget = null + var/result = 0 //To pass the message back to the gun. + +/obj/item/projectile/test/Bump(atom/A as mob|obj|turf|area) + if(A == firer) + loc = A.loc + return //cannot shoot yourself + if(istype(A, /obj/item/projectile)) + return + if(istype(A, /mob/living)) + result = 2 //We hit someone, return 1! + return + result = 1 + return + +/obj/item/projectile/test/process() + var/turf/curloc = get_turf(src) + var/turf/targloc = get_turf(ttarget) + if(!curloc || !targloc) + return 0 + yo = targloc.y - curloc.y + xo = targloc.x - curloc.x + target = targloc + while(loc) //Loop on through! + if(result) + return (result - 1) + + var/mob/living/M = locate() in get_turf(src) + if(istype(M)) //If there is someting living... + return 1 //Return 1 + else + M = locate() in get_step(src,ttarget) + if(istype(M)) + return 1 + + if((!( ttarget ) || loc == ttarget)) + ttarget = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge + step_towards(src, ttarget) diff --git a/code/modules/projectiles/projectile/animate.dm b/code/modules/projectiles/projectile/animate.dm index 5b0f6c90b6c..668e10d584f 100644 --- a/code/modules/projectiles/projectile/animate.dm +++ b/code/modules/projectiles/projectile/animate.dm @@ -1,15 +1,15 @@ -#define SPELL_ANIMATION_TTL 2 MINUTES - -/obj/item/projectile/animate - name = "bolt of animation" - icon_state = "ice_1" - damage = 0 - damage_type = BURN - nodamage = 1 - flag = "energy" - -/obj/item/projectile/animate/Bump(var/atom/change) - if(istype(change, /obj/item) || istype(change, /obj/structure) && !is_type_in_list(change, protected_objects)) - var/obj/O = change - new /mob/living/simple_animal/hostile/mimic/copy(O.loc, O, firer, duration=SPELL_ANIMATION_TTL) +#define SPELL_ANIMATION_TTL 2 MINUTES + +/obj/item/projectile/animate + name = "bolt of animation" + icon_state = "ice_1" + damage = 0 + damage_type = BURN + nodamage = 1 + flag = "energy" + +/obj/item/projectile/animate/Bump(var/atom/change) + if(istype(change, /obj/item) || istype(change, /obj/structure) && !is_type_in_list(change, protected_objects)) + var/obj/O = change + new /mob/living/simple_animal/hostile/mimic/copy(O.loc, O, firer, duration=SPELL_ANIMATION_TTL) ..() \ No newline at end of file diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 96a38fbcfaa..1d88bb9f48c 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -1,858 +1,858 @@ - -/* - * Use: Caches beam state images and holds turfs that had these images overlaid. - * Structure: - * beam_master - * icon_states/dirs of beams - * image for that beam - * references for fired beams - * icon_states/dirs for each placed beam image - * turfs that have that icon_state/dir - */ -var/list/beam_master = list() - -// Special laser the captains gun uses -/obj/item/projectile/beam/captain - name = "captain laser" - damage = 40 - linear_movement = 0 - -/obj/item/projectile/beam/retro - linear_movement = 0 - -/obj/item/projectile/beam/lightning - invisibility = 101 - name = "lightning" - damage = 0 - icon = 'icons/obj/lightning.dmi' - icon_state = "lightning" - stun = 10 - weaken = 10 - stutter = 50 - eyeblur = 50 - var/tang = 0 - layer = 13 - var/turf/last = null - kill_count = 12 - -/obj/item/projectile/beam/lightning/proc/adjustAngle(angle) - angle = round(angle) + 45 - if(angle > 180) - angle -= 180 - else - angle += 180 - if(!angle) - angle = 1 - /*if(angle < 0) - //angle = (round(abs(get_angle(A, user))) + 45) - 90 - angle = round(angle) + 45 + 180 - else - angle = round(angle) + 45*/ - return angle - -/obj/item/projectile/beam/lightning/process() - icon_state = "lightning" - var/first = 1 //So we don't make the overlay in the same tile as the firer - var/broke = 0 - var/broken - var/atom/curr = current - var/Angle=round(Get_Angle(firer,curr)) - var/icon/I=new('icons/obj/lightning.dmi',icon_state) - var/icon/Istart=new('icons/obj/lightning.dmi',"[icon_state]start") - var/icon/Iend=new('icons/obj/lightning.dmi',"[icon_state]end") - I.Turn(Angle+45) - Istart.Turn(Angle+45) - Iend.Turn(Angle+45) - var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x) - var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y) - var/N=0 - var/length=round(sqrt((DX)**2+(DY)**2)) - var/count = 0 - var/turf/T = get_turf(src) - var/list/ouroverlays = list() - - spawn() for(N,N= kill_count) - break - count++ - var/obj/effect/overlay/beam/persist/X=getFromPool(/obj/effect/overlay/beam/persist,T) - X.BeamSource=src - ouroverlays += X - if((N+64>length) && (N+32<=length)) - X.icon=Iend - else if(N==0) - X.icon=Istart - else if(N+32>length) - X.icon=null - else - X.icon=I - - var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) - var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) - if(DX==0) Pixel_x=0 - if(DY==0) Pixel_y=0 - if(Pixel_x>32) - for(var/a=0, a<=Pixel_x,a+=32) - X.x++ - Pixel_x-=32 - if(Pixel_x<-32) - for(var/a=0, a>=Pixel_x,a-=32) - X.x-- - Pixel_x+=32 - if(Pixel_y>32) - for(var/a=0, a<=Pixel_y,a+=32) - X.y++ - Pixel_y-=32 - if(Pixel_y<-32) - for(var/a=0, a>=Pixel_y,a-=32) - X.y-- - Pixel_y+=32 - - //Now that we've calculated the total offset in pixels, we move each beam parts to their closest corresponding turfs - var/x_increm = 0 - var/y_increm = 0 - - while(Pixel_x >= 32 || Pixel_x <= -32) - if(Pixel_x > 0) - Pixel_x -= 32 - x_increm++ - else - Pixel_x += 32 - x_increm-- - - while(Pixel_y >= 32 || Pixel_y <= -32) - if(Pixel_y > 0) - Pixel_y -= 32 - y_increm++ - else - Pixel_y += 32 - y_increm-- - - X.x += x_increm - X.y += y_increm - - X.pixel_x=Pixel_x - X.pixel_y=Pixel_y - var/turf/TT = get_turf(X.loc) - while((TT.timestopped || timestopped || X.timestopped) && count) - sleep(2) - if(TT == firer.loc) - continue - if(TT.density) - qdel(X) - X = null - break - for(var/atom/O in TT) - if(!O.CanPass(src)) - qdel(X) - broke = 1 - break - for(var/mob/living/O in TT.contents) - if(istype(O, /mob/living)) - if(O.density) - qdel(X) - X = null - broke = 1 - break - if(broke) - if(X) - qdel(X) - X = null - break - spawn(10) - for(var/atom/thing in ouroverlays) - if(!thing.timestopped && !thing.loc.timestopped) - ouroverlays -= thing - returnToPool(thing) - spawn - var/tS = 0 - while(loc) //Move until we hit something - if(tS) - tS = 0 - timestopped = loc.timestopped - while((loc.timestopped || timestopped) && !first) - tS = 1 - sleep(3) - if(first) - icon = midicon - if(timestopped || loc.timestopped) - tS = 1 - timestopped = 0 - if((!( current ) || loc == current)) //If we pass our target - broken = 1 - icon = endicon - tang = adjustAngle(get_angle(original,current)) - if(tang > 180) - tang -= 180 - else - tang += 180 - icon_state = "[tang]" - var/turf/simulated/floor/f = current - if(f && istype(f)) - f.break_tile() - f.hotspot_expose(1000,CELL_VOLUME,surfaces=1) - if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) -// to_chat(world, "deleting") - //del(src) //Delete if it passes the world edge - broken = 1 - return - if(kill_count < 1) -// to_chat(world, "deleting") - //del(src) - broken = 1 - kill_count-- -// to_chat(world, "[x] [y]") - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - icon = endicon - if(!broken) - tang = adjustAngle(get_angle(original,current)) - if(tang > 180) - tang -= 180 - else - tang += 180 - icon_state = "[tang]" - Bump(original) - first = 0 - if(broken) -// to_chat(world, "breaking") - break - else - last = get_turf(src.loc) - step_towards(src, current) //Move~ - if(src.loc != current) - tang = adjustAngle(get_angle(src.loc,current)) - icon_state = "[tang]" - if(ouroverlays.len) - sleep(10) - for(var/atom/thing in ouroverlays) - ouroverlays -= thing - returnToPool(thing) - - //del(src) - returnToPool(src) - return -/*cleanup(reference) //Waits .3 seconds then removes the overlay. -// to_chat(world, "setting invisibility") - sleep(50) - src.invisibility = 101 - return*/ - -/obj/item/projectile/beam/lightning/on_hit(atom/target, blocked = 0) - if(istype(target, /mob/living)) - var/mob/living/M = target - M.playsound_local(src, "explosion", 50, 1) - ..() - -/obj/item/projectile/beam/lightning/spell - var/spell/lightning/our_spell - weaken = 0 - stun = 0 -/obj/item/projectile/beam/lightning/spell/Bump(atom/A as mob|obj|turf|area) - . = ..() - if(.) - our_spell.lastbumped = A - return . - -/obj/item/projectile/beam - name = "laser" - icon_state = "laser" - invisibility = 101 - animate_movement = 2 - linear_movement = 1 - layer = 13 - - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - damage = 30 - damage_type = BURN - flag = "laser" - eyeblur = 4 - var/frequency = 1 - var/wait = 0 - -/obj/item/projectile/beam/OnFired() //if assigned, allows for code when the projectile gets fired - target = get_turf(original) - dist_x = abs(target.x - starting.x) - dist_y = abs(target.y - starting.y) - - override_starting_X = starting.x - override_starting_Y = starting.y - override_target_X = target.x - override_target_Y = target.y - - if (target.x > starting.x) - dx = EAST - else - dx = WEST - - if (target.y > starting.y) - dy = NORTH - else - dy = SOUTH - - if(dist_x > dist_y) - error = dist_x/2 - dist_y - else - error = dist_y/2 - dist_x - - target_angle = round(Get_Angle(starting,target)) - - return 1 - -/obj/item/projectile/beam/process() - var/lastposition = loc - var/reference = "\ref[src]" //So we do not have to recalculate it a ton - - target = get_turf(original) - dist_x = abs(target.x - src.x) - dist_y = abs(target.y - src.y) - - if (target.x > src.x) - dx = EAST - else - dx = WEST - - if (target.y > src.y) - dy = NORTH - else - dy = SOUTH - var/target_dir = SOUTH - - if(dist_x > dist_y) - error = dist_x/2 - dist_y - - spawn - reference = bresenham_step(dist_x,dist_y,dx,dy,lastposition,target_dir,reference) - - else - error = dist_y/2 - dist_x - spawn - reference = bresenham_step(dist_y,dist_x,dy,dx,lastposition,target_dir,reference) - - cleanup(reference) - return - -/obj/item/projectile/beam/bresenham_step(var/distA, var/distB, var/dA, var/dB, var/lastposition, var/target_dir, var/reference) - var/first = 1 - var/tS = 0 - while(src && src.loc)// only stop when we've hit something, or hit the end of the map - if(first && timestopped) - tS = 1 - timestopped = 0 - if(error < 0) - var/atom/step = get_step(src, dB) - if(!step) - bullet_die() - src.Move(step) - error += distA - target_dir = null - else - var/atom/step = get_step(src, dA) - if(!step) - bullet_die() - src.Move(step) - error -= distB - target_dir = dA - if(error < 0) - target_dir = dA + dB - - if(isnull(loc)) - return reference - if(lastposition == loc && (!tS && !timestopped && !loc.timestopped)) - kill_count = 0 - lastposition = loc - if(kill_count < 1) - returnToPool(src) - return reference - kill_count-- - if(bump_original_check()) - return reference - - if(linear_movement) - update_pixel() - - //If the icon has not been added yet - if( !("[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]" in beam_master) ) - var/image/I = image(icon,"[icon_state]_pixel",13,target_dir) //Generate it. - I.transform = turn(I.transform, target_angle+45) - I.pixel_x = PixelX - I.pixel_y = PixelY - beam_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] = I //And cache it! - - //Finally add the overlay - if(src.loc && target_dir) - src.loc.overlays += beam_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] - - //Add the turf to a list in the beam master so they can be cleaned up easily. - if(reference in beam_master) - var/list/turf_master = beam_master[reference] - if("[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]" in turf_master) - var/list/turfs = turf_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] - turfs += loc - else - turf_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] = list(loc) - else - var/list/turfs = list() - turfs["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] = list(loc) - beam_master[reference] = turfs - else - //If the icon has not been added yet - if( !("[icon_state][target_dir]" in beam_master) ) - var/image/I = image(icon,icon_state,10,target_dir) //Generate it. - beam_master["[icon_state][target_dir]"] = I //And cache it! - - //Finally add the overlay - if(src.loc && target_dir) - src.loc.overlays += beam_master["[icon_state][target_dir]"] - - //Add the turf to a list in the beam master so they can be cleaned up easily. - if(reference in beam_master) - var/list/turf_master = beam_master[reference] - if("[icon_state][target_dir]" in turf_master) - var/list/turfs = turf_master["[icon_state][target_dir]"] - turfs += loc - else - turf_master["[icon_state][target_dir]"] = list(loc) - else - var/list/turfs = list() - turfs["[icon_state][target_dir]"] = list(loc) - beam_master[reference] = turfs - if(tS) - timestopped = loc.timestopped - tS = 0 - if(wait) - sleep(wait) - wait = 0 - while((loc.timestopped || timestopped) && !first) - sleep(3) - first = 0 - - - return reference - - -/obj/item/projectile/beam/dumbfire(var/dir) - var/reference = "\ref[src]" // So we do not have to recalculate it a ton. - - spawn(0) - var/target_dir = dir ? dir : src.dir// TODO: remove dir arg. Or don't because the way this was set up without it broke spacepods. - var/first = 1 - var/tS = 0 - while(loc) // Move until we hit something. - if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) - returnToPool(src) - break - if(first && timestopped) - tS = 1 - timestopped = 0 - step(src, target_dir) // Move. - if(tS) - tS = 0 - timestopped = loc.timestopped - if(bumped) - break - - if(kill_count-- < 1) - returnToPool(src) - break - - // Add the overlay as we pass over tiles. - - // If the icon has not been added yet. - if(!beam_master.Find("[icon_state][target_dir]")) - beam_master["[icon_state][target_dir]"] = image(icon, icon_state, 10, target_dir) // Generate, and cache it! - - // Finally add the overlay - loc.overlays.Add(beam_master["[icon_state][target_dir]"]) - - // Add the turf to a list in the beam master so they can be cleaned up easily. - if(beam_master.Find(reference)) - var/list/turf_master = beam_master[reference] - - if(turf_master.Find("[icon_state][target_dir]")) - turf_master["[icon_state][target_dir]"] += loc - else - turf_master["[icon_state][target_dir]"] = list(loc) - else - var/list/turfs = new - turfs["[icon_state][target_dir]"] = list(loc) - beam_master[reference] = turfs - while((loc.timestopped || timestopped) && !first) - sleep(3) - first = 0 - - - cleanup(reference) - -/obj/item/projectile/beam/proc/cleanup(const/reference) - var/TS - var/atom/lastloc - var/starttime = world.time - var/cleanedup = 0 - while(world.time - starttime < 3 || TS) - if(loc) - lastloc = loc - TS = lastloc.timestopped - if(TS) - if(world.time - starttime > 3) - if(!cleanedup) - var/list/turf_master = beam_master[reference] - - for(var/laser_state in turf_master) - var/list/turfs = turf_master[laser_state] - for(var/turf/T in turfs) - if(!T.timestopped) - T.overlays.Remove(beam_master[laser_state]) - cleanedup = 1 - sleep(2) - - else sleep(1) - - if(cleanedup) sleep(2) - var/list/turf_master = beam_master[reference] - - for(var/laser_state in turf_master) - var/list/turfs = turf_master[laser_state] - - for(var/turf/T in turfs) - T.overlays.Remove(beam_master[laser_state]) - - turfs.len = 0 - -/obj/item/projectile/beam/practice - name = "laser" - icon_state = "laser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - damage = 0 - damage_type = BURN - flag = "laser" - eyeblur = 2 - -/obj/item/projectile/beam/practice/stormtrooper - -/obj/item/projectile/beam/practice/stormtrooper/on_hit(var/atom/target, var/blocked = 0) - if(..(target, blocked)) - var/mob/living/L = target - var/message = pick("\the [src] narrowly whizzes past [L]!","\the [src] almost hits [L]!","\the [src] straight up misses its target.","[L]'s hair is singed off by \the [src]!","\the [src] misses [L] by a millimetre!","\the [src] doesn't hit","\the [src] misses its intended target.","[L] has a lucky escape from \the [src]!") - target.loc.visible_message("[message]") - -/obj/item/projectile/beam/heavylaser - name = "heavy laser" - icon_state = "heavylaser" - damage = 40 - -/obj/item/projectile/beam/xray - name = "xray beam" - icon_state = "xray" - damage = 30 - -/obj/item/projectile/beam/pulse - name = "pulse" - icon_state = "u_laser" - damage = 50 - destroy = 1 - -/obj/item/projectile/beam/deathlaser - name = "death laser" - icon_state = "heavylaser" - damage = 60 - -/obj/item/projectile/beam/emitter - name = "emitter beam" - icon_state = "emitter" - damage = 30 - -/obj/item/projectile/beam/emitter/singularity_pull() - return - -/obj/item/projectile/beam/lastertag/blue - name = "lasertag beam" - icon_state = "bluelaser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - damage = 0 - damage_type = BURN - flag = "laser" - - on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/M = target - if(istype(M.wear_suit, /obj/item/clothing/suit/redtag)) - M.Weaken(5) - return 1 - -/obj/item/projectile/beam/lastertag/red - name = "lasertag beam" - icon_state = "laser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - damage = 0 - damage_type = BURN - flag = "laser" - - on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/M = target - if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag)) - M.Weaken(5) - return 1 - -/obj/item/projectile/beam/lastertag/omni//A laser tag bolt that stuns EVERYONE - name = "lasertag beam" - icon_state = "omnilaser" - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - damage = 0 - damage_type = BURN - flag = "laser" - - on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/M = target - if((istype(M.wear_suit, /obj/item/clothing/suit/bluetag))||(istype(M.wear_suit, /obj/item/clothing/suit/redtag))) - M.Weaken(5) - return 1 - -/obj/item/projectile/beam/bison - name = "heat ray" - damage_type = BURN - flag = "laser" - kill_count = 100 - layer = 13 - damage = 15 - icon = 'icons/obj/lightning.dmi' - icon_state = "heatray" - animate_movement = 0 - linear_movement = 0 - pass_flags = PASSTABLE - var/drawn = 0 - var/tang = 0 - var/turf/last = null -/obj/item/projectile/beam/bison/proc/adjustAngle(angle) - angle = round(angle) + 45 - if(angle > 180) - angle -= 180 - else - angle += 180 - if(!angle) - angle = 1 - /*if(angle < 0) - //angle = (round(abs(get_angle(A, user))) + 45) - 90 - angle = round(angle) + 45 + 180 - else - angle = round(angle) + 45*/ - return angle - -/obj/item/projectile/beam/bison/process() - //calculating the turfs that we go through - var/lastposition = loc - target = get_turf(original) - dist_x = abs(target.x - src.x) - dist_y = abs(target.y - src.y) - - if (target.x > src.x) - dx = EAST - else - dx = WEST - - if (target.y > src.y) - dy = NORTH - else - dy = SOUTH - - if(dist_x > dist_y) - error = dist_x/2 - dist_y - - spawn while(src && src.loc) - // only stop when we've hit something, or hit the end of the map - if(error < 0) - var/atom/step = get_step(src, dy) - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - src.Move(step) - error += dist_x - else - var/atom/step = get_step(src, dx) - if(!step) - break - src.Move(step) - error -= dist_y - - if(isnull(loc)) - draw_ray(lastposition) - return - if(lastposition == loc) - kill_count = 0 - lastposition = loc - if(kill_count < 1) - //del(src) - draw_ray(lastposition) - returnToPool(src) - return - kill_count-- - - if(!bumped && !isturf(original)) - if(loc == target) - if(!(original in permutated)) - draw_ray(target) - Bump(original) - - else - error = dist_y/2 - dist_x - spawn while(src && src.loc) - // only stop when we've hit something, or hit the end of the map - if(error < 0) - var/atom/step = get_step(src, dx) - if(!step) - break - src.Move(step) - error += dist_y - else - var/atom/step = get_step(src, dy) - if(!step) - break - src.Move(step) - error -= dist_x - - if(isnull(loc)) - draw_ray(lastposition) - return - if(lastposition == loc) - kill_count = 0 - lastposition = loc - if(kill_count < 1) - //del(src) - draw_ray(lastposition) - returnToPool(src) - return - kill_count-- - - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - draw_ray(target) - Bump(original) - - return - -/obj/item/projectile/beam/bison/bullet_die() - draw_ray(loc) - ..() - -/obj/item/projectile/beam/bison/proc/draw_ray(var/turf/lastloc) - if(drawn) return - drawn = 1 - var/atom/curr = lastloc - if(!firer) - firer = starting - var/Angle=round(Get_Angle(firer,curr)) - var/icon/I=new('icons/obj/lightning.dmi',icon_state) - var/icon/Istart=new('icons/obj/lightning.dmi',"[icon_state]start") - var/icon/Iend=new('icons/obj/lightning.dmi',"[icon_state]end") - I.Turn(Angle+45) - Istart.Turn(Angle+45) - Iend.Turn(Angle+45) - var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x) - var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y) - var/N=0 - var/length=round(sqrt((DX)**2+(DY)**2)) - var/count = 0 - var/turf/T = get_turf(firer) - var/timer_total = 16 - var/increment = timer_total/max(1,round(length/32)) - var/current_timer = 5 - - for(N,N<(length+16),N+=32) - if(count >= kill_count) - break - count++ - var/obj/effect/overlay/beam/X=getFromPool(/obj/effect/overlay/beam,T,current_timer,1) - X.BeamSource=src - current_timer += increment - if((N+64>(length+16)) && (N+32<=(length+16))) - X.icon=Iend - else if(N==0) - X.icon=Istart - else if(N+32>(length+16)) - X.icon=null - else - X.icon=I - - - var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) - var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) - if(DX==0) Pixel_x=0 - if(DY==0) Pixel_y=0 - if(Pixel_x>32) - for(var/a=0, a<=Pixel_x,a+=32) - X.x++ - Pixel_x-=32 - if(Pixel_x<-32) - for(var/a=0, a>=Pixel_x,a-=32) - X.x-- - Pixel_x+=32 - if(Pixel_y>32) - for(var/a=0, a<=Pixel_y,a+=32) - X.y++ - Pixel_y-=32 - if(Pixel_y<-32) - for(var/a=0, a>=Pixel_y,a-=32) - X.y-- - Pixel_y+=32 - - //Now that we've calculated the total offset in pixels, we move each beam parts to their closest corresponding turfs - var/x_increm = 0 - var/y_increm = 0 - - while(Pixel_x >= 32 || Pixel_x <= -32) - if(Pixel_x > 0) - Pixel_x -= 32 - x_increm++ - else - Pixel_x += 32 - x_increm-- - - while(Pixel_y >= 32 || Pixel_y <= -32) - if(Pixel_y > 0) - Pixel_y -= 32 - y_increm++ - else - Pixel_y += 32 - y_increm-- - - X.x += x_increm - X.y += y_increm - X.pixel_x=Pixel_x - X.pixel_y=Pixel_y - var/turf/TT = get_turf(X.loc) - if(TT == firer.loc) - continue - - return - -/obj/item/projectile/beam/bison/Bump(atom/A as mob|obj|turf|area) - //Heat Rays go through mobs - if(A == firer) - loc = A.loc - return 0 //cannot shoot yourself - - if(firer && istype(A, /mob/living)) - var/mob/living/M = A - A.bullet_act(src, def_zone) - loc = A.loc - permutated.Add(A) - visible_message("[A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter - if(istype(firer, /mob)) - log_attack("[key_name(firer)] shot [key_name(M)] with a [type]") - M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" - firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" - msg_admin_attack("[key_name(firer)] shot [key_name(M)] with a [type] (JMP)") //BS12 EDIT ALG - if(!iscarbon(firer)) - M.LAssailant = null - else - M.LAssailant = firer - else - M.attack_log += "\[[time_stamp()]\] UNKNOWN/(no longer exists) shot [key_name(M)] with a [type]" - msg_admin_attack("UNKNOWN/(no longer exists) shot [key_name(M)] with a [type] (JMP)") //BS12 EDIT ALG - log_attack("UNKNOWN/(no longer exists) shot [key_name(M)] with a [type]") - return 1 - else - return ..() + +/* + * Use: Caches beam state images and holds turfs that had these images overlaid. + * Structure: + * beam_master + * icon_states/dirs of beams + * image for that beam + * references for fired beams + * icon_states/dirs for each placed beam image + * turfs that have that icon_state/dir + */ +var/list/beam_master = list() + +// Special laser the captains gun uses +/obj/item/projectile/beam/captain + name = "captain laser" + damage = 40 + linear_movement = 0 + +/obj/item/projectile/beam/retro + linear_movement = 0 + +/obj/item/projectile/beam/lightning + invisibility = 101 + name = "lightning" + damage = 0 + icon = 'icons/obj/lightning.dmi' + icon_state = "lightning" + stun = 10 + weaken = 10 + stutter = 50 + eyeblur = 50 + var/tang = 0 + layer = 13 + var/turf/last = null + kill_count = 12 + +/obj/item/projectile/beam/lightning/proc/adjustAngle(angle) + angle = round(angle) + 45 + if(angle > 180) + angle -= 180 + else + angle += 180 + if(!angle) + angle = 1 + /*if(angle < 0) + //angle = (round(abs(get_angle(A, user))) + 45) - 90 + angle = round(angle) + 45 + 180 + else + angle = round(angle) + 45*/ + return angle + +/obj/item/projectile/beam/lightning/process() + icon_state = "lightning" + var/first = 1 //So we don't make the overlay in the same tile as the firer + var/broke = 0 + var/broken + var/atom/curr = current + var/Angle=round(Get_Angle(firer,curr)) + var/icon/I=new('icons/obj/lightning.dmi',icon_state) + var/icon/Istart=new('icons/obj/lightning.dmi',"[icon_state]start") + var/icon/Iend=new('icons/obj/lightning.dmi',"[icon_state]end") + I.Turn(Angle+45) + Istart.Turn(Angle+45) + Iend.Turn(Angle+45) + var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x) + var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y) + var/N=0 + var/length=round(sqrt((DX)**2+(DY)**2)) + var/count = 0 + var/turf/T = get_turf(src) + var/list/ouroverlays = list() + + spawn() for(N,N= kill_count) + break + count++ + var/obj/effect/overlay/beam/persist/X=getFromPool(/obj/effect/overlay/beam/persist,T) + X.BeamSource=src + ouroverlays += X + if((N+64>length) && (N+32<=length)) + X.icon=Iend + else if(N==0) + X.icon=Istart + else if(N+32>length) + X.icon=null + else + X.icon=I + + var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) + var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) + if(DX==0) Pixel_x=0 + if(DY==0) Pixel_y=0 + if(Pixel_x>32) + for(var/a=0, a<=Pixel_x,a+=32) + X.x++ + Pixel_x-=32 + if(Pixel_x<-32) + for(var/a=0, a>=Pixel_x,a-=32) + X.x-- + Pixel_x+=32 + if(Pixel_y>32) + for(var/a=0, a<=Pixel_y,a+=32) + X.y++ + Pixel_y-=32 + if(Pixel_y<-32) + for(var/a=0, a>=Pixel_y,a-=32) + X.y-- + Pixel_y+=32 + + //Now that we've calculated the total offset in pixels, we move each beam parts to their closest corresponding turfs + var/x_increm = 0 + var/y_increm = 0 + + while(Pixel_x >= 32 || Pixel_x <= -32) + if(Pixel_x > 0) + Pixel_x -= 32 + x_increm++ + else + Pixel_x += 32 + x_increm-- + + while(Pixel_y >= 32 || Pixel_y <= -32) + if(Pixel_y > 0) + Pixel_y -= 32 + y_increm++ + else + Pixel_y += 32 + y_increm-- + + X.x += x_increm + X.y += y_increm + + X.pixel_x=Pixel_x + X.pixel_y=Pixel_y + var/turf/TT = get_turf(X.loc) + while((TT.timestopped || timestopped || X.timestopped) && count) + sleep(2) + if(TT == firer.loc) + continue + if(TT.density) + qdel(X) + X = null + break + for(var/atom/O in TT) + if(!O.CanPass(src)) + qdel(X) + broke = 1 + break + for(var/mob/living/O in TT.contents) + if(istype(O, /mob/living)) + if(O.density) + qdel(X) + X = null + broke = 1 + break + if(broke) + if(X) + qdel(X) + X = null + break + spawn(10) + for(var/atom/thing in ouroverlays) + if(!thing.timestopped && !thing.loc.timestopped) + ouroverlays -= thing + returnToPool(thing) + spawn + var/tS = 0 + while(loc) //Move until we hit something + if(tS) + tS = 0 + timestopped = loc.timestopped + while((loc.timestopped || timestopped) && !first) + tS = 1 + sleep(3) + if(first) + icon = midicon + if(timestopped || loc.timestopped) + tS = 1 + timestopped = 0 + if((!( current ) || loc == current)) //If we pass our target + broken = 1 + icon = endicon + tang = adjustAngle(get_angle(original,current)) + if(tang > 180) + tang -= 180 + else + tang += 180 + icon_state = "[tang]" + var/turf/simulated/floor/f = current + if(f && istype(f)) + f.break_tile() + f.hotspot_expose(1000,CELL_VOLUME,surfaces=1) + if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) +// to_chat(world, "deleting") + //del(src) //Delete if it passes the world edge + broken = 1 + return + if(kill_count < 1) +// to_chat(world, "deleting") + //del(src) + broken = 1 + kill_count-- +// to_chat(world, "[x] [y]") + if(!bumped && !isturf(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + icon = endicon + if(!broken) + tang = adjustAngle(get_angle(original,current)) + if(tang > 180) + tang -= 180 + else + tang += 180 + icon_state = "[tang]" + Bump(original) + first = 0 + if(broken) +// to_chat(world, "breaking") + break + else + last = get_turf(src.loc) + step_towards(src, current) //Move~ + if(src.loc != current) + tang = adjustAngle(get_angle(src.loc,current)) + icon_state = "[tang]" + if(ouroverlays.len) + sleep(10) + for(var/atom/thing in ouroverlays) + ouroverlays -= thing + returnToPool(thing) + + //del(src) + returnToPool(src) + return +/*cleanup(reference) //Waits .3 seconds then removes the overlay. +// to_chat(world, "setting invisibility") + sleep(50) + src.invisibility = 101 + return*/ + +/obj/item/projectile/beam/lightning/on_hit(atom/target, blocked = 0) + if(istype(target, /mob/living)) + var/mob/living/M = target + M.playsound_local(src, "explosion", 50, 1) + ..() + +/obj/item/projectile/beam/lightning/spell + var/spell/lightning/our_spell + weaken = 0 + stun = 0 +/obj/item/projectile/beam/lightning/spell/Bump(atom/A as mob|obj|turf|area) + . = ..() + if(.) + our_spell.lastbumped = A + return . + +/obj/item/projectile/beam + name = "laser" + icon_state = "laser" + invisibility = 101 + animate_movement = 2 + linear_movement = 1 + layer = 13 + + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + damage = 30 + damage_type = BURN + flag = "laser" + eyeblur = 4 + var/frequency = 1 + var/wait = 0 + +/obj/item/projectile/beam/OnFired() //if assigned, allows for code when the projectile gets fired + target = get_turf(original) + dist_x = abs(target.x - starting.x) + dist_y = abs(target.y - starting.y) + + override_starting_X = starting.x + override_starting_Y = starting.y + override_target_X = target.x + override_target_Y = target.y + + if (target.x > starting.x) + dx = EAST + else + dx = WEST + + if (target.y > starting.y) + dy = NORTH + else + dy = SOUTH + + if(dist_x > dist_y) + error = dist_x/2 - dist_y + else + error = dist_y/2 - dist_x + + target_angle = round(Get_Angle(starting,target)) + + return 1 + +/obj/item/projectile/beam/process() + var/lastposition = loc + var/reference = "\ref[src]" //So we do not have to recalculate it a ton + + target = get_turf(original) + dist_x = abs(target.x - src.x) + dist_y = abs(target.y - src.y) + + if (target.x > src.x) + dx = EAST + else + dx = WEST + + if (target.y > src.y) + dy = NORTH + else + dy = SOUTH + var/target_dir = SOUTH + + if(dist_x > dist_y) + error = dist_x/2 - dist_y + + spawn + reference = bresenham_step(dist_x,dist_y,dx,dy,lastposition,target_dir,reference) + + else + error = dist_y/2 - dist_x + spawn + reference = bresenham_step(dist_y,dist_x,dy,dx,lastposition,target_dir,reference) + + cleanup(reference) + return + +/obj/item/projectile/beam/bresenham_step(var/distA, var/distB, var/dA, var/dB, var/lastposition, var/target_dir, var/reference) + var/first = 1 + var/tS = 0 + while(src && src.loc)// only stop when we've hit something, or hit the end of the map + if(first && timestopped) + tS = 1 + timestopped = 0 + if(error < 0) + var/atom/step = get_step(src, dB) + if(!step) + bullet_die() + src.Move(step) + error += distA + target_dir = null + else + var/atom/step = get_step(src, dA) + if(!step) + bullet_die() + src.Move(step) + error -= distB + target_dir = dA + if(error < 0) + target_dir = dA + dB + + if(isnull(loc)) + return reference + if(lastposition == loc && (!tS && !timestopped && !loc.timestopped)) + kill_count = 0 + lastposition = loc + if(kill_count < 1) + returnToPool(src) + return reference + kill_count-- + if(bump_original_check()) + return reference + + if(linear_movement) + update_pixel() + + //If the icon has not been added yet + if( !("[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]" in beam_master) ) + var/image/I = image(icon,"[icon_state]_pixel",13,target_dir) //Generate it. + I.transform = turn(I.transform, target_angle+45) + I.pixel_x = PixelX + I.pixel_y = PixelY + beam_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] = I //And cache it! + + //Finally add the overlay + if(src.loc && target_dir) + src.loc.overlays += beam_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] + + //Add the turf to a list in the beam master so they can be cleaned up easily. + if(reference in beam_master) + var/list/turf_master = beam_master[reference] + if("[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]" in turf_master) + var/list/turfs = turf_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] + turfs += loc + else + turf_master["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] = list(loc) + else + var/list/turfs = list() + turfs["[icon_state]_angle[target_angle]_pX[PixelX]_pY[PixelY]"] = list(loc) + beam_master[reference] = turfs + else + //If the icon has not been added yet + if( !("[icon_state][target_dir]" in beam_master) ) + var/image/I = image(icon,icon_state,10,target_dir) //Generate it. + beam_master["[icon_state][target_dir]"] = I //And cache it! + + //Finally add the overlay + if(src.loc && target_dir) + src.loc.overlays += beam_master["[icon_state][target_dir]"] + + //Add the turf to a list in the beam master so they can be cleaned up easily. + if(reference in beam_master) + var/list/turf_master = beam_master[reference] + if("[icon_state][target_dir]" in turf_master) + var/list/turfs = turf_master["[icon_state][target_dir]"] + turfs += loc + else + turf_master["[icon_state][target_dir]"] = list(loc) + else + var/list/turfs = list() + turfs["[icon_state][target_dir]"] = list(loc) + beam_master[reference] = turfs + if(tS) + timestopped = loc.timestopped + tS = 0 + if(wait) + sleep(wait) + wait = 0 + while((loc.timestopped || timestopped) && !first) + sleep(3) + first = 0 + + + return reference + + +/obj/item/projectile/beam/dumbfire(var/dir) + var/reference = "\ref[src]" // So we do not have to recalculate it a ton. + + spawn(0) + var/target_dir = dir ? dir : src.dir// TODO: remove dir arg. Or don't because the way this was set up without it broke spacepods. + var/first = 1 + var/tS = 0 + while(loc) // Move until we hit something. + if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) + returnToPool(src) + break + if(first && timestopped) + tS = 1 + timestopped = 0 + step(src, target_dir) // Move. + if(tS) + tS = 0 + timestopped = loc.timestopped + if(bumped) + break + + if(kill_count-- < 1) + returnToPool(src) + break + + // Add the overlay as we pass over tiles. + + // If the icon has not been added yet. + if(!beam_master.Find("[icon_state][target_dir]")) + beam_master["[icon_state][target_dir]"] = image(icon, icon_state, 10, target_dir) // Generate, and cache it! + + // Finally add the overlay + loc.overlays.Add(beam_master["[icon_state][target_dir]"]) + + // Add the turf to a list in the beam master so they can be cleaned up easily. + if(beam_master.Find(reference)) + var/list/turf_master = beam_master[reference] + + if(turf_master.Find("[icon_state][target_dir]")) + turf_master["[icon_state][target_dir]"] += loc + else + turf_master["[icon_state][target_dir]"] = list(loc) + else + var/list/turfs = new + turfs["[icon_state][target_dir]"] = list(loc) + beam_master[reference] = turfs + while((loc.timestopped || timestopped) && !first) + sleep(3) + first = 0 + + + cleanup(reference) + +/obj/item/projectile/beam/proc/cleanup(const/reference) + var/TS + var/atom/lastloc + var/starttime = world.time + var/cleanedup = 0 + while(world.time - starttime < 3 || TS) + if(loc) + lastloc = loc + TS = lastloc.timestopped + if(TS) + if(world.time - starttime > 3) + if(!cleanedup) + var/list/turf_master = beam_master[reference] + + for(var/laser_state in turf_master) + var/list/turfs = turf_master[laser_state] + for(var/turf/T in turfs) + if(!T.timestopped) + T.overlays.Remove(beam_master[laser_state]) + cleanedup = 1 + sleep(2) + + else sleep(1) + + if(cleanedup) sleep(2) + var/list/turf_master = beam_master[reference] + + for(var/laser_state in turf_master) + var/list/turfs = turf_master[laser_state] + + for(var/turf/T in turfs) + T.overlays.Remove(beam_master[laser_state]) + + turfs.len = 0 + +/obj/item/projectile/beam/practice + name = "laser" + icon_state = "laser" + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + damage = 0 + damage_type = BURN + flag = "laser" + eyeblur = 2 + +/obj/item/projectile/beam/practice/stormtrooper + +/obj/item/projectile/beam/practice/stormtrooper/on_hit(var/atom/target, var/blocked = 0) + if(..(target, blocked)) + var/mob/living/L = target + var/message = pick("\the [src] narrowly whizzes past [L]!","\the [src] almost hits [L]!","\the [src] straight up misses its target.","[L]'s hair is singed off by \the [src]!","\the [src] misses [L] by a millimetre!","\the [src] doesn't hit","\the [src] misses its intended target.","[L] has a lucky escape from \the [src]!") + target.loc.visible_message("[message]") + +/obj/item/projectile/beam/heavylaser + name = "heavy laser" + icon_state = "heavylaser" + damage = 40 + +/obj/item/projectile/beam/xray + name = "xray beam" + icon_state = "xray" + damage = 30 + +/obj/item/projectile/beam/pulse + name = "pulse" + icon_state = "u_laser" + damage = 50 + destroy = 1 + +/obj/item/projectile/beam/deathlaser + name = "death laser" + icon_state = "heavylaser" + damage = 60 + +/obj/item/projectile/beam/emitter + name = "emitter beam" + icon_state = "emitter" + damage = 30 + +/obj/item/projectile/beam/emitter/singularity_pull() + return + +/obj/item/projectile/beam/lastertag/blue + name = "lasertag beam" + icon_state = "bluelaser" + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + damage = 0 + damage_type = BURN + flag = "laser" + + on_hit(var/atom/target, var/blocked = 0) + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/M = target + if(istype(M.wear_suit, /obj/item/clothing/suit/redtag)) + M.Weaken(5) + return 1 + +/obj/item/projectile/beam/lastertag/red + name = "lasertag beam" + icon_state = "laser" + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + damage = 0 + damage_type = BURN + flag = "laser" + + on_hit(var/atom/target, var/blocked = 0) + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/M = target + if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag)) + M.Weaken(5) + return 1 + +/obj/item/projectile/beam/lastertag/omni//A laser tag bolt that stuns EVERYONE + name = "lasertag beam" + icon_state = "omnilaser" + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + damage = 0 + damage_type = BURN + flag = "laser" + + on_hit(var/atom/target, var/blocked = 0) + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/M = target + if((istype(M.wear_suit, /obj/item/clothing/suit/bluetag))||(istype(M.wear_suit, /obj/item/clothing/suit/redtag))) + M.Weaken(5) + return 1 + +/obj/item/projectile/beam/bison + name = "heat ray" + damage_type = BURN + flag = "laser" + kill_count = 100 + layer = 13 + damage = 15 + icon = 'icons/obj/lightning.dmi' + icon_state = "heatray" + animate_movement = 0 + linear_movement = 0 + pass_flags = PASSTABLE + var/drawn = 0 + var/tang = 0 + var/turf/last = null +/obj/item/projectile/beam/bison/proc/adjustAngle(angle) + angle = round(angle) + 45 + if(angle > 180) + angle -= 180 + else + angle += 180 + if(!angle) + angle = 1 + /*if(angle < 0) + //angle = (round(abs(get_angle(A, user))) + 45) - 90 + angle = round(angle) + 45 + 180 + else + angle = round(angle) + 45*/ + return angle + +/obj/item/projectile/beam/bison/process() + //calculating the turfs that we go through + var/lastposition = loc + target = get_turf(original) + dist_x = abs(target.x - src.x) + dist_y = abs(target.y - src.y) + + if (target.x > src.x) + dx = EAST + else + dx = WEST + + if (target.y > src.y) + dy = NORTH + else + dy = SOUTH + + if(dist_x > dist_y) + error = dist_x/2 - dist_y + + spawn while(src && src.loc) + // only stop when we've hit something, or hit the end of the map + if(error < 0) + var/atom/step = get_step(src, dy) + if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + break + src.Move(step) + error += dist_x + else + var/atom/step = get_step(src, dx) + if(!step) + break + src.Move(step) + error -= dist_y + + if(isnull(loc)) + draw_ray(lastposition) + return + if(lastposition == loc) + kill_count = 0 + lastposition = loc + if(kill_count < 1) + //del(src) + draw_ray(lastposition) + returnToPool(src) + return + kill_count-- + + if(!bumped && !isturf(original)) + if(loc == target) + if(!(original in permutated)) + draw_ray(target) + Bump(original) + + else + error = dist_y/2 - dist_x + spawn while(src && src.loc) + // only stop when we've hit something, or hit the end of the map + if(error < 0) + var/atom/step = get_step(src, dx) + if(!step) + break + src.Move(step) + error += dist_y + else + var/atom/step = get_step(src, dy) + if(!step) + break + src.Move(step) + error -= dist_x + + if(isnull(loc)) + draw_ray(lastposition) + return + if(lastposition == loc) + kill_count = 0 + lastposition = loc + if(kill_count < 1) + //del(src) + draw_ray(lastposition) + returnToPool(src) + return + kill_count-- + + if(!bumped && !isturf(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + draw_ray(target) + Bump(original) + + return + +/obj/item/projectile/beam/bison/bullet_die() + draw_ray(loc) + ..() + +/obj/item/projectile/beam/bison/proc/draw_ray(var/turf/lastloc) + if(drawn) return + drawn = 1 + var/atom/curr = lastloc + if(!firer) + firer = starting + var/Angle=round(Get_Angle(firer,curr)) + var/icon/I=new('icons/obj/lightning.dmi',icon_state) + var/icon/Istart=new('icons/obj/lightning.dmi',"[icon_state]start") + var/icon/Iend=new('icons/obj/lightning.dmi',"[icon_state]end") + I.Turn(Angle+45) + Istart.Turn(Angle+45) + Iend.Turn(Angle+45) + var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x) + var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y) + var/N=0 + var/length=round(sqrt((DX)**2+(DY)**2)) + var/count = 0 + var/turf/T = get_turf(firer) + var/timer_total = 16 + var/increment = timer_total/max(1,round(length/32)) + var/current_timer = 5 + + for(N,N<(length+16),N+=32) + if(count >= kill_count) + break + count++ + var/obj/effect/overlay/beam/X=getFromPool(/obj/effect/overlay/beam,T,current_timer,1) + X.BeamSource=src + current_timer += increment + if((N+64>(length+16)) && (N+32<=(length+16))) + X.icon=Iend + else if(N==0) + X.icon=Istart + else if(N+32>(length+16)) + X.icon=null + else + X.icon=I + + + var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) + var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) + if(DX==0) Pixel_x=0 + if(DY==0) Pixel_y=0 + if(Pixel_x>32) + for(var/a=0, a<=Pixel_x,a+=32) + X.x++ + Pixel_x-=32 + if(Pixel_x<-32) + for(var/a=0, a>=Pixel_x,a-=32) + X.x-- + Pixel_x+=32 + if(Pixel_y>32) + for(var/a=0, a<=Pixel_y,a+=32) + X.y++ + Pixel_y-=32 + if(Pixel_y<-32) + for(var/a=0, a>=Pixel_y,a-=32) + X.y-- + Pixel_y+=32 + + //Now that we've calculated the total offset in pixels, we move each beam parts to their closest corresponding turfs + var/x_increm = 0 + var/y_increm = 0 + + while(Pixel_x >= 32 || Pixel_x <= -32) + if(Pixel_x > 0) + Pixel_x -= 32 + x_increm++ + else + Pixel_x += 32 + x_increm-- + + while(Pixel_y >= 32 || Pixel_y <= -32) + if(Pixel_y > 0) + Pixel_y -= 32 + y_increm++ + else + Pixel_y += 32 + y_increm-- + + X.x += x_increm + X.y += y_increm + X.pixel_x=Pixel_x + X.pixel_y=Pixel_y + var/turf/TT = get_turf(X.loc) + if(TT == firer.loc) + continue + + return + +/obj/item/projectile/beam/bison/Bump(atom/A as mob|obj|turf|area) + //Heat Rays go through mobs + if(A == firer) + loc = A.loc + return 0 //cannot shoot yourself + + if(firer && istype(A, /mob/living)) + var/mob/living/M = A + A.bullet_act(src, def_zone) + loc = A.loc + permutated.Add(A) + visible_message("[A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter + if(istype(firer, /mob)) + log_attack("[key_name(firer)] shot [key_name(M)] with a [type]") + M.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" + firer.attack_log += "\[[time_stamp()]\] [key_name(firer)] shot [key_name(M)] with a [type]" + msg_admin_attack("[key_name(firer)] shot [key_name(M)] with a [type] (JMP)") //BS12 EDIT ALG + if(!iscarbon(firer)) + M.LAssailant = null + else + M.LAssailant = firer + else + M.attack_log += "\[[time_stamp()]\] UNKNOWN/(no longer exists) shot [key_name(M)] with a [type]" + msg_admin_attack("UNKNOWN/(no longer exists) shot [key_name(M)] with a [type] (JMP)") //BS12 EDIT ALG + log_attack("UNKNOWN/(no longer exists) shot [key_name(M)] with a [type]") + return 1 + else + return ..() diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index ef76f32af78..9b84545c01b 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -1,317 +1,317 @@ -/obj/item/projectile/bullet - name = "bullet" - icon_state = "bullet" - damage = 60 - damage_type = BRUTE - nodamage = 0 - phase_type = PROJREACT_WINDOWS - penetration = 5 //bullets can now by default move through up to 5 windows, or 2 reinforced windows, or 1 plasma window. (reinforced plasma windows still have enough dampening to completely block them) - flag = "bullet" - var/embed = 1 - -/obj/item/projectile/bullet/on_hit(var/atom/target, var/blocked = 0) - if (..(target, blocked)) - var/mob/living/L = target - shake_camera(L, 3, 2) - return 1 - return 0 - -/obj/item/projectile/bullet/dart - name = "shotgun dart" - damage = 5 - damage_type = TOX - weaken = 5 - -/obj/item/projectile/bullet/weakbullet - icon_state = "bbshell" - damage = 10 - stun = 5 - weaken = 5 - embed = 0 -/obj/item/projectile/bullet/weakbullet/booze - on_hit(var/atom/target, var/blocked = 0) - if(..(target, blocked)) - var/mob/living/M = target - M.dizziness += 20 - M:slurring += 20 - M.confused += 20 - M.eye_blurry += 20 - M.drowsyness += 20 - if(M.dizziness <= 150) - M.Dizzy(150) - M.dizziness = 150 - for(var/datum/reagent/ethanol/A in M.reagents.reagent_list) - M.paralysis += 2 - M.dizziness += 10 - M:slurring += 10 - M.confused += 10 - M.eye_blurry += 10 - M.drowsyness += 10 - A.volume += 5 //Because we can - M.dizziness += 10 - return 1 - return 0 - -/obj/item/projectile/bullet/midbullet - damage = 20 - stun = 5 - weaken = 5 - -/obj/item/projectile/bullet/midbullet/lawgiver - damage = 10 - stun = 0 - weaken = 0 - -/obj/item/projectile/bullet/midbullet2 - damage = 25 - -/obj/item/projectile/bullet/suffocationbullet//How does this even work? - name = "co bullet" - damage = 20 - damage_type = OXY - - -/obj/item/projectile/bullet/cyanideround - name = "poison bullet" - damage = 40 - damage_type = TOX - - -/obj/item/projectile/bullet/burstbullet//I think this one needs something for the on hit - name = "exploding bullet" - damage = 20 - - -/obj/item/projectile/bullet/stunshot - name = "stunshot" - icon_state = "sshell" - damage = 5 - stun = 10 - weaken = 10 - stutter = 10 - -/obj/item/projectile/bullet/a762 - damage = 25 - -#define SPUR_FULL_POWER 4 -#define SPUR_HIGH_POWER 3 -#define SPUR_MEDIUM_POWER 2 -#define SPUR_LOW_POWER 1 -#define SPUR_NO_POWER 0 - -/obj/item/projectile/spur - name = "spur bullet" - damage_type = BRUTE - flag = "bullet" - kill_count = 100 - layer = 13 - damage = 40 - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "spur_high" - animate_movement = 2 - custom_impact = 1 - linear_movement = 0 - -/obj/item/projectile/spur/OnFired() - ..() - var/obj/item/weapon/gun/energy/polarstar/spur/quote = shot_from - if(!quote || !istype(quote)) - return - switch(quote.firelevel) - if(SPUR_FULL_POWER,SPUR_HIGH_POWER) - icon_state = "spur_high" - damage = 40 - kill_count = 20 - if(SPUR_MEDIUM_POWER) - icon_state = "spur_medium" - damage = 30 - kill_count = 13 - if(SPUR_LOW_POWER,SPUR_NO_POWER) - icon_state = "spur_low" - damage = 20 - kill_count = 7 - -/obj/item/projectile/spur/polarstar - name = "polar star bullet" - damage = 20 - -/obj/item/projectile/spur/polarstar/OnFired() - ..() - var/obj/item/weapon/gun/energy/polarstar/quote = shot_from - if(!quote || !istype(quote)) - return - switch(quote.firelevel) - if(SPUR_FULL_POWER,SPUR_HIGH_POWER) - icon_state = "spur_high" - damage = 20 - kill_count = 20 - if(SPUR_MEDIUM_POWER) - icon_state = "spur_medium" - damage = 15 - kill_count = 13 - if(SPUR_LOW_POWER,SPUR_NO_POWER) - icon_state = "spur_low" - damage = 10 - kill_count = 7 - -/obj/item/projectile/spur/Bump(atom/A as mob|obj|turf|area) - - if(loc) - var/turf/T = loc - var/impact_icon = null - var/impact_sound = null - var/PixelX = 0 - var/PixelY = 0 - - switch(get_dir(src,A)) - if(NORTH) - PixelY = 16 - if(SOUTH) - PixelY = -16 - if(EAST) - PixelX = 16 - if(WEST) - PixelX = -16 - if(ismob(A)) - impact_icon = "spur_3" - impact_sound = 'sound/weapons/spur_hitmob.ogg' - else - impact_icon = "spur_1" - impact_sound = 'sound/weapons/spur_hitwall.ogg' - - var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,impact_icon) - impact.pixel_x = PixelX - impact.pixel_y = PixelY - impact.layer = 13 - T.overlays += impact - spawn(3) - T.overlays -= impact - playsound(loc, impact_sound, 30, 1) - - - if(istype(A, /turf/unsimulated/mineral)) - var/turf/unsimulated/mineral/M = A - M.GetDrilled() - if(istype(A, /obj/structure/boulder)) - returnToPool(A) - - return ..() - -/obj/item/projectile/spur/process_step() - if(kill_count <= 0) - if(loc) - var/turf/T = loc - var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,"spur_2") - impact.layer = 13 - T.overlays += impact - spawn(3) - T.overlays -= impact - ..() - -#undef SPUR_FULL_POWER -#undef SPUR_HIGH_POWER -#undef SPUR_MEDIUM_POWER -#undef SPUR_LOW_POWER -#undef SPUR_NO_POWER - - -/obj/item/projectile/bullet/gatling - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "minigun" - damage = 30 - -/obj/item/projectile/bullet/osipr - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "osipr" - damage = 50 - stun = 2 - weaken = 2 - destroy = 1 - bounce_type = PROJREACT_WALLS|PROJREACT_WINDOWS - bounces = 1 - -/obj/item/projectile/bullet/hecate - name = "high penetration bullet" - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "hecate" - damage = 101//you're going to crit, lad - kill_count = 255//oh boy, we're crossing through the entire Z level! - stun = 5 - weaken = 5 - stutter = 5 - phase_type = PROJREACT_WALLS|PROJREACT_WINDOWS|PROJREACT_OBJS|PROJREACT_MOBS|PROJREACT_BLOB - penetration = 20//can hit 3 mobs at once, or go through a wall and hit 2 more mobs, or go through an rwall/blast door and hit 1 mob - var/superspeed = 1 - -/obj/item/projectile/bullet/hecate/OnFired() - ..() - for (var/mob/M in player_list) - if(M && M.client) - var/turf/M_turf = get_turf(M) - if(M_turf && (M_turf.z == starting.z)) - M.playsound_local(starting, 'sound/weapons/hecate_fire_far.ogg', 25, 1) - for (var/mob/living/carbon/human/H in range(src,1)) - if(!H.earprot()) - H.Weaken(2) - H.Stun(2) - H.ear_damage += rand(3, 5) - H.ear_deaf = max(H.ear_deaf,15) +/obj/item/projectile/bullet + name = "bullet" + icon_state = "bullet" + damage = 60 + damage_type = BRUTE + nodamage = 0 + phase_type = PROJREACT_WINDOWS + penetration = 5 //bullets can now by default move through up to 5 windows, or 2 reinforced windows, or 1 plasma window. (reinforced plasma windows still have enough dampening to completely block them) + flag = "bullet" + var/embed = 1 + +/obj/item/projectile/bullet/on_hit(var/atom/target, var/blocked = 0) + if (..(target, blocked)) + var/mob/living/L = target + shake_camera(L, 3, 2) + return 1 + return 0 + +/obj/item/projectile/bullet/dart + name = "shotgun dart" + damage = 5 + damage_type = TOX + weaken = 5 + +/obj/item/projectile/bullet/weakbullet + icon_state = "bbshell" + damage = 10 + stun = 5 + weaken = 5 + embed = 0 +/obj/item/projectile/bullet/weakbullet/booze + on_hit(var/atom/target, var/blocked = 0) + if(..(target, blocked)) + var/mob/living/M = target + M.dizziness += 20 + M:slurring += 20 + M.confused += 20 + M.eye_blurry += 20 + M.drowsyness += 20 + if(M.dizziness <= 150) + M.Dizzy(150) + M.dizziness = 150 + for(var/datum/reagent/ethanol/A in M.reagents.reagent_list) + M.paralysis += 2 + M.dizziness += 10 + M:slurring += 10 + M.confused += 10 + M.eye_blurry += 10 + M.drowsyness += 10 + A.volume += 5 //Because we can + M.dizziness += 10 + return 1 + return 0 + +/obj/item/projectile/bullet/midbullet + damage = 20 + stun = 5 + weaken = 5 + +/obj/item/projectile/bullet/midbullet/lawgiver + damage = 10 + stun = 0 + weaken = 0 + +/obj/item/projectile/bullet/midbullet2 + damage = 25 + +/obj/item/projectile/bullet/suffocationbullet//How does this even work? + name = "co bullet" + damage = 20 + damage_type = OXY + + +/obj/item/projectile/bullet/cyanideround + name = "poison bullet" + damage = 40 + damage_type = TOX + + +/obj/item/projectile/bullet/burstbullet//I think this one needs something for the on hit + name = "exploding bullet" + damage = 20 + + +/obj/item/projectile/bullet/stunshot + name = "stunshot" + icon_state = "sshell" + damage = 5 + stun = 10 + weaken = 10 + stutter = 10 + +/obj/item/projectile/bullet/a762 + damage = 25 + +#define SPUR_FULL_POWER 4 +#define SPUR_HIGH_POWER 3 +#define SPUR_MEDIUM_POWER 2 +#define SPUR_LOW_POWER 1 +#define SPUR_NO_POWER 0 + +/obj/item/projectile/spur + name = "spur bullet" + damage_type = BRUTE + flag = "bullet" + kill_count = 100 + layer = 13 + damage = 40 + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "spur_high" + animate_movement = 2 + custom_impact = 1 + linear_movement = 0 + +/obj/item/projectile/spur/OnFired() + ..() + var/obj/item/weapon/gun/energy/polarstar/spur/quote = shot_from + if(!quote || !istype(quote)) + return + switch(quote.firelevel) + if(SPUR_FULL_POWER,SPUR_HIGH_POWER) + icon_state = "spur_high" + damage = 40 + kill_count = 20 + if(SPUR_MEDIUM_POWER) + icon_state = "spur_medium" + damage = 30 + kill_count = 13 + if(SPUR_LOW_POWER,SPUR_NO_POWER) + icon_state = "spur_low" + damage = 20 + kill_count = 7 + +/obj/item/projectile/spur/polarstar + name = "polar star bullet" + damage = 20 + +/obj/item/projectile/spur/polarstar/OnFired() + ..() + var/obj/item/weapon/gun/energy/polarstar/quote = shot_from + if(!quote || !istype(quote)) + return + switch(quote.firelevel) + if(SPUR_FULL_POWER,SPUR_HIGH_POWER) + icon_state = "spur_high" + damage = 20 + kill_count = 20 + if(SPUR_MEDIUM_POWER) + icon_state = "spur_medium" + damage = 15 + kill_count = 13 + if(SPUR_LOW_POWER,SPUR_NO_POWER) + icon_state = "spur_low" + damage = 10 + kill_count = 7 + +/obj/item/projectile/spur/Bump(atom/A as mob|obj|turf|area) + + if(loc) + var/turf/T = loc + var/impact_icon = null + var/impact_sound = null + var/PixelX = 0 + var/PixelY = 0 + + switch(get_dir(src,A)) + if(NORTH) + PixelY = 16 + if(SOUTH) + PixelY = -16 + if(EAST) + PixelX = 16 + if(WEST) + PixelX = -16 + if(ismob(A)) + impact_icon = "spur_3" + impact_sound = 'sound/weapons/spur_hitmob.ogg' + else + impact_icon = "spur_1" + impact_sound = 'sound/weapons/spur_hitwall.ogg' + + var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,impact_icon) + impact.pixel_x = PixelX + impact.pixel_y = PixelY + impact.layer = 13 + T.overlays += impact + spawn(3) + T.overlays -= impact + playsound(loc, impact_sound, 30, 1) + + + if(istype(A, /turf/unsimulated/mineral)) + var/turf/unsimulated/mineral/M = A + M.GetDrilled() + if(istype(A, /obj/structure/boulder)) + returnToPool(A) + + return ..() + +/obj/item/projectile/spur/process_step() + if(kill_count <= 0) + if(loc) + var/turf/T = loc + var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,"spur_2") + impact.layer = 13 + T.overlays += impact + spawn(3) + T.overlays -= impact + ..() + +#undef SPUR_FULL_POWER +#undef SPUR_HIGH_POWER +#undef SPUR_MEDIUM_POWER +#undef SPUR_LOW_POWER +#undef SPUR_NO_POWER + + +/obj/item/projectile/bullet/gatling + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "minigun" + damage = 30 + +/obj/item/projectile/bullet/osipr + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "osipr" + damage = 50 + stun = 2 + weaken = 2 + destroy = 1 + bounce_type = PROJREACT_WALLS|PROJREACT_WINDOWS + bounces = 1 + +/obj/item/projectile/bullet/hecate + name = "high penetration bullet" + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "hecate" + damage = 101//you're going to crit, lad + kill_count = 255//oh boy, we're crossing through the entire Z level! + stun = 5 + weaken = 5 + stutter = 5 + phase_type = PROJREACT_WALLS|PROJREACT_WINDOWS|PROJREACT_OBJS|PROJREACT_MOBS|PROJREACT_BLOB + penetration = 20//can hit 3 mobs at once, or go through a wall and hit 2 more mobs, or go through an rwall/blast door and hit 1 mob + var/superspeed = 1 + +/obj/item/projectile/bullet/hecate/OnFired() + ..() + for (var/mob/M in player_list) + if(M && M.client) + var/turf/M_turf = get_turf(M) + if(M_turf && (M_turf.z == starting.z)) + M.playsound_local(starting, 'sound/weapons/hecate_fire_far.ogg', 25, 1) + for (var/mob/living/carbon/human/H in range(src,1)) + if(!H.earprot()) + H.Weaken(2) + H.Stun(2) + H.ear_damage += rand(3, 5) + H.ear_deaf = max(H.ear_deaf,15) to_chat(H, "Your ears ring!") - -/obj/item/projectile/bullet/hecate/bresenham_step(var/distA, var/distB, var/dA, var/dB) - if(..()) - if(superspeed) - superspeed = 0 - return 1 - else - superspeed = 1 - return 0 - else - return 0 - -/obj/item/projectile/bullet/a762x55 - damage = 65 - stun = 5 - weaken = 5 - phase_type = PROJREACT_WALLS|PROJREACT_WINDOWS|PROJREACT_OBJS - penetration = 10 - -/obj/item/projectile/bullet/beegun - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "beegun" - damage = 5 - damage_type = TOX - flag = "bio" - -/obj/item/projectile/bullet/beegun/OnFired() - ..() - playsound(starting, 'sound/effects/bees.ogg', 75, 1) - -/obj/item/projectile/bullet/beegun/Bump(atom/A as mob|obj|turf|area) - if (!A) - return 0 - if((A == firer) && !reflected) - loc = A.loc - return 0 - if(bumped) - return 0 - bumped = 1 - - var/turf/T = get_turf(src) - var/mob/living/simple_animal/bee/BEE = new(T) - BEE.strength = 1 - BEE.toxic = 5 - BEE.mut = 2 - BEE.feral = 25 - BEE.icon_state = "bees1-feral" - - if(istype(A,/mob/living)) - var/mob/living/M = A - visible_message("\the [M.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!") - M.bullet_act(src, def_zone) - admin_warn(M) - BEE.loc = M.loc - BEE.target = M - else - BEE.newTarget() - bullet_die() + +/obj/item/projectile/bullet/hecate/bresenham_step(var/distA, var/distB, var/dA, var/dB) + if(..()) + if(superspeed) + superspeed = 0 + return 1 + else + superspeed = 1 + return 0 + else + return 0 + +/obj/item/projectile/bullet/a762x55 + damage = 65 + stun = 5 + weaken = 5 + phase_type = PROJREACT_WALLS|PROJREACT_WINDOWS|PROJREACT_OBJS + penetration = 10 + +/obj/item/projectile/bullet/beegun + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "beegun" + damage = 5 + damage_type = TOX + flag = "bio" + +/obj/item/projectile/bullet/beegun/OnFired() + ..() + playsound(starting, 'sound/effects/bees.ogg', 75, 1) + +/obj/item/projectile/bullet/beegun/Bump(atom/A as mob|obj|turf|area) + if (!A) + return 0 + if((A == firer) && !reflected) + loc = A.loc + return 0 + if(bumped) + return 0 + bumped = 1 + + var/turf/T = get_turf(src) + var/mob/living/simple_animal/bee/BEE = new(T) + BEE.strength = 1 + BEE.toxic = 5 + BEE.mut = 2 + BEE.feral = 25 + BEE.icon_state = "bees1-feral" + + if(istype(A,/mob/living)) + var/mob/living/M = A + visible_message("\the [M.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!") + M.bullet_act(src, def_zone) + admin_warn(M) + BEE.loc = M.loc + BEE.target = M + else + BEE.newTarget() + bullet_die() diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index fcc89a2d6fb..056d7182895 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -1,186 +1,186 @@ -/obj/item/projectile/change - name = "bolt of change" - icon_state = "ice_1" - damage = 0 - damage_type = BURN - nodamage = 1 - flag = "energy" - var/changetype=null - -/obj/item/projectile/change/on_hit(var/atom/change) - var/type = changetype - spawn(1)//fixes bugs caused by the target ceasing to exist before the projectile has died. - wabbajack(change,type) - - -/obj/item/projectile/change/proc/wabbajack(var/mob/living/M,var/type) //WHY: as mob in living_mob_list - if(istype(M, /mob/living) && M.stat != DEAD) - if(M.monkeyizing) - return - if(istype(M, /mob/living/carbon/human/manifested)) - visible_message("The bolt of change doesn't seem to affect [M] in any way.") - return - - // TODO: This needs to be standardized, sort of a premorph() proc or something. - M.monkeyizing = 1 - M.canmove = 0 - M.icon = null - M.overlays.len = 0 - M.invisibility = 101 - - if(istype(M, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/Robot = M - if(Robot.mmi) - qdel(Robot.mmi) - else - for(var/obj/item/W in M) - if(istype(W, /obj/item/weapon/implant)) - qdel(W) - continue - W.layer = initial(W.layer) - W.loc = M.loc - W.dropped(M) - // END TODO - - var/mob/living/new_mob - - // Random chance of fucking up - if(type!=null && prob(10)) - type = null - - var/randomize = type == null? pick(available_staff_transforms):type - - switch(randomize) - if("monkey") - new_mob = new /mob/living/carbon/monkey(M.loc) - new_mob.setGender(M.gender) - var/mob/living/carbon/monkey/Monkey = new_mob - Monkey.languages |= M.languages - if(M.default_language) Monkey.default_language = M.default_language - if("robot") - new_mob = new /mob/living/silicon/robot(M.loc) - new_mob.setGender(M.gender) - new_mob.invisibility = 0 - new_mob.job = "Cyborg" - var/mob/living/silicon/robot/Robot = new_mob - Robot.mmi = new /obj/item/device/mmi(new_mob) - Robot.mmi.transfer_identity(M) //Does not transfer key/client. - Robot.languages |= M.languages - if(M.default_language) Robot.default_language = M.default_language - if("mommi") - new_mob = new /mob/living/silicon/robot/mommi(M.loc) - new_mob.setGender(M.gender) - new_mob.invisibility = 0 - new_mob.job = "MoMMI" - var/mob/living/silicon/robot/mommi/MoMMI = new_mob - MoMMI.mmi = new /obj/item/device/mmi(new_mob) - MoMMI.mmi.transfer_identity(M) //Does not transfer key/client. - MoMMI.languages |= M.languages - if(M.default_language) MoMMI.default_language = M.default_language - if("slime") - var/slimey = pick("",\ - "/purple",\ - "/metal",\ - "/orange",\ - "/blue",\ - "/darkblue",\ - "/darkpurple",\ - "/yellow",\ - "/silver",\ - "/pink",\ - "/red",\ - "/gold",\ - "/green",\ - "/lightpink",\ - "/oil",\ - "/black",\ - "/adamantine",\ - "/bluespace",\ - "/pyrite",\ - "/cerulean",\ - "/sepia"\ - ) - - if (prob(50)) - slimey = "/adult[slimey]" - - slimey = text2path("/mob/living/carbon/slime[slimey]") - new_mob = new slimey(M.loc) - new_mob.setGender(M.gender) - var/mob/living/carbon/slime/Slime = new_mob - Slime.languages |= M.languages - if(M.default_language) Slime.default_language = M.default_language - if("xeno") - var/alien_caste = pick("Hunter","Sentinel","Drone","Larva") - switch(alien_caste) - if("Hunter") new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) - if("Sentinel") new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) - if("Drone") new_mob = new /mob/living/carbon/alien/humanoid/drone(M.loc) - else new_mob = new /mob/living/carbon/alien/larva(M.loc) - var/mob/living/carbon/alien/Alien = new_mob - Alien.languages |= M.languages - if(M.default_language) Alien.default_language = M.default_language - if("human") - new_mob = new /mob/living/carbon/human(M.loc, delay_ready_dna=1) - - if((M.gender == MALE) || (M.gender == FEMALE)) //If the transformed mob is MALE or FEMALE - new_mob.setGender(M.gender) //The new human will inherit its gender - else //If its gender is NEUTRAL or PLURAL, - new_mob.setGender(pick(MALE, FEMALE)) //The new human's gender will be random - - var/datum/preferences/A = new() //Randomize appearance for the human - A.randomize_appearance_for(new_mob) - - var/mob/living/carbon/human/H = new_mob - var/newspecies = pick(all_species-/datum/species/krampus) - H.set_species(newspecies) - H.generate_name() - H.languages |= M.languages - if(M.default_language) H.default_language = M.default_language - if("furry") - new_mob = new /mob/living/carbon/human(M.loc, delay_ready_dna=1) - - if((M.gender == MALE) || (M.gender == FEMALE)) //If the transformed mob is MALE or FEMALE - new_mob.setGender(M.gender) //The new human will inherit its gender - else //If its gender is NEUTRAL or PLURAL, - new_mob.setGender(pick(MALE, FEMALE)) //The new human's gender will be random - - var/datum/preferences/A = new() //Randomize appearance for the human - A.randomize_appearance_for(new_mob) - - var/mob/living/carbon/human/H = new_mob - H.set_species("Tajaran") // idfk - H.languages |= M.languages - if(M.default_language) H.default_language = M.default_language - H.generate_name() - /* RIP - if("cluwne") - new_mob = new /mob/living/simple_animal/hostile/retaliate/cluwne(M.loc) - new_mob.setGender(gender) - new_mob.name = pick(clown_names) - new_mob.real_name = new_mob.name - new_mob.mutations += M_CLUMSY - new_mob.mutations += M_FAT - new_mob.setBrainLoss(100) - */ - else - return - if(M.mind && M.mind.wizard_spells && M.mind.wizard_spells.len) - for (var/spell/S in M.mind.wizard_spells) - new_mob.spell_list += new S.type - - new_mob.a_intent = I_HURT - if(M.mind) - M.mind.transfer_to(new_mob) - else - new_mob.key = M.key - - if(iscarbon(M)) - var/mob/living/carbon/I = M - I.transferBorers(new_mob) - - to_chat(new_mob, "Your form morphs into that of a [randomize].") - - qdel(M) - return new_mob - +/obj/item/projectile/change + name = "bolt of change" + icon_state = "ice_1" + damage = 0 + damage_type = BURN + nodamage = 1 + flag = "energy" + var/changetype=null + +/obj/item/projectile/change/on_hit(var/atom/change) + var/type = changetype + spawn(1)//fixes bugs caused by the target ceasing to exist before the projectile has died. + wabbajack(change,type) + + +/obj/item/projectile/change/proc/wabbajack(var/mob/living/M,var/type) //WHY: as mob in living_mob_list + if(istype(M, /mob/living) && M.stat != DEAD) + if(M.monkeyizing) + return + if(istype(M, /mob/living/carbon/human/manifested)) + visible_message("The bolt of change doesn't seem to affect [M] in any way.") + return + + // TODO: This needs to be standardized, sort of a premorph() proc or something. + M.monkeyizing = 1 + M.canmove = 0 + M.icon = null + M.overlays.len = 0 + M.invisibility = 101 + + if(istype(M, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/Robot = M + if(Robot.mmi) + qdel(Robot.mmi) + else + for(var/obj/item/W in M) + if(istype(W, /obj/item/weapon/implant)) + qdel(W) + continue + W.layer = initial(W.layer) + W.loc = M.loc + W.dropped(M) + // END TODO + + var/mob/living/new_mob + + // Random chance of fucking up + if(type!=null && prob(10)) + type = null + + var/randomize = type == null? pick(available_staff_transforms):type + + switch(randomize) + if("monkey") + new_mob = new /mob/living/carbon/monkey(M.loc) + new_mob.setGender(M.gender) + var/mob/living/carbon/monkey/Monkey = new_mob + Monkey.languages |= M.languages + if(M.default_language) Monkey.default_language = M.default_language + if("robot") + new_mob = new /mob/living/silicon/robot(M.loc) + new_mob.setGender(M.gender) + new_mob.invisibility = 0 + new_mob.job = "Cyborg" + var/mob/living/silicon/robot/Robot = new_mob + Robot.mmi = new /obj/item/device/mmi(new_mob) + Robot.mmi.transfer_identity(M) //Does not transfer key/client. + Robot.languages |= M.languages + if(M.default_language) Robot.default_language = M.default_language + if("mommi") + new_mob = new /mob/living/silicon/robot/mommi(M.loc) + new_mob.setGender(M.gender) + new_mob.invisibility = 0 + new_mob.job = "MoMMI" + var/mob/living/silicon/robot/mommi/MoMMI = new_mob + MoMMI.mmi = new /obj/item/device/mmi(new_mob) + MoMMI.mmi.transfer_identity(M) //Does not transfer key/client. + MoMMI.languages |= M.languages + if(M.default_language) MoMMI.default_language = M.default_language + if("slime") + var/slimey = pick("",\ + "/purple",\ + "/metal",\ + "/orange",\ + "/blue",\ + "/darkblue",\ + "/darkpurple",\ + "/yellow",\ + "/silver",\ + "/pink",\ + "/red",\ + "/gold",\ + "/green",\ + "/lightpink",\ + "/oil",\ + "/black",\ + "/adamantine",\ + "/bluespace",\ + "/pyrite",\ + "/cerulean",\ + "/sepia"\ + ) + + if (prob(50)) + slimey = "/adult[slimey]" + + slimey = text2path("/mob/living/carbon/slime[slimey]") + new_mob = new slimey(M.loc) + new_mob.setGender(M.gender) + var/mob/living/carbon/slime/Slime = new_mob + Slime.languages |= M.languages + if(M.default_language) Slime.default_language = M.default_language + if("xeno") + var/alien_caste = pick("Hunter","Sentinel","Drone","Larva") + switch(alien_caste) + if("Hunter") new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) + if("Sentinel") new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) + if("Drone") new_mob = new /mob/living/carbon/alien/humanoid/drone(M.loc) + else new_mob = new /mob/living/carbon/alien/larva(M.loc) + var/mob/living/carbon/alien/Alien = new_mob + Alien.languages |= M.languages + if(M.default_language) Alien.default_language = M.default_language + if("human") + new_mob = new /mob/living/carbon/human(M.loc, delay_ready_dna=1) + + if((M.gender == MALE) || (M.gender == FEMALE)) //If the transformed mob is MALE or FEMALE + new_mob.setGender(M.gender) //The new human will inherit its gender + else //If its gender is NEUTRAL or PLURAL, + new_mob.setGender(pick(MALE, FEMALE)) //The new human's gender will be random + + var/datum/preferences/A = new() //Randomize appearance for the human + A.randomize_appearance_for(new_mob) + + var/mob/living/carbon/human/H = new_mob + var/newspecies = pick(all_species-/datum/species/krampus) + H.set_species(newspecies) + H.generate_name() + H.languages |= M.languages + if(M.default_language) H.default_language = M.default_language + if("furry") + new_mob = new /mob/living/carbon/human(M.loc, delay_ready_dna=1) + + if((M.gender == MALE) || (M.gender == FEMALE)) //If the transformed mob is MALE or FEMALE + new_mob.setGender(M.gender) //The new human will inherit its gender + else //If its gender is NEUTRAL or PLURAL, + new_mob.setGender(pick(MALE, FEMALE)) //The new human's gender will be random + + var/datum/preferences/A = new() //Randomize appearance for the human + A.randomize_appearance_for(new_mob) + + var/mob/living/carbon/human/H = new_mob + H.set_species("Tajaran") // idfk + H.languages |= M.languages + if(M.default_language) H.default_language = M.default_language + H.generate_name() + /* RIP + if("cluwne") + new_mob = new /mob/living/simple_animal/hostile/retaliate/cluwne(M.loc) + new_mob.setGender(gender) + new_mob.name = pick(clown_names) + new_mob.real_name = new_mob.name + new_mob.mutations += M_CLUMSY + new_mob.mutations += M_FAT + new_mob.setBrainLoss(100) + */ + else + return + if(M.mind && M.mind.wizard_spells && M.mind.wizard_spells.len) + for (var/spell/S in M.mind.wizard_spells) + new_mob.spell_list += new S.type + + new_mob.a_intent = I_HURT + if(M.mind) + M.mind.transfer_to(new_mob) + else + new_mob.key = M.key + + if(iscarbon(M)) + var/mob/living/carbon/I = M + I.transferBorers(new_mob) + + to_chat(new_mob, "Your form morphs into that of a [randomize].") + + qdel(M) + return new_mob + diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 87bfb0afb9d..30f75732e29 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -1,150 +1,150 @@ -/obj/item/projectile/energy - name = "energy" - icon_state = "spark" - damage = 0 - layer = 13 - damage_type = BURN - flag = "energy" - - -/obj/item/projectile/energy/electrode - name = "electrode" - icon_state = "spark" - nodamage = 1 - stun = 10 - weaken = 10 - stutter = 10 -/*VG EDIT - agony = 40 - damage_type = HALLOSS -*/ - //Damage will be handled on the MOB side, to prevent window shattering. - - - -/obj/item/projectile/energy/declone - name = "declone" - icon_state = "declone" - damage = 12 - nodamage = 0 - damage_type = CLONE - irradiate = 40 - -/obj/item/projectile/energy/bolt - name = "bolt" - icon_state = "cbbolt" - damage = 10 - damage_type = TOX - nodamage = 0 - weaken = 10 - stutter = 10 - - -/obj/item/projectile/energy/bolt/large - name = "largebolt" - damage = 20 - -/obj/item/projectile/energy/plasma - name = "plasma" - icon_state = "plasma" - var/knockdown_chance = 0 - -/obj/item/projectile/energy/plasma/on_hit(var/atom/target, var/blocked = 0) - if (..(target, blocked)) - var/mob/living/L = target - L.contaminate() - if(prob(knockdown_chance)) - if(istype(target, /mob/living/carbon/)) - shake_camera(L, 3, 2) - L.apply_effect(2, WEAKEN) +/obj/item/projectile/energy + name = "energy" + icon_state = "spark" + damage = 0 + layer = 13 + damage_type = BURN + flag = "energy" + + +/obj/item/projectile/energy/electrode + name = "electrode" + icon_state = "spark" + nodamage = 1 + stun = 10 + weaken = 10 + stutter = 10 +/*VG EDIT + agony = 40 + damage_type = HALLOSS +*/ + //Damage will be handled on the MOB side, to prevent window shattering. + + + +/obj/item/projectile/energy/declone + name = "declone" + icon_state = "declone" + damage = 12 + nodamage = 0 + damage_type = CLONE + irradiate = 40 + +/obj/item/projectile/energy/bolt + name = "bolt" + icon_state = "cbbolt" + damage = 10 + damage_type = TOX + nodamage = 0 + weaken = 10 + stutter = 10 + + +/obj/item/projectile/energy/bolt/large + name = "largebolt" + damage = 20 + +/obj/item/projectile/energy/plasma + name = "plasma" + icon_state = "plasma" + var/knockdown_chance = 0 + +/obj/item/projectile/energy/plasma/on_hit(var/atom/target, var/blocked = 0) + if (..(target, blocked)) + var/mob/living/L = target + L.contaminate() + if(prob(knockdown_chance)) + if(istype(target, /mob/living/carbon/)) + shake_camera(L, 3, 2) + L.apply_effect(2, WEAKEN) to_chat(L, " The force of the bolt knocks you off your feet!") - return 1 - return 0 - -/obj/item/projectile/energy/plasma/pistol - damage = 12 - icon_state = "plasma1" - irradiate = 12 - -/obj/item/projectile/energy/plasma/light - damage = 25 - icon_state = "plasma2" - knockdown_chance = 30 - -/obj/item/projectile/energy/plasma/rifle - damage = 40 - icon_state = "plasma3" - irradiate = 35 - knockdown_chance = 50 - -/obj/item/projectile/energy/plasma/MP40k - damage = 35 - eyeblur = 4 - irradiate = 25 - knockdown_chance = 40 - icon_state = "plasma3" - -/obj/item/projectile/energy/neurotoxin - name = "neuro" - icon_state = "neurotoxin" - damage = 5 - damage_type = TOX - weaken = 5 - -/obj/item/projectile/energy/rad - name = "rad" - icon_state = "rad" - damage = 30 - damage_type = TOX - nodamage = 0 - weaken = 10 - stutter = 10 - - on_hit(var/atom/hit) - if(ishuman(hit)) - - var/mob/living/carbon/human/H = hit - - H.generate_name() - - scramble(1, H, 100) // Scramble all UIs - scramble(null, H, 5) // Scramble SEs, 5% chance for each block - - H.apply_effect((rand(50, 250)),IRRADIATE) - -/obj/item/projectile/energy/buster - name = "buster shot" - icon_state = "buster" - nodamage = 0 - damage = 20 - damage_type = BURN - -/obj/item/projectile/energy/megabuster - name = "buster pellet" - icon_state = "megabuster" - nodamage = 1 - -/obj/item/projectile/energy/osipr - name = "dark energy ball" - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "dark" - kill_count = 100 - damage = 50 - stun = 10 - weaken = 10 - stutter = 10 - jittery = 30 - destroy = 0 - bounce_sound = 'sound/weapons/osipr_altbounce.ogg' - bounce_type = PROJREACT_WALLS|PROJREACT_WINDOWS - bounces = -1 - phase_type = PROJREACT_OBJS|PROJREACT_MOBS - penetration = -1 - -/obj/item/projectile/energy/osipr/Destroy() - var/turf/T = loc - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(4, 0, T) - s.start() - T.turf_animation('icons/obj/projectiles_impacts.dmi',"dark_explosion",0, 0, 13, 'sound/weapons/osipr_altexplosion.ogg') - ..() + return 1 + return 0 + +/obj/item/projectile/energy/plasma/pistol + damage = 12 + icon_state = "plasma1" + irradiate = 12 + +/obj/item/projectile/energy/plasma/light + damage = 25 + icon_state = "plasma2" + knockdown_chance = 30 + +/obj/item/projectile/energy/plasma/rifle + damage = 40 + icon_state = "plasma3" + irradiate = 35 + knockdown_chance = 50 + +/obj/item/projectile/energy/plasma/MP40k + damage = 35 + eyeblur = 4 + irradiate = 25 + knockdown_chance = 40 + icon_state = "plasma3" + +/obj/item/projectile/energy/neurotoxin + name = "neuro" + icon_state = "neurotoxin" + damage = 5 + damage_type = TOX + weaken = 5 + +/obj/item/projectile/energy/rad + name = "rad" + icon_state = "rad" + damage = 30 + damage_type = TOX + nodamage = 0 + weaken = 10 + stutter = 10 + + on_hit(var/atom/hit) + if(ishuman(hit)) + + var/mob/living/carbon/human/H = hit + + H.generate_name() + + scramble(1, H, 100) // Scramble all UIs + scramble(null, H, 5) // Scramble SEs, 5% chance for each block + + H.apply_effect((rand(50, 250)),IRRADIATE) + +/obj/item/projectile/energy/buster + name = "buster shot" + icon_state = "buster" + nodamage = 0 + damage = 20 + damage_type = BURN + +/obj/item/projectile/energy/megabuster + name = "buster pellet" + icon_state = "megabuster" + nodamage = 1 + +/obj/item/projectile/energy/osipr + name = "dark energy ball" + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "dark" + kill_count = 100 + damage = 50 + stun = 10 + weaken = 10 + stutter = 10 + jittery = 30 + destroy = 0 + bounce_sound = 'sound/weapons/osipr_altbounce.ogg' + bounce_type = PROJREACT_WALLS|PROJREACT_WINDOWS + bounces = -1 + phase_type = PROJREACT_OBJS|PROJREACT_MOBS + penetration = -1 + +/obj/item/projectile/energy/osipr/Destroy() + var/turf/T = loc + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(4, 0, T) + s.start() + T.turf_animation('icons/obj/projectiles_impacts.dmi',"dark_explosion",0, 0, 13, 'sound/weapons/osipr_altexplosion.ogg') + ..() diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 331ffac2862..1406ee449da 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -1,333 +1,333 @@ -/obj/item/projectile/ion - name = "ion bolt" - icon_state = "ion" - damage = 0 - damage_type = BURN - nodamage = 1 - layer = 13 - flag = "energy" - -/obj/item/projectile/ion/Bump(atom/A as mob|obj|turf|area) - if(!bumped && ((A != firer) || reflected)) - empulse(get_turf(A), 1, 1) - ..() - -/obj/item/projectile/bullet/gyro - name ="explosive bolt" - icon_state= "bolter" - damage = 50 - flag = "bullet" - -/obj/item/projectile/bullet/gyro/Bump(var/atom/target) //The bullets lose their ability to penetrate (which was pitiful for these ones) but now explode when hitting anything instead of only some things. - explosion(target, -1, 0, 2) - qdel(src) - -/obj/item/projectile/temp - name = "freeze beam" - icon_state = "temp_4" - damage = 0 - damage_type = BURN - nodamage = 1 - layer = 13 - flag = "energy" - var/temperature = 300 - -/obj/item/projectile/temp/OnFired() - ..() - - var/obj/item/weapon/gun/energy/temperature/T = shot_from - if(istype(T)) - src.temperature = T.temperature - - switch(temperature) - if(501 to INFINITY) - name = "searing beam" //if emagged - icon_state = "temp_8" - if(400 to 500) - name = "burning beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_2 - icon_state = "temp_7" - if(360 to 400) - name = "hot beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_1 - icon_state = "temp_6" - if(335 to 360) - name = "warm beam" //temp at which players get notified of their high body temp - icon_state = "temp_5" - if(295 to 335) - name = "ambient beam" - icon_state = "temp_4" - if(260 to 295) - name = "cool beam" //temp at which players get notified of their low body temp - icon_state = "temp_3" - if(200 to 260) - name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1 - icon_state = "temp_2" - if(120 to 260) - name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2 - icon_state = "temp_1" - if(-INFINITY to 120) - name = "freeze beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_3 - icon_state = "temp_0" - else - name = "temperature beam"//failsafe - icon_state = "temp_4" - - -/obj/item/projectile/temp/on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob - if(istype(target, /mob/living)) - var/mob/living/M = target - if(M.flags & INVULNERABLE) - return 0 - M.bodytemperature = temperature - if(temperature > 500)//emagged - M.adjust_fire_stacks(0.5) - M.on_fire = 1 - M.update_icon = 1 - playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0) - return 1 - -//This shouldn't fucking exist, just spawn a meteor damnit -/obj/item/projectile/meteor - name = "meteor" - icon = 'icons/obj/meteor.dmi' - icon_state = "smallf" - damage = 0 - damage_type = BRUTE - nodamage = 1 - flag = "bullet" - -/obj/item/projectile/meteor/Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return - - //Copied straight from small meteor code - spawn(0) - playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 10, 1) - explosion(src.loc, -1, 1, 3, 4, 0) //Tiny meteor doesn't cause too much damage - qdel(src) - -//Simple fireball -/obj/item/projectile/simple_fireball - name = "fireball" - icon_state = "fireball" - animate_movement = 2 - damage = 0 - nodamage = 1 - flag = "bullet" - -/obj/item/projectile/simple_fireball/Bump(atom/A) - explosion(get_turf(src), -1, -1, 2, 2) - return qdel(src) - -/obj/item/projectile/energy/floramut - name = "alpha somatoray" - icon_state = "energy" - damage = 0 - damage_type = TOX - nodamage = 1 - flag = "energy" - var/mutstrength = 10 - -/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) - var/mob/living/M = target -// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //Plantmen possibly get mutated and damaged by the rays. - if(ishuman(target)) - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT)) - if(prob(mutstrength*2)) - M.apply_effect((rand(30,80)),IRRADIATE) - M.Weaken(5) - for (var/mob/V in viewers(src)) - V.show_message("[M] writhes in pain as \his vacuoles boil.", 1, "You hear the crunching of leaves.", 2) - if(prob(mutstrength*3)) - // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan - // V.show_message("[M] is mutated by the radiation beam.", 1, "You hear the snapping of twigs.", 2) - if(prob(80)) - randmutb(M) - domutcheck(M,null) - else - randmutg(M) - domutcheck(M,null) - else - M.adjustFireLoss(rand(mutstrength/3, mutstrength)) - M.show_message("The radiation beam singes you!") - // for (var/mob/V in viewers(src)) - // V.show_message("[M] is singed by the radiation beam.", 1, "You hear the crackle of burning leaves.", 2) - else - M.show_message("The radiation beam dissipates harmlessly through your body.") - else if(istype(target, /mob/living/carbon/)) - // for (var/mob/V in viewers(src)) - // V.show_message("The radiation beam dissipates harmlessly through [M]", 2) //spooky - M.show_message("The radiation beam dissipates harmlessly through your body.") - else - return 1 - -/obj/item/projectile/energy/floramut/emag - name = "gamma somatoray" - icon_state = "energy" - -/obj/item/projectile/energy/florayield - name = "beta somatoray" - icon_state = "energy2" - damage = 0 - damage_type = TOX - nodamage = 1 - flag = "energy" - -/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0) - var/mob/M = target -// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //These rays make plantmen fat. - if(ishuman(target)) //These rays make plantmen fat. - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - M.nutrition += 30 - else - M.show_message("The radiation beam dissipates harmlessly through your body.") - else if (istype(target, /mob/living/carbon/)) - M.show_message("The radiation beam dissipates harmlessly through your body.") - else - return 1 - - -/obj/item/projectile/beam/mindflayer - name = "flayer ray" - -/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) - if(ishuman(target)) - var/mob/living/carbon/human/M = target - M.adjustBrainLoss(20) - M.hallucination += 20 - -/obj/item/projectile/kinetic - name = "kinetic force" - icon_state = "energy" - damage = 15 - damage_type = BRUTE - flag = "energy" - var/range = 2 - -obj/item/projectile/kinetic/New() - var/turf/proj_turf = get_turf(src) - if(!istype(proj_turf, /turf)) - return - var/datum/gas_mixture/environment = proj_turf.return_air() - var/pressure = environment.return_pressure() - if(pressure < 50) - name = "full strength kinetic force" - damage = 30 - ..() - -/* wat - N3X -/obj/item/projectile/kinetic/Range() - range-- - if(range <= 0) - new /obj/item/effect/kinetic_blast(src.loc) - qdel(src) -*/ - -/obj/item/projectile/kinetic/on_hit(var/atom/target, var/blocked = 0) - if(!loc) return - var/turf/target_turf = get_turf(target) - //testing("Hit [target.type], on [target_turf.type].") - if(istype(target_turf, /turf/unsimulated/mineral)) - var/turf/unsimulated/mineral/M = target_turf - M.GetDrilled() - new /obj/item/effect/kinetic_blast(target_turf) - ..(target,blocked) - -/obj/item/projectile/kinetic/Bump(atom/A as mob|obj|turf|area) - if(!loc) return - if(A == firer) - loc = A.loc - return - - if(src)//Do not add to this if() statement, otherwise the meteor won't delete them - - if(A) - var/turf/target_turf = get_turf(A) - //testing("Bumped [A.type], on [target_turf.type].") - if(istype(target_turf, /turf/unsimulated/mineral)) - var/turf/unsimulated/mineral/M = target_turf - M.GetDrilled() - // Now we bump as a bullet, if the atom is a non-turf. - if(!isturf(A)) - ..(A) - //qdel(src) // Comment this out if you want to shoot through the asteroid, ERASER-style. - returnToPool(src) - return 1 - else - //qdel(src) - returnToPool(src) - return 0 - -/obj/item/effect/kinetic_blast - name = "kinetic explosion" - icon = 'icons/obj/projectiles.dmi' - icon_state = "kinetic_blast" - layer = 4.1 - -/obj/item/effect/kinetic_blast/New() - ..() - spawn(4) - returnToPool(src) - -/obj/item/projectile/stickybomb - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "stickybomb" - damage = 0 - var/obj/item/stickybomb/sticky = null - - -/obj/item/projectile/stickybomb/Bump(atom/A as mob|obj|turf|area) - if(bumped) return 0 - bumped = 1 - - if(A) - density = 0 - invisibility = 101 - kill_count = 0 - if(isliving(A)) - sticky.stick_to(A) - else if(loc) - var/turf/T = get_turf(src) - sticky.stick_to(T,get_dir(src,A)) - bullet_die() - -/obj/item/projectile/stickybomb/bump_original_check()//so players can aim at floors - if(!bumped) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - -/obj/item/projectile/portalgun - name = "portal gun shot" - icon = 'icons/obj/projectiles_experimental.dmi' - icon_state = "portalgun" - damage = 0 - nodamage = 1 - kill_count = 500//enough to cross a ZLevel...twice! - var/setting = 0 - -/obj/item/projectile/portalgun/bump_original_check()//so players can aim at floors - if(!bumped) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - -/obj/item/projectile/portalgun/Bump(atom/A as mob|obj|turf|area) - if(bumped) - return - bumped = 1 - - if(!istype(shot_from,/obj/item/weapon/gun/portalgun)) - bullet_die() - return - - var/obj/item/weapon/gun/portalgun/P = shot_from - - if(isliving(A)) - forceMove(get_step(loc,dir)) - - if(!(locate(/obj/effect/portal) in loc)) - P.open_portal(setting,loc,A) - bullet_die() +/obj/item/projectile/ion + name = "ion bolt" + icon_state = "ion" + damage = 0 + damage_type = BURN + nodamage = 1 + layer = 13 + flag = "energy" + +/obj/item/projectile/ion/Bump(atom/A as mob|obj|turf|area) + if(!bumped && ((A != firer) || reflected)) + empulse(get_turf(A), 1, 1) + ..() + +/obj/item/projectile/bullet/gyro + name ="explosive bolt" + icon_state= "bolter" + damage = 50 + flag = "bullet" + +/obj/item/projectile/bullet/gyro/Bump(var/atom/target) //The bullets lose their ability to penetrate (which was pitiful for these ones) but now explode when hitting anything instead of only some things. + explosion(target, -1, 0, 2) + qdel(src) + +/obj/item/projectile/temp + name = "freeze beam" + icon_state = "temp_4" + damage = 0 + damage_type = BURN + nodamage = 1 + layer = 13 + flag = "energy" + var/temperature = 300 + +/obj/item/projectile/temp/OnFired() + ..() + + var/obj/item/weapon/gun/energy/temperature/T = shot_from + if(istype(T)) + src.temperature = T.temperature + + switch(temperature) + if(501 to INFINITY) + name = "searing beam" //if emagged + icon_state = "temp_8" + if(400 to 500) + name = "burning beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_2 + icon_state = "temp_7" + if(360 to 400) + name = "hot beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_1 + icon_state = "temp_6" + if(335 to 360) + name = "warm beam" //temp at which players get notified of their high body temp + icon_state = "temp_5" + if(295 to 335) + name = "ambient beam" + icon_state = "temp_4" + if(260 to 295) + name = "cool beam" //temp at which players get notified of their low body temp + icon_state = "temp_3" + if(200 to 260) + name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1 + icon_state = "temp_2" + if(120 to 260) + name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2 + icon_state = "temp_1" + if(-INFINITY to 120) + name = "freeze beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_3 + icon_state = "temp_0" + else + name = "temperature beam"//failsafe + icon_state = "temp_4" + + +/obj/item/projectile/temp/on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob + if(istype(target, /mob/living)) + var/mob/living/M = target + if(M.flags & INVULNERABLE) + return 0 + M.bodytemperature = temperature + if(temperature > 500)//emagged + M.adjust_fire_stacks(0.5) + M.on_fire = 1 + M.update_icon = 1 + playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0) + return 1 + +//This shouldn't fucking exist, just spawn a meteor damnit +/obj/item/projectile/meteor + name = "meteor" + icon = 'icons/obj/meteor.dmi' + icon_state = "smallf" + damage = 0 + damage_type = BRUTE + nodamage = 1 + flag = "bullet" + +/obj/item/projectile/meteor/Bump(atom/A as mob|obj|turf|area) + if(A == firer) + loc = A.loc + return + + //Copied straight from small meteor code + spawn(0) + playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 10, 1) + explosion(src.loc, -1, 1, 3, 4, 0) //Tiny meteor doesn't cause too much damage + qdel(src) + +//Simple fireball +/obj/item/projectile/simple_fireball + name = "fireball" + icon_state = "fireball" + animate_movement = 2 + damage = 0 + nodamage = 1 + flag = "bullet" + +/obj/item/projectile/simple_fireball/Bump(atom/A) + explosion(get_turf(src), -1, -1, 2, 2) + return qdel(src) + +/obj/item/projectile/energy/floramut + name = "alpha somatoray" + icon_state = "energy" + damage = 0 + damage_type = TOX + nodamage = 1 + flag = "energy" + var/mutstrength = 10 + +/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) + var/mob/living/M = target +// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //Plantmen possibly get mutated and damaged by the rays. + if(ishuman(target)) + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT)) + if(prob(mutstrength*2)) + M.apply_effect((rand(30,80)),IRRADIATE) + M.Weaken(5) + for (var/mob/V in viewers(src)) + V.show_message("[M] writhes in pain as \his vacuoles boil.", 1, "You hear the crunching of leaves.", 2) + if(prob(mutstrength*3)) + // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan + // V.show_message("[M] is mutated by the radiation beam.", 1, "You hear the snapping of twigs.", 2) + if(prob(80)) + randmutb(M) + domutcheck(M,null) + else + randmutg(M) + domutcheck(M,null) + else + M.adjustFireLoss(rand(mutstrength/3, mutstrength)) + M.show_message("The radiation beam singes you!") + // for (var/mob/V in viewers(src)) + // V.show_message("[M] is singed by the radiation beam.", 1, "You hear the crackle of burning leaves.", 2) + else + M.show_message("The radiation beam dissipates harmlessly through your body.") + else if(istype(target, /mob/living/carbon/)) + // for (var/mob/V in viewers(src)) + // V.show_message("The radiation beam dissipates harmlessly through [M]", 2) //spooky + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 + +/obj/item/projectile/energy/floramut/emag + name = "gamma somatoray" + icon_state = "energy" + +/obj/item/projectile/energy/florayield + name = "beta somatoray" + icon_state = "energy2" + damage = 0 + damage_type = TOX + nodamage = 1 + flag = "energy" + +/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0) + var/mob/M = target +// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //These rays make plantmen fat. + if(ishuman(target)) //These rays make plantmen fat. + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + M.nutrition += 30 + else + M.show_message("The radiation beam dissipates harmlessly through your body.") + else if (istype(target, /mob/living/carbon/)) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 + + +/obj/item/projectile/beam/mindflayer + name = "flayer ray" + +/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) + var/mob/living/carbon/human/M = target + M.adjustBrainLoss(20) + M.hallucination += 20 + +/obj/item/projectile/kinetic + name = "kinetic force" + icon_state = "energy" + damage = 15 + damage_type = BRUTE + flag = "energy" + var/range = 2 + +obj/item/projectile/kinetic/New() + var/turf/proj_turf = get_turf(src) + if(!istype(proj_turf, /turf)) + return + var/datum/gas_mixture/environment = proj_turf.return_air() + var/pressure = environment.return_pressure() + if(pressure < 50) + name = "full strength kinetic force" + damage = 30 + ..() + +/* wat - N3X +/obj/item/projectile/kinetic/Range() + range-- + if(range <= 0) + new /obj/item/effect/kinetic_blast(src.loc) + qdel(src) +*/ + +/obj/item/projectile/kinetic/on_hit(var/atom/target, var/blocked = 0) + if(!loc) return + var/turf/target_turf = get_turf(target) + //testing("Hit [target.type], on [target_turf.type].") + if(istype(target_turf, /turf/unsimulated/mineral)) + var/turf/unsimulated/mineral/M = target_turf + M.GetDrilled() + new /obj/item/effect/kinetic_blast(target_turf) + ..(target,blocked) + +/obj/item/projectile/kinetic/Bump(atom/A as mob|obj|turf|area) + if(!loc) return + if(A == firer) + loc = A.loc + return + + if(src)//Do not add to this if() statement, otherwise the meteor won't delete them + + if(A) + var/turf/target_turf = get_turf(A) + //testing("Bumped [A.type], on [target_turf.type].") + if(istype(target_turf, /turf/unsimulated/mineral)) + var/turf/unsimulated/mineral/M = target_turf + M.GetDrilled() + // Now we bump as a bullet, if the atom is a non-turf. + if(!isturf(A)) + ..(A) + //qdel(src) // Comment this out if you want to shoot through the asteroid, ERASER-style. + returnToPool(src) + return 1 + else + //qdel(src) + returnToPool(src) + return 0 + +/obj/item/effect/kinetic_blast + name = "kinetic explosion" + icon = 'icons/obj/projectiles.dmi' + icon_state = "kinetic_blast" + layer = 4.1 + +/obj/item/effect/kinetic_blast/New() + ..() + spawn(4) + returnToPool(src) + +/obj/item/projectile/stickybomb + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "stickybomb" + damage = 0 + var/obj/item/stickybomb/sticky = null + + +/obj/item/projectile/stickybomb/Bump(atom/A as mob|obj|turf|area) + if(bumped) return 0 + bumped = 1 + + if(A) + density = 0 + invisibility = 101 + kill_count = 0 + if(isliving(A)) + sticky.stick_to(A) + else if(loc) + var/turf/T = get_turf(src) + sticky.stick_to(T,get_dir(src,A)) + bullet_die() + +/obj/item/projectile/stickybomb/bump_original_check()//so players can aim at floors + if(!bumped) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original) + +/obj/item/projectile/portalgun + name = "portal gun shot" + icon = 'icons/obj/projectiles_experimental.dmi' + icon_state = "portalgun" + damage = 0 + nodamage = 1 + kill_count = 500//enough to cross a ZLevel...twice! + var/setting = 0 + +/obj/item/projectile/portalgun/bump_original_check()//so players can aim at floors + if(!bumped) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original) + +/obj/item/projectile/portalgun/Bump(atom/A as mob|obj|turf|area) + if(bumped) + return + bumped = 1 + + if(!istype(shot_from,/obj/item/weapon/gun/portalgun)) + bullet_die() + return + + var/obj/item/weapon/gun/portalgun/P = shot_from + + if(isliving(A)) + forceMove(get_step(loc,dir)) + + if(!(locate(/obj/effect/portal) in loc)) + P.open_portal(setting,loc,A) + bullet_die() diff --git a/code/modules/reagents/Chemistry-Colours.dm b/code/modules/reagents/Chemistry-Colours.dm index 60106435bca..9b171e87775 100644 --- a/code/modules/reagents/Chemistry-Colours.dm +++ b/code/modules/reagents/Chemistry-Colours.dm @@ -1,66 +1,66 @@ -/* - * Returns: - * #RRGGBB(AA) on success, null on failure - */ -/proc/mix_color_from_reagents(const/list/reagent_list) - if(!istype(reagent_list)) - return - - var/color - var/reagent_color - var/vol_counter = 0 - var/vol_temp - // see libs/IconProcs/IconProcs.dm - for(var/datum/reagent/reagent in reagent_list) - if(reagent.id == "blood" && reagent.data["blood_colour"]) - reagent_color = reagent.data["blood_colour"] - else - reagent_color = reagent.color - - vol_temp = reagent.volume - vol_counter += vol_temp - - if(isnull(color)) - color = reagent.color - else if(length(color) >= length(reagent_color)) - color = BlendRGB(color, reagent_color, vol_temp/vol_counter) - else - color = BlendRGB(reagent_color, color, vol_temp/vol_counter) - - return color - -/proc/mix_alpha_from_reagents(const/list/reagent_list) - if(!istype(reagent_list)) - return - - var/alpha - var/total_alpha - - for(var/datum/reagent/reagent in reagent_list) - total_alpha += reagent.alpha - - alpha = total_alpha / reagent_list.len - - return alpha - -/proc/get_reagent_name(var/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/DG) - if(!DG) - return - - var/list/reagent_list = DG.reagents.reagent_list - - if(!reagent_list.len) - DG.name = "glass of...nothing?" - DG.desc = "You can't see anything inside that glass, odd"//this shouldn't ever happen - else if(reagent_list.len > 4) - DG.name = "mixture of chemicals" - DG.desc = "There's too many different chemicals in the glass, you cannot tell them apart." - DG.viewcontents = 0 - else - var/highest_quantity = 0 - for(var/datum/reagent/reagent in reagent_list) - var/new_reag = DG.reagents.get_reagent_amount(reagent.id) - if(new_reag > highest_quantity) - highest_quantity = new_reag - DG.name = "glass of [reagent.name]" - DG.desc = reagent.description +/* + * Returns: + * #RRGGBB(AA) on success, null on failure + */ +/proc/mix_color_from_reagents(const/list/reagent_list) + if(!istype(reagent_list)) + return + + var/color + var/reagent_color + var/vol_counter = 0 + var/vol_temp + // see libs/IconProcs/IconProcs.dm + for(var/datum/reagent/reagent in reagent_list) + if(reagent.id == "blood" && reagent.data["blood_colour"]) + reagent_color = reagent.data["blood_colour"] + else + reagent_color = reagent.color + + vol_temp = reagent.volume + vol_counter += vol_temp + + if(isnull(color)) + color = reagent.color + else if(length(color) >= length(reagent_color)) + color = BlendRGB(color, reagent_color, vol_temp/vol_counter) + else + color = BlendRGB(reagent_color, color, vol_temp/vol_counter) + + return color + +/proc/mix_alpha_from_reagents(const/list/reagent_list) + if(!istype(reagent_list)) + return + + var/alpha + var/total_alpha + + for(var/datum/reagent/reagent in reagent_list) + total_alpha += reagent.alpha + + alpha = total_alpha / reagent_list.len + + return alpha + +/proc/get_reagent_name(var/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/DG) + if(!DG) + return + + var/list/reagent_list = DG.reagents.reagent_list + + if(!reagent_list.len) + DG.name = "glass of...nothing?" + DG.desc = "You can't see anything inside that glass, odd"//this shouldn't ever happen + else if(reagent_list.len > 4) + DG.name = "mixture of chemicals" + DG.desc = "There's too many different chemicals in the glass, you cannot tell them apart." + DG.viewcontents = 0 + else + var/highest_quantity = 0 + for(var/datum/reagent/reagent in reagent_list) + var/new_reag = DG.reagents.get_reagent_amount(reagent.id) + if(new_reag > highest_quantity) + highest_quantity = new_reag + DG.name = "glass of [reagent.name]" + DG.desc = reagent.description diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 94e7b1b226e..ee5ea7a27f4 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -1,2103 +1,2103 @@ -#define SOLID 1 -#define LIQUID 2 -#define GAS 3 -#define FORMAT_DISPENSER_NAME 15 - -/obj/machinery/chem_dispenser - name = "\improper Chem Dispenser" - density = 1 - anchored = 1 - icon = 'icons/obj/chemical.dmi' - icon_state = "dispenser" - use_power = 1 - idle_power_usage = 40 - var/energy = 0 - var/max_energy = 50 - var/rechargerate = 2 - var/amount = 30 - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/recharged = 0 - var/custom = 0 - var/useramount = 30 // Last used amount - var/list/dispensable_reagents = list("hydrogen","lithium","carbon","nitrogen","oxygen","fluorine", - "sodium","aluminum","silicon","phosphorus","sulfur","chlorine","potassium","iron", - "copper","mercury","radium","water","ethanol","sugar","sacid","tungsten") - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - var/targetMoveKey = null //To prevent borgs from leaving without their beakers. - - -/* -USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY -*/ - -/obj/machinery/chem_dispenser/mapping - max_energy = 100 - energy = 100 - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -/obj/machinery/chem_dispenser/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/chem_dispenser, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - - RefreshParts() - dispensable_reagents = sortList(dispensable_reagents) - -/obj/machinery/chem_dispenser/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - T += M.rating-1 - max_energy = initial(max_energy)+(T * 50 / 4) - - T = 0 - for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts) - T += Ma.rating-1 - rechargerate = initial(rechargerate) + (T / 2) - -/* - for(var/obj/item/weapon/stock_parts/scanning_module/Ml in component_parts) - T += Ml.rating - //Who even knows what to use the scanning module for -*/ - -/obj/machinery/chem_dispenser/proc/user_moved(var/list/args) - var/event/E = args["event"] - if(!targetMoveKey) - E.handlers.Remove("\ref[src]:user_moved") - return - - var/turf/T = args["loc"] - - if(!Adjacent(T)) - if(E.holder) - E.holder.on_moved.Remove(targetMoveKey) - detach() - -/obj/machinery/chem_dispenser/proc/recharge() - if(stat & (BROKEN|NOPOWER)) return - var/oldenergy = energy - energy = min(energy + rechargerate, max_energy) - if(energy != oldenergy) - use_power(3000) // This thing uses up alot of power (this is still low as shit for creating reagents from thin air) - nanomanager.update_uis(src) // update all UIs attached to src - -/obj/machinery/chem_dispenser/power_change() - if(powered()) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - stat |= NOPOWER - nanomanager.update_uis(src) // update all UIs attached to src - -/obj/machinery/chem_dispenser/proc/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && !istype(R.module,/obj/item/weapon/robot_module/medical)) //default chem dispenser can only be used by MoMMIs and Mediborgs - return 0 - else - if(!isMoMMI(R)) - targetMoveKey = R.on_moved.Add(src, "user_moved") - return 1 - -/obj/machinery/chem_dispenser/process() - if(recharged < 0) - recharge() - recharged = 15 - else - recharged -= 1 - -/obj/machinery/chem_dispenser/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - -/obj/machinery/chem_dispenser/blob_act() - if (prob(50)) - qdel(src) - - /** - * The ui_interact proc is used to open and update Nano UIs - * If ui_interact is not used then the UI will not update correctly - * ui_interact is currently defined for /atom/movable - * - * @param user /mob The mob who is interacting with this ui - * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") - * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui - * - * @return nothing - */ -/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - if(stat & (BROKEN|NOPOWER)) return - if((user.stat && !isobserver(user)) || user.restrained()) return - if(!chemical_reagents_list || !chemical_reagents_list.len) return - // this is the data which will be sent to the ui - var/data[0] - data["amount"] = amount - data["energy"] = energy - data["maxEnergy"] = max_energy - data["isBeakerLoaded"] = beaker ? 1 : 0 - data["custom"] = custom - - var beakerContents[0] - var beakerCurrentVolume = 0 - if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... - beakerCurrentVolume += R.volume - data["beakerContents"] = beakerContents - - if (beaker) - data["beakerCurrentVolume"] = beakerCurrentVolume - data["beakerMaxVolume"] = beaker.volume - else - data["beakerCurrentVolume"] = null - data["beakerMaxVolume"] = null - - var chemicals[0] - for (var/re in dispensable_reagents) - var/datum/reagent/temp = chemical_reagents_list[re] - if(temp) //formats name because Space Mountain Wind and theoretically others in the future are too long - chemicals.Add(list(list("title" = copytext(temp.name,1,FORMAT_DISPENSER_NAME), "id" = temp.id, "commands" = list("dispense" = temp.id)))) // list in a list because Byond merges the first list... - data["chemicals"] = chemicals - // update the ui if it exists, returns null if no ui is passed/found - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "chem_dispenser.tmpl", "[src.name] 5000", 390, 630) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - -/obj/machinery/chem_dispenser/Topic(href, href_list) - if(..()) - return - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - if(stat & (NOPOWER|BROKEN)) - return 0 // don't update UIs attached to this object - - if(href_list["amount"]) - if(href_list["amount"] == "0") - var/num = input("Enter desired output amount", "Amount", useramount) as num - if (num) - amount = round(text2num(num), 5) - custom = 1 - else - custom = 0 - amount = round(text2num(href_list["amount"]), 5) // round to nearest 5 - amount = Clamp(amount, 5, 100) // Since the user can actually type the commands himself, some sanity checking - if (custom) - useramount = amount - - if(href_list["dispense"]) - if (dispensable_reagents.Find(href_list["dispense"]) && beaker != null) - var/obj/item/weapon/reagent_containers/glass/B = src.beaker - var/datum/reagents/R = B.reagents - if(!R) - if(!B.gcDestroyed) - B.create_reagents(B.volume) - else - qdel(B) - B = null - return - var/space = R.maximum_volume - R.total_volume - - R.add_reagent(href_list["dispense"], min(amount, energy * 10, space)) - energy = max(energy - min(amount, energy * 10, space) / 10, 0) - - if(href_list["ejectBeaker"]) - if(beaker) - detach() - - add_fingerprint(usr) - return 1 // update UIs attached to this object - -/obj/machinery/chem_dispenser/proc/detach() - targetMoveKey=null - - if(beaker) - var/obj/item/weapon/reagent_containers/glass/B = beaker - B.loc = loc - if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) - var/mob/living/silicon/robot/R = beaker:holder:loc - if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) - beaker.loc = R - else - beaker.loc = beaker:holder - beaker = null - return 1 - -/obj/machinery/chem_dispenser/AltClick() - if(usr.canmove && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && beaker && !(stat & (NOPOWER|BROKEN) && usr.dexterity_check())) - detach() - return - return ..() - -/obj/machinery/chem_dispenser/togglePanelOpen(var/obj/toggleitem, mob/user) - if(beaker) - to_chat(user, "You can't reach the maintenance panel with a beaker in the way!") - return - return ..() - -/obj/machinery/chem_dispenser/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) //to be worked on - - if(..()) - return 1 - - if(isrobot(user)) - if(!can_use(user)) - return - - if(istype(D, /obj/item/weapon/reagent_containers/glass)) - if(src.beaker) - to_chat(user, "A beaker is already loaded into the machine.") - return - else if(!panel_open) - if(!user.drop_item(D, src)) - to_chat(user, "You can't let go of \the [D]!") - return - - src.beaker = D - if(user.type == /mob/living/silicon/robot) - var/mob/living/silicon/robot/R = user - R.uneq_active() - - to_chat(user, "You add the beaker to the machine!") - - nanomanager.update_uis(src) // update all UIs attached to src - return 1 - else - to_chat(user, "You can't add a beaker to the machine while the panel is open.") - return - -/obj/machinery/chem_dispenser/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/chem_dispenser/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/chem_dispenser/attack_hand(mob/user as mob) - if(stat & BROKEN) - return - - ui_interact(user) -//Cafe stuff - -/obj/machinery/chem_dispenser/brewer/ - name = "Space-Brewery" - icon_state = "brewer" - dispensable_reagents = list("tea","greentea","redtea", "coffee","milk","cream","water","hot_coco", "soymilk") -/obj/machinery/chem_dispenser/brewer/New() - . = ..() - component_parts = newlist( - /obj/item/weapon/circuitboard/chem_dispenser/brewer, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - RefreshParts() - -/obj/machinery/chem_dispenser/brewer/mapping - max_energy = 100 - energy = 100 - -/obj/machinery/chem_dispenser/brewer/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs - targetMoveKey = R.on_moved.Add(src, "user_moved") - return 1 - else - return 0 - -//Soda/booze dispensers. - -/obj/machinery/chem_dispenser/soda_dispenser/ - name = "Soda Dispenser" - icon_state = "soda_dispenser" - dispensable_reagents = list("spacemountainwind", "sodawater", "lemon_lime", "dr_gibb", "cola", "ice", "tonic") -/obj/machinery/chem_dispenser/soda_dispenser/New() - . = ..() - component_parts = newlist( - /obj/item/weapon/circuitboard/chem_dispenser/soda_dispenser, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - RefreshParts() - -/obj/machinery/chem_dispenser/soda_dispenser/mapping - max_energy = 100 - energy = 100 - -/obj/machinery/chem_dispenser/soda_dispenser/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs - targetMoveKey = R.on_moved.Add(src, "user_moved") - return 1 - else - return 0 - -/obj/machinery/chem_dispenser/booze_dispenser/ - name = "Booze Dispenser" - icon_state = "booze_dispenser" - dispensable_reagents = list("beer", "whiskey", "tequila", "vodka", "vermouth", "rum", "cognac", "wine", "kahlua", "ale", "ice", "water", "gin", "sodawater", "cola", "cream","tomatojuice","orangejuice","limejuice","tonic") -/obj/machinery/chem_dispenser/booze_dispenser/New() - . = ..() - component_parts = newlist( - /obj/item/weapon/circuitboard/chem_dispenser/booze_dispenser, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen - ) - RefreshParts() - -/obj/machinery/chem_dispenser/booze_dispenser/mapping - max_energy = 100 - energy = 100 - -/obj/machinery/chem_dispenser/booze_dispenser/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs - targetMoveKey = R.on_moved.Add(src, "user_moved") - return 1 - else - return 0 - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/obj/machinery/chem_master - name = "\improper ChemMaster 3000" - density = 1 - anchored = 1 - icon = 'icons/obj/chemical.dmi' - icon_state = "mixer" - use_power = 1 - idle_power_usage = 20 - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/obj/item/weapon/storage/pill_bottle/loaded_pill_bottle = null - var/mode = 0 - var/condi = 0 - var/windowtype = "chem_master" //For the browser windows - var/useramount = 30 // Last used amount - //var/bottlesprite = "1" //yes, strings - var/pillsprite = "1" - - var/client/has_sprites = list() - var/chem_board = /obj/item/weapon/circuitboard/chemmaster3000 - var/max_bottle_size = 30 - var/max_pill_count = 20 - - light_color = LIGHT_COLOR_BLUE - light_range_on = 3 - light_power_on = 2 - use_auto_lights = 1 - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - var/targetMoveKey - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ - -/obj/machinery/chem_master/New() - . = ..() - - create_reagents(100) - - component_parts = newlist( - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/console_screen - ) - - component_parts += new chem_board - - RefreshParts() - update_icon() //Needed to add the prongs cleanly - -/obj/machinery/chem_master/RefreshParts() - var/scancount = 0 - var/lasercount = 0 - var/manipcount = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - if(istype(SP, /obj/item/weapon/stock_parts/manipulator)) manipcount += SP.rating-1 - if(istype(SP, /obj/item/weapon/stock_parts/scanning_module)) scancount += SP.rating-1 - if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 - max_bottle_size = initial(max_bottle_size) + lasercount*5 - max_pill_count = initial(max_pill_count) + manipcount*5 - handle_new_reservoir(scancount*25+100) - -/obj/machinery/chem_master/proc/handle_new_reservoir(var/newvol) - if(reagents.maximum_volume == newvol) return //Volume did not change - if(reagents.maximum_volume>newvol) - reagents.remove_any(reagents.maximum_volume-newvol) //If we have more than our new max, remove equally until we reach new max - reagents.maximum_volume = newvol - -/obj/machinery/chem_master/proc/user_moved(var/list/args) - var/event/E = args["event"] - if(!targetMoveKey) - E.handlers.Remove("\ref[src]:user_moved") - return - - var/turf/T = args["loc"] - - if(!Adjacent(T)) - if(E.holder) - E.holder.on_moved.Remove(targetMoveKey) - detach() - -/obj/machinery/chem_master/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if(prob(50)) - qdel(src) - return - -/obj/machinery/chem_master/blob_act() - if(prob(50)) - qdel(src) - -/obj/machinery/chem_master/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob) - if(..()) - return 1 - - else if(istype(B, /obj/item/weapon/reagent_containers/glass)) - - if(src.beaker) - to_chat(user, "There already is a beaker loaded in the machine.") - return - if(!user.drop_item(B, src)) - to_chat(user, "You can't let go of \the [B]!") - return - - src.beaker = B - if(user.type == /mob/living/silicon/robot) - var/mob/living/silicon/robot/R = user - R.uneq_active() - targetMoveKey = R.on_moved.Add(src, "user_moved") - - to_chat(user, "You add the beaker into \the [src]!") - - src.updateUsrDialog() - update_icon() - return 1 - - else if(istype(B, /obj/item/weapon/storage/pill_bottle)) - if(windowtype != "chem_master") //Only the chemmaster will accept pill bottles - to_chat(user, "This [name] does not come with a pill dispenser unit built-in.") - return - if(src.loaded_pill_bottle) - to_chat(user, "There already is a pill bottle loaded in the machine.") - return - if(!user.drop_item(B, src)) - to_chat(user, "You can't let go of \the [B]!") - return - - src.loaded_pill_bottle = B - - to_chat(user, "You add the pill bottle into \the [src]'s dispenser slot!") - - src.updateUsrDialog() - return 1 - -/obj/machinery/chem_master/Topic(href, href_list) - - if(..()) - return 1 - - usr.set_machine(src) - - if(href_list["ejectp"]) - if(loaded_pill_bottle) - loaded_pill_bottle.loc = src.loc - loaded_pill_bottle = null - src.updateUsrDialog() - return 1 - - else if(href_list["close"]) - usr << browse(null, "window=[windowtype]") - usr.unset_machine() - return 1 - - if(beaker) - var/datum/reagents/R = beaker.reagents - if(href_list["analyze"]) - var/dat = list() - if(!condi) - if(href_list["name"] == "Blood") - var/datum/reagent/blood/G - for(var/datum/reagent/F in R.reagent_list) - if(F.name == href_list["name"]) - G = F - break - var/A = G.name - var/B = G.data["blood_type"] - var/C = G.data["blood_DNA"] - dat += "Chemical infos:

    Name:
    [A]

    Description:
    Blood Type: [B]
    DNA: [C]


    (Back)" - else - dat += "Chemical infos:

    Name:
    [href_list["name"]]

    Description:
    [href_list["desc"]]


    (Back)" - else - dat += "Condiment infos:

    Name:
    [href_list["name"]]

    Description:
    [href_list["desc"]]


    (Back)" - //usr << browse(dat, "window=chem_master;size=575x400") - dat = list2text(dat) - var/datum/browser/popup = new(usr, "[windowtype]", "[name]", 585, 400, src) - popup.set_content(dat) - popup.open() - onclose(usr, "[windowtype]") - return 1 - - else if(href_list["add"]) - - if(href_list["amount"]) - var/id = href_list["add"] - var/amount = text2num(href_list["amount"]) - if(amount < 0) - return - R.trans_id_to(src, id, amount) - src.updateUsrDialog() - return 1 - - else if(href_list["addcustom"]) - - var/id = href_list["addcustom"] - useramount = input("Select the amount to transfer.", 30, useramount) as num - useramount = isgoodnumber(useramount) - src.Topic(null, list("amount" = "[useramount]", "add" = "[id]")) - src.updateUsrDialog() - return 1 - - else if(href_list["remove"]) - - if(href_list["amount"]) - var/id = href_list["remove"] - var/amount = text2num(href_list["amount"]) - if(amount < 0) - return - if(mode) - reagents.trans_id_to(beaker, id, amount) - else - reagents.remove_reagent(id, amount) - src.updateUsrDialog() - return 1 - - else if(href_list["removecustom"]) - - var/id = href_list["removecustom"] - useramount = input("Select the amount to transfer.", 30, useramount) as num - useramount = isgoodnumber(useramount) - src.Topic(null, list("amount" = "[useramount]", "remove" = "[id]")) - src.updateUsrDialog() - return 1 - - else if(href_list["toggle"]) - mode = !mode - src.updateUsrDialog() - return 1 - - else if(href_list["main"]) - attack_hand(usr) - src.updateUsrDialog() - return 1 - - else if(href_list["eject"]) - if(beaker) - detach() - src.updateUsrDialog() - return 1 - - else if(href_list["createpill"] || href_list["createpill_multiple"]) - var/count = 1 - if(href_list["createpill_multiple"]) count = isgoodnumber(input("Select the number of pills to make.", 10, max_pill_count) as num) - count = min(max_pill_count, count) - if(!count) - return - - var/amount_per_pill = reagents.total_volume/count - if(amount_per_pill > 50) - amount_per_pill = 50 - if(href_list["createempty"]) - amount_per_pill = 0 //If "createempty" is 1, pills are empty and no reagents are used. - - var/name = reject_bad_text(input(usr,"Name:","Name your pill!","[reagents.get_master_reagent_name()] ([amount_per_pill] units)") as null|text) - if(!name) - return - while(count--) - if((amount_per_pill == 0 || reagents.total_volume == 0) && !href_list["createempty"]) //Don't create empty pills unless "createempty" is 1! - break - - var/obj/item/weapon/reagent_containers/pill/P = new/obj/item/weapon/reagent_containers/pill(src.loc) - if(!name) - name = "[reagents.get_master_reagent_name()] ([amount_per_pill] units)" - P.name = "[name] pill" - P.pixel_x = rand(-7, 7) //Random position - P.pixel_y = rand(-7, 7) - P.icon_state = "pill"+pillsprite - reagents.trans_to(P,amount_per_pill) - if(src.loaded_pill_bottle) - if(loaded_pill_bottle.contents.len < loaded_pill_bottle.storage_slots) - P.loc = loaded_pill_bottle - - src.updateUsrDialog() - return 1 - - else if (href_list["createbottle"] || href_list["createbottle_multiple"]) - if(!condi) - var/name = reject_bad_text(input(usr,"Name:", "Name your bottle!", reagents.get_master_reagent_name())) - if(!name) - name = reagents.get_master_reagent_name() - var/count = 1 - if(href_list["createbottle_multiple"]) - count = isgoodnumber(input("Select the number of bottles to make.", 10, count) as num) - if(count > 4) - count = 4 - if(count < 1) - count = 1 - var/amount_per_bottle = reagents.total_volume > 0 ? reagents.total_volume/count : 0 - amount_per_bottle = min(amount_per_bottle,max_bottle_size) - while(count--) - var/obj/item/weapon/reagent_containers/glass/bottle/P = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc,max_bottle_size) - P.name = "[name] bottle" - P.pixel_x = rand(-7, 7) //random position - P.pixel_y = rand(-7, 7) - //P.icon_state = "bottle"+bottlesprite - reagents.trans_to(P,amount_per_bottle) - src.updateUsrDialog() - return 1 - else - var/obj/item/weapon/reagent_containers/food/condiment/P = new/obj/item/weapon/reagent_containers/food/condiment(src.loc) - reagents.trans_to(P, 50) - src.updateUsrDialog() - return 1 - - else if(href_list["change_pill"]) - #define MAX_PILL_SPRITE 20 //Max icon state of the pill sprites - var/dat = list() - dat += "" - for(var/i = 1 to MAX_PILL_SPRITE) - if(i%4 == 1) - dat += "" - - dat += "" - - if (i%4 == 0) - dat +="" - - dat += "
    " - dat = list2text(dat) - var/datum/browser/popup = new(usr, "[windowtype]", "[name]", 585, 400, src) - popup.set_content(dat) - popup.open() - onclose(usr, "[windowtype]") - //usr << browse(dat, "window=[windowtype]") - return 1 - - /* - else if(href_list["change_bottle"]) - #define MAX_BOTTLE_SPRITE 20 //max icon state of the bottle sprites - var/dat = "" - for(var/i = 1 to MAX_BOTTLE_SPRITE) - if ( i%4==1 ) - dat += "" - - dat += "" - - if ( i%4==0 ) - dat +="" - - dat += "
    " - usr << browse(dat, "window=chem_master") - return - */ - - else if(href_list["pill_sprite"]) - pillsprite = href_list["pill_sprite"] - src.updateUsrDialog() - return 1 - - /* - else if(href_list["bottle_sprite"]) - bottlesprite = href_list["bottle_sprite"] - */ - -/obj/machinery/chem_master/proc/detach() - if(beaker) - beaker.loc = src.loc - beaker.pixel_x = 0 //We fucked with the beaker for overlays, so reset that - beaker.pixel_y = 0 //We fucked with the beaker for overlays, so reset that - if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) - var/mob/living/silicon/robot/R = beaker:holder:loc - if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) - beaker.loc = R - else - beaker.loc = beaker:holder - beaker = null - reagents.clear_reagents() - update_icon() - -/obj/machinery/chem_master/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/chem_master/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/chem_master/attack_hand(mob/user as mob) - - . = ..() - if(.) - return - - user.set_machine(src) - if(!(user.client in has_sprites)) - spawn() - has_sprites += user.client - for(var/i = 1 to MAX_PILL_SPRITE) - usr << browse_rsc(icon('icons/obj/chemical.dmi', "pill" + num2text(i)), "pill[i].png") - /* - for(var/i = 1 to MAX_BOTTLE_SPRITE) - usr << browse_rsc(icon('icons/obj/chemical.dmi', "bottle" + num2text(i)), "bottle[i].png") - */ - - var/dat = list() - if(!beaker) - dat += "Please insert a beaker.
    " - if(!condi) - if(src.loaded_pill_bottle) - dat += "Eject Pill Bottle \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.storage_slots]\]

    " - else - dat += "No pill bottle inserted.

    " - //dat += "Close" - else - var/datum/reagents/R = beaker.reagents - dat += "Eject beaker and Clear Buffer
    " - if(src.loaded_pill_bottle) - dat += "Eject Pill Bottle \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.storage_slots]\]

    " - else if(windowtype == "chem_master") - dat += "No pill bottle inserted.

    " - if(!R.total_volume) - dat += "Beaker is empty." - else - dat += "Add to buffer:
    " - for(var/datum/reagent/G in R.reagent_list) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:518: dat += "[G.name] , [G.volume] Units - " - dat += {"[G.name] , [G.volume] Units - - (Analyze) - (1) - (5) - (10) - (All) - (Custom)
    "} - // END AUTOFIX - - dat += "
    Transfer to [(!mode ? "disposal" : "beaker")]:
    " - if(reagents.total_volume) - for(var/datum/reagent/N in reagents.reagent_list) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:529: dat += "[N.name] , [N.volume] Units - " - dat += {"[N.name] , [N.volume] Units - - (Analyze) - (1) - (5) - (10) - (All) - (Custom)
    "} - // END AUTOFIX - else - dat += "Buffer is empty.
    " - if(!condi) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:539: dat += "

    Create pill (50 units max)
    " - //dat += {"
    "} - dat += {"
    "} - dat += {"

    Create single pill (50 units max)
    - Create multiple pills (50 units max each; [max_pill_count] max)
    - Create empty pills
    - Create bottle ([max_bottle_size] units max)
    - Create multiple bottles ([max_bottle_size] units max each; 4 max)
    "} - // END AUTOFIX - else - dat += "Create bottle (50 units max)" - dat = list2text(dat) - var/datum/browser/popup = new(user, "[windowtype]", "[name]", 575, 400, src) - popup.set_content(dat) - popup.open() - onclose(user, "[windowtype]") - return - -/obj/machinery/chem_master/proc/isgoodnumber(var/num) - if(isnum(num)) - if(num > 200) - num = 200 - else if(num < 0) - num = 1 - else - num = round(num) - return num - else - return 0 - -/obj/machinery/chem_master/update_icon() - - overlays.len = 0 - - if(beaker) - beaker.pixel_x = -9 //Move it far to the left - beaker.pixel_y = 5 //Move it up - beaker.update_icon() //Forcefully update the beaker - overlays += beaker //Set it as an overlay - - if(reagents.total_volume && !(stat & (BROKEN|NOPOWER))) //If we have reagents in here, and the machine is powered and functional - var/image/overlay = image('icons/obj/chemical.dmi', src, "mixer_overlay") - overlay.icon += mix_color_from_reagents(reagents.reagent_list) - overlays += overlay - - var/image/mixer_prongs = image('icons/obj/chemical.dmi', src, "mixer_prongs") - overlays += mixer_prongs //Add prongs on top of all of this - -/obj/machinery/chem_master/on_reagent_change() - update_icon() - -/obj/machinery/chem_master/condimaster - name = "\improper CondiMaster 3000" - condi = 1 - chem_board = /obj/item/weapon/circuitboard/condimaster - windowtype = "condi_master" - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -/obj/machinery/computer/pandemic - name = "PanD.E.M.I.C 2200" - density = 1 - anchored = 1 - icon = 'icons/obj/chemical.dmi' - icon_state = "mixer0" - use_power = 1 - idle_power_usage = 20 - var/temphtml = "" - var/wait = null - var/obj/item/weapon/reagent_containers/glass/beaker = null - - light_color = LIGHT_COLOR_BLUE - var/targetMoveKey - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -/obj/machinery/computer/pandemic/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/pandemic - ) - - RefreshParts() - -/obj/machinery/computer/pandemic/proc/user_moved(var/list/args) - var/event/E = args["event"] - if(!targetMoveKey) - E.handlers.Remove("\ref[src]:user_moved") - return - - var/turf/T = args["loc"] - - if(!Adjacent(T)) - if(E.holder) - E.holder.on_moved.Remove(targetMoveKey) - detach() - - -/obj/machinery/computer/pandemic/set_broken() - icon_state = (src.beaker?"mixer1_b":"mixer0_b") - stat |= BROKEN - - -/obj/machinery/computer/pandemic/power_change() - - if(stat & BROKEN) - icon_state = (src.beaker?"mixer1_b":"mixer0_b") - - else if(powered()) - icon_state = (src.beaker?"mixer1":"mixer0") - stat &= ~NOPOWER - - else - spawn(rand(0, 15)) - src.icon_state = (src.beaker?"mixer1_nopower":"mixer0_nopower") - stat |= NOPOWER - - -/obj/machinery/computer/pandemic/Topic(href, href_list) - if(stat & (NOPOWER|BROKEN)) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - - usr.set_machine(src) - if(!beaker) return - - if (href_list["create_vaccine"]) - if(!src.wait) - var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc) - if(B) - var/path = href_list["create_vaccine"] - var/vaccine_type = text2path(path) - var/datum/disease/D = null - - if(!vaccine_type) - D = archive_diseases[path] - vaccine_type = path - else - if(vaccine_type in diseases) - D = new vaccine_type(0, null) - - if(D) - B.name = "[D.name] vaccine bottle" - B.reagents.add_reagent("vaccine",15,vaccine_type) - wait = 1 - var/datum/reagents/R = beaker.reagents - var/datum/reagent/blood/Blood = null - for(var/datum/reagent/blood/L in R.reagent_list) - if(L) - Blood = L - break - var/list/res = Blood.data["resistances"] - spawn(res.len*200) - src.wait = null - else - src.temphtml = "The replicator is not ready yet." - src.updateUsrDialog() - return - else if (href_list["create_virus_culture"]) - if(!wait) - var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc) - B.icon_state = "bottle3" - var/type = text2path(href_list["create_virus_culture"])//the path is received as string - converting - var/datum/disease/D = null - if(!type) - var/datum/disease/advance/A = archive_diseases[href_list["create_virus_culture"]] - if(A) - D = new A.type(0, A) - else - if(type in diseases) // Make sure this is a disease - D = new type(0, null) - var/list/data = list("viruses"=list(D)) - var/name = sanitize(input(usr,"Name:","Name the culture",D.name)) - if(!name || name == " ") name = D.name - B.name = "[name] culture bottle" - B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium." - B.reagents.add_reagent("blood",20,data) - src.updateUsrDialog() - wait = 1 - spawn(1000) - src.wait = null - else - src.temphtml = "The replicator is not ready yet." - src.updateUsrDialog() - return - else if (href_list["empty_beaker"]) - beaker.reagents.clear_reagents() - src.updateUsrDialog() - return - else if (href_list["eject"]) - detach() - return - else if(href_list["clear"]) - src.temphtml = "" - src.updateUsrDialog() - return - else if(href_list["name_disease"]) - var/norange = (usr.mutations && usr.mutations.len && (M_TK in usr.mutations)) - var/new_name = stripped_input(usr, "Name the Disease", "New Name", "", MAX_NAME_LEN) - if(stat & (NOPOWER|BROKEN)) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr) && !norange) return - var/id = href_list["name_disease"] - if(archive_diseases[id]) - var/datum/disease/advance/A = archive_diseases[id] - A.AssignName(new_name) - for(var/datum/disease/advance/AD in active_diseases) - AD.Refresh() - src.updateUsrDialog() - - - else - usr << browse(null, "window=pandemic") - src.updateUsrDialog() - return - - src.add_fingerprint(usr) - return - -/obj/machinery/computer/pandemic/proc/detach() - beaker.loc = src.loc - if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) - var/mob/living/silicon/robot/R = beaker:holder:loc - if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) - beaker.loc = R - else - beaker.loc = beaker:holder - beaker = null - icon_state = "mixer0" - src.updateUsrDialog() -/obj/machinery/computer/pandemic/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/pandemic/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/pandemic/attack_hand(mob/user as mob) - if(stat & (NOPOWER|BROKEN)) - return - user.set_machine(src) - var/dat = "" - if(src.temphtml) - dat = "[src.temphtml]

    Main Menu" - else if(!beaker) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:722: dat += "Please insert beaker.
    " - dat += {"Please insert beaker.
    - Close"} - // END AUTOFIX - else - var/datum/reagents/R = beaker.reagents - var/datum/reagent/blood/Blood = null - for(var/datum/reagent/blood/B in R.reagent_list) - if(B) - Blood = B - break - if(!R.total_volume||!R.reagent_list.len) - dat += "The beaker is empty
    " - else if(!Blood) - dat += "No blood sample found in beaker" - else if(!Blood.data) - dat += "No blood data found in beaker." - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:738: dat += "

    Blood sample data:

    " - dat += {"

    Blood sample data:

    - Blood DNA: [(Blood.data["blood_DNA"]||"none")]
    - Blood Type: [(Blood.data["blood_type"]||"none")]
    "} - // END AUTOFIX - if(Blood.data["viruses"]) - var/list/vir = Blood.data["viruses"] - if(vir.len) - for(var/datum/disease/D in Blood.data["viruses"]) - if(!D.hidden[PANDEMIC]) - - - var/disease_creation = D.type - if(istype(D, /datum/disease/advance)) - - var/datum/disease/advance/A = D - D = archive_diseases[A.GetDiseaseID()] - disease_creation = A.GetDiseaseID() - if(D.name == "Unknown") - dat += "Name Disease
    " - - if(!D) - CRASH("We weren't able to get the advance disease from the archive.") - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:762: dat += "Disease Agent: [D?"[D.agent] - Create virus culture bottle":"none"]
    " - dat += {"Disease Agent: [D?"[D.agent] - Create virus culture bottle":"none"]
    - Common name: [(D.name||"none")]
    - Description: [(D.desc||"none")]
    - Spread: [(D.spread||"none")]
    - Possible cure: [(D.cure||"none")]

    "} - // END AUTOFIX - if(istype(D, /datum/disease/advance)) - var/datum/disease/advance/A = D - dat += "Symptoms: " - var/english_symptoms = list() - for(var/datum/symptom/S in A.symptoms) - english_symptoms += S.name - dat += english_list(english_symptoms) - - - dat += "
    Contains antibodies to: " - if(Blood.data["resistances"]) - var/list/res = Blood.data["resistances"] - if(res.len) - dat += "
      " - for(var/type in Blood.data["resistances"]) - var/disease_name = "Unknown" - - if(!ispath(type)) - var/datum/disease/advance/A = archive_diseases[type] - if(A) - disease_name = A.name - else - var/datum/disease/D = new type(0, null) - disease_name = D.name - - dat += "
    • [disease_name] - Create vaccine bottle
    • " - dat += "

    " - else - dat += "nothing
    " - else - dat += "nothing
    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:799: dat += "
    Eject beaker[((R.total_volume&&R.reagent_list.len) ? "-- Empty beaker":"")]
    " - dat += {"
    Eject beaker[((R.total_volume&&R.reagent_list.len) ? "-- Empty beaker":"")]
    - Close"} - // END AUTOFIX - user << browse("[src.name]
    [dat]", "window=pandemic;size=575x400") - onclose(user, "pandemic") - return - - -/obj/machinery/computer/pandemic/attackby(var/obj/I as obj, var/mob/user as mob) - if(..()) - return 1 - else if(istype(I, /obj/item/weapon/reagent_containers/glass)) - if(stat & (NOPOWER|BROKEN)) return - if(src.beaker) - to_chat(user, "A beaker is already loaded into the machine.") - return - if(!user.drop_item(I, src)) - to_chat(user, "You can't let go of \the [I]!") - return - - src.beaker = I - if(user.type == /mob/living/silicon/robot) - var/mob/living/silicon/robot/R = user - R.uneq_active() - targetMoveKey = R.on_moved.Add(src, "user_moved") - - to_chat(user, "You add the beaker to the machine!") - - src.updateUsrDialog() - icon_state = "mixer1" - - else - ..() - return -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -/obj/machinery/reagentgrinder - - name = "All-In-One Grinder" - icon = 'icons/obj/kitchen.dmi' - icon_state = "juicer1" - layer = 2.9 - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK | EJECTNOTDEL - pass_flags = PASSTABLE - var/inuse = 0 - var/obj/item/weapon/reagent_containers/beaker = null - var/limit = 10 - var/speed_multiplier = 1 - var/list/blend_items = list ( - - //Sheets - /obj/item/stack/sheet/metal = list("iron" = 20), - /obj/item/stack/sheet/mineral/plasma = list("plasma" = 20), - /obj/item/stack/sheet/mineral/uranium = list("uranium" = 20), - /obj/item/stack/sheet/mineral/clown = list("banana" = 20), - /obj/item/stack/sheet/mineral/silver = list("silver" = 20), - /obj/item/stack/sheet/mineral/gold = list("gold" = 20), - /obj/item/weapon/grown/nettle = list("sacid" = 0), - /obj/item/weapon/grown/deathnettle = list("pacid" = 0), - /obj/item/stack/sheet/charcoal = list("charcoal" = 20), - - //Blender Stuff - /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = -10), //I have no fucking idea what most of these numbers mean and I hate them. - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("ketchup" = -7), - /obj/item/weapon/reagent_containers/food/snacks/grown/corn = list("cornoil" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5), - /obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk = list("rice" = -5), - /obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/plastellium = list("plasticide" = 5), - - /obj/item/seeds = list("blackpepper" = 5), - - - //archaeology! - /obj/item/weapon/rocksliver = list("ground_rock" = 30), - - //All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.! - /obj/item/weapon/reagent_containers/pill = list(), - /obj/item/weapon/reagent_containers/food = list() - ) - - var/list/juice_items = list ( - - //Juicer Stuff - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/banana = list("banana" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/potato = list("potato" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/apple = list("applejuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = list("lemonjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/orange = list("orangejuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/lime = list("limejuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = list("poisonberryjuice" = 0), - ) - - - var/list/holdingitems = list() - var/targetMoveKey - -/******************************************************************** -** Adding Stock Parts to VV so preconstructed shit has its candy ** -********************************************************************/ -//Leaving large beakers out of the component part list to try and dodge beaker cloning. -/obj/machinery/reagentgrinder/New() - . = ..() - beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) - - component_parts = newlist( - /obj/item/weapon/circuitboard/reagentgrinder, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/stock_parts/scanning_module - ) - - RefreshParts() - - return - -/obj/machinery/reagentgrinder/proc/user_moved(var/list/args) - var/event/E = args["event"] - if(!targetMoveKey) - E.handlers.Remove("\ref[src]:user_moved") - return - - var/turf/T = args["loc"] - - if(!Adjacent(T)) - if(E.holder) - E.holder.on_moved.Remove(targetMoveKey) - detach() - - -/obj/machinery/reagentgrinder/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) - T += M.rating-1 - limit = initial(limit)+(T * 5) - - T = 0 - for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) - T += M.rating-1 - speed_multiplier = initial(speed_multiplier)+(T * 0.50) - -/obj/machinery/reagentgrinder/update_icon() - icon_state = "juicer"+num2text(!isnull(beaker)) - return - -/obj/machinery/reagentgrinder/togglePanelOpen(var/obj/toggleitem, mob/user) - if(beaker) - to_chat(user, "You can't reach \the [src]'s maintenance panel with the beaker in the way!") - return -1 - return ..() - -/obj/machinery/reagentgrinder/crowbarDestroy(mob/user) - if(beaker) - to_chat(user, "You can't do that while \the [src] has a beaker loaded!") - return -1 - return ..() - -/obj/machinery/reagentgrinder/attackby(var/obj/item/O as obj, var/mob/user as mob) - - if(..()) - return 1 - - if (istype(O,/obj/item/weapon/reagent_containers/glass) || \ - istype(O,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass) || \ - istype(O,/obj/item/weapon/reagent_containers/food/drinks/shaker)) - - if (beaker) - return 0 - if (panel_open) - to_chat(user, "You can't load a beaker while the maintenance panel is open.") - return 0 - else - if(!user.drop_item(O, src)) - to_chat(user, "You can't let go of \the [O]!") - return - - src.beaker = O - if(user.type == /mob/living/silicon/robot) - var/mob/living/silicon/robot/R = user - R.uneq_active() - targetMoveKey = R.on_moved.Add(src, "user_moved") - - update_icon() - src.updateUsrDialog() - return 1 - - if(holdingitems && holdingitems.len >= limit) - to_chat(usr, "The machine cannot hold any more items.") - return 1 - - //Fill machine with bags - if(istype(O, /obj/item/weapon/storage/bag/plants)||istype(O, /obj/item/weapon/storage/bag/chem)) - var/obj/item/weapon/storage/bag/B = O - for (var/obj/item/G in O.contents) - B.remove_from_storage(G,src) - holdingitems += G - if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill - to_chat(user, "You fill the All-In-One grinder to the brim.") - break - - if(!O.contents.len) - to_chat(user, "You empty the [O] into the All-In-One grinder.") - - src.updateUsrDialog() - return 0 - - if (!is_type_in_list(O, blend_items) && !is_type_in_list(O, juice_items)) - to_chat(user, "Cannot refine into a reagent.") - return 1 - - if(!user.drop_item(O, src)) - user << "\The [O] is stuck to your hands!" - return 1 - - holdingitems += O - src.updateUsrDialog() - return 0 - -/obj/machinery/reagentgrinder/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/reagentgrinder/attack_ai(mob/user as mob) - return 0 - -/obj/machinery/reagentgrinder/attack_hand(mob/user as mob) - user.set_machine(src) - interact(user) - -/obj/machinery/reagentgrinder/attack_robot(mob/user as mob) - return attack_hand(user) - -/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu - var/is_chamber_empty = 0 - var/is_beaker_ready = 0 - var/processing_chamber = "" - var/beaker_contents = "" - var/dat = list() - - if(!inuse) - for (var/obj/item/O in holdingitems) - processing_chamber += "\A [O.name]
    " - - if (!processing_chamber) - is_chamber_empty = 1 - processing_chamber = "Nothing." - if (!beaker) - beaker_contents = "No beaker attached.
    " - else - is_beaker_ready = 1 - beaker_contents = "The beaker contains:
    " - var/anything = 0 - for(var/datum/reagent/R in beaker.reagents.reagent_list) - anything = 1 - beaker_contents += "[R.volume] - [R.name]
    " - if(!anything) - beaker_contents += "Nothing
    " - - - dat += {" - Processing chamber contains:
    - [processing_chamber]
    - [beaker_contents]
    - "} - if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN))) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:1016: dat += "Grind the reagents
    " - dat += {"Grind the reagents
    - Juice the reagents

    "} - // END AUTOFIX - if(holdingitems && holdingitems.len > 0) - dat += "Eject the reagents
    " - if (beaker) - dat += "Detach the beaker
    " - else - dat += "Please wait..." - dat = list2text(dat) - var/datum/browser/popup = new(user, "reagentgrinder", "All-In-One Grinder", src) - popup.set_content(dat) - popup.open() - onclose(user, "reagentgrinder") - return - - -/obj/machinery/reagentgrinder/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - switch(href_list["action"]) - if ("grind") - grind() - if("juice") - juice() - if("eject") - eject() - if ("detach") - detach() - src.updateUsrDialog() - return - -/obj/machinery/reagentgrinder/proc/detach() - - - if (usr.stat != 0) - return - if (!beaker) - return - beaker.loc = src.loc - if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) - var/mob/living/silicon/robot/R = beaker:holder:loc - if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) - beaker.loc = R - else - beaker.loc = beaker:holder - beaker = null - update_icon() - -/obj/machinery/reagentgrinder/proc/eject() - - - if (usr.stat != 0) - return - if (holdingitems && holdingitems.len == 0) - return - - for(var/obj/item/O in holdingitems) - O.loc = src.loc - holdingitems -= O - holdingitems = list() - -/obj/machinery/reagentgrinder/proc/is_allowed(var/obj/item/weapon/reagent_containers/O) - for (var/i in blend_items) - if(istype(O, i)) - return 1 - return 0 - -/obj/machinery/reagentgrinder/proc/get_allowed_by_id(var/obj/item/weapon/grown/O) - for (var/i in blend_items) - if (istype(O, i)) - return blend_items[i] - -/obj/machinery/reagentgrinder/proc/get_allowed_snack_by_id(var/obj/item/weapon/reagent_containers/food/snacks/O) - for(var/i in blend_items) - if(istype(O, i)) - return blend_items[i] - -/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_id(var/obj/item/weapon/reagent_containers/food/snacks/O) - for(var/i in juice_items) - if(istype(O, i)) - return juice_items[i] - -/obj/machinery/reagentgrinder/proc/get_grownweapon_amount(var/obj/item/weapon/grown/O) - if (!istype(O)) - return 5 - else if (O.potency == -1) - return 5 - else - return round(O.potency) - -/obj/machinery/reagentgrinder/proc/get_juice_amount(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) - if (!istype(O)) - return 5 - else if (O.potency == -1) - return 5 - else - return round(5*sqrt(O.potency)) - -/obj/machinery/reagentgrinder/proc/remove_object(var/obj/item/O) - holdingitems -= O - qdel(O) - O = null - -/obj/machinery/reagentgrinder/proc/juice() - power_change() - if(stat & (NOPOWER|BROKEN)) - return - if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) - return - playsound(get_turf(src), speed_multiplier < 2 ? 'sound/machines/juicer.ogg' : 'sound/machines/juicerfast.ogg', 30, 1) - inuse = 1 - spawn(50/speed_multiplier) - inuse = 0 - interact(usr) - //Snacks - for (var/obj/item/weapon/reagent_containers/food/snacks/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - var/allowed = get_allowed_juice_by_id(O) - if(isnull(allowed)) - break - - for (var/r_id in allowed) - - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = get_juice_amount(O) - - beaker.reagents.add_reagent(r_id, min(amount, space)) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - remove_object(O) - -/obj/machinery/reagentgrinder/proc/grind() - - - power_change() - if(stat & (NOPOWER|BROKEN)) - return - if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) - return - playsound(get_turf(src), speed_multiplier < 2 ? 'sound/machines/blender.ogg' : 'sound/machines/blenderfast.ogg', 50, 1) - inuse = 1 - spawn(60/speed_multiplier) - inuse = 0 - interact(usr) - //Snacks and Plants - for (var/obj/item/weapon/reagent_containers/food/snacks/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - var/allowed = get_allowed_snack_by_id(O) - if(isnull(allowed)) - break - - for (var/r_id in allowed) - - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - if(amount <= 0) - if(amount == 0) - if (O.reagents != null && O.reagents.has_reagent("nutriment")) - beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment"), space)) - O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) - else - if (O.reagents != null && O.reagents.has_reagent("nutriment")) - beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)), space)) - O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) - - else - O.reagents.trans_id_to(beaker, r_id, min(amount, space)) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - - if(O.reagents.reagent_list.len == 0) - remove_object(O) - - //Sheets - for (var/obj/item/stack/sheet/O in holdingitems) - var/allowed = get_allowed_by_id(O) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - for(var/i = 1; i <= round(O.amount, 1); i++) - for (var/r_id in allowed) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - beaker.reagents.add_reagent(r_id,min(amount, space)) - if (space < amount) - break - if (i == round(O.amount, 1)) - remove_object(O) - break - - //xenoarch - for(var/obj/item/weapon/rocksliver/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - var/allowed = get_allowed_by_id(O) - for (var/r_id in allowed) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - beaker.reagents.add_reagent(r_id,min(amount, space), O.geological_data) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - remove_object(O) - - //Everything else - Transfers reagents from it into beaker - for (var/obj/item/weapon/reagent_containers/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - var/amount = O.reagents.total_volume - O.reagents.trans_to(beaker, amount) - if(!O.reagents.total_volume) - remove_object(O) - - //All other generics - for (var/obj/item/O in holdingitems) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - var/allowed = get_allowed_by_id(O) - for (var/r_id in allowed) - var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/amount = allowed[r_id] - if (amount == 0) - if (O.reagents != null && O.reagents.has_reagent(r_id)) - beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id), space)) - else - beaker.reagents.add_reagent(r_id,min(amount, space)) - - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - remove_object(O) - -//************************************************************************************* -// -// -//It just felt right to put the ghetto chemistry tools here with chemistry machinery. -// -// -//************************************************************************************* -/obj/item/weapon/electrolyzer - name = "Electrolyzer" - icon = 'icons/obj/chemical.dmi' - icon_state = "chemg_wired" - item_state = "chemg_wired" - desc = "A refurbished grenade-casing jury rigged to split simple chemicals." - w_class = 2.0 - force = 2.0 - var/list/beakers = new/list() - var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass, /obj/item/weapon/reagent_containers/food/drinks/soda_cans/) - var/datum/effect/effect/system/spark_spread/spark_system - -/obj/item/weapon/electrolyzer/New() - . = ..() - spark_system = new - spark_system.set_up(5, 0, src) - spark_system.attach(src) - -/obj/item/weapon/electrolyzer/Destroy() - qdel(spark_system) - spark_system = null - . = ..() - -/obj/item/weapon/electrolyzer/attack_self(mob/user as mob) - if(beakers.len) - for(var/obj/B in beakers) - if(istype(B)) - beakers -= B - user.put_in_hands(B) - to_chat(user, "You remove the containers from the electrolyzer.") - -/obj/item/weapon/electrolyzer/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(iswirecutter(W)) - if(beakers.len) - to_chat(user, "The electrolyzer contains beakers!") - return - else - to_chat(user, "You disassemble the electrolyzer.") - var/turf/T = get_turf(src) - new /obj/item/stack/cable_coil(T,2) - new /obj/item/weapon/grenade/chem_grenade(T) - qdel(src) - return - else if(is_type_in_list(W, allowed_containers)) - var/obj/item/weapon/reagent_containers/glass/G = W - if(G.reagents.reagent_list.len > 1) - to_chat(user, "That mixture is too complex!") - return - if(beakers.len == 2) - to_chat(user, "The grenade can not hold more containers.") - return - else if(beakers.len == 1) - var/obj/item/weapon/reagent_containers/glass/other = beakers[1] - if(other.reagents.total_volume && !G.reagents.total_volume) //We already have one inserted beaker. It must occupy slot 1. Is it empty or active? - to_chat(user, "You add \the [G] to the electrolyzer as the empty container.") - insert_beaker(G,user) - else if(!other.reagents.total_volume && G.reagents.total_volume) - to_chat(user, "You add \the [G] to the electrolyzer as the active container.") - insert_beaker(G,user) - else - to_chat(user, "The electrolyzer requires one active beaker and one empty beaker!") - return - else - to_chat(user, "You add \the [G] to the electrolyzer as the [G.reagents.total_volume ? "active" : "empty"] container.") - insert_beaker(G,user) - else if(istype(W, /obj/item/weapon/cell)) - if(beakers.len < 2) - to_chat(user, "The electrolyzer requires one active beaker and one empty beaker!") - return - var/obj/item/weapon/cell/C = W - var/obj/item/weapon/reagent_containers/active = null - var/obj/item/weapon/reagent_containers/empty = null - var/datum/chemical_reaction/unreaction = null - for(var/obj/item/weapon/reagent_containers/B in beakers) - if(B.reagents.reagent_list.len > 1) //This only fires if their power ran out with a first cell and they try electrolyzing again without removing the old mix - to_chat(user, "That mixture is too complex!") - return - else if(B.reagents.reagent_list.len == 1) - active = B - else if (!B.reagents.reagent_list.len) - empty = B - else - to_chat(user, "An error has occured. Your beaker had between 0 and 1 reagents. Please report this message.") - if(!active || !empty) - to_chat(user, "There must be both an empty and active beaker.") - return - var/datum/reagent/target = active.reagents.reagent_list[1] //Should only have one thing anyway - for(var/R in typesof(/datum/chemical_reaction/)) - var/datum/chemical_reaction/check = new R - if(check.id == target.id) - unreaction = check - break - if(!unreaction) - to_chat(user, "The system didn't react...") - return - var/total_reactions = round(active.reagents.total_volume / unreaction.result_amount) - var/primary = 1 - if(C.charge<30*total_reactions) - total_reactions = round(C.charge/30) //In the case that we don't have ENOUGH charge, this will react us as often as we can - C.charge -= (30*total_reactions) - active.reagents.remove_reagent(unreaction.result,total_reactions*unreaction.result_amount) //This moves over the reactive bulk, and leaves behind the amount too small to react - for(var/E in unreaction.required_reagents) - if(primary) - active.reagents.add_reagent(E, unreaction.required_reagents[E]*total_reactions) //Put component amount * reaction count back in primary - primary = 0 - else - empty.reagents.add_reagent(E, unreaction.required_reagents[E]*total_reactions) - to_chat(user, "The system electrolyzes!") - spark_system.start() - else - ..() - -/obj/item/weapon/electrolyzer/proc/insert_beaker(obj/item/weapon/W as obj, mob/user as mob) - if(user.drop_item(W, src)) - W.loc = src - beakers += W - else - to_chat(user, "You can't let go of \the [W]!") - return - - -/obj/structure/centrifuge - name = "suspicious toilet" - desc = "This toilet is a cleverly disguised improvised centrifuge." - icon = 'icons/obj/watercloset.dmi' - icon_state = "toilet11" - density = 0 - anchored = 1 - var/list/cans = new/list() //These are the empty containers. - var/obj/item/weapon/reagent_containers/beaker = null // This is the active container - - var/targetMoveKey - -/obj/structure/centrifuge/examine(mob/user) - ..() - to_chat(user, "It contains [cans.len] empty containers[beaker ? " and an active container!" : "."]") - -/obj/structure/centrifuge/attackby(obj/item/weapon/reagent_containers/W as obj, mob/user as mob) - if(iscrowbar(W)) - var/obj/structure/toilet/T = new /obj/structure/toilet(src.loc) - T.open = 1 - T.cistern = 1 - T.dir = src.dir - T.update_icon() - new /obj/item/stack/rods(get_turf(src), 2) - to_chat(user, "You pry out the rods, destroying the filter.") - qdel(src) - if(W.is_open_container()) - if(!W.reagents.total_volume) - if(user.drop_item(W, src)) - cans += W - to_chat(user, "You add a passive container. It now contains [cans.len].") - else - if(!beaker) - if(user.drop_item(W, src)) - to_chat(user, "You insert an active container.") - src.beaker = W - if(user.type == /mob/living/silicon/robot) - var/mob/living/silicon/robot/R = user - R.uneq_active() - targetMoveKey = R.on_moved.Add(src, "user_moved") - else - to_chat(user, "There is already an active container.") - return - else - ..() -/obj/structure/centrifuge/proc/user_moved(var/list/args) - var/event/E = args["event"] - if(!targetMoveKey) - E.handlers.Remove("\ref[src]:user_moved") - return - - var/turf/T = args["loc"] - - if(!Adjacent(T)) - if(E.holder) - E.holder.on_moved.Remove(targetMoveKey) - detach() - -/obj/structure/centrifuge/attack_hand(mob/user as mob) - add_fingerprint(user) - if(cans.len || beaker) - for(var/obj/item/O in cans) - O.loc = src.loc - cans -= O - if(beaker) - detach() - to_chat(user, "You remove everything from the centrifuge.") - else - to_chat(user, "There is nothing to eject!") - -/obj/structure/centrifuge/verb/flush() - set name = "Flush" - set category = "Object" - set src in view(1) - - if(!usr.canmove || usr.isUnconscious() || usr.restrained() || !usr.dexterity_check()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain - return - - if(!cans || !beaker) - to_chat(usr, "\The [src] needs an active container and multiple passive containers to work.") - return - - add_fingerprint(usr) - to_chat(usr, "\The [src] groans as it spits out containers.") - while(cans.len>0 && beaker.reagents.reagent_list.len>0) - var/obj/item/weapon/reagent_containers/C = cans[1] - var/datum/reagent/R = beaker.reagents.reagent_list[1] - beaker.reagents.trans_id_to(C,R.id,50) - C.loc = src.loc - cans -= C - if(!cans.len&&beaker.reagents.reagent_list.len) - to_chat(usr, "With no remaining containers, the rest of the concoction swirls down the drain...") - beaker.reagents.clear_reagents() - if(!beaker.reagents.reagent_list.len) - to_chat(usr, "The now-empty active container plops out.") - detach() - return - -/obj/structure/centrifuge/AltClick() - if(Adjacent(usr)) - flush() - return - return ..() - -/obj/structure/centrifuge/proc/detach() - if(beaker) - beaker.forceMove(src.loc) - if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) - var/mob/living/silicon/robot/R = beaker:holder:loc - if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) - beaker.loc = R - else - beaker.loc = beaker:holder - beaker = null - return - -/obj/item/weapon/reagent_containers/glass/mortar - name = "mortar" - desc = "This is a reinforced bowl, used for crushing reagents. Ooga booga Rockstop." - icon = 'icons/obj/food.dmi' - icon_state = "mortar" - flags = FPRINT | OPENCONTAINER - volume = 50 - amount_per_transfer_from_this = 5 - //We want the all-in-one grinder audience - - var/list/blend_items = list ( - /obj/item/stack/sheet/metal = list("iron",20), - /obj/item/stack/sheet/mineral/plasma = list("plasma",20), - /obj/item/stack/sheet/mineral/uranium = list("uranium",20), - /obj/item/stack/sheet/mineral/clown = list("banana",20), - /obj/item/stack/sheet/mineral/silver = list("silver",20), - /obj/item/stack/sheet/mineral/gold = list("gold",20), - /obj/item/weapon/grown/nettle = list("sacid",0), - /obj/item/weapon/grown/deathnettle = list("pacid",0), - /obj/item/stack/sheet/charcoal = list("charcoal",20), - /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list("soymilk",1), - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("ketchup",2), - /obj/item/weapon/reagent_containers/food/snacks/grown/corn = list("cornoil",3), - /obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour",5), - /obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk = list("rice",5), - /obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly",1), - /obj/item/seeds = list("blackpepper",5), - /obj/item/device/flashlight/flare = list("sulfur",10), - /obj/item/stack/cable_coil = list("copper", 10), - /obj/item/weapon/cell = list("lithium", 10), - /obj/item/clothing/head/butt = list("mercury", 10), - /obj/item/weapon/rocksliver = list("ground_rock",30), - - //Recipes must include both variables! - /obj/item/weapon/reagent_containers/food = list("generic",0) - ) - - var/list/juice_items = list ( - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("tomatojuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = list("carrotjuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/berries = list("berryjuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/banana = list("banana",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/potato = list("potato",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = list("lemonjuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/orange = list("orangejuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/lime = list("limejuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice",0), - /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice",0), - /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = list("poisonberryjuice",0), - ) - - - var/obj/item/crushable = null - -/obj/item/weapon/reagent_containers/glass/mortar/Destroy() - qdel(crushable) - crushable = null - . = ..() - -/obj/item/weapon/reagent_containers/glass/mortar/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (isscrewdriver(O)) - if(crushable) - crushable.forceMove(user.loc) - new /obj/item/stack/sheet/metal(user.loc) - new /obj/item/trash/bowl(user.loc) - qdel(src) //Important detail - return - if (crushable) - to_chat(user, "There's already something inside!") - return 1 - if (!is_type_in_list(O, blend_items) && !is_type_in_list(O, juice_items)) - to_chat(user, "You can't grind that!") - return ..() - - if(istype(O, /obj/item/stack/)) - var/obj/item/stack/N = new O.type(src, amount=1) - var/obj/item/stack/S = O - S.use(1) - crushable = N - to_chat(user, "You place \the [N] in \the [src].") - return 0 - else if(!user.drop_item(O, src)) - to_chat(user, "You can't let go of \the [O]!") - return - - crushable = O - to_chat(user, "You place \the [O] in \the [src].") - return 0 - -/obj/item/weapon/reagent_containers/glass/mortar/attack_hand(mob/user as mob) - add_fingerprint(user) - if(user.get_inactive_hand() != src) return ..() - if(crushable) - crushable.forceMove(user.loc) - user.put_in_active_hand(crushable) - crushable = null - return - -/obj/item/weapon/reagent_containers/glass/mortar/attack_self(mob/user as mob) - if(!crushable) - to_chat(user, "There is nothing to be crushed.") - return - if (reagents.total_volume >= volume) - to_chat(user, "There is no more space inside!") - return - if(is_type_in_list(crushable, juice_items)) - to_chat(user, "You smash the contents into juice!") - var/id = null - for(var/i in juice_items) - if(istype(crushable, i)) - id = juice_items[i] - if(!id) - return - var/obj/item/weapon/reagent_containers/food/snacks/grown/juiceable = crushable - if(juiceable.potency == -1) - juiceable.potency = 0 - reagents.add_reagent(id[1], min(round(5*sqrt(juiceable.potency)), volume - reagents.total_volume)) - else if(is_type_in_list(crushable, blend_items)) - to_chat(user, "You grind the contents into dust!") - var/id = null - var/space = volume - reagents.total_volume - for(var/i in blend_items) - if(istype(crushable, i)) - id = blend_items[i] - break - if(!id) - return - if(istype(crushable, /obj/item/weapon/reagent_containers/food/snacks)) //Most growable food - if(id[1] == "generic") - crushable.reagents.trans_to(src,crushable.reagents.total_volume) - else - reagents.add_reagent(id[1],min(id[2], space)) - else if(istype(crushable, /obj/item/stack/sheet) || istype(crushable, /obj/item/seeds) || /obj/item/device/flashlight/flare || /obj/item/stack/cable_coil || /obj/item/weapon/cell || /obj/item/clothing/head/butt) //Generic processes - reagents.add_reagent(id[1],min(id[2], space)) - else if(istype(crushable, /obj/item/weapon/grown)) //Nettle and death nettle - crushable.reagents.trans_to(src,crushable.reagents.total_volume) - else if(istype(crushable, /obj/item/weapon/rocksliver)) //Xenoarch - var/obj/item/weapon/rocksliver/R = crushable - reagents.add_reagent(id[1],min(id[2], space), R.geological_data) - else - to_chat(user, "An error was encountered. Report this message.") - return - else - to_chat(user, "You smash the contents into nothingness.") - qdel(crushable) - crushable = null - return - -/obj/item/weapon/reagent_containers/glass/mortar/examine(mob/user) - ..() - to_chat(user, "It has [crushable ? "an unground [crushable] inside." : "nothing to be crushed."]") +#define SOLID 1 +#define LIQUID 2 +#define GAS 3 +#define FORMAT_DISPENSER_NAME 15 + +/obj/machinery/chem_dispenser + name = "\improper Chem Dispenser" + density = 1 + anchored = 1 + icon = 'icons/obj/chemical.dmi' + icon_state = "dispenser" + use_power = 1 + idle_power_usage = 40 + var/energy = 0 + var/max_energy = 50 + var/rechargerate = 2 + var/amount = 30 + var/obj/item/weapon/reagent_containers/glass/beaker = null + var/recharged = 0 + var/custom = 0 + var/useramount = 30 // Last used amount + var/list/dispensable_reagents = list("hydrogen","lithium","carbon","nitrogen","oxygen","fluorine", + "sodium","aluminum","silicon","phosphorus","sulfur","chlorine","potassium","iron", + "copper","mercury","radium","water","ethanol","sugar","sacid","tungsten") + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + var/targetMoveKey = null //To prevent borgs from leaving without their beakers. + + +/* +USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY +*/ + +/obj/machinery/chem_dispenser/mapping + max_energy = 100 + energy = 100 + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +/obj/machinery/chem_dispenser/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/chem_dispenser, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + + RefreshParts() + dispensable_reagents = sortList(dispensable_reagents) + +/obj/machinery/chem_dispenser/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + T += M.rating-1 + max_energy = initial(max_energy)+(T * 50 / 4) + + T = 0 + for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts) + T += Ma.rating-1 + rechargerate = initial(rechargerate) + (T / 2) + +/* + for(var/obj/item/weapon/stock_parts/scanning_module/Ml in component_parts) + T += Ml.rating + //Who even knows what to use the scanning module for +*/ + +/obj/machinery/chem_dispenser/proc/user_moved(var/list/args) + var/event/E = args["event"] + if(!targetMoveKey) + E.handlers.Remove("\ref[src]:user_moved") + return + + var/turf/T = args["loc"] + + if(!Adjacent(T)) + if(E.holder) + E.holder.on_moved.Remove(targetMoveKey) + detach() + +/obj/machinery/chem_dispenser/proc/recharge() + if(stat & (BROKEN|NOPOWER)) return + var/oldenergy = energy + energy = min(energy + rechargerate, max_energy) + if(energy != oldenergy) + use_power(3000) // This thing uses up alot of power (this is still low as shit for creating reagents from thin air) + nanomanager.update_uis(src) // update all UIs attached to src + +/obj/machinery/chem_dispenser/power_change() + if(powered()) + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + stat |= NOPOWER + nanomanager.update_uis(src) // update all UIs attached to src + +/obj/machinery/chem_dispenser/proc/can_use(var/mob/living/silicon/robot/R) + if(!isMoMMI(R) && !istype(R.module,/obj/item/weapon/robot_module/medical)) //default chem dispenser can only be used by MoMMIs and Mediborgs + return 0 + else + if(!isMoMMI(R)) + targetMoveKey = R.on_moved.Add(src, "user_moved") + return 1 + +/obj/machinery/chem_dispenser/process() + if(recharged < 0) + recharge() + recharged = 15 + else + recharged -= 1 + +/obj/machinery/chem_dispenser/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(50)) + qdel(src) + return + +/obj/machinery/chem_dispenser/blob_act() + if (prob(50)) + qdel(src) + + /** + * The ui_interact proc is used to open and update Nano UIs + * If ui_interact is not used then the UI will not update correctly + * ui_interact is currently defined for /atom/movable + * + * @param user /mob The mob who is interacting with this ui + * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") + * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui + * + * @return nothing + */ +/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + if(stat & (BROKEN|NOPOWER)) return + if((user.stat && !isobserver(user)) || user.restrained()) return + if(!chemical_reagents_list || !chemical_reagents_list.len) return + // this is the data which will be sent to the ui + var/data[0] + data["amount"] = amount + data["energy"] = energy + data["maxEnergy"] = max_energy + data["isBeakerLoaded"] = beaker ? 1 : 0 + data["custom"] = custom + + var beakerContents[0] + var beakerCurrentVolume = 0 + if(beaker && beaker.reagents && beaker.reagents.reagent_list.len) + for(var/datum/reagent/R in beaker.reagents.reagent_list) + beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list... + beakerCurrentVolume += R.volume + data["beakerContents"] = beakerContents + + if (beaker) + data["beakerCurrentVolume"] = beakerCurrentVolume + data["beakerMaxVolume"] = beaker.volume + else + data["beakerCurrentVolume"] = null + data["beakerMaxVolume"] = null + + var chemicals[0] + for (var/re in dispensable_reagents) + var/datum/reagent/temp = chemical_reagents_list[re] + if(temp) //formats name because Space Mountain Wind and theoretically others in the future are too long + chemicals.Add(list(list("title" = copytext(temp.name,1,FORMAT_DISPENSER_NAME), "id" = temp.id, "commands" = list("dispense" = temp.id)))) // list in a list because Byond merges the first list... + data["chemicals"] = chemicals + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "chem_dispenser.tmpl", "[src.name] 5000", 390, 630) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + +/obj/machinery/chem_dispenser/Topic(href, href_list) + if(..()) + return + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + if(stat & (NOPOWER|BROKEN)) + return 0 // don't update UIs attached to this object + + if(href_list["amount"]) + if(href_list["amount"] == "0") + var/num = input("Enter desired output amount", "Amount", useramount) as num + if (num) + amount = round(text2num(num), 5) + custom = 1 + else + custom = 0 + amount = round(text2num(href_list["amount"]), 5) // round to nearest 5 + amount = Clamp(amount, 5, 100) // Since the user can actually type the commands himself, some sanity checking + if (custom) + useramount = amount + + if(href_list["dispense"]) + if (dispensable_reagents.Find(href_list["dispense"]) && beaker != null) + var/obj/item/weapon/reagent_containers/glass/B = src.beaker + var/datum/reagents/R = B.reagents + if(!R) + if(!B.gcDestroyed) + B.create_reagents(B.volume) + else + qdel(B) + B = null + return + var/space = R.maximum_volume - R.total_volume + + R.add_reagent(href_list["dispense"], min(amount, energy * 10, space)) + energy = max(energy - min(amount, energy * 10, space) / 10, 0) + + if(href_list["ejectBeaker"]) + if(beaker) + detach() + + add_fingerprint(usr) + return 1 // update UIs attached to this object + +/obj/machinery/chem_dispenser/proc/detach() + targetMoveKey=null + + if(beaker) + var/obj/item/weapon/reagent_containers/glass/B = beaker + B.loc = loc + if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) + var/mob/living/silicon/robot/R = beaker:holder:loc + if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) + beaker.loc = R + else + beaker.loc = beaker:holder + beaker = null + return 1 + +/obj/machinery/chem_dispenser/AltClick() + if(usr.canmove && !usr.isUnconscious() && !usr.restrained() && Adjacent(usr) && beaker && !(stat & (NOPOWER|BROKEN) && usr.dexterity_check())) + detach() + return + return ..() + +/obj/machinery/chem_dispenser/togglePanelOpen(var/obj/toggleitem, mob/user) + if(beaker) + to_chat(user, "You can't reach the maintenance panel with a beaker in the way!") + return + return ..() + +/obj/machinery/chem_dispenser/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) //to be worked on + + if(..()) + return 1 + + if(isrobot(user)) + if(!can_use(user)) + return + + if(istype(D, /obj/item/weapon/reagent_containers/glass)) + if(src.beaker) + to_chat(user, "A beaker is already loaded into the machine.") + return + else if(!panel_open) + if(!user.drop_item(D, src)) + to_chat(user, "You can't let go of \the [D]!") + return + + src.beaker = D + if(user.type == /mob/living/silicon/robot) + var/mob/living/silicon/robot/R = user + R.uneq_active() + + to_chat(user, "You add the beaker to the machine!") + + nanomanager.update_uis(src) // update all UIs attached to src + return 1 + else + to_chat(user, "You can't add a beaker to the machine while the panel is open.") + return + +/obj/machinery/chem_dispenser/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/chem_dispenser/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/chem_dispenser/attack_hand(mob/user as mob) + if(stat & BROKEN) + return + + ui_interact(user) +//Cafe stuff + +/obj/machinery/chem_dispenser/brewer/ + name = "Space-Brewery" + icon_state = "brewer" + dispensable_reagents = list("tea","greentea","redtea", "coffee","milk","cream","water","hot_coco", "soymilk") +/obj/machinery/chem_dispenser/brewer/New() + . = ..() + component_parts = newlist( + /obj/item/weapon/circuitboard/chem_dispenser/brewer, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + RefreshParts() + +/obj/machinery/chem_dispenser/brewer/mapping + max_energy = 100 + energy = 100 + +/obj/machinery/chem_dispenser/brewer/can_use(var/mob/living/silicon/robot/R) + if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs + targetMoveKey = R.on_moved.Add(src, "user_moved") + return 1 + else + return 0 + +//Soda/booze dispensers. + +/obj/machinery/chem_dispenser/soda_dispenser/ + name = "Soda Dispenser" + icon_state = "soda_dispenser" + dispensable_reagents = list("spacemountainwind", "sodawater", "lemon_lime", "dr_gibb", "cola", "ice", "tonic") +/obj/machinery/chem_dispenser/soda_dispenser/New() + . = ..() + component_parts = newlist( + /obj/item/weapon/circuitboard/chem_dispenser/soda_dispenser, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + RefreshParts() + +/obj/machinery/chem_dispenser/soda_dispenser/mapping + max_energy = 100 + energy = 100 + +/obj/machinery/chem_dispenser/soda_dispenser/can_use(var/mob/living/silicon/robot/R) + if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs + targetMoveKey = R.on_moved.Add(src, "user_moved") + return 1 + else + return 0 + +/obj/machinery/chem_dispenser/booze_dispenser/ + name = "Booze Dispenser" + icon_state = "booze_dispenser" + dispensable_reagents = list("beer", "whiskey", "tequila", "vodka", "vermouth", "rum", "cognac", "wine", "kahlua", "ale", "ice", "water", "gin", "sodawater", "cola", "cream","tomatojuice","orangejuice","limejuice","tonic") +/obj/machinery/chem_dispenser/booze_dispenser/New() + . = ..() + component_parts = newlist( + /obj/item/weapon/circuitboard/chem_dispenser/booze_dispenser, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen + ) + RefreshParts() + +/obj/machinery/chem_dispenser/booze_dispenser/mapping + max_energy = 100 + energy = 100 + +/obj/machinery/chem_dispenser/booze_dispenser/can_use(var/mob/living/silicon/robot/R) + if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs + targetMoveKey = R.on_moved.Add(src, "user_moved") + return 1 + else + return 0 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/obj/machinery/chem_master + name = "\improper ChemMaster 3000" + density = 1 + anchored = 1 + icon = 'icons/obj/chemical.dmi' + icon_state = "mixer" + use_power = 1 + idle_power_usage = 20 + var/obj/item/weapon/reagent_containers/glass/beaker = null + var/obj/item/weapon/storage/pill_bottle/loaded_pill_bottle = null + var/mode = 0 + var/condi = 0 + var/windowtype = "chem_master" //For the browser windows + var/useramount = 30 // Last used amount + //var/bottlesprite = "1" //yes, strings + var/pillsprite = "1" + + var/client/has_sprites = list() + var/chem_board = /obj/item/weapon/circuitboard/chemmaster3000 + var/max_bottle_size = 30 + var/max_pill_count = 20 + + light_color = LIGHT_COLOR_BLUE + light_range_on = 3 + light_power_on = 2 + use_auto_lights = 1 + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + var/targetMoveKey + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ + +/obj/machinery/chem_master/New() + . = ..() + + create_reagents(100) + + component_parts = newlist( + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/console_screen + ) + + component_parts += new chem_board + + RefreshParts() + update_icon() //Needed to add the prongs cleanly + +/obj/machinery/chem_master/RefreshParts() + var/scancount = 0 + var/lasercount = 0 + var/manipcount = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + if(istype(SP, /obj/item/weapon/stock_parts/manipulator)) manipcount += SP.rating-1 + if(istype(SP, /obj/item/weapon/stock_parts/scanning_module)) scancount += SP.rating-1 + if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 + max_bottle_size = initial(max_bottle_size) + lasercount*5 + max_pill_count = initial(max_pill_count) + manipcount*5 + handle_new_reservoir(scancount*25+100) + +/obj/machinery/chem_master/proc/handle_new_reservoir(var/newvol) + if(reagents.maximum_volume == newvol) return //Volume did not change + if(reagents.maximum_volume>newvol) + reagents.remove_any(reagents.maximum_volume-newvol) //If we have more than our new max, remove equally until we reach new max + reagents.maximum_volume = newvol + +/obj/machinery/chem_master/proc/user_moved(var/list/args) + var/event/E = args["event"] + if(!targetMoveKey) + E.handlers.Remove("\ref[src]:user_moved") + return + + var/turf/T = args["loc"] + + if(!Adjacent(T)) + if(E.holder) + E.holder.on_moved.Remove(targetMoveKey) + detach() + +/obj/machinery/chem_master/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if(prob(50)) + qdel(src) + return + +/obj/machinery/chem_master/blob_act() + if(prob(50)) + qdel(src) + +/obj/machinery/chem_master/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob) + if(..()) + return 1 + + else if(istype(B, /obj/item/weapon/reagent_containers/glass)) + + if(src.beaker) + to_chat(user, "There already is a beaker loaded in the machine.") + return + if(!user.drop_item(B, src)) + to_chat(user, "You can't let go of \the [B]!") + return + + src.beaker = B + if(user.type == /mob/living/silicon/robot) + var/mob/living/silicon/robot/R = user + R.uneq_active() + targetMoveKey = R.on_moved.Add(src, "user_moved") + + to_chat(user, "You add the beaker into \the [src]!") + + src.updateUsrDialog() + update_icon() + return 1 + + else if(istype(B, /obj/item/weapon/storage/pill_bottle)) + if(windowtype != "chem_master") //Only the chemmaster will accept pill bottles + to_chat(user, "This [name] does not come with a pill dispenser unit built-in.") + return + if(src.loaded_pill_bottle) + to_chat(user, "There already is a pill bottle loaded in the machine.") + return + if(!user.drop_item(B, src)) + to_chat(user, "You can't let go of \the [B]!") + return + + src.loaded_pill_bottle = B + + to_chat(user, "You add the pill bottle into \the [src]'s dispenser slot!") + + src.updateUsrDialog() + return 1 + +/obj/machinery/chem_master/Topic(href, href_list) + + if(..()) + return 1 + + usr.set_machine(src) + + if(href_list["ejectp"]) + if(loaded_pill_bottle) + loaded_pill_bottle.loc = src.loc + loaded_pill_bottle = null + src.updateUsrDialog() + return 1 + + else if(href_list["close"]) + usr << browse(null, "window=[windowtype]") + usr.unset_machine() + return 1 + + if(beaker) + var/datum/reagents/R = beaker.reagents + if(href_list["analyze"]) + var/dat = list() + if(!condi) + if(href_list["name"] == "Blood") + var/datum/reagent/blood/G + for(var/datum/reagent/F in R.reagent_list) + if(F.name == href_list["name"]) + G = F + break + var/A = G.name + var/B = G.data["blood_type"] + var/C = G.data["blood_DNA"] + dat += "Chemical infos:

    Name:
    [A]

    Description:
    Blood Type: [B]
    DNA: [C]


    (Back)" + else + dat += "Chemical infos:

    Name:
    [href_list["name"]]

    Description:
    [href_list["desc"]]


    (Back)" + else + dat += "Condiment infos:

    Name:
    [href_list["name"]]

    Description:
    [href_list["desc"]]


    (Back)" + //usr << browse(dat, "window=chem_master;size=575x400") + dat = list2text(dat) + var/datum/browser/popup = new(usr, "[windowtype]", "[name]", 585, 400, src) + popup.set_content(dat) + popup.open() + onclose(usr, "[windowtype]") + return 1 + + else if(href_list["add"]) + + if(href_list["amount"]) + var/id = href_list["add"] + var/amount = text2num(href_list["amount"]) + if(amount < 0) + return + R.trans_id_to(src, id, amount) + src.updateUsrDialog() + return 1 + + else if(href_list["addcustom"]) + + var/id = href_list["addcustom"] + useramount = input("Select the amount to transfer.", 30, useramount) as num + useramount = isgoodnumber(useramount) + src.Topic(null, list("amount" = "[useramount]", "add" = "[id]")) + src.updateUsrDialog() + return 1 + + else if(href_list["remove"]) + + if(href_list["amount"]) + var/id = href_list["remove"] + var/amount = text2num(href_list["amount"]) + if(amount < 0) + return + if(mode) + reagents.trans_id_to(beaker, id, amount) + else + reagents.remove_reagent(id, amount) + src.updateUsrDialog() + return 1 + + else if(href_list["removecustom"]) + + var/id = href_list["removecustom"] + useramount = input("Select the amount to transfer.", 30, useramount) as num + useramount = isgoodnumber(useramount) + src.Topic(null, list("amount" = "[useramount]", "remove" = "[id]")) + src.updateUsrDialog() + return 1 + + else if(href_list["toggle"]) + mode = !mode + src.updateUsrDialog() + return 1 + + else if(href_list["main"]) + attack_hand(usr) + src.updateUsrDialog() + return 1 + + else if(href_list["eject"]) + if(beaker) + detach() + src.updateUsrDialog() + return 1 + + else if(href_list["createpill"] || href_list["createpill_multiple"]) + var/count = 1 + if(href_list["createpill_multiple"]) count = isgoodnumber(input("Select the number of pills to make.", 10, max_pill_count) as num) + count = min(max_pill_count, count) + if(!count) + return + + var/amount_per_pill = reagents.total_volume/count + if(amount_per_pill > 50) + amount_per_pill = 50 + if(href_list["createempty"]) + amount_per_pill = 0 //If "createempty" is 1, pills are empty and no reagents are used. + + var/name = reject_bad_text(input(usr,"Name:","Name your pill!","[reagents.get_master_reagent_name()] ([amount_per_pill] units)") as null|text) + if(!name) + return + while(count--) + if((amount_per_pill == 0 || reagents.total_volume == 0) && !href_list["createempty"]) //Don't create empty pills unless "createempty" is 1! + break + + var/obj/item/weapon/reagent_containers/pill/P = new/obj/item/weapon/reagent_containers/pill(src.loc) + if(!name) + name = "[reagents.get_master_reagent_name()] ([amount_per_pill] units)" + P.name = "[name] pill" + P.pixel_x = rand(-7, 7) //Random position + P.pixel_y = rand(-7, 7) + P.icon_state = "pill"+pillsprite + reagents.trans_to(P,amount_per_pill) + if(src.loaded_pill_bottle) + if(loaded_pill_bottle.contents.len < loaded_pill_bottle.storage_slots) + P.loc = loaded_pill_bottle + + src.updateUsrDialog() + return 1 + + else if (href_list["createbottle"] || href_list["createbottle_multiple"]) + if(!condi) + var/name = reject_bad_text(input(usr,"Name:", "Name your bottle!", reagents.get_master_reagent_name())) + if(!name) + name = reagents.get_master_reagent_name() + var/count = 1 + if(href_list["createbottle_multiple"]) + count = isgoodnumber(input("Select the number of bottles to make.", 10, count) as num) + if(count > 4) + count = 4 + if(count < 1) + count = 1 + var/amount_per_bottle = reagents.total_volume > 0 ? reagents.total_volume/count : 0 + amount_per_bottle = min(amount_per_bottle,max_bottle_size) + while(count--) + var/obj/item/weapon/reagent_containers/glass/bottle/P = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc,max_bottle_size) + P.name = "[name] bottle" + P.pixel_x = rand(-7, 7) //random position + P.pixel_y = rand(-7, 7) + //P.icon_state = "bottle"+bottlesprite + reagents.trans_to(P,amount_per_bottle) + src.updateUsrDialog() + return 1 + else + var/obj/item/weapon/reagent_containers/food/condiment/P = new/obj/item/weapon/reagent_containers/food/condiment(src.loc) + reagents.trans_to(P, 50) + src.updateUsrDialog() + return 1 + + else if(href_list["change_pill"]) + #define MAX_PILL_SPRITE 20 //Max icon state of the pill sprites + var/dat = list() + dat += "" + for(var/i = 1 to MAX_PILL_SPRITE) + if(i%4 == 1) + dat += "" + + dat += "" + + if (i%4 == 0) + dat +="" + + dat += "
    " + dat = list2text(dat) + var/datum/browser/popup = new(usr, "[windowtype]", "[name]", 585, 400, src) + popup.set_content(dat) + popup.open() + onclose(usr, "[windowtype]") + //usr << browse(dat, "window=[windowtype]") + return 1 + + /* + else if(href_list["change_bottle"]) + #define MAX_BOTTLE_SPRITE 20 //max icon state of the bottle sprites + var/dat = "" + for(var/i = 1 to MAX_BOTTLE_SPRITE) + if ( i%4==1 ) + dat += "" + + dat += "" + + if ( i%4==0 ) + dat +="" + + dat += "
    " + usr << browse(dat, "window=chem_master") + return + */ + + else if(href_list["pill_sprite"]) + pillsprite = href_list["pill_sprite"] + src.updateUsrDialog() + return 1 + + /* + else if(href_list["bottle_sprite"]) + bottlesprite = href_list["bottle_sprite"] + */ + +/obj/machinery/chem_master/proc/detach() + if(beaker) + beaker.loc = src.loc + beaker.pixel_x = 0 //We fucked with the beaker for overlays, so reset that + beaker.pixel_y = 0 //We fucked with the beaker for overlays, so reset that + if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) + var/mob/living/silicon/robot/R = beaker:holder:loc + if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) + beaker.loc = R + else + beaker.loc = beaker:holder + beaker = null + reagents.clear_reagents() + update_icon() + +/obj/machinery/chem_master/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/chem_master/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/chem_master/attack_hand(mob/user as mob) + + . = ..() + if(.) + return + + user.set_machine(src) + if(!(user.client in has_sprites)) + spawn() + has_sprites += user.client + for(var/i = 1 to MAX_PILL_SPRITE) + usr << browse_rsc(icon('icons/obj/chemical.dmi', "pill" + num2text(i)), "pill[i].png") + /* + for(var/i = 1 to MAX_BOTTLE_SPRITE) + usr << browse_rsc(icon('icons/obj/chemical.dmi', "bottle" + num2text(i)), "bottle[i].png") + */ + + var/dat = list() + if(!beaker) + dat += "Please insert a beaker.
    " + if(!condi) + if(src.loaded_pill_bottle) + dat += "Eject Pill Bottle \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.storage_slots]\]

    " + else + dat += "No pill bottle inserted.

    " + //dat += "Close" + else + var/datum/reagents/R = beaker.reagents + dat += "Eject beaker and Clear Buffer
    " + if(src.loaded_pill_bottle) + dat += "Eject Pill Bottle \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.storage_slots]\]

    " + else if(windowtype == "chem_master") + dat += "No pill bottle inserted.

    " + if(!R.total_volume) + dat += "Beaker is empty." + else + dat += "Add to buffer:
    " + for(var/datum/reagent/G in R.reagent_list) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:518: dat += "[G.name] , [G.volume] Units - " + dat += {"[G.name] , [G.volume] Units - + (Analyze) + (1) + (5) + (10) + (All) + (Custom)
    "} + // END AUTOFIX + + dat += "
    Transfer to [(!mode ? "disposal" : "beaker")]:
    " + if(reagents.total_volume) + for(var/datum/reagent/N in reagents.reagent_list) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:529: dat += "[N.name] , [N.volume] Units - " + dat += {"[N.name] , [N.volume] Units - + (Analyze) + (1) + (5) + (10) + (All) + (Custom)
    "} + // END AUTOFIX + else + dat += "Buffer is empty.
    " + if(!condi) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:539: dat += "

    Create pill (50 units max)
    " + //dat += {"
    "} + dat += {"
    "} + dat += {"

    Create single pill (50 units max)
    + Create multiple pills (50 units max each; [max_pill_count] max)
    + Create empty pills
    + Create bottle ([max_bottle_size] units max)
    + Create multiple bottles ([max_bottle_size] units max each; 4 max)
    "} + // END AUTOFIX + else + dat += "Create bottle (50 units max)" + dat = list2text(dat) + var/datum/browser/popup = new(user, "[windowtype]", "[name]", 575, 400, src) + popup.set_content(dat) + popup.open() + onclose(user, "[windowtype]") + return + +/obj/machinery/chem_master/proc/isgoodnumber(var/num) + if(isnum(num)) + if(num > 200) + num = 200 + else if(num < 0) + num = 1 + else + num = round(num) + return num + else + return 0 + +/obj/machinery/chem_master/update_icon() + + overlays.len = 0 + + if(beaker) + beaker.pixel_x = -9 //Move it far to the left + beaker.pixel_y = 5 //Move it up + beaker.update_icon() //Forcefully update the beaker + overlays += beaker //Set it as an overlay + + if(reagents.total_volume && !(stat & (BROKEN|NOPOWER))) //If we have reagents in here, and the machine is powered and functional + var/image/overlay = image('icons/obj/chemical.dmi', src, "mixer_overlay") + overlay.icon += mix_color_from_reagents(reagents.reagent_list) + overlays += overlay + + var/image/mixer_prongs = image('icons/obj/chemical.dmi', src, "mixer_prongs") + overlays += mixer_prongs //Add prongs on top of all of this + +/obj/machinery/chem_master/on_reagent_change() + update_icon() + +/obj/machinery/chem_master/condimaster + name = "\improper CondiMaster 3000" + condi = 1 + chem_board = /obj/item/weapon/circuitboard/condimaster + windowtype = "condi_master" + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +/obj/machinery/computer/pandemic + name = "PanD.E.M.I.C 2200" + density = 1 + anchored = 1 + icon = 'icons/obj/chemical.dmi' + icon_state = "mixer0" + use_power = 1 + idle_power_usage = 20 + var/temphtml = "" + var/wait = null + var/obj/item/weapon/reagent_containers/glass/beaker = null + + light_color = LIGHT_COLOR_BLUE + var/targetMoveKey + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +/obj/machinery/computer/pandemic/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/pandemic + ) + + RefreshParts() + +/obj/machinery/computer/pandemic/proc/user_moved(var/list/args) + var/event/E = args["event"] + if(!targetMoveKey) + E.handlers.Remove("\ref[src]:user_moved") + return + + var/turf/T = args["loc"] + + if(!Adjacent(T)) + if(E.holder) + E.holder.on_moved.Remove(targetMoveKey) + detach() + + +/obj/machinery/computer/pandemic/set_broken() + icon_state = (src.beaker?"mixer1_b":"mixer0_b") + stat |= BROKEN + + +/obj/machinery/computer/pandemic/power_change() + + if(stat & BROKEN) + icon_state = (src.beaker?"mixer1_b":"mixer0_b") + + else if(powered()) + icon_state = (src.beaker?"mixer1":"mixer0") + stat &= ~NOPOWER + + else + spawn(rand(0, 15)) + src.icon_state = (src.beaker?"mixer1_nopower":"mixer0_nopower") + stat |= NOPOWER + + +/obj/machinery/computer/pandemic/Topic(href, href_list) + if(stat & (NOPOWER|BROKEN)) return + if(usr.stat || usr.restrained()) return + if(!in_range(src, usr)) return + + usr.set_machine(src) + if(!beaker) return + + if (href_list["create_vaccine"]) + if(!src.wait) + var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc) + if(B) + var/path = href_list["create_vaccine"] + var/vaccine_type = text2path(path) + var/datum/disease/D = null + + if(!vaccine_type) + D = archive_diseases[path] + vaccine_type = path + else + if(vaccine_type in diseases) + D = new vaccine_type(0, null) + + if(D) + B.name = "[D.name] vaccine bottle" + B.reagents.add_reagent("vaccine",15,vaccine_type) + wait = 1 + var/datum/reagents/R = beaker.reagents + var/datum/reagent/blood/Blood = null + for(var/datum/reagent/blood/L in R.reagent_list) + if(L) + Blood = L + break + var/list/res = Blood.data["resistances"] + spawn(res.len*200) + src.wait = null + else + src.temphtml = "The replicator is not ready yet." + src.updateUsrDialog() + return + else if (href_list["create_virus_culture"]) + if(!wait) + var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc) + B.icon_state = "bottle3" + var/type = text2path(href_list["create_virus_culture"])//the path is received as string - converting + var/datum/disease/D = null + if(!type) + var/datum/disease/advance/A = archive_diseases[href_list["create_virus_culture"]] + if(A) + D = new A.type(0, A) + else + if(type in diseases) // Make sure this is a disease + D = new type(0, null) + var/list/data = list("viruses"=list(D)) + var/name = sanitize(input(usr,"Name:","Name the culture",D.name)) + if(!name || name == " ") name = D.name + B.name = "[name] culture bottle" + B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium." + B.reagents.add_reagent("blood",20,data) + src.updateUsrDialog() + wait = 1 + spawn(1000) + src.wait = null + else + src.temphtml = "The replicator is not ready yet." + src.updateUsrDialog() + return + else if (href_list["empty_beaker"]) + beaker.reagents.clear_reagents() + src.updateUsrDialog() + return + else if (href_list["eject"]) + detach() + return + else if(href_list["clear"]) + src.temphtml = "" + src.updateUsrDialog() + return + else if(href_list["name_disease"]) + var/norange = (usr.mutations && usr.mutations.len && (M_TK in usr.mutations)) + var/new_name = stripped_input(usr, "Name the Disease", "New Name", "", MAX_NAME_LEN) + if(stat & (NOPOWER|BROKEN)) return + if(usr.stat || usr.restrained()) return + if(!in_range(src, usr) && !norange) return + var/id = href_list["name_disease"] + if(archive_diseases[id]) + var/datum/disease/advance/A = archive_diseases[id] + A.AssignName(new_name) + for(var/datum/disease/advance/AD in active_diseases) + AD.Refresh() + src.updateUsrDialog() + + + else + usr << browse(null, "window=pandemic") + src.updateUsrDialog() + return + + src.add_fingerprint(usr) + return + +/obj/machinery/computer/pandemic/proc/detach() + beaker.loc = src.loc + if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) + var/mob/living/silicon/robot/R = beaker:holder:loc + if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) + beaker.loc = R + else + beaker.loc = beaker:holder + beaker = null + icon_state = "mixer0" + src.updateUsrDialog() +/obj/machinery/computer/pandemic/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/computer/pandemic/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/computer/pandemic/attack_hand(mob/user as mob) + if(stat & (NOPOWER|BROKEN)) + return + user.set_machine(src) + var/dat = "" + if(src.temphtml) + dat = "[src.temphtml]

    Main Menu" + else if(!beaker) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:722: dat += "Please insert beaker.
    " + dat += {"Please insert beaker.
    + Close"} + // END AUTOFIX + else + var/datum/reagents/R = beaker.reagents + var/datum/reagent/blood/Blood = null + for(var/datum/reagent/blood/B in R.reagent_list) + if(B) + Blood = B + break + if(!R.total_volume||!R.reagent_list.len) + dat += "The beaker is empty
    " + else if(!Blood) + dat += "No blood sample found in beaker" + else if(!Blood.data) + dat += "No blood data found in beaker." + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:738: dat += "

    Blood sample data:

    " + dat += {"

    Blood sample data:

    + Blood DNA: [(Blood.data["blood_DNA"]||"none")]
    + Blood Type: [(Blood.data["blood_type"]||"none")]
    "} + // END AUTOFIX + if(Blood.data["viruses"]) + var/list/vir = Blood.data["viruses"] + if(vir.len) + for(var/datum/disease/D in Blood.data["viruses"]) + if(!D.hidden[PANDEMIC]) + + + var/disease_creation = D.type + if(istype(D, /datum/disease/advance)) + + var/datum/disease/advance/A = D + D = archive_diseases[A.GetDiseaseID()] + disease_creation = A.GetDiseaseID() + if(D.name == "Unknown") + dat += "Name Disease
    " + + if(!D) + CRASH("We weren't able to get the advance disease from the archive.") + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:762: dat += "Disease Agent: [D?"[D.agent] - Create virus culture bottle":"none"]
    " + dat += {"Disease Agent: [D?"[D.agent] - Create virus culture bottle":"none"]
    + Common name: [(D.name||"none")]
    + Description: [(D.desc||"none")]
    + Spread: [(D.spread||"none")]
    + Possible cure: [(D.cure||"none")]

    "} + // END AUTOFIX + if(istype(D, /datum/disease/advance)) + var/datum/disease/advance/A = D + dat += "Symptoms: " + var/english_symptoms = list() + for(var/datum/symptom/S in A.symptoms) + english_symptoms += S.name + dat += english_list(english_symptoms) + + + dat += "
    Contains antibodies to: " + if(Blood.data["resistances"]) + var/list/res = Blood.data["resistances"] + if(res.len) + dat += "
      " + for(var/type in Blood.data["resistances"]) + var/disease_name = "Unknown" + + if(!ispath(type)) + var/datum/disease/advance/A = archive_diseases[type] + if(A) + disease_name = A.name + else + var/datum/disease/D = new type(0, null) + disease_name = D.name + + dat += "
    • [disease_name] - Create vaccine bottle
    • " + dat += "

    " + else + dat += "nothing
    " + else + dat += "nothing
    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:799: dat += "
    Eject beaker[((R.total_volume&&R.reagent_list.len) ? "-- Empty beaker":"")]
    " + dat += {"
    Eject beaker[((R.total_volume&&R.reagent_list.len) ? "-- Empty beaker":"")]
    + Close"} + // END AUTOFIX + user << browse("[src.name]
    [dat]", "window=pandemic;size=575x400") + onclose(user, "pandemic") + return + + +/obj/machinery/computer/pandemic/attackby(var/obj/I as obj, var/mob/user as mob) + if(..()) + return 1 + else if(istype(I, /obj/item/weapon/reagent_containers/glass)) + if(stat & (NOPOWER|BROKEN)) return + if(src.beaker) + to_chat(user, "A beaker is already loaded into the machine.") + return + if(!user.drop_item(I, src)) + to_chat(user, "You can't let go of \the [I]!") + return + + src.beaker = I + if(user.type == /mob/living/silicon/robot) + var/mob/living/silicon/robot/R = user + R.uneq_active() + targetMoveKey = R.on_moved.Add(src, "user_moved") + + to_chat(user, "You add the beaker to the machine!") + + src.updateUsrDialog() + icon_state = "mixer1" + + else + ..() + return +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +/obj/machinery/reagentgrinder + + name = "All-In-One Grinder" + icon = 'icons/obj/kitchen.dmi' + icon_state = "juicer1" + layer = 2.9 + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK | EJECTNOTDEL + pass_flags = PASSTABLE + var/inuse = 0 + var/obj/item/weapon/reagent_containers/beaker = null + var/limit = 10 + var/speed_multiplier = 1 + var/list/blend_items = list ( + + //Sheets + /obj/item/stack/sheet/metal = list("iron" = 20), + /obj/item/stack/sheet/mineral/plasma = list("plasma" = 20), + /obj/item/stack/sheet/mineral/uranium = list("uranium" = 20), + /obj/item/stack/sheet/mineral/clown = list("banana" = 20), + /obj/item/stack/sheet/mineral/silver = list("silver" = 20), + /obj/item/stack/sheet/mineral/gold = list("gold" = 20), + /obj/item/weapon/grown/nettle = list("sacid" = 0), + /obj/item/weapon/grown/deathnettle = list("pacid" = 0), + /obj/item/stack/sheet/charcoal = list("charcoal" = 20), + + //Blender Stuff + /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = -10), //I have no fucking idea what most of these numbers mean and I hate them. + /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("ketchup" = -7), + /obj/item/weapon/reagent_containers/food/snacks/grown/corn = list("cornoil" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5), + /obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk = list("rice" = -5), + /obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/plastellium = list("plasticide" = 5), + + /obj/item/seeds = list("blackpepper" = 5), + + + //archaeology! + /obj/item/weapon/rocksliver = list("ground_rock" = 30), + + //All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.! + /obj/item/weapon/reagent_containers/pill = list(), + /obj/item/weapon/reagent_containers/food = list() + ) + + var/list/juice_items = list ( + + //Juicer Stuff + /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/banana = list("banana" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/potato = list("potato" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/apple = list("applejuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = list("lemonjuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/orange = list("orangejuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/lime = list("limejuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0), + /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = list("poisonberryjuice" = 0), + ) + + + var/list/holdingitems = list() + var/targetMoveKey + +/******************************************************************** +** Adding Stock Parts to VV so preconstructed shit has its candy ** +********************************************************************/ +//Leaving large beakers out of the component part list to try and dodge beaker cloning. +/obj/machinery/reagentgrinder/New() + . = ..() + beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) + + component_parts = newlist( + /obj/item/weapon/circuitboard/reagentgrinder, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/stock_parts/scanning_module + ) + + RefreshParts() + + return + +/obj/machinery/reagentgrinder/proc/user_moved(var/list/args) + var/event/E = args["event"] + if(!targetMoveKey) + E.handlers.Remove("\ref[src]:user_moved") + return + + var/turf/T = args["loc"] + + if(!Adjacent(T)) + if(E.holder) + E.holder.on_moved.Remove(targetMoveKey) + detach() + + +/obj/machinery/reagentgrinder/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) + T += M.rating-1 + limit = initial(limit)+(T * 5) + + T = 0 + for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) + T += M.rating-1 + speed_multiplier = initial(speed_multiplier)+(T * 0.50) + +/obj/machinery/reagentgrinder/update_icon() + icon_state = "juicer"+num2text(!isnull(beaker)) + return + +/obj/machinery/reagentgrinder/togglePanelOpen(var/obj/toggleitem, mob/user) + if(beaker) + to_chat(user, "You can't reach \the [src]'s maintenance panel with the beaker in the way!") + return -1 + return ..() + +/obj/machinery/reagentgrinder/crowbarDestroy(mob/user) + if(beaker) + to_chat(user, "You can't do that while \the [src] has a beaker loaded!") + return -1 + return ..() + +/obj/machinery/reagentgrinder/attackby(var/obj/item/O as obj, var/mob/user as mob) + + if(..()) + return 1 + + if (istype(O,/obj/item/weapon/reagent_containers/glass) || \ + istype(O,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass) || \ + istype(O,/obj/item/weapon/reagent_containers/food/drinks/shaker)) + + if (beaker) + return 0 + if (panel_open) + to_chat(user, "You can't load a beaker while the maintenance panel is open.") + return 0 + else + if(!user.drop_item(O, src)) + to_chat(user, "You can't let go of \the [O]!") + return + + src.beaker = O + if(user.type == /mob/living/silicon/robot) + var/mob/living/silicon/robot/R = user + R.uneq_active() + targetMoveKey = R.on_moved.Add(src, "user_moved") + + update_icon() + src.updateUsrDialog() + return 1 + + if(holdingitems && holdingitems.len >= limit) + to_chat(usr, "The machine cannot hold any more items.") + return 1 + + //Fill machine with bags + if(istype(O, /obj/item/weapon/storage/bag/plants)||istype(O, /obj/item/weapon/storage/bag/chem)) + var/obj/item/weapon/storage/bag/B = O + for (var/obj/item/G in O.contents) + B.remove_from_storage(G,src) + holdingitems += G + if(holdingitems && holdingitems.len >= limit) //Sanity checking so the blender doesn't overfill + to_chat(user, "You fill the All-In-One grinder to the brim.") + break + + if(!O.contents.len) + to_chat(user, "You empty the [O] into the All-In-One grinder.") + + src.updateUsrDialog() + return 0 + + if (!is_type_in_list(O, blend_items) && !is_type_in_list(O, juice_items)) + to_chat(user, "Cannot refine into a reagent.") + return 1 + + if(!user.drop_item(O, src)) + user << "\The [O] is stuck to your hands!" + return 1 + + holdingitems += O + src.updateUsrDialog() + return 0 + +/obj/machinery/reagentgrinder/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/reagentgrinder/attack_ai(mob/user as mob) + return 0 + +/obj/machinery/reagentgrinder/attack_hand(mob/user as mob) + user.set_machine(src) + interact(user) + +/obj/machinery/reagentgrinder/attack_robot(mob/user as mob) + return attack_hand(user) + +/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu + var/is_chamber_empty = 0 + var/is_beaker_ready = 0 + var/processing_chamber = "" + var/beaker_contents = "" + var/dat = list() + + if(!inuse) + for (var/obj/item/O in holdingitems) + processing_chamber += "\A [O.name]
    " + + if (!processing_chamber) + is_chamber_empty = 1 + processing_chamber = "Nothing." + if (!beaker) + beaker_contents = "No beaker attached.
    " + else + is_beaker_ready = 1 + beaker_contents = "The beaker contains:
    " + var/anything = 0 + for(var/datum/reagent/R in beaker.reagents.reagent_list) + anything = 1 + beaker_contents += "[R.volume] - [R.name]
    " + if(!anything) + beaker_contents += "Nothing
    " + + + dat += {" + Processing chamber contains:
    + [processing_chamber]
    + [beaker_contents]
    + "} + if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN))) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\reagents\Chemistry-Machinery.dm:1016: dat += "Grind the reagents
    " + dat += {"Grind the reagents
    + Juice the reagents

    "} + // END AUTOFIX + if(holdingitems && holdingitems.len > 0) + dat += "Eject the reagents
    " + if (beaker) + dat += "Detach the beaker
    " + else + dat += "Please wait..." + dat = list2text(dat) + var/datum/browser/popup = new(user, "reagentgrinder", "All-In-One Grinder", src) + popup.set_content(dat) + popup.open() + onclose(user, "reagentgrinder") + return + + +/obj/machinery/reagentgrinder/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + switch(href_list["action"]) + if ("grind") + grind() + if("juice") + juice() + if("eject") + eject() + if ("detach") + detach() + src.updateUsrDialog() + return + +/obj/machinery/reagentgrinder/proc/detach() + + + if (usr.stat != 0) + return + if (!beaker) + return + beaker.loc = src.loc + if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) + var/mob/living/silicon/robot/R = beaker:holder:loc + if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) + beaker.loc = R + else + beaker.loc = beaker:holder + beaker = null + update_icon() + +/obj/machinery/reagentgrinder/proc/eject() + + + if (usr.stat != 0) + return + if (holdingitems && holdingitems.len == 0) + return + + for(var/obj/item/O in holdingitems) + O.loc = src.loc + holdingitems -= O + holdingitems = list() + +/obj/machinery/reagentgrinder/proc/is_allowed(var/obj/item/weapon/reagent_containers/O) + for (var/i in blend_items) + if(istype(O, i)) + return 1 + return 0 + +/obj/machinery/reagentgrinder/proc/get_allowed_by_id(var/obj/item/weapon/grown/O) + for (var/i in blend_items) + if (istype(O, i)) + return blend_items[i] + +/obj/machinery/reagentgrinder/proc/get_allowed_snack_by_id(var/obj/item/weapon/reagent_containers/food/snacks/O) + for(var/i in blend_items) + if(istype(O, i)) + return blend_items[i] + +/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_id(var/obj/item/weapon/reagent_containers/food/snacks/O) + for(var/i in juice_items) + if(istype(O, i)) + return juice_items[i] + +/obj/machinery/reagentgrinder/proc/get_grownweapon_amount(var/obj/item/weapon/grown/O) + if (!istype(O)) + return 5 + else if (O.potency == -1) + return 5 + else + return round(O.potency) + +/obj/machinery/reagentgrinder/proc/get_juice_amount(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) + if (!istype(O)) + return 5 + else if (O.potency == -1) + return 5 + else + return round(5*sqrt(O.potency)) + +/obj/machinery/reagentgrinder/proc/remove_object(var/obj/item/O) + holdingitems -= O + qdel(O) + O = null + +/obj/machinery/reagentgrinder/proc/juice() + power_change() + if(stat & (NOPOWER|BROKEN)) + return + if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) + return + playsound(get_turf(src), speed_multiplier < 2 ? 'sound/machines/juicer.ogg' : 'sound/machines/juicerfast.ogg', 30, 1) + inuse = 1 + spawn(50/speed_multiplier) + inuse = 0 + interact(usr) + //Snacks + for (var/obj/item/weapon/reagent_containers/food/snacks/O in holdingitems) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + + var/allowed = get_allowed_juice_by_id(O) + if(isnull(allowed)) + break + + for (var/r_id in allowed) + + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = get_juice_amount(O) + + beaker.reagents.add_reagent(r_id, min(amount, space)) + + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + + remove_object(O) + +/obj/machinery/reagentgrinder/proc/grind() + + + power_change() + if(stat & (NOPOWER|BROKEN)) + return + if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) + return + playsound(get_turf(src), speed_multiplier < 2 ? 'sound/machines/blender.ogg' : 'sound/machines/blenderfast.ogg', 50, 1) + inuse = 1 + spawn(60/speed_multiplier) + inuse = 0 + interact(usr) + //Snacks and Plants + for (var/obj/item/weapon/reagent_containers/food/snacks/O in holdingitems) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + + var/allowed = get_allowed_snack_by_id(O) + if(isnull(allowed)) + break + + for (var/r_id in allowed) + + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = allowed[r_id] + if(amount <= 0) + if(amount == 0) + if (O.reagents != null && O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment"), space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + else + if (O.reagents != null && O.reagents.has_reagent("nutriment")) + beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)), space)) + O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space)) + + else + O.reagents.trans_id_to(beaker, r_id, min(amount, space)) + + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + + if(O.reagents.reagent_list.len == 0) + remove_object(O) + + //Sheets + for (var/obj/item/stack/sheet/O in holdingitems) + var/allowed = get_allowed_by_id(O) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + for(var/i = 1; i <= round(O.amount, 1); i++) + for (var/r_id in allowed) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = allowed[r_id] + beaker.reagents.add_reagent(r_id,min(amount, space)) + if (space < amount) + break + if (i == round(O.amount, 1)) + remove_object(O) + break + + //xenoarch + for(var/obj/item/weapon/rocksliver/O in holdingitems) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + var/allowed = get_allowed_by_id(O) + for (var/r_id in allowed) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = allowed[r_id] + beaker.reagents.add_reagent(r_id,min(amount, space), O.geological_data) + + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + remove_object(O) + + //Everything else - Transfers reagents from it into beaker + for (var/obj/item/weapon/reagent_containers/O in holdingitems) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + var/amount = O.reagents.total_volume + O.reagents.trans_to(beaker, amount) + if(!O.reagents.total_volume) + remove_object(O) + + //All other generics + for (var/obj/item/O in holdingitems) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + var/allowed = get_allowed_by_id(O) + for (var/r_id in allowed) + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/amount = allowed[r_id] + if (amount == 0) + if (O.reagents != null && O.reagents.has_reagent(r_id)) + beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id), space)) + else + beaker.reagents.add_reagent(r_id,min(amount, space)) + + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + remove_object(O) + +//************************************************************************************* +// +// +//It just felt right to put the ghetto chemistry tools here with chemistry machinery. +// +// +//************************************************************************************* +/obj/item/weapon/electrolyzer + name = "Electrolyzer" + icon = 'icons/obj/chemical.dmi' + icon_state = "chemg_wired" + item_state = "chemg_wired" + desc = "A refurbished grenade-casing jury rigged to split simple chemicals." + w_class = 2.0 + force = 2.0 + var/list/beakers = new/list() + var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass, /obj/item/weapon/reagent_containers/food/drinks/soda_cans/) + var/datum/effect/effect/system/spark_spread/spark_system + +/obj/item/weapon/electrolyzer/New() + . = ..() + spark_system = new + spark_system.set_up(5, 0, src) + spark_system.attach(src) + +/obj/item/weapon/electrolyzer/Destroy() + qdel(spark_system) + spark_system = null + . = ..() + +/obj/item/weapon/electrolyzer/attack_self(mob/user as mob) + if(beakers.len) + for(var/obj/B in beakers) + if(istype(B)) + beakers -= B + user.put_in_hands(B) + to_chat(user, "You remove the containers from the electrolyzer.") + +/obj/item/weapon/electrolyzer/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(iswirecutter(W)) + if(beakers.len) + to_chat(user, "The electrolyzer contains beakers!") + return + else + to_chat(user, "You disassemble the electrolyzer.") + var/turf/T = get_turf(src) + new /obj/item/stack/cable_coil(T,2) + new /obj/item/weapon/grenade/chem_grenade(T) + qdel(src) + return + else if(is_type_in_list(W, allowed_containers)) + var/obj/item/weapon/reagent_containers/glass/G = W + if(G.reagents.reagent_list.len > 1) + to_chat(user, "That mixture is too complex!") + return + if(beakers.len == 2) + to_chat(user, "The grenade can not hold more containers.") + return + else if(beakers.len == 1) + var/obj/item/weapon/reagent_containers/glass/other = beakers[1] + if(other.reagents.total_volume && !G.reagents.total_volume) //We already have one inserted beaker. It must occupy slot 1. Is it empty or active? + to_chat(user, "You add \the [G] to the electrolyzer as the empty container.") + insert_beaker(G,user) + else if(!other.reagents.total_volume && G.reagents.total_volume) + to_chat(user, "You add \the [G] to the electrolyzer as the active container.") + insert_beaker(G,user) + else + to_chat(user, "The electrolyzer requires one active beaker and one empty beaker!") + return + else + to_chat(user, "You add \the [G] to the electrolyzer as the [G.reagents.total_volume ? "active" : "empty"] container.") + insert_beaker(G,user) + else if(istype(W, /obj/item/weapon/cell)) + if(beakers.len < 2) + to_chat(user, "The electrolyzer requires one active beaker and one empty beaker!") + return + var/obj/item/weapon/cell/C = W + var/obj/item/weapon/reagent_containers/active = null + var/obj/item/weapon/reagent_containers/empty = null + var/datum/chemical_reaction/unreaction = null + for(var/obj/item/weapon/reagent_containers/B in beakers) + if(B.reagents.reagent_list.len > 1) //This only fires if their power ran out with a first cell and they try electrolyzing again without removing the old mix + to_chat(user, "That mixture is too complex!") + return + else if(B.reagents.reagent_list.len == 1) + active = B + else if (!B.reagents.reagent_list.len) + empty = B + else + to_chat(user, "An error has occured. Your beaker had between 0 and 1 reagents. Please report this message.") + if(!active || !empty) + to_chat(user, "There must be both an empty and active beaker.") + return + var/datum/reagent/target = active.reagents.reagent_list[1] //Should only have one thing anyway + for(var/R in typesof(/datum/chemical_reaction/)) + var/datum/chemical_reaction/check = new R + if(check.id == target.id) + unreaction = check + break + if(!unreaction) + to_chat(user, "The system didn't react...") + return + var/total_reactions = round(active.reagents.total_volume / unreaction.result_amount) + var/primary = 1 + if(C.charge<30*total_reactions) + total_reactions = round(C.charge/30) //In the case that we don't have ENOUGH charge, this will react us as often as we can + C.charge -= (30*total_reactions) + active.reagents.remove_reagent(unreaction.result,total_reactions*unreaction.result_amount) //This moves over the reactive bulk, and leaves behind the amount too small to react + for(var/E in unreaction.required_reagents) + if(primary) + active.reagents.add_reagent(E, unreaction.required_reagents[E]*total_reactions) //Put component amount * reaction count back in primary + primary = 0 + else + empty.reagents.add_reagent(E, unreaction.required_reagents[E]*total_reactions) + to_chat(user, "The system electrolyzes!") + spark_system.start() + else + ..() + +/obj/item/weapon/electrolyzer/proc/insert_beaker(obj/item/weapon/W as obj, mob/user as mob) + if(user.drop_item(W, src)) + W.loc = src + beakers += W + else + to_chat(user, "You can't let go of \the [W]!") + return + + +/obj/structure/centrifuge + name = "suspicious toilet" + desc = "This toilet is a cleverly disguised improvised centrifuge." + icon = 'icons/obj/watercloset.dmi' + icon_state = "toilet11" + density = 0 + anchored = 1 + var/list/cans = new/list() //These are the empty containers. + var/obj/item/weapon/reagent_containers/beaker = null // This is the active container + + var/targetMoveKey + +/obj/structure/centrifuge/examine(mob/user) + ..() + to_chat(user, "It contains [cans.len] empty containers[beaker ? " and an active container!" : "."]") + +/obj/structure/centrifuge/attackby(obj/item/weapon/reagent_containers/W as obj, mob/user as mob) + if(iscrowbar(W)) + var/obj/structure/toilet/T = new /obj/structure/toilet(src.loc) + T.open = 1 + T.cistern = 1 + T.dir = src.dir + T.update_icon() + new /obj/item/stack/rods(get_turf(src), 2) + to_chat(user, "You pry out the rods, destroying the filter.") + qdel(src) + if(W.is_open_container()) + if(!W.reagents.total_volume) + if(user.drop_item(W, src)) + cans += W + to_chat(user, "You add a passive container. It now contains [cans.len].") + else + if(!beaker) + if(user.drop_item(W, src)) + to_chat(user, "You insert an active container.") + src.beaker = W + if(user.type == /mob/living/silicon/robot) + var/mob/living/silicon/robot/R = user + R.uneq_active() + targetMoveKey = R.on_moved.Add(src, "user_moved") + else + to_chat(user, "There is already an active container.") + return + else + ..() +/obj/structure/centrifuge/proc/user_moved(var/list/args) + var/event/E = args["event"] + if(!targetMoveKey) + E.handlers.Remove("\ref[src]:user_moved") + return + + var/turf/T = args["loc"] + + if(!Adjacent(T)) + if(E.holder) + E.holder.on_moved.Remove(targetMoveKey) + detach() + +/obj/structure/centrifuge/attack_hand(mob/user as mob) + add_fingerprint(user) + if(cans.len || beaker) + for(var/obj/item/O in cans) + O.loc = src.loc + cans -= O + if(beaker) + detach() + to_chat(user, "You remove everything from the centrifuge.") + else + to_chat(user, "There is nothing to eject!") + +/obj/structure/centrifuge/verb/flush() + set name = "Flush" + set category = "Object" + set src in view(1) + + if(!usr.canmove || usr.isUnconscious() || usr.restrained() || !usr.dexterity_check()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain + return + + if(!cans || !beaker) + to_chat(usr, "\The [src] needs an active container and multiple passive containers to work.") + return + + add_fingerprint(usr) + to_chat(usr, "\The [src] groans as it spits out containers.") + while(cans.len>0 && beaker.reagents.reagent_list.len>0) + var/obj/item/weapon/reagent_containers/C = cans[1] + var/datum/reagent/R = beaker.reagents.reagent_list[1] + beaker.reagents.trans_id_to(C,R.id,50) + C.loc = src.loc + cans -= C + if(!cans.len&&beaker.reagents.reagent_list.len) + to_chat(usr, "With no remaining containers, the rest of the concoction swirls down the drain...") + beaker.reagents.clear_reagents() + if(!beaker.reagents.reagent_list.len) + to_chat(usr, "The now-empty active container plops out.") + detach() + return + +/obj/structure/centrifuge/AltClick() + if(Adjacent(usr)) + flush() + return + return ..() + +/obj/structure/centrifuge/proc/detach() + if(beaker) + beaker.forceMove(src.loc) + if(istype(beaker, /obj/item/weapon/reagent_containers/glass/beaker/large/cyborg)) + var/mob/living/silicon/robot/R = beaker:holder:loc + if(R.module_state_1 == beaker || R.module_state_2 == beaker || R.module_state_3 == beaker) + beaker.loc = R + else + beaker.loc = beaker:holder + beaker = null + return + +/obj/item/weapon/reagent_containers/glass/mortar + name = "mortar" + desc = "This is a reinforced bowl, used for crushing reagents. Ooga booga Rockstop." + icon = 'icons/obj/food.dmi' + icon_state = "mortar" + flags = FPRINT | OPENCONTAINER + volume = 50 + amount_per_transfer_from_this = 5 + //We want the all-in-one grinder audience + + var/list/blend_items = list ( + /obj/item/stack/sheet/metal = list("iron",20), + /obj/item/stack/sheet/mineral/plasma = list("plasma",20), + /obj/item/stack/sheet/mineral/uranium = list("uranium",20), + /obj/item/stack/sheet/mineral/clown = list("banana",20), + /obj/item/stack/sheet/mineral/silver = list("silver",20), + /obj/item/stack/sheet/mineral/gold = list("gold",20), + /obj/item/weapon/grown/nettle = list("sacid",0), + /obj/item/weapon/grown/deathnettle = list("pacid",0), + /obj/item/stack/sheet/charcoal = list("charcoal",20), + /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list("soymilk",1), + /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("ketchup",2), + /obj/item/weapon/reagent_containers/food/snacks/grown/corn = list("cornoil",3), + /obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour",5), + /obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk = list("rice",5), + /obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly",1), + /obj/item/seeds = list("blackpepper",5), + /obj/item/device/flashlight/flare = list("sulfur",10), + /obj/item/stack/cable_coil = list("copper", 10), + /obj/item/weapon/cell = list("lithium", 10), + /obj/item/clothing/head/butt = list("mercury", 10), + /obj/item/weapon/rocksliver = list("ground_rock",30), + + //Recipes must include both variables! + /obj/item/weapon/reagent_containers/food = list("generic",0) + ) + + var/list/juice_items = list ( + /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("tomatojuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = list("carrotjuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/berries = list("berryjuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/banana = list("banana",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/potato = list("potato",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = list("lemonjuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/orange = list("orangejuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/lime = list("limejuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice",0), + /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice",0), + /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = list("poisonberryjuice",0), + ) + + + var/obj/item/crushable = null + +/obj/item/weapon/reagent_containers/glass/mortar/Destroy() + qdel(crushable) + crushable = null + . = ..() + +/obj/item/weapon/reagent_containers/glass/mortar/attackby(var/obj/item/O as obj, var/mob/user as mob) + if (isscrewdriver(O)) + if(crushable) + crushable.forceMove(user.loc) + new /obj/item/stack/sheet/metal(user.loc) + new /obj/item/trash/bowl(user.loc) + qdel(src) //Important detail + return + if (crushable) + to_chat(user, "There's already something inside!") + return 1 + if (!is_type_in_list(O, blend_items) && !is_type_in_list(O, juice_items)) + to_chat(user, "You can't grind that!") + return ..() + + if(istype(O, /obj/item/stack/)) + var/obj/item/stack/N = new O.type(src, amount=1) + var/obj/item/stack/S = O + S.use(1) + crushable = N + to_chat(user, "You place \the [N] in \the [src].") + return 0 + else if(!user.drop_item(O, src)) + to_chat(user, "You can't let go of \the [O]!") + return + + crushable = O + to_chat(user, "You place \the [O] in \the [src].") + return 0 + +/obj/item/weapon/reagent_containers/glass/mortar/attack_hand(mob/user as mob) + add_fingerprint(user) + if(user.get_inactive_hand() != src) return ..() + if(crushable) + crushable.forceMove(user.loc) + user.put_in_active_hand(crushable) + crushable = null + return + +/obj/item/weapon/reagent_containers/glass/mortar/attack_self(mob/user as mob) + if(!crushable) + to_chat(user, "There is nothing to be crushed.") + return + if (reagents.total_volume >= volume) + to_chat(user, "There is no more space inside!") + return + if(is_type_in_list(crushable, juice_items)) + to_chat(user, "You smash the contents into juice!") + var/id = null + for(var/i in juice_items) + if(istype(crushable, i)) + id = juice_items[i] + if(!id) + return + var/obj/item/weapon/reagent_containers/food/snacks/grown/juiceable = crushable + if(juiceable.potency == -1) + juiceable.potency = 0 + reagents.add_reagent(id[1], min(round(5*sqrt(juiceable.potency)), volume - reagents.total_volume)) + else if(is_type_in_list(crushable, blend_items)) + to_chat(user, "You grind the contents into dust!") + var/id = null + var/space = volume - reagents.total_volume + for(var/i in blend_items) + if(istype(crushable, i)) + id = blend_items[i] + break + if(!id) + return + if(istype(crushable, /obj/item/weapon/reagent_containers/food/snacks)) //Most growable food + if(id[1] == "generic") + crushable.reagents.trans_to(src,crushable.reagents.total_volume) + else + reagents.add_reagent(id[1],min(id[2], space)) + else if(istype(crushable, /obj/item/stack/sheet) || istype(crushable, /obj/item/seeds) || /obj/item/device/flashlight/flare || /obj/item/stack/cable_coil || /obj/item/weapon/cell || /obj/item/clothing/head/butt) //Generic processes + reagents.add_reagent(id[1],min(id[2], space)) + else if(istype(crushable, /obj/item/weapon/grown)) //Nettle and death nettle + crushable.reagents.trans_to(src,crushable.reagents.total_volume) + else if(istype(crushable, /obj/item/weapon/rocksliver)) //Xenoarch + var/obj/item/weapon/rocksliver/R = crushable + reagents.add_reagent(id[1],min(id[2], space), R.geological_data) + else + to_chat(user, "An error was encountered. Report this message.") + return + else + to_chat(user, "You smash the contents into nothingness.") + qdel(crushable) + crushable = null + return + +/obj/item/weapon/reagent_containers/glass/mortar/examine(mob/user) + ..() + to_chat(user, "It has [crushable ? "an unground [crushable] inside." : "nothing to be crushed."]") diff --git a/code/modules/reagents/Chemistry-Readme.dm b/code/modules/reagents/Chemistry-Readme.dm index f6767faac98..7a039ab75a8 100644 --- a/code/modules/reagents/Chemistry-Readme.dm +++ b/code/modules/reagents/Chemistry-Readme.dm @@ -1,255 +1,255 @@ -/* -NOTE: IF YOU UPDATE THE REAGENT-SYSTEM, ALSO UPDATE THIS README. - -Structure: /////////////////// ////////////////////////// - // Mob or object // -------> // Reagents var (datum) // Is a reference to the datum that holds the reagents. - /////////////////// ////////////////////////// - | | - The object that holds everything. V - reagent_list var (list) A List of datums, each datum is a reagent. - - | | | - V V V - - reagents (datums) Reagents. I.e. Water , antitoxins or mercury. - - -Random important notes: - - An objects on_reagent_change will be called every time the objects reagents change. - Useful if you want to update the objects icon etc. - -About the Holder: - - The holder (reagents datum) is the datum that holds a list of all reagents - currently in the object.It also has all the procs needed to manipulate reagents - - remove_any(var/amount) - This proc removes reagents from the holder until the passed amount - is matched. It'll try to remove some of ALL reagents contained. - - trans_to(var/obj/target, var/amount) - This proc equally transfers the contents of the holder to another - objects holder. You need to pass it the object (not the holder) you want - to transfer to and the amount you want to transfer. Its return value is the - actual amount transfered (if one of the objects is full/empty) - - trans_id_to(var/obj/target, var/reagent, var/amount) - Same as above but only for a specific reagent in the reagent list. - If the specified amount is greater than what is available, it will use - the amount of the reagent that is available. If no reagent exists, returns null. - - metabolize(var/mob/M) - This proc is called by the mobs life proc. It simply calls on_mob_life for - all contained reagents. You shouldnt have to use this one directly. - - handle_reactions() - This proc check all recipes and, on a match, uses them. - It will also call the recipe's on_reaction proc (for explosions or w/e). - Currently, this proc is automatically called by trans_to. - - Modified from the original to preserve reagent data across reactions (originally for xenoarchaeology) - - isolate_reagent(var/reagent) - Pass it a reagent id and it will remove all reagents but that one. - It's that simple. - - del_reagent(var/reagent) - Completely remove the reagent with the matching id. - - reaction_fire(exposed_temp) - Simply calls the reaction_fire procs of all contained reagents. - - update_total() - This one simply updates the total volume of the holder. - (the volume of all reagents added together) - - clear_reagents() - This proc removes ALL reagents from the holder. - - reaction(var/atom/A, var/method=TOUCH, var/volume_modifier=0) - This proc calls the appropriate reaction procs of the reagents. - I.e. if A is an object, it will call the reagents reaction_obj - proc. The method var is used for reaction on mobs. It simply tells - us if the mob TOUCHed the reagent or if it INGESTed the reagent. - Since the volume can be checked in a reagents proc, you might want to - use the volume_modifier var to modifiy the passed value without actually - changing the volume of the reagents. - If you're not sure if you need to use this the answer is very most likely 'No'. - You'll want to use this proc whenever an atom first comes in - contact with the reagents of a holder. (in the 'splash' part of a beaker i.e.) - More on the reaction in the reagent part of this readme. - - add_reagent(var/reagent, var/amount, var/data) - Attempts to add X of the matching reagent to the holder. - You wont use this much. Mostly in new procs for pre-filled - objects. - - remove_reagent(var/reagent, var/amount) - The exact opposite of the add_reagent proc. - - Modified from original to return the reagent's data, in order to preserve reagent data across reactions (originally for xenoarchaeology) - - has_reagent(var/reagent, var/amount) - Returns 1 if the holder contains this reagent. - Or 0 if not. - If you pass it an amount it will additionally check - if the amount is matched. This is optional. - - get_reagent_amount(var/reagent) - Returns the amount of the matching reagent inside the - holder. Returns 0 if the reagent is missing. - - Important variables: - - total_volume - This variable contains the total volume of all reagents in this holder. - - reagent_list - This is a list of all contained reagents. More specifically, references - to the reagent datums. - - maximum_volume - This is the maximum volume of the holder. - - my_atom - This is the atom the holder is 'in'. Useful if you need to find the location. - (i.e. for explosions) - - -About Reagents: - - Reagents are all the things you can mix and fille in bottles etc. This can be anything from - rejuvs over water to ... iron. Each reagent also has a few procs - i'll explain those below. - - reaction_mob(var/mob/M, var/method=TOUCH, var/volume) - This is called by the holder's reation proc. - This version is only called when the reagent - reacts with a mob. The method var can be either - TOUCH or INGEST. You'll want to put stuff like - acid-facemelting in here. - - reaction_animal(var/mob/living/simple_animal/M, var/method=TOUCH, var/volume) - Same as above, but called when the reagent - reacts with a simple animal (because animals - are different enough from humans code-wise) - - reaction_obj(var/obj/O) - This is called by the holder's reation proc. - This version is called when the reagents reacts - with an object. You'll want to put stuff like - object melting in here ... or something. i dunno. - - reaction_turf(var/turf/T) - This is called by the holder's reation proc. - This version is called when the reagents reacts - with a turf. You'll want to put stuff like extra - slippery floors for lube or something in here. - - on_mob_life(var/mob/M) - This proc is called everytime the mobs life proc executes. - This is the place where you put damage for toxins , - drowsyness for sleep toxins etc etc. - You'll want to call the parents proc by using ..() . - If you dont, the chemical will stay in the mob forever - - unless you write your own piece of code to slowly remove it. - (Should be pretty easy, 1 line of code) - - Important variables: - - holder - This variable contains a reference to the holder the chemical is 'in' - - volume - This is the volume of the reagent. - - id - The id of the reagent - - name - The name of the reagent. - - data - This var can be used for whatever the fuck you want. I used it for the sleep - toxins to make them work slowly instead of instantly. You could also use this - for DNA in a blood reagent or ... well whatever you want. - - color - This is a hexadecimal color that represents the reagent outside of containers, - you define it as "#RRGGBB", or, red green blue. You can also define it using the - rgb() proc, which returns a hexadecimal value too. The color is black by default. - - A good website for color calculations: http://www.psyclops.com/tools/rgb/ - - - - -About Recipes: - - Recipes are simple datums that contain a list of required reagents and a result. - They also have a proc that is called when the recipe is matched. - - on_reaction(var/datum/reagents/holder, var/created_volume) - This proc is called when the recipe is matched. - You'll want to add explosions etc here. - To find the location you'll have to do something - like get_turf(holder.my_atom) - - name & id - Should be pretty obvious. - - result - This var contains the id of the resulting reagent. - - required_reagents - This is a list of ids of the required reagents. - Each id also needs an associated value that gives us the minimum required amount - of that reagent. The handle_reaction proc can detect mutiples of the same recipes - so for most cases you want to set the required amount to 1. - - required_catalysts (Added May 2011) - This is a list of the ids of the required catalysts. - Functionally similar to required_reagents, it is a list of reagents that are required - for the reaction. However, unlike required_reagents, catalysts are NOT consumed. - They mearly have to be present in the container. - - result_amount - This is the amount of the resulting reagent this recipe will produce. - I recommend you set this to the total volume of all required reagent. - - required_container - The container the recipe has to take place in in order to happen. Leave this blank/null - if you want the reaction to happen anywhere. - - required_other - Basically like a reagent's data variable. You can set extra requirements for a - reaction with this. - - -About the Tools: - - By default, all atom have a reagents var - but its empty. if you want to use an object for the chem. - system you'll need to add something like this in its new proc: - - to_chat(var/datum/reagents/R = new/datum/reagents(100), <<< create a new datum , 100 is the maximum_volume of the new holder datum.) - to_chat(reagents = R, <<< assign the new datum to the objects reagents var) - to_chat(R.my_atom = src, <<< set the holders my_atom to src so that we know where we are.) - - This can also be done by calling a convenience proc: - atom/proc/create_reagents(var/max_volume) - - - Other important stuff: - - amount_per_transfer_from_this var - This var is mostly used by beakers and bottles. - It simply tells us how much to transfer when - 'pouring' our reagents into something else. - - atom/proc/is_open_container() - Checks atom/var/flags & OPENCONTAINER. - If this returns 1 , you can use syringes, beakers etc - to manipulate the contents of this object. - If it's 0, you'll need to write your own custom reagent - transfer code since you will not be able to use the standard - tools to manipulate it. - +/* +NOTE: IF YOU UPDATE THE REAGENT-SYSTEM, ALSO UPDATE THIS README. + +Structure: /////////////////// ////////////////////////// + // Mob or object // -------> // Reagents var (datum) // Is a reference to the datum that holds the reagents. + /////////////////// ////////////////////////// + | | + The object that holds everything. V + reagent_list var (list) A List of datums, each datum is a reagent. + + | | | + V V V + + reagents (datums) Reagents. I.e. Water , antitoxins or mercury. + + +Random important notes: + + An objects on_reagent_change will be called every time the objects reagents change. + Useful if you want to update the objects icon etc. + +About the Holder: + + The holder (reagents datum) is the datum that holds a list of all reagents + currently in the object.It also has all the procs needed to manipulate reagents + + remove_any(var/amount) + This proc removes reagents from the holder until the passed amount + is matched. It'll try to remove some of ALL reagents contained. + + trans_to(var/obj/target, var/amount) + This proc equally transfers the contents of the holder to another + objects holder. You need to pass it the object (not the holder) you want + to transfer to and the amount you want to transfer. Its return value is the + actual amount transfered (if one of the objects is full/empty) + + trans_id_to(var/obj/target, var/reagent, var/amount) + Same as above but only for a specific reagent in the reagent list. + If the specified amount is greater than what is available, it will use + the amount of the reagent that is available. If no reagent exists, returns null. + + metabolize(var/mob/M) + This proc is called by the mobs life proc. It simply calls on_mob_life for + all contained reagents. You shouldnt have to use this one directly. + + handle_reactions() + This proc check all recipes and, on a match, uses them. + It will also call the recipe's on_reaction proc (for explosions or w/e). + Currently, this proc is automatically called by trans_to. + - Modified from the original to preserve reagent data across reactions (originally for xenoarchaeology) + + isolate_reagent(var/reagent) + Pass it a reagent id and it will remove all reagents but that one. + It's that simple. + + del_reagent(var/reagent) + Completely remove the reagent with the matching id. + + reaction_fire(exposed_temp) + Simply calls the reaction_fire procs of all contained reagents. + + update_total() + This one simply updates the total volume of the holder. + (the volume of all reagents added together) + + clear_reagents() + This proc removes ALL reagents from the holder. + + reaction(var/atom/A, var/method=TOUCH, var/volume_modifier=0) + This proc calls the appropriate reaction procs of the reagents. + I.e. if A is an object, it will call the reagents reaction_obj + proc. The method var is used for reaction on mobs. It simply tells + us if the mob TOUCHed the reagent or if it INGESTed the reagent. + Since the volume can be checked in a reagents proc, you might want to + use the volume_modifier var to modifiy the passed value without actually + changing the volume of the reagents. + If you're not sure if you need to use this the answer is very most likely 'No'. + You'll want to use this proc whenever an atom first comes in + contact with the reagents of a holder. (in the 'splash' part of a beaker i.e.) + More on the reaction in the reagent part of this readme. + + add_reagent(var/reagent, var/amount, var/data) + Attempts to add X of the matching reagent to the holder. + You wont use this much. Mostly in new procs for pre-filled + objects. + + remove_reagent(var/reagent, var/amount) + The exact opposite of the add_reagent proc. + - Modified from original to return the reagent's data, in order to preserve reagent data across reactions (originally for xenoarchaeology) + + has_reagent(var/reagent, var/amount) + Returns 1 if the holder contains this reagent. + Or 0 if not. + If you pass it an amount it will additionally check + if the amount is matched. This is optional. + + get_reagent_amount(var/reagent) + Returns the amount of the matching reagent inside the + holder. Returns 0 if the reagent is missing. + + Important variables: + + total_volume + This variable contains the total volume of all reagents in this holder. + + reagent_list + This is a list of all contained reagents. More specifically, references + to the reagent datums. + + maximum_volume + This is the maximum volume of the holder. + + my_atom + This is the atom the holder is 'in'. Useful if you need to find the location. + (i.e. for explosions) + + +About Reagents: + + Reagents are all the things you can mix and fille in bottles etc. This can be anything from + rejuvs over water to ... iron. Each reagent also has a few procs - i'll explain those below. + + reaction_mob(var/mob/M, var/method=TOUCH, var/volume) + This is called by the holder's reation proc. + This version is only called when the reagent + reacts with a mob. The method var can be either + TOUCH or INGEST. You'll want to put stuff like + acid-facemelting in here. + + reaction_animal(var/mob/living/simple_animal/M, var/method=TOUCH, var/volume) + Same as above, but called when the reagent + reacts with a simple animal (because animals + are different enough from humans code-wise) + + reaction_obj(var/obj/O) + This is called by the holder's reation proc. + This version is called when the reagents reacts + with an object. You'll want to put stuff like + object melting in here ... or something. i dunno. + + reaction_turf(var/turf/T) + This is called by the holder's reation proc. + This version is called when the reagents reacts + with a turf. You'll want to put stuff like extra + slippery floors for lube or something in here. + + on_mob_life(var/mob/M) + This proc is called everytime the mobs life proc executes. + This is the place where you put damage for toxins , + drowsyness for sleep toxins etc etc. + You'll want to call the parents proc by using ..() . + If you dont, the chemical will stay in the mob forever - + unless you write your own piece of code to slowly remove it. + (Should be pretty easy, 1 line of code) + + Important variables: + + holder + This variable contains a reference to the holder the chemical is 'in' + + volume + This is the volume of the reagent. + + id + The id of the reagent + + name + The name of the reagent. + + data + This var can be used for whatever the fuck you want. I used it for the sleep + toxins to make them work slowly instead of instantly. You could also use this + for DNA in a blood reagent or ... well whatever you want. + + color + This is a hexadecimal color that represents the reagent outside of containers, + you define it as "#RRGGBB", or, red green blue. You can also define it using the + rgb() proc, which returns a hexadecimal value too. The color is black by default. + + A good website for color calculations: http://www.psyclops.com/tools/rgb/ + + + + +About Recipes: + + Recipes are simple datums that contain a list of required reagents and a result. + They also have a proc that is called when the recipe is matched. + + on_reaction(var/datum/reagents/holder, var/created_volume) + This proc is called when the recipe is matched. + You'll want to add explosions etc here. + To find the location you'll have to do something + like get_turf(holder.my_atom) + + name & id + Should be pretty obvious. + + result + This var contains the id of the resulting reagent. + + required_reagents + This is a list of ids of the required reagents. + Each id also needs an associated value that gives us the minimum required amount + of that reagent. The handle_reaction proc can detect mutiples of the same recipes + so for most cases you want to set the required amount to 1. + + required_catalysts (Added May 2011) + This is a list of the ids of the required catalysts. + Functionally similar to required_reagents, it is a list of reagents that are required + for the reaction. However, unlike required_reagents, catalysts are NOT consumed. + They mearly have to be present in the container. + + result_amount + This is the amount of the resulting reagent this recipe will produce. + I recommend you set this to the total volume of all required reagent. + + required_container + The container the recipe has to take place in in order to happen. Leave this blank/null + if you want the reaction to happen anywhere. + + required_other + Basically like a reagent's data variable. You can set extra requirements for a + reaction with this. + + +About the Tools: + + By default, all atom have a reagents var - but its empty. if you want to use an object for the chem. + system you'll need to add something like this in its new proc: + + to_chat(var/datum/reagents/R = new/datum/reagents(100), <<< create a new datum , 100 is the maximum_volume of the new holder datum.) + to_chat(reagents = R, <<< assign the new datum to the objects reagents var) + to_chat(R.my_atom = src, <<< set the holders my_atom to src so that we know where we are.) + + This can also be done by calling a convenience proc: + atom/proc/create_reagents(var/max_volume) + + + Other important stuff: + + amount_per_transfer_from_this var + This var is mostly used by beakers and bottles. + It simply tells us how much to transfer when + 'pouring' our reagents into something else. + + atom/proc/is_open_container() + Checks atom/var/flags & OPENCONTAINER. + If this returns 1 , you can use syringes, beakers etc + to manipulate the contents of this object. + If it's 0, you'll need to write your own custom reagent + transfer code since you will not be able to use the standard + tools to manipulate it. + */ \ No newline at end of file diff --git a/code/modules/reagents/grenade_launcher.dm b/code/modules/reagents/grenade_launcher.dm index 83092fd51c0..9c0fd45d03d 100644 --- a/code/modules/reagents/grenade_launcher.dm +++ b/code/modules/reagents/grenade_launcher.dm @@ -1,67 +1,67 @@ - - -/obj/item/weapon/gun/grenadelauncher - name = "grenade launcher" - icon = 'icons/obj/gun.dmi' - icon_state = "riotgun" - item_state = "riotgun" - w_class = 4.0 - throw_speed = 2 - throw_range = 10 - force = 5.0 - var/list/grenades = new/list() - var/max_grenades = 3 - starting_materials = list(MAT_IRON = 2000) - w_type = RECYK_METAL - -/obj/item/weapon/gun/grenadelauncher/examine(mob/user) - ..() - if(!(grenades.len)) - to_chat(user, "It is empty.") - return - to_chat(user, "It has [grenades.len] / [max_grenades] grenades loaded.") - for(var/obj/item/weapon/grenade/G in grenades) - to_chat(user, "\icon [G] [G.name]") - -/obj/item/weapon/gun/grenadelauncher/attackby(obj/item/I as obj, mob/user as mob) - - if((istype(I, /obj/item/weapon/grenade))) - if(grenades.len < max_grenades) - if(user.drop_item(I, src)) - grenades += I - to_chat(user, "You load the [I.name] into the [src.name].") - to_chat(user, "[grenades.len] / [max_grenades] grenades loaded.") - else - to_chat(user, "The [src.name] cannot hold more grenades.") - -/obj/item/weapon/gun/grenadelauncher/afterattack(obj/target, mob/user , flag) - - if (istype(target, /obj/item/weapon/storage/backpack )) - return - - else if (locate (/obj/structure/table, src.loc)) - return - - else if(target == user) - return - - if(grenades.len) - spawn(0) fire_grenade(target,user) - else - to_chat(usr, "The [src.name] is empty.") - -/obj/item/weapon/gun/grenadelauncher/proc/fire_grenade(atom/target, mob/user) - for(var/mob/O in viewers(world.view, user)) - O.show_message(text("[] fired a grenade!", user), 1) - to_chat(user, "You fire the grenade launcher!") - var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta! - grenades -= F - F.loc = user.loc - F.throw_at(target, 30, 2) - message_admins("[key_name_admin(user)] fired [F.name] from [src.name].") - log_game("[key_name_admin(user)] launched [F.name] from [src.name].") - F.active = 1 - F.icon_state = initial(icon_state) + "_active" - playsound(user.loc, 'sound/weapons/grenadelauncher.ogg', 50, 1, -3) - spawn(15) + + +/obj/item/weapon/gun/grenadelauncher + name = "grenade launcher" + icon = 'icons/obj/gun.dmi' + icon_state = "riotgun" + item_state = "riotgun" + w_class = 4.0 + throw_speed = 2 + throw_range = 10 + force = 5.0 + var/list/grenades = new/list() + var/max_grenades = 3 + starting_materials = list(MAT_IRON = 2000) + w_type = RECYK_METAL + +/obj/item/weapon/gun/grenadelauncher/examine(mob/user) + ..() + if(!(grenades.len)) + to_chat(user, "It is empty.") + return + to_chat(user, "It has [grenades.len] / [max_grenades] grenades loaded.") + for(var/obj/item/weapon/grenade/G in grenades) + to_chat(user, "\icon [G] [G.name]") + +/obj/item/weapon/gun/grenadelauncher/attackby(obj/item/I as obj, mob/user as mob) + + if((istype(I, /obj/item/weapon/grenade))) + if(grenades.len < max_grenades) + if(user.drop_item(I, src)) + grenades += I + to_chat(user, "You load the [I.name] into the [src.name].") + to_chat(user, "[grenades.len] / [max_grenades] grenades loaded.") + else + to_chat(user, "The [src.name] cannot hold more grenades.") + +/obj/item/weapon/gun/grenadelauncher/afterattack(obj/target, mob/user , flag) + + if (istype(target, /obj/item/weapon/storage/backpack )) + return + + else if (locate (/obj/structure/table, src.loc)) + return + + else if(target == user) + return + + if(grenades.len) + spawn(0) fire_grenade(target,user) + else + to_chat(usr, "The [src.name] is empty.") + +/obj/item/weapon/gun/grenadelauncher/proc/fire_grenade(atom/target, mob/user) + for(var/mob/O in viewers(world.view, user)) + O.show_message(text("[] fired a grenade!", user), 1) + to_chat(user, "You fire the grenade launcher!") + var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta! + grenades -= F + F.loc = user.loc + F.throw_at(target, 30, 2) + message_admins("[key_name_admin(user)] fired [F.name] from [src.name].") + log_game("[key_name_admin(user)] launched [F.name] from [src.name].") + F.active = 1 + F.icon_state = initial(icon_state) + "_active" + playsound(user.loc, 'sound/weapons/grenadelauncher.ogg', 50, 1, -3) + spawn(15) F.prime() \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 3eabd52b874..6a9ec3bf900 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -1,232 +1,232 @@ -// Reagents to log when splashing non-mobs (all mob splashes are logged automatically) -var/list/LOGGED_SPLASH_REAGENTS = list("fuel", "thermite") - -/obj/item/weapon/reagent_containers - name = "Container" - desc = "..." - icon = 'icons/obj/chemical.dmi' - icon_state = null - w_class = 1 - var/amount_per_transfer_from_this = 5 - var/possible_transfer_amounts = list(5,10,15,25,30) - var/volume = 30 - -/obj/item/weapon/reagent_containers/verb/set_APTFT() //set amount_per_transfer_from_this - set name = "Set transfer amount" - set category = "Object" - set src in range(0) - var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts - if (N) - amount_per_transfer_from_this = N - -/obj/item/weapon/reagent_containers/AltClick() - if(loc == usr && possible_transfer_amounts) - set_APTFT() - return - return ..() - -/obj/item/weapon/reagent_containers/New() - ..() - create_reagents(volume) - - if (!possible_transfer_amounts) - src.verbs -= /obj/item/weapon/reagent_containers/verb/set_APTFT - -/obj/item/weapon/reagent_containers/attack_self(mob/user as mob) - return - -/obj/item/weapon/reagent_containers/attack(mob/M as mob, mob/user as mob, def_zone) - return - -// this prevented pills, food, and other things from being picked up by bags. -// possibly intentional, but removing it allows us to not duplicate functionality. -// -Sayu (storage consolidation) -/* -/obj/item/weapon/reagent_containers/attackby(obj/item/I as obj, mob/user as mob) - return -*/ - -/** - * This usually handles reagent transfer between containers and splashing the contents. - * Please see `transfer()` for a general reusable proc for that. - * - * If you're wondering why you're splashing machinery that accepts beakers when - * inserting them, it's because the machine is returning `FALSE` on `attackby()`, - * which causes `afterattack()` to be called. Return 1 instead on those cases. - * - * If your container is splashing/transferring things at a distance, your `afterattack()` - * isn't checking for adjacency. For that, check that `adjacency_flag` is `TRUE`. - */ -/obj/item/weapon/reagent_containers/afterattack(var/obj/target, var/mob/user, var/adjacency_flag, var/click_params) - return - -/** - * Transfer reagents between reagent_containers/reagent_dispensers. - */ -/proc/transfer_sub(var/atom/source, var/atom/target, var/amount, var/mob/user) - // Typecheck shenanigans - var/source_empty - var/target_full - - if (istype(source, /obj/item/weapon/reagent_containers)) - var/obj/item/weapon/reagent_containers/S = source - source_empty = S.is_empty() - else if (istype(source, /obj/structure/reagent_dispensers)) - var/obj/structure/reagent_dispensers/S = source - source_empty = S.is_empty() - else - //ASSERT(istype(source.reagents)) - source_empty = source.reagents.is_empty() - //warning("Called transfer_sub() with a non-compatible source type ([source.type], [source], \ref[source])") - //return - - - if (istype(target, /obj/item/weapon/reagent_containers)) - var/obj/item/weapon/reagent_containers/T = target - target_full = T.is_full() - // Reagent dispensers can't be refilled (yet) through normal means (TODO?) - /*else if (istype(target, /obj/structure/reagent_dispensers)) - var/obj/structure/reagent_dispensers/T = target - target_full = T.is_full()*/ - else - if(ismob(target)) return null - //ASSERT(istype(target.reagents)) - if(!istype(target.reagents)) return - target_full = target.reagents.is_full() - //warning("Called transfer_sub() with a non-compatible target type ([target.type], [target], \ref[target])") - //return - - // Actual transfer checks - if (source_empty) +// Reagents to log when splashing non-mobs (all mob splashes are logged automatically) +var/list/LOGGED_SPLASH_REAGENTS = list("fuel", "thermite") + +/obj/item/weapon/reagent_containers + name = "Container" + desc = "..." + icon = 'icons/obj/chemical.dmi' + icon_state = null + w_class = 1 + var/amount_per_transfer_from_this = 5 + var/possible_transfer_amounts = list(5,10,15,25,30) + var/volume = 30 + +/obj/item/weapon/reagent_containers/verb/set_APTFT() //set amount_per_transfer_from_this + set name = "Set transfer amount" + set category = "Object" + set src in range(0) + var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts + if (N) + amount_per_transfer_from_this = N + +/obj/item/weapon/reagent_containers/AltClick() + if(loc == usr && possible_transfer_amounts) + set_APTFT() + return + return ..() + +/obj/item/weapon/reagent_containers/New() + ..() + create_reagents(volume) + + if (!possible_transfer_amounts) + src.verbs -= /obj/item/weapon/reagent_containers/verb/set_APTFT + +/obj/item/weapon/reagent_containers/attack_self(mob/user as mob) + return + +/obj/item/weapon/reagent_containers/attack(mob/M as mob, mob/user as mob, def_zone) + return + +// this prevented pills, food, and other things from being picked up by bags. +// possibly intentional, but removing it allows us to not duplicate functionality. +// -Sayu (storage consolidation) +/* +/obj/item/weapon/reagent_containers/attackby(obj/item/I as obj, mob/user as mob) + return +*/ + +/** + * This usually handles reagent transfer between containers and splashing the contents. + * Please see `transfer()` for a general reusable proc for that. + * + * If you're wondering why you're splashing machinery that accepts beakers when + * inserting them, it's because the machine is returning `FALSE` on `attackby()`, + * which causes `afterattack()` to be called. Return 1 instead on those cases. + * + * If your container is splashing/transferring things at a distance, your `afterattack()` + * isn't checking for adjacency. For that, check that `adjacency_flag` is `TRUE`. + */ +/obj/item/weapon/reagent_containers/afterattack(var/obj/target, var/mob/user, var/adjacency_flag, var/click_params) + return + +/** + * Transfer reagents between reagent_containers/reagent_dispensers. + */ +/proc/transfer_sub(var/atom/source, var/atom/target, var/amount, var/mob/user) + // Typecheck shenanigans + var/source_empty + var/target_full + + if (istype(source, /obj/item/weapon/reagent_containers)) + var/obj/item/weapon/reagent_containers/S = source + source_empty = S.is_empty() + else if (istype(source, /obj/structure/reagent_dispensers)) + var/obj/structure/reagent_dispensers/S = source + source_empty = S.is_empty() + else + //ASSERT(istype(source.reagents)) + source_empty = source.reagents.is_empty() + //warning("Called transfer_sub() with a non-compatible source type ([source.type], [source], \ref[source])") + //return + + + if (istype(target, /obj/item/weapon/reagent_containers)) + var/obj/item/weapon/reagent_containers/T = target + target_full = T.is_full() + // Reagent dispensers can't be refilled (yet) through normal means (TODO?) + /*else if (istype(target, /obj/structure/reagent_dispensers)) + var/obj/structure/reagent_dispensers/T = target + target_full = T.is_full()*/ + else + if(ismob(target)) return null + //ASSERT(istype(target.reagents)) + if(!istype(target.reagents)) return + target_full = target.reagents.is_full() + //warning("Called transfer_sub() with a non-compatible target type ([target.type], [target], \ref[target])") + //return + + // Actual transfer checks + if (source_empty) to_chat(user, "\The [source] is empty.") - return -1 - - if (target_full) + return -1 + + if (target_full) to_chat(user, "\The [target] is full.") - return -1 - - return source.reagents.trans_to(target, amount) - -/** - * Helper proc to handle reagent splashes. A negative `amount` will splash all the reagents. - */ -/proc/splash_sub(var/datum/reagents/reagents, var/atom/target, var/amount, var/mob/user) - if (amount == 0 || reagents.is_empty()) + return -1 + + return source.reagents.trans_to(target, amount) + +/** + * Helper proc to handle reagent splashes. A negative `amount` will splash all the reagents. + */ +/proc/splash_sub(var/datum/reagents/reagents, var/atom/target, var/amount, var/mob/user) + if (amount == 0 || reagents.is_empty()) to_chat(user, "There's nothing to splash with!") - return -1 - - reagents.reaction(target, TOUCH) - - if (amount > 0) - reagents.remove_any(amount) - user.visible_message("\The [target] has been splashed with something by [user]!", - "You splash some of the solution onto \the [target].") - else - reagents.clear_reagents() - user.visible_message("\The [target] has been splashed with something by [user]!", - "You splash the solution onto \the [target].") - -/** - * Transfers reagents to other containers/from dispensers. Handles splashing as well. - * - * Use this to avoid having duplicate code on every container. Note that this procedure doesn't check for - * adjacency between the source and the target. - * - * @param target What to check for transferring/splashing. - * @param user The mob performing the transfer. - * @param can_send Whether we are allowed to transfer our reagents to the target. - * @param can_receive Whether we are allowed to transfer from `reagent_dispensers` - * @param splashable_units How many units of reagents should be splashed. -1 for all of them, 0 to disable splashing. - * - * @return If we have transferred reagents, the amount transferred; otherwise, -1 if the transfer has failed, 0 if was a splash. - */ -/obj/item/weapon/reagent_containers/proc/transfer(var/atom/target, var/mob/user, var/can_send = TRUE, var/can_receive = TRUE, var/splashable_units = 0) - if (!istype(target) || !is_open_container()) - return -1 - - var/success - // Transfer from dispenser - if (can_receive && istype(target, /obj/structure/reagent_dispensers)) - var/tx_amount = transfer_sub(target, src, target:amount_per_transfer_from_this, user) - if (tx_amount > 0) + return -1 + + reagents.reaction(target, TOUCH) + + if (amount > 0) + reagents.remove_any(amount) + user.visible_message("\The [target] has been splashed with something by [user]!", + "You splash some of the solution onto \the [target].") + else + reagents.clear_reagents() + user.visible_message("\The [target] has been splashed with something by [user]!", + "You splash the solution onto \the [target].") + +/** + * Transfers reagents to other containers/from dispensers. Handles splashing as well. + * + * Use this to avoid having duplicate code on every container. Note that this procedure doesn't check for + * adjacency between the source and the target. + * + * @param target What to check for transferring/splashing. + * @param user The mob performing the transfer. + * @param can_send Whether we are allowed to transfer our reagents to the target. + * @param can_receive Whether we are allowed to transfer from `reagent_dispensers` + * @param splashable_units How many units of reagents should be splashed. -1 for all of them, 0 to disable splashing. + * + * @return If we have transferred reagents, the amount transferred; otherwise, -1 if the transfer has failed, 0 if was a splash. + */ +/obj/item/weapon/reagent_containers/proc/transfer(var/atom/target, var/mob/user, var/can_send = TRUE, var/can_receive = TRUE, var/splashable_units = 0) + if (!istype(target) || !is_open_container()) + return -1 + + var/success + // Transfer from dispenser + if (can_receive && istype(target, /obj/structure/reagent_dispensers)) + var/tx_amount = transfer_sub(target, src, target:amount_per_transfer_from_this, user) + if (tx_amount > 0) to_chat(user, "You fill \the [src][src.is_full() ? " to the brim" : ""] with [tx_amount] units of the contents of \the [target].") - - return tx_amount - // Transfer to container - else if (can_send /*&& target.reagents**/) - var/obj/container = target - if (!container.is_open_container() && istype(container,/obj/item/weapon/reagent_containers)) - return -1 - - var/list/bad_reagents = reagents.get_bad_reagent_names() // Used for logging - var/tx_amount = transfer_sub(src, target, amount_per_transfer_from_this, user) - success = tx_amount - if(success) - if (tx_amount > 0) + + return tx_amount + // Transfer to container + else if (can_send /*&& target.reagents**/) + var/obj/container = target + if (!container.is_open_container() && istype(container,/obj/item/weapon/reagent_containers)) + return -1 + + var/list/bad_reagents = reagents.get_bad_reagent_names() // Used for logging + var/tx_amount = transfer_sub(src, target, amount_per_transfer_from_this, user) + success = tx_amount + if(success) + if (tx_amount > 0) to_chat(user, "You transfer [tx_amount] units of the solution to \the [target].") - - // Log transfers of 'bad things' (/vg/) - if (tx_amount > 0 && container.log_reagents && bad_reagents && bad_reagents.len > 0) - log_reagents(user, src, target, tx_amount, bad_reagents) - - return (tx_amount) - - if(!success) - // Mob splashing - if(splashable_units != 0) - var/to_splash = reagents.total_volume - if(ismob(target)) - if (src.is_empty() || !target.reagents) - return -1 - - var/mob/living/M = target - - // Log the 'attack' - var/list/splashed_reagents = english_list(get_reagent_names()) - add_logs(user, M, "splashed", admin = TRUE, object = src, addition = "Reagents: [splashed_reagents]") - - // Splash the target - splash_sub(reagents, M, splashable_units, user) - return (to_splash) - // Non-mob splashing - else - if(!src.is_empty()) - for (var/reagent_id in LOGGED_SPLASH_REAGENTS) - if (reagents.has_reagent(reagent_id)) - add_gamelogs(user, "poured '[reagent_id]' onto \the [target]", admin = TRUE, tp_link = TRUE, span_class = "danger") - - // Splash the thing - splash_sub(reagents, target, splashable_units, user) - return (to_splash) - return 0 - -/obj/item/weapon/reagent_containers/proc/is_empty() - return reagents.total_volume <= 0 - -/obj/item/weapon/reagent_containers/proc/is_full() - return reagents.total_volume >= reagents.maximum_volume - -/obj/item/weapon/reagent_containers/proc/can_transfer_an_APTFT() - return reagents.total_volume >= amount_per_transfer_from_this - -/obj/item/weapon/reagent_containers/proc/get_reagent_names() - var/list/reagent_names = list() - for (var/datum/reagent/R in reagents.reagent_list) - reagent_names += R.name - - return reagent_names - -/obj/item/weapon/reagent_containers/proc/get_reagent_ids() - var/list/reagent_ids = list() - for (var/datum/reagent/R in reagents.reagent_list) - reagent_ids += R.id - - return reagent_ids - -/obj/item/weapon/reagent_containers/proc/reagentlist(var/obj/item/weapon/reagent_containers/snack) //Attack logs for regents in pills - var/data - if(snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries - for (var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind - data += "[R.id]([R.volume] unit\s); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. - return data - else return "No reagents" + + // Log transfers of 'bad things' (/vg/) + if (tx_amount > 0 && container.log_reagents && bad_reagents && bad_reagents.len > 0) + log_reagents(user, src, target, tx_amount, bad_reagents) + + return (tx_amount) + + if(!success) + // Mob splashing + if(splashable_units != 0) + var/to_splash = reagents.total_volume + if(ismob(target)) + if (src.is_empty() || !target.reagents) + return -1 + + var/mob/living/M = target + + // Log the 'attack' + var/list/splashed_reagents = english_list(get_reagent_names()) + add_logs(user, M, "splashed", admin = TRUE, object = src, addition = "Reagents: [splashed_reagents]") + + // Splash the target + splash_sub(reagents, M, splashable_units, user) + return (to_splash) + // Non-mob splashing + else + if(!src.is_empty()) + for (var/reagent_id in LOGGED_SPLASH_REAGENTS) + if (reagents.has_reagent(reagent_id)) + add_gamelogs(user, "poured '[reagent_id]' onto \the [target]", admin = TRUE, tp_link = TRUE, span_class = "danger") + + // Splash the thing + splash_sub(reagents, target, splashable_units, user) + return (to_splash) + return 0 + +/obj/item/weapon/reagent_containers/proc/is_empty() + return reagents.total_volume <= 0 + +/obj/item/weapon/reagent_containers/proc/is_full() + return reagents.total_volume >= reagents.maximum_volume + +/obj/item/weapon/reagent_containers/proc/can_transfer_an_APTFT() + return reagents.total_volume >= amount_per_transfer_from_this + +/obj/item/weapon/reagent_containers/proc/get_reagent_names() + var/list/reagent_names = list() + for (var/datum/reagent/R in reagents.reagent_list) + reagent_names += R.name + + return reagent_names + +/obj/item/weapon/reagent_containers/proc/get_reagent_ids() + var/list/reagent_ids = list() + for (var/datum/reagent/R in reagents.reagent_list) + reagent_ids += R.id + + return reagent_ids + +/obj/item/weapon/reagent_containers/proc/reagentlist(var/obj/item/weapon/reagent_containers/snack) //Attack logs for regents in pills + var/data + if(snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries + for (var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind + data += "[R.id]([R.volume] unit\s); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. + return data + else return "No reagents" diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 0cb829d218b..928ce511c2d 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -1,99 +1,99 @@ -/obj/item/weapon/reagent_containers/blood - name = "Bloodpack" - desc = "Contains blood used for transfusion." - icon = 'icons/obj/bloodpack.dmi' - icon_state = "empty" - volume = 200 - - var/blood_type = null - -/obj/item/weapon/reagent_containers/blood/New() - ..() - if(blood_type != null) - name = "[blood_type] Bloodpack" - reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) - update_icon() - -/obj/item/weapon/reagent_containers/blood/on_reagent_change() - update_icon() - if(reagents.total_volume == 0 && name != "Empty Bloodback") - name = "Empty Bloodpack" - desc = "Empty bloodpacks are good in vampire movies, but bad in hospitals." - else if (reagents.reagent_list.len > 0) - var/target_type = null - var/the_volume = 0 - for(var/datum/reagent/A in reagents.reagent_list) - if(A.volume > the_volume && ("blood_type" in A.data)) - the_volume = A.volume - target_type = A.data["blood_type"] - if (target_type) - name = "[target_type] Bloodpack" - desc = "A bloodpack filled with [target_type] blood." - blood_type = target_type - else - name = "Murky Bloodpack" - desc = "A bloodpack that's clearly not filled with blood." - -/obj/item/weapon/reagent_containers/blood/update_icon() - var/percent = round((reagents.total_volume / volume) * 100) - switch(percent) - if(0 to 9) icon_state = "empty" - if(10 to 50) icon_state = "half" - if(51 to INFINITY) icon_state = "full" - -/obj/item/weapon/reagent_containers/blood/examine(mob/user) - //I don't want this to be an open container. - ..() - if(get_dist(user,src) > 3) +/obj/item/weapon/reagent_containers/blood + name = "Bloodpack" + desc = "Contains blood used for transfusion." + icon = 'icons/obj/bloodpack.dmi' + icon_state = "empty" + volume = 200 + + var/blood_type = null + +/obj/item/weapon/reagent_containers/blood/New() + ..() + if(blood_type != null) + name = "[blood_type] Bloodpack" + reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) + update_icon() + +/obj/item/weapon/reagent_containers/blood/on_reagent_change() + update_icon() + if(reagents.total_volume == 0 && name != "Empty Bloodback") + name = "Empty Bloodpack" + desc = "Empty bloodpacks are good in vampire movies, but bad in hospitals." + else if (reagents.reagent_list.len > 0) + var/target_type = null + var/the_volume = 0 + for(var/datum/reagent/A in reagents.reagent_list) + if(A.volume > the_volume && ("blood_type" in A.data)) + the_volume = A.volume + target_type = A.data["blood_type"] + if (target_type) + name = "[target_type] Bloodpack" + desc = "A bloodpack filled with [target_type] blood." + blood_type = target_type + else + name = "Murky Bloodpack" + desc = "A bloodpack that's clearly not filled with blood." + +/obj/item/weapon/reagent_containers/blood/update_icon() + var/percent = round((reagents.total_volume / volume) * 100) + switch(percent) + if(0 to 9) icon_state = "empty" + if(10 to 50) icon_state = "half" + if(51 to INFINITY) icon_state = "full" + +/obj/item/weapon/reagent_containers/blood/examine(mob/user) + //I don't want this to be an open container. + ..() + if(get_dist(user,src) > 3) to_chat(user, "You can't make out the contents.") - return - if(reagents) + return + if(reagents) to_chat(user, "It contains:") - if(reagents.reagent_list.len) - for(var/datum/reagent/R in reagents.reagent_list) - if (R.id == "blood") - var/type = R.data["blood_type"] + if(reagents.reagent_list.len) + for(var/datum/reagent/R in reagents.reagent_list) + if (R.id == "blood") + var/type = R.data["blood_type"] to_chat(user, "[R.volume] units of [R.name], of type [type]") - else + else to_chat(user, "[R.volume] units of [R.name]") - else + else to_chat(user, "Nothing.") - -//These should be kept for legacy purposes, probably. At least until they disappear from maps. -/obj/item/weapon/reagent_containers/blood/APlus - blood_type = "A+" - -/obj/item/weapon/reagent_containers/blood/AMinus - blood_type = "A-" - -/obj/item/weapon/reagent_containers/blood/BPlus - blood_type = "B+" - -/obj/item/weapon/reagent_containers/blood/BMinus - blood_type = "B-" - -/obj/item/weapon/reagent_containers/blood/OPlus - blood_type = "O+" - -/obj/item/weapon/reagent_containers/blood/OMinus - blood_type = "O-" - -/obj/item/weapon/reagent_containers/blood/empty - name = "Empty BloodPack" - desc = "Seems pretty useless... Maybe if there were a way to fill it?" - icon_state = "empty" - New() - ..() - blood_type = null - reagents.clear_reagents() - update_icon() - -/obj/item/weapon/reagent_containers/blood/chemo - name = "Phalanximine IV kit" - desc = "IV kit for chemotherapy." - icon = 'icons/obj/chemopack.dmi' - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("phalanximine", 200) - update_icon() + +//These should be kept for legacy purposes, probably. At least until they disappear from maps. +/obj/item/weapon/reagent_containers/blood/APlus + blood_type = "A+" + +/obj/item/weapon/reagent_containers/blood/AMinus + blood_type = "A-" + +/obj/item/weapon/reagent_containers/blood/BPlus + blood_type = "B+" + +/obj/item/weapon/reagent_containers/blood/BMinus + blood_type = "B-" + +/obj/item/weapon/reagent_containers/blood/OPlus + blood_type = "O+" + +/obj/item/weapon/reagent_containers/blood/OMinus + blood_type = "O-" + +/obj/item/weapon/reagent_containers/blood/empty + name = "Empty BloodPack" + desc = "Seems pretty useless... Maybe if there were a way to fill it?" + icon_state = "empty" + New() + ..() + blood_type = null + reagents.clear_reagents() + update_icon() + +/obj/item/weapon/reagent_containers/blood/chemo + name = "Phalanximine IV kit" + desc = "IV kit for chemotherapy." + icon = 'icons/obj/chemopack.dmi' + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("phalanximine", 200) + update_icon() diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index e5436bbff67..002089c91c2 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -1,107 +1,107 @@ -/obj/item/weapon/reagent_containers/borghypo - name = "Cyborg Hypospray" - desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment." - icon = 'icons/obj/syringe.dmi' - item_state = "hypo" - icon_state = "borghypo" - amount_per_transfer_from_this = 5 - possible_transfer_amounts = null - flags = FPRINT - var/mode = 1 - var/charge_cost = 50 - var/charge_tick = 0 - var/recharge_time = 5 // time it takes for shots to recharge (in seconds) - - var/list/datum/reagents/reagent_list = list() - var/list/reagent_ids = list("tricordrazine", "inaprovaline", "spaceacillin") - //var/list/reagent_ids = list("dexalin", "kelotane", "bicaridine", "anti_toxin", "inaprovaline", "spaceacillin") - -/obj/item/weapon/reagent_containers/borghypo/New(loc) - ..(loc) - qdel(reagents) - reagents = null - - for(var/reagent in reagent_ids) - var/datum/reagents/reagents = new(volume) - reagents.my_atom = src - reagents.add_reagent(reagent, volume) - reagent_list += reagents - - processing_objects += src - -/obj/item/weapon/reagent_containers/borghypo/Destroy() - for(var/datum/reagents/reagents in reagent_list) - qdel(reagents) - - reagent_list = null - - processing_objects -= src - ..() - -/obj/item/weapon/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg - if(++charge_tick < recharge_time) - return 0 - - charge_tick = 0 - - if(isrobot(loc)) - var/mob/living/silicon/robot/robot = loc - - if(robot && robot.cell) - var/datum/reagents/reagents = reagent_list[mode] - - if(reagents.total_volume < reagents.maximum_volume) // don't recharge reagents and drain power if the storage is full - robot.cell.use(charge_cost) // take power from borg - reagents.add_reagent(reagent_ids[mode], 5) // and fill hypo with reagent. - - //update_icon() - return 1 - -// Purely for testing purposes I swear~ -/* -/obj/item/weapon/reagent_containers/borghypo/verb/add_cyanide() - set src in world - add_reagent("cyanide") -*/ - -/obj/item/weapon/reagent_containers/borghypo/attack(mob/M as mob, mob/user as mob) - var/datum/reagents/reagents = reagent_list[mode] - - if(!reagents.total_volume) +/obj/item/weapon/reagent_containers/borghypo + name = "Cyborg Hypospray" + desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment." + icon = 'icons/obj/syringe.dmi' + item_state = "hypo" + icon_state = "borghypo" + amount_per_transfer_from_this = 5 + possible_transfer_amounts = null + flags = FPRINT + var/mode = 1 + var/charge_cost = 50 + var/charge_tick = 0 + var/recharge_time = 5 // time it takes for shots to recharge (in seconds) + + var/list/datum/reagents/reagent_list = list() + var/list/reagent_ids = list("tricordrazine", "inaprovaline", "spaceacillin") + //var/list/reagent_ids = list("dexalin", "kelotane", "bicaridine", "anti_toxin", "inaprovaline", "spaceacillin") + +/obj/item/weapon/reagent_containers/borghypo/New(loc) + ..(loc) + qdel(reagents) + reagents = null + + for(var/reagent in reagent_ids) + var/datum/reagents/reagents = new(volume) + reagents.my_atom = src + reagents.add_reagent(reagent, volume) + reagent_list += reagents + + processing_objects += src + +/obj/item/weapon/reagent_containers/borghypo/Destroy() + for(var/datum/reagents/reagents in reagent_list) + qdel(reagents) + + reagent_list = null + + processing_objects -= src + ..() + +/obj/item/weapon/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg + if(++charge_tick < recharge_time) + return 0 + + charge_tick = 0 + + if(isrobot(loc)) + var/mob/living/silicon/robot/robot = loc + + if(robot && robot.cell) + var/datum/reagents/reagents = reagent_list[mode] + + if(reagents.total_volume < reagents.maximum_volume) // don't recharge reagents and drain power if the storage is full + robot.cell.use(charge_cost) // take power from borg + reagents.add_reagent(reagent_ids[mode], 5) // and fill hypo with reagent. + + //update_icon() + return 1 + +// Purely for testing purposes I swear~ +/* +/obj/item/weapon/reagent_containers/borghypo/verb/add_cyanide() + set src in world + add_reagent("cyanide") +*/ + +/obj/item/weapon/reagent_containers/borghypo/attack(mob/M as mob, mob/user as mob) + var/datum/reagents/reagents = reagent_list[mode] + + if(!reagents.total_volume) to_chat(user, "The injector is empty.") - return - - if(!ismob(M)) - return - + return + + if(!ismob(M)) + return + to_chat(user, "You inject [M] with the injector.") to_chat(M, "You feel a tiny prick!") - reagents.reaction(M, INGEST) - - if(M.reagents) - var/transferred = reagents.trans_to(M, amount_per_transfer_from_this) + reagents.reaction(M, INGEST) + + if(M.reagents) + var/transferred = reagents.trans_to(M, amount_per_transfer_from_this) to_chat(user, "[transferred] units injected. [reagents.total_volume] units remaining.") - -/obj/item/weapon/reagent_containers/borghypo/attack_self(mob/user as mob) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) // change the mode - - if(++mode > reagent_list.len) - mode = 1 - - charge_tick = 0 // prevents wasted chems/cell charge if you're cycling through modes. - + +/obj/item/weapon/reagent_containers/borghypo/attack_self(mob/user as mob) + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) // change the mode + + if(++mode > reagent_list.len) + mode = 1 + + charge_tick = 0 // prevents wasted chems/cell charge if you're cycling through modes. + to_chat(user, "Synthesizer is now producing '[reagent_ids[mode]]'.") - -/obj/item/weapon/reagent_containers/borghypo/examine(mob/user) - ..() - var/contents_count = 0 - for(var/datum/reagents/reagents in reagent_list) + +/obj/item/weapon/reagent_containers/borghypo/examine(mob/user) + ..() + var/contents_count = 0 + for(var/datum/reagents/reagents in reagent_list) to_chat(user, "It's currently has [reagents.total_volume] units of [reagent_ids[++contents_count]] stored.") to_chat(user, "It's currently producing '[reagent_ids[mode]]'.") - -/obj/item/weapon/reagent_containers/borghypo/upgraded - name = "Upgraded Cyborg Hypospray" - desc = "An upgraded hypospray with more potent chemicals and a larger storage capacity." - reagent_ids = list("doctorsdelight", "dexalinp", "spaceacillin", "charcoal") - volume = 50 - recharge_time = 3 // time it takes for shots to recharge (in seconds) + +/obj/item/weapon/reagent_containers/borghypo/upgraded + name = "Upgraded Cyborg Hypospray" + desc = "An upgraded hypospray with more potent chemicals and a larger storage capacity." + reagent_ids = list("doctorsdelight", "dexalinp", "spaceacillin", "charcoal") + volume = 50 + recharge_time = 3 // time it takes for shots to recharge (in seconds) diff --git a/code/modules/reagents/reagent_containers/chempack.dm b/code/modules/reagents/reagent_containers/chempack.dm index e0c08753fd6..0e446775beb 100644 --- a/code/modules/reagents/reagent_containers/chempack.dm +++ b/code/modules/reagents/reagent_containers/chempack.dm @@ -1,320 +1,320 @@ -//************************************************************** -// Chemical Pack -//************************************************************** -//Icons are in chemical.dm, chempack.dmi (left), chempack.dmi (right), and back.dmi - -//This item is designed to be a supplement to items which spray reagents, as well as the chemical mask. -//Currently, this applies to /obj/item/weapon/reagent_containers/spray and its childre, including the chemsprayer, -//as well as /obj/item/weapon/extinguisher and its children. When these items are empty, and attempt to spray, -//they will draw just enough reagents out of the chemical pack to make a full spray, after which they are again empty. -//This means that the sprayers serve more as a nozzle for the chemical pack, rather than the chemical pack serving as a -//refilling system. - -//The verb set_fill() alters how many units are put into the chemical pack when filling it from a reagent dispenser, such as -//a water tank, fuel tank, or sink. It does not affect filling by handheld reagent containers, that is still governed by -//that reagent container's set_APTFT() verb. - -//This item has a large volume, 1200u. As far as I know, the largest volume in the game for a reagent container so far. -//In order to prevent this from just being used as a gigantic beaker, it is not possible to pour reagents out of this -//item into other reagent containers, nor into machines, nor can it be used to force-feed someone the reagents. It cannot -//be loaded into chemistry dispensers or chemmasters, or anything else that takes beakers. It is possible to extract -//reagents from this container using a syringe, but frankly it would be faster to just fill four bluespace beakers rather -//than fill one of these and then extract all 1200u 15u at a time. - -/obj/item/weapon/reagent_containers/chempack - name = "chemical pack" - desc = "Useful for the storage and transport of large volumes of chemicals. Can be used in conjunction with a wide range of chemical-dispensing devices." - icon = 'icons/obj/chemical.dmi' - icon_state = "chempack" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/chempack.dmi', "right_hand" = 'icons/mob/in-hand/right/chempack.dmi') - flags = OPENCONTAINER|FPRINT - slot_flags = SLOT_BACK - throwforce = 3 - w_class = 4.0 - origin_tech = "bluespace=3;materials=3;engineering=5" - var/safety = 0 - var/primed = 0 - var/stage = 0 - var/auxiliary = 0 - var/beaker = null - volume = 1200 - possible_transfer_amounts = null - var/possible_fill_amounts = list(5,10,15,25,30,50,100,200,500,1000) - var/fill_amount = 10 - -/obj/item/weapon/reagent_containers/chempack/equipped(M as mob, back) - var/mob/living/carbon/human/H = M - if(H.back == src) - if(H.wear_mask && istype(H.wear_mask, /obj/item/clothing/mask/chemmask)) - var/obj/item/clothing/mask/chemmask/C = H.wear_mask - C.update_verbs() - -/obj/item/weapon/reagent_containers/chempack/proc/can_use_verbs(mob/user) - var/mob/living/carbon/human/M = user - if (M.stat == DEAD) - to_chat(user, "You can't do that while you're dead!") - return 0 - else if (M.stat == UNCONSCIOUS) - to_chat(user, "You must be conscious to do this!") - return 0 - else if (M.handcuffed) - to_chat(user, "You can't reach the controls while you're restrained!") - return 0 - else - return 1 - -/obj/item/weapon/reagent_containers/chempack/examine(mob/user) - ..() - if(beaker) - to_chat(user, "\icon[beaker] There is \a [beaker] in \the [src]'s auxiliary chamber.") - to_chat(user, "It contains:") - var/obj/item/weapon/reagent_containers/glass/B = beaker - if(B.reagents.reagent_list.len) - for(var/datum/reagent/R in B.reagents.reagent_list) - to_chat(user, "[R.volume] units of [R.name]") - else - to_chat(user, "Nothing.") - -/obj/item/weapon/reagent_containers/chempack/on_reagent_change() - update_icon() - -/obj/item/weapon/reagent_containers/chempack/update_icon() - var/mob/living/carbon/human/H = loc - overlays.len = 0 - - if(reagents.total_volume) - var/image/filling = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10") - var/image/fillingback = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10b") - var/image/fillinghandr = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10rh") - var/image/fillinghandl = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10lh") - - var/percent = round((reagents.total_volume / volume) * 100) - switch(percent) - if(0 to 9) filling.icon_state = "[initial(icon_state)]-10" - if(10 to 24) filling.icon_state = "[initial(icon_state)]10" - if(25 to 49) filling.icon_state = "[initial(icon_state)]25" - if(50 to 74) filling.icon_state = "[initial(icon_state)]50" - if(75 to 79) filling.icon_state = "[initial(icon_state)]75" - if(80 to 90) filling.icon_state = "[initial(icon_state)]80" - if(91 to INFINITY) filling.icon_state = "[initial(icon_state)]100" - - filling.icon += mix_color_from_reagents(reagents.reagent_list) - filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) - - fillingback.icon_state = "[filling.icon_state]b" - fillinghandr.icon_state = "[filling.icon_state]rh" - fillinghandl.icon_state = "[filling.icon_state]lh" - - fillingback.icon += mix_color_from_reagents(reagents.reagent_list) - fillingback.alpha = mix_alpha_from_reagents(reagents.reagent_list) - fillinghandr.icon += mix_color_from_reagents(reagents.reagent_list) - fillinghandr.alpha = mix_alpha_from_reagents(reagents.reagent_list) - fillinghandl.icon += mix_color_from_reagents(reagents.reagent_list) - fillinghandl.alpha = mix_alpha_from_reagents(reagents.reagent_list) - - dynamic_overlay["[BACK_LAYER]"] = fillingback - dynamic_overlay["[L_HAND_LAYER]"] = fillinghandl - dynamic_overlay["[R_HAND_LAYER]"] = fillinghandr - - overlays += filling - if (istype(loc,/mob/living/carbon/human)) //Needs to always update its own overlay, but only update mob overlays if it's actually on a mob. - H.update_inv_back() - H.update_inv_r_hand() - H.update_inv_l_hand() - - else - dynamic_overlay = null - if (istype(loc,/mob/living/carbon/human)) - H.update_inv_back() - H.update_inv_r_hand() - H.update_inv_l_hand() - -/obj/item/weapon/reagent_containers/chempack/verb/flush_tanks() //Completely empties the chempack's tanks, since you can't pour it onto the floor or into something else. - set name = "Flush chemical tanks" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - src.reagents.clear_reagents() - to_chat(usr, "You flush the contents of \the [src].") - src.update_icon() - -obj/item/weapon/reagent_containers/chempack/verb/set_fill() - set name = "Set fill amount" - set category = "Object" - set src in usr - - if (!can_use_verbs(usr)) - return - - var/N = input("Fill amount for this:","[src]") as null|anything in possible_fill_amounts - if (N) - fill_amount = N - -/obj/item/weapon/reagent_containers/chempack/afterattack(atom/A as obj, mob/user as mob, var/adjacency_flag) - if (istype(A, /obj/structure/reagent_dispensers) && adjacency_flag) - var/tx_amount = transfer_sub(A, src, fill_amount, user) - if (tx_amount > 0) - to_chat(user, "You fill \the [src][src.is_full() ? " to the brim" : ""] with [tx_amount] units of the contents of \the [A].") - return - -/obj/item/weapon/reagent_containers/chempack/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/reagent_containers/glass)) - if(src.safety && auxiliary) - if (stage) - to_chat(user, "You need to secure the maintenance panel before you can insert a beaker!") - return - if(user.type == /mob/living/silicon/robot) //Can't have silicons putting their beakers inside this. - return - if(src.beaker) - to_chat(user, "There is already a beaker loaded into \the [src].") - return - else - if(user.drop_item(W, src)) - src.beaker = W - to_chat(user, "You add the beaker to \the [src]'s auxiliary chamber!") - if(user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/chemmask)) - var/obj/item/clothing/mask/chemmask/C = user.wear_mask - C.update_verbs() - return 1 - else - return - - if(iswrench(W)) - if (stage) - to_chat(user, "You need to secure the maintenance panel before you can access the auxiliary chamber bolts!") - return - if (!auxiliary && !src.beaker) - auxiliary = 1 - to_chat(user, "You loosen the bolts of \the [src]'s auxiliary chamber.") - return - else if (!auxiliary) - auxiliary = 1 - to_chat(user, "You loosen the bolts of \the [src]'s auxiliary chamber. The beaker can now be removed.") - return - else if (auxiliary && src.beaker) - auxiliary = 0 - to_chat(user, "You tighten the bolts of \the [src]'s auxiliary chamber, securing the beaker in place.") - return - else - auxiliary = 0 - to_chat(user, "You tighten the bolts of \the [src]'s auxiliary chamber.") - return - - switch(stage) //Handles the different stages of overriding the chemical pack's safeties. This can be done completely with a standard set of tools. - if(0) - if(isscrewdriver(W) && user.back == src) - to_chat(user, "You can't perform maintenance on \the [src] while you're wearing it!") - return - else - if (iscrowbar(W) && src.beaker && auxiliary) - var/obj/item/weapon/reagent_containers/glass/B = beaker - if ((user.get_inactive_hand() == src) || (user.back == src)) - B.loc = user.loc - else - B.loc = loc - beaker = null - to_chat(user, "You pry the beaker out of \the [src].") - if(user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/chemmask)) - var/obj/item/clothing/mask/chemmask/C = user.wear_mask - C.update_verbs() - return - else if (iscrowbar(W) && src.beaker && !auxiliary) - to_chat(user, "The beaker is held tight by the bolts of the auxiliary chamber!") - return - if (isscrewdriver(W) && src.beaker) - to_chat(user, "You can't reach the maintenance panel with the beaker in the way!") - return - else if (isscrewdriver(W)) - stage = 1 - slot_flags = null - to_chat(user, "You unscrew the maintenance panel of \the [src].") - icon_state = "[initial(icon_state)]3" - user.update_inv_r_hand() //These procs are to force the item's in_hand mob overlay to update to reflect the different stages of building. It was the only way I could find to accomplish this. - user.update_inv_l_hand() - return - if(1) - if (iscrowbar(W)) - if (primed == 0) - stage = 2 - else - stage = 3 - to_chat(user, "You pry open the maintenance panel of \the [src].") - icon_state = "[initial(icon_state)]2" - user.update_inv_r_hand() - user.update_inv_l_hand() - return - else if (isscrewdriver(W)) - stage = 0 - slot_flags = SLOT_BACK - to_chat(user, "You secure the maintenance panel of \the [src].") - if (safety == 0) - icon_state = "[initial(icon_state)]" - user.update_inv_r_hand() - user.update_inv_l_hand() - else - icon_state = "[initial(icon_state)]1" - user.update_inv_r_hand() - user.update_inv_l_hand() - return - if(2) - if (iswirecutter(W)) - stage = 3 - primed = 1 - to_chat(user, "You reroute the connections within \the [src].") - return - else if (iscrowbar(W)) - stage = 1 - to_chat(user, "You close the maintenance panel of \the [src].") - icon_state = "[initial(icon_state)]3" - user.update_inv_r_hand() - user.update_inv_l_hand() - return - if(3) - if (ismultitool(W)) - if (safety == 0) - to_chat(user, "You activate the manual safety override of \the [src]!") - to_chat(user, "The bolts for the auxiliary chamber of \the [src] have been exposed!") - safety = 1 - else if (safety == 1) - to_chat(user, "You reactivate the safety restrictions of \the [src].") - to_chat(user, "The bolts for the auxiliary chamber of \the [src] are now hidden.") - safety = 0 - return - else if (iscrowbar(W)) - stage = 1 - to_chat(user, "You close the maintenance panel of \the [src].") - icon_state = "[initial(icon_state)]3" - user.update_inv_r_hand() - user.update_inv_l_hand() - return - -/obj/item/weapon/reagent_containers/chempack/override - safety = 1 - -/obj/item/weapon/reagent_containers/chempack/override/New() - ..() - icon_state = "[initial(icon_state)]1" - -/obj/item/weapon/reagent_containers/chempack/override/fully_loaded - -/obj/item/weapon/reagent_containers/chempack/override/fully_loaded/New() - ..() - beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large - var/obj/item/weapon/reagent_containers/glass/B = beaker - B.reagents.add_reagent("creatine",100) - reagents.add_reagent("kelotane", 125) - reagents.add_reagent("dermaline", 125) - reagents.add_reagent("tricordrazine", 125) - reagents.add_reagent("anti_toxin", 210) - reagents.add_reagent("bicaridine", 125) - reagents.add_reagent("hyperzine", 22) - reagents.add_reagent("imidazoline", 122) - reagents.add_reagent("arithrazine", 32) - reagents.add_reagent("hyronalin", 32) - reagents.add_reagent("alkysine", 32) - reagents.add_reagent("dexalinp", 125) +//************************************************************** +// Chemical Pack +//************************************************************** +//Icons are in chemical.dm, chempack.dmi (left), chempack.dmi (right), and back.dmi + +//This item is designed to be a supplement to items which spray reagents, as well as the chemical mask. +//Currently, this applies to /obj/item/weapon/reagent_containers/spray and its childre, including the chemsprayer, +//as well as /obj/item/weapon/extinguisher and its children. When these items are empty, and attempt to spray, +//they will draw just enough reagents out of the chemical pack to make a full spray, after which they are again empty. +//This means that the sprayers serve more as a nozzle for the chemical pack, rather than the chemical pack serving as a +//refilling system. + +//The verb set_fill() alters how many units are put into the chemical pack when filling it from a reagent dispenser, such as +//a water tank, fuel tank, or sink. It does not affect filling by handheld reagent containers, that is still governed by +//that reagent container's set_APTFT() verb. + +//This item has a large volume, 1200u. As far as I know, the largest volume in the game for a reagent container so far. +//In order to prevent this from just being used as a gigantic beaker, it is not possible to pour reagents out of this +//item into other reagent containers, nor into machines, nor can it be used to force-feed someone the reagents. It cannot +//be loaded into chemistry dispensers or chemmasters, or anything else that takes beakers. It is possible to extract +//reagents from this container using a syringe, but frankly it would be faster to just fill four bluespace beakers rather +//than fill one of these and then extract all 1200u 15u at a time. + +/obj/item/weapon/reagent_containers/chempack + name = "chemical pack" + desc = "Useful for the storage and transport of large volumes of chemicals. Can be used in conjunction with a wide range of chemical-dispensing devices." + icon = 'icons/obj/chemical.dmi' + icon_state = "chempack" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/chempack.dmi', "right_hand" = 'icons/mob/in-hand/right/chempack.dmi') + flags = OPENCONTAINER|FPRINT + slot_flags = SLOT_BACK + throwforce = 3 + w_class = 4.0 + origin_tech = "bluespace=3;materials=3;engineering=5" + var/safety = 0 + var/primed = 0 + var/stage = 0 + var/auxiliary = 0 + var/beaker = null + volume = 1200 + possible_transfer_amounts = null + var/possible_fill_amounts = list(5,10,15,25,30,50,100,200,500,1000) + var/fill_amount = 10 + +/obj/item/weapon/reagent_containers/chempack/equipped(M as mob, back) + var/mob/living/carbon/human/H = M + if(H.back == src) + if(H.wear_mask && istype(H.wear_mask, /obj/item/clothing/mask/chemmask)) + var/obj/item/clothing/mask/chemmask/C = H.wear_mask + C.update_verbs() + +/obj/item/weapon/reagent_containers/chempack/proc/can_use_verbs(mob/user) + var/mob/living/carbon/human/M = user + if (M.stat == DEAD) + to_chat(user, "You can't do that while you're dead!") + return 0 + else if (M.stat == UNCONSCIOUS) + to_chat(user, "You must be conscious to do this!") + return 0 + else if (M.handcuffed) + to_chat(user, "You can't reach the controls while you're restrained!") + return 0 + else + return 1 + +/obj/item/weapon/reagent_containers/chempack/examine(mob/user) + ..() + if(beaker) + to_chat(user, "\icon[beaker] There is \a [beaker] in \the [src]'s auxiliary chamber.") + to_chat(user, "It contains:") + var/obj/item/weapon/reagent_containers/glass/B = beaker + if(B.reagents.reagent_list.len) + for(var/datum/reagent/R in B.reagents.reagent_list) + to_chat(user, "[R.volume] units of [R.name]") + else + to_chat(user, "Nothing.") + +/obj/item/weapon/reagent_containers/chempack/on_reagent_change() + update_icon() + +/obj/item/weapon/reagent_containers/chempack/update_icon() + var/mob/living/carbon/human/H = loc + overlays.len = 0 + + if(reagents.total_volume) + var/image/filling = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10") + var/image/fillingback = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10b") + var/image/fillinghandr = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10rh") + var/image/fillinghandl = image('icons/obj/chempackfillings.dmi', src, "[initial(icon_state)]10lh") + + var/percent = round((reagents.total_volume / volume) * 100) + switch(percent) + if(0 to 9) filling.icon_state = "[initial(icon_state)]-10" + if(10 to 24) filling.icon_state = "[initial(icon_state)]10" + if(25 to 49) filling.icon_state = "[initial(icon_state)]25" + if(50 to 74) filling.icon_state = "[initial(icon_state)]50" + if(75 to 79) filling.icon_state = "[initial(icon_state)]75" + if(80 to 90) filling.icon_state = "[initial(icon_state)]80" + if(91 to INFINITY) filling.icon_state = "[initial(icon_state)]100" + + filling.icon += mix_color_from_reagents(reagents.reagent_list) + filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) + + fillingback.icon_state = "[filling.icon_state]b" + fillinghandr.icon_state = "[filling.icon_state]rh" + fillinghandl.icon_state = "[filling.icon_state]lh" + + fillingback.icon += mix_color_from_reagents(reagents.reagent_list) + fillingback.alpha = mix_alpha_from_reagents(reagents.reagent_list) + fillinghandr.icon += mix_color_from_reagents(reagents.reagent_list) + fillinghandr.alpha = mix_alpha_from_reagents(reagents.reagent_list) + fillinghandl.icon += mix_color_from_reagents(reagents.reagent_list) + fillinghandl.alpha = mix_alpha_from_reagents(reagents.reagent_list) + + dynamic_overlay["[BACK_LAYER]"] = fillingback + dynamic_overlay["[L_HAND_LAYER]"] = fillinghandl + dynamic_overlay["[R_HAND_LAYER]"] = fillinghandr + + overlays += filling + if (istype(loc,/mob/living/carbon/human)) //Needs to always update its own overlay, but only update mob overlays if it's actually on a mob. + H.update_inv_back() + H.update_inv_r_hand() + H.update_inv_l_hand() + + else + dynamic_overlay = null + if (istype(loc,/mob/living/carbon/human)) + H.update_inv_back() + H.update_inv_r_hand() + H.update_inv_l_hand() + +/obj/item/weapon/reagent_containers/chempack/verb/flush_tanks() //Completely empties the chempack's tanks, since you can't pour it onto the floor or into something else. + set name = "Flush chemical tanks" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + src.reagents.clear_reagents() + to_chat(usr, "You flush the contents of \the [src].") + src.update_icon() + +obj/item/weapon/reagent_containers/chempack/verb/set_fill() + set name = "Set fill amount" + set category = "Object" + set src in usr + + if (!can_use_verbs(usr)) + return + + var/N = input("Fill amount for this:","[src]") as null|anything in possible_fill_amounts + if (N) + fill_amount = N + +/obj/item/weapon/reagent_containers/chempack/afterattack(atom/A as obj, mob/user as mob, var/adjacency_flag) + if (istype(A, /obj/structure/reagent_dispensers) && adjacency_flag) + var/tx_amount = transfer_sub(A, src, fill_amount, user) + if (tx_amount > 0) + to_chat(user, "You fill \the [src][src.is_full() ? " to the brim" : ""] with [tx_amount] units of the contents of \the [A].") + return + +/obj/item/weapon/reagent_containers/chempack/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/reagent_containers/glass)) + if(src.safety && auxiliary) + if (stage) + to_chat(user, "You need to secure the maintenance panel before you can insert a beaker!") + return + if(user.type == /mob/living/silicon/robot) //Can't have silicons putting their beakers inside this. + return + if(src.beaker) + to_chat(user, "There is already a beaker loaded into \the [src].") + return + else + if(user.drop_item(W, src)) + src.beaker = W + to_chat(user, "You add the beaker to \the [src]'s auxiliary chamber!") + if(user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/chemmask)) + var/obj/item/clothing/mask/chemmask/C = user.wear_mask + C.update_verbs() + return 1 + else + return + + if(iswrench(W)) + if (stage) + to_chat(user, "You need to secure the maintenance panel before you can access the auxiliary chamber bolts!") + return + if (!auxiliary && !src.beaker) + auxiliary = 1 + to_chat(user, "You loosen the bolts of \the [src]'s auxiliary chamber.") + return + else if (!auxiliary) + auxiliary = 1 + to_chat(user, "You loosen the bolts of \the [src]'s auxiliary chamber. The beaker can now be removed.") + return + else if (auxiliary && src.beaker) + auxiliary = 0 + to_chat(user, "You tighten the bolts of \the [src]'s auxiliary chamber, securing the beaker in place.") + return + else + auxiliary = 0 + to_chat(user, "You tighten the bolts of \the [src]'s auxiliary chamber.") + return + + switch(stage) //Handles the different stages of overriding the chemical pack's safeties. This can be done completely with a standard set of tools. + if(0) + if(isscrewdriver(W) && user.back == src) + to_chat(user, "You can't perform maintenance on \the [src] while you're wearing it!") + return + else + if (iscrowbar(W) && src.beaker && auxiliary) + var/obj/item/weapon/reagent_containers/glass/B = beaker + if ((user.get_inactive_hand() == src) || (user.back == src)) + B.loc = user.loc + else + B.loc = loc + beaker = null + to_chat(user, "You pry the beaker out of \the [src].") + if(user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/chemmask)) + var/obj/item/clothing/mask/chemmask/C = user.wear_mask + C.update_verbs() + return + else if (iscrowbar(W) && src.beaker && !auxiliary) + to_chat(user, "The beaker is held tight by the bolts of the auxiliary chamber!") + return + if (isscrewdriver(W) && src.beaker) + to_chat(user, "You can't reach the maintenance panel with the beaker in the way!") + return + else if (isscrewdriver(W)) + stage = 1 + slot_flags = null + to_chat(user, "You unscrew the maintenance panel of \the [src].") + icon_state = "[initial(icon_state)]3" + user.update_inv_r_hand() //These procs are to force the item's in_hand mob overlay to update to reflect the different stages of building. It was the only way I could find to accomplish this. + user.update_inv_l_hand() + return + if(1) + if (iscrowbar(W)) + if (primed == 0) + stage = 2 + else + stage = 3 + to_chat(user, "You pry open the maintenance panel of \the [src].") + icon_state = "[initial(icon_state)]2" + user.update_inv_r_hand() + user.update_inv_l_hand() + return + else if (isscrewdriver(W)) + stage = 0 + slot_flags = SLOT_BACK + to_chat(user, "You secure the maintenance panel of \the [src].") + if (safety == 0) + icon_state = "[initial(icon_state)]" + user.update_inv_r_hand() + user.update_inv_l_hand() + else + icon_state = "[initial(icon_state)]1" + user.update_inv_r_hand() + user.update_inv_l_hand() + return + if(2) + if (iswirecutter(W)) + stage = 3 + primed = 1 + to_chat(user, "You reroute the connections within \the [src].") + return + else if (iscrowbar(W)) + stage = 1 + to_chat(user, "You close the maintenance panel of \the [src].") + icon_state = "[initial(icon_state)]3" + user.update_inv_r_hand() + user.update_inv_l_hand() + return + if(3) + if (ismultitool(W)) + if (safety == 0) + to_chat(user, "You activate the manual safety override of \the [src]!") + to_chat(user, "The bolts for the auxiliary chamber of \the [src] have been exposed!") + safety = 1 + else if (safety == 1) + to_chat(user, "You reactivate the safety restrictions of \the [src].") + to_chat(user, "The bolts for the auxiliary chamber of \the [src] are now hidden.") + safety = 0 + return + else if (iscrowbar(W)) + stage = 1 + to_chat(user, "You close the maintenance panel of \the [src].") + icon_state = "[initial(icon_state)]3" + user.update_inv_r_hand() + user.update_inv_l_hand() + return + +/obj/item/weapon/reagent_containers/chempack/override + safety = 1 + +/obj/item/weapon/reagent_containers/chempack/override/New() + ..() + icon_state = "[initial(icon_state)]1" + +/obj/item/weapon/reagent_containers/chempack/override/fully_loaded + +/obj/item/weapon/reagent_containers/chempack/override/fully_loaded/New() + ..() + beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large + var/obj/item/weapon/reagent_containers/glass/B = beaker + B.reagents.add_reagent("creatine",100) + reagents.add_reagent("kelotane", 125) + reagents.add_reagent("dermaline", 125) + reagents.add_reagent("tricordrazine", 125) + reagents.add_reagent("anti_toxin", 210) + reagents.add_reagent("bicaridine", 125) + reagents.add_reagent("hyperzine", 22) + reagents.add_reagent("imidazoline", 122) + reagents.add_reagent("arithrazine", 32) + reagents.add_reagent("hyronalin", 32) + reagents.add_reagent("alkysine", 32) + reagents.add_reagent("dexalinp", 125) reagents.add_reagent("leporazine", 125) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 109d78d71b0..3bf1313f44d 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -1,130 +1,130 @@ -//////////////////////////////////////////////////////////////////////////////// -/// Droppers. -//////////////////////////////////////////////////////////////////////////////// -/obj/item/weapon/reagent_containers/dropper - name = "Dropper" - desc = "A dropper. Transfers 5 units." - icon = 'icons/obj/chemical.dmi' - icon_state = "dropper0" - amount_per_transfer_from_this = 5 - possible_transfer_amounts = list(1,2,3,4,5) - volume = 5 - // List of types that can be injected regardless of the CONTAINEROPEN flag - // TODO Remove snowflake - var/injectable_types = list(/obj/item/weapon/reagent_containers/food, - /obj/item/slime_extract, - /obj/item/clothing/mask/cigarette, - /obj/item/weapon/storage/fancy/cigarettes, - /obj/item/weapon/implantcase/chem, - /obj/item/weapon/reagent_containers/pill/time_release) - -/obj/item/weapon/reagent_containers/dropper/update_icon() - icon_state = "dropper[(reagents.total_volume ? 1 : 0)]" - -/obj/item/weapon/reagent_containers/dropper/afterattack(obj/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) return - - if(!target.reagents) - if(reagents.total_volume) - if(istype(target, /obj/machinery/artifact)) - reagents.clear_reagents() - to_chat(user, "You squirt the solution onto the [target]!") - update_icon() - return - var/list/bad_reagents = reagents.get_bad_reagent_names() // Used for logging - if(reagents.total_volume) - - if(target.reagents.total_volume >= target.reagents.maximum_volume) - to_chat(user, "[target] is full.") - return - - if(!target.is_open_container() && !ismob(target) && !is_type_in_list(target, injectable_types)) //You can inject humans and food but you cant remove the shit. - to_chat(user, "You cannot directly fill this object.") - return - - var/trans = 0 - - if(ismob(target)) - if(ishuman(target)) - var/mob/living/carbon/human/victim = target - - var/obj/item/safe_thing = victim.get_body_part_coverage(EYES) - - if(safe_thing) - if(!safe_thing.reagents) - safe_thing.create_reagents(100) - trans = src.reagents.trans_to(safe_thing, amount_per_transfer_from_this) - - user.visible_message("[user] tries to squirt something into [target]'s eyes, but fails!") - spawn(5) - src.reagents.reaction(safe_thing, TOUCH) - to_chat(user, "You transfer [trans] units of the solution.") - update_icon() - return - user.visible_message("[user] squirts something into [target]'s eyes!") - src.reagents.reaction(target, TOUCH) - - var/mob/living/M = target - - var/list/injected = list() - for(var/datum/reagent/R in src.reagents.reagent_list) - injected += R.name - var/contained = english_list(injected) - M.attack_log += text("\[[time_stamp()]\] Has been squirted with [src.name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to squirt [M.name] ([M.key]). Reagents: [contained]") - msg_admin_attack("[user.name] ([user.ckey]) squirted [M.name] ([M.key]) with [src.name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - trans = src.reagents.trans_to(target, amount_per_transfer_from_this) - to_chat(user, "You transfer [trans] units of the solution.") - update_icon() - - // /vg/: Logging transfers of bad things - if(istype(target)) - if(istype(reagents_to_log) && reagents_to_log.len && target.log_reagents) - log_reagents(user, src, target, trans, bad_reagents) - else - - if(!target.is_open_container() && !istype(target,/obj/structure/reagent_dispensers)) - to_chat(user, "You cannot directly remove reagents from [target].") - return - - if(!target.reagents.total_volume) - to_chat(user, "[target] is empty.") - return - - var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) - if(istype(reagents_to_log) && reagents_to_log.len && target.log_reagents) - log_reagents(user, src, target, trans, bad_reagents) - - to_chat(user, "You fill [src] with [trans] units of the solution.") - - update_icon() - - return - -/obj/item/weapon/reagent_containers/dropper/baster - name = "baster" - desc = "A specialized tool for precise addition of chemicals." - icon_state = "baster" - possible_transfer_amounts = list(1,2,3,4,5,10,15) - volume = 15 - -/obj/item/weapon/reagent_containers/dropper/baster/update_icon() - return - -/obj/item/weapon/reagent_containers/dropper/robodropper - name = "Industrial Dropper" - desc = "A larger dropper. Transfers 10 units." - icon = 'icons/obj/chemical.dmi' - icon_state = "dropper0" - amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(1,2,3,4,5,6,7,8,9,10) - volume = 10 - -//////////////////////////////////////////////////////////////////////////////// -/// Droppers. END -//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// Droppers. +//////////////////////////////////////////////////////////////////////////////// +/obj/item/weapon/reagent_containers/dropper + name = "Dropper" + desc = "A dropper. Transfers 5 units." + icon = 'icons/obj/chemical.dmi' + icon_state = "dropper0" + amount_per_transfer_from_this = 5 + possible_transfer_amounts = list(1,2,3,4,5) + volume = 5 + // List of types that can be injected regardless of the CONTAINEROPEN flag + // TODO Remove snowflake + var/injectable_types = list(/obj/item/weapon/reagent_containers/food, + /obj/item/slime_extract, + /obj/item/clothing/mask/cigarette, + /obj/item/weapon/storage/fancy/cigarettes, + /obj/item/weapon/implantcase/chem, + /obj/item/weapon/reagent_containers/pill/time_release) + +/obj/item/weapon/reagent_containers/dropper/update_icon() + icon_state = "dropper[(reagents.total_volume ? 1 : 0)]" + +/obj/item/weapon/reagent_containers/dropper/afterattack(obj/target, mob/user, proximity_flag, click_parameters) + if(!proximity_flag) return + + if(!target.reagents) + if(reagents.total_volume) + if(istype(target, /obj/machinery/artifact)) + reagents.clear_reagents() + to_chat(user, "You squirt the solution onto the [target]!") + update_icon() + return + var/list/bad_reagents = reagents.get_bad_reagent_names() // Used for logging + if(reagents.total_volume) + + if(target.reagents.total_volume >= target.reagents.maximum_volume) + to_chat(user, "[target] is full.") + return + + if(!target.is_open_container() && !ismob(target) && !is_type_in_list(target, injectable_types)) //You can inject humans and food but you cant remove the shit. + to_chat(user, "You cannot directly fill this object.") + return + + var/trans = 0 + + if(ismob(target)) + if(ishuman(target)) + var/mob/living/carbon/human/victim = target + + var/obj/item/safe_thing = victim.get_body_part_coverage(EYES) + + if(safe_thing) + if(!safe_thing.reagents) + safe_thing.create_reagents(100) + trans = src.reagents.trans_to(safe_thing, amount_per_transfer_from_this) + + user.visible_message("[user] tries to squirt something into [target]'s eyes, but fails!") + spawn(5) + src.reagents.reaction(safe_thing, TOUCH) + to_chat(user, "You transfer [trans] units of the solution.") + update_icon() + return + user.visible_message("[user] squirts something into [target]'s eyes!") + src.reagents.reaction(target, TOUCH) + + var/mob/living/M = target + + var/list/injected = list() + for(var/datum/reagent/R in src.reagents.reagent_list) + injected += R.name + var/contained = english_list(injected) + M.attack_log += text("\[[time_stamp()]\] Has been squirted with [src.name] by [user.name] ([user.ckey]). Reagents: [contained]") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to squirt [M.name] ([M.key]). Reagents: [contained]") + msg_admin_attack("[user.name] ([user.ckey]) squirted [M.name] ([M.key]) with [src.name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + trans = src.reagents.trans_to(target, amount_per_transfer_from_this) + to_chat(user, "You transfer [trans] units of the solution.") + update_icon() + + // /vg/: Logging transfers of bad things + if(istype(target)) + if(istype(reagents_to_log) && reagents_to_log.len && target.log_reagents) + log_reagents(user, src, target, trans, bad_reagents) + else + + if(!target.is_open_container() && !istype(target,/obj/structure/reagent_dispensers)) + to_chat(user, "You cannot directly remove reagents from [target].") + return + + if(!target.reagents.total_volume) + to_chat(user, "[target] is empty.") + return + + var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) + if(istype(reagents_to_log) && reagents_to_log.len && target.log_reagents) + log_reagents(user, src, target, trans, bad_reagents) + + to_chat(user, "You fill [src] with [trans] units of the solution.") + + update_icon() + + return + +/obj/item/weapon/reagent_containers/dropper/baster + name = "baster" + desc = "A specialized tool for precise addition of chemicals." + icon_state = "baster" + possible_transfer_amounts = list(1,2,3,4,5,10,15) + volume = 15 + +/obj/item/weapon/reagent_containers/dropper/baster/update_icon() + return + +/obj/item/weapon/reagent_containers/dropper/robodropper + name = "Industrial Dropper" + desc = "A larger dropper. Transfers 10 units." + icon = 'icons/obj/chemical.dmi' + icon_state = "dropper0" + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(1,2,3,4,5,6,7,8,9,10) + volume = 10 + +//////////////////////////////////////////////////////////////////////////////// +/// Droppers. END +//////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/reagents/reagent_containers/food.dm b/code/modules/reagents/reagent_containers/food.dm index 415cff2bcd7..abff1c4a741 100644 --- a/code/modules/reagents/reagent_containers/food.dm +++ b/code/modules/reagents/reagent_containers/food.dm @@ -1,13 +1,13 @@ -//////////////////////////////////////////////////////////////////////////////// -/// Food. -//////////////////////////////////////////////////////////////////////////////// - -//Food is basically a glorified beaker with a lot of fancy coding. Now you know, and knowing is half the battle -/obj/item/weapon/reagent_containers/food - possible_transfer_amounts = null - volume = 50 //Food can contain a beaker's worth of reagents unless specified otherwise. Do note large servings of complex food items can contain well over 50 reagents total - -/obj/item/weapon/reagent_containers/food/New() - ..() - src.pixel_x = rand(-5.0, 5) //Randomizes position slightly. - src.pixel_y = rand(-5.0, 5) +//////////////////////////////////////////////////////////////////////////////// +/// Food. +//////////////////////////////////////////////////////////////////////////////// + +//Food is basically a glorified beaker with a lot of fancy coding. Now you know, and knowing is half the battle +/obj/item/weapon/reagent_containers/food + possible_transfer_amounts = null + volume = 50 //Food can contain a beaker's worth of reagents unless specified otherwise. Do note large servings of complex food items can contain well over 50 reagents total + +/obj/item/weapon/reagent_containers/food/New() + ..() + src.pixel_x = rand(-5.0, 5) //Randomizes position slightly. + src.pixel_y = rand(-5.0, 5) diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm index 923b5dc9f91..0d7492f3cbc 100644 --- a/code/modules/reagents/reagent_containers/food/condiment.dm +++ b/code/modules/reagents/reagent_containers/food/condiment.dm @@ -1,277 +1,277 @@ - -///////////////////////////////////////////////Condiments -//Notes by Darem: The condiments food-subtype is for stuff you don't actually eat but you use to modify existing food. They all -// leave empty containers when used up and can be filled/re-filled with other items. Formatting for first section is identical -// to mixed-drinks code. If you want an object that starts pre-loaded, you need to make it in addition to the other code. - -//Food items that aren't eaten normally and leave an empty container behind -//To clarify, these are special containers used to hold reagents specific to cooking, produced from the Kitchen CondiMaster -/obj/item/weapon/reagent_containers/food/condiment - name = "condiment container" - desc = "Just your average condiment container." - icon = 'icons/obj/food.dmi' - icon_state = "emptycondiment" - item_state = null - flags = FPRINT | OPENCONTAINER - possible_transfer_amounts = list(1,5,10) - volume = 50 - -/obj/item/weapon/reagent_containers/food/condiment/attackby(obj/item/weapon/W as obj, mob/user as mob) - - return - -/obj/item/weapon/reagent_containers/food/condiment/attack_self(mob/user as mob) - - attack(user, user) - return - -/obj/item/weapon/reagent_containers/food/condiment/attack(mob/living/M as mob, mob/user as mob, def_zone) - - var/datum/reagents/R = src.reagents - - if(!R || !R.total_volume) + +///////////////////////////////////////////////Condiments +//Notes by Darem: The condiments food-subtype is for stuff you don't actually eat but you use to modify existing food. They all +// leave empty containers when used up and can be filled/re-filled with other items. Formatting for first section is identical +// to mixed-drinks code. If you want an object that starts pre-loaded, you need to make it in addition to the other code. + +//Food items that aren't eaten normally and leave an empty container behind +//To clarify, these are special containers used to hold reagents specific to cooking, produced from the Kitchen CondiMaster +/obj/item/weapon/reagent_containers/food/condiment + name = "condiment container" + desc = "Just your average condiment container." + icon = 'icons/obj/food.dmi' + icon_state = "emptycondiment" + item_state = null + flags = FPRINT | OPENCONTAINER + possible_transfer_amounts = list(1,5,10) + volume = 50 + +/obj/item/weapon/reagent_containers/food/condiment/attackby(obj/item/weapon/W as obj, mob/user as mob) + + return + +/obj/item/weapon/reagent_containers/food/condiment/attack_self(mob/user as mob) + + attack(user, user) + return + +/obj/item/weapon/reagent_containers/food/condiment/attack(mob/living/M as mob, mob/user as mob, def_zone) + + var/datum/reagents/R = src.reagents + + if(!R || !R.total_volume) to_chat(user, "\The [src] is empty.") - return 0 - - if(M == user) //user drinking it - + return 0 + + if(M == user) //user drinking it + to_chat(M, "You swallow some of the contents of \the [src].") - if(reagents.total_volume) //Deal with the reagents in the food - reagents.reaction(M, INGEST) - spawn(5) - reagents.trans_to(M, amount_per_transfer_from_this) - - playsound(M.loc,'sound/items/drink.ogg', rand(10, 50), 1) - return 1 - - else if(istype(M, /mob/living/carbon)) //user feeding M the condiment. M also being carbon - - M.visible_message("[user] attempts to feed [M] \the [src]", \ - "[user] attempts to feed you \the [src]") - - if(!do_mob(user, M)) - return - - M.visible_message("[user] feeds [M] \the [src]", \ - "[user] feeds you \the [src]") - - //Logging shit - M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") - user.attack_log += text("\[[time_stamp()]\] Fed [src.name] by [M.name] ([M.ckey]) Reagents: [reagentlist(src)]") - log_attack("[user.name] ([user.ckey]) fed [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - if(reagents.total_volume) //Deal with the reagents in the food - reagents.reaction(M, INGEST) - spawn(5) - reagents.trans_to(M, amount_per_transfer_from_this) - - playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) - return 1 - return 0 - -/obj/item/weapon/reagent_containers/food/condiment/attackby(obj/item/I as obj, mob/user as mob) //We already have an attackby for weapons, but sure, whatever - - return - -/obj/item/weapon/reagent_containers/food/condiment/afterattack(obj/target, mob/user , flag) - if(!flag || ismob(target)) return 0 - if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us. - - if(!target.reagents.total_volume) //Nothing in the dispenser + if(reagents.total_volume) //Deal with the reagents in the food + reagents.reaction(M, INGEST) + spawn(5) + reagents.trans_to(M, amount_per_transfer_from_this) + + playsound(M.loc,'sound/items/drink.ogg', rand(10, 50), 1) + return 1 + + else if(istype(M, /mob/living/carbon)) //user feeding M the condiment. M also being carbon + + M.visible_message("[user] attempts to feed [M] \the [src]", \ + "[user] attempts to feed you \the [src]") + + if(!do_mob(user, M)) + return + + M.visible_message("[user] feeds [M] \the [src]", \ + "[user] feeds you \the [src]") + + //Logging shit + M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") + user.attack_log += text("\[[time_stamp()]\] Fed [src.name] by [M.name] ([M.ckey]) Reagents: [reagentlist(src)]") + log_attack("[user.name] ([user.ckey]) fed [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + if(reagents.total_volume) //Deal with the reagents in the food + reagents.reaction(M, INGEST) + spawn(5) + reagents.trans_to(M, amount_per_transfer_from_this) + + playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) + return 1 + return 0 + +/obj/item/weapon/reagent_containers/food/condiment/attackby(obj/item/I as obj, mob/user as mob) //We already have an attackby for weapons, but sure, whatever + + return + +/obj/item/weapon/reagent_containers/food/condiment/afterattack(obj/target, mob/user , flag) + if(!flag || ismob(target)) return 0 + if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us. + + if(!target.reagents.total_volume) //Nothing in the dispenser to_chat(user, "\The [target] is empty.") - return - - if(reagents.total_volume >= reagents.maximum_volume) //Our condiment bottle is full + return + + if(reagents.total_volume >= reagents.maximum_volume) //Our condiment bottle is full to_chat(user, "\The [src] is full.") - return - - var/trans = target.reagents.trans_to(src, target:amount_per_transfer_from_this) + return + + var/trans = target.reagents.trans_to(src, target:amount_per_transfer_from_this) to_chat(user, "You fill [src] with [trans] units of the contents of [target].") - - //Something like a glass or a food item. Player probably wants to transfer TO it. - else if(target.is_open_container() || istype(target, /obj/item/weapon/reagent_containers/food/snacks)) - if(!reagents.total_volume) + + //Something like a glass or a food item. Player probably wants to transfer TO it. + else if(target.is_open_container() || istype(target, /obj/item/weapon/reagent_containers/food/snacks)) + if(!reagents.total_volume) to_chat(user, "\The [src] is empty.") - return - if(target.reagents.total_volume >= target.reagents.maximum_volume) + return + if(target.reagents.total_volume >= target.reagents.maximum_volume) to_chat(user, "You can't add anymore to \the [target].") - return - var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this) + return + var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this) to_chat(user, "You transfer [trans] units of the condiment to \the [target].") - -/obj/item/weapon/reagent_containers/food/condiment/on_reagent_change() //Due to the way condiment bottles work, we define "special types" here - - if(reagents.reagent_list.len > 0) - - switch(reagents.get_master_reagent_id()) - - if("ketchup") - name = "ketchup" - desc = "You feel more American already." - icon_state = "ketchup" - item_state = null - if("capsaicin") - name = "hotsauce" - desc = "You can almost TASTE the stomach ulcers now!" - icon_state = "hotsauce" - item_state = null - if("enzyme") - name = "universal enzyme" - desc = "Used in cooking various dishes." - icon_state = "enzyme" - item_state = null - if("flour") - name = "flour sack" - desc = "A big bag of flour. Good for baking!" - icon_state = "flour" - item_state = null - if("milk") - name = "space milk" - desc = "It's milk. White and nutritious goodness!" - icon_state = "milk" - item_state = "carton" - if("soymilk") - name = "soy milk" - desc = "It's soy milk. White and nutritious goodness!" - icon_state = "soymilk" - item_state = "carton" - if("rice") - name = "rice sack" - desc = "A taste of Asia in the kitchen." - icon_state = "rice" - item_state = null - if("soysauce") - name = "soy sauce" - desc = "A salty soy-based flavoring." - icon_state = "soysauce" - item_state = null - if("frostoil") - name = "coldsauce" - desc = "Leaves the tongue numb in its passage." - icon_state = "coldsauce" - item_state = null - if("sodiumchloride") - name = "salt shaker" - desc = "Salt. From space oceans, presumably." - icon_state = "saltshakersmall" - item_state = null - if("blackpepper") - name = "pepper mill" - desc = "Often used to flavor food or make people sneeze." - icon_state = "peppermillsmall" - item_state = null - if("cornoil") - name = "corn oil" - desc = "A delicious oil used in cooking. Made from corn." - icon_state = "cornoil" - item_state = null - if("sugar") - name = "sugar" - desc = "Tastey space sugar!" - icon_state = "sugar" - item_state = null - if("chefspecial") - name = "\improper Chef Excellence's Special Sauce" - desc = "A potent sauce distilled from the toxin glands of 1000 Space Carp." - icon_state = "emptycondiment" - item_state = null - if("vinegar") - name = "malt vinegar bottle" - desc = "Perfect for fish and chips!" - icon_state = "vinegar_container" - item_state = null - if("honey") - name = "honey pot" - desc = "Sweet and healthy!" - icon_state = "honey" - item_state = null - if("cinnamon") - name = "cinnamon shaker" - desc = "A spice, obtained from the bark of cinnamomum trees." - icon_state = "cinnamon" - item_state = null - else - name = "misc condiment bottle" - desc = "Just your average condiment container." - icon_state = "emptycondiment" - item_state = null - - if(reagents.reagent_list.len == 1) - desc = "Looks like it is [reagents.get_master_reagent_name()], but you are not sure." - else - desc = "A mixture of various condiments. [reagents.get_master_reagent_name()] is one of them." - icon_state = "mixedcondiments" - else - icon_state = "emptycondiment" - name = "condiment bottle" - desc = "An empty condiment bottle." - return - -//Specific condiment bottle entities for mapping and potentially spawning (these are NOT used for any above procs) - -/obj/item/weapon/reagent_containers/food/condiment/enzyme - name = "universal enzyme" - desc = "Used in cooking various dishes." - icon_state = "enzyme" - - New() - ..() - reagents.add_reagent("enzyme", 50) - -/obj/item/weapon/reagent_containers/food/condiment/sugar - - New() - ..() - reagents.add_reagent("sugar", 50) - -/obj/item/weapon/reagent_containers/food/condiment/saltshaker - name = "salt shaker" - desc = "Salt. From space oceans, presumably." - icon_state = "saltshakersmall" - possible_transfer_amounts = list(1, 50) //For clowns turning the lid off. - amount_per_transfer_from_this = 1 - - New() - ..() - reagents.add_reagent("sodiumchloride", 50) - -/obj/item/weapon/reagent_containers/food/condiment/peppermill - name = "pepper mill" - desc = "Often used to flavor food or make people sneeze." - icon_state = "peppermillsmall" - possible_transfer_amounts = list(1, 50) //For clowns turning the lid off. - amount_per_transfer_from_this = 1 - - New() - ..() - reagents.add_reagent("blackpepper", 50) - -/obj/item/weapon/reagent_containers/food/condiment/syndisauce - name = "Chef Excellence's Special Sauce" - desc = "A potent sauce distilled from the toxin glands of 1000 Space Carp with an extra touch of LSD, because why not?" - amount_per_transfer_from_this = 1 - - New() - ..() - reagents.add_reagent("chefspecial", 20) - -/obj/item/weapon/reagent_containers/food/condiment/vinegar - name = "malt vinegar bottle" - desc = "Perfect for fish and chips." - New() - ..() - reagents.add_reagent("vinegar", 50) - -/obj/item/weapon/reagent_containers/food/condiment/exotic - name = "exotic bottle" - desc = "If you can see this label, something is wrong." - //~9% chance of anything but special sauce, which is .09 chance - var/global/list/possible_exotic_condiments = list("enzyme"=10,"blackpepper"=10,"vinegar"=10,"sodiumchloride"=10,"cinnamon"=10,"chefspecial"=1,"frostoil"=10,"soysauce"=10,"capsaicin"=10,"honey"=10,"ketchup"=10,"coco"=10) - New() - ..() - reagents.add_reagent(pickweight(possible_exotic_condiments), 30) + +/obj/item/weapon/reagent_containers/food/condiment/on_reagent_change() //Due to the way condiment bottles work, we define "special types" here + + if(reagents.reagent_list.len > 0) + + switch(reagents.get_master_reagent_id()) + + if("ketchup") + name = "ketchup" + desc = "You feel more American already." + icon_state = "ketchup" + item_state = null + if("capsaicin") + name = "hotsauce" + desc = "You can almost TASTE the stomach ulcers now!" + icon_state = "hotsauce" + item_state = null + if("enzyme") + name = "universal enzyme" + desc = "Used in cooking various dishes." + icon_state = "enzyme" + item_state = null + if("flour") + name = "flour sack" + desc = "A big bag of flour. Good for baking!" + icon_state = "flour" + item_state = null + if("milk") + name = "space milk" + desc = "It's milk. White and nutritious goodness!" + icon_state = "milk" + item_state = "carton" + if("soymilk") + name = "soy milk" + desc = "It's soy milk. White and nutritious goodness!" + icon_state = "soymilk" + item_state = "carton" + if("rice") + name = "rice sack" + desc = "A taste of Asia in the kitchen." + icon_state = "rice" + item_state = null + if("soysauce") + name = "soy sauce" + desc = "A salty soy-based flavoring." + icon_state = "soysauce" + item_state = null + if("frostoil") + name = "coldsauce" + desc = "Leaves the tongue numb in its passage." + icon_state = "coldsauce" + item_state = null + if("sodiumchloride") + name = "salt shaker" + desc = "Salt. From space oceans, presumably." + icon_state = "saltshakersmall" + item_state = null + if("blackpepper") + name = "pepper mill" + desc = "Often used to flavor food or make people sneeze." + icon_state = "peppermillsmall" + item_state = null + if("cornoil") + name = "corn oil" + desc = "A delicious oil used in cooking. Made from corn." + icon_state = "cornoil" + item_state = null + if("sugar") + name = "sugar" + desc = "Tastey space sugar!" + icon_state = "sugar" + item_state = null + if("chefspecial") + name = "\improper Chef Excellence's Special Sauce" + desc = "A potent sauce distilled from the toxin glands of 1000 Space Carp." + icon_state = "emptycondiment" + item_state = null + if("vinegar") + name = "malt vinegar bottle" + desc = "Perfect for fish and chips!" + icon_state = "vinegar_container" + item_state = null + if("honey") + name = "honey pot" + desc = "Sweet and healthy!" + icon_state = "honey" + item_state = null + if("cinnamon") + name = "cinnamon shaker" + desc = "A spice, obtained from the bark of cinnamomum trees." + icon_state = "cinnamon" + item_state = null + else + name = "misc condiment bottle" + desc = "Just your average condiment container." + icon_state = "emptycondiment" + item_state = null + + if(reagents.reagent_list.len == 1) + desc = "Looks like it is [reagents.get_master_reagent_name()], but you are not sure." + else + desc = "A mixture of various condiments. [reagents.get_master_reagent_name()] is one of them." + icon_state = "mixedcondiments" + else + icon_state = "emptycondiment" + name = "condiment bottle" + desc = "An empty condiment bottle." + return + +//Specific condiment bottle entities for mapping and potentially spawning (these are NOT used for any above procs) + +/obj/item/weapon/reagent_containers/food/condiment/enzyme + name = "universal enzyme" + desc = "Used in cooking various dishes." + icon_state = "enzyme" + + New() + ..() + reagents.add_reagent("enzyme", 50) + +/obj/item/weapon/reagent_containers/food/condiment/sugar + + New() + ..() + reagents.add_reagent("sugar", 50) + +/obj/item/weapon/reagent_containers/food/condiment/saltshaker + name = "salt shaker" + desc = "Salt. From space oceans, presumably." + icon_state = "saltshakersmall" + possible_transfer_amounts = list(1, 50) //For clowns turning the lid off. + amount_per_transfer_from_this = 1 + + New() + ..() + reagents.add_reagent("sodiumchloride", 50) + +/obj/item/weapon/reagent_containers/food/condiment/peppermill + name = "pepper mill" + desc = "Often used to flavor food or make people sneeze." + icon_state = "peppermillsmall" + possible_transfer_amounts = list(1, 50) //For clowns turning the lid off. + amount_per_transfer_from_this = 1 + + New() + ..() + reagents.add_reagent("blackpepper", 50) + +/obj/item/weapon/reagent_containers/food/condiment/syndisauce + name = "Chef Excellence's Special Sauce" + desc = "A potent sauce distilled from the toxin glands of 1000 Space Carp with an extra touch of LSD, because why not?" + amount_per_transfer_from_this = 1 + + New() + ..() + reagents.add_reagent("chefspecial", 20) + +/obj/item/weapon/reagent_containers/food/condiment/vinegar + name = "malt vinegar bottle" + desc = "Perfect for fish and chips." + New() + ..() + reagents.add_reagent("vinegar", 50) + +/obj/item/weapon/reagent_containers/food/condiment/exotic + name = "exotic bottle" + desc = "If you can see this label, something is wrong." + //~9% chance of anything but special sauce, which is .09 chance + var/global/list/possible_exotic_condiments = list("enzyme"=10,"blackpepper"=10,"vinegar"=10,"sodiumchloride"=10,"cinnamon"=10,"chefspecial"=1,"frostoil"=10,"soysauce"=10,"capsaicin"=10,"honey"=10,"ketchup"=10,"coco"=10) + New() + ..() + reagents.add_reagent(pickweight(possible_exotic_condiments), 30) diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index ff1c0b31394..d204b8ce802 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -1,1217 +1,1217 @@ -//////////////////////////////////////////////////////////////////////////////// -/// Drinks. -//////////////////////////////////////////////////////////////////////////////// -/obj/item/weapon/reagent_containers/food/drinks - name = "drink" - desc = "yummy" - icon = 'icons/obj/drinks.dmi' - icon_state = null - flags = FPRINT | OPENCONTAINER - var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it. - possible_transfer_amounts = list(5, 10, 25) - volume = 50 - log_reagents = 1 - //Merged from bottle.dm - Hinaichigo - var/const/duration = 13 //Directly relates to the 'weaken' duration. Lowered by armor (i.e. helmets) - var/isGlass = 0 //Whether the 'bottle' is made of glass or not so that milk cartons dont shatter when someone gets hit by it - - //Molotov and smashing variables - var/molotov = 0 //-1 = can be made into molotov, 0 = can't, 1 = has had rag stuffed into it - var/lit = 0 - var/brightness_lit = 3 - var/bottleheight = 23 //To offset the molotov rag and fire - beer and ale are 23 - var/smashtext = "bottle of " //To handle drinking glasses and the flask of holy water - var/smashname = "broken bottle" //As above - var/viewcontents = 1 - var/flammable = 0 - var/flammin = 0 - var/flammin_color = null - -/obj/item/weapon/reagent_containers/food/drinks/on_reagent_change() - if(gulp_size < 5) - gulp_size = 5 - else - gulp_size = max(round(reagents.total_volume / 5), 5) - if(reagents.has_reagent("blackcolor")) - viewcontents = 0 - else - viewcontents = 1 - -/obj/item/weapon/reagent_containers/food/drinks/attack_self(mob/user as mob) - if(!is_open_container()) - to_chat(user, "You can't, \the [src] is closed.")//Added this here and elsewhere to prevent drinking, etc. from closed drink containers. - Hinaichigo +//////////////////////////////////////////////////////////////////////////////// +/// Drinks. +//////////////////////////////////////////////////////////////////////////////// +/obj/item/weapon/reagent_containers/food/drinks + name = "drink" + desc = "yummy" + icon = 'icons/obj/drinks.dmi' + icon_state = null + flags = FPRINT | OPENCONTAINER + var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it. + possible_transfer_amounts = list(5, 10, 25) + volume = 50 + log_reagents = 1 + //Merged from bottle.dm - Hinaichigo + var/const/duration = 13 //Directly relates to the 'weaken' duration. Lowered by armor (i.e. helmets) + var/isGlass = 0 //Whether the 'bottle' is made of glass or not so that milk cartons dont shatter when someone gets hit by it - return 0 - - else if(!src.reagents.total_volume || !src) - to_chat(user, "\The [src] is empty.") - return 0 - - else - imbibe(user) - return 0 - -/obj/item/weapon/reagent_containers/food/drinks/attack(mob/living/M as mob, mob/user as mob, def_zone) - var/datum/reagents/R = src.reagents - var/fillevel = gulp_size - - //Smashing on someone - if(user.a_intent == I_HURT && isGlass && molotov != 1) //To smash a bottle on someone, the user must be harm intent, the bottle must be out of glass, and we don't want a rag in here - - if(!M) //This really shouldn't be checked here, but sure - return - - force = 15 //Smashing bottles over someoen's head hurts. //todo: check that this isn't overwriting anything it shouldn't be - - var/datum/organ/external/affecting = user.zone_sel.selecting //Find what the player is aiming at - - var/armor_block = 0 //Get the target's armour values for normal attack damage. - var/armor_duration = 0 //The more force the bottle has, the longer the duration. - - //Calculating duration and calculating damage. - if(ishuman(M)) - - var/mob/living/carbon/human/H = M - var/headarmor = 0 // Target's head armour - armor_block = H.run_armor_check(affecting, "melee") // For normal attack damage - - //If they have a hat/helmet and the user is targeting their head. - if(istype(H.head, /obj/item/clothing/head) && affecting == "head") - - // If their head has an armour value, assign headarmor to it, else give it 0. - if(H.head.armor["melee"]) - headarmor = H.head.armor["melee"] - else - headarmor = 0 - else - headarmor = 0 - - //Calculate the weakening duration for the target. - armor_duration = (duration - headarmor) + force - - else - //Only humans can have armour, right? - armor_block = M.run_armor_check(affecting, "melee") - if(affecting == "head") - armor_duration = duration + force - armor_duration /= 10 - - //Apply the damage! - M.apply_damage(force, BRUTE, affecting, armor_block) - - // You are going to knock someone out for longer if they are not wearing a helmet. - // For drinking glass - if(affecting == "head" && istype(M, /mob/living/carbon/)) - - //Display an attack message. - for(var/mob/O in viewers(user, null)) - if(M != user) O.show_message(text("[M] has been hit over the head with a [smashtext][src.name], by [user]!"), 1) - else O.show_message(text("[M] hit himself with a [smashtext][src.name] on the head!"), 1) - //Weaken the target for the duration that we calculated and divide it by 5. - if(armor_duration) - M.apply_effect(min(armor_duration, 10) , WEAKEN) // Never weaken more than a flash! - - else - //Default attack message and don't weaken the target. - for(var/mob/O in viewers(user, null)) - if(M != user) O.show_message(text("[M] has been attacked with a [smashtext][src.name], by [user]!"), 1) - else O.show_message(text("[M] has attacked himself with a [smashtext][src.name]!"), 1) - - //Attack logs - user.attack_log += text("\[[time_stamp()]\] Has attacked [M.name] ([M.ckey]) with a bottle!") - M.attack_log += text("\[[time_stamp()]\] Has been smashed with a bottle by [user.name] ([user.ckey])") - log_attack("[user.name] ([user.ckey]) attacked [M.name] with a bottle. ([M.ckey])") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - //The reagents in the bottle splash all over the target, thanks for the idea Nodrak - if(src.reagents) - for(var/mob/O in viewers(user, null)) - O.show_message(text("The contents of \the [smashtext][src] splashes all over [M]!"), 1) - src.reagents.reaction(M, TOUCH) - - //Finally, smash the bottle. This kills (del) the bottle. - src.smash(M, user) - - return - - else if(!is_open_container()) - to_chat(user, "You can't, \the [src] is closed.")//Added this here and elsewhere to prevent drinking, etc. from closed drink containers. - Hinaichigo + //Molotov and smashing variables + var/molotov = 0 //-1 = can be made into molotov, 0 = can't, 1 = has had rag stuffed into it + var/lit = 0 + var/brightness_lit = 3 + var/bottleheight = 23 //To offset the molotov rag and fire - beer and ale are 23 + var/smashtext = "bottle of " //To handle drinking glasses and the flask of holy water + var/smashname = "broken bottle" //As above + var/viewcontents = 1 + var/flammable = 0 + var/flammin = 0 + var/flammin_color = null - return 0 - - else if(!R.total_volume || !R) +/obj/item/weapon/reagent_containers/food/drinks/on_reagent_change() + if(gulp_size < 5) + gulp_size = 5 + else + gulp_size = max(round(reagents.total_volume / 5), 5) + if(reagents.has_reagent("blackcolor")) + viewcontents = 0 + else + viewcontents = 1 + +/obj/item/weapon/reagent_containers/food/drinks/attack_self(mob/user as mob) + if(!is_open_container()) + to_chat(user, "You can't, \the [src] is closed.")//Added this here and elsewhere to prevent drinking, etc. from closed drink containers. - Hinaichigo + + return 0 + + else if(!src.reagents.total_volume || !src) to_chat(user, "\The [src] is empty.") - return 0 - - else if(M == user) - imbibe(user) - return 0 - - else if(istype(M, /mob/living/carbon/human)) - - user.visible_message("[user] attempts to feed [M] \the [src].", "You attempt to feed [M] \the [src].") - - if(!do_mob(user, M)) - return - - user.visible_message("[user] feeds [M] \the [src].", "You feed [M] \the [src].") - - M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") - user.attack_log += text("\[[time_stamp()]\] Fed [M.name] by [M.name] ([M.ckey]) Reagents: [reagentlist(src)]") - log_attack("[user.name] ([user.ckey]) fed [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - if(reagents.total_volume) - if (ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species.chem_flags & NO_DRINK) - reagents.reaction(get_turf(H), TOUCH) - H.visible_message("The contents in [src] fall through and splash onto the ground, what a mess!") - return 0 - - reagents.reaction(M, INGEST) - spawn(5) - reagents.trans_to(M, gulp_size) - - if(isrobot(user)) //Cyborg modules that include drinks automatically refill themselves, but drain the borg's cell - var/mob/living/silicon/robot/bro = user - bro.cell.use(30) - var/refill = R.get_master_reagent_id() - spawn(600) - R.add_reagent(refill, fillevel) - - playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) - return 1 - return 0 - - -/obj/item/weapon/reagent_containers/food/drinks/afterattack(var/atom/target, var/mob/user, var/adjacency_flag, var/click_params) - if (!adjacency_flag) - return - - // Attempt to transfer to our glass - if (transfer(target, user, can_send = FALSE, can_receive = TRUE)) - return - - // Attempt to transfer from our glass - var/refill_id = reagents.get_master_reagent_id() - var/refill_name = reagents.get_master_reagent_name() - - var/sent_amount = transfer(target, user, can_send = TRUE, can_receive = FALSE) - - // Service borgs regenerate the amount transferred after a while - // TODO Why doesn't the borg module handle this nonsense? - if (sent_amount > 0 && isrobot(user)) - var/mob/living/silicon/robot/borg = user - if (!istype(borg.module, /obj/item/weapon/robot_module/butler) || !borg.cell) - return - - var/charge_amount = max(30, 4*sent_amount) - borg.cell.use(charge_amount) - + return 0 + + else + imbibe(user) + return 0 + +/obj/item/weapon/reagent_containers/food/drinks/attack(mob/living/M as mob, mob/user as mob, def_zone) + var/datum/reagents/R = src.reagents + var/fillevel = gulp_size + + //Smashing on someone + if(user.a_intent == I_HURT && isGlass && molotov != 1) //To smash a bottle on someone, the user must be harm intent, the bottle must be out of glass, and we don't want a rag in here + + if(!M) //This really shouldn't be checked here, but sure + return + + force = 15 //Smashing bottles over someoen's head hurts. //todo: check that this isn't overwriting anything it shouldn't be + + var/datum/organ/external/affecting = user.zone_sel.selecting //Find what the player is aiming at + + var/armor_block = 0 //Get the target's armour values for normal attack damage. + var/armor_duration = 0 //The more force the bottle has, the longer the duration. + + //Calculating duration and calculating damage. + if(ishuman(M)) + + var/mob/living/carbon/human/H = M + var/headarmor = 0 // Target's head armour + armor_block = H.run_armor_check(affecting, "melee") // For normal attack damage + + //If they have a hat/helmet and the user is targeting their head. + if(istype(H.head, /obj/item/clothing/head) && affecting == "head") + + // If their head has an armour value, assign headarmor to it, else give it 0. + if(H.head.armor["melee"]) + headarmor = H.head.armor["melee"] + else + headarmor = 0 + else + headarmor = 0 + + //Calculate the weakening duration for the target. + armor_duration = (duration - headarmor) + force + + else + //Only humans can have armour, right? + armor_block = M.run_armor_check(affecting, "melee") + if(affecting == "head") + armor_duration = duration + force + armor_duration /= 10 + + //Apply the damage! + M.apply_damage(force, BRUTE, affecting, armor_block) + + // You are going to knock someone out for longer if they are not wearing a helmet. + // For drinking glass + if(affecting == "head" && istype(M, /mob/living/carbon/)) + + //Display an attack message. + for(var/mob/O in viewers(user, null)) + if(M != user) O.show_message(text("[M] has been hit over the head with a [smashtext][src.name], by [user]!"), 1) + else O.show_message(text("[M] hit himself with a [smashtext][src.name] on the head!"), 1) + //Weaken the target for the duration that we calculated and divide it by 5. + if(armor_duration) + M.apply_effect(min(armor_duration, 10) , WEAKEN) // Never weaken more than a flash! + + else + //Default attack message and don't weaken the target. + for(var/mob/O in viewers(user, null)) + if(M != user) O.show_message(text("[M] has been attacked with a [smashtext][src.name], by [user]!"), 1) + else O.show_message(text("[M] has attacked himself with a [smashtext][src.name]!"), 1) + + //Attack logs + user.attack_log += text("\[[time_stamp()]\] Has attacked [M.name] ([M.ckey]) with a bottle!") + M.attack_log += text("\[[time_stamp()]\] Has been smashed with a bottle by [user.name] ([user.ckey])") + log_attack("[user.name] ([user.ckey]) attacked [M.name] with a bottle. ([M.ckey])") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + //The reagents in the bottle splash all over the target, thanks for the idea Nodrak + if(src.reagents) + for(var/mob/O in viewers(user, null)) + O.show_message(text("The contents of \the [smashtext][src] splashes all over [M]!"), 1) + src.reagents.reaction(M, TOUCH) + + //Finally, smash the bottle. This kills (del) the bottle. + src.smash(M, user) + + return + + else if(!is_open_container()) + to_chat(user, "You can't, \the [src] is closed.")//Added this here and elsewhere to prevent drinking, etc. from closed drink containers. - Hinaichigo + + return 0 + + else if(!R.total_volume || !R) + to_chat(user, "\The [src] is empty.") + return 0 + + else if(M == user) + imbibe(user) + return 0 + + else if(istype(M, /mob/living/carbon/human)) + + user.visible_message("[user] attempts to feed [M] \the [src].", "You attempt to feed [M] \the [src].") + + if(!do_mob(user, M)) + return + + user.visible_message("[user] feeds [M] \the [src].", "You feed [M] \the [src].") + + M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") + user.attack_log += text("\[[time_stamp()]\] Fed [M.name] by [M.name] ([M.ckey]) Reagents: [reagentlist(src)]") + log_attack("[user.name] ([user.ckey]) fed [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") + + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + if(reagents.total_volume) + if (ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species.chem_flags & NO_DRINK) + reagents.reaction(get_turf(H), TOUCH) + H.visible_message("The contents in [src] fall through and splash onto the ground, what a mess!") + return 0 + + reagents.reaction(M, INGEST) + spawn(5) + reagents.trans_to(M, gulp_size) + + if(isrobot(user)) //Cyborg modules that include drinks automatically refill themselves, but drain the borg's cell + var/mob/living/silicon/robot/bro = user + bro.cell.use(30) + var/refill = R.get_master_reagent_id() + spawn(600) + R.add_reagent(refill, fillevel) + + playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) + return 1 + return 0 + + +/obj/item/weapon/reagent_containers/food/drinks/afterattack(var/atom/target, var/mob/user, var/adjacency_flag, var/click_params) + if (!adjacency_flag) + return + + // Attempt to transfer to our glass + if (transfer(target, user, can_send = FALSE, can_receive = TRUE)) + return + + // Attempt to transfer from our glass + var/refill_id = reagents.get_master_reagent_id() + var/refill_name = reagents.get_master_reagent_name() + + var/sent_amount = transfer(target, user, can_send = TRUE, can_receive = FALSE) + + // Service borgs regenerate the amount transferred after a while + // TODO Why doesn't the borg module handle this nonsense? + if (sent_amount > 0 && isrobot(user)) + var/mob/living/silicon/robot/borg = user + if (!istype(borg.module, /obj/item/weapon/robot_module/butler) || !borg.cell) + return + + var/charge_amount = max(30, 4*sent_amount) + borg.cell.use(charge_amount) + to_chat(user, "Now synthesizing [sent_amount] units of [refill_name]...") - spawn(300) - reagents.add_reagent(refill_id, sent_amount) + spawn(300) + reagents.add_reagent(refill_id, sent_amount) to_chat(user, "Cyborg [src] refilled with [refill_name] ([sent_amount] units).") - -/obj/item/weapon/reagent_containers/food/drinks/examine(mob/user) - - if(viewcontents) - ..() - else + +/obj/item/weapon/reagent_containers/food/drinks/examine(mob/user) + + if(viewcontents) + ..() + else to_chat(user, "\icon[src] That's \a [src].") to_chat(user, desc) to_chat(user, "You can't quite make out its content!") - - if(!reagents || reagents.total_volume == 0) + + if(!reagents || reagents.total_volume == 0) to_chat(user, "\The [src] is empty!") - else if (reagents.total_volume <= src.volume/4) + else if (reagents.total_volume <= src.volume/4) to_chat(user, "\The [src] is almost empty!") - else if (reagents.total_volume <= src.volume*0.66) + else if (reagents.total_volume <= src.volume*0.66) to_chat(user, "\The [src] is about half full, or about half empty!") - else if (reagents.total_volume <= src.volume*0.90) + else if (reagents.total_volume <= src.volume*0.90) to_chat(user, "\The [src] is almost full!") - else + else to_chat(user, "\The [src] is full!") - -/obj/item/weapon/reagent_containers/food/drinks/proc/imbibe(mob/user) //Drink the liquid within - - + +/obj/item/weapon/reagent_containers/food/drinks/proc/imbibe(mob/user) //Drink the liquid within + + to_chat(user, "You swallow a gulp of \the [src].[lit ? " It's hot!" : ""]") - playsound(user.loc,'sound/items/drink.ogg', rand(10,50), 1) - - if(lit) - user.bodytemperature += 30 * TEMPERATURE_DAMAGE_COEFFICIENT//only the first gulp will be hot. - - if(isrobot(user)) - reagents.remove_any(gulp_size) - return 1 - if(reagents.total_volume) - if (ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.species.chem_flags & NO_DRINK) - reagents.reaction(get_turf(H), TOUCH) - H.visible_message("The contents in [src] fall through and splash onto the ground, what a mess!") - return 0 - - reagents.reaction(user, INGEST) - spawn(5) - reagents.trans_to(user, gulp_size) - - update_brightness() - return 1 - -/obj/item/weapon/reagent_containers/food/drinks/New() - ..() - -//////////////////////////////////////////////////////////////////////////////// -/// Drinks. END -//////////////////////////////////////////////////////////////////////////////// - -/obj/item/weapon/reagent_containers/food/drinks/golden_cup - desc = "A golden cup" - name = "golden cup" - icon_state = "golden_cup" - item_state = "" //nope :( - w_class = 4 - force = 14 - throwforce = 10 - amount_per_transfer_from_this = 20 - possible_transfer_amounts = null - volume = 150 - flags = FPRINT | OPENCONTAINER - siemens_coefficient = 1 - -/obj/item/weapon/reagent_containers/food/drinks/golden_cup/tournament_26_06_2011 - desc = "A golden cup. It will be presented to a winner of tournament 26 june and name of the winner will be graved on it." - - -///////////////////////////////////////////////Drinks -//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly -// rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50. -// Formatting is the same as food. - -/obj/item/weapon/reagent_containers/food/drinks/milk - name = "space milk" - desc = "It's milk. White and nutritious goodness!" - icon_state = "milk" - item_state = "carton" - vending_cat = "dairy products" -/obj/item/weapon/reagent_containers/food/drinks/milk/New() - ..() - reagents.add_reagent("milk", 50) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/flour - name = "flour sack" - desc = "A big bag of flour. Good for baking!" - icon = 'icons/obj/food.dmi' - icon_state = "flour" - item_state = "flour" -/obj/item/weapon/reagent_containers/food/drinks/flour/New() - ..() - reagents.add_reagent("flour", 50) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soymilk - name = "soy milk" - desc = "It's soy milk. White and nutritious goodness!" - icon_state = "soymilk" - item_state = "carton" - vending_cat = "dairy products"//it's not a dairy product but oh come on who cares -/obj/item/weapon/reagent_containers/food/drinks/soymilk/New() - ..() - reagents.add_reagent("soymilk", 50) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - - -/obj/item/weapon/reagent_containers/food/drinks/coffee - name = "Robust Coffee" - desc = "Careful, the beverage you're about to enjoy is extremely hot." - icon_state = "coffee" -/obj/item/weapon/reagent_containers/food/drinks/coffee/New() - ..() - reagents.add_reagent("coffee", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/tea - name = "Tea" - icon_state = "tea" - item_state = "coffee" -/obj/item/weapon/reagent_containers/food/drinks/tea/New() - ..() - switch(pick(1,2,3)) - if(1) - name = "Duke Purple Tea" - desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea." - reagents.add_reagent("tea", 30) - if(2) - name = "Century Tea" - desc = "In most cultures, if you leave tea out for months it's considered spoiled. Although this tea is black, we still consider it good for cultural reasons. Taste the century." - reagents.add_reagent("redtea", 30) - if(3) - name = "Hippie Farms Eco-Tea" - desc = "Remember when the station was powered by solar panels instead of raping space for its plasma, then creating an engine of destruction? Hippie Farms remembers, maaaan." - reagents.add_reagent("greentea", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/ice - name = "Ice Cup" - desc = "Careful, cold ice, do not chew." - icon_state = "coffee" -/obj/item/weapon/reagent_containers/food/drinks/ice/New() - ..() - reagents.add_reagent("ice", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/h_chocolate - name = "Dutch Hot Coco" - desc = "Made in Space South America." - icon_state = "tea" - item_state = "coffee" -/obj/item/weapon/reagent_containers/food/drinks/h_chocolate/New() - ..() - reagents.add_reagent("hot_coco", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/dry_ramen - name = "Cup Ramen" - desc = "Just add 10ml water, self heats! A taste that reminds you of your school years." - icon_state = "ramen" -/obj/item/weapon/reagent_containers/food/drinks/dry_ramen/New() - ..() - reagents.add_reagent("dry_ramen", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/groans - name = "Groans Soda" - desc = "Groans Soda: We'll make you groan." - icon_state = "groans" -/obj/item/weapon/reagent_containers/food/drinks/groans/New() - ..() - switch(pick(1,2,3,4,5)) - if(1) - name = "Groans Soda: Cuban Spice Flavor" - desc = "Warning: Long exposure to liquid inside may cause you to follow the rumba beat." - icon_state += "_hot" - reagents.add_reagent("condensedcapsaicin", 10) - reagents.add_reagent("rum", 10) - if(2) - name = "Groans Soda: Icey Cold Flavor" - desc = "Cold in a can. Er, bottle." - icon_state += "_cold" - reagents.add_reagent("frostoil", 10) - reagents.add_reagent("ice", 10) - if(3) - name = "Groans Soda: Zero Calories" - desc = "Zero Point Calories. That's right, we fit even MORE nutriment in this thing." - icon_state += "_nutriment" - reagents.add_reagent("nutriment", 20) - if(4) - name = "Groans Soda: Energy Shot" - desc = "Warning: The Groans Energy Blend(tm), may be toxic to those without constant exposure to chemical waste. Drink responsibly." - icon_state += "_energy" - reagents.add_reagent("sugar", 10) - reagents.add_reagent("chemical_waste", 10) - if(5) - name = "Groans Soda: Double Dan" - desc = "Just when you thought you've had enough Dan, The 'Double Dan' strikes back with this wonderful mixture of too many flavors. Bring a barf bag, Drink responsibly." - icon_state += "_doubledew" - reagents.add_reagent("discount", 20) - reagents.add_reagent("discount", 10) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/filk - name = "Filk" - desc = "Only the best Filk for your crew." - icon_state = "filk" -/obj/item/weapon/reagent_containers/food/drinks/filk/New() - ..() - switch(pick(1,2,3,4,5)) - if(1) - name = "Filk: Chocolate Edition" - reagents.add_reagent("hot_coco", 10) - if(2) - name = "Filk: Scripture Edition" - reagents.add_reagent("holywater", 30) - if(3) - name = "Filk: Carribean Edition" - reagents.add_reagent("rum", 30) - if(4) - name = "Filk: Sugar Blast Editon" - reagents.add_reagent("sugar", 30) - reagents.add_reagent("radium", 10) // le epik fallout may mays - reagents.add_reagent("toxicwaste", 10) - if(5) - name = "Filk: Pure Filk Edition" - reagents.add_reagent("discount", 20) - reagents.add_reagent("discount", 10) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo - name = "Grifeo" - desc = "A quality drink." - icon_state = "griefo" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo/New() - ..() - switch(pick(1,2,3,4,5)) - if(1) - name = "Grifeo: Spicy" - reagents.add_reagent("condensedcapsaicin", 30) - if(2) - name = "Grifeo: Frozen" - reagents.add_reagent("frostoil", 30) - if(3) - name = "Grifeo: Crystallic" - reagents.add_reagent("sugar", 20) - reagents.add_reagent("ice", 20) - reagents.add_reagent("space_drugs", 20) - if(4) - name = "Grifeo: Rich" - reagents.add_reagent("tequila", 10) - reagents.add_reagent("chemical_waste", 10) - if(5) - name = "Grifeo: Pure" - reagents.add_reagent("discount", 20) - reagents.add_reagent("discount", 10) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/groansbanned - name = "Groans: Banned Edition" - desc = "Banned literally everywhere." - icon_state = "groansevil" -/obj/item/weapon/reagent_containers/food/drinks/groansbanned/New() - ..() - switch(pick(1,2,3,4,5)) - if(1) - name = "Groans Banned Soda: Fish Suprise" - reagents.add_reagent("carpotoxin", 10) - if(2) - name = "Groans Banned Soda: Bitter Suprise" - reagents.add_reagent("toxin", 20) - if(3) - name = "Groans Banned Soda: Sour Suprise" - reagents.add_reagent("pacid", 20) - if(4) - name = "Groans Banned Soda: Sleepy Suprise" - reagents.add_reagent("stoxin", 10) - if(5) - name = "Groans Banned Soda: Quadruple Dan" - reagents.add_reagent("discount", 40) - reagents.add_reagent("discount", 10) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink - name = "Mann's Drink" - desc = "The only thing a REAL MAN needs." - icon_state = "mannsdrink" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink/New() - ..() - reagents.add_reagent("discount", 30) - reagents.add_reagent("water", 20) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/groans - name = "Groan-o-matic 9000" - desc = "This is for testing reasons." - icon_state = "toddler" - -/obj/item/weapon/groans/attack_self(mob/user as mob) + playsound(user.loc,'sound/items/drink.ogg', rand(10,50), 1) + + if(lit) + user.bodytemperature += 30 * TEMPERATURE_DAMAGE_COEFFICIENT//only the first gulp will be hot. + + if(isrobot(user)) + reagents.remove_any(gulp_size) + return 1 + if(reagents.total_volume) + if (ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.species.chem_flags & NO_DRINK) + reagents.reaction(get_turf(H), TOUCH) + H.visible_message("The contents in [src] fall through and splash onto the ground, what a mess!") + return 0 + + reagents.reaction(user, INGEST) + spawn(5) + reagents.trans_to(user, gulp_size) + + update_brightness() + return 1 + +/obj/item/weapon/reagent_containers/food/drinks/New() + ..() + +//////////////////////////////////////////////////////////////////////////////// +/// Drinks. END +//////////////////////////////////////////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/drinks/golden_cup + desc = "A golden cup" + name = "golden cup" + icon_state = "golden_cup" + item_state = "" //nope :( + w_class = 4 + force = 14 + throwforce = 10 + amount_per_transfer_from_this = 20 + possible_transfer_amounts = null + volume = 150 + flags = FPRINT | OPENCONTAINER + siemens_coefficient = 1 + +/obj/item/weapon/reagent_containers/food/drinks/golden_cup/tournament_26_06_2011 + desc = "A golden cup. It will be presented to a winner of tournament 26 june and name of the winner will be graved on it." + + +///////////////////////////////////////////////Drinks +//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly +// rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50. +// Formatting is the same as food. + +/obj/item/weapon/reagent_containers/food/drinks/milk + name = "space milk" + desc = "It's milk. White and nutritious goodness!" + icon_state = "milk" + item_state = "carton" + vending_cat = "dairy products" +/obj/item/weapon/reagent_containers/food/drinks/milk/New() + ..() + reagents.add_reagent("milk", 50) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/flour + name = "flour sack" + desc = "A big bag of flour. Good for baking!" + icon = 'icons/obj/food.dmi' + icon_state = "flour" + item_state = "flour" +/obj/item/weapon/reagent_containers/food/drinks/flour/New() + ..() + reagents.add_reagent("flour", 50) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soymilk + name = "soy milk" + desc = "It's soy milk. White and nutritious goodness!" + icon_state = "soymilk" + item_state = "carton" + vending_cat = "dairy products"//it's not a dairy product but oh come on who cares +/obj/item/weapon/reagent_containers/food/drinks/soymilk/New() + ..() + reagents.add_reagent("soymilk", 50) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + + +/obj/item/weapon/reagent_containers/food/drinks/coffee + name = "Robust Coffee" + desc = "Careful, the beverage you're about to enjoy is extremely hot." + icon_state = "coffee" +/obj/item/weapon/reagent_containers/food/drinks/coffee/New() + ..() + reagents.add_reagent("coffee", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/tea + name = "Tea" + icon_state = "tea" + item_state = "coffee" +/obj/item/weapon/reagent_containers/food/drinks/tea/New() + ..() + switch(pick(1,2,3)) + if(1) + name = "Duke Purple Tea" + desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea." + reagents.add_reagent("tea", 30) + if(2) + name = "Century Tea" + desc = "In most cultures, if you leave tea out for months it's considered spoiled. Although this tea is black, we still consider it good for cultural reasons. Taste the century." + reagents.add_reagent("redtea", 30) + if(3) + name = "Hippie Farms Eco-Tea" + desc = "Remember when the station was powered by solar panels instead of raping space for its plasma, then creating an engine of destruction? Hippie Farms remembers, maaaan." + reagents.add_reagent("greentea", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/ice + name = "Ice Cup" + desc = "Careful, cold ice, do not chew." + icon_state = "coffee" +/obj/item/weapon/reagent_containers/food/drinks/ice/New() + ..() + reagents.add_reagent("ice", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/h_chocolate + name = "Dutch Hot Coco" + desc = "Made in Space South America." + icon_state = "tea" + item_state = "coffee" +/obj/item/weapon/reagent_containers/food/drinks/h_chocolate/New() + ..() + reagents.add_reagent("hot_coco", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/dry_ramen + name = "Cup Ramen" + desc = "Just add 10ml water, self heats! A taste that reminds you of your school years." + icon_state = "ramen" +/obj/item/weapon/reagent_containers/food/drinks/dry_ramen/New() + ..() + reagents.add_reagent("dry_ramen", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/groans + name = "Groans Soda" + desc = "Groans Soda: We'll make you groan." + icon_state = "groans" +/obj/item/weapon/reagent_containers/food/drinks/groans/New() + ..() + switch(pick(1,2,3,4,5)) + if(1) + name = "Groans Soda: Cuban Spice Flavor" + desc = "Warning: Long exposure to liquid inside may cause you to follow the rumba beat." + icon_state += "_hot" + reagents.add_reagent("condensedcapsaicin", 10) + reagents.add_reagent("rum", 10) + if(2) + name = "Groans Soda: Icey Cold Flavor" + desc = "Cold in a can. Er, bottle." + icon_state += "_cold" + reagents.add_reagent("frostoil", 10) + reagents.add_reagent("ice", 10) + if(3) + name = "Groans Soda: Zero Calories" + desc = "Zero Point Calories. That's right, we fit even MORE nutriment in this thing." + icon_state += "_nutriment" + reagents.add_reagent("nutriment", 20) + if(4) + name = "Groans Soda: Energy Shot" + desc = "Warning: The Groans Energy Blend(tm), may be toxic to those without constant exposure to chemical waste. Drink responsibly." + icon_state += "_energy" + reagents.add_reagent("sugar", 10) + reagents.add_reagent("chemical_waste", 10) + if(5) + name = "Groans Soda: Double Dan" + desc = "Just when you thought you've had enough Dan, The 'Double Dan' strikes back with this wonderful mixture of too many flavors. Bring a barf bag, Drink responsibly." + icon_state += "_doubledew" + reagents.add_reagent("discount", 20) + reagents.add_reagent("discount", 10) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/filk + name = "Filk" + desc = "Only the best Filk for your crew." + icon_state = "filk" +/obj/item/weapon/reagent_containers/food/drinks/filk/New() + ..() + switch(pick(1,2,3,4,5)) + if(1) + name = "Filk: Chocolate Edition" + reagents.add_reagent("hot_coco", 10) + if(2) + name = "Filk: Scripture Edition" + reagents.add_reagent("holywater", 30) + if(3) + name = "Filk: Carribean Edition" + reagents.add_reagent("rum", 30) + if(4) + name = "Filk: Sugar Blast Editon" + reagents.add_reagent("sugar", 30) + reagents.add_reagent("radium", 10) // le epik fallout may mays + reagents.add_reagent("toxicwaste", 10) + if(5) + name = "Filk: Pure Filk Edition" + reagents.add_reagent("discount", 20) + reagents.add_reagent("discount", 10) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo + name = "Grifeo" + desc = "A quality drink." + icon_state = "griefo" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/grifeo/New() + ..() + switch(pick(1,2,3,4,5)) + if(1) + name = "Grifeo: Spicy" + reagents.add_reagent("condensedcapsaicin", 30) + if(2) + name = "Grifeo: Frozen" + reagents.add_reagent("frostoil", 30) + if(3) + name = "Grifeo: Crystallic" + reagents.add_reagent("sugar", 20) + reagents.add_reagent("ice", 20) + reagents.add_reagent("space_drugs", 20) + if(4) + name = "Grifeo: Rich" + reagents.add_reagent("tequila", 10) + reagents.add_reagent("chemical_waste", 10) + if(5) + name = "Grifeo: Pure" + reagents.add_reagent("discount", 20) + reagents.add_reagent("discount", 10) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/groansbanned + name = "Groans: Banned Edition" + desc = "Banned literally everywhere." + icon_state = "groansevil" +/obj/item/weapon/reagent_containers/food/drinks/groansbanned/New() + ..() + switch(pick(1,2,3,4,5)) + if(1) + name = "Groans Banned Soda: Fish Suprise" + reagents.add_reagent("carpotoxin", 10) + if(2) + name = "Groans Banned Soda: Bitter Suprise" + reagents.add_reagent("toxin", 20) + if(3) + name = "Groans Banned Soda: Sour Suprise" + reagents.add_reagent("pacid", 20) + if(4) + name = "Groans Banned Soda: Sleepy Suprise" + reagents.add_reagent("stoxin", 10) + if(5) + name = "Groans Banned Soda: Quadruple Dan" + reagents.add_reagent("discount", 40) + reagents.add_reagent("discount", 10) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink + name = "Mann's Drink" + desc = "The only thing a REAL MAN needs." + icon_state = "mannsdrink" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/mannsdrink/New() + ..() + reagents.add_reagent("discount", 30) + reagents.add_reagent("water", 20) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/groans + name = "Groan-o-matic 9000" + desc = "This is for testing reasons." + icon_state = "toddler" + +/obj/item/weapon/groans/attack_self(mob/user as mob) to_chat(user, "Now spawning groans.") - var/turf/T = get_turf(user.loc) - var/obj/item/weapon/reagent_containers/food/drinks/groans/A = new /obj/item/weapon/reagent_containers/food/drinks/groans(T) - A.desc += " It also smells like a toddler." //This is required - -/obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot - name = "\improper Discount Dan's Noodle Soup" - desc = "Discount Dan is proud to introduce his own take on noodle soups, with this on the go treat! Simply pull the tab, and a self heating mechanism activates!" - icon_state = "ramen" - var/list/ddname = list("Discount Deng's Quik-Noodles - Sweet and Sour Lo Mein Flavor","Frycook Dan's Quik-Noodles - Curly Fry Ketchup Hoedown Flavor","Rabatt Dan's Snabb-Nudlar - Inkokt Lax Sm?rg?sbord Smak","Discount Deng's Quik-Noodles - Teriyaki TVP Flavor","Sconto Danilo's Quik-Noodles - Italian Strozzapreti Lunare Flavor") -/obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot/New() - ..() - name = pick(ddname) - reagents.add_reagent("hot_ramen", 20) - reagents.add_reagent("discount", 10) - reagents.add_reagent("glowingramen", 8) - reagents.add_reagent("toxicwaste", 8) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/discount_ramen - name = "\improper Discount Dan's Noodle Soup" - desc = "Discount Dan is proud to introduce his own take on noodle soups, with this on the go treat! Simply pull the tab, and a self heating mechanism activates!" - icon_state = "ramen" - var/list/ddname = list("Discount Deng's Quik-Noodles - Sweet and Sour Lo Mein Flavor","Frycook Dan's Quik-Noodles - Curly Fry Ketchup Hoedown Flavor","Rabatt Dan's Snabb-Nudlar - Inkokt Lax Sm?rg?sbord Smak","Discount Deng's Quik-Noodles - Teriyaki TVP Flavor","Sconto Danilo's Quik-Noodles - Italian Strozzapreti Lunare Flavor") -/obj/item/weapon/reagent_containers/food/drinks/discount_ramen/New() - ..() - name = pick(ddname) - reagents.add_reagent("dry_ramen", 20) - reagents.add_reagent("discount", 10) - reagents.add_reagent("toxicwaste", 4) - reagents.add_reagent("greenramen", 4) - reagents.add_reagent("glowingramen", 4) - reagents.add_reagent("deepfriedramen", 4) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/discount_ramen/attack_self(mob/user as mob) + var/turf/T = get_turf(user.loc) + var/obj/item/weapon/reagent_containers/food/drinks/groans/A = new /obj/item/weapon/reagent_containers/food/drinks/groans(T) + A.desc += " It also smells like a toddler." //This is required + +/obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot + name = "\improper Discount Dan's Noodle Soup" + desc = "Discount Dan is proud to introduce his own take on noodle soups, with this on the go treat! Simply pull the tab, and a self heating mechanism activates!" + icon_state = "ramen" + var/list/ddname = list("Discount Deng's Quik-Noodles - Sweet and Sour Lo Mein Flavor","Frycook Dan's Quik-Noodles - Curly Fry Ketchup Hoedown Flavor","Rabatt Dan's Snabb-Nudlar - Inkokt Lax Sm?rg?sbord Smak","Discount Deng's Quik-Noodles - Teriyaki TVP Flavor","Sconto Danilo's Quik-Noodles - Italian Strozzapreti Lunare Flavor") +/obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot/New() + ..() + name = pick(ddname) + reagents.add_reagent("hot_ramen", 20) + reagents.add_reagent("discount", 10) + reagents.add_reagent("glowingramen", 8) + reagents.add_reagent("toxicwaste", 8) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/discount_ramen + name = "\improper Discount Dan's Noodle Soup" + desc = "Discount Dan is proud to introduce his own take on noodle soups, with this on the go treat! Simply pull the tab, and a self heating mechanism activates!" + icon_state = "ramen" + var/list/ddname = list("Discount Deng's Quik-Noodles - Sweet and Sour Lo Mein Flavor","Frycook Dan's Quik-Noodles - Curly Fry Ketchup Hoedown Flavor","Rabatt Dan's Snabb-Nudlar - Inkokt Lax Sm?rg?sbord Smak","Discount Deng's Quik-Noodles - Teriyaki TVP Flavor","Sconto Danilo's Quik-Noodles - Italian Strozzapreti Lunare Flavor") +/obj/item/weapon/reagent_containers/food/drinks/discount_ramen/New() + ..() + name = pick(ddname) + reagents.add_reagent("dry_ramen", 20) + reagents.add_reagent("discount", 10) + reagents.add_reagent("toxicwaste", 4) + reagents.add_reagent("greenramen", 4) + reagents.add_reagent("glowingramen", 4) + reagents.add_reagent("deepfriedramen", 4) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/discount_ramen/attack_self(mob/user as mob) to_chat(user, "You pull the tab, you feel the drink heat up in your hands, and its horrible fumes hits your nose like a ton of bricks. You drop the soup in disgust.") - var/turf/T = get_turf(user.loc) - var/obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot/A = new /obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot(T) - A.desc += " It feels warm.." //This is required - user.drop_from_inventory(src) - qdel(src) - - - -/obj/item/weapon/reagent_containers/food/drinks/beer - name = "Space Beer" - desc = "Beer. In space." - icon_state = "beer" - vending_cat = "fermented" - molotov = -1 //can become a molotov - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/beer/New() - ..() - reagents.add_reagent("beer", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/ale - name = "Magm-Ale" - desc = "A true dorf's drink of choice." - icon_state = "alebottle" - item_state = "beer" - vending_cat = "fermented" - molotov = -1 //can become a molotov - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/ale/New() - ..() - reagents.add_reagent("ale", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans - vending_cat = "carbonated drinks" - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola - name = "Space Cola" - desc = "Cola. in space." - icon_state = "cola" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola/New() - ..() - reagents.add_reagent("cola", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic - name = "T-Borg's Tonic Water" - desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away." - icon_state = "tonic" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic/New() - ..() - reagents.add_reagent("tonic", 50) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater - name = "Soda Water" - desc = "A can of soda water. Why not make a scotch and soda?" - icon_state = "sodawater" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater/New() - ..() - reagents.add_reagent("sodawater", 50) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime - name = "Lemon-Lime" - desc = "You wanted ORANGE. It gave you Lemon Lime." - icon_state = "lemon-lime" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime/New() - ..() - reagents.add_reagent("lemon_lime", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up - name = "Space-Up" - desc = "Tastes like a hull breach in your mouth." - icon_state = "space-up" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up/New() - ..() - reagents.add_reagent("space_up", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist - name = "Star-kist" - desc = "The taste of a star in liquid form. And, a bit of tuna...?" - icon_state = "starkist" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist/New() - ..() - reagents.add_reagent("cola", 15) - reagents.add_reagent("orangejuice", 15) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind - name = "Space Mountain Wind" - desc = "Blows right through you like a space wind." - icon_state = "space_mountain_wind" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind/New() - ..() - reagents.add_reagent("spacemountainwind", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko - name = "Thirteen Loko" - desc = "The CMO has advised crew members that consumption of Thirteen Loko may result in seizures, blindness, drunkeness, or even death. Please Drink Responsably." - icon_state = "thirteen_loko" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko/New() - ..() - reagents.add_reagent("thirteenloko", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb - name = "Dr. Gibb" - desc = "A delicious mixture of 42 different flavors." - icon_state = "dr_gibb" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb/New() - ..() - reagents.add_reagent("dr_gibb", 30) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka - name = "Nuka Cola" - desc = "Cool, refreshing, Nuka Cola." - icon_state = "nuka" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka/New() - ..() - reagents.add_reagent("nuka_cola", 30) - src.pixel_x = rand(-10, 10) - src.pixel_y = rand(-10, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum - name = "Nuka Cola Quantum" - desc = "Take the leap... enjoy a Quantum!" - icon_state = "quantum" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum/New() - ..() - reagents.add_reagent("quantum", 30) - src.pixel_x = rand(-10, 10) - src.pixel_y = rand(-10, 10) - -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink - name = "Brawndo" - icon_state = "brawndo" - desc = "It has what plants crave! Electrolytes!" -/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink/New() - ..() - reagents.add_reagent("sportdrink", 30) - src.pixel_x = rand(-10, 10) - src.pixel_y = rand(-10, 10) - -/obj/item/weapon/reagent_containers/food/drinks/coloring - name = "Vial of Food Coloring" - icon = 'icons/obj/chemical.dmi' - icon_state = "vial" - volume = 25 - possible_transfer_amounts = list(1,5) -/obj/item/weapon/reagent_containers/food/drinks/coloring/New() - ..() - reagents.add_reagent("blackcolor", 25) - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) - -/obj/item/weapon/reagent_containers/food/drinks/sillycup - name = "Paper Cup" - desc = "A paper water cup." - icon_state = "water_cup_e" - possible_transfer_amounts = null - volume = 10 -/obj/item/weapon/reagent_containers/food/drinks/sillycup/New() - ..() - src.pixel_x = rand(-10.0, 10) - src.pixel_y = rand(-10.0, 10) -/obj/item/weapon/reagent_containers/food/drinks/sillycup/on_reagent_change() - if(reagents.total_volume) - icon_state = "water_cup" - else - icon_state = "water_cup_e" -//////////////////////////drinkingglass and shaker// -//Note by Darem: This code handles the mixing of drinks. New drinks go in three places: In Chemistry-Reagents.dm (for the drink -// itself), in Chemistry-Recipes.dm (for the reaction that changes the components into the drink), and here (for the drinking glass -// icon states. - -/obj/item/weapon/reagent_containers/food/drinks/shaker - name = "Shaker" - desc = "A metal shaker to mix drinks in." - icon_state = "shaker" - origin_tech = "materials=1" - amount_per_transfer_from_this = 10 - volume = 100 - -/obj/item/weapon/reagent_containers/food/drinks/flask - name = "Captain's Flask" - desc = "A metal flask belonging to the captain." - icon_state = "flask" - origin_tech = "materials=1" - volume = 60 - -/obj/item/weapon/reagent_containers/food/drinks/flask/detflask - name = "Detective's Flask" - desc = "A metal flask with a leather band and golden badge belonging to the detective." - icon_state = "detflask" - volume = 60 - -/obj/item/weapon/reagent_containers/food/drinks/flask/barflask - name = "flask" - desc = "For those who can't be bothered to hang out at the bar to drink." - icon_state = "barflask" - volume = 60 - -/obj/item/weapon/reagent_containers/food/drinks/britcup - name = "cup" - desc = "A cup with the British flag emblazoned on it." - icon_state = "britcup" - volume = 30 - -/obj/item/weapon/reagent_containers/food/drinks/americup - name = "cup" - desc = "A cup with the American flag emblazoned on it." - icon_state = "americup" - volume = 30 - -///////////////////////////////////////////////Alchohol bottles! -Agouri ////////////////////////// -//Functionally identical to regular drinks. The only difference is that the default bottle size is 100. - Darem -//Bottles now weaken and break when smashed on people's heads. - Giacom - - -/obj/item/weapon/reagent_containers/food/drinks/bottle - amount_per_transfer_from_this = 10 - volume = 100 - starting_materials = list(MAT_GLASS = 500) - bottleheight = 31 - melt_temperature = MELTPOINT_GLASS - w_type=RECYK_GLASS - -//Keeping this here for now, I'll ask if I should keep it here. -/obj/item/weapon/broken_bottle - - name = "broken bottle" // changed to lowercase - Hinaichigo - desc = "A bottle with a sharp broken bottom." - icon = 'icons/obj/drinks.dmi' - icon_state = "broken_bottle" - force = 9.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - sharpness = 0.8 //same as glass shards - w_class = 1 - item_state = "beer" - attack_verb = list("stabbed", "slashed", "attacked") - var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken") - starting_materials = list(MAT_GLASS = 500) - melt_temperature = MELTPOINT_GLASS - w_type=RECYK_GLASS - -/obj/item/weapon/broken_bottle/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - - -/obj/item/weapon/reagent_containers/food/drinks/bottle/gin - name = "Griffeater Gin" - desc = "A bottle of high quality gin, produced in the New London Space Station." - icon_state = "ginbottle" - vending_cat = "spirits" - bottleheight = 30 - isGlass = 1 - molotov = -1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/gin/New() - ..() - reagents.add_reagent("gin", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey - name = "Uncle Git's Special Reserve" - desc = "A premium single-malt whiskey, gently matured inside the tunnels of a nuclear shelter. TUNNEL WHISKEY RULES." - icon_state = "whiskeybottle" - vending_cat = "spirits" - isGlass = 1 - molotov = -1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey/New() - ..() - reagents.add_reagent("whiskey", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka - name = "Tunguska Triple Distilled" - desc = "Aah, vodka. Prime choice of drink AND fuel by Russians worldwide." - icon_state = "vodkabottle" - vending_cat = "spirits" - isGlass = 1 - molotov = -1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka/New() - ..() - reagents.add_reagent("vodka", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/tequila - name = "Caccavo Guaranteed Quality Tequila" - desc = "Made from premium petroleum distillates, pure thalidomide and other fine quality ingredients!" - icon_state = "tequilabottle" - vending_cat = "spirits" - isGlass = 1 - molotov = -1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/tequila/New() - ..() - reagents.add_reagent("tequila", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing - name = "Bottle of Nothing" - desc = "A bottle filled with nothing" - icon_state = "bottleofnothing" - isGlass = 1 - molotov = -1 - smashtext = "" -/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing/New() - ..() - reagents.add_reagent("nothing", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/patron - name = "Wrapp Artiste Patron" - desc = "Silver laced tequila, served in space night clubs across the galaxy." - icon_state = "patronbottle" - bottleheight = 26 //has a cork but for now it goes on top of the cork - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/patron/New() - ..() - reagents.add_reagent("patron", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/rum - name = "Captain Pete's Cuban Spiced Rum" - desc = "This isn't just rum, oh no. It's practically GRIFF in a bottle." - icon_state = "rumbottle" - vending_cat = "spirits" - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/rum/New() - ..() - reagents.add_reagent("rum", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth - name = "Goldeneye Vermouth" - desc = "Sweet, sweet dryness~" - icon_state = "vermouthbottle" - vending_cat = "fermented" - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth/New() - ..() - reagents.add_reagent("vermouth", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua - name = "Robert Robust's Coffee Liqueur" - desc = "A widely known, Mexican coffee-flavoured liqueur. In production since 1936, HONK" - icon_state = "kahluabottle" - vending_cat = "fermented" - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua/New() - ..() - reagents.add_reagent("kahlua", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager - name = "College Girl Goldschlager" - desc = "Because they are the only ones who will drink 100 proof cinnamon schnapps." - icon_state = "goldschlagerbottle" - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager/New() - ..() - reagents.add_reagent("goldschlager", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/cognac - name = "Chateau De Baton Premium Cognac" - desc = "A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. You might as well not scream 'SHITCURITY' this time." - icon_state = "cognacbottle" - vending_cat = "spirits" - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/cognac/New() - ..() - reagents.add_reagent("cognac", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/wine - name = "Doublebeard Bearded Special Wine" - desc = "A faint aura of unease and asspainery surrounds the bottle." - icon_state = "winebottle" - vending_cat = "fermented" - bottleheight = 30 - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/wine/New() - ..() - reagents.add_reagent("wine", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe - name = "Jailbreaker Verte" - desc = "One sip of this and you just know you're gonna have a good time." - icon_state = "absinthebottle" - bottleheight = 27 - molotov = -1 - isGlass = 1 -/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe/New() - ..() - reagents.add_reagent("absinthe", 100) - -//////////////////////////JUICES AND STUFF /////////////////////// - -/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice - name = "Orange Juice" - desc = "Full of vitamins and deliciousness!" - icon_state = "orangejuice" - item_state = "carton" - vending_cat = "fruit juices" - starting_materials = null - -/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice/New() - ..() - reagents.add_reagent("orangejuice", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/cream - name = "Milk Cream" - desc = "It's cream. Made from milk. What else did you think you'd find in there?" - icon_state = "cream" - item_state = "carton" - vending_cat = "dairy products" - starting_materials = null - -/obj/item/weapon/reagent_containers/food/drinks/bottle/cream/New() - ..() - reagents.add_reagent("cream", 100) - -/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice - name = "Tomato Juice" - desc = "Well, at least it LOOKS like tomato juice. You can't tell with all that redness." - icon_state = "tomatojuice" - item_state = "carton" - vending_cat = "fruit juices" - starting_materials = null - -/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice/New() - ..() - reagents.add_reagent("tomatojuice", 100) - - -/obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice - name = "Lime Juice" - desc = "Sweet-sour goodness." - icon_state = "limejuice" - item_state = "carton" - vending_cat = "fruit juices" - starting_materials = null - -/obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice/New() - ..() - reagents.add_reagent("limejuice", 100) - - - - - -/obj/item/weapon/reagent_containers/food/drinks/proc/smash(mob/living/M as mob, mob/living/user as mob) - - - if(molotov == 1) //for molotovs - if(lit) - new /obj/effect/decal/cleanable/ash(get_turf(src)) - else - new /obj/item/weapon/reagent_containers/glass/rag(get_turf(src)) - - //Creates a shattering noise and replaces the bottle with a broken_bottle - user.drop_item(force_drop = 1) - var/obj/item/weapon/broken_bottle/B = new /obj/item/weapon/broken_bottle(user.loc) - B.icon_state = src.icon_state - B.force = src.force - B.name = src.smashname - - if(istype(src, /obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) //for drinking glasses - B.icon_state = "glass_empty" - - if(prob(33)) - getFromPool(/obj/item/weapon/shard, get_turf(M)) // Create a glass shard at the target's location! - - var/icon/I = new('icons/obj/drinks.dmi', B.icon_state) - I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) - I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) - B.icon = I - - user.put_in_active_hand(B) - src.transfer_fingerprints_to(B) - playsound(src, "shatter", 70, 1) - - qdel(src) - -//smashing when thrown -/obj/item/weapon/reagent_containers/food/drinks/throw_impact(atom/hit_atom) - ..() - if(isGlass) - isGlass = 0 //to avoid it from hitting the wall, then hitting the floor, which would cause two broken bottles to appear - src.visible_message("The [smashtext][src.name] shatters!","You hear a shatter!") - playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - if(reagents.total_volume) - src.reagents.reaction(hit_atom, TOUCH) //maybe this could be improved? - spawn(5) src.reagents.clear_reagents() //maybe this could be improved? - invisibility = INVISIBILITY_MAXIMUM //so it stays a while to ignite any fuel - - if(molotov == 1) //for molotovs - if(lit) - new /obj/effect/decal/cleanable/ash(get_turf(src)) - var/turf/loca = get_turf(src) - if(loca) + var/turf/T = get_turf(user.loc) + var/obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot/A = new /obj/item/weapon/reagent_containers/food/drinks/discount_ramen_hot(T) + A.desc += " It feels warm.." //This is required + user.drop_from_inventory(src) + qdel(src) + + + +/obj/item/weapon/reagent_containers/food/drinks/beer + name = "Space Beer" + desc = "Beer. In space." + icon_state = "beer" + vending_cat = "fermented" + molotov = -1 //can become a molotov + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/beer/New() + ..() + reagents.add_reagent("beer", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/ale + name = "Magm-Ale" + desc = "A true dorf's drink of choice." + icon_state = "alebottle" + item_state = "beer" + vending_cat = "fermented" + molotov = -1 //can become a molotov + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/ale/New() + ..() + reagents.add_reagent("ale", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans + vending_cat = "carbonated drinks" + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola + name = "Space Cola" + desc = "Cola. in space." + icon_state = "cola" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola/New() + ..() + reagents.add_reagent("cola", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic + name = "T-Borg's Tonic Water" + desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away." + icon_state = "tonic" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/tonic/New() + ..() + reagents.add_reagent("tonic", 50) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater + name = "Soda Water" + desc = "A can of soda water. Why not make a scotch and soda?" + icon_state = "sodawater" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sodawater/New() + ..() + reagents.add_reagent("sodawater", 50) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime + name = "Lemon-Lime" + desc = "You wanted ORANGE. It gave you Lemon Lime." + icon_state = "lemon-lime" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime/New() + ..() + reagents.add_reagent("lemon_lime", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up + name = "Space-Up" + desc = "Tastes like a hull breach in your mouth." + icon_state = "space-up" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up/New() + ..() + reagents.add_reagent("space_up", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist + name = "Star-kist" + desc = "The taste of a star in liquid form. And, a bit of tuna...?" + icon_state = "starkist" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist/New() + ..() + reagents.add_reagent("cola", 15) + reagents.add_reagent("orangejuice", 15) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind + name = "Space Mountain Wind" + desc = "Blows right through you like a space wind." + icon_state = "space_mountain_wind" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind/New() + ..() + reagents.add_reagent("spacemountainwind", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko + name = "Thirteen Loko" + desc = "The CMO has advised crew members that consumption of Thirteen Loko may result in seizures, blindness, drunkeness, or even death. Please Drink Responsably." + icon_state = "thirteen_loko" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko/New() + ..() + reagents.add_reagent("thirteenloko", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb + name = "Dr. Gibb" + desc = "A delicious mixture of 42 different flavors." + icon_state = "dr_gibb" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb/New() + ..() + reagents.add_reagent("dr_gibb", 30) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka + name = "Nuka Cola" + desc = "Cool, refreshing, Nuka Cola." + icon_state = "nuka" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/nuka/New() + ..() + reagents.add_reagent("nuka_cola", 30) + src.pixel_x = rand(-10, 10) + src.pixel_y = rand(-10, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum + name = "Nuka Cola Quantum" + desc = "Take the leap... enjoy a Quantum!" + icon_state = "quantum" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum/New() + ..() + reagents.add_reagent("quantum", 30) + src.pixel_x = rand(-10, 10) + src.pixel_y = rand(-10, 10) + +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink + name = "Brawndo" + icon_state = "brawndo" + desc = "It has what plants crave! Electrolytes!" +/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink/New() + ..() + reagents.add_reagent("sportdrink", 30) + src.pixel_x = rand(-10, 10) + src.pixel_y = rand(-10, 10) + +/obj/item/weapon/reagent_containers/food/drinks/coloring + name = "Vial of Food Coloring" + icon = 'icons/obj/chemical.dmi' + icon_state = "vial" + volume = 25 + possible_transfer_amounts = list(1,5) +/obj/item/weapon/reagent_containers/food/drinks/coloring/New() + ..() + reagents.add_reagent("blackcolor", 25) + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) + +/obj/item/weapon/reagent_containers/food/drinks/sillycup + name = "Paper Cup" + desc = "A paper water cup." + icon_state = "water_cup_e" + possible_transfer_amounts = null + volume = 10 +/obj/item/weapon/reagent_containers/food/drinks/sillycup/New() + ..() + src.pixel_x = rand(-10.0, 10) + src.pixel_y = rand(-10.0, 10) +/obj/item/weapon/reagent_containers/food/drinks/sillycup/on_reagent_change() + if(reagents.total_volume) + icon_state = "water_cup" + else + icon_state = "water_cup_e" +//////////////////////////drinkingglass and shaker// +//Note by Darem: This code handles the mixing of drinks. New drinks go in three places: In Chemistry-Reagents.dm (for the drink +// itself), in Chemistry-Recipes.dm (for the reaction that changes the components into the drink), and here (for the drinking glass +// icon states. + +/obj/item/weapon/reagent_containers/food/drinks/shaker + name = "Shaker" + desc = "A metal shaker to mix drinks in." + icon_state = "shaker" + origin_tech = "materials=1" + amount_per_transfer_from_this = 10 + volume = 100 + +/obj/item/weapon/reagent_containers/food/drinks/flask + name = "Captain's Flask" + desc = "A metal flask belonging to the captain." + icon_state = "flask" + origin_tech = "materials=1" + volume = 60 + +/obj/item/weapon/reagent_containers/food/drinks/flask/detflask + name = "Detective's Flask" + desc = "A metal flask with a leather band and golden badge belonging to the detective." + icon_state = "detflask" + volume = 60 + +/obj/item/weapon/reagent_containers/food/drinks/flask/barflask + name = "flask" + desc = "For those who can't be bothered to hang out at the bar to drink." + icon_state = "barflask" + volume = 60 + +/obj/item/weapon/reagent_containers/food/drinks/britcup + name = "cup" + desc = "A cup with the British flag emblazoned on it." + icon_state = "britcup" + volume = 30 + +/obj/item/weapon/reagent_containers/food/drinks/americup + name = "cup" + desc = "A cup with the American flag emblazoned on it." + icon_state = "americup" + volume = 30 + +///////////////////////////////////////////////Alchohol bottles! -Agouri ////////////////////////// +//Functionally identical to regular drinks. The only difference is that the default bottle size is 100. - Darem +//Bottles now weaken and break when smashed on people's heads. - Giacom + + +/obj/item/weapon/reagent_containers/food/drinks/bottle + amount_per_transfer_from_this = 10 + volume = 100 + starting_materials = list(MAT_GLASS = 500) + bottleheight = 31 + melt_temperature = MELTPOINT_GLASS + w_type=RECYK_GLASS + +//Keeping this here for now, I'll ask if I should keep it here. +/obj/item/weapon/broken_bottle + + name = "broken bottle" // changed to lowercase - Hinaichigo + desc = "A bottle with a sharp broken bottom." + icon = 'icons/obj/drinks.dmi' + icon_state = "broken_bottle" + force = 9.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + sharpness = 0.8 //same as glass shards + w_class = 1 + item_state = "beer" + attack_verb = list("stabbed", "slashed", "attacked") + var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken") + starting_materials = list(MAT_GLASS = 500) + melt_temperature = MELTPOINT_GLASS + w_type=RECYK_GLASS + +/obj/item/weapon/broken_bottle/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + + +/obj/item/weapon/reagent_containers/food/drinks/bottle/gin + name = "Griffeater Gin" + desc = "A bottle of high quality gin, produced in the New London Space Station." + icon_state = "ginbottle" + vending_cat = "spirits" + bottleheight = 30 + isGlass = 1 + molotov = -1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/gin/New() + ..() + reagents.add_reagent("gin", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey + name = "Uncle Git's Special Reserve" + desc = "A premium single-malt whiskey, gently matured inside the tunnels of a nuclear shelter. TUNNEL WHISKEY RULES." + icon_state = "whiskeybottle" + vending_cat = "spirits" + isGlass = 1 + molotov = -1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey/New() + ..() + reagents.add_reagent("whiskey", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka + name = "Tunguska Triple Distilled" + desc = "Aah, vodka. Prime choice of drink AND fuel by Russians worldwide." + icon_state = "vodkabottle" + vending_cat = "spirits" + isGlass = 1 + molotov = -1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka/New() + ..() + reagents.add_reagent("vodka", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/tequila + name = "Caccavo Guaranteed Quality Tequila" + desc = "Made from premium petroleum distillates, pure thalidomide and other fine quality ingredients!" + icon_state = "tequilabottle" + vending_cat = "spirits" + isGlass = 1 + molotov = -1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/tequila/New() + ..() + reagents.add_reagent("tequila", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing + name = "Bottle of Nothing" + desc = "A bottle filled with nothing" + icon_state = "bottleofnothing" + isGlass = 1 + molotov = -1 + smashtext = "" +/obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing/New() + ..() + reagents.add_reagent("nothing", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/patron + name = "Wrapp Artiste Patron" + desc = "Silver laced tequila, served in space night clubs across the galaxy." + icon_state = "patronbottle" + bottleheight = 26 //has a cork but for now it goes on top of the cork + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/patron/New() + ..() + reagents.add_reagent("patron", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/rum + name = "Captain Pete's Cuban Spiced Rum" + desc = "This isn't just rum, oh no. It's practically GRIFF in a bottle." + icon_state = "rumbottle" + vending_cat = "spirits" + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/rum/New() + ..() + reagents.add_reagent("rum", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth + name = "Goldeneye Vermouth" + desc = "Sweet, sweet dryness~" + icon_state = "vermouthbottle" + vending_cat = "fermented" + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth/New() + ..() + reagents.add_reagent("vermouth", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua + name = "Robert Robust's Coffee Liqueur" + desc = "A widely known, Mexican coffee-flavoured liqueur. In production since 1936, HONK" + icon_state = "kahluabottle" + vending_cat = "fermented" + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua/New() + ..() + reagents.add_reagent("kahlua", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager + name = "College Girl Goldschlager" + desc = "Because they are the only ones who will drink 100 proof cinnamon schnapps." + icon_state = "goldschlagerbottle" + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager/New() + ..() + reagents.add_reagent("goldschlager", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/cognac + name = "Chateau De Baton Premium Cognac" + desc = "A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. You might as well not scream 'SHITCURITY' this time." + icon_state = "cognacbottle" + vending_cat = "spirits" + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/cognac/New() + ..() + reagents.add_reagent("cognac", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/wine + name = "Doublebeard Bearded Special Wine" + desc = "A faint aura of unease and asspainery surrounds the bottle." + icon_state = "winebottle" + vending_cat = "fermented" + bottleheight = 30 + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/wine/New() + ..() + reagents.add_reagent("wine", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe + name = "Jailbreaker Verte" + desc = "One sip of this and you just know you're gonna have a good time." + icon_state = "absinthebottle" + bottleheight = 27 + molotov = -1 + isGlass = 1 +/obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe/New() + ..() + reagents.add_reagent("absinthe", 100) + +//////////////////////////JUICES AND STUFF /////////////////////// + +/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice + name = "Orange Juice" + desc = "Full of vitamins and deliciousness!" + icon_state = "orangejuice" + item_state = "carton" + vending_cat = "fruit juices" + starting_materials = null + +/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice/New() + ..() + reagents.add_reagent("orangejuice", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/cream + name = "Milk Cream" + desc = "It's cream. Made from milk. What else did you think you'd find in there?" + icon_state = "cream" + item_state = "carton" + vending_cat = "dairy products" + starting_materials = null + +/obj/item/weapon/reagent_containers/food/drinks/bottle/cream/New() + ..() + reagents.add_reagent("cream", 100) + +/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice + name = "Tomato Juice" + desc = "Well, at least it LOOKS like tomato juice. You can't tell with all that redness." + icon_state = "tomatojuice" + item_state = "carton" + vending_cat = "fruit juices" + starting_materials = null + +/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice/New() + ..() + reagents.add_reagent("tomatojuice", 100) + + +/obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice + name = "Lime Juice" + desc = "Sweet-sour goodness." + icon_state = "limejuice" + item_state = "carton" + vending_cat = "fruit juices" + starting_materials = null + +/obj/item/weapon/reagent_containers/food/drinks/bottle/limejuice/New() + ..() + reagents.add_reagent("limejuice", 100) + + + + + +/obj/item/weapon/reagent_containers/food/drinks/proc/smash(mob/living/M as mob, mob/living/user as mob) + + + if(molotov == 1) //for molotovs + if(lit) + new /obj/effect/decal/cleanable/ash(get_turf(src)) + else + new /obj/item/weapon/reagent_containers/glass/rag(get_turf(src)) + + //Creates a shattering noise and replaces the bottle with a broken_bottle + user.drop_item(force_drop = 1) + var/obj/item/weapon/broken_bottle/B = new /obj/item/weapon/broken_bottle(user.loc) + B.icon_state = src.icon_state + B.force = src.force + B.name = src.smashname + + if(istype(src, /obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) //for drinking glasses + B.icon_state = "glass_empty" + + if(prob(33)) + getFromPool(/obj/item/weapon/shard, get_turf(M)) // Create a glass shard at the target's location! + + var/icon/I = new('icons/obj/drinks.dmi', B.icon_state) + I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) + I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) + B.icon = I + + user.put_in_active_hand(B) + src.transfer_fingerprints_to(B) + playsound(src, "shatter", 70, 1) + + qdel(src) + +//smashing when thrown +/obj/item/weapon/reagent_containers/food/drinks/throw_impact(atom/hit_atom) + ..() + if(isGlass) + isGlass = 0 //to avoid it from hitting the wall, then hitting the floor, which would cause two broken bottles to appear + src.visible_message("The [smashtext][src.name] shatters!","You hear a shatter!") + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + if(reagents.total_volume) + src.reagents.reaction(hit_atom, TOUCH) //maybe this could be improved? + spawn(5) src.reagents.clear_reagents() //maybe this could be improved? + invisibility = INVISIBILITY_MAXIMUM //so it stays a while to ignite any fuel + + if(molotov == 1) //for molotovs + if(lit) + new /obj/effect/decal/cleanable/ash(get_turf(src)) + var/turf/loca = get_turf(src) + if(loca) // to_chat(world, "Burning...") - loca.hotspot_expose(700, 1000,surfaces=istype(loc,/turf)) - else - new /obj/item/weapon/reagent_containers/glass/rag(get_turf(src)) - - - //create new broken bottle - var/obj/item/weapon/broken_bottle/B = new /obj/item/weapon/broken_bottle(loc) - B.force = src.force - B.name = src.smashname - B.icon_state = src.icon_state - - if(istype(src, /obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) //for drinking glasses - B.icon_state = "glass_empty" - - if(prob(33)) - getFromPool(/obj/item/weapon/shard, get_turf(src)) // Create a glass shard at the hit location! - - var/icon/Q = new('icons/obj/drinks.dmi', B.icon_state) - Q.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) - Q.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) - B.icon = Q - src.transfer_fingerprints_to(B) - - - spawn(50) - qdel(src) - - - -////////////////////// -// molotov cocktail // -// by Hinaichigo // -////////////////////// - -/obj/item/weapon/reagent_containers/food/drinks/attackby(var/obj/item/I, mob/user as mob) - if(istype(I, /obj/item/weapon/reagent_containers/glass/rag) && molotov == -1) //check if it is a molotovable drink - just beer and ale for now - other bottles require different rag overlay positions - if you can figure this out then go for it + loca.hotspot_expose(700, 1000,surfaces=istype(loc,/turf)) + else + new /obj/item/weapon/reagent_containers/glass/rag(get_turf(src)) + + + //create new broken bottle + var/obj/item/weapon/broken_bottle/B = new /obj/item/weapon/broken_bottle(loc) + B.force = src.force + B.name = src.smashname + B.icon_state = src.icon_state + + if(istype(src, /obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) //for drinking glasses + B.icon_state = "glass_empty" + + if(prob(33)) + getFromPool(/obj/item/weapon/shard, get_turf(src)) // Create a glass shard at the hit location! + + var/icon/Q = new('icons/obj/drinks.dmi', B.icon_state) + Q.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) + Q.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) + B.icon = Q + src.transfer_fingerprints_to(B) + + + spawn(50) + qdel(src) + + + +////////////////////// +// molotov cocktail // +// by Hinaichigo // +////////////////////// + +/obj/item/weapon/reagent_containers/food/drinks/attackby(var/obj/item/I, mob/user as mob) + if(istype(I, /obj/item/weapon/reagent_containers/glass/rag) && molotov == -1) //check if it is a molotovable drink - just beer and ale for now - other bottles require different rag overlay positions - if you can figure this out then go for it to_chat(user, "You stuff the [I] into the mouth of the [src].") - qdel(I) - I = null - molotov = 1 - flags ^= OPENCONTAINER - name = "incendiary cocktail" - smashtext = "" - desc = "A rag stuffed into a bottle." - update_icon() - slot_flags = SLOT_BELT - else if(I.is_hot()) - light(user,I) - update_brightness(user) - else if(istype(I, /obj/item/device/assembly/igniter)) - var/obj/item/device/assembly/igniter/C = I - C.activate() - light(user,I) - update_brightness(user) - return - -/obj/item/weapon/reagent_containers/food/drinks/proc/light(mob/user,obj/item/I) - var/flavor_text = "[user] lights \the [name] with \the [I]." - if(!lit && molotov == 1) - lit = 1 - visible_message(flavor_text) - processing_objects.Add(src) - update_icon() - if(!lit && flammable) - lit = 1 - visible_message(flavor_text) - flammable = 0 - name = "Flaming [name]" - desc += " Damn that looks hot!" - icon_state += "-flamin" - update_icon() - -/obj/item/weapon/reagent_containers/food/drinks/proc/update_brightness(var/mob/user = null) - if(lit) - set_light(src.brightness_lit) - else - set_light(0) - -/obj/item/weapon/reagent_containers/food/drinks/update_icon() - src.overlays.len = 0 - var/image/Im - if(molotov == 1) - Im = image('icons/obj/grenade.dmi', icon_state = "molotov_rag") - Im.pixel_y += src.bottleheight-23 //since the molotov rag and fire are placed one pixel above the mouth of the bottle, and start out at a height of 23 (for beer and ale) - overlays += Im - if(molotov == 1 && lit) - Im = image('icons/obj/grenade.dmi', icon_state = "molotov_fire") - Im.pixel_y += src.bottleheight-23 - overlays += Im - else - item_state = initial(item_state) - if(ishuman(src.loc)) - var/mob/living/carbon/human/H = src.loc - H.update_inv_belt() - - return - - -/obj/item/weapon/reagent_containers/food/drinks/process() - var/turf/loca = get_turf(src) - if(lit && loca) + qdel(I) + I = null + molotov = 1 + flags ^= OPENCONTAINER + name = "incendiary cocktail" + smashtext = "" + desc = "A rag stuffed into a bottle." + update_icon() + slot_flags = SLOT_BELT + else if(I.is_hot()) + light(user,I) + update_brightness(user) + else if(istype(I, /obj/item/device/assembly/igniter)) + var/obj/item/device/assembly/igniter/C = I + C.activate() + light(user,I) + update_brightness(user) + return + +/obj/item/weapon/reagent_containers/food/drinks/proc/light(mob/user,obj/item/I) + var/flavor_text = "[user] lights \the [name] with \the [I]." + if(!lit && molotov == 1) + lit = 1 + visible_message(flavor_text) + processing_objects.Add(src) + update_icon() + if(!lit && flammable) + lit = 1 + visible_message(flavor_text) + flammable = 0 + name = "Flaming [name]" + desc += " Damn that looks hot!" + icon_state += "-flamin" + update_icon() + +/obj/item/weapon/reagent_containers/food/drinks/proc/update_brightness(var/mob/user = null) + if(lit) + set_light(src.brightness_lit) + else + set_light(0) + +/obj/item/weapon/reagent_containers/food/drinks/update_icon() + src.overlays.len = 0 + var/image/Im + if(molotov == 1) + Im = image('icons/obj/grenade.dmi', icon_state = "molotov_rag") + Im.pixel_y += src.bottleheight-23 //since the molotov rag and fire are placed one pixel above the mouth of the bottle, and start out at a height of 23 (for beer and ale) + overlays += Im + if(molotov == 1 && lit) + Im = image('icons/obj/grenade.dmi', icon_state = "molotov_fire") + Im.pixel_y += src.bottleheight-23 + overlays += Im + else + item_state = initial(item_state) + if(ishuman(src.loc)) + var/mob/living/carbon/human/H = src.loc + H.update_inv_belt() + + return + + +/obj/item/weapon/reagent_containers/food/drinks/process() + var/turf/loca = get_turf(src) + if(lit && loca) // to_chat(world, "Burning...") - loca.hotspot_expose(700, 1000,surfaces=istype(loc,/turf)) - return - - -//todo: can light cigarettes with -//todo: is force = 15 overwriting the force? - -//////// Could be expanded upon: -// make it work with more chemicals and reagents, more like a chem grenade -// only allow the bottle to be stuffed if there are certain reagents inside, like fuel -// different flavor text for different means of lighting -// new fire overlay - current is edited version of the IED one -// a chance to not break, if desired -// fingerprints appearing on the object, which might already happen, and the shard -// belt sprite and new hand sprite -// ability to put out with water or otherwise -// burn out after a time causing the contents to ignite -// make into its own item type so they could be spawned full of fuel with New() -// colored light instead of white light -// the rag can store chemicals as well so maybe the rag's chemicals could react with the bottle's chemicals before or upon breaking -// somehow make it possible to wipe down the bottles instead of exclusively stuffing rags into them -// make rag retain chemical properties or color (if implemented) after smashing -//////// + loca.hotspot_expose(700, 1000,surfaces=istype(loc,/turf)) + return + + +//todo: can light cigarettes with +//todo: is force = 15 overwriting the force? + +//////// Could be expanded upon: +// make it work with more chemicals and reagents, more like a chem grenade +// only allow the bottle to be stuffed if there are certain reagents inside, like fuel +// different flavor text for different means of lighting +// new fire overlay - current is edited version of the IED one +// a chance to not break, if desired +// fingerprints appearing on the object, which might already happen, and the shard +// belt sprite and new hand sprite +// ability to put out with water or otherwise +// burn out after a time causing the contents to ignite +// make into its own item type so they could be spawned full of fuel with New() +// colored light instead of white light +// the rag can store chemicals as well so maybe the rag's chemicals could react with the bottle's chemicals before or upon breaking +// somehow make it possible to wipe down the bottles instead of exclusively stuffing rags into them +// make rag retain chemical properties or color (if implemented) after smashing +//////// diff --git a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm index c5fee3a7a1d..c081e7b3e5b 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm @@ -1,656 +1,656 @@ - - -/obj/item/weapon/reagent_containers/food/drinks/drinkingglass - name = "drinking glass" - desc = "Your standard drinking glass." - icon_state = "glass_empty" - isGlass = 1 - amount_per_transfer_from_this = 10 - volume = 50 - starting_materials = list(MAT_GLASS = 500) - force = 5 - smashtext = "" //due to inconsistencies in the names of the drinks just don't say anything - smashname = "broken glass" - melt_temperature = MELTPOINT_GLASS - w_type=RECYK_GLASS - -//removed smashing - now uses smashing proc from drinks.dm - Hinaichigo -//also now produces a broken glass when smashed instead of just a shard - - on_reagent_change() - ..() - /*if(reagents.reagent_list.len > 1 ) - icon_state = "glass_brown" - name = "Glass of Hooch" - desc = "Two or more drinks, mixed together."*/ - /*else if(reagents.reagent_list.len == 1) - for(var/datum/reagent/R in reagents.reagent_list) - switch(R.id)*/ - viewcontents = 1 - overlays.len = 0 - if (reagents.reagent_list.len > 0) - //mrid = R.get_master_reagent_id() - flammable = 0 - if(!molotov) - lit = 0 - light_color = null - set_light(0) - isGlass = 1 - switch(reagents.get_master_reagent_id()) - if("beer") - icon_state = "beerglass" - name = "beer glass" - desc = "A freezing pint of beer." - if("beer2") - icon_state = "beerglass" - name = "beer glass" - desc = "A freezing pint of beer." - if("ale") - icon_state = "aleglass" - name = "ale glass" - desc = "A freezing pint of delicious ale." - if("milk") - icon_state = "glass_white" - name = "glass of milk" - desc = "White and nutritious goodness!" - if("cream") - icon_state = "glass_white" - name = "glass of cream" - desc = "Ewwww..." - if("chocolate") - icon_state = "chocolateglass" - name = "glass of chocolate" - desc = "Tasty." - if("lemonjuice") - icon_state = "lemonglass" - name = "glass of lemonjuice" - desc = "Sour..." - if("cola") - icon_state = "glass_brown" - name = "glass of Space Cola" - desc = "A glass of refreshing Space Cola." - if("nuka_cola") - icon_state = "nuka_colaglass" - name = "\improper Nuka Cola" - desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland" - if("orangejuice") - icon_state = "glass_orange" - name = "glass of orange juice" - desc = "Vitamins! Yay!" - if("tomatojuice") - icon_state = "glass_red" - name = "glass of tomato juice" - desc = "Are you sure this is tomato juice?" - if("blood") - icon_state = "glass_red" - name = "glass of tomato juice" - desc = "Are you sure this is tomato juice?" - if("limejuice") - icon_state = "glass_green" - name = "glass of lime juice" - desc = "A glass of sweet-sour lime juice." - if("whiskey") - icon_state = "whiskeyglass" - name = "glass of whiskey" - desc = "The silky, smokey whiskey goodness inside the glass makes the drink look very classy." - if("gin") - icon_state = "ginvodkaglass" - name = "glass of gin" - desc = "A crystal clear glass of Griffeater gin." - if("vodka") - icon_state = "ginvodkaglass" - name = "glass of vodka" - desc = "The glass contain wodka. Xynta." - if("sake") - icon_state = "ginvodkaglass" - name = "glass of sake" - desc = "A glass of Sake." - if("goldschlager") - icon_state = "ginvodkaglass" - name = "glass of Goldschlager" - desc = "100 proof that teen girls will drink anything with gold in it." - if("wine") - icon_state = "wineglass" - name = "glass of wine" - desc = "A very classy looking drink." - if("cognac") - icon_state = "cognacglass" - name = "glass of cognac" - desc = "Damn, you feel like some kind of French aristocrat just by holding this." - if ("kahlua") - icon_state = "kahluaglass" - name = "glass of RR coffee liquor" - desc = "DAMN, THIS THING LOOKS ROBUST" - if("vermouth") - icon_state = "vermouthglass" - name = "glass of vermouth" - desc = "You wonder why you're even drinking this straight." - if("tequila") - icon_state = "tequilaglass" - name = "glass of tequila" - desc = "Now all that's missing is the weird colored shades!" - if("patron") - icon_state = "patronglass" - name = "glass of Patron" - desc = "Drinking Patron in the bar, with all the subpar ladies." - if("rum") - icon_state = "rumglass" - name = "glass of rum" - desc = "Now you want to Pray for a pirate suit, don't you?" - if("gintonic") - icon_state = "gintonicglass" - name = "gin and tonic" - desc = "A mild but still great cocktail. Drink up, like a true Englishman." - if("whiskeycola") - icon_state = "whiskeycolaglass" - name = "whiskey cola" - desc = "An innocent-looking mixture of cola and Whiskey. Delicious." - if("whiterussian") - icon_state = "whiterussianglass" - name = "\improper White Russian" - desc = "A very nice looking drink. But that's just, like, your opinion, man." - if("screwdrivercocktail") - icon_state = "screwdriverglass" - name = "\improper Screwdriver" - desc = "A simple, yet superb mixture of Vodka and orange juice. Just the thing for the tired engineer." - if("bloodymary") - icon_state = "bloodymaryglass" - name = "\improper Bloody Mary" - desc = "Tomato juice, mixed with Vodka and a lil' bit of lime. Tastes like liquid murder." - if("martini") - icon_state = "martiniglass" - name = "classic martini" - desc = "Damn, the bartender even stirred it, not shook it." - if("vodkamartini") - icon_state = "martiniglass" - name = "vodka martini" - desc ="A bastardisation of the classic martini. Still great." - if("gargleblaster") - icon_state = "gargleblasterglass" - name = "\improper Pan-Galactic Gargle Blaster" - desc = "Does... does this mean that Arthur and Ford are on the station? Oh joy." - if("bravebull") - icon_state = "bravebullglass" - name = "\improper Brave Bull" - desc = "Tequila and coffee liquor, brought together in a mouthwatering mixture. Drink up." - if("tequilasunrise") - icon_state = "tequilasunriseglass" - name = "\improper Tequila Sunrise" - desc = "Oh great, now you feel nostalgic about sunrises back on Terra..." - if("toxinsspecial") - icon_state = "toxinsspecialglass" - name = "\improper Toxins Special" - desc = "Whoah, this thing is on FIRE!" - if("beepskysmash") - icon_state = "beepskysmashglass" - name = "\improper Beepsky Smash" - desc = "Heavy, hot and strong. Just like the Iron fist of the LAW." - if("doctorsdelight") - icon_state = "doctorsdelightglass" - name = "\improper Doctor's Delight" - desc = "A healthy mixture of juices, guaranteed to keep you healthy until the next toolboxing takes place." - if("manlydorf") - icon_state = "manlydorfglass" - name = "The Manly Dorf" - desc = "A manly concotion made from Ale and Beer. Intended for true men only." - if("irishcream") - icon_state = "irishcreamglass" - name = "\improper Irish Cream" - desc = "It's cream, mixed with whiskey. What else would you expect from the Irish?" - if("cubalibre") - icon_state = "cubalibreglass" - name = "\improper Cuba Libre" - desc = "A classic mix of rum and cola." - if("b52") - icon_state = "b52glass" - name = "\improper B-52" - desc = "Kahlua, Irish Cream, and congac. You will get bombed." - light_color = "#000080" - if(!lit) - flammable = 1 - if("atomicbomb") - icon_state = "atomicbombglass" - name = "\improper Atomic Bomb" - desc = "Nanotrasen cannot take legal responsibility for your actions after imbibing." - if("longislandicedtea") - icon_state = "longislandicedteaglass" - name = "\improper Long Island Iced Tea" - desc = "The liquor cabinet, brought together in a delicious mix. Intended for middle-aged alcoholic women only." - if("threemileisland") - icon_state = "threemileislandglass" - name = "\improper Three Mile Island Ice Tea" - desc = "A glass of this is sure to prevent a meltdown." - if("margarita") - icon_state = "margaritaglass" - name = "\improper Margarita" - desc = "On the rocks with salt on the rim. Arriba~!" - if("blackrussian") - icon_state = "blackrussianglass" - name = "\improper Black Russian" - desc = "For the lactose-intolerant. Still as classy as a White Russian." - if("vodkatonic") - icon_state = "vodkatonicglass" - name = "vodka and tonic" - desc = "For when a gin and tonic isn't Russian enough." - if("manhattan") - icon_state = "manhattanglass" - name = "\improper Manhattan" - desc = "The Detective's undercover drink of choice. He never could stomach gin..." - if("manhattan_proj") - icon_state = "proj_manhattanglass" - name = "\improper Manhattan Project" - desc = "A scienitst drink of choice, for thinking how to blow up the station." - if("ginfizz") - icon_state = "ginfizzglass" - name = "\improper Gin Fizz" - desc = "Refreshingly lemony, deliciously dry." - if("irishcoffee") - icon_state = "irishcoffeeglass" - name = "\improper Irish Coffee" - desc = "Coffee and alcohol. More fun than a Mimosa to drink in the morning." - if("hooch") - icon_state = "glass_brown2" - name = "\improper Hooch" - desc = "You've really hit rock bottom now... your liver packed its bags and left last night." - if("whiskeysoda") - icon_state = "whiskeysodaglass2" - name = "whiskey soda" - desc = "Ultimate refreshment." - if("tonic") - icon_state = "glass_clear" - name = "glass of tonic water" - desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away." - if("sodawater") - icon_state = "glass_clear" - name = "glass of soda water" - desc = "Soda water. Why not make a scotch and soda?" - if("water") - icon_state = "glass_clear" - name = "glass of water" - desc = "The father of all refreshments." - if("spacemountainwind") - icon_state = "Space_mountain_wind_glass" - name = "glass of Space Mountain Wind" - desc = "Space Mountain Wind. As you know, there are no mountains in space, only wind." - if("thirteenloko") - icon_state = "thirteen_loko_glass" - name = "glass of Thirteen Loko" - desc = "This is a glass of Thirteen Loko, it appears to be of the highest quality. The drink, not the glass." - if("dr_gibb") - icon_state = "dr_gibb_glass" - name = "glass of Dr. Gibb" - desc = "Dr. Gibb. Not as dangerous as the name might imply." - if("space_up") - icon_state = "space-up_glass" - name = "glass of Space-up" - desc = "Space-up. It helps keep your cool." - if("moonshine") - icon_state = "glass_clear" - name = "\improper Moonshine" - desc = "You've really hit rock bottom now... your liver packed its bags and left last night." - if("soymilk") - icon_state = "glass_white" - name = "glass of soy milk" - desc = "White and nutritious soy goodness!" - if("berryjuice") - icon_state = "berryjuice" - name = "glass of berry juice" - desc = "Berry juice. Or maybe its jam. Who cares?" - if("poisonberryjuice") - icon_state = "poisonberryjuice" - name = "glass of poison berry juice" - desc = "A glass of deadly juice." - if("carrotjuice") - icon_state = "carrotjuice" - name = "glass of carrot juice" - desc = "It is just like a carrot but without crunching." - if("banana") - icon_state = "banana" - name = "glass of banana juice" - desc = "The raw essence of a banana. HONK" - if("bahama_mama") - icon_state = "bahama_mama" - name = "\improper Bahama Mama" - desc = "Tropic cocktail." - if("singulo") - icon_state = "singulo" - name = "\improper Singulo" - desc = "A blue-space beverage." - if("alliescocktail") - icon_state = "alliescocktail" - name = "\improper Allies Cocktail" - desc = "A drink made from your allies." - if("antifreeze") - icon_state = "antifreeze" - name = "\improper Anti-freeze" - desc = "The ultimate refreshment." - if("barefoot") - icon_state = "b&p" - name = "\improper Barefoot" - desc = "Barefoot and pregnant." - if("demonsblood") - icon_state = "demonsblood" - name = "\improper Demon's Blood" - desc = "Just looking at this thing makes the hair at the back of your neck stand up." - if("booger") - icon_state = "booger" - name = "\improper Booger" - desc = "Ewww..." - if("snowwhite") - icon_state = "snowwhite" - name = "\improper Snow White" - desc = "A cold refreshment." - if("aloe") - icon_state = "aloe" - name = "aloe" - desc = "Very, very, very good." - if("andalusia") - icon_state = "andalusia" - name = "\improper Andalusia" - desc = "A nice, strange named drink." - if("sbiten") - icon_state = "sbitenglass" - name = "\improper Sbiten" - desc = "A spicy mix of vodka and spice. Very hot." - if("red_mead") - icon_state = "red_meadglass" - name = "red mead" - desc = "A True Vikings Beverage, though its color is strange." - if("mead") - icon_state = "meadglass" - name = "mead" - desc = "A Vikings Beverage, though a cheap one." - if("iced_beer") - icon_state = "iced_beerglass" - name = "iced Beer" - desc = "A beer so frosty, the air around it freezes." - if("grog") - icon_state = "grogglass" - name = "grog" - desc = "A fine and cepa drink for Space." - if("soy_latte") - icon_state = "soy_latte" - name = "soy latte" - desc = "A nice and refrshing beverage while you are reading." - if("cafe_latte") - icon_state = "cafe_latte" - name = "cafe latte" - desc = "A nice, strong and refreshing beverage while you are reading." - if("acidspit") - icon_state = "acidspitglass" - name = "\improper Acid Spit" - desc = "A drink from Nanotrasen. Made from live aliens." - if("amasec") - icon_state = "amasecglass" - name = "\improper Amasec" - desc = "Always handy before COMBAT!!!" - if("neurotoxin") - icon_state = "neurotoxinglass" - name = "\improper Neurotoxin" - desc = "A drink that is guaranteed to knock you silly." - if("hippiesdelight") - icon_state = "hippiesdelightglass" - name = "\improper Hippie's Delight" - desc = "A drink enjoyed by people during the 1960's." - if("bananahonk") - icon_state = "bananahonkglass" - name = "\improper Banana Honk" - desc = "A drink from banana heaven." - if("silencer") - icon_state = "silencerglass" - name = "\improper Silencer" - desc = "A drink from mime heaven." - if("nothing") - icon_state = "nothing" - name = "nothing" - desc = "Absolutely nothing." - if("devilskiss") - icon_state = "devilskiss" - name = "\improper Devils Kiss" - desc = "Creepy time!" - if("changelingsting") - icon_state = "changelingsting" - name = "\improper Changeling Sting" - desc = "A stingy drink." - if("irishcarbomb") - icon_state = "irishcarbomb" - name = "\improper Irish Car Bomb" - desc = "An irish car bomb." - if("syndicatebomb") - icon_state = "syndicatebomb" - name = "\improper Syndicate Bomb" - desc = "A syndicate bomb." - isGlass = 0//blablabla hidden features, blablabla joke material - if("erikasurprise") - icon_state = "erikasurprise" - name = "\improper Erika Surprise" - desc = "The surprise is, it's green!" - if("driestmartini") - icon_state = "driestmartiniglass" - name = "\improper Driest Martini" - desc = "Only for the experienced. You think you see sand floating in the glass." - if("ice") - icon_state = "iceglass" - name = "glass of ice" - desc = "Generally, you're supposed to put something else in there too..." - if("icecoffee") - icon_state = "icedcoffeeglass" - name = "iced Coffee" - desc = "A drink to perk you up and refresh you!" - if("coffee") - icon_state = "glass_brown" - name = "glass of coffee" - desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere." - if("bilk") - icon_state = "glass_brown" - name = "glass of bilk" - desc = "A brew of milk and beer. For those alcoholics who fear osteoporosis." - if("fuel") - icon_state = "dr_gibb_glass" - name = "glass of welder fuel" - desc = "Unless you are an industrial tool, this is probably not safe for consumption." - if("brownstar") - icon_state = "brownstar" - name = "\improper Brown Star" - desc = "Its not what it sounds like..." - if("icetea") - icon_state = "icetea" - name = "iced tea" - desc = "No relation to a certain rap artist/ actor." - if("arnoldpalmer") - icon_state = "arnoldpalmer" - name = "Arnold Palmer" - desc = "Known as half and half to some. A mix of ice tea and lemonade" - if("milkshake") - icon_state = "milkshake" - name = "milkshake" - desc = "Glorious brainfreezing mixture." - if("lemonade") - icon_state = "lemonade" - name = "lemonade" - desc = "Oh the nostalgia..." - if("kiraspecial") - icon_state = "kiraspecial" - name = "\improper Kira Special" - desc = "Long live the guy who everyone had mistaken for a girl. Baka!" - if("rewriter") - icon_state = "rewriter" - name = "\improper Rewriter" - desc = "The secert of the sanctuary of the Libarian..." - if("pinacolada") - icon_state = "pinacolada" - name = "\improper Pina Colada" - desc = "If you like this and getting caught in the rain, come with me and escape." - else - icon_state ="glass_colour" - get_reagent_name(src) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "glass") - filling.icon += mix_color_from_reagents(reagents.reagent_list) - filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) - overlays += filling - - - - if(reagents.has_reagent("blackcolor")) - icon_state ="blackglass" - name = "international drink of mystery" - desc = "The identity of this drink has been concealed for its protection." - viewcontents = 0 - else - icon_state = "glass_empty" - name = "drinking glass" - desc = "Your standard drinking glass." - return - -// for /obj/machinery/vending/sovietsoda -/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda - New() - ..() - reagents.add_reagent("sodawater", 50) - on_reagent_change() - -/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola - New() - ..() - reagents.add_reagent("cola", 50) - on_reagent_change() - -// Cafe Stuff. Mugs act the same as drinking glasses, but they don't break when thrown. - -/obj/item/weapon/reagent_containers/food/drinks/mug - name = "mug" - desc = "A simple mug." - icon = 'icons/obj/cafe.dmi' - icon_state = "mug_empty" - isGlass = 0 - amount_per_transfer_from_this = 10 - volume = 30 - starting_materials = list(MAT_IRON = 500) - - on_reagent_change() - - if (reagents.reagent_list.len > 0) - - switch(reagents.get_master_reagent_id()) - if("tea") - icon_state = "tea" - name = "Tea" - desc = "A warm mug of tea." - if("greentea") - icon_state = "greentea" - name = "Green Tea" - desc = "Green Tea served in a traditional Japanese tea cup, just like in your Chinese cartoons!" - if("redtea") - icon_state = "redtea" - name = "Red Tea" - desc = "Red Tea served in a traditional Chinese tea cup, just like in your Malaysian movies!" - if("acidtea") - icon_state = "acidtea" - name = "Earl's Grey Tea" - desc = "A sizzling mug of tea made just for Greys." - if("yinyang") - icon_state = "yinyang" - name = "Zen Tea" - desc = "Enjoy inner peace and ignore the watered down taste" - if("dantea") - icon_state = "dantea" - name = "Discount Dans Green Flavor Tea" - desc = "Tea probably shouldn't be sizzling like that..." - if("singularitea") - icon_state = "singularitea" - name = "Singularitea" - desc = "Brewed under intense radiation to be extra flavorful!" - if("mint") - icon_state = "mint" - name = "Groans Tea: Minty Delight Flavor" - desc = "Groans knows mint might not be the kind of flavor our fans expect from us, but we've made sure to give it that patented Groans zing." - if("chamomile") - icon_state = "chamomile" - name = "Groans Tea: Chamomile Flavor" - desc = "Groans presents the perfect cure for insomnia; Chamomile!" - if("exchamomile") - icon_state = "exchamomile" - name = "Groans Banned Tea: EXTREME Chamomile Flavor" - desc = "Banned literally everywhere." - if("fancydan") - icon_state = "fancydan" - name = "Groans Banned Tea: Fancy Dan Flavor" - desc = "Banned literally everywhere." - if("gyro") - icon_state = "gyro" - name = "Gyro" - desc = "Nyo ho ho~" - if("chifir") - icon_state = "chifir" - name = "Chifir" - desc = "Russian style of tea, not for those with weak stomachs." - if("plasmatea") - icon_state = "plasmatea" - name = "Plasma Pekoe" - desc = "You can practically taste the science, or maybe that's just the horrible plasma burns." - if("coffee") - icon_state = "coffee" - name = "Coffee" - desc = "A warm mug of coffee." - if("cafe_latte") - icon_state = "latte" - name = "Latte" - desc = "Coffee made with espresso and milk." - if("soy_latte") - icon_state = "soylatte" - name = "Soy Latte" - desc = "Latte made with soy milk." - if("espresso") - icon_state = "espresso" - name = "Espresso" - desc = "Coffee made with water." - if("cappuccino") - icon_state = "cappuccino" - name = "Cappuccino" - desc = "coffee made with espresso, milk, and steamed milk." - if("doppio") - icon_state = "doppio" - name = "Doppio" - desc = "Ring ring ring" - if("tonio") - icon_state = "tonio" - name = "Tonio" - desc = "Delicious, and it'll help you out if you get in a Jam." - if("passione") - icon_state = "passione" - name = "Passione" - desc = "Sometimes referred to as a 'Venti Aureo'" - if("seccoffee") - icon_state = "seccoffee" - name = "Wake up call" - desc = "The perfect start for any Sec officer's day." - if("medcoffee") - icon_state = "medcoffee" - name = "Lifeline" - desc = "Some days, the only thing that keeps you going is cryo and caffeine." - if("detcoffee") - icon_state = "detcoffee" - name = "Joe" - desc = "The lights, the smoke, the grime, the station itself felt alive that day as I stepped into my office, mug in hand. It was another one of those days. Some Nurse got smoked in one of the tunnels, and it came down to me to catch the guy did it. I got up to close the blinds of my office, when an officer burst through my door. There had been another one offed in the tunnels, this time an assistant. I grumbled and downed some of my joe. It was bitter, tasteless, but it was what kept me going. I remember back when I was a rookie, this stuff used to taste so great to me. I guess that's just another sign of how this station changes people. I put my mug back down on my desk, dusted off my jacket, and lit my last cigar. I checked to make sure my faithful revolver was loaded, and stepped out, back into the cold halls of the station." - if("etank") - icon_state = "etank" - name = "Recharger" - desc = "Helps you get back on your feet after a long day of robot maintenance. Can also be used as a substitute for motor oil." - if("greytea") - icon_state = "greytea" - name = "Tide" - desc = "This probably shouldn't be considered tea..." - - - - - - else - icon_state ="mug_what" - name = "mug of ..something?" - desc = "You aren't really sure what this is." - else - icon_state = "mug_empty" - name = "mug" - desc = "A simple mug." + + +/obj/item/weapon/reagent_containers/food/drinks/drinkingglass + name = "drinking glass" + desc = "Your standard drinking glass." + icon_state = "glass_empty" + isGlass = 1 + amount_per_transfer_from_this = 10 + volume = 50 + starting_materials = list(MAT_GLASS = 500) + force = 5 + smashtext = "" //due to inconsistencies in the names of the drinks just don't say anything + smashname = "broken glass" + melt_temperature = MELTPOINT_GLASS + w_type=RECYK_GLASS + +//removed smashing - now uses smashing proc from drinks.dm - Hinaichigo +//also now produces a broken glass when smashed instead of just a shard + + on_reagent_change() + ..() + /*if(reagents.reagent_list.len > 1 ) + icon_state = "glass_brown" + name = "Glass of Hooch" + desc = "Two or more drinks, mixed together."*/ + /*else if(reagents.reagent_list.len == 1) + for(var/datum/reagent/R in reagents.reagent_list) + switch(R.id)*/ + viewcontents = 1 + overlays.len = 0 + if (reagents.reagent_list.len > 0) + //mrid = R.get_master_reagent_id() + flammable = 0 + if(!molotov) + lit = 0 + light_color = null + set_light(0) + isGlass = 1 + switch(reagents.get_master_reagent_id()) + if("beer") + icon_state = "beerglass" + name = "beer glass" + desc = "A freezing pint of beer." + if("beer2") + icon_state = "beerglass" + name = "beer glass" + desc = "A freezing pint of beer." + if("ale") + icon_state = "aleglass" + name = "ale glass" + desc = "A freezing pint of delicious ale." + if("milk") + icon_state = "glass_white" + name = "glass of milk" + desc = "White and nutritious goodness!" + if("cream") + icon_state = "glass_white" + name = "glass of cream" + desc = "Ewwww..." + if("chocolate") + icon_state = "chocolateglass" + name = "glass of chocolate" + desc = "Tasty." + if("lemonjuice") + icon_state = "lemonglass" + name = "glass of lemonjuice" + desc = "Sour..." + if("cola") + icon_state = "glass_brown" + name = "glass of Space Cola" + desc = "A glass of refreshing Space Cola." + if("nuka_cola") + icon_state = "nuka_colaglass" + name = "\improper Nuka Cola" + desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland" + if("orangejuice") + icon_state = "glass_orange" + name = "glass of orange juice" + desc = "Vitamins! Yay!" + if("tomatojuice") + icon_state = "glass_red" + name = "glass of tomato juice" + desc = "Are you sure this is tomato juice?" + if("blood") + icon_state = "glass_red" + name = "glass of tomato juice" + desc = "Are you sure this is tomato juice?" + if("limejuice") + icon_state = "glass_green" + name = "glass of lime juice" + desc = "A glass of sweet-sour lime juice." + if("whiskey") + icon_state = "whiskeyglass" + name = "glass of whiskey" + desc = "The silky, smokey whiskey goodness inside the glass makes the drink look very classy." + if("gin") + icon_state = "ginvodkaglass" + name = "glass of gin" + desc = "A crystal clear glass of Griffeater gin." + if("vodka") + icon_state = "ginvodkaglass" + name = "glass of vodka" + desc = "The glass contain wodka. Xynta." + if("sake") + icon_state = "ginvodkaglass" + name = "glass of sake" + desc = "A glass of Sake." + if("goldschlager") + icon_state = "ginvodkaglass" + name = "glass of Goldschlager" + desc = "100 proof that teen girls will drink anything with gold in it." + if("wine") + icon_state = "wineglass" + name = "glass of wine" + desc = "A very classy looking drink." + if("cognac") + icon_state = "cognacglass" + name = "glass of cognac" + desc = "Damn, you feel like some kind of French aristocrat just by holding this." + if ("kahlua") + icon_state = "kahluaglass" + name = "glass of RR coffee liquor" + desc = "DAMN, THIS THING LOOKS ROBUST" + if("vermouth") + icon_state = "vermouthglass" + name = "glass of vermouth" + desc = "You wonder why you're even drinking this straight." + if("tequila") + icon_state = "tequilaglass" + name = "glass of tequila" + desc = "Now all that's missing is the weird colored shades!" + if("patron") + icon_state = "patronglass" + name = "glass of Patron" + desc = "Drinking Patron in the bar, with all the subpar ladies." + if("rum") + icon_state = "rumglass" + name = "glass of rum" + desc = "Now you want to Pray for a pirate suit, don't you?" + if("gintonic") + icon_state = "gintonicglass" + name = "gin and tonic" + desc = "A mild but still great cocktail. Drink up, like a true Englishman." + if("whiskeycola") + icon_state = "whiskeycolaglass" + name = "whiskey cola" + desc = "An innocent-looking mixture of cola and Whiskey. Delicious." + if("whiterussian") + icon_state = "whiterussianglass" + name = "\improper White Russian" + desc = "A very nice looking drink. But that's just, like, your opinion, man." + if("screwdrivercocktail") + icon_state = "screwdriverglass" + name = "\improper Screwdriver" + desc = "A simple, yet superb mixture of Vodka and orange juice. Just the thing for the tired engineer." + if("bloodymary") + icon_state = "bloodymaryglass" + name = "\improper Bloody Mary" + desc = "Tomato juice, mixed with Vodka and a lil' bit of lime. Tastes like liquid murder." + if("martini") + icon_state = "martiniglass" + name = "classic martini" + desc = "Damn, the bartender even stirred it, not shook it." + if("vodkamartini") + icon_state = "martiniglass" + name = "vodka martini" + desc ="A bastardisation of the classic martini. Still great." + if("gargleblaster") + icon_state = "gargleblasterglass" + name = "\improper Pan-Galactic Gargle Blaster" + desc = "Does... does this mean that Arthur and Ford are on the station? Oh joy." + if("bravebull") + icon_state = "bravebullglass" + name = "\improper Brave Bull" + desc = "Tequila and coffee liquor, brought together in a mouthwatering mixture. Drink up." + if("tequilasunrise") + icon_state = "tequilasunriseglass" + name = "\improper Tequila Sunrise" + desc = "Oh great, now you feel nostalgic about sunrises back on Terra..." + if("toxinsspecial") + icon_state = "toxinsspecialglass" + name = "\improper Toxins Special" + desc = "Whoah, this thing is on FIRE!" + if("beepskysmash") + icon_state = "beepskysmashglass" + name = "\improper Beepsky Smash" + desc = "Heavy, hot and strong. Just like the Iron fist of the LAW." + if("doctorsdelight") + icon_state = "doctorsdelightglass" + name = "\improper Doctor's Delight" + desc = "A healthy mixture of juices, guaranteed to keep you healthy until the next toolboxing takes place." + if("manlydorf") + icon_state = "manlydorfglass" + name = "The Manly Dorf" + desc = "A manly concotion made from Ale and Beer. Intended for true men only." + if("irishcream") + icon_state = "irishcreamglass" + name = "\improper Irish Cream" + desc = "It's cream, mixed with whiskey. What else would you expect from the Irish?" + if("cubalibre") + icon_state = "cubalibreglass" + name = "\improper Cuba Libre" + desc = "A classic mix of rum and cola." + if("b52") + icon_state = "b52glass" + name = "\improper B-52" + desc = "Kahlua, Irish Cream, and congac. You will get bombed." + light_color = "#000080" + if(!lit) + flammable = 1 + if("atomicbomb") + icon_state = "atomicbombglass" + name = "\improper Atomic Bomb" + desc = "Nanotrasen cannot take legal responsibility for your actions after imbibing." + if("longislandicedtea") + icon_state = "longislandicedteaglass" + name = "\improper Long Island Iced Tea" + desc = "The liquor cabinet, brought together in a delicious mix. Intended for middle-aged alcoholic women only." + if("threemileisland") + icon_state = "threemileislandglass" + name = "\improper Three Mile Island Ice Tea" + desc = "A glass of this is sure to prevent a meltdown." + if("margarita") + icon_state = "margaritaglass" + name = "\improper Margarita" + desc = "On the rocks with salt on the rim. Arriba~!" + if("blackrussian") + icon_state = "blackrussianglass" + name = "\improper Black Russian" + desc = "For the lactose-intolerant. Still as classy as a White Russian." + if("vodkatonic") + icon_state = "vodkatonicglass" + name = "vodka and tonic" + desc = "For when a gin and tonic isn't Russian enough." + if("manhattan") + icon_state = "manhattanglass" + name = "\improper Manhattan" + desc = "The Detective's undercover drink of choice. He never could stomach gin..." + if("manhattan_proj") + icon_state = "proj_manhattanglass" + name = "\improper Manhattan Project" + desc = "A scienitst drink of choice, for thinking how to blow up the station." + if("ginfizz") + icon_state = "ginfizzglass" + name = "\improper Gin Fizz" + desc = "Refreshingly lemony, deliciously dry." + if("irishcoffee") + icon_state = "irishcoffeeglass" + name = "\improper Irish Coffee" + desc = "Coffee and alcohol. More fun than a Mimosa to drink in the morning." + if("hooch") + icon_state = "glass_brown2" + name = "\improper Hooch" + desc = "You've really hit rock bottom now... your liver packed its bags and left last night." + if("whiskeysoda") + icon_state = "whiskeysodaglass2" + name = "whiskey soda" + desc = "Ultimate refreshment." + if("tonic") + icon_state = "glass_clear" + name = "glass of tonic water" + desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away." + if("sodawater") + icon_state = "glass_clear" + name = "glass of soda water" + desc = "Soda water. Why not make a scotch and soda?" + if("water") + icon_state = "glass_clear" + name = "glass of water" + desc = "The father of all refreshments." + if("spacemountainwind") + icon_state = "Space_mountain_wind_glass" + name = "glass of Space Mountain Wind" + desc = "Space Mountain Wind. As you know, there are no mountains in space, only wind." + if("thirteenloko") + icon_state = "thirteen_loko_glass" + name = "glass of Thirteen Loko" + desc = "This is a glass of Thirteen Loko, it appears to be of the highest quality. The drink, not the glass." + if("dr_gibb") + icon_state = "dr_gibb_glass" + name = "glass of Dr. Gibb" + desc = "Dr. Gibb. Not as dangerous as the name might imply." + if("space_up") + icon_state = "space-up_glass" + name = "glass of Space-up" + desc = "Space-up. It helps keep your cool." + if("moonshine") + icon_state = "glass_clear" + name = "\improper Moonshine" + desc = "You've really hit rock bottom now... your liver packed its bags and left last night." + if("soymilk") + icon_state = "glass_white" + name = "glass of soy milk" + desc = "White and nutritious soy goodness!" + if("berryjuice") + icon_state = "berryjuice" + name = "glass of berry juice" + desc = "Berry juice. Or maybe its jam. Who cares?" + if("poisonberryjuice") + icon_state = "poisonberryjuice" + name = "glass of poison berry juice" + desc = "A glass of deadly juice." + if("carrotjuice") + icon_state = "carrotjuice" + name = "glass of carrot juice" + desc = "It is just like a carrot but without crunching." + if("banana") + icon_state = "banana" + name = "glass of banana juice" + desc = "The raw essence of a banana. HONK" + if("bahama_mama") + icon_state = "bahama_mama" + name = "\improper Bahama Mama" + desc = "Tropic cocktail." + if("singulo") + icon_state = "singulo" + name = "\improper Singulo" + desc = "A blue-space beverage." + if("alliescocktail") + icon_state = "alliescocktail" + name = "\improper Allies Cocktail" + desc = "A drink made from your allies." + if("antifreeze") + icon_state = "antifreeze" + name = "\improper Anti-freeze" + desc = "The ultimate refreshment." + if("barefoot") + icon_state = "b&p" + name = "\improper Barefoot" + desc = "Barefoot and pregnant." + if("demonsblood") + icon_state = "demonsblood" + name = "\improper Demon's Blood" + desc = "Just looking at this thing makes the hair at the back of your neck stand up." + if("booger") + icon_state = "booger" + name = "\improper Booger" + desc = "Ewww..." + if("snowwhite") + icon_state = "snowwhite" + name = "\improper Snow White" + desc = "A cold refreshment." + if("aloe") + icon_state = "aloe" + name = "aloe" + desc = "Very, very, very good." + if("andalusia") + icon_state = "andalusia" + name = "\improper Andalusia" + desc = "A nice, strange named drink." + if("sbiten") + icon_state = "sbitenglass" + name = "\improper Sbiten" + desc = "A spicy mix of vodka and spice. Very hot." + if("red_mead") + icon_state = "red_meadglass" + name = "red mead" + desc = "A True Vikings Beverage, though its color is strange." + if("mead") + icon_state = "meadglass" + name = "mead" + desc = "A Vikings Beverage, though a cheap one." + if("iced_beer") + icon_state = "iced_beerglass" + name = "iced Beer" + desc = "A beer so frosty, the air around it freezes." + if("grog") + icon_state = "grogglass" + name = "grog" + desc = "A fine and cepa drink for Space." + if("soy_latte") + icon_state = "soy_latte" + name = "soy latte" + desc = "A nice and refrshing beverage while you are reading." + if("cafe_latte") + icon_state = "cafe_latte" + name = "cafe latte" + desc = "A nice, strong and refreshing beverage while you are reading." + if("acidspit") + icon_state = "acidspitglass" + name = "\improper Acid Spit" + desc = "A drink from Nanotrasen. Made from live aliens." + if("amasec") + icon_state = "amasecglass" + name = "\improper Amasec" + desc = "Always handy before COMBAT!!!" + if("neurotoxin") + icon_state = "neurotoxinglass" + name = "\improper Neurotoxin" + desc = "A drink that is guaranteed to knock you silly." + if("hippiesdelight") + icon_state = "hippiesdelightglass" + name = "\improper Hippie's Delight" + desc = "A drink enjoyed by people during the 1960's." + if("bananahonk") + icon_state = "bananahonkglass" + name = "\improper Banana Honk" + desc = "A drink from banana heaven." + if("silencer") + icon_state = "silencerglass" + name = "\improper Silencer" + desc = "A drink from mime heaven." + if("nothing") + icon_state = "nothing" + name = "nothing" + desc = "Absolutely nothing." + if("devilskiss") + icon_state = "devilskiss" + name = "\improper Devils Kiss" + desc = "Creepy time!" + if("changelingsting") + icon_state = "changelingsting" + name = "\improper Changeling Sting" + desc = "A stingy drink." + if("irishcarbomb") + icon_state = "irishcarbomb" + name = "\improper Irish Car Bomb" + desc = "An irish car bomb." + if("syndicatebomb") + icon_state = "syndicatebomb" + name = "\improper Syndicate Bomb" + desc = "A syndicate bomb." + isGlass = 0//blablabla hidden features, blablabla joke material + if("erikasurprise") + icon_state = "erikasurprise" + name = "\improper Erika Surprise" + desc = "The surprise is, it's green!" + if("driestmartini") + icon_state = "driestmartiniglass" + name = "\improper Driest Martini" + desc = "Only for the experienced. You think you see sand floating in the glass." + if("ice") + icon_state = "iceglass" + name = "glass of ice" + desc = "Generally, you're supposed to put something else in there too..." + if("icecoffee") + icon_state = "icedcoffeeglass" + name = "iced Coffee" + desc = "A drink to perk you up and refresh you!" + if("coffee") + icon_state = "glass_brown" + name = "glass of coffee" + desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere." + if("bilk") + icon_state = "glass_brown" + name = "glass of bilk" + desc = "A brew of milk and beer. For those alcoholics who fear osteoporosis." + if("fuel") + icon_state = "dr_gibb_glass" + name = "glass of welder fuel" + desc = "Unless you are an industrial tool, this is probably not safe for consumption." + if("brownstar") + icon_state = "brownstar" + name = "\improper Brown Star" + desc = "Its not what it sounds like..." + if("icetea") + icon_state = "icetea" + name = "iced tea" + desc = "No relation to a certain rap artist/ actor." + if("arnoldpalmer") + icon_state = "arnoldpalmer" + name = "Arnold Palmer" + desc = "Known as half and half to some. A mix of ice tea and lemonade" + if("milkshake") + icon_state = "milkshake" + name = "milkshake" + desc = "Glorious brainfreezing mixture." + if("lemonade") + icon_state = "lemonade" + name = "lemonade" + desc = "Oh the nostalgia..." + if("kiraspecial") + icon_state = "kiraspecial" + name = "\improper Kira Special" + desc = "Long live the guy who everyone had mistaken for a girl. Baka!" + if("rewriter") + icon_state = "rewriter" + name = "\improper Rewriter" + desc = "The secert of the sanctuary of the Libarian..." + if("pinacolada") + icon_state = "pinacolada" + name = "\improper Pina Colada" + desc = "If you like this and getting caught in the rain, come with me and escape." + else + icon_state ="glass_colour" + get_reagent_name(src) + var/image/filling = image('icons/obj/reagentfillings.dmi', src, "glass") + filling.icon += mix_color_from_reagents(reagents.reagent_list) + filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) + overlays += filling + + + + if(reagents.has_reagent("blackcolor")) + icon_state ="blackglass" + name = "international drink of mystery" + desc = "The identity of this drink has been concealed for its protection." + viewcontents = 0 + else + icon_state = "glass_empty" + name = "drinking glass" + desc = "Your standard drinking glass." + return + +// for /obj/machinery/vending/sovietsoda +/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda + New() + ..() + reagents.add_reagent("sodawater", 50) + on_reagent_change() + +/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola + New() + ..() + reagents.add_reagent("cola", 50) + on_reagent_change() + +// Cafe Stuff. Mugs act the same as drinking glasses, but they don't break when thrown. + +/obj/item/weapon/reagent_containers/food/drinks/mug + name = "mug" + desc = "A simple mug." + icon = 'icons/obj/cafe.dmi' + icon_state = "mug_empty" + isGlass = 0 + amount_per_transfer_from_this = 10 + volume = 30 + starting_materials = list(MAT_IRON = 500) + + on_reagent_change() + + if (reagents.reagent_list.len > 0) + + switch(reagents.get_master_reagent_id()) + if("tea") + icon_state = "tea" + name = "Tea" + desc = "A warm mug of tea." + if("greentea") + icon_state = "greentea" + name = "Green Tea" + desc = "Green Tea served in a traditional Japanese tea cup, just like in your Chinese cartoons!" + if("redtea") + icon_state = "redtea" + name = "Red Tea" + desc = "Red Tea served in a traditional Chinese tea cup, just like in your Malaysian movies!" + if("acidtea") + icon_state = "acidtea" + name = "Earl's Grey Tea" + desc = "A sizzling mug of tea made just for Greys." + if("yinyang") + icon_state = "yinyang" + name = "Zen Tea" + desc = "Enjoy inner peace and ignore the watered down taste" + if("dantea") + icon_state = "dantea" + name = "Discount Dans Green Flavor Tea" + desc = "Tea probably shouldn't be sizzling like that..." + if("singularitea") + icon_state = "singularitea" + name = "Singularitea" + desc = "Brewed under intense radiation to be extra flavorful!" + if("mint") + icon_state = "mint" + name = "Groans Tea: Minty Delight Flavor" + desc = "Groans knows mint might not be the kind of flavor our fans expect from us, but we've made sure to give it that patented Groans zing." + if("chamomile") + icon_state = "chamomile" + name = "Groans Tea: Chamomile Flavor" + desc = "Groans presents the perfect cure for insomnia; Chamomile!" + if("exchamomile") + icon_state = "exchamomile" + name = "Groans Banned Tea: EXTREME Chamomile Flavor" + desc = "Banned literally everywhere." + if("fancydan") + icon_state = "fancydan" + name = "Groans Banned Tea: Fancy Dan Flavor" + desc = "Banned literally everywhere." + if("gyro") + icon_state = "gyro" + name = "Gyro" + desc = "Nyo ho ho~" + if("chifir") + icon_state = "chifir" + name = "Chifir" + desc = "Russian style of tea, not for those with weak stomachs." + if("plasmatea") + icon_state = "plasmatea" + name = "Plasma Pekoe" + desc = "You can practically taste the science, or maybe that's just the horrible plasma burns." + if("coffee") + icon_state = "coffee" + name = "Coffee" + desc = "A warm mug of coffee." + if("cafe_latte") + icon_state = "latte" + name = "Latte" + desc = "Coffee made with espresso and milk." + if("soy_latte") + icon_state = "soylatte" + name = "Soy Latte" + desc = "Latte made with soy milk." + if("espresso") + icon_state = "espresso" + name = "Espresso" + desc = "Coffee made with water." + if("cappuccino") + icon_state = "cappuccino" + name = "Cappuccino" + desc = "coffee made with espresso, milk, and steamed milk." + if("doppio") + icon_state = "doppio" + name = "Doppio" + desc = "Ring ring ring" + if("tonio") + icon_state = "tonio" + name = "Tonio" + desc = "Delicious, and it'll help you out if you get in a Jam." + if("passione") + icon_state = "passione" + name = "Passione" + desc = "Sometimes referred to as a 'Venti Aureo'" + if("seccoffee") + icon_state = "seccoffee" + name = "Wake up call" + desc = "The perfect start for any Sec officer's day." + if("medcoffee") + icon_state = "medcoffee" + name = "Lifeline" + desc = "Some days, the only thing that keeps you going is cryo and caffeine." + if("detcoffee") + icon_state = "detcoffee" + name = "Joe" + desc = "The lights, the smoke, the grime, the station itself felt alive that day as I stepped into my office, mug in hand. It was another one of those days. Some Nurse got smoked in one of the tunnels, and it came down to me to catch the guy did it. I got up to close the blinds of my office, when an officer burst through my door. There had been another one offed in the tunnels, this time an assistant. I grumbled and downed some of my joe. It was bitter, tasteless, but it was what kept me going. I remember back when I was a rookie, this stuff used to taste so great to me. I guess that's just another sign of how this station changes people. I put my mug back down on my desk, dusted off my jacket, and lit my last cigar. I checked to make sure my faithful revolver was loaded, and stepped out, back into the cold halls of the station." + if("etank") + icon_state = "etank" + name = "Recharger" + desc = "Helps you get back on your feet after a long day of robot maintenance. Can also be used as a substitute for motor oil." + if("greytea") + icon_state = "greytea" + name = "Tide" + desc = "This probably shouldn't be considered tea..." + + + + + + else + icon_state ="mug_what" + name = "mug of ..something?" + desc = "You aren't really sure what this is." + else + icon_state = "mug_empty" + name = "mug" + desc = "A simple mug." return \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/food/drinks/jar.dm b/code/modules/reagents/reagent_containers/food/drinks/jar.dm index 9231da36ed4..6bb42f4e4ce 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/jar.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/jar.dm @@ -1,32 +1,32 @@ - - -///jar - -/obj/item/weapon/reagent_containers/food/drinks/jar - name = "empty jar" - desc = "A jar. You're not sure what it's supposed to hold." - icon_state = "jar" - item_state = "beaker" - starting_materials = list(MAT_GLASS = 500) - melt_temperature = MELTPOINT_GLASS - w_type=RECYK_GLASS - New() - ..() - reagents.add_reagent("slimejelly", 50) - - on_reagent_change() - if (reagents.reagent_list.len > 0) - switch(reagents.get_master_reagent_id()) - if("slime") - icon_state = "jar_slime" - name = "slime jam" - desc = "A jar of slime jam. Delicious!" - else - icon_state ="jar_what" - name = "jar of something" - desc = "You can't really tell what this is." - else - icon_state = "jar" - name = "empty jar" - desc = "A jar. You're not sure what it's supposed to hold." - return + + +///jar + +/obj/item/weapon/reagent_containers/food/drinks/jar + name = "empty jar" + desc = "A jar. You're not sure what it's supposed to hold." + icon_state = "jar" + item_state = "beaker" + starting_materials = list(MAT_GLASS = 500) + melt_temperature = MELTPOINT_GLASS + w_type=RECYK_GLASS + New() + ..() + reagents.add_reagent("slimejelly", 50) + + on_reagent_change() + if (reagents.reagent_list.len > 0) + switch(reagents.get_master_reagent_id()) + if("slime") + icon_state = "jar_slime" + name = "slime jam" + desc = "A jar of slime jam. Delicious!" + else + icon_state ="jar_what" + name = "jar of something" + desc = "You can't really tell what this is." + else + icon_state = "jar" + name = "empty jar" + desc = "A jar. You're not sure what it's supposed to hold." + return diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 06fa03382e0..bf222aa3a42 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -1,3931 +1,3931 @@ -//Food items that are eaten normally and don't leave anything behind. - -/obj/item/weapon/reagent_containers/food/snacks - name = "snack" - desc = "yummy" - icon = 'icons/obj/food.dmi' - icon_state = null - log_reagents = 1 - - var/food_flags //Possible flags: FOOD_LIQUID, FOOD_MEAT, FOOD_ANIMAL, FOOD_SWEET - //FOOD_LIQUID - for stuff like soups - //FOOD_MEAT - stuff that is made from (or contains) meat. Anything that vegetarians won't eat! - //FOOD_ANIMAL - stuff that is made from (or contains) animal products other than meat (eggs, honey, ...). Anything that vegans won't eat! - //FOOD_SWEET - sweet stuff like chocolate and candy - - //Example: food_flags = FOOD_SWEET | FOOD_ANIMAL - //Unfortunately, food created by cooking doesn't inherit food_flags! - - var/bitesize = 1 //How much reagents per bite (and thus how fast is the food consumed ?) - var/bitecount = 0 //How much times was the item bitten ? - var/trash = null //What left-over should we spawn, if any ? - var/slice_path //What can we slice this item into, if anything ? - var/slices_num //How much slices should we expect ? - var/eatverb //How do I eat thing ? (Note : Used for message, "bite", "chew", etc...) - var/wrapped = 0 //Is the food wrapped (preventing one from eating until unwrapped) - var/dried_type = null //What can we dry the food into - var/deepfried = 0 //Is the food deep-fried ? - var/filling_color = "#FFFFFF" //What color would a filling of this item be ? - volume = 100 //Double amount snacks can carry, so that food prepared from excellent items can contain all the nutriments it deserves - -//Proc for effects that trigger on eating that aren't directly tied to the reagents. -/obj/item/weapon/reagent_containers/food/snacks/proc/On_Consume(var/mob/user, var/datum/reagents/reagentreference) - if(!user) - return - if(reagents) - reagentreference = reagents - if(!reagentreference || !reagentreference.total_volume) //Are we done eating (determined by the amount of reagents left, here 0) - user.visible_message("[user] finishes eating \the [src].", \ - "You finish eating \the [src].") - score["foodeaten"]++ //For post-round score - - //Drop our item before we delete it, to clear any references of ourselves in people's hands or whatever. - if(loc == user) - user.drop_from_inventory(src) - else if(ismob(loc)) - var/mob/holder = loc - holder.drop_from_inventory(src) - - if(trash) //Do we have somehing defined as trash for our snack item ? - //Note : This makes sense in some way, or at least this works, just don't mess with it - if(ispath(trash, /obj/item)) - var/obj/item/TrashItem = new trash(user) - user.put_in_hands(TrashItem) - else if(istype(trash, /obj/item)) - user.put_in_hands(trash) - - qdel(src) //Remove the item, we consumed it - - return - -/obj/item/weapon/reagent_containers/food/snacks/attack_self(mob/user) - - attack(user, user) //This is painful, but it works, I guess - return - -/obj/item/weapon/reagent_containers/food/snacks/New() - - ..() - -/obj/item/weapon/reagent_containers/food/snacks/attack(mob/living/M, mob/user, def_zone, eat_override = 0) //M is target of attack action, user is the one initiating it - if(!eatverb) - eatverb = pick("bite", "chew", "nibble", "gnaw", "gobble", "chomp") - if(!reagents.total_volume) //Are we done eating (determined by the amount of reagents left, here 0) - //This is mostly caused either by "persistent" food items or spamming - to_chat(user, "There's nothing left of \the [src]!") - M.drop_from_inventory(src) //Drop our item before we delete it - qdel(src) - return 0 - - if(istype(M, /mob/living/carbon)) //Avoid messing with simple mobs - var/mob/living/carbon/target = M //First definition to avoid colons - if(target == user) //If you're eating it yourself - //In that case, target is the user, but we'll still ask "target" to do things - if(!target.hasmouth) - to_chat(user, "You have no mouth to eat with")//Good luck figuring out how that would happen - - return 0 - var/fullness = target.nutrition + (target.reagents.get_reagent_amount("nutriment") * 25) //This reminds me how unlogical mob nutrition is - if(wrapped) - to_chat(target, "You can't eat wrapped food!") - return 0 - if (!eat_override && ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species.chem_flags & NO_EAT) - user.drop_from_inventory(src) - src.forceMove(get_turf(H)) - playsound(get_turf(H),'sound/items/eatfood.ogg', rand(10,50), 1) - H.visible_message("As [M] attempts to eat \the [src] it falls through and onto the ground as if untouched.", "As you attempt to eat \the [src] it falls through your body and onto the ground as if untouched.") - return 0 - if(fullness <= 50) - target.visible_message("[target] hungrily [eatverb]s some of \the [src] and gobbles it down!", \ - "You hungrily [eatverb] some of \the [src] and gobble it down!") - else if(fullness > 50 && fullness < 150) - target.visible_message("[target] hungrily [eatverb]s \the [src].", \ - "You hungrily [eatverb] \the [src].") - else if(fullness > 150 && fullness < 350) - target.visible_message("[target] [eatverb]s \the [src].", \ - "You [eatverb] \the [src].") - else if(fullness > 350 && fullness < 550) - target.visible_message("[target] unwillingly [eatverb]s some of \the [src].", \ - "You unwillingly [eatverb] some of \the [src].") - else if(fullness > (550 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat - to_chat(target, "You cannot force any more of \the [src] to go down your throat.") - return 0 - else //Feeding someone else, target is eating, user is feeding - if(target.hasmouth) - var/fullness = target.nutrition + (target.reagents.get_reagent_amount("nutriment") * 25) - if(wrapped) - to_chat(user, "The food is wrapped, you can't feed it to [target] like that!") - return 0 - if(fullness <= (550 * (1 + M.overeatduration / 1000))) //The mob will accept - target.visible_message("[user] attempts to feed [target] \the [src].", \ - "[user] attempts to feed you \the [src].") - else //The mob is overfed and will refuse - target.visible_message("[user] cannot force anymore of \the [src] down [target]'s throat!", \ - "[user] cannot force anymore of \the [src] down your throat!") - return 0 - - if(!do_mob(user, target)) - return - if (ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species.chem_flags & NO_EAT) - user.drop_from_inventory(src) - src.forceMove(get_turf(H)) - H.visible_message("As [user] attempts to feed [M] \the [src] it falls through and onto the ground as if untouched.", "As [user] attempts to feed you \the [src] it falls through your body and onto the ground as if untouched.") - return 0 - - add_logs(user, target, "fed", object="[reagentlist(src)]") - target.visible_message("[user] feeds [target] \the [src].", \ - "[user] feeds you \the [src].") - - else - to_chat(user, "[target] doesn't seem to have a mouth. Awkward!") - return - - var/datum/reagents/reagentreference = reagents //Even when the object is qdeleted, the reagents exist until this ref gets removed - if(reagentreference) //Handle ingestion of any reagents (Note : Foods always have reagents) - playsound(target.loc,'sound/items/eatfood.ogg', rand(10,50), 1) - if(reagentreference.total_volume) - reagentreference.reaction(target, INGEST) - spawn() //WHY IS THIS SPAWN() HERE - if(gcDestroyed) - return - if(reagentreference.total_volume > bitesize) - /* - * I totally cannot understand what this code supposed to do. - * Right now every snack consumes in 2 bites, my popcorn does not work right, so I simplify it. -- rastaf0 - var/temp_bitesize = max(reagents.total_volume /2, bitesize) - reagents.trans_to(target, temp_bitesize) - */ - reagentreference.trans_to(target, bitesize) - else - reagentreference.trans_to(target, reagentreference.total_volume) - bitecount++ - On_Consume(target, reagentreference) - return 1 - - return 0 - -/obj/item/weapon/reagent_containers/food/snacks/examine(mob/user) - ..() - if (bitecount) - if(bitecount == 1) - to_chat(user, "\The [src] was bitten by someone!") - else if(bitecount > 1 && bitecount <= 3) - to_chat(user, "\The [src] was bitten [bitecount] times!") - else - to_chat(user, "\The [src] was bitten multiple times!") - -/obj/item/weapon/reagent_containers/food/snacks/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/pen)) //Renaming food - var/n_name = copytext(sanitize(input(user, "What would you like to name this dish?", "Food Renaming", null) as text|null), 1, MAX_NAME_LEN*3) - if(n_name && Adjacent(user) && !user.stat) - name = "[n_name]" - return - if(istype(W, /obj/item/weapon/kitchen/utensil/fork)) - var/obj/item/weapon/kitchen/utensil/fork/fork = W - if(slices_num || slice_path) - to_chat(user, "You can't take the whole [src] at once!.") - return - else - return fork.load_food(src, user) - - if (..()) return - - if((slices_num <= 0 || !slices_num) || !slice_path) //If the food item isn't sliceable, we have no more business to do here, return - return 0 - - if(W.w_class <= 2 && W.is_sharp() < 0.8 && !istype(W,/obj/item/device/analyzer/plant_analyzer)) //Make sure the item is valid to attempt slipping shit into it - if(!iscarbon(user)) - return 0 - - if(user.drop_item(W, src)) - to_chat(user, "You slip \the [W] inside [src].") - - add_fingerprint(user) - contents += W - return 1 //No afterattack here - - if(W.is_sharp() < 0.8) //At this point we are slicing food, so if our item isn't sharp enough, just abort - return 0 - - if(!isturf(src.loc) || !(locate(/obj/structure/table) in src.loc) && !(locate(/obj/item/weapon/tray) in src.loc)) - to_chat(user, "You cannot slice \the [src] here! You need a table or at least a tray.") - return 1 - - var/slices_lost = 0 - if(W.is_sharp() >= 1.2) //Actually sharp things are this sharp, yes - user.visible_message("[user] slices \the [src].", \ - "You slice \the [src].") - else //We're above 0.8 //The magic threshold of pizza slicing - user.visible_message("[user] inaccurately slices \the [src] with \the [W]!", \ - "You inaccurately slice \the [src] with \the [W]!") - slices_lost = rand(1, min(1, round(slices_num/2))) //Randomly lose a few slices along the way, but at least one and up to half - var/reagents_per_slice = reagents.total_volume/slices_num //Figure out how much reagents each slice inherits (losing slices loses reagents) - for(var/i = 1 to (slices_num - slices_lost)) //Transfer those reagents - var/obj/slice = new slice_path(src.loc) - if(istype(src, /obj/item/weapon/reagent_containers/food/snacks/customizable)) //custom sliceable foods have overlays we need to apply - var/obj/item/weapon/reagent_containers/food/snacks/customizable/C = src - var/obj/item/weapon/reagent_containers/food/snacks/customizable/S = slice - S.name = "[C.name][S.name]" - S.filling.color = C.filling.color - S.overlays += S.filling - reagents.trans_to(slice, reagents_per_slice) - qdel(src) //So long and thanks for all the fish - return 1 - -/obj/item/weapon/reagent_containers/food/snacks/Destroy() - if(contents) //Did someone slip shit in the pizza again ? - for(var/atom/movable/surprise in contents) //Find it - surprise.loc = get_turf(src) //Recover it - ..() - -/obj/item/weapon/reagent_containers/food/snacks/attack_animal(mob/M) - if(isanimal(M)) - if(iscorgi(M)) //Feeding food to a corgi - M.delayNextAttack(10) - if(bitecount >= 4) //This really, really shouldn't be hardcoded like this, but sure I guess - M.visible_message("[M] [pick("burps from enjoyment", "yaps for more", "woofs twice", "looks at the area where \the [src] was")].", "You swallow up the last of \the [src].") - playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) - var/mob/living/simple_animal/corgi/C = M - if(C.health <= C.maxHealth + 5) - C.health += 5 - else - C.health = C.maxHealth - qdel(src) - else - M.visible_message("[M] takes a bite of \the [src].", "You take a bite of \the [src].") - playsound(src.loc,'sound/items/eatfood.ogg', rand(10, 50), 1) - bitecount++ - else if(ismouse(M)) //Mouse eating shit - M.delayNextAttack(10) - var/mob/living/simple_animal/mouse/N = M - if(prob(25)) //We are noticed - N.visible_message("[N] nibbles away at \the [src].", "You nibble away at \the [src]") - else - to_chat(N, ("You nibble away at \the [src].")) - N.health = min(N.health + 1, N.maxHealth) - - -//////////////////////////////////////////////////////////////////////////////// -/// FOOD END -//////////////////////////////////////////////////////////////////////////////// - - - -////////////////////////////////////////////////// -////////////////////////////////////////////Snacks -////////////////////////////////////////////////// -//Items in the "Snacks" subcategory are food items that people actually eat. The key points are that they are created -// already filled with reagents and are destroyed when empty. Additionally, they make a "munching" noise when eaten. - -//Notes by Darem: Food in the "snacks" subtype can hold a maximum of 50 units Generally speaking, you don't want to go over 40 -// total for the item because you want to leave space for extra condiments. If you want effect besides healing, add a reagent for -// it. Try to stick to existing reagents when possible (so if you want a stronger healing effect, just use Tricordrazine). On use -// effect (such as the old officer eating a donut code) requires a unique reagent (unless you can figure out a better way). - -//The nutriment reagent and bitesize variable replace the old heal_amt and amount variables. Each unit of nutriment is equal to -// 2 of the old heal_amt variable. Bitesize is the rate at which the reagents are consumed. So if you have 6 nutriment and a -// bitesize of 2, then it'll take 3 bites to eat. Unlike the old system, the contained reagents are evenly spread among all -// the bites. No more contained reagents = no more bites. - -//Here is an example of the new formatting for anyone who wants to add more food items. -///obj/item/weapon/reagent_containers/food/snacks/xenoburger //Identification path for the object. -// name = "Xenoburger" //Name that displays in the UI. -// desc = "Smells caustic. Tastes like heresy." //Duh -// icon_state = "xburger" //Refers to an icon in food.dmi -// food_flags = FOOD_MEAT //For flavour, not that important. Flags are: FOOD_MEAT, FOOD_ANIMAL (for things that vegans don't eat), FOOD_SWEET, FOOD_LIQUID (soups). You can have multiple flags in here by doing this: food_flags = FOOD_MEAT | FOOD_SWEET -// -// New() //Don't mess with this. -// ..() //Same here. -// reagents.add_reagent("xenomicrobes", 10) //This is what is in the food item. you may copy/paste -// reagents.add_reagent("nutriment", 2) // this line of code for all the contents. -// bitesize = 3 //This is the amount each bite consumes. - - - - -/obj/item/weapon/reagent_containers/food/snacks/aesirsalad - name = "Aesir salad" - desc = "Probably too incredible for mortal men to fully enjoy." - icon_state = "aesirsalad" - trash = /obj/item/trash/snack_bowl - New() - ..() - eatverb = pick("crunch", "devour", "nibble", "gnaw", "gobble", "chomp") - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("tricordrazine", 8) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/candy - name = "candy" - desc = "Nougat love it or hate it." - icon_state = "candy" - trash = /obj/item/trash/candy - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("sugar", 3) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/candy/donor - name = "Donor Candy" - desc = "A little treat for blood donors." - trash = /obj/item/trash/candy - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 10) - reagents.add_reagent("sugar", 3) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/candy_corn - name = "candy corn" - desc = "It's a handful of candy corn. Can be stored in a detective's hat." - icon_state = "candy_corn" - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("sugar", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cookie - name = "cookie" - desc = "COOKIE!!!" - icon_state = "COOKIE!!!" - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chocolatebar - name = "chocolate bar" - desc = "Such, sweet, fattening food." - icon_state = "chocolatebarunwrapped" - wrapped = 0 - bitesize = 2 - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("sugar", 5) - reagents.add_reagent("coco", 5) - - attack_self(mob/user) - if(wrapped) - Unwrap(user) - else - ..() - -/obj/item/weapon/reagent_containers/food/snacks/chocolatebar/proc/Unwrap(mob/user) - icon_state = "chocolatebarunwrapped" - desc = "It won't make you all sticky." - to_chat(user, "You remove the foil.") - wrapped = 0 - - -/obj/item/weapon/reagent_containers/food/snacks/chocolatebar/wrapped - desc = "It's wrapped in some foil." - icon_state = "chocolatebar" - wrapped = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chocolateegg - name = "chocolate egg" - desc = "Such, sweet, fattening food." - icon_state = "chocolateegg" - food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs are used - - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("sugar", 2) - reagents.add_reagent("coco", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/donut - name = "donut" - desc = "Goes great with Robust Coffee." - icon_state = "donut1" - food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs are used - -/obj/item/weapon/reagent_containers/food/snacks/donut/normal - name = "donut" - desc = "Goes great with Robust Coffee." - icon_state = "donut1" - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("sprinkles", 1) - src.bitesize = 3 - if(prob(30)) - src.icon_state = "donut2" - src.name = "frosted donut" - reagents.add_reagent("sprinkles", 2) - -/obj/item/weapon/reagent_containers/food/snacks/donut/chaos - name = "Chaos Donut" - desc = "Like life, it never quite tastes the same." - icon_state = "donut1" - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("sprinkles", 1) - bitesize = 10 - switch(rand(1,10)) - if(1) - reagents.add_reagent("nutriment", 3) - if(2) - reagents.add_reagent("capsaicin", 3) - if(3) - reagents.add_reagent("frostoil", 3) - if(4) - reagents.add_reagent("sprinkles", 3) - if(5) - reagents.add_reagent("plasma", 3) - if(6) - reagents.add_reagent("coco", 3) - if(7) - reagents.add_reagent("slimejelly", 3) - if(8) - reagents.add_reagent("banana", 3) - if(9) - reagents.add_reagent("berryjuice", 3) - if(10) - reagents.add_reagent("tricordrazine", 3) - if(prob(30)) - icon_state = "donut2" - name = "frosted chaos donut" - reagents.add_reagent("sprinkles", 2) - - -/obj/item/weapon/reagent_containers/food/snacks/donut/jelly - name = "jelly donut" - desc = "You jelly?" - icon_state = "jdonut1" - bitesize = 5 - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("sprinkles", 1) - reagents.add_reagent("berryjuice", 5) - if(prob(30)) - icon_state = "jdonut2" - name = "Frosted Jelly Donut" - reagents.add_reagent("sprinkles", 2) - -/obj/item/weapon/reagent_containers/food/snacks/donut/slimejelly - name = "jelly donut" - desc = "You jelly?" - icon_state = "jdonut1" - bitesize = 5 - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("sprinkles", 1) - reagents.add_reagent("slimejelly", 5) - bitesize = 5 - if(prob(30)) - icon_state = "jdonut2" - name = "Frosted Jelly Donut" - reagents.add_reagent("sprinkles", 2) - -/obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly - name = "jelly donut" - desc = "You jelly?" - icon_state = "jdonut1" - bitesize = 5 - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("sprinkles", 1) - reagents.add_reagent("cherryjelly", 5) - if(prob(30)) - icon_state = "jdonut2" - name = "Frosted Jelly Donut" - reagents.add_reagent("sprinkles", 2) - -// Eggs - -/obj/item/weapon/reagent_containers/food/snacks/friedegg - name = "fried egg" - desc = "A fried egg, with a touch of salt and pepper." - icon_state = "friedegg" - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("sodiumchloride", 1) - reagents.add_reagent("blackpepper", 1) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/boiledegg - name = "boiled egg" - desc = "A hard boiled egg." - icon_state = "egg" - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 2) - -/obj/item/weapon/reagent_containers/food/snacks/organ - name = "organ" - desc = "It's good for you." - icon = 'icons/obj/surgery.dmi' - icon_state = "appendix" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", rand(3,5)) - reagents.add_reagent("toxin", rand(1,3)) - src.bitesize = 3 - - -/obj/item/weapon/reagent_containers/food/snacks/tofu - name = "Tofu" - icon_state = "tofu" - desc = "We all love tofu." - New() - ..() - reagents.add_reagent("nutriment", 3) - src.bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/tofurkey - name = "Tofurkey" - desc = "A fake turkey made from tofu." - icon_state = "tofurkey" - New() - ..() - reagents.add_reagent("nutriment", 12) - reagents.add_reagent("stoxin", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/stuffing - name = "Stuffing" - desc = "Moist, peppery breadcrumbs for filling the body cavities of dead birds. Dig in!" - icon_state = "stuffing" - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/fishfingers - name = "fish fingers" - desc = "A finger of fish." - icon_state = "fishfingers" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("carppheromones", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice - name = "huge mushroom slice" - desc = "A slice from a huge mushroom." - icon_state = "hugemushroomslice" - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("psilocybin", 3) - src.bitesize = 6 - -/obj/item/weapon/reagent_containers/food/snacks/tomatomeat - name = "tomato slice" - desc = "A slice from a huge tomato" - icon_state = "tomatomeat" - New() - ..() - reagents.add_reagent("nutriment", 3) - src.bitesize = 6 - -/obj/item/weapon/reagent_containers/food/snacks/meat/spiderleg - name = "spider leg" - desc = "A still twitching leg of a giant spider... you don't really want to eat this, do you?" - icon_state = "spiderleg" - food_flags = FOOD_MEAT - New() - ..() - poisonsacs = new /obj/item/weapon/reagent_containers/food/snacks/spiderpoisongland - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("toxin", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/faggot - name = "faggot" - desc = "A great meal all round. Not a cord of wood." - icon_state = "faggot" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sausage - name = "sausage" - desc = "A piece of mixed, long meat." - icon_state = "sausage" - food_flags = FOOD_MEAT - - New() - ..() - eatverb = pick("bite","chew","nibble","deep throat","gobble","chomp") - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/donkpocket - name = "\improper Donk-pocket" - desc = "The food of choice for the seasoned traitor." - icon_state = "donkpocket" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 4) - - var/warm = 0 - proc/cooltime() //Not working, derp? - if(warm) - spawn(4200) //ew - warm = 0 - reagents.del_reagent("tricordrazine") - name = initial(name) - return - -/obj/item/weapon/reagent_containers/food/snacks/brainburger - name = "brainburger" - desc = "A strange looking burger. It looks almost sentient." - icon_state = "brainburger" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("alkysine", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/ghostburger - name = "ghost burger" - desc = "Spooky! It doesn't look very filling." - icon_state = "ghostburger" - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/human - var/hname = "" - var/job = null - - - name = "-burger" - desc = "A bloody burger." - icon_state = "hburger" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/monkeyburger - name = "burger" - desc = "The cornerstone of every nutritious breakfast." - icon_state = "hburger" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/monkeyburger/synth - name = "synthetic burger" - desc = "It tastes like a normal burger, but it's just not the same." - icon_state = "hburger" - New() - ..() - reagents.add_reagent("nutriment", 6) - -/obj/item/weapon/reagent_containers/food/snacks/appendixburger - name = "appendix burger" - desc = "Tastes like appendicitis." - icon_state = "hburger" - food_flags = FOOD_MEAT - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/fishburger - name = "fillet -o- carp sandwich" - desc = "Almost like a carp is yelling somewhere... Give me back that fillet -o- carp, give me that carp." - icon_state = "fishburger" - food_flags = FOOD_MEAT - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("carppheromones", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/tofuburger - name = "tofu burger" - desc = "What.. is that meat?" - icon_state = "tofuburger" - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/chickenburger - name = "chicken burger" - desc = "Tastes like chi...oh wait!" - icon_state = "mc_chicken" - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/chickenburger/New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/roburger - name = "roburger" - desc = "The lettuce is the only organic component. Beep." - icon_state = "roburger" - New() - ..() - reagents.add_reagent("nanites", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/roburgerbig - name = "roburger" - desc = "This massive patty looks like poison. Beep." - icon_state = "roburger" - volume = 100 - New() - ..() - reagents.add_reagent("nanites", 100) - bitesize = 0.1 - -/obj/item/weapon/reagent_containers/food/snacks/xenoburger - name = "xenoburger" - desc = "Smells caustic. Tastes like heresy." - icon_state = "xburger" - food_flags = FOOD_MEAT - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/clownburger - name = "clown burger" - desc = "This tastes funny..." - icon_state = "clownburger" - New() - ..() -/* - var/datum/disease/F = new /datum/disease/pierrot_throat(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 4, data) -*/ - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/mimeburger - name = "mime burger" - desc = "Its taste defies language." - icon_state = "mimeburger" - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/omelette //FUCK THIS - name = "omelette du fromage" - desc = "That's all you can say!" - icon_state = "omelette" - food_flags = FOOD_ANIMAL //made from eggs - trash = /obj/item/trash/plate - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/muffin - name = "muffin" - desc = "A delicious and spongy little cake." - icon_state = "muffin" - food_flags = FOOD_SWEET | FOOD_ANIMAL - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/muffin/berry - name = "berry muffin" - icon_state = "berrymuffin" - desc = "A delicious and spongy little cake, with berries." - -/obj/item/weapon/reagent_containers/food/snacks/muffin/booberry - name = "booberry muffin" - icon_state = "booberrymuffin" - desc = "My stomach is a graveyard! No living being can quench my bloodthirst!" - -/obj/item/weapon/reagent_containers/food/snacks/muffin/dindumuffin - name = "Dindu Muffin" - desc = "This muffin didn't do anything." - icon_state = "dindumuffins" - -/obj/item/weapon/reagent_containers/food/snacks/pie - name = "banana cream pie" - desc = "Just like back home, on clown planet! HONK!" - icon_state = "pie" - trash = /obj/item/trash/pietin - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("banana",5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/pie/throw_impact(atom/hit_atom) - ..() - if(isturf(hit_atom)) - new/obj/effect/decal/cleanable/pie_smudge(src.loc) - if(trash) new trash(src.loc) - qdel(src) - -/obj/item/weapon/reagent_containers/food/snacks/pie/empty //so the H.O.N.K. cream pie mortar can't generate free nutriment - trash = null - New() - ..() - reagents.clear_reagents() - -/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis - name = "berry clafoutis" - desc = "No black birds, this is a good sign." - icon_state = "berryclafoutis" - trash = /obj/item/trash/plate - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("berryjuice", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/waffles - name = "waffles" - desc = "Mmm, waffles" - icon_state = "waffles" - trash = /obj/item/trash/waffles - food_flags = FOOD_ANIMAL - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/eggplantparm - name = "Eggplant Parmigiana" - desc = "The only good recipe for eggplant." - icon_state = "eggplantparm" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/soylentgreen - name = "Soylent Green" - desc = "Not made of people. Honest." //Totally people. - icon_state = "soylent_green" - trash = /obj/item/trash/waffles - New() - ..() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/soylenviridians - name = "Soylen Virdians" - desc = "Not made of people. Honest." //Actually honest for once. - icon_state = "soylent_yellow" - trash = /obj/item/trash/waffles - New() - ..() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/pie/discount - name = "Discount Pie" - icon_state = "meatpie" - desc = "Regulatory laws prevent us from lying to you in the technical sense, so you know this has to contain at least some meat!" - food_flags = FOOD_MEAT - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment",2) - reagents.add_reagent("discount",2) - reagents.add_reagent("toxin",2) - reagents.add_reagent("sugar",4) - -/obj/item/weapon/reagent_containers/food/snacks/pie/meatpie - name = "Meat-pie" - icon_state = "meatpie" - desc = "An old barber recipe, very delicious!" - food_flags = FOOD_MEAT - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/pie/tofupie - name = "Tofu-pie" - icon_state = "meatpie" - desc = "A delicious tofu pie." - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/pie/amanita_pie - name = "amanita pie" - desc = "Sweet and tasty poison pie." - icon_state = "amanita_pie" - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("amatoxin", 3) - reagents.add_reagent("psilocybin", 1) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/pie/plump_pie - name = "plump pie" - desc = "I bet you love stuff made out of plump helmets!" - icon_state = "plump_pie" - New() - ..() - reagents.clear_reagents() - if(prob(10)) - name = "exceptional plump pie" - desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!" - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("tricordrazine", 5) - bitesize = 2 - else - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/pie/xemeatpie - name = "Xeno-pie" - icon_state = "xenomeatpie" - desc = "A delicious meatpie. Probably heretical." - food_flags = FOOD_MEAT - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/wingfangchu - name = "Wing Fang Chu" - desc = "A savory dish of alien wing wang in soy." - icon_state = "wingfangchu" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/human/kabob - name = "-kabob" - icon_state = "kabob" - desc = "A human meat, on a stick." - trash = /obj/item/stack/rods - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/monkeykabob - name = "Meat-kabob" - icon_state = "kabob" - desc = "Delicious meat, on a stick." - trash = /obj/item/stack/rods - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/monkeykabob/synth - name = "Synth-kabob" - icon_state = "kabob" - desc = "Synthetic meat, on a stick." - trash = /obj/item/stack/rods - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/corgikabob - name = "Corgi-kabob" - icon_state = "kabob" - desc = "Only someone without a heart could make this." - trash = /obj/item/stack/rods - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/tofukabob - name = "Tofu-kabob" - icon_state = "kabob" - desc = "Vegan meat, on a stick." - trash = /obj/item/stack/rods - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cubancarp - name = "Cuban Carp" - desc = "A grifftastic sandwich that burns your tongue and then leaves it numb!" - icon_state = "cubancarp" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("carppheromones", 3) - reagents.add_reagent("capsaicin", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/popcorn - name = "popcorn" - desc = "Now let's find some cinema." - icon_state = "popcorn" - trash = /obj/item/trash/popcorn - var/unpopped = 0 - -/obj/item/weapon/reagent_containers/food/snacks/popcorn/New() - ..() - eatverb = pick("bite","crunch","nibble","gnaw","gobble","chomp") - unpopped = rand(1,10) - reagents.add_reagent("nutriment", 2) - bitesize = 0.1 //this snack is supposed to be eating during looooong time. And this it not dinner food! --rastaf0 - -/obj/item/weapon/reagent_containers/food/snacks/popcorn/On_Consume() - if(prob(unpopped)) //lol ...what's the point? << AINT SO POINTLESS NO MORE - to_chat(usr, "You bite down on an un-popped kernel, and it hurts your teeth!") - unpopped = max(0, unpopped-1) - reagents.add_reagent("sacid", 0.1) //only a little tingle. - - -/obj/item/weapon/reagent_containers/food/snacks/sosjerky - name = "\improper Scaredy's Private Reserve Beef Jerky" - icon_state = "sosjerky" - desc = "Beef jerky made from the finest space cows." - trash = /obj/item/trash/sosjerky - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 4) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/no_raisin - name = "4no raisins" - icon_state = "4no_raisins" - desc = "Best raisins in the universe. Not sure why." - trash = /obj/item/trash/raisins - New() - ..() - reagents.add_reagent("nutriment", 6) - -/obj/item/weapon/reagent_containers/food/snacks/bustanuts - name = "Busta-Nuts" - icon_state = "busta_nut" - desc = "2hard4u" - trash = /obj/item/trash/bustanuts - New() - ..() - reagents.add_reagent("bustanut", 6) - reagents.add_reagent("sodiumchloride", 6) - -/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie - name = "space twinkie" - icon_state = "space_twinkie" - desc = "Guaranteed to survive longer than you will." - New() - ..() - reagents.add_reagent("sugar", 4) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers - name = "Cheesie Honkers" - icon_state = "cheesie_honkers" - desc = "Bite sized cheesie snacks that will honk all over your mouth" - trash = /obj/item/trash/cheesie - food_flags = FOOD_ANIMAL //cheese - - New() - ..() - reagents.add_reagent("nutriment", 4) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/syndicake - name = "Syndi-Cakes" - icon_state = "syndi_cakes" - desc = "An extremely moist snack cake that tastes just as good after being nuked." - trash = /obj/item/trash/syndi_cakes - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("doctorsdelight", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/discountchocolate - name = "\improper Discount Dan's Chocolate Bar" - desc = "Something tells you that the glowing green filling inside, isn't healthy." - icon_state = "danbar" - trash = /obj/item/trash/discountchocolate - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("discount", 4) - reagents.add_reagent("moonrocks", 4) - reagents.add_reagent("toxicwaste", 8) - reagents.add_reagent("chemical_waste", 2) //Does nothing, but it's pretty fucking funny. - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/discountburger - name = "\improper Discount Dan's On The Go Burger" - desc = "Its still warm..." - icon_state = "goburger" //Someone make a better sprite for this. - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("discount", 4) - reagents.add_reagent("beff", 4) - reagents.add_reagent("horsemeat", 4) - reagents.add_reagent("offcolorcheese", 4) - reagents.add_reagent("chemical_waste", 2) //Does nothing, but it's pretty fucking funny. - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/danitos - name = "Danitos" - desc = "For only the most MLG hardcore robust spessmen." - icon_state = "danitos" - trash = /obj/item/trash/danitos - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("discount", 4) - reagents.add_reagent("bonemarrow", 4) - reagents.add_reagent("toxicwaste", 8) - reagents.add_reagent("bustanut", 2) //YOU FEELIN HARDCORE BRAH? - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/discountburrito - name = "Discount Dan's Burritos" - desc = "The perfect blend of cheap processing and cheap materials." - icon_state = "danburrito" - var/list/ddname = list("Spooky Dan's BOO-ritos - Texas Toast Chainsaw Massacre Flavor","Sconto Danilo's Burritos - 50% Real Mozzarella Pepperoni Pizza Party Flavor","Descuento Danito's Burritos - Pancake Sausage Brunch Flavor","Descuento Danito's Burritos - Homestyle Comfort Flavor","Spooky Dan's BOO-ritos - Nightmare on Elm Meat Flavor","Descuento Danito's Burritos - Strawberrito Churro Flavor","Descuento Danito's Burritos - Beff and Bean Flavor") - food_flags = FOOD_MEAT - - New() - ..() - name = pick(ddname) - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("discount", 6) - reagents.add_reagent("irradiatedbeans", 4) - reagents.add_reagent("refriedbeans", 4) - reagents.add_reagent("mutatedbeans", 4) - reagents.add_reagent("beff", 4) - reagents.add_reagent("chemical_waste", 2) //Does nothing, but it's pretty fucking funny. - bitesize = 2 - - - -/obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato - name = "Loaded Baked Potato" - desc = "Totally baked." - icon_state = "loadedbakedpotato" - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/fries - name = "Space Fries" - desc = "AKA: French Fries, Freedom Fries, etc" - icon_state = "fries" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 4) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/soydope - name = "Soy Dope" - desc = "Dope from a soy." - icon_state = "soydope" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/spaghetti - name = "Spaghetti" - desc = "Now thats a nice pasta!" - icon_state = "spaghetti" - New() - ..() - reagents.add_reagent("nutriment", 1) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/cheesyfries - name = "Cheesy Fries" - desc = "Fries. Covered in cheese. Duh." - icon_state = "cheesyfries" - trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //cheese - - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/fortunecookie - name = "Fortune cookie" - desc = "A true prophecy in each cookie!" - icon_state = "fortune_cookie" - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/badrecipe - name = "Burned mess" - desc = "Someone should be demoted from chef for this." - icon_state = "badrecipe" - New() - ..() - reagents.add_reagent("toxin", 1) - reagents.add_reagent("carbon", 3) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/meatsteak - name = "Meat steak" - desc = "A piece of hot spicy meat." - icon_state = "meatstake" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("sodiumchloride", 1) - reagents.add_reagent("blackpepper", 1) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/meatsteak/synth - name = "Synthmeat steak" - desc = "It's still a delicious steak, but it has no soul." - icon_state = "meatstake" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("sodiumchloride", 1) - reagents.add_reagent("blackpepper", 1) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/spacylibertyduff - name = "Spacy Liberty Duff" - desc = "Jello gelatin, from Alfred Hubbard's cookbook" - icon_state = "spacylibertyduff" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("psilocybin", 6) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/amanitajelly - name = "Amanita Jelly" - desc = "Looks curiously toxic" - icon_state = "amanitajelly" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("amatoxin", 6) - reagents.add_reagent("psilocybin", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/poppypretzel - name = "Poppy pretzel" - desc = "It's all twisted up!" - icon_state = "poppypretzel" - bitesize = 2 - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/meatballsoup - name = "Meatball soup" - desc = "You've got balls kid, BALLS!" - icon_state = "meatballsoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_MEAT | FOOD_LIQUID - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("water", 5) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/slimesoup - name = "slime soup" - desc = "If no water is available, you may substitute tears." - icon_state = "slimesoup" - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("slimejelly", 5) - reagents.add_reagent("water", 10) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/bloodsoup - name = "Tomato soup" - desc = "Smells like copper" - icon_state = "tomatosoup" - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("blood", 10) - reagents.add_reagent("water", 5) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/clownstears - name = "Clown's Tears" - desc = "Not very funny." - icon_state = "clownstears" - food_flags = FOOD_LIQUID | FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("banana", 5) - reagents.add_reagent("water", 10) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/vegetablesoup - name = "Vegetable soup" - desc = "A true vegan meal." //TODO - icon_state = "vegetablesoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("water", 5) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/nettlesoup - name = "Nettle soup" - desc = "To think, the botanist would've beat you to death with one of these." - icon_state = "nettlesoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("water", 5) - reagents.add_reagent("tricordrazine", 5) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/mysterysoup - name = "Mystery soup" - desc = "The mystery is, why aren't you eating it?" - icon_state = "mysterysoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - var/mysteryselect = pick(1,2,3,4,5,6,7,8,9,10) - switch(mysteryselect) - if(1) - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("capsaicin", 3) - reagents.add_reagent("tomatojuice", 2) - if(2) - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("frostoil", 3) - reagents.add_reagent("tomatojuice", 2) - if(3) - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("water", 5) - reagents.add_reagent("tricordrazine", 5) - if(4) - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("water", 10) - if(5) - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("banana", 10) - if(6) - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("blood", 10) - food_flags |= FOOD_MEAT - if(7) - reagents.add_reagent("slimejelly", 10) - reagents.add_reagent("water", 10) - if(8) - reagents.add_reagent("carbon", 10) - reagents.add_reagent("toxin", 10) - if(9) - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("tomatojuice", 10) - if(10) - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("tomatojuice", 5) - reagents.add_reagent("imidazoline", 5) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/wishsoup - name = "Wish Soup" - desc = "I wish this was soup." - icon_state = "wishsoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("water", 10) - bitesize = 5 - if(prob(25)) - src.desc = "A wish come true!" - reagents.add_reagent("nutriment", 8) - -/obj/item/weapon/reagent_containers/food/snacks/hotchili - name = "Hot Chili" - desc = "A five alarm Texan Chili!" - icon_state = "hotchili" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("capsaicin", 3) - reagents.add_reagent("tomatojuice", 2) - bitesize = 5 - - -/obj/item/weapon/reagent_containers/food/snacks/coldchili - name = "Cold Chili" - desc = "This slush is barely a liquid!" - icon_state = "coldchili" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("frostoil", 3) - reagents.add_reagent("tomatojuice", 2) - bitesize = 5 - -/* No more of this -/obj/item/weapon/reagent_containers/food/snacks/telebacon - name = "Tele Bacon" - desc = "It tastes a little odd but it is still delicious." - icon_state = "bacon" - var/obj/item/beacon/bacon/baconbeacon - bitesize = 2 - New() - ..() - reagents.add_reagent("nutriment", 4) - baconbeacon = new /obj/item/beacon/bacon(src) - On_Consume() - if(!reagents.total_volume) - baconbeacon.loc = usr - baconbeacon.digest_delay() -*/ - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube - name = "monkey cube" - desc = "Just add water!" - icon_state = "monkeycube" - bitesize = 12 - //var/wrapped = 0 - food_flags = FOOD_MEAT - - var/monkey_type = /mob/living/carbon/monkey - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/New() - ..() - reagents.add_reagent("nutriment",10) - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/afterattack(obj/O, mob/user,proximity) - if(!proximity) return - if(istype(O,/obj/structure/sink) && !wrapped) - to_chat(user, "You place [src] under a stream of water...") - return Expand() - ..() - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/attack_self(mob/user) - if(wrapped) - Unwrap(user) - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/On_Consume(var/mob/M) - - to_chat(M, "Something inside of you suddently expands!") - - if (istype(M, /mob/living/carbon/human)) - //Do not try to understand. - var/obj/item/weapon/surprise = new/obj/item/weapon(M) - var/mob/living/carbon/monkey/ook = new monkey_type(null) //no other way to get access to the vars, alas - surprise.icon = ook.icon - surprise.icon_state = ook.icon_state - surprise.name = "malformed [ook.name]" - surprise.desc = "Looks like \a very deformed [ook.name], a little small for its kind. It shows no signs of life." - qdel(ook) //rip nullspace monkey - surprise.transform *= 0.6 - surprise.add_blood(M) - var/mob/living/carbon/human/H = M - var/datum/organ/external/E = H.get_organ("chest") - E.fracture() - for (var/datum/organ/internal/I in E.internal_organs) - I.take_damage(rand(I.min_bruised_damage, I.min_broken_damage+1)) - - if (!E.hidden && prob(60)) //set it snuggly - E.hidden = surprise - E.cavity = 0 - else //someone is having a bad day - E.createwound(CUT, 30) - E.embed(surprise) - else if (ismonkey(M)) - M.visible_message("[M] suddenly tears in half!") - var/mob/living/carbon/monkey/ook = new monkey_type(M.loc) - ook.name = "malformed [ook.name]" - ook.transform *= 0.6 - ook.add_blood(M) - M.gib() - ..() - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Expand() - - for(var/mob/M in viewers(src,7)) - to_chat(M, "\The [src] expands!") - new monkey_type(get_turf(src)) - qdel(src) - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Unwrap(mob/user as mob) - - icon_state = "monkeycube" - desc = "Just add water!" - to_chat(user, "You unwrap the cube.") - wrapped = 0 - return - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped - desc = "Still wrapped in some paper." - icon_state = "monkeycubewrap" - wrapped = 1 - - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/farwacube - name = "farwa cube" - monkey_type =/mob/living/carbon/monkey/tajara -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube - name = "farwa cube" - monkey_type =/mob/living/carbon/monkey/tajara - - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/stokcube - name = "stok cube" - monkey_type =/mob/living/carbon/monkey/unathi -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube - name = "stok cube" - monkey_type =/mob/living/carbon/monkey/unathi - - -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/neaeracube - name = "neaera cube" - monkey_type =/mob/living/carbon/monkey/skrell -/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube - name = "neaera cube" - monkey_type =/mob/living/carbon/monkey/skrell - - -/obj/item/weapon/reagent_containers/food/snacks/spellburger - name = "Spell Burger" - desc = "This is absolutely Ei Nath." - icon_state = "spellburger" - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/bigbiteburger - name = "Big Bite Burger" - desc = "Forget the Big Mac. THIS is the future!" - icon_state = "bigbiteburger" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 14) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/enchiladas - name = "Enchiladas" - desc = "Viva La Mexico!" - icon_state = "enchiladas" - trash = /obj/item/trash/tray - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment",8) - reagents.add_reagent("capsaicin", 6) - bitesize = 4 - -/obj/item/weapon/reagent_containers/food/snacks/monkeysdelight - name = "monkey's Delight" - desc = "Eeee Eee!" - icon_state = "monkeysdelight" - trash = /obj/item/trash/tray - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 10) - reagents.add_reagent("banana", 5) - reagents.add_reagent("blackpepper", 1) - reagents.add_reagent("sodiumchloride", 1) - bitesize = 6 - -/obj/item/weapon/reagent_containers/food/snacks/baguette - name = "Baguette" - desc = "Bon appetit!" - icon_state = "baguette" - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("blackpepper", 1) - reagents.add_reagent("sodiumchloride", 1) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/fishandchips - name = "Fish and Chips" - desc = "I do say so myself chap." - icon_state = "fishandchips" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("carppheromones", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/sandwich - name = "Sandwich" - desc = "A grand creation of meat, cheese, bread, and several leaves of lettuce! Arthur Dent would be proud." - icon_state = "sandwich" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/toastedsandwich - name = "Toasted Sandwich" - desc = "Now if you only had a pepper bar." - icon_state = "toastedsandwich" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT //This is made from a sandwich, which contains meat! - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("carbon", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/grilledcheese - name = "Grilled Cheese Sandwich" - desc = "Goes great with Tomato soup!" - icon_state = "toastedsandwich" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 7) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/tomatosoup - name = "Tomato Soup" - desc = "Drinking this feels like being a vampire! A tomato vampire..." - icon_state = "tomatosoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("tomatojuice", 10) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/rofflewaffles - name = "Roffle Waffles" - desc = "Waffles from Roffle. Co." - icon_state = "rofflewaffles" - trash = /obj/item/trash/waffles - food_flags = FOOD_ANIMAL //eggs - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("psilocybin", 8) - bitesize = 4 - -/obj/item/weapon/reagent_containers/food/snacks/stew - name = "Stew" - desc = "A nice and warm stew. Healthy and strong." - icon_state = "stew" - food_flags = FOOD_LIQUID | FOOD_MEAT - - New() - ..() - eatverb = pick("slurp","sip","suck","inhale","drink") - reagents.add_reagent("nutriment", 10) - reagents.add_reagent("tomatojuice", 5) - reagents.add_reagent("imidazoline", 5) - reagents.add_reagent("water", 5) - bitesize = 10 - -/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast - name = "Jellied Toast" - desc = "A slice of bread covered with delicious jam." - icon_state = "jellytoast" - trash = /obj/item/trash/plate - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 1) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast/cherry - New() - ..() - reagents.add_reagent("cherryjelly", 5) - -/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast/slime - New() - ..() - reagents.add_reagent("slimejelly", 5) - -/obj/item/weapon/reagent_containers/food/snacks/jellyburger - name = "Jelly Burger" - desc = "Culinary delight..?" - icon_state = "jellyburger" - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/jellyburger/slime - New() - ..() - reagents.add_reagent("slimejelly", 5) - -/obj/item/weapon/reagent_containers/food/snacks/jellyburger/cherry - New() - ..() - reagents.add_reagent("cherryjelly", 5) - -/obj/item/weapon/reagent_containers/food/snacks/milosoup - name = "Milosoup" - desc = "The universes best soup! Yum!!!" - icon_state = "milosoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("water", 5) - bitesize = 4 - -/obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat - name = "Stewed Soy Meat" - desc = "Even non-vegetarians will LOVE this!" - icon_state = "stewedsoymeat" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/boiledspaghetti - name = "Boiled Spaghetti" - desc = "A plain dish of noodles, this sucks." - icon_state = "spaghettiboiled" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/boiledrice - name = "Boiled Rice" - desc = "A boring dish of boring rice." - icon_state = "boiledrice" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/ricepudding - name = "Rice Pudding" - desc = "Where's the Jam!" - icon_state = "rpudding" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 4) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/riceball - name = "Rice Ball" - desc = "In mining culture, this is also known as a donut." - icon_state = "riceball" - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/eggplantsushi - name = "Spicy Eggplant Sushi Rolls" - desc = "Eggplant rolls are an example of Asian Fusion as eggplants were introduced from mainland Asia to Japan. This dish is Earth Fusion, originating after the introduction of the chili from the Americas to Japan. Fusion HA!" - icon_state = "eggplantsushi" - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("capsaicin", 2) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/pastatomato - name = "Spaghetti" - desc = "Spaghetti and crushed tomatoes. Just like your abusive father used to make!" - icon_state = "pastatomato" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("tomatojuice", 10) - bitesize = 4 - -/obj/item/weapon/reagent_containers/food/snacks/copypasta - name = "copypasta" - desc = "You probably shouldn't try this, you always hear people talking about how bad it is..." - icon_state = "copypasta" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 12) - reagents.add_reagent("tomatojuice", 20) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/meatballspaghetti - name = "Spaghetti & Meatballs" - desc = "Now thats a nic'e meatball!" - icon_state = "meatballspaghetti" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/spesslaw - name = "Spesslaw" - desc = "A lawyers favourite" - icon_state = "spesslaw" - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/poppypretzel - name = "Poppy Pretzel" - desc = "A large soft pretzel full of POP!" - icon_state = "poppypretzel" - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/carrotfries - name = "Carrot Fries" - desc = "Tasty fries from fresh Carrots." - icon_state = "carrotfries" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("imidazoline", 3) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/superbiteburger - name = "Super Bite Burger" - desc = "This is a mountain of a burger. FOOD!" - icon_state = "superbiteburger" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 40) - bitesize = 10 - -/obj/item/weapon/reagent_containers/food/snacks/candiedapple - name = "Candied Apple" - desc = "An apple coated in sugary sweetness." - icon_state = "candiedapple" - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/pie/applepie - name = "Apple Pie" - desc = "A pie containing sweet sweet love...or apple." - icon_state = "applepie" - food_flags = FOOD_SWEET - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 4) - bitesize = 3 - - -/obj/item/weapon/reagent_containers/food/snacks/pie/cherrypie - name = "Cherry Pie" - desc = "Taste so good, make a grown man cry." - icon_state = "cherrypie" - food_flags = FOOD_SWEET - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 4) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/twobread - name = "Two Bread" - desc = "It is very bitter and winy." - icon_state = "twobread" - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/jellysandwich - name = "Jelly Sandwich" - desc = "You wish you had some peanut butter to go with this..." - icon_state = "jellysandwich" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 2) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/slime - New() - ..() - reagents.add_reagent("slimejelly", 5) - -/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/cherry - New() - ..() - reagents.add_reagent("cherryjelly", 5) -/* -/obj/item/weapon/reagent_containers/food/snacks/boiledslimecore - name = "Boiled slime Core" - desc = "A boiled red thing." - icon_state = "boiledslimecore" - New() - ..() - reagents.add_reagent("slimejelly", 5) - bitesize = 3 -*/ -/obj/item/weapon/reagent_containers/food/snacks/mint - name = "mint" - desc = "it is only wafer thin." - icon_state = "mint" - New() - ..() - reagents.add_reagent("minttoxin", 1) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/mushroomsoup - name = "chantrelle soup" - desc = "A delicious and hearty mushroom soup." - icon_state = "mushroomsoup" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit - name = "plump helmet biscuit" - desc = "This is a finely-prepared plump helmet biscuit. The ingredients are exceptionally minced plump helmet, and well-minced dwarven wheat flour." - icon_state = "phelmbiscuit" - New() - ..() - if(prob(10)) - name = "exceptional plump helmet biscuit" - desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!" - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("tricordrazine", 5) - bitesize = 2 - else - reagents.add_reagent("nutriment", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/chawanmushi - name = "chawanmushi" - desc = "A legendary egg custard that makes friends out of enemies. Probably too hot for a cat to eat." - icon_state = "chawanmushi" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/beetsoup - name = "beet soup" - desc = "Wait, how do you spell it again..?" - icon_state = "beetsoup" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID - - New() - ..() - eatverb = pick("slurp","sip","suck","inhale","drink") - name = pick("borsch","bortsch","borstch","borsh","borshch","borscht") - reagents.add_reagent("nutriment", 8) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/herbsalad - name = "herb salad" - desc = "A tasty salad with apples on top." - icon_state = "herbsalad" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/validsalad - name = "valid salad" - desc = "It's just an herb salad with meatballs and fried potato slices. Nothing suspicious about it." - icon_state = "validsalad" - trash = /obj/item/trash/snack_bowl - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("doctorsdelight", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/appletart - name = "golden apple streusel tart" - desc = "A tasty dessert that won't make it through a metal detector." - icon_state = "gappletart" - trash = /obj/item/trash/plate - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("gold", 5) - bitesize = 3 - -/////////////////////////////////////////////////Sliceable//////////////////////////////////////// -// All the food items that can be sliced into smaller bits like Meatbread and Cheesewheels - -// sliceable is just an organization type path, it doesn't have any additional code or variables tied to it. - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread - name = "meatbread loaf" - desc = "The culinary base of every self-respecting eloquen/tg/entleman." - icon_state = "meatbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatbreadslice - slices_num = 5 - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 30) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/meatbreadslice - name = "meatbread slice" - desc = "A slice of delicious meatbread." - icon_state = "meatbreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread - name = "xenomeatbread loaf" - desc = "The culinary base of every self-respecting eloquen/tg/entleman. Extra Heretical." - icon_state = "xenomeatbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/xenomeatbreadslice - slices_num = 5 - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 30) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/xenomeatbreadslice - name = "xenomeatbread slice" - desc = "A slice of delicious meatbread. Extra Heretical." - icon_state = "xenobreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/spidermeatbread - name = "spider meat loaf" - desc = "Reassuringly green meatloaf made from spider meat." - icon_state = "spidermeatbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/spidermeatbreadslice - slices_num = 5 - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 30) //If the meat is toxic, it will inherit that - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/spidermeatbreadslice - name = "spider meat bread slice" - desc = "A slice of meatloaf made from an animal that most likely still wants you dead." - icon_state = "xenobreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread/synth - name = "synthmeatbread loaf" - desc = "A loaf of synthetic meatbread. You can just taste the mass-production." - icon_state = "meatbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatbreadslice/synth - slices_num = 5 - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 30) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/meatbreadslice/synth - name = "synthmeatbread slice" - desc = "A slice of synthetic meatbread." - icon_state = "meatbreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread - name = "banana-nut bread" - desc = "A heavenly and filling treat." - icon_state = "bananabread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/bananabreadslice - slices_num = 5 - New() - ..() - reagents.add_reagent("banana", 20) - reagents.add_reagent("nutriment", 20) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/bananabreadslice - name = "banana-nut bread slice" - desc = "A slice of delicious banana bread." - icon_state = "bananabreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread - name = "Tofubread" - icon_state = "Like meatbread but for vegetarians. Not guaranteed to give superpowers." - icon_state = "tofubread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/tofubreadslice - slices_num = 5 - New() - ..() - reagents.add_reagent("nutriment", 30) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/tofubreadslice - name = "tofubread slice" - desc = "A slice of delicious tofubread." - icon_state = "tofubreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake - name = "carrot cake" - desc = "A favorite desert of a certain wascally wabbit. Not a lie." - icon_state = "carrotcake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/carrotcakeslice - slices_num = 5 - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 25) - reagents.add_reagent("imidazoline", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/carrotcakeslice - name = "carrot cake slice" - desc = "Carrotty slice of Carrot Cake, carrots are good for your eyes! Also not a lie." - icon_state = "carrotcake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake - name = "brain cake" - desc = "A squishy cake-thing." - icon_state = "braincake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/braincakeslice - slices_num = 5 - food_flags = FOOD_MEAT | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 25) - reagents.add_reagent("alkysine", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/braincakeslice - name = "brain cake slice" - desc = "Lemme tell you something about prions. THEY'RE DELICIOUS." - icon_state = "braincakeslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_MEAT | FOOD_ANIMAL //meat, milk, eggs - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake - name = "cheese cake" - desc = "DANGEROUSLY cheesy." - icon_state = "cheesecake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/cheesecakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL //cheese - - New() - ..() - reagents.add_reagent("nutriment", 25) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cheesecakeslice - name = "cheese cake slice" - desc = "Slice of pure cheestisfaction" - icon_state = "cheesecake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake - name = "vanilla cake" - desc = "A plain cake, not a lie." - icon_state = "plaincake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/plaincakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL //milk and eggs - - New() - ..() - reagents.add_reagent("nutriment", 20) - -/obj/item/weapon/reagent_containers/food/snacks/plaincakeslice - name = "vanilla cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "plaincake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake - name = "orange cake" - desc = "A cake with added orange." - icon_state = "orangecake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/orangecakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 20) - -/obj/item/weapon/reagent_containers/food/snacks/orangecakeslice - name = "orange cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "orangecake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake - name = "lime cake" - desc = "A cake with added lime." - icon_state = "limecake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/limecakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 20) - -/obj/item/weapon/reagent_containers/food/snacks/limecakeslice - name = "lime cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "limecake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake - name = "lemon cake" - desc = "A cake with added lemon." - icon_state = "lemoncake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/lemoncakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - New() - ..() - reagents.add_reagent("nutriment", 20) - -/obj/item/weapon/reagent_containers/food/snacks/lemoncakeslice - name = "lemon cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "lemoncake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake - name = "chocolate cake" - desc = "A cake with added chocolate" - icon_state = "chocolatecake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/chocolatecakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 20) - -/obj/item/weapon/reagent_containers/food/snacks/chocolatecakeslice - name = "chocolate cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "chocolatecake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel - name = "cheese wheel" - desc = "A big wheel of delicious Cheddar." - icon_state = "cheesewheel" - filling_color = "#FFCC33" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/cheesewedge - slices_num = 5 - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 20) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cheesewedge - name = "cheese wedge" - desc = "A wedge of delicious Cheddar. The cheese wheel it was cut from can't have gone far." - icon_state = "cheesewedge" - filling_color = "#FFCC33" - bitesize = 2 - food_flags = FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake - name = "Birthday Cake" - desc = "Happy Birthday..." - icon_state = "birthdaycake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/birthdaycakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 20) - reagents.add_reagent("sprinkles", 10) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/birthdaycakeslice - name = "Birthday Cake slice" - desc = "A slice of your birthday" - icon_state = "birthdaycakeslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/bread - name = "Bread" - icon_state = "Some plain old Earthen bread." - icon_state = "bread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/breadslice - slices_num = 5 - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/breadslice - name = "Bread slice" - desc = "A slice of home." - icon_state = "breadslice" - trash = /obj/item/trash/plate - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/creamcheesebread - name = "Cream Cheese Bread" - desc = "Yum yum yum!" - icon_state = "creamcheesebread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/creamcheesebreadslice - slices_num = 5 - New() - ..() - reagents.add_reagent("nutriment", 20) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/creamcheesebreadslice - name = "Cream Cheese Bread slice" - desc = "A slice of yum!" - icon_state = "creamcheesebreadslice" - trash = /obj/item/trash/plate - bitesize = 2 - - -/obj/item/weapon/reagent_containers/food/snacks/watermelonslice - name = "Watermelon Slice" - desc = "A slice of watery goodness." - icon_state = "watermelonslice" - bitesize = 2 - food_flags = FOOD_SWEET - - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake - name = "Apple Cake" - desc = "A cake centred with Apple" - icon_state = "applecake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/applecakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 15) - -/obj/item/weapon/reagent_containers/food/snacks/applecakeslice - name = "Apple Cake slice" - desc = "A slice of heavenly cake." - icon_state = "applecakeslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie //You can't throw this pie - name = "Pumpkin Pie" - desc = "A delicious treat for the autumn months." - icon_state = "pumpkinpie" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/pumpkinpieslice - slices_num = 5 - trash = /obj/item/trash/pietin - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 15) - -/obj/item/weapon/reagent_containers/food/snacks/pumpkinpieslice - name = "Pumpkin Pie slice" - desc = "A slice of pumpkin pie, with whipped cream on top. Perfection." - icon_state = "pumpkinpieslice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/cracker - name = "Cracker" - desc = "It's a salted cracker." - icon_state = "cracker" - - New() - ..() - reagents.add_reagent("nutriment", 1) - - - -/////////////////////////////////////////////////PIZZA//////////////////////////////////////// - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza - slices_num = 6 - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita - name = "Margherita" - desc = "The most cheezy pizza in galaxy" - icon_state = "pizzamargherita" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/margheritaslice - slices_num = 6 - food_flags = FOOD_ANIMAL //cheese - - New() - ..() - reagents.add_reagent("nutriment", 40) - reagents.add_reagent("tomatojuice", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/margheritaslice - name = "Margherita slice" - desc = "A slice of the most cheezy pizza in galaxy" - icon_state = "pizzamargheritaslice" - bitesize = 2 - food_flags = FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza - name = "Meatpizza" - desc = "A filling pizza laden with meat; perfect for the manliest of carnivores." - icon_state = "meatpizza" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice - slices_num = 6 - food_flags = FOOD_MEAT | FOOD_ANIMAL //It has cheese! - - New() - ..() - reagents.add_reagent("nutriment", 50) - reagents.add_reagent("tomatojuice", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice - name = "Meatpizza slice" - desc = "A slice of pizza, packed with delicious meat." - icon_state = "meatpizzaslice" - bitesize = 2 - food_flags = FOOD_MEAT | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza/synth - name = "Synthmeatpizza" - desc = "A synthetic pizza laden with artificial meat; perfect for the stingiest of chefs." - icon_state = "meatpizza" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice/synth - slices_num = 6 - - New() - ..() - reagents.add_reagent("nutriment", 50) - reagents.add_reagent("tomatojuice", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice/synth - name = "Synthmeatpizza slice" - desc = "A slice of pizza, packed with synthetic meat." - icon_state = "meatpizzaslice" - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza - name = "Mushroompizza" - desc = "Very special pizza" - icon_state = "mushroompizza" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice - slices_num = 6 - New() - ..() - reagents.add_reagent("nutriment", 35) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice - name = "Mushroompizza slice" - desc = "Maybe it is the last slice of pizza in your life." - icon_state = "mushroompizzaslice" - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza - name = "Vegetable pizza" - desc = "No one of Tomatos Sapiens were harmed during making this pizza" - icon_state = "vegetablepizza" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice - slices_num = 6 - New() - ..() - reagents.add_reagent("nutriment", 30) - reagents.add_reagent("tomatojuice", 6) - reagents.add_reagent("imidazoline", 12) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice - name = "Vegetable pizza slice" - desc = "A slice of the most green pizza of all pizzas not containing green ingredients " - icon_state = "vegetablepizzaslice" - bitesize = 2 - -/obj/item/pizzabox - name = "pizza box" - desc = "A box suited for pizzas." - icon = 'icons/obj/food.dmi' - icon_state = "pizzabox1" - starting_materials = list(MAT_CARDBOARD = 3750) - w_type=RECYK_MISC - - var/open = 0 // Is the box open? - var/ismessy = 0 // Fancy mess on the lid - var/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pizza // Content pizza - var/list/boxes = list() // If the boxes are stacked, they come here - var/boxtag = "" - -/obj/item/pizzabox/update_icon() - - overlays = list() - - // Set appropriate description - if( open && pizza ) - desc = "A box suited for pizzas. It appears to have a [pizza.name] inside." - else if( boxes.len > 0 ) - desc = "A pile of boxes suited for pizzas. There appears to be [boxes.len + 1] boxes in the pile." - - var/obj/item/pizzabox/topbox = boxes[boxes.len] - var/toptag = topbox.boxtag - if( toptag != "" ) - desc = "[desc] The box on top has a tag, it reads: '[toptag]'." - else - desc = "A box suited for pizzas." - - if( boxtag != "" ) - desc = "[desc] The box has a tag, it reads: '[boxtag]'." - - // Icon states and overlays - if( open ) - if( ismessy ) - icon_state = "pizzabox_messy" - else - icon_state = "pizzabox_open" - - if( pizza ) - var/image/pizzaimg = image("food.dmi", icon_state = pizza.icon_state) - pizzaimg.pixel_y = -3 - overlays += pizzaimg - - return - else - // Stupid code because byondcode sucks - var/doimgtag = 0 - if( boxes.len > 0 ) - var/obj/item/pizzabox/topbox = boxes[boxes.len] - if( topbox.boxtag != "" ) - doimgtag = 1 - else - if( boxtag != "" ) - doimgtag = 1 - - if( doimgtag ) - var/image/tagimg = image("food.dmi", icon_state = "pizzabox_tag") - tagimg.pixel_y = boxes.len * 3 - overlays += tagimg - - icon_state = "pizzabox[boxes.len+1]" - -/obj/item/pizzabox/attack_hand( mob/user as mob ) - - if( open && pizza ) - user.put_in_hands( pizza ) - - to_chat(user, "You take the [src.pizza] out of the [src].") - src.pizza = null - update_icon() - return - - if( boxes.len > 0 ) - if( user.get_inactive_hand() != src ) - ..() - return - - var/obj/item/pizzabox/box = boxes[boxes.len] - boxes -= box - - user.put_in_hands( box ) - to_chat(user, "You remove the topmost [src] from your hand.") - box.update_icon() - update_icon() - return - ..() - -/obj/item/pizzabox/attack_self( mob/user as mob ) - - if( boxes.len > 0 ) - return - - open = !open - - if( open && pizza ) - ismessy = 1 - - update_icon() - -/obj/item/pizzabox/attackby( obj/item/I as obj, mob/user as mob ) - if( istype(I, /obj/item/pizzabox/) ) - var/obj/item/pizzabox/box = I - - if( !box.open && !src.open ) - // Make a list of all boxes to be added - var/list/boxestoadd = list() - boxestoadd += box - for(var/obj/item/pizzabox/i in box.boxes) - boxestoadd += i - - if( (boxes.len+1) + boxestoadd.len <= 5 ) - if(user.drop_item(I, src)) - - box.boxes = list() // Clear the box boxes so we don't have boxes inside boxes. - Xzibit - src.boxes.Add( boxestoadd ) - - box.update_icon() - update_icon() - - to_chat(user, "You put the [box] ontop of the [src]!") - - else - to_chat(user, "The stack is too high!") - else - to_chat(user, "Close the [box] first!") - - return - - if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/)) // Long ass fucking object name - if(src.pizza) to_chat(user, "[src] already has a pizza in it.") - else if(src.open) - if(user.drop_item(I, src)) - src.pizza = I - src.update_icon() - to_chat(user, "You put [I] in [src].") - else to_chat(user, "Open [src] first.") - - return - - if( istype(I, /obj/item/weapon/pen/) ) - - if( src.open ) - return - - var/t = input("Enter what you want to add to the tag:", "Write", null, null) as text - if (!Adjacent(user) || user.stat) return - - var/obj/item/pizzabox/boxtotagto = src - if( boxes.len > 0 ) - boxtotagto = boxes[boxes.len] - - boxtotagto.boxtag = copytext("[boxtotagto.boxtag][t]", 1, 30) - - update_icon() - return - ..() - -/obj/item/pizzabox/margherita/New() - . = ..() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita(src) - boxtag = "Margherita Deluxe" - -/obj/item/pizzabox/vegetable/New() - . = ..() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza(src) - boxtag = "Gourmet Vegatable" - -/obj/item/pizzabox/mushroom/New() - . = ..() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza(src) - boxtag = "Mushroom Special" - -/obj/item/pizzabox/meat/New() - . = ..() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza(src) - boxtag = "Meatlover's Supreme" - -////////////////////////////////FOOD ADDITIONS//////////////////////////////////////////// - -/obj/item/weapon/reagent_containers/food/snacks/wrap - name = "egg wrap" - desc = "The precursor to Pigs in a Blanket." - icon_state = "wrap" - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/beans - name = "tin of beans" - desc = "Musical fruit in a slightly less musical container." - icon_state = "beans" - New() - ..() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/benedict - name = "eggs benedict" - desc = "There is only one egg on this, how rude." - icon_state = "benedict" - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/hotdog - name = "hotdog" - desc = "Fresh footlong ready to go down on." - icon_state = "hotdog" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("ketchup", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/meatbun - name = "meat bun" - desc = "Has the potential to not be Dog." - icon_state = "meatbun" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 6 - -/obj/item/weapon/reagent_containers/food/snacks/icecreamsandwich - name = "icecream sandwich" - desc = "Portable Ice-cream in it's own packaging." - icon_state = "icecreamsandwich" - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("ice", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/notasandwich - name = "not-a-sandwich" - desc = "Something seems to be wrong with this, you can't quite figure what. Maybe it's his moustache." - icon_state = "notasandwich" - New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sugarcookie - name = "sugar cookie" - desc = "Just like your little sister used to make." - icon_state = "sugarcookie" - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("sugar", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/boiledspiderleg - name = "boiled spider leg" - desc = "A giant spider's leg that's still twitching after being cooked. Gross!" - icon_state = "spiderlegcooked" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/spidereggs - name = "spider eggs" - desc = "A cluster of juicy spider eggs. A great side dish for when you care not for your health." - icon_state = "spidereggs" - food_flags = FOOD_ANIMAL //eggs are eggs - - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("toxin", 1) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/spidereggsham - name = "green eggs and ham" - desc = "Would you eat them on a train? Would you eat them on a plane? Would you eat them on a state of the art corporate deathtrap floating through space?" - icon_state = "spidereggsham" - trash = /obj/item/trash/plate - food_flags = FOOD_MEAT | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("sodiumchloride", 1) - bitesize = 4 - -/obj/item/weapon/reagent_containers/food/snacks/sashimi - name = "carp sashimi" - desc = "Celebrate surviving attack from hostile alien lifeforms by hospitalising yourself." - icon_state = "sashimi" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("carppheromones", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/assburger - name = "assburger" - desc = "You better be REALLY nice to this burger, or it'll report you to the police!" - icon_state = "assburger" - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("spiritbreaker", 10) // Screaming - reagents.add_reagent("mercury", 10) // Idiot - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/pie/asspie - name = "asspie" - desc = "Please remember to check your privlidge, pie eating scum." - icon_state = "asspie" - food_flags = FOOD_MEAT - - New() - ..() - reagents.clear_reagents() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("spiritbreaker", 10) // Screaming - reagents.add_reagent("mercury", 10) // Idiot - bitesize = 3 - -////////////////////////////////ICE CREAM/////////////////////////////////// -/obj/item/weapon/reagent_containers/food/snacks/icecream - name = "ice cream" - desc = "Delicious ice cream." - icon = 'icons/obj/kitchen.dmi' - icon_state = "icecream_cone" - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("sugar",1) - bitesize = 1 - update_icon() - - update_icon() - overlays.len = 0 - var/image/filling = image('icons/obj/kitchen.dmi', src, "icecream_color") - filling.icon += mix_color_from_reagents(reagents.reagent_list) - overlays += filling - -/obj/item/weapon/reagent_containers/food/snacks/icecream/icecreamcone - name = "ice cream cone" - desc = "Delicious ice cream." - icon_state = "icecream_cone" - volume = 500 - New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("sugar",6) - reagents.add_reagent("ice",2) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/icecream/icecreamcup - name = "chocolate ice cream cone" - desc = "Delicious ice cream." - icon_state = "icecream_cup" - volume = 500 - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("sugar",8) - reagents.add_reagent("ice",2) - bitesize = 6 - -/obj/item/weapon/reagent_containers/food/snacks/cereal - name = "box of cereal" - desc = "A box of cereal." - icon = 'icons/obj/food.dmi' - icon_state = "cereal_box" - bitesize = 2 - New() - ..() - reagents.add_reagent("nutriment", 3) - -/obj/item/weapon/reagent_containers/food/snacks/deepfryholder - name = "Deep Fried Foods Holder Obj" - icon = 'icons/obj/food.dmi' - icon_state = "deepfried_holder_icon" - bitesize = 2 - deepfried = 1 - New() - ..() - reagents.add_reagent("nutriment",deepFriedNutriment) - -/////////////////////////////////////////// -// new old food stuff from bs12 -/////////////////////////////////////////// - -/obj/item/weapon/reagent_containers/food/snacks/dough - name = "dough" - desc = "A piece of dough." - icon = 'icons/obj/food_ingredients.dmi' - icon_state = "dough" - bitesize = 2 - food_flags = FOOD_ANIMAL //eggs - - New() - ..() - reagents.add_reagent("nutriment", 3) - -// Dough + rolling pin = flat dough -/obj/item/weapon/reagent_containers/food/snacks/dough/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/kitchen/rollingpin)) - if(isturf(loc)) - new /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough(loc) - to_chat(user, "You flatten [src].") - qdel(src) - else - to_chat(user, "You need to put [src] on a surface to roll it out!") - else - ..() - -// slicable into 3xdoughslices -/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough - name = "flat dough" - desc = "A flattened dough." - icon = 'icons/obj/food_ingredients.dmi' - icon_state = "flat dough" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/doughslice - slices_num = 3 - food_flags = FOOD_ANIMAL //eggs - - New() - ..() - reagents.add_reagent("nutriment", 3) - -/obj/item/weapon/reagent_containers/food/snacks/doughslice - name = "dough slice" - desc = "A building block of an impressive dish." - icon = 'icons/obj/food_ingredients.dmi' - icon_state = "doughslice" - bitesize = 2 - food_flags = FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 1) - -/obj/item/weapon/reagent_containers/food/snacks/bun - name = "burger bun" - desc = "A base for any self-respecting burger." - icon = 'icons/obj/food_ingredients.dmi' - icon_state = "bun" - bitesize = 2 - New() - ..() - reagents.add_reagent("nutriment", 4) - -//////////////////CHRISTMAS AND WINTER FOOD////////////////// - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/buchedenoel - name = "\improper Buche de Noel" - desc = "Merry Christmas" - icon_state = "buche" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/bucheslice - slices_num = 5 - trash = /obj/item/trash/tray - food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/buchedenoel/New() - ..() - reagents.add_reagent("nutriment", 20) - reagents.add_reagent("sugar", 9) - reagents.add_reagent("coco", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/bucheslice - name = "\improper Buche de Noel slice" - desc = "A slice of winter magic" - icon_state = "buche_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey - name = "turkey" - desc = "Tastes like chicken" - icon_state = "turkey" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/turkeyslice - slices_num = 2 - trash = /obj/item/trash/tray - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey/New() - ..() - reagents.add_reagent("nutriment", 20) - reagents.add_reagent("blackpepper", 1) - reagents.add_reagent("sodiumchloride", 1) - reagents.add_reagent("cornoil", 1) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/turkeyslice - name = "turkey drumstick" - desc = "Guaranteed vox-free" - icon_state = "turkey_drumstick" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_MEAT - -//////////////////CHICKEN////////////////// - -/obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets - name = "Chicken Nuggets" - desc = "You'd rather not know how they were prepared." - icon_state = "kfc_nuggets" - item_state = "kfc_bucket" - trash = /obj/item/trash/chicken_bucket - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets/New() - ..() - reagents.add_reagent("nutriment", 6) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick - name = "chicken drumstick" - desc = "We can fry further..." - icon_state = "chicken_drumstick" - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick/New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chicken_fillet - name = "Chicken Fillet" - desc = "This is a fancy word for chicken fingers so that high class people can forget they're eating fried food." - icon_state = "tendies" - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets/New() - ..() - reagents.add_reagent("cornoil", 3) - bitesize = 2 - - -//////////////////CURRY////////////////// - -/obj/item/weapon/reagent_containers/food/snacks/curry - name = "Chicken Balti" - desc = "Finest Indian Cuisine, at least you think it is chicken." - icon_state = "curry_balti" - item_state = "curry_balti" - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/curry/New() - ..() - reagents.add_reagent("nutriment", 20) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/curry/vindaloo - name = "Chicken Vindaloo" - desc = "Me and me Mum and me Dad and me Nan are off to Waterloo, me and me Mum and me Dad and me Nan and a bucket of Vindaloo!" - icon_state = "curry_vindaloo" - item_state = "curry_vindaloo" - -/obj/item/weapon/reagent_containers/food/snacks/curry/vindaloo/New() - ..() - reagents.add_reagent("nutriment", 20) - reagents.add_reagent("capsaicin", 10) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/curry/lemon - name = "Lemon Curry" - desc = "This actually exists?" - icon_state = "curry_lemon" - item_state = "curry_lemon" - -/obj/item/weapon/reagent_containers/food/snacks/curry/lemon/New() - ..() - reagents.add_reagent("nutriment", 20) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/curry/xeno - name = "Xeno Balti" - desc = "Waste not want not." - icon_state = "curry_xeno" - item_state = "curry_xeno" - -/obj/item/weapon/reagent_containers/food/snacks/curry/xeno/New() - ..() - reagents.add_reagent("nutriment", 20) - bitesize = 3 - - -//////////////////CHIPS////////////////// - - -/obj/item/weapon/reagent_containers/food/snacks/chips - name = "chips" - desc = "Commander Riker's What-The-Crisps" - icon_state = "chips" - trash = /obj/item/trash/chips - New() - ..() - reagents.add_reagent("nutriment", 3) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable - name = "Plain Chips" - desc = "Where did the bag come from?" - icon_state = "plain_chips" - item_state = "plain_chips" - trash = null - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/vinegar - name = "Salt and Vinegar Chips" - desc = "The objectively best flavour." - icon_state = "salt_vinegar_chips" - item_state = "salt_vinegar_chips" - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/vinegar/New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/cheddar - name = "Cheddar Chips" - desc = "Dangerously cheesy." - icon_state = "cheddar_chips" - item_state = "cheddar_chips" - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/cheddar/New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/clown - name = "Banana Chips" - desc = "A clown's favourite snack!" - icon_state = "clown_chips" - item_state = "clown_chips" - -/obj/item/weapon/reagent_containers/food/snacks/chip/cookable/clown/New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("honkserum", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/nuclear - name = "Nuclear Chips" - desc = "Radioactive taste!" - icon_state = "nuclear_chips" - item_state = "nuclear_chips" - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/nuclear/New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("nuka_cola", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/communist - name = "Communist Chips" - desc = "A perfect snack to share with the party!" - icon_state = "commie_chips" - item_state = "commie_chips" - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/communist/New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("vodka", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/xeno - name = "Xeno Raiders" - desc = "A great taste that is out of this world!" - icon_state = "xeno_chips" - item_state = "xeno_chips" - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/xeno/New() - ..() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/gigapuddi - name = "Giga Puddi" - desc = "A large crème caramel" - icon_state = "gigapuddi" - trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //milk - - New() - ..() - reagents.add_reagent("nutriment", 20) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/gigapuddi/happy - desc = "A large crème caramel made with extra love" - icon_state = "happypuddi" - food_flags = FOOD_SWEET - -/obj/item/weapon/reagent_containers/food/snacks/gigapuddi/anger - desc = "A large crème caramel made with extra hate" - icon_state = "angerpuddi" - -/obj/item/weapon/reagent_containers/food/snacks/flan - name = "Flan" - desc = "A small crème caramel" - icon_state = "flan" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/honeyflan - name = "Honey Flan" - desc = "The systematic slavery of an entire society of insects, elegantly sized to fit in your mouth." - icon_state = "honeyflan" - trash = /obj/item/trash/plate - New() - ..() - reagents.add_reagent("nutriment", 8) - reagents.add_reagent("cinnamon", 5) - reagents.add_reagent("honey", 6) - bitesize = 3 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/omurice - name = "omelette rice" - desc = "Just like your Japanese animes!" - icon_state = "omurice" - trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //egg - - New() - ..() - reagents.add_reagent("nutriment", 8) - bitesize = 1 - -/obj/item/weapon/reagent_containers/food/snacks/omurice/heart - icon_state = "omuriceheart" - -/obj/item/weapon/reagent_containers/food/snacks/omurice/face - icon_state = "omuriceface" - -/obj/item/weapon/reagent_containers/food/snacks/muffin/bluespace - name = "Bluespace-berry Muffin" - desc = "Just like a normal blueberry muffin, except with completely unnecessary floaty things!" - icon_state = "bluespace" - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/yellowcake - name = "Yellowcake" - desc = "For Fat Men." - icon_state = "yellowcake" - food_flags = FOOD_SWEET | FOOD_ANIMAL //egg - - New() - ..() - reagents.add_reagent("nutriment", 40) - reagents.add_reagent("radium", 10) - reagents.add_reagent("uranium", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/yellowcupcake - name = "Yellowcupcake" - desc = "For Little Boys." - icon_state = "yellowcupcake" - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 15) - reagents.add_reagent("radium", 5) - reagents.add_reagent("uranium", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cookiebowl - name = "Bowl of cookies" - desc = "A bowl full of small cookies." - icon_state = "cookiebowl" - trash = /obj/item/trash/snack_bowl - New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("sugar", 5) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/chococherrycake - name = "chocolate-cherry cake" - desc = "A chocolate cake with icing and cherries." - icon_state = "chococherrycake" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/chococherrycakeslice - slices_num = 5 - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 20) - -/obj/item/weapon/reagent_containers/food/snacks/chococherrycakeslice - name = "chocolate-cherry cake slice" - desc = "Just a slice of cake, it is enough for everyone." - icon_state = "chococherrycake_slice" - trash = /obj/item/trash/plate - bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL - -/obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinbread - name = "Pumpkin Bread" - desc = "A loaf of pumpkin bread." - icon_state = "pumpkinbread" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/pumpkinbreadslice - slices_num = 5 - New() - ..() - reagents.add_reagent("nutriment", 15) - -/obj/item/weapon/reagent_containers/food/snacks/pumpkinbreadslice - name = "Pumpkin Bread slice" - desc = "A slice of pumpkin bread." - icon_state = "pumpkinbreadslice" - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/corndog - name = "Corndog" - desc = "Battered hotdog on a stick!" - icon_state = "corndog" - food_flags = FOOD_MEAT | FOOD_ANIMAL //eggs - - New() - ..() - reagents.add_reagent("nutriment", 5) - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/cornydog - name = "CORNY DOG" - desc = "This is just ridiculous." - icon_state = "cornydog" - trash = /obj/item/stack/rods //no fun allowed - food_flags = FOOD_MEAT - - New() - ..() - reagents.add_reagent("nutriment", 15) - bitesize = 5 - -////////////////SLIDERS//////////////// - -/obj/item/weapon/reagent_containers/food/snacks/slider - name = "slider" - desc = "It's so tiny!" - icon_state = "slider" - food_flags = FOOD_MEAT - -/obj/item/weapon/reagent_containers/food/snacks/slider/New() - ..() - reagents.add_reagent("nutriment", 2.5) - bitesize = 1.5 - -/obj/item/weapon/reagent_containers/food/snacks/slider/synth - name = "synth slider" - desc = "It's made to be tiny!" - -/obj/item/weapon/reagent_containers/food/snacks/slider/xeno - name = "xeno slider" - desc = "It's green!" - icon_state = "slider_xeno" - -/obj/item/weapon/reagent_containers/food/snacks/slider/xeno/New() - ..() - reagents.add_reagent("nutriment", 1) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/slider/chicken - name = "chicken slider" - desc = "Chicken sliders? That's new." - icon_state = "slider_chicken" - -/obj/item/weapon/reagent_containers/food/snacks/slider/chicken/New() - ..() - reagents.add_reagent("nutriment", 1) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/slider/carp - name = "carp slider" - desc = "I wonder how it tastes!" - icon_state = "slider_carp" - -/obj/item/weapon/reagent_containers/food/snacks/slider/carp/New() - ..() - reagents.add_reagent("nutriment", 1) - bitesize = 2.5 - -/obj/item/weapon/reagent_containers/food/snacks/slider/toxiccarp - name = "carp slider" - desc = "I wonder how it tastes!" - icon_state = "slider_carp" - -/obj/item/weapon/reagent_containers/food/snacks/slider/toxiccarp/New() - ..() - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("carpotoxin", 2) - bitesize = 2.5 - -/obj/item/weapon/reagent_containers/food/snacks/slider/carp/spider - name = "spidey slidey" - desc = "I think there's still a leg in there!" - icon_state = "slider_spider" - -/obj/item/weapon/reagent_containers/food/snacks/slider/clown - name = "honky slider" - desc = "HONK!" - icon_state = "slider_clown" - -/obj/item/weapon/reagent_containers/food/snacks/slider/clown/New() - ..() - reagents.add_reagent("honkserum", 2.5) - bitesize = 2.5 - -/obj/item/weapon/reagent_containers/food/snacks/slider/mime - name = "quiet Slider" - desc = "..." - icon_state = "slider_mime" - -/obj/item/weapon/reagent_containers/food/snacks/slider/slippery - name = "slippery slider" - desc = "It's so slippery!" - icon_state = "slider_slippery" - -/obj/item/weapon/reagent_containers/food/snacks/slider/slippery/Crossed(atom/movable/O) //exactly the same as soap - if (istype(O, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = O - if (H.CheckSlip() < 1) - return - - H.stop_pulling() - to_chat(H, "You slipped on the [name]!") - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) - H.Stun(3) - H.Weaken(2) - -////////////////SLIDERS END//////////////// - -/obj/item/weapon/reagent_containers/food/snacks/higashikata - name = "Higashikata Special" - desc = "9 layer parfait, very expensive." - icon_state = "higashikata" - food_flags = FOOD_SWEET | FOOD_ANIMAL - - New() - ..() - reagents.add_reagent("nutriment", 10) - reagents.add_reagent("sugar", 10) - reagents.add_reagent("ice", 10) - reagents.add_reagent("melonjuice", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/sundae - name = "Sundae" - desc = "A colorful ice cream treat." - icon_state = "sundae" - food_flags = FOOD_SWEET | FOOD_ANIMAL //milk - - New() - ..() - reagents.add_reagent("nutriment", 5) - reagents.add_reagent("sugar", 5) - reagents.add_reagent("ice", 5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/potatosalad - name = "Potato Salad" - desc = "With 21st century technology, it could take as long as three days to make this." - icon_state = "potato_salad" - New() - ..() - reagents.add_reagent("nutriment", 10) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/coleslaw - name = "Coleslaw" - desc = "You fought the 'slaw, and the 'slaw won." - icon_state = "coleslaw" - New() - ..() - reagents.add_reagent("nutriment", 4) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/risotto - name = "Risotto" - desc = "For the gentleman's wino, this is an offer one cannot refuse." - icon_state = "risotto" - New() - ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("wine", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/cinnamonroll - name = "cinnamon roll" - desc = "Sweet and spicy!" - icon_state = "cinnamon_roll" - trash = /obj/item/trash/plate - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("cinnamon",5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/cinnamonpie - name = "cinnamon pie" - desc = "Guarranted snail-free!" - icon_state = "cinnamon_pie" - trash = /obj/item/trash/pietin - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 6) - reagents.add_reagent("cinnamon",5) - bitesize = 3 - -/obj/item/weapon/reagent_containers/food/snacks/sundaeramen - name = "Sundae Ramen" - desc = "This is... sundae (?) flavored (?) ramen (?). You just don't know." - icon_state = "sundaeramen" - food_flags = FOOD_SWEET - - New() - ..() - reagents.add_reagent("nutriment", 10) - reagents.add_reagent("discount", 2) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sweetsundaeramen - name = "Sweet Sundae Ramen" - desc = "It's a delicious ramen recipe that can soothe the soul of a savage spaceman." - icon_state = "sweetsundaeramen" - food_flags = FOOD_SWEET | FOOD_ANIMAL //uses puddi in recipe - - New() - ..() - bitesize = 4 - while(reagents.total_volume<70) - generatecontents() - -/obj/item/weapon/reagent_containers/food/snacks/sweetsundaeramen/proc/generatecontents() - switch(pick(1,2,3,4,5,6,7,8,9,10)) - if(1) - desc += " It has peppermint flavoring! But just a few drops." - reagents.add_reagent("zombiepowder", 10) - if(2) - desc += " This may not be everyone's cup of tea, but it's great, I promise." - reagents.add_reagent("oxycodone", 10) - if(3) - desc += " This has the cook's favorite ingredient -- and a lot of it!" - reagents.add_reagent("mindbreaker", 10) - if(4) - desc += " It has TONS of flavor!" - reagents.add_reagent("minttoxin", 10) - if(5) - desc += " The recipe for this thing got lost somewhere..." - reagents.add_reagent("nutriment", 10) - if(6) - desc += " It has extra sweetness and a little bit of crumble!" - reagents.add_reagent("tricordrazine", 10) - if(7) - desc += " It may be thick, but the noodles slip around easily." - reagents.add_reagent("nutriment", 10) - if(8) - desc += " It has a nice crunch!" - reagents.add_reagent("nutriment", 10) - if(9) - desc += " Yummy, but with all the sweets, your chest starts to hurt." - reagents.add_reagent("nutriment", 10) - if(10) - desc += " Just a dollop of garnishes." - reagents.add_reagent("nutriment", 10) - -/obj/item/weapon/reagent_containers/food/snacks/chocofrog - name = "chocolate frog" - desc = "An exotic snack originating from the Space Wizard Federation. Very slippery!" - icon = 'icons/obj/wiz_cards.dmi' - icon_state = "frog" - - flags = PROXMOVE - food_flags = FOOD_SWEET - - var/jump_cd - -/obj/item/weapon/reagent_containers/food/snacks/chocofrog/New() - ..() - reagents.add_reagent("nutriment",2) - reagents.add_reagent("hyperzine",1) - -/obj/item/weapon/reagent_containers/food/snacks/chocofrog/HasProximity(atom/movable/AM as mob|obj) - if(!jump_cd) - jump() - return ..() - -/obj/item/weapon/reagent_containers/food/snacks/chocofrog/proc/jump() - if(!istype(src.loc,/turf)) return - jump_cd=1 - spawn(50) - jump_cd=0 - - var/list/escape_paths=list() - - for(var/turf/T in view(7,src)) - escape_paths |= T - - var/turf/T = pick(escape_paths) - src.throw_at(T, 10, 2) - return 1 - -/obj/item/weapon/reagent_containers/food/snacks/chocofrog/pickup(mob/living/user as mob) - var/mob/living/carbon/human/H = user - if(!H) return 1 - - spawn(0) - if(((M_CLUMSY in H.mutations)) || prob(25)) - if(H.drop_item()) - user.visible_message("[src] escapes from [H]'s hands!","[src] escapes from your grasp!") - - jump() - return 1 - -/obj/item/weapon/reagent_containers/food/snacks/potentham - name = "potent ham" - desc = "I'm sorry Dave, but I am afraid I can't let you eat that." - icon_state = "potentham" - volume = 1 - New() - ..() - reagents.add_reagent("hamserum", 1) - bitesize = 2 - -/obj/item/weapon/reagent_containers/food/snacks/sweet - name = "\improper Sweet" - desc = "Comes in many different and unique flavours!" - food_flags = FOOD_SWEET - icon = 'icons/obj/candymachine.dmi' - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/sweet/New() - ..() - reagents.add_reagent("nutriment", 3) - reagents.add_reagent("sugar", 2) - icon_state = "sweet[rand(1,12)]" - -/obj/item/weapon/reagent_containers/food/snacks/sweet/strange - desc = "Something about this sweet doesn't seem right." - -/obj/item/weapon/reagent_containers/food/snacks/sweet/strange/New() - ..() - var/list/possible_reagents=list("zombiepowder"=5, "mindbreaker"=5, "pacid"=5, "hyperzine"=5, "chloralhydrate"=5, "tricordazine"=5, "doctorsdelight"=5, "mutationtoxin"=5, "mercury"=5, "anti_toxin"=5, "space_drugs"=5, "holywater"=5, "ryetalyn"=5, "cryptobiolin"=5, "dexalinp"=5, "hamserum"=1) - var/reagent=pick(possible_reagents) - reagents.add_reagent(reagent, possible_reagents[reagent]) - -/obj/item/weapon/reagent_containers/food/snacks/chococoin - name = "\improper Choco-Coin" - desc = "A thin wafer of milky, chocolatey, melt-in-your-mouth goodness. That alone is already worth a hoard." - food_flags = FOOD_SWEET - icon_state = "chococoin_unwrapped" - bitesize = 4 - -/obj/item/weapon/reagent_containers/food/snacks/chococoin/wrapped - desc = "Still covered in golden foil wrapper." - icon_state = "chococoin_wrapped" - wrapped = 1 - -/obj/item/weapon/reagent_containers/food/snacks/chococoin/New() - ..() - reagents.add_reagent("nutriment", 2) - reagents.add_reagent("sugar", 2) - reagents.add_reagent("coco", 3) - -/obj/item/weapon/reagent_containers/food/snacks/chococoin/attack_self(mob/user) - if(wrapped) - Unwrap(user) - else - ..() - -/obj/item/weapon/reagent_containers/food/snacks/chococoin/proc/Unwrap(mob/user) - icon_state = "chococoin_unwrapped" - desc = "A thin wafer of milky, chocolatey, melt-in-your-mouth goodness. That alone is already worth a hoard." - to_chat(user, "You remove the golden foil from \the [src].") - wrapped = 0 - -/obj/item/weapon/reagent_containers/food/snacks/eucharist - name = "\improper Eucharist Wafer" - icon_state = "eucharist" - desc = "For the kingdom, the power, and the glory are yours, now and forever." - bitesize = 5 - -/obj/item/weapon/reagent_containers/food/snacks/eucharist/New() - ..() +//Food items that are eaten normally and don't leave anything behind. + +/obj/item/weapon/reagent_containers/food/snacks + name = "snack" + desc = "yummy" + icon = 'icons/obj/food.dmi' + icon_state = null + log_reagents = 1 + + var/food_flags //Possible flags: FOOD_LIQUID, FOOD_MEAT, FOOD_ANIMAL, FOOD_SWEET + //FOOD_LIQUID - for stuff like soups + //FOOD_MEAT - stuff that is made from (or contains) meat. Anything that vegetarians won't eat! + //FOOD_ANIMAL - stuff that is made from (or contains) animal products other than meat (eggs, honey, ...). Anything that vegans won't eat! + //FOOD_SWEET - sweet stuff like chocolate and candy + + //Example: food_flags = FOOD_SWEET | FOOD_ANIMAL + //Unfortunately, food created by cooking doesn't inherit food_flags! + + var/bitesize = 1 //How much reagents per bite (and thus how fast is the food consumed ?) + var/bitecount = 0 //How much times was the item bitten ? + var/trash = null //What left-over should we spawn, if any ? + var/slice_path //What can we slice this item into, if anything ? + var/slices_num //How much slices should we expect ? + var/eatverb //How do I eat thing ? (Note : Used for message, "bite", "chew", etc...) + var/wrapped = 0 //Is the food wrapped (preventing one from eating until unwrapped) + var/dried_type = null //What can we dry the food into + var/deepfried = 0 //Is the food deep-fried ? + var/filling_color = "#FFFFFF" //What color would a filling of this item be ? + volume = 100 //Double amount snacks can carry, so that food prepared from excellent items can contain all the nutriments it deserves + +//Proc for effects that trigger on eating that aren't directly tied to the reagents. +/obj/item/weapon/reagent_containers/food/snacks/proc/On_Consume(var/mob/user, var/datum/reagents/reagentreference) + if(!user) + return + if(reagents) + reagentreference = reagents + if(!reagentreference || !reagentreference.total_volume) //Are we done eating (determined by the amount of reagents left, here 0) + user.visible_message("[user] finishes eating \the [src].", \ + "You finish eating \the [src].") + score["foodeaten"]++ //For post-round score + + //Drop our item before we delete it, to clear any references of ourselves in people's hands or whatever. + if(loc == user) + user.drop_from_inventory(src) + else if(ismob(loc)) + var/mob/holder = loc + holder.drop_from_inventory(src) + + if(trash) //Do we have somehing defined as trash for our snack item ? + //Note : This makes sense in some way, or at least this works, just don't mess with it + if(ispath(trash, /obj/item)) + var/obj/item/TrashItem = new trash(user) + user.put_in_hands(TrashItem) + else if(istype(trash, /obj/item)) + user.put_in_hands(trash) + + qdel(src) //Remove the item, we consumed it + + return + +/obj/item/weapon/reagent_containers/food/snacks/attack_self(mob/user) + + attack(user, user) //This is painful, but it works, I guess + return + +/obj/item/weapon/reagent_containers/food/snacks/New() + + ..() + +/obj/item/weapon/reagent_containers/food/snacks/attack(mob/living/M, mob/user, def_zone, eat_override = 0) //M is target of attack action, user is the one initiating it + if(!eatverb) + eatverb = pick("bite", "chew", "nibble", "gnaw", "gobble", "chomp") + if(!reagents.total_volume) //Are we done eating (determined by the amount of reagents left, here 0) + //This is mostly caused either by "persistent" food items or spamming + to_chat(user, "There's nothing left of \the [src]!") + M.drop_from_inventory(src) //Drop our item before we delete it + qdel(src) + return 0 + + if(istype(M, /mob/living/carbon)) //Avoid messing with simple mobs + var/mob/living/carbon/target = M //First definition to avoid colons + if(target == user) //If you're eating it yourself + //In that case, target is the user, but we'll still ask "target" to do things + if(!target.hasmouth) + to_chat(user, "You have no mouth to eat with")//Good luck figuring out how that would happen + + return 0 + var/fullness = target.nutrition + (target.reagents.get_reagent_amount("nutriment") * 25) //This reminds me how unlogical mob nutrition is + if(wrapped) + to_chat(target, "You can't eat wrapped food!") + return 0 + if (!eat_override && ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species.chem_flags & NO_EAT) + user.drop_from_inventory(src) + src.forceMove(get_turf(H)) + playsound(get_turf(H),'sound/items/eatfood.ogg', rand(10,50), 1) + H.visible_message("As [M] attempts to eat \the [src] it falls through and onto the ground as if untouched.", "As you attempt to eat \the [src] it falls through your body and onto the ground as if untouched.") + return 0 + if(fullness <= 50) + target.visible_message("[target] hungrily [eatverb]s some of \the [src] and gobbles it down!", \ + "You hungrily [eatverb] some of \the [src] and gobble it down!") + else if(fullness > 50 && fullness < 150) + target.visible_message("[target] hungrily [eatverb]s \the [src].", \ + "You hungrily [eatverb] \the [src].") + else if(fullness > 150 && fullness < 350) + target.visible_message("[target] [eatverb]s \the [src].", \ + "You [eatverb] \the [src].") + else if(fullness > 350 && fullness < 550) + target.visible_message("[target] unwillingly [eatverb]s some of \the [src].", \ + "You unwillingly [eatverb] some of \the [src].") + else if(fullness > (550 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat + to_chat(target, "You cannot force any more of \the [src] to go down your throat.") + return 0 + else //Feeding someone else, target is eating, user is feeding + if(target.hasmouth) + var/fullness = target.nutrition + (target.reagents.get_reagent_amount("nutriment") * 25) + if(wrapped) + to_chat(user, "The food is wrapped, you can't feed it to [target] like that!") + return 0 + if(fullness <= (550 * (1 + M.overeatduration / 1000))) //The mob will accept + target.visible_message("[user] attempts to feed [target] \the [src].", \ + "[user] attempts to feed you \the [src].") + else //The mob is overfed and will refuse + target.visible_message("[user] cannot force anymore of \the [src] down [target]'s throat!", \ + "[user] cannot force anymore of \the [src] down your throat!") + return 0 + + if(!do_mob(user, target)) + return + if (ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species.chem_flags & NO_EAT) + user.drop_from_inventory(src) + src.forceMove(get_turf(H)) + H.visible_message("As [user] attempts to feed [M] \the [src] it falls through and onto the ground as if untouched.", "As [user] attempts to feed you \the [src] it falls through your body and onto the ground as if untouched.") + return 0 + + add_logs(user, target, "fed", object="[reagentlist(src)]") + target.visible_message("[user] feeds [target] \the [src].", \ + "[user] feeds you \the [src].") + + else + to_chat(user, "[target] doesn't seem to have a mouth. Awkward!") + return + + var/datum/reagents/reagentreference = reagents //Even when the object is qdeleted, the reagents exist until this ref gets removed + if(reagentreference) //Handle ingestion of any reagents (Note : Foods always have reagents) + playsound(target.loc,'sound/items/eatfood.ogg', rand(10,50), 1) + if(reagentreference.total_volume) + reagentreference.reaction(target, INGEST) + spawn() //WHY IS THIS SPAWN() HERE + if(gcDestroyed) + return + if(reagentreference.total_volume > bitesize) + /* + * I totally cannot understand what this code supposed to do. + * Right now every snack consumes in 2 bites, my popcorn does not work right, so I simplify it. -- rastaf0 + var/temp_bitesize = max(reagents.total_volume /2, bitesize) + reagents.trans_to(target, temp_bitesize) + */ + reagentreference.trans_to(target, bitesize) + else + reagentreference.trans_to(target, reagentreference.total_volume) + bitecount++ + On_Consume(target, reagentreference) + return 1 + + return 0 + +/obj/item/weapon/reagent_containers/food/snacks/examine(mob/user) + ..() + if (bitecount) + if(bitecount == 1) + to_chat(user, "\The [src] was bitten by someone!") + else if(bitecount > 1 && bitecount <= 3) + to_chat(user, "\The [src] was bitten [bitecount] times!") + else + to_chat(user, "\The [src] was bitten multiple times!") + +/obj/item/weapon/reagent_containers/food/snacks/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/pen)) //Renaming food + var/n_name = copytext(sanitize(input(user, "What would you like to name this dish?", "Food Renaming", null) as text|null), 1, MAX_NAME_LEN*3) + if(n_name && Adjacent(user) && !user.stat) + name = "[n_name]" + return + if(istype(W, /obj/item/weapon/kitchen/utensil/fork)) + var/obj/item/weapon/kitchen/utensil/fork/fork = W + if(slices_num || slice_path) + to_chat(user, "You can't take the whole [src] at once!.") + return + else + return fork.load_food(src, user) + + if (..()) return + + if((slices_num <= 0 || !slices_num) || !slice_path) //If the food item isn't sliceable, we have no more business to do here, return + return 0 + + if(W.w_class <= 2 && W.is_sharp() < 0.8 && !istype(W,/obj/item/device/analyzer/plant_analyzer)) //Make sure the item is valid to attempt slipping shit into it + if(!iscarbon(user)) + return 0 + + if(user.drop_item(W, src)) + to_chat(user, "You slip \the [W] inside [src].") + + add_fingerprint(user) + contents += W + return 1 //No afterattack here + + if(W.is_sharp() < 0.8) //At this point we are slicing food, so if our item isn't sharp enough, just abort + return 0 + + if(!isturf(src.loc) || !(locate(/obj/structure/table) in src.loc) && !(locate(/obj/item/weapon/tray) in src.loc)) + to_chat(user, "You cannot slice \the [src] here! You need a table or at least a tray.") + return 1 + + var/slices_lost = 0 + if(W.is_sharp() >= 1.2) //Actually sharp things are this sharp, yes + user.visible_message("[user] slices \the [src].", \ + "You slice \the [src].") + else //We're above 0.8 //The magic threshold of pizza slicing + user.visible_message("[user] inaccurately slices \the [src] with \the [W]!", \ + "You inaccurately slice \the [src] with \the [W]!") + slices_lost = rand(1, min(1, round(slices_num/2))) //Randomly lose a few slices along the way, but at least one and up to half + var/reagents_per_slice = reagents.total_volume/slices_num //Figure out how much reagents each slice inherits (losing slices loses reagents) + for(var/i = 1 to (slices_num - slices_lost)) //Transfer those reagents + var/obj/slice = new slice_path(src.loc) + if(istype(src, /obj/item/weapon/reagent_containers/food/snacks/customizable)) //custom sliceable foods have overlays we need to apply + var/obj/item/weapon/reagent_containers/food/snacks/customizable/C = src + var/obj/item/weapon/reagent_containers/food/snacks/customizable/S = slice + S.name = "[C.name][S.name]" + S.filling.color = C.filling.color + S.overlays += S.filling + reagents.trans_to(slice, reagents_per_slice) + qdel(src) //So long and thanks for all the fish + return 1 + +/obj/item/weapon/reagent_containers/food/snacks/Destroy() + if(contents) //Did someone slip shit in the pizza again ? + for(var/atom/movable/surprise in contents) //Find it + surprise.loc = get_turf(src) //Recover it + ..() + +/obj/item/weapon/reagent_containers/food/snacks/attack_animal(mob/M) + if(isanimal(M)) + if(iscorgi(M)) //Feeding food to a corgi + M.delayNextAttack(10) + if(bitecount >= 4) //This really, really shouldn't be hardcoded like this, but sure I guess + M.visible_message("[M] [pick("burps from enjoyment", "yaps for more", "woofs twice", "looks at the area where \the [src] was")].", "You swallow up the last of \the [src].") + playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) + var/mob/living/simple_animal/corgi/C = M + if(C.health <= C.maxHealth + 5) + C.health += 5 + else + C.health = C.maxHealth + qdel(src) + else + M.visible_message("[M] takes a bite of \the [src].", "You take a bite of \the [src].") + playsound(src.loc,'sound/items/eatfood.ogg', rand(10, 50), 1) + bitecount++ + else if(ismouse(M)) //Mouse eating shit + M.delayNextAttack(10) + var/mob/living/simple_animal/mouse/N = M + if(prob(25)) //We are noticed + N.visible_message("[N] nibbles away at \the [src].", "You nibble away at \the [src]") + else + to_chat(N, ("You nibble away at \the [src].")) + N.health = min(N.health + 1, N.maxHealth) + + +//////////////////////////////////////////////////////////////////////////////// +/// FOOD END +//////////////////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////// +////////////////////////////////////////////Snacks +////////////////////////////////////////////////// +//Items in the "Snacks" subcategory are food items that people actually eat. The key points are that they are created +// already filled with reagents and are destroyed when empty. Additionally, they make a "munching" noise when eaten. + +//Notes by Darem: Food in the "snacks" subtype can hold a maximum of 50 units Generally speaking, you don't want to go over 40 +// total for the item because you want to leave space for extra condiments. If you want effect besides healing, add a reagent for +// it. Try to stick to existing reagents when possible (so if you want a stronger healing effect, just use Tricordrazine). On use +// effect (such as the old officer eating a donut code) requires a unique reagent (unless you can figure out a better way). + +//The nutriment reagent and bitesize variable replace the old heal_amt and amount variables. Each unit of nutriment is equal to +// 2 of the old heal_amt variable. Bitesize is the rate at which the reagents are consumed. So if you have 6 nutriment and a +// bitesize of 2, then it'll take 3 bites to eat. Unlike the old system, the contained reagents are evenly spread among all +// the bites. No more contained reagents = no more bites. + +//Here is an example of the new formatting for anyone who wants to add more food items. +///obj/item/weapon/reagent_containers/food/snacks/xenoburger //Identification path for the object. +// name = "Xenoburger" //Name that displays in the UI. +// desc = "Smells caustic. Tastes like heresy." //Duh +// icon_state = "xburger" //Refers to an icon in food.dmi +// food_flags = FOOD_MEAT //For flavour, not that important. Flags are: FOOD_MEAT, FOOD_ANIMAL (for things that vegans don't eat), FOOD_SWEET, FOOD_LIQUID (soups). You can have multiple flags in here by doing this: food_flags = FOOD_MEAT | FOOD_SWEET +// +// New() //Don't mess with this. +// ..() //Same here. +// reagents.add_reagent("xenomicrobes", 10) //This is what is in the food item. you may copy/paste +// reagents.add_reagent("nutriment", 2) // this line of code for all the contents. +// bitesize = 3 //This is the amount each bite consumes. + + + + +/obj/item/weapon/reagent_containers/food/snacks/aesirsalad + name = "Aesir salad" + desc = "Probably too incredible for mortal men to fully enjoy." + icon_state = "aesirsalad" + trash = /obj/item/trash/snack_bowl + New() + ..() + eatverb = pick("crunch", "devour", "nibble", "gnaw", "gobble", "chomp") + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("tricordrazine", 8) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/candy + name = "candy" + desc = "Nougat love it or hate it." + icon_state = "candy" + trash = /obj/item/trash/candy + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("sugar", 3) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/candy/donor + name = "Donor Candy" + desc = "A little treat for blood donors." + trash = /obj/item/trash/candy + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 10) + reagents.add_reagent("sugar", 3) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/candy_corn + name = "candy corn" + desc = "It's a handful of candy corn. Can be stored in a detective's hat." + icon_state = "candy_corn" + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("sugar", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cookie + name = "cookie" + desc = "COOKIE!!!" + icon_state = "COOKIE!!!" + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chocolatebar + name = "chocolate bar" + desc = "Such, sweet, fattening food." + icon_state = "chocolatebarunwrapped" + wrapped = 0 + bitesize = 2 + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("sugar", 5) + reagents.add_reagent("coco", 5) + + attack_self(mob/user) + if(wrapped) + Unwrap(user) + else + ..() + +/obj/item/weapon/reagent_containers/food/snacks/chocolatebar/proc/Unwrap(mob/user) + icon_state = "chocolatebarunwrapped" + desc = "It won't make you all sticky." + to_chat(user, "You remove the foil.") + wrapped = 0 + + +/obj/item/weapon/reagent_containers/food/snacks/chocolatebar/wrapped + desc = "It's wrapped in some foil." + icon_state = "chocolatebar" + wrapped = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chocolateegg + name = "chocolate egg" + desc = "Such, sweet, fattening food." + icon_state = "chocolateegg" + food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs are used + + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("sugar", 2) + reagents.add_reagent("coco", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/donut + name = "donut" + desc = "Goes great with Robust Coffee." + icon_state = "donut1" + food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs are used + +/obj/item/weapon/reagent_containers/food/snacks/donut/normal + name = "donut" + desc = "Goes great with Robust Coffee." + icon_state = "donut1" + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("sprinkles", 1) + src.bitesize = 3 + if(prob(30)) + src.icon_state = "donut2" + src.name = "frosted donut" + reagents.add_reagent("sprinkles", 2) + +/obj/item/weapon/reagent_containers/food/snacks/donut/chaos + name = "Chaos Donut" + desc = "Like life, it never quite tastes the same." + icon_state = "donut1" + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("sprinkles", 1) + bitesize = 10 + switch(rand(1,10)) + if(1) + reagents.add_reagent("nutriment", 3) + if(2) + reagents.add_reagent("capsaicin", 3) + if(3) + reagents.add_reagent("frostoil", 3) + if(4) + reagents.add_reagent("sprinkles", 3) + if(5) + reagents.add_reagent("plasma", 3) + if(6) + reagents.add_reagent("coco", 3) + if(7) + reagents.add_reagent("slimejelly", 3) + if(8) + reagents.add_reagent("banana", 3) + if(9) + reagents.add_reagent("berryjuice", 3) + if(10) + reagents.add_reagent("tricordrazine", 3) + if(prob(30)) + icon_state = "donut2" + name = "frosted chaos donut" + reagents.add_reagent("sprinkles", 2) + + +/obj/item/weapon/reagent_containers/food/snacks/donut/jelly + name = "jelly donut" + desc = "You jelly?" + icon_state = "jdonut1" + bitesize = 5 + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("sprinkles", 1) + reagents.add_reagent("berryjuice", 5) + if(prob(30)) + icon_state = "jdonut2" + name = "Frosted Jelly Donut" + reagents.add_reagent("sprinkles", 2) + +/obj/item/weapon/reagent_containers/food/snacks/donut/slimejelly + name = "jelly donut" + desc = "You jelly?" + icon_state = "jdonut1" + bitesize = 5 + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("sprinkles", 1) + reagents.add_reagent("slimejelly", 5) + bitesize = 5 + if(prob(30)) + icon_state = "jdonut2" + name = "Frosted Jelly Donut" + reagents.add_reagent("sprinkles", 2) + +/obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly + name = "jelly donut" + desc = "You jelly?" + icon_state = "jdonut1" + bitesize = 5 + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("sprinkles", 1) + reagents.add_reagent("cherryjelly", 5) + if(prob(30)) + icon_state = "jdonut2" + name = "Frosted Jelly Donut" + reagents.add_reagent("sprinkles", 2) + +// Eggs + +/obj/item/weapon/reagent_containers/food/snacks/friedegg + name = "fried egg" + desc = "A fried egg, with a touch of salt and pepper." + icon_state = "friedegg" + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("sodiumchloride", 1) + reagents.add_reagent("blackpepper", 1) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/boiledegg + name = "boiled egg" + desc = "A hard boiled egg." + icon_state = "egg" + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 2) + +/obj/item/weapon/reagent_containers/food/snacks/organ + name = "organ" + desc = "It's good for you." + icon = 'icons/obj/surgery.dmi' + icon_state = "appendix" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", rand(3,5)) + reagents.add_reagent("toxin", rand(1,3)) + src.bitesize = 3 + + +/obj/item/weapon/reagent_containers/food/snacks/tofu + name = "Tofu" + icon_state = "tofu" + desc = "We all love tofu." + New() + ..() + reagents.add_reagent("nutriment", 3) + src.bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/tofurkey + name = "Tofurkey" + desc = "A fake turkey made from tofu." + icon_state = "tofurkey" + New() + ..() + reagents.add_reagent("nutriment", 12) + reagents.add_reagent("stoxin", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/stuffing + name = "Stuffing" + desc = "Moist, peppery breadcrumbs for filling the body cavities of dead birds. Dig in!" + icon_state = "stuffing" + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/fishfingers + name = "fish fingers" + desc = "A finger of fish." + icon_state = "fishfingers" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("carppheromones", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice + name = "huge mushroom slice" + desc = "A slice from a huge mushroom." + icon_state = "hugemushroomslice" + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("psilocybin", 3) + src.bitesize = 6 + +/obj/item/weapon/reagent_containers/food/snacks/tomatomeat + name = "tomato slice" + desc = "A slice from a huge tomato" + icon_state = "tomatomeat" + New() + ..() + reagents.add_reagent("nutriment", 3) + src.bitesize = 6 + +/obj/item/weapon/reagent_containers/food/snacks/meat/spiderleg + name = "spider leg" + desc = "A still twitching leg of a giant spider... you don't really want to eat this, do you?" + icon_state = "spiderleg" + food_flags = FOOD_MEAT + New() + ..() + poisonsacs = new /obj/item/weapon/reagent_containers/food/snacks/spiderpoisongland + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("toxin", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/faggot + name = "faggot" + desc = "A great meal all round. Not a cord of wood." + icon_state = "faggot" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sausage + name = "sausage" + desc = "A piece of mixed, long meat." + icon_state = "sausage" + food_flags = FOOD_MEAT + + New() + ..() + eatverb = pick("bite","chew","nibble","deep throat","gobble","chomp") + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/donkpocket + name = "\improper Donk-pocket" + desc = "The food of choice for the seasoned traitor." + icon_state = "donkpocket" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 4) + + var/warm = 0 + proc/cooltime() //Not working, derp? + if(warm) + spawn(4200) //ew + warm = 0 + reagents.del_reagent("tricordrazine") + name = initial(name) + return + +/obj/item/weapon/reagent_containers/food/snacks/brainburger + name = "brainburger" + desc = "A strange looking burger. It looks almost sentient." + icon_state = "brainburger" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("alkysine", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/ghostburger + name = "ghost burger" + desc = "Spooky! It doesn't look very filling." + icon_state = "ghostburger" + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/human + var/hname = "" + var/job = null + + + name = "-burger" + desc = "A bloody burger." + icon_state = "hburger" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/monkeyburger + name = "burger" + desc = "The cornerstone of every nutritious breakfast." + icon_state = "hburger" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/monkeyburger/synth + name = "synthetic burger" + desc = "It tastes like a normal burger, but it's just not the same." + icon_state = "hburger" + New() + ..() + reagents.add_reagent("nutriment", 6) + +/obj/item/weapon/reagent_containers/food/snacks/appendixburger + name = "appendix burger" + desc = "Tastes like appendicitis." + icon_state = "hburger" + food_flags = FOOD_MEAT + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/fishburger + name = "fillet -o- carp sandwich" + desc = "Almost like a carp is yelling somewhere... Give me back that fillet -o- carp, give me that carp." + icon_state = "fishburger" + food_flags = FOOD_MEAT + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("carppheromones", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/tofuburger + name = "tofu burger" + desc = "What.. is that meat?" + icon_state = "tofuburger" + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/chickenburger + name = "chicken burger" + desc = "Tastes like chi...oh wait!" + icon_state = "mc_chicken" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/chickenburger/New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/roburger + name = "roburger" + desc = "The lettuce is the only organic component. Beep." + icon_state = "roburger" + New() + ..() + reagents.add_reagent("nanites", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/roburgerbig + name = "roburger" + desc = "This massive patty looks like poison. Beep." + icon_state = "roburger" + volume = 100 + New() + ..() + reagents.add_reagent("nanites", 100) + bitesize = 0.1 + +/obj/item/weapon/reagent_containers/food/snacks/xenoburger + name = "xenoburger" + desc = "Smells caustic. Tastes like heresy." + icon_state = "xburger" + food_flags = FOOD_MEAT + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/clownburger + name = "clown burger" + desc = "This tastes funny..." + icon_state = "clownburger" + New() + ..() +/* + var/datum/disease/F = new /datum/disease/pierrot_throat(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 4, data) +*/ + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/mimeburger + name = "mime burger" + desc = "Its taste defies language." + icon_state = "mimeburger" + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/omelette //FUCK THIS + name = "omelette du fromage" + desc = "That's all you can say!" + icon_state = "omelette" + food_flags = FOOD_ANIMAL //made from eggs + trash = /obj/item/trash/plate + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/muffin + name = "muffin" + desc = "A delicious and spongy little cake." + icon_state = "muffin" + food_flags = FOOD_SWEET | FOOD_ANIMAL + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/muffin/berry + name = "berry muffin" + icon_state = "berrymuffin" + desc = "A delicious and spongy little cake, with berries." + +/obj/item/weapon/reagent_containers/food/snacks/muffin/booberry + name = "booberry muffin" + icon_state = "booberrymuffin" + desc = "My stomach is a graveyard! No living being can quench my bloodthirst!" + +/obj/item/weapon/reagent_containers/food/snacks/muffin/dindumuffin + name = "Dindu Muffin" + desc = "This muffin didn't do anything." + icon_state = "dindumuffins" + +/obj/item/weapon/reagent_containers/food/snacks/pie + name = "banana cream pie" + desc = "Just like back home, on clown planet! HONK!" + icon_state = "pie" + trash = /obj/item/trash/pietin + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("banana",5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/pie/throw_impact(atom/hit_atom) + ..() + if(isturf(hit_atom)) + new/obj/effect/decal/cleanable/pie_smudge(src.loc) + if(trash) new trash(src.loc) + qdel(src) + +/obj/item/weapon/reagent_containers/food/snacks/pie/empty //so the H.O.N.K. cream pie mortar can't generate free nutriment + trash = null + New() + ..() + reagents.clear_reagents() + +/obj/item/weapon/reagent_containers/food/snacks/berryclafoutis + name = "berry clafoutis" + desc = "No black birds, this is a good sign." + icon_state = "berryclafoutis" + trash = /obj/item/trash/plate + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("berryjuice", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/waffles + name = "waffles" + desc = "Mmm, waffles" + icon_state = "waffles" + trash = /obj/item/trash/waffles + food_flags = FOOD_ANIMAL + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/eggplantparm + name = "Eggplant Parmigiana" + desc = "The only good recipe for eggplant." + icon_state = "eggplantparm" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/soylentgreen + name = "Soylent Green" + desc = "Not made of people. Honest." //Totally people. + icon_state = "soylent_green" + trash = /obj/item/trash/waffles + New() + ..() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/soylenviridians + name = "Soylen Virdians" + desc = "Not made of people. Honest." //Actually honest for once. + icon_state = "soylent_yellow" + trash = /obj/item/trash/waffles + New() + ..() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/pie/discount + name = "Discount Pie" + icon_state = "meatpie" + desc = "Regulatory laws prevent us from lying to you in the technical sense, so you know this has to contain at least some meat!" + food_flags = FOOD_MEAT + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment",2) + reagents.add_reagent("discount",2) + reagents.add_reagent("toxin",2) + reagents.add_reagent("sugar",4) + +/obj/item/weapon/reagent_containers/food/snacks/pie/meatpie + name = "Meat-pie" + icon_state = "meatpie" + desc = "An old barber recipe, very delicious!" + food_flags = FOOD_MEAT + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/pie/tofupie + name = "Tofu-pie" + icon_state = "meatpie" + desc = "A delicious tofu pie." + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/pie/amanita_pie + name = "amanita pie" + desc = "Sweet and tasty poison pie." + icon_state = "amanita_pie" + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("amatoxin", 3) + reagents.add_reagent("psilocybin", 1) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/pie/plump_pie + name = "plump pie" + desc = "I bet you love stuff made out of plump helmets!" + icon_state = "plump_pie" + New() + ..() + reagents.clear_reagents() + if(prob(10)) + name = "exceptional plump pie" + desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!" + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("tricordrazine", 5) + bitesize = 2 + else + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/pie/xemeatpie + name = "Xeno-pie" + icon_state = "xenomeatpie" + desc = "A delicious meatpie. Probably heretical." + food_flags = FOOD_MEAT + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/wingfangchu + name = "Wing Fang Chu" + desc = "A savory dish of alien wing wang in soy." + icon_state = "wingfangchu" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/human/kabob + name = "-kabob" + icon_state = "kabob" + desc = "A human meat, on a stick." + trash = /obj/item/stack/rods + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/monkeykabob + name = "Meat-kabob" + icon_state = "kabob" + desc = "Delicious meat, on a stick." + trash = /obj/item/stack/rods + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/monkeykabob/synth + name = "Synth-kabob" + icon_state = "kabob" + desc = "Synthetic meat, on a stick." + trash = /obj/item/stack/rods + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/corgikabob + name = "Corgi-kabob" + icon_state = "kabob" + desc = "Only someone without a heart could make this." + trash = /obj/item/stack/rods + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/tofukabob + name = "Tofu-kabob" + icon_state = "kabob" + desc = "Vegan meat, on a stick." + trash = /obj/item/stack/rods + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cubancarp + name = "Cuban Carp" + desc = "A grifftastic sandwich that burns your tongue and then leaves it numb!" + icon_state = "cubancarp" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("carppheromones", 3) + reagents.add_reagent("capsaicin", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/popcorn + name = "popcorn" + desc = "Now let's find some cinema." + icon_state = "popcorn" + trash = /obj/item/trash/popcorn + var/unpopped = 0 + +/obj/item/weapon/reagent_containers/food/snacks/popcorn/New() + ..() + eatverb = pick("bite","crunch","nibble","gnaw","gobble","chomp") + unpopped = rand(1,10) + reagents.add_reagent("nutriment", 2) + bitesize = 0.1 //this snack is supposed to be eating during looooong time. And this it not dinner food! --rastaf0 + +/obj/item/weapon/reagent_containers/food/snacks/popcorn/On_Consume() + if(prob(unpopped)) //lol ...what's the point? << AINT SO POINTLESS NO MORE + to_chat(usr, "You bite down on an un-popped kernel, and it hurts your teeth!") + unpopped = max(0, unpopped-1) + reagents.add_reagent("sacid", 0.1) //only a little tingle. + + +/obj/item/weapon/reagent_containers/food/snacks/sosjerky + name = "\improper Scaredy's Private Reserve Beef Jerky" + icon_state = "sosjerky" + desc = "Beef jerky made from the finest space cows." + trash = /obj/item/trash/sosjerky + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 4) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/no_raisin + name = "4no raisins" + icon_state = "4no_raisins" + desc = "Best raisins in the universe. Not sure why." + trash = /obj/item/trash/raisins + New() + ..() + reagents.add_reagent("nutriment", 6) + +/obj/item/weapon/reagent_containers/food/snacks/bustanuts + name = "Busta-Nuts" + icon_state = "busta_nut" + desc = "2hard4u" + trash = /obj/item/trash/bustanuts + New() + ..() + reagents.add_reagent("bustanut", 6) + reagents.add_reagent("sodiumchloride", 6) + +/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie + name = "space twinkie" + icon_state = "space_twinkie" + desc = "Guaranteed to survive longer than you will." + New() + ..() + reagents.add_reagent("sugar", 4) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers + name = "Cheesie Honkers" + icon_state = "cheesie_honkers" + desc = "Bite sized cheesie snacks that will honk all over your mouth" + trash = /obj/item/trash/cheesie + food_flags = FOOD_ANIMAL //cheese + + New() + ..() + reagents.add_reagent("nutriment", 4) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/syndicake + name = "Syndi-Cakes" + icon_state = "syndi_cakes" + desc = "An extremely moist snack cake that tastes just as good after being nuked." + trash = /obj/item/trash/syndi_cakes + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("doctorsdelight", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/discountchocolate + name = "\improper Discount Dan's Chocolate Bar" + desc = "Something tells you that the glowing green filling inside, isn't healthy." + icon_state = "danbar" + trash = /obj/item/trash/discountchocolate + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("discount", 4) + reagents.add_reagent("moonrocks", 4) + reagents.add_reagent("toxicwaste", 8) + reagents.add_reagent("chemical_waste", 2) //Does nothing, but it's pretty fucking funny. + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/discountburger + name = "\improper Discount Dan's On The Go Burger" + desc = "Its still warm..." + icon_state = "goburger" //Someone make a better sprite for this. + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("discount", 4) + reagents.add_reagent("beff", 4) + reagents.add_reagent("horsemeat", 4) + reagents.add_reagent("offcolorcheese", 4) + reagents.add_reagent("chemical_waste", 2) //Does nothing, but it's pretty fucking funny. + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/danitos + name = "Danitos" + desc = "For only the most MLG hardcore robust spessmen." + icon_state = "danitos" + trash = /obj/item/trash/danitos + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("discount", 4) + reagents.add_reagent("bonemarrow", 4) + reagents.add_reagent("toxicwaste", 8) + reagents.add_reagent("bustanut", 2) //YOU FEELIN HARDCORE BRAH? + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/discountburrito + name = "Discount Dan's Burritos" + desc = "The perfect blend of cheap processing and cheap materials." + icon_state = "danburrito" + var/list/ddname = list("Spooky Dan's BOO-ritos - Texas Toast Chainsaw Massacre Flavor","Sconto Danilo's Burritos - 50% Real Mozzarella Pepperoni Pizza Party Flavor","Descuento Danito's Burritos - Pancake Sausage Brunch Flavor","Descuento Danito's Burritos - Homestyle Comfort Flavor","Spooky Dan's BOO-ritos - Nightmare on Elm Meat Flavor","Descuento Danito's Burritos - Strawberrito Churro Flavor","Descuento Danito's Burritos - Beff and Bean Flavor") + food_flags = FOOD_MEAT + + New() + ..() + name = pick(ddname) + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("discount", 6) + reagents.add_reagent("irradiatedbeans", 4) + reagents.add_reagent("refriedbeans", 4) + reagents.add_reagent("mutatedbeans", 4) + reagents.add_reagent("beff", 4) + reagents.add_reagent("chemical_waste", 2) //Does nothing, but it's pretty fucking funny. + bitesize = 2 + + + +/obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato + name = "Loaded Baked Potato" + desc = "Totally baked." + icon_state = "loadedbakedpotato" + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/fries + name = "Space Fries" + desc = "AKA: French Fries, Freedom Fries, etc" + icon_state = "fries" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 4) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/soydope + name = "Soy Dope" + desc = "Dope from a soy." + icon_state = "soydope" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/spaghetti + name = "Spaghetti" + desc = "Now thats a nice pasta!" + icon_state = "spaghetti" + New() + ..() + reagents.add_reagent("nutriment", 1) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/cheesyfries + name = "Cheesy Fries" + desc = "Fries. Covered in cheese. Duh." + icon_state = "cheesyfries" + trash = /obj/item/trash/plate + food_flags = FOOD_ANIMAL //cheese + + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/fortunecookie + name = "Fortune cookie" + desc = "A true prophecy in each cookie!" + icon_state = "fortune_cookie" + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/badrecipe + name = "Burned mess" + desc = "Someone should be demoted from chef for this." + icon_state = "badrecipe" + New() + ..() + reagents.add_reagent("toxin", 1) + reagents.add_reagent("carbon", 3) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/meatsteak + name = "Meat steak" + desc = "A piece of hot spicy meat." + icon_state = "meatstake" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("sodiumchloride", 1) + reagents.add_reagent("blackpepper", 1) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/meatsteak/synth + name = "Synthmeat steak" + desc = "It's still a delicious steak, but it has no soul." + icon_state = "meatstake" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("sodiumchloride", 1) + reagents.add_reagent("blackpepper", 1) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/spacylibertyduff + name = "Spacy Liberty Duff" + desc = "Jello gelatin, from Alfred Hubbard's cookbook" + icon_state = "spacylibertyduff" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("psilocybin", 6) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/amanitajelly + name = "Amanita Jelly" + desc = "Looks curiously toxic" + icon_state = "amanitajelly" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("amatoxin", 6) + reagents.add_reagent("psilocybin", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/poppypretzel + name = "Poppy pretzel" + desc = "It's all twisted up!" + icon_state = "poppypretzel" + bitesize = 2 + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/meatballsoup + name = "Meatball soup" + desc = "You've got balls kid, BALLS!" + icon_state = "meatballsoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_MEAT | FOOD_LIQUID + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("water", 5) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/slimesoup + name = "slime soup" + desc = "If no water is available, you may substitute tears." + icon_state = "slimesoup" + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("slimejelly", 5) + reagents.add_reagent("water", 10) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/bloodsoup + name = "Tomato soup" + desc = "Smells like copper" + icon_state = "tomatosoup" + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("blood", 10) + reagents.add_reagent("water", 5) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/clownstears + name = "Clown's Tears" + desc = "Not very funny." + icon_state = "clownstears" + food_flags = FOOD_LIQUID | FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("banana", 5) + reagents.add_reagent("water", 10) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/vegetablesoup + name = "Vegetable soup" + desc = "A true vegan meal." //TODO + icon_state = "vegetablesoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("water", 5) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/nettlesoup + name = "Nettle soup" + desc = "To think, the botanist would've beat you to death with one of these." + icon_state = "nettlesoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("water", 5) + reagents.add_reagent("tricordrazine", 5) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/mysterysoup + name = "Mystery soup" + desc = "The mystery is, why aren't you eating it?" + icon_state = "mysterysoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + var/mysteryselect = pick(1,2,3,4,5,6,7,8,9,10) + switch(mysteryselect) + if(1) + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("capsaicin", 3) + reagents.add_reagent("tomatojuice", 2) + if(2) + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("frostoil", 3) + reagents.add_reagent("tomatojuice", 2) + if(3) + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("water", 5) + reagents.add_reagent("tricordrazine", 5) + if(4) + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("water", 10) + if(5) + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("banana", 10) + if(6) + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("blood", 10) + food_flags |= FOOD_MEAT + if(7) + reagents.add_reagent("slimejelly", 10) + reagents.add_reagent("water", 10) + if(8) + reagents.add_reagent("carbon", 10) + reagents.add_reagent("toxin", 10) + if(9) + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("tomatojuice", 10) + if(10) + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("tomatojuice", 5) + reagents.add_reagent("imidazoline", 5) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/wishsoup + name = "Wish Soup" + desc = "I wish this was soup." + icon_state = "wishsoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("water", 10) + bitesize = 5 + if(prob(25)) + src.desc = "A wish come true!" + reagents.add_reagent("nutriment", 8) + +/obj/item/weapon/reagent_containers/food/snacks/hotchili + name = "Hot Chili" + desc = "A five alarm Texan Chili!" + icon_state = "hotchili" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("capsaicin", 3) + reagents.add_reagent("tomatojuice", 2) + bitesize = 5 + + +/obj/item/weapon/reagent_containers/food/snacks/coldchili + name = "Cold Chili" + desc = "This slush is barely a liquid!" + icon_state = "coldchili" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("frostoil", 3) + reagents.add_reagent("tomatojuice", 2) + bitesize = 5 + +/* No more of this +/obj/item/weapon/reagent_containers/food/snacks/telebacon + name = "Tele Bacon" + desc = "It tastes a little odd but it is still delicious." + icon_state = "bacon" + var/obj/item/beacon/bacon/baconbeacon + bitesize = 2 + New() + ..() + reagents.add_reagent("nutriment", 4) + baconbeacon = new /obj/item/beacon/bacon(src) + On_Consume() + if(!reagents.total_volume) + baconbeacon.loc = usr + baconbeacon.digest_delay() +*/ + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube + name = "monkey cube" + desc = "Just add water!" + icon_state = "monkeycube" + bitesize = 12 + //var/wrapped = 0 + food_flags = FOOD_MEAT + + var/monkey_type = /mob/living/carbon/monkey + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/New() + ..() + reagents.add_reagent("nutriment",10) + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/afterattack(obj/O, mob/user,proximity) + if(!proximity) return + if(istype(O,/obj/structure/sink) && !wrapped) + to_chat(user, "You place [src] under a stream of water...") + return Expand() + ..() + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/attack_self(mob/user) + if(wrapped) + Unwrap(user) + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/On_Consume(var/mob/M) + + to_chat(M, "Something inside of you suddently expands!") + + if (istype(M, /mob/living/carbon/human)) + //Do not try to understand. + var/obj/item/weapon/surprise = new/obj/item/weapon(M) + var/mob/living/carbon/monkey/ook = new monkey_type(null) //no other way to get access to the vars, alas + surprise.icon = ook.icon + surprise.icon_state = ook.icon_state + surprise.name = "malformed [ook.name]" + surprise.desc = "Looks like \a very deformed [ook.name], a little small for its kind. It shows no signs of life." + qdel(ook) //rip nullspace monkey + surprise.transform *= 0.6 + surprise.add_blood(M) + var/mob/living/carbon/human/H = M + var/datum/organ/external/E = H.get_organ("chest") + E.fracture() + for (var/datum/organ/internal/I in E.internal_organs) + I.take_damage(rand(I.min_bruised_damage, I.min_broken_damage+1)) + + if (!E.hidden && prob(60)) //set it snuggly + E.hidden = surprise + E.cavity = 0 + else //someone is having a bad day + E.createwound(CUT, 30) + E.embed(surprise) + else if (ismonkey(M)) + M.visible_message("[M] suddenly tears in half!") + var/mob/living/carbon/monkey/ook = new monkey_type(M.loc) + ook.name = "malformed [ook.name]" + ook.transform *= 0.6 + ook.add_blood(M) + M.gib() + ..() + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Expand() + + for(var/mob/M in viewers(src,7)) + to_chat(M, "\The [src] expands!") + new monkey_type(get_turf(src)) + qdel(src) + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Unwrap(mob/user as mob) + + icon_state = "monkeycube" + desc = "Just add water!" + to_chat(user, "You unwrap the cube.") + wrapped = 0 + return + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped + desc = "Still wrapped in some paper." + icon_state = "monkeycubewrap" + wrapped = 1 + + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/farwacube + name = "farwa cube" + monkey_type =/mob/living/carbon/monkey/tajara +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube + name = "farwa cube" + monkey_type =/mob/living/carbon/monkey/tajara + + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/stokcube + name = "stok cube" + monkey_type =/mob/living/carbon/monkey/unathi +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube + name = "stok cube" + monkey_type =/mob/living/carbon/monkey/unathi + + +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/neaeracube + name = "neaera cube" + monkey_type =/mob/living/carbon/monkey/skrell +/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube + name = "neaera cube" + monkey_type =/mob/living/carbon/monkey/skrell + + +/obj/item/weapon/reagent_containers/food/snacks/spellburger + name = "Spell Burger" + desc = "This is absolutely Ei Nath." + icon_state = "spellburger" + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/bigbiteburger + name = "Big Bite Burger" + desc = "Forget the Big Mac. THIS is the future!" + icon_state = "bigbiteburger" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 14) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/enchiladas + name = "Enchiladas" + desc = "Viva La Mexico!" + icon_state = "enchiladas" + trash = /obj/item/trash/tray + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment",8) + reagents.add_reagent("capsaicin", 6) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/monkeysdelight + name = "monkey's Delight" + desc = "Eeee Eee!" + icon_state = "monkeysdelight" + trash = /obj/item/trash/tray + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 10) + reagents.add_reagent("banana", 5) + reagents.add_reagent("blackpepper", 1) + reagents.add_reagent("sodiumchloride", 1) + bitesize = 6 + +/obj/item/weapon/reagent_containers/food/snacks/baguette + name = "Baguette" + desc = "Bon appetit!" + icon_state = "baguette" + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("blackpepper", 1) + reagents.add_reagent("sodiumchloride", 1) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/fishandchips + name = "Fish and Chips" + desc = "I do say so myself chap." + icon_state = "fishandchips" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("carppheromones", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/sandwich + name = "Sandwich" + desc = "A grand creation of meat, cheese, bread, and several leaves of lettuce! Arthur Dent would be proud." + icon_state = "sandwich" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/toastedsandwich + name = "Toasted Sandwich" + desc = "Now if you only had a pepper bar." + icon_state = "toastedsandwich" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT //This is made from a sandwich, which contains meat! + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("carbon", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/grilledcheese + name = "Grilled Cheese Sandwich" + desc = "Goes great with Tomato soup!" + icon_state = "toastedsandwich" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 7) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/tomatosoup + name = "Tomato Soup" + desc = "Drinking this feels like being a vampire! A tomato vampire..." + icon_state = "tomatosoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("tomatojuice", 10) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/rofflewaffles + name = "Roffle Waffles" + desc = "Waffles from Roffle. Co." + icon_state = "rofflewaffles" + trash = /obj/item/trash/waffles + food_flags = FOOD_ANIMAL //eggs + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("psilocybin", 8) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/stew + name = "Stew" + desc = "A nice and warm stew. Healthy and strong." + icon_state = "stew" + food_flags = FOOD_LIQUID | FOOD_MEAT + + New() + ..() + eatverb = pick("slurp","sip","suck","inhale","drink") + reagents.add_reagent("nutriment", 10) + reagents.add_reagent("tomatojuice", 5) + reagents.add_reagent("imidazoline", 5) + reagents.add_reagent("water", 5) + bitesize = 10 + +/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast + name = "Jellied Toast" + desc = "A slice of bread covered with delicious jam." + icon_state = "jellytoast" + trash = /obj/item/trash/plate + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 1) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast/cherry + New() + ..() + reagents.add_reagent("cherryjelly", 5) + +/obj/item/weapon/reagent_containers/food/snacks/jelliedtoast/slime + New() + ..() + reagents.add_reagent("slimejelly", 5) + +/obj/item/weapon/reagent_containers/food/snacks/jellyburger + name = "Jelly Burger" + desc = "Culinary delight..?" + icon_state = "jellyburger" + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/jellyburger/slime + New() + ..() + reagents.add_reagent("slimejelly", 5) + +/obj/item/weapon/reagent_containers/food/snacks/jellyburger/cherry + New() + ..() + reagents.add_reagent("cherryjelly", 5) + +/obj/item/weapon/reagent_containers/food/snacks/milosoup + name = "Milosoup" + desc = "The universes best soup! Yum!!!" + icon_state = "milosoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("water", 5) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat + name = "Stewed Soy Meat" + desc = "Even non-vegetarians will LOVE this!" + icon_state = "stewedsoymeat" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/boiledspaghetti + name = "Boiled Spaghetti" + desc = "A plain dish of noodles, this sucks." + icon_state = "spaghettiboiled" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/boiledrice + name = "Boiled Rice" + desc = "A boring dish of boring rice." + icon_state = "boiledrice" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/ricepudding + name = "Rice Pudding" + desc = "Where's the Jam!" + icon_state = "rpudding" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 4) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/riceball + name = "Rice Ball" + desc = "In mining culture, this is also known as a donut." + icon_state = "riceball" + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/eggplantsushi + name = "Spicy Eggplant Sushi Rolls" + desc = "Eggplant rolls are an example of Asian Fusion as eggplants were introduced from mainland Asia to Japan. This dish is Earth Fusion, originating after the introduction of the chili from the Americas to Japan. Fusion HA!" + icon_state = "eggplantsushi" + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("capsaicin", 2) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/pastatomato + name = "Spaghetti" + desc = "Spaghetti and crushed tomatoes. Just like your abusive father used to make!" + icon_state = "pastatomato" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("tomatojuice", 10) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/copypasta + name = "copypasta" + desc = "You probably shouldn't try this, you always hear people talking about how bad it is..." + icon_state = "copypasta" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 12) + reagents.add_reagent("tomatojuice", 20) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/meatballspaghetti + name = "Spaghetti & Meatballs" + desc = "Now thats a nic'e meatball!" + icon_state = "meatballspaghetti" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/spesslaw + name = "Spesslaw" + desc = "A lawyers favourite" + icon_state = "spesslaw" + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/poppypretzel + name = "Poppy Pretzel" + desc = "A large soft pretzel full of POP!" + icon_state = "poppypretzel" + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/carrotfries + name = "Carrot Fries" + desc = "Tasty fries from fresh Carrots." + icon_state = "carrotfries" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("imidazoline", 3) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/superbiteburger + name = "Super Bite Burger" + desc = "This is a mountain of a burger. FOOD!" + icon_state = "superbiteburger" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 40) + bitesize = 10 + +/obj/item/weapon/reagent_containers/food/snacks/candiedapple + name = "Candied Apple" + desc = "An apple coated in sugary sweetness." + icon_state = "candiedapple" + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/pie/applepie + name = "Apple Pie" + desc = "A pie containing sweet sweet love...or apple." + icon_state = "applepie" + food_flags = FOOD_SWEET + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 4) + bitesize = 3 + + +/obj/item/weapon/reagent_containers/food/snacks/pie/cherrypie + name = "Cherry Pie" + desc = "Taste so good, make a grown man cry." + icon_state = "cherrypie" + food_flags = FOOD_SWEET + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 4) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/twobread + name = "Two Bread" + desc = "It is very bitter and winy." + icon_state = "twobread" + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/jellysandwich + name = "Jelly Sandwich" + desc = "You wish you had some peanut butter to go with this..." + icon_state = "jellysandwich" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 2) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/slime + New() + ..() + reagents.add_reagent("slimejelly", 5) + +/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/cherry + New() + ..() + reagents.add_reagent("cherryjelly", 5) +/* +/obj/item/weapon/reagent_containers/food/snacks/boiledslimecore + name = "Boiled slime Core" + desc = "A boiled red thing." + icon_state = "boiledslimecore" + New() + ..() + reagents.add_reagent("slimejelly", 5) + bitesize = 3 +*/ +/obj/item/weapon/reagent_containers/food/snacks/mint + name = "mint" + desc = "it is only wafer thin." + icon_state = "mint" + New() + ..() + reagents.add_reagent("minttoxin", 1) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/mushroomsoup + name = "chantrelle soup" + desc = "A delicious and hearty mushroom soup." + icon_state = "mushroomsoup" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit + name = "plump helmet biscuit" + desc = "This is a finely-prepared plump helmet biscuit. The ingredients are exceptionally minced plump helmet, and well-minced dwarven wheat flour." + icon_state = "phelmbiscuit" + New() + ..() + if(prob(10)) + name = "exceptional plump helmet biscuit" + desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!" + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("tricordrazine", 5) + bitesize = 2 + else + reagents.add_reagent("nutriment", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/chawanmushi + name = "chawanmushi" + desc = "A legendary egg custard that makes friends out of enemies. Probably too hot for a cat to eat." + icon_state = "chawanmushi" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/beetsoup + name = "beet soup" + desc = "Wait, how do you spell it again..?" + icon_state = "beetsoup" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_LIQUID + + New() + ..() + eatverb = pick("slurp","sip","suck","inhale","drink") + name = pick("borsch","bortsch","borstch","borsh","borshch","borscht") + reagents.add_reagent("nutriment", 8) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/herbsalad + name = "herb salad" + desc = "A tasty salad with apples on top." + icon_state = "herbsalad" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/validsalad + name = "valid salad" + desc = "It's just an herb salad with meatballs and fried potato slices. Nothing suspicious about it." + icon_state = "validsalad" + trash = /obj/item/trash/snack_bowl + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("doctorsdelight", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/appletart + name = "golden apple streusel tart" + desc = "A tasty dessert that won't make it through a metal detector." + icon_state = "gappletart" + trash = /obj/item/trash/plate + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("gold", 5) + bitesize = 3 + +/////////////////////////////////////////////////Sliceable//////////////////////////////////////// +// All the food items that can be sliced into smaller bits like Meatbread and Cheesewheels + +// sliceable is just an organization type path, it doesn't have any additional code or variables tied to it. + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread + name = "meatbread loaf" + desc = "The culinary base of every self-respecting eloquen/tg/entleman." + icon_state = "meatbread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatbreadslice + slices_num = 5 + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 30) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/meatbreadslice + name = "meatbread slice" + desc = "A slice of delicious meatbread." + icon_state = "meatbreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread + name = "xenomeatbread loaf" + desc = "The culinary base of every self-respecting eloquen/tg/entleman. Extra Heretical." + icon_state = "xenomeatbread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/xenomeatbreadslice + slices_num = 5 + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 30) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/xenomeatbreadslice + name = "xenomeatbread slice" + desc = "A slice of delicious meatbread. Extra Heretical." + icon_state = "xenobreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/spidermeatbread + name = "spider meat loaf" + desc = "Reassuringly green meatloaf made from spider meat." + icon_state = "spidermeatbread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/spidermeatbreadslice + slices_num = 5 + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 30) //If the meat is toxic, it will inherit that + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/spidermeatbreadslice + name = "spider meat bread slice" + desc = "A slice of meatloaf made from an animal that most likely still wants you dead." + icon_state = "xenobreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread/synth + name = "synthmeatbread loaf" + desc = "A loaf of synthetic meatbread. You can just taste the mass-production." + icon_state = "meatbread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatbreadslice/synth + slices_num = 5 + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 30) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/meatbreadslice/synth + name = "synthmeatbread slice" + desc = "A slice of synthetic meatbread." + icon_state = "meatbreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread + name = "banana-nut bread" + desc = "A heavenly and filling treat." + icon_state = "bananabread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/bananabreadslice + slices_num = 5 + New() + ..() + reagents.add_reagent("banana", 20) + reagents.add_reagent("nutriment", 20) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/bananabreadslice + name = "banana-nut bread slice" + desc = "A slice of delicious banana bread." + icon_state = "bananabreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread + name = "Tofubread" + icon_state = "Like meatbread but for vegetarians. Not guaranteed to give superpowers." + icon_state = "tofubread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/tofubreadslice + slices_num = 5 + New() + ..() + reagents.add_reagent("nutriment", 30) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/tofubreadslice + name = "tofubread slice" + desc = "A slice of delicious tofubread." + icon_state = "tofubreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake + name = "carrot cake" + desc = "A favorite desert of a certain wascally wabbit. Not a lie." + icon_state = "carrotcake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/carrotcakeslice + slices_num = 5 + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 25) + reagents.add_reagent("imidazoline", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/carrotcakeslice + name = "carrot cake slice" + desc = "Carrotty slice of Carrot Cake, carrots are good for your eyes! Also not a lie." + icon_state = "carrotcake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake + name = "brain cake" + desc = "A squishy cake-thing." + icon_state = "braincake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/braincakeslice + slices_num = 5 + food_flags = FOOD_MEAT | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 25) + reagents.add_reagent("alkysine", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/braincakeslice + name = "brain cake slice" + desc = "Lemme tell you something about prions. THEY'RE DELICIOUS." + icon_state = "braincakeslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_MEAT | FOOD_ANIMAL //meat, milk, eggs + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake + name = "cheese cake" + desc = "DANGEROUSLY cheesy." + icon_state = "cheesecake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/cheesecakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL //cheese + + New() + ..() + reagents.add_reagent("nutriment", 25) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cheesecakeslice + name = "cheese cake slice" + desc = "Slice of pure cheestisfaction" + icon_state = "cheesecake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake + name = "vanilla cake" + desc = "A plain cake, not a lie." + icon_state = "plaincake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/plaincakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL //milk and eggs + + New() + ..() + reagents.add_reagent("nutriment", 20) + +/obj/item/weapon/reagent_containers/food/snacks/plaincakeslice + name = "vanilla cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "plaincake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake + name = "orange cake" + desc = "A cake with added orange." + icon_state = "orangecake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/orangecakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 20) + +/obj/item/weapon/reagent_containers/food/snacks/orangecakeslice + name = "orange cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "orangecake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake + name = "lime cake" + desc = "A cake with added lime." + icon_state = "limecake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/limecakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 20) + +/obj/item/weapon/reagent_containers/food/snacks/limecakeslice + name = "lime cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "limecake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake + name = "lemon cake" + desc = "A cake with added lemon." + icon_state = "lemoncake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/lemoncakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + New() + ..() + reagents.add_reagent("nutriment", 20) + +/obj/item/weapon/reagent_containers/food/snacks/lemoncakeslice + name = "lemon cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "lemoncake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake + name = "chocolate cake" + desc = "A cake with added chocolate" + icon_state = "chocolatecake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/chocolatecakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 20) + +/obj/item/weapon/reagent_containers/food/snacks/chocolatecakeslice + name = "chocolate cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "chocolatecake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel + name = "cheese wheel" + desc = "A big wheel of delicious Cheddar." + icon_state = "cheesewheel" + filling_color = "#FFCC33" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/cheesewedge + slices_num = 5 + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 20) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cheesewedge + name = "cheese wedge" + desc = "A wedge of delicious Cheddar. The cheese wheel it was cut from can't have gone far." + icon_state = "cheesewedge" + filling_color = "#FFCC33" + bitesize = 2 + food_flags = FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake + name = "Birthday Cake" + desc = "Happy Birthday..." + icon_state = "birthdaycake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/birthdaycakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 20) + reagents.add_reagent("sprinkles", 10) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/birthdaycakeslice + name = "Birthday Cake slice" + desc = "A slice of your birthday" + icon_state = "birthdaycakeslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/bread + name = "Bread" + icon_state = "Some plain old Earthen bread." + icon_state = "bread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/breadslice + slices_num = 5 + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/breadslice + name = "Bread slice" + desc = "A slice of home." + icon_state = "breadslice" + trash = /obj/item/trash/plate + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/creamcheesebread + name = "Cream Cheese Bread" + desc = "Yum yum yum!" + icon_state = "creamcheesebread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/creamcheesebreadslice + slices_num = 5 + New() + ..() + reagents.add_reagent("nutriment", 20) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/creamcheesebreadslice + name = "Cream Cheese Bread slice" + desc = "A slice of yum!" + icon_state = "creamcheesebreadslice" + trash = /obj/item/trash/plate + bitesize = 2 + + +/obj/item/weapon/reagent_containers/food/snacks/watermelonslice + name = "Watermelon Slice" + desc = "A slice of watery goodness." + icon_state = "watermelonslice" + bitesize = 2 + food_flags = FOOD_SWEET + + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake + name = "Apple Cake" + desc = "A cake centred with Apple" + icon_state = "applecake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/applecakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 15) + +/obj/item/weapon/reagent_containers/food/snacks/applecakeslice + name = "Apple Cake slice" + desc = "A slice of heavenly cake." + icon_state = "applecakeslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie //You can't throw this pie + name = "Pumpkin Pie" + desc = "A delicious treat for the autumn months." + icon_state = "pumpkinpie" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/pumpkinpieslice + slices_num = 5 + trash = /obj/item/trash/pietin + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 15) + +/obj/item/weapon/reagent_containers/food/snacks/pumpkinpieslice + name = "Pumpkin Pie slice" + desc = "A slice of pumpkin pie, with whipped cream on top. Perfection." + icon_state = "pumpkinpieslice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/cracker + name = "Cracker" + desc = "It's a salted cracker." + icon_state = "cracker" + + New() + ..() + reagents.add_reagent("nutriment", 1) + + + +/////////////////////////////////////////////////PIZZA//////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza + slices_num = 6 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita + name = "Margherita" + desc = "The most cheezy pizza in galaxy" + icon_state = "pizzamargherita" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/margheritaslice + slices_num = 6 + food_flags = FOOD_ANIMAL //cheese + + New() + ..() + reagents.add_reagent("nutriment", 40) + reagents.add_reagent("tomatojuice", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/margheritaslice + name = "Margherita slice" + desc = "A slice of the most cheezy pizza in galaxy" + icon_state = "pizzamargheritaslice" + bitesize = 2 + food_flags = FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza + name = "Meatpizza" + desc = "A filling pizza laden with meat; perfect for the manliest of carnivores." + icon_state = "meatpizza" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice + slices_num = 6 + food_flags = FOOD_MEAT | FOOD_ANIMAL //It has cheese! + + New() + ..() + reagents.add_reagent("nutriment", 50) + reagents.add_reagent("tomatojuice", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice + name = "Meatpizza slice" + desc = "A slice of pizza, packed with delicious meat." + icon_state = "meatpizzaslice" + bitesize = 2 + food_flags = FOOD_MEAT | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza/synth + name = "Synthmeatpizza" + desc = "A synthetic pizza laden with artificial meat; perfect for the stingiest of chefs." + icon_state = "meatpizza" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice/synth + slices_num = 6 + + New() + ..() + reagents.add_reagent("nutriment", 50) + reagents.add_reagent("tomatojuice", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice/synth + name = "Synthmeatpizza slice" + desc = "A slice of pizza, packed with synthetic meat." + icon_state = "meatpizzaslice" + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza + name = "Mushroompizza" + desc = "Very special pizza" + icon_state = "mushroompizza" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice + slices_num = 6 + New() + ..() + reagents.add_reagent("nutriment", 35) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice + name = "Mushroompizza slice" + desc = "Maybe it is the last slice of pizza in your life." + icon_state = "mushroompizzaslice" + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza + name = "Vegetable pizza" + desc = "No one of Tomatos Sapiens were harmed during making this pizza" + icon_state = "vegetablepizza" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice + slices_num = 6 + New() + ..() + reagents.add_reagent("nutriment", 30) + reagents.add_reagent("tomatojuice", 6) + reagents.add_reagent("imidazoline", 12) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice + name = "Vegetable pizza slice" + desc = "A slice of the most green pizza of all pizzas not containing green ingredients " + icon_state = "vegetablepizzaslice" + bitesize = 2 + +/obj/item/pizzabox + name = "pizza box" + desc = "A box suited for pizzas." + icon = 'icons/obj/food.dmi' + icon_state = "pizzabox1" + starting_materials = list(MAT_CARDBOARD = 3750) + w_type=RECYK_MISC + + var/open = 0 // Is the box open? + var/ismessy = 0 // Fancy mess on the lid + var/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pizza // Content pizza + var/list/boxes = list() // If the boxes are stacked, they come here + var/boxtag = "" + +/obj/item/pizzabox/update_icon() + + overlays = list() + + // Set appropriate description + if( open && pizza ) + desc = "A box suited for pizzas. It appears to have a [pizza.name] inside." + else if( boxes.len > 0 ) + desc = "A pile of boxes suited for pizzas. There appears to be [boxes.len + 1] boxes in the pile." + + var/obj/item/pizzabox/topbox = boxes[boxes.len] + var/toptag = topbox.boxtag + if( toptag != "" ) + desc = "[desc] The box on top has a tag, it reads: '[toptag]'." + else + desc = "A box suited for pizzas." + + if( boxtag != "" ) + desc = "[desc] The box has a tag, it reads: '[boxtag]'." + + // Icon states and overlays + if( open ) + if( ismessy ) + icon_state = "pizzabox_messy" + else + icon_state = "pizzabox_open" + + if( pizza ) + var/image/pizzaimg = image("food.dmi", icon_state = pizza.icon_state) + pizzaimg.pixel_y = -3 + overlays += pizzaimg + + return + else + // Stupid code because byondcode sucks + var/doimgtag = 0 + if( boxes.len > 0 ) + var/obj/item/pizzabox/topbox = boxes[boxes.len] + if( topbox.boxtag != "" ) + doimgtag = 1 + else + if( boxtag != "" ) + doimgtag = 1 + + if( doimgtag ) + var/image/tagimg = image("food.dmi", icon_state = "pizzabox_tag") + tagimg.pixel_y = boxes.len * 3 + overlays += tagimg + + icon_state = "pizzabox[boxes.len+1]" + +/obj/item/pizzabox/attack_hand( mob/user as mob ) + + if( open && pizza ) + user.put_in_hands( pizza ) + + to_chat(user, "You take the [src.pizza] out of the [src].") + src.pizza = null + update_icon() + return + + if( boxes.len > 0 ) + if( user.get_inactive_hand() != src ) + ..() + return + + var/obj/item/pizzabox/box = boxes[boxes.len] + boxes -= box + + user.put_in_hands( box ) + to_chat(user, "You remove the topmost [src] from your hand.") + box.update_icon() + update_icon() + return + ..() + +/obj/item/pizzabox/attack_self( mob/user as mob ) + + if( boxes.len > 0 ) + return + + open = !open + + if( open && pizza ) + ismessy = 1 + + update_icon() + +/obj/item/pizzabox/attackby( obj/item/I as obj, mob/user as mob ) + if( istype(I, /obj/item/pizzabox/) ) + var/obj/item/pizzabox/box = I + + if( !box.open && !src.open ) + // Make a list of all boxes to be added + var/list/boxestoadd = list() + boxestoadd += box + for(var/obj/item/pizzabox/i in box.boxes) + boxestoadd += i + + if( (boxes.len+1) + boxestoadd.len <= 5 ) + if(user.drop_item(I, src)) + + box.boxes = list() // Clear the box boxes so we don't have boxes inside boxes. - Xzibit + src.boxes.Add( boxestoadd ) + + box.update_icon() + update_icon() + + to_chat(user, "You put the [box] ontop of the [src]!") + + else + to_chat(user, "The stack is too high!") + else + to_chat(user, "Close the [box] first!") + + return + + if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/)) // Long ass fucking object name + if(src.pizza) to_chat(user, "[src] already has a pizza in it.") + else if(src.open) + if(user.drop_item(I, src)) + src.pizza = I + src.update_icon() + to_chat(user, "You put [I] in [src].") + else to_chat(user, "Open [src] first.") + + return + + if( istype(I, /obj/item/weapon/pen/) ) + + if( src.open ) + return + + var/t = input("Enter what you want to add to the tag:", "Write", null, null) as text + if (!Adjacent(user) || user.stat) return + + var/obj/item/pizzabox/boxtotagto = src + if( boxes.len > 0 ) + boxtotagto = boxes[boxes.len] + + boxtotagto.boxtag = copytext("[boxtotagto.boxtag][t]", 1, 30) + + update_icon() + return + ..() + +/obj/item/pizzabox/margherita/New() + . = ..() + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita(src) + boxtag = "Margherita Deluxe" + +/obj/item/pizzabox/vegetable/New() + . = ..() + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza(src) + boxtag = "Gourmet Vegatable" + +/obj/item/pizzabox/mushroom/New() + . = ..() + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza(src) + boxtag = "Mushroom Special" + +/obj/item/pizzabox/meat/New() + . = ..() + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza(src) + boxtag = "Meatlover's Supreme" + +////////////////////////////////FOOD ADDITIONS//////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/wrap + name = "egg wrap" + desc = "The precursor to Pigs in a Blanket." + icon_state = "wrap" + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/beans + name = "tin of beans" + desc = "Musical fruit in a slightly less musical container." + icon_state = "beans" + New() + ..() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/benedict + name = "eggs benedict" + desc = "There is only one egg on this, how rude." + icon_state = "benedict" + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/hotdog + name = "hotdog" + desc = "Fresh footlong ready to go down on." + icon_state = "hotdog" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("ketchup", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/meatbun + name = "meat bun" + desc = "Has the potential to not be Dog." + icon_state = "meatbun" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 6 + +/obj/item/weapon/reagent_containers/food/snacks/icecreamsandwich + name = "icecream sandwich" + desc = "Portable Ice-cream in it's own packaging." + icon_state = "icecreamsandwich" + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("ice", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/notasandwich + name = "not-a-sandwich" + desc = "Something seems to be wrong with this, you can't quite figure what. Maybe it's his moustache." + icon_state = "notasandwich" + New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sugarcookie + name = "sugar cookie" + desc = "Just like your little sister used to make." + icon_state = "sugarcookie" + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("sugar", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/boiledspiderleg + name = "boiled spider leg" + desc = "A giant spider's leg that's still twitching after being cooked. Gross!" + icon_state = "spiderlegcooked" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/spidereggs + name = "spider eggs" + desc = "A cluster of juicy spider eggs. A great side dish for when you care not for your health." + icon_state = "spidereggs" + food_flags = FOOD_ANIMAL //eggs are eggs + + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("toxin", 1) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/spidereggsham + name = "green eggs and ham" + desc = "Would you eat them on a train? Would you eat them on a plane? Would you eat them on a state of the art corporate deathtrap floating through space?" + icon_state = "spidereggsham" + trash = /obj/item/trash/plate + food_flags = FOOD_MEAT | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("sodiumchloride", 1) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/sashimi + name = "carp sashimi" + desc = "Celebrate surviving attack from hostile alien lifeforms by hospitalising yourself." + icon_state = "sashimi" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("carppheromones", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/assburger + name = "assburger" + desc = "You better be REALLY nice to this burger, or it'll report you to the police!" + icon_state = "assburger" + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("spiritbreaker", 10) // Screaming + reagents.add_reagent("mercury", 10) // Idiot + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/pie/asspie + name = "asspie" + desc = "Please remember to check your privlidge, pie eating scum." + icon_state = "asspie" + food_flags = FOOD_MEAT + + New() + ..() + reagents.clear_reagents() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("spiritbreaker", 10) // Screaming + reagents.add_reagent("mercury", 10) // Idiot + bitesize = 3 + +////////////////////////////////ICE CREAM/////////////////////////////////// +/obj/item/weapon/reagent_containers/food/snacks/icecream + name = "ice cream" + desc = "Delicious ice cream." + icon = 'icons/obj/kitchen.dmi' + icon_state = "icecream_cone" + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("sugar",1) + bitesize = 1 + update_icon() + + update_icon() + overlays.len = 0 + var/image/filling = image('icons/obj/kitchen.dmi', src, "icecream_color") + filling.icon += mix_color_from_reagents(reagents.reagent_list) + overlays += filling + +/obj/item/weapon/reagent_containers/food/snacks/icecream/icecreamcone + name = "ice cream cone" + desc = "Delicious ice cream." + icon_state = "icecream_cone" + volume = 500 + New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("sugar",6) + reagents.add_reagent("ice",2) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/icecream/icecreamcup + name = "chocolate ice cream cone" + desc = "Delicious ice cream." + icon_state = "icecream_cup" + volume = 500 + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("sugar",8) + reagents.add_reagent("ice",2) + bitesize = 6 + +/obj/item/weapon/reagent_containers/food/snacks/cereal + name = "box of cereal" + desc = "A box of cereal." + icon = 'icons/obj/food.dmi' + icon_state = "cereal_box" + bitesize = 2 + New() + ..() + reagents.add_reagent("nutriment", 3) + +/obj/item/weapon/reagent_containers/food/snacks/deepfryholder + name = "Deep Fried Foods Holder Obj" + icon = 'icons/obj/food.dmi' + icon_state = "deepfried_holder_icon" + bitesize = 2 + deepfried = 1 + New() + ..() + reagents.add_reagent("nutriment",deepFriedNutriment) + +/////////////////////////////////////////// +// new old food stuff from bs12 +/////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/dough + name = "dough" + desc = "A piece of dough." + icon = 'icons/obj/food_ingredients.dmi' + icon_state = "dough" + bitesize = 2 + food_flags = FOOD_ANIMAL //eggs + + New() + ..() + reagents.add_reagent("nutriment", 3) + +// Dough + rolling pin = flat dough +/obj/item/weapon/reagent_containers/food/snacks/dough/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/kitchen/rollingpin)) + if(isturf(loc)) + new /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough(loc) + to_chat(user, "You flatten [src].") + qdel(src) + else + to_chat(user, "You need to put [src] on a surface to roll it out!") + else + ..() + +// slicable into 3xdoughslices +/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough + name = "flat dough" + desc = "A flattened dough." + icon = 'icons/obj/food_ingredients.dmi' + icon_state = "flat dough" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/doughslice + slices_num = 3 + food_flags = FOOD_ANIMAL //eggs + + New() + ..() + reagents.add_reagent("nutriment", 3) + +/obj/item/weapon/reagent_containers/food/snacks/doughslice + name = "dough slice" + desc = "A building block of an impressive dish." + icon = 'icons/obj/food_ingredients.dmi' + icon_state = "doughslice" + bitesize = 2 + food_flags = FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 1) + +/obj/item/weapon/reagent_containers/food/snacks/bun + name = "burger bun" + desc = "A base for any self-respecting burger." + icon = 'icons/obj/food_ingredients.dmi' + icon_state = "bun" + bitesize = 2 + New() + ..() + reagents.add_reagent("nutriment", 4) + +//////////////////CHRISTMAS AND WINTER FOOD////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/buchedenoel + name = "\improper Buche de Noel" + desc = "Merry Christmas" + icon_state = "buche" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/bucheslice + slices_num = 5 + trash = /obj/item/trash/tray + food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/buchedenoel/New() + ..() + reagents.add_reagent("nutriment", 20) + reagents.add_reagent("sugar", 9) + reagents.add_reagent("coco", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/bucheslice + name = "\improper Buche de Noel slice" + desc = "A slice of winter magic" + icon_state = "buche_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey + name = "turkey" + desc = "Tastes like chicken" + icon_state = "turkey" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/turkeyslice + slices_num = 2 + trash = /obj/item/trash/tray + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey/New() + ..() + reagents.add_reagent("nutriment", 20) + reagents.add_reagent("blackpepper", 1) + reagents.add_reagent("sodiumchloride", 1) + reagents.add_reagent("cornoil", 1) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/turkeyslice + name = "turkey drumstick" + desc = "Guaranteed vox-free" + icon_state = "turkey_drumstick" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_MEAT + +//////////////////CHICKEN////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets + name = "Chicken Nuggets" + desc = "You'd rather not know how they were prepared." + icon_state = "kfc_nuggets" + item_state = "kfc_bucket" + trash = /obj/item/trash/chicken_bucket + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets/New() + ..() + reagents.add_reagent("nutriment", 6) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick + name = "chicken drumstick" + desc = "We can fry further..." + icon_state = "chicken_drumstick" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/chicken_drumstick/New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chicken_fillet + name = "Chicken Fillet" + desc = "This is a fancy word for chicken fingers so that high class people can forget they're eating fried food." + icon_state = "tendies" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/chicken_nuggets/New() + ..() + reagents.add_reagent("cornoil", 3) + bitesize = 2 + + +//////////////////CURRY////////////////// + +/obj/item/weapon/reagent_containers/food/snacks/curry + name = "Chicken Balti" + desc = "Finest Indian Cuisine, at least you think it is chicken." + icon_state = "curry_balti" + item_state = "curry_balti" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/curry/New() + ..() + reagents.add_reagent("nutriment", 20) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/curry/vindaloo + name = "Chicken Vindaloo" + desc = "Me and me Mum and me Dad and me Nan are off to Waterloo, me and me Mum and me Dad and me Nan and a bucket of Vindaloo!" + icon_state = "curry_vindaloo" + item_state = "curry_vindaloo" + +/obj/item/weapon/reagent_containers/food/snacks/curry/vindaloo/New() + ..() + reagents.add_reagent("nutriment", 20) + reagents.add_reagent("capsaicin", 10) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/curry/lemon + name = "Lemon Curry" + desc = "This actually exists?" + icon_state = "curry_lemon" + item_state = "curry_lemon" + +/obj/item/weapon/reagent_containers/food/snacks/curry/lemon/New() + ..() + reagents.add_reagent("nutriment", 20) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/curry/xeno + name = "Xeno Balti" + desc = "Waste not want not." + icon_state = "curry_xeno" + item_state = "curry_xeno" + +/obj/item/weapon/reagent_containers/food/snacks/curry/xeno/New() + ..() + reagents.add_reagent("nutriment", 20) + bitesize = 3 + + +//////////////////CHIPS////////////////// + + +/obj/item/weapon/reagent_containers/food/snacks/chips + name = "chips" + desc = "Commander Riker's What-The-Crisps" + icon_state = "chips" + trash = /obj/item/trash/chips + New() + ..() + reagents.add_reagent("nutriment", 3) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable + name = "Plain Chips" + desc = "Where did the bag come from?" + icon_state = "plain_chips" + item_state = "plain_chips" + trash = null + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/vinegar + name = "Salt and Vinegar Chips" + desc = "The objectively best flavour." + icon_state = "salt_vinegar_chips" + item_state = "salt_vinegar_chips" + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/vinegar/New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/cheddar + name = "Cheddar Chips" + desc = "Dangerously cheesy." + icon_state = "cheddar_chips" + item_state = "cheddar_chips" + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/cheddar/New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/clown + name = "Banana Chips" + desc = "A clown's favourite snack!" + icon_state = "clown_chips" + item_state = "clown_chips" + +/obj/item/weapon/reagent_containers/food/snacks/chip/cookable/clown/New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("honkserum", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/nuclear + name = "Nuclear Chips" + desc = "Radioactive taste!" + icon_state = "nuclear_chips" + item_state = "nuclear_chips" + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/nuclear/New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("nuka_cola", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/communist + name = "Communist Chips" + desc = "A perfect snack to share with the party!" + icon_state = "commie_chips" + item_state = "commie_chips" + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/communist/New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("vodka", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/xeno + name = "Xeno Raiders" + desc = "A great taste that is out of this world!" + icon_state = "xeno_chips" + item_state = "xeno_chips" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/chips/cookable/xeno/New() + ..() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/gigapuddi + name = "Giga Puddi" + desc = "A large crème caramel" + icon_state = "gigapuddi" + trash = /obj/item/trash/plate + food_flags = FOOD_ANIMAL //milk + + New() + ..() + reagents.add_reagent("nutriment", 20) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/gigapuddi/happy + desc = "A large crème caramel made with extra love" + icon_state = "happypuddi" + food_flags = FOOD_SWEET + +/obj/item/weapon/reagent_containers/food/snacks/gigapuddi/anger + desc = "A large crème caramel made with extra hate" + icon_state = "angerpuddi" + +/obj/item/weapon/reagent_containers/food/snacks/flan + name = "Flan" + desc = "A small crème caramel" + icon_state = "flan" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/honeyflan + name = "Honey Flan" + desc = "The systematic slavery of an entire society of insects, elegantly sized to fit in your mouth." + icon_state = "honeyflan" + trash = /obj/item/trash/plate + New() + ..() + reagents.add_reagent("nutriment", 8) + reagents.add_reagent("cinnamon", 5) + reagents.add_reagent("honey", 6) + bitesize = 3 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/omurice + name = "omelette rice" + desc = "Just like your Japanese animes!" + icon_state = "omurice" + trash = /obj/item/trash/plate + food_flags = FOOD_ANIMAL //egg + + New() + ..() + reagents.add_reagent("nutriment", 8) + bitesize = 1 + +/obj/item/weapon/reagent_containers/food/snacks/omurice/heart + icon_state = "omuriceheart" + +/obj/item/weapon/reagent_containers/food/snacks/omurice/face + icon_state = "omuriceface" + +/obj/item/weapon/reagent_containers/food/snacks/muffin/bluespace + name = "Bluespace-berry Muffin" + desc = "Just like a normal blueberry muffin, except with completely unnecessary floaty things!" + icon_state = "bluespace" + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/yellowcake + name = "Yellowcake" + desc = "For Fat Men." + icon_state = "yellowcake" + food_flags = FOOD_SWEET | FOOD_ANIMAL //egg + + New() + ..() + reagents.add_reagent("nutriment", 40) + reagents.add_reagent("radium", 10) + reagents.add_reagent("uranium", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/yellowcupcake + name = "Yellowcupcake" + desc = "For Little Boys." + icon_state = "yellowcupcake" + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 15) + reagents.add_reagent("radium", 5) + reagents.add_reagent("uranium", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cookiebowl + name = "Bowl of cookies" + desc = "A bowl full of small cookies." + icon_state = "cookiebowl" + trash = /obj/item/trash/snack_bowl + New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("sugar", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/chococherrycake + name = "chocolate-cherry cake" + desc = "A chocolate cake with icing and cherries." + icon_state = "chococherrycake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/chococherrycakeslice + slices_num = 5 + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 20) + +/obj/item/weapon/reagent_containers/food/snacks/chococherrycakeslice + name = "chocolate-cherry cake slice" + desc = "Just a slice of cake, it is enough for everyone." + icon_state = "chococherrycake_slice" + trash = /obj/item/trash/plate + bitesize = 2 + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinbread + name = "Pumpkin Bread" + desc = "A loaf of pumpkin bread." + icon_state = "pumpkinbread" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/pumpkinbreadslice + slices_num = 5 + New() + ..() + reagents.add_reagent("nutriment", 15) + +/obj/item/weapon/reagent_containers/food/snacks/pumpkinbreadslice + name = "Pumpkin Bread slice" + desc = "A slice of pumpkin bread." + icon_state = "pumpkinbreadslice" + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/corndog + name = "Corndog" + desc = "Battered hotdog on a stick!" + icon_state = "corndog" + food_flags = FOOD_MEAT | FOOD_ANIMAL //eggs + + New() + ..() + reagents.add_reagent("nutriment", 5) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/cornydog + name = "CORNY DOG" + desc = "This is just ridiculous." + icon_state = "cornydog" + trash = /obj/item/stack/rods //no fun allowed + food_flags = FOOD_MEAT + + New() + ..() + reagents.add_reagent("nutriment", 15) + bitesize = 5 + +////////////////SLIDERS//////////////// + +/obj/item/weapon/reagent_containers/food/snacks/slider + name = "slider" + desc = "It's so tiny!" + icon_state = "slider" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/slider/New() + ..() + reagents.add_reagent("nutriment", 2.5) + bitesize = 1.5 + +/obj/item/weapon/reagent_containers/food/snacks/slider/synth + name = "synth slider" + desc = "It's made to be tiny!" + +/obj/item/weapon/reagent_containers/food/snacks/slider/xeno + name = "xeno slider" + desc = "It's green!" + icon_state = "slider_xeno" + +/obj/item/weapon/reagent_containers/food/snacks/slider/xeno/New() + ..() + reagents.add_reagent("nutriment", 1) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/slider/chicken + name = "chicken slider" + desc = "Chicken sliders? That's new." + icon_state = "slider_chicken" + +/obj/item/weapon/reagent_containers/food/snacks/slider/chicken/New() + ..() + reagents.add_reagent("nutriment", 1) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/slider/carp + name = "carp slider" + desc = "I wonder how it tastes!" + icon_state = "slider_carp" + +/obj/item/weapon/reagent_containers/food/snacks/slider/carp/New() + ..() + reagents.add_reagent("nutriment", 1) + bitesize = 2.5 + +/obj/item/weapon/reagent_containers/food/snacks/slider/toxiccarp + name = "carp slider" + desc = "I wonder how it tastes!" + icon_state = "slider_carp" + +/obj/item/weapon/reagent_containers/food/snacks/slider/toxiccarp/New() + ..() + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("carpotoxin", 2) + bitesize = 2.5 + +/obj/item/weapon/reagent_containers/food/snacks/slider/carp/spider + name = "spidey slidey" + desc = "I think there's still a leg in there!" + icon_state = "slider_spider" + +/obj/item/weapon/reagent_containers/food/snacks/slider/clown + name = "honky slider" + desc = "HONK!" + icon_state = "slider_clown" + +/obj/item/weapon/reagent_containers/food/snacks/slider/clown/New() + ..() + reagents.add_reagent("honkserum", 2.5) + bitesize = 2.5 + +/obj/item/weapon/reagent_containers/food/snacks/slider/mime + name = "quiet Slider" + desc = "..." + icon_state = "slider_mime" + +/obj/item/weapon/reagent_containers/food/snacks/slider/slippery + name = "slippery slider" + desc = "It's so slippery!" + icon_state = "slider_slippery" + +/obj/item/weapon/reagent_containers/food/snacks/slider/slippery/Crossed(atom/movable/O) //exactly the same as soap + if (istype(O, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = O + if (H.CheckSlip() < 1) + return + + H.stop_pulling() + to_chat(H, "You slipped on the [name]!") + playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) + H.Stun(3) + H.Weaken(2) + +////////////////SLIDERS END//////////////// + +/obj/item/weapon/reagent_containers/food/snacks/higashikata + name = "Higashikata Special" + desc = "9 layer parfait, very expensive." + icon_state = "higashikata" + food_flags = FOOD_SWEET | FOOD_ANIMAL + + New() + ..() + reagents.add_reagent("nutriment", 10) + reagents.add_reagent("sugar", 10) + reagents.add_reagent("ice", 10) + reagents.add_reagent("melonjuice", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/sundae + name = "Sundae" + desc = "A colorful ice cream treat." + icon_state = "sundae" + food_flags = FOOD_SWEET | FOOD_ANIMAL //milk + + New() + ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("sugar", 5) + reagents.add_reagent("ice", 5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/potatosalad + name = "Potato Salad" + desc = "With 21st century technology, it could take as long as three days to make this." + icon_state = "potato_salad" + New() + ..() + reagents.add_reagent("nutriment", 10) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/coleslaw + name = "Coleslaw" + desc = "You fought the 'slaw, and the 'slaw won." + icon_state = "coleslaw" + New() + ..() + reagents.add_reagent("nutriment", 4) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/risotto + name = "Risotto" + desc = "For the gentleman's wino, this is an offer one cannot refuse." + icon_state = "risotto" + New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("wine", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/cinnamonroll + name = "cinnamon roll" + desc = "Sweet and spicy!" + icon_state = "cinnamon_roll" + trash = /obj/item/trash/plate + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("cinnamon",5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/cinnamonpie + name = "cinnamon pie" + desc = "Guarranted snail-free!" + icon_state = "cinnamon_pie" + trash = /obj/item/trash/pietin + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("cinnamon",5) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/sundaeramen + name = "Sundae Ramen" + desc = "This is... sundae (?) flavored (?) ramen (?). You just don't know." + icon_state = "sundaeramen" + food_flags = FOOD_SWEET + + New() + ..() + reagents.add_reagent("nutriment", 10) + reagents.add_reagent("discount", 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sweetsundaeramen + name = "Sweet Sundae Ramen" + desc = "It's a delicious ramen recipe that can soothe the soul of a savage spaceman." + icon_state = "sweetsundaeramen" + food_flags = FOOD_SWEET | FOOD_ANIMAL //uses puddi in recipe + + New() + ..() + bitesize = 4 + while(reagents.total_volume<70) + generatecontents() + +/obj/item/weapon/reagent_containers/food/snacks/sweetsundaeramen/proc/generatecontents() + switch(pick(1,2,3,4,5,6,7,8,9,10)) + if(1) + desc += " It has peppermint flavoring! But just a few drops." + reagents.add_reagent("zombiepowder", 10) + if(2) + desc += " This may not be everyone's cup of tea, but it's great, I promise." + reagents.add_reagent("oxycodone", 10) + if(3) + desc += " This has the cook's favorite ingredient -- and a lot of it!" + reagents.add_reagent("mindbreaker", 10) + if(4) + desc += " It has TONS of flavor!" + reagents.add_reagent("minttoxin", 10) + if(5) + desc += " The recipe for this thing got lost somewhere..." + reagents.add_reagent("nutriment", 10) + if(6) + desc += " It has extra sweetness and a little bit of crumble!" + reagents.add_reagent("tricordrazine", 10) + if(7) + desc += " It may be thick, but the noodles slip around easily." + reagents.add_reagent("nutriment", 10) + if(8) + desc += " It has a nice crunch!" + reagents.add_reagent("nutriment", 10) + if(9) + desc += " Yummy, but with all the sweets, your chest starts to hurt." + reagents.add_reagent("nutriment", 10) + if(10) + desc += " Just a dollop of garnishes." + reagents.add_reagent("nutriment", 10) + +/obj/item/weapon/reagent_containers/food/snacks/chocofrog + name = "chocolate frog" + desc = "An exotic snack originating from the Space Wizard Federation. Very slippery!" + icon = 'icons/obj/wiz_cards.dmi' + icon_state = "frog" + + flags = PROXMOVE + food_flags = FOOD_SWEET + + var/jump_cd + +/obj/item/weapon/reagent_containers/food/snacks/chocofrog/New() + ..() + reagents.add_reagent("nutriment",2) + reagents.add_reagent("hyperzine",1) + +/obj/item/weapon/reagent_containers/food/snacks/chocofrog/HasProximity(atom/movable/AM as mob|obj) + if(!jump_cd) + jump() + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/chocofrog/proc/jump() + if(!istype(src.loc,/turf)) return + jump_cd=1 + spawn(50) + jump_cd=0 + + var/list/escape_paths=list() + + for(var/turf/T in view(7,src)) + escape_paths |= T + + var/turf/T = pick(escape_paths) + src.throw_at(T, 10, 2) + return 1 + +/obj/item/weapon/reagent_containers/food/snacks/chocofrog/pickup(mob/living/user as mob) + var/mob/living/carbon/human/H = user + if(!H) return 1 + + spawn(0) + if(((M_CLUMSY in H.mutations)) || prob(25)) + if(H.drop_item()) + user.visible_message("[src] escapes from [H]'s hands!","[src] escapes from your grasp!") + + jump() + return 1 + +/obj/item/weapon/reagent_containers/food/snacks/potentham + name = "potent ham" + desc = "I'm sorry Dave, but I am afraid I can't let you eat that." + icon_state = "potentham" + volume = 1 + New() + ..() + reagents.add_reagent("hamserum", 1) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/sweet + name = "\improper Sweet" + desc = "Comes in many different and unique flavours!" + food_flags = FOOD_SWEET + icon = 'icons/obj/candymachine.dmi' + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/sweet/New() + ..() + reagents.add_reagent("nutriment", 3) + reagents.add_reagent("sugar", 2) + icon_state = "sweet[rand(1,12)]" + +/obj/item/weapon/reagent_containers/food/snacks/sweet/strange + desc = "Something about this sweet doesn't seem right." + +/obj/item/weapon/reagent_containers/food/snacks/sweet/strange/New() + ..() + var/list/possible_reagents=list("zombiepowder"=5, "mindbreaker"=5, "pacid"=5, "hyperzine"=5, "chloralhydrate"=5, "tricordazine"=5, "doctorsdelight"=5, "mutationtoxin"=5, "mercury"=5, "anti_toxin"=5, "space_drugs"=5, "holywater"=5, "ryetalyn"=5, "cryptobiolin"=5, "dexalinp"=5, "hamserum"=1) + var/reagent=pick(possible_reagents) + reagents.add_reagent(reagent, possible_reagents[reagent]) + +/obj/item/weapon/reagent_containers/food/snacks/chococoin + name = "\improper Choco-Coin" + desc = "A thin wafer of milky, chocolatey, melt-in-your-mouth goodness. That alone is already worth a hoard." + food_flags = FOOD_SWEET + icon_state = "chococoin_unwrapped" + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/chococoin/wrapped + desc = "Still covered in golden foil wrapper." + icon_state = "chococoin_wrapped" + wrapped = 1 + +/obj/item/weapon/reagent_containers/food/snacks/chococoin/New() + ..() + reagents.add_reagent("nutriment", 2) + reagents.add_reagent("sugar", 2) + reagents.add_reagent("coco", 3) + +/obj/item/weapon/reagent_containers/food/snacks/chococoin/attack_self(mob/user) + if(wrapped) + Unwrap(user) + else + ..() + +/obj/item/weapon/reagent_containers/food/snacks/chococoin/proc/Unwrap(mob/user) + icon_state = "chococoin_unwrapped" + desc = "A thin wafer of milky, chocolatey, melt-in-your-mouth goodness. That alone is already worth a hoard." + to_chat(user, "You remove the golden foil from \the [src].") + wrapped = 0 + +/obj/item/weapon/reagent_containers/food/snacks/eucharist + name = "\improper Eucharist Wafer" + icon_state = "eucharist" + desc = "For the kingdom, the power, and the glory are yours, now and forever." + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/eucharist/New() + ..() reagents.add_reagent("holywater", 5) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/food/snacks/grown.dm b/code/modules/reagents/reagent_containers/food/snacks/grown.dm index 2ac7746ffe7..c9c402e7838 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/grown.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/grown.dm @@ -1,776 +1,776 @@ - - -// *********************************************************** -// Foods that are produced from hydroponics ~~~~~~~~~~ -// Data from the seeds carry over to these grown foods -// *********************************************************** - -//Grown foods -//Subclass so we can pass on values -/obj/item/weapon/reagent_containers/food/snacks/grown/ - var/plantname - var/potency = -1 - var/datum/seed/seed - icon = 'icons/obj/harvest.dmi' - New(newloc, newpotency) - if(!isnull(newpotency)) - potency = newpotency - ..() - src.pixel_x = rand(-5.0, 5) - src.pixel_y = rand(-5.0, 5) - -/obj/item/weapon/reagent_containers/food/snacks/grown/New() - ..() - - //Handle some post-spawn var stuff. - spawn(1) - //Fill the object up with the appropriate reagents. - if(!isnull(plantname)) - seed = plant_controller.seeds[plantname] - if(!seed || !seed.chems) - return - - potency = round(seed.potency) - force = seed.thorny ? 5+seed.carnivorous*3 : 0 - - var/totalreagents = 0 - for(var/rid in seed.chems) - var/list/reagent_data = seed.chems[rid] - var/rtotal = reagent_data[1] - if(reagent_data.len > 1 && potency > 0) - rtotal += round(potency/reagent_data[2]) - totalreagents += rtotal - - if(totalreagents) - var/coeff = min(reagents.maximum_volume / totalreagents, 1) - - for(var/rid in seed.chems) - var/list/reagent_data = seed.chems[rid] - var/rtotal = reagent_data[1] - if(reagent_data.len > 1 && potency > 0) - rtotal += round(potency/reagent_data[2]) - reagents.add_reagent(rid, max(1, round(rtotal*coeff, 0.1))) - - if(seed.teleporting) - name = "blue-space [name]" - if(seed.stinging) - name = "stinging [name]" - if(seed.juicy == 2) - name = "slippery [name]" - - if(reagents.total_volume > 0) - bitesize = 1 + round(reagents.total_volume/2, 1) - -/obj/item/weapon/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom) - ..() - if(!seed || !src) return - //if(seed.stinging) //we do NOT want to transfer reagents on throw, as it would mean plantbags full of throwable chloral injectors - // stinging_apply_reagents(M) //plus all sorts of nasty stuff like throw_impact not targeting a specific bodypart to check for protection. - - // We ONLY want to apply special effects if we're hitting a turf! That's because throw_impact will always be - // called on a turf AFTER it's called on the things ON the turf, and will runtime if the item doesn't exist anymore. - if(isturf(hit_atom)) - do_splat_effects(hit_atom) - return - -/obj/item/weapon/reagent_containers/food/snacks/grown/proc/do_splat_effects(atom/hit_atom) - if(seed.teleporting) - splat_reagent_reaction(get_turf(hit_atom)) - if(do_fruit_teleport(hit_atom, usr, potency)) - visible_message("The [src] splatters, causing a distortion in space-time!") - else if(splat_decal(get_turf(hit_atom))) - visible_message("The [src.name] has been squashed.","You hear a smack.") - qdel(src) - return - - if(seed.juicy) - splat_decal(get_turf(hit_atom)) - splat_reagent_reaction(get_turf(hit_atom)) - visible_message("The [src.name] has been squashed.","You hear a smack.") - qdel(src) - return - -/obj/item/weapon/reagent_containers/food/snacks/grown/attack(mob/living/M, mob/user, def_zone) - if(user.a_intent == I_HURT) - . = handle_attack(src,M,user,def_zone) - if(seed.stinging) - if(M.getarmor(def_zone, "melee") < 5) - var/reagentlist = stinging_apply_reagents(M) - if(reagentlist) - to_chat(M, "You are stung by \the [src]!") - add_attacklogs(user, M, "stung", object = src, addition = "Reagents: [english_list(seed.get_reagent_names())]", admin_warn = 1) - to_chat(user, "Some of \the [src]'s stingers break off in the hit!") - potency -= rand(1,(potency/3)+1) - do_splat_effects(M) - return - return ..() - -/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/carbon/M) - ..() - if(!seed) return - if(!istype(M)) return - if(!M.on_foot()) - return - if(seed.thorny || seed.stinging) - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(!H.check_body_part_coverage(FEET)) - var/datum/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot")) - if(affecting && affecting.is_organic()) - if(thorns_apply_damage(M, affecting)) - to_chat(H, "You step on \the [src]'s sharp thorns!") - if(H.species && !(H.species.flags & NO_PAIN)) - H.Weaken(3) - if(stinging_apply_reagents(M)) - to_chat(H, "Your step on \the [src]'s stingers!") - potency -= rand(1,(potency/3)+1) - if(seed.juicy == 2) - if(M.Slip(3, 2)) - to_chat(M, "You slipped on the [name]!") - do_splat_effects(M) - -/obj/item/weapon/reagent_containers/food/snacks/grown/pickup(mob/user) - ..() - if(!seed) return - if(seed.thorny || seed.stinging) - var/mob/living/carbon/human/H = user - if(!istype(H)) - return - if(H.check_body_part_coverage(HANDS)) - return - var/datum/organ/external/affecting = H.get_organ(pick("r_hand","l_hand")) - if(!affecting || !affecting.is_organic()) - return - if(stinging_apply_reagents(H)) - to_chat(H, "You are stung by \the [src]!") - potency -= rand(1,(potency/3)+1) - if(thorns_apply_damage(H, affecting)) - to_chat(H, "You are prickled by the sharp thorns on \the [src]!") - spawn(3) - if(H.species && !(H.species.flags & NO_PAIN)) - H.drop_item(src) - -/obj/item/weapon/reagent_containers/food/snacks/grown/On_Consume(var/mob/living/carbon/human/H) - if(seed.thorny && istype(H)) - var/datum/organ/external/affecting = H.get_organ("head") - if(affecting) - if(thorns_apply_damage(H, affecting)) - to_chat(H, "Your mouth is cut by \the [src]'s sharp thorns!") - //H.stunned++ //just a 1 second pause to prevent people from spamming pagedown on this, since it's important - ..() - -/obj/item/weapon/reagent_containers/food/snacks/grown/examine(mob/user) - ..() - if(!seed) return - var/traits = "" - if(seed.stinging) traits += "It's covered in tiny stingers. " - if(seed.thorny) traits += "It's covered in sharp thorns. " - if(seed.juicy == 2) traits += "It looks ripe and excessively juicy. " - if(seed.teleporting) traits += "It seems to be spatially unstable. " - if(traits) to_chat(user, traits) - -/obj/item/weapon/reagent_containers/food/snacks/grown/proc/splat_decal(turf/T) - var/obj/effect/decal/cleanable/S = getFromPool(seed.splat_type,T) - S.New(S.loc) - if(seed.splat_type == /obj/effect/decal/cleanable/fruit_smudge/) - if(filling_color != "#FFFFFF") - S.color = filling_color - else - S.color = AverageColor(getFlatIcon(src, src.dir, 0), 1, 1) - S.name = "[seed.seed_name] smudge" - if(seed.biolum && seed.biolum_colour) - S.set_light(1, l_color = seed.biolum_colour) - return 1 - -/obj/item/weapon/reagent_containers/food/snacks/grown/proc/splat_reagent_reaction(turf/T) - if(src.reagents.total_volume > 0) - src.reagents.reaction(T) - for(var/atom/A in T) - src.reagents.reaction(A) - return 1 - return 0 - -/obj/item/weapon/reagent_containers/food/snacks/grown/proc/thorns_apply_damage(mob/living/carbon/human/H, datum/organ/external/affecting) - if(!seed.thorny || !affecting) - return 0 - //if(affecting.take_damage(5+seed.carnivorous*3, 0, 0, "plant thorns")) //For some fucked up reason, it's not returning 1 - affecting.take_damage(5+seed.carnivorous*3, 0, 0, "plant thorns") - H.UpdateDamageIcon() - return 1 - -/obj/item/weapon/reagent_containers/food/snacks/grown/proc/stinging_apply_reagents(mob/living/carbon/human/H) - if(!seed.stinging) - return 0 - if(!reagents || reagents.total_volume <= 0) - return 0 - if(!seed.chems || !seed.chems.len) - return 0 - var/injecting = Clamp(1, 3, potency/10) - for(var/rid in seed.chems) //Only transfer reagents that the plant naturally produces, no injecting chloral into your nettles. - reagents.trans_id_to(H,rid,injecting) - . = 1 - -/obj/item/weapon/reagent_containers/food/snacks/grown/proc/do_fruit_teleport(atom/hit_atom, mob/M, var/potency) //Does this need logging? - var/datum/zLevel/L = get_z_level(src) - if(!L || L.teleJammed) - return 0 - - var/outer_teleport_radius = potency/10 //Plant potency determines radius of teleport. - var/inner_teleport_radius = potency/15 //At base potency, nothing will happen, since the radius is 0. - if(inner_teleport_radius < 1) - return 0 - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - - var/list/turfs = new/list() - //This could likely use some standardization but I have no idea how to not break it. - for(var/turf/T in trange(outer_teleport_radius, get_turf(hit_atom))) - if(get_dist(T, hit_atom) <= inner_teleport_radius) - continue - if(is_blocked_turf(T) || istype(T, /turf/space)) - continue - if(T.x > world.maxx-outer_teleport_radius || T.x < outer_teleport_radius) - continue - if(T.y > world.maxy-outer_teleport_radius || T.y < outer_teleport_radius) - continue - turfs += T - if(!turfs.len) - var/list/turfs_to_pick_from = list() - for(var/turf/T in trange(outer_teleport_radius, get_turf(hit_atom))) - if(get_dist(T, hit_atom) > inner_teleport_radius) - turfs_to_pick_from += T - turfs += pick(/turf in turfs_to_pick_from) - var/turf/picked = pick(turfs) - if(!isturf(picked)) - return 0 - switch(rand(1, 2)) //50-50 % chance to teleport the thrower or the target. - if(1) //Teleports the person who threw the fruit - s.set_up(3, 1, M) - s.start() - new/obj/effect/decal/cleanable/molten_item(M.loc) //Leaves a pile of goo behind for dramatic effect. - M.forceMove(picked) //Send then to that location we picked previously - spawn() - s.set_up(3, 1, M) - s.start() //Two set of sparks, one before the teleport and one after. //Sure then ? - if(2) //Teleports the target instead. - s.set_up(3, 1, hit_atom) - s.start() - new/obj/effect/decal/cleanable/molten_item(get_turf(hit_atom)) //Leave a pile of goo behind for dramatic effect... - for(var/mob/A in get_turf(hit_atom)) //For the mobs in the tile that was hit... - A.forceMove(picked) //And teleport them to the chosen location. - spawn() - s.set_up(3, 1, A) - s.start() - return 1 - - -/obj/item/weapon/reagent_containers/food/snacks/grown/corn - name = "ear of corn" - desc = "Needs some butter!" - plantname = "corn" - icon_state = "corn" - potency = 40 - filling_color = "#FFEE00" - trash = /obj/item/weapon/corncob - -/obj/item/weapon/reagent_containers/food/snacks/grown/cherries - name = "cherries" - desc = "Great for toppings!" - icon_state = "cherry" - filling_color = "#FF0000" - gender = PLURAL - plantname = "cherry" - slot_flags = SLOT_EARS - -/obj/item/weapon/reagent_containers/food/snacks/grown/cinnamon - name = "cinnamon sticks" - desc = "Straight from the bark!" - icon_state = "cinnamon" - filling_color = "#D2691E" - gender = PLURAL - plantname = "cinnamomum" - -/obj/item/weapon/reagent_containers/food/snacks/grown/poppy - name = "poppy" - desc = "Long-used as a symbol of rest, peace, and death." - icon_state = "poppy" - potency = 30 - filling_color = "#CC6464" - plantname = "poppies" - -/obj/item/weapon/reagent_containers/food/snacks/grown/harebell - name = "harebell" - desc = "\"I'll sweeten thy sad grave: thou shalt not lack the flower that's like thy face, pale primrose, nor the azured hare-bell, like thy veins; no, nor the leaf of eglantine, whom not to slander, out-sweeten’d not thy breath.\"" - icon_state = "harebell" - potency = 1 - filling_color = "#D4B2C9" - plantname = "harebells" - -/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower - name = "moonflower" - desc = "Store in a location at least 50 yards away from werewolves." - icon_state = "moonflower" - potency = 25 - filling_color = "#E6E6FA" - plantname = "moonflowers" - -/obj/item/weapon/reagent_containers/food/snacks/grown/potato - name = "potato" - desc = "Boil 'em! Mash 'em! Stick 'em in a stew!" - icon_state = "potato" - potency = 25 - filling_color = "#E6E8DA" - plantname = "potato" - -/obj/item/weapon/reagent_containers/food/snacks/grown/potato/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(istype(W, /obj/item/stack/cable_coil)) - if(W:amount >= 5) - W:amount -= 5 - if(!W:amount) - qdel(W) - to_chat(user, "You add some cable to \the [src] and slide it inside the battery encasing.") - var/obj/item/weapon/cell/potato/pocell = new /obj/item/weapon/cell/potato(user.loc) - pocell.maxcharge = src.potency * 10 - pocell.charge = pocell.maxcharge - qdel(src) - return - -/obj/item/weapon/reagent_containers/food/snacks/grown/grapes - name = "bunch of grapes" - desc = "Nutritious!" - icon_state = "grapes" - filling_color = "#A332AD" - plantname = "grapes" - -/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes - name = "bunch of green grapes" - desc = "Nutritious!" - icon_state = "greengrapes" - potency = 25 - filling_color = "#A6FFA3" - plantname = "greengrapes" - -/obj/item/weapon/reagent_containers/food/snacks/grown/peanut - name = "peanut" - desc = "Nuts!" - icon_state = "peanut" - filling_color = "857e27" - potency = 25 - plantname = "peanut" - -/obj/item/weapon/reagent_containers/food/snacks/grown/cabbage - name = "cabbage" - desc = "Ewwwwwwwwww. Cabbage." - icon_state = "cabbage" - potency = 25 - filling_color = "#A2B5A1" - plantname = "cabbage" - -/obj/item/weapon/reagent_containers/food/snacks/grown/berries - name = "bunch of berries" - desc = "Nutritious!" - icon_state = "berrypile" - filling_color = "#C2C9FF" - plantname = "berries" - -/obj/item/weapon/reagent_containers/food/snacks/grown/plastellium - name = "clump of plastellium" - desc = "Hmm, needs some processing" - icon_state = "plastellium" - filling_color = "#C4C4C4" - plantname = "plastic" - -/obj/item/weapon/reagent_containers/food/snacks/grown/glowberries - name = "bunch of glow-berries" - desc = "Nutritious!" - var/light_on = 1 - var/brightness_on = 2 //luminosity when on - filling_color = "#D3FF9E" - icon_state = "glowberrypile" - plantname = "glowberries" - -/obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod - name = "cocoa pod" - desc = "Can be ground into cocoa powder." - icon_state = "cocoapod" - potency = 50 - filling_color = "#9C8E54" - plantname = "cocoa" - -/obj/item/weapon/reagent_containers/food/snacks/grown/sugarcane - name = "sugarcane" - desc = "Sickly sweet." - icon_state = "sugarcane" - potency = 50 - filling_color = "#C0C9AD" - plantname = "sugarcane" - -/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries - name = "bunch of poison-berries" - desc = "Taste so good, you could die!" - icon_state = "poisonberrypile" - gender = PLURAL - potency = 15 - filling_color = "#B422C7" - plantname = "poisonberries" - -/obj/item/weapon/reagent_containers/food/snacks/grown/deathberries - name = "bunch of death-berries" - desc = "Taste so good, you could die!" - icon_state = "deathberrypile" - gender = PLURAL - potency = 50 - filling_color = "#4E0957" - plantname = "deathberries" - -/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris - name = "ambrosia vulgaris branch" - desc = "This is a plant containing various healing chemicals." - icon_state = "ambrosiavulgaris" - potency = 10 - filling_color = "#125709" - plantname = "ambrosia" - -/obj/item/weapon/reagent_containers/food/snacks/grown/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/paper)) - qdel(O) - to_chat(user, "You roll a blunt out of \the [src].") - var/obj/item/clothing/mask/cigarette/blunt/rolled/B = new/obj/item/clothing/mask/cigarette/blunt/rolled(src.loc) - B.name = "[src] blunt" - reagents.trans_to(B, (reagents.total_volume)) - user.put_in_hands(B) - user.drop_from_inventory(src) - qdel(src) - else - return ..() - -/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/deus - name = "ambrosia deus branch" - desc = "Eating this makes you feel immortal!" - icon_state = "ambrosiadeus" - potency = 10 - filling_color = "#229E11" - plantname = "ambrosiadeus" - -/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/deus/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) - if(istype(O, /obj/item/weapon/paper)) - qdel(O) - to_chat(user, "You roll a godly blunt.") - var/obj/item/clothing/mask/cigarette/blunt/deus/rolled/B = new/obj/item/clothing/mask/cigarette/blunt/deus/rolled(src.loc) - reagents.trans_to(B, (reagents.total_volume)) - B.light_color = filling_color - user.put_in_hands(B) - user.drop_from_inventory(src) - qdel(src) - else - return ..() - -/obj/item/weapon/reagent_containers/food/snacks/grown/apple - name = "apple" - desc = "It's a little piece of Eden." - icon_state = "apple" - potency = 15 - filling_color = "#DFE88B" - plantname = "apple" - -/obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned - filling_color = "#B3BD5E" - plantname = "poisonapple" - -/obj/item/weapon/reagent_containers/food/snacks/grown/goldapple - name = "golden apple" - desc = "Emblazoned upon the apple is the word 'Kallisti'." - icon_state = "goldapple" - potency = 15 - filling_color = "#F5CB42" - plantname = "goldapple" - -/obj/item/weapon/reagent_containers/food/snacks/grown/watermelon - name = "watermelon" - desc = "It's full of watery goodness." - icon_state = "watermelon" - potency = 10 - filling_color = "#FA2863" - slice_path = /obj/item/weapon/reagent_containers/food/snacks/watermelonslice - slices_num = 5 - plantname = "watermelon" - -/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin - name = "pumpkin" - desc = "It's large and scary." - icon_state = "pumpkin" - potency = 10 - filling_color = "#FAB728" - plantname = "pumpkin" - -/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin/attackby(obj/item/weapon/W as obj, mob/user as mob) - ..() - if(W.is_sharp() >= 1) - user.visible_message("[user] carves a face into \the [src] with \the [W]!", "You carve a face into \the [src] with \the [W]!") - new /obj/item/clothing/head/pumpkinhead(get_turf(src)) //Don't move it - qdel(src) - return - -/obj/item/weapon/reagent_containers/food/snacks/grown/lime - name = "lime" - desc = "It's so sour, your face will twist." - icon_state = "lime" - potency = 20 - filling_color = "#28FA59" - plantname = "lime" - -/obj/item/weapon/reagent_containers/food/snacks/grown/lemon - name = "lemon" - desc = "When life gives you lemons, be grateful they aren't limes." - icon_state = "lemon" - potency = 20 - filling_color = "#FAF328" - plantname = "lemon" - -/obj/item/weapon/reagent_containers/food/snacks/grown/orange - name = "orange" - desc = "It's an tangy fruit." - icon_state = "orange" - potency = 20 - filling_color = "#FAAD28" - plantname = "orange" - -/obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet - name = "white-beet" - desc = "You can't beat white-beet." - icon_state = "whitebeet" - potency = 15 - filling_color = "#FFFCCC" - plantname = "whitebeet" - -/obj/item/weapon/reagent_containers/food/snacks/grown/banana - name = "banana" - desc = "It's an excellent prop for a comedy." - icon = 'icons/obj/items.dmi' - icon_state = "banana" - item_state = "banana" - filling_color = "#FCF695" - trash = /obj/item/weapon/bananapeel - plantname = "banana" - -/obj/item/weapon/reagent_containers/food/snacks/grown/chili - name = "chili" - desc = "It's spicy! Wait... IT'S BURNING ME!!" - icon_state = "chilipepper" - filling_color = "#FF0000" - plantname = "chili" - -/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant - name = "eggplant" - desc = "Maybe there's a chicken inside?" - icon_state = "eggplant" - filling_color = "#550F5C" - plantname = "eggplant" - -/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans - name = "soybeans" - desc = "It's pretty bland, but oh the possibilities..." - gender = PLURAL - filling_color = "#E6E8B7" - icon_state = "soybeans" - plantname = "soybean" - -/obj/item/weapon/reagent_containers/food/snacks/grown/koibeans - name = "koibean" - desc = "Something about these seems fishy." - gender = PLURAL - icon_state = "koibeans" - filling_color = "#F0E68C" - plantname = "koibean" - -/obj/item/weapon/reagent_containers/food/snacks/grown/tomato - name = "tomato" - desc = "I say to-mah-to, you say tom-mae-to." - icon_state = "tomato" - filling_color = "#FF0000" - potency = 10 - plantname = "tomato" - -/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato - name = "killer-tomato" - desc = "I say to-mah-to, you say tom-mae-to... OH GOD IT'S EATING MY LEGS!!" - icon_state = "killertomato" - potency = 10 - filling_color = "#FF0000" - plantname = "killertomato" - -/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato/attack_self(mob/user as mob) - if(istype(user.loc, /turf/space)) - return - new /mob/living/simple_animal/tomato(user.loc) - qdel(src) - - to_chat(user, "You plant the killer-tomato.") - -/obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato - name = "blood-tomato" - desc = "So bloody...so...very...bloody....AHHHH!!!!" - icon_state = "bloodtomato" - potency = 10 - filling_color = "#FF0000" - plantname = "bloodtomato" - -/obj/item/weapon/reagent_containers/food/snacks/grown/bluetomato - name = "blue-tomato" - desc = "I say blue-mah-to, you say blue-mae-to." - icon_state = "bluetomato" - potency = 10 - filling_color = "#586CFC" - plantname = "bluetomato" - -/obj/item/weapon/reagent_containers/food/snacks/grown/wheat - name = "wheat" - desc = "Sigh... wheat... a-grain?" - gender = PLURAL - icon_state = "wheat" - filling_color = "#F7E186" - plantname = "wheat" - -/obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk - name = "rice stalk" - desc = "Rice to see you." - gender = PLURAL - icon_state = "rice" - filling_color = "#FFF8DB" - plantname = "rice" - -/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod - name = "kudzu pod" - desc = "Pueraria Virallis: An invasive species with vines that rapidly creep and wrap around whatever they contact." - icon_state = "kudzupod" - filling_color = "#59691B" - plantname = "kudzu" - -/obj/item/weapon/reagent_containers/food/snacks/grown/icepepper - name = "ice-pepper" - desc = "It's a mutant strain of chili" - icon_state = "icepepper" - potency = 20 - filling_color = "#66CEED" - plantname = "icechili" - -/obj/item/weapon/reagent_containers/food/snacks/grown/carrot - name = "carrot" - desc = "It's good for the eyes!" - icon_state = "carrot" - potency = 10 - filling_color = "#FFC400" - plantname = "carrot" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/reishi - name = "reishi" - desc = "Ganoderma lucidum: A special fungus believed to help relieve stress." - icon_state = "reishi" - potency = 10 - filling_color = "#FF4800" - plantname = "reishi" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita - name = "fly amanita" - desc = "Amanita Muscaria: Learn poisonous mushrooms by heart. Only pick mushrooms you know." - icon_state = "amanita" - potency = 10 - filling_color = "#FF0000" - plantname = "amanita" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel - name = "destroying angel" - desc = "Amanita Virosa: Deadly poisonous basidiomycete fungus filled with alpha amatoxins." - icon_state = "angel" - potency = 35 - filling_color = "#FFDEDE" - plantname = "destroyingangel" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap - name = "liberty-cap" - desc = "Psilocybe Semilanceata: Liberate yourself!" - icon_state = "libertycap" - potency = 15 - filling_color = "#F714BE" - plantname = "libertycap" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet - name = "plump-helmet" - desc = "Plumus Hellmus: Plump, soft and s-so inviting~" - icon_state = "plumphelmet" - filling_color = "#F714BE" - plantname = "plumphelmet" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom - name = "walking mushroom" - desc = "Plumus Locomotus: The beginning of the great walk." - icon_state = "walkingmushroom" - filling_color = "#FFBFEF" - potency = 30 - plantname = "walkingmushroom" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom/attack_self(mob/user as mob) - if(istype(user.loc, /turf/space)) - return - new /mob/living/simple_animal/hostile/mushroom(user.loc) - qdel(src) - - to_chat(user, "You plant the walking mushroom.") - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle - name = "chanterelle cluster" - desc = "Cantharellus Cibarius: These jolly yellow little shrooms sure look tasty!" - icon_state = "chanterelle" - filling_color = "#FFE991" - plantname = "mushrooms" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom - name = "glowshroom cluster" - desc = "Mycena Bregprox: This species of mushroom glows in the dark. Or does it?" - icon_state = "glowshroom" - filling_color = "#DAFF91" - potency = 30 - plantname = "glowshroom" - -/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom/attack_self(mob/user as mob) - if(istype(user.loc, /turf/space)) - return - var/obj/effect/glowshroom/planted = new /obj/effect/glowshroom(user.loc) - - planted.delay = 50 - planted.endurance = 100 - planted.potency = potency - qdel(src) - - to_chat(user, "You plant the glowshroom.") - -// ************************************* -// Complex Grown Object Defines - -// Putting these at the bottom so they don't clutter the list up. -Cheridan -// ************************************* - -/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato - name = "tomato" //"blue-space" is applied on new(), provided it's teleporting trait hasn't been removed - desc = "Its juices lubricate so well, you might slip through space-time." - icon_state = "bluespacetomato" - potency = 20 - origin_tech = "bluespace = 3" - filling_color = "#91F8FF" - plantname = "bluespacetomato" - -/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/cruciatus - plantname = "ambrosiacruciatus" - name = "ambrosia vulgaris branch" - desc = "This is a plant containing various healing chemicals." - icon_state = "ambrosiavulgaris" - potency = 10 - /*New() //NO SNOWFLAKE ALLOWED - ..() - spawn(5) //So potency can be set in the proc that creates these crops - reagents.add_reagent("nutriment", 1) - reagents.add_reagent("space_drugs", 1 + round(potency/8, 1)) - reagents.add_reagent("kelotane", 1 + round(potency/8, 1)) - reagents.add_reagent("bicaridine", 1 + round(potency/10, 1)) - reagents.add_reagent("toxin", 1 + round(potency/10, 1)) - reagents.add_reagent("spiritbreaker", 10) - bitesize = 1+round(reagents.total_volume/2, 1)*/ + + +// *********************************************************** +// Foods that are produced from hydroponics ~~~~~~~~~~ +// Data from the seeds carry over to these grown foods +// *********************************************************** + +//Grown foods +//Subclass so we can pass on values +/obj/item/weapon/reagent_containers/food/snacks/grown/ + var/plantname + var/potency = -1 + var/datum/seed/seed + icon = 'icons/obj/harvest.dmi' + New(newloc, newpotency) + if(!isnull(newpotency)) + potency = newpotency + ..() + src.pixel_x = rand(-5.0, 5) + src.pixel_y = rand(-5.0, 5) + +/obj/item/weapon/reagent_containers/food/snacks/grown/New() + ..() + + //Handle some post-spawn var stuff. + spawn(1) + //Fill the object up with the appropriate reagents. + if(!isnull(plantname)) + seed = plant_controller.seeds[plantname] + if(!seed || !seed.chems) + return + + potency = round(seed.potency) + force = seed.thorny ? 5+seed.carnivorous*3 : 0 + + var/totalreagents = 0 + for(var/rid in seed.chems) + var/list/reagent_data = seed.chems[rid] + var/rtotal = reagent_data[1] + if(reagent_data.len > 1 && potency > 0) + rtotal += round(potency/reagent_data[2]) + totalreagents += rtotal + + if(totalreagents) + var/coeff = min(reagents.maximum_volume / totalreagents, 1) + + for(var/rid in seed.chems) + var/list/reagent_data = seed.chems[rid] + var/rtotal = reagent_data[1] + if(reagent_data.len > 1 && potency > 0) + rtotal += round(potency/reagent_data[2]) + reagents.add_reagent(rid, max(1, round(rtotal*coeff, 0.1))) + + if(seed.teleporting) + name = "blue-space [name]" + if(seed.stinging) + name = "stinging [name]" + if(seed.juicy == 2) + name = "slippery [name]" + + if(reagents.total_volume > 0) + bitesize = 1 + round(reagents.total_volume/2, 1) + +/obj/item/weapon/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom) + ..() + if(!seed || !src) return + //if(seed.stinging) //we do NOT want to transfer reagents on throw, as it would mean plantbags full of throwable chloral injectors + // stinging_apply_reagents(M) //plus all sorts of nasty stuff like throw_impact not targeting a specific bodypart to check for protection. + + // We ONLY want to apply special effects if we're hitting a turf! That's because throw_impact will always be + // called on a turf AFTER it's called on the things ON the turf, and will runtime if the item doesn't exist anymore. + if(isturf(hit_atom)) + do_splat_effects(hit_atom) + return + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/do_splat_effects(atom/hit_atom) + if(seed.teleporting) + splat_reagent_reaction(get_turf(hit_atom)) + if(do_fruit_teleport(hit_atom, usr, potency)) + visible_message("The [src] splatters, causing a distortion in space-time!") + else if(splat_decal(get_turf(hit_atom))) + visible_message("The [src.name] has been squashed.","You hear a smack.") + qdel(src) + return + + if(seed.juicy) + splat_decal(get_turf(hit_atom)) + splat_reagent_reaction(get_turf(hit_atom)) + visible_message("The [src.name] has been squashed.","You hear a smack.") + qdel(src) + return + +/obj/item/weapon/reagent_containers/food/snacks/grown/attack(mob/living/M, mob/user, def_zone) + if(user.a_intent == I_HURT) + . = handle_attack(src,M,user,def_zone) + if(seed.stinging) + if(M.getarmor(def_zone, "melee") < 5) + var/reagentlist = stinging_apply_reagents(M) + if(reagentlist) + to_chat(M, "You are stung by \the [src]!") + add_attacklogs(user, M, "stung", object = src, addition = "Reagents: [english_list(seed.get_reagent_names())]", admin_warn = 1) + to_chat(user, "Some of \the [src]'s stingers break off in the hit!") + potency -= rand(1,(potency/3)+1) + do_splat_effects(M) + return + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/carbon/M) + ..() + if(!seed) return + if(!istype(M)) return + if(!M.on_foot()) + return + if(seed.thorny || seed.stinging) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(!H.check_body_part_coverage(FEET)) + var/datum/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot")) + if(affecting && affecting.is_organic()) + if(thorns_apply_damage(M, affecting)) + to_chat(H, "You step on \the [src]'s sharp thorns!") + if(H.species && !(H.species.flags & NO_PAIN)) + H.Weaken(3) + if(stinging_apply_reagents(M)) + to_chat(H, "Your step on \the [src]'s stingers!") + potency -= rand(1,(potency/3)+1) + if(seed.juicy == 2) + if(M.Slip(3, 2)) + to_chat(M, "You slipped on the [name]!") + do_splat_effects(M) + +/obj/item/weapon/reagent_containers/food/snacks/grown/pickup(mob/user) + ..() + if(!seed) return + if(seed.thorny || seed.stinging) + var/mob/living/carbon/human/H = user + if(!istype(H)) + return + if(H.check_body_part_coverage(HANDS)) + return + var/datum/organ/external/affecting = H.get_organ(pick("r_hand","l_hand")) + if(!affecting || !affecting.is_organic()) + return + if(stinging_apply_reagents(H)) + to_chat(H, "You are stung by \the [src]!") + potency -= rand(1,(potency/3)+1) + if(thorns_apply_damage(H, affecting)) + to_chat(H, "You are prickled by the sharp thorns on \the [src]!") + spawn(3) + if(H.species && !(H.species.flags & NO_PAIN)) + H.drop_item(src) + +/obj/item/weapon/reagent_containers/food/snacks/grown/On_Consume(var/mob/living/carbon/human/H) + if(seed.thorny && istype(H)) + var/datum/organ/external/affecting = H.get_organ("head") + if(affecting) + if(thorns_apply_damage(H, affecting)) + to_chat(H, "Your mouth is cut by \the [src]'s sharp thorns!") + //H.stunned++ //just a 1 second pause to prevent people from spamming pagedown on this, since it's important + ..() + +/obj/item/weapon/reagent_containers/food/snacks/grown/examine(mob/user) + ..() + if(!seed) return + var/traits = "" + if(seed.stinging) traits += "It's covered in tiny stingers. " + if(seed.thorny) traits += "It's covered in sharp thorns. " + if(seed.juicy == 2) traits += "It looks ripe and excessively juicy. " + if(seed.teleporting) traits += "It seems to be spatially unstable. " + if(traits) to_chat(user, traits) + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/splat_decal(turf/T) + var/obj/effect/decal/cleanable/S = getFromPool(seed.splat_type,T) + S.New(S.loc) + if(seed.splat_type == /obj/effect/decal/cleanable/fruit_smudge/) + if(filling_color != "#FFFFFF") + S.color = filling_color + else + S.color = AverageColor(getFlatIcon(src, src.dir, 0), 1, 1) + S.name = "[seed.seed_name] smudge" + if(seed.biolum && seed.biolum_colour) + S.set_light(1, l_color = seed.biolum_colour) + return 1 + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/splat_reagent_reaction(turf/T) + if(src.reagents.total_volume > 0) + src.reagents.reaction(T) + for(var/atom/A in T) + src.reagents.reaction(A) + return 1 + return 0 + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/thorns_apply_damage(mob/living/carbon/human/H, datum/organ/external/affecting) + if(!seed.thorny || !affecting) + return 0 + //if(affecting.take_damage(5+seed.carnivorous*3, 0, 0, "plant thorns")) //For some fucked up reason, it's not returning 1 + affecting.take_damage(5+seed.carnivorous*3, 0, 0, "plant thorns") + H.UpdateDamageIcon() + return 1 + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/stinging_apply_reagents(mob/living/carbon/human/H) + if(!seed.stinging) + return 0 + if(!reagents || reagents.total_volume <= 0) + return 0 + if(!seed.chems || !seed.chems.len) + return 0 + var/injecting = Clamp(1, 3, potency/10) + for(var/rid in seed.chems) //Only transfer reagents that the plant naturally produces, no injecting chloral into your nettles. + reagents.trans_id_to(H,rid,injecting) + . = 1 + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/do_fruit_teleport(atom/hit_atom, mob/M, var/potency) //Does this need logging? + var/datum/zLevel/L = get_z_level(src) + if(!L || L.teleJammed) + return 0 + + var/outer_teleport_radius = potency/10 //Plant potency determines radius of teleport. + var/inner_teleport_radius = potency/15 //At base potency, nothing will happen, since the radius is 0. + if(inner_teleport_radius < 1) + return 0 + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + + var/list/turfs = new/list() + //This could likely use some standardization but I have no idea how to not break it. + for(var/turf/T in trange(outer_teleport_radius, get_turf(hit_atom))) + if(get_dist(T, hit_atom) <= inner_teleport_radius) + continue + if(is_blocked_turf(T) || istype(T, /turf/space)) + continue + if(T.x > world.maxx-outer_teleport_radius || T.x < outer_teleport_radius) + continue + if(T.y > world.maxy-outer_teleport_radius || T.y < outer_teleport_radius) + continue + turfs += T + if(!turfs.len) + var/list/turfs_to_pick_from = list() + for(var/turf/T in trange(outer_teleport_radius, get_turf(hit_atom))) + if(get_dist(T, hit_atom) > inner_teleport_radius) + turfs_to_pick_from += T + turfs += pick(/turf in turfs_to_pick_from) + var/turf/picked = pick(turfs) + if(!isturf(picked)) + return 0 + switch(rand(1, 2)) //50-50 % chance to teleport the thrower or the target. + if(1) //Teleports the person who threw the fruit + s.set_up(3, 1, M) + s.start() + new/obj/effect/decal/cleanable/molten_item(M.loc) //Leaves a pile of goo behind for dramatic effect. + M.forceMove(picked) //Send then to that location we picked previously + spawn() + s.set_up(3, 1, M) + s.start() //Two set of sparks, one before the teleport and one after. //Sure then ? + if(2) //Teleports the target instead. + s.set_up(3, 1, hit_atom) + s.start() + new/obj/effect/decal/cleanable/molten_item(get_turf(hit_atom)) //Leave a pile of goo behind for dramatic effect... + for(var/mob/A in get_turf(hit_atom)) //For the mobs in the tile that was hit... + A.forceMove(picked) //And teleport them to the chosen location. + spawn() + s.set_up(3, 1, A) + s.start() + return 1 + + +/obj/item/weapon/reagent_containers/food/snacks/grown/corn + name = "ear of corn" + desc = "Needs some butter!" + plantname = "corn" + icon_state = "corn" + potency = 40 + filling_color = "#FFEE00" + trash = /obj/item/weapon/corncob + +/obj/item/weapon/reagent_containers/food/snacks/grown/cherries + name = "cherries" + desc = "Great for toppings!" + icon_state = "cherry" + filling_color = "#FF0000" + gender = PLURAL + plantname = "cherry" + slot_flags = SLOT_EARS + +/obj/item/weapon/reagent_containers/food/snacks/grown/cinnamon + name = "cinnamon sticks" + desc = "Straight from the bark!" + icon_state = "cinnamon" + filling_color = "#D2691E" + gender = PLURAL + plantname = "cinnamomum" + +/obj/item/weapon/reagent_containers/food/snacks/grown/poppy + name = "poppy" + desc = "Long-used as a symbol of rest, peace, and death." + icon_state = "poppy" + potency = 30 + filling_color = "#CC6464" + plantname = "poppies" + +/obj/item/weapon/reagent_containers/food/snacks/grown/harebell + name = "harebell" + desc = "\"I'll sweeten thy sad grave: thou shalt not lack the flower that's like thy face, pale primrose, nor the azured hare-bell, like thy veins; no, nor the leaf of eglantine, whom not to slander, out-sweeten’d not thy breath.\"" + icon_state = "harebell" + potency = 1 + filling_color = "#D4B2C9" + plantname = "harebells" + +/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower + name = "moonflower" + desc = "Store in a location at least 50 yards away from werewolves." + icon_state = "moonflower" + potency = 25 + filling_color = "#E6E6FA" + plantname = "moonflowers" + +/obj/item/weapon/reagent_containers/food/snacks/grown/potato + name = "potato" + desc = "Boil 'em! Mash 'em! Stick 'em in a stew!" + icon_state = "potato" + potency = 25 + filling_color = "#E6E8DA" + plantname = "potato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/potato/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(istype(W, /obj/item/stack/cable_coil)) + if(W:amount >= 5) + W:amount -= 5 + if(!W:amount) + qdel(W) + to_chat(user, "You add some cable to \the [src] and slide it inside the battery encasing.") + var/obj/item/weapon/cell/potato/pocell = new /obj/item/weapon/cell/potato(user.loc) + pocell.maxcharge = src.potency * 10 + pocell.charge = pocell.maxcharge + qdel(src) + return + +/obj/item/weapon/reagent_containers/food/snacks/grown/grapes + name = "bunch of grapes" + desc = "Nutritious!" + icon_state = "grapes" + filling_color = "#A332AD" + plantname = "grapes" + +/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes + name = "bunch of green grapes" + desc = "Nutritious!" + icon_state = "greengrapes" + potency = 25 + filling_color = "#A6FFA3" + plantname = "greengrapes" + +/obj/item/weapon/reagent_containers/food/snacks/grown/peanut + name = "peanut" + desc = "Nuts!" + icon_state = "peanut" + filling_color = "857e27" + potency = 25 + plantname = "peanut" + +/obj/item/weapon/reagent_containers/food/snacks/grown/cabbage + name = "cabbage" + desc = "Ewwwwwwwwww. Cabbage." + icon_state = "cabbage" + potency = 25 + filling_color = "#A2B5A1" + plantname = "cabbage" + +/obj/item/weapon/reagent_containers/food/snacks/grown/berries + name = "bunch of berries" + desc = "Nutritious!" + icon_state = "berrypile" + filling_color = "#C2C9FF" + plantname = "berries" + +/obj/item/weapon/reagent_containers/food/snacks/grown/plastellium + name = "clump of plastellium" + desc = "Hmm, needs some processing" + icon_state = "plastellium" + filling_color = "#C4C4C4" + plantname = "plastic" + +/obj/item/weapon/reagent_containers/food/snacks/grown/glowberries + name = "bunch of glow-berries" + desc = "Nutritious!" + var/light_on = 1 + var/brightness_on = 2 //luminosity when on + filling_color = "#D3FF9E" + icon_state = "glowberrypile" + plantname = "glowberries" + +/obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod + name = "cocoa pod" + desc = "Can be ground into cocoa powder." + icon_state = "cocoapod" + potency = 50 + filling_color = "#9C8E54" + plantname = "cocoa" + +/obj/item/weapon/reagent_containers/food/snacks/grown/sugarcane + name = "sugarcane" + desc = "Sickly sweet." + icon_state = "sugarcane" + potency = 50 + filling_color = "#C0C9AD" + plantname = "sugarcane" + +/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries + name = "bunch of poison-berries" + desc = "Taste so good, you could die!" + icon_state = "poisonberrypile" + gender = PLURAL + potency = 15 + filling_color = "#B422C7" + plantname = "poisonberries" + +/obj/item/weapon/reagent_containers/food/snacks/grown/deathberries + name = "bunch of death-berries" + desc = "Taste so good, you could die!" + icon_state = "deathberrypile" + gender = PLURAL + potency = 50 + filling_color = "#4E0957" + plantname = "deathberries" + +/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris + name = "ambrosia vulgaris branch" + desc = "This is a plant containing various healing chemicals." + icon_state = "ambrosiavulgaris" + potency = 10 + filling_color = "#125709" + plantname = "ambrosia" + +/obj/item/weapon/reagent_containers/food/snacks/grown/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/paper)) + qdel(O) + to_chat(user, "You roll a blunt out of \the [src].") + var/obj/item/clothing/mask/cigarette/blunt/rolled/B = new/obj/item/clothing/mask/cigarette/blunt/rolled(src.loc) + B.name = "[src] blunt" + reagents.trans_to(B, (reagents.total_volume)) + user.put_in_hands(B) + user.drop_from_inventory(src) + qdel(src) + else + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/deus + name = "ambrosia deus branch" + desc = "Eating this makes you feel immortal!" + icon_state = "ambrosiadeus" + potency = 10 + filling_color = "#229E11" + plantname = "ambrosiadeus" + +/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/deus/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/paper)) + qdel(O) + to_chat(user, "You roll a godly blunt.") + var/obj/item/clothing/mask/cigarette/blunt/deus/rolled/B = new/obj/item/clothing/mask/cigarette/blunt/deus/rolled(src.loc) + reagents.trans_to(B, (reagents.total_volume)) + B.light_color = filling_color + user.put_in_hands(B) + user.drop_from_inventory(src) + qdel(src) + else + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/grown/apple + name = "apple" + desc = "It's a little piece of Eden." + icon_state = "apple" + potency = 15 + filling_color = "#DFE88B" + plantname = "apple" + +/obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned + filling_color = "#B3BD5E" + plantname = "poisonapple" + +/obj/item/weapon/reagent_containers/food/snacks/grown/goldapple + name = "golden apple" + desc = "Emblazoned upon the apple is the word 'Kallisti'." + icon_state = "goldapple" + potency = 15 + filling_color = "#F5CB42" + plantname = "goldapple" + +/obj/item/weapon/reagent_containers/food/snacks/grown/watermelon + name = "watermelon" + desc = "It's full of watery goodness." + icon_state = "watermelon" + potency = 10 + filling_color = "#FA2863" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/watermelonslice + slices_num = 5 + plantname = "watermelon" + +/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin + name = "pumpkin" + desc = "It's large and scary." + icon_state = "pumpkin" + potency = 10 + filling_color = "#FAB728" + plantname = "pumpkin" + +/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin/attackby(obj/item/weapon/W as obj, mob/user as mob) + ..() + if(W.is_sharp() >= 1) + user.visible_message("[user] carves a face into \the [src] with \the [W]!", "You carve a face into \the [src] with \the [W]!") + new /obj/item/clothing/head/pumpkinhead(get_turf(src)) //Don't move it + qdel(src) + return + +/obj/item/weapon/reagent_containers/food/snacks/grown/lime + name = "lime" + desc = "It's so sour, your face will twist." + icon_state = "lime" + potency = 20 + filling_color = "#28FA59" + plantname = "lime" + +/obj/item/weapon/reagent_containers/food/snacks/grown/lemon + name = "lemon" + desc = "When life gives you lemons, be grateful they aren't limes." + icon_state = "lemon" + potency = 20 + filling_color = "#FAF328" + plantname = "lemon" + +/obj/item/weapon/reagent_containers/food/snacks/grown/orange + name = "orange" + desc = "It's an tangy fruit." + icon_state = "orange" + potency = 20 + filling_color = "#FAAD28" + plantname = "orange" + +/obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet + name = "white-beet" + desc = "You can't beat white-beet." + icon_state = "whitebeet" + potency = 15 + filling_color = "#FFFCCC" + plantname = "whitebeet" + +/obj/item/weapon/reagent_containers/food/snacks/grown/banana + name = "banana" + desc = "It's an excellent prop for a comedy." + icon = 'icons/obj/items.dmi' + icon_state = "banana" + item_state = "banana" + filling_color = "#FCF695" + trash = /obj/item/weapon/bananapeel + plantname = "banana" + +/obj/item/weapon/reagent_containers/food/snacks/grown/chili + name = "chili" + desc = "It's spicy! Wait... IT'S BURNING ME!!" + icon_state = "chilipepper" + filling_color = "#FF0000" + plantname = "chili" + +/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant + name = "eggplant" + desc = "Maybe there's a chicken inside?" + icon_state = "eggplant" + filling_color = "#550F5C" + plantname = "eggplant" + +/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans + name = "soybeans" + desc = "It's pretty bland, but oh the possibilities..." + gender = PLURAL + filling_color = "#E6E8B7" + icon_state = "soybeans" + plantname = "soybean" + +/obj/item/weapon/reagent_containers/food/snacks/grown/koibeans + name = "koibean" + desc = "Something about these seems fishy." + gender = PLURAL + icon_state = "koibeans" + filling_color = "#F0E68C" + plantname = "koibean" + +/obj/item/weapon/reagent_containers/food/snacks/grown/tomato + name = "tomato" + desc = "I say to-mah-to, you say tom-mae-to." + icon_state = "tomato" + filling_color = "#FF0000" + potency = 10 + plantname = "tomato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato + name = "killer-tomato" + desc = "I say to-mah-to, you say tom-mae-to... OH GOD IT'S EATING MY LEGS!!" + icon_state = "killertomato" + potency = 10 + filling_color = "#FF0000" + plantname = "killertomato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato/attack_self(mob/user as mob) + if(istype(user.loc, /turf/space)) + return + new /mob/living/simple_animal/tomato(user.loc) + qdel(src) + + to_chat(user, "You plant the killer-tomato.") + +/obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato + name = "blood-tomato" + desc = "So bloody...so...very...bloody....AHHHH!!!!" + icon_state = "bloodtomato" + potency = 10 + filling_color = "#FF0000" + plantname = "bloodtomato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/bluetomato + name = "blue-tomato" + desc = "I say blue-mah-to, you say blue-mae-to." + icon_state = "bluetomato" + potency = 10 + filling_color = "#586CFC" + plantname = "bluetomato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/wheat + name = "wheat" + desc = "Sigh... wheat... a-grain?" + gender = PLURAL + icon_state = "wheat" + filling_color = "#F7E186" + plantname = "wheat" + +/obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk + name = "rice stalk" + desc = "Rice to see you." + gender = PLURAL + icon_state = "rice" + filling_color = "#FFF8DB" + plantname = "rice" + +/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod + name = "kudzu pod" + desc = "Pueraria Virallis: An invasive species with vines that rapidly creep and wrap around whatever they contact." + icon_state = "kudzupod" + filling_color = "#59691B" + plantname = "kudzu" + +/obj/item/weapon/reagent_containers/food/snacks/grown/icepepper + name = "ice-pepper" + desc = "It's a mutant strain of chili" + icon_state = "icepepper" + potency = 20 + filling_color = "#66CEED" + plantname = "icechili" + +/obj/item/weapon/reagent_containers/food/snacks/grown/carrot + name = "carrot" + desc = "It's good for the eyes!" + icon_state = "carrot" + potency = 10 + filling_color = "#FFC400" + plantname = "carrot" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/reishi + name = "reishi" + desc = "Ganoderma lucidum: A special fungus believed to help relieve stress." + icon_state = "reishi" + potency = 10 + filling_color = "#FF4800" + plantname = "reishi" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita + name = "fly amanita" + desc = "Amanita Muscaria: Learn poisonous mushrooms by heart. Only pick mushrooms you know." + icon_state = "amanita" + potency = 10 + filling_color = "#FF0000" + plantname = "amanita" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel + name = "destroying angel" + desc = "Amanita Virosa: Deadly poisonous basidiomycete fungus filled with alpha amatoxins." + icon_state = "angel" + potency = 35 + filling_color = "#FFDEDE" + plantname = "destroyingangel" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap + name = "liberty-cap" + desc = "Psilocybe Semilanceata: Liberate yourself!" + icon_state = "libertycap" + potency = 15 + filling_color = "#F714BE" + plantname = "libertycap" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet + name = "plump-helmet" + desc = "Plumus Hellmus: Plump, soft and s-so inviting~" + icon_state = "plumphelmet" + filling_color = "#F714BE" + plantname = "plumphelmet" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom + name = "walking mushroom" + desc = "Plumus Locomotus: The beginning of the great walk." + icon_state = "walkingmushroom" + filling_color = "#FFBFEF" + potency = 30 + plantname = "walkingmushroom" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom/attack_self(mob/user as mob) + if(istype(user.loc, /turf/space)) + return + new /mob/living/simple_animal/hostile/mushroom(user.loc) + qdel(src) + + to_chat(user, "You plant the walking mushroom.") + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle + name = "chanterelle cluster" + desc = "Cantharellus Cibarius: These jolly yellow little shrooms sure look tasty!" + icon_state = "chanterelle" + filling_color = "#FFE991" + plantname = "mushrooms" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom + name = "glowshroom cluster" + desc = "Mycena Bregprox: This species of mushroom glows in the dark. Or does it?" + icon_state = "glowshroom" + filling_color = "#DAFF91" + potency = 30 + plantname = "glowshroom" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom/attack_self(mob/user as mob) + if(istype(user.loc, /turf/space)) + return + var/obj/effect/glowshroom/planted = new /obj/effect/glowshroom(user.loc) + + planted.delay = 50 + planted.endurance = 100 + planted.potency = potency + qdel(src) + + to_chat(user, "You plant the glowshroom.") + +// ************************************* +// Complex Grown Object Defines - +// Putting these at the bottom so they don't clutter the list up. -Cheridan +// ************************************* + +/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato + name = "tomato" //"blue-space" is applied on new(), provided it's teleporting trait hasn't been removed + desc = "Its juices lubricate so well, you might slip through space-time." + icon_state = "bluespacetomato" + potency = 20 + origin_tech = "bluespace = 3" + filling_color = "#91F8FF" + plantname = "bluespacetomato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris/cruciatus + plantname = "ambrosiacruciatus" + name = "ambrosia vulgaris branch" + desc = "This is a plant containing various healing chemicals." + icon_state = "ambrosiavulgaris" + potency = 10 + /*New() //NO SNOWFLAKE ALLOWED + ..() + spawn(5) //So potency can be set in the proc that creates these crops + reagents.add_reagent("nutriment", 1) + reagents.add_reagent("space_drugs", 1 + round(potency/8, 1)) + reagents.add_reagent("kelotane", 1 + round(potency/8, 1)) + reagents.add_reagent("bicaridine", 1 + round(potency/10, 1)) + reagents.add_reagent("toxin", 1 + round(potency/10, 1)) + reagents.add_reagent("spiritbreaker", 10) + bitesize = 1+round(reagents.total_volume/2, 1)*/ diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index e437d7fb21b..7a253169faa 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -1,396 +1,396 @@ - -//////////////////////////////////////////////////////////////////////////////// -/// (Mixing) Glass. -//////////////////////////////////////////////////////////////////////////////// -/obj/item/weapon/reagent_containers/glass - name = " " - var/base_name = " " - desc = " " - icon = 'icons/obj/chemical.dmi' - icon_state = "null" - item_state = "null" - w_type = RECYK_GLASS - amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(5,10,15,25,30,50) - volume = 50 - flags = FPRINT | OPENCONTAINER - - var/label_text = "" - - //This is absolutely terrible - // TODO To remove this, return 1 on every attackby() that handles reagent_containers. - var/list/can_be_placed_into = list( - /obj/machinery/chem_master/, - /obj/machinery/chem_dispenser/, - /obj/machinery/reagentgrinder, - /obj/structure/table, - /obj/structure/closet, - /obj/structure/sink, - /obj/structure/centrifuge/, - /obj/item/weapon/storage, - /obj/item/weapon/solder, - /obj/machinery/atmospherics/unary/cryo_cell, - /obj/machinery/dna_scannernew, - /obj/item/weapon/grenade/chem_grenade, - /obj/item/weapon/electrolyzer, - /obj/machinery/bot/medbot, - /obj/machinery/computer/pandemic, - /obj/item/weapon/storage/secure/safe, - /obj/machinery/iv_drip, - /obj/machinery/disease2/incubator, - /obj/machinery/disposal, - /obj/machinery/apiary, - /mob/living/simple_animal/cow, - /mob/living/simple_animal/hostile/retaliate/goat, - /obj/machinery/centrifuge, - /obj/machinery/cooking/icemachine, - /obj/machinery/sleeper, - /obj/machinery/anomaly, - /obj/machinery/bunsen_burner - ) - -/obj/item/weapon/reagent_containers/glass/get_rating() - return volume / 50 - -/obj/item/weapon/reagent_containers/glass/New() - ..() - base_name = name - update_icon() //Used by all subtypes for reagent filling, and allows roundstart lids - -/obj/item/weapon/reagent_containers/glass/mop_act(obj/item/weapon/mop/M, mob/user) - return is_open_container() - -/obj/item/weapon/reagent_containers/glass/examine(mob/user) - ..() - if(!is_open_container()) + +//////////////////////////////////////////////////////////////////////////////// +/// (Mixing) Glass. +//////////////////////////////////////////////////////////////////////////////// +/obj/item/weapon/reagent_containers/glass + name = " " + var/base_name = " " + desc = " " + icon = 'icons/obj/chemical.dmi' + icon_state = "null" + item_state = "null" + w_type = RECYK_GLASS + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(5,10,15,25,30,50) + volume = 50 + flags = FPRINT | OPENCONTAINER + + var/label_text = "" + + //This is absolutely terrible + // TODO To remove this, return 1 on every attackby() that handles reagent_containers. + var/list/can_be_placed_into = list( + /obj/machinery/chem_master/, + /obj/machinery/chem_dispenser/, + /obj/machinery/reagentgrinder, + /obj/structure/table, + /obj/structure/closet, + /obj/structure/sink, + /obj/structure/centrifuge/, + /obj/item/weapon/storage, + /obj/item/weapon/solder, + /obj/machinery/atmospherics/unary/cryo_cell, + /obj/machinery/dna_scannernew, + /obj/item/weapon/grenade/chem_grenade, + /obj/item/weapon/electrolyzer, + /obj/machinery/bot/medbot, + /obj/machinery/computer/pandemic, + /obj/item/weapon/storage/secure/safe, + /obj/machinery/iv_drip, + /obj/machinery/disease2/incubator, + /obj/machinery/disposal, + /obj/machinery/apiary, + /mob/living/simple_animal/cow, + /mob/living/simple_animal/hostile/retaliate/goat, + /obj/machinery/centrifuge, + /obj/machinery/cooking/icemachine, + /obj/machinery/sleeper, + /obj/machinery/anomaly, + /obj/machinery/bunsen_burner + ) + +/obj/item/weapon/reagent_containers/glass/get_rating() + return volume / 50 + +/obj/item/weapon/reagent_containers/glass/New() + ..() + base_name = name + update_icon() //Used by all subtypes for reagent filling, and allows roundstart lids + +/obj/item/weapon/reagent_containers/glass/mop_act(obj/item/weapon/mop/M, mob/user) + return is_open_container() + +/obj/item/weapon/reagent_containers/glass/examine(mob/user) + ..() + if(!is_open_container()) to_chat(user, "An airtight lid seals it completely.") - -/obj/item/weapon/reagent_containers/glass/attack_self() - ..() - if(is_open_container()) + +/obj/item/weapon/reagent_containers/glass/attack_self() + ..() + if(is_open_container()) to_chat(usr, "You put the lid on \the [src].") - flags ^= OPENCONTAINER - else + flags ^= OPENCONTAINER + else to_chat(usr, "You take the lid off \the [src].") - flags |= OPENCONTAINER - update_icon() - -/obj/item/weapon/reagent_containers/glass/afterattack(var/atom/target, var/mob/user, var/adjacency_flag, var/click_params) - if (!adjacency_flag) - return - - if (is_type_in_list(target, can_be_placed_into)) - return - - var/transfer_result = transfer(target, user, splashable_units = -1) // Potentially splash with everything inside - - if((transfer_result > 10) && (isturf(target) || istype(target, /obj/machinery/portable_atmospherics/hydroponics))) //if we're splashing a decent amount of reagent on the floor - playsound(get_turf(target), 'sound/effects/slosh.ogg', 25, 1) //or in an hydro tray, then we make some noise. - -/obj/item/weapon/reagent_containers/glass/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen)) - var/tmp_label = sanitize(input(user, "Enter a label for [src.name]","Label",src.label_text)) - if (!Adjacent(user) || user.stat) return - if(length(tmp_label) > 10) + flags |= OPENCONTAINER + update_icon() + +/obj/item/weapon/reagent_containers/glass/afterattack(var/atom/target, var/mob/user, var/adjacency_flag, var/click_params) + if (!adjacency_flag) + return + + if (is_type_in_list(target, can_be_placed_into)) + return + + var/transfer_result = transfer(target, user, splashable_units = -1) // Potentially splash with everything inside + + if((transfer_result > 10) && (isturf(target) || istype(target, /obj/machinery/portable_atmospherics/hydroponics))) //if we're splashing a decent amount of reagent on the floor + playsound(get_turf(target), 'sound/effects/slosh.ogg', 25, 1) //or in an hydro tray, then we make some noise. + +/obj/item/weapon/reagent_containers/glass/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen)) + var/tmp_label = sanitize(input(user, "Enter a label for [src.name]","Label",src.label_text)) + if (!Adjacent(user) || user.stat) return + if(length(tmp_label) > 10) to_chat(user, "The label can be at most 10 characters long.") - else + else to_chat(user, "You set the label to \"[tmp_label]\".") - src.label_text = tmp_label - src.update_name_label() - -/obj/item/weapon/reagent_containers/glass/proc/update_name_label() - if(src.label_text == "") - src.name = src.base_name - else - src.name = "[src.base_name] ([src.label_text])" - -/obj/item/weapon/reagent_containers/glass/beaker - name = "beaker" - desc = "A beaker. Can hold up to 50 units." - icon = 'icons/obj/chemical.dmi' - icon_state = "beaker" - item_state = "beaker" - starting_materials = list(MAT_GLASS = 500) - origin_tech = "materials=1" - -/obj/item/weapon/reagent_containers/glass/beaker/mop_act(obj/item/weapon/mop/M, mob/user) - if(..()) - if (src.reagents.total_volume >= 1) - switch(src.reagents.total_volume) - if(1 to 30) - if(M.reagents.total_volume >= 3) + src.label_text = tmp_label + src.update_name_label() + +/obj/item/weapon/reagent_containers/glass/proc/update_name_label() + if(src.label_text == "") + src.name = src.base_name + else + src.name = "[src.base_name] ([src.label_text])" + +/obj/item/weapon/reagent_containers/glass/beaker + name = "beaker" + desc = "A beaker. Can hold up to 50 units." + icon = 'icons/obj/chemical.dmi' + icon_state = "beaker" + item_state = "beaker" + starting_materials = list(MAT_GLASS = 500) + origin_tech = "materials=1" + +/obj/item/weapon/reagent_containers/glass/beaker/mop_act(obj/item/weapon/mop/M, mob/user) + if(..()) + if (src.reagents.total_volume >= 1) + switch(src.reagents.total_volume) + if(1 to 30) + if(M.reagents.total_volume >= 3) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") - return 1 - src.reagents.trans_to(M, 1) + return 1 + src.reagents.trans_to(M, 1) to_chat(user, "You barely manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - if(30 to 100) - if(M.reagents.total_volume >= 5) + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + if(30 to 100) + if(M.reagents.total_volume >= 5) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") - return 1 - src.reagents.trans_to(M, 2) + return 1 + src.reagents.trans_to(M, 2) to_chat(user, "You manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - if(100 to INFINITY) - if(M.reagents.total_volume >= 10) + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + if(100 to INFINITY) + if(M.reagents.total_volume >= 10) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") - return 1 - src.reagents.trans_to(M, 5) + return 1 + src.reagents.trans_to(M, 5) to_chat(user, "You manage to soak [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - else + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + else to_chat(user, "What") - return 1 - else + return 1 + else to_chat(user, "Nothing left to wet [M] with!") - return 1 - -/obj/item/weapon/reagent_containers/glass/beaker/on_reagent_change() - update_icon() - -/obj/item/weapon/reagent_containers/glass/beaker/pickup(mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/glass/beaker/dropped(mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/glass/beaker/attack_hand() - ..() - update_icon() - -/obj/item/weapon/reagent_containers/glass/beaker/update_icon() - overlays.len = 0 - - if(reagents.total_volume) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10") - - var/percent = round((reagents.total_volume / volume) * 100) - switch(percent) - if(0 to 9) filling.icon_state = "[icon_state]-10" - if(10 to 24) filling.icon_state = "[icon_state]10" - if(25 to 49) filling.icon_state = "[icon_state]25" - if(50 to 74) filling.icon_state = "[icon_state]50" - if(75 to 79) filling.icon_state = "[icon_state]75" - if(80 to 90) filling.icon_state = "[icon_state]80" - if(91 to INFINITY) filling.icon_state = "[icon_state]100" - - filling.icon += mix_color_from_reagents(reagents.reagent_list) - filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) - - overlays += filling - - if(!is_open_container()) - var/image/lid = image(icon, src, "lid_[initial(icon_state)]") - overlays += lid - -/obj/item/weapon/reagent_containers/glass/beaker/large - name = "large beaker" - desc = "A large beaker. Can hold up to 100 units." - icon_state = "beakerlarge" - starting_materials = list(MAT_GLASS = 1500) - volume = 100 - possible_transfer_amounts = list(5,10,15,25,30,50,100) - -/obj/item/weapon/reagent_containers/glass/beaker/large/cyborg - var/obj/item/weapon/robot_module/holder - -/obj/item/weapon/reagent_containers/glass/beaker/large/cyborg/New(loc,_holder) - ..() - holder = _holder - -/obj/item/weapon/reagent_containers/glass/beaker/noreact - name = "stasis beaker" - desc = "A beaker powered by experimental bluespace technology. Chemicals are held in stasis and do not react inside of it. Can hold up to 50 units." - icon_state = "beakernoreact" - starting_materials = list(MAT_GLASS = 500) - volume = 50 - flags = FPRINT | OPENCONTAINER | NOREACT - origin_tech = "bluespace=3;materials=4" - -/obj/item/weapon/reagent_containers/glass/beaker/noreact/large - name = "large stasis beaker" - desc = "A beaker powered by experimental bluespace technology. Chemicals are held in stasis and do not react inside of it. Can hold up to 100 units." - icon_state = "beakernoreactlarge" - starting_materials = list(MAT_GLASS = 1500) - volume = 100 - origin_tech = "bluespace=4;materials=6" - -/obj/item/weapon/reagent_containers/glass/beaker/bluespace - name = "bluespace beaker" - desc = "A newly-developed high-capacity beaker, courtesy of bluespace research. Can hold up to 200 units." - icon_state = "beakerbluespace" - starting_materials = list(MAT_GLASS = 2000) - volume = 200 - w_type = RECYK_GLASS - possible_transfer_amounts = list(5,10,15,25,30,50,100,200) - flags = FPRINT | OPENCONTAINER - origin_tech = "bluespace=2;materials=3" - -/obj/item/weapon/reagent_containers/glass/beaker/bluespace/large - name = "large bluespace beaker" - desc = "A prototype ultra-capacity beaker, courtesy of bluespace research. Can hold up to 300 units." - icon_state = "beakerbluespacelarge" - starting_materials = list(MAT_GLASS = 5000) - volume = 300 - possible_transfer_amounts = list(5,10,15,25,30,50,100,150,200,300) - origin_tech = "bluespace=3;materials=5" - -/obj/item/weapon/reagent_containers/glass/beaker/vial - name = "vial" - desc = "A small glass vial. Can hold up to 25 units." - icon_state = "vial" - starting_materials = list(MAT_GLASS = 250) - volume = 25 - possible_transfer_amounts = list(5,10,15,25) - -/obj/item/weapon/reagent_containers/glass/beaker/vial/mop_act(obj/item/weapon/mop/M, mob/user) - return 0 - -/obj/item/weapon/reagent_containers/glass/beaker/cryoxadone - - New() - ..() - reagents.add_reagent("cryoxadone", 30) - -/obj/item/weapon/reagent_containers/glass/beaker/sulphuric - - New() - ..() - reagents.add_reagent("sacid", 50) - -/obj/item/weapon/reagent_containers/glass/beaker/slime - - New() - ..() - reagents.add_reagent("slimejelly", 50) - -/obj/item/weapon/reagent_containers/glass/bucket - desc = "It's a bucket." - name = "bucket" - icon = 'icons/obj/janitor.dmi' - icon_state = "bucket" - item_state = "bucket" - starting_materials = list(MAT_IRON = 200) - w_type = RECYK_METAL - w_class = 3.0 - amount_per_transfer_from_this = 20 - possible_transfer_amounts = list(10,20,30,50,70) - volume = 70 - flags = FPRINT | OPENCONTAINER - slot_flags = SLOT_HEAD - -/obj/item/weapon/reagent_containers/glass/bucket/mop_act(obj/item/weapon/mop/M, mob/user) - if(..()) - if (src.reagents.total_volume >= 1) - switch(src.reagents.total_volume) - if(1 to 30) - if(M.reagents.total_volume >= 5) + return 1 + +/obj/item/weapon/reagent_containers/glass/beaker/on_reagent_change() + update_icon() + +/obj/item/weapon/reagent_containers/glass/beaker/pickup(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/beaker/dropped(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/beaker/attack_hand() + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/beaker/update_icon() + overlays.len = 0 + + if(reagents.total_volume) + var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10") + + var/percent = round((reagents.total_volume / volume) * 100) + switch(percent) + if(0 to 9) filling.icon_state = "[icon_state]-10" + if(10 to 24) filling.icon_state = "[icon_state]10" + if(25 to 49) filling.icon_state = "[icon_state]25" + if(50 to 74) filling.icon_state = "[icon_state]50" + if(75 to 79) filling.icon_state = "[icon_state]75" + if(80 to 90) filling.icon_state = "[icon_state]80" + if(91 to INFINITY) filling.icon_state = "[icon_state]100" + + filling.icon += mix_color_from_reagents(reagents.reagent_list) + filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) + + overlays += filling + + if(!is_open_container()) + var/image/lid = image(icon, src, "lid_[initial(icon_state)]") + overlays += lid + +/obj/item/weapon/reagent_containers/glass/beaker/large + name = "large beaker" + desc = "A large beaker. Can hold up to 100 units." + icon_state = "beakerlarge" + starting_materials = list(MAT_GLASS = 1500) + volume = 100 + possible_transfer_amounts = list(5,10,15,25,30,50,100) + +/obj/item/weapon/reagent_containers/glass/beaker/large/cyborg + var/obj/item/weapon/robot_module/holder + +/obj/item/weapon/reagent_containers/glass/beaker/large/cyborg/New(loc,_holder) + ..() + holder = _holder + +/obj/item/weapon/reagent_containers/glass/beaker/noreact + name = "stasis beaker" + desc = "A beaker powered by experimental bluespace technology. Chemicals are held in stasis and do not react inside of it. Can hold up to 50 units." + icon_state = "beakernoreact" + starting_materials = list(MAT_GLASS = 500) + volume = 50 + flags = FPRINT | OPENCONTAINER | NOREACT + origin_tech = "bluespace=3;materials=4" + +/obj/item/weapon/reagent_containers/glass/beaker/noreact/large + name = "large stasis beaker" + desc = "A beaker powered by experimental bluespace technology. Chemicals are held in stasis and do not react inside of it. Can hold up to 100 units." + icon_state = "beakernoreactlarge" + starting_materials = list(MAT_GLASS = 1500) + volume = 100 + origin_tech = "bluespace=4;materials=6" + +/obj/item/weapon/reagent_containers/glass/beaker/bluespace + name = "bluespace beaker" + desc = "A newly-developed high-capacity beaker, courtesy of bluespace research. Can hold up to 200 units." + icon_state = "beakerbluespace" + starting_materials = list(MAT_GLASS = 2000) + volume = 200 + w_type = RECYK_GLASS + possible_transfer_amounts = list(5,10,15,25,30,50,100,200) + flags = FPRINT | OPENCONTAINER + origin_tech = "bluespace=2;materials=3" + +/obj/item/weapon/reagent_containers/glass/beaker/bluespace/large + name = "large bluespace beaker" + desc = "A prototype ultra-capacity beaker, courtesy of bluespace research. Can hold up to 300 units." + icon_state = "beakerbluespacelarge" + starting_materials = list(MAT_GLASS = 5000) + volume = 300 + possible_transfer_amounts = list(5,10,15,25,30,50,100,150,200,300) + origin_tech = "bluespace=3;materials=5" + +/obj/item/weapon/reagent_containers/glass/beaker/vial + name = "vial" + desc = "A small glass vial. Can hold up to 25 units." + icon_state = "vial" + starting_materials = list(MAT_GLASS = 250) + volume = 25 + possible_transfer_amounts = list(5,10,15,25) + +/obj/item/weapon/reagent_containers/glass/beaker/vial/mop_act(obj/item/weapon/mop/M, mob/user) + return 0 + +/obj/item/weapon/reagent_containers/glass/beaker/cryoxadone + + New() + ..() + reagents.add_reagent("cryoxadone", 30) + +/obj/item/weapon/reagent_containers/glass/beaker/sulphuric + + New() + ..() + reagents.add_reagent("sacid", 50) + +/obj/item/weapon/reagent_containers/glass/beaker/slime + + New() + ..() + reagents.add_reagent("slimejelly", 50) + +/obj/item/weapon/reagent_containers/glass/bucket + desc = "It's a bucket." + name = "bucket" + icon = 'icons/obj/janitor.dmi' + icon_state = "bucket" + item_state = "bucket" + starting_materials = list(MAT_IRON = 200) + w_type = RECYK_METAL + w_class = 3.0 + amount_per_transfer_from_this = 20 + possible_transfer_amounts = list(10,20,30,50,70) + volume = 70 + flags = FPRINT | OPENCONTAINER + slot_flags = SLOT_HEAD + +/obj/item/weapon/reagent_containers/glass/bucket/mop_act(obj/item/weapon/mop/M, mob/user) + if(..()) + if (src.reagents.total_volume >= 1) + switch(src.reagents.total_volume) + if(1 to 30) + if(M.reagents.total_volume >= 5) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") - return 1 - src.reagents.trans_to(M, 1) + return 1 + src.reagents.trans_to(M, 1) to_chat(user, "You barely manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - if(30 to 100) - if(M.reagents.total_volume >= 5) + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + if(30 to 100) + if(M.reagents.total_volume >= 5) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") - return 1 - src.reagents.trans_to(M, 2) + return 1 + src.reagents.trans_to(M, 2) to_chat(user, "You manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - if(100 to INFINITY) - if(M.reagents.total_volume >= 10) + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + if(100 to INFINITY) + if(M.reagents.total_volume >= 10) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") - return 1 - src.reagents.trans_to(M, 5) + return 1 + src.reagents.trans_to(M, 5) to_chat(user, "You manage to soak [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - else + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + else to_chat(user, "What") - return 1 - else + return 1 + else to_chat(user, "Nothing left to wet [M] with!") - return 1 - -/obj/item/weapon/reagent_containers/glass/bucket/attackby(var/obj/D, mob/user as mob) - if(isprox(D)) + return 1 + +/obj/item/weapon/reagent_containers/glass/bucket/attackby(var/obj/D, mob/user as mob) + if(isprox(D)) to_chat(user, "You add \the [D] to \the [src].") - qdel(D) - D = null - user.put_in_hands(new /obj/item/weapon/bucket_sensor) - user.drop_from_inventory(src) - qdel(src) - -/* -/obj/item/weapon/reagent_containers/glass/blender_jug - name = "Blender Jug" - desc = "A blender jug, part of a blender." - icon = 'icons/obj/kitchen.dmi' - icon_state = "blender_jug_e" - volume = 100 - - on_reagent_change() - switch(src.reagents.total_volume) - if(0) - icon_state = "blender_jug_e" - if(1 to 75) - icon_state = "blender_jug_h" - if(76 to 100) - icon_state = "blender_jug_f" - -/obj/item/weapon/reagent_containers/glass/canister //not used apparantly - desc = "It's a canister. Mainly used for transporting fuel." - name = "canister" - icon = 'icons/obj/tank.dmi' - icon_state = "canister" - item_state = "canister" - m_amt = 300 - g_amt = 0 - w_class = 4.0 - - amount_per_transfer_from_this = 20 - possible_transfer_amounts = list(10,20,30,60) - volume = 120 - flags = FPRINT - -/obj/item/weapon/reagent_containers/glass/dispenser - name = "reagent glass" - desc = "A reagent glass." - icon = 'icons/obj/chemical.dmi' - icon_state = "beaker0" - amount_per_transfer_from_this = 10 - flags = FPRINT | OPENCONTAINER - -/obj/item/weapon/reagent_containers/glass/dispenser/surfactant - name = "reagent glass (surfactant)" - icon_state = "liquid" - - New() - ..() - reagents.add_reagent("fluorosurfactant", 20) - -*/ - -//No idea if this actually works anymore. Please handle carefully -/obj/item/weapon/reagent_containers/glass/kettle - name = "Kettle" - desc = "A pot made for holding hot drinks. Can hold up to 75 units." - icon_state = "kettle" - starting_materials = list(MAT_IRON = 200) - volume = 75 - w_type = RECYK_GLASS - amount_per_transfer_from_this = 10 - flags = FPRINT | OPENCONTAINER - -/obj/item/weapon/reagent_containers/glass/kettle/red - icon_state = "kettle_red" - -/obj/item/weapon/reagent_containers/glass/kettle/blue - icon_state = "kettle_blue" - -/obj/item/weapon/reagent_containers/glass/kettle/purple - icon_state = "kettle_purple" - -/obj/item/weapon/reagent_containers/glass/kettle/green - icon_state = "kettle_green" + qdel(D) + D = null + user.put_in_hands(new /obj/item/weapon/bucket_sensor) + user.drop_from_inventory(src) + qdel(src) + +/* +/obj/item/weapon/reagent_containers/glass/blender_jug + name = "Blender Jug" + desc = "A blender jug, part of a blender." + icon = 'icons/obj/kitchen.dmi' + icon_state = "blender_jug_e" + volume = 100 + + on_reagent_change() + switch(src.reagents.total_volume) + if(0) + icon_state = "blender_jug_e" + if(1 to 75) + icon_state = "blender_jug_h" + if(76 to 100) + icon_state = "blender_jug_f" + +/obj/item/weapon/reagent_containers/glass/canister //not used apparantly + desc = "It's a canister. Mainly used for transporting fuel." + name = "canister" + icon = 'icons/obj/tank.dmi' + icon_state = "canister" + item_state = "canister" + m_amt = 300 + g_amt = 0 + w_class = 4.0 + + amount_per_transfer_from_this = 20 + possible_transfer_amounts = list(10,20,30,60) + volume = 120 + flags = FPRINT + +/obj/item/weapon/reagent_containers/glass/dispenser + name = "reagent glass" + desc = "A reagent glass." + icon = 'icons/obj/chemical.dmi' + icon_state = "beaker0" + amount_per_transfer_from_this = 10 + flags = FPRINT | OPENCONTAINER + +/obj/item/weapon/reagent_containers/glass/dispenser/surfactant + name = "reagent glass (surfactant)" + icon_state = "liquid" + + New() + ..() + reagents.add_reagent("fluorosurfactant", 20) + +*/ + +//No idea if this actually works anymore. Please handle carefully +/obj/item/weapon/reagent_containers/glass/kettle + name = "Kettle" + desc = "A pot made for holding hot drinks. Can hold up to 75 units." + icon_state = "kettle" + starting_materials = list(MAT_IRON = 200) + volume = 75 + w_type = RECYK_GLASS + amount_per_transfer_from_this = 10 + flags = FPRINT | OPENCONTAINER + +/obj/item/weapon/reagent_containers/glass/kettle/red + icon_state = "kettle_red" + +/obj/item/weapon/reagent_containers/glass/kettle/blue + icon_state = "kettle_blue" + +/obj/item/weapon/reagent_containers/glass/kettle/purple + icon_state = "kettle_purple" + +/obj/item/weapon/reagent_containers/glass/kettle/green + icon_state = "kettle_green" diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index 3550f86a775..77517fb2e6c 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -1,389 +1,389 @@ - -//Not to be confused with /obj/item/weapon/reagent_containers/food/drinks/bottle - -/obj/item/weapon/reagent_containers/glass/bottle - name = "bottle" - desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle" - item_state = "atoxinbottle" - amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(5,10,15,25,30) - flags = FPRINT | OPENCONTAINER - volume = 30 - starting_materials = list(MAT_GLASS = 1000) - w_type = RECYK_GLASS - melt_temperature = MELTPOINT_GLASS - origin_tech = "materials=1" - -/obj/item/weapon/reagent_containers/glass/bottle/New(loc,altvol=30) - volume = altvol - ..(loc) - -//JUST -/obj/item/weapon/reagent_containers/glass/bottle/mop_act(obj/item/weapon/mop/M, mob/user) - if(..()) - if(src.reagents.total_volume >= 1) - if(M.reagents.total_volume >= 1) + +//Not to be confused with /obj/item/weapon/reagent_containers/food/drinks/bottle + +/obj/item/weapon/reagent_containers/glass/bottle + name = "bottle" + desc = "A small bottle." + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle" + item_state = "atoxinbottle" + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(5,10,15,25,30) + flags = FPRINT | OPENCONTAINER + volume = 30 + starting_materials = list(MAT_GLASS = 1000) + w_type = RECYK_GLASS + melt_temperature = MELTPOINT_GLASS + origin_tech = "materials=1" + +/obj/item/weapon/reagent_containers/glass/bottle/New(loc,altvol=30) + volume = altvol + ..(loc) + +//JUST +/obj/item/weapon/reagent_containers/glass/bottle/mop_act(obj/item/weapon/mop/M, mob/user) + if(..()) + if(src.reagents.total_volume >= 1) + if(M.reagents.total_volume >= 1) to_chat(user, "You dip \the [M]'s tip into \the [src] but don't soak anything up.") - return 1 - else - src.reagents.trans_to(M, 1) + return 1 + else + src.reagents.trans_to(M, 1) to_chat(user, "You barely manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) - else + playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + else to_chat(user, "Nothing left to wet [M] with!") - return 1 - -/* - * Hard to have colored bottles work with dynamic reagent filling -/obj/item/weapon/reagent_containers/glass/bottle/New() - ..() - if(!icon_state) - icon_state = "bottle[rand(1,20)]" -*/ - -/obj/item/weapon/reagent_containers/glass/bottle/on_reagent_change() - update_icon() - -/obj/item/weapon/reagent_containers/glass/bottle/pickup(mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/glass/bottle/dropped(mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/glass/bottle/attack_hand() - ..() - update_icon() - -/obj/item/weapon/reagent_containers/glass/bottle/update_icon() - - overlays.len = 0 - - if(reagents.total_volume) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]5") - - var/percent = round((reagents.total_volume / volume) * 100) - switch(percent) //Percentages are pretty fucked so here comes the decimal rollercoaster with halfway rounding - if(0 to 24) filling.icon_state = "[icon_state]5" - if(25 to 41) filling.icon_state = "[icon_state]10" - if(42 to 58) filling.icon_state = "[icon_state]15" - if(59 to 74) filling.icon_state = "[icon_state]20" - if(75 to 91) filling.icon_state = "[icon_state]25" - if(92 to INFINITY) filling.icon_state = "[icon_state]30" - - filling.icon += mix_color_from_reagents(reagents.reagent_list) - overlays += filling - - if(!is_open_container()) - var/image/lid = image(icon, src, "lid_[initial(icon_state)]") - overlays += lid - -/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline - name = "inaprovaline bottle" - desc = "A small bottle. Contains inaprovaline - used to stabilize patients." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle16" - - New() - ..() - reagents.add_reagent("inaprovaline", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/toxin - name = "toxin bottle" - desc = "A small bottle of toxins. Do not drink, it is poisonous." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle12" - - New() - ..() - reagents.add_reagent("toxin", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/charcoal - name = "activated charcoal bottle" - desc = "A small bottle of activated charcoal. Used for treatment of overdoses." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle-charcoal" - - New() - ..() - reagents.add_reagent("charcoal", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/cyanide - name = "cyanide bottle" - desc = "A small bottle of cyanide. Bitter almonds?" - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle12" - - New() - ..() - reagents.add_reagent("cyanide", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/stoxin - name = "sleep-toxin bottle" - desc = "A small bottle of sleep toxins. Just the fumes make you sleepy." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle20" - - New() - ..() - reagents.add_reagent("stoxin", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate - name = "Chloral Hydrate Bottle" - desc = "A small bottle of Chloral Hydrate. Mickey's Favorite!" - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle20" - - New() - ..() - reagents.add_reagent("chloralhydrate", 15) //Intentionally low since it is so strong. Still enough to knock someone out. - -/obj/item/weapon/reagent_containers/glass/bottle/antitoxin - name = "anti-toxin bottle" - desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle17" - - New() - ..() - reagents.add_reagent("anti_toxin", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/mutagen - name = "unstable mutagen bottle" - desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle20" - - New() - ..() - reagents.add_reagent("mutagen", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/ammonia - name = "ammonia bottle" - desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle20" - - New() - ..() - reagents.add_reagent("ammonia", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/diethylamine - name = "diethylamine bottle" - desc = "A small bottle." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle17" - - New() - ..() - reagents.add_reagent("diethylamine", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/flu_virion - name = "Flu virion culture bottle" - desc = "A small bottle. Contains H13N1 flu virion culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/advance/flu(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/epiglottis_virion - name = "Epiglottis virion culture bottle" - desc = "A small bottle. Contains Epiglottis virion culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/advance/voice_change(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/liver_enhance_virion - name = "Liver enhancement virion culture bottle" - desc = "A small bottle. Contains liver enhancement virion culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/advance/heal(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/hullucigen_virion - name = "Hullucigen virion culture bottle" - desc = "A small bottle. Contains hullucigen virion culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/advance/hullucigen(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat - name = "Pierrot's Throat culture bottle" - desc = "A small bottle. Contains H0NI<42 virion culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/pierrot_throat(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/cold - name = "Rhinovirus culture bottle" - desc = "A small bottle. Contains XY-rhinovirus culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/advance/F = new /datum/disease/advance/cold(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/random - name = "Random culture bottle" - desc = "A small bottle. Contains a random disease." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/advance/F = new(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/retrovirus - name = "Retrovirus culture bottle" - desc = "A small bottle. Contains a retrovirus culture in a synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/dna_retrovirus(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/gbs - name = "GBS culture bottle" - desc = "A small bottle. Contains Gravitokinetic Bipotential SADS+ culture in synthblood medium."//Or simply - General BullShit - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - amount_per_transfer_from_this = 5 - - New() - var/datum/reagents/R = new/datum/reagents(20) - reagents = R - R.my_atom = src - var/datum/disease/F = new /datum/disease/gbs - var/list/data = list("virus"= F) - R.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/fake_gbs - name = "GBS culture bottle" - desc = "A small bottle. Contains Gravitokinetic Bipotential SADS- culture in synthblood medium."//Or simply - General BullShit - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/fake_gbs(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/* -/obj/item/weapon/reagent_containers/glass/bottle/rhumba_beat - name = "Rhumba Beat culture bottle" - desc = "A small bottle. Contains The Rhumba Beat culture in synthblood medium."//Or simply - General BullShit - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - amount_per_transfer_from_this = 5 - - New() - var/datum/reagents/R = new/datum/reagents(20) - reagents = R - R.my_atom = src - var/datum/disease/F = new /datum/disease/rhumba_beat - var/list/data = list("virus"= F) - R.add_reagent("blood", 20, data) -*/ - -/obj/item/weapon/reagent_containers/glass/bottle/brainrot - name = "Brainrot culture bottle" - desc = "A small bottle. Contains Cryptococcus Cosmosis culture in synthblood medium." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/brainrot(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/magnitis - name = "Magnitis culture bottle" - desc = "A small bottle. Contains a small dosage of Fukkos Miracos." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/magnitis(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/wizarditis - name = "Wizarditis culture bottle" - desc = "A small bottle. Contains a sample of Rincewindus Vulgaris." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - var/datum/disease/F = new /datum/disease/wizarditis(0) - var/list/data = list("viruses"= list(F)) - reagents.add_reagent("blood", 20, data) - -/obj/item/weapon/reagent_containers/glass/bottle/pacid - name = "Polytrinic Acid Bottle" - desc = "A small bottle. Contains a small amount of Polytrinic Acid" - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle17" - New() - ..() - reagents.add_reagent("pacid", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/adminordrazine - name = "Adminordrazine Bottle" - desc = "A small bottle. Contains the liquid essence of the gods." - icon = 'icons/obj/drinks.dmi' - //icon_state = "holyflask" - New() - ..() - reagents.add_reagent("adminordrazine", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/capsaicin - name = "Capsaicin Bottle" - desc = "A small bottle. Contains hot sauce." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle3" - New() - ..() - reagents.add_reagent("capsaicin", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/frostoil - name = "Frost Oil Bottle" - desc = "A small bottle. Contains cold sauce." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle17" - New() - ..() - reagents.add_reagent("frostoil", 30) - -/obj/item/weapon/reagent_containers/glass/bottle/antisocial - //No special name or description - - New() - ..() - reagents.add_reagent("bicarodyne", 30) + return 1 + +/* + * Hard to have colored bottles work with dynamic reagent filling +/obj/item/weapon/reagent_containers/glass/bottle/New() + ..() + if(!icon_state) + icon_state = "bottle[rand(1,20)]" +*/ + +/obj/item/weapon/reagent_containers/glass/bottle/on_reagent_change() + update_icon() + +/obj/item/weapon/reagent_containers/glass/bottle/pickup(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/bottle/dropped(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/bottle/attack_hand() + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/bottle/update_icon() + + overlays.len = 0 + + if(reagents.total_volume) + var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]5") + + var/percent = round((reagents.total_volume / volume) * 100) + switch(percent) //Percentages are pretty fucked so here comes the decimal rollercoaster with halfway rounding + if(0 to 24) filling.icon_state = "[icon_state]5" + if(25 to 41) filling.icon_state = "[icon_state]10" + if(42 to 58) filling.icon_state = "[icon_state]15" + if(59 to 74) filling.icon_state = "[icon_state]20" + if(75 to 91) filling.icon_state = "[icon_state]25" + if(92 to INFINITY) filling.icon_state = "[icon_state]30" + + filling.icon += mix_color_from_reagents(reagents.reagent_list) + overlays += filling + + if(!is_open_container()) + var/image/lid = image(icon, src, "lid_[initial(icon_state)]") + overlays += lid + +/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline + name = "inaprovaline bottle" + desc = "A small bottle. Contains inaprovaline - used to stabilize patients." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle16" + + New() + ..() + reagents.add_reagent("inaprovaline", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/toxin + name = "toxin bottle" + desc = "A small bottle of toxins. Do not drink, it is poisonous." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle12" + + New() + ..() + reagents.add_reagent("toxin", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/charcoal + name = "activated charcoal bottle" + desc = "A small bottle of activated charcoal. Used for treatment of overdoses." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle-charcoal" + + New() + ..() + reagents.add_reagent("charcoal", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/cyanide + name = "cyanide bottle" + desc = "A small bottle of cyanide. Bitter almonds?" + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle12" + + New() + ..() + reagents.add_reagent("cyanide", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/stoxin + name = "sleep-toxin bottle" + desc = "A small bottle of sleep toxins. Just the fumes make you sleepy." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle20" + + New() + ..() + reagents.add_reagent("stoxin", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate + name = "Chloral Hydrate Bottle" + desc = "A small bottle of Chloral Hydrate. Mickey's Favorite!" + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle20" + + New() + ..() + reagents.add_reagent("chloralhydrate", 15) //Intentionally low since it is so strong. Still enough to knock someone out. + +/obj/item/weapon/reagent_containers/glass/bottle/antitoxin + name = "anti-toxin bottle" + desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle17" + + New() + ..() + reagents.add_reagent("anti_toxin", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/mutagen + name = "unstable mutagen bottle" + desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle20" + + New() + ..() + reagents.add_reagent("mutagen", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/ammonia + name = "ammonia bottle" + desc = "A small bottle." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle20" + + New() + ..() + reagents.add_reagent("ammonia", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/diethylamine + name = "diethylamine bottle" + desc = "A small bottle." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle17" + + New() + ..() + reagents.add_reagent("diethylamine", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/flu_virion + name = "Flu virion culture bottle" + desc = "A small bottle. Contains H13N1 flu virion culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/advance/flu(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/epiglottis_virion + name = "Epiglottis virion culture bottle" + desc = "A small bottle. Contains Epiglottis virion culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/advance/voice_change(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/liver_enhance_virion + name = "Liver enhancement virion culture bottle" + desc = "A small bottle. Contains liver enhancement virion culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/advance/heal(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/hullucigen_virion + name = "Hullucigen virion culture bottle" + desc = "A small bottle. Contains hullucigen virion culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/advance/hullucigen(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat + name = "Pierrot's Throat culture bottle" + desc = "A small bottle. Contains H0NI<42 virion culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/pierrot_throat(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/cold + name = "Rhinovirus culture bottle" + desc = "A small bottle. Contains XY-rhinovirus culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/advance/F = new /datum/disease/advance/cold(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/random + name = "Random culture bottle" + desc = "A small bottle. Contains a random disease." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/advance/F = new(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/retrovirus + name = "Retrovirus culture bottle" + desc = "A small bottle. Contains a retrovirus culture in a synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/dna_retrovirus(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/gbs + name = "GBS culture bottle" + desc = "A small bottle. Contains Gravitokinetic Bipotential SADS+ culture in synthblood medium."//Or simply - General BullShit + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + amount_per_transfer_from_this = 5 + + New() + var/datum/reagents/R = new/datum/reagents(20) + reagents = R + R.my_atom = src + var/datum/disease/F = new /datum/disease/gbs + var/list/data = list("virus"= F) + R.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/fake_gbs + name = "GBS culture bottle" + desc = "A small bottle. Contains Gravitokinetic Bipotential SADS- culture in synthblood medium."//Or simply - General BullShit + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/fake_gbs(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/* +/obj/item/weapon/reagent_containers/glass/bottle/rhumba_beat + name = "Rhumba Beat culture bottle" + desc = "A small bottle. Contains The Rhumba Beat culture in synthblood medium."//Or simply - General BullShit + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + amount_per_transfer_from_this = 5 + + New() + var/datum/reagents/R = new/datum/reagents(20) + reagents = R + R.my_atom = src + var/datum/disease/F = new /datum/disease/rhumba_beat + var/list/data = list("virus"= F) + R.add_reagent("blood", 20, data) +*/ + +/obj/item/weapon/reagent_containers/glass/bottle/brainrot + name = "Brainrot culture bottle" + desc = "A small bottle. Contains Cryptococcus Cosmosis culture in synthblood medium." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/brainrot(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/magnitis + name = "Magnitis culture bottle" + desc = "A small bottle. Contains a small dosage of Fukkos Miracos." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/magnitis(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/wizarditis + name = "Wizarditis culture bottle" + desc = "A small bottle. Contains a sample of Rincewindus Vulgaris." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + var/datum/disease/F = new /datum/disease/wizarditis(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent("blood", 20, data) + +/obj/item/weapon/reagent_containers/glass/bottle/pacid + name = "Polytrinic Acid Bottle" + desc = "A small bottle. Contains a small amount of Polytrinic Acid" + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle17" + New() + ..() + reagents.add_reagent("pacid", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/adminordrazine + name = "Adminordrazine Bottle" + desc = "A small bottle. Contains the liquid essence of the gods." + icon = 'icons/obj/drinks.dmi' + //icon_state = "holyflask" + New() + ..() + reagents.add_reagent("adminordrazine", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/capsaicin + name = "Capsaicin Bottle" + desc = "A small bottle. Contains hot sauce." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle3" + New() + ..() + reagents.add_reagent("capsaicin", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/frostoil + name = "Frost Oil Bottle" + desc = "A small bottle. Contains cold sauce." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle17" + New() + ..() + reagents.add_reagent("frostoil", 30) + +/obj/item/weapon/reagent_containers/glass/bottle/antisocial + //No special name or description + + New() + ..() + reagents.add_reagent("bicarodyne", 30) diff --git a/code/modules/reagents/reagent_containers/glass/bottle/robot.dm b/code/modules/reagents/reagent_containers/glass/bottle/robot.dm index abe3a7fc102..c4e0716a678 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle/robot.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle/robot.dm @@ -1,33 +1,33 @@ - -/obj/item/weapon/reagent_containers/glass/bottle/robot - amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(5,10,15,25,30,50,100) - flags = FPRINT | OPENCONTAINER - volume = 60 - var/reagent = "" - - -/obj/item/weapon/reagent_containers/glass/bottle/robot/inaprovaline - name = "internal inaprovaline bottle" - desc = "A small bottle. Contains inaprovaline - used to stabilize patients." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle16" - reagent = "inaprovaline" - - New() - ..() - reagents.add_reagent("inaprovaline", 60) - return - - -/obj/item/weapon/reagent_containers/glass/bottle/robot/antitoxin - name = "internal anti-toxin bottle" - desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug." - icon = 'icons/obj/chemical.dmi' - //icon_state = "bottle17" - reagent = "anti_toxin" - - New() - ..() - reagents.add_reagent("anti_toxin", 60) + +/obj/item/weapon/reagent_containers/glass/bottle/robot + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(5,10,15,25,30,50,100) + flags = FPRINT | OPENCONTAINER + volume = 60 + var/reagent = "" + + +/obj/item/weapon/reagent_containers/glass/bottle/robot/inaprovaline + name = "internal inaprovaline bottle" + desc = "A small bottle. Contains inaprovaline - used to stabilize patients." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle16" + reagent = "inaprovaline" + + New() + ..() + reagents.add_reagent("inaprovaline", 60) + return + + +/obj/item/weapon/reagent_containers/glass/bottle/robot/antitoxin + name = "internal anti-toxin bottle" + desc = "A small bottle of Anti-toxins. Counters poisons, and repairs damage, a wonder drug." + icon = 'icons/obj/chemical.dmi' + //icon_state = "bottle17" + reagent = "anti_toxin" + + New() + ..() + reagents.add_reagent("anti_toxin", 60) return \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index f8451516c12..812f43195e6 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -1,109 +1,109 @@ -//////////////////////////////////////////////////////////////////////////////// -/// HYPOSPRAY -//////////////////////////////////////////////////////////////////////////////// - -/obj/item/weapon/reagent_containers/hypospray - name = "hypospray" - desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients." - icon = 'icons/obj/syringe.dmi' - item_state = "hypo" - icon_state = "hypo" - amount_per_transfer_from_this = 5 - volume = 30 - possible_transfer_amounts = null - flags = FPRINT | OPENCONTAINER - slot_flags = SLOT_BELT - -/obj/item/weapon/reagent_containers/hypospray/attack_paw(mob/user as mob) - return src.attack_hand(user) - - -/obj/item/weapon/reagent_containers/hypospray/New() //comment this to make hypos start off empty - ..() - reagents.add_reagent("doctorsdelight", 30) - return - -/obj/item/weapon/reagent_containers/hypospray/creatine/New() // TESTING! - ..() - reagents.add_reagent("creatine", 30) - return - -/obj/item/weapon/reagent_containers/hypospray/attack(mob/M as mob, mob/user as mob) - if(!reagents.total_volume) +//////////////////////////////////////////////////////////////////////////////// +/// HYPOSPRAY +//////////////////////////////////////////////////////////////////////////////// + +/obj/item/weapon/reagent_containers/hypospray + name = "hypospray" + desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients." + icon = 'icons/obj/syringe.dmi' + item_state = "hypo" + icon_state = "hypo" + amount_per_transfer_from_this = 5 + volume = 30 + possible_transfer_amounts = null + flags = FPRINT | OPENCONTAINER + slot_flags = SLOT_BELT + +/obj/item/weapon/reagent_containers/hypospray/attack_paw(mob/user as mob) + return src.attack_hand(user) + + +/obj/item/weapon/reagent_containers/hypospray/New() //comment this to make hypos start off empty + ..() + reagents.add_reagent("doctorsdelight", 30) + return + +/obj/item/weapon/reagent_containers/hypospray/creatine/New() // TESTING! + ..() + reagents.add_reagent("creatine", 30) + return + +/obj/item/weapon/reagent_containers/hypospray/attack(mob/M as mob, mob/user as mob) + if(!reagents.total_volume) to_chat(user, "[src] is empty.") - return - if (!( istype(M, /mob) )) - return - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species && (H.species.chem_flags & NO_INJECT)) + return + if (!( istype(M, /mob) )) + return + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species && (H.species.chem_flags & NO_INJECT)) to_chat(user, "\The [src]'s needle fails to pierce [H]") - return - - var/inject_message = "You inject [M] with [src]." - if(M == user) - inject_message = "You inject yourself with [src]." - else if((M_CLUMSY in user.mutations) && prob(50)) - inject_message = "Oops! You inject yourself with [src] by accident." - M = user - - if (reagents.total_volume) + return + + var/inject_message = "You inject [M] with [src]." + if(M == user) + inject_message = "You inject yourself with [src]." + else if((M_CLUMSY in user.mutations) && prob(50)) + inject_message = "Oops! You inject yourself with [src] by accident." + M = user + + if (reagents.total_volume) to_chat(user, inject_message) to_chat(M, "You feel a tiny prick!") - playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) - - src.reagents.reaction(M, INGEST) - if(M.reagents) - - var/list/injected = list() - for(var/datum/reagent/R in src.reagents.reagent_list) - injected += R.name - var/contained = english_list(injected) - M.attack_log += text("\[[time_stamp()]\] Has been injected with [src.name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to inject [M.name] ([M.key]). Reagents: [contained]") - msg_admin_attack("[user.name] ([user.ckey]) injected [M.name] ([M.key]) with [src.name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - log_attack("[user.name] ([user.ckey]) injected [M.name] ([M.ckey]) with [src.name] Reagents: [contained]" ) - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - var/trans = reagents.trans_to(M, amount_per_transfer_from_this) + playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) + + src.reagents.reaction(M, INGEST) + if(M.reagents) + + var/list/injected = list() + for(var/datum/reagent/R in src.reagents.reagent_list) + injected += R.name + var/contained = english_list(injected) + M.attack_log += text("\[[time_stamp()]\] Has been injected with [src.name] by [user.name] ([user.ckey]). Reagents: [contained]") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to inject [M.name] ([M.key]). Reagents: [contained]") + msg_admin_attack("[user.name] ([user.ckey]) injected [M.name] ([M.key]) with [src.name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") + log_attack("[user.name] ([user.ckey]) injected [M.name] ([M.ckey]) with [src.name] Reagents: [contained]" ) + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + var/trans = reagents.trans_to(M, amount_per_transfer_from_this) to_chat(user, "[trans] units injected. [reagents.total_volume] units remaining in [src].") - - return - -/obj/item/weapon/reagent_containers/hypospray/autoinjector - name = "autoinjector" - desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel." - icon_state = "autoinjector1" - item_state = "autoinjector" - amount_per_transfer_from_this = 5 - volume = 5 - -/obj/item/weapon/reagent_containers/hypospray/autoinjector/New() - ..() - reagents.remove_reagent("tricordrazine", 30) - reagents.add_reagent("inaprovaline", 5) - update_icon() - return - -/obj/item/weapon/reagent_containers/hypospray/autoinjector/attack(mob/M as mob, mob/user as mob) - ..() - if(reagents.total_volume <= 0) //Prevents autoinjectors to be refilled. - flags &= ~OPENCONTAINER - update_icon() - return - -/obj/item/weapon/reagent_containers/hypospray/autoinjector/update_icon() - if(reagents.total_volume > 0) - icon_state = "autoinjector1" - else - icon_state = "autoinjector0" - -/obj/item/weapon/reagent_containers/hypospray/autoinjector/examine(mob/user) - ..() - if(reagents && reagents.reagent_list.len) + + return + +/obj/item/weapon/reagent_containers/hypospray/autoinjector + name = "autoinjector" + desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel." + icon_state = "autoinjector1" + item_state = "autoinjector" + amount_per_transfer_from_this = 5 + volume = 5 + +/obj/item/weapon/reagent_containers/hypospray/autoinjector/New() + ..() + reagents.remove_reagent("tricordrazine", 30) + reagents.add_reagent("inaprovaline", 5) + update_icon() + return + +/obj/item/weapon/reagent_containers/hypospray/autoinjector/attack(mob/M as mob, mob/user as mob) + ..() + if(reagents.total_volume <= 0) //Prevents autoinjectors to be refilled. + flags &= ~OPENCONTAINER + update_icon() + return + +/obj/item/weapon/reagent_containers/hypospray/autoinjector/update_icon() + if(reagents.total_volume > 0) + icon_state = "autoinjector1" + else + icon_state = "autoinjector0" + +/obj/item/weapon/reagent_containers/hypospray/autoinjector/examine(mob/user) + ..() + if(reagents && reagents.reagent_list.len) to_chat(user, "It ready for injection.") - else + else to_chat(user, "The autoinjector has been spent.") diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index fbd936b7e67..89dc8eef222 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -1,284 +1,284 @@ -//////////////////////////////////////////////////////////////////////////////// -/// Pills. -//////////////////////////////////////////////////////////////////////////////// -/obj/item/weapon/reagent_containers/pill - name = "pill" - desc = "A small capsule of dried chemicals, used to administer medicine and poison alike in one easy serving." - icon = 'icons/obj/chemical.dmi' - icon_state = null - item_state = "pill" - possible_transfer_amounts = null - volume = 50 - starting_materials = null -// starting_materials = list(MAT_IRON = 5) //What? - w_type = RECYK_METAL - - New() - ..() - if(!icon_state) - icon_state = "pill[rand(1,20)]" - -/obj/item/weapon/reagent_containers/pill/attack_self(mob/user as mob) - - return attack(user, user) //Dealt with in attack code - -/obj/item/weapon/reagent_containers/pill/attack(mob/M as mob, mob/user as mob, def_zone) - // Feeding others needs time to succeed - if (user != M && (ishuman(M) || ismonkey(M))) - user.visible_message("[user] attempts to force [M] to swallow \the [src].", "You attempt to force [M] to swallow \the [src].") - - if (!do_mob(user, M)) - return 1 - - user.visible_message("[user] forces [M] to swallow \the [src].", "You force [M] to swallow \the [src].") - add_attacklogs(user, M, "fed", object = src, addition = "Reagents: [english_list(list(reagentlist(src)))]", admin_warn = TRUE) - else if (user == M) - user.visible_message("[user] swallows \the [src].", "You swallow \the [src].") - else - return 0 - - user.drop_from_inventory(src) // Update icon - if (ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species.chem_flags & NO_EAT) - src.forceMove(get_turf(H)) - H.visible_message("\The [src] falls through and onto the ground.", "You hear \the [src] plinking around for a second before it hits the ground below you.") - return 0 - injest(M) - return 1 - -// Handles pill dissolving in containers -/obj/item/weapon/reagent_containers/pill/afterattack(var/obj/item/weapon/reagent_containers/target, var/mob/user, var/adjacency_flag, var/click_params) - if (!adjacency_flag || !istype(target) || !target.is_open_container()) - return - - var/target_was_empty = (target.reagents.total_volume == 0) - var/list/bad_reagents = reagents.get_bad_reagent_names() - var/tx_amount = reagents.trans_to(target, reagents.total_volume) - - // Log transfers of 'bad 'things' (/vg/) - if (tx_amount > 0 && target.log_reagents && bad_reagents && bad_reagents.len > 0) - log_reagents(user, src, target, tx_amount, bad_reagents) - - // Show messages - if (tx_amount > 0) - user.visible_message("[user] puts something into \the [target], filling it.") - if (src.is_empty()) +//////////////////////////////////////////////////////////////////////////////// +/// Pills. +//////////////////////////////////////////////////////////////////////////////// +/obj/item/weapon/reagent_containers/pill + name = "pill" + desc = "A small capsule of dried chemicals, used to administer medicine and poison alike in one easy serving." + icon = 'icons/obj/chemical.dmi' + icon_state = null + item_state = "pill" + possible_transfer_amounts = null + volume = 50 + starting_materials = null +// starting_materials = list(MAT_IRON = 5) //What? + w_type = RECYK_METAL + + New() + ..() + if(!icon_state) + icon_state = "pill[rand(1,20)]" + +/obj/item/weapon/reagent_containers/pill/attack_self(mob/user as mob) + + return attack(user, user) //Dealt with in attack code + +/obj/item/weapon/reagent_containers/pill/attack(mob/M as mob, mob/user as mob, def_zone) + // Feeding others needs time to succeed + if (user != M && (ishuman(M) || ismonkey(M))) + user.visible_message("[user] attempts to force [M] to swallow \the [src].", "You attempt to force [M] to swallow \the [src].") + + if (!do_mob(user, M)) + return 1 + + user.visible_message("[user] forces [M] to swallow \the [src].", "You force [M] to swallow \the [src].") + add_attacklogs(user, M, "fed", object = src, addition = "Reagents: [english_list(list(reagentlist(src)))]", admin_warn = TRUE) + else if (user == M) + user.visible_message("[user] swallows \the [src].", "You swallow \the [src].") + else + return 0 + + user.drop_from_inventory(src) // Update icon + if (ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species.chem_flags & NO_EAT) + src.forceMove(get_turf(H)) + H.visible_message("\The [src] falls through and onto the ground.", "You hear \the [src] plinking around for a second before it hits the ground below you.") + return 0 + injest(M) + return 1 + +// Handles pill dissolving in containers +/obj/item/weapon/reagent_containers/pill/afterattack(var/obj/item/weapon/reagent_containers/target, var/mob/user, var/adjacency_flag, var/click_params) + if (!adjacency_flag || !istype(target) || !target.is_open_container()) + return + + var/target_was_empty = (target.reagents.total_volume == 0) + var/list/bad_reagents = reagents.get_bad_reagent_names() + var/tx_amount = reagents.trans_to(target, reagents.total_volume) + + // Log transfers of 'bad 'things' (/vg/) + if (tx_amount > 0 && target.log_reagents && bad_reagents && bad_reagents.len > 0) + log_reagents(user, src, target, tx_amount, bad_reagents) + + // Show messages + if (tx_amount > 0) + user.visible_message("[user] puts something into \the [target], filling it.") + if (src.is_empty()) to_chat(user, "You [target_was_empty ? "crush" : "dissolve"] the pill into \the [target].") - qdel(src) - else + qdel(src) + else to_chat(user, "You [target_was_empty ? "crush partially" : "partially dissolve"] the pill into \the [target], filling it.") - else + else to_chat(user, "\The [target] is full!") - -//OOP, HO! -/obj/item/weapon/reagent_containers/pill/proc/injest(mob/M as mob) - if(!reagents) return - if(!M) return - if (!src.is_empty()) - reagents.reaction(M, INGEST) - reagents.trans_to(M, reagents.total_volume) - qdel(src) - -//////////////////////////////////////////////////////////////////////////////// -/// Pills. END -//////////////////////////////////////////////////////////////////////////////// - -//Pills -/obj/item/weapon/reagent_containers/pill/creatine - name = "Creatine Suicide Pill (50 units)" - desc = "WILL ALSO KILL YOU VIOLENTLY." - icon_state = "pill5" - - New() - ..() - reagents.add_reagent("creatine", 50) - -/obj/item/weapon/reagent_containers/pill/antitox - name = "Anti-toxins pill" - desc = "Neutralizes many common toxins." - icon_state = "pill17" - - New() - ..() - reagents.add_reagent("anti_toxin", 25) - -/obj/item/weapon/reagent_containers/pill/tox - name = "Toxins pill" - desc = "Highly toxic." - icon_state = "pill5" - - New() - ..() - reagents.add_reagent("toxin", 50) - -/obj/item/weapon/reagent_containers/pill/cyanide - name = "Cyanide pill" - desc = "Don't swallow this." - icon_state = "pill5" - - New() - ..() - reagents.add_reagent("cyanide", 50) - -/obj/item/weapon/reagent_containers/pill/adminordrazine - name = "Adminordrazine pill" - desc = "It's magic. We don't have to explain it." - icon_state = "pill16" - - New() - ..() - reagents.add_reagent("adminordrazine", 50) - -/obj/item/weapon/reagent_containers/pill/stox - name = "Sleeping pill" - desc = "Commonly used to treat insomnia." - icon_state = "pill8" - - New() - ..() - reagents.add_reagent("stoxin", 30) - -/obj/item/weapon/reagent_containers/pill/kelotane - name = "Kelotane pill" - desc = "Used to treat burns." - icon_state = "pill11" - - New() - ..() - reagents.add_reagent("kelotane", 30) - -/obj/item/weapon/reagent_containers/pill/tramadol - name = "Tramadol pill" - desc = "A simple painkiller." - icon_state = "pill8" - - New() - ..() - reagents.add_reagent("tramadol", 15) - - -/obj/item/weapon/reagent_containers/pill/methylphenidate - name = "Methylphenidate pill" - desc = "Improves the ability to concentrate." - icon_state = "pill8" - - New() - ..() - reagents.add_reagent("methylphenidate", 15) - -/obj/item/weapon/reagent_containers/pill/citalopram - name = "Citalopram pill" - desc = "Mild anti-depressant." - icon_state = "pill8" - - New() - ..() - reagents.add_reagent("citalopram", 15) - - -/obj/item/weapon/reagent_containers/pill/inaprovaline - name = "Inaprovaline pill" - desc = "Used to stabilize patients." - icon_state = "pill20" - - New() - ..() - reagents.add_reagent("inaprovaline", 30) - -/obj/item/weapon/reagent_containers/pill/dexalin - name = "Dexalin pill" - desc = "Used to treat oxygen deprivation." - icon_state = "pill16" - - New() - ..() - reagents.add_reagent("dexalin", 30) - -/obj/item/weapon/reagent_containers/pill/bicaridine - name = "Bicaridine pill" - desc = "Used to treat physical injuries." - icon_state = "pill18" - - New() - ..() - reagents.add_reagent("bicaridine", 30) - -/obj/item/weapon/reagent_containers/pill/happy - name = "Happy pill" - desc = "Happy happy joy joy!" - icon_state = "pill18" - - New() - ..() - reagents.add_reagent("space_drugs", 15) - reagents.add_reagent("sugar", 15) - -/obj/item/weapon/reagent_containers/pill/zoom - name = "Zoom pill" - desc = "Zoooom!" - icon_state = "pill18" - - New() - ..() - reagents.add_reagent("impedrezene", 10) - reagents.add_reagent("synaptizine", 1) - reagents.add_reagent("hyperzine", 10) - -/obj/item/weapon/reagent_containers/pill/hyperzine - name = "Hyperzine pill" - desc = "Gotta go fast!" - - icon_state = "pill18" - New() - ..() - reagents.add_reagent("hyperzine", 10) - -/obj/item/weapon/storage/pill_bottle/time_release - name = "controlled release pill bottle" - desc = "A bottle containing special pills which can be calibrated for delayed release with sugar." - -/obj/item/weapon/storage/pill_bottle/time_release/New() - ..() - for(var/i=1 to 7) - new /obj/item/weapon/reagent_containers/pill/time_release(src) - -/obj/item/weapon/reagent_containers/pill/time_release - name = "time release pill" - desc = "A pill which will not be metabolized until all of the sugar inside metabolizes. By extension, the chemicals inside do not react with one another until entering the body. Unlike other pills, it is specially designed to be compatible with droppers and syringes." - icon_state = "pill18" - flags = FPRINT | NOREACT - -/obj/item/weapon/reagent_containers/pill/time_release/injest(mob/M as mob) - if(!reagents) return - if(!M) return - var/timer = round(reagents.get_reagent_amount("sugar"),1) - forceMove(M) - spawn(timer*30) - reagents.del_reagent("sugar") - reagents.reaction(M, INGEST) - reagents.trans_to(M, reagents.total_volume) - qdel(src) - -/obj/item/weapon/storage/pill_bottle/random - name = "trail mix" - desc = "Just what the assistant ordered." - -/obj/item/weapon/storage/pill_bottle/random/New() - ..() - for(var/i=1 to 14) - new /obj/item/weapon/reagent_containers/pill/random(src) - -/obj/item/weapon/reagent_containers/pill/random - name = "unknown pill" - desc = "Dare you enter my chemical realm?" - -/obj/item/weapon/reagent_containers/pill/random/New() - ..() - var/chemical = pick("hyperzine", "oxycodone", "doctorsdelight", "lexorin", "leporazine", "mutagen", "ryetalyn", "pacid", "cornoil", "tonio", "space_drugs","zombiepowder") - reagents.add_reagent(chemical, 10) - /* Possible choices: - Good: Hyperzine, Oxycodone, Doctor's Delight, Leporazine - Neutral: Corn Oil, Ryetalyn, Tonio, Space Drugs - Bad: Mutagen, Polytrinic Acid, Lexorin, Zombie Powder - */ + +//OOP, HO! +/obj/item/weapon/reagent_containers/pill/proc/injest(mob/M as mob) + if(!reagents) return + if(!M) return + if (!src.is_empty()) + reagents.reaction(M, INGEST) + reagents.trans_to(M, reagents.total_volume) + qdel(src) + +//////////////////////////////////////////////////////////////////////////////// +/// Pills. END +//////////////////////////////////////////////////////////////////////////////// + +//Pills +/obj/item/weapon/reagent_containers/pill/creatine + name = "Creatine Suicide Pill (50 units)" + desc = "WILL ALSO KILL YOU VIOLENTLY." + icon_state = "pill5" + + New() + ..() + reagents.add_reagent("creatine", 50) + +/obj/item/weapon/reagent_containers/pill/antitox + name = "Anti-toxins pill" + desc = "Neutralizes many common toxins." + icon_state = "pill17" + + New() + ..() + reagents.add_reagent("anti_toxin", 25) + +/obj/item/weapon/reagent_containers/pill/tox + name = "Toxins pill" + desc = "Highly toxic." + icon_state = "pill5" + + New() + ..() + reagents.add_reagent("toxin", 50) + +/obj/item/weapon/reagent_containers/pill/cyanide + name = "Cyanide pill" + desc = "Don't swallow this." + icon_state = "pill5" + + New() + ..() + reagents.add_reagent("cyanide", 50) + +/obj/item/weapon/reagent_containers/pill/adminordrazine + name = "Adminordrazine pill" + desc = "It's magic. We don't have to explain it." + icon_state = "pill16" + + New() + ..() + reagents.add_reagent("adminordrazine", 50) + +/obj/item/weapon/reagent_containers/pill/stox + name = "Sleeping pill" + desc = "Commonly used to treat insomnia." + icon_state = "pill8" + + New() + ..() + reagents.add_reagent("stoxin", 30) + +/obj/item/weapon/reagent_containers/pill/kelotane + name = "Kelotane pill" + desc = "Used to treat burns." + icon_state = "pill11" + + New() + ..() + reagents.add_reagent("kelotane", 30) + +/obj/item/weapon/reagent_containers/pill/tramadol + name = "Tramadol pill" + desc = "A simple painkiller." + icon_state = "pill8" + + New() + ..() + reagents.add_reagent("tramadol", 15) + + +/obj/item/weapon/reagent_containers/pill/methylphenidate + name = "Methylphenidate pill" + desc = "Improves the ability to concentrate." + icon_state = "pill8" + + New() + ..() + reagents.add_reagent("methylphenidate", 15) + +/obj/item/weapon/reagent_containers/pill/citalopram + name = "Citalopram pill" + desc = "Mild anti-depressant." + icon_state = "pill8" + + New() + ..() + reagents.add_reagent("citalopram", 15) + + +/obj/item/weapon/reagent_containers/pill/inaprovaline + name = "Inaprovaline pill" + desc = "Used to stabilize patients." + icon_state = "pill20" + + New() + ..() + reagents.add_reagent("inaprovaline", 30) + +/obj/item/weapon/reagent_containers/pill/dexalin + name = "Dexalin pill" + desc = "Used to treat oxygen deprivation." + icon_state = "pill16" + + New() + ..() + reagents.add_reagent("dexalin", 30) + +/obj/item/weapon/reagent_containers/pill/bicaridine + name = "Bicaridine pill" + desc = "Used to treat physical injuries." + icon_state = "pill18" + + New() + ..() + reagents.add_reagent("bicaridine", 30) + +/obj/item/weapon/reagent_containers/pill/happy + name = "Happy pill" + desc = "Happy happy joy joy!" + icon_state = "pill18" + + New() + ..() + reagents.add_reagent("space_drugs", 15) + reagents.add_reagent("sugar", 15) + +/obj/item/weapon/reagent_containers/pill/zoom + name = "Zoom pill" + desc = "Zoooom!" + icon_state = "pill18" + + New() + ..() + reagents.add_reagent("impedrezene", 10) + reagents.add_reagent("synaptizine", 1) + reagents.add_reagent("hyperzine", 10) + +/obj/item/weapon/reagent_containers/pill/hyperzine + name = "Hyperzine pill" + desc = "Gotta go fast!" + + icon_state = "pill18" + New() + ..() + reagents.add_reagent("hyperzine", 10) + +/obj/item/weapon/storage/pill_bottle/time_release + name = "controlled release pill bottle" + desc = "A bottle containing special pills which can be calibrated for delayed release with sugar." + +/obj/item/weapon/storage/pill_bottle/time_release/New() + ..() + for(var/i=1 to 7) + new /obj/item/weapon/reagent_containers/pill/time_release(src) + +/obj/item/weapon/reagent_containers/pill/time_release + name = "time release pill" + desc = "A pill which will not be metabolized until all of the sugar inside metabolizes. By extension, the chemicals inside do not react with one another until entering the body. Unlike other pills, it is specially designed to be compatible with droppers and syringes." + icon_state = "pill18" + flags = FPRINT | NOREACT + +/obj/item/weapon/reagent_containers/pill/time_release/injest(mob/M as mob) + if(!reagents) return + if(!M) return + var/timer = round(reagents.get_reagent_amount("sugar"),1) + forceMove(M) + spawn(timer*30) + reagents.del_reagent("sugar") + reagents.reaction(M, INGEST) + reagents.trans_to(M, reagents.total_volume) + qdel(src) + +/obj/item/weapon/storage/pill_bottle/random + name = "trail mix" + desc = "Just what the assistant ordered." + +/obj/item/weapon/storage/pill_bottle/random/New() + ..() + for(var/i=1 to 14) + new /obj/item/weapon/reagent_containers/pill/random(src) + +/obj/item/weapon/reagent_containers/pill/random + name = "unknown pill" + desc = "Dare you enter my chemical realm?" + +/obj/item/weapon/reagent_containers/pill/random/New() + ..() + var/chemical = pick("hyperzine", "oxycodone", "doctorsdelight", "lexorin", "leporazine", "mutagen", "ryetalyn", "pacid", "cornoil", "tonio", "space_drugs","zombiepowder") + reagents.add_reagent(chemical, 10) + /* Possible choices: + Good: Hyperzine, Oxycodone, Doctor's Delight, Leporazine + Neutral: Corn Oil, Ryetalyn, Tonio, Space Drugs + Bad: Mutagen, Polytrinic Acid, Lexorin, Zombie Powder + */ diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 3a452f8917c..9b392ccb4a9 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -1,196 +1,196 @@ -// Reagents to log when sprayed -var/global/list/logged_sprayed_reagents = list("sacid", "pacid", "lube", "fuel") - -/obj/item/weapon/reagent_containers/spray - name = "spray bottle" - desc = "A spray bottle, with an unscrewable top." - icon = 'icons/obj/janitor.dmi' - icon_state = "cleaner" - item_state = "cleaner" - flags = OPENCONTAINER|FPRINT - slot_flags = SLOT_BELT - throwforce = 3 - w_class = 2.0 - throw_speed = 2 - throw_range = 10 - amount_per_transfer_from_this = 10 - volume = 250 - possible_transfer_amounts = null - - var/delay_spraying = TRUE // Whether to delay the next attack after using it - - //! List of things to avoid spraying on close range. TODO Remove snowflake, handle this in every attackby() properly. - var/list/ignore_spray_types = list(/obj/item/weapon/storage, /obj/structure/table, /obj/structure/rack, /obj/structure/closet, /obj/structure/sink) - -/obj/item/weapon/reagent_containers/spray/afterattack(atom/A as mob|obj, mob/user as mob, var/adjacency_flag, var/click_params) - if (adjacency_flag && is_type_in_list(A, ignore_spray_types)) - return - - if (delay_spraying) - user.delayNextAttack(8) - - if (istype(A, /obj/structure/reagent_dispensers) && adjacency_flag) - transfer(A, user, can_send = FALSE, can_receive = TRUE) - return - - if (is_empty()) //If empty, checks for a nonempty chempack on the user. - var/mob/living/M = user - if (M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack)) - var/obj/item/weapon/reagent_containers/chempack/P = M.back - if (!P.safety) - if (!P.is_empty()) - if (istype(src,/obj/item/weapon/reagent_containers/spray/chemsprayer)) //The chemsprayer uses three times its amount_per_transfer_from_this per spray. - transfer_sub(P, src, amount_per_transfer_from_this*3, user) - else - transfer_sub(P, src, amount_per_transfer_from_this, user) - else +// Reagents to log when sprayed +var/global/list/logged_sprayed_reagents = list("sacid", "pacid", "lube", "fuel") + +/obj/item/weapon/reagent_containers/spray + name = "spray bottle" + desc = "A spray bottle, with an unscrewable top." + icon = 'icons/obj/janitor.dmi' + icon_state = "cleaner" + item_state = "cleaner" + flags = OPENCONTAINER|FPRINT + slot_flags = SLOT_BELT + throwforce = 3 + w_class = 2.0 + throw_speed = 2 + throw_range = 10 + amount_per_transfer_from_this = 10 + volume = 250 + possible_transfer_amounts = null + + var/delay_spraying = TRUE // Whether to delay the next attack after using it + + //! List of things to avoid spraying on close range. TODO Remove snowflake, handle this in every attackby() properly. + var/list/ignore_spray_types = list(/obj/item/weapon/storage, /obj/structure/table, /obj/structure/rack, /obj/structure/closet, /obj/structure/sink) + +/obj/item/weapon/reagent_containers/spray/afterattack(atom/A as mob|obj, mob/user as mob, var/adjacency_flag, var/click_params) + if (adjacency_flag && is_type_in_list(A, ignore_spray_types)) + return + + if (delay_spraying) + user.delayNextAttack(8) + + if (istype(A, /obj/structure/reagent_dispensers) && adjacency_flag) + transfer(A, user, can_send = FALSE, can_receive = TRUE) + return + + if (is_empty()) //If empty, checks for a nonempty chempack on the user. + var/mob/living/M = user + if (M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack)) + var/obj/item/weapon/reagent_containers/chempack/P = M.back + if (!P.safety) + if (!P.is_empty()) + if (istype(src,/obj/item/weapon/reagent_containers/spray/chemsprayer)) //The chemsprayer uses three times its amount_per_transfer_from_this per spray. + transfer_sub(P, src, amount_per_transfer_from_this*3, user) + else + transfer_sub(P, src, amount_per_transfer_from_this, user) + else to_chat(user, "\The [P] is empty!") - return - else + return + else to_chat(user, "\The [src] is empty!") - return - else + return + else to_chat(user, "\The [src] is empty!") - return - - // Log reagents - var/list/log_reagent_list = list() - - for (var/reagent_id in logged_sprayed_reagents) - if (reagents.has_reagent(reagent_id)) - log_reagent_list += "'[reagent_id]'" - - if (log_reagent_list.len > 0) - add_gamelogs(user, "sprayed {[english_list(log_reagent_list, and_text = ", ")]} with \the [src]", admin = TRUE, tp_link = TRUE) - - // Override for your custom puff behaviour - make_puff(A, user) - -/obj/item/weapon/reagent_containers/spray/attack_self(var/mob/user) - amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10) + return + + // Log reagents + var/list/log_reagent_list = list() + + for (var/reagent_id in logged_sprayed_reagents) + if (reagents.has_reagent(reagent_id)) + log_reagent_list += "'[reagent_id]'" + + if (log_reagent_list.len > 0) + add_gamelogs(user, "sprayed {[english_list(log_reagent_list, and_text = ", ")]} with \the [src]", admin = TRUE, tp_link = TRUE) + + // Override for your custom puff behaviour + make_puff(A, user) + +/obj/item/weapon/reagent_containers/spray/attack_self(var/mob/user) + amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10) to_chat(user, "You switched [amount_per_transfer_from_this == 10 ? "on" : "off"] the pressure nozzle. You'll now use [amount_per_transfer_from_this] units per spray.") - -/obj/item/weapon/reagent_containers/spray/proc/make_puff(var/atom/target, var/mob/user) - // Create the chemical puff - var/transfer_amount = amount_per_transfer_from_this - if (!can_transfer_an_APTFT() && !is_empty()) //If it doesn't contain enough reagents to fulfill its amount_per_transfer_from_this, but also isn't empty, it'll spray whatever it has left. - transfer_amount = reagents.total_volume - var/mix_color = mix_color_from_reagents(reagents.reagent_list) - var/obj/effect/decal/chemical_puff/D = getFromPool(/obj/effect/decal/chemical_puff, get_turf(src), mix_color, amount_per_transfer_from_this) - reagents.trans_to(D, transfer_amount, 1/3) - - // Move the puff toward the target - spawn(0) - for (var/i = 0, i < 3, i++) - step_towards(D, target) - D.react() - sleep(3) - - returnToPool(D) - - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) - -/obj/item/weapon/reagent_containers/spray/verb/empty() - - - set name = "Empty Spray Bottle" - set category = "Object" - set src in usr - - if(isturf(usr.loc)) + +/obj/item/weapon/reagent_containers/spray/proc/make_puff(var/atom/target, var/mob/user) + // Create the chemical puff + var/transfer_amount = amount_per_transfer_from_this + if (!can_transfer_an_APTFT() && !is_empty()) //If it doesn't contain enough reagents to fulfill its amount_per_transfer_from_this, but also isn't empty, it'll spray whatever it has left. + transfer_amount = reagents.total_volume + var/mix_color = mix_color_from_reagents(reagents.reagent_list) + var/obj/effect/decal/chemical_puff/D = getFromPool(/obj/effect/decal/chemical_puff, get_turf(src), mix_color, amount_per_transfer_from_this) + reagents.trans_to(D, transfer_amount, 1/3) + + // Move the puff toward the target + spawn(0) + for (var/i = 0, i < 3, i++) + step_towards(D, target) + D.react() + sleep(3) + + returnToPool(D) + + playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + +/obj/item/weapon/reagent_containers/spray/verb/empty() + + + set name = "Empty Spray Bottle" + set category = "Object" + set src in usr + + if(isturf(usr.loc)) to_chat(usr, "You empty the [src] onto the floor.") - reagents.reaction(usr.loc) - spawn(5) src.reagents.clear_reagents() - -//space cleaner -/obj/item/weapon/reagent_containers/spray/cleaner - name = "space cleaner" - desc = "BLAM!-brand non-foaming space cleaner!" - - -/obj/item/weapon/reagent_containers/spray/cleaner/New() - ..() - reagents.add_reagent("cleaner", 250) - -//pepperspray -/obj/item/weapon/reagent_containers/spray/pepper - name = "pepperspray" - desc = "Manufactured by UhangInc, used to blind and down an opponent quickly." - icon = 'icons/obj/weapons.dmi' - icon_state = "pepperspray" - item_state = "pepperspray" - volume = 40 - amount_per_transfer_from_this = 10 - - -/obj/item/weapon/reagent_containers/spray/pepper/New() - ..() - reagents.add_reagent("condensedcapsaicin", 40) - -// Plant-B-Gone -/obj/item/weapon/reagent_containers/spray/plantbgone // -- Skie - name = "Plant-B-Gone" - desc = "Kills those pesky weeds!" - icon = 'icons/obj/hydroponics.dmi' - icon_state = "plantbgone" - item_state = "plantbgone" - volume = 100 - -/obj/item/weapon/reagent_containers/spray/plantbgone/New() - ..() - reagents.add_reagent("plantbgone", 100) - - -//chemsprayer -/obj/item/weapon/reagent_containers/spray/chemsprayer - name = "chem sprayer" - desc = "A utility used to spray large amounts of reagent in a given area." - icon = 'icons/obj/gun.dmi' - icon_state = "chemsprayer" - item_state = "chemsprayer" - throwforce = 3 - w_class = 3.0 - volume = 600 - origin_tech = "combat=3;materials=3;engineering=3;syndicate=5" - - delay_spraying = FALSE - -/obj/item/weapon/reagent_containers/spray/chemsprayer/make_puff(var/atom/target, var/mob/user) - // Create the chemical puffs - var/mix_color = mix_color_from_reagents(reagents.reagent_list) - var/Sprays[3] - - for (var/i = 1, i <= 3, i++) - if (src.reagents.total_volume < 1) - break - - var/obj/effect/decal/chemical_puff/D = getFromPool(/obj/effect/decal/chemical_puff, get_turf(src), mix_color, amount_per_transfer_from_this) - reagents.trans_to(D, amount_per_transfer_from_this) - Sprays[i] = D - - // Move the puffs towards the target - var/direction = get_dir(src, target) - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T, turn(direction, 90)) - var/turf/T2 = get_step(T, turn(direction, -90)) - var/list/the_targets = list(T, T1, T2) - - for (var/i = 1, i <= Sprays.len, i++) - spawn() - var/obj/effect/decal/chemical_puff/D = Sprays[i] - if (!D) - continue - - // Spreads the sprays a little bit - var/turf/my_target = pick(the_targets) - the_targets -= my_target - - for (var/j = 1, j <= rand(6, 8), j++) - step_towards(D, my_target) - D.react(iteration_delay = 0) - sleep(2) - - returnToPool(D) - - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) - + reagents.reaction(usr.loc) + spawn(5) src.reagents.clear_reagents() + +//space cleaner +/obj/item/weapon/reagent_containers/spray/cleaner + name = "space cleaner" + desc = "BLAM!-brand non-foaming space cleaner!" + + +/obj/item/weapon/reagent_containers/spray/cleaner/New() + ..() + reagents.add_reagent("cleaner", 250) + +//pepperspray +/obj/item/weapon/reagent_containers/spray/pepper + name = "pepperspray" + desc = "Manufactured by UhangInc, used to blind and down an opponent quickly." + icon = 'icons/obj/weapons.dmi' + icon_state = "pepperspray" + item_state = "pepperspray" + volume = 40 + amount_per_transfer_from_this = 10 + + +/obj/item/weapon/reagent_containers/spray/pepper/New() + ..() + reagents.add_reagent("condensedcapsaicin", 40) + +// Plant-B-Gone +/obj/item/weapon/reagent_containers/spray/plantbgone // -- Skie + name = "Plant-B-Gone" + desc = "Kills those pesky weeds!" + icon = 'icons/obj/hydroponics.dmi' + icon_state = "plantbgone" + item_state = "plantbgone" + volume = 100 + +/obj/item/weapon/reagent_containers/spray/plantbgone/New() + ..() + reagents.add_reagent("plantbgone", 100) + + +//chemsprayer +/obj/item/weapon/reagent_containers/spray/chemsprayer + name = "chem sprayer" + desc = "A utility used to spray large amounts of reagent in a given area." + icon = 'icons/obj/gun.dmi' + icon_state = "chemsprayer" + item_state = "chemsprayer" + throwforce = 3 + w_class = 3.0 + volume = 600 + origin_tech = "combat=3;materials=3;engineering=3;syndicate=5" + + delay_spraying = FALSE + +/obj/item/weapon/reagent_containers/spray/chemsprayer/make_puff(var/atom/target, var/mob/user) + // Create the chemical puffs + var/mix_color = mix_color_from_reagents(reagents.reagent_list) + var/Sprays[3] + + for (var/i = 1, i <= 3, i++) + if (src.reagents.total_volume < 1) + break + + var/obj/effect/decal/chemical_puff/D = getFromPool(/obj/effect/decal/chemical_puff, get_turf(src), mix_color, amount_per_transfer_from_this) + reagents.trans_to(D, amount_per_transfer_from_this) + Sprays[i] = D + + // Move the puffs towards the target + var/direction = get_dir(src, target) + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T, turn(direction, 90)) + var/turf/T2 = get_step(T, turn(direction, -90)) + var/list/the_targets = list(T, T1, T2) + + for (var/i = 1, i <= Sprays.len, i++) + spawn() + var/obj/effect/decal/chemical_puff/D = Sprays[i] + if (!D) + continue + + // Spreads the sprays a little bit + var/turf/my_target = pick(the_targets) + the_targets -= my_target + + for (var/j = 1, j <= rand(6, 8), j++) + step_towards(D, my_target) + D.react(iteration_delay = 0) + sleep(2) + + returnToPool(D) + + playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 4107be38915..913f0feb2e7 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -1,415 +1,415 @@ -//////////////////////////////////////////////////////////////////////////////// -/// Syringes. -//////////////////////////////////////////////////////////////////////////////// -#define SYRINGE_DRAW 0 -#define SYRINGE_INJECT 1 -#define SYRINGE_BROKEN 2 - -#define INJECTION_BODY 0 -#define INJECTION_SUIT_PORT 1 - -/obj/item/weapon/reagent_containers/syringe - name = "syringe" - desc = "A syringe." - icon = 'icons/obj/syringe.dmi' - item_state = "syringe_0" - icon_state = "0" - amount_per_transfer_from_this = 5 - sharpness = 1 - possible_transfer_amounts = null //list(5,10,15) - volume = 15 - starting_materials = list(MAT_GLASS = 1000) - w_type = RECYK_GLASS - - var/mode = SYRINGE_DRAW - var/can_draw_blood = TRUE - var/can_stab = TRUE - - // List of types that can be injected regardless of the CONTAINEROPEN flag - // TODO Remove snowflake - var/injectable_types = list(/obj/item/weapon/reagent_containers/food, - /obj/item/slime_extract, - /obj/item/clothing/mask/cigarette, - /obj/item/weapon/storage/fancy/cigarettes, - /obj/item/weapon/implantcase/chem, - /obj/item/weapon/reagent_containers/pill/time_release) - -/obj/item/weapon/reagent_containers/syringe/suicide_act(mob/user) +//////////////////////////////////////////////////////////////////////////////// +/// Syringes. +//////////////////////////////////////////////////////////////////////////////// +#define SYRINGE_DRAW 0 +#define SYRINGE_INJECT 1 +#define SYRINGE_BROKEN 2 + +#define INJECTION_BODY 0 +#define INJECTION_SUIT_PORT 1 + +/obj/item/weapon/reagent_containers/syringe + name = "syringe" + desc = "A syringe." + icon = 'icons/obj/syringe.dmi' + item_state = "syringe_0" + icon_state = "0" + amount_per_transfer_from_this = 5 + sharpness = 1 + possible_transfer_amounts = null //list(5,10,15) + volume = 15 + starting_materials = list(MAT_GLASS = 1000) + w_type = RECYK_GLASS + + var/mode = SYRINGE_DRAW + var/can_draw_blood = TRUE + var/can_stab = TRUE + + // List of types that can be injected regardless of the CONTAINEROPEN flag + // TODO Remove snowflake + var/injectable_types = list(/obj/item/weapon/reagent_containers/food, + /obj/item/slime_extract, + /obj/item/clothing/mask/cigarette, + /obj/item/weapon/storage/fancy/cigarettes, + /obj/item/weapon/implantcase/chem, + /obj/item/weapon/reagent_containers/pill/time_release) + +/obj/item/weapon/reagent_containers/syringe/suicide_act(mob/user) to_chat(viewers(user), "[user] appears to be injecting an air bubble using a [src.name]! It looks like \he's trying to commit suicide.") - return(OXYLOSS) - -/obj/item/weapon/reagent_containers/syringe/on_reagent_change() - update_icon() - -/obj/item/weapon/reagent_containers/syringe/pickup(mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/syringe/dropped(mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/syringe/attack_self(mob/user as mob) - switch(mode) - if(SYRINGE_DRAW) - mode = SYRINGE_INJECT - if(SYRINGE_INJECT) - mode = SYRINGE_DRAW - if(SYRINGE_BROKEN) - return - update_icon() - -/obj/item/weapon/reagent_containers/syringe/attack_hand(var/mob/user) - ..() - update_icon() - -/obj/item/weapon/reagent_containers/syringe/attack_paw(var/mob/user) - return attack_hand(user) - -/obj/item/weapon/reagent_containers/syringe/afterattack(obj/target, mob/user, proximity_flag, click_parameters) - if(proximity_flag == 0) // not adjacent - return - - if(!target.reagents) return - - if(mode == SYRINGE_BROKEN) + return(OXYLOSS) + +/obj/item/weapon/reagent_containers/syringe/on_reagent_change() + update_icon() + +/obj/item/weapon/reagent_containers/syringe/pickup(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/syringe/dropped(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/syringe/attack_self(mob/user as mob) + switch(mode) + if(SYRINGE_DRAW) + mode = SYRINGE_INJECT + if(SYRINGE_INJECT) + mode = SYRINGE_DRAW + if(SYRINGE_BROKEN) + return + update_icon() + +/obj/item/weapon/reagent_containers/syringe/attack_hand(var/mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/syringe/attack_paw(var/mob/user) + return attack_hand(user) + +/obj/item/weapon/reagent_containers/syringe/afterattack(obj/target, mob/user, proximity_flag, click_parameters) + if(proximity_flag == 0) // not adjacent + return + + if(!target.reagents) return + + if(mode == SYRINGE_BROKEN) to_chat(user, "\The [src] is broken!") - return - - if (user.a_intent == I_HURT && ismob(target)) - if((M_CLUMSY in user.mutations) && prob(50)) - target = user - - if (target != user && !can_stab) // You still can stab yourself if you're clumsy, honk + return + + if (user.a_intent == I_HURT && ismob(target)) + if((M_CLUMSY in user.mutations) && prob(50)) + target = user + + if (target != user && !can_stab) // You still can stab yourself if you're clumsy, honk to_chat(user, "You can't grasp \the [src] properly for stabbing!") - return - - syringestab(target, user) - return - - if (mode == SYRINGE_DRAW) - handle_draw(target, user) - else if (mode == SYRINGE_INJECT) - handle_inject(target, user) - -/obj/item/weapon/reagent_containers/syringe/update_icon() - if(mode == SYRINGE_BROKEN) - icon_state = "broken" - overlays.len = 0 - return - var/rounded_vol = round(reagents.total_volume,5) - overlays.len = 0 - if(ismob(loc)) - var/injoverlay - switch(mode) - if (SYRINGE_DRAW) - injoverlay = "draw" - if (SYRINGE_INJECT) - injoverlay = "inject" - overlays += injoverlay - icon_state = "[rounded_vol]" - item_state = "syringe_[rounded_vol]" - - if(reagents.total_volume) - var/image/filling = image('icons/obj/reagentfillings.dmi', src, "syringe10") - - filling.icon_state = "syringe[rounded_vol]" - - filling.icon += mix_color_from_reagents(reagents.reagent_list) - overlays += filling - -/obj/item/weapon/reagent_containers/syringe/proc/handle_draw(var/atom/target, var/mob/user) - if (!target) - return - - if (src.is_full()) + return + + syringestab(target, user) + return + + if (mode == SYRINGE_DRAW) + handle_draw(target, user) + else if (mode == SYRINGE_INJECT) + handle_inject(target, user) + +/obj/item/weapon/reagent_containers/syringe/update_icon() + if(mode == SYRINGE_BROKEN) + icon_state = "broken" + overlays.len = 0 + return + var/rounded_vol = round(reagents.total_volume,5) + overlays.len = 0 + if(ismob(loc)) + var/injoverlay + switch(mode) + if (SYRINGE_DRAW) + injoverlay = "draw" + if (SYRINGE_INJECT) + injoverlay = "inject" + overlays += injoverlay + icon_state = "[rounded_vol]" + item_state = "syringe_[rounded_vol]" + + if(reagents.total_volume) + var/image/filling = image('icons/obj/reagentfillings.dmi', src, "syringe10") + + filling.icon_state = "syringe[rounded_vol]" + + filling.icon += mix_color_from_reagents(reagents.reagent_list) + overlays += filling + +/obj/item/weapon/reagent_containers/syringe/proc/handle_draw(var/atom/target, var/mob/user) + if (!target) + return + + if (src.is_full()) to_chat(user, "\The [src] is full.") - return - - // Drawing from mobs draws from their blood or equivalent - if (ismob(target)) - if (!can_draw_blood) + return + + // Drawing from mobs draws from their blood or equivalent + if (ismob(target)) + if (!can_draw_blood) to_chat(user, "This needle isn't designed for drawing fluids from living things.") - return - - if (istype(target, /mob/living/carbon/slime)) + return + + if (istype(target, /mob/living/carbon/slime)) to_chat(user, "You are unable to locate any blood.") - return - - if (reagents.has_reagent("blood")) // TODO Current reagent system can't handle multiple blood sources properly + return + + if (reagents.has_reagent("blood")) // TODO Current reagent system can't handle multiple blood sources properly to_chat(user, "There is already a blood sample in this syringe!") - return - if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(H.species && (H.species.chem_flags & NO_INJECT)) - user.visible_message("[user] attempts to poke [H] with \the [src] but it won't go in!", "You fail to pierce [H] with \the [src]") - return - - if (iscarbon(target)) - var/mob/living/carbon/T = target - if (!T.dna) + return + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(H.species && (H.species.chem_flags & NO_INJECT)) + user.visible_message("[user] attempts to poke [H] with \the [src] but it won't go in!", "You fail to pierce [H] with \the [src]") + return + + if (iscarbon(target)) + var/mob/living/carbon/T = target + if (!T.dna) to_chat(user, "You are unable to locate any blood.") - warning("Tried to draw blood or equivalent from [target] (\ref[target]) but it's missing their DNA datum!") - return - - if (M_NOCLONE in T.mutations) // Target has been husked + warning("Tried to draw blood or equivalent from [target] (\ref[target]) but it's missing their DNA datum!") + return + + if (M_NOCLONE in T.mutations) // Target has been husked to_chat(user, "You are unable to locate any blood.") - return - - var/amount = src.reagents.maximum_volume - src.reagents.total_volume - var/datum/reagent/B = T.take_blood(null, amount) - //reagents.add_reagent("blood", - if (B) - reagents.add_reagent("blood", amount, B.data) - user.visible_message("[user] takes a blood sample from [target].", - "You take a blood sample from [target].") - else - user.visible_message("[user] inserts the syringe into [target], draws back the plunger and gets... nothing?",\ - "You insert the syringe into [target], draw back the plunger and get... nothing?") - // Drawing from objects draws their contents - else if (isobj(target)) - if (!target.is_open_container() && !istype(target, /obj/structure/reagent_dispensers) && !istype(target, /obj/item/slime_extract)) + return + + var/amount = src.reagents.maximum_volume - src.reagents.total_volume + var/datum/reagent/B = T.take_blood(null, amount) + //reagents.add_reagent("blood", + if (B) + reagents.add_reagent("blood", amount, B.data) + user.visible_message("[user] takes a blood sample from [target].", + "You take a blood sample from [target].") + else + user.visible_message("[user] inserts the syringe into [target], draws back the plunger and gets... nothing?",\ + "You insert the syringe into [target], draw back the plunger and get... nothing?") + // Drawing from objects draws their contents + else if (isobj(target)) + if (!target.is_open_container() && !istype(target, /obj/structure/reagent_dispensers) && !istype(target, /obj/item/slime_extract)) to_chat(user, "You cannot directly remove reagents from this object.") - return - - var/tx_amount = 0 - if (istype(target, /obj/item/weapon/reagent_containers) || istype(target, /obj/structure/reagent_dispensers)) - tx_amount = transfer_sub(target, src, amount_per_transfer_from_this, user) - else - tx_amount = target.reagents.trans_to(src, amount_per_transfer_from_this) - - if (tx_amount > 0) + return + + var/tx_amount = 0 + if (istype(target, /obj/item/weapon/reagent_containers) || istype(target, /obj/structure/reagent_dispensers)) + tx_amount = transfer_sub(target, src, amount_per_transfer_from_this, user) + else + tx_amount = target.reagents.trans_to(src, amount_per_transfer_from_this) + + if (tx_amount > 0) to_chat(user, "You fill \the [src] with [tx_amount] units of the solution.") - else if (tx_amount == 0) + else if (tx_amount == 0) to_chat(user, "\The [target] is empty.") - - if (src.is_full()) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/proc/handle_inject(var/atom/target, var/mob/user) - if (src.is_empty()) + + if (src.is_full()) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/proc/handle_inject(var/atom/target, var/mob/user) + if (src.is_empty()) to_chat(user, "\The [src] is empty.") - return - - // TODO Remove snowflake - if (!ismob(target) && !target.is_open_container() && !is_type_in_list(target, injectable_types)) + return + + // TODO Remove snowflake + if (!ismob(target) && !target.is_open_container() && !is_type_in_list(target, injectable_types)) to_chat(user, "You cannot directly fill this object.") - return - - if (target.reagents.total_volume >= target.reagents.maximum_volume) + return + + if (target.reagents.total_volume >= target.reagents.maximum_volume) to_chat(user, "\The [target] is full.") - return - - // Attempting to inject someone else takes time - if (ismob(target) && target != user) - if (get_injection_action(target) == INJECTION_SUIT_PORT) - user.visible_message("[user] begins hunting for an injection port \the [src] on [target]'s suit!", - "You begin hunting for an injection port for \the [src] on [target]'s suit!") - else - user.visible_message("[user] is trying to inject [target] with \the [src]!", - "You try to inject [target] with \the [src]!") - - if (!do_mob(user, target, get_injection_time(target))) - return - - user.visible_message("[user] injects [target] with the \the [src]!", - "You inject [target] with \the [src]!") - - if (istype(target, /mob/living)) - var/reagent_names = english_list(get_reagent_names()) - add_attacklogs(user, target, "injected", object = src, addition = "Reagents: [reagent_names]", admin_warn = TRUE) - - // Handle transfers and mob reactions - var/list/bad_reagents = reagents.get_bad_reagent_names() // Used for logging - var/tx_amount = min(amount_per_transfer_from_this, reagents.total_volume) - if (ismob(target)) - // TODO Every reagent reacts with the full volume instead of being scaled accordingly - // TODO which is pretty irrelevant now but should be fixed - reagents.reaction(target, INGEST) - - tx_amount = reagents.trans_to(target, tx_amount) + return + + // Attempting to inject someone else takes time + if (ismob(target) && target != user) + if (get_injection_action(target) == INJECTION_SUIT_PORT) + user.visible_message("[user] begins hunting for an injection port \the [src] on [target]'s suit!", + "You begin hunting for an injection port for \the [src] on [target]'s suit!") + else + user.visible_message("[user] is trying to inject [target] with \the [src]!", + "You try to inject [target] with \the [src]!") + + if (!do_mob(user, target, get_injection_time(target))) + return + + user.visible_message("[user] injects [target] with the \the [src]!", + "You inject [target] with \the [src]!") + + if (istype(target, /mob/living)) + var/reagent_names = english_list(get_reagent_names()) + add_attacklogs(user, target, "injected", object = src, addition = "Reagents: [reagent_names]", admin_warn = TRUE) + + // Handle transfers and mob reactions + var/list/bad_reagents = reagents.get_bad_reagent_names() // Used for logging + var/tx_amount = min(amount_per_transfer_from_this, reagents.total_volume) + if (ismob(target)) + // TODO Every reagent reacts with the full volume instead of being scaled accordingly + // TODO which is pretty irrelevant now but should be fixed + reagents.reaction(target, INGEST) + + tx_amount = reagents.trans_to(target, tx_amount) to_chat(user, "You inject [tx_amount] units of the solution. The syringe now contains [reagents.total_volume] units.") - - // Log transfers of 'bad things' (/vg/) - if (tx_amount > 0 && isobj(target) && target:log_reagents && bad_reagents && bad_reagents.len > 0) - log_reagents(user, src, target, tx_amount, bad_reagents) - - if (src.is_empty()) - mode = SYRINGE_DRAW - update_icon() - -// Injecting people with a space suit/hardsuit is harder -/obj/item/weapon/reagent_containers/syringe/proc/get_injection_time(var/mob/target) - if (istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - return (H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit/space)) ? 60 : 30 - else - return 30 - -/obj/item/weapon/reagent_containers/syringe/proc/get_injection_action(var/mob/target) - if (istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - return (H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) ? INJECTION_SUIT_PORT : INJECTION_BODY - else - return INJECTION_BODY - -/obj/item/weapon/reagent_containers/syringe/proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob) - if (ishuman(target)) - var/mob/living/carbon/human/H = target - var/target_zone = check_zone(user.zone_sel.selecting, target) - var/datum/organ/external/affecting = H.get_organ(target_zone) - - if (!affecting) - return - else if (affecting.status & ORGAN_DESTROYED) + + // Log transfers of 'bad things' (/vg/) + if (tx_amount > 0 && isobj(target) && target:log_reagents && bad_reagents && bad_reagents.len > 0) + log_reagents(user, src, target, tx_amount, bad_reagents) + + if (src.is_empty()) + mode = SYRINGE_DRAW + update_icon() + +// Injecting people with a space suit/hardsuit is harder +/obj/item/weapon/reagent_containers/syringe/proc/get_injection_time(var/mob/target) + if (istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + return (H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit/space)) ? 60 : 30 + else + return 30 + +/obj/item/weapon/reagent_containers/syringe/proc/get_injection_action(var/mob/target) + if (istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + return (H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) ? INJECTION_SUIT_PORT : INJECTION_BODY + else + return INJECTION_BODY + +/obj/item/weapon/reagent_containers/syringe/proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob) + if (ishuman(target)) + var/mob/living/carbon/human/H = target + var/target_zone = check_zone(user.zone_sel.selecting, target) + var/datum/organ/external/affecting = H.get_organ(target_zone) + + if (!affecting) + return + else if (affecting.status & ORGAN_DESTROYED) to_chat(user, "What [affecting.display_name]?") - return - - var/hit_area = affecting.display_name - if((user != target) && H.check_shields(7, "the [src.name]")) - return - - // Check for protection on the targeted area and show messages - var/deflected = (target != user && target.getarmor(target_zone, "melee") > 5 && prob(50)) - - add_attacklogs(user, target, (deflected ? "attempted to inject" : "injected"), object = src, addition = "Deflected: [deflected ? "YES" : "NO"]; Reagents: [english_list(get_reagent_names())]", admin_warn = !deflected) - - if (deflected) - user.visible_message("[user] tries to stab [target] in \the [hit_area] with \the [src], but the attack is deflected by armor!", "You try to stab [target] in \the [hit_area] with \the [src], but the attack is deflected by armor!") - user.u_equip(src, 1) - qdel(src) - return // Avoid the transfer since we're using qdel - else - user.visible_message("[user] stabs [target] in \the [hit_area] with \the [src]!", "You stab [target] in \the [hit_area] with \the [src]!") - affecting.take_damage(3) - else - user.visible_message("[user] stabs [target] with \the [src]!", "You stab [target] with \the [src]!") - target.take_organ_damage(3)// 7 is the same as crowbar punch - - // Break the syringe and transfer some of the reagents to the target - src.reagents.reaction(target, INGEST) - var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand - src.reagents.trans_to(target, syringestab_amount_transferred) - src.desc += " It is broken." - src.mode = SYRINGE_BROKEN - src.add_blood(target) - src.add_fingerprint(usr) - src.update_icon() - -/obj/item/weapon/reagent_containers/syringe/giant - name = "giant syringe" - desc = "A syringe used for lethal injections." - amount_per_transfer_from_this = 50 - possible_transfer_amounts = null - volume = 50 - - can_draw_blood = FALSE - can_stab = FALSE - -/obj/item/weapon/reagent_containers/syringe/giant/get_injection_time(var/mob/target) - if (istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - return (H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit/space)) ? 330 : 300 - else - return 300 - -/obj/item/weapon/reagent_containers/syringe/giant/update_icon() - if (mode == SYRINGE_BROKEN) - icon_state = "broken" - return - - var/rounded_vol = round(reagents.total_volume, 50) - icon_state = (ismob(loc) ? "[mode == SYRINGE_DRAW ? "d" : "i"][rounded_vol]" : "[rounded_vol]") - item_state = "syringe_[rounded_vol]" - -//////////////////////////////////////////////////////////////////////////////// -/// Syringes. END -//////////////////////////////////////////////////////////////////////////////// - - - -/obj/item/weapon/reagent_containers/syringe/inaprovaline - name = "Syringe (inaprovaline)" - desc = "Contains inaprovaline - used to stabilize patients." -/obj/item/weapon/reagent_containers/syringe/inaprovaline/New() - ..() - reagents.add_reagent("inaprovaline", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/antitoxin - name = "Syringe (anti-toxin)" - desc = "Contains anti-toxins." -/obj/item/weapon/reagent_containers/syringe/antitoxin/New() - ..() - reagents.add_reagent("anti_toxin", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/antiviral - name = "Syringe (spaceacillin)" - desc = "Contains antiviral agents." -/obj/item/weapon/reagent_containers/syringe/antiviral/New() - ..() - reagents.add_reagent("spaceacillin", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/charcoal - name = "Syringe (Activated Charcoal)" - desc = "Contains activated charcoal - used to treat overdoses." -/obj/item/weapon/reagent_containers/syringe/charcoal/New() - ..() - reagents.add_reagent("charcoal", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/giant/chloral - name = "Lethal Injection Syringe" - desc = "Puts people into a sleep they'll never wake up from." -/obj/item/weapon/reagent_containers/syringe/giant/chloral/New() - ..() - reagents.add_reagent("chloralhydrate", 50) - mode = SYRINGE_INJECT - update_icon() - - -//Robot syringes -//Not special in any way, code wise. They don't have added variables or procs. -/obj/item/weapon/reagent_containers/syringe/robot/antitoxin - name = "Syringe (anti-toxin)" - desc = "Contains anti-toxins." -/obj/item/weapon/reagent_containers/syringe/robot/antitoxin/New() - ..() - reagents.add_reagent("anti_toxin", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/robot/inoprovaline - name = "Syringe (inoprovaline)" - desc = "Contains inaprovaline - used to stabilize patients." -/obj/item/weapon/reagent_containers/syringe/robot/inoprovaline/New() - ..() - reagents.add_reagent("inaprovaline", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/robot/charcoal - name = "Syringe (Activated Charcoal)" - desc = "Contains activated charcoal - used to treat overdoses." -/obj/item/weapon/reagent_containers/syringe/robot/charcoal/New() - ..() - reagents.add_reagent("charcoal", 15) - mode = SYRINGE_INJECT - update_icon() - -/obj/item/weapon/reagent_containers/syringe/robot/mixed - name = "Syringe (mixed)" - desc = "Contains inaprovaline & anti-toxins." -/obj/item/weapon/reagent_containers/syringe/robot/mixed/New() - ..() - reagents.add_reagent("inaprovaline", 7) - reagents.add_reagent("anti_toxin", 8) - mode = SYRINGE_INJECT - update_icon() + return + + var/hit_area = affecting.display_name + if((user != target) && H.check_shields(7, "the [src.name]")) + return + + // Check for protection on the targeted area and show messages + var/deflected = (target != user && target.getarmor(target_zone, "melee") > 5 && prob(50)) + + add_attacklogs(user, target, (deflected ? "attempted to inject" : "injected"), object = src, addition = "Deflected: [deflected ? "YES" : "NO"]; Reagents: [english_list(get_reagent_names())]", admin_warn = !deflected) + + if (deflected) + user.visible_message("[user] tries to stab [target] in \the [hit_area] with \the [src], but the attack is deflected by armor!", "You try to stab [target] in \the [hit_area] with \the [src], but the attack is deflected by armor!") + user.u_equip(src, 1) + qdel(src) + return // Avoid the transfer since we're using qdel + else + user.visible_message("[user] stabs [target] in \the [hit_area] with \the [src]!", "You stab [target] in \the [hit_area] with \the [src]!") + affecting.take_damage(3) + else + user.visible_message("[user] stabs [target] with \the [src]!", "You stab [target] with \the [src]!") + target.take_organ_damage(3)// 7 is the same as crowbar punch + + // Break the syringe and transfer some of the reagents to the target + src.reagents.reaction(target, INGEST) + var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand + src.reagents.trans_to(target, syringestab_amount_transferred) + src.desc += " It is broken." + src.mode = SYRINGE_BROKEN + src.add_blood(target) + src.add_fingerprint(usr) + src.update_icon() + +/obj/item/weapon/reagent_containers/syringe/giant + name = "giant syringe" + desc = "A syringe used for lethal injections." + amount_per_transfer_from_this = 50 + possible_transfer_amounts = null + volume = 50 + + can_draw_blood = FALSE + can_stab = FALSE + +/obj/item/weapon/reagent_containers/syringe/giant/get_injection_time(var/mob/target) + if (istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + return (H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit/space)) ? 330 : 300 + else + return 300 + +/obj/item/weapon/reagent_containers/syringe/giant/update_icon() + if (mode == SYRINGE_BROKEN) + icon_state = "broken" + return + + var/rounded_vol = round(reagents.total_volume, 50) + icon_state = (ismob(loc) ? "[mode == SYRINGE_DRAW ? "d" : "i"][rounded_vol]" : "[rounded_vol]") + item_state = "syringe_[rounded_vol]" + +//////////////////////////////////////////////////////////////////////////////// +/// Syringes. END +//////////////////////////////////////////////////////////////////////////////// + + + +/obj/item/weapon/reagent_containers/syringe/inaprovaline + name = "Syringe (inaprovaline)" + desc = "Contains inaprovaline - used to stabilize patients." +/obj/item/weapon/reagent_containers/syringe/inaprovaline/New() + ..() + reagents.add_reagent("inaprovaline", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/antitoxin + name = "Syringe (anti-toxin)" + desc = "Contains anti-toxins." +/obj/item/weapon/reagent_containers/syringe/antitoxin/New() + ..() + reagents.add_reagent("anti_toxin", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/antiviral + name = "Syringe (spaceacillin)" + desc = "Contains antiviral agents." +/obj/item/weapon/reagent_containers/syringe/antiviral/New() + ..() + reagents.add_reagent("spaceacillin", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/charcoal + name = "Syringe (Activated Charcoal)" + desc = "Contains activated charcoal - used to treat overdoses." +/obj/item/weapon/reagent_containers/syringe/charcoal/New() + ..() + reagents.add_reagent("charcoal", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/giant/chloral + name = "Lethal Injection Syringe" + desc = "Puts people into a sleep they'll never wake up from." +/obj/item/weapon/reagent_containers/syringe/giant/chloral/New() + ..() + reagents.add_reagent("chloralhydrate", 50) + mode = SYRINGE_INJECT + update_icon() + + +//Robot syringes +//Not special in any way, code wise. They don't have added variables or procs. +/obj/item/weapon/reagent_containers/syringe/robot/antitoxin + name = "Syringe (anti-toxin)" + desc = "Contains anti-toxins." +/obj/item/weapon/reagent_containers/syringe/robot/antitoxin/New() + ..() + reagents.add_reagent("anti_toxin", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/robot/inoprovaline + name = "Syringe (inoprovaline)" + desc = "Contains inaprovaline - used to stabilize patients." +/obj/item/weapon/reagent_containers/syringe/robot/inoprovaline/New() + ..() + reagents.add_reagent("inaprovaline", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/robot/charcoal + name = "Syringe (Activated Charcoal)" + desc = "Contains activated charcoal - used to treat overdoses." +/obj/item/weapon/reagent_containers/syringe/robot/charcoal/New() + ..() + reagents.add_reagent("charcoal", 15) + mode = SYRINGE_INJECT + update_icon() + +/obj/item/weapon/reagent_containers/syringe/robot/mixed + name = "Syringe (mixed)" + desc = "Contains inaprovaline & anti-toxins." +/obj/item/weapon/reagent_containers/syringe/robot/mixed/New() + ..() + reagents.add_reagent("inaprovaline", 7) + reagents.add_reagent("anti_toxin", 8) + mode = SYRINGE_INJECT + update_icon() diff --git a/code/modules/reagents/syringe_gun.dm b/code/modules/reagents/syringe_gun.dm index 22e74ae1024..bc12ecb1919 100644 --- a/code/modules/reagents/syringe_gun.dm +++ b/code/modules/reagents/syringe_gun.dm @@ -1,162 +1,162 @@ - - - -/obj/item/weapon/gun/syringe - name = "syringe gun" - desc = "A spring loaded rifle designed to fit syringes, designed to incapacitate unruly patients from a distance." - icon = 'icons/obj/gun.dmi' - icon_state = "syringegun" - item_state = null - inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') - w_class = 3.0 - throw_speed = 2 - throw_range = 10 - force = 4.0 - var/list/syringes = new/list() - var/max_syringes = 1 - starting_materials = list(MAT_IRON = 2000) - w_type = RECYK_METAL - -/obj/item/weapon/gun/syringe/examine(mob/user) - ..() - to_chat(user, "[syringes.len] / [max_syringes] syringes.") - -/obj/item/weapon/gun/syringe/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/weapon/reagent_containers/syringe)) - var/obj/item/weapon/reagent_containers/syringe/S = I - if(S.mode != 2)//SYRINGE_BROKEN in syringes.dm - if(syringes.len < max_syringes) - if(user.drop_item(I, src)) - syringes += I - to_chat(user, "You put the syringe in [src].") - to_chat(user, "[syringes.len] / [max_syringes] syringes.") - else - to_chat(user, "[src] cannot hold more syringes.") - else - to_chat(user, "This syringe is broken!") - - return 1 // Avoid calling the syringe's afterattack() - -/obj/item/weapon/gun/syringe/afterattack(obj/target, mob/user , flag) - if(/*!isturf(target.loc) || */target == user) return - ..() - -/obj/item/weapon/gun/syringe/can_fire() - return syringes.len - -/obj/item/weapon/gun/syringe/can_hit(var/mob/living/target as mob, var/mob/living/user as mob) - return 1 //SHOOT AND LET THE GOD GUIDE IT (probably will hit a wall anyway) - -/obj/item/weapon/gun/syringe/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) - if(syringes.len) - if(M_CLUMSY in user.mutations) - if(prob(50)) - to_chat(user, "You accidentally shoot yourself!") - var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] - if((!S) || (!S.reagents)) - to_chat(user, "Thankfully, nothing happens.") - return - syringes -= S - S.reagents.trans_to(user, S.reagents.total_volume) - qdel(S) - return - - spawn(0) fire_syringe(target,user) - else - to_chat(user, "[src] is empty.") - -/obj/item/weapon/gun/syringe/proc/fire_syringe(atom/target, mob/user) - if (locate (/obj/structure/table, src.loc)) - return - else - var/turf/trg = get_turf(target) - var/obj/effect/syringe_gun_dummy/D = new/obj/effect/syringe_gun_dummy(get_turf(src)) - var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] - if((!S) || (!S.reagents)) //ho boy! wot runtimes! - return - S.reagents.trans_to(D, S.reagents.total_volume) - syringes -= S - qdel(S) - S = null - D.icon_state = "syringeproj" - D.name = "syringe" - playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1) - log_attack("[user.name] ([user.ckey]) fired \the [src] at [target] [ismob(target) ? "([target:ckey])" : ""] ([target.x],[target.y],[target.z])" ) - for(var/i=0, i<6, i++) - if(!D) break - if(D.loc == trg) break - step_towards(D,trg) - - if(D) - for(var/mob/living/carbon/M in D.loc) - if(!istype(M,/mob/living/carbon)) continue - if(M == user) continue - var/blocked = 0 - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species && (H.species.chem_flags & NO_INJECT)) - H.visible_message("\The [D] bounces harmlessly off of [H].", "\The [D] bounces off you harmlessly and breaks as it hits the ground.") - qdel(D) - return - - blocked = istype(H.wear_suit, /obj/item/clothing/suit/space) // Block the syringe if the guy's wearing a spess suit. - //Syringe gun attack logging by Yvarov - var/R - if(D.reagents) - for(var/datum/reagent/A in D.reagents.reagent_list) - R += A.id + " (" - R += num2text(A.volume) + ")," - if (istype(M, /mob)) - M.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] shot [M]/[M.ckey] with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""]" - user.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] shot [M]/[M.ckey] with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""]" - msg_admin_attack("[user] ([user.ckey]) shot [M] ([M.ckey]) with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""] (JMP)") - if(!iscarbon(user)) - M.LAssailant = null - else - M.LAssailant = user - - else - M.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [M]/[M.ckey] with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""]" - msg_admin_attack("UNKNOWN shot [M] ([M.ckey]) with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""] (JMP)") - - if(!blocked) - if(D.reagents) - D.reagents.trans_to(M, 15) - M.visible_message("[M] is hit by the syringe!") - - else - var/mob/living/carbon/human/H = M - M.visible_message("[M] is hit by the syringe, but \his [H.wear_suit] blocked it!") // Fuck you validhunters. - - qdel(D) - break - if(D) - for(var/atom/A in D.loc) - if(A == user) continue - if(A.density) qdel(D) - - sleep(1) - - if (D) spawn(10) qdel(D) - - return - -/obj/item/weapon/gun/syringe/rapidsyringe - name = "rapid syringe gun" - desc = "A modification of the syringe gun design, using a rotating cylinder to store up to four syringes." - icon_state = "rapidsyringegun" - max_syringes = 4 - - -/obj/effect/syringe_gun_dummy - name = "" - desc = "" - icon = 'icons/obj/chemical.dmi' - icon_state = "null" - anchored = 1 - density = 0 - - New() - var/datum/reagents/R = new/datum/reagents(15) - reagents = R - R.my_atom = src + + + +/obj/item/weapon/gun/syringe + name = "syringe gun" + desc = "A spring loaded rifle designed to fit syringes, designed to incapacitate unruly patients from a distance." + icon = 'icons/obj/gun.dmi' + icon_state = "syringegun" + item_state = null + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') + w_class = 3.0 + throw_speed = 2 + throw_range = 10 + force = 4.0 + var/list/syringes = new/list() + var/max_syringes = 1 + starting_materials = list(MAT_IRON = 2000) + w_type = RECYK_METAL + +/obj/item/weapon/gun/syringe/examine(mob/user) + ..() + to_chat(user, "[syringes.len] / [max_syringes] syringes.") + +/obj/item/weapon/gun/syringe/attackby(obj/item/I as obj, mob/user as mob) + if(istype(I, /obj/item/weapon/reagent_containers/syringe)) + var/obj/item/weapon/reagent_containers/syringe/S = I + if(S.mode != 2)//SYRINGE_BROKEN in syringes.dm + if(syringes.len < max_syringes) + if(user.drop_item(I, src)) + syringes += I + to_chat(user, "You put the syringe in [src].") + to_chat(user, "[syringes.len] / [max_syringes] syringes.") + else + to_chat(user, "[src] cannot hold more syringes.") + else + to_chat(user, "This syringe is broken!") + + return 1 // Avoid calling the syringe's afterattack() + +/obj/item/weapon/gun/syringe/afterattack(obj/target, mob/user , flag) + if(/*!isturf(target.loc) || */target == user) return + ..() + +/obj/item/weapon/gun/syringe/can_fire() + return syringes.len + +/obj/item/weapon/gun/syringe/can_hit(var/mob/living/target as mob, var/mob/living/user as mob) + return 1 //SHOOT AND LET THE GOD GUIDE IT (probably will hit a wall anyway) + +/obj/item/weapon/gun/syringe/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0) + if(syringes.len) + if(M_CLUMSY in user.mutations) + if(prob(50)) + to_chat(user, "You accidentally shoot yourself!") + var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] + if((!S) || (!S.reagents)) + to_chat(user, "Thankfully, nothing happens.") + return + syringes -= S + S.reagents.trans_to(user, S.reagents.total_volume) + qdel(S) + return + + spawn(0) fire_syringe(target,user) + else + to_chat(user, "[src] is empty.") + +/obj/item/weapon/gun/syringe/proc/fire_syringe(atom/target, mob/user) + if (locate (/obj/structure/table, src.loc)) + return + else + var/turf/trg = get_turf(target) + var/obj/effect/syringe_gun_dummy/D = new/obj/effect/syringe_gun_dummy(get_turf(src)) + var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] + if((!S) || (!S.reagents)) //ho boy! wot runtimes! + return + S.reagents.trans_to(D, S.reagents.total_volume) + syringes -= S + qdel(S) + S = null + D.icon_state = "syringeproj" + D.name = "syringe" + playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1) + log_attack("[user.name] ([user.ckey]) fired \the [src] at [target] [ismob(target) ? "([target:ckey])" : ""] ([target.x],[target.y],[target.z])" ) + for(var/i=0, i<6, i++) + if(!D) break + if(D.loc == trg) break + step_towards(D,trg) + + if(D) + for(var/mob/living/carbon/M in D.loc) + if(!istype(M,/mob/living/carbon)) continue + if(M == user) continue + var/blocked = 0 + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species && (H.species.chem_flags & NO_INJECT)) + H.visible_message("\The [D] bounces harmlessly off of [H].", "\The [D] bounces off you harmlessly and breaks as it hits the ground.") + qdel(D) + return + + blocked = istype(H.wear_suit, /obj/item/clothing/suit/space) // Block the syringe if the guy's wearing a spess suit. + //Syringe gun attack logging by Yvarov + var/R + if(D.reagents) + for(var/datum/reagent/A in D.reagents.reagent_list) + R += A.id + " (" + R += num2text(A.volume) + ")," + if (istype(M, /mob)) + M.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] shot [M]/[M.ckey] with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""]" + user.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] shot [M]/[M.ckey] with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""]" + msg_admin_attack("[user] ([user.ckey]) shot [M] ([M.ckey]) with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""] (JMP)") + if(!iscarbon(user)) + M.LAssailant = null + else + M.LAssailant = user + + else + M.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [M]/[M.ckey] with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""]" + msg_admin_attack("UNKNOWN shot [M] ([M.ckey]) with a syringegun ([R]) [blocked ? "\[BLOCKED\]" : ""] (JMP)") + + if(!blocked) + if(D.reagents) + D.reagents.trans_to(M, 15) + M.visible_message("[M] is hit by the syringe!") + + else + var/mob/living/carbon/human/H = M + M.visible_message("[M] is hit by the syringe, but \his [H.wear_suit] blocked it!") // Fuck you validhunters. + + qdel(D) + break + if(D) + for(var/atom/A in D.loc) + if(A == user) continue + if(A.density) qdel(D) + + sleep(1) + + if (D) spawn(10) qdel(D) + + return + +/obj/item/weapon/gun/syringe/rapidsyringe + name = "rapid syringe gun" + desc = "A modification of the syringe gun design, using a rotating cylinder to store up to four syringes." + icon_state = "rapidsyringegun" + max_syringes = 4 + + +/obj/effect/syringe_gun_dummy + name = "" + desc = "" + icon = 'icons/obj/chemical.dmi' + icon_state = "null" + anchored = 1 + density = 0 + + New() + var/datum/reagents/R = new/datum/reagents(15) + reagents = R + R.my_atom = src diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 767eb873992..15432cf3a76 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -1,446 +1,446 @@ -//conveyor2 is pretty much like the original, except it supports corners, but not diverters. -//note that corner pieces transfer stuff clockwise when running forward, and anti-clockwise backwards. - -// May need to be increased. -#define CONVEYOR_CONTROL_RANGE 30 - -/obj/machinery/conveyor - icon = 'icons/obj/recycling.dmi' - icon_state = "conveyor0" - name = "conveyor belt" - desc = "A conveyor belt." - anchored = 1 - - var/operating = 0 // 1 if running forward, -1 if backwards, 0 if off - var/operable = 1 // true if can operate (no broken segments in this belt run) - var/in_reverse = 0 // Swap forwards/reverse dirs. (Good for diagonals) - var/forwards // this is the default (forward) direction, set by the map dir - var/backwards // hopefully self-explanatory - var/movedir // the actual direction to move stuff in - - var/list/affecting // the list of all items that will be moved this ptick - var/id_tag = "" // the control ID - must match controller ID - - var/frequency = 1367 - var/datum/radio_frequency/radio_connection - - var/max_moved = 25 - - machine_flags = SCREWTOGGLE | CROWDESTROY | MULTITOOL_MENU - -/obj/machinery/conveyor/centcom_auto - id_tag = "round_end_belt" - -// Auto conveyour is always on unless unpowered - -/obj/machinery/conveyor/auto/New(loc, newdir) - ..(loc, newdir) - operating = 1 - setmove() - -/obj/machinery/conveyor/auto/update() - if(stat & BROKEN) - icon_state = "conveyor-broken" - operating = 0 - return - else if(!operable) - operating = 0 - else if(stat & NOPOWER) - operating = 0 - else - operating = 1 - icon_state = "conveyor[operating]" - - - -/obj/machinery/conveyor/initialize() - if(frequency) - set_frequency(frequency) - update() - -/obj/machinery/conveyor/proc/set_frequency(var/new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_CONVEYORS) - -/obj/machinery/conveyor/receive_signal(datum/signal/signal) - if(!signal || signal.encryption) return - - if(id_tag != signal.data["tag"] || !signal.data["command"]) return - switch(signal.data["command"]) - if("forward") - operating = 1 - setmove() - return 1 - if("reverse") - operating = -1 - setmove() - return 1 - if("stop") - operating = 0 - update() - return 1 - else - testing("Got unknown command \"[signal.data["command"]]\" from [src]!") - - -/* - * Create a conveyor. - */ -/obj/machinery/conveyor/New(loc, newdir = null, building = 0) - . = ..(loc) - - //Gotta go fast! - machines -= src - fast_machines += src - - if(newdir) - dir = newdir - - component_parts = newlist(/obj/item/weapon/circuitboard/conveyor) - - updateConfig(!building) - -/obj/machinery/conveyor/proc/updateConfig(var/startup=0) - switch(dir) - if(NORTH) - forwards = NORTH - backwards = SOUTH - if(SOUTH) - forwards = SOUTH - backwards = NORTH - if(EAST) - forwards = EAST - backwards = WEST - if(WEST) - forwards = WEST - backwards = EAST - if(NORTHEAST) - forwards = EAST - backwards = SOUTH - if(NORTHWEST) - forwards = SOUTH - backwards = WEST - if(SOUTHEAST) - forwards = NORTH - backwards = EAST - if(SOUTHWEST) - forwards = WEST - backwards = NORTH - - if(in_reverse) - var/next_backwards=forwards - forwards=backwards - backwards=next_backwards - - if(!startup) // Need to wait for the radio_controller to wake up. - initialize() - -/obj/machinery/conveyor/proc/setmove() - if(operating == 1) - movedir = forwards - else - movedir = backwards - update() - -/obj/machinery/conveyor/proc/update() - if(stat & BROKEN) - icon_state = "conveyor-broken" - operating = 0 - return - if(!operable) - operating = 0 - if(stat & NOPOWER) - operating = 0 - var/disp_op = operating - if(in_reverse && disp_op!=0) - disp_op = -operating - icon_state = "conveyor[disp_op]" - - // machine process - // move items to the target location -/obj/machinery/conveyor/process() - if(stat & (BROKEN | NOPOWER)) - return - if(!operating) - return - use_power(100) - - affecting = loc.contents - src // moved items will be all in loc - spawn(1) // slight delay to prevent infinite propagation due to map order //TODO: please no spawn() in process(). It's a very bad idea - var/items_moved = 0 - for(var/atom/movable/A in affecting) - if(!A.anchored) - if(A.loc == src.loc) // prevents the object from being affected if it's not currently here. - step(A,movedir) - items_moved++ - if(items_moved >= max_moved) - break - -/obj/machinery/conveyor/togglePanelOpen(var/obj/item/toggle_item, mob/user) - if(operating) - to_chat(user, "You can't reach \the [src]'s panel through the moving machinery.") - return -1 - return ..() - -/obj/machinery/conveyor/crowbarDestroy(mob/user) - if(operating) - to_chat(user, "You can't reach \the [src]'s panel through the moving machinery.") - return -1 - return ..() - -// attack with item, place item on conveyor -/obj/machinery/conveyor/attackby(var/obj/item/W, mob/user) - . = ..() - if(.) - return . - user.drop_item(W, src.loc) - return 0 - -/obj/machinery/conveyor/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - //var/obj/item/device/multitool/P = get_multitool(user) - var/dis_id_tag="-----" - if(id_tag!=null && id_tag!="") - dis_id_tag=id_tag - return {" - "} - - -/obj/machinery/conveyor/multitool_topic(var/mob/user,var/list/href_list,var/obj/O) - . = ..() - if(.) return . - if("setdir" in href_list) - operating=0 - dir=text2num(href_list["setdir"]) - updateConfig() - return MT_UPDATE - if("reverse" in href_list) - operating=0 - in_reverse=!in_reverse - updateConfig() - return MT_UPDATE -// attack with hand, move pulled object onto conveyor -/obj/machinery/conveyor/attack_hand(mob/user as mob) - user.Move_Pulled(src) - - -// make the conveyor broken -// also propagate inoperability to any connected conveyor with the same ID -/obj/machinery/conveyor/proc/broken() - stat |= BROKEN - update() - - /* - var/obj/machinery/conveyor/C = locate() in get_step(src, dir) - if(C) - C.set_operable(dir, id, 0) - - C = locate() in get_step(src, turn(dir,180)) - if(C) - C.set_operable(turn(dir,180), id, 0) - */ - - -//set the operable var if ID matches, propagating in the given direction - -/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op) - - - if(id_tag != match_id) - return - operable = op - - update() - var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir) - if(C) - C.set_operable(stepdir, id_tag, op) - -/* -/obj/machinery/conveyor/verb/destroy() - set src in view() - src.broken() -*/ - -/obj/machinery/conveyor/power_change() - ..() - update() - -// the conveyor control switch -// -// - -/obj/machinery/conveyor_switch - name = "conveyor switch" - desc = "A conveyor control switch." - icon = 'icons/obj/recycling.dmi' - icon_state = "switch-off" - var/position = 0 // 0 off, -1 reverse, 1 forward - var/last_pos = -1 // last direction setting - var/convdir = 0 // lock to one direction. -1 = reverse, 0 = not locked, 1 = forward - var/operated = 1 // true if just operated - - var/id_tag = "" // must match conveyor IDs to control them - - var/frequency = 1367 - var/datum/radio_frequency/radio_connection - machine_flags = MULTITOOL_MENU - - anchored = 1 - -/obj/machinery/conveyor_switch/oneway // Kept in for mapping legacy because I am too lazy to actually fix the maps. - -/obj/machinery/conveyor_switch/receive_signal(datum/signal/signal) - if(!signal || signal.encryption) return - if(src == signal.source) return - - if(id_tag != signal.data["tag"] || !signal.data["command"]) return - if(!convdir) - switch(signal.data["command"]) - if("forward") - position = 1 - last_pos = 0 - if("reverse") - position = -1 - last_pos = 0 - if("stop") - last_pos = position - position = 0 - else - testing("Got unknown command \"[signal.data["command"]]\" from [src]!") - return - else - switch(signal.data["command"]) - if("forward") - if(convdir==1) - position = 1 - if("reverse") - if(convdir==-1) - position = -1 - if("stop") - position = 0 - else - testing("Got unknown command \"[signal.data["command"]]\" from [src]!") - return - update() - -/obj/machinery/conveyor_switch/New() - ..() - update() - spawn(5) // allow map load - updateConfig() - -/obj/machinery/conveyor_switch/proc/updateConfig() - //initialize() - -// update the icon depending on the position - -/obj/machinery/conveyor_switch/proc/update() - if(position<0) - icon_state = "switch-rev" - else if(position>0) - icon_state = "switch-fwd" - else - icon_state = "switch-off" - -/obj/machinery/conveyor_switch/initialize() - if(frequency) - set_frequency(frequency) - update() - -/obj/machinery/conveyor_switch/proc/set_frequency(var/new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_CONVEYORS) - -// attack with hand, switch position -/obj/machinery/conveyor_switch/attack_hand(mob/user) - if(isobserver(usr) && !canGhostWrite(user,src,"toggled")) - to_chat(usr, "Nope.") - return 0 - if(!convdir) - if(position == 0) - if(last_pos < 0) - position = 1 - last_pos = 0 - send_command("forward") - else - position = -1 - last_pos = 0 - send_command("reverse") - else - last_pos = position - position = 0 - send_command("stop") - else - if(position == 0) - position = convdir - send_command(convdir==1?"forward":"reverse") - else - position = 0 - send_command("stop") - - update() - -/obj/machinery/conveyor_switch/proc/send_command(var/command) - if(radio_connection) - var/datum/signal/signal = getFromPool(/datum/signal) - signal.source=src - signal.transmission_method = 1 //radio signal - signal.data["tag"] = id_tag - signal.data["timestamp"] = world.time - - signal.data["command"] = command - - radio_connection.post_signal(src, signal, range = CONVEYOR_CONTROL_RANGE) - -/obj/machinery/conveyor_switch/attackby(var/obj/item/W, mob/user) - . = ..() - if(.) - return . - if(istype(W, /obj/item/weapon/wrench)) - to_chat(user, "Deconstructing \the [src]...") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - if(do_after(user, src,50)) - to_chat(user, "You disassemble \the [src].") - var/turf/T=get_turf(src) - new /obj/item/device/assembly/signaler(T) - new /obj/item/stack/rods(T,1) - qdel(src) - return 1 - -/obj/machinery/conveyor_switch/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) - var/dis_id_tag="-----" - if(id_tag!=null && id_tag!="") - dis_id_tag=id_tag - return {" - "} - -/obj/machinery/conveyor_switch/multitool_topic(var/mob/user,var/list/href_list,var/obj/O) - . = ..() - if(.) return - if("setconvdir" in href_list) - convdir = text2num(href_list["setconvdir"]) - updateConfig() - return MT_UPDATE +//conveyor2 is pretty much like the original, except it supports corners, but not diverters. +//note that corner pieces transfer stuff clockwise when running forward, and anti-clockwise backwards. + +// May need to be increased. +#define CONVEYOR_CONTROL_RANGE 30 + +/obj/machinery/conveyor + icon = 'icons/obj/recycling.dmi' + icon_state = "conveyor0" + name = "conveyor belt" + desc = "A conveyor belt." + anchored = 1 + + var/operating = 0 // 1 if running forward, -1 if backwards, 0 if off + var/operable = 1 // true if can operate (no broken segments in this belt run) + var/in_reverse = 0 // Swap forwards/reverse dirs. (Good for diagonals) + var/forwards // this is the default (forward) direction, set by the map dir + var/backwards // hopefully self-explanatory + var/movedir // the actual direction to move stuff in + + var/list/affecting // the list of all items that will be moved this ptick + var/id_tag = "" // the control ID - must match controller ID + + var/frequency = 1367 + var/datum/radio_frequency/radio_connection + + var/max_moved = 25 + + machine_flags = SCREWTOGGLE | CROWDESTROY | MULTITOOL_MENU + +/obj/machinery/conveyor/centcom_auto + id_tag = "round_end_belt" + +// Auto conveyour is always on unless unpowered + +/obj/machinery/conveyor/auto/New(loc, newdir) + ..(loc, newdir) + operating = 1 + setmove() + +/obj/machinery/conveyor/auto/update() + if(stat & BROKEN) + icon_state = "conveyor-broken" + operating = 0 + return + else if(!operable) + operating = 0 + else if(stat & NOPOWER) + operating = 0 + else + operating = 1 + icon_state = "conveyor[operating]" + + + +/obj/machinery/conveyor/initialize() + if(frequency) + set_frequency(frequency) + update() + +/obj/machinery/conveyor/proc/set_frequency(var/new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CONVEYORS) + +/obj/machinery/conveyor/receive_signal(datum/signal/signal) + if(!signal || signal.encryption) return + + if(id_tag != signal.data["tag"] || !signal.data["command"]) return + switch(signal.data["command"]) + if("forward") + operating = 1 + setmove() + return 1 + if("reverse") + operating = -1 + setmove() + return 1 + if("stop") + operating = 0 + update() + return 1 + else + testing("Got unknown command \"[signal.data["command"]]\" from [src]!") + + +/* + * Create a conveyor. + */ +/obj/machinery/conveyor/New(loc, newdir = null, building = 0) + . = ..(loc) + + //Gotta go fast! + machines -= src + fast_machines += src + + if(newdir) + dir = newdir + + component_parts = newlist(/obj/item/weapon/circuitboard/conveyor) + + updateConfig(!building) + +/obj/machinery/conveyor/proc/updateConfig(var/startup=0) + switch(dir) + if(NORTH) + forwards = NORTH + backwards = SOUTH + if(SOUTH) + forwards = SOUTH + backwards = NORTH + if(EAST) + forwards = EAST + backwards = WEST + if(WEST) + forwards = WEST + backwards = EAST + if(NORTHEAST) + forwards = EAST + backwards = SOUTH + if(NORTHWEST) + forwards = SOUTH + backwards = WEST + if(SOUTHEAST) + forwards = NORTH + backwards = EAST + if(SOUTHWEST) + forwards = WEST + backwards = NORTH + + if(in_reverse) + var/next_backwards=forwards + forwards=backwards + backwards=next_backwards + + if(!startup) // Need to wait for the radio_controller to wake up. + initialize() + +/obj/machinery/conveyor/proc/setmove() + if(operating == 1) + movedir = forwards + else + movedir = backwards + update() + +/obj/machinery/conveyor/proc/update() + if(stat & BROKEN) + icon_state = "conveyor-broken" + operating = 0 + return + if(!operable) + operating = 0 + if(stat & NOPOWER) + operating = 0 + var/disp_op = operating + if(in_reverse && disp_op!=0) + disp_op = -operating + icon_state = "conveyor[disp_op]" + + // machine process + // move items to the target location +/obj/machinery/conveyor/process() + if(stat & (BROKEN | NOPOWER)) + return + if(!operating) + return + use_power(100) + + affecting = loc.contents - src // moved items will be all in loc + spawn(1) // slight delay to prevent infinite propagation due to map order //TODO: please no spawn() in process(). It's a very bad idea + var/items_moved = 0 + for(var/atom/movable/A in affecting) + if(!A.anchored) + if(A.loc == src.loc) // prevents the object from being affected if it's not currently here. + step(A,movedir) + items_moved++ + if(items_moved >= max_moved) + break + +/obj/machinery/conveyor/togglePanelOpen(var/obj/item/toggle_item, mob/user) + if(operating) + to_chat(user, "You can't reach \the [src]'s panel through the moving machinery.") + return -1 + return ..() + +/obj/machinery/conveyor/crowbarDestroy(mob/user) + if(operating) + to_chat(user, "You can't reach \the [src]'s panel through the moving machinery.") + return -1 + return ..() + +// attack with item, place item on conveyor +/obj/machinery/conveyor/attackby(var/obj/item/W, mob/user) + . = ..() + if(.) + return . + user.drop_item(W, src.loc) + return 0 + +/obj/machinery/conveyor/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + //var/obj/item/device/multitool/P = get_multitool(user) + var/dis_id_tag="-----" + if(id_tag!=null && id_tag!="") + dis_id_tag=id_tag + return {" + "} + + +/obj/machinery/conveyor/multitool_topic(var/mob/user,var/list/href_list,var/obj/O) + . = ..() + if(.) return . + if("setdir" in href_list) + operating=0 + dir=text2num(href_list["setdir"]) + updateConfig() + return MT_UPDATE + if("reverse" in href_list) + operating=0 + in_reverse=!in_reverse + updateConfig() + return MT_UPDATE +// attack with hand, move pulled object onto conveyor +/obj/machinery/conveyor/attack_hand(mob/user as mob) + user.Move_Pulled(src) + + +// make the conveyor broken +// also propagate inoperability to any connected conveyor with the same ID +/obj/machinery/conveyor/proc/broken() + stat |= BROKEN + update() + + /* + var/obj/machinery/conveyor/C = locate() in get_step(src, dir) + if(C) + C.set_operable(dir, id, 0) + + C = locate() in get_step(src, turn(dir,180)) + if(C) + C.set_operable(turn(dir,180), id, 0) + */ + + +//set the operable var if ID matches, propagating in the given direction + +/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op) + + + if(id_tag != match_id) + return + operable = op + + update() + var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir) + if(C) + C.set_operable(stepdir, id_tag, op) + +/* +/obj/machinery/conveyor/verb/destroy() + set src in view() + src.broken() +*/ + +/obj/machinery/conveyor/power_change() + ..() + update() + +// the conveyor control switch +// +// + +/obj/machinery/conveyor_switch + name = "conveyor switch" + desc = "A conveyor control switch." + icon = 'icons/obj/recycling.dmi' + icon_state = "switch-off" + var/position = 0 // 0 off, -1 reverse, 1 forward + var/last_pos = -1 // last direction setting + var/convdir = 0 // lock to one direction. -1 = reverse, 0 = not locked, 1 = forward + var/operated = 1 // true if just operated + + var/id_tag = "" // must match conveyor IDs to control them + + var/frequency = 1367 + var/datum/radio_frequency/radio_connection + machine_flags = MULTITOOL_MENU + + anchored = 1 + +/obj/machinery/conveyor_switch/oneway // Kept in for mapping legacy because I am too lazy to actually fix the maps. + +/obj/machinery/conveyor_switch/receive_signal(datum/signal/signal) + if(!signal || signal.encryption) return + if(src == signal.source) return + + if(id_tag != signal.data["tag"] || !signal.data["command"]) return + if(!convdir) + switch(signal.data["command"]) + if("forward") + position = 1 + last_pos = 0 + if("reverse") + position = -1 + last_pos = 0 + if("stop") + last_pos = position + position = 0 + else + testing("Got unknown command \"[signal.data["command"]]\" from [src]!") + return + else + switch(signal.data["command"]) + if("forward") + if(convdir==1) + position = 1 + if("reverse") + if(convdir==-1) + position = -1 + if("stop") + position = 0 + else + testing("Got unknown command \"[signal.data["command"]]\" from [src]!") + return + update() + +/obj/machinery/conveyor_switch/New() + ..() + update() + spawn(5) // allow map load + updateConfig() + +/obj/machinery/conveyor_switch/proc/updateConfig() + //initialize() + +// update the icon depending on the position + +/obj/machinery/conveyor_switch/proc/update() + if(position<0) + icon_state = "switch-rev" + else if(position>0) + icon_state = "switch-fwd" + else + icon_state = "switch-off" + +/obj/machinery/conveyor_switch/initialize() + if(frequency) + set_frequency(frequency) + update() + +/obj/machinery/conveyor_switch/proc/set_frequency(var/new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CONVEYORS) + +// attack with hand, switch position +/obj/machinery/conveyor_switch/attack_hand(mob/user) + if(isobserver(usr) && !canGhostWrite(user,src,"toggled")) + to_chat(usr, "Nope.") + return 0 + if(!convdir) + if(position == 0) + if(last_pos < 0) + position = 1 + last_pos = 0 + send_command("forward") + else + position = -1 + last_pos = 0 + send_command("reverse") + else + last_pos = position + position = 0 + send_command("stop") + else + if(position == 0) + position = convdir + send_command(convdir==1?"forward":"reverse") + else + position = 0 + send_command("stop") + + update() + +/obj/machinery/conveyor_switch/proc/send_command(var/command) + if(radio_connection) + var/datum/signal/signal = getFromPool(/datum/signal) + signal.source=src + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + + signal.data["command"] = command + + radio_connection.post_signal(src, signal, range = CONVEYOR_CONTROL_RANGE) + +/obj/machinery/conveyor_switch/attackby(var/obj/item/W, mob/user) + . = ..() + if(.) + return . + if(istype(W, /obj/item/weapon/wrench)) + to_chat(user, "Deconstructing \the [src]...") + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + if(do_after(user, src,50)) + to_chat(user, "You disassemble \the [src].") + var/turf/T=get_turf(src) + new /obj/item/device/assembly/signaler(T) + new /obj/item/stack/rods(T,1) + qdel(src) + return 1 + +/obj/machinery/conveyor_switch/multitool_menu(var/mob/user,var/obj/item/device/multitool/P) + var/dis_id_tag="-----" + if(id_tag!=null && id_tag!="") + dis_id_tag=id_tag + return {" + "} + +/obj/machinery/conveyor_switch/multitool_topic(var/mob/user,var/list/href_list,var/obj/O) + . = ..() + if(.) return + if("setconvdir" in href_list) + convdir = text2num(href_list["setconvdir"]) + updateConfig() + return MT_UPDATE diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm index 00d22bd2f14..9cb6b1fe165 100644 --- a/code/modules/recycling/disposal-construction.dm +++ b/code/modules/recycling/disposal-construction.dm @@ -1,278 +1,278 @@ -// Disposal pipe construction -// This is the pipe that you drag around, not the attached ones. - -/obj/structure/disposalconstruct - - name = "disposal pipe segment" - desc = "A huge pipe segment used for constructing disposal systems." - icon = 'icons/obj/pipes/disposal.dmi' - icon_state = "conpipe-s" - anchored = 0 - density = 0 - pressure_resistance = 5*ONE_ATMOSPHERE - starting_materials = list(MAT_IRON = 1850) - w_type = RECYK_METAL - level = 2 - var/ptype = 0 - // 0=straight, 1=bent, 2=junction-j1, 3=junction-j2, 4=junction-y, 5=trunk, 6=disposal bin, 7=outlet, 8=inlet - - var/dpdir = 0 // directions as disposalpipe - var/base_state = "pipe-s" - - // update iconstate and dpdir due to dir and type - proc/update() - var/flip = turn(dir, 180) - var/left = turn(dir, 90) - var/right = turn(dir, -90) - - switch(ptype) - if(0) - base_state = "pipe-s" - dpdir = dir | flip - if(1) - base_state = "pipe-c" - dpdir = dir | right - if(2) - base_state = "pipe-j1" - dpdir = dir | right | flip - if(3) - base_state = "pipe-j2" - dpdir = dir | left | flip - if(4) - base_state = "pipe-y" - dpdir = dir | left | right - if(5) - base_state = "pipe-t" - dpdir = dir - // disposal bin has only one dir, thus we don't need to care about setting it - if(6) - if(anchored) - base_state = "disposal" - else - base_state = "condisposal" - - if(7) - base_state = "outlet" - dpdir = dir - - if(8) - base_state = "intake" - dpdir = dir - - if(9, 11) - base_state = "pipe-j1s" - dpdir = dir | right | flip - - if(10, 12) - base_state = "pipe-j2s" - dpdir = dir | left | flip - - if(ptype<6 || ptype>8) - icon_state = "con[base_state]" - else - icon_state = base_state - - if(invisibility) // if invisible, fade icon - icon -= rgb(0,0,0,128) - - // hide called by levelupdate if turf intact status changes - // change visibility status and force update of icon - hide(var/intact) - invisibility = (intact && level==1) ? 101: 0 // hide if floor is intact - update() - - - // flip and rotate verbs - verb/rotate() - set name = "Rotate Pipe" - set category = "Object" - set src in view(1) - - if(usr.isUnconscious()) - return - - if(anchored) - to_chat(usr, "You must unfasten the pipe before rotating it.") - return - - dir = turn(dir, -90) - update() - - verb/flip() - set name = "Flip Pipe" - set category = "Object" - set src in view(1) - if(usr.isUnconscious()) - return - - if(anchored) - to_chat(usr, "You must unfasten the pipe before flipping it.") - return - - dir = turn(dir, 180) - switch(ptype) - if(2) - ptype = 3 - if(3) - ptype = 2 - if(9) - ptype = 10 - if(10) - ptype = 9 - if(11) - ptype = 12 - if(12) - ptype = 11 - - update() - - // returns the type path of disposalpipe corresponding to this item dtype - proc/dpipetype() - switch(ptype) - if(0,1) - return /obj/structure/disposalpipe/segment - if(2,3,4) - return /obj/structure/disposalpipe/junction - if(5) - return /obj/structure/disposalpipe/trunk - if(6) - return /obj/machinery/disposal - if(7) - return /obj/structure/disposaloutlet - if(8) - return /obj/machinery/disposal/deliveryChute - if(9,10) - return /obj/structure/disposalpipe/sortjunction - if(11, 12) - return /obj/structure/disposalpipe/wrapsortjunction - return - - - - // attackby item - // wrench: (un)anchor - // weldingtool: convert to real pipe - - attackby(var/obj/item/I, var/mob/user) - var/nicetype = "pipe" - var/ispipe = 0 // Indicates if we should change the level of this pipe - src.add_fingerprint(user) - switch(ptype) - if(6) - nicetype = "disposal bin" - if(7) - nicetype = "disposal outlet" - if(8) - nicetype = "delivery chute" - if(9, 10) - nicetype = "sorting pipe" - ispipe = 1 - if(11, 12) - nicetype = "wrap sorting pipe" - ispipe = 1 - else - nicetype = "pipe" - ispipe = 1 - - var/turf/T = src.loc - if(T.intact) - to_chat(user, "You can only attach the [nicetype] if the floor plating is removed.") - return - - var/obj/structure/disposalpipe/CP = locate() in T - if(ptype>=6 && ptype <= 8) // Disposal or outlet - if(CP) // There's something there - if(!istype(CP,/obj/structure/disposalpipe/trunk) && !anchored) - to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.") - return - else // Nothing under, fuck. - if(!anchored) - to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.") - return - else - if(CP) - update() - var/pdir = CP.dpdir - if(istype(CP, /obj/structure/disposalpipe/broken)) - pdir = CP.dir - if(pdir & dpdir) - to_chat(user, "There is already a [nicetype] at that location.") - return - - - if(istype(I, /obj/item/weapon/wrench)) - if(anchored) - anchored = 0 - if(ispipe) - level = 2 - density = 0 - else - density = 1 - to_chat(user, "You detach the [nicetype] from the underfloor.") - else - anchored = 1 - if(ispipe) - level = 1 // We don't want disposal bins to disappear under the floors - density = 0 - else - density = 1 // We don't want disposal bins or outlets to go density 0 - to_chat(user, "You attach the [nicetype] to the underfloor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) - update() - - else if(istype(I, /obj/item/weapon/weldingtool)) - if(anchored) - var/obj/item/weapon/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) - to_chat(user, "Welding the [nicetype] in place.") - if(do_after(user, src, 20)) - if(!src || !W.isOn()) return - to_chat(user, "The [nicetype] has been welded in place!") - update() // TODO: Make this neat - if(ispipe) // Pipe - - var/pipetype = dpipetype() - var/obj/structure/disposalpipe/P = new pipetype(src.loc) - src.transfer_fingerprints_to(P) - P.base_icon_state = base_state - P.dir = dir - P.dpdir = dpdir - P.updateicon() - - //Needs some special treatment ;) - switch(ptype) - if(9, 10) - var/obj/structure/disposalpipe/sortjunction/SortP = P - SortP.updatedir() - if(11, 12) - var/obj/structure/disposalpipe/wrapsortjunction/sort_P = P - sort_P.update_dir() - - else if(ptype==6) // Disposal bin - var/obj/machinery/disposal/P = new /obj/machinery/disposal(src.loc) - src.transfer_fingerprints_to(P) - P.mode = 0 // start with pump off - - else if(ptype==7) // Disposal outlet - - var/obj/structure/disposaloutlet/P = new /obj/structure/disposaloutlet(src.loc) - src.transfer_fingerprints_to(P) - P.dir = dir - var/obj/structure/disposalpipe/trunk/Trunk = CP - Trunk.linked = P - - else if(ptype==8) // Disposal outlet - - var/obj/machinery/disposal/deliveryChute/P = new /obj/machinery/disposal/deliveryChute(src.loc) - src.transfer_fingerprints_to(P) - P.dir = dir - - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return - else - to_chat(user, "You need to attach it to the plating first!") - return +// Disposal pipe construction +// This is the pipe that you drag around, not the attached ones. + +/obj/structure/disposalconstruct + + name = "disposal pipe segment" + desc = "A huge pipe segment used for constructing disposal systems." + icon = 'icons/obj/pipes/disposal.dmi' + icon_state = "conpipe-s" + anchored = 0 + density = 0 + pressure_resistance = 5*ONE_ATMOSPHERE + starting_materials = list(MAT_IRON = 1850) + w_type = RECYK_METAL + level = 2 + var/ptype = 0 + // 0=straight, 1=bent, 2=junction-j1, 3=junction-j2, 4=junction-y, 5=trunk, 6=disposal bin, 7=outlet, 8=inlet + + var/dpdir = 0 // directions as disposalpipe + var/base_state = "pipe-s" + + // update iconstate and dpdir due to dir and type + proc/update() + var/flip = turn(dir, 180) + var/left = turn(dir, 90) + var/right = turn(dir, -90) + + switch(ptype) + if(0) + base_state = "pipe-s" + dpdir = dir | flip + if(1) + base_state = "pipe-c" + dpdir = dir | right + if(2) + base_state = "pipe-j1" + dpdir = dir | right | flip + if(3) + base_state = "pipe-j2" + dpdir = dir | left | flip + if(4) + base_state = "pipe-y" + dpdir = dir | left | right + if(5) + base_state = "pipe-t" + dpdir = dir + // disposal bin has only one dir, thus we don't need to care about setting it + if(6) + if(anchored) + base_state = "disposal" + else + base_state = "condisposal" + + if(7) + base_state = "outlet" + dpdir = dir + + if(8) + base_state = "intake" + dpdir = dir + + if(9, 11) + base_state = "pipe-j1s" + dpdir = dir | right | flip + + if(10, 12) + base_state = "pipe-j2s" + dpdir = dir | left | flip + + if(ptype<6 || ptype>8) + icon_state = "con[base_state]" + else + icon_state = base_state + + if(invisibility) // if invisible, fade icon + icon -= rgb(0,0,0,128) + + // hide called by levelupdate if turf intact status changes + // change visibility status and force update of icon + hide(var/intact) + invisibility = (intact && level==1) ? 101: 0 // hide if floor is intact + update() + + + // flip and rotate verbs + verb/rotate() + set name = "Rotate Pipe" + set category = "Object" + set src in view(1) + + if(usr.isUnconscious()) + return + + if(anchored) + to_chat(usr, "You must unfasten the pipe before rotating it.") + return + + dir = turn(dir, -90) + update() + + verb/flip() + set name = "Flip Pipe" + set category = "Object" + set src in view(1) + if(usr.isUnconscious()) + return + + if(anchored) + to_chat(usr, "You must unfasten the pipe before flipping it.") + return + + dir = turn(dir, 180) + switch(ptype) + if(2) + ptype = 3 + if(3) + ptype = 2 + if(9) + ptype = 10 + if(10) + ptype = 9 + if(11) + ptype = 12 + if(12) + ptype = 11 + + update() + + // returns the type path of disposalpipe corresponding to this item dtype + proc/dpipetype() + switch(ptype) + if(0,1) + return /obj/structure/disposalpipe/segment + if(2,3,4) + return /obj/structure/disposalpipe/junction + if(5) + return /obj/structure/disposalpipe/trunk + if(6) + return /obj/machinery/disposal + if(7) + return /obj/structure/disposaloutlet + if(8) + return /obj/machinery/disposal/deliveryChute + if(9,10) + return /obj/structure/disposalpipe/sortjunction + if(11, 12) + return /obj/structure/disposalpipe/wrapsortjunction + return + + + + // attackby item + // wrench: (un)anchor + // weldingtool: convert to real pipe + + attackby(var/obj/item/I, var/mob/user) + var/nicetype = "pipe" + var/ispipe = 0 // Indicates if we should change the level of this pipe + src.add_fingerprint(user) + switch(ptype) + if(6) + nicetype = "disposal bin" + if(7) + nicetype = "disposal outlet" + if(8) + nicetype = "delivery chute" + if(9, 10) + nicetype = "sorting pipe" + ispipe = 1 + if(11, 12) + nicetype = "wrap sorting pipe" + ispipe = 1 + else + nicetype = "pipe" + ispipe = 1 + + var/turf/T = src.loc + if(T.intact) + to_chat(user, "You can only attach the [nicetype] if the floor plating is removed.") + return + + var/obj/structure/disposalpipe/CP = locate() in T + if(ptype>=6 && ptype <= 8) // Disposal or outlet + if(CP) // There's something there + if(!istype(CP,/obj/structure/disposalpipe/trunk) && !anchored) + to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.") + return + else // Nothing under, fuck. + if(!anchored) + to_chat(user, "The [nicetype] requires a trunk underneath it in order to work.") + return + else + if(CP) + update() + var/pdir = CP.dpdir + if(istype(CP, /obj/structure/disposalpipe/broken)) + pdir = CP.dir + if(pdir & dpdir) + to_chat(user, "There is already a [nicetype] at that location.") + return + + + if(istype(I, /obj/item/weapon/wrench)) + if(anchored) + anchored = 0 + if(ispipe) + level = 2 + density = 0 + else + density = 1 + to_chat(user, "You detach the [nicetype] from the underfloor.") + else + anchored = 1 + if(ispipe) + level = 1 // We don't want disposal bins to disappear under the floors + density = 0 + else + density = 1 // We don't want disposal bins or outlets to go density 0 + to_chat(user, "You attach the [nicetype] to the underfloor.") + playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + update() + + else if(istype(I, /obj/item/weapon/weldingtool)) + if(anchored) + var/obj/item/weapon/weldingtool/W = I + if(W.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + to_chat(user, "Welding the [nicetype] in place.") + if(do_after(user, src, 20)) + if(!src || !W.isOn()) return + to_chat(user, "The [nicetype] has been welded in place!") + update() // TODO: Make this neat + if(ispipe) // Pipe + + var/pipetype = dpipetype() + var/obj/structure/disposalpipe/P = new pipetype(src.loc) + src.transfer_fingerprints_to(P) + P.base_icon_state = base_state + P.dir = dir + P.dpdir = dpdir + P.updateicon() + + //Needs some special treatment ;) + switch(ptype) + if(9, 10) + var/obj/structure/disposalpipe/sortjunction/SortP = P + SortP.updatedir() + if(11, 12) + var/obj/structure/disposalpipe/wrapsortjunction/sort_P = P + sort_P.update_dir() + + else if(ptype==6) // Disposal bin + var/obj/machinery/disposal/P = new /obj/machinery/disposal(src.loc) + src.transfer_fingerprints_to(P) + P.mode = 0 // start with pump off + + else if(ptype==7) // Disposal outlet + + var/obj/structure/disposaloutlet/P = new /obj/structure/disposaloutlet(src.loc) + src.transfer_fingerprints_to(P) + P.dir = dir + var/obj/structure/disposalpipe/trunk/Trunk = CP + Trunk.linked = P + + else if(ptype==8) // Disposal outlet + + var/obj/machinery/disposal/deliveryChute/P = new /obj/machinery/disposal/deliveryChute(src.loc) + src.transfer_fingerprints_to(P) + P.dir = dir + + qdel(src) + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + else + to_chat(user, "You need to attach it to the plating first!") + return diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 0452073fda0..ae99304cfce 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -1,1484 +1,1484 @@ -// Disposal bin -// Holds items for disposal into pipe system -// Draws air from turf, gradually charges internal reservoir -// Once full (~1 atm), uses air resv to flush items into the pipes -// Automatically recharges air (unless off), will flush when ready if pre-set -// Can hold items and human size things, no other draggables -// Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation -#define SEND_PRESSURE 0.05*ONE_ATMOSPHERE - -/obj/machinery/disposal - name = "disposal unit" - desc = "A pneumatic waste disposal unit." - icon = 'icons/obj/pipes/disposal.dmi' - icon_state = "disposal" - anchored = 1 - density = 1 - var/datum/gas_mixture/air_contents // internal reservoir - var/mode = 1 // item mode 0=off 1=charging 2=charged - var/flush = 0 // true if flush handle is pulled - var/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk - var/flushing = 0 // true if flushing in progress - var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush - var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush. - var/last_sound = 0 - -// create a new disposal -// find the attached trunk (if present) and init gas resvr. -/obj/machinery/disposal/New() - ..() - spawn(5) - for(var/obj/structure/disposalpipe/trunk/O in loc.contents)//This is more efficient than locate() - trunk = O - - if(trunk) - if(trunk.disposal != src) - trunk.disposal = src - - if(trunk.linked != trunk.disposal) - trunk.linked = trunk.disposal - else - mode = 0 - flush = 0 - - air_contents = new/datum/gas_mixture() - //gas.volume = 1.05 * CELLSTANDARD - update_icon() - -/obj/machinery/disposal/Destroy() - if(trunk) - if(trunk.disposal) - trunk.disposal = null - if(trunk.linked) - trunk.linked = null - - trunk = null - - ..() - -/obj/machinery/disposal/ex_act(var/severity,var/child=null) - var/child_severity=severity - if(!child) - child_severity++ - if(child_severity <= 3) - for(var/obj/O in contents) - O.ex_act(child_severity) - switch(severity) - if(2 to INFINITY) - if(prob(50)) - eject() - if(severity==2) - qdel(src) - if(1) - eject() - qdel(src) - - -// attack by item places it in to disposal -/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user) - if(stat & BROKEN || !I || !user) - return - - if(isrobot(user) && !istype(I, /obj/item/weapon/storage/bag/trash) && !istype(user,/mob/living/silicon/robot/mommi)) - return - src.add_fingerprint(user) - if(mode<=0) // It's off - if(istype(I, /obj/item/weapon/screwdriver)) - if(contents.len > 0) - to_chat(user, "Eject the items first!") - return - if(mode==0) // It's off but still not unscrewed - mode=-1 // Set it to doubleoff l0l - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You remove the screws around the power connection.") - return - else if(mode==-1) - mode=0 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You attach the screws around the power connection.") - return - else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1) - if(contents.len > 0) - to_chat(user, "Eject the items first!") - return - var/obj/item/weapon/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) - to_chat(user, "You start slicing the floorweld off the disposal unit.") - - if(do_after(user, src,20)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the disposal unit.") - var/obj/structure/disposalconstruct/C = new (src.loc) - src.transfer_fingerprints_to(C) - C.ptype = 6 // 6 = disposal unit - C.anchored = 1 - C.density = 1 - C.update_icon() - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(I, /obj/item/weapon/storage/bag/)) - var/obj/item/weapon/storage/bag/B = I - if(B.contents.len == 0) - if(user.drop_item(I, src)) - to_chat(user, "You throw away the empty [B].") - return - to_chat(user, "You empty the [B].") - B.mass_remove(src) - B.update_icon() - update_icon() - return - - var/obj/item/weapon/grab/G = I - if(istype(G)) // handle grabbed mob - if(ismob(G.affecting)) - var/mob/GM = G.affecting - user.attack_log += " [user]([user.ckey]) has attempted to put [GM]([GM.ckey]) in disposals." - GM.attack_log += " [user]([user.ckey]) has attempted to put [GM]([GM.ckey]) in disposals." - user.visible_message("[usr] starts putting [GM.name] into \the [src].", "You start putting \the [GM.name] into the [src].", "You hear some clunking.") - if(do_after(usr, src, 20)) - if (GM.client) - GM.client.perspective = EYE_PERSPECTIVE - GM.client.eye = src - GM.loc = src - user.visible_message("[GM.name] has been placed in \the [src] by [user].", "[GM.name] has been placed in \the [src] by you.", "You hear a loud clunk.") - qdel(G) - log_attack("[usr] ([usr.ckey]) placed [GM] ([GM.ckey]) in a disposals unit.") - return - - if(!I) return - - if(user.drop_item(I, src)) - user.visible_message("[user.name] places \the [I] into the [src].", "You place \the [I] into the [src].") - - update_icon() - -// can breath normally in the disposal -/obj/machinery/disposal/alter_health() - return get_turf(src) - -// attempt to move while inside -/obj/machinery/disposal/relaymove(mob/user as mob) - if(user.stat || src.flushing) - return - src.go_out(user) - return - -// leave the disposal -/obj/machinery/disposal/proc/go_out(mob/user) - - - if (user.client) - user.client.eye = user.client.mob - user.client.perspective = MOB_PERSPECTIVE - user.loc = src.loc - update_icon() - return - - -// monkeys can only pull the flush lever -/obj/machinery/disposal/attack_paw(mob/user as mob) - if(stat & BROKEN) - return - - flush = !flush - update_icon() - return - -// ai as human but can't flush -/obj/machinery/disposal/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - ui_interact(user) - -// human interact with machine -/obj/machinery/disposal/attack_hand(mob/user as mob) - if(user && user.loc == src) - to_chat(usr, "You cannot reach the controls from inside.") - return - /* - if(mode==-1) - to_chat(usr, "The disposal units power is disabled.") - return - */ - src.add_fingerprint(user) - ui_interact(user) - -// user interaction -/obj/machinery/disposal/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/list/data[0] - - data["pressure"] = round(100 * air_contents.return_pressure() / (SEND_PRESSURE)) - data["flush"] = flush - data["mode"] = mode - data["isAI"] = isAI(user) - - // update the ui with data if it exists, returns null if no ui is passed/found or if force_open is 1/true - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "disposalsbin.tmpl", "Waste Disposal Unit", 430, 150) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // Make the UI auto-update. - ui.set_auto_update(1) - -// handle machine interaction -/obj/machinery/disposal/Topic(href, href_list) - if(usr.loc == src) - to_chat(usr, "You cannot reach the controls from inside.") - return - - if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1 - to_chat(usr, "The disposal units power is disabled.") - return - if(..()) - usr << browse(null, "window=disposal") - usr.unset_machine() - return 1 - else - src.add_fingerprint(usr) - usr.set_machine(src) - - if(href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=disposal") - return - - if(href_list["pump"]) - if(text2num(href_list["pump"])) - mode = 1 - else - mode = 0 - update_icon() - - if(href_list["handle"]) - flush = text2num(href_list["handle"]) - update_icon() - - if(href_list["eject"]) - eject() - - nanomanager.update_uis(src) - - return - -// eject the contents of the disposal unit -/obj/machinery/disposal/proc/eject() - for(var/atom/movable/AM in src) - AM.loc = src.loc - AM.pipe_eject(0) - update_icon() - -// update the icon & overlays to reflect mode & status -/obj/machinery/disposal/update_icon() - overlays.len = 0 - if(stat & BROKEN) - icon_state = "disposal-broken" - mode = 0 - flush = 0 - return - - // flush handle - if(flush) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-handle") - - // only handle is shown if no power - if(stat & NOPOWER || mode == -1) - return - - // check for items in disposal - occupied light - if(contents.len > 0) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-full") - - // charging and ready light - if(mode == 1) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-charge") - else if(mode == 2) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-ready") - -// timed process -// charge the gas reservoir and perform flush if ready -/obj/machinery/disposal/process() - if(stat & BROKEN) // nothing can happen if broken - return - - if(!air_contents) // Potentially causes a runtime otherwise (if this is really shitty, blame pete //Donkie) - return - - flush_count++ - if( flush_count >= flush_every_ticks ) - if( contents.len ) - if(mode == 2) - spawn(0) - feedback_inc("disposal_auto_flush",1) - flush() - flush_count = 0 - - src.updateDialog() - - if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power - spawn(0) - flush() - - if(stat & NOPOWER) // won't charge if no power - return - - use_power(100) // base power usage - - if(mode != 1) // if off or ready, no need to charge - return - - // otherwise charge - use_power(500) // charging power usage - - var/atom/L = loc // recharging from loc turf - - var/datum/gas_mixture/env = L.return_air() - var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure() - - if(env.temperature > 0) - var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = env.remove(transfer_moles) - air_contents.merge(removed) - - - // if full enough, switch to ready mode - if(air_contents.return_pressure() >= SEND_PRESSURE) - mode = 2 - update_icon() - return - -// perform a flush -/obj/machinery/disposal/proc/flush() - - - flushing = 1 - flick("[icon_state]-flush", src) - - var/wrapcheck = 0 - var/obj/structure/disposalholder/H = new() // virtual holder object which actually - // travels through the pipes. - for(var/obj/item/delivery/O in src) - wrapcheck = 1 - - if(wrapcheck == 1) - H.tomail = 1 - - - air_contents = new() // new empty gas resv. - - sleep(10) - if(last_sound < world.time + 1) - playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0) - last_sound = world.time - sleep(5) // wait for animation to finish - - - H.init(src) // copy the contents of disposer to holder - - H.start(src) // start the holder processing movement - flushing = 0 - // now reset disposal state - flush = 0 - if(mode == 2) // if was ready, - mode = 1 // switch to charging - update_icon() - return - - -// called when area power changes -/obj/machinery/disposal/power_change() - ..() // do default setting/reset of stat NOPOWER bit - update_icon() // update icon - return - - -// called when holder is expelled from a disposal -// should usually only occur if the pipe network is modified -/obj/machinery/disposal/proc/expel(var/obj/structure/disposalholder/H) - - - var/turf/target - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - if(H) // Somehow, someone managed to flush a window which broke mid-transit and caused the disposal to go in an infinite loop trying to expel null, hopefully this fixes it - H.active = 0 // Stop disposalholder's move() processing so we don't call the trunk's expel() too - for(var/atom/movable/AM in H) - target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5)) - - AM.loc = src.loc - AM.pipe_eject(0) - spawn(1) - if(AM) - AM.throw_at(target, 5, 1) - - H.vent_gas(loc) - qdel(H) - -/obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if (istype(mover,/obj/item) && mover.throwing) - var/obj/item/I = mover - if(istype(I, /obj/item/weapon/dummy) || istype(I, /obj/item/projectile)) - return - if(prob(75)) - I.loc = src - for(var/mob/M in viewers(src)) - M.show_message("\the [I] lands in \the [src].", 1) - else - for(var/mob/M in viewers(src)) - M.show_message("\the [I] bounces off of \the [src]'s rim!.", 1) - return 0 - else - return ..(mover, target, height, air_group) - -/obj/machinery/disposal/MouseDrop_T(atom/dropping, mob/user) - if(istype(user, /mob/living/silicon/ai)) - return - - if(!ismob(dropping)) - if(istype(dropping, /obj/item)) - if(!user.restrained() && user.canmove) - attackby(dropping, user) - - return - - var/locHolder = dropping.loc - var/mob/target = dropping - - if(target == user) - if(!user.restrained() && user.canmove) - target.visible_message("[target] starts climbing into the [src].", "You start climbing into the [src].") - else - return - else - if(isanimal(user)) - return // animals cannot put mobs other than themselves into disposal - - if(!user.restrained() && user.canmove) - if(target.locked_to) - return - - user.visible_message("[user] starts stuffing [target] into the [src].", "You start stuffing [target] into the [src].") - else - return - - if(!do_after(user, src, 20)) - return - - if(locHolder != target.loc) - return - - if(target == user) - if(!user.restrained() && user.canmove) - target.visible_message("[target] climbed into the [src].", "You climbed into the [src].") - else - return - else - if(!user.restrained() && user.canmove) - if(target.locked_to) - return - - user.visible_message("[user] stuffed [target] into the [src]!", "You stuffed [target] into the [src]!") - log_attack("[key_name(user)] placed [key_name(target)] in a disposals unit/([src]).") - else - return - - add_fingerprint(user) - - if(target.client) - target.client.perspective = EYE_PERSPECTIVE - target.client.eye = src - - target.loc = src - - update_icon() - -// virtual disposal object -// travels through pipes in lieu of actual items -// contents will be items flushed by the disposal -// this allows the gas flushed to be tracked - -/obj/structure/disposalholder - invisibility = 101 - var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point - var/active = 0 // true if the holder is moving, otherwise inactive - dir = 0 - var/count = 1000 //*** can travel 1000 steps before going inactive (in case of loops) - var/has_fat_guy = 0 // true if contains a fat person - var/destinationTag = "DISPOSALS"// changes if contains a delivery container - var/tomail = 0 //changes if contains wrapped package - var/hasmob = 0 //If it contains a mob - - - // initialize a holder from the contents of a disposal unit - proc/init(var/obj/machinery/disposal/D) - gas = D.air_contents// transfer gas resv. into holder object - - //Check for any living mobs trigger hasmob. - //hasmob effects whether the package goes to cargo or its tagged destination. - for(var/mob/living/M in D) - if(M && M.stat != 2) - hasmob = 1 - - //Checks 1 contents level deep. This means that players can be sent through disposals... - //...but it should require a second person to open the package. (i.e. person inside a wrapped locker) - for(var/obj/O in D) - if(O.contents) - for(var/mob/living/M in O.contents) - if(M && M.stat != 2) - hasmob = 1 - - // now everything inside the disposal gets put into the holder - // note AM since can contain mobs or objs - for(var/atom/movable/AM in D) - AM.forceMove(src) - if(istype(AM, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = AM - if((M_FAT in H.mutations) && (H.species && H.species.flags & CAN_BE_FAT)) // is a human and fat? - has_fat_guy = 1 // set flag on holder - if(istype(AM, /obj/item/delivery/large) && !hasmob) - var/obj/item/delivery/large/T = AM - src.destinationTag = T.sortTag - if(istype(AM, /obj/item/delivery) && !hasmob) - var/obj/item/delivery/T = AM - src.destinationTag = T.sortTag - - // start the movement process - // argument is the disposal unit the holder started in - proc/start(var/obj/machinery/disposal/D) - if(!D.trunk) - D.expel(src) // no trunk connected, so expel immediately - return - - forceMove(D.trunk) - active = 1 - dir = DOWN - spawn(1) - move() // spawn off the movement process - - // movement process, persists while holder is moving through pipes - proc/move() - var/obj/structure/disposalpipe/last - while(active) - /* vg edit - if(hasmob && prob(3)) - for(var/mob/living/H in src) - H.take_overall_damage(20, 0, "Blunt Trauma")//horribly maim any living creature jumping down disposals. c'est la vie - */ - - if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy - active = 0 - // find the fat guys - for(var/mob/living/carbon/human/H in src) - - break - sleep(1) // was 1 - if(!loc || isnull(loc)) - qdel(src) - return - - var/obj/structure/disposalpipe/curr = loc - last = curr - curr = curr.transfer(src) - if(!curr) - last.expel(src, loc, dir) - - // - if(!(count--)) - active = 0 - return - - - - // find the turf which should contain the next pipe - proc/nextloc() - return get_step(loc,dir) - - // find a matching pipe on a turf - proc/findpipe(var/turf/T) - - - if(!T) - return null - - var/fdir = turn(dir, 180) // flip the movement direction - for(var/obj/structure/disposalpipe/P in T) - if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir - return P - // if no matching pipe, return null - return null - - // merge two holder objects - // used when a a holder meets a stuck holder - proc/merge(var/obj/structure/disposalholder/other) - for(var/atom/movable/AM in other) - AM.forceMove(src) // move everything in other holder to this one - if(ismob(AM)) - var/mob/M = AM - if(M.client) // if a client mob, update eye to follow this holder - M.client.eye = src - - if(other.has_fat_guy) - has_fat_guy = 1 - qdel(other) - - - // called when player tries to move while in a pipe - relaymove(mob/user as mob) - if (user.stat) - return - if (src.loc) - for (var/mob/M in hearers(src.loc.loc)) - to_chat(M, "CLONG, clong!") - - playsound(get_turf(src), 'sound/effects/clang.ogg', 50, 0, 0) - - // called to vent all gas in holder to a location - proc/vent_gas(var/atom/location) - location.assume_air(gas) // vent all gas to turf - return - -// Disposal pipes - -/obj/structure/disposalpipe - icon = 'icons/obj/pipes/disposal.dmi' - name = "disposal pipe" - desc = "An underfloor disposal pipe." - anchored = 1 - density = 0 - - level = 1 // underfloor only - var/dpdir = 0 // bitmask of pipe directions - dir = 0 // dir will contain dominant direction for junction pipes - var/health = 10 // health points 0-10 - layer = 2.3 // slightly lower than wires and other pipes - var/base_icon_state // initial icon state on map - - // new pipe, set the icon_state as on map - New() - ..() - base_icon_state = icon_state - return - - - // pipe is deleted - // ensure if holder is present, it is expelled - Destroy() - var/obj/structure/disposalholder/H = locate() in src - if(H) - // holder was present - H.active = 0 - var/turf/T = src.loc - if(T.density) - // deleting pipe is inside a dense turf (wall) - // this is unlikely, but just dump out everything into the turf in case - - for(var/atom/movable/AM in H) - AM.forceMove(T) - AM.pipe_eject(0) - qdel(H) - ..() - return - - // otherwise, do normal expel from turf - if(H) - expel(H, T, 0) - ..() - - // returns the direction of the next pipe object, given the entrance dir - // by default, returns the bitmask of remaining directions - proc/nextdir(var/fromdir) - return dpdir & (~turn(fromdir, 180)) - - // transfer the holder through this pipe segment - // overriden for special behaviour - // - proc/transfer(var/obj/structure/disposalholder/H) - var/nextdir = nextdir(H.dir) - H.dir = nextdir - var/turf/T = H.nextloc() - var/obj/structure/disposalpipe/P = H.findpipe(T) - - if(P) - // find other holder in next loc, if inactive merge it with current - var/obj/structure/disposalholder/H2 = locate() in P - if(H2 && !H2.active) - H.merge(H2) - - H.forceMove(P) - else // if wasn't a pipe, then set loc to turf - H.forceMove(T) - return null - - return P - - - // update the icon_state to reflect hidden status - proc/update() - var/turf/T = src.loc - hide(T.intact && !istype(T,/turf/space)) // space never hides pipes - - // hide called by levelupdate if turf intact status changes - // change visibility status and force update of icon - hide(var/intact) - invisibility = intact ? 101: 0 // hide if floor is intact - updateicon() - - // update actual icon_state depending on visibility - // if invisible, append "f" to icon_state to show faded version - // this will be revealed if a T-scanner is used - // if visible, use regular icon_state - proc/updateicon() - if(invisibility) - icon_state = "[base_icon_state]f" - else - icon_state = base_icon_state - return - - - // expel the held objects into a turf - // called when there is a break in the pipe - // - - proc/expel(var/obj/structure/disposalholder/H, var/turf/T, var/direction) - - - var/turf/target - if(!T || isnull(T)) - T = loc - if(T.density) // dense ouput turf, so stop holder - H.active = 0 - H.forceMove(src) - return - if(T.intact && istype(T,/turf/simulated/floor)) //intact floor, pop the tile - var/turf/simulated/floor/F = T - //F.health = 100 - F.break_tile() - - if(direction) // direction is specified - if(istype(T, /turf/space)) // if ended in space, then range is unlimited - target = get_edge_target_turf(T, direction) - else // otherwise limit to 10 tiles - target = get_ranged_target_turf(T, direction, 10) - - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - if(H) - for(var/atom/movable/AM in H) - AM.forceMove(T) - AM.pipe_eject(direction) - spawn(1) - if(AM) - AM.throw_at(target, 100, 1) - H.vent_gas(T) - qdel(H) - - else // no specified direction, so throw in random direction - - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - if(H) - for(var/atom/movable/AM in H) - target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5)) - - AM.forceMove(T) - AM.pipe_eject(0) - spawn(1) - if(AM) - AM.throw_at(target, 5, 1) - - H.vent_gas(T) // all gas vent to turf - qdel(H) - - return - - // call to break the pipe - // will expel any holder inside at the time - // then delete the pipe - // remains : set to leave broken pipe pieces in place - proc/broken(var/remains = 0) - if(remains) - for(var/D in cardinal) - if(D & dpdir) - var/obj/structure/disposalpipe/broken/P = new(src.loc) - P.dir = D - - src.invisibility = 101 // make invisible (since we won't delete the pipe immediately) - var/obj/structure/disposalholder/H = locate() in src - if(H) - // holder was present - H.active = 0 - var/turf/T = src.loc - if(T.density) - // broken pipe is inside a dense turf (wall) - // this is unlikely, but just dump out everything into the turf in case - - for(var/atom/movable/AM in H) - AM.forceMove(T) - AM.pipe_eject(0) - qdel(H) - return - - // otherwise, do normal expel from turf - if(H) - expel(H, T, 0) - - spawn(2) // delete pipe after 2 ticks to ensure expel proc finished - qdel(src) - - - // pipe affected by explosion - ex_act(severity) - - switch(severity) - if(1.0) - broken(0) - return - if(2.0) - health -= rand(5,15) - healthcheck() - return - if(3.0) - health -= rand(0,15) - healthcheck() - return - - - // test health for brokenness - proc/healthcheck() - if(health < -2) - broken(0) - else if(health<1) - broken(1) - return - - //attack by item - //weldingtool: unfasten and convert to obj/disposalconstruct - - attackby(var/obj/item/I, var/mob/user) - - var/turf/T = src.loc - if(T.intact) - return // prevent interaction with T-scanner revealed pipes - src.add_fingerprint(user) - if(istype(I, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/W = I - - if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) - // check if anything changed over 2 seconds - var/turf/uloc = user.loc - var/atom/wloc = W.loc - to_chat(user, "Slicing the disposal pipe.") - sleep(30) - if(!W.isOn()) return - if(user.loc == uloc && wloc == W.loc) - welded() - else - to_chat(user, "You must stay still while welding the pipe.") - else - to_chat(user, "You need more welding fuel to cut the pipe.") - return - - // called when pipe is cut with welder - proc/welded() - - - var/obj/structure/disposalconstruct/C = new (src.loc) - switch(base_icon_state) - if("pipe-s") - C.ptype = 0 - if("pipe-c") - C.ptype = 1 - if("pipe-j1") - C.ptype = 2 - if("pipe-j2") - C.ptype = 3 - if("pipe-y") - C.ptype = 4 - if("pipe-t") - C.ptype = 5 - if("pipe-j1s") - C.ptype = 9 - if("pipe-j2s") - C.ptype = 10 - src.transfer_fingerprints_to(C) - C.change_dir(dir) - C.density = 0 - C.anchored = 1 - C.update() - - qdel(src) - -// *** TEST verb -//client/verb/dispstop() -// for(var/obj/structure/disposalholder/H in world) -// H.active = 0 - -// a straight or bent segment -/obj/structure/disposalpipe/segment - icon_state = "pipe-s" - -/obj/structure/disposalpipe/segment/New() - ..() - if(icon_state == "pipe-s") - dpdir = dir | turn(dir, 180) - else - dpdir = dir | turn(dir, -90) - - update() - -//a three-way junction with dir being the dominant direction -/obj/structure/disposalpipe/junction - icon_state = "pipe-j1" - -/obj/structure/disposalpipe/junction/New() - ..() - if(icon_state == "pipe-j1") - dpdir = dir | turn(dir, -90) | turn(dir,180) - else if(icon_state == "pipe-j2") - dpdir = dir | turn(dir, 90) | turn(dir,180) - else // pipe-y - dpdir = dir | turn(dir,90) | turn(dir, -90) - update() - return - -// next direction to move -// if coming in from secondary dirs, then next is primary dir -// if coming in from primary dir, then next is equal chance of other dirs - -/obj/structure/disposalpipe/junction/nextdir(var/fromdir) - var/flipdir = turn(fromdir, 180) - if(flipdir != dir) // came from secondary dir - return dir // so exit through primary - else // came from primary - // so need to choose either secondary exit - var/mask = ..(fromdir) - - // find a bit which is set - var/setbit = 0 - if(mask & NORTH) - setbit = NORTH - else if(mask & SOUTH) - setbit = SOUTH - else if(mask & EAST) - setbit = EAST - else - setbit = WEST - - if(prob(50)) // 50% chance to choose the found bit or the other one - return setbit - else - return mask & (~setbit) - -//a three-way junction that sorts objects -/obj/structure/disposalpipe/sortjunction - icon_state = "pipe-j1s" - var/sortType = 0 //Deprecated, here for legacy support. - var/sort_tag //Replacement of the above, more construction friendly. - - var/posdir = 0 - var/negdir = 0 - var/sortdir = 0 - -/obj/structure/disposalpipe/sortjunction/proc/updatedesc() - desc = "An underfloor disposal pipe with a package sorting mechanism." - if(sort_tag) - desc += "\nIt's tagged with [sort_tag]." - -/obj/structure/disposalpipe/sortjunction/proc/updatedir() - posdir = dir - negdir = turn(posdir, 180) - - if(icon_state == "pipe-j1s") - sortdir = turn(posdir, -90) - else - icon_state = "pipe-j2s" - sortdir = turn(posdir, 90) - - dpdir = sortdir | posdir | negdir - -/obj/structure/disposalpipe/sortjunction/New() - . = ..() - if(sortType && !sort_tag) - sort_tag = uppertext(DEFAULT_TAGGER_LOCATIONS[sortType]) - - updatedir() - updatedesc() - update() - -/obj/structure/disposalpipe/sortjunction/attackby(var/obj/item/I, var/mob/user) - if(istype(I, /obj/item/device/destTagger)) - var/obj/item/device/destTagger/O = I - - if(O.currTag)// Tag set - sort_tag = uppertext(O.destinations[O.currTag]) - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) - to_chat(user, "Changed filter to [sort_tag]") - updatedesc() - return 1 - - . = ..() - // next direction to move - // if coming in from negdir, then next is primary dir or sortdir - // if coming in from posdir, then flip around and go back to posdir - // if coming in from sortdir, go to posdir - -/obj/structure/disposalpipe/sortjunction/nextdir(var/fromdir, var/sortTag) - //var/flipdir = turn(fromdir, 180) - if(fromdir != sortdir) // probably came from the negdir - - if(sort_tag == sortTag) //if destination matches filtered type... - return sortdir // exit through sortdirection - else - return posdir - else // came from sortdir - // so go with the flow to positive direction - return posdir - -/obj/structure/disposalpipe/sortjunction/transfer(var/obj/structure/disposalholder/H) - var/nextdir = nextdir(H.dir, H.destinationTag) - H.dir = nextdir - var/turf/T = H.nextloc() - var/obj/structure/disposalpipe/P = H.findpipe(T) - - if(P) - // find other holder in next loc, if inactive merge it with current - var/obj/structure/disposalholder/H2 = locate() in P - if(H2 && !H2.active) - H.merge(H2) - - H.forceMove(P) - else // if wasn't a pipe, then set loc to turf - H.forceMove(T) - return - - return P - -////////////////// SortJunctionSubtypes////////////////// -//Box -/obj/structure/disposalpipe/sortjunction/Disposals - sortType = 1 - -/obj/structure/disposalpipe/sortjunction/Cargo - sortType = 2 - -/obj/structure/disposalpipe/sortjunction/QM - sortType = 3 - -/obj/structure/disposalpipe/sortjunction/Engineering - sortType = 4 - -/obj/structure/disposalpipe/sortjunction/CE - sortType = 5 - -/obj/structure/disposalpipe/sortjunction/Atmos - sortType = 6 - -/obj/structure/disposalpipe/sortjunction/Security - sortType = 7 - -/obj/structure/disposalpipe/sortjunction/HoS - sortType = 8 - -/obj/structure/disposalpipe/sortjunction/Medbay - sortType = 9 - -/obj/structure/disposalpipe/sortjunction/CMO - sortType = 10 - -/obj/structure/disposalpipe/sortjunction/Chemistry - sortType = 11 - -/obj/structure/disposalpipe/sortjunction/Research - sortType = 12 - -/obj/structure/disposalpipe/sortjunction/RD - sortType = 13 - -/obj/structure/disposalpipe/sortjunction/Robotics - sortType = 14 - -/obj/structure/disposalpipe/sortjunction/HoP - sortType = 15 - -/obj/structure/disposalpipe/sortjunction/Library - sortType = 16 - -/obj/structure/disposalpipe/sortjunction/Chapel - sortType = 17 - -/obj/structure/disposalpipe/sortjunction/Theatre - sortType = 18 - -/obj/structure/disposalpipe/sortjunction/Bar - sortType = 19 - -/obj/structure/disposalpipe/sortjunction/Kitchen - sortType = 20 - -/obj/structure/disposalpipe/sortjunction/Hydroponics - sortType = 21 - -/obj/structure/disposalpipe/sortjunction/Janitor - sortType = 22 - -/obj/structure/disposalpipe/sortjunction/Genetics - sortType = 23 - -/obj/structure/disposalpipe/sortjunction/Telecomms - sortType = 24 - -/obj/structure/disposalpipe/sortjunction/Mechanics - sortType = 25 - -/obj/structure/disposalpipe/sortjunction/Telescience - sortType = 26 - -////////////////// -//a three-way junction that sorts objects destined for the mail office mail table (tomail = 1) -/obj/structure/disposalpipe/wrapsortjunction - - desc = "An underfloor disposal pipe which sorts wrapped and unwrapped objects." - icon_state = "pipe-j1s" - var/posdir = 0 - var/negdir = 0 - var/sortdir = 0 - -/obj/structure/disposalpipe/wrapsortjunction/New() - . = ..() - - update_dir() - update() - -/obj/structure/disposalpipe/wrapsortjunction/update_dir() - posdir = dir - negdir = turn(posdir, 180) - - if(icon_state == "pipe-j1s") - sortdir = turn(posdir, -90) - else - icon_state = "pipe-j2s" - sortdir = turn(posdir, 90) - dpdir = sortdir | posdir | negdir - - . = ..() - -// next direction to move -// if coming in from negdir, then next is primary dir or sortdir -// if coming in from posdir, then flip around and go back to posdir -// if coming in from sortdir, go to posdir - -/obj/structure/disposalpipe/wrapsortjunction/nextdir(var/fromdir, var/istomail) - //var/flipdir = turn(fromdir, 180) - if(fromdir != sortdir) // probably came from the negdir - - if(istomail) //if destination matches filtered type... - return sortdir // exit through sortdirection - else - return posdir - else // came from sortdir - // so go with the flow to positive direction - return posdir - -/obj/structure/disposalpipe/wrapsortjunction/transfer(var/obj/structure/disposalholder/H) - var/nextdir = nextdir(H.dir, H.tomail) - H.dir = nextdir - var/turf/T = H.nextloc() - var/obj/structure/disposalpipe/P = H.findpipe(T) - - if(P) - // find other holder in next loc, if inactive merge it with current - var/obj/structure/disposalholder/H2 = locate() in P - if(H2 && !H2.active) - H.merge(H2) - - H.forceMove(P) - else // if wasn't a pipe, then set loc to turf - H.forceMove(T) - return - - return P - -//a trunk joining to a disposal bin or outlet on the same turf -/obj/structure/disposalpipe/trunk - icon_state = "pipe-t" - var/obj/machinery/disposal/disposal - var/obj/structure/disposaloutlet/disposaloutlet - var/obj/linked - -/obj/structure/disposalpipe/trunk/New() - . = ..() - dpdir = dir - - spawn(1) - getlinked() - - update() - -/obj/structure/disposalpipe/trunk/proc/getlinked() - disposal = locate() in loc - - if(disposal) - if(disposal.trunk != src) - disposal.trunk = src - - linked = disposal - - disposaloutlet = locate() in loc - - if(disposaloutlet) - if(disposaloutlet.trunk != src) - disposaloutlet.trunk = src - - linked = disposaloutlet - -/obj/structure/disposalpipe/trunk/Destroy() - if(disposal) - if(disposal.trunk) - disposal.trunk = null - - disposal = null - - if(disposaloutlet) - if(disposaloutlet.trunk) - disposaloutlet.trunk = null - - disposaloutlet = null - - if(linked) - linked = null - - ..() - - // Override attackby so we disallow trunkremoval when somethings ontop -/obj/structure/disposalpipe/trunk/attackby(var/obj/item/I, var/mob/user) - - //Disposal bins or chutes - /* - These shouldn't be required - var/obj/machinery/disposal/D = locate() in src.loc - if(D && D.anchored) - return - - //Disposal outlet - var/obj/structure/disposaloutlet/O = locate() in src.loc - if(O && O.anchored) - return - */ - - //Disposal constructors - var/obj/structure/disposalconstruct/C = locate() in src.loc - if(C && C.anchored) - return - - var/turf/T = src.loc - if(T.intact) - return // prevent interaction with T-scanner revealed pipes - src.add_fingerprint(user) - if(istype(I, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/W = I - - if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) - // check if anything changed over 2 seconds - var/turf/uloc = user.loc - var/atom/wloc = W.loc - to_chat(user, "Slicing the disposal pipe.") - sleep(30) - if(!W.isOn()) return - if(user.loc == uloc && wloc == W.loc) - welded() - else - to_chat(user, "You must stay still while welding the pipe.") - else - to_chat(user, "You need more welding fuel to cut the pipe.") - return - - // would transfer to next pipe segment, but we are in a trunk - // if not entering from disposal bin, - // transfer to linked object (outlet or bin) - -/obj/structure/disposalpipe/trunk/transfer(var/obj/structure/disposalholder/H) - - if(H.dir == DOWN) // we just entered from a disposer - return ..() // so do base transfer proc - // otherwise, go to the linked object - if(linked) - var/obj/structure/disposaloutlet/O = linked - if(istype(O) && (H)) - O.expel(H) // expel at outlet - else - var/obj/machinery/disposal/D = linked - if(H) - D.expel(H) // expel at disposal - else - if(H) - src.expel(H, src.loc, 0) // expel at turf - return null - - // nextdir - -/obj/structure/disposalpipe/trunk/nextdir(var/fromdir) - if(fromdir == DOWN) - return dir - else - return 0 - -// a broken pipe -/obj/structure/disposalpipe/broken - icon_state = "pipe-b" - dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes - // i.e. will be treated as an empty turf - desc = "A broken piece of disposal pipe." - - New() - ..() - update() - return - - // called when welded - // for broken pipe, remove and turn into scrap - - welded() -// var/obj/item/scrap/S = new(src.loc) -// S.set_components(200,0,0) - qdel(src) - -// the disposal outlet machine - -/obj/structure/disposaloutlet - name = "disposal outlet" - desc = "An outlet for the pneumatic disposal system." - icon = 'icons/obj/pipes/disposal.dmi' - icon_state = "outlet" - density = 1 - anchored = 1 - var/active = 0 - var/turf/target // this will be where the output objects are 'thrown' to. - var/mode = 0 - var/obj/structure/disposalpipe/trunk/trunk - - New() - . = ..() - - spawn(1) - target = get_ranged_target_turf(src, dir, 10) - - trunk = locate() in loc - - if(trunk) - if(trunk.disposaloutlet != src) - trunk.disposaloutlet = src - - if(trunk.linked != trunk.disposaloutlet) - trunk.linked = trunk.disposaloutlet - - Destroy() - if(trunk) - if(trunk.disposaloutlet) - trunk.disposaloutlet = null - - if(trunk.linked) - trunk.linked = null - - trunk = null - - ..() - - // expel the contents of the holder object, then delete it - // called when the holder exits the outlet - proc/expel(var/obj/structure/disposalholder/H) - - - flick("outlet-open", src) - playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0) - sleep(20) //wait until correct animation frame - playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - - if(H) - for(var/atom/movable/AM in H) - AM.forceMove(src.loc) - AM.pipe_eject(dir) - spawn(5) - if(AM) - AM.throw_at(target, 3, 1) - H.vent_gas(src.loc) - qdel(H) - - return - - attackby(var/obj/item/I, var/mob/user) - if(!I || !user) - return - src.add_fingerprint(user) - if(istype(I, /obj/item/weapon/screwdriver)) - if(mode==0) - mode=1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You remove the screws around the power connection.") - return - else if(mode==1) - mode=0 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You attach the screws around the power connection.") - return - else if(istype(I,/obj/item/weapon/weldingtool) && mode==1) - var/obj/item/weapon/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) - to_chat(user, "You start slicing the floorweld off the disposal outlet.") - if(do_after(user, src,20)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the disposal outlet.") - var/obj/structure/disposalconstruct/C = new (src.loc) - src.transfer_fingerprints_to(C) - C.ptype = 7 // 7 = outlet - C.update() - C.anchored = 1 - C.density = 1 - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - - -// called when movable is expelled from a disposal pipe or outlet -// by default does nothing, override for special behaviour - -/atom/movable/proc/pipe_eject(var/direction) - return - -// check if mob has client, if so restore client view on eject -/mob/pipe_eject(var/direction) - if (src.client) - src.client.perspective = MOB_PERSPECTIVE - src.client.eye = src - - return - -/obj/effect/decal/cleanable/blood/gibs/pipe_eject(var/direction) - var/list/dirs - if(direction) - dirs = list( direction, turn(direction, -45), turn(direction, 45)) - else - dirs = alldirs.Copy() - - src.streak(dirs) - -/obj/effect/decal/cleanable/blood/gibs/robot/pipe_eject(var/direction) - var/list/dirs - if(direction) - dirs = list( direction, turn(direction, -45), turn(direction, 45)) - else - dirs = alldirs.Copy() - - src.streak(dirs) +// Disposal bin +// Holds items for disposal into pipe system +// Draws air from turf, gradually charges internal reservoir +// Once full (~1 atm), uses air resv to flush items into the pipes +// Automatically recharges air (unless off), will flush when ready if pre-set +// Can hold items and human size things, no other draggables +// Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation +#define SEND_PRESSURE 0.05*ONE_ATMOSPHERE + +/obj/machinery/disposal + name = "disposal unit" + desc = "A pneumatic waste disposal unit." + icon = 'icons/obj/pipes/disposal.dmi' + icon_state = "disposal" + anchored = 1 + density = 1 + var/datum/gas_mixture/air_contents // internal reservoir + var/mode = 1 // item mode 0=off 1=charging 2=charged + var/flush = 0 // true if flush handle is pulled + var/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk + var/flushing = 0 // true if flushing in progress + var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush + var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush. + var/last_sound = 0 + +// create a new disposal +// find the attached trunk (if present) and init gas resvr. +/obj/machinery/disposal/New() + ..() + spawn(5) + for(var/obj/structure/disposalpipe/trunk/O in loc.contents)//This is more efficient than locate() + trunk = O + + if(trunk) + if(trunk.disposal != src) + trunk.disposal = src + + if(trunk.linked != trunk.disposal) + trunk.linked = trunk.disposal + else + mode = 0 + flush = 0 + + air_contents = new/datum/gas_mixture() + //gas.volume = 1.05 * CELLSTANDARD + update_icon() + +/obj/machinery/disposal/Destroy() + if(trunk) + if(trunk.disposal) + trunk.disposal = null + if(trunk.linked) + trunk.linked = null + + trunk = null + + ..() + +/obj/machinery/disposal/ex_act(var/severity,var/child=null) + var/child_severity=severity + if(!child) + child_severity++ + if(child_severity <= 3) + for(var/obj/O in contents) + O.ex_act(child_severity) + switch(severity) + if(2 to INFINITY) + if(prob(50)) + eject() + if(severity==2) + qdel(src) + if(1) + eject() + qdel(src) + + +// attack by item places it in to disposal +/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user) + if(stat & BROKEN || !I || !user) + return + + if(isrobot(user) && !istype(I, /obj/item/weapon/storage/bag/trash) && !istype(user,/mob/living/silicon/robot/mommi)) + return + src.add_fingerprint(user) + if(mode<=0) // It's off + if(istype(I, /obj/item/weapon/screwdriver)) + if(contents.len > 0) + to_chat(user, "Eject the items first!") + return + if(mode==0) // It's off but still not unscrewed + mode=-1 // Set it to doubleoff l0l + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You remove the screws around the power connection.") + return + else if(mode==-1) + mode=0 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You attach the screws around the power connection.") + return + else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1) + if(contents.len > 0) + to_chat(user, "Eject the items first!") + return + var/obj/item/weapon/weldingtool/W = I + if(W.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + to_chat(user, "You start slicing the floorweld off the disposal unit.") + + if(do_after(user, src,20)) + if(!src || !W.isOn()) return + to_chat(user, "You sliced the floorweld off the disposal unit.") + var/obj/structure/disposalconstruct/C = new (src.loc) + src.transfer_fingerprints_to(C) + C.ptype = 6 // 6 = disposal unit + C.anchored = 1 + C.density = 1 + C.update_icon() + qdel(src) + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(istype(I, /obj/item/weapon/storage/bag/)) + var/obj/item/weapon/storage/bag/B = I + if(B.contents.len == 0) + if(user.drop_item(I, src)) + to_chat(user, "You throw away the empty [B].") + return + to_chat(user, "You empty the [B].") + B.mass_remove(src) + B.update_icon() + update_icon() + return + + var/obj/item/weapon/grab/G = I + if(istype(G)) // handle grabbed mob + if(ismob(G.affecting)) + var/mob/GM = G.affecting + user.attack_log += " [user]([user.ckey]) has attempted to put [GM]([GM.ckey]) in disposals." + GM.attack_log += " [user]([user.ckey]) has attempted to put [GM]([GM.ckey]) in disposals." + user.visible_message("[usr] starts putting [GM.name] into \the [src].", "You start putting \the [GM.name] into the [src].", "You hear some clunking.") + if(do_after(usr, src, 20)) + if (GM.client) + GM.client.perspective = EYE_PERSPECTIVE + GM.client.eye = src + GM.loc = src + user.visible_message("[GM.name] has been placed in \the [src] by [user].", "[GM.name] has been placed in \the [src] by you.", "You hear a loud clunk.") + qdel(G) + log_attack("[usr] ([usr.ckey]) placed [GM] ([GM.ckey]) in a disposals unit.") + return + + if(!I) return + + if(user.drop_item(I, src)) + user.visible_message("[user.name] places \the [I] into the [src].", "You place \the [I] into the [src].") + + update_icon() + +// can breath normally in the disposal +/obj/machinery/disposal/alter_health() + return get_turf(src) + +// attempt to move while inside +/obj/machinery/disposal/relaymove(mob/user as mob) + if(user.stat || src.flushing) + return + src.go_out(user) + return + +// leave the disposal +/obj/machinery/disposal/proc/go_out(mob/user) + + + if (user.client) + user.client.eye = user.client.mob + user.client.perspective = MOB_PERSPECTIVE + user.loc = src.loc + update_icon() + return + + +// monkeys can only pull the flush lever +/obj/machinery/disposal/attack_paw(mob/user as mob) + if(stat & BROKEN) + return + + flush = !flush + update_icon() + return + +// ai as human but can't flush +/obj/machinery/disposal/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + ui_interact(user) + +// human interact with machine +/obj/machinery/disposal/attack_hand(mob/user as mob) + if(user && user.loc == src) + to_chat(usr, "You cannot reach the controls from inside.") + return + /* + if(mode==-1) + to_chat(usr, "The disposal units power is disabled.") + return + */ + src.add_fingerprint(user) + ui_interact(user) + +// user interaction +/obj/machinery/disposal/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/list/data[0] + + data["pressure"] = round(100 * air_contents.return_pressure() / (SEND_PRESSURE)) + data["flush"] = flush + data["mode"] = mode + data["isAI"] = isAI(user) + + // update the ui with data if it exists, returns null if no ui is passed/found or if force_open is 1/true + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "disposalsbin.tmpl", "Waste Disposal Unit", 430, 150) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // Make the UI auto-update. + ui.set_auto_update(1) + +// handle machine interaction +/obj/machinery/disposal/Topic(href, href_list) + if(usr.loc == src) + to_chat(usr, "You cannot reach the controls from inside.") + return + + if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1 + to_chat(usr, "The disposal units power is disabled.") + return + if(..()) + usr << browse(null, "window=disposal") + usr.unset_machine() + return 1 + else + src.add_fingerprint(usr) + usr.set_machine(src) + + if(href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=disposal") + return + + if(href_list["pump"]) + if(text2num(href_list["pump"])) + mode = 1 + else + mode = 0 + update_icon() + + if(href_list["handle"]) + flush = text2num(href_list["handle"]) + update_icon() + + if(href_list["eject"]) + eject() + + nanomanager.update_uis(src) + + return + +// eject the contents of the disposal unit +/obj/machinery/disposal/proc/eject() + for(var/atom/movable/AM in src) + AM.loc = src.loc + AM.pipe_eject(0) + update_icon() + +// update the icon & overlays to reflect mode & status +/obj/machinery/disposal/update_icon() + overlays.len = 0 + if(stat & BROKEN) + icon_state = "disposal-broken" + mode = 0 + flush = 0 + return + + // flush handle + if(flush) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-handle") + + // only handle is shown if no power + if(stat & NOPOWER || mode == -1) + return + + // check for items in disposal - occupied light + if(contents.len > 0) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-full") + + // charging and ready light + if(mode == 1) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-charge") + else if(mode == 2) + overlays += image('icons/obj/pipes/disposal.dmi', "dispover-ready") + +// timed process +// charge the gas reservoir and perform flush if ready +/obj/machinery/disposal/process() + if(stat & BROKEN) // nothing can happen if broken + return + + if(!air_contents) // Potentially causes a runtime otherwise (if this is really shitty, blame pete //Donkie) + return + + flush_count++ + if( flush_count >= flush_every_ticks ) + if( contents.len ) + if(mode == 2) + spawn(0) + feedback_inc("disposal_auto_flush",1) + flush() + flush_count = 0 + + src.updateDialog() + + if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power + spawn(0) + flush() + + if(stat & NOPOWER) // won't charge if no power + return + + use_power(100) // base power usage + + if(mode != 1) // if off or ready, no need to charge + return + + // otherwise charge + use_power(500) // charging power usage + + var/atom/L = loc // recharging from loc turf + + var/datum/gas_mixture/env = L.return_air() + var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure() + + if(env.temperature > 0) + var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION) + + //Actually transfer the gas + var/datum/gas_mixture/removed = env.remove(transfer_moles) + air_contents.merge(removed) + + + // if full enough, switch to ready mode + if(air_contents.return_pressure() >= SEND_PRESSURE) + mode = 2 + update_icon() + return + +// perform a flush +/obj/machinery/disposal/proc/flush() + + + flushing = 1 + flick("[icon_state]-flush", src) + + var/wrapcheck = 0 + var/obj/structure/disposalholder/H = new() // virtual holder object which actually + // travels through the pipes. + for(var/obj/item/delivery/O in src) + wrapcheck = 1 + + if(wrapcheck == 1) + H.tomail = 1 + + + air_contents = new() // new empty gas resv. + + sleep(10) + if(last_sound < world.time + 1) + playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0) + last_sound = world.time + sleep(5) // wait for animation to finish + + + H.init(src) // copy the contents of disposer to holder + + H.start(src) // start the holder processing movement + flushing = 0 + // now reset disposal state + flush = 0 + if(mode == 2) // if was ready, + mode = 1 // switch to charging + update_icon() + return + + +// called when area power changes +/obj/machinery/disposal/power_change() + ..() // do default setting/reset of stat NOPOWER bit + update_icon() // update icon + return + + +// called when holder is expelled from a disposal +// should usually only occur if the pipe network is modified +/obj/machinery/disposal/proc/expel(var/obj/structure/disposalholder/H) + + + var/turf/target + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + if(H) // Somehow, someone managed to flush a window which broke mid-transit and caused the disposal to go in an infinite loop trying to expel null, hopefully this fixes it + H.active = 0 // Stop disposalholder's move() processing so we don't call the trunk's expel() too + for(var/atom/movable/AM in H) + target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5)) + + AM.loc = src.loc + AM.pipe_eject(0) + spawn(1) + if(AM) + AM.throw_at(target, 5, 1) + + H.vent_gas(loc) + qdel(H) + +/obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if (istype(mover,/obj/item) && mover.throwing) + var/obj/item/I = mover + if(istype(I, /obj/item/weapon/dummy) || istype(I, /obj/item/projectile)) + return + if(prob(75)) + I.loc = src + for(var/mob/M in viewers(src)) + M.show_message("\the [I] lands in \the [src].", 1) + else + for(var/mob/M in viewers(src)) + M.show_message("\the [I] bounces off of \the [src]'s rim!.", 1) + return 0 + else + return ..(mover, target, height, air_group) + +/obj/machinery/disposal/MouseDrop_T(atom/dropping, mob/user) + if(istype(user, /mob/living/silicon/ai)) + return + + if(!ismob(dropping)) + if(istype(dropping, /obj/item)) + if(!user.restrained() && user.canmove) + attackby(dropping, user) + + return + + var/locHolder = dropping.loc + var/mob/target = dropping + + if(target == user) + if(!user.restrained() && user.canmove) + target.visible_message("[target] starts climbing into the [src].", "You start climbing into the [src].") + else + return + else + if(isanimal(user)) + return // animals cannot put mobs other than themselves into disposal + + if(!user.restrained() && user.canmove) + if(target.locked_to) + return + + user.visible_message("[user] starts stuffing [target] into the [src].", "You start stuffing [target] into the [src].") + else + return + + if(!do_after(user, src, 20)) + return + + if(locHolder != target.loc) + return + + if(target == user) + if(!user.restrained() && user.canmove) + target.visible_message("[target] climbed into the [src].", "You climbed into the [src].") + else + return + else + if(!user.restrained() && user.canmove) + if(target.locked_to) + return + + user.visible_message("[user] stuffed [target] into the [src]!", "You stuffed [target] into the [src]!") + log_attack("[key_name(user)] placed [key_name(target)] in a disposals unit/([src]).") + else + return + + add_fingerprint(user) + + if(target.client) + target.client.perspective = EYE_PERSPECTIVE + target.client.eye = src + + target.loc = src + + update_icon() + +// virtual disposal object +// travels through pipes in lieu of actual items +// contents will be items flushed by the disposal +// this allows the gas flushed to be tracked + +/obj/structure/disposalholder + invisibility = 101 + var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point + var/active = 0 // true if the holder is moving, otherwise inactive + dir = 0 + var/count = 1000 //*** can travel 1000 steps before going inactive (in case of loops) + var/has_fat_guy = 0 // true if contains a fat person + var/destinationTag = "DISPOSALS"// changes if contains a delivery container + var/tomail = 0 //changes if contains wrapped package + var/hasmob = 0 //If it contains a mob + + + // initialize a holder from the contents of a disposal unit + proc/init(var/obj/machinery/disposal/D) + gas = D.air_contents// transfer gas resv. into holder object + + //Check for any living mobs trigger hasmob. + //hasmob effects whether the package goes to cargo or its tagged destination. + for(var/mob/living/M in D) + if(M && M.stat != 2) + hasmob = 1 + + //Checks 1 contents level deep. This means that players can be sent through disposals... + //...but it should require a second person to open the package. (i.e. person inside a wrapped locker) + for(var/obj/O in D) + if(O.contents) + for(var/mob/living/M in O.contents) + if(M && M.stat != 2) + hasmob = 1 + + // now everything inside the disposal gets put into the holder + // note AM since can contain mobs or objs + for(var/atom/movable/AM in D) + AM.forceMove(src) + if(istype(AM, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = AM + if((M_FAT in H.mutations) && (H.species && H.species.flags & CAN_BE_FAT)) // is a human and fat? + has_fat_guy = 1 // set flag on holder + if(istype(AM, /obj/item/delivery/large) && !hasmob) + var/obj/item/delivery/large/T = AM + src.destinationTag = T.sortTag + if(istype(AM, /obj/item/delivery) && !hasmob) + var/obj/item/delivery/T = AM + src.destinationTag = T.sortTag + + // start the movement process + // argument is the disposal unit the holder started in + proc/start(var/obj/machinery/disposal/D) + if(!D.trunk) + D.expel(src) // no trunk connected, so expel immediately + return + + forceMove(D.trunk) + active = 1 + dir = DOWN + spawn(1) + move() // spawn off the movement process + + // movement process, persists while holder is moving through pipes + proc/move() + var/obj/structure/disposalpipe/last + while(active) + /* vg edit + if(hasmob && prob(3)) + for(var/mob/living/H in src) + H.take_overall_damage(20, 0, "Blunt Trauma")//horribly maim any living creature jumping down disposals. c'est la vie + */ + + if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy + active = 0 + // find the fat guys + for(var/mob/living/carbon/human/H in src) + + break + sleep(1) // was 1 + if(!loc || isnull(loc)) + qdel(src) + return + + var/obj/structure/disposalpipe/curr = loc + last = curr + curr = curr.transfer(src) + if(!curr) + last.expel(src, loc, dir) + + // + if(!(count--)) + active = 0 + return + + + + // find the turf which should contain the next pipe + proc/nextloc() + return get_step(loc,dir) + + // find a matching pipe on a turf + proc/findpipe(var/turf/T) + + + if(!T) + return null + + var/fdir = turn(dir, 180) // flip the movement direction + for(var/obj/structure/disposalpipe/P in T) + if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir + return P + // if no matching pipe, return null + return null + + // merge two holder objects + // used when a a holder meets a stuck holder + proc/merge(var/obj/structure/disposalholder/other) + for(var/atom/movable/AM in other) + AM.forceMove(src) // move everything in other holder to this one + if(ismob(AM)) + var/mob/M = AM + if(M.client) // if a client mob, update eye to follow this holder + M.client.eye = src + + if(other.has_fat_guy) + has_fat_guy = 1 + qdel(other) + + + // called when player tries to move while in a pipe + relaymove(mob/user as mob) + if (user.stat) + return + if (src.loc) + for (var/mob/M in hearers(src.loc.loc)) + to_chat(M, "CLONG, clong!") + + playsound(get_turf(src), 'sound/effects/clang.ogg', 50, 0, 0) + + // called to vent all gas in holder to a location + proc/vent_gas(var/atom/location) + location.assume_air(gas) // vent all gas to turf + return + +// Disposal pipes + +/obj/structure/disposalpipe + icon = 'icons/obj/pipes/disposal.dmi' + name = "disposal pipe" + desc = "An underfloor disposal pipe." + anchored = 1 + density = 0 + + level = 1 // underfloor only + var/dpdir = 0 // bitmask of pipe directions + dir = 0 // dir will contain dominant direction for junction pipes + var/health = 10 // health points 0-10 + layer = 2.3 // slightly lower than wires and other pipes + var/base_icon_state // initial icon state on map + + // new pipe, set the icon_state as on map + New() + ..() + base_icon_state = icon_state + return + + + // pipe is deleted + // ensure if holder is present, it is expelled + Destroy() + var/obj/structure/disposalholder/H = locate() in src + if(H) + // holder was present + H.active = 0 + var/turf/T = src.loc + if(T.density) + // deleting pipe is inside a dense turf (wall) + // this is unlikely, but just dump out everything into the turf in case + + for(var/atom/movable/AM in H) + AM.forceMove(T) + AM.pipe_eject(0) + qdel(H) + ..() + return + + // otherwise, do normal expel from turf + if(H) + expel(H, T, 0) + ..() + + // returns the direction of the next pipe object, given the entrance dir + // by default, returns the bitmask of remaining directions + proc/nextdir(var/fromdir) + return dpdir & (~turn(fromdir, 180)) + + // transfer the holder through this pipe segment + // overriden for special behaviour + // + proc/transfer(var/obj/structure/disposalholder/H) + var/nextdir = nextdir(H.dir) + H.dir = nextdir + var/turf/T = H.nextloc() + var/obj/structure/disposalpipe/P = H.findpipe(T) + + if(P) + // find other holder in next loc, if inactive merge it with current + var/obj/structure/disposalholder/H2 = locate() in P + if(H2 && !H2.active) + H.merge(H2) + + H.forceMove(P) + else // if wasn't a pipe, then set loc to turf + H.forceMove(T) + return null + + return P + + + // update the icon_state to reflect hidden status + proc/update() + var/turf/T = src.loc + hide(T.intact && !istype(T,/turf/space)) // space never hides pipes + + // hide called by levelupdate if turf intact status changes + // change visibility status and force update of icon + hide(var/intact) + invisibility = intact ? 101: 0 // hide if floor is intact + updateicon() + + // update actual icon_state depending on visibility + // if invisible, append "f" to icon_state to show faded version + // this will be revealed if a T-scanner is used + // if visible, use regular icon_state + proc/updateicon() + if(invisibility) + icon_state = "[base_icon_state]f" + else + icon_state = base_icon_state + return + + + // expel the held objects into a turf + // called when there is a break in the pipe + // + + proc/expel(var/obj/structure/disposalholder/H, var/turf/T, var/direction) + + + var/turf/target + if(!T || isnull(T)) + T = loc + if(T.density) // dense ouput turf, so stop holder + H.active = 0 + H.forceMove(src) + return + if(T.intact && istype(T,/turf/simulated/floor)) //intact floor, pop the tile + var/turf/simulated/floor/F = T + //F.health = 100 + F.break_tile() + + if(direction) // direction is specified + if(istype(T, /turf/space)) // if ended in space, then range is unlimited + target = get_edge_target_turf(T, direction) + else // otherwise limit to 10 tiles + target = get_ranged_target_turf(T, direction, 10) + + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + if(H) + for(var/atom/movable/AM in H) + AM.forceMove(T) + AM.pipe_eject(direction) + spawn(1) + if(AM) + AM.throw_at(target, 100, 1) + H.vent_gas(T) + qdel(H) + + else // no specified direction, so throw in random direction + + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + if(H) + for(var/atom/movable/AM in H) + target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5)) + + AM.forceMove(T) + AM.pipe_eject(0) + spawn(1) + if(AM) + AM.throw_at(target, 5, 1) + + H.vent_gas(T) // all gas vent to turf + qdel(H) + + return + + // call to break the pipe + // will expel any holder inside at the time + // then delete the pipe + // remains : set to leave broken pipe pieces in place + proc/broken(var/remains = 0) + if(remains) + for(var/D in cardinal) + if(D & dpdir) + var/obj/structure/disposalpipe/broken/P = new(src.loc) + P.dir = D + + src.invisibility = 101 // make invisible (since we won't delete the pipe immediately) + var/obj/structure/disposalholder/H = locate() in src + if(H) + // holder was present + H.active = 0 + var/turf/T = src.loc + if(T.density) + // broken pipe is inside a dense turf (wall) + // this is unlikely, but just dump out everything into the turf in case + + for(var/atom/movable/AM in H) + AM.forceMove(T) + AM.pipe_eject(0) + qdel(H) + return + + // otherwise, do normal expel from turf + if(H) + expel(H, T, 0) + + spawn(2) // delete pipe after 2 ticks to ensure expel proc finished + qdel(src) + + + // pipe affected by explosion + ex_act(severity) + + switch(severity) + if(1.0) + broken(0) + return + if(2.0) + health -= rand(5,15) + healthcheck() + return + if(3.0) + health -= rand(0,15) + healthcheck() + return + + + // test health for brokenness + proc/healthcheck() + if(health < -2) + broken(0) + else if(health<1) + broken(1) + return + + //attack by item + //weldingtool: unfasten and convert to obj/disposalconstruct + + attackby(var/obj/item/I, var/mob/user) + + var/turf/T = src.loc + if(T.intact) + return // prevent interaction with T-scanner revealed pipes + src.add_fingerprint(user) + if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/W = I + + if(W.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + // check if anything changed over 2 seconds + var/turf/uloc = user.loc + var/atom/wloc = W.loc + to_chat(user, "Slicing the disposal pipe.") + sleep(30) + if(!W.isOn()) return + if(user.loc == uloc && wloc == W.loc) + welded() + else + to_chat(user, "You must stay still while welding the pipe.") + else + to_chat(user, "You need more welding fuel to cut the pipe.") + return + + // called when pipe is cut with welder + proc/welded() + + + var/obj/structure/disposalconstruct/C = new (src.loc) + switch(base_icon_state) + if("pipe-s") + C.ptype = 0 + if("pipe-c") + C.ptype = 1 + if("pipe-j1") + C.ptype = 2 + if("pipe-j2") + C.ptype = 3 + if("pipe-y") + C.ptype = 4 + if("pipe-t") + C.ptype = 5 + if("pipe-j1s") + C.ptype = 9 + if("pipe-j2s") + C.ptype = 10 + src.transfer_fingerprints_to(C) + C.change_dir(dir) + C.density = 0 + C.anchored = 1 + C.update() + + qdel(src) + +// *** TEST verb +//client/verb/dispstop() +// for(var/obj/structure/disposalholder/H in world) +// H.active = 0 + +// a straight or bent segment +/obj/structure/disposalpipe/segment + icon_state = "pipe-s" + +/obj/structure/disposalpipe/segment/New() + ..() + if(icon_state == "pipe-s") + dpdir = dir | turn(dir, 180) + else + dpdir = dir | turn(dir, -90) + + update() + +//a three-way junction with dir being the dominant direction +/obj/structure/disposalpipe/junction + icon_state = "pipe-j1" + +/obj/structure/disposalpipe/junction/New() + ..() + if(icon_state == "pipe-j1") + dpdir = dir | turn(dir, -90) | turn(dir,180) + else if(icon_state == "pipe-j2") + dpdir = dir | turn(dir, 90) | turn(dir,180) + else // pipe-y + dpdir = dir | turn(dir,90) | turn(dir, -90) + update() + return + +// next direction to move +// if coming in from secondary dirs, then next is primary dir +// if coming in from primary dir, then next is equal chance of other dirs + +/obj/structure/disposalpipe/junction/nextdir(var/fromdir) + var/flipdir = turn(fromdir, 180) + if(flipdir != dir) // came from secondary dir + return dir // so exit through primary + else // came from primary + // so need to choose either secondary exit + var/mask = ..(fromdir) + + // find a bit which is set + var/setbit = 0 + if(mask & NORTH) + setbit = NORTH + else if(mask & SOUTH) + setbit = SOUTH + else if(mask & EAST) + setbit = EAST + else + setbit = WEST + + if(prob(50)) // 50% chance to choose the found bit or the other one + return setbit + else + return mask & (~setbit) + +//a three-way junction that sorts objects +/obj/structure/disposalpipe/sortjunction + icon_state = "pipe-j1s" + var/sortType = 0 //Deprecated, here for legacy support. + var/sort_tag //Replacement of the above, more construction friendly. + + var/posdir = 0 + var/negdir = 0 + var/sortdir = 0 + +/obj/structure/disposalpipe/sortjunction/proc/updatedesc() + desc = "An underfloor disposal pipe with a package sorting mechanism." + if(sort_tag) + desc += "\nIt's tagged with [sort_tag]." + +/obj/structure/disposalpipe/sortjunction/proc/updatedir() + posdir = dir + negdir = turn(posdir, 180) + + if(icon_state == "pipe-j1s") + sortdir = turn(posdir, -90) + else + icon_state = "pipe-j2s" + sortdir = turn(posdir, 90) + + dpdir = sortdir | posdir | negdir + +/obj/structure/disposalpipe/sortjunction/New() + . = ..() + if(sortType && !sort_tag) + sort_tag = uppertext(DEFAULT_TAGGER_LOCATIONS[sortType]) + + updatedir() + updatedesc() + update() + +/obj/structure/disposalpipe/sortjunction/attackby(var/obj/item/I, var/mob/user) + if(istype(I, /obj/item/device/destTagger)) + var/obj/item/device/destTagger/O = I + + if(O.currTag)// Tag set + sort_tag = uppertext(O.destinations[O.currTag]) + playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) + to_chat(user, "Changed filter to [sort_tag]") + updatedesc() + return 1 + + . = ..() + // next direction to move + // if coming in from negdir, then next is primary dir or sortdir + // if coming in from posdir, then flip around and go back to posdir + // if coming in from sortdir, go to posdir + +/obj/structure/disposalpipe/sortjunction/nextdir(var/fromdir, var/sortTag) + //var/flipdir = turn(fromdir, 180) + if(fromdir != sortdir) // probably came from the negdir + + if(sort_tag == sortTag) //if destination matches filtered type... + return sortdir // exit through sortdirection + else + return posdir + else // came from sortdir + // so go with the flow to positive direction + return posdir + +/obj/structure/disposalpipe/sortjunction/transfer(var/obj/structure/disposalholder/H) + var/nextdir = nextdir(H.dir, H.destinationTag) + H.dir = nextdir + var/turf/T = H.nextloc() + var/obj/structure/disposalpipe/P = H.findpipe(T) + + if(P) + // find other holder in next loc, if inactive merge it with current + var/obj/structure/disposalholder/H2 = locate() in P + if(H2 && !H2.active) + H.merge(H2) + + H.forceMove(P) + else // if wasn't a pipe, then set loc to turf + H.forceMove(T) + return + + return P + +////////////////// SortJunctionSubtypes////////////////// +//Box +/obj/structure/disposalpipe/sortjunction/Disposals + sortType = 1 + +/obj/structure/disposalpipe/sortjunction/Cargo + sortType = 2 + +/obj/structure/disposalpipe/sortjunction/QM + sortType = 3 + +/obj/structure/disposalpipe/sortjunction/Engineering + sortType = 4 + +/obj/structure/disposalpipe/sortjunction/CE + sortType = 5 + +/obj/structure/disposalpipe/sortjunction/Atmos + sortType = 6 + +/obj/structure/disposalpipe/sortjunction/Security + sortType = 7 + +/obj/structure/disposalpipe/sortjunction/HoS + sortType = 8 + +/obj/structure/disposalpipe/sortjunction/Medbay + sortType = 9 + +/obj/structure/disposalpipe/sortjunction/CMO + sortType = 10 + +/obj/structure/disposalpipe/sortjunction/Chemistry + sortType = 11 + +/obj/structure/disposalpipe/sortjunction/Research + sortType = 12 + +/obj/structure/disposalpipe/sortjunction/RD + sortType = 13 + +/obj/structure/disposalpipe/sortjunction/Robotics + sortType = 14 + +/obj/structure/disposalpipe/sortjunction/HoP + sortType = 15 + +/obj/structure/disposalpipe/sortjunction/Library + sortType = 16 + +/obj/structure/disposalpipe/sortjunction/Chapel + sortType = 17 + +/obj/structure/disposalpipe/sortjunction/Theatre + sortType = 18 + +/obj/structure/disposalpipe/sortjunction/Bar + sortType = 19 + +/obj/structure/disposalpipe/sortjunction/Kitchen + sortType = 20 + +/obj/structure/disposalpipe/sortjunction/Hydroponics + sortType = 21 + +/obj/structure/disposalpipe/sortjunction/Janitor + sortType = 22 + +/obj/structure/disposalpipe/sortjunction/Genetics + sortType = 23 + +/obj/structure/disposalpipe/sortjunction/Telecomms + sortType = 24 + +/obj/structure/disposalpipe/sortjunction/Mechanics + sortType = 25 + +/obj/structure/disposalpipe/sortjunction/Telescience + sortType = 26 + +////////////////// +//a three-way junction that sorts objects destined for the mail office mail table (tomail = 1) +/obj/structure/disposalpipe/wrapsortjunction + + desc = "An underfloor disposal pipe which sorts wrapped and unwrapped objects." + icon_state = "pipe-j1s" + var/posdir = 0 + var/negdir = 0 + var/sortdir = 0 + +/obj/structure/disposalpipe/wrapsortjunction/New() + . = ..() + + update_dir() + update() + +/obj/structure/disposalpipe/wrapsortjunction/update_dir() + posdir = dir + negdir = turn(posdir, 180) + + if(icon_state == "pipe-j1s") + sortdir = turn(posdir, -90) + else + icon_state = "pipe-j2s" + sortdir = turn(posdir, 90) + dpdir = sortdir | posdir | negdir + + . = ..() + +// next direction to move +// if coming in from negdir, then next is primary dir or sortdir +// if coming in from posdir, then flip around and go back to posdir +// if coming in from sortdir, go to posdir + +/obj/structure/disposalpipe/wrapsortjunction/nextdir(var/fromdir, var/istomail) + //var/flipdir = turn(fromdir, 180) + if(fromdir != sortdir) // probably came from the negdir + + if(istomail) //if destination matches filtered type... + return sortdir // exit through sortdirection + else + return posdir + else // came from sortdir + // so go with the flow to positive direction + return posdir + +/obj/structure/disposalpipe/wrapsortjunction/transfer(var/obj/structure/disposalholder/H) + var/nextdir = nextdir(H.dir, H.tomail) + H.dir = nextdir + var/turf/T = H.nextloc() + var/obj/structure/disposalpipe/P = H.findpipe(T) + + if(P) + // find other holder in next loc, if inactive merge it with current + var/obj/structure/disposalholder/H2 = locate() in P + if(H2 && !H2.active) + H.merge(H2) + + H.forceMove(P) + else // if wasn't a pipe, then set loc to turf + H.forceMove(T) + return + + return P + +//a trunk joining to a disposal bin or outlet on the same turf +/obj/structure/disposalpipe/trunk + icon_state = "pipe-t" + var/obj/machinery/disposal/disposal + var/obj/structure/disposaloutlet/disposaloutlet + var/obj/linked + +/obj/structure/disposalpipe/trunk/New() + . = ..() + dpdir = dir + + spawn(1) + getlinked() + + update() + +/obj/structure/disposalpipe/trunk/proc/getlinked() + disposal = locate() in loc + + if(disposal) + if(disposal.trunk != src) + disposal.trunk = src + + linked = disposal + + disposaloutlet = locate() in loc + + if(disposaloutlet) + if(disposaloutlet.trunk != src) + disposaloutlet.trunk = src + + linked = disposaloutlet + +/obj/structure/disposalpipe/trunk/Destroy() + if(disposal) + if(disposal.trunk) + disposal.trunk = null + + disposal = null + + if(disposaloutlet) + if(disposaloutlet.trunk) + disposaloutlet.trunk = null + + disposaloutlet = null + + if(linked) + linked = null + + ..() + + // Override attackby so we disallow trunkremoval when somethings ontop +/obj/structure/disposalpipe/trunk/attackby(var/obj/item/I, var/mob/user) + + //Disposal bins or chutes + /* + These shouldn't be required + var/obj/machinery/disposal/D = locate() in src.loc + if(D && D.anchored) + return + + //Disposal outlet + var/obj/structure/disposaloutlet/O = locate() in src.loc + if(O && O.anchored) + return + */ + + //Disposal constructors + var/obj/structure/disposalconstruct/C = locate() in src.loc + if(C && C.anchored) + return + + var/turf/T = src.loc + if(T.intact) + return // prevent interaction with T-scanner revealed pipes + src.add_fingerprint(user) + if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/W = I + + if(W.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + // check if anything changed over 2 seconds + var/turf/uloc = user.loc + var/atom/wloc = W.loc + to_chat(user, "Slicing the disposal pipe.") + sleep(30) + if(!W.isOn()) return + if(user.loc == uloc && wloc == W.loc) + welded() + else + to_chat(user, "You must stay still while welding the pipe.") + else + to_chat(user, "You need more welding fuel to cut the pipe.") + return + + // would transfer to next pipe segment, but we are in a trunk + // if not entering from disposal bin, + // transfer to linked object (outlet or bin) + +/obj/structure/disposalpipe/trunk/transfer(var/obj/structure/disposalholder/H) + + if(H.dir == DOWN) // we just entered from a disposer + return ..() // so do base transfer proc + // otherwise, go to the linked object + if(linked) + var/obj/structure/disposaloutlet/O = linked + if(istype(O) && (H)) + O.expel(H) // expel at outlet + else + var/obj/machinery/disposal/D = linked + if(H) + D.expel(H) // expel at disposal + else + if(H) + src.expel(H, src.loc, 0) // expel at turf + return null + + // nextdir + +/obj/structure/disposalpipe/trunk/nextdir(var/fromdir) + if(fromdir == DOWN) + return dir + else + return 0 + +// a broken pipe +/obj/structure/disposalpipe/broken + icon_state = "pipe-b" + dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes + // i.e. will be treated as an empty turf + desc = "A broken piece of disposal pipe." + + New() + ..() + update() + return + + // called when welded + // for broken pipe, remove and turn into scrap + + welded() +// var/obj/item/scrap/S = new(src.loc) +// S.set_components(200,0,0) + qdel(src) + +// the disposal outlet machine + +/obj/structure/disposaloutlet + name = "disposal outlet" + desc = "An outlet for the pneumatic disposal system." + icon = 'icons/obj/pipes/disposal.dmi' + icon_state = "outlet" + density = 1 + anchored = 1 + var/active = 0 + var/turf/target // this will be where the output objects are 'thrown' to. + var/mode = 0 + var/obj/structure/disposalpipe/trunk/trunk + + New() + . = ..() + + spawn(1) + target = get_ranged_target_turf(src, dir, 10) + + trunk = locate() in loc + + if(trunk) + if(trunk.disposaloutlet != src) + trunk.disposaloutlet = src + + if(trunk.linked != trunk.disposaloutlet) + trunk.linked = trunk.disposaloutlet + + Destroy() + if(trunk) + if(trunk.disposaloutlet) + trunk.disposaloutlet = null + + if(trunk.linked) + trunk.linked = null + + trunk = null + + ..() + + // expel the contents of the holder object, then delete it + // called when the holder exits the outlet + proc/expel(var/obj/structure/disposalholder/H) + + + flick("outlet-open", src) + playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0) + sleep(20) //wait until correct animation frame + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + + if(H) + for(var/atom/movable/AM in H) + AM.forceMove(src.loc) + AM.pipe_eject(dir) + spawn(5) + if(AM) + AM.throw_at(target, 3, 1) + H.vent_gas(src.loc) + qdel(H) + + return + + attackby(var/obj/item/I, var/mob/user) + if(!I || !user) + return + src.add_fingerprint(user) + if(istype(I, /obj/item/weapon/screwdriver)) + if(mode==0) + mode=1 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You remove the screws around the power connection.") + return + else if(mode==1) + mode=0 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You attach the screws around the power connection.") + return + else if(istype(I,/obj/item/weapon/weldingtool) && mode==1) + var/obj/item/weapon/weldingtool/W = I + if(W.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + to_chat(user, "You start slicing the floorweld off the disposal outlet.") + if(do_after(user, src,20)) + if(!src || !W.isOn()) return + to_chat(user, "You sliced the floorweld off the disposal outlet.") + var/obj/structure/disposalconstruct/C = new (src.loc) + src.transfer_fingerprints_to(C) + C.ptype = 7 // 7 = outlet + C.update() + C.anchored = 1 + C.density = 1 + qdel(src) + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + + +// called when movable is expelled from a disposal pipe or outlet +// by default does nothing, override for special behaviour + +/atom/movable/proc/pipe_eject(var/direction) + return + +// check if mob has client, if so restore client view on eject +/mob/pipe_eject(var/direction) + if (src.client) + src.client.perspective = MOB_PERSPECTIVE + src.client.eye = src + + return + +/obj/effect/decal/cleanable/blood/gibs/pipe_eject(var/direction) + var/list/dirs + if(direction) + dirs = list( direction, turn(direction, -45), turn(direction, 45)) + else + dirs = alldirs.Copy() + + src.streak(dirs) + +/obj/effect/decal/cleanable/blood/gibs/robot/pipe_eject(var/direction) + var/list/dirs + if(direction) + dirs = list( direction, turn(direction, -45), turn(direction, 45)) + else + dirs = alldirs.Copy() + + src.streak(dirs) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 9df826a2485..abbc5c8c62a 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -1,588 +1,588 @@ -//Default list destination taggers and such can use. - -var/list/DEFAULT_TAGGER_LOCATIONS = list( - "Disposals", - "Cargo Bay", - "QM Office", - "Engineering", - "CE Office", - "Atmospherics", - "Security", - "HoS Office", - "Medbay", - "CMO Office", - "Chemistry", - "Research", - "RD Office", - "Robotics", - "HoP Office", - "Library", - "Chapel", - "Theatre", - "Bar", - "Kitchen", - "Hydroponics", - "Janitor Closet", - "Genetics", - "Telecomms", - "Mechanics", - "Telescience" - ) - -/obj/item/device/destTagger - name = "destination tagger" - desc = "Used to set the destination of properly wrapped packages." - icon_state = "dest_tagger" - - var/panel = 0 //If the panel is open. - var/mode = 0 //If the tagger is "hacked" so you can add extra tags. - - var/currTag = 0 - var/list/destinations - - w_class = 1 - item_state = "electronic" - flags = FPRINT - siemens_coefficient = 1 - slot_flags = SLOT_BELT - -/obj/item/device/destTagger/panel - panel = 1 - -/obj/item/device/destTagger/panel/New() - . = ..() - update_icon() - -/obj/item/device/destTagger/New() - . = ..() - destinations = DEFAULT_TAGGER_LOCATIONS.Copy() //T-thanks BYOND. - -/obj/item/device/destTagger/interact(mob/user as mob) - - var/dat = "" - - for (var/i = 1, i <= destinations.len, i++) - dat += "" - - if (i % 4 == 0) - dat += "" - - dat += "
    [destinations[i]][mode ? "\[X\]" : ""]

    Current Selection: [currTag ? destinations[currTag] : "None"].

    " - - if(mode) - dat += "Add destination" - - var/datum/browser/popup = new(user, "destTagger", name, 380, 350, src) - popup.add_stylesheet("shared", 'nano/css/shared.css') - popup.set_content(dat) - popup.open() - -/obj/item/device/destTagger/attack_self(mob/user as mob) - interact(user) - -/obj/item/device/destTagger/attackby(obj/item/W, mob/user) - if(isscrewdriver(W)) - panel = !panel - to_chat(user, "You [panel ? "open" : "close"] the panel on \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - update_icon() - return 1 - - if(ismultitool(W) && panel) - mode = !mode - to_chat(user, "You [mode ? "disable" : "enable"] the lock on \the [src].") - return 1 - - . = ..() - -/obj/item/device/destTagger/update_icon() - if(panel) - icon_state = "dest_tagger_p" - desc += "\nThe panel appears to be open." - else - icon_state = "dest_tagger" - desc = initial(desc) - -/obj/item/device/destTagger/Topic(href, href_list) - . = ..() - if(.) - return - - add_fingerprint(usr) - - if(href_list["nextTag"]) - currTag = Clamp(text2num(href_list["nextTag"]), 0, destinations.len) - interact(usr) - return 1 - - if(href_list["remove_dest"] && mode) - var/idx = Clamp(text2num(href_list["remove_dest"]), 1, destinations.len) - destinations -= destinations[idx] - interact(usr) - return 1 - - if(href_list["new_dest"] && mode) - var/newtag = uppertext(copytext(sanitize(input(usr, "Destination ID?","Add Destination") as text), 1, MAX_NAME_LEN)) - destinations |= newtag - interact(usr) - return 1 - -/obj/machinery/disposal/deliveryChute - name = "Delivery chute" - desc = "A chute for big and small packages alike!" - density = 1 - icon_state = "intake" - var/c_mode = 0 - var/doFlushIn=0 - var/num_contents=0 - -/obj/machinery/disposal/deliveryChute/New() - ..() - processing_objects.Remove(src) - spawn(5) - trunk = locate() in src.loc - if(trunk) - trunk.linked = src // link the pipe trunk to self - -/obj/machinery/disposal/deliveryChute/interact() - return - -/obj/machinery/disposal/deliveryChute/update_icon() - return - -/obj/machinery/disposal/deliveryChute/Bumped(var/atom/movable/AM) //Go straight into the chute - if(istype(AM, /obj/item/projectile) || istype(AM, /obj/item/weapon/dummy)) return - - if(dir != get_dir(src, AM)) - return - - //testing("[src] FUCKING BUMPED BY \a [AM]") - - if(istype(AM, /obj)) - var/obj/O = AM - O.loc = src - else if(istype(AM, /mob)) - var/mob/M = AM - M.loc = src - //src.flush() This spams audio like fucking crazy. - // Instead, we queue up for the next process. - doFlushIn=5 // Ticks, adjust if delay is too long or too short - num_contents++ - -/obj/machinery/disposal/deliveryChute/flush() - flushing = 1 - flick("intake-closing", src) - var/deliveryCheck = 0 - var/obj/structure/disposalholder/H = new() // virtual holder object which actually - // travels through the pipes. - for(var/obj/item/delivery/large/O in src) - deliveryCheck = 1 - if(O.sortTag == 0) - O.sortTag = "DISPOSALS" - for(var/obj/item/delivery/O in src) - deliveryCheck = 1 - if (O.sortTag == 0) - O.sortTag = "DISPOSALS" - if(deliveryCheck == 0) - H.destinationTag = "DISPOSALS" - - air_contents = new() // new empty gas resv. - - sleep(10) - playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0) - sleep(5) // wait for animation to finish - - H.init(src) // copy the contents of disposer to holder - num_contents=0 - doFlushIn=0 - - H.start(src) // start the holder processing movement - flushing = 0 - // now reset disposal state - flush = 0 - if(mode == 2) // if was ready, - mode = 1 // switch to charging - update_icon() - return - -/obj/machinery/disposal/deliveryChute/attackby(var/obj/item/I, var/mob/user) - if(!I || !user) - return - - if(istype(I, /obj/item/weapon/screwdriver)) - if(c_mode==0) - c_mode=1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You remove the screws around the power connection.") - return - else if(c_mode==1) - c_mode=0 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You attach the screws around the power connection.") - return - else if(istype(I,/obj/item/weapon/weldingtool) && c_mode==1) - var/obj/item/weapon/weldingtool/W = I - if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) - to_chat(user, "You start slicing the floorweld off the delivery chute.") - if(do_after(user, src,20)) - if(!src || !W.isOn()) return - to_chat(user, "You sliced the floorweld off the delivery chute.") - var/obj/structure/disposalconstruct/C = new (src.loc) - C.ptype = 8 // 8 = Delivery chute - C.update() - C.anchored = 1 - C.density = 1 - qdel(src) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return - -/obj/machinery/disposal/deliveryChute/process() - if(doFlushIn>0) - if(doFlushIn==1 || num_contents>=50) - //testing("[src] FLUSHING") - spawn(0) - src.flush() - doFlushIn-- - -//Base framework for sorting machines. -/obj/machinery/sorting_machine - name = "Sorting Machine" - desc = "Sorts stuff." - density = 1 - icon = 'icons/obj/recycling.dmi' - icon_state = "grinder-b1" - anchored = 1 - - machine_flags = SCREWTOGGLE | CROWDESTROY | MULTITOOL_MENU - - idle_power_usage = 100 //No active power usage because this thing passively uses 100, always. Don't ask me why N3X15 coded it like this. - - var/atom/movable/mover //Virtual atom used to check passing ability on the out turf. - - var/input_dir = EAST - var/output_dir = WEST - var/filter_dir = SOUTH - - var/max_items_moved = 100 - -/obj/machinery/sorting_machine/New() - . = ..() - - mover = new - -/obj/machinery/sorting_machine/Destroy() - . = ..() - - qdel(mover) - mover = null - -/obj/machinery/sorting_machine/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/bin in component_parts) - T += bin.rating//intentionally not doing '- 1' here, for the math below - max_items_moved = initial(max_items_moved) * (T / 3) //Usefull upgrade/10, that's an increase from 10 (base matter bins) to 30 (super matter bins) - - T = 0//reusing T here because muh RAM - for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) - T += C.rating - 1 - idle_power_usage = initial(idle_power_usage) - (T * (initial(idle_power_usage) / 4))//25% power usage reduction for an advanced capacitor, 50% for a super one. - -/obj/machinery/sorting_machine/process() - if(stat & (BROKEN | NOPOWER)) - return - - var/turf/in_T = get_step(src, input_dir) - var/turf/out_T = get_step(src, output_dir) - var/turf/filter_T = get_step(src, filter_dir) - - if(!out_T.CanPass(mover, out_T) || !out_T.Enter(mover) || !filter_T.CanPass(mover, filter_T) || !filter_T.Enter(mover)) - return - - var/affecting = in_T.contents - var/items_moved = 0 - - for(var/atom/movable/A in affecting) - if(A.anchored) - continue - - if(sort(A)) - A.forceMove(filter_T) - else - A.forceMove(out_T) - - items_moved++ - if(items_moved >= max_items_moved) - break - -/obj/machinery/sorting_machine/attack_ai(mob/user) - interact(user) - -/obj/machinery/sorting_machine/attack_hand(mob/user) - interact(user) - -/obj/machinery/sorting_machine/Topic(href, href_list) - . = ..() - if(.) - return - - if(href_list["close"]) - if(usr.machine == src) - usr.unset_machine() - return 1 - - src.add_fingerprint(usr)//After close, else it wouldn't make sense. - -/obj/machinery/sorting_machine/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) - return {" - - "} - -//Handles changing of the IO dirs, 'ID's: 1 is input, 2 is output, and 3 is filter, in this proc. - -/obj/machinery/sorting_machine/multitool_topic(var/mob/user, var/list/href_list, var/obj/item/device/multitool/P) - . = ..() - if(.) - return . - - if("changedir" in href_list) - var/changingdir = text2num(href_list["changedir"]) - changingdir = Clamp(changingdir, 1, 3)//No runtimes from HREF exploits. - - var/newdir = input("Select the new direction", "MinerX SortMaster 5000", "North") as null|anything in list("North", "South", "East", "West") - if(!newdir) - return 1 - newdir = text2dir(newdir) - - var/list/dirlist = list(input_dir, output_dir, filter_dir)//Behold the idea I got on how to do this. - var/olddir = dirlist[changingdir]//Store this for future reference before wiping it next line - dirlist[changingdir] = -1//Make the dir that's being changed -1 so it doesn't see itself. - - var/conflictingdir = dirlist.Find(newdir)//Check if the dir is conflicting with another one - if(conflictingdir)//Welp, it is. - dirlist[conflictingdir] = olddir//Set it to the olddir of the dir we're changing - - dirlist[changingdir] = newdir//Set the changindir to the selected dir - - input_dir = dirlist[1] - output_dir = dirlist[2] - filter_dir = dirlist[3] - - return MT_UPDATE - //Honestly I didn't expect that to fit in, what, 10 lines of code? - -//Return 1 if the atom is to be filtered of the line. -/obj/machinery/sorting_machine/proc/sort(var/atom/movable/A) - return prob(50) //Henk because the base sorting machine shouldn't ever exist anyways. - -//RECYCLING SORTING MACHINE. -//AKA the old sorting machine until I decided to use the sorting machines in an OOP way for BELT HELL! -/obj/machinery/sorting_machine/recycling - name = "Recycling Sorting Machine" - - var/list/selected_types = list("Glasses", "Metals/Minerals", "Electronics") - var/list/types[6] - -/obj/machinery/sorting_machine/recycling/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/sorting_machine/recycling, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/capacitor - ) - RefreshParts() - - // Set up types. BYOND is the dumb and won't let me do this in the var def. - types[RECYK_BIOLOGICAL] = "Biological" - types[RECYK_WOOD] = "Wooden" - types[RECYK_ELECTRONIC] = "Electronics" - types[RECYK_GLASS] = "Glasses" - types[RECYK_METAL] = "Metals/Minerals" - types[RECYK_MISC] = "Miscellaneous" - -/obj/machinery/sorting_machine/recycling/Topic(href, href_list) - . = ..() - if(.) - return - - if(href_list["toggle_types"]) - var/typeID = text2num(href_list["toggle_types"]) - - typeID = Clamp(typeID, 1, types.len)//No HREF exploits causing runtimes. - - if(types[typeID] in selected_types)//Toggle these - selected_types -= types[typeID] - else - selected_types += types[typeID] - - updateUsrDialog() - return 1 - -/obj/machinery/sorting_machine/recycling/sort(atom/movable/A) - return A.w_type && (types[A.w_type] in selected_types) - -/obj/machinery/sorting_machine/recycling/interact(mob/user) - if(stat & (BROKEN | NOPOWER)) - if(user.machine == src) - usr.unset_machine() - return - - user.set_machine(src) - - var/dat = "Select the desired items to sort from the line.
    " - - for (var/i = 1, i <= types.len, i++) - var/selected = (types[i] in selected_types) - var/cssclass = selected ? "linkOn" : "linkDanger"//Fancy coloured buttons - - dat += "[types[i]]
    " - - var/datum/browser/popup = new(user, "recycksortingmachine", name, 320, 200, src) - popup.add_stylesheet("shared", 'nano/css/shared.css') - popup.set_content(dat) - popup.open() - -//Essentially a standalone version of disposals sorting pipes. -/obj/machinery/sorting_machine/destination - name = "Destination Sorting Machine" - desc = "Like those disposals pipes sorting machines, except not in a pipe." - - var/list/destinations - var/list/sorting[0] - var/unwrapped = 0 //Whatever unwrapped packages should be picked from the line. - -/obj/machinery/sorting_machine/destination/New() - . = ..() - - destinations = DEFAULT_TAGGER_LOCATIONS.Copy() //Here because BYOND. - - for(var/i = 1, i <= destinations.len, i++) - destinations[i] = uppertext(destinations[i]) - - component_parts = newlist( - /obj/item/weapon/circuitboard/sorting_machine/destination, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/capacitor - ) - RefreshParts() - -/obj/machinery/sorting_machine/destination/interact(mob/user) - if(stat & (BROKEN | NOPOWER)) - if(user.machine == src) - usr.unset_machine() - return - - user.set_machine(src) - - var/dat = "Select the desired items to sort from the line.
    " - - for (var/i = 1, i <= destinations.len, i++) - var/selected = (destinations[i] in sorting) - var/cssclass = selected ? "linkOn" : "linkDanger" //Fancy coloured buttons - - dat += "[destinations[i]] \[X\]
    " - - dat += "Add a new destination

    " - - dat += "Filter unwrapped packages" - - var/datum/browser/popup = new(user, "destsortingmachine", name, 320, 200, src) - popup.add_stylesheet("shared", 'nano/css/shared.css') - popup.set_content(dat) - popup.open() - -/obj/machinery/sorting_machine/destination/sort(atom/movable/A) - if(istype(A, /obj/item/delivery/large)) - var/obj/item/delivery/large/B = A - return B.sortTag in sorting - - if(istype(A, /obj/item/delivery)) - var/obj/item/delivery/B = A - return B.sortTag in sorting - - return unwrapped - -/obj/machinery/sorting_machine/destination/Topic(href, href_list) - . = ..() - if(.) - return - - if(href_list["toggle_dest"]) - var/idx = Clamp(text2num(href_list["toggle_dest"]), 0, destinations.len) - if(destinations[idx] in sorting) - sorting -= destinations[idx] - else - sorting += destinations[idx] - updateUsrDialog() - return 1 - - if(href_list["remove_dest"]) - var/idx = Clamp(text2num(href_list["remove_dest"]), 0, destinations.len) - sorting -= destinations[idx] - destinations -= destinations[idx] - updateUsrDialog() - return 1 - - if(href_list["add_dest"]) - var/newtag = uppertext(copytext(sanitize(input(usr, "Destination ID?","Add Destination") as text), 1, MAX_NAME_LEN)) - destinations |= newtag - updateUsrDialog() - return 1 - - if(href_list["toggle_wrapped"]) - unwrapped = !unwrapped - updateUsrDialog() - return 1 - -/obj/machinery/sorting_machine/destination/unwrapped - unwrapped = 1 - -/obj/machinery/sorting_machine/destination/taxi_engi - sorting = list( - "QM OFFICE", - "CARGO BAY", - "JANITOR CLOSET", - "HOP OFFICE", - "HYDROPONICS", - "KITCHEN", - "THEATRE", - "BAR", - "ATMOSPHERICS", - "CE OFFICE", - "ENGINEERING" - ) - -/obj/machinery/sorting_machine/destination/taxi_engi/unwrapped - unwrapped = 1 - -/obj/machinery/sorting_machine/destination/taxi_med - sorting = list( - "MEDBAY", - "CMO OFFICE", - "CHEMISTRY", - "GENETICS", - "RESEARCH", - "RD OFFICE", - "TELECOMMS", - "ROBOTICS" - ) - -/obj/machinery/sorting_machine/destination/taxi_secsci - sorting = list( - "SECURITY", - "HOS OFFICE", - "CHAPEL", - "LIBRARY" - ) +//Default list destination taggers and such can use. + +var/list/DEFAULT_TAGGER_LOCATIONS = list( + "Disposals", + "Cargo Bay", + "QM Office", + "Engineering", + "CE Office", + "Atmospherics", + "Security", + "HoS Office", + "Medbay", + "CMO Office", + "Chemistry", + "Research", + "RD Office", + "Robotics", + "HoP Office", + "Library", + "Chapel", + "Theatre", + "Bar", + "Kitchen", + "Hydroponics", + "Janitor Closet", + "Genetics", + "Telecomms", + "Mechanics", + "Telescience" + ) + +/obj/item/device/destTagger + name = "destination tagger" + desc = "Used to set the destination of properly wrapped packages." + icon_state = "dest_tagger" + + var/panel = 0 //If the panel is open. + var/mode = 0 //If the tagger is "hacked" so you can add extra tags. + + var/currTag = 0 + var/list/destinations + + w_class = 1 + item_state = "electronic" + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + +/obj/item/device/destTagger/panel + panel = 1 + +/obj/item/device/destTagger/panel/New() + . = ..() + update_icon() + +/obj/item/device/destTagger/New() + . = ..() + destinations = DEFAULT_TAGGER_LOCATIONS.Copy() //T-thanks BYOND. + +/obj/item/device/destTagger/interact(mob/user as mob) + + var/dat = "" + + for (var/i = 1, i <= destinations.len, i++) + dat += "" + + if (i % 4 == 0) + dat += "" + + dat += "
    [destinations[i]][mode ? "\[X\]" : ""]

    Current Selection: [currTag ? destinations[currTag] : "None"].

    " + + if(mode) + dat += "Add destination" + + var/datum/browser/popup = new(user, "destTagger", name, 380, 350, src) + popup.add_stylesheet("shared", 'nano/css/shared.css') + popup.set_content(dat) + popup.open() + +/obj/item/device/destTagger/attack_self(mob/user as mob) + interact(user) + +/obj/item/device/destTagger/attackby(obj/item/W, mob/user) + if(isscrewdriver(W)) + panel = !panel + to_chat(user, "You [panel ? "open" : "close"] the panel on \the [src].") + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + update_icon() + return 1 + + if(ismultitool(W) && panel) + mode = !mode + to_chat(user, "You [mode ? "disable" : "enable"] the lock on \the [src].") + return 1 + + . = ..() + +/obj/item/device/destTagger/update_icon() + if(panel) + icon_state = "dest_tagger_p" + desc += "\nThe panel appears to be open." + else + icon_state = "dest_tagger" + desc = initial(desc) + +/obj/item/device/destTagger/Topic(href, href_list) + . = ..() + if(.) + return + + add_fingerprint(usr) + + if(href_list["nextTag"]) + currTag = Clamp(text2num(href_list["nextTag"]), 0, destinations.len) + interact(usr) + return 1 + + if(href_list["remove_dest"] && mode) + var/idx = Clamp(text2num(href_list["remove_dest"]), 1, destinations.len) + destinations -= destinations[idx] + interact(usr) + return 1 + + if(href_list["new_dest"] && mode) + var/newtag = uppertext(copytext(sanitize(input(usr, "Destination ID?","Add Destination") as text), 1, MAX_NAME_LEN)) + destinations |= newtag + interact(usr) + return 1 + +/obj/machinery/disposal/deliveryChute + name = "Delivery chute" + desc = "A chute for big and small packages alike!" + density = 1 + icon_state = "intake" + var/c_mode = 0 + var/doFlushIn=0 + var/num_contents=0 + +/obj/machinery/disposal/deliveryChute/New() + ..() + processing_objects.Remove(src) + spawn(5) + trunk = locate() in src.loc + if(trunk) + trunk.linked = src // link the pipe trunk to self + +/obj/machinery/disposal/deliveryChute/interact() + return + +/obj/machinery/disposal/deliveryChute/update_icon() + return + +/obj/machinery/disposal/deliveryChute/Bumped(var/atom/movable/AM) //Go straight into the chute + if(istype(AM, /obj/item/projectile) || istype(AM, /obj/item/weapon/dummy)) return + + if(dir != get_dir(src, AM)) + return + + //testing("[src] FUCKING BUMPED BY \a [AM]") + + if(istype(AM, /obj)) + var/obj/O = AM + O.loc = src + else if(istype(AM, /mob)) + var/mob/M = AM + M.loc = src + //src.flush() This spams audio like fucking crazy. + // Instead, we queue up for the next process. + doFlushIn=5 // Ticks, adjust if delay is too long or too short + num_contents++ + +/obj/machinery/disposal/deliveryChute/flush() + flushing = 1 + flick("intake-closing", src) + var/deliveryCheck = 0 + var/obj/structure/disposalholder/H = new() // virtual holder object which actually + // travels through the pipes. + for(var/obj/item/delivery/large/O in src) + deliveryCheck = 1 + if(O.sortTag == 0) + O.sortTag = "DISPOSALS" + for(var/obj/item/delivery/O in src) + deliveryCheck = 1 + if (O.sortTag == 0) + O.sortTag = "DISPOSALS" + if(deliveryCheck == 0) + H.destinationTag = "DISPOSALS" + + air_contents = new() // new empty gas resv. + + sleep(10) + playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0) + sleep(5) // wait for animation to finish + + H.init(src) // copy the contents of disposer to holder + num_contents=0 + doFlushIn=0 + + H.start(src) // start the holder processing movement + flushing = 0 + // now reset disposal state + flush = 0 + if(mode == 2) // if was ready, + mode = 1 // switch to charging + update_icon() + return + +/obj/machinery/disposal/deliveryChute/attackby(var/obj/item/I, var/mob/user) + if(!I || !user) + return + + if(istype(I, /obj/item/weapon/screwdriver)) + if(c_mode==0) + c_mode=1 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You remove the screws around the power connection.") + return + else if(c_mode==1) + c_mode=0 + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You attach the screws around the power connection.") + return + else if(istype(I,/obj/item/weapon/weldingtool) && c_mode==1) + var/obj/item/weapon/weldingtool/W = I + if(W.remove_fuel(0,user)) + playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + to_chat(user, "You start slicing the floorweld off the delivery chute.") + if(do_after(user, src,20)) + if(!src || !W.isOn()) return + to_chat(user, "You sliced the floorweld off the delivery chute.") + var/obj/structure/disposalconstruct/C = new (src.loc) + C.ptype = 8 // 8 = Delivery chute + C.update() + C.anchored = 1 + C.density = 1 + qdel(src) + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + +/obj/machinery/disposal/deliveryChute/process() + if(doFlushIn>0) + if(doFlushIn==1 || num_contents>=50) + //testing("[src] FLUSHING") + spawn(0) + src.flush() + doFlushIn-- + +//Base framework for sorting machines. +/obj/machinery/sorting_machine + name = "Sorting Machine" + desc = "Sorts stuff." + density = 1 + icon = 'icons/obj/recycling.dmi' + icon_state = "grinder-b1" + anchored = 1 + + machine_flags = SCREWTOGGLE | CROWDESTROY | MULTITOOL_MENU + + idle_power_usage = 100 //No active power usage because this thing passively uses 100, always. Don't ask me why N3X15 coded it like this. + + var/atom/movable/mover //Virtual atom used to check passing ability on the out turf. + + var/input_dir = EAST + var/output_dir = WEST + var/filter_dir = SOUTH + + var/max_items_moved = 100 + +/obj/machinery/sorting_machine/New() + . = ..() + + mover = new + +/obj/machinery/sorting_machine/Destroy() + . = ..() + + qdel(mover) + mover = null + +/obj/machinery/sorting_machine/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/bin in component_parts) + T += bin.rating//intentionally not doing '- 1' here, for the math below + max_items_moved = initial(max_items_moved) * (T / 3) //Usefull upgrade/10, that's an increase from 10 (base matter bins) to 30 (super matter bins) + + T = 0//reusing T here because muh RAM + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) + T += C.rating - 1 + idle_power_usage = initial(idle_power_usage) - (T * (initial(idle_power_usage) / 4))//25% power usage reduction for an advanced capacitor, 50% for a super one. + +/obj/machinery/sorting_machine/process() + if(stat & (BROKEN | NOPOWER)) + return + + var/turf/in_T = get_step(src, input_dir) + var/turf/out_T = get_step(src, output_dir) + var/turf/filter_T = get_step(src, filter_dir) + + if(!out_T.CanPass(mover, out_T) || !out_T.Enter(mover) || !filter_T.CanPass(mover, filter_T) || !filter_T.Enter(mover)) + return + + var/affecting = in_T.contents + var/items_moved = 0 + + for(var/atom/movable/A in affecting) + if(A.anchored) + continue + + if(sort(A)) + A.forceMove(filter_T) + else + A.forceMove(out_T) + + items_moved++ + if(items_moved >= max_items_moved) + break + +/obj/machinery/sorting_machine/attack_ai(mob/user) + interact(user) + +/obj/machinery/sorting_machine/attack_hand(mob/user) + interact(user) + +/obj/machinery/sorting_machine/Topic(href, href_list) + . = ..() + if(.) + return + + if(href_list["close"]) + if(usr.machine == src) + usr.unset_machine() + return 1 + + src.add_fingerprint(usr)//After close, else it wouldn't make sense. + +/obj/machinery/sorting_machine/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) + return {" + + "} + +//Handles changing of the IO dirs, 'ID's: 1 is input, 2 is output, and 3 is filter, in this proc. + +/obj/machinery/sorting_machine/multitool_topic(var/mob/user, var/list/href_list, var/obj/item/device/multitool/P) + . = ..() + if(.) + return . + + if("changedir" in href_list) + var/changingdir = text2num(href_list["changedir"]) + changingdir = Clamp(changingdir, 1, 3)//No runtimes from HREF exploits. + + var/newdir = input("Select the new direction", "MinerX SortMaster 5000", "North") as null|anything in list("North", "South", "East", "West") + if(!newdir) + return 1 + newdir = text2dir(newdir) + + var/list/dirlist = list(input_dir, output_dir, filter_dir)//Behold the idea I got on how to do this. + var/olddir = dirlist[changingdir]//Store this for future reference before wiping it next line + dirlist[changingdir] = -1//Make the dir that's being changed -1 so it doesn't see itself. + + var/conflictingdir = dirlist.Find(newdir)//Check if the dir is conflicting with another one + if(conflictingdir)//Welp, it is. + dirlist[conflictingdir] = olddir//Set it to the olddir of the dir we're changing + + dirlist[changingdir] = newdir//Set the changindir to the selected dir + + input_dir = dirlist[1] + output_dir = dirlist[2] + filter_dir = dirlist[3] + + return MT_UPDATE + //Honestly I didn't expect that to fit in, what, 10 lines of code? + +//Return 1 if the atom is to be filtered of the line. +/obj/machinery/sorting_machine/proc/sort(var/atom/movable/A) + return prob(50) //Henk because the base sorting machine shouldn't ever exist anyways. + +//RECYCLING SORTING MACHINE. +//AKA the old sorting machine until I decided to use the sorting machines in an OOP way for BELT HELL! +/obj/machinery/sorting_machine/recycling + name = "Recycling Sorting Machine" + + var/list/selected_types = list("Glasses", "Metals/Minerals", "Electronics") + var/list/types[6] + +/obj/machinery/sorting_machine/recycling/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/sorting_machine/recycling, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/capacitor + ) + RefreshParts() + + // Set up types. BYOND is the dumb and won't let me do this in the var def. + types[RECYK_BIOLOGICAL] = "Biological" + types[RECYK_WOOD] = "Wooden" + types[RECYK_ELECTRONIC] = "Electronics" + types[RECYK_GLASS] = "Glasses" + types[RECYK_METAL] = "Metals/Minerals" + types[RECYK_MISC] = "Miscellaneous" + +/obj/machinery/sorting_machine/recycling/Topic(href, href_list) + . = ..() + if(.) + return + + if(href_list["toggle_types"]) + var/typeID = text2num(href_list["toggle_types"]) + + typeID = Clamp(typeID, 1, types.len)//No HREF exploits causing runtimes. + + if(types[typeID] in selected_types)//Toggle these + selected_types -= types[typeID] + else + selected_types += types[typeID] + + updateUsrDialog() + return 1 + +/obj/machinery/sorting_machine/recycling/sort(atom/movable/A) + return A.w_type && (types[A.w_type] in selected_types) + +/obj/machinery/sorting_machine/recycling/interact(mob/user) + if(stat & (BROKEN | NOPOWER)) + if(user.machine == src) + usr.unset_machine() + return + + user.set_machine(src) + + var/dat = "Select the desired items to sort from the line.
    " + + for (var/i = 1, i <= types.len, i++) + var/selected = (types[i] in selected_types) + var/cssclass = selected ? "linkOn" : "linkDanger"//Fancy coloured buttons + + dat += "[types[i]]
    " + + var/datum/browser/popup = new(user, "recycksortingmachine", name, 320, 200, src) + popup.add_stylesheet("shared", 'nano/css/shared.css') + popup.set_content(dat) + popup.open() + +//Essentially a standalone version of disposals sorting pipes. +/obj/machinery/sorting_machine/destination + name = "Destination Sorting Machine" + desc = "Like those disposals pipes sorting machines, except not in a pipe." + + var/list/destinations + var/list/sorting[0] + var/unwrapped = 0 //Whatever unwrapped packages should be picked from the line. + +/obj/machinery/sorting_machine/destination/New() + . = ..() + + destinations = DEFAULT_TAGGER_LOCATIONS.Copy() //Here because BYOND. + + for(var/i = 1, i <= destinations.len, i++) + destinations[i] = uppertext(destinations[i]) + + component_parts = newlist( + /obj/item/weapon/circuitboard/sorting_machine/destination, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/capacitor + ) + RefreshParts() + +/obj/machinery/sorting_machine/destination/interact(mob/user) + if(stat & (BROKEN | NOPOWER)) + if(user.machine == src) + usr.unset_machine() + return + + user.set_machine(src) + + var/dat = "Select the desired items to sort from the line.
    " + + for (var/i = 1, i <= destinations.len, i++) + var/selected = (destinations[i] in sorting) + var/cssclass = selected ? "linkOn" : "linkDanger" //Fancy coloured buttons + + dat += "[destinations[i]] \[X\]
    " + + dat += "Add a new destination

    " + + dat += "Filter unwrapped packages" + + var/datum/browser/popup = new(user, "destsortingmachine", name, 320, 200, src) + popup.add_stylesheet("shared", 'nano/css/shared.css') + popup.set_content(dat) + popup.open() + +/obj/machinery/sorting_machine/destination/sort(atom/movable/A) + if(istype(A, /obj/item/delivery/large)) + var/obj/item/delivery/large/B = A + return B.sortTag in sorting + + if(istype(A, /obj/item/delivery)) + var/obj/item/delivery/B = A + return B.sortTag in sorting + + return unwrapped + +/obj/machinery/sorting_machine/destination/Topic(href, href_list) + . = ..() + if(.) + return + + if(href_list["toggle_dest"]) + var/idx = Clamp(text2num(href_list["toggle_dest"]), 0, destinations.len) + if(destinations[idx] in sorting) + sorting -= destinations[idx] + else + sorting += destinations[idx] + updateUsrDialog() + return 1 + + if(href_list["remove_dest"]) + var/idx = Clamp(text2num(href_list["remove_dest"]), 0, destinations.len) + sorting -= destinations[idx] + destinations -= destinations[idx] + updateUsrDialog() + return 1 + + if(href_list["add_dest"]) + var/newtag = uppertext(copytext(sanitize(input(usr, "Destination ID?","Add Destination") as text), 1, MAX_NAME_LEN)) + destinations |= newtag + updateUsrDialog() + return 1 + + if(href_list["toggle_wrapped"]) + unwrapped = !unwrapped + updateUsrDialog() + return 1 + +/obj/machinery/sorting_machine/destination/unwrapped + unwrapped = 1 + +/obj/machinery/sorting_machine/destination/taxi_engi + sorting = list( + "QM OFFICE", + "CARGO BAY", + "JANITOR CLOSET", + "HOP OFFICE", + "HYDROPONICS", + "KITCHEN", + "THEATRE", + "BAR", + "ATMOSPHERICS", + "CE OFFICE", + "ENGINEERING" + ) + +/obj/machinery/sorting_machine/destination/taxi_engi/unwrapped + unwrapped = 1 + +/obj/machinery/sorting_machine/destination/taxi_med + sorting = list( + "MEDBAY", + "CMO OFFICE", + "CHEMISTRY", + "GENETICS", + "RESEARCH", + "RD OFFICE", + "TELECOMMS", + "ROBOTICS" + ) + +/obj/machinery/sorting_machine/destination/taxi_secsci + sorting = list( + "SECURITY", + "HOS OFFICE", + "CHAPEL", + "LIBRARY" + ) diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index aac4bbb9ceb..ac72ebcd413 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -1,76 +1,76 @@ -/*///////////////Circuit Imprinter (By Darem)//////////////////////// - Used to print new circuit boards (for computers and similar systems) and AI modules. Each circuit board pattern are stored in -a /datum/desgin on the linked R&D console. You can then print them out in a fasion similar to a regular lathe. However, instead of -using metal and glass, it uses glass and reagents (usually sulfuric acis). - -*/ - -#define IMPRINTER_BUILD_TIME 1 - -/obj/machinery/r_n_d/fabricator/circuit_imprinter - name = "Circuit Imprinter" - icon_state = "circuit_imprinter" - desc = "A fabricator capable of etching circuit designs onto glass and minerals." - flags = OPENCONTAINER - - max_material_storage = 75000 - build_time = IMPRINTER_BUILD_TIME - build_number = 1 - - research_flags = HASOUTPUT | TAKESMATIN | CONSOLECONTROL | LOCKBOXES - - part_sets = list( - "Machine Boards" = list(), - "Console Boards" = list(), - "Mecha Boards" = list(), - "Module Boards" = list(), - "Engineering Boards" = list(), - "Misc" = list() - ) - - allowed_materials = list( - MAT_GLASS, - MAT_GOLD, - MAT_DIAMOND, - MAT_URANIUM, - MAT_PLASMA - ) - -/obj/machinery/r_n_d/fabricator/circuit_imprinter/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/circuit_imprinter, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/beaker - ) - - // Don't log reagent transfers. They're just spammy. - log_reagents=0 - - RefreshParts() - -/obj/machinery/r_n_d/fabricator/circuit_imprinter/Destroy() - if(linked_console && linked_console.linked_imprinter == src) - linked_console.linked_imprinter = null //Clearing of the rest is handled in the parent. - - . = ..() - - -/obj/machinery/r_n_d/fabricator/circuit_imprinter/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) - T += G.reagents.maximum_volume - - create_reagents(T) // Holder for the reagents used as materials. - T = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) - T += M.rating - max_material_storage = T * 75000 - -/obj/machinery/r_n_d/fabricator/circuit_imprinter/attackby(var/obj/item/O as obj, var/mob/user as mob) - ..() - if (O.is_open_container()) - return 0 +/*///////////////Circuit Imprinter (By Darem)//////////////////////// + Used to print new circuit boards (for computers and similar systems) and AI modules. Each circuit board pattern are stored in +a /datum/desgin on the linked R&D console. You can then print them out in a fasion similar to a regular lathe. However, instead of +using metal and glass, it uses glass and reagents (usually sulfuric acis). + +*/ + +#define IMPRINTER_BUILD_TIME 1 + +/obj/machinery/r_n_d/fabricator/circuit_imprinter + name = "Circuit Imprinter" + icon_state = "circuit_imprinter" + desc = "A fabricator capable of etching circuit designs onto glass and minerals." + flags = OPENCONTAINER + + max_material_storage = 75000 + build_time = IMPRINTER_BUILD_TIME + build_number = 1 + + research_flags = HASOUTPUT | TAKESMATIN | CONSOLECONTROL | LOCKBOXES + + part_sets = list( + "Machine Boards" = list(), + "Console Boards" = list(), + "Mecha Boards" = list(), + "Module Boards" = list(), + "Engineering Boards" = list(), + "Misc" = list() + ) + + allowed_materials = list( + MAT_GLASS, + MAT_GOLD, + MAT_DIAMOND, + MAT_URANIUM, + MAT_PLASMA + ) + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/circuit_imprinter, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/reagent_containers/glass/beaker + ) + + // Don't log reagent transfers. They're just spammy. + log_reagents=0 + + RefreshParts() + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/Destroy() + if(linked_console && linked_console.linked_imprinter == src) + linked_console.linked_imprinter = null //Clearing of the rest is handled in the parent. + + . = ..() + + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) + T += G.reagents.maximum_volume + + create_reagents(T) // Holder for the reagents used as materials. + T = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) + T += M.rating + max_material_storage = T * 75000 + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/attackby(var/obj/item/O as obj, var/mob/user as mob) + ..() + if (O.is_open_container()) + return 0 diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 421abfece7c..d4caafd94aa 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1,162 +1,162 @@ - //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/*************************************************************** -** Design Datums ** -** All the data for building stuff and tracking reliability. ** -***************************************************************/ -/* -For the materials datum, it assumes you need reagents unless specified otherwise. To designate a material that isn't a reagent, -you use one of the material IDs below. These are NOT ids in the usual sense (they aren't defined in the object or part of a datum), -they are simply references used as part of a "has materials?" type proc. They all start with a $ to denote that they aren't reagents. -The currently supporting non-reagent materials: -- $iron (/obj/item/stack/metal). One sheet = 3750 units. NB: do not use $metal. It is outdated and will cause issues -- $glass (/obj/item/stack/glass). One sheet = 3750 units. -- $plasma (/obj/item/stack/plasma). One sheet = 3750 units. -- $silver (/obj/item/stack/silver). One sheet = 3750 units. -- $gold (/obj/item/stack/gold). One sheet = 3750 units. -- $uranium (/obj/item/stack/uranium). One sheet = 3750 units. -- $diamond (/obj/item/stack/diamond). One sheet = 3750 units. -- $clown (/obj/item/stack/clown). One sheet = 3750 units. ("Bananium") -- $cardboard (/obj/item/stack/sheet/cardboard). One sheet = 3750 units. -(Insert new ones here) - -Don't add new keyword/IDs if they are made from an existing one (such as rods which are made from metal). Only add raw materials. - -Design Guidlines -- The reliability formula for all R&D built items is reliability_base (a fixed number) + total tech levels required to make it + -reliability_mod (starts at 0, gets improved through experimentation). Example: PACMAN generator. 79 base reliablity + 6 tech -(3 plasmatech, 3 powerstorage) + 0 (since it's completely new) = 85% reliability. Reliability is the chance it works CORRECTLY. -- When adding new designs, check rdreadme.dm to see what kind of things have already been made and where new stuff is needed. -- A single sheet of anything is 3750 units of material. Materials besides metal/glass require help from other jobs (mining for -other types of metals and chemistry for reagents). -- Add the AUTOLATHE tag to - -The required techs are the following: -- Materials Research max=9 "materials" -- Engineering Research max=5 "engineering" -- Plasma Research max=4 "plasmatech" -- Power Manipulation Technology max=6 "powerstorage" -- 'Blue-space' Research max=10 "bluespace" -- Biological Technology max=5 "biotech" -- Combat Systems Research max=6 "combat" -- Electromagnetic Spectrum Research max=8 "magnets" -- Data Theory Research max=5 "programming" -- Illegal Technologies Research max=8 "syndicate" -*/ - -#define IMPRINTER 1 //For circuits. Uses glass/chemicals. -#define PROTOLATHE 2 //New stuff. Uses glass/metal/chemicals -#define AUTOLATHE 4 //Uses glass/metal only. -#define CRAFTLATHE 8 //Uses fuck if I know. For use eventually. -#define MECHFAB 16 //Remember, objects built under fabricators need DESIGNS -#define PODFAB 32 //Used by the spacepod part fabricator. Same idea as the mechfab -#define FLATPACKER 64 //This design creates a machine, not an item. -#define GENFAB 128 //Generic item. -//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable. - -/datum/design //Datum for object designs, used in construction - var/name = "Name" //Name of the created object. - var/desc = "Desc" //Description of the created object. - var/id = "id" //ID of the created object for easy refernece. Alphanumeric, lower-case, no symbols - var/list/req_tech = list() //IDs of that techs the object originated from and the minimum level requirements. - var/reliability_mod = 0 //Reliability modifier of the device at it's starting point. - var/reliability_base = 100 //Base reliability of a device before modifiers. - var/reliability = 100 //Reliability of the device. - var/build_type = null //Flag as to what kind machine the design is built in. See defines. - var/list/materials = list() //List of materials. Format: "id" = amount. - var/build_path = null //The file path of the object that gets created - var/locked = 0 //If true it will spawn inside a lockbox with currently sec access - var/list/req_lock_access //Sets the access for the lockbox that a locked item spawns in - var/category = "Misc" //Primarily used for Mech Fabricators, but can be used for anything - -//A proc to calculate the reliability of a design based on tech levels and innate modifiers. -//Input: A list of /datum/tech; Output: The new reliabilty. -/datum/design/proc/CalcReliability(var/list/temp_techs) - var/new_reliability = reliability_mod + reliability_base - for(var/datum/tech/T in temp_techs) - if(T.id in req_tech) - new_reliability += T.level - new_reliability = Clamp(new_reliability, reliability_base, 100) - reliability = new_reliability - return - -//give it an object or a type -//if it gets passed an object, it makes it into a type -//it then finds the design which has a buildpath of that type -//material_strict will check the atom's materials against the design's materials if set to 1, but won't for machines -//If you want to check machine materials strictly as well, set material_strict to 2 -proc/FindDesign(var/atom/part, material_strict = 0) - if(ispath(part)) - return FindTypeDesign(part) - - if(!istype(part)) - return - - for(var/datum/design/D in design_list) - if(D.build_path == part.type) - if(material_strict && ((istype(part, /obj/machinery) && material_strict == 2) || (!istype(part, /obj/machinery) && material_strict)) && istype(part.materials, /list)) //if we care about materials, we have to check candidates - var/all_correct = 1 - - for(var/matID in D.materials) - if(copytext(matID, 1, 2) == "$" && (part.materials.storage[matID] != D.materials[matID])) //if it's a materal, but it doesn't match the atom's values - all_correct = 0 - break - if(all_correct) - return D - else - return D - -proc/FindTypeDesign(var/part_path) - for(var/datum/design/D in design_list) - if(D.build_path == part_path) - return D - -//Acts as FindDesign, but makes a new design if it doesn't find one -//Doesn't take types for the design creation, so don't rely on it for that -proc/getScanDesign(var/obj/O) - var/datum/design/D - if(O.materials) - D = FindDesign(O, 1) //The 1 means we check strict materials - if we don't have materials, we just check the type - else - D = FindDesign(O) - if(D) - return D - - else - return new/datum/design/mechanic_design(O) - -//sum of the required tech of a design -/datum/design/proc/TechTotal() - var/total = 0 - for(var/tech in src.req_tech) - total += src.req_tech[tech] - return total - -//sum of the required materials of a design -//do not confuse this with Total_Materials. That gets the machine's materials, this gets design materials -/datum/design/proc/MatTotal() - var/total = 0 - for(var/matID in src.materials) - total += src.materials[matID] - //log_admin("[total] for [part.name]") - return total - -//////////////////////////////////////// -//Disks for transporting design datums// -//////////////////////////////////////// - -/obj/item/weapon/disk/design_disk - name = "Component Design Disk" - desc = "A disk for storing device design data for construction in lathes." - icon = 'icons/obj/cloning.dmi' - icon_state = "datadisk2" - item_state = "card-id" - w_class = 1.0 - starting_materials = list(MAT_IRON = 30, MAT_GLASS = 10) - w_type = RECYK_ELECTRONIC - var/datum/design/blueprint - -/obj/item/weapon/disk/design_disk/New() - ..() - src.pixel_x = rand(-5.0, 5) - src.pixel_y = rand(-5.0, 5) + //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/*************************************************************** +** Design Datums ** +** All the data for building stuff and tracking reliability. ** +***************************************************************/ +/* +For the materials datum, it assumes you need reagents unless specified otherwise. To designate a material that isn't a reagent, +you use one of the material IDs below. These are NOT ids in the usual sense (they aren't defined in the object or part of a datum), +they are simply references used as part of a "has materials?" type proc. They all start with a $ to denote that they aren't reagents. +The currently supporting non-reagent materials: +- $iron (/obj/item/stack/metal). One sheet = 3750 units. NB: do not use $metal. It is outdated and will cause issues +- $glass (/obj/item/stack/glass). One sheet = 3750 units. +- $plasma (/obj/item/stack/plasma). One sheet = 3750 units. +- $silver (/obj/item/stack/silver). One sheet = 3750 units. +- $gold (/obj/item/stack/gold). One sheet = 3750 units. +- $uranium (/obj/item/stack/uranium). One sheet = 3750 units. +- $diamond (/obj/item/stack/diamond). One sheet = 3750 units. +- $clown (/obj/item/stack/clown). One sheet = 3750 units. ("Bananium") +- $cardboard (/obj/item/stack/sheet/cardboard). One sheet = 3750 units. +(Insert new ones here) + +Don't add new keyword/IDs if they are made from an existing one (such as rods which are made from metal). Only add raw materials. + +Design Guidlines +- The reliability formula for all R&D built items is reliability_base (a fixed number) + total tech levels required to make it + +reliability_mod (starts at 0, gets improved through experimentation). Example: PACMAN generator. 79 base reliablity + 6 tech +(3 plasmatech, 3 powerstorage) + 0 (since it's completely new) = 85% reliability. Reliability is the chance it works CORRECTLY. +- When adding new designs, check rdreadme.dm to see what kind of things have already been made and where new stuff is needed. +- A single sheet of anything is 3750 units of material. Materials besides metal/glass require help from other jobs (mining for +other types of metals and chemistry for reagents). +- Add the AUTOLATHE tag to + +The required techs are the following: +- Materials Research max=9 "materials" +- Engineering Research max=5 "engineering" +- Plasma Research max=4 "plasmatech" +- Power Manipulation Technology max=6 "powerstorage" +- 'Blue-space' Research max=10 "bluespace" +- Biological Technology max=5 "biotech" +- Combat Systems Research max=6 "combat" +- Electromagnetic Spectrum Research max=8 "magnets" +- Data Theory Research max=5 "programming" +- Illegal Technologies Research max=8 "syndicate" +*/ + +#define IMPRINTER 1 //For circuits. Uses glass/chemicals. +#define PROTOLATHE 2 //New stuff. Uses glass/metal/chemicals +#define AUTOLATHE 4 //Uses glass/metal only. +#define CRAFTLATHE 8 //Uses fuck if I know. For use eventually. +#define MECHFAB 16 //Remember, objects built under fabricators need DESIGNS +#define PODFAB 32 //Used by the spacepod part fabricator. Same idea as the mechfab +#define FLATPACKER 64 //This design creates a machine, not an item. +#define GENFAB 128 //Generic item. +//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable. + +/datum/design //Datum for object designs, used in construction + var/name = "Name" //Name of the created object. + var/desc = "Desc" //Description of the created object. + var/id = "id" //ID of the created object for easy refernece. Alphanumeric, lower-case, no symbols + var/list/req_tech = list() //IDs of that techs the object originated from and the minimum level requirements. + var/reliability_mod = 0 //Reliability modifier of the device at it's starting point. + var/reliability_base = 100 //Base reliability of a device before modifiers. + var/reliability = 100 //Reliability of the device. + var/build_type = null //Flag as to what kind machine the design is built in. See defines. + var/list/materials = list() //List of materials. Format: "id" = amount. + var/build_path = null //The file path of the object that gets created + var/locked = 0 //If true it will spawn inside a lockbox with currently sec access + var/list/req_lock_access //Sets the access for the lockbox that a locked item spawns in + var/category = "Misc" //Primarily used for Mech Fabricators, but can be used for anything + +//A proc to calculate the reliability of a design based on tech levels and innate modifiers. +//Input: A list of /datum/tech; Output: The new reliabilty. +/datum/design/proc/CalcReliability(var/list/temp_techs) + var/new_reliability = reliability_mod + reliability_base + for(var/datum/tech/T in temp_techs) + if(T.id in req_tech) + new_reliability += T.level + new_reliability = Clamp(new_reliability, reliability_base, 100) + reliability = new_reliability + return + +//give it an object or a type +//if it gets passed an object, it makes it into a type +//it then finds the design which has a buildpath of that type +//material_strict will check the atom's materials against the design's materials if set to 1, but won't for machines +//If you want to check machine materials strictly as well, set material_strict to 2 +proc/FindDesign(var/atom/part, material_strict = 0) + if(ispath(part)) + return FindTypeDesign(part) + + if(!istype(part)) + return + + for(var/datum/design/D in design_list) + if(D.build_path == part.type) + if(material_strict && ((istype(part, /obj/machinery) && material_strict == 2) || (!istype(part, /obj/machinery) && material_strict)) && istype(part.materials, /list)) //if we care about materials, we have to check candidates + var/all_correct = 1 + + for(var/matID in D.materials) + if(copytext(matID, 1, 2) == "$" && (part.materials.storage[matID] != D.materials[matID])) //if it's a materal, but it doesn't match the atom's values + all_correct = 0 + break + if(all_correct) + return D + else + return D + +proc/FindTypeDesign(var/part_path) + for(var/datum/design/D in design_list) + if(D.build_path == part_path) + return D + +//Acts as FindDesign, but makes a new design if it doesn't find one +//Doesn't take types for the design creation, so don't rely on it for that +proc/getScanDesign(var/obj/O) + var/datum/design/D + if(O.materials) + D = FindDesign(O, 1) //The 1 means we check strict materials - if we don't have materials, we just check the type + else + D = FindDesign(O) + if(D) + return D + + else + return new/datum/design/mechanic_design(O) + +//sum of the required tech of a design +/datum/design/proc/TechTotal() + var/total = 0 + for(var/tech in src.req_tech) + total += src.req_tech[tech] + return total + +//sum of the required materials of a design +//do not confuse this with Total_Materials. That gets the machine's materials, this gets design materials +/datum/design/proc/MatTotal() + var/total = 0 + for(var/matID in src.materials) + total += src.materials[matID] + //log_admin("[total] for [part.name]") + return total + +//////////////////////////////////////// +//Disks for transporting design datums// +//////////////////////////////////////// + +/obj/item/weapon/disk/design_disk + name = "Component Design Disk" + desc = "A disk for storing device design data for construction in lathes." + icon = 'icons/obj/cloning.dmi' + icon_state = "datadisk2" + item_state = "card-id" + w_class = 1.0 + starting_materials = list(MAT_IRON = 30, MAT_GLASS = 10) + w_type = RECYK_ELECTRONIC + var/datum/design/blueprint + +/obj/item/weapon/disk/design_disk/New() + ..() + src.pixel_x = rand(-5.0, 5) + src.pixel_y = rand(-5.0, 5) diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 47f23af30b6..55a050c0e45 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -1,114 +1,114 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/* -Destructive Analyzer - -It is used to destroy hand-held objects and advance technological research. Controls are in the linked R&D console. - -Note: Must be placed within 3 tiles of the R&D Console -*/ -/obj/machinery/r_n_d/destructive_analyzer - name = "Destructive Analyzer" - icon_state = "d_analyzer" - var/obj/item/weapon/loaded_item = null - var/decon_mod = 1 - - research_flags = CONSOLECONTROL - -/obj/machinery/r_n_d/destructive_analyzer/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/destructive_analyzer, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/micro_laser - ) - - RefreshParts() - -/obj/machinery/r_n_d/destructive_analyzer/Destroy() - if(linked_console && linked_console.linked_destroy == src) - linked_console.linked_destroy = null - - . = ..() - -/obj/machinery/r_n_d/destructive_analyzer/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/S in component_parts) - T += S.rating * 0.1 - T = Clamp(T, 0, 1) - decon_mod = T - -/obj/machinery/r_n_d/destructive_analyzer/proc/ConvertReqString2List(var/list/source_list) - var/list/temp_list = params2list(source_list) - for(var/O in temp_list) - temp_list[O] = text2num(temp_list[O]) - return temp_list - -/obj/machinery/r_n_d/destructive_analyzer/togglePanelOpen(var/obj/toggleitem, mob/user) - if(loaded_item) - to_chat(user, "You can't open the maintenance panel while an item is loaded!") - return -1 - return ..() - -/obj/machinery/r_n_d/destructive_analyzer/crowbarDestroy(mob/user) - if(..() == 1) - if(loaded_item) - loaded_item.forceMove(loc) - return 1 - return -1 - -/obj/machinery/r_n_d/destructive_analyzer/attackby(var/obj/O as obj, var/mob/user as mob) - if(..()) - return 1 - if (istype(O, /obj/item) && !loaded_item && !panel_open) - if(isrobot(user)) //Don't put your module items in there! - if(isMoMMI(user)) - var/mob/living/silicon/robot/mommi/mommi = user - if(mommi.is_in_modules(O,permit_sheets=1)) - to_chat(user, "You cannot insert something that is part of you.") - return - else - return - if(!O.origin_tech) - to_chat(user, "This doesn't seem to have a tech origin!") - return - var/list/temp_tech = ConvertReqString2List(O.origin_tech) - if (temp_tech.len == 0) - to_chat(user, "You cannot deconstruct this item!") - return - /*if(O.reliability < 90 && O.crit_fail == 0) - to_chat(usr, "Item is neither reliable enough or broken enough to learn from.") - return*/ - if(user.drop_item(O, src)) - busy = 1 - loaded_item = O - to_chat(user, "You add the [O.name] to the machine!") - flick("d_analyzer_la", src) - spawn(10) - icon_state = "d_analyzer_l" - busy = 0 - return - -/obj/machinery/r_n_d/destructive_analyzer/attack_hand(mob/user as mob) - if (..(user)) - return - if (loaded_item && !panel_open && !busy) - to_chat(user, "You remove the [loaded_item.name] from the [src].") - loaded_item.loc = src.loc - loaded_item = null - icon_state = "d_analyzer" - -/obj/machinery/r_n_d/destructive_analyzer/attack_ghost(mob/user) - return - -//For testing purposes only. -/*/obj/item/weapon/deconstruction_test - name = "Test Item" - desc = "WTF?" - icon = 'icons/obj/weapons.dmi' - icon_state = "d20" - g_amt = 5000 - m_amt = 5000 - origin_tech = "materials=5;plasmatech=5;syndicate=5;programming=9"*/ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/* +Destructive Analyzer + +It is used to destroy hand-held objects and advance technological research. Controls are in the linked R&D console. + +Note: Must be placed within 3 tiles of the R&D Console +*/ +/obj/machinery/r_n_d/destructive_analyzer + name = "Destructive Analyzer" + icon_state = "d_analyzer" + var/obj/item/weapon/loaded_item = null + var/decon_mod = 1 + + research_flags = CONSOLECONTROL + +/obj/machinery/r_n_d/destructive_analyzer/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/destructive_analyzer, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/micro_laser + ) + + RefreshParts() + +/obj/machinery/r_n_d/destructive_analyzer/Destroy() + if(linked_console && linked_console.linked_destroy == src) + linked_console.linked_destroy = null + + . = ..() + +/obj/machinery/r_n_d/destructive_analyzer/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/S in component_parts) + T += S.rating * 0.1 + T = Clamp(T, 0, 1) + decon_mod = T + +/obj/machinery/r_n_d/destructive_analyzer/proc/ConvertReqString2List(var/list/source_list) + var/list/temp_list = params2list(source_list) + for(var/O in temp_list) + temp_list[O] = text2num(temp_list[O]) + return temp_list + +/obj/machinery/r_n_d/destructive_analyzer/togglePanelOpen(var/obj/toggleitem, mob/user) + if(loaded_item) + to_chat(user, "You can't open the maintenance panel while an item is loaded!") + return -1 + return ..() + +/obj/machinery/r_n_d/destructive_analyzer/crowbarDestroy(mob/user) + if(..() == 1) + if(loaded_item) + loaded_item.forceMove(loc) + return 1 + return -1 + +/obj/machinery/r_n_d/destructive_analyzer/attackby(var/obj/O as obj, var/mob/user as mob) + if(..()) + return 1 + if (istype(O, /obj/item) && !loaded_item && !panel_open) + if(isrobot(user)) //Don't put your module items in there! + if(isMoMMI(user)) + var/mob/living/silicon/robot/mommi/mommi = user + if(mommi.is_in_modules(O,permit_sheets=1)) + to_chat(user, "You cannot insert something that is part of you.") + return + else + return + if(!O.origin_tech) + to_chat(user, "This doesn't seem to have a tech origin!") + return + var/list/temp_tech = ConvertReqString2List(O.origin_tech) + if (temp_tech.len == 0) + to_chat(user, "You cannot deconstruct this item!") + return + /*if(O.reliability < 90 && O.crit_fail == 0) + to_chat(usr, "Item is neither reliable enough or broken enough to learn from.") + return*/ + if(user.drop_item(O, src)) + busy = 1 + loaded_item = O + to_chat(user, "You add the [O.name] to the machine!") + flick("d_analyzer_la", src) + spawn(10) + icon_state = "d_analyzer_l" + busy = 0 + return + +/obj/machinery/r_n_d/destructive_analyzer/attack_hand(mob/user as mob) + if (..(user)) + return + if (loaded_item && !panel_open && !busy) + to_chat(user, "You remove the [loaded_item.name] from the [src].") + loaded_item.loc = src.loc + loaded_item = null + icon_state = "d_analyzer" + +/obj/machinery/r_n_d/destructive_analyzer/attack_ghost(mob/user) + return + +//For testing purposes only. +/*/obj/item/weapon/deconstruction_test + name = "Test Item" + desc = "WTF?" + icon = 'icons/obj/weapons.dmi' + icon_state = "d20" + g_amt = 5000 + m_amt = 5000 + origin_tech = "materials=5;plasmatech=5;syndicate=5;programming=9"*/ diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index 5c86e544513..28b682592d5 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -1,389 +1,389 @@ -var/global/list/obj/machinery/message_server/message_servers = list() - -/datum/data_pda_msg - var/recipient = "Unspecified" //name of the person - var/sender = "Unspecified" //name of the sender - var/message = "Blank" //transferred message - -/datum/data_pda_msg/New(var/param_rec = "",var/param_sender = "",var/param_message = "") - - if(param_rec) - recipient = param_rec - if(param_sender) - sender = param_sender - if(param_message) - message = param_message - -/datum/data_rc_msg - var/rec_dpt = "Unspecified" //name of the person - var/send_dpt = "Unspecified" //name of the sender - var/message = "Blank" //transferred message - var/stamp = "Unstamped" - var/id_auth = "Unauthenticated" - var/priority = "Normal" - -/datum/data_rc_msg/New(var/param_rec = "",var/param_sender = "",var/param_message = "",var/param_stamp = "",var/param_id_auth = "",var/param_priority) - if(param_rec) - rec_dpt = param_rec - if(param_sender) - send_dpt = param_sender - if(param_message) - message = param_message - if(param_stamp) - stamp = param_stamp - if(param_id_auth) - id_auth = param_id_auth - if(param_priority) - switch(param_priority) - if(1) - priority = "Normal" - if(2) - priority = "High" - if(3) - priority = "Extreme" - else - priority = "Undetermined" - -/obj/machinery/message_server - icon = 'icons/obj/machines/research.dmi' - icon_state = "server" - name = "Messaging Server" - density = 1 - anchored = 1.0 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 100 - ghost_read=0 - ghost_write=0 // #430 - - var/list/datum/data_pda_msg/pda_msgs = list() - var/list/datum/data_rc_msg/rc_msgs = list() - var/active = 1 - var/decryptkey = "password" - -/obj/machinery/message_server/New() - message_servers += src - decryptkey = GenerateKey() - send_pda_message("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.") - ..() - return - -/obj/machinery/message_server/Destroy() - message_servers -= src - ..() - return - -/obj/machinery/message_server/proc/GenerateKey() - //Feel free to move to Helpers. - var/newKey - newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le") - newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai") - newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") - return newKey - -/obj/machinery/message_server/process() - //if(decryptkey == "password") - // decryptkey = generateKey() - if(active && (stat & (BROKEN|NOPOWER))) - active = 0 - return - update_icon() - return - -/obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "") - pda_msgs += new/datum/data_pda_msg(recipient,sender,message) - -/obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1) - rc_msgs += new/datum/data_rc_msg(recipient,sender,message,stamp,id_auth) - -/obj/machinery/message_server/attack_hand(user as mob) - if(isobserver(user) && !isAdminGhost(user)) - return 0 +var/global/list/obj/machinery/message_server/message_servers = list() + +/datum/data_pda_msg + var/recipient = "Unspecified" //name of the person + var/sender = "Unspecified" //name of the sender + var/message = "Blank" //transferred message + +/datum/data_pda_msg/New(var/param_rec = "",var/param_sender = "",var/param_message = "") + + if(param_rec) + recipient = param_rec + if(param_sender) + sender = param_sender + if(param_message) + message = param_message + +/datum/data_rc_msg + var/rec_dpt = "Unspecified" //name of the person + var/send_dpt = "Unspecified" //name of the sender + var/message = "Blank" //transferred message + var/stamp = "Unstamped" + var/id_auth = "Unauthenticated" + var/priority = "Normal" + +/datum/data_rc_msg/New(var/param_rec = "",var/param_sender = "",var/param_message = "",var/param_stamp = "",var/param_id_auth = "",var/param_priority) + if(param_rec) + rec_dpt = param_rec + if(param_sender) + send_dpt = param_sender + if(param_message) + message = param_message + if(param_stamp) + stamp = param_stamp + if(param_id_auth) + id_auth = param_id_auth + if(param_priority) + switch(param_priority) + if(1) + priority = "Normal" + if(2) + priority = "High" + if(3) + priority = "Extreme" + else + priority = "Undetermined" + +/obj/machinery/message_server + icon = 'icons/obj/machines/research.dmi' + icon_state = "server" + name = "Messaging Server" + density = 1 + anchored = 1.0 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 100 + ghost_read=0 + ghost_write=0 // #430 + + var/list/datum/data_pda_msg/pda_msgs = list() + var/list/datum/data_rc_msg/rc_msgs = list() + var/active = 1 + var/decryptkey = "password" + +/obj/machinery/message_server/New() + message_servers += src + decryptkey = GenerateKey() + send_pda_message("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.") + ..() + return + +/obj/machinery/message_server/Destroy() + message_servers -= src + ..() + return + +/obj/machinery/message_server/proc/GenerateKey() + //Feel free to move to Helpers. + var/newKey + newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le") + newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai") + newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") + return newKey + +/obj/machinery/message_server/process() + //if(decryptkey == "password") + // decryptkey = generateKey() + if(active && (stat & (BROKEN|NOPOWER))) + active = 0 + return + update_icon() + return + +/obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "") + pda_msgs += new/datum/data_pda_msg(recipient,sender,message) + +/obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1) + rc_msgs += new/datum/data_rc_msg(recipient,sender,message,stamp,id_auth) + +/obj/machinery/message_server/attack_hand(user as mob) + if(isobserver(user) && !isAdminGhost(user)) + return 0 // to_chat(user, "There seem to be some parts missing from this server. They should arrive on the station in a few days, give or take a few CentCom delays.") to_chat(user, "You toggle PDA message passing from [active ? "On" : "Off"] to [active ? "Off" : "On"]") - active = !active - update_icon() - - return - -/obj/machinery/message_server/update_icon() - if((stat & (BROKEN|NOPOWER))) - icon_state = "server-nopower" - else if (!active) - icon_state = "server-off" - else - icon_state = "server-on" - - return - - -/datum/feedback_variable - var/variable - var/value - var/details - -/datum/feedback_variable/New(var/param_variable,var/param_value = 0) - variable = param_variable - value = param_value - -/datum/feedback_variable/proc/inc(var/num = 1) - if(isnum(value)) - value += num - else - value = text2num(value) - if(isnum(value)) - value += num - else - value = num - -/datum/feedback_variable/proc/dec(var/num = 1) - if(isnum(value)) - value -= num - else - value = text2num(value) - if(isnum(value)) - value -= num - else - value = -num - -/datum/feedback_variable/proc/set_value(var/num) - if(isnum(num)) - value = num - -/datum/feedback_variable/proc/get_value() - return value - -/datum/feedback_variable/proc/get_variable() - return variable - -/datum/feedback_variable/proc/set_details(var/text) - if(istext(text)) - details = text - -/datum/feedback_variable/proc/add_details(var/text) - if(istext(text)) - if(!details) - details = text - else - details += " [text]" - -/datum/feedback_variable/proc/get_details() - return details - -/datum/feedback_variable/proc/get_parsed() - return list(variable,value,details) - -var/obj/machinery/blackbox_recorder/blackbox - -/obj/machinery/blackbox_recorder - icon = 'icons/obj/stationobjs.dmi' - icon_state = "blackbox" - name = "Blackbox Recorder" - density = 1 - anchored = 1.0 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 100 - var/list/messages = list() //Stores messages of non-standard frequencies - var/list/messages_admin = list() - - var/list/msg_common = list() - var/list/msg_science = list() - var/list/msg_command = list() - var/list/msg_medical = list() - var/list/msg_engineering = list() - var/list/msg_security = list() - var/list/msg_deathsquad = list() - var/list/msg_ert = list() - var/list/msg_syndicate = list() - var/list/msg_service = list() - var/list/msg_cargo = list() - - var/list/datum/feedback_variable/feedback = new() - - //Only one can exsist in the world! -/obj/machinery/blackbox_recorder/New() - ..() - if(blackbox) - if(istype(blackbox,/obj/machinery/blackbox_recorder)) - qdel(src) - blackbox = src - -/obj/machinery/blackbox_recorder/Destroy() - var/turf/T = locate(1,1,2) - if(T) - blackbox = null - var/obj/machinery/blackbox_recorder/BR = new/obj/machinery/blackbox_recorder(T) - BR.msg_common = msg_common - BR.msg_science = msg_science - BR.msg_command = msg_command - BR.msg_medical = msg_medical - BR.msg_engineering = msg_engineering - BR.msg_security = msg_security - BR.msg_deathsquad = msg_deathsquad - BR.msg_ert = msg_ert - BR.msg_syndicate = msg_syndicate - BR.msg_service = msg_service - BR.msg_cargo = msg_cargo - BR.feedback = feedback - BR.messages = messages - BR.messages_admin = messages_admin - if(blackbox != BR) - blackbox = BR - ..() - -/obj/machinery/blackbox_recorder/proc/find_feedback_datum(var/variable) - for(var/datum/feedback_variable/FV in feedback) - if(FV.get_variable() == variable) - return FV - var/datum/feedback_variable/FV = new(variable) - feedback += FV - return FV - -/obj/machinery/blackbox_recorder/proc/get_round_feedback() - return feedback - -/obj/machinery/blackbox_recorder/proc/round_end_data_gathering() - - - var/pda_msg_amt = 0 - var/rc_msg_amt = 0 - - for(var/obj/machinery/message_server/MS in machines) - if(MS.pda_msgs.len > pda_msg_amt) - pda_msg_amt = MS.pda_msgs.len - if(MS.rc_msgs.len > rc_msg_amt) - rc_msg_amt = MS.rc_msgs.len - - feedback_set_details("radio_usage","") - - feedback_add_details("radio_usage","COM-[msg_common.len]") - feedback_add_details("radio_usage","SCI-[msg_science.len]") - feedback_add_details("radio_usage","HEA-[msg_command.len]") - feedback_add_details("radio_usage","MED-[msg_medical.len]") - feedback_add_details("radio_usage","ENG-[msg_engineering.len]") - feedback_add_details("radio_usage","SEC-[msg_security.len]") - feedback_add_details("radio_usage","DTH-[msg_deathsquad.len]") - feedback_add_details("radio_usage","ERT-[msg_ert.len]") - feedback_add_details("radio_usage","SYN-[msg_syndicate.len]") - feedback_add_details("radio_usage","SER-[msg_service.len]") - feedback_add_details("radio_usage","CAR-[msg_cargo.len]") - feedback_add_details("radio_usage","OTH-[messages.len]") - feedback_add_details("radio_usage","PDA-[pda_msg_amt]") - feedback_add_details("radio_usage","RC-[rc_msg_amt]") - - - feedback_set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set. - - -//This proc is only to be called at round end. -/obj/machinery/blackbox_recorder/proc/save_all_data_to_sql() - if(!feedback) return - - //#warning Blackbox recording disabled. Please remove warning once this has been determined to be the problem. - //return - - var/watch = start_watch() - log_startup_progress("Storing Black Box data...") - round_end_data_gathering() //round_end time logging and some other data processing - establish_db_connection() - if(!dbcon.IsConnected()) return - var/round_id - - var/nqueries = 0 - - var/DBQuery/query = dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM erro_feedback") - query.Execute() - nqueries++ - while(query.NextRow()) - round_id = query.item[1] - - if(!isnum(round_id)) - round_id = text2num(round_id) - round_id++ - - /* - for(var/datum/feedback_variable/FV in feedback) - var/sql = "INSERT INTO erro_feedback VALUES (null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")" - var/DBQuery/query_insert = dbcon.NewQuery(sql) - query_insert.Execute() - nqueries++ - sleep(1) // Let other shit do things - */ - // MySQL and MariaDB support compound inserts and this insert is slow as fuck. - var/sql = "INSERT INTO erro_feedback VALUES " - var/ninserts=0 - for(var/datum/feedback_variable/FV in feedback) - if(ninserts>0) - sql += "," - ninserts++ - sql += "(null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")" - var/DBQuery/query_insert = dbcon.NewQuery(sql) - query_insert.Execute() - nqueries++ - - log_startup_progress(" Wrote Black Box data with [nqueries] queries in [stop_watch(watch)]s.") - -// Sanitize inputs to avoid SQL injection attacks -proc/sql_sanitize_text(var/text) - text = replacetext(text, "'", "''") - text = replacetext(text, ";", "") - text = replacetext(text, "&", "") - return text - -proc/feedback_set(var/variable,var/value) - if(!blackbox) return - - variable = sql_sanitize_text(variable) - - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) - - if(!FV) return - - FV.set_value(value) - -proc/feedback_inc(var/variable,var/value) - if(!blackbox) return - - variable = sql_sanitize_text(variable) - - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) - - if(!FV) return - - FV.inc(value) - -proc/feedback_dec(var/variable,var/value) - if(!blackbox) return - - variable = sql_sanitize_text(variable) - - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) - - if(!FV) return - - FV.dec(value) - -proc/feedback_set_details(var/variable,var/details) - if(!blackbox) return - - variable = sql_sanitize_text(variable) - details = sql_sanitize_text(details) - - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) - - if(!FV) return - - FV.set_details(details) - -proc/feedback_add_details(var/variable,var/details) - if(!blackbox) return - - variable = sql_sanitize_text(variable) - details = sql_sanitize_text(details) - - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) - - if(!FV) return - - FV.add_details(details) + active = !active + update_icon() + + return + +/obj/machinery/message_server/update_icon() + if((stat & (BROKEN|NOPOWER))) + icon_state = "server-nopower" + else if (!active) + icon_state = "server-off" + else + icon_state = "server-on" + + return + + +/datum/feedback_variable + var/variable + var/value + var/details + +/datum/feedback_variable/New(var/param_variable,var/param_value = 0) + variable = param_variable + value = param_value + +/datum/feedback_variable/proc/inc(var/num = 1) + if(isnum(value)) + value += num + else + value = text2num(value) + if(isnum(value)) + value += num + else + value = num + +/datum/feedback_variable/proc/dec(var/num = 1) + if(isnum(value)) + value -= num + else + value = text2num(value) + if(isnum(value)) + value -= num + else + value = -num + +/datum/feedback_variable/proc/set_value(var/num) + if(isnum(num)) + value = num + +/datum/feedback_variable/proc/get_value() + return value + +/datum/feedback_variable/proc/get_variable() + return variable + +/datum/feedback_variable/proc/set_details(var/text) + if(istext(text)) + details = text + +/datum/feedback_variable/proc/add_details(var/text) + if(istext(text)) + if(!details) + details = text + else + details += " [text]" + +/datum/feedback_variable/proc/get_details() + return details + +/datum/feedback_variable/proc/get_parsed() + return list(variable,value,details) + +var/obj/machinery/blackbox_recorder/blackbox + +/obj/machinery/blackbox_recorder + icon = 'icons/obj/stationobjs.dmi' + icon_state = "blackbox" + name = "Blackbox Recorder" + density = 1 + anchored = 1.0 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 100 + var/list/messages = list() //Stores messages of non-standard frequencies + var/list/messages_admin = list() + + var/list/msg_common = list() + var/list/msg_science = list() + var/list/msg_command = list() + var/list/msg_medical = list() + var/list/msg_engineering = list() + var/list/msg_security = list() + var/list/msg_deathsquad = list() + var/list/msg_ert = list() + var/list/msg_syndicate = list() + var/list/msg_service = list() + var/list/msg_cargo = list() + + var/list/datum/feedback_variable/feedback = new() + + //Only one can exsist in the world! +/obj/machinery/blackbox_recorder/New() + ..() + if(blackbox) + if(istype(blackbox,/obj/machinery/blackbox_recorder)) + qdel(src) + blackbox = src + +/obj/machinery/blackbox_recorder/Destroy() + var/turf/T = locate(1,1,2) + if(T) + blackbox = null + var/obj/machinery/blackbox_recorder/BR = new/obj/machinery/blackbox_recorder(T) + BR.msg_common = msg_common + BR.msg_science = msg_science + BR.msg_command = msg_command + BR.msg_medical = msg_medical + BR.msg_engineering = msg_engineering + BR.msg_security = msg_security + BR.msg_deathsquad = msg_deathsquad + BR.msg_ert = msg_ert + BR.msg_syndicate = msg_syndicate + BR.msg_service = msg_service + BR.msg_cargo = msg_cargo + BR.feedback = feedback + BR.messages = messages + BR.messages_admin = messages_admin + if(blackbox != BR) + blackbox = BR + ..() + +/obj/machinery/blackbox_recorder/proc/find_feedback_datum(var/variable) + for(var/datum/feedback_variable/FV in feedback) + if(FV.get_variable() == variable) + return FV + var/datum/feedback_variable/FV = new(variable) + feedback += FV + return FV + +/obj/machinery/blackbox_recorder/proc/get_round_feedback() + return feedback + +/obj/machinery/blackbox_recorder/proc/round_end_data_gathering() + + + var/pda_msg_amt = 0 + var/rc_msg_amt = 0 + + for(var/obj/machinery/message_server/MS in machines) + if(MS.pda_msgs.len > pda_msg_amt) + pda_msg_amt = MS.pda_msgs.len + if(MS.rc_msgs.len > rc_msg_amt) + rc_msg_amt = MS.rc_msgs.len + + feedback_set_details("radio_usage","") + + feedback_add_details("radio_usage","COM-[msg_common.len]") + feedback_add_details("radio_usage","SCI-[msg_science.len]") + feedback_add_details("radio_usage","HEA-[msg_command.len]") + feedback_add_details("radio_usage","MED-[msg_medical.len]") + feedback_add_details("radio_usage","ENG-[msg_engineering.len]") + feedback_add_details("radio_usage","SEC-[msg_security.len]") + feedback_add_details("radio_usage","DTH-[msg_deathsquad.len]") + feedback_add_details("radio_usage","ERT-[msg_ert.len]") + feedback_add_details("radio_usage","SYN-[msg_syndicate.len]") + feedback_add_details("radio_usage","SER-[msg_service.len]") + feedback_add_details("radio_usage","CAR-[msg_cargo.len]") + feedback_add_details("radio_usage","OTH-[messages.len]") + feedback_add_details("radio_usage","PDA-[pda_msg_amt]") + feedback_add_details("radio_usage","RC-[rc_msg_amt]") + + + feedback_set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set. + + +//This proc is only to be called at round end. +/obj/machinery/blackbox_recorder/proc/save_all_data_to_sql() + if(!feedback) return + + //#warning Blackbox recording disabled. Please remove warning once this has been determined to be the problem. + //return + + var/watch = start_watch() + log_startup_progress("Storing Black Box data...") + round_end_data_gathering() //round_end time logging and some other data processing + establish_db_connection() + if(!dbcon.IsConnected()) return + var/round_id + + var/nqueries = 0 + + var/DBQuery/query = dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM erro_feedback") + query.Execute() + nqueries++ + while(query.NextRow()) + round_id = query.item[1] + + if(!isnum(round_id)) + round_id = text2num(round_id) + round_id++ + + /* + for(var/datum/feedback_variable/FV in feedback) + var/sql = "INSERT INTO erro_feedback VALUES (null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")" + var/DBQuery/query_insert = dbcon.NewQuery(sql) + query_insert.Execute() + nqueries++ + sleep(1) // Let other shit do things + */ + // MySQL and MariaDB support compound inserts and this insert is slow as fuck. + var/sql = "INSERT INTO erro_feedback VALUES " + var/ninserts=0 + for(var/datum/feedback_variable/FV in feedback) + if(ninserts>0) + sql += "," + ninserts++ + sql += "(null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")" + var/DBQuery/query_insert = dbcon.NewQuery(sql) + query_insert.Execute() + nqueries++ + + log_startup_progress(" Wrote Black Box data with [nqueries] queries in [stop_watch(watch)]s.") + +// Sanitize inputs to avoid SQL injection attacks +proc/sql_sanitize_text(var/text) + text = replacetext(text, "'", "''") + text = replacetext(text, ";", "") + text = replacetext(text, "&", "") + return text + +proc/feedback_set(var/variable,var/value) + if(!blackbox) return + + variable = sql_sanitize_text(variable) + + var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + + if(!FV) return + + FV.set_value(value) + +proc/feedback_inc(var/variable,var/value) + if(!blackbox) return + + variable = sql_sanitize_text(variable) + + var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + + if(!FV) return + + FV.inc(value) + +proc/feedback_dec(var/variable,var/value) + if(!blackbox) return + + variable = sql_sanitize_text(variable) + + var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + + if(!FV) return + + FV.dec(value) + +proc/feedback_set_details(var/variable,var/details) + if(!blackbox) return + + variable = sql_sanitize_text(variable) + details = sql_sanitize_text(details) + + var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + + if(!FV) return + + FV.set_details(details) + +proc/feedback_add_details(var/variable,var/details) + if(!blackbox) return + + variable = sql_sanitize_text(variable) + details = sql_sanitize_text(details) + + var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + + if(!FV) return + + FV.add_details(details) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index d8363c00ec6..57faf457ab0 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -1,81 +1,81 @@ -/* -Protolathe - -Similar to an autolathe, you load glass and metal sheets (but not other objects) into it to be used as raw materials for the stuff -it creates. All the menus and other manipulation commands are in the R&D console. -*/ - -#define PROTOLATHE_BUILD_TIME 1 - -/obj/machinery/r_n_d/fabricator/protolathe - name = "Protolathe" - icon_state = "protolathe" - desc = "A fabricator capable of producing prototypes from research schematics." - flags = OPENCONTAINER - - start_end_anims = 1 - - build_time = PROTOLATHE_BUILD_TIME - build_number = 2 - - light_color = LIGHT_COLOR_CYAN - - research_flags = CONSOLECONTROL | HASOUTPUT | TAKESMATIN | HASMAT_OVER | LOCKBOXES - - part_sets = list( - "Stock Parts" = list(), - "Bluespace" = list(), - "Data" = list(), - "Engineering" = list(), - "Medical" = list(), - "Mining" = list(), - "Robotics" = list(), - "Weapons" = list(), - "Armor" = list(), - "Misc" = list(), - ) - -/obj/machinery/r_n_d/fabricator/protolathe/power_change() - ..() - if(!(stat & (BROKEN|NOPOWER))) - set_light(2) - else - set_light(0) - -/obj/machinery/r_n_d/fabricator/protolathe/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/protolathe, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/matter_bin, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/reagent_containers/glass/beaker, - /obj/item/weapon/reagent_containers/glass/beaker - ) - - RefreshParts() - -/obj/machinery/r_n_d/fabricator/protolathe/Destroy() - if(linked_console && linked_console.linked_lathe == src) - linked_console.linked_lathe = null - - . = ..() - -/obj/machinery/r_n_d/fabricator/protolathe/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) - T += G.reagents.maximum_volume - - create_reagents(T) // Holder for the reagents used as materials. - - . = ..() - -/obj/machinery/r_n_d/fabricator/protolathe/setup_part_sets() - return - -/obj/machinery/r_n_d/fabricator/protolathe/attackby(var/obj/item/O as obj, var/mob/user as mob) - ..() - if (O.is_open_container()) - return 1 +/* +Protolathe + +Similar to an autolathe, you load glass and metal sheets (but not other objects) into it to be used as raw materials for the stuff +it creates. All the menus and other manipulation commands are in the R&D console. +*/ + +#define PROTOLATHE_BUILD_TIME 1 + +/obj/machinery/r_n_d/fabricator/protolathe + name = "Protolathe" + icon_state = "protolathe" + desc = "A fabricator capable of producing prototypes from research schematics." + flags = OPENCONTAINER + + start_end_anims = 1 + + build_time = PROTOLATHE_BUILD_TIME + build_number = 2 + + light_color = LIGHT_COLOR_CYAN + + research_flags = CONSOLECONTROL | HASOUTPUT | TAKESMATIN | HASMAT_OVER | LOCKBOXES + + part_sets = list( + "Stock Parts" = list(), + "Bluespace" = list(), + "Data" = list(), + "Engineering" = list(), + "Medical" = list(), + "Mining" = list(), + "Robotics" = list(), + "Weapons" = list(), + "Armor" = list(), + "Misc" = list(), + ) + +/obj/machinery/r_n_d/fabricator/protolathe/power_change() + ..() + if(!(stat & (BROKEN|NOPOWER))) + set_light(2) + else + set_light(0) + +/obj/machinery/r_n_d/fabricator/protolathe/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/protolathe, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/matter_bin, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/reagent_containers/glass/beaker, + /obj/item/weapon/reagent_containers/glass/beaker + ) + + RefreshParts() + +/obj/machinery/r_n_d/fabricator/protolathe/Destroy() + if(linked_console && linked_console.linked_lathe == src) + linked_console.linked_lathe = null + + . = ..() + +/obj/machinery/r_n_d/fabricator/protolathe/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) + T += G.reagents.maximum_volume + + create_reagents(T) // Holder for the reagents used as materials. + + . = ..() + +/obj/machinery/r_n_d/fabricator/protolathe/setup_part_sets() + return + +/obj/machinery/r_n_d/fabricator/protolathe/attackby(var/obj/item/O as obj, var/mob/user as mob) + ..() + if (O.is_open_container()) + return 1 diff --git a/code/modules/research/rd-readme.dm b/code/modules/research/rd-readme.dm index 8680460c227..ce5a72bc4ef 100644 --- a/code/modules/research/rd-readme.dm +++ b/code/modules/research/rd-readme.dm @@ -1,239 +1,239 @@ -/* -Research and Development System. (Designed specifically for the /tg/station 13 (Space Station 13) open source project) - -///////////////Overview/////////////////// -This system is a "tech tree" research and development system designed for SS13. It allows a "researcher" job (this document assumes -the "scientist" job is given this role) the tools necessiary to research new and better technologies. In general, the system works -by breaking existing technology and using what you learn from to advance your knowledge of SCIENCE! As your knowledge progresses, -you can build newer (and better?) devices (which you can also, eventually, deconstruct to advance your knowledge). - -A brief overview is below. For more details, see the related files. - -////////////Game Use///////////// -The major research and development is performed using a combination of four machines: -- R&D Console: A computer console that allows you to manipulate the other devices that are linked to it and view/manipulate the -technologies you have researched so far. -- Protolathe: Used to make new hand-held devices and parts for larger devices. All metals and reagents as raw materials. -- Destructive Analyzer: You can put hand-held objects into it and it'll analyze them for technological advancements but it destroys -them in the process. Destroyed items will send their raw materials to a linked Protolathe (if any) -- Circuit Imprinter: Similar to the Protolathe, it allows for the construction of circuit boards. Uses glass and acid as the raw -materials. - -While researching you are dealing with two different types of information: Technology Paths and Device Designs. Technology Paths -are the "Tech Trees" of the game. You start out with a number of them at the game start and they are improved by using the -Destructive Analyzer. By themselves, they don't do a whole lot. However, they unlock Device Designs. This is the information used -by the circuit imprinter and the protolathe to produce objects. It also tracks the current reliability of that particular design. - -//EXISTING TECH -Each tech path should have at LEAST one item at every level (levels 1 - 20). This is to allow for a more fluid progression of the -researching. Existing tech (ie, anything you can find on the station or get from the quartermaster) shouldn't go higher then -level 5 or 7. Everything past that should be stuff you research. - -Below is a checklist to make sure every tree is filled. As new items get added to R&D, add them here if there is an empty slot. -When thinking about new stuff, check here to see if there are any slots unfilled. - -//MATERIALS -1 | Metal -2 | Solid Plasma -3 | Silver -4 | Gold, Super Capacitor -5 | Uranium, Nuclear Gun, SUPERPACMAN -6 | Diamond, MRSPACMAN -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//PLASMA TECH -1 | -2 | Solid Plasma -3 | Pacman Generator -4 | -5 | -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//POWER TECH -1 | Basic Capacitor, Basic Cell -2 | High-Capacity Cell (10,000) -3 | Super-Capacity Cell (20,000), Powersink, PACMAN -4 | SUPERPACMAN -5 | MRSPACMAN, Super Capacitor -6 | Hyper-Capacity Cell (30,000) -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//BLUE SPACE -1 | -2 | Teleporter Console Board -3 | Teleport Gun, Hand Tele -4 | Teleportation Scroll -5 | -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//BIOTECH -1 | Bruise Pack, Scalple -2 | PANDEMIC Board, Mass Spectrometer -3 | AI Core, Brains (MMI) -4 | MMI+Radio -5 | -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//MAGNETS -1 | Basic Sensor -2 | Comm Console Board -3 | Adv Sensor -4 | Adv Mass Spectrometer, Chameleon Projector -5 | Phasic Sensor -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//PROGRAMMING -1 | Arcade Board -2 | Sec Camera -3 | Cloning Machine Console Board -4 | AI Core, Intellicard -5 | Pico-Manipulator, Ultra-Micro-Laser -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//SYNDICATE -1 | Sleepypen -2 | TYRANT Module, Emag -3 | Cloaking Device, Power Sink -4 | -5 | -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - -//COMBAT -1 | Flashbang, Mousetrap, Nettle -2 | Stun Baton -3 | Power Axe, Death Nettle, Nuclear Gun -4 | -5 | -6 | -7 | -8 | -9 | -10 | -11 | -12 | -13 | -14 | -15 | -16 | -17 | -18 | -19 | -20 | - - - - - - - +/* +Research and Development System. (Designed specifically for the /tg/station 13 (Space Station 13) open source project) + +///////////////Overview/////////////////// +This system is a "tech tree" research and development system designed for SS13. It allows a "researcher" job (this document assumes +the "scientist" job is given this role) the tools necessiary to research new and better technologies. In general, the system works +by breaking existing technology and using what you learn from to advance your knowledge of SCIENCE! As your knowledge progresses, +you can build newer (and better?) devices (which you can also, eventually, deconstruct to advance your knowledge). + +A brief overview is below. For more details, see the related files. + +////////////Game Use///////////// +The major research and development is performed using a combination of four machines: +- R&D Console: A computer console that allows you to manipulate the other devices that are linked to it and view/manipulate the +technologies you have researched so far. +- Protolathe: Used to make new hand-held devices and parts for larger devices. All metals and reagents as raw materials. +- Destructive Analyzer: You can put hand-held objects into it and it'll analyze them for technological advancements but it destroys +them in the process. Destroyed items will send their raw materials to a linked Protolathe (if any) +- Circuit Imprinter: Similar to the Protolathe, it allows for the construction of circuit boards. Uses glass and acid as the raw +materials. + +While researching you are dealing with two different types of information: Technology Paths and Device Designs. Technology Paths +are the "Tech Trees" of the game. You start out with a number of them at the game start and they are improved by using the +Destructive Analyzer. By themselves, they don't do a whole lot. However, they unlock Device Designs. This is the information used +by the circuit imprinter and the protolathe to produce objects. It also tracks the current reliability of that particular design. + +//EXISTING TECH +Each tech path should have at LEAST one item at every level (levels 1 - 20). This is to allow for a more fluid progression of the +researching. Existing tech (ie, anything you can find on the station or get from the quartermaster) shouldn't go higher then +level 5 or 7. Everything past that should be stuff you research. + +Below is a checklist to make sure every tree is filled. As new items get added to R&D, add them here if there is an empty slot. +When thinking about new stuff, check here to see if there are any slots unfilled. + +//MATERIALS +1 | Metal +2 | Solid Plasma +3 | Silver +4 | Gold, Super Capacitor +5 | Uranium, Nuclear Gun, SUPERPACMAN +6 | Diamond, MRSPACMAN +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//PLASMA TECH +1 | +2 | Solid Plasma +3 | Pacman Generator +4 | +5 | +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//POWER TECH +1 | Basic Capacitor, Basic Cell +2 | High-Capacity Cell (10,000) +3 | Super-Capacity Cell (20,000), Powersink, PACMAN +4 | SUPERPACMAN +5 | MRSPACMAN, Super Capacitor +6 | Hyper-Capacity Cell (30,000) +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//BLUE SPACE +1 | +2 | Teleporter Console Board +3 | Teleport Gun, Hand Tele +4 | Teleportation Scroll +5 | +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//BIOTECH +1 | Bruise Pack, Scalple +2 | PANDEMIC Board, Mass Spectrometer +3 | AI Core, Brains (MMI) +4 | MMI+Radio +5 | +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//MAGNETS +1 | Basic Sensor +2 | Comm Console Board +3 | Adv Sensor +4 | Adv Mass Spectrometer, Chameleon Projector +5 | Phasic Sensor +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//PROGRAMMING +1 | Arcade Board +2 | Sec Camera +3 | Cloning Machine Console Board +4 | AI Core, Intellicard +5 | Pico-Manipulator, Ultra-Micro-Laser +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//SYNDICATE +1 | Sleepypen +2 | TYRANT Module, Emag +3 | Cloaking Device, Power Sink +4 | +5 | +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + +//COMBAT +1 | Flashbang, Mousetrap, Nettle +2 | Stun Baton +3 | Power Axe, Death Nettle, Nuclear Gun +4 | +5 | +6 | +7 | +8 | +9 | +10 | +11 | +12 | +13 | +14 | +15 | +16 | +17 | +18 | +19 | +20 | + + + + + + + */ \ No newline at end of file diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index c260bc1a526..c87bf918a04 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -1,1124 +1,1124 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/* -Research and Development (R&D) Console - -This is the main work horse of the R&D system. It contains the menus/controls for the Destructive Analyzer, Protolathe, and Circuit -imprinter. It also contains the /datum/research holder with all the known/possible technology paths and device designs. - -Basic use: When it first is created, it will attempt to link up to related devices within 3 squares. It'll only link up if they -aren't already linked to another console. Any consoles it cannot link up with (either because all of a certain type are already -linked or there aren't any in range), you'll just not have access to that menu. In the settings menu, there are menu options that -allow a player to attempt to re-sync with nearby consoles. You can also force it to disconnect from a specific console. - -The imprinting and construction menus do NOT require toxins access to access but all the other menus do. However, if you leave it -on a menu, nothing is to stop the person from using the options on that menu (although they won't be able to change to a different -one). You can also lock the console on the settings menu if you're feeling paranoid and you don't want anyone messing with it who -doesn't have toxins access. - -When a R&D console is destroyed or even partially disassembled, you lose all research data on it. However, there are two ways around -this dire fate: -- The easiest way is to go to the settings menu and select "Sync Database with Network." That causes it to upload (but not download) -it's data to every other device in the game. Each console has a "disconnect from network" option that'll will cause data base sync -operations to skip that console. This is useful if you want to make a "public" R&D console or, for example, give the engineers -a circuit imprinter with certain designs on it and don't want it accidentally updating. The downside of this method is that you have -to have physical access to the other console to send data back. Note: An R&D console is on CentCom so if a random griffan happens to -cause a ton of data to be lost, an admin can go send it back. -- The second method is with Technology Disks and Design Disks. Each of these disks can hold a single technology or design datum in -it's entirety. You can then take the disk to any R&D console and upload it's data to it. This method is a lot more secure (since it -won't update every console in existence) but it's more of a hassle to do. Also, the disks can be stolen. - - -*/ -#define RESEARCH_MAX_Q_LEN 30 -/obj/machinery/computer/rdconsole - name = "R&D Console" - icon_state = "rdcomp" - circuit = "/obj/item/weapon/circuitboard/rdconsole" - var/datum/research/files //Stores all the collected research data. - var/obj/item/weapon/disk/tech_disk/t_disk = null //Stores the technology disk. - var/obj/item/weapon/disk/design_disk/d_disk = null //Stores the design disk. - - var/obj/machinery/r_n_d/destructive_analyzer/linked_destroy = null //Linked Destructive Analyzer - var/obj/machinery/r_n_d/fabricator/protolathe/linked_lathe = null //Linked Protolathe - var/obj/machinery/r_n_d/fabricator/circuit_imprinter/linked_imprinter = null //Linked Circuit Imprinter - - var/list/obj/machinery/linked_machines = list() - var/list/research_machines = list( - /obj/machinery/r_n_d/fabricator/protolathe, - /obj/machinery/r_n_d/destructive_analyzer, - /obj/machinery/r_n_d/fabricator/circuit_imprinter, - /obj/machinery/r_n_d/fabricator/mech, - /obj/machinery/r_n_d/fabricator/pod, - /obj/machinery/r_n_d/fabricator/mechanic_fab, - /obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker, - /obj/machinery/r_n_d/reverse_engine, - /obj/machinery/r_n_d/blueprinter - ) - var/screen = 1.0 //Which screen is currently showing. - var/id = 0 //ID of the computer (for server restrictions). - var/sync = 1 //If sync = 0, it doesn't show up on Server Control Console - - var/list/filtered = list( //Filters categories in the protolathe menu - "protolathe" = list(), - "imprinter" = list() - ) - var/autorefresh = 1 //Prevents the window from being updated while queueing items - - req_access = list(access_tox) //Data and setting manipulation requires scientist access. - - starting_materials = list() - - light_color = LIGHT_COLOR_PINK - - var/part_sets = list( - "Stock Parts" = list(), - "Bluespace" = list(), - "Data" = list(), - "Engineering" = list(), - "Medical" = list(), - "Mining" = list(), - "Robotics" = list(), - "Weapons" = list(), - "Armor" = list(), - "Misc" = list(), - ) - -/obj/machinery/computer/rdconsole/Destroy() - . = ..() - for(var/obj/machinery/r_n_d/R in linked_machines) - R.linked_console = null - linked_machines -= R - R.update_icon() - - if(linked_destroy) - linked_destroy.linked_console = null - linked_destroy.update_icon() - linked_destroy = null - - if(linked_imprinter) - linked_imprinter.linked_console = null - linked_imprinter.update_icon() - linked_imprinter = null - - if(linked_lathe) - linked_lathe.linked_console = null - linked_lathe.update_icon() - linked_lathe = null - -/obj/machinery/computer/rdconsole/proc/Maximize() - files.known_tech = tech_list.Copy() - for(var/datum/tech/KT in files.known_tech) - if(KT.level < KT.max_level) - KT.level=KT.max_level - -/obj/machinery/computer/rdconsole/proc/CallTechName(var/ID) //A simple helper proc to find the name of a tech with a given ID. - var/datum/tech/check_tech - var/return_name = "" - - for (var/T in typesof(/datum/tech) - /datum/tech) - check_tech = T - - if (initial(check_tech.id) == ID) - return_name = initial(check_tech.name) - break - - return return_name - -/obj/machinery/computer/rdconsole/proc/CallMaterialName(var/ID) - var/return_name = null - if (copytext(ID, 1, 2) == "$") - var/datum/material/mat = materials.getMaterial(ID) - return mat.processed_name - else - for(var/R in typesof(/datum/reagent) - /datum/reagent) - var/datum/reagent/T = new R() - if(T.id == ID) - return_name = T.name - break - return return_name - -/obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any). - if(!isarea(areaMaster) || isspace(areaMaster)) - say("Unable to process synchronization") - return - - - for(var/obj/machinery/r_n_d/D in rnd_machines) //any machine in the room, just for funsies - if(D.linked_console != null || D.disabled || D.panel_open || !D.areaMaster || (D.areaMaster != areaMaster)) - continue - if(D.type in research_machines) - linked_machines += D - D.linked_console = src - D.update_icon() - for(var/obj/machinery/r_n_d/D in linked_machines) - if(linked_lathe && linked_destroy && linked_imprinter) break // stop if we have all of our linked - switch(D.type) - if(/obj/machinery/r_n_d/fabricator/protolathe) - if(!linked_lathe) - linked_lathe = D - if(/obj/machinery/r_n_d/destructive_analyzer) - if(!linked_destroy) - linked_destroy = D - if(/obj/machinery/r_n_d/fabricator/circuit_imprinter) - if(!linked_imprinter) - linked_imprinter = D - if(linked_lathe) - linked_lathe.part_sets = part_sets - return - -//Have it automatically push research to the centcomm server so wild griffins can't fuck up R&D's work --NEO -/obj/machinery/computer/rdconsole/proc/griefProtection() - for(var/obj/machinery/r_n_d/server/centcom/C in machines) - for(var/datum/tech/T in files.known_tech) - C.files.AddTech2Known(T) - for(var/datum/design/D in files.known_designs) - C.files.AddDesign2Known(D) - C.files.RefreshResearch() - - -/obj/machinery/computer/rdconsole/New() - ..() - files = new /datum/research(src) //Setup the research data holder. - if(!id) - for(var/obj/machinery/r_n_d/server/centcom/S in machines) - S.initialize() - break - -/obj/machinery/computer/rdconsole/initialize() - SyncRDevices() - -/* Instead of calling this every tick, it is only being called when needed -/obj/machinery/computer/rdconsole/process() - griefProtection() -*/ - -/obj/machinery/computer/rdconsole/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) - if(..()) - return - if(istype(D, /obj/item/weapon/disk)) - if(t_disk || d_disk) - to_chat(user, "A disk is already loaded into the machine.") - return - - if(istype(D, /obj/item/weapon/disk/tech_disk)) - if(user.drop_item(D,src)) - t_disk = D - else if (istype(D, /obj/item/weapon/disk/design_disk)) - if(user.drop_item(D,src)) - d_disk = D - else - to_chat(user, "Machine cannot accept disks in that format.") - return - - to_chat(user, "You add the disk to the machine!") - - src.updateUsrDialog() - return - -/obj/machinery/computer/rdconsole/emag(mob/user) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) - emagged = 1 - to_chat(user, "You disable the security protocols") - -/obj/machinery/computer/rdconsole/Topic(href, href_list) - if(..()) - return - - var/updateAfter = 1 //STOP - - add_fingerprint(usr) - - usr.set_machine(src) - if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code. - var/temp_screen = text2num(href_list["menu"]) - if(temp_screen <= 1.1 || (2 <= temp_screen && 4.9 >= temp_screen) || src.allowed(usr) || emagged) //Unless you are making something, you need access. - screen = temp_screen - else - to_chat(usr, "Unauthorized Access.") - - else if(href_list["updt_tech"]) //Update the research holder with information from the technology disk. - screen = 0.0 - spawn(50) - screen = 1.2 - files.AddTech2Known(t_disk.stored) - if(t_disk.stored.new_category && !(t_disk.stored.new_category in part_sets)) - part_sets += t_disk.stored.new_category - part_sets[t_disk.stored.new_category] = list() - if(linked_lathe) - linked_lathe.part_sets = part_sets - updateUsrDialog() - griefProtection() //Update centcomm too - - else if(href_list["hax"]) // aww shit - if(!usr.client.holder) return - screen = 0.0 - spawn(50) - Maximize() - screen = 1.0 - updateUsrDialog() - griefProtection() //Update centcomm too - - else if(href_list["clear_tech"]) //Erase data on the technology disk. - t_disk.stored = null - - else if(href_list["eject_tech"]) //Eject the technology disk. - t_disk:loc = src.loc - t_disk = null - screen = 1.0 - - else if(href_list["copy_tech"]) //Copys some technology data from the research holder to the disk. - for(var/datum/tech/T in files.known_tech) - if(href_list["copy_tech_ID"] == T.id) - t_disk.stored = T - break - screen = 1.2 - - else if(href_list["updt_design"]) //Updates the research holder with design data from the design disk. - screen = 0.0 - spawn(50) - screen = 1.4 - files.AddDesign2Known(d_disk.blueprint) - updateUsrDialog() - griefProtection() //Update centcomm too - - else if(href_list["clear_design"]) //Erases data on the design disk. - d_disk.blueprint = null - - else if(href_list["eject_design"]) //Eject the design disk. - d_disk:loc = src.loc - d_disk = null - screen = 1.0 - - else if(href_list["copy_design"]) //Copy design data from the research holder to the design disk. - for(var/datum/design/D in files.known_designs) - if(href_list["copy_design_ID"] == D.id) - d_disk.blueprint = D - break - screen = 1.4 - - else if(href_list["eject_item"]) //Eject the item inside the destructive analyzer. - if(linked_destroy) - if(linked_destroy.busy) - to_chat(usr, "The destructive analyzer is busy at the moment.") - - else if(linked_destroy.loaded_item) - linked_destroy.loaded_item.loc = linked_destroy.loc - linked_destroy.loaded_item = null - linked_destroy.icon_state = "d_analyzer" - screen = 2.1 - - else if(href_list["deconstruct"]) //Deconstruct the item in the destructive analyzer and update the research holder. - if(linked_destroy) - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - if(linked_destroy.busy) - to_chat(usr, "The destructive analyzer is busy at the moment.") - else - var/choice = input("Proceeding will destroy loaded item.") in list("Proceed", "Cancel") - if(choice == "Cancel" || !linked_destroy) return - linked_destroy.busy = 1 - screen = 0.1 - updateUsrDialog() - flick("d_analyzer_process", linked_destroy) - spawn(24) - if(linked_destroy) - if(!linked_destroy.hacked) - if(!linked_destroy.loaded_item) - to_chat(usr, "The destructive analyzer appears to be empty.") - screen = 1.0 - linked_destroy.busy = 0 - return - if(linked_destroy.loaded_item.reliability >= 90) - var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) - for(var/T in temp_tech) - files.UpdateTech(T, temp_tech[T]) - if(linked_destroy.loaded_item.reliability < 100 && linked_destroy.loaded_item.crit_fail) - files.UpdateDesign(linked_destroy.loaded_item.type) - if(linked_lathe && linked_destroy.loaded_item.materials) //Also sends salvaged materials to a linked protolathe, if any. - for(var/matID in linked_destroy.loaded_item.materials.storage) //Transfers by ID - linked_lathe.materials.addAmount(matID, linked_destroy.loaded_item.materials.storage[matID]) - linked_destroy.loaded_item = null - for(var/obj/I in linked_destroy.contents) - for(var/mob/M in I.contents) - M.death() - if(istype(I,/obj/item/stack/sheet)) //Only deconstructs one sheet at a time instead of the entire stack - var/obj/item/stack/sheet/S = I - if(S.amount > 1) - S.amount-- - linked_destroy.loaded_item = S - else - qdel(S) - S = null - linked_destroy.icon_state = "d_analyzer" - else - if(!(I in linked_destroy.component_parts)) - qdel(I) - I = null - linked_destroy.icon_state = "d_analyzer" - use_power(250) - screen = 1.0 - updateUsrDialog() - linked_destroy.busy = 0 - - else if(href_list["lock"]) //Lock the console from use by anyone without tox access. - if(src.allowed(usr)) - screen = text2num(href_list["lock"]) - else - to_chat(usr, "Unauthorized Access.") - - else if(href_list["sync"]) //Sync the research holder with all the R&D consoles in the game that aren't sync protected. - screen = 0.0 - if(!sync) - to_chat(usr, "You must connect to the network first!") - else - griefProtection() //Putting this here because I dont trust the sync process - spawn(30) - if(src) - for(var/obj/machinery/r_n_d/server/S in machines) - var/server_processed = 0 - if(S.disabled) - continue - if((id in S.id_with_upload) || istype(S, /obj/machinery/r_n_d/server/centcom)) - for(var/datum/tech/T in files.known_tech) - S.files.AddTech2Known(T) - for(var/datum/design/D in files.known_designs) - S.files.AddDesign2Known(D) - S.files.RefreshResearch() - server_processed = 1 - if(((id in S.id_with_download) && !istype(S, /obj/machinery/r_n_d/server/centcom)) || S.hacked) - for(var/datum/tech/T in S.files.known_tech) - files.AddTech2Known(T) - for(var/datum/design/D in S.files.known_designs) - files.AddDesign2Known(D) - files.RefreshResearch() - server_processed = 1 - if(!istype(S, /obj/machinery/r_n_d/server/centcom) && server_processed) - S.produce_heat(100) - screen = 1.6 - updateUsrDialog() - - else if(href_list["togglesync"]) //Prevents the console from being synced by other consoles. Can still send data. - sync = !sync - - else if(href_list["build"]) //Causes the Protolathe to build something. - if (!autorefresh) updateAfter = 0 //STOP - if(linked_lathe) - var/datum/design/being_built = null - for(var/datum/design/D in files.known_designs) - if(D.id == href_list["build"]) - being_built = D - break - if(being_built) - var/power = 2000 - for(var/M in being_built.materials) - power += round(being_built.materials[M] / 5) - power = max(2000, power) - //screen = 0.3 - var/n - if (href_list["customamt"]) - n = round(input("Queue how many? (Maximum [RESEARCH_MAX_Q_LEN - linked_lathe.queue.len])", "Protolathe Queue") as num|null) - if (!linked_lathe) return //in case the 'lathe gets unlinked or destroyed or someshit while the popup is open - else - n = text2num(href_list["n"]) - n = Clamp(n, 0, RESEARCH_MAX_Q_LEN - linked_lathe.queue.len) - for(var/i=1;i<=n;i++) - use_power(power) - linked_lathe.queue += being_built - if(href_list["now"]=="1") - linked_lathe.stopped=0 - - else if(href_list["imprint"]) //Causes the Circuit Imprinter to build something. - if (!autorefresh) updateAfter = 0 //STOP - if(linked_imprinter) - var/datum/design/being_built = null - - if(linked_imprinter.queue.len >= RESEARCH_MAX_Q_LEN) - to_chat(usr, "Maximum number of items in production queue exceeded.") - return - - for(var/datum/design/D in files.known_designs) - if(D.id == href_list["imprint"]) - being_built = D - break - if(being_built) - var/power = 2000 - for(var/M in being_built.materials) - power += round(being_built.materials[M] / 5) - power = max(2000, power) - var/n - if (href_list["customamt"]) - n = round(input("Queue how many? (Maximum [RESEARCH_MAX_Q_LEN - linked_imprinter.queue.len])", "Circuit Imprinter Queue") as num|null) - if (!linked_imprinter) return //in case the imprinter gets unlinked or destroyed or someshit while the popup is open - else - n = text2num(href_list["n"]) - n = Clamp(n, 0, RESEARCH_MAX_Q_LEN - linked_imprinter.queue.len) - for(var/i=1;i<=n;i++) - linked_imprinter.queue += being_built - use_power(power) - if(href_list["now"]=="1") - linked_imprinter.stopped=0 - - else if(href_list["disposeI"] && linked_imprinter) //Causes the circuit imprinter to dispose of a single reagent (all of it) - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - linked_imprinter.reagents.del_reagent(href_list["dispose"]) - - else if(href_list["disposeallI"] && linked_imprinter) //Causes the circuit imprinter to dispose of all it's reagents. - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - linked_imprinter.reagents.clear_reagents() - - else if(href_list["disposeP"] && linked_lathe) //Causes the protolathe to dispose of a single reagent (all of it) - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - linked_lathe.reagents.del_reagent(href_list["dispose"]) - - else if(href_list["disposeallP"] && linked_lathe) //Causes the protolathe to dispose of all it's reagents. - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - linked_lathe.reagents.clear_reagents() - - else if(href_list["removeQItem"]) //Causes the protolathe to dispose of all it's reagents. - var/i=text2num(href_list["removeQItem"]) - switch(href_list["device"]) - if("protolathe") - if(linked_lathe) - linked_lathe.queue.Cut(i,i+1) - if("imprinter") - if(linked_imprinter) - linked_imprinter.queue.Cut(i,i+1) - - else if(href_list["clearQ"]) //Causes the protolathe to dispose of all it's reagents. - switch(href_list["device"]) - if("protolathe") - if(linked_lathe) - linked_lathe.queue.len = 0 - if("imprinter") - if(linked_imprinter) - linked_imprinter.queue.len = 0 - - else if(href_list["setProtolatheStopped"] && linked_lathe) //Causes the protolathe to dispose of all it's reagents. - linked_lathe.stopped=(href_list["setProtolatheStopped"]=="1") - - else if(href_list["setImprinterStopped"] && linked_imprinter) //Causes the protolathe to dispose of all it's reagents. - linked_imprinter.stopped=(href_list["setImprinterStopped"]=="1") - - else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - var/desired_num_sheets = text2num(href_list["lathe_ejectsheet_amt"]) - if (desired_num_sheets <= 0) - return - var/matID=href_list["lathe_ejectsheet"] - var/datum/material/M=linked_lathe.materials.getMaterial(matID) - if(!istype(M)) - warning("PROTOLATHE: Unknown material [matID]! ([href])") - else - var/obj/item/stack/sheet/sheet = new M.sheettype(linked_lathe.get_output()) - var/available_num_sheets = round(linked_lathe.materials.storage[matID]/sheet.perunit) - if(available_num_sheets>0) - sheet.amount = min(available_num_sheets, desired_num_sheets) - linked_lathe.materials.removeAmount(matID, sheet.amount * sheet.perunit) - else - qdel (sheet) - sheet = null - else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the protolathe to eject a sheet of material - if(!src.allowed(usr)) - to_chat(usr, "Unauthorized Access.") - return - var/desired_num_sheets = text2num(href_list["imprinter_ejectsheet_amt"]) - if (desired_num_sheets <= 0) return - var/matID=href_list["imprinter_ejectsheet"] - var/datum/material/M=linked_imprinter.materials.getMaterial(matID) - if(!istype(M)) - warning("IMPRINTER: Unknown material [matID]! ([href])") - else - var/obj/item/stack/sheet/sheet = new M.sheettype(linked_imprinter.get_output()) - var/available_num_sheets = round(linked_imprinter.materials.storage[matID]/sheet.perunit) - if(available_num_sheets>0) - sheet.amount = min(available_num_sheets, desired_num_sheets) - linked_imprinter.materials.removeAmount(matID, sheet.amount * sheet.perunit) - else - qdel (sheet) - sheet = null - - else if(href_list["find_device"]) //The R&D console looks for devices nearby to link up with. - screen = 0.0 - spawn(20) - SyncRDevices() - screen = 1.7 - updateUsrDialog() - - else if(href_list["disconnect"]) //The R&D console disconnects with a specific device. - switch(href_list["disconnect"]) - if("destroy") - linked_destroy.linked_console = null - linked_destroy.update_icon() - linked_destroy = null - if("lathe") - linked_lathe.linked_console = null - linked_lathe.update_icon() - linked_lathe = null - if("imprinter") - linked_imprinter.linked_console = null - linked_imprinter.update_icon() - linked_imprinter = null - - else if(href_list["reset"]) //Reset the R&D console's database. - griefProtection() - var/choice = alert("R&D Console Database Reset", "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "Continue", "Cancel") - if(choice == "Continue") - screen = 0.0 - qdel(files) - files = new /datum/research(src) - spawn(20) - screen = 1.6 - updateUsrDialog() - - else if(href_list["toggleCategory"]) //Filter or unfilter a category - var/cat = href_list["toggleCategory"] - var/machine = href_list["machine"] - if (cat in filtered[machine]) - filtered[machine] -= cat - else - filtered[machine] += cat - - else if(href_list["toggleAllCategories"]) //Filter all categories, if all are filtered, clear filter. - var/machine = href_list["machine"] - var/list/tempfilter = filtered[machine] //t-thanks BYOND - if(tempfilter.len == (machine == "protolathe" ? linked_lathe.part_sets.len : linked_imprinter.part_sets.len)) - filtered[machine] = list() - else - filtered[machine] = list() - if (machine == "protolathe") - for(var/name_set in linked_lathe.part_sets) - filtered[machine] += name_set - else - for(var/name_set in linked_imprinter.part_sets) - filtered[machine] += name_set - - else if(href_list["toggleAutoRefresh"]) //STOP - autorefresh = !autorefresh - - if (updateAfter) updateUsrDialog() - return - -/obj/machinery/computer/rdconsole/proc/protolathe_header() - var/list/options=list() - if(screen!=3.1) - options += "Design Selection" - if(screen!=3.2) - options += "Material Storage" - if(screen!=3.3) - options += "Chemical Storage" - if(screen!=3.4) - options += "Production Queue ([linked_lathe.queue.len])" - return {"\[Main Menu\] -
    [list2text(options," || ")]

    "} - -/obj/machinery/computer/rdconsole/proc/CircuitImprinterHeader() - var/list/options=list() - if(screen!=4.1) - options += "Design Selection" - if(screen!=4.3) - options += "Material Storage" - if(screen!=4.2) - options += "Chemical Storage" - if(screen!=4.4) - options += "Production Queue ([linked_imprinter.queue.len])" - return {"\[Main Menu\] -
    [list2text(options," || ")]

    "} - -/obj/machinery/computer/rdconsole/attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - - user.set_machine(src) - var/dat = list("") - files.RefreshResearch() - switch(screen) //A quick check to make sure you get the right screen when a device is disconnected. - if(2 to 2.9) - if(linked_destroy == null) - screen = 2.0 - else if(linked_destroy.loaded_item == null) - screen = 2.1 - else - screen = 2.2 - if(3 to 3.9) - if(linked_lathe == null) - screen = 3.0 - if(4 to 4.9) - if(linked_imprinter == null) - screen = 4.0 - - switch(screen) - - //////////////////////R&D CONSOLE SCREENS////////////////// - if(0.0) dat += "Updating Database...." - - if(0.1) dat += "Processing and Updating Database..." - - if(0.2) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:584: dat += "SYSTEM LOCKED

    " - dat += {"SYSTEM LOCKED

    - Unlock"} - // END AUTOFIX - if(0.3) - dat += "Constructing Prototypes. Please Wait..." - - if(0.4) - dat += "Imprinting Circuit. Please Wait..." - - if(1.0) //Main Menu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:594: dat += "Main Menu:

    " - dat += {"Main Menu:

    - Current Research Levels
    "} - // END AUTOFIX - if(t_disk) dat += "Disk Operations
    " - else if(d_disk) dat += "Disk Operations
    " - else dat += "(Please Insert Disk)
    " - if(linked_destroy != null) dat += "Destructive Analyzer Menu
    " - if(linked_lathe != null) dat += "Protolathe Construction Menu
    " - if(linked_imprinter != null) dat += "Circuit Construction Menu
    " - if(user.client.holder) dat += "MAXIMUM SCIENCE
    " - dat += "Settings" - - if(1.1) //Research viewer - dat += "Current Research Levels:

    " - for(var/datum/tech/T in files.known_tech) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:607: dat += "[T.name]
    " - dat += {"[T.name]
    - * Level: [T.level]
    - * Summary: [T.desc]
    "} - // END AUTOFIX - dat += "Main Menu" - - if(1.2) //Technology Disk Menu - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:614: dat += "Main Menu
    " - dat += {"Main Menu
    - Disk Contents: (Technology Data Disk)

    "} - // END AUTOFIX - if(t_disk.stored == null) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:617: dat += "The disk has no data stored on it.
    " - dat += {"The disk has no data stored on it.
    - Operations: - Load Tech to Disk || "} - // END AUTOFIX - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:621: dat += "Name: [t_disk.stored.name]
    " - dat += {"Name: [t_disk.stored.name]
    - Level: [t_disk.stored.level]
    - Description: [t_disk.stored.desc]
    - Operations: - Upload to Database || - Clear Disk || "} - // END AUTOFIX - dat += "Eject Disk" - - if(1.3) //Technology Disk submenu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:630: dat += "
    Main Menu || " - dat += {"
    Main Menu || - Return to Disk Operations
    - Load Technology to Disk:

    "} - // END AUTOFIX - for(var/datum/tech/T in files.known_tech) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:634: dat += "[T.name] " - dat += {"[T.name] - (Copy to Disk)
    "} - // END AUTOFIX - if(1.4) //Design Disk menu. - dat += "Main Menu
    " - if(d_disk.blueprint == null) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:640: dat += "The disk has no data stored on it.
    " - dat += {"The disk has no data stored on it.
    - Operations: - Load Design to Disk || "} - // END AUTOFIX - else - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:644: dat += "Name: [d_disk.blueprint.name]
    " - dat += {"Name: [d_disk.blueprint.name]
    - Level: [Clamp(d_disk.blueprint.reliability + rand(-15,15), 0, 100)]
    "} - // END AUTOFIX - switch(d_disk.blueprint.build_type) - if(IMPRINTER) dat += "Lathe Type: Circuit Imprinter
    " - if(PROTOLATHE) dat += "Lathe Type: Proto-lathe
    " - if(AUTOLATHE) dat += "Lathe Type: Auto-lathe
    " - dat += "Required Materials:
    " - for(var/M in d_disk.blueprint.materials) - if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]]
    " - else dat += "* [M] x [d_disk.blueprint.materials[M]]
    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:654: dat += "
    Operations: " - dat += {"
    Operations: - Upload to Database || - Clear Disk || "} - // END AUTOFIX - dat += "Eject Disk" - - if(1.5) //Technology disk submenu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:660: dat += "Main Menu || " - dat += {"Main Menu || - Return to Disk Operations
    - Load Design to Disk:

    "} - // END AUTOFIX - for(var/datum/design/D in files.known_designs) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:664: dat += "[D.name] " - dat += {"[D.name] - (Copy to Disk)
    "} - // END AUTOFIX - if(1.6) //R&D console settings - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:668: dat += "Main Menu
    " - dat += {"Main Menu
    - R&D Console Setting:

    "} - // END AUTOFIX - if(sync) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:671: dat += "Sync Database with Network
    " - dat += {"Sync Database with Network
    - Disconnect from Research Network
    "} - // END AUTOFIX - else - dat += "Connect to Research Network
    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:675: dat += "Device Linkage Menu
    " - dat += {"Device Linkage Menu
    - Lock Console
    - Reset R&D Database.
    "} - // END AUTOFIX - if(1.7) //R&D device linkage - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:680: dat += "Main Menu || " - dat += {"Main Menu || - Settings Menu
    - R&D Console Device Linkage Menu:

    - Re-sync with Nearby Devices
    - Linked Devices:
    "} - // END AUTOFIX - var/remain_link = linked_machines - if(linked_destroy) - dat += "* Destructive Analyzer (Disconnect)
    " - remain_link -= linked_destroy - else - dat += "* (No Destructive Analyzer Linked)
    " - if(linked_lathe) - dat += "* Protolathe (Disconnect)
    " - remain_link -= linked_lathe - else - dat += "* (No Protolathe Linked)
    " - if(linked_imprinter) - dat += "* Circuit Imprinter (Disconnect)
    " - remain_link -= linked_imprinter - else - dat += "* (No Circuit Imprinter Linked)
    " - if(remain_link) - for(var/obj/machinery/r_n_d/R in remain_link) - dat += "* [R.name]
    " - - ////////////////////DESTRUCTIVE ANALYZER SCREENS//////////////////////////// - if(2.0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:700: dat += "NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE

    " - dat += {"NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE

    - Main Menu"} - // END AUTOFIX - if(2.1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:704: dat += "No Item Loaded. Standing-by...

    " - dat += {"No Item Loaded. Standing-by...

    - Main Menu"} - // END AUTOFIX - if(2.2) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:708: dat += "Main Menu
    " - dat += {"Main Menu
    - Deconstruction Menu
    - Name: [linked_destroy.loaded_item.name]
    - Origin Tech:
    "} - // END AUTOFIX - var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) - for(var/T in temp_tech) - dat += "* [CallTechName(T)] [temp_tech[T]]
    " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:715: dat += "
    Deconstruct Item || " - dat += {"
    Deconstruct Item || - Eject Item || "} - // END AUTOFIX - /////////////////////PROTOLATHE SCREENS///////////////////////// - if(3.0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:720: dat += "Main Menu
    " - dat += {"Main Menu
    - NO PROTOLATHE LINKED TO CONSOLE

    "} - // END AUTOFIX - if(3.1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:724: dat += "Main Menu || " - dat += protolathe_header()+{"Protolathe Construction Menu \[Auto-Refresh: [autorefresh ? "ON" : "OFF"]\]
    "} - // END AUTOFIX - dat += "Filter: " - for(var/name_set in linked_lathe.part_sets) - if (name_set in filtered["protolathe"]) - dat += "[name_set] / " - else - dat += "[name_set] / " - dat += "Filter All
    " - - for(var/name_set in linked_lathe.part_sets) - if(name_set in filtered["protolathe"]) - continue - dat += "

    [name_set]

      " - for(var/datum/design/D in files.known_designs) - if(!(D.build_type & PROTOLATHE) || D.category != name_set) - continue - var/temp_dat = "[D.name] [linked_lathe.output_part_cost(D)]" - var/upTo=10 - for(var/M in D.materials) - var/num_units_avail=linked_lathe.check_mat(D,M) - if(num_units_avail) - upTo = min(upTo, num_units_avail) - else - break - if (upTo) - dat += {"
    • - [temp_dat] Queue: "} - if(upTo>=5) - dat += "(×5)" - if(upTo>=10) - dat += "(×10)" - dat += "(Custom)" - dat += "
    • " - else - dat += "
    • [temp_dat]
    • " - dat += "
    " - - if(3.2) //Protolathe Material Storage Sub-menu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:763: dat += "Main Menu || " - dat += protolathe_header()+{"Material Storage
      "} - // END AUTOFIX - - - for(var/matID in linked_lathe.materials.storage) - var/datum/material/M=linked_lathe.materials.getMaterial(matID) - dat += "
    • [linked_lathe.materials.storage[matID]] cm3 of [M.processed_name]" - if(linked_lathe.materials.storage[matID] >= M.cc_per_sheet) - dat += " - (1 Sheet) " - if(linked_lathe.materials.storage[matID] >= (M.cc_per_sheet*5)) - dat += "(5 Sheets) " - dat += "(Max Sheets)" - else - dat += " - (Empty)" - dat += "
    • " - dat += "
    " - - if(3.3) //Protolathe Chemical Storage Submenu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:823: dat += "Main Menu || " - dat += protolathe_header()+{"Chemical Storage

    "} - // END AUTOFIX - for(var/datum/reagent/R in linked_lathe.reagents.reagent_list) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:827: dat += "Name: [R.name] | Units: [R.volume] " - dat += {"Name: [R.name] | Units: [R.volume] - (Purge)
    - Disposal All Chemicals in Storage
    "} - // END AUTOFIX - - if(3.4) //Protolathe Queue Management - dat += protolathe_header()+"Production Queue

      " - for(var/i=1;i<=linked_lathe.queue.len;i++) - var/datum/design/I=linked_lathe.queue[i] - dat += "
    • Name: [I.name]" - if(linked_lathe.stopped) - dat += "(Remove)
    • " - dat += "
    Remove All Queued Items
    " - if(linked_lathe.stopped) - dat += "Start Production" - else - dat += "Stop Production" - - ///////////////////CIRCUIT IMPRINTER SCREENS//////////////////// - if(4.0) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:833: dat += "Main Menu
    " - dat += {"Main Menu
    - NO CIRCUIT IMPRINTER LINKED TO CONSOLE

    "} - // END AUTOFIX - if(4.1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:837: dat += "Main Menu || " - dat += {"[CircuitImprinterHeader()] - Circuit Imprinter Menu \[Auto-Refresh: [autorefresh ? "ON" : "OFF"]\]
    - Material Amount: [linked_imprinter.TotalMaterials()] cm3
    - Chemical Volume: [linked_imprinter.reagents.total_volume]
    "} - // END AUTOFIX - dat += "Filter: " - for(var/name_set in linked_imprinter.part_sets) - if (name_set in filtered["imprinter"]) - dat += "[name_set] / " - else - dat += "[name_set] / " - dat += "Filter All
    " - - for(var/name_set in linked_imprinter.part_sets) - if(name_set in filtered["imprinter"]) - continue - dat += "

    [name_set]

      " - for(var/datum/design/D in files.known_designs) - if(!(D.build_type & IMPRINTER) || D.category != name_set) - continue - var/temp_dat = "[D.name] [linked_imprinter.output_part_cost(D)]" - var/upTo=10 - for(var/M in D.materials) - var/num_units_avail=linked_imprinter.check_mat(D,M) - if(num_units_avail) - upTo = min(upTo, num_units_avail) - else - break - if (upTo) - dat += {"
    • [temp_dat] Queue: "} - if(upTo>=5) - dat += "(×5)" - if(upTo>=10) - dat += "(×10)" - dat += "(Custom)" - dat += "
    • " - else - dat += "
    • [temp_dat]
    • " - dat += "
    " - - if(4.2) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:869: dat += "Main Menu || " - dat += {"[CircuitImprinterHeader()] - Chemical Storage
    "} - // END AUTOFIX - for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:873: dat += "Name: [R.name] | Units: [R.volume] " - dat += {"Name: [R.name] | Units: [R.volume] - (Purge)
    - Disposal All Chemicals in Storage
    "} - // END AUTOFIX - if(4.3) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:878: dat += "Main Menu || " - dat += {"[CircuitImprinterHeader()] - Material Storage
      "} - - - for(var/matID in linked_imprinter.materials.storage) - var/datum/material/M=linked_imprinter.materials.getMaterial(matID) - if(!(matID in linked_imprinter.allowed_materials)) - continue - dat += "
    • [linked_imprinter.materials.storage[matID]] cm3 of [M.processed_name]" - if(linked_imprinter.materials.storage[matID] >= M.cc_per_sheet) - dat += " - (1 Sheet) " - if(linked_imprinter.materials.storage[matID] >= (M.cc_per_sheet*5)) - dat += "(5 Sheets) " - dat += "(Max Sheets)" - else - dat += " - (Empty)" - dat += "
    • " - dat += "
    " - - if(4.4) //Imprinter Queue Management - dat += CircuitImprinterHeader()+"Production Queue

      " - for(var/i=1;i<=linked_imprinter.queue.len;i++) - var/datum/design/I=linked_imprinter.queue[i] - dat += "
    • Name: [I.name]" - if(linked_imprinter.stopped) - dat += "(Remove)
    • " - dat += "
    Remove All Queued Items
    " - if(linked_imprinter.stopped) - dat += "Start Production" - else - dat += "Stop Production" - - dat = list2text(dat) - user << browse("Research and Development Console
    [dat]", "window=rdconsole;size=575x400") - onclose(user, "rdconsole") - -/obj/machinery/computer/rdconsole/mommi - name = "MoMMI R&D Console" - id = 3 - req_access = list(access_tox) - circuit = "/obj/item/weapon/circuitboard/rdconsole/mommi" - -/obj/machinery/computer/rdconsole/robotics - name = "Robotics R&D Console" - id = 2 - req_one_access = list(access_robotics) - req_access=list() - circuit = "/obj/item/weapon/circuitboard/rdconsole/robotics" - -/obj/machinery/computer/rdconsole/mechanic - name = "Mechanics R&D Console" - id = 4 - req_one_access = list(access_mechanic) - req_access=list() - circuit = "/obj/item/weapon/circuitboard/rdconsole/mechanic" - -/obj/machinery/computer/rdconsole/core - name = "Core R&D Console" - id = 1 - req_access = list(access_tox) - circuit = "/obj/item/weapon/circuitboard/rdconsole" - -/obj/machinery/computer/rdconsole/pod - name = "Pod Bay R&D Console" - id = 5 - req_access=list() - circuit = "/obj/item/weapon/circuitboard/rdconsole/pod" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/* +Research and Development (R&D) Console + +This is the main work horse of the R&D system. It contains the menus/controls for the Destructive Analyzer, Protolathe, and Circuit +imprinter. It also contains the /datum/research holder with all the known/possible technology paths and device designs. + +Basic use: When it first is created, it will attempt to link up to related devices within 3 squares. It'll only link up if they +aren't already linked to another console. Any consoles it cannot link up with (either because all of a certain type are already +linked or there aren't any in range), you'll just not have access to that menu. In the settings menu, there are menu options that +allow a player to attempt to re-sync with nearby consoles. You can also force it to disconnect from a specific console. + +The imprinting and construction menus do NOT require toxins access to access but all the other menus do. However, if you leave it +on a menu, nothing is to stop the person from using the options on that menu (although they won't be able to change to a different +one). You can also lock the console on the settings menu if you're feeling paranoid and you don't want anyone messing with it who +doesn't have toxins access. + +When a R&D console is destroyed or even partially disassembled, you lose all research data on it. However, there are two ways around +this dire fate: +- The easiest way is to go to the settings menu and select "Sync Database with Network." That causes it to upload (but not download) +it's data to every other device in the game. Each console has a "disconnect from network" option that'll will cause data base sync +operations to skip that console. This is useful if you want to make a "public" R&D console or, for example, give the engineers +a circuit imprinter with certain designs on it and don't want it accidentally updating. The downside of this method is that you have +to have physical access to the other console to send data back. Note: An R&D console is on CentCom so if a random griffan happens to +cause a ton of data to be lost, an admin can go send it back. +- The second method is with Technology Disks and Design Disks. Each of these disks can hold a single technology or design datum in +it's entirety. You can then take the disk to any R&D console and upload it's data to it. This method is a lot more secure (since it +won't update every console in existence) but it's more of a hassle to do. Also, the disks can be stolen. + + +*/ +#define RESEARCH_MAX_Q_LEN 30 +/obj/machinery/computer/rdconsole + name = "R&D Console" + icon_state = "rdcomp" + circuit = "/obj/item/weapon/circuitboard/rdconsole" + var/datum/research/files //Stores all the collected research data. + var/obj/item/weapon/disk/tech_disk/t_disk = null //Stores the technology disk. + var/obj/item/weapon/disk/design_disk/d_disk = null //Stores the design disk. + + var/obj/machinery/r_n_d/destructive_analyzer/linked_destroy = null //Linked Destructive Analyzer + var/obj/machinery/r_n_d/fabricator/protolathe/linked_lathe = null //Linked Protolathe + var/obj/machinery/r_n_d/fabricator/circuit_imprinter/linked_imprinter = null //Linked Circuit Imprinter + + var/list/obj/machinery/linked_machines = list() + var/list/research_machines = list( + /obj/machinery/r_n_d/fabricator/protolathe, + /obj/machinery/r_n_d/destructive_analyzer, + /obj/machinery/r_n_d/fabricator/circuit_imprinter, + /obj/machinery/r_n_d/fabricator/mech, + /obj/machinery/r_n_d/fabricator/pod, + /obj/machinery/r_n_d/fabricator/mechanic_fab, + /obj/machinery/r_n_d/fabricator/mechanic_fab/flatpacker, + /obj/machinery/r_n_d/reverse_engine, + /obj/machinery/r_n_d/blueprinter + ) + var/screen = 1.0 //Which screen is currently showing. + var/id = 0 //ID of the computer (for server restrictions). + var/sync = 1 //If sync = 0, it doesn't show up on Server Control Console + + var/list/filtered = list( //Filters categories in the protolathe menu + "protolathe" = list(), + "imprinter" = list() + ) + var/autorefresh = 1 //Prevents the window from being updated while queueing items + + req_access = list(access_tox) //Data and setting manipulation requires scientist access. + + starting_materials = list() + + light_color = LIGHT_COLOR_PINK + + var/part_sets = list( + "Stock Parts" = list(), + "Bluespace" = list(), + "Data" = list(), + "Engineering" = list(), + "Medical" = list(), + "Mining" = list(), + "Robotics" = list(), + "Weapons" = list(), + "Armor" = list(), + "Misc" = list(), + ) + +/obj/machinery/computer/rdconsole/Destroy() + . = ..() + for(var/obj/machinery/r_n_d/R in linked_machines) + R.linked_console = null + linked_machines -= R + R.update_icon() + + if(linked_destroy) + linked_destroy.linked_console = null + linked_destroy.update_icon() + linked_destroy = null + + if(linked_imprinter) + linked_imprinter.linked_console = null + linked_imprinter.update_icon() + linked_imprinter = null + + if(linked_lathe) + linked_lathe.linked_console = null + linked_lathe.update_icon() + linked_lathe = null + +/obj/machinery/computer/rdconsole/proc/Maximize() + files.known_tech = tech_list.Copy() + for(var/datum/tech/KT in files.known_tech) + if(KT.level < KT.max_level) + KT.level=KT.max_level + +/obj/machinery/computer/rdconsole/proc/CallTechName(var/ID) //A simple helper proc to find the name of a tech with a given ID. + var/datum/tech/check_tech + var/return_name = "" + + for (var/T in typesof(/datum/tech) - /datum/tech) + check_tech = T + + if (initial(check_tech.id) == ID) + return_name = initial(check_tech.name) + break + + return return_name + +/obj/machinery/computer/rdconsole/proc/CallMaterialName(var/ID) + var/return_name = null + if (copytext(ID, 1, 2) == "$") + var/datum/material/mat = materials.getMaterial(ID) + return mat.processed_name + else + for(var/R in typesof(/datum/reagent) - /datum/reagent) + var/datum/reagent/T = new R() + if(T.id == ID) + return_name = T.name + break + return return_name + +/obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any). + if(!isarea(areaMaster) || isspace(areaMaster)) + say("Unable to process synchronization") + return + + + for(var/obj/machinery/r_n_d/D in rnd_machines) //any machine in the room, just for funsies + if(D.linked_console != null || D.disabled || D.panel_open || !D.areaMaster || (D.areaMaster != areaMaster)) + continue + if(D.type in research_machines) + linked_machines += D + D.linked_console = src + D.update_icon() + for(var/obj/machinery/r_n_d/D in linked_machines) + if(linked_lathe && linked_destroy && linked_imprinter) break // stop if we have all of our linked + switch(D.type) + if(/obj/machinery/r_n_d/fabricator/protolathe) + if(!linked_lathe) + linked_lathe = D + if(/obj/machinery/r_n_d/destructive_analyzer) + if(!linked_destroy) + linked_destroy = D + if(/obj/machinery/r_n_d/fabricator/circuit_imprinter) + if(!linked_imprinter) + linked_imprinter = D + if(linked_lathe) + linked_lathe.part_sets = part_sets + return + +//Have it automatically push research to the centcomm server so wild griffins can't fuck up R&D's work --NEO +/obj/machinery/computer/rdconsole/proc/griefProtection() + for(var/obj/machinery/r_n_d/server/centcom/C in machines) + for(var/datum/tech/T in files.known_tech) + C.files.AddTech2Known(T) + for(var/datum/design/D in files.known_designs) + C.files.AddDesign2Known(D) + C.files.RefreshResearch() + + +/obj/machinery/computer/rdconsole/New() + ..() + files = new /datum/research(src) //Setup the research data holder. + if(!id) + for(var/obj/machinery/r_n_d/server/centcom/S in machines) + S.initialize() + break + +/obj/machinery/computer/rdconsole/initialize() + SyncRDevices() + +/* Instead of calling this every tick, it is only being called when needed +/obj/machinery/computer/rdconsole/process() + griefProtection() +*/ + +/obj/machinery/computer/rdconsole/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) + if(..()) + return + if(istype(D, /obj/item/weapon/disk)) + if(t_disk || d_disk) + to_chat(user, "A disk is already loaded into the machine.") + return + + if(istype(D, /obj/item/weapon/disk/tech_disk)) + if(user.drop_item(D,src)) + t_disk = D + else if (istype(D, /obj/item/weapon/disk/design_disk)) + if(user.drop_item(D,src)) + d_disk = D + else + to_chat(user, "Machine cannot accept disks in that format.") + return + + to_chat(user, "You add the disk to the machine!") + + src.updateUsrDialog() + return + +/obj/machinery/computer/rdconsole/emag(mob/user) + playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + emagged = 1 + to_chat(user, "You disable the security protocols") + +/obj/machinery/computer/rdconsole/Topic(href, href_list) + if(..()) + return + + var/updateAfter = 1 //STOP + + add_fingerprint(usr) + + usr.set_machine(src) + if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code. + var/temp_screen = text2num(href_list["menu"]) + if(temp_screen <= 1.1 || (2 <= temp_screen && 4.9 >= temp_screen) || src.allowed(usr) || emagged) //Unless you are making something, you need access. + screen = temp_screen + else + to_chat(usr, "Unauthorized Access.") + + else if(href_list["updt_tech"]) //Update the research holder with information from the technology disk. + screen = 0.0 + spawn(50) + screen = 1.2 + files.AddTech2Known(t_disk.stored) + if(t_disk.stored.new_category && !(t_disk.stored.new_category in part_sets)) + part_sets += t_disk.stored.new_category + part_sets[t_disk.stored.new_category] = list() + if(linked_lathe) + linked_lathe.part_sets = part_sets + updateUsrDialog() + griefProtection() //Update centcomm too + + else if(href_list["hax"]) // aww shit + if(!usr.client.holder) return + screen = 0.0 + spawn(50) + Maximize() + screen = 1.0 + updateUsrDialog() + griefProtection() //Update centcomm too + + else if(href_list["clear_tech"]) //Erase data on the technology disk. + t_disk.stored = null + + else if(href_list["eject_tech"]) //Eject the technology disk. + t_disk:loc = src.loc + t_disk = null + screen = 1.0 + + else if(href_list["copy_tech"]) //Copys some technology data from the research holder to the disk. + for(var/datum/tech/T in files.known_tech) + if(href_list["copy_tech_ID"] == T.id) + t_disk.stored = T + break + screen = 1.2 + + else if(href_list["updt_design"]) //Updates the research holder with design data from the design disk. + screen = 0.0 + spawn(50) + screen = 1.4 + files.AddDesign2Known(d_disk.blueprint) + updateUsrDialog() + griefProtection() //Update centcomm too + + else if(href_list["clear_design"]) //Erases data on the design disk. + d_disk.blueprint = null + + else if(href_list["eject_design"]) //Eject the design disk. + d_disk:loc = src.loc + d_disk = null + screen = 1.0 + + else if(href_list["copy_design"]) //Copy design data from the research holder to the design disk. + for(var/datum/design/D in files.known_designs) + if(href_list["copy_design_ID"] == D.id) + d_disk.blueprint = D + break + screen = 1.4 + + else if(href_list["eject_item"]) //Eject the item inside the destructive analyzer. + if(linked_destroy) + if(linked_destroy.busy) + to_chat(usr, "The destructive analyzer is busy at the moment.") + + else if(linked_destroy.loaded_item) + linked_destroy.loaded_item.loc = linked_destroy.loc + linked_destroy.loaded_item = null + linked_destroy.icon_state = "d_analyzer" + screen = 2.1 + + else if(href_list["deconstruct"]) //Deconstruct the item in the destructive analyzer and update the research holder. + if(linked_destroy) + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + if(linked_destroy.busy) + to_chat(usr, "The destructive analyzer is busy at the moment.") + else + var/choice = input("Proceeding will destroy loaded item.") in list("Proceed", "Cancel") + if(choice == "Cancel" || !linked_destroy) return + linked_destroy.busy = 1 + screen = 0.1 + updateUsrDialog() + flick("d_analyzer_process", linked_destroy) + spawn(24) + if(linked_destroy) + if(!linked_destroy.hacked) + if(!linked_destroy.loaded_item) + to_chat(usr, "The destructive analyzer appears to be empty.") + screen = 1.0 + linked_destroy.busy = 0 + return + if(linked_destroy.loaded_item.reliability >= 90) + var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) + for(var/T in temp_tech) + files.UpdateTech(T, temp_tech[T]) + if(linked_destroy.loaded_item.reliability < 100 && linked_destroy.loaded_item.crit_fail) + files.UpdateDesign(linked_destroy.loaded_item.type) + if(linked_lathe && linked_destroy.loaded_item.materials) //Also sends salvaged materials to a linked protolathe, if any. + for(var/matID in linked_destroy.loaded_item.materials.storage) //Transfers by ID + linked_lathe.materials.addAmount(matID, linked_destroy.loaded_item.materials.storage[matID]) + linked_destroy.loaded_item = null + for(var/obj/I in linked_destroy.contents) + for(var/mob/M in I.contents) + M.death() + if(istype(I,/obj/item/stack/sheet)) //Only deconstructs one sheet at a time instead of the entire stack + var/obj/item/stack/sheet/S = I + if(S.amount > 1) + S.amount-- + linked_destroy.loaded_item = S + else + qdel(S) + S = null + linked_destroy.icon_state = "d_analyzer" + else + if(!(I in linked_destroy.component_parts)) + qdel(I) + I = null + linked_destroy.icon_state = "d_analyzer" + use_power(250) + screen = 1.0 + updateUsrDialog() + linked_destroy.busy = 0 + + else if(href_list["lock"]) //Lock the console from use by anyone without tox access. + if(src.allowed(usr)) + screen = text2num(href_list["lock"]) + else + to_chat(usr, "Unauthorized Access.") + + else if(href_list["sync"]) //Sync the research holder with all the R&D consoles in the game that aren't sync protected. + screen = 0.0 + if(!sync) + to_chat(usr, "You must connect to the network first!") + else + griefProtection() //Putting this here because I dont trust the sync process + spawn(30) + if(src) + for(var/obj/machinery/r_n_d/server/S in machines) + var/server_processed = 0 + if(S.disabled) + continue + if((id in S.id_with_upload) || istype(S, /obj/machinery/r_n_d/server/centcom)) + for(var/datum/tech/T in files.known_tech) + S.files.AddTech2Known(T) + for(var/datum/design/D in files.known_designs) + S.files.AddDesign2Known(D) + S.files.RefreshResearch() + server_processed = 1 + if(((id in S.id_with_download) && !istype(S, /obj/machinery/r_n_d/server/centcom)) || S.hacked) + for(var/datum/tech/T in S.files.known_tech) + files.AddTech2Known(T) + for(var/datum/design/D in S.files.known_designs) + files.AddDesign2Known(D) + files.RefreshResearch() + server_processed = 1 + if(!istype(S, /obj/machinery/r_n_d/server/centcom) && server_processed) + S.produce_heat(100) + screen = 1.6 + updateUsrDialog() + + else if(href_list["togglesync"]) //Prevents the console from being synced by other consoles. Can still send data. + sync = !sync + + else if(href_list["build"]) //Causes the Protolathe to build something. + if (!autorefresh) updateAfter = 0 //STOP + if(linked_lathe) + var/datum/design/being_built = null + for(var/datum/design/D in files.known_designs) + if(D.id == href_list["build"]) + being_built = D + break + if(being_built) + var/power = 2000 + for(var/M in being_built.materials) + power += round(being_built.materials[M] / 5) + power = max(2000, power) + //screen = 0.3 + var/n + if (href_list["customamt"]) + n = round(input("Queue how many? (Maximum [RESEARCH_MAX_Q_LEN - linked_lathe.queue.len])", "Protolathe Queue") as num|null) + if (!linked_lathe) return //in case the 'lathe gets unlinked or destroyed or someshit while the popup is open + else + n = text2num(href_list["n"]) + n = Clamp(n, 0, RESEARCH_MAX_Q_LEN - linked_lathe.queue.len) + for(var/i=1;i<=n;i++) + use_power(power) + linked_lathe.queue += being_built + if(href_list["now"]=="1") + linked_lathe.stopped=0 + + else if(href_list["imprint"]) //Causes the Circuit Imprinter to build something. + if (!autorefresh) updateAfter = 0 //STOP + if(linked_imprinter) + var/datum/design/being_built = null + + if(linked_imprinter.queue.len >= RESEARCH_MAX_Q_LEN) + to_chat(usr, "Maximum number of items in production queue exceeded.") + return + + for(var/datum/design/D in files.known_designs) + if(D.id == href_list["imprint"]) + being_built = D + break + if(being_built) + var/power = 2000 + for(var/M in being_built.materials) + power += round(being_built.materials[M] / 5) + power = max(2000, power) + var/n + if (href_list["customamt"]) + n = round(input("Queue how many? (Maximum [RESEARCH_MAX_Q_LEN - linked_imprinter.queue.len])", "Circuit Imprinter Queue") as num|null) + if (!linked_imprinter) return //in case the imprinter gets unlinked or destroyed or someshit while the popup is open + else + n = text2num(href_list["n"]) + n = Clamp(n, 0, RESEARCH_MAX_Q_LEN - linked_imprinter.queue.len) + for(var/i=1;i<=n;i++) + linked_imprinter.queue += being_built + use_power(power) + if(href_list["now"]=="1") + linked_imprinter.stopped=0 + + else if(href_list["disposeI"] && linked_imprinter) //Causes the circuit imprinter to dispose of a single reagent (all of it) + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + linked_imprinter.reagents.del_reagent(href_list["dispose"]) + + else if(href_list["disposeallI"] && linked_imprinter) //Causes the circuit imprinter to dispose of all it's reagents. + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + linked_imprinter.reagents.clear_reagents() + + else if(href_list["disposeP"] && linked_lathe) //Causes the protolathe to dispose of a single reagent (all of it) + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + linked_lathe.reagents.del_reagent(href_list["dispose"]) + + else if(href_list["disposeallP"] && linked_lathe) //Causes the protolathe to dispose of all it's reagents. + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + linked_lathe.reagents.clear_reagents() + + else if(href_list["removeQItem"]) //Causes the protolathe to dispose of all it's reagents. + var/i=text2num(href_list["removeQItem"]) + switch(href_list["device"]) + if("protolathe") + if(linked_lathe) + linked_lathe.queue.Cut(i,i+1) + if("imprinter") + if(linked_imprinter) + linked_imprinter.queue.Cut(i,i+1) + + else if(href_list["clearQ"]) //Causes the protolathe to dispose of all it's reagents. + switch(href_list["device"]) + if("protolathe") + if(linked_lathe) + linked_lathe.queue.len = 0 + if("imprinter") + if(linked_imprinter) + linked_imprinter.queue.len = 0 + + else if(href_list["setProtolatheStopped"] && linked_lathe) //Causes the protolathe to dispose of all it's reagents. + linked_lathe.stopped=(href_list["setProtolatheStopped"]=="1") + + else if(href_list["setImprinterStopped"] && linked_imprinter) //Causes the protolathe to dispose of all it's reagents. + linked_imprinter.stopped=(href_list["setImprinterStopped"]=="1") + + else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + var/desired_num_sheets = text2num(href_list["lathe_ejectsheet_amt"]) + if (desired_num_sheets <= 0) + return + var/matID=href_list["lathe_ejectsheet"] + var/datum/material/M=linked_lathe.materials.getMaterial(matID) + if(!istype(M)) + warning("PROTOLATHE: Unknown material [matID]! ([href])") + else + var/obj/item/stack/sheet/sheet = new M.sheettype(linked_lathe.get_output()) + var/available_num_sheets = round(linked_lathe.materials.storage[matID]/sheet.perunit) + if(available_num_sheets>0) + sheet.amount = min(available_num_sheets, desired_num_sheets) + linked_lathe.materials.removeAmount(matID, sheet.amount * sheet.perunit) + else + qdel (sheet) + sheet = null + else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the protolathe to eject a sheet of material + if(!src.allowed(usr)) + to_chat(usr, "Unauthorized Access.") + return + var/desired_num_sheets = text2num(href_list["imprinter_ejectsheet_amt"]) + if (desired_num_sheets <= 0) return + var/matID=href_list["imprinter_ejectsheet"] + var/datum/material/M=linked_imprinter.materials.getMaterial(matID) + if(!istype(M)) + warning("IMPRINTER: Unknown material [matID]! ([href])") + else + var/obj/item/stack/sheet/sheet = new M.sheettype(linked_imprinter.get_output()) + var/available_num_sheets = round(linked_imprinter.materials.storage[matID]/sheet.perunit) + if(available_num_sheets>0) + sheet.amount = min(available_num_sheets, desired_num_sheets) + linked_imprinter.materials.removeAmount(matID, sheet.amount * sheet.perunit) + else + qdel (sheet) + sheet = null + + else if(href_list["find_device"]) //The R&D console looks for devices nearby to link up with. + screen = 0.0 + spawn(20) + SyncRDevices() + screen = 1.7 + updateUsrDialog() + + else if(href_list["disconnect"]) //The R&D console disconnects with a specific device. + switch(href_list["disconnect"]) + if("destroy") + linked_destroy.linked_console = null + linked_destroy.update_icon() + linked_destroy = null + if("lathe") + linked_lathe.linked_console = null + linked_lathe.update_icon() + linked_lathe = null + if("imprinter") + linked_imprinter.linked_console = null + linked_imprinter.update_icon() + linked_imprinter = null + + else if(href_list["reset"]) //Reset the R&D console's database. + griefProtection() + var/choice = alert("R&D Console Database Reset", "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "Continue", "Cancel") + if(choice == "Continue") + screen = 0.0 + qdel(files) + files = new /datum/research(src) + spawn(20) + screen = 1.6 + updateUsrDialog() + + else if(href_list["toggleCategory"]) //Filter or unfilter a category + var/cat = href_list["toggleCategory"] + var/machine = href_list["machine"] + if (cat in filtered[machine]) + filtered[machine] -= cat + else + filtered[machine] += cat + + else if(href_list["toggleAllCategories"]) //Filter all categories, if all are filtered, clear filter. + var/machine = href_list["machine"] + var/list/tempfilter = filtered[machine] //t-thanks BYOND + if(tempfilter.len == (machine == "protolathe" ? linked_lathe.part_sets.len : linked_imprinter.part_sets.len)) + filtered[machine] = list() + else + filtered[machine] = list() + if (machine == "protolathe") + for(var/name_set in linked_lathe.part_sets) + filtered[machine] += name_set + else + for(var/name_set in linked_imprinter.part_sets) + filtered[machine] += name_set + + else if(href_list["toggleAutoRefresh"]) //STOP + autorefresh = !autorefresh + + if (updateAfter) updateUsrDialog() + return + +/obj/machinery/computer/rdconsole/proc/protolathe_header() + var/list/options=list() + if(screen!=3.1) + options += "Design Selection" + if(screen!=3.2) + options += "Material Storage" + if(screen!=3.3) + options += "Chemical Storage" + if(screen!=3.4) + options += "Production Queue ([linked_lathe.queue.len])" + return {"\[Main Menu\] +
    [list2text(options," || ")]

    "} + +/obj/machinery/computer/rdconsole/proc/CircuitImprinterHeader() + var/list/options=list() + if(screen!=4.1) + options += "Design Selection" + if(screen!=4.3) + options += "Material Storage" + if(screen!=4.2) + options += "Chemical Storage" + if(screen!=4.4) + options += "Production Queue ([linked_imprinter.queue.len])" + return {"\[Main Menu\] +
    [list2text(options," || ")]

    "} + +/obj/machinery/computer/rdconsole/attack_hand(mob/user as mob) + if(stat & (BROKEN|NOPOWER)) + return + + user.set_machine(src) + var/dat = list("") + files.RefreshResearch() + switch(screen) //A quick check to make sure you get the right screen when a device is disconnected. + if(2 to 2.9) + if(linked_destroy == null) + screen = 2.0 + else if(linked_destroy.loaded_item == null) + screen = 2.1 + else + screen = 2.2 + if(3 to 3.9) + if(linked_lathe == null) + screen = 3.0 + if(4 to 4.9) + if(linked_imprinter == null) + screen = 4.0 + + switch(screen) + + //////////////////////R&D CONSOLE SCREENS////////////////// + if(0.0) dat += "Updating Database...." + + if(0.1) dat += "Processing and Updating Database..." + + if(0.2) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:584: dat += "SYSTEM LOCKED

    " + dat += {"SYSTEM LOCKED

    + Unlock"} + // END AUTOFIX + if(0.3) + dat += "Constructing Prototypes. Please Wait..." + + if(0.4) + dat += "Imprinting Circuit. Please Wait..." + + if(1.0) //Main Menu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:594: dat += "Main Menu:

    " + dat += {"Main Menu:

    + Current Research Levels
    "} + // END AUTOFIX + if(t_disk) dat += "Disk Operations
    " + else if(d_disk) dat += "Disk Operations
    " + else dat += "(Please Insert Disk)
    " + if(linked_destroy != null) dat += "Destructive Analyzer Menu
    " + if(linked_lathe != null) dat += "Protolathe Construction Menu
    " + if(linked_imprinter != null) dat += "Circuit Construction Menu
    " + if(user.client.holder) dat += "MAXIMUM SCIENCE
    " + dat += "Settings" + + if(1.1) //Research viewer + dat += "Current Research Levels:

    " + for(var/datum/tech/T in files.known_tech) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:607: dat += "[T.name]
    " + dat += {"[T.name]
    + * Level: [T.level]
    + * Summary: [T.desc]
    "} + // END AUTOFIX + dat += "Main Menu" + + if(1.2) //Technology Disk Menu + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:614: dat += "Main Menu
    " + dat += {"Main Menu
    + Disk Contents: (Technology Data Disk)

    "} + // END AUTOFIX + if(t_disk.stored == null) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:617: dat += "The disk has no data stored on it.
    " + dat += {"The disk has no data stored on it.
    + Operations: + Load Tech to Disk || "} + // END AUTOFIX + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:621: dat += "Name: [t_disk.stored.name]
    " + dat += {"Name: [t_disk.stored.name]
    + Level: [t_disk.stored.level]
    + Description: [t_disk.stored.desc]
    + Operations: + Upload to Database || + Clear Disk || "} + // END AUTOFIX + dat += "Eject Disk" + + if(1.3) //Technology Disk submenu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:630: dat += "
    Main Menu || " + dat += {"
    Main Menu || + Return to Disk Operations
    + Load Technology to Disk:

    "} + // END AUTOFIX + for(var/datum/tech/T in files.known_tech) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:634: dat += "[T.name] " + dat += {"[T.name] + (Copy to Disk)
    "} + // END AUTOFIX + if(1.4) //Design Disk menu. + dat += "Main Menu
    " + if(d_disk.blueprint == null) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:640: dat += "The disk has no data stored on it.
    " + dat += {"The disk has no data stored on it.
    + Operations: + Load Design to Disk || "} + // END AUTOFIX + else + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:644: dat += "Name: [d_disk.blueprint.name]
    " + dat += {"Name: [d_disk.blueprint.name]
    + Level: [Clamp(d_disk.blueprint.reliability + rand(-15,15), 0, 100)]
    "} + // END AUTOFIX + switch(d_disk.blueprint.build_type) + if(IMPRINTER) dat += "Lathe Type: Circuit Imprinter
    " + if(PROTOLATHE) dat += "Lathe Type: Proto-lathe
    " + if(AUTOLATHE) dat += "Lathe Type: Auto-lathe
    " + dat += "Required Materials:
    " + for(var/M in d_disk.blueprint.materials) + if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]]
    " + else dat += "* [M] x [d_disk.blueprint.materials[M]]
    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:654: dat += "
    Operations: " + dat += {"
    Operations: + Upload to Database || + Clear Disk || "} + // END AUTOFIX + dat += "Eject Disk" + + if(1.5) //Technology disk submenu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:660: dat += "Main Menu || " + dat += {"Main Menu || + Return to Disk Operations
    + Load Design to Disk:

    "} + // END AUTOFIX + for(var/datum/design/D in files.known_designs) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:664: dat += "[D.name] " + dat += {"[D.name] + (Copy to Disk)
    "} + // END AUTOFIX + if(1.6) //R&D console settings + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:668: dat += "Main Menu
    " + dat += {"Main Menu
    + R&D Console Setting:

    "} + // END AUTOFIX + if(sync) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:671: dat += "Sync Database with Network
    " + dat += {"Sync Database with Network
    + Disconnect from Research Network
    "} + // END AUTOFIX + else + dat += "Connect to Research Network
    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:675: dat += "Device Linkage Menu
    " + dat += {"Device Linkage Menu
    + Lock Console
    + Reset R&D Database.
    "} + // END AUTOFIX + if(1.7) //R&D device linkage + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:680: dat += "Main Menu || " + dat += {"Main Menu || + Settings Menu
    + R&D Console Device Linkage Menu:

    + Re-sync with Nearby Devices
    + Linked Devices:
    "} + // END AUTOFIX + var/remain_link = linked_machines + if(linked_destroy) + dat += "* Destructive Analyzer (Disconnect)
    " + remain_link -= linked_destroy + else + dat += "* (No Destructive Analyzer Linked)
    " + if(linked_lathe) + dat += "* Protolathe (Disconnect)
    " + remain_link -= linked_lathe + else + dat += "* (No Protolathe Linked)
    " + if(linked_imprinter) + dat += "* Circuit Imprinter (Disconnect)
    " + remain_link -= linked_imprinter + else + dat += "* (No Circuit Imprinter Linked)
    " + if(remain_link) + for(var/obj/machinery/r_n_d/R in remain_link) + dat += "* [R.name]
    " + + ////////////////////DESTRUCTIVE ANALYZER SCREENS//////////////////////////// + if(2.0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:700: dat += "NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE

    " + dat += {"NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE

    + Main Menu"} + // END AUTOFIX + if(2.1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:704: dat += "No Item Loaded. Standing-by...

    " + dat += {"No Item Loaded. Standing-by...

    + Main Menu"} + // END AUTOFIX + if(2.2) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:708: dat += "Main Menu
    " + dat += {"Main Menu
    + Deconstruction Menu
    + Name: [linked_destroy.loaded_item.name]
    + Origin Tech:
    "} + // END AUTOFIX + var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech) + for(var/T in temp_tech) + dat += "* [CallTechName(T)] [temp_tech[T]]
    " + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:715: dat += "
    Deconstruct Item || " + dat += {"
    Deconstruct Item || + Eject Item || "} + // END AUTOFIX + /////////////////////PROTOLATHE SCREENS///////////////////////// + if(3.0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:720: dat += "Main Menu
    " + dat += {"Main Menu
    + NO PROTOLATHE LINKED TO CONSOLE

    "} + // END AUTOFIX + if(3.1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:724: dat += "Main Menu || " + dat += protolathe_header()+{"Protolathe Construction Menu \[Auto-Refresh: [autorefresh ? "ON" : "OFF"]\]
    "} + // END AUTOFIX + dat += "Filter: " + for(var/name_set in linked_lathe.part_sets) + if (name_set in filtered["protolathe"]) + dat += "[name_set] / " + else + dat += "[name_set] / " + dat += "Filter All
    " + + for(var/name_set in linked_lathe.part_sets) + if(name_set in filtered["protolathe"]) + continue + dat += "

    [name_set]

      " + for(var/datum/design/D in files.known_designs) + if(!(D.build_type & PROTOLATHE) || D.category != name_set) + continue + var/temp_dat = "[D.name] [linked_lathe.output_part_cost(D)]" + var/upTo=10 + for(var/M in D.materials) + var/num_units_avail=linked_lathe.check_mat(D,M) + if(num_units_avail) + upTo = min(upTo, num_units_avail) + else + break + if (upTo) + dat += {"
    • + [temp_dat] Queue: "} + if(upTo>=5) + dat += "(×5)" + if(upTo>=10) + dat += "(×10)" + dat += "(Custom)" + dat += "
    • " + else + dat += "
    • [temp_dat]
    • " + dat += "
    " + + if(3.2) //Protolathe Material Storage Sub-menu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:763: dat += "Main Menu || " + dat += protolathe_header()+{"Material Storage
      "} + // END AUTOFIX + + + for(var/matID in linked_lathe.materials.storage) + var/datum/material/M=linked_lathe.materials.getMaterial(matID) + dat += "
    • [linked_lathe.materials.storage[matID]] cm3 of [M.processed_name]" + if(linked_lathe.materials.storage[matID] >= M.cc_per_sheet) + dat += " - (1 Sheet) " + if(linked_lathe.materials.storage[matID] >= (M.cc_per_sheet*5)) + dat += "(5 Sheets) " + dat += "(Max Sheets)" + else + dat += " - (Empty)" + dat += "
    • " + dat += "
    " + + if(3.3) //Protolathe Chemical Storage Submenu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:823: dat += "Main Menu || " + dat += protolathe_header()+{"Chemical Storage

    "} + // END AUTOFIX + for(var/datum/reagent/R in linked_lathe.reagents.reagent_list) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:827: dat += "Name: [R.name] | Units: [R.volume] " + dat += {"Name: [R.name] | Units: [R.volume] + (Purge)
    + Disposal All Chemicals in Storage
    "} + // END AUTOFIX + + if(3.4) //Protolathe Queue Management + dat += protolathe_header()+"Production Queue

      " + for(var/i=1;i<=linked_lathe.queue.len;i++) + var/datum/design/I=linked_lathe.queue[i] + dat += "
    • Name: [I.name]" + if(linked_lathe.stopped) + dat += "(Remove)
    • " + dat += "
    Remove All Queued Items
    " + if(linked_lathe.stopped) + dat += "Start Production" + else + dat += "Stop Production" + + ///////////////////CIRCUIT IMPRINTER SCREENS//////////////////// + if(4.0) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:833: dat += "Main Menu
    " + dat += {"Main Menu
    + NO CIRCUIT IMPRINTER LINKED TO CONSOLE

    "} + // END AUTOFIX + if(4.1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:837: dat += "Main Menu || " + dat += {"[CircuitImprinterHeader()] + Circuit Imprinter Menu \[Auto-Refresh: [autorefresh ? "ON" : "OFF"]\]
    + Material Amount: [linked_imprinter.TotalMaterials()] cm3
    + Chemical Volume: [linked_imprinter.reagents.total_volume]
    "} + // END AUTOFIX + dat += "Filter: " + for(var/name_set in linked_imprinter.part_sets) + if (name_set in filtered["imprinter"]) + dat += "[name_set] / " + else + dat += "[name_set] / " + dat += "Filter All
    " + + for(var/name_set in linked_imprinter.part_sets) + if(name_set in filtered["imprinter"]) + continue + dat += "

    [name_set]

      " + for(var/datum/design/D in files.known_designs) + if(!(D.build_type & IMPRINTER) || D.category != name_set) + continue + var/temp_dat = "[D.name] [linked_imprinter.output_part_cost(D)]" + var/upTo=10 + for(var/M in D.materials) + var/num_units_avail=linked_imprinter.check_mat(D,M) + if(num_units_avail) + upTo = min(upTo, num_units_avail) + else + break + if (upTo) + dat += {"
    • [temp_dat] Queue: "} + if(upTo>=5) + dat += "(×5)" + if(upTo>=10) + dat += "(×10)" + dat += "(Custom)" + dat += "
    • " + else + dat += "
    • [temp_dat]
    • " + dat += "
    " + + if(4.2) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:869: dat += "Main Menu || " + dat += {"[CircuitImprinterHeader()] + Chemical Storage
    "} + // END AUTOFIX + for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:873: dat += "Name: [R.name] | Units: [R.volume] " + dat += {"Name: [R.name] | Units: [R.volume] + (Purge)
    + Disposal All Chemicals in Storage
    "} + // END AUTOFIX + if(4.3) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\rdconsole.dm:878: dat += "Main Menu || " + dat += {"[CircuitImprinterHeader()] + Material Storage
      "} + + + for(var/matID in linked_imprinter.materials.storage) + var/datum/material/M=linked_imprinter.materials.getMaterial(matID) + if(!(matID in linked_imprinter.allowed_materials)) + continue + dat += "
    • [linked_imprinter.materials.storage[matID]] cm3 of [M.processed_name]" + if(linked_imprinter.materials.storage[matID] >= M.cc_per_sheet) + dat += " - (1 Sheet) " + if(linked_imprinter.materials.storage[matID] >= (M.cc_per_sheet*5)) + dat += "(5 Sheets) " + dat += "(Max Sheets)" + else + dat += " - (Empty)" + dat += "
    • " + dat += "
    " + + if(4.4) //Imprinter Queue Management + dat += CircuitImprinterHeader()+"Production Queue

      " + for(var/i=1;i<=linked_imprinter.queue.len;i++) + var/datum/design/I=linked_imprinter.queue[i] + dat += "
    • Name: [I.name]" + if(linked_imprinter.stopped) + dat += "(Remove)
    • " + dat += "
    Remove All Queued Items
    " + if(linked_imprinter.stopped) + dat += "Start Production" + else + dat += "Stop Production" + + dat = list2text(dat) + user << browse("Research and Development Console
    [dat]", "window=rdconsole;size=575x400") + onclose(user, "rdconsole") + +/obj/machinery/computer/rdconsole/mommi + name = "MoMMI R&D Console" + id = 3 + req_access = list(access_tox) + circuit = "/obj/item/weapon/circuitboard/rdconsole/mommi" + +/obj/machinery/computer/rdconsole/robotics + name = "Robotics R&D Console" + id = 2 + req_one_access = list(access_robotics) + req_access=list() + circuit = "/obj/item/weapon/circuitboard/rdconsole/robotics" + +/obj/machinery/computer/rdconsole/mechanic + name = "Mechanics R&D Console" + id = 4 + req_one_access = list(access_mechanic) + req_access=list() + circuit = "/obj/item/weapon/circuitboard/rdconsole/mechanic" + +/obj/machinery/computer/rdconsole/core + name = "Core R&D Console" + id = 1 + req_access = list(access_tox) + circuit = "/obj/item/weapon/circuitboard/rdconsole" + +/obj/machinery/computer/rdconsole/pod + name = "Pod Bay R&D Console" + id = 5 + req_access=list() + circuit = "/obj/item/weapon/circuitboard/rdconsole/pod" diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index bd7991e1e4d..fd8d7d051ad 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -1,248 +1,248 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 -var/global/list/rnd_machines = list() -//All devices that link into the R&D console fall into thise type for easy identification and some shared procs. -/obj/machinery/r_n_d - name = "R&D Device" - icon = 'icons/obj/machines/research.dmi' - density = 1 - anchored = 1 - use_power = 1 - var/busy = 0 - var/hacked = 0 - var/disabled = 0 - var/shocked = 0 - var/obj/machinery/computer/rdconsole/linked_console - var/output_dir = 0 // Direction used to output to (for things like fabs), set to 0 for loc. - var/stopped = 0 - var/base_state = "" - var/build_time = 0 - - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - - var/nano_file = "" - - var/max_material_storage = 0 - var/list/allowed_materials[0] //list of material IDs we take, if we whitelist - - var/research_flags //see setup.dm for details of these - - var/datum/wires/rnd/wires = null - -/obj/machinery/r_n_d/New() - rnd_machines |= src - ..() - - wires = new(src) - - base_state = icon_state - icon_state_open = "[base_state]_t" - - if(research_flags & TAKESMATIN && !materials) - materials = getFromPool(/datum/materials, src) - - if(ticker) initialize() - -// Define initial output. -/obj/machinery/r_n_d/initialize() - ..() - if(research_flags &HASOUTPUT) - for(var/direction in cardinal) - if(locate(/obj/machinery/mineral/output, get_step(get_turf(src), direction))) - output_dir = direction - break - -/obj/machinery/r_n_d/Destroy() - if(linked_console) - linked_console.linked_machines -= src - linked_console = null - - rnd_machines -= src - wires = null - ..() - -/obj/machinery/r_n_d/process() - ..() - if(shocked>0) - shocked-- - -/obj/machinery/r_n_d/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - if(istype(mover) && mover.checkpass(PASSMACHINE)) - return 1 - return ..() - -/obj/machinery/r_n_d/update_icon() - overlays.len = 0 - if(linked_console) - overlays += "[base_state]_link" - -/obj/machinery/r_n_d/blob_act() - if (prob(50)) - qdel(src) - -/obj/machinery/r_n_d/attack_hand(mob/user as mob) - if (shocked) - shock(user,50) - if(panel_open) - wires.Interact(user) - else if (research_flags & NANOTOUCH) - ui_interact(user) - return - - -/obj/machinery/r_n_d/Topic(href, href_list) - if(..()) - return - if(href_list["close"]) - if(usr.machine == src) usr.unset_machine() - return 1 - usr.set_machine(src) - src.add_fingerprint(usr) - src.updateUsrDialog() - -//Called when the hack wire is toggled in some way -/obj/machinery/r_n_d/proc/update_hacked() - return - -/obj/machinery/r_n_d/togglePanelOpen(var/item/toggleitem, mob/user) - if(..()) - if (panel_open && linked_console) - linked_console.linked_machines -= src - switch(src.type) - if(/obj/machinery/r_n_d/fabricator/protolathe) - linked_console.linked_lathe = null - if(/obj/machinery/r_n_d/destructive_analyzer) - linked_console.linked_destroy = null - if(/obj/machinery/r_n_d/fabricator/circuit_imprinter) - linked_console.linked_imprinter = null - linked_console = null - overlays -= "[base_state]_link" - return 1 - -/obj/machinery/r_n_d/crowbarDestroy(mob/user) - if(..() == 1) - if (materials) - for(var/matID in materials.storage) - var/datum/material/M = materials.getMaterial(matID) - var/obj/item/stack/sheet/sheet = new M.sheettype(src.loc) - if(sheet) - var/available_num_sheets = round(materials.storage[matID]/sheet.perunit) - if(available_num_sheets>0) - sheet.amount = available_num_sheets - materials.removeAmount(matID, sheet.amount * sheet.perunit) - else - qdel(sheet) - return 1 - return -1 - -/obj/machinery/r_n_d/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (shocked) - shock(user,50) - if (busy) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 +var/global/list/rnd_machines = list() +//All devices that link into the R&D console fall into thise type for easy identification and some shared procs. +/obj/machinery/r_n_d + name = "R&D Device" + icon = 'icons/obj/machines/research.dmi' + density = 1 + anchored = 1 + use_power = 1 + var/busy = 0 + var/hacked = 0 + var/disabled = 0 + var/shocked = 0 + var/obj/machinery/computer/rdconsole/linked_console + var/output_dir = 0 // Direction used to output to (for things like fabs), set to 0 for loc. + var/stopped = 0 + var/base_state = "" + var/build_time = 0 + + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + + var/nano_file = "" + + var/max_material_storage = 0 + var/list/allowed_materials[0] //list of material IDs we take, if we whitelist + + var/research_flags //see setup.dm for details of these + + var/datum/wires/rnd/wires = null + +/obj/machinery/r_n_d/New() + rnd_machines |= src + ..() + + wires = new(src) + + base_state = icon_state + icon_state_open = "[base_state]_t" + + if(research_flags & TAKESMATIN && !materials) + materials = getFromPool(/datum/materials, src) + + if(ticker) initialize() + +// Define initial output. +/obj/machinery/r_n_d/initialize() + ..() + if(research_flags &HASOUTPUT) + for(var/direction in cardinal) + if(locate(/obj/machinery/mineral/output, get_step(get_turf(src), direction))) + output_dir = direction + break + +/obj/machinery/r_n_d/Destroy() + if(linked_console) + linked_console.linked_machines -= src + linked_console = null + + rnd_machines -= src + wires = null + ..() + +/obj/machinery/r_n_d/process() + ..() + if(shocked>0) + shocked-- + +/obj/machinery/r_n_d/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + if(istype(mover) && mover.checkpass(PASSMACHINE)) + return 1 + return ..() + +/obj/machinery/r_n_d/update_icon() + overlays.len = 0 + if(linked_console) + overlays += "[base_state]_link" + +/obj/machinery/r_n_d/blob_act() + if (prob(50)) + qdel(src) + +/obj/machinery/r_n_d/attack_hand(mob/user as mob) + if (shocked) + shock(user,50) + if(panel_open) + wires.Interact(user) + else if (research_flags & NANOTOUCH) + ui_interact(user) + return + + +/obj/machinery/r_n_d/Topic(href, href_list) + if(..()) + return + if(href_list["close"]) + if(usr.machine == src) usr.unset_machine() + return 1 + usr.set_machine(src) + src.add_fingerprint(usr) + src.updateUsrDialog() + +//Called when the hack wire is toggled in some way +/obj/machinery/r_n_d/proc/update_hacked() + return + +/obj/machinery/r_n_d/togglePanelOpen(var/item/toggleitem, mob/user) + if(..()) + if (panel_open && linked_console) + linked_console.linked_machines -= src + switch(src.type) + if(/obj/machinery/r_n_d/fabricator/protolathe) + linked_console.linked_lathe = null + if(/obj/machinery/r_n_d/destructive_analyzer) + linked_console.linked_destroy = null + if(/obj/machinery/r_n_d/fabricator/circuit_imprinter) + linked_console.linked_imprinter = null + linked_console = null + overlays -= "[base_state]_link" + return 1 + +/obj/machinery/r_n_d/crowbarDestroy(mob/user) + if(..() == 1) + if (materials) + for(var/matID in materials.storage) + var/datum/material/M = materials.getMaterial(matID) + var/obj/item/stack/sheet/sheet = new M.sheettype(src.loc) + if(sheet) + var/available_num_sheets = round(materials.storage[matID]/sheet.perunit) + if(available_num_sheets>0) + sheet.amount = available_num_sheets + materials.removeAmount(matID, sheet.amount * sheet.perunit) + else + qdel(sheet) + return 1 + return -1 + +/obj/machinery/r_n_d/attackby(var/obj/item/O as obj, var/mob/user as mob) + if (shocked) + shock(user,50) + if (busy) to_chat(user, "The [src.name] is busy. Please wait for completion of previous operation.") - return 1 - if( ..() ) - return 1 - if(panel_open) - wires.Interact(user) - return 1 - if (stat) - return 1 - if (disabled) - return 1 - if (istype(O, /obj/item/device/multitool)) - if(!panel_open && research_flags &HASOUTPUT) - var/result = input("Set your location as output?") in list("Yes","No","Machine Location") - switch(result) - if("Yes") - if(!Adjacent(user)) + return 1 + if( ..() ) + return 1 + if(panel_open) + wires.Interact(user) + return 1 + if (stat) + return 1 + if (disabled) + return 1 + if (istype(O, /obj/item/device/multitool)) + if(!panel_open && research_flags &HASOUTPUT) + var/result = input("Set your location as output?") in list("Yes","No","Machine Location") + switch(result) + if("Yes") + if(!Adjacent(user)) to_chat(user, "Cannot set this as the output location; You're not adjacent to it!") - return 1 - - output_dir = get_dir(src, user) + return 1 + + output_dir = get_dir(src, user) to_chat(user, "Output set.") - if("Machine Location") - output_dir = 0 + if("Machine Location") + output_dir = 0 to_chat(user, "Output set.") - return 1 - return - if (!linked_console && !(istype(src, /obj/machinery/r_n_d/fabricator))) //fabricators get a free pass because they aren't tied to a console + return 1 + return + if (!linked_console && !(istype(src, /obj/machinery/r_n_d/fabricator))) //fabricators get a free pass because they aren't tied to a console to_chat(user, "\The [src] must be linked to an R&D console first!") - return 1 - if(istype(O,/obj/item/stack/sheet) && research_flags &TAKESMATIN) - busy = 1 - - var/found = "" //the matID we're compatible with - for(var/matID in materials.storage) - var/datum/material/M = materials.getMaterial(matID) - if(M.sheettype==O.type) - found = matID - if(!found) - if(O.materials && research_flags &FAB_RECYCLER) - busy = 0 - return 0 //let the autolathe try to do it's thing - to_chat(user, "\The [src] rejects \the [O.name].") - busy = 0 - return 1 - if(allowed_materials && allowed_materials.len) - if(!(found in allowed_materials)) - if(O.materials && research_flags &FAB_RECYCLER) - busy = 0 - return 0 //let the autolathe try to do it's thing + return 1 + if(istype(O,/obj/item/stack/sheet) && research_flags &TAKESMATIN) + busy = 1 + + var/found = "" //the matID we're compatible with + for(var/matID in materials.storage) + var/datum/material/M = materials.getMaterial(matID) + if(M.sheettype==O.type) + found = matID + if(!found) + if(O.materials && research_flags &FAB_RECYCLER) + busy = 0 + return 0 //let the autolathe try to do it's thing + to_chat(user, "\The [src] rejects \the [O.name].") + busy = 0 + return 1 + if(allowed_materials && allowed_materials.len) + if(!(found in allowed_materials)) + if(O.materials && research_flags &FAB_RECYCLER) + busy = 0 + return 0 //let the autolathe try to do it's thing to_chat(user, "\The [src] rejects \the [O.name].") - busy = 0 - return 1 - - var/obj/item/stack/sheet/S = O - if (TotalMaterials() + S.perunit > max_material_storage) + busy = 0 + return 1 + + var/obj/item/stack/sheet/S = O + if (TotalMaterials() + S.perunit > max_material_storage) to_chat(user, "\The [src]'s material bin is full. Please remove material before adding more.") - busy = 0 - return 1 - - var/obj/item/stack/sheet/stack = O - var/amount = round(input("How many sheets do you want to add? (0 - [stack.amount])") as num)//No decimals - if(!O || !O.loc || O.loc != user) - busy = 0 - return - if(amount < 0)//No negative numbers - amount = 0 - if(amount == 0) - busy = 0 - return 1 //1 So the autolathe doesn't recycle the stack. - if(amount > stack.amount) - amount = stack.amount - if(max_material_storage - TotalMaterials() < (amount*stack.perunit))//Can't overfill - amount = min(stack.amount, round((max_material_storage-TotalMaterials())/stack.perunit)) - - if(research_flags & HASMAT_OVER) - update_icon() - overlays |= "[base_state]_[stack.name]" - spawn(10) - overlays -= "[base_state]_[stack.name]" - - icon_state = "[base_state]" - use_power(max(1000, (3750*amount/10))) - stack.use(amount) + busy = 0 + return 1 + + var/obj/item/stack/sheet/stack = O + var/amount = round(input("How many sheets do you want to add? (0 - [stack.amount])") as num)//No decimals + if(!O || !O.loc || O.loc != user) + busy = 0 + return + if(amount < 0)//No negative numbers + amount = 0 + if(amount == 0) + busy = 0 + return 1 //1 So the autolathe doesn't recycle the stack. + if(amount > stack.amount) + amount = stack.amount + if(max_material_storage - TotalMaterials() < (amount*stack.perunit))//Can't overfill + amount = min(stack.amount, round((max_material_storage-TotalMaterials())/stack.perunit)) + + if(research_flags & HASMAT_OVER) + update_icon() + overlays |= "[base_state]_[stack.name]" + spawn(10) + overlays -= "[base_state]_[stack.name]" + + icon_state = "[base_state]" + use_power(max(1000, (3750*amount/10))) + stack.use(amount) to_chat(user, "You add [amount] sheet[amount > 1 ? "s":""] to the [src.].") - icon_state = "[base_state]" - - var/datum/material/material = materials.getMaterial(found) - materials.addAmount(found, amount * material.cc_per_sheet) - busy = 0 - return 1 - src.updateUsrDialog() - return 0 - -/obj/machinery/r_n_d/proc/TotalMaterials() //returns the total of all the stored materials. Makes code neater. - if(materials) - return materials.getVolume() - return 0 - -// Returns the atom to output to. -// Yes this can potentially return null, however that shouldn't be an issue for the code that uses it. -/obj/machinery/r_n_d/proc/get_output() - if(!output_dir) - return get_turf(loc) - - . = get_step(get_turf(src), output_dir) - if(!.) - return loc // Map edge I guess. + icon_state = "[base_state]" + + var/datum/material/material = materials.getMaterial(found) + materials.addAmount(found, amount * material.cc_per_sheet) + busy = 0 + return 1 + src.updateUsrDialog() + return 0 + +/obj/machinery/r_n_d/proc/TotalMaterials() //returns the total of all the stored materials. Makes code neater. + if(materials) + return materials.getVolume() + return 0 + +// Returns the atom to output to. +// Yes this can potentially return null, however that shouldn't be an issue for the code that uses it. +/obj/machinery/r_n_d/proc/get_output() + if(!output_dir) + return get_turf(loc) + + . = get_step(get_turf(src), output_dir) + if(!.) + return loc // Map edge I guess. diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm index 69615c08ed3..90d66dafd89 100644 --- a/code/modules/research/research.dm +++ b/code/modules/research/research.dm @@ -1,318 +1,318 @@ -/* -General Explination: -The research datum is the "folder" where all the research information is stored in a R&D console. It's also a holder for all the -various procs used to manipulate it. It has four variables and seven procs: - -Variables: -- possible_tech is a list of all the /datum/tech that can potentially be researched by the player. The RefreshResearch() proc -(explained later) only goes through those when refreshing what you know. Generally, possible_tech contains ALL of the existing tech -but it is possible to add tech to the game that DON'T start in it (example: Xeno tech). Generally speaking, you don't want to mess -with these since they should be the default version of the datums. They're actually stored in a list rather then using typesof to -refer to them since it makes it a bit easier to search through them for specific information. -- know_tech is the companion list to possible_tech. It's the tech you can actually research and improve. Until it's added to this -list, it can't be improved. All the tech in this list are visible to the player. -- possible_designs is functionally identical to possbile_tech except it's for /datum/design. -- known_designs is functionally identical to known_tech except it's for /datum/design - -Procs: -- TechHasReqs: Used by other procs (specifically RefreshResearch) to see whether all of a tech's requirements are currently in -known_tech and at a high enough level. -- DesignHasReqs: Same as TechHasReqs but for /datum/design and known_design. -- AddTech2Known: Adds a /datum/tech to known_tech. It checks to see whether it already has that tech (if so, it just replaces it). If -it doesn't have it, it adds it. Note: It does NOT check possible_tech at all. So if you want to add something strange to it (like -a player made tech?) you can. -- AddDesign2Known: Same as AddTech2Known except for /datum/design and known_designs. -- RefreshResearch: This is the workhorse of the R&D system. It updates the /datum/research holder and adds any unlocked tech paths -and designs you have reached the requirements for. It only checks through possible_tech and possible_designs, however, so it won't -accidentally add "secret" tech to it. -- UpdateTech is used as part of the actual researching process. It takes an ID and finds techs with that same ID in known_tech. When -it finds it, it checks to see whether it can improve it at all. If the known_tech's level is less then or equal to -the inputted level, it increases the known tech's level to the inputted level -1 or know tech's level +1 (whichever is higher). - -The tech datums are the actual "tech trees" that you improve through researching. Each one has five variables: -- Name: Pretty obvious. This is often viewable to the players. -- Desc: Pretty obvious. Also player viewable. -- ID: This is the unique ID of the tech that is used by the various procs to find and/or maniuplate it. -- Level: This is the current level of the tech. All techs start at 1 and have a max of 20. Devices and some techs require a certain -level in specific techs before you can produce them. -- Req_tech: This is a list of the techs required to unlock this tech path. If left blank, it'll automatically be loaded into the -research holder datum. - -*/ -/*************************************************************** -** Master Types ** -** Includes all the helper procs and basic tech processing. ** -***************************************************************/ - -var/global/list/design_list = list() -var/global/list/tech_list = list() - -var/global/list/hidden_tech = list( - /datum/tech, - /datum/tech/nanotrasen, - ) - -/datum/research //Holder for all the existing, archived, and known tech. Individual to console. - var/list/known_tech = list() //List of locally known tech. - var/list/known_designs = list() //List of available designs (at base reliability). - -/datum/research/New() //Insert techs into possible_tech here. Known_tech automatically updated. - if(!tech_list.len) - for(var/T in typesof(/datum/tech) - hidden_tech) - tech_list += new T() - if(!design_list.len) - for(var/D in typesof(/datum/design) - /datum/design) - design_list += new D() - RefreshResearch() - - - -//Checks to see if tech has all the required pre-reqs. -//Input: datum/tech; Output: 0/1 (false/true) -/datum/research/proc/TechHasReqs(var/datum/tech/T) - if(T.req_tech.len == 0) - return 1 - var/matches = 0 - for(var/req in T.req_tech) - for(var/datum/tech/known in known_tech) - if((req == known.id) && (known.level >= T.req_tech[req])) - matches++ - break - if(matches == T.req_tech.len) - return 1 - else - return 0 - -//Checks to see if design has all the required pre-reqs. -//Input: datum/design; Output: 0/1 (false/true) -/datum/research/proc/DesignHasReqs(var/datum/design/D) - if(D.req_tech.len == 0) - return 1 - var/matches = 0 - var/list/k_tech = list() - for(var/datum/tech/known in known_tech) - k_tech[known.id] = known.level - for(var/req in D.req_tech) - if(!isnull(k_tech[req]) && k_tech[req] >= D.req_tech[req]) - matches++ - if(matches == D.req_tech.len) - return 1 - else - return 0 -/* -//Checks to see if design has all the required pre-reqs. -//Input: datum/design; Output: 0/1 (false/true) -/datum/research/proc/DesignHasReqs(var/datum/design/D) - if(D.req_tech.len == 0) - return 1 - var/matches = 0 - for(var/req in D.req_tech) - for(var/datum/tech/known in known_tech) - if((req == known.id) && (known.level >= D.req_tech[req])) - matches++ - break - if(matches == D.req_tech.len) - return 1 - else - return 0 -*/ -//Adds a tech to known_tech list. Checks to make sure there aren't duplicates and updates existing tech's levels if needed. -//Input: datum/tech; Output: Null -/datum/research/proc/AddTech2Known(var/datum/tech/T) - for(var/datum/tech/known in known_tech) - if(T.id == known.id) - if(T.level > known.level) - known.level = T.level - return 1 - known_tech += T - return 2 - -/datum/research/proc/AddDesign2Known(var/datum/design/D) - if(!(D in known_designs)) - for(var/datum/design/known in known_designs) - if(D.id == known.id) - if(D.reliability_mod > known.reliability_mod) - known.reliability_mod = D.reliability_mod - return - known_designs += D - return - -//Refreshes known_tech and known_designs list. Then updates the reliability vars of the designs in the known_designs list. -//Input/Output: n/a -/datum/research/proc/RefreshResearch() - for(var/datum/tech/PT in tech_list) - if(TechHasReqs(PT)) - AddTech2Known(PT) - for(var/datum/design/PD in design_list) - if(DesignHasReqs(PD)) - AddDesign2Known(PD) - for(var/datum/tech/T in known_tech) - T = Clamp(T.level, 1, 20) - for(var/datum/design/D in known_designs) - D.CalcReliability(known_tech) - return - -//Refreshes the levels of a given tech. -//Input: Tech's ID and Level; Output: null -/datum/research/proc/UpdateTech(var/ID, var/level) - for(var/datum/tech/KT in known_tech) - if(KT.id == ID) - if(KT.level <= level) KT.level = max((KT.level + 1), (level - 1)) - return - -/datum/research/proc/UpdateDesign(var/path) - for(var/datum/design/KD in known_designs) - if(KD.build_path == path) - KD.reliability_mod += rand(1,2) - break - return - -/*************************************************************** - ** Technology Datums ** - ** Includes all the various technoliges and what they make. ** - ***************************************************************/ - -datum/tech //Datum of individual technologies. - var/name = "name" //Name of the technology. - var/desc = "description" //General description of what it does and what it makes. - var/id = "id" //An easily referenced ID. Must be alphanumeric, lower-case, and no symbols. - var/level = 1 //A simple number scale of the research level. Level 0 = Secret tech. - var/max_level = 1 // Maximum level this can be at (for admin hax) - var/goal_level =-1 // Used for job objectives. Set to max_level unless max_level is unobtainable. - var/list/req_tech = list() //List of ids associated values of techs required to research this tech. "id" = # - var/new_category = null - -/datum/tech/New() - if(goal_level==-1) - goal_level=max_level - ..() - -//Trunk Technologies (don't require any other techs and you start knowning them). - -datum/tech/materials - name = "Materials Research" - desc = "Development of new and improved materials." - id = "materials" - max_level=9 - goal_level=8 // 9 is Phazon. - -datum/tech/engineering - name = "Engineering Research" - desc = "Development of new and improved engineering parts and." - id = "engineering" - max_level=5 - -datum/tech/plasmatech - name = "Plasma Research" - desc = "Research into the mysterious substance colloqually known as 'plasma'." - id = "plasmatech" - max_level=4 - -datum/tech/powerstorage - name = "Power Manipulation Technology" - desc = "The various technologies behind the storage and generation of electicity." - id = "powerstorage" - max_level=6 - -datum/tech/bluespace - name = "'Blue-space' Research" - desc = "Research into the sub-reality known as 'blue-space'" - id = "bluespace" - max_level =10 - goal_level=4 // Without phazon. - -datum/tech/biotech - name = "Biological Technology" - desc = "Research into the deeper mysteries of life and organic substances." - id = "biotech" - max_level=5 // Max USABLE level. - -datum/tech/combat - name = "Combat Systems Research" - desc = "The development of offensive and defensive systems." - id = "combat" - goal_level=5 // Pulse rifles don't count. - max_level=6 - -datum/tech/magnets - name = "Electromagnetic Spectrum Research" - desc = "Research into the electromagnetic spectrum. No clue how they actually work, though." - id = "magnets" - goal_level=5 // No phazon - max_level=8 - -datum/tech/programming - name = "Data Theory Research" - desc = "The development of new computer and artificial intelligence and data storage systems." - id = "programming" - max_level=5 - -datum/tech/syndicate - name = "Illegal Technologies Research" - desc = "The study of technologies that violate standard Nanotrasen regulations." - id = "syndicate" - goal_level=0 // Doesn't count towards maxed research, since it's illegal. - max_level=8 - -datum/tech/nanotrasen - name = "Nanotrasen Experimental Technologies" - desc = "The research of miscellaneous bleeding-edge technologies, sponsored by Nanotrasen." - id = "nanotrasen" - goal_level=0 // Doesn't count towards maxed research, since it's bonus. - max_level=8 - new_category = "Nanotrasen" - -/* -datum/tech/arcane - name = "Arcane Research" - desc = "Research into the occult and arcane field for use in practical science" - id = "arcane" - level = 0 //It didn't become "secret" as advertised. - -//Branch Techs -datum/tech/explosives - name = "Explosives Research" - desc = "The creation and application of explosive materials." - id = "explosives" - req_tech = list("materials" = 3) - -datum/tech/generators - name = "Power Generation Technology" - desc = "Research into more powerful and more reliable sources." - id = "generators" - req_tech = list("powerstorage" = 2) - -datum/tech/robotics - name = "Robotics Technology" - desc = "The development of advanced automated, autonomous machines." - id = "robotics" - req_tech = list("materials" = 3, "programming" = 3) -*/ - - -/obj/item/weapon/disk/tech_disk - name = "Technology Disk" - desc = "A disk for storing technology data for further research." - icon = 'icons/obj/cloning.dmi' - icon_state = "datadisk2" - item_state = "card-id" - w_class = 1.0 - starting_materials = list(MAT_IRON = 30, MAT_GLASS = 10) - w_type = RECYK_ELECTRONIC - var/datum/tech/stored - -/obj/item/weapon/disk/tech_disk/New() - ..() - src.pixel_x = rand(-5.0, 5) - src.pixel_y = rand(-5.0, 5) - -/obj/item/weapon/disk/tech_disk/nanotrasen - name = "Technology Disk (Nanotrasen 1)" - -/obj/item/weapon/disk/tech_disk/nanotrasen/New() - ..() - stored = new/datum/tech/nanotrasen(src) - -/obj/item/weapon/paper/tech_nanotrasen - name = "paper - 'Nanotrasen Experimental Technologies'" - info = "Thank you for participating in this Nanotrasen-sponsored initiative!

    This technology disk will open you the doors of Nanotrasen's most bleeding-edge experimental devices, and we look forward to you testing them for us! Also, note that you will still need to perform some research before these designs become available for you to print, but here's a guide to the tech levels that they will require.
    1. Hookshot: Materials=2, Engineering=5, Electromagnetic=2
    2. Ricochet Rifle: Materials=3, Power=3, Combat=3
    3. Gravity Well Gun: Materials=7, Bluespace=5, Electromagnetic=5

    We look forward to the results of your experiments. Depending on their success we might grant you access to even more bleeding-edge technologies in the future! Make Science proud!

    Central Command R&D Lab" +/* +General Explination: +The research datum is the "folder" where all the research information is stored in a R&D console. It's also a holder for all the +various procs used to manipulate it. It has four variables and seven procs: + +Variables: +- possible_tech is a list of all the /datum/tech that can potentially be researched by the player. The RefreshResearch() proc +(explained later) only goes through those when refreshing what you know. Generally, possible_tech contains ALL of the existing tech +but it is possible to add tech to the game that DON'T start in it (example: Xeno tech). Generally speaking, you don't want to mess +with these since they should be the default version of the datums. They're actually stored in a list rather then using typesof to +refer to them since it makes it a bit easier to search through them for specific information. +- know_tech is the companion list to possible_tech. It's the tech you can actually research and improve. Until it's added to this +list, it can't be improved. All the tech in this list are visible to the player. +- possible_designs is functionally identical to possbile_tech except it's for /datum/design. +- known_designs is functionally identical to known_tech except it's for /datum/design + +Procs: +- TechHasReqs: Used by other procs (specifically RefreshResearch) to see whether all of a tech's requirements are currently in +known_tech and at a high enough level. +- DesignHasReqs: Same as TechHasReqs but for /datum/design and known_design. +- AddTech2Known: Adds a /datum/tech to known_tech. It checks to see whether it already has that tech (if so, it just replaces it). If +it doesn't have it, it adds it. Note: It does NOT check possible_tech at all. So if you want to add something strange to it (like +a player made tech?) you can. +- AddDesign2Known: Same as AddTech2Known except for /datum/design and known_designs. +- RefreshResearch: This is the workhorse of the R&D system. It updates the /datum/research holder and adds any unlocked tech paths +and designs you have reached the requirements for. It only checks through possible_tech and possible_designs, however, so it won't +accidentally add "secret" tech to it. +- UpdateTech is used as part of the actual researching process. It takes an ID and finds techs with that same ID in known_tech. When +it finds it, it checks to see whether it can improve it at all. If the known_tech's level is less then or equal to +the inputted level, it increases the known tech's level to the inputted level -1 or know tech's level +1 (whichever is higher). + +The tech datums are the actual "tech trees" that you improve through researching. Each one has five variables: +- Name: Pretty obvious. This is often viewable to the players. +- Desc: Pretty obvious. Also player viewable. +- ID: This is the unique ID of the tech that is used by the various procs to find and/or maniuplate it. +- Level: This is the current level of the tech. All techs start at 1 and have a max of 20. Devices and some techs require a certain +level in specific techs before you can produce them. +- Req_tech: This is a list of the techs required to unlock this tech path. If left blank, it'll automatically be loaded into the +research holder datum. + +*/ +/*************************************************************** +** Master Types ** +** Includes all the helper procs and basic tech processing. ** +***************************************************************/ + +var/global/list/design_list = list() +var/global/list/tech_list = list() + +var/global/list/hidden_tech = list( + /datum/tech, + /datum/tech/nanotrasen, + ) + +/datum/research //Holder for all the existing, archived, and known tech. Individual to console. + var/list/known_tech = list() //List of locally known tech. + var/list/known_designs = list() //List of available designs (at base reliability). + +/datum/research/New() //Insert techs into possible_tech here. Known_tech automatically updated. + if(!tech_list.len) + for(var/T in typesof(/datum/tech) - hidden_tech) + tech_list += new T() + if(!design_list.len) + for(var/D in typesof(/datum/design) - /datum/design) + design_list += new D() + RefreshResearch() + + + +//Checks to see if tech has all the required pre-reqs. +//Input: datum/tech; Output: 0/1 (false/true) +/datum/research/proc/TechHasReqs(var/datum/tech/T) + if(T.req_tech.len == 0) + return 1 + var/matches = 0 + for(var/req in T.req_tech) + for(var/datum/tech/known in known_tech) + if((req == known.id) && (known.level >= T.req_tech[req])) + matches++ + break + if(matches == T.req_tech.len) + return 1 + else + return 0 + +//Checks to see if design has all the required pre-reqs. +//Input: datum/design; Output: 0/1 (false/true) +/datum/research/proc/DesignHasReqs(var/datum/design/D) + if(D.req_tech.len == 0) + return 1 + var/matches = 0 + var/list/k_tech = list() + for(var/datum/tech/known in known_tech) + k_tech[known.id] = known.level + for(var/req in D.req_tech) + if(!isnull(k_tech[req]) && k_tech[req] >= D.req_tech[req]) + matches++ + if(matches == D.req_tech.len) + return 1 + else + return 0 +/* +//Checks to see if design has all the required pre-reqs. +//Input: datum/design; Output: 0/1 (false/true) +/datum/research/proc/DesignHasReqs(var/datum/design/D) + if(D.req_tech.len == 0) + return 1 + var/matches = 0 + for(var/req in D.req_tech) + for(var/datum/tech/known in known_tech) + if((req == known.id) && (known.level >= D.req_tech[req])) + matches++ + break + if(matches == D.req_tech.len) + return 1 + else + return 0 +*/ +//Adds a tech to known_tech list. Checks to make sure there aren't duplicates and updates existing tech's levels if needed. +//Input: datum/tech; Output: Null +/datum/research/proc/AddTech2Known(var/datum/tech/T) + for(var/datum/tech/known in known_tech) + if(T.id == known.id) + if(T.level > known.level) + known.level = T.level + return 1 + known_tech += T + return 2 + +/datum/research/proc/AddDesign2Known(var/datum/design/D) + if(!(D in known_designs)) + for(var/datum/design/known in known_designs) + if(D.id == known.id) + if(D.reliability_mod > known.reliability_mod) + known.reliability_mod = D.reliability_mod + return + known_designs += D + return + +//Refreshes known_tech and known_designs list. Then updates the reliability vars of the designs in the known_designs list. +//Input/Output: n/a +/datum/research/proc/RefreshResearch() + for(var/datum/tech/PT in tech_list) + if(TechHasReqs(PT)) + AddTech2Known(PT) + for(var/datum/design/PD in design_list) + if(DesignHasReqs(PD)) + AddDesign2Known(PD) + for(var/datum/tech/T in known_tech) + T = Clamp(T.level, 1, 20) + for(var/datum/design/D in known_designs) + D.CalcReliability(known_tech) + return + +//Refreshes the levels of a given tech. +//Input: Tech's ID and Level; Output: null +/datum/research/proc/UpdateTech(var/ID, var/level) + for(var/datum/tech/KT in known_tech) + if(KT.id == ID) + if(KT.level <= level) KT.level = max((KT.level + 1), (level - 1)) + return + +/datum/research/proc/UpdateDesign(var/path) + for(var/datum/design/KD in known_designs) + if(KD.build_path == path) + KD.reliability_mod += rand(1,2) + break + return + +/*************************************************************** + ** Technology Datums ** + ** Includes all the various technoliges and what they make. ** + ***************************************************************/ + +datum/tech //Datum of individual technologies. + var/name = "name" //Name of the technology. + var/desc = "description" //General description of what it does and what it makes. + var/id = "id" //An easily referenced ID. Must be alphanumeric, lower-case, and no symbols. + var/level = 1 //A simple number scale of the research level. Level 0 = Secret tech. + var/max_level = 1 // Maximum level this can be at (for admin hax) + var/goal_level =-1 // Used for job objectives. Set to max_level unless max_level is unobtainable. + var/list/req_tech = list() //List of ids associated values of techs required to research this tech. "id" = # + var/new_category = null + +/datum/tech/New() + if(goal_level==-1) + goal_level=max_level + ..() + +//Trunk Technologies (don't require any other techs and you start knowning them). + +datum/tech/materials + name = "Materials Research" + desc = "Development of new and improved materials." + id = "materials" + max_level=9 + goal_level=8 // 9 is Phazon. + +datum/tech/engineering + name = "Engineering Research" + desc = "Development of new and improved engineering parts and." + id = "engineering" + max_level=5 + +datum/tech/plasmatech + name = "Plasma Research" + desc = "Research into the mysterious substance colloqually known as 'plasma'." + id = "plasmatech" + max_level=4 + +datum/tech/powerstorage + name = "Power Manipulation Technology" + desc = "The various technologies behind the storage and generation of electicity." + id = "powerstorage" + max_level=6 + +datum/tech/bluespace + name = "'Blue-space' Research" + desc = "Research into the sub-reality known as 'blue-space'" + id = "bluespace" + max_level =10 + goal_level=4 // Without phazon. + +datum/tech/biotech + name = "Biological Technology" + desc = "Research into the deeper mysteries of life and organic substances." + id = "biotech" + max_level=5 // Max USABLE level. + +datum/tech/combat + name = "Combat Systems Research" + desc = "The development of offensive and defensive systems." + id = "combat" + goal_level=5 // Pulse rifles don't count. + max_level=6 + +datum/tech/magnets + name = "Electromagnetic Spectrum Research" + desc = "Research into the electromagnetic spectrum. No clue how they actually work, though." + id = "magnets" + goal_level=5 // No phazon + max_level=8 + +datum/tech/programming + name = "Data Theory Research" + desc = "The development of new computer and artificial intelligence and data storage systems." + id = "programming" + max_level=5 + +datum/tech/syndicate + name = "Illegal Technologies Research" + desc = "The study of technologies that violate standard Nanotrasen regulations." + id = "syndicate" + goal_level=0 // Doesn't count towards maxed research, since it's illegal. + max_level=8 + +datum/tech/nanotrasen + name = "Nanotrasen Experimental Technologies" + desc = "The research of miscellaneous bleeding-edge technologies, sponsored by Nanotrasen." + id = "nanotrasen" + goal_level=0 // Doesn't count towards maxed research, since it's bonus. + max_level=8 + new_category = "Nanotrasen" + +/* +datum/tech/arcane + name = "Arcane Research" + desc = "Research into the occult and arcane field for use in practical science" + id = "arcane" + level = 0 //It didn't become "secret" as advertised. + +//Branch Techs +datum/tech/explosives + name = "Explosives Research" + desc = "The creation and application of explosive materials." + id = "explosives" + req_tech = list("materials" = 3) + +datum/tech/generators + name = "Power Generation Technology" + desc = "Research into more powerful and more reliable sources." + id = "generators" + req_tech = list("powerstorage" = 2) + +datum/tech/robotics + name = "Robotics Technology" + desc = "The development of advanced automated, autonomous machines." + id = "robotics" + req_tech = list("materials" = 3, "programming" = 3) +*/ + + +/obj/item/weapon/disk/tech_disk + name = "Technology Disk" + desc = "A disk for storing technology data for further research." + icon = 'icons/obj/cloning.dmi' + icon_state = "datadisk2" + item_state = "card-id" + w_class = 1.0 + starting_materials = list(MAT_IRON = 30, MAT_GLASS = 10) + w_type = RECYK_ELECTRONIC + var/datum/tech/stored + +/obj/item/weapon/disk/tech_disk/New() + ..() + src.pixel_x = rand(-5.0, 5) + src.pixel_y = rand(-5.0, 5) + +/obj/item/weapon/disk/tech_disk/nanotrasen + name = "Technology Disk (Nanotrasen 1)" + +/obj/item/weapon/disk/tech_disk/nanotrasen/New() + ..() + stored = new/datum/tech/nanotrasen(src) + +/obj/item/weapon/paper/tech_nanotrasen + name = "paper - 'Nanotrasen Experimental Technologies'" + info = "Thank you for participating in this Nanotrasen-sponsored initiative!

    This technology disk will open you the doors of Nanotrasen's most bleeding-edge experimental devices, and we look forward to you testing them for us! Also, note that you will still need to perform some research before these designs become available for you to print, but here's a guide to the tech levels that they will require.
    1. Hookshot: Materials=2, Engineering=5, Electromagnetic=2
    2. Ricochet Rifle: Materials=3, Power=3, Combat=3
    3. Gravity Well Gun: Materials=7, Bluespace=5, Electromagnetic=5

    We look forward to the results of your experiments. Depending on their success we might grant you access to even more bleeding-edge technologies in the future! Make Science proud!

    Central Command R&D Lab" diff --git a/code/modules/research/research_shuttle.dm b/code/modules/research/research_shuttle.dm index 421d98f3f94..52d60452a74 100644 --- a/code/modules/research/research_shuttle.dm +++ b/code/modules/research/research_shuttle.dm @@ -1,121 +1,121 @@ - -/**********************Shuttle Computer**************************/ - -//copy paste from the mining shuttle - -var/research_shuttle_tickstomove = 10 -var/research_shuttle_moving = 0 -var/research_shuttle_location = 0 // 0 = station 13, 1 = research station - -proc/move_research_shuttle() - if(research_shuttle_moving) return - research_shuttle_moving = 1 - spawn(research_shuttle_tickstomove*10) - var/area/fromArea - var/area/toArea - if (research_shuttle_location == 1) - fromArea = locate(/area/shuttle/research/outpost) - toArea = locate(/area/shuttle/research/station) - else - fromArea = locate(/area/shuttle/research/station) - toArea = locate(/area/shuttle/research/outpost) - var/list/search = fromArea.search_contents_for(/obj/item/weapon/disk/nuclear) - if(!isemptylist(search)) - research_shuttle_moving = 0 - return - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in toArea) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - - if(istype(T, /turf/simulated)) - qdel(T) - //Do I really need to explain this loop? - for(var/atom/A in toArea) - if(istype(A,/mob/living)) - var/mob/living/unlucky_person = A - unlucky_person.gib() - // Weird things happen when this shit gets in the way. - if(istype(A,/obj/structure/lattice) \ - || istype(A, /obj/structure/window) \ - || istype(A, /obj/structure/grille)) - qdel(A) - - fromArea.move_contents_to(toArea) - if (research_shuttle_location) - research_shuttle_location = 0 - else - research_shuttle_location = 1 - - for(var/mob/M in toArea) - if(M.client) - spawn(0) - if(M.locked_to) - shake_camera(M, 3, 1) // locked_to, not a lot of shaking - else - shake_camera(M, 10, 1) // unlocked_to, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.locked_to) - M.Weaken(3) - - research_shuttle_moving = 0 - return - -/obj/machinery/computer/research_shuttle - name = "Research Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_research) - circuit = "/obj/item/weapon/circuitboard/research_shuttle" - var/location = 0 //0 = station, 1 = research base - machine_flags = EMAGGABLE | SCREWTOGGLE - light_color = LIGHT_COLOR_CYAN - -/obj/machinery/computer/research_shuttle/attack_hand(user as mob) - if(..(user)) - return - src.add_fingerprint(usr) - var/dat = "
    Research shuttle:
    Send
    " - user << browse("[dat]", "window=researchshuttle;size=200x100") - -/obj/machinery/computer/research_shuttle/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(!src.allowed(usr)) + +/**********************Shuttle Computer**************************/ + +//copy paste from the mining shuttle + +var/research_shuttle_tickstomove = 10 +var/research_shuttle_moving = 0 +var/research_shuttle_location = 0 // 0 = station 13, 1 = research station + +proc/move_research_shuttle() + if(research_shuttle_moving) return + research_shuttle_moving = 1 + spawn(research_shuttle_tickstomove*10) + var/area/fromArea + var/area/toArea + if (research_shuttle_location == 1) + fromArea = locate(/area/shuttle/research/outpost) + toArea = locate(/area/shuttle/research/station) + else + fromArea = locate(/area/shuttle/research/station) + toArea = locate(/area/shuttle/research/outpost) + var/list/search = fromArea.search_contents_for(/obj/item/weapon/disk/nuclear) + if(!isemptylist(search)) + research_shuttle_moving = 0 + return + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in toArea) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + + if(istype(T, /turf/simulated)) + qdel(T) + //Do I really need to explain this loop? + for(var/atom/A in toArea) + if(istype(A,/mob/living)) + var/mob/living/unlucky_person = A + unlucky_person.gib() + // Weird things happen when this shit gets in the way. + if(istype(A,/obj/structure/lattice) \ + || istype(A, /obj/structure/window) \ + || istype(A, /obj/structure/grille)) + qdel(A) + + fromArea.move_contents_to(toArea) + if (research_shuttle_location) + research_shuttle_location = 0 + else + research_shuttle_location = 1 + + for(var/mob/M in toArea) + if(M.client) + spawn(0) + if(M.locked_to) + shake_camera(M, 3, 1) // locked_to, not a lot of shaking + else + shake_camera(M, 10, 1) // unlocked_to, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.locked_to) + M.Weaken(3) + + research_shuttle_moving = 0 + return + +/obj/machinery/computer/research_shuttle + name = "Research Shuttle Console" + icon = 'icons/obj/computer.dmi' + icon_state = "shuttle" + req_access = list(access_research) + circuit = "/obj/item/weapon/circuitboard/research_shuttle" + var/location = 0 //0 = station, 1 = research base + machine_flags = EMAGGABLE | SCREWTOGGLE + light_color = LIGHT_COLOR_CYAN + +/obj/machinery/computer/research_shuttle/attack_hand(user as mob) + if(..(user)) + return + src.add_fingerprint(usr) + var/dat = "
    Research shuttle:
    Send
    " + user << browse("[dat]", "window=researchshuttle;size=200x100") + +/obj/machinery/computer/research_shuttle/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if(!src.allowed(usr)) to_chat(usr, "Unauthorized Access.") - return - if(href_list["move"]) - if(ticker.mode.name == "blob") - if(ticker.mode:declared) + return + if(href_list["move"]) + if(ticker.mode.name == "blob") + if(ticker.mode:declared) to_chat(usr, "Under directive 7-10, [station_name()] is quarantined until further notice.") - return - var/area/A = locate(/area/shuttle/research/station) - if(!research_shuttle_location) - var/list/search = A.search_contents_for(/obj/item/weapon/disk/nuclear) - if(!isemptylist(search)) + return + var/area/A = locate(/area/shuttle/research/station) + if(!research_shuttle_location) + var/list/search = A.search_contents_for(/obj/item/weapon/disk/nuclear) + if(!isemptylist(search)) to_chat(usr, "The nuclear disk is too precious for Nanotrasen to send it to an Asteroid.") - return - if (!research_shuttle_moving) + return + if (!research_shuttle_moving) to_chat(usr, "Shuttle recieved message and will be sent shortly.") - move_research_shuttle() - else + move_research_shuttle() + else to_chat(usr, "Shuttle is already moving.") - -/obj/machinery/computer/research_shuttle/emag(mob/user as mob) - ..() - src.req_access = list() + +/obj/machinery/computer/research_shuttle/emag(mob/user as mob) + ..() + src.req_access = list() to_chat(usr, "You disable the console's access requirement.") diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index d0dc1e33a5f..1959449338b 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -1,374 +1,374 @@ -/obj/machinery/r_n_d/server - name = "R&D Server" - icon = 'icons/obj/machines/research.dmi' - icon_state = "server" - var/datum/research/files - var/health = 100 - var/list/id_with_upload = list() //List of R&D consoles with upload to server access. - var/list/id_with_download = list() //List of R&D consoles with download from server access. - var/id_with_upload_string = "" //String versions for easy editing in map editor. - var/id_with_download_string = "" - var/server_id = 0 - var/heat_gen = 100 - var/heating_power = 40000 - var/delay = 10 - req_access = list(access_rd) //Only the R&D can change server settings. - -/obj/machinery/r_n_d/server/New() - . = ..() - - component_parts = newlist( - /obj/item/weapon/circuitboard/rdserver, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/capacitor - ) - - RefreshParts() - src.initialize(); //Agouri - -/obj/machinery/r_n_d/server/Destroy() - griefProtection() - ..() - -/obj/machinery/r_n_d/server/RefreshParts() - var/tot_rating = 0 - for(var/obj/item/weapon/stock_parts/SP in src) - tot_rating += SP.rating - heat_gen /= max(1, tot_rating) - -/obj/machinery/r_n_d/server/initialize() - if(!files) files = new /datum/research(src) - var/list/temp_list - if(!id_with_upload.len) - temp_list = list() - temp_list = text2list(id_with_upload_string, ";") - for(var/N in temp_list) - id_with_upload += text2num(N) - if(!id_with_download.len) - temp_list = list() - temp_list = text2list(id_with_download_string, ";") - for(var/N in temp_list) - id_with_download += text2num(N) - -/obj/machinery/r_n_d/server/process() - var/datum/gas_mixture/environment = loc.return_air() - switch(environment.temperature) - if(0 to T0C) - health = min(100, health + 1) - if(T0C to (T20C + 20)) - health = Clamp(health, 0, 100) - if((T20C + 20) to INFINITY) - health = max(0, health - 1) - if(health <= 0) - griefProtection() //I dont like putting this in process() but it's the best I can do without re-writing a chunk of rd servers. - files.known_designs = list() - var/changed=0 - for(var/datum/tech/T in files.known_tech) - if(prob(1)) - T.level = 0 // This never happens, so make it dramatic. T.level-- - changed=1 - if(changed) - files.RefreshResearch() - if(delay) - delay-- - else - produce_heat(heat_gen) - delay = initial(delay) - -/obj/machinery/r_n_d/server/emp_act(severity) - griefProtection() - ..() - - -/obj/machinery/r_n_d/server/ex_act(severity) - griefProtection() - ..() - - -/obj/machinery/r_n_d/server/blob_act() - griefProtection() - ..() - - - -//Backup files to centcomm to help admins recover data after greifer attacks -/obj/machinery/r_n_d/server/proc/griefProtection() - for(var/obj/machinery/r_n_d/server/centcom/C in machines) - for(var/datum/tech/T in files.known_tech) - C.files.AddTech2Known(T) - for(var/datum/design/D in files.known_designs) - C.files.AddDesign2Known(D) - C.files.RefreshResearch() - -/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt) - if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater. - var/turf/simulated/L = loc - if(istype(L)) - var/datum/gas_mixture/env = L.return_air() - if(env.temperature < (heat_amt+T0C)) - - var/transfer_moles = 0.25 * env.total_moles() - - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - if(removed) - - var/heat_capacity = removed.heat_capacity() - if(heat_capacity == 0 || heat_capacity == null) - heat_capacity = 1 - removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000) - - env.merge(removed) - -/obj/machinery/r_n_d/server/attack_hand(mob/user as mob) - if (disabled) - return - if (shocked) - shock(user,50) - -/obj/machinery/r_n_d/server/centcom - name = "Centcom Central R&D Database" - server_id = -1 - -/obj/machinery/r_n_d/server/centcom/initialize() - ..() - var/list/no_id_servers = list() - var/list/server_ids = list() - for(var/obj/machinery/r_n_d/server/S in machines) - switch(S.server_id) - if(-1) - continue - if(0) - no_id_servers += S - else - server_ids += S.server_id - - for(var/obj/machinery/r_n_d/server/S in no_id_servers) - var/num = 1 - while(!S.server_id) - if(num in server_ids) - num++ - else - S.server_id = num - server_ids += num - no_id_servers -= S - -/obj/machinery/r_n_d/server/centcom/process() - return PROCESS_KILL //don't need process() - - -/obj/machinery/computer/rdservercontrol - name = "R&D Server Controller" - icon_state = "rdcomp" - var/screen = 0 - var/obj/machinery/r_n_d/server/temp_server - var/list/servers = list() - var/list/consoles = list() - var/badmin = 0 - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/rdservercontrol/Topic(href, href_list) - if(..()) - return - - add_fingerprint(usr) - usr.set_machine(src) - if(!src.allowed(usr) && !emagged) +/obj/machinery/r_n_d/server + name = "R&D Server" + icon = 'icons/obj/machines/research.dmi' + icon_state = "server" + var/datum/research/files + var/health = 100 + var/list/id_with_upload = list() //List of R&D consoles with upload to server access. + var/list/id_with_download = list() //List of R&D consoles with download from server access. + var/id_with_upload_string = "" //String versions for easy editing in map editor. + var/id_with_download_string = "" + var/server_id = 0 + var/heat_gen = 100 + var/heating_power = 40000 + var/delay = 10 + req_access = list(access_rd) //Only the R&D can change server settings. + +/obj/machinery/r_n_d/server/New() + . = ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/rdserver, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor + ) + + RefreshParts() + src.initialize(); //Agouri + +/obj/machinery/r_n_d/server/Destroy() + griefProtection() + ..() + +/obj/machinery/r_n_d/server/RefreshParts() + var/tot_rating = 0 + for(var/obj/item/weapon/stock_parts/SP in src) + tot_rating += SP.rating + heat_gen /= max(1, tot_rating) + +/obj/machinery/r_n_d/server/initialize() + if(!files) files = new /datum/research(src) + var/list/temp_list + if(!id_with_upload.len) + temp_list = list() + temp_list = text2list(id_with_upload_string, ";") + for(var/N in temp_list) + id_with_upload += text2num(N) + if(!id_with_download.len) + temp_list = list() + temp_list = text2list(id_with_download_string, ";") + for(var/N in temp_list) + id_with_download += text2num(N) + +/obj/machinery/r_n_d/server/process() + var/datum/gas_mixture/environment = loc.return_air() + switch(environment.temperature) + if(0 to T0C) + health = min(100, health + 1) + if(T0C to (T20C + 20)) + health = Clamp(health, 0, 100) + if((T20C + 20) to INFINITY) + health = max(0, health - 1) + if(health <= 0) + griefProtection() //I dont like putting this in process() but it's the best I can do without re-writing a chunk of rd servers. + files.known_designs = list() + var/changed=0 + for(var/datum/tech/T in files.known_tech) + if(prob(1)) + T.level = 0 // This never happens, so make it dramatic. T.level-- + changed=1 + if(changed) + files.RefreshResearch() + if(delay) + delay-- + else + produce_heat(heat_gen) + delay = initial(delay) + +/obj/machinery/r_n_d/server/emp_act(severity) + griefProtection() + ..() + + +/obj/machinery/r_n_d/server/ex_act(severity) + griefProtection() + ..() + + +/obj/machinery/r_n_d/server/blob_act() + griefProtection() + ..() + + + +//Backup files to centcomm to help admins recover data after greifer attacks +/obj/machinery/r_n_d/server/proc/griefProtection() + for(var/obj/machinery/r_n_d/server/centcom/C in machines) + for(var/datum/tech/T in files.known_tech) + C.files.AddTech2Known(T) + for(var/datum/design/D in files.known_designs) + C.files.AddDesign2Known(D) + C.files.RefreshResearch() + +/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt) + if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater. + var/turf/simulated/L = loc + if(istype(L)) + var/datum/gas_mixture/env = L.return_air() + if(env.temperature < (heat_amt+T0C)) + + var/transfer_moles = 0.25 * env.total_moles() + + var/datum/gas_mixture/removed = env.remove(transfer_moles) + + if(removed) + + var/heat_capacity = removed.heat_capacity() + if(heat_capacity == 0 || heat_capacity == null) + heat_capacity = 1 + removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000) + + env.merge(removed) + +/obj/machinery/r_n_d/server/attack_hand(mob/user as mob) + if (disabled) + return + if (shocked) + shock(user,50) + +/obj/machinery/r_n_d/server/centcom + name = "Centcom Central R&D Database" + server_id = -1 + +/obj/machinery/r_n_d/server/centcom/initialize() + ..() + var/list/no_id_servers = list() + var/list/server_ids = list() + for(var/obj/machinery/r_n_d/server/S in machines) + switch(S.server_id) + if(-1) + continue + if(0) + no_id_servers += S + else + server_ids += S.server_id + + for(var/obj/machinery/r_n_d/server/S in no_id_servers) + var/num = 1 + while(!S.server_id) + if(num in server_ids) + num++ + else + S.server_id = num + server_ids += num + no_id_servers -= S + +/obj/machinery/r_n_d/server/centcom/process() + return PROCESS_KILL //don't need process() + + +/obj/machinery/computer/rdservercontrol + name = "R&D Server Controller" + icon_state = "rdcomp" + var/screen = 0 + var/obj/machinery/r_n_d/server/temp_server + var/list/servers = list() + var/list/consoles = list() + var/badmin = 0 + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/rdservercontrol/Topic(href, href_list) + if(..()) + return + + add_fingerprint(usr) + usr.set_machine(src) + if(!src.allowed(usr) && !emagged) to_chat(usr, "You do not have the required access level") - return - - if(href_list["main"]) - screen = 0 - - else if(href_list["access"] || href_list["data"] || href_list["transfer"]) - temp_server = null - consoles = list() - servers = list() - for(var/obj/machinery/r_n_d/server/S in machines) - if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"])) - temp_server = S - break - if(href_list["access"]) - screen = 1 - for(var/obj/machinery/computer/rdconsole/C in machines) - if(C.sync) - consoles += C - else if(href_list["data"]) - screen = 2 - else if(href_list["transfer"]) - screen = 3 - for(var/obj/machinery/r_n_d/server/S in machines) - if(S == src) - continue - servers += S - - else if(href_list["upload_toggle"]) - var/num = text2num(href_list["upload_toggle"]) - if(num in temp_server.id_with_upload) - temp_server.id_with_upload -= num - else - temp_server.id_with_upload += num - - else if(href_list["download_toggle"]) - var/num = text2num(href_list["download_toggle"]) - if(num in temp_server.id_with_download) - temp_server.id_with_download -= num - else - temp_server.id_with_download += num - - else if(href_list["reset_tech"]) - var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel") - if(choice == "Continue") - for(var/datum/tech/T in temp_server.files.known_tech) - if(T.id == href_list["reset_tech"]) - T.level = 1 - break - temp_server.files.RefreshResearch() - - else if(href_list["reset_design"]) - var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel") - if(choice == "Continue") - for(var/datum/design/D in temp_server.files.known_designs) - if(D.id == href_list["reset_design"]) - D.reliability_mod = 0 - temp_server.files.known_designs -= D - break - temp_server.files.RefreshResearch() - - updateUsrDialog() - return - -/obj/machinery/computer/rdservercontrol/attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/dat = "" - - switch(screen) - if(0) //Main Menu - dat += "Connected Servers:

    " - - for(var/obj/machinery/r_n_d/server/S in machines) - if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin) - continue - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:289: dat += "[S.name] || " - dat += {"[S.name] || - Access Rights | - Data Management"} - // END AUTOFIX - if(badmin) dat += " | Server-to-Server Transfer" - dat += "
    " - - if(1) //Access rights menu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:296: dat += "[temp_server.name] Access Rights

    " - dat += {"[temp_server.name] Access Rights

    - Consoles with Upload Access
    "} - // END AUTOFIX - for(var/obj/machinery/computer/rdconsole/C in consoles) - var/turf/console_turf = get_turf(C) - dat += "* [console_turf.loc]" //FYI, these are all numeric ids, eventually. - if(C.id in temp_server.id_with_upload) - dat += " (Remove)
    " - else - dat += " (Add)
    " - dat += "Consoles with Download Access
    " - for(var/obj/machinery/computer/rdconsole/C in consoles) - var/turf/console_turf = get_turf(C) - dat += "* [console_turf.loc]" - if(C.id in temp_server.id_with_download) - dat += " (Remove)
    " - else - dat += " (Add)
    " - dat += "
    Main Menu" - - if(2) //Data Management menu - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:316: dat += "[temp_server.name] Data ManagementP

    " - dat += {"[temp_server.name] Data Management

    - Known Technologies
    "} - // END AUTOFIX - for(var/datum/tech/T in temp_server.files.known_tech) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:319: dat += "* [T.name] " - dat += {"* [T.name] - (Reset)
    "} //FYI, these are all strings - // END AUTOFIX - dat += "Known Designs
    " - for(var/datum/design/D in temp_server.files.known_designs) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:323: dat += "* [D.name] " - dat += {"* [D.name] - (Delete)
    "} - // END AUTOFIX - dat += "
    Main Menu" - - if(3) //Server Data Transfer - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:328: dat += "[temp_server.name] Server to Server Transfer

    " - dat += {"[temp_server.name] Server to Server Transfer

    - Send Data to what server?
    "} - // END AUTOFIX - for(var/obj/machinery/r_n_d/server/S in servers) - dat += "[S.name] (Transfer)
    " - dat += "
    Main Menu" - user << browse("R&D Server Control
    [dat]", "window=server_control;size=575x400") - onclose(user, "server_control") - return - -/obj/machinery/computer/rdservercontrol/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) - if(istype(D, /obj/item/weapon/screwdriver)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 20)) - if (src.stat & BROKEN) + return + + if(href_list["main"]) + screen = 0 + + else if(href_list["access"] || href_list["data"] || href_list["transfer"]) + temp_server = null + consoles = list() + servers = list() + for(var/obj/machinery/r_n_d/server/S in machines) + if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"])) + temp_server = S + break + if(href_list["access"]) + screen = 1 + for(var/obj/machinery/computer/rdconsole/C in machines) + if(C.sync) + consoles += C + else if(href_list["data"]) + screen = 2 + else if(href_list["transfer"]) + screen = 3 + for(var/obj/machinery/r_n_d/server/S in machines) + if(S == src) + continue + servers += S + + else if(href_list["upload_toggle"]) + var/num = text2num(href_list["upload_toggle"]) + if(num in temp_server.id_with_upload) + temp_server.id_with_upload -= num + else + temp_server.id_with_upload += num + + else if(href_list["download_toggle"]) + var/num = text2num(href_list["download_toggle"]) + if(num in temp_server.id_with_download) + temp_server.id_with_download -= num + else + temp_server.id_with_download += num + + else if(href_list["reset_tech"]) + var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel") + if(choice == "Continue") + for(var/datum/tech/T in temp_server.files.known_tech) + if(T.id == href_list["reset_tech"]) + T.level = 1 + break + temp_server.files.RefreshResearch() + + else if(href_list["reset_design"]) + var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel") + if(choice == "Continue") + for(var/datum/design/D in temp_server.files.known_designs) + if(D.id == href_list["reset_design"]) + D.reliability_mod = 0 + temp_server.files.known_designs -= D + break + temp_server.files.RefreshResearch() + + updateUsrDialog() + return + +/obj/machinery/computer/rdservercontrol/attack_hand(mob/user as mob) + if(stat & (BROKEN|NOPOWER)) + return + user.set_machine(src) + var/dat = "" + + switch(screen) + if(0) //Main Menu + dat += "Connected Servers:

    " + + for(var/obj/machinery/r_n_d/server/S in machines) + if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin) + continue + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:289: dat += "[S.name] || " + dat += {"[S.name] || + Access Rights | + Data Management"} + // END AUTOFIX + if(badmin) dat += " | Server-to-Server Transfer" + dat += "
    " + + if(1) //Access rights menu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:296: dat += "[temp_server.name] Access Rights

    " + dat += {"[temp_server.name] Access Rights

    + Consoles with Upload Access
    "} + // END AUTOFIX + for(var/obj/machinery/computer/rdconsole/C in consoles) + var/turf/console_turf = get_turf(C) + dat += "* [console_turf.loc]" //FYI, these are all numeric ids, eventually. + if(C.id in temp_server.id_with_upload) + dat += " (Remove)
    " + else + dat += " (Add)
    " + dat += "Consoles with Download Access
    " + for(var/obj/machinery/computer/rdconsole/C in consoles) + var/turf/console_turf = get_turf(C) + dat += "* [console_turf.loc]" + if(C.id in temp_server.id_with_download) + dat += " (Remove)
    " + else + dat += " (Add)
    " + dat += "
    Main Menu" + + if(2) //Data Management menu + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:316: dat += "[temp_server.name] Data ManagementP

    " + dat += {"[temp_server.name] Data Management

    + Known Technologies
    "} + // END AUTOFIX + for(var/datum/tech/T in temp_server.files.known_tech) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:319: dat += "* [T.name] " + dat += {"* [T.name] + (Reset)
    "} //FYI, these are all strings + // END AUTOFIX + dat += "Known Designs
    " + for(var/datum/design/D in temp_server.files.known_designs) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:323: dat += "* [D.name] " + dat += {"* [D.name] + (Delete)
    "} + // END AUTOFIX + dat += "
    Main Menu" + + if(3) //Server Data Transfer + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\research\server.dm:328: dat += "[temp_server.name] Server to Server Transfer

    " + dat += {"[temp_server.name] Server to Server Transfer

    + Send Data to what server?
    "} + // END AUTOFIX + for(var/obj/machinery/r_n_d/server/S in servers) + dat += "[S.name] (Transfer)
    " + dat += "
    Main Menu" + user << browse("R&D Server Control
    [dat]", "window=server_control;size=575x400") + onclose(user, "server_control") + return + +/obj/machinery/computer/rdservercontrol/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) + if(istype(D, /obj/item/weapon/screwdriver)) + playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 20)) + if (src.stat & BROKEN) to_chat(user, "The broken glass falls out.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - getFromPool(/obj/item/weapon/shard, loc) - var/obj/item/weapon/circuitboard/rdservercontrol/M = new /obj/item/weapon/circuitboard/rdservercontrol( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - qdel(src) - else + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + getFromPool(/obj/item/weapon/shard, loc) + var/obj/item/weapon/circuitboard/rdservercontrol/M = new /obj/item/weapon/circuitboard/rdservercontrol( A ) + for (var/obj/C in src) + C.loc = src.loc + A.circuit = M + A.state = 3 + A.icon_state = "3" + A.anchored = 1 + qdel(src) + else to_chat(user, "You disconnect the monitor.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/rdservercontrol/M = new /obj/item/weapon/circuitboard/rdservercontrol( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - qdel(src) - else if(istype(D, /obj/item/weapon/card/emag) && !emagged) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) - emagged = 1 + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + var/obj/item/weapon/circuitboard/rdservercontrol/M = new /obj/item/weapon/circuitboard/rdservercontrol( A ) + for (var/obj/C in src) + C.loc = src.loc + A.circuit = M + A.state = 4 + A.icon_state = "4" + A.anchored = 1 + qdel(src) + else if(istype(D, /obj/item/weapon/card/emag) && !emagged) + playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + emagged = 1 to_chat(user, "You you disable the security protocols") - src.updateUsrDialog() - return - - -/obj/machinery/r_n_d/server/robotics - name = "Robotics R&D Server" - id_with_upload_string = "1;2" - id_with_download_string = "1;2;3;4;5" - server_id = 2 - - -/obj/machinery/r_n_d/server/core - name = "Core R&D Server" - id_with_upload_string = "1" - id_with_download_string = "1" - server_id = 1 + src.updateUsrDialog() + return + + +/obj/machinery/r_n_d/server/robotics + name = "Robotics R&D Server" + id_with_upload_string = "1;2" + id_with_download_string = "1;2;3;4;5" + server_id = 2 + + +/obj/machinery/r_n_d/server/core + name = "Core R&D Server" + id_with_upload_string = "1" + id_with_download_string = "1" + server_id = 1 diff --git a/code/modules/research/xenoarchaeology/areas.dm b/code/modules/research/xenoarchaeology/areas.dm index 87b055150f1..9507b9431a5 100644 --- a/code/modules/research/xenoarchaeology/areas.dm +++ b/code/modules/research/xenoarchaeology/areas.dm @@ -1,103 +1,103 @@ - -/area/research_outpost - name = "Research Outpost" - icon_state = "anomaly" - - general_area = /area/research_outpost - general_area_name = "Research Outpost" - -/area/research_outpost/hallway - name = "Research Outpost Hallway" - icon_state = "hallC" - -/area/research_outpost/gearstore - name = "Expedition Preparation" - icon_state = "anog" - -/area/research_outpost/power - name = "Research Outpost Power" - icon_state = "engine" - -/area/research_outpost/atmos - name = "Research Outpost Atmospherics" - icon_state = "atmos" - -/area/research_outpost/maint - name = "Research Outpost Maintenance" - icon_state = "maintcentral" - -/area/research_outpost/iso1 - name = "Isolation Cell" - icon_state = "iso1" - -/area/research_outpost/iso2 - name = "Isolation Cell" - icon_state = "iso2" - -/area/research_outpost/iso3 - name = "Isolation Cell" - icon_state = "iso3" - -/area/research_outpost/harvesting - name = "Exotic Particles Collection" - icon_state = "anolab" - -/area/research_outpost/sample - name = "Sample Preparation Room" - icon_state = "anosample" - -/area/research_outpost/spectro - name = "Mass Spectrometry Lab" - icon_state = "anospectro" - -/area/research_outpost/anomaly - name = "Anomalous Materials Lab" - icon_state = "anolab" - -/area/research_outpost/med - name = "Research Outpost Medbay" - icon_state = "medbay3" - -/area/research_outpost/entry - name = "Research Outpost Shuttle Dock" - icon_state = "entry" - -/area/research_outpost/longtermstorage - name = "Long-Term Storage" - icon_state = "primarystorage" - -/area/research_outpost/tempstorage - name = "Temporary Storage" - icon_state = "storage" - -/area/research_outpost/maintstore1 - name = "Auxiliary Storage" - icon_state = "auxstorage" - -/area/research_outpost/maintstore2 - name = "Maintenance Storage" - icon_state = "auxstorage" - -/area/research_outpost/breakroom - name = "Break Room" - icon_state = "outpost_breakroom" - -/area/research_outpost/dorm1 - name = "Dormitory 1" - icon_state = "outpost_dorm1" - -/area/research_outpost/dorm2 - name = "Dormitory 2" - icon_state = "outpost_dorm2" - -/area/research_outpost/bathroom - name = "Bathroom" - icon_state = "outpost_bathroom" - -/area/research_outpost/solars - name = "Research Outpost Solar Array" - icon_state = "outpost_solars" - -/area/research_outpost/xenobot - name = "Research Outpost Xenobotany" + +/area/research_outpost + name = "Research Outpost" + icon_state = "anomaly" + + general_area = /area/research_outpost + general_area_name = "Research Outpost" + +/area/research_outpost/hallway + name = "Research Outpost Hallway" + icon_state = "hallC" + +/area/research_outpost/gearstore + name = "Expedition Preparation" + icon_state = "anog" + +/area/research_outpost/power + name = "Research Outpost Power" + icon_state = "engine" + +/area/research_outpost/atmos + name = "Research Outpost Atmospherics" + icon_state = "atmos" + +/area/research_outpost/maint + name = "Research Outpost Maintenance" + icon_state = "maintcentral" + +/area/research_outpost/iso1 + name = "Isolation Cell" + icon_state = "iso1" + +/area/research_outpost/iso2 + name = "Isolation Cell" + icon_state = "iso2" + +/area/research_outpost/iso3 + name = "Isolation Cell" + icon_state = "iso3" + +/area/research_outpost/harvesting + name = "Exotic Particles Collection" + icon_state = "anolab" + +/area/research_outpost/sample + name = "Sample Preparation Room" + icon_state = "anosample" + +/area/research_outpost/spectro + name = "Mass Spectrometry Lab" + icon_state = "anospectro" + +/area/research_outpost/anomaly + name = "Anomalous Materials Lab" + icon_state = "anolab" + +/area/research_outpost/med + name = "Research Outpost Medbay" + icon_state = "medbay3" + +/area/research_outpost/entry + name = "Research Outpost Shuttle Dock" + icon_state = "entry" + +/area/research_outpost/longtermstorage + name = "Long-Term Storage" + icon_state = "primarystorage" + +/area/research_outpost/tempstorage + name = "Temporary Storage" + icon_state = "storage" + +/area/research_outpost/maintstore1 + name = "Auxiliary Storage" + icon_state = "auxstorage" + +/area/research_outpost/maintstore2 + name = "Maintenance Storage" + icon_state = "auxstorage" + +/area/research_outpost/breakroom + name = "Break Room" + icon_state = "outpost_breakroom" + +/area/research_outpost/dorm1 + name = "Dormitory 1" + icon_state = "outpost_dorm1" + +/area/research_outpost/dorm2 + name = "Dormitory 2" + icon_state = "outpost_dorm2" + +/area/research_outpost/bathroom + name = "Bathroom" + icon_state = "outpost_bathroom" + +/area/research_outpost/solars + name = "Research Outpost Solar Array" + icon_state = "outpost_solars" + +/area/research_outpost/xenobot + name = "Research Outpost Xenobotany" icon_state = "outpost_xenobot" \ No newline at end of file diff --git a/code/modules/research/xenoarchaeology/readme.dm b/code/modules/research/xenoarchaeology/readme.dm index 2eecadc690a..c5aa7a2f800 100644 --- a/code/modules/research/xenoarchaeology/readme.dm +++ b/code/modules/research/xenoarchaeology/readme.dm @@ -1,5 +1,5 @@ - -//coming soon -//there'll probably be some stuff on the wiki at some point - + +//coming soon +//there'll probably be some stuff on the wiki at some point + //original code from alfie275 / lunacode, artifacts are from isaidno \ No newline at end of file diff --git a/code/modules/scripting/AST/AST Nodes.dm b/code/modules/scripting/AST/AST Nodes.dm index c8bb3ba9f78..406076427ff 100644 --- a/code/modules/scripting/AST/AST Nodes.dm +++ b/code/modules/scripting/AST/AST Nodes.dm @@ -1,129 +1,129 @@ -/* - File: AST Nodes - An abstract syntax tree (AST) is a representation of source code in a computer-friendly format. It is composed of nodes, - each of which represents a certain part of the source code. For example, an node represents an if statement in the - script's source code. Because it is a representation of the source code in memory, it is independent of any specific scripting language. - This allows a script in any language for which a parser exists to be run by the interpreter. - - The AST is produced by an object. It consists of a with an arbitrary amount of statements. These statements are - run in order by an object. A statement may in turn run another block (such as an if statement might if its condition is - met). - - Articles: - - -*/ -/* - Constants: Operator Precedence - OOP_OR - Logical or - OOP_AND - Logical and - OOP_BIT - Bitwise operations - OOP_EQUAL - Equality checks - OOP_COMPARE - Greater than, less then, etc - OOP_ADD - Addition and subtraction - OOP_MULTIPLY - Multiplication and division - OOP_POW - Exponents - OOP_UNARY - Unary Operators - OOP_GROUP - Parentheses -*/ -/var/const/OOP_OR = 1 //|| -/var/const/OOP_AND = OOP_OR + 1 //&& -/var/const/OOP_BIT = OOP_AND + 1 //&, | -/var/const/OOP_EQUAL = OOP_BIT + 1 //==, != -/var/const/OOP_COMPARE = OOP_EQUAL + 1 //>, <, >=, <= -/var/const/OOP_ADD = OOP_COMPARE + 1 //+, - -/var/const/OOP_MULTIPLY= OOP_ADD + 1 //*, /, % -/var/const/OOP_POW = OOP_MULTIPLY + 1 //^ -/var/const/OOP_UNARY = OOP_POW + 1 //! -/var/const/OOP_GROUP = OOP_UNARY + 1 //() - -/* - Class: node -*/ -/datum/node/proc/ToString() - return "[src.type]" -/* - Class: identifier -*/ -/datum/node/identifier - var/id_name - -/datum/node/identifier/New(id) - . = ..() - src.id_name = id - -/datum/node/identifier/ToString() - return id_name - -/* - Class: expression -*/ -/datum/node/expression -/* - Class: operator - See and for subtypes. -*/ -/datum/node/expression/operator - var/datum/node/expression/exp - var/token = "" // Used when giving type mismatches. - var/tmp/name - var/tmp/precedence - -/datum/node/expression/operator/New() - .=..() - if(!src.name) - src.name = "[src.type]" - -/datum/node/expression/operator/ToString() - return "operator: [name]" - -/* - Class: FunctionCall -*/ -/datum/node/expression/FunctionCall - //Function calls can also be expressions or statements. - var/func_name - var/datum/node/identifier/object - var/list/parameters = list() - -/* - Class: literal -*/ -/datum/node/expression/value/literal - var/value - -/datum/node/expression/value/literal/New(value) - . = ..() - src.value = value - -/datum/node/expression/value/literal/ToString() - return src.value - -/* - Class: variable -*/ -/datum/node/expression/value/variable - var/datum/node/object //Either a node/identifier or another node/expression/value/variable which points to the object - var/datum/node/identifier/id - - -/datum/node/expression/value/variable/New(ident) - . = ..() - id = ident - if(istext(id)) - id = new(id) - -/datum/node/expression/value/variable/ToString() - return src.id.ToString() - -/* - Class: reference -*/ -/datum/node/expression/value/reference - var/datum/value - -/datum/node/expression/value/reference/New(value) - . = ..() - src.value = value - -/datum/node/expression/value/reference/ToString() +/* + File: AST Nodes + An abstract syntax tree (AST) is a representation of source code in a computer-friendly format. It is composed of nodes, + each of which represents a certain part of the source code. For example, an node represents an if statement in the + script's source code. Because it is a representation of the source code in memory, it is independent of any specific scripting language. + This allows a script in any language for which a parser exists to be run by the interpreter. + + The AST is produced by an object. It consists of a with an arbitrary amount of statements. These statements are + run in order by an object. A statement may in turn run another block (such as an if statement might if its condition is + met). + + Articles: + - +*/ +/* + Constants: Operator Precedence + OOP_OR - Logical or + OOP_AND - Logical and + OOP_BIT - Bitwise operations + OOP_EQUAL - Equality checks + OOP_COMPARE - Greater than, less then, etc + OOP_ADD - Addition and subtraction + OOP_MULTIPLY - Multiplication and division + OOP_POW - Exponents + OOP_UNARY - Unary Operators + OOP_GROUP - Parentheses +*/ +/var/const/OOP_OR = 1 //|| +/var/const/OOP_AND = OOP_OR + 1 //&& +/var/const/OOP_BIT = OOP_AND + 1 //&, | +/var/const/OOP_EQUAL = OOP_BIT + 1 //==, != +/var/const/OOP_COMPARE = OOP_EQUAL + 1 //>, <, >=, <= +/var/const/OOP_ADD = OOP_COMPARE + 1 //+, - +/var/const/OOP_MULTIPLY= OOP_ADD + 1 //*, /, % +/var/const/OOP_POW = OOP_MULTIPLY + 1 //^ +/var/const/OOP_UNARY = OOP_POW + 1 //! +/var/const/OOP_GROUP = OOP_UNARY + 1 //() + +/* + Class: node +*/ +/datum/node/proc/ToString() + return "[src.type]" +/* + Class: identifier +*/ +/datum/node/identifier + var/id_name + +/datum/node/identifier/New(id) + . = ..() + src.id_name = id + +/datum/node/identifier/ToString() + return id_name + +/* + Class: expression +*/ +/datum/node/expression +/* + Class: operator + See and for subtypes. +*/ +/datum/node/expression/operator + var/datum/node/expression/exp + var/token = "" // Used when giving type mismatches. + var/tmp/name + var/tmp/precedence + +/datum/node/expression/operator/New() + .=..() + if(!src.name) + src.name = "[src.type]" + +/datum/node/expression/operator/ToString() + return "operator: [name]" + +/* + Class: FunctionCall +*/ +/datum/node/expression/FunctionCall + //Function calls can also be expressions or statements. + var/func_name + var/datum/node/identifier/object + var/list/parameters = list() + +/* + Class: literal +*/ +/datum/node/expression/value/literal + var/value + +/datum/node/expression/value/literal/New(value) + . = ..() + src.value = value + +/datum/node/expression/value/literal/ToString() + return src.value + +/* + Class: variable +*/ +/datum/node/expression/value/variable + var/datum/node/object //Either a node/identifier or another node/expression/value/variable which points to the object + var/datum/node/identifier/id + + +/datum/node/expression/value/variable/New(ident) + . = ..() + id = ident + if(istext(id)) + id = new(id) + +/datum/node/expression/value/variable/ToString() + return src.id.ToString() + +/* + Class: reference +*/ +/datum/node/expression/value/reference + var/datum/value + +/datum/node/expression/value/reference/New(value) + . = ..() + src.value = value + +/datum/node/expression/value/reference/ToString() return "ref: [src.value] ([src.value.type])" \ No newline at end of file diff --git a/code/modules/scripting/AST/Blocks.dm b/code/modules/scripting/AST/Blocks.dm index 331e49c16fe..5b9a0ffa584 100644 --- a/code/modules/scripting/AST/Blocks.dm +++ b/code/modules/scripting/AST/Blocks.dm @@ -1,45 +1,45 @@ -/* - File: Block Types -*/ -/* - Class: BlockDefinition - An object representing a set of actions to perform independently from the rest of the script. Blocks are basically just - lists of statements to execute which also contain some local variables and methods. Note that since functions are local to a block, - it is possible to have a function definition inside of any type of block (such as in an if statement or another function), - and not just in the global scope as in many languages. -*/ -/datum/node/BlockDefinition - var/list/statements = new - var/list/functions = new - var/list/initial_variables = new - -/* - Proc: SetVar - Defines a permanent variable. The variable will not be deleted when it goes out of scope. - - Notes: - Since all pre-existing temporary variables are deleted, it is not generally desirable to use this proc after the interpreter has been instantiated. - Instead, use . - - See Also: - - -*/ -/datum/node/BlockDefinition/proc/SetVar(name, value) - initial_variables[name] = value - - -/* - Class: GlobalBlock - A block object representing the global scope. -*/ -// -/datum/node/BlockDefinition/GlobalBlock/New() - initial_variables["null"] = null - return ..() - -/* - Class: FunctionBlock - A block representing a function body. -*/ -// +/* + File: Block Types +*/ +/* + Class: BlockDefinition + An object representing a set of actions to perform independently from the rest of the script. Blocks are basically just + lists of statements to execute which also contain some local variables and methods. Note that since functions are local to a block, + it is possible to have a function definition inside of any type of block (such as in an if statement or another function), + and not just in the global scope as in many languages. +*/ +/datum/node/BlockDefinition + var/list/statements = new + var/list/functions = new + var/list/initial_variables = new + +/* + Proc: SetVar + Defines a permanent variable. The variable will not be deleted when it goes out of scope. + + Notes: + Since all pre-existing temporary variables are deleted, it is not generally desirable to use this proc after the interpreter has been instantiated. + Instead, use . + + See Also: + - +*/ +/datum/node/BlockDefinition/proc/SetVar(name, value) + initial_variables[name] = value + + +/* + Class: GlobalBlock + A block object representing the global scope. +*/ +// +/datum/node/BlockDefinition/GlobalBlock/New() + initial_variables["null"] = null + return ..() + +/* + Class: FunctionBlock + A block representing a function body. +*/ +// /datum/node/BlockDefinition/FunctionBlock \ No newline at end of file diff --git a/code/modules/scripting/AST/Operators/Binary Operators.dm b/code/modules/scripting/AST/Operators/Binary Operators.dm index ccbccc53323..a80436fa1cd 100644 --- a/code/modules/scripting/AST/Operators/Binary Operators.dm +++ b/code/modules/scripting/AST/Operators/Binary Operators.dm @@ -1,191 +1,191 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/* - File: Binary Operators -*/ -/* - Class: binary - Represents a binary operator in the AST. A binary operator takes two operands (ie x and y) and returns a value. -*/ -/datum/node/expression/operator/binary - var/datum/node/expression/exp2 - -////////// Comparison Operators ////////// -/* - Class: Equal - Returns true if x = y. -*/ -// -/datum/node/expression/operator/binary/Equal - token = "==" - precedence = OOP_EQUAL - -/* -Class: NotEqual -Returns true if x and y aren't equal. -*/ -// -/datum/node/expression/operator/binary/NotEqual - token = "!=" - precedence = OOP_EQUAL - -/* -Class: Greater -Returns true if x > y. -*/ -// -/datum/node/expression/operator/binary/Greater - token = ">" - precedence = OOP_COMPARE - -/* -Class: Less -Returns true if x < y. -*/ -// -/datum/node/expression/operator/binary/Less - token = "<" - precedence = OOP_COMPARE - -/* -Class: GreaterOrEqual -Returns true if x >= y. -*/ -// -/datum/node/expression/operator/binary/GreaterOrEqual - token = ">=" - precedence = OOP_COMPARE - -/* -Class: LessOrEqual -Returns true if x <= y. -*/ -// -/datum/node/expression/operator/binary/LessOrEqual - token = "<=" - precedence = OOP_COMPARE - - -////////// Logical Operators ////////// - -/* -Class: LogicalAnd -Returns true if x and y are true. -*/ -// -/datum/node/expression/operator/binary/LogicalAnd - token = "&&" - precedence = OOP_AND - -/* -Class: LogicalOr -Returns true if x, y, or both are true. -*/ -// -/datum/node/expression/operator/binary/LogicalOr - token = "||" - precedence = OOP_OR - -/* -Class: LogicalXor -Returns true if either x or y but not both are true. -*/ -// -/datum/node/expression/operator/binary/LogicalXor //Not implemented in nS - precedence = OOP_OR - - -////////// Bitwise Operators ////////// - -/* -Class: BitwiseAnd -Performs a bitwise and operation. - -Example: -011 & 110 = 010 -*/ -// -/datum/node/expression/operator/binary/BitwiseAnd - token = "&" - precedence = OOP_BIT - -/* -Class: BitwiseOr -Performs a bitwise or operation. - -Example: -011 | 110 = 111 -*/ -// -/datum/node/expression/operator/binary/BitwiseOr - token = "|" - precedence = OOP_BIT - -/* -Class: BitwiseXor -Performs a bitwise exclusive or operation. - -Example: -011 xor 110 = 101 -*/ -// -/datum/node/expression/operator/binary/BitwiseXor - token = "`" - precedence = OOP_BIT - - -////////// Arithmetic Operators ////////// - -/* -Class: Add -Returns the sum of x and y. -*/ -// -/datum/node/expression/operator/binary/Add - token = "+" - precedence = OOP_ADD - -/* -Class: Subtract -Returns the difference of x and y. -*/ -// -/datum/node/expression/operator/binary/Subtract - token = "-" - precedence = OOP_ADD - -/* -Class: Multiply -Returns the product of x and y. -*/ -// -/datum/node/expression/operator/binary/Multiply - token = "*" - precedence = OOP_MULTIPLY - -/* -Class: Divide -Returns the quotient of x and y. -*/ -// -/datum/node/expression/operator/binary/Divide - token = "/" - precedence = OOP_MULTIPLY - -/* -Class: Power -Returns x raised to the power of y. -*/ -// -/datum/node/expression/operator/binary/Power - token = "^" - precedence = OOP_POW - -/* -Class: Modulo -Returns the remainder of x / y. -*/ -// -/datum/node/expression/operator/binary/Modulo - token = "%" - precedence = OOP_MULTIPLY +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/* + File: Binary Operators +*/ +/* + Class: binary + Represents a binary operator in the AST. A binary operator takes two operands (ie x and y) and returns a value. +*/ +/datum/node/expression/operator/binary + var/datum/node/expression/exp2 + +////////// Comparison Operators ////////// +/* + Class: Equal + Returns true if x = y. +*/ +// +/datum/node/expression/operator/binary/Equal + token = "==" + precedence = OOP_EQUAL + +/* +Class: NotEqual +Returns true if x and y aren't equal. +*/ +// +/datum/node/expression/operator/binary/NotEqual + token = "!=" + precedence = OOP_EQUAL + +/* +Class: Greater +Returns true if x > y. +*/ +// +/datum/node/expression/operator/binary/Greater + token = ">" + precedence = OOP_COMPARE + +/* +Class: Less +Returns true if x < y. +*/ +// +/datum/node/expression/operator/binary/Less + token = "<" + precedence = OOP_COMPARE + +/* +Class: GreaterOrEqual +Returns true if x >= y. +*/ +// +/datum/node/expression/operator/binary/GreaterOrEqual + token = ">=" + precedence = OOP_COMPARE + +/* +Class: LessOrEqual +Returns true if x <= y. +*/ +// +/datum/node/expression/operator/binary/LessOrEqual + token = "<=" + precedence = OOP_COMPARE + + +////////// Logical Operators ////////// + +/* +Class: LogicalAnd +Returns true if x and y are true. +*/ +// +/datum/node/expression/operator/binary/LogicalAnd + token = "&&" + precedence = OOP_AND + +/* +Class: LogicalOr +Returns true if x, y, or both are true. +*/ +// +/datum/node/expression/operator/binary/LogicalOr + token = "||" + precedence = OOP_OR + +/* +Class: LogicalXor +Returns true if either x or y but not both are true. +*/ +// +/datum/node/expression/operator/binary/LogicalXor //Not implemented in nS + precedence = OOP_OR + + +////////// Bitwise Operators ////////// + +/* +Class: BitwiseAnd +Performs a bitwise and operation. + +Example: +011 & 110 = 010 +*/ +// +/datum/node/expression/operator/binary/BitwiseAnd + token = "&" + precedence = OOP_BIT + +/* +Class: BitwiseOr +Performs a bitwise or operation. + +Example: +011 | 110 = 111 +*/ +// +/datum/node/expression/operator/binary/BitwiseOr + token = "|" + precedence = OOP_BIT + +/* +Class: BitwiseXor +Performs a bitwise exclusive or operation. + +Example: +011 xor 110 = 101 +*/ +// +/datum/node/expression/operator/binary/BitwiseXor + token = "`" + precedence = OOP_BIT + + +////////// Arithmetic Operators ////////// + +/* +Class: Add +Returns the sum of x and y. +*/ +// +/datum/node/expression/operator/binary/Add + token = "+" + precedence = OOP_ADD + +/* +Class: Subtract +Returns the difference of x and y. +*/ +// +/datum/node/expression/operator/binary/Subtract + token = "-" + precedence = OOP_ADD + +/* +Class: Multiply +Returns the product of x and y. +*/ +// +/datum/node/expression/operator/binary/Multiply + token = "*" + precedence = OOP_MULTIPLY + +/* +Class: Divide +Returns the quotient of x and y. +*/ +// +/datum/node/expression/operator/binary/Divide + token = "/" + precedence = OOP_MULTIPLY + +/* +Class: Power +Returns x raised to the power of y. +*/ +// +/datum/node/expression/operator/binary/Power + token = "^" + precedence = OOP_POW + +/* +Class: Modulo +Returns the remainder of x / y. +*/ +// +/datum/node/expression/operator/binary/Modulo + token = "%" + precedence = OOP_MULTIPLY diff --git a/code/modules/scripting/AST/Operators/Unary Operators.dm b/code/modules/scripting/AST/Operators/Unary Operators.dm index e7cd4b8489a..386e76368da 100644 --- a/code/modules/scripting/AST/Operators/Unary Operators.dm +++ b/code/modules/scripting/AST/Operators/Unary Operators.dm @@ -1,51 +1,51 @@ -/* - File: Unary Operators -*/ -/* - Class: unary - Represents a unary operator in the AST. Unary operators take a single operand (referred to as x below) and return a value. -*/ -/datum/node/expression/operator/unary - precedence = OOP_UNARY - -/* - Class: LogicalNot - Returns !x. - - Example: - !true = false and !false = true -*/ -// -/datum/node/expression/operator/unary/LogicalNot - name = "logical not" - -/* - Class: BitwiseNot - Returns the value of a bitwise not operation performed on x. - - Example: - ~10 (decimal 2) = 01 (decimal 1). -*/ -// -/datum/node/expression/operator/unary/BitwiseNot - name = "bitwise not" - -/* - Class: Minus - Returns -x. -*/ -// -/datum/node/expression/operator/unary/Minus - name = "minus" - -/* - Class: group - A special unary operator representing a value in parentheses. -*/ -// -/datum/node/expression/operator/unary/group - precedence = OOP_GROUP - -/datum/node/expression/operator/unary/New(var/datum/node/expression/exp) - src.exp = exp - return ..() +/* + File: Unary Operators +*/ +/* + Class: unary + Represents a unary operator in the AST. Unary operators take a single operand (referred to as x below) and return a value. +*/ +/datum/node/expression/operator/unary + precedence = OOP_UNARY + +/* + Class: LogicalNot + Returns !x. + + Example: + !true = false and !false = true +*/ +// +/datum/node/expression/operator/unary/LogicalNot + name = "logical not" + +/* + Class: BitwiseNot + Returns the value of a bitwise not operation performed on x. + + Example: + ~10 (decimal 2) = 01 (decimal 1). +*/ +// +/datum/node/expression/operator/unary/BitwiseNot + name = "bitwise not" + +/* + Class: Minus + Returns -x. +*/ +// +/datum/node/expression/operator/unary/Minus + name = "minus" + +/* + Class: group + A special unary operator representing a value in parentheses. +*/ +// +/datum/node/expression/operator/unary/group + precedence = OOP_GROUP + +/datum/node/expression/operator/unary/New(var/datum/node/expression/exp) + src.exp = exp + return ..() diff --git a/code/modules/scripting/AST/Statements.dm b/code/modules/scripting/AST/Statements.dm index bae9f3de68c..db392f1ded2 100644 --- a/code/modules/scripting/AST/Statements.dm +++ b/code/modules/scripting/AST/Statements.dm @@ -1,110 +1,110 @@ -/* - File: Statement Types -*/ -/* - Class: statement - An object representing a single instruction run by an interpreter. -*/ -/datum/node/statement -/* - Class: FunctionCall - Represents a call to a function. -*/ -// -/datum/node/statement/FunctionCall - var/func_name - var/datum/node/identifier/object - var/list/parameters = new - -/* -Class: FunctionDefinition -Defines a function. -*/ -// -/datum/node/statement/FunctionDefinition - var/func_name - var/list/parameters = new - var/datum/node/BlockDefinition/FunctionBlock/block - -/* -Class: VariableAssignment -Sets a variable in an accessible scope to the given value if one exists, otherwise initializes a new local variable to the given value. - -Notes: -If a variable with the same name exists in a higher block, the value will be assigned to it. If not, -a new variable is created in the current block. To force creation of a new variable, use . - -See Also: -- -*/ -// -/datum/node/statement/VariableAssignment - var/datum/node/identifier/object - var/datum/node/identifier/var_name - var/datum/node/expression/value - -/* -Class: VariableDeclaration -Intializes a local variable to a null value. - -See Also: -- -*/ -// -/datum/node/statement/VariableDeclaration - var/datum/node/identifier/object - var/datum/node/identifier/var_name - -/* -Class: IfStatement -*/ -// -/datum/node/statement/IfStatement - var/skip = 0 - var/datum/node/BlockDefinition/block - var/datum/node/BlockDefinition/else_block //may be null - var/datum/node/expression/cond - var/datum/node/statement/else_if - -/datum/node/statement/IfStatement/ElseIf - -/* -Class: WhileLoop -Loops while a given condition is true. -*/ -// -/datum/node/statement/WhileLoop - var/datum/node/BlockDefinition/block - var/datum/node/expression/cond - -/* -Class: ForLoop -Loops while test is true, initializing a variable, increasing the variable -*/ -/datum/node/statement/ForLoop - var/datum/node/BlockDefinition/block - var/datum/node/expression/test - var/datum/node/expression/init - var/datum/node/expression/increment - -/* -Class: BreakStatement -Ends a loop. -*/ -// -/datum/node/statement/BreakStatement - -/* -Class: ContinueStatement -Skips to the next iteration of a loop. -*/ -// -/datum/node/statement/ContinueStatement - -/* -Class: ReturnStatement -Ends the function and returns a value. -*/ -// -/datum/node/statement/ReturnStatement +/* + File: Statement Types +*/ +/* + Class: statement + An object representing a single instruction run by an interpreter. +*/ +/datum/node/statement +/* + Class: FunctionCall + Represents a call to a function. +*/ +// +/datum/node/statement/FunctionCall + var/func_name + var/datum/node/identifier/object + var/list/parameters = new + +/* +Class: FunctionDefinition +Defines a function. +*/ +// +/datum/node/statement/FunctionDefinition + var/func_name + var/list/parameters = new + var/datum/node/BlockDefinition/FunctionBlock/block + +/* +Class: VariableAssignment +Sets a variable in an accessible scope to the given value if one exists, otherwise initializes a new local variable to the given value. + +Notes: +If a variable with the same name exists in a higher block, the value will be assigned to it. If not, +a new variable is created in the current block. To force creation of a new variable, use . + +See Also: +- +*/ +// +/datum/node/statement/VariableAssignment + var/datum/node/identifier/object + var/datum/node/identifier/var_name + var/datum/node/expression/value + +/* +Class: VariableDeclaration +Intializes a local variable to a null value. + +See Also: +- +*/ +// +/datum/node/statement/VariableDeclaration + var/datum/node/identifier/object + var/datum/node/identifier/var_name + +/* +Class: IfStatement +*/ +// +/datum/node/statement/IfStatement + var/skip = 0 + var/datum/node/BlockDefinition/block + var/datum/node/BlockDefinition/else_block //may be null + var/datum/node/expression/cond + var/datum/node/statement/else_if + +/datum/node/statement/IfStatement/ElseIf + +/* +Class: WhileLoop +Loops while a given condition is true. +*/ +// +/datum/node/statement/WhileLoop + var/datum/node/BlockDefinition/block + var/datum/node/expression/cond + +/* +Class: ForLoop +Loops while test is true, initializing a variable, increasing the variable +*/ +/datum/node/statement/ForLoop + var/datum/node/BlockDefinition/block + var/datum/node/expression/test + var/datum/node/expression/init + var/datum/node/expression/increment + +/* +Class: BreakStatement +Ends a loop. +*/ +// +/datum/node/statement/BreakStatement + +/* +Class: ContinueStatement +Skips to the next iteration of a loop. +*/ +// +/datum/node/statement/ContinueStatement + +/* +Class: ReturnStatement +Ends the function and returns a value. +*/ +// +/datum/node/statement/ReturnStatement var/datum/node/expression/value \ No newline at end of file diff --git a/code/modules/scripting/Errors.dm b/code/modules/scripting/Errors.dm index 47fb83f8217..e8723d1c926 100644 --- a/code/modules/scripting/Errors.dm +++ b/code/modules/scripting/Errors.dm @@ -1,169 +1,169 @@ -/* - File: Errors -*/ -/* - Class: scriptError - An error scanning or parsing the source code. -*/ -/datum/scriptError -/* - Var: message - A message describing the problem. -*/ - var/message - -/datum/scriptError/New(msg = null) - if(msg)message = msg - -/datum/scriptError/BadToken - message = "Unexpected token: " - var/datum/token/token - -/datum/scriptError/BadToken/New(datum/token/t) - token = t - if(t && t.line) - message = "[t.line]: [message]" - - if(istype(t)) - message += "[t.value]" - - else - message += "[t]" - -/datum/scriptError/InvalidID - parent_type = /datum/scriptError/BadToken - message = "Invalid identifier name: " - -/datum/scriptError/ReservedWord - parent_type = /datum/scriptError/BadToken - message = "Identifer using reserved word: " - -/datum/scriptError/BadNumber - parent_type = /datum/scriptError/BadToken - message = "Bad number: " - -/datum/scriptError/BadReturn - var/datum/token/token - message = "Unexpected return statement outside of a function." - -/datum/scriptError/BadReturn/New(datum/token/t) - src.token = t - -/datum/scriptError/EndOfFile - message = "Unexpected end of file." - -/datum/scriptError/ExpectedToken - message = "Expected: '" - -/datum/scriptError/ExpectedToken/New(id, datum/token/T) - if(T && T.line) - message = "[T.line]: [message]" - - message += "[id]'. " - - if(T) - message += "Found '[T.value]'." - - -/datum/scriptError/UnterminatedComment - message = "Unterminated multi-line comment statement: expected */" - -/datum/scriptError/DuplicateFunction/New(name, datum/token/t) - message = "Function '[name]' defined twice." - -/datum/scriptError/ParameterFunction - message = "You cannot use a function inside a parameter." - -/datum/scriptError/ParameterFunction/New(datum/token/t) - var/line = "?" - if(t) - line = t.line - message = "[line]: [message]" - -/* - Class: runtimeError - An error thrown by the interpreter in running the script. -*/ -/datum/runtimeError - var/name -/* - Var: message - A basic description as to what went wrong. -*/ - var/message - var/datum/stack/stack -/* - Proc: ToString - Returns a description of the error suitable for showing to the user. -*/ -/datum/runtimeError/proc/ToString() - . = "[name]: [message]" - if(!stack.Top()) - return - - . += "\nStack:" - while(stack.Top()) - var/datum/node/statement/FunctionCall/stmt = stack.Pop() - . += "\n\t [stmt.func_name]()" - -/datum/runtimeError/TypeMismatch - name = "TypeMismatchError" - -/datum/runtimeError/TypeMismatch/New(op, a, b) - message = "Type mismatch: '[a]' [op] '[b]'" - -/datum/runtimeError/TypeMismatch/unary/New(op, a) - message = "Type mismatch: [op]'[a]'" - -/datum/runtimeError/TypeMismatch/New(op, a, b) - message = "Type mismatch: '[a]' [op] '[b]'" - -/datum/runtimeError/UnexpectedReturn - name = "UnexpectedReturnError" - message = "Unexpected return statement." - -/datum/runtimeError/UnknownInstruction - name = "UnknownInstructionError" - message = "Unknown instruction type. This may be due to incompatible compiler and interpreter versions or a lack of implementation." - -/datum/runtimeError/UndefinedVariable - name = "UndefinedVariableError" - -/datum/runtimeError/UndefinedVariable/New(variable) - message = "Variable '[variable]' has not been declared." - -/datum/runtimeError/UndefinedFunction - name = "UndefinedFunctionError" - -/datum/runtimeError/UndefinedFunction/New(function) - message = "Function '[function]()' has not been defined." - -/datum/runtimeError/DuplicateVariableDeclaration - name = "DuplicateVariableError" - -/datum/runtimeError/DuplicateVariableDeclaration/New(variable) - message="Variable '[variable]' was already declared." - -/datum/runtimeError/IterationLimitReached - name = "MaxIterationError" - message = "A loop has reached its maximum number of iterations." - -/datum/runtimeError/RecursionLimitReached - name = "MaxRecursionError" - message = "The maximum amount of recursion has been reached." - -/datum/runtimeError/DivisionByZero - name = "DivideByZeroError" - message = "Division by zero attempted." - -/datum/runtimeError/MaxCPU - name = "MaxComputationalUse" - message = "Maximum amount of computational cycles reached (>= 1000)." - -/datum/runtimeError/VectorLimit - name = "VectorSizeOverflow" - message = "Maximum vector size reached" - -/datum/runtimeError/StringLimit - name = "StringSizeOverflow" - message = "Maximum string size reached" +/* + File: Errors +*/ +/* + Class: scriptError + An error scanning or parsing the source code. +*/ +/datum/scriptError +/* + Var: message + A message describing the problem. +*/ + var/message + +/datum/scriptError/New(msg = null) + if(msg)message = msg + +/datum/scriptError/BadToken + message = "Unexpected token: " + var/datum/token/token + +/datum/scriptError/BadToken/New(datum/token/t) + token = t + if(t && t.line) + message = "[t.line]: [message]" + + if(istype(t)) + message += "[t.value]" + + else + message += "[t]" + +/datum/scriptError/InvalidID + parent_type = /datum/scriptError/BadToken + message = "Invalid identifier name: " + +/datum/scriptError/ReservedWord + parent_type = /datum/scriptError/BadToken + message = "Identifer using reserved word: " + +/datum/scriptError/BadNumber + parent_type = /datum/scriptError/BadToken + message = "Bad number: " + +/datum/scriptError/BadReturn + var/datum/token/token + message = "Unexpected return statement outside of a function." + +/datum/scriptError/BadReturn/New(datum/token/t) + src.token = t + +/datum/scriptError/EndOfFile + message = "Unexpected end of file." + +/datum/scriptError/ExpectedToken + message = "Expected: '" + +/datum/scriptError/ExpectedToken/New(id, datum/token/T) + if(T && T.line) + message = "[T.line]: [message]" + + message += "[id]'. " + + if(T) + message += "Found '[T.value]'." + + +/datum/scriptError/UnterminatedComment + message = "Unterminated multi-line comment statement: expected */" + +/datum/scriptError/DuplicateFunction/New(name, datum/token/t) + message = "Function '[name]' defined twice." + +/datum/scriptError/ParameterFunction + message = "You cannot use a function inside a parameter." + +/datum/scriptError/ParameterFunction/New(datum/token/t) + var/line = "?" + if(t) + line = t.line + message = "[line]: [message]" + +/* + Class: runtimeError + An error thrown by the interpreter in running the script. +*/ +/datum/runtimeError + var/name +/* + Var: message + A basic description as to what went wrong. +*/ + var/message + var/datum/stack/stack +/* + Proc: ToString + Returns a description of the error suitable for showing to the user. +*/ +/datum/runtimeError/proc/ToString() + . = "[name]: [message]" + if(!stack.Top()) + return + + . += "\nStack:" + while(stack.Top()) + var/datum/node/statement/FunctionCall/stmt = stack.Pop() + . += "\n\t [stmt.func_name]()" + +/datum/runtimeError/TypeMismatch + name = "TypeMismatchError" + +/datum/runtimeError/TypeMismatch/New(op, a, b) + message = "Type mismatch: '[a]' [op] '[b]'" + +/datum/runtimeError/TypeMismatch/unary/New(op, a) + message = "Type mismatch: [op]'[a]'" + +/datum/runtimeError/TypeMismatch/New(op, a, b) + message = "Type mismatch: '[a]' [op] '[b]'" + +/datum/runtimeError/UnexpectedReturn + name = "UnexpectedReturnError" + message = "Unexpected return statement." + +/datum/runtimeError/UnknownInstruction + name = "UnknownInstructionError" + message = "Unknown instruction type. This may be due to incompatible compiler and interpreter versions or a lack of implementation." + +/datum/runtimeError/UndefinedVariable + name = "UndefinedVariableError" + +/datum/runtimeError/UndefinedVariable/New(variable) + message = "Variable '[variable]' has not been declared." + +/datum/runtimeError/UndefinedFunction + name = "UndefinedFunctionError" + +/datum/runtimeError/UndefinedFunction/New(function) + message = "Function '[function]()' has not been defined." + +/datum/runtimeError/DuplicateVariableDeclaration + name = "DuplicateVariableError" + +/datum/runtimeError/DuplicateVariableDeclaration/New(variable) + message="Variable '[variable]' was already declared." + +/datum/runtimeError/IterationLimitReached + name = "MaxIterationError" + message = "A loop has reached its maximum number of iterations." + +/datum/runtimeError/RecursionLimitReached + name = "MaxRecursionError" + message = "The maximum amount of recursion has been reached." + +/datum/runtimeError/DivisionByZero + name = "DivideByZeroError" + message = "Division by zero attempted." + +/datum/runtimeError/MaxCPU + name = "MaxComputationalUse" + message = "Maximum amount of computational cycles reached (>= 1000)." + +/datum/runtimeError/VectorLimit + name = "VectorSizeOverflow" + message = "Maximum vector size reached" + +/datum/runtimeError/StringLimit + name = "StringSizeOverflow" + message = "Maximum string size reached" diff --git a/code/modules/scripting/IDE.dm b/code/modules/scripting/IDE.dm index 314e86cb9db..56c18999117 100644 --- a/code/modules/scripting/IDE.dm +++ b/code/modules/scripting/IDE.dm @@ -1,188 +1,188 @@ -/client/verb/tcssave() - set hidden = 1 - if(mob.machine || issilicon(mob)) - if(telecomms_check(mob)) - var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine - if(Machine.editingcode != mob) - return - - if(Machine.SelectedServer) - var/obj/machinery/telecomms/server/Server = Machine.SelectedServer - var/tcscode = winget(src, "tcscode", "text") - Server.setcode( tcscode ) // this actually saves the code from input to the server - src << output(null, "tcserror") // clear the errors - else - src << output(null, "tcserror") - src << output("Failed to save: Unable to locate server machine. (Back up your code before exiting the window!)", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to save: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to save: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") - - -/client/verb/tcscompile() - set hidden = 1 - if(mob.machine || issilicon(mob)) - if(telecomms_check(mob)) - var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine - if(Machine.editingcode != mob) - return - - if(Machine.SelectedServer) - var/obj/machinery/telecomms/server/Server = Machine.SelectedServer - Server.setcode( winget(src, "tcscode", "text") ) // save code first - - spawn(0) - // Output all the compile-time errors - src << output(null, "tcserror") - src << output("Please wait, compiling...", "tcserror") - - var/list/compileerrors = Server.compile(mob) // then compile the code! - if(!telecomms_check(mob)) - return - - if(compileerrors.len) - src << output("Compile Errors", "tcserror") - for(var/datum/scriptError/e in compileerrors) - src << output("\t>[e.message]", "tcserror") - src << output("([compileerrors.len] errors)", "tcserror") - - // Output compile errors to all other people viewing the code too - for(var/mob/M in Machine.viewingcode) - if(M.client) - M << output(null, "tcserror") - M << output("Compile Errors", "tcserror") - for(var/datum/scriptError/e in compileerrors) - M << output("\t>[e.message]", "tcserror") - M << output("([compileerrors.len] errors)", "tcserror") - - - else - src << output("TCS compilation successful!", "tcserror") - src << output("(0 errors)", "tcserror") - - for(var/mob/M in Machine.viewingcode) - if(M.client) - M << output("TCS compilation successful!", "tcserror") - M << output("(0 errors)", "tcserror") - - else - src << output(null, "tcserror") - src << output("Failed to compile: Unable to locate server machine. (Back up your code before exiting the window!)", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") - -/client/verb/tcsrun() - set hidden = 1 - if(mob.machine || issilicon(mob)) - if(telecomms_check(mob)) - var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine - if(Machine.editingcode != mob) - return - - if(Machine.SelectedServer) - var/obj/machinery/telecomms/server/Server = Machine.SelectedServer - - var/datum/signal/signal = getFromPool(/datum/signal) - signal.data["message"] = "" - if(Server.freq_listening.len > 0) - signal.frequency = Server.freq_listening[1] - else - signal.frequency = 1459 - signal.data["name"] = "" - signal.data["job"] = "" - signal.data["reject"] = 0 - signal.data["server"] = Server - - Server.Compiler.Run(signal) - - - else - src << output(null, "tcserror") - src << output("Failed to run: Unable to locate server machine. (Back up your code before exiting the window!)", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to run: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to run: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") - - -/client/verb/exittcs() - set hidden = 1 - if(mob.machine || issilicon(mob)) - if(telecomms_check(mob)) - var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine - if(Machine.editingcode == mob) - Machine.storedcode = "[winget(mob, "tcscode", "text")]" - Machine.editingcode = null - else - if(mob in Machine.viewingcode) - Machine.viewingcode.Remove(mob) - -/client/verb/tcsrevert() - set hidden = 1 - if(mob.machine || issilicon(mob)) - if(telecomms_check(mob)) - var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine - if(Machine.editingcode != mob) - return - - if(Machine.SelectedServer) - var/obj/machinery/telecomms/server/Server = Machine.SelectedServer - - // Replace quotation marks with quotation macros for proper winset() compatibility - var/showcode = replacetext(Server.rawcode, "\\\"", "\\\\\"") - showcode = replacetext(showcode, "\"", "\\\"") - - winset(mob, "tcscode", "text=\"[showcode]\"") - - src << output(null, "tcserror") // clear the errors - else - src << output(null, "tcserror") - src << output("Failed to revert: Unable to locate server machine.", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to revert: Unable to locate machine.", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to revert: Unable to locate machine.", "tcserror") - - -/client/verb/tcsclearmem() - set hidden = 1 - if(mob.machine || issilicon(mob)) - if(telecomms_check(mob)) - var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine - if(Machine.editingcode != mob) - return - - if(Machine.SelectedServer) - var/obj/machinery/telecomms/server/Server = Machine.SelectedServer - Server.memory = list() // clear the memory - // Show results - src << output(null, "tcserror") - src << output("Server memory cleared!", "tcserror") - for(var/mob/M in Machine.viewingcode) - if(M.client) - M << output("Server memory cleared!", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to clear memory: Unable to locate server machine.", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to clear memory: Unable to locate machine.", "tcserror") - else - src << output(null, "tcserror") - src << output("Failed to clear memory: Unable to locate machine.", "tcserror") - -/proc/telecomms_check(var/mob/mob) - if(mob && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && in_range(mob.machine, mob) || issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic)) - return 1 +/client/verb/tcssave() + set hidden = 1 + if(mob.machine || issilicon(mob)) + if(telecomms_check(mob)) + var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine + if(Machine.editingcode != mob) + return + + if(Machine.SelectedServer) + var/obj/machinery/telecomms/server/Server = Machine.SelectedServer + var/tcscode = winget(src, "tcscode", "text") + Server.setcode( tcscode ) // this actually saves the code from input to the server + src << output(null, "tcserror") // clear the errors + else + src << output(null, "tcserror") + src << output("Failed to save: Unable to locate server machine. (Back up your code before exiting the window!)", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to save: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to save: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") + + +/client/verb/tcscompile() + set hidden = 1 + if(mob.machine || issilicon(mob)) + if(telecomms_check(mob)) + var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine + if(Machine.editingcode != mob) + return + + if(Machine.SelectedServer) + var/obj/machinery/telecomms/server/Server = Machine.SelectedServer + Server.setcode( winget(src, "tcscode", "text") ) // save code first + + spawn(0) + // Output all the compile-time errors + src << output(null, "tcserror") + src << output("Please wait, compiling...", "tcserror") + + var/list/compileerrors = Server.compile(mob) // then compile the code! + if(!telecomms_check(mob)) + return + + if(compileerrors.len) + src << output("Compile Errors", "tcserror") + for(var/datum/scriptError/e in compileerrors) + src << output("\t>[e.message]", "tcserror") + src << output("([compileerrors.len] errors)", "tcserror") + + // Output compile errors to all other people viewing the code too + for(var/mob/M in Machine.viewingcode) + if(M.client) + M << output(null, "tcserror") + M << output("Compile Errors", "tcserror") + for(var/datum/scriptError/e in compileerrors) + M << output("\t>[e.message]", "tcserror") + M << output("([compileerrors.len] errors)", "tcserror") + + + else + src << output("TCS compilation successful!", "tcserror") + src << output("(0 errors)", "tcserror") + + for(var/mob/M in Machine.viewingcode) + if(M.client) + M << output("TCS compilation successful!", "tcserror") + M << output("(0 errors)", "tcserror") + + else + src << output(null, "tcserror") + src << output("Failed to compile: Unable to locate server machine. (Back up your code before exiting the window!)", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") + +/client/verb/tcsrun() + set hidden = 1 + if(mob.machine || issilicon(mob)) + if(telecomms_check(mob)) + var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine + if(Machine.editingcode != mob) + return + + if(Machine.SelectedServer) + var/obj/machinery/telecomms/server/Server = Machine.SelectedServer + + var/datum/signal/signal = getFromPool(/datum/signal) + signal.data["message"] = "" + if(Server.freq_listening.len > 0) + signal.frequency = Server.freq_listening[1] + else + signal.frequency = 1459 + signal.data["name"] = "" + signal.data["job"] = "" + signal.data["reject"] = 0 + signal.data["server"] = Server + + Server.Compiler.Run(signal) + + + else + src << output(null, "tcserror") + src << output("Failed to run: Unable to locate server machine. (Back up your code before exiting the window!)", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to run: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to run: Unable to locate machine. (Back up your code before exiting the window!)", "tcserror") + + +/client/verb/exittcs() + set hidden = 1 + if(mob.machine || issilicon(mob)) + if(telecomms_check(mob)) + var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine + if(Machine.editingcode == mob) + Machine.storedcode = "[winget(mob, "tcscode", "text")]" + Machine.editingcode = null + else + if(mob in Machine.viewingcode) + Machine.viewingcode.Remove(mob) + +/client/verb/tcsrevert() + set hidden = 1 + if(mob.machine || issilicon(mob)) + if(telecomms_check(mob)) + var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine + if(Machine.editingcode != mob) + return + + if(Machine.SelectedServer) + var/obj/machinery/telecomms/server/Server = Machine.SelectedServer + + // Replace quotation marks with quotation macros for proper winset() compatibility + var/showcode = replacetext(Server.rawcode, "\\\"", "\\\\\"") + showcode = replacetext(showcode, "\"", "\\\"") + + winset(mob, "tcscode", "text=\"[showcode]\"") + + src << output(null, "tcserror") // clear the errors + else + src << output(null, "tcserror") + src << output("Failed to revert: Unable to locate server machine.", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to revert: Unable to locate machine.", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to revert: Unable to locate machine.", "tcserror") + + +/client/verb/tcsclearmem() + set hidden = 1 + if(mob.machine || issilicon(mob)) + if(telecomms_check(mob)) + var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine + if(Machine.editingcode != mob) + return + + if(Machine.SelectedServer) + var/obj/machinery/telecomms/server/Server = Machine.SelectedServer + Server.memory = list() // clear the memory + // Show results + src << output(null, "tcserror") + src << output("Server memory cleared!", "tcserror") + for(var/mob/M in Machine.viewingcode) + if(M.client) + M << output("Server memory cleared!", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to clear memory: Unable to locate server machine.", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to clear memory: Unable to locate machine.", "tcserror") + else + src << output(null, "tcserror") + src << output("Failed to clear memory: Unable to locate machine.", "tcserror") + +/proc/telecomms_check(var/mob/mob) + if(mob && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && in_range(mob.machine, mob) || issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic)) + return 1 return 0 \ No newline at end of file diff --git a/code/modules/scripting/Implementations/_Logic.dm b/code/modules/scripting/Implementations/_Logic.dm index e5b28496bab..fa76f742a5d 100644 --- a/code/modules/scripting/Implementations/_Logic.dm +++ b/code/modules/scripting/Implementations/_Logic.dm @@ -1,226 +1,226 @@ -// Script -> BYOND code procs -#define SCRIPT_MAX_REPLACEMENTS_ALLOWED 200 -// --- List operations (lists known as vectors in n_script) --- - -// Clone of list() -/proc/n_list() - var/list/returnlist = list() - for(var/e in args) - returnlist.Add(e) - return returnlist - -// Clone of pick() -/proc/n_pick() - var/list/finalpick = list() - for(var/e in args) - if(isobject(e)) - if(istype(e, /list)) - var/list/sublist = e - for(var/sube in sublist) - finalpick.Add(sube) - continue - finalpick.Add(e) - - return pick(finalpick) - -// Clone of list[] -/proc/n_listpos(var/list/L, var/pos, var/value) - if(!istype(L, /list)) return - if(isnum(pos)) - if(!value) - if(L.len >= pos && !(pos > L.len)) - return L[pos] - else - if(L.len >= pos && !(pos > L.len)) - L[pos] = value - else if(istext(pos)) - if(!value) - return L[pos] - else - L[pos] = value - -// Clone of list.Copy() -/proc/n_listcopy(var/list/L, var/start, var/end) - if(!istype(L, /list)) return - return L.Copy(start, end) - -// Clone of list.Add() -/proc/n_listadd() - var/list/chosenlist - var/i = 1 - for(var/e in args) - if(i == 1) - if(isobject(e)) - if(istype(e, /list)) - chosenlist = e - i = 2 - else - if(chosenlist) - chosenlist.Add(e) - -// Clone of list.Remove() -/proc/n_listremove() - var/list/chosenlist - var/i = 1 - for(var/e in args) - if(i == 1) - if(isobject(e)) - if(istype(e, /list)) - chosenlist = e - i = 2 - else - if(chosenlist) - chosenlist.Remove(e) - -// Clone of list.len = 0 -/proc/n_listcut(var/list/L, var/start, var/end) - if(!istype(L, /list)) return - return L.Cut(start, end) - -// Clone of list.Swap() -/proc/n_listswap(var/list/L, var/firstindex, var/secondindex) - if(!istype(L, /list)) return - if(L.len >= secondindex && L.len >= firstindex) - return L.Swap(firstindex, secondindex) - -// Clone of list.Insert() -/proc/n_listinsert(var/list/L, var/index, var/element) - if(!istype(L, /list)) return - return L.Insert(index, element) - -// --- Miscellaneous functions --- - -// Clone of sleep() -/proc/delay(var/time) - sleep(time) - -// Clone of rand() -/proc/rand_chance(var/low = 0, var/high) - return rand(low, high) - -// Clone of prob() -/proc/prob_chance(var/chance) - return prob(chance) - -// Merge of list.Find() and findtext() -/proc/smartfind(var/haystack, var/needle, var/start = 1, var/end = 0) - if(haystack && needle) - if(isobject(haystack)) - if(istype(haystack, /list)) - if(length(haystack) >= end && start > 0) - var/list/listhaystack = haystack - return listhaystack.Find(needle, start, end) - - else - if(istext(haystack)) - if(length(haystack) >= end && start > 0) - return findtext(haystack, needle, start, end) - -// Clone of copytext() -/proc/docopytext(var/string, var/start = 1, var/end = 0) - if(istext(string) && isnum(start) && isnum(end)) - if(start > 0) - return copytext(string, start, end) - -// Clone of length() -/proc/smartlength(var/container) - if(container) - if(istype(container, /list) || istext(container)) - return length(container) - return 0 - -// BY DONKIE~ -// String stuff -/proc/n_lower(var/string) - if(istext(string)) - return lowertext(string) - -/proc/n_upper(var/string) - if(istext(string)) - return uppertext(string) - -/proc/time() - return world.time + (12 HOURS) - -/proc/timestamp(var/format = "hh:mm:ss") // Get the game time in text - return time2text(world.time + (10 HOURS), format) // Yes, 10, not 12 hours, for some reason time2text() is being moronic (T-thanks BYOND), and it's adding 2 hours to this, I don't even know either. - -proc/string_explode(var/string, var/separator = "") - if(istext(string) && (istext(separator) || isnull(separator))) - return text2list(string, separator) - -proc/n_repeat(var/string, var/amount) - if(istext(string) && isnum(amount)) - var/i - var/newstring = "" - if(length(newstring)*amount >=1000) - return - for(i=0, i<=amount, i++) - if(i>=1000) - break - newstring = newstring + string - - return newstring - -// I don't know if it's neccesary to make my own proc, but I think I have to to be able to check for istext. -proc/n_str2num(var/string) - if(istext(string)) - return text2num(string) - -// Clamps N between min and max -/proc/n_clamp(var/num, var/min = 0, var/max = 1) - if(isnum(num) && isnum(min) && isnum(max)) - return Clamp(num, min, max) - -// Number shit -proc/n_num2str(var/num) - if(isnum(num)) - return num2text(num) - -// Squareroot -proc/n_sqrt(var/num) - if(isnum(num)) - return sqrt(num) - -// Magnitude of num -proc/n_abs(var/num) - if(isnum(num)) - return abs(num) - -// Round down -proc/n_floor(var/num) - if(isnum(num)) - return round(num) - -// Round up -proc/n_ceil(var/num) - if(isnum(num)) - return round(num)+1 - -// Round to nearest integer -proc/n_round(var/num) - if(isnum(num)) - if(num-round(num)<0.5) - return round(num) - return n_ceil(num) - -// END OF BY DONKIE :( - -/proc/n_sin(var/const/x) - return sin(x) - -/proc/n_cos(var/const/x) - return cos(x) - -/proc/n_asin(var/const/x) - return arcsin(x) - -/proc/n_acos(var/const/x) - return arccos(x) - - -/proc/n_max(...) - return max(arglist(args)) - -/proc/n_min(...) +// Script -> BYOND code procs +#define SCRIPT_MAX_REPLACEMENTS_ALLOWED 200 +// --- List operations (lists known as vectors in n_script) --- + +// Clone of list() +/proc/n_list() + var/list/returnlist = list() + for(var/e in args) + returnlist.Add(e) + return returnlist + +// Clone of pick() +/proc/n_pick() + var/list/finalpick = list() + for(var/e in args) + if(isobject(e)) + if(istype(e, /list)) + var/list/sublist = e + for(var/sube in sublist) + finalpick.Add(sube) + continue + finalpick.Add(e) + + return pick(finalpick) + +// Clone of list[] +/proc/n_listpos(var/list/L, var/pos, var/value) + if(!istype(L, /list)) return + if(isnum(pos)) + if(!value) + if(L.len >= pos && !(pos > L.len)) + return L[pos] + else + if(L.len >= pos && !(pos > L.len)) + L[pos] = value + else if(istext(pos)) + if(!value) + return L[pos] + else + L[pos] = value + +// Clone of list.Copy() +/proc/n_listcopy(var/list/L, var/start, var/end) + if(!istype(L, /list)) return + return L.Copy(start, end) + +// Clone of list.Add() +/proc/n_listadd() + var/list/chosenlist + var/i = 1 + for(var/e in args) + if(i == 1) + if(isobject(e)) + if(istype(e, /list)) + chosenlist = e + i = 2 + else + if(chosenlist) + chosenlist.Add(e) + +// Clone of list.Remove() +/proc/n_listremove() + var/list/chosenlist + var/i = 1 + for(var/e in args) + if(i == 1) + if(isobject(e)) + if(istype(e, /list)) + chosenlist = e + i = 2 + else + if(chosenlist) + chosenlist.Remove(e) + +// Clone of list.len = 0 +/proc/n_listcut(var/list/L, var/start, var/end) + if(!istype(L, /list)) return + return L.Cut(start, end) + +// Clone of list.Swap() +/proc/n_listswap(var/list/L, var/firstindex, var/secondindex) + if(!istype(L, /list)) return + if(L.len >= secondindex && L.len >= firstindex) + return L.Swap(firstindex, secondindex) + +// Clone of list.Insert() +/proc/n_listinsert(var/list/L, var/index, var/element) + if(!istype(L, /list)) return + return L.Insert(index, element) + +// --- Miscellaneous functions --- + +// Clone of sleep() +/proc/delay(var/time) + sleep(time) + +// Clone of rand() +/proc/rand_chance(var/low = 0, var/high) + return rand(low, high) + +// Clone of prob() +/proc/prob_chance(var/chance) + return prob(chance) + +// Merge of list.Find() and findtext() +/proc/smartfind(var/haystack, var/needle, var/start = 1, var/end = 0) + if(haystack && needle) + if(isobject(haystack)) + if(istype(haystack, /list)) + if(length(haystack) >= end && start > 0) + var/list/listhaystack = haystack + return listhaystack.Find(needle, start, end) + + else + if(istext(haystack)) + if(length(haystack) >= end && start > 0) + return findtext(haystack, needle, start, end) + +// Clone of copytext() +/proc/docopytext(var/string, var/start = 1, var/end = 0) + if(istext(string) && isnum(start) && isnum(end)) + if(start > 0) + return copytext(string, start, end) + +// Clone of length() +/proc/smartlength(var/container) + if(container) + if(istype(container, /list) || istext(container)) + return length(container) + return 0 + +// BY DONKIE~ +// String stuff +/proc/n_lower(var/string) + if(istext(string)) + return lowertext(string) + +/proc/n_upper(var/string) + if(istext(string)) + return uppertext(string) + +/proc/time() + return world.time + (12 HOURS) + +/proc/timestamp(var/format = "hh:mm:ss") // Get the game time in text + return time2text(world.time + (10 HOURS), format) // Yes, 10, not 12 hours, for some reason time2text() is being moronic (T-thanks BYOND), and it's adding 2 hours to this, I don't even know either. + +proc/string_explode(var/string, var/separator = "") + if(istext(string) && (istext(separator) || isnull(separator))) + return text2list(string, separator) + +proc/n_repeat(var/string, var/amount) + if(istext(string) && isnum(amount)) + var/i + var/newstring = "" + if(length(newstring)*amount >=1000) + return + for(i=0, i<=amount, i++) + if(i>=1000) + break + newstring = newstring + string + + return newstring + +// I don't know if it's neccesary to make my own proc, but I think I have to to be able to check for istext. +proc/n_str2num(var/string) + if(istext(string)) + return text2num(string) + +// Clamps N between min and max +/proc/n_clamp(var/num, var/min = 0, var/max = 1) + if(isnum(num) && isnum(min) && isnum(max)) + return Clamp(num, min, max) + +// Number shit +proc/n_num2str(var/num) + if(isnum(num)) + return num2text(num) + +// Squareroot +proc/n_sqrt(var/num) + if(isnum(num)) + return sqrt(num) + +// Magnitude of num +proc/n_abs(var/num) + if(isnum(num)) + return abs(num) + +// Round down +proc/n_floor(var/num) + if(isnum(num)) + return round(num) + +// Round up +proc/n_ceil(var/num) + if(isnum(num)) + return round(num)+1 + +// Round to nearest integer +proc/n_round(var/num) + if(isnum(num)) + if(num-round(num)<0.5) + return round(num) + return n_ceil(num) + +// END OF BY DONKIE :( + +/proc/n_sin(var/const/x) + return sin(x) + +/proc/n_cos(var/const/x) + return cos(x) + +/proc/n_asin(var/const/x) + return arcsin(x) + +/proc/n_acos(var/const/x) + return arccos(x) + + +/proc/n_max(...) + return max(arglist(args)) + +/proc/n_min(...) return min(arglist(args)) \ No newline at end of file diff --git a/code/modules/scripting/Interpreter/Evaluation.dm b/code/modules/scripting/Interpreter/Evaluation.dm index 84c255fe9ad..e83e0c214a7 100644 --- a/code/modules/scripting/Interpreter/Evaluation.dm +++ b/code/modules/scripting/Interpreter/Evaluation.dm @@ -1,203 +1,203 @@ -/proc/isobject(x) - return (istype(x, /datum) || istype(x, /list) || istype(x, /savefile) || istype(x, /client) || (x == world)) - -/datum/n_Interpreter/proc/Eval(datum/node/expression/exp) - if(istype(exp, /datum/node/expression/FunctionCall)) - return RunFunction(exp) - - else if(istype(exp, /datum/node/expression/operator)) - return EvalOperator(exp) - - else if(istype(exp, /datum/node/expression/value/literal)) - var/datum/node/expression/value/literal/lit = exp - return lit.value - - else if(istype(exp, /datum/node/expression/value/reference)) - var/datum/node/expression/value/reference/ref = exp - return ref.value - - else if(istype(exp, /datum/node/expression/value/variable)) - var/datum/node/expression/value/variable/v = exp - if(!v.object) - return Eval(GetVariable(v.id.id_name)) - else - var/datum/D - if(istype(v.object, /datum/node/identifier)) - D = GetVariable(v.object:id_name) - else - D = v.object - - D = Eval(D) - if(!isobject(D)) - return null - - if(!D.vars.Find(v.id.id_name)) - RaiseError(new/datum/runtimeError/UndefinedVariable("[v.object.ToString()].[v.id.id_name]")) - return null - - return Eval(D.vars[v.id.id_name]) - - else if(istype(exp, /datum/node/expression)) - RaiseError(new/datum/runtimeError/UnknownInstruction()) - - else - return exp - -/datum/n_Interpreter/proc/EvalOperator(datum/node/expression/operator/exp) - if(istype(exp, /datum/node/expression/operator/binary)) - var/datum/node/expression/operator/binary/bin = exp - try // This way we can forgo sanity in the actual evaluation (other than divide by 0). - switch(bin.type) - if(/datum/node/expression/operator/binary/Equal) - return Equal(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/NotEqual) - return NotEqual(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Greater) - return Greater(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Less) - return Less(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/GreaterOrEqual) - return GreaterOrEqual(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/LessOrEqual) - return LessOrEqual(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/LogicalAnd) - return LogicalAnd(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/LogicalOr) - return LogicalOr(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/LogicalXor) - return LogicalXor(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/BitwiseAnd) - return BitwiseAnd(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/BitwiseOr) - return BitwiseOr(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/BitwiseXor) - return BitwiseXor(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Add) - return Add(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Subtract) - return Subtract(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Multiply) - return Multiply(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Divide) - return Divide(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Power) - return Power(Eval(bin.exp), Eval(bin.exp2)) - - if(/datum/node/expression/operator/binary/Modulo) - return Modulo(Eval(bin.exp), Eval(bin.exp2)) - - else - RaiseError(new/datum/runtimeError/UnknownInstruction()) - - catch - RaiseError(new/datum/runtimeError/TypeMismatch(bin.token, Eval(bin.exp), Eval(bin.exp2))) - - else - try - switch(exp.type) - if(/datum/node/expression/operator/unary/Minus) - return Minus(Eval(exp.exp)) - - if(/datum/node/expression/operator/unary/LogicalNot) - return LogicalNot(Eval(exp.exp)) - - if(/datum/node/expression/operator/unary/BitwiseNot) - return BitwiseNot(Eval(exp.exp)) - - if(/datum/node/expression/operator/unary/group) - return Eval(exp.exp) - - else - RaiseError(new/datum/runtimeError/UnknownInstruction()) - catch - RaiseError(new/datum/runtimeError/TypeMismatch/unary(exp.token, Eval(exp.exp))) - -//Binary// -//Comparison operators -/datum/n_Interpreter/proc/Equal(a, b) - return a == b - -/datum/n_Interpreter/proc/NotEqual(a, b) - return a != b //LogicalNot(Equal(a, b)) - -/datum/n_Interpreter/proc/Greater(a, b) - return a > b - -/datum/n_Interpreter/proc/Less(a, b) - return a < b - -/datum/n_Interpreter/proc/GreaterOrEqual(a, b) - return a >= b - -/datum/n_Interpreter/proc/LessOrEqual(a, b) - return a <= b - -//Logical Operators -/datum/n_Interpreter/proc/LogicalAnd(a, b) - return a && b - -/datum/n_Interpreter/proc/LogicalOr(a, b) - return a || b - -/datum/n_Interpreter/proc/LogicalXor(a, b) - return (a || b) && !(a && b) - -//Bitwise Operators -/datum/n_Interpreter/proc/BitwiseAnd(a, b) - return a & b - -/datum/n_Interpreter/proc/BitwiseOr(a, b) - return a | b - -/datum/n_Interpreter/proc/BitwiseXor(a, b) - return a ^ b - -//Arithmetic Operators -/datum/n_Interpreter/proc/Add(a, b) - return a + b - -/datum/n_Interpreter/proc/Subtract(a, b) - return a - b - -/datum/n_Interpreter/proc/Divide(a, b) - if(b == 0) - RaiseError(new/datum/runtimeError/DivisionByZero()) - return null - - return a / b - -/datum/n_Interpreter/proc/Multiply(a, b) - return a * b - -/datum/n_Interpreter/proc/Modulo(a, b) - - return a % b - -/datum/n_Interpreter/proc/Power(a, b) - return a ** b - -//Unary// -/datum/n_Interpreter/proc/Minus(a) - return -a - -/datum/n_Interpreter/proc/LogicalNot(a) - return !a - -/datum/n_Interpreter/proc/BitwiseNot(a) - return ~a +/proc/isobject(x) + return (istype(x, /datum) || istype(x, /list) || istype(x, /savefile) || istype(x, /client) || (x == world)) + +/datum/n_Interpreter/proc/Eval(datum/node/expression/exp) + if(istype(exp, /datum/node/expression/FunctionCall)) + return RunFunction(exp) + + else if(istype(exp, /datum/node/expression/operator)) + return EvalOperator(exp) + + else if(istype(exp, /datum/node/expression/value/literal)) + var/datum/node/expression/value/literal/lit = exp + return lit.value + + else if(istype(exp, /datum/node/expression/value/reference)) + var/datum/node/expression/value/reference/ref = exp + return ref.value + + else if(istype(exp, /datum/node/expression/value/variable)) + var/datum/node/expression/value/variable/v = exp + if(!v.object) + return Eval(GetVariable(v.id.id_name)) + else + var/datum/D + if(istype(v.object, /datum/node/identifier)) + D = GetVariable(v.object:id_name) + else + D = v.object + + D = Eval(D) + if(!isobject(D)) + return null + + if(!D.vars.Find(v.id.id_name)) + RaiseError(new/datum/runtimeError/UndefinedVariable("[v.object.ToString()].[v.id.id_name]")) + return null + + return Eval(D.vars[v.id.id_name]) + + else if(istype(exp, /datum/node/expression)) + RaiseError(new/datum/runtimeError/UnknownInstruction()) + + else + return exp + +/datum/n_Interpreter/proc/EvalOperator(datum/node/expression/operator/exp) + if(istype(exp, /datum/node/expression/operator/binary)) + var/datum/node/expression/operator/binary/bin = exp + try // This way we can forgo sanity in the actual evaluation (other than divide by 0). + switch(bin.type) + if(/datum/node/expression/operator/binary/Equal) + return Equal(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/NotEqual) + return NotEqual(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Greater) + return Greater(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Less) + return Less(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/GreaterOrEqual) + return GreaterOrEqual(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/LessOrEqual) + return LessOrEqual(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/LogicalAnd) + return LogicalAnd(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/LogicalOr) + return LogicalOr(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/LogicalXor) + return LogicalXor(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/BitwiseAnd) + return BitwiseAnd(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/BitwiseOr) + return BitwiseOr(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/BitwiseXor) + return BitwiseXor(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Add) + return Add(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Subtract) + return Subtract(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Multiply) + return Multiply(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Divide) + return Divide(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Power) + return Power(Eval(bin.exp), Eval(bin.exp2)) + + if(/datum/node/expression/operator/binary/Modulo) + return Modulo(Eval(bin.exp), Eval(bin.exp2)) + + else + RaiseError(new/datum/runtimeError/UnknownInstruction()) + + catch + RaiseError(new/datum/runtimeError/TypeMismatch(bin.token, Eval(bin.exp), Eval(bin.exp2))) + + else + try + switch(exp.type) + if(/datum/node/expression/operator/unary/Minus) + return Minus(Eval(exp.exp)) + + if(/datum/node/expression/operator/unary/LogicalNot) + return LogicalNot(Eval(exp.exp)) + + if(/datum/node/expression/operator/unary/BitwiseNot) + return BitwiseNot(Eval(exp.exp)) + + if(/datum/node/expression/operator/unary/group) + return Eval(exp.exp) + + else + RaiseError(new/datum/runtimeError/UnknownInstruction()) + catch + RaiseError(new/datum/runtimeError/TypeMismatch/unary(exp.token, Eval(exp.exp))) + +//Binary// +//Comparison operators +/datum/n_Interpreter/proc/Equal(a, b) + return a == b + +/datum/n_Interpreter/proc/NotEqual(a, b) + return a != b //LogicalNot(Equal(a, b)) + +/datum/n_Interpreter/proc/Greater(a, b) + return a > b + +/datum/n_Interpreter/proc/Less(a, b) + return a < b + +/datum/n_Interpreter/proc/GreaterOrEqual(a, b) + return a >= b + +/datum/n_Interpreter/proc/LessOrEqual(a, b) + return a <= b + +//Logical Operators +/datum/n_Interpreter/proc/LogicalAnd(a, b) + return a && b + +/datum/n_Interpreter/proc/LogicalOr(a, b) + return a || b + +/datum/n_Interpreter/proc/LogicalXor(a, b) + return (a || b) && !(a && b) + +//Bitwise Operators +/datum/n_Interpreter/proc/BitwiseAnd(a, b) + return a & b + +/datum/n_Interpreter/proc/BitwiseOr(a, b) + return a | b + +/datum/n_Interpreter/proc/BitwiseXor(a, b) + return a ^ b + +//Arithmetic Operators +/datum/n_Interpreter/proc/Add(a, b) + return a + b + +/datum/n_Interpreter/proc/Subtract(a, b) + return a - b + +/datum/n_Interpreter/proc/Divide(a, b) + if(b == 0) + RaiseError(new/datum/runtimeError/DivisionByZero()) + return null + + return a / b + +/datum/n_Interpreter/proc/Multiply(a, b) + return a * b + +/datum/n_Interpreter/proc/Modulo(a, b) + + return a % b + +/datum/n_Interpreter/proc/Power(a, b) + return a ** b + +//Unary// +/datum/n_Interpreter/proc/Minus(a) + return -a + +/datum/n_Interpreter/proc/LogicalNot(a) + return !a + +/datum/n_Interpreter/proc/BitwiseNot(a) + return ~a diff --git a/code/modules/scripting/Interpreter/Interaction.dm b/code/modules/scripting/Interpreter/Interaction.dm index ffcf8f716d8..fcc0925ab2e 100644 --- a/code/modules/scripting/Interpreter/Interaction.dm +++ b/code/modules/scripting/Interpreter/Interaction.dm @@ -1,157 +1,157 @@ -/* - File: Interpreter (Public) - Contains methods for interacting with the interpreter. -*/ -/* - Class: n_Interpreter - Procedures allowing for interaction with the script that is being run by the interpreter object. -*/ - -/* - Proc: Load - Loads a 'compiled' script into memory. - - Parameters: - program - A object which represents the script's global scope. -*/ -/datum/n_Interpreter/proc/Load(var/datum/node/BlockDefinition/GlobalBlock/program) - ASSERT(program) - src.program = program - CreateGlobalScope() - alertadmins = 0 // reset admin alerts - -/* -Proc: Run -Runs the script. -*/ -/datum/n_Interpreter/proc/Run() - cur_recursion = 0 // reset recursion - cur_statements = 0 // reset CPU tracking - - ASSERT(src.program) - RunBlock(src.program) - -/* -Proc: SetVar -Defines a global variable for the duration of the next execution of a script. - -Notes: -This differs from in that variables set using this procedure only last for the session, -while those defined from the block object persist if it is ran multiple times. - -See Also: -- -*/ -/datum/n_Interpreter/proc/SetVar(name, value) - if(!istext(name)) - //CRASH("Invalid variable name") - return - - AssignVariable(name, value) - -/* -Proc: SetProc -Defines a procedure to be available to the script. - -Parameters: -name - The name of the procedure as exposed to the script. -path - The typepath of a proc to be called when the function call is read by the interpreter, or, if object is specified, a string representing the procedure's name. -object - (Optional) An object which will the be target of a function call. -params - Only required if object is not null, a list of the names of parameters the proc takes. -*/ -/datum/n_Interpreter/proc/SetProc(name, path, object = null, list/params = null) - if(!istext(name)) - //CRASH("Invalid function name") - return - - if(!object) - globalScope.functions[name] = path - - else - var/datum/node/statement/FunctionDefinition/S = new() - S.func_name = name - S.parameters = params - S.block = new() - S.block.SetVar("src", object) - var/datum/node/expression/FunctionCall/C = new() - C.func_name = path - C.object = new("src") - for(var/p in params) - C.parameters += new/datum/node/expression/value/variable(p) - - var/datum/node/statement/ReturnStatement/R = new() - R.value = C - S.block.statements += R - globalScope.functions[name] = S -/* -Proc: VarExists -Checks whether a global variable with the specified name exists. -*/ -/datum/n_Interpreter/proc/VarExists(name) - return globalScope.variables.Find(name) //convert to 1/0 first? - -/* -Proc: ProcExists -Checks whether a global function with the specified name exists. -*/ -/datum/n_Interpreter/proc/ProcExists(name) - return globalScope.functions.Find(name) - -/* -Proc: GetVar -Returns the value of a global variable in the script. Remember to ensure that the variable exists before calling this procedure. - -See Also: -- -*/ -/datum/n_Interpreter/proc/GetVar(name) - if(!VarExists(name)) - //CRASH("No variable named '[name]'.") - return - var/x = globalScope.variables[name] - return Eval(x) - -/* -Proc: GetCleanVar -Returns the value of a global variable in the script and cleans it (sanitizes). -*/ - -/datum/n_Interpreter/proc/GetCleanVar(name, compare) - var/x = GetVar(name) - if(istext(x) && compare && x != compare) // Was changed - x = sanitize(x) - return x - -/* -Proc: CallProc -Calls a global function defined in the script and, amazingly enough, returns its return value. Remember to ensure that the function -exists before calling this procedure. - -See Also: -- -*/ -/datum/n_Interpreter/proc/CallProc(name, params[]=null) - if(!ProcExists(name)) - //CRASH("No function named '[name]'.") - return - - var/datum/node/statement/FunctionDefinition/func = globalScope.functions[name] - - if(istype(func)) - var/datum/node/statement/FunctionCall/stmt = new - stmt.func_name = func.func_name - stmt.parameters = params - return RunFunction(stmt) - - else - return call(func)(arglist(params)) - //CRASH("Unknown function type '[name]'.") - -/* -Event: HandleError -Called when the interpreter throws a runtime error. - -See Also: -- -*/ -/datum/n_Interpreter/proc/HandleError(var/datum/runtimeError/e) +/* + File: Interpreter (Public) + Contains methods for interacting with the interpreter. +*/ +/* + Class: n_Interpreter + Procedures allowing for interaction with the script that is being run by the interpreter object. +*/ + +/* + Proc: Load + Loads a 'compiled' script into memory. + + Parameters: + program - A object which represents the script's global scope. +*/ +/datum/n_Interpreter/proc/Load(var/datum/node/BlockDefinition/GlobalBlock/program) + ASSERT(program) + src.program = program + CreateGlobalScope() + alertadmins = 0 // reset admin alerts + +/* +Proc: Run +Runs the script. +*/ +/datum/n_Interpreter/proc/Run() + cur_recursion = 0 // reset recursion + cur_statements = 0 // reset CPU tracking + + ASSERT(src.program) + RunBlock(src.program) + +/* +Proc: SetVar +Defines a global variable for the duration of the next execution of a script. + +Notes: +This differs from in that variables set using this procedure only last for the session, +while those defined from the block object persist if it is ran multiple times. + +See Also: +- +*/ +/datum/n_Interpreter/proc/SetVar(name, value) + if(!istext(name)) + //CRASH("Invalid variable name") + return + + AssignVariable(name, value) + +/* +Proc: SetProc +Defines a procedure to be available to the script. + +Parameters: +name - The name of the procedure as exposed to the script. +path - The typepath of a proc to be called when the function call is read by the interpreter, or, if object is specified, a string representing the procedure's name. +object - (Optional) An object which will the be target of a function call. +params - Only required if object is not null, a list of the names of parameters the proc takes. +*/ +/datum/n_Interpreter/proc/SetProc(name, path, object = null, list/params = null) + if(!istext(name)) + //CRASH("Invalid function name") + return + + if(!object) + globalScope.functions[name] = path + + else + var/datum/node/statement/FunctionDefinition/S = new() + S.func_name = name + S.parameters = params + S.block = new() + S.block.SetVar("src", object) + var/datum/node/expression/FunctionCall/C = new() + C.func_name = path + C.object = new("src") + for(var/p in params) + C.parameters += new/datum/node/expression/value/variable(p) + + var/datum/node/statement/ReturnStatement/R = new() + R.value = C + S.block.statements += R + globalScope.functions[name] = S +/* +Proc: VarExists +Checks whether a global variable with the specified name exists. +*/ +/datum/n_Interpreter/proc/VarExists(name) + return globalScope.variables.Find(name) //convert to 1/0 first? + +/* +Proc: ProcExists +Checks whether a global function with the specified name exists. +*/ +/datum/n_Interpreter/proc/ProcExists(name) + return globalScope.functions.Find(name) + +/* +Proc: GetVar +Returns the value of a global variable in the script. Remember to ensure that the variable exists before calling this procedure. + +See Also: +- +*/ +/datum/n_Interpreter/proc/GetVar(name) + if(!VarExists(name)) + //CRASH("No variable named '[name]'.") + return + var/x = globalScope.variables[name] + return Eval(x) + +/* +Proc: GetCleanVar +Returns the value of a global variable in the script and cleans it (sanitizes). +*/ + +/datum/n_Interpreter/proc/GetCleanVar(name, compare) + var/x = GetVar(name) + if(istext(x) && compare && x != compare) // Was changed + x = sanitize(x) + return x + +/* +Proc: CallProc +Calls a global function defined in the script and, amazingly enough, returns its return value. Remember to ensure that the function +exists before calling this procedure. + +See Also: +- +*/ +/datum/n_Interpreter/proc/CallProc(name, params[]=null) + if(!ProcExists(name)) + //CRASH("No function named '[name]'.") + return + + var/datum/node/statement/FunctionDefinition/func = globalScope.functions[name] + + if(istype(func)) + var/datum/node/statement/FunctionCall/stmt = new + stmt.func_name = func.func_name + stmt.parameters = params + return RunFunction(stmt) + + else + return call(func)(arglist(params)) + //CRASH("Unknown function type '[name]'.") + +/* +Event: HandleError +Called when the interpreter throws a runtime error. + +See Also: +- +*/ +/datum/n_Interpreter/proc/HandleError(var/datum/runtimeError/e) diff --git a/code/modules/scripting/Interpreter/Interpreter.dm b/code/modules/scripting/Interpreter/Interpreter.dm index bd1e6dbeb97..572993bee4c 100644 --- a/code/modules/scripting/Interpreter/Interpreter.dm +++ b/code/modules/scripting/Interpreter/Interpreter.dm @@ -1,378 +1,378 @@ -/* - File: Interpreter (Internal) -*/ -/* - Class: n_Interpreter -*/ -/* - Macros: Status Macros - RETURNING - Indicates that the current function is returning a value. - BREAKING - Indicates that the current loop is being terminated. - CONTINUING - Indicates that the rest of the current iteration of a loop is being skipped. -*/ -#define RETURNING 1 -#define BREAKING 2 -#define CONTINUING 4 - -/datum/n_Interpreter - var/datum/scope/curScope - var/datum/scope/globalScope - - var/datum/node/BlockDefinition/program - var/datum/node/statement/FunctionDefinition/curFunction - var/datum/stack/scopes = new() - var/datum/stack/functions = new() - - var/datum/container // associated container for interpeter -/* - Var: status - A variable indicating that the rest of the current block should be skipped. This may be set to any combination of . -*/ - var/status = 0 - var/returnVal - - var/max_statements = 900 // maximum amount of statements that can be called in one execution. this is to prevent massive crashes and exploitation - var/cur_statements = 0 // current amount of statements called - var/alertadmins = 0 // set to 1 if the admins shouldn't be notified of anymore issues - var/max_iterations = 100 // max number of uninterrupted loops possible - var/max_recursion = 10 // max recursions without returning anything (or completing the code block) - var/cur_recursion = 0 // current amount of recursion -/* - Var: persist - If 0, global variables will be reset after Run() finishes. -*/ - var/persist = 1 - var/paused = 0 - -/* - Constructor: New - Calls with the given parameters. -*/ -/datum/n_Interpreter/New(datum/node/BlockDefinition/GlobalBlock/program = null) - . = ..() - if(program) - Load(program) - -/* - Set ourselves to Garbage Collect -*/ -/datum/n_Interpreter/proc/GC() - ..() - container = null - -/* - Proc: RaiseError - Raises a runtime error. -*/ -/datum/n_Interpreter/proc/RaiseError(datum/runtimeError/e) - e.stack = functions.Copy() - e.stack.Push(curFunction) - src.HandleError(e) - -/datum/n_Interpreter/proc/CreateScope(datum/node/BlockDefinition/B) - var/datum/scope/S = new(B, curScope) - scopes.Push(curScope) - curScope = S - return S - -/datum/n_Interpreter/proc/CreateGlobalScope() - scopes.Clear() - var/datum/scope/S = new(program, null) - globalScope = S - return S - -/* -Proc: AlertAdmins -Alerts the admins of a script that is bad. -*/ -/datum/n_Interpreter/proc/AlertAdmins() - if(container && !alertadmins) - if(istype(container, /datum/TCS_Compiler)) - var/datum/TCS_Compiler/Compiler = container - var/obj/machinery/telecomms/server/Holder = Compiler.Holder - var/message = "Potential crash-inducing NTSL script detected at telecommunications server [Compiler.Holder] ([Holder.x], [Holder.y], [Holder.z])." - - alertadmins = 1 - message_admins(message, 1) -/* -Proc: RunBlock -Runs each statement in a block of code. -*/ -/datum/n_Interpreter/proc/RunBlock(var/datum/node/BlockDefinition/Block, var/datum/scope/scope = null) - var/is_global = istype(Block, /datum/node/BlockDefinition/GlobalBlock) - if(!is_global) - if(scope) - curScope = scope - else - CreateScope(Block) - else - if(!persist) - CreateGlobalScope() - - curScope = globalScope - - if(cur_statements < max_statements) - for(var/datum/node/statement/S in Block.statements) - while(paused) sleep(10) - - cur_statements++ - if(cur_statements >= max_statements) - RaiseError(new/datum/runtimeError/MaxCPU()) - AlertAdmins() - break - - if(istype(S, /datum/node/statement/VariableAssignment)) - var/datum/node/statement/VariableAssignment/stmt = S - var/name = stmt.var_name.id_name - - if(!stmt.object) - // Below we assign the variable first to null if it doesn't already exist. - // This is necessary for assignments like +=, and when the variable is used in a function - // If the variable already exists in a different block, then AssignVariable will automatically use that one. - if(!IsVariableAccessible(name)) - AssignVariable(name, null) - - AssignVariable(name, Eval(stmt.value)) - else - var/datum/D = Eval(GetVariable(stmt.object.id_name)) - if(!D) - return - - D.vars[stmt.var_name.id_name] = Eval(stmt.value) - - else if(istype(S, /datum/node/statement/VariableDeclaration)) - //VariableDeclaration nodes are used to forcibly declare a local variable so that one in a higher scope isn't used by default. - var/datum/node/statement/VariableDeclaration/dec=S - if(!dec.object) - AssignVariable(dec.var_name.id_name, null, curScope) - else - var/datum/D = Eval(GetVariable(dec.object.id_name)) - if(!D) - return - - D.vars[dec.var_name.id_name] = null - - else if(istype(S, /datum/node/statement/FunctionCall)) - RunFunction(S) - - else if(istype(S, /datum/node/statement/FunctionDefinition)) - //do nothing - - else if(istype(S, /datum/node/statement/WhileLoop)) - RunWhile(S) - - else if(istype(S, /datum/node/statement/IfStatement)) - RunIf(S) - - else if(istype(S, /datum/node/statement/ReturnStatement)) - if(!curFunction) - RaiseError(new/datum/runtimeError/UnexpectedReturn()) - continue - - status |= RETURNING - returnVal = Eval(S:value) - break - - else if(istype(S, /datum/node/statement/BreakStatement)) - status |= BREAKING - break - - else if(istype(S, /datum/node/statement/ContinueStatement)) - status |= CONTINUING - break - - else - RaiseError(new/datum/runtimeError/UnknownInstruction()) - - if(status) - break - - curScope = scopes.Pop() - -/* -Proc: RunFunction -Runs a function block or a proc with the arguments specified in the script. -*/ -/datum/n_Interpreter/proc/RunFunction(var/datum/node/statement/FunctionCall/stmt) - //Note that anywhere /datum/node/statement/FunctionCall/stmt is used so may /datum/node/expression/FunctionCall - - // If recursion gets too high (max 50 nested functions) throw an error - if(cur_recursion >= max_recursion) - AlertAdmins() - RaiseError(new/datum/runtimeError/RecursionLimitReached()) - return 0 - - var/datum/node/statement/FunctionDefinition/def - if(!stmt.object) //A scope's function is being called, stmt.object is null - def = GetFunction(stmt.func_name) - - else if(istype(stmt.object)) //A method of an object exposed as a variable is being called, stmt.object is a /node/identifier - var/O = GetVariable(stmt.object.id_name) //Gets a reference to the object which is the target of the function call. - if(!O) return //Error already thrown in GetVariable() - def = Eval(O) - - if(!def) - return - - cur_recursion++ // add recursion - if(istype(def)) - if(curFunction) functions.Push(curFunction) - var/datum/scope/S = CreateScope(def.block) - - for(var/i = 1 to def.parameters.len) - var/val - if(stmt.parameters.len >= i) - val = stmt.parameters[i] - //else - // unspecified param - AssignVariable(def.parameters[i], new/datum/node/expression/value/literal(Eval(val)), S) - - curFunction = stmt - RunBlock(def.block, S) - - //Handle return value - . = returnVal - status &= ~RETURNING - returnVal = null - curFunction = functions.Pop() - cur_recursion-- - - else - cur_recursion-- - var/list/params = new - for(var/datum/node/expression/P in stmt.parameters) - params += list(Eval(P)) - - if(isobject(def)) //def is an object which is the target of a function call - if(!hascall(def, stmt.func_name)) - RaiseError(new/datum/runtimeError/UndefinedFunction("[stmt.object.id_name].[stmt.func_name]")) - return - - return call(def, stmt.func_name)(arglist(params)) - - else //def is a path to a global proc - return call(def)(arglist(params)) - //else - // RaiseError(new/runtimeError/UnknownInstruction()) - -/* -Proc: RunIf -Checks a condition and runs either the if block or else block. -*/ -/datum/n_Interpreter/proc/RunIf(var/datum/node/statement/IfStatement/stmt) - if(!stmt.skip) - if(Eval(stmt.cond)) - RunBlock(stmt.block) - // Loop through the if else chain and tell them to be skipped. - var/datum/node/statement/IfStatement/i = stmt.else_if - var/fail_safe = 800 - - while(i && fail_safe) - fail_safe -= 1 - i.skip = 1 - i = i.else_if - - else if(stmt.else_block) - RunBlock(stmt.else_block) - - // We don't need to skip you anymore. - stmt.skip = 0 - -/* -Proc: RunWhile -Runs a while loop. -*/ - -/datum/n_Interpreter/proc/RunWhile(var/datum/node/statement/WhileLoop/stmt) - var/i = 1 - while(Eval(stmt.cond) && Iterate(stmt.block, i++)) - continue - - status &= ~BREAKING - -/* -Proc:Iterate -Runs a single iteration of a loop. Returns a value indicating whether or not to continue looping. -*/ - -/datum/n_Interpreter/proc/Iterate(var/datum/node/BlockDefinition/block, count) - RunBlock(block) - if(max_iterations > 0 && count >= max_iterations) - RaiseError(new/datum/runtimeError/IterationLimitReached()) - return 0 - - if(status & (BREAKING|RETURNING)) - return 0 - - status &= ~CONTINUING - return 1 - -/* -Proc: GetFunction -Finds a function in an accessible scope with the given name. Returns a . -*/ - -/datum/n_Interpreter/proc/GetFunction(name) - var/datum/scope/S = curScope - while(S) - if(S.functions.Find(name)) - return S.functions[name] - S = S.parent - - RaiseError(new/datum/runtimeError/UndefinedFunction(name)) - -/* -Proc: GetVariable -Finds a variable in an accessible scope and returns its value. -*/ - -/datum/n_Interpreter/proc/GetVariable(name) - var/datum/scope/S = curScope - while(S) - if(S.variables.Find(name)) - return S.variables[name] - S = S.parent - - RaiseError(new/datum/runtimeError/UndefinedVariable(name)) - -/datum/n_Interpreter/proc/GetVariableScope(name) //needed for when you reassign a variable in a higher scope - var/datum/scope/S = curScope - while(S) - if(S.variables.Find(name)) - return S - - S = S.parent - - -/datum/n_Interpreter/proc/IsVariableAccessible(name) - var/datum/scope/S = curScope - while(S) - if(S.variables.Find(name)) - return TRUE - S = S.parent - - return FALSE - - -/* -Proc: AssignVariable -Assigns a value to a variable in a specific block. - -Parameters: -name - The name of the variable to assign. -value - The value to assign to it. -S - The scope the variable resides in. If it is null, a scope with the variable already existing is found. If no scopes have a variable of the given name, the current scope is used. -*/ - -/datum/n_Interpreter/proc/AssignVariable(name, datum/node/expression/value, var/datum/scope/S = null) - if(!S) S = GetVariableScope(name) - if(!S) S = curScope - if(!S) S = globalScope - - ASSERT(istype(S)) - if(istext(value) || isnum(value) || isnull(value)) value = new/datum/node/expression/value/literal(value) - else if(!istype(value) && isobject(value)) value = new/datum/node/expression/value/reference(value) - //TODO: check for invalid name - S.variables["[name]"] = value - - +/* + File: Interpreter (Internal) +*/ +/* + Class: n_Interpreter +*/ +/* + Macros: Status Macros + RETURNING - Indicates that the current function is returning a value. + BREAKING - Indicates that the current loop is being terminated. + CONTINUING - Indicates that the rest of the current iteration of a loop is being skipped. +*/ +#define RETURNING 1 +#define BREAKING 2 +#define CONTINUING 4 + +/datum/n_Interpreter + var/datum/scope/curScope + var/datum/scope/globalScope + + var/datum/node/BlockDefinition/program + var/datum/node/statement/FunctionDefinition/curFunction + var/datum/stack/scopes = new() + var/datum/stack/functions = new() + + var/datum/container // associated container for interpeter +/* + Var: status + A variable indicating that the rest of the current block should be skipped. This may be set to any combination of . +*/ + var/status = 0 + var/returnVal + + var/max_statements = 900 // maximum amount of statements that can be called in one execution. this is to prevent massive crashes and exploitation + var/cur_statements = 0 // current amount of statements called + var/alertadmins = 0 // set to 1 if the admins shouldn't be notified of anymore issues + var/max_iterations = 100 // max number of uninterrupted loops possible + var/max_recursion = 10 // max recursions without returning anything (or completing the code block) + var/cur_recursion = 0 // current amount of recursion +/* + Var: persist + If 0, global variables will be reset after Run() finishes. +*/ + var/persist = 1 + var/paused = 0 + +/* + Constructor: New + Calls with the given parameters. +*/ +/datum/n_Interpreter/New(datum/node/BlockDefinition/GlobalBlock/program = null) + . = ..() + if(program) + Load(program) + +/* + Set ourselves to Garbage Collect +*/ +/datum/n_Interpreter/proc/GC() + ..() + container = null + +/* + Proc: RaiseError + Raises a runtime error. +*/ +/datum/n_Interpreter/proc/RaiseError(datum/runtimeError/e) + e.stack = functions.Copy() + e.stack.Push(curFunction) + src.HandleError(e) + +/datum/n_Interpreter/proc/CreateScope(datum/node/BlockDefinition/B) + var/datum/scope/S = new(B, curScope) + scopes.Push(curScope) + curScope = S + return S + +/datum/n_Interpreter/proc/CreateGlobalScope() + scopes.Clear() + var/datum/scope/S = new(program, null) + globalScope = S + return S + +/* +Proc: AlertAdmins +Alerts the admins of a script that is bad. +*/ +/datum/n_Interpreter/proc/AlertAdmins() + if(container && !alertadmins) + if(istype(container, /datum/TCS_Compiler)) + var/datum/TCS_Compiler/Compiler = container + var/obj/machinery/telecomms/server/Holder = Compiler.Holder + var/message = "Potential crash-inducing NTSL script detected at telecommunications server [Compiler.Holder] ([Holder.x], [Holder.y], [Holder.z])." + + alertadmins = 1 + message_admins(message, 1) +/* +Proc: RunBlock +Runs each statement in a block of code. +*/ +/datum/n_Interpreter/proc/RunBlock(var/datum/node/BlockDefinition/Block, var/datum/scope/scope = null) + var/is_global = istype(Block, /datum/node/BlockDefinition/GlobalBlock) + if(!is_global) + if(scope) + curScope = scope + else + CreateScope(Block) + else + if(!persist) + CreateGlobalScope() + + curScope = globalScope + + if(cur_statements < max_statements) + for(var/datum/node/statement/S in Block.statements) + while(paused) sleep(10) + + cur_statements++ + if(cur_statements >= max_statements) + RaiseError(new/datum/runtimeError/MaxCPU()) + AlertAdmins() + break + + if(istype(S, /datum/node/statement/VariableAssignment)) + var/datum/node/statement/VariableAssignment/stmt = S + var/name = stmt.var_name.id_name + + if(!stmt.object) + // Below we assign the variable first to null if it doesn't already exist. + // This is necessary for assignments like +=, and when the variable is used in a function + // If the variable already exists in a different block, then AssignVariable will automatically use that one. + if(!IsVariableAccessible(name)) + AssignVariable(name, null) + + AssignVariable(name, Eval(stmt.value)) + else + var/datum/D = Eval(GetVariable(stmt.object.id_name)) + if(!D) + return + + D.vars[stmt.var_name.id_name] = Eval(stmt.value) + + else if(istype(S, /datum/node/statement/VariableDeclaration)) + //VariableDeclaration nodes are used to forcibly declare a local variable so that one in a higher scope isn't used by default. + var/datum/node/statement/VariableDeclaration/dec=S + if(!dec.object) + AssignVariable(dec.var_name.id_name, null, curScope) + else + var/datum/D = Eval(GetVariable(dec.object.id_name)) + if(!D) + return + + D.vars[dec.var_name.id_name] = null + + else if(istype(S, /datum/node/statement/FunctionCall)) + RunFunction(S) + + else if(istype(S, /datum/node/statement/FunctionDefinition)) + //do nothing + + else if(istype(S, /datum/node/statement/WhileLoop)) + RunWhile(S) + + else if(istype(S, /datum/node/statement/IfStatement)) + RunIf(S) + + else if(istype(S, /datum/node/statement/ReturnStatement)) + if(!curFunction) + RaiseError(new/datum/runtimeError/UnexpectedReturn()) + continue + + status |= RETURNING + returnVal = Eval(S:value) + break + + else if(istype(S, /datum/node/statement/BreakStatement)) + status |= BREAKING + break + + else if(istype(S, /datum/node/statement/ContinueStatement)) + status |= CONTINUING + break + + else + RaiseError(new/datum/runtimeError/UnknownInstruction()) + + if(status) + break + + curScope = scopes.Pop() + +/* +Proc: RunFunction +Runs a function block or a proc with the arguments specified in the script. +*/ +/datum/n_Interpreter/proc/RunFunction(var/datum/node/statement/FunctionCall/stmt) + //Note that anywhere /datum/node/statement/FunctionCall/stmt is used so may /datum/node/expression/FunctionCall + + // If recursion gets too high (max 50 nested functions) throw an error + if(cur_recursion >= max_recursion) + AlertAdmins() + RaiseError(new/datum/runtimeError/RecursionLimitReached()) + return 0 + + var/datum/node/statement/FunctionDefinition/def + if(!stmt.object) //A scope's function is being called, stmt.object is null + def = GetFunction(stmt.func_name) + + else if(istype(stmt.object)) //A method of an object exposed as a variable is being called, stmt.object is a /node/identifier + var/O = GetVariable(stmt.object.id_name) //Gets a reference to the object which is the target of the function call. + if(!O) return //Error already thrown in GetVariable() + def = Eval(O) + + if(!def) + return + + cur_recursion++ // add recursion + if(istype(def)) + if(curFunction) functions.Push(curFunction) + var/datum/scope/S = CreateScope(def.block) + + for(var/i = 1 to def.parameters.len) + var/val + if(stmt.parameters.len >= i) + val = stmt.parameters[i] + //else + // unspecified param + AssignVariable(def.parameters[i], new/datum/node/expression/value/literal(Eval(val)), S) + + curFunction = stmt + RunBlock(def.block, S) + + //Handle return value + . = returnVal + status &= ~RETURNING + returnVal = null + curFunction = functions.Pop() + cur_recursion-- + + else + cur_recursion-- + var/list/params = new + for(var/datum/node/expression/P in stmt.parameters) + params += list(Eval(P)) + + if(isobject(def)) //def is an object which is the target of a function call + if(!hascall(def, stmt.func_name)) + RaiseError(new/datum/runtimeError/UndefinedFunction("[stmt.object.id_name].[stmt.func_name]")) + return + + return call(def, stmt.func_name)(arglist(params)) + + else //def is a path to a global proc + return call(def)(arglist(params)) + //else + // RaiseError(new/runtimeError/UnknownInstruction()) + +/* +Proc: RunIf +Checks a condition and runs either the if block or else block. +*/ +/datum/n_Interpreter/proc/RunIf(var/datum/node/statement/IfStatement/stmt) + if(!stmt.skip) + if(Eval(stmt.cond)) + RunBlock(stmt.block) + // Loop through the if else chain and tell them to be skipped. + var/datum/node/statement/IfStatement/i = stmt.else_if + var/fail_safe = 800 + + while(i && fail_safe) + fail_safe -= 1 + i.skip = 1 + i = i.else_if + + else if(stmt.else_block) + RunBlock(stmt.else_block) + + // We don't need to skip you anymore. + stmt.skip = 0 + +/* +Proc: RunWhile +Runs a while loop. +*/ + +/datum/n_Interpreter/proc/RunWhile(var/datum/node/statement/WhileLoop/stmt) + var/i = 1 + while(Eval(stmt.cond) && Iterate(stmt.block, i++)) + continue + + status &= ~BREAKING + +/* +Proc:Iterate +Runs a single iteration of a loop. Returns a value indicating whether or not to continue looping. +*/ + +/datum/n_Interpreter/proc/Iterate(var/datum/node/BlockDefinition/block, count) + RunBlock(block) + if(max_iterations > 0 && count >= max_iterations) + RaiseError(new/datum/runtimeError/IterationLimitReached()) + return 0 + + if(status & (BREAKING|RETURNING)) + return 0 + + status &= ~CONTINUING + return 1 + +/* +Proc: GetFunction +Finds a function in an accessible scope with the given name. Returns a . +*/ + +/datum/n_Interpreter/proc/GetFunction(name) + var/datum/scope/S = curScope + while(S) + if(S.functions.Find(name)) + return S.functions[name] + S = S.parent + + RaiseError(new/datum/runtimeError/UndefinedFunction(name)) + +/* +Proc: GetVariable +Finds a variable in an accessible scope and returns its value. +*/ + +/datum/n_Interpreter/proc/GetVariable(name) + var/datum/scope/S = curScope + while(S) + if(S.variables.Find(name)) + return S.variables[name] + S = S.parent + + RaiseError(new/datum/runtimeError/UndefinedVariable(name)) + +/datum/n_Interpreter/proc/GetVariableScope(name) //needed for when you reassign a variable in a higher scope + var/datum/scope/S = curScope + while(S) + if(S.variables.Find(name)) + return S + + S = S.parent + + +/datum/n_Interpreter/proc/IsVariableAccessible(name) + var/datum/scope/S = curScope + while(S) + if(S.variables.Find(name)) + return TRUE + S = S.parent + + return FALSE + + +/* +Proc: AssignVariable +Assigns a value to a variable in a specific block. + +Parameters: +name - The name of the variable to assign. +value - The value to assign to it. +S - The scope the variable resides in. If it is null, a scope with the variable already existing is found. If no scopes have a variable of the given name, the current scope is used. +*/ + +/datum/n_Interpreter/proc/AssignVariable(name, datum/node/expression/value, var/datum/scope/S = null) + if(!S) S = GetVariableScope(name) + if(!S) S = curScope + if(!S) S = globalScope + + ASSERT(istype(S)) + if(istext(value) || isnum(value) || isnull(value)) value = new/datum/node/expression/value/literal(value) + else if(!istype(value) && isobject(value)) value = new/datum/node/expression/value/reference(value) + //TODO: check for invalid name + S.variables["[name]"] = value + + diff --git a/code/modules/scripting/Interpreter/Scope.dm b/code/modules/scripting/Interpreter/Scope.dm index 24b3fbf727d..09e8dea999f 100644 --- a/code/modules/scripting/Interpreter/Scope.dm +++ b/code/modules/scripting/Interpreter/Scope.dm @@ -1,16 +1,16 @@ -/* - Class: scope - A runtime instance of a block. Used internally by the interpreter. -*/ -/datum/scope - var/datum/scope/parent = null - var/datum/node/BlockDefinition/block - var/list/functions - var/list/variables - -/datum/scope/New(var/datum/node/BlockDefinition/B, var/datum/scope/parent) - src.block = B - src.parent = parent - src.variables = B.initial_variables.Copy() - src.functions = B.functions.Copy() - . = ..() +/* + Class: scope + A runtime instance of a block. Used internally by the interpreter. +*/ +/datum/scope + var/datum/scope/parent = null + var/datum/node/BlockDefinition/block + var/list/functions + var/list/variables + +/datum/scope/New(var/datum/node/BlockDefinition/B, var/datum/scope/parent) + src.block = B + src.parent = parent + src.variables = B.initial_variables.Copy() + src.functions = B.functions.Copy() + . = ..() diff --git a/code/modules/scripting/Options.dm b/code/modules/scripting/Options.dm index 63aaa7cd72a..a92da87c6f1 100644 --- a/code/modules/scripting/Options.dm +++ b/code/modules/scripting/Options.dm @@ -1,121 +1,121 @@ -/* -File: Options -*/ -// Ascii values of characters -/var/const/ascii_A = 65 -/var/const/ascii_Z = 90 -/var/const/ascii_a = 97 -/var/const/ascii_z = 122 -/var/const/ascii_DOLLAR = 36 // $ -/var/const/ascii_ZERO = 48 -/var/const/ascii_NINE = 57 -/var/const/ascii_UNDERSCORE = 95 // _ - -/* - Class: n_scriptOptions -*/ -/datum/n_scriptOptions/proc/CanStartID(char) //returns true if the character can start a variable, function, or keyword name (by default letters or an underscore) - if(!isnum(char)) - char = text2ascii(char) - - return (char in ascii_A to ascii_Z) || (char in ascii_a to ascii_z) || char == ascii_UNDERSCORE || char == ascii_DOLLAR - -/datum/n_scriptOptions/proc/IsValidIDChar(char) //returns true if the character can be in the body of a variable, function, or keyword name (by default letters, numbers, and underscore) - if(!isnum(char)) - char = text2ascii(char) - - return CanStartID(char) || IsDigit(char) - -/datum/n_scriptOptions/proc/IsDigit(char) - if(!isnum(char)) - char = text2ascii(char) - - return char in ascii_ZERO to ascii_NINE - -/datum/n_scriptOptions/proc/IsValidID(id) //returns true if all the characters in the string are okay to be in an identifier name - if(!CanStartID(id)) //don't need to grab first char in id, since text2ascii does it automatically - return 0 - - if(length(id) == 1) - return 1 - - for(var/i=2 to length(id)) - if(!IsValidIDChar(copytext(id, i, i + 1))) - return 0 - return 1 - -/* - Class: nS_Options - An implementation of for the n_Script language. -*/ -/datum/n_scriptOptions/nS_Options - var/list/symbols = list( - "(", - ")", - "\[", - "]", - ";", - ",", - "{", - "}" - ) //scanner - Characters that can be in symbols -/* -Var: keywords -An associative list used by the parser to parse keywords. Indices are strings which will trigger the keyword when parsed and the -associated values are types of which the proc will be called. -*/ - var/list/keywords = list( - "if" = /datum/n_Keyword/nS_Keyword/kwIf, - "else" = /datum/n_Keyword/nS_Keyword/kwElse, - "elseif" = /datum/n_Keyword/nS_Keyword/kwElseIf, - "while" = /datum/n_Keyword/nS_Keyword/kwWhile, - "break" = /datum/n_Keyword/nS_Keyword/kwBreak, - "continue" = /datum/n_Keyword/nS_Keyword/kwContinue, - "return" = /datum/n_Keyword/nS_Keyword/kwReturn, - "def" = /datum/n_Keyword/nS_Keyword/kwDef - ) - - var/list/assign_operators = list( - "=" = null, - "&=" = "&", - "|=" = "|", - "`=" = "`", - "+=" = "+", - "-=" = "-", - "*=" = "*", - "/=" = "/", - "^=" = "^", - "%=" = "%" - ) - - var/list/unary_operators = list( - "!" = /datum/node/expression/operator/unary/LogicalNot, - "~" = /datum/node/expression/operator/unary/BitwiseNot, - "-" = /datum/node/expression/operator/unary/Minus - ) - - var/list/binary_operators = list( - "==" = /datum/node/expression/operator/binary/Equal, - "!=" = /datum/node/expression/operator/binary/NotEqual, - ">" = /datum/node/expression/operator/binary/Greater, - "<" = /datum/node/expression/operator/binary/Less, - ">=" = /datum/node/expression/operator/binary/GreaterOrEqual, - "<=" = /datum/node/expression/operator/binary/LessOrEqual, - "&&" = /datum/node/expression/operator/binary/LogicalAnd, - "||" = /datum/node/expression/operator/binary/LogicalOr, - "&" = /datum/node/expression/operator/binary/BitwiseAnd, - "|" = /datum/node/expression/operator/binary/BitwiseOr, - "`" = /datum/node/expression/operator/binary/BitwiseXor, - "+" = /datum/node/expression/operator/binary/Add, - "-" = /datum/node/expression/operator/binary/Subtract, - "*" = /datum/node/expression/operator/binary/Multiply, - "/" = /datum/node/expression/operator/binary/Divide, - "^" = /datum/node/expression/operator/binary/Power, - "%" = /datum/node/expression/operator/binary/Modulo - ) - -/datum/n_scriptOptions/nS_Options/New() - . = ..() - for(var/O in assign_operators + binary_operators + unary_operators) - if(!symbols.Find(O)) +/* +File: Options +*/ +// Ascii values of characters +/var/const/ascii_A = 65 +/var/const/ascii_Z = 90 +/var/const/ascii_a = 97 +/var/const/ascii_z = 122 +/var/const/ascii_DOLLAR = 36 // $ +/var/const/ascii_ZERO = 48 +/var/const/ascii_NINE = 57 +/var/const/ascii_UNDERSCORE = 95 // _ + +/* + Class: n_scriptOptions +*/ +/datum/n_scriptOptions/proc/CanStartID(char) //returns true if the character can start a variable, function, or keyword name (by default letters or an underscore) + if(!isnum(char)) + char = text2ascii(char) + + return (char in ascii_A to ascii_Z) || (char in ascii_a to ascii_z) || char == ascii_UNDERSCORE || char == ascii_DOLLAR + +/datum/n_scriptOptions/proc/IsValidIDChar(char) //returns true if the character can be in the body of a variable, function, or keyword name (by default letters, numbers, and underscore) + if(!isnum(char)) + char = text2ascii(char) + + return CanStartID(char) || IsDigit(char) + +/datum/n_scriptOptions/proc/IsDigit(char) + if(!isnum(char)) + char = text2ascii(char) + + return char in ascii_ZERO to ascii_NINE + +/datum/n_scriptOptions/proc/IsValidID(id) //returns true if all the characters in the string are okay to be in an identifier name + if(!CanStartID(id)) //don't need to grab first char in id, since text2ascii does it automatically + return 0 + + if(length(id) == 1) + return 1 + + for(var/i=2 to length(id)) + if(!IsValidIDChar(copytext(id, i, i + 1))) + return 0 + return 1 + +/* + Class: nS_Options + An implementation of for the n_Script language. +*/ +/datum/n_scriptOptions/nS_Options + var/list/symbols = list( + "(", + ")", + "\[", + "]", + ";", + ",", + "{", + "}" + ) //scanner - Characters that can be in symbols +/* +Var: keywords +An associative list used by the parser to parse keywords. Indices are strings which will trigger the keyword when parsed and the +associated values are types of which the proc will be called. +*/ + var/list/keywords = list( + "if" = /datum/n_Keyword/nS_Keyword/kwIf, + "else" = /datum/n_Keyword/nS_Keyword/kwElse, + "elseif" = /datum/n_Keyword/nS_Keyword/kwElseIf, + "while" = /datum/n_Keyword/nS_Keyword/kwWhile, + "break" = /datum/n_Keyword/nS_Keyword/kwBreak, + "continue" = /datum/n_Keyword/nS_Keyword/kwContinue, + "return" = /datum/n_Keyword/nS_Keyword/kwReturn, + "def" = /datum/n_Keyword/nS_Keyword/kwDef + ) + + var/list/assign_operators = list( + "=" = null, + "&=" = "&", + "|=" = "|", + "`=" = "`", + "+=" = "+", + "-=" = "-", + "*=" = "*", + "/=" = "/", + "^=" = "^", + "%=" = "%" + ) + + var/list/unary_operators = list( + "!" = /datum/node/expression/operator/unary/LogicalNot, + "~" = /datum/node/expression/operator/unary/BitwiseNot, + "-" = /datum/node/expression/operator/unary/Minus + ) + + var/list/binary_operators = list( + "==" = /datum/node/expression/operator/binary/Equal, + "!=" = /datum/node/expression/operator/binary/NotEqual, + ">" = /datum/node/expression/operator/binary/Greater, + "<" = /datum/node/expression/operator/binary/Less, + ">=" = /datum/node/expression/operator/binary/GreaterOrEqual, + "<=" = /datum/node/expression/operator/binary/LessOrEqual, + "&&" = /datum/node/expression/operator/binary/LogicalAnd, + "||" = /datum/node/expression/operator/binary/LogicalOr, + "&" = /datum/node/expression/operator/binary/BitwiseAnd, + "|" = /datum/node/expression/operator/binary/BitwiseOr, + "`" = /datum/node/expression/operator/binary/BitwiseXor, + "+" = /datum/node/expression/operator/binary/Add, + "-" = /datum/node/expression/operator/binary/Subtract, + "*" = /datum/node/expression/operator/binary/Multiply, + "/" = /datum/node/expression/operator/binary/Divide, + "^" = /datum/node/expression/operator/binary/Power, + "%" = /datum/node/expression/operator/binary/Modulo + ) + +/datum/n_scriptOptions/nS_Options/New() + . = ..() + for(var/O in assign_operators + binary_operators + unary_operators) + if(!symbols.Find(O)) symbols += O \ No newline at end of file diff --git a/code/modules/scripting/Parser/Expressions.dm b/code/modules/scripting/Parser/Expressions.dm index 8bca367effe..1416de35104 100644 --- a/code/modules/scripting/Parser/Expressions.dm +++ b/code/modules/scripting/Parser/Expressions.dm @@ -1,371 +1,371 @@ -/* - File: Expressions - Procedures for parsing expressions. -*/ - -/* - Macros: Expression Macros - OPERATOR - A value indicating the parser currently expects a binary operator. - VALUE - A value indicating the parser currently expects a value. - SHIFT - Tells the parser to push the current operator onto the stack. - REDUCE - Tells the parser to reduce the stack. -*/ -#define OPERATOR 1 -#define VALUE 2 -#define SHIFT 0 -#define REDUCE 1 - -/* - Class: nS_Parser -*/ -/datum/n_Parser/nS_Parser -/* - Var: expecting - A variable which keeps track of whether an operator or value is expected. It should be either or . See - for more information. -*/ - var/expecting = VALUE - -/* - Proc: Precedence - Compares two operators, decides which is higher in the order of operations, and returns or . -*/ -/datum/n_Parser/nS_Parser/proc/Precedence(var/datum/node/expression/operator/top, var/datum/node/expression/operator/input) - if(istype(top)) - top = top.precedence - - if(istype(input)) - - input = input:precedence - - if(top >= input) - return REDUCE - - return SHIFT - -/* - Proc: GetExpression - Takes a token expected to represent a value and returns an node. -*/ -/datum/n_Parser/nS_Parser/proc/GetExpression(var/datum/token/T) - if(!T) - return - - if(istype(T, /datum/node/expression)) - return T - - switch(T.type) - if(/datum/token/word) - return new/datum/node/expression/value/variable(T.value) - - if(/datum/token/accessor) - var/datum/token/accessor/A = T - var/datum/node/expression/value/variable/E// = new(A.member) - var/datum/stack/S = new() - - while(istype(A.object, /datum/token/accessor)) - S.Push(A) - A = A.object - - ASSERT(istext(A.object)) - - while(A) - var/datum/node/expression/value/variable/V = new() - V.id = new(A.member) - if(E) - V.object = E - else - V.object = new/datum/node/identifier(A.object) - - E = V - A = S.Pop() - return E - - if(/datum/token/number, /datum/token/string) - return new/datum/node/expression/value/literal(T.value) - -/* - Proc: GetOperator - Gets a path related to a token or string and returns an instance of the given type. This is used to get an instance of either a binary or unary - operator from a token. - - Parameters: - O - The input value. If this is a token, O is reset to the token's value. - When O is a string and is in L, its associated value is used as the path to instantiate. - type - The desired type of the returned object. - L - The list in which to search for O. - - See Also: - - - - -*/ -/datum/n_Parser/nS_Parser/proc/GetOperator(O, type = /datum/node/expression/operator, L[]) - if(istype(O, type)) - return O //O is already the desired type - - if(istype(O, /datum/token)) - O = O:value //sets O to text - - if(istext(O)) //sets O to path - if(L.Find(O)) - O = L[O] - else - return null - - if(ispath(O)) - O = new O //catches path from last check - - else - return null //Unknown type - - return O - -/* - Proc: GetBinaryOperator - Uses to search for an instance of a binary operator type with which the given string is associated. For example, if - O is set to "+", an node is returned. - - See Also: - - - - -*/ -/datum/n_Parser/nS_Parser/proc/GetBinaryOperator(O) - return GetOperator(O, /datum/node/expression/operator/binary, options.binary_operators) - -/* - Proc: GetUnaryOperator - Uses to search for an instance of a unary operator type with which the given string is associated. For example, if - O is set to "!", a node is returned. - - See Also: - - - - -*/ -/datum/n_Parser/nS_Parser/proc/GetUnaryOperator(O) - return GetOperator(O, /datum/node/expression/operator/unary, options.unary_operators) - -/* - Proc: Reduce - Takes the operator on top of the opr stack and assigns its operand(s). Then this proc pushes the value of that operation to the top - of the val stack. -*/ -/datum/n_Parser/nS_Parser/proc/Reduce(var/datum/stack/opr, var/datum/stack/val) - var/datum/node/expression/operator/O = opr.Pop() - if(!O) - return - - if(!istype(O)) - errors += new/datum/scriptError("Error reducing expression - invalid operator.") - return - - //Take O and assign its operands, popping one or two values from the val stack - //depending on whether O is a binary or unary operator. - if(istype(O, /datum/node/expression/operator/binary)) - var/datum/node/expression/operator/binary/B=O - B.exp2 = val.Pop() - B.exp = val.Pop() - val.Push(B) - - else - O.exp=val.Pop() - val.Push(O) - -/* - Proc: EndOfExpression - Returns true if the current token represents the end of an expression. - - Parameters: - end - A list of values to compare the current token to. -*/ -/datum/n_Parser/nS_Parser/proc/EndOfExpression(end[]) - if(!curToken) - return 1 - if(istype(curToken, /datum/token/symbol) && end.Find(curToken.value)) - return 1 - if(istype(curToken, /datum/token/end) && end.Find(/datum/token/end)) - return 1 - return 0 - -/* - Proc: ParseExpression - Uses the Shunting-yard algorithm to parse expressions. - - Notes: - - When an opening parenthesis is found, then is called to handle it. - - The variable helps distinguish unary operators from binary operators (for cases like the - operator, which can be either). - - Articles: - - - - - - See Also: - - - - - - -*/ - -/datum/n_Parser/nS_Parser/proc/ParseExpression(var/list/end = list(/datum/token/end), list/ErrChars = list("{", "}"), check_functions = 0) - var/datum/stack/opr = new - var/datum/stack/val = new - src.expecting = VALUE - var/loop = 0 - for() - loop++ - if(loop > 800) - errors += new/datum/scriptError("Too many nested tokens.") - return - - if(EndOfExpression(end)) - break - - if(istype(curToken, /datum/token/symbol) && ErrChars.Find(curToken.value)) - errors += new/datum/scriptError/BadToken(curToken) - break - - if(index > tokens.len) //End of File - errors += new/datum/scriptError/EndOfFile() - break - - var/datum/token/ntok - if(index + 1 <= tokens.len) - ntok = tokens[index + 1] - - if(istype(curToken, /datum/token/symbol) && curToken.value == "(") //Parse parentheses expression - if(expecting != VALUE) - errors += new/datum/scriptError/ExpectedToken("operator", curToken) - NextToken() - continue - - val.Push(ParseParenExpression()) - - else if(istype(curToken, /datum/token/symbol)) //Operator found. - var/datum/node/expression/operator/curOperator //Figure out whether it is unary or binary and get a new instance. - if(src.expecting == OPERATOR) - curOperator = GetBinaryOperator(curToken) - if(!curOperator) - errors += new/datum/scriptError/ExpectedToken("operator", curToken) - NextToken() - continue - else - curOperator = GetUnaryOperator(curToken) - if(!curOperator) //given symbol isn't a unary operator - errors += new/datum/scriptError/ExpectedToken("expression", curToken) - NextToken() - continue - - if(opr.Top() && Precedence(opr.Top(), curOperator) == REDUCE) //Check order of operations and reduce if necessary - Reduce(opr, val) - continue - - opr.Push(curOperator) - src.expecting = VALUE - - else if(ntok && ntok.value == "(" && istype(ntok, /datum/token/symbol)\ - && istype(curToken, /datum/token/word)) //Parse function call - - if(!check_functions) - - var/datum/token/preToken = curToken - var/old_expect = src.expecting - var/fex = ParseFunctionExpression() - if(old_expect != VALUE) - errors += new/datum/scriptError/ExpectedToken("operator", preToken) - NextToken() - continue - - val.Push(fex) - else - errors += new/datum/scriptError/ParameterFunction(curToken) - break - - else if(istype(curToken, /datum/token/keyword)) //inline keywords - var/datum/n_Keyword/kw = options.keywords[curToken.value] - kw = new kw(inline=1) - if(kw) - if(!kw.Parse(src)) - return - else - errors += new/datum/scriptError/BadToken(curToken) - - else if(istype(curToken, /datum/token/end)) //semicolon found where it wasn't expected - errors += new/datum/scriptError/BadToken(curToken) - NextToken() - continue - else - if(expecting != VALUE) - errors += new/datum/scriptError/ExpectedToken("operator", curToken) - NextToken() - continue - - val.Push(GetExpression(curToken)) - src.expecting = OPERATOR - - NextToken() - - while(opr.Top()) - Reduce(opr, val) - //Reduce the value stack completely - . = val.Pop() //Return what should be the last value on the stack - - if(val.Top()) // - var/datum/node/N = val.Pop() - errors += new/datum/scriptError("Error parsing expression. Unexpected value left on stack: [N.ToString()].") - return null - -/* - Proc: ParseFunctionExpression - Parses a function call inside of an expression. - - See Also: - - -*/ - -/datum/n_Parser/nS_Parser/proc/ParseFunctionExpression() - var/datum/node/expression/FunctionCall/exp = new - exp.func_name = curToken.value - NextToken() //skip function name - NextToken() //skip open parenthesis, already found - var/loops = 0 - - for() - loops++ - if(loops >= 800) - errors += new/datum/scriptError("Too many nested expressions.") - break - //CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;") - - if(istype(curToken, /datum/token/symbol) && curToken.value == ")") - return exp - exp.parameters += ParseParamExpression() - if(errors.len) - return exp - - if(curToken.value == "," && istype(curToken, /datum/token/symbol)) - NextToken() //skip comma - - if(istype(curToken, /datum/token/end)) //Prevents infinite loop... - errors += new/datum/scriptError/ExpectedToken(")") - return exp - -/* - Proc: ParseParenExpression - Parses an expression that ends with a close parenthesis. This is used for parsing expressions inside of parentheses. - - See Also: - - -*/ -/datum/n_Parser/nS_Parser/proc/ParseParenExpression() - if(!CheckToken("(", /datum/token/symbol)) - return - return new/datum/node/expression/operator/unary/group(ParseExpression(list(")"))) - -/* - Proc: ParseParamExpression - Parses an expression that ends with either a comma or close parenthesis. This is used for parsing the parameters passed to a function call. - - See Also: - - -*/ -/datum/n_Parser/nS_Parser/proc/ParseParamExpression(var/check_functions = 0) - var/cf = check_functions +/* + File: Expressions + Procedures for parsing expressions. +*/ + +/* + Macros: Expression Macros + OPERATOR - A value indicating the parser currently expects a binary operator. + VALUE - A value indicating the parser currently expects a value. + SHIFT - Tells the parser to push the current operator onto the stack. + REDUCE - Tells the parser to reduce the stack. +*/ +#define OPERATOR 1 +#define VALUE 2 +#define SHIFT 0 +#define REDUCE 1 + +/* + Class: nS_Parser +*/ +/datum/n_Parser/nS_Parser +/* + Var: expecting + A variable which keeps track of whether an operator or value is expected. It should be either or . See + for more information. +*/ + var/expecting = VALUE + +/* + Proc: Precedence + Compares two operators, decides which is higher in the order of operations, and returns or . +*/ +/datum/n_Parser/nS_Parser/proc/Precedence(var/datum/node/expression/operator/top, var/datum/node/expression/operator/input) + if(istype(top)) + top = top.precedence + + if(istype(input)) + + input = input:precedence + + if(top >= input) + return REDUCE + + return SHIFT + +/* + Proc: GetExpression + Takes a token expected to represent a value and returns an node. +*/ +/datum/n_Parser/nS_Parser/proc/GetExpression(var/datum/token/T) + if(!T) + return + + if(istype(T, /datum/node/expression)) + return T + + switch(T.type) + if(/datum/token/word) + return new/datum/node/expression/value/variable(T.value) + + if(/datum/token/accessor) + var/datum/token/accessor/A = T + var/datum/node/expression/value/variable/E// = new(A.member) + var/datum/stack/S = new() + + while(istype(A.object, /datum/token/accessor)) + S.Push(A) + A = A.object + + ASSERT(istext(A.object)) + + while(A) + var/datum/node/expression/value/variable/V = new() + V.id = new(A.member) + if(E) + V.object = E + else + V.object = new/datum/node/identifier(A.object) + + E = V + A = S.Pop() + return E + + if(/datum/token/number, /datum/token/string) + return new/datum/node/expression/value/literal(T.value) + +/* + Proc: GetOperator + Gets a path related to a token or string and returns an instance of the given type. This is used to get an instance of either a binary or unary + operator from a token. + + Parameters: + O - The input value. If this is a token, O is reset to the token's value. + When O is a string and is in L, its associated value is used as the path to instantiate. + type - The desired type of the returned object. + L - The list in which to search for O. + + See Also: + - + - +*/ +/datum/n_Parser/nS_Parser/proc/GetOperator(O, type = /datum/node/expression/operator, L[]) + if(istype(O, type)) + return O //O is already the desired type + + if(istype(O, /datum/token)) + O = O:value //sets O to text + + if(istext(O)) //sets O to path + if(L.Find(O)) + O = L[O] + else + return null + + if(ispath(O)) + O = new O //catches path from last check + + else + return null //Unknown type + + return O + +/* + Proc: GetBinaryOperator + Uses to search for an instance of a binary operator type with which the given string is associated. For example, if + O is set to "+", an node is returned. + + See Also: + - + - +*/ +/datum/n_Parser/nS_Parser/proc/GetBinaryOperator(O) + return GetOperator(O, /datum/node/expression/operator/binary, options.binary_operators) + +/* + Proc: GetUnaryOperator + Uses to search for an instance of a unary operator type with which the given string is associated. For example, if + O is set to "!", a node is returned. + + See Also: + - + - +*/ +/datum/n_Parser/nS_Parser/proc/GetUnaryOperator(O) + return GetOperator(O, /datum/node/expression/operator/unary, options.unary_operators) + +/* + Proc: Reduce + Takes the operator on top of the opr stack and assigns its operand(s). Then this proc pushes the value of that operation to the top + of the val stack. +*/ +/datum/n_Parser/nS_Parser/proc/Reduce(var/datum/stack/opr, var/datum/stack/val) + var/datum/node/expression/operator/O = opr.Pop() + if(!O) + return + + if(!istype(O)) + errors += new/datum/scriptError("Error reducing expression - invalid operator.") + return + + //Take O and assign its operands, popping one or two values from the val stack + //depending on whether O is a binary or unary operator. + if(istype(O, /datum/node/expression/operator/binary)) + var/datum/node/expression/operator/binary/B=O + B.exp2 = val.Pop() + B.exp = val.Pop() + val.Push(B) + + else + O.exp=val.Pop() + val.Push(O) + +/* + Proc: EndOfExpression + Returns true if the current token represents the end of an expression. + + Parameters: + end - A list of values to compare the current token to. +*/ +/datum/n_Parser/nS_Parser/proc/EndOfExpression(end[]) + if(!curToken) + return 1 + if(istype(curToken, /datum/token/symbol) && end.Find(curToken.value)) + return 1 + if(istype(curToken, /datum/token/end) && end.Find(/datum/token/end)) + return 1 + return 0 + +/* + Proc: ParseExpression + Uses the Shunting-yard algorithm to parse expressions. + + Notes: + - When an opening parenthesis is found, then is called to handle it. + - The variable helps distinguish unary operators from binary operators (for cases like the - operator, which can be either). + + Articles: + - + - + + See Also: + - + - + - +*/ + +/datum/n_Parser/nS_Parser/proc/ParseExpression(var/list/end = list(/datum/token/end), list/ErrChars = list("{", "}"), check_functions = 0) + var/datum/stack/opr = new + var/datum/stack/val = new + src.expecting = VALUE + var/loop = 0 + for() + loop++ + if(loop > 800) + errors += new/datum/scriptError("Too many nested tokens.") + return + + if(EndOfExpression(end)) + break + + if(istype(curToken, /datum/token/symbol) && ErrChars.Find(curToken.value)) + errors += new/datum/scriptError/BadToken(curToken) + break + + if(index > tokens.len) //End of File + errors += new/datum/scriptError/EndOfFile() + break + + var/datum/token/ntok + if(index + 1 <= tokens.len) + ntok = tokens[index + 1] + + if(istype(curToken, /datum/token/symbol) && curToken.value == "(") //Parse parentheses expression + if(expecting != VALUE) + errors += new/datum/scriptError/ExpectedToken("operator", curToken) + NextToken() + continue + + val.Push(ParseParenExpression()) + + else if(istype(curToken, /datum/token/symbol)) //Operator found. + var/datum/node/expression/operator/curOperator //Figure out whether it is unary or binary and get a new instance. + if(src.expecting == OPERATOR) + curOperator = GetBinaryOperator(curToken) + if(!curOperator) + errors += new/datum/scriptError/ExpectedToken("operator", curToken) + NextToken() + continue + else + curOperator = GetUnaryOperator(curToken) + if(!curOperator) //given symbol isn't a unary operator + errors += new/datum/scriptError/ExpectedToken("expression", curToken) + NextToken() + continue + + if(opr.Top() && Precedence(opr.Top(), curOperator) == REDUCE) //Check order of operations and reduce if necessary + Reduce(opr, val) + continue + + opr.Push(curOperator) + src.expecting = VALUE + + else if(ntok && ntok.value == "(" && istype(ntok, /datum/token/symbol)\ + && istype(curToken, /datum/token/word)) //Parse function call + + if(!check_functions) + + var/datum/token/preToken = curToken + var/old_expect = src.expecting + var/fex = ParseFunctionExpression() + if(old_expect != VALUE) + errors += new/datum/scriptError/ExpectedToken("operator", preToken) + NextToken() + continue + + val.Push(fex) + else + errors += new/datum/scriptError/ParameterFunction(curToken) + break + + else if(istype(curToken, /datum/token/keyword)) //inline keywords + var/datum/n_Keyword/kw = options.keywords[curToken.value] + kw = new kw(inline=1) + if(kw) + if(!kw.Parse(src)) + return + else + errors += new/datum/scriptError/BadToken(curToken) + + else if(istype(curToken, /datum/token/end)) //semicolon found where it wasn't expected + errors += new/datum/scriptError/BadToken(curToken) + NextToken() + continue + else + if(expecting != VALUE) + errors += new/datum/scriptError/ExpectedToken("operator", curToken) + NextToken() + continue + + val.Push(GetExpression(curToken)) + src.expecting = OPERATOR + + NextToken() + + while(opr.Top()) + Reduce(opr, val) + //Reduce the value stack completely + . = val.Pop() //Return what should be the last value on the stack + + if(val.Top()) // + var/datum/node/N = val.Pop() + errors += new/datum/scriptError("Error parsing expression. Unexpected value left on stack: [N.ToString()].") + return null + +/* + Proc: ParseFunctionExpression + Parses a function call inside of an expression. + + See Also: + - +*/ + +/datum/n_Parser/nS_Parser/proc/ParseFunctionExpression() + var/datum/node/expression/FunctionCall/exp = new + exp.func_name = curToken.value + NextToken() //skip function name + NextToken() //skip open parenthesis, already found + var/loops = 0 + + for() + loops++ + if(loops >= 800) + errors += new/datum/scriptError("Too many nested expressions.") + break + //CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;") + + if(istype(curToken, /datum/token/symbol) && curToken.value == ")") + return exp + exp.parameters += ParseParamExpression() + if(errors.len) + return exp + + if(curToken.value == "," && istype(curToken, /datum/token/symbol)) + NextToken() //skip comma + + if(istype(curToken, /datum/token/end)) //Prevents infinite loop... + errors += new/datum/scriptError/ExpectedToken(")") + return exp + +/* + Proc: ParseParenExpression + Parses an expression that ends with a close parenthesis. This is used for parsing expressions inside of parentheses. + + See Also: + - +*/ +/datum/n_Parser/nS_Parser/proc/ParseParenExpression() + if(!CheckToken("(", /datum/token/symbol)) + return + return new/datum/node/expression/operator/unary/group(ParseExpression(list(")"))) + +/* + Proc: ParseParamExpression + Parses an expression that ends with either a comma or close parenthesis. This is used for parsing the parameters passed to a function call. + + See Also: + - +*/ +/datum/n_Parser/nS_Parser/proc/ParseParamExpression(var/check_functions = 0) + var/cf = check_functions return ParseExpression(list(",", ")"), check_functions = cf) \ No newline at end of file diff --git a/code/modules/scripting/Parser/Keywords.dm b/code/modules/scripting/Parser/Keywords.dm index 32ca217748e..7e8d99328ef 100644 --- a/code/modules/scripting/Parser/Keywords.dm +++ b/code/modules/scripting/Parser/Keywords.dm @@ -1,206 +1,206 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/* - File: Keywords -*/ -var/const/KW_FAIL = 0 //Fatal error; stop parsing entire script. -var/const/KW_PASS = 1 //OK -var/const/KW_ERR = 2 //Non-fatal error, keyword couldn't be handled properly. Ignore keyword but continue on. -var/const/KW_WARN = 3 //Warning - -/* -var/const/Class: n_Keyword -var/const/Represents a special statement in the code triggered by a keyword. -*/ -/datum/n_Keyword -/* - Var: inline - 1 if the keyword is in an expression (e.g. the new keyword in many languages), 0 otherwise (such as the if and else keywords). -*/ - var/inline - -/datum/n_Keyword/New(inline = 0) - src.inline = inline - return ..() - -/* - Proc: Parse - Called when the parser finds a keyword in the code. - - Parameters: - parser - The parser that created this object. You can use the parameter to manipulate the parser in order to add statements and blocks - to its AST. -*/ -/datum/n_Keyword/proc/Parse(var/datum/n_Parser/parser) - return -/* - Class: nS_Keyword - A keyword in n_Script. By default these include return, if, else, while, and def. To enable or disable a keyword, change the - list. - - Behavior: - When a parser is expecting a new statement, and a keyword listed in is found, it will call the keyword's - proc. -*/ -/datum/n_Keyword/nS_Keyword/New(var/inline = 0) - if(inline) - qdel (src) - -/datum/n_Keyword/nS_Keyword/kwReturn/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) // Exit out of the program by setting the tokens list size to the same as index. - parser.tokens.len = parser.index - return - - var/datum/node/statement/ReturnStatement/stmt = new - parser.NextToken() //skip 'return' token - stmt.value = parser.ParseExpression() - parser.curBlock.statements += stmt - -/datum/n_Keyword/nS_Keyword/kwIf/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - var/datum/node/statement/IfStatement/stmt = new - parser.NextToken() //skip 'if' token - stmt.cond = parser.ParseParenExpression() - if(!parser.CheckToken(")", /datum/token/symbol)) - return KW_FAIL - - if(!parser.CheckToken("{", /datum/token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0 - return KW_ERR - - parser.curBlock.statements += stmt - stmt.block = new - parser.AddBlock(stmt.block) - -/datum/n_Keyword/nS_Keyword/kwElseIf/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - var/list/L = parser.curBlock.statements - var/datum/node/statement/IfStatement/ifstmt - - if(L && L.len) - ifstmt = L[L.len] //Get the last statement in the current block - - if(!ifstmt || !istype(ifstmt) || ifstmt.else_if) - to_chat(usr, "NTSL: ELSE IF FAILED: [!ifstmt], [!istype(ifstmt)], [!istype(ifstmt) || ifstmt.else_if]")// Usr is unsafe as SHIT but JUST incase I forget this debug line like the fucking asset cache... - - parser.errors += new/datum/scriptError/ExpectedToken("if statement", parser.curToken) - return KW_FAIL - - var/datum/node/statement/IfStatement/ElseIf/stmt = new - parser.NextToken() //skip 'if' token - stmt.cond = parser.ParseParenExpression() - if(!parser.CheckToken(")", /datum/token/symbol)) - return KW_FAIL - - if(!parser.CheckToken("{", /datum/token/symbol, skip = 0)) //Token needs to be preserved for parse loop, so skip=0 - return KW_ERR - - parser.curBlock.statements += stmt - stmt.block = new - ifstmt.else_if = stmt - parser.AddBlock(stmt.block) - -/datum/n_Keyword/nS_Keyword/kwElse/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - var/list/L = parser.curBlock.statements - var/datum/node/statement/IfStatement/stmt - - if(L && L.len) - stmt = L[L.len] //Get the last statement in the current block - - if(!stmt || !istype(stmt) || stmt.else_block) //Ensure that it is an if statement - to_chat(usr, "NTSL: ELSE IF FAILED: [!stmt], [!istype(stmt)], [!istype(stmt) || stmt.else_block]")// Usr is unsafe as SHIT but JUST incase I forget this debug line like the fucking asset cache... - - parser.errors += new/datum/scriptError/ExpectedToken("if statement", parser.curToken) - return KW_FAIL - - parser.NextToken() //skip 'else' token - if(!parser.CheckToken("{", /datum/token/symbol, skip = 0)) - return KW_ERR - - stmt.else_block = new() - parser.AddBlock(stmt.else_block) - -/datum/n_Keyword/nS_Keyword/kwWhile/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - var/datum/node/statement/WhileLoop/stmt = new - parser.NextToken() //skip 'while' token - stmt.cond = parser.ParseParenExpression() - if(!parser.CheckToken(")", /datum/token/symbol)) - return KW_FAIL - - if(!parser.CheckToken("{", /datum/token/symbol, skip=0)) - return KW_ERR - - parser.curBlock.statements += stmt - stmt.block = new - parser.AddBlock(stmt.block) - -/datum/n_Keyword/nS_Keyword/kwBreak/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) - parser.errors += new/datum/scriptError/BadToken(parser.curToken) - . = KW_WARN - - var/datum/node/statement/BreakStatement/stmt = new - parser.NextToken() //skip 'break' token - parser.curBlock.statements += stmt - -/datum/n_Keyword/nS_Keyword/kwContinue/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) - parser.errors += new/datum/scriptError/BadToken(parser.curToken) - . = KW_WARN - - var/datum/node/statement/ContinueStatement/stmt = new - parser.NextToken() //skip 'break' token - parser.curBlock.statements += stmt - -/datum/n_Keyword/nS_Keyword/kwDef/Parse(var/datum/n_Parser/nS_Parser/parser) - . = KW_PASS - var/datum/node/statement/FunctionDefinition/def = new - parser.NextToken() //skip 'def' token - - if(!parser.options.IsValidID(parser.curToken.value)) - parser.errors += new/datum/scriptError/InvalidID(parser.curToken) - return KW_FAIL - - def.func_name = parser.curToken.value - parser.NextToken() - - if(!parser.CheckToken("(", /datum/token/symbol)) - return KW_FAIL - - for() //for now parameters can be separated by whitespace - they don't need a comma in between - if(istype(parser.curToken, /datum/token/symbol)) - switch(parser.curToken.value) - if(",") - parser.NextToken() - if(")") - break - else - parser.errors += new/datum/scriptError/BadToken(parser.curToken) - return KW_ERR - - else if(istype(parser.curToken, /datum/token/word)) - def.parameters += parser.curToken.value - parser.NextToken() - - else - parser.errors += new/datum/scriptError/InvalidID(parser.curToken) - return KW_ERR - - if(!parser.CheckToken(")", /datum/token/symbol)) - return KW_FAIL - - if(istype(parser.curToken, /datum/token/end)) //Function prototype - parser.curBlock.statements += def - - else if(parser.curToken.value == "{" && istype(parser.curToken, /datum/token/symbol)) - def.block = new - parser.curBlock.statements += def - parser.curBlock.functions[def.func_name] = def - parser.AddBlock(def.block) - else - parser.errors += new/datum/scriptError/BadToken(parser.curToken) - return KW_FAIL +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +/* + File: Keywords +*/ +var/const/KW_FAIL = 0 //Fatal error; stop parsing entire script. +var/const/KW_PASS = 1 //OK +var/const/KW_ERR = 2 //Non-fatal error, keyword couldn't be handled properly. Ignore keyword but continue on. +var/const/KW_WARN = 3 //Warning + +/* +var/const/Class: n_Keyword +var/const/Represents a special statement in the code triggered by a keyword. +*/ +/datum/n_Keyword +/* + Var: inline + 1 if the keyword is in an expression (e.g. the new keyword in many languages), 0 otherwise (such as the if and else keywords). +*/ + var/inline + +/datum/n_Keyword/New(inline = 0) + src.inline = inline + return ..() + +/* + Proc: Parse + Called when the parser finds a keyword in the code. + + Parameters: + parser - The parser that created this object. You can use the parameter to manipulate the parser in order to add statements and blocks + to its AST. +*/ +/datum/n_Keyword/proc/Parse(var/datum/n_Parser/parser) + return +/* + Class: nS_Keyword + A keyword in n_Script. By default these include return, if, else, while, and def. To enable or disable a keyword, change the + list. + + Behavior: + When a parser is expecting a new statement, and a keyword listed in is found, it will call the keyword's + proc. +*/ +/datum/n_Keyword/nS_Keyword/New(var/inline = 0) + if(inline) + qdel (src) + +/datum/n_Keyword/nS_Keyword/kwReturn/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) // Exit out of the program by setting the tokens list size to the same as index. + parser.tokens.len = parser.index + return + + var/datum/node/statement/ReturnStatement/stmt = new + parser.NextToken() //skip 'return' token + stmt.value = parser.ParseExpression() + parser.curBlock.statements += stmt + +/datum/n_Keyword/nS_Keyword/kwIf/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + var/datum/node/statement/IfStatement/stmt = new + parser.NextToken() //skip 'if' token + stmt.cond = parser.ParseParenExpression() + if(!parser.CheckToken(")", /datum/token/symbol)) + return KW_FAIL + + if(!parser.CheckToken("{", /datum/token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0 + return KW_ERR + + parser.curBlock.statements += stmt + stmt.block = new + parser.AddBlock(stmt.block) + +/datum/n_Keyword/nS_Keyword/kwElseIf/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + var/list/L = parser.curBlock.statements + var/datum/node/statement/IfStatement/ifstmt + + if(L && L.len) + ifstmt = L[L.len] //Get the last statement in the current block + + if(!ifstmt || !istype(ifstmt) || ifstmt.else_if) + to_chat(usr, "NTSL: ELSE IF FAILED: [!ifstmt], [!istype(ifstmt)], [!istype(ifstmt) || ifstmt.else_if]")// Usr is unsafe as SHIT but JUST incase I forget this debug line like the fucking asset cache... + + parser.errors += new/datum/scriptError/ExpectedToken("if statement", parser.curToken) + return KW_FAIL + + var/datum/node/statement/IfStatement/ElseIf/stmt = new + parser.NextToken() //skip 'if' token + stmt.cond = parser.ParseParenExpression() + if(!parser.CheckToken(")", /datum/token/symbol)) + return KW_FAIL + + if(!parser.CheckToken("{", /datum/token/symbol, skip = 0)) //Token needs to be preserved for parse loop, so skip=0 + return KW_ERR + + parser.curBlock.statements += stmt + stmt.block = new + ifstmt.else_if = stmt + parser.AddBlock(stmt.block) + +/datum/n_Keyword/nS_Keyword/kwElse/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + var/list/L = parser.curBlock.statements + var/datum/node/statement/IfStatement/stmt + + if(L && L.len) + stmt = L[L.len] //Get the last statement in the current block + + if(!stmt || !istype(stmt) || stmt.else_block) //Ensure that it is an if statement + to_chat(usr, "NTSL: ELSE IF FAILED: [!stmt], [!istype(stmt)], [!istype(stmt) || stmt.else_block]")// Usr is unsafe as SHIT but JUST incase I forget this debug line like the fucking asset cache... + + parser.errors += new/datum/scriptError/ExpectedToken("if statement", parser.curToken) + return KW_FAIL + + parser.NextToken() //skip 'else' token + if(!parser.CheckToken("{", /datum/token/symbol, skip = 0)) + return KW_ERR + + stmt.else_block = new() + parser.AddBlock(stmt.else_block) + +/datum/n_Keyword/nS_Keyword/kwWhile/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + var/datum/node/statement/WhileLoop/stmt = new + parser.NextToken() //skip 'while' token + stmt.cond = parser.ParseParenExpression() + if(!parser.CheckToken(")", /datum/token/symbol)) + return KW_FAIL + + if(!parser.CheckToken("{", /datum/token/symbol, skip=0)) + return KW_ERR + + parser.curBlock.statements += stmt + stmt.block = new + parser.AddBlock(stmt.block) + +/datum/n_Keyword/nS_Keyword/kwBreak/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) + parser.errors += new/datum/scriptError/BadToken(parser.curToken) + . = KW_WARN + + var/datum/node/statement/BreakStatement/stmt = new + parser.NextToken() //skip 'break' token + parser.curBlock.statements += stmt + +/datum/n_Keyword/nS_Keyword/kwContinue/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) + parser.errors += new/datum/scriptError/BadToken(parser.curToken) + . = KW_WARN + + var/datum/node/statement/ContinueStatement/stmt = new + parser.NextToken() //skip 'break' token + parser.curBlock.statements += stmt + +/datum/n_Keyword/nS_Keyword/kwDef/Parse(var/datum/n_Parser/nS_Parser/parser) + . = KW_PASS + var/datum/node/statement/FunctionDefinition/def = new + parser.NextToken() //skip 'def' token + + if(!parser.options.IsValidID(parser.curToken.value)) + parser.errors += new/datum/scriptError/InvalidID(parser.curToken) + return KW_FAIL + + def.func_name = parser.curToken.value + parser.NextToken() + + if(!parser.CheckToken("(", /datum/token/symbol)) + return KW_FAIL + + for() //for now parameters can be separated by whitespace - they don't need a comma in between + if(istype(parser.curToken, /datum/token/symbol)) + switch(parser.curToken.value) + if(",") + parser.NextToken() + if(")") + break + else + parser.errors += new/datum/scriptError/BadToken(parser.curToken) + return KW_ERR + + else if(istype(parser.curToken, /datum/token/word)) + def.parameters += parser.curToken.value + parser.NextToken() + + else + parser.errors += new/datum/scriptError/InvalidID(parser.curToken) + return KW_ERR + + if(!parser.CheckToken(")", /datum/token/symbol)) + return KW_FAIL + + if(istype(parser.curToken, /datum/token/end)) //Function prototype + parser.curBlock.statements += def + + else if(parser.curToken.value == "{" && istype(parser.curToken, /datum/token/symbol)) + def.block = new + parser.curBlock.statements += def + parser.curBlock.functions[def.func_name] = def + parser.AddBlock(def.block) + else + parser.errors += new/datum/scriptError/BadToken(parser.curToken) + return KW_FAIL diff --git a/code/modules/scripting/Parser/Parser.dm b/code/modules/scripting/Parser/Parser.dm index d9c737e7ea8..cdd7b647a6c 100644 --- a/code/modules/scripting/Parser/Parser.dm +++ b/code/modules/scripting/Parser/Parser.dm @@ -1,205 +1,205 @@ -/* - File: Parser -*/ -/* - Class: n_Parser - An object that reads tokens and produces an AST (abstract syntax tree). -*/ -/datum/n_Parser -/* - Var: index - The parser's current position in the token's list. -*/ - var/index = 1 -/* - Var: tokens - A list of tokens in the source code generated by a scanner. -*/ - var/list/tokens = new -/* - Var: errors - A list of fatal errors found by the parser. If there are any items in this list, then it is not safe to run the returned AST. - - See Also: - - -*/ - var/list/errors = new -/* - Var: warnings - A list of non-fatal problems in the script. -*/ - var/list/warnings = new -/* - Var: curToken - The token at in . -*/ - var/datum/token/curToken - var/datum/stack/blocks = new - var/datum/node/BlockDefinition/GlobalBlock/global_block = new - var/datum/node/BlockDefinition/GlobalBlock/curBlock - -/* - Proc: Parse - Reads the tokens and returns the AST's node. Be sure to populate the tokens list before calling this procedure. -*/ -/datum/n_Parser/proc/Parse() - return -/* - Proc: NextToken - Sets to the next token in the list, or null if there are no more tokens. -*/ -/datum/n_Parser/proc/NextToken() - if(index >= tokens.len) - curToken = null - else - curToken = tokens[++index] - return curToken - -/* - Class: nS_Parser - An implmentation of a parser for n_Script. -*/ -/datum/n_Parser/nS_Parser - var/datum/n_scriptOptions/nS_Options/options -/* - Constructor: New - - Parameters: - tokens - A list of tokens to parse. - options - An object used for configuration. -*/ -/datum/n_Parser/nS_Parser/New(tokens[], var/datum/n_scriptOptions/options) - src.tokens = tokens - src.options = options - curBlock = global_block - return ..() - -/datum/n_Parser/nS_Parser/Parse() - ASSERT(tokens) - for(,src.index <= src.tokens.len, src.index++) - curToken = tokens[index] - switch(curToken.type) - if(/datum/token/keyword) - var/datum/n_Keyword/kw = options.keywords[curToken.value] - kw = new kw() - if(kw) - if(!kw.Parse(src)) - return - - if(/datum/token/word) - var/datum/token/ntok - if(index + 1 > tokens.len) - errors += new/datum/scriptError/BadToken(curToken) - continue - - ntok = tokens[index + 1] - - if(!istype(ntok, /datum/token/symbol)) - errors += new/datum/scriptError/BadToken(ntok) - continue - - if(ntok.value == "(") - ParseFunctionStatement() - - else if(options.assign_operators.Find(ntok.value)) - ParseAssignment() - - else - errors += new/datum/scriptError/BadToken(ntok) - continue - - if(!istype(curToken, /datum/token/end)) - errors += new/datum/scriptError/ExpectedToken(";", curToken) - continue - - if(/datum/token/symbol) - if(curToken.value == "}") - if(!EndBlock()) - errors += new/datum/scriptError/BadToken(curToken) - continue - - else - errors += new/datum/scriptError/BadToken(curToken) - continue - - if(/datum/token/end) - warnings += new/datum/scriptError/BadToken(curToken) - continue - - else - errors += new/datum/scriptError/BadToken(curToken) - return - - return global_block - -/datum/n_Parser/nS_Parser/proc/CheckToken(val, type, err = 1, skip = 1) - if(curToken.value != val || !istype(curToken, type)) - if(err) - errors += new/datum/scriptError/ExpectedToken(val, curToken) - return 0 - if(skip) - NextToken() - - return 1 - -/datum/n_Parser/nS_Parser/proc/AddBlock(var/datum/node/BlockDefinition/B) - blocks.Push(curBlock) - curBlock = B - -/datum/n_Parser/nS_Parser/proc/EndBlock() - if(curBlock == global_block) - return 0 - - curBlock = blocks.Pop() - return 1 - -/datum/n_Parser/nS_Parser/proc/ParseAssignment() - var/name = curToken.value - if(!options.IsValidID(name)) - errors += new/datum/scriptError/InvalidID(curToken) - return - - NextToken() - var/t = options.binary_operators[options.assign_operators[curToken.value]] - var/datum/node/statement/VariableAssignment/stmt = new() - stmt.var_name = new(name) - NextToken() - - if(t) - stmt.value = new t() - stmt.value:exp = new/datum/node/expression/value/variable(stmt.var_name) - stmt.value:exp2 = ParseExpression() - else - stmt.value = ParseExpression() - - curBlock.statements += stmt - -/datum/n_Parser/nS_Parser/proc/ParseFunctionStatement() - if(!istype(curToken, /datum/token/word)) - errors += new/datum/scriptError("Bad identifier in function call.") - return - - var/datum/node/statement/FunctionCall/stmt=new - stmt.func_name = curToken.value - NextToken() //skip function name - if(!CheckToken("(", /datum/token/symbol)) //Check for and skip open parenthesis - return - var/loops = 0 - for() - loops++ - if(loops >= 800) - errors +=new/datum/scriptError("Cannot find ending params.") - return - - if(!curToken) - errors+=new/datum/scriptError/EndOfFile() - return - if(istype(curToken, /datum/token/symbol) && curToken.value == ")") - curBlock.statements += stmt - NextToken() //Skip close parenthesis - return - - var/datum/node/expression/P = ParseParamExpression(check_functions = 1) - stmt.parameters += P - if(istype(curToken, /datum/token/symbol) && curToken.value == ",") - NextToken() +/* + File: Parser +*/ +/* + Class: n_Parser + An object that reads tokens and produces an AST (abstract syntax tree). +*/ +/datum/n_Parser +/* + Var: index + The parser's current position in the token's list. +*/ + var/index = 1 +/* + Var: tokens + A list of tokens in the source code generated by a scanner. +*/ + var/list/tokens = new +/* + Var: errors + A list of fatal errors found by the parser. If there are any items in this list, then it is not safe to run the returned AST. + + See Also: + - +*/ + var/list/errors = new +/* + Var: warnings + A list of non-fatal problems in the script. +*/ + var/list/warnings = new +/* + Var: curToken + The token at in . +*/ + var/datum/token/curToken + var/datum/stack/blocks = new + var/datum/node/BlockDefinition/GlobalBlock/global_block = new + var/datum/node/BlockDefinition/GlobalBlock/curBlock + +/* + Proc: Parse + Reads the tokens and returns the AST's node. Be sure to populate the tokens list before calling this procedure. +*/ +/datum/n_Parser/proc/Parse() + return +/* + Proc: NextToken + Sets to the next token in the list, or null if there are no more tokens. +*/ +/datum/n_Parser/proc/NextToken() + if(index >= tokens.len) + curToken = null + else + curToken = tokens[++index] + return curToken + +/* + Class: nS_Parser + An implmentation of a parser for n_Script. +*/ +/datum/n_Parser/nS_Parser + var/datum/n_scriptOptions/nS_Options/options +/* + Constructor: New + + Parameters: + tokens - A list of tokens to parse. + options - An object used for configuration. +*/ +/datum/n_Parser/nS_Parser/New(tokens[], var/datum/n_scriptOptions/options) + src.tokens = tokens + src.options = options + curBlock = global_block + return ..() + +/datum/n_Parser/nS_Parser/Parse() + ASSERT(tokens) + for(,src.index <= src.tokens.len, src.index++) + curToken = tokens[index] + switch(curToken.type) + if(/datum/token/keyword) + var/datum/n_Keyword/kw = options.keywords[curToken.value] + kw = new kw() + if(kw) + if(!kw.Parse(src)) + return + + if(/datum/token/word) + var/datum/token/ntok + if(index + 1 > tokens.len) + errors += new/datum/scriptError/BadToken(curToken) + continue + + ntok = tokens[index + 1] + + if(!istype(ntok, /datum/token/symbol)) + errors += new/datum/scriptError/BadToken(ntok) + continue + + if(ntok.value == "(") + ParseFunctionStatement() + + else if(options.assign_operators.Find(ntok.value)) + ParseAssignment() + + else + errors += new/datum/scriptError/BadToken(ntok) + continue + + if(!istype(curToken, /datum/token/end)) + errors += new/datum/scriptError/ExpectedToken(";", curToken) + continue + + if(/datum/token/symbol) + if(curToken.value == "}") + if(!EndBlock()) + errors += new/datum/scriptError/BadToken(curToken) + continue + + else + errors += new/datum/scriptError/BadToken(curToken) + continue + + if(/datum/token/end) + warnings += new/datum/scriptError/BadToken(curToken) + continue + + else + errors += new/datum/scriptError/BadToken(curToken) + return + + return global_block + +/datum/n_Parser/nS_Parser/proc/CheckToken(val, type, err = 1, skip = 1) + if(curToken.value != val || !istype(curToken, type)) + if(err) + errors += new/datum/scriptError/ExpectedToken(val, curToken) + return 0 + if(skip) + NextToken() + + return 1 + +/datum/n_Parser/nS_Parser/proc/AddBlock(var/datum/node/BlockDefinition/B) + blocks.Push(curBlock) + curBlock = B + +/datum/n_Parser/nS_Parser/proc/EndBlock() + if(curBlock == global_block) + return 0 + + curBlock = blocks.Pop() + return 1 + +/datum/n_Parser/nS_Parser/proc/ParseAssignment() + var/name = curToken.value + if(!options.IsValidID(name)) + errors += new/datum/scriptError/InvalidID(curToken) + return + + NextToken() + var/t = options.binary_operators[options.assign_operators[curToken.value]] + var/datum/node/statement/VariableAssignment/stmt = new() + stmt.var_name = new(name) + NextToken() + + if(t) + stmt.value = new t() + stmt.value:exp = new/datum/node/expression/value/variable(stmt.var_name) + stmt.value:exp2 = ParseExpression() + else + stmt.value = ParseExpression() + + curBlock.statements += stmt + +/datum/n_Parser/nS_Parser/proc/ParseFunctionStatement() + if(!istype(curToken, /datum/token/word)) + errors += new/datum/scriptError("Bad identifier in function call.") + return + + var/datum/node/statement/FunctionCall/stmt=new + stmt.func_name = curToken.value + NextToken() //skip function name + if(!CheckToken("(", /datum/token/symbol)) //Check for and skip open parenthesis + return + var/loops = 0 + for() + loops++ + if(loops >= 800) + errors +=new/datum/scriptError("Cannot find ending params.") + return + + if(!curToken) + errors+=new/datum/scriptError/EndOfFile() + return + if(istype(curToken, /datum/token/symbol) && curToken.value == ")") + curBlock.statements += stmt + NextToken() //Skip close parenthesis + return + + var/datum/node/expression/P = ParseParamExpression(check_functions = 1) + stmt.parameters += P + if(istype(curToken, /datum/token/symbol) && curToken.value == ",") + NextToken() diff --git a/code/modules/scripting/Scanner/Scanner.dm b/code/modules/scripting/Scanner/Scanner.dm index 011621c8ea8..12f6f22baaf 100644 --- a/code/modules/scripting/Scanner/Scanner.dm +++ b/code/modules/scripting/Scanner/Scanner.dm @@ -1,291 +1,291 @@ -/* - File: Scanner -*/ -/* - Class: n_Scanner - An object responsible for breaking up source code into tokens for use by the parser. -*/ -/datum/n_Scanner - var/code -/* - Var: errors - A list of fatal errors found by the scanner. If there are any items in this list, then it is not safe to parse the returned tokens. - - See Also: - - -*/ - var/list/errors = new -/* - Var: warnings - A list of non-fatal problems in the source code found by the scanner. -*/ - var/list/warnings = new - -/* - Proc: LoadCode - Loads source code. -*/ -/datum/n_Scanner/proc/LoadCode(var/c) - code=c - -/* - Proc: LoadCodeFromFile - Gets the code from a file and calls . -*/ -/datum/n_Scanner/proc/LoadCodeFromFile(var/f) - LoadCode(file2text(f)) - -/* - Proc: Scan - Runs the scanner and returns the resulting list of tokens. Ensure that has been called first. -*/ -/datum/n_Scanner/proc/Scan() - -/* - Class: nS_Scanner - A scanner implementation for n_Script. -*/ -/datum/n_Scanner/nS_Scanner -/* - Variable: codepos - The scanner's position in the source code. -*/ - var/codepos = 1 - var/line = 1 - var/linepos = 0 //column=codepos-linepos - var/datum/n_scriptOptions/nS_Options/options - - var/commenting = 0 - // 1: single-line - // 2: multi-line -/* - Variable: ignore - A list of characters that are ignored by the scanner. - - Default Value: - Whitespace -*/ - var/list/ignore = list(" ", "\t", "\n") //Don't add tokens for whitespace -/* - Variable: end_stmt - A list of characters that end a statement. Each item may only be one character long. - - Default Value: - Semicolon -*/ - var/list/end_stmt = list(";") -/* - Variable: string_delim - A list of characters that can start and end strings. - - Default Value: - Double and single quotes. -*/ - var/list/string_delim = list("\"", "'") -/* - Variable: delim - A list of characters that denote the start of a new token. This list is automatically populated. -*/ - var/list/delim = new - -/* - Macro: COL - The current column number. -*/ - #define COL codepos-linepos - -/* - Constructor: New - Parameters: - code - The source code to tokenize. - options - An object used to configure the scanner. -*/ -/datum/n_Scanner/nS_Scanner/New(var/code, var/datum/n_scriptOptions/nS_Options/options) - . = ..() - ignore += ascii2text(13) //Carriage return - delim += ignore + options.symbols + end_stmt + string_delim - src.options = options - LoadCode(code) - -/datum/n_Scanner/nS_Scanner/Scan() //Creates a list of tokens from source code - var/list/tokens = new - for(, src.codepos <= length(code), src.codepos++) - - var/char = copytext(code, codepos, codepos + 1) - var/nextchar = copytext(code, codepos + 1, codepos + 2) - if(char == "\n") - line++ - linepos = codepos - - if(ignore.Find(char)) - continue - - else if(char == "/" && (nextchar == "*" || nextchar == "/")) - ReadComment() - - else if(end_stmt.Find(char)) - tokens += new/datum/token/end(char, line, COL) - - else if(string_delim.Find(char)) - codepos++ //skip string delimiter - tokens += ReadString(char) - - else if(options.CanStartID(char)) - tokens += ReadWord() - - else if(options.IsDigit(char)) - tokens += ReadNumber() - - else if(options.symbols.Find(char)) - tokens += ReadSymbol() - - - codepos = initial(codepos) - line = initial(line) - linepos = initial(linepos) - return tokens - - -/* - Proc: ReadString - Reads a string in the source code into a token. - - Parameters: - start - The character used to start the string. -*/ -/datum/n_Scanner/nS_Scanner/proc/ReadString(start) - var/buf - for(, codepos <= length(code), codepos++)//codepos to length(code)) - var/char = copytext(code, codepos, codepos + 1) - switch(char) - if("\\") //Backslash (\) encountered in string - codepos++ //Skip next character in string, since it was escaped by a backslash - char = copytext(code, codepos, codepos+1) - switch(char) - if("\\") //Double backslash - buf += "\\" - if("n") //\n Newline - buf += "\n" - else - if(char == start) //\" Doublequote - buf += start - else //Unknown escaped text - buf += char - if("\n") - . = new/datum/token/string(buf, line, COL) - errors += new/datum/scriptError("Unterminated string. Newline reached.", .) - line++ - linepos = codepos - break - else - if(char == start) //string delimiter found, end string - break - else - buf += char //Just a normal character in a string - if(!.) - return new/datum/token/string(buf, line, COL) - -/* - Proc: ReadWord - Reads characters separated by an item in into a token. -*/ -/datum/n_Scanner/nS_Scanner/proc/ReadWord() - var/char = copytext(code, codepos, codepos + 1) - var/buf - - while(!delim.Find(char) && codepos <= length(code)) - buf += char - char = copytext(code, ++codepos, codepos + 1) - codepos-- //allow main Scan() proc to read the delimiter - if(options.keywords.Find(buf)) - return new/datum/token/keyword(buf, line, COL) - else - return new/datum/token/word(buf, line, COL) - -/* - Proc: ReadSymbol - Reads a symbol into a token. -*/ -/datum/n_Scanner/nS_Scanner/proc/ReadSymbol() - var/char=copytext(code, codepos, codepos + 1) - var/buf - - while(options.symbols.Find(buf + char)) - buf += char - if(++codepos > length(code)) break - char = copytext(code, codepos, codepos + 1) - - codepos-- //allow main Scan() proc to read the next character - return new /datum/token/symbol(buf, line, COL) - -/* - Proc: ReadNumber - Reads a number into a token. -*/ -/datum/n_Scanner/nS_Scanner/proc/ReadNumber() - var/char = copytext(code, codepos, codepos + 1) - var/buf - var/dec = 0 - - while(options.IsDigit(char) || (char == "." && !dec)) - if(char == ".") - dec = 1 - - buf += char - codepos++ - char = copytext(code, codepos, codepos + 1) - - var/datum/token/number/T = new(buf, line, COL) - if(isnull(text2num(buf))) - errors += new/datum/scriptError("Bad number: ", T) - T.value = 0 - - codepos-- //allow main Scan() proc to read the next character - return T - -/* - Proc: ReadComment - Reads a comment and outputs the type of comment -*/ - -/datum/n_Scanner/nS_Scanner/proc/ReadComment() - var/char = copytext(code, codepos, codepos + 1) - var/nextchar = copytext(code, codepos + 1, codepos + 2) - var/charstring = char + nextchar - var/comm = 1 - // 1: single-line comment - // 2: multi-line comment - var/expectedend = 0 - - if(charstring == "//" || charstring == "/*") - if(charstring == "/*") - comm = 2 // starts a multi-line comment - - while(comm) - if(++codepos > length(code)) - break - - if(expectedend) // ending statement expected... - char = copytext(code, codepos, codepos + 1) - if(char == "/") // ending statement found - beak the comment - comm = 0 - break - - if(comm == 2) - // multi-line comments are broken by ending statements - char = copytext(code, codepos, codepos + 1) - if(char == "*") - expectedend = 1 - continue - else - char = copytext(code, codepos, codepos + 1) - if(char == "\n") - comm = 0 - break - - if(expectedend) - expectedend = 0 - - if(comm == 2) - errors += new/datum/scriptError/UnterminatedComment() - +/* + File: Scanner +*/ +/* + Class: n_Scanner + An object responsible for breaking up source code into tokens for use by the parser. +*/ +/datum/n_Scanner + var/code +/* + Var: errors + A list of fatal errors found by the scanner. If there are any items in this list, then it is not safe to parse the returned tokens. + + See Also: + - +*/ + var/list/errors = new +/* + Var: warnings + A list of non-fatal problems in the source code found by the scanner. +*/ + var/list/warnings = new + +/* + Proc: LoadCode + Loads source code. +*/ +/datum/n_Scanner/proc/LoadCode(var/c) + code=c + +/* + Proc: LoadCodeFromFile + Gets the code from a file and calls . +*/ +/datum/n_Scanner/proc/LoadCodeFromFile(var/f) + LoadCode(file2text(f)) + +/* + Proc: Scan + Runs the scanner and returns the resulting list of tokens. Ensure that has been called first. +*/ +/datum/n_Scanner/proc/Scan() + +/* + Class: nS_Scanner + A scanner implementation for n_Script. +*/ +/datum/n_Scanner/nS_Scanner +/* + Variable: codepos + The scanner's position in the source code. +*/ + var/codepos = 1 + var/line = 1 + var/linepos = 0 //column=codepos-linepos + var/datum/n_scriptOptions/nS_Options/options + + var/commenting = 0 + // 1: single-line + // 2: multi-line +/* + Variable: ignore + A list of characters that are ignored by the scanner. + + Default Value: + Whitespace +*/ + var/list/ignore = list(" ", "\t", "\n") //Don't add tokens for whitespace +/* + Variable: end_stmt + A list of characters that end a statement. Each item may only be one character long. + + Default Value: + Semicolon +*/ + var/list/end_stmt = list(";") +/* + Variable: string_delim + A list of characters that can start and end strings. + + Default Value: + Double and single quotes. +*/ + var/list/string_delim = list("\"", "'") +/* + Variable: delim + A list of characters that denote the start of a new token. This list is automatically populated. +*/ + var/list/delim = new + +/* + Macro: COL + The current column number. +*/ + #define COL codepos-linepos + +/* + Constructor: New + Parameters: + code - The source code to tokenize. + options - An object used to configure the scanner. +*/ +/datum/n_Scanner/nS_Scanner/New(var/code, var/datum/n_scriptOptions/nS_Options/options) + . = ..() + ignore += ascii2text(13) //Carriage return + delim += ignore + options.symbols + end_stmt + string_delim + src.options = options + LoadCode(code) + +/datum/n_Scanner/nS_Scanner/Scan() //Creates a list of tokens from source code + var/list/tokens = new + for(, src.codepos <= length(code), src.codepos++) + + var/char = copytext(code, codepos, codepos + 1) + var/nextchar = copytext(code, codepos + 1, codepos + 2) + if(char == "\n") + line++ + linepos = codepos + + if(ignore.Find(char)) + continue + + else if(char == "/" && (nextchar == "*" || nextchar == "/")) + ReadComment() + + else if(end_stmt.Find(char)) + tokens += new/datum/token/end(char, line, COL) + + else if(string_delim.Find(char)) + codepos++ //skip string delimiter + tokens += ReadString(char) + + else if(options.CanStartID(char)) + tokens += ReadWord() + + else if(options.IsDigit(char)) + tokens += ReadNumber() + + else if(options.symbols.Find(char)) + tokens += ReadSymbol() + + + codepos = initial(codepos) + line = initial(line) + linepos = initial(linepos) + return tokens + + +/* + Proc: ReadString + Reads a string in the source code into a token. + + Parameters: + start - The character used to start the string. +*/ +/datum/n_Scanner/nS_Scanner/proc/ReadString(start) + var/buf + for(, codepos <= length(code), codepos++)//codepos to length(code)) + var/char = copytext(code, codepos, codepos + 1) + switch(char) + if("\\") //Backslash (\) encountered in string + codepos++ //Skip next character in string, since it was escaped by a backslash + char = copytext(code, codepos, codepos+1) + switch(char) + if("\\") //Double backslash + buf += "\\" + if("n") //\n Newline + buf += "\n" + else + if(char == start) //\" Doublequote + buf += start + else //Unknown escaped text + buf += char + if("\n") + . = new/datum/token/string(buf, line, COL) + errors += new/datum/scriptError("Unterminated string. Newline reached.", .) + line++ + linepos = codepos + break + else + if(char == start) //string delimiter found, end string + break + else + buf += char //Just a normal character in a string + if(!.) + return new/datum/token/string(buf, line, COL) + +/* + Proc: ReadWord + Reads characters separated by an item in into a token. +*/ +/datum/n_Scanner/nS_Scanner/proc/ReadWord() + var/char = copytext(code, codepos, codepos + 1) + var/buf + + while(!delim.Find(char) && codepos <= length(code)) + buf += char + char = copytext(code, ++codepos, codepos + 1) + codepos-- //allow main Scan() proc to read the delimiter + if(options.keywords.Find(buf)) + return new/datum/token/keyword(buf, line, COL) + else + return new/datum/token/word(buf, line, COL) + +/* + Proc: ReadSymbol + Reads a symbol into a token. +*/ +/datum/n_Scanner/nS_Scanner/proc/ReadSymbol() + var/char=copytext(code, codepos, codepos + 1) + var/buf + + while(options.symbols.Find(buf + char)) + buf += char + if(++codepos > length(code)) break + char = copytext(code, codepos, codepos + 1) + + codepos-- //allow main Scan() proc to read the next character + return new /datum/token/symbol(buf, line, COL) + +/* + Proc: ReadNumber + Reads a number into a token. +*/ +/datum/n_Scanner/nS_Scanner/proc/ReadNumber() + var/char = copytext(code, codepos, codepos + 1) + var/buf + var/dec = 0 + + while(options.IsDigit(char) || (char == "." && !dec)) + if(char == ".") + dec = 1 + + buf += char + codepos++ + char = copytext(code, codepos, codepos + 1) + + var/datum/token/number/T = new(buf, line, COL) + if(isnull(text2num(buf))) + errors += new/datum/scriptError("Bad number: ", T) + T.value = 0 + + codepos-- //allow main Scan() proc to read the next character + return T + +/* + Proc: ReadComment + Reads a comment and outputs the type of comment +*/ + +/datum/n_Scanner/nS_Scanner/proc/ReadComment() + var/char = copytext(code, codepos, codepos + 1) + var/nextchar = copytext(code, codepos + 1, codepos + 2) + var/charstring = char + nextchar + var/comm = 1 + // 1: single-line comment + // 2: multi-line comment + var/expectedend = 0 + + if(charstring == "//" || charstring == "/*") + if(charstring == "/*") + comm = 2 // starts a multi-line comment + + while(comm) + if(++codepos > length(code)) + break + + if(expectedend) // ending statement expected... + char = copytext(code, codepos, codepos + 1) + if(char == "/") // ending statement found - beak the comment + comm = 0 + break + + if(comm == 2) + // multi-line comments are broken by ending statements + char = copytext(code, codepos, codepos + 1) + if(char == "*") + expectedend = 1 + continue + else + char = copytext(code, codepos, codepos + 1) + if(char == "\n") + comm = 0 + break + + if(expectedend) + expectedend = 0 + + if(comm == 2) + errors += new/datum/scriptError/UnterminatedComment() + diff --git a/code/modules/scripting/Scanner/Tokens.dm b/code/modules/scripting/Scanner/Tokens.dm index acf7bbbad99..f27fa675d6b 100644 --- a/code/modules/scripting/Scanner/Tokens.dm +++ b/code/modules/scripting/Scanner/Tokens.dm @@ -1,40 +1,40 @@ -/* - Class: Token - Represents an entity and position in the source code. -*/ -/datum/token - var/value - var/line - var/column - -/datum/token/New(v, l = 0, c = 0) - value = v - line = l - column = c - -/datum/token/string - -/datum/token/symbol - -/datum/token/word - -/datum/token/keyword - -/datum/token/number/New() - . = ..() - if(!isnum(value)) - value = text2num(value) - ASSERT(!isnull(value)) - -/datum/token/accessor - var/object - var/member - -/datum/token/accessor/New(object, member, l = 0, c = 0) - src.object = object - src.member = member - src.value = "[object].[member]" //for debugging only - src.line = l - src.column = c - -/datum/token/end +/* + Class: Token + Represents an entity and position in the source code. +*/ +/datum/token + var/value + var/line + var/column + +/datum/token/New(v, l = 0, c = 0) + value = v + line = l + column = c + +/datum/token/string + +/datum/token/symbol + +/datum/token/word + +/datum/token/keyword + +/datum/token/number/New() + . = ..() + if(!isnum(value)) + value = text2num(value) + ASSERT(!isnull(value)) + +/datum/token/accessor + var/object + var/member + +/datum/token/accessor/New(object, member, l = 0, c = 0) + src.object = object + src.member = member + src.value = "[object].[member]" //for debugging only + src.line = l + src.column = c + +/datum/token/end diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security levels/keycard authentication.dm index 23b7ce727dc..bbd61056800 100644 --- a/code/modules/security levels/keycard authentication.dm +++ b/code/modules/security levels/keycard authentication.dm @@ -1,198 +1,198 @@ -var/global/list/obj/machinery/keycard_auth/authenticators = list() - -/obj/machinery/keycard_auth - name = "Keycard Authentication Device" - desc = "This device is used to trigger station functions, which require more than one ID card to authenticate." - icon = 'icons/obj/monitors.dmi' - icon_state = "auth_off" - var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made. - var/event = "" - var/screen = 1 - var/confirmed = 0 //This variable is set by the device that confirms the request. - var/confirm_delay = 20 //(2 seconds) - var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device. - var/obj/machinery/keycard_auth/event_source - var/mob/event_triggered_by - var/mob/event_confirmed_by - //1 = select event - //2 = authenticate - anchored = 1.0 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 6 - power_channel = ENVIRON - -/obj/machinery/keycard_auth/New() - ..() - authenticators += src - -/obj/machinery/keycard_auth/attack_ai(mob/user as mob) +var/global/list/obj/machinery/keycard_auth/authenticators = list() + +/obj/machinery/keycard_auth + name = "Keycard Authentication Device" + desc = "This device is used to trigger station functions, which require more than one ID card to authenticate." + icon = 'icons/obj/monitors.dmi' + icon_state = "auth_off" + var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made. + var/event = "" + var/screen = 1 + var/confirmed = 0 //This variable is set by the device that confirms the request. + var/confirm_delay = 20 //(2 seconds) + var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device. + var/obj/machinery/keycard_auth/event_source + var/mob/event_triggered_by + var/mob/event_confirmed_by + //1 = select event + //2 = authenticate + anchored = 1.0 + use_power = 1 + idle_power_usage = 2 + active_power_usage = 6 + power_channel = ENVIRON + +/obj/machinery/keycard_auth/New() + ..() + authenticators += src + +/obj/machinery/keycard_auth/attack_ai(mob/user as mob) to_chat(user, "The station AI is not to interact with these devices.") - return - -/obj/machinery/keycard_auth/attack_paw(mob/user as mob) + return + +/obj/machinery/keycard_auth/attack_paw(mob/user as mob) to_chat(user, "You are too primitive to use this device.") - return - -/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(stat & (NOPOWER|BROKEN)) + return + +/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(stat & (NOPOWER|BROKEN)) to_chat(user, "This device is not powered.") - return - if(istype(W,/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/ID = W - if(access_keycard_auth in ID.access) - if(active == 1) - //This is not the device that made the initial request. It is the device confirming the request. - if(event_source) - event_source.confirmed = 1 - event_source.event_confirmed_by = usr - else if(screen == 2) - event_triggered_by = usr - broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices - -/obj/machinery/keycard_auth/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER - icon_state = "auth_off" - else - stat |= NOPOWER - -/obj/machinery/keycard_auth/Destroy() - ..() - authenticators -= src - -/obj/machinery/keycard_auth/attack_hand(mob/user as mob) - if(user.stat || stat & (NOPOWER|BROKEN)) + return + if(istype(W,/obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/ID = W + if(access_keycard_auth in ID.access) + if(active == 1) + //This is not the device that made the initial request. It is the device confirming the request. + if(event_source) + event_source.confirmed = 1 + event_source.event_confirmed_by = usr + else if(screen == 2) + event_triggered_by = usr + broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices + +/obj/machinery/keycard_auth/power_change() + if(powered(ENVIRON)) + stat &= ~NOPOWER + icon_state = "auth_off" + else + stat |= NOPOWER + +/obj/machinery/keycard_auth/Destroy() + ..() + authenticators -= src + +/obj/machinery/keycard_auth/attack_hand(mob/user as mob) + if(user.stat || stat & (NOPOWER|BROKEN)) to_chat(user, "This device is not powered.") - return - if(busy) + return + if(busy) to_chat(user, "This device is busy.") - return - - user.set_machine(src) - - var/dat = "

    Keycard Authentication Device

    " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\security levels\keycard authentication.dm:66: dat += "This device is used to trigger some high security events. It requires the simultaneous swipe of two high-level ID cards." - dat += {"This device is used to trigger some high security events. It requires the simultaneous swipe of two high-level ID cards. -


    "} - // END AUTOFIX - if(screen == 1) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\security levels\keycard authentication.dm:70: dat += "Select an event to trigger:
      " - dat += {"Select an event to trigger:"} - // END AUTOFIX - user << browse(dat, "window=keycard_auth;size=500x250") - if(screen == 2) - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\security levels\keycard authentication.dm:78: dat += "Please swipe your card to authorize the following event: [event]" - dat += {"Please swipe your card to authorize the following event: [event] -

      Back"} - // END AUTOFIX - user << browse(dat, "window=keycard_auth;size=500x250") - return - - -/obj/machinery/keycard_auth/Topic(href, href_list) - if(..()) return 1 - if(busy) + return + + user.set_machine(src) + + var/dat = "

      Keycard Authentication Device

      " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\security levels\keycard authentication.dm:66: dat += "This device is used to trigger some high security events. It requires the simultaneous swipe of two high-level ID cards." + dat += {"This device is used to trigger some high security events. It requires the simultaneous swipe of two high-level ID cards. +


      "} + // END AUTOFIX + if(screen == 1) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\security levels\keycard authentication.dm:70: dat += "Select an event to trigger:
        " + dat += {"Select an event to trigger:"} + // END AUTOFIX + user << browse(dat, "window=keycard_auth;size=500x250") + if(screen == 2) + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\\modules\security levels\keycard authentication.dm:78: dat += "Please swipe your card to authorize the following event: [event]" + dat += {"Please swipe your card to authorize the following event: [event] +

        Back"} + // END AUTOFIX + user << browse(dat, "window=keycard_auth;size=500x250") + return + + +/obj/machinery/keycard_auth/Topic(href, href_list) + if(..()) return 1 + if(busy) to_chat(usr, "This device is busy.") - return - if(usr.stat || stat & (BROKEN|NOPOWER)) + return + if(usr.stat || stat & (BROKEN|NOPOWER)) to_chat(usr, "This device is without power.") - return - if(href_list["triggerevent"]) - event = href_list["triggerevent"] - screen = 2 - if(href_list["reset"]) - reset() - - updateUsrDialog() - add_fingerprint(usr) - return - -/obj/machinery/keycard_auth/proc/reset() - active = 0 - event = "" - screen = 1 - confirmed = 0 - event_source = null - icon_state = "auth_off" - event_triggered_by = null - event_confirmed_by = null - -/obj/machinery/keycard_auth/proc/broadcast_request() - icon_state = "auth_on" - for(var/obj/machinery/keycard_auth/KA in authenticators) - if(KA == src) continue - KA.reset() - spawn() - KA.receive_request(src) - - sleep(confirm_delay) - if(confirmed) - confirmed = 0 - trigger_event(event) - log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]") - message_admins("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]", 1) - reset() - -/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source) - if(stat & (BROKEN|NOPOWER)) - return - event_source = source - busy = 1 - active = 1 - icon_state = "auth_on" - - sleep(confirm_delay) - - event_source = null - icon_state = "auth_off" - active = 0 - busy = 0 - -/obj/machinery/keycard_auth/proc/trigger_event() - switch(event) - if("Red alert") - set_security_level(SEC_LEVEL_RED) - feedback_inc("alert_keycard_auth_red",1) - if("Grant Emergency Maintenance Access") - make_maint_all_access() - feedback_inc("alert_keycard_auth_maintGrant",1) - if("Revoke Emergency Maintenance Access") - revoke_maint_all_access() - feedback_inc("alert_keycard_auth_maintRevoke",1) - if("Emergency Response Team") - trigger_armed_response_team(1) - feedback_inc("alert_keycard_auth_ert",1) - -var/global/maint_all_access = 0 - -/proc/make_maint_all_access() - maint_all_access = 1 + return + if(href_list["triggerevent"]) + event = href_list["triggerevent"] + screen = 2 + if(href_list["reset"]) + reset() + + updateUsrDialog() + add_fingerprint(usr) + return + +/obj/machinery/keycard_auth/proc/reset() + active = 0 + event = "" + screen = 1 + confirmed = 0 + event_source = null + icon_state = "auth_off" + event_triggered_by = null + event_confirmed_by = null + +/obj/machinery/keycard_auth/proc/broadcast_request() + icon_state = "auth_on" + for(var/obj/machinery/keycard_auth/KA in authenticators) + if(KA == src) continue + KA.reset() + spawn() + KA.receive_request(src) + + sleep(confirm_delay) + if(confirmed) + confirmed = 0 + trigger_event(event) + log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]") + message_admins("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]", 1) + reset() + +/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source) + if(stat & (BROKEN|NOPOWER)) + return + event_source = source + busy = 1 + active = 1 + icon_state = "auth_on" + + sleep(confirm_delay) + + event_source = null + icon_state = "auth_off" + active = 0 + busy = 0 + +/obj/machinery/keycard_auth/proc/trigger_event() + switch(event) + if("Red alert") + set_security_level(SEC_LEVEL_RED) + feedback_inc("alert_keycard_auth_red",1) + if("Grant Emergency Maintenance Access") + make_maint_all_access() + feedback_inc("alert_keycard_auth_maintGrant",1) + if("Revoke Emergency Maintenance Access") + revoke_maint_all_access() + feedback_inc("alert_keycard_auth_maintRevoke",1) + if("Emergency Response Team") + trigger_armed_response_team(1) + feedback_inc("alert_keycard_auth_ert",1) + +var/global/maint_all_access = 0 + +/proc/make_maint_all_access() + maint_all_access = 1 to_chat(world, "Attention!") to_chat(world, "The maintenance access requirement has been revoked on all airlocks.") - -/proc/revoke_maint_all_access() - maint_all_access = 0 + +/proc/revoke_maint_all_access() + maint_all_access = 0 to_chat(world, "Attention!") to_chat(world, "The maintenance access requirement has been readded on all maintenance airlocks.") - -/obj/machinery/door/airlock/allowed(mob/M) - if(maint_all_access && src.check_access_list(list(access_maint_tunnels))) - return 1 + +/obj/machinery/door/airlock/allowed(mob/M) + if(maint_all_access && src.check_access_list(list(access_maint_tunnels))) + return 1 return ..(M) \ No newline at end of file diff --git a/code/modules/security levels/security levels.dm b/code/modules/security levels/security levels.dm index 95a473d960e..c8ee6d1a822 100644 --- a/code/modules/security levels/security levels.dm +++ b/code/modules/security levels/security levels.dm @@ -1,116 +1,116 @@ -/var/security_level = 0 -//0 = code green -//1 = code blue -//2 = code red -//3 = code delta - -//config.alert_desc_blue_downto - -/proc/set_security_level(var/level) - switch(level) - if("green") - level = SEC_LEVEL_GREEN - if("blue") - level = SEC_LEVEL_BLUE - if("red") - level = SEC_LEVEL_RED - if("delta") - level = SEC_LEVEL_DELTA - - //Will not be announced if you try to set to the same level as it already is - if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) - switch(level) - if(SEC_LEVEL_GREEN) +/var/security_level = 0 +//0 = code green +//1 = code blue +//2 = code red +//3 = code delta + +//config.alert_desc_blue_downto + +/proc/set_security_level(var/level) + switch(level) + if("green") + level = SEC_LEVEL_GREEN + if("blue") + level = SEC_LEVEL_BLUE + if("red") + level = SEC_LEVEL_RED + if("delta") + level = SEC_LEVEL_DELTA + + //Will not be announced if you try to set to the same level as it already is + if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) + switch(level) + if(SEC_LEVEL_GREEN) to_chat(world, "Attention! Security level lowered to green") to_chat(world, "[config.alert_desc_green]") - security_level = SEC_LEVEL_GREEN - for(var/obj/machinery/firealarm/FA in machines) - if(FA.z == 1) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_green") - if(SEC_LEVEL_BLUE) - if(security_level < SEC_LEVEL_BLUE) + security_level = SEC_LEVEL_GREEN + for(var/obj/machinery/firealarm/FA in machines) + if(FA.z == 1) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_green") + if(SEC_LEVEL_BLUE) + if(security_level < SEC_LEVEL_BLUE) to_chat(world, "Attention! Security level elevated to blue") to_chat(world, "[config.alert_desc_blue_upto]") - else + else to_chat(world, "Attention! Security level lowered to blue") to_chat(world, "[config.alert_desc_blue_downto]") - security_level = SEC_LEVEL_BLUE - for(var/obj/machinery/firealarm/FA in machines) - if(FA.z == 1) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue") - if(SEC_LEVEL_RED) - if(security_level < SEC_LEVEL_RED) + security_level = SEC_LEVEL_BLUE + for(var/obj/machinery/firealarm/FA in machines) + if(FA.z == 1) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue") + if(SEC_LEVEL_RED) + if(security_level < SEC_LEVEL_RED) to_chat(world, "Attention! Code red!") to_chat(world, "[config.alert_desc_red_upto]") - else + else to_chat(world, "Attention! Code red!") to_chat(world, "[config.alert_desc_red_downto]") - security_level = SEC_LEVEL_RED - - /* - At the time of commit, setting status displays didn't work properly - var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) - if(CC) - CC.post_status("alert", "redalert")*/ - - for(var/obj/machinery/firealarm/FA in machines) - if(FA.z == 1) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") - - if(SEC_LEVEL_DELTA) + security_level = SEC_LEVEL_RED + + /* - At the time of commit, setting status displays didn't work properly + var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world) + if(CC) + CC.post_status("alert", "redalert")*/ + + for(var/obj/machinery/firealarm/FA in machines) + if(FA.z == 1) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") + + if(SEC_LEVEL_DELTA) to_chat(world, "Attention! Delta security level reached!") to_chat(world, "[config.alert_desc_delta]") - security_level = SEC_LEVEL_DELTA - for(var/obj/machinery/firealarm/FA in machines) - if(FA.z == 1) - FA.overlays = list() - FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta") - else - return - -/proc/get_security_level() - switch(security_level) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/num2seclevel(var/num) - switch(num) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/seclevel2num(var/seclevel) - switch( lowertext(seclevel) ) - if("green") - return SEC_LEVEL_GREEN - if("blue") - return SEC_LEVEL_BLUE - if("red") - return SEC_LEVEL_RED - if("delta") - return SEC_LEVEL_DELTA - - -/*DEBUG -/mob/verb/set_thing0() - set_security_level(0) -/mob/verb/set_thing1() - set_security_level(1) -/mob/verb/set_thing2() - set_security_level(2) -/mob/verb/set_thing3() - set_security_level(3) + security_level = SEC_LEVEL_DELTA + for(var/obj/machinery/firealarm/FA in machines) + if(FA.z == 1) + FA.overlays = list() + FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta") + else + return + +/proc/get_security_level() + switch(security_level) + if(SEC_LEVEL_GREEN) + return "green" + if(SEC_LEVEL_BLUE) + return "blue" + if(SEC_LEVEL_RED) + return "red" + if(SEC_LEVEL_DELTA) + return "delta" + +/proc/num2seclevel(var/num) + switch(num) + if(SEC_LEVEL_GREEN) + return "green" + if(SEC_LEVEL_BLUE) + return "blue" + if(SEC_LEVEL_RED) + return "red" + if(SEC_LEVEL_DELTA) + return "delta" + +/proc/seclevel2num(var/seclevel) + switch( lowertext(seclevel) ) + if("green") + return SEC_LEVEL_GREEN + if("blue") + return SEC_LEVEL_BLUE + if("red") + return SEC_LEVEL_RED + if("delta") + return SEC_LEVEL_DELTA + + +/*DEBUG +/mob/verb/set_thing0() + set_security_level(0) +/mob/verb/set_thing1() + set_security_level(1) +/mob/verb/set_thing2() + set_security_level(2) +/mob/verb/set_thing3() + set_security_level(3) */ \ No newline at end of file diff --git a/code/names.dm b/code/names.dm index 477c13bfd12..5abbefcfc63 100644 --- a/code/names.dm +++ b/code/names.dm @@ -1,18 +1,18 @@ -var/list/ai_names = file2list("config/names/ai.txt") -var/list/wizard_first = file2list("config/names/wizardfirst.txt") -var/list/wizard_second = file2list("config/names/wizardsecond.txt") -var/list/ninja_titles = file2list("config/names/ninjatitle.txt") -var/list/ninja_names = file2list("config/names/ninjaname.txt") -var/list/commando_names = file2list("config/names/death_commando.txt") -var/list/first_names_male = file2list("config/names/first_male.txt") -var/list/first_names_female = file2list("config/names/first_female.txt") -var/list/last_names = file2list("config/names/last.txt") -var/list/clown_names = file2list("config/names/clown.txt") - - -var/list/verbs = file2list("config/names/verbs.txt") -var/list/adjectives = file2list("config/names/adjectives.txt") -//loaded on startup because of " -//would include in rsc if ' was used - +var/list/ai_names = file2list("config/names/ai.txt") +var/list/wizard_first = file2list("config/names/wizardfirst.txt") +var/list/wizard_second = file2list("config/names/wizardsecond.txt") +var/list/ninja_titles = file2list("config/names/ninjatitle.txt") +var/list/ninja_names = file2list("config/names/ninjaname.txt") +var/list/commando_names = file2list("config/names/death_commando.txt") +var/list/first_names_male = file2list("config/names/first_male.txt") +var/list/first_names_female = file2list("config/names/first_female.txt") +var/list/last_names = file2list("config/names/last.txt") +var/list/clown_names = file2list("config/names/clown.txt") + + +var/list/verbs = file2list("config/names/verbs.txt") +var/list/adjectives = file2list("config/names/adjectives.txt") +//loaded on startup because of " +//would include in rsc if ' was used + var/list/vox_name_syllables = list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah") \ No newline at end of file diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 5b494e9fdfb..102367fc84b 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -1,86 +1,86 @@ -#define world_style {"\"body {font-family: Verdana, sans-serif;} -h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;} -em {font-style: normal; font-weight: bold;} -.motd {color: #638500; font-family: Verdana, sans-serif;} -.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 - {color: #638500; text-decoration: underline;} -.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover - {color: #638500;} -.prefix { font-weight: bold;} -.ooc { font-weight: bold;} -.adminobserverooc {color: #0099cc; font-weight: bold;} -.adminooc {color: #b82e00; font-weight: bold;} -.adminobserver {color: #996600; font-weight: bold;} -.admin {color: #386aff; font-weight: bold;} -.adminsay {color: #9611D4; font-weight: bold;} -.name { font-weight: bold;} -.say {} -.siliconsay {font-family: 'Courier New', Courier, monospace;} -.deadsay {color: #5c00e6;} -.radio {color: #008000;} -.deptradio {color: #993399;} -.comradio {color: #193A7A;} -.syndradio {color: #6d3f40;} -.dsquadradio {color: #686868;} -.resteamradio {color: #18BC46;} -.aiprivradio {color: #ff00ff;} -.centradio {color: #5C5C8A;} -.secradio {color: #A30000;} -.engradio {color: #A66300;} -.medradio {color: #008160;} -.sciradio {color: #993399;} -.supradio {color: #5F4519;} -.serradio {color: #3399CC;} -.djradio {color: #663300;} -.mommi {color: navy;} -.alert {color: #ff0000;} -h1.alert, h2.alert {color: #000000;} -.emote { font-style: italic;} -.selecteddna {color: #FFFFFF; background-color: #001B1B} -.attack {color: #ff0000;} -.moderate {color: #CC0000;} -.disarm {color: #990000;} -.passive {color: #660000;} -.danger {color: #ff0000; font-weight: bold;} -.userdanger {color: #ff0000; font-weight: bold; font-size: 120%} -.warning {color: #ff0000; font-style: italic;} -.sinister {color: #800080; font-weight: bold; font-style: italic;} /* /vg/ */ -.blob {color: #006221; font-weight: bold; font-style: italic;} -.confirm {color: #00af3b;} -.rose {color: #ff5050;} -.info {color: #0000CC;} -.notice {color: #000099;} -.bnotice {color: #000099; font-weight: bold;} -.sans {font-family: 'Comic Sans MS', cursive, sans-serif;} -.alien {color: #543354;} -.ancient {color: #008B8B; font-stye: italic;} -.newscaster {color: #800000;} -.mod {color: #735638; font-weight: bold;} -.modooc {color: #000000; font-weight: bold;} -.adminmod {color: #402A14; font-weight: bold;} -.tajaran {color: #803B56;} -.skrell {color: #00CED1;} -.solcom {color: #22228B;} -.soghun {color: #228B22;} -.vox {color: #AA00AA;} -.rough {font-family: 'Trebuchet MS', cursive, sans-serif;} -.say_quote {font-family: Georgia, Verdana, sans-serif;} -.cult {color: #800080; font-weight: bold; font-style: italic;} -.interface {color: #330033;} -.big {font-size: 150%;} -.bold {font-weight: bold;} -.center {text-align: center;} -.red {color: #FF0000;} -.grey {color: #585858; font-family: Dotum, sans-serif;} -.skeleton {color: #585858; font-weight: bold; font-style: italic;} -.gutter {color: #61380B; font-style: italic;} -/* /vg/ */ -.good {color: green;} -.average {color: #FF8000;} -.bad {color: #FF0000;} -/* /vg/ Saycode Rewrite */ -.italics, .talkinto {font-style:italic;} -.whisper {font-style:italic;color:#333333;} -/* Recruiting stuff */ -.recruit {color: #5c00e6; font-weight: bold; font-style: italic;} -"} +#define world_style {"\"body {font-family: Verdana, sans-serif;} +h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;} +em {font-style: normal; font-weight: bold;} +.motd {color: #638500; font-family: Verdana, sans-serif;} +.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 + {color: #638500; text-decoration: underline;} +.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover + {color: #638500;} +.prefix { font-weight: bold;} +.ooc { font-weight: bold;} +.adminobserverooc {color: #0099cc; font-weight: bold;} +.adminooc {color: #b82e00; font-weight: bold;} +.adminobserver {color: #996600; font-weight: bold;} +.admin {color: #386aff; font-weight: bold;} +.adminsay {color: #9611D4; font-weight: bold;} +.name { font-weight: bold;} +.say {} +.siliconsay {font-family: 'Courier New', Courier, monospace;} +.deadsay {color: #5c00e6;} +.radio {color: #008000;} +.deptradio {color: #993399;} +.comradio {color: #193A7A;} +.syndradio {color: #6d3f40;} +.dsquadradio {color: #686868;} +.resteamradio {color: #18BC46;} +.aiprivradio {color: #ff00ff;} +.centradio {color: #5C5C8A;} +.secradio {color: #A30000;} +.engradio {color: #A66300;} +.medradio {color: #008160;} +.sciradio {color: #993399;} +.supradio {color: #5F4519;} +.serradio {color: #3399CC;} +.djradio {color: #663300;} +.mommi {color: navy;} +.alert {color: #ff0000;} +h1.alert, h2.alert {color: #000000;} +.emote { font-style: italic;} +.selecteddna {color: #FFFFFF; background-color: #001B1B} +.attack {color: #ff0000;} +.moderate {color: #CC0000;} +.disarm {color: #990000;} +.passive {color: #660000;} +.danger {color: #ff0000; font-weight: bold;} +.userdanger {color: #ff0000; font-weight: bold; font-size: 120%} +.warning {color: #ff0000; font-style: italic;} +.sinister {color: #800080; font-weight: bold; font-style: italic;} /* /vg/ */ +.blob {color: #006221; font-weight: bold; font-style: italic;} +.confirm {color: #00af3b;} +.rose {color: #ff5050;} +.info {color: #0000CC;} +.notice {color: #000099;} +.bnotice {color: #000099; font-weight: bold;} +.sans {font-family: 'Comic Sans MS', cursive, sans-serif;} +.alien {color: #543354;} +.ancient {color: #008B8B; font-stye: italic;} +.newscaster {color: #800000;} +.mod {color: #735638; font-weight: bold;} +.modooc {color: #000000; font-weight: bold;} +.adminmod {color: #402A14; font-weight: bold;} +.tajaran {color: #803B56;} +.skrell {color: #00CED1;} +.solcom {color: #22228B;} +.soghun {color: #228B22;} +.vox {color: #AA00AA;} +.rough {font-family: 'Trebuchet MS', cursive, sans-serif;} +.say_quote {font-family: Georgia, Verdana, sans-serif;} +.cult {color: #800080; font-weight: bold; font-style: italic;} +.interface {color: #330033;} +.big {font-size: 150%;} +.bold {font-weight: bold;} +.center {text-align: center;} +.red {color: #FF0000;} +.grey {color: #585858; font-family: Dotum, sans-serif;} +.skeleton {color: #585858; font-weight: bold; font-style: italic;} +.gutter {color: #61380B; font-style: italic;} +/* /vg/ */ +.good {color: green;} +.average {color: #FF8000;} +.bad {color: #FF0000;} +/* /vg/ Saycode Rewrite */ +.italics, .talkinto {font-style:italic;} +.whisper {font-style:italic;color:#333333;} +/* Recruiting stuff */ +.recruit {color: #5c00e6; font-weight: bold; font-style: italic;} +"} diff --git a/code/unused/Virus2Prob.dm b/code/unused/Virus2Prob.dm index bf9868041dd..fa58aeedc12 100644 --- a/code/unused/Virus2Prob.dm +++ b/code/unused/Virus2Prob.dm @@ -1,12 +1,12 @@ -var/list/prob_G_list = list() - -/proc/probG(var/define,var/everyother) - if(prob_G_list["[define]"]) - prob_G_list["[define]"] += 1 - if(prob_G_list["[define]"] == everyother) - prob_G_list["[define]"] = 0 - return 1 - else - (prob_G_list["[define]"]) = 0 - (prob_G_list["[define]"]) = rand(1,everyother-1) - return 0 +var/list/prob_G_list = list() + +/proc/probG(var/define,var/everyother) + if(prob_G_list["[define]"]) + prob_G_list["[define]"] += 1 + if(prob_G_list["[define]"] == everyother) + prob_G_list["[define]"] = 0 + return 1 + else + (prob_G_list["[define]"]) = 0 + (prob_G_list["[define]"]) = rand(1,everyother-1) + return 0 diff --git a/code/unused/computer2/airlock_control.dm b/code/unused/computer2/airlock_control.dm index e14dca1e630..925644410d9 100644 --- a/code/unused/computer2/airlock_control.dm +++ b/code/unused/computer2/airlock_control.dm @@ -1,60 +1,60 @@ -/datum/computer/file/computer_program/airlock_control - name = "Airlock Master" - size = 16.0 - id_tag = "TAG" - - - return_text() - if(..()) - return - - var/dat = "Close | " - dat += "Quit" - - /* - dat += "
        Frequency: " - dat += "-- " - dat += "- " - dat += "[format_frequency(src.master.frequency)] " - dat += "+ " - dat += "++" - dat += "
        " - */ - - - dat += "
        ID:[src.id_tag]
        " - - dat += "Cycle" - - - dat += "

    " - - return dat - - Topic(href, href_list) - if(..()) - return - - if(href_list["set_tag"]) - var/t = input(usr, "Please enter new tag", src.id_tag, null) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t) - return - if (!in_range(src.master, usr)) - return - - src.id_tag = t - -// if(href_list["adj_freq"]) -// var/new_frequency = (src.master.frequency + text2num(href_list["adj_freq"])) -// src.master.set_frequency(new_frequency) - - if(href_list["send_command"]) - var/datum/signal/signal = new - signal.data["tag"] = id_tag - signal.data["command"] = href_list["send_command"] - peripheral_command("send signal", signal) - - src.master.add_fingerprint(usr) - src.master.updateUsrDialog() +/datum/computer/file/computer_program/airlock_control + name = "Airlock Master" + size = 16.0 + id_tag = "TAG" + + + return_text() + if(..()) + return + + var/dat = "Close | " + dat += "Quit" + + /* + dat += "
    Frequency: " + dat += "-- " + dat += "- " + dat += "[format_frequency(src.master.frequency)] " + dat += "+ " + dat += "++" + dat += "
    " + */ + + + dat += "
    ID:[src.id_tag]
    " + + dat += "Cycle" + + + dat += "
    " + + return dat + + Topic(href, href_list) + if(..()) + return + + if(href_list["set_tag"]) + var/t = input(usr, "Please enter new tag", src.id_tag, null) as text + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t) + return + if (!in_range(src.master, usr)) + return + + src.id_tag = t + +// if(href_list["adj_freq"]) +// var/new_frequency = (src.master.frequency + text2num(href_list["adj_freq"])) +// src.master.set_frequency(new_frequency) + + if(href_list["send_command"]) + var/datum/signal/signal = new + signal.data["tag"] = id_tag + signal.data["command"] = href_list["send_command"] + peripheral_command("send signal", signal) + + src.master.add_fingerprint(usr) + src.master.updateUsrDialog() return \ No newline at end of file diff --git a/code/unused/computer2/arcade.dm b/code/unused/computer2/arcade.dm index 679e2bd4a43..db4c63b6182 100644 --- a/code/unused/computer2/arcade.dm +++ b/code/unused/computer2/arcade.dm @@ -1,136 +1,136 @@ -/datum/computer/file/computer_program/arcade - name = "Arcade 500" - size = 8.0 - var/enemy_name = "Space Villian" - var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc - var/player_hp = 30 //Player health/attack points - var/player_mp = 10 - var/enemy_hp = 45 //Enemy health/attack points - var/enemy_mp = 20 - var/gameover = 0 - var/blocked = 0 //Player cannot attack/heal while set - - New(obj/holding as obj) - if(holding) - src.holder = holding - - if(istype(src.holder.loc,/obj/machinery/computer2)) - src.master = src.holder.loc - -// var/name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ") - - var/name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Evil ", "the Dread King ", "the Space ", "Lord ") - var/name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon") - - src.enemy_name = replacetext((name_part1 + name_part2), "the ", "") -// src.name = (name_action + name_part1 + name_part2) - - - -/datum/computer/file/computer_program/arcade/return_text() - if(..()) - return - - var/dat = "Close | " - dat += "Quit" - - dat += "

    [src.enemy_name]

    " - - dat += "

    [src.temp]

    " - dat += "
    Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]
    " - - if (src.gameover) - dat += "
    New Game" - else - dat += "
    Attack | " - dat += "Heal | " - dat += "Recharge Power" - - dat += "
    " - - return dat - -/datum/computer/file/computer_program/arcade/Topic(href, href_list) - if(..()) - return - - if (!src.blocked) - if (href_list["attack"]) - src.blocked = 1 - var/attackamt = rand(2,6) - src.temp = "You attack for [attackamt] damage!" - src.master.updateUsrDialog() - - sleep(10) - src.enemy_hp -= attackamt - src.arcade_action() - - else if (href_list["heal"]) - src.blocked = 1 - var/pointamt = rand(1,3) - var/healamt = rand(6,8) - src.temp = "You use [pointamt] magic to heal for [healamt] damage!" - src.master.updateUsrDialog() - - sleep(10) - src.player_mp -= pointamt - src.player_hp += healamt - src.blocked = 1 - src.master.updateUsrDialog() - src.arcade_action() - - else if (href_list["charge"]) - src.blocked = 1 - var/chargeamt = rand(4,7) - src.temp = "You regain [chargeamt] points" - src.player_mp += chargeamt - - src.master.updateUsrDialog() - sleep(10) - src.arcade_action() - - if (href_list["newgame"]) //Reset everything - temp = "New Round" - player_hp = 30 - player_mp = 10 - enemy_hp = 45 - enemy_mp = 20 - gameover = 0 - - src.master.add_fingerprint(usr) - src.master.updateUsrDialog() - return - -/datum/computer/file/computer_program/arcade/proc/arcade_action() - if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0)) - src.gameover = 1 - src.temp = "[src.enemy_name] has fallen! Rejoice!" - src.peripheral_command("vend prize") - - else if ((src.enemy_mp <= 5) && (prob(70))) - var/stealamt = rand(2,3) - src.temp = "[src.enemy_name] steals [stealamt] of your power!" - src.player_mp -= stealamt - src.master.updateUsrDialog() - - if (src.player_mp <= 0) - src.gameover = 1 - sleep(10) - src.temp = "You have been drained! GAME OVER" - - else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4)) - src.temp = "[src.enemy_name] heals for 4 health!" - src.enemy_hp += 4 - src.enemy_mp -= 4 - - else - var/attackamt = rand(3,6) - src.temp = "[src.enemy_name] attacks for [attackamt] damage!" - src.player_hp -= attackamt - - if ((src.player_mp <= 0) || (src.player_hp <= 0)) - src.gameover = 1 - src.temp = "You have been crushed! GAME OVER" - - src.blocked = 0 +/datum/computer/file/computer_program/arcade + name = "Arcade 500" + size = 8.0 + var/enemy_name = "Space Villian" + var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc + var/player_hp = 30 //Player health/attack points + var/player_mp = 10 + var/enemy_hp = 45 //Enemy health/attack points + var/enemy_mp = 20 + var/gameover = 0 + var/blocked = 0 //Player cannot attack/heal while set + + New(obj/holding as obj) + if(holding) + src.holder = holding + + if(istype(src.holder.loc,/obj/machinery/computer2)) + src.master = src.holder.loc + +// var/name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ") + + var/name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Evil ", "the Dread King ", "the Space ", "Lord ") + var/name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon") + + src.enemy_name = replacetext((name_part1 + name_part2), "the ", "") +// src.name = (name_action + name_part1 + name_part2) + + + +/datum/computer/file/computer_program/arcade/return_text() + if(..()) + return + + var/dat = "Close | " + dat += "Quit" + + dat += "

    [src.enemy_name]

    " + + dat += "

    [src.temp]

    " + dat += "
    Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]
    " + + if (src.gameover) + dat += "
    New Game" + else + dat += "
    Attack | " + dat += "Heal | " + dat += "Recharge Power" + + dat += "
    " + + return dat + +/datum/computer/file/computer_program/arcade/Topic(href, href_list) + if(..()) + return + + if (!src.blocked) + if (href_list["attack"]) + src.blocked = 1 + var/attackamt = rand(2,6) + src.temp = "You attack for [attackamt] damage!" + src.master.updateUsrDialog() + + sleep(10) + src.enemy_hp -= attackamt + src.arcade_action() + + else if (href_list["heal"]) + src.blocked = 1 + var/pointamt = rand(1,3) + var/healamt = rand(6,8) + src.temp = "You use [pointamt] magic to heal for [healamt] damage!" + src.master.updateUsrDialog() + + sleep(10) + src.player_mp -= pointamt + src.player_hp += healamt + src.blocked = 1 + src.master.updateUsrDialog() + src.arcade_action() + + else if (href_list["charge"]) + src.blocked = 1 + var/chargeamt = rand(4,7) + src.temp = "You regain [chargeamt] points" + src.player_mp += chargeamt + + src.master.updateUsrDialog() + sleep(10) + src.arcade_action() + + if (href_list["newgame"]) //Reset everything + temp = "New Round" + player_hp = 30 + player_mp = 10 + enemy_hp = 45 + enemy_mp = 20 + gameover = 0 + + src.master.add_fingerprint(usr) + src.master.updateUsrDialog() + return + +/datum/computer/file/computer_program/arcade/proc/arcade_action() + if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0)) + src.gameover = 1 + src.temp = "[src.enemy_name] has fallen! Rejoice!" + src.peripheral_command("vend prize") + + else if ((src.enemy_mp <= 5) && (prob(70))) + var/stealamt = rand(2,3) + src.temp = "[src.enemy_name] steals [stealamt] of your power!" + src.player_mp -= stealamt + src.master.updateUsrDialog() + + if (src.player_mp <= 0) + src.gameover = 1 + sleep(10) + src.temp = "You have been drained! GAME OVER" + + else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4)) + src.temp = "[src.enemy_name] heals for 4 health!" + src.enemy_hp += 4 + src.enemy_mp -= 4 + + else + var/attackamt = rand(3,6) + src.temp = "[src.enemy_name] attacks for [attackamt] damage!" + src.player_hp -= attackamt + + if ((src.player_mp <= 0) || (src.player_hp <= 0)) + src.gameover = 1 + src.temp = "You have been crushed! GAME OVER" + + src.blocked = 0 return \ No newline at end of file diff --git a/code/unused/computer2/base_program.dm b/code/unused/computer2/base_program.dm index 8b89713a5de..59fc73fce16 100644 --- a/code/unused/computer2/base_program.dm +++ b/code/unused/computer2/base_program.dm @@ -1,263 +1,263 @@ -/datum/computer - var/size = 4.0 - var/obj/item/weapon/disk/data/holder = null - var/datum/computer/folder/holding_folder = null - folder - name = "Folder" - size = 0.0 - var/gen = 0 - Del() - for(var/datum/computer/F in src.contents) - del(F) - ..() - proc - add_file(datum/computer/R) - if(!holder || holder.read_only || !R) - return 0 - if(istype(R,/datum/computer/folder) && (src.gen>=10)) - return 0 - if((holder.file_used + R.size) <= holder.file_amount) - src.contents.Add(R) - R.holder = holder - R.holding_folder = src - src.holder.file_used -= src.size - src.size += R.size - src.holder.file_used += src.size - if(istype(R,/datum/computer/folder)) - R:gen = (src.gen+1) - return 1 - return 0 - - remove_file(datum/computer/R) - if(holder && !holder.read_only || !R) +/datum/computer + var/size = 4.0 + var/obj/item/weapon/disk/data/holder = null + var/datum/computer/folder/holding_folder = null + folder + name = "Folder" + size = 0.0 + var/gen = 0 + Del() + for(var/datum/computer/F in src.contents) + del(F) + ..() + proc + add_file(datum/computer/R) + if(!holder || holder.read_only || !R) + return 0 + if(istype(R,/datum/computer/folder) && (src.gen>=10)) + return 0 + if((holder.file_used + R.size) <= holder.file_amount) + src.contents.Add(R) + R.holder = holder + R.holding_folder = src + src.holder.file_used -= src.size + src.size += R.size + src.holder.file_used += src.size + if(istype(R,/datum/computer/folder)) + R:gen = (src.gen+1) + return 1 + return 0 + + remove_file(datum/computer/R) + if(holder && !holder.read_only || !R) // to_chat(world, "Removing file [R]. File_used: [src.holder.file_used]") - src.contents.Remove(R) - src.holder.file_used -= src.size - src.size -= R.size - src.holder.file_used += src.size - src.holder.file_used = max(src.holder.file_used, 0) + src.contents.Remove(R) + src.holder.file_used -= src.size + src.size -= R.size + src.holder.file_used += src.size + src.holder.file_used = max(src.holder.file_used, 0) // to_chat(world, "Removed file [R]. File_used: [src.holder.file_used]") - return 1 - return 0 - file - name = "File" - var/extension = "FILE" //Differentiate between types of files, why not - proc - copy_file_to_folder(datum/computer/folder/newfolder) - if(!newfolder || (!istype(newfolder)) || (!newfolder.holder) || (newfolder.holder.read_only)) - return 0 - - if((newfolder.holder.file_used + src.size) <= newfolder.holder.file_amount) - var/datum/computer/file/newfile = new src.type - - for(var/V in src.vars) - if (issaved(src.vars[V]) && V != "holder") - newfile.vars[V] = src.vars[V] - - if(!newfolder.add_file(newfile)) - del(newfile) - - return 1 - - return 0 - - - Del() - if(holder && holding_folder) - holding_folder.remove_file(src) - ..() - - -/datum/computer/file/computer_program - name = "blank program" - extension = "PROG" - //var/size = 4.0 - //var/obj/item/weapon/disk/data/holder = null - var/obj/machinery/computer2/master = null - var/active_icon = null - var/id_tag = null - var/list/req_access = list() - - New(obj/holding as obj) - if(holding) - src.holder = holding - - if(istype(src.holder.loc,/obj/machinery/computer2)) - src.master = src.holder.loc - - Del() - if(master) - master.processing_programs.Remove(src) - ..() - - proc - return_text() - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(master.stat & (NOPOWER|BROKEN)) - return 1 - - if(!(holder in src.master.contents)) + return 1 + return 0 + file + name = "File" + var/extension = "FILE" //Differentiate between types of files, why not + proc + copy_file_to_folder(datum/computer/folder/newfolder) + if(!newfolder || (!istype(newfolder)) || (!newfolder.holder) || (newfolder.holder.read_only)) + return 0 + + if((newfolder.holder.file_used + src.size) <= newfolder.holder.file_amount) + var/datum/computer/file/newfile = new src.type + + for(var/V in src.vars) + if (issaved(src.vars[V]) && V != "holder") + newfile.vars[V] = src.vars[V] + + if(!newfolder.add_file(newfile)) + del(newfile) + + return 1 + + return 0 + + + Del() + if(holder && holding_folder) + holding_folder.remove_file(src) + ..() + + +/datum/computer/file/computer_program + name = "blank program" + extension = "PROG" + //var/size = 4.0 + //var/obj/item/weapon/disk/data/holder = null + var/obj/machinery/computer2/master = null + var/active_icon = null + var/id_tag = null + var/list/req_access = list() + + New(obj/holding as obj) + if(holding) + src.holder = holding + + if(istype(src.holder.loc,/obj/machinery/computer2)) + src.master = src.holder.loc + + Del() + if(master) + master.processing_programs.Remove(src) + ..() + + proc + return_text() + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(master.stat & (NOPOWER|BROKEN)) + return 1 + + if(!(holder in src.master.contents)) // to_chat(world, "Holder [holder] not in [master] of prg:[src]") - if(master.active_program == src) - master.active_program = null - return 1 - - if(!src.holder.root) - src.holder.root = new /datum/computer/folder - src.holder.root.holder = src - src.holder.root.name = "root" - - return 0 - - process() - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - master.processing_programs.Remove(src) - return 1 - - if(!src.holder.root) - src.holder.root = new /datum/computer/folder - src.holder.root.holder = src - src.holder.root.name = "root" - - return 0 - - receive_command(obj/source, command, datum/signal/signal) - if((!src.holder) || (!src.master) || (!source) || (source != src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(master.stat & (NOPOWER|BROKEN)) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - return 1 - - return 0 - - peripheral_command(command, datum/signal/signal) - if(master) - master.send_command(command, signal) - else - del(signal) - - transfer_holder(obj/item/weapon/disk/data/newholder,datum/computer/folder/newfolder) - - if((newholder.file_used + src.size) > newholder.file_amount) - return 0 - - if(!newholder.root) - newholder.root = new /datum/computer/folder - newholder.root.holder = newholder - newholder.root.name = "root" - - if(!newfolder) - newfolder = newholder.root - - if((src.holder && src.holder.read_only) || newholder.read_only) - return 0 - - if((src.holder) && (src.holder.root)) - src.holder.root.remove_file(src) - - newfolder.add_file(src) - - if(istype(newholder.loc,/obj/machinery/computer2)) - src.master = newholder.loc - + if(master.active_program == src) + master.active_program = null + return 1 + + if(!src.holder.root) + src.holder.root = new /datum/computer/folder + src.holder.root.holder = src + src.holder.root.name = "root" + + return 0 + + process() + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + master.processing_programs.Remove(src) + return 1 + + if(!src.holder.root) + src.holder.root = new /datum/computer/folder + src.holder.root.holder = src + src.holder.root.name = "root" + + return 0 + + receive_command(obj/source, command, datum/signal/signal) + if((!src.holder) || (!src.master) || (!source) || (source != src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(master.stat & (NOPOWER|BROKEN)) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + return 1 + + return 0 + + peripheral_command(command, datum/signal/signal) + if(master) + master.send_command(command, signal) + else + del(signal) + + transfer_holder(obj/item/weapon/disk/data/newholder,datum/computer/folder/newfolder) + + if((newholder.file_used + src.size) > newholder.file_amount) + return 0 + + if(!newholder.root) + newholder.root = new /datum/computer/folder + newholder.root.holder = newholder + newholder.root.name = "root" + + if(!newfolder) + newfolder = newholder.root + + if((src.holder && src.holder.read_only) || newholder.read_only) + return 0 + + if((src.holder) && (src.holder.root)) + src.holder.root.remove_file(src) + + newfolder.add_file(src) + + if(istype(newholder.loc,/obj/machinery/computer2)) + src.master = newholder.loc + // to_chat(world, "Setting [src.holder] to [newholder]") - src.holder = newholder - return 1 - - //Check access per program. - allowed(mob/M) - //check if it doesn't require any access at all - if(src.check_access(null)) - return 1 - if(istype(M, /mob/living/silicon)) - //AI can do whatever he wants - return 1 - else if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - //if they are holding or wearing a card that has access, that works - if(src.check_access(H.equipped()) || src.check_access(H.wear_id)) - return 1 - else if(istype(M, /mob/living/carbon/monkey)) - var/mob/living/carbon/monkey/george = M - //they can only hold things :( - if(george.equipped() && istype(george.equipped(), /obj/item/weapon/card/id) && src.check_access(george.equipped())) - return 1 - return 0 - - check_access(obj/item/weapon/card/id/I) - if(!src.req_access) //no requirements - return 1 - if(!istype(src.req_access, /list)) //something's very wrong - return 1 - - var/list/L = src.req_access - if(!L.len) //no requirements - return 1 - if(!I || !istype(I, /obj/item/weapon/card/id) || !I.access) //not ID or no access - return 0 - for(var/req in src.req_access) - if(!(req in I.access)) //doesn't have this access - return 0 - return 1 - - Topic(href, href_list) - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(master.stat & (NOPOWER|BROKEN)) - return 1 - - if(src.master.active_program != src) - return 1 - - if ((!usr.contents.Find(src.master) && (!in_range(src.master, usr) || !istype(src.master.loc, /turf))) && (!istype(usr, /mob/living/silicon))) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - return 1 - - usr.machine = src.master - - if (href_list["close"]) - usr.machine = null - usr << browse(null, "window=comp2") - return 0 - - if (href_list["quit"]) -// src.master.processing_programs.Remove(src) - if(src.master.host_program && src.master.host_program.holder && (src.master.host_program.holder in src.master.contents)) - src.master.run_program(src.master.host_program) - src.master.updateUsrDialog() - return 1 - else - src.master.active_program = null - src.master.updateUsrDialog() - return 1 - + src.holder = newholder + return 1 + + //Check access per program. + allowed(mob/M) + //check if it doesn't require any access at all + if(src.check_access(null)) + return 1 + if(istype(M, /mob/living/silicon)) + //AI can do whatever he wants + return 1 + else if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + //if they are holding or wearing a card that has access, that works + if(src.check_access(H.equipped()) || src.check_access(H.wear_id)) + return 1 + else if(istype(M, /mob/living/carbon/monkey)) + var/mob/living/carbon/monkey/george = M + //they can only hold things :( + if(george.equipped() && istype(george.equipped(), /obj/item/weapon/card/id) && src.check_access(george.equipped())) + return 1 + return 0 + + check_access(obj/item/weapon/card/id/I) + if(!src.req_access) //no requirements + return 1 + if(!istype(src.req_access, /list)) //something's very wrong + return 1 + + var/list/L = src.req_access + if(!L.len) //no requirements + return 1 + if(!I || !istype(I, /obj/item/weapon/card/id) || !I.access) //not ID or no access + return 0 + for(var/req in src.req_access) + if(!(req in I.access)) //doesn't have this access + return 0 + return 1 + + Topic(href, href_list) + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(master.stat & (NOPOWER|BROKEN)) + return 1 + + if(src.master.active_program != src) + return 1 + + if ((!usr.contents.Find(src.master) && (!in_range(src.master, usr) || !istype(src.master.loc, /turf))) && (!istype(usr, /mob/living/silicon))) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + return 1 + + usr.machine = src.master + + if (href_list["close"]) + usr.machine = null + usr << browse(null, "window=comp2") + return 0 + + if (href_list["quit"]) +// src.master.processing_programs.Remove(src) + if(src.master.host_program && src.master.host_program.holder && (src.master.host_program.holder in src.master.contents)) + src.master.run_program(src.master.host_program) + src.master.updateUsrDialog() + return 1 + else + src.master.active_program = null + src.master.updateUsrDialog() + return 1 + return 0 \ No newline at end of file diff --git a/code/unused/computer2/buildandrepair.dm b/code/unused/computer2/buildandrepair.dm index 60951f3071a..8f11b2ed266 100644 --- a/code/unused/computer2/buildandrepair.dm +++ b/code/unused/computer2/buildandrepair.dm @@ -1,151 +1,151 @@ -//Motherboard is just used in assembly/disassembly, doesn't exist in the actual computer object. -/obj/item/weapon/motherboard - name = "Computer mainboard" - desc = "A computer motherboard." - icon = 'icons/obj/module.dmi' - icon_state = "mainboard" - item_state = "electronic" - w_class = 3 - var/created_name = null //If defined, result computer will have this name. - -/obj/computer2frame - density = 1 - anchored = 0 - name = "Computer-frame" - icon = 'icons/obj/stock_parts.dmi' - icon_state = "0" - var/state = 0 - var/obj/item/weapon/motherboard/mainboard = null - var/obj/item/weapon/disk/data/fixed_disk/hd = null - var/list/peripherals = list() - var/created_icon_state = "aiupload" - -/obj/computer2frame/attackby(obj/item/P as obj, mob/user as mob) - switch(state) - if(0) - if(istype(P, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 20)) +//Motherboard is just used in assembly/disassembly, doesn't exist in the actual computer object. +/obj/item/weapon/motherboard + name = "Computer mainboard" + desc = "A computer motherboard." + icon = 'icons/obj/module.dmi' + icon_state = "mainboard" + item_state = "electronic" + w_class = 3 + var/created_name = null //If defined, result computer will have this name. + +/obj/computer2frame + density = 1 + anchored = 0 + name = "Computer-frame" + icon = 'icons/obj/stock_parts.dmi' + icon_state = "0" + var/state = 0 + var/obj/item/weapon/motherboard/mainboard = null + var/obj/item/weapon/disk/data/fixed_disk/hd = null + var/list/peripherals = list() + var/created_icon_state = "aiupload" + +/obj/computer2frame/attackby(obj/item/P as obj, mob/user as mob) + switch(state) + if(0) + if(istype(P, /obj/item/weapon/wrench)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 20)) to_chat(user, "You wrench the frame into place.") - src.anchored = 1 - src.state = 1 - if(istype(P, /obj/item/weapon/weldingtool)) - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - if(do_after(user, src, 20)) + src.anchored = 1 + src.state = 1 + if(istype(P, /obj/item/weapon/weldingtool)) + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + if(do_after(user, src, 20)) to_chat(user, "You deconstruct the frame.") - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) - M.amount = 5 - qdel(src) - if(1) - if(istype(P, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, src, 20)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) + M.amount = 5 + qdel(src) + if(1) + if(istype(P, /obj/item/weapon/wrench)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, src, 20)) to_chat(user, "You unfasten the frame.") - src.anchored = 0 - src.state = 0 - if(istype(P, /obj/item/weapon/motherboard) && !mainboard) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + src.anchored = 0 + src.state = 0 + if(istype(P, /obj/item/weapon/motherboard) && !mainboard) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You place the mainboard inside the frame.") - src.icon_state = "1" - src.mainboard = P - user.drop_item() - P.loc = src - if(istype(P, /obj/item/weapon/screwdriver) && mainboard) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + src.icon_state = "1" + src.mainboard = P + user.drop_item() + P.loc = src + if(istype(P, /obj/item/weapon/screwdriver) && mainboard) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You screw the mainboard into place.") - src.state = 2 - src.icon_state = "2" - if(istype(P, /obj/item/weapon/crowbar) && mainboard) - playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + src.state = 2 + src.icon_state = "2" + if(istype(P, /obj/item/weapon/crowbar) && mainboard) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You remove the mainboard.") - src.state = 1 - src.icon_state = "0" - mainboard.loc = src.loc - src.mainboard = null - if(2) - if(istype(P, /obj/item/weapon/screwdriver) && mainboard && (!peripherals.len)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + src.state = 1 + src.icon_state = "0" + mainboard.loc = src.loc + src.mainboard = null + if(2) + if(istype(P, /obj/item/weapon/screwdriver) && mainboard && (!peripherals.len)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You unfasten the mainboard.") - src.state = 1 - src.icon_state = "1" - - if(istype(P, /obj/item/weapon/peripheral)) - if(src.peripherals.len < 3) - user.drop_item() - src.peripherals.Add(P) - P.loc = src + src.state = 1 + src.icon_state = "1" + + if(istype(P, /obj/item/weapon/peripheral)) + if(src.peripherals.len < 3) + user.drop_item() + src.peripherals.Add(P) + P.loc = src to_chat(user, "You add [P] to the frame.") - else + else to_chat(user, "There is no more room for peripheral cards.") - - if(istype(P, /obj/item/weapon/crowbar) && src.peripherals.len) - playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + + if(istype(P, /obj/item/weapon/crowbar) && src.peripherals.len) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You remove the peripheral boards.") - for(var/obj/item/weapon/peripheral/W in src.peripherals) - W.loc = src.loc - src.peripherals.Remove(W) - - if(istype(P, /obj/item/weapon/cable_coil)) - if(P:amount >= 5) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20)) - P:amount -= 5 - if(!P:amount) del(P) + for(var/obj/item/weapon/peripheral/W in src.peripherals) + W.loc = src.loc + src.peripherals.Remove(W) + + if(istype(P, /obj/item/weapon/cable_coil)) + if(P:amount >= 5) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20)) + P:amount -= 5 + if(!P:amount) del(P) to_chat(user, "You add cables to the frame.") - src.state = 3 - src.icon_state = "3" - if(3) - if(istype(P, /obj/item/weapon/wirecutters)) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) + src.state = 3 + src.icon_state = "3" + if(3) + if(istype(P, /obj/item/weapon/wirecutters)) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) to_chat(user, "You remove the cables.") - src.state = 2 - src.icon_state = "2" - var/obj/item/weapon/cable_coil/A = new /obj/item/weapon/cable_coil( src.loc ) - A.amount = 5 - if(src.hd) - src.hd.loc = src.loc - src.hd = null - - if(istype(P, /obj/item/weapon/disk/data/fixed_disk) && !src.hd) - user.drop_item() - src.hd = P - P.loc = src + src.state = 2 + src.icon_state = "2" + var/obj/item/weapon/cable_coil/A = new /obj/item/weapon/cable_coil( src.loc ) + A.amount = 5 + if(src.hd) + src.hd.loc = src.loc + src.hd = null + + if(istype(P, /obj/item/weapon/disk/data/fixed_disk) && !src.hd) + user.drop_item() + src.hd = P + P.loc = src to_chat(user, "You connect the drive to the cabling.") - - if(istype(P, /obj/item/weapon/crowbar) && src.hd) - playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + + if(istype(P, /obj/item/weapon/crowbar) && src.hd) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You remove the hard drive.") - src.hd.loc = src.loc - src.hd = null - - if(istype(P, /obj/item/stack/sheet/glass/glass)) - if(P:amount >= 2) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, src, 20)) - P:use(2) + src.hd.loc = src.loc + src.hd = null + + if(istype(P, /obj/item/stack/sheet/glass/glass)) + if(P:amount >= 2) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, src, 20)) + P:use(2) to_chat(user, "You put in the glass panel.") - src.state = 4 - src.icon_state = "4" - if(4) - if(istype(P, /obj/item/weapon/crowbar)) - playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + src.state = 4 + src.icon_state = "4" + if(4) + if(istype(P, /obj/item/weapon/crowbar)) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You remove the glass panel.") - src.state = 3 - src.icon_state = "3" - new /obj/item/stack/sheet/glass/glass( src.loc, 2 ) - if(istype(P, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + src.state = 3 + src.icon_state = "3" + new /obj/item/stack/sheet/glass/glass( src.loc, 2 ) + if(istype(P, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You connect the monitor.") - var/obj/machinery/computer2/C= new /obj/machinery/computer2( src.loc ) - C.setup_drive_size = 0 - C.icon_state = src.created_icon_state - if(mainboard.created_name) C.name = mainboard.created_name - del(mainboard) - if(hd) - C.hd = hd - hd.loc = C - for(var/obj/item/weapon/peripheral/W in src.peripherals) - W.loc = C - W.host = C - C.peripherals.Add(W) + var/obj/machinery/computer2/C= new /obj/machinery/computer2( src.loc ) + C.setup_drive_size = 0 + C.icon_state = src.created_icon_state + if(mainboard.created_name) C.name = mainboard.created_name + del(mainboard) + if(hd) + C.hd = hd + hd.loc = C + for(var/obj/item/weapon/peripheral/W in src.peripherals) + W.loc = C + W.host = C + C.peripherals.Add(W) del(src) \ No newline at end of file diff --git a/code/unused/computer2/computerII.dm b/code/unused/computer2/computerII.dm index 3a16751dfdc..7f0fa84a58a 100644 --- a/code/unused/computer2/computerII.dm +++ b/code/unused/computer2/computerII.dm @@ -1,414 +1,414 @@ - -/obj/machinery/computer2 - name = "computer" - desc = "A computer workstation." - icon = 'icons/obj/computer.dmi' - icon_state = "aiupload" - density = 1 - anchored = 1.0 - req_access = list() //This doesn't determine PROGRAM req access, just the access needed to install/delete programs. - var/base_icon_state = "aiupload" //Assembly creates a new computer2 and not a child typepath, so initial doesn't work!! - var/datum/radio_frequency/radio_connection - var/obj/item/weapon/disk/data/fixed_disk/hd = null - var/datum/computer/file/computer_program/active_program - var/datum/computer/file/computer_program/host_program //active is set to this when the normal active quits, if available - var/list/processing_programs = list() - var/obj/item/weapon/card/id/authid = null //For records computers etc - var/obj/item/weapon/card/id/auxid = null //For computers that need two ids for some reason. - var/obj/item/weapon/disk/data/diskette = null - var/list/peripherals = list() - //Setup for Starting program & peripherals - var/setup_starting_program = null //If set to a program path it will start with this one active. - var/setup_starting_peripheral = null //Spawn with radio card and whatever path is here. - var/setup_drive_size = 64.0 //How big is the drive (set to 0 for no drive) - var/setup_id_tag - var/setup_has_radio = 0 //Does it spawn with a radio peripheral? - var/setup_radio_tag - var/setup_frequency = 1411 - -/obj/item/weapon/disk/data - var/datum/computer/folder/root = null - var/file_amount = 32.0 - var/file_used = 0.0 - var/portable = 1 - var/title = "Data Disk" - New() - src.root = new /datum/computer/folder - src.root.holder = src - src.root.name = "root" - -/obj/item/weapon/disk/data/fixed_disk - name = "Storage Drive" - icon_state = "harddisk" - title = "Storage Drive" - file_amount = 80.0 - portable = 0 - - attack_self(mob/user as mob) - return - -/obj/item/weapon/disk/data/computer2test - name = "Programme Diskette" - file_amount = 128.0 - New() - ..() - src.root.add_file( new /datum/computer/file/computer_program/arcade(src)) - src.root.add_file( new /datum/computer/file/computer_program/med_data(src)) - src.root.add_file( new /datum/computer/file/computer_program/airlock_control(src)) - src.root.add_file( new /datum/computer/file/computer_program/messenger(src)) - src.root.add_file( new /datum/computer/file/computer_program/progman(src)) - -/obj/machinery/computer2/medical - name = "Medical computer" - icon_state = "dna" - setup_has_radio = 1 - setup_starting_program = /datum/computer/file/computer_program/med_data - setup_starting_peripheral = /obj/item/weapon/peripheral/printer - -/obj/machinery/computer2/arcade - name = "arcade machine" - icon_state = "arcade" - desc = "An arcade machine." - setup_drive_size = 16.0 - setup_starting_program = /datum/computer/file/computer_program/arcade - setup_starting_peripheral = /obj/item/weapon/peripheral/prize_vendor - - -/obj/machinery/computer2/New() - ..() - - spawn(4) - if(setup_has_radio) - var/obj/item/weapon/peripheral/radio/radio = new /obj/item/weapon/peripheral/radio(src) - radio.frequency = setup_frequency - radio.code = setup_radio_tag - - if(!hd && (setup_drive_size > 0)) - src.hd = new /obj/item/weapon/disk/data/fixed_disk(src) - src.hd.file_amount = src.setup_drive_size - - if(ispath(src.setup_starting_program)) - src.active_program = new src.setup_starting_program - src.active_program.id_tag = setup_id_tag - - src.hd.file_amount = max(src.hd.file_amount, src.active_program.size) - - src.active_program.transfer_holder(src.hd) - - if(ispath(src.setup_starting_peripheral)) - new src.setup_starting_peripheral(src) - - src.base_icon_state = src.icon_state - - return - -/obj/machinery/computer2/attack_hand(mob/user as mob) - if(..()) - return - - user.machine = src - - var/dat - if((src.active_program) && (src.active_program.master == src) && (src.active_program.holder in src)) - dat = src.active_program.return_text() - else - dat = "Thinktronic BIOS V1.4

    " - - dat += "Current ID: [src.authid ? "[src.authid.name]" : "----------"]
    " - dat += "Auxiliary ID: [src.auxid ? "[src.auxid.name]" : "----------"]

    " - - var/progdat - if((src.hd) && (src.hd.root)) - for(var/datum/computer/file/computer_program/P in src.hd.root.contents) - progdat += "[P.name]Size: [P.size]" - - progdat += "Run" - - if(P in src.processing_programs) - progdat += "Halt" - else - progdat += "Load" - - progdat += "Del" - - continue - - dat += "Disk Space: \[[src.hd.file_used]/[src.hd.file_amount]\]
    " - dat += "Programs on Fixed Disk:
    " - - if(!progdat) - progdat = "No programs found.
    " - dat += "
    [progdat]
    " - - else - - dat += "Programs on Fixed Disk:
    " - dat += "
    No fixed disk detected.

    " - - dat += "
    " - - progdat = null - if((src.diskette) && (src.diskette.root)) - - dat += "Eject
    " - - for(var/datum/computer/file/computer_program/P in src.diskette.root.contents) - progdat += "[P.name]Size: [P.size]" - progdat += "Run" - - if(P in src.processing_programs) - progdat += "Halt" - else - progdat += "Load" - - progdat += "Install" - - continue - - dat += "Disk Space: \[[src.diskette.file_used]/[src.diskette.file_amount]\]
    " - dat += "Programs on Disk:
    " - - if(!progdat) - progdat = "No data found.
    " - dat += "
    [progdat]
    " - - else - - dat += "Programs on Disk:
    " - dat += "
    No diskette loaded.

    " - - dat += "
    " - - user << browse(dat,"window=comp2") - onclose(user,"comp2") - return - -/obj/machinery/computer2/Topic(href, href_list) - if(..()) - return - - if(!src.active_program) - if((href_list["prog"]) && (href_list["function"])) - var/datum/computer/file/computer_program/newprog = locate(href_list["prog"]) - if(newprog && istype(newprog)) - switch(href_list["function"]) - if("run") - src.run_program(newprog) - if("load") - src.load_program(newprog) - if("unload") - src.unload_program(newprog) - if((href_list["file"]) && (href_list["function"])) - var/datum/computer/file/newfile = locate(href_list["file"]) - if(!newfile) - return - switch(href_list["function"]) - if("install") - if((src.hd) && (src.hd.root) && (src.allowed(usr))) - newfile.copy_file_to_folder(src.hd.root) - - if("delete") - if(src.allowed(usr)) - src.delete_file(newfile) - - //If there is already one loaded eject, or if not and they have one insert it. - if (href_list["id"]) - switch(href_list["id"]) - if("auth") - if(!isnull(src.authid)) - src.authid.loc = get_turf(src) - src.authid = null - else - var/obj/item/I = usr.equipped() - if (istype(I, /obj/item/weapon/card/id)) - usr.drop_item() - I.loc = src - src.authid = I - if("aux") - if(!isnull(src.auxid)) - src.auxid.loc = get_turf(src) - src.auxid = null - else - var/obj/item/I = usr.equipped() - if (istype(I, /obj/item/weapon/card/id)) - usr.drop_item() - I.loc = src - src.auxid = I - - //Same but for a data disk - else if (href_list["disk"]) - if(!isnull(src.diskette)) - src.diskette.loc = get_turf(src) - src.diskette = null -/* else - var/obj/item/I = usr.equipped() - if (istype(I, /obj/item/weapon/disk/data)) - usr.drop_item() - I.loc = src - src.diskette = I -*/ - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer2/process() - if(stat & (NOPOWER|BROKEN)) - return - use_power(250) - - for(var/datum/computer/file/computer_program/P in src.processing_programs) - P.process() - - return - -/obj/machinery/computer2/power_change() - if(stat & BROKEN) - icon_state = src.base_icon_state - src.icon_state += "b" - - else if(powered()) - icon_state = src.base_icon_state - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - icon_state = src.base_icon_state - src.icon_state += "0" - stat |= NOPOWER - - -/obj/machinery/computer2/attackby(obj/item/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES - if ((!src.diskette) && W:portable) - user.machine = src - user.drop_item() - W.loc = src - src.diskette = W + +/obj/machinery/computer2 + name = "computer" + desc = "A computer workstation." + icon = 'icons/obj/computer.dmi' + icon_state = "aiupload" + density = 1 + anchored = 1.0 + req_access = list() //This doesn't determine PROGRAM req access, just the access needed to install/delete programs. + var/base_icon_state = "aiupload" //Assembly creates a new computer2 and not a child typepath, so initial doesn't work!! + var/datum/radio_frequency/radio_connection + var/obj/item/weapon/disk/data/fixed_disk/hd = null + var/datum/computer/file/computer_program/active_program + var/datum/computer/file/computer_program/host_program //active is set to this when the normal active quits, if available + var/list/processing_programs = list() + var/obj/item/weapon/card/id/authid = null //For records computers etc + var/obj/item/weapon/card/id/auxid = null //For computers that need two ids for some reason. + var/obj/item/weapon/disk/data/diskette = null + var/list/peripherals = list() + //Setup for Starting program & peripherals + var/setup_starting_program = null //If set to a program path it will start with this one active. + var/setup_starting_peripheral = null //Spawn with radio card and whatever path is here. + var/setup_drive_size = 64.0 //How big is the drive (set to 0 for no drive) + var/setup_id_tag + var/setup_has_radio = 0 //Does it spawn with a radio peripheral? + var/setup_radio_tag + var/setup_frequency = 1411 + +/obj/item/weapon/disk/data + var/datum/computer/folder/root = null + var/file_amount = 32.0 + var/file_used = 0.0 + var/portable = 1 + var/title = "Data Disk" + New() + src.root = new /datum/computer/folder + src.root.holder = src + src.root.name = "root" + +/obj/item/weapon/disk/data/fixed_disk + name = "Storage Drive" + icon_state = "harddisk" + title = "Storage Drive" + file_amount = 80.0 + portable = 0 + + attack_self(mob/user as mob) + return + +/obj/item/weapon/disk/data/computer2test + name = "Programme Diskette" + file_amount = 128.0 + New() + ..() + src.root.add_file( new /datum/computer/file/computer_program/arcade(src)) + src.root.add_file( new /datum/computer/file/computer_program/med_data(src)) + src.root.add_file( new /datum/computer/file/computer_program/airlock_control(src)) + src.root.add_file( new /datum/computer/file/computer_program/messenger(src)) + src.root.add_file( new /datum/computer/file/computer_program/progman(src)) + +/obj/machinery/computer2/medical + name = "Medical computer" + icon_state = "dna" + setup_has_radio = 1 + setup_starting_program = /datum/computer/file/computer_program/med_data + setup_starting_peripheral = /obj/item/weapon/peripheral/printer + +/obj/machinery/computer2/arcade + name = "arcade machine" + icon_state = "arcade" + desc = "An arcade machine." + setup_drive_size = 16.0 + setup_starting_program = /datum/computer/file/computer_program/arcade + setup_starting_peripheral = /obj/item/weapon/peripheral/prize_vendor + + +/obj/machinery/computer2/New() + ..() + + spawn(4) + if(setup_has_radio) + var/obj/item/weapon/peripheral/radio/radio = new /obj/item/weapon/peripheral/radio(src) + radio.frequency = setup_frequency + radio.code = setup_radio_tag + + if(!hd && (setup_drive_size > 0)) + src.hd = new /obj/item/weapon/disk/data/fixed_disk(src) + src.hd.file_amount = src.setup_drive_size + + if(ispath(src.setup_starting_program)) + src.active_program = new src.setup_starting_program + src.active_program.id_tag = setup_id_tag + + src.hd.file_amount = max(src.hd.file_amount, src.active_program.size) + + src.active_program.transfer_holder(src.hd) + + if(ispath(src.setup_starting_peripheral)) + new src.setup_starting_peripheral(src) + + src.base_icon_state = src.icon_state + + return + +/obj/machinery/computer2/attack_hand(mob/user as mob) + if(..()) + return + + user.machine = src + + var/dat + if((src.active_program) && (src.active_program.master == src) && (src.active_program.holder in src)) + dat = src.active_program.return_text() + else + dat = "Thinktronic BIOS V1.4

    " + + dat += "Current ID: [src.authid ? "[src.authid.name]" : "----------"]
    " + dat += "Auxiliary ID: [src.auxid ? "[src.auxid.name]" : "----------"]

    " + + var/progdat + if((src.hd) && (src.hd.root)) + for(var/datum/computer/file/computer_program/P in src.hd.root.contents) + progdat += "[P.name]Size: [P.size]" + + progdat += "Run" + + if(P in src.processing_programs) + progdat += "Halt" + else + progdat += "Load" + + progdat += "Del" + + continue + + dat += "Disk Space: \[[src.hd.file_used]/[src.hd.file_amount]\]
    " + dat += "Programs on Fixed Disk:
    " + + if(!progdat) + progdat = "No programs found.
    " + dat += "
    [progdat]
    " + + else + + dat += "Programs on Fixed Disk:
    " + dat += "
    No fixed disk detected.

    " + + dat += "
    " + + progdat = null + if((src.diskette) && (src.diskette.root)) + + dat += "Eject
    " + + for(var/datum/computer/file/computer_program/P in src.diskette.root.contents) + progdat += "[P.name]Size: [P.size]" + progdat += "Run" + + if(P in src.processing_programs) + progdat += "Halt" + else + progdat += "Load" + + progdat += "Install" + + continue + + dat += "Disk Space: \[[src.diskette.file_used]/[src.diskette.file_amount]\]
    " + dat += "Programs on Disk:
    " + + if(!progdat) + progdat = "No data found.
    " + dat += "
    [progdat]
    " + + else + + dat += "Programs on Disk:
    " + dat += "
    No diskette loaded.

    " + + dat += "
    " + + user << browse(dat,"window=comp2") + onclose(user,"comp2") + return + +/obj/machinery/computer2/Topic(href, href_list) + if(..()) + return + + if(!src.active_program) + if((href_list["prog"]) && (href_list["function"])) + var/datum/computer/file/computer_program/newprog = locate(href_list["prog"]) + if(newprog && istype(newprog)) + switch(href_list["function"]) + if("run") + src.run_program(newprog) + if("load") + src.load_program(newprog) + if("unload") + src.unload_program(newprog) + if((href_list["file"]) && (href_list["function"])) + var/datum/computer/file/newfile = locate(href_list["file"]) + if(!newfile) + return + switch(href_list["function"]) + if("install") + if((src.hd) && (src.hd.root) && (src.allowed(usr))) + newfile.copy_file_to_folder(src.hd.root) + + if("delete") + if(src.allowed(usr)) + src.delete_file(newfile) + + //If there is already one loaded eject, or if not and they have one insert it. + if (href_list["id"]) + switch(href_list["id"]) + if("auth") + if(!isnull(src.authid)) + src.authid.loc = get_turf(src) + src.authid = null + else + var/obj/item/I = usr.equipped() + if (istype(I, /obj/item/weapon/card/id)) + usr.drop_item() + I.loc = src + src.authid = I + if("aux") + if(!isnull(src.auxid)) + src.auxid.loc = get_turf(src) + src.auxid = null + else + var/obj/item/I = usr.equipped() + if (istype(I, /obj/item/weapon/card/id)) + usr.drop_item() + I.loc = src + src.auxid = I + + //Same but for a data disk + else if (href_list["disk"]) + if(!isnull(src.diskette)) + src.diskette.loc = get_turf(src) + src.diskette = null +/* else + var/obj/item/I = usr.equipped() + if (istype(I, /obj/item/weapon/disk/data)) + usr.drop_item() + I.loc = src + src.diskette = I +*/ + src.add_fingerprint(usr) + src.updateUsrDialog() + return + +/obj/machinery/computer2/process() + if(stat & (NOPOWER|BROKEN)) + return + use_power(250) + + for(var/datum/computer/file/computer_program/P in src.processing_programs) + P.process() + + return + +/obj/machinery/computer2/power_change() + if(stat & BROKEN) + icon_state = src.base_icon_state + src.icon_state += "b" + + else if(powered()) + icon_state = src.base_icon_state + stat &= ~NOPOWER + else + spawn(rand(0, 15)) + icon_state = src.base_icon_state + src.icon_state += "0" + stat |= NOPOWER + + +/obj/machinery/computer2/attackby(obj/item/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES + if ((!src.diskette) && W:portable) + user.machine = src + user.drop_item() + W.loc = src + src.diskette = W to_chat(user, "You insert [W].") - src.updateUsrDialog() - return - - else if (istype(W, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, src, 20)) - var/obj/computer2frame/A = new /obj/computer2frame( src.loc ) - A.created_icon_state = src.base_icon_state - if (src.stat & BROKEN) + src.updateUsrDialog() + return + + else if (istype(W, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, src, 20)) + var/obj/computer2frame/A = new /obj/computer2frame( src.loc ) + A.created_icon_state = src.base_icon_state + if (src.stat & BROKEN) to_chat(user, "The broken glass falls out.") - new /obj/item/weapon/shard( src.loc ) - A.state = 3 - A.icon_state = "3" - else + new /obj/item/weapon/shard( src.loc ) + A.state = 3 + A.icon_state = "3" + else to_chat(user, "You disconnect the monitor.") - A.state = 4 - A.icon_state = "4" - - for (var/obj/item/weapon/peripheral/C in src.peripherals) - C.loc = A - A.peripherals.Add(C) - - if(src.diskette) - src.diskette.loc = src.loc - - //TO-DO: move card reading to peripheral cards instead - if(src.authid) - src.authid.loc = src.loc - - if(src.auxid) - src.auxid.loc = src.loc - - if(src.hd) - src.hd.loc = A - A.hd = src.hd - - A.mainboard = new /obj/item/weapon/motherboard(A) - A.mainboard.created_name = src.name - - - A.anchored = 1 - del(src) - - else - src.attack_hand(user) - return - -/obj/machinery/computer2/proc/send_command(command, datum/signal/signal) - for(var/obj/item/weapon/peripheral/P in src.peripherals) - P.receive_command(src, command, signal) - - del(signal) - -/obj/machinery/computer2/proc/receive_command(obj/source, command, datum/signal/signal) - if(source in src.contents) - - for(var/datum/computer/file/computer_program/P in src.processing_programs) - P.receive_command(src, command, signal) - - del(signal) - - return - - -/obj/machinery/computer2/proc/run_program(datum/computer/file/computer_program/program,datum/computer/file/computer_program/host) - if(!program) - return 0 - -// src.unload_program(src.active_program) - - if(src.load_program(program)) - if(host && istype(host)) - src.host_program = host - else - src.host_program = null - - src.active_program = program - return 1 - - return 0 - -/obj/machinery/computer2/proc/load_program(datum/computer/file/computer_program/program) - if((!program) || (!program.holder)) - return 0 - - if(!(program.holder in src)) + A.state = 4 + A.icon_state = "4" + + for (var/obj/item/weapon/peripheral/C in src.peripherals) + C.loc = A + A.peripherals.Add(C) + + if(src.diskette) + src.diskette.loc = src.loc + + //TO-DO: move card reading to peripheral cards instead + if(src.authid) + src.authid.loc = src.loc + + if(src.auxid) + src.auxid.loc = src.loc + + if(src.hd) + src.hd.loc = A + A.hd = src.hd + + A.mainboard = new /obj/item/weapon/motherboard(A) + A.mainboard.created_name = src.name + + + A.anchored = 1 + del(src) + + else + src.attack_hand(user) + return + +/obj/machinery/computer2/proc/send_command(command, datum/signal/signal) + for(var/obj/item/weapon/peripheral/P in src.peripherals) + P.receive_command(src, command, signal) + + del(signal) + +/obj/machinery/computer2/proc/receive_command(obj/source, command, datum/signal/signal) + if(source in src.contents) + + for(var/datum/computer/file/computer_program/P in src.processing_programs) + P.receive_command(src, command, signal) + + del(signal) + + return + + +/obj/machinery/computer2/proc/run_program(datum/computer/file/computer_program/program,datum/computer/file/computer_program/host) + if(!program) + return 0 + +// src.unload_program(src.active_program) + + if(src.load_program(program)) + if(host && istype(host)) + src.host_program = host + else + src.host_program = null + + src.active_program = program + return 1 + + return 0 + +/obj/machinery/computer2/proc/load_program(datum/computer/file/computer_program/program) + if((!program) || (!program.holder)) + return 0 + + if(!(program.holder in src)) // to_chat(world, "Not in src") - program = new program.type - program.transfer_holder(src.hd) - - if(program.master != src) - program.master = src - - if(program in src.processing_programs) - return 1 - else - src.processing_programs.Add(program) - return 1 - - return 0 - -/obj/machinery/computer2/proc/unload_program(datum/computer/file/computer_program/program) - if((!program) || (!src.hd)) - return 0 - - if(program in src.processing_programs) - src.processing_programs.Remove(program) - return 1 - - return 0 - -/obj/machinery/computer2/proc/delete_file(datum/computer/file/file) + program = new program.type + program.transfer_holder(src.hd) + + if(program.master != src) + program.master = src + + if(program in src.processing_programs) + return 1 + else + src.processing_programs.Add(program) + return 1 + + return 0 + +/obj/machinery/computer2/proc/unload_program(datum/computer/file/computer_program/program) + if((!program) || (!src.hd)) + return 0 + + if(program in src.processing_programs) + src.processing_programs.Remove(program) + return 1 + + return 0 + +/obj/machinery/computer2/proc/delete_file(datum/computer/file/file) // to_chat(world, "Deleting [file]...") - if((!file) || (!file.holder) || (file.holder.read_only)) + if((!file) || (!file.holder) || (file.holder.read_only)) // to_chat(world, "Cannot delete :(") - return 0 - - if(file in src.processing_programs) - src.processing_programs.Remove(file) - - if(src.active_program == file) - src.active_program = null - -// file.holder.root.remove_file(file) - + return 0 + + if(file in src.processing_programs) + src.processing_programs.Remove(file) + + if(src.active_program == file) + src.active_program = null + +// file.holder.root.remove_file(file) + // to_chat(world, "Now calling del on [file]...") - del(file) + del(file) return 1 \ No newline at end of file diff --git a/code/unused/computer2/filebrowse.dm b/code/unused/computer2/filebrowse.dm index 38e2774f522..c315635b49f 100644 --- a/code/unused/computer2/filebrowse.dm +++ b/code/unused/computer2/filebrowse.dm @@ -1,164 +1,164 @@ -/datum/computer/file/computer_program/progman - name = "ProgManager" - size = 16.0 - var/datum/computer/folder/current_folder - var/mode = 0 - var/datum/computer/file/clipboard - - - return_text() - if(..()) - return - - if((!src.current_folder) || !(src.current_folder.holder in src.master)) - src.current_folder = src.holder.root - - var/dat = "Close | " - dat += "Quit" - - switch(mode) - if(0) - dat += " |Create Folder" - //dat += " | Create File" - dat += " | Paste" - dat += " | Root" - dat += " | Drive
    " - - dat += "Contents of [current_folder] | Drive:\[[src.current_folder.holder.title]]
    " - dat += "Used: \[[src.current_folder.holder.file_used]/[src.current_folder.holder.file_amount]\]
    " - - dat += "" - for(var/datum/computer/P in current_folder.contents) - if(P == src) - dat += "" - continue - dat += "" - dat += "" - - dat += "" - - dat += "" - dat += "" - - - if(istype(P,/datum/computer/file)) - dat += "" - - dat += "" - - dat += "
    SystemSize: [src.size]SYSTEM
    [P.name]Size: [P.size][(istype(P,/datum/computer/folder)) ? "FOLDER" : "[P:extension]"]DelRenameCopy
    " - - if(1) - dat += " | Main" - dat += " | Eject
    " - - for(var/obj/item/weapon/disk/data/D in src.master) - if(D == current_folder.holder) - dat += "[D.name]
    " - else - dat += "[D.title]
    " - - - return dat - - Topic(href, href_list) - if(..()) - return - - if(href_list["create"]) - if(current_folder) - var/datum/computer/F = null - switch(href_list["create"]) - if("folder") - F = new /datum/computer/folder - if(!current_folder.add_file(F)) +/datum/computer/file/computer_program/progman + name = "ProgManager" + size = 16.0 + var/datum/computer/folder/current_folder + var/mode = 0 + var/datum/computer/file/clipboard + + + return_text() + if(..()) + return + + if((!src.current_folder) || !(src.current_folder.holder in src.master)) + src.current_folder = src.holder.root + + var/dat = "Close | " + dat += "Quit" + + switch(mode) + if(0) + dat += " |Create Folder" + //dat += " | Create File" + dat += " | Paste" + dat += " | Root" + dat += " | Drive
    " + + dat += "Contents of [current_folder] | Drive:\[[src.current_folder.holder.title]]
    " + dat += "Used: \[[src.current_folder.holder.file_used]/[src.current_folder.holder.file_amount]\]
    " + + dat += "" + for(var/datum/computer/P in current_folder.contents) + if(P == src) + dat += "" + continue + dat += "" + dat += "" + + dat += "" + + dat += "" + dat += "" + + + if(istype(P,/datum/computer/file)) + dat += "" + + dat += "" + + dat += "
    SystemSize: [src.size]SYSTEM
    [P.name]Size: [P.size][(istype(P,/datum/computer/folder)) ? "FOLDER" : "[P:extension]"]DelRenameCopy
    " + + if(1) + dat += " | Main" + dat += " | Eject
    " + + for(var/obj/item/weapon/disk/data/D in src.master) + if(D == current_folder.holder) + dat += "[D.name]
    " + else + dat += "[D.title]
    " + + + return dat + + Topic(href, href_list) + if(..()) + return + + if(href_list["create"]) + if(current_folder) + var/datum/computer/F = null + switch(href_list["create"]) + if("folder") + F = new /datum/computer/folder + if(!current_folder.add_file(F)) // to_chat(world, "Couldn't add folder :(") - del(F) - if("file") - F = new /datum/computer/file - if(!current_folder.add_file(F)) + del(F) + if("file") + F = new /datum/computer/file + if(!current_folder.add_file(F)) // to_chat(world, "Couldn't add file :(") - del(F) - - if(href_list["file"] && href_list["function"]) - var/datum/computer/F = locate(href_list["file"]) - if(!F || !istype(F)) - return - switch(href_list["function"]) - if("open") - if(istype(F,/datum/computer/folder)) - src.current_folder = F - else if(istype(F,/datum/computer/file/computer_program)) - src.master.run_program(F,src) - src.master.updateUsrDialog() - return - - if("delete") - src.master.delete_file(F) - - if("copy") - if(istype(F,/datum/computer/file) && (!F.holder || (F.holder in src.master.contents))) - src.clipboard = F - - if("paste") - if(istype(F,/datum/computer/folder)) - if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents)) - return - - if(!istype(src.clipboard)) - return - - src.clipboard.copy_file_to_folder(F) - - if("rename") - spawn(0) - var/t = input(usr, "Please enter new name", F.name, null) as text - t = copytext(sanitize(t), 1, 16) - if (!t) - return - if (!in_range(src.master, usr) || !(F.holder in src.master)) - return - if(F.holder.read_only) - return - F.name = capitalize(lowertext(t)) - src.master.updateUsrDialog() - return - - -/* - if(href_list["open"]) - var/datum/computer/F = locate(href_list["open"]) - if(!F || !istype(F)) - return - - if(istype(F,/datum/computer/folder)) - src.current_folder = F - else if(istype(F,/datum/computer/file/computer_program)) - src.master.run_program(F) - src.master.updateUsrDialog() - return - - if(href_list["delete"]) - var/datum/computer/F = locate(href_list["delete"]) - if(!F || !istype(F)) - return - - src.master.delete_file(F) -*/ - if(href_list["top_folder"]) - src.current_folder = src.current_folder.holder.root - - if(href_list["mode"]) - var/newmode = text2num(href_list["mode"]) - newmode = max(newmode,0) - src.mode = newmode - - if(href_list["drive"]) - var/obj/item/weapon/disk/data/D = locate(href_list["drive"]) - if(D && istype(D) && D.root) - current_folder = D.root - src.mode = 0 - - src.master.add_fingerprint(usr) - src.master.updateUsrDialog() + del(F) + + if(href_list["file"] && href_list["function"]) + var/datum/computer/F = locate(href_list["file"]) + if(!F || !istype(F)) + return + switch(href_list["function"]) + if("open") + if(istype(F,/datum/computer/folder)) + src.current_folder = F + else if(istype(F,/datum/computer/file/computer_program)) + src.master.run_program(F,src) + src.master.updateUsrDialog() + return + + if("delete") + src.master.delete_file(F) + + if("copy") + if(istype(F,/datum/computer/file) && (!F.holder || (F.holder in src.master.contents))) + src.clipboard = F + + if("paste") + if(istype(F,/datum/computer/folder)) + if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents)) + return + + if(!istype(src.clipboard)) + return + + src.clipboard.copy_file_to_folder(F) + + if("rename") + spawn(0) + var/t = input(usr, "Please enter new name", F.name, null) as text + t = copytext(sanitize(t), 1, 16) + if (!t) + return + if (!in_range(src.master, usr) || !(F.holder in src.master)) + return + if(F.holder.read_only) + return + F.name = capitalize(lowertext(t)) + src.master.updateUsrDialog() + return + + +/* + if(href_list["open"]) + var/datum/computer/F = locate(href_list["open"]) + if(!F || !istype(F)) + return + + if(istype(F,/datum/computer/folder)) + src.current_folder = F + else if(istype(F,/datum/computer/file/computer_program)) + src.master.run_program(F) + src.master.updateUsrDialog() + return + + if(href_list["delete"]) + var/datum/computer/F = locate(href_list["delete"]) + if(!F || !istype(F)) + return + + src.master.delete_file(F) +*/ + if(href_list["top_folder"]) + src.current_folder = src.current_folder.holder.root + + if(href_list["mode"]) + var/newmode = text2num(href_list["mode"]) + newmode = max(newmode,0) + src.mode = newmode + + if(href_list["drive"]) + var/obj/item/weapon/disk/data/D = locate(href_list["drive"]) + if(D && istype(D) && D.root) + current_folder = D.root + src.mode = 0 + + src.master.add_fingerprint(usr) + src.master.updateUsrDialog() return \ No newline at end of file diff --git a/code/unused/computer2/med_rec.dm b/code/unused/computer2/med_rec.dm index 46f69267d5b..5d103a95435 100644 --- a/code/unused/computer2/med_rec.dm +++ b/code/unused/computer2/med_rec.dm @@ -1,463 +1,463 @@ -/datum/computer/file/computer_program/med_data - name = "Medical Records" - size = 32.0 - active_icon = "dna" - req_access = list(ACCESS_MEDICAL) - var/authenticated = null - var/rank = null - var/screen = null - var/datum/data/record/active1 = null - var/datum/data/record/active2 = null - var/a_id = null - var/temp = null - -/datum/computer/file/computer_program/med_data/return_text() - if(..()) - return - var/dat - if (src.temp) - dat = text("[src.temp]

    Clear Screen") - else - dat = text("Confirm Identity: []
    ", master, (src.master.authid ? text("[]", src.master.authid.name) : "----------")) - if (src.authenticated) - switch(src.screen) - if(1.0) - dat += {" -Search Records -
    List Records -
    -
    Virus Database -
    Medbot Tracking -
    -
    Record Maintenance -
    {Log Out}
    -"} - if(2.0) - dat += "Record List:
    " - for(var/datum/data/record/R in data_core.general) - dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) - //Foreach goto(132) - dat += text("
    Back", src) - if(3.0) - dat += text("Records Maintenance
    \nBackup To Disk
    \nUpload From disk
    \nDelete All Records
    \n
    \nBack", src, src, src, src) - if(4.0) - dat += "
    Medical Record

    " - if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) - dat += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", src.active1.fields["name"], src.active1.fields["id"], src, src.active1.fields["sex"], src, src.active1.fields["age"], src, src.active1.fields["fingerprint"], src, src.active1.fields["p_stat"], src, src.active1.fields["m_stat"]) - 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: []
    \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["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"]) - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - dat += text("[]
    Delete Entry

    ", src.active2.fields[text("com_[]", counter)], src, counter) - counter++ - dat += text("Add Entry

    ", src) - dat += text("Delete Record (Medical Only)

    ", src) - else - dat += "Medical Record Lost!
    " - dat += text("New Record

    ") - dat += text("\nPrint Record
    \nBack
    ", src, src) - if(5.0) - dat += {"
    Virus Database
    -
    GBS -
    Common Cold -
    Flu -
    Jungle Fever -
    Clowning Around -
    Plasmatoid -
    Space Rhinovirus -
    Robot Transformation -
    Back"} - if(6.0) - dat += "
    Medical Robot Monitor
    " - dat += "Back" - dat += "
    Medical Robots:" - var/bdat = null - for(var/obj/machinery/bot/medbot/M in machines) - var/turf/bl = get_turf(M) - bdat += "[M.name] - \[[bl.x],[bl.y]\] - [M.on ? "Online" : "Offline"]
    " - if(!isnull(M.reagent_glass)) - bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]" - else - bdat += "Using Internal Synthesizer." - - if(!bdat) - dat += "
    None detected
    " - else - dat += "[bdat]" - - else - else - dat += text("{Log In}", src) - dat += "
    {Quit}" - - return dat - -/datum/computer/file/computer_program/med_data/Topic(href, href_list) - if(..()) - return - if (!( data_core.general.Find(src.active1) )) - src.active1 = null - if (!( data_core.medical.Find(src.active2) )) - src.active2 = null - if (href_list["temp"]) - src.temp = null - else if (href_list["logout"]) - src.authenticated = null - src.screen = null - src.active1 = null - src.active2 = null - else if (href_list["login"]) - if (istype(usr, /mob/living/silicon)) - src.active1 = null - src.active2 = null - src.authenticated = 1 - src.rank = "AI" - src.screen = 1 - else if (istype(src.master.authid, /obj/item/weapon/card/id)) - src.active1 = null - src.active2 = null - if (src.check_access(src.master.authid)) - src.authenticated = src.master.authid.registered_name - src.rank = src.master.authid.assignment - src.screen = 1 - if (src.authenticated) - - if(href_list["screen"]) - src.screen = text2num(href_list["screen"]) - if(src.screen < 1) - src.screen = 1 - - src.active1 = null - src.active2 = null - - if(href_list["vir"]) - switch(href_list["vir"]) - if("gbs") - src.temp = {"Name: GBS -
    Number of stages: 5 -
    Spread: Airborne Transmission -
    Possible Cure: Spaceacillin -
    Affected Species: Human -
    -
    Notes: If left untreated death will occur. -
    -
    Severity: Major"} - if("cc") - src.temp = {"Name: Common Cold -
    Number of stages: 3 -
    Spread: Airborne Transmission -
    Possible Cure: Rest -
    Affected Species: Human -
    -
    Notes: If left untreated the subject will contract the flu. -
    -
    Severity: Minor"} - if("f") - src.temp = {"Name: The Flu -
    Number of stages: 3 -
    Spread: Airborne Transmission -
    Possible Cure: Rest -
    Affected Species: Human -
    -
    Notes: If left untreated the subject will feel quite unwell. -
    -
    Severity: Medium"} - if("jf") - src.temp = {"Name: Jungle Fever -
    Number of stages: 1 -
    Spread: Airborne Transmission -
    Possible Cure: None -
    Affected Species: Monkey -
    -
    Notes: monkeys with this disease will bite humans, causing humans to spontaneously to mutate into a monkey. -
    -
    Severity: Medium"} - if("ca") - src.temp = {"Name: Clowning Around -
    Number of stages: 4 -
    Spread: Airborne Transmission -
    Possible Cure: Spaceacillin -
    Affected Species: Human -
    -
    Notes: Subjects are affected by rampant honking and a fondness for shenanigans. They may also spontaneously phase through closed airlocks. -
    -
    Severity: Laughable"} - if("p") - src.temp = {"Name: Plasmatoid -
    Number of stages: 3 -
    Spread: Airborne Transmission -
    Possible Cure: Inaprovaline -
    Affected Species: Human and Monkey -
    -
    Notes: With this disease the victim will need plasma to breathe. -
    -
    Severity: Major"} - if("dna") - src.temp = {"Name: Space Rhinovirus -
    Number of stages: 4 -
    Spread: Airborne Transmission -
    Possible Cure: Spaceacillin -
    Affected Species: Human -
    -
    Notes: This disease transplants the genetic code of the intial vector into new hosts. -
    -
    Severity: Medium"} - if("bot") - src.temp = {"Name: Robot Transformation -
    Number of stages: 5 -
    Spread: Infected food -
    Possible Cure: None -
    Affected Species: Human -
    -
    Notes: This disease, actually acute nanomachine infection, converts the victim into a cyborg. -
    -
    Severity: Major"} - - if (href_list["del_all"]) - src.temp = text("Are you sure you wish to delete all records?
    \n\tYes
    \n\tNo
    ", src, src) - - if (href_list["del_all2"]) - for(var/datum/data/record/R in data_core.medical) - del(R) - src.temp = "All records deleted." - - if (href_list["field"]) - var/a1 = src.active1 - var/a2 = src.active2 - switch(href_list["field"]) - if("fingerprint") - if (istype(src.active1, /datum/data/record)) - var/t1 = input("Please input fingerprint hash:", "Med. records", src.active1.fields["id"], null) as text - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - src.active1.fields["fingerprint"] = t1 - if("sex") - if (istype(src.active1, /datum/data/record)) - if (src.active1.fields["sex"] == "Male") - src.active1.fields["sex"] = "Female" - else - src.active1.fields["sex"] = "Male" - if("age") - if (istype(src.active1, /datum/data/record)) - var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as text - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) - return - src.active1.fields["age"] = t1 - if("mi_dis") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["mi_dis"] = t1 - if("mi_dis_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["mi_dis_d"] = t1 - if("ma_dis") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["ma_dis"] = t1 - if("ma_dis_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["ma_dis_d"] = t1 - if("alg") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["alg"] = t1 - if("alg_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["alg_d"] = t1 - if("cdi") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["cdi"] = t1 - if("cdi_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["cdi_d"] = t1 - if("notes") - if (istype(src.active2, /datum/data/record)) - var/t1 = input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null) as message - if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - src.active2.fields["notes"] = t1 - if("p_stat") - if (istype(src.active1, /datum/data/record)) - src.temp = text("Physical Condition:
    \n\t*Deceased*
    \n\t*Unconscious*
    \n\tActive
    \n\tPhysically Unfit
    ", src, src, src, src) - if("m_stat") - if (istype(src.active1, /datum/data/record)) - src.temp = text("Mental Condition:
    \n\t*Insane*
    \n\t*Unstable*
    \n\t*Watch*
    \n\tStable
    ", src, src, src, src) - if("b_type") - if (istype(src.active2, /datum/data/record)) - src.temp = text("Blood Type:
    \n\tA- A+
    \n\tB- B+
    \n\tAB- AB+
    \n\tO- O+
    ", src, src, src, src, src, src, src, src) - else - - if (href_list["p_stat"]) - if (src.active1) - switch(href_list["p_stat"]) - if("deceased") - src.active1.fields["p_stat"] = "*Deceased*" - if("unconscious") - src.active1.fields["p_stat"] = "*Unconscious*" - if("active") - src.active1.fields["p_stat"] = "Active" - if("unfit") - src.active1.fields["p_stat"] = "Physically Unfit" - - if (href_list["m_stat"]) - if (src.active1) - switch(href_list["m_stat"]) - if("insane") - src.active1.fields["m_stat"] = "*Insane*" - if("unstable") - src.active1.fields["m_stat"] = "*Unstable*" - if("watch") - src.active1.fields["m_stat"] = "*Watch*" - if("stable") - src.active2.fields["m_stat"] = "Stable" - - - if (href_list["b_type"]) - if (src.active2) - switch(href_list["b_type"]) - if("an") - src.active2.fields["b_type"] = "A-" - if("bn") - src.active2.fields["b_type"] = "B-" - if("abn") - src.active2.fields["b_type"] = "AB-" - if("on") - src.active2.fields["b_type"] = "O-" - if("ap") - src.active2.fields["b_type"] = "A+" - if("bp") - src.active2.fields["b_type"] = "B+" - if("abp") - src.active2.fields["b_type"] = "AB+" - if("op") - src.active2.fields["b_type"] = "O+" - - - if (href_list["del_r"]) - if (src.active2) - src.temp = "Are you sure you wish to delete the record (Medical Portion Only)?
    \n\tYes
    \n\tNo
    " - - if (href_list["del_r2"]) - if (src.active2) - del(src.active2) - - if (href_list["d_rec"]) - var/datum/data/record/R = locate(href_list["d_rec"]) - var/datum/data/record/M = locate(href_list["d_rec"]) - if (!( data_core.general.Find(R) )) - src.temp = "Record Not Found!" - return - for(var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - else - //Foreach continue //goto(2540) - src.active1 = R - src.active2 = M - src.screen = 4 - - if (href_list["new"]) - if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) ))) - var/datum/data/record/R = new /datum/data/record( ) - R.fields["name"] = src.active1.fields["name"] - R.fields["id"] = src.active1.fields["id"] - R.name = text("Medical Record #[]", R.fields["id"]) - R.fields["b_type"] = "Unknown" - R.fields["mi_dis"] = "None" - R.fields["mi_dis_d"] = "No minor disabilities have been declared." - R.fields["ma_dis"] = "None" - R.fields["ma_dis_d"] = "No major disabilities have been diagnosed." - R.fields["alg"] = "None" - R.fields["alg_d"] = "No allergies have been detected in this patient." - R.fields["cdi"] = "None" - R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - R.fields["notes"] = "No notes." - data_core.medical += R - src.active2 = R - src.screen = 4 - - if (href_list["add_c"]) - if (!( istype(src.active2, /datum/data/record) )) - return - var/a2 = src.active2 - var/t1 = input("Add Comment:", "Med. records", null, null) as message - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) - return - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - counter++ - src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2556
    []", src.authenticated, src.rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1) - - if (href_list["del_c"]) - if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) - src.active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" - - if (href_list["search"]) - var/t1 = input("Search String: (Name or ID)", "Med. records", null, null) as text - if ((!( t1 ) || usr.stat || (!src.master) || !( src.authenticated ) || usr.restrained() || ((!in_range(src.master, usr)) && (!istype(usr, /mob/living/silicon))))) - return - src.active1 = null - src.active2 = null - t1 = lowertext(t1) - for(var/datum/data/record/R in data_core.general) - if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]))) - src.active1 = R - else - - if (!( src.active1 )) - src.temp = text("Could not locate record [].", t1) - else - for(var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == src.active1.fields["name"] || E.fields["id"] == src.active1.fields["id"])) - src.active2 = E - else - - src.screen = 4 - - if (href_list["print_p"]) - var/info = "
    Medical Record

    " - if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) - 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"]) - else - info += "General Record Lost!
    " - if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) - info += text("
    \n
    Medical Data

    \nBlood Type: []
    \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["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"]) - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - info += text("[]
    ", src.active2.fields[text("com_[]", counter)]) - counter++ - else - info += "Medical Record Lost!
    " - info += "
    " - - var/datum/signal/signal = new - signal.data["data"] = info - signal.data["title"] = "Medical Record" - src.peripheral_command("print",signal) - - src.master.add_fingerprint(usr) - src.master.updateUsrDialog() +/datum/computer/file/computer_program/med_data + name = "Medical Records" + size = 32.0 + active_icon = "dna" + req_access = list(ACCESS_MEDICAL) + var/authenticated = null + var/rank = null + var/screen = null + var/datum/data/record/active1 = null + var/datum/data/record/active2 = null + var/a_id = null + var/temp = null + +/datum/computer/file/computer_program/med_data/return_text() + if(..()) + return + var/dat + if (src.temp) + dat = text("[src.temp]

    Clear Screen") + else + dat = text("Confirm Identity: []
    ", master, (src.master.authid ? text("[]", src.master.authid.name) : "----------")) + if (src.authenticated) + switch(src.screen) + if(1.0) + dat += {" +Search Records +
    List Records +
    +
    Virus Database +
    Medbot Tracking +
    +
    Record Maintenance +
    {Log Out}
    +"} + if(2.0) + dat += "Record List:
    " + for(var/datum/data/record/R in data_core.general) + dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) + //Foreach goto(132) + dat += text("
    Back", src) + if(3.0) + dat += text("Records Maintenance
    \nBackup To Disk
    \nUpload From disk
    \nDelete All Records
    \n
    \nBack", src, src, src, src) + if(4.0) + dat += "
    Medical Record

    " + if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) + dat += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", src.active1.fields["name"], src.active1.fields["id"], src, src.active1.fields["sex"], src, src.active1.fields["age"], src, src.active1.fields["fingerprint"], src, src.active1.fields["p_stat"], src, src.active1.fields["m_stat"]) + 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: []
    \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["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"]) + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + dat += text("[]
    Delete Entry

    ", src.active2.fields[text("com_[]", counter)], src, counter) + counter++ + dat += text("Add Entry

    ", src) + dat += text("Delete Record (Medical Only)

    ", src) + else + dat += "Medical Record Lost!
    " + dat += text("New Record

    ") + dat += text("\nPrint Record
    \nBack
    ", src, src) + if(5.0) + dat += {"
    Virus Database
    +
    GBS +
    Common Cold +
    Flu +
    Jungle Fever +
    Clowning Around +
    Plasmatoid +
    Space Rhinovirus +
    Robot Transformation +
    Back"} + if(6.0) + dat += "
    Medical Robot Monitor
    " + dat += "Back" + dat += "
    Medical Robots:" + var/bdat = null + for(var/obj/machinery/bot/medbot/M in machines) + var/turf/bl = get_turf(M) + bdat += "[M.name] - \[[bl.x],[bl.y]\] - [M.on ? "Online" : "Offline"]
    " + if(!isnull(M.reagent_glass)) + bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]" + else + bdat += "Using Internal Synthesizer." + + if(!bdat) + dat += "
    None detected
    " + else + dat += "[bdat]" + + else + else + dat += text("{Log In}", src) + dat += "
    {Quit}" + + return dat + +/datum/computer/file/computer_program/med_data/Topic(href, href_list) + if(..()) + return + if (!( data_core.general.Find(src.active1) )) + src.active1 = null + if (!( data_core.medical.Find(src.active2) )) + src.active2 = null + if (href_list["temp"]) + src.temp = null + else if (href_list["logout"]) + src.authenticated = null + src.screen = null + src.active1 = null + src.active2 = null + else if (href_list["login"]) + if (istype(usr, /mob/living/silicon)) + src.active1 = null + src.active2 = null + src.authenticated = 1 + src.rank = "AI" + src.screen = 1 + else if (istype(src.master.authid, /obj/item/weapon/card/id)) + src.active1 = null + src.active2 = null + if (src.check_access(src.master.authid)) + src.authenticated = src.master.authid.registered_name + src.rank = src.master.authid.assignment + src.screen = 1 + if (src.authenticated) + + if(href_list["screen"]) + src.screen = text2num(href_list["screen"]) + if(src.screen < 1) + src.screen = 1 + + src.active1 = null + src.active2 = null + + if(href_list["vir"]) + switch(href_list["vir"]) + if("gbs") + src.temp = {"Name: GBS +
    Number of stages: 5 +
    Spread: Airborne Transmission +
    Possible Cure: Spaceacillin +
    Affected Species: Human +
    +
    Notes: If left untreated death will occur. +
    +
    Severity: Major"} + if("cc") + src.temp = {"Name: Common Cold +
    Number of stages: 3 +
    Spread: Airborne Transmission +
    Possible Cure: Rest +
    Affected Species: Human +
    +
    Notes: If left untreated the subject will contract the flu. +
    +
    Severity: Minor"} + if("f") + src.temp = {"Name: The Flu +
    Number of stages: 3 +
    Spread: Airborne Transmission +
    Possible Cure: Rest +
    Affected Species: Human +
    +
    Notes: If left untreated the subject will feel quite unwell. +
    +
    Severity: Medium"} + if("jf") + src.temp = {"Name: Jungle Fever +
    Number of stages: 1 +
    Spread: Airborne Transmission +
    Possible Cure: None +
    Affected Species: Monkey +
    +
    Notes: monkeys with this disease will bite humans, causing humans to spontaneously to mutate into a monkey. +
    +
    Severity: Medium"} + if("ca") + src.temp = {"Name: Clowning Around +
    Number of stages: 4 +
    Spread: Airborne Transmission +
    Possible Cure: Spaceacillin +
    Affected Species: Human +
    +
    Notes: Subjects are affected by rampant honking and a fondness for shenanigans. They may also spontaneously phase through closed airlocks. +
    +
    Severity: Laughable"} + if("p") + src.temp = {"Name: Plasmatoid +
    Number of stages: 3 +
    Spread: Airborne Transmission +
    Possible Cure: Inaprovaline +
    Affected Species: Human and Monkey +
    +
    Notes: With this disease the victim will need plasma to breathe. +
    +
    Severity: Major"} + if("dna") + src.temp = {"Name: Space Rhinovirus +
    Number of stages: 4 +
    Spread: Airborne Transmission +
    Possible Cure: Spaceacillin +
    Affected Species: Human +
    +
    Notes: This disease transplants the genetic code of the intial vector into new hosts. +
    +
    Severity: Medium"} + if("bot") + src.temp = {"Name: Robot Transformation +
    Number of stages: 5 +
    Spread: Infected food +
    Possible Cure: None +
    Affected Species: Human +
    +
    Notes: This disease, actually acute nanomachine infection, converts the victim into a cyborg. +
    +
    Severity: Major"} + + if (href_list["del_all"]) + src.temp = text("Are you sure you wish to delete all records?
    \n\tYes
    \n\tNo
    ", src, src) + + if (href_list["del_all2"]) + for(var/datum/data/record/R in data_core.medical) + del(R) + src.temp = "All records deleted." + + if (href_list["field"]) + var/a1 = src.active1 + var/a2 = src.active2 + switch(href_list["field"]) + if("fingerprint") + if (istype(src.active1, /datum/data/record)) + var/t1 = input("Please input fingerprint hash:", "Med. records", src.active1.fields["id"], null) as text + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + src.active1.fields["fingerprint"] = t1 + if("sex") + if (istype(src.active1, /datum/data/record)) + if (src.active1.fields["sex"] == "Male") + src.active1.fields["sex"] = "Female" + else + src.active1.fields["sex"] = "Male" + if("age") + if (istype(src.active1, /datum/data/record)) + var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as text + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + src.active1.fields["age"] = t1 + if("mi_dis") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["mi_dis"] = t1 + if("mi_dis_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["mi_dis_d"] = t1 + if("ma_dis") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["ma_dis"] = t1 + if("ma_dis_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["ma_dis_d"] = t1 + if("alg") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["alg"] = t1 + if("alg_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["alg_d"] = t1 + if("cdi") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["cdi"] = t1 + if("cdi_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["cdi_d"] = t1 + if("notes") + if (istype(src.active2, /datum/data/record)) + var/t1 = input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null) as message + if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + src.active2.fields["notes"] = t1 + if("p_stat") + if (istype(src.active1, /datum/data/record)) + src.temp = text("Physical Condition:
    \n\t*Deceased*
    \n\t*Unconscious*
    \n\tActive
    \n\tPhysically Unfit
    ", src, src, src, src) + if("m_stat") + if (istype(src.active1, /datum/data/record)) + src.temp = text("Mental Condition:
    \n\t*Insane*
    \n\t*Unstable*
    \n\t*Watch*
    \n\tStable
    ", src, src, src, src) + if("b_type") + if (istype(src.active2, /datum/data/record)) + src.temp = text("Blood Type:
    \n\tA- A+
    \n\tB- B+
    \n\tAB- AB+
    \n\tO- O+
    ", src, src, src, src, src, src, src, src) + else + + if (href_list["p_stat"]) + if (src.active1) + switch(href_list["p_stat"]) + if("deceased") + src.active1.fields["p_stat"] = "*Deceased*" + if("unconscious") + src.active1.fields["p_stat"] = "*Unconscious*" + if("active") + src.active1.fields["p_stat"] = "Active" + if("unfit") + src.active1.fields["p_stat"] = "Physically Unfit" + + if (href_list["m_stat"]) + if (src.active1) + switch(href_list["m_stat"]) + if("insane") + src.active1.fields["m_stat"] = "*Insane*" + if("unstable") + src.active1.fields["m_stat"] = "*Unstable*" + if("watch") + src.active1.fields["m_stat"] = "*Watch*" + if("stable") + src.active2.fields["m_stat"] = "Stable" + + + if (href_list["b_type"]) + if (src.active2) + switch(href_list["b_type"]) + if("an") + src.active2.fields["b_type"] = "A-" + if("bn") + src.active2.fields["b_type"] = "B-" + if("abn") + src.active2.fields["b_type"] = "AB-" + if("on") + src.active2.fields["b_type"] = "O-" + if("ap") + src.active2.fields["b_type"] = "A+" + if("bp") + src.active2.fields["b_type"] = "B+" + if("abp") + src.active2.fields["b_type"] = "AB+" + if("op") + src.active2.fields["b_type"] = "O+" + + + if (href_list["del_r"]) + if (src.active2) + src.temp = "Are you sure you wish to delete the record (Medical Portion Only)?
    \n\tYes
    \n\tNo
    " + + if (href_list["del_r2"]) + if (src.active2) + del(src.active2) + + if (href_list["d_rec"]) + var/datum/data/record/R = locate(href_list["d_rec"]) + var/datum/data/record/M = locate(href_list["d_rec"]) + if (!( data_core.general.Find(R) )) + src.temp = "Record Not Found!" + return + for(var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + else + //Foreach continue //goto(2540) + src.active1 = R + src.active2 = M + src.screen = 4 + + if (href_list["new"]) + if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) ))) + var/datum/data/record/R = new /datum/data/record( ) + R.fields["name"] = src.active1.fields["name"] + R.fields["id"] = src.active1.fields["id"] + R.name = text("Medical Record #[]", R.fields["id"]) + R.fields["b_type"] = "Unknown" + R.fields["mi_dis"] = "None" + R.fields["mi_dis_d"] = "No minor disabilities have been declared." + R.fields["ma_dis"] = "None" + R.fields["ma_dis_d"] = "No major disabilities have been diagnosed." + R.fields["alg"] = "None" + R.fields["alg_d"] = "No allergies have been detected in this patient." + R.fields["cdi"] = "None" + R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." + R.fields["notes"] = "No notes." + data_core.medical += R + src.active2 = R + src.screen = 4 + + if (href_list["add_c"]) + if (!( istype(src.active2, /datum/data/record) )) + return + var/a2 = src.active2 + var/t1 = input("Add Comment:", "Med. records", null, null) as message + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) + return + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + counter++ + src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2556
    []", src.authenticated, src.rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1) + + if (href_list["del_c"]) + if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) + src.active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" + + if (href_list["search"]) + var/t1 = input("Search String: (Name or ID)", "Med. records", null, null) as text + if ((!( t1 ) || usr.stat || (!src.master) || !( src.authenticated ) || usr.restrained() || ((!in_range(src.master, usr)) && (!istype(usr, /mob/living/silicon))))) + return + src.active1 = null + src.active2 = null + t1 = lowertext(t1) + for(var/datum/data/record/R in data_core.general) + if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]))) + src.active1 = R + else + + if (!( src.active1 )) + src.temp = text("Could not locate record [].", t1) + else + for(var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == src.active1.fields["name"] || E.fields["id"] == src.active1.fields["id"])) + src.active2 = E + else + + src.screen = 4 + + if (href_list["print_p"]) + var/info = "
    Medical Record

    " + if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) + 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"]) + else + info += "General Record Lost!
    " + if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) + info += text("
    \n
    Medical Data

    \nBlood Type: []
    \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["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"]) + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + info += text("[]
    ", src.active2.fields[text("com_[]", counter)]) + counter++ + else + info += "Medical Record Lost!
    " + info += "
    " + + var/datum/signal/signal = new + signal.data["data"] = info + signal.data["title"] = "Medical Record" + src.peripheral_command("print",signal) + + src.master.add_fingerprint(usr) + src.master.updateUsrDialog() return \ No newline at end of file diff --git a/code/unused/computer2/messenger.dm b/code/unused/computer2/messenger.dm index be1930bb7a2..e9090f3d054 100644 --- a/code/unused/computer2/messenger.dm +++ b/code/unused/computer2/messenger.dm @@ -1,97 +1,97 @@ -/datum/computer/file/computer_program/messenger - name = "Messenger" - size = 8.0 - var/messages = null - var/screen_name = "User" - -//To-do: take screen_name from inserted id card?? -//Saving log to file datum - - return_text() - if(..()) - return - - var/dat = "Close | " - dat += "Quit
    " - - dat += "SpaceMessenger V4.1.2
    " - - dat += "Send Message" - - dat += " | Clear" - dat += " | Print" - - dat += " | Name:[src.screen_name]
    " - - dat += messages - - dat += "
    " - - return dat - - Topic(href, href_list) - if(..()) - return - - if(href_list["send_msg"]) - var/t = input(usr, "Please enter messenger", src.id_tag, null) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t) - return - if (!in_range(src.master, usr)) - return - - var/datum/signal/signal = new - signal.data["type"] = "message" - signal.data["data"] = t - signal.data["sender"] = src.screen_name - src.messages += "→ You:
    [t]
    " - - peripheral_command("send signal", signal) - - if(href_list["func_msg"]) - switch(href_list["func_msg"]) - if("clear") - src.messages = null - - if("print") - var/datum/signal/signal = new - signal.data["data"] = src.messages - signal.data["title"] = "Chatlog" - peripheral_command("print", signal) - - //if("save") - //TO-DO - - - if(href_list["set_name"]) - var/t = input(usr, "Please enter screen name", src.id_tag, null) as text - t = copytext(sanitize(t), 1, 20) - if (!t) - return - if (!in_range(src.master, usr)) - return - - src.screen_name = t - - src.master.add_fingerprint(usr) - src.master.updateUsrDialog() - return - - receive_command(obj/source, command, datum/signal/signal) - if(..() || !signal) - return - - if(command == "radio signal") - switch(signal.data["type"]) - if("message") - var/sender = signal.data["sender"] - if(!sender) - sender = "Unknown" - - src.messages += "← From [sender]:
    [signal.data["data"]]
    " - if(src.master.active_program == src) - playsound(src.master.loc, 'sound/machines/twobeep.ogg', 50, 1) - src.master.updateUsrDialog() - +/datum/computer/file/computer_program/messenger + name = "Messenger" + size = 8.0 + var/messages = null + var/screen_name = "User" + +//To-do: take screen_name from inserted id card?? +//Saving log to file datum + + return_text() + if(..()) + return + + var/dat = "Close | " + dat += "Quit
    " + + dat += "SpaceMessenger V4.1.2
    " + + dat += "Send Message" + + dat += " | Clear" + dat += " | Print" + + dat += " | Name:[src.screen_name]
    " + + dat += messages + + dat += "
    " + + return dat + + Topic(href, href_list) + if(..()) + return + + if(href_list["send_msg"]) + var/t = input(usr, "Please enter messenger", src.id_tag, null) as text + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t) + return + if (!in_range(src.master, usr)) + return + + var/datum/signal/signal = new + signal.data["type"] = "message" + signal.data["data"] = t + signal.data["sender"] = src.screen_name + src.messages += "→ You:
    [t]
    " + + peripheral_command("send signal", signal) + + if(href_list["func_msg"]) + switch(href_list["func_msg"]) + if("clear") + src.messages = null + + if("print") + var/datum/signal/signal = new + signal.data["data"] = src.messages + signal.data["title"] = "Chatlog" + peripheral_command("print", signal) + + //if("save") + //TO-DO + + + if(href_list["set_name"]) + var/t = input(usr, "Please enter screen name", src.id_tag, null) as text + t = copytext(sanitize(t), 1, 20) + if (!t) + return + if (!in_range(src.master, usr)) + return + + src.screen_name = t + + src.master.add_fingerprint(usr) + src.master.updateUsrDialog() + return + + receive_command(obj/source, command, datum/signal/signal) + if(..() || !signal) + return + + if(command == "radio signal") + switch(signal.data["type"]) + if("message") + var/sender = signal.data["sender"] + if(!sender) + sender = "Unknown" + + src.messages += "← From [sender]:
    [signal.data["data"]]
    " + if(src.master.active_program == src) + playsound(src.master.loc, 'sound/machines/twobeep.ogg', 50, 1) + src.master.updateUsrDialog() + return \ No newline at end of file diff --git a/code/unused/computer2/peripherals.dm b/code/unused/computer2/peripherals.dm index f89423b3baf..f223cc5d56a 100644 --- a/code/unused/computer2/peripherals.dm +++ b/code/unused/computer2/peripherals.dm @@ -1,209 +1,209 @@ -/obj/item/weapon/peripheral - name = "Peripheral card" - desc = "A computer circuit board." - icon = 'icons/obj/module.dmi' - icon_state = "id_mod" - item_state = "electronic" - w_class = 2 - var/obj/machinery/computer2/host - var/id = null - - New() - ..() - spawn(2) - if(istype(src.loc,/obj/machinery/computer2)) - host = src.loc - host.peripherals.Add(src) -// var/setup_id = "\ref[src]" -// src.id = copytext(setup_id,4,(length(setup_id)-1) ) - - Del() - if(host) - host.peripherals.Remove(src) - ..() - - - proc - receive_command(obj/source, command, datum/signal/signal) - if((source != host) || !(src in host)) - return 1 - - if(!command) - return 1 - - return 0 - - send_command(command, datum/signal/signal) - if(!command || !host) - return - - src.host.receive_command(src, command, signal) - - return - -/obj/item/weapon/peripheral/radio - name = "Wireless card" - var/frequency = 1419 - var/code = null - var/datum/radio_frequency/radio_connection - New() - ..() - if(radio_controller) - initialize() - - initialize() - set_frequency(frequency) - - proc - set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency) - - receive_command(obj/source, command, datum/signal/signal) - if(..()) - return - - if(!signal || !radio_connection) - return - - switch(command) - if("send signal") - src.radio_connection.post_signal(src, signal) - - return - - receive_signal(datum/signal/signal) - if(!signal || (signal.encryption && signal.encryption != code)) - return - - var/datum/signal/newsignal = new - newsignal.data = signal.data - if(src.code) - newsignal.encryption = src.code - - send_command("radio signal",newsignal) - return - -/obj/item/weapon/peripheral/printer - name = "Printer module" - desc = "A small printer designed to fit into a computer casing." - icon_state = "card_mod" - var/printing = 0 - - receive_command(obj/source,command, datum/signal/signal) - if(..()) - return - - if(!signal) - return - - if((command == "print") && !src.printing) - src.printing = 1 - - var/print_data = signal.data["data"] - var/print_title = signal.data["title"] - if(!print_data) - src.printing = 0 - return - spawn(50) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.host.loc ) - P.info = print_data - if(print_title) - P.name = "paper - '[print_title]'" - - src.printing = 0 - return - - return - -/obj/item/weapon/peripheral/prize_vendor - name = "Prize vending module" - desc = "An arcade prize dispenser designed to fit inside a computer casing." - icon_state = "power_mod" - var/last_vend = 0 //Delay between vends if manually activated(ie a dude is holding it and shaking stuff out) - - receive_command(obj/source,command, datum/signal/signal) - if(..()) - return - - if(command == "vend prize") - src.vend_prize() - - return - - attack_self(mob/user as mob) - if( (last_vend + 400) < world.time) +/obj/item/weapon/peripheral + name = "Peripheral card" + desc = "A computer circuit board." + icon = 'icons/obj/module.dmi' + icon_state = "id_mod" + item_state = "electronic" + w_class = 2 + var/obj/machinery/computer2/host + var/id = null + + New() + ..() + spawn(2) + if(istype(src.loc,/obj/machinery/computer2)) + host = src.loc + host.peripherals.Add(src) +// var/setup_id = "\ref[src]" +// src.id = copytext(setup_id,4,(length(setup_id)-1) ) + + Del() + if(host) + host.peripherals.Remove(src) + ..() + + + proc + receive_command(obj/source, command, datum/signal/signal) + if((source != host) || !(src in host)) + return 1 + + if(!command) + return 1 + + return 0 + + send_command(command, datum/signal/signal) + if(!command || !host) + return + + src.host.receive_command(src, command, signal) + + return + +/obj/item/weapon/peripheral/radio + name = "Wireless card" + var/frequency = 1419 + var/code = null + var/datum/radio_frequency/radio_connection + New() + ..() + if(radio_controller) + initialize() + + initialize() + set_frequency(frequency) + + proc + set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency) + + receive_command(obj/source, command, datum/signal/signal) + if(..()) + return + + if(!signal || !radio_connection) + return + + switch(command) + if("send signal") + src.radio_connection.post_signal(src, signal) + + return + + receive_signal(datum/signal/signal) + if(!signal || (signal.encryption && signal.encryption != code)) + return + + var/datum/signal/newsignal = new + newsignal.data = signal.data + if(src.code) + newsignal.encryption = src.code + + send_command("radio signal",newsignal) + return + +/obj/item/weapon/peripheral/printer + name = "Printer module" + desc = "A small printer designed to fit into a computer casing." + icon_state = "card_mod" + var/printing = 0 + + receive_command(obj/source,command, datum/signal/signal) + if(..()) + return + + if(!signal) + return + + if((command == "print") && !src.printing) + src.printing = 1 + + var/print_data = signal.data["data"] + var/print_title = signal.data["title"] + if(!print_data) + src.printing = 0 + return + spawn(50) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.host.loc ) + P.info = print_data + if(print_title) + P.name = "paper - '[print_title]'" + + src.printing = 0 + return + + return + +/obj/item/weapon/peripheral/prize_vendor + name = "Prize vending module" + desc = "An arcade prize dispenser designed to fit inside a computer casing." + icon_state = "power_mod" + var/last_vend = 0 //Delay between vends if manually activated(ie a dude is holding it and shaking stuff out) + + receive_command(obj/source,command, datum/signal/signal) + if(..()) + return + + if(command == "vend prize") + src.vend_prize() + + return + + attack_self(mob/user as mob) + if( (last_vend + 400) < world.time) to_chat(user, "You shake something out of [src]!") - src.vend_prize() - src.last_vend = world.time - else + src.vend_prize() + src.last_vend = world.time + else to_chat(user, "[src] isn't ready to dispense a prize yet.") - - return - - proc/vend_prize() - var/obj/item/prize - var/prizeselect = rand(1,4) - var/turf/prize_location = null - - if(src.host) - prize_location = src.host.loc - else - prize_location = get_turf(src) - - switch(prizeselect) - if(1) - prize = new /obj/item/weapon/money( prize_location ) - prize.name = "space ticket" - prize.desc = "It's almost like actual currency!" - if(2) - prize = new /obj/item/beacon( prize_location ) - prize.name = "electronic blink toy game" - prize.desc = "Blink. Blink. Blink." - if(3) - prize = new /obj/item/weapon/lighter/zippo( prize_location ) - prize.name = "Burno Lighter" - prize.desc = "Almost like a decent lighter!" - if(4) - prize = new /obj/item/weapon/c_tube( prize_location ) - prize.name = "toy sword" - prize.icon = 'icons/obj/weapons.dmi' - prize.icon_state = "sword1" - prize.desc = "A sword made of cheap plastic." - -/* -/obj/item/weapon/peripheral/card_scanner - name = "ID scanner module" - icon_state = "card_mod" - var/obj/item/weapon/card/id/authid = null - - attack_self(mob/user as mob) - if(authid) + + return + + proc/vend_prize() + var/obj/item/prize + var/prizeselect = rand(1,4) + var/turf/prize_location = null + + if(src.host) + prize_location = src.host.loc + else + prize_location = get_turf(src) + + switch(prizeselect) + if(1) + prize = new /obj/item/weapon/money( prize_location ) + prize.name = "space ticket" + prize.desc = "It's almost like actual currency!" + if(2) + prize = new /obj/item/beacon( prize_location ) + prize.name = "electronic blink toy game" + prize.desc = "Blink. Blink. Blink." + if(3) + prize = new /obj/item/weapon/lighter/zippo( prize_location ) + prize.name = "Burno Lighter" + prize.desc = "Almost like a decent lighter!" + if(4) + prize = new /obj/item/weapon/c_tube( prize_location ) + prize.name = "toy sword" + prize.icon = 'icons/obj/weapons.dmi' + prize.icon_state = "sword1" + prize.desc = "A sword made of cheap plastic." + +/* +/obj/item/weapon/peripheral/card_scanner + name = "ID scanner module" + icon_state = "card_mod" + var/obj/item/weapon/card/id/authid = null + + attack_self(mob/user as mob) + if(authid) to_chat(user, "The card falls out.") - src.authid.loc = get_turf(user) - src.authid = null - - return - - receive_command(obj/source,command, datum/signal/signal) - if(..()) - return - - if(!signal || (signal.data["ref_id"] != "\ref[src]") ) - return - - switch(command) - if("eject card") - if(src.authid) - src.authid.loc = src.host.loc - src.authid = null - if("add card access") - var/new_access = signal.data["access"] - if(!new_access) - return - - - - return + src.authid.loc = get_turf(user) + src.authid = null + + return + + receive_command(obj/source,command, datum/signal/signal) + if(..()) + return + + if(!signal || (signal.data["ref_id"] != "\ref[src]") ) + return + + switch(command) + if("eject card") + if(src.authid) + src.authid.loc = src.host.loc + src.authid = null + if("add card access") + var/new_access = signal.data["access"] + if(!new_access) + return + + + + return */ \ No newline at end of file diff --git a/code/unused/filter_control.dm b/code/unused/filter_control.dm index e11d45dc3b5..88665e9ef0f 100644 --- a/code/unused/filter_control.dm +++ b/code/unused/filter_control.dm @@ -1,163 +1,163 @@ -// Currently only used to control /obj/machinery/inlet/filter -// todo: expand to vent control as well? - -/obj/machinery/filter_control/New() - ..() - spawn(5) //wait for world - for(var/obj/machinery/inlet/filter/F in machines) - if(F.control == src.control) - F.f_mask = src.f_mask - desc = "A remote control for a filter: [control]" - -/obj/machinery/filter_control/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/filter_control/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/filter_control/attackby(obj/item/weapon/W, mob/user as mob) - if(istype(W, /obj/item/weapon/detective_scanner)) - return ..() - if(istype(W, /obj/item/weapon/screwdriver)) - src.add_fingerprint(user) - user.show_message(text("Now [] the panel...", (src.locked) ? "unscrewing" : "reattaching"), 1) - sleep(30) - src.locked =! src.locked - src.updateicon() - return - if(istype(W, /obj/item/weapon/wirecutters) && !src.locked) - stat ^= BROKEN - src.add_fingerprint(user) - for(var/mob/O in viewers(user, null)) - O.show_message(text("[] has []activated []!", user, (stat&BROKEN) ? "de" : "re", src), 1) - src.updateicon() - return - if(istype(W, /obj/item/weapon/card/emag) && !emagged) - emagged++ - for(var/mob/O in viewers(user, null)) - O.show_message(text("[] has shorted out the []'s access system with an electromagnetic card!", user, src), 1) - src.updateicon() - return src.attack_hand(user) - return src.attack_hand(user) - -/obj/machinery/filter_control/process() - if(!(stat & NOPOWER)) - use_power(5,ENVIRON) - AutoUpdateAI(src) - src.updateUsrDialog() - src.updateicon() - -/obj/machinery/filter_control/attack_hand(mob/user as mob) - if(stat & NOPOWER) - user << browse(null, "window=filter_control") - user.machine = null - return - if(user.stat || user.lying) - return - if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon/ai)) - return 0 - - var/list/gases = list("O2", "N2", "Plasma", "CO2", "N2O") - var/dat - user.machine = src - - var/IGoodConnection = 0 - var/IBadConnection = 0 - - for(var/obj/machinery/inlet/filter/F in machines) - if((F.control == src.control) && !(F.stat && (NOPOWER|BROKEN))) - IGoodConnection++ - else if(F.control == src.control) - IBadConnection++ - var/ITotalConnections = IGoodConnection+IBadConnection - - if(ITotalConnections && !(stat & BROKEN)) //ugly - dat += "Connection status: Inlets:[ITotalConnections]/[IGoodConnection]
    \n Control ID: [control]

    \n" - else - dat += "No Connections Detected!
    \n Control ID: [control]
    \n" - if(!stat & BROKEN) - for (var/i = 1; i <= gases.len; i++) - dat += "[gases[i]]: [(src.f_mask & 1 << (i - 1)) ? "Siphoning" : "Passing"]
    \n" - else - dat += "Warning! Severe Internal Memory Corruption!
    \n
    \nConsult a qualified station technician immediately!

    \n" - dat += "
    \nError codes: 0x0000001E 0x0000007B
    \n" - - dat += "
    \nClose
    \n" - user << browse(dat, "window=filter_control;size=300x225") - onclose(user, "filter_control") -/obj/machinery/filter_control/Topic(href, href_list) - if (href_list["close"]) - usr << browse(null, "window=filter_control;") - usr.machine = null - return //Who cares if we're dead or whatever let us close the fucking window - if(..()) - return 1 - else - usr.machine = src - if (src.allowed(usr) || src.emagged && !(stat & BROKEN)) - if (href_list["tg"]) //someone modified the html so I added a check here - // toggle gas - src.f_mask ^= text2num(href_list["tg"]) - for(var/obj/machinery/inlet/filter/FI in machines) - if(FI.control == src.control) - FI.f_mask ^= text2num(href_list["tg"]) - else - usr.see("Access Denied ([src.name] operation restricted to authorized atmospheric technicians.)") - AutoUpdateAI(src) - src.updateUsrDialog() - src.add_fingerprint(usr) - else - usr << browse(null, "window=filter_control") - usr.machine = null - return - -/obj/machinery/filter_control/proc/updateicon() - overlays.len = 0 - if(stat & NOPOWER) - icon_state = "filter_control-nopower" - return - icon_state = "filter_control" - if(src.locked && (stat & BROKEN)) - overlays += image('icons/obj/stationobjs.dmi', "filter_control00") - return - else if(!src.locked) - icon_state = "filter_control-unlocked" - if(stat & BROKEN) - overlays += image('icons/obj/stationobjs.dmi', "filter_control-wirecut") - overlays += image('icons/obj/stationobjs.dmi', "filter_control00") - return - - var/GoodConnection = 0 - for(var/obj/machinery/inlet/filter/F in machines) - if((F.control == src.control) && !(F.stat && (NOPOWER|BROKEN))) - GoodConnection++ - break - - if(GoodConnection && src.f_mask) - overlays += image('icons/obj/stationobjs.dmi', "filter_control1") - else if(GoodConnection) - overlays += image('icons/obj/stationobjs.dmi', "filter_control10") - else if(src.f_mask) - overlays += image('icons/obj/stationobjs.dmi', "filter_control0") - else - overlays += image('icons/obj/stationobjs.dmi', "filter_control00") - - if (src.f_mask & (GAS_N2O|GAS_PL)) - src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-tox") - if (src.f_mask & GAS_O2) - src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-o2") - if (src.f_mask & GAS_N2) - src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-n2") - if (src.f_mask & GAS_CO2) - src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-co2") - return - -/obj/machinery/filter_control/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER - else - stat |= NOPOWER - spawn(rand(1,15)) - src.updateicon() +// Currently only used to control /obj/machinery/inlet/filter +// todo: expand to vent control as well? + +/obj/machinery/filter_control/New() + ..() + spawn(5) //wait for world + for(var/obj/machinery/inlet/filter/F in machines) + if(F.control == src.control) + F.f_mask = src.f_mask + desc = "A remote control for a filter: [control]" + +/obj/machinery/filter_control/attack_ai(mob/user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/filter_control/attack_paw(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/filter_control/attackby(obj/item/weapon/W, mob/user as mob) + if(istype(W, /obj/item/weapon/detective_scanner)) + return ..() + if(istype(W, /obj/item/weapon/screwdriver)) + src.add_fingerprint(user) + user.show_message(text("Now [] the panel...", (src.locked) ? "unscrewing" : "reattaching"), 1) + sleep(30) + src.locked =! src.locked + src.updateicon() + return + if(istype(W, /obj/item/weapon/wirecutters) && !src.locked) + stat ^= BROKEN + src.add_fingerprint(user) + for(var/mob/O in viewers(user, null)) + O.show_message(text("[] has []activated []!", user, (stat&BROKEN) ? "de" : "re", src), 1) + src.updateicon() + return + if(istype(W, /obj/item/weapon/card/emag) && !emagged) + emagged++ + for(var/mob/O in viewers(user, null)) + O.show_message(text("[] has shorted out the []'s access system with an electromagnetic card!", user, src), 1) + src.updateicon() + return src.attack_hand(user) + return src.attack_hand(user) + +/obj/machinery/filter_control/process() + if(!(stat & NOPOWER)) + use_power(5,ENVIRON) + AutoUpdateAI(src) + src.updateUsrDialog() + src.updateicon() + +/obj/machinery/filter_control/attack_hand(mob/user as mob) + if(stat & NOPOWER) + user << browse(null, "window=filter_control") + user.machine = null + return + if(user.stat || user.lying) + return + if ((get_dist(src, user) > 1 || !istype(src.loc, /turf)) && !istype(user, /mob/living/silicon/ai)) + return 0 + + var/list/gases = list("O2", "N2", "Plasma", "CO2", "N2O") + var/dat + user.machine = src + + var/IGoodConnection = 0 + var/IBadConnection = 0 + + for(var/obj/machinery/inlet/filter/F in machines) + if((F.control == src.control) && !(F.stat && (NOPOWER|BROKEN))) + IGoodConnection++ + else if(F.control == src.control) + IBadConnection++ + var/ITotalConnections = IGoodConnection+IBadConnection + + if(ITotalConnections && !(stat & BROKEN)) //ugly + dat += "Connection status: Inlets:[ITotalConnections]/[IGoodConnection]
    \n Control ID: [control]

    \n" + else + dat += "No Connections Detected!
    \n Control ID: [control]
    \n" + if(!stat & BROKEN) + for (var/i = 1; i <= gases.len; i++) + dat += "[gases[i]]: [(src.f_mask & 1 << (i - 1)) ? "Siphoning" : "Passing"]
    \n" + else + dat += "Warning! Severe Internal Memory Corruption!
    \n
    \nConsult a qualified station technician immediately!

    \n" + dat += "
    \nError codes: 0x0000001E 0x0000007B
    \n" + + dat += "
    \nClose
    \n" + user << browse(dat, "window=filter_control;size=300x225") + onclose(user, "filter_control") +/obj/machinery/filter_control/Topic(href, href_list) + if (href_list["close"]) + usr << browse(null, "window=filter_control;") + usr.machine = null + return //Who cares if we're dead or whatever let us close the fucking window + if(..()) + return 1 + else + usr.machine = src + if (src.allowed(usr) || src.emagged && !(stat & BROKEN)) + if (href_list["tg"]) //someone modified the html so I added a check here + // toggle gas + src.f_mask ^= text2num(href_list["tg"]) + for(var/obj/machinery/inlet/filter/FI in machines) + if(FI.control == src.control) + FI.f_mask ^= text2num(href_list["tg"]) + else + usr.see("Access Denied ([src.name] operation restricted to authorized atmospheric technicians.)") + AutoUpdateAI(src) + src.updateUsrDialog() + src.add_fingerprint(usr) + else + usr << browse(null, "window=filter_control") + usr.machine = null + return + +/obj/machinery/filter_control/proc/updateicon() + overlays.len = 0 + if(stat & NOPOWER) + icon_state = "filter_control-nopower" + return + icon_state = "filter_control" + if(src.locked && (stat & BROKEN)) + overlays += image('icons/obj/stationobjs.dmi', "filter_control00") + return + else if(!src.locked) + icon_state = "filter_control-unlocked" + if(stat & BROKEN) + overlays += image('icons/obj/stationobjs.dmi', "filter_control-wirecut") + overlays += image('icons/obj/stationobjs.dmi', "filter_control00") + return + + var/GoodConnection = 0 + for(var/obj/machinery/inlet/filter/F in machines) + if((F.control == src.control) && !(F.stat && (NOPOWER|BROKEN))) + GoodConnection++ + break + + if(GoodConnection && src.f_mask) + overlays += image('icons/obj/stationobjs.dmi', "filter_control1") + else if(GoodConnection) + overlays += image('icons/obj/stationobjs.dmi', "filter_control10") + else if(src.f_mask) + overlays += image('icons/obj/stationobjs.dmi', "filter_control0") + else + overlays += image('icons/obj/stationobjs.dmi', "filter_control00") + + if (src.f_mask & (GAS_N2O|GAS_PL)) + src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-tox") + if (src.f_mask & GAS_O2) + src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-o2") + if (src.f_mask & GAS_N2) + src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-n2") + if (src.f_mask & GAS_CO2) + src.overlays += image('icons/obj/stationobjs.dmi', "filter_control-co2") + return + +/obj/machinery/filter_control/power_change() + if(powered(ENVIRON)) + stat &= ~NOPOWER + else + stat |= NOPOWER + spawn(rand(1,15)) + src.updateicon() return \ No newline at end of file diff --git a/code/unused/gamemodes/ctf.dm b/code/unused/gamemodes/ctf.dm index 41c810c1985..e5aae91f29e 100644 --- a/code/unused/gamemodes/ctf.dm +++ b/code/unused/gamemodes/ctf.dm @@ -1,141 +1,141 @@ -/* -/datum/game_mode/ctf - name = "ctf" - config_tag = "ctf" - -/datum/game_mode/ctf/announce() +/* +/datum/game_mode/ctf + name = "ctf" + config_tag = "ctf" + +/datum/game_mode/ctf/announce() to_chat(world, "The current game mode is - Capture the Flag!") to_chat(world, "Capture the other teams flag and bring it back to your base!") to_chat(world, "Respawn is on") - -/datum/game_mode/ctf/pre_setup() - - config.allow_ai = 0 - var/list/mobs = list() - var/total_mobs - for(var/mob/living/carbon/human/M in world) - if (M.client) - mobs += M - total_mobs++ - - var/obj/R = locate("landmark*Red-Spawn") - var/obj/G = locate("landmark*Green-Spawn") - - var/mob_check - for(var/mob/living/carbon/human/M in mobs) - if(!M) - continue - mob_check++ - if(mob_check <= total_mobs/2) //add to red team else to green - spawn() - if(M.client) + +/datum/game_mode/ctf/pre_setup() + + config.allow_ai = 0 + var/list/mobs = list() + var/total_mobs + for(var/mob/living/carbon/human/M in world) + if (M.client) + mobs += M + total_mobs++ + + var/obj/R = locate("landmark*Red-Spawn") + var/obj/G = locate("landmark*Green-Spawn") + + var/mob_check + for(var/mob/living/carbon/human/M in mobs) + if(!M) + continue + mob_check++ + if(mob_check <= total_mobs/2) //add to red team else to green + spawn() + if(M.client) to_chat(M, "You are in the Red Team!") - del(M.wear_suit) - M.w_uniform = new /obj/item/clothing/under/color/red(M) - M.w_uniform.layer = 20 - del(M.shoes) - M.wear_suit = new /obj/item/clothing/suit/armor/tdome/red(M) - M.wear_suit.layer = 20 - M.shoes = new /obj/item/clothing/shoes/black(M) - M.shoes.layer = 20 - M.wear_mask = new /obj/item/clothing/mask/gas/emergency(M) - M.wear_mask.layer = 20 - M.gloves = new /obj/item/clothing/gloves/swat(M) - M.gloves.layer = 20 - M.glasses = new /obj/item/clothing/glasses/thermal(M) - M.glasses.layer = 20 - var/obj/item/device/radio/headset/H = new /obj/item/device/radio/headset(M) - H.set_frequency(1465) - M.w_radio = H - M.w_radio.layer = 20 - var/obj/item/weapon/tank/air/O = new /obj/item/weapon/tank/air(M) - M.back = O - M.back.layer = 20 - M.internal = O - - del(M.wear_id) - var/obj/item/weapon/card/id/W = new(M) - W.name = "[M.real_name]'s ID card (Red Team)" - W.access = access_red - W.assignment = "Red Team" - W.registered_name = M.real_name - M.wear_id = W - M.wear_id.layer = 20 - if(R) - M.loc = R.loc - else + del(M.wear_suit) + M.w_uniform = new /obj/item/clothing/under/color/red(M) + M.w_uniform.layer = 20 + del(M.shoes) + M.wear_suit = new /obj/item/clothing/suit/armor/tdome/red(M) + M.wear_suit.layer = 20 + M.shoes = new /obj/item/clothing/shoes/black(M) + M.shoes.layer = 20 + M.wear_mask = new /obj/item/clothing/mask/gas/emergency(M) + M.wear_mask.layer = 20 + M.gloves = new /obj/item/clothing/gloves/swat(M) + M.gloves.layer = 20 + M.glasses = new /obj/item/clothing/glasses/thermal(M) + M.glasses.layer = 20 + var/obj/item/device/radio/headset/H = new /obj/item/device/radio/headset(M) + H.set_frequency(1465) + M.w_radio = H + M.w_radio.layer = 20 + var/obj/item/weapon/tank/air/O = new /obj/item/weapon/tank/air(M) + M.back = O + M.back.layer = 20 + M.internal = O + + del(M.wear_id) + var/obj/item/weapon/card/id/W = new(M) + W.name = "[M.real_name]'s ID card (Red Team)" + W.access = access_red + W.assignment = "Red Team" + W.registered_name = M.real_name + M.wear_id = W + M.wear_id.layer = 20 + if(R) + M.loc = R.loc + else to_chat(world, "No red team spawn point detected") - M.client.team = "Red" - else - spawn() - if(M.client) + M.client.team = "Red" + else + spawn() + if(M.client) to_chat(M, "You are in the Green Team!") - del(M.wear_suit) - M.w_uniform = new /obj/item/clothing/under/color/green(M) - M.w_uniform.layer = 20 - del(M.shoes) - M.wear_suit = new /obj/item/clothing/suit/armor/tdome/green(M) - M.wear_suit.layer = 20 - M.shoes = new /obj/item/clothing/shoes/black(M) - M.shoes.layer = 20 - M.wear_mask = new /obj/item/clothing/mask/gas/emergency(M) - M.wear_mask.layer = 20 - M.gloves = new /obj/item/clothing/gloves/swat(M) - M.gloves.layer = 20 - M.glasses = new /obj/item/clothing/glasses/thermal(M) - M.glasses.layer = 20 - var/obj/item/device/radio/headset/H = new /obj/item/device/radio/headset(M) - H.set_frequency(1449) - M.w_radio = H - M.w_radio.layer = 20 - var/obj/item/weapon/tank/air/O = new /obj/item/weapon/tank/air(M) - M.back = O - M.back.layer = 20 - M.internal = O - - del(M.wear_id) - var/obj/item/weapon/card/id/W = new(M) - W.name = "[M.real_name]'s ID card (Green Team)" - W.access = access_green - W.assignment = "Green Team" - W.registered_name = M.real_name - M.wear_id = W - M.wear_id.layer = 20 - if(G) - M.loc = G.loc - else + del(M.wear_suit) + M.w_uniform = new /obj/item/clothing/under/color/green(M) + M.w_uniform.layer = 20 + del(M.shoes) + M.wear_suit = new /obj/item/clothing/suit/armor/tdome/green(M) + M.wear_suit.layer = 20 + M.shoes = new /obj/item/clothing/shoes/black(M) + M.shoes.layer = 20 + M.wear_mask = new /obj/item/clothing/mask/gas/emergency(M) + M.wear_mask.layer = 20 + M.gloves = new /obj/item/clothing/gloves/swat(M) + M.gloves.layer = 20 + M.glasses = new /obj/item/clothing/glasses/thermal(M) + M.glasses.layer = 20 + var/obj/item/device/radio/headset/H = new /obj/item/device/radio/headset(M) + H.set_frequency(1449) + M.w_radio = H + M.w_radio.layer = 20 + var/obj/item/weapon/tank/air/O = new /obj/item/weapon/tank/air(M) + M.back = O + M.back.layer = 20 + M.internal = O + + del(M.wear_id) + var/obj/item/weapon/card/id/W = new(M) + W.name = "[M.real_name]'s ID card (Green Team)" + W.access = access_green + W.assignment = "Green Team" + W.registered_name = M.real_name + M.wear_id = W + M.wear_id.layer = 20 + if(G) + M.loc = G.loc + else to_chat(world, "No green team spawn point detected") - M.client.team = "Green" - - -/datum/game_mode/ctf/post_setup() - abandon_allowed = 1 - setup_game() - - spawn (50) - var/obj/L = locate("landmark*Red-Flag") - if (L) - new /obj/item/weapon/ctf_flag/red(L.loc) - else + M.client.team = "Green" + + +/datum/game_mode/ctf/post_setup() + abandon_allowed = 1 + setup_game() + + spawn (50) + var/obj/L = locate("landmark*Red-Flag") + if (L) + new /obj/item/weapon/ctf_flag/red(L.loc) + else to_chat(world, "No red flag spawn point detected") - - L = locate("landmark*Green-Flag") - if (L) - new /obj/item/weapon/ctf_flag/green(L.loc) - else + + L = locate("landmark*Green-Flag") + if (L) + new /obj/item/weapon/ctf_flag/green(L.loc) + else to_chat(world, "No green flag spawn point detected") - - L = locate("landmark*The-Red-Team") - if (L) - new /obj/machinery/red_injector(L.loc) - else + + L = locate("landmark*The-Red-Team") + if (L) + new /obj/machinery/red_injector(L.loc) + else to_chat(world, "No red team spawn injector point detected") - - L = locate("landmark*The-Green-Team") - if (L) - new /obj/machinery/green_injector(L.loc) - else + + L = locate("landmark*The-Green-Team") + if (L) + new /obj/machinery/green_injector(L.loc) + else to_chat(world, "No green team injector spawn point detected") - ..() - + ..() + */ \ No newline at end of file diff --git a/code/unused/gamemodes/ctf_items.dm b/code/unused/gamemodes/ctf_items.dm index 5f242d727a5..9771043ee2b 100644 --- a/code/unused/gamemodes/ctf_items.dm +++ b/code/unused/gamemodes/ctf_items.dm @@ -1,139 +1,139 @@ -/obj/item/weapon/ctf_flag - name = "Flag" - desc = "Its a flag" - w_class = 5 - icon = 'flags.dmi' - icon_state = "flag_neutral" - item_state = "paper" - -/obj/item/weapon/ctf_flag/red - name = "The Red Flag" - desc = "Catch dat fukken flag" - icon_state = "flag_red" - -/obj/item/weapon/ctf_flag/green - name = "The Green Flag" - desc = "Catch dat fukken flag" - icon_state = "flag_green" - -/obj/item/weapon/ctf_flag/New() - ..() - spawn(200) - process() - return - -/obj/item/weapon/ctf_flag/process() - if(istype(src, /obj/item/weapon/ctf_flag/green)) - var/obj/L = locate("landmark*Green-Flag") - if(locate("landmark*Green-Flag", src)) - spawn(200) - process() - return - else if(!src.check_if_equipped() && L) - new /obj/item/weapon/ctf_flag/green(L.loc) - del(src) - if(istype(src, /obj/item/weapon/ctf_flag/red)) - var/obj/L = locate("landmark*Red-Flag") - if(locate("landmark*Red-Flag", src)) - spawn(200) - process() - return - else if(!src.check_if_equipped() && L) - new /obj/item/weapon/ctf_flag/red(L.loc) - del(src) - return - -/obj/item/weapon/ctf_flag/proc/check_if_equipped() - var/equipped = 0 - for(var/mob/M in living_mob_list) - if(M &&!M.stat) - var/list/L = M.get_contents() - if(src in L) - equipped = 1 - break - return equipped - -/obj/machinery/red_injector - name = "Red Team Flag Injector" - desc = "Insert flag here" - anchored = 1 - density = 1 - var/score = 0 - var/operating = 0 - icon = 'flags.dmi' - icon_state = "red_injector" -/* -/obj/machinery/red_injector/ex_act(severity) - return - -/obj/machinery/red_injector/attackby(var/obj/item/weapon/ctf_flag/C, mob/user) - if(src.operating) +/obj/item/weapon/ctf_flag + name = "Flag" + desc = "Its a flag" + w_class = 5 + icon = 'flags.dmi' + icon_state = "flag_neutral" + item_state = "paper" + +/obj/item/weapon/ctf_flag/red + name = "The Red Flag" + desc = "Catch dat fukken flag" + icon_state = "flag_red" + +/obj/item/weapon/ctf_flag/green + name = "The Green Flag" + desc = "Catch dat fukken flag" + icon_state = "flag_green" + +/obj/item/weapon/ctf_flag/New() + ..() + spawn(200) + process() + return + +/obj/item/weapon/ctf_flag/process() + if(istype(src, /obj/item/weapon/ctf_flag/green)) + var/obj/L = locate("landmark*Green-Flag") + if(locate("landmark*Green-Flag", src)) + spawn(200) + process() + return + else if(!src.check_if_equipped() && L) + new /obj/item/weapon/ctf_flag/green(L.loc) + del(src) + if(istype(src, /obj/item/weapon/ctf_flag/red)) + var/obj/L = locate("landmark*Red-Flag") + if(locate("landmark*Red-Flag", src)) + spawn(200) + process() + return + else if(!src.check_if_equipped() && L) + new /obj/item/weapon/ctf_flag/red(L.loc) + del(src) + return + +/obj/item/weapon/ctf_flag/proc/check_if_equipped() + var/equipped = 0 + for(var/mob/M in living_mob_list) + if(M &&!M.stat) + var/list/L = M.get_contents() + if(src in L) + equipped = 1 + break + return equipped + +/obj/machinery/red_injector + name = "Red Team Flag Injector" + desc = "Insert flag here" + anchored = 1 + density = 1 + var/score = 0 + var/operating = 0 + icon = 'flags.dmi' + icon_state = "red_injector" +/* +/obj/machinery/red_injector/ex_act(severity) + return + +/obj/machinery/red_injector/attackby(var/obj/item/weapon/ctf_flag/C, mob/user) + if(src.operating) to_chat(user, "Cannot put a flag in right now") - return - src.operating = 1 - if(istype(C, /obj/item/weapon/ctf_flag/green)) - if(locate("landmark*Red-Flag", /obj/item/weapon/ctf_flag/red)) - src.score++ + return + src.operating = 1 + if(istype(C, /obj/item/weapon/ctf_flag/green)) + if(locate("landmark*Red-Flag", /obj/item/weapon/ctf_flag/red)) + src.score++ to_chat(world, "[user.real_name] has scored for the red team!") - if(ticker.mode.name == "ctf") - ticker.red_score++ - var/obj/L = locate("landmark*Green-Flag") - if (L) - del(C) - new /obj/item/weapon/ctf_flag/green(L.loc) - else + if(ticker.mode.name == "ctf") + ticker.red_score++ + var/obj/L = locate("landmark*Green-Flag") + if (L) + del(C) + new /obj/item/weapon/ctf_flag/green(L.loc) + else to_chat(world, "No green flag spawn point detected") - if(src.score >= 15) + if(src.score >= 15) to_chat(world, "The Red Team has won!") to_chat(world, "They have scored [score] times with the flag!") - sleep(300) - world.Reboot() - else + sleep(300) + world.Reboot() + else to_chat(user, "You need to have your flag in the beginning position!") - else if(istype(C, /obj/item/weapon/ctf_flag/red)) + else if(istype(C, /obj/item/weapon/ctf_flag/red)) to_chat(world, "[user.real_name] has tried to score with their own flag! Idiot!") - src.operating = 0 - return -*/ -/obj/machinery/green_injector - name = "Green Team Flag Injector" - desc = "Insert flag here" - anchored = 1 - density = 1 - var/operating = 0 - var/score = 0 - icon = 'flags.dmi' - icon_state = "green_injector" - -/obj/machinery/green_injector/ex_act(severity) - return -/* -/obj/machinery/green_injector/attackby(var/obj/item/weapon/ctf_flag/C, mob/user) - if(src.operating) + src.operating = 0 + return +*/ +/obj/machinery/green_injector + name = "Green Team Flag Injector" + desc = "Insert flag here" + anchored = 1 + density = 1 + var/operating = 0 + var/score = 0 + icon = 'flags.dmi' + icon_state = "green_injector" + +/obj/machinery/green_injector/ex_act(severity) + return +/* +/obj/machinery/green_injector/attackby(var/obj/item/weapon/ctf_flag/C, mob/user) + if(src.operating) to_chat(user, "Cannot put a flag in right now") - return - src.operating = 1 - if(istype(C, /obj/item/weapon/ctf_flag/red)) - if(locate("landmark*Green-Flag", /obj/item/weapon/ctf_flag/green)) - src.score++ + return + src.operating = 1 + if(istype(C, /obj/item/weapon/ctf_flag/red)) + if(locate("landmark*Green-Flag", /obj/item/weapon/ctf_flag/green)) + src.score++ to_chat(world, "[user.real_name] has scored for the green team!") - if(ticker.mode.name == "ctf") - ticker.green_score++ - var/obj/L = locate("landmark*Red-Flag") - if (L) - del(C) - new /obj/item/weapon/ctf_flag/red(L.loc) - else + if(ticker.mode.name == "ctf") + ticker.green_score++ + var/obj/L = locate("landmark*Red-Flag") + if (L) + del(C) + new /obj/item/weapon/ctf_flag/red(L.loc) + else to_chat(world, "No red flag spawn point detected") - if(src.score >= 15) + if(src.score >= 15) to_chat(world, "The Green Team has won!") to_chat(world, "They have scored [score] times with the flag!") - sleep(300) - world.Reboot() - else + sleep(300) + world.Reboot() + else to_chat(user, "You need to have your flag in the beginning position!") - else if(istype(C, /obj/item/weapon/ctf_flag/green)) + else if(istype(C, /obj/item/weapon/ctf_flag/green)) to_chat(world, "[user.real_name] has tried to score with their own flag! Idiot!") - src.operating = 0 - return + src.operating = 0 + return */ \ No newline at end of file diff --git a/code/unused/gamemodes/deathmatch.dm b/code/unused/gamemodes/deathmatch.dm index e957f2d9184..194d7aa86ca 100644 --- a/code/unused/gamemodes/deathmatch.dm +++ b/code/unused/gamemodes/deathmatch.dm @@ -1,67 +1,67 @@ -/* -/datum/game_mode/deathmatch - name = "deathmatch" - config_tag = "deathmatch" - var/startedat - var/const/gamelength = 15 * 600 // 1/10 second - - announce() +/* +/datum/game_mode/deathmatch + name = "deathmatch" + config_tag = "deathmatch" + var/startedat + var/const/gamelength = 15 * 600 // 1/10 second + + announce() to_chat(world, "The current game mode is - Death Commando Deathmatch!") to_chat(world, "Just kill everyone else. They're gonna try to kill you, after all. Respawning is enabled.") - - post_setup() - startedat = world.realtime - abandon_allowed = 1 - setup_game() - - // TODO: DEFERRED Make this massively cleaner. It should hook before spawning, not after. - var/list/mobs = list() - for(var/mob/living/carbon/human/M in world) - if (M.client) - mobs += M - for(var/mob/living/carbon/human/M in mobs) - spawn() - if(M.client) - for(var/obj/item/weapon/W in list(M.wear_suit, M.w_uniform, M.r_store, M.l_store, M.wear_id, M.belt, - M.gloves, M.glasses, M.head, M.ears, M.shoes, M.wear_mask, M.back, - M.handcuffed, M.r_hand, M.l_hand)) - M.u_equip(W) - del(W) - - var/randomname = "Killiam Shakespeare" - if(commando_names.len) - randomname = pick(commando_names) - commando_names -= randomname - var/newname = input(M,"You are a death commando. Would you like to change your name?", "Character Creation", randomname) - if(!length(newname)) - newname = randomname - newname = strip_html(newname,40) - - M.real_name = newname - M.name = newname // there are WAY more things than this to change, I'm almost certain - - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/swat_suit/death_commando(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/death_commando(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/m_pill/cyanide(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/weapon/flashbang(M), slot_r_store) - - var/obj/item/weapon/tank/air/O = new(M) - M.equip_to_slot_or_del(O, slot_back) - M.internal = O - - var/obj/item/weapon/card/id/W = new(M) - W.access = get_all_accesses() - W.name = "[newname]'s ID card (Death Commando)" - W.assignment = "Death Commando" - W.registered_name = newname - M.equip_to_slot_or_del(W, slot_wear_id) - ..() - - check_win() - return 1 + + post_setup() + startedat = world.realtime + abandon_allowed = 1 + setup_game() + + // TODO: DEFERRED Make this massively cleaner. It should hook before spawning, not after. + var/list/mobs = list() + for(var/mob/living/carbon/human/M in world) + if (M.client) + mobs += M + for(var/mob/living/carbon/human/M in mobs) + spawn() + if(M.client) + for(var/obj/item/weapon/W in list(M.wear_suit, M.w_uniform, M.r_store, M.l_store, M.wear_id, M.belt, + M.gloves, M.glasses, M.head, M.ears, M.shoes, M.wear_mask, M.back, + M.handcuffed, M.r_hand, M.l_hand)) + M.u_equip(W) + del(W) + + var/randomname = "Killiam Shakespeare" + if(commando_names.len) + randomname = pick(commando_names) + commando_names -= randomname + var/newname = input(M,"You are a death commando. Would you like to change your name?", "Character Creation", randomname) + if(!length(newname)) + newname = randomname + newname = strip_html(newname,40) + + M.real_name = newname + M.name = newname // there are WAY more things than this to change, I'm almost certain + + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/swat_suit/death_commando(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/death_commando(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/m_pill/cyanide(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/flashbang(M), slot_r_store) + + var/obj/item/weapon/tank/air/O = new(M) + M.equip_to_slot_or_del(O, slot_back) + M.internal = O + + var/obj/item/weapon/card/id/W = new(M) + W.access = get_all_accesses() + W.name = "[newname]'s ID card (Death Commando)" + W.assignment = "Death Commando" + W.registered_name = newname + M.equip_to_slot_or_del(W, slot_wear_id) + ..() + + check_win() + return 1 */ \ No newline at end of file diff --git a/code/unused/gamemodes/monkey.dm b/code/unused/gamemodes/monkey.dm index d7baaf1f735..d2e8dd7347e 100644 --- a/code/unused/gamemodes/monkey.dm +++ b/code/unused/gamemodes/monkey.dm @@ -1,131 +1,131 @@ -#define MONKEY_MODE_RUNNING 0 -#define MONKEY_MODE_NO_RABID_LEFT 1 -#define MONKEY_MODE_SHUTTLE_CAPTURED 2 -#define MONKEY_MODE_SHUTTLE_WITH_HUMANS 3 - -#define MONKEY_MODE_MONKEYS 4 - -/datum/game_mode/monkey - name = "monkey" - config_tag = "monkey" - var/state = MONKEY_MODE_RUNNING - var/list/datum/mind/initial_monkeys = new - -/datum/game_mode/monkey/announce() +#define MONKEY_MODE_RUNNING 0 +#define MONKEY_MODE_NO_RABID_LEFT 1 +#define MONKEY_MODE_SHUTTLE_CAPTURED 2 +#define MONKEY_MODE_SHUTTLE_WITH_HUMANS 3 + +#define MONKEY_MODE_MONKEYS 4 + +/datum/game_mode/monkey + name = "monkey" + config_tag = "monkey" + var/state = MONKEY_MODE_RUNNING + var/list/datum/mind/initial_monkeys = new + +/datum/game_mode/monkey/announce() to_chat(world, "The current game mode is - Monkey!") to_chat(world, "Some of your crew members have been infected by a mutageous virus!") to_chat(world, "Escape on the shuttle but the humans have precedence!") - -/datum/game_mode/monkey/can_start() - if (num_players()<2) - return 0 - for(var/mob/new_player/P in player_list) - if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) - return 1 - return 0 - -/datum/game_mode/monkey/pre_setup() - var/list/possible_monkeys = get_players_for_role(BE_MONKEY) - - // stop setup if no possible monkeys - if(!possible_monkeys.len) - return 0 - - var/num_monkeys = MONKEY_MODE_MONKEYS - var/num_players = num_players() - - if (num_players<=num_monkeys) - num_monkeys = round(num_players/2) - - for(var/j = 1 to num_monkeys) - if (!possible_monkeys.len) - break - var/datum/mind/monkey = pick(possible_monkeys) - possible_monkeys-=monkey - initial_monkeys += monkey - monkey.special_role = "monkey" - - if(!initial_monkeys.len) - return 0 - return 1 - -/datum/game_mode/monkey/post_setup() - spawn (50) - for (var/datum/mind/monkey in initial_monkeys) - var/mob/living/carbon/human/H = monkey.current - var/mob/living/carbon/monkey/new_monkey = H.monkeyize() + +/datum/game_mode/monkey/can_start() + if (num_players()<2) + return 0 + for(var/mob/new_player/P in player_list) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 + +/datum/game_mode/monkey/pre_setup() + var/list/possible_monkeys = get_players_for_role(BE_MONKEY) + + // stop setup if no possible monkeys + if(!possible_monkeys.len) + return 0 + + var/num_monkeys = MONKEY_MODE_MONKEYS + var/num_players = num_players() + + if (num_players<=num_monkeys) + num_monkeys = round(num_players/2) + + for(var/j = 1 to num_monkeys) + if (!possible_monkeys.len) + break + var/datum/mind/monkey = pick(possible_monkeys) + possible_monkeys-=monkey + initial_monkeys += monkey + monkey.special_role = "monkey" + + if(!initial_monkeys.len) + return 0 + return 1 + +/datum/game_mode/monkey/post_setup() + spawn (50) + for (var/datum/mind/monkey in initial_monkeys) + var/mob/living/carbon/human/H = monkey.current + var/mob/living/carbon/monkey/new_monkey = H.monkeyize() to_chat(new_monkey, "Your goal is to capture the entire human civilization and your first target is Centcom. Hijack the shuttle without humans aboard!") - - for (var/mob/living/carbon/monkey/rabid_monkey in mob_list) - if (!(rabid_monkey.mind in initial_monkeys) && (!isturf(rabid_monkey.loc) || rabid_monkey.z!=1)) - continue - rabid_monkey.contract_disease(new /datum/disease/jungle_fever,1,0) - del(initial_monkeys) - ..() - -/datum/game_mode/monkey/proc/is_important_monkey(var/mob/living/carbon/monkey/M as mob) - var/turf/T = get_turf(M) - var/area/A = get_area(M) - if(M.stat!=2) - - for(var/datum/disease/D in M.viruses) - if(istype(D, /datum/disease/jungle_fever) && ( T.z==1 || is_type_in_list(A, centcom_areas))) - return 1 - - -/datum/game_mode/monkey/check_win() - if (state==MONKEY_MODE_SHUTTLE_CAPTURED || state==MONKEY_MODE_SHUTTLE_WITH_HUMANS) - return - var/infected_count = 0 - for (var/mob/living/carbon/monkey/rabid_monkey in mob_list) - if (is_important_monkey(rabid_monkey)) - infected_count++ - if (infected_count==0) - state = MONKEY_MODE_NO_RABID_LEFT - -/datum/game_mode/monkey/check_finished() - return (emergency_shuttle.location==2) || (state>0) - -/datum/game_mode/monkey/declare_completion() - var/monkeywin = 0 - if (state != MONKEY_MODE_NO_RABID_LEFT) - for(var/mob/living/carbon/monkey/monkey_player in mob_list) - if (is_important_monkey(monkey_player)) - var/area/A = get_area(monkey_player) - if ( is_type_in_list(A, centcom_areas)) - monkeywin = 1 - break - - if(monkeywin) - for(var/mob/living/carbon/human/human_player in mob_list) - if (human_player.stat != 2) - var/area/A = get_area(human_player) - if (istype(A, /area/shuttle/escape/centcom)) - monkeywin = 0 - break - - if (monkeywin) - feedback_set_details("round_end_result","win - monkey win") + + for (var/mob/living/carbon/monkey/rabid_monkey in mob_list) + if (!(rabid_monkey.mind in initial_monkeys) && (!isturf(rabid_monkey.loc) || rabid_monkey.z!=1)) + continue + rabid_monkey.contract_disease(new /datum/disease/jungle_fever,1,0) + del(initial_monkeys) + ..() + +/datum/game_mode/monkey/proc/is_important_monkey(var/mob/living/carbon/monkey/M as mob) + var/turf/T = get_turf(M) + var/area/A = get_area(M) + if(M.stat!=2) + + for(var/datum/disease/D in M.viruses) + if(istype(D, /datum/disease/jungle_fever) && ( T.z==1 || is_type_in_list(A, centcom_areas))) + return 1 + + +/datum/game_mode/monkey/check_win() + if (state==MONKEY_MODE_SHUTTLE_CAPTURED || state==MONKEY_MODE_SHUTTLE_WITH_HUMANS) + return + var/infected_count = 0 + for (var/mob/living/carbon/monkey/rabid_monkey in mob_list) + if (is_important_monkey(rabid_monkey)) + infected_count++ + if (infected_count==0) + state = MONKEY_MODE_NO_RABID_LEFT + +/datum/game_mode/monkey/check_finished() + return (emergency_shuttle.location==2) || (state>0) + +/datum/game_mode/monkey/declare_completion() + var/monkeywin = 0 + if (state != MONKEY_MODE_NO_RABID_LEFT) + for(var/mob/living/carbon/monkey/monkey_player in mob_list) + if (is_important_monkey(monkey_player)) + var/area/A = get_area(monkey_player) + if ( is_type_in_list(A, centcom_areas)) + monkeywin = 1 + break + + if(monkeywin) + for(var/mob/living/carbon/human/human_player in mob_list) + if (human_player.stat != 2) + var/area/A = get_area(human_player) + if (istype(A, /area/shuttle/escape/centcom)) + monkeywin = 0 + break + + if (monkeywin) + feedback_set_details("round_end_result","win - monkey win") to_chat(world, "The monkeys have won! Humanity is doomed!") - for (var/mob/living/carbon/human/player in player_list) - spawn(rand(0,150)) - player.monkeyize() - sleep(200) - else - feedback_set_details("round_end_result","loss - crew win") + for (var/mob/living/carbon/human/player in player_list) + spawn(rand(0,150)) + player.monkeyize() + sleep(200) + else + feedback_set_details("round_end_result","loss - crew win") to_chat(world, "The Research Staff has stopped the monkey invasion!") - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_monkey() - for(var/mob/living/carbon/monkey/monkey_player in mob_list) - for(var/datum/disease/D in monkey_player.viruses) - if (istype(D, /datum/disease/jungle_fever) && monkey_player.ckey) + ..() + return 1 + + +/datum/game_mode/proc/auto_declare_completion_monkey() + for(var/mob/living/carbon/monkey/monkey_player in mob_list) + for(var/datum/disease/D in monkey_player.viruses) + if (istype(D, /datum/disease/jungle_fever) && monkey_player.ckey) to_chat(world, "[monkey_player.ckey] was played infested [monkey_player]. [monkey_player.stat == 2 ? "(DEAD)" : ""]") - return 1 - -#undef MONKEY_MODE_RUNNING -#undef MONKEY_MODE_NO_RABID_LEFT -#undef MONKEY_MODE_SHUTTLE_CAPTURED -#undef MONKEY_MODE_SHUTTLE_WITH_HUMANS + return 1 + +#undef MONKEY_MODE_RUNNING +#undef MONKEY_MODE_NO_RABID_LEFT +#undef MONKEY_MODE_SHUTTLE_CAPTURED +#undef MONKEY_MODE_SHUTTLE_WITH_HUMANS diff --git a/code/unused/gamemodes/restructuring.dm b/code/unused/gamemodes/restructuring.dm index dd9592843a7..332ec8e2963 100644 --- a/code/unused/gamemodes/restructuring.dm +++ b/code/unused/gamemodes/restructuring.dm @@ -1,77 +1,77 @@ -/datum/game_mode/restructuring - name = "Corporate Restructuring" - config_tag = "restructuring" -/* -/datum/game_mode/restructuring/announce() +/datum/game_mode/restructuring + name = "Corporate Restructuring" + config_tag = "restructuring" +/* +/datum/game_mode/restructuring/announce() to_chat(world, "GLOBAL TRANSMISSION FROM HEAD OFFICE: A CORPORATE RESTRUCTURING IS TO TAKE PLACE") to_chat(world, "Stay tuned for further news; note that we do care for our employees and any layoffs will be dealt with discretion and compassion") - - -/datum/game_mode/restructuring/post_setup() - setup_game() - var/list/mobs = get_mob_list() - while (mobs.len == 0) - sleep 30 - mobs = get_mob_list() - spawn (120) - pick_target() - ..() - -/datum/game_mode/restructuring/proc/pick_target(who) - var/mob/target - var/mob/target_desc - - if (!who) - target = pick(get_mob_list()) - target_desc = get_target_desc(target) + + +/datum/game_mode/restructuring/post_setup() + setup_game() + var/list/mobs = get_mob_list() + while (mobs.len == 0) + sleep 30 + mobs = get_mob_list() + spawn (120) + pick_target() + ..() + +/datum/game_mode/restructuring/proc/pick_target(who) + var/mob/target + var/mob/target_desc + + if (!who) + target = pick(get_mob_list()) + target_desc = get_target_desc(target) to_chat(world, "HEAD OFFICE: [target_desc] is accused of attempting to start a Union and is now considered a threat to the station. Terminate the employee immediately.") - else - target = who - target_desc = get_target_desc(target) + else + target = who + target_desc = get_target_desc(target) to_chat(world, "HEAD OFFICE: [target_desc] is accused of fornicating with staff of the same sex. Terminate the employee immediately.") - ticker.target = target - - target.store_memory("Head office has ordered your downsizing. Ruh roh", 0) - - for(var/mob/living/silicon/ai/M in world) + ticker.target = target + + target.store_memory("Head office has ordered your downsizing. Ruh roh", 0) + + for(var/mob/living/silicon/ai/M in world) to_chat(M, "These are your laws now:") - M.set_zeroth_law("[target_desc] is not human.") - M.show_laws() - -/datum/game_mode/restructuring/check_win() - var/list/left_alive = get_mob_list() - if (left_alive.len == 1) - var/thewinner = the_winner() + M.set_zeroth_law("[target_desc] is not human.") + M.show_laws() + +/datum/game_mode/restructuring/check_win() + var/list/left_alive = get_mob_list() + if (left_alive.len == 1) + var/thewinner = the_winner() to_chat(world, "HEAD OFFICE: Thanks to his superior brown-nosing abilities, [thewinner] has been promoted to senior management! Congratulations!") - return 1 - else if (left_alive.len == 0) + return 1 + else if (left_alive.len == 0) to_chat(world, "HEAD OFFICE: Cost cutting measures have achieved 100% efficiency. Thank you for understanding our position during this volatile economic downturn.") - return 1 - else - if(ticker.target.stat != 2) - return 0 + return 1 + else + if(ticker.target.stat != 2) + return 0 to_chat(world, "HEAD OFFICE: It seems we have made a mistake in our paperwork. The previous target for termination was chosen based on race, sex, and/or religious beliefs, which is against company policy. Please cancel previous termination request.") - pick_target() - return 0 - -/datum/game_mode/restructuring/proc/get_mob_list() - var/list/mobs = list() - for(var/mob/M in world) - if (M.stat<2 && M.client && istype(M, /mob/living/carbon/human)) - mobs += M - return mobs - -/datum/game_mode/restructuring/proc/the_winner() - for(var/mob/M in world) - if (M.stat<2 && M.client && istype(M, /mob/living/carbon/human)) - return M.name - -/datum/game_mode/restructuring/proc/get_target_desc(mob/target) //return a useful string describing the target - var/targetrank = null - for(var/datum/data/record/R in data_core.general) - if (R.fields["name"] == target.real_name) - targetrank = R.fields["rank"] - if(!targetrank) - return "[target.name]" - return "[target.name] the [targetrank]" + pick_target() + return 0 + +/datum/game_mode/restructuring/proc/get_mob_list() + var/list/mobs = list() + for(var/mob/M in world) + if (M.stat<2 && M.client && istype(M, /mob/living/carbon/human)) + mobs += M + return mobs + +/datum/game_mode/restructuring/proc/the_winner() + for(var/mob/M in world) + if (M.stat<2 && M.client && istype(M, /mob/living/carbon/human)) + return M.name + +/datum/game_mode/restructuring/proc/get_target_desc(mob/target) //return a useful string describing the target + var/targetrank = null + for(var/datum/data/record/R in data_core.general) + if (R.fields["name"] == target.real_name) + targetrank = R.fields["rank"] + if(!targetrank) + return "[target.name]" + return "[target.name] the [targetrank]" */ \ No newline at end of file diff --git a/code/unused/gamemodes/ruby.dm b/code/unused/gamemodes/ruby.dm index 515e62c9a0d..58cb017db45 100644 --- a/code/unused/gamemodes/ruby.dm +++ b/code/unused/gamemodes/ruby.dm @@ -1,290 +1,290 @@ -// RUBY MODE -// There is a weapon of some sort that spawns on the station -// It calls out to crew members in an effort to find a wielder -// The wielder is made an abomination - they're given a grotesque mask and special powers -// The Abomination wins by murdering the entire crew, then himself -// The crew wins by destroying the weapon - - -/datum/game_mode/ruby - name = "ruby" - config_tag = "ruby" - - var/datum/mind/abomination - var/finished = 0 - var/abominationwins = 0 - var/winnerkey - var/obj/macguffin - var/list/killed = list() - var/respawns = 0 - - - -/datum/game_mode/ruby/post_setup() - var/list/possible_abominations = get_possible_abominations() - - if(possible_abominations.len>0) - abomination = pick(possible_abominations) - /* - if(istype(ruby)) - abomination.special_role = "abomination" - if(wizardstart.len == 0) +// RUBY MODE +// There is a weapon of some sort that spawns on the station +// It calls out to crew members in an effort to find a wielder +// The wielder is made an abomination - they're given a grotesque mask and special powers +// The Abomination wins by murdering the entire crew, then himself +// The crew wins by destroying the weapon + + +/datum/game_mode/ruby + name = "ruby" + config_tag = "ruby" + + var/datum/mind/abomination + var/finished = 0 + var/abominationwins = 0 + var/winnerkey + var/obj/macguffin + var/list/killed = list() + var/respawns = 0 + + + +/datum/game_mode/ruby/post_setup() + var/list/possible_abominations = get_possible_abominations() + + if(possible_abominations.len>0) + abomination = pick(possible_abominations) + /* + if(istype(ruby)) + abomination.special_role = "abomination" + if(wizardstart.len == 0) to_chat(wizard.current, "A starting location for you could not be found, please report this bug!") - else - var/starting_loc = pick(wizardstart) - wizard.current.loc = starting_loc - - for (var/obj/effect/landmark/A in world) - if (A.name == "Teleport-Scroll") - new /obj/item/weapon/teleportation_scroll(A.loc) - del(A) - continue - */ - ..() - -/datum/game_mode/ruby/check_finished() - if(!macguffin || abominationwins) - return 1 - else - return 0 - -/datum/game_mode/ruby/declare_completion() - if(abominationwins) - feedback_set_details("round_end_result","win - abomination win") + else + var/starting_loc = pick(wizardstart) + wizard.current.loc = starting_loc + + for (var/obj/effect/landmark/A in world) + if (A.name == "Teleport-Scroll") + new /obj/item/weapon/teleportation_scroll(A.loc) + del(A) + continue + */ + ..() + +/datum/game_mode/ruby/check_finished() + if(!macguffin || abominationwins) + return 1 + else + return 0 + +/datum/game_mode/ruby/declare_completion() + if(abominationwins) + feedback_set_details("round_end_result","win - abomination win") to_chat(world, "The Abomination has murdered the station and sacrificed himself to Cjopaze! (played by [winnerkey])") - else - feedback_set_details("round_end_result","loss - abomination killed") + else + feedback_set_details("round_end_result","loss - abomination killed") to_chat(world, "The Abomination has been stopped and Cjopaze's influence resisted! The station lives another day,") - if(killed.len > 0) + if(killed.len > 0) to_chat(world, "Those who were sacrificed shall be remembered: ") - for(var/mob/M in killed) - if(M) + for(var/mob/M in killed) + if(M) to_chat(world, "[M.real_name]") - /* - for(var/datum/mind/traitor in traitors) - var/traitorwin = 1 - var/traitor_name - - if(traitor.current) - traitor_name = "[traitor.current.real_name] (played by [traitor.key])" - else - traitor_name = "[traitor.key] (character destroyed)" - + /* + for(var/datum/mind/traitor in traitors) + var/traitorwin = 1 + var/traitor_name + + if(traitor.current) + traitor_name = "[traitor.current.real_name] (played by [traitor.key])" + else + traitor_name = "[traitor.key] (character destroyed)" + to_chat(world, "The syndicate traitor was [traitor_name]") - var/count = 1 - for(var/datum/objective/objective in traitor.objectives) - if(objective.check_completion()) + var/count = 1 + for(var/datum/objective/objective in traitor.objectives) + if(objective.check_completion()) to_chat(world, "Objective #[count]: [objective.explanation_text] Success") - else + else to_chat(world, "Objective #[count]: [objective.explanation_text] Failed") - traitorwin = 0 - count++ - - if(traitorwin) + traitorwin = 0 + count++ + + if(traitorwin) to_chat(world, "The traitor was successful!") - else + else to_chat(world, "The traitor has failed!") - */ - ..() - return 1 - - -/datum/game_mode/ruby/proc/spawn_macguffin() - -/datum/game_mode/ruby/proc/get_possible_abominations() - - - -/mob/proc/make_abomination() - src.see_in_dark = 20 - src.verbs += /client/proc/planar_shift - src.verbs += /client/proc/vile_ressurection - src.verbs += /client/proc/defile_corpse - src.verbs += /client/proc/summon_weapon - src.verbs += /client/proc/sacrifice_self - src.verbs += /client/proc/hunt - src.verbs += /client/proc/howl - var/datum/game_mode/ruby/rmode = ticker.mode - rmode.abomination = src.mind - return - - -/client/proc/planar_shift() - set name = "Planar Shift" - set category = "Abomination" - // This is a pretty shitty way to do this. Should use the spell_holder method from Wizard mode - /* - if(!usr.incorporeal_move) - usr.sight |= SEE_MOBS - usr.sight |= SEE_OBJS - usr.sight |= SEE_TURFS - //usr.density = 0 - usr.incorporeal_move = INCORPOREAL_GHOST - else - usr.sight &= ~SEE_MOBS - usr.sight &= ~SEE_TURFS - usr.sight &= ~SEE_OBJS - usr.density = 1 - usr.incorporeal_move = INCORPOREAL_DEACTIVATE - src.verbs -= /client/proc/planar_shift - spawn(300) src.verbs += /client/proc/planar_shift - */ - -/client/proc/vile_ressurection() - set name = "Vile Ressurection" - set category = "Abomination" - if(src.mob.stat != 2 || !src.mob) - return - if(ticker.mode:respawns > 0) - // spawn a new body - ticker.mode:respawns -= 1 - else - // nope - -/client/proc/defile_corpse(var/mob/living/carbon/human/H in view()) - set name = "Defile Corpse" - set category = "Abomination" - if(istype(H, /mob/living/carbon/human)) - var/datum/game_mode/ruby/rmode = ticker.mode - rmode.killed.Add(H) - ticker.mode:respawns += 1 - var/fluffmessage = pick("[usr] rips the flesh from [H]'s corpse and plucks their eyes from their sockets!", "[usr] does unspeakable things to [H]'s corpse!", "[usr] binds [H]'s corpse with their own entrails!") - usr.visible_message(fluffmessage) - // play sound - -/client/proc/summon_weapon() - set name = "Summon Weapon" - set category = "Abomination" - - for(var/obj/item/weapon/rubyweapon/w in world) - if(istype(w, /obj/item/weapon/rubyweapon)) - if(istype(w.loc, /mob)) - var/mob/M = w.loc - M.drop_item() - w.loc = usr.loc - else - w.loc = usr.loc - src.verbs -= /client/proc/summon_weapon - spawn(300) src.verbs += /client/proc/summon_weapon - return - -/client/proc/sacrifice_self() - set name = "Sacrifice Self" - set category = "Abomination" - set desc = "Everything must come to an end. After you have freed them, you must free yourself." - - for(var/mob/living/carbon/human/H in player_list) - if(!H.client || H.client == src) - continue + */ + ..() + return 1 + + +/datum/game_mode/ruby/proc/spawn_macguffin() + +/datum/game_mode/ruby/proc/get_possible_abominations() + + + +/mob/proc/make_abomination() + src.see_in_dark = 20 + src.verbs += /client/proc/planar_shift + src.verbs += /client/proc/vile_ressurection + src.verbs += /client/proc/defile_corpse + src.verbs += /client/proc/summon_weapon + src.verbs += /client/proc/sacrifice_self + src.verbs += /client/proc/hunt + src.verbs += /client/proc/howl + var/datum/game_mode/ruby/rmode = ticker.mode + rmode.abomination = src.mind + return + + +/client/proc/planar_shift() + set name = "Planar Shift" + set category = "Abomination" + // This is a pretty shitty way to do this. Should use the spell_holder method from Wizard mode + /* + if(!usr.incorporeal_move) + usr.sight |= SEE_MOBS + usr.sight |= SEE_OBJS + usr.sight |= SEE_TURFS + //usr.density = 0 + usr.incorporeal_move = INCORPOREAL_GHOST + else + usr.sight &= ~SEE_MOBS + usr.sight &= ~SEE_TURFS + usr.sight &= ~SEE_OBJS + usr.density = 1 + usr.incorporeal_move = INCORPOREAL_DEACTIVATE + src.verbs -= /client/proc/planar_shift + spawn(300) src.verbs += /client/proc/planar_shift + */ + +/client/proc/vile_ressurection() + set name = "Vile Ressurection" + set category = "Abomination" + if(src.mob.stat != 2 || !src.mob) + return + if(ticker.mode:respawns > 0) + // spawn a new body + ticker.mode:respawns -= 1 + else + // nope + +/client/proc/defile_corpse(var/mob/living/carbon/human/H in view()) + set name = "Defile Corpse" + set category = "Abomination" + if(istype(H, /mob/living/carbon/human)) + var/datum/game_mode/ruby/rmode = ticker.mode + rmode.killed.Add(H) + ticker.mode:respawns += 1 + var/fluffmessage = pick("[usr] rips the flesh from [H]'s corpse and plucks their eyes from their sockets!", "[usr] does unspeakable things to [H]'s corpse!", "[usr] binds [H]'s corpse with their own entrails!") + usr.visible_message(fluffmessage) + // play sound + +/client/proc/summon_weapon() + set name = "Summon Weapon" + set category = "Abomination" + + for(var/obj/item/weapon/rubyweapon/w in world) + if(istype(w, /obj/item/weapon/rubyweapon)) + if(istype(w.loc, /mob)) + var/mob/M = w.loc + M.drop_item() + w.loc = usr.loc + else + w.loc = usr.loc + src.verbs -= /client/proc/summon_weapon + spawn(300) src.verbs += /client/proc/summon_weapon + return + +/client/proc/sacrifice_self() + set name = "Sacrifice Self" + set category = "Abomination" + set desc = "Everything must come to an end. After you have freed them, you must free yourself." + + for(var/mob/living/carbon/human/H in player_list) + if(!H.client || H.client == src) + continue to_chat(src, "Your work is not done. You will not find release until they are all free.") - return - usr.gib(1) - ticker.mode:abominationwins = 1 - -/client/proc/hunt() - set name = "Hunt" - set category = "Abomination" - set desc = "" - - var/list/candidates = list() - - for(var/mob/living/carbon/human/H in player_list) - if(!H.client || H.client == src) continue - //if(!H.client) continue - candidates.Add(H) - - usr.visible_message(text("[usr]'s flesh ripples and parts, revealing dozens of eyes poking from its surface. They all glance wildly around for a few moments before receding again.")) - - var/mob/living/carbon/human/H = pick(candidates) - - if(!H) return - - var/filename="crmap[ckey].tmp" - var/html="" - var/denytypes[0] - var/tilesizex=32 - var/tilesizey=32 - //If the temp. file exists, delete it - src << browse("

    Sensing prey...

    ", "window=hunt") - if (fexists(filename)) fdel(filename) - - //Display everything in the world - for (var/y=H.y-3,y<=H.y+3,y++) - html+="" - text2file(html,filename) - html="" - sleep(-1) - //for (var/x=H.x-5,x<=H.x+5,x++) - for(var/x=H.x-3, x<=H.x+3, x++) - //Turfs - var/turf/T=locate(x,y,H.z) - if (!T) continue - var/icon/I=icon(T.icon,T.icon_state) - var/imgstring=replacetext("[T.type]-[T.icon_state]","/","_") - - //Movable atoms - for (var/atom/movable/A in T) - //Make sure it's allowed to be displayed - var/allowed=1 - for (var/X in denytypes) - if (istype(A,X)) - allowed=0 - break - if (!allowed) continue - - if (A.icon) I.Blend(icon(A.icon,A.icon_state,A.dir),ICON_OVERLAY) - imgstring+=replacetext("__[A.type]_[A.icon_state]","/","_") - - //Output it - src << browse_rsc(I,"[imgstring].dmi") - html+="" - - text2file("
    ",filename) - - //Display it - src << browse(file(filename),"window=hunt") - - - -/client/proc/howl() // This is just a way for the Abomination to make the game more atmospheric periodically. - set name = "Howl" - set category = "Abomination" - set desc = "" - - usr.visible_message(text("[usr]'s form warbles and distorts before settling back into its grotesque shape once more.")) - // Play a random spooky sound - maybe cause some visual, non-mechanical effects to appear at random for a few seconds. - - src.verbs -= /client/proc/howl - spawn(rand(300,1800)) src.verbs += /client/proc/howl - -/obj/item/weapon/rubyweapon - desc = "" - name = "wepon" - icon_state = "wepon" - w_class = 3.0 - throwforce = 60.0 - throw_speed = 2 - throw_range = 20 - force = 24.0 - var/mob/owner - - proc/check_owner() - if(!owner) - sleep(300) - if(!owner) - spawn() search_for_new_owner() - else - spawn(1800) check_owner() - - proc/search_for_new_owner() - var/list/possible_owners = list() - for(var/mob/living/carbon/human/H in mob_list) - possible_owners.Add(H) - - var/mob/living/carbon/human/H = pick(possible_owners) - // Send message to H - // Take a snapshot of the item's location, browse it to H - spawn(rand(600,1800)) search_for_new_owner() - - attack_self(mob/user as mob) + return + usr.gib(1) + ticker.mode:abominationwins = 1 + +/client/proc/hunt() + set name = "Hunt" + set category = "Abomination" + set desc = "" + + var/list/candidates = list() + + for(var/mob/living/carbon/human/H in player_list) + if(!H.client || H.client == src) continue + //if(!H.client) continue + candidates.Add(H) + + usr.visible_message(text("[usr]'s flesh ripples and parts, revealing dozens of eyes poking from its surface. They all glance wildly around for a few moments before receding again.")) + + var/mob/living/carbon/human/H = pick(candidates) + + if(!H) return + + var/filename="crmap[ckey].tmp" + var/html="" + var/denytypes[0] + var/tilesizex=32 + var/tilesizey=32 + //If the temp. file exists, delete it + src << browse("

    Sensing prey...

    ", "window=hunt") + if (fexists(filename)) fdel(filename) + + //Display everything in the world + for (var/y=H.y-3,y<=H.y+3,y++) + html+="" + text2file(html,filename) + html="" + sleep(-1) + //for (var/x=H.x-5,x<=H.x+5,x++) + for(var/x=H.x-3, x<=H.x+3, x++) + //Turfs + var/turf/T=locate(x,y,H.z) + if (!T) continue + var/icon/I=icon(T.icon,T.icon_state) + var/imgstring=replacetext("[T.type]-[T.icon_state]","/","_") + + //Movable atoms + for (var/atom/movable/A in T) + //Make sure it's allowed to be displayed + var/allowed=1 + for (var/X in denytypes) + if (istype(A,X)) + allowed=0 + break + if (!allowed) continue + + if (A.icon) I.Blend(icon(A.icon,A.icon_state,A.dir),ICON_OVERLAY) + imgstring+=replacetext("__[A.type]_[A.icon_state]","/","_") + + //Output it + src << browse_rsc(I,"[imgstring].dmi") + html+="" + + text2file("
    ",filename) + + //Display it + src << browse(file(filename),"window=hunt") + + + +/client/proc/howl() // This is just a way for the Abomination to make the game more atmospheric periodically. + set name = "Howl" + set category = "Abomination" + set desc = "" + + usr.visible_message(text("[usr]'s form warbles and distorts before settling back into its grotesque shape once more.")) + // Play a random spooky sound - maybe cause some visual, non-mechanical effects to appear at random for a few seconds. + + src.verbs -= /client/proc/howl + spawn(rand(300,1800)) src.verbs += /client/proc/howl + +/obj/item/weapon/rubyweapon + desc = "" + name = "wepon" + icon_state = "wepon" + w_class = 3.0 + throwforce = 60.0 + throw_speed = 2 + throw_range = 20 + force = 24.0 + var/mob/owner + + proc/check_owner() + if(!owner) + sleep(300) + if(!owner) + spawn() search_for_new_owner() + else + spawn(1800) check_owner() + + proc/search_for_new_owner() + var/list/possible_owners = list() + for(var/mob/living/carbon/human/H in mob_list) + possible_owners.Add(H) + + var/mob/living/carbon/human/H = pick(possible_owners) + // Send message to H + // Take a snapshot of the item's location, browse it to H + spawn(rand(600,1800)) search_for_new_owner() + + attack_self(mob/user as mob) // Blow all lights nearby \ No newline at end of file diff --git a/code/unused/hivebot/death.dm b/code/unused/hivebot/death.dm index 43e7c257a53..7201151ee96 100644 --- a/code/unused/hivebot/death.dm +++ b/code/unused/hivebot/death.dm @@ -1,24 +1,24 @@ -/mob/living/silicon/hivebot/death(gibbed) - if(src.mainframe) - src.mainframe.return_to(src) - src.stat = 2 - src.canmove = 0 - - if(src.blind) - src.blind.layer = 0 - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.sight |= SEE_OBJS - - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - src.updateicon() - - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch - store_memory("Time of death: [tod]", 0) - - if (src.key) - spawn(50) - if(src.key && src.stat == 2) - src.verbs += /client/proc/ghost +/mob/living/silicon/hivebot/death(gibbed) + if(src.mainframe) + src.mainframe.return_to(src) + src.stat = 2 + src.canmove = 0 + + if(src.blind) + src.blind.layer = 0 + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + src.updateicon() + + var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + store_memory("Time of death: [tod]", 0) + + if (src.key) + spawn(50) + if(src.key && src.stat == 2) + src.verbs += /client/proc/ghost return ..(gibbed) \ No newline at end of file diff --git a/code/unused/hivebot/emote.dm b/code/unused/hivebot/emote.dm index 1d1b58168cc..e28e577e17e 100644 --- a/code/unused/hivebot/emote.dm +++ b/code/unused/hivebot/emote.dm @@ -1,141 +1,141 @@ -/mob/living/silicon/hivebot/emote(var/act) - if(timestopped) return //under effects of time magick - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - var/m_type = 1 - var/message - - switch(act) - if ("salute") - if (!src.buckled) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] salutes to [param]." - else - message = "[src] salutes." - m_type = 1 - if ("bow") - if (!src.buckled) - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] bows to [param]." - else - message = "[src] bows." - m_type = 1 - - if ("clap") - if (!src.restrained()) - message = "[src] claps." - m_type = 2 - if ("flap") - if (!src.restrained()) - message = "[src] flaps his wings." - m_type = 2 - - if ("aflap") - if (!src.restrained()) - message = "[src] flaps his wings ANGRILY!" - m_type = 2 - - if ("custom") - var/input = input("Choose an emote to display.") as text|null - if (!input) - return - input = sanitize(input) - var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") - if (input2 == "Visible") - m_type = 1 - else if (input2 == "Hearable") - m_type = 2 - else - alert("Unable to use this emote, must be either hearable or visible.") - return - message = "[src] [input]" - - if ("twitch") - message = "[src] twitches violently." - m_type = 1 - - if ("twitch_s") - message = "[src] twitches." - m_type = 1 - - if ("nod") - message = "[src] nods." - m_type = 1 - - if ("glare") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] glares at [param]." - else - message = "[src] glares." - - if ("stare") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - if (!M) - param = null - - if (param) - message = "[src] stares at [param]." - else - message = "[src] stares." - - if ("look") - var/M = null - if (param) - for (var/mob/A in view(null, null)) - if (param == A.name) - M = A - break - - if (!M) - param = null - - if (param) - message = "[src] looks at [param]." - else - message = "[src] looks." - m_type = 1 - else +/mob/living/silicon/hivebot/emote(var/act) + if(timestopped) return //under effects of time magick + var/param = null + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + var/m_type = 1 + var/message + + switch(act) + if ("salute") + if (!src.buckled) + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] salutes to [param]." + else + message = "[src] salutes." + m_type = 1 + if ("bow") + if (!src.buckled) + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] bows to [param]." + else + message = "[src] bows." + m_type = 1 + + if ("clap") + if (!src.restrained()) + message = "[src] claps." + m_type = 2 + if ("flap") + if (!src.restrained()) + message = "[src] flaps his wings." + m_type = 2 + + if ("aflap") + if (!src.restrained()) + message = "[src] flaps his wings ANGRILY!" + m_type = 2 + + if ("custom") + var/input = input("Choose an emote to display.") as text|null + if (!input) + return + input = sanitize(input) + var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") + if (input2 == "Visible") + m_type = 1 + else if (input2 == "Hearable") + m_type = 2 + else + alert("Unable to use this emote, must be either hearable or visible.") + return + message = "[src] [input]" + + if ("twitch") + message = "[src] twitches violently." + m_type = 1 + + if ("twitch_s") + message = "[src] twitches." + m_type = 1 + + if ("nod") + message = "[src] nods." + m_type = 1 + + if ("glare") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] glares at [param]." + else + message = "[src] glares." + + if ("stare") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + if (!M) + param = null + + if (param) + message = "[src] stares at [param]." + else + message = "[src] stares." + + if ("look") + var/M = null + if (param) + for (var/mob/A in view(null, null)) + if (param == A.name) + M = A + break + + if (!M) + param = null + + if (param) + message = "[src] looks at [param]." + else + message = "[src] looks." + m_type = 1 + else // to_chat(custom_emote(VISIBLE, act)src, text("Invalid Emote: []", act)) - if ((message && src.stat == 0)) - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) + if ((message && src.stat == 0)) + if (m_type & 1) + for(var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + else + for(var/mob/O in hearers(src, null)) + O.show_message(message, m_type) return \ No newline at end of file diff --git a/code/unused/hivebot/examine.dm b/code/unused/hivebot/examine.dm index 398a2e1df85..2db3f41576c 100644 --- a/code/unused/hivebot/examine.dm +++ b/code/unused/hivebot/examine.dm @@ -1,17 +1,17 @@ -/mob/living/silicon/hivebot/examine(mob/user) +/mob/living/silicon/hivebot/examine(mob/user) to_chat(user, "*---------*") to_chat(user, text("This is \icon[src] [src.name]!")) - if (src.stat == 2) + if (src.stat == 2) to_chat(user, text("[src.name] is powered-down.")) - if (src.getBruteLoss()) - if (src.getBruteLoss() < 75) + if (src.getBruteLoss()) + if (src.getBruteLoss() < 75) to_chat(user, text("[src.name] looks slightly dented")) - else + else to_chat(user, text("[src.name] looks severely dented!")) - if (src.getFireLoss()) - if (src.getFireLoss() < 75) + if (src.getFireLoss()) + if (src.getFireLoss() < 75) to_chat(user, text("[src.name] looks slightly burnt!")) - else + else to_chat(user, text("[src.name] looks severely burnt!")) - if (src.stat == 1) + if (src.stat == 1) to_chat(user, text("[src.name] doesn't seem to be responding.")) diff --git a/code/unused/hivebot/hive_modules.dm b/code/unused/hivebot/hive_modules.dm index cb263a192d1..ea34ed0ac62 100644 --- a/code/unused/hivebot/hive_modules.dm +++ b/code/unused/hivebot/hive_modules.dm @@ -1,57 +1,57 @@ -/obj/item/weapon/hive_module - name = "hive robot module" - icon = 'icons/obj/module.dmi' - icon_state = "std_module" - w_class = 2.0 - item_state = "electronic" - flags = FPRINT|TABLEPASS | CONDUCT - var/list/modules = list() - -/obj/item/weapon/hive_module/standard - name = "give standard robot module" - -/obj/item/weapon/hive_module/engineering - name = "HiveBot engineering robot module" - -/obj/item/weapon/hive_module/New()//Shit all the mods have - src.modules += new /obj/item/device/flash(src) - - -/obj/item/weapon/hive_module/standard/New() - ..() - src.modules += new /obj/item/weapon/melee/baton(src) - src.modules += new /obj/item/weapon/extinguisher(src) - //var/obj/item/weapon/gun/mp5/M = new /obj/item/weapon/gun/mp5(src) - //M.weapon_lock = 0 - //src.modules += M - - -/obj/item/weapon/hive_module/engineering/New() - - src.modules += new /obj/item/weapon/extinguisher(src) - src.modules += new /obj/item/weapon/screwdriver(src) - src.modules += new /obj/item/weapon/weldingtool(src) - src.modules += new /obj/item/weapon/wrench(src) - src.modules += new /obj/item/device/analyzer(src) - src.modules += new /obj/item/device/flashlight(src) - - var/obj/item/weapon/rcd/R = new /obj/item/weapon/rcd(src) - R.matter = 30 - src.modules += R - - src.modules += new /obj/item/device/t_scanner(src) - src.modules += new /obj/item/weapon/crowbar(src) - src.modules += new /obj/item/weapon/wirecutters(src) - src.modules += new /obj/item/device/multitool(src) - - var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(src) - M.amount = 50 - src.modules += M - - var/obj/item/stack/sheet/glass/rglass/G = new /obj/item/stack/sheet/glass/rglass(src) - G.amount = 50 - src.modules += G - - var/obj/item/weapon/cable_coil/W = new /obj/item/weapon/cable_coil(src) - W.amount = 50 - src.modules += W +/obj/item/weapon/hive_module + name = "hive robot module" + icon = 'icons/obj/module.dmi' + icon_state = "std_module" + w_class = 2.0 + item_state = "electronic" + flags = FPRINT|TABLEPASS | CONDUCT + var/list/modules = list() + +/obj/item/weapon/hive_module/standard + name = "give standard robot module" + +/obj/item/weapon/hive_module/engineering + name = "HiveBot engineering robot module" + +/obj/item/weapon/hive_module/New()//Shit all the mods have + src.modules += new /obj/item/device/flash(src) + + +/obj/item/weapon/hive_module/standard/New() + ..() + src.modules += new /obj/item/weapon/melee/baton(src) + src.modules += new /obj/item/weapon/extinguisher(src) + //var/obj/item/weapon/gun/mp5/M = new /obj/item/weapon/gun/mp5(src) + //M.weapon_lock = 0 + //src.modules += M + + +/obj/item/weapon/hive_module/engineering/New() + + src.modules += new /obj/item/weapon/extinguisher(src) + src.modules += new /obj/item/weapon/screwdriver(src) + src.modules += new /obj/item/weapon/weldingtool(src) + src.modules += new /obj/item/weapon/wrench(src) + src.modules += new /obj/item/device/analyzer(src) + src.modules += new /obj/item/device/flashlight(src) + + var/obj/item/weapon/rcd/R = new /obj/item/weapon/rcd(src) + R.matter = 30 + src.modules += R + + src.modules += new /obj/item/device/t_scanner(src) + src.modules += new /obj/item/weapon/crowbar(src) + src.modules += new /obj/item/weapon/wirecutters(src) + src.modules += new /obj/item/device/multitool(src) + + var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(src) + M.amount = 50 + src.modules += M + + var/obj/item/stack/sheet/glass/rglass/G = new /obj/item/stack/sheet/glass/rglass(src) + G.amount = 50 + src.modules += G + + var/obj/item/weapon/cable_coil/W = new /obj/item/weapon/cable_coil(src) + W.amount = 50 + src.modules += W diff --git a/code/unused/hivebot/hivebot.dm b/code/unused/hivebot/hivebot.dm index 9adfa294a54..286a3bcc746 100644 --- a/code/unused/hivebot/hivebot.dm +++ b/code/unused/hivebot/hivebot.dm @@ -1,501 +1,501 @@ -/mob/living/silicon/hivebot/New(loc,mainframe) +/mob/living/silicon/hivebot/New(loc,mainframe) to_chat(src, "Your icons have been generated!") - updateicon() - - if(mainframe) - dependent = 1 - src.real_name = mainframe:name - src.name = src.real_name - else - src.real_name = "Robot [pick(rand(1, 999))]" - src.name = src.real_name - - src.radio = new /obj/item/device/radio(src) - ..() - - -/mob/living/silicon/hivebot/proc/pick_module() - if(src.module) - return - var/mod = input("Please, select a module!", "Robot", null, null) as null|anything in list("Combat", "Engineering") - if(src.module || !mod) - return - switch(mod) - if("Combat") - src.module = new /obj/item/weapon/hive_module/standard(src) - - if("Engineering") - src.module = new /obj/item/weapon/hive_module/engineering(src) - - - src.hands.icon_state = "malf" - updateicon() - - -/mob/living/silicon/hivebot/blob_act() - if (src.stat != 2) - src.adjustBruteLoss(60) - src.updatehealth() - return 1 - return 0 - -/mob/living/silicon/hivebot/Stat() - ..() - - if(statpanel("Status")) - if(emergency_shuttle.online && emergency_shuttle.location < 2) - var/timeleft = emergency_shuttle.timeleft() - if (timeleft) - stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") - - stat(null, text("Charge Left: [src.energy]/[src.energy_max]")) - -/mob/living/silicon/hivebot/restrained() - return 0 - -/mob/living/silicon/hivebot/ex_act(severity) - if(!blinded) - flick("flash", src.flash) - - if (src.stat == 2 && src.client) - src.gib(1) - return - - else if (src.stat == 2 && !src.client) - del(src) - return - - switch(severity) - if(1.0) - if (src.stat != 2) - adjustBruteLoss(100) - adjustFireLoss(100) - src.gib(1) - return - if(2.0) - if (src.stat != 2) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3.0) - if (src.stat != 2) - adjustBruteLoss(30) - - src.updatehealth() - -/mob/living/silicon/hivebot/meteorhit(obj/O as obj) - for(var/mob/M in viewers(src, null)) - M.show_message(text("[src] has been hit by [O]"), 1) - //Foreach goto(19) - if (src.health > 0) - src.adjustBruteLoss(30) - if ((O.icon_state == "flaming")) - src.adjustFireLoss(40) - src.updatehealth() - return - -/mob/living/silicon/hivebot/bullet_act(flag) -/* - if (flag == PROJECTILE_BULLET) - if (src.stat != 2) - src.bruteloss += 60 - src.updatehealth() - - else if (flag == PROJECTILE_MEDBULLET) - if (src.stat != 2) - src.bruteloss += 30 - src.updatehealth() - - else if (flag == PROJECTILE_WEAKBULLET) - if (src.stat != 2) - src.bruteloss += 15 - src.updatehealth() - - else if (flag == PROJECTILE_MPBULLET) - if (src.stat != 2) - src.bruteloss += 20 - src.updatehealth() - - else if (flag == PROJECTILE_SLUG) - if (src.stat != 2) - src.bruteloss += 40 - src.updatehealth() - - else if (flag == PROJECTILE_BAG) - if (src.stat != 2) - src.bruteloss += 2 - src.updatehealth() - - - else if (flag == PROJECTILE_TASER) - return - - else if (flag == PROJECTILE_WAVE) - if (src.stat != 2) - src.bruteloss += 25 - src.updatehealth() - return - - else if(flag == PROJECTILE_LASER) - if (src.stat != 2) - src.bruteloss += 20 - src.updatehealth() - else if(flag == PROJECTILE_PULSE) - if (src.stat != 2) - src.bruteloss += 40 - src.updatehealth() -*/ - return - - - -/mob/living/silicon/hivebot/Bump(atom/movable/AM as mob|obj, yes) - spawn( 0 ) - if ((!( yes ) || src.now_pushing)) - return - src.now_pushing = 1 - if(ismob(AM)) - var/mob/tmob = AM - /*if(istype(tmob, /mob/living/carbon/human) && (M_FAT in tmob.mutations)) - if(prob(20)) - for(var/mob/M in viewers(src, null)) - if(M.client) + updateicon() + + if(mainframe) + dependent = 1 + src.real_name = mainframe:name + src.name = src.real_name + else + src.real_name = "Robot [pick(rand(1, 999))]" + src.name = src.real_name + + src.radio = new /obj/item/device/radio(src) + ..() + + +/mob/living/silicon/hivebot/proc/pick_module() + if(src.module) + return + var/mod = input("Please, select a module!", "Robot", null, null) as null|anything in list("Combat", "Engineering") + if(src.module || !mod) + return + switch(mod) + if("Combat") + src.module = new /obj/item/weapon/hive_module/standard(src) + + if("Engineering") + src.module = new /obj/item/weapon/hive_module/engineering(src) + + + src.hands.icon_state = "malf" + updateicon() + + +/mob/living/silicon/hivebot/blob_act() + if (src.stat != 2) + src.adjustBruteLoss(60) + src.updatehealth() + return 1 + return 0 + +/mob/living/silicon/hivebot/Stat() + ..() + + if(statpanel("Status")) + if(emergency_shuttle.online && emergency_shuttle.location < 2) + var/timeleft = emergency_shuttle.timeleft() + if (timeleft) + stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") + + stat(null, text("Charge Left: [src.energy]/[src.energy_max]")) + +/mob/living/silicon/hivebot/restrained() + return 0 + +/mob/living/silicon/hivebot/ex_act(severity) + if(!blinded) + flick("flash", src.flash) + + if (src.stat == 2 && src.client) + src.gib(1) + return + + else if (src.stat == 2 && !src.client) + del(src) + return + + switch(severity) + if(1.0) + if (src.stat != 2) + adjustBruteLoss(100) + adjustFireLoss(100) + src.gib(1) + return + if(2.0) + if (src.stat != 2) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + if (src.stat != 2) + adjustBruteLoss(30) + + src.updatehealth() + +/mob/living/silicon/hivebot/meteorhit(obj/O as obj) + for(var/mob/M in viewers(src, null)) + M.show_message(text("[src] has been hit by [O]"), 1) + //Foreach goto(19) + if (src.health > 0) + src.adjustBruteLoss(30) + if ((O.icon_state == "flaming")) + src.adjustFireLoss(40) + src.updatehealth() + return + +/mob/living/silicon/hivebot/bullet_act(flag) +/* + if (flag == PROJECTILE_BULLET) + if (src.stat != 2) + src.bruteloss += 60 + src.updatehealth() + + else if (flag == PROJECTILE_MEDBULLET) + if (src.stat != 2) + src.bruteloss += 30 + src.updatehealth() + + else if (flag == PROJECTILE_WEAKBULLET) + if (src.stat != 2) + src.bruteloss += 15 + src.updatehealth() + + else if (flag == PROJECTILE_MPBULLET) + if (src.stat != 2) + src.bruteloss += 20 + src.updatehealth() + + else if (flag == PROJECTILE_SLUG) + if (src.stat != 2) + src.bruteloss += 40 + src.updatehealth() + + else if (flag == PROJECTILE_BAG) + if (src.stat != 2) + src.bruteloss += 2 + src.updatehealth() + + + else if (flag == PROJECTILE_TASER) + return + + else if (flag == PROJECTILE_WAVE) + if (src.stat != 2) + src.bruteloss += 25 + src.updatehealth() + return + + else if(flag == PROJECTILE_LASER) + if (src.stat != 2) + src.bruteloss += 20 + src.updatehealth() + else if(flag == PROJECTILE_PULSE) + if (src.stat != 2) + src.bruteloss += 40 + src.updatehealth() +*/ + return + + + +/mob/living/silicon/hivebot/Bump(atom/movable/AM as mob|obj, yes) + spawn( 0 ) + if ((!( yes ) || src.now_pushing)) + return + src.now_pushing = 1 + if(ismob(AM)) + var/mob/tmob = AM + /*if(istype(tmob, /mob/living/carbon/human) && (M_FAT in tmob.mutations)) + if(prob(20)) + for(var/mob/M in viewers(src, null)) + if(M.client) to_chat(M, M << "[src] fails to push [tmob]'s fat ass out of the way.") - src.now_pushing = 0 - //src.unlock_medal("That's No Moon, That's A Gourmand!", 1) - return*/ - src.now_pushing = 0 - ..() - if (!istype(AM, /atom/movable)) - return - if (!src.now_pushing) - src.now_pushing = 1 - if (!AM.anchored) - var/t = get_dir(src, AM) - step(AM, t) - src.now_pushing = null - return - return - - -/mob/living/silicon/hivebot/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/weldingtool) && W:welding) - if (W:remove_fuel(0)) - src.adjustBruteLoss(-30) - src.updatehealth() - src.add_fingerprint(user) - for(var/mob/O in viewers(user, null)) - O.show_message(text("[user] has fixed some of the dents on [src]!"), 1) - else + src.now_pushing = 0 + //src.unlock_medal("That's No Moon, That's A Gourmand!", 1) + return*/ + src.now_pushing = 0 + ..() + if (!istype(AM, /atom/movable)) + return + if (!src.now_pushing) + src.now_pushing = 1 + if (!AM.anchored) + var/t = get_dir(src, AM) + step(AM, t) + src.now_pushing = null + return + return + + +/mob/living/silicon/hivebot/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/weldingtool) && W:welding) + if (W:remove_fuel(0)) + src.adjustBruteLoss(-30) + src.updatehealth() + src.add_fingerprint(user) + for(var/mob/O in viewers(user, null)) + O.show_message(text("[user] has fixed some of the dents on [src]!"), 1) + else to_chat(user, "Need more welding fuel!") - return - -/mob/living/silicon/hivebot/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - - if (M.a_intent == "grab") - if (M == src) - return - var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) - G.assailant = M - if (M.hand) - M.l_hand = G - else - M.r_hand = G - G.layer = 20 - G.affecting = src - src.grabbed_by += G - G.synch() - playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] has grabbed [] passively!", M, src), 1) - - else if (M.a_intent == "hurt") - var/damage = rand(5, 10) - if (prob(90)) - /* - if (M.class == "combat") - damage += 15 - if(prob(20)) - src.weakened = max(src.weakened,4) - src.stunned = max(src.stunned,4) - */ - playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] has slashed at []!", M, src), 1) - if(prob(8)) - flick("noise", src.flash) - src.adjustBruteLoss(damage) - src.updatehealth() - else - playsound(src.loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] took a swipe at []!", M, src), 1) - return - - else if (M.a_intent == "disarm") - if(!(src.lying)) - var/randn = rand(1, 100) - if (randn <= 40) - src.stunned = 5 - step(src,get_dir(M,src)) - spawn(5) step(src,get_dir(M,src)) - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] has pushed back []!", M, src), 1) - else - playsound(src.loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] attempted to push back []!", M, src), 1) - return - -/mob/living/silicon/hivebot/attack_hand(mob/user) - ..() - return - - -/mob/living/silicon/hivebot/proc/allowed(mob/M) - //check if it doesn't require any access at all - if(src.check_access(null)) - return 1 - return 0 - -/mob/living/silicon/hivebot/proc/check_access(obj/item/weapon/card/id/I) - if(!istype(src.req_access, /list)) //something's very wrong - return 1 - - var/list/L = src.req_access - if(!L.len) //no requirements - return 1 - if(!I || !istype(I, /obj/item/weapon/card/id) || !I.access) //not ID or no access - return 0 - for(var/req in src.req_access) - if(!(req in I.access)) //doesn't have this access - return 0 - return 1 - -/mob/living/silicon/hivebot/proc/updateicon() - - - src.overlays.len = 0 - - if(src.stat == 0) - src.overlays += "eyes" - else - src.overlays -= "eyes" - - -/mob/living/silicon/hivebot/proc/installed_modules() - - - if(!src.module) - src.pick_module() - return - var/dat = "Modules\n" - dat += {"Close -
    -
    - Activated Modules -
    - Module 1: [module_state_1 ? "[module_state_1]" : "No Module"]
    - Module 2: [module_state_2 ? "
    [module_state_2]" : "No Module"]
    - Module 3: [module_state_3 ? "
    [module_state_3]" : "No Module"]
    -
    - Installed Modules

    "} - - for (var/obj in src.module.modules) - if(src.activated(obj)) - dat += text("[obj]: Activated
    ") - else - dat += text("[obj]:
    Activate
    ") -/* - if(src.activated(obj)) - dat += text("[obj]: \[Activated | Deactivate\]
    ") - else - dat += text("[obj]: \[Activate | Deactivated\]
    ") -*/ - src << browse(dat, "window=robotmod&can_close=0") - - -/mob/living/silicon/hivebot/Topic(href, href_list) - ..() - if (href_list["mach_close"]) - var/t1 = text("window=[href_list["mach_close"]]") - src.machine = null - src << browse(null, t1) - return - - if (href_list["mod"]) - var/obj/item/O = locate(href_list["mod"]) - O.attack_self(src) - - if (href_list["act"]) - var/obj/item/O = locate(href_list["act"]) - if(activated(O)) + return + +/mob/living/silicon/hivebot/attack_alien(mob/living/carbon/alien/humanoid/M as mob) + + if (M.a_intent == "grab") + if (M == src) + return + var/obj/item/weapon/grab/G = getFromPool(/obj/item/weapon/grab,M,src) + G.assailant = M + if (M.hand) + M.l_hand = G + else + M.r_hand = G + G.layer = 20 + G.affecting = src + src.grabbed_by += G + G.synch() + playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] has grabbed [] passively!", M, src), 1) + + else if (M.a_intent == "hurt") + var/damage = rand(5, 10) + if (prob(90)) + /* + if (M.class == "combat") + damage += 15 + if(prob(20)) + src.weakened = max(src.weakened,4) + src.stunned = max(src.stunned,4) + */ + playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] has slashed at []!", M, src), 1) + if(prob(8)) + flick("noise", src.flash) + src.adjustBruteLoss(damage) + src.updatehealth() + else + playsound(src.loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] took a swipe at []!", M, src), 1) + return + + else if (M.a_intent == "disarm") + if(!(src.lying)) + var/randn = rand(1, 100) + if (randn <= 40) + src.stunned = 5 + step(src,get_dir(M,src)) + spawn(5) step(src,get_dir(M,src)) + playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] has pushed back []!", M, src), 1) + else + playsound(src.loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + O.show_message(text("[] attempted to push back []!", M, src), 1) + return + +/mob/living/silicon/hivebot/attack_hand(mob/user) + ..() + return + + +/mob/living/silicon/hivebot/proc/allowed(mob/M) + //check if it doesn't require any access at all + if(src.check_access(null)) + return 1 + return 0 + +/mob/living/silicon/hivebot/proc/check_access(obj/item/weapon/card/id/I) + if(!istype(src.req_access, /list)) //something's very wrong + return 1 + + var/list/L = src.req_access + if(!L.len) //no requirements + return 1 + if(!I || !istype(I, /obj/item/weapon/card/id) || !I.access) //not ID or no access + return 0 + for(var/req in src.req_access) + if(!(req in I.access)) //doesn't have this access + return 0 + return 1 + +/mob/living/silicon/hivebot/proc/updateicon() + + + src.overlays.len = 0 + + if(src.stat == 0) + src.overlays += "eyes" + else + src.overlays -= "eyes" + + +/mob/living/silicon/hivebot/proc/installed_modules() + + + if(!src.module) + src.pick_module() + return + var/dat = "Modules\n" + dat += {"Close +
    +
    + Activated Modules +
    + Module 1: [module_state_1 ? "[module_state_1]" : "No Module"]
    + Module 2: [module_state_2 ? "
    [module_state_2]" : "No Module"]
    + Module 3: [module_state_3 ? "
    [module_state_3]" : "No Module"]
    +
    + Installed Modules

    "} + + for (var/obj in src.module.modules) + if(src.activated(obj)) + dat += text("[obj]: Activated
    ") + else + dat += text("[obj]:
    Activate
    ") +/* + if(src.activated(obj)) + dat += text("[obj]: \[Activated | Deactivate\]
    ") + else + dat += text("[obj]: \[Activate | Deactivated\]
    ") +*/ + src << browse(dat, "window=robotmod&can_close=0") + + +/mob/living/silicon/hivebot/Topic(href, href_list) + ..() + if (href_list["mach_close"]) + var/t1 = text("window=[href_list["mach_close"]]") + src.machine = null + src << browse(null, t1) + return + + if (href_list["mod"]) + var/obj/item/O = locate(href_list["mod"]) + O.attack_self(src) + + if (href_list["act"]) + var/obj/item/O = locate(href_list["act"]) + if(activated(O)) to_chat(src, "Already activated") - return - if(!src.module_state_1) - src.module_state_1 = O - O.layer = 20 - src.contents += O - else if(!src.module_state_2) - src.module_state_2 = O - O.layer = 20 - src.contents += O - else if(!src.module_state_3) - src.module_state_3 = O - O.layer = 20 - src.contents += O - else + return + if(!src.module_state_1) + src.module_state_1 = O + O.layer = 20 + src.contents += O + else if(!src.module_state_2) + src.module_state_2 = O + O.layer = 20 + src.contents += O + else if(!src.module_state_3) + src.module_state_3 = O + O.layer = 20 + src.contents += O + else to_chat(src, "You need to disable a module first!") - src.installed_modules() - - if (href_list["deact"]) - var/obj/item/O = locate(href_list["deact"]) - if(activated(O)) - if(src.module_state_1 == O) - src.module_state_1 = null - src.contents -= O - else if(src.module_state_2 == O) - src.module_state_2 = null - src.contents -= O - else if(src.module_state_3 == O) - src.module_state_3 = null - src.contents -= O - else + src.installed_modules() + + if (href_list["deact"]) + var/obj/item/O = locate(href_list["deact"]) + if(activated(O)) + if(src.module_state_1 == O) + src.module_state_1 = null + src.contents -= O + else if(src.module_state_2 == O) + src.module_state_2 = null + src.contents -= O + else if(src.module_state_3 == O) + src.module_state_3 = null + src.contents -= O + else to_chat(src, "Module isn't activated.") - else + else to_chat(src, "Module isn't activated") - src.installed_modules() - return - -/mob/living/silicon/hivebot/proc/uneq_active() - if(isnull(src.module_active)) - return - if(src.module_state_1 == src.module_active) - if (src.client) - src.client.screen -= module_state_1 - src.contents -= module_state_1 - src.module_active = null - src.module_state_1 = null - src.inv1.icon_state = "inv1" - else if(src.module_state_2 == src.module_active) - if (src.client) - src.client.screen -= module_state_2 - src.contents -= module_state_2 - src.module_active = null - src.module_state_2 = null - src.inv2.icon_state = "inv2" - else if(src.module_state_3 == src.module_active) - if (src.client) - src.client.screen -= module_state_3 - src.contents -= module_state_3 - src.module_active = null - src.module_state_3 = null - src.inv3.icon_state = "inv3" - - -/mob/living/silicon/hivebot/proc/activated(obj/item/O) - if(src.module_state_1 == O) - return 1 - else if(src.module_state_2 == O) - return 1 - else if(src.module_state_3 == O) - return 1 - else - return 0 - -/mob/living/silicon/hivebot/proc/radio_menu() - var/dat = {" - -Microphone: [src.radio.broadcasting ? "Engaged" : "Disengaged"]
    -Speaker: [src.radio.listening ? "Engaged" : "Disengaged"]
    -Frequency: -- -- -[format_frequency(src.radio.frequency)] -+ -+
    -------- -
    "} - src << browse(dat, "window=radio") - onclose(src, "radio") - return - - -/mob/living/silicon/hivebot/Move(a, b, flag) - - if (src.buckled) - return - - if (src.restrained()) - src.stop_pulling() - - var/t7 = 1 - if (src.restrained()) - for(var/mob/M in range(src, 1)) - if ((M.pulling == src && M.stat == 0 && !( M.restrained() ))) - t7 = null - if ((t7 && (src.pulling && ((get_dist(src, src.pulling) <= 1 || src.pulling.loc == src.loc) && (src.client && src.client.moving))))) - var/turf/T = src.loc - . = ..() - - if (src.pulling && src.pulling.loc) - if(!( isturf(src.pulling.loc) )) - src.stop_pulling() - return - else - if(Debug) - diary <<"src.pulling disappeared? at [__LINE__] in mob.dm - src.pulling = [src.pulling]" - diary <<"REPORT THIS" - - ///// - if(src.pulling && src.pulling.anchored) - src.stop_pulling() - return - - if (!src.restrained()) - var/diag = get_dir(src, src.pulling) - if ((diag - 1) & diag) - else - diag = null - if ((get_dist(src, src.pulling) > 1 || diag)) - if (ismob(src.pulling)) - var/mob/M = src.pulling - var/ok = 1 - if (locate(/obj/item/weapon/grab, M.grabbed_by)) - if (prob(75)) - var/obj/item/weapon/grab/G = pick(M.grabbed_by) - if (istype(G, /obj/item/weapon/grab)) - for(var/mob/O in viewers(M, null)) - O.show_message(text("[G.affecting] has been pulled from [G.assailant]'s grip by [src]"), 1) - returnToPool(G) - else - ok = 0 - if (locate(/obj/item/weapon/grab, M.grabbed_by.len)) - ok = 0 - if (ok) - var/atom/movable/t = M.pulling - M.stop_pulling() - step(src.pulling, get_dir(src.pulling.loc, T)) - M.start_pulling(t) - else - if (src.pulling) - step(src.pulling, get_dir(src.pulling.loc, T)) - else - src.stop_pulling() - . = ..() - if ((src.s_active && !( s_active in src.contents ) )) - src.s_active.close(src) - return - - -/mob/living/silicon/hivebot/verb/cmd_return_mainframe() - set category = "Robot Commands" - set name = "Recall to Mainframe." - return_mainframe() - -/mob/living/silicon/hivebot/proc/return_mainframe() - if(mainframe) - mainframe.return_to(src) - else + src.installed_modules() + return + +/mob/living/silicon/hivebot/proc/uneq_active() + if(isnull(src.module_active)) + return + if(src.module_state_1 == src.module_active) + if (src.client) + src.client.screen -= module_state_1 + src.contents -= module_state_1 + src.module_active = null + src.module_state_1 = null + src.inv1.icon_state = "inv1" + else if(src.module_state_2 == src.module_active) + if (src.client) + src.client.screen -= module_state_2 + src.contents -= module_state_2 + src.module_active = null + src.module_state_2 = null + src.inv2.icon_state = "inv2" + else if(src.module_state_3 == src.module_active) + if (src.client) + src.client.screen -= module_state_3 + src.contents -= module_state_3 + src.module_active = null + src.module_state_3 = null + src.inv3.icon_state = "inv3" + + +/mob/living/silicon/hivebot/proc/activated(obj/item/O) + if(src.module_state_1 == O) + return 1 + else if(src.module_state_2 == O) + return 1 + else if(src.module_state_3 == O) + return 1 + else + return 0 + +/mob/living/silicon/hivebot/proc/radio_menu() + var/dat = {" + +Microphone: [src.radio.broadcasting ? "Engaged" : "Disengaged"]
    +Speaker: [src.radio.listening ? "Engaged" : "Disengaged"]
    +Frequency: +- +- +[format_frequency(src.radio.frequency)] ++ ++
    +------- +
    "} + src << browse(dat, "window=radio") + onclose(src, "radio") + return + + +/mob/living/silicon/hivebot/Move(a, b, flag) + + if (src.buckled) + return + + if (src.restrained()) + src.stop_pulling() + + var/t7 = 1 + if (src.restrained()) + for(var/mob/M in range(src, 1)) + if ((M.pulling == src && M.stat == 0 && !( M.restrained() ))) + t7 = null + if ((t7 && (src.pulling && ((get_dist(src, src.pulling) <= 1 || src.pulling.loc == src.loc) && (src.client && src.client.moving))))) + var/turf/T = src.loc + . = ..() + + if (src.pulling && src.pulling.loc) + if(!( isturf(src.pulling.loc) )) + src.stop_pulling() + return + else + if(Debug) + diary <<"src.pulling disappeared? at [__LINE__] in mob.dm - src.pulling = [src.pulling]" + diary <<"REPORT THIS" + + ///// + if(src.pulling && src.pulling.anchored) + src.stop_pulling() + return + + if (!src.restrained()) + var/diag = get_dir(src, src.pulling) + if ((diag - 1) & diag) + else + diag = null + if ((get_dist(src, src.pulling) > 1 || diag)) + if (ismob(src.pulling)) + var/mob/M = src.pulling + var/ok = 1 + if (locate(/obj/item/weapon/grab, M.grabbed_by)) + if (prob(75)) + var/obj/item/weapon/grab/G = pick(M.grabbed_by) + if (istype(G, /obj/item/weapon/grab)) + for(var/mob/O in viewers(M, null)) + O.show_message(text("[G.affecting] has been pulled from [G.assailant]'s grip by [src]"), 1) + returnToPool(G) + else + ok = 0 + if (locate(/obj/item/weapon/grab, M.grabbed_by.len)) + ok = 0 + if (ok) + var/atom/movable/t = M.pulling + M.stop_pulling() + step(src.pulling, get_dir(src.pulling.loc, T)) + M.start_pulling(t) + else + if (src.pulling) + step(src.pulling, get_dir(src.pulling.loc, T)) + else + src.stop_pulling() + . = ..() + if ((src.s_active && !( s_active in src.contents ) )) + src.s_active.close(src) + return + + +/mob/living/silicon/hivebot/verb/cmd_return_mainframe() + set category = "Robot Commands" + set name = "Recall to Mainframe." + return_mainframe() + +/mob/living/silicon/hivebot/proc/return_mainframe() + if(mainframe) + mainframe.return_to(src) + else to_chat(src, "You lack a dedicated mainframe!") return \ No newline at end of file diff --git a/code/unused/hivebot/hivebotdefine.dm b/code/unused/hivebot/hivebotdefine.dm index f2c055617d6..27cc4f196b4 100644 --- a/code/unused/hivebot/hivebotdefine.dm +++ b/code/unused/hivebot/hivebotdefine.dm @@ -1,44 +1,44 @@ -/mob/living/silicon/hivebot - name = "Robot" - icon = 'icons/mob/hivebot.dmi' - icon_state = "basic" - health = 80 - var/health_max = 80 - -//HUD - var/obj/screen/cells = null - var/obj/screen/inv1 = null - var/obj/screen/inv2 = null - var/obj/screen/inv3 = null - -//3 Modules can be activated at any one time. - var/obj/item/weapon/robot_module/module = null - var/module_active = null - var/module_state_1 = null - var/module_state_2 = null - var/module_state_3 = null - - var/obj/item/device/radio/radio = null - - var/list/req_access = list(ACCESS_ROBOTICS) - var/energy = 4000 - var/energy_max = 4000 - var/jetpack = 0 - - var/mob/living/silicon/hive_mainframe/mainframe = null - var/dependent = 0 - var/shell = 1 - -/mob/living/silicon/hive_mainframe - name = "Robot Mainframe" - voice_name = "synthesized voice" - - icon_state = "hive_main" - health = 200 - var/health_max = 200 - - anchored = 1 - var/online = 1 - var/mob/living/silicon/hivebot = null - var/hivebot_name = null +/mob/living/silicon/hivebot + name = "Robot" + icon = 'icons/mob/hivebot.dmi' + icon_state = "basic" + health = 80 + var/health_max = 80 + +//HUD + var/obj/screen/cells = null + var/obj/screen/inv1 = null + var/obj/screen/inv2 = null + var/obj/screen/inv3 = null + +//3 Modules can be activated at any one time. + var/obj/item/weapon/robot_module/module = null + var/module_active = null + var/module_state_1 = null + var/module_state_2 = null + var/module_state_3 = null + + var/obj/item/device/radio/radio = null + + var/list/req_access = list(ACCESS_ROBOTICS) + var/energy = 4000 + var/energy_max = 4000 + var/jetpack = 0 + + var/mob/living/silicon/hive_mainframe/mainframe = null + var/dependent = 0 + var/shell = 1 + +/mob/living/silicon/hive_mainframe + name = "Robot Mainframe" + voice_name = "synthesized voice" + + icon_state = "hive_main" + health = 200 + var/health_max = 200 + + anchored = 1 + var/online = 1 + var/mob/living/silicon/hivebot = null + var/hivebot_name = null var/force_mind = 0 \ No newline at end of file diff --git a/code/unused/hivebot/hud.dm b/code/unused/hivebot/hud.dm index 6f357a8433a..eda5f306586 100644 --- a/code/unused/hivebot/hud.dm +++ b/code/unused/hivebot/hud.dm @@ -1,252 +1,252 @@ - -/obj/hud/proc/hivebot_hud() - - - src.adding = list( ) - src.other = list( ) - src.intents = list( ) - src.mon_blo = list( ) - src.m_ints = list( ) - src.mov_int = list( ) - src.vimpaired = list( ) - src.darkMask = list( ) - - src.g_dither = new src.h_type( src ) - src.g_dither.screen_loc = "WEST,SOUTH to EAST,NORTH" - src.g_dither.name = "Mask" - src.g_dither.icon_state = "dither12g" - src.g_dither.layer = 18 - src.g_dither.mouse_opacity = 0 - - src.alien_view = new src.h_type(src) - src.alien_view.screen_loc = "WEST,SOUTH to EAST,NORTH" - src.alien_view.name = "Alien" - src.alien_view.icon_state = "alien" - src.alien_view.layer = 18 - src.alien_view.mouse_opacity = 0 - - src.blurry = new src.h_type( src ) - src.blurry.screen_loc = "WEST,SOUTH to EAST,NORTH" - src.blurry.name = "Blurry" - src.blurry.icon_state = "blurry" - src.blurry.layer = 17 - src.blurry.mouse_opacity = 0 - - src.druggy = new src.h_type( src ) - src.druggy.screen_loc = "WEST,SOUTH to EAST,NORTH" - src.druggy.name = "Druggy" - src.druggy.icon_state = "druggy" - src.druggy.layer = 17 - src.druggy.mouse_opacity = 0 - - // station explosion cinematic - src.station_explosion = new src.h_type( src ) - src.station_explosion.icon = 'icons/effects/station_explosion.dmi' - src.station_explosion.icon_state = "start" - src.station_explosion.layer = 20 - src.station_explosion.mouse_opacity = 0 - src.station_explosion.screen_loc = "1,3" - - var/obj/screen/using - - -//Radio - using = new src.h_type( src ) - using.name = "radio" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "radio" - using.screen_loc = ui_movi_old - using.layer = 20 - src.adding += using - -//Generic overlays - - using = new src.h_type(src) //Right hud bar - using.dir = SOUTH - using.icon = 'icons/mob/screen1_robot.dmi' - using.screen_loc = "EAST+1,SOUTH to EAST+1,NORTH" - using.layer = 19 - src.adding += using - - using = new src.h_type(src) //Lower hud bar - using.dir = EAST - using.icon = 'icons/mob/screen1_robot.dmi' - using.screen_loc = "WEST,SOUTH-1 to EAST,SOUTH-1" - using.layer = 19 - src.adding += using - - using = new src.h_type(src) //Corner Button - using.dir = NORTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.screen_loc = "EAST+1,SOUTH-1" - using.layer = 19 - src.adding += using - - -//Module select - - using = new src.h_type( src ) - using.name = "module1" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "inv1" - using.screen_loc = ui_inv1 - using.layer = 20 - src.adding += using - mymob:inv1 = using - - using = new src.h_type( src ) - using.name = "module2" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "inv2" - using.screen_loc = ui_inv2 - using.layer = 20 - src.adding += using - mymob:inv2 = using - - using = new src.h_type( src ) - using.name = "module3" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "inv3" - using.screen_loc = ui_inv3 - using.layer = 20 - src.adding += using - mymob:inv3 = using - -//End of module select - -//Intent - using = new src.h_type( src ) - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent) - using.screen_loc = ui_acti - using.layer = 20 - src.adding += using - action_intent = using - - using = new src.h_type( src ) - using.name = "arrowleft" - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "s_arrow" - using.dir = WEST - using.screen_loc = ui_iarrowleft - using.layer = 19 - src.adding += using - - using = new src.h_type( src ) - using.name = "arrowright" - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "s_arrow" - using.dir = EAST - using.screen_loc = ui_iarrowright - using.layer = 19 - src.adding += using -//End of Intent - -//Cell - mymob:cells = new /obj/screen( null ) - mymob:cells.icon = 'icons/mob/screen1_robot.dmi' - mymob:cells.icon_state = "charge-empty" - mymob:cells.name = "cell" - mymob:cells.screen_loc = ui_toxin - -//Health - mymob.healths = new /obj/screen( null ) - mymob.healths.icon = 'icons/mob/screen1_robot.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_health - -//Installed Module - mymob.hands = new /obj/screen( null ) - mymob.hands.icon = 'icons/mob/screen1_robot.dmi' - mymob.hands.icon_state = "nomod" - mymob.hands.name = "module" - mymob.hands.screen_loc = ui_dropbutton - -//Module Panel - using = new src.h_type( src ) - using.name = "panel" - using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = "panel" - using.screen_loc = ui_throw - using.layer = 19 - src.adding += using - -//Store - mymob.throw_icon = new /obj/screen(null) - mymob.throw_icon.icon = 'icons/mob/screen1_robot.dmi' - mymob.throw_icon.icon_state = "store" - mymob.throw_icon.name = "store" - mymob.throw_icon.screen_loc = ui_hand - -//Temp - mymob.bodytemp = new /obj/screen( null ) - mymob.bodytemp.icon_state = "temp0" - mymob.bodytemp.name = "body temperature" - mymob.bodytemp.screen_loc = ui_temp - -//does nothing (fire and oxy) - mymob.oxygen = new /obj/screen( null ) - mymob.oxygen.icon = 'icons/mob/screen1_robot.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - - mymob.fire = new /obj/screen( null ) - mymob.fire.icon = 'icons/mob/screen1_robot.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - - - - mymob.pullin = new /obj/screen( null ) - mymob.pullin.icon = 'icons/mob/screen1_robot.dmi' - mymob.pullin.icon_state = "pull0" - mymob.pullin.name = "pull" - mymob.pullin.screen_loc = ui_pull - - mymob.blind = new /obj/screen( null ) - mymob.blind.icon = 'icons/mob/screen1_full.dmi'' - mymob.blind.icon_state = "blackimageoverlay" - mymob.blind.name = " " - mymob.blind.screen_loc = "1,1" - mymob.blind.layer = 0 - mymob.blind.mouse_opacity = 0 - - mymob.flash = new /obj/screen( null ) - mymob.flash.icon = 'icons/mob/screen1_robot.dmi' - mymob.flash.icon_state = "blank" - mymob.flash.name = "flash" - mymob.flash.screen_loc = "1,1 to 15,15" - mymob.flash.layer = 17 - - mymob.sleep = new /obj/screen( null ) - mymob.sleep.icon = 'icons/mob/screen1_robot.dmi' - mymob.sleep.icon_state = "sleep0" - mymob.sleep.name = "sleep" - mymob.sleep.screen_loc = ui_sleep - - mymob.rest = new /obj/screen( null ) - mymob.rest.icon = 'icons/mob/screen1_robot.dmi' - mymob.rest.icon_state = "rest0" - mymob.rest.name = "rest" - mymob.rest.screen_loc = ui_rest - - - mymob.zone_sel = new /obj/screen/zone_sel( null ) - mymob.zone_sel.overlays.len = 0 - mymob.zone_sel.overlays += image("icon" = 'icons/mob/zone_sel.dmi', "icon_state" = text("[]", mymob.zone_sel.selecting)) - - mymob.client.reset_screen() - - mymob.client.screen += list(mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, mymob.rest, mymob.sleep) //, mymob.mach ) - mymob.client.screen += src.adding + src.other - - return + +/obj/hud/proc/hivebot_hud() + + + src.adding = list( ) + src.other = list( ) + src.intents = list( ) + src.mon_blo = list( ) + src.m_ints = list( ) + src.mov_int = list( ) + src.vimpaired = list( ) + src.darkMask = list( ) + + src.g_dither = new src.h_type( src ) + src.g_dither.screen_loc = "WEST,SOUTH to EAST,NORTH" + src.g_dither.name = "Mask" + src.g_dither.icon_state = "dither12g" + src.g_dither.layer = 18 + src.g_dither.mouse_opacity = 0 + + src.alien_view = new src.h_type(src) + src.alien_view.screen_loc = "WEST,SOUTH to EAST,NORTH" + src.alien_view.name = "Alien" + src.alien_view.icon_state = "alien" + src.alien_view.layer = 18 + src.alien_view.mouse_opacity = 0 + + src.blurry = new src.h_type( src ) + src.blurry.screen_loc = "WEST,SOUTH to EAST,NORTH" + src.blurry.name = "Blurry" + src.blurry.icon_state = "blurry" + src.blurry.layer = 17 + src.blurry.mouse_opacity = 0 + + src.druggy = new src.h_type( src ) + src.druggy.screen_loc = "WEST,SOUTH to EAST,NORTH" + src.druggy.name = "Druggy" + src.druggy.icon_state = "druggy" + src.druggy.layer = 17 + src.druggy.mouse_opacity = 0 + + // station explosion cinematic + src.station_explosion = new src.h_type( src ) + src.station_explosion.icon = 'icons/effects/station_explosion.dmi' + src.station_explosion.icon_state = "start" + src.station_explosion.layer = 20 + src.station_explosion.mouse_opacity = 0 + src.station_explosion.screen_loc = "1,3" + + var/obj/screen/using + + +//Radio + using = new src.h_type( src ) + using.name = "radio" + using.dir = SOUTHWEST + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "radio" + using.screen_loc = ui_movi_old + using.layer = 20 + src.adding += using + +//Generic overlays + + using = new src.h_type(src) //Right hud bar + using.dir = SOUTH + using.icon = 'icons/mob/screen1_robot.dmi' + using.screen_loc = "EAST+1,SOUTH to EAST+1,NORTH" + using.layer = 19 + src.adding += using + + using = new src.h_type(src) //Lower hud bar + using.dir = EAST + using.icon = 'icons/mob/screen1_robot.dmi' + using.screen_loc = "WEST,SOUTH-1 to EAST,SOUTH-1" + using.layer = 19 + src.adding += using + + using = new src.h_type(src) //Corner Button + using.dir = NORTHWEST + using.icon = 'icons/mob/screen1_robot.dmi' + using.screen_loc = "EAST+1,SOUTH-1" + using.layer = 19 + src.adding += using + + +//Module select + + using = new src.h_type( src ) + using.name = "module1" + using.dir = SOUTHWEST + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "inv1" + using.screen_loc = ui_inv1 + using.layer = 20 + src.adding += using + mymob:inv1 = using + + using = new src.h_type( src ) + using.name = "module2" + using.dir = SOUTHWEST + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "inv2" + using.screen_loc = ui_inv2 + using.layer = 20 + src.adding += using + mymob:inv2 = using + + using = new src.h_type( src ) + using.name = "module3" + using.dir = SOUTHWEST + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "inv3" + using.screen_loc = ui_inv3 + using.layer = 20 + src.adding += using + mymob:inv3 = using + +//End of module select + +//Intent + using = new src.h_type( src ) + using.name = "act_intent" + using.dir = SOUTHWEST + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent) + using.screen_loc = ui_acti + using.layer = 20 + src.adding += using + action_intent = using + + using = new src.h_type( src ) + using.name = "arrowleft" + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "s_arrow" + using.dir = WEST + using.screen_loc = ui_iarrowleft + using.layer = 19 + src.adding += using + + using = new src.h_type( src ) + using.name = "arrowright" + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "s_arrow" + using.dir = EAST + using.screen_loc = ui_iarrowright + using.layer = 19 + src.adding += using +//End of Intent + +//Cell + mymob:cells = new /obj/screen( null ) + mymob:cells.icon = 'icons/mob/screen1_robot.dmi' + mymob:cells.icon_state = "charge-empty" + mymob:cells.name = "cell" + mymob:cells.screen_loc = ui_toxin + +//Health + mymob.healths = new /obj/screen( null ) + mymob.healths.icon = 'icons/mob/screen1_robot.dmi' + mymob.healths.icon_state = "health0" + mymob.healths.name = "health" + mymob.healths.screen_loc = ui_health + +//Installed Module + mymob.hands = new /obj/screen( null ) + mymob.hands.icon = 'icons/mob/screen1_robot.dmi' + mymob.hands.icon_state = "nomod" + mymob.hands.name = "module" + mymob.hands.screen_loc = ui_dropbutton + +//Module Panel + using = new src.h_type( src ) + using.name = "panel" + using.icon = 'icons/mob/screen1_robot.dmi' + using.icon_state = "panel" + using.screen_loc = ui_throw + using.layer = 19 + src.adding += using + +//Store + mymob.throw_icon = new /obj/screen(null) + mymob.throw_icon.icon = 'icons/mob/screen1_robot.dmi' + mymob.throw_icon.icon_state = "store" + mymob.throw_icon.name = "store" + mymob.throw_icon.screen_loc = ui_hand + +//Temp + mymob.bodytemp = new /obj/screen( null ) + mymob.bodytemp.icon_state = "temp0" + mymob.bodytemp.name = "body temperature" + mymob.bodytemp.screen_loc = ui_temp + +//does nothing (fire and oxy) + mymob.oxygen = new /obj/screen( null ) + mymob.oxygen.icon = 'icons/mob/screen1_robot.dmi' + mymob.oxygen.icon_state = "oxy0" + mymob.oxygen.name = "oxygen" + mymob.oxygen.screen_loc = ui_oxygen + + mymob.fire = new /obj/screen( null ) + mymob.fire.icon = 'icons/mob/screen1_robot.dmi' + mymob.fire.icon_state = "fire0" + mymob.fire.name = "fire" + mymob.fire.screen_loc = ui_fire + + + + mymob.pullin = new /obj/screen( null ) + mymob.pullin.icon = 'icons/mob/screen1_robot.dmi' + mymob.pullin.icon_state = "pull0" + mymob.pullin.name = "pull" + mymob.pullin.screen_loc = ui_pull + + mymob.blind = new /obj/screen( null ) + mymob.blind.icon = 'icons/mob/screen1_full.dmi'' + mymob.blind.icon_state = "blackimageoverlay" + mymob.blind.name = " " + mymob.blind.screen_loc = "1,1" + mymob.blind.layer = 0 + mymob.blind.mouse_opacity = 0 + + mymob.flash = new /obj/screen( null ) + mymob.flash.icon = 'icons/mob/screen1_robot.dmi' + mymob.flash.icon_state = "blank" + mymob.flash.name = "flash" + mymob.flash.screen_loc = "1,1 to 15,15" + mymob.flash.layer = 17 + + mymob.sleep = new /obj/screen( null ) + mymob.sleep.icon = 'icons/mob/screen1_robot.dmi' + mymob.sleep.icon_state = "sleep0" + mymob.sleep.name = "sleep" + mymob.sleep.screen_loc = ui_sleep + + mymob.rest = new /obj/screen( null ) + mymob.rest.icon = 'icons/mob/screen1_robot.dmi' + mymob.rest.icon_state = "rest0" + mymob.rest.name = "rest" + mymob.rest.screen_loc = ui_rest + + + mymob.zone_sel = new /obj/screen/zone_sel( null ) + mymob.zone_sel.overlays.len = 0 + mymob.zone_sel.overlays += image("icon" = 'icons/mob/zone_sel.dmi', "icon_state" = text("[]", mymob.zone_sel.selecting)) + + mymob.client.reset_screen() + + mymob.client.screen += list(mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, mymob.rest, mymob.sleep) //, mymob.mach ) + mymob.client.screen += src.adding + src.other + + return diff --git a/code/unused/hivebot/life.dm b/code/unused/hivebot/life.dm index bc3698bf518..e65b3e77e3d 100644 --- a/code/unused/hivebot/life.dm +++ b/code/unused/hivebot/life.dm @@ -1,228 +1,228 @@ -/mob/living/silicon/hivebot/Life() - set invisibility = 0 - set background = 1 - if(timestopped) return 0 //under effects of time magick - - if (src.monkeyizing) - return - - if (src.stat != 2) - use_power() - - src.blinded = null - - clamp_values() - - handle_regular_status_updates() - - if(client) - src.shell = 0 - handle_regular_hud_updates() - update_items() - if(dependent) - mainframe_check() - - update_canmove() - - -/mob/living/silicon/hivebot - proc - clamp_values() - - stunned = max(min(stunned, 10),0) - paralysis = max(min(paralysis, 1), 0) - weakened = max(min(weakened, 15), 0) - sleeping = max(min(sleeping, 1), 0) - setToxLoss(0) - setOxyLoss(0) - - use_power() - - if (src.energy) - if(src.energy <= 0) - death() - - else if (src.energy <= 10) - src.module_active = null - src.module_state_1 = null - src.module_state_2 = null - src.module_state_3 = null - src.energy -=1 - else - if(src.module_state_1) - src.energy -=1 - if(src.module_state_2) - src.energy -=1 - if(src.module_state_3) - src.energy -=1 - src.energy -=1 - src.blinded = 0 - src.stat = 0 - else - src.blinded = 1 - src.stat = 1 - - update_canmove() - if(paralysis || stunned || weakened || buckled) canmove = 0 - else canmove = 1 - - - handle_regular_status_updates() - - health = src.health_max - (getFireLoss() + getBruteLoss()) - - if(health <= 0) - death() - - if (src.stat != 2) //Alive. - - if (src.paralysis || src.stunned || src.weakened) //Stunned etc. - if (src.stunned > 0) - src.stunned-- - src.stat = 0 - if (src.weakened > 0) - src.weakened-- - src.lying = 0 - src.stat = 0 - if (src.paralysis > 0) - src.paralysis-- - src.blinded = 0 - src.lying = 0 - src.stat = 1 - - else //Not stunned. - src.lying = 0 - src.stat = 0 - - else //Dead. - src.blinded = 1 - src.stat = 2 - - src.density = !( src.lying ) - - if ((src.sdisabilities & 1)) - src.blinded = 1 - if ((src.sdisabilities & 4)) - src.ear_deaf = 1 - - if (src.eye_blurry > 0) - src.eye_blurry-- - src.eye_blurry = max(0, src.eye_blurry) - - if (src.druggy > 0) - src.druggy-- - src.druggy = max(0, src.druggy) - - return 1 - - handle_regular_hud_updates() - - if (src.stat == 2 || M_XRAY in src.mutations) - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.sight |= SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (src.stat != 2) - src.sight &= ~SEE_MOBS - src.sight &= ~SEE_TURFS - src.sight &= ~SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - - if (src.healths) - if (src.stat != 2) - switch(health) - if(health_max to INFINITY) - src.healths.icon_state = "health0" - if(src.health_max*0.80 to src.health_max) - src.healths.icon_state = "health1" - if(src.health_max*0.60 to src.health_max*0.80) - src.healths.icon_state = "health2" - if(src.health_max*0.40 to src.health_max*0.60) - src.healths.icon_state = "health3" - if(src.health_max*0.20 to src.health_max*0.40) - src.healths.icon_state = "health4" - if(0 to health_max*0.20) - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" - else - src.healths.icon_state = "health7" - - if (src.cells) - switch(src.energy) - if(src.energy_max*0.75 to INFINITY) - src.cells.icon_state = "charge4" - if(0.5*src.energy_max to 0.75*src.energy_max) - src.cells.icon_state = "charge3" - if(0.25*src.energy_max to 0.5*src.energy_max) - src.cells.icon_state = "charge2" - if(0 to 0.25*src.energy_max) - src.cells.icon_state = "charge1" - else - src.cells.icon_state = "charge0" - - switch(src.bodytemperature) //310.055 optimal body temp - - if(335 to INFINITY) - src.bodytemp.icon_state = "temp2" - if(320 to 335) - src.bodytemp.icon_state = "temp1" - if(300 to 320) - src.bodytemp.icon_state = "temp0" - if(260 to 300) - src.bodytemp.icon_state = "temp-1" - else - src.bodytemp.icon_state = "temp-2" - - - if(src.pullin) src.pullin.icon_state = "pull[src.pulling ? 1 : 0]" - - src.client.screen -= src.hud_used.blurry - src.client.screen -= src.hud_used.druggy - src.client.screen -= src.hud_used.vimpaired - - if ((src.blind && src.stat != 2)) - if ((src.blinded)) - src.blind.layer = 18 - else - src.blind.layer = 0 - - if (src.disabilities & 1) - src.client.screen += src.hud_used.vimpaired - - if (src.eye_blurry) - src.client.screen += src.hud_used.blurry - - if (src.druggy) - src.client.screen += src.hud_used.druggy - - if (src.stat != 2) - if (src.machine) - if (!( src.machine.check_eye(src) )) - src.reset_view(null) - else - if(!client.adminobs) - reset_view(null) - - return 1 - - - update_items() - if (src.client) - src.client.screen -= src.contents - src.client.screen += src.contents - if(src.module_state_1) - src.module_state_1:screen_loc = ui_inv1 - if(src.module_state_2) - src.module_state_2:screen_loc = ui_inv2 - if(src.module_state_3) - src.module_state_3:screen_loc = ui_inv3 - - mainframe_check() - if(mainframe) - if(mainframe.stat == 2) - mainframe.return_to(src) - else +/mob/living/silicon/hivebot/Life() + set invisibility = 0 + set background = 1 + if(timestopped) return 0 //under effects of time magick + + if (src.monkeyizing) + return + + if (src.stat != 2) + use_power() + + src.blinded = null + + clamp_values() + + handle_regular_status_updates() + + if(client) + src.shell = 0 + handle_regular_hud_updates() + update_items() + if(dependent) + mainframe_check() + + update_canmove() + + +/mob/living/silicon/hivebot + proc + clamp_values() + + stunned = max(min(stunned, 10),0) + paralysis = max(min(paralysis, 1), 0) + weakened = max(min(weakened, 15), 0) + sleeping = max(min(sleeping, 1), 0) + setToxLoss(0) + setOxyLoss(0) + + use_power() + + if (src.energy) + if(src.energy <= 0) + death() + + else if (src.energy <= 10) + src.module_active = null + src.module_state_1 = null + src.module_state_2 = null + src.module_state_3 = null + src.energy -=1 + else + if(src.module_state_1) + src.energy -=1 + if(src.module_state_2) + src.energy -=1 + if(src.module_state_3) + src.energy -=1 + src.energy -=1 + src.blinded = 0 + src.stat = 0 + else + src.blinded = 1 + src.stat = 1 + + update_canmove() + if(paralysis || stunned || weakened || buckled) canmove = 0 + else canmove = 1 + + + handle_regular_status_updates() + + health = src.health_max - (getFireLoss() + getBruteLoss()) + + if(health <= 0) + death() + + if (src.stat != 2) //Alive. + + if (src.paralysis || src.stunned || src.weakened) //Stunned etc. + if (src.stunned > 0) + src.stunned-- + src.stat = 0 + if (src.weakened > 0) + src.weakened-- + src.lying = 0 + src.stat = 0 + if (src.paralysis > 0) + src.paralysis-- + src.blinded = 0 + src.lying = 0 + src.stat = 1 + + else //Not stunned. + src.lying = 0 + src.stat = 0 + + else //Dead. + src.blinded = 1 + src.stat = 2 + + src.density = !( src.lying ) + + if ((src.sdisabilities & 1)) + src.blinded = 1 + if ((src.sdisabilities & 4)) + src.ear_deaf = 1 + + if (src.eye_blurry > 0) + src.eye_blurry-- + src.eye_blurry = max(0, src.eye_blurry) + + if (src.druggy > 0) + src.druggy-- + src.druggy = max(0, src.druggy) + + return 1 + + handle_regular_hud_updates() + + if (src.stat == 2 || M_XRAY in src.mutations) + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (src.stat != 2) + src.sight &= ~SEE_MOBS + src.sight &= ~SEE_TURFS + src.sight &= ~SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + if (src.healths) + if (src.stat != 2) + switch(health) + if(health_max to INFINITY) + src.healths.icon_state = "health0" + if(src.health_max*0.80 to src.health_max) + src.healths.icon_state = "health1" + if(src.health_max*0.60 to src.health_max*0.80) + src.healths.icon_state = "health2" + if(src.health_max*0.40 to src.health_max*0.60) + src.healths.icon_state = "health3" + if(src.health_max*0.20 to src.health_max*0.40) + src.healths.icon_state = "health4" + if(0 to health_max*0.20) + src.healths.icon_state = "health5" + else + src.healths.icon_state = "health6" + else + src.healths.icon_state = "health7" + + if (src.cells) + switch(src.energy) + if(src.energy_max*0.75 to INFINITY) + src.cells.icon_state = "charge4" + if(0.5*src.energy_max to 0.75*src.energy_max) + src.cells.icon_state = "charge3" + if(0.25*src.energy_max to 0.5*src.energy_max) + src.cells.icon_state = "charge2" + if(0 to 0.25*src.energy_max) + src.cells.icon_state = "charge1" + else + src.cells.icon_state = "charge0" + + switch(src.bodytemperature) //310.055 optimal body temp + + if(335 to INFINITY) + src.bodytemp.icon_state = "temp2" + if(320 to 335) + src.bodytemp.icon_state = "temp1" + if(300 to 320) + src.bodytemp.icon_state = "temp0" + if(260 to 300) + src.bodytemp.icon_state = "temp-1" + else + src.bodytemp.icon_state = "temp-2" + + + if(src.pullin) src.pullin.icon_state = "pull[src.pulling ? 1 : 0]" + + src.client.screen -= src.hud_used.blurry + src.client.screen -= src.hud_used.druggy + src.client.screen -= src.hud_used.vimpaired + + if ((src.blind && src.stat != 2)) + if ((src.blinded)) + src.blind.layer = 18 + else + src.blind.layer = 0 + + if (src.disabilities & 1) + src.client.screen += src.hud_used.vimpaired + + if (src.eye_blurry) + src.client.screen += src.hud_used.blurry + + if (src.druggy) + src.client.screen += src.hud_used.druggy + + if (src.stat != 2) + if (src.machine) + if (!( src.machine.check_eye(src) )) + src.reset_view(null) + else + if(!client.adminobs) + reset_view(null) + + return 1 + + + update_items() + if (src.client) + src.client.screen -= src.contents + src.client.screen += src.contents + if(src.module_state_1) + src.module_state_1:screen_loc = ui_inv1 + if(src.module_state_2) + src.module_state_2:screen_loc = ui_inv2 + if(src.module_state_3) + src.module_state_3:screen_loc = ui_inv3 + + mainframe_check() + if(mainframe) + if(mainframe.stat == 2) + mainframe.return_to(src) + else death() \ No newline at end of file diff --git a/code/unused/hivebot/login.dm b/code/unused/hivebot/login.dm index 3a811b4c8a9..4cf122d7978 100644 --- a/code/unused/hivebot/login.dm +++ b/code/unused/hivebot/login.dm @@ -1,15 +1,15 @@ -/mob/living/silicon/hivebot/Login() - ..() - - update_clothing() - - if (!isturf(src.loc)) - src.client.eye = src.loc - src.client.perspective = EYE_PERSPECTIVE - if (src.stat == 2) - src.verbs += /client/proc/ghost - if(src.real_name == "Hiveborg") - src.real_name += " " - src.real_name += "-[rand(1, 999)]" - src.name = src.real_name +/mob/living/silicon/hivebot/Login() + ..() + + update_clothing() + + if (!isturf(src.loc)) + src.client.eye = src.loc + src.client.perspective = EYE_PERSPECTIVE + if (src.stat == 2) + src.verbs += /client/proc/ghost + if(src.real_name == "Hiveborg") + src.real_name += " " + src.real_name += "-[rand(1, 999)]" + src.name = src.real_name return \ No newline at end of file diff --git a/code/unused/hivebot/mainframe.dm b/code/unused/hivebot/mainframe.dm index 265a12d2205..1cdc5181ebe 100644 --- a/code/unused/hivebot/mainframe.dm +++ b/code/unused/hivebot/mainframe.dm @@ -1,164 +1,164 @@ -/mob/living/silicon/hive_mainframe/New() - Namepick() - -/mob/living/silicon/hive_mainframe/Life() - if(timestopped) return 0 //under effects of time magick - if (src.stat == 2) - return - else - src.updatehealth() - - if (src.health <= 0) - death() - return - - if(src.force_mind) - if(!src.mind) - if(src.client) - src.mind = new - src.mind.key = src.key - src.mind.current = src - src.force_mind = 0 - -/mob/living/silicon/hive_mainframe/Stat() - ..() - - if(statpanel("Status")) - if(emergency_shuttle.online && emergency_shuttle.location < 2) - var/timeleft = emergency_shuttle.timeleft() - if (timeleft) - stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") - -/mob/living/silicon/hive_mainframe/updatehealth() - if (src.nodamage == 0) - src.health = 100 - src.getFireLoss() - src.getBruteLoss() - else - src.health = 100 - src.stat = 0 - -/mob/living/silicon/hive_mainframe/death(gibbed) - src.stat = 2 - src.canmove = 0 - if(src.blind) - src.blind.layer = 0 - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.sight |= SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - src.lying = 1 - src.icon_state = "hive_main-crash" - - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch - mind.store_memory("Time of death: [tod]", 0) - - if (src.key) - spawn(50) - if(src.key && src.stat == 2) - src.verbs += /client/proc/ghost - return ..(gibbed) - -/mob/living/silicon/hive_mainframe/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "queries, \"[text]\""; - else if (ending == "!") - return "declares, \"[copytext(text, 1, length(text))]\""; - - return "states, \"[text]\""; - - -/mob/living/silicon/hive_mainframe/proc/return_to(var/mob/user) - if(user.mind) - user.mind.transfer_to(src) - spawn(20) - user:shell = 1 - user:real_name = "Robot [pick(rand(1, 999))]" - user:name = user:real_name - - - return - -/mob/living/silicon/hive_mainframe/verb/cmd_deploy_to() - set category = "Mainframe Commands" - set name = "Deploy to shell." - deploy_to() - -/mob/living/silicon/hive_mainframe/verb/deploy_to() - - - if(usr.stat == 2 || (usr.status_flags & FAKEDEATH)) +/mob/living/silicon/hive_mainframe/New() + Namepick() + +/mob/living/silicon/hive_mainframe/Life() + if(timestopped) return 0 //under effects of time magick + if (src.stat == 2) + return + else + src.updatehealth() + + if (src.health <= 0) + death() + return + + if(src.force_mind) + if(!src.mind) + if(src.client) + src.mind = new + src.mind.key = src.key + src.mind.current = src + src.force_mind = 0 + +/mob/living/silicon/hive_mainframe/Stat() + ..() + + if(statpanel("Status")) + if(emergency_shuttle.online && emergency_shuttle.location < 2) + var/timeleft = emergency_shuttle.timeleft() + if (timeleft) + stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]") + +/mob/living/silicon/hive_mainframe/updatehealth() + if (src.nodamage == 0) + src.health = 100 - src.getFireLoss() - src.getBruteLoss() + else + src.health = 100 + src.stat = 0 + +/mob/living/silicon/hive_mainframe/death(gibbed) + src.stat = 2 + src.canmove = 0 + if(src.blind) + src.blind.layer = 0 + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + src.lying = 1 + src.icon_state = "hive_main-crash" + + var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch + mind.store_memory("Time of death: [tod]", 0) + + if (src.key) + spawn(50) + if(src.key && src.stat == 2) + src.verbs += /client/proc/ghost + return ..(gibbed) + +/mob/living/silicon/hive_mainframe/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "queries, \"[text]\""; + else if (ending == "!") + return "declares, \"[copytext(text, 1, length(text))]\""; + + return "states, \"[text]\""; + + +/mob/living/silicon/hive_mainframe/proc/return_to(var/mob/user) + if(user.mind) + user.mind.transfer_to(src) + spawn(20) + user:shell = 1 + user:real_name = "Robot [pick(rand(1, 999))]" + user:name = user:real_name + + + return + +/mob/living/silicon/hive_mainframe/verb/cmd_deploy_to() + set category = "Mainframe Commands" + set name = "Deploy to shell." + deploy_to() + +/mob/living/silicon/hive_mainframe/verb/deploy_to() + + + if(usr.stat == 2 || (usr.status_flags & FAKEDEATH)) to_chat(usr, "You can't deploy because you are dead!") - return - - var/list/bodies = new/list() - - for(var/mob/living/silicon/hivebot/H in mob_list) - if(H.z == src.z) - if(H.shell) - if(!H.stat) - bodies += H - - var/target_shell = input(usr, "Which body to control?") as null|anything in bodies - - if (!target_shell) - return - - else if(src.mind) - spawn(30) - target_shell:mainframe = src - target_shell:dependent = 1 - target_shell:real_name = src.name - target_shell:name = target_shell:real_name - src.mind.transfer_to(target_shell) - return - - -/client/proc/MainframeMove(n,direct,var/mob/living/silicon/hive_mainframe/user) - return -/obj/hud/proc/hive_mainframe_hud() - return - - - - - -/mob/living/silicon/hive_mainframe/Login() - ..() - update_clothing() - for(var/S in src.client.screen) - del(S) - src.flash = new /obj/screen( null ) - src.flash.icon_state = "blank" - src.flash.name = "flash" - src.flash.screen_loc = "1,1 to 15,15" - src.flash.layer = 17 - src.blind = new /obj/screen( null ) - src.blind.icon_state = "black" - src.blind.name = " " - src.blind.screen_loc = "1,1 to 15,15" - src.blind.layer = 0 - src.client.screen += list( src.blind, src.flash ) - if(!isturf(src.loc)) - src.client.eye = src.loc - src.client.perspective = EYE_PERSPECTIVE - if (src.stat == 2) - src.verbs += /client/proc/ghost - return - - - -/mob/living/silicon/hive_mainframe/proc/Namepick() - var/randomname = pick(ai_names) - var/newname = input(src,"You are the a Mainframe Unit. Would you like to change your name to something else?", "Name change",randomname) - - if (length(newname) == 0) - newname = randomname - - if (newname) - if (length(newname) >= 26) - newname = copytext(newname, 1, 26) - newname = replacetext(newname, ">", "'") - src.real_name = newname + return + + var/list/bodies = new/list() + + for(var/mob/living/silicon/hivebot/H in mob_list) + if(H.z == src.z) + if(H.shell) + if(!H.stat) + bodies += H + + var/target_shell = input(usr, "Which body to control?") as null|anything in bodies + + if (!target_shell) + return + + else if(src.mind) + spawn(30) + target_shell:mainframe = src + target_shell:dependent = 1 + target_shell:real_name = src.name + target_shell:name = target_shell:real_name + src.mind.transfer_to(target_shell) + return + + +/client/proc/MainframeMove(n,direct,var/mob/living/silicon/hive_mainframe/user) + return +/obj/hud/proc/hive_mainframe_hud() + return + + + + + +/mob/living/silicon/hive_mainframe/Login() + ..() + update_clothing() + for(var/S in src.client.screen) + del(S) + src.flash = new /obj/screen( null ) + src.flash.icon_state = "blank" + src.flash.name = "flash" + src.flash.screen_loc = "1,1 to 15,15" + src.flash.layer = 17 + src.blind = new /obj/screen( null ) + src.blind.icon_state = "black" + src.blind.name = " " + src.blind.screen_loc = "1,1 to 15,15" + src.blind.layer = 0 + src.client.screen += list( src.blind, src.flash ) + if(!isturf(src.loc)) + src.client.eye = src.loc + src.client.perspective = EYE_PERSPECTIVE + if (src.stat == 2) + src.verbs += /client/proc/ghost + return + + + +/mob/living/silicon/hive_mainframe/proc/Namepick() + var/randomname = pick(ai_names) + var/newname = input(src,"You are the a Mainframe Unit. Would you like to change your name to something else?", "Name change",randomname) + + if (length(newname) == 0) + newname = randomname + + if (newname) + if (length(newname) >= 26) + newname = copytext(newname, 1, 26) + newname = replacetext(newname, ">", "'") + src.real_name = newname src.name = newname \ No newline at end of file diff --git a/code/unused/hivebot/say.dm b/code/unused/hivebot/say.dm index afb46ebfd6c..4e27664fff3 100644 --- a/code/unused/hivebot/say.dm +++ b/code/unused/hivebot/say.dm @@ -1,10 +1,10 @@ - -/mob/living/silicon/hivebot/say_quote(var/text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "queries, \"[text]\""; - else if (ending == "!") - return "declares, \"[copytext(text, 1, length(text))]\""; - - return "states, \"[text]\""; + +/mob/living/silicon/hivebot/say_quote(var/text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "queries, \"[text]\""; + else if (ending == "!") + return "declares, \"[copytext(text, 1, length(text))]\""; + + return "states, \"[text]\""; diff --git a/code/unused/mining/machine_craftlathe_unused.dm b/code/unused/mining/machine_craftlathe_unused.dm index 2f65715d1e8..0210cc3274e 100644 --- a/code/unused/mining/machine_craftlathe_unused.dm +++ b/code/unused/mining/machine_craftlathe_unused.dm @@ -1,235 +1,235 @@ -/*********************NEW AUTOLATHE / CRAFT LATHE***********************/ - -var/list/datum/craftlathe_item/CRAFT_ITEMS = list() -var/CRAFT_ITEMS_SETUP = 1 //this should probably be a pre-game thing, but i'll do it so the first lathe2 that's created will set-up the recipes. - -proc/check_craftlathe_recipe(var/list/param_recipe) - if(param_recipe.len != 9) - return - var/i - var/match = 0 //this one counts if there is at least one non-"" ingredient. - for(var/datum/craftlathe_item/CI in CRAFT_ITEMS) - match = 0 - for(i = 1; i <= 9; i++) - if(CI.recipe[i] != param_recipe[i]) - match = 0 //use this so it passes by the match > 0 check below, otherwise i'd need a new variable to tell the return CI below that the check failed - break - if(CI.recipe[i] != "") - match++ - if(match > 0) - return CI - return 0 - -/datum/craftlathe_item - var/id = "" //must be unique for each item type. used to create recipes - var/name = "unknown" //what the lathe will show as it's contents - var/list/recipe = list("","","","","","","","","") //the 9 items here represent what items need to be placed in the lathe to produce this item. - var/item_type = null //this is used on items like sheets which are added when inserted into the lathe. - var/amount = 1 - var/amount_attackby = 1 - -/datum/craftlathe_item/New(var/param_id,var/param_name,var/param_amount,var/param_ammount_per_attackby,var/list/param_recipe,var/param_type = null) - ..() - id = param_id - name = param_name - recipe = param_recipe - item_type = param_type - amount = param_amount; - amount_attackby = param_ammount_per_attackby - return - -//this proc checks the recipe you give in it's parameter with the entire list of available items. If any match, it returns the item from CRAFT_ITEMS. the returned item should not be changed!! - -/obj/machinery/autolathe2 - name = "Craft lathe" - icon_state = "autolathe" - density = 1 - anchored = 1 - var/datum/craftlathe_item/selected = null - var/datum/craftlathe_item/make = null - var/list/datum/craftlathe_item/craft_contents = list() - var/list/current_recipe = list("","","","","","","","","") - -/obj/machinery/autolathe2/New() - ..() - if(CRAFT_ITEMS_SETUP) - CRAFT_ITEMS_SETUP = 0 - build_recipes() - return - -/obj/machinery/autolathe2/attack_hand(mob/user as mob) - var/dat - dat = text("

    Craft Lathe

    ") - dat += text("
    ") - - dat += text("Materials

    ") - var/datum/craftlathe_item/CI - var/i - for(i = 1; i <= craft_contents.len; i++) - CI = craft_contents[i] - if (CI == selected) - dat += text("[CI.name] ([CI.amount])
    ") - else - dat += text("[CI.name] ([CI.amount])
    ") - - dat += text("

    ") - - dat += text("Crafting Table

    ") - - dat += text(" ") - - var/j = 0 - var/k = 0 - for (i = 0; i < 3; i++) - dat += text(" ") - for (j = 1; j <= 3; j++) - k = i * 3 + j - if (current_recipe[k]) - dat += text(" ") - else - dat += text(" ") - dat += text(" ") - dat += text("
    [current_recipe[k]]----
    ") - - dat += text("

    ") - dat += text("Will make: ") - if (make) - dat += text("[make.name]") - else - dat += text("nothing useful") - - dat += text("

    ") - user << browse("[dat]", "window=craft") - -/obj/machinery/autolathe2/Topic(href, href_list) - if(..()) - return - usr.machine = src - src.add_fingerprint(usr) - if(href_list["remove"]) - var/n = text2num(href_list["remove"]) - if(!n || n < 1 || n > 9) - return - current_recipe[n] = "" - if(href_list["select"]) - var/n = text2num(href_list["select"]) - if(!n || n < 1 || n > 9) - return - selected = craft_contents[n] - if(href_list["add"]) - var/n = text2num(href_list["add"]) - if(!n || n < 1 || n > 9) - return - if(selected) - current_recipe[n] = selected.id - if(href_list["make"]) - var/datum/craftlathe_item/MAKE = check_craftlathe_recipe(src.current_recipe) - if(MAKE) - for (var/datum/craftlathe_item/CI2 in craft_contents) - if(CI2.id == MAKE.id) - CI2.amount += CI2.amount_attackby - src.updateUsrDialog() - return - craft_contents += new/datum/craftlathe_item(MAKE.id,MAKE.name,MAKE.amount,MAKE.amount_attackby,MAKE.recipe,MAKE.item_type) - var/datum/craftlathe_item/CI = check_craftlathe_recipe(src.current_recipe) - if(CI) - make = CI - else - make = null - src.updateUsrDialog() - - - -/obj/machinery/autolathe2/attackby(obj/item/weapon/W as obj, mob/user as mob) - usr.machine = src - src.add_fingerprint(usr) - for (var/datum/craftlathe_item/CI in CRAFT_ITEMS) - if(W.type == CI.item_type) - for (var/datum/craftlathe_item/CI2 in craft_contents) - if(CI2.item_type == W.type) - CI2.amount += CI2.amount_attackby - rmv_item(W) - return - craft_contents += new/datum/craftlathe_item(CI.id,CI.name,CI.amount,CI.amount_attackby,CI.recipe,CI.item_type) - rmv_item(W) - return - src.updateUsrDialog() - return - -/obj/machinery/autolathe2/proc/rmv_item(obj/item/W as obj) - if(istype(W,/obj/item/stack)) - var/obj/item/stack/S = W - S.amount-- - if (S.amount <= 0) - del(S) - else - del(W) - -/obj/machinery/autolathe2/proc/build_recipes() - //Parameters: ID, Name, Amount, Amount_added_per_attackby, Recipe, Object type - CRAFT_ITEMS += new/datum/craftlathe_item("METAL","Metal",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/metal) - CRAFT_ITEMS += new/datum/craftlathe_item("R METAL","Reinforced Metal",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/r_metal) - CRAFT_ITEMS += new/datum/craftlathe_item("GLASS","Glass",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/glass/glass) - CRAFT_ITEMS += new/datum/craftlathe_item("R GLASS","Reinforced Glass",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/glass/rglass) - CRAFT_ITEMS += new/datum/craftlathe_item("GOLD","Gold",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/gold) - CRAFT_ITEMS += new/datum/craftlathe_item("SILVER","Silver",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/silver) - CRAFT_ITEMS += new/datum/craftlathe_item("DIAMOND","Diamond",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/diamond) - CRAFT_ITEMS += new/datum/craftlathe_item("PLASMA","Plasma",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/plasma) - CRAFT_ITEMS += new/datum/craftlathe_item("URANIUM","Uranium",1,1,list("","","","","","","","",""),/obj/item/weapon/ore/mineral/uranium) - CRAFT_ITEMS += new/datum/craftlathe_item("CLOWN","Bananium",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/clown) - CRAFT_ITEMS += new/datum/craftlathe_item("ADMAMANTINE","Adamantine",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/adamantine) - CRAFT_ITEMS += new/datum/craftlathe_item("SCREWS","Screws",9,9,list("","","","","METAL","","","METAL","")) - CRAFT_ITEMS += new/datum/craftlathe_item("COGS","Cogs",9,9,list("","METAL","","METAL","METAL","METAL","","METAL","")) - CRAFT_ITEMS += new/datum/craftlathe_item("SWITCH","Switch",12,12,list("METAL","","METAL","METAL","METAL","","METAL","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("KEYBOARD","Keyboard",1,1,list("","","","SWITCH","SWITCH","SWITCH","SWITCH","SWITCH","SWITCH")) - CRAFT_ITEMS += new/datum/craftlathe_item("M PANEL","Metal Panel",10,10,list("","","","","METAL","METAL","","METAL","METAL")) - CRAFT_ITEMS += new/datum/craftlathe_item("CASE","Equipment Case",1,1,list("M PANEL","M PANEL","M PANEL","M PANEL","","M PANEL","M PANEL","M PANEL","M PANEL")) - CRAFT_ITEMS += new/datum/craftlathe_item("G PANEL","Glass Panel",10,10,list("","","","","GLASS","GLASS","","GLASS","GLASS")) - CRAFT_ITEMS += new/datum/craftlathe_item("SCREEN","Screen",1,1,list("","GLASS","","GLASS","PLASMA","GLASS","","GLASS","")) - CRAFT_ITEMS += new/datum/craftlathe_item("EL SILVER","Electronics Silver",30,30,list("","","","","SILVER","","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("EL GOLD","Electronics Gold",6,6,list("","","","","GOLD","","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("TINTED GL","Tinted Glass",2,2,list("","METAL","","","GLASS","","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("TANK VALVE","Tank Transfer Valuve",1,1,list("","PIPE","","","PIPE","SWITCH","","PIPE","")) - CRAFT_ITEMS += new/datum/craftlathe_item("PIPE","Pipe",1,1,list("","M PANEL","","","M PANEL","","","M PANEL","")) - - CRAFT_ITEMS += new/datum/craftlathe_item("CB FRAME","Circuitboard Frame",1,1,list("","","","M PANEL","G PANEL","M PANEL","G PANEL","M PANEL","G PANEL")) - CRAFT_ITEMS += new/datum/craftlathe_item("ROM","ROM Module",1,1,list("EL SILVER","EL SILVER","EL SILVER","EL SILVER","","EL SILVER","EL SILVER","EL SILVER","EL SILVER")) - CRAFT_ITEMS += new/datum/craftlathe_item("RAM","RAM Module",1,1,list("EL SILVER","EL SILVER","EL SILVER","EL SILVER","EL GOLD","EL SILVER","EL SILVER","EL SILVER","EL SILVER")) - CRAFT_ITEMS += new/datum/craftlathe_item("PROCESSOR","Processor",1,1,list("EL GOLD","EL SILVER","EL GOLD","EL SILVER","EL SILVER","EL SILVER","EL SILVER","EL GOLD","EL SILVER")) - CRAFT_ITEMS += new/datum/craftlathe_item("ANTENNA","Antenna",1,1,list("","","EL SILVER","","","EL SILVER","EL SILVER","EL SILVER","EL SILVER")) - CRAFT_ITEMS += new/datum/craftlathe_item("OP RECEPTOR","Optic Receptor",1,1,list("G PANEL","G PANEL","G PANEL","","EL GOLD","","G PANEL","G PANEL","G PANEL")) - CRAFT_ITEMS += new/datum/craftlathe_item("THERMAL OP R","Thermal Optic Receptor",1,1,list("","OP RECEPTOR","","ROM","DIAMOND","DIAMOND","","OP RECEPTOR","")) - CRAFT_ITEMS += new/datum/craftlathe_item("MASON OP R","Mason Optic Receptor",1,1,list("","OP RECEPTOR","","ROM","EL SILVER","EL SILVER","","OP RECEPTOR","")) - CRAFT_ITEMS += new/datum/craftlathe_item("EAR FRAME","Earpiece Frame",1,1,list("M PANEL","M PANEL","M PANEL","M PANEL","","M PANEL","M PANEL","M PANEL","")) - CRAFT_ITEMS += new/datum/craftlathe_item("RADIO M","Radio Module",1,1,list("","ANTENNA","","","ROM","","CB FRAME","CB FRAME","CB FRAME")) - CRAFT_ITEMS += new/datum/craftlathe_item("EARPIECE","Radio Earpiece",1,1,list("","","","","RADIO M","","","EAR FRAME","")) - CRAFT_ITEMS += new/datum/craftlathe_item("EARMUFFS","Earmuffs",1,1,list("","M PANEL","","EAR FRAME","","EAR FRAME","","","")) - - CRAFT_ITEMS += new/datum/craftlathe_item("GLASSES FRAME","Glasses Frame",1,1,list("M PANEL","","M PANEL","M PANEL","","M PANEL","M PANEL","M PANEL","M PANEL")) - CRAFT_ITEMS += new/datum/craftlathe_item("MASONS","Mason Scanners",1,1,list("","","","MASON OP R","GLASSES FRAME","MASON OP R","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("THERMALS","Thermal Scanners",1,1,list("","","","THERMAL OP R","GLASSES FRAME","THERMAL OP R","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("SUNGLASSES","Sunglasses",1,1,list("","","","TINTED GL","GLASSES FRAME","TINTED GL","","","")) - - CRAFT_ITEMS += new/datum/craftlathe_item("HELMET FR","Helmet Frame",1,1,list("METAL","METAL","METAL","METAL","","METAL","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("HELMET","Security Helmet",1,1,list("R METAL","R METAL","R METAL","R METAL","HELMET FR","R METAL","","GLASS","")) - CRAFT_ITEMS += new/datum/craftlathe_item("HOS HELMET","HoS Helmet",1,1,list("SILVER","GOLD","SILVER","SILVER","HELMET","SILVER","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("HARDHAT","Hardhat",1,1,list("","FLASHLIGHT","","","HELMET FR","","","","")) - CRAFT_ITEMS += new/datum/craftlathe_item("SWAT HELMET","SWAT Helmet",1,1,list("","","","","HELMET","","R GLASS","R GLASS","R GLASS")) - CRAFT_ITEMS += new/datum/craftlathe_item("WELDING HELM","Welding Helmet",1,1,list("","","","","HELMET FR","","TINTED GL","TINTED GL","TINTED GL")) - CRAFT_ITEMS += new/datum/craftlathe_item("SPACE HELMET","Space Helmet",1,1,list("R METAL","SILVER","R METAL","SILVER","HELMET FR","SILVER","R GLASS","R GLASS","R GLASS")) - CRAFT_ITEMS += new/datum/craftlathe_item("RIG HELMET","RIG Helmet",1,1,list("R METAL","SILVER","R METAL","SILVER","SPACE HELMET","SILVER","R GLASS","R GLASS","R GLASS")) - CRAFT_ITEMS += new/datum/craftlathe_item("GAS MASK","Gas Mask",1,1,list("","","","","HELMET FR","TANK VALVE","","G PANEL","")) - - CRAFT_ITEMS += new/datum/craftlathe_item("ARMOR FRAME","Armor Frame",1,1,list("R METAL","","R METAL","R METAL","R METAL","R METAL","R METAL","R METAL","R METAL")) - CRAFT_ITEMS += new/datum/craftlathe_item("ARMOR","Armored Vest",1,1,list("R METAL","","R METAL","R METAL","ARMOR FRAME","R METAL","R METAL","R METAL","R METAL")) - CRAFT_ITEMS += new/datum/craftlathe_item("HOS ARMOR","HoS Armor",1,1,list("DIAMOND","","DIAMOND","URANIUM","ARMOR","URANIUM","URANIUM","R METAL","URANIUM")) - CRAFT_ITEMS += new/datum/craftlathe_item("CAP ARMOR","Captain Armor",1,1,list("DIAMOND","","DIAMOND","URANIUM","HOS ARMOR","URANIUM","URANIUM","R METAL","URANIUM")) - CRAFT_ITEMS += new/datum/craftlathe_item("SPACE S FR","Space Suit Frame",1,1,list("SILVER","","SILVER","SILVER","SILVER","SILVER","SILVER","SILVER","SILVER")) - CRAFT_ITEMS += new/datum/craftlathe_item("SPACE SUIT","Space Suit",1,1,list("SILVER","","SILVER","RAM","SPACE S FR","RADIO M","SILVER","SILVEr","SILVER")) - CRAFT_ITEMS += new/datum/craftlathe_item("RIG SUIT","RIG Suit",1,1,list("SILVER","","SILVER","SILVER","SPACE SUIT","SILVER","SILVER","SILVER","SILVER")) - //TODO: Flashlight, type paths - return - - - +/*********************NEW AUTOLATHE / CRAFT LATHE***********************/ + +var/list/datum/craftlathe_item/CRAFT_ITEMS = list() +var/CRAFT_ITEMS_SETUP = 1 //this should probably be a pre-game thing, but i'll do it so the first lathe2 that's created will set-up the recipes. + +proc/check_craftlathe_recipe(var/list/param_recipe) + if(param_recipe.len != 9) + return + var/i + var/match = 0 //this one counts if there is at least one non-"" ingredient. + for(var/datum/craftlathe_item/CI in CRAFT_ITEMS) + match = 0 + for(i = 1; i <= 9; i++) + if(CI.recipe[i] != param_recipe[i]) + match = 0 //use this so it passes by the match > 0 check below, otherwise i'd need a new variable to tell the return CI below that the check failed + break + if(CI.recipe[i] != "") + match++ + if(match > 0) + return CI + return 0 + +/datum/craftlathe_item + var/id = "" //must be unique for each item type. used to create recipes + var/name = "unknown" //what the lathe will show as it's contents + var/list/recipe = list("","","","","","","","","") //the 9 items here represent what items need to be placed in the lathe to produce this item. + var/item_type = null //this is used on items like sheets which are added when inserted into the lathe. + var/amount = 1 + var/amount_attackby = 1 + +/datum/craftlathe_item/New(var/param_id,var/param_name,var/param_amount,var/param_ammount_per_attackby,var/list/param_recipe,var/param_type = null) + ..() + id = param_id + name = param_name + recipe = param_recipe + item_type = param_type + amount = param_amount; + amount_attackby = param_ammount_per_attackby + return + +//this proc checks the recipe you give in it's parameter with the entire list of available items. If any match, it returns the item from CRAFT_ITEMS. the returned item should not be changed!! + +/obj/machinery/autolathe2 + name = "Craft lathe" + icon_state = "autolathe" + density = 1 + anchored = 1 + var/datum/craftlathe_item/selected = null + var/datum/craftlathe_item/make = null + var/list/datum/craftlathe_item/craft_contents = list() + var/list/current_recipe = list("","","","","","","","","") + +/obj/machinery/autolathe2/New() + ..() + if(CRAFT_ITEMS_SETUP) + CRAFT_ITEMS_SETUP = 0 + build_recipes() + return + +/obj/machinery/autolathe2/attack_hand(mob/user as mob) + var/dat + dat = text("

    Craft Lathe

    ") + dat += text("
    ") + + dat += text("Materials

    ") + var/datum/craftlathe_item/CI + var/i + for(i = 1; i <= craft_contents.len; i++) + CI = craft_contents[i] + if (CI == selected) + dat += text("[CI.name] ([CI.amount])
    ") + else + dat += text("[CI.name] ([CI.amount])
    ") + + dat += text("

    ") + + dat += text("Crafting Table

    ") + + dat += text(" ") + + var/j = 0 + var/k = 0 + for (i = 0; i < 3; i++) + dat += text(" ") + for (j = 1; j <= 3; j++) + k = i * 3 + j + if (current_recipe[k]) + dat += text(" ") + else + dat += text(" ") + dat += text(" ") + dat += text("
    [current_recipe[k]]----
    ") + + dat += text("

    ") + dat += text("Will make: ") + if (make) + dat += text("[make.name]") + else + dat += text("nothing useful") + + dat += text("

    ") + user << browse("[dat]", "window=craft") + +/obj/machinery/autolathe2/Topic(href, href_list) + if(..()) + return + usr.machine = src + src.add_fingerprint(usr) + if(href_list["remove"]) + var/n = text2num(href_list["remove"]) + if(!n || n < 1 || n > 9) + return + current_recipe[n] = "" + if(href_list["select"]) + var/n = text2num(href_list["select"]) + if(!n || n < 1 || n > 9) + return + selected = craft_contents[n] + if(href_list["add"]) + var/n = text2num(href_list["add"]) + if(!n || n < 1 || n > 9) + return + if(selected) + current_recipe[n] = selected.id + if(href_list["make"]) + var/datum/craftlathe_item/MAKE = check_craftlathe_recipe(src.current_recipe) + if(MAKE) + for (var/datum/craftlathe_item/CI2 in craft_contents) + if(CI2.id == MAKE.id) + CI2.amount += CI2.amount_attackby + src.updateUsrDialog() + return + craft_contents += new/datum/craftlathe_item(MAKE.id,MAKE.name,MAKE.amount,MAKE.amount_attackby,MAKE.recipe,MAKE.item_type) + var/datum/craftlathe_item/CI = check_craftlathe_recipe(src.current_recipe) + if(CI) + make = CI + else + make = null + src.updateUsrDialog() + + + +/obj/machinery/autolathe2/attackby(obj/item/weapon/W as obj, mob/user as mob) + usr.machine = src + src.add_fingerprint(usr) + for (var/datum/craftlathe_item/CI in CRAFT_ITEMS) + if(W.type == CI.item_type) + for (var/datum/craftlathe_item/CI2 in craft_contents) + if(CI2.item_type == W.type) + CI2.amount += CI2.amount_attackby + rmv_item(W) + return + craft_contents += new/datum/craftlathe_item(CI.id,CI.name,CI.amount,CI.amount_attackby,CI.recipe,CI.item_type) + rmv_item(W) + return + src.updateUsrDialog() + return + +/obj/machinery/autolathe2/proc/rmv_item(obj/item/W as obj) + if(istype(W,/obj/item/stack)) + var/obj/item/stack/S = W + S.amount-- + if (S.amount <= 0) + del(S) + else + del(W) + +/obj/machinery/autolathe2/proc/build_recipes() + //Parameters: ID, Name, Amount, Amount_added_per_attackby, Recipe, Object type + CRAFT_ITEMS += new/datum/craftlathe_item("METAL","Metal",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/metal) + CRAFT_ITEMS += new/datum/craftlathe_item("R METAL","Reinforced Metal",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/r_metal) + CRAFT_ITEMS += new/datum/craftlathe_item("GLASS","Glass",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/glass/glass) + CRAFT_ITEMS += new/datum/craftlathe_item("R GLASS","Reinforced Glass",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/glass/rglass) + CRAFT_ITEMS += new/datum/craftlathe_item("GOLD","Gold",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/gold) + CRAFT_ITEMS += new/datum/craftlathe_item("SILVER","Silver",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/silver) + CRAFT_ITEMS += new/datum/craftlathe_item("DIAMOND","Diamond",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/diamond) + CRAFT_ITEMS += new/datum/craftlathe_item("PLASMA","Plasma",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/plasma) + CRAFT_ITEMS += new/datum/craftlathe_item("URANIUM","Uranium",1,1,list("","","","","","","","",""),/obj/item/weapon/ore/mineral/uranium) + CRAFT_ITEMS += new/datum/craftlathe_item("CLOWN","Bananium",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/clown) + CRAFT_ITEMS += new/datum/craftlathe_item("ADMAMANTINE","Adamantine",1,1,list("","","","","","","","",""),/obj/item/stack/sheet/mineral/adamantine) + CRAFT_ITEMS += new/datum/craftlathe_item("SCREWS","Screws",9,9,list("","","","","METAL","","","METAL","")) + CRAFT_ITEMS += new/datum/craftlathe_item("COGS","Cogs",9,9,list("","METAL","","METAL","METAL","METAL","","METAL","")) + CRAFT_ITEMS += new/datum/craftlathe_item("SWITCH","Switch",12,12,list("METAL","","METAL","METAL","METAL","","METAL","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("KEYBOARD","Keyboard",1,1,list("","","","SWITCH","SWITCH","SWITCH","SWITCH","SWITCH","SWITCH")) + CRAFT_ITEMS += new/datum/craftlathe_item("M PANEL","Metal Panel",10,10,list("","","","","METAL","METAL","","METAL","METAL")) + CRAFT_ITEMS += new/datum/craftlathe_item("CASE","Equipment Case",1,1,list("M PANEL","M PANEL","M PANEL","M PANEL","","M PANEL","M PANEL","M PANEL","M PANEL")) + CRAFT_ITEMS += new/datum/craftlathe_item("G PANEL","Glass Panel",10,10,list("","","","","GLASS","GLASS","","GLASS","GLASS")) + CRAFT_ITEMS += new/datum/craftlathe_item("SCREEN","Screen",1,1,list("","GLASS","","GLASS","PLASMA","GLASS","","GLASS","")) + CRAFT_ITEMS += new/datum/craftlathe_item("EL SILVER","Electronics Silver",30,30,list("","","","","SILVER","","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("EL GOLD","Electronics Gold",6,6,list("","","","","GOLD","","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("TINTED GL","Tinted Glass",2,2,list("","METAL","","","GLASS","","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("TANK VALVE","Tank Transfer Valuve",1,1,list("","PIPE","","","PIPE","SWITCH","","PIPE","")) + CRAFT_ITEMS += new/datum/craftlathe_item("PIPE","Pipe",1,1,list("","M PANEL","","","M PANEL","","","M PANEL","")) + + CRAFT_ITEMS += new/datum/craftlathe_item("CB FRAME","Circuitboard Frame",1,1,list("","","","M PANEL","G PANEL","M PANEL","G PANEL","M PANEL","G PANEL")) + CRAFT_ITEMS += new/datum/craftlathe_item("ROM","ROM Module",1,1,list("EL SILVER","EL SILVER","EL SILVER","EL SILVER","","EL SILVER","EL SILVER","EL SILVER","EL SILVER")) + CRAFT_ITEMS += new/datum/craftlathe_item("RAM","RAM Module",1,1,list("EL SILVER","EL SILVER","EL SILVER","EL SILVER","EL GOLD","EL SILVER","EL SILVER","EL SILVER","EL SILVER")) + CRAFT_ITEMS += new/datum/craftlathe_item("PROCESSOR","Processor",1,1,list("EL GOLD","EL SILVER","EL GOLD","EL SILVER","EL SILVER","EL SILVER","EL SILVER","EL GOLD","EL SILVER")) + CRAFT_ITEMS += new/datum/craftlathe_item("ANTENNA","Antenna",1,1,list("","","EL SILVER","","","EL SILVER","EL SILVER","EL SILVER","EL SILVER")) + CRAFT_ITEMS += new/datum/craftlathe_item("OP RECEPTOR","Optic Receptor",1,1,list("G PANEL","G PANEL","G PANEL","","EL GOLD","","G PANEL","G PANEL","G PANEL")) + CRAFT_ITEMS += new/datum/craftlathe_item("THERMAL OP R","Thermal Optic Receptor",1,1,list("","OP RECEPTOR","","ROM","DIAMOND","DIAMOND","","OP RECEPTOR","")) + CRAFT_ITEMS += new/datum/craftlathe_item("MASON OP R","Mason Optic Receptor",1,1,list("","OP RECEPTOR","","ROM","EL SILVER","EL SILVER","","OP RECEPTOR","")) + CRAFT_ITEMS += new/datum/craftlathe_item("EAR FRAME","Earpiece Frame",1,1,list("M PANEL","M PANEL","M PANEL","M PANEL","","M PANEL","M PANEL","M PANEL","")) + CRAFT_ITEMS += new/datum/craftlathe_item("RADIO M","Radio Module",1,1,list("","ANTENNA","","","ROM","","CB FRAME","CB FRAME","CB FRAME")) + CRAFT_ITEMS += new/datum/craftlathe_item("EARPIECE","Radio Earpiece",1,1,list("","","","","RADIO M","","","EAR FRAME","")) + CRAFT_ITEMS += new/datum/craftlathe_item("EARMUFFS","Earmuffs",1,1,list("","M PANEL","","EAR FRAME","","EAR FRAME","","","")) + + CRAFT_ITEMS += new/datum/craftlathe_item("GLASSES FRAME","Glasses Frame",1,1,list("M PANEL","","M PANEL","M PANEL","","M PANEL","M PANEL","M PANEL","M PANEL")) + CRAFT_ITEMS += new/datum/craftlathe_item("MASONS","Mason Scanners",1,1,list("","","","MASON OP R","GLASSES FRAME","MASON OP R","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("THERMALS","Thermal Scanners",1,1,list("","","","THERMAL OP R","GLASSES FRAME","THERMAL OP R","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("SUNGLASSES","Sunglasses",1,1,list("","","","TINTED GL","GLASSES FRAME","TINTED GL","","","")) + + CRAFT_ITEMS += new/datum/craftlathe_item("HELMET FR","Helmet Frame",1,1,list("METAL","METAL","METAL","METAL","","METAL","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("HELMET","Security Helmet",1,1,list("R METAL","R METAL","R METAL","R METAL","HELMET FR","R METAL","","GLASS","")) + CRAFT_ITEMS += new/datum/craftlathe_item("HOS HELMET","HoS Helmet",1,1,list("SILVER","GOLD","SILVER","SILVER","HELMET","SILVER","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("HARDHAT","Hardhat",1,1,list("","FLASHLIGHT","","","HELMET FR","","","","")) + CRAFT_ITEMS += new/datum/craftlathe_item("SWAT HELMET","SWAT Helmet",1,1,list("","","","","HELMET","","R GLASS","R GLASS","R GLASS")) + CRAFT_ITEMS += new/datum/craftlathe_item("WELDING HELM","Welding Helmet",1,1,list("","","","","HELMET FR","","TINTED GL","TINTED GL","TINTED GL")) + CRAFT_ITEMS += new/datum/craftlathe_item("SPACE HELMET","Space Helmet",1,1,list("R METAL","SILVER","R METAL","SILVER","HELMET FR","SILVER","R GLASS","R GLASS","R GLASS")) + CRAFT_ITEMS += new/datum/craftlathe_item("RIG HELMET","RIG Helmet",1,1,list("R METAL","SILVER","R METAL","SILVER","SPACE HELMET","SILVER","R GLASS","R GLASS","R GLASS")) + CRAFT_ITEMS += new/datum/craftlathe_item("GAS MASK","Gas Mask",1,1,list("","","","","HELMET FR","TANK VALVE","","G PANEL","")) + + CRAFT_ITEMS += new/datum/craftlathe_item("ARMOR FRAME","Armor Frame",1,1,list("R METAL","","R METAL","R METAL","R METAL","R METAL","R METAL","R METAL","R METAL")) + CRAFT_ITEMS += new/datum/craftlathe_item("ARMOR","Armored Vest",1,1,list("R METAL","","R METAL","R METAL","ARMOR FRAME","R METAL","R METAL","R METAL","R METAL")) + CRAFT_ITEMS += new/datum/craftlathe_item("HOS ARMOR","HoS Armor",1,1,list("DIAMOND","","DIAMOND","URANIUM","ARMOR","URANIUM","URANIUM","R METAL","URANIUM")) + CRAFT_ITEMS += new/datum/craftlathe_item("CAP ARMOR","Captain Armor",1,1,list("DIAMOND","","DIAMOND","URANIUM","HOS ARMOR","URANIUM","URANIUM","R METAL","URANIUM")) + CRAFT_ITEMS += new/datum/craftlathe_item("SPACE S FR","Space Suit Frame",1,1,list("SILVER","","SILVER","SILVER","SILVER","SILVER","SILVER","SILVER","SILVER")) + CRAFT_ITEMS += new/datum/craftlathe_item("SPACE SUIT","Space Suit",1,1,list("SILVER","","SILVER","RAM","SPACE S FR","RADIO M","SILVER","SILVEr","SILVER")) + CRAFT_ITEMS += new/datum/craftlathe_item("RIG SUIT","RIG Suit",1,1,list("SILVER","","SILVER","SILVER","SPACE SUIT","SILVER","SILVER","SILVER","SILVER")) + //TODO: Flashlight, type paths + return + + + return \ No newline at end of file diff --git a/code/unused/mining/machine_gas_extractor_unused.dm b/code/unused/mining/machine_gas_extractor_unused.dm index 4e4f82fa469..1b295a86876 100644 --- a/code/unused/mining/machine_gas_extractor_unused.dm +++ b/code/unused/mining/machine_gas_extractor_unused.dm @@ -1,78 +1,78 @@ -/**********************Gas extractor**************************/ - -/obj/machinery/mineral/gasextractor - name = "Gas extractor" - desc = "A machine which extracts gasses from ores" - icon = 'icons/obj/computer.dmi' - icon_state = "aiupload" - var/obj/machinery/mineral/input = null - var/obj/machinery/mineral/output = null - var/message = ""; - var/processing = 0 - var/newtoxins = 0 - density = 1 - anchored = 1.0 - -/obj/machinery/mineral/gasextractor/New() - ..() - spawn( 5 ) - for (var/dir in cardinal) - src.input = locate(/obj/machinery/mineral/input, get_step(src, dir)) - if(src.input) break - for (var/dir in cardinal) - src.output = locate(/obj/machinery/mineral/output, get_step(src, dir)) - if(src.output) break - return - return - -/obj/machinery/mineral/gasextractor/attack_hand(user as mob) - - if(processing == 1) +/**********************Gas extractor**************************/ + +/obj/machinery/mineral/gasextractor + name = "Gas extractor" + desc = "A machine which extracts gasses from ores" + icon = 'icons/obj/computer.dmi' + icon_state = "aiupload" + var/obj/machinery/mineral/input = null + var/obj/machinery/mineral/output = null + var/message = ""; + var/processing = 0 + var/newtoxins = 0 + density = 1 + anchored = 1.0 + +/obj/machinery/mineral/gasextractor/New() + ..() + spawn( 5 ) + for (var/dir in cardinal) + src.input = locate(/obj/machinery/mineral/input, get_step(src, dir)) + if(src.input) break + for (var/dir in cardinal) + src.output = locate(/obj/machinery/mineral/output, get_step(src, dir)) + if(src.output) break + return + return + +/obj/machinery/mineral/gasextractor/attack_hand(user as mob) + + if(processing == 1) to_chat(user, "The machine is processing") - return - - var/dat - dat = text("input connection status: ") - if (input) - dat += text("CONNECTED") - else - dat += text("NOT CONNECTED") - dat += text("
    output connection status: ") - if (output) - dat += text("CONNECTED") - else - dat += text("NOT CONNECTED") - - dat += text("

    Extract gas") - - dat += text("

    Message: [message]") - - user << browse("[dat]", "window=purifier") - -/obj/machinery/mineral/gasextractor/Topic(href, href_list) - if(..()) - return - - usr.machine = src - src.add_fingerprint(usr) - if(href_list["extract"]) - if (src.output) - if (locate(/obj/machinery/portable_atmospherics/canister,output.loc)) - newtoxins = 0 - processing = 1 - var/obj/item/weapon/ore/O - while(locate(/obj/item/weapon/ore/plasma, input.loc) && locate(/obj/machinery/portable_atmospherics/canister,output.loc)) - O = locate(/obj/item/weapon/ore/plasma, input.loc) - if (istype(O,/obj/item/weapon/ore/plasma)) - var/obj/machinery/portable_atmospherics/canister/C - C = locate(/obj/machinery/portable_atmospherics/canister,output.loc) - C.air_contents.toxins += 100 - newtoxins += 100 - del(O) - sleep(5); - processing = 0; - message = "Canister filled with [newtoxins] units of toxins" - else - message = "No canister found" - src.updateUsrDialog() - return + return + + var/dat + dat = text("input connection status: ") + if (input) + dat += text("CONNECTED") + else + dat += text("NOT CONNECTED") + dat += text("
    output connection status: ") + if (output) + dat += text("CONNECTED") + else + dat += text("NOT CONNECTED") + + dat += text("

    Extract gas") + + dat += text("

    Message: [message]") + + user << browse("[dat]", "window=purifier") + +/obj/machinery/mineral/gasextractor/Topic(href, href_list) + if(..()) + return + + usr.machine = src + src.add_fingerprint(usr) + if(href_list["extract"]) + if (src.output) + if (locate(/obj/machinery/portable_atmospherics/canister,output.loc)) + newtoxins = 0 + processing = 1 + var/obj/item/weapon/ore/O + while(locate(/obj/item/weapon/ore/plasma, input.loc) && locate(/obj/machinery/portable_atmospherics/canister,output.loc)) + O = locate(/obj/item/weapon/ore/plasma, input.loc) + if (istype(O,/obj/item/weapon/ore/plasma)) + var/obj/machinery/portable_atmospherics/canister/C + C = locate(/obj/machinery/portable_atmospherics/canister,output.loc) + C.air_contents.toxins += 100 + newtoxins += 100 + del(O) + sleep(5); + processing = 0; + message = "Canister filled with [newtoxins] units of toxins" + else + message = "No canister found" + src.updateUsrDialog() + return diff --git a/code/unused/mining/machine_purifier_unused.dm b/code/unused/mining/machine_purifier_unused.dm index 84322261dfa..36b11fea864 100644 --- a/code/unused/mining/machine_purifier_unused.dm +++ b/code/unused/mining/machine_purifier_unused.dm @@ -1,89 +1,89 @@ -/**********************Mineral purifier (not used, replaced with mineral processing unit)**************************/ - -/obj/machinery/mineral/purifier - name = "Ore Purifier" - desc = "A machine which makes building material out of ores" - icon = 'icons/obj/computer.dmi' - icon_state = "aiupload" - var/obj/machinery/mineral/input = null - var/obj/machinery/mineral/output = null - var/processed = 0 - var/processing = 0 - density = 1 - anchored = 1.0 - -/obj/machinery/mineral/purifier/attack_hand(user as mob) - - if(processing == 1) +/**********************Mineral purifier (not used, replaced with mineral processing unit)**************************/ + +/obj/machinery/mineral/purifier + name = "Ore Purifier" + desc = "A machine which makes building material out of ores" + icon = 'icons/obj/computer.dmi' + icon_state = "aiupload" + var/obj/machinery/mineral/input = null + var/obj/machinery/mineral/output = null + var/processed = 0 + var/processing = 0 + density = 1 + anchored = 1.0 + +/obj/machinery/mineral/purifier/attack_hand(user as mob) + + if(processing == 1) to_chat(user, "The machine is processing") - return - - var/dat - dat = text("input connection status: ") - if (input) - dat += text("CONNECTED") - else - dat += text("NOT CONNECTED") - dat += text("
    output connection status: ") - if (output) - dat += text("CONNECTED") - else - dat += text("NOT CONNECTED") - - dat += text("

    Purify") - - dat += text("

    found: [processed]") - user << browse("[dat]", "window=purifier") - -/obj/machinery/mineral/purifier/Topic(href, href_list) - if(..()) - return - usr.machine = src - src.add_fingerprint(usr) - if(href_list["purify"]) - if (src.output) - processing = 1; - var/obj/item/weapon/ore/O - processed = 0; - while(locate(/obj/item/weapon/ore, input.loc)) - O = locate(/obj/item/weapon/ore, input.loc) - if (istype(O,/obj/item/weapon/ore/iron)) - var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(output)) - M.amount = 1 - qdel(O) - if (istype(O,/obj/item/weapon/ore/diamond)) - new /obj/item/stack/sheet/mineral/diamond(output.loc) - qdel(O) - if (istype(O,/obj/item/weapon/ore/plasma)) - new /obj/item/stack/sheet/mineral/plasma(output.loc) - qdel(O) - if (istype(O,/obj/item/weapon/ore/gold)) - new /obj/item/stack/sheet/mineral/gold(output.loc) - qdel(O) - if (istype(O,/obj/item/weapon/ore/silver)) - new /obj/item/stack/sheet/mineral/silver(output.loc) - qdel(O) - if (istype(O,/obj/item/weapon/ore/uranium)) - new /obj/item/weapon/ore/mineral/uranium(output.loc) - qdel(O) - /*if (istype(O,/obj/item/weapon/ore/adamantine)) - new /obj/item/weapon/ore/adamantine(output.loc) - qdel(O)*/ //Dunno what this area does so I'll keep it commented out for now -Durandan - processed++ - sleep(5); - processing = 0; - src.updateUsrDialog() - return - - -/obj/machinery/mineral/purifier/New() - ..() - spawn( 5 ) - for (var/dir in cardinal) - src.input = locate(/obj/machinery/mineral/input, get_step(src, dir)) - if(src.input) break - for (var/dir in cardinal) - src.output = locate(/obj/machinery/mineral/output, get_step(src, dir)) - if(src.output) break - return - return + return + + var/dat + dat = text("input connection status: ") + if (input) + dat += text("CONNECTED") + else + dat += text("NOT CONNECTED") + dat += text("
    output connection status: ") + if (output) + dat += text("CONNECTED") + else + dat += text("NOT CONNECTED") + + dat += text("

    Purify") + + dat += text("

    found: [processed]") + user << browse("[dat]", "window=purifier") + +/obj/machinery/mineral/purifier/Topic(href, href_list) + if(..()) + return + usr.machine = src + src.add_fingerprint(usr) + if(href_list["purify"]) + if (src.output) + processing = 1; + var/obj/item/weapon/ore/O + processed = 0; + while(locate(/obj/item/weapon/ore, input.loc)) + O = locate(/obj/item/weapon/ore, input.loc) + if (istype(O,/obj/item/weapon/ore/iron)) + var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(output)) + M.amount = 1 + qdel(O) + if (istype(O,/obj/item/weapon/ore/diamond)) + new /obj/item/stack/sheet/mineral/diamond(output.loc) + qdel(O) + if (istype(O,/obj/item/weapon/ore/plasma)) + new /obj/item/stack/sheet/mineral/plasma(output.loc) + qdel(O) + if (istype(O,/obj/item/weapon/ore/gold)) + new /obj/item/stack/sheet/mineral/gold(output.loc) + qdel(O) + if (istype(O,/obj/item/weapon/ore/silver)) + new /obj/item/stack/sheet/mineral/silver(output.loc) + qdel(O) + if (istype(O,/obj/item/weapon/ore/uranium)) + new /obj/item/weapon/ore/mineral/uranium(output.loc) + qdel(O) + /*if (istype(O,/obj/item/weapon/ore/adamantine)) + new /obj/item/weapon/ore/adamantine(output.loc) + qdel(O)*/ //Dunno what this area does so I'll keep it commented out for now -Durandan + processed++ + sleep(5); + processing = 0; + src.updateUsrDialog() + return + + +/obj/machinery/mineral/purifier/New() + ..() + spawn( 5 ) + for (var/dir in cardinal) + src.input = locate(/obj/machinery/mineral/input, get_step(src, dir)) + if(src.input) break + for (var/dir in cardinal) + src.output = locate(/obj/machinery/mineral/output, get_step(src, dir)) + if(src.output) break + return + return diff --git a/code/unused/mining/mine_generator_unused.dm b/code/unused/mining/mine_generator_unused.dm index 5ca754dd143..965e398d0dd 100644 --- a/code/unused/mining/mine_generator_unused.dm +++ b/code/unused/mining/mine_generator_unused.dm @@ -1,175 +1,175 @@ -/**********************Random mine generator************************/ - -//this item is intended to give the effect of entering the mine, so that light gradually fades -/obj/effect/mine_generator - name = "Random mine generator" - anchored = 1 - unacidable = 1 - var/turf/last_loc - var/turf/target_loc - var/turf/start_loc - var/randXParam //the value of these two parameters are generated by the code itself and used to - var/randYParam //determine the random XY parameters - var/mineDirection = 3 - /* - 0 = none - 1 = N - 2 = NNW - 3 = NW - 4 = WNW - 5 = W - 6 = WSW - 7 = SW - 8 = SSW - 9 = S - 10 = SSE - 11 = SE - 12 = ESE - 13 = E - 14 = ENE - 15 = NE - 16 = NNE - */ - -/obj/effect/mine_generator/New() - last_loc = src.loc - var/i - for(i = 0; i < 50; i++) - gererateTargetLoc() - //target_loc = locate(last_loc.x + rand(5), last_loc.y + rand(5), src.z) - fillWithAsteroids() - del(src) - return - - -/obj/effect/mine_generator/proc/gererateTargetLoc() //this proc determines where the next square-room will end. - switch(mineDirection) - if(1) - randXParam = 0 - randYParam = 4 - if(2) - randXParam = 1 - randYParam = 3 - if(3) - randXParam = 2 - randYParam = 2 - if(4) - randXParam = 3 - randYParam = 1 - if(5) - randXParam = 4 - randYParam = 0 - if(6) - randXParam = 3 - randYParam = -1 - if(7) - randXParam = 2 - randYParam = -2 - if(8) - randXParam = 1 - randYParam = -3 - if(9) - randXParam = 0 - randYParam = -4 - if(10) - randXParam = -1 - randYParam = -3 - if(11) - randXParam = -2 - randYParam = -2 - if(12) - randXParam = -3 - randYParam = -1 - if(13) - randXParam = -4 - randYParam = 0 - if(14) - randXParam = -3 - randYParam = 1 - if(15) - randXParam = -2 - randYParam = 2 - if(16) - randXParam = -1 - randYParam = 3 - target_loc = last_loc - if (randXParam > 0) - target_loc = locate(target_loc.x+rand(randXParam),target_loc.y,src.z) - if (randYParam > 0) - target_loc = locate(target_loc.x,target_loc.y+rand(randYParam),src.z) - if (randXParam < 0) - target_loc = locate(target_loc.x-rand(-randXParam),target_loc.y,src.z) - if (randYParam < 0) - target_loc = locate(target_loc.x,target_loc.y-rand(-randXParam),src.z) - if (mineDirection == 1 || mineDirection == 5 || mineDirection == 9 || mineDirection == 13) //if N,S,E,W, turn quickly - if(prob(50)) - mineDirection += 2 - else - mineDirection -= 2 - if(mineDirection < 1) - mineDirection += 16 - else - if(prob(50)) - if(prob(50)) - mineDirection += 1 - else - mineDirection -= 1 - if(mineDirection < 1) - mineDirection += 16 - return - - -/obj/effect/mine_generator/proc/fillWithAsteroids() - - - if(last_loc) - start_loc = last_loc - - if(start_loc && target_loc) - var/x1 - var/y1 - - var/turf/line_start = start_loc - var/turf/column = line_start - - if(start_loc.x <= target_loc.x) - if(start_loc.y <= target_loc.y) //GOING NORTH-EAST - for(y1 = start_loc.y; y1 <= target_loc.y; y1++) - for(x1 = start_loc.x; x1 <= target_loc.x; x1++) - new/turf/simulated/floor/plating/airless/asteroid(column) - column = get_step(column,EAST) - line_start = get_step(line_start,NORTH) - column = line_start - last_loc = target_loc - return - else //GOING NORTH-WEST - for(y1 = start_loc.y; y1 >= target_loc.y; y1--) - for(x1 = start_loc.x; x1 <= target_loc.x; x1++) - new/turf/simulated/floor/plating/airless/asteroid(column) - column = get_step(column,WEST) - line_start = get_step(line_start,NORTH) - column = line_start - last_loc = target_loc - return - else - if(start_loc.y <= target_loc.y) //GOING SOUTH-EAST - for(y1 = start_loc.y; y1 <= target_loc.y; y1++) - for(x1 = start_loc.x; x1 >= target_loc.x; x1--) - new/turf/simulated/floor/plating/airless/asteroid(column) - column = get_step(column,EAST) - line_start = get_step(line_start,SOUTH) - column = line_start - last_loc = target_loc - return - else //GOING SOUTH-WEST - for(y1 = start_loc.y; y1 >= target_loc.y; y1--) - for(x1 = start_loc.x; x1 >= target_loc.x; x1--) - new/turf/simulated/floor/plating/airless/asteroid(column) - column = get_step(column,WEST) - line_start = get_step(line_start,SOUTH) - column = line_start - last_loc = target_loc - return - - +/**********************Random mine generator************************/ + +//this item is intended to give the effect of entering the mine, so that light gradually fades +/obj/effect/mine_generator + name = "Random mine generator" + anchored = 1 + unacidable = 1 + var/turf/last_loc + var/turf/target_loc + var/turf/start_loc + var/randXParam //the value of these two parameters are generated by the code itself and used to + var/randYParam //determine the random XY parameters + var/mineDirection = 3 + /* + 0 = none + 1 = N + 2 = NNW + 3 = NW + 4 = WNW + 5 = W + 6 = WSW + 7 = SW + 8 = SSW + 9 = S + 10 = SSE + 11 = SE + 12 = ESE + 13 = E + 14 = ENE + 15 = NE + 16 = NNE + */ + +/obj/effect/mine_generator/New() + last_loc = src.loc + var/i + for(i = 0; i < 50; i++) + gererateTargetLoc() + //target_loc = locate(last_loc.x + rand(5), last_loc.y + rand(5), src.z) + fillWithAsteroids() + del(src) + return + + +/obj/effect/mine_generator/proc/gererateTargetLoc() //this proc determines where the next square-room will end. + switch(mineDirection) + if(1) + randXParam = 0 + randYParam = 4 + if(2) + randXParam = 1 + randYParam = 3 + if(3) + randXParam = 2 + randYParam = 2 + if(4) + randXParam = 3 + randYParam = 1 + if(5) + randXParam = 4 + randYParam = 0 + if(6) + randXParam = 3 + randYParam = -1 + if(7) + randXParam = 2 + randYParam = -2 + if(8) + randXParam = 1 + randYParam = -3 + if(9) + randXParam = 0 + randYParam = -4 + if(10) + randXParam = -1 + randYParam = -3 + if(11) + randXParam = -2 + randYParam = -2 + if(12) + randXParam = -3 + randYParam = -1 + if(13) + randXParam = -4 + randYParam = 0 + if(14) + randXParam = -3 + randYParam = 1 + if(15) + randXParam = -2 + randYParam = 2 + if(16) + randXParam = -1 + randYParam = 3 + target_loc = last_loc + if (randXParam > 0) + target_loc = locate(target_loc.x+rand(randXParam),target_loc.y,src.z) + if (randYParam > 0) + target_loc = locate(target_loc.x,target_loc.y+rand(randYParam),src.z) + if (randXParam < 0) + target_loc = locate(target_loc.x-rand(-randXParam),target_loc.y,src.z) + if (randYParam < 0) + target_loc = locate(target_loc.x,target_loc.y-rand(-randXParam),src.z) + if (mineDirection == 1 || mineDirection == 5 || mineDirection == 9 || mineDirection == 13) //if N,S,E,W, turn quickly + if(prob(50)) + mineDirection += 2 + else + mineDirection -= 2 + if(mineDirection < 1) + mineDirection += 16 + else + if(prob(50)) + if(prob(50)) + mineDirection += 1 + else + mineDirection -= 1 + if(mineDirection < 1) + mineDirection += 16 + return + + +/obj/effect/mine_generator/proc/fillWithAsteroids() + + + if(last_loc) + start_loc = last_loc + + if(start_loc && target_loc) + var/x1 + var/y1 + + var/turf/line_start = start_loc + var/turf/column = line_start + + if(start_loc.x <= target_loc.x) + if(start_loc.y <= target_loc.y) //GOING NORTH-EAST + for(y1 = start_loc.y; y1 <= target_loc.y; y1++) + for(x1 = start_loc.x; x1 <= target_loc.x; x1++) + new/turf/simulated/floor/plating/airless/asteroid(column) + column = get_step(column,EAST) + line_start = get_step(line_start,NORTH) + column = line_start + last_loc = target_loc + return + else //GOING NORTH-WEST + for(y1 = start_loc.y; y1 >= target_loc.y; y1--) + for(x1 = start_loc.x; x1 <= target_loc.x; x1++) + new/turf/simulated/floor/plating/airless/asteroid(column) + column = get_step(column,WEST) + line_start = get_step(line_start,NORTH) + column = line_start + last_loc = target_loc + return + else + if(start_loc.y <= target_loc.y) //GOING SOUTH-EAST + for(y1 = start_loc.y; y1 <= target_loc.y; y1++) + for(x1 = start_loc.x; x1 >= target_loc.x; x1--) + new/turf/simulated/floor/plating/airless/asteroid(column) + column = get_step(column,EAST) + line_start = get_step(line_start,SOUTH) + column = line_start + last_loc = target_loc + return + else //GOING SOUTH-WEST + for(y1 = start_loc.y; y1 >= target_loc.y; y1--) + for(x1 = start_loc.x; x1 >= target_loc.x; x1--) + new/turf/simulated/floor/plating/airless/asteroid(column) + column = get_step(column,WEST) + line_start = get_step(line_start,SOUTH) + column = line_start + last_loc = target_loc + return + + return \ No newline at end of file diff --git a/code/unused/mining/rail_unused.dm b/code/unused/mining/rail_unused.dm index 5c6a2456c7c..9c1a57a925b 100644 --- a/code/unused/mining/rail_unused.dm +++ b/code/unused/mining/rail_unused.dm @@ -1,339 +1,339 @@ -/**********************Rail track**************************/ - -/obj/machinery/rail_track - name = "Rail track" - icon = 'icons/obj/mining.dmi' - icon_state = "rail" - dir = 2 - var/id = null //this is needed for switches to work Set to the same on the whole length of the track - anchored = 1 - -/**********************Rail intersection**************************/ - -/obj/machinery/rail_track/intersections - name = "Rail track intersection" - icon_state = "rail_intersection" - -/obj/machinery/rail_track/intersections/attack_hand(user as mob) - switch (dir) - if (1) dir = 5 - if (5) dir = 4 - if (4) dir = 9 - if (9) dir = 2 - if (2) dir = 10 - if (10) dir = 8 - if (8) dir = 6 - if (6) dir = 1 - return - -/obj/machinery/rail_track/intersections/NSE - name = "Rail track T intersection" - icon_state = "rail_intersection_NSE" - dir = 2 - -/obj/machinery/rail_track/intersections/NSE/attack_hand(user as mob) - switch (dir) - if (1) dir = 5 - if (2) dir = 5 - if (5) dir = 9 - if (9) dir = 2 - return - -/obj/machinery/rail_track/intersections/SEW - name = "Rail track T intersection" - icon_state = "rail_intersection_SEW" - dir = 8 - -/obj/machinery/rail_track/intersections/SEW/attack_hand(user as mob) - switch (dir) - if (8) dir = 6 - if (4) dir = 6 - if (6) dir = 5 - if (5) dir = 8 - return - -/obj/machinery/rail_track/intersections/NSW - name = "Rail track T intersection" - icon_state = "rail_intersection_NSW" - dir = 2 - -/obj/machinery/rail_track/intersections/NSW/attack_hand(user as mob) - switch (dir) - if (1) dir = 10 - if (2) dir = 10 - if (10) dir = 6 - if (6) dir = 2 - return - -/obj/machinery/rail_track/intersections/NEW - name = "Rail track T intersection" - icon_state = "rail_intersection_NEW" - dir = 8 - -/obj/machinery/rail_track/intersections/NEW/attack_hand(user as mob) - switch (dir) - if (4) dir = 9 - if (8) dir = 9 - if (9) dir = 10 - if (10) dir = 8 - return - -/**********************Rail switch**************************/ - -/obj/machinery/rail_switch - name = "Rail switch" - icon = 'icons/obj/mining.dmi' - icon_state = "rail" - dir = 2 - icon = 'icons/obj/recycling.dmi' - icon_state = "switch-off" - var/obj/machinery/rail_track/track = null - var/id //used for to change the track pieces - -/obj/machinery/rail_switch/New() - spawn(10) - src.track = locate(/obj/machinery/rail_track, get_step(src, NORTH)) - if(track) - id = track.id - return - -/obj/machinery/rail_switch/attack_hand(user as mob) +/**********************Rail track**************************/ + +/obj/machinery/rail_track + name = "Rail track" + icon = 'icons/obj/mining.dmi' + icon_state = "rail" + dir = 2 + var/id = null //this is needed for switches to work Set to the same on the whole length of the track + anchored = 1 + +/**********************Rail intersection**************************/ + +/obj/machinery/rail_track/intersections + name = "Rail track intersection" + icon_state = "rail_intersection" + +/obj/machinery/rail_track/intersections/attack_hand(user as mob) + switch (dir) + if (1) dir = 5 + if (5) dir = 4 + if (4) dir = 9 + if (9) dir = 2 + if (2) dir = 10 + if (10) dir = 8 + if (8) dir = 6 + if (6) dir = 1 + return + +/obj/machinery/rail_track/intersections/NSE + name = "Rail track T intersection" + icon_state = "rail_intersection_NSE" + dir = 2 + +/obj/machinery/rail_track/intersections/NSE/attack_hand(user as mob) + switch (dir) + if (1) dir = 5 + if (2) dir = 5 + if (5) dir = 9 + if (9) dir = 2 + return + +/obj/machinery/rail_track/intersections/SEW + name = "Rail track T intersection" + icon_state = "rail_intersection_SEW" + dir = 8 + +/obj/machinery/rail_track/intersections/SEW/attack_hand(user as mob) + switch (dir) + if (8) dir = 6 + if (4) dir = 6 + if (6) dir = 5 + if (5) dir = 8 + return + +/obj/machinery/rail_track/intersections/NSW + name = "Rail track T intersection" + icon_state = "rail_intersection_NSW" + dir = 2 + +/obj/machinery/rail_track/intersections/NSW/attack_hand(user as mob) + switch (dir) + if (1) dir = 10 + if (2) dir = 10 + if (10) dir = 6 + if (6) dir = 2 + return + +/obj/machinery/rail_track/intersections/NEW + name = "Rail track T intersection" + icon_state = "rail_intersection_NEW" + dir = 8 + +/obj/machinery/rail_track/intersections/NEW/attack_hand(user as mob) + switch (dir) + if (4) dir = 9 + if (8) dir = 9 + if (9) dir = 10 + if (10) dir = 8 + return + +/**********************Rail switch**************************/ + +/obj/machinery/rail_switch + name = "Rail switch" + icon = 'icons/obj/mining.dmi' + icon_state = "rail" + dir = 2 + icon = 'icons/obj/recycling.dmi' + icon_state = "switch-off" + var/obj/machinery/rail_track/track = null + var/id //used for to change the track pieces + +/obj/machinery/rail_switch/New() + spawn(10) + src.track = locate(/obj/machinery/rail_track, get_step(src, NORTH)) + if(track) + id = track.id + return + +/obj/machinery/rail_switch/attack_hand(user as mob) to_chat(user, "You switch the rail track's direction") - for (var/obj/machinery/rail_track/T in machines) - if (T.id == src.id) - var/obj/machinery/rail_car/C = locate(/obj/machinery/rail_car, T.loc) - if (C) - switch (T.dir) - if(1) - switch(C.direction) - if("N") C.direction = "S" - if("S") C.direction = "N" - if("E") C.direction = "S" - if("W") C.direction = "S" - if(2) - switch(C.direction) - if("N") C.direction = "S" - if("S") C.direction = "N" - if("E") C.direction = "S" - if("W") C.direction = "S" - if(4) - switch(C.direction) - if("N") C.direction = "E" - if("S") C.direction = "E" - if("E") C.direction = "W" - if("W") C.direction = "E" - if(8) - switch(C.direction) - if("N") C.direction = "E" - if("S") C.direction = "E" - if("E") C.direction = "W" - if("W") C.direction = "E" - if(5) - switch(C.direction) - if("N") C.direction = "S" - if("S") C.direction = "E" - if("E") C.direction = "S" - if("W") C.direction = "S" - if(6) - switch(C.direction) - if("N") C.direction = "S" - if("S") C.direction = "W" - if("E") C.direction = "S" - if("W") C.direction = "S" - if(9) - switch(C.direction) - if("N") C.direction = "E" - if("S") C.direction = "E" - if("E") C.direction = "N" - if("W") C.direction = "E" - if(10) - switch(C.direction) - if("N") C.direction = "W" - if("S") C.direction = "W" - if("E") C.direction = "W" - if("W") C.direction = "N" - return - -/**********************Rail car**************************/ - -/obj/machinery/rail_car - name = "Rail car" - icon = 'icons/obj/storage.dmi' - icon_state = "miningcar" - var/direction = "S" //S = south, N = north, E = east, W = west. Determines whichw ay it'll look first - var/moving = 0; - anchored = 1 - density = 1 - var/speed = 0 - var/slowing = 0 - var/atom/movable/load = null //what it's carrying - -/obj/machinery/rail_car/attack_hand(user as mob) - if (moving == 0) - processing_items.Add(src) - moving = 1 - else - processing_items.Remove(src) - moving = 0 - return - -/* -for (var/client/C) + for (var/obj/machinery/rail_track/T in machines) + if (T.id == src.id) + var/obj/machinery/rail_car/C = locate(/obj/machinery/rail_car, T.loc) + if (C) + switch (T.dir) + if(1) + switch(C.direction) + if("N") C.direction = "S" + if("S") C.direction = "N" + if("E") C.direction = "S" + if("W") C.direction = "S" + if(2) + switch(C.direction) + if("N") C.direction = "S" + if("S") C.direction = "N" + if("E") C.direction = "S" + if("W") C.direction = "S" + if(4) + switch(C.direction) + if("N") C.direction = "E" + if("S") C.direction = "E" + if("E") C.direction = "W" + if("W") C.direction = "E" + if(8) + switch(C.direction) + if("N") C.direction = "E" + if("S") C.direction = "E" + if("E") C.direction = "W" + if("W") C.direction = "E" + if(5) + switch(C.direction) + if("N") C.direction = "S" + if("S") C.direction = "E" + if("E") C.direction = "S" + if("W") C.direction = "S" + if(6) + switch(C.direction) + if("N") C.direction = "S" + if("S") C.direction = "W" + if("E") C.direction = "S" + if("W") C.direction = "S" + if(9) + switch(C.direction) + if("N") C.direction = "E" + if("S") C.direction = "E" + if("E") C.direction = "N" + if("W") C.direction = "E" + if(10) + switch(C.direction) + if("N") C.direction = "W" + if("S") C.direction = "W" + if("E") C.direction = "W" + if("W") C.direction = "N" + return + +/**********************Rail car**************************/ + +/obj/machinery/rail_car + name = "Rail car" + icon = 'icons/obj/storage.dmi' + icon_state = "miningcar" + var/direction = "S" //S = south, N = north, E = east, W = west. Determines whichw ay it'll look first + var/moving = 0; + anchored = 1 + density = 1 + var/speed = 0 + var/slowing = 0 + var/atom/movable/load = null //what it's carrying + +/obj/machinery/rail_car/attack_hand(user as mob) + if (moving == 0) + processing_items.Add(src) + moving = 1 + else + processing_items.Remove(src) + moving = 0 + return + +/* +for (var/client/C) to_chat(C, "Dela.") -*/ - -/obj/machinery/rail_car/MouseDrop_T(var/atom/movable/C, mob/user) - - if(user.stat) - return - - if (!istype(C) || C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 ) - return - - if(ismob(C)) - load(C) - - -/obj/machinery/rail_car/proc/load(var/atom/movable/C) - - - if(get_dist(C, src) > 1) - return - //mode = 1 - - C.loc = src.loc - sleep(2) - C.loc = src - load = C - - C.pixel_y += 9 - if(C.layer < layer) - C.layer = layer + 0.1 - overlays += C - - if(ismob(C)) - var/mob/M = C - if(M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - - //mode = 0 - //send_status() - -/obj/machinery/rail_car/proc/unload(var/dirn = 0) - if(!load) - return - - overlays.len = 0 - - load.loc = src.loc - load.pixel_y -= 9 - load.layer = initial(load.layer) - if(ismob(load)) - var/mob/M = load - if(M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = src - - - if(dirn) - step(load, dirn) - - load = null - - // in case non-load items end up in contents, dump every else too - // this seems to happen sometimes due to race conditions - // with items dropping as mobs are loaded - - for(var/atom/movable/AM in src) - AM.loc = src.loc - AM.layer = initial(AM.layer) - AM.pixel_y = initial(AM.pixel_y) - if(ismob(AM)) - var/mob/M = AM - if(M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = src - -/obj/machinery/rail_car/relaymove(var/mob/user) - if(user.stat) - return - if(load == user) - unload(0) - return - -/obj/machinery/rail_car/process() - if (moving == 1) - if (slowing == 1) - if (speed > 0) - speed--; - if (speed == 0) - slowing = 0 - else - if (speed < 10) - speed++; - var/i = 0 - for (i = 0; i < speed; i++) - if (moving == 1) - switch (direction) - if ("S") - for (var/obj/machinery/rail_track/R in locate(src.x,src.y-1,src.z)) - if (R.dir == 10) - direction = "W" - if (R.dir == 9) - direction = "E" - if (R.dir == 2 || R.dir == 1 || R.dir == 10 || R.dir == 9) - for (var/mob/living/M in locate(src.x,src.y-1,src.z)) - step(M,get_dir(src,R)) - step(src,get_dir(src,R)) - break - else - moving = 0 - speed = 0 - if ("N") - for (var/obj/machinery/rail_track/R in locate(src.x,src.y+1,src.z)) - if (R.dir == 5) - direction = "E" - if (R.dir == 6) - direction = "W" - if (R.dir == 5 || R.dir == 1 || R.dir == 6 || R.dir == 2) - for (var/mob/living/M in locate(src.x,src.y+1,src.z)) - step(M,get_dir(src,R)) - step(src,get_dir(src,R)) - break - else - moving = 0 - speed = 0 - if ("E") - for (var/obj/machinery/rail_track/R in locate(src.x+1,src.y,src.z)) - if (R.dir == 6) - direction = "S" - if (R.dir == 10) - direction = "N" - if (R.dir == 4 || R.dir == 8 || R.dir == 10 || R.dir == 6) - for (var/mob/living/M in locate(src.x+1,src.y,src.z)) - step(M,get_dir(src,R)) - step(src,get_dir(src,R)) - break - else - moving = 0 - speed = 0 - if ("W") - for (var/obj/machinery/rail_track/R in locate(src.x-1,src.y,src.z)) - if (R.dir == 9) - direction = "N" - if (R.dir == 5) - direction = "S" - if (R.dir == 8 || R.dir == 9 || R.dir == 5 || R.dir == 4) - for (var/mob/living/M in locate(src.x-1,src.y,src.z)) - step(M,get_dir(src,R)) - step(src,get_dir(src,R)) - break - else - moving = 0 - speed = 0 - sleep(1) - else - processing_items.Remove(src) - moving = 0 +*/ + +/obj/machinery/rail_car/MouseDrop_T(var/atom/movable/C, mob/user) + + if(user.stat) + return + + if (!istype(C) || C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 ) + return + + if(ismob(C)) + load(C) + + +/obj/machinery/rail_car/proc/load(var/atom/movable/C) + + + if(get_dist(C, src) > 1) + return + //mode = 1 + + C.loc = src.loc + sleep(2) + C.loc = src + load = C + + C.pixel_y += 9 + if(C.layer < layer) + C.layer = layer + 0.1 + overlays += C + + if(ismob(C)) + var/mob/M = C + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + + //mode = 0 + //send_status() + +/obj/machinery/rail_car/proc/unload(var/dirn = 0) + if(!load) + return + + overlays.len = 0 + + load.loc = src.loc + load.pixel_y -= 9 + load.layer = initial(load.layer) + if(ismob(load)) + var/mob/M = load + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + + + if(dirn) + step(load, dirn) + + load = null + + // in case non-load items end up in contents, dump every else too + // this seems to happen sometimes due to race conditions + // with items dropping as mobs are loaded + + for(var/atom/movable/AM in src) + AM.loc = src.loc + AM.layer = initial(AM.layer) + AM.pixel_y = initial(AM.pixel_y) + if(ismob(AM)) + var/mob/M = AM + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + +/obj/machinery/rail_car/relaymove(var/mob/user) + if(user.stat) + return + if(load == user) + unload(0) + return + +/obj/machinery/rail_car/process() + if (moving == 1) + if (slowing == 1) + if (speed > 0) + speed--; + if (speed == 0) + slowing = 0 + else + if (speed < 10) + speed++; + var/i = 0 + for (i = 0; i < speed; i++) + if (moving == 1) + switch (direction) + if ("S") + for (var/obj/machinery/rail_track/R in locate(src.x,src.y-1,src.z)) + if (R.dir == 10) + direction = "W" + if (R.dir == 9) + direction = "E" + if (R.dir == 2 || R.dir == 1 || R.dir == 10 || R.dir == 9) + for (var/mob/living/M in locate(src.x,src.y-1,src.z)) + step(M,get_dir(src,R)) + step(src,get_dir(src,R)) + break + else + moving = 0 + speed = 0 + if ("N") + for (var/obj/machinery/rail_track/R in locate(src.x,src.y+1,src.z)) + if (R.dir == 5) + direction = "E" + if (R.dir == 6) + direction = "W" + if (R.dir == 5 || R.dir == 1 || R.dir == 6 || R.dir == 2) + for (var/mob/living/M in locate(src.x,src.y+1,src.z)) + step(M,get_dir(src,R)) + step(src,get_dir(src,R)) + break + else + moving = 0 + speed = 0 + if ("E") + for (var/obj/machinery/rail_track/R in locate(src.x+1,src.y,src.z)) + if (R.dir == 6) + direction = "S" + if (R.dir == 10) + direction = "N" + if (R.dir == 4 || R.dir == 8 || R.dir == 10 || R.dir == 6) + for (var/mob/living/M in locate(src.x+1,src.y,src.z)) + step(M,get_dir(src,R)) + step(src,get_dir(src,R)) + break + else + moving = 0 + speed = 0 + if ("W") + for (var/obj/machinery/rail_track/R in locate(src.x-1,src.y,src.z)) + if (R.dir == 9) + direction = "N" + if (R.dir == 5) + direction = "S" + if (R.dir == 8 || R.dir == 9 || R.dir == 5 || R.dir == 4) + for (var/mob/living/M in locate(src.x-1,src.y,src.z)) + step(M,get_dir(src,R)) + step(src,get_dir(src,R)) + break + else + moving = 0 + speed = 0 + sleep(1) + else + processing_items.Remove(src) + moving = 0 return \ No newline at end of file diff --git a/code/unused/optics/beam.dm b/code/unused/optics/beam.dm index 63bff415375..14e52c5d0fc 100644 --- a/code/unused/optics/beam.dm +++ b/code/unused/optics/beam.dm @@ -1,179 +1,179 @@ -// the laser beam - - -/obj/effect/beam/laser - name = "laser beam" - icon = 'icons/effects/beam.dmi' - icon_state = "full" - density = 0 - mouse_opacity = 0 - pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE - flags = TABLEPASS - var/wavelength // the (vaccuum) wavelength of the beam - var/width = 1 // 1=thin, 2=medium, 3=wide - - var/obj/effect/beam/laser/next - var/obj/effect/beam/laser/prev - var/obj/master - - New(var/atom/newloc, var/dirn, var/lambda, var/omega=1, var/half=0) - - if(!isturf(loc)) - return - +// the laser beam + + +/obj/effect/beam/laser + name = "laser beam" + icon = 'icons/effects/beam.dmi' + icon_state = "full" + density = 0 + mouse_opacity = 0 + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + flags = TABLEPASS + var/wavelength // the (vaccuum) wavelength of the beam + var/width = 1 // 1=thin, 2=medium, 3=wide + + var/obj/effect/beam/laser/next + var/obj/effect/beam/laser/prev + var/obj/master + + New(var/atom/newloc, var/dirn, var/lambda, var/omega=1, var/half=0) + + if(!isturf(loc)) + return + // to_chat(world, "creating beam at ([newloc.x],[newloc.y]) with [dirn] [lambda] [omega] [half]") - - icon_state = "[omega]-[half ? "half" : "full"]" - dir = dirn - set_wavelength(lambda) - ..(newloc) - spawn(0) - src.propagate() - src.verbs -= /atom/movable/verb/pull - - - - proc/propagate() - var/turf/T = get_step(src, dir) - if(T) - if(T.Enter(src)) - next = new(T, dir, wavelength, width, 0) - next.prev = src - next.master = src.master - else - spawn(5) - propagate() - - - proc/remove() - if(next) - next.remove() - del(src) - - - - proc/blocked(var/atom/A) - return density || opacity -/* -/turf/Enter(atom/movable/mover as mob|obj) - if (!mover || !isturf(mover.loc)) - return 1 - - - //First, check objects to block exit that are not on the border - for(var/obj/obstacle in mover.loc) - if((obstacle.flags & ~ON_BORDER) && (mover != obstacle) && (forget != obstacle)) - if(!obstacle.CheckExit(mover, src)) - mover.Bump(obstacle, 1) - return 0 - - //Now, check objects to block exit that are on the border - for(var/obj/border_obstacle in mover.loc) - if((border_obstacle.flags & ON_BORDER) && (mover != border_obstacle) && (forget != border_obstacle)) - if(!border_obstacle.CheckExit(mover, src)) - mover.Bump(border_obstacle, 1) - return 0 - - //Next, check objects to block entry that are on the border - for(var/obj/border_obstacle in src) - if(border_obstacle.flags & ON_BORDER) - if(!border_obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != border_obstacle)) - mover.Bump(border_obstacle, 1) - return 0 - - //Then, check the turf itself - if (!src.CanPass(mover, src)) - mover.Bump(src, 1) - return 0 - - //Finally, check objects/mobs to block entry that are not on the border - for(var/atom/movable/obstacle in src) - if(obstacle.flags & ~ON_BORDER) - if(!obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != obstacle)) - mover.Bump(obstacle, 1) - return 0 - return 1 //Nothing found to block so return success! -*/ - - - HasEntered(var/atom/movable/AM) - if(istype(AM, /obj/effect/beam)) - return - if(blocked(AM)) - remove(src) - if(prev) - prev.propagate() - else if(master) - master:turn_on() - - proc/set_wavelength(var/lambda) - - - var/w = round(lambda,1) // integer wavelength - wavelength = lambda - // first look for cached version of the icon at this wavelength - var/icon/cached = beam_icons["[w]"] - if(cached) - icon = cached - - return - - // no cached version, so generate a new one - - // this maps a wavelength in the range 380-780 nm to an R,G,B,A value - var/red = 0 - var/green = 0 - var/blue = 0 - var/alpha = 0 - - switch(w) - if(380 to 439) - red = (440-w) / 60 - green = 0 - blue = 1 - if(440 to 489) - red = 0 - green = (w-440) / 50 - blue = 1 - if(490 to 509) - red = 0 - green = 1 - blue = (510 - w) / 20 - if(510 to 579) - red = (w-510) / 70 - green = 1 - blue = 0 - if(580 to 644) - red = 1 - green = (645-w) / 65 - blue = 0 - if(645 to 780) - red = 1 - green = 0 - blue = 0 - - // colour is done, now calculate intensity - switch(w) - if(380 to 419) - alpha = 0.75*(w-380)/40 - if(420 to 700) - alpha = 0.75 - if(701 to 780) - alpha = 0.75*(780-w)/80 - - // remap alpha by intensity gamma - if(alpha != 0) - alpha = alpha**0.80 - - var/icon/I = icon('icons/effects/beam.dmi') - I.MapColors(red,0,0,0, 0,green,0,0, 0,0,blue,0, 0,0,0,alpha, 0,0,0,0) - icon = I - - beam_icons["[w]"] = I - - - -// global cache of beam icons -// this is an assoc list mapping (integer) wavelength to icons - + + icon_state = "[omega]-[half ? "half" : "full"]" + dir = dirn + set_wavelength(lambda) + ..(newloc) + spawn(0) + src.propagate() + src.verbs -= /atom/movable/verb/pull + + + + proc/propagate() + var/turf/T = get_step(src, dir) + if(T) + if(T.Enter(src)) + next = new(T, dir, wavelength, width, 0) + next.prev = src + next.master = src.master + else + spawn(5) + propagate() + + + proc/remove() + if(next) + next.remove() + del(src) + + + + proc/blocked(var/atom/A) + return density || opacity +/* +/turf/Enter(atom/movable/mover as mob|obj) + if (!mover || !isturf(mover.loc)) + return 1 + + + //First, check objects to block exit that are not on the border + for(var/obj/obstacle in mover.loc) + if((obstacle.flags & ~ON_BORDER) && (mover != obstacle) && (forget != obstacle)) + if(!obstacle.CheckExit(mover, src)) + mover.Bump(obstacle, 1) + return 0 + + //Now, check objects to block exit that are on the border + for(var/obj/border_obstacle in mover.loc) + if((border_obstacle.flags & ON_BORDER) && (mover != border_obstacle) && (forget != border_obstacle)) + if(!border_obstacle.CheckExit(mover, src)) + mover.Bump(border_obstacle, 1) + return 0 + + //Next, check objects to block entry that are on the border + for(var/obj/border_obstacle in src) + if(border_obstacle.flags & ON_BORDER) + if(!border_obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != border_obstacle)) + mover.Bump(border_obstacle, 1) + return 0 + + //Then, check the turf itself + if (!src.CanPass(mover, src)) + mover.Bump(src, 1) + return 0 + + //Finally, check objects/mobs to block entry that are not on the border + for(var/atom/movable/obstacle in src) + if(obstacle.flags & ~ON_BORDER) + if(!obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != obstacle)) + mover.Bump(obstacle, 1) + return 0 + return 1 //Nothing found to block so return success! +*/ + + + HasEntered(var/atom/movable/AM) + if(istype(AM, /obj/effect/beam)) + return + if(blocked(AM)) + remove(src) + if(prev) + prev.propagate() + else if(master) + master:turn_on() + + proc/set_wavelength(var/lambda) + + + var/w = round(lambda,1) // integer wavelength + wavelength = lambda + // first look for cached version of the icon at this wavelength + var/icon/cached = beam_icons["[w]"] + if(cached) + icon = cached + + return + + // no cached version, so generate a new one + + // this maps a wavelength in the range 380-780 nm to an R,G,B,A value + var/red = 0 + var/green = 0 + var/blue = 0 + var/alpha = 0 + + switch(w) + if(380 to 439) + red = (440-w) / 60 + green = 0 + blue = 1 + if(440 to 489) + red = 0 + green = (w-440) / 50 + blue = 1 + if(490 to 509) + red = 0 + green = 1 + blue = (510 - w) / 20 + if(510 to 579) + red = (w-510) / 70 + green = 1 + blue = 0 + if(580 to 644) + red = 1 + green = (645-w) / 65 + blue = 0 + if(645 to 780) + red = 1 + green = 0 + blue = 0 + + // colour is done, now calculate intensity + switch(w) + if(380 to 419) + alpha = 0.75*(w-380)/40 + if(420 to 700) + alpha = 0.75 + if(701 to 780) + alpha = 0.75*(780-w)/80 + + // remap alpha by intensity gamma + if(alpha != 0) + alpha = alpha**0.80 + + var/icon/I = icon('icons/effects/beam.dmi') + I.MapColors(red,0,0,0, 0,green,0,0, 0,0,blue,0, 0,0,0,alpha, 0,0,0,0) + icon = I + + beam_icons["[w]"] = I + + + +// global cache of beam icons +// this is an assoc list mapping (integer) wavelength to icons + var/list/beam_icons = new() \ No newline at end of file diff --git a/code/unused/optics/laser-pointer.dm b/code/unused/optics/laser-pointer.dm index 8838e2d3bfa..d8fa59dc32b 100644 --- a/code/unused/optics/laser-pointer.dm +++ b/code/unused/optics/laser-pointer.dm @@ -1,73 +1,73 @@ -// A laser pointer. Emits a (tunable) low-power laser beam -// Used for alignment and testing of the optics system - -/obj/item/device/laser_pointer - name = "laser pointer" - desc = "A portable low-power laser used for optical system alignment. The label reads: 'Danger: Class IIIa laser device. Avoid direct eye exposure." - icon = 'optics.dmi' - icon_state = "pointer0" - var/on = 0 // true if operating - var/wavelength = 632 // operation wavelength (nm) - - var/gain_peak = 632 // gain peak (nm) - var/gain_width = 35 // gain bandwidth (nm) - var/peak_output = 0.005 // max output 5 mW - layer = OBJ_LAYER + 0.1 - - w_class = 4 - m_amt = 500 - g_amt = 100 - w_amt = 200 - - var/obj/effect/beam/laser/beam // the created beam - - flags = FPRINT | CONDUCT | TABLEPASS - - attack_ai() - return - - attack_paw() - return - - attack_self(var/mob/user) - - - on = !on - if(on) - turn_on() - else - turn_off() - - updateicon() - - verb/rotate() - set name = "Rotate" - set src in view(1) - turn_off() - dir = turn(dir, -90) - if(on) turn_on() - - Move(var/atom/newloc,var/newdir) - . = ..(newloc,newdir) - if(on && . && isturf(newloc)) - turn_off() - turn_on() - return . - - proc/turn_on() - if(!isturf(loc)) - return - - beam = new(loc, dir, wavelength, 1, 1) - beam.master = src - - proc/turn_off() - if(beam) - beam.remove() - - dropped() - turn_off() - turn_on() - - proc/updateicon() +// A laser pointer. Emits a (tunable) low-power laser beam +// Used for alignment and testing of the optics system + +/obj/item/device/laser_pointer + name = "laser pointer" + desc = "A portable low-power laser used for optical system alignment. The label reads: 'Danger: Class IIIa laser device. Avoid direct eye exposure." + icon = 'optics.dmi' + icon_state = "pointer0" + var/on = 0 // true if operating + var/wavelength = 632 // operation wavelength (nm) + + var/gain_peak = 632 // gain peak (nm) + var/gain_width = 35 // gain bandwidth (nm) + var/peak_output = 0.005 // max output 5 mW + layer = OBJ_LAYER + 0.1 + + w_class = 4 + m_amt = 500 + g_amt = 100 + w_amt = 200 + + var/obj/effect/beam/laser/beam // the created beam + + flags = FPRINT | CONDUCT | TABLEPASS + + attack_ai() + return + + attack_paw() + return + + attack_self(var/mob/user) + + + on = !on + if(on) + turn_on() + else + turn_off() + + updateicon() + + verb/rotate() + set name = "Rotate" + set src in view(1) + turn_off() + dir = turn(dir, -90) + if(on) turn_on() + + Move(var/atom/newloc,var/newdir) + . = ..(newloc,newdir) + if(on && . && isturf(newloc)) + turn_off() + turn_on() + return . + + proc/turn_on() + if(!isturf(loc)) + return + + beam = new(loc, dir, wavelength, 1, 1) + beam.master = src + + proc/turn_off() + if(beam) + beam.remove() + + dropped() + turn_off() + turn_on() + + proc/updateicon() icon_state = "pointer[on]" \ No newline at end of file diff --git a/code/unused/optics/mirror.dm b/code/unused/optics/mirror.dm index c50d3efc044..aa4b987dce4 100644 --- a/code/unused/optics/mirror.dm +++ b/code/unused/optics/mirror.dm @@ -1,83 +1,83 @@ -// Mirror object -// Part of the optics system -// -// reflects laser beams -// 16 directional states 0/22.5/45/67.5deg to allow for 0/45deg beam angles - - -// ideas: -// frame/stand icon w/ mirror directional overlay -// two sets of overlay icons for 0/45 and 22.5/67.5 deg angles - -// can rotate cw/acw - need screwdriver to loosen/tighten mirror -// use wrench to anchor/unanchor frame -// if touched, gets dirty - fingerprints, which reduce reflectivity -// if dirty and hit with high-power beam, mirror may shatter -// some kind of dust accumulation with HasProximity? Could check for mob w/o labcoat etc. -// can clean with acetone+wipes - -/obj/optical/mirror - icon = 'optical.dmi' - icon_state = "mirrorA" - dir = 1 - desc = "A large, optical-grade mirror firmly mounted on a stand." - flags = FPRINT - anchored = 0 - var/rotatable = 0 // true if mirror can be rotated - var/angle = 0 // normal of mirror, 0-15. 0=N, 1=NNE, 2=NE, 3=ENE, 4=E etc - - - New() - ..() - set_angle() - - - - //set the angle from icon_state and dir - proc/set_angle() - switch(dir) - if(1) - angle = 0 - if(5) - angle = 2 - if(4) - angle = 4 - if(6) - angle = 6 - if(2) - angle = 8 - if(10) - angle = 10 - if(8) - angle = 12 - if(9) - angle = 14 - - if(icon_state == "mirrorB") // 22.5deg turned states - angle++ - return - - // set the dir and icon_state from the angle - proc/set_dir() - if(angle%2 == 1) - icon_state = "mirrorB" - else - icon_state = "mirrorA" - switch(round(angle/2)*2) - if(0) - dir = 1 - if(2) - dir = 5 - if(4) - dir = 4 - if(6) - dir = 6 - if(8) - dir = 2 - if(10) - dir = 10 - if(12) - dir = 8 - if(14) - dir = 9 +// Mirror object +// Part of the optics system +// +// reflects laser beams +// 16 directional states 0/22.5/45/67.5deg to allow for 0/45deg beam angles + + +// ideas: +// frame/stand icon w/ mirror directional overlay +// two sets of overlay icons for 0/45 and 22.5/67.5 deg angles + +// can rotate cw/acw - need screwdriver to loosen/tighten mirror +// use wrench to anchor/unanchor frame +// if touched, gets dirty - fingerprints, which reduce reflectivity +// if dirty and hit with high-power beam, mirror may shatter +// some kind of dust accumulation with HasProximity? Could check for mob w/o labcoat etc. +// can clean with acetone+wipes + +/obj/optical/mirror + icon = 'optical.dmi' + icon_state = "mirrorA" + dir = 1 + desc = "A large, optical-grade mirror firmly mounted on a stand." + flags = FPRINT + anchored = 0 + var/rotatable = 0 // true if mirror can be rotated + var/angle = 0 // normal of mirror, 0-15. 0=N, 1=NNE, 2=NE, 3=ENE, 4=E etc + + + New() + ..() + set_angle() + + + + //set the angle from icon_state and dir + proc/set_angle() + switch(dir) + if(1) + angle = 0 + if(5) + angle = 2 + if(4) + angle = 4 + if(6) + angle = 6 + if(2) + angle = 8 + if(10) + angle = 10 + if(8) + angle = 12 + if(9) + angle = 14 + + if(icon_state == "mirrorB") // 22.5deg turned states + angle++ + return + + // set the dir and icon_state from the angle + proc/set_dir() + if(angle%2 == 1) + icon_state = "mirrorB" + else + icon_state = "mirrorA" + switch(round(angle/2)*2) + if(0) + dir = 1 + if(2) + dir = 5 + if(4) + dir = 4 + if(6) + dir = 6 + if(8) + dir = 2 + if(10) + dir = 10 + if(12) + dir = 8 + if(14) + dir = 9 return \ No newline at end of file diff --git a/code/unused/pda2/base_os.dm b/code/unused/pda2/base_os.dm index b407950de35..cc2cdb63eb1 100644 --- a/code/unused/pda2/base_os.dm +++ b/code/unused/pda2/base_os.dm @@ -1,446 +1,446 @@ -/datum/computer/file/pda_program/os - proc - receive_os_command(list/command_list) - if((!src.holder) || (!src.master) || (!command_list) || !(command_list["command"])) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - return 1 - - return 0 - -//Main os program: Provides old pda interface and four programs including file browser, notes, messenger, and atmos scan - main_os - name = "ThinkOS 7" - size = 8.0 - var/mode = 0 - //Note vars - var/note = "Congratulations, your station has chosen the Thinktronic 5150 Personal Data Assistant!" - var/note_mode = 0 //0 For note editor, 1 for note browser - var/datum/computer/file/text/note_file = null //If set, save to this file. - //Messenger vars - var/list/detected_pdas = list() - var/message_on = 1 - var/message_silent = 0 //To beep or not to beep, that is the question - var/message_mode = 0 //0 for pda list, 1 for messages - var/message_tone = "beep" //Custom ringtone - var/message_note = null //Current messages in memory (Store as separate file only later??) - //File browser vars - var/datum/computer/folder/browse_folder = null - var/datum/computer/file/clipboard = null //Current file to copy - - - - receive_os_command(list/command_list) - if(..()) - return - +/datum/computer/file/pda_program/os + proc + receive_os_command(list/command_list) + if((!src.holder) || (!src.master) || (!command_list) || !(command_list["command"])) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + return 1 + + return 0 + +//Main os program: Provides old pda interface and four programs including file browser, notes, messenger, and atmos scan + main_os + name = "ThinkOS 7" + size = 8.0 + var/mode = 0 + //Note vars + var/note = "Congratulations, your station has chosen the Thinktronic 5150 Personal Data Assistant!" + var/note_mode = 0 //0 For note editor, 1 for note browser + var/datum/computer/file/text/note_file = null //If set, save to this file. + //Messenger vars + var/list/detected_pdas = list() + var/message_on = 1 + var/message_silent = 0 //To beep or not to beep, that is the question + var/message_mode = 0 //0 for pda list, 1 for messages + var/message_tone = "beep" //Custom ringtone + var/message_note = null //Current messages in memory (Store as separate file only later??) + //File browser vars + var/datum/computer/folder/browse_folder = null + var/datum/computer/file/clipboard = null //Current file to copy + + + + receive_os_command(list/command_list) + if(..()) + return + // to_chat(world, "[command_list["command"]]") - return - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - - switch(src.mode) - if(0) - dat += "

    PERSONAL DATA ASSISTANT

    " - dat += "Owner: [src.master.owner]

    " - - dat += "

    General Functions

    " - dat += "" - - dat += "

    Utilities

    " - dat += "" - - if(1) - //Note Program. Can save/load note files. - dat += "

    Notekeeper V2.5

    " - - if(!src.note_mode) - dat += "Edit" - dat += " | New File" - dat += " | Save" - dat += " | Load
    " - - dat += src.note - else - dat += " Back" - dat += " | \[[src.holding_folder.holder.file_amount - src.holding_folder.holder.file_used]\] Free
    " - dat += "" - - for(var/datum/computer/file/text/T in src.holding_folder.contents) - dat += "" - dat += "" - dat += "" - - dat += "
    [T.name][T.extension]Length: [T.data ? (length(T.data)) : "0"]
    " - - if(2) - //Messenger. Uses Radio. Is a messenger. - //TO-DO: ~file sharing~ - src.master.overlays.len = 0 //Remove existing alerts - dat += "

    SpaceMessenger V4.0.5

    " - - if (!src.message_mode) - - dat += "Ringer: [src.message_silent == 1 ? "Off" : "On"] | " - dat += "Send / Receive: [src.message_on == 1 ? "On" : "Off"] | " - dat += "Set Ringtone | " - dat += "Messages
    " - - dat += "Scan
    " - dat += "Detected PDAs
    " - - dat += "
      " - - var/count = 0 - - if (src.message_on) - for (var/obj/item/device/pda2/P in src.detected_pdas) - if (!P.owner) - src.detected_pdas -= P - continue - else if (P == src) //I guess this can happen if somebody copies the system file. - src.detected_pdas -= P - continue - - dat += "
    • [P]" - - dat += "
    • " - count++ - - dat += "
    " - - if (count == 0) - dat += "None detected.
    " - - else - dat += "Clear | " - dat += "Back
    " - - dat += "

    Messages

    " - - dat += src.message_note - dat += "
    " - - if(3) - //File Browser. - //To-do(?): Setting "favorite" programs to access straight from main menu - //Not sure how needed it is, not like they have to go through 500 subfolders or whatever - if((!src.browse_folder) || !(src.browse_folder.holder in src.master)) - src.browse_folder = src.holding_folder - - dat += " | Paste" - dat += " | Drive: " - dat += "\[[src.browse_folder.holder == src.master.hd ? "MAIN" : "CART"]\]
    " - - dat += "Contents of [browse_folder] | Drive ID:\[[src.browse_folder.holder.title]]
    " - dat += "Used: \[[src.browse_folder.holder.file_used]/[src.browse_folder.holder.file_amount]\]
    " - - dat += "" - for(var/datum/computer/file/F in browse_folder.contents) - if(F == src) - dat += "" - continue - dat += "" - dat += "" - - dat += "" - - dat += "" - dat += "" - - dat += "" - - dat += "" - - dat += "
    SystemSize: [src.size]SYSTEM
    [F.name]Size: [F.size][F.extension]DelRenameCopy
    " - - if(4) - //Atmos Scanner - dat += "

    Atmospheric Readings

    " - - var/turf/T = get_turf_or_move(get_turf(src.master)) - if (isnull(T)) - dat += "Unable to obtain a reading.
    " - else - var/datum/gas_mixture/environment = T.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() - - dat += "Air Pressure: [round(pressure,0.1)] kPa
    " - - if (total_moles()) - var/o2_level = environment.oxygen/total_moles() - var/n2_level = environment.nitrogen/total_moles() - var/co2_level = environment.carbon_dioxide/total_moles() - var/plasma_level = environment.toxins/total_moles() - var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) - - dat += "Nitrogen: [round(n2_level*100)]%
    " - - dat += "Oxygen: [round(o2_level*100)]%
    " - - dat += "Carbon Dioxide: [round(co2_level*100)]%
    " - - dat += "Plasma: [round(plasma_level*100)]%
    " - - if(unknown_level > 0.01) - dat += "OTHER: [round(unknown_level)]%
    " - - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " - - dat += "
    " - - return dat - - Topic(href, href_list) - if(..()) - return - - if(href_list["mode"]) - var/newmode = text2num(href_list["mode"]) - src.mode = max(newmode, 0) - - else if(href_list["flight"]) - src.master.toggle_light() - - else if(href_list["scanner"]) - if(src.master.scan_program) - src.master.scan_program = null - - else if(href_list["input"]) - switch(href_list["input"]) - if("tone") - var/t = input(usr, "Please enter new ringtone", src.name, src.message_tone) as text - if (!t) - return - - if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) - return - - if(!(src.holder in src.master)) - return - - t = copytext(sanitize(t), 1, 20) - src.message_tone = t - - if("note") - var/t = input(usr, "Please enter note", src.name, src.note) as message - if (!t) - return - - if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) - return - - if(!(src.holder in src.master)) - return - - t = copytext(adminscrub(t), 1, MAX_MESSAGE_LEN) - src.note = t - - - if("message") - var/obj/item/device/pda2/P = locate(href_list["target"]) - if(!P || !istype(P)) - return - - var/t = input(usr, "Please enter message", P.name, null) as text - if (!t) - return - - if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) - return - - if(!(src.holder in src.master)) - return - - - var/datum/signal/signal = new - signal.data["command"] = "text message" - signal.data["message"] = t - signal.data["sender"] = src.master.owner - signal.data["tag"] = "\ref[P]" - src.post_signal(signal) - src.message_note += "→ To [P.owner]:
    [t]
    " - log_pda("[usr] sent [t] to [P.owner]") - - if("rename") - var/datum/computer/file/F = locate(href_list["target"]) - if(!F || !istype(F)) - return - - var/t = input(usr, "Please enter new name", src.name, F.name) as text - t = copytext(sanitize(t), 1, 16) - if (!t) - return - if (!in_range(src.master, usr) || !(F.holder in src.master)) - return - if(F.holder.read_only) - return - F.name = capitalize(lowertext(t)) - - - else if(href_list["message_func"]) //Messenger specific topic junk - switch(href_list["message_func"]) - if("ringer") - src.message_silent = !src.message_silent - if("on") - src.message_on = !src.message_on - if("clear") - src.message_note = null - if("scan") - if(src.message_on) - src.detected_pdas = list() - var/datum/signal/signal = new - signal.data["command"] = "report pda" - src.post_signal(signal) - - else if(href_list["note_func"]) //Note program specific topic junk - switch(href_list["note_func"]) - if("new") - src.note_file = null - src.note = null - if("save") - if(src.note_file && src.note_file.holder in src.master) - src.note_file.data = src.note - else - var/datum/computer/file/text/F = new /datum/computer/file/text - if(!src.holding_folder.add_file(F)) - del(F) - else - src.note_file = F - F.data = src.note - - if("load") - var/datum/computer/file/text/T = locate(href_list["target"]) - if(!T || !istype(T)) - return - - src.note_file = T - src.note = note_file.data - src.note_mode = 0 - - if("switchmenu") - src.note_mode = !src.note_mode - - else if(href_list["browse_func"]) //File browser specific topic junk - var/datum/computer/target = locate(href_list["target"]) - switch(href_list["browse_func"]) - if("drive") - if(src.browse_folder.holder == src.master.hd && src.master.cartridge && (src.master.cartridge.root)) - src.browse_folder = src.master.cartridge.root - else - src.browse_folder = src.holding_folder - if("open") - if(!target || !istype(target)) - return - if(istype(target, /datum/computer/file/pda_program)) - if(istype(target,/datum/computer/file/pda_program/os) && (src.master.host_program)) - return - else - src.master.run_program(target) - src.master.updateSelfDialog() - return - - if("delete") - if(!target || !istype(target)) - return - src.master.delete_file(target) - - if("copy") - if(istype(target,/datum/computer/file) && (!target.holder || (target.holder in src.master.contents))) - src.clipboard = target - - if("paste") - if(istype(target,/datum/computer/folder)) - if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents)) - return - - if(!istype(src.clipboard)) - return - - src.clipboard.copy_file_to_folder(target) - - - else if(href_list["message_mode"]) - var/newmode = text2num(href_list["message_mode"]) - src.message_mode = max(newmode, 0) - - src.master.add_fingerprint(usr) - src.master.updateSelfDialog() - return - - receive_signal(datum/signal/signal) - if(..()) - return - - switch(signal.data["command"]) - if("text message") - if(!message_on || !signal.data["message"]) - return - var/sender = signal.data["sender"] - if(!sender) - sender = "!Unknown!" - - src.message_note += "← From [sender]:
    [signal.data["message"]]
    " - var/alert_beep = null //Don't beep if set to silent. - if(!src.message_silent) - alert_beep = src.message_tone - - src.master.display_alert(alert_beep) - src.master.updateSelfDialog() - - if("report pda") - if(!message_on) - return - - var/datum/signal/newsignal = new - newsignal.data["command"] = "reporting pda" - newsignal.data["tag"] = "\ref[signal.source]" - src.post_signal(newsignal) - - if("reporting pda") - if(!detected_pdas) - detected_pdas = new() - - if(!(signal.source in detected_pdas)) - detected_pdas += signal.source - - src.master.updateSelfDialog() - - return - - return_text_header() - if(!src.master) - return - - var/dat - - if(src.mode) - dat += " | Main Menu" - - else if (!isnull(src.master.cartridge)) - dat += " | Eject [src.master.cartridge]" - - dat += " | Refresh" - + return + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + + switch(src.mode) + if(0) + dat += "

    PERSONAL DATA ASSISTANT

    " + dat += "Owner: [src.master.owner]

    " + + dat += "

    General Functions

    " + dat += "" + + dat += "

    Utilities

    " + dat += "" + + if(1) + //Note Program. Can save/load note files. + dat += "

    Notekeeper V2.5

    " + + if(!src.note_mode) + dat += "Edit" + dat += " | New File" + dat += " | Save" + dat += " | Load
    " + + dat += src.note + else + dat += " Back" + dat += " | \[[src.holding_folder.holder.file_amount - src.holding_folder.holder.file_used]\] Free
    " + dat += "" + + for(var/datum/computer/file/text/T in src.holding_folder.contents) + dat += "" + dat += "" + dat += "" + + dat += "
    [T.name][T.extension]Length: [T.data ? (length(T.data)) : "0"]
    " + + if(2) + //Messenger. Uses Radio. Is a messenger. + //TO-DO: ~file sharing~ + src.master.overlays.len = 0 //Remove existing alerts + dat += "

    SpaceMessenger V4.0.5

    " + + if (!src.message_mode) + + dat += "Ringer: [src.message_silent == 1 ? "Off" : "On"] | " + dat += "Send / Receive: [src.message_on == 1 ? "On" : "Off"] | " + dat += "Set Ringtone | " + dat += "Messages
    " + + dat += "Scan
    " + dat += "Detected PDAs
    " + + dat += "
      " + + var/count = 0 + + if (src.message_on) + for (var/obj/item/device/pda2/P in src.detected_pdas) + if (!P.owner) + src.detected_pdas -= P + continue + else if (P == src) //I guess this can happen if somebody copies the system file. + src.detected_pdas -= P + continue + + dat += "
    • [P]" + + dat += "
    • " + count++ + + dat += "
    " + + if (count == 0) + dat += "None detected.
    " + + else + dat += "Clear | " + dat += "Back
    " + + dat += "

    Messages

    " + + dat += src.message_note + dat += "
    " + + if(3) + //File Browser. + //To-do(?): Setting "favorite" programs to access straight from main menu + //Not sure how needed it is, not like they have to go through 500 subfolders or whatever + if((!src.browse_folder) || !(src.browse_folder.holder in src.master)) + src.browse_folder = src.holding_folder + + dat += " | Paste" + dat += " | Drive: " + dat += "\[[src.browse_folder.holder == src.master.hd ? "MAIN" : "CART"]\]
    " + + dat += "Contents of [browse_folder] | Drive ID:\[[src.browse_folder.holder.title]]
    " + dat += "Used: \[[src.browse_folder.holder.file_used]/[src.browse_folder.holder.file_amount]\]
    " + + dat += "" + for(var/datum/computer/file/F in browse_folder.contents) + if(F == src) + dat += "" + continue + dat += "" + dat += "" + + dat += "" + + dat += "" + dat += "" + + dat += "" + + dat += "" + + dat += "
    SystemSize: [src.size]SYSTEM
    [F.name]Size: [F.size][F.extension]DelRenameCopy
    " + + if(4) + //Atmos Scanner + dat += "

    Atmospheric Readings

    " + + var/turf/T = get_turf_or_move(get_turf(src.master)) + if (isnull(T)) + dat += "Unable to obtain a reading.
    " + else + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + + dat += "Air Pressure: [round(pressure,0.1)] kPa
    " + + if (total_moles()) + var/o2_level = environment.oxygen/total_moles() + var/n2_level = environment.nitrogen/total_moles() + var/co2_level = environment.carbon_dioxide/total_moles() + var/plasma_level = environment.toxins/total_moles() + var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + + dat += "Nitrogen: [round(n2_level*100)]%
    " + + dat += "Oxygen: [round(o2_level*100)]%
    " + + dat += "Carbon Dioxide: [round(co2_level*100)]%
    " + + dat += "Plasma: [round(plasma_level*100)]%
    " + + if(unknown_level > 0.01) + dat += "OTHER: [round(unknown_level)]%
    " + + dat += "Temperature: [round(environment.temperature-T0C)]°C
    " + + dat += "
    " + + return dat + + Topic(href, href_list) + if(..()) + return + + if(href_list["mode"]) + var/newmode = text2num(href_list["mode"]) + src.mode = max(newmode, 0) + + else if(href_list["flight"]) + src.master.toggle_light() + + else if(href_list["scanner"]) + if(src.master.scan_program) + src.master.scan_program = null + + else if(href_list["input"]) + switch(href_list["input"]) + if("tone") + var/t = input(usr, "Please enter new ringtone", src.name, src.message_tone) as text + if (!t) + return + + if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) + return + + if(!(src.holder in src.master)) + return + + t = copytext(sanitize(t), 1, 20) + src.message_tone = t + + if("note") + var/t = input(usr, "Please enter note", src.name, src.note) as message + if (!t) + return + + if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) + return + + if(!(src.holder in src.master)) + return + + t = copytext(adminscrub(t), 1, MAX_MESSAGE_LEN) + src.note = t + + + if("message") + var/obj/item/device/pda2/P = locate(href_list["target"]) + if(!P || !istype(P)) + return + + var/t = input(usr, "Please enter message", P.name, null) as text + if (!t) + return + + if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) + return + + if(!(src.holder in src.master)) + return + + + var/datum/signal/signal = new + signal.data["command"] = "text message" + signal.data["message"] = t + signal.data["sender"] = src.master.owner + signal.data["tag"] = "\ref[P]" + src.post_signal(signal) + src.message_note += "→ To [P.owner]:
    [t]
    " + log_pda("[usr] sent [t] to [P.owner]") + + if("rename") + var/datum/computer/file/F = locate(href_list["target"]) + if(!F || !istype(F)) + return + + var/t = input(usr, "Please enter new name", src.name, F.name) as text + t = copytext(sanitize(t), 1, 16) + if (!t) + return + if (!in_range(src.master, usr) || !(F.holder in src.master)) + return + if(F.holder.read_only) + return + F.name = capitalize(lowertext(t)) + + + else if(href_list["message_func"]) //Messenger specific topic junk + switch(href_list["message_func"]) + if("ringer") + src.message_silent = !src.message_silent + if("on") + src.message_on = !src.message_on + if("clear") + src.message_note = null + if("scan") + if(src.message_on) + src.detected_pdas = list() + var/datum/signal/signal = new + signal.data["command"] = "report pda" + src.post_signal(signal) + + else if(href_list["note_func"]) //Note program specific topic junk + switch(href_list["note_func"]) + if("new") + src.note_file = null + src.note = null + if("save") + if(src.note_file && src.note_file.holder in src.master) + src.note_file.data = src.note + else + var/datum/computer/file/text/F = new /datum/computer/file/text + if(!src.holding_folder.add_file(F)) + del(F) + else + src.note_file = F + F.data = src.note + + if("load") + var/datum/computer/file/text/T = locate(href_list["target"]) + if(!T || !istype(T)) + return + + src.note_file = T + src.note = note_file.data + src.note_mode = 0 + + if("switchmenu") + src.note_mode = !src.note_mode + + else if(href_list["browse_func"]) //File browser specific topic junk + var/datum/computer/target = locate(href_list["target"]) + switch(href_list["browse_func"]) + if("drive") + if(src.browse_folder.holder == src.master.hd && src.master.cartridge && (src.master.cartridge.root)) + src.browse_folder = src.master.cartridge.root + else + src.browse_folder = src.holding_folder + if("open") + if(!target || !istype(target)) + return + if(istype(target, /datum/computer/file/pda_program)) + if(istype(target,/datum/computer/file/pda_program/os) && (src.master.host_program)) + return + else + src.master.run_program(target) + src.master.updateSelfDialog() + return + + if("delete") + if(!target || !istype(target)) + return + src.master.delete_file(target) + + if("copy") + if(istype(target,/datum/computer/file) && (!target.holder || (target.holder in src.master.contents))) + src.clipboard = target + + if("paste") + if(istype(target,/datum/computer/folder)) + if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents)) + return + + if(!istype(src.clipboard)) + return + + src.clipboard.copy_file_to_folder(target) + + + else if(href_list["message_mode"]) + var/newmode = text2num(href_list["message_mode"]) + src.message_mode = max(newmode, 0) + + src.master.add_fingerprint(usr) + src.master.updateSelfDialog() + return + + receive_signal(datum/signal/signal) + if(..()) + return + + switch(signal.data["command"]) + if("text message") + if(!message_on || !signal.data["message"]) + return + var/sender = signal.data["sender"] + if(!sender) + sender = "!Unknown!" + + src.message_note += "← From [sender]:
    [signal.data["message"]]
    " + var/alert_beep = null //Don't beep if set to silent. + if(!src.message_silent) + alert_beep = src.message_tone + + src.master.display_alert(alert_beep) + src.master.updateSelfDialog() + + if("report pda") + if(!message_on) + return + + var/datum/signal/newsignal = new + newsignal.data["command"] = "reporting pda" + newsignal.data["tag"] = "\ref[signal.source]" + src.post_signal(newsignal) + + if("reporting pda") + if(!detected_pdas) + detected_pdas = new() + + if(!(signal.source in detected_pdas)) + detected_pdas += signal.source + + src.master.updateSelfDialog() + + return + + return_text_header() + if(!src.master) + return + + var/dat + + if(src.mode) + dat += " | Main Menu" + + else if (!isnull(src.master.cartridge)) + dat += " | Eject [src.master.cartridge]" + + dat += " | Refresh" + return dat \ No newline at end of file diff --git a/code/unused/pda2/base_program.dm b/code/unused/pda2/base_program.dm index d59e4f5e015..7c964be94c6 100644 --- a/code/unused/pda2/base_program.dm +++ b/code/unused/pda2/base_program.dm @@ -1,185 +1,185 @@ -//Eventual plan: Convert all datum/data to datum/computer/file -/datum/computer/file/text - name = "text" - extension = "TEXT" - size = 2.0 - var/data = null - -/datum/computer/file/record - name = "record" - extension = "REC" - - var/list/fields = list( ) - - -//base pda program - -/datum/computer/file/pda_program - name = "blank program" - extension = "PPROG" - var/obj/item/device/pda2/master = null - var/id_tag = null - - os - name = "blank system program" - extension = "PSYS" - - scan - name = "blank scan program" - extension = "PSCAN" - - New(obj/holding as obj) - if(holding) - src.holder = holding - - if(istype(src.holder.loc,/obj/item/device/pda2)) - src.master = src.holder.loc - - proc - return_text() - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(!(holder in src.master.contents)) +//Eventual plan: Convert all datum/data to datum/computer/file +/datum/computer/file/text + name = "text" + extension = "TEXT" + size = 2.0 + var/data = null + +/datum/computer/file/record + name = "record" + extension = "REC" + + var/list/fields = list( ) + + +//base pda program + +/datum/computer/file/pda_program + name = "blank program" + extension = "PPROG" + var/obj/item/device/pda2/master = null + var/id_tag = null + + os + name = "blank system program" + extension = "PSYS" + + scan + name = "blank scan program" + extension = "PSCAN" + + New(obj/holding as obj) + if(holding) + src.holder = holding + + if(istype(src.holder.loc,/obj/item/device/pda2)) + src.master = src.holder.loc + + proc + return_text() + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(!(holder in src.master.contents)) // to_chat(world, "Holder [holder] not in [master] of prg:[src]") - if(master.active_program == src) - master.active_program = null - return 1 - - if(!src.holder.root) - src.holder.root = new /datum/computer/folder - src.holder.root.holder = src - src.holder.root.name = "root" - - return 0 - - process() //This isn't actually used at the moment - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - return 1 - - if(!src.holder.root) - src.holder.root = new /datum/computer/folder - src.holder.root.holder = src - src.holder.root.name = "root" - - return 0 - - //maybe remove this, I haven't found a good use for it yet - send_os_command(list/command_list) - if(!src.master || !src.holder || src.master.host_program || !command_list) - return 1 - - if(!istype(src.master.host_program) || src.master.host_program == src) - return 1 - - src.master.host_program.receive_os_command() - - return 0 - - return_text_header() - if(!src.master || !src.holder) - return - - var/dat = " | Main Menu" - dat += " | Refresh" - - return dat - - post_signal(datum/signal/signal, newfreq) - if(master) - master.post_signal(signal, newfreq) - else - del(signal) - - transfer_holder(obj/item/weapon/disk/data/newholder,datum/computer/folder/newfolder) - - if((newholder.file_used + src.size) > newholder.file_amount) - return 0 - - if(!newholder.root) - newholder.root = new /datum/computer/folder - newholder.root.holder = newholder - newholder.root.name = "root" - - if(!newfolder) - newfolder = newholder.root - - if((src.holder && src.holder.read_only) || newholder.read_only) - return 0 - - if((src.holder) && (src.holder.root)) - src.holder.root.remove_file(src) - - newfolder.add_file(src) - - if(istype(newholder.loc,/obj/item/device/pda2)) - src.master = newholder.loc - + if(master.active_program == src) + master.active_program = null + return 1 + + if(!src.holder.root) + src.holder.root = new /datum/computer/folder + src.holder.root.holder = src + src.holder.root.name = "root" + + return 0 + + process() //This isn't actually used at the moment + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + return 1 + + if(!src.holder.root) + src.holder.root = new /datum/computer/folder + src.holder.root.holder = src + src.holder.root.name = "root" + + return 0 + + //maybe remove this, I haven't found a good use for it yet + send_os_command(list/command_list) + if(!src.master || !src.holder || src.master.host_program || !command_list) + return 1 + + if(!istype(src.master.host_program) || src.master.host_program == src) + return 1 + + src.master.host_program.receive_os_command() + + return 0 + + return_text_header() + if(!src.master || !src.holder) + return + + var/dat = " | Main Menu" + dat += " | Refresh" + + return dat + + post_signal(datum/signal/signal, newfreq) + if(master) + master.post_signal(signal, newfreq) + else + del(signal) + + transfer_holder(obj/item/weapon/disk/data/newholder,datum/computer/folder/newfolder) + + if((newholder.file_used + src.size) > newholder.file_amount) + return 0 + + if(!newholder.root) + newholder.root = new /datum/computer/folder + newholder.root.holder = newholder + newholder.root.name = "root" + + if(!newfolder) + newfolder = newholder.root + + if((src.holder && src.holder.read_only) || newholder.read_only) + return 0 + + if((src.holder) && (src.holder.root)) + src.holder.root.remove_file(src) + + newfolder.add_file(src) + + if(istype(newholder.loc,/obj/item/device/pda2)) + src.master = newholder.loc + // to_chat(world, "Setting [src.holder] to [newholder]") - src.holder = newholder - return 1 - - - receive_signal(datum/signal/signal) - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - return 1 - - return 0 - - - Topic(href, href_list) - if((!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(src.master.active_program != src) - return 1 - - if ((!usr.contents.Find(src.master) && (!in_range(src.master, usr) || !istype(src.master.loc, /turf))) && (!istype(usr, /mob/living/silicon))) - return 1 - - if(!(holder in src.master.contents)) - if(master.active_program == src) - master.active_program = null - return 1 - - usr.machine = src.master - - if (href_list["close"]) - usr.machine = null - usr << browse(null, "window=pda2") - return 0 - - if (href_list["quit"]) -// src.master.processing_programs.Remove(src) - if(src.master.host_program && src.master.host_program.holder && (src.master.host_program.holder in src.master.contents)) - src.master.run_program(src.master.host_program) - src.master.updateSelfDialog() - return 1 - else - src.master.active_program = null - src.master.updateSelfDialog() - return 1 - + src.holder = newholder + return 1 + + + receive_signal(datum/signal/signal) + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + return 1 + + return 0 + + + Topic(href, href_list) + if((!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(src.master.active_program != src) + return 1 + + if ((!usr.contents.Find(src.master) && (!in_range(src.master, usr) || !istype(src.master.loc, /turf))) && (!istype(usr, /mob/living/silicon))) + return 1 + + if(!(holder in src.master.contents)) + if(master.active_program == src) + master.active_program = null + return 1 + + usr.machine = src.master + + if (href_list["close"]) + usr.machine = null + usr << browse(null, "window=pda2") + return 0 + + if (href_list["quit"]) +// src.master.processing_programs.Remove(src) + if(src.master.host_program && src.master.host_program.holder && (src.master.host_program.holder in src.master.contents)) + src.master.run_program(src.master.host_program) + src.master.updateSelfDialog() + return 1 + else + src.master.active_program = null + src.master.updateSelfDialog() + return 1 + return 0 \ No newline at end of file diff --git a/code/unused/pda2/pda2.dm b/code/unused/pda2/pda2.dm index aeace9bcd1a..08386c2fe18 100644 --- a/code/unused/pda2/pda2.dm +++ b/code/unused/pda2/pda2.dm @@ -1,298 +1,298 @@ -//The advanced pea-green monochrome lcd of tomorrow. - - -//TO-DO: rearrange all this disk/data stuff so that fixed disks are the parent type -//because otherwise you have carts going into floppy drives and it's ALL MAD -/obj/item/weapon/disk/data/cartridge - name = "Cart 2.0" - desc = "A data cartridge for portable microcomputers." - icon = 'icons/obj/pda.dmi' - icon_state = "cart" - item_state = "electronic" - file_amount = 80.0 - title = "ROM Cart" - - pda2test - name = "Test Cart" - New() - ..() - src.root.add_file( new /datum/computer/file/computer_program/arcade(src)) - src.root.add_file( new /datum/computer/file/pda_program/manifest(src)) - src.root.add_file( new /datum/computer/file/pda_program/status_display(src)) - src.root.add_file( new /datum/computer/file/pda_program/signaler(src)) - src.root.add_file( new /datum/computer/file/pda_program/qm_records(src)) - src.root.add_file( new /datum/computer/file/pda_program/scan/health_scan(src)) - src.root.add_file( new /datum/computer/file/pda_program/records/security(src)) - src.root.add_file( new /datum/computer/file/pda_program/records/medical(src)) - src.read_only = 1 - - -/obj/item/device/pda2 - name = "PDA" - desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by an EEPROM cartridge." - icon = 'icons/obj/pda.dmi' - icon_state = "pda" - item_state = "electronic" - w_class = 2.0 - flags = FPRINT | TABLEPASS - slow_flags = SLOT_BELT - - var/owner = null - var/default_cartridge = null // Access level defined by cartridge - var/obj/item/weapon/disk/data/cartridge/cartridge = null //current cartridge - var/datum/computer/file/pda_program/active_program = null - var/datum/computer/file/pda_program/os/host_program = null - var/datum/computer/file/pda_program/scan/scan_program = null - var/obj/item/weapon/disk/data/fixed_disk/hd = null - var/fon = 0 //Is the flashlight function on? - var/f_lum = 3 //Luminosity for the flashlight function -// var/datum/data/record/active1 = null //General -// var/datum/data/record/active2 = null //Medical -// var/datum/data/record/active3 = null //Security -// var/obj/item/weapon/integrated_uplink/uplink = null //Maybe replace uplink with some remote ~syndicate~ server - var/frequency = 1149 - var/datum/radio_frequency/radio_connection - - var/setup_default_cartridge = null //Cartridge contains job-specific programs - var/setup_drive_size = 24.0 //PDAs don't have much work room at all, really. - var/setup_system_os_path = /datum/computer/file/pda_program/os/main_os //Needs an operating system to...operate!! - - -/obj/item/device/pda2/pickup(mob/user) - if (src.fon) - src.sd_SetLuminosity(0) - user.sd_SetLuminosity(user.luminosity + src.f_lum) - -/obj/item/device/pda2/dropped(mob/user) - if (src.fon) - user.sd_SetLuminosity(user.luminosity - src.f_lum) - src.sd_SetLuminosity(src.f_lum) - -/obj/item/device/pda2/New() - ..() - spawn(5) - src.hd = new /obj/item/weapon/disk/data/fixed_disk(src) - src.hd.file_amount = src.setup_drive_size - src.hd.name = "Minidrive" - src.hd.title = "Minidrive" - - if(src.setup_system_os_path) - src.host_program = new src.setup_system_os_path - - src.hd.file_amount = max(src.hd.file_amount, src.host_program.size) - - src.host_program.transfer_holder(src.hd) - - if(radio_controller) - radio_controller.add_object(src, frequency) - - - if (src.default_cartridge) - src.cartridge = new src.setup_default_cartridge(src) -// if(src.owner) -// processing_items.Add(src) - -/obj/item/device/pda2/attack_self(mob/user as mob) - user.machine = src - - var/dat = "Personal Data Assistant" - - dat += "Close" - - if (!src.owner) - if(src.cartridge) - dat += " | Eject [src.cartridge]" - dat += "
    Warning: No owner information entered. Please swipe card.

    " - dat += "Retry" - else - if(src.active_program) - dat += src.active_program.return_text() - else - if(src.host_program) - src.run_program(src.host_program) - dat += src.active_program.return_text() - else - if(src.cartridge) - dat += " | Eject [src.cartridge]
    " - dat += "
    Fatal Error 0x17
    " - dat += "No System Software Loaded
    " - //To-do: System recovery shit (maybe have a dedicated computer for this kind of thing) - - - user << browse(dat,"window=pda2") - onclose(user,"pda2") - return - -/obj/item/device/pda2/Topic(href, href_list) - ..() - - if (usr.contents.Find(src) || usr.contents.Find(src.master) || (istype(src.loc, /turf) && get_dist(src, usr) <= 1)) - if (usr.stat || usr.restrained()) - return - - src.add_fingerprint(usr) - usr.machine = src - - - if(href_list["return_to_host"]) - if(src.host_program) - src.active_program = src.host_program - src.host_program = null - - else if (href_list["eject_cart"]) - src.eject_cartridge() - - else if (href_list["refresh"]) - src.updateSelfDialog() - - else if (href_list["close"]) - usr << browse(null, "window=pda2") - usr.machine = null - - src.updateSelfDialog() - return - -/obj/item/device/pda2/attackby(obj/item/weapon/C as obj, mob/user as mob) - if (istype(C, /obj/item/weapon/disk/data/cartridge) && isnull(src.cartridge)) - user.drop_item() - C.loc = src +//The advanced pea-green monochrome lcd of tomorrow. + + +//TO-DO: rearrange all this disk/data stuff so that fixed disks are the parent type +//because otherwise you have carts going into floppy drives and it's ALL MAD +/obj/item/weapon/disk/data/cartridge + name = "Cart 2.0" + desc = "A data cartridge for portable microcomputers." + icon = 'icons/obj/pda.dmi' + icon_state = "cart" + item_state = "electronic" + file_amount = 80.0 + title = "ROM Cart" + + pda2test + name = "Test Cart" + New() + ..() + src.root.add_file( new /datum/computer/file/computer_program/arcade(src)) + src.root.add_file( new /datum/computer/file/pda_program/manifest(src)) + src.root.add_file( new /datum/computer/file/pda_program/status_display(src)) + src.root.add_file( new /datum/computer/file/pda_program/signaler(src)) + src.root.add_file( new /datum/computer/file/pda_program/qm_records(src)) + src.root.add_file( new /datum/computer/file/pda_program/scan/health_scan(src)) + src.root.add_file( new /datum/computer/file/pda_program/records/security(src)) + src.root.add_file( new /datum/computer/file/pda_program/records/medical(src)) + src.read_only = 1 + + +/obj/item/device/pda2 + name = "PDA" + desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by an EEPROM cartridge." + icon = 'icons/obj/pda.dmi' + icon_state = "pda" + item_state = "electronic" + w_class = 2.0 + flags = FPRINT | TABLEPASS + slow_flags = SLOT_BELT + + var/owner = null + var/default_cartridge = null // Access level defined by cartridge + var/obj/item/weapon/disk/data/cartridge/cartridge = null //current cartridge + var/datum/computer/file/pda_program/active_program = null + var/datum/computer/file/pda_program/os/host_program = null + var/datum/computer/file/pda_program/scan/scan_program = null + var/obj/item/weapon/disk/data/fixed_disk/hd = null + var/fon = 0 //Is the flashlight function on? + var/f_lum = 3 //Luminosity for the flashlight function +// var/datum/data/record/active1 = null //General +// var/datum/data/record/active2 = null //Medical +// var/datum/data/record/active3 = null //Security +// var/obj/item/weapon/integrated_uplink/uplink = null //Maybe replace uplink with some remote ~syndicate~ server + var/frequency = 1149 + var/datum/radio_frequency/radio_connection + + var/setup_default_cartridge = null //Cartridge contains job-specific programs + var/setup_drive_size = 24.0 //PDAs don't have much work room at all, really. + var/setup_system_os_path = /datum/computer/file/pda_program/os/main_os //Needs an operating system to...operate!! + + +/obj/item/device/pda2/pickup(mob/user) + if (src.fon) + src.sd_SetLuminosity(0) + user.sd_SetLuminosity(user.luminosity + src.f_lum) + +/obj/item/device/pda2/dropped(mob/user) + if (src.fon) + user.sd_SetLuminosity(user.luminosity - src.f_lum) + src.sd_SetLuminosity(src.f_lum) + +/obj/item/device/pda2/New() + ..() + spawn(5) + src.hd = new /obj/item/weapon/disk/data/fixed_disk(src) + src.hd.file_amount = src.setup_drive_size + src.hd.name = "Minidrive" + src.hd.title = "Minidrive" + + if(src.setup_system_os_path) + src.host_program = new src.setup_system_os_path + + src.hd.file_amount = max(src.hd.file_amount, src.host_program.size) + + src.host_program.transfer_holder(src.hd) + + if(radio_controller) + radio_controller.add_object(src, frequency) + + + if (src.default_cartridge) + src.cartridge = new src.setup_default_cartridge(src) +// if(src.owner) +// processing_items.Add(src) + +/obj/item/device/pda2/attack_self(mob/user as mob) + user.machine = src + + var/dat = "Personal Data Assistant" + + dat += "Close" + + if (!src.owner) + if(src.cartridge) + dat += " | Eject [src.cartridge]" + dat += "
    Warning: No owner information entered. Please swipe card.

    " + dat += "Retry" + else + if(src.active_program) + dat += src.active_program.return_text() + else + if(src.host_program) + src.run_program(src.host_program) + dat += src.active_program.return_text() + else + if(src.cartridge) + dat += " | Eject [src.cartridge]
    " + dat += "
    Fatal Error 0x17
    " + dat += "No System Software Loaded
    " + //To-do: System recovery shit (maybe have a dedicated computer for this kind of thing) + + + user << browse(dat,"window=pda2") + onclose(user,"pda2") + return + +/obj/item/device/pda2/Topic(href, href_list) + ..() + + if (usr.contents.Find(src) || usr.contents.Find(src.master) || (istype(src.loc, /turf) && get_dist(src, usr) <= 1)) + if (usr.stat || usr.restrained()) + return + + src.add_fingerprint(usr) + usr.machine = src + + + if(href_list["return_to_host"]) + if(src.host_program) + src.active_program = src.host_program + src.host_program = null + + else if (href_list["eject_cart"]) + src.eject_cartridge() + + else if (href_list["refresh"]) + src.updateSelfDialog() + + else if (href_list["close"]) + usr << browse(null, "window=pda2") + usr.machine = null + + src.updateSelfDialog() + return + +/obj/item/device/pda2/attackby(obj/item/weapon/C as obj, mob/user as mob) + if (istype(C, /obj/item/weapon/disk/data/cartridge) && isnull(src.cartridge)) + user.drop_item() + C.loc = src to_chat(user, "You insert [C] into [src].") - src.cartridge = C - src.updateSelfDialog() - - else if (istype(C, /obj/item/weapon/card/id) && !src.owner && C:registered_name) - src.owner = C:registered_name - src.name = "PDA-[src.owner]" + src.cartridge = C + src.updateSelfDialog() + + else if (istype(C, /obj/item/weapon/card/id) && !src.owner && C:registered_name) + src.owner = C:registered_name + src.name = "PDA-[src.owner]" to_chat(user, "Card scanned.") - src.updateSelfDialog() - -/obj/item/device/pda2/receive_signal(datum/signal/signal) - if(!signal || signal.encryption || !src.owner) return - - if(signal.data["tag"] && signal.data["tag"] != "\ref[src]") return - - if(src.host_program) - src.host_program.receive_signal(signal) - - if(src.active_program && (src.active_program != src.host_program)) - src.host_program.receive_signal(signal) - - return - -/obj/item/device/pda2/attack(mob/M as mob, mob/user as mob) - if(src.scan_program) - return - else - ..() - -/obj/item/device/pda2/afterattack(atom/A as mob|obj|turf|area, mob/user as mob) - var/scan_dat = null - if(src.scan_program && istype(src.scan_program)) - scan_dat = src.scan_program.scan_atom(A) - - if(scan_dat) - A.visible_message("[user] has scanned [A]!") - user.show_message(scan_dat, 1) - - return - - -/obj/item/device/pda2/proc - - post_signal(datum/signal/signal,var/newfreq) - if(!signal) - return - var/freq = newfreq - if(!freq) - freq = src.frequency - - signal.source = src - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - signal.transmission_method = TRANSMISSION_RADIO - if(frequency) - return frequency.post_signal(src, signal) - else - del(signal) - - eject_cartridge() - if(src.cartridge) - var/turf/T = get_turf(src) - - if(src.active_program && (src.active_program.holder == src.cartridge)) - src.active_program = null - - if(src.host_program && (src.host_program.holder == src.cartridge)) - src.host_program = null - - if(src.scan_program && (src.scan_program.holder == src.cartridge)) - src.scan_program = null - - src.cartridge.loc = T - src.cartridge = null - - return - - //Toggle the built-in flashlight - toggle_light() - src.fon = (!src.fon) - - if (ismob(src.loc)) - if (src.fon) - src.loc.sd_SetLuminosity(src.loc.luminosity + src.f_lum) - else - src.loc.sd_SetLuminosity(src.loc.luminosity - src.f_lum) - else - src.sd_SetLuminosity(src.fon * src.f_lum) - - src.updateSelfDialog() - - display_alert(var/alert_message) //Add alert overlay and beep - if (alert_message) - playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, src.loc)) - O.show_message(text("\icon[src] *[alert_message]*")) - - src.overlays.len = 0 - src.overlays += image('icons/obj/pda.dmi', "pda-r") - return - - run_program(datum/computer/file/pda_program/program) - if((!program) || (!program.holder)) - return 0 - - if(!(program.holder in src)) + src.updateSelfDialog() + +/obj/item/device/pda2/receive_signal(datum/signal/signal) + if(!signal || signal.encryption || !src.owner) return + + if(signal.data["tag"] && signal.data["tag"] != "\ref[src]") return + + if(src.host_program) + src.host_program.receive_signal(signal) + + if(src.active_program && (src.active_program != src.host_program)) + src.host_program.receive_signal(signal) + + return + +/obj/item/device/pda2/attack(mob/M as mob, mob/user as mob) + if(src.scan_program) + return + else + ..() + +/obj/item/device/pda2/afterattack(atom/A as mob|obj|turf|area, mob/user as mob) + var/scan_dat = null + if(src.scan_program && istype(src.scan_program)) + scan_dat = src.scan_program.scan_atom(A) + + if(scan_dat) + A.visible_message("[user] has scanned [A]!") + user.show_message(scan_dat, 1) + + return + + +/obj/item/device/pda2/proc + + post_signal(datum/signal/signal,var/newfreq) + if(!signal) + return + var/freq = newfreq + if(!freq) + freq = src.frequency + + signal.source = src + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + signal.transmission_method = TRANSMISSION_RADIO + if(frequency) + return frequency.post_signal(src, signal) + else + del(signal) + + eject_cartridge() + if(src.cartridge) + var/turf/T = get_turf(src) + + if(src.active_program && (src.active_program.holder == src.cartridge)) + src.active_program = null + + if(src.host_program && (src.host_program.holder == src.cartridge)) + src.host_program = null + + if(src.scan_program && (src.scan_program.holder == src.cartridge)) + src.scan_program = null + + src.cartridge.loc = T + src.cartridge = null + + return + + //Toggle the built-in flashlight + toggle_light() + src.fon = (!src.fon) + + if (ismob(src.loc)) + if (src.fon) + src.loc.sd_SetLuminosity(src.loc.luminosity + src.f_lum) + else + src.loc.sd_SetLuminosity(src.loc.luminosity - src.f_lum) + else + src.sd_SetLuminosity(src.fon * src.f_lum) + + src.updateSelfDialog() + + display_alert(var/alert_message) //Add alert overlay and beep + if (alert_message) + playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 1) + for (var/mob/O in hearers(3, src.loc)) + O.show_message(text("\icon[src] *[alert_message]*")) + + src.overlays.len = 0 + src.overlays += image('icons/obj/pda.dmi', "pda-r") + return + + run_program(datum/computer/file/pda_program/program) + if((!program) || (!program.holder)) + return 0 + + if(!(program.holder in src)) // to_chat(world, "Not in src") - program = new program.type - program.transfer_holder(src.hd) - - if(program.master != src) - program.master = src - - if(!src.host_program && istype(program, /datum/computer/file/pda_program/os)) - src.host_program = program - - if(istype(program, /datum/computer/file/pda_program/scan)) - if(program == src.scan_program) - src.scan_program = null - else - src.scan_program = program - return 1 - - src.active_program = program - return 1 - - delete_file(datum/computer/file/file) + program = new program.type + program.transfer_holder(src.hd) + + if(program.master != src) + program.master = src + + if(!src.host_program && istype(program, /datum/computer/file/pda_program/os)) + src.host_program = program + + if(istype(program, /datum/computer/file/pda_program/scan)) + if(program == src.scan_program) + src.scan_program = null + else + src.scan_program = program + return 1 + + src.active_program = program + return 1 + + delete_file(datum/computer/file/file) // to_chat(world, "Deleting [file]...") - if((!file) || (!file.holder) || (file.holder.read_only)) + if((!file) || (!file.holder) || (file.holder.read_only)) // to_chat(world, "Cannot delete :(") - return 0 - - //Don't delete the running program you jerk - if(src.active_program == file || src.host_program == file) - src.active_program = null - + return 0 + + //Don't delete the running program you jerk + if(src.active_program == file || src.host_program == file) + src.active_program = null + // to_chat(world, "Now calling del on [file]...") - del(file) + del(file) return 1 \ No newline at end of file diff --git a/code/unused/pda2/record_progs.dm b/code/unused/pda2/record_progs.dm index 2ea856c93e2..46f733273bf 100644 --- a/code/unused/pda2/record_progs.dm +++ b/code/unused/pda2/record_progs.dm @@ -1,181 +1,181 @@ -//CONTENTS: -//Generic records -//Security records -//Medical records - - -/datum/computer/file/pda_program/records - var/mode = 0 - var/datum/data/record/active1 = null //General - var/datum/data/record/active2 = null //Security/Medical/Whatever - -//To-do: editing arrest status/etc from pda. -/datum/computer/file/pda_program/records/security - name = "Security Records" - size = 12.0 - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - - switch(src.mode) - if(0) - dat += "

    Security Record List

    " - - for (var/datum/data/record/R in data_core.general) - dat += "[R.fields["id"]]: [R.fields["name"]]
    " - - dat += "
    " - - if(1) - - dat += "

    Security Record

    " - - dat += "
    Back
    " - - if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) - dat += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]
    " - dat += "Sex: [src.active1.fields["sex"]]
    " - dat += "Age: [src.active1.fields["age"]]
    " - dat += "Fingerprint: [src.active1.fields["fingerprint"]]
    " - dat += "Physical Status: [src.active1.fields["p_stat"]]
    " - dat += "Mental Status: [src.active1.fields["m_stat"]]
    " - else - dat += "Record Lost!
    " - - dat += "
    " - - dat += "

    Security Data

    " - if (istype(src.active2, /datum/data/record) && data_core.security.Find(src.active2)) - dat += "Criminal Status: [src.active2.fields["criminal"]]
    " - - dat += "Minor Crimes: [src.active2.fields["mi_crim"]]
    " - dat += "Details: [src.active2.fields["mi_crim"]]

    " - - dat += "Major Crimes: [src.active2.fields["ma_crim"]]
    " - dat += "Details: [src.active2.fields["ma_crim_d"]]

    " - - dat += "Important Notes:
    " - dat += "[src.active2.fields["notes"]]" - else - dat += "Record Lost!
    " - - dat += "
    " - - return dat - - Topic(href, href_list) - if(..()) - return - - if(href_list["mode"]) - var/newmode = text2num(href_list["mode"]) - src.mode = max(newmode, 0) - - else if(href_list["select_rec"]) - var/datum/data/record/R = locate(href_list["select_rec"]) - var/datum/data/record/S = locate(href_list["select_rec"]) - - if (data_core.general.Find(R)) - for (var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - S = E - break - - src.active1 = R - src.active2 = S - - src.mode = 1 - - src.master.add_fingerprint(usr) - src.master.updateSelfDialog() - return - -/datum/computer/file/pda_program/records/medical - name = "Medical Records" - size = 8.0 - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - - switch(src.mode) - if(0) - - dat += "

    Medical Record List

    " - for (var/datum/data/record/R in data_core.general) - dat += "[R.fields["id"]]: [R.fields["name"]]
    " - dat += "
    " - - if(1) - - dat += "

    Medical Record

    " - - dat += "
    Back
    " - - if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) - dat += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]
    " - dat += "Sex: [src.active1.fields["sex"]]
    " - dat += "Age: [src.active1.fields["age"]]
    " - dat += "Fingerprint: [src.active1.fields["fingerprint"]]
    " - dat += "Physical Status: [src.active1.fields["p_stat"]]
    " - dat += "Mental Status: [src.active1.fields["m_stat"]]
    " - else - dat += "Record Lost!
    " - - dat += "
    " - - dat += "

    Medical Data

    " - if (istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)) - dat += "Blood Type: [src.active2.fields["b_type"]]

    " - - dat += "Minor Disabilities: [src.active2.fields["mi_dis"]]
    " - dat += "Details: [src.active2.fields["mi_dis_d"]]

    " - - dat += "Major Disabilities: [src.active2.fields["ma_dis"]]
    " - dat += "Details: [src.active2.fields["ma_dis_d"]]

    " - - dat += "Allergies: [src.active2.fields["alg"]]
    " - dat += "Details: [src.active2.fields["alg_d"]]

    " - - dat += "Current Diseases: [src.active2.fields["cdi"]]
    " - dat += "Details: [src.active2.fields["cdi_d"]]

    " - - dat += "Important Notes: [src.active2.fields["notes"]]
    " - else - dat += "Record Lost!
    " - - dat += "
    " - - return dat - - Topic(href, href_list) - if(..()) - return - - if(href_list["mode"]) - var/newmode = text2num(href_list["mode"]) - src.mode = max(newmode, 0) - - else if(href_list["select_rec"]) - var/datum/data/record/R = locate(href_list["select_rec"]) - var/datum/data/record/M = locate(href_list["select_rec"]) - - if (data_core.general.Find(R)) - for (var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - break - - src.active1 = R - src.active2 = M - - src.mode = 1 - - src.master.add_fingerprint(usr) - src.master.updateSelfDialog() +//CONTENTS: +//Generic records +//Security records +//Medical records + + +/datum/computer/file/pda_program/records + var/mode = 0 + var/datum/data/record/active1 = null //General + var/datum/data/record/active2 = null //Security/Medical/Whatever + +//To-do: editing arrest status/etc from pda. +/datum/computer/file/pda_program/records/security + name = "Security Records" + size = 12.0 + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + + switch(src.mode) + if(0) + dat += "

    Security Record List

    " + + for (var/datum/data/record/R in data_core.general) + dat += "[R.fields["id"]]: [R.fields["name"]]
    " + + dat += "
    " + + if(1) + + dat += "

    Security Record

    " + + dat += "
    Back
    " + + if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) + dat += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]
    " + dat += "Sex: [src.active1.fields["sex"]]
    " + dat += "Age: [src.active1.fields["age"]]
    " + dat += "Fingerprint: [src.active1.fields["fingerprint"]]
    " + dat += "Physical Status: [src.active1.fields["p_stat"]]
    " + dat += "Mental Status: [src.active1.fields["m_stat"]]
    " + else + dat += "Record Lost!
    " + + dat += "
    " + + dat += "

    Security Data

    " + if (istype(src.active2, /datum/data/record) && data_core.security.Find(src.active2)) + dat += "Criminal Status: [src.active2.fields["criminal"]]
    " + + dat += "Minor Crimes: [src.active2.fields["mi_crim"]]
    " + dat += "Details: [src.active2.fields["mi_crim"]]

    " + + dat += "Major Crimes: [src.active2.fields["ma_crim"]]
    " + dat += "Details: [src.active2.fields["ma_crim_d"]]

    " + + dat += "Important Notes:
    " + dat += "[src.active2.fields["notes"]]" + else + dat += "Record Lost!
    " + + dat += "
    " + + return dat + + Topic(href, href_list) + if(..()) + return + + if(href_list["mode"]) + var/newmode = text2num(href_list["mode"]) + src.mode = max(newmode, 0) + + else if(href_list["select_rec"]) + var/datum/data/record/R = locate(href_list["select_rec"]) + var/datum/data/record/S = locate(href_list["select_rec"]) + + if (data_core.general.Find(R)) + for (var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + S = E + break + + src.active1 = R + src.active2 = S + + src.mode = 1 + + src.master.add_fingerprint(usr) + src.master.updateSelfDialog() + return + +/datum/computer/file/pda_program/records/medical + name = "Medical Records" + size = 8.0 + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + + switch(src.mode) + if(0) + + dat += "

    Medical Record List

    " + for (var/datum/data/record/R in data_core.general) + dat += "[R.fields["id"]]: [R.fields["name"]]
    " + dat += "
    " + + if(1) + + dat += "

    Medical Record

    " + + dat += "
    Back
    " + + if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) + dat += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]
    " + dat += "Sex: [src.active1.fields["sex"]]
    " + dat += "Age: [src.active1.fields["age"]]
    " + dat += "Fingerprint: [src.active1.fields["fingerprint"]]
    " + dat += "Physical Status: [src.active1.fields["p_stat"]]
    " + dat += "Mental Status: [src.active1.fields["m_stat"]]
    " + else + dat += "Record Lost!
    " + + dat += "
    " + + dat += "

    Medical Data

    " + if (istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)) + dat += "Blood Type: [src.active2.fields["b_type"]]

    " + + dat += "Minor Disabilities: [src.active2.fields["mi_dis"]]
    " + dat += "Details: [src.active2.fields["mi_dis_d"]]

    " + + dat += "Major Disabilities: [src.active2.fields["ma_dis"]]
    " + dat += "Details: [src.active2.fields["ma_dis_d"]]

    " + + dat += "Allergies: [src.active2.fields["alg"]]
    " + dat += "Details: [src.active2.fields["alg_d"]]

    " + + dat += "Current Diseases: [src.active2.fields["cdi"]]
    " + dat += "Details: [src.active2.fields["cdi_d"]]

    " + + dat += "Important Notes: [src.active2.fields["notes"]]
    " + else + dat += "Record Lost!
    " + + dat += "
    " + + return dat + + Topic(href, href_list) + if(..()) + return + + if(href_list["mode"]) + var/newmode = text2num(href_list["mode"]) + src.mode = max(newmode, 0) + + else if(href_list["select_rec"]) + var/datum/data/record/R = locate(href_list["select_rec"]) + var/datum/data/record/M = locate(href_list["select_rec"]) + + if (data_core.general.Find(R)) + for (var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + break + + src.active1 = R + src.active2 = M + + src.mode = 1 + + src.master.add_fingerprint(usr) + src.master.updateSelfDialog() return \ No newline at end of file diff --git a/code/unused/pda2/scanners.dm b/code/unused/pda2/scanners.dm index 4e771bc8364..40af6361502 100644 --- a/code/unused/pda2/scanners.dm +++ b/code/unused/pda2/scanners.dm @@ -1,104 +1,104 @@ -//CONTENTS: -//Base scanner stuff -//Health scanner -//Forensic scanner -//Reagent scanner - -/datum/computer/file/pda_program/scan - return_text() - return src.return_text_header() - - proc/scan_atom(atom/A as mob|obj|turf|area) - - - if( !A || (!src.holder) || (!src.master)) - return 1 - - if((!istype(holder)) || (!istype(master))) - return 1 - - if(!(holder in src.master.contents)) - if(master.scan_program == src) - master.scan_program = null - return 1 - - return 0 - - //Health analyzer program - health_scan - name = "Health Scan" - size = 8.0 - - scan_atom(atom/A as mob|obj|turf|area) - if(..()) - return - - var/mob/living/carbon/C = A - if(!istype(C)) - return - - var/dat = "Analyzing Results for [C]:\n" - dat += "\t Overall Status: [C.stat > 1 ? "dead" : "[C.health]% healthy"]\n" - dat += "\t Damage Specifics: [C.getOxyLoss() > 50 ? "" : ""][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "" : ""][C.getToxLoss()]-[C.getFireLoss() > 50 ? "" : ""][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "" : ""][C.getBruteLoss()]\n" - dat += "\t Key: Suffocation/Toxin/Burns/Brute\n" - dat += "\t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)" - if(C.virus) - dat += "\nWarning Virus Detected.\nName: [C.virus.name].\nType: [C.virus.spread].\nStage: [C.virus.stage]/[C.virus.max_stages].\nPossible Cure: [C.virus.cure]" - - return dat - - //Forensic scanner - forensic_scan - name = "Forensic Scan" - size = 8.0 - - scan_atom(atom/A as mob|obj|turf|area) - if(..()) - return - var/dat = null - - if(istype(A,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = A - if (!istype(H.dna, /datum/dna) || !isnull(H.gloves)) - dat += "Unable to scan [A]'s fingerprints.\n" - else - dat += "[H]'s Fingerprints: [md5(H.dna.uni_identity)]\n" - if ( !(H.blood_DNA.len) ) - dat += "No blood found on [H]\n" - else - for(var/i = 1, i < H.blood_DNA.len, i++) - var/list/templist = H.blood_DNA[i] +//CONTENTS: +//Base scanner stuff +//Health scanner +//Forensic scanner +//Reagent scanner + +/datum/computer/file/pda_program/scan + return_text() + return src.return_text_header() + + proc/scan_atom(atom/A as mob|obj|turf|area) + + + if( !A || (!src.holder) || (!src.master)) + return 1 + + if((!istype(holder)) || (!istype(master))) + return 1 + + if(!(holder in src.master.contents)) + if(master.scan_program == src) + master.scan_program = null + return 1 + + return 0 + + //Health analyzer program + health_scan + name = "Health Scan" + size = 8.0 + + scan_atom(atom/A as mob|obj|turf|area) + if(..()) + return + + var/mob/living/carbon/C = A + if(!istype(C)) + return + + var/dat = "Analyzing Results for [C]:\n" + dat += "\t Overall Status: [C.stat > 1 ? "dead" : "[C.health]% healthy"]\n" + dat += "\t Damage Specifics: [C.getOxyLoss() > 50 ? "" : ""][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "" : ""][C.getToxLoss()]-[C.getFireLoss() > 50 ? "" : ""][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "" : ""][C.getBruteLoss()]\n" + dat += "\t Key: Suffocation/Toxin/Burns/Brute\n" + dat += "\t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)" + if(C.virus) + dat += "\nWarning Virus Detected.\nName: [C.virus.name].\nType: [C.virus.spread].\nStage: [C.virus.stage]/[C.virus.max_stages].\nPossible Cure: [C.virus.cure]" + + return dat + + //Forensic scanner + forensic_scan + name = "Forensic Scan" + size = 8.0 + + scan_atom(atom/A as mob|obj|turf|area) + if(..()) + return + var/dat = null + + if(istype(A,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = A + if (!istype(H.dna, /datum/dna) || !isnull(H.gloves)) + dat += "Unable to scan [A]'s fingerprints.\n" + else + dat += "[H]'s Fingerprints: [md5(H.dna.uni_identity)]\n" + if ( !(H.blood_DNA.len) ) + dat += "No blood found on [H]\n" + else + for(var/i = 1, i < H.blood_DNA.len, i++) + var/list/templist = H.blood_DNA[i] to_chat(user, "Blood type: [templist[2]]\nDNA: [templist[1]]") - - if (!A.fingerprints) - dat += "Unable to locate any fingerprints on [A]!\n" - else - var/list/L = params2list(A:fingerprints) - dat += "Isolated [L.len] fingerprints.\n" - for(var/i in L) - dat += "\t [i]\n" - - return dat - - - //Reagent scanning program - reagent_scan - name = "Reagent Scan" - size = 6.0 - - scan_atom(atom/A as mob|obj|turf|area) - if(..()) - return - var/dat = null - if(!isnull(A.reagents)) - if(A.reagents.reagent_list.len > 0) - var/reagents_length = A.reagents.reagent_list.len - dat += "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.\n" - for (var/datum/reagent/re in A.reagents.reagent_list) - dat += "\t [re] - [re.volume]\n" - else - dat = "No active chemical agents found in [A]." - else - dat = "No significant chemical agents found in [A]." - - return dat + + if (!A.fingerprints) + dat += "Unable to locate any fingerprints on [A]!\n" + else + var/list/L = params2list(A:fingerprints) + dat += "Isolated [L.len] fingerprints.\n" + for(var/i in L) + dat += "\t [i]\n" + + return dat + + + //Reagent scanning program + reagent_scan + name = "Reagent Scan" + size = 6.0 + + scan_atom(atom/A as mob|obj|turf|area) + if(..()) + return + var/dat = null + if(!isnull(A.reagents)) + if(A.reagents.reagent_list.len > 0) + var/reagents_length = A.reagents.reagent_list.len + dat += "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.\n" + for (var/datum/reagent/re in A.reagents.reagent_list) + dat += "\t [re] - [re.volume]\n" + else + dat = "No active chemical agents found in [A]." + else + dat = "No significant chemical agents found in [A]." + + return dat diff --git a/code/unused/pda2/smallprogs.dm b/code/unused/pda2/smallprogs.dm index 549e8fc0f52..9fe4e19785f 100644 --- a/code/unused/pda2/smallprogs.dm +++ b/code/unused/pda2/smallprogs.dm @@ -1,204 +1,204 @@ -//Assorted small programs not worthy of their own file -//CONTENTS: -//Crew Manifest viewer -//Status display controller -//Remote signaling program -//Cargo orders monitor - -//Manifest -/datum/computer/file/pda_program/manifest - name = "Manifest" - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - - dat += "

    Crew Manifest

    " - dat += "Entries cannot be modified from this terminal.

    " - - for (var/datum/data/record/t in data_core.general) - dat += "[t.fields["name"]] - [t.fields["rank"]]
    " - dat += "
    " - - return dat - -//Status Display -/datum/computer/file/pda_program/status_display - name = "Status Controller" - size = 8.0 - var/message1 // For custom messages on the displays. - var/message2 - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - - dat += "

    Station Status Display Interlink

    " - - dat += "\[ Clear \]
    " - dat += "\[ Shuttle ETA \]
    " - dat += "\[ Message \]" - - dat += "
    " - dat += "\[ Alert: None |" - - dat += " Red Alert |" - dat += " Lockdown |" - dat += " Biohazard \]
    " - - return dat - - - Topic(href, href_list) - if(..()) - return - - if(href_list["statdisp"]) - switch(href_list["statdisp"]) - if("message") - post_status("message", message1, message2) - if("alert") - post_status("alert", href_list["alert"]) - - if("setmsg1") - message1 = input("Line 1", "Enter Message Text", message1) as text|null - if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) - return - - if(!(src.holder in src.master)) - return - src.master.updateSelfDialog() - - if("setmsg2") - message2 = input("Line 2", "Enter Message Text", message2) as text|null - if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) - return - - if(!(src.holder in src.master)) - return - - src.master.updateSelfDialog() - else - post_status(href_list["statdisp"]) - - src.master.add_fingerprint(usr) - src.master.updateSelfDialog() - return - - proc/post_status(var/command, var/data1, var/data2) - if(!src.master) - return - - var/datum/signal/status_signal = new - status_signal.source = src.master - status_signal.transmission_method = 1 - status_signal.data["command"] = command - - switch(command) - if("message") - status_signal.data["msg1"] = data1 - status_signal.data["msg2"] = data2 - if("alert") - status_signal.data["picture_state"] = data1 - - src.post_signal(status_signal,"1435") - -//Signaler -/datum/computer/file/pda_program/signaler - name = "Signalix 5" - size = 8.0 - var/send_freq = 1457 //Frequency signal is sent at, should be kept within normal radio ranges. - var/send_code = 30 - var/last_transmission = 0 //No signal spamming etc - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - - dat += "

    Remote Signaling System

    " - dat += {" -Send Signal
    - -Frequency: -- -- -[format_frequency(send_freq)] -+ -+
    -
    -Code: -- -- -[send_code] -+ -+
    "} - - return dat - - Topic(href, href_list) - if(..()) - return - - if (href_list["send"]) - if(last_transmission && world.time < (last_transmission + 5)) - return - last_transmission = world.time - spawn( 0 ) - var/time = time2text(world.realtime,"hh:mm:ss") - lastsignalers.Add("[time] : [usr.key] used [src.master] @ location ([src.master.loc.x],[src.master.loc.y],[src.master.loc.z]) : [format_frequency(send_freq)]/[send_code]") - - var/datum/signal/signal = new - signal.source = src - signal.encryption = send_code - signal.data["message"] = "ACTIVATE" - - src.post_signal(signal,"[send_freq]") - return - - else if (href_list["adj_freq"]) - src.send_freq = sanitize_frequency(src.send_freq + text2num(href_list["adj_freq"])) - - else if (href_list["adj_code"]) - src.send_code += text2num(href_list["adj_code"]) - src.send_code = round(src.send_code) - src.send_code = min(100, src.send_code) - src.send_code = max(1, src.send_code) - - src.master.add_fingerprint(usr) - src.master.updateSelfDialog() - return - -//Supply record monitor -/datum/computer/file/pda_program/qm_records - name = "Supply Records" - size = 8.0 - - return_text() - if(..()) - return - - var/dat = src.return_text_header() - dat += "

    Supply Record Interlink

    " - - dat += "
    Supply shuttle
    " - dat += "Location: [supply_shuttle_moving ? "Moving to station ([supply_shuttle_timeleft] Mins.)":supply_shuttle_at_station ? "Station":"Dock"]
    " - dat += "Current approved orders:
      " - for(var/S in supply_shuttle_shoppinglist) - var/datum/supply_order/SO = S - dat += "
    1. [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    2. " - dat += "
    " - - dat += "Current requests:
      " - for(var/S in supply_shuttle_requestlist) - var/datum/supply_order/SO = S - dat += "
    1. [SO.object.name] requested by [SO.orderedby]
    2. " - dat += "
    Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." - - return dat +//Assorted small programs not worthy of their own file +//CONTENTS: +//Crew Manifest viewer +//Status display controller +//Remote signaling program +//Cargo orders monitor + +//Manifest +/datum/computer/file/pda_program/manifest + name = "Manifest" + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + + dat += "

    Crew Manifest

    " + dat += "Entries cannot be modified from this terminal.

    " + + for (var/datum/data/record/t in data_core.general) + dat += "[t.fields["name"]] - [t.fields["rank"]]
    " + dat += "
    " + + return dat + +//Status Display +/datum/computer/file/pda_program/status_display + name = "Status Controller" + size = 8.0 + var/message1 // For custom messages on the displays. + var/message2 + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + + dat += "

    Station Status Display Interlink

    " + + dat += "\[ Clear \]
    " + dat += "\[ Shuttle ETA \]
    " + dat += "\[ Message \]" + + dat += "
    " + dat += "\[ Alert: None |" + + dat += " Red Alert |" + dat += " Lockdown |" + dat += " Biohazard \]
    " + + return dat + + + Topic(href, href_list) + if(..()) + return + + if(href_list["statdisp"]) + switch(href_list["statdisp"]) + if("message") + post_status("message", message1, message2) + if("alert") + post_status("alert", href_list["alert"]) + + if("setmsg1") + message1 = input("Line 1", "Enter Message Text", message1) as text|null + if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) + return + + if(!(src.holder in src.master)) + return + src.master.updateSelfDialog() + + if("setmsg2") + message2 = input("Line 2", "Enter Message Text", message2) as text|null + if (!src.master || !in_range(src.master, usr) && src.master.loc != usr) + return + + if(!(src.holder in src.master)) + return + + src.master.updateSelfDialog() + else + post_status(href_list["statdisp"]) + + src.master.add_fingerprint(usr) + src.master.updateSelfDialog() + return + + proc/post_status(var/command, var/data1, var/data2) + if(!src.master) + return + + var/datum/signal/status_signal = new + status_signal.source = src.master + status_signal.transmission_method = 1 + status_signal.data["command"] = command + + switch(command) + if("message") + status_signal.data["msg1"] = data1 + status_signal.data["msg2"] = data2 + if("alert") + status_signal.data["picture_state"] = data1 + + src.post_signal(status_signal,"1435") + +//Signaler +/datum/computer/file/pda_program/signaler + name = "Signalix 5" + size = 8.0 + var/send_freq = 1457 //Frequency signal is sent at, should be kept within normal radio ranges. + var/send_code = 30 + var/last_transmission = 0 //No signal spamming etc + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + + dat += "

    Remote Signaling System

    " + dat += {" +Send Signal
    + +Frequency: +- +- +[format_frequency(send_freq)] ++ ++
    +
    +Code: +- +- +[send_code] ++ ++
    "} + + return dat + + Topic(href, href_list) + if(..()) + return + + if (href_list["send"]) + if(last_transmission && world.time < (last_transmission + 5)) + return + last_transmission = world.time + spawn( 0 ) + var/time = time2text(world.realtime,"hh:mm:ss") + lastsignalers.Add("[time] : [usr.key] used [src.master] @ location ([src.master.loc.x],[src.master.loc.y],[src.master.loc.z]) : [format_frequency(send_freq)]/[send_code]") + + var/datum/signal/signal = new + signal.source = src + signal.encryption = send_code + signal.data["message"] = "ACTIVATE" + + src.post_signal(signal,"[send_freq]") + return + + else if (href_list["adj_freq"]) + src.send_freq = sanitize_frequency(src.send_freq + text2num(href_list["adj_freq"])) + + else if (href_list["adj_code"]) + src.send_code += text2num(href_list["adj_code"]) + src.send_code = round(src.send_code) + src.send_code = min(100, src.send_code) + src.send_code = max(1, src.send_code) + + src.master.add_fingerprint(usr) + src.master.updateSelfDialog() + return + +//Supply record monitor +/datum/computer/file/pda_program/qm_records + name = "Supply Records" + size = 8.0 + + return_text() + if(..()) + return + + var/dat = src.return_text_header() + dat += "

    Supply Record Interlink

    " + + dat += "
    Supply shuttle
    " + dat += "Location: [supply_shuttle_moving ? "Moving to station ([supply_shuttle_timeleft] Mins.)":supply_shuttle_at_station ? "Station":"Dock"]
    " + dat += "Current approved orders:
      " + for(var/S in supply_shuttle_shoppinglist) + var/datum/supply_order/SO = S + dat += "
    1. [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    2. " + dat += "
    " + + dat += "Current requests:
      " + for(var/S in supply_shuttle_requestlist) + var/datum/supply_order/SO = S + dat += "
    1. [SO.object.name] requested by [SO.orderedby]
    2. " + dat += "
    Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." + + return dat diff --git a/code/unused/shuttle_engines.dm b/code/unused/shuttle_engines.dm index 457154db0f2..168d6d1901a 100644 --- a/code/unused/shuttle_engines.dm +++ b/code/unused/shuttle_engines.dm @@ -1,37 +1,37 @@ - -/obj/structure/shuttle - name = "shuttle" - icon = 'icons/turf/shuttle.dmi' - -/obj/structure/shuttle/engine - name = "engine" - density = 1 - anchored = 1.0 - -/obj/structure/shuttle/engine/heater - name = "heater" - icon_state = "heater" - -/obj/structure/shuttle/engine/platform - name = "platform" - icon_state = "platform" - -/obj/structure/shuttle/engine/propulsion - name = "propulsion" - icon_state = "propulsion" - opacity = 1 - -/obj/structure/shuttle/engine/propulsion/burst - name = "burst" - -/obj/structure/shuttle/engine/propulsion/burst/left - name = "left" - icon_state = "burst_l" - -/obj/structure/shuttle/engine/propulsion/burst/right - name = "right" - icon_state = "burst_r" - -/obj/structure/shuttle/engine/router - name = "router" - icon_state = "router" + +/obj/structure/shuttle + name = "shuttle" + icon = 'icons/turf/shuttle.dmi' + +/obj/structure/shuttle/engine + name = "engine" + density = 1 + anchored = 1.0 + +/obj/structure/shuttle/engine/heater + name = "heater" + icon_state = "heater" + +/obj/structure/shuttle/engine/platform + name = "platform" + icon_state = "platform" + +/obj/structure/shuttle/engine/propulsion + name = "propulsion" + icon_state = "propulsion" + opacity = 1 + +/obj/structure/shuttle/engine/propulsion/burst + name = "burst" + +/obj/structure/shuttle/engine/propulsion/burst/left + name = "left" + icon_state = "burst_l" + +/obj/structure/shuttle/engine/propulsion/burst/right + name = "right" + icon_state = "burst_r" + +/obj/structure/shuttle/engine/router + name = "router" + icon_state = "router" diff --git a/code/unused/siphs.dm b/code/unused/siphs.dm index d9d5a893a4b..d54d1541e81 100644 --- a/code/unused/siphs.dm +++ b/code/unused/siphs.dm @@ -1,517 +1,517 @@ -/obj/machinery/atmoalter/siphs/New() - ..() - src.gas = new /datum/gas_mixture() - - return - -/obj/machinery/atmoalter/siphs/proc/releaseall() - src.t_status = 1 - src.t_per = max_valve - return - -/obj/machinery/atmoalter/siphs/proc/reset(valve, auto) - if(c_status!=0) - return - - if (valve < 0) - src.t_per = -valve - src.t_status = 1 - else - if (valve > 0) - src.t_per = valve - src.t_status = 2 - else - src.t_status = 3 - if (auto) - src.t_status = 4 - src.setstate() - return - -/obj/machinery/atmoalter/siphs/proc/release(amount, flag) - /* - var/T = src.loc - if (!( istype(T, /turf) )) - return - if (locate(/obj/move, T)) - T = locate(/obj/move, T) - if (!( amount )) - return - if (!( flag )) - amount = min(amount, max_valve) - src.gas.turf_add(T, amount) - return - */ //TODO: FIX - -/obj/machinery/atmoalter/siphs/proc/siphon(amount, flag) - /* - var/T = src.loc - if (!( istype(T, /turf) )) - return - if (locate(/obj/move, T)) - T = locate(/obj/move, T) - if (!( amount )) - return - if (!( flag )) - amount = min(amount, 900000.0) - src.gas.turf_take(T, amount) - return - */ //TODO: FIX - -/obj/machinery/atmoalter/siphs/proc/setstate() - - - if(stat & NOPOWER) - icon_state = "siphon:0" - return - - if (src.holding) - src.icon_state = "siphon:T" - else - if (src.t_status != 3) - src.icon_state = "siphon:1" - else - src.icon_state = "siphon:0" - return - -/obj/machinery/atmoalter/siphs/fullairsiphon/New() - /* - ..() - if(!empty) - src.gas.oxygen = 2.73E7 - src.gas.n2 = 1.027E8 - return - */ //TODO: FIX - -/obj/machinery/atmoalter/siphs/fullairsiphon/port/reset(valve, auto) - - if (valve < 0) - src.t_per = -valve - src.t_status = 1 - else - if (valve > 0) - src.t_per = valve - src.t_status = 2 - else - src.t_status = 3 - if (auto) - src.t_status = 4 - src.setstate() - return - -/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent/attackby(W as obj, user as mob) - - if (istype(W, /obj/item/weapon/screwdriver)) - if (src.c_status) - src.anchored = 1 - src.c_status = 0 - else - if (locate(/obj/machinery/connector, src.loc)) - src.anchored = 1 - src.c_status = 3 - else - if (istype(W, /obj/item/weapon/wrench)) - src.alterable = !( src.alterable ) - return - -/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent/setstate() - - - if(stat & NOPOWER) - icon_state = "vent-p" - return - - if (src.t_status == 4) - src.icon_state = "vent2" - else - if (src.t_status == 3) - src.icon_state = "vent0" - else - src.icon_state = "vent1" - return - -/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent/reset(valve, auto) - - if (auto) - src.t_status = 4 - return - -/obj/machinery/atmoalter/siphs/scrubbers/process() - /* - if(stat & NOPOWER) return - - if(src.gas.temperature >= 3000) - src.melt() - - if (src.t_status != 3) - var/turf/T = src.loc - if (istype(T, /turf)) - if (locate(/obj/move, T)) - T = locate(/obj/move, T) - if (T.firelevel < 900000.0) - src.gas.turf_add_all_oxy(T) - - else - T = null - switch(src.t_status) - if(1.0) - if( !portable() ) use_power(50, ENVIRON) - if (src.holding) - var/t1 = src.gas.total_moles() - var/t2 = t1 - var/t = src.t_per - if (src.t_per > t2) - t = t2 - src.holding.gas.transfer_from(src.gas, t) - else - if (T) - var/t1 = src.gas.total_moles() - var/t2 = t1 - var/t = src.t_per - if (src.t_per > t2) - t = t2 - src.gas.turf_add(T, t) - if(2.0) - if( !portable() ) use_power(50, ENVIRON) - if (src.holding) - var/t1 = src.gas.total_moles() - var/t2 = src.maximum - t1 - var/t = src.t_per - if (src.t_per > t2) - t = t2 - src.gas.transfer_from(src.holding.gas, t) - else - if (T) - var/t1 = src.gas.total_moles() - var/t2 = src.maximum - t1 - var/t = src.t_per - if (t > t2) - t = t2 - src.gas.turf_take(T, t) - if(4.0) - if( !portable() ) use_power(50, ENVIRON) - if (T) - if (T.firelevel > 900000.0) - src.f_time = world.time + 400 - else - if (world.time > src.f_time) - src.gas.extract_toxs(T) - if( !portable() ) use_power(150, ENVIRON) - var/contain = src.gas.total_moles() - if (contain > 1.3E8) - src.gas.turf_add(T, 1.3E8 - contain) - - src.setstate() - src.updateDialog() - return - */ //TODO: FIX - -/obj/machinery/atmoalter/siphs/scrubbers/air_filter/setstate() - - if(stat & NOPOWER) - icon_state = "vent-p" - return - - if (src.t_status == 4) - src.icon_state = "vent2" - else - if (src.t_status == 3) - src.icon_state = "vent0" - else - src.icon_state = "vent1" - return - -/obj/machinery/atmoalter/siphs/scrubbers/air_filter/attackby(W as obj, user as mob) - - if (istype(W, /obj/item/weapon/screwdriver)) - if (src.c_status) - src.anchored = 1 - src.c_status = 0 - else - if (locate(/obj/machinery/connector, src.loc)) - src.anchored = 1 - src.c_status = 3 - else - if (istype(W, /obj/item/weapon/wrench)) - src.alterable = !( src.alterable ) - return - -/obj/machinery/atmoalter/siphs/scrubbers/air_filter/reset(valve, auto) - - if (auto) - src.t_status = 4 - src.setstate() - return - -/obj/machinery/atmoalter/siphs/scrubbers/port/setstate() - - if(stat & NOPOWER) - icon_state = "scrubber:0" - return - - if (src.holding) - src.icon_state = "scrubber:T" - else - if (src.t_status != 3) - src.icon_state = "scrubber:1" - else - src.icon_state = "scrubber:0" - return - -/obj/machinery/atmoalter/siphs/scrubbers/port/reset(valve, auto) - - if (valve < 0) - src.t_per = -valve - src.t_status = 1 - else - if (valve > 0) - src.t_per = valve - src.t_status = 2 - else - src.t_status = 3 - if (auto) - src.t_status = 4 - src.setstate() - return - -//true if the siphon is portable (therfore no power needed) - -/obj/machinery/proc/portable() - return istype(src, /obj/machinery/atmoalter/siphs/fullairsiphon/port) || istype(src, /obj/machinery/atmoalter/siphs/scrubbers/port) - -/obj/machinery/atmoalter/siphs/power_change() - - if( portable() ) - return - - if(!powered(ENVIRON)) - spawn(rand(0,15)) - stat |= NOPOWER - setstate() - else - stat &= ~NOPOWER - setstate() - - -/obj/machinery/atmoalter/siphs/process() - /* -// var/dbg = (suffix=="d") && Debug - - if(stat & NOPOWER) return - - if (src.t_status != 3) - var/turf/T = src.loc - if (istype(T, /turf)) - if (locate(/obj/move, T)) - T = locate(/obj/move, T) - else - T = null - switch(src.t_status) - if(1.0) - if( !portable() ) use_power(50, ENVIRON) - if (src.holding) - var/t1 = src.gas.total_moles() - var/t2 = t1 - var/t = src.t_per - if (src.t_per > t2) - t = t2 - src.holding.gas.transfer_from(src.gas, t) - else - if (T) - var/t1 = src.gas.total_moles() - var/t2 = t1 - var/t = src.t_per - if (src.t_per > t2) - t = t2 - src.gas.turf_add(T, t) - if(2.0) - if( !portable() ) use_power(50, ENVIRON) - if (src.holding) - var/t1 = src.gas.total_moles() - var/t2 = src.maximum - t1 - var/t = src.t_per - if (src.t_per > t2) - t = t2 - src.gas.transfer_from(src.holding.gas, t) - else - if (T) - var/t1 = src.gas.total_moles() - var/t2 = src.maximum - t1 - var/t = src.t_per - if (t > t2) - t = t2 - //var/g = gas.total_moles() - //if(dbg) world.log << "VP0 : [t] from turf: [gas.total_moles()]" - //if(dbg) Air() - - src.gas.turf_take(T, t) - //if(dbg) world.log << "VP1 : now [gas.total_moles()]" - - //if(dbg) world.log << "[gas.total_moles()-g] ([t]) from turf to siph" - - //if(dbg) Air() - if(4.0) - if( !portable() ) - use_power(50, ENVIRON) - - if (T) - if (T.firelevel > 900000.0) - src.f_time = world.time + 300 - else - if (world.time > src.f_time) - var/difference = CELLSTANDARD - (T.oxygen + T.n2) - if (difference > 0) - var/t1 = src.gas.total_moles() - if (difference > t1) - difference = t1 - src.gas.turf_add(T, difference) - - src.updateDialog() - - src.setstate() - return - */ //TODO: FIX - -/obj/machinery/atmoalter/siphs/attack_ai(user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/atmoalter/siphs/attack_paw(user as mob) - - return src.attack_hand(user) - return - -/obj/machinery/atmoalter/siphs/attack_hand(var/mob/user as mob) - - if(stat & NOPOWER) return - - if(src.portable() && istype(user, /mob/living/silicon/ai)) //AI can't use portable siphons - return - - user.machine = src - var/tt - switch(src.t_status) - if(1.0) - tt = text("Releasing Siphon Stop", src, src) - if(2.0) - tt = text("Release Siphoning Stop", src, src) - if(3.0) - tt = text("Release Siphon Stopped Automatic", src, src, src) - else - tt = "Automatic equalizers are on!" - var/ct = null - switch(src.c_status) - if(1.0) - ct = text("Releasing Accept Stop", src, src) - if(2.0) - ct = text("Release Accepting Stop", src, src) - if(3.0) - ct = text("Release Accept Stopped", src, src) - else - ct = "Disconnected" - var/at = null - if (src.t_status == 4) - at = text("Automatic On Stop", src) - var/dat = text("Canister Valves []
    \n\tContains/Capacity [] / []
    \n\tUpper Valve Status: [] []
    \n\t\tM - - - - [] + + + + M
    \n\tPipe Valve Status: []
    \n\t\tM - - - - [] + + + + M
    \n
    \n\nClose
    \n\t
    ", (!( src.alterable ) ? "Valves are locked. Unlock with wrench!" : "You can lock this interface with a wrench."), num2text(src.gas.return_pressure(), 10), num2text(src.maximum, 10), (src.t_status == 4 ? text("[]", at) : text("[]", tt)), (src.holding ? text("
    (Tank ([])", src, src.holding.air_contents.return_pressure()) : null), src, num2text(max_valve, 7), src, src, src, src, src.t_per, src, src, src, src, src, num2text(max_valve, 7), ct, src, num2text(max_valve, 7), src, src, src, src, src.c_per, src, src, src, src, src, num2text(max_valve, 7), user) - user << browse(dat, "window=siphon;size=600x300") - onclose(user, "siphon") - return - -/obj/machinery/atmoalter/siphs/Topic(href, href_list) - if(..()) return 1 - - if (usr.stat || usr.restrained()) - return - if ((!( src.alterable )) && (!istype(usr, /mob/living/silicon/ai))) - return - if (((get_dist(src, usr) <= 1 || usr.telekinesis == 1) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon/ai))) - usr.machine = src - if (href_list["c"]) - var/c = text2num(href_list["c"]) - switch(c) - if(1.0) - src.c_status = 1 - if(2.0) - src.c_status = 2 - if(3.0) - src.c_status = 3 - else - else - if (href_list["t"]) - var/t = text2num(href_list["t"]) - if (src.t_status == 0) - return - switch(t) - if(1.0) - src.t_status = 1 - if(2.0) - src.t_status = 2 - if(3.0) - src.t_status = 3 - if(4.0) - src.t_status = 4 - src.f_time = 1 - else - else - if (href_list["tp"]) - var/tp = text2num(href_list["tp"]) - src.t_per += tp - src.t_per = min(max(round(src.t_per), 0), max_valve) - else - if (href_list["cp"]) - var/cp = text2num(href_list["cp"]) - src.c_per += cp - src.c_per = min(max(round(src.c_per), 0), max_valve) - else - if (href_list["tank"]) - var/cp = text2num(href_list["tank"]) - if (cp == 1) - src.holding.loc = src.loc - src.holding = null - if (src.t_status == 2) - src.t_status = 3 - src.updateUsrDialog() - - src.add_fingerprint(usr) - else - usr << browse(null, "window=canister") - return - return - -/obj/machinery/atmoalter/siphs/attackby(var/obj/W as obj, mob/user as mob) - - if (istype(W, /obj/item/weapon/tank)) - if (src.holding) - return - var/obj/item/weapon/tank/T = W - user.drop_item() - T.loc = src - src.holding = T - else - if (istype(W, /obj/item/weapon/screwdriver)) - var/obj/machinery/connector/con = locate(/obj/machinery/connector, src.loc) - if (src.c_status) - src.anchored = 0 - src.c_status = 0 - user.show_message("You have disconnected the siphon.") - if(con) - con.connected = null - else - if (con && !con.connected) - src.anchored = 1 - src.c_status = 3 - user.show_message("You have connected the siphon.") - con.connected = src - else - user.show_message("There is nothing here to connect to the siphon.") - - - else - if (istype(W, /obj/item/weapon/wrench)) - src.alterable = !( src.alterable ) - if (src.alterable) +/obj/machinery/atmoalter/siphs/New() + ..() + src.gas = new /datum/gas_mixture() + + return + +/obj/machinery/atmoalter/siphs/proc/releaseall() + src.t_status = 1 + src.t_per = max_valve + return + +/obj/machinery/atmoalter/siphs/proc/reset(valve, auto) + if(c_status!=0) + return + + if (valve < 0) + src.t_per = -valve + src.t_status = 1 + else + if (valve > 0) + src.t_per = valve + src.t_status = 2 + else + src.t_status = 3 + if (auto) + src.t_status = 4 + src.setstate() + return + +/obj/machinery/atmoalter/siphs/proc/release(amount, flag) + /* + var/T = src.loc + if (!( istype(T, /turf) )) + return + if (locate(/obj/move, T)) + T = locate(/obj/move, T) + if (!( amount )) + return + if (!( flag )) + amount = min(amount, max_valve) + src.gas.turf_add(T, amount) + return + */ //TODO: FIX + +/obj/machinery/atmoalter/siphs/proc/siphon(amount, flag) + /* + var/T = src.loc + if (!( istype(T, /turf) )) + return + if (locate(/obj/move, T)) + T = locate(/obj/move, T) + if (!( amount )) + return + if (!( flag )) + amount = min(amount, 900000.0) + src.gas.turf_take(T, amount) + return + */ //TODO: FIX + +/obj/machinery/atmoalter/siphs/proc/setstate() + + + if(stat & NOPOWER) + icon_state = "siphon:0" + return + + if (src.holding) + src.icon_state = "siphon:T" + else + if (src.t_status != 3) + src.icon_state = "siphon:1" + else + src.icon_state = "siphon:0" + return + +/obj/machinery/atmoalter/siphs/fullairsiphon/New() + /* + ..() + if(!empty) + src.gas.oxygen = 2.73E7 + src.gas.n2 = 1.027E8 + return + */ //TODO: FIX + +/obj/machinery/atmoalter/siphs/fullairsiphon/port/reset(valve, auto) + + if (valve < 0) + src.t_per = -valve + src.t_status = 1 + else + if (valve > 0) + src.t_per = valve + src.t_status = 2 + else + src.t_status = 3 + if (auto) + src.t_status = 4 + src.setstate() + return + +/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent/attackby(W as obj, user as mob) + + if (istype(W, /obj/item/weapon/screwdriver)) + if (src.c_status) + src.anchored = 1 + src.c_status = 0 + else + if (locate(/obj/machinery/connector, src.loc)) + src.anchored = 1 + src.c_status = 3 + else + if (istype(W, /obj/item/weapon/wrench)) + src.alterable = !( src.alterable ) + return + +/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent/setstate() + + + if(stat & NOPOWER) + icon_state = "vent-p" + return + + if (src.t_status == 4) + src.icon_state = "vent2" + else + if (src.t_status == 3) + src.icon_state = "vent0" + else + src.icon_state = "vent1" + return + +/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent/reset(valve, auto) + + if (auto) + src.t_status = 4 + return + +/obj/machinery/atmoalter/siphs/scrubbers/process() + /* + if(stat & NOPOWER) return + + if(src.gas.temperature >= 3000) + src.melt() + + if (src.t_status != 3) + var/turf/T = src.loc + if (istype(T, /turf)) + if (locate(/obj/move, T)) + T = locate(/obj/move, T) + if (T.firelevel < 900000.0) + src.gas.turf_add_all_oxy(T) + + else + T = null + switch(src.t_status) + if(1.0) + if( !portable() ) use_power(50, ENVIRON) + if (src.holding) + var/t1 = src.gas.total_moles() + var/t2 = t1 + var/t = src.t_per + if (src.t_per > t2) + t = t2 + src.holding.gas.transfer_from(src.gas, t) + else + if (T) + var/t1 = src.gas.total_moles() + var/t2 = t1 + var/t = src.t_per + if (src.t_per > t2) + t = t2 + src.gas.turf_add(T, t) + if(2.0) + if( !portable() ) use_power(50, ENVIRON) + if (src.holding) + var/t1 = src.gas.total_moles() + var/t2 = src.maximum - t1 + var/t = src.t_per + if (src.t_per > t2) + t = t2 + src.gas.transfer_from(src.holding.gas, t) + else + if (T) + var/t1 = src.gas.total_moles() + var/t2 = src.maximum - t1 + var/t = src.t_per + if (t > t2) + t = t2 + src.gas.turf_take(T, t) + if(4.0) + if( !portable() ) use_power(50, ENVIRON) + if (T) + if (T.firelevel > 900000.0) + src.f_time = world.time + 400 + else + if (world.time > src.f_time) + src.gas.extract_toxs(T) + if( !portable() ) use_power(150, ENVIRON) + var/contain = src.gas.total_moles() + if (contain > 1.3E8) + src.gas.turf_add(T, 1.3E8 - contain) + + src.setstate() + src.updateDialog() + return + */ //TODO: FIX + +/obj/machinery/atmoalter/siphs/scrubbers/air_filter/setstate() + + if(stat & NOPOWER) + icon_state = "vent-p" + return + + if (src.t_status == 4) + src.icon_state = "vent2" + else + if (src.t_status == 3) + src.icon_state = "vent0" + else + src.icon_state = "vent1" + return + +/obj/machinery/atmoalter/siphs/scrubbers/air_filter/attackby(W as obj, user as mob) + + if (istype(W, /obj/item/weapon/screwdriver)) + if (src.c_status) + src.anchored = 1 + src.c_status = 0 + else + if (locate(/obj/machinery/connector, src.loc)) + src.anchored = 1 + src.c_status = 3 + else + if (istype(W, /obj/item/weapon/wrench)) + src.alterable = !( src.alterable ) + return + +/obj/machinery/atmoalter/siphs/scrubbers/air_filter/reset(valve, auto) + + if (auto) + src.t_status = 4 + src.setstate() + return + +/obj/machinery/atmoalter/siphs/scrubbers/port/setstate() + + if(stat & NOPOWER) + icon_state = "scrubber:0" + return + + if (src.holding) + src.icon_state = "scrubber:T" + else + if (src.t_status != 3) + src.icon_state = "scrubber:1" + else + src.icon_state = "scrubber:0" + return + +/obj/machinery/atmoalter/siphs/scrubbers/port/reset(valve, auto) + + if (valve < 0) + src.t_per = -valve + src.t_status = 1 + else + if (valve > 0) + src.t_per = valve + src.t_status = 2 + else + src.t_status = 3 + if (auto) + src.t_status = 4 + src.setstate() + return + +//true if the siphon is portable (therfore no power needed) + +/obj/machinery/proc/portable() + return istype(src, /obj/machinery/atmoalter/siphs/fullairsiphon/port) || istype(src, /obj/machinery/atmoalter/siphs/scrubbers/port) + +/obj/machinery/atmoalter/siphs/power_change() + + if( portable() ) + return + + if(!powered(ENVIRON)) + spawn(rand(0,15)) + stat |= NOPOWER + setstate() + else + stat &= ~NOPOWER + setstate() + + +/obj/machinery/atmoalter/siphs/process() + /* +// var/dbg = (suffix=="d") && Debug + + if(stat & NOPOWER) return + + if (src.t_status != 3) + var/turf/T = src.loc + if (istype(T, /turf)) + if (locate(/obj/move, T)) + T = locate(/obj/move, T) + else + T = null + switch(src.t_status) + if(1.0) + if( !portable() ) use_power(50, ENVIRON) + if (src.holding) + var/t1 = src.gas.total_moles() + var/t2 = t1 + var/t = src.t_per + if (src.t_per > t2) + t = t2 + src.holding.gas.transfer_from(src.gas, t) + else + if (T) + var/t1 = src.gas.total_moles() + var/t2 = t1 + var/t = src.t_per + if (src.t_per > t2) + t = t2 + src.gas.turf_add(T, t) + if(2.0) + if( !portable() ) use_power(50, ENVIRON) + if (src.holding) + var/t1 = src.gas.total_moles() + var/t2 = src.maximum - t1 + var/t = src.t_per + if (src.t_per > t2) + t = t2 + src.gas.transfer_from(src.holding.gas, t) + else + if (T) + var/t1 = src.gas.total_moles() + var/t2 = src.maximum - t1 + var/t = src.t_per + if (t > t2) + t = t2 + //var/g = gas.total_moles() + //if(dbg) world.log << "VP0 : [t] from turf: [gas.total_moles()]" + //if(dbg) Air() + + src.gas.turf_take(T, t) + //if(dbg) world.log << "VP1 : now [gas.total_moles()]" + + //if(dbg) world.log << "[gas.total_moles()-g] ([t]) from turf to siph" + + //if(dbg) Air() + if(4.0) + if( !portable() ) + use_power(50, ENVIRON) + + if (T) + if (T.firelevel > 900000.0) + src.f_time = world.time + 300 + else + if (world.time > src.f_time) + var/difference = CELLSTANDARD - (T.oxygen + T.n2) + if (difference > 0) + var/t1 = src.gas.total_moles() + if (difference > t1) + difference = t1 + src.gas.turf_add(T, difference) + + src.updateDialog() + + src.setstate() + return + */ //TODO: FIX + +/obj/machinery/atmoalter/siphs/attack_ai(user as mob) + src.add_hiddenprint(user) + return src.attack_hand(user) + +/obj/machinery/atmoalter/siphs/attack_paw(user as mob) + + return src.attack_hand(user) + return + +/obj/machinery/atmoalter/siphs/attack_hand(var/mob/user as mob) + + if(stat & NOPOWER) return + + if(src.portable() && istype(user, /mob/living/silicon/ai)) //AI can't use portable siphons + return + + user.machine = src + var/tt + switch(src.t_status) + if(1.0) + tt = text("Releasing Siphon Stop", src, src) + if(2.0) + tt = text("Release Siphoning Stop", src, src) + if(3.0) + tt = text("Release Siphon Stopped Automatic", src, src, src) + else + tt = "Automatic equalizers are on!" + var/ct = null + switch(src.c_status) + if(1.0) + ct = text("Releasing Accept Stop", src, src) + if(2.0) + ct = text("Release Accepting Stop", src, src) + if(3.0) + ct = text("Release Accept Stopped", src, src) + else + ct = "Disconnected" + var/at = null + if (src.t_status == 4) + at = text("Automatic On Stop", src) + var/dat = text("Canister Valves []
    \n\tContains/Capacity [] / []
    \n\tUpper Valve Status: [] []
    \n\t\tM - - - - [] + + + + M
    \n\tPipe Valve Status: []
    \n\t\tM - - - - [] + + + + M
    \n
    \n\nClose
    \n\t
    ", (!( src.alterable ) ? "Valves are locked. Unlock with wrench!" : "You can lock this interface with a wrench."), num2text(src.gas.return_pressure(), 10), num2text(src.maximum, 10), (src.t_status == 4 ? text("[]", at) : text("[]", tt)), (src.holding ? text("
    (Tank ([])", src, src.holding.air_contents.return_pressure()) : null), src, num2text(max_valve, 7), src, src, src, src, src.t_per, src, src, src, src, src, num2text(max_valve, 7), ct, src, num2text(max_valve, 7), src, src, src, src, src.c_per, src, src, src, src, src, num2text(max_valve, 7), user) + user << browse(dat, "window=siphon;size=600x300") + onclose(user, "siphon") + return + +/obj/machinery/atmoalter/siphs/Topic(href, href_list) + if(..()) return 1 + + if (usr.stat || usr.restrained()) + return + if ((!( src.alterable )) && (!istype(usr, /mob/living/silicon/ai))) + return + if (((get_dist(src, usr) <= 1 || usr.telekinesis == 1) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon/ai))) + usr.machine = src + if (href_list["c"]) + var/c = text2num(href_list["c"]) + switch(c) + if(1.0) + src.c_status = 1 + if(2.0) + src.c_status = 2 + if(3.0) + src.c_status = 3 + else + else + if (href_list["t"]) + var/t = text2num(href_list["t"]) + if (src.t_status == 0) + return + switch(t) + if(1.0) + src.t_status = 1 + if(2.0) + src.t_status = 2 + if(3.0) + src.t_status = 3 + if(4.0) + src.t_status = 4 + src.f_time = 1 + else + else + if (href_list["tp"]) + var/tp = text2num(href_list["tp"]) + src.t_per += tp + src.t_per = min(max(round(src.t_per), 0), max_valve) + else + if (href_list["cp"]) + var/cp = text2num(href_list["cp"]) + src.c_per += cp + src.c_per = min(max(round(src.c_per), 0), max_valve) + else + if (href_list["tank"]) + var/cp = text2num(href_list["tank"]) + if (cp == 1) + src.holding.loc = src.loc + src.holding = null + if (src.t_status == 2) + src.t_status = 3 + src.updateUsrDialog() + + src.add_fingerprint(usr) + else + usr << browse(null, "window=canister") + return + return + +/obj/machinery/atmoalter/siphs/attackby(var/obj/W as obj, mob/user as mob) + + if (istype(W, /obj/item/weapon/tank)) + if (src.holding) + return + var/obj/item/weapon/tank/T = W + user.drop_item() + T.loc = src + src.holding = T + else + if (istype(W, /obj/item/weapon/screwdriver)) + var/obj/machinery/connector/con = locate(/obj/machinery/connector, src.loc) + if (src.c_status) + src.anchored = 0 + src.c_status = 0 + user.show_message("You have disconnected the siphon.") + if(con) + con.connected = null + else + if (con && !con.connected) + src.anchored = 1 + src.c_status = 3 + user.show_message("You have connected the siphon.") + con.connected = src + else + user.show_message("There is nothing here to connect to the siphon.") + + + else + if (istype(W, /obj/item/weapon/wrench)) + src.alterable = !( src.alterable ) + if (src.alterable) to_chat(user, "You unlock the interface!") - else + else to_chat(user, "You lock the interface!") - return - - + return + + diff --git a/code/unused/spacecraft/manufacturing.dm b/code/unused/spacecraft/manufacturing.dm index 9036407ac5e..69abccce0d5 100644 --- a/code/unused/spacecraft/manufacturing.dm +++ b/code/unused/spacecraft/manufacturing.dm @@ -1,247 +1,247 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -// Entirely unfinished. Mostly just bouncing ideas off the code. - - -// Smelting -// Grinding -// Spraying -// Crate - -/obj/deploycrate - icon = 'icons/obj/mining.dmi' - icon_state = "deploycrate" - density = 1 - var/payload - -/obj/deploycrate/attack_hand(mob/user as mob) - switch(payload) - if(null) - return - //if("cloner") - // make a cloner - // blah blah - for (var/mob/V in hearers(src)) - V.show_message("[src] lets out a pneumatic hiss, its panels rapdily unfolding and expanding to produce its payload.", 2) - del(src) - - -/obj/machinery/nanosprayer - icon = 'icons/obj/mining.dmi' - icon_state = "sprayer" - density = 1 - anchored = 1 - var/payload - var/hacked = 0 - var/temp = 100 - - var/usr_density = 5 - var/usr_lastupdate = 0 - - var/time_started = 0 - - var/points = 0 - var/totalpoints = 0 - - var/state = 0 // 0 - Idle, 1 - Spraying, 2 - Done, 3 - Overheated - -obj/machinery/nanosprayer/proc/update_temp() - // 1 second : 1 degree - if(src.state == 0) - var/diff = (world.time - usr_lastupdate) * 10 - temp -= diff - if(temp < 100) - temp = 100 - usr_lastupdate = world.time - return temp - else if(src.state == 1) - var/diff = (world.time - usr_lastupdate) * 10 - diff = diff * usr_density - temp += diff - usr_lastupdate = world.time - return temp - -obj/machinery/nanosprayer/process() - src.time_started = world.time - totalpoints = lentext(payload) * rand(5,10) - if(!totalpoints) - totalpoints = 1 - while(src.state == 1) - // Each unit of cost is 20 seconds - density - temp += density * rand(1,4) - sleep(200 - (usr_density * 10)) - if(src.temp > 350) - src.state = 3 - src.overheat() - return 0 - points += usr_density - if(points >= totalpoints) - src.state = 2 - src.complete() - return 1 - - -obj/machinery/nanosprayer/proc/cooldown() - while(state != 1) - sleep(200) - temp -= rand(5,20) - if(temp < 100) - temp = 100 - return - -obj/machinery/nanosprayer/proc/overheat() - return - -obj/machinery/nanosprayer/proc/complete() - src.totalpoints = 0 - src.points = 0 - spawn() cooldown() - return - -obj/machinery/nanosprayer/attack_hand(user as mob) - var/dat - if(..()) - return - dat += text("Core Temp: [temp]�C
    ") - dat += text("Nanocloud Density: [usr_density] million
    ") - dat += text("\[- / +\]
    ") - if(payload) - dat += text("
    Task: [payload]
    ") - switch(state) - if(0) - dat += text("Status: Idling
    ") - if(1) - dat += text("Status: Spraying
    ") - if(2) - dat += text("Status: Spray Task Complete
    ") - if(3) - dat += text("Status: OVERHEATED
    ") - if(state == 1) - if(points <= 0) - points = 1 - var/complete = (points * 100)/totalpoints - if(complete < 0) - complete = 0 - if(complete > 100) - complete = 100 - dat += text("Progress: [complete]%
    ") - if(state == 2) - dat += text("Progress: 100%
    ") - dat += text("\[Release Payload\]
    ") - dat += text("

    Set Task
    ") - dat += text("Start Spray
    ") - dat += text("Cancel Spray") - dat += text("

    Refresh") - user << browse("NANO SPRAY 1.1[dat]", "window=nanosprayer") - onclose(user, "nanosprayer") - -obj/machinery/nanosprayer/Topic(href, href_list) - if(..()) - return - usr.machine = src - src.add_fingerprint(usr) - if(href_list["plus"]) - usr_density += 1 - if(href_list["minus"]) - usr_density -= 1 - if(usr_density < 1) - usr_density = 1 - if(href_list["start"]) - if(state == 0) - state = 1 - spawn() src.process() - if(href_list["stop"]) - if(state == 1) - state = 0 - points = 0 - totalpoints = 0 - spawn() cooldown() - if(href_list["settask"]) - if(state == 0) - var/temppayload = input("Set a Task:", "Job Assignment") as text|null - if(temppayload) - payload = temppayload - //if(href_list["release"]) - // if(state == 2) - // Create the crate somewhere - src.updateUsrDialog() - -/obj/machinery/smelter - icon = 'icons/obj/mining.dmi' - icon_state = "sprayer" - density = 1 - anchored = 1 - var/locked = 0 - var/closed = 0 - var/state = 0 // 0 - Idle, 1 - Smelt, 2 - Cool, 3 - Clean - var/slag = 0 - var/hacked = 0 - -obj/machinery/smelter/attack_hand(user as mob) - var/dat - if(..()) - return - dat += text("

    Smelt-o-Matic Control Interface

    ") - dat += text("The red light is [src.closed ? "off" : "on"].
    ") - dat += text("The green light is [src.locked ? "on" : "off"].
    ") - switch(slag) - if(0) - dat += text("The meter is resting at zero.
    ") - if(1 to 2) - dat += text("The meter is wobbling at the mid-point marker.
    ") - if(3) - dat += text("The meter strains, displaying its maximum value.
    ") - else - dat += text("The meter has broken.
    ") - switch(state) - if(0) - dat += text("Status:Idle
    ") - if(1) - dat += text("Status:Smelting
    ") - if(2) - dat += text("Status:Cooling
    ") - if(3) - dat += text("Status:Cleaning
    ") - dat += text("

    Turn key [src.locked ? "to upper-left position" : "to upper-right position"]
    ") - dat += text("Flip switch [src.closed ? "up" : "down"]
    ") - dat += text("Push large flashing yellow button
    ") - user << browse("SMELTOMATIC[dat]", "window=smelter") - onclose(user, "smelter") - - -obj/machinery/smelter/Topic(href, href_list) - if(..()) - return - usr.machine = src - src.add_fingerprint(usr) - if(href_list["key"]) - src.locked = !src.locked - if(href_list["switch"]) - src.closed = !src.closed - if(href_list["button"]) - //Do stuff to actually smelt shit or something I don't know - return - src.updateUsrDialog() - - -/obj/machinery/slaggrinder - icon = 'icons/obj/mining.dmi' - - density = 1 - anchored = 1 - - - -/obj/machinery/adminmachine - icon = 'icons/obj/mining.dmi' - icon_state = "sprayer" - density = 1 - anchored = 1 - - var/gameticker - var/gameworld - - New() - ..() - gameticker = ticker - gameworld = world +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +// Entirely unfinished. Mostly just bouncing ideas off the code. + + +// Smelting +// Grinding +// Spraying +// Crate + +/obj/deploycrate + icon = 'icons/obj/mining.dmi' + icon_state = "deploycrate" + density = 1 + var/payload + +/obj/deploycrate/attack_hand(mob/user as mob) + switch(payload) + if(null) + return + //if("cloner") + // make a cloner + // blah blah + for (var/mob/V in hearers(src)) + V.show_message("[src] lets out a pneumatic hiss, its panels rapdily unfolding and expanding to produce its payload.", 2) + del(src) + + +/obj/machinery/nanosprayer + icon = 'icons/obj/mining.dmi' + icon_state = "sprayer" + density = 1 + anchored = 1 + var/payload + var/hacked = 0 + var/temp = 100 + + var/usr_density = 5 + var/usr_lastupdate = 0 + + var/time_started = 0 + + var/points = 0 + var/totalpoints = 0 + + var/state = 0 // 0 - Idle, 1 - Spraying, 2 - Done, 3 - Overheated + +obj/machinery/nanosprayer/proc/update_temp() + // 1 second : 1 degree + if(src.state == 0) + var/diff = (world.time - usr_lastupdate) * 10 + temp -= diff + if(temp < 100) + temp = 100 + usr_lastupdate = world.time + return temp + else if(src.state == 1) + var/diff = (world.time - usr_lastupdate) * 10 + diff = diff * usr_density + temp += diff + usr_lastupdate = world.time + return temp + +obj/machinery/nanosprayer/process() + src.time_started = world.time + totalpoints = lentext(payload) * rand(5,10) + if(!totalpoints) + totalpoints = 1 + while(src.state == 1) + // Each unit of cost is 20 seconds - density + temp += density * rand(1,4) + sleep(200 - (usr_density * 10)) + if(src.temp > 350) + src.state = 3 + src.overheat() + return 0 + points += usr_density + if(points >= totalpoints) + src.state = 2 + src.complete() + return 1 + + +obj/machinery/nanosprayer/proc/cooldown() + while(state != 1) + sleep(200) + temp -= rand(5,20) + if(temp < 100) + temp = 100 + return + +obj/machinery/nanosprayer/proc/overheat() + return + +obj/machinery/nanosprayer/proc/complete() + src.totalpoints = 0 + src.points = 0 + spawn() cooldown() + return + +obj/machinery/nanosprayer/attack_hand(user as mob) + var/dat + if(..()) + return + dat += text("Core Temp: [temp]�C
    ") + dat += text("Nanocloud Density: [usr_density] million
    ") + dat += text("\[- / +\]
    ") + if(payload) + dat += text("
    Task: [payload]
    ") + switch(state) + if(0) + dat += text("Status: Idling
    ") + if(1) + dat += text("Status: Spraying
    ") + if(2) + dat += text("Status: Spray Task Complete
    ") + if(3) + dat += text("Status: OVERHEATED
    ") + if(state == 1) + if(points <= 0) + points = 1 + var/complete = (points * 100)/totalpoints + if(complete < 0) + complete = 0 + if(complete > 100) + complete = 100 + dat += text("Progress: [complete]%
    ") + if(state == 2) + dat += text("Progress: 100%
    ") + dat += text("\[Release Payload\]
    ") + dat += text("

    Set Task
    ") + dat += text("Start Spray
    ") + dat += text("Cancel Spray") + dat += text("

    Refresh") + user << browse("NANO SPRAY 1.1[dat]", "window=nanosprayer") + onclose(user, "nanosprayer") + +obj/machinery/nanosprayer/Topic(href, href_list) + if(..()) + return + usr.machine = src + src.add_fingerprint(usr) + if(href_list["plus"]) + usr_density += 1 + if(href_list["minus"]) + usr_density -= 1 + if(usr_density < 1) + usr_density = 1 + if(href_list["start"]) + if(state == 0) + state = 1 + spawn() src.process() + if(href_list["stop"]) + if(state == 1) + state = 0 + points = 0 + totalpoints = 0 + spawn() cooldown() + if(href_list["settask"]) + if(state == 0) + var/temppayload = input("Set a Task:", "Job Assignment") as text|null + if(temppayload) + payload = temppayload + //if(href_list["release"]) + // if(state == 2) + // Create the crate somewhere + src.updateUsrDialog() + +/obj/machinery/smelter + icon = 'icons/obj/mining.dmi' + icon_state = "sprayer" + density = 1 + anchored = 1 + var/locked = 0 + var/closed = 0 + var/state = 0 // 0 - Idle, 1 - Smelt, 2 - Cool, 3 - Clean + var/slag = 0 + var/hacked = 0 + +obj/machinery/smelter/attack_hand(user as mob) + var/dat + if(..()) + return + dat += text("

    Smelt-o-Matic Control Interface

    ") + dat += text("The red light is [src.closed ? "off" : "on"].
    ") + dat += text("The green light is [src.locked ? "on" : "off"].
    ") + switch(slag) + if(0) + dat += text("The meter is resting at zero.
    ") + if(1 to 2) + dat += text("The meter is wobbling at the mid-point marker.
    ") + if(3) + dat += text("The meter strains, displaying its maximum value.
    ") + else + dat += text("The meter has broken.
    ") + switch(state) + if(0) + dat += text("Status:Idle
    ") + if(1) + dat += text("Status:Smelting
    ") + if(2) + dat += text("Status:Cooling
    ") + if(3) + dat += text("Status:Cleaning
    ") + dat += text("

    Turn key [src.locked ? "to upper-left position" : "to upper-right position"]
    ") + dat += text("Flip switch [src.closed ? "up" : "down"]
    ") + dat += text("Push large flashing yellow button
    ") + user << browse("SMELTOMATIC[dat]", "window=smelter") + onclose(user, "smelter") + + +obj/machinery/smelter/Topic(href, href_list) + if(..()) + return + usr.machine = src + src.add_fingerprint(usr) + if(href_list["key"]) + src.locked = !src.locked + if(href_list["switch"]) + src.closed = !src.closed + if(href_list["button"]) + //Do stuff to actually smelt shit or something I don't know + return + src.updateUsrDialog() + + +/obj/machinery/slaggrinder + icon = 'icons/obj/mining.dmi' + + density = 1 + anchored = 1 + + + +/obj/machinery/adminmachine + icon = 'icons/obj/mining.dmi' + icon_state = "sprayer" + density = 1 + anchored = 1 + + var/gameticker + var/gameworld + + New() + ..() + gameticker = ticker + gameworld = world diff --git a/code/unused/spacecraft/shipcore.dm b/code/unused/spacecraft/shipcore.dm index 751e5dc6398..59ae6886f7b 100644 --- a/code/unused/spacecraft/shipcore.dm +++ b/code/unused/spacecraft/shipcore.dm @@ -1,348 +1,348 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -/obj/machinery/shipcore - icon = 'craft.dmi' - icon_state = "core" - density = 1 - - var/width = 6 - var/height = 8 - var/list/turfs = list() - var/list/builders - var/list/components = list() - var/build_status = "unbuilt" - - - proc/group_self() - builders = list() - turfs = list() - components = list() - - src.anchored = 1 - - var/obj/ship_builder/L = new(locate(src.x, src.y, src.z)) - L.dir = WEST - L.distance = width/2 - L.core = src - - var/obj/ship_builder/R = new(locate(src.x+1, src.y, src.z)) - R.dir = EAST - R.distance = (width/2)-1 - R.core = src - - builders.Add(L, R) - - spawn() L.scan() - spawn() R.scan() - - var/h - for(h=1, h[src.wires[wire] ? "Mend" : "Cut"] Pulse
    ") - - dat += text("The red light is [src.disabled ? "off" : "on"].
    ") - dat += text("The green light is [src.shocked ? "off" : "on"].
    ") - dat += text("The blue light is [src.hacked ? "off" : "on"].
    ") -*/ - switch(src.build_status) - if("unbuilt") - dat += "

    Core Status: Undeployed


    " - dat += "Build Ship
    " - if("built") - dat += "

    Core Status: Deployed


    " - dat += "Move
    " - if("rebuilding") - dat += "

    Core Status: Recalibrating


    " - user << browse("Ship Core[dat]","window=shipcore") - onclose(user, "shipcore") - return - user << browse("Ship Core Control Panel[dat]", "window=shipcore") - onclose(user, "shipcore") - return - -obj/machinery/shipcore/Topic(href, href_list) - if(..()) - return - usr.machine = src - src.add_fingerprint(usr) - if(href_list["groupself"]) - src.group_self() - if (href_list["move"]) - var/list/beacons = list() - for(var/obj/effect/ship_landing_beacon/b in world) - if(istype(b, /obj/effect/ship_landing_beacon)) - if(b.active) - beacons.Add(b) - if(!beacons.len) - return - var/obj/choice = input("Choose a beacon to land at.", "Beacon Selection") in beacons - if(choice) - src.MoveShip(choice.loc) - - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - src.attack_hand(M) - src.updateUsrDialog() - return - - - -obj/machinery/ship_component - name = "ship component" - icon = 'craft.dmi' - var/obj/machinery/shipcore/core - var/required_draw = 0 - var/active = 1 - - proc - draw_power(var/n as num) - if(!n) - n = required_draw - if(core.draw_power(n)) - return 1 - else - return 0 - -obj/machinery/ship_component/thruster - name = "thruster" - icon_state = "thruster" - density = 1 - opacity = 1 - - var/cooldown = 600 // In 1/10th seconds - var/lastused - var/ready = 0 - required_draw = 100 - - proc - check_ready() - if(ready) - return 1 - if(lastused + cooldown <= world.time) - for(var/turf/T in range(1,src)) - if(istype(T, /turf/space)) - src.ready = 1 - break - else - src.ready = 0 - return src.ready - - fire() - src.check_ready() - if(!ready) - return 0 - if(src.draw_power()) - src.ready = 0 - src.lastused = world.time - return 1 - else - return 0 - -obj/machinery/ship_component/engine - name = "engine" - icon_state = "engine" - density = 1 - opacity = 1 - - var/charge = 1000 - var/capacity = 1000 - - draw_power(var/n as num) - if(charge >= n) - charge -= n - return 1 - else - return 0 - -obj/machinery/ship_component/control_panel - name = "control panel" - icon_state = "controlpanel" - density = 1 - opacity = 0 - - attack_hand(user as mob) - var/dat - if(..()) - return - if(!src.core) - dat += "No linked core found. Deploy ship core first." - else - dat += "Ship Status: [src.core.build_status]

    " - dat += "

    Installed Components:



    " - dat += "" - for(var/obj/machinery/ship_component/C in core.components) - dat += "" - if(istype(C, /obj/machinery/ship_component/engine)) - dat += "" - if(istype(C, /obj/machinery/ship_component/thruster)) - dat += "" - dat += "
    [C.name][C.active ? "Active" : "Inactive"]
    Fuel: [C:charge]/[C:capacity]
    Status: [C:check_ready() ? "Ready" : "On Cooldown"]
    " - user << browse("Ship Controls[dat]","window=shipcontrols") - onclose(user, "shipcontrols") - - Topic(href, href_list) - if(..()) - return - usr.machine = src - src.add_fingerprint(usr) - - - - - - - - -/obj/ship_builder - icon = 'craft.dmi' - icon_state = "builder" - density = 0 - opacity = 0 - - var/obj/machinery/shipcore/core - var/distance = 0 - - proc/scan() - if(distance < 0) - cleanup_self() - var/i - for(i=0, i[src.wires[wire] ? "Mend" : "Cut"] Pulse
    ") + + dat += text("The red light is [src.disabled ? "off" : "on"].
    ") + dat += text("The green light is [src.shocked ? "off" : "on"].
    ") + dat += text("The blue light is [src.hacked ? "off" : "on"].
    ") +*/ + switch(src.build_status) + if("unbuilt") + dat += "

    Core Status: Undeployed


    " + dat += "Build Ship
    " + if("built") + dat += "

    Core Status: Deployed


    " + dat += "Move
    " + if("rebuilding") + dat += "

    Core Status: Recalibrating


    " + user << browse("Ship Core[dat]","window=shipcore") + onclose(user, "shipcore") + return + user << browse("Ship Core Control Panel[dat]", "window=shipcore") + onclose(user, "shipcore") + return + +obj/machinery/shipcore/Topic(href, href_list) + if(..()) + return + usr.machine = src + src.add_fingerprint(usr) + if(href_list["groupself"]) + src.group_self() + if (href_list["move"]) + var/list/beacons = list() + for(var/obj/effect/ship_landing_beacon/b in world) + if(istype(b, /obj/effect/ship_landing_beacon)) + if(b.active) + beacons.Add(b) + if(!beacons.len) + return + var/obj/choice = input("Choose a beacon to land at.", "Beacon Selection") in beacons + if(choice) + src.MoveShip(choice.loc) + + for(var/mob/M in viewers(1, src)) + if ((M.client && M.machine == src)) + src.attack_hand(M) + src.updateUsrDialog() + return + + + +obj/machinery/ship_component + name = "ship component" + icon = 'craft.dmi' + var/obj/machinery/shipcore/core + var/required_draw = 0 + var/active = 1 + + proc + draw_power(var/n as num) + if(!n) + n = required_draw + if(core.draw_power(n)) + return 1 + else + return 0 + +obj/machinery/ship_component/thruster + name = "thruster" + icon_state = "thruster" + density = 1 + opacity = 1 + + var/cooldown = 600 // In 1/10th seconds + var/lastused + var/ready = 0 + required_draw = 100 + + proc + check_ready() + if(ready) + return 1 + if(lastused + cooldown <= world.time) + for(var/turf/T in range(1,src)) + if(istype(T, /turf/space)) + src.ready = 1 + break + else + src.ready = 0 + return src.ready + + fire() + src.check_ready() + if(!ready) + return 0 + if(src.draw_power()) + src.ready = 0 + src.lastused = world.time + return 1 + else + return 0 + +obj/machinery/ship_component/engine + name = "engine" + icon_state = "engine" + density = 1 + opacity = 1 + + var/charge = 1000 + var/capacity = 1000 + + draw_power(var/n as num) + if(charge >= n) + charge -= n + return 1 + else + return 0 + +obj/machinery/ship_component/control_panel + name = "control panel" + icon_state = "controlpanel" + density = 1 + opacity = 0 + + attack_hand(user as mob) + var/dat + if(..()) + return + if(!src.core) + dat += "No linked core found. Deploy ship core first." + else + dat += "Ship Status: [src.core.build_status]

    " + dat += "

    Installed Components:



    " + dat += "" + for(var/obj/machinery/ship_component/C in core.components) + dat += "" + if(istype(C, /obj/machinery/ship_component/engine)) + dat += "" + if(istype(C, /obj/machinery/ship_component/thruster)) + dat += "" + dat += "
    [C.name][C.active ? "Active" : "Inactive"]
    Fuel: [C:charge]/[C:capacity]
    Status: [C:check_ready() ? "Ready" : "On Cooldown"]
    " + user << browse("Ship Controls[dat]","window=shipcontrols") + onclose(user, "shipcontrols") + + Topic(href, href_list) + if(..()) + return + usr.machine = src + src.add_fingerprint(usr) + + + + + + + + +/obj/ship_builder + icon = 'craft.dmi' + icon_state = "builder" + density = 0 + opacity = 0 + + var/obj/machinery/shipcore/core + var/distance = 0 + + proc/scan() + if(distance < 0) + cleanup_self() + var/i + for(i=0, i 0) - step(src, src.dir) - sleep(1) - t1-- - else - var/t1 = round(src.speed / 5) - while(t1 > 0) - step(src, src.dir) - t1-- - return - -/obj/machinery/vehicle/meteorhit(var/obj/O as obj) - for (var/obj/item/I in src) - I.loc = src.loc - - for (var/mob/M in src) - M.loc = src.loc - if (M.client) - M.client.eye = M.client.mob - M.client.perspective = MOB_PERSPECTIVE - del(src) - -/obj/machinery/vehicle/ex_act(severity) - switch (severity) - if (1.0) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - //SN src = null - del(src) - if(2.0) - if (prob(50)) - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - ex_act(severity) - //SN src = null - del(src) - -/obj/machinery/vehicle/blob_act() - for(var/atom/movable/A as mob|obj in src) - A.loc = src.loc - del(src) - -/obj/machinery/vehicle/Bump(var/atom/A) +/obj/machinery/vehicle + name = "Vehicle Pod" + icon = 'escapepod.dmi' + icon_state = "podfire" + density = 1 + flags = FPRINT + anchored = 1.0 + var/speed = 10.0 + var/maximum_speed = 10.0 + var/can_rotate = 1 + var/can_maximize_speed = 0 + var/one_person_only = 0 + use_power = 0 + +/obj/machinery/vehicle/pod + name = "Escape Pod" + desc = "A pod, for, moving in space" + icon = 'escapepod.dmi' + icon_state = "pod" + can_rotate = 0 + var/id = 1.0 + +/obj/machinery/vehicle/recon + name = "Reconaissance Pod" + desc = "A fast moving pod." + icon = 'escapepod.dmi' + icon_state = "recon" + speed = 1.0 + maximum_speed = 30.0 + can_maximize_speed = 1 + one_person_only = 1 + + +/obj/machinery/vehicle/process() + if (src.speed) + if (src.speed <= 10) + var/t1 = 10 - src.speed + while(t1 > 0) + step(src, src.dir) + sleep(1) + t1-- + else + var/t1 = round(src.speed / 5) + while(t1 > 0) + step(src, src.dir) + t1-- + return + +/obj/machinery/vehicle/meteorhit(var/obj/O as obj) + for (var/obj/item/I in src) + I.loc = src.loc + + for (var/mob/M in src) + M.loc = src.loc + if (M.client) + M.client.eye = M.client.mob + M.client.perspective = MOB_PERSPECTIVE + del(src) + +/obj/machinery/vehicle/ex_act(severity) + switch (severity) + if (1.0) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + //SN src = null + del(src) + if(2.0) + if (prob(50)) + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + ex_act(severity) + //SN src = null + del(src) + +/obj/machinery/vehicle/blob_act() + for(var/atom/movable/A as mob|obj in src) + A.loc = src.loc + del(src) + +/obj/machinery/vehicle/Bump(var/atom/A) // to_chat(world, "[src] bumped into [A]") - spawn (0) - ..() - src.speed = 0 - return - return - -/obj/machinery/vehicle/relaymove(mob/user as mob, direction) - if (user.stat) - return - - if ((user in src)) - if (direction & 1) - src.speed = max(src.speed - 1, 1) - else if (direction & 2) - src.speed = min(src.maximum_speed, src.speed + 1) - else if (src.can_rotate && direction & 4) - src.dir = turn(src.dir, -90.0) - else if (src.can_rotate && direction & 8) - src.dir = turn(src.dir, 90) - else if (direction & 16 && src.can_maximize_speed) - src.speed = src.maximum_speed - -/obj/machinery/vehicle/verb/eject() - set src = usr.loc - - if (usr.stat) - return - - var/mob/M = usr - M.loc = src.loc - if (M.client) - M.client.eye = M.client.mob - M.client.perspective = MOB_PERSPECTIVE - step(M, turn(src.dir, 180)) - return - -/obj/machinery/vehicle/verb/board() - set src in oview(1) - - if (usr.stat) - return - - if (src.one_person_only && locate(/mob, src)) + spawn (0) + ..() + src.speed = 0 + return + return + +/obj/machinery/vehicle/relaymove(mob/user as mob, direction) + if (user.stat) + return + + if ((user in src)) + if (direction & 1) + src.speed = max(src.speed - 1, 1) + else if (direction & 2) + src.speed = min(src.maximum_speed, src.speed + 1) + else if (src.can_rotate && direction & 4) + src.dir = turn(src.dir, -90.0) + else if (src.can_rotate && direction & 8) + src.dir = turn(src.dir, 90) + else if (direction & 16 && src.can_maximize_speed) + src.speed = src.maximum_speed + +/obj/machinery/vehicle/verb/eject() + set src = usr.loc + + if (usr.stat) + return + + var/mob/M = usr + M.loc = src.loc + if (M.client) + M.client.eye = M.client.mob + M.client.perspective = MOB_PERSPECTIVE + step(M, turn(src.dir, 180)) + return + +/obj/machinery/vehicle/verb/board() + set src in oview(1) + + if (usr.stat) + return + + if (src.one_person_only && locate(/mob, src)) to_chat(usr, "There is no room! You can only fit one person.") - return - - var/mob/M = usr - if (M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - - M.loc = src - -/obj/machinery/vehicle/verb/unload(var/atom/movable/A in src) - set src in oview(1) - - if (usr.stat) - return - - if (istype(A, /atom/movable)) - A.loc = src.loc - for(var/mob/O in view(src, null)) - if ((O.client && !(O.blinded))) + return + + var/mob/M = usr + if (M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + + M.loc = src + +/obj/machinery/vehicle/verb/unload(var/atom/movable/A in src) + set src in oview(1) + + if (usr.stat) + return + + if (istype(A, /atom/movable)) + A.loc = src.loc + for(var/mob/O in view(src, null)) + if ((O.client && !(O.blinded))) to_chat(O, text(" [] unloads [] from []!", usr, A, src)) - - if (ismob(A)) - var/mob/M = A - if (M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = M - -/obj/machinery/vehicle/verb/load() - set src in oview(1) - - if (usr.stat) - return - - if (((istype(usr, /mob/living/carbon/human)) && (!(ticker) || (ticker && ticker.mode != "monkey")))) - var/mob/living/carbon/human/H = usr - - if ((H.pulling && !(H.pulling.anchored))) - if (src.one_person_only && !(istype(H.pulling, /obj/item/weapon))) + + if (ismob(A)) + var/mob/M = A + if (M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = M + +/obj/machinery/vehicle/verb/load() + set src in oview(1) + + if (usr.stat) + return + + if (((istype(usr, /mob/living/carbon/human)) && (!(ticker) || (ticker && ticker.mode != "monkey")))) + var/mob/living/carbon/human/H = usr + + if ((H.pulling && !(H.pulling.anchored))) + if (src.one_person_only && !(istype(H.pulling, /obj/item/weapon))) to_chat(usr, "You may only place items in.") - else - H.pulling.loc = src - if (ismob(H.pulling)) - var/mob/M = H.pulling - if (M.client) - M.client.perspective = EYE_PERSPECTIVE - M.client.eye = src - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) + else + H.pulling.loc = src + if (ismob(H.pulling)) + var/mob/M = H.pulling + if (M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) to_chat(O, text(" [] loads [] into []!", H, H.pulling, src)) - - H.stop_pulling() - - -/obj/machinery/vehicle/space_ship - icon = 'escapepod.dmi' - icon_state = "pod" - var/datum/global_iterator/space_ship_inertial_movement/pr_inertial_movement - var/datum/global_iterator/space_ship_speed_increment/pr_speed_increment - var/last_relay = 0 - var/obj/machinery/portable_atmospherics/canister/internal_tank - var/health = 100 - var/datum/effects/system/spark_spread/spark_system = new - - New() - ..() - internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src) - pr_inertial_movement = new /datum/global_iterator/space_ship_inertial_movement(list(src),0) - pr_speed_increment = new /datum/global_iterator/space_ship_speed_increment(list(src),0) - src.spark_system.set_up(2, 0, src) - src.spark_system.attach(src) - return - - proc/inspace() - if(istype(src.loc, /turf/space)) - return 1 - return 0 - - remove_air(amount) - if(src.internal_tank) - return src.internal_tank.air_contents.remove(amount) - else - var/turf/T = get_turf(src) - return T.remove_air(amount) - - return_air() - if(src.internal_tank) - return src.internal_tank.return_air() - return - - proc/return_pressure() - if(src.internal_tank) - return src.internal_tank.return_pressure() - return 0 - - proc/return_temperature() - if(src.internal_tank) - return src.internal_tank.return_temperature() - return 0 - - Bump(var/atom/movable/A) - if(istype(A)) - step(A, src.dir) - else - if(pr_inertial_movement.cur_delay<2) - take_damage(25) - pr_speed_increment.stop() - pr_inertial_movement.stop() - return - - proc/take_damage(value) - if(isnum(value)) - src.health -= value - if(src.health>0) - src.spark_system.start() + + H.stop_pulling() + + +/obj/machinery/vehicle/space_ship + icon = 'escapepod.dmi' + icon_state = "pod" + var/datum/global_iterator/space_ship_inertial_movement/pr_inertial_movement + var/datum/global_iterator/space_ship_speed_increment/pr_speed_increment + var/last_relay = 0 + var/obj/machinery/portable_atmospherics/canister/internal_tank + var/health = 100 + var/datum/effects/system/spark_spread/spark_system = new + + New() + ..() + internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src) + pr_inertial_movement = new /datum/global_iterator/space_ship_inertial_movement(list(src),0) + pr_speed_increment = new /datum/global_iterator/space_ship_speed_increment(list(src),0) + src.spark_system.set_up(2, 0, src) + src.spark_system.attach(src) + return + + proc/inspace() + if(istype(src.loc, /turf/space)) + return 1 + return 0 + + remove_air(amount) + if(src.internal_tank) + return src.internal_tank.air_contents.remove(amount) + else + var/turf/T = get_turf(src) + return T.remove_air(amount) + + return_air() + if(src.internal_tank) + return src.internal_tank.return_air() + return + + proc/return_pressure() + if(src.internal_tank) + return src.internal_tank.return_pressure() + return 0 + + proc/return_temperature() + if(src.internal_tank) + return src.internal_tank.return_temperature() + return 0 + + Bump(var/atom/movable/A) + if(istype(A)) + step(A, src.dir) + else + if(pr_inertial_movement.cur_delay<2) + take_damage(25) + pr_speed_increment.stop() + pr_inertial_movement.stop() + return + + proc/take_damage(value) + if(isnum(value)) + src.health -= value + if(src.health>0) + src.spark_system.start() // to_chat(world, "[src] health is [health]") - else - src.ex_act(1) - return - - process() - return - - proc/get_desired_speed() - return (pr_inertial_movement.max_delay-pr_inertial_movement.desired_delay)/(pr_inertial_movement.max_delay-pr_inertial_movement.min_delay)*100 - - proc/get_current_speed() - return (pr_inertial_movement.max_delay-pr_inertial_movement.cur_delay)/(pr_inertial_movement.max_delay-pr_inertial_movement.min_delay)*100 - -/obj/machinery/vehicle/space_ship/relaymove(mob/user as mob, direction) - spawn() - if (user.stat || world.time-last_relay<2) - return - last_relay = world.time - var/speed_change = 0 - if(direction & NORTH) - pr_inertial_movement.desired_delay = between(pr_inertial_movement.min_delay, pr_inertial_movement.desired_delay-1, pr_inertial_movement.max_delay) - speed_change = 1 - else if (direction & SOUTH) - pr_inertial_movement.desired_delay = between(pr_inertial_movement.min_delay, pr_inertial_movement.desired_delay+1, pr_inertial_movement.max_delay) - speed_change = 1 - else if (src.can_rotate && direction & 4) - src.dir = turn(src.dir, -90.0) - else if (src.can_rotate && direction & 8) - src.dir = turn(src.dir, 90) - if(speed_change) + else + src.ex_act(1) + return + + process() + return + + proc/get_desired_speed() + return (pr_inertial_movement.max_delay-pr_inertial_movement.desired_delay)/(pr_inertial_movement.max_delay-pr_inertial_movement.min_delay)*100 + + proc/get_current_speed() + return (pr_inertial_movement.max_delay-pr_inertial_movement.cur_delay)/(pr_inertial_movement.max_delay-pr_inertial_movement.min_delay)*100 + +/obj/machinery/vehicle/space_ship/relaymove(mob/user as mob, direction) + spawn() + if (user.stat || world.time-last_relay<2) + return + last_relay = world.time + var/speed_change = 0 + if(direction & NORTH) + pr_inertial_movement.desired_delay = between(pr_inertial_movement.min_delay, pr_inertial_movement.desired_delay-1, pr_inertial_movement.max_delay) + speed_change = 1 + else if (direction & SOUTH) + pr_inertial_movement.desired_delay = between(pr_inertial_movement.min_delay, pr_inertial_movement.desired_delay+1, pr_inertial_movement.max_delay) + speed_change = 1 + else if (src.can_rotate && direction & 4) + src.dir = turn(src.dir, -90.0) + else if (src.can_rotate && direction & 8) + src.dir = turn(src.dir, 90) + if(speed_change) // to_chat(user, "Desired speed: [get_desired_speed()]%") - src.pr_speed_increment.start() - src.pr_inertial_movement.start() - return - -//should try two directional iterator datums, one for vertical, one for horizontal movement. -/datum/global_iterator/space_ship_inertial_movement - delay = 1 - var/min_delay = 0 - var/max_delay = 15 - var/desired_delay - var/cur_delay - var/last_move - - New() - ..() - desired_delay = max_delay - cur_delay = max_delay - - stop() - src.cur_delay = max_delay - src.desired_delay = max_delay - return ..() - - process(var/obj/machinery/vehicle/space_ship/SS as obj) - if(cur_delay >= max_delay) - return src.stop() - if(world.time - last_move < cur_delay) - return - last_move = world.time -/* - if(src.delay>=SS.max_delay) - return src.stop() -*/ - if(!step(SS, SS.dir) || !SS.inspace()) - src.stop() - return - - proc/set_desired_delay(var/num as num) - src.desired_delay = num - return - -/datum/global_iterator/space_ship_speed_increment - delay = 5 - - process(var/obj/machinery/vehicle/space_ship/SS as obj) - if(SS.pr_inertial_movement.desired_delay!=SS.pr_inertial_movement.cur_delay) - var/delta = SS.pr_inertial_movement.desired_delay - SS.pr_inertial_movement.cur_delay - SS.pr_inertial_movement.cur_delay += delta>0?1:-1 -/* - for(var/mob/M in SS) + src.pr_speed_increment.start() + src.pr_inertial_movement.start() + return + +//should try two directional iterator datums, one for vertical, one for horizontal movement. +/datum/global_iterator/space_ship_inertial_movement + delay = 1 + var/min_delay = 0 + var/max_delay = 15 + var/desired_delay + var/cur_delay + var/last_move + + New() + ..() + desired_delay = max_delay + cur_delay = max_delay + + stop() + src.cur_delay = max_delay + src.desired_delay = max_delay + return ..() + + process(var/obj/machinery/vehicle/space_ship/SS as obj) + if(cur_delay >= max_delay) + return src.stop() + if(world.time - last_move < cur_delay) + return + last_move = world.time +/* + if(src.delay>=SS.max_delay) + return src.stop() +*/ + if(!step(SS, SS.dir) || !SS.inspace()) + src.stop() + return + + proc/set_desired_delay(var/num as num) + src.desired_delay = num + return + +/datum/global_iterator/space_ship_speed_increment + delay = 5 + + process(var/obj/machinery/vehicle/space_ship/SS as obj) + if(SS.pr_inertial_movement.desired_delay!=SS.pr_inertial_movement.cur_delay) + var/delta = SS.pr_inertial_movement.desired_delay - SS.pr_inertial_movement.cur_delay + SS.pr_inertial_movement.cur_delay += delta>0?1:-1 +/* + for(var/mob/M in SS) to_chat(M, "Current speed: [SS.get_current_speed()]") -*/ - else - src.stop() - return +*/ + else + src.stop() + return diff --git a/code/world.dm b/code/world.dm index 54f67dbbfa5..9e2df1932f4 100644 --- a/code/world.dm +++ b/code/world.dm @@ -1,476 +1,476 @@ -/world - mob = /mob/new_player - turf = /turf/space - view = "15x15" - cache_lifespan = 0 //stops player uploaded stuff from being kept in the rsc past the current session - //loop_checks = 0 -#define RECOMMENDED_VERSION 501 - - -var/savefile/panicfile -/world/New() - //populate_seed_list() - plant_controller = new() - - // Honk honk, fuck you science - for(var/i=1, i<=map.zLevels.len, i++) - WORLD_X_OFFSET += rand(-50,50) - WORLD_Y_OFFSET += rand(-50,50) - - // Initialize world events as early as possible. - on_login = new () - on_ban = new () - on_unban = new () - - - /*Runtimes, not sure if i need it still so commenting out for now - starticon = rotate_icon('icons/obj/lightning.dmi', "lightningstart") - midicon = rotate_icon('icons/obj/lightning.dmi', "lightning") - endicon = rotate_icon('icons/obj/lightning.dmi', "lightningend") - */ - - // logs - var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - - investigations["hrefs"] = new /datum/log_controller("hrefs", filename="data/logs/[date_string] hrefs.htm", persist=TRUE) - investigations["atmos"] = new /datum/log_controller("atmos", filename="data/logs/[date_string] atmos.htm", persist=TRUE) - - diary = file("data/logs/[date_string].log") - panicfile = new/savefile("data/logs/profiling/proclogs/[date_string].sav") - diaryofmeanpeople = file("data/logs/[date_string] Attack.log") - admin_diary = file("data/logs/[date_string] admin only.log") - - var/log_start = "---------------------\n\[[time_stamp()]\]WORLD: starting up..." - - diary << log_start - diaryofmeanpeople << log_start - admin_diary << log_start - var/ourround = time_stamp() - panicfile.cd = ourround - - - changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently -/* - * IF YOU HAVE BYOND VERSION BELOW 507.1248 OR ARE ABLE TO WALK THROUGH WINDOORS/BORDER WINDOWS COMMENT OUT - * #define BORDER_USE_TURF_EXIT - * FOR MORE INFORMATION SEE: http://www.byond.com/forum/?post=1666940 - */ -#ifdef BORDER_USE_TURF_EXIT - if(byond_version < 507) - warning("Your server's byond version does not meet the recommended requirements for this code. Please update BYOND to atleast 507.1248 or comment BORDER_USE_TURF_EXIT in global.dm") -#elif - if(byond_version < RECOMMENDED_VERSION) - world.log << "Your server's byond version does not meet the recommended requirements for this code. Please update BYOND" -#endif - make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) - - load_configuration() - load_mode() - load_motd() - load_admins() - load_mods() - LoadBansjob() - if(config.usewhitelist) - load_whitelist() - if(config.usealienwhitelist) - load_alienwhitelist() - jobban_loadbanfile() - jobban_updatelegacybans() - appearance_loadbanfile() - LoadBans() - SetupHooks() // /vg/ - - library_catalog.initialize() - - spawn() copy_logs() // Just copy the logs. - if(config && config.log_runtimes) - log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD")]-runtime.log") - if(config && config.server_name != null && config.server_suffix && world.port > 0) - // dumb and hardcoded but I don't care~ - config.server_name += " #[(world.port % 1000) / 100]" - - Get_Holiday() //~Carn, needs to be here when the station is named so :P - - src.update_status() - - makepowernets() - paperwork_setup() - - //sun = new /datum/sun() - radio_controller = new /datum/controller/radio() - data_core = new /obj/effect/datacore() - paiController = new /datum/paiController() - - if(!setup_database_connection()) - world.log << "Your server failed to establish a connection with the feedback database." - else - world.log << "Feedback database connection established." - migration_controller_mysql = new - migration_controller_sqlite = new ("players2.sqlite", "players2_empty.sqlite") - - if(!setup_old_database_connection()) - world.log << "Your server failed to establish a connection with the tgstation database." - else - world.log << "Tgstation database connection established." - - plmaster = new /obj/effect/overlay() - plmaster.icon = 'icons/effects/tile_effects.dmi' - plmaster.icon_state = "plasma" - plmaster.layer = FLY_LAYER - plmaster.mouse_opacity = 0 - - slmaster = new /obj/effect/overlay() - slmaster.icon = 'icons/effects/tile_effects.dmi' - slmaster.icon_state = "sleeping_agent" - slmaster.layer = FLY_LAYER - slmaster.mouse_opacity = 0 - - src.update_status() - - sleep_offline = 1 - - send2mainirc("Server starting up on [config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]") - - processScheduler = new - master_controller = new /datum/controller/game_controller() - - spawn(1) - processScheduler.deferSetupFor(/datum/controller/process/ticker) - processScheduler.setup() - - master_controller.setup() - - setup_species() - setup_shuttles() - - stat_collection.artifacts_discovered = 0 // Because artifacts during generation get counted otherwise! - - for(var/plugin_type in typesof(/plugin)) - var/plugin/P = new plugin_type() - plugins[P.name] = P - P.on_world_loaded() - - process_teleport_locs() //Sets up the wizard teleport locations - process_ghost_teleport_locs() //Sets up ghost teleport locations. - process_adminbus_teleport_locs() //Sets up adminbus teleport locations. - SortAreas() //Build the list of all existing areas and sort it alphabetically - - spawn(3000) //so we aren't adding to the round-start lag - if(config.ToRban) - ToRban_autoupdate() - /*if(config.kick_inactive) - KickInactiveClients()*/ - -#undef RECOMMENDED_VERSION - - return ..() - -//world/Topic(href, href_list[]) -// to_chat(world, "Received a Topic() call!") -// to_chat(world, "[href]") -// for(var/a in href_list) -// to_chat(world, "[a]") -// if(href_list["hello"]) -// to_chat(world, "Hello world!") -// return "Hello world!" -// to_chat(world, "End of Topic() call.") -// ..() - -/world/Topic(T, addr, master, key) - diary << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]" - - if (T == "ping") - var/x = 1 - for (var/client/C) - x++ - return x - - else if(T == "players") - var/n = 0 - for(var/mob/M in player_list) - if(M.client) - n++ - return n - - else if (T == "status") - var/list/s = list() - s["version"] = game_version - s["mode"] = master_mode - s["respawn"] = config ? abandon_allowed : 0 - s["enter"] = enter_allowed - s["vote"] = config.allow_vote_mode - s["ai"] = config.allow_ai - s["host"] = host ? host : null - s["players"] = list() - s["map_name"] = map.nameLong - s["gamestate"] = 1 - if(ticker) - s["gamestate"] = ticker.current_state - s["active_players"] = get_active_player_count() - s["revision"] = return_revision() - var/n = 0 - var/admins = 0 - - for(var/client/C in clients) - if(C.holder) - if(C.holder.fakekey) - continue //so stealthmins aren't revealed by the hub - admins++ - s["player[n]"] = C.key - n++ - s["players"] = n - - if(revdata) s["revision"] = revdata.revision - s["admins"] = admins - - return list2params(s) - else if (findtext(T,"notes:")) - var/notekey = copytext(T, 7) - return list2params(exportnotes(notekey)) - - -/world/Reboot(reason) - if(config.map_voting) - //testing("we have done a map vote") - if(fexists(vote.chosen_map)) - //testing("[vote.chosen_map] exists") - var/start = 1 - var/pos = findtext(vote.chosen_map, "/", start) - var/lastpos = pos - //testing("First slash [lastpos]") - while(pos > 0) - lastpos = pos - pos = findtext(vote.chosen_map, "/", start) - start = pos + 1 - //testing("Next slash [pos]") - var/filename = copytext(vote.chosen_map, lastpos + 1, 0) - //testing("Found [filename]") - - if(!fcopy(vote.chosen_map, filename)) - //testing("Fcopy failed, deleting and copying") - fdel(filename) - fcopy(vote.chosen_map, filename) - sleep(60) - - processScheduler.stop() - paperwork_stop() - - spawn(0) - world << sound(pick('sound/AI/newroundsexy.ogg', 'sound/misc/apcdestroyed.ogg', 'sound/misc/bangindonk.ogg', 'sound/misc/slugmissioncomplete.ogg')) // random end sounds!! - LastyBatsy - - - for(var/client/C in clients) - if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite - C << link("byond://[config.server]") - - else - C << link("byond://[world.address]:[world.port]") - - - ..() - - -#define INACTIVITY_KICK 6000 //10 minutes in ticks (approx.) -/world/proc/KickInactiveClients() - spawn(-1) - //set background = 1 - while(1) - sleep(INACTIVITY_KICK) - for(var/client/C in clients) - if(C.is_afk(INACTIVITY_KICK)) - if(!istype(C.mob, /mob/dead)) - log_access("AFK: [key_name(C)]") - to_chat(C, "You have been inactive for more than 10 minutes and have been disconnected.") - del(C) -//#undef INACTIVITY_KICK - - -/world/proc/load_mode() - var/list/Lines = file2list("data/mode.txt") - if(Lines.len) - if(Lines[1]) - master_mode = Lines[1] - diary << "Saved mode is '[master_mode]'" - -/world/proc/save_mode(var/the_mode) - var/F = file("data/mode.txt") - fdel(F) - to_chat(F, the_mode) - -/world/proc/load_motd() - join_motd = file2text("config/motd.txt") - -/world/proc/load_configuration() - config = new /datum/configuration() - config.load("config/config.txt") - config.load("config/game_options.txt","game_options") - config.loadsql("config/dbconfig.txt") - config.loadforumsql("config/forumdbconfig.txt") - // apply some settings from config.. - abandon_allowed = config.respawn - -/world/proc/load_mods() - if(config.admin_legacy_system) - var/text = file2text("config/moderators.txt") - if (!text) - diary << "Failed to load config/mods.txt\n" - else - var/list/lines = text2list(text, "\n") - for(var/line in lines) - if (!line) - continue - - if (copytext(line, 1, 2) == ";") - continue - - var/rights = admin_ranks["Moderator"] - var/ckey = copytext(line, 1, length(line)+1) - var/datum/admins/D = new /datum/admins("Moderator", rights, ckey) - D.associate(directory[ckey]) - -/world/proc/update_status() - var/s = "" - - if (config && config.server_name) - s += "[config.server_name] — " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\\documents\\\projects\vgstation13\code\world.dm:235: s += "[station_name()]"; - s += {"[station_name()]" - ( - " //Change this to wherever you want the hub to link to - Default" //Replace this with something else. Or ever better, delete it and uncomment the game version - - )"} - // END AUTOFIX - var/list/features = list() - - if(ticker) - if(master_mode) - features += master_mode - else - features += "STARTING" - - if (!enter_allowed) - features += "closed" - - features += abandon_allowed ? "respawn" : "no respawn" - - if (config && config.allow_vote_mode) - features += "vote" - - if (config && config.allow_ai) - features += "AI allowed" - - var/n = 0 - for (var/mob/M in player_list) - if (M.client) - n++ - - if (n > 1) - features += "~[n] players" - else if (n > 0) - features += "~[n] player" - - /* - is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already. - if (host) - features += "hosted by [host]" - */ - - if (!host && config && config.hostedby) - features += "hosted by [config.hostedby]" - - if (features) - s += ": [list2text(features, ", ")]" - - /* does this help? I do not know */ - if (src.status != s) - src.status = s - -#define FAILED_DB_CONNECTION_CUTOFF 5 -var/failed_db_connections = 0 -var/failed_old_db_connections = 0 - -proc/setup_database_connection() - - - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. - return 0 - - if(!dbcon) - dbcon = new() - - var/user = sqlfdbklogin - var/pass = sqlfdbkpass - var/db = sqlfdbkdb - var/address = sqladdress - var/port = sqlport - - dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") - . = dbcon.IsConnected() - if ( . ) - failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. - else - world.log << "Database Error: [dbcon.ErrorMsg()]" - failed_db_connections++ //If it failed, increase the failed connections counter. - - return . - -//This proc ensures that the connection to the feedback database (global variable dbcon) is established -proc/establish_db_connection() - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) - return 0 - - var/DBQuery/q - if(dbcon) - q = dbcon.NewQuery("show global variables like 'wait_timeout'") - q.Execute() - if(q && q.ErrorMsg()) - dbcon.Disconnect() - if(!dbcon || !dbcon.IsConnected()) - return setup_database_connection() - else - return 1 - - - - -//These two procs are for the old database, while it's being phased out. See the tgstation.sql file in the SQL folder for more information. -proc/setup_old_database_connection() - - - if(failed_old_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. - return 0 - - if(!dbcon_old) - dbcon_old = new() - - var/user = sqllogin - var/pass = sqlpass - var/db = sqldb - var/address = sqladdress - var/port = sqlport - - dbcon_old.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") - . = dbcon_old.IsConnected() - if ( . ) - failed_old_db_connections = 0 //If this connection succeeded, reset the failed connections counter. - else - failed_old_db_connections++ //If it failed, increase the failed connections counter. - world.log << dbcon_old.ErrorMsg() - - return . - -//This proc ensures that the connection to the feedback database (global variable dbcon) is established -proc/establish_old_db_connection() - if(failed_old_db_connections > FAILED_DB_CONNECTION_CUTOFF) - return 0 - - if(!dbcon_old || !dbcon_old.IsConnected()) - return setup_old_database_connection() - else - return 1 - -#undef FAILED_DB_CONNECTION_CUTOFF +/world + mob = /mob/new_player + turf = /turf/space + view = "15x15" + cache_lifespan = 0 //stops player uploaded stuff from being kept in the rsc past the current session + //loop_checks = 0 +#define RECOMMENDED_VERSION 501 + + +var/savefile/panicfile +/world/New() + //populate_seed_list() + plant_controller = new() + + // Honk honk, fuck you science + for(var/i=1, i<=map.zLevels.len, i++) + WORLD_X_OFFSET += rand(-50,50) + WORLD_Y_OFFSET += rand(-50,50) + + // Initialize world events as early as possible. + on_login = new () + on_ban = new () + on_unban = new () + + + /*Runtimes, not sure if i need it still so commenting out for now + starticon = rotate_icon('icons/obj/lightning.dmi', "lightningstart") + midicon = rotate_icon('icons/obj/lightning.dmi', "lightning") + endicon = rotate_icon('icons/obj/lightning.dmi', "lightningend") + */ + + // logs + var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") + + investigations["hrefs"] = new /datum/log_controller("hrefs", filename="data/logs/[date_string] hrefs.htm", persist=TRUE) + investigations["atmos"] = new /datum/log_controller("atmos", filename="data/logs/[date_string] atmos.htm", persist=TRUE) + + diary = file("data/logs/[date_string].log") + panicfile = new/savefile("data/logs/profiling/proclogs/[date_string].sav") + diaryofmeanpeople = file("data/logs/[date_string] Attack.log") + admin_diary = file("data/logs/[date_string] admin only.log") + + var/log_start = "---------------------\n\[[time_stamp()]\]WORLD: starting up..." + + diary << log_start + diaryofmeanpeople << log_start + admin_diary << log_start + var/ourround = time_stamp() + panicfile.cd = ourround + + + changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently +/* + * IF YOU HAVE BYOND VERSION BELOW 507.1248 OR ARE ABLE TO WALK THROUGH WINDOORS/BORDER WINDOWS COMMENT OUT + * #define BORDER_USE_TURF_EXIT + * FOR MORE INFORMATION SEE: http://www.byond.com/forum/?post=1666940 + */ +#ifdef BORDER_USE_TURF_EXIT + if(byond_version < 507) + warning("Your server's byond version does not meet the recommended requirements for this code. Please update BYOND to atleast 507.1248 or comment BORDER_USE_TURF_EXIT in global.dm") +#elif + if(byond_version < RECOMMENDED_VERSION) + world.log << "Your server's byond version does not meet the recommended requirements for this code. Please update BYOND" +#endif + make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) + + load_configuration() + load_mode() + load_motd() + load_admins() + load_mods() + LoadBansjob() + if(config.usewhitelist) + load_whitelist() + if(config.usealienwhitelist) + load_alienwhitelist() + jobban_loadbanfile() + jobban_updatelegacybans() + appearance_loadbanfile() + LoadBans() + SetupHooks() // /vg/ + + library_catalog.initialize() + + spawn() copy_logs() // Just copy the logs. + if(config && config.log_runtimes) + log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD")]-runtime.log") + if(config && config.server_name != null && config.server_suffix && world.port > 0) + // dumb and hardcoded but I don't care~ + config.server_name += " #[(world.port % 1000) / 100]" + + Get_Holiday() //~Carn, needs to be here when the station is named so :P + + src.update_status() + + makepowernets() + paperwork_setup() + + //sun = new /datum/sun() + radio_controller = new /datum/controller/radio() + data_core = new /obj/effect/datacore() + paiController = new /datum/paiController() + + if(!setup_database_connection()) + world.log << "Your server failed to establish a connection with the feedback database." + else + world.log << "Feedback database connection established." + migration_controller_mysql = new + migration_controller_sqlite = new ("players2.sqlite", "players2_empty.sqlite") + + if(!setup_old_database_connection()) + world.log << "Your server failed to establish a connection with the tgstation database." + else + world.log << "Tgstation database connection established." + + plmaster = new /obj/effect/overlay() + plmaster.icon = 'icons/effects/tile_effects.dmi' + plmaster.icon_state = "plasma" + plmaster.layer = FLY_LAYER + plmaster.mouse_opacity = 0 + + slmaster = new /obj/effect/overlay() + slmaster.icon = 'icons/effects/tile_effects.dmi' + slmaster.icon_state = "sleeping_agent" + slmaster.layer = FLY_LAYER + slmaster.mouse_opacity = 0 + + src.update_status() + + sleep_offline = 1 + + send2mainirc("Server starting up on [config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]") + + processScheduler = new + master_controller = new /datum/controller/game_controller() + + spawn(1) + processScheduler.deferSetupFor(/datum/controller/process/ticker) + processScheduler.setup() + + master_controller.setup() + + setup_species() + setup_shuttles() + + stat_collection.artifacts_discovered = 0 // Because artifacts during generation get counted otherwise! + + for(var/plugin_type in typesof(/plugin)) + var/plugin/P = new plugin_type() + plugins[P.name] = P + P.on_world_loaded() + + process_teleport_locs() //Sets up the wizard teleport locations + process_ghost_teleport_locs() //Sets up ghost teleport locations. + process_adminbus_teleport_locs() //Sets up adminbus teleport locations. + SortAreas() //Build the list of all existing areas and sort it alphabetically + + spawn(3000) //so we aren't adding to the round-start lag + if(config.ToRban) + ToRban_autoupdate() + /*if(config.kick_inactive) + KickInactiveClients()*/ + +#undef RECOMMENDED_VERSION + + return ..() + +//world/Topic(href, href_list[]) +// to_chat(world, "Received a Topic() call!") +// to_chat(world, "[href]") +// for(var/a in href_list) +// to_chat(world, "[a]") +// if(href_list["hello"]) +// to_chat(world, "Hello world!") +// return "Hello world!" +// to_chat(world, "End of Topic() call.") +// ..() + +/world/Topic(T, addr, master, key) + diary << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]" + + if (T == "ping") + var/x = 1 + for (var/client/C) + x++ + return x + + else if(T == "players") + var/n = 0 + for(var/mob/M in player_list) + if(M.client) + n++ + return n + + else if (T == "status") + var/list/s = list() + s["version"] = game_version + s["mode"] = master_mode + s["respawn"] = config ? abandon_allowed : 0 + s["enter"] = enter_allowed + s["vote"] = config.allow_vote_mode + s["ai"] = config.allow_ai + s["host"] = host ? host : null + s["players"] = list() + s["map_name"] = map.nameLong + s["gamestate"] = 1 + if(ticker) + s["gamestate"] = ticker.current_state + s["active_players"] = get_active_player_count() + s["revision"] = return_revision() + var/n = 0 + var/admins = 0 + + for(var/client/C in clients) + if(C.holder) + if(C.holder.fakekey) + continue //so stealthmins aren't revealed by the hub + admins++ + s["player[n]"] = C.key + n++ + s["players"] = n + + if(revdata) s["revision"] = revdata.revision + s["admins"] = admins + + return list2params(s) + else if (findtext(T,"notes:")) + var/notekey = copytext(T, 7) + return list2params(exportnotes(notekey)) + + +/world/Reboot(reason) + if(config.map_voting) + //testing("we have done a map vote") + if(fexists(vote.chosen_map)) + //testing("[vote.chosen_map] exists") + var/start = 1 + var/pos = findtext(vote.chosen_map, "/", start) + var/lastpos = pos + //testing("First slash [lastpos]") + while(pos > 0) + lastpos = pos + pos = findtext(vote.chosen_map, "/", start) + start = pos + 1 + //testing("Next slash [pos]") + var/filename = copytext(vote.chosen_map, lastpos + 1, 0) + //testing("Found [filename]") + + if(!fcopy(vote.chosen_map, filename)) + //testing("Fcopy failed, deleting and copying") + fdel(filename) + fcopy(vote.chosen_map, filename) + sleep(60) + + processScheduler.stop() + paperwork_stop() + + spawn(0) + world << sound(pick('sound/AI/newroundsexy.ogg', 'sound/misc/apcdestroyed.ogg', 'sound/misc/bangindonk.ogg', 'sound/misc/slugmissioncomplete.ogg')) // random end sounds!! - LastyBatsy + + + for(var/client/C in clients) + if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite + C << link("byond://[config.server]") + + else + C << link("byond://[world.address]:[world.port]") + + + ..() + + +#define INACTIVITY_KICK 6000 //10 minutes in ticks (approx.) +/world/proc/KickInactiveClients() + spawn(-1) + //set background = 1 + while(1) + sleep(INACTIVITY_KICK) + for(var/client/C in clients) + if(C.is_afk(INACTIVITY_KICK)) + if(!istype(C.mob, /mob/dead)) + log_access("AFK: [key_name(C)]") + to_chat(C, "You have been inactive for more than 10 minutes and have been disconnected.") + del(C) +//#undef INACTIVITY_KICK + + +/world/proc/load_mode() + var/list/Lines = file2list("data/mode.txt") + if(Lines.len) + if(Lines[1]) + master_mode = Lines[1] + diary << "Saved mode is '[master_mode]'" + +/world/proc/save_mode(var/the_mode) + var/F = file("data/mode.txt") + fdel(F) + to_chat(F, the_mode) + +/world/proc/load_motd() + join_motd = file2text("config/motd.txt") + +/world/proc/load_configuration() + config = new /datum/configuration() + config.load("config/config.txt") + config.load("config/game_options.txt","game_options") + config.loadsql("config/dbconfig.txt") + config.loadforumsql("config/forumdbconfig.txt") + // apply some settings from config.. + abandon_allowed = config.respawn + +/world/proc/load_mods() + if(config.admin_legacy_system) + var/text = file2text("config/moderators.txt") + if (!text) + diary << "Failed to load config/mods.txt\n" + else + var/list/lines = text2list(text, "\n") + for(var/line in lines) + if (!line) + continue + + if (copytext(line, 1, 2) == ";") + continue + + var/rights = admin_ranks["Moderator"] + var/ckey = copytext(line, 1, length(line)+1) + var/datum/admins/D = new /datum/admins("Moderator", rights, ckey) + D.associate(directory[ckey]) + +/world/proc/update_status() + var/s = "" + + if (config && config.server_name) + s += "[config.server_name] — " + + + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\\documents\\\projects\vgstation13\code\world.dm:235: s += "[station_name()]"; + s += {"[station_name()]" + ( + " //Change this to wherever you want the hub to link to + Default" //Replace this with something else. Or ever better, delete it and uncomment the game version + + )"} + // END AUTOFIX + var/list/features = list() + + if(ticker) + if(master_mode) + features += master_mode + else + features += "STARTING" + + if (!enter_allowed) + features += "closed" + + features += abandon_allowed ? "respawn" : "no respawn" + + if (config && config.allow_vote_mode) + features += "vote" + + if (config && config.allow_ai) + features += "AI allowed" + + var/n = 0 + for (var/mob/M in player_list) + if (M.client) + n++ + + if (n > 1) + features += "~[n] players" + else if (n > 0) + features += "~[n] player" + + /* + is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already. + if (host) + features += "hosted by [host]" + */ + + if (!host && config && config.hostedby) + features += "hosted by [config.hostedby]" + + if (features) + s += ": [list2text(features, ", ")]" + + /* does this help? I do not know */ + if (src.status != s) + src.status = s + +#define FAILED_DB_CONNECTION_CUTOFF 5 +var/failed_db_connections = 0 +var/failed_old_db_connections = 0 + +proc/setup_database_connection() + + + if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. + return 0 + + if(!dbcon) + dbcon = new() + + var/user = sqlfdbklogin + var/pass = sqlfdbkpass + var/db = sqlfdbkdb + var/address = sqladdress + var/port = sqlport + + dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") + . = dbcon.IsConnected() + if ( . ) + failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. + else + world.log << "Database Error: [dbcon.ErrorMsg()]" + failed_db_connections++ //If it failed, increase the failed connections counter. + + return . + +//This proc ensures that the connection to the feedback database (global variable dbcon) is established +proc/establish_db_connection() + if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) + return 0 + + var/DBQuery/q + if(dbcon) + q = dbcon.NewQuery("show global variables like 'wait_timeout'") + q.Execute() + if(q && q.ErrorMsg()) + dbcon.Disconnect() + if(!dbcon || !dbcon.IsConnected()) + return setup_database_connection() + else + return 1 + + + + +//These two procs are for the old database, while it's being phased out. See the tgstation.sql file in the SQL folder for more information. +proc/setup_old_database_connection() + + + if(failed_old_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. + return 0 + + if(!dbcon_old) + dbcon_old = new() + + var/user = sqllogin + var/pass = sqlpass + var/db = sqldb + var/address = sqladdress + var/port = sqlport + + dbcon_old.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") + . = dbcon_old.IsConnected() + if ( . ) + failed_old_db_connections = 0 //If this connection succeeded, reset the failed connections counter. + else + failed_old_db_connections++ //If it failed, increase the failed connections counter. + world.log << dbcon_old.ErrorMsg() + + return . + +//This proc ensures that the connection to the feedback database (global variable dbcon) is established +proc/establish_old_db_connection() + if(failed_old_db_connections > FAILED_DB_CONNECTION_CUTOFF) + return 0 + + if(!dbcon_old || !dbcon_old.IsConnected()) + return setup_old_database_connection() + else + return 1 + +#undef FAILED_DB_CONNECTION_CUTOFF diff --git a/maps/RandomZLevels/Academy.dm b/maps/RandomZLevels/Academy.dm index eb91c32bfe1..997276e74b8 100644 --- a/maps/RandomZLevels/Academy.dm +++ b/maps/RandomZLevels/Academy.dm @@ -1,43 +1,43 @@ -//Academy Areas - -/area/awaymission/academy - name = "\improper Academy Asteroids" - icon_state = "away" - -/area/awaymission/academy/headmaster - name = "\improper Academy Fore Block" - icon_state = "away1" - -/area/awaymission/academy/classrooms - name = "\improper Academy Classroom Block" - icon_state = "away2" - -/area/awaymission/academy/academyaft - name = "\improper Academy Ship Aft Block" - icon_state = "away3" - -/area/awaymission/academy/academygate - name = "\improper Academy Gateway" - icon_state = "away4" - -//Academy Items - -/obj/machinery/singularity/academy - dissipate = 0 - move_self = 0 - grav_pull = 1 - -/obj/machinery/singularity/academy/admin_investigate_setup() - return - -/obj/machinery/singularity/academy/process() - eat() - if(prob(1)) - mezzer() - - -/obj/item/clothing/glasses/meson/truesight - name = "The Lens of Truesight" - desc = "I can see forever!" - icon_state = "monocle" +//Academy Areas + +/area/awaymission/academy + name = "\improper Academy Asteroids" + icon_state = "away" + +/area/awaymission/academy/headmaster + name = "\improper Academy Fore Block" + icon_state = "away1" + +/area/awaymission/academy/classrooms + name = "\improper Academy Classroom Block" + icon_state = "away2" + +/area/awaymission/academy/academyaft + name = "\improper Academy Ship Aft Block" + icon_state = "away3" + +/area/awaymission/academy/academygate + name = "\improper Academy Gateway" + icon_state = "away4" + +//Academy Items + +/obj/machinery/singularity/academy + dissipate = 0 + move_self = 0 + grav_pull = 1 + +/obj/machinery/singularity/academy/admin_investigate_setup() + return + +/obj/machinery/singularity/academy/process() + eat() + if(prob(1)) + mezzer() + + +/obj/item/clothing/glasses/meson/truesight + name = "The Lens of Truesight" + desc = "I can see forever!" + icon_state = "monocle" item_state = "headset" \ No newline at end of file diff --git a/maps/RandomZLevels/challenge.dm b/maps/RandomZLevels/challenge.dm index 19b44525d54..f7aa861eb80 100644 --- a/maps/RandomZLevels/challenge.dm +++ b/maps/RandomZLevels/challenge.dm @@ -1,32 +1,32 @@ -//Challenge Areas - -/area/awaymission/challenge/start - name = "Where Am I?" - icon_state = "away" - -/area/awaymission/challenge/main - name = "\improper Danger Room" - icon_state = "away1" - requires_power = 0 - -/area/awaymission/challenge/end - name = "Administration" - icon_state = "away2" - requires_power = 0 - - -/obj/machinery/power/emitter/energycannon - name = "Energy Cannon" - desc = "A heavy duty industrial laser" - icon = 'icons/obj/singularity.dmi' - icon_state = "emitter" - anchored = 1 - density = 1 - - use_power = 0 - idle_power_usage = 0 - active_power_usage = 0 - - active = 1 - locked = 1 +//Challenge Areas + +/area/awaymission/challenge/start + name = "Where Am I?" + icon_state = "away" + +/area/awaymission/challenge/main + name = "\improper Danger Room" + icon_state = "away1" + requires_power = 0 + +/area/awaymission/challenge/end + name = "Administration" + icon_state = "away2" + requires_power = 0 + + +/obj/machinery/power/emitter/energycannon + name = "Energy Cannon" + desc = "A heavy duty industrial laser" + icon = 'icons/obj/singularity.dmi' + icon_state = "emitter" + anchored = 1 + density = 1 + + use_power = 0 + idle_power_usage = 0 + active_power_usage = 0 + + active = 1 + locked = 1 state = 2 \ No newline at end of file diff --git a/maps/RandomZLevels/stationCollision.dm b/maps/RandomZLevels/stationCollision.dm index bbccb2537d8..91926422615 100644 --- a/maps/RandomZLevels/stationCollision.dm +++ b/maps/RandomZLevels/stationCollision.dm @@ -1,189 +1,189 @@ -/* Station-Collision(sc) away mission map specific stuff - * - * Notes: - * Feel free to use parts of this map, or even all of it for your own project. Just include me in the credits :) - * - * Some of this code unnecessary, but the intent is to add a little bit of everything to serve as examples - * for anyone who wants to make their own stuff. - * - * Contains: - * Areas - * Landmarks - * Guns - * Safe code hints - * Captain's safe - * Modified Nar-Sie - */ - -/* - * Areas - */ - //Gateroom gets its own APC specifically for the gate - /area/awaymission/gateroom - - //Library, medbay, storage room - /area/awaymission/southblock - - //Arrivals, security, hydroponics, shuttles (since they dont move, they dont need specific areas) - /area/awaymission/arrivalblock - - //Crew quarters, cafeteria, chapel - /area/awaymission/midblock - - //engineering, bridge (not really north but it doesnt really need its own APC) - /area/awaymission/northblock - - //That massive research room - /area/awaymission/research - -//Syndicate shuttle -/area/awaymission/syndishuttle - - -/* - * Landmarks - Instead of spawning a new object type, I'll spawn the bible using a landmark! - */ -/obj/effect/landmark/sc_bible_spawner - name = "Safecode hint spawner" - -/obj/effect/landmark/sc_bible_spawner/New() - var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible/booze(src.loc) - B.name = "The Holy book of the Geometer" - B.deity_name = "Narsie" - B.icon_state = "melted" - B.item_state = "melted" - new /obj/item/weapon/paper/sc_safehint_paper_bible(B) - new /obj/item/weapon/pen(B) - del(src) - -/* - * Guns - I'm making these specifically so that I dont spawn a pile of fully loaded weapons on the map. - */ -//Captain's retro laser - Fires practice laser shots instead. -obj/item/weapon/gun/energy/laser/retro/sc_retro - name ="retro laser" - icon_state = "retro" - desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces." - projectile_type = "/obj/item/projectile/beam/practice" - clumsy_check = 0 //No sense in having a harmless gun blow up in the clowns face - -//Syndicate silenced pistol. This definition is not necessary, it's just habit. -/obj/item/weapon/gun/projectile/silenced/sc_silenced - -//Make it so that these guns only spawn with a couple bullets... if any -/obj/item/weapon/gun/projectile/silenced/sc_silenced/New() - ..() - for(var/ammo in loaded) - if(prob(95)) //95% chance - loaded -= ammo - -//Syndicate sub-machine guns. -/obj/item/weapon/gun/projectile/automatic/c20r/sc_c20r - -/obj/item/weapon/gun/projectile/automatic/c20r/sc_c20r/New() - ..() - for(var/ammo in loaded) - if(prob(95)) //95% chance - loaded -= ammo - -//Barman's shotgun -/obj/item/weapon/gun/projectile/shotgun/pump/sc_pump - -/obj/item/weapon/gun/projectile/shotgun/pump/sc_pump/New() - ..() - for(var/ammo in loaded) - if(prob(95)) //95% chance - loaded -= ammo - -//Lasers -/obj/item/weapon/gun/energy/laser/practice/sc_laser - name = "Old laser" - desc = "A once potent weapon, years of dust have collected in the chamber and lens of this weapon, weakening the beam significantly." - clumsy_check = 0 - -/* - * Safe code hints - */ - -//These vars hold the code itself, they'll be generated at round-start -var/sc_safecode1 = "[rand(0,9)]" -var/sc_safecode2 = "[rand(0,9)]" -var/sc_safecode3 = "[rand(0,9)]" -var/sc_safecode4 = "[rand(0,9)]" -var/sc_safecode5 = "[rand(0,9)]" - -//Pieces of paper actually containing the hints -/obj/item/weapon/paper/sc_safehint_paper_prison - name = "smudged paper" - -/obj/item/weapon/paper/sc_safehint_paper_prison/New() - ..() - info = "The ink is smudged, you can only make out a couple numbers: '[sc_safecode1]**[sc_safecode4]*'" - -/obj/item/weapon/paper/sc_safehint_paper_hydro - name = "shredded paper" -/obj/item/weapon/paper/sc_safehint_paper_hydro/New() - ..() - info = "Although the paper is shredded, you can clearly see the number: '[sc_safecode2]'" - -/obj/item/weapon/paper/sc_safehint_paper_caf - name = "blood-soaked paper" - //This does not have to be in New() because it is a constant. There are no variables in it i.e. [sc_safcode] - info = "This paper is soaked in blood, it is impossible to read any text." - -/obj/item/weapon/paper/sc_safehint_paper_bible - name = "hidden paper" -/obj/item/weapon/paper/sc_safehint_paper_bible/New() - ..() - info = {"It would appear that the pen hidden with the paper had leaked ink over the paper. - However you can make out the last three digits:'[sc_safecode3][sc_safecode4][sc_safecode5]' - "} - -/obj/item/weapon/paper/sc_safehint_paper_shuttle - info = {"Target: Research-station Epsilon
    - Objective: Prototype weaponry. The captain likely keeps them locked in her safe.
    -
    - Our on-board spy has learned the code and has hidden away a few copies of the code around the station. Unfortunatly he has been captured by security - Your objective is to split up, locate any of the papers containing the captain's safe code, open the safe and - secure anything found inside. If possible, recover the imprisioned syndicate operative and recieve the code from him.
    -
    - As always, eliminate anyone who gets in the way.
    -
    - Your assigned ship is designed specifically for penetrating the hull of another station or ship with minimal damage to operatives. - It is completely fly-by-wire meaning you have just have to enjoy the ride and when the red light comes on... find something to hold onto! - "} -/* - * Captain's safe - */ -/obj/item/weapon/storage/secure/safe/sc_ssafe - name = "Captain's secure safe" - -/obj/item/weapon/storage/secure/safe/sc_ssafe/New() - ..() - l_code = "[sc_safecode1][sc_safecode2][sc_safecode3][sc_safecode4][sc_safecode5]" - l_set = 1 - new /obj/item/weapon/gun/energy/mindflayer(src) - new /obj/item/device/soulstone(src) - new /obj/item/clothing/head/helmet/space/cult(src) - new /obj/item/clothing/suit/space/cult(src) - //new /obj/item/weapon/teleportation_scroll(src) - new /obj/item/weapon/ore/diamond(src) - -/** - * Modified Nar-Sie. - */ -/obj/machinery/singularity/narsie/wizard/sc_Narsie - desc = "Your body becomes weak and your feel your mind slipping away as you try to comprehend what you know can't be possible." - move_self = 0 // Contained narsie does not move! - -/* - * Override this to prevent no adminlog runtimes and admin warnings about a singularity without containment. - */ -/obj/machinery/singularity/narsie/wizard/sc_Narsie/admin_investigate_setup() - return - -/obj/machinery/singularity/narsie/wizard/sc_Narsie/process() - eat() - - if (prob(25)) - mezzer() +/* Station-Collision(sc) away mission map specific stuff + * + * Notes: + * Feel free to use parts of this map, or even all of it for your own project. Just include me in the credits :) + * + * Some of this code unnecessary, but the intent is to add a little bit of everything to serve as examples + * for anyone who wants to make their own stuff. + * + * Contains: + * Areas + * Landmarks + * Guns + * Safe code hints + * Captain's safe + * Modified Nar-Sie + */ + +/* + * Areas + */ + //Gateroom gets its own APC specifically for the gate + /area/awaymission/gateroom + + //Library, medbay, storage room + /area/awaymission/southblock + + //Arrivals, security, hydroponics, shuttles (since they dont move, they dont need specific areas) + /area/awaymission/arrivalblock + + //Crew quarters, cafeteria, chapel + /area/awaymission/midblock + + //engineering, bridge (not really north but it doesnt really need its own APC) + /area/awaymission/northblock + + //That massive research room + /area/awaymission/research + +//Syndicate shuttle +/area/awaymission/syndishuttle + + +/* + * Landmarks - Instead of spawning a new object type, I'll spawn the bible using a landmark! + */ +/obj/effect/landmark/sc_bible_spawner + name = "Safecode hint spawner" + +/obj/effect/landmark/sc_bible_spawner/New() + var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible/booze(src.loc) + B.name = "The Holy book of the Geometer" + B.deity_name = "Narsie" + B.icon_state = "melted" + B.item_state = "melted" + new /obj/item/weapon/paper/sc_safehint_paper_bible(B) + new /obj/item/weapon/pen(B) + del(src) + +/* + * Guns - I'm making these specifically so that I dont spawn a pile of fully loaded weapons on the map. + */ +//Captain's retro laser - Fires practice laser shots instead. +obj/item/weapon/gun/energy/laser/retro/sc_retro + name ="retro laser" + icon_state = "retro" + desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces." + projectile_type = "/obj/item/projectile/beam/practice" + clumsy_check = 0 //No sense in having a harmless gun blow up in the clowns face + +//Syndicate silenced pistol. This definition is not necessary, it's just habit. +/obj/item/weapon/gun/projectile/silenced/sc_silenced + +//Make it so that these guns only spawn with a couple bullets... if any +/obj/item/weapon/gun/projectile/silenced/sc_silenced/New() + ..() + for(var/ammo in loaded) + if(prob(95)) //95% chance + loaded -= ammo + +//Syndicate sub-machine guns. +/obj/item/weapon/gun/projectile/automatic/c20r/sc_c20r + +/obj/item/weapon/gun/projectile/automatic/c20r/sc_c20r/New() + ..() + for(var/ammo in loaded) + if(prob(95)) //95% chance + loaded -= ammo + +//Barman's shotgun +/obj/item/weapon/gun/projectile/shotgun/pump/sc_pump + +/obj/item/weapon/gun/projectile/shotgun/pump/sc_pump/New() + ..() + for(var/ammo in loaded) + if(prob(95)) //95% chance + loaded -= ammo + +//Lasers +/obj/item/weapon/gun/energy/laser/practice/sc_laser + name = "Old laser" + desc = "A once potent weapon, years of dust have collected in the chamber and lens of this weapon, weakening the beam significantly." + clumsy_check = 0 + +/* + * Safe code hints + */ + +//These vars hold the code itself, they'll be generated at round-start +var/sc_safecode1 = "[rand(0,9)]" +var/sc_safecode2 = "[rand(0,9)]" +var/sc_safecode3 = "[rand(0,9)]" +var/sc_safecode4 = "[rand(0,9)]" +var/sc_safecode5 = "[rand(0,9)]" + +//Pieces of paper actually containing the hints +/obj/item/weapon/paper/sc_safehint_paper_prison + name = "smudged paper" + +/obj/item/weapon/paper/sc_safehint_paper_prison/New() + ..() + info = "The ink is smudged, you can only make out a couple numbers: '[sc_safecode1]**[sc_safecode4]*'" + +/obj/item/weapon/paper/sc_safehint_paper_hydro + name = "shredded paper" +/obj/item/weapon/paper/sc_safehint_paper_hydro/New() + ..() + info = "Although the paper is shredded, you can clearly see the number: '[sc_safecode2]'" + +/obj/item/weapon/paper/sc_safehint_paper_caf + name = "blood-soaked paper" + //This does not have to be in New() because it is a constant. There are no variables in it i.e. [sc_safcode] + info = "This paper is soaked in blood, it is impossible to read any text." + +/obj/item/weapon/paper/sc_safehint_paper_bible + name = "hidden paper" +/obj/item/weapon/paper/sc_safehint_paper_bible/New() + ..() + info = {"It would appear that the pen hidden with the paper had leaked ink over the paper. + However you can make out the last three digits:'[sc_safecode3][sc_safecode4][sc_safecode5]' + "} + +/obj/item/weapon/paper/sc_safehint_paper_shuttle + info = {"Target: Research-station Epsilon
    + Objective: Prototype weaponry. The captain likely keeps them locked in her safe.
    +
    + Our on-board spy has learned the code and has hidden away a few copies of the code around the station. Unfortunatly he has been captured by security + Your objective is to split up, locate any of the papers containing the captain's safe code, open the safe and + secure anything found inside. If possible, recover the imprisioned syndicate operative and recieve the code from him.
    +
    + As always, eliminate anyone who gets in the way.
    +
    + Your assigned ship is designed specifically for penetrating the hull of another station or ship with minimal damage to operatives. + It is completely fly-by-wire meaning you have just have to enjoy the ride and when the red light comes on... find something to hold onto! + "} +/* + * Captain's safe + */ +/obj/item/weapon/storage/secure/safe/sc_ssafe + name = "Captain's secure safe" + +/obj/item/weapon/storage/secure/safe/sc_ssafe/New() + ..() + l_code = "[sc_safecode1][sc_safecode2][sc_safecode3][sc_safecode4][sc_safecode5]" + l_set = 1 + new /obj/item/weapon/gun/energy/mindflayer(src) + new /obj/item/device/soulstone(src) + new /obj/item/clothing/head/helmet/space/cult(src) + new /obj/item/clothing/suit/space/cult(src) + //new /obj/item/weapon/teleportation_scroll(src) + new /obj/item/weapon/ore/diamond(src) + +/** + * Modified Nar-Sie. + */ +/obj/machinery/singularity/narsie/wizard/sc_Narsie + desc = "Your body becomes weak and your feel your mind slipping away as you try to comprehend what you know can't be possible." + move_self = 0 // Contained narsie does not move! + +/* + * Override this to prevent no adminlog runtimes and admin warnings about a singularity without containment. + */ +/obj/machinery/singularity/narsie/wizard/sc_Narsie/admin_investigate_setup() + return + +/obj/machinery/singularity/narsie/wizard/sc_Narsie/process() + eat() + + if (prob(25)) + mezzer() diff --git a/maps/RandomZLevels/wildwest.dm b/maps/RandomZLevels/wildwest.dm index 5bbec254da0..b8cc8ba65cd 100644 --- a/maps/RandomZLevels/wildwest.dm +++ b/maps/RandomZLevels/wildwest.dm @@ -1,176 +1,176 @@ -/* Code for the Wild West map by Brotemis - * Contains: - * Wish Granter - * Meat Grinder - */ - -/* - * Wish Granter - */ -/obj/machinery/wish_granter_dark - name = "Wish Granter" - desc = "You're not so sure about this, anymore..." - icon = 'icons/obj/device.dmi' - icon_state = "syndbeacon" - - anchored = 1 - density = 1 - use_power = 0 - - var/chargesa = 1 - var/insistinga = 0 - -/obj/machinery/wish_granter_dark/attack_hand(var/mob/living/carbon/human/user as mob) - usr.set_machine(src) - - if(chargesa <= 0) +/* Code for the Wild West map by Brotemis + * Contains: + * Wish Granter + * Meat Grinder + */ + +/* + * Wish Granter + */ +/obj/machinery/wish_granter_dark + name = "Wish Granter" + desc = "You're not so sure about this, anymore..." + icon = 'icons/obj/device.dmi' + icon_state = "syndbeacon" + + anchored = 1 + density = 1 + use_power = 0 + + var/chargesa = 1 + var/insistinga = 0 + +/obj/machinery/wish_granter_dark/attack_hand(var/mob/living/carbon/human/user as mob) + usr.set_machine(src) + + if(chargesa <= 0) to_chat(user, "The Wish Granter lies silent.") - return - - else if(!istype(user, /mob/living/carbon/human)) + return + + else if(!istype(user, /mob/living/carbon/human)) to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.") - return - - else if(is_special_character(user)) + return + + else if(is_special_character(user)) to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.") - - else if (!insistinga) + + else if (!insistinga) to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?") - insistinga++ - - else - chargesa-- - insistinga = 0 - var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","To Kill","Peace") - switch(wish) - if("Power") + insistinga++ + + else + chargesa-- + insistinga = 0 + var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","To Kill","Peace") + switch(wish) + if("Power") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.") - if (!(M_LASER in user.mutations)) - user.mutations.Add(M_LASER) + if (!(M_LASER in user.mutations)) + user.mutations.Add(M_LASER) to_chat(user, "\blue You feel pressure building behind your eyes.") - if (!(M_RESIST_COLD in user.mutations)) - user.mutations.Add(M_RESIST_COLD) + if (!(M_RESIST_COLD in user.mutations)) + user.mutations.Add(M_RESIST_COLD) to_chat(user, "\blue Your body feels warm.") - if (!(M_RESIST_HEAT in user.mutations)) - user.mutations.Add(M_RESIST_HEAT) + if (!(M_RESIST_HEAT in user.mutations)) + user.mutations.Add(M_RESIST_HEAT) to_chat(user, "\blue Your skin feels icy to the touch.") - if (!(M_XRAY in user.mutations)) - user.mutations.Add(M_XRAY) - user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) - user.see_in_dark = 8 - user.see_invisible = SEE_INVISIBLE_LEVEL_TWO + if (!(M_XRAY in user.mutations)) + user.mutations.Add(M_XRAY) + user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + user.see_in_dark = 8 + user.see_invisible = SEE_INVISIBLE_LEVEL_TWO to_chat(user, "\blue The walls suddenly disappear.") - user.dna.mutantrace = "shadow" - user.update_mutantrace() - if("Wealth") + user.dna.mutantrace = "shadow" + user.update_mutantrace() + if("Wealth") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.") - new /obj/structure/closet/syndicate/resources/everything(loc) - user.dna.mutantrace = "shadow" - user.update_mutantrace() - if("Immortality") + new /obj/structure/closet/syndicate/resources/everything(loc) + user.dna.mutantrace = "shadow" + user.update_mutantrace() + if("Immortality") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.") - user.verbs += /mob/living/carbon/proc/immortality - user.dna.mutantrace = "shadow" - user.update_mutantrace() - if("To Kill") + user.verbs += /mob/living/carbon/proc/immortality + user.dna.mutantrace = "shadow" + user.update_mutantrace() + if("To Kill") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.") - ticker.mode.traitors += user.mind - user.mind.special_role = "traitor" - var/datum/objective/hijack/hijack = new - hijack.owner = user.mind - user.mind.objectives += hijack + ticker.mode.traitors += user.mind + user.mind.special_role = "traitor" + var/datum/objective/hijack/hijack = new + hijack.owner = user.mind + user.mind.objectives += hijack to_chat(user, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!") - var/obj_count = 1 - for(var/datum/objective/OBJ in user.mind.objectives) + var/obj_count = 1 + for(var/datum/objective/OBJ in user.mind.objectives) to_chat(user, "Objective #[obj_count]: [OBJ.explanation_text]") - obj_count++ - user.dna.mutantrace = "shadow" - user.update_mutantrace() - if("Peace") + obj_count++ + user.dna.mutantrace = "shadow" + user.update_mutantrace() + if("Peace") to_chat(user, "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.") to_chat(user, "You feel as if you just narrowly avoided a terrible fate...") - for(var/mob/living/simple_animal/hostile/faithless/F in mob_list) - F.health = -10 - F.stat = 2 - F.icon_state = "faithless_dead" - - -///////////////Meatgrinder////////////// - - -/obj/effect/meatgrinder - name = "Meat Grinder" - desc = "What is that thing?" - density = 1 - anchored = 1 - layer = 3 - icon = 'icons/mob/critter.dmi' - icon_state = "blob" - var/triggerproc = "explode" //name of the proc thats called when the mine is triggered - var/triggered = 0 - -/obj/effect/meatgrinder/New() - icon_state = "blob" - -/obj/effect/meatgrinder/Crossed(AM as mob|obj) - Bumped(AM) - -/obj/effect/meatgrinder/Bumped(mob/M as mob|obj) - - if(triggered) return - - if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey)) - for(var/mob/O in viewers(world.view, src.loc)) + for(var/mob/living/simple_animal/hostile/faithless/F in mob_list) + F.health = -10 + F.stat = 2 + F.icon_state = "faithless_dead" + + +///////////////Meatgrinder////////////// + + +/obj/effect/meatgrinder + name = "Meat Grinder" + desc = "What is that thing?" + density = 1 + anchored = 1 + layer = 3 + icon = 'icons/mob/critter.dmi' + icon_state = "blob" + var/triggerproc = "explode" //name of the proc thats called when the mine is triggered + var/triggered = 0 + +/obj/effect/meatgrinder/New() + icon_state = "blob" + +/obj/effect/meatgrinder/Crossed(AM as mob|obj) + Bumped(AM) + +/obj/effect/meatgrinder/Bumped(mob/M as mob|obj) + + if(triggered) return + + if(istype(M, /mob/living/carbon/human) || istype(M, /mob/living/carbon/monkey)) + for(var/mob/O in viewers(world.view, src.loc)) to_chat(O, "[M] triggered the \icon[src] [src]") - triggered = 1 - call(src,triggerproc)(M) - -/obj/effect/meatgrinder/proc/triggerrad1(mob) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - for(var/mob/O in viewers(world.view, src.loc)) - s.set_up(3, 1, src) - s.start() - explosion(mob, 1, 0, 0, 0) - spawn(0) - del(src) - -/obj/effect/meatgrinder - name = "Meat Grinder" - icon_state = "blob" - triggerproc = "triggerrad1" - - -/////For the Wishgranter/////////// - -/mob/living/carbon/proc/immortality() - set category = "Immortality" - set name = "Resurrection" - - var/mob/living/carbon/C = usr - if(!C.stat) + triggered = 1 + call(src,triggerproc)(M) + +/obj/effect/meatgrinder/proc/triggerrad1(mob) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + for(var/mob/O in viewers(world.view, src.loc)) + s.set_up(3, 1, src) + s.start() + explosion(mob, 1, 0, 0, 0) + spawn(0) + del(src) + +/obj/effect/meatgrinder + name = "Meat Grinder" + icon_state = "blob" + triggerproc = "triggerrad1" + + +/////For the Wishgranter/////////// + +/mob/living/carbon/proc/immortality() + set category = "Immortality" + set name = "Resurrection" + + var/mob/living/carbon/C = usr + if(!C.stat) to_chat(C, "You're not dead yet!") - return + return to_chat(C, "Death is not your end!") - - spawn(rand(800,1200)) - if(C.stat == DEAD) - resurrect() - C.stat = CONSCIOUS - C.tod = null - C.setToxLoss(0) - C.setOxyLoss(0) - C.setCloneLoss(0) - C.SetParalysis(0) - C.SetStunned(0) - C.SetWeakened(0) - C.radiation = 0 - C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss()) - C.reagents.clear_reagents() + + spawn(rand(800,1200)) + if(C.stat == DEAD) + resurrect() + C.stat = CONSCIOUS + C.tod = null + C.setToxLoss(0) + C.setOxyLoss(0) + C.setCloneLoss(0) + C.SetParalysis(0) + C.SetStunned(0) + C.SetWeakened(0) + C.radiation = 0 + C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss()) + C.reagents.clear_reagents() to_chat(C, "You have regenerated.") - C.visible_message("[usr] appears to wake from the dead, having healed all wounds.") - C.update_canmove() + C.visible_message("[usr] appears to wake from the dead, having healed all wounds.") + C.update_canmove() return 1 \ No newline at end of file diff --git a/maps/_map.dm b/maps/_map.dm index 7bd595abdae..bfaf86bb9a5 100644 --- a/maps/_map.dm +++ b/maps/_map.dm @@ -1,184 +1,184 @@ -#define ZLEVEL_BASE_CHANCE 10 //Not a strict chance, but a relative one -#define ZLEVEL_STATION_MODIFIER 0.5 //multiplier on the chance -#define ZLEVEL_SPACE_MODIFIER 1.5 - -//************************************************************** -// -// Map Datums -// -------------- -// Each map can have its own datum now. This means no more -// hardcoded bullshit. Same for each Z-level. -// -// Should be mostly self-explanatory. Define /datum/map/active -// in your map file. See current maps for examples. -// -// Base Turf -// -------------- -// Because the times are changing, even space being space -// is now considered hardcoding. So now you can have -// grass or asteroid under the station -// -//************************************************************** - -/datum/map - - var/nameShort = "" - var/nameLong = "" - var/list/zLevels = list() - var/zMainStation = 1 - var/zCentcomm = 2 - var/zTCommSat = 3 - var/zDerelict = 4 - var/zAsteroid = 5 - var/zDeepSpace = 6 - - //Center of thunderdome admin room - var/tDomeX = 0 - var/tDomeY = 0 - var/tDomeZ = 0 - - //nanoui stuff - var/map_dir = "" - - //Fuck the preprocessor - var/dorf = 0 - -/datum/map/New() - - . = ..() - src.loadZLevels(src.zLevels) - return - -/datum/map/proc/loadZLevels(list/levelPaths) - - - for(var/i = 1 to levelPaths.len) - var/path = levelPaths[i] - addZLevel(new path, i) - -/datum/map/proc/addZLevel(datum/zLevel/level, z_to_use = 0) - - - if(!istype(level)) - warning("ERROR: addZLevel received [level ? "a bad level of type [ispath(level) ? "[level]" : "[level.type]" ]" : "no level at all!"]") - return - if(!level.base_turf) - level.base_turf = /turf/space - if(z_to_use > zLevels.len) - zLevels.len = z_to_use - zLevels[z_to_use] = level - if(!level.movementJammed) - accessable_z_levels += list("[z_to_use]" = level.movementChance) - -var/global/list/accessable_z_levels = list() - -//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there. -//Generated by the map datum on roundstart - and added to during the round -//This comment is a memorial to balance bickering from a long-gone TGstation - Errorage and Urist - - -//////////////////////////////////////////////////////////////// - -/datum/zLevel - - var/name = "" - var/teleJammed = 0 - var/movementJammed = 0 //Prevents you from accessing the zlevel by drifting - var/movementChance = ZLEVEL_BASE_CHANCE - var/base_turf //Our base turf, what shows under the station when destroyed. Defaults to space because it's fukken Space Station 13 - -//////////////////////////////// - -/datum/zLevel/station - - name = "station" - movementChance = ZLEVEL_BASE_CHANCE * ZLEVEL_STATION_MODIFIER - -/datum/zLevel/centcomm - - name = "centcomm" - teleJammed = 1 - movementJammed = 1 - -/datum/zLevel/space - - name = "space" - movementChance = ZLEVEL_BASE_CHANCE * ZLEVEL_SPACE_MODIFIER - -/datum/zLevel/mining - - name = "mining" - -//Currently experimental, contains nothing worthy of interest -/datum/zLevel/desert - - name = "desert" - teleJammed = 1 - movementJammed = 1 - base_turf = /turf/unsimulated/beach/sand - -// Debug /////////////////////////////////////////////////////// - -/* -/mob/verb/getCurMapData() - to_chat(src, "\nCurrent map data:") - to_chat(src, "* Short name: [map.nameShort]") - to_chat(src, "* Long name: [map.nameLong]") - to_chat(src, "* [map.zLevels.len] Z-levels: [map.zLevels]") - for(var/datum/zLevel/level in map.zLevels) - to_chat(src, " * [level.name], Telejammed : [level.teleJammed], Movejammed : [level.movementJammed]") - to_chat(src, "* Main station Z: [map.zMainStation]") - to_chat(src, "* Centcomm Z: [map.zCentcomm]") - to_chat(src, "* Thunderdome coords: ([map.tDomeX],[map.tDomeY],[map.tDomeZ])") - to_chat(src, "* Space movement chances: [accessable_z_levels]") - for(var/z in accessable_z_levels) - to_chat(src, " * [z] has chance [accessable_z_levels[z]]") - return -*/ - -// Base Turf ////////////////////////////////////////////////// - -//Returns the lowest turf available on a given Z-level, defaults to space. - -proc/get_base_turf(var/z) - - - var/datum/zLevel/L = map.zLevels[z] - return L.base_turf - -proc/change_base_turf(var/choice,var/new_base_path,var/update_old_base = 0) - if(update_old_base) - for(var/turf/T in turfs) - if(T.type == get_base_turf(choice) && T.z == choice) - T.ChangeTurf(new_base_path) - var/datum/zLevel/L = map.zLevels[choice] - L.base_turf = new_base_path - for(var/obj/structure/docking_port/destination/D in all_docking_ports) - if(D.z == choice) - D.base_turf_type = new_base_path - -/client/proc/set_base_turf() - - - set category = "Debug" - set name = "Set Base Turf" - set desc = "Set the base turf for a z-level. Defaults to space, does not replace existing tiles." - - if(check_rights(R_DEBUG, 0)) - if(!holder) - return - var/choice = input("Which Z-level do you wish to set the base turf for?") as null|num - if(!choice) - return - var/new_base_path = input("Please select a turf path (cancel to reset to /turf/space).") as null|anything in typesof(/turf) - if(!new_base_path) - new_base_path = /turf/space //Only hardcode in the whole thing, feel free to change this if somewhere in the distant future spess is deprecated - var/update_old_base = alert(src, "Do you wish to update the old base? This will LAG.", "Update old turfs?", "Yes", "No") - update_old_base = update_old_base == "No" ? 0 : 1 - if(update_old_base) - message_admins("[key_name_admin(usr)] is replacing the old base turf on Z level [choice] with [get_base_turf(choice)]. This is likely to lag.") - log_admin("[key_name_admin(usr)] has replaced the old base turf on Z level [choice] with [get_base_turf(choice)].") - change_base_turf(choice,new_base_path,update_old_base) - feedback_add_details("admin_verb", "BTC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - message_admins("[key_name_admin(usr)] has set the base turf for Z-level [choice] to [get_base_turf(choice)]. This will affect all destroyed turfs from now on.") +#define ZLEVEL_BASE_CHANCE 10 //Not a strict chance, but a relative one +#define ZLEVEL_STATION_MODIFIER 0.5 //multiplier on the chance +#define ZLEVEL_SPACE_MODIFIER 1.5 + +//************************************************************** +// +// Map Datums +// -------------- +// Each map can have its own datum now. This means no more +// hardcoded bullshit. Same for each Z-level. +// +// Should be mostly self-explanatory. Define /datum/map/active +// in your map file. See current maps for examples. +// +// Base Turf +// -------------- +// Because the times are changing, even space being space +// is now considered hardcoding. So now you can have +// grass or asteroid under the station +// +//************************************************************** + +/datum/map + + var/nameShort = "" + var/nameLong = "" + var/list/zLevels = list() + var/zMainStation = 1 + var/zCentcomm = 2 + var/zTCommSat = 3 + var/zDerelict = 4 + var/zAsteroid = 5 + var/zDeepSpace = 6 + + //Center of thunderdome admin room + var/tDomeX = 0 + var/tDomeY = 0 + var/tDomeZ = 0 + + //nanoui stuff + var/map_dir = "" + + //Fuck the preprocessor + var/dorf = 0 + +/datum/map/New() + + . = ..() + src.loadZLevels(src.zLevels) + return + +/datum/map/proc/loadZLevels(list/levelPaths) + + + for(var/i = 1 to levelPaths.len) + var/path = levelPaths[i] + addZLevel(new path, i) + +/datum/map/proc/addZLevel(datum/zLevel/level, z_to_use = 0) + + + if(!istype(level)) + warning("ERROR: addZLevel received [level ? "a bad level of type [ispath(level) ? "[level]" : "[level.type]" ]" : "no level at all!"]") + return + if(!level.base_turf) + level.base_turf = /turf/space + if(z_to_use > zLevels.len) + zLevels.len = z_to_use + zLevels[z_to_use] = level + if(!level.movementJammed) + accessable_z_levels += list("[z_to_use]" = level.movementChance) + +var/global/list/accessable_z_levels = list() + +//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there. +//Generated by the map datum on roundstart - and added to during the round +//This comment is a memorial to balance bickering from a long-gone TGstation - Errorage and Urist + + +//////////////////////////////////////////////////////////////// + +/datum/zLevel + + var/name = "" + var/teleJammed = 0 + var/movementJammed = 0 //Prevents you from accessing the zlevel by drifting + var/movementChance = ZLEVEL_BASE_CHANCE + var/base_turf //Our base turf, what shows under the station when destroyed. Defaults to space because it's fukken Space Station 13 + +//////////////////////////////// + +/datum/zLevel/station + + name = "station" + movementChance = ZLEVEL_BASE_CHANCE * ZLEVEL_STATION_MODIFIER + +/datum/zLevel/centcomm + + name = "centcomm" + teleJammed = 1 + movementJammed = 1 + +/datum/zLevel/space + + name = "space" + movementChance = ZLEVEL_BASE_CHANCE * ZLEVEL_SPACE_MODIFIER + +/datum/zLevel/mining + + name = "mining" + +//Currently experimental, contains nothing worthy of interest +/datum/zLevel/desert + + name = "desert" + teleJammed = 1 + movementJammed = 1 + base_turf = /turf/unsimulated/beach/sand + +// Debug /////////////////////////////////////////////////////// + +/* +/mob/verb/getCurMapData() + to_chat(src, "\nCurrent map data:") + to_chat(src, "* Short name: [map.nameShort]") + to_chat(src, "* Long name: [map.nameLong]") + to_chat(src, "* [map.zLevels.len] Z-levels: [map.zLevels]") + for(var/datum/zLevel/level in map.zLevels) + to_chat(src, " * [level.name], Telejammed : [level.teleJammed], Movejammed : [level.movementJammed]") + to_chat(src, "* Main station Z: [map.zMainStation]") + to_chat(src, "* Centcomm Z: [map.zCentcomm]") + to_chat(src, "* Thunderdome coords: ([map.tDomeX],[map.tDomeY],[map.tDomeZ])") + to_chat(src, "* Space movement chances: [accessable_z_levels]") + for(var/z in accessable_z_levels) + to_chat(src, " * [z] has chance [accessable_z_levels[z]]") + return +*/ + +// Base Turf ////////////////////////////////////////////////// + +//Returns the lowest turf available on a given Z-level, defaults to space. + +proc/get_base_turf(var/z) + + + var/datum/zLevel/L = map.zLevels[z] + return L.base_turf + +proc/change_base_turf(var/choice,var/new_base_path,var/update_old_base = 0) + if(update_old_base) + for(var/turf/T in turfs) + if(T.type == get_base_turf(choice) && T.z == choice) + T.ChangeTurf(new_base_path) + var/datum/zLevel/L = map.zLevels[choice] + L.base_turf = new_base_path + for(var/obj/structure/docking_port/destination/D in all_docking_ports) + if(D.z == choice) + D.base_turf_type = new_base_path + +/client/proc/set_base_turf() + + + set category = "Debug" + set name = "Set Base Turf" + set desc = "Set the base turf for a z-level. Defaults to space, does not replace existing tiles." + + if(check_rights(R_DEBUG, 0)) + if(!holder) + return + var/choice = input("Which Z-level do you wish to set the base turf for?") as null|num + if(!choice) + return + var/new_base_path = input("Please select a turf path (cancel to reset to /turf/space).") as null|anything in typesof(/turf) + if(!new_base_path) + new_base_path = /turf/space //Only hardcode in the whole thing, feel free to change this if somewhere in the distant future spess is deprecated + var/update_old_base = alert(src, "Do you wish to update the old base? This will LAG.", "Update old turfs?", "Yes", "No") + update_old_base = update_old_base == "No" ? 0 : 1 + if(update_old_base) + message_admins("[key_name_admin(usr)] is replacing the old base turf on Z level [choice] with [get_base_turf(choice)]. This is likely to lag.") + log_admin("[key_name_admin(usr)] has replaced the old base turf on Z level [choice] with [get_base_turf(choice)].") + change_base_turf(choice,new_base_path,update_old_base) + feedback_add_details("admin_verb", "BTC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + message_admins("[key_name_admin(usr)] has set the base turf for Z-level [choice] to [get_base_turf(choice)]. This will affect all destroyed turfs from now on.") log_admin("[key_name(usr)] has set the base turf for Z-level [choice] to [get_base_turf(choice)]. This will affect all destroyed turfs from now on.") \ No newline at end of file